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 1443382998 Lines: 80 92 87.0 %
Date: 2015-09-27 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         184 : static void dbl(u8 *pad)
      21             : {
      22             :         int i, carry;
      23             : 
      24         184 :         carry = pad[0] & 0x80;
      25        2944 :         for (i = 0; i < AES_BLOCK_SIZE - 1; i++)
      26        2760 :                 pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7);
      27         184 :         pad[AES_BLOCK_SIZE - 1] <<= 1;
      28         184 :         if (carry)
      29          70 :                 pad[AES_BLOCK_SIZE - 1] ^= 0x87;
      30         184 : }
      31             : 
      32             : 
      33         184 : static void xor(u8 *a, const u8 *b)
      34             : {
      35             :         int i;
      36             : 
      37        3128 :         for (i = 0; i < AES_BLOCK_SIZE; i++)
      38        2944 :                 *a++ ^= *b++;
      39         184 : }
      40             : 
      41             : 
      42          60 : static void xorend(u8 *a, int alen, const u8 *b, int blen)
      43             : {
      44             :         int i;
      45             : 
      46          60 :         if (alen < blen)
      47          60 :                 return;
      48             : 
      49        1020 :         for (i = 0; i < blen; i++)
      50         960 :                 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          62 : 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          62 :         u8 *buf = NULL;
      69             :         int ret;
      70             :         size_t i;
      71             : 
      72          62 :         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          62 :         ret = omac1_aes_128(key, zero, sizeof(zero), tmp);
      79          62 :         if (ret)
      80           0 :                 return ret;
      81             : 
      82         244 :         for (i = 0; i < num_elem - 1; i++) {
      83         182 :                 ret = omac1_aes_128(key, addr[i], len[i], tmp2);
      84         182 :                 if (ret)
      85           0 :                         return ret;
      86             : 
      87         182 :                 dbl(tmp);
      88         182 :                 xor(tmp, tmp2);
      89             :         }
      90          62 :         if (len[i] >= AES_BLOCK_SIZE) {
      91          60 :                 buf = os_malloc(len[i]);
      92          60 :                 if (!buf)
      93           0 :                         return -ENOMEM;
      94             : 
      95          60 :                 os_memcpy(buf, addr[i], len[i]);
      96          60 :                 xorend(buf, len[i], tmp, AES_BLOCK_SIZE);
      97          60 :                 ret = omac1_aes_128(key, buf, len[i], mac);
      98          60 :                 bin_clear_free(buf, len[i]);
      99          60 :                 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          40 : 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          40 :         const u8 *k1 = key, *k2 = key + 16;
     117             :         u8 v[AES_BLOCK_SIZE];
     118             :         size_t i;
     119             :         u8 *iv, *crypt_pw;
     120             : 
     121          40 :         if (num_elem > ARRAY_SIZE(_addr) - 1)
     122           0 :                 return -1;
     123             : 
     124         158 :         for (i = 0; i < num_elem; i++) {
     125         118 :                 _addr[i] = addr[i];
     126         118 :                 _len[i] = len[i];
     127             :         }
     128          40 :         _addr[num_elem] = pw;
     129          40 :         _len[num_elem] = pwlen;
     130             : 
     131          40 :         if (aes_s2v(k1, num_elem + 1, _addr, _len, v))
     132           0 :                 return -1;
     133             : 
     134          40 :         iv = out;
     135          40 :         crypt_pw = out + AES_BLOCK_SIZE;
     136             : 
     137          40 :         os_memcpy(iv, v, AES_BLOCK_SIZE);
     138          40 :         os_memcpy(crypt_pw, pw, pwlen);
     139             : 
     140             :         /* zero out 63rd and 31st bits of ctr (from right) */
     141          40 :         v[8] &= 0x7f;
     142          40 :         v[12] &= 0x7f;
     143          40 :         return aes_128_ctr_encrypt(k2, v, crypt_pw, pwlen);
     144             : }
     145             : 
     146             : 
     147          22 : 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          22 :         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          22 :         if (iv_c_len < AES_BLOCK_SIZE || num_elem > ARRAY_SIZE(_addr) - 1)
     161           0 :                 return -1;
     162          22 :         crypt_len = iv_c_len - AES_BLOCK_SIZE;
     163             : 
     164          86 :         for (i = 0; i < num_elem; i++) {
     165          64 :                 _addr[i] = addr[i];
     166          64 :                 _len[i] = len[i];
     167             :         }
     168          22 :         _addr[num_elem] = out;
     169          22 :         _len[num_elem] = crypt_len;
     170             : 
     171          22 :         os_memcpy(iv, iv_crypt, AES_BLOCK_SIZE);
     172          22 :         os_memcpy(out, iv_crypt + AES_BLOCK_SIZE, crypt_len);
     173             : 
     174          22 :         iv[8] &= 0x7f;
     175          22 :         iv[12] &= 0x7f;
     176             : 
     177          22 :         ret = aes_128_ctr_encrypt(k2, iv, out, crypt_len);
     178          22 :         if (ret)
     179           0 :                 return ret;
     180             : 
     181          22 :         ret = aes_s2v(k1, num_elem + 1, _addr, _len, check);
     182          22 :         if (ret)
     183           0 :                 return ret;
     184          22 :         if (os_memcmp(check, iv_crypt, AES_BLOCK_SIZE) == 0)
     185          22 :                 return 0;
     186             : 
     187           0 :         return -1;
     188             : }

Generated by: LCOV version 1.10