• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifdef UNSAFE_BUFFERS_BUILD
6 // TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
7 #pragma allow_unsafe_buffers
8 #endif
9 
10 #include "net/ssl/ssl_platform_key_android.h"
11 
12 #include <strings.h>
13 
14 #include <memory>
15 #include <optional>
16 #include <utility>
17 #include <vector>
18 
19 #include "base/android/scoped_java_ref.h"
20 #include "base/containers/flat_set.h"
21 #include "base/logging.h"
22 #include "net/android/keystore.h"
23 #include "net/base/net_errors.h"
24 #include "net/ssl/ssl_platform_key_util.h"
25 #include "net/ssl/threaded_ssl_private_key.h"
26 #include "third_party/boringssl/src/include/openssl/ecdsa.h"
27 #include "third_party/boringssl/src/include/openssl/evp.h"
28 #include "third_party/boringssl/src/include/openssl/mem.h"
29 #include "third_party/boringssl/src/include/openssl/nid.h"
30 #include "third_party/boringssl/src/include/openssl/rsa.h"
31 #include "third_party/boringssl/src/include/openssl/ssl.h"
32 
33 using base::android::JavaRef;
34 using base::android::ScopedJavaGlobalRef;
35 
36 namespace net {
37 
38 namespace {
39 
GetJavaAlgorithm(uint16_t algorithm)40 const char* GetJavaAlgorithm(uint16_t algorithm) {
41   switch (algorithm) {
42     case SSL_SIGN_RSA_PKCS1_SHA1:
43       return "SHA1withRSA";
44     case SSL_SIGN_RSA_PKCS1_SHA256:
45       return "SHA256withRSA";
46     case SSL_SIGN_RSA_PKCS1_SHA384:
47       return "SHA384withRSA";
48     case SSL_SIGN_RSA_PKCS1_SHA512:
49       return "SHA512withRSA";
50     case SSL_SIGN_ECDSA_SHA1:
51       return "SHA1withECDSA";
52     case SSL_SIGN_ECDSA_SECP256R1_SHA256:
53       return "SHA256withECDSA";
54     case SSL_SIGN_ECDSA_SECP384R1_SHA384:
55       return "SHA384withECDSA";
56     case SSL_SIGN_ECDSA_SECP521R1_SHA512:
57       return "SHA512withECDSA";
58     case SSL_SIGN_RSA_PSS_SHA256:
59       return "SHA256withRSA/PSS";
60     case SSL_SIGN_RSA_PSS_SHA384:
61       return "SHA384withRSA/PSS";
62     case SSL_SIGN_RSA_PSS_SHA512:
63       return "SHA512withRSA/PSS";
64     default:
65       return nullptr;
66   }
67 }
68 
69 // Java's public-key encryption algorithms are mis-named. It incorrectly
70 // classifies RSA's "mode" as ECB.
71 const char kRSANoPadding[] = "RSA/ECB/NoPadding";
72 
73 class SSLPlatformKeyAndroid : public ThreadedSSLPrivateKey::Delegate {
74  public:
SSLPlatformKeyAndroid(bssl::UniquePtr<EVP_PKEY> pubkey,const JavaRef<jobject> & key)75   SSLPlatformKeyAndroid(bssl::UniquePtr<EVP_PKEY> pubkey,
76                         const JavaRef<jobject>& key)
77       : pubkey_(std::move(pubkey)),
78         provider_name_(android::GetPrivateKeyClassName(key)) {
79     key_.Reset(key);
80 
81     std::optional<bool> supports_rsa_no_padding;
82     for (uint16_t algorithm : SSLPrivateKey::DefaultAlgorithmPreferences(
83              EVP_PKEY_id(pubkey_.get()), true /* include PSS */)) {
84       const char* java_algorithm = GetJavaAlgorithm(algorithm);
85       if (java_algorithm &&
86           android::PrivateKeySupportsSignature(key_, java_algorithm)) {
87         preferences_.push_back(algorithm);
88       } else if (SSL_is_signature_algorithm_rsa_pss(algorithm)) {
89         // Check if we can use the fallback path instead.
90         if (!supports_rsa_no_padding) {
91           supports_rsa_no_padding =
92               android::PrivateKeySupportsCipher(key_, kRSANoPadding);
93         }
94         if (*supports_rsa_no_padding) {
95           preferences_.push_back(algorithm);
96           use_pss_fallback_.insert(algorithm);
97         }
98       }
99     }
100   }
101 
102   SSLPlatformKeyAndroid(const SSLPlatformKeyAndroid&) = delete;
103   SSLPlatformKeyAndroid& operator=(const SSLPlatformKeyAndroid&) = delete;
104 
105   ~SSLPlatformKeyAndroid() override = default;
106 
GetProviderName()107   std::string GetProviderName() override { return provider_name_; }
108 
GetAlgorithmPreferences()109   std::vector<uint16_t> GetAlgorithmPreferences() override {
110     return preferences_;
111   }
112 
Sign(uint16_t algorithm,base::span<const uint8_t> input,std::vector<uint8_t> * signature)113   Error Sign(uint16_t algorithm,
114              base::span<const uint8_t> input,
115              std::vector<uint8_t>* signature) override {
116     if (use_pss_fallback_.contains(algorithm)) {
117       return SignPSSFallback(algorithm, input, signature);
118     }
119 
120     const char* java_algorithm = GetJavaAlgorithm(algorithm);
121     if (!java_algorithm) {
122       LOG(ERROR) << "Unknown algorithm " << algorithm;
123       return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
124     }
125     if (!android::SignWithPrivateKey(key_, java_algorithm, input, signature)) {
126       LOG(ERROR) << "Could not sign message with private key!";
127       return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
128     }
129     return OK;
130   }
131 
132  private:
SignPSSFallback(uint16_t algorithm,base::span<const uint8_t> input,std::vector<uint8_t> * signature)133   Error SignPSSFallback(uint16_t algorithm,
134                         base::span<const uint8_t> input,
135                         std::vector<uint8_t>* signature) {
136     const EVP_MD* md = SSL_get_signature_algorithm_digest(algorithm);
137     uint8_t digest[EVP_MAX_MD_SIZE];
138     unsigned digest_len;
139     if (!EVP_Digest(input.data(), input.size(), digest, &digest_len, md,
140                     nullptr)) {
141       return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
142     }
143 
144     std::optional<std::vector<uint8_t>> padded =
145         AddPSSPadding(pubkey_.get(), md, base::span(digest, digest_len));
146     if (!padded) {
147       return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
148     }
149 
150     if (!android::EncryptWithPrivateKey(key_, kRSANoPadding, *padded,
151                                         signature)) {
152       return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
153     }
154     return OK;
155   }
156 
157   bssl::UniquePtr<EVP_PKEY> pubkey_;
158   ScopedJavaGlobalRef<jobject> key_;
159   std::string provider_name_;
160   std::vector<uint16_t> preferences_;
161   base::flat_set<uint16_t> use_pss_fallback_;
162 };
163 
164 }  // namespace
165 
WrapJavaPrivateKey(const X509Certificate * certificate,const JavaRef<jobject> & key)166 scoped_refptr<SSLPrivateKey> WrapJavaPrivateKey(
167     const X509Certificate* certificate,
168     const JavaRef<jobject>& key) {
169   bssl::UniquePtr<EVP_PKEY> pubkey = GetClientCertPublicKey(certificate);
170   if (!pubkey)
171     return nullptr;
172 
173   return base::MakeRefCounted<ThreadedSSLPrivateKey>(
174       std::make_unique<SSLPlatformKeyAndroid>(std::move(pubkey), key),
175       GetSSLPlatformKeyTaskRunner());
176 }
177 
SignatureAlgorithmsToJavaKeyTypes(base::span<const uint16_t> algorithms)178 std::vector<std::string> SignatureAlgorithmsToJavaKeyTypes(
179     base::span<const uint16_t> algorithms) {
180   std::vector<std::string> key_types;
181   bool has_rsa = false, has_ec = false;
182   for (uint16_t alg : algorithms) {
183     switch (SSL_get_signature_algorithm_key_type(alg)) {
184       case EVP_PKEY_RSA:
185         if (!has_rsa) {
186           // https://developer.android.com/reference/android/security/keystore/KeyProperties#KEY_ALGORITHM_RSA
187           key_types.push_back("RSA");
188           has_rsa = true;
189         }
190         break;
191       case EVP_PKEY_EC:
192         if (!has_ec) {
193           // https://developer.android.com/reference/android/security/keystore/KeyProperties#KEY_ALGORITHM_EC
194           key_types.push_back("EC");
195           has_ec = true;
196         }
197         break;
198     }
199   }
200   return key_types;
201 }
202 
203 }  // namespace net
204