]> git.saurik.com Git - apple/security.git/blob - libsecurity_smime/lib/cert.c
Security-58286.270.3.0.1.tar.gz
[apple/security.git] / libsecurity_smime / lib / cert.c
1 /*
2 * cert.c
3 * security_smime
4 *
5 * Created by john on Wed Mar 12 2003.
6 * Copyright (c) 2003 __MyCompanyName__. All rights reserved.
7 *
8 */
9
10 #include "cert.h"
11 #include "cmstpriv.h"
12 #include <security_asn1/secerr.h>
13 #include <Security/SecKeychain.h>
14 #include <Security/SecKeychainItem.h>
15 #include <Security/SecKeychainSearch.h>
16 #include <Security/SecIdentityPriv.h>
17 #include <Security/SecIdentitySearch.h>
18 #include <Security/SecCertificatePriv.h>
19 #include <Security/SecPolicySearch.h>
20 #include <Security/oidsalg.h>
21 #include <Security/cssmapi.h>
22 #include <Security/oidscert.h>
23 #include <Security/oidscert.h>
24
25 /* for errKCDuplicateItem */
26 #include <Security/SecBase.h>
27
28 /* @@@ Remove this once it's back in the appropriate header. */
29 static const uint8 X509V1IssuerNameStd[] = {INTEL_X509V3_CERT_R08, 23};
30 static const CSSM_OID OID_X509V1IssuerNameStd = {INTEL_X509V3_CERT_R08_LENGTH+1, (uint8 *)X509V1IssuerNameStd};
31
32 /*
33 * Normalize a Printable String. Per RFC2459 (4.1.2.4), printable strings are case
34 * insensitive and we're supposed to ignore leading and trailing
35 * whitespace, and collapse multiple whitespace characters into one.
36 */
37 static void
38 CERT_NormalizeString(CSSM_DATA_PTR string)
39 {
40 char *pD, *pCh, *pEos;
41
42 if (!string->Length)
43 return;
44
45 pD = pCh = (char *)string->Data;
46 pEos = pCh + string->Length - 1;
47
48 /* Strip trailing NULL terminators */
49 while(*pEos == 0)
50 pEos--;
51
52 /* Remove trailing spaces */
53 while(isspace(*pEos))
54 pEos--;
55
56 /* Point to one past last non-space character */
57 pEos++;
58
59 /* skip all leading whitespace */
60 while(isspace(*pCh) && (pCh < pEos))
61 pCh++;
62
63 /* Eliminate multiple whitespace and convent to upper case.
64 * pCh points to first non-white char.
65 * pD still points to start of string. */
66 while(pCh < pEos)
67 {
68 char ch = *pCh++;
69 *pD++ = toupper(ch);
70 if(isspace(ch))
71 {
72 /* skip 'til next nonwhite */
73 while(isspace(*pCh) && (pCh < pEos))
74 pCh++;
75 }
76 }
77
78 string->Length = pD - (char *)string->Data;
79 }
80
81 /*
82 * Normalize an RDN. Per RFC2459 (4.1.2.4), printable strings are case
83 * insensitive and we're supposed to ignore leading and trailing
84 * whitespace, and collapse multiple whitespace characters into one.
85 *
86 * Incoming NSS_Name is assumed to be entirely within specifed coder's
87 * address space; we'll be munging some of that and possibly replacing
88 * some pointers with others allocated from the same space.
89 */
90 void
91 CERT_NormalizeX509NameNSS(NSS_Name *nssName)
92 {
93 NSS_RDN *rdn;
94
95 for (rdn = *nssName->rdns; rdn; ++rdn)
96 {
97 NSS_ATV *attr;
98 for (attr = *rdn->atvs; attr; ++attr)
99 {
100 /*
101 * attr->value is an ASN_ANY containing an encoded
102 * string. We only normalize Prinatable String types.
103 * If we find one, decode it, normalize it, encode the
104 * result, and put the encoding back in attr->value.
105 * We temporarily "leak" the original string, which only
106 * has a lifetime of the incoming SecNssCoder.
107 */
108 NSS_TaggedItem *attrVal = &attr->value;
109 if(attrVal->tag != SEC_ASN1_PRINTABLE_STRING)
110 continue;
111
112 CERT_NormalizeString(&attrVal->item);
113 }
114 }
115 }
116
117 SecCertificateRef CERT_FindCertByNicknameOrEmailAddr(SecKeychainRef keychainOrArray, char *name)
118 {
119 SecCertificateRef certificate;
120 OSStatus status=SecCertificateFindByEmail(keychainOrArray,name,&certificate);
121 return status==errSecSuccess?certificate:NULL;
122 }
123
124 SecPublicKeyRef SECKEY_CopyPublicKey(SecPublicKeyRef pubKey)
125 {
126 CFRetain(pubKey);
127 return pubKey;
128 }
129
130 void SECKEY_DestroyPublicKey(SecPublicKeyRef pubKey)
131 {
132 CFRelease(pubKey);
133 }
134
135 SecPublicKeyRef SECKEY_CopyPrivateKey(SecPublicKeyRef privKey)
136 {
137 CFRetain(privKey);
138 return privKey;
139 }
140
141 void SECKEY_DestroyPrivateKey(SecPublicKeyRef privKey)
142 {
143 CFRelease(privKey);
144 }
145
146 void CERT_DestroyCertificate(SecCertificateRef cert)
147 {
148 CFRelease(cert);
149 }
150
151 SecCertificateRef CERT_DupCertificate(SecCertificateRef cert)
152 {
153 CFRetain(cert);
154 return cert;
155 }
156
157 SecIdentityRef CERT_FindIdentityByUsage(SecKeychainRef keychainOrArray,
158 char *nickname, SECCertUsage usage, Boolean validOnly, void *proto_win)
159 {
160 SecIdentityRef identityRef = NULL;
161 SecCertificateRef cert = CERT_FindCertByNicknameOrEmailAddr(keychainOrArray, nickname);
162 if (!cert)
163 return NULL;
164
165 SecIdentityCreateWithCertificate(keychainOrArray, cert, &identityRef);
166 CFRelease(cert);
167
168 return identityRef;
169 }
170
171 SecCertificateRef CERT_FindUserCertByUsage(SecKeychainRef keychainOrArray,
172 char *nickname,SECCertUsage usage,Boolean validOnly,void *proto_win)
173 {
174 SecItemClass itemClass = kSecCertificateItemClass;
175 SecKeychainSearchRef searchRef;
176 SecKeychainItemRef itemRef = NULL;
177 OSStatus status;
178 SecKeychainAttribute attrs[1];
179 const char *serialNumber = "12345678";
180 // const SecKeychainAttributeList attrList;
181 #if 0
182 attrs[0].tag = kSecLabelItemAttr;
183 attrs[0].length = strlen(nickname)+1;
184 attrs[0].data = nickname;
185 #else
186 attrs[0].tag = kSecSerialNumberItemAttr;
187 attrs[0].length = strlen(serialNumber)+1;
188 attrs[0].data = (uint8 *)serialNumber;
189 #endif
190 SecKeychainAttributeList attrList = { 0, attrs };
191 // 12 34 56 78
192 status = SecKeychainSearchCreateFromAttributes(keychainOrArray,itemClass,&attrList,&searchRef);
193 if (status)
194 {
195 printf("CERT_FindUserCertByUsage: SecKeychainSearchCreateFromAttributes:%ld",status);
196 return NULL;
197 }
198 status = SecKeychainSearchCopyNext(searchRef,&itemRef);
199 if (status)
200 printf("CERT_FindUserCertByUsage: SecKeychainSearchCopyNext:%ld",status);
201 CFRelease(searchRef);
202 return (SecCertificateRef)itemRef;
203 }
204
205 /*
206 startNewClass(X509Certificate)
207 CertType, kSecCertTypeItemAttr, "CertType", 0, NULL, UINT32)
208 CertEncoding, kSecCertEncodingItemAttr, "CertEncoding", 0, NULL, UINT32)
209 PrintName, kSecLabelItemAttr, "PrintName", 0, NULL, BLOB)
210 Alias, kSecAliasItemAttr, "Alias", 0, NULL, BLOB)
211 Subject, kSecSubjectItemAttr, "Subject", 0, NULL, BLOB)
212 Issuer, kSecIssuerItemAttr, "Issuer", 0, NULL, BLOB)
213 SerialNumber, kSecSerialNumberItemAttr, "SerialNumber", 0, NULL, BLOB)
214 SubjectKeyIdentifier, kSecSubjectKeyIdentifierItemAttr, "SubjectKeyIdentifier", 0, NULL, BLOB)
215 PublicKeyHash, kSecPublicKeyHashItemAttr, "PublicKeyHash", 0, NULL, BLOB)
216 endNewClass()
217 */
218
219 CFArrayRef CERT_CertChainFromCert(SecCertificateRef cert, SECCertUsage usage, Boolean includeRoot)
220 {
221 SecPolicySearchRef searchRef = NULL;
222 SecPolicyRef policy = NULL;
223 CFArrayRef wrappedCert = NULL;
224 SecTrustRef trust = NULL;
225 CFArrayRef certChain = NULL;
226 CSSM_TP_APPLE_EVIDENCE_INFO *statusChain;
227 OSStatus status = 0;
228 SecTrustResultType trustResult = kSecTrustResultInvalid;
229
230 if (!cert)
231 goto loser;
232
233 status = SecPolicySearchCreate(CSSM_CERT_X_509v3, &CSSMOID_APPLE_X509_BASIC, NULL, &searchRef);
234 if (status)
235 goto loser;
236 status = SecPolicySearchCopyNext(searchRef, &policy);
237 if (status)
238 goto loser;
239
240 wrappedCert = CERT_CertListFromCert(cert);
241 status = SecTrustCreateWithCertificates(wrappedCert, policy, &trust);
242 if (status)
243 goto loser;
244
245 status = SecTrustEvaluate(trust, &trustResult);
246 if (status)
247 goto loser;
248
249 status = SecTrustGetResult(trust, NULL, &certChain, &statusChain);
250 if (status)
251 goto loser;
252
253 /* We don't drop the root if there is only 1 (self signed) certificate in the chain. */
254 if (!includeRoot && CFArrayGetCount(certChain) > 1)
255 {
256 CFMutableArrayRef subChain = CFArrayCreateMutableCopy(NULL, 0, certChain);
257 CFRelease(certChain);
258 certChain = subChain;
259 if (subChain)
260 CFArrayRemoveValueAtIndex(subChain, CFArrayGetCount(subChain) - 1);
261 }
262
263 loser:
264 if (searchRef)
265 CFRelease(searchRef);
266 if (policy)
267 CFRelease(policy);
268 if (wrappedCert)
269 CFRelease(wrappedCert);
270 if (trust)
271 CFRelease(trust);
272 if (certChain && status)
273 {
274 CFRelease(certChain);
275 certChain = NULL;
276 }
277
278 return certChain;
279 }
280
281 CFArrayRef CERT_CertListFromCert(SecCertificateRef cert)
282 {
283 const void *value = cert;
284 return cert ? CFArrayCreate(NULL, &value, 1, &kCFTypeArrayCallBacks) : NULL;
285 }
286
287 CFArrayRef CERT_DupCertList(CFArrayRef oldList)
288 {
289 CFRetain(oldList);
290 return oldList;
291 }
292
293 // Extract a public key object from a SubjectPublicKeyInfo
294 SecPublicKeyRef CERT_ExtractPublicKey(SecCertificateRef cert)
295 {
296 SecPublicKeyRef keyRef = NULL;
297 SecCertificateCopyPublicKey(cert,&keyRef);
298 return keyRef;
299 }
300
301 SECStatus CERT_CheckCertUsage (SecCertificateRef cert,unsigned char usage)
302 {
303 // abort();
304 // @@@ It's all good, it's ok.
305 return SECSuccess;
306 }
307
308 // Find a certificate in the database by a email address
309 // "emailAddr" is the email address to look up
310 SecCertificateRef CERT_FindCertByEmailAddr(SecKeychainRef keychainOrArray, char *emailAddr)
311 {
312 abort();
313 return NULL;
314 }
315
316 // Find a certificate in the database by a DER encoded certificate
317 // "derCert" is the DER encoded certificate
318 SecCertificateRef CERT_FindCertByDERCert(SecKeychainRef keychainOrArray, const SECItem *derCert)
319 {
320 // @@@ Technically this should look though keychainOrArray for a cert matching this one I guess.
321 SecCertificateRef cert = NULL;
322 OSStatus rv;
323
324 rv = SecCertificateCreateFromData(derCert, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, &cert);
325 if (rv && cert)
326 {
327 PORT_SetError(SEC_ERROR_NO_EMAIL_CERT);
328 CFRelease(cert);
329 cert = NULL;
330 }
331
332 return cert;
333 }
334
335 // Generate a certificate key from the issuer and serialnumber, then look it up in the database.
336 // Return the cert if found. "issuerAndSN" is the issuer and serial number to look for
337 SecCertificateRef CERT_FindCertByIssuerAndSN (CFTypeRef keychainOrArray, const SecCmsIssuerAndSN *issuerAndSN)
338 {
339 SecCertificateRef certificate;
340 OSStatus status = SecCertificateFindByIssuerAndSN(keychainOrArray, &issuerAndSN->derIssuer,
341 &issuerAndSN->serialNumber, &certificate);
342 if (status)
343 {
344 PORT_SetError(SEC_ERROR_NO_EMAIL_CERT);
345 certificate = NULL;
346 }
347
348 return certificate;
349 }
350
351 SecCertificateRef CERT_FindCertBySubjectKeyID (CFTypeRef keychainOrArray, const SecAsn1Item *subjKeyID)
352 {
353 SecCertificateRef certificate;
354 OSStatus status = SecCertificateFindBySubjectKeyID(keychainOrArray,subjKeyID,&certificate);
355 if (status)
356 {
357 PORT_SetError(SEC_ERROR_NO_EMAIL_CERT);
358 certificate = NULL;
359 }
360
361 return certificate;
362 }
363
364 static SecIdentityRef
365 CERT_FindIdentityByCertificate (CFTypeRef keychainOrArray, SecCertificateRef certificate)
366 {
367 SecIdentityRef identity = NULL;
368 SecIdentityCreateWithCertificate(keychainOrArray, certificate, &identity);
369 if (!identity)
370 PORT_SetError(SEC_ERROR_NOT_A_RECIPIENT);
371
372 return identity;
373 }
374
375 SecIdentityRef
376 CERT_FindIdentityByIssuerAndSN (CFTypeRef keychainOrArray, const SecCmsIssuerAndSN *issuerAndSN)
377 {
378 SecCertificateRef certificate = CERT_FindCertByIssuerAndSN(keychainOrArray, issuerAndSN);
379 if (!certificate)
380 return NULL;
381
382 return CERT_FindIdentityByCertificate(keychainOrArray, certificate);
383 }
384
385 SecIdentityRef
386 CERT_FindIdentityBySubjectKeyID (CFTypeRef keychainOrArray, const SECItem *subjKeyID)
387 {
388 SecCertificateRef certificate = CERT_FindCertBySubjectKeyID(keychainOrArray, subjKeyID);
389 if (!certificate)
390 return NULL;
391
392 return CERT_FindIdentityByCertificate(keychainOrArray, certificate);
393 }
394
395 // find the smime symmetric capabilities profile for a given cert
396 SECItem *CERT_FindSMimeProfile(SecCertificateRef cert)
397 {
398 return NULL;
399 }
400
401 // Return the decoded value of the subjectKeyID extension. The caller should
402 // free up the storage allocated in retItem->data.
403 SECStatus CERT_FindSubjectKeyIDExtension (SecCertificateRef cert,SECItem *retItem)
404 {
405 fprintf(stderr, "WARNING: CERT_FindSubjectKeyIDExtension unimplemented\n");
406 return SECFailure;
407 }
408
409 static void * appMalloc (uint32 size, void *allocRef) {
410 return (malloc (size));
411 }
412
413 static void appFree (void *mem_ptr, void *allocRef) {
414 free (mem_ptr);
415 return;
416 }
417
418 static void * appRealloc (void *ptr, uint32 size, void *allocRef) {
419 return (realloc (ptr, size));
420 }
421
422 static void * appCalloc (uint32 num, uint32 size, void *allocRef) {
423 return (calloc (num, size));
424 }
425
426 static CSSM_API_MEMORY_FUNCS memFuncs = {
427 appMalloc,
428 appFree,
429 appRealloc,
430 appCalloc,
431 NULL
432 };
433
434 // return a valid CL handle
435 static int InitializeCL (CSSM_CL_HANDLE *clHandle)
436 {
437 CSSM_VERSION version = {2, 0};
438
439 // load the module
440 CSSM_RETURN result = CSSM_ModuleLoad (&gGuidAppleX509CL, CSSM_KEY_HIERARCHY_NONE, NULL, NULL);
441 if (result != 0)
442 {
443 return false;
444 }
445
446 result = CSSM_ModuleAttach (&gGuidAppleX509CL, &version, &memFuncs, 0, CSSM_SERVICE_CL, 0, 0, NULL, 0, NULL, clHandle);
447 if (result != 0)
448 {
449 return false;
450 }
451
452 return true;
453 }
454
455 // cleanup a CL handle
456 static void CloseCL (CSSM_CL_HANDLE clHandle)
457 {
458 CSSM_ModuleDetach (clHandle);
459 CSSM_ModuleUnload (&gGuidAppleX509CL, NULL, NULL);
460 }
461
462 // Extract the issuer and serial number from a certificate
463 SecCmsIssuerAndSN *CERT_GetCertIssuerAndSN(PRArenaPool *pl, SecCertificateRef cert)
464 {
465 OSStatus status;
466 SecCmsIssuerAndSN *certIssuerAndSN;
467 CSSM_CL_HANDLE clHandle;
468 CSSM_DATA_PTR serialNumber = 0;
469 CSSM_DATA_PTR issuer = 0;
470 CSSM_DATA certData = {};
471 CSSM_HANDLE resultsHandle = 0;
472 uint32 numberOfFields = 0;
473 CSSM_RETURN result;
474 void *mark;
475
476 mark = PORT_ArenaMark(pl);
477
478 if (!InitializeCL (&clHandle))
479 goto loser;
480 status = SecCertificateGetData(cert, &certData);
481 if (status)
482 goto loser;
483
484 /* Get the issuer from the cert. */
485 result = CSSM_CL_CertGetFirstFieldValue(clHandle, &certData, &OID_X509V1IssuerNameStd, &resultsHandle, &numberOfFields, &issuer);
486
487 /* @@@ Remove this once we are sure CSSMOID_X509V1IssuerNameStd is working. */
488 /* Fall back on old normalized issuer if the new oid isn't supported yet. */
489 if (result)
490 result = CSSM_CL_CertGetFirstFieldValue(clHandle, &certData, &CSSMOID_X509V1IssuerName, &resultsHandle, &numberOfFields, &issuer);
491
492 if (result || numberOfFields < 1)
493 goto loser;
494 result = CSSM_CL_CertAbortQuery(clHandle, resultsHandle);
495 if (result)
496 goto loser;
497
498
499 /* Get the serialNumber from the cert. */
500 result = CSSM_CL_CertGetFirstFieldValue(clHandle, &certData, &CSSMOID_X509V1SerialNumber, &resultsHandle, &numberOfFields, &serialNumber);
501 if (result || numberOfFields < 1)
502 goto loser;
503 result = CSSM_CL_CertAbortQuery(clHandle, resultsHandle);
504 if (result)
505 goto loser;
506
507 /* Allocate the SecCmsIssuerAndSN struct. */
508 certIssuerAndSN = (SecCmsIssuerAndSN *)PORT_ArenaZAlloc (pl, sizeof(SecCmsIssuerAndSN));
509 if (certIssuerAndSN == NULL)
510 goto loser;
511
512 /* Copy the issuer. */
513 certIssuerAndSN->derIssuer.Data = (uint8 *) PORT_ArenaAlloc(pl, issuer->Length);
514 if (!certIssuerAndSN->derIssuer.Data)
515 goto loser;
516 PORT_Memcpy(certIssuerAndSN->derIssuer.Data, issuer->Data, issuer->Length);
517 certIssuerAndSN->derIssuer.Length = issuer->Length;
518
519 /* Copy the serialNumber. */
520 certIssuerAndSN->serialNumber.Data = (uint8 *) PORT_ArenaAlloc(pl, serialNumber->Length);
521 if (!certIssuerAndSN->serialNumber.Data)
522 goto loser;
523 PORT_Memcpy(certIssuerAndSN->serialNumber.Data, serialNumber->Data, serialNumber->Length);
524 certIssuerAndSN->serialNumber.Length = serialNumber->Length;
525
526 PORT_ArenaUnmark(pl, mark);
527
528 CSSM_CL_FreeFieldValue(clHandle, &CSSMOID_X509V1SerialNumber, serialNumber);
529 CSSM_CL_FreeFieldValue(clHandle, &OID_X509V1IssuerNameStd, issuer);
530
531 CloseCL (clHandle);
532
533 return certIssuerAndSN;
534
535 loser:
536 PORT_ArenaRelease(pl, mark);
537
538 if (serialNumber)
539 CSSM_CL_FreeFieldValue(clHandle, &CSSMOID_X509V1SerialNumber, serialNumber);
540 if (issuer)
541 CSSM_CL_FreeFieldValue(clHandle, &OID_X509V1IssuerNameStd, issuer);
542
543 CloseCL (clHandle);
544
545 PORT_SetError(SEC_INTERNAL_ONLY);
546 return NULL;
547 }
548
549 // import a collection of certs into the temporary or permanent cert database
550 SECStatus CERT_ImportCerts(SecKeychainRef keychain, SECCertUsage usage, unsigned int ncerts,
551 SECItem **derCerts, SecCertificateRef **retCerts, Boolean keepCerts, Boolean caOnly, char *nickname)
552 {
553 OSStatus rv = SECFailure;
554 SecCertificateRef cert;
555 unsigned int ci;
556
557 // @@@ Do something with caOnly and nickname
558 if (caOnly || nickname)
559 abort();
560
561 for (ci = 0; ci < ncerts; ++ci)
562 {
563 rv = SecCertificateCreateFromData(derCerts[ci], CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, &cert);
564 if (rv)
565 break;
566 if (keepCerts)
567 {
568 rv = SecCertificateAddToKeychain(cert, keychain);
569 if (rv)
570 {
571 if (rv == errKCDuplicateItem)
572 rv = errSecSuccess;
573 else
574 {
575 CFRelease(cert);
576 break;
577 }
578 }
579 }
580
581 if (retCerts)
582 {
583 // @@@ not yet
584 abort();
585 }
586 else
587 CFRelease(cert);
588 }
589
590 return rv;
591 }
592
593 SECStatus CERT_SaveSMimeProfile(SecCertificateRef cert, SECItem *emailProfile,SECItem *profileTime)
594 {
595 fprintf(stderr, "WARNING: CERT_SaveSMimeProfile unimplemented\n");
596 return SECSuccess;
597 }
598
599 // Check the hostname to make sure that it matches the shexp that
600 // is given in the common name of the certificate.
601 SECStatus CERT_VerifyCertName(SecCertificateRef cert, const char *hostname)
602 {
603 fprintf(stderr, "WARNING: CERT_VerifyCertName unimplemented\n");
604 return SECSuccess;
605 }
606
607 /*
608 ** OLD OBSOLETE FUNCTIONS with enum SECCertUsage - DO NOT USE FOR NEW CODE
609 ** verify a certificate by checking validity times against a certain time,
610 ** that we trust the issuer, and that the signature on the certificate is
611 ** valid.
612 ** "cert" the certificate to verify
613 ** "checkSig" only check signatures if true
614 */
615 SECStatus
616 CERT_VerifyCert(SecKeychainRef keychainOrArray, SecCertificateRef cert,
617 CFTypeRef policies, CFAbsoluteTime stime, SecTrustRef *trustRef)
618 {
619 CFArrayRef certificates;
620 const void *certs = cert;
621 SecTrustRef trust = NULL;
622 OSStatus rv;
623
624 certificates = CFArrayCreate(NULL, &certs, 1, &kCFTypeArrayCallBacks);
625 rv = SecTrustCreateWithCertificates(certificates, policies, &trust);
626 CFRelease(certificates);
627 if (rv)
628 goto loser;
629
630 rv = SecTrustSetKeychains(trust, keychainOrArray);
631 if (rv)
632 goto loser;
633
634 CFDateRef verifyDate = CFDateCreate(NULL, stime);
635 rv = SecTrustSetVerifyDate(trust, verifyDate);
636 CFRelease(verifyDate);
637 if (rv)
638 goto loser;
639
640 if (trustRef)
641 {
642 *trustRef = trust;
643 }
644 else
645 {
646 SecTrustResultType result;
647 /* The caller doesn't want a SecTrust object, so let's evaluate it for them. */
648 rv = SecTrustEvaluate(trust, &result);
649 if (rv)
650 goto loser;
651
652 switch (result)
653 {
654 case kSecTrustResultProceed:
655 case kSecTrustResultUnspecified:
656 /* TP Verification succeeded and there was either a UserTurst entry
657 telling us to procceed, or no user trust setting was specified. */
658 CFRelease(trust);
659 break;
660 default:
661 PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
662 rv = SECFailure;
663 goto loser;
664 break;
665 }
666 }
667
668 return SECSuccess;
669 loser:
670 if (trust)
671 CFRelease(trust);
672
673 return rv;
674 }
675
676 CFTypeRef
677 CERT_PolicyForCertUsage(SECCertUsage certUsage)
678 {
679 SecPolicySearchRef search;
680 SecPolicyRef policy = NULL;
681 const CSSM_OID *policyOID;
682 OSStatus rv;
683
684 switch (certUsage)
685 {
686 case certUsageSSLServerWithStepUp:
687 case certUsageSSLCA:
688 case certUsageVerifyCA:
689 case certUsageAnyCA:
690 goto loser;
691 break;
692 case certUsageSSLClient:
693 case certUsageSSLServer:
694 policyOID = &CSSMOID_APPLE_TP_SSL;
695 break;
696 case certUsageUserCertImport:
697 policyOID = &CSSMOID_APPLE_TP_CSR_GEN;
698 break;
699 case certUsageStatusResponder:
700 policyOID = &CSSMOID_APPLE_TP_REVOCATION_OCSP;
701 break;
702 case certUsageObjectSigner:
703 case certUsageProtectedObjectSigner:
704 policyOID = &CSSMOID_APPLE_ISIGN;
705 break;
706 case certUsageEmailSigner:
707 case certUsageEmailRecipient:
708 policyOID = &CSSMOID_APPLE_X509_BASIC;
709 break;
710 default:
711 goto loser;
712 }
713 rv = SecPolicySearchCreate(CSSM_CERT_X_509v3, policyOID, NULL, &search);
714 if (rv)
715 goto loser;
716
717 rv = SecPolicySearchCopyNext(search, &policy);
718 if (rv)
719 goto loser;
720
721 loser:
722 CFRelease(search);
723 return policy;
724 }