1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
   | ///////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sha1.h"
#include "hmac.h"
/* Convinience function */
void SHA1_Atomic(uint8_t *in, unsigned int in_len, uint8_t *out)
{
 SHA1_CTX ctx;
 SHA1Init(&ctx);
 SHA1Update(&ctx, in, in_len);
 SHA1Final(out, &ctx);
}
void HMAC_SHA1_Init(HMAC_SHA1_CTX *hmac, uint8_t *key, size_t key_len)
{
 /*
  * Why does Solaris use 4 byte value for ipad and opad?
  * is it for performnce reason?
  */
 uint8_t ipad[SHA1_HMAC_BLOCK_SIZE];
 uint8_t opad[SHA1_HMAC_BLOCK_SIZE];
 uint8_t digested_key[SHA1_DIGEST_LENGTH];
 uint8_t *keyptr;
 int i;
 /*
  * If the key is too long we need to hash the key and use that instead
  * And we don't want to modify the actual key
  */
 keyptr = key;
 /* Need to hash the key if too big */
 if (key_len > SHA1_HMAC_BLOCK_SIZE) {
  SHA1_Atomic(key, key_len, digested_key);
  keyptr = digested_key;
  key_len = SHA1_DIGEST_LENGTH;
 }
 bzero(ipad, SHA1_HMAC_BLOCK_SIZE);
 bzero(opad, SHA1_HMAC_BLOCK_SIZE);
 bcopy(keyptr, ipad, key_len);
 bcopy(keyptr, opad, key_len);
 /* XOR key with ipad and opad */
 for (i = 0; i < SHA1_HMAC_BLOCK_SIZE; i++) {
  ipad[i] ^= HMAC_IPAD;
  opad[i] ^= HMAC_OPAD;
 }
 /* Start by hashing the resulting string. */
 SHA1Init(&hmac->hc_icontext);
 SHA1Update(&hmac->hc_icontext, (uint8_t *)ipad, SHA1_HMAC_BLOCK_SIZE);
 SHA1Init(&hmac->hc_ocontext);
 SHA1Update(&hmac->hc_ocontext, (uint8_t *)opad, SHA1_HMAC_BLOCK_SIZE);
}
 
/* Do the inner SHA1 of the algorithm */
void HMAC_SHA1_Update(HMAC_SHA1_CTX *hmac, uint8_t *data, size_t data_len)
{
 SHA1Update(&hmac->hc_icontext, data, data_len);
}
 
/* Finish the inner SHA1 and compute the outer SHA1
 *
 * **Note that the argument order is different from SHA1Final
 * It made sense to me to put hmac_ctx before the pointer to the output
 * so that it's consistent with the other calls that use the hmac_ctx
 */
void HMAC_SHA1_Final(HMAC_SHA1_CTX *hmac, uint8_t *digest)
{
 /* Do a SHA1 final on the inner context */
 SHA1Final(digest, &hmac->hc_icontext);
 /*
  * Do a SHA1 final on the outer context, feeding the inner
  * digest as data
  */
 SHA1Update(&hmac->hc_ocontext, digest, SHA1_DIGEST_LENGTH);
 /* Do a SHA1 final on the outer context, storing the computing digest */
 SHA1Final(digest, &hmac->hc_ocontext);
 /* paranoid? */
 bzero(hmac, sizeof (HMAC_SHA1_CTX));
}
 
 
/* Convinience function */
void HMAC_SHA1_Atomic(uint8_t *data, size_t data_len,
 uint8_t *key, size_t key_len, uint8_t *mac)
{
 HMAC_SHA1_CTX hmac;
 HMAC_SHA1_Init(&hmac, key, key_len);
 HMAC_SHA1_Update(&hmac, data, data_len);
 HMAC_SHA1_Final(&hmac, mac);
} |