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