1/* 2 * Copyright (c) 2012 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24// #define COMMON_HMAC_FUNCTIONS 25#include "CommonHMAC.h" 26#include "CommonHmacSPI.h" 27#include "CommonDigest.h" 28#include "CommonDigestSPI.h" 29#include "CommonDigestPriv.h" 30#include <corecrypto/cchmac.h> 31#include "ccMemory.h" 32#include "ccdebug.h" 33 34#ifndef NDEBUG 35#define ASSERT(s) 36#else 37#define ASSERT(s) assert(s) 38#endif 39 40#define HMAC_MAX_BLOCK_SIZE CC_SHA512_BLOCK_BYTES 41#define HMAC_MAX_DIGEST_SIZE CC_SHA512_DIGEST_LENGTH 42 43/* 44 * This is what a CCHmacContext actually points to. 45 * we have 384 bytes to work with 46 */ 47 48typedef struct { 49 const struct ccdigest_info *di; 50 cchmac_ctx_decl(HMAC_MAX_BLOCK_SIZE, HMAC_MAX_DIGEST_SIZE, ctx); 51} _NewHmacContext; 52 53 54typedef struct { 55 CCHmacAlgorithm ccHmacValue; 56 CCDigestAlgorithm ccDigestAlg; 57 const char *ccDigestName; 58} ccHmac2DigestConversion; 59 60 61const ccHmac2DigestConversion ccconversionTable[] = { 62 { kCCHmacAlgSHA1, kCCDigestSHA1, "sha1" }, 63 { kCCHmacAlgMD5, kCCDigestMD5, "md5" }, 64 { kCCHmacAlgSHA224, kCCDigestSHA224, "sha224" }, 65 { kCCHmacAlgSHA256, kCCDigestSHA256, "sha256" }, 66 { kCCHmacAlgSHA384, kCCDigestSHA384, "sha384" }, 67 { kCCHmacAlgSHA512, kCCDigestSHA512, "sha512" }, 68}; 69 70const static int ccHmacConversionTableLength = sizeof(ccconversionTable) / sizeof(ccHmac2DigestConversion); 71 72static const struct ccdigest_info * 73convertccHmacSelector(CCHmacAlgorithm oldSelector) 74{ 75 int i; 76 77 for(i=0; i<ccHmacConversionTableLength; i++) 78 if(oldSelector == ccconversionTable[i].ccHmacValue) { 79 return CCDigestGetDigestInfo(ccconversionTable[i].ccDigestAlg); 80 } 81 return NULL; 82} 83 84 85void CCHmacInit( 86 CCHmacContext *ctx, 87 CCHmacAlgorithm algorithm, /* kCCHmacSHA1, kCCHmacMD5 */ 88 const void *key, 89 size_t keyLength) /* length of key in bytes */ 90{ 91 _NewHmacContext *hmacCtx = (_NewHmacContext *)ctx; 92 // CCDigestCtxPtr digestCtx = &hmacCtx->digestCtx; 93 94 CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering Algorithm: %d\n", algorithm); 95 96 97 ASSERT(sizeof(_NewHmacContext) < sizeof(CCHmacContext)); 98 99 if(hmacCtx == NULL) { 100 CC_DEBUG_LOG(CC_DEBUG, "NULL Context passed in\n"); 101 return; 102 } 103 104 if(key == NULL) { 105 CC_DEBUG_LOG(CC_DEBUG, "NULL Context passed in\n"); 106 return; 107 } 108 109 CC_XZEROMEM(hmacCtx, sizeof(_NewHmacContext)); 110 111 if((hmacCtx->di = convertccHmacSelector(algorithm)) == NULL) { 112 CC_DEBUG_LOG(CC_DEBUG, "CCHMac Unknown Digest %d\n", algorithm); 113 return; 114 } 115 116 cchmac_init(hmacCtx->di, hmacCtx->ctx, keyLength, key); 117 118 119} 120 121void CCHmacUpdate( 122 CCHmacContext *ctx, 123 const void *dataIn, 124 size_t dataInLength) /* length of data in bytes */ 125{ 126 _NewHmacContext *hmacCtx = (_NewHmacContext *)ctx; 127 128 CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); 129 cchmac_update(hmacCtx->di, hmacCtx->ctx, dataInLength, dataIn); 130} 131 132void CCHmacFinal( 133 CCHmacContext *ctx, 134 void *macOut) 135{ 136 _NewHmacContext *hmacCtx = (_NewHmacContext *)ctx; 137 138 CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); 139 cchmac_final(hmacCtx->di, hmacCtx->ctx, macOut); 140} 141 142void 143CCHmacDestroy(CCHmacContextRef ctx) 144{ 145 CC_XZEROMEM(ctx, sizeof(_NewHmacContext)); 146 CC_XFREE(ctx, sizeof(_NewHmacContext)); 147} 148 149 150size_t 151CCHmacOutputSizeFromRef(CCHmacContextRef ctx) 152{ 153 _NewHmacContext *hmacCtx = (_NewHmacContext *)ctx; 154 CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); 155 return hmacCtx->di->output_size; 156} 157 158 159size_t 160CCHmacOutputSize(CCDigestAlg alg) 161{ 162 CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); 163 return CCDigestGetOutputSize(alg); 164} 165 166 167/* 168 * Stateless, one-shot HMAC function. 169 * Output is written to caller-supplied buffer, as in CCHmacFinal(). 170 */ 171void CCHmac( 172 CCHmacAlgorithm algorithm, /* kCCHmacSHA1, kCCHmacMD5 */ 173 const void *key, 174 size_t keyLength, /* length of key in bytes */ 175 const void *data, 176 size_t dataLength, /* length of data in bytes */ 177 void *macOut) /* MAC written here */ 178{ 179 CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering Algorithm: %d\n", algorithm); 180 cchmac(convertccHmacSelector(algorithm), keyLength, key, dataLength, data, macOut); 181} 182 183 184 185CCHmacContextRef 186CCHmacCreate(CCDigestAlg alg, const void *key, size_t keyLength) 187{ 188 _NewHmacContext *hmacCtx; 189 190 CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); 191 /* if this fails, it's time to adjust CC_HMAC_CONTEXT_SIZE */ 192 if((hmacCtx = CC_XMALLOC(sizeof(_NewHmacContext))) == NULL) return NULL; 193 194 CC_XZEROMEM(hmacCtx, sizeof(_NewHmacContext)); 195 196 if((hmacCtx->di = CCDigestGetDigestInfo(alg)) == NULL) { 197 CC_DEBUG_LOG(CC_DEBUG, "CCHMac Unknown Digest %d\n"); 198 CC_XFREE(hmacCtx, sizeof(_NewHmacContext)); 199 return NULL; 200 } 201 202 cchmac_init(hmacCtx->di, hmacCtx->ctx, keyLength, key); 203 return (CCHmacContextRef) hmacCtx; 204} 205 206