2 * Copyright (C) 2008-2015 Martin Willi
3 * Copyright (C) 2012 Tobias Brunner
5 * Copyright (C) secunet Security Networks AG
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 #include "aesni_xcbc.h"
19 #include "aesni_key.h"
21 #include <crypto/prfs/mac_prf.h>
22 #include <crypto/signers/mac_signer.h>
24 typedef struct private_aesni_mac_t private_aesni_mac_t
;
27 * Private data of a mac_t object.
29 struct private_aesni_mac_t
{
32 * Public mac_t interface.
57 * remaining, unprocessed bytes in append mode
59 u_char rem
[AES_BLOCK_SIZE
];
62 * number of bytes used in remaining
67 * TRUE if we have zero bytes to xcbc in final()
72 METHOD(mac_t
, get_mac
, bool,
73 private_aesni_mac_t
*this, chunk_t data
, uint8_t *out
)
83 ks
= this->k1
->schedule
;
92 if (this->rem_size
+ data
.len
> AES_BLOCK_SIZE
)
94 /* (3) For each block M[i], where i = 1 ... n-1:
95 * XOR M[i] with E[i-1], then encrypt the result with Key K1,
99 /* append data to remaining bytes, process block M[1] */
100 memcpy(this->rem
+ this->rem_size
, data
.ptr
,
101 AES_BLOCK_SIZE
- this->rem_size
);
102 data
= chunk_skip(data
, AES_BLOCK_SIZE
- this->rem_size
);
104 e
= _mm_xor_si128(e
, _mm_loadu_si128((__m128i
*)this->rem
));
106 e
= _mm_xor_si128(e
, ks
[0]);
107 e
= _mm_aesenc_si128(e
, ks
[1]);
108 e
= _mm_aesenc_si128(e
, ks
[2]);
109 e
= _mm_aesenc_si128(e
, ks
[3]);
110 e
= _mm_aesenc_si128(e
, ks
[4]);
111 e
= _mm_aesenc_si128(e
, ks
[5]);
112 e
= _mm_aesenc_si128(e
, ks
[6]);
113 e
= _mm_aesenc_si128(e
, ks
[7]);
114 e
= _mm_aesenc_si128(e
, ks
[8]);
115 e
= _mm_aesenc_si128(e
, ks
[9]);
116 e
= _mm_aesenclast_si128(e
, ks
[10]);
118 bi
= (__m128i
*)data
.ptr
;
119 rem
= data
.len
% AES_BLOCK_SIZE
;
120 blocks
= data
.len
/ AES_BLOCK_SIZE
;
122 { /* don't do last block */
123 rem
= AES_BLOCK_SIZE
;
127 /* process blocks M[2] ... M[n-1] */
128 for (i
= 0; i
< blocks
; i
++)
130 e
= _mm_xor_si128(e
, _mm_loadu_si128(bi
+ i
));
132 e
= _mm_xor_si128(e
, ks
[0]);
133 e
= _mm_aesenc_si128(e
, ks
[1]);
134 e
= _mm_aesenc_si128(e
, ks
[2]);
135 e
= _mm_aesenc_si128(e
, ks
[3]);
136 e
= _mm_aesenc_si128(e
, ks
[4]);
137 e
= _mm_aesenc_si128(e
, ks
[5]);
138 e
= _mm_aesenc_si128(e
, ks
[6]);
139 e
= _mm_aesenc_si128(e
, ks
[7]);
140 e
= _mm_aesenc_si128(e
, ks
[8]);
141 e
= _mm_aesenc_si128(e
, ks
[9]);
142 e
= _mm_aesenclast_si128(e
, ks
[10]);
145 /* store remaining bytes of block M[n] */
146 memcpy(this->rem
, data
.ptr
+ data
.len
- rem
, rem
);
147 this->rem_size
= rem
;
151 /* no complete block, just copy into remaining */
152 memcpy(this->rem
+ this->rem_size
, data
.ptr
, data
.len
);
153 this->rem_size
+= data
.len
;
158 /* (4) For block M[n]: */
159 if (this->rem_size
== AES_BLOCK_SIZE
&& !this->zero
)
161 /* a) If the blocksize of M[n] is 128 bits:
162 * XOR M[n] with E[n-1] and Key K2, then encrypt the result with
163 * Key K1, yielding E[n].
165 e
= _mm_xor_si128(e
, this->k2
);
169 /* b) If the blocksize of M[n] is less than 128 bits:
171 * i) Pad M[n] with a single "1" bit, followed by the number of
172 * "0" bits (possibly none) required to increase M[n]'s
173 * blocksize to 128 bits.
175 if (this->rem_size
< AES_BLOCK_SIZE
)
177 memset(this->rem
+ this->rem_size
, 0,
178 AES_BLOCK_SIZE
- this->rem_size
);
179 this->rem
[this->rem_size
] = 0x80;
181 /* ii) XOR M[n] with E[n-1] and Key K3, then encrypt the result
182 * with Key K1, yielding E[n].
184 e
= _mm_xor_si128(e
, this->k3
);
186 e
= _mm_xor_si128(e
, _mm_loadu_si128((__m128i
*)this->rem
));
188 e
= _mm_xor_si128(e
, ks
[0]);
189 e
= _mm_aesenc_si128(e
, ks
[1]);
190 e
= _mm_aesenc_si128(e
, ks
[2]);
191 e
= _mm_aesenc_si128(e
, ks
[3]);
192 e
= _mm_aesenc_si128(e
, ks
[4]);
193 e
= _mm_aesenc_si128(e
, ks
[5]);
194 e
= _mm_aesenc_si128(e
, ks
[6]);
195 e
= _mm_aesenc_si128(e
, ks
[7]);
196 e
= _mm_aesenc_si128(e
, ks
[8]);
197 e
= _mm_aesenc_si128(e
, ks
[9]);
198 e
= _mm_aesenclast_si128(e
, ks
[10]);
199 _mm_storeu_si128((__m128i
*)out
, e
);
201 /* (2) Define E[0] = 0x00000000000000000000000000000000 */
202 e
= _mm_setzero_si128();
210 METHOD(mac_t
, get_mac_size
, size_t,
211 private_aesni_mac_t
*this)
213 return AES_BLOCK_SIZE
;
216 METHOD(mac_t
, set_key
, bool,
217 private_aesni_mac_t
*this, chunk_t key
)
220 u_char k1
[AES_BLOCK_SIZE
];
225 this->e
= _mm_setzero_si128();
229 /* Create RFC4434 variable keys if required */
230 if (key
.len
== AES_BLOCK_SIZE
)
234 else if (key
.len
< AES_BLOCK_SIZE
)
235 { /* pad short keys */
236 k
= chunk_alloca(AES_BLOCK_SIZE
);
237 memset(k
.ptr
, 0, k
.len
);
238 memcpy(k
.ptr
, key
.ptr
, key
.len
);
241 { /* shorten key using XCBC */
242 k
= chunk_alloca(AES_BLOCK_SIZE
);
243 memset(k
.ptr
, 0, k
.len
);
244 if (!set_key(this, k
) || !get_mac(this, key
, k
.ptr
))
251 * (1) Derive 3 128-bit keys (K1, K2 and K3) from the 128-bit secret
253 * K1 = 0x01010101010101010101010101010101 encrypted with Key K
254 * K2 = 0x02020202020202020202020202020202 encrypted with Key K
255 * K3 = 0x03030303030303030303030303030303 encrypted with Key K
258 DESTROY_IF(this->k1
);
259 this->k1
= aesni_key_create(TRUE
, k
);
265 t1
= _mm_set1_epi8(0x01);
266 t2
= _mm_set1_epi8(0x02);
267 t3
= _mm_set1_epi8(0x03);
269 t1
= _mm_xor_si128(t1
, this->k1
->schedule
[0]);
270 t2
= _mm_xor_si128(t2
, this->k1
->schedule
[0]);
271 t3
= _mm_xor_si128(t3
, this->k1
->schedule
[0]);
273 for (round
= 1; round
< this->k1
->rounds
; round
++)
275 t1
= _mm_aesenc_si128(t1
, this->k1
->schedule
[round
]);
276 t2
= _mm_aesenc_si128(t2
, this->k1
->schedule
[round
]);
277 t3
= _mm_aesenc_si128(t3
, this->k1
->schedule
[round
]);
280 t1
= _mm_aesenclast_si128(t1
, this->k1
->schedule
[this->k1
->rounds
]);
281 t2
= _mm_aesenclast_si128(t2
, this->k1
->schedule
[this->k1
->rounds
]);
282 t3
= _mm_aesenclast_si128(t3
, this->k1
->schedule
[this->k1
->rounds
]);
284 _mm_storeu_si128((__m128i
*)k1
, t1
);
288 this->k1
->destroy(this->k1
);
289 this->k1
= aesni_key_create(TRUE
, chunk_from_thing(k1
));
291 memwipe(k1
, AES_BLOCK_SIZE
);
292 return this->k1
!= NULL
;
295 METHOD(mac_t
, destroy
, void,
296 private_aesni_mac_t
*this)
298 DESTROY_IF(this->k1
);
299 memwipe(&this->k2
, sizeof(this->k2
));
300 memwipe(&this->k3
, sizeof(this->k3
));
305 * Described in header
307 mac_t
*aesni_xcbc_create(encryption_algorithm_t algo
, size_t key_size
)
309 private_aesni_mac_t
*this;
311 INIT_ALIGN(this, sizeof(__m128i
),
314 .get_mac_size
= _get_mac_size
,
320 return &this->public;
324 * Described in header.
326 prf_t
*aesni_xcbc_prf_create(pseudo_random_function_t algo
)
332 case PRF_AES128_XCBC
:
333 xcbc
= aesni_xcbc_create(ENCR_AES_CBC
, 16);
340 return mac_prf_create(xcbc
);
346 * Described in header
348 signer_t
*aesni_xcbc_signer_create(integrity_algorithm_t algo
)
355 case AUTH_AES_XCBC_96
:
356 xcbc
= aesni_xcbc_create(ENCR_AES_CBC
, 16);
364 return mac_signer_create(xcbc
, trunc
);