]>
git.saurik.com Git - apple/security.git/blob - AppleCSP/PBKDF2/HMACSHA1.c
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
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
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.
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>
26 #include <MiscCSPAlgs/SHA1.h>
27 #include <MiscCSPAlgs/MD5.h>
29 #include <stdlib.h> // for malloc - maybe we should use CssmAllocator?
30 #include <Security/cssmerr.h>
32 #pragma mark --- Common digest class ---
36 sha1Obj sha1Context
; // must be allocd via sha1Alloc
37 struct MD5Context md5Context
;
42 /* Ops on a DigestCtx */
43 static CSSM_RETURN
DigestCtxInit(
48 if(ctx
->dig
.sha1Context
== NULL
) {
49 ctx
->dig
.sha1Context
= sha1Alloc();
50 if(ctx
->dig
.sha1Context
== NULL
) {
51 return CSSMERR_CSP_MEMORY_ERROR
;
55 sha1Reinit(ctx
->dig
.sha1Context
);
59 MD5Init(&ctx
->dig
.md5Context
);
65 static void DigestCtxFree(
69 sha1Free(ctx
->dig
.sha1Context
);
71 memset(ctx
, 0, sizeof(DigestCtx
));
74 static void DigestCtxUpdate(
80 sha1AddData(ctx
->dig
.sha1Context
, (unsigned char *)textPtr
, textLen
);
83 MD5Update(&ctx
->dig
.md5Context
, (unsigned char *)textPtr
, textLen
);
87 static void DigestCtxFinal(
92 sha1GetDigest(ctx
->dig
.sha1Context
, (unsigned char *)digest
);
95 MD5Final(&ctx
->dig
.md5Context
, (unsigned char *)digest
);
99 #pragma mark --- HMAC class ---
103 UInt8 k_opad
[kSHA1BlockSize
];
106 hmacContextRef
hmacAlloc()
108 hmacContextRef hmac
= (hmacContextRef
)malloc(sizeof(struct hmacContext
));
109 memset(hmac
, 0, sizeof(struct hmacContext
));
117 DigestCtxFree(&hmac
->digest
);
118 memset(hmac
, 0, sizeof(struct hmacContext
));
124 CSSM_RETURN
hmacInit(
128 CSSM_BOOL isSha1
) // true -> SHA1; false -> MD5
130 UInt8 tk
[kSHA1DigestSize
];
133 UInt8 k_ipad
[kSHA1BlockSize
];
134 UInt32 digestSize
= sha1Digest
? kSHA1DigestSize
: MD5_DIGEST_SIZE
;
136 DigestCtxInit(&hmac
->digest
, isSha1
);
138 /* If the key is longer than kSHA1BlockSize reset it to key=digest(key) */
139 if (keyLen
<= kSHA1BlockSize
)
140 key
= (UInt8
*)keyPtr
;
142 DigestCtxUpdate(&hmac
->digest
, (UInt8
*)keyPtr
, keyLen
);
143 DigestCtxFinal(&hmac
->digest
, tk
);
146 DigestCtxInit(&hmac
->digest
, isSha1
);
149 /* The HMAC_<DIG> transform looks like:
150 <DIG> (K XOR opad || <DIG> (K XOR ipad || text))
151 Where K is a n byte key
152 ipad is the byte 0x36 repeated 64 times.
153 opad is the byte 0x5c repeated 64 times.
154 text is the data being protected.
156 /* Copy the key into k_ipad and k_opad while doing the XOR. */
157 for (byte
= 0; byte
< keyLen
; byte
++)
159 k_ipad
[byte
] = key
[byte
] ^ 0x36;
160 hmac
->k_opad
[byte
] = key
[byte
] ^ 0x5c;
162 /* Fill the remainder of k_ipad and k_opad with 0 XORed with the appropriate value. */
163 if (keyLen
< kSHA1BlockSize
)
165 memset (k_ipad
+ keyLen
, 0x36, kSHA1BlockSize
- keyLen
);
166 memset (hmac
->k_opad
+ keyLen
, 0x5c, kSHA1BlockSize
- keyLen
);
168 DigestCtxUpdate(&hmac
->digest
, k_ipad
, kSHA1BlockSize
);
172 CSSM_RETURN
hmacUpdate(
177 DigestCtxUpdate(&hmac
->digest
, textPtr
, textLen
);
181 CSSM_RETURN
hmacFinal(
183 void *resultPtr
) // caller mallocs, must be appropriate output size for
184 // current digest algorithm
186 UInt32 digestSize
= hmac
->digest
.isSha1
? kSHA1DigestSize
: kHMACMD5DigestSize
;
188 DigestCtxFinal(&hmac
->digest
, resultPtr
);
189 DigestCtxInit(&hmac
->digest
, hmac
->digest
.isSha1
);
190 /* Perform outer digest */
191 DigestCtxUpdate(&hmac
->digest
, hmac
->k_opad
, kSHA1BlockSize
);
192 DigestCtxUpdate(&hmac
->digest
, resultPtr
, digestSize
);
193 DigestCtxFinal(&hmac
->digest
, resultPtr
);
197 /* one-shot, ignoring memory errors. */
199 hmacsha1 (const void *keyPtr
, UInt32 keyLen
,
200 const void *textPtr
, UInt32 textLen
,
203 hmacContextRef hmac
= hmacAlloc();
204 hmacInit(hmac
, keyPtr
, keyLen
, CSSM_TRUE
);
205 hmacUpdate(hmac
, textPtr
, textLen
);
206 hmacFinal(hmac
, resultPtr
);