Remove untrusted from the ring::signature signing API.

This commit is contained in:
Brian Smith 2019-04-05 14:08:09 -10:00
parent 306d163613
commit cfe46261e8
7 changed files with 62 additions and 102 deletions

View File

@ -72,9 +72,13 @@ impl Ed25519KeyPair {
///
/// If you need to parse PKCS#8 v1 files (without the public key) then use
/// `Ed25519KeyPair::from_pkcs8_maybe_unchecked()` instead.
pub fn from_pkcs8(input: untrusted::Input) -> Result<Self, error::KeyRejected> {
let (seed, public_key) = unwrap_pkcs8(pkcs8::Version::V2Only, input)?;
Self::from_seed_and_public_key(seed, public_key.unwrap())
pub fn from_pkcs8(pkcs8: &[u8]) -> Result<Self, error::KeyRejected> {
let (seed, public_key) =
unwrap_pkcs8(pkcs8::Version::V2Only, untrusted::Input::from(pkcs8))?;
Self::from_seed_and_public_key(
seed.as_slice_less_safe(),
public_key.unwrap().as_slice_less_safe(),
)
}
/// Constructs an Ed25519 key pair by parsing an unencrypted PKCS#8 v1 or v2
@ -89,12 +93,16 @@ impl Ed25519KeyPair {
/// between the public key and the private key.
///
/// PKCS#8 v2 files are parsed exactly like `Ed25519KeyPair::from_pkcs8()`.
pub fn from_pkcs8_maybe_unchecked(input: untrusted::Input) -> Result<Self, error::KeyRejected> {
let (seed, public_key) = unwrap_pkcs8(pkcs8::Version::V1OrV2, input)?;
pub fn from_pkcs8_maybe_unchecked(pkcs8: &[u8]) -> Result<Self, error::KeyRejected> {
let (seed, public_key) =
unwrap_pkcs8(pkcs8::Version::V1OrV2, untrusted::Input::from(pkcs8))?;
if let Some(public_key) = public_key {
Self::from_seed_and_public_key(seed, public_key)
Self::from_seed_and_public_key(
seed.as_slice_less_safe(),
public_key.as_slice_less_safe(),
)
} else {
Self::from_seed_unchecked(seed)
Self::from_seed_unchecked(seed.as_slice_less_safe())
}
}
@ -109,14 +117,14 @@ impl Ed25519KeyPair {
/// public key). This also detects any corruption of the public or private
/// key.
pub fn from_seed_and_public_key(
seed: untrusted::Input, public_key: untrusted::Input,
seed: &[u8], public_key: &[u8],
) -> Result<Self, error::KeyRejected> {
let pair = Self::from_seed_unchecked(seed)?;
// This implicitly verifies that `public_key` is the right length.
// XXX: This rejects ~18 keys when they are partially reduced, though
// those keys are virtually impossible to find.
if public_key != *pair.public_key.as_ref() {
if public_key != pair.public_key.as_ref() {
let err = if public_key.len() != pair.public_key.as_ref().len() {
error::KeyRejected::invalid_encoding()
} else {
@ -137,9 +145,8 @@ impl Ed25519KeyPair {
/// Since the public key is not given, the public key will be computed from
/// the private key. It is not possible to detect misuse or corruption of
/// the private key since the public key isn't given as input.
pub fn from_seed_unchecked(seed: untrusted::Input) -> Result<Self, error::KeyRejected> {
pub fn from_seed_unchecked(seed: &[u8]) -> Result<Self, error::KeyRejected> {
let seed = seed
.as_slice_less_safe()
.try_into_()
.map_err(|_| error::KeyRejected::invalid_encoding())?;
Ok(Self::from_seed_(seed))

View File

@ -102,12 +102,12 @@ impl EcdsaKeyPair {
/// `ECPrivateKey`, if present, must be the same named curve that is in the
/// algorithm identifier in the PKCS#8 header.
pub fn from_pkcs8(
alg: &'static EcdsaSigningAlgorithm, input: untrusted::Input,
alg: &'static EcdsaSigningAlgorithm, pkcs8: &[u8],
) -> Result<Self, error::KeyRejected> {
let key_pair = ec::suite_b::key_pair_from_pkcs8(
alg.curve,
alg.pkcs8_template,
input,
untrusted::Input::from(pkcs8),
cpu::features(),
)?;
Ok(Self::new(alg, key_pair))
@ -120,11 +120,14 @@ impl EcdsaKeyPair {
/// recommended to use `RsaPubeyPair::from_pkcs8()` (with a PKCS#8-encoded
/// key) instead.
pub fn from_private_key_and_public_key(
alg: &'static EcdsaSigningAlgorithm, private_key: untrusted::Input,
public_key: untrusted::Input,
alg: &'static EcdsaSigningAlgorithm, private_key: &[u8], public_key: &[u8],
) -> Result<Self, error::KeyRejected> {
let key_pair =
ec::suite_b::key_pair_from_bytes(alg.curve, private_key, public_key, cpu::features())?;
let key_pair = ec::suite_b::key_pair_from_bytes(
alg.curve,
untrusted::Input::from(private_key),
untrusted::Input::from(public_key),
cpu::features(),
)?;
Ok(Self::new(alg, key_pair))
}
@ -143,13 +146,13 @@ impl EcdsaKeyPair {
}
}
/// Returns the signature of the message `msg` using a random nonce
/// Returns the signature of the `message` using a random nonce
/// generated by `rng`.
pub fn sign(
&self, rng: &rand::SecureRandom, msg: untrusted::Input,
&self, rng: &rand::SecureRandom, message: &[u8],
) -> Result<signature::Signature, error::Unspecified> {
// Step 4 (out of order).
let h = digest::digest(self.alg.digest_alg, msg.as_slice_less_safe());
let h = digest::digest(self.alg.digest_alg, message);
self.sign_(rng, h)
}
@ -381,7 +384,6 @@ static EC_PUBLIC_KEY_P384_PKCS8_V1_TEMPLATE: pkcs8::Template = pkcs8::Template {
#[cfg(test)]
mod tests {
use crate::{signature, test};
use untrusted;
#[test]
fn signature_ecdsa_sign_fixed_test() {
@ -392,16 +394,9 @@ mod tests {
let curve_name = test_case.consume_string("Curve");
let digest_name = test_case.consume_string("Digest");
let msg = test_case.consume_bytes("Msg");
let msg = untrusted::Input::from(&msg);
let d = test_case.consume_bytes("d");
let d = untrusted::Input::from(&d);
let q = test_case.consume_bytes("Q");
let q = untrusted::Input::from(&q);
let k = test_case.consume_bytes("k");
let expected_result = test_case.consume_bytes("Sig");
@ -415,10 +410,10 @@ mod tests {
};
let private_key =
signature::EcdsaKeyPair::from_private_key_and_public_key(alg, d, q).unwrap();
signature::EcdsaKeyPair::from_private_key_and_public_key(alg, &d, &q).unwrap();
let rng = test::rand::FixedSliceRandom { bytes: &k };
let actual_result = private_key.sign(&rng, msg).unwrap();
let actual_result = private_key.sign(&rng, &msg).unwrap();
assert_eq!(actual_result.as_ref(), &expected_result[..]);
@ -436,16 +431,9 @@ mod tests {
let curve_name = test_case.consume_string("Curve");
let digest_name = test_case.consume_string("Digest");
let msg = test_case.consume_bytes("Msg");
let msg = untrusted::Input::from(&msg);
let d = test_case.consume_bytes("d");
let d = untrusted::Input::from(&d);
let q = test_case.consume_bytes("Q");
let q = untrusted::Input::from(&q);
let k = test_case.consume_bytes("k");
let expected_result = test_case.consume_bytes("Sig");
@ -459,10 +447,10 @@ mod tests {
};
let private_key =
signature::EcdsaKeyPair::from_private_key_and_public_key(alg, d, q).unwrap();
signature::EcdsaKeyPair::from_private_key_and_public_key(alg, &d, &q).unwrap();
let rng = test::rand::FixedSliceRandom { bytes: &k };
let actual_result = private_key.sign(&rng, msg).unwrap();
let actual_result = private_key.sign(&rng, &msg).unwrap();
assert_eq!(actual_result.as_ref(), &expected_result[..]);

View File

@ -136,14 +136,14 @@ impl RsaKeyPair {
///
/// [RFC 5958]:
/// https://tools.ietf.org/html/rfc5958
pub fn from_pkcs8(input: untrusted::Input) -> Result<Self, KeyRejected> {
pub fn from_pkcs8(pkcs8: &[u8]) -> Result<Self, KeyRejected> {
const RSA_ENCRYPTION: &[u8] = include_bytes!("../data/alg-rsa-encryption.der");
let (der, _) = pkcs8::unwrap_key_(
untrusted::Input::from(&RSA_ENCRYPTION),
pkcs8::Version::V1Only,
input,
untrusted::Input::from(pkcs8),
)?;
Self::from_der(der)
Self::from_der(der.as_slice_less_safe())
}
/// Parses an RSA private key that is not inside a PKCS#8 wrapper.
@ -161,8 +161,8 @@ impl RsaKeyPair {
///
/// [NIST SP-800-56B rev. 1]:
/// http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Br1.pdf
pub fn from_der(input: untrusted::Input) -> Result<Self, KeyRejected> {
input.read_all(KeyRejected::invalid_encoding(), |input| {
pub fn from_der(input: &[u8]) -> Result<Self, KeyRejected> {
untrusted::Input::from(input).read_all(KeyRejected::invalid_encoding(), |input| {
der::nested(
input,
der::Tag::Sequence,
@ -601,7 +601,6 @@ mod tests {
// We intentionally avoid `use super::*` so that we are sure to use only
// the public API; this ensures that enough of the API is public.
use crate::{rand, signature};
use untrusted;
// `KeyPair::sign` requires that the output buffer is the same length as
// the public key modulus. Test what happens when it isn't the same length.
@ -614,8 +613,7 @@ mod tests {
const PRIVATE_KEY_DER: &'static [u8] =
include_bytes!("signature_rsa_example_private_key.der");
let key_bytes_der = untrusted::Input::from(PRIVATE_KEY_DER);
let key_pair = signature::RsaKeyPair::from_der(key_bytes_der).unwrap();
let key_pair = signature::RsaKeyPair::from_der(PRIVATE_KEY_DER).unwrap();
// The output buffer is one byte too short.
let mut signature = vec![0; key_pair.public_modulus_len() - 1];

View File

@ -140,8 +140,7 @@
//! // Normally the application would store the PKCS#8 file persistently. Later
//! // it would read the PKCS#8 file from persistent storage to use it.
//!
//! let key_pair =
//! signature::Ed25519KeyPair::from_pkcs8(untrusted::Input::from(pkcs8_bytes.as_ref()))?;
//! let key_pair = signature::Ed25519KeyPair::from_pkcs8(pkcs8_bytes.as_ref())?;
//!
//! // Sign the message "hello, world".
//! const MESSAGE: &[u8] = b"hello, world";
@ -203,8 +202,7 @@
//! // Create an `RsaKeyPair` from the DER-encoded bytes. This example uses
//! // a 2048-bit key, but larger keys are also supported.
//! let private_key_der = read_file(private_key_path)?;
//! let private_key_der = untrusted::Input::from(&private_key_der);
//! let key_pair = signature::RsaKeyPair::from_der(private_key_der)
//! let key_pair = signature::RsaKeyPair::from_der(&private_key_der)
//! .map_err(|_| MyError::BadPrivateKey)?;
//!
//! // Sign the message "hello, world", using PKCS#1 v1.5 padding and the

View File

@ -75,12 +75,11 @@ fn ecdsa_from_pkcs8_test() {
};
let input = test_case.consume_bytes("Input");
let input = untrusted::Input::from(&input);
let error = test_case.consume_optional_string("Error");
match (
signature::EcdsaKeyPair::from_pkcs8(this_fixed, input),
signature::EcdsaKeyPair::from_pkcs8(this_fixed, &input),
error.clone(),
) {
(Ok(_), None) => (),
@ -90,7 +89,7 @@ fn ecdsa_from_pkcs8_test() {
};
match (
signature::EcdsaKeyPair::from_pkcs8(this_asn1, input),
signature::EcdsaKeyPair::from_pkcs8(this_asn1, &input),
error.clone(),
) {
(Ok(_), None) => (),
@ -99,8 +98,8 @@ fn ecdsa_from_pkcs8_test() {
(Err(actual), Some(expected)) => assert_eq!(actual.description(), expected),
};
assert!(signature::EcdsaKeyPair::from_pkcs8(other_fixed, input).is_err());
assert!(signature::EcdsaKeyPair::from_pkcs8(other_asn1, input).is_err());
assert!(signature::EcdsaKeyPair::from_pkcs8(other_fixed, &input).is_err());
assert!(signature::EcdsaKeyPair::from_pkcs8(other_asn1, &input).is_err());
Ok(())
},
@ -127,8 +126,7 @@ fn ecdsa_generate_pkcs8_test() {
println!();
#[cfg(feature = "use_heap")]
let _ = signature::EcdsaKeyPair::from_pkcs8(*alg, untrusted::Input::from(pkcs8.as_ref()))
.unwrap();
let _ = signature::EcdsaKeyPair::from_pkcs8(*alg, pkcs8.as_ref()).unwrap();
}
}
@ -225,7 +223,7 @@ fn ecdsa_test_public_key_coverage() {
let key_pair = signature::EcdsaKeyPair::from_pkcs8(
&signature::ECDSA_P256_SHA256_FIXED_SIGNING,
untrusted::Input::from(PRIVATE_KEY),
PRIVATE_KEY,
)
.unwrap();

View File

@ -43,7 +43,6 @@ fn test_signature_ed25519() {
assert_eq!(section, "");
let seed = test_case.consume_bytes("SEED");
assert_eq!(32, seed.len());
let seed = untrusted::Input::from(&seed);
let public_key = test_case.consume_bytes("PUB");
assert_eq!(32, public_key.len());
@ -53,19 +52,15 @@ fn test_signature_ed25519() {
let expected_sig = test_case.consume_bytes("SIG");
{
let key_pair =
Ed25519KeyPair::from_seed_and_public_key(seed, untrusted::Input::from(&public_key))
.unwrap();
let key_pair = Ed25519KeyPair::from_seed_and_public_key(&seed, &public_key).unwrap();
let actual_sig = key_pair.sign(&msg);
assert_eq!(&expected_sig[..], actual_sig.as_ref());
}
// Test PKCS#8 generation, parsing, and private-to-public calculations.
let rng = test::rand::FixedSliceRandom {
bytes: seed.as_slice_less_safe(),
};
let rng = test::rand::FixedSliceRandom { bytes: &seed };
let pkcs8 = Ed25519KeyPair::generate_pkcs8(&rng).unwrap();
let key_pair = Ed25519KeyPair::from_pkcs8(untrusted::Input::from(pkcs8.as_ref())).unwrap();
let key_pair = Ed25519KeyPair::from_pkcs8(pkcs8.as_ref()).unwrap();
assert_eq!(public_key, key_pair.public_key().as_ref());
// Test Signature generation.
@ -98,32 +93,16 @@ fn test_ed25519_from_seed_and_public_key_misuse() {
const PRIVATE_KEY: &[u8] = include_bytes!("ed25519_test_private_key.bin");
const PUBLIC_KEY: &[u8] = include_bytes!("ed25519_test_public_key.bin");
assert!(Ed25519KeyPair::from_seed_and_public_key(
untrusted::Input::from(PRIVATE_KEY),
untrusted::Input::from(PUBLIC_KEY)
)
.is_ok());
assert!(Ed25519KeyPair::from_seed_and_public_key(PRIVATE_KEY, PUBLIC_KEY).is_ok());
// Truncated private key.
assert!(Ed25519KeyPair::from_seed_and_public_key(
untrusted::Input::from(&PRIVATE_KEY[..31]),
untrusted::Input::from(PUBLIC_KEY)
)
.is_err());
assert!(Ed25519KeyPair::from_seed_and_public_key(&PRIVATE_KEY[..31], PUBLIC_KEY).is_err());
// Truncated public key.
assert!(Ed25519KeyPair::from_seed_and_public_key(
untrusted::Input::from(PRIVATE_KEY),
untrusted::Input::from(&PUBLIC_KEY[..31])
)
.is_err());
assert!(Ed25519KeyPair::from_seed_and_public_key(PRIVATE_KEY, &PUBLIC_KEY[..31]).is_err());
// Swapped public and private key.
assert!(Ed25519KeyPair::from_seed_and_public_key(
untrusted::Input::from(PUBLIC_KEY),
untrusted::Input::from(PRIVATE_KEY)
)
.is_err());
assert!(Ed25519KeyPair::from_seed_and_public_key(PUBLIC_KEY, PRIVATE_KEY).is_err());
}
#[test]
@ -137,7 +116,7 @@ fn test_ed25519_from_pkcs8_unchecked() {
let error = test_case.consume_optional_string("Error");
match (
Ed25519KeyPair::from_pkcs8_maybe_unchecked(untrusted::Input::from(&input)),
Ed25519KeyPair::from_pkcs8_maybe_unchecked(&input),
error.clone(),
) {
(Ok(_), None) => (),
@ -161,10 +140,7 @@ fn test_ed25519_from_pkcs8() {
let input = test_case.consume_bytes("Input");
let error = test_case.consume_optional_string("Error");
match (
Ed25519KeyPair::from_pkcs8(untrusted::Input::from(&input)),
error.clone(),
) {
match (Ed25519KeyPair::from_pkcs8(&input), error.clone()) {
(Ok(_), None) => (),
(Err(e), None) => panic!("Failed with error \"{}\", but expected to succeed", e),
(Ok(_), Some(e)) => panic!("Succeeded, but expected error \"{}\"", e),
@ -183,8 +159,7 @@ fn ed25519_test_public_key_coverage() {
const PUBLIC_KEY_DEBUG: &'static str =
"PublicKey(\"5809e9fef6dcec58f0f2e3b0d67e9880a11957e083ace85835c3b6c8fbaf6b7d\")";
let key_pair =
signature::Ed25519KeyPair::from_pkcs8(untrusted::Input::from(PRIVATE_KEY)).unwrap();
let key_pair = signature::Ed25519KeyPair::from_pkcs8(PRIVATE_KEY).unwrap();
// Test `AsRef<[u8]>`
assert_eq!(key_pair.public_key().as_ref(), PUBLIC_KEY);

View File

@ -51,11 +51,9 @@ fn rsa_from_pkcs8_test() {
assert_eq!(section, "");
let input = test_case.consume_bytes("Input");
let input = untrusted::Input::from(&input);
let error = test_case.consume_optional_string("Error");
match (signature::RsaKeyPair::from_pkcs8(input), error) {
match (signature::RsaKeyPair::from_pkcs8(&input), error) {
(Ok(_), None) => (),
(Err(e), None) => panic!("Failed with error \"{}\", but expected to succeed", e),
(Ok(_), Some(e)) => panic!("Succeeded, but expected error \"{}\"", e),
@ -89,8 +87,7 @@ fn test_signature_rsa_pkcs1_sign() {
let expected = test_case.consume_bytes("Sig");
let result = test_case.consume_string("Result");
let private_key = untrusted::Input::from(&private_key);
let key_pair = signature::RsaKeyPair::from_der(private_key);
let key_pair = signature::RsaKeyPair::from_der(&private_key);
if result == "Fail-Invalid-Key" {
assert!(key_pair.is_err());
return Ok(());
@ -128,8 +125,7 @@ fn test_signature_rsa_pss_sign() {
let result = test_case.consume_string("Result");
let private_key = test_case.consume_bytes("Key");
let private_key = untrusted::Input::from(&private_key);
let key_pair = signature::RsaKeyPair::from_der(private_key);
let key_pair = signature::RsaKeyPair::from_der(&private_key);
if key_pair.is_err() && result == "Fail-Invalid-Key" {
return Ok(());
}
@ -295,7 +291,7 @@ fn rsa_test_public_key_coverage() {
const PUBLIC_KEY: &[u8] = include_bytes!("rsa_test_public_key_2048.der");
const PUBLIC_KEY_DEBUG: &str = include_str!("rsa_test_public_key_2048_debug.txt");
let key_pair = signature::RsaKeyPair::from_pkcs8(untrusted::Input::from(PRIVATE_KEY)).unwrap();
let key_pair = signature::RsaKeyPair::from_pkcs8(PRIVATE_KEY).unwrap();
// Test `AsRef<[u8]>`
assert_eq!(key_pair.public_key().as_ref(), PUBLIC_KEY);