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