]> git.saurik.com Git - apple/security.git/blob - AppleCSP/PBKDF2/HMACSHA1.c
Security-28.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 <CryptKit/SHA1.h>
27 #include <string.h>
28 #include <stdlib.h> // for malloc - maybe we should use CssmAllocator?
29 #include <Security/cssmerr.h>
30
31 struct hmacContext {
32 sha1Obj sha1Context;
33 UInt8 k_opad[kSHA1BlockSize];
34 };
35
36 hmacContextRef hmacAlloc()
37 {
38 hmacContextRef hmac = (hmacContextRef)malloc(sizeof(struct hmacContext));
39 memset(hmac, 0, sizeof(struct hmacContext));
40 return hmac;
41 }
42
43 void hmacFree(
44 hmacContextRef hmac)
45 {
46 if(hmac != NULL) {
47 if(hmac->sha1Context != NULL) {
48 sha1Free (hmac->sha1Context);
49 }
50 memset(hmac, 0, sizeof(struct hmacContext));
51 free(hmac);
52 }
53 }
54
55 /* reusable init */
56 CSSM_RETURN hmacInit(
57 hmacContextRef hmac,
58 const void *keyPtr,
59 UInt32 keyLen)
60 {
61 UInt8 tk[kSHA1DigestSize];
62 UInt8 *key;
63 UInt32 byte;
64 UInt8 k_ipad[kSHA1BlockSize];
65
66 if(hmac->sha1Context == NULL) {
67 hmac->sha1Context = sha1Alloc();
68 if(hmac->sha1Context == NULL) {
69 return CSSMERR_CSP_MEMORY_ERROR;
70 }
71 }
72 else {
73 sha1Reinit(hmac->sha1Context);
74 }
75
76 /* If the key is longer than kSHA1BlockSize reset it to key=SHA1(key) */
77 if (keyLen <= kSHA1BlockSize)
78 key = (UInt8*)keyPtr;
79 else {
80 sha1AddData(hmac->sha1Context, (UInt8*)keyPtr, keyLen);
81 memcpy (tk, sha1Digest(hmac->sha1Context), kSHA1DigestSize);
82 key = tk;
83 keyLen = kSHA1DigestSize;
84 sha1Reinit (hmac->sha1Context);
85 }
86
87 /* The HMAC_SHA_1 transform looks like:
88 SHA1 (K XOR opad || SHA1 (K XOR ipad || text))
89 Where K is a n byte key
90 ipad is the byte 0x36 repeated 64 times.
91 opad is the byte 0x5c repeated 64 times.
92 text is the data being protected.
93 */
94 /* Copy the key into k_ipad and k_opad while doing the XOR. */
95 for (byte = 0; byte < keyLen; byte++)
96 {
97 k_ipad[byte] = key[byte] ^ 0x36;
98 hmac->k_opad[byte] = key[byte] ^ 0x5c;
99 }
100 /* Fill the remainder of k_ipad and k_opad with 0 XORed with the appropriate value. */
101 if (keyLen < kSHA1BlockSize)
102 {
103 memset (k_ipad + keyLen, 0x36, kSHA1BlockSize - keyLen);
104 memset (hmac->k_opad + keyLen, 0x5c, kSHA1BlockSize - keyLen);
105 }
106 sha1AddData (hmac->sha1Context, k_ipad, kSHA1BlockSize);
107 return CSSM_OK;
108 }
109
110 CSSM_RETURN hmacUpdate(
111 hmacContextRef hmac,
112 const void *textPtr,
113 UInt32 textLen)
114 {
115 sha1AddData (hmac->sha1Context, (UInt8*)textPtr, textLen);
116 return CSSM_OK;
117 }
118
119 CSSM_RETURN hmacFinal(
120 hmacContextRef hmac,
121 void *resultPtr) // caller mallocs, must be HMACSHA1_OUT_SIZE bytes
122 {
123 memcpy (resultPtr, sha1Digest (hmac->sha1Context), kSHA1DigestSize);
124 sha1Reinit (hmac->sha1Context);
125 /* Perform outer SHA1 */
126 sha1AddData (hmac->sha1Context, hmac->k_opad, kSHA1BlockSize);
127 sha1AddData (hmac->sha1Context, (UInt8*)resultPtr, kSHA1DigestSize);
128 memcpy (resultPtr, sha1Digest (hmac->sha1Context), kSHA1DigestSize);
129 return CSSM_OK;
130 }
131
132 /* one-shot, ignoring memory errors. */
133 void
134 hmacsha1 (const void *keyPtr, UInt32 keyLen,
135 const void *textPtr, UInt32 textLen,
136 void *resultPtr)
137 {
138 hmacContextRef hmac = hmacAlloc();
139 hmacInit(hmac, keyPtr, keyLen);
140 hmacUpdate(hmac, textPtr, textLen);
141 hmacFinal(hmac, resultPtr);
142 hmacFree(hmac);
143 }
144