215 lines
6.8 KiB
C
215 lines
6.8 KiB
C
/*
|
|
******************************************************************************
|
|
* 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 <roger@interpeak.se>
|
|
******************************************************************************
|
|
*/
|
|
|
|
/*
|
|
****************************************************************************
|
|
* 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 <ipcom_type.h>
|
|
#include <ipcom_cstyle.h>
|
|
#include <ipcom_clib.h>
|
|
|
|
#include "ip8021x.h"
|
|
#include "ip8021x_h.h"
|
|
|
|
#ifdef IPMCRYPTO
|
|
#include <ip/openssl/aes.h>
|
|
#else
|
|
#include <openssl/aes.h>
|
|
#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
|
|
****************************************************************************
|
|
*/
|
|
|