]> git.saurik.com Git - apple/security.git/blob - SecureTransport/hdskcert.c
Security-29.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
91 SSLErr
92 SSLEncodeCertificate(SSLRecord *certificate, SSLContext *ctx)
93 { SSLErr err;
94 UInt32 totalLength;
95 int i, j, certCount;
96 UInt8 *progress;
97 SSLCertificate *cert;
98
99 /* Match DER-encoded root certs here */
100
101 cert = ctx->localCert;
102 CASSERT(cert != 0);
103 totalLength = 0;
104 certCount = 0;
105 while (cert)
106 { totalLength += 3 + cert->derCert.length; /* 3 for encoded length field */
107 ++certCount;
108 cert = cert->next;
109 }
110
111 certificate->contentType = SSL_handshake;
112 certificate->protocolVersion = SSL_Version_3_0;
113 if ((err = SSLAllocBuffer(&certificate->contents, totalLength + 7, &ctx->sysCtx)) != 0)
114 return err;
115
116 progress = certificate->contents.data;
117 *progress++ = SSL_certificate;
118 progress = SSLEncodeInt(progress, totalLength+3, 3); /* Handshake message length */
119 progress = SSLEncodeInt(progress, totalLength, 3); /* Vector length */
120
121 /* Root cert is first in the linked list, but has to go last, so walk list backwards */
122 for (i = 0; i < certCount; ++i)
123 { cert = ctx->localCert;
124 for (j = i+1; j < certCount; ++j)
125 cert = cert->next;
126 progress = SSLEncodeInt(progress, cert->derCert.length, 3);
127 memcpy(progress, cert->derCert.data, cert->derCert.length);
128 progress += cert->derCert.length;
129 }
130
131 CASSERT(progress == certificate->contents.data + certificate->contents.length);
132
133 if (ctx->protocolSide == SSL_ClientSide)
134 ctx->certSent = 1;
135
136 return SSLNoErr;
137 }
138
139 SSLErr
140 SSLProcessCertificate(SSLBuffer message, SSLContext *ctx)
141 { SSLErr err;
142 UInt32 listLen, certLen;
143 #ifndef __APPLE__
144 SSLBuffer buf;
145 #endif
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 #ifdef __APPLE__
165 cert = (SSLCertificate *)sslMalloc(sizeof(SSLCertificate));
166 if(cert == NULL) {
167 return SSLMemoryErr;
168 }
169 if ((err = SSLAllocBuffer(&cert->derCert, certLen, &ctx->sysCtx)) != 0)
170 { sslFree(cert);
171 return err;
172 }
173 #else
174 if ((err = SSLAllocBuffer(&buf, sizeof(SSLCertificate), &ctx->sysCtx)) != 0)
175 return err;
176 cert = (SSLCertificate*)buf.data;
177 if ((err = SSLAllocBuffer(&cert->derCert, certLen, &ctx->sysCtx)) != 0)
178 { SSLFreeBuffer(&buf, &ctx->sysCtx);
179 return err;
180 }
181 #endif
182 memcpy(cert->derCert.data, p, certLen);
183 p += certLen;
184 cert->next = ctx->peerCert; /* Insert backwards; root cert will be first in linked list */
185 ctx->peerCert = cert;
186 #ifndef _APPLE_CDSA_
187 /* we don't parse this, the CL does */
188 if ((err = ASNParseX509Certificate(cert->derCert, &cert->cert, ctx)) != 0)
189 return err;
190 #endif
191 listLen -= 3+certLen;
192 }
193 CASSERT(p == message.data + message.length && listLen == 0);
194
195 if (ctx->peerCert == 0)
196 return X509CertChainInvalidErr;
197
198 #ifdef _APPLE_CDSA_
199 if((err = sslVerifyCertChain(ctx, ctx->peerCert)) != 0)
200 #else
201 if ((err = X509VerifyCertChain(ctx->peerCert, ctx)) != 0)
202 #endif
203 return err;
204
205 /* Server's certificate is the last one in the chain */
206 cert = ctx->peerCert;
207 while (cert->next != 0)
208 cert = cert->next;
209 /* Convert its public key to RSAREF format */
210 #ifdef _APPLE_CDSA_
211 if ((err = sslPubKeyFromCert(ctx,
212 &cert->derCert,
213 &ctx->peerPubKey,
214 &ctx->peerPubKeyCsp)) != 0)
215 #else
216 if ((err = X509ExtractPublicKey(&cert->cert.pubKey, &ctx->peerKey)) != 0)
217 #endif
218 return err;
219
220 #ifndef _APPLE_CDSA_
221 /*
222 * This appears to be redundant with the cert check above;
223 * it's here for additional cert checking by clients of SSLRef.
224 */
225 if (ctx->certCtx.checkCertFunc != 0)
226 { SSLBuffer certList, *certs;
227 int i,certCount;
228 SSLCertificate *c;
229
230 if ((err = SSLGetPeerCertificateChainLength(ctx, &certCount)) != 0)
231 return err;
232 if ((err = SSLAllocBuffer(&certList, certCount * sizeof(SSLBuffer), &ctx->sysCtx)) != 0)
233 return err;
234 certs = (SSLBuffer *)certList.data;
235 c = ctx->peerCert;
236 for (i = 0; i < certCount; i++, c = c->next)
237 certs[i] = c->derCert;
238
239 if ((err = ctx->certCtx.checkCertFunc(certCount, certs, ctx->certCtx.checkCertRef)) != 0)
240 { SSLFreeBuffer(&certList, &ctx->sysCtx);
241 return err;
242 }
243 SSLFreeBuffer(&certList, &ctx->sysCtx);
244 }
245 #endif /* _APPLE_CDSA_ */
246
247 return SSLNoErr;
248 }
249
250 SSLErr
251 SSLEncodeCertificateRequest(SSLRecord *request, SSLContext *ctx)
252 {
253 #if !ST_SERVER_MODE_ENABLE
254
255 /* cert request only happens in server mode */
256 errorLog0("SSLEncodeCertificateRequest called\n");
257 return SSLUnsupportedErr;
258
259 #else
260
261 SSLErr err;
262 UInt32 dnListLen, msgLen;
263 UInt8 *progress;
264 DNListElem *dn;
265
266 dnListLen = 0;
267 dn = ctx->acceptableDNList;
268 CASSERT(dn != NULL);
269 while (dn)
270 { dnListLen += 2 + dn->derDN.length;
271 dn = dn->next;
272 }
273 msgLen = 1 + 1 + 2 + dnListLen;
274
275 request->contentType = SSL_handshake;
276 request->protocolVersion = SSL_Version_3_0;
277 if ((err = SSLAllocBuffer(&request->contents, msgLen + 4, &ctx->sysCtx)) != 0)
278 return err;
279
280 progress = request->contents.data;
281 *progress++ = SSL_certificate_request;
282 progress = SSLEncodeInt(progress, msgLen, 3);
283
284 *progress++ = 1; /* one cert type */
285 *progress++ = 1; /* RSA-sign type */
286 progress = SSLEncodeInt(progress, dnListLen, 2);
287 dn = ctx->acceptableDNList;
288 while (dn)
289 { progress = SSLEncodeInt(progress, dn->derDN.length, 2);
290 memcpy(progress, dn->derDN.data, dn->derDN.length);
291 progress += dn->derDN.length;
292 dn = dn->next;
293 }
294
295 CASSERT(progress == request->contents.data + request->contents.length);
296
297 return SSLNoErr;
298 #endif /* ST_SERVER_MODE_ENABLE */
299 }
300
301 SSLErr
302 SSLProcessCertificateRequest(SSLBuffer message, SSLContext *ctx)
303 { SSLErr err;
304 int i, dnListLen, dnLen;
305 unsigned int typeCount;
306 UInt8 *progress;
307 SSLBuffer dnBuf;
308 DNListElem *dn;
309
310 /* cert request only happens in during client authentication, which
311 * we don't do */
312 errorLog0("SSLProcessCertificateRequest called\n");
313 if (message.length < 3) {
314 errorLog0("SSLProcessCertificateRequest: length decode error 1\n");
315 return ERR(SSLProtocolErr);
316 }
317 progress = message.data;
318 typeCount = *progress++;
319 if (typeCount < 1 || message.length < 3 + typeCount) {
320 errorLog0("SSLProcessCertificateRequest: length decode error 2\n");
321 return ERR(SSLProtocolErr);
322 }
323 for (i = 0; i < typeCount; i++)
324 { if (*progress++ == 1)
325 ctx->x509Requested = 1;
326 }
327
328 dnListLen = SSLDecodeInt(progress, 2);
329 progress += 2;
330 if (message.length != 3 + typeCount + dnListLen) {
331 errorLog0("SSLProcessCertificateRequest: length decode error 3\n");
332 return ERR(SSLProtocolErr);
333 }
334 while (dnListLen > 0)
335 { if (dnListLen < 2) {
336 errorLog0("SSLProcessCertificateRequest: dnListLen error 1\n");
337 return ERR(SSLProtocolErr);
338 }
339 dnLen = SSLDecodeInt(progress, 2);
340 progress += 2;
341 if (dnListLen < 2 + dnLen) {
342 errorLog0("SSLProcessCertificateRequest: dnListLen error 2\n");
343 return ERR(SSLProtocolErr);
344 }
345 if (ERR(err = SSLAllocBuffer(&dnBuf, sizeof(DNListElem), &ctx->sysCtx)) != 0)
346 return err;
347 dn = (DNListElem*)dnBuf.data;
348 if (ERR(err = SSLAllocBuffer(&dn->derDN, dnLen, &ctx->sysCtx)) != 0)
349 { SSLFreeBuffer(&dnBuf, &ctx->sysCtx);
350 return err;
351 }
352 memcpy(dn->derDN.data, progress, dnLen);
353 progress += dnLen;
354 dn->next = ctx->acceptableDNList;
355 ctx->acceptableDNList = dn;
356 dnListLen -= 2 + dnLen;
357 }
358
359 CASSERT(progress == message.data + message.length);
360
361 return SSLNoErr;
362 }
363
364 SSLErr
365 SSLEncodeCertificateVerify(SSLRecord *certVerify, SSLContext *ctx)
366 { SSLErr err;
367 UInt8 signedHashData[36];
368 SSLBuffer hashData, shaMsgState, md5MsgState;
369 UInt32 len;
370 UInt32 outputLen;
371
372 certVerify->contents.data = 0;
373 hashData.data = signedHashData;
374 hashData.length = 36;
375
376 if (ERR(err = CloneHashState(&SSLHashSHA1, ctx->shaState, &shaMsgState, ctx)) != 0)
377 goto fail;
378 if (ERR(err = CloneHashState(&SSLHashMD5, ctx->md5State, &md5MsgState, ctx)) != 0)
379 goto fail;
380 if (ERR(err = SSLCalculateFinishedMessage(hashData, shaMsgState, md5MsgState, 0, ctx)) != 0)
381 goto fail;
382
383 #if RSAREF
384 len = (ctx->localKey.bits + 7)/8;
385 #elif BSAFE
386 { A_RSA_KEY *keyInfo;
387 int rsaResult;
388
389 if ((rsaResult = B_GetKeyInfo((POINTER*)&keyInfo, ctx->localKey, KI_RSAPublic)) != 0)
390 return ERR(SSLUnknownErr);
391 len = keyInfo->modulus.len;
392 }
393 #elif _APPLE_CDSA_
394 CASSERT(ctx->signingPrivKey != NULL);
395 len = sslKeyLengthInBytes(ctx->signingPrivKey);
396 #else
397 #error No asymmetric crypto specified
398 #endif /* RSAREF / BSAFE */
399
400 certVerify->contentType = SSL_handshake;
401 certVerify->protocolVersion = SSL_Version_3_0;
402 if (ERR(err = SSLAllocBuffer(&certVerify->contents, len + 6, &ctx->sysCtx)) != 0)
403 goto fail;
404
405 certVerify->contents.data[0] = SSL_certificate_verify;
406 SSLEncodeInt(certVerify->contents.data+1, len+2, 3);
407 SSLEncodeInt(certVerify->contents.data+4, len, 2);
408 #if RSAREF
409 if (RSAPrivateEncrypt(certVerify->contents.data+6, &outputLen,
410 signedHashData, 36, &ctx->localKey) != 0) /* Sign the structure */
411 { err = ERR(SSLUnknownErr);
412 goto fail;
413 }
414 #elif BSAFE
415 { B_ALGORITHM_OBJ rsa;
416 B_ALGORITHM_METHOD *chooser[] = { &AM_RSA_CRT_ENCRYPT, 0 };
417 int rsaResult;
418
419 if (ERR(rsaResult = B_CreateAlgorithmObject(&rsa)) != 0)
420 return SSLUnknownErr;
421 if (ERR(rsaResult = B_SetAlgorithmInfo(rsa, AI_PKCS_RSAPrivate, 0)) != 0)
422 return SSLUnknownErr;
423 if (ERR(rsaResult = B_EncryptInit(rsa, ctx->localKey, chooser, NO_SURR)) != 0)
424 return SSLUnknownErr;
425 if (ERR(rsaResult = B_EncryptUpdate(rsa, certVerify->contents.data+6,
426 &outputLen, len, signedHashData, 36, 0, NO_SURR)) != 0)
427 return SSLUnknownErr;
428 if (ERR(rsaResult = B_EncryptFinal(rsa, certVerify->contents.data+6+outputLen,
429 &outputLen, len-outputLen, 0, NO_SURR)) != 0)
430 return SSLUnknownErr;
431 B_DestroyAlgorithmObject(&rsa);
432 }
433 #elif _APPLE_CDSA_
434
435 err = sslRsaRawSign(ctx,
436 ctx->signingPrivKey,
437 ctx->signingKeyCsp,
438 signedHashData,
439 36, // MD5 size + SHA1 size
440 certVerify->contents.data+6,
441 len, // we mallocd len+6
442 &outputLen);
443 if(err) {
444 goto fail;
445 }
446 #else
447 #error No asymmetric crypto specified
448 #endif /* RSAREF / BSAFE */
449
450 CASSERT(outputLen == len);
451
452 err = SSLNoErr;
453
454 fail:
455 ERR(SSLFreeBuffer(&shaMsgState, &ctx->sysCtx));
456 ERR(SSLFreeBuffer(&md5MsgState, &ctx->sysCtx));
457
458 return err;
459 }
460
461 SSLErr
462 SSLProcessCertificateVerify(SSLBuffer message, SSLContext *ctx)
463 { SSLErr err;
464 UInt8 signedHashData[36];
465 UInt16 signatureLen;
466 SSLBuffer hashData, shaMsgState, md5MsgState, outputData;
467 #if defined(BSAFE) || defined(RSAREF)
468 unsigned int outputLen;
469 #endif
470 unsigned int publicModulusLen;
471
472 shaMsgState.data = 0;
473 md5MsgState.data = 0;
474 outputData.data = 0;
475
476 if (message.length < 2) {
477 errorLog0("SSLProcessCertificateVerify: msg len error\n");
478 return ERR(SSLProtocolErr);
479 }
480
481 signatureLen = (UInt16)SSLDecodeInt(message.data, 2);
482 if (message.length != 2 + signatureLen) {
483 errorLog0("SSLProcessCertificateVerify: sig len error 1\n");
484 return ERR(SSLProtocolErr);
485 }
486
487 #if RSAREF
488 publicModulusLen = (ctx->peerKey.bits + 7)/8;
489 #elif BSAFE
490 { A_RSA_KEY *keyInfo;
491 int rsaResult;
492
493 if ((rsaResult = B_GetKeyInfo((POINTER*)&keyInfo, ctx->peerKey, KI_RSAPublic)) != 0)
494 return SSLUnknownErr;
495 publicModulusLen = keyInfo->modulus.len;
496 }
497 #elif _APPLE_CDSA_
498 CASSERT(ctx->peerPubKey != NULL);
499 publicModulusLen = sslKeyLengthInBytes(ctx->peerPubKey);
500 #else
501 #error No asymmetric crypto specified
502 #endif /* RSAREF / BSAFE */
503
504 if (signatureLen != publicModulusLen) {
505 errorLog0("SSLProcessCertificateVerify: sig len error 2\n");
506 return ERR(SSLProtocolErr);
507 }
508 outputData.data = 0;
509 hashData.data = signedHashData;
510 hashData.length = 36;
511
512 if (ERR(err = CloneHashState(&SSLHashSHA1, ctx->shaState, &shaMsgState, ctx)) != 0)
513 goto fail;
514 if (ERR(err = CloneHashState(&SSLHashMD5, ctx->md5State, &md5MsgState, ctx)) != 0)
515 goto fail;
516 if (ERR(err = SSLCalculateFinishedMessage(hashData, shaMsgState, md5MsgState, 0, ctx)) != 0)
517 goto fail;
518
519 if (ERR(err = SSLAllocBuffer(&outputData, publicModulusLen, &ctx->sysCtx)) != 0)
520 goto fail;
521
522 #if RSAREF
523 if (RSAPublicDecrypt(outputData.data, &outputLen,
524 message.data + 2, signatureLen, &ctx->peerKey) != 0)
525 { ERR(err = SSLUnknownErr);
526 goto fail;
527 }
528 #elif BSAFE
529 { B_ALGORITHM_OBJ rsa;
530 B_ALGORITHM_METHOD *chooser[] = { &AM_MD2, &AM_MD5, &AM_RSA_DECRYPT, 0 };
531 int rsaResult;
532 unsigned int decryptLen;
533
534 if ((rsaResult = B_CreateAlgorithmObject(&rsa)) != 0)
535 return SSLUnknownErr;
536 if ((rsaResult = B_SetAlgorithmInfo(rsa, AI_PKCS_RSAPublic, 0)) != 0)
537 return SSLUnknownErr;
538 if ((rsaResult = B_DecryptInit(rsa, ctx->peerKey, chooser, NO_SURR)) != 0)
539 return SSLUnknownErr;
540 if ((rsaResult = B_DecryptUpdate(rsa, outputData.data, &decryptLen, 36,
541 message.data + 2, signatureLen, 0, NO_SURR)) != 0)
542 return SSLUnknownErr;
543 outputLen = decryptLen;
544 if ((rsaResult = B_DecryptFinal(rsa, outputData.data+outputLen,
545 &decryptLen, 36-outputLen, 0, NO_SURR)) != 0)
546 return SSLUnknownErr;
547 outputLen += decryptLen;
548 B_DestroyAlgorithmObject(&rsa);
549 }
550 #elif _APPLE_CDSA_
551 /*
552 * The CSP does the decrypt & compare for us in one shot
553 */
554 err = sslRsaRawVerify(ctx,
555 ctx->peerPubKey,
556 ctx->peerPubKeyCsp, // FIXME - maybe we just use cspHand?
557 message.data + 2,
558 signatureLen,
559 outputData.data,
560 36);
561 if(err) {
562 goto fail;
563 }
564
565 #endif /* RSAREF / BSAFE */
566
567 #if !_APPLE_CDSA_
568 /* we don't have to do the compare */
569 if (outputLen != 36)
570 {
571 ERR(err = SSLProtocolErr);
572 goto fail;
573 }
574 outputData.length = outputLen;
575
576 DUMP_BUFFER_NAME("Finished got ", outputData);
577 DUMP_BUFFER_NAME("Finished wanted", hashData);
578
579 if (memcmp(outputData.data, signedHashData, 36) != 0)
580 {
581 ERR(err = SSLProtocolErr);
582 goto fail;
583 }
584 #endif /* BSAFE, RSAREF only */
585
586 err = SSLNoErr;
587
588 fail:
589 ERR(SSLFreeBuffer(&shaMsgState, &ctx->sysCtx));
590 ERR(SSLFreeBuffer(&md5MsgState, &ctx->sysCtx));
591 ERR(SSLFreeBuffer(&outputData, &ctx->sysCtx));
592
593 return err;
594 }