]> git.saurik.com Git - apple/security.git/blob - SecureTransport/appleCdsa.c
3e502e0c91a7e80348db15ba19379ecddb216794
[apple/security.git] / SecureTransport / appleCdsa.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: appleCdsa.c
21
22 Contains: interface between SSL and CDSA
23
24 Written by: Doug Mitchell
25
26 Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved.
27
28 */
29
30 #include "ssl.h"
31 #include "sslctx.h"
32 #include "sslalloc.h"
33 #include "appleCdsa.h"
34 #include "sslerrs.h"
35 #include "sslutil.h"
36 #include "sslDebug.h"
37 #include "sslBER.h"
38 #include "ModuleAttacher.h"
39
40 #ifndef _SSL_KEYCHAIN_H_
41 #include "sslKeychain.h"
42 #endif
43
44 #include <string.h>
45 #include <stdlib.h>
46 #include <assert.h>
47
48 #include <Security/cssm.h>
49 #include <Security/cssmapple.h>
50
51 /* X.509 includes, from cssmapi */
52 #include <Security/x509defs.h> /* x.509 function and type defs */
53 #include <Security/oidsalg.h>
54 #include <Security/oidscert.h>
55
56 #pragma mark *** Utilities ***
57
58 /*
59 * Set up a Raw symmetric key with specified algorithm and key bits.
60 */
61 SSLErr sslSetUpSymmKey(
62 CSSM_KEY_PTR symKey,
63 CSSM_ALGORITHMS alg,
64 CSSM_KEYUSE keyUse, // CSSM_KEYUSE_ENCRYPT, etc.
65 CSSM_BOOL copyKey, // true: copy keyData false: set by reference
66 uint8 *keyData,
67 uint32 keyDataLen) // in bytes
68 {
69 SSLErr serr;
70 CSSM_KEYHEADER *hdr;
71
72 memset(symKey, 0, sizeof(CSSM_KEY));
73 if(copyKey) {
74 serr = stSetUpCssmData(&symKey->KeyData, keyDataLen);
75 if(serr) {
76 return serr;
77 }
78 memmove(symKey->KeyData.Data, keyData, keyDataLen);
79 }
80 else {
81 symKey->KeyData.Data = keyData;
82 symKey->KeyData.Length = keyDataLen;
83 }
84
85 /* set up the header */
86 hdr = &symKey->KeyHeader;
87 hdr->BlobType = CSSM_KEYBLOB_RAW;
88 hdr->Format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING;
89 hdr->AlgorithmId = alg;
90 hdr->KeyClass = CSSM_KEYCLASS_SESSION_KEY;
91 hdr->LogicalKeySizeInBits = keyDataLen * 8;
92 hdr->KeyAttr = CSSM_KEYATTR_MODIFIABLE | CSSM_KEYATTR_EXTRACTABLE;
93 hdr->KeyUsage = keyUse;
94 hdr->WrapAlgorithmId = CSSM_ALGID_NONE;
95 return SSLNoErr;
96 }
97
98 /*
99 * Free a CSSM_KEY - its CSP resources, KCItemRef, and the key itself.
100 */
101 SSLErr sslFreeKey(
102 CSSM_CSP_HANDLE cspHand,
103 CSSM_KEY_PTR *key, /* so we can null it out */
104 #if ST_KEYCHAIN_ENABLE && ST_KC_KEYS_NEED_REF
105 SecKeychainRef *kcItem)
106 #else
107 void *kcItem)
108 #endif
109 {
110 CASSERT(key != NULL);
111
112 if(*key != NULL) {
113 if(cspHand != 0) {
114 CSSM_FreeKey(cspHand, NULL, *key, CSSM_FALSE);
115 }
116 sslFree(*key);
117 *key = NULL;
118 }
119 #if ST_KEYCHAIN_ENABLE && ST_KC_KEYS_NEED_REF
120 if((kcItem != NULL) && (*kcItem != NULL)) {
121 KCReleaseItem(kcItem); /* does this NULL the referent? */
122 *kcItem = NULL;
123 }
124 #endif
125 return SSLNoErr;
126 }
127
128 /*
129 * Standard app-level memory functions required by CDSA.
130 */
131 void * stAppMalloc (uint32 size, void *allocRef) {
132 return( malloc(size) );
133 }
134 void stAppFree (void *mem_ptr, void *allocRef) {
135 free(mem_ptr);
136 return;
137 }
138 void * stAppRealloc (void *ptr, uint32 size, void *allocRef) {
139 return( realloc( ptr, size ) );
140 }
141 void * stAppCalloc (uint32 num, uint32 size, void *allocRef) {
142 return( calloc( num, size ) );
143 }
144
145 /*
146 * Ensure there's a connection to ctx->cspHand. If there
147 * already is one, fine.
148 * Note that as of 12/18/00, we assume we're connected to
149 * all modules all the time (since we do an attachToAll() in
150 * SSLNewContext()).
151 */
152 SSLErr attachToCsp(SSLContext *ctx)
153 {
154 CASSERT(ctx != NULL);
155 if(ctx->cspHand != 0) {
156 return SSLNoErr;
157 }
158 else {
159 return SSLAttachFailure;
160 }
161 }
162
163 /*
164 * Connect to TP, CL; reusable.
165 */
166 SSLErr attachToCl(SSLContext *ctx)
167 {
168 CASSERT(ctx != NULL);
169 if(ctx->clHand != 0) {
170 return SSLNoErr;
171 }
172 else {
173 return SSLAttachFailure;
174 }
175 }
176
177 SSLErr attachToTp(SSLContext *ctx)
178 {
179 CASSERT(ctx != NULL);
180 if(ctx->tpHand != 0) {
181 return SSLNoErr;
182 }
183 else {
184 return SSLAttachFailure;
185 }
186 }
187
188 /*
189 * Convenience function - attach to CSP, CL, TP. Reusable.
190 */
191 SSLErr attachToAll(SSLContext *ctx)
192 {
193 CSSM_RETURN crtn;
194
195 CASSERT(ctx != NULL);
196 crtn = attachToModules(&ctx->cspHand, &ctx->clHand,
197 &ctx->tpHand
198 #if ST_FAKE_KEYCHAIN || ST_FAKE_GET_CSPDL_HANDLE
199 ,
200 &ctx->cspDlHand
201 #endif
202 );
203 if(crtn) {
204 return SSLAttachFailure;
205 }
206 else {
207 return SSLNoErr;
208 }
209 }
210
211 SSLErr detachFromAll(SSLContext *ctx)
212 {
213 #if 0
214 /* No more, attachments are kept on a global basis */
215 CASSERT(ctx != NULL);
216 if(ctx->cspHand != 0) {
217 CSSM_ModuleDetach(ctx->cspHand);
218 ctx->cspHand = 0;
219 }
220 if(ctx->tpHand != 0) {
221 CSSM_ModuleDetach(ctx->tpHand);
222 ctx->tpHand = 0;
223 }
224 if(ctx->clHand != 0) {
225 CSSM_ModuleDetach(ctx->clHand);
226 ctx->clHand = 0;
227 }
228 #endif /* 0 */
229 return SSLNoErr;
230 }
231
232 #pragma mark -
233 #pragma mark *** CSSM_DATA routines ***
234
235 CSSM_DATA_PTR stMallocCssmData(
236 uint32 size)
237 {
238 CSSM_DATA_PTR rtn = (CSSM_DATA_PTR)stAppMalloc(sizeof(CSSM_DATA), NULL);
239
240 if(rtn == NULL) {
241 return NULL;
242 }
243 rtn->Length = size;
244 if(size == 0) {
245 rtn->Data = NULL;
246 }
247 else {
248 rtn->Data = (uint8 *)stAppMalloc(size, NULL);
249 }
250 return rtn;
251 }
252
253 void stFreeCssmData(
254 CSSM_DATA_PTR data,
255 CSSM_BOOL freeStruct)
256 {
257 if(data == NULL) {
258 return;
259 }
260 if(data->Data != NULL) {
261 stAppFree(data->Data, NULL);
262 data->Data = NULL;
263 }
264 data->Length = 0;
265 if(freeStruct) {
266 stAppFree(data, NULL);
267 }
268 }
269
270 /*
271 * Ensure that indicated CSSM_DATA_PTR can handle 'length' bytes of data.
272 * Malloc the Data ptr if necessary.
273 */
274 SSLErr stSetUpCssmData(
275 CSSM_DATA_PTR data,
276 uint32 length)
277 {
278 CASSERT(data != NULL);
279 if(data->Length == 0) {
280 data->Data = (uint8 *)stAppMalloc(length, NULL);
281 if(data->Data == NULL) {
282 return SSLMemoryErr;
283 }
284 }
285 else if(data->Length < length) {
286 errorLog0("stSetUpCssmData: length too small\n");
287 return SSLMemoryErr;
288 }
289 data->Length = length;
290 return SSLNoErr;
291 }
292
293 #pragma mark -
294 #pragma mark *** Public CSP Functions ***
295
296 /*
297 * Common RNG function; replaces SSLRef's SSLRandomFunc.
298 * FIXME - just use /dev/random.
299 */
300 SSLErr sslRand(SSLContext *ctx, SSLBuffer *buf)
301 {
302 CSSM_RETURN crtn;
303 CSSM_CC_HANDLE rngHand;
304 CSSM_DATA randData;
305 SSLErr serr;
306
307 CASSERT(ctx != NULL);
308 CASSERT(buf != NULL);
309 CASSERT(buf->data != NULL);
310
311 serr = attachToCsp(ctx);
312 if(serr) {
313 return serr;
314 }
315 if(buf->length == 0) {
316 dprintf0("sslRand: zero buf->length\n");
317 return SSLNoErr;
318 }
319
320 /*
321 * We happen to know that the CSP has a really good RNG
322 * seed if we don't specify anything; let's use it
323 */
324 crtn = CSSM_CSP_CreateRandomGenContext(ctx->cspHand,
325 CSSM_ALGID_APPLE_YARROW,
326 NULL, /* seed */
327 buf->length,
328 &rngHand);
329 if(crtn) {
330 stPrintCdsaError("CSSM_CSP_CreateRandomGenContext", crtn);
331 return SSLCryptoError;
332 }
333 SSLBUF_TO_CSSM(buf, &randData);
334 crtn = CSSM_GenerateRandom(rngHand, &randData);
335 if(crtn) {
336 stPrintCdsaError("CSSM_GenerateRandom", crtn);
337 serr = SSLCryptoError;
338 }
339 CSSM_DeleteContext(rngHand);
340 return serr;
341 }
342
343 /*
344 * Raw RSA sign/verify.
345 *
346 * Initial X port: CSP doesns't support this, so we'll do sign/verify via
347 * raw RSA encrypt/decrypt here.
348 */
349 #define SIGN_VFY_VIA_ENCR_DECR 0
350
351 #if SIGN_VFY_VIA_ENCR_DECR
352
353 SSLErr sslRsaRawSign(
354 SSLContext *ctx,
355 const CSSM_KEY *privKey,
356 CSSM_CSP_HANDLE cspHand,
357 const UInt8 *plainText,
358 UInt32 plainTextLen,
359 UInt8 *sig, // mallocd by caller; RETURNED
360 UInt32 sigLen, // available
361 UInt32 *actualBytes) // RETURNED
362 {
363 /* Raw RSA sign with no digest is the same as raw RSA encrypt. */
364 /* Force CSSM_KEYUSE_ANY in case CL provided keyuse bits more specific
365 * than we really want */
366 SSLErr serr;
367 CSSM_KEYUSE savedKeyUse = privKey->KeyHeader.KeyUsage;
368 privKey->KeyHeader.KeyUsage = CSSM_KEYUSE_ANY;
369 serr = sslRsaEncrypt(ctx,
370 privKey,
371 cspHand,
372 plainText,
373 plainTextLen,
374 sig,
375 sigLen,
376 actualBytes);
377 privKey->KeyHeader.KeyUsage = savedKeyUse;
378 return serr;
379 }
380
381 SSLErr sslRsaRawVerify(
382 SSLContext *ctx,
383 const CSSM_KEY *pubKey,
384 CSSM_CSP_HANDLE cspHand,
385 const UInt8 *plainText,
386 UInt32 plainTextLen,
387 const UInt8 *sig,
388 UInt32 sigLen)
389 {
390 /*
391 * Raw RSA verify with no digest is just a comparison of the incoming
392 * plaintext with (signature, decrypted via raw RSA decrypt).
393 */
394
395 UInt32 actualBytes;
396 SSLErr serr;
397 UInt8 *digest;
398
399 /* Force CSSM_KEYUSE_ANY in case CL provided keyuse bits more specific
400 * than we really want */
401 CSSM_KEYUSE savedKeyUse = pubKey->KeyHeader.KeyUsage;
402 pubKey->KeyHeader.KeyUsage = CSSM_KEYUSE_ANY;
403
404 /* malloc space for decrypting the signature */
405 digest = sslMalloc(plainTextLen);
406 if(digest == NULL) {
407 return SSLMemoryErr;
408 }
409
410 /* decrypt signature */
411 serr = sslRsaDecrypt(ctx,
412 pubKey,
413 cspHand,
414 sig,
415 sigLen,
416 digest,
417 plainTextLen,
418 &actualBytes);
419 pubKey->KeyHeader.KeyUsage = savedKeyUse;
420 if(serr) {
421 goto errOut;
422 }
423 if((actualBytes != plainTextLen) ||
424 (memcmp(plainText, digest, plainTextLen))) {
425 errorLog0("sslRsaRawVerify: sig miscompare\n");
426 serr = SSLCryptoError;
427 }
428 else {
429 serr = SSLNoErr;
430 }
431 errOut:
432 sslFree(digest);
433 return serr;
434 }
435
436 #else /* OS9 and future post-cheetah version */
437
438 SSLErr sslRsaRawSign(
439 SSLContext *ctx,
440 const CSSM_KEY *privKey,
441 CSSM_CSP_HANDLE cspHand,
442 const UInt8 *plainText,
443 UInt32 plainTextLen,
444 UInt8 *sig, // mallocd by caller; RETURNED
445 UInt32 sigLen, // available
446 UInt32 *actualBytes) // RETURNED
447 {
448 CSSM_CC_HANDLE sigHand = 0;
449 CSSM_RETURN crtn;
450 SSLErr serr;
451 CSSM_DATA sigData;
452 CSSM_DATA ptextData;
453
454 CASSERT(ctx != NULL);
455 if((privKey == NULL) ||
456 (cspHand == 0) ||
457 (plainText == NULL) ||
458 (sig == NULL) ||
459 (actualBytes == NULL)) {
460 errorLog0("sslRsaRawSign: bad arguments\n");
461 return SSLInternalError;
462 }
463 *actualBytes = 0;
464
465 crtn = CSSM_CSP_CreateSignatureContext(cspHand,
466 CSSM_ALGID_RSA,
467 NULL, // passPhrase
468 privKey,
469 &sigHand);
470 if(crtn) {
471 stPrintCdsaError("CSSM_CSP_CreateSignatureContext (1)", crtn);
472 return SSLCryptoError;
473 }
474
475 ptextData.Data = (uint8 *)plainText;
476 ptextData.Length = plainTextLen;
477
478 /* caller better get this right, or the SignData will fail */
479 sigData.Data = sig;
480 sigData.Length = sigLen;
481
482 crtn = CSSM_SignData(sigHand,
483 &ptextData,
484 1,
485 CSSM_ALGID_NONE, // digestAlg
486 &sigData);
487 if(crtn) {
488 stPrintCdsaError("CSSM_SignData", crtn);
489 serr = SSLCryptoError;
490 }
491 else {
492 *actualBytes = sigData.Length;
493 serr = SSLNoErr;
494 }
495 if(sigHand != 0) {
496 CSSM_DeleteContext(sigHand);
497 }
498 return serr;
499 }
500
501 SSLErr sslRsaRawVerify(
502 SSLContext *ctx,
503 const CSSM_KEY *pubKey,
504 CSSM_CSP_HANDLE cspHand,
505 const UInt8 *plainText,
506 UInt32 plainTextLen,
507 const UInt8 *sig,
508 UInt32 sigLen)
509 {
510 CSSM_CC_HANDLE sigHand = 0;
511 CSSM_RETURN crtn;
512 SSLErr serr;
513 CSSM_DATA sigData;
514 CSSM_DATA ptextData;
515
516 CASSERT(ctx != NULL);
517 if((pubKey == NULL) ||
518 (cspHand == 0) ||
519 (plainText == NULL) ||
520 (sig == NULL)) {
521 errorLog0("sslRsaRawVerify: bad arguments\n");
522 return SSLInternalError;
523 }
524
525 crtn = CSSM_CSP_CreateSignatureContext(cspHand,
526 CSSM_ALGID_RSA,
527 NULL, // passPhrase
528 pubKey,
529 &sigHand);
530 if(sigHand == 0) {
531 stPrintCdsaError("CSSM_CSP_CreateSignatureContext (2)", crtn);
532 return SSLCryptoError;
533 }
534
535 ptextData.Data = (uint8 *)plainText;
536 ptextData.Length = plainTextLen;
537 sigData.Data = (uint8 *)sig;
538 sigData.Length = sigLen;
539
540 crtn = CSSM_VerifyData(sigHand,
541 &ptextData,
542 1,
543 CSSM_ALGID_NONE, // digestAlg
544 &sigData);
545 if(crtn) {
546 stPrintCdsaError("CSSM_VerifyData", crtn);
547 serr = SSLCryptoError;
548 }
549 else {
550 serr = SSLNoErr;
551 }
552 if(sigHand != 0) {
553 CSSM_DeleteContext(sigHand);
554 }
555 return serr;
556 }
557 #endif /* SIGN_VFY_VIA_ENCR_DECR */
558
559 /*
560 * Encrypt/Decrypt
561 */
562 #if APPLE_DOMESTIC_CSP_REQUIRED
563
564 /*
565 * Mucho work needed to get this functionality out of export CSP....
566 */
567
568 SSLErr sslRsaEncrypt(
569 SSLContext *ctx,
570 const CSSM_KEY *pubKey,
571 CSSM_CSP_HANDLE cspHand,
572 const UInt8 *plainText,
573 UInt32 plainTextLen,
574 UInt8 *cipherText, // mallocd by caller; RETURNED
575 UInt32 cipherTextLen, // available
576 UInt32 *actualBytes) // RETURNED
577 {
578 CSSM_DATA ctextData = {0, NULL};
579 CSSM_DATA ptextData;
580 CSSM_DATA remData = {0, NULL};
581 CSSM_CC_HANDLE cryptHand = 0;
582 SSLErr serr = SSLInternalError;
583 CSSM_RETURN crtn;
584 uint32 bytesMoved = 0;
585 CSSM_ACCESS_CREDENTIALS creds;
586
587 CASSERT(ctx != NULL);
588 CASSERT(actualBytes != NULL);
589 *actualBytes = 0;
590
591 if((pubKey == NULL) || (cspHand == 0)) {
592 errorLog0("sslRsaEncrypt: bad pubKey/cspHand\n");
593 return SSLInternalError;
594 }
595
596 #if RSA_PUB_KEY_USAGE_HACK
597 ((CSSM_KEY_PTR)pubKey)->KeyHeader.KeyUsage |= CSSM_KEYUSE_ENCRYPT;
598 #endif
599 memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
600
601 crtn = CSSM_CSP_CreateAsymmetricContext(cspHand,
602 CSSM_ALGID_RSA,
603 &creds,
604 pubKey,
605 CSSM_PADDING_PKCS1,
606 &cryptHand);
607 if(crtn) {
608 stPrintCdsaError("CSSM_CSP_CreateAsymmetricContext", crtn);
609 return SSLCryptoError;
610 }
611 ptextData.Data = (uint8 *)plainText;
612 ptextData.Length = plainTextLen;
613
614 if(pubKey->KeyHeader.KeyClass == CSSM_KEYCLASS_PRIVATE_KEY) {
615 /*
616 * Special case, encrypting with private key (i.e., raw sign). Add
617 * the required context attr.
618 */
619 CSSM_CONTEXT_ATTRIBUTE modeAttr;
620
621 modeAttr.AttributeType = CSSM_ATTRIBUTE_MODE;
622 modeAttr.AttributeLength = sizeof(uint32);
623 modeAttr.Attribute.Uint32 = CSSM_ALGMODE_PRIVATE_KEY;
624 crtn = CSSM_UpdateContextAttributes(cryptHand, 1, &modeAttr);
625 if(crtn) {
626 stPrintCdsaError("CSSM_UpdateContextAttributes", crtn);
627 CSSM_DeleteContext(cryptHand);
628 return SSLCryptoError;
629 }
630 }
631
632 /*
633 * Have CSP malloc ciphertext
634 */
635 crtn = CSSM_EncryptData(cryptHand,
636 &ptextData,
637 1,
638 &ctextData,
639 1,
640 &bytesMoved,
641 &remData);
642 if(crtn == CSSM_OK) {
643 /*
644 * ciphertext in both ctextData and remData; ensure it'll fit
645 * in caller's buf & copy
646 */
647 if(bytesMoved > cipherTextLen) {
648 errorLog2("sslRsaEncrypt overflow; cipherTextLen %ld bytesMoved %ld\n",
649 cipherTextLen, bytesMoved);
650 serr = SSLDataOverflow;
651 }
652 else {
653 UInt32 toMoveCtext;
654 UInt32 toMoveRem;
655
656 *actualBytes = bytesMoved;
657 /*
658 * Snag valid data from ctextData - its length or bytesMoved,
659 * whichever is less
660 */
661 if(ctextData.Length > bytesMoved) {
662 /* everything's in ctext */
663 toMoveCtext = bytesMoved;
664 toMoveRem = 0;
665 }
666 else {
667 /* must be some in remData too */
668 toMoveCtext = ctextData.Length;
669 toMoveRem = bytesMoved - toMoveCtext; // remainder
670 }
671 if(toMoveCtext) {
672 memmove(cipherText, ctextData.Data, toMoveCtext);
673 }
674 if(toMoveRem) {
675 memmove(cipherText + toMoveCtext, remData.Data,
676 toMoveRem);
677 }
678 serr = SSLNoErr;
679 }
680 }
681 else {
682 stPrintCdsaError("CSSM_EncryptData", crtn);
683 serr = SSLCryptoError;
684 }
685 if(cryptHand != 0) {
686 CSSM_DeleteContext(cryptHand);
687 }
688
689 /* free data mallocd by CSP */
690 stFreeCssmData(&ctextData, CSSM_FALSE);
691 stFreeCssmData(&remData, CSSM_FALSE);
692 return serr;
693 }
694
695 SSLErr sslRsaDecrypt(
696 SSLContext *ctx,
697 const CSSM_KEY *privKey,
698 CSSM_CSP_HANDLE cspHand,
699 const UInt8 *cipherText,
700 UInt32 cipherTextLen,
701 UInt8 *plainText, // mallocd by caller; RETURNED
702 UInt32 plainTextLen, // available
703 UInt32 *actualBytes) // RETURNED
704 {
705 CSSM_DATA ptextData = {0, NULL};
706 CSSM_DATA ctextData;
707 CSSM_DATA remData = {0, NULL};
708 CSSM_CC_HANDLE cryptHand = 0;
709 SSLErr serr = SSLInternalError;
710 CSSM_RETURN crtn;
711 uint32 bytesMoved = 0;
712 CSSM_ACCESS_CREDENTIALS creds;
713
714 CASSERT(ctx != NULL);
715 CASSERT(actualBytes != NULL);
716 *actualBytes = 0;
717
718 if((privKey == NULL) || (cspHand == 0)) {
719 errorLog0("sslRsaDecrypt: bad privKey/cspHand\n");
720 return SSLInternalError;
721 }
722 memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
723 crtn = CSSM_CSP_CreateAsymmetricContext(cspHand,
724 CSSM_ALGID_RSA,
725 &creds,
726 privKey,
727 CSSM_PADDING_PKCS1,
728 &cryptHand);
729 if(crtn) {
730 stPrintCdsaError("CSSM_CSP_CreateAsymmetricContext", crtn);
731 return SSLCryptoError;
732 }
733 ctextData.Data = (uint8 *)cipherText;
734 ctextData.Length = cipherTextLen;
735
736 if(privKey->KeyHeader.KeyClass == CSSM_KEYCLASS_PUBLIC_KEY) {
737 /*
738 * Special case, decrypting with public key (i.e., raw verify). Add
739 * the required context attr.
740 */
741 CSSM_CONTEXT_ATTRIBUTE modeAttr;
742
743 modeAttr.AttributeType = CSSM_ATTRIBUTE_MODE;
744 modeAttr.AttributeLength = sizeof(uint32);
745 modeAttr.Attribute.Uint32 = CSSM_ALGMODE_PUBLIC_KEY;
746 crtn = CSSM_UpdateContextAttributes(cryptHand, 1, &modeAttr);
747 if(crtn) {
748 stPrintCdsaError("CSSM_UpdateContextAttributes", crtn);
749 CSSM_DeleteContext(cryptHand);
750 return SSLCryptoError;
751 }
752 }
753
754 /*
755 * Have CSP malloc plaintext
756 */
757 crtn = CSSM_DecryptData(cryptHand,
758 &ctextData,
759 1,
760 &ptextData,
761 1,
762 &bytesMoved,
763 &remData);
764 if(crtn == CSSM_OK) {
765 /*
766 * plaintext in both ptextData and remData; ensure it'll fit
767 * in caller's buf & copy
768 */
769 if(bytesMoved > plainTextLen) {
770 errorLog2("sslRsaDecrypt overflow; plainTextLen %ld bytesMoved %ld\n",
771 plainTextLen, bytesMoved);
772 serr = SSLDataOverflow;
773 }
774 else {
775 UInt32 toMovePtext;
776 UInt32 toMoveRem;
777
778 *actualBytes = bytesMoved;
779 /*
780 * Snag valid data from ptextData - its length or bytesMoved,
781 * whichever is less
782 */
783 if(ptextData.Length > bytesMoved) {
784 /* everything's in ptext */
785 toMovePtext = bytesMoved;
786 toMoveRem = 0;
787 }
788 else {
789 /* must be some in remData too */
790 toMovePtext = ptextData.Length;
791 toMoveRem = bytesMoved - toMovePtext; // remainder
792 }
793 if(toMovePtext) {
794 memmove(plainText, ptextData.Data, toMovePtext);
795 }
796 if(toMoveRem) {
797 memmove(plainText + toMovePtext, remData.Data,
798 toMoveRem);
799 }
800 serr = SSLNoErr;
801 }
802 }
803 else {
804 stPrintCdsaError("CSSM_DecryptData", crtn);
805 serr = SSLCryptoError;
806 }
807 if(cryptHand != 0) {
808 CSSM_DeleteContext(cryptHand);
809 }
810
811 /* free data mallocd by CSP */
812 stFreeCssmData(&ptextData, CSSM_FALSE);
813 stFreeCssmData(&remData, CSSM_FALSE);
814 return serr;
815 }
816
817 #endif /* APPLE_DOMESTIC_CSP_REQUIRED */
818
819 /*
820 * Obtain size of key in bytes.
821 */
822 UInt32 sslKeyLengthInBytes(const CSSM_KEY *key)
823 {
824 CASSERT(key != NULL);
825 return (((key->KeyHeader.LogicalKeySizeInBits) + 7) / 8);
826 }
827
828 /*
829 * Get raw key bits from an RSA public key.
830 */
831 SSLErr sslGetPubKeyBits(
832 SSLContext *ctx,
833 const CSSM_KEY *pubKey,
834 CSSM_CSP_HANDLE cspHand,
835 SSLBuffer *modulus, // data mallocd and RETURNED
836 SSLBuffer *exponent) // data mallocd and RETURNED
837 {
838 CSSM_KEY wrappedKey;
839 CSSM_BOOL didWrap = CSSM_FALSE;
840 const CSSM_KEYHEADER *hdr;
841 CSSM_CC_HANDLE ccHand;
842 CSSM_RETURN crtn;
843 SSLBuffer pubKeyBlob;
844 SSLErr srtn;
845 CSSM_ACCESS_CREDENTIALS creds;
846
847 CASSERT(ctx != NULL);
848 CASSERT(modulus != NULL);
849 CASSERT(exponent != NULL);
850 CASSERT(pubKey != NULL);
851
852 hdr = &pubKey->KeyHeader;
853 if(hdr->KeyClass != CSSM_KEYCLASS_PUBLIC_KEY) {
854 errorLog1("sslGetPubKeyBits: bad keyClass (%ld)\n", hdr->KeyClass);
855 return SSLInternalError;
856 }
857 if(hdr->AlgorithmId != CSSM_ALGID_RSA) {
858 errorLog1("sslGetPubKeyBits: bad AlgorithmId (%ld)\n", hdr->AlgorithmId);
859 return SSLInternalError;
860 }
861
862 /*
863 * Handle possible reference format - I think it should be in
864 * blob form since it came from the DL, but conversion is
865 * simple.
866 */
867 switch(hdr->BlobType) {
868 case CSSM_KEYBLOB_RAW:
869 /* easy case */
870 CSSM_TO_SSLBUF(&pubKey->KeyData, &pubKeyBlob);
871 break;
872
873 case CSSM_KEYBLOB_REFERENCE:
874 /*
875 * Convert to a blob via "NULL wrap"; no wrapping key,
876 * ALGID_NONE
877 */
878 srtn = attachToCsp(ctx);
879 if(srtn) {
880 return srtn;
881 }
882 memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
883 crtn = CSSM_CSP_CreateSymmetricContext(ctx->cspHand,
884 CSSM_ALGID_NONE,
885 CSSM_ALGMODE_NONE,
886 &creds, // creds
887 pubKey,
888 NULL, // InitVector
889 CSSM_PADDING_NONE,
890 0, // reserved
891 &ccHand);
892 if(crtn) {
893 stPrintCdsaError("sslGetPubKeyBits: CreateSymmetricContext failure", crtn);
894 return SSLMemoryErr;
895 }
896 memset(&wrappedKey, 0, sizeof(CSSM_KEY));
897 crtn = CSSM_WrapKey(ccHand,
898 &creds,
899 pubKey,
900 NULL, // descriptiveData
901 &wrappedKey);
902 CSSM_DeleteContext(ccHand);
903 if(crtn) {
904 stPrintCdsaError("CSSM_WrapKey", crtn);
905 return SSLCryptoError;
906 }
907 hdr = &wrappedKey.KeyHeader;
908 if(hdr->BlobType != CSSM_KEYBLOB_RAW) {
909 errorLog1("sslGetPubKeyBits: bad BlobType (%ld) after WrapKey\n",
910 hdr->BlobType);
911 return SSLCryptoError;
912 }
913 didWrap = CSSM_TRUE;
914 CSSM_TO_SSLBUF(&wrappedKey.KeyData, &pubKeyBlob);
915 break;
916
917 default:
918 errorLog1("sslGetPubKeyBits: bad BlobType (%ld)\n",
919 hdr->BlobType);
920 return SSLInternalError;
921
922 } /* switch BlobType */
923
924 CASSERT(hdr->BlobType == CSSM_KEYBLOB_RAW);
925 srtn = sslDecodeRsaBlob(&pubKeyBlob, modulus, exponent);
926 if(didWrap) {
927 CSSM_FreeKey(ctx->cspHand, NULL, &wrappedKey, CSSM_FALSE);
928 }
929 return srtn;
930 }
931
932 /*
933 * Given raw RSA key bits, cook up a CSSM_KEY_PTR. Used in
934 * Server-initiated key exchange.
935 */
936 SSLErr sslGetPubKeyFromBits(
937 SSLContext *ctx,
938 const SSLBuffer *modulus,
939 const SSLBuffer *exponent,
940 CSSM_KEY_PTR *pubKey, // mallocd and RETURNED
941 CSSM_CSP_HANDLE *cspHand) // RETURNED
942 {
943 CSSM_KEY_PTR key = NULL;
944 SSLErr serr;
945 SSLBuffer blob;
946 CSSM_KEYHEADER_PTR hdr;
947 CSSM_KEY_SIZE keySize;
948 CSSM_RETURN crtn;
949
950 CASSERT((ctx != NULL) && (modulus != NULL) && (exponent != NULL));
951 CASSERT((pubKey != NULL) && (cspHand != NULL));
952
953 *pubKey = NULL;
954 *cspHand = 0;
955
956 serr = attachToCsp(ctx);
957 if(serr) {
958 return serr;
959 }
960 serr = sslEncodeRsaBlob(modulus, exponent, &blob);
961 if(serr) {
962 return serr;
963 }
964
965 /* the rest is boilerplate, cook up a good-looking public key */
966 key = sslMalloc(sizeof(CSSM_KEY));
967 if(key == NULL) {
968 return SSLMemoryErr;
969 }
970 memset(key, 0, sizeof(CSSM_KEY));
971 hdr = &key->KeyHeader;
972
973 hdr->HeaderVersion = CSSM_KEYHEADER_VERSION;
974 /* key_ptr->KeyHeader.CspId is unknown (remains 0) */
975 hdr->BlobType = CSSM_KEYBLOB_RAW;
976 hdr->AlgorithmId = CSSM_ALGID_RSA;
977 hdr->Format = CSSM_KEYBLOB_RAW_FORMAT_PKCS1;
978 hdr->KeyClass = CSSM_KEYCLASS_PUBLIC_KEY;
979 /* comply with ASA requirements */
980 hdr->KeyUsage = CSSM_KEYUSE_VERIFY;
981 hdr->KeyAttr = CSSM_KEYATTR_EXTRACTABLE;
982 /* key_ptr->KeyHeader.StartDate is unknown (remains 0) */
983 /* key_ptr->KeyHeader.EndDate is unknown (remains 0) */
984 hdr->WrapAlgorithmId = CSSM_ALGID_NONE;
985 hdr->WrapMode = CSSM_ALGMODE_NONE;
986
987 /* blob->data was mallocd by sslEncodeRsaBlob, pass it over to
988 * actual key */
989 SSLBUF_TO_CSSM(&blob, &key->KeyData);
990
991 /*
992 * Get keySizeInBits. This also serves to validate the key blob
993 * we just cooked up.
994 */
995 crtn = CSSM_QueryKeySizeInBits(ctx->cspHand, CSSM_INVALID_HANDLE, key, &keySize);
996 if(crtn) {
997 stPrintCdsaError("sslGetPubKeyFromBits: QueryKeySizeInBits\n", crtn);
998 serr = SSLCryptoError;
999 goto abort;
1000 }
1001
1002 /* success */
1003 hdr->LogicalKeySizeInBits = keySize.EffectiveKeySizeInBits;
1004 *pubKey = key;
1005 *cspHand = ctx->cspHand;
1006 return SSLNoErr;
1007
1008 abort:
1009 /* note this frees the blob */
1010 sslFreeKey(ctx->cspHand, &key, NULL);
1011 return serr;
1012 }
1013
1014 #pragma mark -
1015 #pragma mark *** Public Certificate Functions ***
1016
1017 /*
1018 * Given a DER-encoded cert, obtain its public key as a CSSM_KEY_PTR.
1019 * Caller must CSSM_FreeKey and free the CSSM_KEY_PTR itself.
1020 *
1021 * For now, the returned cspHand is a copy of ctx->cspHand, so it
1022 * doesn't have to be detached later - this may change.
1023 *
1024 * Update: since CSSM_CL_CertGetKeyInfo() doesn't provide a means for
1025 * us to tell the CL what CSP to use, we really have no way of knowing
1026 * what is going on here...we return the process-wide (bare) cspHand,
1027 * which is currently always able to deal with this raw public key.
1028 */
1029 SSLErr sslPubKeyFromCert(
1030 SSLContext *ctx,
1031 const SSLBuffer *derCert,
1032 CSSM_KEY_PTR *pubKey, // RETURNED
1033 CSSM_CSP_HANDLE *cspHand) // RETURNED
1034 {
1035 SSLErr serr;
1036 CSSM_DATA certData;
1037 CSSM_RETURN crtn;
1038
1039 CASSERT(ctx != NULL);
1040 CASSERT(derCert != NULL);
1041 CASSERT(pubKey != NULL);
1042 CASSERT(cspHand != NULL);
1043
1044 *pubKey = NULL;
1045 *cspHand = 0;
1046
1047 serr = attachToCl(ctx);
1048 if(serr) {
1049 return serr;
1050 }
1051 serr = attachToCsp(ctx);
1052 if(serr) {
1053 return serr;
1054 }
1055 SSLBUF_TO_CSSM(derCert, &certData);
1056 crtn = CSSM_CL_CertGetKeyInfo(ctx->clHand, &certData, pubKey);
1057 if(crtn) {
1058 return SSLBadCert;
1059 }
1060 else {
1061 *cspHand = ctx->cspHand;
1062 return SSLNoErr;
1063 }
1064 }
1065
1066 #if 0
1067
1068 #include <Files.h>
1069 #include <Errors.h>
1070
1071 /* for writing root cert to a file */
1072
1073 static OSErr writeBlob(const CSSM_DATA_PTR blob,
1074 const char *fileName)
1075 {
1076 OSErr err = noErr;
1077 FSSpec fsp;
1078 short fileRef;
1079 long count = blob->Length;
1080 int len = strlen(fileName);
1081
1082 fsp.vRefNum = 0;
1083 fsp.parID = 0;
1084 fsp.name[0] = len;
1085 memmove(&fsp.name[1], fileName, len);
1086
1087 err = FSpCreate(&fsp, 0, 0, 0);
1088 if(err && (err != dupFNErr)) {
1089 dprintf1("***FSpCreate() returned %d\n", err);
1090 return err;
1091 }
1092 err = FSpOpenDF(&fsp, fsRdWrPerm, &fileRef);
1093 if(err) {
1094 dprintf1("***FSpOpenDF() returned %d\n", err);
1095 return err;
1096 }
1097 err = FSWrite(fileRef, &count, blob->Data);
1098 if(err) {
1099 dprintf1("***FSWrite() returned %d\n", err);
1100 return err;
1101 }
1102 err = FSClose(fileRef);
1103 if(err) {
1104 dprintf1("***FSClose() returned %d\n", err);
1105 return err;
1106 }
1107 return 0;
1108 }
1109
1110 void writeBufBlob(const SSLBuffer *blob,
1111 const char *fileName)
1112 {
1113 CSSM_DATA d;
1114
1115 SSLBUF_TO_CSSM(blob, &d)
1116 writeBlob(&d, fileName);
1117 }
1118
1119 #endif /* 0 */
1120
1121 #if ST_KEYCHAIN_ENABLE && ST_MANAGES_TRUSTED_ROOTS
1122
1123 /*
1124 * Given a CSSM_CERTGROUP which fails due to CSSM_TP_INVALID_ANCHOR
1125 * (chain verifies to an unknown root):
1126 *
1127 * -- find the root cert
1128 * -- add it to newRootCertKc if present (else error)
1129 * -- add it to trustedCerts
1130 * -- re-verify certgroup, demand full success
1131 */
1132 static SSLErr sslHandleNewRoot(
1133 SSLContext *ctx,
1134 CSSM_CERTGROUP_PTR certGroup)
1135 {
1136 int i;
1137 CSSM_DATA_PTR rootCert;
1138 CSSM_BOOL expired;
1139 SSLErr serr;
1140 CSSM_BOOL brtn;
1141
1142 CASSERT(ctx != NULL);
1143 CASSERT(certGroup != NULL);
1144
1145 if(ctx->newRootCertKc == NULL) {
1146 /* no place to add this; done */
1147 return SSLUnknownRootCert;
1148 }
1149
1150 /*
1151 * The root cert "should" be at the end of the chain, but
1152 * let's not assume that. (We are assuming that there is
1153 * only one root in the cert group...)
1154 */
1155 for(i=0; i<certGroup->NumCerts; i++) {
1156 rootCert = &certGroup->CertList[i];
1157 if(sslVerifyCert(ctx, rootCert, rootCert, ctx->cspHand, &expired)) {
1158 break;
1159 }
1160 }
1161 if(i == certGroup->NumCerts) {
1162 /* Huh! no root cert!? We should not have been called! */
1163 errorLog0("sslHandleNewRoot: no root cert!\n");
1164 return SSLInternalError;
1165 }
1166
1167 /*
1168 * Add to newRootCertKc. This may well fail due to user interaction.
1169 */
1170 serr = sslAddNewRoot(ctx, rootCert);
1171 if(serr) {
1172 return serr;
1173 }
1174
1175 /*
1176 * Just to be sure...reverify the whole cert chain.
1177 */
1178 brtn = CSSM_TP_CertGroupVerify(
1179 ctx->tpHand,
1180 ctx->clHand,
1181 ctx->cspHand,
1182 NULL, // DBList
1183 NULL, // PolicyIdentifiers
1184 0, // NumberofPolicyIdentifiers
1185 CSSM_TP_STOP_ON_POLICY,
1186 certGroup,
1187 ctx->trustedCerts, // AnchorCerts
1188 ctx->numTrustedCerts,
1189 NULL, // VerifyScope
1190 0, // ScopeSize
1191 0, // Action
1192 0, // Data
1193 NULL, // evidence
1194 NULL); // evidenceSize
1195 if(brtn == CSSM_FALSE) {
1196 errorLog0("sslHandleNewRoot: adding new root did not help!\n");
1197 return SSLUnknownRootCert;
1198 }
1199 return SSLNoErr;
1200 }
1201
1202 #endif /* ST_KEYCHAIN_ENABLE && ST_MANAGES_TRUSTED_ROOTS */
1203
1204 /* free a CSSM_CERT_GROUP */
1205 static void sslFreeCertGroup(
1206 CSSM_CERTGROUP_PTR certGroup,
1207 CSSM_BOOL freeCerts, // free individual cert fields
1208 CSSM_BOOL freeStruct) // free the overall CSSM_CERTGROUP
1209 {
1210 unsigned dex;
1211
1212 if(certGroup == NULL) {
1213 return;
1214 }
1215
1216 /* free the individual cert Data fields */
1217 if(certGroup->GroupList.CertList) {
1218 if(freeCerts) {
1219 for(dex=0; dex<certGroup->NumCerts; dex++) {
1220 stFreeCssmData(&certGroup->GroupList.CertList[dex], CSSM_FALSE);
1221 }
1222 }
1223 /* and the array of CSSM_DATAs */
1224 stAppFree(certGroup->GroupList.CertList, NULL);
1225 }
1226 if(freeStruct) {
1227 stAppFree(certGroup, NULL);
1228 }
1229 }
1230
1231 /*
1232 * Verify a chain of DER-encoded certs.
1233 * First cert in a chain is root; this must also be present
1234 * in ctx->trustedCerts.
1235 */
1236 SSLErr sslVerifyCertChain(
1237 SSLContext *ctx,
1238 const SSLCertificate *certChain)
1239 {
1240 UInt32 numCerts;
1241 CSSM_CERTGROUP certGroup;
1242 int i;
1243 SSLErr serr;
1244 SSLCertificate *c = (SSLCertificate *)certChain;
1245 CSSM_RETURN crtn;
1246 CSSM_TP_VERIFY_CONTEXT vfyCtx;
1247 CSSM_TP_CALLERAUTH_CONTEXT authCtx;
1248 CSSM_FIELD policyId;
1249 CSSM_DL_DB_LIST dbList;
1250 CSSM_APPLE_TP_SSL_OPTIONS sslOpts;
1251 CSSM_APPLE_TP_ACTION_DATA actionData;
1252
1253 /* FIXME - allowAnyRoot should probably mean "return success" with
1254 * no checking */
1255
1256 numCerts = SSLGetCertificateChainLength(certChain);
1257 if(numCerts == 0) {
1258 /* nope */
1259 return SSLBadCert;
1260 }
1261 #if 0
1262 serr = attachToAll(ctx);
1263 if(serr) {
1264 return serr;
1265 }
1266 #endif
1267
1268 /*
1269 * SSLCertificate chain --> CSSM TP cert group.
1270 * TP Cert group has root at the end, opposite of
1271 * SSLCertificate chain.
1272 */
1273 certGroup.GroupList.CertList =
1274 (CSSM_DATA_PTR)sslMalloc(numCerts * sizeof(CSSM_DATA));
1275 if(certGroup.GroupList.CertList == NULL) {
1276 return SSLMemoryErr;
1277 }
1278 certGroup.CertGroupType = CSSM_CERTGROUP_DATA;
1279 certGroup.CertType = CSSM_CERT_X_509v3;
1280 certGroup.CertEncoding = CSSM_CERT_ENCODING_DER;
1281 certGroup.NumCerts = numCerts;
1282
1283 memset(certGroup.GroupList.CertList, 0, numCerts * sizeof(CSSM_DATA));
1284
1285 for(i=numCerts-1; i>=0; i--) {
1286 SSLBUF_TO_CSSM(&c->derCert, &certGroup.GroupList.CertList[i]);
1287 c = c->next;
1288 }
1289
1290 memset(&vfyCtx, 0, sizeof(CSSM_TP_VERIFY_CONTEXT));
1291 vfyCtx.Action = CSSM_TP_ACTION_DEFAULT;
1292 vfyCtx.Cred = &authCtx;
1293
1294 /* CSSM_TP_CALLERAUTH_CONTEXT components */
1295 /*
1296 typedef struct cssm_tp_callerauth_context {
1297 CSSM_TP_POLICYINFO Policy;
1298 CSSM_TIMESTRING VerifyTime;
1299 CSSM_TP_STOP_ON VerificationAbortOn;
1300 CSSM_TP_VERIFICATION_RESULTS_CALLBACK CallbackWithVerifiedCert;
1301 uint32 NumberOfAnchorCerts;
1302 CSSM_DATA_PTR AnchorCerts;
1303 CSSM_DL_DB_LIST_PTR DBList;
1304 CSSM_ACCESS_CREDENTIALS_PTR CallerCredentials;
1305 } CSSM_TP_CALLERAUTH_CONTEXT, *CSSM_TP_CALLERAUTH_CONTEXT_PTR;
1306 */
1307
1308 /* SSL-specific FieldValue */
1309 sslOpts.Version = CSSM_APPLE_TP_SSL_OPTS_VERSION;
1310 sslOpts.ServerNameLen = ctx->peerDomainNameLen;
1311 sslOpts.ServerName = ctx->peerDomainName;
1312
1313 /* TP-wide ActionData */
1314 actionData.Version = CSSM_APPLE_TP_ACTION_VERSION;
1315 actionData.ActionFlags = 0x80000000; // @@@ secret root-cert-enable
1316 if(ctx->allowExpiredCerts) {
1317 actionData.ActionFlags |= CSSM_TP_ACTION_ALLOW_EXPIRED;
1318 }
1319 vfyCtx.ActionData.Data = (uint8 *)&actionData;
1320 vfyCtx.ActionData.Length = sizeof(actionData);
1321
1322 /* zero or one policy here */
1323 policyId.FieldOid = CSSMOID_APPLE_TP_SSL;
1324 policyId.FieldValue.Data = (uint8 *)&sslOpts;
1325 policyId.FieldValue.Length = sizeof(sslOpts);
1326 authCtx.Policy.NumberOfPolicyIds = 1;
1327 authCtx.Policy.PolicyIds = &policyId;
1328
1329 authCtx.VerifyTime = NULL;
1330 authCtx.VerificationAbortOn = CSSM_TP_STOP_ON_POLICY;
1331 authCtx.CallbackWithVerifiedCert = NULL;
1332 authCtx.NumberOfAnchorCerts = ctx->numTrustedCerts;
1333 authCtx.AnchorCerts = ctx->trustedCerts;
1334 memset(&dbList, 0, sizeof(CSSM_DL_DB_LIST));
1335 authCtx.DBList = &dbList;
1336 authCtx.CallerCredentials = NULL;
1337
1338 /*
1339 * Here we go; hand it over to TP. Note trustedCerts are our
1340 * known good Anchor certs; they're already formatted properly.
1341 * Unlike most other Apple code, we demand full success here,
1342 * implying that the last cert in the chain is indeed an Anchor
1343 * cert. We already know that all of our anchor certs are
1344 * roots, so on successful return, we'll know the incoming
1345 * chain has a root, it verifies to that root, and that that
1346 * root is in trustedCerts.
1347 */
1348 crtn = CSSM_TP_CertGroupVerify(ctx->tpHand,
1349 ctx->clHand,
1350 ctx->cspHand,
1351 &certGroup,
1352 &vfyCtx,
1353 NULL); // no evidence needed
1354
1355 serr = SSLNoErr;
1356 if(crtn) {
1357 /* get some detailed error info */
1358 switch(crtn) {
1359 case CSSMERR_TP_INVALID_ANCHOR_CERT:
1360 /* root found but we don't trust it */
1361 if(ctx->allowAnyRoot) {
1362 dprintf0("***Warning: accepting unknown root cert\n");
1363 break;
1364 }
1365 #if ST_KEYCHAIN_ENABLE && ST_MANAGES_TRUSTED_ROOTS
1366 if(ctx->newRootCertKc != NULL) {
1367 /* see if user wants to handle new root */
1368 serr = sslHandleNewRoot(ctx, &certGroup);
1369 }
1370 else {
1371 serr = SSLUnknownRootCert;
1372 }
1373 #else
1374 serr = SSLUnknownRootCert;
1375 #endif /* ST_KEYCHAIN_ENABLE && ST_MANAGES_TRUSTED_ROOTS */
1376 break;
1377 case CSSMERR_TP_NOT_TRUSTED:
1378 /* no root, not even in implicit SSL roots */
1379 if(ctx->allowAnyRoot) {
1380 dprintf0("***Warning: accepting unverified cert chain\n");
1381 break;
1382 }
1383 serr = SSLNoRootCert;
1384 break;
1385 case CSSMERR_TP_CERT_EXPIRED:
1386 assert(!ctx->allowExpiredCerts);
1387 serr = SSLCertExpired;
1388 break;
1389 case CSSMERR_TP_CERT_NOT_VALID_YET:
1390 serr = SSLCertNotYetValid;
1391 break;
1392 default:
1393 stPrintCdsaError(
1394 "sslVerifyCertChain: CSSM_TP_CertGroupVerify returned", crtn);
1395 serr = X509CertChainInvalidErr;
1396 break;
1397 }
1398 } /* brtn FALSE */
1399
1400 /*
1401 * don't free individual certs - caller still owns them
1402 * don't free struct - on stack
1403 */
1404 sslFreeCertGroup(&certGroup, CSSM_FALSE, CSSM_FALSE);
1405 return serr;
1406 }
1407
1408
1409 #if 0
1410 /* not needed in X */
1411
1412 /*
1413 * Given two certs, verify subjectCert with issuerCert. Returns
1414 * CSSM_TRUE on successful verify.
1415 * Only special case on error is "subject cert expired", indicated by
1416 * *subjectExpired returned as CSSM_TRUE.
1417 */
1418 CSSM_BOOL sslVerifyCert(
1419 SSLContext *ctx,
1420 const CSSM_DATA_PTR subjectCert,
1421 const CSSM_DATA_PTR issuerCert,
1422 CSSM_CSP_HANDLE cspHand, // can verify with issuerCert
1423 CSSM_BOOL *subjectExpired) // RETURNED
1424 {
1425 CSSM_KEY_PTR issuerPubKey = NULL;
1426 CSSM_DATA_PTR sigOid = NULL;
1427 CSSM_HANDLE ResultsHandle;
1428 uint32 NumberOfFields;
1429 CSSM_ERROR_PTR pErr = NULL;
1430 CSSM_BOOL brtn;
1431 uint32 *algId = NULL; // mallocd by CL_Passthrough
1432 CSSM_CC_HANDLE ccHand = 0;
1433
1434 *subjectExpired = CSSM_FALSE;
1435
1436 /* ensure connection to CL, TP */
1437 if(attachToCl(ctx)) {
1438 return CSSM_FALSE;
1439 }
1440 if(attachToTp(ctx)) {
1441 return CSSM_FALSE;
1442 }
1443
1444 /* public key from issuer cert */
1445 issuerPubKey = CSSM_CL_CertGetKeyInfo(ctx->clHand, issuerCert);
1446 if(issuerPubKey == NULL) {
1447 return CSSM_FALSE;
1448 }
1449 /* subsequent errors to abort: */
1450
1451 /* signature alg from subject cert */
1452 sigOid = CSSM_CL_CertGetFirstFieldValue(ctx->clHand,
1453 subjectCert,
1454 &CSSMOID_X509V1SignatureAlgorithm,
1455 &ResultsHandle,
1456 &NumberOfFields);
1457 if(sigOid == NULL) {
1458 stPrintCdsaError("CSSM_CL_CertGetFirstFieldValue");
1459 brtn = CSSM_FALSE;
1460 CSSM_CL_CertAbortQuery(ctx->clHand, ResultsHandle);
1461 goto abort;
1462 }
1463 /* cleanup query state */
1464 CSSM_CL_CertAbortQuery(ctx->clHand, ResultsHandle);
1465
1466 /* convert: alg OID to CSSM_ALGID_xxx */
1467 algId = (uint32 *)CSSM_CL_PassThrough(ctx->clHand,
1468 0, // no handle needed
1469 INTEL_X509V3_PASSTHROUGH_ALGOID_TO_ALGID,
1470 sigOid);
1471 if(*algId == CSSM_ALGID_NONE) {
1472 brtn = CSSM_FALSE;
1473 goto abort;
1474 }
1475
1476 /* set up a sign context with obtained pub key and algorithm */
1477 ccHand = CSSM_CSP_CreateSignatureContext(cspHand,
1478 *algId,
1479 NULL, // no passphrase
1480 issuerPubKey);
1481 if(ccHand == 0) {
1482 brtn = CSSM_FALSE;
1483 goto abort;
1484 }
1485
1486 /* go for it - CL takes over from here */
1487 brtn = CSSM_CL_CertVerify(ctx->clHand,
1488 ccHand,
1489 subjectCert,
1490 issuerCert,
1491 NULL, // VerifyScope
1492 0); // ScopeSize
1493 if(!brtn && (CSSM_GetError()->error == CSSM_CL_CERT_EXPIRED)) {
1494 *subjectExpired = CSSM_TRUE;
1495 }
1496
1497 abort:
1498 if(issuerPubKey != NULL) {
1499 CSSM_Free(issuerPubKey->KeyData.Data);
1500 CSSM_Free(issuerPubKey);
1501 }
1502 if(sigOid != NULL) {
1503 CSSM_Free(sigOid->Data);
1504 CSSM_Free(sigOid);
1505 }
1506 if(ccHand != 0) {
1507 CSSM_DeleteContext(ccHand);
1508 }
1509 if(algId != NULL) {
1510 CSSM_Free(algId);
1511 }
1512 return brtn;
1513 }
1514 #endif /* 0 - not needed */
1515
1516 #if ST_KEYCHAIN_ENABLE
1517 /* no cert parsing in this version */
1518
1519 /*
1520 * Given a DER-encoded cert, obtain its DER-encoded subject name.
1521 */
1522 CSSM_DATA_PTR sslGetCertSubjectName(
1523 SSLContext *ctx,
1524 const CSSM_DATA_PTR cert)
1525 {
1526 uint32 NumberOfFields = 0;
1527 CSSM_HANDLE ResultsHandle = 0;
1528 CSSM_DATA_PTR pEncodedName = NULL;
1529 CSSM_RETURN crtn;
1530
1531 /* ensure connection to CL */
1532 if(attachToCl(ctx)) {
1533 return NULL;
1534 }
1535 crtn = CSSM_CL_CertGetFirstFieldValue(
1536 ctx->clHand,
1537 cert,
1538 &CSSMOID_X509V1SubjectName,
1539 &ResultsHandle,
1540 &NumberOfFields,
1541 &pEncodedName);
1542 if(crtn) {
1543 stPrintCdsaError("CertGetFirstFieldValue", crtn);
1544 }
1545 CSSM_CL_CertAbortQuery(ctx->clHand, ResultsHandle);
1546 return pEncodedName;
1547 }
1548 #endif ST_KEYCHAIN_ENABLE
1549
1550 #if (SSL_DEBUG && ST_KEYCHAIN_ENABLE && ST_MANAGES_TRUSTED_ROOTS)
1551 void verifyTrustedRoots(SSLContext *ctx,
1552 CSSM_DATA_PTR certs,
1553 unsigned numCerts)
1554 {
1555 int i;
1556 CSSM_DATA_PTR cert;
1557 CSSM_BOOL expired;
1558
1559 for(i=0; i<numCerts; i++) {
1560 cert = &certs[i];
1561 if(!sslVerifyCert(ctx,
1562 cert,
1563 cert,
1564 ctx->cspHand,
1565 &expired)) {
1566 sslPanic("Bad trusted cert!\n");
1567 }
1568 }
1569 }
1570 #endif
1571
1572