GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / bcmcrypto / aeskeywrap.c
blobb1797d39c6aeee6376ca72bcd59f54b485c3f70a
1 /*
2 * aeskeywrap.c
3 * Perform RFC3394 AES-based key wrap and unwrap functions.
5 * Copyright (C) 2012, 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 241182 2011-02-17 21:50:03Z $
16 #include <typedefs.h>
18 #ifdef BCMDRIVER
19 #include <osl.h>
20 #else
21 #include <string.h>
22 #endif /* BCMDRIVER */
24 #include <bcmcrypto/aes.h>
25 #include <bcmcrypto/aeskeywrap.h>
26 #include <bcmcrypto/rijndael-alg-fst.h>
28 #ifdef BCMAESKEYWRAP_TEST
29 #include <stdio.h>
31 #define dbg(args) printf args
33 void
34 pinter(const char *label, const uint8 *A, const size_t il, const uint8 *R)
36 unsigned int k;
37 printf("%s", label);
38 for (k = 0; k < AKW_BLOCK_LEN; k++)
39 printf("%02X", A[k]);
40 printf(" ");
41 for (k = 0; k < il; k++) {
42 printf("%02X", R[k]);
43 if (!((k+1)%AKW_BLOCK_LEN))
44 printf(" ");
46 printf("\n");
49 void
50 pres(const char *label, const size_t len, const uint8 *data)
52 unsigned int k;
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))
57 printf(" ");
59 printf("\n");
61 #else
62 #define dbg(args)
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
70 * input is il bytes
71 * output is (il+8) bytes
73 int
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));
85 return (1);
87 if (il > AKW_MAX_WRAP_LEN) {
88 dbg(("aes_wrap: input length %lu too large\n", (unsigned long)il));
89 return (1);
91 if (il % AKW_BLOCK_LEN) {
92 dbg(("aes_wrap: input length %lu must be a multiple of block length\n",
93 (unsigned long)il));
94 return (1);
97 dbg((" Input:\n"));
98 dbg((" KEK: "));
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));
108 /* Set A = IV */
109 memcpy(A, aeskeywrapIV, AKW_BLOCK_LEN);
110 /* For i = 1 to n */
111 /* R[i] = P[i] */
112 memcpy(R, input, il);
114 /* For j = 0 to 5 */
115 for (j = 0; j < 6; j++) {
116 /* For i = 1 to n */
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);
134 /* Set C[0] = A */
135 memcpy(output, A, AKW_BLOCK_LEN);
136 /* For i = 1 to n */
137 /* C[i] = R[i] */
138 memcpy(&output[AKW_BLOCK_LEN], R, il);
140 return (0);
143 /* aes_unwrap: perform AES-based key unwrap function defined in RFC3394,
144 * return 0 on success, 1 on error
145 * input is il bytes
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));
161 return (1);
163 if (il > (AKW_MAX_WRAP_LEN + AKW_BLOCK_LEN)) {
164 dbg(("aes_unwrap: input length %lu too large\n", (unsigned long)il));
165 return (1);
167 if (il % AKW_BLOCK_LEN) {
168 dbg(("aes_unwrap: input length %lu must be a multiple of block length\n",
169 (unsigned long)il));
170 return (1);
173 dbg((" Input:\n"));
174 dbg((" KEK: "));
175 for (k = 0; k < (int)kl; k++)
176 dbg(("%02X", key[k]));
177 dbg(("\n Data: "));
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));
184 /* Set A = C[0] */
185 memcpy(A, input, AKW_BLOCK_LEN);
187 /* For i = 1 to n */
188 /* R[i] = C[i] */
189 memcpy(R, &input[AKW_BLOCK_LEN], ol);
191 /* For j = 5 to 0 */
192 for (j = 5; j >= 0; j--) {
193 /* For i = n to 1 */
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);
205 /* A = MSB(64, 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)) {
214 /* For i = 1 to n */
215 /* P[i] = R[i] */
216 memcpy(&output[0], R, ol);
217 return 0;
218 } else {
219 dbg(("aes_unwrap: IV mismatch in unwrapped data\n"));
220 return 1;
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);
244 if (retv) {
245 dbg(("%s: aes_wrap failed\n", *argv));
246 fail++;
248 if (memcmp(output, akw_vec[k].ref, akw_vec[k].il+AKW_BLOCK_LEN) != 0) {
249 dbg(("%s: aes_wrap failed\n", *argv));
250 fail++;
253 retv = aes_unwrap(akw_vec[k].kl, akw_vec[k].key, akw_vec[k].il + AKW_BLOCK_LEN,
254 output, input2);
255 pres("\n AES Unwrap: ", akw_vec[k].il, input2);
257 if (retv) {
258 dbg(("%s: aes_unwrap failed\n", *argv));
259 fail++;
261 if (memcmp(akw_vec[k].input, input2, akw_vec[k].il) != 0) {
262 dbg(("%s: aes_unwrap failed\n", *argv));
263 fail++;
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));
271 fail++;
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));
279 fail++;
283 dbg(("%s: %s\n", *argv, fail?"FAILED":"PASSED"));
284 return (fail);
286 #endif /* BCMAESKEYWRAP_TEST */