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/SecItemPriv.h>
42 #include <security_keychain/KCCursor.h>
43 #include <security_cdsa_utilities/Schema.h>
44 #include <security_cdsa_utils/cuCdsaUtils.h>
45 #include <sys/param.h>
47 #include "CertificateValues.h"
48 #include "SecCertificateP.h"
49 #include "SecCertificatePrivP.h"
51 #include "AppleBaselineEscrowCertificates.h"
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 static SecCertificateGetTypeID_osx(void)
70 SecCertificateGetTypeID(void)
75 return gTypes().Certificate
.typeID
;
77 END_SECAPI1(_kCFRuntimeNotATypeID
)
81 SecCertificateIsItemImplInstance(SecCertificateRef certificate
)
83 if (certificate
== NULL
) {
89 CFTypeID typeID
= CFGetTypeID(certificate
);
91 #if 0 /* debug code to verify type IDs */
92 syslog(LOG_ERR
, "SecCertificate typeID=%d [STU=%d, OSX=%d, SKI=%d]",
94 (int)SecCertificateGetTypeID(),
95 (int)SecCertificateGetTypeID_osx(),
96 (int)SecKeychainItemGetTypeID());
98 if (typeID
== _kCFRuntimeNotATypeID
) {
102 return (typeID
== SecCertificateGetTypeID_osx() ||
103 typeID
== SecKeychainItemGetTypeID()) ? true : false;
107 /* convert a new-world SecCertificateRef to an old-world ItemImpl instance */
109 SecCertificateCreateItemImplInstance(SecCertificateRef certificate
)
112 return (SecCertificateRef
)(certificate
? CFRetain(certificate
) : NULL
);
117 SecCertificateRef implCertRef
= (SecCertificateRef
) SecCertificateCopyKeychainItem(certificate
);
121 CFDataRef data
= SecCertificateCopyData(certificate
);
126 CSSM_DATA cssmCertData
;
127 cssmCertData
.Length
= (data
) ? (CSSM_SIZE
)CFDataGetLength(data
) : 0;
128 cssmCertData
.Data
= (data
) ? (uint8
*)CFDataGetBytePtr(data
) : NULL
;
130 SecPointer
<Certificate
> certificatePtr(new Certificate(cssmCertData
, CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
));
131 implCertRef
= certificatePtr
->handle();
139 /* convert an old-world ItemImpl instance to a new-world SecCertificateRef */
141 SecCertificateCreateFromItemImplInstance(SecCertificateRef certificate
)
144 return (SecCertificateRef
)(certificate
? CFRetain(certificate
) : NULL
);
149 SecCertificateRef result
= NULL
;
150 CFDataRef data
= NULL
;
152 CssmData certData
= Certificate::required(certificate
)->data();
153 if (certData
.Data
&& certData
.Length
) {
154 data
= CFDataCreate(NULL
, certData
.Data
, certData
.Length
);
157 if (certData
.Data
&& !certData
.Length
) {
158 /* zero-length certs can exist, so don't bother logging this */
161 syslog(LOG_ERR
, "WARNING: SecKeychainSearchCopyNext failed to retrieve certificate data (length=%ld, data=0x%lX)",
162 (long)certData
.Length
, (uintptr_t)certData
.Data
);
169 result
= SecCertificateCreateWithKeychainItem(NULL
, data
, certificate
);
178 SecCertificateSetKeychainItem(SecCertificateRef certificate
, CFTypeRef keychain_item
)
180 // pre-STU, this function is a no-op since it's the same item reference
181 return errSecSuccess
;
187 SecCertificateCopyKeychainItem(SecCertificateRef certificate
)
190 CFRetain(certificate
);
196 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
198 SecCertificateCreateFromData(const CSSM_DATA
*data
, CSSM_CERT_TYPE type
, CSSM_CERT_ENCODING encoding
, SecCertificateRef
*certificate
)
203 SecPointer
<Certificate
> certificatePtr(new Certificate(Required(data
), type
, encoding
));
204 Required(certificate
) = certificatePtr
->handle();
208 /* bridge to support old functionality */
209 if (!data
|| !data
->Data
|| !data
->Length
|| !certificate
) {
212 SecCertificateRef certRef
= NULL
;
214 // <rdar://problem/24403998> REG: Adobe {Photoshop, InDesign} CC(2015) crashes on launch
215 // If you take the length that SecKeychainItemCopyContent gives you (a Uint32) and assign it incorrectly
216 // to a CSSM_DATA Length field (a CSSM_SIZE, i.e., a size_t), the upper 32 bits aren't set. If those bits
217 // are non-zero, the length is incredibly wrong.
219 // Assume that there will not exist a certificate > 4GiB, and fake this length field.
220 CSSM_SIZE length
= data
->Length
& 0xfffffffful
;
222 CFDataRef dataRef
= CFDataCreate(NULL
, data
->Data
, length
);
224 certRef
= SecCertificateCreateWithData(NULL
, dataRef
);
227 *certificate
= certRef
;
228 return (certRef
) ? errSecSuccess
: errSecUnknownFormat
;
235 SecCertificateCreateWithData(CFAllocatorRef allocator
, CFDataRef data
)
237 SecCertificateRef certificate
= NULL
;
238 OSStatus __secapiresult
;
240 CSSM_DATA cssmCertData
;
241 cssmCertData
.Length
= (data
) ? (CSSM_SIZE
)CFDataGetLength(data
) : 0;
242 cssmCertData
.Data
= (data
) ? (uint8
*)CFDataGetBytePtr(data
) : NULL
;
244 //NOTE: there isn't yet a Certificate constructor which accepts a CFAllocatorRef
245 SecPointer
<Certificate
> certificatePtr(new Certificate(cssmCertData
, CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
));
246 certificate
= certificatePtr
->handle();
248 __secapiresult
=errSecSuccess
;
250 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
251 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
252 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
253 catch (...) { __secapiresult
=errSecInternalComponent
; }
258 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA) */
260 SecCertificateAddToKeychain(SecCertificateRef certificate
, SecKeychainRef keychain
)
262 // This macro creates an ItemImpl certificate if it does not exist
265 Item
item(Certificate::required(__itemImplRef
));
266 Keychain::optional(keychain
)->add(item
);
271 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
273 SecCertificateGetData(SecCertificateRef certificate
, CSSM_DATA_PTR data
)
278 Required(data
) = Certificate::required(certificate
)->data();
284 if (!certificate
|| !data
) {
285 __secapiresult
=errSecParam
;
287 else if (SecCertificateIsItemImplInstance(certificate
)) {
288 Required(data
) = Certificate::required(certificate
)->data();
291 data
->Length
= (CSSM_SIZE
)SecCertificateGetLength(certificate
);
292 data
->Data
= (uint8
*)SecCertificateGetBytePtr(certificate
);
302 SecCertificateCopyData(SecCertificateRef certificate
)
304 CFDataRef data
= NULL
;
305 OSStatus __secapiresult
= errSecSuccess
;
307 CssmData output
= Certificate::required(certificate
)->data();
308 CFIndex length
= (CFIndex
)output
.length();
309 const UInt8
*bytes
= (const UInt8
*)output
.data();
310 if (length
&& bytes
) {
311 data
= CFDataCreate(NULL
, bytes
, length
);
314 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
315 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
316 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
317 catch (...) { __secapiresult
=errSecInternalComponent
; }
325 SecCertificateCopySHA256Digest(SecCertificateRef certificate
)
327 CFDataRef data
= NULL
;
328 OSStatus __secapiresult
= errSecSuccess
;
330 data
= Certificate::required(certificate
)->sha256Hash();
335 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
336 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
337 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
338 catch (...) { __secapiresult
=errSecInternalComponent
; }
345 SecCertificateGetSHA1Digest(SecCertificateRef certificate
)
347 CFDataRef data
= NULL
;
348 OSStatus __secapiresult
= errSecSuccess
;
350 data
= Certificate::required(certificate
)->sha1Hash();
352 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
353 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
354 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
355 catch (...) { __secapiresult
=errSecInternalComponent
; }
362 SecCertificateCopyPublicKeySHA1Digest(SecCertificateRef certificate
)
364 CFDataRef data
= NULL
;
365 OSStatus __secapiresult
= errSecSuccess
;
367 CssmData output
= Certificate::required(certificate
)->publicKeyHash();
368 CFIndex length
= (CFIndex
)output
.length();
369 const UInt8
*bytes
= (const UInt8
*)output
.data();
370 if (length
&& bytes
) {
371 data
= CFDataCreate(NULL
, bytes
, length
);
374 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
375 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
376 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
377 catch (...) { __secapiresult
=errSecInternalComponent
; }
384 SecCertificateCopyDNSNames(SecCertificateRef certificate
)
386 CFArrayRef names
= NULL
;
387 OSStatus __secapiresult
= errSecSuccess
;
389 names
= Certificate::required(certificate
)->copyDNSNames();
391 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
392 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
393 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
394 catch (...) { __secapiresult
=errSecInternalComponent
; }
399 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
401 SecCertificateGetType(SecCertificateRef certificate
, CSSM_CERT_TYPE
*certificateType
)
403 // This macro creates an ItemImpl certificate if it does not exist
406 Required(certificateType
) = Certificate::required(__itemImplRef
)->type();
411 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
413 SecCertificateGetSubject(SecCertificateRef certificate
, const CSSM_X509_NAME
**subject
)
415 // This macro creates an ItemImpl certificate if it does not exist
418 Required(subject
) = Certificate::required(__itemImplRef
)->subjectName();
423 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
425 SecCertificateGetIssuer(SecCertificateRef certificate
, const CSSM_X509_NAME
**issuer
)
427 // This macro creates an ItemImpl certificate if it does not exist
430 Required(issuer
) = Certificate::required(__itemImplRef
)->issuerName();
435 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
437 SecCertificateGetCLHandle(SecCertificateRef certificate
, CSSM_CL_HANDLE
*clHandle
)
439 // This macro creates an ItemImpl certificate if it does not exist
442 Required(clHandle
) = Certificate::required(__itemImplRef
)->clHandle();
447 /* private function; assumes input is old-style ItemImpl certificate reference,
448 and does not release that certificate reference!
451 SecCertificateGetCLHandle_legacy(SecCertificateRef certificate
, CSSM_CL_HANDLE
*clHandle
)
455 Required(clHandle
) = Certificate::required(certificate
)->clHandle();
461 * Private API to infer a display name for a SecCertificateRef which
462 * may or may not be in a keychain.
467 SecCertificateInferLabel(SecCertificateRef certificate
, CFStringRef
*label
)
469 // This macro creates an ItemImpl certificate if it does not exist
472 Certificate::required(__itemImplRef
)->inferLabel(false, &Required(label
));
477 /* OS X only (note: iOS version has different arguments and return value) */
479 SecCertificateCopyPublicKey(SecCertificateRef certificate
, SecKeyRef
*key
)
481 // This macro creates an ItemImpl certificate if it does not exist
484 Required(key
) = Certificate::required(__itemImplRef
)->publicKey()->handle();
489 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
491 SecCertificateGetAlgorithmID(SecCertificateRef certificate
, const CSSM_X509_ALGORITHM_IDENTIFIER
**algid
)
493 // This macro creates an ItemImpl certificate if it does not exist
496 Required(algid
) = Certificate::required(__itemImplRef
)->algorithmID();
501 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA) */
503 SecCertificateCopyCommonName(SecCertificateRef certificate
, CFStringRef
*commonName
)
505 // This macro creates an ItemImpl certificate if it does not exist
508 Required(commonName
) = Certificate::required(__itemImplRef
)->commonName();
516 SecCertificateCopySubjectSummary(SecCertificateRef certificate
)
518 CFStringRef summary
= NULL
;
519 OSStatus __secapiresult
;
521 Certificate::required(certificate
)->inferLabel(false, &summary
);
523 __secapiresult
=errSecSuccess
;
525 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
526 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
527 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
528 catch (...) { __secapiresult
=errSecInternalComponent
; }
535 SecCertificateCopyIssuerSummary(SecCertificateRef certificate
)
537 CFStringRef issuerStr
= NULL
;
538 SecCertificateRefP certP
= NULL
;
539 CFDataRef certData
= SecCertificateCopyData(certificate
);
541 certP
= SecCertificateCreateWithDataP(NULL
, certData
);
545 issuerStr
= SecCertificateCopyIssuerSummaryP(certP
);
554 SecCertificateCopySubjectComponent(SecCertificateRef certificate
, const CSSM_OID
*component
, CFStringRef
*result
)
556 // This macro creates an ItemImpl certificate if it does not exist
559 Required(result
) = Certificate::required(__itemImplRef
)->distinguishedName(&CSSMOID_X509V1SubjectNameCStruct
, component
);
564 /* OS X only; deprecated SPI */
566 SecCertificateGetCommonName(SecCertificateRef certificate
, CFStringRef
*commonName
)
568 // deprecated SPI signature; replaced by SecCertificateCopyCommonName
569 return SecCertificateCopyCommonName(certificate
, commonName
);
572 /* OS X only; deprecated SPI */
574 SecCertificateGetEmailAddress(SecCertificateRef certificate
, CFStringRef
*emailAddress
)
576 // This macro creates an ItemImpl certificate if it does not exist
579 Required(emailAddress
) = Certificate::required(__itemImplRef
)->copyFirstEmailAddress();
586 SecCertificateCopyEmailAddresses(SecCertificateRef certificate
, CFArrayRef
*emailAddresses
)
588 // This macro creates an ItemImpl certificate if it does not exist
591 Required(emailAddresses
) = Certificate::required(__itemImplRef
)->copyEmailAddresses();
596 /* Return a zero terminated list of CSSM_DATA_PTR's with the values of the field specified by field.
597 * Caller must call releaseFieldValues to free the storage allocated by this call.
602 SecCertificateCopyFieldValues(SecCertificateRef certificate
, const CSSM_OID
*field
, CSSM_DATA_PTR
**fieldValues
)
604 // This macro creates an ItemImpl certificate if it does not exist
607 Required(fieldValues
) = Certificate::required(__itemImplRef
)->copyFieldValues(Required(field
));
614 SecCertificateReleaseFieldValues(SecCertificateRef certificate
, const CSSM_OID
*field
, CSSM_DATA_PTR
*fieldValues
)
616 // This macro creates an ItemImpl certificate if it does not exist
619 Certificate::required(__itemImplRef
)->releaseFieldValues(Required(field
), fieldValues
);
626 SecCertificateCopyFirstFieldValue(SecCertificateRef certificate
, const CSSM_OID
*field
, CSSM_DATA_PTR
*fieldValue
)
628 // This macro creates an ItemImpl certificate if it does not exist
631 Required(fieldValue
) = Certificate::required(__itemImplRef
)->copyFirstFieldValue(Required(field
));
638 SecCertificateReleaseFirstFieldValue(SecCertificateRef certificate
, const CSSM_OID
*field
, CSSM_DATA_PTR fieldValue
)
640 // This macro creates an ItemImpl certificate if it does not exist
643 Certificate::required(__itemImplRef
)->releaseFieldValue(Required(field
), fieldValue
);
650 SecCertificateFindByIssuerAndSN(CFTypeRef keychainOrArray
,const CSSM_DATA
*issuer
,
651 const CSSM_DATA
*serialNumber
, SecCertificateRef
*certificate
)
653 if (issuer
&& serialNumber
) {
654 CFRef
<CFMutableDictionaryRef
> query
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
655 CFDictionarySetValue(query
, kSecClass
, kSecClassCertificate
);
656 CFDictionarySetValue(query
, kSecReturnRef
, kCFBooleanTrue
);
657 CFDictionarySetValue(query
, kSecAttrNoLegacy
, kCFBooleanTrue
);
659 CFRef
<CFDataRef
> issuerData
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, (const UInt8
*)issuer
->Data
, issuer
->Length
, kCFAllocatorNull
);
660 CFDictionarySetValue(query
, kSecAttrIssuer
, issuerData
);
662 CFRef
<CFDataRef
> serialNumberData
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, (const UInt8
*)serialNumber
->Data
, serialNumber
->Length
, kCFAllocatorNull
);
663 CFDictionarySetValue(query
, kSecAttrSerialNumber
, serialNumberData
);
665 OSStatus status
= SecItemCopyMatching(query
, (CFTypeRef
*)certificate
);
666 if (status
== errSecSuccess
) {
673 StorageManager::KeychainList keychains
;
674 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
675 Required(certificate
) = Certificate::findByIssuerAndSN(keychains
, CssmData::required(issuer
), CssmData::required(serialNumber
))->handle();
678 // convert ItemImpl-based SecCertificateRef to new-world version before returning
679 CssmData certData
= Certificate::required(*certificate
)->data();
680 CFRef
<CFDataRef
> cfData(CFDataCreate(NULL
, certData
.Data
, certData
.Length
));
681 SecCertificateRef tmpRef
= *certificate
;
682 *certificate
= SecCertificateCreateWithData(NULL
, cfData
);
691 SecCertificateFindBySubjectKeyID(CFTypeRef keychainOrArray
, const CSSM_DATA
*subjectKeyID
,
692 SecCertificateRef
*certificate
)
695 CFRef
<CFMutableDictionaryRef
> query
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
696 CFDictionarySetValue(query
, kSecClass
, kSecClassCertificate
);
697 CFDictionarySetValue(query
, kSecReturnRef
, kCFBooleanTrue
);
698 CFDictionarySetValue(query
, kSecAttrNoLegacy
, kCFBooleanTrue
);
700 CFRef
<CFDataRef
> subjectKeyIDData
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, (const UInt8
*)subjectKeyID
->Data
, subjectKeyID
->Length
, kCFAllocatorNull
);
701 CFDictionarySetValue(query
, kSecAttrSubjectKeyID
, subjectKeyIDData
);
703 OSStatus status
= SecItemCopyMatching(query
, (CFTypeRef
*)certificate
);
704 if (status
== errSecSuccess
) {
711 StorageManager::KeychainList keychains
;
712 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
713 Required(certificate
) = Certificate::findBySubjectKeyID(keychains
, CssmData::required(subjectKeyID
))->handle();
716 // convert ItemImpl-based SecCertificateRef to new-world version before returning
717 CssmData certData
= Certificate::required(*certificate
)->data();
718 CFRef
<CFDataRef
> cfData(CFDataCreate(NULL
, certData
.Data
, certData
.Length
));
719 SecCertificateRef tmpRef
= *certificate
;
720 *certificate
= SecCertificateCreateWithData(NULL
, cfData
);
729 SecCertificateFindByEmail(CFTypeRef keychainOrArray
, const char *emailAddress
, SecCertificateRef
*certificate
)
732 CFRef
<CFMutableDictionaryRef
> query
= CFDictionaryCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
733 CFDictionarySetValue(query
, kSecClass
, kSecClassCertificate
);
734 CFDictionarySetValue(query
, kSecReturnRef
, kCFBooleanTrue
);
735 CFDictionarySetValue(query
, kSecAttrNoLegacy
, kCFBooleanTrue
);
737 CFRef
<CFStringRef
> emailAddressString
= CFStringCreateWithCString(kCFAllocatorDefault
, emailAddress
, kCFStringEncodingUTF8
);
738 CFTypeRef keys
[] = { kSecPolicyName
};
739 CFTypeRef values
[] = { emailAddressString
};
740 CFRef
<CFDictionaryRef
> properties
= CFDictionaryCreate(kCFAllocatorDefault
, keys
, values
, 1, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
741 CFRef
<SecPolicyRef
> policy
= SecPolicyCreateWithProperties(kSecPolicyAppleSMIME
, properties
);
742 CFDictionarySetValue(query
, kSecMatchPolicy
, policy
);
744 OSStatus status
= SecItemCopyMatching(query
, (CFTypeRef
*)certificate
);
745 if (status
== errSecSuccess
) {
752 StorageManager::KeychainList keychains
;
753 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
754 Required(certificate
) = Certificate::findByEmail(keychains
, emailAddress
)->handle();
757 // convert ItemImpl-based SecCertificateRef to new-world version before returning
758 CssmData certData
= Certificate::required(*certificate
)->data();
759 CFRef
<CFDataRef
> cfData(CFDataCreate(NULL
, certData
.Data
, certData
.Length
));
760 SecCertificateRef tmpRef
= *certificate
;
761 *certificate
= SecCertificateCreateWithData(NULL
, cfData
);
770 SecKeychainSearchCreateForCertificateByIssuerAndSN(CFTypeRef keychainOrArray
, const CSSM_DATA
*issuer
,
771 const CSSM_DATA
*serialNumber
, SecKeychainSearchRef
*searchRef
)
777 StorageManager::KeychainList keychains
;
778 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
779 KCCursor
cursor(Certificate::cursorForIssuerAndSN(keychains
, CssmData::required(issuer
), CssmData::required(serialNumber
)));
780 *searchRef
= cursor
->handle();
787 SecKeychainSearchCreateForCertificateByIssuerAndSN_CF(CFTypeRef keychainOrArray
, CFDataRef issuer
,
788 CFDataRef serialNumber
, SecKeychainSearchRef
*searchRef
)
794 StorageManager::KeychainList keychains
;
795 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
797 Required(serialNumber
);
798 KCCursor
cursor(Certificate::cursorForIssuerAndSN_CF(keychains
, issuer
, serialNumber
));
799 *searchRef
= cursor
->handle();
806 SecKeychainSearchCreateForCertificateBySubjectKeyID(CFTypeRef keychainOrArray
, const CSSM_DATA
*subjectKeyID
,
807 SecKeychainSearchRef
*searchRef
)
813 StorageManager::KeychainList keychains
;
814 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
815 KCCursor
cursor(Certificate::cursorForSubjectKeyID(keychains
, CssmData::required(subjectKeyID
)));
816 *searchRef
= cursor
->handle();
823 SecKeychainSearchCreateForCertificateByEmail(CFTypeRef keychainOrArray
, const char *emailAddress
,
824 SecKeychainSearchRef
*searchRef
)
830 StorageManager::KeychainList keychains
;
831 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
832 KCCursor
cursor(Certificate::cursorForEmail(keychains
, emailAddress
));
833 *searchRef
= cursor
->handle();
840 SecDigestGetData (CSSM_ALGORITHMS alg
, CSSM_DATA
* digest
, const CSSM_DATA
* data
)
844 if (!digest
|| !digest
->Data
|| !digest
->Length
|| !data
|| !data
->Data
|| !data
->Length
)
847 CSP
csp(gGuidAppleCSP
);
848 Digest
context(csp
, alg
);
849 CssmData
input(data
->Data
, data
->Length
);
850 CssmData
output(digest
->Data
, digest
->Length
);
852 context
.digest(input
, output
);
853 digest
->Length
= output
.length();
860 /* determine whether a cert is self-signed */
861 OSStatus
SecCertificateIsSelfSigned(
862 SecCertificateRef certificate
,
863 Boolean
*isSelfSigned
) /* RETURNED */
867 *isSelfSigned
= Certificate::required(certificate
)->isSelfSigned();
873 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
875 SecCertificateCopyPreference(
877 CSSM_KEYUSE keyUsage
,
878 SecCertificateRef
*certificate
)
883 Required(certificate
);
884 StorageManager::KeychainList keychains
;
885 globals().storageManager
.getSearchList(keychains
);
886 KCCursor
cursor(keychains
, kSecGenericPasswordItemClass
, NULL
);
888 char idUTF8
[MAXPATHLEN
];
889 if (!CFStringGetCString(name
, idUTF8
, sizeof(idUTF8
)-1, kCFStringEncodingUTF8
))
890 idUTF8
[0] = (char)'\0';
891 CssmData
service(const_cast<char *>(idUTF8
), strlen(idUTF8
));
892 FourCharCode itemType
= 'cprf';
893 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecServiceItemAttr
), service
);
894 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecTypeItemAttr
), itemType
);
896 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecScriptCodeItemAttr
), (sint32
)keyUsage
);
899 if (!cursor
->next(prefItem
))
900 MacOSError::throwMe(errSecItemNotFound
);
902 // get persistent certificate reference
903 SecKeychainAttribute itemAttrs
[] = { { kSecGenericItemAttr
, 0, NULL
} };
904 SecKeychainAttributeList itemAttrList
= { sizeof(itemAttrs
) / sizeof(itemAttrs
[0]), itemAttrs
};
905 prefItem
->getContent(NULL
, &itemAttrList
, NULL
, NULL
);
907 // find certificate, given persistent reference data
908 CFDataRef pItemRef
= CFDataCreateWithBytesNoCopy(NULL
, (const UInt8
*)itemAttrs
[0].data
, itemAttrs
[0].length
, kCFAllocatorNull
);
909 SecKeychainItemRef certItemRef
= nil
;
910 OSStatus status
= SecKeychainItemCopyFromPersistentReference(pItemRef
, &certItemRef
); //%%% need to make this a method of ItemImpl
911 prefItem
->freeContent(&itemAttrList
, NULL
);
917 *certificate
= (SecCertificateRef
)certItemRef
;
920 if (certItemRef
&& (CFGetTypeID(certItemRef
) == SecIdentityGetTypeID())) {
921 // SecKeychainItemCopyFromPersistentReference handed out an identity reference
923 status
= SecIdentityCopyCertificate((SecIdentityRef
)certItemRef
, certificate
);
924 CFRelease(certItemRef
);
927 #if 0 /* SecKeychainItemCopyFromPersistentReference now does this work for us */
928 // convert ItemImpl-based SecCertificateRef to new-world version before returning
929 CssmData certData
= Certificate::required(*certificate
)->data();
930 CFRef
<CFDataRef
> cfData(CFDataCreate(NULL
, certData
.Data
, certData
.Length
));
931 SecCertificateRef tmpRef
= *certificate
;
932 *certificate
= SecCertificateCreateWithData(NULL
, cfData
);
942 SecCertificateCopyPreferred(
946 // This function will look for a matching preference in the following order:
947 // - matches the name and the supplied key use
948 // - matches the name and the special 'ANY' key use
949 // - matches the name with no key usage constraint
951 SecCertificateRef certRef
= NULL
;
952 CSSM_KEYUSE keyUse
= ConvertArrayToKeyUsage(keyUsage
);
953 OSStatus status
= SecCertificateCopyPreference(name
, keyUse
, &certRef
);
954 if (status
!= errSecSuccess
&& keyUse
!= CSSM_KEYUSE_ANY
)
955 status
= SecCertificateCopyPreference(name
, CSSM_KEYUSE_ANY
, &certRef
);
956 if (status
!= errSecSuccess
&& keyUse
!= 0)
957 status
= SecCertificateCopyPreference(name
, 0, &certRef
);
962 /* OS X only; not exported */
964 SecCertificateFindPreferenceItemWithNameAndKeyUsage(
965 CFTypeRef keychainOrArray
,
968 SecKeychainItemRef
*itemRef
)
972 StorageManager::KeychainList keychains
;
973 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
974 KCCursor
cursor(keychains
, kSecGenericPasswordItemClass
, NULL
);
976 char idUTF8
[MAXPATHLEN
];
977 idUTF8
[0] = (char)'\0';
980 if (!CFStringGetCString(name
, idUTF8
, sizeof(idUTF8
)-1, kCFStringEncodingUTF8
))
981 idUTF8
[0] = (char)'\0';
983 size_t idUTF8Len
= strlen(idUTF8
);
985 MacOSError::throwMe(errSecParam
);
987 CssmData
service(const_cast<char *>(idUTF8
), idUTF8Len
);
988 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecServiceItemAttr
), service
);
989 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecTypeItemAttr
), (FourCharCode
)'cprf');
991 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecScriptCodeItemAttr
), (sint32
)keyUsage
);
994 if (!cursor
->next(item
))
995 MacOSError::throwMe(errSecItemNotFound
);
998 *itemRef
=item
->handle();
1003 /* OS X only; not exported */
1005 OSStatus
SecCertificateDeletePreferenceItemWithNameAndKeyUsage(
1006 CFTypeRef keychainOrArray
,
1010 // when a specific key usage is passed, we'll only match & delete that pref;
1011 // when a key usage of 0 is passed, all matching prefs should be deleted.
1012 // maxUsages represents the most matches there could theoretically be, so
1013 // cut things off at that point if we're still finding items (if they can't
1014 // be deleted for some reason, we'd never break out of the loop.)
1017 SecKeychainItemRef item
= NULL
;
1018 int count
= 0, maxUsages
= 12;
1019 while (++count
<= maxUsages
&&
1020 (status
= SecCertificateFindPreferenceItemWithNameAndKeyUsage(keychainOrArray
, name
, keyUsage
, &item
)) == errSecSuccess
) {
1021 status
= SecKeychainItemDelete(item
);
1026 // it's not an error if the item isn't found
1027 return (status
== errSecItemNotFound
) ? errSecSuccess
: status
;
1030 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA) */
1031 OSStatus
SecCertificateSetPreference(
1032 SecCertificateRef certificate
,
1034 CSSM_KEYUSE keyUsage
,
1041 // treat NULL certificate as a request to clear the preference
1042 // (note: if keyUsage is 0, this clears all key usage prefs for name)
1043 return SecCertificateDeletePreferenceItemWithNameAndKeyUsage(NULL
, name
, keyUsage
);
1046 // This macro creates an ItemImpl certificate if it does not exist
1049 // determine the account attribute
1051 // This attribute must be synthesized from certificate label + pref item type + key usage,
1052 // as only the account and service attributes can make a generic keychain item unique.
1053 // For 'iprf' type items (but not 'cprf'), we append a trailing space. This insures that
1054 // we can save a certificate preference if an identity preference already exists for the
1055 // given service name, and vice-versa.
1056 // If the key usage is 0 (i.e. the normal case), we omit the appended key usage string.
1058 CFStringRef labelStr
= nil
;
1059 Certificate::required(__itemImplRef
)->inferLabel(false, &labelStr
);
1061 MacOSError::throwMe(errSecDataTooLarge
); // data is "in a format which cannot be displayed"
1063 CFIndex accountUTF8Len
= CFStringGetMaximumSizeForEncoding(CFStringGetLength(labelStr
), kCFStringEncodingUTF8
) + 1;
1064 const char *templateStr
= "%s [key usage 0x%X]";
1065 const int keyUsageMaxStrLen
= 8;
1066 accountUTF8Len
+= strlen(templateStr
) + keyUsageMaxStrLen
;
1067 char accountUTF8
[accountUTF8Len
];
1068 if (!CFStringGetCString(labelStr
, accountUTF8
, accountUTF8Len
-1, kCFStringEncodingUTF8
))
1069 accountUTF8
[0] = (char)'\0';
1071 snprintf(accountUTF8
, accountUTF8Len
-1, templateStr
, accountUTF8
, keyUsage
);
1072 CssmData
account(const_cast<char *>(accountUTF8
), strlen(accountUTF8
));
1073 CFRelease(labelStr
);
1075 // service attribute (name provided by the caller)
1076 CFIndex serviceUTF8Len
= CFStringGetMaximumSizeForEncoding(CFStringGetLength(name
), kCFStringEncodingUTF8
) + 1;;
1077 char serviceUTF8
[serviceUTF8Len
];
1078 if (!CFStringGetCString(name
, serviceUTF8
, serviceUTF8Len
-1, kCFStringEncodingUTF8
))
1079 serviceUTF8
[0] = (char)'\0';
1080 CssmData
service(const_cast<char *>(serviceUTF8
), strlen(serviceUTF8
));
1082 // look for existing preference item, in case this is an update
1083 StorageManager::KeychainList keychains
;
1084 globals().storageManager
.getSearchList(keychains
);
1085 KCCursor
cursor(keychains
, kSecGenericPasswordItemClass
, NULL
);
1086 FourCharCode itemType
= 'cprf';
1087 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecServiceItemAttr
), service
);
1088 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecTypeItemAttr
), itemType
);
1090 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecScriptCodeItemAttr
), (sint32
)keyUsage
);
1094 Item
item(kSecGenericPasswordItemClass
, 'aapl', 0, NULL
, false);
1095 bool add
= (!cursor
->next(item
));
1096 // at this point, we either have a new item to add or an existing item to update
1098 // set item attribute values
1099 item
->setAttribute(Schema::attributeInfo(kSecServiceItemAttr
), service
);
1100 item
->setAttribute(Schema::attributeInfo(kSecTypeItemAttr
), itemType
);
1101 item
->setAttribute(Schema::attributeInfo(kSecAccountItemAttr
), account
);
1102 item
->setAttribute(Schema::attributeInfo(kSecScriptCodeItemAttr
), (sint32
)keyUsage
);
1103 item
->setAttribute(Schema::attributeInfo(kSecLabelItemAttr
), service
);
1109 // generic attribute (store persistent certificate reference)
1110 CFDataRef pItemRef
= nil
;
1111 Certificate::required(__itemImplRef
)->copyPersistentReference(pItemRef
);
1113 MacOSError::throwMe(errSecInvalidItemRef
);
1115 const UInt8
*dataPtr
= CFDataGetBytePtr(pItemRef
);
1116 CFIndex dataLen
= CFDataGetLength(pItemRef
);
1117 CssmData
pref(const_cast<void *>(reinterpret_cast<const void *>(dataPtr
)), dataLen
);
1118 item
->setAttribute(Schema::attributeInfo(kSecGenericItemAttr
), pref
);
1119 CFRelease(pItemRef
);
1122 Keychain keychain
= nil
;
1124 keychain
= globals().storageManager
.defaultKeychain();
1125 if (!keychain
->exists())
1126 MacOSError::throwMe(errSecNoSuchKeychain
); // Might be deleted or not available at this time.
1129 keychain
= globals().storageManager
.defaultKeychainUI(item
);
1133 keychain
->add(item
);
1135 catch (const MacOSError
&err
) {
1136 if (err
.osStatus() != errSecDuplicateItem
)
1137 throw; // if item already exists, fall through to update
1145 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
1146 OSStatus
SecCertificateSetPreferred(
1147 SecCertificateRef certificate
,
1149 CFArrayRef keyUsage
)
1151 CSSM_KEYUSE keyUse
= ConvertArrayToKeyUsage(keyUsage
);
1152 return SecCertificateSetPreference(certificate
, name
, keyUse
, NULL
);
1155 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
1156 CFDictionaryRef
SecCertificateCopyValues(SecCertificateRef certificate
, CFArrayRef keys
, CFErrorRef
*error
)
1158 CFDictionaryRef result
= NULL
;
1159 OSStatus __secapiresult
;
1160 SecCertificateRef tmpcert
= NULL
;
1162 // convert input to a new-style certificate reference if necessary,
1163 // since the implementation of CertificateValues calls SecCertificate API functions
1164 // which now assume a unified certificate reference.
1165 if (SecCertificateIsItemImplInstance(certificate
)) {
1166 tmpcert
= SecCertificateCreateFromItemImplInstance(certificate
);
1169 if (certificate
&& !tmpcert
) {
1170 tmpcert
= (SecCertificateRef
) CFRetain(certificate
);
1174 CertificateValues
cv(tmpcert
);
1175 result
= cv
.copyFieldValues(keys
,error
);
1178 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1179 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1180 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1181 catch (...) { __secapiresult
=errSecInternalComponent
; }
1182 if (tmpcert
) { CFRelease(tmpcert
); }
1186 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
1187 CFStringRef
SecCertificateCopyLongDescription(CFAllocatorRef alloc
, SecCertificateRef certificate
, CFErrorRef
*error
)
1189 return SecCertificateCopyShortDescription(alloc
, certificate
, error
);
1192 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
1193 CFStringRef
SecCertificateCopyShortDescription(CFAllocatorRef alloc
, SecCertificateRef certificate
, CFErrorRef
*error
)
1195 CFStringRef result
= NULL
;
1196 OSStatus __secapiresult
= SecCertificateInferLabel(certificate
, &result
);
1197 if (error
!=NULL
&& __secapiresult
!=errSecSuccess
)
1199 *error
= CFErrorCreate(kCFAllocatorDefault
, kCFErrorDomainOSStatus
,
1200 __secapiresult
? __secapiresult
: CSSM_ERRCODE_INTERNAL_ERROR
, NULL
);
1205 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
1206 CFDataRef
SecCertificateCopySerialNumber(SecCertificateRef certificate
, CFErrorRef
*error
)
1208 CFDataRef result
= NULL
;
1209 OSStatus __secapiresult
;
1212 CertificateValues
cv(certificate
);
1213 result
= cv
.copySerialNumber(error
);
1216 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1217 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1218 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1219 catch (...) { __secapiresult
=errSecInternalComponent
; }
1223 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
1224 CFDataRef
SecCertificateCopyNormalizedIssuerContent(SecCertificateRef certificate
, CFErrorRef
*error
)
1226 CFDataRef result
= NULL
;
1227 OSStatus __secapiresult
;
1230 CertificateValues
cv(certificate
);
1231 result
= cv
.copyNormalizedIssuerContent(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
; }
1241 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
1242 CFDataRef
SecCertificateCopyNormalizedSubjectContent(SecCertificateRef certificate
, CFErrorRef
*error
)
1244 CFDataRef result
= NULL
;
1245 OSStatus __secapiresult
;
1248 CertificateValues
cv(certificate
);
1249 result
= cv
.copyNormalizedSubjectContent(error
);
1252 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1253 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1254 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1255 catch (...) { __secapiresult
=errSecInternalComponent
; }
1260 CFDataRef
SecCertificateCopyIssuerSequence(SecCertificateRef certificate
)
1262 CFDataRef result
= NULL
;
1263 OSStatus __secapiresult
;
1266 CertificateValues
cv(certificate
);
1267 result
= cv
.copyIssuerSequence(NULL
);
1270 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1271 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1272 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1273 catch (...) { __secapiresult
=errSecInternalComponent
; }
1279 CFDataRef
SecCertificateCopySubjectSequence(SecCertificateRef certificate
)
1281 CFDataRef result
= NULL
;
1282 OSStatus __secapiresult
;
1285 CertificateValues
cv(certificate
);
1286 result
= cv
.copySubjectSequence(NULL
);
1289 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1290 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1291 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1292 catch (...) { __secapiresult
=errSecInternalComponent
; }
1298 CFDictionaryRef
SecCertificateCopyAttributeDictionary(SecCertificateRef certificate
)
1300 CFDictionaryRef result
= NULL
;
1304 CertificateValues
cv(certificate
);
1305 result
= cv
.copyAttributeDictionary(NULL
);
1308 catch (const MacOSError
&err
) { status
=err
.osStatus(); }
1309 catch (const CommonError
&err
) { status
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1310 catch (const std::bad_alloc
&) { status
=errSecAllocate
; }
1311 catch (...) { status
=errSecInternalComponent
; }
1318 bool SecCertificateIsValid(SecCertificateRef certificate
, CFAbsoluteTime verifyTime
)
1321 OSStatus __secapiresult
;
1324 CFErrorRef error
= NULL
;
1325 CertificateValues
cv(certificate
);
1326 result
= cv
.isValid(verifyTime
, &error
);
1327 if (error
) CFRelease(error
);
1330 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1331 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1332 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1333 catch (...) { __secapiresult
=errSecInternalComponent
; }
1338 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_9, __IPHONE_NA, __IPHONE_NA) */
1339 bool SecCertificateIsValidX(SecCertificateRef certificate
, CFAbsoluteTime verifyTime
)
1342 * deprecated function name
1344 return SecCertificateIsValid(certificate
, verifyTime
);
1348 CFAbsoluteTime
SecCertificateNotValidBefore(SecCertificateRef certificate
)
1350 CFAbsoluteTime result
= 0;
1351 OSStatus __secapiresult
;
1354 CFErrorRef error
= NULL
;
1355 CertificateValues
cv(certificate
);
1356 result
= cv
.notValidBefore(&error
);
1357 if (error
) CFRelease(error
);
1360 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1361 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1362 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1363 catch (...) { __secapiresult
=errSecInternalComponent
; }
1369 CFAbsoluteTime
SecCertificateNotValidAfter(SecCertificateRef certificate
)
1371 CFAbsoluteTime result
= 0;
1372 OSStatus __secapiresult
;
1375 CFErrorRef error
= NULL
;
1376 CertificateValues
cv(certificate
);
1377 result
= cv
.notValidAfter(&error
);
1378 if (error
) CFRelease(error
);
1381 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1382 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1383 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1384 catch (...) { __secapiresult
=errSecInternalComponent
; }
1391 SecCertificateRef
SecCertificateCreateWithBytes(CFAllocatorRef allocator
,
1392 const UInt8
*bytes
, CFIndex length
)
1394 SecCertificateRef certificate
= NULL
;
1395 OSStatus __secapiresult
;
1397 CSSM_DATA cssmCertData
= { (CSSM_SIZE
)length
, (uint8
*)bytes
};
1399 //NOTE: there isn't yet a Certificate constructor which accepts a CFAllocatorRef
1400 SecPointer
<Certificate
> certificatePtr(new Certificate(cssmCertData
, CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
));
1401 certificate
= certificatePtr
->handle();
1403 __secapiresult
=errSecSuccess
;
1405 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1406 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1407 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1408 catch (...) { __secapiresult
=errSecInternalComponent
; }
1415 CFIndex
SecCertificateGetLength(SecCertificateRef certificate
)
1418 OSStatus __secapiresult
;
1420 CssmData output
= Certificate::required(certificate
)->data();
1421 length
= (CFIndex
)output
.length();
1422 __secapiresult
=errSecSuccess
;
1424 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1425 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1426 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1427 catch (...) { __secapiresult
=errSecInternalComponent
; }
1434 const UInt8
*SecCertificateGetBytePtr(SecCertificateRef certificate
)
1436 const UInt8
*bytes
= NULL
;
1437 OSStatus __secapiresult
;
1439 CssmData output
= Certificate::required(certificate
)->data();
1440 bytes
= (const UInt8
*)output
.data();
1441 __secapiresult
=errSecSuccess
;
1443 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1444 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1445 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1446 catch (...) { __secapiresult
=errSecInternalComponent
; }
1453 static CFArrayRef
CopyEscrowCertificates(SecCertificateEscrowRootType escrowRootType
, CFErrorRef
*error
)
1455 // Return array of CFDataRef certificates.
1456 CFArrayRef result
= NULL
;
1460 // Get the hard coded set of production roots
1461 // static struct RootRecord* kProductionEscrowRoots[] = {&kOldEscrowRootRecord, &kProductionEscrowRootRecord};
1463 struct RootRecord
** pEscrowRoots
= NULL
;
1464 switch (escrowRootType
) {
1465 case kSecCertificateBaselineEscrowRoot
:
1466 numRoots
= kNumberOfBaseLineEscrowRoots
;
1467 pEscrowRoots
= kBaseLineEscrowRoots
;
1469 case kSecCertificateProductionEscrowRoot
:
1470 numRoots
= kNumberOfBaseLineEscrowRoots
; //%%% currently, production == baseline on OS X
1471 pEscrowRoots
= kBaseLineEscrowRoots
;
1473 case kSecCertificateBaselinePCSEscrowRoot
:
1474 numRoots
= kNumberOfBaseLinePCSEscrowRoots
;
1475 pEscrowRoots
= kBaseLinePCSEscrowRoots
;
1477 case kSecCertificateProductionPCSEscrowRoot
:
1478 numRoots
= kNumberOfBaseLinePCSEscrowRoots
; //%%% currently, production == baseline on OS X
1479 pEscrowRoots
= kBaseLinePCSEscrowRoots
;
1485 CFDataRef productionCerts
[numRoots
];
1486 struct RootRecord
* pRootRecord
= NULL
;
1488 for (iCnt
= 0; pEscrowRoots
!= NULL
&& iCnt
< numRoots
; iCnt
++)
1490 pRootRecord
= pEscrowRoots
[iCnt
];
1491 if (NULL
!= pRootRecord
&& pRootRecord
->_length
> 0 && NULL
!= pRootRecord
->_bytes
)
1493 productionCerts
[iCnt
] = CFDataCreate(kCFAllocatorDefault
, pRootRecord
->_bytes
, pRootRecord
->_length
);
1496 result
= CFArrayCreate(kCFAllocatorDefault
, (const void **)productionCerts
, numRoots
, &kCFTypeArrayCallBacks
);
1497 for (iCnt
= 0; iCnt
< numRoots
; iCnt
++)
1499 if (NULL
!= productionCerts
[iCnt
])
1501 CFRelease(productionCerts
[iCnt
]);
1511 CFArrayRef
SecCertificateCopyEscrowRoots(SecCertificateEscrowRootType escrowRootType
)
1513 CFArrayRef result
= NULL
;
1516 CFDataRef certData
= NULL
;
1518 // The request is for the base line certificates.
1519 // Use the hard coded data to generate the return array
1520 if (kSecCertificateBaselineEscrowRoot
== escrowRootType
)
1522 // Get the hard coded set of roots
1523 numRoots
= kNumberOfBaseLineEscrowRoots
;
1524 SecCertificateRef baseLineCerts
[numRoots
];
1525 struct RootRecord
* pRootRecord
= NULL
;
1527 for (iCnt
= 0; iCnt
< numRoots
; iCnt
++)
1529 pRootRecord
= kBaseLineEscrowRoots
[iCnt
];
1530 if (NULL
!= pRootRecord
&& pRootRecord
->_length
> 0 && NULL
!= pRootRecord
->_bytes
)
1532 certData
= CFDataCreate(kCFAllocatorDefault
, pRootRecord
->_bytes
, pRootRecord
->_length
);
1533 if (NULL
!= certData
)
1535 baseLineCerts
[iCnt
] = SecCertificateCreateWithData(kCFAllocatorDefault
, certData
);
1536 CFRelease(certData
);
1540 result
= CFArrayCreate(kCFAllocatorDefault
, (const void **)baseLineCerts
, numRoots
, &kCFTypeArrayCallBacks
);
1541 for (iCnt
= 0; iCnt
< numRoots
; iCnt
++)
1543 if (NULL
!= baseLineCerts
[iCnt
])
1545 CFRelease(baseLineCerts
[iCnt
]);
1549 // The request is for the current certificates.
1552 CFErrorRef error
= NULL
;
1553 CFArrayRef cert_datas
= CopyEscrowCertificates(escrowRootType
, &error
);
1554 if (NULL
!= error
|| NULL
== cert_datas
|| 0 == (numRoots
= (int)CFArrayGetCount(cert_datas
)))
1561 if (NULL
!= cert_datas
)
1563 CFRelease(cert_datas
);
1568 SecCertificateRef assetCerts
[numRoots
];
1569 for (iCnt
= 0; iCnt
< numRoots
; iCnt
++)
1571 certData
= (CFDataRef
)CFArrayGetValueAtIndex(cert_datas
, iCnt
);
1572 if (NULL
!= certData
)
1574 SecCertificateRef aCertRef
= SecCertificateCreateWithData(kCFAllocatorDefault
, certData
);
1575 assetCerts
[iCnt
] = aCertRef
;
1579 assetCerts
[iCnt
] = NULL
;
1585 result
= CFArrayCreate(kCFAllocatorDefault
, (const void **)assetCerts
, numRoots
, &kCFTypeArrayCallBacks
);
1586 for (iCnt
= 0; iCnt
< numRoots
; iCnt
++)
1588 if (NULL
!= assetCerts
[iCnt
])
1590 CFRelease(assetCerts
[iCnt
]);
1594 CFRelease(cert_datas
);
1603 SecSignatureHashAlgorithm
SecCertificateGetSignatureHashAlgorithm(SecCertificateRef certificate
)
1605 SecSignatureHashAlgorithm result
= kSecSignatureHashAlgorithmUnknown
;
1606 CSSM_X509_ALGORITHM_IDENTIFIER_PTR algId
= NULL
;
1607 CSSM_DATA_PTR fieldValue
= NULL
;
1608 CSSM_OID_PTR algOID
= NULL
;
1609 const CSSM_OID
*sigAlgOID
= &CSSMOID_X509V1SignatureAlgorithm
;
1612 status
= SecCertificateCopyFirstFieldValue(certificate
, sigAlgOID
, &fieldValue
);
1613 if (status
|| !fieldValue
) {
1616 algId
= (CSSM_X509_ALGORITHM_IDENTIFIER_PTR
)fieldValue
->Data
;
1617 algOID
= (algId
) ? &algId
->algorithm
: NULL
;
1620 if (!algOID
->Data
|| !algOID
->Length
) {
1623 /* classify the signature algorithm OID into one of our known types */
1624 if (cuCompareCssmData(algOID
, &CSSMOID_ECDSA_WithSHA512
) ||
1625 cuCompareCssmData(algOID
, &CSSMOID_SHA512WithRSA
) ||
1626 cuCompareCssmData(algOID
, &CSSMOID_SHA512
)) {
1627 result
= kSecSignatureHashAlgorithmSHA512
;
1630 if (cuCompareCssmData(algOID
, &CSSMOID_ECDSA_WithSHA384
) ||
1631 cuCompareCssmData(algOID
, &CSSMOID_SHA384WithRSA
) ||
1632 cuCompareCssmData(algOID
, &CSSMOID_SHA384
)) {
1633 result
= kSecSignatureHashAlgorithmSHA384
;
1636 if (cuCompareCssmData(algOID
, &CSSMOID_ECDSA_WithSHA256
) ||
1637 cuCompareCssmData(algOID
, &CSSMOID_SHA256WithRSA
) ||
1638 cuCompareCssmData(algOID
, &CSSMOID_SHA256
)) {
1639 result
= kSecSignatureHashAlgorithmSHA256
;
1642 if (cuCompareCssmData(algOID
, &CSSMOID_ECDSA_WithSHA224
) ||
1643 cuCompareCssmData(algOID
, &CSSMOID_SHA224WithRSA
) ||
1644 cuCompareCssmData(algOID
, &CSSMOID_SHA224
)) {
1645 result
= kSecSignatureHashAlgorithmSHA224
;
1648 if (cuCompareCssmData(algOID
, &CSSMOID_ECDSA_WithSHA1
) ||
1649 cuCompareCssmData(algOID
, &CSSMOID_SHA1WithRSA
) ||
1650 cuCompareCssmData(algOID
, &CSSMOID_SHA1WithDSA
) ||
1651 cuCompareCssmData(algOID
, &CSSMOID_SHA1WithDSA_CMS
) ||
1652 cuCompareCssmData(algOID
, &CSSMOID_SHA1WithDSA_JDK
) ||
1653 cuCompareCssmData(algOID
, &CSSMOID_SHA1WithRSA_OIW
) ||
1654 cuCompareCssmData(algOID
, &CSSMOID_APPLE_FEE_SHA1
) ||
1655 cuCompareCssmData(algOID
, &CSSMOID_SHA1
)) {
1656 result
= kSecSignatureHashAlgorithmSHA1
;
1659 if (cuCompareCssmData(algOID
, &CSSMOID_MD5WithRSA
) ||
1660 cuCompareCssmData(algOID
, &CSSMOID_APPLE_FEE_MD5
) ||
1661 cuCompareCssmData(algOID
, &CSSMOID_MD5
)) {
1662 result
= kSecSignatureHashAlgorithmMD5
;
1665 if (cuCompareCssmData(algOID
, &CSSMOID_MD4WithRSA
) ||
1666 cuCompareCssmData(algOID
, &CSSMOID_MD4
)) {
1667 result
= kSecSignatureHashAlgorithmMD4
;
1670 if (cuCompareCssmData(algOID
, &CSSMOID_MD2WithRSA
) ||
1671 cuCompareCssmData(algOID
, &CSSMOID_MD2
)) {
1672 result
= kSecSignatureHashAlgorithmMD2
;
1678 (void)SecCertificateReleaseFirstFieldValue(certificate
, sigAlgOID
, fieldValue
);