3 * AES encrypt/decrypt wrapper functions used around Rijndael reference
6 * Copyright (C) 2010, Broadcom Corporation
9 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
10 * the contents of this file may not be disclosed to third parties, copied
11 * or duplicated in any form, in whole or in part, without the prior
12 * written permission of Broadcom Corporation.
14 * $Id: aes.c,v 1.34.10.1 2010-05-28 15:25:49 Exp $
21 #include <stddef.h> /* for size_t */
23 extern void bcopy(const void *src
, void *dst
, size_t len
);
24 extern int bcmp(const void *b1
, const void *b2
, size_t len
);
25 extern void bzero(void *b
, size_t len
);
27 #define bcopy(src, dst, len) memcpy((dst), (src), (len))
28 #define bcmp(b1, b2, len) memcmp((b1), (b2), (len))
29 #define bzero(b, len) memset((b), 0, (len))
31 #endif /* BCMDRIVER */
32 #include <bcmendian.h>
34 #include <proto/802.11.h>
35 #include <bcmcrypto/aes.h>
36 #include <bcmcrypto/rijndael-alg-fst.h>
41 #define dbg(args) printf args
44 pinter(const char *label
, const uint8
*A
, const size_t il
, const uint8
*R
)
48 for (k
= 0; k
< AES_BLOCK_SZ
; k
++)
51 for (k
= 0; k
< il
; k
++) {
53 if (!((k
+ 1) % AES_BLOCK_SZ
))
60 pres(const char *label
, const size_t len
, const uint8
*data
)
63 printf("%s\n", label
);
64 for (k
= 0; k
< len
; k
++) {
65 printf("%02x ", data
[k
]);
66 if (!((k
+ 1) % AES_BLOCK_SZ
))
72 #ifdef BCMAES_GENTABLE
74 ptable(const char *tablename
, const uint32
*table
)
77 printf("static const uint32 %s[256] = {\n ", tablename
);
78 for (k
= 0; k
< 256; k
++) {
79 printf("0x%08xU", table
[k
]);
90 #endif /* BCMAES_GENTABLE */
94 #define pinter(label, A, il, R)
95 #define pres(label, len, data)
96 #endif /* BCMAES_TEST */
103 /* Perform AES block encryption, including key schedule setup */
105 BCMROMFN(aes_encrypt
)(const size_t kl
, const uint8
*K
, const uint8
*ptxt
, uint8
*ctxt
)
107 uint32 rk
[4 * (AES_MAXROUNDS
+ 1)];
108 rijndaelKeySetupEnc(rk
, K
, (int)AES_KEY_BITLEN(kl
));
109 rijndaelEncrypt(rk
, (int)AES_ROUNDS(kl
), ptxt
, ctxt
);
112 /* Perform AES block decryption, including key schedule setup */
114 BCMROMFN(aes_decrypt
)(const size_t kl
, const uint8
*K
, const uint8
*ctxt
, uint8
*ptxt
)
116 uint32 rk
[4 * (AES_MAXROUNDS
+ 1)];
117 rijndaelKeySetupDec(rk
, K
, (int)AES_KEY_BITLEN(kl
));
118 rijndaelDecrypt(rk
, (int)AES_ROUNDS(kl
), ctxt
, ptxt
);
121 /* AES-CBC mode encryption algorithm
122 * - handle partial blocks with padding of type as above
123 * - assumes nonce is ready to use as-is (i.e. any
124 * encryption/randomization of nonce/IV is handled by the caller)
125 * - ptxt and ctxt can point to the same location
126 * - returns -1 on error or final length of output
131 BCMROMFN(aes_cbc_encrypt_pad
)(uint32
*rk
,
132 const size_t key_len
,
134 const size_t data_len
,
140 uint8 tmp
[AES_BLOCK_SZ
];
141 uint32 encrypt_len
= 0;
144 /* First block get XORed with nonce/IV */
145 const unsigned char *iv
= nonce
;
146 unsigned char *crypt_data
= ctxt
;
147 const unsigned char *plain_data
= ptxt
;
148 uint32 remaining
= (uint32
)data_len
;
150 while (remaining
>= AES_BLOCK_SZ
)
152 xor_128bit_block(iv
, plain_data
, tmp
);
153 aes_block_encrypt((int)AES_ROUNDS(key_len
), rk
, tmp
, crypt_data
);
154 remaining
-= AES_BLOCK_SZ
;
156 crypt_data
+= AES_BLOCK_SZ
;
157 plain_data
+= AES_BLOCK_SZ
;
158 encrypt_len
+= AES_BLOCK_SZ
;
161 if (padd_type
== NO_PADDING
)
165 for (j
= 0; j
< remaining
; j
++)
167 tmp
[j
] = plain_data
[j
] ^ iv
[j
];
172 case PAD_LEN_PADDING
:
173 for (j
= remaining
; j
< AES_BLOCK_SZ
; j
++) {
174 tmp
[j
] = (AES_BLOCK_SZ
- remaining
) ^ iv
[j
];
181 aes_block_encrypt((int)AES_ROUNDS(key_len
), rk
, tmp
, crypt_data
);
182 encrypt_len
+= AES_BLOCK_SZ
;
184 return (encrypt_len
);
187 /* AES-CBC mode encryption algorithm
188 * - does not handle partial blocks
189 * - assumes nonce is ready to use as-is (i.e. any
190 * encryption/randomization of nonce/IV is handled by the caller)
191 * - ptxt and ctxt can point to the same location
192 * - returns -1 on error
196 BCMROMFN(aes_cbc_encrypt
)(uint32
*rk
,
197 const size_t key_len
,
199 const size_t data_len
,
203 if (data_len
% AES_BLOCK_SZ
) return (-1);
204 if (data_len
< AES_BLOCK_SZ
) return (-1);
206 return aes_cbc_encrypt_pad(rk
, key_len
, nonce
, data_len
, ptxt
, ctxt
, NO_PADDING
);
210 /* AES-CBC mode decryption algorithm
211 * - handle partial plaintext blocks with padding
212 * - ptxt and ctxt can point to the same location
213 * - returns -1 on error
216 BCMROMFN(aes_cbc_decrypt_pad
)(uint32
*rk
,
217 const size_t key_len
,
219 const size_t data_len
,
224 uint8 tmp
[AES_BLOCK_SZ
];
225 uint32 remaining
= (uint32
)data_len
;
226 /* First block get XORed with nonce/IV */
227 const unsigned char *iv
= nonce
;
228 const unsigned char *crypt_data
= ctxt
;
229 uint32 plaintext_len
= 0;
230 unsigned char *plain_data
= ptxt
;
232 if (data_len
% AES_BLOCK_SZ
) return (-1);
233 if (data_len
< AES_BLOCK_SZ
) return (-1);
235 while (remaining
>= AES_BLOCK_SZ
)
237 aes_block_decrypt((int)AES_ROUNDS(key_len
), rk
, crypt_data
, tmp
);
238 xor_128bit_block(tmp
, iv
, plain_data
);
239 remaining
-= AES_BLOCK_SZ
;
241 crypt_data
+= AES_BLOCK_SZ
;
242 plain_data
+= AES_BLOCK_SZ
;
243 plaintext_len
+= AES_BLOCK_SZ
;
245 if (padd_type
== PAD_LEN_PADDING
)
246 plaintext_len
-= ptxt
[plaintext_len
-1];
247 return (plaintext_len
);
251 BCMROMFN(aes_cbc_decrypt
)(uint32
*rk
,
252 const size_t key_len
,
254 const size_t data_len
,
259 return aes_cbc_decrypt_pad(rk
, key_len
, nonce
, data_len
, ctxt
, ptxt
, NO_PADDING
);
264 /* AES-CTR mode encryption/decryption algorithm
265 * - max data_len is (AES_BLOCK_SZ * 2^16)
266 * - nonce must be AES_BLOCK_SZ bytes
267 * - assumes nonce is ready to use as-is (i.e. any
268 * encryption/randomization of nonce/IV is handled by the caller)
269 * - ptxt and ctxt can point to the same location
270 * - returns -1 on error
273 BCMROMFN(aes_ctr_crypt
)(unsigned int *rk
,
274 const size_t key_len
,
276 const size_t data_len
,
281 uint8 tmp
[AES_BLOCK_SZ
], ctr
[AES_BLOCK_SZ
];
283 if (data_len
> (AES_BLOCK_SZ
* AES_CTR_MAXBLOCKS
)) return (-1);
285 bcopy(nonce
, ctr
, AES_BLOCK_SZ
);
287 for (k
= 0; k
< (data_len
/ AES_BLOCK_SZ
); k
++) {
288 aes_block_encrypt((int)AES_ROUNDS(key_len
), rk
, ctr
, tmp
);
289 xor_128bit_block(ptxt
, tmp
, ctxt
);
290 ctr
[AES_BLOCK_SZ
-1]++;
291 if (!ctr
[AES_BLOCK_SZ
- 1]) ctr
[AES_BLOCK_SZ
- 2]++;
292 ptxt
+= AES_BLOCK_SZ
;
293 ctxt
+= AES_BLOCK_SZ
;
295 /* handle partial block */
296 if (data_len
%AES_BLOCK_SZ
) {
297 aes_block_encrypt((int)AES_ROUNDS(key_len
), rk
, ctr
, tmp
);
298 for (k
= 0; k
< (data_len
% AES_BLOCK_SZ
); k
++)
299 ctxt
[k
] = ptxt
[k
] ^ tmp
[k
];
306 /* AES-CCM mode MAC calculation
307 * - computes AES_CCM_AUTH_LEN MAC
308 * - nonce must be AES_CCM_NONCE_LEN bytes
309 * - returns -1 on error
313 BCMROMFN(aes_ccm_mac
)(unsigned int *rk
,
314 const size_t key_len
,
316 const size_t aad_len
,
318 const size_t data_len
,
322 uint8 B_0
[AES_BLOCK_SZ
], X
[AES_BLOCK_SZ
];
325 if (aad_len
> AES_CCM_AAD_MAX_LEN
) return (-1);
327 pres("aes_ccm_mac: nonce:", AES_CCM_NONCE_LEN
, nonce
);
328 pres("aes_ccm_mac: aad:", aad_len
, aad
);
329 pres("aes_ccm_mac: input:", data_len
, ptxt
);
331 /* B_0 = Flags || Nonce || l(m) */
332 B_0
[0] = AES_CCM_AUTH_FLAGS
;
334 B_0
[0] |= AES_CCM_AUTH_AAD_FLAG
;
335 bcopy(nonce
, &B_0
[1], AES_CCM_NONCE_LEN
);
336 B_0
[AES_BLOCK_SZ
- 2] = (uint8
)(data_len
>> 8) & 0xff;
337 B_0
[AES_BLOCK_SZ
- 1] = (uint8
)(data_len
& 0xff);
339 /* X_1 := E( K, B_0 ) */
340 pres("aes_ccm_mac: CBC IV in:", AES_BLOCK_SZ
, B_0
);
341 aes_block_encrypt((int)AES_ROUNDS(key_len
), rk
, B_0
, X
);
342 pres("aes_ccm_mac: CBC IV out:", AES_BLOCK_SZ
, X
);
344 /* X_i + 1 := E( K, X_i XOR B_i ) for i = 1, ..., n */
348 pres("aes_ccm_mac: aad:", aad_len
, aad
);
349 X
[0] ^= (aad_len
>> 8) & 0xff;
350 X
[1] ^= aad_len
& 0xff;
356 if (k
== AES_BLOCK_SZ
) {
357 pres("aes_ccm_mac: After xor (full block aad):", AES_BLOCK_SZ
, X
);
358 aes_block_encrypt((int)AES_ROUNDS(key_len
), rk
, X
, X
);
359 pres("aes_ccm_mac: After AES (full block aad):", AES_BLOCK_SZ
, X
);
363 /* handle partial last block */
364 if (k
% AES_BLOCK_SZ
) {
365 pres("aes_ccm_mac: After xor (partial block aad):", AES_BLOCK_SZ
, X
);
366 aes_block_encrypt((int)AES_ROUNDS(key_len
), rk
, X
, X
);
367 pres("aes_ccm_mac: After AES (partial block aad):", AES_BLOCK_SZ
, X
);
371 /* then the message data */
372 for (k
= 0; k
< (data_len
/ AES_BLOCK_SZ
); k
++) {
373 xor_128bit_block(X
, ptxt
, X
);
374 pres("aes_ccm_mac: After xor (full block data):", AES_BLOCK_SZ
, X
);
375 ptxt
+= AES_BLOCK_SZ
;
376 aes_block_encrypt((int)AES_ROUNDS(key_len
), rk
, X
, X
);
377 pres("aes_ccm_mac: After AES (full block data):", AES_BLOCK_SZ
, X
);
379 /* last block may be partial, padding is implicit in this xor */
380 for (k
= 0; k
< (data_len
% AES_BLOCK_SZ
); k
++)
382 if (data_len
% AES_BLOCK_SZ
) {
383 pres("aes_ccm_mac: After xor (final block data):", AES_BLOCK_SZ
, X
);
384 aes_block_encrypt((int)AES_ROUNDS(key_len
), rk
, X
, X
);
385 pres("aes_ccm_mac: After AES (final block data):", AES_BLOCK_SZ
, X
);
388 /* T := first-M-bytes( X_n+1 ) */
389 bcopy(X
, mac
, AES_CCM_AUTH_LEN
);
390 pres("aes_ccm_mac: MAC:", AES_CCM_AUTH_LEN
, mac
);
395 /* AES-CCM mode encryption
396 * - computes AES_CCM_AUTH_LEN MAC and then encrypts ptxt and MAC
397 * - nonce must be AES_CCM_NONCE_LEN bytes
398 * - ctxt must have sufficient tailroom for CCM MAC
399 * - ptxt and ctxt can point to the same location
400 * - returns -1 on error
404 BCMROMFN(aes_ccm_encrypt
)(unsigned int *rk
,
405 const size_t key_len
,
407 const size_t aad_len
,
409 const size_t data_len
,
414 uint8 A
[AES_BLOCK_SZ
], X
[AES_BLOCK_SZ
];
416 /* initialize counter */
417 A
[0] = AES_CCM_CRYPT_FLAGS
;
418 bcopy(nonce
, &A
[1], AES_CCM_NONCE_LEN
);
419 A
[AES_BLOCK_SZ
-2] = 0;
420 A
[AES_BLOCK_SZ
-1] = 0;
421 pres("aes_ccm_encrypt: initial counter:", AES_BLOCK_SZ
, A
);
423 /* calculate and encrypt MAC */
424 if (aes_ccm_mac(rk
, key_len
, nonce
, aad_len
, aad
, data_len
, ptxt
, X
))
426 pres("aes_ccm_encrypt: MAC:", AES_CCM_AUTH_LEN
, X
);
427 if (aes_ctr_crypt(rk
, key_len
, A
, AES_CCM_AUTH_LEN
, X
, X
))
429 pres("aes_ccm_encrypt: encrypted MAC:", AES_CCM_AUTH_LEN
, X
);
430 bcopy(X
, mac
, AES_CCM_AUTH_LEN
);
433 A
[AES_BLOCK_SZ
- 1] = 1;
434 if (aes_ctr_crypt(rk
, key_len
, A
, data_len
, ptxt
, ctxt
))
436 pres("aes_ccm_encrypt: encrypted data:", data_len
, ctxt
);
441 /* AES-CCM mode decryption
442 * - decrypts ctxt, then computes AES_CCM_AUTH_LEN MAC and checks it against
444 * - the decrypted MAC is included in ptxt
445 * - nonce must be AES_CCM_NONCE_LEN bytes
446 * - ptxt and ctxt can point to the same location
447 * - returns -1 on error
451 BCMROMFN(aes_ccm_decrypt
)(unsigned int *rk
,
452 const size_t key_len
,
454 const size_t aad_len
,
456 const size_t data_len
,
460 uint8 A
[AES_BLOCK_SZ
], X
[AES_BLOCK_SZ
];
462 /* initialize counter */
463 A
[0] = AES_CCM_CRYPT_FLAGS
;
464 bcopy(nonce
, &A
[1], AES_CCM_NONCE_LEN
);
465 A
[AES_BLOCK_SZ
- 2] = 0;
466 A
[AES_BLOCK_SZ
- 1] = 1;
467 pres("aes_ccm_decrypt: initial counter:", AES_BLOCK_SZ
, A
);
470 if (aes_ctr_crypt(rk
, key_len
, A
, data_len
-AES_CCM_AUTH_LEN
, ctxt
, ptxt
))
472 pres("aes_ccm_decrypt: decrypted data:", data_len
-AES_CCM_AUTH_LEN
, ptxt
);
475 A
[AES_BLOCK_SZ
- 2] = 0;
476 A
[AES_BLOCK_SZ
- 1] = 0;
477 if (aes_ctr_crypt(rk
, key_len
, A
, AES_CCM_AUTH_LEN
,
478 ctxt
+data_len
-AES_CCM_AUTH_LEN
, ptxt
+ data_len
- AES_CCM_AUTH_LEN
))
480 pres("aes_ccm_decrypt: decrypted MAC:", AES_CCM_AUTH_LEN
,
481 ptxt
+ data_len
- AES_CCM_AUTH_LEN
);
484 if (aes_ccm_mac(rk
, key_len
, nonce
, aad_len
, aad
,
485 data_len
- AES_CCM_AUTH_LEN
, ptxt
, X
))
487 pres("aes_ccm_decrypt: MAC:", AES_CCM_AUTH_LEN
, X
);
488 if (bcmp(X
, ptxt
+ data_len
- AES_CCM_AUTH_LEN
, AES_CCM_AUTH_LEN
) != 0)
494 /* AES-CCMP mode encryption algorithm
495 * - packet buffer should be an 802.11 MPDU, starting with Frame Control,
496 * and including the CCMP extended IV
497 * - encrypts in-place
498 * - packet buffer must have sufficient tailroom for CCMP MAC
499 * - returns -1 on error
504 BCMROMFN(aes_ccmp_encrypt
)(unsigned int *rk
,
505 const size_t key_len
,
506 const size_t data_len
,
509 uint8 nonce_1st_byte
)
511 uint8 nonce
[AES_CCMP_NONCE_LEN
], aad
[AES_CCMP_AAD_MAX_LEN
];
512 struct dot11_header
*h
= (struct dot11_header
*) p
;
516 aes_ccmp_cal_params(h
, legacy
, nonce_1st_byte
, nonce
, aad
, &la
, &lh
);
518 pres("aes_ccmp_encrypt: aad:", la
, aad
);
522 * B3..Bn, n = floor((l(m)+(AES_BLOCK_SZ-1))/AES_BLOCK_SZ) + 2
526 status
= aes_ccm_encrypt(rk
, key_len
, nonce
, la
, aad
,
527 data_len
- lh
, p
+ lh
, p
+ lh
, p
+ data_len
);
529 pres("aes_ccmp_encrypt: Encrypted packet with MAC:",
530 data_len
+AES_CCMP_AUTH_LEN
, p
);
532 if (status
) return (AES_CCMP_ENCRYPT_ERROR
);
533 else return (AES_CCMP_ENCRYPT_SUCCESS
);
537 BCMROMFN(aes_ccmp_decrypt
)(unsigned int *rk
,
538 const size_t key_len
,
539 const size_t data_len
,
542 uint8 nonce_1st_byte
)
544 uint8 nonce
[AES_CCMP_NONCE_LEN
], aad
[AES_CCMP_AAD_MAX_LEN
];
545 struct dot11_header
*h
= (struct dot11_header
*)p
;
549 aes_ccmp_cal_params(h
, legacy
, nonce_1st_byte
, nonce
, aad
, &la
, &lh
);
551 pres("aes_ccmp_decrypt: aad:", la
, aad
);
555 * B3..Bn, n = floor((l(m)+(AES_BLOCK_SZ-1))/AES_BLOCK_SZ) + 2
559 status
= aes_ccm_decrypt(rk
, key_len
, nonce
, la
, aad
,
560 data_len
- lh
, p
+ lh
, p
+ lh
);
562 pres("aes_ccmp_decrypt: Decrypted packet with MAC:", data_len
, p
);
564 if (status
) return (AES_CCMP_DECRYPT_MIC_FAIL
);
565 else return (AES_CCMP_DECRYPT_SUCCESS
);
569 BCMROMFN(aes_ccmp_cal_params
)(struct dot11_header
*h
, bool legacy
,
570 uint8 nonce_1st_byte
, uint8
*nonce
, uint8
*aad
, uint
*la
, uint
*lh
)
578 bzero(nonce
, AES_CCMP_NONCE_LEN
);
579 bzero(aad
, AES_CCMP_AAD_MAX_LEN
);
582 subtype
= (fc
& FC_SUBTYPE_MASK
) >> FC_SUBTYPE_SHIFT
;
583 wds
= ((fc
& (FC_TODS
| FC_FROMDS
)) == (FC_TODS
| FC_FROMDS
));
584 /* all QoS subtypes have the FC_SUBTYPE_QOS_DATA bit set */
585 qos
= (FC_TYPE(fc
) == FC_TYPE_DATA
) && (subtype
& FC_SUBTYPE_QOS_DATA
);
588 qc
= ltoh16(*((uint16
*)((uchar
*)h
+
589 (wds
? DOT11_A4_HDR_LEN
: DOT11_A3_HDR_LEN
))));
593 dbg(("aes_ccmp_cal_params: A4 present\n"));
594 addlen
+= ETHER_ADDR_LEN
;
597 dbg(("aes_ccmp_cal_params: QC present\n"));
598 addlen
+= DOT11_QOS_LEN
;
601 /* length of MPDU header, including IV */
602 *lh
= DOT11_A3_HDR_LEN
+ DOT11_IV_AES_CCM_LEN
+ addlen
;
604 *la
= AES_CCMP_AAD_MIN_LEN
+ addlen
;
606 iv_data
= (uint8
*)h
+ DOT11_A3_HDR_LEN
+ addlen
;
608 *nonce
++ = nonce_1st_byte
;
610 bcopy((uchar
*)&h
->a2
, nonce
, ETHER_ADDR_LEN
);
611 nonce
+= ETHER_ADDR_LEN
;
614 *nonce
++ = iv_data
[7];
616 *nonce
++ = iv_data
[6];
618 *nonce
++ = iv_data
[5];
620 *nonce
++ = iv_data
[4];
622 *nonce
++ = iv_data
[1];
624 *nonce
++ = iv_data
[0];
626 pres("aes_ccmp_cal_params: nonce:", AES_CCM_NONCE_LEN
, nonce
- AES_CCM_NONCE_LEN
);
628 /* B1..B2 = l(aad) || aad || pad(aad) */
629 /* aad: maskedFC || A1 || A2 || A3 || maskedSC || A4 || maskedQC */
633 /* For a management frame, don't mask the the subtype bits */
634 if (nonce_1st_byte
& AES_CCMP_NF_MANAGEMENT
)
635 fc
&= (FC_SUBTYPE_MASK
| AES_CCMP_FC_MASK
);
638 fc
&= AES_CCMP_FC_MASK
;
640 /* 802.11i Draft 3 inconsistencies:
641 * Clause 8.3.4.4.3: "FC Â MPDU Frame Control field, with Retry bit masked
642 * to zero." (8.3.4.4.3).
643 * Figure 29: "FC Â MPDU Frame Control field, with Retry, MoreData, CF-ACK,
644 * CF-POLL bits masked to zero."
645 * F.10.4.1: "FC Â MPDU Frame Control field, with Retry, MoreData,
646 * PwrMgmt bits masked to zero."
649 /* Our implementation: match 8.3.4.4.3 */
650 fc
&= AES_CCMP_LEGACY_FC_MASK
;
652 *aad
++ = (uint8
)(fc
& 0xff);
653 *aad
++ = (uint8
)((fc
>> 8) & 0xff);
655 bcopy((uchar
*)&h
->a1
, aad
, 3*ETHER_ADDR_LEN
);
656 aad
+= 3*ETHER_ADDR_LEN
;
658 seq
= ltoh16(h
->seq
);
660 seq
&= AES_CCMP_SEQ_MASK
;
662 seq
&= AES_CCMP_LEGACY_SEQ_MASK
;
665 *aad
++ = (uint8
)(seq
& 0xff);
666 *aad
++ = (uint8
)((seq
>> 8) & 0xff);
669 bcopy((uchar
*)&h
->a4
, aad
, ETHER_ADDR_LEN
);
670 aad
+= ETHER_ADDR_LEN
;
674 /* 802.11i Draft 7.0 inconsistencies:
675 * Clause 8.3.3.3.2: "QC Â The Quality of Service Control, a
676 * two-octet field that includes the MSDU priority, reserved
678 * I.7.4: TID portion of QoS
681 /* Our implementation: match the test vectors */
682 qc
&= AES_CCMP_QOS_MASK
;
683 *aad
++ = (uint8
)(qc
& 0xff);
684 *aad
++ = (uint8
)((qc
>> 8) & 0xff);
686 /* 802.11i Draft 3.0 inconsistencies: */
687 /* Clause 8.3.4.4.3: "QC Â The QoS Control, if present." */
688 /* Figure 30: "QC Â The QoS TC from QoS Control, if present." */
689 /* F.10.4.1: "QC Â The QoS TC from QoS Control, if present." */
691 /* Our implementation: Match clause 8.3.4.4.3 */
692 qc
&= AES_CCMP_LEGACY_QOS_MASK
;
693 *aad
++ = (uint8
)(qc
& 0xff);
694 *aad
++ = (uint8
)((qc
>> 8) & 0xff);
700 /* 128-bit long string of zeros */
701 static uint8 Z128
[] = {
702 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
703 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
706 /* CMAC Subkey generation polynomial for 128-bit blocks */
707 static uint8 R128
[] = {
708 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
709 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87
712 /* AES-CMAC subkey generation
713 * - computes subkeys K1 and K2 of length AES_BLOCK_SZ
716 aes_cmac_gen_subkeys(const size_t kl
, const uint8
*K
, uint8
*K1
, uint8
*K2
)
718 uint8 L
[AES_BLOCK_SZ
];
723 aes_encrypt(kl
, K
, Z128
, L
);
725 pres("CIPHK", AES_BLOCK_SZ
, L
);
727 /* If MSB1(L) = 0, then K1 = L << 1 */
728 /* Else K1 = (L << 1) ⊕ Rb */
730 for (i
= AES_BLOCK_SZ
-1; i
>= 0; i
--) {
733 high
= (L
[i
] & 0x80) >> 7;
735 if ((L
[0] & 0x80) != 0) xor_128bit_block(K1
, R128
, K1
);
736 pres("K1", AES_BLOCK_SZ
, K1
);
738 /* If MSB1(K1) = 0, then K2 = K1 << 1 */
739 /* Else K2 = (K1 << 1) ⊕ Rb */
741 for (i
= AES_BLOCK_SZ
-1; i
>= 0; i
--) {
744 high
= (K1
[i
] & 0x80) >> 7;
746 if ((K1
[0] & 0x80) != 0) xor_128bit_block(K2
, R128
, K2
);
747 pres("K2", AES_BLOCK_SZ
, K2
);
752 /* AES-CMAC mode calculation
753 * - computes AES_CMAC_AUTH_LEN MAC
754 * - operates on complete bytes only (i.e. data_len is in bytes)
758 aes_cmac(const size_t key_len
, const uint8
* K
,
759 const uint8
*K1
, const uint8
*K2
,
760 const size_t data_len
,
765 uint8 Mn
[AES_BLOCK_SZ
], tmp
[AES_BLOCK_SZ
], C
[AES_BLOCK_SZ
];
766 uint32 rk
[4 * (AES_MAXROUNDS
+ 1)];
768 /* If Mlen = 0, let n = 1; else, let n = ⎡Mlen/b⎤ */
772 n
= (data_len
+ AES_BLOCK_SZ
- 1)/AES_BLOCK_SZ
;
774 /* Let M1, M2, ... , Mn-1, Mn* denote the unique sequence of bit
775 strings such that M = M1 || M2 || ... || Mn-1 || Mn*, where M1,
776 M2,..., Mn-1 are complete blocks. If Mn* is a complete block, let
777 Mn = K1 ⊕ Mn*; else, let Mn = K2 ⊕ (Mn*||10j), where j = nb-Mlen-1
780 if (data_len
== (n
* AES_BLOCK_SZ
)) {
781 /* Mn* is a complete block */
782 xor_128bit_block(K1
, &(ptxt
[(n
-1)*AES_BLOCK_SZ
]), Mn
);
784 /* Mn* is a partial block, pad with 0s and use K2 */
785 pblen
= data_len
- ((n
-1)*AES_BLOCK_SZ
);
786 for (i
= 0; i
< pblen
; i
++) Mn
[i
] = ptxt
[((n
-1)*AES_BLOCK_SZ
) + i
];
788 for (i
= pblen
+1; i
< AES_BLOCK_SZ
; i
++) Mn
[i
] = 0;
789 xor_128bit_block(K2
, Mn
, Mn
);
793 bzero(C
, AES_BLOCK_SZ
);
795 /* For i = 1 to n, let Ci = CIPHK(Ci-1 ⊕ Mi) */
796 rijndaelKeySetupEnc(rk
, K
, (int)AES_KEY_BITLEN(key_len
));
797 for (i
= 1; i
< n
; i
++) {
798 xor_128bit_block(C
, &(ptxt
[(i
-1)*AES_BLOCK_SZ
]), tmp
);
799 aes_block_encrypt((int)AES_ROUNDS(key_len
), rk
, tmp
, C
);
801 xor_128bit_block(C
, Mn
, tmp
);
802 aes_block_encrypt((int)AES_ROUNDS(key_len
), rk
, tmp
, C
);
804 /* Let T = MSBTlen(Cn) */
805 bcopy(C
, mac
, AES_CMAC_AUTH_LEN
);
812 aes_cmac_calc(const uint8
*data
, const size_t data_length
, const uint8
*mic_key
,
813 const size_t key_len
, uint8
*mic
)
815 uint8 K1
[AES_BLOCK_SZ
], K2
[AES_BLOCK_SZ
];
817 aes_cmac_gen_subkeys(key_len
, mic_key
, K1
, K2
);
818 aes_cmac(key_len
, mic_key
, K1
, K2
, data_length
, data
, mic
);
822 #ifdef BCMAES_GENTABLE
823 /* AES table expansion for rijndael-alg-fst.c
824 * - can compute all 10 tables needed by rijndael-alg-fst.c
825 * - only stores table entries for non-NULL entries in "at" structure, so
826 * can be used to generate a subset of the tables if only some are needed
829 aes_gen_tables(const uint8
*S
, const uint8
*Si
, aes_tables_t at
)
833 uint8 si2
, si4
, si8
, si9
, sib
, sid
, sie
;
834 uint32 Te0tmp
, Td0tmp
;
836 for (k
= 0; k
< AES_SBOX_ENTRIES
; k
++) {
859 sid
= si8
^ si4
^ Si
[k
];
862 sie
= si8
^ si4
^ si2
;
864 Te0tmp
= (s2
<< 24) | (S
[k
] << 16) | (S
[k
] << 8) | s3
;
868 at
.Te1
[k
] = ROTATE(Te0tmp
, 24);
870 at
.Te2
[k
] = ROTATE(Te0tmp
, 16);
872 at
.Te3
[k
] = ROTATE(Te0tmp
, 8);
874 at
.Te4
[k
] = (S
[k
] << 24) | (S
[k
] << 16) | (S
[k
] << 8) | S
[k
];
876 Td0tmp
= (sie
<< 24) | (si9
<< 16) | (sid
<< 8) | sib
;
880 at
.Td1
[k
] = ROTATE(Td0tmp
, 24);
882 at
.Td2
[k
] = ROTATE(Td0tmp
, 16);
884 at
.Td3
[k
] = ROTATE(Td0tmp
, 8);
886 at
.Td4
[k
] = (Si
[k
] << 24) | (Si
[k
] << 16) | (Si
[k
] << 8) | Si
[k
];
889 #endif /* BCMAES_GENTABLE */
892 #include "aes_vectors.h"
895 get_nonce_1st_byte(struct dot11_header
*h
)
903 subtype
= (fc
& FC_SUBTYPE_MASK
) >> FC_SUBTYPE_SHIFT
;
904 wds
= ((fc
& (FC_TODS
| FC_FROMDS
)) == (FC_TODS
| FC_FROMDS
));
905 /* all QoS subtypes have the FC_SUBTYPE_QOS_DATA bit set */
906 qos
= (FC_TYPE(fc
) == FC_TYPE_DATA
) && (subtype
& FC_SUBTYPE_QOS_DATA
);
909 qc
= ltoh16(*((uint16
*)((uchar
*)h
+
910 (wds
? DOT11_A4_HDR_LEN
: DOT11_A3_HDR_LEN
))));
913 /* nonce = priority octet || A2 || PN, !legacy */
914 return (uint8
)(QOS_TID(qc
) & 0x0f);
917 int main(int argc
, char **argv
)
919 uint8 output
[BUFSIZ
], input2
[BUFSIZ
];
920 int retv
, k
, fail
= 0;
921 uint32 rk
[4 * (AES_MAXROUNDS
+ 1)];
923 #ifdef BCMAES_GENTABLE
924 uint32 Te0test
[256], Te1test
[256], Te2test
[256], Te3test
[256], Te4test
[256];
925 uint32 Td0test
[256], Td1test
[256], Td2test
[256], Td3test
[256], Td4test
[256];
928 Te0test
, Te1test
, Te2test
, Te3test
, Te4test
,
929 Td0test
, Td1test
, Td2test
, Td3test
, Td4test
931 #endif /* BCMAES_GENTABLE */
934 dbg(("%s: AES-CBC\n", *argv
));
935 for (k
= 0; k
< NUM_CBC_VECTORS
; k
++) {
936 rijndaelKeySetupEnc(rk
, aes_cbc_vec
[k
].key
,
937 AES_KEY_BITLEN(aes_cbc_vec
[k
].kl
));
938 retv
= aes_cbc_encrypt(rk
, aes_cbc_vec
[k
].kl
,
939 aes_cbc_vec
[k
].nonce
, aes_cbc_vec
[k
].il
,
940 aes_cbc_vec
[k
].input
, output
);
941 pres("AES CBC Encrypt: ", aes_cbc_vec
[k
].il
, output
);
944 dbg(("%s: aes_cbc_encrypt failed\n", *argv
));
947 if (bcmp(output
, aes_cbc_vec
[k
].ref
, aes_cbc_vec
[k
].il
) != 0) {
948 dbg(("%s: aes_cbc_encrypt failed\n", *argv
));
952 rijndaelKeySetupDec(rk
, aes_cbc_vec
[k
].key
,
953 AES_KEY_BITLEN(aes_cbc_vec
[k
].kl
));
954 retv
= aes_cbc_decrypt(rk
, aes_cbc_vec
[k
].kl
,
955 aes_cbc_vec
[k
].nonce
, aes_cbc_vec
[k
].il
,
956 aes_cbc_vec
[k
].ref
, input2
);
957 pres("AES CBC Decrypt: ", aes_cbc_vec
[k
].il
, input2
);
960 dbg(("%s: aes_cbc_decrypt failed\n", *argv
));
963 if (bcmp(aes_cbc_vec
[k
].input
, input2
, aes_cbc_vec
[k
].il
) != 0) {
964 dbg(("%s: aes_cbc_decrypt failed\n", *argv
));
969 /* AES-CTR, full blocks */
970 dbg(("%s: AES-CTR, full blocks\n", *argv
));
971 for (k
= 0; k
< NUM_CTR_VECTORS
; k
++) {
972 rijndaelKeySetupEnc(rk
, aes_ctr_vec
[k
].key
,
973 AES_KEY_BITLEN(aes_ctr_vec
[k
].kl
));
974 retv
= aes_ctr_crypt(rk
, aes_ctr_vec
[k
].kl
,
975 aes_ctr_vec
[k
].nonce
, aes_ctr_vec
[k
].il
,
976 aes_ctr_vec
[k
].input
, output
);
977 pres("AES CTR Encrypt: ", aes_ctr_vec
[k
].il
, output
);
980 dbg(("%s: aes_ctr_crypt failed\n", *argv
));
983 if (bcmp(output
, aes_ctr_vec
[k
].ref
, aes_ctr_vec
[k
].il
) != 0) {
984 dbg(("%s: aes_ctr_crypt encrypt failed\n", *argv
));
988 rijndaelKeySetupEnc(rk
, aes_ctr_vec
[k
].key
,
989 AES_KEY_BITLEN(aes_ctr_vec
[k
].kl
));
990 retv
= aes_ctr_crypt(rk
, aes_ctr_vec
[k
].kl
,
991 aes_ctr_vec
[k
].nonce
, aes_ctr_vec
[k
].il
,
992 aes_ctr_vec
[k
].ref
, input2
);
993 pres("AES CTR Decrypt: ", aes_ctr_vec
[k
].il
, input2
);
996 dbg(("%s: aes_ctr_crypt failed\n", *argv
));
999 if (bcmp(aes_ctr_vec
[k
].input
, input2
, aes_ctr_vec
[k
].il
) != 0) {
1000 dbg(("%s: aes_ctr_crypt decrypt failed\n", *argv
));
1005 /* AES-CTR, one partial block */
1006 dbg(("%s: AES-CTR, one partial block\n", *argv
));
1007 for (k
= 0; k
< NUM_CTR_VECTORS
; k
++) {
1008 rijndaelKeySetupEnc(rk
, aes_ctr_vec
[k
].key
,
1009 AES_KEY_BITLEN(aes_ctr_vec
[k
].kl
));
1010 retv
= aes_ctr_crypt(rk
, aes_ctr_vec
[k
].kl
,
1011 aes_ctr_vec
[k
].nonce
, k
+1,
1012 aes_ctr_vec
[k
].input
, output
);
1013 pres("AES CTR Partial Block Encrypt: ", k
+1, output
);
1016 dbg(("%s: aes_ctr_crypt failed\n", *argv
));
1019 if (bcmp(output
, aes_ctr_vec
[k
].ref
, k
+ 1) != 0) {
1020 dbg(("%s: aes_ctr_crypt encrypt failed\n", *argv
));
1024 rijndaelKeySetupEnc(rk
, aes_ctr_vec
[k
].key
,
1025 AES_KEY_BITLEN(aes_ctr_vec
[k
].kl
));
1026 retv
= aes_ctr_crypt(rk
, aes_ctr_vec
[k
].kl
,
1027 aes_ctr_vec
[k
].nonce
, k
+ 1,
1028 aes_ctr_vec
[k
].ref
, input2
);
1029 pres("AES CTR Partial Block Decrypt: ", k
+ 1, input2
);
1032 dbg(("%s: aes_ctr_crypt failed\n", *argv
));
1035 if (bcmp(aes_ctr_vec
[k
].input
, input2
, k
+ 1) != 0) {
1036 dbg(("%s: aes_ctr_crypt decrypt failed\n", *argv
));
1041 /* AES-CTR, multi-block partial */
1042 dbg(("%s: AES-CTR, multi-block partial\n", *argv
));
1043 for (k
= 0; k
< NUM_CTR_VECTORS
; k
++) {
1044 rijndaelKeySetupEnc(rk
, aes_ctr_vec
[k
].key
,
1045 AES_KEY_BITLEN(aes_ctr_vec
[k
].kl
));
1046 retv
= aes_ctr_crypt(rk
, aes_ctr_vec
[k
].kl
,
1047 aes_ctr_vec
[k
].nonce
, AES_BLOCK_SZ
+ NUM_CTR_VECTORS
+k
+1,
1048 aes_ctr_vec
[k
].input
, output
);
1049 pres("AES CTR Partial Multi-Block Encrypt: ",
1050 AES_BLOCK_SZ
+ NUM_CTR_VECTORS
+ k
+ 1, output
);
1053 dbg(("%s: aes_ctr_crypt failed\n", *argv
));
1056 if (bcmp(output
, aes_ctr_vec
[k
].ref
, AES_BLOCK_SZ
+NUM_CTR_VECTORS
+ k
+ 1) != 0) {
1057 dbg(("%s: aes_ctr_crypt encrypt failed\n", *argv
));
1061 rijndaelKeySetupEnc(rk
, aes_ctr_vec
[k
].key
,
1062 AES_KEY_BITLEN(aes_ctr_vec
[k
].kl
));
1063 retv
= aes_ctr_crypt(rk
, aes_ctr_vec
[k
].kl
,
1064 aes_ctr_vec
[k
].nonce
, AES_BLOCK_SZ
+ NUM_CTR_VECTORS
+ k
+ 1,
1065 aes_ctr_vec
[k
].ref
, input2
);
1066 pres("AES CTR Partial Multi-Block Decrypt: ",
1067 AES_BLOCK_SZ
+ NUM_CTR_VECTORS
+ k
+ 1, input2
);
1070 dbg(("%s: aes_ctr_crypt failed\n", *argv
));
1073 if (bcmp(aes_ctr_vec
[k
].input
, input2
,
1074 AES_BLOCK_SZ
+ NUM_CTR_VECTORS
+ k
+ 1) != 0) {
1075 dbg(("%s: aes_ctr_crypt decrypt failed\n", *argv
));
1081 dbg(("%s: AES-CCM\n", *argv
));
1082 for (k
= 0; k
< NUM_CCM_VECTORS
; k
++) {
1083 rijndaelKeySetupEnc(rk
, aes_ccm_vec
[k
].key
,
1084 AES_KEY_BITLEN(aes_ccm_vec
[k
].kl
));
1085 retv
= aes_ccm_mac(rk
, aes_ccm_vec
[k
].kl
,
1086 aes_ccm_vec
[k
].nonce
, aes_ccm_vec
[k
].al
,
1087 aes_ccm_vec
[k
].aad
, aes_ccm_vec
[k
].il
,
1088 aes_ccm_vec
[k
].input
, output
);
1091 dbg(("%s: aes_ccm_mac failed\n", *argv
));
1094 if (bcmp(output
, aes_ccm_vec
[k
].mac
, AES_CCM_AUTH_LEN
) != 0) {
1095 dbg(("%s: aes_ccm_mac failed\n", *argv
));
1099 rijndaelKeySetupEnc(rk
, aes_ccm_vec
[k
].key
,
1100 AES_KEY_BITLEN(aes_ccm_vec
[k
].kl
));
1101 retv
= aes_ccm_encrypt(rk
, aes_ccm_vec
[k
].kl
,
1102 aes_ccm_vec
[k
].nonce
, aes_ccm_vec
[k
].al
,
1103 aes_ccm_vec
[k
].aad
, aes_ccm_vec
[k
].il
,
1104 aes_ccm_vec
[k
].input
, output
, &output
[aes_ccm_vec
[k
].il
]);
1105 pres("AES CCM Encrypt: ", aes_ccm_vec
[k
].il
+ AES_CCM_AUTH_LEN
, output
);
1108 dbg(("%s: aes_ccm_encrypt failed\n", *argv
));
1111 if (bcmp(output
, aes_ccm_vec
[k
].ref
, aes_ccm_vec
[k
].il
+ AES_CCM_AUTH_LEN
) != 0) {
1112 dbg(("%s: aes_ccm_encrypt failed\n", *argv
));
1116 rijndaelKeySetupEnc(rk
, aes_ccm_vec
[k
].key
,
1117 AES_KEY_BITLEN(aes_ccm_vec
[k
].kl
));
1118 retv
= aes_ccm_decrypt(rk
, aes_ccm_vec
[k
].kl
,
1119 aes_ccm_vec
[k
].nonce
, aes_ccm_vec
[k
].al
,
1120 aes_ccm_vec
[k
].aad
, aes_ccm_vec
[k
].il
+ AES_CCM_AUTH_LEN
,
1121 aes_ccm_vec
[k
].ref
, input2
);
1122 pres("AES CCM Decrypt: ", aes_ccm_vec
[k
].il
+ AES_CCM_AUTH_LEN
, input2
);
1125 dbg(("%s: aes_ccm_decrypt failed\n", *argv
));
1128 if (bcmp(aes_ccm_vec
[k
].input
, input2
, aes_ccm_vec
[k
].il
) != 0) {
1129 dbg(("%s: aes_ccm_decrypt failed\n", *argv
));
1135 dbg(("%s: AES-CCMP\n", *argv
));
1136 for (k
= 0; k
< NUM_CCMP_VECTORS
; k
++) {
1137 uint8 nonce_1st_byte
;
1138 dbg(("%s: AES-CCMP vector %d\n", *argv
, k
));
1139 rijndaelKeySetupEnc(rk
, aes_ccmp_vec
[k
].key
,
1140 AES_KEY_BITLEN(aes_ccmp_vec
[k
].kl
));
1141 bcopy(aes_ccmp_vec
[k
].input
, output
, aes_ccmp_vec
[k
].il
);
1142 nonce_1st_byte
= get_nonce_1st_byte((struct dot11_header
*)output
);
1143 retv
= aes_ccmp_encrypt(rk
, aes_ccmp_vec
[k
].kl
,
1144 aes_ccmp_vec
[k
].il
, output
,
1145 aes_ccmp_vec
[k
].flags
[2],
1149 dbg(("%s: aes_ccmp_encrypt of vector %d returned error\n", *argv
, k
));
1152 if (bcmp(output
, aes_ccmp_vec
[k
].ref
,
1153 aes_ccmp_vec
[k
].il
+AES_CCM_AUTH_LEN
) != 0) {
1154 dbg(("%s: aes_ccmp_encrypt of vector %d reference mismatch\n", *argv
, k
));
1158 rijndaelKeySetupEnc(rk
, aes_ccmp_vec
[k
].key
,
1159 AES_KEY_BITLEN(aes_ccmp_vec
[k
].kl
));
1160 bcopy(aes_ccmp_vec
[k
].ref
, output
, aes_ccmp_vec
[k
].il
+AES_CCM_AUTH_LEN
);
1161 nonce_1st_byte
= get_nonce_1st_byte((struct dot11_header
*)output
);
1162 retv
= aes_ccmp_decrypt(rk
, aes_ccmp_vec
[k
].kl
,
1163 aes_ccmp_vec
[k
].il
+AES_CCM_AUTH_LEN
, output
,
1164 aes_ccmp_vec
[k
].flags
[2],
1168 dbg(("%s: aes_ccmp_decrypt of vector %d returned error %d\n",
1172 if (bcmp(output
, aes_ccmp_vec
[k
].input
, aes_ccmp_vec
[k
].il
) != 0) {
1173 dbg(("%s: aes_ccmp_decrypt of vector %d reference mismatch\n", *argv
, k
));
1179 #ifdef BCMAES_GENTABLE
1180 aes_gen_tables(AES_Sbox
, AES_Inverse_Sbox
, at
);
1181 ptable("Te0", Te0test
);
1182 ptable("Te1", Te1test
);
1183 ptable("Te2", Te2test
);
1184 ptable("Te3", Te3test
);
1185 ptable("Te4", Te4test
);
1187 ptable("Td0", Td0test
);
1188 ptable("Td1", Td1test
);
1189 ptable("Td2", Td2test
);
1190 ptable("Td3", Td3test
);
1191 ptable("Td4", Td4test
);
1192 #endif /* BCMAES_GENTABLE */
1194 fprintf(stderr
, "%s: %s\n", *argv
, fail
? "FAILED" : "PASSED");
1198 #endif /* BCMAES_TEST */