#include "HMACSHA1.h"
#include <CryptKit/SHA1.h>
#include <string.h>
#include <stdlib.h> // for malloc - maybe we should use CssmAllocator?
#include <Security/cssmerr.h>
struct hmacContext {
sha1Obj sha1Context;
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) {
if(hmac->sha1Context != NULL) {
sha1Free (hmac->sha1Context);
}
memset(hmac, 0, sizeof(struct hmacContext));
free(hmac);
}
}
CSSM_RETURN hmacInit(
hmacContextRef hmac,
const void *keyPtr,
UInt32 keyLen)
{
UInt8 tk[kSHA1DigestSize];
UInt8 *key;
UInt32 byte;
UInt8 k_ipad[kSHA1BlockSize];
if(hmac->sha1Context == NULL) {
hmac->sha1Context = sha1Alloc();
if(hmac->sha1Context == NULL) {
return CSSMERR_CSP_MEMORY_ERROR;
}
}
else {
sha1Reinit(hmac->sha1Context);
}
if (keyLen <= kSHA1BlockSize)
key = (UInt8*)keyPtr;
else {
sha1AddData(hmac->sha1Context, (UInt8*)keyPtr, keyLen);
memcpy (tk, sha1Digest(hmac->sha1Context), kSHA1DigestSize);
key = tk;
keyLen = kSHA1DigestSize;
sha1Reinit (hmac->sha1Context);
}
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);
}
sha1AddData (hmac->sha1Context, k_ipad, kSHA1BlockSize);
return CSSM_OK;
}
CSSM_RETURN hmacUpdate(
hmacContextRef hmac,
const void *textPtr,
UInt32 textLen)
{
sha1AddData (hmac->sha1Context, (UInt8*)textPtr, textLen);
return CSSM_OK;
}
CSSM_RETURN hmacFinal(
hmacContextRef hmac,
void *resultPtr) {
memcpy (resultPtr, sha1Digest (hmac->sha1Context), kSHA1DigestSize);
sha1Reinit (hmac->sha1Context);
sha1AddData (hmac->sha1Context, hmac->k_opad, kSHA1BlockSize);
sha1AddData (hmac->sha1Context, (UInt8*)resultPtr, kSHA1DigestSize);
memcpy (resultPtr, sha1Digest (hmac->sha1Context), kSHA1DigestSize);
return CSSM_OK;
}
void
hmacsha1 (const void *keyPtr, UInt32 keyLen,
const void *textPtr, UInt32 textLen,
void *resultPtr)
{
hmacContextRef hmac = hmacAlloc();
hmacInit(hmac, keyPtr, keyLen);
hmacUpdate(hmac, textPtr, textLen);
hmacFinal(hmac, resultPtr);
hmacFree(hmac);
}