2 * Copyright (c) 2002-2016 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 OSStatus
SecCertificateGetCLHandle_legacy(SecCertificateRef certificate
, CSSM_CL_HANDLE
*clHandle
);
54 extern CSSM_KEYUSE
ConvertArrayToKeyUsage(CFArrayRef usage
);
56 #define SEC_CONST_DECL(k,v) const CFStringRef k = CFSTR(v);
58 SEC_CONST_DECL (kSecCertificateProductionEscrowKey
, "ProductionEscrowKey");
59 SEC_CONST_DECL (kSecCertificateProductionPCSEscrowKey
, "ProductionPCSEscrowKey");
60 SEC_CONST_DECL (kSecCertificateEscrowFileName
, "AppleESCertificates");
63 using namespace CssmClient
;
67 static SecCertificateGetTypeID_osx(void)
69 SecCertificateGetTypeID(void)
74 return gTypes().Certificate
.typeID
;
76 END_SECAPI1(_kCFRuntimeNotATypeID
)
80 SecCertificateIsItemImplInstance(SecCertificateRef certificate
)
82 if (certificate
== NULL
) {
88 CFTypeID typeID
= CFGetTypeID(certificate
);
90 #if 0 /* debug code to verify type IDs */
91 syslog(LOG_ERR
, "SecCertificate typeID=%d [STU=%d, OSX=%d, SKI=%d]",
93 (int)SecCertificateGetTypeID(),
94 (int)SecCertificateGetTypeID_osx(),
95 (int)SecKeychainItemGetTypeID());
97 if (typeID
== _kCFRuntimeNotATypeID
) {
101 return (typeID
== SecCertificateGetTypeID_osx() ||
102 typeID
== SecKeychainItemGetTypeID()) ? true : false;
106 /* convert a new-world SecCertificateRef to an old-world ItemImpl instance */
108 SecCertificateCreateItemImplInstance(SecCertificateRef certificate
)
111 return (SecCertificateRef
)(certificate
? CFRetain(certificate
) : NULL
);
116 SecCertificateRef implCertRef
= (SecCertificateRef
) SecCertificateCopyKeychainItem(certificate
);
120 CFDataRef data
= SecCertificateCopyData(certificate
);
125 CSSM_DATA cssmCertData
;
126 cssmCertData
.Length
= (data
) ? (CSSM_SIZE
)CFDataGetLength(data
) : 0;
127 cssmCertData
.Data
= (data
) ? (uint8
*)CFDataGetBytePtr(data
) : NULL
;
129 SecPointer
<Certificate
> certificatePtr(new Certificate(cssmCertData
, CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
));
130 implCertRef
= certificatePtr
->handle();
138 /* convert an old-world ItemImpl instance to a new-world SecCertificateRef */
140 SecCertificateCreateFromItemImplInstance(SecCertificateRef certificate
)
143 return (SecCertificateRef
)(certificate
? CFRetain(certificate
) : NULL
);
148 SecCertificateRef result
= NULL
;
149 CFDataRef data
= NULL
;
151 CssmData certData
= Certificate::required(certificate
)->data();
152 if (certData
.Data
&& certData
.Length
) {
153 data
= CFDataCreate(NULL
, certData
.Data
, certData
.Length
);
156 if (certData
.Data
&& !certData
.Length
) {
157 /* zero-length certs can exist, so don't bother logging this */
160 syslog(LOG_ERR
, "WARNING: SecKeychainSearchCopyNext failed to retrieve certificate data (length=%ld, data=0x%lX)",
161 (long)certData
.Length
, (uintptr_t)certData
.Data
);
168 result
= SecCertificateCreateWithKeychainItem(NULL
, data
, certificate
);
177 SecCertificateSetKeychainItem(SecCertificateRef certificate
, CFTypeRef keychain_item
)
179 // pre-STU, this function is a no-op since it's the same item reference
180 return errSecSuccess
;
186 SecCertificateCopyKeychainItem(SecCertificateRef certificate
)
189 CFRetain(certificate
);
195 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
197 SecCertificateCreateFromData(const CSSM_DATA
*data
, CSSM_CERT_TYPE type
, CSSM_CERT_ENCODING encoding
, SecCertificateRef
*certificate
)
202 SecPointer
<Certificate
> certificatePtr(new Certificate(Required(data
), type
, encoding
));
203 Required(certificate
) = certificatePtr
->handle();
207 /* bridge to support old functionality */
208 if (!data
|| !data
->Data
|| !data
->Length
|| !certificate
) {
211 SecCertificateRef certRef
= NULL
;
213 // <rdar://problem/24403998> REG: Adobe {Photoshop, InDesign} CC(2015) crashes on launch
214 // If you take the length that SecKeychainItemCopyContent gives you (a Uint32) and assign it incorrectly
215 // to a CSSM_DATA Length field (a CSSM_SIZE, i.e., a size_t), the upper 32 bits aren't set. If those bits
216 // are non-zero, the length is incredibly wrong.
218 // Assume that there will not exist a certificate > 4GiB, and fake this length field.
219 CSSM_SIZE length
= data
->Length
& 0xfffffffful
;
221 CFDataRef dataRef
= CFDataCreate(NULL
, data
->Data
, length
);
223 certRef
= SecCertificateCreateWithData(NULL
, dataRef
);
226 *certificate
= certRef
;
227 return (certRef
) ? errSecSuccess
: errSecUnknownFormat
;
234 SecCertificateCreateWithData(CFAllocatorRef allocator
, CFDataRef data
)
236 SecCertificateRef certificate
= NULL
;
237 OSStatus __secapiresult
;
239 CSSM_DATA cssmCertData
;
240 cssmCertData
.Length
= (data
) ? (CSSM_SIZE
)CFDataGetLength(data
) : 0;
241 cssmCertData
.Data
= (data
) ? (uint8
*)CFDataGetBytePtr(data
) : NULL
;
243 //NOTE: there isn't yet a Certificate constructor which accepts a CFAllocatorRef
244 SecPointer
<Certificate
> certificatePtr(new Certificate(cssmCertData
, CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
));
245 certificate
= certificatePtr
->handle();
247 __secapiresult
=errSecSuccess
;
249 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
250 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
251 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
252 catch (...) { __secapiresult
=errSecInternalComponent
; }
257 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA) */
259 SecCertificateAddToKeychain(SecCertificateRef certificate
, SecKeychainRef keychain
)
261 // This macro creates an ItemImpl certificate if it does not exist
264 Item
item(Certificate::required(__itemImplRef
));
265 Keychain::optional(keychain
)->add(item
);
270 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
272 SecCertificateGetData(SecCertificateRef certificate
, CSSM_DATA_PTR data
)
277 Required(data
) = Certificate::required(certificate
)->data();
283 if (!certificate
|| !data
) {
284 __secapiresult
=errSecParam
;
286 else if (SecCertificateIsItemImplInstance(certificate
)) {
287 Required(data
) = Certificate::required(certificate
)->data();
290 data
->Length
= (CSSM_SIZE
)SecCertificateGetLength(certificate
);
291 data
->Data
= (uint8
*)SecCertificateGetBytePtr(certificate
);
301 SecCertificateCopyData(SecCertificateRef certificate
)
303 CFDataRef data
= NULL
;
304 OSStatus __secapiresult
= errSecSuccess
;
306 CssmData output
= Certificate::required(certificate
)->data();
307 CFIndex length
= (CFIndex
)output
.length();
308 const UInt8
*bytes
= (const UInt8
*)output
.data();
309 if (length
&& bytes
) {
310 data
= CFDataCreate(NULL
, bytes
, length
);
313 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
314 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
315 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
316 catch (...) { __secapiresult
=errSecInternalComponent
; }
324 SecCertificateCopySHA256Digest(SecCertificateRef certificate
)
326 CFDataRef data
= NULL
;
327 OSStatus __secapiresult
= errSecSuccess
;
329 data
= Certificate::required(certificate
)->sha256Hash();
334 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
335 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
336 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
337 catch (...) { __secapiresult
=errSecInternalComponent
; }
344 SecCertificateGetSHA1Digest(SecCertificateRef certificate
)
346 CFDataRef data
= NULL
;
347 OSStatus __secapiresult
= errSecSuccess
;
349 data
= Certificate::required(certificate
)->sha1Hash();
351 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
352 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
353 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
354 catch (...) { __secapiresult
=errSecInternalComponent
; }
361 SecCertificateCopyPublicKeySHA1Digest(SecCertificateRef certificate
)
363 CFDataRef data
= NULL
;
364 OSStatus __secapiresult
= errSecSuccess
;
366 CssmData output
= Certificate::required(certificate
)->publicKeyHash();
367 CFIndex length
= (CFIndex
)output
.length();
368 const UInt8
*bytes
= (const UInt8
*)output
.data();
369 if (length
&& bytes
) {
370 data
= CFDataCreate(NULL
, bytes
, length
);
373 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
374 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
375 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
376 catch (...) { __secapiresult
=errSecInternalComponent
; }
383 SecCertificateCopyDNSNames(SecCertificateRef certificate
)
385 CFArrayRef names
= NULL
;
386 OSStatus __secapiresult
= errSecSuccess
;
388 names
= Certificate::required(certificate
)->copyDNSNames();
390 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
391 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
392 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
393 catch (...) { __secapiresult
=errSecInternalComponent
; }
398 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
400 SecCertificateGetType(SecCertificateRef certificate
, CSSM_CERT_TYPE
*certificateType
)
402 // This macro creates an ItemImpl certificate if it does not exist
405 Required(certificateType
) = Certificate::required(__itemImplRef
)->type();
410 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
412 SecCertificateGetSubject(SecCertificateRef certificate
, const CSSM_X509_NAME
**subject
)
414 // This macro creates an ItemImpl certificate if it does not exist
417 Required(subject
) = Certificate::required(__itemImplRef
)->subjectName();
422 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
424 SecCertificateGetIssuer(SecCertificateRef certificate
, const CSSM_X509_NAME
**issuer
)
426 // This macro creates an ItemImpl certificate if it does not exist
429 Required(issuer
) = Certificate::required(__itemImplRef
)->issuerName();
434 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
436 SecCertificateGetCLHandle(SecCertificateRef certificate
, CSSM_CL_HANDLE
*clHandle
)
438 // This macro creates an ItemImpl certificate if it does not exist
441 Required(clHandle
) = Certificate::required(__itemImplRef
)->clHandle();
446 /* private function; assumes input is old-style ItemImpl certificate reference,
447 and does not release that certificate reference!
450 SecCertificateGetCLHandle_legacy(SecCertificateRef certificate
, CSSM_CL_HANDLE
*clHandle
)
454 Required(clHandle
) = Certificate::required(certificate
)->clHandle();
460 * Private API to infer a display name for a SecCertificateRef which
461 * may or may not be in a keychain.
466 SecCertificateInferLabel(SecCertificateRef certificate
, CFStringRef
*label
)
468 // This macro creates an ItemImpl certificate if it does not exist
471 Certificate::required(__itemImplRef
)->inferLabel(false, &Required(label
));
476 /* OS X only (note: iOS version has different arguments and return value) */
478 SecCertificateCopyPublicKey(SecCertificateRef certificate
, SecKeyRef
*key
)
480 // This macro creates an ItemImpl certificate if it does not exist
483 Required(key
) = Certificate::required(__itemImplRef
)->publicKey()->handle();
488 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
490 SecCertificateGetAlgorithmID(SecCertificateRef certificate
, const CSSM_X509_ALGORITHM_IDENTIFIER
**algid
)
492 // This macro creates an ItemImpl certificate if it does not exist
495 Required(algid
) = Certificate::required(__itemImplRef
)->algorithmID();
500 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA) */
502 SecCertificateCopyCommonName(SecCertificateRef certificate
, CFStringRef
*commonName
)
504 // This macro creates an ItemImpl certificate if it does not exist
507 Required(commonName
) = Certificate::required(__itemImplRef
)->commonName();
515 SecCertificateCopySubjectSummary(SecCertificateRef certificate
)
517 CFStringRef summary
= NULL
;
518 OSStatus __secapiresult
;
520 Certificate::required(certificate
)->inferLabel(false, &summary
);
522 __secapiresult
=errSecSuccess
;
524 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
525 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
526 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
527 catch (...) { __secapiresult
=errSecInternalComponent
; }
534 SecCertificateCopyIssuerSummary(SecCertificateRef certificate
)
536 CFStringRef issuerStr
= NULL
;
537 SecCertificateRefP certP
= NULL
;
538 CFDataRef certData
= SecCertificateCopyData(certificate
);
540 certP
= SecCertificateCreateWithDataP(NULL
, certData
);
544 issuerStr
= SecCertificateCopyIssuerSummaryP(certP
);
553 SecCertificateCopySubjectComponent(SecCertificateRef certificate
, const CSSM_OID
*component
, CFStringRef
*result
)
555 // This macro creates an ItemImpl certificate if it does not exist
558 Required(result
) = Certificate::required(__itemImplRef
)->distinguishedName(&CSSMOID_X509V1SubjectNameCStruct
, component
);
563 /* OS X only; deprecated SPI */
565 SecCertificateGetCommonName(SecCertificateRef certificate
, CFStringRef
*commonName
)
567 // deprecated SPI signature; replaced by SecCertificateCopyCommonName
568 return SecCertificateCopyCommonName(certificate
, commonName
);
571 /* OS X only; deprecated SPI */
573 SecCertificateGetEmailAddress(SecCertificateRef certificate
, CFStringRef
*emailAddress
)
575 // This macro creates an ItemImpl certificate if it does not exist
578 Required(emailAddress
) = Certificate::required(__itemImplRef
)->copyFirstEmailAddress();
585 SecCertificateCopyEmailAddresses(SecCertificateRef certificate
, CFArrayRef
*emailAddresses
)
587 // This macro creates an ItemImpl certificate if it does not exist
590 Required(emailAddresses
) = Certificate::required(__itemImplRef
)->copyEmailAddresses();
595 /* Return a zero terminated list of CSSM_DATA_PTR's with the values of the field specified by field.
596 * Caller must call releaseFieldValues to free the storage allocated by this call.
601 SecCertificateCopyFieldValues(SecCertificateRef certificate
, const CSSM_OID
*field
, CSSM_DATA_PTR
**fieldValues
)
603 // This macro creates an ItemImpl certificate if it does not exist
606 Required(fieldValues
) = Certificate::required(__itemImplRef
)->copyFieldValues(Required(field
));
613 SecCertificateReleaseFieldValues(SecCertificateRef certificate
, const CSSM_OID
*field
, CSSM_DATA_PTR
*fieldValues
)
615 // This macro creates an ItemImpl certificate if it does not exist
618 Certificate::required(__itemImplRef
)->releaseFieldValues(Required(field
), fieldValues
);
625 SecCertificateCopyFirstFieldValue(SecCertificateRef certificate
, const CSSM_OID
*field
, CSSM_DATA_PTR
*fieldValue
)
627 // This macro creates an ItemImpl certificate if it does not exist
630 Required(fieldValue
) = Certificate::required(__itemImplRef
)->copyFirstFieldValue(Required(field
));
637 SecCertificateReleaseFirstFieldValue(SecCertificateRef certificate
, const CSSM_OID
*field
, CSSM_DATA_PTR fieldValue
)
639 // This macro creates an ItemImpl certificate if it does not exist
642 Certificate::required(__itemImplRef
)->releaseFieldValue(Required(field
), fieldValue
);
649 SecCertificateFindByIssuerAndSN(CFTypeRef keychainOrArray
,const CSSM_DATA
*issuer
,
650 const CSSM_DATA
*serialNumber
, SecCertificateRef
*certificate
)
654 StorageManager::KeychainList keychains
;
655 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
656 Required(certificate
) = Certificate::findByIssuerAndSN(keychains
, CssmData::required(issuer
), CssmData::required(serialNumber
))->handle();
659 // convert ItemImpl-based SecCertificateRef to new-world version before returning
660 CssmData certData
= Certificate::required(*certificate
)->data();
661 CFRef
<CFDataRef
> cfData(CFDataCreate(NULL
, certData
.Data
, certData
.Length
));
662 SecCertificateRef tmpRef
= *certificate
;
663 *certificate
= SecCertificateCreateWithData(NULL
, cfData
);
672 SecCertificateFindBySubjectKeyID(CFTypeRef keychainOrArray
, const CSSM_DATA
*subjectKeyID
,
673 SecCertificateRef
*certificate
)
677 StorageManager::KeychainList keychains
;
678 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
679 Required(certificate
) = Certificate::findBySubjectKeyID(keychains
, CssmData::required(subjectKeyID
))->handle();
682 // convert ItemImpl-based SecCertificateRef to new-world version before returning
683 CssmData certData
= Certificate::required(*certificate
)->data();
684 CFRef
<CFDataRef
> cfData(CFDataCreate(NULL
, certData
.Data
, certData
.Length
));
685 SecCertificateRef tmpRef
= *certificate
;
686 *certificate
= SecCertificateCreateWithData(NULL
, cfData
);
695 SecCertificateFindByEmail(CFTypeRef keychainOrArray
, const char *emailAddress
, SecCertificateRef
*certificate
)
699 StorageManager::KeychainList keychains
;
700 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
701 Required(certificate
) = Certificate::findByEmail(keychains
, emailAddress
)->handle();
704 // convert ItemImpl-based SecCertificateRef to new-world version before returning
705 CssmData certData
= Certificate::required(*certificate
)->data();
706 CFRef
<CFDataRef
> cfData(CFDataCreate(NULL
, certData
.Data
, certData
.Length
));
707 SecCertificateRef tmpRef
= *certificate
;
708 *certificate
= SecCertificateCreateWithData(NULL
, cfData
);
717 SecKeychainSearchCreateForCertificateByIssuerAndSN(CFTypeRef keychainOrArray
, const CSSM_DATA
*issuer
,
718 const CSSM_DATA
*serialNumber
, SecKeychainSearchRef
*searchRef
)
724 StorageManager::KeychainList keychains
;
725 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
726 KCCursor
cursor(Certificate::cursorForIssuerAndSN(keychains
, CssmData::required(issuer
), CssmData::required(serialNumber
)));
727 *searchRef
= cursor
->handle();
734 SecKeychainSearchCreateForCertificateByIssuerAndSN_CF(CFTypeRef keychainOrArray
, CFDataRef issuer
,
735 CFDataRef serialNumber
, SecKeychainSearchRef
*searchRef
)
741 StorageManager::KeychainList keychains
;
742 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
744 Required(serialNumber
);
745 KCCursor
cursor(Certificate::cursorForIssuerAndSN_CF(keychains
, issuer
, serialNumber
));
746 *searchRef
= cursor
->handle();
753 SecKeychainSearchCreateForCertificateBySubjectKeyID(CFTypeRef keychainOrArray
, const CSSM_DATA
*subjectKeyID
,
754 SecKeychainSearchRef
*searchRef
)
760 StorageManager::KeychainList keychains
;
761 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
762 KCCursor
cursor(Certificate::cursorForSubjectKeyID(keychains
, CssmData::required(subjectKeyID
)));
763 *searchRef
= cursor
->handle();
770 SecKeychainSearchCreateForCertificateByEmail(CFTypeRef keychainOrArray
, const char *emailAddress
,
771 SecKeychainSearchRef
*searchRef
)
777 StorageManager::KeychainList keychains
;
778 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
779 KCCursor
cursor(Certificate::cursorForEmail(keychains
, emailAddress
));
780 *searchRef
= cursor
->handle();
787 SecDigestGetData (CSSM_ALGORITHMS alg
, CSSM_DATA
* digest
, const CSSM_DATA
* data
)
791 if (!digest
|| !digest
->Data
|| !digest
->Length
|| !data
|| !data
->Data
|| !data
->Length
)
794 CSP
csp(gGuidAppleCSP
);
795 Digest
context(csp
, alg
);
796 CssmData
input(data
->Data
, data
->Length
);
797 CssmData
output(digest
->Data
, digest
->Length
);
799 context
.digest(input
, output
);
800 digest
->Length
= output
.length();
807 /* determine whether a cert is self-signed */
808 OSStatus
SecCertificateIsSelfSigned(
809 SecCertificateRef certificate
,
810 Boolean
*isSelfSigned
) /* RETURNED */
814 *isSelfSigned
= Certificate::required(certificate
)->isSelfSigned();
820 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
822 SecCertificateCopyPreference(
824 CSSM_KEYUSE keyUsage
,
825 SecCertificateRef
*certificate
)
830 Required(certificate
);
831 StorageManager::KeychainList keychains
;
832 globals().storageManager
.getSearchList(keychains
);
833 KCCursor
cursor(keychains
, kSecGenericPasswordItemClass
, NULL
);
835 char idUTF8
[MAXPATHLEN
];
836 if (!CFStringGetCString(name
, idUTF8
, sizeof(idUTF8
)-1, kCFStringEncodingUTF8
))
837 idUTF8
[0] = (char)'\0';
838 CssmData
service(const_cast<char *>(idUTF8
), strlen(idUTF8
));
839 FourCharCode itemType
= 'cprf';
840 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecServiceItemAttr
), service
);
841 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecTypeItemAttr
), itemType
);
843 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecScriptCodeItemAttr
), (sint32
)keyUsage
);
846 if (!cursor
->next(prefItem
))
847 MacOSError::throwMe(errSecItemNotFound
);
849 // get persistent certificate reference
850 SecKeychainAttribute itemAttrs
[] = { { kSecGenericItemAttr
, 0, NULL
} };
851 SecKeychainAttributeList itemAttrList
= { sizeof(itemAttrs
) / sizeof(itemAttrs
[0]), itemAttrs
};
852 prefItem
->getContent(NULL
, &itemAttrList
, NULL
, NULL
);
854 // find certificate, given persistent reference data
855 CFDataRef pItemRef
= CFDataCreateWithBytesNoCopy(NULL
, (const UInt8
*)itemAttrs
[0].data
, itemAttrs
[0].length
, kCFAllocatorNull
);
856 SecKeychainItemRef certItemRef
= nil
;
857 OSStatus status
= SecKeychainItemCopyFromPersistentReference(pItemRef
, &certItemRef
); //%%% need to make this a method of ItemImpl
858 prefItem
->freeContent(&itemAttrList
, NULL
);
864 *certificate
= (SecCertificateRef
)certItemRef
;
867 if (certItemRef
&& (CFGetTypeID(certItemRef
) == SecIdentityGetTypeID())) {
868 // SecKeychainItemCopyFromPersistentReference handed out an identity reference
870 status
= SecIdentityCopyCertificate((SecIdentityRef
)certItemRef
, certificate
);
871 CFRelease(certItemRef
);
874 #if 0 /* SecKeychainItemCopyFromPersistentReference now does this work for us */
875 // convert ItemImpl-based SecCertificateRef to new-world version before returning
876 CssmData certData
= Certificate::required(*certificate
)->data();
877 CFRef
<CFDataRef
> cfData(CFDataCreate(NULL
, certData
.Data
, certData
.Length
));
878 SecCertificateRef tmpRef
= *certificate
;
879 *certificate
= SecCertificateCreateWithData(NULL
, cfData
);
889 SecCertificateCopyPreferred(
893 // This function will look for a matching preference in the following order:
894 // - matches the name and the supplied key use
895 // - matches the name and the special 'ANY' key use
896 // - matches the name with no key usage constraint
898 SecCertificateRef certRef
= NULL
;
899 CSSM_KEYUSE keyUse
= ConvertArrayToKeyUsage(keyUsage
);
900 OSStatus status
= SecCertificateCopyPreference(name
, keyUse
, &certRef
);
901 if (status
!= errSecSuccess
&& keyUse
!= CSSM_KEYUSE_ANY
)
902 status
= SecCertificateCopyPreference(name
, CSSM_KEYUSE_ANY
, &certRef
);
903 if (status
!= errSecSuccess
&& keyUse
!= 0)
904 status
= SecCertificateCopyPreference(name
, 0, &certRef
);
909 /* OS X only; not exported */
911 SecCertificateFindPreferenceItemWithNameAndKeyUsage(
912 CFTypeRef keychainOrArray
,
915 SecKeychainItemRef
*itemRef
)
919 StorageManager::KeychainList keychains
;
920 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
921 KCCursor
cursor(keychains
, kSecGenericPasswordItemClass
, NULL
);
923 char idUTF8
[MAXPATHLEN
];
924 idUTF8
[0] = (char)'\0';
927 if (!CFStringGetCString(name
, idUTF8
, sizeof(idUTF8
)-1, kCFStringEncodingUTF8
))
928 idUTF8
[0] = (char)'\0';
930 size_t idUTF8Len
= strlen(idUTF8
);
932 MacOSError::throwMe(errSecParam
);
934 CssmData
service(const_cast<char *>(idUTF8
), idUTF8Len
);
935 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecServiceItemAttr
), service
);
936 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecTypeItemAttr
), (FourCharCode
)'cprf');
938 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecScriptCodeItemAttr
), (sint32
)keyUsage
);
941 if (!cursor
->next(item
))
942 MacOSError::throwMe(errSecItemNotFound
);
945 *itemRef
=item
->handle();
950 /* OS X only; not exported */
952 OSStatus
SecCertificateDeletePreferenceItemWithNameAndKeyUsage(
953 CFTypeRef keychainOrArray
,
957 // when a specific key usage is passed, we'll only match & delete that pref;
958 // when a key usage of 0 is passed, all matching prefs should be deleted.
959 // maxUsages represents the most matches there could theoretically be, so
960 // cut things off at that point if we're still finding items (if they can't
961 // be deleted for some reason, we'd never break out of the loop.)
964 SecKeychainItemRef item
= NULL
;
965 int count
= 0, maxUsages
= 12;
966 while (++count
<= maxUsages
&&
967 (status
= SecCertificateFindPreferenceItemWithNameAndKeyUsage(keychainOrArray
, name
, keyUsage
, &item
)) == errSecSuccess
) {
968 status
= SecKeychainItemDelete(item
);
973 // it's not an error if the item isn't found
974 return (status
== errSecItemNotFound
) ? errSecSuccess
: status
;
977 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA) */
978 OSStatus
SecCertificateSetPreference(
979 SecCertificateRef certificate
,
981 CSSM_KEYUSE keyUsage
,
988 // treat NULL certificate as a request to clear the preference
989 // (note: if keyUsage is 0, this clears all key usage prefs for name)
990 return SecCertificateDeletePreferenceItemWithNameAndKeyUsage(NULL
, name
, keyUsage
);
993 // This macro creates an ItemImpl certificate if it does not exist
996 // determine the account attribute
998 // This attribute must be synthesized from certificate label + pref item type + key usage,
999 // as only the account and service attributes can make a generic keychain item unique.
1000 // For 'iprf' type items (but not 'cprf'), we append a trailing space. This insures that
1001 // we can save a certificate preference if an identity preference already exists for the
1002 // given service name, and vice-versa.
1003 // If the key usage is 0 (i.e. the normal case), we omit the appended key usage string.
1005 CFStringRef labelStr
= nil
;
1006 Certificate::required(__itemImplRef
)->inferLabel(false, &labelStr
);
1008 MacOSError::throwMe(errSecDataTooLarge
); // data is "in a format which cannot be displayed"
1010 CFIndex accountUTF8Len
= CFStringGetMaximumSizeForEncoding(CFStringGetLength(labelStr
), kCFStringEncodingUTF8
) + 1;
1011 const char *templateStr
= "%s [key usage 0x%X]";
1012 const int keyUsageMaxStrLen
= 8;
1013 accountUTF8Len
+= strlen(templateStr
) + keyUsageMaxStrLen
;
1014 char accountUTF8
[accountUTF8Len
];
1015 if (!CFStringGetCString(labelStr
, accountUTF8
, accountUTF8Len
-1, kCFStringEncodingUTF8
))
1016 accountUTF8
[0] = (char)'\0';
1018 snprintf(accountUTF8
, accountUTF8Len
-1, templateStr
, accountUTF8
, keyUsage
);
1019 CssmData
account(const_cast<char *>(accountUTF8
), strlen(accountUTF8
));
1020 CFRelease(labelStr
);
1022 // service attribute (name provided by the caller)
1023 CFIndex serviceUTF8Len
= CFStringGetMaximumSizeForEncoding(CFStringGetLength(name
), kCFStringEncodingUTF8
) + 1;;
1024 char serviceUTF8
[serviceUTF8Len
];
1025 if (!CFStringGetCString(name
, serviceUTF8
, serviceUTF8Len
-1, kCFStringEncodingUTF8
))
1026 serviceUTF8
[0] = (char)'\0';
1027 CssmData
service(const_cast<char *>(serviceUTF8
), strlen(serviceUTF8
));
1029 // look for existing preference item, in case this is an update
1030 StorageManager::KeychainList keychains
;
1031 globals().storageManager
.getSearchList(keychains
);
1032 KCCursor
cursor(keychains
, kSecGenericPasswordItemClass
, NULL
);
1033 FourCharCode itemType
= 'cprf';
1034 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecServiceItemAttr
), service
);
1035 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecTypeItemAttr
), itemType
);
1037 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecScriptCodeItemAttr
), (sint32
)keyUsage
);
1041 Item
item(kSecGenericPasswordItemClass
, 'aapl', 0, NULL
, false);
1042 bool add
= (!cursor
->next(item
));
1043 // at this point, we either have a new item to add or an existing item to update
1045 // set item attribute values
1046 item
->setAttribute(Schema::attributeInfo(kSecServiceItemAttr
), service
);
1047 item
->setAttribute(Schema::attributeInfo(kSecTypeItemAttr
), itemType
);
1048 item
->setAttribute(Schema::attributeInfo(kSecAccountItemAttr
), account
);
1049 item
->setAttribute(Schema::attributeInfo(kSecScriptCodeItemAttr
), (sint32
)keyUsage
);
1050 item
->setAttribute(Schema::attributeInfo(kSecLabelItemAttr
), service
);
1056 // generic attribute (store persistent certificate reference)
1057 CFDataRef pItemRef
= nil
;
1058 Certificate::required(__itemImplRef
)->copyPersistentReference(pItemRef
);
1060 MacOSError::throwMe(errSecInvalidItemRef
);
1062 const UInt8
*dataPtr
= CFDataGetBytePtr(pItemRef
);
1063 CFIndex dataLen
= CFDataGetLength(pItemRef
);
1064 CssmData
pref(const_cast<void *>(reinterpret_cast<const void *>(dataPtr
)), dataLen
);
1065 item
->setAttribute(Schema::attributeInfo(kSecGenericItemAttr
), pref
);
1066 CFRelease(pItemRef
);
1069 Keychain keychain
= nil
;
1071 keychain
= globals().storageManager
.defaultKeychain();
1072 if (!keychain
->exists())
1073 MacOSError::throwMe(errSecNoSuchKeychain
); // Might be deleted or not available at this time.
1076 keychain
= globals().storageManager
.defaultKeychainUI(item
);
1080 keychain
->add(item
);
1082 catch (const MacOSError
&err
) {
1083 if (err
.osStatus() != errSecDuplicateItem
)
1084 throw; // if item already exists, fall through to update
1092 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
1093 OSStatus
SecCertificateSetPreferred(
1094 SecCertificateRef certificate
,
1096 CFArrayRef keyUsage
)
1098 CSSM_KEYUSE keyUse
= ConvertArrayToKeyUsage(keyUsage
);
1099 return SecCertificateSetPreference(certificate
, name
, keyUse
, NULL
);
1102 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
1103 CFDictionaryRef
SecCertificateCopyValues(SecCertificateRef certificate
, CFArrayRef keys
, CFErrorRef
*error
)
1105 CFDictionaryRef result
= NULL
;
1106 OSStatus __secapiresult
;
1107 SecCertificateRef tmpcert
= NULL
;
1109 // convert input to a new-style certificate reference if necessary,
1110 // since the implementation of CertificateValues calls SecCertificate API functions
1111 // which now assume a unified certificate reference.
1112 if (SecCertificateIsItemImplInstance(certificate
)) {
1113 tmpcert
= SecCertificateCreateFromItemImplInstance(certificate
);
1116 if (certificate
&& !tmpcert
) {
1117 tmpcert
= (SecCertificateRef
) CFRetain(certificate
);
1121 CertificateValues
cv(tmpcert
);
1122 result
= cv
.copyFieldValues(keys
,error
);
1125 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1126 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1127 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1128 catch (...) { __secapiresult
=errSecInternalComponent
; }
1129 if (tmpcert
) { CFRelease(tmpcert
); }
1133 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
1134 CFStringRef
SecCertificateCopyLongDescription(CFAllocatorRef alloc
, SecCertificateRef certificate
, CFErrorRef
*error
)
1136 return SecCertificateCopyShortDescription(alloc
, certificate
, error
);
1139 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
1140 CFStringRef
SecCertificateCopyShortDescription(CFAllocatorRef alloc
, SecCertificateRef certificate
, CFErrorRef
*error
)
1142 CFStringRef result
= NULL
;
1143 OSStatus __secapiresult
= SecCertificateInferLabel(certificate
, &result
);
1144 if (error
!=NULL
&& __secapiresult
!=errSecSuccess
)
1146 *error
= CFErrorCreate(kCFAllocatorDefault
, kCFErrorDomainOSStatus
,
1147 __secapiresult
? __secapiresult
: CSSM_ERRCODE_INTERNAL_ERROR
, NULL
);
1152 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
1153 CFDataRef
SecCertificateCopySerialNumber(SecCertificateRef certificate
, CFErrorRef
*error
)
1155 CFDataRef result
= NULL
;
1156 OSStatus __secapiresult
;
1159 CertificateValues
cv(certificate
);
1160 result
= cv
.copySerialNumber(error
);
1163 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1164 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1165 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1166 catch (...) { __secapiresult
=errSecInternalComponent
; }
1170 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
1171 CFDataRef
SecCertificateCopyNormalizedIssuerContent(SecCertificateRef certificate
, CFErrorRef
*error
)
1173 CFDataRef result
= NULL
;
1174 OSStatus __secapiresult
;
1177 CertificateValues
cv(certificate
);
1178 result
= cv
.copyNormalizedIssuerContent(error
);
1181 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1182 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1183 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1184 catch (...) { __secapiresult
=errSecInternalComponent
; }
1188 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
1189 CFDataRef
SecCertificateCopyNormalizedSubjectContent(SecCertificateRef certificate
, CFErrorRef
*error
)
1191 CFDataRef result
= NULL
;
1192 OSStatus __secapiresult
;
1195 CertificateValues
cv(certificate
);
1196 result
= cv
.copyNormalizedSubjectContent(error
);
1199 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1200 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1201 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1202 catch (...) { __secapiresult
=errSecInternalComponent
; }
1207 CFDataRef
SecCertificateCopyIssuerSequence(SecCertificateRef certificate
)
1209 CFDataRef result
= NULL
;
1210 OSStatus __secapiresult
;
1213 CertificateValues
cv(certificate
);
1214 result
= cv
.copyIssuerSequence(NULL
);
1217 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1218 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1219 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1220 catch (...) { __secapiresult
=errSecInternalComponent
; }
1226 CFDataRef
SecCertificateCopySubjectSequence(SecCertificateRef certificate
)
1228 CFDataRef result
= NULL
;
1229 OSStatus __secapiresult
;
1232 CertificateValues
cv(certificate
);
1233 result
= cv
.copySubjectSequence(NULL
);
1236 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1237 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1238 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1239 catch (...) { __secapiresult
=errSecInternalComponent
; }
1245 CFDictionaryRef
SecCertificateCopyAttributeDictionary(SecCertificateRef certificate
)
1247 CFDictionaryRef result
= NULL
;
1251 CertificateValues
cv(certificate
);
1252 result
= cv
.copyAttributeDictionary(NULL
);
1255 catch (const MacOSError
&err
) { status
=err
.osStatus(); }
1256 catch (const CommonError
&err
) { status
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1257 catch (const std::bad_alloc
&) { status
=errSecAllocate
; }
1258 catch (...) { status
=errSecInternalComponent
; }
1265 bool SecCertificateIsValid(SecCertificateRef certificate
, CFAbsoluteTime verifyTime
)
1268 OSStatus __secapiresult
;
1271 CFErrorRef error
= NULL
;
1272 CertificateValues
cv(certificate
);
1273 result
= cv
.isValid(verifyTime
, &error
);
1274 if (error
) CFRelease(error
);
1277 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1278 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1279 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1280 catch (...) { __secapiresult
=errSecInternalComponent
; }
1285 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_9, __IPHONE_NA, __IPHONE_NA) */
1286 bool SecCertificateIsValidX(SecCertificateRef certificate
, CFAbsoluteTime verifyTime
)
1289 * deprecated function name
1291 return SecCertificateIsValid(certificate
, verifyTime
);
1295 CFAbsoluteTime
SecCertificateNotValidBefore(SecCertificateRef certificate
)
1297 CFAbsoluteTime result
= 0;
1298 OSStatus __secapiresult
;
1301 CFErrorRef error
= NULL
;
1302 CertificateValues
cv(certificate
);
1303 result
= cv
.notValidBefore(&error
);
1304 if (error
) CFRelease(error
);
1307 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1308 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1309 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1310 catch (...) { __secapiresult
=errSecInternalComponent
; }
1316 CFAbsoluteTime
SecCertificateNotValidAfter(SecCertificateRef certificate
)
1318 CFAbsoluteTime result
= 0;
1319 OSStatus __secapiresult
;
1322 CFErrorRef error
= NULL
;
1323 CertificateValues
cv(certificate
);
1324 result
= cv
.notValidAfter(&error
);
1325 if (error
) CFRelease(error
);
1328 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1329 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1330 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1331 catch (...) { __secapiresult
=errSecInternalComponent
; }
1338 SecCertificateRef
SecCertificateCreateWithBytes(CFAllocatorRef allocator
,
1339 const UInt8
*bytes
, CFIndex length
)
1341 SecCertificateRef certificate
= NULL
;
1342 OSStatus __secapiresult
;
1344 CSSM_DATA cssmCertData
= { (CSSM_SIZE
)length
, (uint8
*)bytes
};
1346 //NOTE: there isn't yet a Certificate constructor which accepts a CFAllocatorRef
1347 SecPointer
<Certificate
> certificatePtr(new Certificate(cssmCertData
, CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
));
1348 certificate
= certificatePtr
->handle();
1350 __secapiresult
=errSecSuccess
;
1352 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1353 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1354 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1355 catch (...) { __secapiresult
=errSecInternalComponent
; }
1362 CFIndex
SecCertificateGetLength(SecCertificateRef certificate
)
1365 OSStatus __secapiresult
;
1367 CssmData output
= Certificate::required(certificate
)->data();
1368 length
= (CFIndex
)output
.length();
1369 __secapiresult
=errSecSuccess
;
1371 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1372 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1373 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1374 catch (...) { __secapiresult
=errSecInternalComponent
; }
1381 const UInt8
*SecCertificateGetBytePtr(SecCertificateRef certificate
)
1383 const UInt8
*bytes
= NULL
;
1384 OSStatus __secapiresult
;
1386 CssmData output
= Certificate::required(certificate
)->data();
1387 bytes
= (const UInt8
*)output
.data();
1388 __secapiresult
=errSecSuccess
;
1390 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1391 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1392 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1393 catch (...) { __secapiresult
=errSecInternalComponent
; }
1400 static CFArrayRef
CopyEscrowCertificates(SecCertificateEscrowRootType escrowRootType
, CFErrorRef
*error
)
1402 // Return array of CFDataRef certificates.
1403 CFArrayRef result
= NULL
;
1407 // Get the hard coded set of production roots
1408 // static struct RootRecord* kProductionEscrowRoots[] = {&kOldEscrowRootRecord, &kProductionEscrowRootRecord};
1410 struct RootRecord
** pEscrowRoots
= NULL
;
1411 switch (escrowRootType
) {
1412 case kSecCertificateBaselineEscrowRoot
:
1413 numRoots
= kNumberOfBaseLineEscrowRoots
;
1414 pEscrowRoots
= kBaseLineEscrowRoots
;
1416 case kSecCertificateProductionEscrowRoot
:
1417 numRoots
= kNumberOfBaseLineEscrowRoots
; //%%% currently, production == baseline on OS X
1418 pEscrowRoots
= kBaseLineEscrowRoots
;
1420 case kSecCertificateBaselinePCSEscrowRoot
:
1421 numRoots
= kNumberOfBaseLinePCSEscrowRoots
;
1422 pEscrowRoots
= kBaseLinePCSEscrowRoots
;
1424 case kSecCertificateProductionPCSEscrowRoot
:
1425 numRoots
= kNumberOfBaseLinePCSEscrowRoots
; //%%% currently, production == baseline on OS X
1426 pEscrowRoots
= kBaseLinePCSEscrowRoots
;
1432 CFDataRef productionCerts
[numRoots
];
1433 struct RootRecord
* pRootRecord
= NULL
;
1435 for (iCnt
= 0; pEscrowRoots
!= NULL
&& iCnt
< numRoots
; iCnt
++)
1437 pRootRecord
= pEscrowRoots
[iCnt
];
1438 if (NULL
!= pRootRecord
&& pRootRecord
->_length
> 0 && NULL
!= pRootRecord
->_bytes
)
1440 productionCerts
[iCnt
] = CFDataCreate(kCFAllocatorDefault
, pRootRecord
->_bytes
, pRootRecord
->_length
);
1443 result
= CFArrayCreate(kCFAllocatorDefault
, (const void **)productionCerts
, numRoots
, &kCFTypeArrayCallBacks
);
1444 for (iCnt
= 0; iCnt
< numRoots
; iCnt
++)
1446 if (NULL
!= productionCerts
[iCnt
])
1448 CFRelease(productionCerts
[iCnt
]);
1458 CFArrayRef
SecCertificateCopyEscrowRoots(SecCertificateEscrowRootType escrowRootType
)
1460 CFArrayRef result
= NULL
;
1463 CFDataRef certData
= NULL
;
1465 // The request is for the base line certificates.
1466 // Use the hard coded data to generate the return array
1467 if (kSecCertificateBaselineEscrowRoot
== escrowRootType
)
1469 // Get the hard coded set of roots
1470 numRoots
= kNumberOfBaseLineEscrowRoots
;
1471 SecCertificateRef baseLineCerts
[numRoots
];
1472 struct RootRecord
* pRootRecord
= NULL
;
1474 for (iCnt
= 0; iCnt
< numRoots
; iCnt
++)
1476 pRootRecord
= kBaseLineEscrowRoots
[iCnt
];
1477 if (NULL
!= pRootRecord
&& pRootRecord
->_length
> 0 && NULL
!= pRootRecord
->_bytes
)
1479 certData
= CFDataCreate(kCFAllocatorDefault
, pRootRecord
->_bytes
, pRootRecord
->_length
);
1480 if (NULL
!= certData
)
1482 baseLineCerts
[iCnt
] = SecCertificateCreateWithData(kCFAllocatorDefault
, certData
);
1483 CFRelease(certData
);
1487 result
= CFArrayCreate(kCFAllocatorDefault
, (const void **)baseLineCerts
, numRoots
, &kCFTypeArrayCallBacks
);
1488 for (iCnt
= 0; iCnt
< numRoots
; iCnt
++)
1490 if (NULL
!= baseLineCerts
[iCnt
])
1492 CFRelease(baseLineCerts
[iCnt
]);
1496 // The request is for the current certificates.
1499 CFErrorRef error
= NULL
;
1500 CFArrayRef cert_datas
= CopyEscrowCertificates(escrowRootType
, &error
);
1501 if (NULL
!= error
|| NULL
== cert_datas
|| 0 == (numRoots
= (int)CFArrayGetCount(cert_datas
)))
1508 if (NULL
!= cert_datas
)
1510 CFRelease(cert_datas
);
1515 SecCertificateRef assetCerts
[numRoots
];
1516 for (iCnt
= 0; iCnt
< numRoots
; iCnt
++)
1518 certData
= (CFDataRef
)CFArrayGetValueAtIndex(cert_datas
, iCnt
);
1519 if (NULL
!= certData
)
1521 SecCertificateRef aCertRef
= SecCertificateCreateWithData(kCFAllocatorDefault
, certData
);
1522 assetCerts
[iCnt
] = aCertRef
;
1526 assetCerts
[iCnt
] = NULL
;
1532 result
= CFArrayCreate(kCFAllocatorDefault
, (const void **)assetCerts
, numRoots
, &kCFTypeArrayCallBacks
);
1533 for (iCnt
= 0; iCnt
< numRoots
; iCnt
++)
1535 if (NULL
!= assetCerts
[iCnt
])
1537 CFRelease(assetCerts
[iCnt
]);
1541 CFRelease(cert_datas
);
1550 SecSignatureHashAlgorithm
SecCertificateGetSignatureHashAlgorithm(SecCertificateRef certificate
)
1552 SecSignatureHashAlgorithm result
= kSecSignatureHashAlgorithmUnknown
;
1553 CSSM_X509_ALGORITHM_IDENTIFIER_PTR algId
= NULL
;
1554 CSSM_DATA_PTR fieldValue
= NULL
;
1555 CSSM_OID_PTR algOID
= NULL
;
1556 const CSSM_OID
*sigAlgOID
= &CSSMOID_X509V1SignatureAlgorithm
;
1559 status
= SecCertificateCopyFirstFieldValue(certificate
, sigAlgOID
, &fieldValue
);
1560 if (status
|| !fieldValue
) {
1563 algId
= (CSSM_X509_ALGORITHM_IDENTIFIER_PTR
)fieldValue
->Data
;
1564 algOID
= (algId
) ? &algId
->algorithm
: NULL
;
1567 if (!algOID
->Data
|| !algOID
->Length
) {
1570 /* classify the signature algorithm OID into one of our known types */
1571 if (cuCompareCssmData(algOID
, &CSSMOID_ECDSA_WithSHA512
) ||
1572 cuCompareCssmData(algOID
, &CSSMOID_SHA512WithRSA
) ||
1573 cuCompareCssmData(algOID
, &CSSMOID_SHA512
)) {
1574 result
= kSecSignatureHashAlgorithmSHA512
;
1577 if (cuCompareCssmData(algOID
, &CSSMOID_ECDSA_WithSHA384
) ||
1578 cuCompareCssmData(algOID
, &CSSMOID_SHA384WithRSA
) ||
1579 cuCompareCssmData(algOID
, &CSSMOID_SHA384
)) {
1580 result
= kSecSignatureHashAlgorithmSHA384
;
1583 if (cuCompareCssmData(algOID
, &CSSMOID_ECDSA_WithSHA256
) ||
1584 cuCompareCssmData(algOID
, &CSSMOID_SHA256WithRSA
) ||
1585 cuCompareCssmData(algOID
, &CSSMOID_SHA256
)) {
1586 result
= kSecSignatureHashAlgorithmSHA256
;
1589 if (cuCompareCssmData(algOID
, &CSSMOID_ECDSA_WithSHA224
) ||
1590 cuCompareCssmData(algOID
, &CSSMOID_SHA224WithRSA
) ||
1591 cuCompareCssmData(algOID
, &CSSMOID_SHA224
)) {
1592 result
= kSecSignatureHashAlgorithmSHA224
;
1595 if (cuCompareCssmData(algOID
, &CSSMOID_ECDSA_WithSHA1
) ||
1596 cuCompareCssmData(algOID
, &CSSMOID_SHA1WithRSA
) ||
1597 cuCompareCssmData(algOID
, &CSSMOID_SHA1WithDSA
) ||
1598 cuCompareCssmData(algOID
, &CSSMOID_SHA1WithDSA_CMS
) ||
1599 cuCompareCssmData(algOID
, &CSSMOID_SHA1WithDSA_JDK
) ||
1600 cuCompareCssmData(algOID
, &CSSMOID_SHA1WithRSA_OIW
) ||
1601 cuCompareCssmData(algOID
, &CSSMOID_APPLE_FEE_SHA1
) ||
1602 cuCompareCssmData(algOID
, &CSSMOID_SHA1
)) {
1603 result
= kSecSignatureHashAlgorithmSHA1
;
1606 if (cuCompareCssmData(algOID
, &CSSMOID_MD5WithRSA
) ||
1607 cuCompareCssmData(algOID
, &CSSMOID_APPLE_FEE_MD5
) ||
1608 cuCompareCssmData(algOID
, &CSSMOID_MD5
)) {
1609 result
= kSecSignatureHashAlgorithmMD5
;
1612 if (cuCompareCssmData(algOID
, &CSSMOID_MD4WithRSA
) ||
1613 cuCompareCssmData(algOID
, &CSSMOID_MD4
)) {
1614 result
= kSecSignatureHashAlgorithmMD4
;
1617 if (cuCompareCssmData(algOID
, &CSSMOID_MD2WithRSA
) ||
1618 cuCompareCssmData(algOID
, &CSSMOID_MD2
)) {
1619 result
= kSecSignatureHashAlgorithmMD2
;
1625 (void)SecCertificateReleaseFirstFieldValue(certificate
, sigAlgOID
, fieldValue
);