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