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

Generated by: LCOV version 1.10