/*
 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 *
 * File: michael.cpp
 *
 * Purpose: The implementation of LIST data structure.
 *
 * Author: Kyle Hsu
 *
 * Date: Sep 4, 2002
 *
 * Functions:
 *      s_dwGetUINT32 - Convert from BYTE[] to DWORD in a portable way
 *      s_vPutUINT32 - Convert from DWORD to BYTE[] in a portable way
 *      s_vClear - Reset the state to the empty message.
 *      s_vSetKey - Set the key.
 *      MIC_vInit - Set the key.
 *      s_vAppendByte - Append the byte to our word-sized buffer.
 *      MIC_vAppend - call s_vAppendByte.
 *      MIC_vGetMIC - Append the minimum padding and call s_vAppendByte.
 *
 * Revision History:
 *
 */

#include "tmacro.h"
#include "michael.h"

/*---------------------  Static Definitions -------------------------*/

/*---------------------  Static Variables  --------------------------*/

/*---------------------  Static Functions  --------------------------*/
/*
static DWORD s_dwGetUINT32(BYTE * p);         // Get DWORD from 4 bytes LSByte first
static void s_vPutUINT32(BYTE* p, DWORD val); // Put DWORD into 4 bytes LSByte first
*/
static void s_vClear(void);                       // Clear the internal message,
                                              // resets the object to the state just after construction.
static void s_vSetKey(DWORD dwK0, DWORD dwK1);
static void s_vAppendByte(BYTE b);            // Add a single byte to the internal message

/*---------------------  Export Variables  --------------------------*/
static DWORD  L, R;           // Current state

static DWORD  K0, K1;         // Key
static DWORD  M;              // Message accumulator (single word)
static UINT   nBytesInM;      // # bytes in M

/*---------------------  Export Functions  --------------------------*/

/*
static DWORD s_dwGetUINT32 (BYTE * p)
// Convert from BYTE[] to DWORD in a portable way
{
    DWORD res = 0;
    UINT i;
    for(i=0; i<4; i++ )
    {
        res |= (*p++) << (8*i);
    }
    return res;
}

static void s_vPutUINT32 (BYTE* p, DWORD val)
// Convert from DWORD to BYTE[] in a portable way
{
    UINT i;
    for(i=0; i<4; i++ )
    {
        *p++ = (BYTE) (val & 0xff);
        val >>= 8;
    }
}
*/

static void s_vClear (void)
{
    // Reset the state to the empty message.
    L = K0;
    R = K1;
    nBytesInM = 0;
    M = 0;
}

static void s_vSetKey (DWORD dwK0, DWORD dwK1)
{
    // Set the key
    K0 = dwK0;
    K1 = dwK1;
    // and reset the message
    s_vClear();
}

static void s_vAppendByte (BYTE b)
{
    // Append the byte to our word-sized buffer
    M |= b << (8*nBytesInM);
    nBytesInM++;
    // Process the word if it is full.
    if( nBytesInM >= 4 )
    {
        L ^= M;
        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;
        // Clear the buffer
        M = 0;
        nBytesInM = 0;
    }
}

void MIC_vInit (DWORD dwK0, DWORD dwK1)
{
    // Set the key
    s_vSetKey(dwK0, dwK1);
}


void MIC_vUnInit (void)
{
    // Wipe the key material
    K0 = 0;
    K1 = 0;

    // And the other fields as well.
    //Note that this sets (L,R) to (K0,K1) which is just fine.
    s_vClear();
}

void MIC_vAppend (PBYTE src, UINT nBytes)
{
    // This is simple
    while (nBytes > 0)
    {
        s_vAppendByte(*src++);
        nBytes--;
    }
}

void MIC_vGetMIC (PDWORD pdwL, PDWORD pdwR)
{
    // Append the minimum padding
    s_vAppendByte(0x5a);
    s_vAppendByte(0);
    s_vAppendByte(0);
    s_vAppendByte(0);
    s_vAppendByte(0);
    // and then zeroes until the length is a multiple of 4
    while( nBytesInM != 0 )
    {
        s_vAppendByte(0);
    }
    // The s_vAppendByte function has already computed the result.
    *pdwL = L;
    *pdwR = R;
    // Reset to the empty message.
    s_vClear();
}

