3 * Perform RFC3394 AES-based key wrap and unwrap functions.
5 * Copyright (C) 2012, Broadcom Corporation
8 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation;
9 * the contents of this file may not be disclosed to third parties, copied
10 * or duplicated in any form, in whole or in part, without the prior
11 * written permission of Broadcom Corporation.
13 * $Id: aeskeywrap.c 241182 2011-02-17 21:50:03Z $
22 #endif /* BCMDRIVER */
24 #include <bcmcrypto/aes.h>
25 #include <bcmcrypto/aeskeywrap.h>
26 #include <bcmcrypto/rijndael-alg-fst.h>
28 #ifdef BCMAESKEYWRAP_TEST
31 #define dbg(args) printf args
34 pinter(const char *label
, const uint8
*A
, const size_t il
, const uint8
*R
)
38 for (k
= 0; k
< AKW_BLOCK_LEN
; k
++)
41 for (k
= 0; k
< il
; k
++) {
43 if (!((k
+1)%AKW_BLOCK_LEN
))
50 pres(const char *label
, const size_t len
, const uint8
*data
)
53 printf("%lu %s", (unsigned long)len
, label
);
54 for (k
= 0; k
< len
; k
++) {
55 printf("%02x", data
[k
]);
56 if (!((k
+ 1) % AKW_BLOCK_LEN
))
63 #define pinter(label, A, il, R)
64 #endif /* BCMAESKEYWRAP_TEST */
66 static const uint8 aeskeywrapIV
[] = { 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6 };
68 /* aes_wrap: perform AES-based keywrap function defined in RFC3394
69 * return 0 on success, 1 on error
71 * output is (il+8) bytes
74 BCMROMFN(aes_wrap
)(size_t kl
, uint8
*key
, size_t il
, uint8
*input
, uint8
*output
)
76 uint32 rk
[4*(AES_MAXROUNDS
+1)];
77 uint8 A
[AES_BLOCK_SZ
];
78 uint8 R
[AKW_MAX_WRAP_LEN
];
79 uint8 B
[AES_BLOCK_SZ
];
80 int n
= (int)(il
/AKW_BLOCK_LEN
), i
, j
, k
;
82 /* validate kl (must be valid AES key length) */
83 if ((kl
!= 16) && (kl
!= 24) && (kl
!= 32)) {
84 dbg(("aes_wrap: invlaid key length %lu\n", (unsigned long)kl
));
87 if (il
> AKW_MAX_WRAP_LEN
) {
88 dbg(("aes_wrap: input length %lu too large\n", (unsigned long)il
));
91 if (il
% AKW_BLOCK_LEN
) {
92 dbg(("aes_wrap: input length %lu must be a multiple of block length\n",
99 for (k
= 0; k
< (int)kl
; k
++)
100 dbg(("%02X", key
[k
]));
101 dbg(("\n Key Data: "));
102 for (k
= 0; k
< (int)il
; k
++)
103 dbg(("%02X", input
[k
]));
104 dbg(("\n\n Wrap: \n"));
106 rijndaelKeySetupEnc(rk
, key
, (int)AES_KEY_BITLEN(kl
));
109 memcpy(A
, aeskeywrapIV
, AKW_BLOCK_LEN
);
112 memcpy(R
, input
, il
);
115 for (j
= 0; j
< 6; j
++) {
117 for (i
= 0; i
< n
; i
++) {
118 dbg(("\n %d\n", (n
*j
)+i
+1));
119 pinter(" In ", A
, il
, R
);
120 /* B = AES(K, A | R[i]) */
121 memcpy(&A
[AKW_BLOCK_LEN
], &R
[i
*AKW_BLOCK_LEN
], AKW_BLOCK_LEN
);
122 aes_block_encrypt((int)AES_ROUNDS(kl
), rk
, A
, B
);
124 /* R[i] = LSB(64, B) */
125 memcpy(&R
[i
*AKW_BLOCK_LEN
], &B
[AKW_BLOCK_LEN
], AKW_BLOCK_LEN
);
127 /* A = MSB(64, B) ^ t where t = (n*j)+i */
128 memcpy(&A
[0], &B
[0], AKW_BLOCK_LEN
);
129 pinter(" Enc ", A
, il
, R
);
130 A
[AKW_BLOCK_LEN
-1] ^= ((n
*j
)+i
+1);
131 pinter(" XorT ", A
, il
, R
);
135 memcpy(output
, A
, AKW_BLOCK_LEN
);
138 memcpy(&output
[AKW_BLOCK_LEN
], R
, il
);
143 /* aes_unwrap: perform AES-based key unwrap function defined in RFC3394,
144 * return 0 on success, 1 on error
146 * output is (il-8) bytes
149 BCMROMFN(aes_unwrap
)(size_t kl
, uint8
*key
, size_t il
, uint8
*input
, uint8
*output
)
151 uint32 rk
[4*(AES_MAXROUNDS
+1)];
152 uint8 A
[AES_BLOCK_SZ
];
153 uint8 R
[AKW_MAX_WRAP_LEN
+ AKW_BLOCK_LEN
];
154 uint8 B
[AES_BLOCK_SZ
];
155 size_t ol
= il
- AKW_BLOCK_LEN
;
156 int n
= (int)(ol
/AKW_BLOCK_LEN
), i
, j
, k
;
158 /* validate kl (must be valid AES key length) */
159 if ((kl
!= 16) && (kl
!= 24) && (kl
!= 32)) {
160 dbg(("aes_wrap: invlaid key length %lu\n", (unsigned long)kl
));
163 if (il
> (AKW_MAX_WRAP_LEN
+ AKW_BLOCK_LEN
)) {
164 dbg(("aes_unwrap: input length %lu too large\n", (unsigned long)il
));
167 if (il
% AKW_BLOCK_LEN
) {
168 dbg(("aes_unwrap: input length %lu must be a multiple of block length\n",
175 for (k
= 0; k
< (int)kl
; k
++)
176 dbg(("%02X", key
[k
]));
178 for (k
= 0; k
< (int)il
; k
++)
179 dbg(("%02X", input
[k
]));
180 dbg(("\n\n Unwrap: \n"));
182 rijndaelKeySetupDec(rk
, key
, (int)AES_KEY_BITLEN(kl
));
185 memcpy(A
, input
, AKW_BLOCK_LEN
);
189 memcpy(R
, &input
[AKW_BLOCK_LEN
], ol
);
192 for (j
= 5; j
>= 0; j
--) {
194 for (i
= n
- 1; i
>= 0; i
--) {
195 dbg(("\n %d\n", (n
*j
)+i
+1));
196 pinter(" In ", A
, ol
, R
);
198 /* B = AES - 1 (K, (A ^ t) | R[i]) where t = n * j + i */
199 A
[AKW_BLOCK_LEN
- 1] ^= ((n
*j
)+i
+1);
200 pinter(" XorT ", A
, ol
, R
);
202 memcpy(&A
[AKW_BLOCK_LEN
], &R
[i
*AKW_BLOCK_LEN
], AKW_BLOCK_LEN
);
203 aes_block_decrypt((int)AES_ROUNDS(kl
), rk
, A
, B
);
206 memcpy(&A
[0], &B
[0], AKW_BLOCK_LEN
);
208 /* R[i] = LSB(64, B) */
209 memcpy(&R
[i
*AKW_BLOCK_LEN
], &B
[AKW_BLOCK_LEN
], AKW_BLOCK_LEN
);
210 pinter(" Dec ", A
, ol
, R
);
213 if (!memcmp(A
, aeskeywrapIV
, AKW_BLOCK_LEN
)) {
216 memcpy(&output
[0], R
, ol
);
219 dbg(("aes_unwrap: IV mismatch in unwrapped data\n"));
224 #ifdef BCMAESKEYWRAP_TEST
225 #include "aeskeywrap_vectors.h"
226 #define NUM_VECTORS (sizeof(akw_vec)/sizeof(akw_vec[0]))
227 #define NUM_WRAP_FAIL_VECTORS \
228 (sizeof(akw_wrap_fail_vec)/sizeof(akw_wrap_fail_vec[0]))
229 #define NUM_UNWRAP_FAIL_VECTORS \
230 (sizeof(akw_unwrap_fail_vec)/sizeof(akw_unwrap_fail_vec[0]))
233 main(int argc
, char **argv
)
235 uint8 output
[AKW_MAX_WRAP_LEN
+AKW_BLOCK_LEN
];
236 uint8 input2
[AKW_MAX_WRAP_LEN
];
237 int retv
, k
, fail
= 0;
239 for (k
= 0; k
< NUM_VECTORS
; k
++) {
240 retv
= aes_wrap(akw_vec
[k
].kl
, akw_vec
[k
].key
, akw_vec
[k
].il
,
241 akw_vec
[k
].input
, output
);
242 pres("\n AES Wrap: ", akw_vec
[k
].il
+AKW_BLOCK_LEN
, output
);
245 dbg(("%s: aes_wrap failed\n", *argv
));
248 if (memcmp(output
, akw_vec
[k
].ref
, akw_vec
[k
].il
+AKW_BLOCK_LEN
) != 0) {
249 dbg(("%s: aes_wrap failed\n", *argv
));
253 retv
= aes_unwrap(akw_vec
[k
].kl
, akw_vec
[k
].key
, akw_vec
[k
].il
+ AKW_BLOCK_LEN
,
255 pres("\n AES Unwrap: ", akw_vec
[k
].il
, input2
);
258 dbg(("%s: aes_unwrap failed\n", *argv
));
261 if (memcmp(akw_vec
[k
].input
, input2
, akw_vec
[k
].il
) != 0) {
262 dbg(("%s: aes_unwrap failed\n", *argv
));
267 for (k
= 0; k
< NUM_WRAP_FAIL_VECTORS
; k
++) {
268 if (!aes_wrap(akw_wrap_fail_vec
[k
].kl
, akw_wrap_fail_vec
[k
].key
,
269 akw_wrap_fail_vec
[k
].il
, akw_wrap_fail_vec
[k
].input
, output
)) {
270 dbg(("%s: aes_wrap didn't detect failure case\n", *argv
));
275 for (k
= 0; k
< NUM_UNWRAP_FAIL_VECTORS
; k
++) {
276 if (!aes_unwrap(akw_unwrap_fail_vec
[k
].kl
, akw_unwrap_fail_vec
[k
].key
,
277 akw_unwrap_fail_vec
[k
].il
, akw_unwrap_fail_vec
[k
].input
, input2
)) {
278 dbg(("%s: aes_unwrap didn't detect failure case\n", *argv
));
283 dbg(("%s: %s\n", *argv
, fail
?"FAILED":"PASSED"));
286 #endif /* BCMAESKEYWRAP_TEST */