Files
m241Neelima/vxworks-6.9/target/src/drv/wlan/dot11CryptoLib.c
T
2026-07-30 11:19:44 +05:30

425 lines
14 KiB
C

/* dot11CryptoLib.c - Encrypt/Decrypt functions for wireless framework */
/*
* Copyright (c) 2010 Wind River Systems, Inc.
*
* The right to copy, distribute, modify or otherwise make use
* of this software may be licensed only pursuant to the terms
* of an applicable Wind River license agreement.
*/
/*
Modification History
--------------------
02a,02mar10,kr Initial version
*/
/*
DESCRIPTION
This module contains functions for computing AES key wrap and unwrap:
- depends on openssl for the AES encryption;
- code adapted from the file ipcrypto_aeskeywrap.c.
This module also contains functions for computing RC4-TKIP encryption/decryption:
- does not depend on any library;
- code adapted from the CCI library (cci_DefaultCipherRC4TKIP.c).
\NOMANUAL
*/
#include <vxWorks.h>
#include <stdio.h>
#include <openssl/aes.h>
#include "drv/wlan/dot11Lib.h"
#include "drv/wlan/dot11RsnLib.h"
#define LOGERROR(__s) DOT11_LOG(DOT11_DEBUG_ERROR, DOT11_AREA_RSN, \
(__s "\n", 0,0,0,0,0,0))
#define AESKW_BLOCKSIZE 8
#define AES_BLOCKSIZE 16
#define AES_KEY_128_BYTES 16
#define AES_KEY_192_BYTES 24
#define AES_KEY_256_BYTES 32
#define AES_CHECK_KEYLEN(len) ((len==AES_KEY_128_BYTES)||(len==AES_KEY_192_BYTES)||(len==AES_KEY_256_BYTES))
#define AESKW_WRAP_MIN_BLOCK 2
#define AESKW_UNWRAP_MIN_BLOCK (AESKW_WRAP_MIN_BLOCK+1)
#define AESKW_XOR_BLOCK(out, in1, in2) {int ijk;for( ijk = 0; ijk < AESKW_BLOCKSIZE; ijk++ ) out[ijk] = in1[ijk] ^ in2[ijk];}
#define AESKW_CVT(b,n) {memset(b,0,AESKW_BLOCKSIZE);b[AESKW_BLOCKSIZE-1] = ((n)&0xFF);b[AESKW_BLOCKSIZE-2] = (((n)&0xFF00)>>8);\
b[AESKW_BLOCKSIZE-3] = (((n)&0xFF0000)>>16);b[AESKW_BLOCKSIZE-4] = (((n)&0xFF000000)>>24);}
/***************************************************************************
*
* dot11CryptoAesKeyWrap
*
* Description: Encrypt (wrap) a key using AES-KEYWRAP
* Parameters: key - pointer to key buffer
* keyLength - length of key, must be 128 bit, 192 bit or 256 bit (in bytes)
* iv - pointer to IV.
* ivLength - length of IV. Must be AESKW_BLOCKSIZE
* plainText - pointer to buffer to encrypt (wrap)
* plainTextLength - length of buffer to encrypt. Must be multiple of AESKW_BLOCKSIZE
* cipherText - pointer to buffer in which to copy output
* cipherTextLength - pointer to the length of the cipherText buffer. On output,
* this is updated to the length of data copied into the cipherText buffer
* Returns: OK or ERROR
*
*/
STATUS dot11CryptoAesKeyWrap(UINT8 *key, int keyLength,
UINT8 *iv, int ivLength,
UINT8 *plainText, int plainTextLength,
UINT8 *cipherText, UINT32 *cipherTextLength )
{
STATUS status = OK;
AES_KEY aesKey;
/*
** --- Check for proper key length
*/
if (AES_CHECK_KEYLEN(keyLength))
{
/*
** --- Check for proper IV length
*/
if (ivLength == AESKW_BLOCKSIZE)
{
/*
** --- Make sure the input is aligned to 64-bit boundaries
*/
if ( !(plainTextLength % AESKW_BLOCKSIZE) )
{
/*
** --- Make sure the output buffer is at least
** one block (64-bits) larger than the input.
*/
if (*cipherTextLength >= (plainTextLength+AESKW_BLOCKSIZE))
{
int numBlocks = plainTextLength/AESKW_BLOCKSIZE;
UINT8 *R;
UINT8 A[AESKW_BLOCKSIZE];
UINT8 B[AES_BLOCKSIZE];
UINT8 T[AESKW_BLOCKSIZE];
int i,j;
if (numBlocks >= AESKW_WRAP_MIN_BLOCK)
{
/*
** --- Set output buffer size
*/
*cipherTextLength = plainTextLength+AESKW_BLOCKSIZE;
/*
** --- Initialize variables
**
** Set A = IV, an initial value (see 2.2.3)
** For i = 1 to n
** R[i] = P[i]
*/
memcpy(A, iv, AESKW_BLOCKSIZE);
R = cipherText + AESKW_BLOCKSIZE;
memcpy( R, plainText, plainTextLength );
if ( -1 == AES_set_encrypt_key(key, keyLength << 3,&aesKey)) {
LOGERROR("AES_set_encrypt_key failed");
return ERROR;
}
for ( j = 0; j < 6; j++ )
{
for ( i = 0; i < numBlocks; i++ )
{
/*
** --- Do: B = AES(K, A | R[i])
** --- Do: R[i] = LSB(64, B)
*/
memcpy( B + AESKW_BLOCKSIZE, R + (i * AESKW_BLOCKSIZE), AESKW_BLOCKSIZE);
memcpy( B, A, AESKW_BLOCKSIZE);
AES_ecb_encrypt(B,B, &aesKey,AES_ENCRYPT);
/* ccip_aes_encrypt( CCI_MODE_ECB, key, keyLength, B, AES_BLOCKSIZE, B, NULL ); */
memcpy( A, B, AESKW_BLOCKSIZE);
memcpy( R + (i * AESKW_BLOCKSIZE), B + AESKW_BLOCKSIZE, AESKW_BLOCKSIZE);
/*
** --- Do: A = MSB(64, B) ^ t where t = (n*j)+i
*/
AESKW_CVT(T,(numBlocks*j)+(i+1));
AESKW_XOR_BLOCK(A,T,A);
}
}
/*
** --- Do: Set C[0] = A
*/
memcpy( cipherText, A, AESKW_BLOCKSIZE);
}
else
{
status = ERROR;
LOGERROR("Keywrap: outputBuffer too small\n");
}
}
else
{
status = ERROR;
LOGERROR("Keywrap: message too short\n");
}
}
else
{
status = ERROR;
LOGERROR("Keywrap: input buffer not a multiple of the blocksize");
}
}
else
{
status = ERROR;
LOGERROR("Keywrap: invalid blocksize");
}
}
else
{
status = ERROR;
LOGERROR("Keywrap: invalid keylength");
}
return( status );
}
/***************************************************************************
*
* dot11CryptoAesKeyUnwrap
*
* Description: Decrypt (unwrap) a key using AES-KEYWRAP
* Parameters: key - pointer to key buffer
* keyLength - length of key, must be 128 bit, 192 bit or 256 bit (in bytes)
* iv - pointer to IV.
* ivLength - length of IV. Must be AESKW_BLOCKSIZE
* cipherText - pointer to buffer to decrypt (unwrap)
* cipherTextLength - length of buffer to decrypt. Must be multiple of AESKW_BLOCKSIZE
* plainText - pointer to buffer in which to copy output
* plainTextLength - pointer to the length of the plainText buffer. On output,
* this is updated to the length of data copied into the plainText buffer
* Returns: OK or ERROR
*
*/
STATUS dot11CryptoAesKeyUnwrap(UINT8 *key, int keyLength,
UINT8 *iv, int ivLength,
UINT8 *cipherText, int cipherTextLength,
UINT8 *plainText, UINT32 *plainTextLength)
{
STATUS status = OK;
AES_KEY aesKey;
/*
** --- Check for proper key length
*/
if (AES_CHECK_KEYLEN(keyLength))
{
/*
** --- Check for proper IV length
*/
if (ivLength == AESKW_BLOCKSIZE)
{
/*
** --- Make sure the input is aligned to 64-bit boundaries
*/
if ( !(cipherTextLength % AESKW_BLOCKSIZE) )
{
/*
** --- Make sure the output buffer is at least
** one block (64-bits) smaller than the input
*/
if (*plainTextLength >= (cipherTextLength-AESKW_BLOCKSIZE))
{
int numBlocks = (cipherTextLength/AESKW_BLOCKSIZE)-1;
UINT8 *R, *A;
UINT8 B[AES_BLOCKSIZE];
UINT8 T[AESKW_BLOCKSIZE];
int i,j;
if ((numBlocks+1) >= AESKW_UNWRAP_MIN_BLOCK)
{
/*
** --- Set output buffer size
*/
*plainTextLength = cipherTextLength-AESKW_BLOCKSIZE;
/*
** --- Initialize variables
**
** Set A = C[0]
** For i = 1 to n
** R[i] = C[i]
*/
A = cipherText;
R = plainText;
memcpy( R, cipherText + AESKW_BLOCKSIZE, cipherTextLength-AESKW_BLOCKSIZE );
if ( -1 == AES_set_decrypt_key(key, keyLength << 3,&aesKey)) {
LOGERROR("AES_set_decrypt_key failed");
return ERROR;
}
for ( j = 6; j > 0; j-- )
{
for ( i = numBlocks; i > 0; i-- )
{
/*
** --- Do: (A ^ t)
*/
AESKW_CVT(T,((numBlocks)*(j-1))+(i));
AESKW_XOR_BLOCK(A,T,A);
/*
** --- Do: B = AES(K, A | R[i])
** --- Do: R[i] = LSB(64, B)
*/
memcpy( B + AESKW_BLOCKSIZE, R + ((i-1) * AESKW_BLOCKSIZE), AESKW_BLOCKSIZE);
memcpy( B, A, AESKW_BLOCKSIZE);
AES_ecb_encrypt(B, B,&aesKey, AES_DECRYPT);
memcpy( A, B, AESKW_BLOCKSIZE);
memcpy( R + ((i-1) * AESKW_BLOCKSIZE), B + AESKW_BLOCKSIZE, AESKW_BLOCKSIZE);
}
}
/*
** --- Make sure the first block is equal to the IV
*/
if (memcmp( A, iv, AESKW_BLOCKSIZE))
{
status = ERROR;
LOGERROR("Keyunwrap: decoding error");
}
}
else
{
LOGERROR("Keyunwrap:message too short");
status = ERROR;
}
}
else
{
status = ERROR;
LOGERROR("keyunwrap: output buffer too small");
}
}
else
{
LOGERROR("keyunwrap: input buffer not a multiple of the blocksize");
status = ERROR;
}
}
else
{
LOGERROR("keyunwrap: invalid iv length");
status = ERROR;
}
}
else
{
LOGERROR("invalid key length");
status = ERROR;
}
return( status );
}
/***************************************************************************
*
* dot11CryptoRc4 - Encrypts the given data using RC4
*
* RETURNS: OK or ERROR
*
*/
STATUS dot11CryptoRc4(
UINT8* key, /* Key to encrypt data with */
int keyLen, /* Length (in bytes) of the key */
int keyStreamOffset, /* Number of bytes to discard from start of KS */
UINT8 *inputData, /* Pointer to data to be encrypted */
UINT32 inputLength, /* Length of the data */
UINT8 *outputData, /* Pointer to result buffer */
UINT32 *outputDataLen /* I/O arg: len of outputData, set to len of result */
)
{
UINT8 swap; /* Temporary variable used to swap values in s-box*/
int loop, i, j; /* Counter variables */
int t; /* Temporary storage */
UINT8 K; /* Pseudo-random number to encrypt current byte */
UINT8 s[256]; /* Initial s-box for keystream */
UINT8 k[256]; /* Key array. */
if( *outputDataLen < inputLength )
{
return ERROR;
}
/* Fill up the arrays to starting values. S-box is numbered 0 - 255
and the key array is filled with the key, repeated over and over */
for (i=0; i<256; i++)
{
s[i] = i;
k[i] = key[i % keyLen];
}
/* Set up the s-table */
j = 0;
for (i=0; i<256; i++)
{
j = (j + s[i] + k[i]) & 0xff;
swap = s[i];
s[i] = s[j];
s[j] = swap;
}
i = j = 0;
/* Discard the first bytes of the keystream, if desired */
for (loop=0; loop < keyStreamOffset; loop++)
{
i = (i + 1) & 0xff;
j = (j + s[i]) & 0xff;
swap = s[i];
s[i] = s[j];
s[j] = swap;
t = (s[i] + s[j]) & 0xff;
K = s[t];
/* Do nothing with K */
}
/* Stream through the data, getting a different pseudo-random number
from the key-stream and XORing it with the data */
for (loop = 0; loop < inputLength; loop ++)
{
i = (i + 1) & 0xff;
j = (j + s[i]) & 0xff;
swap = s[i];
s[i] = s[j];
s[j] = swap;
t = (s[i] + s[j]) & 0xff;
K = s[t];
/*inputData[loop] ^= K;*/
outputData[loop] = inputData[loop] ^ K;
}
*outputDataLen = inputLength;
return OK;
}