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