]> git.saurik.com Git - apple/security.git/blob - SecureTransport/sslDigests.cpp
Security-179.tar.gz
[apple/security.git] / SecureTransport / sslDigests.cpp
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: sslDigests.cpp
21
22 Contains: interface between SSL and SHA, MD5 digest implementations
23
24 Written by: Doug Mitchell
25
26 Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved.
27
28 */
29
30 #include "sslContext.h"
31 #include "cryptType.h"
32 #include "sslMemory.h"
33 #include "sslDigests.h"
34 #include "sslDebug.h"
35 #include "appleCdsa.h"
36 #include <Security/cssm.h>
37 #include <string.h>
38
39 #define DIGEST_PRINT 0
40 #if DIGEST_PRINT
41 #define dgprintf(s) printf s
42 #else
43 #define dgprintf(s)
44 #endif
45
46 /*
47 * Common digest context. The SSLBuffer.data pointer in a "digest state" argument
48 * casts to one of these.
49 */
50 typedef struct {
51 CSSM_CC_HANDLE hashHand;
52 } cdsaHashContext;
53
54 const UInt8 SSLMACPad1[MAX_MAC_PADDING] =
55 {
56 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
57 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
58 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
59 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
60 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
61 0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36
62 };
63
64 const UInt8 SSLMACPad2[MAX_MAC_PADDING] =
65 {
66 0x5C,0x5C,0x5C,0x5C,0x5C,0x5C,0x5C,0x5C,
67 0x5C,0x5C,0x5C,0x5C,0x5C,0x5C,0x5C,0x5C,
68 0x5C,0x5C,0x5C,0x5C,0x5C,0x5C,0x5C,0x5C,
69 0x5C,0x5C,0x5C,0x5C,0x5C,0x5C,0x5C,0x5C,
70 0x5C,0x5C,0x5C,0x5C,0x5C,0x5C,0x5C,0x5C,
71 0x5C,0x5C,0x5C,0x5C,0x5C,0x5C,0x5C,0x5C
72 };
73
74 /*
75 * Public general hash functions
76 */
77
78 /*
79 * A convenience wrapper for HashReference.clone, which has the added benefit of
80 * allocating the state buffer for the caller.
81 */
82 OSStatus
83 CloneHashState(
84 const HashReference &ref,
85 const SSLBuffer &state,
86 SSLBuffer &newState,
87 SSLContext *ctx)
88 {
89 OSStatus err;
90 if ((err = SSLAllocBuffer(newState, ref.contextSize, ctx)) != 0)
91 return err;
92 return ref.clone(state, newState);
93 }
94
95 /*
96 * Wrapper for HashReference.init.
97 */
98 OSStatus
99 ReadyHash(const HashReference &ref, SSLBuffer &state, SSLContext *ctx)
100 {
101 OSStatus err;
102 if ((err = SSLAllocBuffer(state, ref.contextSize, ctx)) != 0)
103 return err;
104 return ref.init(state, ctx);
105 }
106
107 /*
108 * Wrapper for HashReference.clone. Tolerates NULL digestCtx and frees it if it's
109 * there.
110 */
111 OSStatus CloseHash(const HashReference &ref, SSLBuffer &state, SSLContext *ctx)
112 {
113 OSStatus serr;
114
115 if(state.data == NULL) {
116 return noErr;
117 }
118 serr = ref.close(state, ctx);
119 if(serr) {
120 return serr;
121 }
122 return SSLFreeBuffer(state, ctx);
123 }
124
125 static OSStatus HashNullInit(SSLBuffer &digestCtx, SSLContext *sslCtx);
126 static OSStatus HashNullUpdate(SSLBuffer &digestCtx, const SSLBuffer &data);
127 static OSStatus HashNullFinal(SSLBuffer &digestCtx, SSLBuffer &digest);
128 static OSStatus HashNullClose(SSLBuffer &digestCtx, SSLContext *sslCtx);
129 static OSStatus HashNullClone(const SSLBuffer &src, SSLBuffer &dst);
130
131 static OSStatus HashMD5Init(SSLBuffer &digestCtx, SSLContext *sslCtx);
132 static OSStatus HashSHA1Init(SSLBuffer &digestCtx, SSLContext *sslCtx);
133 static OSStatus cdsaHashInit(SSLBuffer &digestCtx, SSLContext *sslCtx,
134 CSSM_ALGORITHMS digestAlg);
135 static OSStatus cdsaHashUpdate(SSLBuffer &digestCtx, const SSLBuffer &data);
136 static OSStatus cdsaHashFinal(SSLBuffer &digestCtx, SSLBuffer &digest);
137 static OSStatus cdsaHashClose(SSLBuffer &digestCtx, SSLContext *sslCtx);
138 static OSStatus cdsaHashClone(const SSLBuffer &src, SSLBuffer &dest);
139
140 /*
141 * These are the handles by which the bulk of digesting work
142 * is done.
143 */
144 const HashReference SSLHashNull =
145 {
146 0,
147 0,
148 0,
149 HashNullInit,
150 HashNullUpdate,
151 HashNullFinal,
152 HashNullClose,
153 HashNullClone
154 };
155
156 const HashReference SSLHashMD5 =
157 {
158 sizeof(cdsaHashContext),
159 16,
160 48,
161 HashMD5Init,
162 cdsaHashUpdate,
163 cdsaHashFinal,
164 cdsaHashClose,
165 cdsaHashClone
166 };
167
168 const HashReference SSLHashSHA1 =
169 {
170 sizeof(cdsaHashContext),
171 20,
172 40,
173 HashSHA1Init,
174 cdsaHashUpdate,
175 cdsaHashFinal,
176 cdsaHashClose,
177 cdsaHashClone
178 };
179
180 /*** NULL ***/
181 static OSStatus HashNullInit(SSLBuffer &digestCtx, SSLContext *sslCtx) {
182 return noErr;
183 }
184
185 static OSStatus HashNullUpdate(SSLBuffer &digestCtx, const SSLBuffer &data) {
186 return noErr;
187 }
188
189 static OSStatus HashNullFinal(SSLBuffer &digestCtx, SSLBuffer &digest) {
190 return noErr;
191 }
192 static OSStatus HashNullClose(SSLBuffer &digestCtx, SSLContext *sslCtx) {
193 return noErr;
194 }
195 static OSStatus HashNullClone(const SSLBuffer &src, SSLBuffer &dest) {
196 return noErr;
197 }
198
199 static OSStatus HashMD5Init(SSLBuffer &digestCtx, SSLContext *sslCtx)
200 {
201 assert(digestCtx.length >= sizeof(cdsaHashContext));
202 return cdsaHashInit(digestCtx, sslCtx, CSSM_ALGID_MD5);
203 }
204
205 static OSStatus HashSHA1Init(SSLBuffer &digestCtx, SSLContext *sslCtx)
206 {
207 assert(digestCtx.length >= sizeof(cdsaHashContext));
208 return cdsaHashInit(digestCtx, sslCtx, CSSM_ALGID_SHA1);
209 }
210
211 /* common digest functions via CDSA */
212 static OSStatus cdsaHashInit(SSLBuffer &digestCtx,
213 SSLContext *sslCtx,
214 CSSM_ALGORITHMS digestAlg)
215 {
216 OSStatus serr;
217 cdsaHashContext *cdsaCtx;
218 CSSM_CC_HANDLE hashHand = 0;
219 CSSM_RETURN crtn;
220
221 assert(digestCtx.length >= sizeof(cdsaHashContext));
222 serr = attachToCsp(sslCtx); // should be a nop
223 if(serr) {
224 return serr;
225 }
226 cdsaCtx = (cdsaHashContext *)digestCtx.data;
227 cdsaCtx->hashHand = 0;
228 dgprintf(("###cdsaHashInit cdsaCtx %p\n", cdsaCtx));
229
230 /* cook up a digest context, initialize it */
231 crtn = CSSM_CSP_CreateDigestContext(sslCtx->cspHand,
232 digestAlg,
233 &hashHand);
234 if(crtn) {
235 sslErrorLog("CSSM_CSP_CreateDigestContext failure\n");
236 return errSSLCrypto;
237 }
238 crtn = CSSM_DigestDataInit(hashHand);
239 if(crtn) {
240 CSSM_DeleteContext(hashHand);
241 sslErrorLog("CSSM_DigestDataInit failure\n");
242 return errSSLCrypto;
243 }
244 cdsaCtx->hashHand = hashHand;
245 return noErr;
246 }
247
248 static OSStatus cdsaHashUpdate(SSLBuffer &digestCtx, const SSLBuffer &data)
249 {
250 cdsaHashContext *cdsaCtx;
251 CSSM_RETURN crtn;
252 CSSM_DATA cdata;
253
254 assert(digestCtx.length >= sizeof(cdsaHashContext));
255 cdsaCtx = (cdsaHashContext *)digestCtx.data;
256 //dgprintf(("###cdsaHashUpdate cdsaCtx %p\n", cdsaCtx));
257
258 SSLBUF_TO_CSSM(&data, &cdata);
259 crtn = CSSM_DigestDataUpdate(cdsaCtx->hashHand, &cdata, 1);
260 if(crtn) {
261 sslErrorLog("CSSM_DigestDataUpdate failure\n");
262 return errSSLCrypto;
263 }
264 else {
265 return noErr;
266 }
267 }
268
269 static OSStatus cdsaHashFinal(SSLBuffer &digestCtx, SSLBuffer &digest)
270 {
271 cdsaHashContext *cdsaCtx;
272 CSSM_RETURN crtn;
273 CSSM_DATA cdata;
274 OSStatus srtn = noErr;
275
276 assert(digestCtx.length >= sizeof(cdsaHashContext));
277 cdsaCtx = (cdsaHashContext *)digestCtx.data;
278 dgprintf(("###cdsaHashFinal cdsaCtx %p\n", cdsaCtx));
279 SSLBUF_TO_CSSM(&digest, &cdata);
280 crtn = CSSM_DigestDataFinal(cdsaCtx->hashHand, &cdata);
281 if(crtn) {
282 sslErrorLog("CSSM_DigestDataFinal failure\n");
283 srtn = errSSLCrypto;
284 }
285 else {
286 digest.length = cdata.Length;
287 }
288 CSSM_DeleteContext(cdsaCtx->hashHand);
289 cdsaCtx->hashHand = 0;
290 return srtn;
291 }
292
293 static OSStatus cdsaHashClose(SSLBuffer &digestCtx, SSLContext *sslCtx)
294 {
295 cdsaHashContext *cdsaCtx;
296
297 assert(digestCtx.length >= sizeof(cdsaHashContext));
298 cdsaCtx = (cdsaHashContext *)digestCtx.data;
299 dgprintf(("###cdsaHashClose cdsaCtx %p\n", cdsaCtx));
300 if(cdsaCtx->hashHand != 0) {
301 CSSM_DeleteContext(cdsaCtx->hashHand);
302 cdsaCtx->hashHand = 0;
303 }
304 return noErr;
305 }
306
307 static OSStatus cdsaHashClone(const SSLBuffer &src, SSLBuffer &dst)
308 {
309 cdsaHashContext *srcCtx;
310 cdsaHashContext *dstCtx;
311 CSSM_RETURN crtn;
312
313 assert(src.length >= sizeof(cdsaHashContext));
314 assert(dst.length >= sizeof(cdsaHashContext));
315 srcCtx = (cdsaHashContext *)src.data;
316 dstCtx = (cdsaHashContext *)dst.data;
317 dgprintf(("###cdsaHashClone srcCtx %p dstCtx %p\n", srcCtx, dstCtx));
318
319 crtn = CSSM_DigestDataClone(srcCtx->hashHand, &dstCtx->hashHand);
320 if(crtn) {
321 sslErrorLog("CSSM_DigestDataClone failure\n");
322 return errSSLCrypto;
323 }
324 else {
325 return noErr;
326 }
327 }
328