]> git.saurik.com Git - apple/security.git/blob - libsecurity_smime/lib/cert.c
Security-57337.20.44.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
229 if (!cert)
230 goto loser;
231
232 status = SecPolicySearchCreate(CSSM_CERT_X_509v3, &CSSMOID_APPLE_X509_BASIC, NULL, &searchRef);
233 if (status)
234 goto loser;
235 status = SecPolicySearchCopyNext(searchRef, &policy);
236 if (status)
237 goto loser;
238
239 wrappedCert = CERT_CertListFromCert(cert);
240 status = SecTrustCreateWithCertificates(wrappedCert, policy, &trust);
241 if (status)
242 goto loser;
243
244 status = SecTrustEvaluate(trust, NULL);
245 if (status)
246 goto loser;
247
248 status = SecTrustGetResult(trust, NULL, &certChain, &statusChain);
249 if (status)
250 goto loser;
251
252 /* We don't drop the root if there is only 1 (self signed) certificate in the chain. */
253 if (!includeRoot && CFArrayGetCount(certChain) > 1)
254 {
255 CFMutableArrayRef subChain = CFArrayCreateMutableCopy(NULL, 0, certChain);
256 CFRelease(certChain);
257 certChain = subChain;
258 if (subChain)
259 CFArrayRemoveValueAtIndex(subChain, CFArrayGetCount(subChain) - 1);
260 }
261
262 loser:
263 if (searchRef)
264 CFRelease(searchRef);
265 if (policy)
266 CFRelease(policy);
267 if (wrappedCert)
268 CFRelease(wrappedCert);
269 if (trust)
270 CFRelease(trust);
271 if (certChain && status)
272 {
273 CFRelease(certChain);
274 certChain = NULL;
275 }
276
277 return certChain;
278 }
279
280 CFArrayRef CERT_CertListFromCert(SecCertificateRef cert)
281 {
282 const void *value = cert;
283 return cert ? CFArrayCreate(NULL, &value, 1, &kCFTypeArrayCallBacks) : NULL;
284 }
285
286 CFArrayRef CERT_DupCertList(CFArrayRef oldList)
287 {
288 CFRetain(oldList);
289 return oldList;
290 }
291
292 // Extract a public key object from a SubjectPublicKeyInfo
293 SecPublicKeyRef CERT_ExtractPublicKey(SecCertificateRef cert)
294 {
295 SecPublicKeyRef keyRef = NULL;
296 SecCertificateCopyPublicKey(cert,&keyRef);
297 return keyRef;
298 }
299
300 SECStatus CERT_CheckCertUsage (SecCertificateRef cert,unsigned char usage)
301 {
302 // abort();
303 // @@@ It's all good, it's ok.
304 return SECSuccess;
305 }
306
307 // Find a certificate in the database by a email address
308 // "emailAddr" is the email address to look up
309 SecCertificateRef CERT_FindCertByEmailAddr(SecKeychainRef keychainOrArray, char *emailAddr)
310 {
311 abort();
312 return NULL;
313 }
314
315 // Find a certificate in the database by a DER encoded certificate
316 // "derCert" is the DER encoded certificate
317 SecCertificateRef CERT_FindCertByDERCert(SecKeychainRef keychainOrArray, const SECItem *derCert)
318 {
319 // @@@ Technically this should look though keychainOrArray for a cert matching this one I guess.
320 SecCertificateRef cert = NULL;
321 OSStatus rv;
322
323 rv = SecCertificateCreateFromData(derCert, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, &cert);
324 if (rv && cert)
325 {
326 PORT_SetError(SEC_ERROR_NO_EMAIL_CERT);
327 CFRelease(cert);
328 cert = NULL;
329 }
330
331 return cert;
332 }
333
334 // Generate a certificate key from the issuer and serialnumber, then look it up in the database.
335 // Return the cert if found. "issuerAndSN" is the issuer and serial number to look for
336 SecCertificateRef CERT_FindCertByIssuerAndSN (CFTypeRef keychainOrArray, const SecCmsIssuerAndSN *issuerAndSN)
337 {
338 SecCertificateRef certificate;
339 OSStatus status = SecCertificateFindByIssuerAndSN(keychainOrArray, &issuerAndSN->derIssuer,
340 &issuerAndSN->serialNumber, &certificate);
341 if (status)
342 {
343 PORT_SetError(SEC_ERROR_NO_EMAIL_CERT);
344 certificate = NULL;
345 }
346
347 return certificate;
348 }
349
350 SecCertificateRef CERT_FindCertBySubjectKeyID (CFTypeRef keychainOrArray, const SecAsn1Item *subjKeyID)
351 {
352 SecCertificateRef certificate;
353 OSStatus status = SecCertificateFindBySubjectKeyID(keychainOrArray,subjKeyID,&certificate);
354 if (status)
355 {
356 PORT_SetError(SEC_ERROR_NO_EMAIL_CERT);
357 certificate = NULL;
358 }
359
360 return certificate;
361 }
362
363 static SecIdentityRef
364 CERT_FindIdentityByCertificate (CFTypeRef keychainOrArray, SecCertificateRef certificate)
365 {
366 SecIdentityRef identity = NULL;
367 SecIdentityCreateWithCertificate(keychainOrArray, certificate, &identity);
368 if (!identity)
369 PORT_SetError(SEC_ERROR_NOT_A_RECIPIENT);
370
371 return identity;
372 }
373
374 SecIdentityRef
375 CERT_FindIdentityByIssuerAndSN (CFTypeRef keychainOrArray, const SecCmsIssuerAndSN *issuerAndSN)
376 {
377 SecCertificateRef certificate = CERT_FindCertByIssuerAndSN(keychainOrArray, issuerAndSN);
378 if (!certificate)
379 return NULL;
380
381 return CERT_FindIdentityByCertificate(keychainOrArray, certificate);
382 }
383
384 SecIdentityRef
385 CERT_FindIdentityBySubjectKeyID (CFTypeRef keychainOrArray, const SECItem *subjKeyID)
386 {
387 SecCertificateRef certificate = CERT_FindCertBySubjectKeyID(keychainOrArray, subjKeyID);
388 if (!certificate)
389 return NULL;
390
391 return CERT_FindIdentityByCertificate(keychainOrArray, certificate);
392 }
393
394 // find the smime symmetric capabilities profile for a given cert
395 SECItem *CERT_FindSMimeProfile(SecCertificateRef cert)
396 {
397 return NULL;
398 }
399
400 // Return the decoded value of the subjectKeyID extension. The caller should
401 // free up the storage allocated in retItem->data.
402 SECStatus CERT_FindSubjectKeyIDExtension (SecCertificateRef cert,SECItem *retItem)
403 {
404 fprintf(stderr, "WARNING: CERT_FindSubjectKeyIDExtension unimplemented\n");
405 return SECFailure;
406 }
407
408 static void * appMalloc (uint32 size, void *allocRef) {
409 return (malloc (size));
410 }
411
412 static void appFree (void *mem_ptr, void *allocRef) {
413 free (mem_ptr);
414 return;
415 }
416
417 static void * appRealloc (void *ptr, uint32 size, void *allocRef) {
418 return (realloc (ptr, size));
419 }
420
421 static void * appCalloc (uint32 num, uint32 size, void *allocRef) {
422 return (calloc (num, size));
423 }
424
425 static CSSM_API_MEMORY_FUNCS memFuncs = {
426 appMalloc,
427 appFree,
428 appRealloc,
429 appCalloc,
430 NULL
431 };
432
433 // return a valid CL handle
434 static int InitializeCL (CSSM_CL_HANDLE *clHandle)
435 {
436 CSSM_VERSION version = {2, 0};
437
438 // load the module
439 CSSM_RETURN result = CSSM_ModuleLoad (&gGuidAppleX509CL, CSSM_KEY_HIERARCHY_NONE, NULL, NULL);
440 if (result != 0)
441 {
442 return false;
443 }
444
445 result = CSSM_ModuleAttach (&gGuidAppleX509CL, &version, &memFuncs, 0, CSSM_SERVICE_CL, 0, 0, NULL, 0, NULL, clHandle);
446 if (result != 0)
447 {
448 return false;
449 }
450
451 return true;
452 }
453
454 // cleanup a CL handle
455 static void CloseCL (CSSM_CL_HANDLE clHandle)
456 {
457 CSSM_ModuleDetach (clHandle);
458 CSSM_ModuleUnload (&gGuidAppleX509CL, NULL, NULL);
459 }
460
461 // Extract the issuer and serial number from a certificate
462 SecCmsIssuerAndSN *CERT_GetCertIssuerAndSN(PRArenaPool *pl, SecCertificateRef cert)
463 {
464 OSStatus status;
465 SecCmsIssuerAndSN *certIssuerAndSN;
466 CSSM_CL_HANDLE clHandle;
467 CSSM_DATA_PTR serialNumber = 0;
468 CSSM_DATA_PTR issuer = 0;
469 CSSM_DATA certData = {};
470 CSSM_HANDLE resultsHandle = 0;
471 uint32 numberOfFields = 0;
472 CSSM_RETURN result;
473 void *mark;
474
475 mark = PORT_ArenaMark(pl);
476
477 if (!InitializeCL (&clHandle))
478 goto loser;
479 status = SecCertificateGetData(cert, &certData);
480 if (status)
481 goto loser;
482
483 /* Get the issuer from the cert. */
484 result = CSSM_CL_CertGetFirstFieldValue(clHandle, &certData, &OID_X509V1IssuerNameStd, &resultsHandle, &numberOfFields, &issuer);
485
486 /* @@@ Remove this once we are sure CSSMOID_X509V1IssuerNameStd is working. */
487 /* Fall back on old normalized issuer if the new oid isn't supported yet. */
488 if (result)
489 result = CSSM_CL_CertGetFirstFieldValue(clHandle, &certData, &CSSMOID_X509V1IssuerName, &resultsHandle, &numberOfFields, &issuer);
490
491 if (result || numberOfFields < 1)
492 goto loser;
493 result = CSSM_CL_CertAbortQuery(clHandle, resultsHandle);
494 if (result)
495 goto loser;
496
497
498 /* Get the serialNumber from the cert. */
499 result = CSSM_CL_CertGetFirstFieldValue(clHandle, &certData, &CSSMOID_X509V1SerialNumber, &resultsHandle, &numberOfFields, &serialNumber);
500 if (result || numberOfFields < 1)
501 goto loser;
502 result = CSSM_CL_CertAbortQuery(clHandle, resultsHandle);
503 if (result)
504 goto loser;
505
506 /* Allocate the SecCmsIssuerAndSN struct. */
507 certIssuerAndSN = (SecCmsIssuerAndSN *)PORT_ArenaZAlloc (pl, sizeof(SecCmsIssuerAndSN));
508 if (certIssuerAndSN == NULL)
509 goto loser;
510
511 /* Copy the issuer. */
512 certIssuerAndSN->derIssuer.Data = (uint8 *) PORT_ArenaAlloc(pl, issuer->Length);
513 if (!certIssuerAndSN->derIssuer.Data)
514 goto loser;
515 PORT_Memcpy(certIssuerAndSN->derIssuer.Data, issuer->Data, issuer->Length);
516 certIssuerAndSN->derIssuer.Length = issuer->Length;
517
518 /* Copy the serialNumber. */
519 certIssuerAndSN->serialNumber.Data = (uint8 *) PORT_ArenaAlloc(pl, serialNumber->Length);
520 if (!certIssuerAndSN->serialNumber.Data)
521 goto loser;
522 PORT_Memcpy(certIssuerAndSN->serialNumber.Data, serialNumber->Data, serialNumber->Length);
523 certIssuerAndSN->serialNumber.Length = serialNumber->Length;
524
525 PORT_ArenaUnmark(pl, mark);
526
527 CSSM_CL_FreeFieldValue(clHandle, &CSSMOID_X509V1SerialNumber, serialNumber);
528 CSSM_CL_FreeFieldValue(clHandle, &OID_X509V1IssuerNameStd, issuer);
529
530 CloseCL (clHandle);
531
532 return certIssuerAndSN;
533
534 loser:
535 PORT_ArenaRelease(pl, mark);
536
537 if (serialNumber)
538 CSSM_CL_FreeFieldValue(clHandle, &CSSMOID_X509V1SerialNumber, serialNumber);
539 if (issuer)
540 CSSM_CL_FreeFieldValue(clHandle, &OID_X509V1IssuerNameStd, issuer);
541
542 CloseCL (clHandle);
543
544 PORT_SetError(SEC_INTERNAL_ONLY);
545 return NULL;
546 }
547
548 // import a collection of certs into the temporary or permanent cert database
549 SECStatus CERT_ImportCerts(SecKeychainRef keychain, SECCertUsage usage, unsigned int ncerts,
550 SECItem **derCerts, SecCertificateRef **retCerts, Boolean keepCerts, Boolean caOnly, char *nickname)
551 {
552 OSStatus rv = SECFailure;
553 SecCertificateRef cert;
554 unsigned int ci;
555
556 // @@@ Do something with caOnly and nickname
557 if (caOnly || nickname)
558 abort();
559
560 for (ci = 0; ci < ncerts; ++ci)
561 {
562 rv = SecCertificateCreateFromData(derCerts[ci], CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER, &cert);
563 if (rv)
564 break;
565 if (keepCerts)
566 {
567 rv = SecCertificateAddToKeychain(cert, keychain);
568 if (rv)
569 {
570 if (rv == errKCDuplicateItem)
571 rv = errSecSuccess;
572 else
573 {
574 CFRelease(cert);
575 break;
576 }
577 }
578 }
579
580 if (retCerts)
581 {
582 // @@@ not yet
583 abort();
584 }
585 else
586 CFRelease(cert);
587 }
588
589 return rv;
590 }
591
592 SECStatus CERT_SaveSMimeProfile(SecCertificateRef cert, SECItem *emailProfile,SECItem *profileTime)
593 {
594 fprintf(stderr, "WARNING: CERT_SaveSMimeProfile unimplemented\n");
595 return SECSuccess;
596 }
597
598 // Check the hostname to make sure that it matches the shexp that
599 // is given in the common name of the certificate.
600 SECStatus CERT_VerifyCertName(SecCertificateRef cert, const char *hostname)
601 {
602 fprintf(stderr, "WARNING: CERT_VerifyCertName unimplemented\n");
603 return SECSuccess;
604 }
605
606 /*
607 ** OLD OBSOLETE FUNCTIONS with enum SECCertUsage - DO NOT USE FOR NEW CODE
608 ** verify a certificate by checking validity times against a certain time,
609 ** that we trust the issuer, and that the signature on the certificate is
610 ** valid.
611 ** "cert" the certificate to verify
612 ** "checkSig" only check signatures if true
613 */
614 SECStatus
615 CERT_VerifyCert(SecKeychainRef keychainOrArray, SecCertificateRef cert,
616 CFTypeRef policies, CFAbsoluteTime stime, SecTrustRef *trustRef)
617 {
618 CFArrayRef certificates;
619 const void *certs = cert;
620 SecTrustRef trust = NULL;
621 OSStatus rv;
622
623 certificates = CFArrayCreate(NULL, &certs, 1, &kCFTypeArrayCallBacks);
624 rv = SecTrustCreateWithCertificates(certificates, policies, &trust);
625 CFRelease(certificates);
626 if (rv)
627 goto loser;
628
629 rv = SecTrustSetKeychains(trust, keychainOrArray);
630 if (rv)
631 goto loser;
632
633 CFDateRef verifyDate = CFDateCreate(NULL, stime);
634 rv = SecTrustSetVerifyDate(trust, verifyDate);
635 CFRelease(verifyDate);
636 if (rv)
637 goto loser;
638
639 if (trustRef)
640 {
641 *trustRef = trust;
642 }
643 else
644 {
645 SecTrustResultType result;
646 /* The caller doesn't want a SecTrust object, so let's evaluate it for them. */
647 rv = SecTrustEvaluate(trust, &result);
648 if (rv)
649 goto loser;
650
651 switch (result)
652 {
653 case kSecTrustResultProceed:
654 case kSecTrustResultUnspecified:
655 /* TP Verification succeeded and there was either a UserTurst entry
656 telling us to procceed, or no user trust setting was specified. */
657 CFRelease(trust);
658 break;
659 default:
660 PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
661 rv = SECFailure;
662 goto loser;
663 break;
664 }
665 }
666
667 return SECSuccess;
668 loser:
669 if (trust)
670 CFRelease(trust);
671
672 return rv;
673 }
674
675 CFTypeRef
676 CERT_PolicyForCertUsage(SECCertUsage certUsage)
677 {
678 SecPolicySearchRef search;
679 SecPolicyRef policy = NULL;
680 const CSSM_OID *policyOID;
681 OSStatus rv;
682
683 switch (certUsage)
684 {
685 case certUsageSSLServerWithStepUp:
686 case certUsageSSLCA:
687 case certUsageVerifyCA:
688 case certUsageAnyCA:
689 goto loser;
690 break;
691 case certUsageSSLClient:
692 case certUsageSSLServer:
693 policyOID = &CSSMOID_APPLE_TP_SSL;
694 break;
695 case certUsageUserCertImport:
696 policyOID = &CSSMOID_APPLE_TP_CSR_GEN;
697 break;
698 case certUsageStatusResponder:
699 policyOID = &CSSMOID_APPLE_TP_REVOCATION_OCSP;
700 break;
701 case certUsageObjectSigner:
702 case certUsageProtectedObjectSigner:
703 policyOID = &CSSMOID_APPLE_ISIGN;
704 break;
705 case certUsageEmailSigner:
706 case certUsageEmailRecipient:
707 policyOID = &CSSMOID_APPLE_X509_BASIC;
708 break;
709 default:
710 goto loser;
711 }
712 rv = SecPolicySearchCreate(CSSM_CERT_X_509v3, policyOID, NULL, &search);
713 if (rv)
714 goto loser;
715
716 rv = SecPolicySearchCopyNext(search, &policy);
717 if (rv)
718 goto loser;
719
720 loser:
721 CFRelease(search);
722 return policy;
723 }