Skip to content

Commit 608d764

Browse files
committed
Only accept PKCS#8 keys
1 parent 0133734 commit 608d764

File tree

5 files changed

+39
-0
lines changed

5 files changed

+39
-0
lines changed

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ openssl-probe = "0.1"
3434
[target.'cfg(not(any(target_os = "windows", target_os = "macos", target_os = "ios")))'.build_dependencies]
3535
openssl-src = { version = "300.0.3", optional = true }
3636

37+
[dependencies]
38+
pem-rfc7468 = { version = "0.2.4", features = ["std"] }
39+
3740
[dev-dependencies]
3841
pem = "1.0"
3942
rsa = { version = "0.5.0", features = ["alloc", "pem", "std"] }

src/imp/openssl.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
extern crate openssl;
22
extern crate openssl_probe;
3+
extern crate pem_rfc7468;
34

45
use self::openssl::error::ErrorStack;
56
use self::openssl::hash::MessageDigest;
@@ -117,6 +118,8 @@ pub enum Error {
117118
Normal(ErrorStack),
118119
Ssl(ssl::Error, X509VerifyResult),
119120
EmptyChain,
121+
DecodePemLabel(pem_rfc7468::Error),
122+
NotPkcs8,
120123
}
121124

122125
impl error::Error for Error {
@@ -125,6 +128,8 @@ impl error::Error for Error {
125128
Error::Normal(ref e) => error::Error::source(e),
126129
Error::Ssl(ref e, _) => error::Error::source(e),
127130
Error::EmptyChain => None,
131+
Error::DecodePemLabel(ref e) => error::Error::source(e),
132+
Error::NotPkcs8 => None,
128133
}
129134
}
130135
}
@@ -139,6 +144,8 @@ impl fmt::Display for Error {
139144
fmt,
140145
"at least one certificate must be provided to create an identity"
141146
),
147+
Error::DecodePemLabel(ref e) => fmt::Display::fmt(e, fmt),
148+
Error::NotPkcs8 => write!(fmt, "expected PKCS#8 PEM"),
142149
}
143150
}
144151
}
@@ -171,6 +178,11 @@ impl Identity {
171178
}
172179

173180
pub fn from_pkcs8(buf: &[u8], key: &[u8]) -> Result<Identity, Error> {
181+
let label = pem_rfc7468::decode_label(key).map_err(Error::DecodePemLabel)?;
182+
if label != "PRIVATE KEY" {
183+
return Err(Error::NotPkcs8);
184+
}
185+
174186
let pkey = PKey::private_key_from_pem(key)?;
175187
let mut cert_chain = X509::stack_from_pem(buf)?.into_iter();
176188
let cert = cert_chain.next().ok_or(Error::EmptyChain)?;

src/imp/schannel.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
extern crate pem_rfc7468;
12
extern crate schannel;
23

34
use self::schannel::cert_context::{CertContext, HashAlgorithm, KeySpec};
@@ -96,6 +97,12 @@ impl Identity {
9697
}
9798

9899
pub fn from_pkcs8(pem: &[u8], key: &[u8]) -> Result<Identity, Error> {
100+
let label = pem_rfc7468::decode_label(key)
101+
.map_err(|err| io::Error::new(io::ErrorKind::InvalidInput, err))?;
102+
if label != "PRIVATE KEY" {
103+
return Err(io::Error::new(io::ErrorKind::InvalidInput, "not a PKCS#8 key").into());
104+
}
105+
99106
let mut store = Memory::new()?.into_store();
100107
let mut cert_iter = pem::PemBlock::new(pem).into_iter();
101108
let leaf = cert_iter.next().ok_or_else(|| {

src/imp/security_framework.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
extern crate libc;
2+
extern crate pem_rfc7468;
23
extern crate security_framework;
34
extern crate security_framework_sys;
45
extern crate tempfile;
@@ -85,6 +86,12 @@ pub struct Identity {
8586

8687
impl Identity {
8788
pub fn from_pkcs8(pem: &[u8], key: &[u8]) -> Result<Identity, Error> {
89+
let label =
90+
pem_rfc7468::decode_label(key).map_err(|_| Error(base::Error::from(errSecParam)))?;
91+
if label != "PRIVATE KEY" {
92+
return Err(Error(base::Error::from(errSecParam)));
93+
}
94+
8895
let dir = TempDir::new().map_err(|_| Error(base::Error::from(errSecIO)))?;
8996
let keychain = keychain::CreateOptions::new()
9097
.password("password")

src/test.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,16 @@ fn import_same_identity_multiple_times() {
356356
let _ = p!(Identity::from_pkcs8(&cert, &key));
357357
}
358358

359+
#[test]
360+
fn from_pkcs8_rejects_rsa_key() {
361+
let keys = test_cert_gen::keys();
362+
let cert = keys.server.cert_and_key.cert.to_pem().into_bytes();
363+
let rsa_key = key_to_pem(keys.server.cert_and_key.key.get_der());
364+
assert!(Identity::from_pkcs8(&cert, rsa_key.as_bytes()).is_err());
365+
let pkcs8_key = rsa_to_pkcs8(&rsa_key);
366+
assert!(Identity::from_pkcs8(&cert, pkcs8_key.as_bytes()).is_ok());
367+
}
368+
359369
#[test]
360370
fn shutdown() {
361371
let keys = test_cert_gen::keys();

0 commit comments

Comments
 (0)