Update broken references to image assets
[chromium-blink-merge.git] / net / ssl / ssl_platform_key_nss.cc
blobd08bd98b0f2f69f9c685aefb6c1d4e7c590e515e
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 <keyhi.h>
8 #include <pk11pub.h>
9 #include <prerror.h>
11 #include <openssl/bn.h>
12 #include <openssl/ecdsa.h>
13 #include <openssl/rsa.h>
15 #include "base/logging.h"
16 #include "base/macros.h"
17 #include "base/sequenced_task_runner.h"
18 #include "base/stl_util.h"
19 #include "crypto/scoped_nss_types.h"
20 #include "crypto/scoped_openssl_types.h"
21 #include "net/cert/x509_certificate.h"
22 #include "net/ssl/ssl_private_key.h"
23 #include "net/ssl/threaded_ssl_private_key.h"
25 namespace net {
27 namespace {
29 void LogPRError() {
30 PRErrorCode err = PR_GetError();
31 const char* err_name = PR_ErrorToName(err);
32 if (err_name == nullptr)
33 err_name = "";
34 LOG(ERROR) << "Could not sign digest: " << err << " (" << err_name << ")";
37 class SSLPlatformKeyNSS : public ThreadedSSLPrivateKey::Delegate {
38 public:
39 SSLPlatformKeyNSS(SSLPrivateKey::Type type,
40 crypto::ScopedSECKEYPrivateKey key)
41 : type_(type), key_(key.Pass()) {}
42 ~SSLPlatformKeyNSS() override {}
44 SSLPrivateKey::Type GetType() override { return type_; }
46 bool SupportsHash(SSLPrivateKey::Hash hash) override { return true; }
48 size_t GetMaxSignatureLengthInBytes() override {
49 int len = PK11_SignatureLen(key_.get());
50 if (len <= 0)
51 return 0;
52 // NSS signs raw ECDSA signatures rather than a DER-encoded ECDSA-Sig-Value.
53 if (type_ == SSLPrivateKey::Type::ECDSA)
54 return ECDSA_SIG_max_len(static_cast<size_t>(len) / 2);
55 return static_cast<size_t>(len);
58 Error SignDigest(SSLPrivateKey::Hash hash,
59 const base::StringPiece& input,
60 std::vector<uint8_t>* signature) override {
61 SECItem digest_item;
62 digest_item.data =
63 const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(input.data()));
64 digest_item.len = input.size();
66 crypto::ScopedOpenSSLBytes free_digest_info;
67 if (type_ == SSLPrivateKey::Type::RSA) {
68 // PK11_Sign expects the caller to prepend the DigestInfo.
69 int hash_nid = NID_undef;
70 switch (hash) {
71 case SSLPrivateKey::Hash::MD5_SHA1:
72 hash_nid = NID_md5_sha1;
73 break;
74 case SSLPrivateKey::Hash::SHA1:
75 hash_nid = NID_sha1;
76 break;
77 case SSLPrivateKey::Hash::SHA256:
78 hash_nid = NID_sha256;
79 break;
80 case SSLPrivateKey::Hash::SHA384:
81 hash_nid = NID_sha384;
82 break;
83 case SSLPrivateKey::Hash::SHA512:
84 hash_nid = NID_sha512;
85 break;
87 DCHECK_NE(NID_undef, hash_nid);
88 int is_alloced;
89 size_t prefix_len;
90 if (!RSA_add_pkcs1_prefix(&digest_item.data, &prefix_len, &is_alloced,
91 hash_nid, digest_item.data, digest_item.len)) {
92 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
94 digest_item.len = prefix_len;
95 if (is_alloced)
96 free_digest_info.reset(digest_item.data);
99 int len = PK11_SignatureLen(key_.get());
100 if (len <= 0) {
101 LogPRError();
102 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
104 signature->resize(len);
105 SECItem signature_item;
106 signature_item.data = vector_as_array(signature);
107 signature_item.len = signature->size();
109 SECStatus rv = PK11_Sign(key_.get(), &signature_item, &digest_item);
110 if (rv != SECSuccess) {
111 LogPRError();
112 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
114 signature->resize(signature_item.len);
116 // NSS emits raw ECDSA signatures, but BoringSSL expects a DER-encoded
117 // ECDSA-Sig-Value.
118 if (type_ == SSLPrivateKey::Type::ECDSA) {
119 if (signature->size() % 2 != 0) {
120 LOG(ERROR) << "Bad signature length";
121 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
123 size_t order_len = signature->size() / 2;
125 // Convert the RAW ECDSA signature to a DER-encoded ECDSA-Sig-Value.
126 crypto::ScopedECDSA_SIG sig(ECDSA_SIG_new());
127 if (!sig || !BN_bin2bn(vector_as_array(signature), order_len, sig->r) ||
128 !BN_bin2bn(vector_as_array(signature) + order_len, order_len,
129 sig->s)) {
130 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
133 int len = i2d_ECDSA_SIG(sig.get(), nullptr);
134 if (len <= 0)
135 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
136 signature->resize(len);
137 uint8_t* ptr = vector_as_array(signature);
138 len = i2d_ECDSA_SIG(sig.get(), &ptr);
139 if (len <= 0)
140 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
141 signature->resize(len);
144 return OK;
147 private:
148 SSLPrivateKey::Type type_;
149 crypto::ScopedSECKEYPrivateKey key_;
151 DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyNSS);
154 } // namespace
156 scoped_ptr<SSLPrivateKey> FetchClientCertPrivateKey(
157 X509Certificate* certificate,
158 scoped_refptr<base::SequencedTaskRunner> task_runner) {
159 crypto::ScopedSECKEYPrivateKey key(
160 PK11_FindKeyByAnyCert(certificate->os_cert_handle(), nullptr));
161 if (!key)
162 return nullptr;
164 KeyType nss_type = SECKEY_GetPrivateKeyType(key.get());
165 SSLPrivateKey::Type type;
166 switch (nss_type) {
167 case rsaKey:
168 type = SSLPrivateKey::Type::RSA;
169 break;
170 case ecKey:
171 type = SSLPrivateKey::Type::ECDSA;
172 break;
173 default:
174 LOG(ERROR) << "Unknown key type: " << nss_type;
175 return nullptr;
177 return make_scoped_ptr(new ThreadedSSLPrivateKey(
178 make_scoped_ptr(new SSLPlatformKeyNSS(type, key.Pass())),
179 task_runner.Pass()));
182 } // namespace net