Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / net / ssl / ssl_platform_key_android.cc
blobc918f3600fe69b06215e5c112e0ca1b470a44a2b
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
3 // found in the LICENSE file.
5 #include "net/ssl/ssl_platform_key.h"
7 #include <openssl/digest.h>
8 #include <openssl/evp.h>
10 #include "base/logging.h"
11 #include "base/macros.h"
12 #include "base/stl_util.h"
13 #include "crypto/scoped_openssl_types.h"
14 #include "net/base/net_errors.h"
15 #include "net/ssl/openssl_client_key_store.h"
16 #include "net/ssl/ssl_private_key.h"
17 #include "net/ssl/threaded_ssl_private_key.h"
19 namespace net {
21 namespace {
23 class SSLPlatformKeyAndroid : public ThreadedSSLPrivateKey::Delegate {
24 public:
25 SSLPlatformKeyAndroid(crypto::ScopedEVP_PKEY key, SSLPrivateKey::Type type)
26 : key_(key.Pass()), type_(type) {}
28 ~SSLPlatformKeyAndroid() override {}
30 SSLPrivateKey::Type GetType() override { return type_; }
32 bool SupportsHash(SSLPrivateKey::Hash hash) override { return true; }
34 size_t GetMaxSignatureLengthInBytes() override {
35 return EVP_PKEY_size(key_.get());
38 Error SignDigest(SSLPrivateKey::Hash hash,
39 const base::StringPiece& input,
40 std::vector<uint8_t>* signature) override {
41 crypto::ScopedEVP_PKEY_CTX ctx =
42 crypto::ScopedEVP_PKEY_CTX(EVP_PKEY_CTX_new(key_.get(), NULL));
43 if (!ctx)
44 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
45 if (!EVP_PKEY_sign_init(ctx.get()))
46 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
48 if (type_ == SSLPrivateKey::Type::RSA) {
49 const EVP_MD* digest = nullptr;
50 switch (hash) {
51 case SSLPrivateKey::Hash::MD5_SHA1:
52 digest = EVP_md5_sha1();
53 break;
54 case SSLPrivateKey::Hash::SHA1:
55 digest = EVP_sha1();
56 break;
57 case SSLPrivateKey::Hash::SHA256:
58 digest = EVP_sha256();
59 break;
60 case SSLPrivateKey::Hash::SHA384:
61 digest = EVP_sha384();
62 break;
63 case SSLPrivateKey::Hash::SHA512:
64 digest = EVP_sha512();
65 break;
66 default:
67 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
69 DCHECK(digest);
70 if (!EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_PADDING))
71 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
72 if (!EVP_PKEY_CTX_set_signature_md(ctx.get(), digest))
73 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
76 uint8_t* input_ptr =
77 const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(input.data()));
78 size_t input_len = input.size();
79 size_t sig_len = 0;
80 if (!EVP_PKEY_sign(ctx.get(), NULL, &sig_len, input_ptr, input_len))
81 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
82 signature->resize(sig_len);
83 uint8_t* sig = const_cast<uint8_t*>(
84 reinterpret_cast<const uint8_t*>(vector_as_array(signature)));
85 if (!sig)
86 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
87 if (!EVP_PKEY_sign(ctx.get(), sig, &sig_len, input_ptr, input_len))
88 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
90 signature->resize(sig_len);
92 return OK;
95 private:
96 crypto::ScopedEVP_PKEY key_;
97 SSLPrivateKey::Type type_;
99 DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyAndroid);
102 } // namespace
104 scoped_ptr<SSLPrivateKey> FetchClientCertPrivateKey(
105 X509Certificate* certificate,
106 scoped_refptr<base::SequencedTaskRunner> task_runner) {
107 crypto::ScopedEVP_PKEY key =
108 OpenSSLClientKeyStore::GetInstance()->FetchClientCertPrivateKey(
109 certificate);
110 if (!key)
111 return nullptr;
113 SSLPrivateKey::Type type;
114 switch (EVP_PKEY_id(key.get())) {
115 case EVP_PKEY_RSA:
116 type = SSLPrivateKey::Type::RSA;
117 break;
118 case EVP_PKEY_EC:
119 type = SSLPrivateKey::Type::ECDSA;
120 break;
121 default:
122 LOG(ERROR) << "Unknown key type: " << EVP_PKEY_id(key.get());
123 return nullptr;
125 return make_scoped_ptr(new ThreadedSSLPrivateKey(
126 make_scoped_ptr(new SSLPlatformKeyAndroid(key.Pass(), type)),
127 task_runner.Pass()));
130 } // namespace net