]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_keychain/lib/SecCertificate.cpp
Security-58286.200.222.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
49 #include "AppleBaselineEscrowCertificates.h"
50
51
52 OSStatus SecCertificateGetCLHandle_legacy(SecCertificateRef certificate, CSSM_CL_HANDLE *clHandle);
53 extern CSSM_KEYUSE ConvertArrayToKeyUsage(CFArrayRef usage);
54
55
56
57
58 using namespace CssmClient;
59
60 CFTypeID static SecCertificateGetTypeID_osx(void)
61 {
62 BEGIN_SECAPI
63
64 return gTypes().Certificate.typeID;
65
66 END_SECAPI1(_kCFRuntimeNotATypeID)
67 }
68
69 Boolean
70 SecCertificateIsItemImplInstance(SecCertificateRef certificate)
71 {
72 if (certificate == NULL) {
73 return false;
74 }
75
76 CFTypeID typeID = CFGetTypeID(certificate);
77
78 #if 0 /* debug code to verify type IDs */
79 syslog(LOG_ERR, "SecCertificate typeID=%d [STU=%d, OSX=%d, SKI=%d]",
80 (int)typeID,
81 (int)SecCertificateGetTypeID(),
82 (int)SecCertificateGetTypeID_osx(),
83 (int)SecKeychainItemGetTypeID());
84 #endif
85 if (typeID == _kCFRuntimeNotATypeID) {
86 return false;
87 }
88
89 return (typeID == SecCertificateGetTypeID_osx() ||
90 typeID == SecKeychainItemGetTypeID()) ? true : false;
91 }
92
93 /* convert a new-world SecCertificateRef to an old-world ItemImpl instance */
94 SecCertificateRef
95 SecCertificateCreateItemImplInstance(SecCertificateRef certificate)
96 {
97 if (!certificate) {
98 return NULL;
99 }
100 SecCertificateRef implCertRef = (SecCertificateRef) SecCertificateCopyKeychainItem(certificate);
101 if (implCertRef) {
102 return implCertRef;
103 }
104 CFDataRef data = SecCertificateCopyData(certificate);
105 if (!data) {
106 return NULL;
107 }
108 try {
109 CSSM_DATA cssmCertData;
110 cssmCertData.Length = (data) ? (CSSM_SIZE)CFDataGetLength(data) : 0;
111 cssmCertData.Data = (data) ? (uint8 *)CFDataGetBytePtr(data) : NULL;
112
113 SecPointer<Certificate> certificatePtr(new Certificate(cssmCertData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER));
114 implCertRef = certificatePtr->handle();
115 }
116 catch (...) {}
117 CFRelease(data);
118 return implCertRef;
119 }
120
121 /* convert an old-world ItemImpl instance to a new-world SecCertificateRef */
122 SecCertificateRef
123 SecCertificateCreateFromItemImplInstance(SecCertificateRef certificate)
124 {
125 if (!certificate) {
126 return NULL;
127 }
128 SecCertificateRef result = NULL;
129 CFDataRef data = NULL;
130 try {
131 CssmData certData = Certificate::required(certificate)->data();
132 if (certData.Data && certData.Length) {
133 data = CFDataCreate(NULL, certData.Data, certData.Length);
134 }
135 if (!data) {
136 if (certData.Data && !certData.Length) {
137 /* zero-length certs can exist, so don't bother logging this */
138 }
139 else {
140 syslog(LOG_ERR, "WARNING: SecKeychainSearchCopyNext failed to retrieve certificate data (length=%ld, data=0x%lX)",
141 (long)certData.Length, (uintptr_t)certData.Data);
142 }
143 return NULL;
144 }
145 }
146 catch (...) {}
147
148 result = SecCertificateCreateWithKeychainItem(NULL, data, certificate);
149 if (data)
150 CFRelease(data);
151 return result;
152 }
153
154
155 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
156 OSStatus
157 SecCertificateCreateFromData(const CSSM_DATA *data, CSSM_CERT_TYPE type, CSSM_CERT_ENCODING encoding, SecCertificateRef *certificate)
158 {
159 /* bridge to support old functionality */
160 if (!data || !data->Data || !data->Length || !certificate) {
161 return errSecParam;
162 }
163 SecCertificateRef certRef = NULL;
164
165 // <rdar://problem/24403998> REG: Adobe {Photoshop, InDesign} CC(2015) crashes on launch
166 // If you take the length that SecKeychainItemCopyContent gives you (a Uint32) and assign it incorrectly
167 // to a CSSM_DATA Length field (a CSSM_SIZE, i.e., a size_t), the upper 32 bits aren't set. If those bits
168 // are non-zero, the length is incredibly wrong.
169 //
170 // Assume that there will not exist a certificate > 4GiB, and fake this length field.
171 CSSM_SIZE length = data->Length & 0xfffffffful;
172
173 CFDataRef dataRef = CFDataCreate(NULL, data->Data, length);
174 if (dataRef) {
175 certRef = SecCertificateCreateWithData(NULL, dataRef);
176 CFRelease(dataRef);
177 }
178 *certificate = certRef;
179 return (certRef) ? errSecSuccess : errSecUnknownFormat;
180 }
181
182 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_3, __IPHONE_NA) */
183 OSStatus
184 SecCertificateAddToKeychain(SecCertificateRef certificate, SecKeychainRef keychain)
185 {
186 // This macro creates an ItemImpl certificate if it does not exist
187 BEGIN_SECCERTAPI
188
189 Item item(Certificate::required(__itemImplRef));
190 Keychain::optional(keychain)->add(item);
191
192 END_SECCERTAPI
193 }
194
195 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
196 OSStatus
197 SecCertificateGetData(SecCertificateRef certificate, CSSM_DATA_PTR data)
198 {
199 BEGIN_SECCERTAPI
200
201 if (!certificate || !data) {
202 __secapiresult=errSecParam;
203 }
204 else if (SecCertificateIsItemImplInstance(certificate)) {
205 Required(data) = Certificate::required(certificate)->data();
206 }
207 else {
208 data->Length = (CSSM_SIZE)SecCertificateGetLength(certificate);
209 data->Data = (uint8*)SecCertificateGetBytePtr(certificate);
210 }
211
212 END_SECCERTAPI
213 }
214
215 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
216 OSStatus
217 SecCertificateGetType(SecCertificateRef certificate, CSSM_CERT_TYPE *certificateType)
218 {
219 // This macro creates an ItemImpl certificate if it does not exist
220 BEGIN_SECCERTAPI
221
222 Required(certificateType) = Certificate::required(__itemImplRef)->type();
223
224 END_SECCERTAPI
225 }
226
227 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
228 OSStatus
229 SecCertificateGetSubject(SecCertificateRef certificate, const CSSM_X509_NAME **subject)
230 {
231 // This macro creates an ItemImpl certificate if it does not exist
232 BEGIN_SECCERTAPI
233
234 Required(subject) = Certificate::required(__itemImplRef)->subjectName();
235
236 END_SECCERTAPI
237 }
238
239 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
240 OSStatus
241 SecCertificateGetIssuer(SecCertificateRef certificate, const CSSM_X509_NAME **issuer)
242 {
243 // This macro creates an ItemImpl certificate if it does not exist
244 BEGIN_SECCERTAPI
245
246 Required(issuer) = Certificate::required(__itemImplRef)->issuerName();
247
248 END_SECCERTAPI
249 }
250
251 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
252 OSStatus
253 SecCertificateGetCLHandle(SecCertificateRef certificate, CSSM_CL_HANDLE *clHandle)
254 {
255 // This macro creates an ItemImpl certificate if it does not exist
256 BEGIN_SECCERTAPI
257
258 Required(clHandle) = Certificate::required(__itemImplRef)->clHandle();
259
260 END_SECCERTAPI
261 }
262
263 /* private function; assumes input is old-style ItemImpl certificate reference,
264 and does not release that certificate reference!
265 */
266 OSStatus
267 SecCertificateGetCLHandle_legacy(SecCertificateRef certificate, CSSM_CL_HANDLE *clHandle)
268 {
269 BEGIN_SECAPI
270
271 Required(clHandle) = Certificate::required(certificate)->clHandle();
272
273 END_SECAPI
274 }
275
276 /*
277 * Private API to infer a display name for a SecCertificateRef which
278 * may or may not be in a keychain.
279 *
280 * OS X only
281 */
282 OSStatus
283 SecCertificateInferLabel(SecCertificateRef certificate, CFStringRef *label)
284 {
285 // This macro creates an ItemImpl certificate if it does not exist
286 BEGIN_SECCERTAPI
287
288 Certificate::required(__itemImplRef)->inferLabel(false, &Required(label));
289
290 END_SECCERTAPI
291 }
292
293 /* OS X only (note: iOS version has different arguments and return value) */
294 OSStatus
295 SecCertificateCopyPublicKey(SecCertificateRef certificate, SecKeyRef *key)
296 {
297 // This macro creates an ItemImpl certificate if it does not exist
298 BEGIN_SECCERTAPI
299
300 Required(key) = Certificate::required(__itemImplRef)->publicKey()->handle();
301
302 END_SECCERTAPI
303 }
304
305 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
306 OSStatus
307 SecCertificateGetAlgorithmID(SecCertificateRef certificate, const CSSM_X509_ALGORITHM_IDENTIFIER **algid)
308 {
309 // This macro creates an ItemImpl certificate if it does not exist
310 BEGIN_SECCERTAPI
311
312 Required(algid) = Certificate::required(__itemImplRef)->algorithmID();
313
314 END_SECCERTAPI
315 }
316
317 /* OS X only */
318 OSStatus
319 SecCertificateCopySubjectComponent(SecCertificateRef certificate, const CSSM_OID *component, CFStringRef *result)
320 {
321 // This macro creates an ItemImpl certificate if it does not exist
322 BEGIN_SECCERTAPI
323
324 Required(result) = Certificate::required(__itemImplRef)->distinguishedName(&CSSMOID_X509V1SubjectNameCStruct, component);
325
326 END_SECCERTAPI
327 }
328
329 /* OS X only; deprecated SPI */
330 OSStatus
331 SecCertificateGetCommonName(SecCertificateRef certificate, CFStringRef *commonName)
332 {
333 // deprecated SPI signature; replaced by SecCertificateCopyCommonName
334 return SecCertificateCopyCommonName(certificate, commonName);
335 }
336
337 /* OS X only; deprecated SPI */
338 OSStatus
339 SecCertificateGetEmailAddress(SecCertificateRef certificate, CFStringRef *emailAddress)
340 {
341 // This macro creates an ItemImpl certificate if it does not exist
342 BEGIN_SECCERTAPI
343
344 Required(emailAddress) = Certificate::required(__itemImplRef)->copyFirstEmailAddress();
345
346 END_SECCERTAPI
347 }
348
349 /* Return a zero terminated list of CSSM_DATA_PTR's with the values of the field specified by field.
350 * Caller must call releaseFieldValues to free the storage allocated by this call.
351 *
352 * OS X only
353 */
354 OSStatus
355 SecCertificateCopyFieldValues(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR **fieldValues)
356 {
357 // This macro creates an ItemImpl certificate if it does not exist
358 BEGIN_SECCERTAPI
359
360 Required(fieldValues) = Certificate::required(__itemImplRef)->copyFieldValues(Required(field));
361
362 END_SECCERTAPI
363 }
364
365 /* OS X only */
366 OSStatus
367 SecCertificateReleaseFieldValues(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR *fieldValues)
368 {
369 // This macro creates an ItemImpl certificate if it does not exist
370 BEGIN_SECCERTAPI
371
372 Certificate::required(__itemImplRef)->releaseFieldValues(Required(field), fieldValues);
373
374 END_SECCERTAPI
375 }
376
377 /* OS X only */
378 OSStatus
379 SecCertificateCopyFirstFieldValue(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR *fieldValue)
380 {
381 // This macro creates an ItemImpl certificate if it does not exist
382 BEGIN_SECCERTAPI
383
384 Required(fieldValue) = Certificate::required(__itemImplRef)->copyFirstFieldValue(Required(field));
385
386 END_SECCERTAPI
387 }
388
389 /* OS X only */
390 OSStatus
391 SecCertificateReleaseFirstFieldValue(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR fieldValue)
392 {
393 // This macro creates an ItemImpl certificate if it does not exist
394 BEGIN_SECCERTAPI
395
396 Certificate::required(__itemImplRef)->releaseFieldValue(Required(field), fieldValue);
397
398 END_SECCERTAPI
399 }
400
401 /* OS X only */
402 OSStatus
403 SecCertificateFindByIssuerAndSN(CFTypeRef keychainOrArray,const CSSM_DATA *issuer,
404 const CSSM_DATA *serialNumber, SecCertificateRef *certificate)
405 {
406 if (issuer && serialNumber) {
407 CFRef<CFMutableDictionaryRef> query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
408 CFDictionarySetValue(query, kSecClass, kSecClassCertificate);
409 CFDictionarySetValue(query, kSecReturnRef, kCFBooleanTrue);
410 CFDictionarySetValue(query, kSecAttrNoLegacy, kCFBooleanTrue);
411
412 CFRef<CFDataRef> issuerData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8 *)issuer->Data, issuer->Length, kCFAllocatorNull);
413 CFDictionarySetValue(query, kSecAttrIssuer, issuerData);
414
415 CFRef<CFDataRef> serialNumberData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8 *)serialNumber->Data, serialNumber->Length, kCFAllocatorNull);
416 CFDictionarySetValue(query, kSecAttrSerialNumber, serialNumberData);
417
418 OSStatus status = SecItemCopyMatching(query, (CFTypeRef*)certificate);
419 if (status == errSecSuccess) {
420 return status;
421 }
422 }
423
424 BEGIN_SECAPI
425
426 StorageManager::KeychainList keychains;
427 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
428 Required(certificate) = Certificate::findByIssuerAndSN(keychains, CssmData::required(issuer), CssmData::required(serialNumber))->handle();
429
430 // convert ItemImpl-based SecCertificateRef to new-world version before returning
431 CssmData certData = Certificate::required(*certificate)->data();
432 CFRef<CFDataRef> cfData(CFDataCreate(NULL, certData.Data, certData.Length));
433 SecCertificateRef tmpRef = *certificate;
434 *certificate = SecCertificateCreateWithData(NULL, cfData);
435 CFRelease(tmpRef);
436
437 END_SECAPI
438 }
439
440 /* OS X only */
441 OSStatus
442 SecCertificateFindBySubjectKeyID(CFTypeRef keychainOrArray, const CSSM_DATA *subjectKeyID,
443 SecCertificateRef *certificate)
444 {
445 if (subjectKeyID) {
446 CFRef<CFMutableDictionaryRef> query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
447 CFDictionarySetValue(query, kSecClass, kSecClassCertificate);
448 CFDictionarySetValue(query, kSecReturnRef, kCFBooleanTrue);
449 CFDictionarySetValue(query, kSecAttrNoLegacy, kCFBooleanTrue);
450
451 CFRef<CFDataRef> subjectKeyIDData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8 *)subjectKeyID->Data, subjectKeyID->Length, kCFAllocatorNull);
452 CFDictionarySetValue(query, kSecAttrSubjectKeyID, subjectKeyIDData);
453
454 OSStatus status = SecItemCopyMatching(query, (CFTypeRef*)certificate);
455 if (status == errSecSuccess) {
456 return status;
457 }
458 }
459
460 BEGIN_SECAPI
461
462 StorageManager::KeychainList keychains;
463 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
464 Required(certificate) = Certificate::findBySubjectKeyID(keychains, CssmData::required(subjectKeyID))->handle();
465
466 // convert ItemImpl-based SecCertificateRef to new-world version before returning
467 CssmData certData = Certificate::required(*certificate)->data();
468 CFRef<CFDataRef> cfData(CFDataCreate(NULL, certData.Data, certData.Length));
469 SecCertificateRef tmpRef = *certificate;
470 *certificate = SecCertificateCreateWithData(NULL, cfData);
471 CFRelease(tmpRef);
472
473 END_SECAPI
474 }
475
476 /* OS X only */
477 OSStatus
478 SecCertificateFindByEmail(CFTypeRef keychainOrArray, const char *emailAddress, SecCertificateRef *certificate)
479 {
480 if (emailAddress) {
481 CFRef<CFMutableDictionaryRef> query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
482 CFDictionarySetValue(query, kSecClass, kSecClassCertificate);
483 CFDictionarySetValue(query, kSecReturnRef, kCFBooleanTrue);
484 CFDictionarySetValue(query, kSecAttrNoLegacy, kCFBooleanTrue);
485
486 CFRef<CFStringRef> emailAddressString = CFStringCreateWithCString(kCFAllocatorDefault, emailAddress, kCFStringEncodingUTF8);
487 CFTypeRef keys[] = { kSecPolicyName };
488 CFTypeRef values[] = { emailAddressString };
489 CFRef<CFDictionaryRef> properties = CFDictionaryCreate(kCFAllocatorDefault, keys, values, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
490 CFRef<SecPolicyRef> policy = SecPolicyCreateWithProperties(kSecPolicyAppleSMIME, properties);
491 CFDictionarySetValue(query, kSecMatchPolicy, policy);
492
493 OSStatus status = SecItemCopyMatching(query, (CFTypeRef*)certificate);
494 if (status == errSecSuccess) {
495 return status;
496 }
497 }
498
499 BEGIN_SECAPI
500
501 StorageManager::KeychainList keychains;
502 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
503 Required(certificate) = Certificate::findByEmail(keychains, emailAddress)->handle();
504
505 // convert ItemImpl-based SecCertificateRef to new-world version before returning
506 CssmData certData = Certificate::required(*certificate)->data();
507 CFRef<CFDataRef> cfData(CFDataCreate(NULL, certData.Data, certData.Length));
508 SecCertificateRef tmpRef = *certificate;
509 *certificate = SecCertificateCreateWithData(NULL, cfData);
510 CFRelease(tmpRef);
511
512 END_SECAPI
513 }
514
515 /* OS X only */
516 OSStatus
517 SecKeychainSearchCreateForCertificateByIssuerAndSN(CFTypeRef keychainOrArray, const CSSM_DATA *issuer,
518 const CSSM_DATA *serialNumber, SecKeychainSearchRef *searchRef)
519 {
520 BEGIN_SECAPI
521
522 Required(searchRef);
523
524 StorageManager::KeychainList keychains;
525 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
526 KCCursor cursor(Certificate::cursorForIssuerAndSN(keychains, CssmData::required(issuer), CssmData::required(serialNumber)));
527 *searchRef = cursor->handle();
528
529 END_SECAPI
530 }
531
532 /* OS X only */
533 OSStatus
534 SecKeychainSearchCreateForCertificateByIssuerAndSN_CF(CFTypeRef keychainOrArray, CFDataRef issuer,
535 CFDataRef serialNumber, SecKeychainSearchRef *searchRef)
536 {
537 BEGIN_SECAPI
538
539 Required(searchRef);
540
541 StorageManager::KeychainList keychains;
542 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
543 Required(issuer);
544 Required(serialNumber);
545 KCCursor cursor(Certificate::cursorForIssuerAndSN_CF(keychains, issuer, serialNumber));
546 *searchRef = cursor->handle();
547
548 END_SECAPI
549 }
550
551 /* OS X only */
552 OSStatus
553 SecKeychainSearchCreateForCertificateBySubjectKeyID(CFTypeRef keychainOrArray, const CSSM_DATA *subjectKeyID,
554 SecKeychainSearchRef *searchRef)
555 {
556 BEGIN_SECAPI
557
558 Required(searchRef);
559
560 StorageManager::KeychainList keychains;
561 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
562 KCCursor cursor(Certificate::cursorForSubjectKeyID(keychains, CssmData::required(subjectKeyID)));
563 *searchRef = cursor->handle();
564
565 END_SECAPI
566 }
567
568 /* OS X only */
569 OSStatus
570 SecKeychainSearchCreateForCertificateByEmail(CFTypeRef keychainOrArray, const char *emailAddress,
571 SecKeychainSearchRef *searchRef)
572 {
573 BEGIN_SECAPI
574
575 Required(searchRef);
576
577 StorageManager::KeychainList keychains;
578 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
579 KCCursor cursor(Certificate::cursorForEmail(keychains, emailAddress));
580 *searchRef = cursor->handle();
581
582 END_SECAPI
583 }
584
585 /* OS X only */
586 CSSM_RETURN
587 SecDigestGetData (CSSM_ALGORITHMS alg, CSSM_DATA* digest, const CSSM_DATA* data)
588 {
589 BEGIN_SECAPI
590 // sanity checking
591 if (!digest || !digest->Data || !digest->Length || !data || !data->Data || !data->Length)
592 return errSecParam;
593
594 CSP csp(gGuidAppleCSP);
595 Digest context(csp, alg);
596 CssmData input(data->Data, data->Length);
597 CssmData output(digest->Data, digest->Length);
598
599 context.digest(input, output);
600 digest->Length = output.length();
601
602 return CSSM_OK;
603 END_SECAPI1(1);
604 }
605
606 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
607 OSStatus
608 SecCertificateCopyPreference(
609 CFStringRef name,
610 CSSM_KEYUSE keyUsage,
611 SecCertificateRef *certificate)
612 {
613 BEGIN_SECAPI
614
615 Required(name);
616 Required(certificate);
617 StorageManager::KeychainList keychains;
618 globals().storageManager.getSearchList(keychains);
619 KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL);
620
621 char idUTF8[MAXPATHLEN];
622 if (!CFStringGetCString(name, idUTF8, sizeof(idUTF8)-1, kCFStringEncodingUTF8))
623 idUTF8[0] = (char)'\0';
624 CssmData service(const_cast<char *>(idUTF8), strlen(idUTF8));
625 FourCharCode itemType = 'cprf';
626 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service);
627 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), itemType);
628 if (keyUsage)
629 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage);
630
631 Item prefItem;
632 if (!cursor->next(prefItem))
633 MacOSError::throwMe(errSecItemNotFound);
634
635 // get persistent certificate reference
636 SecKeychainAttribute itemAttrs[] = { { kSecGenericItemAttr, 0, NULL } };
637 SecKeychainAttributeList itemAttrList = { sizeof(itemAttrs) / sizeof(itemAttrs[0]), itemAttrs };
638 prefItem->getContent(NULL, &itemAttrList, NULL, NULL);
639
640 // find certificate, given persistent reference data
641 CFDataRef pItemRef = CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)itemAttrs[0].data, itemAttrs[0].length, kCFAllocatorNull);
642 SecKeychainItemRef certItemRef = nil;
643 OSStatus status = SecKeychainItemCopyFromPersistentReference(pItemRef, &certItemRef); //%%% need to make this a method of ItemImpl
644 prefItem->freeContent(&itemAttrList, NULL);
645 if (pItemRef)
646 CFRelease(pItemRef);
647 if (status)
648 return status;
649
650 *certificate = (SecCertificateRef)certItemRef;
651
652 if (certItemRef && (CFGetTypeID(certItemRef) == SecIdentityGetTypeID())) {
653 // SecKeychainItemCopyFromPersistentReference handed out an identity reference
654 *certificate = NULL;
655 status = SecIdentityCopyCertificate((SecIdentityRef)certItemRef, certificate);
656 CFRelease(certItemRef);
657 return status;
658 }
659
660 END_SECAPI
661 }
662
663 /* OS X only */
664 SecCertificateRef
665 SecCertificateCopyPreferred(
666 CFStringRef name,
667 CFArrayRef keyUsage)
668 {
669 // This function will look for a matching preference in the following order:
670 // - matches the name and the supplied key use
671 // - matches the name and the special 'ANY' key use
672 // - matches the name with no key usage constraint
673
674 SecCertificateRef certRef = NULL;
675 CSSM_KEYUSE keyUse = ConvertArrayToKeyUsage(keyUsage);
676 OSStatus status = SecCertificateCopyPreference(name, keyUse, &certRef);
677 if (status != errSecSuccess && keyUse != CSSM_KEYUSE_ANY)
678 status = SecCertificateCopyPreference(name, CSSM_KEYUSE_ANY, &certRef);
679 if (status != errSecSuccess && keyUse != 0)
680 status = SecCertificateCopyPreference(name, 0, &certRef);
681
682 return certRef;
683 }
684
685 /* OS X only; not exported */
686 static OSStatus
687 SecCertificateFindPreferenceItemWithNameAndKeyUsage(
688 CFTypeRef keychainOrArray,
689 CFStringRef name,
690 int32_t keyUsage,
691 SecKeychainItemRef *itemRef)
692 {
693 BEGIN_SECAPI
694
695 StorageManager::KeychainList keychains;
696 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
697 KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL);
698
699 char idUTF8[MAXPATHLEN];
700 idUTF8[0] = (char)'\0';
701 if (name)
702 {
703 if (!CFStringGetCString(name, idUTF8, sizeof(idUTF8)-1, kCFStringEncodingUTF8))
704 idUTF8[0] = (char)'\0';
705 }
706 size_t idUTF8Len = strlen(idUTF8);
707 if (!idUTF8Len)
708 MacOSError::throwMe(errSecParam);
709
710 CssmData service(const_cast<char *>(idUTF8), idUTF8Len);
711 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service);
712 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), (FourCharCode)'cprf');
713 if (keyUsage)
714 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage);
715
716 Item item;
717 if (!cursor->next(item))
718 MacOSError::throwMe(errSecItemNotFound);
719
720 if (itemRef)
721 *itemRef=item->handle();
722
723 END_SECAPI
724 }
725
726 /* OS X only; not exported */
727 static
728 OSStatus SecCertificateDeletePreferenceItemWithNameAndKeyUsage(
729 CFTypeRef keychainOrArray,
730 CFStringRef name,
731 int32_t keyUsage)
732 {
733 // when a specific key usage is passed, we'll only match & delete that pref;
734 // when a key usage of 0 is passed, all matching prefs should be deleted.
735 // maxUsages represents the most matches there could theoretically be, so
736 // cut things off at that point if we're still finding items (if they can't
737 // be deleted for some reason, we'd never break out of the loop.)
738
739 OSStatus status = errSecSuccess;
740 SecKeychainItemRef item = NULL;
741 int count = 0, maxUsages = 12;
742 while (++count <= maxUsages &&
743 (status = SecCertificateFindPreferenceItemWithNameAndKeyUsage(keychainOrArray, name, keyUsage, &item)) == errSecSuccess) {
744 status = SecKeychainItemDelete(item);
745 CFRelease(item);
746 item = NULL;
747 }
748
749 // it's not an error if the item isn't found
750 return (status == errSecItemNotFound) ? errSecSuccess : status;
751 }
752
753 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA) */
754 OSStatus SecCertificateSetPreference(
755 SecCertificateRef certificate,
756 CFStringRef name,
757 CSSM_KEYUSE keyUsage,
758 CFDateRef date)
759 {
760 if (!name) {
761 return errSecParam;
762 }
763 if (!certificate) {
764 // treat NULL certificate as a request to clear the preference
765 // (note: if keyUsage is 0, this clears all key usage prefs for name)
766 return SecCertificateDeletePreferenceItemWithNameAndKeyUsage(NULL, name, keyUsage);
767 }
768
769 // This macro creates an ItemImpl certificate if it does not exist
770 BEGIN_SECCERTAPI
771
772 // determine the account attribute
773 //
774 // This attribute must be synthesized from certificate label + pref item type + key usage,
775 // as only the account and service attributes can make a generic keychain item unique.
776 // For 'iprf' type items (but not 'cprf'), we append a trailing space. This insures that
777 // we can save a certificate preference if an identity preference already exists for the
778 // given service name, and vice-versa.
779 // If the key usage is 0 (i.e. the normal case), we omit the appended key usage string.
780 //
781 CFStringRef labelStr = nil;
782 Certificate::required(__itemImplRef)->inferLabel(false, &labelStr);
783 if (!labelStr) {
784 MacOSError::throwMe(errSecDataTooLarge); // data is "in a format which cannot be displayed"
785 }
786 CFIndex accountUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(labelStr), kCFStringEncodingUTF8) + 1;
787 const char *templateStr = "%s [key usage 0x%X]";
788 const int keyUsageMaxStrLen = 8;
789 accountUTF8Len += strlen(templateStr) + keyUsageMaxStrLen;
790 char *accountUTF8 = (char *)malloc(accountUTF8Len);
791 if (!accountUTF8) {
792 MacOSError::throwMe(errSecMemoryError);
793 }
794 if (!CFStringGetCString(labelStr, accountUTF8, accountUTF8Len-1, kCFStringEncodingUTF8))
795 accountUTF8[0] = (char)'\0';
796 if (keyUsage)
797 snprintf(accountUTF8, accountUTF8Len-1, templateStr, accountUTF8, keyUsage);
798 CssmDataContainer account(const_cast<char *>(accountUTF8), strlen(accountUTF8));
799 free(accountUTF8);
800 CFRelease(labelStr);
801
802 // service attribute (name provided by the caller)
803 CFIndex serviceUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(name), kCFStringEncodingUTF8) + 1;;
804 char *serviceUTF8 = (char *)malloc(serviceUTF8Len);
805 if (!serviceUTF8) {
806 MacOSError::throwMe(errSecMemoryError);
807 }
808 if (!CFStringGetCString(name, serviceUTF8, serviceUTF8Len-1, kCFStringEncodingUTF8))
809 serviceUTF8[0] = (char)'\0';
810 CssmDataContainer service(const_cast<char *>(serviceUTF8), strlen(serviceUTF8));
811 free(serviceUTF8);
812
813 // look for existing preference item, in case this is an update
814 StorageManager::KeychainList keychains;
815 globals().storageManager.getSearchList(keychains);
816 KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL);
817 FourCharCode itemType = 'cprf';
818 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service);
819 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), itemType);
820 if (keyUsage)
821 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage);
822 if (date)
823 ; // %%%TBI
824
825 Item item(kSecGenericPasswordItemClass, 'aapl', 0, NULL, false);
826 bool add = (!cursor->next(item));
827 // at this point, we either have a new item to add or an existing item to update
828
829 // set item attribute values
830 item->setAttribute(Schema::attributeInfo(kSecServiceItemAttr), service);
831 item->setAttribute(Schema::attributeInfo(kSecTypeItemAttr), itemType);
832 item->setAttribute(Schema::attributeInfo(kSecAccountItemAttr), account);
833 item->setAttribute(Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage);
834 item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), service);
835
836 // date
837 if (date)
838 ; // %%%TBI
839
840 // generic attribute (store persistent certificate reference)
841 CFDataRef pItemRef = nil;
842 Certificate::required(__itemImplRef)->copyPersistentReference(pItemRef);
843 if (!pItemRef) {
844 MacOSError::throwMe(errSecInvalidItemRef);
845 }
846 const UInt8 *dataPtr = CFDataGetBytePtr(pItemRef);
847 CFIndex dataLen = CFDataGetLength(pItemRef);
848 CssmData pref(const_cast<void *>(reinterpret_cast<const void *>(dataPtr)), dataLen);
849 item->setAttribute(Schema::attributeInfo(kSecGenericItemAttr), pref);
850 CFRelease(pItemRef);
851
852 if (add) {
853 Keychain keychain = nil;
854 try {
855 keychain = globals().storageManager.defaultKeychain();
856 if (!keychain->exists())
857 MacOSError::throwMe(errSecNoSuchKeychain); // Might be deleted or not available at this time.
858 }
859 catch(...) {
860 keychain = globals().storageManager.defaultKeychainUI(item);
861 }
862
863 try {
864 keychain->add(item);
865 }
866 catch (const MacOSError &err) {
867 if (err.osStatus() != errSecDuplicateItem)
868 throw; // if item already exists, fall through to update
869 }
870 }
871 item->update();
872
873 END_SECCERTAPI
874 }
875
876 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
877 OSStatus SecCertificateSetPreferred(
878 SecCertificateRef certificate,
879 CFStringRef name,
880 CFArrayRef keyUsage)
881 {
882 CSSM_KEYUSE keyUse = ConvertArrayToKeyUsage(keyUsage);
883 return SecCertificateSetPreference(certificate, name, keyUse, NULL);
884 }
885
886 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
887 CFDictionaryRef SecCertificateCopyValues(SecCertificateRef certificate, CFArrayRef keys, CFErrorRef *error)
888 {
889 CFDictionaryRef result = NULL;
890 OSStatus __secapiresult;
891 SecCertificateRef tmpcert = NULL;
892
893 // convert input to a new-style certificate reference if necessary,
894 // since the implementation of CertificateValues calls SecCertificate API functions
895 // which now assume a unified certificate reference.
896 if (SecCertificateIsItemImplInstance(certificate)) {
897 tmpcert = SecCertificateCreateFromItemImplInstance(certificate);
898 }
899 if (certificate && !tmpcert) {
900 tmpcert = (SecCertificateRef) CFRetain(certificate);
901 }
902 try
903 {
904 CertificateValues cv(tmpcert);
905 result = cv.copyFieldValues(keys,error);
906 __secapiresult=0;
907 }
908 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
909 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
910 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
911 catch (...) { __secapiresult=errSecInternalComponent; }
912 if (tmpcert) { CFRelease(tmpcert); }
913 return result;
914 }
915
916 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
917 CFStringRef SecCertificateCopyLongDescription(CFAllocatorRef alloc, SecCertificateRef certificate, CFErrorRef *error)
918 {
919 return SecCertificateCopyShortDescription(alloc, certificate, error);
920 }
921
922 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
923 CFStringRef SecCertificateCopyShortDescription(CFAllocatorRef alloc, SecCertificateRef certificate, CFErrorRef *error)
924 {
925 CFStringRef result = NULL;
926 OSStatus __secapiresult = SecCertificateInferLabel(certificate, &result);
927 if (error!=NULL && __secapiresult!=errSecSuccess)
928 {
929 *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainOSStatus,
930 __secapiresult ? __secapiresult : CSSM_ERRCODE_INTERNAL_ERROR, NULL);
931 }
932 return result;
933 }
934
935 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
936 CFDataRef SecCertificateCopySerialNumber(SecCertificateRef certificate, CFErrorRef *error)
937 {
938 CFDataRef result = NULL;
939 OSStatus __secapiresult;
940 try
941 {
942 CertificateValues cv(certificate);
943 result = cv.copySerialNumber(error);
944 __secapiresult=0;
945 }
946 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
947 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
948 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
949 catch (...) { __secapiresult=errSecInternalComponent; }
950 return result;
951 }
952
953 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_12_4, __IPHONE_NA, __IPHONE_NA) */
954 CFDataRef SecCertificateCopyNormalizedIssuerContent(SecCertificateRef certificate, CFErrorRef *error)
955 {
956 CFDataRef result = NULL;
957 OSStatus __secapiresult;
958 try
959 {
960 CertificateValues cv(certificate);
961 result = cv.copyNormalizedIssuerContent(error);
962 __secapiresult=0;
963 }
964 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
965 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
966 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
967 catch (...) { __secapiresult=errSecInternalComponent; }
968 return result;
969 }
970
971 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_12_4, __IPHONE_NA, __IPHONE_NA) */
972 CFDataRef SecCertificateCopyNormalizedSubjectContent(SecCertificateRef certificate, CFErrorRef *error)
973 {
974 CFDataRef result = NULL;
975 OSStatus __secapiresult;
976 try
977 {
978 CertificateValues cv(certificate);
979 result = cv.copyNormalizedSubjectContent(error);
980 __secapiresult=0;
981 }
982 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
983 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
984 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
985 catch (...) { __secapiresult=errSecInternalComponent; }
986 return result;
987 }
988
989 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_9, __IPHONE_NA, __IPHONE_NA) */
990 bool SecCertificateIsValidX(SecCertificateRef certificate, CFAbsoluteTime verifyTime)
991 {
992 /*
993 * deprecated function name
994 */
995 return SecCertificateIsValid(certificate, verifyTime);
996 }
997
998 /* OS X only */
999 CFDataRef SecCertificateCopyPublicKeySHA1DigestFromCertificateData(CFAllocatorRef allocator,
1000 CFDataRef der_certificate)
1001 {
1002 CFDataRef result = NULL;
1003 SecCertificateRef iosCertRef = SecCertificateCreateWithData(allocator, der_certificate);
1004 if (NULL == iosCertRef)
1005 {
1006 return result;
1007 }
1008
1009 result = SecCertificateCopyPublicKeySHA1Digest(iosCertRef);
1010 CFRelease(iosCertRef);
1011 return result;
1012 }
1013