Something went wrong. Try again.
Cider Isn't Darwin Emulation, Really
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215/* * Copyright (c) 2006 Apple Computer, Inc. All Rights Reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The 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. * * @APPLE_LICENSE_HEADER_END@ */
/* * CommonHMAC.h - Keyed Message Authentication Code (HMAC) functions. * * Created 3/27/2006 by Doug Mitchell. */
#include <CommonCrypto/CommonHMAC.h>#include <strings.h>#include <stdlib.h>#include <assert.h>
#ifndef NDEBUG#define ASSERT(s)#else#define ASSERT(s) assert(s)#endif
/* * Callouts for digest ops. * The void *ctx pointers are needed to accommodate different underlying * digest context types. */typedef void (*ccDigestInit)(void *ctx);typedef void (*ccDigestUpdate)(void *ctx, const void *data, CC_LONG len);typedef void (*ccDigestFinal)(unsigned char *md, void *ctx);
#define HMAC_MAX_BLOCK_SIZE CC_SHA512_BLOCK_BYTES#define HMAC_MAX_DIGEST_SIZE CC_SHA512_DIGEST_LENGTH
/* * This is what a CCHmacContext actually points to. */typedef struct { uint32_t digestLen; uint32_t blockLen; union { CC_MD5_CTX md5Ctx; CC_SHA1_CTX sha1Ctx; CC_SHA256_CTX sha256Ctx; CC_SHA512_CTX sha512Ctx; } digest; uint8_t k_opad[HMAC_MAX_BLOCK_SIZE]; /* max block size */ ccDigestInit digestInit; ccDigestUpdate digestUpdate; ccDigestFinal digestFinal;} _CCHmacContext;
void CCHmacInit( CCHmacContext *ctx, CCHmacAlgorithm algorithm, /* kCCHmacSHA1, kCCHmacMD5 */ const void *key, size_t keyLength) /* length of key in bytes */{ _CCHmacContext *hmacCtx = (_CCHmacContext *)ctx; uint8_t tk[HMAC_MAX_DIGEST_SIZE]; uint8_t *keyP; uint32_t byte; uint8_t k_ipad[HMAC_MAX_BLOCK_SIZE];
/* if this fails, it's time to adjust CC_HMAC_CONTEXT_SIZE */ ASSERT(sizeof(_CCHmacContext) < sizeof(CCHmacContext)); if(hmacCtx == NULL) { return; } memset(hmacCtx, 0, sizeof(*hmacCtx)); switch(algorithm) { case kCCHmacAlgMD5: hmacCtx->digestLen = CC_MD5_DIGEST_LENGTH; hmacCtx->blockLen = CC_MD5_BLOCK_BYTES; hmacCtx->digestInit = (void *)CC_MD5_Init; hmacCtx->digestUpdate = (void *)CC_MD5_Update; hmacCtx->digestFinal = (void *)CC_MD5_Final; break; case kCCHmacAlgSHA1: hmacCtx->digestLen = CC_SHA1_DIGEST_LENGTH; hmacCtx->blockLen = CC_SHA1_BLOCK_BYTES; hmacCtx->digestInit = (void *)CC_SHA1_Init; hmacCtx->digestUpdate = (void *)CC_SHA1_Update; hmacCtx->digestFinal = (void *)CC_SHA1_Final; break; case kCCHmacAlgSHA224: hmacCtx->digestLen = CC_SHA224_DIGEST_LENGTH; hmacCtx->blockLen = CC_SHA224_BLOCK_BYTES; hmacCtx->digestInit = (void *)CC_SHA224_Init; hmacCtx->digestUpdate = (void *)CC_SHA224_Update; hmacCtx->digestFinal = (void *)CC_SHA224_Final; break; case kCCHmacAlgSHA256: hmacCtx->digestLen = CC_SHA256_DIGEST_LENGTH; hmacCtx->blockLen = CC_SHA256_BLOCK_BYTES; hmacCtx->digestInit = (void *)CC_SHA256_Init; hmacCtx->digestUpdate = (void *)CC_SHA256_Update; hmacCtx->digestFinal = (void *)CC_SHA256_Final; break; case kCCHmacAlgSHA384: hmacCtx->digestLen = CC_SHA384_DIGEST_LENGTH; hmacCtx->blockLen = CC_SHA384_BLOCK_BYTES; hmacCtx->digestInit = (void *)CC_SHA384_Init; hmacCtx->digestUpdate = (void *)CC_SHA384_Update; hmacCtx->digestFinal = (void *)CC_SHA384_Final; break; case kCCHmacAlgSHA512: hmacCtx->digestLen = CC_SHA512_DIGEST_LENGTH; hmacCtx->blockLen = CC_SHA512_BLOCK_BYTES; hmacCtx->digestInit = (void *)CC_SHA512_Init; hmacCtx->digestUpdate = (void *)CC_SHA512_Update; hmacCtx->digestFinal = (void *)CC_SHA512_Final; break; default: return; } hmacCtx->digestInit(&hmacCtx->digest); /* If the key is longer than block size, reset it to key=digest(key) */ if (keyLength <= hmacCtx->blockLen) keyP = (uint8_t *)key; else { hmacCtx->digestUpdate(&hmacCtx->digest, key, keyLength); hmacCtx->digestFinal(tk, &hmacCtx->digest); keyP = tk; keyLength = hmacCtx->digestLen; hmacCtx->digestInit(&hmacCtx->digest); } /* The HMAC_<DIG> transform looks like: <DIG> (K XOR opad || <DIG> (K XOR ipad || text)) Where K is a n byte key ipad is the byte 0x36 repeated 64 times. opad is the byte 0x5c repeated 64 times. text is the data being protected. */ /* Copy the key into k_ipad and k_opad while doing the XOR. */ for (byte = 0; byte < keyLength; byte++) { k_ipad[byte] = keyP[byte] ^ 0x36; hmacCtx->k_opad[byte] = keyP[byte] ^ 0x5c; } /* Fill the remainder of k_ipad and k_opad with 0 XORed with the appropriate value. */ if (keyLength < hmacCtx->blockLen) { memset (k_ipad + keyLength, 0x36, hmacCtx->blockLen - keyLength); memset (hmacCtx->k_opad + keyLength, 0x5c, hmacCtx->blockLen - keyLength); } hmacCtx->digestUpdate(&hmacCtx->digest, k_ipad, hmacCtx->blockLen);}
void CCHmacUpdate( CCHmacContext *ctx, const void *dataIn, size_t dataInLength) /* length of data in bytes */{ _CCHmacContext *hmacCtx = (_CCHmacContext *)ctx; hmacCtx->digestUpdate(&hmacCtx->digest, dataIn, dataInLength);}
void CCHmacFinal( CCHmacContext *ctx, void *macOut){ _CCHmacContext *hmacCtx = (_CCHmacContext *)ctx; hmacCtx->digestFinal(macOut, &hmacCtx->digest); hmacCtx->digestInit(&hmacCtx->digest); /* Perform outer digest */ hmacCtx->digestUpdate(&hmacCtx->digest, hmacCtx->k_opad, hmacCtx->blockLen); hmacCtx->digestUpdate(&hmacCtx->digest, macOut, hmacCtx->digestLen); hmacCtx->digestFinal(macOut, &hmacCtx->digest);}
/* * Stateless, one-shot HMAC function. * Output is written to caller-spullied buffer, as in CCHmacFinal(). */void CCHmac( CCHmacAlgorithm algorithm, /* kCCHmacSHA1, kCCHmacMD5 */ const void *key, size_t keyLength, /* length of key in bytes */ const void *data, size_t dataLength, /* length of data in bytes */ void *macOut) /* MAC written here */{ CCHmacContext ctx; CCHmacInit(&ctx, algorithm, key, keyLength); CCHmacUpdate(&ctx, data, dataLength); CCHmacFinal(&ctx, macOut);}