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.h" |
6 | 6 |
7 #include <Security/SecBase.h> | 7 #include <Security/SecBase.h> |
8 #include <Security/SecCertificate.h> | 8 #include <Security/SecCertificate.h> |
9 #include <Security/SecIdentity.h> | 9 #include <Security/SecIdentity.h> |
10 #include <Security/SecKey.h> | 10 #include <Security/SecKey.h> |
(...skipping 11 matching lines...) Expand all Loading... |
22 #include "base/mac/scoped_cftyperef.h" | 22 #include "base/mac/scoped_cftyperef.h" |
23 #include "base/macros.h" | 23 #include "base/macros.h" |
24 #include "base/memory/ptr_util.h" | 24 #include "base/memory/ptr_util.h" |
25 #include "base/memory/scoped_policy.h" | 25 #include "base/memory/scoped_policy.h" |
26 #include "base/sequenced_task_runner.h" | 26 #include "base/sequenced_task_runner.h" |
27 #include "base/synchronization/lock.h" | 27 #include "base/synchronization/lock.h" |
28 #include "crypto/mac_security_services_lock.h" | 28 #include "crypto/mac_security_services_lock.h" |
29 #include "crypto/openssl_util.h" | 29 #include "crypto/openssl_util.h" |
30 #include "net/base/net_errors.h" | 30 #include "net/base/net_errors.h" |
31 #include "net/cert/x509_certificate.h" | 31 #include "net/cert/x509_certificate.h" |
32 #include "net/ssl/ssl_platform_key_task_runner.h" | 32 #include "net/ssl/ssl_platform_key_util.h" |
33 #include "net/ssl/ssl_private_key.h" | 33 #include "net/ssl/ssl_private_key.h" |
34 #include "net/ssl/threaded_ssl_private_key.h" | 34 #include "net/ssl/threaded_ssl_private_key.h" |
35 | 35 |
36 namespace net { | 36 namespace net { |
37 | 37 |
38 // CSSM functions are deprecated as of OSX 10.7, but have no replacement. | 38 // CSSM functions are deprecated as of OSX 10.7, but have no replacement. |
39 // https://bugs.chromium.org/p/chromium/issues/detail?id=590914#c1 | 39 // https://bugs.chromium.org/p/chromium/issues/detail?id=590914#c1 |
40 #pragma clang diagnostic push | 40 #pragma clang diagnostic push |
41 #pragma clang diagnostic ignored "-Wdeprecated-declarations" | 41 #pragma clang diagnostic ignored "-Wdeprecated-declarations" |
42 | 42 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
84 if (status != noErr) { | 84 if (status != noErr) { |
85 OSSTATUS_LOG(WARNING, status); | 85 OSSTATUS_LOG(WARNING, status); |
86 return nullptr; | 86 return nullptr; |
87 } | 87 } |
88 | 88 |
89 return private_key.release(); | 89 return private_key.release(); |
90 } | 90 } |
91 | 91 |
92 class SSLPlatformKeyMac : public ThreadedSSLPrivateKey::Delegate { | 92 class SSLPlatformKeyMac : public ThreadedSSLPrivateKey::Delegate { |
93 public: | 93 public: |
94 SSLPlatformKeyMac(SecKeyRef key, const CSSM_KEY* cssm_key) | 94 SSLPlatformKeyMac(SSLPrivateKey::Type type, |
95 : key_(key, base::scoped_policy::RETAIN), cssm_key_(cssm_key) { | 95 size_t max_length, |
96 DCHECK(cssm_key_->KeyHeader.AlgorithmId == CSSM_ALGID_RSA || | 96 SecKeyRef key, |
97 cssm_key_->KeyHeader.AlgorithmId == CSSM_ALGID_ECDSA); | 97 const CSSM_KEY* cssm_key) |
98 } | 98 : type_(type), |
| 99 max_length_(max_length), |
| 100 key_(key, base::scoped_policy::RETAIN), |
| 101 cssm_key_(cssm_key) {} |
99 | 102 |
100 ~SSLPlatformKeyMac() override {} | 103 ~SSLPlatformKeyMac() override {} |
101 | 104 |
102 SSLPrivateKey::Type GetType() override { | 105 SSLPrivateKey::Type GetType() override { return type_; } |
103 if (cssm_key_->KeyHeader.AlgorithmId == CSSM_ALGID_RSA) { | |
104 return SSLPrivateKey::Type::RSA; | |
105 } else { | |
106 DCHECK_EQ(CSSM_ALGID_ECDSA, cssm_key_->KeyHeader.AlgorithmId); | |
107 return SSLPrivateKey::Type::ECDSA; | |
108 } | |
109 } | |
110 | 106 |
111 std::vector<SSLPrivateKey::Hash> GetDigestPreferences() override { | 107 std::vector<SSLPrivateKey::Hash> GetDigestPreferences() override { |
112 static const SSLPrivateKey::Hash kHashes[] = { | 108 static const SSLPrivateKey::Hash kHashes[] = { |
113 SSLPrivateKey::Hash::SHA512, SSLPrivateKey::Hash::SHA384, | 109 SSLPrivateKey::Hash::SHA512, SSLPrivateKey::Hash::SHA384, |
114 SSLPrivateKey::Hash::SHA256, SSLPrivateKey::Hash::SHA1}; | 110 SSLPrivateKey::Hash::SHA256, SSLPrivateKey::Hash::SHA1}; |
115 return std::vector<SSLPrivateKey::Hash>(kHashes, | 111 return std::vector<SSLPrivateKey::Hash>(kHashes, |
116 kHashes + arraysize(kHashes)); | 112 kHashes + arraysize(kHashes)); |
117 } | 113 } |
118 | 114 |
119 size_t GetMaxSignatureLengthInBytes() override { | 115 size_t GetMaxSignatureLengthInBytes() override { return max_length_; } |
120 if (cssm_key_->KeyHeader.AlgorithmId == CSSM_ALGID_RSA) { | |
121 return (cssm_key_->KeyHeader.LogicalKeySizeInBits + 7) / 8; | |
122 } else { | |
123 // LogicalKeySizeInBits is the size of an EC public key. But an | |
124 // ECDSA signature length depends on the size of the base point's | |
125 // order. For P-256, P-384, and P-521, these two sizes are the same. | |
126 return ECDSA_SIG_max_len((cssm_key_->KeyHeader.LogicalKeySizeInBits + 7) / | |
127 8); | |
128 } | |
129 } | |
130 | 116 |
131 Error SignDigest(SSLPrivateKey::Hash hash, | 117 Error SignDigest(SSLPrivateKey::Hash hash, |
132 const base::StringPiece& input, | 118 const base::StringPiece& input, |
133 std::vector<uint8_t>* signature) override { | 119 std::vector<uint8_t>* signature) override { |
134 crypto::OpenSSLErrStackTracer tracer(FROM_HERE); | 120 crypto::OpenSSLErrStackTracer tracer(FROM_HERE); |
135 | 121 |
136 CSSM_CSP_HANDLE csp_handle; | 122 CSSM_CSP_HANDLE csp_handle; |
137 OSStatus status = SecKeyGetCSPHandle(key_.get(), &csp_handle); | 123 OSStatus status = SecKeyGetCSPHandle(key_.get(), &csp_handle); |
138 if (status != noErr) { | 124 if (status != noErr) { |
139 OSSTATUS_LOG(WARNING, status); | 125 OSSTATUS_LOG(WARNING, status); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 CSSM_CONTEXT_ATTRIBUTE blinding_attr; | 181 CSSM_CONTEXT_ATTRIBUTE blinding_attr; |
196 blinding_attr.AttributeType = CSSM_ATTRIBUTE_RSA_BLINDING; | 182 blinding_attr.AttributeType = CSSM_ATTRIBUTE_RSA_BLINDING; |
197 blinding_attr.AttributeLength = sizeof(uint32_t); | 183 blinding_attr.AttributeLength = sizeof(uint32_t); |
198 blinding_attr.Attribute.Uint32 = 1; | 184 blinding_attr.Attribute.Uint32 = 1; |
199 if (CSSM_UpdateContextAttributes(cssm_signature.get(), 1, | 185 if (CSSM_UpdateContextAttributes(cssm_signature.get(), 1, |
200 &blinding_attr) != CSSM_OK) { | 186 &blinding_attr) != CSSM_OK) { |
201 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; | 187 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; |
202 } | 188 } |
203 } | 189 } |
204 | 190 |
205 signature->resize(GetMaxSignatureLengthInBytes()); | 191 signature->resize(max_length_); |
206 CSSM_DATA signature_data; | 192 CSSM_DATA signature_data; |
207 signature_data.Length = signature->size(); | 193 signature_data.Length = signature->size(); |
208 signature_data.Data = signature->data(); | 194 signature_data.Data = signature->data(); |
209 | 195 |
210 if (CSSM_SignData(cssm_signature.get(), &hash_data, 1, CSSM_ALGID_NONE, | 196 if (CSSM_SignData(cssm_signature.get(), &hash_data, 1, CSSM_ALGID_NONE, |
211 &signature_data) != CSSM_OK) { | 197 &signature_data) != CSSM_OK) { |
212 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; | 198 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; |
213 } | 199 } |
214 signature->resize(signature_data.Length); | 200 signature->resize(signature_data.Length); |
215 return OK; | 201 return OK; |
216 } | 202 } |
217 | 203 |
218 private: | 204 private: |
| 205 SSLPrivateKey::Type type_; |
| 206 size_t max_length_; |
219 base::ScopedCFTypeRef<SecKeyRef> key_; | 207 base::ScopedCFTypeRef<SecKeyRef> key_; |
220 const CSSM_KEY* cssm_key_; | 208 const CSSM_KEY* cssm_key_; |
221 | 209 |
222 DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyMac); | 210 DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyMac); |
223 }; | 211 }; |
224 | 212 |
225 } // namespace | 213 } // namespace |
226 | 214 |
227 scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey( | 215 scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey( |
228 X509Certificate* certificate) { | 216 X509Certificate* certificate) { |
229 // Look up the private key. | 217 // Look up the private key. |
230 base::ScopedCFTypeRef<SecKeyRef> private_key( | 218 base::ScopedCFTypeRef<SecKeyRef> private_key( |
231 FetchSecKeyRefForCertificate(certificate)); | 219 FetchSecKeyRefForCertificate(certificate)); |
232 if (!private_key) | 220 if (!private_key) |
233 return nullptr; | 221 return nullptr; |
234 | 222 |
235 const CSSM_KEY* cssm_key; | 223 const CSSM_KEY* cssm_key; |
236 OSStatus status = SecKeyGetCSSMKey(private_key.get(), &cssm_key); | 224 OSStatus status = SecKeyGetCSSMKey(private_key.get(), &cssm_key); |
237 if (status != noErr) | 225 if (status != noErr) |
238 return nullptr; | 226 return nullptr; |
239 | 227 |
240 if (cssm_key->KeyHeader.AlgorithmId != CSSM_ALGID_RSA && | 228 SSLPrivateKey::Type key_type; |
241 cssm_key->KeyHeader.AlgorithmId != CSSM_ALGID_ECDSA) { | 229 size_t max_length; |
242 LOG(ERROR) << "Unknown key type: " << cssm_key->KeyHeader.AlgorithmId; | 230 if (!GetClientCertInfo(certificate, &key_type, &max_length)) |
243 return nullptr; | 231 return nullptr; |
244 } | 232 |
245 return make_scoped_refptr(new ThreadedSSLPrivateKey( | 233 return make_scoped_refptr(new ThreadedSSLPrivateKey( |
246 base::MakeUnique<SSLPlatformKeyMac>(private_key.get(), cssm_key), | 234 base::MakeUnique<SSLPlatformKeyMac>(key_type, max_length, |
| 235 private_key.get(), cssm_key), |
247 GetSSLPlatformKeyTaskRunner())); | 236 GetSSLPlatformKeyTaskRunner())); |
248 } | 237 } |
249 | 238 |
250 #pragma clang diagnostic pop // "-Wdeprecated-declarations" | 239 #pragma clang diagnostic pop // "-Wdeprecated-declarations" |
251 | 240 |
252 } // namespace net | 241 } // namespace net |
OLD | NEW |