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