/src/BearSSL/src/symcipher/aes_ct64_ctrcbc.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2017 Thomas Pornin <pornin@bolet.org> |
3 | | * |
4 | | * Permission is hereby granted, free of charge, to any person obtaining |
5 | | * a copy of this software and associated documentation files (the |
6 | | * "Software"), to deal in the Software without restriction, including |
7 | | * without limitation the rights to use, copy, modify, merge, publish, |
8 | | * distribute, sublicense, and/or sell copies of the Software, and to |
9 | | * permit persons to whom the Software is furnished to do so, subject to |
10 | | * the following conditions: |
11 | | * |
12 | | * The above copyright notice and this permission notice shall be |
13 | | * included in all copies or substantial portions of the Software. |
14 | | * |
15 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
16 | | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
17 | | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
18 | | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
19 | | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
20 | | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
21 | | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
22 | | * SOFTWARE. |
23 | | */ |
24 | | |
25 | | #include "inner.h" |
26 | | |
27 | | /* see bearssl_block.h */ |
28 | | void |
29 | | br_aes_ct64_ctrcbc_init(br_aes_ct64_ctrcbc_keys *ctx, |
30 | | const void *key, size_t len) |
31 | 743 | { |
32 | 743 | ctx->vtable = &br_aes_ct64_ctrcbc_vtable; |
33 | 743 | ctx->num_rounds = br_aes_ct64_keysched(ctx->skey, key, len); |
34 | 743 | } |
35 | | |
36 | | static void |
37 | | xorbuf(void *dst, const void *src, size_t len) |
38 | 3.86k | { |
39 | 3.86k | unsigned char *d; |
40 | 3.86k | const unsigned char *s; |
41 | | |
42 | 3.86k | d = dst; |
43 | 3.86k | s = src; |
44 | 65.7k | while (len -- > 0) { |
45 | 61.8k | *d ++ ^= *s ++; |
46 | 61.8k | } |
47 | 3.86k | } |
48 | | |
49 | | /* see bearssl_block.h */ |
50 | | void |
51 | | br_aes_ct64_ctrcbc_ctr(const br_aes_ct64_ctrcbc_keys *ctx, |
52 | | void *ctr, void *data, size_t len) |
53 | 1.69k | { |
54 | 1.69k | unsigned char *buf; |
55 | 1.69k | unsigned char *ivbuf; |
56 | 1.69k | uint32_t iv0, iv1, iv2, iv3; |
57 | 1.69k | uint64_t sk_exp[120]; |
58 | | |
59 | 1.69k | br_aes_ct64_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); |
60 | | |
61 | | /* |
62 | | * We keep the counter as four 32-bit values, with big-endian |
63 | | * convention, because that's what is expected for purposes of |
64 | | * incrementing the counter value. |
65 | | */ |
66 | 1.69k | ivbuf = ctr; |
67 | 1.69k | iv0 = br_dec32be(ivbuf + 0); |
68 | 1.69k | iv1 = br_dec32be(ivbuf + 4); |
69 | 1.69k | iv2 = br_dec32be(ivbuf + 8); |
70 | 1.69k | iv3 = br_dec32be(ivbuf + 12); |
71 | | |
72 | 1.69k | buf = data; |
73 | 1.69k | while (len > 0) { |
74 | 1.69k | uint64_t q[8]; |
75 | 1.69k | uint32_t w[16]; |
76 | 1.69k | unsigned char tmp[64]; |
77 | 1.69k | int i, j; |
78 | | |
79 | | /* |
80 | | * The bitslice implementation expects values in |
81 | | * little-endian convention, so we have to byteswap them. |
82 | | */ |
83 | 1.69k | j = (len >= 64) ? 16 : (int)(len >> 2); |
84 | 3.39k | for (i = 0; i < j; i += 4) { |
85 | 1.69k | uint32_t carry; |
86 | | |
87 | 1.69k | w[i + 0] = br_swap32(iv0); |
88 | 1.69k | w[i + 1] = br_swap32(iv1); |
89 | 1.69k | w[i + 2] = br_swap32(iv2); |
90 | 1.69k | w[i + 3] = br_swap32(iv3); |
91 | 1.69k | iv3 ++; |
92 | 1.69k | carry = ~(iv3 | -iv3) >> 31; |
93 | 1.69k | iv2 += carry; |
94 | 1.69k | carry &= -(~(iv2 | -iv2) >> 31); |
95 | 1.69k | iv1 += carry; |
96 | 1.69k | carry &= -(~(iv1 | -iv1) >> 31); |
97 | 1.69k | iv0 += carry; |
98 | 1.69k | } |
99 | 1.69k | memset(w + i, 0, (16 - i) * sizeof(uint32_t)); |
100 | | |
101 | 8.49k | for (i = 0; i < 4; i ++) { |
102 | 6.79k | br_aes_ct64_interleave_in( |
103 | 6.79k | &q[i], &q[i + 4], w + (i << 2)); |
104 | 6.79k | } |
105 | 1.69k | br_aes_ct64_ortho(q); |
106 | 1.69k | br_aes_ct64_bitslice_encrypt(ctx->num_rounds, sk_exp, q); |
107 | 1.69k | br_aes_ct64_ortho(q); |
108 | 8.49k | for (i = 0; i < 4; i ++) { |
109 | 6.79k | br_aes_ct64_interleave_out( |
110 | 6.79k | w + (i << 2), q[i], q[i + 4]); |
111 | 6.79k | } |
112 | | |
113 | 1.69k | br_range_enc32le(tmp, w, 16); |
114 | 1.69k | if (len <= 64) { |
115 | 1.69k | xorbuf(buf, tmp, len); |
116 | 1.69k | break; |
117 | 1.69k | } |
118 | 0 | xorbuf(buf, tmp, 64); |
119 | 0 | buf += 64; |
120 | 0 | len -= 64; |
121 | 0 | } |
122 | 1.69k | br_enc32be(ivbuf + 0, iv0); |
123 | 1.69k | br_enc32be(ivbuf + 4, iv1); |
124 | 1.69k | br_enc32be(ivbuf + 8, iv2); |
125 | 1.69k | br_enc32be(ivbuf + 12, iv3); |
126 | 1.69k | } |
127 | | |
128 | | /* see bearssl_block.h */ |
129 | | void |
130 | | br_aes_ct64_ctrcbc_mac(const br_aes_ct64_ctrcbc_keys *ctx, |
131 | | void *cbcmac, const void *data, size_t len) |
132 | 2.25k | { |
133 | 2.25k | const unsigned char *buf; |
134 | 2.25k | uint32_t cm0, cm1, cm2, cm3; |
135 | 2.25k | uint64_t q[8]; |
136 | 2.25k | uint64_t sk_exp[120]; |
137 | | |
138 | 2.25k | br_aes_ct64_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); |
139 | | |
140 | 2.25k | cm0 = br_dec32le((unsigned char *)cbcmac + 0); |
141 | 2.25k | cm1 = br_dec32le((unsigned char *)cbcmac + 4); |
142 | 2.25k | cm2 = br_dec32le((unsigned char *)cbcmac + 8); |
143 | 2.25k | cm3 = br_dec32le((unsigned char *)cbcmac + 12); |
144 | | |
145 | 2.25k | buf = data; |
146 | 2.25k | memset(q, 0, sizeof q); |
147 | 4.31k | while (len > 0) { |
148 | 2.06k | uint32_t w[4]; |
149 | | |
150 | 2.06k | w[0] = cm0 ^ br_dec32le(buf + 0); |
151 | 2.06k | w[1] = cm1 ^ br_dec32le(buf + 4); |
152 | 2.06k | w[2] = cm2 ^ br_dec32le(buf + 8); |
153 | 2.06k | w[3] = cm3 ^ br_dec32le(buf + 12); |
154 | | |
155 | 2.06k | br_aes_ct64_interleave_in(&q[0], &q[4], w); |
156 | 2.06k | br_aes_ct64_ortho(q); |
157 | 2.06k | br_aes_ct64_bitslice_encrypt(ctx->num_rounds, sk_exp, q); |
158 | 2.06k | br_aes_ct64_ortho(q); |
159 | 2.06k | br_aes_ct64_interleave_out(w, q[0], q[4]); |
160 | | |
161 | 2.06k | cm0 = w[0]; |
162 | 2.06k | cm1 = w[1]; |
163 | 2.06k | cm2 = w[2]; |
164 | 2.06k | cm3 = w[3]; |
165 | 2.06k | buf += 16; |
166 | 2.06k | len -= 16; |
167 | 2.06k | } |
168 | | |
169 | 2.25k | br_enc32le((unsigned char *)cbcmac + 0, cm0); |
170 | 2.25k | br_enc32le((unsigned char *)cbcmac + 4, cm1); |
171 | 2.25k | br_enc32le((unsigned char *)cbcmac + 8, cm2); |
172 | 2.25k | br_enc32le((unsigned char *)cbcmac + 12, cm3); |
173 | 2.25k | } |
174 | | |
175 | | /* see bearssl_block.h */ |
176 | | void |
177 | | br_aes_ct64_ctrcbc_encrypt(const br_aes_ct64_ctrcbc_keys *ctx, |
178 | | void *ctr, void *cbcmac, void *data, size_t len) |
179 | 3.75k | { |
180 | | /* |
181 | | * When encrypting, the CBC-MAC processing must be lagging by |
182 | | * one block, since it operates on the encrypted values, so |
183 | | * it must wait for that encryption to complete. |
184 | | */ |
185 | | |
186 | 3.75k | unsigned char *buf; |
187 | 3.75k | unsigned char *ivbuf; |
188 | 3.75k | uint32_t iv0, iv1, iv2, iv3; |
189 | 3.75k | uint32_t cm0, cm1, cm2, cm3; |
190 | 3.75k | uint64_t sk_exp[120]; |
191 | 3.75k | uint64_t q[8]; |
192 | 3.75k | int first_iter; |
193 | | |
194 | 3.75k | br_aes_ct64_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); |
195 | | |
196 | | /* |
197 | | * We keep the counter as four 32-bit values, with big-endian |
198 | | * convention, because that's what is expected for purposes of |
199 | | * incrementing the counter value. |
200 | | */ |
201 | 3.75k | ivbuf = ctr; |
202 | 3.75k | iv0 = br_dec32be(ivbuf + 0); |
203 | 3.75k | iv1 = br_dec32be(ivbuf + 4); |
204 | 3.75k | iv2 = br_dec32be(ivbuf + 8); |
205 | 3.75k | iv3 = br_dec32be(ivbuf + 12); |
206 | | |
207 | | /* |
208 | | * The current CBC-MAC value is kept in little-endian convention. |
209 | | */ |
210 | 3.75k | cm0 = br_dec32le((unsigned char *)cbcmac + 0); |
211 | 3.75k | cm1 = br_dec32le((unsigned char *)cbcmac + 4); |
212 | 3.75k | cm2 = br_dec32le((unsigned char *)cbcmac + 8); |
213 | 3.75k | cm3 = br_dec32le((unsigned char *)cbcmac + 12); |
214 | | |
215 | 3.75k | buf = data; |
216 | 3.75k | first_iter = 1; |
217 | 3.75k | memset(q, 0, sizeof q); |
218 | 8.17k | while (len > 0) { |
219 | 5.03k | uint32_t w[8], carry; |
220 | | |
221 | | /* |
222 | | * The bitslice implementation expects values in |
223 | | * little-endian convention, so we have to byteswap them. |
224 | | */ |
225 | 5.03k | w[0] = br_swap32(iv0); |
226 | 5.03k | w[1] = br_swap32(iv1); |
227 | 5.03k | w[2] = br_swap32(iv2); |
228 | 5.03k | w[3] = br_swap32(iv3); |
229 | 5.03k | iv3 ++; |
230 | 5.03k | carry = ~(iv3 | -iv3) >> 31; |
231 | 5.03k | iv2 += carry; |
232 | 5.03k | carry &= -(~(iv2 | -iv2) >> 31); |
233 | 5.03k | iv1 += carry; |
234 | 5.03k | carry &= -(~(iv1 | -iv1) >> 31); |
235 | 5.03k | iv0 += carry; |
236 | | |
237 | | /* |
238 | | * The block for CBC-MAC. |
239 | | */ |
240 | 5.03k | w[4] = cm0; |
241 | 5.03k | w[5] = cm1; |
242 | 5.03k | w[6] = cm2; |
243 | 5.03k | w[7] = cm3; |
244 | | |
245 | 5.03k | br_aes_ct64_interleave_in(&q[0], &q[4], w); |
246 | 5.03k | br_aes_ct64_interleave_in(&q[1], &q[5], w + 4); |
247 | 5.03k | br_aes_ct64_ortho(q); |
248 | 5.03k | br_aes_ct64_bitslice_encrypt(ctx->num_rounds, sk_exp, q); |
249 | 5.03k | br_aes_ct64_ortho(q); |
250 | 5.03k | br_aes_ct64_interleave_out(w, q[0], q[4]); |
251 | 5.03k | br_aes_ct64_interleave_out(w + 4, q[1], q[5]); |
252 | | |
253 | | /* |
254 | | * We do the XOR with the plaintext in 32-bit registers, |
255 | | * so that the value are available for CBC-MAC processing |
256 | | * as well. |
257 | | */ |
258 | 5.03k | w[0] ^= br_dec32le(buf + 0); |
259 | 5.03k | w[1] ^= br_dec32le(buf + 4); |
260 | 5.03k | w[2] ^= br_dec32le(buf + 8); |
261 | 5.03k | w[3] ^= br_dec32le(buf + 12); |
262 | 5.03k | br_enc32le(buf + 0, w[0]); |
263 | 5.03k | br_enc32le(buf + 4, w[1]); |
264 | 5.03k | br_enc32le(buf + 8, w[2]); |
265 | 5.03k | br_enc32le(buf + 12, w[3]); |
266 | | |
267 | 5.03k | buf += 16; |
268 | 5.03k | len -= 16; |
269 | | |
270 | | /* |
271 | | * We set the cm* values to the block to encrypt in the |
272 | | * next iteration. |
273 | | */ |
274 | 5.03k | if (first_iter) { |
275 | 611 | first_iter = 0; |
276 | 611 | cm0 ^= w[0]; |
277 | 611 | cm1 ^= w[1]; |
278 | 611 | cm2 ^= w[2]; |
279 | 611 | cm3 ^= w[3]; |
280 | 4.42k | } else { |
281 | 4.42k | cm0 = w[0] ^ w[4]; |
282 | 4.42k | cm1 = w[1] ^ w[5]; |
283 | 4.42k | cm2 = w[2] ^ w[6]; |
284 | 4.42k | cm3 = w[3] ^ w[7]; |
285 | 4.42k | } |
286 | | |
287 | | /* |
288 | | * If this was the last iteration, then compute the |
289 | | * extra block encryption to complete CBC-MAC. |
290 | | */ |
291 | 5.03k | if (len == 0) { |
292 | 611 | w[0] = cm0; |
293 | 611 | w[1] = cm1; |
294 | 611 | w[2] = cm2; |
295 | 611 | w[3] = cm3; |
296 | 611 | br_aes_ct64_interleave_in(&q[0], &q[4], w); |
297 | 611 | br_aes_ct64_ortho(q); |
298 | 611 | br_aes_ct64_bitslice_encrypt( |
299 | 611 | ctx->num_rounds, sk_exp, q); |
300 | 611 | br_aes_ct64_ortho(q); |
301 | 611 | br_aes_ct64_interleave_out(w, q[0], q[4]); |
302 | 611 | cm0 = w[0]; |
303 | 611 | cm1 = w[1]; |
304 | 611 | cm2 = w[2]; |
305 | 611 | cm3 = w[3]; |
306 | 611 | break; |
307 | 611 | } |
308 | 5.03k | } |
309 | | |
310 | 3.75k | br_enc32be(ivbuf + 0, iv0); |
311 | 3.75k | br_enc32be(ivbuf + 4, iv1); |
312 | 3.75k | br_enc32be(ivbuf + 8, iv2); |
313 | 3.75k | br_enc32be(ivbuf + 12, iv3); |
314 | 3.75k | br_enc32le((unsigned char *)cbcmac + 0, cm0); |
315 | 3.75k | br_enc32le((unsigned char *)cbcmac + 4, cm1); |
316 | 3.75k | br_enc32le((unsigned char *)cbcmac + 8, cm2); |
317 | 3.75k | br_enc32le((unsigned char *)cbcmac + 12, cm3); |
318 | 3.75k | } |
319 | | |
320 | | /* see bearssl_block.h */ |
321 | | void |
322 | | br_aes_ct64_ctrcbc_decrypt(const br_aes_ct64_ctrcbc_keys *ctx, |
323 | | void *ctr, void *cbcmac, void *data, size_t len) |
324 | 665 | { |
325 | 665 | unsigned char *buf; |
326 | 665 | unsigned char *ivbuf; |
327 | 665 | uint32_t iv0, iv1, iv2, iv3; |
328 | 665 | uint32_t cm0, cm1, cm2, cm3; |
329 | 665 | uint64_t sk_exp[120]; |
330 | 665 | uint64_t q[8]; |
331 | | |
332 | 665 | br_aes_ct64_skey_expand(sk_exp, ctx->num_rounds, ctx->skey); |
333 | | |
334 | | /* |
335 | | * We keep the counter as four 32-bit values, with big-endian |
336 | | * convention, because that's what is expected for purposes of |
337 | | * incrementing the counter value. |
338 | | */ |
339 | 665 | ivbuf = ctr; |
340 | 665 | iv0 = br_dec32be(ivbuf + 0); |
341 | 665 | iv1 = br_dec32be(ivbuf + 4); |
342 | 665 | iv2 = br_dec32be(ivbuf + 8); |
343 | 665 | iv3 = br_dec32be(ivbuf + 12); |
344 | | |
345 | | /* |
346 | | * The current CBC-MAC value is kept in little-endian convention. |
347 | | */ |
348 | 665 | cm0 = br_dec32le((unsigned char *)cbcmac + 0); |
349 | 665 | cm1 = br_dec32le((unsigned char *)cbcmac + 4); |
350 | 665 | cm2 = br_dec32le((unsigned char *)cbcmac + 8); |
351 | 665 | cm3 = br_dec32le((unsigned char *)cbcmac + 12); |
352 | | |
353 | 665 | buf = data; |
354 | 665 | memset(q, 0, sizeof q); |
355 | 2.83k | while (len > 0) { |
356 | 2.16k | uint32_t w[8], carry; |
357 | 2.16k | unsigned char tmp[16]; |
358 | | |
359 | | /* |
360 | | * The bitslice implementation expects values in |
361 | | * little-endian convention, so we have to byteswap them. |
362 | | */ |
363 | 2.16k | w[0] = br_swap32(iv0); |
364 | 2.16k | w[1] = br_swap32(iv1); |
365 | 2.16k | w[2] = br_swap32(iv2); |
366 | 2.16k | w[3] = br_swap32(iv3); |
367 | 2.16k | iv3 ++; |
368 | 2.16k | carry = ~(iv3 | -iv3) >> 31; |
369 | 2.16k | iv2 += carry; |
370 | 2.16k | carry &= -(~(iv2 | -iv2) >> 31); |
371 | 2.16k | iv1 += carry; |
372 | 2.16k | carry &= -(~(iv1 | -iv1) >> 31); |
373 | 2.16k | iv0 += carry; |
374 | | |
375 | | /* |
376 | | * The block for CBC-MAC. |
377 | | */ |
378 | 2.16k | w[4] = cm0 ^ br_dec32le(buf + 0); |
379 | 2.16k | w[5] = cm1 ^ br_dec32le(buf + 4); |
380 | 2.16k | w[6] = cm2 ^ br_dec32le(buf + 8); |
381 | 2.16k | w[7] = cm3 ^ br_dec32le(buf + 12); |
382 | | |
383 | 2.16k | br_aes_ct64_interleave_in(&q[0], &q[4], w); |
384 | 2.16k | br_aes_ct64_interleave_in(&q[1], &q[5], w + 4); |
385 | 2.16k | br_aes_ct64_ortho(q); |
386 | 2.16k | br_aes_ct64_bitslice_encrypt(ctx->num_rounds, sk_exp, q); |
387 | 2.16k | br_aes_ct64_ortho(q); |
388 | 2.16k | br_aes_ct64_interleave_out(w, q[0], q[4]); |
389 | 2.16k | br_aes_ct64_interleave_out(w + 4, q[1], q[5]); |
390 | | |
391 | 2.16k | br_enc32le(tmp + 0, w[0]); |
392 | 2.16k | br_enc32le(tmp + 4, w[1]); |
393 | 2.16k | br_enc32le(tmp + 8, w[2]); |
394 | 2.16k | br_enc32le(tmp + 12, w[3]); |
395 | 2.16k | xorbuf(buf, tmp, 16); |
396 | 2.16k | cm0 = w[4]; |
397 | 2.16k | cm1 = w[5]; |
398 | 2.16k | cm2 = w[6]; |
399 | 2.16k | cm3 = w[7]; |
400 | 2.16k | buf += 16; |
401 | 2.16k | len -= 16; |
402 | 2.16k | } |
403 | | |
404 | 665 | br_enc32be(ivbuf + 0, iv0); |
405 | 665 | br_enc32be(ivbuf + 4, iv1); |
406 | 665 | br_enc32be(ivbuf + 8, iv2); |
407 | 665 | br_enc32be(ivbuf + 12, iv3); |
408 | 665 | br_enc32le((unsigned char *)cbcmac + 0, cm0); |
409 | 665 | br_enc32le((unsigned char *)cbcmac + 4, cm1); |
410 | 665 | br_enc32le((unsigned char *)cbcmac + 8, cm2); |
411 | 665 | br_enc32le((unsigned char *)cbcmac + 12, cm3); |
412 | 665 | } |
413 | | |
414 | | /* see bearssl_block.h */ |
415 | | const br_block_ctrcbc_class br_aes_ct64_ctrcbc_vtable = { |
416 | | sizeof(br_aes_ct64_ctrcbc_keys), |
417 | | 16, |
418 | | 4, |
419 | | (void (*)(const br_block_ctrcbc_class **, const void *, size_t)) |
420 | | &br_aes_ct64_ctrcbc_init, |
421 | | (void (*)(const br_block_ctrcbc_class *const *, |
422 | | void *, void *, void *, size_t)) |
423 | | &br_aes_ct64_ctrcbc_encrypt, |
424 | | (void (*)(const br_block_ctrcbc_class *const *, |
425 | | void *, void *, void *, size_t)) |
426 | | &br_aes_ct64_ctrcbc_decrypt, |
427 | | (void (*)(const br_block_ctrcbc_class *const *, |
428 | | void *, void *, size_t)) |
429 | | &br_aes_ct64_ctrcbc_ctr, |
430 | | (void (*)(const br_block_ctrcbc_class *const *, |
431 | | void *, const void *, size_t)) |
432 | | &br_aes_ct64_ctrcbc_mac |
433 | | }; |