This is my Fourth week working in AESTE and i got my PAY!!! Woots~ I’m starting to get comfortable and used to the working environment here, everyday having something to look forward to is really fun. Well for this week I continue on the topic about implementing HOTP. SHA1 calculation was successfully tested and very straight forward to implement just type the following code (with HASHES.c and HASHES.h library included)

BYTE TEST1[] = “abc”;
HASH_SUM sha;
SHA1Initialize(&sha);
//HashAddData(&sha,”abc”, 3); //not recommended for C18 compiler
HashAddData(&sha, (const unsigned char *) TEST1, strlen(TEST1)); //preferred method
SHA1Calculate(&sha, Message_Digest);

Then all the 20byte hash value will be stored in Message_Digest[] in the form of HEX. To extract it one by one

static char hex_tmp[20];

for(i=0;i<20;i++)
{
sprintf(&hex_tmp[i*2],”%02X”, Message_Digest[i]);
}

Next would be to upgrade SHA1 calculation into an HMAC-SHA1, a keyed-hash message authentication code (HMAC) involves combining a secret cryptographic key with hash function (SHA1). The main reason is to have an additional KEY to the SHA1 hash function. Follow this document RFC2104 to implement HMAC-SHA1. However the result of HMAC-SHA1 will still be in the form of 20bytes HEX value and for HOTP only minimum 6decimal digit is desired. Therefore this long hash value needs to be truncated into a 6 decimal number. Follow this document (RFC4226) for more detailed information. The method suggested was to use bit SHIFTING and OR to obtain 6digit decimal number. After trying it several times i realize C18 compiler could not perform the task correctly therefore i change the method to the following:

offset = Message_Digest[sizeof(Message_Digest)-1] & 0x0F;
b3 = (Message_Digest[offset] & 0x7F);
b2 = (Message_Digest[offset+1] & 0xFF);
b1 = (Message_Digest[offset+2] & 0xFF);
b0 = (Message_Digest[offset+3] & 0xFF);
hotp_code += b3 << 24;
hotp_code += b2 << 16;
hotp_code += b1 << 8;
hotp_code += b0;

hotp_value = hotp_code%1000000;

By doing so, the HOTP value generated is the same with the one documented in RFC4226.


Possible Error one might encounter:

  1. ERROR: certain object file (.obj) or unsigned int or signed int could not fit into the RAM of MCU – To solve this error, the linker script must be edited follow my previous POST to know how to do so.
  2. The Hash value generated using HASHES.c library is different from the one documented in RFC. There might be 2 possibility (a) The TEXT generated lack ‘\0’ which is why I stated above using ‘(const unsigned char *)   TEST1’
    (b) The size of the TEXT is incorrect, after testing it several times i realized with TEXT = “abc” and changing length of string to 3 or 4 or 5 or 6 will result a different HASH value
  3. Like i mention previously if shift bit (<<) and OR ( | ) was used to generate HOTP, it might not work properly so change to the method above

After fixing all the possible error to implement a HOTP for my project I proceed with making the HOTP to become counter based synchronization. To make it counter based is pretty straight forward also, because after successfully implementing HMAC-SHA1 based on the document in RFC2104, just change the string “Sample #1” into a 8byte Counter:

Counter[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // Counter = 0

HashAddData(&sha, Counter, sizeof(Counter));

Next week I will be focusing on the synchronization of the server and client counter.