--- /dev/null
+/*
+ * Copyright (c) 2002 Apple Computer, Inc. All Rights Reserved.
+ *
+ * The contents of this file constitute Original Code as defined in and are
+ * subject to the Apple Public Source License Version 1.2 (the 'License').
+ * You may not use this file except in compliance with the License. Please obtain
+ * a copy of the License at http://www.apple.com/publicsource and read it before
+ * using this file.
+ *
+ * This Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
+ * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
+ * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
+ * specific language governing rights and limitations under the License.
+ */
+
+
+/*
+ File: tls_hmac.c
+
+ Contains: HMAC routines used by TLS
+
+ Written by: Doug Mitchell
+*/
+
+#include "tls_hmac.h"
+#include "appleCdsa.h"
+#include "sslMemory.h"
+#include "cryptType.h"
+#include "sslDigests.h"
+#include <strings.h>
+#include <assert.h>
+#include <Security/cssm.h>
+
+/* Per-session state, opaque to callers; all fields set at alloc time */
+struct HMACContext {
+ SSLContext *ctx;
+ CSSM_CC_HANDLE ccHand;
+ const struct HMACReference *hmac;
+};
+
+#pragma mark *** Common CDSA_based HMAC routines ***
+
+/* Create an HMAC session */
+static OSStatus HMAC_Alloc(
+ const struct HMACReference *hmac,
+ SSLContext *ctx,
+ const void *keyPtr,
+ unsigned keyLen,
+ HMACContextRef *hmacCtx) // RETURNED
+{
+ CSSM_RETURN crtn;
+ CSSM_KEY cssmKey;
+ OSStatus serr;
+ CSSM_ALGORITHMS calg;
+ HMACContextRef href = (HMACContextRef)sslMalloc(sizeof(struct HMACContext));
+
+ if(href == NULL) {
+ return memFullErr;
+ }
+ href->ctx = ctx;
+ href->ccHand = 0;
+ href->hmac = hmac;
+
+ /*
+ * Since the key is present in the CDSA context, we cook up the context now.
+ * Currently we can't reuse an HMAC context if the key changes.
+ */
+ switch(hmac->alg) {
+ case HA_SHA1:
+ calg = CSSM_ALGID_SHA1HMAC;
+ break;
+ case HA_MD5:
+ calg = CSSM_ALGID_MD5HMAC;
+ break;
+ default:
+ assert(0);
+ return errSSLInternal;
+ }
+ serr = sslSetUpSymmKey(&cssmKey,
+ calg,
+ CSSM_KEYUSE_SIGN | CSSM_KEYUSE_VERIFY,
+ CSSM_FALSE, /* don't malloc/copy key */
+ (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 errSSLCrypto;
+ }
+
+ /* success */
+ *hmacCtx = href;
+ return noErr;
+}
+
+/* free a session */
+static OSStatus HMAC_Free(
+ HMACContextRef hmacCtx)
+{
+ if(hmacCtx != NULL) {
+ if(hmacCtx->ccHand != 0) {
+ CSSM_DeleteContext(hmacCtx->ccHand);
+ hmacCtx->ccHand = 0;
+ }
+ sslFree(hmacCtx);
+ }
+ return noErr;
+}
+
+/* Reusable init */
+static OSStatus HMAC_Init(
+ HMACContextRef hmacCtx)
+{
+ CSSM_RETURN crtn;
+
+ if(hmacCtx == NULL) {
+ return errSSLInternal;
+ }
+ assert(hmacCtx->ctx != NULL);
+ assert(hmacCtx->hmac != NULL);
+ assert(hmacCtx->ccHand != 0);
+
+ crtn = CSSM_GenerateMacInit(hmacCtx->ccHand);
+ if(crtn) {
+ return errSSLCrypto;
+ }
+ return noErr;
+}
+
+/* normal crypt ops */
+static OSStatus HMAC_Update(
+ HMACContextRef hmacCtx,
+ const void *data,
+ unsigned dataLen)
+{
+ CSSM_RETURN crtn;
+ CSSM_DATA cdata;
+
+ if(hmacCtx == NULL) {
+ return errSSLInternal;
+ }
+ 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 errSSLCrypto;
+ }
+ return noErr;
+}
+
+static OSStatus HMAC_Final(
+ HMACContextRef hmacCtx,
+ void *hmac, // mallocd by caller
+ unsigned *hmacLen) // IN/OUT
+{
+ CSSM_RETURN crtn;
+ CSSM_DATA cdata;
+
+ if(hmacCtx == NULL) {
+ return errSSLInternal;
+ }
+ if((hmac == NULL) || (hmacLen == 0)) {
+ return errSSLInternal;
+ }
+ 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 errSSLCrypto;
+ }
+ *hmacLen = cdata.Length;
+ return noErr;
+}
+
+/* one-shot */
+static OSStatus HMAC_Hmac (
+ HMACContextRef hmacCtx,
+ const void *data,
+ unsigned dataLen,
+ void *hmac, // mallocd by caller
+ unsigned *hmacLen) // IN/OUT
+{
+ OSStatus serr;
+ const HMACReference *hmacRef;
+
+ if(hmacCtx == NULL) {
+ return errSSLInternal;
+ }
+ 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 OSStatus HMAC_AllocNull(
+ const struct HMACReference *hmac,
+ SSLContext *ctx,
+ const void *keyPtr,
+ unsigned keyLen,
+ HMACContextRef *hmacCtx) // RETURNED
+{
+ *hmacCtx = NULL;
+ return noErr;
+}
+
+static OSStatus HMAC_FreeNull(
+ HMACContextRef hmacCtx)
+{
+ return noErr;
+}
+
+static OSStatus HMAC_InitNull(
+ HMACContextRef hmacCtx)
+ {
+ return noErr;
+}
+
+static OSStatus HMAC_UpdateNull(
+ HMACContextRef hmacCtx,
+ const void *data,
+ unsigned dataLen)
+{
+ return noErr;
+}
+
+static OSStatus HMAC_FinalNull(
+ HMACContextRef hmacCtx,
+ void *hmac, // mallocd by caller
+ unsigned *hmacLen) // IN/OUT
+{
+ return noErr;
+}
+
+static OSStatus HMAC_HmacNull (
+ HMACContextRef hmacCtx,
+ const void *data,
+ unsigned dataLen,
+ void *hmac, // mallocd by caller
+ unsigned *hmacLen)
+{
+ return noErr;
+}
+
+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
+};