#include "HMACSHA1.h"
#include "pbkdDigest.h"
#include <string.h>
#include <stdlib.h> // for malloc - maybe we should use Allocator?
#include <Security/cssmerr.h>
struct hmacContext {
DigestCtx digest;
UInt8 k_opad[kSHA1BlockSize];
};
hmacContextRef hmacAlloc()
{
hmacContextRef hmac = (hmacContextRef)malloc(sizeof(struct hmacContext));
memset(hmac, 0, sizeof(struct hmacContext));
return hmac;
}
void hmacFree(
hmacContextRef hmac)
{
if(hmac != NULL) {
DigestCtxFree(&hmac->digest);
memset(hmac, 0, sizeof(struct hmacContext));
free(hmac);
}
}
CSSM_RETURN hmacInit(
hmacContextRef hmac,
const void *keyPtr,
UInt32 keyLen,
CSSM_BOOL isSha1) {
UInt8 tk[kMaxDigestSize];
UInt8 *key;
UInt32 byte;
UInt8 k_ipad[kSHA1BlockSize];
UInt32 digestSize = isSha1 ? kSHA1DigestSize : kMD5DigestSize;
CSSM_ALGORITHMS hashAlg = isSha1 ? CSSM_ALGID_SHA1 : CSSM_ALGID_MD5;
DigestCtxInit(&hmac->digest, hashAlg);
if (keyLen <= kSHA1BlockSize)
key = (UInt8*)keyPtr;
else {
DigestCtxUpdate(&hmac->digest, (UInt8*)keyPtr, keyLen);
DigestCtxFinal(&hmac->digest, tk);
key = tk;
keyLen = digestSize;
DigestCtxInit(&hmac->digest, hashAlg);
}
for (byte = 0; byte < keyLen; byte++)
{
k_ipad[byte] = key[byte] ^ 0x36;
hmac->k_opad[byte] = key[byte] ^ 0x5c;
}
if (keyLen < kSHA1BlockSize)
{
memset (k_ipad + keyLen, 0x36, kSHA1BlockSize - keyLen);
memset (hmac->k_opad + keyLen, 0x5c, kSHA1BlockSize - keyLen);
}
DigestCtxUpdate(&hmac->digest, k_ipad, kSHA1BlockSize);
return CSSM_OK;
}
CSSM_RETURN hmacUpdate(
hmacContextRef hmac,
const void *textPtr,
UInt32 textLen)
{
DigestCtxUpdate(&hmac->digest, textPtr, textLen);
return CSSM_OK;
}
CSSM_RETURN hmacFinal(
hmacContextRef hmac,
void *resultPtr) {
UInt32 digestSize = (hmac->digest.hashAlg == CSSM_ALGID_SHA1) ?
kSHA1DigestSize : kHMACMD5DigestSize;
DigestCtxFinal(&hmac->digest, resultPtr);
DigestCtxInit(&hmac->digest, hmac->digest.hashAlg);
DigestCtxUpdate(&hmac->digest, hmac->k_opad, kSHA1BlockSize);
DigestCtxUpdate(&hmac->digest, resultPtr, digestSize);
DigestCtxFinal(&hmac->digest, resultPtr);
return CSSM_OK;
}
void
hmacsha1 (const void *keyPtr, UInt32 keyLen,
const void *textPtr, UInt32 textLen,
void *resultPtr)
{
hmacContextRef hmac = hmacAlloc();
hmacInit(hmac, keyPtr, keyLen, CSSM_TRUE);
hmacUpdate(hmac, textPtr, textLen);
hmacFinal(hmac, resultPtr);
hmacFree(hmac);
}