#include <CommonCrypto/CommonHMAC.h>
#include <CommonCrypto/CommonHmacSPI.h>
#include <CommonCrypto/CommonDigest.h>
#include <CommonCrypto/CommonDigestSPI.h>
#include "CommonDigestPriv.h"
#include <corecrypto/cchmac.h>
#include <corecrypto/cc_priv.h>
#include "ccMemory.h"
#include "ccdebug.h"
#ifndef NDEBUG
#define ASSERT(s)
#else
#define ASSERT(s) assert(s)
#endif
#define HMAC_MAX_BLOCK_SIZE CC_SHA512_BLOCK_BYTES
#define HMAC_MAX_DIGEST_SIZE CC_SHA512_DIGEST_LENGTH
typedef struct {
const struct ccdigest_info *di;
#if defined(_WIN32) //rdar://problem/27873676
struct cchmac_ctx ctx[cc_ctx_n(struct cchmac_ctx, cchmac_ctx_size(HMAC_MAX_DIGEST_SIZE, HMAC_MAX_BLOCK_SIZE))];
#else
cchmac_ctx_decl(HMAC_MAX_DIGEST_SIZE, HMAC_MAX_BLOCK_SIZE, ctx);
#endif
} _NewHmacContext;
typedef struct {
CCHmacAlgorithm ccHmacValue;
CCDigestAlgorithm ccDigestAlg;
const char *ccDigestName;
} ccHmac2DigestConversion;
const ccHmac2DigestConversion ccconversionTable[] = {
{ kCCHmacAlgSHA1, kCCDigestSHA1, "sha1" },
{ kCCHmacAlgMD5, kCCDigestMD5, "md5" },
{ kCCHmacAlgSHA224, kCCDigestSHA224, "sha224" },
{ kCCHmacAlgSHA256, kCCDigestSHA256, "sha256" },
{ kCCHmacAlgSHA384, kCCDigestSHA384, "sha384" },
{ kCCHmacAlgSHA512, kCCDigestSHA512, "sha512" },
};
const static int ccHmacConversionTableLength = sizeof(ccconversionTable) / sizeof(ccHmac2DigestConversion);
static const struct ccdigest_info *
convertccHmacSelector(CCHmacAlgorithm oldSelector)
{
int i;
for(i=0; i<ccHmacConversionTableLength; i++)
if(oldSelector == ccconversionTable[i].ccHmacValue) {
return CCDigestGetDigestInfo(ccconversionTable[i].ccDigestAlg);
}
return NULL;
}
void CCHmacInit(
CCHmacContext *ctx,
CCHmacAlgorithm algorithm,
const void *key,
size_t keyLength)
{
_NewHmacContext *hmacCtx = (_NewHmacContext *)ctx;
CC_DEBUG_LOG("Entering Algorithm: %d\n", algorithm);
ASSERT(sizeof(_NewHmacContext) < sizeof(CCHmacContext));
if(hmacCtx == NULL) {
CC_DEBUG_LOG( "NULL Context passed in\n");
return;
}
CC_XZEROMEM(hmacCtx, sizeof(_NewHmacContext));
if((hmacCtx->di = convertccHmacSelector(algorithm)) == NULL) {
CC_DEBUG_LOG( "CCHMac Unknown Digest %d\n", algorithm);
return;
}
cchmac_init(hmacCtx->di, hmacCtx->ctx, keyLength, key);
}
void CCHmacUpdate(
CCHmacContext *ctx,
const void *dataIn,
size_t dataInLength)
{
_NewHmacContext *hmacCtx = (_NewHmacContext *)ctx;
CC_DEBUG_LOG("Entering\n");
cchmac_update(hmacCtx->di, hmacCtx->ctx, dataInLength, dataIn);
}
void CCHmacFinal(
CCHmacContext *ctx,
void *macOut)
{
_NewHmacContext *hmacCtx = (_NewHmacContext *)ctx;
CC_DEBUG_LOG("Entering\n");
cchmac_final(hmacCtx->di, hmacCtx->ctx, macOut);
}
void
CCHmacDestroy(CCHmacContextRef ctx)
{
CC_XZEROMEM(ctx, sizeof(_NewHmacContext));
CC_XFREE(ctx, sizeof(_NewHmacContext));
}
size_t
CCHmacOutputSizeFromRef(CCHmacContextRef ctx)
{
_NewHmacContext *hmacCtx = (_NewHmacContext *)ctx;
CC_DEBUG_LOG("Entering\n");
return hmacCtx->di->output_size;
}
size_t
CCHmacOutputSize(CCDigestAlg alg)
{
CC_DEBUG_LOG("Entering\n");
return CCDigestGetOutputSize(alg);
}
void CCHmac(
CCHmacAlgorithm algorithm,
const void *key,
size_t keyLength,
const void *data,
size_t dataLength,
void *macOut)
{
CC_DEBUG_LOG("Entering Algorithm: %d\n", algorithm);
cchmac(convertccHmacSelector(algorithm), keyLength, key, dataLength, data, macOut);
}
CCHmacContextRef
CCHmacCreate(CCDigestAlg alg, const void *key, size_t keyLength)
{
_NewHmacContext *hmacCtx;
CC_DEBUG_LOG("Entering\n");
if((hmacCtx = CC_XMALLOC(sizeof(_NewHmacContext))) == NULL) return NULL;
CC_XZEROMEM(hmacCtx, sizeof(_NewHmacContext));
if((hmacCtx->di = CCDigestGetDigestInfo(alg)) == NULL) {
CC_DEBUG_LOG( "CCHMac Unknown Digest %d\n");
CC_XFREE(hmacCtx, sizeof(_NewHmacContext));
return NULL;
}
cchmac_init(hmacCtx->di, hmacCtx->ctx, keyLength, key);
return (CCHmacContextRef) hmacCtx;
}
void CCHmacOneShot(CCDigestAlg alg, const void *key, size_t keyLength, const void *data, size_t dataLength, void *macOut) {
const struct ccdigest_info *di = CCDigestGetDigestInfo(alg);
cchmac(di, keyLength, key, dataLength, data, macOut);
}
CCHmacContextRef
CCHmacClone(CCHmacContextRef ctx) {
_NewHmacContext *hmacCtx;
CC_DEBUG_LOG("Entering\n");
if((hmacCtx = CC_XMALLOC(sizeof(_NewHmacContext))) == NULL) return NULL;
CC_XMEMCPY(hmacCtx, ctx, sizeof(_NewHmacContext));
return (CCHmacContextRef) hmacCtx;
}