2 * Copyright (c) 2002-2014 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
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 <sys/param.h>
44 #include "CertificateValues.h"
45 #include "SecCertificateP.h"
46 #include "SecCertificatePrivP.h"
48 #include "AppleBaselineEscrowCertificates.h"
51 extern CSSM_KEYUSE
ConvertArrayToKeyUsage(CFArrayRef usage
);
53 #define SEC_CONST_DECL(k,v) CFTypeRef k = (CFTypeRef)(CFSTR(v));
55 SEC_CONST_DECL (kSecCertificateProductionEscrowKey
, "ProductionEscrowKey");
56 SEC_CONST_DECL (kSecCertificateProductionPCSEscrowKey
, "ProductionPCSEscrowKey");
57 SEC_CONST_DECL (kSecCertificateEscrowFileName
, "AppleESCertificates");
60 using namespace CssmClient
;
63 SecCertificateGetTypeID(void)
67 return gTypes().Certificate
.typeID
;
69 END_SECAPI1(_kCFRuntimeNotATypeID
)
74 SecCertificateCreateFromData(const CSSM_DATA
*data
, CSSM_CERT_TYPE type
, CSSM_CERT_ENCODING encoding
, SecCertificateRef
*certificate
)
78 SecPointer
<Certificate
> certificatePtr(new Certificate(Required(data
), type
, encoding
));
79 Required(certificate
) = certificatePtr
->handle();
86 SecCertificateCreateWithData(CFAllocatorRef allocator
, CFDataRef data
)
88 SecCertificateRef certificate
= NULL
;
89 OSStatus __secapiresult
;
91 CSSM_DATA cssmCertData
;
92 cssmCertData
.Length
= (data
) ? (CSSM_SIZE
)CFDataGetLength(data
) : 0;
93 cssmCertData
.Data
= (data
) ? (uint8
*)CFDataGetBytePtr(data
) : NULL
;
95 //NOTE: there isn't yet a Certificate constructor which accepts a CFAllocatorRef
96 SecPointer
<Certificate
> certificatePtr(new Certificate(cssmCertData
, CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
));
97 certificate
= certificatePtr
->handle();
99 __secapiresult
=errSecSuccess
;
101 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
102 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
103 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
104 catch (...) { __secapiresult
=errSecInternalComponent
; }
109 SecCertificateAddToKeychain(SecCertificateRef certificate
, SecKeychainRef keychain
)
113 Item
item(Certificate::required(certificate
));
114 Keychain::optional(keychain
)->add(item
);
120 SecCertificateGetData(SecCertificateRef certificate
, CSSM_DATA_PTR data
)
124 Required(data
) = Certificate::required(certificate
)->data();
131 SecCertificateCopyData(SecCertificateRef certificate
)
133 CFDataRef data
= NULL
;
134 OSStatus __secapiresult
= errSecSuccess
;
136 CssmData output
= Certificate::required(certificate
)->data();
137 CFIndex length
= (CFIndex
)output
.length();
138 const UInt8
*bytes
= (const UInt8
*)output
.data();
139 if (length
&& bytes
) {
140 data
= CFDataCreate(NULL
, bytes
, length
);
143 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
144 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
145 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
146 catch (...) { __secapiresult
=errSecInternalComponent
; }
151 SecCertificateGetSHA1Digest(SecCertificateRef certificate
)
153 CFDataRef data
= NULL
;
154 OSStatus __secapiresult
= errSecSuccess
;
156 data
= Certificate::required(certificate
)->sha1Hash();
158 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
159 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
160 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
161 catch (...) { __secapiresult
=errSecInternalComponent
; }
166 SecCertificateCopyDNSNames(SecCertificateRef certificate
)
168 CFArrayRef names
= NULL
;
169 OSStatus __secapiresult
= errSecSuccess
;
171 names
= Certificate::required(certificate
)->copyDNSNames();
173 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
174 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
175 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
176 catch (...) { __secapiresult
=errSecInternalComponent
; }
181 SecCertificateGetType(SecCertificateRef certificate
, CSSM_CERT_TYPE
*certificateType
)
185 Required(certificateType
) = Certificate::required(certificate
)->type();
192 SecCertificateGetSubject(SecCertificateRef certificate
, const CSSM_X509_NAME
**subject
)
196 Required(subject
) = Certificate::required(certificate
)->subjectName();
203 SecCertificateGetIssuer(SecCertificateRef certificate
, const CSSM_X509_NAME
**issuer
)
207 Required(issuer
) = Certificate::required(certificate
)->issuerName();
214 SecCertificateGetCLHandle(SecCertificateRef certificate
, CSSM_CL_HANDLE
*clHandle
)
218 Required(clHandle
) = Certificate::required(certificate
)->clHandle();
224 * Private API to infer a display name for a SecCertificateRef which
225 * may or may not be in a keychain.
228 SecCertificateInferLabel(SecCertificateRef certificate
, CFStringRef
*label
)
232 Certificate::required(certificate
)->inferLabel(false,
239 SecCertificateCopyPublicKey(SecCertificateRef certificate
, SecKeyRef
*key
)
243 Required(key
) = Certificate::required(certificate
)->publicKey()->handle();
249 SecCertificateGetAlgorithmID(SecCertificateRef certificate
, const CSSM_X509_ALGORITHM_IDENTIFIER
**algid
)
253 Required(algid
) = Certificate::required(certificate
)->algorithmID();
259 SecCertificateCopyCommonName(SecCertificateRef certificate
, CFStringRef
*commonName
)
263 Required(commonName
) = Certificate::required(certificate
)->commonName();
270 SecCertificateCopySubjectSummary(SecCertificateRef certificate
)
272 CFStringRef summary
= NULL
;
273 OSStatus __secapiresult
;
275 Certificate::required(certificate
)->inferLabel(false, &summary
);
277 __secapiresult
=errSecSuccess
;
279 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
280 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
281 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
282 catch (...) { __secapiresult
=errSecInternalComponent
; }
287 SecCertificateCopyIssuerSummary(SecCertificateRef certificate
)
289 CFStringRef issuerStr
= NULL
;
290 SecCertificateRefP certP
= NULL
;
291 CFDataRef certData
= SecCertificateCopyData(certificate
);
293 certP
= SecCertificateCreateWithDataP(NULL
, certData
);
297 issuerStr
= SecCertificateCopyIssuerSummaryP(certP
);
304 SecCertificateCopySubjectComponent(SecCertificateRef certificate
, const CSSM_OID
*component
, CFStringRef
*result
)
308 Required(result
) = Certificate::required(certificate
)->distinguishedName(&CSSMOID_X509V1SubjectNameCStruct
, component
);
314 SecCertificateGetCommonName(SecCertificateRef certificate
, CFStringRef
*commonName
)
316 // deprecated SPI signature; replaced by SecCertificateCopyCommonName
317 return SecCertificateCopyCommonName(certificate
, commonName
);
321 SecCertificateGetEmailAddress(SecCertificateRef certificate
, CFStringRef
*emailAddress
)
325 Required(emailAddress
) = Certificate::required(certificate
)->copyFirstEmailAddress();
331 SecCertificateCopyEmailAddresses(SecCertificateRef certificate
, CFArrayRef
*emailAddresses
)
335 Required(emailAddresses
) = Certificate::required(certificate
)->copyEmailAddresses();
341 SecCertificateCopyFieldValues(SecCertificateRef certificate
, const CSSM_OID
*field
, CSSM_DATA_PTR
**fieldValues
)
343 /* Return a zero terminated list of CSSM_DATA_PTR's with the values of the field specified by field. Caller must call releaseFieldValues to free the storage allocated by this call. */
346 Required(fieldValues
) = Certificate::required(certificate
)->copyFieldValues(Required(field
));
352 SecCertificateReleaseFieldValues(SecCertificateRef certificate
, const CSSM_OID
*field
, CSSM_DATA_PTR
*fieldValues
)
356 Certificate::required(certificate
)->releaseFieldValues(Required(field
), fieldValues
);
362 SecCertificateCopyFirstFieldValue(SecCertificateRef certificate
, const CSSM_OID
*field
, CSSM_DATA_PTR
*fieldValue
)
366 Required(fieldValue
) = Certificate::required(certificate
)->copyFirstFieldValue(Required(field
));
372 SecCertificateReleaseFirstFieldValue(SecCertificateRef certificate
, const CSSM_OID
*field
, CSSM_DATA_PTR fieldValue
)
376 Certificate::required(certificate
)->releaseFieldValue(Required(field
), fieldValue
);
382 SecCertificateFindByIssuerAndSN(CFTypeRef keychainOrArray
,const CSSM_DATA
*issuer
,
383 const CSSM_DATA
*serialNumber
, SecCertificateRef
*certificate
)
387 StorageManager::KeychainList keychains
;
388 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
389 Required(certificate
) = Certificate::findByIssuerAndSN(keychains
, CssmData::required(issuer
), CssmData::required(serialNumber
))->handle();
395 SecCertificateFindBySubjectKeyID(CFTypeRef keychainOrArray
, const CSSM_DATA
*subjectKeyID
,
396 SecCertificateRef
*certificate
)
400 StorageManager::KeychainList keychains
;
401 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
402 Required(certificate
) = Certificate::findBySubjectKeyID(keychains
, CssmData::required(subjectKeyID
))->handle();
408 SecCertificateFindByEmail(CFTypeRef keychainOrArray
, const char *emailAddress
, SecCertificateRef
*certificate
)
412 StorageManager::KeychainList keychains
;
413 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
414 Required(certificate
) = Certificate::findByEmail(keychains
, emailAddress
)->handle();
420 SecKeychainSearchCreateForCertificateByIssuerAndSN(CFTypeRef keychainOrArray
, const CSSM_DATA
*issuer
,
421 const CSSM_DATA
*serialNumber
, SecKeychainSearchRef
*searchRef
)
427 StorageManager::KeychainList keychains
;
428 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
429 KCCursor
cursor(Certificate::cursorForIssuerAndSN(keychains
, CssmData::required(issuer
), CssmData::required(serialNumber
)));
430 *searchRef
= cursor
->handle();
436 SecKeychainSearchCreateForCertificateByIssuerAndSN_CF(CFTypeRef keychainOrArray
, CFDataRef issuer
,
437 CFDataRef serialNumber
, SecKeychainSearchRef
*searchRef
)
443 StorageManager::KeychainList keychains
;
444 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
446 Required(serialNumber
);
447 KCCursor
cursor(Certificate::cursorForIssuerAndSN_CF(keychains
, issuer
, serialNumber
));
448 *searchRef
= cursor
->handle();
454 SecKeychainSearchCreateForCertificateBySubjectKeyID(CFTypeRef keychainOrArray
, const CSSM_DATA
*subjectKeyID
,
455 SecKeychainSearchRef
*searchRef
)
461 StorageManager::KeychainList keychains
;
462 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
463 KCCursor
cursor(Certificate::cursorForSubjectKeyID(keychains
, CssmData::required(subjectKeyID
)));
464 *searchRef
= cursor
->handle();
470 SecKeychainSearchCreateForCertificateByEmail(CFTypeRef keychainOrArray
, const char *emailAddress
,
471 SecKeychainSearchRef
*searchRef
)
477 StorageManager::KeychainList keychains
;
478 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
479 KCCursor
cursor(Certificate::cursorForEmail(keychains
, emailAddress
));
480 *searchRef
= cursor
->handle();
485 /* NOT EXPORTED YET; copied from SecurityInterface but could be useful in the future.
487 SecGetAppleCSPHandle()
490 return CSP(gGuidAppleCSP)->handle();
495 SecGetAppleCLHandle()
498 return CL(gGuidAppleX509CL)->handle();
504 SecDigestGetData (CSSM_ALGORITHMS alg
, CSSM_DATA
* digest
, const CSSM_DATA
* data
)
508 if (!digest
|| !digest
->Data
|| !digest
->Length
|| !data
|| !data
->Data
|| !data
->Length
)
511 CSP
csp(gGuidAppleCSP
);
512 Digest
context(csp
, alg
);
513 CssmData
input(data
->Data
, data
->Length
);
514 CssmData
output(digest
->Data
, digest
->Length
);
516 context
.digest(input
, output
);
517 digest
->Length
= output
.length();
523 /* determine whether a cert is self-signed */
524 OSStatus
SecCertificateIsSelfSigned(
525 SecCertificateRef certificate
,
526 Boolean
*isSelfSigned
) /* RETURNED */
530 *isSelfSigned
= Certificate::required(certificate
)->isSelfSigned();
536 SecCertificateCopyPreference(
538 CSSM_KEYUSE keyUsage
,
539 SecCertificateRef
*certificate
)
544 Required(certificate
);
545 StorageManager::KeychainList keychains
;
546 globals().storageManager
.getSearchList(keychains
);
547 KCCursor
cursor(keychains
, kSecGenericPasswordItemClass
, NULL
);
549 char idUTF8
[MAXPATHLEN
];
550 if (!CFStringGetCString(name
, idUTF8
, sizeof(idUTF8
)-1, kCFStringEncodingUTF8
))
551 idUTF8
[0] = (char)'\0';
552 CssmData
service(const_cast<char *>(idUTF8
), strlen(idUTF8
));
553 FourCharCode itemType
= 'cprf';
554 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecServiceItemAttr
), service
);
555 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecTypeItemAttr
), itemType
);
557 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecScriptCodeItemAttr
), (sint32
)keyUsage
);
560 if (!cursor
->next(prefItem
))
561 MacOSError::throwMe(errSecItemNotFound
);
563 // get persistent certificate reference
564 SecKeychainAttribute itemAttrs
[] = { { kSecGenericItemAttr
, 0, NULL
} };
565 SecKeychainAttributeList itemAttrList
= { sizeof(itemAttrs
) / sizeof(itemAttrs
[0]), itemAttrs
};
566 prefItem
->getContent(NULL
, &itemAttrList
, NULL
, NULL
);
568 // find certificate, given persistent reference data
569 CFDataRef pItemRef
= CFDataCreateWithBytesNoCopy(NULL
, (const UInt8
*)itemAttrs
[0].data
, itemAttrs
[0].length
, kCFAllocatorNull
);
570 SecKeychainItemRef certItemRef
= nil
;
571 OSStatus status
= SecKeychainItemCopyFromPersistentReference(pItemRef
, &certItemRef
); //%%% need to make this a method of ItemImpl
572 prefItem
->freeContent(&itemAttrList
, NULL
);
578 *certificate
= (SecCertificateRef
)certItemRef
;
584 SecCertificateCopyPreferred(
588 // This function will look for a matching preference in the following order:
589 // - matches the name and the supplied key use
590 // - matches the name and the special 'ANY' key use
591 // - matches the name with no key usage constraint
593 SecCertificateRef certRef
= NULL
;
594 CSSM_KEYUSE keyUse
= ConvertArrayToKeyUsage(keyUsage
);
595 OSStatus status
= SecCertificateCopyPreference(name
, keyUse
, &certRef
);
596 if (status
!= errSecSuccess
&& keyUse
!= CSSM_KEYUSE_ANY
)
597 status
= SecCertificateCopyPreference(name
, CSSM_KEYUSE_ANY
, &certRef
);
598 if (status
!= errSecSuccess
&& keyUse
!= 0)
599 status
= SecCertificateCopyPreference(name
, 0, &certRef
);
605 SecCertificateFindPreferenceItemWithNameAndKeyUsage(
606 CFTypeRef keychainOrArray
,
609 SecKeychainItemRef
*itemRef
)
613 StorageManager::KeychainList keychains
;
614 globals().storageManager
.optionalSearchList(keychainOrArray
, keychains
);
615 KCCursor
cursor(keychains
, kSecGenericPasswordItemClass
, NULL
);
617 char idUTF8
[MAXPATHLEN
];
618 idUTF8
[0] = (char)'\0';
621 if (!CFStringGetCString(name
, idUTF8
, sizeof(idUTF8
)-1, kCFStringEncodingUTF8
))
622 idUTF8
[0] = (char)'\0';
624 size_t idUTF8Len
= strlen(idUTF8
);
626 MacOSError::throwMe(errSecParam
);
628 CssmData
service(const_cast<char *>(idUTF8
), idUTF8Len
);
629 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecServiceItemAttr
), service
);
630 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecTypeItemAttr
), (FourCharCode
)'cprf');
632 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecScriptCodeItemAttr
), (sint32
)keyUsage
);
635 if (!cursor
->next(item
))
636 MacOSError::throwMe(errSecItemNotFound
);
639 *itemRef
=item
->handle();
645 OSStatus
SecCertificateDeletePreferenceItemWithNameAndKeyUsage(
646 CFTypeRef keychainOrArray
,
650 // when a specific key usage is passed, we'll only match & delete that pref;
651 // when a key usage of 0 is passed, all matching prefs should be deleted.
652 // maxUsages represents the most matches there could theoretically be, so
653 // cut things off at that point if we're still finding items (if they can't
654 // be deleted for some reason, we'd never break out of the loop.)
657 SecKeychainItemRef item
= NULL
;
658 int count
= 0, maxUsages
= 12;
659 while (++count
<= maxUsages
&&
660 (status
= SecCertificateFindPreferenceItemWithNameAndKeyUsage(keychainOrArray
, name
, keyUsage
, &item
)) == errSecSuccess
) {
661 status
= SecKeychainItemDelete(item
);
666 // it's not an error if the item isn't found
667 return (status
== errSecItemNotFound
) ? errSecSuccess
: status
;
670 OSStatus
SecCertificateSetPreference(
671 SecCertificateRef certificate
,
673 CSSM_KEYUSE keyUsage
,
680 // treat NULL certificate as a request to clear the preference
681 // (note: if keyUsage is 0, this clears all key usage prefs for name)
682 return SecCertificateDeletePreferenceItemWithNameAndKeyUsage(NULL
, name
, keyUsage
);
687 // determine the account attribute
689 // This attribute must be synthesized from certificate label + pref item type + key usage,
690 // as only the account and service attributes can make a generic keychain item unique.
691 // For 'iprf' type items (but not 'cprf'), we append a trailing space. This insures that
692 // we can save a certificate preference if an identity preference already exists for the
693 // given service name, and vice-versa.
694 // If the key usage is 0 (i.e. the normal case), we omit the appended key usage string.
696 CFStringRef labelStr
= nil
;
697 Certificate::required(certificate
)->inferLabel(false, &labelStr
);
699 MacOSError::throwMe(errSecDataTooLarge
); // data is "in a format which cannot be displayed"
701 CFIndex accountUTF8Len
= CFStringGetMaximumSizeForEncoding(CFStringGetLength(labelStr
), kCFStringEncodingUTF8
) + 1;
702 const char *templateStr
= "%s [key usage 0x%X]";
703 const int keyUsageMaxStrLen
= 8;
704 accountUTF8Len
+= strlen(templateStr
) + keyUsageMaxStrLen
;
705 char accountUTF8
[accountUTF8Len
];
706 if (!CFStringGetCString(labelStr
, accountUTF8
, accountUTF8Len
-1, kCFStringEncodingUTF8
))
707 accountUTF8
[0] = (char)'\0';
709 snprintf(accountUTF8
, accountUTF8Len
-1, templateStr
, accountUTF8
, keyUsage
);
710 CssmData
account(const_cast<char *>(accountUTF8
), strlen(accountUTF8
));
713 // service attribute (name provided by the caller)
714 CFIndex serviceUTF8Len
= CFStringGetMaximumSizeForEncoding(CFStringGetLength(name
), kCFStringEncodingUTF8
) + 1;;
715 char serviceUTF8
[serviceUTF8Len
];
716 if (!CFStringGetCString(name
, serviceUTF8
, serviceUTF8Len
-1, kCFStringEncodingUTF8
))
717 serviceUTF8
[0] = (char)'\0';
718 CssmData
service(const_cast<char *>(serviceUTF8
), strlen(serviceUTF8
));
720 // look for existing preference item, in case this is an update
721 StorageManager::KeychainList keychains
;
722 globals().storageManager
.getSearchList(keychains
);
723 KCCursor
cursor(keychains
, kSecGenericPasswordItemClass
, NULL
);
724 FourCharCode itemType
= 'cprf';
725 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecServiceItemAttr
), service
);
726 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecTypeItemAttr
), itemType
);
728 cursor
->add(CSSM_DB_EQUAL
, Schema::attributeInfo(kSecScriptCodeItemAttr
), (sint32
)keyUsage
);
732 Item
item(kSecGenericPasswordItemClass
, 'aapl', 0, NULL
, false);
733 bool add
= (!cursor
->next(item
));
734 // at this point, we either have a new item to add or an existing item to update
736 // set item attribute values
737 item
->setAttribute(Schema::attributeInfo(kSecServiceItemAttr
), service
);
738 item
->setAttribute(Schema::attributeInfo(kSecTypeItemAttr
), itemType
);
739 item
->setAttribute(Schema::attributeInfo(kSecAccountItemAttr
), account
);
740 item
->setAttribute(Schema::attributeInfo(kSecScriptCodeItemAttr
), (sint32
)keyUsage
);
741 item
->setAttribute(Schema::attributeInfo(kSecLabelItemAttr
), service
);
747 // generic attribute (store persistent certificate reference)
748 CFDataRef pItemRef
= nil
;
749 Certificate::required(certificate
)->copyPersistentReference(pItemRef
);
751 MacOSError::throwMe(errSecInvalidItemRef
);
753 const UInt8
*dataPtr
= CFDataGetBytePtr(pItemRef
);
754 CFIndex dataLen
= CFDataGetLength(pItemRef
);
755 CssmData
pref(const_cast<void *>(reinterpret_cast<const void *>(dataPtr
)), dataLen
);
756 item
->setAttribute(Schema::attributeInfo(kSecGenericItemAttr
), pref
);
760 Keychain keychain
= nil
;
762 keychain
= globals().storageManager
.defaultKeychain();
763 if (!keychain
->exists())
764 MacOSError::throwMe(errSecNoSuchKeychain
); // Might be deleted or not available at this time.
767 keychain
= globals().storageManager
.defaultKeychainUI(item
);
773 catch (const MacOSError
&err
) {
774 if (err
.osStatus() != errSecDuplicateItem
)
775 throw; // if item already exists, fall through to update
783 OSStatus
SecCertificateSetPreferred(
784 SecCertificateRef certificate
,
788 CSSM_KEYUSE keyUse
= ConvertArrayToKeyUsage(keyUsage
);
789 return SecCertificateSetPreference(certificate
, name
, keyUse
, NULL
);
792 CFDictionaryRef
SecCertificateCopyValues(SecCertificateRef certificate
, CFArrayRef keys
, CFErrorRef
*error
)
794 CFDictionaryRef result
= NULL
;
795 OSStatus __secapiresult
;
798 CertificateValues
cv(certificate
);
799 result
= cv
.copyFieldValues(keys
,error
);
802 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
803 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
804 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
805 catch (...) { __secapiresult
=errSecInternalComponent
; }
809 CFStringRef
SecCertificateCopyLongDescription(CFAllocatorRef alloc
, SecCertificateRef certificate
, CFErrorRef
*error
)
811 return SecCertificateCopyShortDescription(alloc
, certificate
, error
);
814 CFStringRef
SecCertificateCopyShortDescription(CFAllocatorRef alloc
, SecCertificateRef certificate
, CFErrorRef
*error
)
816 CFStringRef result
= NULL
;
817 OSStatus __secapiresult
;
820 __secapiresult
= SecCertificateInferLabel(certificate
, &result
);
822 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
823 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
824 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
825 catch (...) { __secapiresult
=errSecInternalComponent
; }
826 if (error
!=NULL
&& __secapiresult
!=errSecSuccess
)
828 *error
= CFErrorCreate(kCFAllocatorDefault
, kCFErrorDomainOSStatus
,
829 __secapiresult
? __secapiresult
: CSSM_ERRCODE_INTERNAL_ERROR
, NULL
);
834 CFDataRef
SecCertificateCopySerialNumber(SecCertificateRef certificate
, CFErrorRef
*error
)
836 CFDataRef result
= NULL
;
837 OSStatus __secapiresult
;
840 CertificateValues
cv(certificate
);
841 result
= cv
.copySerialNumber(error
);
844 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
845 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
846 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
847 catch (...) { __secapiresult
=errSecInternalComponent
; }
851 CFDataRef
SecCertificateCopyNormalizedIssuerContent(SecCertificateRef certificate
, CFErrorRef
*error
)
853 CFDataRef result
= NULL
;
854 OSStatus __secapiresult
;
857 CertificateValues
cv(certificate
);
858 result
= cv
.copyNormalizedIssuerContent(error
);
861 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
862 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
863 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
864 catch (...) { __secapiresult
=errSecInternalComponent
; }
868 CFDataRef
SecCertificateCopyNormalizedSubjectContent(SecCertificateRef certificate
, CFErrorRef
*error
)
870 CFDataRef result
= NULL
;
871 OSStatus __secapiresult
;
874 CertificateValues
cv(certificate
);
875 result
= cv
.copyNormalizedSubjectContent(error
);
878 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
879 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
880 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
881 catch (...) { __secapiresult
=errSecInternalComponent
; }
885 CFDataRef
SecCertificateCopyIssuerSequence(SecCertificateRef certificate
)
887 CFDataRef result
= NULL
;
888 OSStatus __secapiresult
;
891 CertificateValues
cv(certificate
);
892 result
= cv
.copyIssuerSequence(NULL
);
895 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
896 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
897 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
898 catch (...) { __secapiresult
=errSecInternalComponent
; }
902 CFDataRef
SecCertificateCopySubjectSequence(SecCertificateRef certificate
)
904 CFDataRef result
= NULL
;
905 OSStatus __secapiresult
;
908 CertificateValues
cv(certificate
);
909 result
= cv
.copySubjectSequence(NULL
);
912 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
913 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
914 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
915 catch (...) { __secapiresult
=errSecInternalComponent
; }
919 bool SecCertificateIsValid(SecCertificateRef certificate
, CFAbsoluteTime verifyTime
)
922 OSStatus __secapiresult
;
925 CFErrorRef error
= NULL
;
926 CertificateValues
cv(certificate
);
927 result
= cv
.isValid(verifyTime
, &error
);
928 if (error
) CFRelease(error
);
931 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
932 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
933 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
934 catch (...) { __secapiresult
=errSecInternalComponent
; }
939 * deprecated function name
941 bool SecCertificateIsValidX(SecCertificateRef certificate
, CFAbsoluteTime verifyTime
)
943 return SecCertificateIsValid(certificate
, verifyTime
);
947 CFAbsoluteTime
SecCertificateNotValidBefore(SecCertificateRef certificate
)
949 CFAbsoluteTime result
= 0;
950 OSStatus __secapiresult
;
953 CFErrorRef error
= NULL
;
954 CertificateValues
cv(certificate
);
955 result
= cv
.notValidBefore(&error
);
956 if (error
) CFRelease(error
);
959 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
960 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
961 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
962 catch (...) { __secapiresult
=errSecInternalComponent
; }
966 CFAbsoluteTime
SecCertificateNotValidAfter(SecCertificateRef certificate
)
968 CFAbsoluteTime result
= 0;
969 OSStatus __secapiresult
;
972 CFErrorRef error
= NULL
;
973 CertificateValues
cv(certificate
);
974 result
= cv
.notValidAfter(&error
);
975 if (error
) CFRelease(error
);
978 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
979 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
980 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
981 catch (...) { __secapiresult
=errSecInternalComponent
; }
986 SecCertificateRef
SecCertificateCreateWithBytes(CFAllocatorRef allocator
,
987 const UInt8
*bytes
, CFIndex length
)
989 SecCertificateRef certificate
= NULL
;
990 OSStatus __secapiresult
;
992 CSSM_DATA cssmCertData
= { (CSSM_SIZE
)length
, (uint8
*)bytes
};
994 //NOTE: there isn't yet a Certificate constructor which accepts a CFAllocatorRef
995 SecPointer
<Certificate
> certificatePtr(new Certificate(cssmCertData
, CSSM_CERT_X_509v3
, CSSM_CERT_ENCODING_DER
));
996 certificate
= certificatePtr
->handle();
998 __secapiresult
=errSecSuccess
;
1000 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1001 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1002 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1003 catch (...) { __secapiresult
=errSecInternalComponent
; }
1008 CFIndex
SecCertificateGetLength(SecCertificateRef certificate
)
1011 OSStatus __secapiresult
;
1013 CssmData output
= Certificate::required(certificate
)->data();
1014 length
= (CFIndex
)output
.length();
1015 __secapiresult
=errSecSuccess
;
1017 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1018 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1019 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1020 catch (...) { __secapiresult
=errSecInternalComponent
; }
1025 const UInt8
*SecCertificateGetBytePtr(SecCertificateRef certificate
)
1027 const UInt8
*bytes
= NULL
;
1028 OSStatus __secapiresult
;
1030 CssmData output
= Certificate::required(certificate
)->data();
1031 bytes
= (const UInt8
*)output
.data();
1032 __secapiresult
=errSecSuccess
;
1034 catch (const MacOSError
&err
) { __secapiresult
=err
.osStatus(); }
1035 catch (const CommonError
&err
) { __secapiresult
=SecKeychainErrFromOSStatus(err
.osStatus()); }
1036 catch (const std::bad_alloc
&) { __secapiresult
=errSecAllocate
; }
1037 catch (...) { __secapiresult
=errSecInternalComponent
; }
1041 static CFArrayRef
CopyEscrowCertificates(SecCertificateEscrowRootType escrowRootType
, CFErrorRef
*error
)
1043 // Return array of CFDataRef certificates.
1044 CFArrayRef result
= NULL
;
1048 // Get the hard coded set of production roots
1049 // static struct RootRecord* kProductionEscrowRoots[] = {&kOldEscrowRootRecord, &kProductionEscrowRootRecord};
1051 struct RootRecord
** pEscrowRoots
= NULL
;
1052 switch (escrowRootType
) {
1053 case kSecCertificateBaselineEscrowRoot
:
1054 numRoots
= kNumberOfBaseLineEscrowRoots
;
1055 pEscrowRoots
= kBaseLineEscrowRoots
;
1057 case kSecCertificateProductionEscrowRoot
:
1058 numRoots
= kNumberOfBaseLineEscrowRoots
; //%%% currently, production == baseline on OS X
1059 pEscrowRoots
= kBaseLineEscrowRoots
;
1061 case kSecCertificateBaselinePCSEscrowRoot
:
1062 numRoots
= kNumberOfBaseLinePCSEscrowRoots
;
1063 pEscrowRoots
= kBaseLinePCSEscrowRoots
;
1065 case kSecCertificateProductionPCSEscrowRoot
:
1066 numRoots
= kNumberOfBaseLinePCSEscrowRoots
; //%%% currently, production == baseline on OS X
1067 pEscrowRoots
= kBaseLinePCSEscrowRoots
;
1073 CFDataRef productionCerts
[numRoots
];
1074 struct RootRecord
* pRootRecord
= NULL
;
1076 for (iCnt
= 0; pEscrowRoots
!= NULL
&& iCnt
< numRoots
; iCnt
++)
1078 pRootRecord
= pEscrowRoots
[iCnt
];
1079 if (NULL
!= pRootRecord
&& pRootRecord
->_length
> 0 && NULL
!= pRootRecord
->_bytes
)
1081 productionCerts
[iCnt
] = CFDataCreate(kCFAllocatorDefault
, pRootRecord
->_bytes
, pRootRecord
->_length
);
1084 result
= CFArrayCreate(kCFAllocatorDefault
, (const void **)productionCerts
, numRoots
, &kCFTypeArrayCallBacks
);
1085 for (iCnt
= 0; iCnt
< numRoots
; iCnt
++)
1087 if (NULL
!= productionCerts
[iCnt
])
1089 CFRelease(productionCerts
[iCnt
]);
1097 CFArrayRef
SecCertificateCopyEscrowRoots(SecCertificateEscrowRootType escrowRootType
)
1099 CFArrayRef result
= NULL
;
1102 CFDataRef certData
= NULL
;
1104 // The request is for the base line certificates.
1105 // Use the hard coded data to generate the return array
1106 if (kSecCertificateBaselineEscrowRoot
== escrowRootType
)
1108 // Get the hard coded set of roots
1109 numRoots
= kNumberOfBaseLineEscrowRoots
;
1110 SecCertificateRef baseLineCerts
[numRoots
];
1111 struct RootRecord
* pRootRecord
= NULL
;
1113 for (iCnt
= 0; iCnt
< numRoots
; iCnt
++)
1115 pRootRecord
= kBaseLineEscrowRoots
[iCnt
];
1116 if (NULL
!= pRootRecord
&& pRootRecord
->_length
> 0 && NULL
!= pRootRecord
->_bytes
)
1118 certData
= CFDataCreate(kCFAllocatorDefault
, pRootRecord
->_bytes
, pRootRecord
->_length
);
1119 if (NULL
!= certData
)
1121 baseLineCerts
[iCnt
] = SecCertificateCreateWithData(kCFAllocatorDefault
, certData
);
1122 CFRelease(certData
);
1126 result
= CFArrayCreate(kCFAllocatorDefault
, (const void **)baseLineCerts
, numRoots
, &kCFTypeArrayCallBacks
);
1127 for (iCnt
= 0; iCnt
< numRoots
; iCnt
++)
1129 if (NULL
!= baseLineCerts
[iCnt
])
1131 CFRelease(baseLineCerts
[iCnt
]);
1135 // The request is for the current certificates.
1138 CFErrorRef error
= NULL
;
1139 CFArrayRef cert_datas
= CopyEscrowCertificates(escrowRootType
, &error
);
1140 if (NULL
!= error
|| NULL
== cert_datas
|| 0 == (numRoots
= (int)CFArrayGetCount(cert_datas
)))
1147 if (NULL
!= cert_datas
)
1149 CFRelease(cert_datas
);
1154 SecCertificateRef assetCerts
[numRoots
];
1155 for (iCnt
= 0; iCnt
< numRoots
; iCnt
++)
1157 certData
= (CFDataRef
)CFArrayGetValueAtIndex(cert_datas
, iCnt
);
1158 if (NULL
!= certData
)
1160 SecCertificateRef aCertRef
= SecCertificateCreateWithData(kCFAllocatorDefault
, certData
);
1161 assetCerts
[iCnt
] = aCertRef
;
1165 assetCerts
[iCnt
] = NULL
;
1171 result
= CFArrayCreate(kCFAllocatorDefault
, (const void **)assetCerts
, numRoots
, &kCFTypeArrayCallBacks
);
1172 for (iCnt
= 0; iCnt
< numRoots
; iCnt
++)
1174 if (NULL
!= assetCerts
[iCnt
])
1176 CFRelease(assetCerts
[iCnt
]);
1180 CFRelease(cert_datas
);