#include "MacContext.h"
#include <HMACSHA1.h>
#include <Security/cssmerr.h>
#include <CommonCrypto/CommonDigest.h>
#ifdef CRYPTKIT_CSP_ENABLE
#include <security_cryptkit/HmacSha1Legacy.h>
#endif
MacContext::~MacContext()
{
memset(&hmacCtx, 0, sizeof(hmacCtx));
}
void MacContext::init(const Context &context, bool isSigning)
{
CCHmacAlgorithm ccAlg;
CSSM_SIZE keyLen;
uint8 *keyData = NULL;
symmetricKeyBits(context, session(), mAlg,
isSigning ? CSSM_KEYUSE_SIGN : CSSM_KEYUSE_VERIFY,
keyData, keyLen);
uint32 minKey = 0;
switch(mAlg) {
case CSSM_ALGID_SHA1HMAC:
minKey = HMAC_SHA_MIN_KEY_SIZE;
mDigestSize = CC_SHA1_DIGEST_LENGTH;
ccAlg = kCCHmacAlgSHA1;
break;
case CSSM_ALGID_MD5HMAC:
minKey = HMAC_MD5_MIN_KEY_SIZE;
mDigestSize = CC_MD5_DIGEST_LENGTH;
ccAlg = kCCHmacAlgMD5;
break;
default:
assert(0); CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
}
if((keyLen < minKey) || (keyLen > HMAC_MAX_KEY_SIZE)) {
CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY);
}
CCHmacInit(&hmacCtx, ccAlg, keyData, keyLen);
}
void MacContext::update(const CssmData &data)
{
CCHmacUpdate(&hmacCtx, data.data(), data.length());
}
void MacContext::final(CssmData &out)
{
if(out.length() < mDigestSize) {
CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
}
CCHmacFinal(&hmacCtx, out.data());
out.Length = mDigestSize;
}
#define MAX_DIGEST_SIZE CC_SHA1_DIGEST_LENGTH
void MacContext::final(const CssmData &in)
{
unsigned char mac[MAX_DIGEST_SIZE];
CCHmacFinal(&hmacCtx, mac);
if(memcmp(mac, in.data(), mDigestSize)) {
CssmError::throwMe(CSSMERR_CSP_VERIFY_FAILED);
}
}
size_t MacContext::outputSize(bool final, size_t inSize)
{
return mDigestSize;
}
#ifdef CRYPTKIT_CSP_ENABLE
MacLegacyContext::~MacLegacyContext()
{
if(mHmac) {
hmacLegacyFree(mHmac);
mHmac = NULL;
}
}
void MacLegacyContext::init(const Context &context, bool isSigning)
{
if(mHmac == NULL) {
mHmac = hmacLegacyAlloc();
if(mHmac == NULL) {
CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
}
}
CSSM_SIZE keyLen;
uint8 *keyData = NULL;
symmetricKeyBits(context, session(), CSSM_ALGID_SHA1HMAC,
isSigning ? CSSM_KEYUSE_SIGN : CSSM_KEYUSE_VERIFY,
keyData, keyLen);
if((keyLen < HMAC_SHA_MIN_KEY_SIZE) || (keyLen > HMAC_MAX_KEY_SIZE)) {
CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY);
}
OSStatus ortn = hmacLegacyInit(mHmac, keyData, (UInt32)keyLen);
if(ortn) {
MacOSError::throwMe(ortn);
}
}
void MacLegacyContext::update(const CssmData &data)
{
OSStatus ortn = hmacLegacyUpdate(mHmac,
data.data(),
(UInt32)data.length());
if(ortn) {
MacOSError::throwMe(ortn);
}
}
void MacLegacyContext::final(CssmData &out)
{
if(out.length() < kHMACSHA1DigestSize) {
CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
}
hmacLegacyFinal(mHmac, out.data());
}
void MacLegacyContext::final(const CssmData &in)
{
unsigned char mac[kHMACSHA1DigestSize];
hmacLegacyFinal(mHmac, mac);
if(memcmp(mac, in.data(), kHMACSHA1DigestSize)) {
CssmError::throwMe(CSSMERR_CSP_VERIFY_FAILED);
}
}
size_t MacLegacyContext::outputSize(bool final, size_t inSize)
{
return kHMACSHA1DigestSize;
}
#endif