Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/ssl/ssl_platform_key.h" | 5 #include "net/ssl/ssl_platform_key_mac.h" |
| 6 | 6 |
| 7 #include <dlfcn.h> | |
| 8 #include <CoreFoundation/CoreFoundation.h> | |
| 7 #include <Security/cssm.h> | 9 #include <Security/cssm.h> |
| 8 #include <Security/SecBase.h> | 10 #include <Security/SecBase.h> |
| 9 #include <Security/SecCertificate.h> | 11 #include <Security/SecCertificate.h> |
| 10 #include <Security/SecIdentity.h> | 12 #include <Security/SecIdentity.h> |
| 11 #include <Security/SecKey.h> | 13 #include <Security/SecKey.h> |
| 12 | 14 |
| 13 #include <memory> | 15 #include <memory> |
| 14 | 16 |
| 17 #include "base/lazy_instance.h" | |
| 15 #include "base/location.h" | 18 #include "base/location.h" |
| 16 #include "base/logging.h" | 19 #include "base/logging.h" |
| 20 #include "base/mac/foundation_util.h" | |
| 17 #include "base/mac/mac_logging.h" | 21 #include "base/mac/mac_logging.h" |
| 22 #include "base/mac/mac_util.h" | |
| 18 #include "base/mac/scoped_cftyperef.h" | 23 #include "base/mac/scoped_cftyperef.h" |
| 19 #include "base/macros.h" | 24 #include "base/macros.h" |
| 20 #include "base/memory/ptr_util.h" | 25 #include "base/memory/ptr_util.h" |
| 21 #include "base/memory/scoped_policy.h" | 26 #include "base/memory/scoped_policy.h" |
| 27 #include "base/numerics/safe_conversions.h" | |
| 22 #include "base/synchronization/lock.h" | 28 #include "base/synchronization/lock.h" |
| 23 #include "crypto/mac_security_services_lock.h" | 29 #include "crypto/mac_security_services_lock.h" |
| 24 #include "crypto/openssl_util.h" | 30 #include "crypto/openssl_util.h" |
| 25 #include "net/base/net_errors.h" | 31 #include "net/base/net_errors.h" |
| 26 #include "net/cert/x509_certificate.h" | 32 #include "net/cert/x509_certificate.h" |
| 33 #include "net/ssl/ssl_platform_key.h" | |
| 27 #include "net/ssl/ssl_platform_key_util.h" | 34 #include "net/ssl/ssl_platform_key_util.h" |
| 28 #include "net/ssl/ssl_private_key.h" | 35 #include "net/ssl/ssl_private_key.h" |
| 29 #include "net/ssl/threaded_ssl_private_key.h" | 36 #include "net/ssl/threaded_ssl_private_key.h" |
| 30 #include "third_party/boringssl/src/include/openssl/ecdsa.h" | 37 #include "third_party/boringssl/src/include/openssl/ecdsa.h" |
| 31 #include "third_party/boringssl/src/include/openssl/mem.h" | 38 #include "third_party/boringssl/src/include/openssl/mem.h" |
| 32 #include "third_party/boringssl/src/include/openssl/nid.h" | 39 #include "third_party/boringssl/src/include/openssl/nid.h" |
| 33 #include "third_party/boringssl/src/include/openssl/rsa.h" | 40 #include "third_party/boringssl/src/include/openssl/rsa.h" |
| 34 | 41 |
| 42 // TODO(davidben): Remove this after https://crbug.com/669240 is fixed. | |
| 43 #if !defined(MAC_OS_X_VERSION_10_12) || \ | |
| 44 MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12 | |
| 45 typedef CFStringRef SecKeyAlgorithm; | |
| 46 #endif | |
| 47 | |
| 35 namespace net { | 48 namespace net { |
| 36 | 49 |
| 37 // CSSM functions are deprecated as of OSX 10.7, but have no replacement. | 50 // CSSM functions are deprecated as of OSX 10.7, but have no replacement. |
| 38 // https://bugs.chromium.org/p/chromium/issues/detail?id=590914#c1 | 51 // https://bugs.chromium.org/p/chromium/issues/detail?id=590914#c1 |
| 39 #pragma clang diagnostic push | 52 #pragma clang diagnostic push |
| 40 #pragma clang diagnostic ignored "-Wdeprecated-declarations" | 53 #pragma clang diagnostic ignored "-Wdeprecated-declarations" |
| 41 | 54 |
| 42 namespace { | 55 namespace { |
| 43 | 56 |
| 44 class ScopedCSSM_CC_HANDLE { | 57 class ScopedCSSM_CC_HANDLE { |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 55 CSSM_DeleteContext(handle_); | 68 CSSM_DeleteContext(handle_); |
| 56 handle_ = 0; | 69 handle_ = 0; |
| 57 } | 70 } |
| 58 | 71 |
| 59 private: | 72 private: |
| 60 CSSM_CC_HANDLE handle_; | 73 CSSM_CC_HANDLE handle_; |
| 61 | 74 |
| 62 DISALLOW_COPY_AND_ASSIGN(ScopedCSSM_CC_HANDLE); | 75 DISALLOW_COPY_AND_ASSIGN(ScopedCSSM_CC_HANDLE); |
| 63 }; | 76 }; |
| 64 | 77 |
| 65 // Looks up the private key for |certificate| in KeyChain and returns | 78 // Looks up the private key for |certificate| in |keychain| and returns |
| 66 // a SecKeyRef or nullptr on failure. The caller takes ownership of the | 79 // a SecKeyRef or nullptr on failure. The caller takes ownership of the |
| 67 // result. | 80 // result. |
| 68 SecKeyRef FetchSecKeyRefForCertificate(const X509Certificate* certificate) { | 81 SecKeyRef FetchSecKeyRefForCertificate(const X509Certificate* certificate, |
| 82 SecKeychainRef keychain) { | |
| 69 OSStatus status; | 83 OSStatus status; |
| 70 base::ScopedCFTypeRef<SecIdentityRef> identity; | 84 base::ScopedCFTypeRef<SecIdentityRef> identity; |
| 71 { | 85 { |
| 72 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); | 86 base::AutoLock lock(crypto::GetMacSecurityServicesLock()); |
| 73 status = SecIdentityCreateWithCertificate( | 87 status = SecIdentityCreateWithCertificate( |
| 74 nullptr, certificate->os_cert_handle(), identity.InitializeInto()); | 88 keychain, certificate->os_cert_handle(), identity.InitializeInto()); |
| 75 } | 89 } |
| 76 if (status != noErr) { | 90 if (status != noErr) { |
| 77 OSSTATUS_LOG(WARNING, status); | 91 OSSTATUS_LOG(WARNING, status); |
| 78 return nullptr; | 92 return nullptr; |
| 79 } | 93 } |
| 80 | 94 |
| 81 base::ScopedCFTypeRef<SecKeyRef> private_key; | 95 base::ScopedCFTypeRef<SecKeyRef> private_key; |
| 82 status = SecIdentityCopyPrivateKey(identity, private_key.InitializeInto()); | 96 status = SecIdentityCopyPrivateKey(identity, private_key.InitializeInto()); |
| 83 if (status != noErr) { | 97 if (status != noErr) { |
| 84 OSSTATUS_LOG(WARNING, status); | 98 OSSTATUS_LOG(WARNING, status); |
| 85 return nullptr; | 99 return nullptr; |
| 86 } | 100 } |
| 87 | 101 |
| 88 return private_key.release(); | 102 return private_key.release(); |
| 89 } | 103 } |
| 90 | 104 |
| 91 class SSLPlatformKeyMac : public ThreadedSSLPrivateKey::Delegate { | 105 // These symbols were added in the 10.12 SDK, but we currently use an older SDK, |
| 106 // so look them up with dlsym. | |
| 107 // | |
| 108 // TODO(davidben): After https://crbug.com/669240 is fixed, use the APIs | |
| 109 // directly. | |
| 110 struct SecKeyAPIs { | |
| 111 SecKeyAPIs() { Init(); } | |
| 112 | |
| 113 void Init() { | |
| 114 SecKeyCreateSignature = reinterpret_cast<SecKeyCreateSignatureFunc>( | |
| 115 dlsym(RTLD_DEFAULT, "SecKeyCreateSignature")); | |
| 116 if (!SecKeyCreateSignature) { | |
| 117 NOTREACHED(); | |
| 118 return; | |
| 119 } | |
| 120 | |
| 121 #define LOOKUP_ALGORITHM(name) \ | |
| 122 do { \ | |
| 123 SecKeyAlgorithm* algorithm = \ | |
| 124 reinterpret_cast<SecKeyAlgorithm*>(dlsym(RTLD_DEFAULT, #name)); \ | |
| 125 if (!algorithm) { \ | |
| 126 NOTREACHED(); \ | |
| 127 return; \ | |
|
Ryan Sleevi
2016/12/13 22:21:07
Is it really fatal if these can't be looked up?
davidben
2016/12/14 00:59:43
If it happens, we got the version check wrong. I t
| |
| 128 } \ | |
| 129 name = *algorithm; \ | |
| 130 } while (0) | |
| 131 | |
| 132 LOOKUP_ALGORITHM(kSecKeyAlgorithmRSASignatureDigestPKCS1v15Raw); | |
| 133 LOOKUP_ALGORITHM(kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1); | |
| 134 LOOKUP_ALGORITHM(kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256); | |
| 135 LOOKUP_ALGORITHM(kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384); | |
| 136 LOOKUP_ALGORITHM(kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512); | |
| 137 LOOKUP_ALGORITHM(kSecKeyAlgorithmECDSASignatureDigestX962SHA1); | |
| 138 LOOKUP_ALGORITHM(kSecKeyAlgorithmECDSASignatureDigestX962SHA256); | |
| 139 LOOKUP_ALGORITHM(kSecKeyAlgorithmECDSASignatureDigestX962SHA384); | |
| 140 LOOKUP_ALGORITHM(kSecKeyAlgorithmECDSASignatureDigestX962SHA512); | |
| 141 | |
| 142 #undef LOOKUP_ALGORITHM | |
| 143 | |
| 144 valid = true; | |
| 145 } | |
| 146 | |
| 147 using SecKeyCreateSignatureFunc = CFDataRef (*)(SecKeyRef key, | |
| 148 SecKeyAlgorithm algorithm, | |
| 149 CFDataRef dataToSign, | |
| 150 CFErrorRef* error); | |
| 151 | |
| 152 bool valid = false; | |
| 153 SecKeyCreateSignatureFunc SecKeyCreateSignature = NULL; | |
|
Ryan Sleevi
2016/12/13 22:21:07
nullptr?
davidben
2016/12/14 00:59:43
Done.
| |
| 154 SecKeyAlgorithm kSecKeyAlgorithmRSASignatureDigestPKCS1v15Raw = NULL; | |
| 155 SecKeyAlgorithm kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1 = NULL; | |
| 156 SecKeyAlgorithm kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256 = NULL; | |
| 157 SecKeyAlgorithm kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384 = NULL; | |
| 158 SecKeyAlgorithm kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512 = NULL; | |
| 159 SecKeyAlgorithm kSecKeyAlgorithmECDSASignatureDigestX962SHA1 = NULL; | |
| 160 SecKeyAlgorithm kSecKeyAlgorithmECDSASignatureDigestX962SHA256 = NULL; | |
| 161 SecKeyAlgorithm kSecKeyAlgorithmECDSASignatureDigestX962SHA384 = NULL; | |
| 162 SecKeyAlgorithm kSecKeyAlgorithmECDSASignatureDigestX962SHA512 = NULL; | |
| 163 }; | |
| 164 | |
| 165 base::LazyInstance<SecKeyAPIs>::Leaky g_sec_key_apis = | |
| 166 LAZY_INSTANCE_INITIALIZER; | |
| 167 | |
| 168 class SSLPlatformKeyCSSM : public ThreadedSSLPrivateKey::Delegate { | |
| 92 public: | 169 public: |
| 93 SSLPlatformKeyMac(SSLPrivateKey::Type type, | 170 SSLPlatformKeyCSSM(SSLPrivateKey::Type type, |
| 94 size_t max_length, | 171 size_t max_length, |
| 95 SecKeyRef key, | 172 SecKeyRef key, |
| 96 const CSSM_KEY* cssm_key) | 173 const CSSM_KEY* cssm_key) |
| 97 : type_(type), | 174 : type_(type), |
| 98 max_length_(max_length), | 175 max_length_(max_length), |
| 99 key_(key, base::scoped_policy::RETAIN), | 176 key_(key, base::scoped_policy::RETAIN), |
| 100 cssm_key_(cssm_key) {} | 177 cssm_key_(cssm_key) {} |
| 101 | 178 |
| 102 ~SSLPlatformKeyMac() override {} | 179 ~SSLPlatformKeyCSSM() override {} |
| 103 | 180 |
| 104 SSLPrivateKey::Type GetType() override { return type_; } | 181 SSLPrivateKey::Type GetType() override { return type_; } |
| 105 | 182 |
| 106 std::vector<SSLPrivateKey::Hash> GetDigestPreferences() override { | 183 std::vector<SSLPrivateKey::Hash> GetDigestPreferences() override { |
| 107 static const SSLPrivateKey::Hash kHashes[] = { | 184 static const SSLPrivateKey::Hash kHashes[] = { |
| 108 SSLPrivateKey::Hash::SHA512, SSLPrivateKey::Hash::SHA384, | 185 SSLPrivateKey::Hash::SHA512, SSLPrivateKey::Hash::SHA384, |
| 109 SSLPrivateKey::Hash::SHA256, SSLPrivateKey::Hash::SHA1}; | 186 SSLPrivateKey::Hash::SHA256, SSLPrivateKey::Hash::SHA1}; |
| 110 return std::vector<SSLPrivateKey::Hash>(kHashes, | 187 return std::vector<SSLPrivateKey::Hash>(kHashes, |
| 111 kHashes + arraysize(kHashes)); | 188 kHashes + arraysize(kHashes)); |
| 112 } | 189 } |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 199 signature->resize(signature_data.Length); | 276 signature->resize(signature_data.Length); |
| 200 return OK; | 277 return OK; |
| 201 } | 278 } |
| 202 | 279 |
| 203 private: | 280 private: |
| 204 SSLPrivateKey::Type type_; | 281 SSLPrivateKey::Type type_; |
| 205 size_t max_length_; | 282 size_t max_length_; |
| 206 base::ScopedCFTypeRef<SecKeyRef> key_; | 283 base::ScopedCFTypeRef<SecKeyRef> key_; |
| 207 const CSSM_KEY* cssm_key_; | 284 const CSSM_KEY* cssm_key_; |
| 208 | 285 |
| 209 DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyMac); | 286 DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyCSSM); |
| 287 }; | |
| 288 | |
| 289 class SSLPlatformKeySecKey : public ThreadedSSLPrivateKey::Delegate { | |
| 290 public: | |
| 291 SSLPlatformKeySecKey(SSLPrivateKey::Type type, | |
| 292 size_t max_length, | |
| 293 SecKeyRef key) | |
| 294 : type_(type), | |
| 295 max_length_(max_length), | |
| 296 key_(key, base::scoped_policy::RETAIN) {} | |
| 297 | |
| 298 ~SSLPlatformKeySecKey() override {} | |
| 299 | |
| 300 SSLPrivateKey::Type GetType() override { return type_; } | |
| 301 | |
| 302 std::vector<SSLPrivateKey::Hash> GetDigestPreferences() override { | |
| 303 static const SSLPrivateKey::Hash kHashes[] = { | |
| 304 SSLPrivateKey::Hash::SHA512, SSLPrivateKey::Hash::SHA384, | |
| 305 SSLPrivateKey::Hash::SHA256, SSLPrivateKey::Hash::SHA1}; | |
| 306 return std::vector<SSLPrivateKey::Hash>(kHashes, | |
| 307 kHashes + arraysize(kHashes)); | |
|
Ryan Sleevi
2016/12/13 22:21:07
pedantry nit: Can you not std::begin(kHashes), std
davidben
2016/12/14 00:59:43
Done. (This was copy-pasted from code that predate
| |
| 308 } | |
| 309 | |
| 310 size_t GetMaxSignatureLengthInBytes() override { return max_length_; } | |
| 311 | |
| 312 Error SignDigest(SSLPrivateKey::Hash hash, | |
| 313 const base::StringPiece& input, | |
| 314 std::vector<uint8_t>* signature) override { | |
| 315 const SecKeyAPIs& apis = g_sec_key_apis.Get(); | |
| 316 if (!apis.valid) { | |
| 317 LOG(ERROR) << "SecKey APIs not found"; | |
| 318 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; | |
| 319 } | |
| 320 | |
| 321 SecKeyAlgorithm algorithm = NULL; | |
| 322 if (type_ == SSLPrivateKey::Type::RSA) { | |
| 323 switch (hash) { | |
| 324 case SSLPrivateKey::Hash::SHA512: | |
| 325 algorithm = apis.kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA512; | |
| 326 break; | |
| 327 case SSLPrivateKey::Hash::SHA384: | |
| 328 algorithm = apis.kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA384; | |
| 329 break; | |
| 330 case SSLPrivateKey::Hash::SHA256: | |
| 331 algorithm = apis.kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA256; | |
| 332 break; | |
| 333 case SSLPrivateKey::Hash::SHA1: | |
| 334 algorithm = apis.kSecKeyAlgorithmRSASignatureDigestPKCS1v15SHA1; | |
| 335 break; | |
| 336 case SSLPrivateKey::Hash::MD5_SHA1: | |
| 337 algorithm = apis.kSecKeyAlgorithmRSASignatureDigestPKCS1v15Raw; | |
| 338 break; | |
| 339 } | |
| 340 } else if (SSLPrivateKey::IsECDSAType(type_)) { | |
| 341 switch (hash) { | |
| 342 case SSLPrivateKey::Hash::SHA512: | |
| 343 algorithm = apis.kSecKeyAlgorithmECDSASignatureDigestX962SHA512; | |
| 344 break; | |
| 345 case SSLPrivateKey::Hash::SHA384: | |
| 346 algorithm = apis.kSecKeyAlgorithmECDSASignatureDigestX962SHA384; | |
| 347 break; | |
| 348 case SSLPrivateKey::Hash::SHA256: | |
| 349 algorithm = apis.kSecKeyAlgorithmECDSASignatureDigestX962SHA256; | |
| 350 break; | |
| 351 case SSLPrivateKey::Hash::SHA1: | |
| 352 algorithm = apis.kSecKeyAlgorithmECDSASignatureDigestX962SHA1; | |
| 353 break; | |
| 354 case SSLPrivateKey::Hash::MD5_SHA1: | |
| 355 // MD5-SHA1 is not used with ECDSA. | |
| 356 break; | |
| 357 } | |
| 358 } | |
| 359 | |
| 360 if (!algorithm) { | |
| 361 NOTREACHED(); | |
| 362 return ERR_FAILED; | |
| 363 } | |
| 364 | |
| 365 base::ScopedCFTypeRef<CFDataRef> input_ref(CFDataCreateWithBytesNoCopy( | |
| 366 kCFAllocatorDefault, reinterpret_cast<const uint8_t*>(input.data()), | |
| 367 base::checked_cast<CFIndex>(input.size()), kCFAllocatorNull)); | |
| 368 | |
| 369 base::ScopedCFTypeRef<CFErrorRef> error; | |
| 370 base::ScopedCFTypeRef<CFDataRef> signature_ref(apis.SecKeyCreateSignature( | |
| 371 key_, algorithm, input_ref, error.InitializeInto())); | |
| 372 if (!signature_ref) { | |
| 373 LOG(ERROR) << error; | |
| 374 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; | |
| 375 } | |
| 376 | |
| 377 signature->assign( | |
| 378 CFDataGetBytePtr(signature_ref), | |
| 379 CFDataGetBytePtr(signature_ref) + CFDataGetLength(signature_ref)); | |
| 380 return OK; | |
| 381 } | |
| 382 | |
| 383 private: | |
| 384 SSLPrivateKey::Type type_; | |
| 385 size_t max_length_; | |
| 386 base::ScopedCFTypeRef<SecKeyRef> key_; | |
| 387 | |
| 388 DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeySecKey); | |
| 210 }; | 389 }; |
| 211 | 390 |
| 212 } // namespace | 391 } // namespace |
| 213 | 392 |
| 214 scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey( | 393 scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKeyFromKeychain( |
| 215 X509Certificate* certificate) { | 394 X509Certificate* certificate, |
| 395 SecKeychainRef keychain) { | |
| 216 // Look up the private key. | 396 // Look up the private key. |
| 217 base::ScopedCFTypeRef<SecKeyRef> private_key( | 397 base::ScopedCFTypeRef<SecKeyRef> private_key( |
| 218 FetchSecKeyRefForCertificate(certificate)); | 398 FetchSecKeyRefForCertificate(certificate, keychain)); |
| 219 if (!private_key) | 399 if (!private_key) |
| 220 return nullptr; | 400 return nullptr; |
| 221 | 401 |
| 402 SSLPrivateKey::Type key_type; | |
| 403 size_t max_length; | |
| 404 if (!GetClientCertInfo(certificate, &key_type, &max_length)) | |
| 405 return nullptr; | |
| 406 | |
| 407 if (base::mac::IsAtLeastOS10_12()) { | |
| 408 return make_scoped_refptr( | |
| 409 new ThreadedSSLPrivateKey(base::MakeUnique<SSLPlatformKeySecKey>( | |
| 410 key_type, max_length, private_key.get()), | |
| 411 GetSSLPlatformKeyTaskRunner())); | |
| 412 } | |
| 413 | |
| 222 const CSSM_KEY* cssm_key; | 414 const CSSM_KEY* cssm_key; |
| 223 OSStatus status = SecKeyGetCSSMKey(private_key.get(), &cssm_key); | 415 OSStatus status = SecKeyGetCSSMKey(private_key.get(), &cssm_key); |
| 224 if (status != noErr) { | 416 if (status != noErr) { |
| 225 OSSTATUS_LOG(WARNING, status); | 417 OSSTATUS_LOG(WARNING, status); |
| 226 return nullptr; | 418 return nullptr; |
| 227 } | 419 } |
| 228 | 420 |
| 229 SSLPrivateKey::Type key_type; | 421 return make_scoped_refptr(new ThreadedSSLPrivateKey( |
| 230 size_t max_length; | 422 base::MakeUnique<SSLPlatformKeyCSSM>(key_type, max_length, |
| 231 if (!GetClientCertInfo(certificate, &key_type, &max_length)) | 423 private_key.get(), cssm_key), |
| 232 return nullptr; | 424 GetSSLPlatformKeyTaskRunner())); |
| 425 } | |
| 233 | 426 |
| 234 return make_scoped_refptr(new ThreadedSSLPrivateKey( | 427 scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey( |
| 235 base::MakeUnique<SSLPlatformKeyMac>(key_type, max_length, | 428 X509Certificate* certificate) { |
| 236 private_key.get(), cssm_key), | 429 return FetchClientCertPrivateKeyFromKeychain(certificate, nullptr); |
| 237 GetSSLPlatformKeyTaskRunner())); | |
| 238 } | 430 } |
| 239 | 431 |
| 240 #pragma clang diagnostic pop // "-Wdeprecated-declarations" | 432 #pragma clang diagnostic pop // "-Wdeprecated-declarations" |
| 241 | 433 |
| 242 } // namespace net | 434 } // namespace net |
| OLD | NEW |