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