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