2  * Copyright (c) 2003,2011-2012,2014 Apple Inc. All Rights Reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. Please obtain a copy of the License at 
  10  * http://www.opensource.apple.com/apsl/ and read it before using this 
  13  * The Original Code and all software distributed under the License are 
  14  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  15  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  16  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  17  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  18  * Please see the License for the specific language governing rights and 
  19  * limitations under the License. 
  21  * @APPLE_LICENSE_HEADER_END@ 
  29 #include <security_asn1/secerr.h> 
  30 #include <Security/SecKeychain.h> 
  31 #include <Security/SecKeychainItem.h> 
  32 #include <Security/SecKeychainSearch.h> 
  33 #include <Security/SecIdentity.h> 
  34 #include <Security/SecIdentityPriv.h> 
  35 #include <Security/SecIdentitySearch.h> 
  36 #include <Security/SecCertificatePriv.h> 
  37 #include <Security/SecPolicyPriv.h> 
  38 #include <Security/oidsalg.h> 
  39 #include <Security/cssmapi.h> 
  40 #include <Security/oidscert.h> 
  41 #include <Security/oidscert.h> 
  44 /* for errKCDuplicateItem */ 
  45 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h> 
  49 #define dprintf(args...)      fprintf(stderr, args) 
  51 #define dprintf(args...) 
  54 /* @@@ Remove this once it's back in the appropriate header. */ 
  55 static const uint8 X509V1IssuerNameStd
[] = {INTEL_X509V3_CERT_R08
, 23}; 
  56 static const CSSM_OID OID_X509V1IssuerNameStd 
= {INTEL_X509V3_CERT_R08_LENGTH
+1,  (uint8 
*)X509V1IssuerNameStd
}; 
  59  * Normalize a Printable String. Per RFC2459 (4.1.2.4), printable strings are case  
  60  * insensitive and we're supposed to ignore leading and trailing  
  61  * whitespace, and collapse multiple whitespace characters into one.  
  64 CERT_NormalizeString(CSSM_DATA_PTR string
) 
  66     char *pD
, *pCh
, *pEos
; 
  71     pD 
= pCh 
= (char *)string
->Data
; 
  72     pEos 
= pCh 
+ string
->Length 
- 1; 
  74     /* Strip trailing NULL terminators */ 
  78     /* Remove trailing spaces */ 
  82     /* Point to one past last non-space character */ 
  85     /* skip all leading whitespace */ 
  86     while(isspace(*pCh
) && (pCh 
< pEos
)) 
  89     /* Eliminate multiple whitespace and convent to upper case. 
  90      * pCh points to first non-white char. 
  91      * pD still points to start of string. */ 
  98             /* skip 'til next nonwhite */ 
  99             while(isspace(*pCh
) && (pCh 
< pEos
)) 
 104     string
->Length 
= pD 
- (char *)string
->Data
; 
 108  * Normalize an RDN. Per RFC2459 (4.1.2.4), printable strings are case  
 109  * insensitive and we're supposed to ignore leading and trailing  
 110  * whitespace, and collapse multiple whitespace characters into one.  
 112  * Incoming NSS_Name is assumed to be entirely within specifed coder's 
 113  * address space; we'll be munging some of that and possibly replacing 
 114  * some pointers with others allocated from the same space.  
 117 CERT_NormalizeX509NameNSS(NSS_Name 
*nssName
) 
 121     for (rdn 
= *nssName
->rdns
; rdn
; ++rdn
) 
 124         for (attr 
= *rdn
->atvs
; attr
; ++attr
) 
 127                 * attr->value is an ASN_ANY containing an encoded 
 128                 * string. We only normalize Prinatable String types.  
 129                 * If we find one, decode it, normalize it, encode the 
 130                 * result, and put the encoding back in attr->value. 
 131                 * We temporarily "leak" the original string, which only 
 132                 * has a lifetime of the incoming SecNssCoder.  
 134             NSS_TaggedItem 
*attrVal 
= &attr
->value
; 
 135             if(attrVal
->tag 
!= SEC_ASN1_PRINTABLE_STRING
) 
 138             CERT_NormalizeString(&attrVal
->item
); 
 143 SecCertificateRef 
CERT_FindCertByNicknameOrEmailAddr(SecKeychainRef keychainOrArray
, char *name
) 
 145    SecCertificateRef certificate
; 
 146     OSStatus status
=SecCertificateFindByEmail(keychainOrArray
,name
,&certificate
); 
 147     return status
==noErr
?certificate
:NULL
; 
 150 SecPublicKeyRef 
SECKEY_CopyPublicKey(SecPublicKeyRef pubKey
) 
 156 void SECKEY_DestroyPublicKey(SecPublicKeyRef pubKey
) 
 161 SecPublicKeyRef 
SECKEY_CopyPrivateKey(SecPublicKeyRef privKey
) 
 167 void SECKEY_DestroyPrivateKey(SecPublicKeyRef privKey
) 
 172 void CERT_DestroyCertificate(SecCertificateRef cert
) 
 177 SecCertificateRef 
CERT_DupCertificate(SecCertificateRef cert
) 
 183 SecIdentityRef 
CERT_FindIdentityByUsage(SecKeychainRef keychainOrArray
, 
 184                          char *nickname
, SECCertUsage usage
, Boolean validOnly
, void *proto_win
) 
 186     SecIdentityRef identityRef 
= NULL
; 
 187     SecCertificateRef cert 
= CERT_FindCertByNicknameOrEmailAddr(keychainOrArray
, nickname
); 
 191     SecIdentityCreateWithCertificate(keychainOrArray
, cert
, &identityRef
); 
 197 SecCertificateRef 
CERT_FindUserCertByUsage(SecKeychainRef keychainOrArray
, 
 198                          char *nickname
,SECCertUsage usage
,Boolean validOnly
,void *proto_win
) 
 200     SecItemClass itemClass 
= kSecCertificateItemClass
; 
 201     SecKeychainSearchRef searchRef
; 
 202     SecKeychainItemRef itemRef 
= NULL
; 
 204     SecKeychainAttribute attrs
[1]; 
 205     const char *serialNumber 
= "12345678"; 
 206  //   const SecKeychainAttributeList attrList; 
 208     attrs
[0].tag 
= kSecLabelItemAttr
; 
 209     attrs
[0].length 
= strlen(nickname
)+1; 
 210     attrs
[0].data 
= nickname
; 
 212     attrs
[0].tag 
= kSecSerialNumberItemAttr
; 
 213     attrs
[0].length 
= (UInt32
)strlen(serialNumber
)+1; 
 214     attrs
[0].data 
= (uint8 
*)serialNumber
; 
 216     SecKeychainAttributeList attrList 
= { 0, attrs 
}; 
 218         status 
= SecKeychainSearchCreateFromAttributes(keychainOrArray
,itemClass
,&attrList
,&searchRef
); 
 221         printf("CERT_FindUserCertByUsage: SecKeychainSearchCreateFromAttributes:%d",(int)status
); 
 224         status 
= SecKeychainSearchCopyNext(searchRef
,&itemRef
); 
 226         printf("CERT_FindUserCertByUsage: SecKeychainSearchCopyNext:%d",(int)status
); 
 227     CFRelease(searchRef
); 
 228     return (SecCertificateRef
)itemRef
; 
 232 startNewClass(X509Certificate) 
 233 CertType, kSecCertTypeItemAttr, "CertType", 0, NULL, UINT32) 
 234 CertEncoding, kSecCertEncodingItemAttr, "CertEncoding", 0, NULL, UINT32) 
 235 PrintName, kSecLabelItemAttr, "PrintName", 0, NULL, BLOB) 
 236 Alias, kSecAlias, "Alias", 0, NULL, BLOB) 
 237 Subject, kSecSubjectItemAttr, "Subject", 0, NULL, BLOB) 
 238 Issuer, kSecIssuerItemAttr, "Issuer", 0, NULL, BLOB) 
 239 SerialNumber, kSecSerialNumberItemAttr, "SerialNumber", 0, NULL, BLOB) 
 240 SubjectKeyIdentifier, kSecSubjectKeyIdentifierItemAttr, "SubjectKeyIdentifier", 0, NULL, BLOB) 
 241 PublicKeyHash, kSecPublicKeyHashItemAttr, "PublicKeyHash", 0, NULL, BLOB) 
 245 CFArrayRef 
CERT_CertChainFromCert(SecCertificateRef cert
, SECCertUsage usage
, Boolean includeRoot
) 
 247     SecPolicyRef policy 
= NULL
; 
 248     CFArrayRef wrappedCert 
= NULL
; 
 249     SecTrustRef trust 
= NULL
; 
 250     CFMutableArrayRef certs 
= NULL
; 
 256     policy 
= SecPolicyCreateBasicX509(); 
 260     wrappedCert 
= CERT_CertListFromCert(cert
); 
 261     status 
= SecTrustCreateWithCertificates(wrappedCert
, policy
, &trust
); 
 265     /* SecTrustEvaluate will build us the best chain available using its heuristics. 
 266      * We'll ignore the trust result. */ 
 267     status 
= SecTrustEvaluate(trust
, NULL
); 
 270     CFIndex idx
, count 
= SecTrustGetCertificateCount(trust
); 
 272     /* If we weren't able to build a chain to a self-signed cert, warn. */ 
 273     Boolean isSelfSigned 
= false; 
 274     SecCertificateRef lastCert 
= SecTrustGetCertificateAtIndex(trust
, count 
- 1); 
 275     if (lastCert 
&& (0 == SecCertificateIsSelfSigned(lastCert
, &isSelfSigned
)) && !isSelfSigned
) { 
 276         CFStringRef commonName 
= NULL
; 
 277         (void)SecCertificateCopyCommonName(cert
, &commonName
); 
 278         fprintf(stderr
, "Warning: unable to build chain to self-signed root for signer \"%s\"", 
 279                 commonName 
? CFStringGetCStringPtr(commonName
, kCFStringEncodingUTF8
) : ""); 
 280         if (commonName
) { CFRelease(commonName
); } 
 283     /* We don't drop the root if there is only 1 certificate in the chain. */ 
 284     if (!includeRoot 
&& count 
> 1) { count
--; } 
 286     certs 
= CFArrayCreateMutable(kCFAllocatorDefault
, count
, &kCFTypeArrayCallBacks
); 
 287     for(idx 
= 0; idx 
< count
; idx
++) 
 288         CFArrayAppendValue(certs
, SecTrustGetCertificateAtIndex(trust
, idx
)); 
 294         CFRelease(wrappedCert
); 
 306 CFArrayRef 
CERT_CertListFromCert(SecCertificateRef cert
) 
 308     const void *value 
= cert
; 
 309     return cert 
? CFArrayCreate(NULL
, &value
, 1, &kCFTypeArrayCallBacks
) : NULL
; 
 312 CFArrayRef 
CERT_DupCertList(CFArrayRef oldList
) 
 318 // Extract a public key object from a SubjectPublicKeyInfo 
 319 SecPublicKeyRef 
CERT_ExtractPublicKey(SecCertificateRef cert
) 
 321     SecPublicKeyRef keyRef 
= NULL
; 
 322     SecCertificateCopyPublicKey(cert
,&keyRef
); 
 326 SECStatus 
CERT_CheckCertUsage (SecCertificateRef cert
,unsigned char usage
) 
 329     // @@@ It's all good, it's ok. 
 333 // Find a certificate in the database by a email address 
 334 // "emailAddr" is the email address to look up 
 335 SecCertificateRef 
CERT_FindCertByEmailAddr(SecKeychainRef keychainOrArray
, char *emailAddr
) 
 341 // Find a certificate in the database by a DER encoded certificate 
 342 // "derCert" is the DER encoded certificate 
 343 SecCertificateRef 
CERT_FindCertByDERCert(SecKeychainRef keychainOrArray
, const SECItem 
*derCert
) 
 345     // @@@ Technically this should look though keychainOrArray for a cert matching this one I guess. 
 346     SecCertificateRef cert 
= NULL
; 
 349     rv 
= SecCertificateCreateFromData(derCert
, CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
, &cert
); 
 352         PORT_SetError(SEC_ERROR_NO_EMAIL_CERT
); 
 360 static int compareCssmData( 
 364     if((d1 
== NULL
) || (d2 
== NULL
)) { 
 367     if(d1
->Length 
!= d2
->Length
) { 
 370     if(memcmp(d1
->Data
, d2
->Data
, d1
->Length
)) { 
 376 // Generate a certificate key from the issuer and serialnumber, then look it up in the database. 
 377 // Return the cert if found. "issuerAndSN" is the issuer and serial number to look for 
 378 SecCertificateRef 
CERT_FindCertByIssuerAndSN (CFTypeRef keychainOrArray
,  
 379     CSSM_DATA_PTR 
*rawCerts
, CFArrayRef certList
, PRArenaPool 
*pl
, const SecCmsIssuerAndSN 
*issuerAndSN
) 
 381     SecCertificateRef certificate 
= NULL
; 
 382     int numRawCerts 
= SecCmsArrayCount((void **)rawCerts
); 
 387      * First search the rawCerts array. 
 389     for(dex
=0; dex
<numRawCerts
; dex
++) { 
 390         ortn 
= SecCertificateCreateFromData(rawCerts
[dex
],  
 391             CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
, 
 396         SecCmsIssuerAndSN 
*isn 
= CERT_GetCertIssuerAndSN(pl
, certificate
); 
 398             CFRelease(certificate
); 
 401         if(!compareCssmData(&isn
->derIssuer
, &issuerAndSN
->derIssuer
)) { 
 402             CFRelease(certificate
); 
 405         if(!compareCssmData(&isn
->serialNumber
, &issuerAndSN
->serialNumber
)) { 
 406             CFRelease(certificate
); 
 410         dprintf("CERT_FindCertByIssuerAndSN: found cert %p\n", certificate
); 
 414     /* Search the user-added certList */ 
 415     if (certList 
&& CFArrayGetCount(certList
)) { 
 416         CFIndex c
, count 
= CFArrayGetCount(certList
); 
 417         for (c 
= 0; c 
< count
; c
++) { 
 418             SecCertificateRef cert 
= (SecCertificateRef
)CFArrayGetValueAtIndex(certList
, c
); 
 419             SecCmsIssuerAndSN 
*isn 
= CERT_GetCertIssuerAndSN(pl
, cert
); 
 423             if(!compareCssmData(&isn
->derIssuer
, &issuerAndSN
->derIssuer
)) { 
 426             if(!compareCssmData(&isn
->serialNumber
, &issuerAndSN
->serialNumber
)) { 
 432         if (certificate
) { return certificate
; } 
 435     /* now search keychain(s) */ 
 436     OSStatus status 
= SecCertificateFindByIssuerAndSN(keychainOrArray
, &issuerAndSN
->derIssuer
, 
 437         &issuerAndSN
->serialNumber
, &certificate
); 
 440         PORT_SetError(SEC_ERROR_NO_EMAIL_CERT
); 
 447 SecCertificateRef 
CERT_FindCertBySubjectKeyID (CFTypeRef keychainOrArray
,  
 448     CSSM_DATA_PTR 
*rawCerts
, CFArrayRef certList
, const SECItem 
*subjKeyID
) 
 450     SecCertificateRef certificate
; 
 451     int numRawCerts 
= SecCmsArrayCount((void **)rawCerts
); 
 457      * First search the rawCerts array. 
 459     for(dex
=0; dex
<numRawCerts
; dex
++) { 
 461         ortn 
= SecCertificateCreateFromData(rawCerts
[dex
],  
 462             CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
, 
 467         if(CERT_FindSubjectKeyIDExtension(certificate
, &skid
)) { 
 468             CFRelease(certificate
); 
 472         match 
= compareCssmData(subjKeyID
, &skid
); 
 473         SECITEM_FreeItem(&skid
, PR_FALSE
); 
 478         CFRelease(certificate
); 
 481     /* Search the user-added certList */ 
 482     if (certList 
&& CFArrayGetCount(certList
)) { 
 483         CFDataRef subjectkeyid 
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, subjKeyID
->Data
, subjKeyID
->Length
, kCFAllocatorNull
); 
 484         CFIndex c
, count 
= CFArrayGetCount(certList
); 
 485         for (c 
= 0; c 
< count
; c
++) { 
 486             SecCertificateRef cert 
= (SecCertificateRef
)CFArrayGetValueAtIndex(certList
, c
); 
 487             CFDataRef skid 
= (cert
) ? SecCertificateGetSubjectKeyID(cert
) : NULL
; 
 488             if (skid 
&& CFEqual(skid
, subjectkeyid
)) { 
 494         if (subjectkeyid
) { CFRelease(subjectkeyid
); }; 
 495         if (certificate
) { return certificate
; } 
 498     /* now search keychain(s) */ 
 499     OSStatus status 
= SecCertificateFindBySubjectKeyID(keychainOrArray
,subjKeyID
,&certificate
); 
 502         PORT_SetError(SEC_ERROR_NO_EMAIL_CERT
); 
 509 static SecIdentityRef
 
 510 CERT_FindIdentityByCertificate (CFTypeRef keychainOrArray
, SecCertificateRef CF_CONSUMED certificate
) 
 512     SecIdentityRef  identity 
= NULL
; 
 513     SecIdentityCreateWithCertificate(keychainOrArray
, certificate
, &identity
); 
 515         PORT_SetError(SEC_ERROR_NOT_A_RECIPIENT
); 
 517         CFRelease(certificate
); 
 524 CERT_FindIdentityByIssuerAndSN (CFTypeRef keychainOrArray
, const SecCmsIssuerAndSN 
*issuerAndSN
) 
 526     SecCertificateRef certificate 
= CERT_FindCertByIssuerAndSN(keychainOrArray
, NULL
, NULL
, NULL
, issuerAndSN
); 
 530     return CERT_FindIdentityByCertificate(keychainOrArray
, certificate
); 
 534 CERT_FindIdentityBySubjectKeyID (CFTypeRef keychainOrArray
, const SECItem 
*subjKeyID
) 
 536     SecCertificateRef certificate 
= CERT_FindCertBySubjectKeyID(keychainOrArray
, NULL
, NULL
, subjKeyID
); 
 540     return CERT_FindIdentityByCertificate(keychainOrArray
, certificate
); 
 543 // find the smime symmetric capabilities profile for a given cert 
 544 SECItem 
*CERT_FindSMimeProfile(SecCertificateRef cert
) 
 549 // Return the decoded value of the subjectKeyID extension. The caller should  
 550 // free up the storage allocated in retItem->data. 
 551 SECStatus 
CERT_FindSubjectKeyIDExtension (SecCertificateRef cert
, SECItem 
*retItem
) 
 553     CSSM_DATA_PTR fieldValue 
= NULL
; 
 555     CSSM_X509_EXTENSION 
*extp
; 
 556     CE_SubjectKeyID 
*skid
; 
 558     ortn 
= SecCertificateCopyFirstFieldValue(cert
, &CSSMOID_SubjectKeyIdentifier
, 
 560     if(ortn 
|| (fieldValue 
== NULL
)) { 
 561         /* this cert doesn't have that extension */ 
 564     extp 
= (CSSM_X509_EXTENSION 
*)fieldValue
->Data
; 
 565     skid 
= (CE_SubjectKeyID 
*)extp
->value
.parsedValue
; 
 566     retItem
->Data 
= (uint8 
*)PORT_Alloc(skid
->Length
); 
 567     retItem
->Length 
= skid
->Length
; 
 568     memmove(retItem
->Data
, skid
->Data
, retItem
->Length
); 
 569     SecCertificateReleaseFirstFieldValue(cert
, &CSSMOID_SubjectKeyIdentifier
, 
 574 // Extract the issuer and serial number from a certificate 
 575 SecCmsIssuerAndSN 
*CERT_GetCertIssuerAndSN(PRArenaPool 
*pl
, SecCertificateRef cert
) 
 578     SecCmsIssuerAndSN 
*certIssuerAndSN
; 
 579     SecCertificateRef certRef
; 
 580     SecCertificateRef itemImplRef 
= NULL
; 
 581     CSSM_CL_HANDLE clHandle
; 
 582     CSSM_DATA_PTR serialNumber 
= 0; 
 583     CSSM_DATA_PTR issuer 
= 0; 
 584     CSSM_DATA certData 
= {}; 
 585     CSSM_HANDLE resultsHandle 
= 0; 
 586     uint32 numberOfFields 
= 0; 
 590     mark 
= PORT_ArenaMark(pl
); 
 592     /* Retain input cert and get pointer to its data */ 
 593     certRef 
= (SecCertificateRef
)((cert
) ? CFRetain(cert
) : NULL
); 
 594     status 
= SecCertificateGetData(certRef
, &certData
); 
 598     // Convert unified input certRef to itemImpl instance. 
 599     // note: must not release this instance while we're using its CL handle! 
 600     itemImplRef 
= SecCertificateCreateItemImplInstance(cert
); 
 601     status 
= SecCertificateGetCLHandle_legacy(itemImplRef
, &clHandle
); 
 603     status 
= SecCertificateGetCLHandle(certRef
, &clHandle
); 
 608     /* Get the issuer from the cert. */ 
 609     result 
= CSSM_CL_CertGetFirstFieldValue(clHandle
, &certData
, 
 610         &OID_X509V1IssuerNameStd
, &resultsHandle
, &numberOfFields
, &issuer
); 
 612     if (result 
|| numberOfFields 
< 1) 
 614     result 
= CSSM_CL_CertAbortQuery(clHandle
, resultsHandle
); 
 618     /* Get the serialNumber from the cert. */ 
 619     result 
= CSSM_CL_CertGetFirstFieldValue(clHandle
, &certData
, 
 620         &CSSMOID_X509V1SerialNumber
, &resultsHandle
, &numberOfFields
, &serialNumber
); 
 621     if (result 
|| numberOfFields 
< 1) 
 623     result 
= CSSM_CL_CertAbortQuery(clHandle
, resultsHandle
); 
 627     /* Allocate the SecCmsIssuerAndSN struct. */ 
 628     certIssuerAndSN 
= (SecCmsIssuerAndSN 
*)PORT_ArenaZAlloc (pl
, sizeof(SecCmsIssuerAndSN
)); 
 629     if (certIssuerAndSN 
== NULL
) 
 632     /* Copy the issuer. */ 
 633     certIssuerAndSN
->derIssuer
.Data 
= (uint8 
*) PORT_ArenaAlloc(pl
, issuer
->Length
); 
 634     if (!certIssuerAndSN
->derIssuer
.Data
) 
 636     PORT_Memcpy(certIssuerAndSN
->derIssuer
.Data
, issuer
->Data
, issuer
->Length
); 
 637     certIssuerAndSN
->derIssuer
.Length 
= issuer
->Length
; 
 639     /* Copy the serialNumber. */ 
 640     certIssuerAndSN
->serialNumber
.Data 
= (uint8 
*) PORT_ArenaAlloc(pl
, serialNumber
->Length
); 
 641     if (!certIssuerAndSN
->serialNumber
.Data
) 
 643     PORT_Memcpy(certIssuerAndSN
->serialNumber
.Data
, serialNumber
->Data
, serialNumber
->Length
); 
 644     certIssuerAndSN
->serialNumber
.Length 
= serialNumber
->Length
; 
 646     PORT_ArenaUnmark(pl
, mark
); 
 648     CSSM_CL_FreeFieldValue(clHandle
, &CSSMOID_X509V1SerialNumber
, serialNumber
); 
 649     CSSM_CL_FreeFieldValue(clHandle
, &OID_X509V1IssuerNameStd
, issuer
); 
 652         CFRelease(itemImplRef
); 
 656     return certIssuerAndSN
; 
 659     PORT_ArenaRelease(pl
, mark
); 
 662         CSSM_CL_FreeFieldValue(clHandle
, &CSSMOID_X509V1SerialNumber
, serialNumber
); 
 664         CSSM_CL_FreeFieldValue(clHandle
, &OID_X509V1IssuerNameStd
, issuer
); 
 666         CFRelease(itemImplRef
); 
 670     PORT_SetError(SEC_INTERNAL_ONLY
); 
 674 // import a collection of certs into the temporary or permanent cert database 
 675 SECStatus 
CERT_ImportCerts(SecKeychainRef keychain
, SECCertUsage usage
, unsigned int ncerts
, 
 676     SECItem 
**derCerts
, SecCertificateRef 
**retCerts
, Boolean keepCerts
, Boolean caOnly
, char *nickname
) 
 678     OSStatus rv 
= SECFailure
; 
 679     SecCertificateRef cert
; 
 682     // @@@ Do something with caOnly and nickname 
 683     if (caOnly 
|| nickname
) 
 686     for (ci 
= 0; ci 
< ncerts
; ++ci
) 
 688         rv 
= SecCertificateCreateFromData(derCerts
[ci
], CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
, &cert
); 
 693             rv 
= SecCertificateAddToKeychain(cert
, keychain
); 
 696                 if (rv 
== errKCDuplicateItem
) 
 718 SECStatus 
CERT_SaveSMimeProfile(SecCertificateRef cert
, SECItem 
*emailProfile
,SECItem 
*profileTime
) 
 720     fprintf(stderr
, "WARNING: CERT_SaveSMimeProfile unimplemented\n"); 
 724 // Check the hostname to make sure that it matches the shexp that 
 725 // is given in the common name of the certificate. 
 726 SECStatus 
CERT_VerifyCertName(SecCertificateRef cert
, const char *hostname
) 
 728     fprintf(stderr
, "WARNING: CERT_VerifyCertName unimplemented\n"); 
 733 ** OLD OBSOLETE FUNCTIONS with enum SECCertUsage - DO NOT USE FOR NEW CODE 
 734 ** verify a certificate by checking validity times against a certain time, 
 735 ** that we trust the issuer, and that the signature on the certificate is 
 737 **      "cert" the certificate to verify 
 738 **      "checkSig" only check signatures if true 
 741 CERT_VerifyCert(SecKeychainRef keychainOrArray
, SecCertificateRef cert
, 
 742                 const CSSM_DATA_PTR 
*otherCerts
,    /* intermediates */ 
 743                 CFTypeRef policies
, CFAbsoluteTime stime
, SecTrustRef 
*trustRef
) 
 745     CFMutableArrayRef certificates 
= NULL
; 
 746     SecTrustRef trust 
= NULL
; 
 748     int numOtherCerts 
= SecCmsArrayCount((void **)otherCerts
); 
 752      * Certs to evaluate: first the leaf - our cert - then all the rest we know 
 753      * about. It's OK for otherCerts to contain a copy of the leaf.  
 755     certificates 
= CFArrayCreateMutable(NULL
, numOtherCerts 
+ 1, &kCFTypeArrayCallBacks
); 
 756     CFArrayAppendValue(certificates
, cert
); 
 757     for(dex
=0; dex
<numOtherCerts
; dex
++) { 
 758         SecCertificateRef intCert
; 
 760         rv 
= SecCertificateCreateFromData(otherCerts
[dex
],  
 761             CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
, 
 766         CFArrayAppendValue(certificates
, intCert
); 
 769     rv 
= SecTrustCreateWithCertificates(certificates
, policies
, &trust
); 
 770     CFRelease(certificates
); 
 775     rv 
= SecTrustSetKeychains(trust
, keychainOrArray
); 
 779     CFDateRef verifyDate 
= CFDateCreate(NULL
, stime
); 
 780     rv 
= SecTrustSetVerifyDate(trust
, verifyDate
); 
 781     CFRelease(verifyDate
); 
 791         SecTrustResultType result
; 
 792         /* The caller doesn't want a SecTrust object, so let's evaluate it for them. */ 
 793         rv 
= SecTrustEvaluate(trust
, &result
); 
 799         case kSecTrustResultProceed
: 
 800         case kSecTrustResultUnspecified
: 
 801             /* TP Verification succeeded and there was either a UserTurst entry 
 802                telling us to procceed, or no user trust setting was specified. */ 
 806             PORT_SetError(SEC_ERROR_UNTRUSTED_CERT
); 
 815 #if 0 /* debugging */ 
 816         syslog(LOG_ERR
, "CERT_VerifyCert has failed with %d (input policies and output trust follow)", 
 818         if (policies
) CFShow(policies
); 
 819         if (trust
) CFShow(trust
); 
 824         CFRelease(certificates
); 
 829 CERT_PolicyForCertUsage(SECCertUsage certUsage
) 
 831     SecPolicyRef policy 
= NULL
; 
 835     case certUsageSSLServerWithStepUp
: 
 837     case certUsageVerifyCA
: 
 841     case certUsageSSLClient
: 
 842         policy 
= SecPolicyCreateSSL(false, NULL
); 
 844     case certUsageSSLServer
: 
 845         policy 
= SecPolicyCreateSSL(true, NULL
); 
 847     case certUsageStatusResponder
: 
 848         policy 
= SecPolicyCreateOCSPSigner(); 
 850     case certUsageObjectSigner
: 
 851     case certUsageProtectedObjectSigner
: 
 852     case certUsageUserCertImport
: 
 853     case certUsageEmailSigner
: 
 854     case certUsageEmailRecipient
: 
 855         policy 
= SecPolicyCreateBasicX509();