]> git.saurik.com Git - apple/security.git/blob - SecureTransport/tls_hmac.cpp
Security-179.tar.gz
[apple/security.git] / SecureTransport / tls_hmac.cpp
1 /*
2 * Copyright (c) 2002 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: tls_hmac.c
21
22 Contains: HMAC routines used by TLS
23
24 Written by: Doug Mitchell
25 */
26
27 #include "tls_hmac.h"
28 #include "appleCdsa.h"
29 #include "sslMemory.h"
30 #include "cryptType.h"
31 #include "sslDigests.h"
32 #include <strings.h>
33 #include <assert.h>
34 #include <Security/cssm.h>
35
36 /* Per-session state, opaque to callers; all fields set at alloc time */
37 struct HMACContext {
38 SSLContext *ctx;
39 CSSM_CC_HANDLE ccHand;
40 const struct HMACReference *hmac;
41 };
42
43 #pragma mark *** Common CDSA_based HMAC routines ***
44
45 /* Create an HMAC session */
46 static OSStatus HMAC_Alloc(
47 const struct HMACReference *hmac,
48 SSLContext *ctx,
49 const void *keyPtr,
50 unsigned keyLen,
51 HMACContextRef *hmacCtx) // RETURNED
52 {
53 CSSM_RETURN crtn;
54 CSSM_KEY cssmKey;
55 OSStatus serr;
56 CSSM_ALGORITHMS calg;
57 HMACContextRef href = (HMACContextRef)sslMalloc(sizeof(struct HMACContext));
58
59 if(href == NULL) {
60 return memFullErr;
61 }
62 href->ctx = ctx;
63 href->ccHand = 0;
64 href->hmac = hmac;
65
66 /*
67 * Since the key is present in the CDSA context, we cook up the context now.
68 * Currently we can't reuse an HMAC context if the key changes.
69 */
70 switch(hmac->alg) {
71 case HA_SHA1:
72 calg = CSSM_ALGID_SHA1HMAC;
73 break;
74 case HA_MD5:
75 calg = CSSM_ALGID_MD5HMAC;
76 break;
77 default:
78 assert(0);
79 return errSSLInternal;
80 }
81 serr = sslSetUpSymmKey(&cssmKey,
82 calg,
83 CSSM_KEYUSE_SIGN | CSSM_KEYUSE_VERIFY,
84 CSSM_FALSE, /* don't malloc/copy key */
85 (uint8 *)keyPtr,
86 keyLen);
87 if(serr) {
88 return serr;
89 }
90 if(attachToCsp(ctx)) {
91 return serr;
92 }
93 crtn = CSSM_CSP_CreateMacContext(ctx->cspHand,
94 calg,
95 &cssmKey,
96 &href->ccHand);
97 if(crtn) {
98 stPrintCdsaError("CSSM_CSP_CreateMacContext", crtn);
99 return errSSLCrypto;
100 }
101
102 /* success */
103 *hmacCtx = href;
104 return noErr;
105 }
106
107 /* free a session */
108 static OSStatus HMAC_Free(
109 HMACContextRef hmacCtx)
110 {
111 if(hmacCtx != NULL) {
112 if(hmacCtx->ccHand != 0) {
113 CSSM_DeleteContext(hmacCtx->ccHand);
114 hmacCtx->ccHand = 0;
115 }
116 sslFree(hmacCtx);
117 }
118 return noErr;
119 }
120
121 /* Reusable init */
122 static OSStatus HMAC_Init(
123 HMACContextRef hmacCtx)
124 {
125 CSSM_RETURN crtn;
126
127 if(hmacCtx == NULL) {
128 return errSSLInternal;
129 }
130 assert(hmacCtx->ctx != NULL);
131 assert(hmacCtx->hmac != NULL);
132 assert(hmacCtx->ccHand != 0);
133
134 crtn = CSSM_GenerateMacInit(hmacCtx->ccHand);
135 if(crtn) {
136 stPrintCdsaError("CSSM_GenerateMacInit", crtn);
137 return errSSLCrypto;
138 }
139 return noErr;
140 }
141
142 /* normal crypt ops */
143 static OSStatus HMAC_Update(
144 HMACContextRef hmacCtx,
145 const void *data,
146 unsigned dataLen)
147 {
148 CSSM_RETURN crtn;
149 CSSM_DATA cdata;
150
151 if(hmacCtx == NULL) {
152 return errSSLInternal;
153 }
154 assert(hmacCtx->ctx != NULL);
155 assert(hmacCtx->hmac != NULL);
156 assert(hmacCtx->ccHand != 0);
157 cdata.Data = (uint8 *)data;
158 cdata.Length = dataLen;
159 crtn = CSSM_GenerateMacUpdate(hmacCtx->ccHand, &cdata, 1);
160 if(crtn) {
161 stPrintCdsaError("CSSM_GenerateMacUpdate", crtn);
162 return errSSLCrypto;
163 }
164 return noErr;
165 }
166
167 static OSStatus HMAC_Final(
168 HMACContextRef hmacCtx,
169 void *hmac, // mallocd by caller
170 unsigned *hmacLen) // IN/OUT
171 {
172 CSSM_RETURN crtn;
173 CSSM_DATA cdata;
174
175 if(hmacCtx == NULL) {
176 return errSSLInternal;
177 }
178 if((hmac == NULL) || (hmacLen == 0)) {
179 return errSSLInternal;
180 }
181 assert(hmacCtx->ctx != NULL);
182 assert(hmacCtx->hmac != NULL);
183 assert(hmacCtx->ccHand != 0);
184 cdata.Data = (uint8 *)hmac;
185 cdata.Length = *hmacLen;
186 crtn = CSSM_GenerateMacFinal(hmacCtx->ccHand, &cdata);
187 if(crtn) {
188 stPrintCdsaError("CSSM_GenerateMacFinal", crtn);
189 return errSSLCrypto;
190 }
191 *hmacLen = cdata.Length;
192 return noErr;
193 }
194
195 /* one-shot */
196 static OSStatus HMAC_Hmac (
197 HMACContextRef hmacCtx,
198 const void *data,
199 unsigned dataLen,
200 void *hmac, // mallocd by caller
201 unsigned *hmacLen) // IN/OUT
202 {
203 OSStatus serr;
204 const HMACReference *hmacRef;
205
206 if(hmacCtx == NULL) {
207 return errSSLInternal;
208 }
209 hmacRef = hmacCtx->hmac;
210 assert(hmacRef != NULL);
211 serr = hmacRef->init(hmacCtx);
212 if(serr) {
213 return serr;
214 }
215 serr = hmacRef->update(hmacCtx, data, dataLen);
216 if(serr) {
217 return serr;
218 }
219 return hmacRef->final(hmacCtx, hmac, hmacLen);
220 }
221
222 #pragma mark *** Null HMAC ***
223
224 static OSStatus HMAC_AllocNull(
225 const struct HMACReference *hmac,
226 SSLContext *ctx,
227 const void *keyPtr,
228 unsigned keyLen,
229 HMACContextRef *hmacCtx) // RETURNED
230 {
231 *hmacCtx = NULL;
232 return noErr;
233 }
234
235 static OSStatus HMAC_FreeNull(
236 HMACContextRef hmacCtx)
237 {
238 return noErr;
239 }
240
241 static OSStatus HMAC_InitNull(
242 HMACContextRef hmacCtx)
243 {
244 return noErr;
245 }
246
247 static OSStatus HMAC_UpdateNull(
248 HMACContextRef hmacCtx,
249 const void *data,
250 unsigned dataLen)
251 {
252 return noErr;
253 }
254
255 static OSStatus HMAC_FinalNull(
256 HMACContextRef hmacCtx,
257 void *hmac, // mallocd by caller
258 unsigned *hmacLen) // IN/OUT
259 {
260 return noErr;
261 }
262
263 static OSStatus HMAC_HmacNull (
264 HMACContextRef hmacCtx,
265 const void *data,
266 unsigned dataLen,
267 void *hmac, // mallocd by caller
268 unsigned *hmacLen)
269 {
270 return noErr;
271 }
272
273 const HMACReference TlsHmacNull = {
274 0,
275 HA_Null,
276 HMAC_AllocNull,
277 HMAC_FreeNull,
278 HMAC_InitNull,
279 HMAC_UpdateNull,
280 HMAC_FinalNull,
281 HMAC_HmacNull
282 };
283
284 const HMACReference TlsHmacSHA1 = {
285 20,
286 HA_SHA1,
287 HMAC_Alloc,
288 HMAC_Free,
289 HMAC_Init,
290 HMAC_Update,
291 HMAC_Final,
292 HMAC_Hmac
293 };
294
295 const HMACReference TlsHmacMD5 = {
296 16,
297 HA_MD5,
298 HMAC_Alloc,
299 HMAC_Free,
300 HMAC_Init,
301 HMAC_Update,
302 HMAC_Final,
303 HMAC_Hmac
304 };
305
306 const HashHmacReference HashHmacNull = {
307 &SSLHashNull,
308 &TlsHmacNull
309 };
310
311 const HashHmacReference HashHmacMD5 = {
312 &SSLHashMD5,
313 &TlsHmacMD5
314 };
315
316 const HashHmacReference HashHmacSHA1 = {
317 &SSLHashSHA1,
318 &TlsHmacSHA1
319 };