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"
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/client_key_store.h"
23 #include "net/ssl/ssl_private_key.h"
24 #include "net/ssl/threaded_ssl_private_key.h"
31 PRErrorCode err
= PR_GetError();
32 const char* err_name
= PR_ErrorToName(err
);
33 if (err_name
== nullptr)
35 LOG(ERROR
) << "Could not sign digest: " << err
<< " (" << err_name
<< ")";
38 class SSLPlatformKeyNSS
: public ThreadedSSLPrivateKey::Delegate
{
40 SSLPlatformKeyNSS(SSLPrivateKey::Type type
,
41 crypto::ScopedSECKEYPrivateKey key
)
42 : type_(type
), key_(key
.Pass()) {}
43 ~SSLPlatformKeyNSS() override
{}
45 SSLPrivateKey::Type
GetType() override
{ return type_
; }
47 bool SupportsHash(SSLPrivateKey::Hash hash
) override
{ return true; }
49 size_t GetMaxSignatureLengthInBytes() override
{
50 int len
= PK11_SignatureLen(key_
.get());
53 // NSS signs raw ECDSA signatures rather than a DER-encoded ECDSA-Sig-Value.
54 if (type_
== SSLPrivateKey::Type::ECDSA
)
55 return ECDSA_SIG_max_len(static_cast<size_t>(len
) / 2);
56 return static_cast<size_t>(len
);
59 Error
SignDigest(SSLPrivateKey::Hash hash
,
60 const base::StringPiece
& input
,
61 std::vector
<uint8_t>* signature
) override
{
64 const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(input
.data()));
65 digest_item
.len
= input
.size();
67 crypto::ScopedOpenSSLBytes free_digest_info
;
68 if (type_
== SSLPrivateKey::Type::RSA
) {
69 // PK11_Sign expects the caller to prepend the DigestInfo.
70 int hash_nid
= NID_undef
;
72 case SSLPrivateKey::Hash::MD5_SHA1
:
73 hash_nid
= NID_md5_sha1
;
75 case SSLPrivateKey::Hash::SHA1
:
78 case SSLPrivateKey::Hash::SHA256
:
79 hash_nid
= NID_sha256
;
81 case SSLPrivateKey::Hash::SHA384
:
82 hash_nid
= NID_sha384
;
84 case SSLPrivateKey::Hash::SHA512
:
85 hash_nid
= NID_sha512
;
88 DCHECK_NE(NID_undef
, hash_nid
);
91 if (!RSA_add_pkcs1_prefix(&digest_item
.data
, &prefix_len
, &is_alloced
,
92 hash_nid
, digest_item
.data
, digest_item
.len
)) {
93 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED
;
95 digest_item
.len
= prefix_len
;
97 free_digest_info
.reset(digest_item
.data
);
100 int len
= PK11_SignatureLen(key_
.get());
103 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED
;
105 signature
->resize(len
);
106 SECItem signature_item
;
107 signature_item
.data
= vector_as_array(signature
);
108 signature_item
.len
= signature
->size();
110 SECStatus rv
= PK11_Sign(key_
.get(), &signature_item
, &digest_item
);
111 if (rv
!= SECSuccess
) {
113 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED
;
115 signature
->resize(signature_item
.len
);
117 // NSS emits raw ECDSA signatures, but BoringSSL expects a DER-encoded
119 if (type_
== SSLPrivateKey::Type::ECDSA
) {
120 if (signature
->size() % 2 != 0) {
121 LOG(ERROR
) << "Bad signature length";
122 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED
;
124 size_t order_len
= signature
->size() / 2;
126 // Convert the RAW ECDSA signature to a DER-encoded ECDSA-Sig-Value.
127 crypto::ScopedECDSA_SIG
sig(ECDSA_SIG_new());
128 if (!sig
|| !BN_bin2bn(vector_as_array(signature
), order_len
, sig
->r
) ||
129 !BN_bin2bn(vector_as_array(signature
) + order_len
, order_len
,
131 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED
;
134 int len
= i2d_ECDSA_SIG(sig
.get(), nullptr);
136 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED
;
137 signature
->resize(len
);
138 uint8_t* ptr
= vector_as_array(signature
);
139 len
= i2d_ECDSA_SIG(sig
.get(), &ptr
);
141 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED
;
142 signature
->resize(len
);
149 SSLPrivateKey::Type type_
;
150 crypto::ScopedSECKEYPrivateKey key_
;
152 DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyNSS
);
157 scoped_ptr
<SSLPrivateKey
> FetchClientCertPrivateKey(
158 X509Certificate
* certificate
,
159 scoped_refptr
<base::SequencedTaskRunner
> task_runner
) {
160 crypto::ScopedSECKEYPrivateKey
key(
161 PK11_FindKeyByAnyCert(certificate
->os_cert_handle(), nullptr));
163 return ClientKeyStore::GetInstance()->FetchClientCertPrivateKey(
167 KeyType nss_type
= SECKEY_GetPrivateKeyType(key
.get());
168 SSLPrivateKey::Type type
;
171 type
= SSLPrivateKey::Type::RSA
;
174 type
= SSLPrivateKey::Type::ECDSA
;
177 LOG(ERROR
) << "Unknown key type: " << nss_type
;
180 return make_scoped_ptr(new ThreadedSSLPrivateKey(
181 make_scoped_ptr(new SSLPlatformKeyNSS(type
, key
.Pass())),
182 task_runner
.Pass()));