diff options
author | Wolfram Sang <wsa+renesas@sang-engineering.com> | 2016-05-31 12:56:13 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2016-06-07 22:42:53 -0700 |
commit | 13a9930d15b424ab7d3b906af8ba7ff8c409edfe (patch) | |
tree | ca1490a09b5f633a1cec5014dd360ad5c934f336 /drivers/staging/ks7010/michael_mic.c | |
parent | staging: lustre: set function scope with static (diff) | |
download | linux-dev-13a9930d15b424ab7d3b906af8ba7ff8c409edfe.tar.xz linux-dev-13a9930d15b424ab7d3b906af8ba7ff8c409edfe.zip |
staging: ks7010: add driver from Nanonote extra-repository
See the TODO for details where this driver came from. Only a few minor
changes were made to make the driver suitable for staging:
* updated Kconfig help text and dependencies
* added TODO
* removed two __DATE__ and __TIME__ printouts to allow reproducible builds
* added to staging main Kconfig + Makefile
Tested on a Renesas Salvator-X board with a Spectec SDW-823 card. I
could connect to a WPA-protected network.
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/ks7010/michael_mic.c')
-rw-r--r-- | drivers/staging/ks7010/michael_mic.c | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/drivers/staging/ks7010/michael_mic.c b/drivers/staging/ks7010/michael_mic.c new file mode 100644 index 000000000000..ec8769a97442 --- /dev/null +++ b/drivers/staging/ks7010/michael_mic.c @@ -0,0 +1,143 @@ +/* + * Driver for KeyStream wireless LAN + * + * michael_mic.c + * $Id: michael_mic.c 991 2009-09-14 01:38:58Z sekine $ + * + * Copyright (C) 2005-2008 KeyStream Corp. + * Copyright (C) 2009 Renesas Technology Corp. + * + * This program is free software; you can redistribute it and/or modify + * it undr the terms of the GNU General Public License version 2 as + * published by the Free Sotware Foundation. + */ + +#include <linux/types.h> +#include <linux/string.h> +#include "michael_mic.h" + +// Rotation functions on 32 bit values +#define ROL32( A, n ) ( ((A) << (n)) | ( ((A)>>(32-(n))) & ( (1UL << (n)) - 1 ) ) ) +#define ROR32( A, n ) ROL32( (A), 32-(n) ) +// Convert from Byte[] to UInt32 in a portable way +#define getUInt32( A, B ) (uint32_t)(A[B+0] << 0) + (A[B+1] << 8) + (A[B+2] << 16) + (A[B+3] << 24) + +// Convert from UInt32 to Byte[] in a portable way +#define putUInt32( A, B, C ) A[B+0] = (uint8_t) (C & 0xff); \ + A[B+1] = (uint8_t) ((C>>8) & 0xff); \ + A[B+2] = (uint8_t) ((C>>16) & 0xff); \ + A[B+3] = (uint8_t) ((C>>24) & 0xff) + +// Reset the state to the empty message. +#define MichaelClear( A ) A->L = A->K0; \ + A->R = A->K1; \ + A->nBytesInM = 0; + +static +void MichaelInitializeFunction( struct michel_mic_t *Mic, uint8_t *key ) +{ + // Set the key + Mic->K0 = getUInt32( key , 0 ); + Mic->K1 = getUInt32( key , 4 ); + + //clear(); + MichaelClear(Mic); +} + +#define MichaelBlockFunction(L, R) \ +do{ \ + R ^= ROL32( L, 17 ); \ + L += R; \ + R ^= ((L & 0xff00ff00) >> 8) | ((L & 0x00ff00ff) << 8); \ + L += R; \ + R ^= ROL32( L, 3 ); \ + L += R; \ + R ^= ROR32( L, 2 ); \ + L += R; \ +}while(0) + + +static +void MichaelAppend( struct michel_mic_t *Mic, uint8_t *src, int nBytes ) +{ + int addlen ; + if (Mic->nBytesInM) { + addlen = 4 - Mic->nBytesInM; + if (addlen > nBytes) + addlen = nBytes; + memcpy(&Mic->M[Mic->nBytesInM], src, addlen); + Mic->nBytesInM += addlen; + src += addlen; + nBytes -= addlen; + + if (Mic->nBytesInM < 4) + return; + + Mic->L ^= getUInt32(Mic->M,0); + MichaelBlockFunction(Mic->L, Mic->R); + Mic->nBytesInM = 0; + } + + while(nBytes >= 4){ + Mic->L ^= getUInt32(src,0); + MichaelBlockFunction(Mic->L, Mic->R); + src += 4; + nBytes -= 4; + } + + if (nBytes > 0) { + Mic->nBytesInM = nBytes; + memcpy(Mic->M, src, nBytes); + } +} + +static +void MichaelGetMIC( struct michel_mic_t *Mic, uint8_t *dst ) +{ + uint8_t *data = Mic->M; + switch (Mic->nBytesInM) { + case 0: + Mic->L ^= 0x5a; + break; + case 1: + Mic->L ^= data[0] | 0x5a00; + break; + case 2: + Mic->L ^= data[0] | (data[1] << 8) | 0x5a0000; + break; + case 3: + Mic->L ^= data[0] | (data[1] << 8) | (data[2] << 16) | + 0x5a000000; + break; + } + MichaelBlockFunction(Mic->L, Mic->R); + MichaelBlockFunction(Mic->L, Mic->R); + // The appendByte function has already computed the result. + putUInt32( dst, 0, Mic->L ); + putUInt32( dst, 4, Mic->R ); + + // Reset to the empty message. + MichaelClear(Mic); +} + +void MichaelMICFunction( struct michel_mic_t *Mic, uint8_t *Key, + uint8_t *Data, int Len, uint8_t priority, + uint8_t *Result ) +{ + uint8_t pad_data[4] = {priority,0,0,0}; + // Compute the MIC value + /* + * IEEE802.11i page 47 + * Figure 43g TKIP MIC processing format + * +--+--+--------+--+----+--+--+--+--+--+--+--+--+ + * |6 |6 |1 |3 |M |1 |1 |1 |1 |1 |1 |1 |1 | Octet + * +--+--+--------+--+----+--+--+--+--+--+--+--+--+ + * |DA|SA|Priority|0 |Data|M0|M1|M2|M3|M4|M5|M6|M7| + * +--+--+--------+--+----+--+--+--+--+--+--+--+--+ + */ + MichaelInitializeFunction( Mic, Key ) ; + MichaelAppend( Mic, (uint8_t*)Data, 12 ); /* |DA|SA| */ + MichaelAppend( Mic, pad_data, 4 ); /* |Priority|0|0|0| */ + MichaelAppend( Mic, (uint8_t*)(Data+12), Len -12 ); /* |Data| */ + MichaelGetMIC( Mic, Result ) ; +} |