linux/drivers/staging/ks7010/michael_mic.c
<<
>>
Prefs
   1/*
   2 *   Driver for KeyStream wireless LAN
   3 *
   4 *   Copyright (C) 2005-2008 KeyStream Corp.
   5 *   Copyright (C) 2009 Renesas Technology Corp.
   6 *
   7 *   This program is free software; you can redistribute it and/or modify
   8 *   it under the terms of the GNU General Public License version 2 as
   9 *   published by the Free Software Foundation.
  10 */
  11
  12#include <linux/types.h>
  13#include <linux/string.h>
  14#include "michael_mic.h"
  15
  16// Rotation functions on 32 bit values
  17#define ROL32( A, n )   ( ((A) << (n)) | ( ((A)>>(32-(n))) & ( (1UL << (n)) - 1 ) ) )
  18#define ROR32( A, n )   ROL32( (A), 32-(n) )
  19// Convert from Byte[] to UInt32 in a portable way
  20#define getUInt32( A, B )       (uint32_t)(A[B+0] << 0) + (A[B+1] << 8) + (A[B+2] << 16) + (A[B+3] << 24)
  21
  22// Convert from UInt32 to Byte[] in a portable way
  23#define putUInt32(A, B, C)                                      \
  24do {                                                            \
  25        A[B + 0] = (uint8_t)(C & 0xff);                         \
  26        A[B + 1] = (uint8_t)((C >> 8) & 0xff);                  \
  27        A[B + 2] = (uint8_t)((C >> 16) & 0xff);                 \
  28        A[B + 3] = (uint8_t)((C >> 24) & 0xff);                 \
  29} while (0)
  30
  31// Reset the state to the empty message.
  32#define MichaelClear(A)                 \
  33do {                                    \
  34        A->L = A->K0;                   \
  35        A->R = A->K1;                   \
  36        A->nBytesInM = 0;               \
  37} while (0)
  38
  39static
  40void MichaelInitializeFunction(struct michel_mic_t *Mic, uint8_t *key)
  41{
  42        // Set the key
  43        Mic->K0 = getUInt32(key, 0);
  44        Mic->K1 = getUInt32(key, 4);
  45
  46        //clear();
  47        MichaelClear(Mic);
  48}
  49
  50#define MichaelBlockFunction(L, R)                              \
  51do{                                                             \
  52        R ^= ROL32( L, 17 );                                    \
  53        L += R;                                                 \
  54        R ^= ((L & 0xff00ff00) >> 8) | ((L & 0x00ff00ff) << 8); \
  55        L += R;                                                 \
  56        R ^= ROL32( L, 3 );                                     \
  57        L += R;                                                 \
  58        R ^= ROR32( L, 2 );                                     \
  59        L += R;                                                 \
  60}while(0)
  61
  62static
  63void MichaelAppend(struct michel_mic_t *Mic, uint8_t *src, int nBytes)
  64{
  65        int addlen;
  66        if (Mic->nBytesInM) {
  67                addlen = 4 - Mic->nBytesInM;
  68                if (addlen > nBytes)
  69                        addlen = nBytes;
  70                memcpy(&Mic->M[Mic->nBytesInM], src, addlen);
  71                Mic->nBytesInM += addlen;
  72                src += addlen;
  73                nBytes -= addlen;
  74
  75                if (Mic->nBytesInM < 4)
  76                        return;
  77
  78                Mic->L ^= getUInt32(Mic->M, 0);
  79                MichaelBlockFunction(Mic->L, Mic->R);
  80                Mic->nBytesInM = 0;
  81        }
  82
  83        while (nBytes >= 4) {
  84                Mic->L ^= getUInt32(src, 0);
  85                MichaelBlockFunction(Mic->L, Mic->R);
  86                src += 4;
  87                nBytes -= 4;
  88        }
  89
  90        if (nBytes > 0) {
  91                Mic->nBytesInM = nBytes;
  92                memcpy(Mic->M, src, nBytes);
  93        }
  94}
  95
  96static
  97void MichaelGetMIC(struct michel_mic_t *Mic, uint8_t *dst)
  98{
  99        uint8_t *data = Mic->M;
 100        switch (Mic->nBytesInM) {
 101        case 0:
 102                Mic->L ^= 0x5a;
 103                break;
 104        case 1:
 105                Mic->L ^= data[0] | 0x5a00;
 106                break;
 107        case 2:
 108                Mic->L ^= data[0] | (data[1] << 8) | 0x5a0000;
 109                break;
 110        case 3:
 111                Mic->L ^= data[0] | (data[1] << 8) | (data[2] << 16) |
 112                    0x5a000000;
 113                break;
 114        }
 115        MichaelBlockFunction(Mic->L, Mic->R);
 116        MichaelBlockFunction(Mic->L, Mic->R);
 117        // The appendByte function has already computed the result.
 118        putUInt32(dst, 0, Mic->L);
 119        putUInt32(dst, 4, Mic->R);
 120
 121        // Reset to the empty message.
 122        MichaelClear(Mic);
 123}
 124
 125void MichaelMICFunction(struct michel_mic_t *Mic, uint8_t *Key,
 126                        uint8_t *Data, int Len, uint8_t priority,
 127                        uint8_t *Result)
 128{
 129        uint8_t pad_data[4] = { priority, 0, 0, 0 };
 130        // Compute the MIC value
 131        /*
 132         * IEEE802.11i  page 47
 133         * Figure 43g TKIP MIC processing format
 134         * +--+--+--------+--+----+--+--+--+--+--+--+--+--+
 135         * |6 |6 |1       |3 |M   |1 |1 |1 |1 |1 |1 |1 |1 | Octet
 136         * +--+--+--------+--+----+--+--+--+--+--+--+--+--+
 137         * |DA|SA|Priority|0 |Data|M0|M1|M2|M3|M4|M5|M6|M7|
 138         * +--+--+--------+--+----+--+--+--+--+--+--+--+--+
 139         */
 140        MichaelInitializeFunction(Mic, Key);
 141        MichaelAppend(Mic, (uint8_t *) Data, 12);       /* |DA|SA| */
 142        MichaelAppend(Mic, pad_data, 4);        /* |Priority|0|0|0| */
 143        MichaelAppend(Mic, (uint8_t *) (Data + 12), Len - 12);  /* |Data| */
 144        MichaelGetMIC(Mic, Result);
 145}
 146