Remove untrusted
from the ring::agreement
API.
This commit is contained in:
parent
cfe46261e8
commit
888bdd506f
@ -23,7 +23,6 @@
|
||||
//! ```
|
||||
//! # fn x25519_agreement_example() -> Result<(), ring::error::Unspecified> {
|
||||
//! use ring::{agreement, rand};
|
||||
//! use untrusted;
|
||||
//!
|
||||
//! let rng = rand::SystemRandom::new();
|
||||
//!
|
||||
@ -34,23 +33,21 @@
|
||||
//! // message.
|
||||
//! let my_public_key = my_private_key.compute_public_key()?;
|
||||
//!
|
||||
//! // In a real application, the peer public key would be parsed out of a
|
||||
//! // protocol message. Here we just generate one.
|
||||
//! let peer_public_key = {
|
||||
//! let peer_private_key = agreement::EphemeralPrivateKey::generate(&agreement::X25519, &rng)?;
|
||||
//! peer_private_key.compute_public_key()?
|
||||
//! };
|
||||
//! let peer_public_key = untrusted::Input::from(peer_public_key.as_ref());
|
||||
//! // In a real application, the peer public key would be parsed out of a
|
||||
//! // protocol message. Here we just generate one.
|
||||
//! let peer_public_key = {
|
||||
//! let peer_private_key =
|
||||
//! agreement::EphemeralPrivateKey::generate(&agreement::X25519, &rng)?;
|
||||
//! peer_private_key.compute_public_key()?
|
||||
//! };
|
||||
//!
|
||||
//! // In a real application, the protocol specifies how to determine what
|
||||
//! // algorithm was used to generate the peer's private key. Here, we know it
|
||||
//! // is X25519 since we just generated it.
|
||||
//! let peer_public_key_alg = &agreement::X25519;
|
||||
//! agreement::UnparsedPublicKey::new(&agreement::X25519, peer_public_key)
|
||||
//! };
|
||||
//!
|
||||
//! agreement::agree_ephemeral(
|
||||
//! my_private_key,
|
||||
//! peer_public_key_alg,
|
||||
//! peer_public_key,
|
||||
//! &peer_public_key,
|
||||
//! ring::error::Unspecified,
|
||||
//! |_key_material| {
|
||||
//! // In a real application, we'd apply a KDF to the key material and the
|
||||
@ -139,6 +136,31 @@ impl AsRef<[u8]> for PublicKey {
|
||||
|
||||
derive_debug_self_as_ref_hex_bytes!(PublicKey);
|
||||
|
||||
/// An unparsed (possibly invalid) public key for key agreement.
|
||||
pub struct UnparsedPublicKey<B: AsRef<[u8]>> {
|
||||
algorithm: &'static Algorithm,
|
||||
bytes: B,
|
||||
}
|
||||
|
||||
impl<B: Copy> Copy for UnparsedPublicKey<B> where B: AsRef<[u8]> {}
|
||||
|
||||
impl<B: Clone> Clone for UnparsedPublicKey<B>
|
||||
where
|
||||
B: AsRef<[u8]>,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
algorithm: self.algorithm,
|
||||
bytes: self.bytes.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: AsRef<[u8]>> UnparsedPublicKey<B> {
|
||||
/// Constructs a new `UnparsedPublicKey`.
|
||||
pub fn new(algorithm: &'static Algorithm, bytes: B) -> Self { Self { algorithm, bytes } }
|
||||
}
|
||||
|
||||
/// Performs a key agreement with an ephemeral private key and the given public
|
||||
/// key.
|
||||
///
|
||||
@ -146,14 +168,12 @@ derive_debug_self_as_ref_hex_bytes!(PublicKey);
|
||||
/// will not be usable after calling `agree_ephemeral`, thus guaranteeing that
|
||||
/// the key is used for only one key agreement.
|
||||
///
|
||||
/// `peer_public_key_alg` is the algorithm/curve for the peer's public key
|
||||
/// point; `agree_ephemeral` will return `Err(error_value)` if it does not
|
||||
/// match `my_private_key's` algorithm/curve.
|
||||
///
|
||||
/// `peer_public_key` is the peer's public key. `agree_ephemeral` verifies that
|
||||
/// it is encoded in the standard form for the algorithm and that the key is
|
||||
/// *valid*; see the algorithm's documentation for details on how keys are to
|
||||
/// be encoded and what constitutes a valid key for that algorithm.
|
||||
/// `peer_public_key` is the peer's public key. `agree_ephemeral` will return
|
||||
/// `Err(error_value)` if it does not match `my_private_key's` algorithm/curve.
|
||||
/// `agree_ephemeral` verifies that it is encoded in the standard form for the
|
||||
/// algorithm and that the key is *valid*; see the algorithm's documentation for
|
||||
/// details on how keys are to be encoded and what constitutes a valid key for
|
||||
/// that algorithm.
|
||||
///
|
||||
/// `error_value` is the value to return if an error occurs before `kdf` is
|
||||
/// called, e.g. when decoding of the peer's public key fails or when the public
|
||||
@ -162,9 +182,24 @@ derive_debug_self_as_ref_hex_bytes!(PublicKey);
|
||||
/// After the key agreement is done, `agree_ephemeral` calls `kdf` with the raw
|
||||
/// key material from the key agreement operation and then returns what `kdf`
|
||||
/// returns.
|
||||
pub fn agree_ephemeral<F, R, E>(
|
||||
my_private_key: EphemeralPrivateKey, peer_public_key_alg: &Algorithm,
|
||||
peer_public_key: untrusted::Input, error_value: E, kdf: F,
|
||||
#[inline]
|
||||
pub fn agree_ephemeral<B: AsRef<[u8]>, F, R, E>(
|
||||
my_private_key: EphemeralPrivateKey, peer_public_key: &UnparsedPublicKey<B>, error_value: E,
|
||||
kdf: F,
|
||||
) -> Result<R, E>
|
||||
where
|
||||
F: FnOnce(&[u8]) -> Result<R, E>,
|
||||
{
|
||||
let peer_public_key = UnparsedPublicKey {
|
||||
algorithm: peer_public_key.algorithm,
|
||||
bytes: peer_public_key.bytes.as_ref(),
|
||||
};
|
||||
agree_ephemeral_(my_private_key, peer_public_key, error_value, kdf)
|
||||
}
|
||||
|
||||
fn agree_ephemeral_<F, R, E>(
|
||||
my_private_key: EphemeralPrivateKey, peer_public_key: UnparsedPublicKey<&[u8]>, error_value: E,
|
||||
kdf: F,
|
||||
) -> Result<R, E>
|
||||
where
|
||||
F: FnOnce(&[u8]) -> Result<R, E>,
|
||||
@ -174,7 +209,7 @@ where
|
||||
// The domain parameters are hard-coded. This check verifies that the
|
||||
// peer's public key's domain parameters match the domain parameters of
|
||||
// this private key.
|
||||
if peer_public_key_alg != my_private_key.alg {
|
||||
if peer_public_key.algorithm != my_private_key.alg {
|
||||
return Err(error_value);
|
||||
}
|
||||
|
||||
@ -197,8 +232,12 @@ where
|
||||
//
|
||||
// We have a pretty liberal interpretation of the NIST's spec's "Destroy"
|
||||
// that doesn't meet the NSA requirement to "zeroize."
|
||||
(alg.ecdh)(shared_key, &my_private_key.private_key, peer_public_key)
|
||||
.map_err(|_| error_value)?;
|
||||
(alg.ecdh)(
|
||||
shared_key,
|
||||
&my_private_key.private_key,
|
||||
untrusted::Input::from(peer_public_key.bytes),
|
||||
)
|
||||
.map_err(|_| error_value)?;
|
||||
|
||||
// NSA Guide Steps 5 and 6.
|
||||
//
|
||||
|
@ -42,32 +42,28 @@ fn agreement_agree_ephemeral() {
|
||||
|
||||
let curve_name = test_case.consume_string("Curve");
|
||||
let alg = alg_from_curve_name(&curve_name);
|
||||
let peer_public = test_case.consume_bytes("PeerQ");
|
||||
let peer_public = untrusted::Input::from(&peer_public);
|
||||
let peer_public = agreement::UnparsedPublicKey::new(alg, test_case.consume_bytes("PeerQ"));
|
||||
|
||||
match test_case.consume_optional_string("Error") {
|
||||
None => {
|
||||
let my_private = test_case.consume_bytes("D");
|
||||
let rng = test::rand::FixedSliceRandom { bytes: &my_private };
|
||||
let my_private = agreement::EphemeralPrivateKey::generate(alg, &rng)?;
|
||||
|
||||
let my_private = {
|
||||
let rng = test::rand::FixedSliceRandom { bytes: &my_private };
|
||||
agreement::EphemeralPrivateKey::generate(alg, &rng)?
|
||||
};
|
||||
let my_public = test_case.consume_bytes("MyQ");
|
||||
let output = test_case.consume_bytes("Output");
|
||||
|
||||
let computed_public = my_private.compute_public_key().unwrap();
|
||||
assert_eq!(computed_public.as_ref(), &my_public[..]);
|
||||
|
||||
assert!(agreement::agree_ephemeral(
|
||||
my_private,
|
||||
alg,
|
||||
peer_public,
|
||||
(),
|
||||
|key_material| {
|
||||
assert!(
|
||||
agreement::agree_ephemeral(my_private, &peer_public, (), |key_material| {
|
||||
assert_eq!(key_material, &output[..]);
|
||||
Ok(())
|
||||
}
|
||||
)
|
||||
.is_ok());
|
||||
})
|
||||
.is_ok()
|
||||
);
|
||||
},
|
||||
|
||||
Some(_) => {
|
||||
@ -82,8 +78,7 @@ fn agreement_agree_ephemeral() {
|
||||
}
|
||||
assert!(agreement::agree_ephemeral(
|
||||
dummy_private_key,
|
||||
alg,
|
||||
peer_public,
|
||||
&peer_public,
|
||||
(),
|
||||
kdf_not_called
|
||||
)
|
||||
@ -151,11 +146,10 @@ fn x25519(private_key: &[u8], public_key: &[u8]) -> Vec<u8> {
|
||||
fn x25519_(private_key: &[u8], public_key: &[u8]) -> Result<Vec<u8>, error::Unspecified> {
|
||||
let rng = test::rand::FixedSliceRandom { bytes: private_key };
|
||||
let private_key = agreement::EphemeralPrivateKey::generate(&agreement::X25519, &rng)?;
|
||||
let public_key = untrusted::Input::from(public_key);
|
||||
let public_key = agreement::UnparsedPublicKey::new(&agreement::X25519, public_key);
|
||||
agreement::agree_ephemeral(
|
||||
private_key,
|
||||
&agreement::X25519,
|
||||
public_key,
|
||||
&public_key,
|
||||
error::Unspecified,
|
||||
|agreed_value| Ok(Vec::from(agreed_value)),
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user