1/* 2 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. 3 * All rights reserved. 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; if not, write to the Free Software Foundation, Inc., 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * 20 * File: michael.cpp 21 * 22 * Purpose: The implementation of LIST data structure. 23 * 24 * Author: Kyle Hsu 25 * 26 * Date: Sep 4, 2002 27 * 28 * Functions: 29 * s_dwGetUINT32 - Convert from u8[] to u32 in a portable way 30 * s_vPutUINT32 - Convert from u32 to u8[] in a portable way 31 * s_vClear - Reset the state to the empty message. 32 * s_vSetKey - Set the key. 33 * MIC_vInit - Set the key. 34 * s_vAppendByte - Append the byte to our word-sized buffer. 35 * MIC_vAppend - call s_vAppendByte. 36 * MIC_vGetMIC - Append the minimum padding and call s_vAppendByte. 37 * 38 * Revision History: 39 * 40 */ 41 42#include "tmacro.h" 43#include "michael.h" 44 45/* 46 * static u32 s_dwGetUINT32(u8 * p); Get u32 from 47 * 4 bytes LSByte first 48 * static void s_vPutUINT32(u8* p, u32 val); Put u32 into 49 * 4 bytes LSByte first 50 */ 51static void s_vClear(void); /* Clear the internal message, 52 * resets the object to the 53 * state just after construction. */ 54static void s_vSetKey(u32 dwK0, u32 dwK1); 55static void s_vAppendByte(u8 b); /* Add a single byte to the internal 56 * message */ 57 58static u32 L, R; /* Current state */ 59static u32 K0, K1; /* Key */ 60static u32 M; /* Message accumulator (single word) */ 61static unsigned int nBytesInM; /* # bytes in M */ 62 63/* 64static u32 s_dwGetUINT32 (u8 * p) 65// Convert from u8[] to u32 in a portable way 66{ 67 u32 res = 0; 68 unsigned int i; 69 for (i = 0; i < 4; i++) 70 res |= (*p++) << (8*i); 71 return res; 72} 73 74static void s_vPutUINT32(u8 *p, u32 val) 75// Convert from u32 to u8[] in a portable way 76{ 77 unsigned int i; 78 for (i = 0; i < 4; i++) { 79 *p++ = (u8) (val & 0xff); 80 val >>= 8; 81 } 82} 83*/ 84 85static void s_vClear(void) 86{ 87 /* Reset the state to the empty message. */ 88 L = K0; 89 R = K1; 90 nBytesInM = 0; 91 M = 0; 92} 93 94static void s_vSetKey(u32 dwK0, u32 dwK1) 95{ 96 /* Set the key */ 97 K0 = dwK0; 98 K1 = dwK1; 99 /* and reset the message */ 100 s_vClear(); 101} 102 103static void s_vAppendByte(u8 b) 104{ 105 /* Append the byte to our word-sized buffer */ 106 M |= b << (8*nBytesInM); 107 nBytesInM++; 108 /* Process the word if it is full. */ 109 if (nBytesInM >= 4) { 110 L ^= M; 111 R ^= ROL32(L, 17); 112 L += R; 113 R ^= ((L & 0xff00ff00) >> 8) | ((L & 0x00ff00ff) << 8); 114 L += R; 115 R ^= ROL32(L, 3); 116 L += R; 117 R ^= ROR32(L, 2); 118 L += R; 119 /* Clear the buffer */ 120 M = 0; 121 nBytesInM = 0; 122 } 123} 124 125void MIC_vInit(u32 dwK0, u32 dwK1) 126{ 127 /* Set the key */ 128 s_vSetKey(dwK0, dwK1); 129} 130 131void MIC_vUnInit(void) 132{ 133 /* Wipe the key material */ 134 K0 = 0; 135 K1 = 0; 136 137 /* And the other fields as well. */ 138 /* Note that this sets (L,R) to (K0,K1) which is just fine. */ 139 s_vClear(); 140} 141 142void MIC_vAppend(u8 * src, unsigned int nBytes) 143{ 144 /* This is simple */ 145 while (nBytes > 0) { 146 s_vAppendByte(*src++); 147 nBytes--; 148 } 149} 150 151void MIC_vGetMIC(u32 * pdwL, u32 * pdwR) 152{ 153 /* Append the minimum padding */ 154 s_vAppendByte(0x5a); 155 s_vAppendByte(0); 156 s_vAppendByte(0); 157 s_vAppendByte(0); 158 s_vAppendByte(0); 159 /* and then zeroes until the length is a multiple of 4 */ 160 while (nBytesInM != 0) 161 s_vAppendByte(0); 162 /* The s_vAppendByte function has already computed the result. */ 163 *pdwL = L; 164 *pdwR = R; 165 /* Reset to the empty message. */ 166 s_vClear(); 167} 168