]> git.saurik.com Git - apple/security.git/blob - SecureTransport/hdskcert.c
Security-54.tar.gz
[apple/security.git] / SecureTransport / hdskcert.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: hdskcert.c
21
22 Contains: certificate request/verify messages
23
24 Written by: Doug Mitchell, based on Netscape SSLRef 3.0
25
26 Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved.
27
28 */
29 /* *********************************************************************
30 File: hdskcert.c
31
32 SSLRef 3.0 Final -- 11/19/96
33
34 Copyright (c)1996 by Netscape Communications Corp.
35
36 By retrieving this software you are bound by the licensing terms
37 disclosed in the file "LICENSE.txt". Please read it, and if you don't
38 accept the terms, delete this software.
39
40 SSLRef 3.0 was developed by Netscape Communications Corp. of Mountain
41 View, California <http://home.netscape.com/> and Consensus Development
42 Corporation of Berkeley, California <http://www.consensus.com/>.
43
44 *********************************************************************
45
46 File: hdskcert.c Contains support for certificate-related messages
47
48 Support for encoding and decoding the certificate, certificate
49 request, and certificate verify messages.
50
51 ****************************************************************** */
52
53 #ifndef _SSLCTX_H_
54 #include "sslctx.h"
55 #endif
56
57 #ifndef _SSLHDSHK_H_
58 #include "sslhdshk.h"
59 #endif
60
61 #ifndef _SSLALLOC_H_
62 #include "sslalloc.h"
63 #endif
64
65 #ifndef _SSLALERT_H_
66 #include "sslalert.h"
67 #endif
68
69 #ifndef _SSL_DEBUG_H_
70 #include "sslDebug.h"
71 #endif
72
73 #ifndef _SSLUTIL_H_
74 #include "sslutil.h"
75 #endif
76
77 #ifndef _DIGESTS_H_
78 #include "digests.h"
79 #endif
80
81 #ifndef _APPLE_CDSA_H_
82 #include "appleCdsa.h"
83 #endif
84
85 #ifndef _SSL_DEBUG_H_
86 #include "sslDebug.h"
87 #endif
88
89 #include <string.h>
90 #include <assert.h>
91
92 SSLErr
93 SSLEncodeCertificate(SSLRecord *certificate, SSLContext *ctx)
94 { SSLErr err;
95 UInt32 totalLength;
96 int i, j, certCount;
97 UInt8 *progress;
98 SSLCertificate *cert;
99
100 /* Match DER-encoded root certs here */
101
102 cert = ctx->localCert;
103 CASSERT(cert != 0);
104 totalLength = 0;
105 certCount = 0;
106 while (cert)
107 { totalLength += 3 + cert->derCert.length; /* 3 for encoded length field */
108 ++certCount;
109 cert = cert->next;
110 }
111
112 certificate->contentType = SSL_handshake;
113 assert((ctx->negProtocolVersion == SSL_Version_3_0) ||
114 (ctx->negProtocolVersion == TLS_Version_1_0));
115 certificate->protocolVersion = ctx->negProtocolVersion;
116 if ((err = SSLAllocBuffer(&certificate->contents, totalLength + 7, &ctx->sysCtx)) != 0)
117 return err;
118
119 progress = certificate->contents.data;
120 *progress++ = SSL_certificate;
121 progress = SSLEncodeInt(progress, totalLength+3, 3); /* Handshake message length */
122 progress = SSLEncodeInt(progress, totalLength, 3); /* Vector length */
123
124 /* Root cert is first in the linked list, but has to go last, so walk list backwards */
125 for (i = 0; i < certCount; ++i)
126 { cert = ctx->localCert;
127 for (j = i+1; j < certCount; ++j)
128 cert = cert->next;
129 progress = SSLEncodeInt(progress, cert->derCert.length, 3);
130 memcpy(progress, cert->derCert.data, cert->derCert.length);
131 progress += cert->derCert.length;
132 }
133
134 CASSERT(progress == certificate->contents.data + certificate->contents.length);
135
136 if (ctx->protocolSide == SSL_ClientSide)
137 ctx->certSent = 1;
138
139 return SSLNoErr;
140 }
141
142 SSLErr
143 SSLProcessCertificate(SSLBuffer message, SSLContext *ctx)
144 { SSLErr err;
145 UInt32 listLen, certLen;
146 UInt8 *p;
147 SSLCertificate *cert;
148
149 p = message.data;
150 listLen = SSLDecodeInt(p,3);
151 p += 3;
152 if (listLen + 3 != message.length) {
153 errorLog0("SSLProcessCertificate: length decode error 1\n");
154 return SSLProtocolErr;
155 }
156
157 while (listLen > 0)
158 { certLen = SSLDecodeInt(p,3);
159 p += 3;
160 if (listLen < certLen + 3) {
161 errorLog0("SSLProcessCertificate: length decode error 2\n");
162 return SSLProtocolErr;
163 }
164 cert = (SSLCertificate *)sslMalloc(sizeof(SSLCertificate));
165 if(cert == NULL) {
166 return SSLMemoryErr;
167 }
168 if ((err = SSLAllocBuffer(&cert->derCert, certLen, &ctx->sysCtx)) != 0)
169 { sslFree(cert);
170 return err;
171 }
172 memcpy(cert->derCert.data, p, certLen);
173 p += certLen;
174 cert->next = ctx->peerCert; /* Insert backwards; root cert will be first in linked list */
175 ctx->peerCert = cert;
176 listLen -= 3+certLen;
177 }
178 CASSERT(p == message.data + message.length && listLen == 0);
179
180 if (ctx->peerCert == 0)
181 return X509CertChainInvalidErr;
182
183 if((err = sslVerifyCertChain(ctx, ctx->peerCert)) != 0)
184 return err;
185
186 /* Server's certificate is the last one in the chain */
187 cert = ctx->peerCert;
188 while (cert->next != 0)
189 cert = cert->next;
190 /* Convert its public key to CDSA format */
191 if ((err = sslPubKeyFromCert(ctx,
192 &cert->derCert,
193 &ctx->peerPubKey,
194 &ctx->peerPubKeyCsp)) != 0)
195 return err;
196
197 return SSLNoErr;
198 }
199
200 SSLErr
201 SSLEncodeCertificateRequest(SSLRecord *request, SSLContext *ctx)
202 {
203 #if !ST_SERVER_MODE_ENABLE
204
205 /* cert request only happens in server mode */
206 errorLog0("SSLEncodeCertificateRequest called\n");
207 return SSLUnsupportedErr;
208
209 #else
210
211 SSLErr err;
212 UInt32 dnListLen, msgLen;
213 UInt8 *progress;
214 DNListElem *dn;
215
216 dnListLen = 0;
217 dn = ctx->acceptableDNList;
218 CASSERT(dn != NULL);
219 while (dn)
220 { dnListLen += 2 + dn->derDN.length;
221 dn = dn->next;
222 }
223 msgLen = 1 + 1 + 2 + dnListLen;
224
225 request->contentType = SSL_handshake;
226 assert((ctx->negProtocolVersion == SSL_Version_3_0) ||
227 (ctx->negProtocolVersion == TLS_Version_1_0));
228 request->protocolVersion = ctx->negProtocolVersion;
229 if ((err = SSLAllocBuffer(&request->contents, msgLen + 4, &ctx->sysCtx)) != 0)
230 return err;
231
232 progress = request->contents.data;
233 *progress++ = SSL_certificate_request;
234 progress = SSLEncodeInt(progress, msgLen, 3);
235
236 *progress++ = 1; /* one cert type */
237 *progress++ = 1; /* RSA-sign type */
238 progress = SSLEncodeInt(progress, dnListLen, 2);
239 dn = ctx->acceptableDNList;
240 while (dn)
241 { progress = SSLEncodeInt(progress, dn->derDN.length, 2);
242 memcpy(progress, dn->derDN.data, dn->derDN.length);
243 progress += dn->derDN.length;
244 dn = dn->next;
245 }
246
247 CASSERT(progress == request->contents.data + request->contents.length);
248
249 return SSLNoErr;
250 #endif /* ST_SERVER_MODE_ENABLE */
251 }
252
253 SSLErr
254 SSLProcessCertificateRequest(SSLBuffer message, SSLContext *ctx)
255 { SSLErr err;
256 int i, dnListLen, dnLen;
257 unsigned int typeCount;
258 UInt8 *progress;
259 SSLBuffer dnBuf;
260 DNListElem *dn;
261
262 /* cert request only happens in during client authentication, which
263 * we don't do */
264 errorLog0("SSLProcessCertificateRequest called\n");
265 if (message.length < 3) {
266 errorLog0("SSLProcessCertificateRequest: length decode error 1\n");
267 return ERR(SSLProtocolErr);
268 }
269 progress = message.data;
270 typeCount = *progress++;
271 if (typeCount < 1 || message.length < 3 + typeCount) {
272 errorLog0("SSLProcessCertificateRequest: length decode error 2\n");
273 return ERR(SSLProtocolErr);
274 }
275 for (i = 0; i < typeCount; i++)
276 { if (*progress++ == 1)
277 ctx->x509Requested = 1;
278 }
279
280 dnListLen = SSLDecodeInt(progress, 2);
281 progress += 2;
282 if (message.length != 3 + typeCount + dnListLen) {
283 errorLog0("SSLProcessCertificateRequest: length decode error 3\n");
284 return ERR(SSLProtocolErr);
285 }
286 while (dnListLen > 0)
287 { if (dnListLen < 2) {
288 errorLog0("SSLProcessCertificateRequest: dnListLen error 1\n");
289 return ERR(SSLProtocolErr);
290 }
291 dnLen = SSLDecodeInt(progress, 2);
292 progress += 2;
293 if (dnListLen < 2 + dnLen) {
294 errorLog0("SSLProcessCertificateRequest: dnListLen error 2\n");
295 return ERR(SSLProtocolErr);
296 }
297 if (ERR(err = SSLAllocBuffer(&dnBuf, sizeof(DNListElem), &ctx->sysCtx)) != 0)
298 return err;
299 dn = (DNListElem*)dnBuf.data;
300 if (ERR(err = SSLAllocBuffer(&dn->derDN, dnLen, &ctx->sysCtx)) != 0)
301 { SSLFreeBuffer(&dnBuf, &ctx->sysCtx);
302 return err;
303 }
304 memcpy(dn->derDN.data, progress, dnLen);
305 progress += dnLen;
306 dn->next = ctx->acceptableDNList;
307 ctx->acceptableDNList = dn;
308 dnListLen -= 2 + dnLen;
309 }
310
311 CASSERT(progress == message.data + message.length);
312
313 return SSLNoErr;
314 }
315
316 SSLErr
317 SSLEncodeCertificateVerify(SSLRecord *certVerify, SSLContext *ctx)
318 { SSLErr err;
319 UInt8 signedHashData[36];
320 SSLBuffer hashData, shaMsgState, md5MsgState;
321 UInt32 len;
322 UInt32 outputLen;
323
324 certVerify->contents.data = 0;
325 hashData.data = signedHashData;
326 hashData.length = 36;
327
328 if (ERR(err = CloneHashState(&SSLHashSHA1, ctx->shaState, &shaMsgState, ctx)) != 0)
329 goto fail;
330 if (ERR(err = CloneHashState(&SSLHashMD5, ctx->md5State, &md5MsgState, ctx)) != 0)
331 goto fail;
332 assert(ctx->sslTslCalls != NULL);
333 if (ERR(err = ctx->sslTslCalls->computeCertVfyMac(ctx,
334 hashData, shaMsgState, md5MsgState)) != 0)
335 goto fail;
336
337 CASSERT(ctx->signingPrivKey != NULL);
338 len = sslKeyLengthInBytes(ctx->signingPrivKey);
339
340 certVerify->contentType = SSL_handshake;
341 assert((ctx->negProtocolVersion == SSL_Version_3_0) ||
342 (ctx->negProtocolVersion == TLS_Version_1_0));
343 certVerify->protocolVersion = ctx->negProtocolVersion;
344 if (ERR(err = SSLAllocBuffer(&certVerify->contents, len + 6, &ctx->sysCtx)) != 0)
345 goto fail;
346
347 certVerify->contents.data[0] = SSL_certificate_verify;
348 SSLEncodeInt(certVerify->contents.data+1, len+2, 3);
349 SSLEncodeInt(certVerify->contents.data+4, len, 2);
350
351 err = sslRsaRawSign(ctx,
352 ctx->signingPrivKey,
353 ctx->signingKeyCsp,
354 signedHashData,
355 36, // MD5 size + SHA1 size
356 certVerify->contents.data+6,
357 len, // we mallocd len+6
358 &outputLen);
359 if(err) {
360 goto fail;
361 }
362
363 CASSERT(outputLen == len);
364
365 err = SSLNoErr;
366
367 fail:
368 ERR(SSLFreeBuffer(&shaMsgState, &ctx->sysCtx));
369 ERR(SSLFreeBuffer(&md5MsgState, &ctx->sysCtx));
370
371 return err;
372 }
373
374 SSLErr
375 SSLProcessCertificateVerify(SSLBuffer message, SSLContext *ctx)
376 { SSLErr err;
377 UInt8 signedHashData[36];
378 UInt16 signatureLen;
379 SSLBuffer hashData, shaMsgState, md5MsgState, outputData;
380 unsigned int publicModulusLen;
381
382 shaMsgState.data = 0;
383 md5MsgState.data = 0;
384 outputData.data = 0;
385
386 if (message.length < 2) {
387 errorLog0("SSLProcessCertificateVerify: msg len error\n");
388 return ERR(SSLProtocolErr);
389 }
390
391 signatureLen = (UInt16)SSLDecodeInt(message.data, 2);
392 if (message.length != 2 + signatureLen) {
393 errorLog0("SSLProcessCertificateVerify: sig len error 1\n");
394 return ERR(SSLProtocolErr);
395 }
396
397 CASSERT(ctx->peerPubKey != NULL);
398 publicModulusLen = sslKeyLengthInBytes(ctx->peerPubKey);
399
400 if (signatureLen != publicModulusLen) {
401 errorLog0("SSLProcessCertificateVerify: sig len error 2\n");
402 return ERR(SSLProtocolErr);
403 }
404 outputData.data = 0;
405 hashData.data = signedHashData;
406 hashData.length = 36;
407
408 if (ERR(err = CloneHashState(&SSLHashSHA1, ctx->shaState, &shaMsgState, ctx)) != 0)
409 goto fail;
410 if (ERR(err = CloneHashState(&SSLHashMD5, ctx->md5State, &md5MsgState, ctx)) != 0)
411 goto fail;
412 assert(ctx->sslTslCalls != NULL);
413 if (ERR(err = ctx->sslTslCalls->computeCertVfyMac(ctx, hashData,
414 shaMsgState, md5MsgState)) != 0)
415 goto fail;
416
417 if (ERR(err = SSLAllocBuffer(&outputData, publicModulusLen, &ctx->sysCtx)) != 0)
418 goto fail;
419
420 /*
421 * The CSP does the decrypt & compare for us in one shot
422 */
423 err = sslRsaRawVerify(ctx,
424 ctx->peerPubKey,
425 ctx->peerPubKeyCsp, // FIXME - maybe we just use cspHand?
426 message.data + 2,
427 signatureLen,
428 outputData.data,
429 36);
430 if(err) {
431 goto fail;
432 }
433 err = SSLNoErr;
434
435 fail:
436 ERR(SSLFreeBuffer(&shaMsgState, &ctx->sysCtx));
437 ERR(SSLFreeBuffer(&md5MsgState, &ctx->sysCtx));
438 ERR(SSLFreeBuffer(&outputData, &ctx->sysCtx));
439
440 return err;
441 }