/* ****************************************************************************** * INTERPEAK SOURCE FILE * * Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ip8021x_aes.c,v $ $Revision: 1.3.40.1 $ * $Source: /home/interpeak/CVSRoot/ip8021x/src/ip8021x_aes.c,v $ * $Author: hxu4 $ * $State: Exp $ $Locker: $ * * INTERPEAK_COPYRIGHT_STRING * Design and implementation by Roger Boden ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* 802.11i specifies that AES keys shall be encrypted using the AES key wrap algorithm, defined in rfc 3394. The following notation is used in the description of the key wrapping algorithms: AES(K, W) Encrypt W using the AES codebook with key K AES-1(K, W) Decrypt W using the AES codebook with key K MSB(j, W) Return the most significant j bits of W LSB(j, W) Return the least significant j bits of W B1 ^ B2 The bitwise exclusive or (XOR) of B1 and B2 B1 | B2 Concatenate B1 and B2 K The key-encryption key K n The number of 64-bit key data blocks s The number of steps in the wrapping process, s = 6n P[i] The ith plaintext key data block C[i] The ith ciphertext data block A The 64-bit integrity check register R[i] An array of 64-bit registers where i = 0, 1, 2, ..., n A[t], R[i][t] The contents of registers A and R[i] after encryption step t. IV The 64-bit initial value used during the wrapping process. */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ #include "ip8021x_config.h" /* **************************************************************************** * 3 INCLUDE FILES **************************************************************************** */ #define IPCOM_USE_CLIB_PROTO #include #include #include #include "ip8021x.h" #include "ip8021x_h.h" #ifdef IPMCRYPTO #include #else #include #endif /* **************************************************************************** * 4 DEFINES **************************************************************************** */ /* **************************************************************************** * 5 TYPES **************************************************************************** */ /* **************************************************************************** * 6 EXTERN PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 7 LOCAL PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 8 DATA **************************************************************************** */ /* **************************************************************************** * 9 STATIC FUNCTIONS **************************************************************************** */ /* **************************************************************************** * 10 GLOBAL FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ip8021x_aes_key_unwrap *=========================================================================== * Description: This function implements the AES key unwrap algorithm as * specified in rfc 3394. This implementation is based on the * index based operation. All parameter have the same name as * in rfc 3394. * Note: this implementation only supports n <= 42. However, * in WPA n is always 2 so this should be a problem. * Parameters: K - the key encryption key * n - the number of 64-bit key data blocks * C - the cipher text data blocks * P - the plain text data blocks * Returns: * IPCOM_SUCCESS - if the key was successfully unwrapped * IPCOM_ERR_FAILED - in case the integrity check fails * IPCOM_ERR_INVALID_ARG - if n>42 */ IP_GLOBAL Ip_err ip8021x_aes_key_unwrap(const Ip_u8 *K, int n, const Ip_u8 *C, Ip_u8 *P) { Ip_u8 A[8]; Ip_u8 *R; Ip_u8 B[16]; int i; int j; AES_KEY key; if (n > 42) { IP_PANIC(); return IPCOM_ERR_INVALID_ARG; } (void)AES_set_decrypt_key(K, 128, &key); /* 1) Initialize variables. * Set A = C[0] * For i = 1 to n * R[i] = C[i] */ ipcom_memcpy(A, C, 8); R = P; /* Use plain buffer as R, will save us a malloc/free and a memcpy in 3 below. */ ipcom_memcpy(R, C + 8, 8 * n); /* 2) Compute intermediate values. * For j = 5 to 0 * For i = n to 1 * B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i * A = MSB(64, B) * R[i] = LSB(64, B) */ for (j = 5; j >= 0; j--) { R = P + (n - 1) * 8; for (i = n; i >= 1; i--) { ipcom_memcpy(B, A, 8); /* (A ^ t), t can maximum be 6n (5*n+n). If n<=42 then t<256 and only b[7] will * be affected by the xor operation */ B[7] ^= n * j + i; ipcom_memcpy(B + 8, R, 8); AES_decrypt(B, B, &key); ipcom_memcpy(A, B, 8); ipcom_memcpy(R, B + 8, 8); R -= 8; } } /* 3) Output results. * * The unwrapped key is already in P, since we set R=P above. * Verify the integrity check register. */ for (i = 0; i < 8; i++) { if (A[i] != 0xa6) return IPCOM_ERR_FAILED; } return IPCOM_SUCCESS; } /* **************************************************************************** * 11 PUBLIC FUNCTIONS **************************************************************************** */ /* **************************************************************************** * END OF FILE **************************************************************************** */