www.pudn.com > bq26100SHA1c_files.rar > bq26100_auth.c, change:2006-10-10,size:16227b


/******************************************************************************/ 
/* bq26100_auth.C: ARM9 based authentication with bq26100                     */ 
/******************************************************************************/ 
/* This file contains the main() and Auth() functions. The main() function    */ 
/* calls the Auth() function so that the microprocessor does the SHA1 HMAC    */ 
/* that is compatible with the bq26100. Once the microprocessor is done       */ 
/* computing the HMAC the main() function calls the SDQ commands necessary to */ 
/* have the bq26100 perform authentication and compare it's results with the  */ 
/* ones of the microprocessor.                                                */ 
/* The LED statuses are the following:                                        */ 
/*        *STEADY GREEN - Authentication Succesful                            */ 
/*        *STEADY RED - Authentication Failed                                 */ 
/*        *BLINKING RED - No device detected								  */ 
/*																			  */ 
/* This code has been implemented using the MCB-STR9 evaluation board which   */ 
/* is based in ST Microelectronics ARM966E Core. 							  */ 
/*                                                                            */ 
/* Written by:																  */ 
/*      Michael A. Vega														  */ 
/*		Applications, Battery Monitor Soultions								  */ 
/*		Texas Instruments, Inc.												  */ 
/*																			  */ 
/******************************************************************************/ 
 
#include <stdlib.h> 
 
 
// Libraries required by STR91x to control GPIOs 
#include "STR91x.h" 
#include "91x_type.h" 
#include "91x_map.h" 
#include "91x_gpio.h" 
#include "91x_scu.h" 
#include "91x_conf.h" 
 
// Header file that declares the functions required to call SDQ routines 
#include "sdq.h" 
 
 
// Required to use the GPIO_InitStruct structure which will be used to initialize the GPIOs 
GPIO_InitTypeDef GPIO_InitStruct; 
 
// Global Variables 
u8 Message[20];			//These are the 20 bytes for the random message	sent to bq26100 
u8 Key[16];				//These are the 16 bytes for the secret key, should match with contents of valid bq26100  
u8 Digest[20];			//These are the 20 bytes for the SHA1 response of the bq26100 
 
 
// The functions used to implement the SHA1 as computed by the microcontroller were 
// developed following the same guidance as described in the "How to Implement SHA-1/HMAC 
// Authentication for bq26100" document. It can be found in www.ti.com by searching SLUA389. 
 
 
// Global Variables for SHA1 
u32 Ws[80];			//Global Work schedule variable 
u32 A; 
u32 B; 
u32 C; 
u32 D; 
u32 E; 
u32 H[5]; 
u32 Random[5];		//The 16 bytes of random message for the bq26100 are contained here 
					//for microcontroller to use in SHA1/HMAC 
u32 Digest_32[5];	//The result of the SHA1/HMAC obtained by the microcontroller is contained here 
 
 
/**********************************************************************/ 
/* 	unsigned long Rotl(unsigned long x, int n)					      */ 
/*																      */ 
/*	Description : 		This procedure is a rotate left n spaces of	  */ 
/*				  		32-bit word x.								  */ 
/* 	Arguments : 		x - word to be rotated						  */ 
/*						n - amount of spaces to rotated to the left   */ 
/*	Global Variables:	None   										  */ 
/*  Returns: 			Result of 32-bit word rotated n times         */ 
/**********************************************************************/ 
u32 Rotl(u32 x, int n){ 
	return (x<<n) |  (x>>(32-n)); 
}	 
 
 
 
/**********************************************************************/ 
/* 	unsigned long W(int t)		                    			      */ 
/*																      */ 
/*	Description : 		This procedure determines the work schedule   */ 
/*				  		for W(16) through W(79)						  */ 
/* 	Arguments : 		t - index of work schedule 16 through 79	  */ 
/*	Global Variables:	Ws[]   										  */ 
/*  Returns: 			Work schedule value with index t              */ 
/**********************************************************************/ 
u32 W(int t){ 
	return Rotl(Ws[t-3] ^ Ws[t-8] ^ Ws[t-14] ^ Ws[t-16], 1); 
}	 
 
/**********************************************************************/ 
/* 	unsigned long K(int t)	 									      */ 
/*																      */ 
/*	Description : 		This procedure selects one of the K values 	  */ 
/*				  		depending on the index t.					  */ 
/* 	Arguments : 		t - index 									  */ 
/*	Global Variables:	None   										  */ 
/*  Returns: 			One of the 4 K values				          */ 
/**********************************************************************/ 
u32 K(int t){ 
	if (t<=19) 
		return 0x5a827999; 
	else if (t>=20 && t<=39) 
		return 0x6ed9eba1; 
	else if (t>=40 && t<=59) 
		return 0x8f1bbcdc; 
	else if (t>=60 && t<=79) 
		return 0xca62c1d6; 
	else 
		return 0;		//Invalid value, not expected 
} 
	 
/*******************************************************************************/ 
/* 	unsigned long f(unsigned long x, unsigned long y, unsigned long z, int t)  */ 
/*																               */ 
/*	Description : 		This procedure selects the ft(b,c,d) function based    */ 
/*				  		on SLUA389 and FIPS 180-2 document. 			           */ 
/* 	Arguments : 		x - b as seen in document						       */ 
/*						y - c as seen in document                              */ 
/*                      z - d as seed in document                              */ 
/*                      t - index											   */ 
/*	Global Variables:	None   										           */ 
/*  Returns: 			Result of ft function                                  */ 
/*******************************************************************************/ 
u32 f(u32 x, u32 y, u32 z, int t){ 
	if (t<=19) 
		return (x & y) ^ ((~x) & z); 
	else if (t>=20 && t<=39) 
		return x ^ y ^ z; 
	else if (t>=40 && t<=59) 
		return (x & y) ^ (x & z) ^ (y & z); 
	else if (t>=60 && t<=79) 
		return x ^ y ^ z; 
	else 
		return 0;       //Invalid value, not expected 
}	 
 
 
 
/**********************************************************************/ 
/* 	void Auth(void)					      							  */ 
/*																      */ 
/*	Description : 		This procedure computes the SHA1/HMAC as 	  */ 
/*				  		required by the bq26100						  */ 
/* 	Arguments : 		i - times that SHA1 is executing			  */ 
/*						t - index 0 through 79						  */ 
/*     					temp - Used to update working variables		  */ 
/*	Global Variables:	Random[], Message[], Key[], Ws[], H[],		  */ 
/*						A, B, C, D, E								  */ 
/*  Returns: 			Result of 32-bit word rotated n times         */ 
/**********************************************************************/  
void Auth(void){ 
	int i;			//Used for doing two times the SHA1 as required by the bq26100 
	int t;			//Used for the indexes 0 through 79 
	u32 temp;		//Used as the temp variable during the loop in which the working 
					//variables A, B, C, D and E are updated 
	 
// The 20 bytes of random message that are given to the bq26100 are arranged in 32-bit words 
// so that the microcontroller can compute the SHA1/HMAC 
	Random[0] = Message[0x10] + Message[0x11]*0x0100 + Message[0x12]*0x010000 + Message[0x13]*0x01000000; 
	Random[1] = Message[0x0C] + Message[0x0D]*0x0100 + Message[0x0E]*0x010000 + Message[0x0F]*0x01000000; 
	Random[2] = Message[0x08] + Message[0x09]*0x0100 + Message[0x0A]*0x010000 + Message[0x0B]*0x01000000; 
	Random[3] = Message[0x04] + Message[0x05]*0x0100 + Message[0x06]*0x010000 + Message[0x07]*0x01000000; 
	Random[4] = Message[0x00] + Message[0x01]*0x0100 + Message[0x02]*0x010000 + Message[0x03]*0x01000000; 
// The SHA1 is computed two times so that it complies with the bq26100 specification 
	for (i=0; i<=1; i++){ 
//Work Schedule 
	// The first four Working schedule variables Ws[0-3], are based on the key that is  
	// implied that the bq26100 contains. 
		Ws[0] = Key[0x0C] + Key[0x0D]*0x0100 + Key[0x0E]*0x010000 + Key[0x0F]*0x01000000; 
		Ws[1] = Key[0x08] + Key[0x09]*0x0100 + Key[0x0A]*0x010000 + Key[0x0B]*0x01000000; 
		Ws[2] = Key[0x04] + Key[0x05]*0x0100 + Key[0x06]*0x010000 + Key[0x07]*0x01000000; 
		Ws[3] = Key[0x00] + Key[0x01]*0x0100 + Key[0x02]*0x010000 + Key[0x03]*0x01000000; 
// On the first run of the SHA1 the random message is used 		 
		if (i==0){ 
			Ws[4] = Random[0]; 
			Ws[5] = Random[1]; 
			Ws[6] = Random[2]; 
			Ws[7] = Random[3]; 
			Ws[8] = Random[4]; 
		} 
// On the second run of the SHA1, H(Kd || M) is used		 
		else{ 
			Ws[4] = H[0]; 
			Ws[5] = H[1]; 
			Ws[6] = H[2]; 
			Ws[7] = H[3]; 
			Ws[8] = H[4]; 
		} 
// The Work schedule variables Ws[9-15] remain the same regardless of which run of the SHA1. 
// These values are as required by bq26100. 
		Ws[9] = 0x80000000; 
		Ws[10] = 0x00000000; 
		Ws[11] = 0x00000000; 
		Ws[12] = 0x00000000; 
		Ws[13] = 0x00000000; 
		Ws[14] = 0x00000000; 
		Ws[15] = 0x00000120; 
 
// The Work schedule variables Ws[16-79] are determined by the W(t) function	 
		for (t = 16; t <= 79; t++) 
			Ws[t]=W(t); 
// Working Variables, always start the same	regardless of which SHA1 run 
		A = 0x67452301; 
		B = 0xefcdab89; 
		C = 0x98badcfe; 
		D = 0x10325476; 
		E = 0xc3d2e1f0; 
// Hash Values, always start the same regardless of what SHA1 run 
		H[0] = A; 
		H[1] = B; 
		H[2] = C; 
		H[3] = D; 
		H[4] = E; 
// Loop to change working variables A, B, C, D and E 
// This is defined by FIPS 180-2 document 
		for (t = 0; t <= 79; t++){ 
			temp = Rotl(A,5) + f(B,C,D,t) + E + K(t) + Ws[t]; 
			E = D; 
			D = C; 
			C = Rotl(B,30); 
			B = A; 
			A = temp; 
		} 
// 160-Bit SHA-1 Digest 
		H[0] = A + H[0]; 
		H[1] = B + H[1]; 
		H[2] = C + H[2]; 
		H[3] = D + H[3]; 
		H[4] = E + H[4]; 
	}//End of for loop 
}	//End Auth() function 
 
/**********************************************************************/ 
/* 	int main(void)					      							  */ 
/*																      */ 
/*	Description : 		This is the main function. It calls the SDQ	  */ 
/*				  		communication and the SHA1 function. Results  */ 
/*						are displayed through LEDs.					  */ 
/* 	Arguments : 		*Value - generic variable for read functions  */ 
/*						i - used for repeat loops				      */ 
/*	Global Variables:	Message[], Key[], Digest[], Digest_32[]		  */ 
/*  Returns: 			None								          */ 
/**********************************************************************/ 
int main (void){ 
	u8 *Value; 
	int i; 
  	 
// Select the key to be used here. In this example 0x3601FCFB12B87356C1548630FD3EA0D2 is used.   
	Key[0] = 0xD2; 
	Key[1] = 0xA0; 
	Key[2] = 0x3E; 
	Key[3] = 0xFD; 
	Key[4] = 0x30; 
	Key[5] = 0x86; 
	Key[6] = 0x54; 
	Key[7] = 0xC1; 
	Key[8] = 0x56; 
	Key[9] = 0x73; 
	Key[10] = 0xB8; 
	Key[11] = 0x12; 
	Key[12] = 0xFB; 
	Key[13] = 0xFC; 
	Key[14] = 0x01; 
	Key[15] = 0x36; 
	 
	 
/*	for (i=0; i<=15; i++){ 
  		Key[i] = 0x00; 
  	} 
*/  
// Create a random message generator and insert here. In this example the message is fixed.  	 
	srand(0); 
	for (i=0; i<=19; i++){ 
		Message[i] = rand()%256; 
  	} 
 
	Auth();	 		//Perform SHA1 authentication through host 
   	 
// Initialize Port 9.3 for SDQ communication 
  	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3; 
  	GPIO_InitStruct.GPIO_Direction = GPIO_PinOutput; 
  	GPIO_InitStruct.GPIO_Type = GPIO_Type_PushPull; 
  	GPIO_InitStruct.GPIO_IPConnected = GPIO_IPConnected_Disable; 
  	GPIO_InitStruct.GPIO_Alternate = GPIO_OutputAlt1; 
  	GPIO_Init(GPIO9, &GPIO_InitStruct); 
 
// Initilaize ports 8.0 and 8.6 for LED driving 
  	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_All; 
  	GPIO_InitStruct.GPIO_Direction = GPIO_PinOutput; 
  	GPIO_InitStruct.GPIO_Type = GPIO_Type_PushPull; 
  	GPIO_InitStruct.GPIO_IPConnected = GPIO_IPConnected_Disable; 
  	GPIO_InitStruct.GPIO_Alternate = GPIO_OutputAlt1; 
  	GPIO_Init(GPIO8, &GPIO_InitStruct); 
 
  	GPIO_Write(GPIO8, 0x00);	//Ensure that all ports of GPIO 8 are low, 
							  	//given that they are connected to LCD and do not want 
							  	//disturb it. 
 
   
// Send 160-bit Message to bq26100 
	SendReset();	   			 
	*Value = TestPresence(); 		//Determine if there is a SDQ compatible device connected 
	if (*Value==0x00){	//No device connected or functional 
		GPIO_WriteBit(GPIO8, GPIO_Pin_0, Bit_RESET); 
		while (1){				 		//Blink red LED at a 0.5 sec on and 0.5 sec off rate 
			GPIO_WriteBit(GPIO8, GPIO_Pin_6, Bit_RESET);  	//Red LED off 
			wait_us(1e6/2);  					  			//wait approximately 0.5 seconds 
			GPIO_WriteBit(GPIO8, GPIO_Pin_6, Bit_SET); 	  	//Red LED on 
			wait_us(1e6/2);									//wait approximately 0.5 seconds 
		} 
	} 
// Skip ROM Command 
	WriteOneByte(0xCC); 
// Write Message Command 
	WriteOneByte(0x22);	//Write Message Command 
// Write Address 
	WriteOneByte(0x00);	//Address Low Byte 
	WriteOneByte(0x00);	//Address High Byte 
// Write first byte of message, Message[0] 
	WriteOneByte(Message[0x00]);	 
	*Value = ReadOneByte();	//Read CRC of Message Command, Address and Data 
	//CRC are not being calculated by the microcontroller, the results given by 
	//bq26100 are being ignored 
// Read Data to Verify Write 
	*Value = ReadOneByte(); 
// Write the remaining bytes of the message 
	for (i=1; i<=19; i++){ 
		WriteOneByte(Message[i]); 
		*Value = ReadOneByte();		//Read CRC 
		*Value = ReadOneByte();		//Read Data 
	} 
 
 
// Write Control to set AUTH bit to initiate Authentication by bq26100 
	SendReset(); 
	*Value = TestPresence(); 
// Skip ROM Command 
	WriteOneByte(0xCC); 
// Write Control Command 
	WriteOneByte(0x77);	//Write Control Command 
// Write Address 
	WriteOneByte(0x00);	//Address Low Byte 
	WriteOneByte(0x00);	//Address High Byte 
// Write Auth Bit of Control Register 
	WriteOneByte(0x01);	 
	*Value = ReadOneByte();	//Read CRC of Write Control Command, Address and Data 
// Read Data to Verify Write 
	*Value = ReadOneByte(); 
 
	 
//Read Digest 
	SendReset(); 
	*Value = TestPresence(); 
// Skip ROM Command 
	WriteOneByte(0xCC); 
// Read Digest Command 
	WriteOneByte(0xDD);	//Read Digest Command 
// Write Address 
	WriteOneByte(0x00);	//Address Low Byte 
	WriteOneByte(0x00);	//Address High Byte 
	*Value = ReadOneByte();	//Read CRC of Read Digest Command, Address 
// Read Digest 
	for (i=0; i<=19; i++){ 
		Digest[i] = ReadOneByte(); 
	} 
// Read CRC of Digest 
	*Value = ReadOneByte(); 
 
// The 20 bytes of the digest returned by the bq26100 is arranged in 32-bit words so that it 
// can be compared with the results computed by the microcontroller 
	Digest_32[4] = Digest[0x00] + Digest[0x01]*0x0100 + Digest[0x02]*0x010000 + Digest[0x03]*0x01000000; 
	Digest_32[3] = Digest[0x04] + Digest[0x05]*0x0100 + Digest[0x06]*0x010000 + Digest[0x07]*0x01000000; 
	Digest_32[2] = Digest[0x08] + Digest[0x09]*0x0100 + Digest[0x0A]*0x010000 + Digest[0x0B]*0x01000000; 
	Digest_32[1] = Digest[0x0C] + Digest[0x0D]*0x0100 + Digest[0x0E]*0x010000 + Digest[0x0F]*0x01000000; 
	Digest_32[0] = Digest[0x10] + Digest[0x11]*0x0100 + Digest[0x12]*0x010000 + Digest[0x13]*0x01000000; 
 
// The results given by microcontroller and bq26100 are compared 
	if (Digest_32[0] == H[0]){ 
		if (Digest_32[1] == H[1]){ 
			if (Digest_32[2] == H[2]){ 
				if (Digest_32[3] == H[3]){ 
					if (Digest_32[4] == H[4]){ 	//If all values are same then Authentication is successful 
						GPIO_WriteBit(GPIO8, GPIO_Pin_0, Bit_SET);		//LED Green on 
						GPIO_WriteBit(GPIO8, GPIO_Pin_6, Bit_RESET); 	//LED Red off 
					} 
					else{						//If any of the values do not match then authentication fails 
						GPIO_WriteBit(GPIO8, GPIO_Pin_6, Bit_SET); 		//LED Red on 
						GPIO_WriteBit(GPIO8, GPIO_Pin_0, Bit_RESET); 	//LED Green off 
					} 
				} 
				else{ 
					GPIO_WriteBit(GPIO8, GPIO_Pin_6, Bit_SET); 			//LED Red on 
					GPIO_WriteBit(GPIO8, GPIO_Pin_0, Bit_RESET);		//LED Green off 
				} 
			}			 
			else{ 
				GPIO_WriteBit(GPIO8, GPIO_Pin_6, Bit_SET); 				//LED Red on 
				GPIO_WriteBit(GPIO8, GPIO_Pin_0, Bit_RESET);			//LED Green off	 
			} 
		} 
		else{ 
			GPIO_WriteBit(GPIO8, GPIO_Pin_6, Bit_SET); 					//LED Red on 
			GPIO_WriteBit(GPIO8, GPIO_Pin_0, Bit_RESET);				//LED Green off 
		} 
	} 
	else{ 
		GPIO_WriteBit(GPIO8, GPIO_Pin_6, Bit_SET); 						//LED Red on 
		GPIO_WriteBit(GPIO8, GPIO_Pin_0, Bit_RESET);					//LED Green off 
	} 
   
}