1/* 2 * aeskeywrap.c 3 * Perform RFC3394 AES-based key wrap and unwrap functions. 4 * 5 * Copyright (C) 2015, 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. 12 * 13 * $Id: aeskeywrap.c 241182 2011-02-17 21:50:03Z $ 14 */ 15 16#include <typedefs.h> 17 18#ifdef BCMDRIVER 19#include <osl.h> 20#else 21#include <string.h> 22#endif /* BCMDRIVER */ 23 24#include <bcmcrypto/aes.h> 25#include <bcmcrypto/aeskeywrap.h> 26#include <bcmcrypto/rijndael-alg-fst.h> 27 28#ifdef BCMAESKEYWRAP_TEST 29#include <stdio.h> 30 31#define dbg(args) printf args 32 33void 34pinter(const char *label, const uint8 *A, const size_t il, const uint8 *R) 35{ 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(" "); 45 } 46 printf("\n"); 47} 48 49void 50pres(const char *label, const size_t len, const uint8 *data) 51{ 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(" "); 58 } 59 printf("\n"); 60} 61#else 62#define dbg(args) 63#define pinter(label, A, il, R) 64#endif /* BCMAESKEYWRAP_TEST */ 65 66static const uint8 aeskeywrapIV[] = { 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6 }; 67 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 72 */ 73int 74BCMROMFN(aes_wrap)(size_t kl, uint8 *key, size_t il, uint8 *input, uint8 *output) 75{ 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; 81 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); 86 } 87 if (il > AKW_MAX_WRAP_LEN) { 88 dbg(("aes_wrap: input length %lu too large\n", (unsigned long)il)); 89 return (1); 90 } 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); 95 } 96 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")); 105 106 rijndaelKeySetupEnc(rk, key, (int)AES_KEY_BITLEN(kl)); 107 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); 113 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); 123 124 /* R[i] = LSB(64, B) */ 125 memcpy(&R[i*AKW_BLOCK_LEN], &B[AKW_BLOCK_LEN], AKW_BLOCK_LEN); 126 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); 132 } 133 } 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); 139 140 return (0); 141} 142 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 147 */ 148int 149BCMROMFN(aes_unwrap)(size_t kl, uint8 *key, size_t il, uint8 *input, uint8 *output) 150{ 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; 157 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); 162 } 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); 166 } 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); 171 } 172 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")); 181 182 rijndaelKeySetupDec(rk, key, (int)AES_KEY_BITLEN(kl)); 183 184 /* Set A = C[0] */ 185 memcpy(A, input, AKW_BLOCK_LEN); 186 187 /* For i = 1 to n */ 188 /* R[i] = C[i] */ 189 memcpy(R, &input[AKW_BLOCK_LEN], ol); 190 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); 197 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); 201 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); 204 205 /* A = MSB(64, B) */ 206 memcpy(&A[0], &B[0], AKW_BLOCK_LEN); 207 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); 211 } 212 } 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; 221 } 222} 223 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])) 231 232int 233main(int argc, char **argv) 234{ 235 uint8 output[AKW_MAX_WRAP_LEN+AKW_BLOCK_LEN]; 236 uint8 input2[AKW_MAX_WRAP_LEN]; 237 int retv, k, fail = 0; 238 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); 243 244 if (retv) { 245 dbg(("%s: aes_wrap failed\n", *argv)); 246 fail++; 247 } 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++; 251 } 252 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); 256 257 if (retv) { 258 dbg(("%s: aes_unwrap failed\n", *argv)); 259 fail++; 260 } 261 if (memcmp(akw_vec[k].input, input2, akw_vec[k].il) != 0) { 262 dbg(("%s: aes_unwrap failed\n", *argv)); 263 fail++; 264 } 265 } 266 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++; 272 } 273 } 274 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++; 280 } 281 } 282 283 dbg(("%s: %s\n", *argv, fail?"FAILED":"PASSED")); 284 return (fail); 285} 286#endif /* BCMAESKEYWRAP_TEST */ 287