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