LCOV - code coverage report
Current view: top level - src/crypto - aes-siv.c (source / functions) Hit Total Coverage
Test: wpa_supplicant/hostapd combined for hwsim test run 1422976643 Lines: 80 92 87.0 %
Date: 2015-02-03 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /*
       2             :  * AES SIV (RFC 5297)
       3             :  * Copyright (c) 2013 Cozybit, Inc.
       4             :  *
       5             :  * This software may be distributed under the terms of the BSD license.
       6             :  * See README for more details.
       7             :  */
       8             : 
       9             : #include "includes.h"
      10             : 
      11             : #include "common.h"
      12             : #include "aes.h"
      13             : #include "aes_wrap.h"
      14             : #include "aes_siv.h"
      15             : 
      16             : 
      17             : static const u8 zero[AES_BLOCK_SIZE];
      18             : 
      19             : 
      20         130 : static void dbl(u8 *pad)
      21             : {
      22             :         int i, carry;
      23             : 
      24         130 :         carry = pad[0] & 0x80;
      25        2080 :         for (i = 0; i < AES_BLOCK_SIZE - 1; i++)
      26        1950 :                 pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7);
      27         130 :         pad[AES_BLOCK_SIZE - 1] <<= 1;
      28         130 :         if (carry)
      29         104 :                 pad[AES_BLOCK_SIZE - 1] ^= 0x87;
      30         130 : }
      31             : 
      32             : 
      33         130 : static void xor(u8 *a, const u8 *b)
      34             : {
      35             :         int i;
      36             : 
      37        2210 :         for (i = 0; i < AES_BLOCK_SIZE; i++)
      38        2080 :                 *a++ ^= *b++;
      39         130 : }
      40             : 
      41             : 
      42          42 : static void xorend(u8 *a, int alen, const u8 *b, int blen)
      43             : {
      44             :         int i;
      45             : 
      46          42 :         if (alen < blen)
      47          42 :                 return;
      48             : 
      49         714 :         for (i = 0; i < blen; i++)
      50         672 :                 a[alen - blen + i] ^= b[i];
      51             : }
      52             : 
      53             : 
      54           2 : static void pad_block(u8 *pad, const u8 *addr, size_t len)
      55             : {
      56           2 :         os_memset(pad, 0, AES_BLOCK_SIZE);
      57           2 :         os_memcpy(pad, addr, len);
      58             : 
      59           2 :         if (len < AES_BLOCK_SIZE)
      60           2 :                 pad[len] = 0x80;
      61           2 : }
      62             : 
      63             : 
      64          44 : static int aes_s2v(const u8 *key, size_t num_elem, const u8 *addr[],
      65             :                    size_t *len, u8 *mac)
      66             : {
      67             :         u8 tmp[AES_BLOCK_SIZE], tmp2[AES_BLOCK_SIZE];
      68          44 :         u8 *buf = NULL;
      69             :         int ret;
      70             :         size_t i;
      71             : 
      72          44 :         if (!num_elem) {
      73           0 :                 os_memcpy(tmp, zero, sizeof(zero));
      74           0 :                 tmp[AES_BLOCK_SIZE - 1] = 1;
      75           0 :                 return omac1_aes_128(key, tmp, sizeof(tmp), mac);
      76             :         }
      77             : 
      78          44 :         ret = omac1_aes_128(key, zero, sizeof(zero), tmp);
      79          44 :         if (ret)
      80           0 :                 return ret;
      81             : 
      82         172 :         for (i = 0; i < num_elem - 1; i++) {
      83         128 :                 ret = omac1_aes_128(key, addr[i], len[i], tmp2);
      84         128 :                 if (ret)
      85           0 :                         return ret;
      86             : 
      87         128 :                 dbl(tmp);
      88         128 :                 xor(tmp, tmp2);
      89             :         }
      90          44 :         if (len[i] >= AES_BLOCK_SIZE) {
      91          42 :                 buf = os_malloc(len[i]);
      92          42 :                 if (!buf)
      93           0 :                         return -ENOMEM;
      94             : 
      95          42 :                 os_memcpy(buf, addr[i], len[i]);
      96          42 :                 xorend(buf, len[i], tmp, AES_BLOCK_SIZE);
      97          42 :                 ret = omac1_aes_128(key, buf, len[i], mac);
      98          42 :                 bin_clear_free(buf, len[i]);
      99          42 :                 return ret;
     100             :         }
     101             : 
     102           2 :         dbl(tmp);
     103           2 :         pad_block(tmp2, addr[i], len[i]);
     104           2 :         xor(tmp, tmp2);
     105             : 
     106           2 :         return omac1_aes_128(key, tmp, sizeof(tmp), mac);
     107             : }
     108             : 
     109             : 
     110          27 : int aes_siv_encrypt(const u8 *key, const u8 *pw,
     111             :                     size_t pwlen, size_t num_elem,
     112             :                     const u8 *addr[], const size_t *len, u8 *out)
     113             : {
     114             :         const u8 *_addr[6];
     115             :         size_t _len[6];
     116          27 :         const u8 *k1 = key, *k2 = key + 16;
     117             :         u8 v[AES_BLOCK_SIZE];
     118             :         size_t i;
     119             :         u8 *iv, *crypt_pw;
     120             : 
     121          27 :         if (num_elem > ARRAY_SIZE(_addr) - 1)
     122           0 :                 return -1;
     123             : 
     124         106 :         for (i = 0; i < num_elem; i++) {
     125          79 :                 _addr[i] = addr[i];
     126          79 :                 _len[i] = len[i];
     127             :         }
     128          27 :         _addr[num_elem] = pw;
     129          27 :         _len[num_elem] = pwlen;
     130             : 
     131          27 :         if (aes_s2v(k1, num_elem + 1, _addr, _len, v))
     132           0 :                 return -1;
     133             : 
     134          27 :         iv = out;
     135          27 :         crypt_pw = out + AES_BLOCK_SIZE;
     136             : 
     137          27 :         os_memcpy(iv, v, AES_BLOCK_SIZE);
     138          27 :         os_memcpy(crypt_pw, pw, pwlen);
     139             : 
     140             :         /* zero out 63rd and 31st bits of ctr (from right) */
     141          27 :         v[8] &= 0x7f;
     142          27 :         v[12] &= 0x7f;
     143          27 :         return aes_128_ctr_encrypt(k2, v, crypt_pw, pwlen);
     144             : }
     145             : 
     146             : 
     147          17 : int aes_siv_decrypt(const u8 *key, const u8 *iv_crypt, size_t iv_c_len,
     148             :                     size_t num_elem, const u8 *addr[], const size_t *len,
     149             :                     u8 *out)
     150             : {
     151             :         const u8 *_addr[6];
     152             :         size_t _len[6];
     153          17 :         const u8 *k1 = key, *k2 = key + 16;
     154             :         size_t crypt_len;
     155             :         size_t i;
     156             :         int ret;
     157             :         u8 iv[AES_BLOCK_SIZE];
     158             :         u8 check[AES_BLOCK_SIZE];
     159             : 
     160          17 :         if (iv_c_len < AES_BLOCK_SIZE || num_elem > ARRAY_SIZE(_addr) - 1)
     161           0 :                 return -1;
     162          17 :         crypt_len = iv_c_len - AES_BLOCK_SIZE;
     163             : 
     164          66 :         for (i = 0; i < num_elem; i++) {
     165          49 :                 _addr[i] = addr[i];
     166          49 :                 _len[i] = len[i];
     167             :         }
     168          17 :         _addr[num_elem] = out;
     169          17 :         _len[num_elem] = crypt_len;
     170             : 
     171          17 :         os_memcpy(iv, iv_crypt, AES_BLOCK_SIZE);
     172          17 :         os_memcpy(out, iv_crypt + AES_BLOCK_SIZE, crypt_len);
     173             : 
     174          17 :         iv[8] &= 0x7f;
     175          17 :         iv[12] &= 0x7f;
     176             : 
     177          17 :         ret = aes_128_ctr_encrypt(k2, iv, out, crypt_len);
     178          17 :         if (ret)
     179           0 :                 return ret;
     180             : 
     181          17 :         ret = aes_s2v(k1, num_elem + 1, _addr, _len, check);
     182          17 :         if (ret)
     183           0 :                 return ret;
     184          17 :         if (os_memcmp(check, iv_crypt, AES_BLOCK_SIZE) == 0)
     185          17 :                 return 0;
     186             : 
     187           0 :         return -1;
     188             : }

Generated by: LCOV version 1.10