/*
 * 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:
 *
 */

#if !defined(__TMACRO_H__)
#include "tmacro.h"
#endif
#if !defined(__TBIT_H__)
#include "tbit.h"
#endif
#if !defined(__MICHAEL_H__)
#include "michael.h"
#endif

/*---------------------  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();
}

