]> git.saurik.com Git - apple/security.git/blob - Security/libsecurity_keychain/lib/SecCertificate.cpp
Security-57031.10.10.tar.gz
[apple/security.git] / Security / libsecurity_keychain / lib / SecCertificate.cpp
1 /*
2 * Copyright (c) 2002-2014 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_keychain/KCCursor.h>
42 #include <security_cdsa_utilities/Schema.h>
43 #include <sys/param.h>
44 #include "CertificateValues.h"
45 #include "SecCertificateP.h"
46 #include "SecCertificatePrivP.h"
47
48 #include "AppleBaselineEscrowCertificates.h"
49
50
51 extern CSSM_KEYUSE ConvertArrayToKeyUsage(CFArrayRef usage);
52
53 #define SEC_CONST_DECL(k,v) CFTypeRef k = (CFTypeRef)(CFSTR(v));
54
55 SEC_CONST_DECL (kSecCertificateProductionEscrowKey, "ProductionEscrowKey");
56 SEC_CONST_DECL (kSecCertificateProductionPCSEscrowKey, "ProductionPCSEscrowKey");
57 SEC_CONST_DECL (kSecCertificateEscrowFileName, "AppleESCertificates");
58
59
60 using namespace CssmClient;
61
62 CFTypeID
63 SecCertificateGetTypeID(void)
64 {
65 BEGIN_SECAPI
66
67 return gTypes().Certificate.typeID;
68
69 END_SECAPI1(_kCFRuntimeNotATypeID)
70 }
71
72
73 OSStatus
74 SecCertificateCreateFromData(const CSSM_DATA *data, CSSM_CERT_TYPE type, CSSM_CERT_ENCODING encoding, SecCertificateRef *certificate)
75 {
76 BEGIN_SECAPI
77
78 SecPointer<Certificate> certificatePtr(new Certificate(Required(data), type, encoding));
79 Required(certificate) = certificatePtr->handle();
80
81 END_SECAPI
82 }
83
84 /* new in 10.6 */
85 SecCertificateRef
86 SecCertificateCreateWithData(CFAllocatorRef allocator, CFDataRef data)
87 {
88 SecCertificateRef certificate = NULL;
89 OSStatus __secapiresult;
90 try {
91 CSSM_DATA cssmCertData;
92 cssmCertData.Length = (data) ? (CSSM_SIZE)CFDataGetLength(data) : 0;
93 cssmCertData.Data = (data) ? (uint8 *)CFDataGetBytePtr(data) : NULL;
94
95 //NOTE: there isn't yet a Certificate constructor which accepts a CFAllocatorRef
96 SecPointer<Certificate> certificatePtr(new Certificate(cssmCertData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER));
97 certificate = certificatePtr->handle();
98
99 __secapiresult=errSecSuccess;
100 }
101 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
102 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
103 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
104 catch (...) { __secapiresult=errSecInternalComponent; }
105 return certificate;
106 }
107
108 OSStatus
109 SecCertificateAddToKeychain(SecCertificateRef certificate, SecKeychainRef keychain)
110 {
111 BEGIN_SECAPI
112
113 Item item(Certificate::required(certificate));
114 Keychain::optional(keychain)->add(item);
115
116 END_SECAPI
117 }
118
119 OSStatus
120 SecCertificateGetData(SecCertificateRef certificate, CSSM_DATA_PTR data)
121 {
122 BEGIN_SECAPI
123
124 Required(data) = Certificate::required(certificate)->data();
125
126 END_SECAPI
127 }
128
129 /* new in 10.6 */
130 CFDataRef
131 SecCertificateCopyData(SecCertificateRef certificate)
132 {
133 CFDataRef data = NULL;
134 OSStatus __secapiresult = errSecSuccess;
135 try {
136 CssmData output = Certificate::required(certificate)->data();
137 CFIndex length = (CFIndex)output.length();
138 const UInt8 *bytes = (const UInt8 *)output.data();
139 if (length && bytes) {
140 data = CFDataCreate(NULL, bytes, length);
141 }
142 }
143 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
144 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
145 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
146 catch (...) { __secapiresult=errSecInternalComponent; }
147 return data;
148 }
149
150 CFDataRef
151 SecCertificateGetSHA1Digest(SecCertificateRef certificate)
152 {
153 CFDataRef data = NULL;
154 OSStatus __secapiresult = errSecSuccess;
155 try {
156 data = Certificate::required(certificate)->sha1Hash();
157 }
158 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
159 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
160 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
161 catch (...) { __secapiresult=errSecInternalComponent; }
162 return data;
163 }
164
165 CFArrayRef
166 SecCertificateCopyDNSNames(SecCertificateRef certificate)
167 {
168 CFArrayRef names = NULL;
169 OSStatus __secapiresult = errSecSuccess;
170 try {
171 names = Certificate::required(certificate)->copyDNSNames();
172 }
173 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
174 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
175 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
176 catch (...) { __secapiresult=errSecInternalComponent; }
177 return names;
178 }
179
180 OSStatus
181 SecCertificateGetType(SecCertificateRef certificate, CSSM_CERT_TYPE *certificateType)
182 {
183 BEGIN_SECAPI
184
185 Required(certificateType) = Certificate::required(certificate)->type();
186
187 END_SECAPI
188 }
189
190
191 OSStatus
192 SecCertificateGetSubject(SecCertificateRef certificate, const CSSM_X509_NAME **subject)
193 {
194 BEGIN_SECAPI
195
196 Required(subject) = Certificate::required(certificate)->subjectName();
197
198 END_SECAPI
199 }
200
201
202 OSStatus
203 SecCertificateGetIssuer(SecCertificateRef certificate, const CSSM_X509_NAME **issuer)
204 {
205 BEGIN_SECAPI
206
207 Required(issuer) = Certificate::required(certificate)->issuerName();
208
209 END_SECAPI
210 }
211
212
213 OSStatus
214 SecCertificateGetCLHandle(SecCertificateRef certificate, CSSM_CL_HANDLE *clHandle)
215 {
216 BEGIN_SECAPI
217
218 Required(clHandle) = Certificate::required(certificate)->clHandle();
219
220 END_SECAPI
221 }
222
223 /*
224 * Private API to infer a display name for a SecCertificateRef which
225 * may or may not be in a keychain.
226 */
227 OSStatus
228 SecCertificateInferLabel(SecCertificateRef certificate, CFStringRef *label)
229 {
230 BEGIN_SECAPI
231
232 Certificate::required(certificate)->inferLabel(false,
233 &Required(label));
234
235 END_SECAPI
236 }
237
238 OSStatus
239 SecCertificateCopyPublicKey(SecCertificateRef certificate, SecKeyRef *key)
240 {
241 BEGIN_SECAPI
242
243 Required(key) = Certificate::required(certificate)->publicKey()->handle();
244
245 END_SECAPI
246 }
247
248 OSStatus
249 SecCertificateGetAlgorithmID(SecCertificateRef certificate, const CSSM_X509_ALGORITHM_IDENTIFIER **algid)
250 {
251 BEGIN_SECAPI
252
253 Required(algid) = Certificate::required(certificate)->algorithmID();
254
255 END_SECAPI
256 }
257
258 OSStatus
259 SecCertificateCopyCommonName(SecCertificateRef certificate, CFStringRef *commonName)
260 {
261 BEGIN_SECAPI
262
263 Required(commonName) = Certificate::required(certificate)->commonName();
264
265 END_SECAPI
266 }
267
268 /* new in 10.6 */
269 CFStringRef
270 SecCertificateCopySubjectSummary(SecCertificateRef certificate)
271 {
272 CFStringRef summary = NULL;
273 OSStatus __secapiresult;
274 try {
275 Certificate::required(certificate)->inferLabel(false, &summary);
276
277 __secapiresult=errSecSuccess;
278 }
279 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
280 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
281 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
282 catch (...) { __secapiresult=errSecInternalComponent; }
283 return summary;
284 }
285
286 CFStringRef
287 SecCertificateCopyIssuerSummary(SecCertificateRef certificate)
288 {
289 CFStringRef issuerStr = NULL;
290 SecCertificateRefP certP = NULL;
291 CFDataRef certData = SecCertificateCopyData(certificate);
292 if (certData) {
293 certP = SecCertificateCreateWithDataP(NULL, certData);
294 CFRelease(certData);
295 }
296 if (certP) {
297 issuerStr = SecCertificateCopyIssuerSummaryP(certP);
298 CFRelease(certP);
299 }
300 return issuerStr;
301 }
302
303 OSStatus
304 SecCertificateCopySubjectComponent(SecCertificateRef certificate, const CSSM_OID *component, CFStringRef *result)
305 {
306 BEGIN_SECAPI
307
308 Required(result) = Certificate::required(certificate)->distinguishedName(&CSSMOID_X509V1SubjectNameCStruct, component);
309
310 END_SECAPI
311 }
312
313 OSStatus
314 SecCertificateGetCommonName(SecCertificateRef certificate, CFStringRef *commonName)
315 {
316 // deprecated SPI signature; replaced by SecCertificateCopyCommonName
317 return SecCertificateCopyCommonName(certificate, commonName);
318 }
319
320 OSStatus
321 SecCertificateGetEmailAddress(SecCertificateRef certificate, CFStringRef *emailAddress)
322 {
323 BEGIN_SECAPI
324
325 Required(emailAddress) = Certificate::required(certificate)->copyFirstEmailAddress();
326
327 END_SECAPI
328 }
329
330 OSStatus
331 SecCertificateCopyEmailAddresses(SecCertificateRef certificate, CFArrayRef *emailAddresses)
332 {
333 BEGIN_SECAPI
334
335 Required(emailAddresses) = Certificate::required(certificate)->copyEmailAddresses();
336
337 END_SECAPI
338 }
339
340 OSStatus
341 SecCertificateCopyFieldValues(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR **fieldValues)
342 {
343 /* Return a zero terminated list of CSSM_DATA_PTR's with the values of the field specified by field. Caller must call releaseFieldValues to free the storage allocated by this call. */
344 BEGIN_SECAPI
345
346 Required(fieldValues) = Certificate::required(certificate)->copyFieldValues(Required(field));
347
348 END_SECAPI
349 }
350
351 OSStatus
352 SecCertificateReleaseFieldValues(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR *fieldValues)
353 {
354 BEGIN_SECAPI
355
356 Certificate::required(certificate)->releaseFieldValues(Required(field), fieldValues);
357
358 END_SECAPI
359 }
360
361 OSStatus
362 SecCertificateCopyFirstFieldValue(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR *fieldValue)
363 {
364 BEGIN_SECAPI
365
366 Required(fieldValue) = Certificate::required(certificate)->copyFirstFieldValue(Required(field));
367
368 END_SECAPI
369 }
370
371 OSStatus
372 SecCertificateReleaseFirstFieldValue(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR fieldValue)
373 {
374 BEGIN_SECAPI
375
376 Certificate::required(certificate)->releaseFieldValue(Required(field), fieldValue);
377
378 END_SECAPI
379 }
380
381 OSStatus
382 SecCertificateFindByIssuerAndSN(CFTypeRef keychainOrArray,const CSSM_DATA *issuer,
383 const CSSM_DATA *serialNumber, SecCertificateRef *certificate)
384 {
385 BEGIN_SECAPI
386
387 StorageManager::KeychainList keychains;
388 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
389 Required(certificate) = Certificate::findByIssuerAndSN(keychains, CssmData::required(issuer), CssmData::required(serialNumber))->handle();
390
391 END_SECAPI
392 }
393
394 OSStatus
395 SecCertificateFindBySubjectKeyID(CFTypeRef keychainOrArray, const CSSM_DATA *subjectKeyID,
396 SecCertificateRef *certificate)
397 {
398 BEGIN_SECAPI
399
400 StorageManager::KeychainList keychains;
401 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
402 Required(certificate) = Certificate::findBySubjectKeyID(keychains, CssmData::required(subjectKeyID))->handle();
403
404 END_SECAPI
405 }
406
407 OSStatus
408 SecCertificateFindByEmail(CFTypeRef keychainOrArray, const char *emailAddress, SecCertificateRef *certificate)
409 {
410 BEGIN_SECAPI
411
412 StorageManager::KeychainList keychains;
413 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
414 Required(certificate) = Certificate::findByEmail(keychains, emailAddress)->handle();
415
416 END_SECAPI
417 }
418
419 OSStatus
420 SecKeychainSearchCreateForCertificateByIssuerAndSN(CFTypeRef keychainOrArray, const CSSM_DATA *issuer,
421 const CSSM_DATA *serialNumber, SecKeychainSearchRef *searchRef)
422 {
423 BEGIN_SECAPI
424
425 Required(searchRef);
426
427 StorageManager::KeychainList keychains;
428 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
429 KCCursor cursor(Certificate::cursorForIssuerAndSN(keychains, CssmData::required(issuer), CssmData::required(serialNumber)));
430 *searchRef = cursor->handle();
431
432 END_SECAPI
433 }
434
435 OSStatus
436 SecKeychainSearchCreateForCertificateByIssuerAndSN_CF(CFTypeRef keychainOrArray, CFDataRef issuer,
437 CFDataRef serialNumber, SecKeychainSearchRef *searchRef)
438 {
439 BEGIN_SECAPI
440
441 Required(searchRef);
442
443 StorageManager::KeychainList keychains;
444 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
445 Required(issuer);
446 Required(serialNumber);
447 KCCursor cursor(Certificate::cursorForIssuerAndSN_CF(keychains, issuer, serialNumber));
448 *searchRef = cursor->handle();
449
450 END_SECAPI
451 }
452
453 OSStatus
454 SecKeychainSearchCreateForCertificateBySubjectKeyID(CFTypeRef keychainOrArray, const CSSM_DATA *subjectKeyID,
455 SecKeychainSearchRef *searchRef)
456 {
457 BEGIN_SECAPI
458
459 Required(searchRef);
460
461 StorageManager::KeychainList keychains;
462 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
463 KCCursor cursor(Certificate::cursorForSubjectKeyID(keychains, CssmData::required(subjectKeyID)));
464 *searchRef = cursor->handle();
465
466 END_SECAPI
467 }
468
469 OSStatus
470 SecKeychainSearchCreateForCertificateByEmail(CFTypeRef keychainOrArray, const char *emailAddress,
471 SecKeychainSearchRef *searchRef)
472 {
473 BEGIN_SECAPI
474
475 Required(searchRef);
476
477 StorageManager::KeychainList keychains;
478 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
479 KCCursor cursor(Certificate::cursorForEmail(keychains, emailAddress));
480 *searchRef = cursor->handle();
481
482 END_SECAPI
483 }
484
485 /* NOT EXPORTED YET; copied from SecurityInterface but could be useful in the future.
486 CSSM_CSP_HANDLE
487 SecGetAppleCSPHandle()
488 {
489 BEGIN_SECAPI
490 return CSP(gGuidAppleCSP)->handle();
491 END_SECAPI1(NULL);
492 }
493
494 CSSM_CL_HANDLE
495 SecGetAppleCLHandle()
496 {
497 BEGIN_SECAPI
498 return CL(gGuidAppleX509CL)->handle();
499 END_SECAPI1(NULL);
500 }
501 */
502
503 CSSM_RETURN
504 SecDigestGetData (CSSM_ALGORITHMS alg, CSSM_DATA* digest, const CSSM_DATA* data)
505 {
506 BEGIN_SECAPI
507 // sanity checking
508 if (!digest || !digest->Data || !digest->Length || !data || !data->Data || !data->Length)
509 return errSecParam;
510
511 CSP csp(gGuidAppleCSP);
512 Digest context(csp, alg);
513 CssmData input(data->Data, data->Length);
514 CssmData output(digest->Data, digest->Length);
515
516 context.digest(input, output);
517 digest->Length = output.length();
518
519 return CSSM_OK;
520 END_SECAPI1(1);
521 }
522
523 /* determine whether a cert is self-signed */
524 OSStatus SecCertificateIsSelfSigned(
525 SecCertificateRef certificate,
526 Boolean *isSelfSigned) /* RETURNED */
527 {
528 BEGIN_SECAPI
529
530 *isSelfSigned = Certificate::required(certificate)->isSelfSigned();
531
532 END_SECAPI
533 }
534
535 OSStatus
536 SecCertificateCopyPreference(
537 CFStringRef name,
538 CSSM_KEYUSE keyUsage,
539 SecCertificateRef *certificate)
540 {
541 BEGIN_SECAPI
542
543 Required(name);
544 Required(certificate);
545 StorageManager::KeychainList keychains;
546 globals().storageManager.getSearchList(keychains);
547 KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL);
548
549 char idUTF8[MAXPATHLEN];
550 if (!CFStringGetCString(name, idUTF8, sizeof(idUTF8)-1, kCFStringEncodingUTF8))
551 idUTF8[0] = (char)'\0';
552 CssmData service(const_cast<char *>(idUTF8), strlen(idUTF8));
553 FourCharCode itemType = 'cprf';
554 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service);
555 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), itemType);
556 if (keyUsage)
557 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage);
558
559 Item prefItem;
560 if (!cursor->next(prefItem))
561 MacOSError::throwMe(errSecItemNotFound);
562
563 // get persistent certificate reference
564 SecKeychainAttribute itemAttrs[] = { { kSecGenericItemAttr, 0, NULL } };
565 SecKeychainAttributeList itemAttrList = { sizeof(itemAttrs) / sizeof(itemAttrs[0]), itemAttrs };
566 prefItem->getContent(NULL, &itemAttrList, NULL, NULL);
567
568 // find certificate, given persistent reference data
569 CFDataRef pItemRef = CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)itemAttrs[0].data, itemAttrs[0].length, kCFAllocatorNull);
570 SecKeychainItemRef certItemRef = nil;
571 OSStatus status = SecKeychainItemCopyFromPersistentReference(pItemRef, &certItemRef); //%%% need to make this a method of ItemImpl
572 prefItem->freeContent(&itemAttrList, NULL);
573 if (pItemRef)
574 CFRelease(pItemRef);
575 if (status)
576 return status;
577
578 *certificate = (SecCertificateRef)certItemRef;
579
580 END_SECAPI
581 }
582
583 SecCertificateRef
584 SecCertificateCopyPreferred(
585 CFStringRef name,
586 CFArrayRef keyUsage)
587 {
588 // This function will look for a matching preference in the following order:
589 // - matches the name and the supplied key use
590 // - matches the name and the special 'ANY' key use
591 // - matches the name with no key usage constraint
592
593 SecCertificateRef certRef = NULL;
594 CSSM_KEYUSE keyUse = ConvertArrayToKeyUsage(keyUsage);
595 OSStatus status = SecCertificateCopyPreference(name, keyUse, &certRef);
596 if (status != errSecSuccess && keyUse != CSSM_KEYUSE_ANY)
597 status = SecCertificateCopyPreference(name, CSSM_KEYUSE_ANY, &certRef);
598 if (status != errSecSuccess && keyUse != 0)
599 status = SecCertificateCopyPreference(name, 0, &certRef);
600
601 return certRef;
602 }
603
604 static OSStatus
605 SecCertificateFindPreferenceItemWithNameAndKeyUsage(
606 CFTypeRef keychainOrArray,
607 CFStringRef name,
608 int32_t keyUsage,
609 SecKeychainItemRef *itemRef)
610 {
611 BEGIN_SECAPI
612
613 StorageManager::KeychainList keychains;
614 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
615 KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL);
616
617 char idUTF8[MAXPATHLEN];
618 idUTF8[0] = (char)'\0';
619 if (name)
620 {
621 if (!CFStringGetCString(name, idUTF8, sizeof(idUTF8)-1, kCFStringEncodingUTF8))
622 idUTF8[0] = (char)'\0';
623 }
624 size_t idUTF8Len = strlen(idUTF8);
625 if (!idUTF8Len)
626 MacOSError::throwMe(errSecParam);
627
628 CssmData service(const_cast<char *>(idUTF8), idUTF8Len);
629 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service);
630 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), (FourCharCode)'cprf');
631 if (keyUsage)
632 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage);
633
634 Item item;
635 if (!cursor->next(item))
636 MacOSError::throwMe(errSecItemNotFound);
637
638 if (itemRef)
639 *itemRef=item->handle();
640
641 END_SECAPI
642 }
643
644 static
645 OSStatus SecCertificateDeletePreferenceItemWithNameAndKeyUsage(
646 CFTypeRef keychainOrArray,
647 CFStringRef name,
648 int32_t keyUsage)
649 {
650 // when a specific key usage is passed, we'll only match & delete that pref;
651 // when a key usage of 0 is passed, all matching prefs should be deleted.
652 // maxUsages represents the most matches there could theoretically be, so
653 // cut things off at that point if we're still finding items (if they can't
654 // be deleted for some reason, we'd never break out of the loop.)
655
656 OSStatus status;
657 SecKeychainItemRef item = NULL;
658 int count = 0, maxUsages = 12;
659 while (++count <= maxUsages &&
660 (status = SecCertificateFindPreferenceItemWithNameAndKeyUsage(keychainOrArray, name, keyUsage, &item)) == errSecSuccess) {
661 status = SecKeychainItemDelete(item);
662 CFRelease(item);
663 item = NULL;
664 }
665
666 // it's not an error if the item isn't found
667 return (status == errSecItemNotFound) ? errSecSuccess : status;
668 }
669
670 OSStatus SecCertificateSetPreference(
671 SecCertificateRef certificate,
672 CFStringRef name,
673 CSSM_KEYUSE keyUsage,
674 CFDateRef date)
675 {
676 if (!name) {
677 return errSecParam;
678 }
679 if (!certificate) {
680 // treat NULL certificate as a request to clear the preference
681 // (note: if keyUsage is 0, this clears all key usage prefs for name)
682 return SecCertificateDeletePreferenceItemWithNameAndKeyUsage(NULL, name, keyUsage);
683 }
684
685 BEGIN_SECAPI
686
687 // determine the account attribute
688 //
689 // This attribute must be synthesized from certificate label + pref item type + key usage,
690 // as only the account and service attributes can make a generic keychain item unique.
691 // For 'iprf' type items (but not 'cprf'), we append a trailing space. This insures that
692 // we can save a certificate preference if an identity preference already exists for the
693 // given service name, and vice-versa.
694 // If the key usage is 0 (i.e. the normal case), we omit the appended key usage string.
695 //
696 CFStringRef labelStr = nil;
697 Certificate::required(certificate)->inferLabel(false, &labelStr);
698 if (!labelStr) {
699 MacOSError::throwMe(errSecDataTooLarge); // data is "in a format which cannot be displayed"
700 }
701 CFIndex accountUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(labelStr), kCFStringEncodingUTF8) + 1;
702 const char *templateStr = "%s [key usage 0x%X]";
703 const int keyUsageMaxStrLen = 8;
704 accountUTF8Len += strlen(templateStr) + keyUsageMaxStrLen;
705 char accountUTF8[accountUTF8Len];
706 if (!CFStringGetCString(labelStr, accountUTF8, accountUTF8Len-1, kCFStringEncodingUTF8))
707 accountUTF8[0] = (char)'\0';
708 if (keyUsage)
709 snprintf(accountUTF8, accountUTF8Len-1, templateStr, accountUTF8, keyUsage);
710 CssmData account(const_cast<char *>(accountUTF8), strlen(accountUTF8));
711 CFRelease(labelStr);
712
713 // service attribute (name provided by the caller)
714 CFIndex serviceUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(name), kCFStringEncodingUTF8) + 1;;
715 char serviceUTF8[serviceUTF8Len];
716 if (!CFStringGetCString(name, serviceUTF8, serviceUTF8Len-1, kCFStringEncodingUTF8))
717 serviceUTF8[0] = (char)'\0';
718 CssmData service(const_cast<char *>(serviceUTF8), strlen(serviceUTF8));
719
720 // look for existing preference item, in case this is an update
721 StorageManager::KeychainList keychains;
722 globals().storageManager.getSearchList(keychains);
723 KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL);
724 FourCharCode itemType = 'cprf';
725 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service);
726 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), itemType);
727 if (keyUsage)
728 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage);
729 if (date)
730 ; // %%%TBI
731
732 Item item(kSecGenericPasswordItemClass, 'aapl', 0, NULL, false);
733 bool add = (!cursor->next(item));
734 // at this point, we either have a new item to add or an existing item to update
735
736 // set item attribute values
737 item->setAttribute(Schema::attributeInfo(kSecServiceItemAttr), service);
738 item->setAttribute(Schema::attributeInfo(kSecTypeItemAttr), itemType);
739 item->setAttribute(Schema::attributeInfo(kSecAccountItemAttr), account);
740 item->setAttribute(Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage);
741 item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), service);
742
743 // date
744 if (date)
745 ; // %%%TBI
746
747 // generic attribute (store persistent certificate reference)
748 CFDataRef pItemRef = nil;
749 Certificate::required(certificate)->copyPersistentReference(pItemRef);
750 if (!pItemRef) {
751 MacOSError::throwMe(errSecInvalidItemRef);
752 }
753 const UInt8 *dataPtr = CFDataGetBytePtr(pItemRef);
754 CFIndex dataLen = CFDataGetLength(pItemRef);
755 CssmData pref(const_cast<void *>(reinterpret_cast<const void *>(dataPtr)), dataLen);
756 item->setAttribute(Schema::attributeInfo(kSecGenericItemAttr), pref);
757 CFRelease(pItemRef);
758
759 if (add) {
760 Keychain keychain = nil;
761 try {
762 keychain = globals().storageManager.defaultKeychain();
763 if (!keychain->exists())
764 MacOSError::throwMe(errSecNoSuchKeychain); // Might be deleted or not available at this time.
765 }
766 catch(...) {
767 keychain = globals().storageManager.defaultKeychainUI(item);
768 }
769
770 try {
771 keychain->add(item);
772 }
773 catch (const MacOSError &err) {
774 if (err.osStatus() != errSecDuplicateItem)
775 throw; // if item already exists, fall through to update
776 }
777 }
778 item->update();
779
780 END_SECAPI
781 }
782
783 OSStatus SecCertificateSetPreferred(
784 SecCertificateRef certificate,
785 CFStringRef name,
786 CFArrayRef keyUsage)
787 {
788 CSSM_KEYUSE keyUse = ConvertArrayToKeyUsage(keyUsage);
789 return SecCertificateSetPreference(certificate, name, keyUse, NULL);
790 }
791
792 CFDictionaryRef SecCertificateCopyValues(SecCertificateRef certificate, CFArrayRef keys, CFErrorRef *error)
793 {
794 CFDictionaryRef result = NULL;
795 OSStatus __secapiresult;
796 try
797 {
798 CertificateValues cv(certificate);
799 result = cv.copyFieldValues(keys,error);
800 __secapiresult=0;
801 }
802 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
803 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
804 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
805 catch (...) { __secapiresult=errSecInternalComponent; }
806 return result;
807 }
808
809 CFStringRef SecCertificateCopyLongDescription(CFAllocatorRef alloc, SecCertificateRef certificate, CFErrorRef *error)
810 {
811 return SecCertificateCopyShortDescription(alloc, certificate, error);
812 }
813
814 CFStringRef SecCertificateCopyShortDescription(CFAllocatorRef alloc, SecCertificateRef certificate, CFErrorRef *error)
815 {
816 CFStringRef result = NULL;
817 OSStatus __secapiresult;
818 try
819 {
820 __secapiresult = SecCertificateInferLabel(certificate, &result);
821 }
822 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
823 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
824 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
825 catch (...) { __secapiresult=errSecInternalComponent; }
826 if (error!=NULL && __secapiresult!=errSecSuccess)
827 {
828 *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainOSStatus,
829 __secapiresult ? __secapiresult : CSSM_ERRCODE_INTERNAL_ERROR, NULL);
830 }
831 return result;
832 }
833
834 CFDataRef SecCertificateCopySerialNumber(SecCertificateRef certificate, CFErrorRef *error)
835 {
836 CFDataRef result = NULL;
837 OSStatus __secapiresult;
838 try
839 {
840 CertificateValues cv(certificate);
841 result = cv.copySerialNumber(error);
842 __secapiresult=0;
843 }
844 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
845 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
846 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
847 catch (...) { __secapiresult=errSecInternalComponent; }
848 return result;
849 }
850
851 CFDataRef SecCertificateCopyNormalizedIssuerContent(SecCertificateRef certificate, CFErrorRef *error)
852 {
853 CFDataRef result = NULL;
854 OSStatus __secapiresult;
855 try
856 {
857 CertificateValues cv(certificate);
858 result = cv.copyNormalizedIssuerContent(error);
859 __secapiresult=0;
860 }
861 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
862 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
863 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
864 catch (...) { __secapiresult=errSecInternalComponent; }
865 return result;
866 }
867
868 CFDataRef SecCertificateCopyNormalizedSubjectContent(SecCertificateRef certificate, CFErrorRef *error)
869 {
870 CFDataRef result = NULL;
871 OSStatus __secapiresult;
872 try
873 {
874 CertificateValues cv(certificate);
875 result = cv.copyNormalizedSubjectContent(error);
876 __secapiresult=0;
877 }
878 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
879 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
880 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
881 catch (...) { __secapiresult=errSecInternalComponent; }
882 return result;
883 }
884
885 CFDataRef SecCertificateCopyIssuerSequence(SecCertificateRef certificate)
886 {
887 CFDataRef result = NULL;
888 OSStatus __secapiresult;
889 try
890 {
891 CertificateValues cv(certificate);
892 result = cv.copyIssuerSequence(NULL);
893 __secapiresult=0;
894 }
895 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
896 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
897 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
898 catch (...) { __secapiresult=errSecInternalComponent; }
899 return result;
900 }
901
902 CFDataRef SecCertificateCopySubjectSequence(SecCertificateRef certificate)
903 {
904 CFDataRef result = NULL;
905 OSStatus __secapiresult;
906 try
907 {
908 CertificateValues cv(certificate);
909 result = cv.copySubjectSequence(NULL);
910 __secapiresult=0;
911 }
912 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
913 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
914 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
915 catch (...) { __secapiresult=errSecInternalComponent; }
916 return result;
917 }
918
919 bool SecCertificateIsValid(SecCertificateRef certificate, CFAbsoluteTime verifyTime)
920 {
921 bool result = NULL;
922 OSStatus __secapiresult;
923 try
924 {
925 CFErrorRef error = NULL;
926 CertificateValues cv(certificate);
927 result = cv.isValid(verifyTime, &error);
928 if (error) CFRelease(error);
929 __secapiresult=0;
930 }
931 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
932 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
933 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
934 catch (...) { __secapiresult=errSecInternalComponent; }
935 return result;
936 }
937
938 /*
939 * deprecated function name
940 */
941 bool SecCertificateIsValidX(SecCertificateRef certificate, CFAbsoluteTime verifyTime)
942 {
943 return SecCertificateIsValid(certificate, verifyTime);
944 }
945
946
947 CFAbsoluteTime SecCertificateNotValidBefore(SecCertificateRef certificate)
948 {
949 CFAbsoluteTime result = 0;
950 OSStatus __secapiresult;
951 try
952 {
953 CFErrorRef error = NULL;
954 CertificateValues cv(certificate);
955 result = cv.notValidBefore(&error);
956 if (error) CFRelease(error);
957 __secapiresult=0;
958 }
959 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
960 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
961 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
962 catch (...) { __secapiresult=errSecInternalComponent; }
963 return result;
964 }
965
966 CFAbsoluteTime SecCertificateNotValidAfter(SecCertificateRef certificate)
967 {
968 CFAbsoluteTime result = 0;
969 OSStatus __secapiresult;
970 try
971 {
972 CFErrorRef error = NULL;
973 CertificateValues cv(certificate);
974 result = cv.notValidAfter(&error);
975 if (error) CFRelease(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 /* new in 10.8 */
986 SecCertificateRef SecCertificateCreateWithBytes(CFAllocatorRef allocator,
987 const UInt8 *bytes, CFIndex length)
988 {
989 SecCertificateRef certificate = NULL;
990 OSStatus __secapiresult;
991 try {
992 CSSM_DATA cssmCertData = { (CSSM_SIZE)length, (uint8 *)bytes };
993
994 //NOTE: there isn't yet a Certificate constructor which accepts a CFAllocatorRef
995 SecPointer<Certificate> certificatePtr(new Certificate(cssmCertData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER));
996 certificate = certificatePtr->handle();
997
998 __secapiresult=errSecSuccess;
999 }
1000 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
1001 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
1002 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
1003 catch (...) { __secapiresult=errSecInternalComponent; }
1004 return certificate;
1005 }
1006
1007 /* new in 10.8 */
1008 CFIndex SecCertificateGetLength(SecCertificateRef certificate)
1009 {
1010 CFIndex length = 0;
1011 OSStatus __secapiresult;
1012 try {
1013 CssmData output = Certificate::required(certificate)->data();
1014 length = (CFIndex)output.length();
1015 __secapiresult=errSecSuccess;
1016 }
1017 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
1018 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
1019 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
1020 catch (...) { __secapiresult=errSecInternalComponent; }
1021 return length;
1022 }
1023
1024 /* new in 10.8 */
1025 const UInt8 *SecCertificateGetBytePtr(SecCertificateRef certificate)
1026 {
1027 const UInt8 *bytes = NULL;
1028 OSStatus __secapiresult;
1029 try {
1030 CssmData output = Certificate::required(certificate)->data();
1031 bytes = (const UInt8 *)output.data();
1032 __secapiresult=errSecSuccess;
1033 }
1034 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
1035 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
1036 catch (const std::bad_alloc &) { __secapiresult=errSecAllocate; }
1037 catch (...) { __secapiresult=errSecInternalComponent; }
1038 return bytes;
1039 }
1040
1041 static CFArrayRef CopyEscrowCertificates(SecCertificateEscrowRootType escrowRootType, CFErrorRef *error)
1042 {
1043 // Return array of CFDataRef certificates.
1044 CFArrayRef result = NULL;
1045 int iCnt;
1046 int numRoots = 0;
1047
1048 // Get the hard coded set of production roots
1049 // static struct RootRecord* kProductionEscrowRoots[] = {&kOldEscrowRootRecord, &kProductionEscrowRootRecord};
1050
1051 struct RootRecord** pEscrowRoots = NULL;
1052 switch (escrowRootType) {
1053 case kSecCertificateBaselineEscrowRoot:
1054 numRoots = kNumberOfBaseLineEscrowRoots;
1055 pEscrowRoots = kBaseLineEscrowRoots;
1056 break;
1057 case kSecCertificateProductionEscrowRoot:
1058 numRoots = kNumberOfBaseLineEscrowRoots; //%%% currently, production == baseline on OS X
1059 pEscrowRoots = kBaseLineEscrowRoots;
1060 break;
1061 case kSecCertificateBaselinePCSEscrowRoot:
1062 numRoots = kNumberOfBaseLinePCSEscrowRoots;
1063 pEscrowRoots = kBaseLinePCSEscrowRoots;
1064 break;
1065 case kSecCertificateProductionPCSEscrowRoot:
1066 numRoots = kNumberOfBaseLinePCSEscrowRoots; //%%% currently, production == baseline on OS X
1067 pEscrowRoots = kBaseLinePCSEscrowRoots;
1068 break;
1069 default:
1070 break;
1071 }
1072
1073 CFDataRef productionCerts[numRoots];
1074 struct RootRecord* pRootRecord = NULL;
1075
1076 for (iCnt = 0; pEscrowRoots != NULL && iCnt < numRoots; iCnt++)
1077 {
1078 pRootRecord = pEscrowRoots[iCnt];
1079 if (NULL != pRootRecord && pRootRecord->_length > 0 && NULL != pRootRecord->_bytes)
1080 {
1081 productionCerts[iCnt] = CFDataCreate(kCFAllocatorDefault, pRootRecord->_bytes, pRootRecord->_length);
1082 }
1083 }
1084 result = CFArrayCreate(kCFAllocatorDefault, (const void **)productionCerts, numRoots, &kCFTypeArrayCallBacks);
1085 for (iCnt = 0; iCnt < numRoots; iCnt++)
1086 {
1087 if (NULL != productionCerts[iCnt])
1088 {
1089 CFRelease(productionCerts[iCnt]);
1090 }
1091 }
1092
1093 return result;
1094 }
1095
1096 /* new in 10.9 */
1097 CFArrayRef SecCertificateCopyEscrowRoots(SecCertificateEscrowRootType escrowRootType)
1098 {
1099 CFArrayRef result = NULL;
1100 int iCnt;
1101 int numRoots = 0;
1102 CFDataRef certData = NULL;
1103
1104 // The request is for the base line certificates.
1105 // Use the hard coded data to generate the return array
1106 if (kSecCertificateBaselineEscrowRoot == escrowRootType)
1107 {
1108 // Get the hard coded set of roots
1109 numRoots = kNumberOfBaseLineEscrowRoots;
1110 SecCertificateRef baseLineCerts[numRoots];
1111 struct RootRecord* pRootRecord = NULL;
1112
1113 for (iCnt = 0; iCnt < numRoots; iCnt++)
1114 {
1115 pRootRecord = kBaseLineEscrowRoots[iCnt];
1116 if (NULL != pRootRecord && pRootRecord->_length > 0 && NULL != pRootRecord->_bytes)
1117 {
1118 certData = CFDataCreate(kCFAllocatorDefault, pRootRecord->_bytes, pRootRecord->_length);
1119 if (NULL != certData)
1120 {
1121 baseLineCerts[iCnt] = SecCertificateCreateWithData(kCFAllocatorDefault, certData);
1122 CFRelease(certData);
1123 }
1124 }
1125 }
1126 result = CFArrayCreate(kCFAllocatorDefault, (const void **)baseLineCerts, numRoots, &kCFTypeArrayCallBacks);
1127 for (iCnt = 0; iCnt < numRoots; iCnt++)
1128 {
1129 if (NULL != baseLineCerts[iCnt])
1130 {
1131 CFRelease(baseLineCerts[iCnt]);
1132 }
1133 }
1134 }
1135 // The request is for the current certificates.
1136 else
1137 {
1138 CFErrorRef error = NULL;
1139 CFArrayRef cert_datas = CopyEscrowCertificates(escrowRootType, &error);
1140 if (NULL != error || NULL == cert_datas || 0 == (numRoots = (int)CFArrayGetCount(cert_datas)))
1141 {
1142 if (NULL != error)
1143 {
1144 CFRelease(error);
1145 }
1146
1147 if (NULL != cert_datas)
1148 {
1149 CFRelease(cert_datas);
1150 }
1151 return result;
1152 }
1153
1154 SecCertificateRef assetCerts[numRoots];
1155 for (iCnt = 0; iCnt < numRoots; iCnt++)
1156 {
1157 certData = (CFDataRef)CFArrayGetValueAtIndex(cert_datas, iCnt);
1158 if (NULL != certData)
1159 {
1160 SecCertificateRef aCertRef = SecCertificateCreateWithData(kCFAllocatorDefault, certData);
1161 assetCerts[iCnt] = aCertRef;
1162 }
1163 else
1164 {
1165 assetCerts[iCnt] = NULL;
1166 }
1167 }
1168
1169 if (numRoots > 0)
1170 {
1171 result = CFArrayCreate(kCFAllocatorDefault, (const void **)assetCerts, numRoots, &kCFTypeArrayCallBacks);
1172 for (iCnt = 0; iCnt < numRoots; iCnt++)
1173 {
1174 if (NULL != assetCerts[iCnt])
1175 {
1176 CFRelease(assetCerts[iCnt]);
1177 }
1178 }
1179 }
1180 CFRelease(cert_datas);
1181 }
1182 return result;
1183 }
1184