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