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/ssl_private_key.h"
23 #include "net/ssl/threaded_ssl_private_key.h"
30 PRErrorCode err
= PR_GetError();
31 const char* err_name
= PR_ErrorToName(err
);
32 if (err_name
== nullptr)
34 LOG(ERROR
) << "Could not sign digest: " << err
<< " (" << err_name
<< ")";
37 class SSLPlatformKeyNSS
: public ThreadedSSLPrivateKey::Delegate
{
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());
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
{
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
;
71 case SSLPrivateKey::Hash::MD5_SHA1
:
72 hash_nid
= NID_md5_sha1
;
74 case SSLPrivateKey::Hash::SHA1
:
77 case SSLPrivateKey::Hash::SHA256
:
78 hash_nid
= NID_sha256
;
80 case SSLPrivateKey::Hash::SHA384
:
81 hash_nid
= NID_sha384
;
83 case SSLPrivateKey::Hash::SHA512
:
84 hash_nid
= NID_sha512
;
87 DCHECK_NE(NID_undef
, hash_nid
);
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
;
96 free_digest_info
.reset(digest_item
.data
);
99 int len
= PK11_SignatureLen(key_
.get());
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
) {
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
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
,
130 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED
;
133 int len
= i2d_ECDSA_SIG(sig
.get(), nullptr);
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
);
140 return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED
;
141 signature
->resize(len
);
148 SSLPrivateKey::Type type_
;
149 crypto::ScopedSECKEYPrivateKey key_
;
151 DISALLOW_COPY_AND_ASSIGN(SSLPlatformKeyNSS
);
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));
164 KeyType nss_type
= SECKEY_GetPrivateKeyType(key
.get());
165 SSLPrivateKey::Type type
;
168 type
= SSLPrivateKey::Type::RSA
;
171 type
= SSLPrivateKey::Type::ECDSA
;
174 LOG(ERROR
) << "Unknown key type: " << nss_type
;
177 return make_scoped_ptr(new ThreadedSSLPrivateKey(
178 make_scoped_ptr(new SSLPlatformKeyNSS(type
, key
.Pass())),
179 task_runner
.Pass()));