Resync with broadcom drivers 5.100.138.20 and utilities.
[tomato.git] / release / src-rt / bcmcrypto / aeskeywrap.c
blob4d21ed69dc6315f7416b9d6d1059413ffe697c3f
1 /*
2 * aeskeywrap.c
3 * Perform RFC3394 AES-based key wrap and unwrap functions.
5 * Copyright (C) 2010, Broadcom Corporation
6 * All Rights Reserved.
7 *
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,v 1.31 2009-04-21 01:06:59 Exp $
16 #include <typedefs.h>
18 #ifdef BCMDRIVER
19 #include <osl.h>
20 #else
21 #if defined(__GNUC__)
22 extern void bcopy(const void *src, void *dst, int len);
23 extern int bcmp(const void *b1, const void *b2, int len);
24 #else
25 #include <string.h>
26 #define bcopy(src, dst, len) memcpy((dst), (src), (len))
27 #define bcmp(b1, b2, len) memcmp((b1), (b2), (len))
28 #endif /* __GNUC__ */
29 #include <stddef.h> /* for size_t */
30 #endif /* BCMDRIVER */
32 #include <bcmcrypto/aes.h>
33 #include <bcmcrypto/aeskeywrap.h>
34 #include <bcmcrypto/rijndael-alg-fst.h>
36 #ifdef BCMAESKEYWRAP_TEST
37 #include <stdio.h>
39 #define dbg(args) printf args
41 void pinter(const char *label, const uint8 *A, const size_t il, const uint8 *R)
43 unsigned int k;
44 printf("%s", label);
45 for (k = 0; k < AKW_BLOCK_LEN; k++)
46 printf("%02X", A[k]);
47 printf(" ");
48 for (k = 0; k < il; k++) {
49 printf("%02X", R[k]);
50 if (!((k+1)%AKW_BLOCK_LEN))
51 printf(" ");
53 printf("\n");
56 void pres(const char *label, const size_t len, const uint8 *data)
58 unsigned int k;
59 printf("%lu %s", (unsigned long)len, label);
60 for (k = 0; k < len; k++) {
61 printf("%02x", data[k]);
62 if (!((k + 1) % AKW_BLOCK_LEN))
63 printf(" ");
65 printf("\n");
67 #else
68 #define dbg(args)
69 #define pinter(label, A, il, R)
70 #endif /* BCMAESKEYWRAP_TEST */
72 static const uint8 aeskeywrapIV[] = { 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6 };
74 /* aes_wrap: perform AES-based keywrap function defined in RFC3394
75 * return 0 on success, 1 on error
76 * input is il bytes
77 * output is (il+8) bytes
79 int
80 BCMROMFN(aes_wrap)(size_t kl, uint8 *key, size_t il, uint8 *input, uint8 *output)
82 uint32 rk[4*(AES_MAXROUNDS+1)];
83 uint8 A[AES_BLOCK_SZ];
84 uint8 R[AKW_MAX_WRAP_LEN];
85 uint8 B[AES_BLOCK_SZ];
86 int n = (int)(il/AKW_BLOCK_LEN), i, j, k;
88 /* validate kl (must be valid AES key length) */
89 if ((kl != 16) && (kl != 24) && (kl != 32)) {
90 dbg(("aes_wrap: invlaid key length %lu\n", (unsigned long)kl));
91 return (1);
93 if (il > AKW_MAX_WRAP_LEN) {
94 dbg(("aes_wrap: input length %lu too large\n", (unsigned long)il));
95 return (1);
97 if (il % AKW_BLOCK_LEN) {
98 dbg(("aes_wrap: input length %lu must be a multiple of block length\n",
99 (unsigned long)il));
100 return (1);
103 dbg((" Input:\n"));
104 dbg((" KEK: "));
105 for (k = 0; k < (int)kl; k++)
106 dbg(("%02X", key[k]));
107 dbg(("\n Key Data: "));
108 for (k = 0; k < (int)il; k++)
109 dbg(("%02X", input[k]));
110 dbg(("\n\n Wrap: \n"));
112 rijndaelKeySetupEnc(rk, key, (int)AES_KEY_BITLEN(kl));
114 /* Set A = IV */
115 bcopy(aeskeywrapIV, A, AKW_BLOCK_LEN);
116 /* For i = 1 to n */
117 /* R[i] = P[i] */
118 bcopy(input, R, il);
120 /* For j = 0 to 5 */
121 for (j = 0; j < 6; j++) {
122 /* For i = 1 to n */
123 for (i = 0; i < n; i++) {
124 dbg(("\n %d\n", (n*j)+i+1));
125 pinter(" In ", A, il, R);
126 /* B = AES(K, A | R[i]) */
127 bcopy(&R[i*AKW_BLOCK_LEN], &A[AKW_BLOCK_LEN], AKW_BLOCK_LEN);
128 aes_block_encrypt((int)AES_ROUNDS(kl), rk, A, B);
130 /* R[i] = LSB(64, B) */
131 bcopy(&B[AKW_BLOCK_LEN], &R[i*AKW_BLOCK_LEN], AKW_BLOCK_LEN);
133 /* A = MSB(64, B) ^ t where t = (n*j)+i */
134 bcopy(&B[0], &A[0], AKW_BLOCK_LEN);
135 pinter(" Enc ", A, il, R);
136 A[AKW_BLOCK_LEN-1] ^= ((n*j)+i+1);
137 pinter(" XorT ", A, il, R);
140 /* Set C[0] = A */
141 bcopy(A, output, AKW_BLOCK_LEN);
142 /* For i = 1 to n */
143 /* C[i] = R[i] */
144 bcopy(R, &output[AKW_BLOCK_LEN], il);
146 return (0);
149 /* aes_unwrap: perform AES-based key unwrap function defined in RFC3394,
150 * return 0 on success, 1 on error
151 * input is il bytes
152 * output is (il-8) bytes
155 BCMROMFN(aes_unwrap)(size_t kl, uint8 *key, size_t il, uint8 *input, uint8 *output)
157 uint32 rk[4*(AES_MAXROUNDS+1)];
158 uint8 A[AES_BLOCK_SZ];
159 uint8 R[AKW_MAX_WRAP_LEN + AKW_BLOCK_LEN];
160 uint8 B[AES_BLOCK_SZ];
161 size_t ol = il - AKW_BLOCK_LEN;
162 int n = (int)(ol/AKW_BLOCK_LEN), i, j, k;
164 /* validate kl (must be valid AES key length) */
165 if ((kl != 16) && (kl != 24) && (kl != 32)) {
166 dbg(("aes_wrap: invlaid key length %lu\n", (unsigned long)kl));
167 return (1);
169 if (il > (AKW_MAX_WRAP_LEN + AKW_BLOCK_LEN)) {
170 dbg(("aes_unwrap: input length %lu too large\n", (unsigned long)il));
171 return (1);
173 if (il % AKW_BLOCK_LEN) {
174 dbg(("aes_unwrap: input length %lu must be a multiple of block length\n",
175 (unsigned long)il));
176 return (1);
179 dbg((" Input:\n"));
180 dbg((" KEK: "));
181 for (k = 0; k < (int)kl; k++)
182 dbg(("%02X", key[k]));
183 dbg(("\n Data: "));
184 for (k = 0; k < (int)il; k++)
185 dbg(("%02X", input[k]));
186 dbg(("\n\n Unwrap: \n"));
188 rijndaelKeySetupDec(rk, key, (int)AES_KEY_BITLEN(kl));
190 /* Set A = C[0] */
191 bcopy(input, A, AKW_BLOCK_LEN);
193 /* For i = 1 to n */
194 /* R[i] = C[i] */
195 bcopy(&input[AKW_BLOCK_LEN], R, ol);
197 /* For j = 5 to 0 */
198 for (j = 5; j >= 0; j--) {
199 /* For i = n to 1 */
200 for (i = n - 1; i >= 0; i--) {
201 dbg(("\n %d\n", (n*j)+i+1));
202 pinter(" In ", A, ol, R);
204 /* B = AES - 1 (K, (A ^ t) | R[i]) where t = n * j + i */
205 A[AKW_BLOCK_LEN - 1] ^= ((n*j)+i+1);
206 pinter(" XorT ", A, ol, R);
208 bcopy(&R[i*AKW_BLOCK_LEN], &A[AKW_BLOCK_LEN], AKW_BLOCK_LEN);
209 aes_block_decrypt((int)AES_ROUNDS(kl), rk, A, B);
211 /* A = MSB(64, B) */
212 bcopy(&B[0], &A[0], AKW_BLOCK_LEN);
214 /* R[i] = LSB(64, B) */
215 bcopy(&B[AKW_BLOCK_LEN], &R[i*AKW_BLOCK_LEN], AKW_BLOCK_LEN);
216 pinter(" Dec ", A, ol, R);
219 if (!bcmp(A, aeskeywrapIV, AKW_BLOCK_LEN)) {
220 /* For i = 1 to n */
221 /* P[i] = R[i] */
222 bcopy(R, &output[0], ol);
223 return 0;
224 } else {
225 dbg(("aes_unwrap: IV mismatch in unwrapped data\n"));
226 return 1;
230 #ifdef BCMAESKEYWRAP_TEST
231 #include "aeskeywrap_vectors.h"
232 #define NUM_VECTORS (sizeof(akw_vec)/sizeof(akw_vec[0]))
233 #define NUM_WRAP_FAIL_VECTORS \
234 (sizeof(akw_wrap_fail_vec)/sizeof(akw_wrap_fail_vec[0]))
235 #define NUM_UNWRAP_FAIL_VECTORS \
236 (sizeof(akw_unwrap_fail_vec)/sizeof(akw_unwrap_fail_vec[0]))
238 int main(int argc, char **argv)
240 uint8 output[AKW_MAX_WRAP_LEN+AKW_BLOCK_LEN];
241 uint8 input2[AKW_MAX_WRAP_LEN];
242 int retv, k, fail = 0;
244 for (k = 0; k < NUM_VECTORS; k++) {
245 retv = aes_wrap(akw_vec[k].kl, akw_vec[k].key, akw_vec[k].il,
246 akw_vec[k].input, output);
247 pres("\n AES Wrap: ", akw_vec[k].il+AKW_BLOCK_LEN, output);
249 if (retv) {
250 dbg(("%s: aes_wrap failed\n", *argv));
251 fail++;
253 if (bcmp(output, akw_vec[k].ref, akw_vec[k].il+AKW_BLOCK_LEN) != 0) {
254 dbg(("%s: aes_wrap failed\n", *argv));
255 fail++;
258 retv = aes_unwrap(akw_vec[k].kl, akw_vec[k].key, akw_vec[k].il + AKW_BLOCK_LEN,
259 output, input2);
260 pres("\n AES Unwrap: ", akw_vec[k].il, input2);
262 if (retv) {
263 dbg(("%s: aes_unwrap failed\n", *argv));
264 fail++;
266 if (bcmp(akw_vec[k].input, input2, akw_vec[k].il) != 0) {
267 dbg(("%s: aes_unwrap failed\n", *argv));
268 fail++;
272 for (k = 0; k < NUM_WRAP_FAIL_VECTORS; k++) {
273 if (!aes_wrap(akw_wrap_fail_vec[k].kl, akw_wrap_fail_vec[k].key,
274 akw_wrap_fail_vec[k].il, akw_wrap_fail_vec[k].input, output)) {
275 dbg(("%s: aes_wrap didn't detect failure case\n", *argv));
276 fail++;
280 for (k = 0; k < NUM_UNWRAP_FAIL_VECTORS; k++) {
281 if (!aes_unwrap(akw_unwrap_fail_vec[k].kl, akw_unwrap_fail_vec[k].key,
282 akw_unwrap_fail_vec[k].il, akw_unwrap_fail_vec[k].input, input2)) {
283 dbg(("%s: aes_unwrap didn't detect failure case\n", *argv));
284 fail++;
288 dbg(("%s: %s\n", *argv, fail?"FAILED":"PASSED"));
289 return (fail);
291 #endif /* BCMAESKEYWRAP_TEST */