aes_ccm.c revision 1.1 1 /* $NetBSD: aes_ccm.c,v 1.1 2020/07/25 22:15:55 riastradh Exp $ */
2
3 /*-
4 * Copyright (c) 2020 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /*
30 * AES-CCM, as defined in:
31 *
32 * D. Whiting, R. Housley, and N. Ferguson, `Counter with CBC-MAC
33 * (CCM)', IETF RFC 3610, September 2003.
34 * https://tools.ietf.org/html/rfc3610
35 */
36
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(1, "$NetBSD: aes_ccm.c,v 1.1 2020/07/25 22:15:55 riastradh Exp $");
39
40 #include <sys/types.h>
41 #include <sys/param.h>
42 #include <sys/systm.h>
43
44 #include <lib/libkern/libkern.h>
45
46 #include <crypto/aes/aes.h>
47 #include <crypto/aes/aes_ccm.h>
48
49 static inline void
50 xor(uint8_t *x, const uint8_t *a, const uint8_t *b, size_t n)
51 {
52
53 while (n --> 0)
54 *x++ = *a++ ^ *b++;
55 }
56
57 static inline void
58 xor16(uint8_t *x, const uint8_t *a, const uint8_t *b)
59 {
60
61 xor(x, a, b, 16);
62 }
63
64 /* RFC 3610, 2.2 Authentication */
65 #define CCM_AFLAGS_ADATA __BIT(6)
66 #define CCM_AFLAGS_M __BITS(5,3)
67 #define CCM_AFLAGS_L __BITS(2,0)
68
69 /* RFC 3610, 2.3 Encryption */
70 #define CCM_EFLAGS_L __BITS(2,0)
71
72 static void
73 aes_ccm_inc(struct aes_ccm *C)
74 {
75
76 KASSERT(C->L == 2);
77 if (++C->in[15] == 0 && ++C->in[14] == 0)
78 panic("AES-CCM overflow");
79 }
80
81 static void
82 aes_ccm_zero_ctr(struct aes_ccm *C)
83 {
84
85 KASSERT(C->L == 2);
86 C->in[14] = C->in[15] = 0;
87 }
88
89 void
90 aes_ccm_init(struct aes_ccm *C, unsigned nr, const struct aesenc *enc,
91 unsigned L, unsigned M,
92 const uint8_t *nonce, unsigned noncelen, const void *ad, size_t adlen,
93 size_t mlen)
94 {
95 const uint8_t *adp = ad;
96 unsigned i;
97
98 KASSERT(L == 2);
99 KASSERT(M % 2 == 0);
100 KASSERT(M >= 4);
101 KASSERT(M <= 16);
102 KASSERT(noncelen == 15 - L);
103
104 C->enc = enc;
105 C->nr = nr;
106 C->L = L;
107 C->M = M;
108 C->mlen = C->mleft = mlen;
109
110 /* Encode B0, the initial authenticated data block. */
111 C->auth[0] = __SHIFTIN(adlen == 0 ? 0 : 1, CCM_AFLAGS_ADATA);
112 C->auth[0] |= __SHIFTIN((M - 2)/2, CCM_AFLAGS_M);
113 C->auth[0] |= __SHIFTIN(L - 1, CCM_AFLAGS_L);
114 memcpy(C->auth + 1, nonce, noncelen);
115 for (i = 0; i < L; i++, mlen >>= 8) {
116 KASSERT(i < 16 - 1 - noncelen);
117 C->auth[16 - i - 1] = mlen & 0xff;
118 }
119 aes_enc(enc, C->auth, C->auth, C->nr);
120
121 /* Process additional authenticated data, if any. */
122 if (adlen) {
123 /* Encode the length according to the table on p. 4. */
124 if (adlen < 0xff00) {
125 C->auth[0] ^= adlen >> 8;
126 C->auth[1] ^= adlen;
127 i = 2;
128 } else if (adlen < 0xffffffff) {
129 C->auth[0] ^= 0xff;
130 C->auth[1] ^= 0xfe;
131 C->auth[2] ^= adlen >> 24;
132 C->auth[3] ^= adlen >> 16;
133 C->auth[4] ^= adlen >> 8;
134 C->auth[5] ^= adlen;
135 i = 6;
136 #if SIZE_MAX > 0xffffffffU
137 } else {
138 CTASSERT(SIZE_MAX <= 0xffffffffffffffff);
139 C->auth[0] ^= 0xff;
140 C->auth[1] ^= 0xff;
141 C->auth[2] ^= adlen >> 56;
142 C->auth[3] ^= adlen >> 48;
143 C->auth[4] ^= adlen >> 40;
144 C->auth[5] ^= adlen >> 32;
145 C->auth[6] ^= adlen >> 24;
146 C->auth[7] ^= adlen >> 16;
147 C->auth[8] ^= adlen >> 8;
148 C->auth[9] ^= adlen;
149 i = 10;
150 #endif
151 }
152
153 /* Fill out the partial block if we can, and encrypt. */
154 xor(C->auth + i, C->auth + i, adp, MIN(adlen, 16 - i));
155 adp += MIN(adlen, 16 - i);
156 adlen -= MIN(adlen, 16 - i);
157 aes_enc(enc, C->auth, C->auth, C->nr);
158
159 /* If there was anything more, process 16 bytes at a time. */
160 for (; adlen >= 16; adp += 16, adlen -= 16) {
161 xor16(C->auth, C->auth, adp);
162 aes_enc(enc, C->auth, C->auth, C->nr);
163 }
164
165 /*
166 * If there's anything at the end, enter it in (padded
167 * with zeros, which is a no-op) and process it.
168 */
169 if (adlen) {
170 xor(C->auth, C->auth, adp, adlen);
171 aes_enc(enc, C->auth, C->auth, C->nr);
172 }
173 }
174
175 /* Set up the AES input for AES-CTR encryption. */
176 C->in[0] = __SHIFTIN(L - 1, CCM_EFLAGS_L);
177 memcpy(C->in + 1, nonce, noncelen);
178 memset(C->in + 1 + noncelen, 0, 16 - 1 - noncelen);
179
180 /* Start on a block boundary. */
181 C->i = 0;
182 }
183
184 void
185 aes_ccm_enc(struct aes_ccm *C, const void *in, void *out, size_t nbytes)
186 {
187 const uint8_t *p = in;
188 uint8_t *q = out;
189
190 KASSERTMSG(C->i != ~0u,
191 "%s not allowed after message complete", __func__);
192 KASSERTMSG(nbytes <= C->mleft,
193 "message too long: promised %zu bytes, processing >=%zu",
194 C->mlen, C->mlen - C->mleft + nbytes);
195 C->mleft -= nbytes;
196
197 /* Finish a partial block if it was already started. */
198 if (C->i) {
199 unsigned m = MIN(16 - C->i, nbytes);
200
201 xor(C->auth + C->i, C->auth + C->i, p, m);
202 xor(q, C->out + C->i, p, m);
203 C->i += m;
204 p += m;
205 q += m;
206 nbytes -= m;
207
208 if (C->i == 16) {
209 /* Finished a block; authenticate it. */
210 aes_enc(C->enc, C->auth, C->auth, C->nr);
211 C->i = 0;
212 } else {
213 /* Didn't finish block, must be done with input. */
214 KASSERT(nbytes == 0);
215 return;
216 }
217 }
218
219 /* Process 16 bytes at a time. */
220 for (; nbytes >= 16; p += 16, q += 16, nbytes -= 16) {
221 /* authenticate */
222 xor16(C->auth, C->auth, p);
223 aes_enc(C->enc, C->auth, C->auth, C->nr);
224
225 /* encrypt */
226 aes_ccm_inc(C);
227 aes_enc(C->enc, C->in, C->out, C->nr);
228 xor16(q, C->out, p);
229 }
230
231 /* Incorporate any <16-byte unit as a partial block. */
232 if (nbytes) {
233 /* authenticate */
234 xor(C->auth, C->auth, p, nbytes);
235
236 /* encrypt */
237 aes_ccm_inc(C);
238 aes_enc(C->enc, C->in, C->out, C->nr);
239 xor(q, C->out, p, nbytes);
240
241 C->i = nbytes;
242 }
243 }
244
245 void
246 aes_ccm_dec(struct aes_ccm *C, const void *in, void *out, size_t nbytes)
247 {
248 const uint8_t *p = in;
249 uint8_t *q = out;
250
251 KASSERTMSG(C->i != ~0u,
252 "%s not allowed after message complete", __func__);
253 KASSERTMSG(nbytes <= C->mleft,
254 "message too long: promised %zu bytes, processing >=%zu",
255 C->mlen, C->mlen - C->mleft + nbytes);
256 C->mleft -= nbytes;
257
258 /* Finish a partial block if it was already started. */
259 if (C->i) {
260 unsigned m = MIN(16 - C->i, nbytes);
261
262 xor(q, C->out + C->i, p, m);
263 xor(C->auth + C->i, C->auth + C->i, q, m);
264 C->i += m;
265 p += m;
266 q += m;
267 nbytes -= m;
268
269 if (C->i == 16) {
270 /* Finished a block; authenticate it. */
271 aes_enc(C->enc, C->auth, C->auth, C->nr);
272 C->i = 0;
273 } else {
274 /* Didn't finish block, must be done with input. */
275 KASSERT(nbytes == 0);
276 return;
277 }
278 }
279
280 /* Process 16 bytes at a time. */
281 for (; nbytes >= 16; p += 16, q += 16, nbytes -= 16) {
282 /* decrypt */
283 aes_ccm_inc(C);
284 aes_enc(C->enc, C->in, C->out, C->nr);
285 xor16(q, C->out, p);
286
287 /* authenticate */
288 xor16(C->auth, C->auth, q);
289 aes_enc(C->enc, C->auth, C->auth, C->nr);
290 }
291
292 /* Incorporate any <16-byte unit as a partial block. */
293 if (nbytes) {
294 /* decrypt */
295 aes_ccm_inc(C);
296 aes_enc(C->enc, C->in, C->out, C->nr);
297 xor(q, C->out, p, nbytes);
298
299 /* authenticate */
300 xor(C->auth, C->auth, q, nbytes);
301
302 C->i = nbytes;
303 }
304 }
305
306 void
307 aes_ccm_tag(struct aes_ccm *C, void *out)
308 {
309
310 KASSERTMSG(C->mleft == 0,
311 "message too short: promised %zu bytes, processed %zu",
312 C->mlen, C->mlen - C->mleft);
313
314 /* Zero-pad and munch up a partial block, if any. */
315 if (C->i)
316 aes_enc(C->enc, C->auth, C->auth, C->nr);
317
318 /* Zero the counter and generate a pad for the tag. */
319 aes_ccm_zero_ctr(C);
320 aes_enc(C->enc, C->in, C->out, C->nr);
321
322 /* Copy out as many bytes as requested. */
323 xor(out, C->out, C->auth, C->M);
324
325 C->i = ~0u; /* paranoia: prevent future misuse */
326 }
327
328 int
329 aes_ccm_verify(struct aes_ccm *C, const void *tag)
330 {
331 uint8_t expected[16];
332 int result;
333
334 aes_ccm_tag(C, expected);
335 result = consttime_memequal(tag, expected, C->M);
336 explicit_memset(expected, 0, sizeof expected);
337
338 return result;
339 }
340
341 /* RFC 3610, 8 */
342
343 static const uint8_t keyC[16] = {
344 0xc0,0xc1,0xc2,0xc3, 0xc4,0xc5,0xc6,0xc7,
345 0xc8,0xc9,0xca,0xcb, 0xcc,0xcd,0xce,0xcf,
346 };
347
348 static const uint8_t keyD[16] = {
349 0xd7,0x82,0x8d,0x13, 0xb2,0xb0,0xbd,0xc3,
350 0x25,0xa7,0x62,0x36, 0xdf,0x93,0xcc,0x6b,
351 };
352
353 static const uint8_t ptxt_seq[] = {
354 0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07,
355 0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
356 0x10,0x11,0x12,0x13, 0x14,0x15,0x16,0x17,
357 0x18,0x19,0x1a,0x1b, 0x1c,0x1d,0x1e,0x1f,
358 0x20,
359 };
360
361 static const uint8_t ptxt_rand[] = {
362 0x6e,0x37,0xa6,0xef, 0x54,0x6d,0x95,0x5d,
363 0x34,0xab,0x60,0x59, 0xab,0xf2,0x1c,0x0b,
364 0x02,0xfe,0xb8,0x8f, 0x85,0x6d,0xf4,0xa3,
365 0x73,0x81,0xbc,0xe3, 0xcc,0x12,0x85,0x17,
366 0xd4,
367 };
368
369 static const struct {
370 const uint8_t *key;
371 size_t noncelen;
372 const uint8_t nonce[13];
373 size_t adlen;
374 const uint8_t *ad;
375 size_t mlen;
376 const uint8_t *ptxt;
377 unsigned M;
378 const uint8_t tag[16];
379 const uint8_t *ctxt;
380 } T[] = {
381 [0] = { /* Packet Vector #1, p. 11 */
382 .key = keyC,
383 .nonce = {
384 0x00,0x00,0x00,0x03, 0x02,0x01,0x00,0xa0,
385 0xa1,0xa2,0xa3,0xa4, 0xa5,
386 },
387 .adlen = 8,
388 .ad = ptxt_seq,
389 .mlen = 23,
390 .ptxt = ptxt_seq + 8,
391 .M = 8,
392 .tag = {0x17,0xe8,0xd1,0x2c,0xfd, 0xf9,0x26,0xe0},
393 .ctxt = (const uint8_t[23]) {
394 0x58,0x8c,0x97,0x9a, 0x61,0xc6,0x63,0xd2,
395 0xf0,0x66,0xd0,0xc2, 0xc0,0xf9,0x89,0x80,
396 0x6d,0x5f,0x6b,0x61, 0xda,0xc3,0x84,
397 },
398 },
399 [1] = { /* Packet Vector #2, p. 11 */
400 .key = keyC,
401 .nonce = {
402 0x00,0x00,0x00,0x04, 0x03,0x02,0x01,0xa0,
403 0xa1,0xa2,0xa3,0xa4, 0xa5,
404 },
405 .adlen = 8,
406 .ad = ptxt_seq,
407 .mlen = 24,
408 .ptxt = ptxt_seq + 8,
409 .M = 8,
410 .tag = {0xa0,0x91,0xd5,0x6e, 0x10,0x40,0x09,0x16},
411 .ctxt = (const uint8_t[24]) {
412 0x72,0xc9,0x1a,0x36, 0xe1,0x35,0xf8,0xcf,
413 0x29,0x1c,0xa8,0x94, 0x08,0x5c,0x87,0xe3,
414 0xcc,0x15,0xc4,0x39, 0xc9,0xe4,0x3a,0x3b,
415 },
416 },
417 [2] = { /* Packet Vector #3, p. 12 */
418 .key = keyC,
419 .nonce = {
420 0x00,0x00,0x00,0x05, 0x04,0x03,0x02,0xa0,
421 0xa1,0xa2,0xa3,0xa4, 0xa5,
422 },
423 .adlen = 8,
424 .ad = ptxt_seq,
425 .mlen = 25,
426 .ptxt = ptxt_seq + 8,
427 .M = 8,
428 .tag = {0x4a,0xda,0xa7,0x6f, 0xbd,0x9f,0xb0,0xc5},
429 .ctxt = (const uint8_t[25]) {
430 0x51,0xb1,0xe5,0xf4, 0x4a,0x19,0x7d,0x1d,
431 0xa4,0x6b,0x0f,0x8e, 0x2d,0x28,0x2a,0xe8,
432 0x71,0xe8,0x38,0xbb, 0x64,0xda,0x85,0x96,
433 0x57,
434 },
435 },
436 [3] = { /* Packet Vector #4, p. 13 */
437 .key = keyC,
438 .nonce = {
439 0x00,0x00,0x00,0x06, 0x05,0x04,0x03,0xa0,
440 0xa1,0xa2,0xa3,0xa4, 0xa5,
441 },
442 .adlen = 12,
443 .ad = ptxt_seq,
444 .mlen = 19,
445 .ptxt = ptxt_seq + 12,
446 .M = 8,
447 .tag = {0x96,0xc8,0x61,0xb9, 0xc9,0xe6,0x1e,0xf1},
448 .ctxt = (const uint8_t[19]) {
449 0xa2,0x8c,0x68,0x65, 0x93,0x9a,0x9a,0x79,
450 0xfa,0xaa,0x5c,0x4c, 0x2a,0x9d,0x4a,0x91,
451 0xcd,0xac,0x8c,
452 },
453 },
454 [4] = { /* Packet Vector #5, p. 13 */
455 .key = keyC,
456 .nonce = {
457 0x00,0x00,0x00,0x07, 0x06,0x05,0x04,0xa0,
458 0xa1,0xa2,0xa3,0xa4, 0xa5,
459 },
460 .adlen = 12,
461 .ad = ptxt_seq,
462 .mlen = 20,
463 .ptxt = ptxt_seq + 12,
464 .M = 8,
465 .tag = {0x51,0xe8,0x3f,0x07, 0x7d,0x9c,0x2d,0x93},
466 .ctxt = (const uint8_t[20]) {
467 0xdc,0xf1,0xfb,0x7b, 0x5d,0x9e,0x23,0xfb,
468 0x9d,0x4e,0x13,0x12, 0x53,0x65,0x8a,0xd8,
469 0x6e,0xbd,0xca,0x3e,
470 },
471 },
472 [5] = { /* Packet Vector #6, p. 13 */
473 .key = keyC,
474 .nonce = {
475 0x00,0x00,0x00,0x08, 0x07,0x06,0x05,0xa0,
476 0xa1,0xa2,0xa3,0xa4, 0xa5,
477 },
478 .adlen = 12,
479 .ad = ptxt_seq,
480 .mlen = 21,
481 .ptxt = ptxt_seq + 12,
482 .M = 8,
483 .tag = {0x40,0x5a,0x04,0x43, 0xac,0x91,0xcb,0x94},
484 .ctxt = (const uint8_t[21]) {
485 0x6f,0xc1,0xb0,0x11, 0xf0,0x06,0x56,0x8b,
486 0x51,0x71,0xa4,0x2d, 0x95,0x3d,0x46,0x9b,
487 0x25,0x70,0xa4,0xbd, 0x87,
488 },
489 },
490 [6] = { /* Packet Vector #24 */
491 .key = keyD,
492 .nonce = {
493 0x00,0x8d,0x49,0x3b, 0x30,0xae,0x8b,0x3c,
494 0x96,0x96,0x76,0x6c, 0xfa,
495 },
496 .adlen = 12,
497 .ad = ptxt_rand,
498 .mlen = 21,
499 .ptxt = ptxt_rand + 12,
500 .M = 10,
501 .tag = {0x6d,0xce,0x9e,0x82, 0xef,0xa1,0x6d,0xa6, 0x20,0x59},
502 .ctxt = (const uint8_t[21]) {
503 0xf3,0x29,0x05,0xb8, 0x8a,0x64,0x1b,0x04,
504 0xb9,0xc9,0xff,0xb5, 0x8c,0xc3,0x90,0x90,
505 0x0f,0x3d,0xa1,0x2a, 0xb1,
506 },
507 },
508 };
509
510 int
511 aes_ccm_selftest(void)
512 {
513 const unsigned L = 2;
514 const unsigned noncelen = 13;
515 struct aesenc enc, *AE = &enc;
516 struct aes_ccm ccm, *C = &ccm;
517 uint8_t buf[33 + 2], *bufp = buf + 1;
518 uint8_t tag[16 + 2], *tagp = tag + 1;
519 unsigned i;
520 int result = 0;
521
522 bufp[-1] = bufp[33] = 0x1a;
523 tagp[-1] = tagp[16] = 0x53;
524
525 for (i = 0; i < __arraycount(T); i++) {
526 const unsigned nr = aes_setenckey128(AE, T[i].key);
527
528 /* encrypt and authenticate */
529 aes_ccm_init(C, nr, AE, L, T[i].M, T[i].nonce, noncelen,
530 T[i].ad, T[i].adlen, T[i].mlen);
531 aes_ccm_enc(C, T[i].ptxt, bufp, 1);
532 aes_ccm_enc(C, T[i].ptxt + 1, bufp + 1, 2);
533 aes_ccm_enc(C, T[i].ptxt + 3, bufp + 3, T[i].mlen - 4);
534 aes_ccm_enc(C, T[i].ptxt + T[i].mlen - 1,
535 bufp + T[i].mlen - 1, 1);
536 aes_ccm_tag(C, tagp);
537 if (memcmp(bufp, T[i].ctxt, T[i].mlen)) {
538 char name[32];
539 snprintf(name, sizeof name, "%s: ctxt %u", __func__,
540 i);
541 hexdump(printf, name, bufp, T[i].mlen);
542 result = -1;
543 }
544 if (memcmp(tagp, T[i].tag, T[i].M)) {
545 char name[32];
546 snprintf(name, sizeof name, "%s: tag %u", __func__, i);
547 hexdump(printf, name, tagp, T[i].M);
548 result = -1;
549 }
550
551 /* decrypt and verify */
552 aes_ccm_init(C, nr, AE, L, T[i].M, T[i].nonce, noncelen,
553 T[i].ad, T[i].adlen, T[i].mlen);
554 aes_ccm_dec(C, T[i].ctxt, bufp, 1);
555 aes_ccm_dec(C, T[i].ctxt + 1, bufp + 1, 2);
556 aes_ccm_dec(C, T[i].ctxt + 3, bufp + 3, T[i].mlen - 4);
557 aes_ccm_dec(C, T[i].ctxt + T[i].mlen - 1,
558 bufp + T[i].mlen - 1, 1);
559 if (!aes_ccm_verify(C, T[i].tag)) {
560 printf("%s: verify %u failed\n", __func__, i);
561 result = -1;
562 }
563 if (memcmp(bufp, T[i].ptxt, T[i].mlen)) {
564 char name[32];
565 snprintf(name, sizeof name, "%s: ptxt %u", __func__,
566 i);
567 hexdump(printf, name, bufp, T[i].mlen);
568 result = -1;
569 }
570
571 /* decrypt and verify with a bit flipped */
572 memcpy(tagp, T[i].tag, T[i].M);
573 tagp[0] ^= 0x80;
574 aes_ccm_init(C, nr, AE, L, T[i].M, T[i].nonce, noncelen,
575 T[i].ad, T[i].adlen, T[i].mlen);
576 aes_ccm_dec(C, T[i].ctxt, bufp, 1);
577 aes_ccm_dec(C, T[i].ctxt + 1, bufp + 1, 2);
578 aes_ccm_dec(C, T[i].ctxt + 3, bufp + 3, T[i].mlen - 4);
579 aes_ccm_dec(C, T[i].ctxt + T[i].mlen - 1,
580 bufp + T[i].mlen - 1, 1);
581 if (aes_ccm_verify(C, tagp)) {
582 printf("%s: forgery %u succeeded\n", __func__, i);
583 result = -1;
584 }
585 }
586
587 if (bufp[-1] != 0x1a || bufp[33] != 0x1a) {
588 printf("%s: buffer overrun\n", __func__);
589 result = -1;
590 }
591 if (tagp[-1] != 0x53 || tagp[16] != 0x53) {
592 printf("%s: tag overrun\n", __func__);
593 result = -1;
594 }
595
596 return result;
597 }
598
599 /* XXX provisional hack */
600 #include <sys/module.h>
601
602 MODULE(MODULE_CLASS_MISC, aes_ccm, NULL);
603
604 static int
605 aes_ccm_modcmd(modcmd_t cmd, void *opaque)
606 {
607
608 switch (cmd) {
609 case MODULE_CMD_INIT:
610 if (aes_ccm_selftest())
611 return EIO;
612 aprint_verbose("aes_ccm: self-test passed\n");
613 return 0;
614 case MODULE_CMD_FINI:
615 return 0;
616 default:
617 return ENOTTY;
618 }
619 }
620