Skip to content

Commit 1318c44

Browse files
authored
Fix load_private_key for ECDSA keys (#16)
Previously it would return an incorrect signature verification algorithm, which would cause verification to fail. Add tests using rcgen for a variety of key algorithm
1 parent e020c8d commit 1318c44

File tree

14 files changed

+301
-315
lines changed

14 files changed

+301
-315
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ jobs:
4545
run: cargo fmt -- --check -l
4646
- name: cargo clippy (warnings)
4747
run: cargo clippy --all-targets -- -D warnings
48+
- name: cargo clippy --no-default-features (warnings)
49+
run: cargo clippy --no-default-features --all-targets -- -D warnings
4850

4951
test-fips:
5052
name: Test using FIPS openssl

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ antidote = "1.0.0"
2626
hex = "0.4.3"
2727
lazy_static = "1.4.0"
2828
once_cell = "1.8.0"
29+
rcgen = { version = "0.13.1", default-features = false, features = [
30+
"aws_lc_rs",
31+
] }
2932
rstest = "0.23.0"
3033
# Use aws_lc_rs to test our provider
3134
rustls = { version = "0.23.0", features = ["aws_lc_rs"] }

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ pub fn custom_provider(
201201
}
202202

203203
/// All supported cipher suites in descending order of preference:
204-
/// * [tls13::TLS13_AES_256_GCM_SHA384]
204+
/// * TLS13_AES_256_GCM_SHA384
205205
/// * TLS13_AES_128_GCM_SHA256
206206
/// * TLS13_CHACHA20_POLY1305_SHA256
207207
/// * TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384

src/signer.rs

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,6 @@ pub(crate) static RSA_SCHEMES: &[SignatureScheme] = &[
2121
SignatureScheme::RSA_PKCS1_SHA256,
2222
];
2323

24-
/// All ECDSA signature schemes in descending order of preference
25-
pub(crate) static ECDSA_SCHEMES: &[SignatureScheme] = &[
26-
SignatureScheme::ECDSA_NISTP521_SHA512,
27-
SignatureScheme::ECDSA_NISTP384_SHA384,
28-
SignatureScheme::ECDSA_NISTP256_SHA256,
29-
];
30-
3124
#[derive(Debug)]
3225
struct Signer {
3326
key: Arc<openssl::pkey::PKey<Private>>,
@@ -134,10 +127,36 @@ impl SigningKey for PKey {
134127
None
135128
}
136129
}
137-
SignatureAlgorithm::ECDSA => ECDSA_SCHEMES
138-
.iter()
139-
.find(|scheme| offered.contains(scheme))
140-
.map(|scheme| Box::new(self.signer(*scheme)) as Box<dyn rustls::sign::Signer>),
130+
SignatureAlgorithm::ECDSA => {
131+
// First determine our scheme
132+
self.0
133+
.ec_key()
134+
.ok()
135+
.and_then(|ec_key| {
136+
let nid = ec_key.group().curve_name();
137+
let scheme = match nid {
138+
Some(openssl::nid::Nid::X9_62_PRIME256V1) => {
139+
SignatureScheme::ECDSA_NISTP256_SHA256
140+
}
141+
Some(openssl::nid::Nid::SECP384R1) => {
142+
SignatureScheme::ECDSA_NISTP384_SHA384
143+
}
144+
Some(openssl::nid::Nid::SECP521R1) => {
145+
SignatureScheme::ECDSA_NISTP521_SHA512
146+
}
147+
_ => return None,
148+
};
149+
Some(scheme)
150+
})
151+
// Now see if that was offered
152+
.and_then(|scheme| {
153+
if offered.contains(&scheme) {
154+
Some(Box::new(self.signer(scheme)) as Box<dyn rustls::sign::Signer>)
155+
} else {
156+
None
157+
}
158+
})
159+
}
141160
_ => None,
142161
}
143162
}

src/tls12.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,29 @@
11
use crate::aead::{self, TAG_LEN};
22
use crate::hash::{SHA256, SHA384};
33
use crate::prf::Prf;
4-
use crate::signer::{ECDSA_SCHEMES, RSA_SCHEMES};
4+
use crate::signer::RSA_SCHEMES;
55
use rustls::crypto::cipher::{
66
make_tls12_aad, AeadKey, InboundOpaqueMessage, InboundPlainMessage, Iv, KeyBlockShape,
77
MessageDecrypter, MessageEncrypter, Nonce, OutboundOpaqueMessage, OutboundPlainMessage,
88
PrefixedPayload, Tls12AeadAlgorithm, UnsupportedOperationError, NONCE_LEN,
99
};
10+
use rustls::crypto::KeyExchangeAlgorithm;
1011
use rustls::{
11-
crypto::KeyExchangeAlgorithm, CipherSuite, CipherSuiteCommon, SupportedCipherSuite,
12-
Tls12CipherSuite,
12+
CipherSuite, CipherSuiteCommon, ConnectionTrafficSecrets, Error, SignatureScheme,
13+
SupportedCipherSuite, Tls12CipherSuite,
1314
};
14-
use rustls::{ConnectionTrafficSecrets, Error};
1515

1616
const GCM_EXPLICIT_NONCE_LENGTH: usize = 8;
1717
const GCM_IMPLICIT_NONCE_LENGTH: usize = 4;
1818

19+
static ECDSA_SCHEMES: &[SignatureScheme] = &[
20+
#[cfg(not(feature = "fips"))]
21+
SignatureScheme::ED25519,
22+
SignatureScheme::ECDSA_NISTP521_SHA512,
23+
SignatureScheme::ECDSA_NISTP384_SHA384,
24+
SignatureScheme::ECDSA_NISTP256_SHA256,
25+
];
26+
1927
/// The TLS1.2 ciphersuite `TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256`.
2028
#[cfg(all(chacha, not(feature = "fips")))]
2129
pub static TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: SupportedCipherSuite =

src/verify.rs

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,100 +58,116 @@ pub static SUPPORTED_SIG_ALGS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgori
5858

5959
/// RSA PKCS#1 1.5 signatures using SHA-256.
6060
pub(crate) static RSA_PKCS1_SHA256: &dyn SignatureVerificationAlgorithm = &OpenSslAlgorithm {
61+
display_name: "RSA_PKCS1_SHA256",
6162
public_key_alg_id: alg_id::RSA_ENCRYPTION,
6263
signature_alg_id: alg_id::RSA_PKCS1_SHA256,
6364
};
6465

6566
/// RSA PKCS#1 1.5 signatures using SHA-384.
6667
pub(crate) static RSA_PKCS1_SHA384: &dyn SignatureVerificationAlgorithm = &OpenSslAlgorithm {
68+
display_name: "RSA_PKCS1_SHA384",
6769
public_key_alg_id: alg_id::RSA_ENCRYPTION,
6870
signature_alg_id: alg_id::RSA_PKCS1_SHA384,
6971
};
7072

7173
/// RSA PKCS#1 1.5 signatures using SHA-512.
7274
pub(crate) static RSA_PKCS1_SHA512: &dyn SignatureVerificationAlgorithm = &OpenSslAlgorithm {
75+
display_name: "RSA_PKCS1_SHA512",
7376
public_key_alg_id: alg_id::RSA_ENCRYPTION,
7477
signature_alg_id: alg_id::RSA_PKCS1_SHA512,
7578
};
7679

7780
/// RSA PSS signatures using SHA-256.
7881
pub(crate) static RSA_PSS_SHA256: &dyn SignatureVerificationAlgorithm = &OpenSslAlgorithm {
82+
display_name: "RSA_PSS_SHA256",
7983
public_key_alg_id: alg_id::RSA_ENCRYPTION,
8084
signature_alg_id: alg_id::RSA_PSS_SHA256,
8185
};
8286

8387
/// RSA PSS signatures using SHA-384.
8488
pub(crate) static RSA_PSS_SHA384: &dyn SignatureVerificationAlgorithm = &OpenSslAlgorithm {
89+
display_name: "RSA_PSS_SHA384",
8590
public_key_alg_id: alg_id::RSA_ENCRYPTION,
8691
signature_alg_id: alg_id::RSA_PSS_SHA384,
8792
};
8893

8994
/// RSA PSS signatures using SHA-512.
9095
pub(crate) static RSA_PSS_SHA512: &dyn SignatureVerificationAlgorithm = &OpenSslAlgorithm {
96+
display_name: "RSA_PSS_SHA512",
9197
public_key_alg_id: alg_id::RSA_ENCRYPTION,
9298
signature_alg_id: alg_id::RSA_PSS_SHA512,
9399
};
94100

95101
#[cfg(not(feature = "fips"))]
96102
/// ED25519 signatures according to RFC 8410
97103
pub(crate) static ED25519: &dyn SignatureVerificationAlgorithm = &OpenSslAlgorithm {
104+
display_name: "ED25519",
98105
public_key_alg_id: alg_id::ED25519,
99106
signature_alg_id: alg_id::ED25519,
100107
};
101108

102109
/// ECDSA signatures using the P-256 curve and SHA-256.
103110
pub(crate) static ECDSA_P256_SHA256: &dyn SignatureVerificationAlgorithm = &OpenSslAlgorithm {
111+
display_name: "ECDSA_P256_SHA256",
104112
public_key_alg_id: alg_id::ECDSA_P256,
105113
signature_alg_id: alg_id::ECDSA_SHA256,
106114
};
107115

108116
/// ECDSA signatures using the P-256 curve and SHA-384. Deprecated.
109117
pub(crate) static ECDSA_P256_SHA384: &dyn SignatureVerificationAlgorithm = &OpenSslAlgorithm {
118+
display_name: "ECDSA_P256_SHA384",
110119
public_key_alg_id: alg_id::ECDSA_P256,
111120
signature_alg_id: alg_id::ECDSA_SHA384,
112121
};
113122

114123
/// ECDSA signatures using the P-384 curve and SHA-256. Deprecated.
115124
pub(crate) static ECDSA_P384_SHA256: &dyn SignatureVerificationAlgorithm = &OpenSslAlgorithm {
125+
display_name: "ECDSA_P384_SHA256",
116126
public_key_alg_id: alg_id::ECDSA_P384,
117127
signature_alg_id: alg_id::ECDSA_SHA256,
118128
};
119129

120130
/// ECDSA signatures using the P-384 curve and SHA-384.
121131
pub(crate) static ECDSA_P384_SHA384: &dyn SignatureVerificationAlgorithm = &OpenSslAlgorithm {
132+
display_name: "ECDSA_P384_SHA384",
122133
public_key_alg_id: alg_id::ECDSA_P384,
123134
signature_alg_id: alg_id::ECDSA_SHA384,
124135
};
125136

126137
/// ECDSA signatures using the P-521 curve and SHA-256.
127138
pub(crate) static ECDSA_P521_SHA256: &dyn SignatureVerificationAlgorithm = &OpenSslAlgorithm {
139+
display_name: "ECDSA_P521_SHA256",
128140
public_key_alg_id: alg_id::ECDSA_P521,
129141
signature_alg_id: alg_id::ECDSA_SHA256,
130142
};
131143

132144
/// ECDSA signatures using the P-521 curve and SHA-384.
133145
pub(crate) static ECDSA_P521_SHA384: &dyn SignatureVerificationAlgorithm = &OpenSslAlgorithm {
146+
display_name: "ECDSA_P521_SHA384",
134147
public_key_alg_id: alg_id::ECDSA_P521,
135148
signature_alg_id: alg_id::ECDSA_SHA384,
136149
};
137150

138151
/// ECDSA signatures using the P-521 curve and SHA-512.
139152
pub(crate) static ECDSA_P521_SHA512: &dyn SignatureVerificationAlgorithm = &OpenSslAlgorithm {
153+
display_name: "ECDSA_P521_SHA512",
140154
public_key_alg_id: alg_id::ECDSA_P521,
141155
signature_alg_id: alg_id::ECDSA_SHA512,
142156
};
143157

144158
struct OpenSslAlgorithm {
159+
display_name: &'static str,
145160
public_key_alg_id: AlgorithmIdentifier,
146161
signature_alg_id: AlgorithmIdentifier,
147162
}
148163

149164
impl fmt::Debug for OpenSslAlgorithm {
150165
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
151-
f.debug_struct("OpenSSLAlgorithm")
152-
.field("public_key_alg_id", &self.public_key_alg_id)
153-
.field("signature_alg_id", &self.signature_alg_id)
154-
.finish()
166+
write!(
167+
f,
168+
"rustls_openssl Signature Verification Algorithm: {}",
169+
self.display_name
170+
)
155171
}
156172
}
157173

@@ -293,3 +309,20 @@ impl SignatureVerificationAlgorithm for OpenSslAlgorithm {
293309
crate::fips()
294310
}
295311
}
312+
313+
#[cfg(test)]
314+
mod tests {
315+
use super::*;
316+
317+
#[test]
318+
fn test_open_ssl_algorithm_debug() {
319+
assert_eq!(
320+
format!("{:?}", ECDSA_P256_SHA256),
321+
"rustls_openssl Signature Verification Algorithm: ECDSA_P256_SHA256"
322+
);
323+
assert_eq!(
324+
format!("{:?}", RSA_PSS_SHA256),
325+
"rustls_openssl Signature Verification Algorithm: RSA_PSS_SHA256"
326+
);
327+
}
328+
}

tests/certs/RootCA.crt

Lines changed: 0 additions & 20 deletions
This file was deleted.

tests/certs/RootCA.key

Lines changed: 0 additions & 28 deletions
This file was deleted.

tests/certs/RootCA.pem

Lines changed: 0 additions & 20 deletions
This file was deleted.

tests/certs/localhost.crt

Lines changed: 0 additions & 21 deletions
This file was deleted.

0 commit comments

Comments
 (0)