]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_keychain/lib/SecCertificate.cpp
Security-57337.50.23.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
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
282 #endif
283
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
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 }
321 #endif
322
323 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
324 OSStatus
325 SecCertificateGetType(SecCertificateRef certificate, CSSM_CERT_TYPE *certificateType)
326 {
327 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
328 BEGIN_SECCERTAPI
329
330 Required(certificateType) = Certificate::required(__itemImplRef)->type();
331
332 END_SECCERTAPI
333 }
334
335 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
336 OSStatus
337 SecCertificateGetSubject(SecCertificateRef certificate, const CSSM_X509_NAME **subject)
338 {
339 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
340 BEGIN_SECCERTAPI
341
342 Required(subject) = Certificate::required(__itemImplRef)->subjectName();
343
344 END_SECCERTAPI
345 }
346
347 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
348 OSStatus
349 SecCertificateGetIssuer(SecCertificateRef certificate, const CSSM_X509_NAME **issuer)
350 {
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
364 BEGIN_SECAPI
365
366 Required(clHandle) = Certificate::required(certificate)->clHandle();
367
368 END_SECAPI
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;
410
411 #endif
412 }
413
414 /* private function; assumes input is old-style ItemImpl certificate reference,
415 and does not release that certificate reference!
416 */
417 OSStatus
418 SecCertificateGetCLHandle_legacy(SecCertificateRef certificate, CSSM_CL_HANDLE *clHandle)
419 {
420 BEGIN_SECAPI
421
422 Required(clHandle) = Certificate::required(certificate)->clHandle();
423
424 END_SECAPI
425 }
426
427
428 /*
429 * Private API to infer a display name for a SecCertificateRef which
430 * may or may not be in a keychain.
431 *
432 * OS X only
433 */
434 OSStatus
435 SecCertificateInferLabel(SecCertificateRef certificate, CFStringRef *label)
436 {
437 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
438 BEGIN_SECCERTAPI
439
440 Certificate::required(__itemImplRef)->inferLabel(false, &Required(label));
441
442 END_SECCERTAPI
443 }
444
445 /* OS X only (note: iOS version has different arguments and return value) */
446 OSStatus
447 SecCertificateCopyPublicKey(SecCertificateRef certificate, SecKeyRef *key)
448 {
449 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
450 BEGIN_SECCERTAPI
451
452 Required(key) = Certificate::required(__itemImplRef)->publicKey()->handle();
453
454 END_SECCERTAPI
455 }
456
457 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
458 OSStatus
459 SecCertificateGetAlgorithmID(SecCertificateRef certificate, const CSSM_X509_ALGORITHM_IDENTIFIER **algid)
460 {
461 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
462 BEGIN_SECCERTAPI
463
464 Required(algid) = Certificate::required(__itemImplRef)->algorithmID();
465
466 END_SECCERTAPI
467 }
468
469 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA) */
470 OSStatus
471 SecCertificateCopyCommonName(SecCertificateRef certificate, CFStringRef *commonName)
472 {
473 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
474 BEGIN_SECCERTAPI
475
476 Required(commonName) = Certificate::required(__itemImplRef)->commonName();
477
478 END_SECCERTAPI
479 }
480
481 #if !SECTRUST_OSX
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
491 __secapiresult=errSecSuccess;
492 }
493 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
494 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
495 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
496 catch (...) { __secapiresult=errSecInternalComponent; }
497 return summary;
498 }
499 #endif
500
501 #if !SECTRUST_OSX
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 }
518 #endif
519
520 /* OS X only */
521 OSStatus
522 SecCertificateCopySubjectComponent(SecCertificateRef certificate, const CSSM_OID *component, CFStringRef *result)
523 {
524 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
525 BEGIN_SECCERTAPI
526
527 Required(result) = Certificate::required(__itemImplRef)->distinguishedName(&CSSMOID_X509V1SubjectNameCStruct, component);
528
529 END_SECCERTAPI
530 }
531
532 /* OS X only; deprecated SPI */
533 OSStatus
534 SecCertificateGetCommonName(SecCertificateRef certificate, CFStringRef *commonName)
535 {
536 // deprecated SPI signature; replaced by SecCertificateCopyCommonName
537 return SecCertificateCopyCommonName(certificate, commonName);
538 }
539
540 /* OS X only; deprecated SPI */
541 OSStatus
542 SecCertificateGetEmailAddress(SecCertificateRef certificate, CFStringRef *emailAddress)
543 {
544 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
545 BEGIN_SECCERTAPI
546
547 Required(emailAddress) = Certificate::required(__itemImplRef)->copyFirstEmailAddress();
548
549 END_SECCERTAPI
550 }
551
552 /* OS X only */
553 OSStatus
554 SecCertificateCopyEmailAddresses(SecCertificateRef certificate, CFArrayRef *emailAddresses)
555 {
556 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
557 BEGIN_SECCERTAPI
558
559 Required(emailAddresses) = Certificate::required(__itemImplRef)->copyEmailAddresses();
560
561 END_SECCERTAPI
562 }
563
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 */
569 OSStatus
570 SecCertificateCopyFieldValues(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR **fieldValues)
571 {
572 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
573 BEGIN_SECCERTAPI
574
575 Required(fieldValues) = Certificate::required(__itemImplRef)->copyFieldValues(Required(field));
576
577 END_SECCERTAPI
578 }
579
580 /* OS X only */
581 OSStatus
582 SecCertificateReleaseFieldValues(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR *fieldValues)
583 {
584 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
585 BEGIN_SECCERTAPI
586
587 Certificate::required(__itemImplRef)->releaseFieldValues(Required(field), fieldValues);
588
589 END_SECCERTAPI
590 }
591
592 /* OS X only */
593 OSStatus
594 SecCertificateCopyFirstFieldValue(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR *fieldValue)
595 {
596 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
597 BEGIN_SECCERTAPI
598
599 Required(fieldValue) = Certificate::required(__itemImplRef)->copyFirstFieldValue(Required(field));
600
601 END_SECCERTAPI
602 }
603
604 /* OS X only */
605 OSStatus
606 SecCertificateReleaseFirstFieldValue(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR fieldValue)
607 {
608 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
609 BEGIN_SECCERTAPI
610
611 Certificate::required(__itemImplRef)->releaseFieldValue(Required(field), fieldValue);
612
613 END_SECCERTAPI
614 }
615
616 /* OS X only */
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
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
636 END_SECAPI
637 }
638
639 /* OS X only */
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
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
659 END_SECAPI
660 }
661
662 /* OS X only */
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
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
681 END_SECAPI
682 }
683
684 /* OS X only */
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
701 /* OS X only */
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
720 /* OS X only */
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
737 /* OS X only */
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
754 /* OS X only */
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)
761 return errSecParam;
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
775 #if !SECTRUST_OSX
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 }
787 #endif
788
789 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
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
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
844 END_SECAPI
845 }
846
847 /* OS X only */
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);
861 if (status != errSecSuccess && keyUse != CSSM_KEYUSE_ANY)
862 status = SecCertificateCopyPreference(name, CSSM_KEYUSE_ANY, &certRef);
863 if (status != errSecSuccess && keyUse != 0)
864 status = SecCertificateCopyPreference(name, 0, &certRef);
865
866 return certRef;
867 }
868
869 /* OS X only; not exported */
870 static OSStatus
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)
892 MacOSError::throwMe(errSecParam);
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
910 /* OS X only; not exported */
911 static
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 &&
927 (status = SecCertificateFindPreferenceItemWithNameAndKeyUsage(keychainOrArray, name, keyUsage, &item)) == errSecSuccess) {
928 status = SecKeychainItemDelete(item);
929 CFRelease(item);
930 item = NULL;
931 }
932
933 // it's not an error if the item isn't found
934 return (status == errSecItemNotFound) ? errSecSuccess : status;
935 }
936
937 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA) */
938 OSStatus SecCertificateSetPreference(
939 SecCertificateRef certificate,
940 CFStringRef name,
941 CSSM_KEYUSE keyUsage,
942 CFDateRef date)
943 {
944 if (!name) {
945 return errSecParam;
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
953 // This macro converts a new-style SecCertificateRef to an old-style ItemImpl
954 BEGIN_SECCERTAPI
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;
966 Certificate::required(__itemImplRef)->inferLabel(false, &labelStr);
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;
1018 Certificate::required(__itemImplRef)->copyPersistentReference(pItemRef);
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
1049 END_SECCERTAPI
1050 }
1051
1052 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
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
1062 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
1063 CFDictionaryRef SecCertificateCopyValues(SecCertificateRef certificate, CFArrayRef keys, CFErrorRef *error)
1064 {
1065 CFDictionaryRef result = NULL;
1066 OSStatus __secapiresult;
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()); }
1075 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
1076 catch (...) { __secapiresult=errSecInternalComponent; }
1077 return result;
1078 }
1079
1080 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
1081 CFStringRef SecCertificateCopyLongDescription(CFAllocatorRef alloc, SecCertificateRef certificate, CFErrorRef *error)
1082 {
1083 return SecCertificateCopyShortDescription(alloc, certificate, error);
1084 }
1085
1086 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
1087 CFStringRef SecCertificateCopyShortDescription(CFAllocatorRef alloc, SecCertificateRef certificate, CFErrorRef *error)
1088 {
1089 CFStringRef result = NULL;
1090 OSStatus __secapiresult = SecCertificateInferLabel(certificate, &result);
1091 if (error!=NULL && __secapiresult!=errSecSuccess)
1092 {
1093 *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainOSStatus,
1094 __secapiresult ? __secapiresult : CSSM_ERRCODE_INTERNAL_ERROR, NULL);
1095 }
1096 return result;
1097 }
1098
1099 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
1100 CFDataRef SecCertificateCopySerialNumber(SecCertificateRef certificate, CFErrorRef *error)
1101 {
1102 CFDataRef result = NULL;
1103 OSStatus __secapiresult;
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()); }
1112 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
1113 catch (...) { __secapiresult=errSecInternalComponent; }
1114 return result;
1115 }
1116
1117 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
1118 CFDataRef SecCertificateCopyNormalizedIssuerContent(SecCertificateRef certificate, CFErrorRef *error)
1119 {
1120 CFDataRef result = NULL;
1121 OSStatus __secapiresult;
1122 try
1123 {
1124 CertificateValues cv(certificate);
1125 result = cv.copyNormalizedIssuerContent(error);
1126 __secapiresult=0;
1127 }
1128 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
1129 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
1130 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
1131 catch (...) { __secapiresult=errSecInternalComponent; }
1132 return result;
1133 }
1134
1135 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
1136 CFDataRef SecCertificateCopyNormalizedSubjectContent(SecCertificateRef certificate, CFErrorRef *error)
1137 {
1138 CFDataRef result = NULL;
1139 OSStatus __secapiresult;
1140 try
1141 {
1142 CertificateValues cv(certificate);
1143 result = cv.copyNormalizedSubjectContent(error);
1144 __secapiresult=0;
1145 }
1146 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
1147 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
1148 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
1149 catch (...) { __secapiresult=errSecInternalComponent; }
1150 return result;
1151 }
1152
1153 #if !SECTRUST_OSX
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 }
1170 #endif
1171
1172 #if !SECTRUST_OSX
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 }
1189 #endif
1190
1191 #if !SECTRUST_OSX
1192 bool SecCertificateIsValid(SecCertificateRef certificate, CFAbsoluteTime verifyTime)
1193 {
1194 bool result = NULL;
1195 OSStatus __secapiresult;
1196 try
1197 {
1198 CFErrorRef error = NULL;
1199 CertificateValues cv(certificate);
1200 result = cv.isValid(verifyTime, &error);
1201 if (error) CFRelease(error);
1202 __secapiresult=0;
1203 }
1204 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
1205 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
1206 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
1207 catch (...) { __secapiresult=errSecInternalComponent; }
1208 return result;
1209 }
1210 #endif
1211
1212 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_9, __IPHONE_NA, __IPHONE_NA) */
1213 bool SecCertificateIsValidX(SecCertificateRef certificate, CFAbsoluteTime verifyTime)
1214 {
1215 /*
1216 * deprecated function name
1217 */
1218 return SecCertificateIsValid(certificate, verifyTime);
1219 }
1220
1221 #if !SECTRUST_OSX
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 }
1240 #endif
1241
1242 #if !SECTRUST_OSX
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;
1260 }
1261 #endif
1262
1263 #if !SECTRUST_OSX
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
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 certificate;
1284 }
1285 #endif
1286
1287 #if !SECTRUST_OSX
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();
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 length;
1303 }
1304 #endif
1305
1306 #if !SECTRUST_OSX
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();
1315 __secapiresult=errSecSuccess;
1316 }
1317 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
1318 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
1319 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
1320 catch (...) { __secapiresult=errSecInternalComponent; }
1321 return bytes;
1322 }
1323 #endif
1324
1325 #if !SECTRUST_OSX
1326 /* not exported */
1327 static CFArrayRef CopyEscrowCertificates(SecCertificateEscrowRootType escrowRootType, CFErrorRef *error)
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
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
1359 CFDataRef productionCerts[numRoots];
1360 struct RootRecord* pRootRecord = NULL;
1361
1362 for (iCnt = 0; pEscrowRoots != NULL && iCnt < numRoots; iCnt++)
1363 {
1364 pRootRecord = pEscrowRoots[iCnt];
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 }
1381 #endif
1382
1383 #if !SECTRUST_OSX
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.
1424 else
1425 {
1426 CFErrorRef error = NULL;
1427 CFArrayRef cert_datas = CopyEscrowCertificates(escrowRootType, &error);
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 }
1470
1471 return result;
1472 }
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
1557