]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 | 1 | /* |
5c19dc3a | 2 | * Copyright (c) 2002-2015 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> | |
41 | #include <security_keychain/KCCursor.h> | |
42 | #include <security_cdsa_utilities/Schema.h> | |
5c19dc3a | 43 | #include <security_cdsa_utils/cuCdsaUtils.h> |
b1ab9ed8 | 44 | #include <sys/param.h> |
5c19dc3a | 45 | #include <syslog.h> |
b1ab9ed8 A |
46 | #include "CertificateValues.h" |
47 | #include "SecCertificateP.h" | |
4d3cab3d | 48 | #include "SecCertificatePrivP.h" |
427c49bc | 49 | |
d8f41ccd | 50 | #include "AppleBaselineEscrowCertificates.h" |
427c49bc | 51 | |
b1ab9ed8 | 52 | |
5c19dc3a A |
53 | SecCertificateRef SecCertificateCreateItemImplInstance(SecCertificateRef certificate); |
54 | OSStatus SecCertificateGetCLHandle_legacy(SecCertificateRef certificate, CSSM_CL_HANDLE *clHandle); | |
b1ab9ed8 A |
55 | extern CSSM_KEYUSE ConvertArrayToKeyUsage(CFArrayRef usage); |
56 | ||
5c19dc3a | 57 | #define SEC_CONST_DECL(k,v) const CFStringRef k = CFSTR(v); |
427c49bc A |
58 | |
59 | SEC_CONST_DECL (kSecCertificateProductionEscrowKey, "ProductionEscrowKey"); | |
d8f41ccd | 60 | SEC_CONST_DECL (kSecCertificateProductionPCSEscrowKey, "ProductionPCSEscrowKey"); |
427c49bc A |
61 | SEC_CONST_DECL (kSecCertificateEscrowFileName, "AppleESCertificates"); |
62 | ||
b1ab9ed8 A |
63 | |
64 | using namespace CssmClient; | |
65 | ||
5c19dc3a | 66 | #if !SECTRUST_OSX |
b1ab9ed8 A |
67 | CFTypeID |
68 | SecCertificateGetTypeID(void) | |
69 | { | |
70 | BEGIN_SECAPI | |
71 | ||
72 | return gTypes().Certificate.typeID; | |
73 | ||
74 | END_SECAPI1(_kCFRuntimeNotATypeID) | |
75 | } | |
5c19dc3a | 76 | #endif |
b1ab9ed8 | 77 | |
5c19dc3a A |
78 | /* convert a new-world SecCertificateRef to an old-world ItemImpl instance */ |
79 | SecCertificateRef | |
80 | SecCertificateCreateItemImplInstance(SecCertificateRef certificate) | |
81 | { | |
82 | #if !SECTRUST_OSX | |
83 | return (SecCertificateRef)(certificate ? CFRetain(certificate) : NULL); | |
84 | #else | |
85 | if (!certificate) { | |
86 | return NULL; | |
87 | } | |
88 | SecCertificateRef implCertRef = (SecCertificateRef) SecCertificateCopyKeychainItem(certificate); | |
89 | if (implCertRef) { | |
90 | return implCertRef; | |
91 | } | |
92 | CFDataRef data = SecCertificateCopyData(certificate); | |
93 | if (!data) { | |
94 | return NULL; | |
95 | } | |
96 | try { | |
97 | CSSM_DATA cssmCertData; | |
98 | cssmCertData.Length = (data) ? (CSSM_SIZE)CFDataGetLength(data) : 0; | |
99 | cssmCertData.Data = (data) ? (uint8 *)CFDataGetBytePtr(data) : NULL; | |
b1ab9ed8 | 100 | |
5c19dc3a A |
101 | SecPointer<Certificate> certificatePtr(new Certificate(cssmCertData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER)); |
102 | implCertRef = certificatePtr->handle(); | |
103 | } | |
104 | catch (...) {} | |
105 | CFRelease(data); | |
106 | return implCertRef; | |
107 | #endif | |
108 | } | |
109 | ||
110 | /* convert an old-world ItemImpl instance to a new-world SecCertificateRef */ | |
111 | SecCertificateRef | |
112 | SecCertificateCreateFromItemImplInstance(SecCertificateRef certificate) | |
113 | { | |
114 | #if !SECTRUST_OSX | |
115 | return (SecCertificateRef)(certificate ? CFRetain(certificate) : NULL); | |
116 | #else | |
117 | if (!certificate) { | |
118 | return NULL; | |
119 | } | |
120 | SecCertificateRef result = NULL; | |
121 | CFDataRef data = NULL; | |
122 | try { | |
123 | CssmData certData = Certificate::required(certificate)->data(); | |
124 | if (certData.Data && certData.Length) { | |
125 | data = CFDataCreate(NULL, certData.Data, certData.Length); | |
126 | } | |
127 | if (!data) { | |
128 | if (certData.Data && !certData.Length) { | |
129 | /* zero-length certs can exist, so don't bother logging this */ | |
130 | } | |
131 | else { | |
132 | syslog(LOG_ERR, "WARNING: SecKeychainSearchCopyNext failed to retrieve certificate data (length=%ld, data=0x%lX)", | |
133 | (long)certData.Length, (uintptr_t)certData.Data); | |
134 | } | |
135 | return NULL; | |
136 | } | |
137 | } | |
138 | catch (...) {} | |
139 | ||
140 | result = SecCertificateCreateWithKeychainItem(NULL, data, certificate); | |
141 | if (data) | |
142 | CFRelease(data); | |
143 | return result; | |
144 | #endif | |
145 | } | |
146 | ||
147 | /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */ | |
b1ab9ed8 A |
148 | OSStatus |
149 | SecCertificateCreateFromData(const CSSM_DATA *data, CSSM_CERT_TYPE type, CSSM_CERT_ENCODING encoding, SecCertificateRef *certificate) | |
150 | { | |
5c19dc3a | 151 | #if !SECTRUST_OSX |
b1ab9ed8 A |
152 | BEGIN_SECAPI |
153 | ||
154 | SecPointer<Certificate> certificatePtr(new Certificate(Required(data), type, encoding)); | |
155 | Required(certificate) = certificatePtr->handle(); | |
156 | ||
157 | END_SECAPI | |
5c19dc3a A |
158 | #else |
159 | /* bridge to support old functionality */ | |
160 | if (!data || !data->Data || !data->Length || !certificate) { | |
161 | return errSecParam; | |
162 | } | |
163 | SecCertificateRef certRef = NULL; | |
164 | CFDataRef dataRef = CFDataCreate(NULL, data->Data, data->Length); | |
165 | if (dataRef) { | |
166 | certRef = SecCertificateCreateWithData(NULL, dataRef); | |
167 | CFRelease(dataRef); | |
168 | } | |
169 | *certificate = certRef; | |
170 | return (certRef) ? errSecSuccess : errSecUnknownFormat; | |
171 | #endif | |
b1ab9ed8 A |
172 | } |
173 | ||
5c19dc3a | 174 | #if !SECTRUST_OSX |
b1ab9ed8 A |
175 | /* new in 10.6 */ |
176 | SecCertificateRef | |
177 | SecCertificateCreateWithData(CFAllocatorRef allocator, CFDataRef data) | |
178 | { | |
179 | SecCertificateRef certificate = NULL; | |
180 | OSStatus __secapiresult; | |
181 | try { | |
182 | CSSM_DATA cssmCertData; | |
183 | cssmCertData.Length = (data) ? (CSSM_SIZE)CFDataGetLength(data) : 0; | |
184 | cssmCertData.Data = (data) ? (uint8 *)CFDataGetBytePtr(data) : NULL; | |
185 | ||
186 | //NOTE: there isn't yet a Certificate constructor which accepts a CFAllocatorRef | |
187 | SecPointer<Certificate> certificatePtr(new Certificate(cssmCertData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER)); | |
188 | certificate = certificatePtr->handle(); | |
189 | ||
427c49bc | 190 | __secapiresult=errSecSuccess; |
b1ab9ed8 A |
191 | } |
192 | catch (const MacOSError &err) { __secapiresult=err.osStatus(); } | |
193 | catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } | |
427c49bc A |
194 | catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } |
195 | catch (...) { __secapiresult=errSecInternalComponent; } | |
b1ab9ed8 A |
196 | return certificate; |
197 | } | |
5c19dc3a | 198 | #endif |
b1ab9ed8 | 199 | |
5c19dc3a | 200 | /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA) */ |
b1ab9ed8 A |
201 | OSStatus |
202 | SecCertificateAddToKeychain(SecCertificateRef certificate, SecKeychainRef keychain) | |
203 | { | |
5c19dc3a A |
204 | // This macro converts a new-style SecCertificateRef to an old-style ItemImpl |
205 | BEGIN_SECCERTAPI | |
b1ab9ed8 | 206 | |
5c19dc3a | 207 | Item item(Certificate::required(__itemImplRef)); |
b1ab9ed8 A |
208 | Keychain::optional(keychain)->add(item); |
209 | ||
5c19dc3a | 210 | END_SECCERTAPI |
b1ab9ed8 A |
211 | } |
212 | ||
5c19dc3a | 213 | /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */ |
b1ab9ed8 A |
214 | OSStatus |
215 | SecCertificateGetData(SecCertificateRef certificate, CSSM_DATA_PTR data) | |
216 | { | |
5c19dc3a A |
217 | // This macro converts a new-style SecCertificateRef to an old-style ItemImpl |
218 | BEGIN_SECCERTAPI | |
b1ab9ed8 | 219 | |
5c19dc3a | 220 | Required(data) = Certificate::required(__itemImplRef)->data(); |
b1ab9ed8 | 221 | |
5c19dc3a | 222 | END_SECCERTAPI |
b1ab9ed8 A |
223 | } |
224 | ||
5c19dc3a | 225 | #if !SECTRUST_OSX |
b1ab9ed8 A |
226 | /* new in 10.6 */ |
227 | CFDataRef | |
228 | SecCertificateCopyData(SecCertificateRef certificate) | |
229 | { | |
230 | CFDataRef data = NULL; | |
427c49bc | 231 | OSStatus __secapiresult = errSecSuccess; |
b1ab9ed8 A |
232 | try { |
233 | CssmData output = Certificate::required(certificate)->data(); | |
234 | CFIndex length = (CFIndex)output.length(); | |
235 | const UInt8 *bytes = (const UInt8 *)output.data(); | |
236 | if (length && bytes) { | |
237 | data = CFDataCreate(NULL, bytes, length); | |
238 | } | |
b1ab9ed8 A |
239 | } |
240 | catch (const MacOSError &err) { __secapiresult=err.osStatus(); } | |
241 | catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } | |
427c49bc A |
242 | catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } |
243 | catch (...) { __secapiresult=errSecInternalComponent; } | |
244 | return data; | |
245 | } | |
5c19dc3a | 246 | #endif |
427c49bc | 247 | |
5c19dc3a | 248 | #if !SECTRUST_OSX |
427c49bc A |
249 | CFDataRef |
250 | SecCertificateGetSHA1Digest(SecCertificateRef certificate) | |
251 | { | |
252 | CFDataRef data = NULL; | |
253 | OSStatus __secapiresult = errSecSuccess; | |
254 | try { | |
255 | data = Certificate::required(certificate)->sha1Hash(); | |
256 | } | |
257 | catch (const MacOSError &err) { __secapiresult=err.osStatus(); } | |
258 | catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } | |
259 | catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } | |
260 | catch (...) { __secapiresult=errSecInternalComponent; } | |
b1ab9ed8 A |
261 | return data; |
262 | } | |
e3d460c9 A |
263 | |
264 | CFDataRef | |
265 | SecCertificateCopySHA256Digest(SecCertificateRef certificate) | |
266 | { | |
267 | CFDataRef data = NULL; | |
268 | OSStatus __secapiresult = errSecSuccess; | |
269 | try { | |
270 | data = Certificate::required(certificate)->sha256Hash(); | |
271 | if (data) | |
272 | CFRetain(data); | |
273 | } | |
274 | catch (const MacOSError &err) { __secapiresult=err.osStatus(); } | |
275 | catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } | |
276 | catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } | |
277 | catch (...) { __secapiresult=errSecInternalComponent; } | |
278 | return data; | |
279 | } | |
280 | ||
281 | ||
5c19dc3a | 282 | #endif |
b1ab9ed8 | 283 | |
5c19dc3a A |
284 | #if !SECTRUST_OSX |
285 | CFDataRef | |
286 | SecCertificateCopyPublicKeySHA1Digest(SecCertificateRef certificate) | |
287 | { | |
288 | CFDataRef data = NULL; | |
289 | OSStatus __secapiresult = errSecSuccess; | |
290 | try { | |
291 | CssmData output = Certificate::required(certificate)->publicKeyHash(); | |
292 | CFIndex length = (CFIndex)output.length(); | |
293 | const UInt8 *bytes = (const UInt8 *)output.data(); | |
294 | if (length && bytes) { | |
295 | data = CFDataCreate(NULL, bytes, length); | |
296 | } | |
297 | } | |
298 | catch (const MacOSError &err) { __secapiresult=err.osStatus(); } | |
299 | catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } | |
300 | catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } | |
301 | catch (...) { __secapiresult=errSecInternalComponent; } | |
302 | return data; | |
303 | } | |
304 | #endif | |
305 | ||
306 | #if !SECTRUST_OSX | |
4d3cab3d A |
307 | CFArrayRef |
308 | SecCertificateCopyDNSNames(SecCertificateRef certificate) | |
309 | { | |
310 | CFArrayRef names = NULL; | |
311 | OSStatus __secapiresult = errSecSuccess; | |
312 | try { | |
313 | names = Certificate::required(certificate)->copyDNSNames(); | |
314 | } | |
315 | catch (const MacOSError &err) { __secapiresult=err.osStatus(); } | |
316 | catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } | |
317 | catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } | |
318 | catch (...) { __secapiresult=errSecInternalComponent; } | |
319 | return names; | |
320 | } | |
5c19dc3a | 321 | #endif |
427c49bc | 322 | |
5c19dc3a | 323 | /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */ |
b1ab9ed8 A |
324 | OSStatus |
325 | SecCertificateGetType(SecCertificateRef certificate, CSSM_CERT_TYPE *certificateType) | |
326 | { | |
5c19dc3a A |
327 | // This macro converts a new-style SecCertificateRef to an old-style ItemImpl |
328 | BEGIN_SECCERTAPI | |
b1ab9ed8 | 329 | |
5c19dc3a | 330 | Required(certificateType) = Certificate::required(__itemImplRef)->type(); |
b1ab9ed8 | 331 | |
5c19dc3a | 332 | END_SECCERTAPI |
b1ab9ed8 A |
333 | } |
334 | ||
5c19dc3a | 335 | /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */ |
b1ab9ed8 A |
336 | OSStatus |
337 | SecCertificateGetSubject(SecCertificateRef certificate, const CSSM_X509_NAME **subject) | |
338 | { | |
5c19dc3a A |
339 | // This macro converts a new-style SecCertificateRef to an old-style ItemImpl |
340 | BEGIN_SECCERTAPI | |
b1ab9ed8 | 341 | |
5c19dc3a | 342 | Required(subject) = Certificate::required(__itemImplRef)->subjectName(); |
b1ab9ed8 | 343 | |
5c19dc3a | 344 | END_SECCERTAPI |
b1ab9ed8 A |
345 | } |
346 | ||
5c19dc3a | 347 | /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */ |
b1ab9ed8 A |
348 | OSStatus |
349 | SecCertificateGetIssuer(SecCertificateRef certificate, const CSSM_X509_NAME **issuer) | |
350 | { | |
5c19dc3a A |
351 | // This macro converts a new-style SecCertificateRef to an old-style ItemImpl |
352 | BEGIN_SECCERTAPI | |
353 | ||
354 | Required(issuer) = Certificate::required(__itemImplRef)->issuerName(); | |
355 | ||
356 | END_SECCERTAPI | |
357 | } | |
358 | ||
359 | /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */ | |
360 | OSStatus | |
361 | SecCertificateGetCLHandle(SecCertificateRef certificate, CSSM_CL_HANDLE *clHandle) | |
362 | { | |
363 | #if !SECTRUST_OSX | |
b1ab9ed8 A |
364 | BEGIN_SECAPI |
365 | ||
5c19dc3a | 366 | Required(clHandle) = Certificate::required(certificate)->clHandle(); |
b1ab9ed8 A |
367 | |
368 | END_SECAPI | |
5c19dc3a A |
369 | #else |
370 | #if 0 | |
371 | // This macro converts a new-style SecCertificateRef to an old-style ItemImpl | |
372 | BEGIN_SECCERTAPI | |
373 | ||
374 | Required(clHandle) = Certificate::required(__itemImplRef)->clHandle(); | |
375 | ||
376 | END_SECCERTAPI | |
377 | #endif | |
378 | /* bridge code to support deprecated functionality */ | |
379 | OSStatus __secapiresult=errSecSuccess; | |
380 | bool kcItem=true; | |
381 | SecCertificateRef __itemImplRef=(SecCertificateRef)SecCertificateCopyKeychainItem(certificate); | |
382 | if (!__itemImplRef) { __itemImplRef=SecCertificateCreateItemImplInstance(certificate); kcItem=false; } | |
383 | try { | |
384 | Required(clHandle) = Certificate::required(__itemImplRef)->clHandle(); | |
385 | } | |
386 | catch (const MacOSError &err) { __secapiresult=err.osStatus(); } | |
387 | catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } | |
388 | catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } | |
389 | catch (...) { __secapiresult=errSecInternalComponent; } | |
390 | if (__itemImplRef) { | |
391 | if (!kcItem) { | |
392 | /* we can't release the temporary certificate, or the CL handle becomes invalid. | |
393 | * for now, just stick the temporary certificate into an array. | |
394 | * TBD: use a dictionary, indexed by hash of certificate. */ | |
395 | static CFMutableArrayRef sLegacyCertArray = NULL; | |
396 | if (!sLegacyCertArray) { | |
397 | sLegacyCertArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); | |
398 | if (!sLegacyCertArray) { | |
399 | return errSecAllocate; | |
400 | } | |
401 | } | |
402 | CFArrayAppendValue(sLegacyCertArray, __itemImplRef); | |
403 | #ifndef NDEBUG | |
404 | syslog(LOG_ERR, "WARNING: SecCertificateGetCLHandle called on certificate which is not in a keychain."); | |
405 | #endif | |
406 | } | |
407 | CFRelease(__itemImplRef); | |
408 | } | |
409 | return __secapiresult; | |
b1ab9ed8 | 410 | |
5c19dc3a A |
411 | #endif |
412 | } | |
b1ab9ed8 | 413 | |
5c19dc3a A |
414 | /* private function; assumes input is old-style ItemImpl certificate reference, |
415 | and does not release that certificate reference! | |
416 | */ | |
b1ab9ed8 | 417 | OSStatus |
5c19dc3a | 418 | SecCertificateGetCLHandle_legacy(SecCertificateRef certificate, CSSM_CL_HANDLE *clHandle) |
b1ab9ed8 A |
419 | { |
420 | BEGIN_SECAPI | |
421 | ||
5c19dc3a | 422 | Required(clHandle) = Certificate::required(certificate)->clHandle(); |
b1ab9ed8 A |
423 | |
424 | END_SECAPI | |
425 | } | |
426 | ||
5c19dc3a | 427 | |
b1ab9ed8 A |
428 | /* |
429 | * Private API to infer a display name for a SecCertificateRef which | |
430 | * may or may not be in a keychain. | |
5c19dc3a A |
431 | * |
432 | * OS X only | |
b1ab9ed8 A |
433 | */ |
434 | OSStatus | |
435 | SecCertificateInferLabel(SecCertificateRef certificate, CFStringRef *label) | |
436 | { | |
5c19dc3a A |
437 | // This macro converts a new-style SecCertificateRef to an old-style ItemImpl |
438 | BEGIN_SECCERTAPI | |
b1ab9ed8 | 439 | |
5c19dc3a | 440 | Certificate::required(__itemImplRef)->inferLabel(false, &Required(label)); |
b1ab9ed8 | 441 | |
5c19dc3a | 442 | END_SECCERTAPI |
b1ab9ed8 A |
443 | } |
444 | ||
5c19dc3a | 445 | /* OS X only (note: iOS version has different arguments and return value) */ |
b1ab9ed8 A |
446 | OSStatus |
447 | SecCertificateCopyPublicKey(SecCertificateRef certificate, SecKeyRef *key) | |
448 | { | |
5c19dc3a A |
449 | // This macro converts a new-style SecCertificateRef to an old-style ItemImpl |
450 | BEGIN_SECCERTAPI | |
b1ab9ed8 | 451 | |
5c19dc3a | 452 | Required(key) = Certificate::required(__itemImplRef)->publicKey()->handle(); |
b1ab9ed8 | 453 | |
5c19dc3a | 454 | END_SECCERTAPI |
b1ab9ed8 A |
455 | } |
456 | ||
5c19dc3a | 457 | /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */ |
b1ab9ed8 A |
458 | OSStatus |
459 | SecCertificateGetAlgorithmID(SecCertificateRef certificate, const CSSM_X509_ALGORITHM_IDENTIFIER **algid) | |
460 | { | |
5c19dc3a A |
461 | // This macro converts a new-style SecCertificateRef to an old-style ItemImpl |
462 | BEGIN_SECCERTAPI | |
b1ab9ed8 | 463 | |
5c19dc3a | 464 | Required(algid) = Certificate::required(__itemImplRef)->algorithmID(); |
b1ab9ed8 | 465 | |
5c19dc3a | 466 | END_SECCERTAPI |
b1ab9ed8 A |
467 | } |
468 | ||
5c19dc3a | 469 | /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA) */ |
b1ab9ed8 A |
470 | OSStatus |
471 | SecCertificateCopyCommonName(SecCertificateRef certificate, CFStringRef *commonName) | |
472 | { | |
5c19dc3a A |
473 | // This macro converts a new-style SecCertificateRef to an old-style ItemImpl |
474 | BEGIN_SECCERTAPI | |
b1ab9ed8 | 475 | |
5c19dc3a | 476 | Required(commonName) = Certificate::required(__itemImplRef)->commonName(); |
b1ab9ed8 | 477 | |
5c19dc3a | 478 | END_SECCERTAPI |
b1ab9ed8 A |
479 | } |
480 | ||
5c19dc3a | 481 | #if !SECTRUST_OSX |
b1ab9ed8 A |
482 | /* new in 10.6 */ |
483 | CFStringRef | |
484 | SecCertificateCopySubjectSummary(SecCertificateRef certificate) | |
485 | { | |
486 | CFStringRef summary = NULL; | |
487 | OSStatus __secapiresult; | |
488 | try { | |
489 | Certificate::required(certificate)->inferLabel(false, &summary); | |
490 | ||
427c49bc | 491 | __secapiresult=errSecSuccess; |
b1ab9ed8 A |
492 | } |
493 | catch (const MacOSError &err) { __secapiresult=err.osStatus(); } | |
494 | catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } | |
427c49bc A |
495 | catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } |
496 | catch (...) { __secapiresult=errSecInternalComponent; } | |
b1ab9ed8 A |
497 | return summary; |
498 | } | |
5c19dc3a | 499 | #endif |
b1ab9ed8 | 500 | |
5c19dc3a | 501 | #if !SECTRUST_OSX |
4d3cab3d A |
502 | CFStringRef |
503 | SecCertificateCopyIssuerSummary(SecCertificateRef certificate) | |
504 | { | |
505 | CFStringRef issuerStr = NULL; | |
506 | SecCertificateRefP certP = NULL; | |
507 | CFDataRef certData = SecCertificateCopyData(certificate); | |
508 | if (certData) { | |
509 | certP = SecCertificateCreateWithDataP(NULL, certData); | |
510 | CFRelease(certData); | |
511 | } | |
512 | if (certP) { | |
513 | issuerStr = SecCertificateCopyIssuerSummaryP(certP); | |
514 | CFRelease(certP); | |
515 | } | |
516 | return issuerStr; | |
517 | } | |
5c19dc3a | 518 | #endif |
4d3cab3d | 519 | |
5c19dc3a | 520 | /* OS X only */ |
b1ab9ed8 A |
521 | OSStatus |
522 | SecCertificateCopySubjectComponent(SecCertificateRef certificate, const CSSM_OID *component, CFStringRef *result) | |
523 | { | |
5c19dc3a A |
524 | // This macro converts a new-style SecCertificateRef to an old-style ItemImpl |
525 | BEGIN_SECCERTAPI | |
b1ab9ed8 | 526 | |
5c19dc3a | 527 | Required(result) = Certificate::required(__itemImplRef)->distinguishedName(&CSSMOID_X509V1SubjectNameCStruct, component); |
b1ab9ed8 | 528 | |
5c19dc3a | 529 | END_SECCERTAPI |
b1ab9ed8 A |
530 | } |
531 | ||
5c19dc3a | 532 | /* OS X only; deprecated SPI */ |
b1ab9ed8 A |
533 | OSStatus |
534 | SecCertificateGetCommonName(SecCertificateRef certificate, CFStringRef *commonName) | |
535 | { | |
536 | // deprecated SPI signature; replaced by SecCertificateCopyCommonName | |
537 | return SecCertificateCopyCommonName(certificate, commonName); | |
538 | } | |
539 | ||
5c19dc3a | 540 | /* OS X only; deprecated SPI */ |
b1ab9ed8 A |
541 | OSStatus |
542 | SecCertificateGetEmailAddress(SecCertificateRef certificate, CFStringRef *emailAddress) | |
543 | { | |
5c19dc3a A |
544 | // This macro converts a new-style SecCertificateRef to an old-style ItemImpl |
545 | BEGIN_SECCERTAPI | |
b1ab9ed8 | 546 | |
5c19dc3a | 547 | Required(emailAddress) = Certificate::required(__itemImplRef)->copyFirstEmailAddress(); |
b1ab9ed8 | 548 | |
5c19dc3a | 549 | END_SECCERTAPI |
b1ab9ed8 A |
550 | } |
551 | ||
5c19dc3a | 552 | /* OS X only */ |
b1ab9ed8 A |
553 | OSStatus |
554 | SecCertificateCopyEmailAddresses(SecCertificateRef certificate, CFArrayRef *emailAddresses) | |
555 | { | |
5c19dc3a A |
556 | // This macro converts a new-style SecCertificateRef to an old-style ItemImpl |
557 | BEGIN_SECCERTAPI | |
b1ab9ed8 | 558 | |
5c19dc3a | 559 | Required(emailAddresses) = Certificate::required(__itemImplRef)->copyEmailAddresses(); |
b1ab9ed8 | 560 | |
5c19dc3a | 561 | END_SECCERTAPI |
b1ab9ed8 A |
562 | } |
563 | ||
5c19dc3a A |
564 | /* Return a zero terminated list of CSSM_DATA_PTR's with the values of the field specified by field. |
565 | * Caller must call releaseFieldValues to free the storage allocated by this call. | |
566 | * | |
567 | * OS X only | |
568 | */ | |
b1ab9ed8 A |
569 | OSStatus |
570 | SecCertificateCopyFieldValues(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR **fieldValues) | |
571 | { | |
5c19dc3a A |
572 | // This macro converts a new-style SecCertificateRef to an old-style ItemImpl |
573 | BEGIN_SECCERTAPI | |
b1ab9ed8 | 574 | |
5c19dc3a | 575 | Required(fieldValues) = Certificate::required(__itemImplRef)->copyFieldValues(Required(field)); |
b1ab9ed8 | 576 | |
5c19dc3a | 577 | END_SECCERTAPI |
b1ab9ed8 A |
578 | } |
579 | ||
5c19dc3a | 580 | /* OS X only */ |
b1ab9ed8 A |
581 | OSStatus |
582 | SecCertificateReleaseFieldValues(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR *fieldValues) | |
583 | { | |
5c19dc3a A |
584 | // This macro converts a new-style SecCertificateRef to an old-style ItemImpl |
585 | BEGIN_SECCERTAPI | |
b1ab9ed8 | 586 | |
5c19dc3a | 587 | Certificate::required(__itemImplRef)->releaseFieldValues(Required(field), fieldValues); |
b1ab9ed8 | 588 | |
5c19dc3a | 589 | END_SECCERTAPI |
b1ab9ed8 A |
590 | } |
591 | ||
5c19dc3a | 592 | /* OS X only */ |
b1ab9ed8 A |
593 | OSStatus |
594 | SecCertificateCopyFirstFieldValue(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR *fieldValue) | |
595 | { | |
5c19dc3a A |
596 | // This macro converts a new-style SecCertificateRef to an old-style ItemImpl |
597 | BEGIN_SECCERTAPI | |
b1ab9ed8 | 598 | |
5c19dc3a | 599 | Required(fieldValue) = Certificate::required(__itemImplRef)->copyFirstFieldValue(Required(field)); |
b1ab9ed8 | 600 | |
5c19dc3a | 601 | END_SECCERTAPI |
b1ab9ed8 A |
602 | } |
603 | ||
5c19dc3a | 604 | /* OS X only */ |
b1ab9ed8 A |
605 | OSStatus |
606 | SecCertificateReleaseFirstFieldValue(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR fieldValue) | |
607 | { | |
5c19dc3a A |
608 | // This macro converts a new-style SecCertificateRef to an old-style ItemImpl |
609 | BEGIN_SECCERTAPI | |
b1ab9ed8 | 610 | |
5c19dc3a | 611 | Certificate::required(__itemImplRef)->releaseFieldValue(Required(field), fieldValue); |
b1ab9ed8 | 612 | |
5c19dc3a | 613 | END_SECCERTAPI |
b1ab9ed8 A |
614 | } |
615 | ||
5c19dc3a | 616 | /* OS X only */ |
b1ab9ed8 A |
617 | OSStatus |
618 | SecCertificateFindByIssuerAndSN(CFTypeRef keychainOrArray,const CSSM_DATA *issuer, | |
619 | const CSSM_DATA *serialNumber, SecCertificateRef *certificate) | |
620 | { | |
621 | BEGIN_SECAPI | |
622 | ||
623 | StorageManager::KeychainList keychains; | |
624 | globals().storageManager.optionalSearchList(keychainOrArray, keychains); | |
625 | Required(certificate) = Certificate::findByIssuerAndSN(keychains, CssmData::required(issuer), CssmData::required(serialNumber))->handle(); | |
626 | ||
5c19dc3a A |
627 | #if SECTRUST_OSX |
628 | // convert ItemImpl-based SecCertificateRef to new-world version before returning | |
629 | CssmData certData = Certificate::required(*certificate)->data(); | |
630 | CFRef<CFDataRef> cfData(CFDataCreate(NULL, certData.Data, certData.Length)); | |
631 | SecCertificateRef tmpRef = *certificate; | |
632 | *certificate = SecCertificateCreateWithData(NULL, cfData); | |
633 | CFRelease(tmpRef); | |
634 | #endif | |
635 | ||
b1ab9ed8 A |
636 | END_SECAPI |
637 | } | |
638 | ||
5c19dc3a | 639 | /* OS X only */ |
b1ab9ed8 A |
640 | OSStatus |
641 | SecCertificateFindBySubjectKeyID(CFTypeRef keychainOrArray, const CSSM_DATA *subjectKeyID, | |
642 | SecCertificateRef *certificate) | |
643 | { | |
644 | BEGIN_SECAPI | |
645 | ||
646 | StorageManager::KeychainList keychains; | |
647 | globals().storageManager.optionalSearchList(keychainOrArray, keychains); | |
648 | Required(certificate) = Certificate::findBySubjectKeyID(keychains, CssmData::required(subjectKeyID))->handle(); | |
649 | ||
5c19dc3a A |
650 | #if SECTRUST_OSX |
651 | // convert ItemImpl-based SecCertificateRef to new-world version before returning | |
652 | CssmData certData = Certificate::required(*certificate)->data(); | |
653 | CFRef<CFDataRef> cfData(CFDataCreate(NULL, certData.Data, certData.Length)); | |
654 | SecCertificateRef tmpRef = *certificate; | |
655 | *certificate = SecCertificateCreateWithData(NULL, cfData); | |
656 | CFRelease(tmpRef); | |
657 | #endif | |
658 | ||
b1ab9ed8 A |
659 | END_SECAPI |
660 | } | |
661 | ||
5c19dc3a | 662 | /* OS X only */ |
b1ab9ed8 A |
663 | OSStatus |
664 | SecCertificateFindByEmail(CFTypeRef keychainOrArray, const char *emailAddress, SecCertificateRef *certificate) | |
665 | { | |
666 | BEGIN_SECAPI | |
667 | ||
668 | StorageManager::KeychainList keychains; | |
669 | globals().storageManager.optionalSearchList(keychainOrArray, keychains); | |
670 | Required(certificate) = Certificate::findByEmail(keychains, emailAddress)->handle(); | |
671 | ||
5c19dc3a A |
672 | #if SECTRUST_OSX |
673 | // convert ItemImpl-based SecCertificateRef to new-world version before returning | |
674 | CssmData certData = Certificate::required(*certificate)->data(); | |
675 | CFRef<CFDataRef> cfData(CFDataCreate(NULL, certData.Data, certData.Length)); | |
676 | SecCertificateRef tmpRef = *certificate; | |
677 | *certificate = SecCertificateCreateWithData(NULL, cfData); | |
678 | CFRelease(tmpRef); | |
679 | #endif | |
680 | ||
b1ab9ed8 A |
681 | END_SECAPI |
682 | } | |
683 | ||
5c19dc3a | 684 | /* OS X only */ |
b1ab9ed8 A |
685 | OSStatus |
686 | SecKeychainSearchCreateForCertificateByIssuerAndSN(CFTypeRef keychainOrArray, const CSSM_DATA *issuer, | |
687 | const CSSM_DATA *serialNumber, SecKeychainSearchRef *searchRef) | |
688 | { | |
689 | BEGIN_SECAPI | |
690 | ||
691 | Required(searchRef); | |
692 | ||
693 | StorageManager::KeychainList keychains; | |
694 | globals().storageManager.optionalSearchList(keychainOrArray, keychains); | |
695 | KCCursor cursor(Certificate::cursorForIssuerAndSN(keychains, CssmData::required(issuer), CssmData::required(serialNumber))); | |
696 | *searchRef = cursor->handle(); | |
697 | ||
698 | END_SECAPI | |
699 | } | |
700 | ||
5c19dc3a | 701 | /* OS X only */ |
b1ab9ed8 A |
702 | OSStatus |
703 | SecKeychainSearchCreateForCertificateByIssuerAndSN_CF(CFTypeRef keychainOrArray, CFDataRef issuer, | |
704 | CFDataRef serialNumber, SecKeychainSearchRef *searchRef) | |
705 | { | |
706 | BEGIN_SECAPI | |
707 | ||
708 | Required(searchRef); | |
709 | ||
710 | StorageManager::KeychainList keychains; | |
711 | globals().storageManager.optionalSearchList(keychainOrArray, keychains); | |
712 | Required(issuer); | |
713 | Required(serialNumber); | |
714 | KCCursor cursor(Certificate::cursorForIssuerAndSN_CF(keychains, issuer, serialNumber)); | |
715 | *searchRef = cursor->handle(); | |
716 | ||
717 | END_SECAPI | |
718 | } | |
719 | ||
5c19dc3a | 720 | /* OS X only */ |
b1ab9ed8 A |
721 | OSStatus |
722 | SecKeychainSearchCreateForCertificateBySubjectKeyID(CFTypeRef keychainOrArray, const CSSM_DATA *subjectKeyID, | |
723 | SecKeychainSearchRef *searchRef) | |
724 | { | |
725 | BEGIN_SECAPI | |
726 | ||
727 | Required(searchRef); | |
728 | ||
729 | StorageManager::KeychainList keychains; | |
730 | globals().storageManager.optionalSearchList(keychainOrArray, keychains); | |
731 | KCCursor cursor(Certificate::cursorForSubjectKeyID(keychains, CssmData::required(subjectKeyID))); | |
732 | *searchRef = cursor->handle(); | |
733 | ||
734 | END_SECAPI | |
735 | } | |
736 | ||
5c19dc3a | 737 | /* OS X only */ |
b1ab9ed8 A |
738 | OSStatus |
739 | SecKeychainSearchCreateForCertificateByEmail(CFTypeRef keychainOrArray, const char *emailAddress, | |
740 | SecKeychainSearchRef *searchRef) | |
741 | { | |
742 | BEGIN_SECAPI | |
743 | ||
744 | Required(searchRef); | |
745 | ||
746 | StorageManager::KeychainList keychains; | |
747 | globals().storageManager.optionalSearchList(keychainOrArray, keychains); | |
748 | KCCursor cursor(Certificate::cursorForEmail(keychains, emailAddress)); | |
749 | *searchRef = cursor->handle(); | |
750 | ||
751 | END_SECAPI | |
752 | } | |
753 | ||
5c19dc3a | 754 | /* OS X only */ |
b1ab9ed8 A |
755 | CSSM_RETURN |
756 | SecDigestGetData (CSSM_ALGORITHMS alg, CSSM_DATA* digest, const CSSM_DATA* data) | |
757 | { | |
758 | BEGIN_SECAPI | |
759 | // sanity checking | |
760 | if (!digest || !digest->Data || !digest->Length || !data || !data->Data || !data->Length) | |
427c49bc | 761 | return errSecParam; |
b1ab9ed8 A |
762 | |
763 | CSP csp(gGuidAppleCSP); | |
764 | Digest context(csp, alg); | |
765 | CssmData input(data->Data, data->Length); | |
766 | CssmData output(digest->Data, digest->Length); | |
767 | ||
768 | context.digest(input, output); | |
769 | digest->Length = output.length(); | |
770 | ||
771 | return CSSM_OK; | |
772 | END_SECAPI1(1); | |
773 | } | |
774 | ||
5c19dc3a | 775 | #if !SECTRUST_OSX |
b1ab9ed8 A |
776 | /* determine whether a cert is self-signed */ |
777 | OSStatus SecCertificateIsSelfSigned( | |
778 | SecCertificateRef certificate, | |
779 | Boolean *isSelfSigned) /* RETURNED */ | |
780 | { | |
781 | BEGIN_SECAPI | |
782 | ||
783 | *isSelfSigned = Certificate::required(certificate)->isSelfSigned(); | |
784 | ||
785 | END_SECAPI | |
786 | } | |
5c19dc3a | 787 | #endif |
b1ab9ed8 | 788 | |
5c19dc3a | 789 | /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */ |
b1ab9ed8 A |
790 | OSStatus |
791 | SecCertificateCopyPreference( | |
792 | CFStringRef name, | |
793 | CSSM_KEYUSE keyUsage, | |
794 | SecCertificateRef *certificate) | |
795 | { | |
796 | BEGIN_SECAPI | |
797 | ||
798 | Required(name); | |
799 | Required(certificate); | |
800 | StorageManager::KeychainList keychains; | |
801 | globals().storageManager.getSearchList(keychains); | |
802 | KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL); | |
803 | ||
804 | char idUTF8[MAXPATHLEN]; | |
805 | if (!CFStringGetCString(name, idUTF8, sizeof(idUTF8)-1, kCFStringEncodingUTF8)) | |
806 | idUTF8[0] = (char)'\0'; | |
807 | CssmData service(const_cast<char *>(idUTF8), strlen(idUTF8)); | |
808 | FourCharCode itemType = 'cprf'; | |
809 | cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service); | |
810 | cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), itemType); | |
811 | if (keyUsage) | |
812 | cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage); | |
813 | ||
814 | Item prefItem; | |
815 | if (!cursor->next(prefItem)) | |
816 | MacOSError::throwMe(errSecItemNotFound); | |
817 | ||
818 | // get persistent certificate reference | |
819 | SecKeychainAttribute itemAttrs[] = { { kSecGenericItemAttr, 0, NULL } }; | |
820 | SecKeychainAttributeList itemAttrList = { sizeof(itemAttrs) / sizeof(itemAttrs[0]), itemAttrs }; | |
821 | prefItem->getContent(NULL, &itemAttrList, NULL, NULL); | |
822 | ||
823 | // find certificate, given persistent reference data | |
824 | CFDataRef pItemRef = CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)itemAttrs[0].data, itemAttrs[0].length, kCFAllocatorNull); | |
825 | SecKeychainItemRef certItemRef = nil; | |
826 | OSStatus status = SecKeychainItemCopyFromPersistentReference(pItemRef, &certItemRef); //%%% need to make this a method of ItemImpl | |
827 | prefItem->freeContent(&itemAttrList, NULL); | |
828 | if (pItemRef) | |
829 | CFRelease(pItemRef); | |
830 | if (status) | |
831 | return status; | |
832 | ||
833 | *certificate = (SecCertificateRef)certItemRef; | |
834 | ||
5c19dc3a A |
835 | #if SECTRUST_OSX |
836 | // convert ItemImpl-based SecCertificateRef to new-world version before returning | |
837 | CssmData certData = Certificate::required(*certificate)->data(); | |
838 | CFRef<CFDataRef> cfData(CFDataCreate(NULL, certData.Data, certData.Length)); | |
839 | SecCertificateRef tmpRef = *certificate; | |
840 | *certificate = SecCertificateCreateWithData(NULL, cfData); | |
841 | CFRelease(tmpRef); | |
842 | #endif | |
843 | ||
b1ab9ed8 A |
844 | END_SECAPI |
845 | } | |
846 | ||
5c19dc3a | 847 | /* OS X only */ |
b1ab9ed8 A |
848 | SecCertificateRef |
849 | SecCertificateCopyPreferred( | |
850 | CFStringRef name, | |
851 | CFArrayRef keyUsage) | |
852 | { | |
853 | // This function will look for a matching preference in the following order: | |
854 | // - matches the name and the supplied key use | |
855 | // - matches the name and the special 'ANY' key use | |
856 | // - matches the name with no key usage constraint | |
857 | ||
858 | SecCertificateRef certRef = NULL; | |
859 | CSSM_KEYUSE keyUse = ConvertArrayToKeyUsage(keyUsage); | |
860 | OSStatus status = SecCertificateCopyPreference(name, keyUse, &certRef); | |
427c49bc | 861 | if (status != errSecSuccess && keyUse != CSSM_KEYUSE_ANY) |
b1ab9ed8 | 862 | status = SecCertificateCopyPreference(name, CSSM_KEYUSE_ANY, &certRef); |
427c49bc | 863 | if (status != errSecSuccess && keyUse != 0) |
b1ab9ed8 A |
864 | status = SecCertificateCopyPreference(name, 0, &certRef); |
865 | ||
866 | return certRef; | |
867 | } | |
868 | ||
5c19dc3a | 869 | /* OS X only; not exported */ |
427c49bc | 870 | static OSStatus |
b1ab9ed8 A |
871 | SecCertificateFindPreferenceItemWithNameAndKeyUsage( |
872 | CFTypeRef keychainOrArray, | |
873 | CFStringRef name, | |
874 | int32_t keyUsage, | |
875 | SecKeychainItemRef *itemRef) | |
876 | { | |
877 | BEGIN_SECAPI | |
878 | ||
879 | StorageManager::KeychainList keychains; | |
880 | globals().storageManager.optionalSearchList(keychainOrArray, keychains); | |
881 | KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL); | |
882 | ||
883 | char idUTF8[MAXPATHLEN]; | |
884 | idUTF8[0] = (char)'\0'; | |
885 | if (name) | |
886 | { | |
887 | if (!CFStringGetCString(name, idUTF8, sizeof(idUTF8)-1, kCFStringEncodingUTF8)) | |
888 | idUTF8[0] = (char)'\0'; | |
889 | } | |
890 | size_t idUTF8Len = strlen(idUTF8); | |
891 | if (!idUTF8Len) | |
427c49bc | 892 | MacOSError::throwMe(errSecParam); |
b1ab9ed8 A |
893 | |
894 | CssmData service(const_cast<char *>(idUTF8), idUTF8Len); | |
895 | cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service); | |
896 | cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), (FourCharCode)'cprf'); | |
897 | if (keyUsage) | |
898 | cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage); | |
899 | ||
900 | Item item; | |
901 | if (!cursor->next(item)) | |
902 | MacOSError::throwMe(errSecItemNotFound); | |
903 | ||
904 | if (itemRef) | |
905 | *itemRef=item->handle(); | |
906 | ||
907 | END_SECAPI | |
908 | } | |
909 | ||
5c19dc3a | 910 | /* OS X only; not exported */ |
427c49bc | 911 | static |
b1ab9ed8 A |
912 | OSStatus SecCertificateDeletePreferenceItemWithNameAndKeyUsage( |
913 | CFTypeRef keychainOrArray, | |
914 | CFStringRef name, | |
915 | int32_t keyUsage) | |
916 | { | |
917 | // when a specific key usage is passed, we'll only match & delete that pref; | |
918 | // when a key usage of 0 is passed, all matching prefs should be deleted. | |
919 | // maxUsages represents the most matches there could theoretically be, so | |
920 | // cut things off at that point if we're still finding items (if they can't | |
921 | // be deleted for some reason, we'd never break out of the loop.) | |
922 | ||
923 | OSStatus status; | |
924 | SecKeychainItemRef item = NULL; | |
925 | int count = 0, maxUsages = 12; | |
926 | while (++count <= maxUsages && | |
427c49bc | 927 | (status = SecCertificateFindPreferenceItemWithNameAndKeyUsage(keychainOrArray, name, keyUsage, &item)) == errSecSuccess) { |
b1ab9ed8 A |
928 | status = SecKeychainItemDelete(item); |
929 | CFRelease(item); | |
930 | item = NULL; | |
931 | } | |
932 | ||
933 | // it's not an error if the item isn't found | |
427c49bc | 934 | return (status == errSecItemNotFound) ? errSecSuccess : status; |
b1ab9ed8 A |
935 | } |
936 | ||
5c19dc3a | 937 | /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA) */ |
b1ab9ed8 A |
938 | OSStatus SecCertificateSetPreference( |
939 | SecCertificateRef certificate, | |
940 | CFStringRef name, | |
941 | CSSM_KEYUSE keyUsage, | |
942 | CFDateRef date) | |
943 | { | |
944 | if (!name) { | |
427c49bc | 945 | return errSecParam; |
b1ab9ed8 A |
946 | } |
947 | if (!certificate) { | |
948 | // treat NULL certificate as a request to clear the preference | |
949 | // (note: if keyUsage is 0, this clears all key usage prefs for name) | |
950 | return SecCertificateDeletePreferenceItemWithNameAndKeyUsage(NULL, name, keyUsage); | |
951 | } | |
952 | ||
5c19dc3a A |
953 | // This macro converts a new-style SecCertificateRef to an old-style ItemImpl |
954 | BEGIN_SECCERTAPI | |
b1ab9ed8 A |
955 | |
956 | // determine the account attribute | |
957 | // | |
958 | // This attribute must be synthesized from certificate label + pref item type + key usage, | |
959 | // as only the account and service attributes can make a generic keychain item unique. | |
960 | // For 'iprf' type items (but not 'cprf'), we append a trailing space. This insures that | |
961 | // we can save a certificate preference if an identity preference already exists for the | |
962 | // given service name, and vice-versa. | |
963 | // If the key usage is 0 (i.e. the normal case), we omit the appended key usage string. | |
964 | // | |
965 | CFStringRef labelStr = nil; | |
5c19dc3a | 966 | Certificate::required(__itemImplRef)->inferLabel(false, &labelStr); |
b1ab9ed8 A |
967 | if (!labelStr) { |
968 | MacOSError::throwMe(errSecDataTooLarge); // data is "in a format which cannot be displayed" | |
969 | } | |
970 | CFIndex accountUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(labelStr), kCFStringEncodingUTF8) + 1; | |
971 | const char *templateStr = "%s [key usage 0x%X]"; | |
972 | const int keyUsageMaxStrLen = 8; | |
973 | accountUTF8Len += strlen(templateStr) + keyUsageMaxStrLen; | |
974 | char accountUTF8[accountUTF8Len]; | |
975 | if (!CFStringGetCString(labelStr, accountUTF8, accountUTF8Len-1, kCFStringEncodingUTF8)) | |
976 | accountUTF8[0] = (char)'\0'; | |
977 | if (keyUsage) | |
978 | snprintf(accountUTF8, accountUTF8Len-1, templateStr, accountUTF8, keyUsage); | |
979 | CssmData account(const_cast<char *>(accountUTF8), strlen(accountUTF8)); | |
980 | CFRelease(labelStr); | |
981 | ||
982 | // service attribute (name provided by the caller) | |
983 | CFIndex serviceUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(name), kCFStringEncodingUTF8) + 1;; | |
984 | char serviceUTF8[serviceUTF8Len]; | |
985 | if (!CFStringGetCString(name, serviceUTF8, serviceUTF8Len-1, kCFStringEncodingUTF8)) | |
986 | serviceUTF8[0] = (char)'\0'; | |
987 | CssmData service(const_cast<char *>(serviceUTF8), strlen(serviceUTF8)); | |
988 | ||
989 | // look for existing preference item, in case this is an update | |
990 | StorageManager::KeychainList keychains; | |
991 | globals().storageManager.getSearchList(keychains); | |
992 | KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL); | |
993 | FourCharCode itemType = 'cprf'; | |
994 | cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service); | |
995 | cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), itemType); | |
996 | if (keyUsage) | |
997 | cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage); | |
998 | if (date) | |
999 | ; // %%%TBI | |
1000 | ||
1001 | Item item(kSecGenericPasswordItemClass, 'aapl', 0, NULL, false); | |
1002 | bool add = (!cursor->next(item)); | |
1003 | // at this point, we either have a new item to add or an existing item to update | |
1004 | ||
1005 | // set item attribute values | |
1006 | item->setAttribute(Schema::attributeInfo(kSecServiceItemAttr), service); | |
1007 | item->setAttribute(Schema::attributeInfo(kSecTypeItemAttr), itemType); | |
1008 | item->setAttribute(Schema::attributeInfo(kSecAccountItemAttr), account); | |
1009 | item->setAttribute(Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage); | |
1010 | item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), service); | |
1011 | ||
1012 | // date | |
1013 | if (date) | |
1014 | ; // %%%TBI | |
1015 | ||
1016 | // generic attribute (store persistent certificate reference) | |
1017 | CFDataRef pItemRef = nil; | |
5c19dc3a | 1018 | Certificate::required(__itemImplRef)->copyPersistentReference(pItemRef); |
b1ab9ed8 A |
1019 | if (!pItemRef) { |
1020 | MacOSError::throwMe(errSecInvalidItemRef); | |
1021 | } | |
1022 | const UInt8 *dataPtr = CFDataGetBytePtr(pItemRef); | |
1023 | CFIndex dataLen = CFDataGetLength(pItemRef); | |
1024 | CssmData pref(const_cast<void *>(reinterpret_cast<const void *>(dataPtr)), dataLen); | |
1025 | item->setAttribute(Schema::attributeInfo(kSecGenericItemAttr), pref); | |
1026 | CFRelease(pItemRef); | |
1027 | ||
1028 | if (add) { | |
1029 | Keychain keychain = nil; | |
1030 | try { | |
1031 | keychain = globals().storageManager.defaultKeychain(); | |
1032 | if (!keychain->exists()) | |
1033 | MacOSError::throwMe(errSecNoSuchKeychain); // Might be deleted or not available at this time. | |
1034 | } | |
1035 | catch(...) { | |
1036 | keychain = globals().storageManager.defaultKeychainUI(item); | |
1037 | } | |
1038 | ||
1039 | try { | |
1040 | keychain->add(item); | |
1041 | } | |
1042 | catch (const MacOSError &err) { | |
1043 | if (err.osStatus() != errSecDuplicateItem) | |
1044 | throw; // if item already exists, fall through to update | |
1045 | } | |
1046 | } | |
1047 | item->update(); | |
1048 | ||
5c19dc3a | 1049 | END_SECCERTAPI |
b1ab9ed8 A |
1050 | } |
1051 | ||
5c19dc3a | 1052 | /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */ |
b1ab9ed8 A |
1053 | OSStatus SecCertificateSetPreferred( |
1054 | SecCertificateRef certificate, | |
1055 | CFStringRef name, | |
1056 | CFArrayRef keyUsage) | |
1057 | { | |
1058 | CSSM_KEYUSE keyUse = ConvertArrayToKeyUsage(keyUsage); | |
1059 | return SecCertificateSetPreference(certificate, name, keyUse, NULL); | |
1060 | } | |
1061 | ||
5c19dc3a | 1062 | /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */ |
b1ab9ed8 A |
1063 | CFDictionaryRef SecCertificateCopyValues(SecCertificateRef certificate, CFArrayRef keys, CFErrorRef *error) |
1064 | { | |
1065 | CFDictionaryRef result = NULL; | |
427c49bc | 1066 | OSStatus __secapiresult; |
b1ab9ed8 A |
1067 | try |
1068 | { | |
1069 | CertificateValues cv(certificate); | |
1070 | result = cv.copyFieldValues(keys,error); | |
1071 | __secapiresult=0; | |
1072 | } | |
1073 | catch (const MacOSError &err) { __secapiresult=err.osStatus(); } | |
1074 | catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } | |
427c49bc A |
1075 | catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } |
1076 | catch (...) { __secapiresult=errSecInternalComponent; } | |
1077 | return result; | |
b1ab9ed8 A |
1078 | } |
1079 | ||
5c19dc3a | 1080 | /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */ |
b1ab9ed8 A |
1081 | CFStringRef SecCertificateCopyLongDescription(CFAllocatorRef alloc, SecCertificateRef certificate, CFErrorRef *error) |
1082 | { | |
1083 | return SecCertificateCopyShortDescription(alloc, certificate, error); | |
1084 | } | |
1085 | ||
5c19dc3a | 1086 | /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */ |
b1ab9ed8 A |
1087 | CFStringRef SecCertificateCopyShortDescription(CFAllocatorRef alloc, SecCertificateRef certificate, CFErrorRef *error) |
1088 | { | |
1089 | CFStringRef result = NULL; | |
5c19dc3a | 1090 | OSStatus __secapiresult = SecCertificateInferLabel(certificate, &result); |
427c49bc | 1091 | if (error!=NULL && __secapiresult!=errSecSuccess) |
b1ab9ed8 A |
1092 | { |
1093 | *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainOSStatus, | |
1094 | __secapiresult ? __secapiresult : CSSM_ERRCODE_INTERNAL_ERROR, NULL); | |
1095 | } | |
427c49bc | 1096 | return result; |
b1ab9ed8 A |
1097 | } |
1098 | ||
5c19dc3a | 1099 | /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */ |
b1ab9ed8 A |
1100 | CFDataRef SecCertificateCopySerialNumber(SecCertificateRef certificate, CFErrorRef *error) |
1101 | { | |
1102 | CFDataRef result = NULL; | |
427c49bc | 1103 | OSStatus __secapiresult; |
b1ab9ed8 A |
1104 | try |
1105 | { | |
1106 | CertificateValues cv(certificate); | |
1107 | result = cv.copySerialNumber(error); | |
1108 | __secapiresult=0; | |
1109 | } | |
1110 | catch (const MacOSError &err) { __secapiresult=err.osStatus(); } | |
1111 | catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } | |
427c49bc A |
1112 | catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } |
1113 | catch (...) { __secapiresult=errSecInternalComponent; } | |
1114 | return result; | |
b1ab9ed8 A |
1115 | } |
1116 | ||
5c19dc3a | 1117 | /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */ |
b1ab9ed8 A |
1118 | CFDataRef SecCertificateCopyNormalizedIssuerContent(SecCertificateRef certificate, CFErrorRef *error) |
1119 | { | |
1120 | CFDataRef result = NULL; | |
427c49bc | 1121 | OSStatus __secapiresult; |
b1ab9ed8 A |
1122 | try |
1123 | { | |
1124 | CertificateValues cv(certificate); | |
427c49bc | 1125 | result = cv.copyNormalizedIssuerContent(error); |
b1ab9ed8 A |
1126 | __secapiresult=0; |
1127 | } | |
1128 | catch (const MacOSError &err) { __secapiresult=err.osStatus(); } | |
1129 | catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } | |
427c49bc A |
1130 | catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } |
1131 | catch (...) { __secapiresult=errSecInternalComponent; } | |
1132 | return result; | |
b1ab9ed8 A |
1133 | } |
1134 | ||
5c19dc3a | 1135 | /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */ |
b1ab9ed8 A |
1136 | CFDataRef SecCertificateCopyNormalizedSubjectContent(SecCertificateRef certificate, CFErrorRef *error) |
1137 | { | |
1138 | CFDataRef result = NULL; | |
427c49bc | 1139 | OSStatus __secapiresult; |
b1ab9ed8 A |
1140 | try |
1141 | { | |
1142 | CertificateValues cv(certificate); | |
427c49bc | 1143 | result = cv.copyNormalizedSubjectContent(error); |
b1ab9ed8 A |
1144 | __secapiresult=0; |
1145 | } | |
1146 | catch (const MacOSError &err) { __secapiresult=err.osStatus(); } | |
1147 | catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } | |
427c49bc A |
1148 | catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } |
1149 | catch (...) { __secapiresult=errSecInternalComponent; } | |
1150 | return result; | |
b1ab9ed8 A |
1151 | } |
1152 | ||
5c19dc3a | 1153 | #if !SECTRUST_OSX |
427c49bc A |
1154 | CFDataRef SecCertificateCopyIssuerSequence(SecCertificateRef certificate) |
1155 | { | |
1156 | CFDataRef result = NULL; | |
1157 | OSStatus __secapiresult; | |
1158 | try | |
1159 | { | |
1160 | CertificateValues cv(certificate); | |
1161 | result = cv.copyIssuerSequence(NULL); | |
1162 | __secapiresult=0; | |
1163 | } | |
1164 | catch (const MacOSError &err) { __secapiresult=err.osStatus(); } | |
1165 | catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } | |
1166 | catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } | |
1167 | catch (...) { __secapiresult=errSecInternalComponent; } | |
1168 | return result; | |
1169 | } | |
5c19dc3a | 1170 | #endif |
427c49bc | 1171 | |
5c19dc3a | 1172 | #if !SECTRUST_OSX |
427c49bc A |
1173 | CFDataRef SecCertificateCopySubjectSequence(SecCertificateRef certificate) |
1174 | { | |
1175 | CFDataRef result = NULL; | |
1176 | OSStatus __secapiresult; | |
1177 | try | |
1178 | { | |
1179 | CertificateValues cv(certificate); | |
1180 | result = cv.copySubjectSequence(NULL); | |
1181 | __secapiresult=0; | |
1182 | } | |
1183 | catch (const MacOSError &err) { __secapiresult=err.osStatus(); } | |
1184 | catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } | |
1185 | catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } | |
1186 | catch (...) { __secapiresult=errSecInternalComponent; } | |
1187 | return result; | |
1188 | } | |
5c19dc3a | 1189 | #endif |
427c49bc | 1190 | |
5c19dc3a | 1191 | #if !SECTRUST_OSX |
427c49bc | 1192 | bool SecCertificateIsValid(SecCertificateRef certificate, CFAbsoluteTime verifyTime) |
b1ab9ed8 A |
1193 | { |
1194 | bool result = NULL; | |
427c49bc | 1195 | OSStatus __secapiresult; |
b1ab9ed8 A |
1196 | try |
1197 | { | |
427c49bc | 1198 | CFErrorRef error = NULL; |
b1ab9ed8 | 1199 | CertificateValues cv(certificate); |
427c49bc A |
1200 | result = cv.isValid(verifyTime, &error); |
1201 | if (error) CFRelease(error); | |
b1ab9ed8 A |
1202 | __secapiresult=0; |
1203 | } | |
1204 | catch (const MacOSError &err) { __secapiresult=err.osStatus(); } | |
1205 | catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } | |
427c49bc A |
1206 | catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } |
1207 | catch (...) { __secapiresult=errSecInternalComponent; } | |
1208 | return result; | |
1209 | } | |
5c19dc3a | 1210 | #endif |
427c49bc | 1211 | |
5c19dc3a | 1212 | /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_9, __IPHONE_NA, __IPHONE_NA) */ |
427c49bc A |
1213 | bool SecCertificateIsValidX(SecCertificateRef certificate, CFAbsoluteTime verifyTime) |
1214 | { | |
5c19dc3a A |
1215 | /* |
1216 | * deprecated function name | |
1217 | */ | |
427c49bc A |
1218 | return SecCertificateIsValid(certificate, verifyTime); |
1219 | } | |
1220 | ||
5c19dc3a | 1221 | #if !SECTRUST_OSX |
427c49bc A |
1222 | CFAbsoluteTime SecCertificateNotValidBefore(SecCertificateRef certificate) |
1223 | { | |
1224 | CFAbsoluteTime result = 0; | |
1225 | OSStatus __secapiresult; | |
1226 | try | |
1227 | { | |
1228 | CFErrorRef error = NULL; | |
1229 | CertificateValues cv(certificate); | |
1230 | result = cv.notValidBefore(&error); | |
1231 | if (error) CFRelease(error); | |
1232 | __secapiresult=0; | |
1233 | } | |
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; } | |
1238 | return result; | |
1239 | } | |
5c19dc3a | 1240 | #endif |
427c49bc | 1241 | |
5c19dc3a | 1242 | #if !SECTRUST_OSX |
427c49bc A |
1243 | CFAbsoluteTime SecCertificateNotValidAfter(SecCertificateRef certificate) |
1244 | { | |
1245 | CFAbsoluteTime result = 0; | |
1246 | OSStatus __secapiresult; | |
1247 | try | |
1248 | { | |
1249 | CFErrorRef error = NULL; | |
1250 | CertificateValues cv(certificate); | |
1251 | result = cv.notValidAfter(&error); | |
1252 | if (error) CFRelease(error); | |
1253 | __secapiresult=0; | |
1254 | } | |
1255 | catch (const MacOSError &err) { __secapiresult=err.osStatus(); } | |
1256 | catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } | |
1257 | catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } | |
1258 | catch (...) { __secapiresult=errSecInternalComponent; } | |
1259 | return result; | |
b1ab9ed8 | 1260 | } |
5c19dc3a | 1261 | #endif |
b1ab9ed8 | 1262 | |
5c19dc3a | 1263 | #if !SECTRUST_OSX |
b1ab9ed8 A |
1264 | /* new in 10.8 */ |
1265 | SecCertificateRef SecCertificateCreateWithBytes(CFAllocatorRef allocator, | |
1266 | const UInt8 *bytes, CFIndex length) | |
1267 | { | |
1268 | SecCertificateRef certificate = NULL; | |
1269 | OSStatus __secapiresult; | |
1270 | try { | |
1271 | CSSM_DATA cssmCertData = { (CSSM_SIZE)length, (uint8 *)bytes }; | |
1272 | ||
1273 | //NOTE: there isn't yet a Certificate constructor which accepts a CFAllocatorRef | |
1274 | SecPointer<Certificate> certificatePtr(new Certificate(cssmCertData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER)); | |
1275 | certificate = certificatePtr->handle(); | |
1276 | ||
427c49bc | 1277 | __secapiresult=errSecSuccess; |
b1ab9ed8 A |
1278 | } |
1279 | catch (const MacOSError &err) { __secapiresult=err.osStatus(); } | |
1280 | catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } | |
427c49bc A |
1281 | catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } |
1282 | catch (...) { __secapiresult=errSecInternalComponent; } | |
b1ab9ed8 A |
1283 | return certificate; |
1284 | } | |
5c19dc3a | 1285 | #endif |
b1ab9ed8 | 1286 | |
5c19dc3a | 1287 | #if !SECTRUST_OSX |
b1ab9ed8 A |
1288 | /* new in 10.8 */ |
1289 | CFIndex SecCertificateGetLength(SecCertificateRef certificate) | |
1290 | { | |
1291 | CFIndex length = 0; | |
1292 | OSStatus __secapiresult; | |
1293 | try { | |
1294 | CssmData output = Certificate::required(certificate)->data(); | |
1295 | length = (CFIndex)output.length(); | |
427c49bc | 1296 | __secapiresult=errSecSuccess; |
b1ab9ed8 A |
1297 | } |
1298 | catch (const MacOSError &err) { __secapiresult=err.osStatus(); } | |
1299 | catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } | |
427c49bc A |
1300 | catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } |
1301 | catch (...) { __secapiresult=errSecInternalComponent; } | |
b1ab9ed8 A |
1302 | return length; |
1303 | } | |
5c19dc3a | 1304 | #endif |
b1ab9ed8 | 1305 | |
5c19dc3a | 1306 | #if !SECTRUST_OSX |
b1ab9ed8 A |
1307 | /* new in 10.8 */ |
1308 | const UInt8 *SecCertificateGetBytePtr(SecCertificateRef certificate) | |
1309 | { | |
1310 | const UInt8 *bytes = NULL; | |
1311 | OSStatus __secapiresult; | |
1312 | try { | |
1313 | CssmData output = Certificate::required(certificate)->data(); | |
1314 | bytes = (const UInt8 *)output.data(); | |
427c49bc | 1315 | __secapiresult=errSecSuccess; |
b1ab9ed8 A |
1316 | } |
1317 | catch (const MacOSError &err) { __secapiresult=err.osStatus(); } | |
1318 | catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); } | |
427c49bc A |
1319 | catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; } |
1320 | catch (...) { __secapiresult=errSecInternalComponent; } | |
b1ab9ed8 A |
1321 | return bytes; |
1322 | } | |
5c19dc3a | 1323 | #endif |
b1ab9ed8 | 1324 | |
5c19dc3a A |
1325 | #if !SECTRUST_OSX |
1326 | /* not exported */ | |
d8f41ccd | 1327 | static CFArrayRef CopyEscrowCertificates(SecCertificateEscrowRootType escrowRootType, CFErrorRef *error) |
427c49bc A |
1328 | { |
1329 | // Return array of CFDataRef certificates. | |
1330 | CFArrayRef result = NULL; | |
1331 | int iCnt; | |
1332 | int numRoots = 0; | |
1333 | ||
1334 | // Get the hard coded set of production roots | |
1335 | // static struct RootRecord* kProductionEscrowRoots[] = {&kOldEscrowRootRecord, &kProductionEscrowRootRecord}; | |
1336 | ||
d8f41ccd A |
1337 | struct RootRecord** pEscrowRoots = NULL; |
1338 | switch (escrowRootType) { | |
1339 | case kSecCertificateBaselineEscrowRoot: | |
1340 | numRoots = kNumberOfBaseLineEscrowRoots; | |
1341 | pEscrowRoots = kBaseLineEscrowRoots; | |
1342 | break; | |
1343 | case kSecCertificateProductionEscrowRoot: | |
1344 | numRoots = kNumberOfBaseLineEscrowRoots; //%%% currently, production == baseline on OS X | |
1345 | pEscrowRoots = kBaseLineEscrowRoots; | |
1346 | break; | |
1347 | case kSecCertificateBaselinePCSEscrowRoot: | |
1348 | numRoots = kNumberOfBaseLinePCSEscrowRoots; | |
1349 | pEscrowRoots = kBaseLinePCSEscrowRoots; | |
1350 | break; | |
1351 | case kSecCertificateProductionPCSEscrowRoot: | |
1352 | numRoots = kNumberOfBaseLinePCSEscrowRoots; //%%% currently, production == baseline on OS X | |
1353 | pEscrowRoots = kBaseLinePCSEscrowRoots; | |
1354 | break; | |
1355 | default: | |
1356 | break; | |
1357 | } | |
1358 | ||
427c49bc A |
1359 | CFDataRef productionCerts[numRoots]; |
1360 | struct RootRecord* pRootRecord = NULL; | |
1361 | ||
d8f41ccd | 1362 | for (iCnt = 0; pEscrowRoots != NULL && iCnt < numRoots; iCnt++) |
427c49bc | 1363 | { |
d8f41ccd | 1364 | pRootRecord = pEscrowRoots[iCnt]; |
427c49bc A |
1365 | if (NULL != pRootRecord && pRootRecord->_length > 0 && NULL != pRootRecord->_bytes) |
1366 | { | |
1367 | productionCerts[iCnt] = CFDataCreate(kCFAllocatorDefault, pRootRecord->_bytes, pRootRecord->_length); | |
1368 | } | |
1369 | } | |
1370 | result = CFArrayCreate(kCFAllocatorDefault, (const void **)productionCerts, numRoots, &kCFTypeArrayCallBacks); | |
1371 | for (iCnt = 0; iCnt < numRoots; iCnt++) | |
1372 | { | |
1373 | if (NULL != productionCerts[iCnt]) | |
1374 | { | |
1375 | CFRelease(productionCerts[iCnt]); | |
1376 | } | |
1377 | } | |
1378 | ||
1379 | return result; | |
1380 | } | |
5c19dc3a | 1381 | #endif |
427c49bc | 1382 | |
5c19dc3a | 1383 | #if !SECTRUST_OSX |
427c49bc A |
1384 | /* new in 10.9 */ |
1385 | CFArrayRef SecCertificateCopyEscrowRoots(SecCertificateEscrowRootType escrowRootType) | |
1386 | { | |
1387 | CFArrayRef result = NULL; | |
1388 | int iCnt; | |
1389 | int numRoots = 0; | |
1390 | CFDataRef certData = NULL; | |
1391 | ||
1392 | // The request is for the base line certificates. | |
1393 | // Use the hard coded data to generate the return array | |
1394 | if (kSecCertificateBaselineEscrowRoot == escrowRootType) | |
1395 | { | |
1396 | // Get the hard coded set of roots | |
1397 | numRoots = kNumberOfBaseLineEscrowRoots; | |
1398 | SecCertificateRef baseLineCerts[numRoots]; | |
1399 | struct RootRecord* pRootRecord = NULL; | |
1400 | ||
1401 | for (iCnt = 0; iCnt < numRoots; iCnt++) | |
1402 | { | |
1403 | pRootRecord = kBaseLineEscrowRoots[iCnt]; | |
1404 | if (NULL != pRootRecord && pRootRecord->_length > 0 && NULL != pRootRecord->_bytes) | |
1405 | { | |
1406 | certData = CFDataCreate(kCFAllocatorDefault, pRootRecord->_bytes, pRootRecord->_length); | |
1407 | if (NULL != certData) | |
1408 | { | |
1409 | baseLineCerts[iCnt] = SecCertificateCreateWithData(kCFAllocatorDefault, certData); | |
1410 | CFRelease(certData); | |
1411 | } | |
1412 | } | |
1413 | } | |
1414 | result = CFArrayCreate(kCFAllocatorDefault, (const void **)baseLineCerts, numRoots, &kCFTypeArrayCallBacks); | |
1415 | for (iCnt = 0; iCnt < numRoots; iCnt++) | |
1416 | { | |
1417 | if (NULL != baseLineCerts[iCnt]) | |
1418 | { | |
1419 | CFRelease(baseLineCerts[iCnt]); | |
1420 | } | |
1421 | } | |
1422 | } | |
1423 | // The request is for the current certificates. | |
d8f41ccd | 1424 | else |
427c49bc A |
1425 | { |
1426 | CFErrorRef error = NULL; | |
d8f41ccd | 1427 | CFArrayRef cert_datas = CopyEscrowCertificates(escrowRootType, &error); |
427c49bc A |
1428 | if (NULL != error || NULL == cert_datas || 0 == (numRoots = (int)CFArrayGetCount(cert_datas))) |
1429 | { | |
1430 | if (NULL != error) | |
1431 | { | |
1432 | CFRelease(error); | |
1433 | } | |
1434 | ||
1435 | if (NULL != cert_datas) | |
1436 | { | |
1437 | CFRelease(cert_datas); | |
1438 | } | |
1439 | return result; | |
1440 | } | |
1441 | ||
1442 | SecCertificateRef assetCerts[numRoots]; | |
1443 | for (iCnt = 0; iCnt < numRoots; iCnt++) | |
1444 | { | |
1445 | certData = (CFDataRef)CFArrayGetValueAtIndex(cert_datas, iCnt); | |
1446 | if (NULL != certData) | |
1447 | { | |
1448 | SecCertificateRef aCertRef = SecCertificateCreateWithData(kCFAllocatorDefault, certData); | |
1449 | assetCerts[iCnt] = aCertRef; | |
1450 | } | |
1451 | else | |
1452 | { | |
1453 | assetCerts[iCnt] = NULL; | |
1454 | } | |
1455 | } | |
1456 | ||
1457 | if (numRoots > 0) | |
1458 | { | |
1459 | result = CFArrayCreate(kCFAllocatorDefault, (const void **)assetCerts, numRoots, &kCFTypeArrayCallBacks); | |
1460 | for (iCnt = 0; iCnt < numRoots; iCnt++) | |
1461 | { | |
1462 | if (NULL != assetCerts[iCnt]) | |
1463 | { | |
1464 | CFRelease(assetCerts[iCnt]); | |
1465 | } | |
1466 | } | |
1467 | } | |
1468 | CFRelease(cert_datas); | |
1469 | } | |
5c19dc3a | 1470 | |
427c49bc A |
1471 | return result; |
1472 | } | |
5c19dc3a A |
1473 | #endif |
1474 | ||
1475 | #if !SECTRUST_OSX | |
1476 | /* new in 10.11 */ | |
1477 | SecSignatureHashAlgorithm SecCertificateGetSignatureHashAlgorithm(SecCertificateRef certificate) | |
1478 | { | |
1479 | SecSignatureHashAlgorithm result = kSecSignatureHashAlgorithmUnknown; | |
1480 | CSSM_X509_ALGORITHM_IDENTIFIER_PTR algId = NULL; | |
1481 | CSSM_DATA_PTR fieldValue = NULL; | |
1482 | CSSM_OID_PTR algOID = NULL; | |
1483 | const CSSM_OID *sigAlgOID = &CSSMOID_X509V1SignatureAlgorithm; | |
1484 | OSStatus status; | |
1485 | ||
1486 | status = SecCertificateCopyFirstFieldValue(certificate, sigAlgOID, &fieldValue); | |
1487 | if (status || !fieldValue) { | |
1488 | return result; | |
1489 | } | |
1490 | algId = (CSSM_X509_ALGORITHM_IDENTIFIER_PTR)fieldValue->Data; | |
1491 | algOID = (algId) ? &algId->algorithm : NULL; | |
1492 | ||
1493 | while (algOID) { | |
1494 | if (!algOID->Data || !algOID->Length) { | |
1495 | break; | |
1496 | } | |
1497 | /* classify the signature algorithm OID into one of our known types */ | |
1498 | if (cuCompareCssmData(algOID, &CSSMOID_ECDSA_WithSHA512) || | |
1499 | cuCompareCssmData(algOID, &CSSMOID_SHA512WithRSA) || | |
1500 | cuCompareCssmData(algOID, &CSSMOID_SHA512)) { | |
1501 | result = kSecSignatureHashAlgorithmSHA512; | |
1502 | break; | |
1503 | } | |
1504 | if (cuCompareCssmData(algOID, &CSSMOID_ECDSA_WithSHA384) || | |
1505 | cuCompareCssmData(algOID, &CSSMOID_SHA384WithRSA) || | |
1506 | cuCompareCssmData(algOID, &CSSMOID_SHA384)) { | |
1507 | result = kSecSignatureHashAlgorithmSHA384; | |
1508 | break; | |
1509 | } | |
1510 | if (cuCompareCssmData(algOID, &CSSMOID_ECDSA_WithSHA256) || | |
1511 | cuCompareCssmData(algOID, &CSSMOID_SHA256WithRSA) || | |
1512 | cuCompareCssmData(algOID, &CSSMOID_SHA256)) { | |
1513 | result = kSecSignatureHashAlgorithmSHA256; | |
1514 | break; | |
1515 | } | |
1516 | if (cuCompareCssmData(algOID, &CSSMOID_ECDSA_WithSHA224) || | |
1517 | cuCompareCssmData(algOID, &CSSMOID_SHA224WithRSA) || | |
1518 | cuCompareCssmData(algOID, &CSSMOID_SHA224)) { | |
1519 | result = kSecSignatureHashAlgorithmSHA224; | |
1520 | break; | |
1521 | } | |
1522 | if (cuCompareCssmData(algOID, &CSSMOID_ECDSA_WithSHA1) || | |
1523 | cuCompareCssmData(algOID, &CSSMOID_SHA1WithRSA) || | |
1524 | cuCompareCssmData(algOID, &CSSMOID_SHA1WithDSA) || | |
1525 | cuCompareCssmData(algOID, &CSSMOID_SHA1WithDSA_CMS) || | |
1526 | cuCompareCssmData(algOID, &CSSMOID_SHA1WithDSA_JDK) || | |
1527 | cuCompareCssmData(algOID, &CSSMOID_SHA1WithRSA_OIW) || | |
1528 | cuCompareCssmData(algOID, &CSSMOID_APPLE_FEE_SHA1) || | |
1529 | cuCompareCssmData(algOID, &CSSMOID_SHA1)) { | |
1530 | result = kSecSignatureHashAlgorithmSHA1; | |
1531 | break; | |
1532 | } | |
1533 | if (cuCompareCssmData(algOID, &CSSMOID_MD5WithRSA) || | |
1534 | cuCompareCssmData(algOID, &CSSMOID_APPLE_FEE_MD5) || | |
1535 | cuCompareCssmData(algOID, &CSSMOID_MD5)) { | |
1536 | result = kSecSignatureHashAlgorithmMD5; | |
1537 | break; | |
1538 | } | |
1539 | if (cuCompareCssmData(algOID, &CSSMOID_MD4WithRSA) || | |
1540 | cuCompareCssmData(algOID, &CSSMOID_MD4)) { | |
1541 | result = kSecSignatureHashAlgorithmMD4; | |
1542 | break; | |
1543 | } | |
1544 | if (cuCompareCssmData(algOID, &CSSMOID_MD2WithRSA) || | |
1545 | cuCompareCssmData(algOID, &CSSMOID_MD2)) { | |
1546 | result = kSecSignatureHashAlgorithmMD2; | |
1547 | break; | |
1548 | } | |
1549 | break; | |
1550 | } | |
1551 | ||
1552 | (void)SecCertificateReleaseFirstFieldValue(certificate, sigAlgOID, fieldValue); | |
1553 | ||
1554 | return result; | |
1555 | } | |
1556 | #endif | |
427c49bc | 1557 |