]> git.saurik.com Git - apple/security.git/blame - libsecurity_smime/lib/cert.c
Security-58286.70.7.tar.gz
[apple/security.git] / libsecurity_smime / lib / cert.c
CommitLineData
b1ab9ed8
A
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"
b1ab9ed8
A
12#include <security_asn1/secerr.h>
13#include <Security/SecKeychain.h>
14#include <Security/SecKeychainItem.h>
15#include <Security/SecKeychainSearch.h>
b1ab9ed8
A
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 */
d8f41ccd 26#include <Security/SecBase.h>
b1ab9ed8
A
27
28/* @@@ Remove this once it's back in the appropriate header. */
29static const uint8 X509V1IssuerNameStd[] = {INTEL_X509V3_CERT_R08, 23};
30static 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 */
37static void
38CERT_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 */
90void
91CERT_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
117SecCertificateRef CERT_FindCertByNicknameOrEmailAddr(SecKeychainRef keychainOrArray, char *name)
118{
119 SecCertificateRef certificate;
120 OSStatus status=SecCertificateFindByEmail(keychainOrArray,name,&certificate);
d8f41ccd 121 return status==errSecSuccess?certificate:NULL;
b1ab9ed8
A
122}
123
124SecPublicKeyRef SECKEY_CopyPublicKey(SecPublicKeyRef pubKey)
125{
126 CFRetain(pubKey);
127 return pubKey;
128}
129
130void SECKEY_DestroyPublicKey(SecPublicKeyRef pubKey)
131{
132 CFRelease(pubKey);
133}
134
135SecPublicKeyRef SECKEY_CopyPrivateKey(SecPublicKeyRef privKey)
136{
137 CFRetain(privKey);
138 return privKey;
139}
140
141void SECKEY_DestroyPrivateKey(SecPublicKeyRef privKey)
142{
143 CFRelease(privKey);
144}
145
146void CERT_DestroyCertificate(SecCertificateRef cert)
147{
148 CFRelease(cert);
149}
150
151SecCertificateRef CERT_DupCertificate(SecCertificateRef cert)
152{
153 CFRetain(cert);
154 return cert;
155}
156
157SecIdentityRef 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
171SecCertificateRef 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
5c19dc3a
A
182 attrs[0].tag = kSecLabelItemAttr;
183 attrs[0].length = strlen(nickname)+1;
184 attrs[0].data = nickname;
b1ab9ed8 185#else
5c19dc3a
A
186 attrs[0].tag = kSecSerialNumberItemAttr;
187 attrs[0].length = strlen(serialNumber)+1;
188 attrs[0].data = (uint8 *)serialNumber;
b1ab9ed8
A
189#endif
190 SecKeychainAttributeList attrList = { 0, attrs };
191 // 12 34 56 78
192 status = SecKeychainSearchCreateFromAttributes(keychainOrArray,itemClass,&attrList,&searchRef);
193 if (status)
194 {
d8f41ccd 195 printf("CERT_FindUserCertByUsage: SecKeychainSearchCreateFromAttributes:%ld",status);
b1ab9ed8
A
196 return NULL;
197 }
198 status = SecKeychainSearchCopyNext(searchRef,&itemRef);
199 if (status)
d8f41ccd 200 printf("CERT_FindUserCertByUsage: SecKeychainSearchCopyNext:%ld",status);
b1ab9ed8
A
201 CFRelease(searchRef);
202 return (SecCertificateRef)itemRef;
203}
204
205/*
206startNewClass(X509Certificate)
207CertType, kSecCertTypeItemAttr, "CertType", 0, NULL, UINT32)
208CertEncoding, kSecCertEncodingItemAttr, "CertEncoding", 0, NULL, UINT32)
209PrintName, kSecLabelItemAttr, "PrintName", 0, NULL, BLOB)
d8f41ccd 210Alias, kSecAliasItemAttr, "Alias", 0, NULL, BLOB)
b1ab9ed8
A
211Subject, kSecSubjectItemAttr, "Subject", 0, NULL, BLOB)
212Issuer, kSecIssuerItemAttr, "Issuer", 0, NULL, BLOB)
213SerialNumber, kSecSerialNumberItemAttr, "SerialNumber", 0, NULL, BLOB)
214SubjectKeyIdentifier, kSecSubjectKeyIdentifierItemAttr, "SubjectKeyIdentifier", 0, NULL, BLOB)
215PublicKeyHash, kSecPublicKeyHashItemAttr, "PublicKeyHash", 0, NULL, BLOB)
216endNewClass()
217*/
218
219CFArrayRef 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;
b1ab9ed8
A
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
b1ab9ed8
A
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
262loser:
263 if (searchRef)
264 CFRelease(searchRef);
265 if (policy)
266 CFRelease(policy);
267 if (wrappedCert)
268 CFRelease(wrappedCert);
269 if (trust)
270 CFRelease(trust);
b1ab9ed8
A
271 if (certChain && status)
272 {
273 CFRelease(certChain);
274 certChain = NULL;
275 }
276
277 return certChain;
278}
279
280CFArrayRef CERT_CertListFromCert(SecCertificateRef cert)
281{
282 const void *value = cert;
283 return cert ? CFArrayCreate(NULL, &value, 1, &kCFTypeArrayCallBacks) : NULL;
284}
285
286CFArrayRef CERT_DupCertList(CFArrayRef oldList)
287{
288 CFRetain(oldList);
289 return oldList;
290}
291
292// Extract a public key object from a SubjectPublicKeyInfo
293SecPublicKeyRef CERT_ExtractPublicKey(SecCertificateRef cert)
294{
295 SecPublicKeyRef keyRef = NULL;
296 SecCertificateCopyPublicKey(cert,&keyRef);
297 return keyRef;
298}
299
300SECStatus 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
309SecCertificateRef 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
317SecCertificateRef 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
b1ab9ed8
A
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
d8f41ccd 336SecCertificateRef CERT_FindCertByIssuerAndSN (CFTypeRef keychainOrArray, const SecCmsIssuerAndSN *issuerAndSN)
b1ab9ed8
A
337{
338 SecCertificateRef certificate;
b1ab9ed8
A
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
d8f41ccd 350SecCertificateRef CERT_FindCertBySubjectKeyID (CFTypeRef keychainOrArray, const SecAsn1Item *subjKeyID)
b1ab9ed8
A
351{
352 SecCertificateRef certificate;
b1ab9ed8
A
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
363static SecIdentityRef
364CERT_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
374SecIdentityRef
375CERT_FindIdentityByIssuerAndSN (CFTypeRef keychainOrArray, const SecCmsIssuerAndSN *issuerAndSN)
376{
d8f41ccd 377 SecCertificateRef certificate = CERT_FindCertByIssuerAndSN(keychainOrArray, issuerAndSN);
b1ab9ed8
A
378 if (!certificate)
379 return NULL;
380
381 return CERT_FindIdentityByCertificate(keychainOrArray, certificate);
382}
383
384SecIdentityRef
385CERT_FindIdentityBySubjectKeyID (CFTypeRef keychainOrArray, const SECItem *subjKeyID)
386{
d8f41ccd 387 SecCertificateRef certificate = CERT_FindCertBySubjectKeyID(keychainOrArray, subjKeyID);
b1ab9ed8
A
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
395SECItem *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.
d8f41ccd
A
402SECStatus CERT_FindSubjectKeyIDExtension (SecCertificateRef cert,SECItem *retItem)
403{
404 fprintf(stderr, "WARNING: CERT_FindSubjectKeyIDExtension unimplemented\n");
405 return SECFailure;
406}
407
408static void * appMalloc (uint32 size, void *allocRef) {
409 return (malloc (size));
410}
411
412static void appFree (void *mem_ptr, void *allocRef) {
413 free (mem_ptr);
414 return;
415}
416
417static void * appRealloc (void *ptr, uint32 size, void *allocRef) {
418 return (realloc (ptr, size));
419}
420
421static void * appCalloc (uint32 num, uint32 size, void *allocRef) {
422 return (calloc (num, size));
423}
424
425static CSSM_API_MEMORY_FUNCS memFuncs = {
426 appMalloc,
427 appFree,
428 appRealloc,
429 appCalloc,
430 NULL
431 };
432
433// return a valid CL handle
434static int InitializeCL (CSSM_CL_HANDLE *clHandle)
b1ab9ed8 435{
d8f41ccd
A
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 }
b1ab9ed8 444
d8f41ccd
A
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;
b1ab9ed8 449 }
d8f41ccd
A
450
451 return true;
452}
453
454// cleanup a CL handle
455static void CloseCL (CSSM_CL_HANDLE clHandle)
456{
457 CSSM_ModuleDetach (clHandle);
458 CSSM_ModuleUnload (&gGuidAppleX509CL, NULL, NULL);
b1ab9ed8
A
459}
460
461// Extract the issuer and serial number from a certificate
462SecCmsIssuerAndSN *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
d8f41ccd 477 if (!InitializeCL (&clHandle))
b1ab9ed8
A
478 goto loser;
479 status = SecCertificateGetData(cert, &certData);
480 if (status)
481 goto loser;
482
483 /* Get the issuer from the cert. */
d8f41ccd
A
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);
b1ab9ed8
A
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. */
d8f41ccd 499 result = CSSM_CL_CertGetFirstFieldValue(clHandle, &certData, &CSSMOID_X509V1SerialNumber, &resultsHandle, &numberOfFields, &serialNumber);
b1ab9ed8
A
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
d8f41ccd
A
530 CloseCL (clHandle);
531
b1ab9ed8
A
532 return certIssuerAndSN;
533
534loser:
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
d8f41ccd
A
542 CloseCL (clHandle);
543
b1ab9ed8
A
544 PORT_SetError(SEC_INTERNAL_ONLY);
545 return NULL;
546}
547
548// import a collection of certs into the temporary or permanent cert database
549SECStatus 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)
d8f41ccd 571 rv = errSecSuccess;
b1ab9ed8
A
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
592SECStatus 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.
600SECStatus 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*/
614SECStatus
615CERT_VerifyCert(SecKeychainRef keychainOrArray, SecCertificateRef cert,
b1ab9ed8
A
616 CFTypeRef policies, CFAbsoluteTime stime, SecTrustRef *trustRef)
617{
d8f41ccd
A
618 CFArrayRef certificates;
619 const void *certs = cert;
b1ab9ed8
A
620 SecTrustRef trust = NULL;
621 OSStatus rv;
d8f41ccd
A
622
623 certificates = CFArrayCreate(NULL, &certs, 1, &kCFTypeArrayCallBacks);
b1ab9ed8
A
624 rv = SecTrustCreateWithCertificates(certificates, policies, &trust);
625 CFRelease(certificates);
b1ab9ed8
A
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;
668loser:
669 if (trust)
670 CFRelease(trust);
d8f41ccd 671
b1ab9ed8
A
672 return rv;
673}
674
675CFTypeRef
676CERT_PolicyForCertUsage(SECCertUsage certUsage)
677{
d8f41ccd 678 SecPolicySearchRef search;
b1ab9ed8
A
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
720loser:
d8f41ccd 721 CFRelease(search);
b1ab9ed8
A
722 return policy;
723}