]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_keychain/lib/SecCertificate.cpp
a9b145d48ba6455a5735ff23d3b5ce35126ad358
[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 /* Return a zero terminated list of CSSM_DATA_PTR's with the values of the field specified by field.
356 * Caller must call releaseFieldValues to free the storage allocated by this call.
357 *
358 * OS X only
359 */
360 OSStatus
361 SecCertificateCopyFieldValues(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR **fieldValues)
362 {
363 // This macro creates an ItemImpl certificate if it does not exist
364 BEGIN_SECCERTAPI
365
366 Required(fieldValues) = Certificate::required(__itemImplRef)->copyFieldValues(Required(field));
367
368 END_SECCERTAPI
369 }
370
371 /* OS X only */
372 OSStatus
373 SecCertificateReleaseFieldValues(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 Certificate::required(__itemImplRef)->releaseFieldValues(Required(field), fieldValues);
379
380 END_SECCERTAPI
381 }
382
383 /* OS X only */
384 OSStatus
385 SecCertificateCopyFirstFieldValue(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR *fieldValue)
386 {
387 // This macro creates an ItemImpl certificate if it does not exist
388 BEGIN_SECCERTAPI
389
390 Required(fieldValue) = Certificate::required(__itemImplRef)->copyFirstFieldValue(Required(field));
391
392 END_SECCERTAPI
393 }
394
395 /* OS X only */
396 OSStatus
397 SecCertificateReleaseFirstFieldValue(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 Certificate::required(__itemImplRef)->releaseFieldValue(Required(field), fieldValue);
403
404 END_SECCERTAPI
405 }
406
407 /* OS X only */
408 OSStatus
409 SecCertificateFindByIssuerAndSN(CFTypeRef keychainOrArray,const CSSM_DATA *issuer,
410 const CSSM_DATA *serialNumber, SecCertificateRef *certificate)
411 {
412 if (issuer && serialNumber) {
413 CFRef<CFMutableDictionaryRef> query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
414 CFDictionarySetValue(query, kSecClass, kSecClassCertificate);
415 CFDictionarySetValue(query, kSecReturnRef, kCFBooleanTrue);
416 CFDictionarySetValue(query, kSecAttrNoLegacy, kCFBooleanTrue);
417
418 CFRef<CFDataRef> issuerData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8 *)issuer->Data, issuer->Length, kCFAllocatorNull);
419 CFDictionarySetValue(query, kSecAttrIssuer, issuerData);
420
421 CFRef<CFDataRef> serialNumberData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8 *)serialNumber->Data, serialNumber->Length, kCFAllocatorNull);
422 CFDictionarySetValue(query, kSecAttrSerialNumber, serialNumberData);
423
424 OSStatus status = SecItemCopyMatching(query, (CFTypeRef*)certificate);
425 if (status == errSecSuccess) {
426 return status;
427 }
428 }
429
430 BEGIN_SECAPI
431
432 StorageManager::KeychainList keychains;
433 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
434 Required(certificate) = Certificate::findByIssuerAndSN(keychains, CssmData::required(issuer), CssmData::required(serialNumber))->handle();
435
436 // convert ItemImpl-based SecCertificateRef to new-world version before returning
437 CssmData certData = Certificate::required(*certificate)->data();
438 CFRef<CFDataRef> cfData(CFDataCreate(NULL, certData.Data, certData.Length));
439 SecCertificateRef tmpRef = *certificate;
440 *certificate = SecCertificateCreateWithData(NULL, cfData);
441 CFRelease(tmpRef);
442
443 END_SECAPI
444 }
445
446 /* OS X only */
447 OSStatus
448 SecCertificateFindBySubjectKeyID(CFTypeRef keychainOrArray, const CSSM_DATA *subjectKeyID,
449 SecCertificateRef *certificate)
450 {
451 if (subjectKeyID) {
452 CFRef<CFMutableDictionaryRef> query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
453 CFDictionarySetValue(query, kSecClass, kSecClassCertificate);
454 CFDictionarySetValue(query, kSecReturnRef, kCFBooleanTrue);
455 CFDictionarySetValue(query, kSecAttrNoLegacy, kCFBooleanTrue);
456
457 CFRef<CFDataRef> subjectKeyIDData = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, (const UInt8 *)subjectKeyID->Data, subjectKeyID->Length, kCFAllocatorNull);
458 CFDictionarySetValue(query, kSecAttrSubjectKeyID, subjectKeyIDData);
459
460 OSStatus status = SecItemCopyMatching(query, (CFTypeRef*)certificate);
461 if (status == errSecSuccess) {
462 return status;
463 }
464 }
465
466 BEGIN_SECAPI
467
468 StorageManager::KeychainList keychains;
469 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
470 Required(certificate) = Certificate::findBySubjectKeyID(keychains, CssmData::required(subjectKeyID))->handle();
471
472 // convert ItemImpl-based SecCertificateRef to new-world version before returning
473 CssmData certData = Certificate::required(*certificate)->data();
474 CFRef<CFDataRef> cfData(CFDataCreate(NULL, certData.Data, certData.Length));
475 SecCertificateRef tmpRef = *certificate;
476 *certificate = SecCertificateCreateWithData(NULL, cfData);
477 CFRelease(tmpRef);
478
479 END_SECAPI
480 }
481
482 /* OS X only */
483 OSStatus
484 SecCertificateFindByEmail(CFTypeRef keychainOrArray, const char *emailAddress, SecCertificateRef *certificate)
485 {
486 if (emailAddress) {
487 CFRef<CFMutableDictionaryRef> query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
488 CFDictionarySetValue(query, kSecClass, kSecClassCertificate);
489 CFDictionarySetValue(query, kSecReturnRef, kCFBooleanTrue);
490 CFDictionarySetValue(query, kSecAttrNoLegacy, kCFBooleanTrue);
491
492 CFRef<CFStringRef> emailAddressString = CFStringCreateWithCString(kCFAllocatorDefault, emailAddress, kCFStringEncodingUTF8);
493 CFTypeRef keys[] = { kSecPolicyName };
494 CFTypeRef values[] = { emailAddressString };
495 CFRef<CFDictionaryRef> properties = CFDictionaryCreate(kCFAllocatorDefault, keys, values, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
496 CFRef<SecPolicyRef> policy = SecPolicyCreateWithProperties(kSecPolicyAppleSMIME, properties);
497 CFDictionarySetValue(query, kSecMatchPolicy, policy);
498
499 OSStatus status = SecItemCopyMatching(query, (CFTypeRef*)certificate);
500 if (status == errSecSuccess) {
501 return status;
502 }
503 }
504
505 BEGIN_SECAPI
506
507 StorageManager::KeychainList keychains;
508 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
509 Required(certificate) = Certificate::findByEmail(keychains, emailAddress)->handle();
510
511 // convert ItemImpl-based SecCertificateRef to new-world version before returning
512 CssmData certData = Certificate::required(*certificate)->data();
513 CFRef<CFDataRef> cfData(CFDataCreate(NULL, certData.Data, certData.Length));
514 SecCertificateRef tmpRef = *certificate;
515 *certificate = SecCertificateCreateWithData(NULL, cfData);
516 CFRelease(tmpRef);
517
518 END_SECAPI
519 }
520
521 /* OS X only */
522 OSStatus
523 SecKeychainSearchCreateForCertificateByIssuerAndSN(CFTypeRef keychainOrArray, const CSSM_DATA *issuer,
524 const CSSM_DATA *serialNumber, SecKeychainSearchRef *searchRef)
525 {
526 BEGIN_SECAPI
527
528 Required(searchRef);
529
530 StorageManager::KeychainList keychains;
531 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
532 KCCursor cursor(Certificate::cursorForIssuerAndSN(keychains, CssmData::required(issuer), CssmData::required(serialNumber)));
533 *searchRef = cursor->handle();
534
535 END_SECAPI
536 }
537
538 /* OS X only */
539 OSStatus
540 SecKeychainSearchCreateForCertificateByIssuerAndSN_CF(CFTypeRef keychainOrArray, CFDataRef issuer,
541 CFDataRef serialNumber, SecKeychainSearchRef *searchRef)
542 {
543 BEGIN_SECAPI
544
545 Required(searchRef);
546
547 StorageManager::KeychainList keychains;
548 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
549 Required(issuer);
550 Required(serialNumber);
551 KCCursor cursor(Certificate::cursorForIssuerAndSN_CF(keychains, issuer, serialNumber));
552 *searchRef = cursor->handle();
553
554 END_SECAPI
555 }
556
557 /* OS X only */
558 OSStatus
559 SecKeychainSearchCreateForCertificateBySubjectKeyID(CFTypeRef keychainOrArray, const CSSM_DATA *subjectKeyID,
560 SecKeychainSearchRef *searchRef)
561 {
562 BEGIN_SECAPI
563
564 Required(searchRef);
565
566 StorageManager::KeychainList keychains;
567 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
568 KCCursor cursor(Certificate::cursorForSubjectKeyID(keychains, CssmData::required(subjectKeyID)));
569 *searchRef = cursor->handle();
570
571 END_SECAPI
572 }
573
574 /* OS X only */
575 OSStatus
576 SecKeychainSearchCreateForCertificateByEmail(CFTypeRef keychainOrArray, const char *emailAddress,
577 SecKeychainSearchRef *searchRef)
578 {
579 BEGIN_SECAPI
580
581 Required(searchRef);
582
583 StorageManager::KeychainList keychains;
584 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
585 KCCursor cursor(Certificate::cursorForEmail(keychains, emailAddress));
586 *searchRef = cursor->handle();
587
588 END_SECAPI
589 }
590
591 /* OS X only */
592 CSSM_RETURN
593 SecDigestGetData (CSSM_ALGORITHMS alg, CSSM_DATA* digest, const CSSM_DATA* data)
594 {
595 BEGIN_SECAPI
596 // sanity checking
597 if (!digest || !digest->Data || !digest->Length || !data || !data->Data || !data->Length)
598 return errSecParam;
599
600 CSP csp(gGuidAppleCSP);
601 Digest context(csp, alg);
602 CssmData input(data->Data, data->Length);
603 CssmData output(digest->Data, digest->Length);
604
605 context.digest(input, output);
606 digest->Length = output.length();
607
608 return CSSM_OK;
609 END_SECAPI1(1);
610 }
611
612 /* OS X only: DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER */
613 OSStatus
614 SecCertificateCopyPreference(
615 CFStringRef name,
616 CSSM_KEYUSE keyUsage,
617 SecCertificateRef *certificate)
618 {
619 BEGIN_SECAPI
620
621 Required(name);
622 Required(certificate);
623 StorageManager::KeychainList keychains;
624 globals().storageManager.getSearchList(keychains);
625 KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL);
626
627 char idUTF8[MAXPATHLEN];
628 if (!CFStringGetCString(name, idUTF8, sizeof(idUTF8)-1, kCFStringEncodingUTF8))
629 idUTF8[0] = (char)'\0';
630 CssmData service(const_cast<char *>(idUTF8), strlen(idUTF8));
631 FourCharCode itemType = 'cprf';
632 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service);
633 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), itemType);
634 if (keyUsage)
635 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage);
636
637 Item prefItem;
638 if (!cursor->next(prefItem))
639 MacOSError::throwMe(errSecItemNotFound);
640
641 // get persistent certificate reference
642 SecKeychainAttribute itemAttrs[] = { { kSecGenericItemAttr, 0, NULL } };
643 SecKeychainAttributeList itemAttrList = { sizeof(itemAttrs) / sizeof(itemAttrs[0]), itemAttrs };
644 prefItem->getContent(NULL, &itemAttrList, NULL, NULL);
645
646 // find certificate, given persistent reference data
647 CFDataRef pItemRef = CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)itemAttrs[0].data, itemAttrs[0].length, kCFAllocatorNull);
648 SecKeychainItemRef certItemRef = nil;
649 OSStatus status = SecKeychainItemCopyFromPersistentReference(pItemRef, &certItemRef); //%%% need to make this a method of ItemImpl
650 prefItem->freeContent(&itemAttrList, NULL);
651 if (pItemRef)
652 CFRelease(pItemRef);
653 if (status)
654 return status;
655
656 *certificate = (SecCertificateRef)certItemRef;
657
658 if (certItemRef && (CFGetTypeID(certItemRef) == SecIdentityGetTypeID())) {
659 // SecKeychainItemCopyFromPersistentReference handed out an identity reference
660 *certificate = NULL;
661 status = SecIdentityCopyCertificate((SecIdentityRef)certItemRef, certificate);
662 CFRelease(certItemRef);
663 return status;
664 }
665
666 END_SECAPI
667 }
668
669 /* OS X only */
670 SecCertificateRef
671 SecCertificateCopyPreferred(
672 CFStringRef name,
673 CFArrayRef keyUsage)
674 {
675 // This function will look for a matching preference in the following order:
676 // - matches the name and the supplied key use
677 // - matches the name and the special 'ANY' key use
678 // - matches the name with no key usage constraint
679
680 SecCertificateRef certRef = NULL;
681 CSSM_KEYUSE keyUse = ConvertArrayToKeyUsage(keyUsage);
682 OSStatus status = SecCertificateCopyPreference(name, keyUse, &certRef);
683 if (status != errSecSuccess && keyUse != CSSM_KEYUSE_ANY)
684 status = SecCertificateCopyPreference(name, CSSM_KEYUSE_ANY, &certRef);
685 if (status != errSecSuccess && keyUse != 0)
686 status = SecCertificateCopyPreference(name, 0, &certRef);
687
688 return certRef;
689 }
690
691 /* OS X only; not exported */
692 static OSStatus
693 SecCertificateFindPreferenceItemWithNameAndKeyUsage(
694 CFTypeRef keychainOrArray,
695 CFStringRef name,
696 int32_t keyUsage,
697 SecKeychainItemRef *itemRef)
698 {
699 BEGIN_SECAPI
700
701 StorageManager::KeychainList keychains;
702 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
703 KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL);
704
705 char idUTF8[MAXPATHLEN];
706 idUTF8[0] = (char)'\0';
707 if (name)
708 {
709 if (!CFStringGetCString(name, idUTF8, sizeof(idUTF8)-1, kCFStringEncodingUTF8))
710 idUTF8[0] = (char)'\0';
711 }
712 size_t idUTF8Len = strlen(idUTF8);
713 if (!idUTF8Len)
714 MacOSError::throwMe(errSecParam);
715
716 CssmData service(const_cast<char *>(idUTF8), idUTF8Len);
717 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service);
718 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), (FourCharCode)'cprf');
719 if (keyUsage)
720 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage);
721
722 Item item;
723 if (!cursor->next(item))
724 MacOSError::throwMe(errSecItemNotFound);
725
726 if (itemRef)
727 *itemRef=item->handle();
728
729 END_SECAPI
730 }
731
732 /* OS X only; not exported */
733 static
734 OSStatus SecCertificateDeletePreferenceItemWithNameAndKeyUsage(
735 CFTypeRef keychainOrArray,
736 CFStringRef name,
737 int32_t keyUsage)
738 {
739 // when a specific key usage is passed, we'll only match & delete that pref;
740 // when a key usage of 0 is passed, all matching prefs should be deleted.
741 // maxUsages represents the most matches there could theoretically be, so
742 // cut things off at that point if we're still finding items (if they can't
743 // be deleted for some reason, we'd never break out of the loop.)
744
745 OSStatus status = errSecSuccess;
746 SecKeychainItemRef item = NULL;
747 int count = 0, maxUsages = 12;
748 while (++count <= maxUsages &&
749 (status = SecCertificateFindPreferenceItemWithNameAndKeyUsage(keychainOrArray, name, keyUsage, &item)) == errSecSuccess) {
750 status = SecKeychainItemDelete(item);
751 CFRelease(item);
752 item = NULL;
753 }
754
755 // it's not an error if the item isn't found
756 return (status == errSecItemNotFound) ? errSecSuccess : status;
757 }
758
759 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_5, __IPHONE_NA) */
760 OSStatus SecCertificateSetPreference(
761 SecCertificateRef certificate,
762 CFStringRef name,
763 CSSM_KEYUSE keyUsage,
764 CFDateRef date)
765 {
766 if (!name) {
767 return errSecParam;
768 }
769 if (!certificate) {
770 // treat NULL certificate as a request to clear the preference
771 // (note: if keyUsage is 0, this clears all key usage prefs for name)
772 return SecCertificateDeletePreferenceItemWithNameAndKeyUsage(NULL, name, keyUsage);
773 }
774
775 // This macro creates an ItemImpl certificate if it does not exist
776 BEGIN_SECCERTAPI
777
778 // determine the account attribute
779 //
780 // This attribute must be synthesized from certificate label + pref item type + key usage,
781 // as only the account and service attributes can make a generic keychain item unique.
782 // For 'iprf' type items (but not 'cprf'), we append a trailing space. This insures that
783 // we can save a certificate preference if an identity preference already exists for the
784 // given service name, and vice-versa.
785 // If the key usage is 0 (i.e. the normal case), we omit the appended key usage string.
786 //
787 CFStringRef labelStr = nil;
788 Certificate::required(__itemImplRef)->inferLabel(false, &labelStr);
789 if (!labelStr) {
790 MacOSError::throwMe(errSecDataTooLarge); // data is "in a format which cannot be displayed"
791 }
792 CFIndex accountUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(labelStr), kCFStringEncodingUTF8) + 1;
793 const char *templateStr = "%s [key usage 0x%X]";
794 const int keyUsageMaxStrLen = 8;
795 accountUTF8Len += strlen(templateStr) + keyUsageMaxStrLen;
796 char accountUTF8[accountUTF8Len];
797 if (!CFStringGetCString(labelStr, accountUTF8, accountUTF8Len-1, kCFStringEncodingUTF8))
798 accountUTF8[0] = (char)'\0';
799 if (keyUsage)
800 snprintf(accountUTF8, accountUTF8Len-1, templateStr, accountUTF8, keyUsage);
801 CssmData account(const_cast<char *>(accountUTF8), strlen(accountUTF8));
802 CFRelease(labelStr);
803
804 // service attribute (name provided by the caller)
805 CFIndex serviceUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(name), kCFStringEncodingUTF8) + 1;;
806 char serviceUTF8[serviceUTF8Len];
807 if (!CFStringGetCString(name, serviceUTF8, serviceUTF8Len-1, kCFStringEncodingUTF8))
808 serviceUTF8[0] = (char)'\0';
809 CssmData service(const_cast<char *>(serviceUTF8), strlen(serviceUTF8));
810
811 // look for existing preference item, in case this is an update
812 StorageManager::KeychainList keychains;
813 globals().storageManager.getSearchList(keychains);
814 KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL);
815 FourCharCode itemType = 'cprf';
816 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service);
817 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), itemType);
818 if (keyUsage)
819 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage);
820 if (date)
821 ; // %%%TBI
822
823 Item item(kSecGenericPasswordItemClass, 'aapl', 0, NULL, false);
824 bool add = (!cursor->next(item));
825 // at this point, we either have a new item to add or an existing item to update
826
827 // set item attribute values
828 item->setAttribute(Schema::attributeInfo(kSecServiceItemAttr), service);
829 item->setAttribute(Schema::attributeInfo(kSecTypeItemAttr), itemType);
830 item->setAttribute(Schema::attributeInfo(kSecAccountItemAttr), account);
831 item->setAttribute(Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage);
832 item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), service);
833
834 // date
835 if (date)
836 ; // %%%TBI
837
838 // generic attribute (store persistent certificate reference)
839 CFDataRef pItemRef = nil;
840 Certificate::required(__itemImplRef)->copyPersistentReference(pItemRef);
841 if (!pItemRef) {
842 MacOSError::throwMe(errSecInvalidItemRef);
843 }
844 const UInt8 *dataPtr = CFDataGetBytePtr(pItemRef);
845 CFIndex dataLen = CFDataGetLength(pItemRef);
846 CssmData pref(const_cast<void *>(reinterpret_cast<const void *>(dataPtr)), dataLen);
847 item->setAttribute(Schema::attributeInfo(kSecGenericItemAttr), pref);
848 CFRelease(pItemRef);
849
850 if (add) {
851 Keychain keychain = nil;
852 try {
853 keychain = globals().storageManager.defaultKeychain();
854 if (!keychain->exists())
855 MacOSError::throwMe(errSecNoSuchKeychain); // Might be deleted or not available at this time.
856 }
857 catch(...) {
858 keychain = globals().storageManager.defaultKeychainUI(item);
859 }
860
861 try {
862 keychain->add(item);
863 }
864 catch (const MacOSError &err) {
865 if (err.osStatus() != errSecDuplicateItem)
866 throw; // if item already exists, fall through to update
867 }
868 }
869 item->update();
870
871 END_SECCERTAPI
872 }
873
874 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
875 OSStatus SecCertificateSetPreferred(
876 SecCertificateRef certificate,
877 CFStringRef name,
878 CFArrayRef keyUsage)
879 {
880 CSSM_KEYUSE keyUse = ConvertArrayToKeyUsage(keyUsage);
881 return SecCertificateSetPreference(certificate, name, keyUse, NULL);
882 }
883
884 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
885 CFDictionaryRef SecCertificateCopyValues(SecCertificateRef certificate, CFArrayRef keys, CFErrorRef *error)
886 {
887 CFDictionaryRef result = NULL;
888 OSStatus __secapiresult;
889 SecCertificateRef tmpcert = NULL;
890
891 // convert input to a new-style certificate reference if necessary,
892 // since the implementation of CertificateValues calls SecCertificate API functions
893 // which now assume a unified certificate reference.
894 if (SecCertificateIsItemImplInstance(certificate)) {
895 tmpcert = SecCertificateCreateFromItemImplInstance(certificate);
896 }
897 if (certificate && !tmpcert) {
898 tmpcert = (SecCertificateRef) CFRetain(certificate);
899 }
900 try
901 {
902 CertificateValues cv(tmpcert);
903 result = cv.copyFieldValues(keys,error);
904 __secapiresult=0;
905 }
906 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
907 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
908 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
909 catch (...) { __secapiresult=errSecInternalComponent; }
910 if (tmpcert) { CFRelease(tmpcert); }
911 return result;
912 }
913
914 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
915 CFStringRef SecCertificateCopyLongDescription(CFAllocatorRef alloc, SecCertificateRef certificate, CFErrorRef *error)
916 {
917 return SecCertificateCopyShortDescription(alloc, certificate, error);
918 }
919
920 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
921 CFStringRef SecCertificateCopyShortDescription(CFAllocatorRef alloc, SecCertificateRef certificate, CFErrorRef *error)
922 {
923 CFStringRef result = NULL;
924 OSStatus __secapiresult = SecCertificateInferLabel(certificate, &result);
925 if (error!=NULL && __secapiresult!=errSecSuccess)
926 {
927 *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainOSStatus,
928 __secapiresult ? __secapiresult : CSSM_ERRCODE_INTERNAL_ERROR, NULL);
929 }
930 return result;
931 }
932
933 /* OS X only: __OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA) */
934 CFDataRef SecCertificateCopySerialNumber(SecCertificateRef certificate, CFErrorRef *error)
935 {
936 CFDataRef result = NULL;
937 OSStatus __secapiresult;
938 try
939 {
940 CertificateValues cv(certificate);
941 result = cv.copySerialNumber(error);
942 __secapiresult=0;
943 }
944 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
945 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
946 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
947 catch (...) { __secapiresult=errSecInternalComponent; }
948 return result;
949 }
950
951 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_12_4, __IPHONE_NA, __IPHONE_NA) */
952 CFDataRef SecCertificateCopyNormalizedIssuerContent(SecCertificateRef certificate, CFErrorRef *error)
953 {
954 CFDataRef result = NULL;
955 OSStatus __secapiresult;
956 try
957 {
958 CertificateValues cv(certificate);
959 result = cv.copyNormalizedIssuerContent(error);
960 __secapiresult=0;
961 }
962 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
963 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
964 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
965 catch (...) { __secapiresult=errSecInternalComponent; }
966 return result;
967 }
968
969 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_12_4, __IPHONE_NA, __IPHONE_NA) */
970 CFDataRef SecCertificateCopyNormalizedSubjectContent(SecCertificateRef certificate, CFErrorRef *error)
971 {
972 CFDataRef result = NULL;
973 OSStatus __secapiresult;
974 try
975 {
976 CertificateValues cv(certificate);
977 result = cv.copyNormalizedSubjectContent(error);
978 __secapiresult=0;
979 }
980 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
981 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
982 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
983 catch (...) { __secapiresult=errSecInternalComponent; }
984 return result;
985 }
986
987 /* OS X only: __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_7, __MAC_10_9, __IPHONE_NA, __IPHONE_NA) */
988 bool SecCertificateIsValidX(SecCertificateRef certificate, CFAbsoluteTime verifyTime)
989 {
990 /*
991 * deprecated function name
992 */
993 return SecCertificateIsValid(certificate, verifyTime);
994 }