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);
} |
Partager