]> git.saurik.com Git - apple/security.git/blob - libsecurity_keychain/lib/SecCertificate.cpp
Security-55163.44.tar.gz
[apple/security.git] / libsecurity_keychain / lib / SecCertificate.cpp
1 /*
2 * Copyright (c) 2002-2010 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
47 extern CSSM_KEYUSE ConvertArrayToKeyUsage(CFArrayRef usage);
48
49
50 using namespace CssmClient;
51
52 CFTypeID
53 SecCertificateGetTypeID(void)
54 {
55 BEGIN_SECAPI
56
57 return gTypes().Certificate.typeID;
58
59 END_SECAPI1(_kCFRuntimeNotATypeID)
60 }
61
62
63 OSStatus
64 SecCertificateCreateFromData(const CSSM_DATA *data, CSSM_CERT_TYPE type, CSSM_CERT_ENCODING encoding, SecCertificateRef *certificate)
65 {
66 BEGIN_SECAPI
67
68 SecPointer<Certificate> certificatePtr(new Certificate(Required(data), type, encoding));
69 Required(certificate) = certificatePtr->handle();
70
71 END_SECAPI
72 }
73
74 /* new in 10.6 */
75 SecCertificateRef
76 SecCertificateCreateWithData(CFAllocatorRef allocator, CFDataRef data)
77 {
78 SecCertificateRef certificate = NULL;
79 OSStatus __secapiresult;
80 try {
81 CSSM_DATA cssmCertData;
82 cssmCertData.Length = (data) ? (CSSM_SIZE)CFDataGetLength(data) : 0;
83 cssmCertData.Data = (data) ? (uint8 *)CFDataGetBytePtr(data) : NULL;
84
85 //NOTE: there isn't yet a Certificate constructor which accepts a CFAllocatorRef
86 SecPointer<Certificate> certificatePtr(new Certificate(cssmCertData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER));
87 certificate = certificatePtr->handle();
88
89 __secapiresult=noErr;
90 }
91 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
92 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
93 catch (const std::bad_alloc &) { __secapiresult=memFullErr; }
94 catch (...) { __secapiresult=internalComponentErr; }
95 return certificate;
96 }
97
98 OSStatus
99 SecCertificateAddToKeychain(SecCertificateRef certificate, SecKeychainRef keychain)
100 {
101 BEGIN_SECAPI
102
103 Item item(Certificate::required(certificate));
104 Keychain::optional(keychain)->add(item);
105
106 END_SECAPI
107 }
108
109 OSStatus
110 SecCertificateGetData(SecCertificateRef certificate, CSSM_DATA_PTR data)
111 {
112 BEGIN_SECAPI
113
114 Required(data) = Certificate::required(certificate)->data();
115
116 END_SECAPI
117 }
118
119 /* new in 10.6 */
120 CFDataRef
121 SecCertificateCopyData(SecCertificateRef certificate)
122 {
123 CFDataRef data = NULL;
124 OSStatus __secapiresult;
125 try {
126 CssmData output = Certificate::required(certificate)->data();
127 CFIndex length = (CFIndex)output.length();
128 const UInt8 *bytes = (const UInt8 *)output.data();
129 if (length && bytes) {
130 data = CFDataCreate(NULL, bytes, length);
131 }
132 __secapiresult=noErr;
133 }
134 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
135 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
136 catch (const std::bad_alloc &) { __secapiresult=memFullErr; }
137 catch (...) { __secapiresult=internalComponentErr; }
138 return data;
139 }
140
141 OSStatus
142 SecCertificateGetType(SecCertificateRef certificate, CSSM_CERT_TYPE *certificateType)
143 {
144 BEGIN_SECAPI
145
146 Required(certificateType) = Certificate::required(certificate)->type();
147
148 END_SECAPI
149 }
150
151
152 OSStatus
153 SecCertificateGetSubject(SecCertificateRef certificate, const CSSM_X509_NAME **subject)
154 {
155 BEGIN_SECAPI
156
157 Required(subject) = Certificate::required(certificate)->subjectName();
158
159 END_SECAPI
160 }
161
162
163 OSStatus
164 SecCertificateGetIssuer(SecCertificateRef certificate, const CSSM_X509_NAME **issuer)
165 {
166 BEGIN_SECAPI
167
168 Required(issuer) = Certificate::required(certificate)->issuerName();
169
170 END_SECAPI
171 }
172
173
174 OSStatus
175 SecCertificateGetCLHandle(SecCertificateRef certificate, CSSM_CL_HANDLE *clHandle)
176 {
177 BEGIN_SECAPI
178
179 Required(clHandle) = Certificate::required(certificate)->clHandle();
180
181 END_SECAPI
182 }
183
184 /*
185 * Private API to infer a display name for a SecCertificateRef which
186 * may or may not be in a keychain.
187 */
188 OSStatus
189 SecCertificateInferLabel(SecCertificateRef certificate, CFStringRef *label)
190 {
191 BEGIN_SECAPI
192
193 Certificate::required(certificate)->inferLabel(false,
194 &Required(label));
195
196 END_SECAPI
197 }
198
199 OSStatus
200 SecCertificateCopyPublicKey(SecCertificateRef certificate, SecKeyRef *key)
201 {
202 BEGIN_SECAPI
203
204 Required(key) = Certificate::required(certificate)->publicKey()->handle();
205
206 END_SECAPI
207 }
208
209 OSStatus
210 SecCertificateGetAlgorithmID(SecCertificateRef certificate, const CSSM_X509_ALGORITHM_IDENTIFIER **algid)
211 {
212 BEGIN_SECAPI
213
214 Required(algid) = Certificate::required(certificate)->algorithmID();
215
216 END_SECAPI
217 }
218
219 OSStatus
220 SecCertificateCopyCommonName(SecCertificateRef certificate, CFStringRef *commonName)
221 {
222 BEGIN_SECAPI
223
224 Required(commonName) = Certificate::required(certificate)->commonName();
225
226 END_SECAPI
227 }
228
229 /* new in 10.6 */
230 CFStringRef
231 SecCertificateCopySubjectSummary(SecCertificateRef certificate)
232 {
233 CFStringRef summary = NULL;
234 OSStatus __secapiresult;
235 try {
236 Certificate::required(certificate)->inferLabel(false, &summary);
237
238 __secapiresult=noErr;
239 }
240 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
241 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
242 catch (const std::bad_alloc &) { __secapiresult=memFullErr; }
243 catch (...) { __secapiresult=internalComponentErr; }
244 return summary;
245 }
246
247 OSStatus
248 SecCertificateCopySubjectComponent(SecCertificateRef certificate, const CSSM_OID *component, CFStringRef *result)
249 {
250 BEGIN_SECAPI
251
252 Required(result) = Certificate::required(certificate)->distinguishedName(&CSSMOID_X509V1SubjectNameCStruct, component);
253
254 END_SECAPI
255 }
256
257 OSStatus
258 SecCertificateGetCommonName(SecCertificateRef certificate, CFStringRef *commonName)
259 {
260 // deprecated SPI signature; replaced by SecCertificateCopyCommonName
261 return SecCertificateCopyCommonName(certificate, commonName);
262 }
263
264 OSStatus
265 SecCertificateGetEmailAddress(SecCertificateRef certificate, CFStringRef *emailAddress)
266 {
267 BEGIN_SECAPI
268
269 Required(emailAddress) = Certificate::required(certificate)->copyFirstEmailAddress();
270
271 END_SECAPI
272 }
273
274 OSStatus
275 SecCertificateCopyEmailAddresses(SecCertificateRef certificate, CFArrayRef *emailAddresses)
276 {
277 BEGIN_SECAPI
278
279 Required(emailAddresses) = Certificate::required(certificate)->copyEmailAddresses();
280
281 END_SECAPI
282 }
283
284 OSStatus
285 SecCertificateCopyFieldValues(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR **fieldValues)
286 {
287 /* 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. */
288 BEGIN_SECAPI
289
290 Required(fieldValues) = Certificate::required(certificate)->copyFieldValues(Required(field));
291
292 END_SECAPI
293 }
294
295 OSStatus
296 SecCertificateReleaseFieldValues(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR *fieldValues)
297 {
298 BEGIN_SECAPI
299
300 Certificate::required(certificate)->releaseFieldValues(Required(field), fieldValues);
301
302 END_SECAPI
303 }
304
305 OSStatus
306 SecCertificateCopyFirstFieldValue(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR *fieldValue)
307 {
308 BEGIN_SECAPI
309
310 Required(fieldValue) = Certificate::required(certificate)->copyFirstFieldValue(Required(field));
311
312 END_SECAPI
313 }
314
315 OSStatus
316 SecCertificateReleaseFirstFieldValue(SecCertificateRef certificate, const CSSM_OID *field, CSSM_DATA_PTR fieldValue)
317 {
318 BEGIN_SECAPI
319
320 Certificate::required(certificate)->releaseFieldValue(Required(field), fieldValue);
321
322 END_SECAPI
323 }
324
325 OSStatus
326 SecCertificateFindByIssuerAndSN(CFTypeRef keychainOrArray,const CSSM_DATA *issuer,
327 const CSSM_DATA *serialNumber, SecCertificateRef *certificate)
328 {
329 BEGIN_SECAPI
330
331 StorageManager::KeychainList keychains;
332 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
333 Required(certificate) = Certificate::findByIssuerAndSN(keychains, CssmData::required(issuer), CssmData::required(serialNumber))->handle();
334
335 END_SECAPI
336 }
337
338 OSStatus
339 SecCertificateFindBySubjectKeyID(CFTypeRef keychainOrArray, const CSSM_DATA *subjectKeyID,
340 SecCertificateRef *certificate)
341 {
342 BEGIN_SECAPI
343
344 StorageManager::KeychainList keychains;
345 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
346 Required(certificate) = Certificate::findBySubjectKeyID(keychains, CssmData::required(subjectKeyID))->handle();
347
348 END_SECAPI
349 }
350
351 OSStatus
352 SecCertificateFindByEmail(CFTypeRef keychainOrArray, const char *emailAddress, SecCertificateRef *certificate)
353 {
354 BEGIN_SECAPI
355
356 StorageManager::KeychainList keychains;
357 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
358 Required(certificate) = Certificate::findByEmail(keychains, emailAddress)->handle();
359
360 END_SECAPI
361 }
362
363 OSStatus
364 SecKeychainSearchCreateForCertificateByIssuerAndSN(CFTypeRef keychainOrArray, const CSSM_DATA *issuer,
365 const CSSM_DATA *serialNumber, SecKeychainSearchRef *searchRef)
366 {
367 BEGIN_SECAPI
368
369 Required(searchRef);
370
371 StorageManager::KeychainList keychains;
372 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
373 KCCursor cursor(Certificate::cursorForIssuerAndSN(keychains, CssmData::required(issuer), CssmData::required(serialNumber)));
374 *searchRef = cursor->handle();
375
376 END_SECAPI
377 }
378
379 OSStatus
380 SecKeychainSearchCreateForCertificateByIssuerAndSN_CF(CFTypeRef keychainOrArray, CFDataRef issuer,
381 CFDataRef serialNumber, SecKeychainSearchRef *searchRef)
382 {
383 BEGIN_SECAPI
384
385 Required(searchRef);
386
387 StorageManager::KeychainList keychains;
388 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
389 Required(issuer);
390 Required(serialNumber);
391 KCCursor cursor(Certificate::cursorForIssuerAndSN_CF(keychains, issuer, serialNumber));
392 *searchRef = cursor->handle();
393
394 END_SECAPI
395 }
396
397 OSStatus
398 SecKeychainSearchCreateForCertificateBySubjectKeyID(CFTypeRef keychainOrArray, const CSSM_DATA *subjectKeyID,
399 SecKeychainSearchRef *searchRef)
400 {
401 BEGIN_SECAPI
402
403 Required(searchRef);
404
405 StorageManager::KeychainList keychains;
406 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
407 KCCursor cursor(Certificate::cursorForSubjectKeyID(keychains, CssmData::required(subjectKeyID)));
408 *searchRef = cursor->handle();
409
410 END_SECAPI
411 }
412
413 OSStatus
414 SecKeychainSearchCreateForCertificateByEmail(CFTypeRef keychainOrArray, const char *emailAddress,
415 SecKeychainSearchRef *searchRef)
416 {
417 BEGIN_SECAPI
418
419 Required(searchRef);
420
421 StorageManager::KeychainList keychains;
422 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
423 KCCursor cursor(Certificate::cursorForEmail(keychains, emailAddress));
424 *searchRef = cursor->handle();
425
426 END_SECAPI
427 }
428
429 /* NOT EXPORTED YET; copied from SecurityInterface but could be useful in the future.
430 CSSM_CSP_HANDLE
431 SecGetAppleCSPHandle()
432 {
433 BEGIN_SECAPI
434 return CSP(gGuidAppleCSP)->handle();
435 END_SECAPI1(NULL);
436 }
437
438 CSSM_CL_HANDLE
439 SecGetAppleCLHandle()
440 {
441 BEGIN_SECAPI
442 return CL(gGuidAppleX509CL)->handle();
443 END_SECAPI1(NULL);
444 }
445 */
446
447 CSSM_RETURN
448 SecDigestGetData (CSSM_ALGORITHMS alg, CSSM_DATA* digest, const CSSM_DATA* data)
449 {
450 BEGIN_SECAPI
451 // sanity checking
452 if (!digest || !digest->Data || !digest->Length || !data || !data->Data || !data->Length)
453 return paramErr;
454
455 CSP csp(gGuidAppleCSP);
456 Digest context(csp, alg);
457 CssmData input(data->Data, data->Length);
458 CssmData output(digest->Data, digest->Length);
459
460 context.digest(input, output);
461 digest->Length = output.length();
462
463 return CSSM_OK;
464 END_SECAPI1(1);
465 }
466
467 /* determine whether a cert is self-signed */
468 OSStatus SecCertificateIsSelfSigned(
469 SecCertificateRef certificate,
470 Boolean *isSelfSigned) /* RETURNED */
471 {
472 BEGIN_SECAPI
473
474 *isSelfSigned = Certificate::required(certificate)->isSelfSigned();
475
476 END_SECAPI
477 }
478
479 OSStatus
480 SecCertificateCopyPreference(
481 CFStringRef name,
482 CSSM_KEYUSE keyUsage,
483 SecCertificateRef *certificate)
484 {
485 BEGIN_SECAPI
486
487 Required(name);
488 Required(certificate);
489 StorageManager::KeychainList keychains;
490 globals().storageManager.getSearchList(keychains);
491 KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL);
492
493 char idUTF8[MAXPATHLEN];
494 if (!CFStringGetCString(name, idUTF8, sizeof(idUTF8)-1, kCFStringEncodingUTF8))
495 idUTF8[0] = (char)'\0';
496 CssmData service(const_cast<char *>(idUTF8), strlen(idUTF8));
497 FourCharCode itemType = 'cprf';
498 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service);
499 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), itemType);
500 if (keyUsage)
501 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage);
502
503 Item prefItem;
504 if (!cursor->next(prefItem))
505 MacOSError::throwMe(errSecItemNotFound);
506
507 // get persistent certificate reference
508 SecKeychainAttribute itemAttrs[] = { { kSecGenericItemAttr, 0, NULL } };
509 SecKeychainAttributeList itemAttrList = { sizeof(itemAttrs) / sizeof(itemAttrs[0]), itemAttrs };
510 prefItem->getContent(NULL, &itemAttrList, NULL, NULL);
511
512 // find certificate, given persistent reference data
513 CFDataRef pItemRef = CFDataCreateWithBytesNoCopy(NULL, (const UInt8 *)itemAttrs[0].data, itemAttrs[0].length, kCFAllocatorNull);
514 SecKeychainItemRef certItemRef = nil;
515 OSStatus status = SecKeychainItemCopyFromPersistentReference(pItemRef, &certItemRef); //%%% need to make this a method of ItemImpl
516 prefItem->freeContent(&itemAttrList, NULL);
517 if (pItemRef)
518 CFRelease(pItemRef);
519 if (status)
520 return status;
521
522 *certificate = (SecCertificateRef)certItemRef;
523
524 END_SECAPI
525 }
526
527 SecCertificateRef
528 SecCertificateCopyPreferred(
529 CFStringRef name,
530 CFArrayRef keyUsage)
531 {
532 // This function will look for a matching preference in the following order:
533 // - matches the name and the supplied key use
534 // - matches the name and the special 'ANY' key use
535 // - matches the name with no key usage constraint
536
537 SecCertificateRef certRef = NULL;
538 CSSM_KEYUSE keyUse = ConvertArrayToKeyUsage(keyUsage);
539 OSStatus status = SecCertificateCopyPreference(name, keyUse, &certRef);
540 if (status != noErr && keyUse != CSSM_KEYUSE_ANY)
541 status = SecCertificateCopyPreference(name, CSSM_KEYUSE_ANY, &certRef);
542 if (status != noErr && keyUse != 0)
543 status = SecCertificateCopyPreference(name, 0, &certRef);
544
545 return certRef;
546 }
547
548 OSStatus
549 SecCertificateFindPreferenceItemWithNameAndKeyUsage(
550 CFTypeRef keychainOrArray,
551 CFStringRef name,
552 int32_t keyUsage,
553 SecKeychainItemRef *itemRef)
554 {
555 BEGIN_SECAPI
556
557 StorageManager::KeychainList keychains;
558 globals().storageManager.optionalSearchList(keychainOrArray, keychains);
559 KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL);
560
561 char idUTF8[MAXPATHLEN];
562 idUTF8[0] = (char)'\0';
563 if (name)
564 {
565 if (!CFStringGetCString(name, idUTF8, sizeof(idUTF8)-1, kCFStringEncodingUTF8))
566 idUTF8[0] = (char)'\0';
567 }
568 size_t idUTF8Len = strlen(idUTF8);
569 if (!idUTF8Len)
570 MacOSError::throwMe(paramErr);
571
572 CssmData service(const_cast<char *>(idUTF8), idUTF8Len);
573 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service);
574 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), (FourCharCode)'cprf');
575 if (keyUsage)
576 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage);
577
578 Item item;
579 if (!cursor->next(item))
580 MacOSError::throwMe(errSecItemNotFound);
581
582 if (itemRef)
583 *itemRef=item->handle();
584
585 END_SECAPI
586 }
587
588 OSStatus SecCertificateDeletePreferenceItemWithNameAndKeyUsage(
589 CFTypeRef keychainOrArray,
590 CFStringRef name,
591 int32_t keyUsage)
592 {
593 // when a specific key usage is passed, we'll only match & delete that pref;
594 // when a key usage of 0 is passed, all matching prefs should be deleted.
595 // maxUsages represents the most matches there could theoretically be, so
596 // cut things off at that point if we're still finding items (if they can't
597 // be deleted for some reason, we'd never break out of the loop.)
598
599 OSStatus status;
600 SecKeychainItemRef item = NULL;
601 int count = 0, maxUsages = 12;
602 while (++count <= maxUsages &&
603 (status = SecCertificateFindPreferenceItemWithNameAndKeyUsage(keychainOrArray, name, keyUsage, &item)) == noErr) {
604 status = SecKeychainItemDelete(item);
605 CFRelease(item);
606 item = NULL;
607 }
608
609 // it's not an error if the item isn't found
610 return (status == errSecItemNotFound) ? noErr : status;
611 }
612
613 OSStatus SecCertificateSetPreference(
614 SecCertificateRef certificate,
615 CFStringRef name,
616 CSSM_KEYUSE keyUsage,
617 CFDateRef date)
618 {
619 if (!name) {
620 return paramErr;
621 }
622 if (!certificate) {
623 // treat NULL certificate as a request to clear the preference
624 // (note: if keyUsage is 0, this clears all key usage prefs for name)
625 return SecCertificateDeletePreferenceItemWithNameAndKeyUsage(NULL, name, keyUsage);
626 }
627
628 BEGIN_SECAPI
629
630 // determine the account attribute
631 //
632 // This attribute must be synthesized from certificate label + pref item type + key usage,
633 // as only the account and service attributes can make a generic keychain item unique.
634 // For 'iprf' type items (but not 'cprf'), we append a trailing space. This insures that
635 // we can save a certificate preference if an identity preference already exists for the
636 // given service name, and vice-versa.
637 // If the key usage is 0 (i.e. the normal case), we omit the appended key usage string.
638 //
639 CFStringRef labelStr = nil;
640 Certificate::required(certificate)->inferLabel(false, &labelStr);
641 if (!labelStr) {
642 MacOSError::throwMe(errSecDataTooLarge); // data is "in a format which cannot be displayed"
643 }
644 CFIndex accountUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(labelStr), kCFStringEncodingUTF8) + 1;
645 const char *templateStr = "%s [key usage 0x%X]";
646 const int keyUsageMaxStrLen = 8;
647 accountUTF8Len += strlen(templateStr) + keyUsageMaxStrLen;
648 char accountUTF8[accountUTF8Len];
649 if (!CFStringGetCString(labelStr, accountUTF8, accountUTF8Len-1, kCFStringEncodingUTF8))
650 accountUTF8[0] = (char)'\0';
651 if (keyUsage)
652 snprintf(accountUTF8, accountUTF8Len-1, templateStr, accountUTF8, keyUsage);
653 CssmData account(const_cast<char *>(accountUTF8), strlen(accountUTF8));
654 CFRelease(labelStr);
655
656 // service attribute (name provided by the caller)
657 CFIndex serviceUTF8Len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(name), kCFStringEncodingUTF8) + 1;;
658 char serviceUTF8[serviceUTF8Len];
659 if (!CFStringGetCString(name, serviceUTF8, serviceUTF8Len-1, kCFStringEncodingUTF8))
660 serviceUTF8[0] = (char)'\0';
661 CssmData service(const_cast<char *>(serviceUTF8), strlen(serviceUTF8));
662
663 // look for existing preference item, in case this is an update
664 StorageManager::KeychainList keychains;
665 globals().storageManager.getSearchList(keychains);
666 KCCursor cursor(keychains, kSecGenericPasswordItemClass, NULL);
667 FourCharCode itemType = 'cprf';
668 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecServiceItemAttr), service);
669 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecTypeItemAttr), itemType);
670 if (keyUsage)
671 cursor->add(CSSM_DB_EQUAL, Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage);
672 if (date)
673 ; // %%%TBI
674
675 Item item(kSecGenericPasswordItemClass, 'aapl', 0, NULL, false);
676 bool add = (!cursor->next(item));
677 // at this point, we either have a new item to add or an existing item to update
678
679 // set item attribute values
680 item->setAttribute(Schema::attributeInfo(kSecServiceItemAttr), service);
681 item->setAttribute(Schema::attributeInfo(kSecTypeItemAttr), itemType);
682 item->setAttribute(Schema::attributeInfo(kSecAccountItemAttr), account);
683 item->setAttribute(Schema::attributeInfo(kSecScriptCodeItemAttr), (sint32)keyUsage);
684 item->setAttribute(Schema::attributeInfo(kSecLabelItemAttr), service);
685
686 // date
687 if (date)
688 ; // %%%TBI
689
690 // generic attribute (store persistent certificate reference)
691 CFDataRef pItemRef = nil;
692 Certificate::required(certificate)->copyPersistentReference(pItemRef);
693 if (!pItemRef) {
694 MacOSError::throwMe(errSecInvalidItemRef);
695 }
696 const UInt8 *dataPtr = CFDataGetBytePtr(pItemRef);
697 CFIndex dataLen = CFDataGetLength(pItemRef);
698 CssmData pref(const_cast<void *>(reinterpret_cast<const void *>(dataPtr)), dataLen);
699 item->setAttribute(Schema::attributeInfo(kSecGenericItemAttr), pref);
700 CFRelease(pItemRef);
701
702 if (add) {
703 Keychain keychain = nil;
704 try {
705 keychain = globals().storageManager.defaultKeychain();
706 if (!keychain->exists())
707 MacOSError::throwMe(errSecNoSuchKeychain); // Might be deleted or not available at this time.
708 }
709 catch(...) {
710 keychain = globals().storageManager.defaultKeychainUI(item);
711 }
712
713 try {
714 keychain->add(item);
715 }
716 catch (const MacOSError &err) {
717 if (err.osStatus() != errSecDuplicateItem)
718 throw; // if item already exists, fall through to update
719 }
720 }
721 item->update();
722
723 END_SECAPI
724 }
725
726 OSStatus SecCertificateSetPreferred(
727 SecCertificateRef certificate,
728 CFStringRef name,
729 CFArrayRef keyUsage)
730 {
731 CSSM_KEYUSE keyUse = ConvertArrayToKeyUsage(keyUsage);
732 return SecCertificateSetPreference(certificate, name, keyUse, NULL);
733 }
734
735 CFDictionaryRef SecCertificateCopyValues(SecCertificateRef certificate, CFArrayRef keys, CFErrorRef *error)
736 {
737 CFDictionaryRef result = NULL;
738 OSStatus __secapiresult;
739 try
740 {
741 CertificateValues cv(certificate);
742 result = cv.copyFieldValues(keys,error);
743 __secapiresult=0;
744 }
745 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
746 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
747 catch (const std::bad_alloc &) { __secapiresult=memFullErr; }
748 catch (...) { __secapiresult=internalComponentErr; }
749 return result;
750 }
751
752 CFStringRef SecCertificateCopyLongDescription(CFAllocatorRef alloc, SecCertificateRef certificate, CFErrorRef *error)
753 {
754 return SecCertificateCopyShortDescription(alloc, certificate, error);
755 }
756
757 CFStringRef SecCertificateCopyShortDescription(CFAllocatorRef alloc, SecCertificateRef certificate, CFErrorRef *error)
758 {
759 CFStringRef result = NULL;
760 OSStatus __secapiresult;
761 try
762 {
763 __secapiresult = SecCertificateInferLabel(certificate, &result);
764 }
765 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
766 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
767 catch (const std::bad_alloc &) { __secapiresult=memFullErr; }
768 catch (...) { __secapiresult=internalComponentErr; }
769 if (error!=NULL && __secapiresult!=noErr)
770 {
771 *error = CFErrorCreate(kCFAllocatorDefault, kCFErrorDomainOSStatus,
772 __secapiresult ? __secapiresult : CSSM_ERRCODE_INTERNAL_ERROR, NULL);
773 }
774 return result;
775 }
776
777 CFDataRef SecCertificateCopySerialNumber(SecCertificateRef certificate, CFErrorRef *error)
778 {
779 CFDataRef result = NULL;
780 OSStatus __secapiresult;
781 try
782 {
783 CertificateValues cv(certificate);
784 result = cv.copySerialNumber(error);
785 __secapiresult=0;
786 }
787 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
788 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
789 catch (const std::bad_alloc &) { __secapiresult=memFullErr; }
790 catch (...) { __secapiresult=internalComponentErr; }
791 return result;
792 }
793
794 CFDataRef SecCertificateCopyNormalizedIssuerContent(SecCertificateRef certificate, CFErrorRef *error)
795 {
796 CFDataRef result = NULL;
797 OSStatus __secapiresult;
798 try
799 {
800 CertificateValues cv(certificate);
801 result = cv.getNormalizedIssuerContent(error);
802 __secapiresult=0;
803 }
804 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
805 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
806 catch (const std::bad_alloc &) { __secapiresult=memFullErr; }
807 catch (...) { __secapiresult=internalComponentErr; }
808 return result;
809 }
810
811 CFDataRef SecCertificateCopyNormalizedSubjectContent(SecCertificateRef certificate, CFErrorRef *error)
812 {
813 CFDataRef result = NULL;
814 OSStatus __secapiresult;
815 try
816 {
817 CertificateValues cv(certificate);
818 result = cv.getNormalizedSubjectContent(error);
819 __secapiresult=0;
820 }
821 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
822 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
823 catch (const std::bad_alloc &) { __secapiresult=memFullErr; }
824 catch (...) { __secapiresult=internalComponentErr; }
825 return result;
826 }
827
828 bool SecCertificateIsValidX(SecCertificateRef certificate, CFAbsoluteTime verifyTime)
829 {
830 bool result = NULL;
831 OSStatus __secapiresult;
832 try
833 {
834 CFErrorRef error = NULL;
835 CertificateValues cv(certificate);
836 result = cv.SecCertificateIsValidX(verifyTime, &error);
837 __secapiresult=0;
838 }
839 catch (const MacOSError &err) { __secapiresult=err.osStatus(); }
840 catch (const CommonError &err) { __secapiresult=SecKeychainErrFromOSStatus(err.osStatus()); }
841 catch (const std::bad_alloc &) { __secapiresult=memFullErr; }
842 catch (...) { __secapiresult=internalComponentErr; }
843 return result;
844 }
845
846 /* new in 10.8 */
847 SecCertificateRef SecCertificateCreateWithBytes(CFAllocatorRef allocator,
848 const UInt8 *bytes, CFIndex length)
849 {
850 SecCertificateRef certificate = NULL;
851 OSStatus __secapiresult;
852 try {
853 CSSM_DATA cssmCertData = { (CSSM_SIZE)length, (uint8 *)bytes };
854
855 //NOTE: there isn't yet a Certificate constructor which accepts a CFAllocatorRef
856 SecPointer<Certificate> certificatePtr(new Certificate(cssmCertData, CSSM_CERT_X_509v3, CSSM_CERT_ENCODING_DER));
857 certificate = certificatePtr->handle();
858
859 __secapiresult=noErr;
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=memFullErr; }
864 catch (...) { __secapiresult=internalComponentErr; }
865 return certificate;
866 }
867
868 /* new in 10.8 */
869 CFIndex SecCertificateGetLength(SecCertificateRef certificate)
870 {
871 CFIndex length = 0;
872 OSStatus __secapiresult;
873 try {
874 CssmData output = Certificate::required(certificate)->data();
875 length = (CFIndex)output.length();
876 __secapiresult=noErr;
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=memFullErr; }
881 catch (...) { __secapiresult=internalComponentErr; }
882 return length;
883 }
884
885 /* new in 10.8 */
886 const UInt8 *SecCertificateGetBytePtr(SecCertificateRef certificate)
887 {
888 const UInt8 *bytes = NULL;
889 OSStatus __secapiresult;
890 try {
891 CssmData output = Certificate::required(certificate)->data();
892 bytes = (const UInt8 *)output.data();
893 __secapiresult=noErr;
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=memFullErr; }
898 catch (...) { __secapiresult=internalComponentErr; }
899 return bytes;
900 }
901