]> git.saurik.com Git - apple/security.git/blob - AppleCSP/PBKDF2/HMACSHA1.c
Security-163.tar.gz
[apple/security.git] / AppleCSP / PBKDF2 / HMACSHA1.c
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 /*
20 File: HMACSHA1.c
21 Contains: Apple Data Security Services HMACSHA1 function definition.
22 Copyright: (C) 1999 by Apple Computer, Inc., all rights reserved
23 Written by: Michael Brouwer <mb@apple.com>
24 */
25 #include "HMACSHA1.h"
26 #include "pbkdDigest.h"
27 #include <MiscCSPAlgs/SHA1.h>
28 #include <MiscCSPAlgs/MD5.h>
29 #include <string.h>
30 #include <stdlib.h> // for malloc - maybe we should use CssmAllocator?
31 #include <Security/cssmerr.h>
32
33
34
35 struct hmacContext {
36 DigestCtx digest;
37 UInt8 k_opad[kSHA1BlockSize];
38 };
39
40 hmacContextRef hmacAlloc()
41 {
42 hmacContextRef hmac = (hmacContextRef)malloc(sizeof(struct hmacContext));
43 memset(hmac, 0, sizeof(struct hmacContext));
44 return hmac;
45 }
46
47 void hmacFree(
48 hmacContextRef hmac)
49 {
50 if(hmac != NULL) {
51 DigestCtxFree(&hmac->digest);
52 memset(hmac, 0, sizeof(struct hmacContext));
53 free(hmac);
54 }
55 }
56
57 /* reusable init */
58 CSSM_RETURN hmacInit(
59 hmacContextRef hmac,
60 const void *keyPtr,
61 UInt32 keyLen,
62 CSSM_BOOL isSha1) // true -> SHA1; false -> MD5
63 {
64 UInt8 tk[kSHA1DigestSize];
65 UInt8 *key;
66 UInt32 byte;
67 UInt8 k_ipad[kSHA1BlockSize];
68 UInt32 digestSize = sha1Digest ? kSHA1DigestSize : MD5_DIGEST_SIZE;
69
70 DigestCtxInit(&hmac->digest, isSha1);
71
72 /* If the key is longer than kSHA1BlockSize reset it to key=digest(key) */
73 if (keyLen <= kSHA1BlockSize)
74 key = (UInt8*)keyPtr;
75 else {
76 DigestCtxUpdate(&hmac->digest, (UInt8*)keyPtr, keyLen);
77 DigestCtxFinal(&hmac->digest, tk);
78 key = tk;
79 keyLen = digestSize;
80 DigestCtxInit(&hmac->digest, isSha1);
81 }
82
83 /* The HMAC_<DIG> transform looks like:
84 <DIG> (K XOR opad || <DIG> (K XOR ipad || text))
85 Where K is a n byte key
86 ipad is the byte 0x36 repeated 64 times.
87 opad is the byte 0x5c repeated 64 times.
88 text is the data being protected.
89 */
90 /* Copy the key into k_ipad and k_opad while doing the XOR. */
91 for (byte = 0; byte < keyLen; byte++)
92 {
93 k_ipad[byte] = key[byte] ^ 0x36;
94 hmac->k_opad[byte] = key[byte] ^ 0x5c;
95 }
96 /* Fill the remainder of k_ipad and k_opad with 0 XORed with the appropriate value. */
97 if (keyLen < kSHA1BlockSize)
98 {
99 memset (k_ipad + keyLen, 0x36, kSHA1BlockSize - keyLen);
100 memset (hmac->k_opad + keyLen, 0x5c, kSHA1BlockSize - keyLen);
101 }
102 DigestCtxUpdate(&hmac->digest, k_ipad, kSHA1BlockSize);
103 return CSSM_OK;
104 }
105
106 CSSM_RETURN hmacUpdate(
107 hmacContextRef hmac,
108 const void *textPtr,
109 UInt32 textLen)
110 {
111 DigestCtxUpdate(&hmac->digest, textPtr, textLen);
112 return CSSM_OK;
113 }
114
115 CSSM_RETURN hmacFinal(
116 hmacContextRef hmac,
117 void *resultPtr) // caller mallocs, must be appropriate output size for
118 // current digest algorithm
119 {
120 UInt32 digestSize = hmac->digest.isSha1 ? kSHA1DigestSize : kHMACMD5DigestSize;
121
122 DigestCtxFinal(&hmac->digest, resultPtr);
123 DigestCtxInit(&hmac->digest, hmac->digest.isSha1);
124 /* Perform outer digest */
125 DigestCtxUpdate(&hmac->digest, hmac->k_opad, kSHA1BlockSize);
126 DigestCtxUpdate(&hmac->digest, resultPtr, digestSize);
127 DigestCtxFinal(&hmac->digest, resultPtr);
128 return CSSM_OK;
129 }
130
131 /* one-shot, ignoring memory errors. */
132 void
133 hmacsha1 (const void *keyPtr, UInt32 keyLen,
134 const void *textPtr, UInt32 textLen,
135 void *resultPtr)
136 {
137 hmacContextRef hmac = hmacAlloc();
138 hmacInit(hmac, keyPtr, keyLen, CSSM_TRUE);
139 hmacUpdate(hmac, textPtr, textLen);
140 hmacFinal(hmac, resultPtr);
141 hmacFree(hmac);
142 }
143