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  
dbl(u8 * pad)20  static void dbl(u8 *pad)
21  {
22  	int i, carry;
23  
24  	carry = pad[0] & 0x80;
25  	for (i = 0; i < AES_BLOCK_SIZE - 1; i++)
26  		pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7);
27  	pad[AES_BLOCK_SIZE - 1] <<= 1;
28  	if (carry)
29  		pad[AES_BLOCK_SIZE - 1] ^= 0x87;
30  }
31  
32  
xor(u8 * a,const u8 * b)33  static void xor(u8 *a, const u8 *b)
34  {
35  	int i;
36  
37  	for (i = 0; i < AES_BLOCK_SIZE; i++)
38  		*a++ ^= *b++;
39  }
40  
41  
xorend(u8 * a,int alen,const u8 * b,int blen)42  static void xorend(u8 *a, int alen, const u8 *b, int blen)
43  {
44  	int i;
45  
46  	if (alen < blen)
47  		return;
48  
49  	for (i = 0; i < blen; i++)
50  		a[alen - blen + i] ^= b[i];
51  }
52  
53  
pad_block(u8 * pad,const u8 * addr,size_t len)54  static void pad_block(u8 *pad, const u8 *addr, size_t len)
55  {
56  	os_memset(pad, 0, AES_BLOCK_SIZE);
57  	os_memcpy(pad, addr, len);
58  
59  	if (len < AES_BLOCK_SIZE)
60  		pad[len] = 0x80;
61  }
62  
63  
aes_s2v(const u8 * key,size_t key_len,size_t num_elem,const u8 * addr[],size_t * len,u8 * mac)64  static int aes_s2v(const u8 *key, size_t key_len,
65  		   size_t num_elem, const u8 *addr[], size_t *len, u8 *mac)
66  {
67  	u8 tmp[AES_BLOCK_SIZE], tmp2[AES_BLOCK_SIZE];
68  	u8 *buf = NULL;
69  	int ret;
70  	size_t i;
71  	const u8 *data[1];
72  	size_t data_len[1];
73  
74  	if (!num_elem) {
75  		os_memcpy(tmp, zero, sizeof(zero));
76  		tmp[AES_BLOCK_SIZE - 1] = 1;
77  		data[0] = tmp;
78  		data_len[0] = sizeof(tmp);
79  		return omac1_aes_vector(key, key_len, 1, data, data_len, mac);
80  	}
81  
82  	data[0] = zero;
83  	data_len[0] = sizeof(zero);
84  	ret = omac1_aes_vector(key, key_len, 1, data, data_len, tmp);
85  	if (ret)
86  		return ret;
87  
88  	for (i = 0; i < num_elem - 1; i++) {
89  		ret = omac1_aes_vector(key, key_len, 1, &addr[i], &len[i],
90  				       tmp2);
91  		if (ret)
92  			return ret;
93  
94  		dbl(tmp);
95  		xor(tmp, tmp2);
96  	}
97  	if (len[i] >= AES_BLOCK_SIZE) {
98  		buf = os_memdup(addr[i], len[i]);
99  		if (!buf)
100  			return -ENOMEM;
101  
102  		xorend(buf, len[i], tmp, AES_BLOCK_SIZE);
103  		data[0] = buf;
104  		ret = omac1_aes_vector(key, key_len, 1, data, &len[i], mac);
105  		bin_clear_free(buf, len[i]);
106  		return ret;
107  	}
108  
109  	dbl(tmp);
110  	pad_block(tmp2, addr[i], len[i]);
111  	xor(tmp, tmp2);
112  
113  	data[0] = tmp;
114  	data_len[0] = sizeof(tmp);
115  	return omac1_aes_vector(key, key_len, 1, data, data_len, mac);
116  }
117  
118  
aes_siv_encrypt(const u8 * key,size_t key_len,const u8 * pw,size_t pwlen,size_t num_elem,const u8 * addr[],const size_t * len,u8 * out)119  int aes_siv_encrypt(const u8 *key, size_t key_len,
120  		    const u8 *pw, size_t pwlen,
121  		    size_t num_elem, const u8 *addr[], const size_t *len,
122  		    u8 *out)
123  {
124  	const u8 *_addr[6];
125  	size_t _len[6];
126  	const u8 *k1, *k2;
127  	u8 v[AES_BLOCK_SIZE];
128  	size_t i;
129  	u8 *iv, *crypt_pw;
130  
131  	if (num_elem > ARRAY_SIZE(_addr) - 1 ||
132  	    (key_len != 32 && key_len != 48 && key_len != 64))
133  		return -1;
134  
135  	key_len /= 2;
136  	k1 = key;
137  	k2 = key + key_len;
138  
139  	for (i = 0; i < num_elem; i++) {
140  		_addr[i] = addr[i];
141  		_len[i] = len[i];
142  	}
143  	_addr[num_elem] = pw;
144  	_len[num_elem] = pwlen;
145  
146  	if (aes_s2v(k1, key_len, num_elem + 1, _addr, _len, v))
147  		return -1;
148  
149  	iv = out;
150  	crypt_pw = out + AES_BLOCK_SIZE;
151  
152  	os_memcpy(iv, v, AES_BLOCK_SIZE);
153  	os_memcpy(crypt_pw, pw, pwlen);
154  
155  	/* zero out 63rd and 31st bits of ctr (from right) */
156  	v[8] &= 0x7f;
157  	v[12] &= 0x7f;
158  	return aes_ctr_encrypt(k2, key_len, v, crypt_pw, pwlen);
159  }
160  
161  
aes_siv_decrypt(const u8 * key,size_t key_len,const u8 * iv_crypt,size_t iv_c_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * out)162  int aes_siv_decrypt(const u8 *key, size_t key_len,
163  		    const u8 *iv_crypt, size_t iv_c_len,
164  		    size_t num_elem, const u8 *addr[], const size_t *len,
165  		    u8 *out)
166  {
167  	const u8 *_addr[6];
168  	size_t _len[6];
169  	const u8 *k1, *k2;
170  	size_t crypt_len;
171  	size_t i;
172  	int ret;
173  	u8 iv[AES_BLOCK_SIZE];
174  	u8 check[AES_BLOCK_SIZE];
175  
176  	if (iv_c_len < AES_BLOCK_SIZE || num_elem > ARRAY_SIZE(_addr) - 1 ||
177  	    (key_len != 32 && key_len != 48 && key_len != 64))
178  		return -1;
179  	crypt_len = iv_c_len - AES_BLOCK_SIZE;
180  	key_len /= 2;
181  	k1 = key;
182  	k2 = key + key_len;
183  
184  	for (i = 0; i < num_elem; i++) {
185  		_addr[i] = addr[i];
186  		_len[i] = len[i];
187  	}
188  	_addr[num_elem] = out;
189  	_len[num_elem] = crypt_len;
190  
191  	os_memcpy(iv, iv_crypt, AES_BLOCK_SIZE);
192  	os_memcpy(out, iv_crypt + AES_BLOCK_SIZE, crypt_len);
193  
194  	iv[8] &= 0x7f;
195  	iv[12] &= 0x7f;
196  
197  	ret = aes_ctr_encrypt(k2, key_len, iv, out, crypt_len);
198  	if (ret)
199  		return ret;
200  
201  	ret = aes_s2v(k1, key_len, num_elem + 1, _addr, _len, check);
202  	if (ret)
203  		return ret;
204  	if (os_memcmp(check, iv_crypt, AES_BLOCK_SIZE) == 0)
205  		return 0;
206  
207  	return -1;
208  }
209