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