]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 | 1 | /* |
fa7225c8 | 2 | * Copyright (c) 2002-2016 Apple Inc. All Rights Reserved. |
b1ab9ed8 A |
3 | * |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
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 | |
11 | * file. | |
12 | * | |
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. | |
20 | * | |
21 | * @APPLE_LICENSE_HEADER_END@ | |
22 | */ | |
23 | ||
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> | |
35 | ||
36 | #include "SecBridge.h" | |
37 | ||
38 | // %%% used by SecCertificate{Copy,Set}Preference | |
39 | #include <Security/SecKeychainItemPriv.h> | |
40 | #include <Security/SecIdentityPriv.h> | |
b04fe171 | 41 | #include <Security/SecItemPriv.h> |
b1ab9ed8 A |
42 | #include <security_keychain/KCCursor.h> |
43 | #include <security_cdsa_utilities/Schema.h> | |
5c19dc3a | 44 | #include <security_cdsa_utils/cuCdsaUtils.h> |
b1ab9ed8 | 45 | #include <sys/param.h> |
5c19dc3a | 46 | #include <syslog.h> |
b1ab9ed8 | 47 | #include "CertificateValues.h" |
d64be36e | 48 | #include "LegacyAPICounts.h" |
427c49bc | 49 | |
5c19dc3a | 50 | OSStatus SecCertificateGetCLHandle_legacy(SecCertificateRef certificate, CSSM_CL_HANDLE *clHandle); |
b1ab9ed8 A |
51 | extern CSSM_KEYUSE ConvertArrayToKeyUsage(CFArrayRef usage); |
52 | ||
427c49bc | 53 | |
427c49bc | 54 | |
b1ab9ed8 A |
55 | |
56 | using namespace CssmClient; | |
57 | ||
6b200bc3 | 58 | CFTypeID static SecCertificateGetTypeID_osx(void) |
b1ab9ed8 A |
59 | { |
60 | BEGIN_SECAPI | |
61 | ||
62 | return gTypes().Certificate.typeID; | |
63 | ||
64 | END_SECAPI1(_kCFRuntimeNotATypeID) | |
65 | } | |
fa7225c8 A |
66 | |
67 | Boolean | |
68 | SecCertificateIsItemImplInstance(SecCertificateRef certificate) | |
69 | { | |
70 | if (certificate == NULL) { | |
71 | return false; | |
72 | } | |
6b200bc3 | 73 | |
fa7225c8 A |
74 | CFTypeID typeID = CFGetTypeID(certificate); |
75 | ||
fa7225c8 A |
76 | if (typeID == _kCFRuntimeNotATypeID) { |
77 | return false; | |
78 | } | |
79 | ||
80 | return (typeID == SecCertificateGetTypeID_osx() || | |
81 | typeID == SecKeychainItemGetTypeID()) ? true : false; | |
fa7225c8 | 82 | } |
b1ab9ed8 | 83 | |
5c19dc3a A |
84 | /* convert a new-world SecCertificateRef to an old-world ItemImpl instance */ |
85 | SecCertificateRef | |
86 | SecCertificateCreateItemImplInstance(SecCertificateRef certificate) | |
87 | { | |
5c19dc3a A |
88 | if (!certificate) { |
89 | return NULL; | |
90 | } | |
91 | SecCertificateRef implCertRef = (SecCertificateRef) SecCertificateCopyKeychainItem(certificate); | |
92 | if (implCertRef) { | |
93 | return implCertRef; | |
94 | } | |
95 | CFDataRef data = SecCertificateCopyData(certificate); | |
96 | if (!data) { | |
97 | return NULL; | |
98 | } | |
99 | try { | |
100 | CSSM_DATA cssmCertData; | |
101 | cssmCertData.Length = (data) ? (CSSM_SIZE)CFDataGetLength(data) : 0; | |
102 | cssmCertData.Data = (data) ? (uint8 *)CFDataGetBytePtr(data) : NULL; | |
b1ab9ed8 | 103 | |
5c19dc3a A |
104 | SecPointer<Certificate> certificatePtr(new Certificate(cssmCertData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER)); |
105 | implCertRef = certificatePtr->handle(); | |
106 | } | |
107 | catch (...) {} | |
108 | CFRelease(data); | |
109 | return implCertRef; | |
5c19dc3a A |
110 | } |
111 | ||
112 | /* convert an old-world ItemImpl instance to a new-world SecCertificateRef */ | |
113 | SecCertificateRef | |
114 | SecCertificateCreateFromItemImplInstance(SecCertificateRef certificate) | |
115 | { | |
5c19dc3a A |
116 | if (!certificate) { |
117 | return NULL; | |
118 | } | |
119 | SecCertificateRef result = NULL; | |
120 | CFDataRef data = NULL; | |
121 | try { | |
122 | CssmData certData = Certificate::required(certificate)->data(); | |
123 | if (certData.Data && certData.Length) { | |
124 | data = CFDataCreate(NULL, certData.Data, certData.Length); | |
125 | } | |
126 | if (!data) { | |
127 | if (certData.Data && !certData.Length) { | |
128 | /* zero-length certs can exist, so don't bother logging this */ | |
129 | } | |
130 | else { | |
131 | syslog(LOG_ERR, "WARNING: SecKeychainSearchCopyNext failed to retrieve certificate data (length=%ld, data=0x%lX)", | |
132 | (long)certData.Length, (uintptr_t)certData.Data); | |
133 | } | |
134 | return NULL; | |
135 | } | |
136 | } | |
137 | catch (...) {} | |
138 | ||
139 | result = SecCertificateCreateWithKeychainItem(NULL, data, certificate); | |
140 | if (data) | |
141 | CFRelease(data); | |
142 | return result; | |
5c19dc3a A |
143 | } |
144 | ||
fa7225c8 | 145 | |
5c19dc3a | 146 | /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */ |
b1ab9ed8 A |
147 | OSStatus |
148 | SecCertificateCreateFromData(const CSSM_DATA *data, CSSM_CERT_TYPE type, CSSM_CERT_ENCODING encoding, SecCertificateRef *certificate) | |
149 | { | |
5c19dc3a A |
150 | /* bridge to support old functionality */ |
151 | if (!data || !data->Data || !data->Length || !certificate) { | |
152 | return errSecParam; | |
153 | } | |
154 | SecCertificateRef certRef = NULL; | |
fa7225c8 A |
155 | |
156 | // <rdar://problem/24403998> REG: Adobe {Photoshop, InDesign} CC(2015) crashes on launch | |
157 | // If you take the length that SecKeychainItemCopyContent gives you (a Uint32) and assign it incorrectly | |
158 | // to a CSSM_DATA Length field (a CSSM_SIZE, i.e., a size_t), the upper 32 bits aren't set. If those bits | |
159 | // are non-zero, the length is incredibly wrong. | |
160 | // | |
161 | // Assume that there will not exist a certificate > 4GiB, and fake this length field. | |
162 | CSSM_SIZE length = data->Length & 0xfffffffful; | |
163 | ||
164 | CFDataRef dataRef = CFDataCreate(NULL, data->Data, length); | |
5c19dc3a A |
165 | if (dataRef) { |
166 | certRef = SecCertificateCreateWithData(NULL, dataRef); | |
167 | CFRelease(dataRef); | |
168 | } | |
169 | *certificate = certRef; | |
170 | return (certRef) ? errSecSuccess : errSecUnknownFormat; | |
b1ab9ed8 A |
171 | } |
172 | ||
5c19dc3a | 173 | /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA) */ |
b1ab9ed8 A |
174 | OSStatus |
175 | SecCertificateAddToKeychain(SecCertificateRef certificate, SecKeychainRef keychain) | |
176 | { | |
fa7225c8 | 177 | // This macro creates an ItemImpl certificate if it does not exist |
5c19dc3a | 178 | BEGIN_SECCERTAPI |
b1ab9ed8 | 179 | |
5c19dc3a | 180 | Item item(Certificate::required(__itemImplRef)); |
b1ab9ed8 A |
181 | Keychain::optional(keychain)->add(item); |
182 | ||
5c19dc3a | 183 | END_SECCERTAPI |
b1ab9ed8 A |
184 | } |
185 | ||
5c19dc3a | 186 | /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */ |
b1ab9ed8 A |
187 | OSStatus |
188 | SecCertificateGetData(SecCertificateRef certificate, CSSM_DATA_PTR data) | |
189 | { | |
5c19dc3a | 190 | BEGIN_SECCERTAPI |
b1ab9ed8 | 191 | |
fa7225c8 A |
192 | if (!certificate || !data) { |
193 | __secapiresult=errSecParam; | |
194 | } | |
195 | else if (SecCertificateIsItemImplInstance(certificate)) { | |
196 | Required(data) = Certificate::required(certificate)->data(); | |
197 | } | |
198 | else { | |
199 | data->Length = (CSSM_SIZE)SecCertificateGetLength(certificate); | |
200 | data->Data = (uint8*)SecCertificateGetBytePtr(certificate); | |
201 | } | |
b1ab9ed8 | 202 | |
5c19dc3a | 203 | END_SECCERTAPI |
e3d460c9 | 204 | } |
427c49bc | 205 | |
5c19dc3a | 206 | /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */ |
b1ab9ed8 A |
207 | OSStatus |
208 | SecCertificateGetType(SecCertificateRef certificate, CSSM_CERT_TYPE *certificateType) | |
209 | { | |
fa7225c8 | 210 | // This macro creates an ItemImpl certificate if it does not exist |
5c19dc3a | 211 | BEGIN_SECCERTAPI |
b1ab9ed8 | 212 | |
5c19dc3a | 213 | Required(certificateType) = Certificate::required(__itemImplRef)->type(); |
b1ab9ed8 | 214 | |
5c19dc3a | 215 | END_SECCERTAPI |
b1ab9ed8 A |
216 | } |
217 | ||
5c19dc3a | 218 | /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */ |
b1ab9ed8 A |
219 | OSStatus |
220 | SecCertificateGetSubject(SecCertificateRef certificate, const CSSM_X509_NAME **subject) | |
221 | { | |
fa7225c8 | 222 | // This macro creates an ItemImpl certificate if it does not exist |
5c19dc3a | 223 | BEGIN_SECCERTAPI |
b1ab9ed8 | 224 | |
5c19dc3a | 225 | Required(subject) = Certificate::required(__itemImplRef)->subjectName(); |
b1ab9ed8 | 226 | |
5c19dc3a | 227 | END_SECCERTAPI |
b1ab9ed8 A |
228 | } |
229 | ||
5c19dc3a | 230 | /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */ |
b1ab9ed8 A |
231 | OSStatus |
232 | SecCertificateGetIssuer(SecCertificateRef certificate, const CSSM_X509_NAME **issuer) | |
233 | { | |
fa7225c8 | 234 | // This macro creates an ItemImpl certificate if it does not exist |
5c19dc3a A |
235 | BEGIN_SECCERTAPI |
236 | ||
237 | Required(issuer) = Certificate::required(__itemImplRef)->issuerName(); | |
238 | ||
239 | END_SECCERTAPI | |
240 | } | |
241 | ||
242 | /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */ | |
243 | OSStatus | |
244 | SecCertificateGetCLHandle(SecCertificateRef certificate, CSSM_CL_HANDLE *clHandle) | |
245 | { | |
fa7225c8 | 246 | // This macro creates an ItemImpl certificate if it does not exist |
5c19dc3a A |
247 | BEGIN_SECCERTAPI |
248 | ||
249 | Required(clHandle) = Certificate::required(__itemImplRef)->clHandle(); | |
250 | ||
251 | END_SECCERTAPI | |
5c19dc3a | 252 | } |
b1ab9ed8 | 253 | |
5c19dc3a A |
254 | /* private function; assumes input is old-style ItemImpl certificate reference, |
255 | and does not release that certificate reference! | |
256 | */ | |
b1ab9ed8 | 257 | OSStatus |
5c19dc3a | 258 | SecCertificateGetCLHandle_legacy(SecCertificateRef certificate, CSSM_CL_HANDLE *clHandle) |
b1ab9ed8 A |
259 | { |
260 | BEGIN_SECAPI | |
261 | ||
5c19dc3a | 262 | Required(clHandle) = Certificate::required(certificate)->clHandle(); |
b1ab9ed8 A |
263 | |
264 | END_SECAPI | |
265 | } | |
266 | ||
267 | /* | |
268 | * Private API to infer a display name for a SecCertificateRef which | |
269 | * may or may not be in a keychain. | |
5c19dc3a A |
270 | * |
271 | * OS X only | |
b1ab9ed8 A |
272 | */ |
273 | OSStatus | |
274 | SecCertificateInferLabel(SecCertificateRef certificate, CFStringRef *label) | |
275 | { | |
fa7225c8 | 276 | // This macro creates an ItemImpl certificate if it does not exist |
5c19dc3a | 277 | BEGIN_SECCERTAPI |
b1ab9ed8 | 278 | |
5c19dc3a | 279 | Certificate::required(__itemImplRef)->inferLabel(false, &Required(label)); |
b1ab9ed8 | 280 | |
5c19dc3a | 281 | END_SECCERTAPI |
b1ab9ed8 A |
282 | } |
283 | ||
5c19dc3a | 284 | /* OS X only (note: iOS version has different arguments and return value) */ |
b1ab9ed8 A |
285 | OSStatus |
286 | SecCertificateCopyPublicKey(SecCertificateRef certificate, SecKeyRef *key) | |
287 | { | |
fa7225c8 | 288 | // This macro creates an ItemImpl certificate if it does not exist |
5c19dc3a | 289 | BEGIN_SECCERTAPI |
b1ab9ed8 | 290 | |
5c19dc3a | 291 | Required(key) = Certificate::required(__itemImplRef)->publicKey()->handle(); |
b1ab9ed8 | 292 | |
5c19dc3a | 293 | END_SECCERTAPI |
b1ab9ed8 A |
294 | } |
295 | ||
5c19dc3a | 296 | /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */ |
b1ab9ed8 A |
297 | OSStatus |
298 | SecCertificateGetAlgorithmID(SecCertificateRef certificate, const CSSM_X509_ALGORITHM_IDENTIFIER **algid) | |
299 | { | |
fa7225c8 | 300 | // This macro creates an ItemImpl certificate if it does not exist |
5c19dc3a | 301 | BEGIN_SECCERTAPI |
b1ab9ed8 | 302 | |
5c19dc3a | 303 | Required(algid) = Certificate::required(__itemImplRef)->algorithmID(); |
b1ab9ed8 | 304 | |
5c19dc3a | 305 | END_SECCERTAPI |
b1ab9ed8 A |
306 | } |
307 | ||
5c19dc3a | 308 | /* OS X only */ |
b1ab9ed8 A |
309 | OSStatus |
310 | SecCertificateCopySubjectComponent(SecCertificateRef certificate, const CSSM_OID *component, CFStringRef *result) | |
311 | { | |
fa7225c8 | 312 | // This macro creates an ItemImpl certificate if it does not exist |
5c19dc3a | 313 | BEGIN_SECCERTAPI |
b1ab9ed8 | 314 | |
5c19dc3a | 315 | Required(result) = Certificate::required(__itemImplRef)->distinguishedName(&CSSMOID_X509V1SubjectNameCStruct, component); |
b1ab9ed8 | 316 | |
5c19dc3a | 317 | END_SECCERTAPI |
b1ab9ed8 A |
318 | } |
319 | ||
5c19dc3a | 320 | /* OS X only; deprecated SPI */ |
b1ab9ed8 A |
321 | OSStatus |
322 | SecCertificateGetCommonName(SecCertificateRef certificate, CFStringRef *commonName) | |
323 | { | |
324 | // deprecated SPI signature; replaced by SecCertificateCopyCommonName | |
325 | return SecCertificateCopyCommonName(certificate, commonName); | |
326 | } | |
327 | ||
5c19dc3a | 328 | /* OS X only; deprecated SPI */ |
b1ab9ed8 A |
329 | OSStatus |
330 | SecCertificateGetEmailAddress(SecCertificateRef certificate, CFStringRef *emailAddress) | |
331 | { | |
fa7225c8 | 332 | // This macro creates an ItemImpl certificate if it does not exist |
5c19dc3a | 333 | BEGIN_SECCERTAPI |
b1ab9ed8 | 334 | |
5c19dc3a | 335 | Required(emailAddress) = Certificate::required(__itemImplRef)->copyFirstEmailAddress(); |
b1ab9ed8 | 336 | |
5c19dc3a | 337 | END_SECCERTAPI |
b1ab9ed8 A |
338 | } |
339 | ||
5c19dc3a A |
340 | /* Return a zero terminated list of CSSM_DATA_PTR's with the values of the field specified by field. |
341 | * Caller must call releaseFieldValues to free the storage allocated by this call. | |
342 | * | |
343 | * OS X only | |
344 | */ | |
b1ab9ed8 A |
345 | OSStatus |
346 | SecCertificateCopyFieldValues(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR **fieldValues) | |
347 | { | |
fa7225c8 | 348 | // This macro creates an ItemImpl certificate if it does not exist |
5c19dc3a | 349 | BEGIN_SECCERTAPI |
b1ab9ed8 | 350 | |
5c19dc3a | 351 | Required(fieldValues) = Certificate::required(__itemImplRef)->copyFieldValues(Required(field)); |
b1ab9ed8 | 352 | |
5c19dc3a | 353 | END_SECCERTAPI |
b1ab9ed8 A |
354 | } |
355 | ||
5c19dc3a | 356 | /* OS X only */ |
b1ab9ed8 A |
357 | OSStatus |
358 | SecCertificateReleaseFieldValues(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR *fieldValues) | |
359 | { | |
fa7225c8 | 360 | // This macro creates an ItemImpl certificate if it does not exist |
5c19dc3a | 361 | BEGIN_SECCERTAPI |
b1ab9ed8 | 362 | |
5c19dc3a | 363 | Certificate::required(__itemImplRef)->releaseFieldValues(Required(field), fieldValues); |
b1ab9ed8 | 364 | |
5c19dc3a | 365 | END_SECCERTAPI |
b1ab9ed8 A |
366 | } |
367 | ||
5c19dc3a | 368 | /* OS X only */ |
b1ab9ed8 A |
369 | OSStatus |
370 | SecCertificateCopyFirstFieldValue(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR *fieldValue) | |
371 | { | |
fa7225c8 | 372 | // This macro creates an ItemImpl certificate if it does not exist |
5c19dc3a | 373 | BEGIN_SECCERTAPI |
b1ab9ed8 | 374 | |
5c19dc3a | 375 | Required(fieldValue) = Certificate::required(__itemImplRef)->copyFirstFieldValue(Required(field)); |
b1ab9ed8 | 376 | |
5c19dc3a | 377 | END_SECCERTAPI |
b1ab9ed8 A |
378 | } |
379 | ||
5c19dc3a | 380 | /* OS X only */ |
b1ab9ed8 A |
381 | OSStatus |
382 | SecCertificateReleaseFirstFieldValue(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR fieldValue) | |
383 | { | |
fa7225c8 | 384 | // This macro creates an ItemImpl certificate if it does not exist |
5c19dc3a | 385 | BEGIN_SECCERTAPI |
b1ab9ed8 | 386 | |
5c19dc3a | 387 | Certificate::required(__itemImplRef)->releaseFieldValue(Required(field), fieldValue); |
b1ab9ed8 | 388 | |
5c19dc3a | 389 | END_SECCERTAPI |
b1ab9ed8 A |
390 | } |
391 | ||
5c19dc3a | 392 | /* OS X only */ |
b1ab9ed8 A |
393 | OSStatus |
394 | SecCertificateFindByIssuerAndSN(CFTypeRef keychainOrArray,const CSSM_DATA *issuer, | |
395 | const CSSM_DATA *serialNumber, SecCertificateRef *certificate) | |
396 | { | |
b04fe171 A |
397 | if (issuer && serialNumber) { |
398 | CFRef<CFMutableDictionaryRef> query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); | |
399 | CFDictionarySetValue(query, kSecClass, kSecClassCertificate); | |
400 | CFDictionarySetValue(query, kSecReturnRef, kCFBooleanTrue); | |
b54c578e | 401 | CFDictionarySetValue(query, kSecUseDataProtectionKeychain, kCFBooleanTrue); |
b04fe171 A |
402 | |
403 | CFRef<CFDataRef> issuerData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8 *)issuer->Data, issuer->Length, kCFAllocatorNull); | |
404 | CFDictionarySetValue(query, kSecAttrIssuer, issuerData); | |
405 | ||
406 | CFRef<CFDataRef> serialNumberData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8 *)serialNumber->Data, serialNumber->Length, kCFAllocatorNull); | |
407 | CFDictionarySetValue(query, kSecAttrSerialNumber, serialNumberData); | |
408 | ||
409 | OSStatus status = SecItemCopyMatching(query, (CFTypeRef*)certificate); | |
410 | if (status == errSecSuccess) { | |
411 | return status; | |
412 | } | |
413 | } | |
414 | ||
b1ab9ed8 A |
415 | BEGIN_SECAPI |
416 | ||
417 | StorageManager::KeychainList keychains; | |
418 | globals().storageManager.optionalSearchList(keychainOrArray, keychains); | |
419 | Required(certificate) = Certificate::findByIssuerAndSN(keychains, CssmData::required(issuer), CssmData::required(serialNumber))->handle(); | |
420 | ||
5c19dc3a A |
421 | // convert ItemImpl-based SecCertificateRef to new-world version before returning |
422 | CssmData certData = Certificate::required(*certificate)->data(); | |
423 | CFRef<CFDataRef> cfData(CFDataCreate(NULL, certData.Data, certData.Length)); | |
424 | SecCertificateRef tmpRef = *certificate; | |
425 | *certificate = SecCertificateCreateWithData(NULL, cfData); | |
426 | CFRelease(tmpRef); | |
5c19dc3a | 427 | |
b1ab9ed8 A |
428 | END_SECAPI |
429 | } | |
430 | ||
5c19dc3a | 431 | /* OS X only */ |
b1ab9ed8 A |
432 | OSStatus |
433 | SecCertificateFindBySubjectKeyID(CFTypeRef keychainOrArray, const CSSM_DATA *subjectKeyID, | |
434 | SecCertificateRef *certificate) | |
435 | { | |
b04fe171 A |
436 | if (subjectKeyID) { |
437 | CFRef<CFMutableDictionaryRef> query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); | |
438 | CFDictionarySetValue(query, kSecClass, kSecClassCertificate); | |
439 | CFDictionarySetValue(query, kSecReturnRef, kCFBooleanTrue); | |
b54c578e | 440 | CFDictionarySetValue(query, kSecUseDataProtectionKeychain, kCFBooleanTrue); |
b04fe171 A |
441 | |
442 | CFRef<CFDataRef> subjectKeyIDData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8 *)subjectKeyID->Data, subjectKeyID->Length, kCFAllocatorNull); | |
443 | CFDictionarySetValue(query, kSecAttrSubjectKeyID, subjectKeyIDData); | |
444 | ||
445 | OSStatus status = SecItemCopyMatching(query, (CFTypeRef*)certificate); | |
446 | if (status == errSecSuccess) { | |
447 | return status; | |
448 | } | |
449 | } | |
450 | ||
451 | BEGIN_SECAPI | |
b1ab9ed8 A |
452 | |
453 | StorageManager::KeychainList keychains; | |
454 | globals().storageManager.optionalSearchList(keychainOrArray, keychains); | |
455 | Required(certificate) = Certificate::findBySubjectKeyID(keychains, CssmData::required(subjectKeyID))->handle(); | |
456 | ||
5c19dc3a A |
457 | // convert ItemImpl-based SecCertificateRef to new-world version before returning |
458 | CssmData certData = Certificate::required(*certificate)->data(); | |
459 | CFRef<CFDataRef> cfData(CFDataCreate(NULL, certData.Data, certData.Length)); | |
460 | SecCertificateRef tmpRef = *certificate; | |
461 | *certificate = SecCertificateCreateWithData(NULL, cfData); | |
462 | CFRelease(tmpRef); | |
5c19dc3a | 463 | |
b1ab9ed8 A |
464 | END_SECAPI |
465 | } | |
466 | ||
5c19dc3a | 467 | /* OS X only */ |
b1ab9ed8 A |
468 | OSStatus |
469 | SecCertificateFindByEmail(CFTypeRef keychainOrArray, const char *emailAddress, SecCertificateRef *certificate) | |
470 | { | |
b04fe171 A |
471 | if (emailAddress) { |
472 | CFRef<CFMutableDictionaryRef> query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); | |
473 | CFDictionarySetValue(query, kSecClass, kSecClassCertificate); | |
474 | CFDictionarySetValue(query, kSecReturnRef, kCFBooleanTrue); | |
b54c578e | 475 | CFDictionarySetValue(query, kSecUseDataProtectionKeychain, kCFBooleanTrue); |
b04fe171 A |
476 | |
477 | CFRef<CFStringRef> emailAddressString = CFStringCreateWithCString(kCFAllocatorDefault, emailAddress, kCFStringEncodingUTF8); | |
478 | CFTypeRef keys[] = { kSecPolicyName }; | |
479 | CFTypeRef values[] = { emailAddressString }; | |
480 | CFRef<CFDictionaryRef> properties = CFDictionaryCreate(kCFAllocatorDefault, keys, values, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); | |
481 | CFRef<SecPolicyRef> policy = SecPolicyCreateWithProperties(kSecPolicyAppleSMIME, properties); | |
482 | CFDictionarySetValue(query, kSecMatchPolicy, policy); | |
483 | ||
484 | OSStatus status = SecItemCopyMatching(query, (CFTypeRef*)certificate); | |
485 | if (status == errSecSuccess) { | |
486 | return status; | |
487 | } | |
488 | } | |
489 | ||
490 | BEGIN_SECAPI | |
b1ab9ed8 A |
491 | |
492 | StorageManager::KeychainList keychains; | |
493 | globals().storageManager.optionalSearchList(keychainOrArray, keychains); | |
494 | Required(certificate) = Certificate::findByEmail(keychains, emailAddress)->handle(); | |
495 | ||
5c19dc3a A |
496 | // convert ItemImpl-based SecCertificateRef to new-world version before returning |
497 | CssmData certData = Certificate::required(*certificate)->data(); | |
498 | CFRef<CFDataRef> cfData(CFDataCreate(NULL, certData.Data, certData.Length)); | |
499 | SecCertificateRef tmpRef = *certificate; | |
500 | *certificate = SecCertificateCreateWithData(NULL, cfData); | |
501 | CFRelease(tmpRef); | |
5c19dc3a | 502 | |
b1ab9ed8 A |
503 | END_SECAPI |
504 | } | |
505 | ||
5c19dc3a | 506 | /* OS X only */ |
b1ab9ed8 A |
507 | OSStatus |
508 | SecKeychainSearchCreateForCertificateByIssuerAndSN(CFTypeRef keychainOrArray, const CSSM_DATA *issuer, | |
509 | const CSSM_DATA *serialNumber, SecKeychainSearchRef *searchRef) | |
510 | { | |
511 | BEGIN_SECAPI | |
512 | ||
513 | Required(searchRef); | |
514 | ||
515 | StorageManager::KeychainList keychains; | |
516 | globals().storageManager.optionalSearchList(keychainOrArray, keychains); | |
517 | KCCursor cursor(Certificate::cursorForIssuerAndSN(keychains, CssmData::required(issuer), CssmData::required(serialNumber))); | |
518 | *searchRef = cursor->handle(); | |
519 | ||
520 | END_SECAPI | |
521 | } | |
522 | ||
5c19dc3a | 523 | /* OS X only */ |
b1ab9ed8 A |
524 | OSStatus |
525 | SecKeychainSearchCreateForCertificateByIssuerAndSN_CF(CFTypeRef keychainOrArray, CFDataRef issuer, | |
526 | CFDataRef serialNumber, SecKeychainSearchRef *searchRef) | |
527 | { | |
528 | BEGIN_SECAPI | |
529 | ||
530 | Required(searchRef); | |
531 | ||
532 | StorageManager::KeychainList keychains; | |
533 | globals().storageManager.optionalSearchList(keychainOrArray, keychains); | |
534 | Required(issuer); | |
535 | Required(serialNumber); | |
536 | KCCursor cursor(Certificate::cursorForIssuerAndSN_CF(keychains, issuer, serialNumber)); | |
537 | *searchRef = cursor->handle(); | |
538 | ||
539 | END_SECAPI | |
540 | } | |
541 | ||
5c19dc3a | 542 | /* OS X only */ |
b1ab9ed8 A |
543 | OSStatus |
544 | SecKeychainSearchCreateForCertificateBySubjectKeyID(CFTypeRef keychainOrArray, const CSSM_DATA *subjectKeyID, | |
545 | SecKeychainSearchRef *searchRef) | |
546 | { | |
547 | BEGIN_SECAPI | |
548 | ||
549 | Required(searchRef); | |
550 | ||
551 | StorageManager::KeychainList keychains; | |
552 | globals().storageManager.optionalSearchList(keychainOrArray, keychains); | |
553 | KCCursor cursor(Certificate::cursorForSubjectKeyID(keychains, CssmData::required(subjectKeyID))); | |
554 | *searchRef = cursor->handle(); | |
555 | ||
556 | END_SECAPI | |
557 | } | |
558 | ||
5c19dc3a | 559 | /* OS X only */ |
b1ab9ed8 A |
560 | OSStatus |
561 | SecKeychainSearchCreateForCertificateByEmail(CFTypeRef keychainOrArray, const char *emailAddress, | |
562 | SecKeychainSearchRef *searchRef) | |
563 | { | |
564 | BEGIN_SECAPI | |
565 | ||
566 | Required(searchRef); | |
567 | ||
568 | StorageManager::KeychainList keychains; | |
569 | globals().storageManager.optionalSearchList(keychainOrArray, keychains); | |
570 | KCCursor cursor(Certificate::cursorForEmail(keychains, emailAddress)); | |
571 | *searchRef = cursor->handle(); | |
572 | ||
573 | END_SECAPI | |
574 | } | |
575 | ||
5c19dc3a | 576 | /* OS X only */ |
b1ab9ed8 A |
577 | CSSM_RETURN |
578 | SecDigestGetData (CSSM_ALGORITHMS alg, CSSM_DATA* digest, const CSSM_DATA* data) | |
579 | { | |
580 | BEGIN_SECAPI | |
581 | // sanity checking | |
582 | if (!digest || !digest->Data || !digest->Length || !data || !data->Data || !data->Length) | |
427c49bc | 583 | return errSecParam; |
b1ab9ed8 A |
584 | |
585 | CSP csp(gGuidAppleCSP); | |
586 | Digest context(csp, alg); | |
587 | CssmData input(data->Data, data->Length); | |
588 | CssmData output(digest->Data, digest->Length); | |
589 | ||
590 | context.digest(input, output); | |
591 | digest->Length = output.length(); | |
592 | ||
593 | return CSSM_OK; | |
594 | END_SECAPI1(1); | |
595 | } | |
596 | ||
5c19dc3a | 597 | /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */ |
b1ab9ed8 A |
598 | OSStatus |
599 | SecCertificateCopyPreference( | |
600 | CFStringRef name, | |
601 | CSSM_KEYUSE keyUsage, | |
602 | SecCertificateRef *certificate) | |
603 | { | |
604 | BEGIN_SECAPI | |
605 | ||
606 | Required(name); | |
607 | Required(certificate); | |
608 | StorageManager::KeychainList keychains; | |
609 | globals().storageManager.getSearchList(keychains); | |
610 | KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL); | |
611 | ||
612 | char idUTF8[MAXPATHLEN]; | |
613 | if (!CFStringGetCString(name, idUTF8, sizeof(idUTF8)-1, kCFStringEncodingUTF8)) | |
614 | idUTF8[0] = (char)'\0'; | |
615 | CssmData service(const_cast<char *>(idUTF8), strlen(idUTF8)); | |
616 | FourCharCode itemType = 'cprf'; | |
617 | cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service); | |
618 | cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), itemType); | |
d64be36e | 619 | if (keyUsage) { |
b1ab9ed8 | 620 | cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage); |
d64be36e | 621 | } |
b1ab9ed8 | 622 | |
d64be36e A |
623 | Item prefItem; |
624 | if (!cursor->next(prefItem)) { | |
625 | MacOSError::throwMe(errSecItemNotFound); | |
626 | } | |
b1ab9ed8 A |
627 | |
628 | // get persistent certificate reference | |
629 | SecKeychainAttribute itemAttrs[] = { { kSecGenericItemAttr, 0, NULL } }; | |
630 | SecKeychainAttributeList itemAttrList = { sizeof(itemAttrs) / sizeof(itemAttrs[0]), itemAttrs }; | |
631 | prefItem->getContent(NULL, &itemAttrList, NULL, NULL); | |
632 | ||
633 | // find certificate, given persistent reference data | |
634 | CFDataRef pItemRef = CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)itemAttrs[0].data, itemAttrs[0].length, kCFAllocatorNull); | |
635 | SecKeychainItemRef certItemRef = nil; | |
636 | OSStatus status = SecKeychainItemCopyFromPersistentReference(pItemRef, &certItemRef); //%%% need to make this a method of ItemImpl | |
637 | prefItem->freeContent(&itemAttrList, NULL); | |
638 | if (pItemRef) | |
639 | CFRelease(pItemRef); | |
640 | if (status) | |
641 | return status; | |
642 | ||
643 | *certificate = (SecCertificateRef)certItemRef; | |
644 | ||
fa7225c8 A |
645 | if (certItemRef && (CFGetTypeID(certItemRef) == SecIdentityGetTypeID())) { |
646 | // SecKeychainItemCopyFromPersistentReference handed out an identity reference | |
647 | *certificate = NULL; | |
648 | status = SecIdentityCopyCertificate((SecIdentityRef)certItemRef, certificate); | |
649 | CFRelease(certItemRef); | |
650 | return status; | |
651 | } | |
5c19dc3a | 652 | |
b1ab9ed8 A |
653 | END_SECAPI |
654 | } | |
655 | ||
5c19dc3a | 656 | /* OS X only */ |
b1ab9ed8 A |
657 | SecCertificateRef |
658 | SecCertificateCopyPreferred( | |
659 | CFStringRef name, | |
660 | CFArrayRef keyUsage) | |
661 | { | |
662 | // This function will look for a matching preference in the following order: | |
663 | // - matches the name and the supplied key use | |
664 | // - matches the name and the special 'ANY' key use | |
665 | // - matches the name with no key usage constraint | |
666 | ||
667 | SecCertificateRef certRef = NULL; | |
668 | CSSM_KEYUSE keyUse = ConvertArrayToKeyUsage(keyUsage); | |
669 | OSStatus status = SecCertificateCopyPreference(name, keyUse, &certRef); | |
427c49bc | 670 | if (status != errSecSuccess && keyUse != CSSM_KEYUSE_ANY) |
b1ab9ed8 | 671 | status = SecCertificateCopyPreference(name, CSSM_KEYUSE_ANY, &certRef); |
427c49bc | 672 | if (status != errSecSuccess && keyUse != 0) |
b1ab9ed8 A |
673 | status = SecCertificateCopyPreference(name, 0, &certRef); |
674 | ||
675 | return certRef; | |
676 | } | |
677 | ||
5c19dc3a | 678 | /* OS X only; not exported */ |
427c49bc | 679 | static OSStatus |
b1ab9ed8 A |
680 | SecCertificateFindPreferenceItemWithNameAndKeyUsage( |
681 | CFTypeRef keychainOrArray, | |
682 | CFStringRef name, | |
683 | int32_t keyUsage, | |
684 | SecKeychainItemRef *itemRef) | |
685 | { | |
686 | BEGIN_SECAPI | |
687 | ||
688 | StorageManager::KeychainList keychains; | |
689 | globals().storageManager.optionalSearchList(keychainOrArray, keychains); | |
690 | KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL); | |
691 | ||
692 | char idUTF8[MAXPATHLEN]; | |
693 | idUTF8[0] = (char)'\0'; | |
694 | if (name) | |
695 | { | |
696 | if (!CFStringGetCString(name, idUTF8, sizeof(idUTF8)-1, kCFStringEncodingUTF8)) | |
697 | idUTF8[0] = (char)'\0'; | |
698 | } | |
699 | size_t idUTF8Len = strlen(idUTF8); | |
700 | if (!idUTF8Len) | |
427c49bc | 701 | MacOSError::throwMe(errSecParam); |
b1ab9ed8 A |
702 | |
703 | CssmData service(const_cast<char *>(idUTF8), idUTF8Len); | |
704 | cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service); | |
705 | cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), (FourCharCode)'cprf'); | |
d64be36e | 706 | if (keyUsage) { |
b1ab9ed8 | 707 | cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage); |
d64be36e | 708 | } |
b1ab9ed8 A |
709 | |
710 | Item item; | |
711 | if (!cursor->next(item)) | |
712 | MacOSError::throwMe(errSecItemNotFound); | |
713 | ||
714 | if (itemRef) | |
715 | *itemRef=item->handle(); | |
716 | ||
717 | END_SECAPI | |
718 | } | |
719 | ||
5c19dc3a | 720 | /* OS X only; not exported */ |
427c49bc | 721 | static |
b1ab9ed8 A |
722 | OSStatus SecCertificateDeletePreferenceItemWithNameAndKeyUsage( |
723 | CFTypeRef keychainOrArray, | |
724 | CFStringRef name, | |
725 | int32_t keyUsage) | |
726 | { | |
727 | // when a specific key usage is passed, we'll only match & delete that pref; | |
728 | // when a key usage of 0 is passed, all matching prefs should be deleted. | |
729 | // maxUsages represents the most matches there could theoretically be, so | |
730 | // cut things off at that point if we're still finding items (if they can't | |
731 | // be deleted for some reason, we'd never break out of the loop.) | |
732 | ||
6b200bc3 | 733 | OSStatus status = errSecSuccess; |
b1ab9ed8 A |
734 | SecKeychainItemRef item = NULL; |
735 | int count = 0, maxUsages = 12; | |
736 | while (++count <= maxUsages && | |
427c49bc | 737 | (status = SecCertificateFindPreferenceItemWithNameAndKeyUsage(keychainOrArray, name, keyUsage, &item)) == errSecSuccess) { |
b1ab9ed8 A |
738 | status = SecKeychainItemDelete(item); |
739 | CFRelease(item); | |
740 | item = NULL; | |
741 | } | |
742 | ||
743 | // it's not an error if the item isn't found | |
427c49bc | 744 | return (status == errSecItemNotFound) ? errSecSuccess : status; |
b1ab9ed8 A |
745 | } |
746 | ||
5c19dc3a | 747 | /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA) */ |
b1ab9ed8 A |
748 | OSStatus SecCertificateSetPreference( |
749 | SecCertificateRef certificate, | |
750 | CFStringRef name, | |
751 | CSSM_KEYUSE keyUsage, | |
752 | CFDateRef date) | |
753 | { | |
754 | if (!name) { | |
427c49bc | 755 | return errSecParam; |
b1ab9ed8 A |
756 | } |
757 | if (!certificate) { | |
758 | // treat NULL certificate as a request to clear the preference | |
759 | // (note: if keyUsage is 0, this clears all key usage prefs for name) | |
760 | return SecCertificateDeletePreferenceItemWithNameAndKeyUsage(NULL, name, keyUsage); | |
761 | } | |
762 | ||
fa7225c8 | 763 | // This macro creates an ItemImpl certificate if it does not exist |
5c19dc3a | 764 | BEGIN_SECCERTAPI |
b1ab9ed8 A |
765 | |
766 | // determine the account attribute | |
767 | // | |
768 | // This attribute must be synthesized from certificate label + pref item type + key usage, | |
769 | // as only the account and service attributes can make a generic keychain item unique. | |
770 | // For 'iprf' type items (but not 'cprf'), we append a trailing space. This insures that | |
771 | // we can save a certificate preference if an identity preference already exists for the | |
772 | // given service name, and vice-versa. | |
773 | // If the key usage is 0 (i.e. the normal case), we omit the appended key usage string. | |
774 | // | |
775 | CFStringRef labelStr = nil; | |
5c19dc3a | 776 | Certificate::required(__itemImplRef)->inferLabel(false, &labelStr); |
b1ab9ed8 A |
777 | if (!labelStr) { |
778 | MacOSError::throwMe(errSecDataTooLarge); // data is "in a format which cannot be displayed" | |
779 | } | |
780 | CFIndex accountUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(labelStr), kCFStringEncodingUTF8) + 1; | |
781 | const char *templateStr = "%s [key usage 0x%X]"; | |
782 | const int keyUsageMaxStrLen = 8; | |
783 | accountUTF8Len += strlen(templateStr) + keyUsageMaxStrLen; | |
79b9da22 A |
784 | char *accountUTF8 = (char *)malloc(accountUTF8Len); |
785 | if (!accountUTF8) { | |
786 | MacOSError::throwMe(errSecMemoryError); | |
787 | } | |
b1ab9ed8 A |
788 | if (!CFStringGetCString(labelStr, accountUTF8, accountUTF8Len-1, kCFStringEncodingUTF8)) |
789 | accountUTF8[0] = (char)'\0'; | |
790 | if (keyUsage) | |
791 | snprintf(accountUTF8, accountUTF8Len-1, templateStr, accountUTF8, keyUsage); | |
79b9da22 A |
792 | CssmDataContainer account(const_cast<char *>(accountUTF8), strlen(accountUTF8)); |
793 | free(accountUTF8); | |
b1ab9ed8 A |
794 | CFRelease(labelStr); |
795 | ||
796 | // service attribute (name provided by the caller) | |
797 | CFIndex serviceUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(name), kCFStringEncodingUTF8) + 1;; | |
79b9da22 A |
798 | char *serviceUTF8 = (char *)malloc(serviceUTF8Len); |
799 | if (!serviceUTF8) { | |
800 | MacOSError::throwMe(errSecMemoryError); | |
801 | } | |
b1ab9ed8 A |
802 | if (!CFStringGetCString(name, serviceUTF8, serviceUTF8Len-1, kCFStringEncodingUTF8)) |
803 | serviceUTF8[0] = (char)'\0'; | |
79b9da22 A |
804 | CssmDataContainer service(const_cast<char *>(serviceUTF8), strlen(serviceUTF8)); |
805 | free(serviceUTF8); | |
b1ab9ed8 A |
806 | |
807 | // look for existing preference item, in case this is an update | |
808 | StorageManager::KeychainList keychains; | |
809 | globals().storageManager.getSearchList(keychains); | |
810 | KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL); | |
811 | FourCharCode itemType = 'cprf'; | |
812 | cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service); | |
813 | cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), itemType); | |
d64be36e | 814 | if (keyUsage) { |
b1ab9ed8 | 815 | cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage); |
d64be36e | 816 | } |
b1ab9ed8 | 817 | |
d64be36e | 818 | Item item(kSecGenericPasswordItemClass, 'aapl', 0, NULL, false); |
b1ab9ed8 A |
819 | bool add = (!cursor->next(item)); |
820 | // at this point, we either have a new item to add or an existing item to update | |
821 | ||
822 | // set item attribute values | |
823 | item->setAttribute(Schema::attributeInfo(kSecServiceItemAttr), service); | |
824 | item->setAttribute(Schema::attributeInfo(kSecTypeItemAttr), itemType); | |
825 | item->setAttribute(Schema::attributeInfo(kSecAccountItemAttr), account); | |
826 | item->setAttribute(Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage); | |
827 | item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), service); | |
828 | ||
b1ab9ed8 A |
829 | // generic attribute (store persistent certificate reference) |
830 | CFDataRef pItemRef = nil; | |
5c19dc3a | 831 | Certificate::required(__itemImplRef)->copyPersistentReference(pItemRef); |
b1ab9ed8 A |
832 | if (!pItemRef) { |
833 | MacOSError::throwMe(errSecInvalidItemRef); | |
834 | } | |
835 | const UInt8 *dataPtr = CFDataGetBytePtr(pItemRef); | |
836 | CFIndex dataLen = CFDataGetLength(pItemRef); | |
837 | CssmData pref(const_cast<void *>(reinterpret_cast<const void *>(dataPtr)), dataLen); | |
838 | item->setAttribute(Schema::attributeInfo(kSecGenericItemAttr), pref); | |
839 | CFRelease(pItemRef); | |
840 | ||
841 | if (add) { | |
842 | Keychain keychain = nil; | |
843 | try { | |
844 | keychain = globals().storageManager.defaultKeychain(); | |
845 | if (!keychain->exists()) | |
846 | MacOSError::throwMe(errSecNoSuchKeychain); // Might be deleted or not available at this time. | |
847 | } | |
848 | catch(...) { | |
849 | keychain = globals().storageManager.defaultKeychainUI(item); | |
850 | } | |
851 | ||
852 | try { | |
853 | keychain->add(item); | |
854 | } | |
855 | catch (const MacOSError &err) { | |
856 | if (err.osStatus() != errSecDuplicateItem) | |
857 | throw; // if item already exists, fall through to update | |
858 | } | |
859 | } | |
860 | item->update(); | |
861 | ||
5c19dc3a | 862 | END_SECCERTAPI |
b1ab9ed8 A |
863 | } |
864 | ||
5c19dc3a | 865 | /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */ |
b1ab9ed8 A |
866 | OSStatus SecCertificateSetPreferred( |
867 | SecCertificateRef certificate, | |
868 | CFStringRef name, | |
869 | CFArrayRef keyUsage) | |
870 | { | |
d64be36e | 871 | COUNTLEGACYAPI |
b1ab9ed8 A |
872 | CSSM_KEYUSE keyUse = ConvertArrayToKeyUsage(keyUsage); |
873 | return SecCertificateSetPreference(certificate, name, keyUse, NULL); | |
874 | } | |
875 | ||
5c19dc3a | 876 | /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */ |
b1ab9ed8 A |
877 | CFDictionaryRef SecCertificateCopyValues(SecCertificateRef certificate, CFArrayRef keys, CFErrorRef *error) |
878 | { | |
879 | CFDictionaryRef result = NULL; | |
427c49bc | 880 | OSStatus __secapiresult; |
fa7225c8 | 881 | SecCertificateRef tmpcert = NULL; |
6b200bc3 | 882 | |
fa7225c8 A |
883 | // convert input to a new-style certificate reference if necessary, |
884 | // since the implementation of CertificateValues calls SecCertificate API functions | |
885 | // which now assume a unified certificate reference. | |
886 | if (SecCertificateIsItemImplInstance(certificate)) { | |
887 | tmpcert = SecCertificateCreateFromItemImplInstance(certificate); | |
888 | } | |
fa7225c8 A |
889 | if (certificate && !tmpcert) { |
890 | tmpcert = (SecCertificateRef) CFRetain(certificate); | |
891 | } | |
b1ab9ed8 A |
892 | try |
893 | { | |
fa7225c8 | 894 | CertificateValues cv(tmpcert); |
b1ab9ed8 A |
895 | result = cv.copyFieldValues(keys,error); |
896 | __secapiresult=0; | |
897 | } | |
898 | catch (const MacOSError &err) { __secapiresult=err.osStatus(); } | |
899 | catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } | |
427c49bc A |
900 | catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } |
901 | catch (...) { __secapiresult=errSecInternalComponent; } | |
fa7225c8 | 902 | if (tmpcert) { CFRelease(tmpcert); } |
427c49bc | 903 | return result; |
b1ab9ed8 A |
904 | } |
905 | ||
5c19dc3a | 906 | /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */ |
b1ab9ed8 A |
907 | CFStringRef SecCertificateCopyLongDescription(CFAllocatorRef alloc, SecCertificateRef certificate, CFErrorRef *error) |
908 | { | |
909 | return SecCertificateCopyShortDescription(alloc, certificate, error); | |
910 | } | |
911 | ||
5c19dc3a | 912 | /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */ |
b1ab9ed8 A |
913 | CFStringRef SecCertificateCopyShortDescription(CFAllocatorRef alloc, SecCertificateRef certificate, CFErrorRef *error) |
914 | { | |
915 | CFStringRef result = NULL; | |
5c19dc3a | 916 | OSStatus __secapiresult = SecCertificateInferLabel(certificate, &result); |
427c49bc | 917 | if (error!=NULL && __secapiresult!=errSecSuccess) |
b1ab9ed8 A |
918 | { |
919 | *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainOSStatus, | |
920 | __secapiresult ? __secapiresult : CSSM_ERRCODE_INTERNAL_ERROR, NULL); | |
921 | } | |
427c49bc | 922 | return result; |
b1ab9ed8 A |
923 | } |
924 | ||
5c19dc3a | 925 | /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */ |
b1ab9ed8 A |
926 | CFDataRef SecCertificateCopySerialNumber(SecCertificateRef certificate, CFErrorRef *error) |
927 | { | |
928 | CFDataRef result = NULL; | |
427c49bc | 929 | OSStatus __secapiresult; |
b1ab9ed8 A |
930 | try |
931 | { | |
932 | CertificateValues cv(certificate); | |
933 | result = cv.copySerialNumber(error); | |
934 | __secapiresult=0; | |
935 | } | |
936 | catch (const MacOSError &err) { __secapiresult=err.osStatus(); } | |
937 | catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } | |
427c49bc A |
938 | catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } |
939 | catch (...) { __secapiresult=errSecInternalComponent; } | |
940 | return result; | |
b1ab9ed8 A |
941 | } |
942 | ||
6b200bc3 | 943 | /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_12_4, __IPHONE_NA, __IPHONE_NA) */ |
b1ab9ed8 A |
944 | CFDataRef SecCertificateCopyNormalizedIssuerContent(SecCertificateRef certificate, CFErrorRef *error) |
945 | { | |
946 | CFDataRef result = NULL; | |
427c49bc | 947 | OSStatus __secapiresult; |
b1ab9ed8 A |
948 | try |
949 | { | |
950 | CertificateValues cv(certificate); | |
427c49bc | 951 | result = cv.copyNormalizedIssuerContent(error); |
b1ab9ed8 A |
952 | __secapiresult=0; |
953 | } | |
954 | catch (const MacOSError &err) { __secapiresult=err.osStatus(); } | |
955 | catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } | |
427c49bc A |
956 | catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } |
957 | catch (...) { __secapiresult=errSecInternalComponent; } | |
958 | return result; | |
b1ab9ed8 A |
959 | } |
960 | ||
6b200bc3 | 961 | /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_12_4, __IPHONE_NA, __IPHONE_NA) */ |
b1ab9ed8 A |
962 | CFDataRef SecCertificateCopyNormalizedSubjectContent(SecCertificateRef certificate, CFErrorRef *error) |
963 | { | |
964 | CFDataRef result = NULL; | |
427c49bc | 965 | OSStatus __secapiresult; |
b1ab9ed8 A |
966 | try |
967 | { | |
968 | CertificateValues cv(certificate); | |
427c49bc | 969 | result = cv.copyNormalizedSubjectContent(error); |
b1ab9ed8 A |
970 | __secapiresult=0; |
971 | } | |
972 | catch (const MacOSError &err) { __secapiresult=err.osStatus(); } | |
973 | catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } | |
427c49bc A |
974 | catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } |
975 | catch (...) { __secapiresult=errSecInternalComponent; } | |
976 | return result; | |
b1ab9ed8 A |
977 | } |
978 | ||
5c19dc3a | 979 | /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_9, __IPHONE_NA, __IPHONE_NA) */ |
427c49bc A |
980 | bool SecCertificateIsValidX(SecCertificateRef certificate, CFAbsoluteTime verifyTime) |
981 | { | |
5c19dc3a A |
982 | /* |
983 | * deprecated function name | |
984 | */ | |
427c49bc A |
985 | return SecCertificateIsValid(certificate, verifyTime); |
986 | } | |
8a50f688 A |
987 | |
988 | /* OS X only */ | |
989 | CFDataRef SecCertificateCopyPublicKeySHA1DigestFromCertificateData(CFAllocatorRef allocator, | |
990 | CFDataRef der_certificate) | |
991 | { | |
992 | CFDataRef result = NULL; | |
993 | SecCertificateRef iosCertRef = SecCertificateCreateWithData(allocator, der_certificate); | |
994 | if (NULL == iosCertRef) | |
995 | { | |
996 | return result; | |
997 | } | |
998 | ||
999 | result = SecCertificateCopyPublicKeySHA1Digest(iosCertRef); | |
1000 | CFRelease(iosCertRef); | |
1001 | return result; | |
1002 | } | |
1003 |