Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(216)

Side by Side Diff: net/ssl/ssl_platform_key_android.cc

Issue 1640833002: Android SSLPrivateKey Work (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix rebase. Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/ssl/ssl_platform_key_android.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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_android.h" 5 #include "net/ssl/ssl_platform_key_android.h"
6 6
7 #include <openssl/digest.h> 7 #include <vector>
8 #include <openssl/evp.h>
9 #include <utility>
10 8
9 #include "base/android/build_info.h"
10 #include "base/android/scoped_java_ref.h"
11 #include "base/lazy_instance.h"
11 #include "base/logging.h" 12 #include "base/logging.h"
12 #include "base/macros.h" 13 #include "base/macros.h"
13 #include "crypto/scoped_openssl_types.h" 14 #include "crypto/scoped_openssl_types.h"
15 #include "net/android/keystore.h"
16 #include "net/android/legacy_openssl.h"
14 #include "net/base/net_errors.h" 17 #include "net/base/net_errors.h"
18 #include "net/ssl/ssl_platform_key.h"
15 #include "net/ssl/ssl_platform_key_task_runner.h" 19 #include "net/ssl/ssl_platform_key_task_runner.h"
16 #include "net/ssl/ssl_private_key.h" 20 #include "net/ssl/ssl_private_key.h"
17 #include "net/ssl/threaded_ssl_private_key.h" 21 #include "net/ssl/threaded_ssl_private_key.h"
18 22
23 using base::android::ScopedJavaLocalRef;
24 using base::android::ScopedJavaGlobalRef;
25
19 namespace net { 26 namespace net {
20 27
21 namespace { 28 namespace {
22 29
30 // On Android < 4.2, the libkeystore.so ENGINE uses CRYPTO_EX_DATA and is not
31 // added to the global engine list. If all references to it are dropped, OpenSSL
32 // will dlclose the module, leaving a dangling function pointer in the RSA
33 // CRYPTO_EX_DATA class. To work around this, leak an extra reference to the
34 // ENGINE we extract in GetRsaLegacyKey.
35 //
36 // In 4.2, this change avoids the problem:
37 // https://android.googlesource.com/platform/libcore/+/106a8928fb4249f2f3d4dba1d ddbe73ca5cb3d61
38 //
39 // https://crbug.com/381465
40 class KeystoreEngineWorkaround {
41 public:
42 KeystoreEngineWorkaround() {}
43
44 void LeakEngine(jobject private_key) {
45 if (!engine_.is_null())
46 return;
47 ScopedJavaLocalRef<jobject> engine =
48 android::GetOpenSSLEngineForPrivateKey(private_key);
49 if (engine.is_null()) {
50 NOTREACHED();
51 return;
52 }
53 engine_.Reset(engine);
54 }
55
56 private:
57 ScopedJavaGlobalRef<jobject> engine_;
58 };
59
60 void LeakEngine(jobject private_key) {
61 static base::LazyInstance<KeystoreEngineWorkaround>::Leaky s_instance =
62 LAZY_INSTANCE_INITIALIZER;
63 s_instance.Get().LeakEngine(private_key);
64 }
65
66 android::AndroidRSA* GetLegacyRSAKey(jobject private_key) {
67 const int kAndroid42ApiLevel = 17;
68
69 if (base::android::BuildInfo::GetInstance()->sdk_int() >=
70 kAndroid42ApiLevel) {
71 return nullptr;
72 }
73
74 // Route around platform limitation: if Android < 4.2, then
75 // base::android::RawSignDigestWithPrivateKey() cannot work, so try to get the
76 // system OpenSSL's EVP_PKEY backing this PrivateKey object.
77 android::AndroidEVP_PKEY* sys_pkey =
78 android::GetOpenSSLSystemHandleForPrivateKey(private_key);
79 if (sys_pkey == nullptr)
80 return nullptr;
81
82 if (sys_pkey->type != android::ANDROID_EVP_PKEY_RSA) {
83 LOG(ERROR) << "Private key has wrong type!";
84 return nullptr;
85 }
86
87 android::AndroidRSA* sys_rsa = sys_pkey->pkey.rsa;
88 if (sys_rsa->engine) {
89 // |private_key| may not have an engine if the PrivateKey did not come
90 // from the key store, such as in unit tests.
91 if (strcmp(sys_rsa->engine->id, "keystore") == 0) {
92 LeakEngine(private_key);
93 } else {
94 NOTREACHED();
95 }
96 }
97
98 return sys_rsa;
99 }
100
23 class SSLPlatformKeyAndroid : public ThreadedSSLPrivateKey::Delegate { 101 class SSLPlatformKeyAndroid : public ThreadedSSLPrivateKey::Delegate {
24 public: 102 public:
25 SSLPlatformKeyAndroid(crypto::ScopedEVP_PKEY key, SSLPrivateKey::Type type) 103 SSLPlatformKeyAndroid(SSLPrivateKey::Type type,
26 : key_(std::move(key)), type_(type) {} 104 jobject key,
105 size_t max_length)
106 : type_(type), max_length_(max_length) {
107 key_.Reset(nullptr, key);
108 }
27 109
28 ~SSLPlatformKeyAndroid() override {} 110 ~SSLPlatformKeyAndroid() override {}
29 111
30 SSLPrivateKey::Type GetType() override { return type_; } 112 SSLPrivateKey::Type GetType() override { return type_; }
31 113
32 std::vector<SSLPrivateKey::Hash> GetDigestPreferences() override { 114 std::vector<SSLPrivateKey::Hash> GetDigestPreferences() override {
33 static const SSLPrivateKey::Hash kHashes[] = { 115 static const SSLPrivateKey::Hash kHashes[] = {
34 SSLPrivateKey::Hash::SHA512, SSLPrivateKey::Hash::SHA384, 116 SSLPrivateKey::Hash::SHA512, SSLPrivateKey::Hash::SHA384,
35 SSLPrivateKey::Hash::SHA256, SSLPrivateKey::Hash::SHA1}; 117 SSLPrivateKey::Hash::SHA256, SSLPrivateKey::Hash::SHA1};
36 return std::vector<SSLPrivateKey::Hash>(kHashes, 118 return std::vector<SSLPrivateKey::Hash>(kHashes,
37 kHashes + arraysize(kHashes)); 119 kHashes + arraysize(kHashes));
38 } 120 }
39 121
40 size_t GetMaxSignatureLengthInBytes() override { 122 size_t GetMaxSignatureLengthInBytes() override { return max_length_; }
41 return EVP_PKEY_size(key_.get());
42 }
43 123
44 Error SignDigest(SSLPrivateKey::Hash hash, 124 Error SignDigest(SSLPrivateKey::Hash hash,
45 const base::StringPiece& input, 125 const base::StringPiece& input,
46 std::vector<uint8_t>* signature) override { 126 std::vector<uint8_t>* signature) override {
47 crypto::ScopedEVP_PKEY_CTX ctx = 127 const int kAndroid42ApiLevel = 17;
48 crypto::ScopedEVP_PKEY_CTX(EVP_PKEY_CTX_new(key_.get(), NULL)); 128 if (base::android::BuildInfo::GetInstance()->sdk_int() >=
49 if (!ctx) 129 kAndroid42ApiLevel) {
50 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; 130 if (!android::RawSignDigestWithPrivateKey(key_.obj(), input, signature)) {
51 if (!EVP_PKEY_sign_init(ctx.get())) 131 LOG(ERROR) << "Could not sign message";
52 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; 132 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
53
54 if (type_ == SSLPrivateKey::Type::RSA) {
55 const EVP_MD* digest = nullptr;
56 switch (hash) {
57 case SSLPrivateKey::Hash::MD5_SHA1:
58 digest = EVP_md5_sha1();
59 break;
60 case SSLPrivateKey::Hash::SHA1:
61 digest = EVP_sha1();
62 break;
63 case SSLPrivateKey::Hash::SHA256:
64 digest = EVP_sha256();
65 break;
66 case SSLPrivateKey::Hash::SHA384:
67 digest = EVP_sha384();
68 break;
69 case SSLPrivateKey::Hash::SHA512:
70 digest = EVP_sha512();
71 break;
72 default:
73 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
74 } 133 }
75 DCHECK(digest); 134 return OK;
76 if (!EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_PADDING))
77 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
78 if (!EVP_PKEY_CTX_set_signature_md(ctx.get(), digest))
79 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
80 } 135 }
81 136
82 const uint8_t* input_ptr = reinterpret_cast<const uint8_t*>(input.data()); 137 // Pre-4.2 Legacy Codepath
83 size_t input_len = input.size(); 138 android::AndroidRSA* legacy_rsa = GetLegacyRSAKey(key_.obj());
84 size_t sig_len = 0; 139 signature->resize(max_length_);
85 if (!EVP_PKEY_sign(ctx.get(), NULL, &sig_len, input_ptr, input_len)) 140 int ret = legacy_rsa->meth->rsa_priv_enc(
86 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; 141 input.size(), reinterpret_cast<const uint8_t*>(input.data()),
87 signature->resize(sig_len); 142 signature->data(), legacy_rsa, android::ANDROID_RSA_PKCS1_PADDING);
88 if (!EVP_PKEY_sign(ctx.get(), signature->data(), &sig_len, input_ptr, 143 if (ret < 0) {
89 input_len)) { 144 // System OpenSSL will use a separate error queue, so it is still
145 // necessary to push a new error.
146 LOG(ERROR) << "Could not sign message with legacy RSA key";
90 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED; 147 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
91 } 148 }
92 149 signature->resize(ret);
93 signature->resize(sig_len);
94
95 return OK; 150 return OK;
96 } 151 }
97 152
98 private: 153 private:
99 crypto::ScopedEVP_PKEY key_;
100 SSLPrivateKey::Type type_; 154 SSLPrivateKey::Type type_;
155 ScopedJavaGlobalRef<jobject> key_;
156 size_t max_length_;
101 157
102 DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyAndroid); 158 DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyAndroid);
103 }; 159 };
104 160
161 // VectorBignumSize returns the number of bytes needed to represent the bignum
162 // given in |v|, i.e. the length of |v| less any leading zero bytes.
163 size_t VectorBignumSize(const std::vector<uint8_t>& v) {
164 size_t size = v.size();
165 // Ignore any leading zero bytes.
166 for (size_t i = 0; i < v.size() && v[i] == 0; i++) {
167 size--;
168 }
169 return size;
170 }
171
105 } // namespace 172 } // namespace
106 173
107 scoped_refptr<SSLPrivateKey> WrapOpenSSLPrivateKey(crypto::ScopedEVP_PKEY key) { 174 scoped_refptr<SSLPrivateKey> WrapJavaPrivateKey(jobject key) {
108 if (!key) 175 if (!key)
109 return nullptr; 176 return nullptr;
110 177
111 SSLPrivateKey::Type type; 178 SSLPrivateKey::Type type;
112 switch (EVP_PKEY_id(key.get())) { 179 std::vector<uint8_t> key_params;
113 case EVP_PKEY_RSA: 180 switch (android::GetPrivateKeyType(key)) {
181 case android::PRIVATE_KEY_TYPE_RSA:
114 type = SSLPrivateKey::Type::RSA; 182 type = SSLPrivateKey::Type::RSA;
183 if (!android::GetRSAKeyModulus(key, &key_params)) {
184 LOG(ERROR) << "Failed to get private key modulus";
185 return nullptr;
186 }
115 break; 187 break;
116 case EVP_PKEY_EC: 188 case android::PRIVATE_KEY_TYPE_ECDSA:
117 type = SSLPrivateKey::Type::ECDSA; 189 type = SSLPrivateKey::Type::ECDSA;
190 if (!android::GetECKeyOrder(key, &key_params)) {
191 LOG(ERROR) << "Failed to get private key order";
192 return nullptr;
193 }
118 break; 194 break;
119 default: 195 default:
120 LOG(ERROR) << "Unknown key type: " << EVP_PKEY_id(key.get()); 196 LOG(ERROR) << "Unknown key type: " << android::GetPrivateKeyType(key);
121 return nullptr; 197 return nullptr;
122 } 198 }
123 return make_scoped_refptr(new ThreadedSSLPrivateKey( 199
124 make_scoped_ptr(new SSLPlatformKeyAndroid(std::move(key), type)), 200 return make_scoped_refptr(
125 GetSSLPlatformKeyTaskRunner())); 201 new ThreadedSSLPrivateKey(make_scoped_ptr(new SSLPlatformKeyAndroid(
202 type, key, VectorBignumSize(key_params))),
203 GetSSLPlatformKeyTaskRunner()));
126 } 204 }
127 205
128 } // namespace net 206 } // namespace net
OLDNEW
« no previous file with comments | « net/ssl/ssl_platform_key_android.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698