#include "tls_hmac.h"
#include "appleCdsa.h"
#include "sslalloc.h"
#include "sslerrs.h"
#include "cryptType.h"
#include "digests.h"
#include <strings.h>
#include <assert.h>
#include <Security/cssm.h>
struct HMACContext {
SSLContext *ctx;
CSSM_CC_HANDLE ccHand;
const struct HMACReference *hmac;
};
#pragma mark *** Common CDSA_based HMAC routines ***
static SSLErr HMAC_Alloc(
const struct HMACReference *hmac,
SSLContext *ctx,
const void *keyPtr,
unsigned keyLen,
HMACContextRef *hmacCtx) {
CSSM_RETURN crtn;
CSSM_KEY cssmKey;
SSLErr serr;
CSSM_ALGORITHMS calg;
HMACContextRef href = sslMalloc(sizeof(struct HMACContext));
if(href == NULL) {
return SSLMemoryErr;
}
href->ctx = ctx;
href->ccHand = 0;
href->hmac = hmac;
switch(hmac->alg) {
case HA_SHA1:
calg = CSSM_ALGID_SHA1HMAC;
break;
case HA_MD5:
calg = CSSM_ALGID_MD5HMAC;
break;
default:
assert(0);
return SSLInternalError;
}
serr = sslSetUpSymmKey(&cssmKey,
calg,
CSSM_KEYUSE_SIGN | CSSM_KEYUSE_VERIFY,
CSSM_FALSE,
(uint8 *)keyPtr,
keyLen);
if(serr) {
return serr;
}
if(attachToCsp(ctx)) {
return serr;
}
crtn = CSSM_CSP_CreateMacContext(ctx->cspHand,
calg,
&cssmKey,
&href->ccHand);
if(crtn) {
return SSLCryptoError;
}
*hmacCtx = href;
return SSLNoErr;
}
static SSLErr HMAC_Free(
HMACContextRef hmacCtx)
{
if(hmacCtx != NULL) {
if(hmacCtx->ccHand != 0) {
CSSM_DeleteContext(hmacCtx->ccHand);
hmacCtx->ccHand = 0;
}
sslFree(hmacCtx);
}
return SSLNoErr;
}
static SSLErr HMAC_Init(
HMACContextRef hmacCtx)
{
CSSM_RETURN crtn;
if(hmacCtx == NULL) {
return SSLInternalError;
}
assert(hmacCtx->ctx != NULL);
assert(hmacCtx->hmac != NULL);
assert(hmacCtx->ccHand != 0);
crtn = CSSM_GenerateMacInit(hmacCtx->ccHand);
if(crtn) {
return SSLCryptoError;
}
return SSLNoErr;
}
static SSLErr HMAC_Update(
HMACContextRef hmacCtx,
const void *data,
unsigned dataLen)
{
CSSM_RETURN crtn;
CSSM_DATA cdata;
if(hmacCtx == NULL) {
return SSLInternalError;
}
assert(hmacCtx->ctx != NULL);
assert(hmacCtx->hmac != NULL);
assert(hmacCtx->ccHand != 0);
cdata.Data = (uint8 *)data;
cdata.Length = dataLen;
crtn = CSSM_GenerateMacUpdate(hmacCtx->ccHand, &cdata, 1);
if(crtn) {
return SSLCryptoError;
}
return SSLNoErr;
}
static SSLErr HMAC_Final(
HMACContextRef hmacCtx,
void *hmac, unsigned *hmacLen) {
CSSM_RETURN crtn;
CSSM_DATA cdata;
if(hmacCtx == NULL) {
return SSLInternalError;
}
if((hmac == NULL) || (hmacLen == 0)) {
return SSLInternalError;
}
assert(hmacCtx->ctx != NULL);
assert(hmacCtx->hmac != NULL);
assert(hmacCtx->ccHand != 0);
cdata.Data = (uint8 *)hmac;
cdata.Length = *hmacLen;
crtn = CSSM_GenerateMacFinal(hmacCtx->ccHand, &cdata);
if(crtn) {
return SSLCryptoError;
}
*hmacLen = cdata.Length;
return SSLNoErr;
}
static SSLErr HMAC_Hmac (
HMACContextRef hmacCtx,
const void *data,
unsigned dataLen,
void *hmac, unsigned *hmacLen) {
SSLErr serr;
const HMACReference *hmacRef;
if(hmacCtx == NULL) {
return SSLInternalError;
}
hmacRef = hmacCtx->hmac;
assert(hmacRef != NULL);
serr = hmacRef->init(hmacCtx);
if(serr) {
return serr;
}
serr = hmacRef->update(hmacCtx, data, dataLen);
if(serr) {
return serr;
}
return hmacRef->final(hmacCtx, hmac, hmacLen);
}
#pragma mark *** Null HMAC ***
static SSLErr HMAC_AllocNull(
const struct HMACReference *hmac,
SSLContext *ctx,
const void *keyPtr,
unsigned keyLen,
HMACContextRef *hmacCtx) {
*hmacCtx = NULL;
return SSLNoErr;
}
static SSLErr HMAC_FreeNull(
HMACContextRef hmacCtx)
{
return SSLNoErr;
}
static SSLErr HMAC_InitNull(
HMACContextRef hmacCtx)
{
return SSLNoErr;
}
static SSLErr HMAC_UpdateNull(
HMACContextRef hmacCtx,
const void *data,
unsigned dataLen)
{
return SSLNoErr;
}
static SSLErr HMAC_FinalNull(
HMACContextRef hmacCtx,
void *hmac, unsigned *hmacLen) {
return SSLNoErr;
}
static SSLErr HMAC_HmacNull (
HMACContextRef hmacCtx,
const void *data,
unsigned dataLen,
void *hmac, unsigned *hmacLen)
{
return SSLNoErr;
}
const HMACReference TlsHmacNull = {
0,
HA_Null,
HMAC_AllocNull,
HMAC_FreeNull,
HMAC_InitNull,
HMAC_UpdateNull,
HMAC_FinalNull,
HMAC_HmacNull
};
const HMACReference TlsHmacSHA1 = {
20,
HA_SHA1,
HMAC_Alloc,
HMAC_Free,
HMAC_Init,
HMAC_Update,
HMAC_Final,
HMAC_Hmac
};
const HMACReference TlsHmacMD5 = {
16,
HA_MD5,
HMAC_Alloc,
HMAC_Free,
HMAC_Init,
HMAC_Update,
HMAC_Final,
HMAC_Hmac
};
const HashHmacReference HashHmacNull = {
&SSLHashNull,
&TlsHmacNull
};
const HashHmacReference HashHmacMD5 = {
&SSLHashMD5,
&TlsHmacMD5
};
const HashHmacReference HashHmacSHA1 = {
&SSLHashSHA1,
&TlsHmacSHA1
};