2 * Copyright (c) 2002-2015 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@
24 #include <Security/SecCertificate.h>
25 #include <Security/SecCertificatePriv.h>
26 #include <security_keychain/Certificate.h>
27 #include <security_keychain/Item.h>
28 #include <security_keychain/KCCursor.h>
29 #include <Security/cssmapi.h>
30 #include <Security/cssmapple.h>
31 #include <security_cdsa_client/cspclient.h>
32 #include <security_cdsa_client/clclient.h>
33 #include <security_cdsa_client/tpclient.h>
34 #include <Security/cssmtype.h>
36 #include "SecBridge.h"
38 // %%% used by SecCertificate{Copy,Set}Preference
39 #include <Security/SecKeychainItemPriv.h>
40 #include <Security/SecIdentityPriv.h>
41 #include <security_keychain/KCCursor.h>
42 #include <security_cdsa_utilities/Schema.h>
43 #include <security_cdsa_utils/cuCdsaUtils.h>
44 #include <sys/param.h>
46 #include "CertificateValues.h"
47 #include "SecCertificateP.h"
48 #include "SecCertificatePrivP.h"
50 #include "AppleBaselineEscrowCertificates.h"
53 SecCertificateRef
SecCertificateCreateItemImplInstance(SecCertificateRef certificate
);
54 OSStatus
SecCertificateGetCLHandle_legacy(SecCertificateRef certificate
, CSSM_CL_HANDLE
*clHandle
);
55 extern CSSM_KEYUSE
ConvertArrayToKeyUsage(CFArrayRef usage
);
57 #define SEC_CONST_DECL(k,v) const CFStringRef k = CFSTR(v);
59 SEC_CONST_DECL (kSecCertificateProductionEscrowKey
, "ProductionEscrowKey");
60 SEC_CONST_DECL (kSecCertificateProductionPCSEscrowKey
, "ProductionPCSEscrowKey");
61 SEC_CONST_DECL (kSecCertificateEscrowFileName
, "AppleESCertificates");
64 using namespace CssmClient
;
68 SecCertificateGetTypeID(void)
72 return gTypes().Certificate
.typeID
;
74 END_SECAPI1(_kCFRuntimeNotATypeID
)
78 /* convert a new-world SecCertificateRef to an old-world ItemImpl instance */
80 SecCertificateCreateItemImplInstance(SecCertificateRef certificate
)
83 return (SecCertificateRef
)(certificate
? CFRetain(certificate
) : NULL
);
88 SecCertificateRef implCertRef
= (SecCertificateRef
) SecCertificateCopyKeychainItem(certificate
);
92 CFDataRef data
= SecCertificateCopyData(certificate
);
97 CSSM_DATA cssmCertData
;
98 cssmCertData
.Length
= (data
) ? (CSSM_SIZE
)CFDataGetLength(data
) : 0;
99 cssmCertData
.Data
= (data
) ? (uint8
*)CFDataGetBytePtr(data
) : NULL
;
101 SecPointer
<Certificate
> certificatePtr(new Certificate(cssmCertData
, CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
));
102 implCertRef
= certificatePtr
->handle();
110 /* convert an old-world ItemImpl instance to a new-world SecCertificateRef */
112 SecCertificateCreateFromItemImplInstance(SecCertificateRef certificate
)
115 return (SecCertificateRef
)(certificate
? CFRetain(certificate
) : NULL
);
120 SecCertificateRef result
= NULL
;
121 CFDataRef data
= NULL
;
123 CssmData certData
= Certificate::required(certificate
)->data();
124 if (certData
.Data
&& certData
.Length
) {
125 data
= CFDataCreate(NULL
, certData
.Data
, certData
.Length
);
128 if (certData
.Data
&& !certData
.Length
) {
129 /* zero-length certs can exist, so don't bother logging this */
132 syslog(LOG_ERR
, "WARNING: SecKeychainSearchCopyNext failed to retrieve certificate data (length=%ld, data=0x%lX)",
133 (long)certData
.Length
, (uintptr_t)certData
.Data
);
140 result
= SecCertificateCreateWithKeychainItem(NULL
, data
, certificate
);
147 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
149 SecCertificateCreateFromData(const CSSM_DATA
*data
, CSSM_CERT_TYPE type
, CSSM_CERT_ENCODING encoding
, SecCertificateRef
*certificate
)
154 SecPointer
<Certificate
> certificatePtr(new Certificate(Required(data
), type
, encoding
));
155 Required(certificate
) = certificatePtr
->handle();
159 /* bridge to support old functionality */
160 if (!data
|| !data
->Data
|| !data
->Length
|| !certificate
) {
163 SecCertificateRef certRef
= NULL
;
164 CFDataRef dataRef
= CFDataCreate(NULL
, data
->Data
, data
->Length
);
166 certRef
= SecCertificateCreateWithData(NULL
, dataRef
);
169 *certificate
= certRef
;
170 return (certRef
) ? errSecSuccess
: errSecUnknownFormat
;
177 SecCertificateCreateWithData(CFAllocatorRef allocator
, CFDataRef data
)
179 SecCertificateRef certificate
= NULL
;
180 OSStatus __secapiresult
;
182 CSSM_DATA cssmCertData
;
183 cssmCertData
.Length
= (data
) ? (CSSM_SIZE
)CFDataGetLength(data
) : 0;
184 cssmCertData
.Data
= (data
) ? (uint8
*)CFDataGetBytePtr(data
) : NULL
;
186 //NOTE: there isn't yet a Certificate constructor which accepts a CFAllocatorRef
187 SecPointer
<Certificate
> certificatePtr(new Certificate(cssmCertData
, CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
));
188 certificate
= certificatePtr
->handle();
190 __secapiresult
=errSecSuccess
;
192 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
193 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
194 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
195 catch (...) { __secapiresult
=errSecInternalComponent
; }
200 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA) */
202 SecCertificateAddToKeychain(SecCertificateRef certificate
, SecKeychainRef keychain
)
204 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
207 Item
item(Certificate::required(__itemImplRef
));
208 Keychain::optional(keychain
)->add(item
);
213 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
215 SecCertificateGetData(SecCertificateRef certificate
, CSSM_DATA_PTR data
)
217 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
220 Required(data
) = Certificate::required(__itemImplRef
)->data();
228 SecCertificateCopyData(SecCertificateRef certificate
)
230 CFDataRef data
= NULL
;
231 OSStatus __secapiresult
= errSecSuccess
;
233 CssmData output
= Certificate::required(certificate
)->data();
234 CFIndex length
= (CFIndex
)output
.length();
235 const UInt8
*bytes
= (const UInt8
*)output
.data();
236 if (length
&& bytes
) {
237 data
= CFDataCreate(NULL
, bytes
, length
);
240 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
241 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
242 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
243 catch (...) { __secapiresult
=errSecInternalComponent
; }
250 SecCertificateGetSHA1Digest(SecCertificateRef certificate
)
252 CFDataRef data
= NULL
;
253 OSStatus __secapiresult
= errSecSuccess
;
255 data
= Certificate::required(certificate
)->sha1Hash();
257 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
258 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
259 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
260 catch (...) { __secapiresult
=errSecInternalComponent
; }
265 SecCertificateCopySHA256Digest(SecCertificateRef certificate
)
267 CFDataRef data
= NULL
;
268 OSStatus __secapiresult
= errSecSuccess
;
270 data
= Certificate::required(certificate
)->sha256Hash();
274 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
275 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
276 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
277 catch (...) { __secapiresult
=errSecInternalComponent
; }
286 SecCertificateCopyPublicKeySHA1Digest(SecCertificateRef certificate
)
288 CFDataRef data
= NULL
;
289 OSStatus __secapiresult
= errSecSuccess
;
291 CssmData output
= Certificate::required(certificate
)->publicKeyHash();
292 CFIndex length
= (CFIndex
)output
.length();
293 const UInt8
*bytes
= (const UInt8
*)output
.data();
294 if (length
&& bytes
) {
295 data
= CFDataCreate(NULL
, bytes
, length
);
298 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
299 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
300 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
301 catch (...) { __secapiresult
=errSecInternalComponent
; }
308 SecCertificateCopyDNSNames(SecCertificateRef certificate
)
310 CFArrayRef names
= NULL
;
311 OSStatus __secapiresult
= errSecSuccess
;
313 names
= Certificate::required(certificate
)->copyDNSNames();
315 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
316 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
317 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
318 catch (...) { __secapiresult
=errSecInternalComponent
; }
323 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
325 SecCertificateGetType(SecCertificateRef certificate
, CSSM_CERT_TYPE
*certificateType
)
327 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
330 Required(certificateType
) = Certificate::required(__itemImplRef
)->type();
335 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
337 SecCertificateGetSubject(SecCertificateRef certificate
, const CSSM_X509_NAME
**subject
)
339 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
342 Required(subject
) = Certificate::required(__itemImplRef
)->subjectName();
347 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
349 SecCertificateGetIssuer(SecCertificateRef certificate
, const CSSM_X509_NAME
**issuer
)
351 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
354 Required(issuer
) = Certificate::required(__itemImplRef
)->issuerName();
359 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
361 SecCertificateGetCLHandle(SecCertificateRef certificate
, CSSM_CL_HANDLE
*clHandle
)
366 Required(clHandle
) = Certificate::required(certificate
)->clHandle();
371 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
374 Required(clHandle
) = Certificate::required(__itemImplRef
)->clHandle();
378 /* bridge code to support deprecated functionality */
379 OSStatus __secapiresult
=errSecSuccess
;
381 SecCertificateRef __itemImplRef
=(SecCertificateRef
)SecCertificateCopyKeychainItem(certificate
);
382 if (!__itemImplRef
) { __itemImplRef
=SecCertificateCreateItemImplInstance(certificate
); kcItem
=false; }
384 Required(clHandle
) = Certificate::required(__itemImplRef
)->clHandle();
386 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
387 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
388 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
389 catch (...) { __secapiresult
=errSecInternalComponent
; }
392 /* we can't release the temporary certificate, or the CL handle becomes invalid.
393 * for now, just stick the temporary certificate into an array.
394 * TBD: use a dictionary, indexed by hash of certificate. */
395 static CFMutableArrayRef sLegacyCertArray
= NULL
;
396 if (!sLegacyCertArray
) {
397 sLegacyCertArray
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
398 if (!sLegacyCertArray
) {
399 return errSecAllocate
;
402 CFArrayAppendValue(sLegacyCertArray
, __itemImplRef
);
404 syslog(LOG_ERR
, "WARNING: SecCertificateGetCLHandle called on certificate which is not in a keychain.");
407 CFRelease(__itemImplRef
);
409 return __secapiresult
;
414 /* private function; assumes input is old-style ItemImpl certificate reference,
415 and does not release that certificate reference!
418 SecCertificateGetCLHandle_legacy(SecCertificateRef certificate
, CSSM_CL_HANDLE
*clHandle
)
422 Required(clHandle
) = Certificate::required(certificate
)->clHandle();
429 * Private API to infer a display name for a SecCertificateRef which
430 * may or may not be in a keychain.
435 SecCertificateInferLabel(SecCertificateRef certificate
, CFStringRef
*label
)
437 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
440 Certificate::required(__itemImplRef
)->inferLabel(false, &Required(label
));
445 /* OS X only (note: iOS version has different arguments and return value) */
447 SecCertificateCopyPublicKey(SecCertificateRef certificate
, SecKeyRef
*key
)
449 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
452 Required(key
) = Certificate::required(__itemImplRef
)->publicKey()->handle();
457 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
459 SecCertificateGetAlgorithmID(SecCertificateRef certificate
, const CSSM_X509_ALGORITHM_IDENTIFIER
**algid
)
461 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
464 Required(algid
) = Certificate::required(__itemImplRef
)->algorithmID();
469 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA) */
471 SecCertificateCopyCommonName(SecCertificateRef certificate
, CFStringRef
*commonName
)
473 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
476 Required(commonName
) = Certificate::required(__itemImplRef
)->commonName();
484 SecCertificateCopySubjectSummary(SecCertificateRef certificate
)
486 CFStringRef summary
= NULL
;
487 OSStatus __secapiresult
;
489 Certificate::required(certificate
)->inferLabel(false, &summary
);
491 __secapiresult
=errSecSuccess
;
493 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
494 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
495 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
496 catch (...) { __secapiresult
=errSecInternalComponent
; }
503 SecCertificateCopyIssuerSummary(SecCertificateRef certificate
)
505 CFStringRef issuerStr
= NULL
;
506 SecCertificateRefP certP
= NULL
;
507 CFDataRef certData
= SecCertificateCopyData(certificate
);
509 certP
= SecCertificateCreateWithDataP(NULL
, certData
);
513 issuerStr
= SecCertificateCopyIssuerSummaryP(certP
);
522 SecCertificateCopySubjectComponent(SecCertificateRef certificate
, const CSSM_OID
*component
, CFStringRef
*result
)
524 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
527 Required(result
) = Certificate::required(__itemImplRef
)->distinguishedName(&CSSMOID_X509V1SubjectNameCStruct
, component
);
532 /* OS X only; deprecated SPI */
534 SecCertificateGetCommonName(SecCertificateRef certificate
, CFStringRef
*commonName
)
536 // deprecated SPI signature; replaced by SecCertificateCopyCommonName
537 return SecCertificateCopyCommonName(certificate
, commonName
);
540 /* OS X only; deprecated SPI */
542 SecCertificateGetEmailAddress(SecCertificateRef certificate
, CFStringRef
*emailAddress
)
544 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
547 Required(emailAddress
) = Certificate::required(__itemImplRef
)->copyFirstEmailAddress();
554 SecCertificateCopyEmailAddresses(SecCertificateRef certificate
, CFArrayRef
*emailAddresses
)
556 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
559 Required(emailAddresses
) = Certificate::required(__itemImplRef
)->copyEmailAddresses();
564 /* Return a zero terminated list of CSSM_DATA_PTR's with the values of the field specified by field.
565 * Caller must call releaseFieldValues to free the storage allocated by this call.
570 SecCertificateCopyFieldValues(SecCertificateRef certificate
, const CSSM_OID
*field
, CSSM_DATA_PTR
**fieldValues
)
572 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
575 Required(fieldValues
) = Certificate::required(__itemImplRef
)->copyFieldValues(Required(field
));
582 SecCertificateReleaseFieldValues(SecCertificateRef certificate
, const CSSM_OID
*field
, CSSM_DATA_PTR
*fieldValues
)
584 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
587 Certificate::required(__itemImplRef
)->releaseFieldValues(Required(field
), fieldValues
);
594 SecCertificateCopyFirstFieldValue(SecCertificateRef certificate
, const CSSM_OID
*field
, CSSM_DATA_PTR
*fieldValue
)
596 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
599 Required(fieldValue
) = Certificate::required(__itemImplRef
)->copyFirstFieldValue(Required(field
));
606 SecCertificateReleaseFirstFieldValue(SecCertificateRef certificate
, const CSSM_OID
*field
, CSSM_DATA_PTR fieldValue
)
608 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
611 Certificate::required(__itemImplRef
)->releaseFieldValue(Required(field
), fieldValue
);
618 SecCertificateFindByIssuerAndSN(CFTypeRef keychainOrArray
,const CSSM_DATA
*issuer
,
619 const CSSM_DATA
*serialNumber
, SecCertificateRef
*certificate
)
623 StorageManager::KeychainList keychains
;
624 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
625 Required(certificate
) = Certificate::findByIssuerAndSN(keychains
, CssmData::required(issuer
), CssmData::required(serialNumber
))->handle();
628 // convert ItemImpl-based SecCertificateRef to new-world version before returning
629 CssmData certData
= Certificate::required(*certificate
)->data();
630 CFRef
<CFDataRef
> cfData(CFDataCreate(NULL
, certData
.Data
, certData
.Length
));
631 SecCertificateRef tmpRef
= *certificate
;
632 *certificate
= SecCertificateCreateWithData(NULL
, cfData
);
641 SecCertificateFindBySubjectKeyID(CFTypeRef keychainOrArray
, const CSSM_DATA
*subjectKeyID
,
642 SecCertificateRef
*certificate
)
646 StorageManager::KeychainList keychains
;
647 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
648 Required(certificate
) = Certificate::findBySubjectKeyID(keychains
, CssmData::required(subjectKeyID
))->handle();
651 // convert ItemImpl-based SecCertificateRef to new-world version before returning
652 CssmData certData
= Certificate::required(*certificate
)->data();
653 CFRef
<CFDataRef
> cfData(CFDataCreate(NULL
, certData
.Data
, certData
.Length
));
654 SecCertificateRef tmpRef
= *certificate
;
655 *certificate
= SecCertificateCreateWithData(NULL
, cfData
);
664 SecCertificateFindByEmail(CFTypeRef keychainOrArray
, const char *emailAddress
, SecCertificateRef
*certificate
)
668 StorageManager::KeychainList keychains
;
669 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
670 Required(certificate
) = Certificate::findByEmail(keychains
, emailAddress
)->handle();
673 // convert ItemImpl-based SecCertificateRef to new-world version before returning
674 CssmData certData
= Certificate::required(*certificate
)->data();
675 CFRef
<CFDataRef
> cfData(CFDataCreate(NULL
, certData
.Data
, certData
.Length
));
676 SecCertificateRef tmpRef
= *certificate
;
677 *certificate
= SecCertificateCreateWithData(NULL
, cfData
);
686 SecKeychainSearchCreateForCertificateByIssuerAndSN(CFTypeRef keychainOrArray
, const CSSM_DATA
*issuer
,
687 const CSSM_DATA
*serialNumber
, SecKeychainSearchRef
*searchRef
)
693 StorageManager::KeychainList keychains
;
694 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
695 KCCursor
cursor(Certificate::cursorForIssuerAndSN(keychains
, CssmData::required(issuer
), CssmData::required(serialNumber
)));
696 *searchRef
= cursor
->handle();
703 SecKeychainSearchCreateForCertificateByIssuerAndSN_CF(CFTypeRef keychainOrArray
, CFDataRef issuer
,
704 CFDataRef serialNumber
, SecKeychainSearchRef
*searchRef
)
710 StorageManager::KeychainList keychains
;
711 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
713 Required(serialNumber
);
714 KCCursor
cursor(Certificate::cursorForIssuerAndSN_CF(keychains
, issuer
, serialNumber
));
715 *searchRef
= cursor
->handle();
722 SecKeychainSearchCreateForCertificateBySubjectKeyID(CFTypeRef keychainOrArray
, const CSSM_DATA
*subjectKeyID
,
723 SecKeychainSearchRef
*searchRef
)
729 StorageManager::KeychainList keychains
;
730 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
731 KCCursor
cursor(Certificate::cursorForSubjectKeyID(keychains
, CssmData::required(subjectKeyID
)));
732 *searchRef
= cursor
->handle();
739 SecKeychainSearchCreateForCertificateByEmail(CFTypeRef keychainOrArray
, const char *emailAddress
,
740 SecKeychainSearchRef
*searchRef
)
746 StorageManager::KeychainList keychains
;
747 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
748 KCCursor
cursor(Certificate::cursorForEmail(keychains
, emailAddress
));
749 *searchRef
= cursor
->handle();
756 SecDigestGetData (CSSM_ALGORITHMS alg
, CSSM_DATA
* digest
, const CSSM_DATA
* data
)
760 if (!digest
|| !digest
->Data
|| !digest
->Length
|| !data
|| !data
->Data
|| !data
->Length
)
763 CSP
csp(gGuidAppleCSP
);
764 Digest
context(csp
, alg
);
765 CssmData
input(data
->Data
, data
->Length
);
766 CssmData
output(digest
->Data
, digest
->Length
);
768 context
.digest(input
, output
);
769 digest
->Length
= output
.length();
776 /* determine whether a cert is self-signed */
777 OSStatus
SecCertificateIsSelfSigned(
778 SecCertificateRef certificate
,
779 Boolean
*isSelfSigned
) /* RETURNED */
783 *isSelfSigned
= Certificate::required(certificate
)->isSelfSigned();
789 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
791 SecCertificateCopyPreference(
793 CSSM_KEYUSE keyUsage
,
794 SecCertificateRef
*certificate
)
799 Required(certificate
);
800 StorageManager::KeychainList keychains
;
801 globals().storageManager
.getSearchList(keychains
);
802 KCCursor
cursor(keychains
, kSecGenericPasswordItemClass
, NULL
);
804 char idUTF8
[MAXPATHLEN
];
805 if (!CFStringGetCString(name
, idUTF8
, sizeof(idUTF8
)-1, kCFStringEncodingUTF8
))
806 idUTF8
[0] = (char)'\0';
807 CssmData
service(const_cast<char *>(idUTF8
), strlen(idUTF8
));
808 FourCharCode itemType
= 'cprf';
809 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecServiceItemAttr
), service
);
810 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecTypeItemAttr
), itemType
);
812 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecScriptCodeItemAttr
), (sint32
)keyUsage
);
815 if (!cursor
->next(prefItem
))
816 MacOSError::throwMe(errSecItemNotFound
);
818 // get persistent certificate reference
819 SecKeychainAttribute itemAttrs
[] = { { kSecGenericItemAttr
, 0, NULL
} };
820 SecKeychainAttributeList itemAttrList
= { sizeof(itemAttrs
) / sizeof(itemAttrs
[0]), itemAttrs
};
821 prefItem
->getContent(NULL
, &itemAttrList
, NULL
, NULL
);
823 // find certificate, given persistent reference data
824 CFDataRef pItemRef
= CFDataCreateWithBytesNoCopy(NULL
, (const UInt8
*)itemAttrs
[0].data
, itemAttrs
[0].length
, kCFAllocatorNull
);
825 SecKeychainItemRef certItemRef
= nil
;
826 OSStatus status
= SecKeychainItemCopyFromPersistentReference(pItemRef
, &certItemRef
); //%%% need to make this a method of ItemImpl
827 prefItem
->freeContent(&itemAttrList
, NULL
);
833 *certificate
= (SecCertificateRef
)certItemRef
;
836 // convert ItemImpl-based SecCertificateRef to new-world version before returning
837 CssmData certData
= Certificate::required(*certificate
)->data();
838 CFRef
<CFDataRef
> cfData(CFDataCreate(NULL
, certData
.Data
, certData
.Length
));
839 SecCertificateRef tmpRef
= *certificate
;
840 *certificate
= SecCertificateCreateWithData(NULL
, cfData
);
849 SecCertificateCopyPreferred(
853 // This function will look for a matching preference in the following order:
854 // - matches the name and the supplied key use
855 // - matches the name and the special 'ANY' key use
856 // - matches the name with no key usage constraint
858 SecCertificateRef certRef
= NULL
;
859 CSSM_KEYUSE keyUse
= ConvertArrayToKeyUsage(keyUsage
);
860 OSStatus status
= SecCertificateCopyPreference(name
, keyUse
, &certRef
);
861 if (status
!= errSecSuccess
&& keyUse
!= CSSM_KEYUSE_ANY
)
862 status
= SecCertificateCopyPreference(name
, CSSM_KEYUSE_ANY
, &certRef
);
863 if (status
!= errSecSuccess
&& keyUse
!= 0)
864 status
= SecCertificateCopyPreference(name
, 0, &certRef
);
869 /* OS X only; not exported */
871 SecCertificateFindPreferenceItemWithNameAndKeyUsage(
872 CFTypeRef keychainOrArray
,
875 SecKeychainItemRef
*itemRef
)
879 StorageManager::KeychainList keychains
;
880 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
881 KCCursor
cursor(keychains
, kSecGenericPasswordItemClass
, NULL
);
883 char idUTF8
[MAXPATHLEN
];
884 idUTF8
[0] = (char)'\0';
887 if (!CFStringGetCString(name
, idUTF8
, sizeof(idUTF8
)-1, kCFStringEncodingUTF8
))
888 idUTF8
[0] = (char)'\0';
890 size_t idUTF8Len
= strlen(idUTF8
);
892 MacOSError::throwMe(errSecParam
);
894 CssmData
service(const_cast<char *>(idUTF8
), idUTF8Len
);
895 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecServiceItemAttr
), service
);
896 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecTypeItemAttr
), (FourCharCode
)'cprf');
898 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecScriptCodeItemAttr
), (sint32
)keyUsage
);
901 if (!cursor
->next(item
))
902 MacOSError::throwMe(errSecItemNotFound
);
905 *itemRef
=item
->handle();
910 /* OS X only; not exported */
912 OSStatus
SecCertificateDeletePreferenceItemWithNameAndKeyUsage(
913 CFTypeRef keychainOrArray
,
917 // when a specific key usage is passed, we'll only match & delete that pref;
918 // when a key usage of 0 is passed, all matching prefs should be deleted.
919 // maxUsages represents the most matches there could theoretically be, so
920 // cut things off at that point if we're still finding items (if they can't
921 // be deleted for some reason, we'd never break out of the loop.)
924 SecKeychainItemRef item
= NULL
;
925 int count
= 0, maxUsages
= 12;
926 while (++count
<= maxUsages
&&
927 (status
= SecCertificateFindPreferenceItemWithNameAndKeyUsage(keychainOrArray
, name
, keyUsage
, &item
)) == errSecSuccess
) {
928 status
= SecKeychainItemDelete(item
);
933 // it's not an error if the item isn't found
934 return (status
== errSecItemNotFound
) ? errSecSuccess
: status
;
937 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA) */
938 OSStatus
SecCertificateSetPreference(
939 SecCertificateRef certificate
,
941 CSSM_KEYUSE keyUsage
,
948 // treat NULL certificate as a request to clear the preference
949 // (note: if keyUsage is 0, this clears all key usage prefs for name)
950 return SecCertificateDeletePreferenceItemWithNameAndKeyUsage(NULL
, name
, keyUsage
);
953 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
956 // determine the account attribute
958 // This attribute must be synthesized from certificate label + pref item type + key usage,
959 // as only the account and service attributes can make a generic keychain item unique.
960 // For 'iprf' type items (but not 'cprf'), we append a trailing space. This insures that
961 // we can save a certificate preference if an identity preference already exists for the
962 // given service name, and vice-versa.
963 // If the key usage is 0 (i.e. the normal case), we omit the appended key usage string.
965 CFStringRef labelStr
= nil
;
966 Certificate::required(__itemImplRef
)->inferLabel(false, &labelStr
);
968 MacOSError::throwMe(errSecDataTooLarge
); // data is "in a format which cannot be displayed"
970 CFIndex accountUTF8Len
= CFStringGetMaximumSizeForEncoding(CFStringGetLength(labelStr
), kCFStringEncodingUTF8
) + 1;
971 const char *templateStr
= "%s [key usage 0x%X]";
972 const int keyUsageMaxStrLen
= 8;
973 accountUTF8Len
+= strlen(templateStr
) + keyUsageMaxStrLen
;
974 char accountUTF8
[accountUTF8Len
];
975 if (!CFStringGetCString(labelStr
, accountUTF8
, accountUTF8Len
-1, kCFStringEncodingUTF8
))
976 accountUTF8
[0] = (char)'\0';
978 snprintf(accountUTF8
, accountUTF8Len
-1, templateStr
, accountUTF8
, keyUsage
);
979 CssmData
account(const_cast<char *>(accountUTF8
), strlen(accountUTF8
));
982 // service attribute (name provided by the caller)
983 CFIndex serviceUTF8Len
= CFStringGetMaximumSizeForEncoding(CFStringGetLength(name
), kCFStringEncodingUTF8
) + 1;;
984 char serviceUTF8
[serviceUTF8Len
];
985 if (!CFStringGetCString(name
, serviceUTF8
, serviceUTF8Len
-1, kCFStringEncodingUTF8
))
986 serviceUTF8
[0] = (char)'\0';
987 CssmData
service(const_cast<char *>(serviceUTF8
), strlen(serviceUTF8
));
989 // look for existing preference item, in case this is an update
990 StorageManager::KeychainList keychains
;
991 globals().storageManager
.getSearchList(keychains
);
992 KCCursor
cursor(keychains
, kSecGenericPasswordItemClass
, NULL
);
993 FourCharCode itemType
= 'cprf';
994 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecServiceItemAttr
), service
);
995 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecTypeItemAttr
), itemType
);
997 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecScriptCodeItemAttr
), (sint32
)keyUsage
);
1001 Item
item(kSecGenericPasswordItemClass
, 'aapl', 0, NULL
, false);
1002 bool add
= (!cursor
->next(item
));
1003 // at this point, we either have a new item to add or an existing item to update
1005 // set item attribute values
1006 item
->setAttribute(Schema::attributeInfo(kSecServiceItemAttr
), service
);
1007 item
->setAttribute(Schema::attributeInfo(kSecTypeItemAttr
), itemType
);
1008 item
->setAttribute(Schema::attributeInfo(kSecAccountItemAttr
), account
);
1009 item
->setAttribute(Schema::attributeInfo(kSecScriptCodeItemAttr
), (sint32
)keyUsage
);
1010 item
->setAttribute(Schema::attributeInfo(kSecLabelItemAttr
), service
);
1016 // generic attribute (store persistent certificate reference)
1017 CFDataRef pItemRef
= nil
;
1018 Certificate::required(__itemImplRef
)->copyPersistentReference(pItemRef
);
1020 MacOSError::throwMe(errSecInvalidItemRef
);
1022 const UInt8
*dataPtr
= CFDataGetBytePtr(pItemRef
);
1023 CFIndex dataLen
= CFDataGetLength(pItemRef
);
1024 CssmData
pref(const_cast<void *>(reinterpret_cast<const void *>(dataPtr
)), dataLen
);
1025 item
->setAttribute(Schema::attributeInfo(kSecGenericItemAttr
), pref
);
1026 CFRelease(pItemRef
);
1029 Keychain keychain
= nil
;
1031 keychain
= globals().storageManager
.defaultKeychain();
1032 if (!keychain
->exists())
1033 MacOSError::throwMe(errSecNoSuchKeychain
); // Might be deleted or not available at this time.
1036 keychain
= globals().storageManager
.defaultKeychainUI(item
);
1040 keychain
->add(item
);
1042 catch (const MacOSError
&err
) {
1043 if (err
.osStatus() != errSecDuplicateItem
)
1044 throw; // if item already exists, fall through to update
1052 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
1053 OSStatus
SecCertificateSetPreferred(
1054 SecCertificateRef certificate
,
1056 CFArrayRef keyUsage
)
1058 CSSM_KEYUSE keyUse
= ConvertArrayToKeyUsage(keyUsage
);
1059 return SecCertificateSetPreference(certificate
, name
, keyUse
, NULL
);
1062 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
1063 CFDictionaryRef
SecCertificateCopyValues(SecCertificateRef certificate
, CFArrayRef keys
, CFErrorRef
*error
)
1065 CFDictionaryRef result
= NULL
;
1066 OSStatus __secapiresult
;
1069 CertificateValues
cv(certificate
);
1070 result
= cv
.copyFieldValues(keys
,error
);
1073 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1074 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1075 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1076 catch (...) { __secapiresult
=errSecInternalComponent
; }
1080 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
1081 CFStringRef
SecCertificateCopyLongDescription(CFAllocatorRef alloc
, SecCertificateRef certificate
, CFErrorRef
*error
)
1083 return SecCertificateCopyShortDescription(alloc
, certificate
, error
);
1086 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
1087 CFStringRef
SecCertificateCopyShortDescription(CFAllocatorRef alloc
, SecCertificateRef certificate
, CFErrorRef
*error
)
1089 CFStringRef result
= NULL
;
1090 OSStatus __secapiresult
= SecCertificateInferLabel(certificate
, &result
);
1091 if (error
!=NULL
&& __secapiresult
!=errSecSuccess
)
1093 *error
= CFErrorCreate(kCFAllocatorDefault
, kCFErrorDomainOSStatus
,
1094 __secapiresult
? __secapiresult
: CSSM_ERRCODE_INTERNAL_ERROR
, NULL
);
1099 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
1100 CFDataRef
SecCertificateCopySerialNumber(SecCertificateRef certificate
, CFErrorRef
*error
)
1102 CFDataRef result
= NULL
;
1103 OSStatus __secapiresult
;
1106 CertificateValues
cv(certificate
);
1107 result
= cv
.copySerialNumber(error
);
1110 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1111 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1112 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1113 catch (...) { __secapiresult
=errSecInternalComponent
; }
1117 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
1118 CFDataRef
SecCertificateCopyNormalizedIssuerContent(SecCertificateRef certificate
, CFErrorRef
*error
)
1120 CFDataRef result
= NULL
;
1121 OSStatus __secapiresult
;
1124 CertificateValues
cv(certificate
);
1125 result
= cv
.copyNormalizedIssuerContent(error
);
1128 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1129 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1130 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1131 catch (...) { __secapiresult
=errSecInternalComponent
; }
1135 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
1136 CFDataRef
SecCertificateCopyNormalizedSubjectContent(SecCertificateRef certificate
, CFErrorRef
*error
)
1138 CFDataRef result
= NULL
;
1139 OSStatus __secapiresult
;
1142 CertificateValues
cv(certificate
);
1143 result
= cv
.copyNormalizedSubjectContent(error
);
1146 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1147 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1148 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1149 catch (...) { __secapiresult
=errSecInternalComponent
; }
1154 CFDataRef
SecCertificateCopyIssuerSequence(SecCertificateRef certificate
)
1156 CFDataRef result
= NULL
;
1157 OSStatus __secapiresult
;
1160 CertificateValues
cv(certificate
);
1161 result
= cv
.copyIssuerSequence(NULL
);
1164 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1165 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1166 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1167 catch (...) { __secapiresult
=errSecInternalComponent
; }
1173 CFDataRef
SecCertificateCopySubjectSequence(SecCertificateRef certificate
)
1175 CFDataRef result
= NULL
;
1176 OSStatus __secapiresult
;
1179 CertificateValues
cv(certificate
);
1180 result
= cv
.copySubjectSequence(NULL
);
1183 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1184 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1185 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1186 catch (...) { __secapiresult
=errSecInternalComponent
; }
1192 bool SecCertificateIsValid(SecCertificateRef certificate
, CFAbsoluteTime verifyTime
)
1195 OSStatus __secapiresult
;
1198 CFErrorRef error
= NULL
;
1199 CertificateValues
cv(certificate
);
1200 result
= cv
.isValid(verifyTime
, &error
);
1201 if (error
) CFRelease(error
);
1204 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1205 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1206 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1207 catch (...) { __secapiresult
=errSecInternalComponent
; }
1212 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_9, __IPHONE_NA, __IPHONE_NA) */
1213 bool SecCertificateIsValidX(SecCertificateRef certificate
, CFAbsoluteTime verifyTime
)
1216 * deprecated function name
1218 return SecCertificateIsValid(certificate
, verifyTime
);
1222 CFAbsoluteTime
SecCertificateNotValidBefore(SecCertificateRef certificate
)
1224 CFAbsoluteTime result
= 0;
1225 OSStatus __secapiresult
;
1228 CFErrorRef error
= NULL
;
1229 CertificateValues
cv(certificate
);
1230 result
= cv
.notValidBefore(&error
);
1231 if (error
) CFRelease(error
);
1234 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1235 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1236 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1237 catch (...) { __secapiresult
=errSecInternalComponent
; }
1243 CFAbsoluteTime
SecCertificateNotValidAfter(SecCertificateRef certificate
)
1245 CFAbsoluteTime result
= 0;
1246 OSStatus __secapiresult
;
1249 CFErrorRef error
= NULL
;
1250 CertificateValues
cv(certificate
);
1251 result
= cv
.notValidAfter(&error
);
1252 if (error
) CFRelease(error
);
1255 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1256 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1257 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1258 catch (...) { __secapiresult
=errSecInternalComponent
; }
1265 SecCertificateRef
SecCertificateCreateWithBytes(CFAllocatorRef allocator
,
1266 const UInt8
*bytes
, CFIndex length
)
1268 SecCertificateRef certificate
= NULL
;
1269 OSStatus __secapiresult
;
1271 CSSM_DATA cssmCertData
= { (CSSM_SIZE
)length
, (uint8
*)bytes
};
1273 //NOTE: there isn't yet a Certificate constructor which accepts a CFAllocatorRef
1274 SecPointer
<Certificate
> certificatePtr(new Certificate(cssmCertData
, CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
));
1275 certificate
= certificatePtr
->handle();
1277 __secapiresult
=errSecSuccess
;
1279 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1280 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1281 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1282 catch (...) { __secapiresult
=errSecInternalComponent
; }
1289 CFIndex
SecCertificateGetLength(SecCertificateRef certificate
)
1292 OSStatus __secapiresult
;
1294 CssmData output
= Certificate::required(certificate
)->data();
1295 length
= (CFIndex
)output
.length();
1296 __secapiresult
=errSecSuccess
;
1298 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1299 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1300 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1301 catch (...) { __secapiresult
=errSecInternalComponent
; }
1308 const UInt8
*SecCertificateGetBytePtr(SecCertificateRef certificate
)
1310 const UInt8
*bytes
= NULL
;
1311 OSStatus __secapiresult
;
1313 CssmData output
= Certificate::required(certificate
)->data();
1314 bytes
= (const UInt8
*)output
.data();
1315 __secapiresult
=errSecSuccess
;
1317 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1318 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1319 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1320 catch (...) { __secapiresult
=errSecInternalComponent
; }
1327 static CFArrayRef
CopyEscrowCertificates(SecCertificateEscrowRootType escrowRootType
, CFErrorRef
*error
)
1329 // Return array of CFDataRef certificates.
1330 CFArrayRef result
= NULL
;
1334 // Get the hard coded set of production roots
1335 // static struct RootRecord* kProductionEscrowRoots[] = {&kOldEscrowRootRecord, &kProductionEscrowRootRecord};
1337 struct RootRecord
** pEscrowRoots
= NULL
;
1338 switch (escrowRootType
) {
1339 case kSecCertificateBaselineEscrowRoot
:
1340 numRoots
= kNumberOfBaseLineEscrowRoots
;
1341 pEscrowRoots
= kBaseLineEscrowRoots
;
1343 case kSecCertificateProductionEscrowRoot
:
1344 numRoots
= kNumberOfBaseLineEscrowRoots
; //%%% currently, production == baseline on OS X
1345 pEscrowRoots
= kBaseLineEscrowRoots
;
1347 case kSecCertificateBaselinePCSEscrowRoot
:
1348 numRoots
= kNumberOfBaseLinePCSEscrowRoots
;
1349 pEscrowRoots
= kBaseLinePCSEscrowRoots
;
1351 case kSecCertificateProductionPCSEscrowRoot
:
1352 numRoots
= kNumberOfBaseLinePCSEscrowRoots
; //%%% currently, production == baseline on OS X
1353 pEscrowRoots
= kBaseLinePCSEscrowRoots
;
1359 CFDataRef productionCerts
[numRoots
];
1360 struct RootRecord
* pRootRecord
= NULL
;
1362 for (iCnt
= 0; pEscrowRoots
!= NULL
&& iCnt
< numRoots
; iCnt
++)
1364 pRootRecord
= pEscrowRoots
[iCnt
];
1365 if (NULL
!= pRootRecord
&& pRootRecord
->_length
> 0 && NULL
!= pRootRecord
->_bytes
)
1367 productionCerts
[iCnt
] = CFDataCreate(kCFAllocatorDefault
, pRootRecord
->_bytes
, pRootRecord
->_length
);
1370 result
= CFArrayCreate(kCFAllocatorDefault
, (const void **)productionCerts
, numRoots
, &kCFTypeArrayCallBacks
);
1371 for (iCnt
= 0; iCnt
< numRoots
; iCnt
++)
1373 if (NULL
!= productionCerts
[iCnt
])
1375 CFRelease(productionCerts
[iCnt
]);
1385 CFArrayRef
SecCertificateCopyEscrowRoots(SecCertificateEscrowRootType escrowRootType
)
1387 CFArrayRef result
= NULL
;
1390 CFDataRef certData
= NULL
;
1392 // The request is for the base line certificates.
1393 // Use the hard coded data to generate the return array
1394 if (kSecCertificateBaselineEscrowRoot
== escrowRootType
)
1396 // Get the hard coded set of roots
1397 numRoots
= kNumberOfBaseLineEscrowRoots
;
1398 SecCertificateRef baseLineCerts
[numRoots
];
1399 struct RootRecord
* pRootRecord
= NULL
;
1401 for (iCnt
= 0; iCnt
< numRoots
; iCnt
++)
1403 pRootRecord
= kBaseLineEscrowRoots
[iCnt
];
1404 if (NULL
!= pRootRecord
&& pRootRecord
->_length
> 0 && NULL
!= pRootRecord
->_bytes
)
1406 certData
= CFDataCreate(kCFAllocatorDefault
, pRootRecord
->_bytes
, pRootRecord
->_length
);
1407 if (NULL
!= certData
)
1409 baseLineCerts
[iCnt
] = SecCertificateCreateWithData(kCFAllocatorDefault
, certData
);
1410 CFRelease(certData
);
1414 result
= CFArrayCreate(kCFAllocatorDefault
, (const void **)baseLineCerts
, numRoots
, &kCFTypeArrayCallBacks
);
1415 for (iCnt
= 0; iCnt
< numRoots
; iCnt
++)
1417 if (NULL
!= baseLineCerts
[iCnt
])
1419 CFRelease(baseLineCerts
[iCnt
]);
1423 // The request is for the current certificates.
1426 CFErrorRef error
= NULL
;
1427 CFArrayRef cert_datas
= CopyEscrowCertificates(escrowRootType
, &error
);
1428 if (NULL
!= error
|| NULL
== cert_datas
|| 0 == (numRoots
= (int)CFArrayGetCount(cert_datas
)))
1435 if (NULL
!= cert_datas
)
1437 CFRelease(cert_datas
);
1442 SecCertificateRef assetCerts
[numRoots
];
1443 for (iCnt
= 0; iCnt
< numRoots
; iCnt
++)
1445 certData
= (CFDataRef
)CFArrayGetValueAtIndex(cert_datas
, iCnt
);
1446 if (NULL
!= certData
)
1448 SecCertificateRef aCertRef
= SecCertificateCreateWithData(kCFAllocatorDefault
, certData
);
1449 assetCerts
[iCnt
] = aCertRef
;
1453 assetCerts
[iCnt
] = NULL
;
1459 result
= CFArrayCreate(kCFAllocatorDefault
, (const void **)assetCerts
, numRoots
, &kCFTypeArrayCallBacks
);
1460 for (iCnt
= 0; iCnt
< numRoots
; iCnt
++)
1462 if (NULL
!= assetCerts
[iCnt
])
1464 CFRelease(assetCerts
[iCnt
]);
1468 CFRelease(cert_datas
);
1477 SecSignatureHashAlgorithm
SecCertificateGetSignatureHashAlgorithm(SecCertificateRef certificate
)
1479 SecSignatureHashAlgorithm result
= kSecSignatureHashAlgorithmUnknown
;
1480 CSSM_X509_ALGORITHM_IDENTIFIER_PTR algId
= NULL
;
1481 CSSM_DATA_PTR fieldValue
= NULL
;
1482 CSSM_OID_PTR algOID
= NULL
;
1483 const CSSM_OID
*sigAlgOID
= &CSSMOID_X509V1SignatureAlgorithm
;
1486 status
= SecCertificateCopyFirstFieldValue(certificate
, sigAlgOID
, &fieldValue
);
1487 if (status
|| !fieldValue
) {
1490 algId
= (CSSM_X509_ALGORITHM_IDENTIFIER_PTR
)fieldValue
->Data
;
1491 algOID
= (algId
) ? &algId
->algorithm
: NULL
;
1494 if (!algOID
->Data
|| !algOID
->Length
) {
1497 /* classify the signature algorithm OID into one of our known types */
1498 if (cuCompareCssmData(algOID
, &CSSMOID_ECDSA_WithSHA512
) ||
1499 cuCompareCssmData(algOID
, &CSSMOID_SHA512WithRSA
) ||
1500 cuCompareCssmData(algOID
, &CSSMOID_SHA512
)) {
1501 result
= kSecSignatureHashAlgorithmSHA512
;
1504 if (cuCompareCssmData(algOID
, &CSSMOID_ECDSA_WithSHA384
) ||
1505 cuCompareCssmData(algOID
, &CSSMOID_SHA384WithRSA
) ||
1506 cuCompareCssmData(algOID
, &CSSMOID_SHA384
)) {
1507 result
= kSecSignatureHashAlgorithmSHA384
;
1510 if (cuCompareCssmData(algOID
, &CSSMOID_ECDSA_WithSHA256
) ||
1511 cuCompareCssmData(algOID
, &CSSMOID_SHA256WithRSA
) ||
1512 cuCompareCssmData(algOID
, &CSSMOID_SHA256
)) {
1513 result
= kSecSignatureHashAlgorithmSHA256
;
1516 if (cuCompareCssmData(algOID
, &CSSMOID_ECDSA_WithSHA224
) ||
1517 cuCompareCssmData(algOID
, &CSSMOID_SHA224WithRSA
) ||
1518 cuCompareCssmData(algOID
, &CSSMOID_SHA224
)) {
1519 result
= kSecSignatureHashAlgorithmSHA224
;
1522 if (cuCompareCssmData(algOID
, &CSSMOID_ECDSA_WithSHA1
) ||
1523 cuCompareCssmData(algOID
, &CSSMOID_SHA1WithRSA
) ||
1524 cuCompareCssmData(algOID
, &CSSMOID_SHA1WithDSA
) ||
1525 cuCompareCssmData(algOID
, &CSSMOID_SHA1WithDSA_CMS
) ||
1526 cuCompareCssmData(algOID
, &CSSMOID_SHA1WithDSA_JDK
) ||
1527 cuCompareCssmData(algOID
, &CSSMOID_SHA1WithRSA_OIW
) ||
1528 cuCompareCssmData(algOID
, &CSSMOID_APPLE_FEE_SHA1
) ||
1529 cuCompareCssmData(algOID
, &CSSMOID_SHA1
)) {
1530 result
= kSecSignatureHashAlgorithmSHA1
;
1533 if (cuCompareCssmData(algOID
, &CSSMOID_MD5WithRSA
) ||
1534 cuCompareCssmData(algOID
, &CSSMOID_APPLE_FEE_MD5
) ||
1535 cuCompareCssmData(algOID
, &CSSMOID_MD5
)) {
1536 result
= kSecSignatureHashAlgorithmMD5
;
1539 if (cuCompareCssmData(algOID
, &CSSMOID_MD4WithRSA
) ||
1540 cuCompareCssmData(algOID
, &CSSMOID_MD4
)) {
1541 result
= kSecSignatureHashAlgorithmMD4
;
1544 if (cuCompareCssmData(algOID
, &CSSMOID_MD2WithRSA
) ||
1545 cuCompareCssmData(algOID
, &CSSMOID_MD2
)) {
1546 result
= kSecSignatureHashAlgorithmMD2
;
1552 (void)SecCertificateReleaseFirstFieldValue(certificate
, sigAlgOID
, fieldValue
);