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