#include "HMACSHA1.h"
#include "pbkdDigest.h"
#include <MiscCSPAlgs/SHA1.h>
#include <MiscCSPAlgs/MD5.h>
#include <string.h>
#include <stdlib.h> // for malloc - maybe we should use CssmAllocator?
#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[kSHA1DigestSize];
UInt8 *key;
UInt32 byte;
UInt8 k_ipad[kSHA1BlockSize];
UInt32 digestSize = sha1Digest ? kSHA1DigestSize : MD5_DIGEST_SIZE;
DigestCtxInit(&hmac->digest, isSha1);
if (keyLen <= kSHA1BlockSize)
key = (UInt8*)keyPtr;
else {
DigestCtxUpdate(&hmac->digest, (UInt8*)keyPtr, keyLen);
DigestCtxFinal(&hmac->digest, tk);
key = tk;
keyLen = digestSize;
DigestCtxInit(&hmac->digest, isSha1);
}
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.isSha1 ? kSHA1DigestSize : kHMACMD5DigestSize;
DigestCtxFinal(&hmac->digest, resultPtr);
DigestCtxInit(&hmac->digest, hmac->digest.isSha1);
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);
}