3 * AES encrypt/decrypt wrapper functions used around Rijndael reference
6 * Copyright (C) 2012, 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 241182 2011-02-17 21:50:03Z $
23 #endif /* BCMDRIVER */
25 #include <bcmendian.h>
27 #include <proto/802.11.h>
28 #include <bcmcrypto/aes.h>
29 #include <bcmcrypto/rijndael-alg-fst.h>
34 #define dbg(args) printf args
37 pinter(const char *label
, const uint8
*A
, const size_t il
, const uint8
*R
)
41 for (k
= 0; k
< AES_BLOCK_SZ
; k
++)
44 for (k
= 0; k
< il
; k
++) {
46 if (!((k
+ 1) % AES_BLOCK_SZ
))
53 pres(const char *label
, const size_t len
, const uint8
*data
)
56 printf("%s\n", label
);
57 for (k
= 0; k
< len
; k
++) {
58 printf("%02x ", data
[k
]);
59 if (!((k
+ 1) % AES_BLOCK_SZ
))
65 #ifdef BCMAES_GENTABLE
67 ptable(const char *tablename
, const uint32
*table
)
70 printf("static const uint32 %s[256] = {\n ", tablename
);
71 for (k
= 0; k
< 256; k
++) {
72 printf("0x%08xU", table
[k
]);
83 #endif /* BCMAES_GENTABLE */
87 #define pinter(label, A, il, R)
88 #define pres(label, len, data)
89 #endif /* BCMAES_TEST */
96 /* Perform AES block encryption, including key schedule setup */
98 BCMROMFN(aes_encrypt
)(const size_t kl
, const uint8
*K
, const uint8
*ptxt
, uint8
*ctxt
)
100 uint32 rk
[4 * (AES_MAXROUNDS
+ 1)];
101 rijndaelKeySetupEnc(rk
, K
, (int)AES_KEY_BITLEN(kl
));
102 rijndaelEncrypt(rk
, (int)AES_ROUNDS(kl
), ptxt
, ctxt
);
105 /* Perform AES block decryption, including key schedule setup */
107 BCMROMFN(aes_decrypt
)(const size_t kl
, const uint8
*K
, const uint8
*ctxt
, uint8
*ptxt
)
109 uint32 rk
[4 * (AES_MAXROUNDS
+ 1)];
110 rijndaelKeySetupDec(rk
, K
, (int)AES_KEY_BITLEN(kl
));
111 rijndaelDecrypt(rk
, (int)AES_ROUNDS(kl
), ctxt
, ptxt
);
114 /* AES-CBC mode encryption algorithm
115 * - handle partial blocks with padding of type as above
116 * - assumes nonce is ready to use as-is (i.e. any
117 * encryption/randomization of nonce/IV is handled by the caller)
118 * - ptxt and ctxt can point to the same location
119 * - returns -1 on error or final length of output
124 BCMROMFN(aes_cbc_encrypt_pad
)(uint32
*rk
,
125 const size_t key_len
,
127 const size_t data_len
,
133 uint8 tmp
[AES_BLOCK_SZ
];
134 uint32 encrypt_len
= 0;
137 /* First block get XORed with nonce/IV */
138 const unsigned char *iv
= nonce
;
139 unsigned char *crypt_data
= ctxt
;
140 const unsigned char *plain_data
= ptxt
;
141 uint32 remaining
= (uint32
)data_len
;
143 while (remaining
>= AES_BLOCK_SZ
) {
144 xor_128bit_block(iv
, plain_data
, tmp
);
145 aes_block_encrypt((int)AES_ROUNDS(key_len
), rk
, tmp
, crypt_data
);
146 remaining
-= AES_BLOCK_SZ
;
148 crypt_data
+= AES_BLOCK_SZ
;
149 plain_data
+= AES_BLOCK_SZ
;
150 encrypt_len
+= AES_BLOCK_SZ
;
153 if (padd_type
== NO_PADDING
)
157 for (j
= 0; j
< remaining
; j
++) {
158 tmp
[j
] = plain_data
[j
] ^ iv
[j
];
162 case PAD_LEN_PADDING
:
163 for (j
= remaining
; j
< AES_BLOCK_SZ
; j
++) {
164 tmp
[j
] = (AES_BLOCK_SZ
- remaining
) ^ iv
[j
];
171 aes_block_encrypt((int)AES_ROUNDS(key_len
), rk
, tmp
, crypt_data
);
172 encrypt_len
+= AES_BLOCK_SZ
;
174 return (encrypt_len
);
177 /* AES-CBC mode encryption algorithm
178 * - does not handle partial blocks
179 * - assumes nonce is ready to use as-is (i.e. any
180 * encryption/randomization of nonce/IV is handled by the caller)
181 * - ptxt and ctxt can point to the same location
182 * - returns -1 on error
186 BCMROMFN(aes_cbc_encrypt
)(uint32
*rk
,
187 const size_t key_len
,
189 const size_t data_len
,
193 if (data_len
% AES_BLOCK_SZ
)
195 if (data_len
< AES_BLOCK_SZ
)
198 return aes_cbc_encrypt_pad(rk
, key_len
, nonce
, data_len
, ptxt
, ctxt
, NO_PADDING
);
202 /* AES-CBC mode decryption algorithm
203 * - handle partial plaintext blocks with padding
204 * - ptxt and ctxt can point to the same location
205 * - returns -1 on error
208 BCMROMFN(aes_cbc_decrypt_pad
)(uint32
*rk
,
209 const size_t key_len
,
211 const size_t data_len
,
216 uint8 tmp
[AES_BLOCK_SZ
];
217 uint32 remaining
= (uint32
)data_len
;
218 /* First block get XORed with nonce/IV */
219 const unsigned char *iv
= nonce
;
220 const unsigned char *crypt_data
= ctxt
;
221 uint32 plaintext_len
= 0;
222 unsigned char *plain_data
= ptxt
;
224 if (data_len
% AES_BLOCK_SZ
)
226 if (data_len
< AES_BLOCK_SZ
)
229 while (remaining
>= AES_BLOCK_SZ
) {
230 aes_block_decrypt((int)AES_ROUNDS(key_len
), rk
, crypt_data
, tmp
);
231 xor_128bit_block(tmp
, iv
, plain_data
);
232 remaining
-= AES_BLOCK_SZ
;
234 crypt_data
+= AES_BLOCK_SZ
;
235 plain_data
+= AES_BLOCK_SZ
;
236 plaintext_len
+= AES_BLOCK_SZ
;
238 if (padd_type
== PAD_LEN_PADDING
)
239 plaintext_len
-= ptxt
[plaintext_len
-1];
240 return (plaintext_len
);
244 BCMROMFN(aes_cbc_decrypt
)(uint32
*rk
,
245 const size_t key_len
,
247 const size_t data_len
,
251 return aes_cbc_decrypt_pad(rk
, key_len
, nonce
, data_len
, ctxt
, ptxt
, NO_PADDING
);
254 /* AES-CTR mode encryption/decryption algorithm
255 * - max data_len is (AES_BLOCK_SZ * 2^16)
256 * - nonce must be AES_BLOCK_SZ bytes
257 * - assumes nonce is ready to use as-is (i.e. any
258 * encryption/randomization of nonce/IV is handled by the caller)
259 * - ptxt and ctxt can point to the same location
260 * - returns -1 on error
263 BCMROMFN(aes_ctr_crypt
)(unsigned int *rk
,
264 const size_t key_len
,
266 const size_t data_len
,
271 uint8 tmp
[AES_BLOCK_SZ
], ctr
[AES_BLOCK_SZ
];
273 if (data_len
> (AES_BLOCK_SZ
* AES_CTR_MAXBLOCKS
)) return (-1);
275 memcpy(ctr
, nonce
, AES_BLOCK_SZ
);
277 for (k
= 0; k
< (data_len
/ AES_BLOCK_SZ
); k
++) {
278 aes_block_encrypt((int)AES_ROUNDS(key_len
), rk
, ctr
, tmp
);
279 xor_128bit_block(ptxt
, tmp
, ctxt
);
280 ctr
[AES_BLOCK_SZ
-1]++;
281 if (!ctr
[AES_BLOCK_SZ
- 1]) ctr
[AES_BLOCK_SZ
- 2]++;
282 ptxt
+= AES_BLOCK_SZ
;
283 ctxt
+= AES_BLOCK_SZ
;
285 /* handle partial block */
286 if (data_len
% AES_BLOCK_SZ
) {
287 aes_block_encrypt((int)AES_ROUNDS(key_len
), rk
, ctr
, tmp
);
288 for (k
= 0; k
< (data_len
% AES_BLOCK_SZ
); k
++)
289 ctxt
[k
] = ptxt
[k
] ^ tmp
[k
];
296 /* AES-CCM mode MAC calculation
297 * - computes AES_CCM_AUTH_LEN MAC
298 * - nonce must be AES_CCM_NONCE_LEN bytes
299 * - returns -1 on error
303 BCMROMFN(aes_ccm_mac
)(unsigned int *rk
,
304 const size_t key_len
,
306 const size_t aad_len
,
308 const size_t data_len
,
312 uint8 B_0
[AES_BLOCK_SZ
], X
[AES_BLOCK_SZ
];
315 if (aad_len
> AES_CCM_AAD_MAX_LEN
) return (-1);
317 pres("aes_ccm_mac: nonce:", AES_CCM_NONCE_LEN
, nonce
);
318 pres("aes_ccm_mac: aad:", aad_len
, aad
);
319 pres("aes_ccm_mac: input:", data_len
, ptxt
);
321 /* B_0 = Flags || Nonce || l(m) */
322 B_0
[0] = AES_CCM_AUTH_FLAGS
;
324 B_0
[0] |= AES_CCM_AUTH_AAD_FLAG
;
325 memcpy(&B_0
[1], nonce
, AES_CCM_NONCE_LEN
);
326 B_0
[AES_BLOCK_SZ
- 2] = (uint8
)(data_len
>> 8) & 0xff;
327 B_0
[AES_BLOCK_SZ
- 1] = (uint8
)(data_len
& 0xff);
329 /* X_1 := E( K, B_0 ) */
330 pres("aes_ccm_mac: CBC IV in:", AES_BLOCK_SZ
, B_0
);
331 aes_block_encrypt((int)AES_ROUNDS(key_len
), rk
, B_0
, X
);
332 pres("aes_ccm_mac: CBC IV out:", AES_BLOCK_SZ
, X
);
334 /* X_i + 1 := E( K, X_i XOR B_i ) for i = 1, ..., n */
338 pres("aes_ccm_mac: aad:", aad_len
, aad
);
339 X
[0] ^= (aad_len
>> 8) & 0xff;
340 X
[1] ^= aad_len
& 0xff;
346 if (k
== AES_BLOCK_SZ
) {
347 pres("aes_ccm_mac: After xor (full block aad):", AES_BLOCK_SZ
, X
);
348 aes_block_encrypt((int)AES_ROUNDS(key_len
), rk
, X
, X
);
349 pres("aes_ccm_mac: After AES (full block aad):", AES_BLOCK_SZ
, X
);
353 /* handle partial last block */
354 if (k
% AES_BLOCK_SZ
) {
355 pres("aes_ccm_mac: After xor (partial block aad):", AES_BLOCK_SZ
, X
);
356 aes_block_encrypt((int)AES_ROUNDS(key_len
), rk
, X
, X
);
357 pres("aes_ccm_mac: After AES (partial block aad):", AES_BLOCK_SZ
, X
);
361 /* then the message data */
362 for (k
= 0; k
< (data_len
/ AES_BLOCK_SZ
); k
++) {
363 xor_128bit_block(X
, ptxt
, X
);
364 pres("aes_ccm_mac: After xor (full block data):", AES_BLOCK_SZ
, X
);
365 ptxt
+= AES_BLOCK_SZ
;
366 aes_block_encrypt((int)AES_ROUNDS(key_len
), rk
, X
, X
);
367 pres("aes_ccm_mac: After AES (full block data):", AES_BLOCK_SZ
, X
);
369 /* last block may be partial, padding is implicit in this xor */
370 for (k
= 0; k
< (data_len
% AES_BLOCK_SZ
); k
++)
372 if (data_len
% AES_BLOCK_SZ
) {
373 pres("aes_ccm_mac: After xor (final block data):", AES_BLOCK_SZ
, X
);
374 aes_block_encrypt((int)AES_ROUNDS(key_len
), rk
, X
, X
);
375 pres("aes_ccm_mac: After AES (final block data):", AES_BLOCK_SZ
, X
);
378 /* T := first-M-bytes( X_n+1 ) */
379 memcpy(mac
, X
, AES_CCM_AUTH_LEN
);
380 pres("aes_ccm_mac: MAC:", AES_CCM_AUTH_LEN
, mac
);
385 /* AES-CCM mode encryption
386 * - computes AES_CCM_AUTH_LEN MAC and then encrypts ptxt and MAC
387 * - nonce must be AES_CCM_NONCE_LEN bytes
388 * - ctxt must have sufficient tailroom for CCM MAC
389 * - ptxt and ctxt can point to the same location
390 * - returns -1 on error
394 BCMROMFN(aes_ccm_encrypt
)(unsigned int *rk
,
395 const size_t key_len
,
397 const size_t aad_len
,
399 const size_t data_len
,
404 uint8 A
[AES_BLOCK_SZ
], X
[AES_BLOCK_SZ
];
406 /* initialize counter */
407 A
[0] = AES_CCM_CRYPT_FLAGS
;
408 memcpy(&A
[1], nonce
, AES_CCM_NONCE_LEN
);
409 A
[AES_BLOCK_SZ
-2] = 0;
410 A
[AES_BLOCK_SZ
-1] = 0;
411 pres("aes_ccm_encrypt: initial counter:", AES_BLOCK_SZ
, A
);
413 /* calculate and encrypt MAC */
414 if (aes_ccm_mac(rk
, key_len
, nonce
, aad_len
, aad
, data_len
, ptxt
, X
))
416 pres("aes_ccm_encrypt: MAC:", AES_CCM_AUTH_LEN
, X
);
417 if (aes_ctr_crypt(rk
, key_len
, A
, AES_CCM_AUTH_LEN
, X
, X
))
419 pres("aes_ccm_encrypt: encrypted MAC:", AES_CCM_AUTH_LEN
, X
);
420 memcpy(mac
, X
, AES_CCM_AUTH_LEN
);
423 A
[AES_BLOCK_SZ
- 1] = 1;
424 if (aes_ctr_crypt(rk
, key_len
, A
, data_len
, ptxt
, ctxt
))
426 pres("aes_ccm_encrypt: encrypted data:", data_len
, ctxt
);
431 /* AES-CCM mode decryption
432 * - decrypts ctxt, then computes AES_CCM_AUTH_LEN MAC and checks it against
434 * - the decrypted MAC is included in ptxt
435 * - nonce must be AES_CCM_NONCE_LEN bytes
436 * - ptxt and ctxt can point to the same location
437 * - returns -1 on error
441 BCMROMFN(aes_ccm_decrypt
)(unsigned int *rk
,
442 const size_t key_len
,
444 const size_t aad_len
,
446 const size_t data_len
,
450 uint8 A
[AES_BLOCK_SZ
], X
[AES_BLOCK_SZ
];
452 /* initialize counter */
453 A
[0] = AES_CCM_CRYPT_FLAGS
;
454 memcpy(&A
[1], nonce
, AES_CCM_NONCE_LEN
);
455 A
[AES_BLOCK_SZ
- 2] = 0;
456 A
[AES_BLOCK_SZ
- 1] = 1;
457 pres("aes_ccm_decrypt: initial counter:", AES_BLOCK_SZ
, A
);
460 if (aes_ctr_crypt(rk
, key_len
, A
, data_len
-AES_CCM_AUTH_LEN
, ctxt
, ptxt
))
462 pres("aes_ccm_decrypt: decrypted data:", data_len
-AES_CCM_AUTH_LEN
, ptxt
);
465 A
[AES_BLOCK_SZ
- 2] = 0;
466 A
[AES_BLOCK_SZ
- 1] = 0;
467 if (aes_ctr_crypt(rk
, key_len
, A
, AES_CCM_AUTH_LEN
,
468 ctxt
+data_len
-AES_CCM_AUTH_LEN
, ptxt
+ data_len
- AES_CCM_AUTH_LEN
))
470 pres("aes_ccm_decrypt: decrypted MAC:", AES_CCM_AUTH_LEN
,
471 ptxt
+ data_len
- AES_CCM_AUTH_LEN
);
474 if (aes_ccm_mac(rk
, key_len
, nonce
, aad_len
, aad
,
475 data_len
- AES_CCM_AUTH_LEN
, ptxt
, X
))
477 pres("aes_ccm_decrypt: MAC:", AES_CCM_AUTH_LEN
, X
);
478 if (memcmp(X
, ptxt
+ data_len
- AES_CCM_AUTH_LEN
, AES_CCM_AUTH_LEN
) != 0)
484 /* AES-CCMP mode encryption algorithm
485 * - packet buffer should be an 802.11 MPDU, starting with Frame Control,
486 * and including the CCMP extended IV
487 * - encrypts in-place
488 * - packet buffer must have sufficient tailroom for CCMP MAC
489 * - returns -1 on error
494 BCMROMFN(aes_ccmp_encrypt
)(unsigned int *rk
,
495 const size_t key_len
,
496 const size_t data_len
,
499 uint8 nonce_1st_byte
)
501 uint8 nonce
[AES_CCMP_NONCE_LEN
], aad
[AES_CCMP_AAD_MAX_LEN
];
502 struct dot11_header
*h
= (struct dot11_header
*) p
;
506 aes_ccmp_cal_params(h
, legacy
, nonce_1st_byte
, nonce
, aad
, &la
, &lh
);
508 pres("aes_ccmp_encrypt: aad:", la
, aad
);
512 * B3..Bn, n = floor((l(m)+(AES_BLOCK_SZ-1))/AES_BLOCK_SZ) + 2
516 status
= aes_ccm_encrypt(rk
, key_len
, nonce
, la
, aad
,
517 data_len
- lh
, p
+ lh
, p
+ lh
, p
+ data_len
);
519 pres("aes_ccmp_encrypt: Encrypted packet with MAC:",
520 data_len
+AES_CCMP_AUTH_LEN
, p
);
523 return (AES_CCMP_ENCRYPT_ERROR
);
525 return (AES_CCMP_ENCRYPT_SUCCESS
);
529 BCMROMFN(aes_ccmp_decrypt
)(unsigned int *rk
,
530 const size_t key_len
,
531 const size_t data_len
,
534 uint8 nonce_1st_byte
)
536 uint8 nonce
[AES_CCMP_NONCE_LEN
], aad
[AES_CCMP_AAD_MAX_LEN
];
537 struct dot11_header
*h
= (struct dot11_header
*)p
;
541 aes_ccmp_cal_params(h
, legacy
, nonce_1st_byte
, nonce
, aad
, &la
, &lh
);
543 pres("aes_ccmp_decrypt: aad:", la
, aad
);
547 * B3..Bn, n = floor((l(m)+(AES_BLOCK_SZ-1))/AES_BLOCK_SZ) + 2
551 status
= aes_ccm_decrypt(rk
, key_len
, nonce
, la
, aad
,
552 data_len
- lh
, p
+ lh
, p
+ lh
);
554 pres("aes_ccmp_decrypt: Decrypted packet with MAC:", data_len
, p
);
557 return (AES_CCMP_DECRYPT_MIC_FAIL
);
559 return (AES_CCMP_DECRYPT_SUCCESS
);
563 BCMROMFN(aes_ccmp_cal_params
)(struct dot11_header
*h
, bool legacy
,
564 uint8 nonce_1st_byte
, uint8
*nonce
, uint8
*aad
, uint
*la
, uint
*lh
)
572 memset(nonce
, 0, AES_CCMP_NONCE_LEN
);
573 memset(aad
, 0, AES_CCMP_AAD_MAX_LEN
);
576 subtype
= (fc
& FC_SUBTYPE_MASK
) >> FC_SUBTYPE_SHIFT
;
577 wds
= ((fc
& (FC_TODS
| FC_FROMDS
)) == (FC_TODS
| FC_FROMDS
));
578 /* all QoS subtypes have the FC_SUBTYPE_QOS_DATA bit set */
579 qos
= (FC_TYPE(fc
) == FC_TYPE_DATA
) && (subtype
& FC_SUBTYPE_QOS_DATA
);
582 qc
= ltoh16(*((uint16
*)((uchar
*)h
+
583 (wds
? DOT11_A4_HDR_LEN
: DOT11_A3_HDR_LEN
))));
587 dbg(("aes_ccmp_cal_params: A4 present\n"));
588 addlen
+= ETHER_ADDR_LEN
;
591 dbg(("aes_ccmp_cal_params: QC present\n"));
592 addlen
+= DOT11_QOS_LEN
;
595 /* length of MPDU header, including IV */
596 *lh
= DOT11_A3_HDR_LEN
+ DOT11_IV_AES_CCM_LEN
+ addlen
;
598 *la
= AES_CCMP_AAD_MIN_LEN
+ addlen
;
600 iv_data
= (uint8
*)h
+ DOT11_A3_HDR_LEN
+ addlen
;
602 *nonce
++ = nonce_1st_byte
;
604 memcpy(nonce
, (uchar
*)&h
->a2
, ETHER_ADDR_LEN
);
605 nonce
+= ETHER_ADDR_LEN
;
608 *nonce
++ = iv_data
[7];
610 *nonce
++ = iv_data
[6];
612 *nonce
++ = iv_data
[5];
614 *nonce
++ = iv_data
[4];
616 *nonce
++ = iv_data
[1];
618 *nonce
++ = iv_data
[0];
620 pres("aes_ccmp_cal_params: nonce:", AES_CCM_NONCE_LEN
, nonce
- AES_CCM_NONCE_LEN
);
622 /* B1..B2 = l(aad) || aad || pad(aad) */
623 /* aad: maskedFC || A1 || A2 || A3 || maskedSC || A4 || maskedQC */
627 /* For a management frame, don't mask the the subtype bits */
628 if (nonce_1st_byte
& AES_CCMP_NF_MANAGEMENT
)
629 fc
&= (FC_SUBTYPE_MASK
| AES_CCMP_FC_MASK
);
632 fc
&= AES_CCMP_FC_MASK
;
634 /* 802.11i Draft 3 inconsistencies:
635 * Clause 8.3.4.4.3: "FC - MPDU Frame Control field, with Retry bit masked
636 * to zero." (8.3.4.4.3).
637 * Figure 29: "FC - MPDU Frame Control field, with Retry, MoreData, CF-ACK,
638 * CF-POLL bits masked to zero."
639 * F.10.4.1: "FC - MPDU Frame Control field, with Retry, MoreData,
640 * PwrMgmt bits masked to zero."
643 /* Our implementation: match 8.3.4.4.3 */
644 fc
&= AES_CCMP_LEGACY_FC_MASK
;
646 *aad
++ = (uint8
)(fc
& 0xff);
647 *aad
++ = (uint8
)((fc
>> 8) & 0xff);
649 memcpy(aad
, (uchar
*)&h
->a1
, 3*ETHER_ADDR_LEN
);
650 aad
+= 3*ETHER_ADDR_LEN
;
652 seq
= ltoh16(h
->seq
);
654 seq
&= AES_CCMP_SEQ_MASK
;
656 seq
&= AES_CCMP_LEGACY_SEQ_MASK
;
659 *aad
++ = (uint8
)(seq
& 0xff);
660 *aad
++ = (uint8
)((seq
>> 8) & 0xff);
663 memcpy(aad
, (uchar
*)&h
->a4
, ETHER_ADDR_LEN
);
664 aad
+= ETHER_ADDR_LEN
;
668 /* 802.11i Draft 7.0 inconsistencies:
669 * Clause 8.3.3.3.2: "QC - The Quality of Service Control, a
670 * two-octet field that includes the MSDU priority, reserved
672 * I.7.4: TID portion of QoS
675 /* Our implementation: match the test vectors */
676 qc
&= AES_CCMP_QOS_MASK
;
677 *aad
++ = (uint8
)(qc
& 0xff);
678 *aad
++ = (uint8
)((qc
>> 8) & 0xff);
680 /* 802.11i Draft 3.0 inconsistencies: */
681 /* Clause 8.3.4.4.3: "QC - The QoS Control, if present." */
682 /* Figure 30: "QC - The QoS TC from QoS Control, if present." */
683 /* F.10.4.1: "QC - The QoS TC from QoS Control, if present." */
685 /* Our implementation: Match clause 8.3.4.4.3 */
686 qc
&= AES_CCMP_LEGACY_QOS_MASK
;
687 *aad
++ = (uint8
)(qc
& 0xff);
688 *aad
++ = (uint8
)((qc
>> 8) & 0xff);
693 /* 128-bit long string of zeros */
694 static const uint8 Z128
[] = {
695 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
696 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
699 /* CMAC Subkey generation polynomial for 128-bit blocks */
700 static const uint8 R128
[] = {
701 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
702 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87
705 /* AES-CMAC subkey generation
706 * - computes subkeys K1 and K2 of length AES_BLOCK_SZ
709 aes_cmac_gen_subkeys(const size_t kl
, const uint8
*K
, uint8
*K1
, uint8
*K2
)
711 uint8 L
[AES_BLOCK_SZ
];
716 aes_encrypt(kl
, K
, Z128
, L
);
718 pres("CIPHK", AES_BLOCK_SZ
, L
);
720 /* If MSB1(L) = 0, then K1 = L << 1 */
721 /* Else K1 = (L << 1) ^ Rb */
723 for (i
= AES_BLOCK_SZ
-1; i
>= 0; i
--) {
726 high
= (L
[i
] & 0x80) >> 7;
728 if ((L
[0] & 0x80) != 0)
729 xor_128bit_block(K1
, R128
, K1
);
730 pres("K1", AES_BLOCK_SZ
, K1
);
732 /* If MSB1(K1) = 0, then K2 = K1 << 1 */
733 /* Else K2 = (K1 << 1) ^ Rb */
735 for (i
= AES_BLOCK_SZ
-1; i
>= 0; i
--) {
738 high
= (K1
[i
] & 0x80) >> 7;
740 if ((K1
[0] & 0x80) != 0)
741 xor_128bit_block(K2
, R128
, K2
);
742 pres("K2", AES_BLOCK_SZ
, K2
);
747 /* AES-CMAC mode calculation
748 * - computes AES_CMAC_AUTH_LEN MAC
749 * - operates on complete bytes only (i.e. data_len is in bytes)
753 aes_cmac(const size_t key_len
, const uint8
* K
,
754 const uint8
*K1
, const uint8
*K2
,
755 const size_t data_len
,
760 uint8 Mn
[AES_BLOCK_SZ
], tmp
[AES_BLOCK_SZ
], C
[AES_BLOCK_SZ
];
761 uint32 rk
[4 * (AES_MAXROUNDS
+ 1)];
763 /* If Mlen = 0, let n = 1; else, let n = Mlen/b */
767 n
= ((uint
)data_len
+ AES_BLOCK_SZ
- 1)/AES_BLOCK_SZ
;
769 /* Let M1, M2, ... , Mn-1, Mn* denote the unique sequence of bit
770 strings such that M = M1 || M2 || ... || Mn-1 || Mn*, where M1,
771 M2,..., Mn-1 are complete blocks. If Mn* is a complete block, let
772 Mn = K1 ^ Mn*; else, let Mn = K2 ^ (Mn*||10j), where j = nb-Mlen-1
775 if (data_len
== (n
* AES_BLOCK_SZ
)) {
776 /* Mn* is a complete block */
777 xor_128bit_block(K1
, &(ptxt
[(n
-1)*AES_BLOCK_SZ
]), Mn
);
779 /* Mn* is a partial block, pad with 0s and use K2 */
780 pblen
= (uint
)data_len
- ((n
-1)*AES_BLOCK_SZ
);
781 for (i
= 0; i
< pblen
; i
++)
782 Mn
[i
] = ptxt
[((n
-1)*AES_BLOCK_SZ
) + i
];
784 for (i
= pblen
+ 1; i
< AES_BLOCK_SZ
; i
++)
786 xor_128bit_block(K2
, Mn
, Mn
);
790 memset(C
, 0, AES_BLOCK_SZ
);
792 /* For i = 1 to n, let Ci = CIPHK(Ci-1 ^ Mi) */
793 rijndaelKeySetupEnc(rk
, K
, (int)AES_KEY_BITLEN(key_len
));
794 for (i
= 1; i
< n
; i
++) {
795 xor_128bit_block(C
, &(ptxt
[(i
-1)*AES_BLOCK_SZ
]), tmp
);
796 aes_block_encrypt((int)AES_ROUNDS(key_len
), rk
, tmp
, C
);
798 xor_128bit_block(C
, Mn
, tmp
);
799 aes_block_encrypt((int)AES_ROUNDS(key_len
), rk
, tmp
, C
);
801 /* Let T = MSBTlen(Cn) */
802 memcpy(mac
, C
, AES_CMAC_AUTH_LEN
);
808 aes_cmac_calc(const uint8
*data
, const size_t data_length
, const uint8
*mic_key
,
809 const size_t key_len
, uint8
*mic
)
811 uint8 K1
[AES_BLOCK_SZ
], K2
[AES_BLOCK_SZ
];
813 aes_cmac_gen_subkeys(key_len
, mic_key
, K1
, K2
);
814 aes_cmac(key_len
, mic_key
, K1
, K2
, data_length
, data
, mic
);
817 #ifdef BCMAES_GENTABLE
818 /* AES table expansion for rijndael-alg-fst.c
819 * - can compute all 10 tables needed by rijndael-alg-fst.c
820 * - only stores table entries for non-NULL entries in "at" structure, so
821 * can be used to generate a subset of the tables if only some are needed
824 aes_gen_tables(const uint8
*S
, const uint8
*Si
, aes_tables_t at
)
828 uint8 si2
, si4
, si8
, si9
, sib
, sid
, sie
;
829 uint32 Te0tmp
, Td0tmp
;
831 for (k
= 0; k
< AES_SBOX_ENTRIES
; k
++) {
854 sid
= si8
^ si4
^ Si
[k
];
857 sie
= si8
^ si4
^ si2
;
859 Te0tmp
= (s2
<< 24) | (S
[k
] << 16) | (S
[k
] << 8) | s3
;
863 at
.Te1
[k
] = ROTATE(Te0tmp
, 24);
865 at
.Te2
[k
] = ROTATE(Te0tmp
, 16);
867 at
.Te3
[k
] = ROTATE(Te0tmp
, 8);
869 at
.Te4
[k
] = (S
[k
] << 24) | (S
[k
] << 16) | (S
[k
] << 8) | S
[k
];
871 Td0tmp
= (sie
<< 24) | (si9
<< 16) | (sid
<< 8) | sib
;
875 at
.Td1
[k
] = ROTATE(Td0tmp
, 24);
877 at
.Td2
[k
] = ROTATE(Td0tmp
, 16);
879 at
.Td3
[k
] = ROTATE(Td0tmp
, 8);
881 at
.Td4
[k
] = (Si
[k
] << 24) | (Si
[k
] << 16) | (Si
[k
] << 8) | Si
[k
];
884 #endif /* BCMAES_GENTABLE */
887 #include "aes_vectors.h"
890 get_nonce_1st_byte(struct dot11_header
*h
)
898 subtype
= (fc
& FC_SUBTYPE_MASK
) >> FC_SUBTYPE_SHIFT
;
899 wds
= ((fc
& (FC_TODS
| FC_FROMDS
)) == (FC_TODS
| FC_FROMDS
));
900 /* all QoS subtypes have the FC_SUBTYPE_QOS_DATA bit set */
901 qos
= (FC_TYPE(fc
) == FC_TYPE_DATA
) && (subtype
& FC_SUBTYPE_QOS_DATA
);
904 qc
= ltoh16(*((uint16
*)((uchar
*)h
+
905 (wds
? DOT11_A4_HDR_LEN
: DOT11_A3_HDR_LEN
))));
908 /* nonce = priority octet || A2 || PN, !legacy */
909 return (uint8
)(QOS_TID(qc
) & 0x0f);
913 main(int argc
, char **argv
)
915 uint8 output
[BUFSIZ
], input2
[BUFSIZ
];
916 int retv
, k
, fail
= 0;
917 uint32 rk
[4 * (AES_MAXROUNDS
+ 1)];
919 #ifdef BCMAES_GENTABLE
920 uint32 Te0test
[256], Te1test
[256], Te2test
[256], Te3test
[256], Te4test
[256];
921 uint32 Td0test
[256], Td1test
[256], Td2test
[256], Td3test
[256], Td4test
[256];
924 Te0test
, Te1test
, Te2test
, Te3test
, Te4test
,
925 Td0test
, Td1test
, Td2test
, Td3test
, Td4test
927 #endif /* BCMAES_GENTABLE */
930 dbg(("%s: AES-CBC\n", *argv
));
931 for (k
= 0; k
< NUM_CBC_VECTORS
; k
++) {
932 rijndaelKeySetupEnc(rk
, aes_cbc_vec
[k
].key
,
933 AES_KEY_BITLEN(aes_cbc_vec
[k
].kl
));
934 retv
= aes_cbc_encrypt(rk
, aes_cbc_vec
[k
].kl
,
935 aes_cbc_vec
[k
].nonce
, aes_cbc_vec
[k
].il
,
936 aes_cbc_vec
[k
].input
, output
);
937 pres("AES CBC Encrypt: ", aes_cbc_vec
[k
].il
, output
);
940 dbg(("%s: aes_cbc_encrypt failed\n", *argv
));
943 if (memcmp(output
, aes_cbc_vec
[k
].ref
, aes_cbc_vec
[k
].il
) != 0) {
944 dbg(("%s: aes_cbc_encrypt failed\n", *argv
));
948 rijndaelKeySetupDec(rk
, aes_cbc_vec
[k
].key
,
949 AES_KEY_BITLEN(aes_cbc_vec
[k
].kl
));
950 retv
= aes_cbc_decrypt(rk
, aes_cbc_vec
[k
].kl
,
951 aes_cbc_vec
[k
].nonce
, aes_cbc_vec
[k
].il
,
952 aes_cbc_vec
[k
].ref
, input2
);
953 pres("AES CBC Decrypt: ", aes_cbc_vec
[k
].il
, input2
);
956 dbg(("%s: aes_cbc_decrypt failed\n", *argv
));
959 if (memcmp(aes_cbc_vec
[k
].input
, input2
, aes_cbc_vec
[k
].il
) != 0) {
960 dbg(("%s: aes_cbc_decrypt failed\n", *argv
));
965 /* AES-CTR, full blocks */
966 dbg(("%s: AES-CTR, full blocks\n", *argv
));
967 for (k
= 0; k
< NUM_CTR_VECTORS
; k
++) {
968 rijndaelKeySetupEnc(rk
, aes_ctr_vec
[k
].key
,
969 AES_KEY_BITLEN(aes_ctr_vec
[k
].kl
));
970 retv
= aes_ctr_crypt(rk
, aes_ctr_vec
[k
].kl
,
971 aes_ctr_vec
[k
].nonce
, aes_ctr_vec
[k
].il
,
972 aes_ctr_vec
[k
].input
, output
);
973 pres("AES CTR Encrypt: ", aes_ctr_vec
[k
].il
, output
);
976 dbg(("%s: aes_ctr_crypt failed\n", *argv
));
979 if (memcmp(output
, aes_ctr_vec
[k
].ref
, aes_ctr_vec
[k
].il
) != 0) {
980 dbg(("%s: aes_ctr_crypt encrypt failed\n", *argv
));
984 rijndaelKeySetupEnc(rk
, aes_ctr_vec
[k
].key
,
985 AES_KEY_BITLEN(aes_ctr_vec
[k
].kl
));
986 retv
= aes_ctr_crypt(rk
, aes_ctr_vec
[k
].kl
,
987 aes_ctr_vec
[k
].nonce
, aes_ctr_vec
[k
].il
,
988 aes_ctr_vec
[k
].ref
, input2
);
989 pres("AES CTR Decrypt: ", aes_ctr_vec
[k
].il
, input2
);
992 dbg(("%s: aes_ctr_crypt failed\n", *argv
));
995 if (memcmp(aes_ctr_vec
[k
].input
, input2
, aes_ctr_vec
[k
].il
) != 0) {
996 dbg(("%s: aes_ctr_crypt decrypt failed\n", *argv
));
1001 /* AES-CTR, one partial block */
1002 dbg(("%s: AES-CTR, one partial block\n", *argv
));
1003 for (k
= 0; k
< NUM_CTR_VECTORS
; k
++) {
1004 rijndaelKeySetupEnc(rk
, aes_ctr_vec
[k
].key
,
1005 AES_KEY_BITLEN(aes_ctr_vec
[k
].kl
));
1006 retv
= aes_ctr_crypt(rk
, aes_ctr_vec
[k
].kl
,
1007 aes_ctr_vec
[k
].nonce
, k
+1,
1008 aes_ctr_vec
[k
].input
, output
);
1009 pres("AES CTR Partial Block Encrypt: ", k
+1, output
);
1012 dbg(("%s: aes_ctr_crypt failed\n", *argv
));
1015 if (memcmp(output
, aes_ctr_vec
[k
].ref
, k
+ 1) != 0) {
1016 dbg(("%s: aes_ctr_crypt encrypt failed\n", *argv
));
1020 rijndaelKeySetupEnc(rk
, aes_ctr_vec
[k
].key
,
1021 AES_KEY_BITLEN(aes_ctr_vec
[k
].kl
));
1022 retv
= aes_ctr_crypt(rk
, aes_ctr_vec
[k
].kl
,
1023 aes_ctr_vec
[k
].nonce
, k
+ 1,
1024 aes_ctr_vec
[k
].ref
, input2
);
1025 pres("AES CTR Partial Block Decrypt: ", k
+ 1, input2
);
1028 dbg(("%s: aes_ctr_crypt failed\n", *argv
));
1031 if (memcmp(aes_ctr_vec
[k
].input
, input2
, k
+ 1) != 0) {
1032 dbg(("%s: aes_ctr_crypt decrypt failed\n", *argv
));
1037 /* AES-CTR, multi-block partial */
1038 dbg(("%s: AES-CTR, multi-block partial\n", *argv
));
1039 for (k
= 0; k
< NUM_CTR_VECTORS
; k
++) {
1040 rijndaelKeySetupEnc(rk
, aes_ctr_vec
[k
].key
,
1041 AES_KEY_BITLEN(aes_ctr_vec
[k
].kl
));
1042 retv
= aes_ctr_crypt(rk
, aes_ctr_vec
[k
].kl
,
1043 aes_ctr_vec
[k
].nonce
, AES_BLOCK_SZ
+ NUM_CTR_VECTORS
+k
+1,
1044 aes_ctr_vec
[k
].input
, output
);
1045 pres("AES CTR Partial Multi-Block Encrypt: ",
1046 AES_BLOCK_SZ
+ NUM_CTR_VECTORS
+ k
+ 1, output
);
1049 dbg(("%s: aes_ctr_crypt failed\n", *argv
));
1052 if (memcmp(output
, aes_ctr_vec
[k
].ref
, AES_BLOCK_SZ
+NUM_CTR_VECTORS
+ k
+ 1) != 0) {
1053 dbg(("%s: aes_ctr_crypt encrypt failed\n", *argv
));
1057 rijndaelKeySetupEnc(rk
, aes_ctr_vec
[k
].key
,
1058 AES_KEY_BITLEN(aes_ctr_vec
[k
].kl
));
1059 retv
= aes_ctr_crypt(rk
, aes_ctr_vec
[k
].kl
,
1060 aes_ctr_vec
[k
].nonce
, AES_BLOCK_SZ
+ NUM_CTR_VECTORS
+ k
+ 1,
1061 aes_ctr_vec
[k
].ref
, input2
);
1062 pres("AES CTR Partial Multi-Block Decrypt: ",
1063 AES_BLOCK_SZ
+ NUM_CTR_VECTORS
+ k
+ 1, input2
);
1066 dbg(("%s: aes_ctr_crypt failed\n", *argv
));
1069 if (memcmp(aes_ctr_vec
[k
].input
, input2
,
1070 AES_BLOCK_SZ
+ NUM_CTR_VECTORS
+ k
+ 1) != 0) {
1071 dbg(("%s: aes_ctr_crypt decrypt failed\n", *argv
));
1077 dbg(("%s: AES-CCM\n", *argv
));
1078 for (k
= 0; k
< NUM_CCM_VECTORS
; k
++) {
1079 rijndaelKeySetupEnc(rk
, aes_ccm_vec
[k
].key
,
1080 AES_KEY_BITLEN(aes_ccm_vec
[k
].kl
));
1081 retv
= aes_ccm_mac(rk
, aes_ccm_vec
[k
].kl
,
1082 aes_ccm_vec
[k
].nonce
, aes_ccm_vec
[k
].al
,
1083 aes_ccm_vec
[k
].aad
, aes_ccm_vec
[k
].il
,
1084 aes_ccm_vec
[k
].input
, output
);
1087 dbg(("%s: aes_ccm_mac failed\n", *argv
));
1090 if (memcmp(output
, aes_ccm_vec
[k
].mac
, AES_CCM_AUTH_LEN
) != 0) {
1091 dbg(("%s: aes_ccm_mac failed\n", *argv
));
1095 rijndaelKeySetupEnc(rk
, aes_ccm_vec
[k
].key
,
1096 AES_KEY_BITLEN(aes_ccm_vec
[k
].kl
));
1097 retv
= aes_ccm_encrypt(rk
, aes_ccm_vec
[k
].kl
,
1098 aes_ccm_vec
[k
].nonce
, aes_ccm_vec
[k
].al
,
1099 aes_ccm_vec
[k
].aad
, aes_ccm_vec
[k
].il
,
1100 aes_ccm_vec
[k
].input
, output
, &output
[aes_ccm_vec
[k
].il
]);
1101 pres("AES CCM Encrypt: ", aes_ccm_vec
[k
].il
+ AES_CCM_AUTH_LEN
, output
);
1104 dbg(("%s: aes_ccm_encrypt failed\n", *argv
));
1107 if (memcmp(output
, aes_ccm_vec
[k
].ref
, aes_ccm_vec
[k
].il
+ AES_CCM_AUTH_LEN
) != 0) {
1108 dbg(("%s: aes_ccm_encrypt failed\n", *argv
));
1112 rijndaelKeySetupEnc(rk
, aes_ccm_vec
[k
].key
,
1113 AES_KEY_BITLEN(aes_ccm_vec
[k
].kl
));
1114 retv
= aes_ccm_decrypt(rk
, aes_ccm_vec
[k
].kl
,
1115 aes_ccm_vec
[k
].nonce
, aes_ccm_vec
[k
].al
,
1116 aes_ccm_vec
[k
].aad
, aes_ccm_vec
[k
].il
+ AES_CCM_AUTH_LEN
,
1117 aes_ccm_vec
[k
].ref
, input2
);
1118 pres("AES CCM Decrypt: ", aes_ccm_vec
[k
].il
+ AES_CCM_AUTH_LEN
, input2
);
1121 dbg(("%s: aes_ccm_decrypt failed\n", *argv
));
1124 if (memcmp(aes_ccm_vec
[k
].input
, input2
, aes_ccm_vec
[k
].il
) != 0) {
1125 dbg(("%s: aes_ccm_decrypt failed\n", *argv
));
1131 dbg(("%s: AES-CCMP\n", *argv
));
1132 for (k
= 0; k
< NUM_CCMP_VECTORS
; k
++) {
1133 uint8 nonce_1st_byte
;
1134 dbg(("%s: AES-CCMP vector %d\n", *argv
, k
));
1135 rijndaelKeySetupEnc(rk
, aes_ccmp_vec
[k
].key
,
1136 AES_KEY_BITLEN(aes_ccmp_vec
[k
].kl
));
1137 memcpy(output
, aes_ccmp_vec
[k
].input
, aes_ccmp_vec
[k
].il
);
1138 nonce_1st_byte
= get_nonce_1st_byte((struct dot11_header
*)output
);
1139 retv
= aes_ccmp_encrypt(rk
, aes_ccmp_vec
[k
].kl
,
1140 aes_ccmp_vec
[k
].il
, output
,
1141 aes_ccmp_vec
[k
].flags
[2],
1145 dbg(("%s: aes_ccmp_encrypt of vector %d returned error\n", *argv
, k
));
1148 if (memcmp(output
, aes_ccmp_vec
[k
].ref
,
1149 aes_ccmp_vec
[k
].il
+AES_CCM_AUTH_LEN
) != 0) {
1150 dbg(("%s: aes_ccmp_encrypt of vector %d reference mismatch\n", *argv
, k
));
1154 rijndaelKeySetupEnc(rk
, aes_ccmp_vec
[k
].key
,
1155 AES_KEY_BITLEN(aes_ccmp_vec
[k
].kl
));
1156 memcpy(output
, aes_ccmp_vec
[k
].ref
, aes_ccmp_vec
[k
].il
+AES_CCM_AUTH_LEN
);
1157 nonce_1st_byte
= get_nonce_1st_byte((struct dot11_header
*)output
);
1158 retv
= aes_ccmp_decrypt(rk
, aes_ccmp_vec
[k
].kl
,
1159 aes_ccmp_vec
[k
].il
+AES_CCM_AUTH_LEN
, output
,
1160 aes_ccmp_vec
[k
].flags
[2],
1164 dbg(("%s: aes_ccmp_decrypt of vector %d returned error %d\n",
1168 if (memcmp(output
, aes_ccmp_vec
[k
].input
, aes_ccmp_vec
[k
].il
) != 0) {
1169 dbg(("%s: aes_ccmp_decrypt of vector %d reference mismatch\n", *argv
, k
));
1175 #ifdef BCMAES_GENTABLE
1176 aes_gen_tables(AES_Sbox
, AES_Inverse_Sbox
, at
);
1177 ptable("Te0", Te0test
);
1178 ptable("Te1", Te1test
);
1179 ptable("Te2", Te2test
);
1180 ptable("Te3", Te3test
);
1181 ptable("Te4", Te4test
);
1183 ptable("Td0", Td0test
);
1184 ptable("Td1", Td1test
);
1185 ptable("Td2", Td2test
);
1186 ptable("Td3", Td3test
);
1187 ptable("Td4", Td4test
);
1188 #endif /* BCMAES_GENTABLE */
1190 fprintf(stderr
, "%s: %s\n", *argv
, fail
? "FAILED" : "PASSED");
1194 #endif /* BCMAES_TEST */