From e79faabb55898344297da8c5f30e702a2482f756 Mon Sep 17 00:00:00 2001 From: Justin Smith Date: Mon, 9 Sep 2024 09:15:37 -0400 Subject: [PATCH] Allow parsing of EC public keys, get format --- aws-lc-rs/src/agreement.rs | 208 ++++++++++++++++----------- aws-lc-rs/src/agreement/ephemeral.rs | 10 +- aws-lc-rs/src/ec.rs | 184 +++++++++++++++++++----- 3 files changed, 273 insertions(+), 129 deletions(-) diff --git a/aws-lc-rs/src/agreement.rs b/aws-lc-rs/src/agreement.rs index 2de2a6211a3..5b4a44bed4d 100644 --- a/aws-lc-rs/src/agreement.rs +++ b/aws-lc-rs/src/agreement.rs @@ -51,6 +51,7 @@ //! ``` mod ephemeral; +pub use ec::ParsedPublicKeyFormat; pub use ephemeral::{agree_ephemeral, EphemeralPrivateKey}; use crate::cbb::LcCBB; @@ -60,12 +61,11 @@ use crate::fips::indicator_check; use crate::ptr::{ConstPointer, LcPtr}; use crate::{ec, hex}; use aws_lc::{ - CBS_init, EVP_PKEY_CTX_new_id, EVP_PKEY_bits, EVP_PKEY_derive, EVP_PKEY_derive_init, + EVP_PKEY_CTX_new_id, EVP_PKEY_bits, EVP_PKEY_derive, EVP_PKEY_derive_init, EVP_PKEY_derive_set_peer, EVP_PKEY_get0_EC_KEY, EVP_PKEY_get_raw_private_key, - EVP_PKEY_get_raw_public_key, EVP_PKEY_id, EVP_PKEY_keygen, EVP_PKEY_keygen_init, - EVP_PKEY_new_raw_private_key, EVP_PKEY_new_raw_public_key, EVP_marshal_public_key, - EVP_parse_public_key, NID_X9_62_prime256v1, NID_secp384r1, NID_secp521r1, BIGNUM, CBS, - EVP_PKEY, EVP_PKEY_X25519, NID_X25519, + EVP_PKEY_get_raw_public_key, EVP_PKEY_keygen, EVP_PKEY_keygen_init, + EVP_PKEY_new_raw_private_key, EVP_marshal_public_key, NID_X9_62_prime256v1, NID_secp256k1, + NID_secp384r1, NID_secp521r1, BIGNUM, EVP_PKEY, EVP_PKEY_X25519, NID_X25519, }; use crate::encoding::{ @@ -75,7 +75,6 @@ use crate::encoding::{ use core::fmt; use core::fmt::{Debug, Formatter}; use core::ptr::null_mut; -use std::mem::MaybeUninit; #[allow(non_camel_case_types)] #[derive(PartialEq, Eq)] @@ -683,6 +682,47 @@ pub struct UnparsedPublicKey> { bytes: B, } +/// A parsed public key for key agreement. +#[derive(Debug)] +pub struct ParsedPublicKey(ec::ParsedPublicKey); + +impl ParsedPublicKey { + /// The format of the public key. + #[must_use] + pub fn format(&self) -> ParsedPublicKeyFormat { + self.0.format() + } + /// The algorithm of the public key. + #[must_use] + #[allow(non_upper_case_globals)] + pub fn alg(&self) -> &'static Algorithm { + match self.0.nid() { + NID_X25519 => &X25519, + NID_secp256k1 => &ECDH_P256, + NID_secp384r1 => &ECDH_P384, + NID_secp521r1 => &ECDH_P521, + _ => unreachable!("Unreachable agreement algorithm nid: {}", self.0.nid()), + } + } + #[allow(dead_code)] + fn key(&self) -> &LcPtr { + self.0.key() + } + fn key_mut(&mut self) -> &mut LcPtr { + self.0.key_mut() + } +} + +impl> UnparsedPublicKey { + #[allow(dead_code)] + fn parse(&self) -> Result { + Ok(ParsedPublicKey(ec::ParsedPublicKey::new( + &self.bytes, + self.alg.id.nid(), + )?)) + } +} + impl> Copy for UnparsedPublicKey {} impl> Debug for UnparsedPublicKey { @@ -715,6 +755,23 @@ impl> UnparsedPublicKey { } } +impl> TryFrom<&UnparsedPublicKey> for ParsedPublicKey { + type Error = Unspecified; + fn try_from(upk: &UnparsedPublicKey) -> Result { + Ok(ParsedPublicKey(ec::ParsedPublicKey::new( + &upk.bytes, + upk.alg.id.nid(), + )?)) + } +} + +impl> TryFrom> for ParsedPublicKey { + type Error = Unspecified; + fn try_from(upk: UnparsedPublicKey) -> Result { + Self::try_from(&upk) + } +} + /// Performs a key agreement with a private key and the given public key. /// /// `my_private_key` is the private key to use. Only a reference to the key @@ -744,37 +801,34 @@ impl> UnparsedPublicKey { /// `error_value` on internal failure. #[inline] #[allow(clippy::missing_panics_doc)] -pub fn agree, F, R, E>( +pub fn agree + Debug, F, R, E>( my_private_key: &PrivateKey, - peer_public_key: &UnparsedPublicKey, + peer_public_key: B, error_value: E, kdf: F, ) -> Result where F: FnOnce(&[u8]) -> Result, { - let expected_alg = my_private_key.algorithm(); - let expected_nid = expected_alg.id.nid(); + let peer_pub_key = peer_public_key.try_into(); + if let Ok(mut peer_pub_key) = peer_pub_key { + let mut buffer = [0u8; MAX_AGREEMENT_SECRET_LEN]; - if peer_public_key.alg != expected_alg { - return Err(error_value); + let secret: &[u8] = match &my_private_key.inner_key { + KeyInner::X25519(priv_key) => { + x25519_diffie_hellman(&mut buffer, priv_key, peer_pub_key.key_mut()) + .or(Err(error_value))? + } + KeyInner::ECDH_P256(priv_key) + | KeyInner::ECDH_P384(priv_key) + | KeyInner::ECDH_P521(priv_key) => { + ec_key_ecdh(&mut buffer, priv_key, peer_pub_key.key_mut()).or(Err(error_value))? + } + }; + kdf(secret) + } else { + Err(error_value) } - - let peer_pub_bytes = peer_public_key.bytes.as_ref(); - - let mut buffer = [0u8; MAX_AGREEMENT_SECRET_LEN]; - - let secret: &[u8] = match &my_private_key.inner_key { - KeyInner::X25519(priv_key) => { - x25519_diffie_hellman(&mut buffer, priv_key, peer_pub_bytes).or(Err(error_value))? - } - KeyInner::ECDH_P256(priv_key) - | KeyInner::ECDH_P384(priv_key) - | KeyInner::ECDH_P521(priv_key) => { - ec_key_ecdh(&mut buffer, priv_key, peer_pub_bytes, expected_nid).or(Err(error_value))? - } - }; - kdf(secret) } // Current max secret length is P-521's. @@ -785,18 +839,15 @@ const MAX_AGREEMENT_SECRET_LEN: usize = AlgorithmID::ECDH_P521.private_key_len() fn ec_key_ecdh<'a>( buffer: &'a mut [u8; MAX_AGREEMENT_SECRET_LEN], priv_key: &LcPtr, - peer_pub_key_bytes: &[u8], - nid: i32, + peer_pub_key: &mut LcPtr, ) -> Result<&'a [u8], ()> { - let mut pub_key = ec::try_parse_public_key_bytes(peer_pub_key_bytes, nid)?; - let mut pkey_ctx = priv_key.create_EVP_PKEY_CTX()?; if 1 != unsafe { EVP_PKEY_derive_init(*pkey_ctx.as_mut()) } { return Err(()); }; - if 1 != unsafe { EVP_PKEY_derive_set_peer(*pkey_ctx.as_mut(), *pub_key.as_mut()) } { + if 1 != unsafe { EVP_PKEY_derive_set_peer(*pkey_ctx.as_mut(), *peer_pub_key.as_mut()) } { return Err(()); } @@ -819,7 +870,7 @@ fn ec_key_ecdh<'a>( fn x25519_diffie_hellman<'a>( buffer: &'a mut [u8; MAX_AGREEMENT_SECRET_LEN], priv_key: &LcPtr, - peer_pub_key: &[u8], + peer_pub_key: &mut LcPtr, ) -> Result<&'a [u8], ()> { let mut pkey_ctx = priv_key.create_EVP_PKEY_CTX()?; @@ -827,9 +878,7 @@ fn x25519_diffie_hellman<'a>( return Err(()); }; - let mut pub_key = try_parse_x25519_public_key_bytes(peer_pub_key)?; - - if 1 != unsafe { EVP_PKEY_derive_set_peer(*pkey_ctx.as_mut(), *pub_key.as_mut()) } { + if 1 != unsafe { EVP_PKEY_derive_set_peer(*pkey_ctx.as_mut(), *peer_pub_key.as_mut()) } { return Err(()); } @@ -846,53 +895,13 @@ fn x25519_diffie_hellman<'a>( Ok(&buffer[0..AlgorithmID::X25519.pub_key_len()]) } -pub(crate) fn try_parse_x25519_public_key_bytes( - key_bytes: &[u8], -) -> Result, Unspecified> { - try_parse_x25519_subject_public_key_info_bytes(key_bytes) - .or(try_parse_x25519_public_key_raw_bytes(key_bytes)) -} - -fn try_parse_x25519_public_key_raw_bytes(key_bytes: &[u8]) -> Result, Unspecified> { - let expected_pub_key_len = X25519.id.pub_key_len(); - if key_bytes.len() != expected_pub_key_len { - return Err(Unspecified); - } - - Ok(LcPtr::new(unsafe { - EVP_PKEY_new_raw_public_key( - EVP_PKEY_X25519, - null_mut(), - key_bytes.as_ptr(), - key_bytes.len(), - ) - })?) -} - -fn try_parse_x25519_subject_public_key_info_bytes( - key_bytes: &[u8], -) -> Result, Unspecified> { - // Try to parse as SubjectPublicKeyInfo first - let mut cbs = { - let mut cbs = MaybeUninit::::uninit(); - unsafe { - CBS_init(cbs.as_mut_ptr(), key_bytes.as_ptr(), key_bytes.len()); - cbs.assume_init() - } - }; - let evp_pkey = LcPtr::new(unsafe { EVP_parse_public_key(&mut cbs) })?; - if EVP_PKEY_X25519 != unsafe { EVP_PKEY_id(*evp_pkey.as_const()) } { - return Err(Unspecified); - } - Ok(evp_pkey) -} - #[cfg(test)] mod tests { use crate::agreement::{ - agree, Algorithm, PrivateKey, PublicKey, UnparsedPublicKey, ECDH_P256, ECDH_P384, - ECDH_P521, X25519, + agree, Algorithm, ParsedPublicKey, PrivateKey, PublicKey, UnparsedPublicKey, ECDH_P256, + ECDH_P384, ECDH_P521, X25519, }; + use crate::ec::ParsedPublicKeyFormat; use crate::encoding::{ AsBigEndian, AsDer, Curve25519SeedBin, EcPrivateKeyBin, EcPrivateKeyRfc5915Der, EcPublicKeyCompressedBin, EcPublicKeyUncompressedBin, PublicKeyX509Der, @@ -961,15 +970,10 @@ mod tests { #[test] fn test_agreement_invalid_keys() { fn test_with_key(alg: &'static Algorithm, my_private_key: &PrivateKey, test_key: &[u8]) { + let public_key = &UnparsedPublicKey::new(alg, test_key); assert!(PrivateKey::from_private_key(alg, test_key).is_err()); assert!(PrivateKey::from_private_key_der(alg, test_key).is_err()); - assert!(agree( - my_private_key, - &UnparsedPublicKey::new(alg, test_key), - (), - |_| Ok(()) - ) - .is_err()); + assert!(agree(my_private_key, public_key, (), |_| Ok(())).is_err()); } let alg_variants: [&'static Algorithm; 4] = [&X25519, &ECDH_P256, &ECDH_P384, &ECDH_P521]; @@ -1345,17 +1349,47 @@ mod tests { if verify_ec_raw_traits { let raw = AsBigEndian::::as_be_bytes(public_key).unwrap(); + public_key_formats_verifier( + public_key.algorithm(), + raw.as_ref(), + ParsedPublicKeyFormat::Compressed, + ); public_keys.push(raw.as_ref().into()); let raw = AsBigEndian::::as_be_bytes(public_key).unwrap(); + public_key_formats_verifier( + public_key.algorithm(), + raw.as_ref(), + ParsedPublicKeyFormat::Uncompressed, + ); public_keys.push(raw.as_ref().into()); } let peer_x509 = AsDer::::as_der(public_key).unwrap(); + public_key_formats_verifier( + public_key.algorithm(), + peer_x509.as_ref(), + ParsedPublicKeyFormat::X509, + ); public_keys.push(peer_x509.as_ref().into()); public_keys } + fn public_key_formats_verifier>( + algorith: &'static Algorithm, + pub_key_bytes: B, + expected_format: ParsedPublicKeyFormat, + ) { + let upk = UnparsedPublicKey::new(algorith, pub_key_bytes); + let parsed_public_key: ParsedPublicKey = upk.try_into().unwrap(); + assert_eq!( + parsed_public_key.format(), + expected_format, + "Expected: {expected_format:?} Actual: {:?}", + parsed_public_key.format() + ); + } + #[test] fn private_key_drop() { let private_key = PrivateKey::generate(&ECDH_P256).unwrap(); diff --git a/aws-lc-rs/src/agreement/ephemeral.rs b/aws-lc-rs/src/agreement/ephemeral.rs index 0e3c4b00981..3c2710963d1 100644 --- a/aws-lc-rs/src/agreement/ephemeral.rs +++ b/aws-lc-rs/src/agreement/ephemeral.rs @@ -1,7 +1,7 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 OR ISC -use crate::agreement::{agree, Algorithm, PrivateKey, PublicKey, UnparsedPublicKey}; +use crate::agreement::{agree, Algorithm, ParsedPublicKey, PrivateKey, PublicKey}; use crate::error::Unspecified; use crate::rand::SecureRandom; use core::fmt; @@ -98,9 +98,9 @@ impl EphemeralPrivateKey { #[allow(clippy::needless_pass_by_value)] #[allow(clippy::missing_panics_doc)] #[allow(clippy::module_name_repetitions)] -pub fn agree_ephemeral, F, R, E>( +pub fn agree_ephemeral + Debug, F, R, E>( my_private_key: EphemeralPrivateKey, - peer_public_key: &UnparsedPublicKey, + peer_public_key: B, error_value: E, kdf: F, ) -> Result @@ -494,8 +494,8 @@ mod tests { let rng = test::rand::FixedSliceRandom { bytes: private_key }; let private_key = agreement::EphemeralPrivateKey::generate_for_test(&agreement::X25519, &rng)?; - let public_key = agreement::UnparsedPublicKey::new(&agreement::X25519, public_key); - agreement::agree_ephemeral(private_key, &public_key, Unspecified, |agreed_value| { + let public_key = &agreement::UnparsedPublicKey::new(&agreement::X25519, public_key); + agreement::agree_ephemeral(private_key, public_key, Unspecified, |agreed_value| { Ok(Vec::from(agreed_value)) }) } diff --git a/aws-lc-rs/src/ec.rs b/aws-lc-rs/src/ec.rs index 14c3dee7aa8..39766b40d9c 100644 --- a/aws-lc-rs/src/ec.rs +++ b/aws-lc-rs/src/ec.rs @@ -28,9 +28,10 @@ use aws_lc::{ EC_KEY_set_private_key, EC_KEY_set_public_key, EC_POINT_mul, EC_POINT_new, EC_POINT_oct2point, EC_POINT_point2oct, EVP_DigestVerify, EVP_DigestVerifyInit, EVP_PKEY_CTX_new_id, EVP_PKEY_CTX_set_ec_paramgen_curve_nid, EVP_PKEY_assign_EC_KEY, EVP_PKEY_get0_EC_KEY, - EVP_PKEY_keygen, EVP_PKEY_keygen_init, EVP_PKEY_new, EVP_parse_public_key, - NID_X9_62_prime256v1, NID_secp256k1, NID_secp384r1, NID_secp521r1, BIGNUM, CBS, ECDSA_SIG, - EC_GROUP, EC_KEY, EC_POINT, EVP_PKEY, EVP_PKEY_EC, + EVP_PKEY_id, EVP_PKEY_keygen, EVP_PKEY_keygen_init, EVP_PKEY_new, EVP_PKEY_new_raw_public_key, + EVP_parse_public_key, NID_X9_62_prime256v1, NID_secp256k1, NID_secp384r1, NID_secp521r1, + BIGNUM, CBS, ECDSA_SIG, EC_GROUP, EC_KEY, EC_POINT, EVP_PKEY, EVP_PKEY_EC, EVP_PKEY_X25519, + NID_X25519, }; use crate::digest::digest_ctx::DigestContext; @@ -64,6 +65,133 @@ pub(crate) const PUBLIC_KEY_MAX_LEN: usize = 1 + (2 * ELEM_MAX_BYTES); /// `42` is the length of the P-521 template. pub const PKCS8_DOCUMENT_MAX_LEN: usize = 42 + SCALAR_MAX_BYTES + PUBLIC_KEY_MAX_LEN; +#[derive(Debug)] +pub(crate) struct ParsedPublicKey { + format: ParsedPublicKeyFormat, + nid: i32, + key: LcPtr, +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +/// The format of a parsed public key. +/// +/// This is used to distinguish between different types of public key formats +/// supported by *aws-lc-rs*. +#[non_exhaustive] +pub enum ParsedPublicKeyFormat { + /// The key is in an X.509 SubjectPublicKeyInfo format. + X509, + /// The key is in an uncompressed form (X9.62). + Uncompressed, + /// The key is in a compressed form (SEC 1: Elliptic Curve Cryptography, Version 2.0). + Compressed, + /// The key is in a raw form. + Raw, +} + +/// A parsed public key for key agreement. +impl ParsedPublicKey { + pub fn nid(&self) -> i32 { + self.nid + } + + pub fn format(&self) -> ParsedPublicKeyFormat { + self.format + } + + pub(crate) fn key(&self) -> &LcPtr { + &self.key + } + + pub(crate) fn key_mut(&mut self) -> &mut LcPtr { + &mut self.key + } +} + +impl ParsedPublicKey { + #[allow(non_upper_case_globals)] + pub(crate) fn new(bytes: impl AsRef<[u8]>, nid: i32) -> Result { + let key_bytes = bytes.as_ref(); + if key_bytes.is_empty() { + return Err(KeyRejected::unspecified()); + } + let format = match key_bytes[0] { + 0x04 => ParsedPublicKeyFormat::Uncompressed, + 0x02 | 0x03 => ParsedPublicKeyFormat::Compressed, + _ => ParsedPublicKeyFormat::X509, + }; + match nid { + NID_X25519 => { + let pub_key = try_parse_x25519_public_key_bytes(key_bytes)?; + Ok(ParsedPublicKey { + format, + nid: NID_X25519, + key: pub_key, + }) + } + NID_X9_62_prime256v1 | NID_secp256k1 | NID_secp384r1 | NID_secp521r1 => { + try_parse_subject_public_key_info_bytes(key_bytes) + .and_then(|key| { + validate_evp_key(&key.as_const(), nid).map(|()| ParsedPublicKey { + format: ParsedPublicKeyFormat::X509, + nid, + key, + }) + }) + .or( + try_parse_public_key_raw_bytes(key_bytes, nid).map(|key| ParsedPublicKey { + format, + nid, + key, + }), + ) + } + _ => Err(KeyRejected::unspecified()), + } + } +} + +pub(crate) fn try_parse_x25519_public_key_bytes( + key_bytes: &[u8], +) -> Result, Unspecified> { + try_parse_x25519_subject_public_key_info_bytes(key_bytes) + .or(try_parse_x25519_public_key_raw_bytes(key_bytes)) +} + +fn try_parse_x25519_public_key_raw_bytes(key_bytes: &[u8]) -> Result, Unspecified> { + const EXPECTED_PUB_KEY_LEN: usize = 32; + if key_bytes.len() != EXPECTED_PUB_KEY_LEN { + return Err(Unspecified); + } + + Ok(LcPtr::new(unsafe { + EVP_PKEY_new_raw_public_key( + EVP_PKEY_X25519, + null_mut(), + key_bytes.as_ptr(), + key_bytes.len(), + ) + })?) +} + +fn try_parse_x25519_subject_public_key_info_bytes( + key_bytes: &[u8], +) -> Result, Unspecified> { + // Try to parse as SubjectPublicKeyInfo first + let mut cbs = { + let mut cbs = MaybeUninit::::uninit(); + unsafe { + CBS_init(cbs.as_mut_ptr(), key_bytes.as_ptr(), key_bytes.len()); + cbs.assume_init() + } + }; + let evp_pkey = LcPtr::new(unsafe { EVP_parse_public_key(&mut cbs) })?; + if EVP_PKEY_X25519 != unsafe { EVP_PKEY_id(*evp_pkey.as_const()) } { + return Err(Unspecified); + } + Ok(evp_pkey) +} + /// An ECDSA verification algorithm. #[derive(Debug, Eq, PartialEq)] pub struct EcdsaVerificationAlgorithm { @@ -243,12 +371,13 @@ impl VerificationAlgorithm for EcdsaVerificationAlgorithm { msg: &[u8], signature: &[u8], ) -> Result<(), Unspecified> { + let mut pkey = ParsedPublicKey::new(public_key, self.id.nid())?; match self.sig_format { EcdsaSignatureFormat::ASN1 => { - verify_asn1_signature(self.id, self.digest, public_key, msg, signature) + verify_asn1_signature(self.digest, pkey.key_mut(), msg, signature) } EcdsaSignatureFormat::Fixed => { - verify_fixed_signature(self.id, self.digest, public_key, msg, signature) + verify_fixed_signature(self.id, self.digest, pkey.key_mut(), msg, signature) } } } @@ -257,7 +386,7 @@ impl VerificationAlgorithm for EcdsaVerificationAlgorithm { fn verify_fixed_signature( alg: &'static AlgorithmID, digest: &'static digest::Algorithm, - public_key: &[u8], + public_key: &mut LcPtr, msg: &[u8], signature: &[u8], ) -> Result<(), Unspecified> { @@ -271,18 +400,15 @@ fn verify_fixed_signature( } let out_bytes = LcPtr::new(out_bytes)?; let signature = unsafe { out_bytes.as_slice(out_bytes_len.assume_init()) }; - verify_asn1_signature(alg, digest, public_key, msg, signature) + verify_asn1_signature(digest, public_key, msg, signature) } fn verify_asn1_signature( - alg: &'static AlgorithmID, digest: &'static digest::Algorithm, - public_key: &[u8], + public_key: &mut LcPtr, msg: &[u8], signature: &[u8], ) -> Result<(), Unspecified> { - let mut pkey = try_parse_public_key_bytes(public_key, alg.nid())?; - let mut md_ctx = DigestContext::new_uninit(); let digest = digest::match_digest_type(&digest.id); @@ -293,7 +419,7 @@ fn verify_asn1_signature( null_mut(), *digest, null_mut(), - *pkey.as_mut(), + *public_key.as_mut(), ) } { return Err(Unspecified); @@ -340,7 +466,7 @@ pub(crate) fn verify_evp_key_nid( } #[inline] -fn validate_evp_key( +pub(crate) fn validate_evp_key( evp_pkey: &ConstPointer, expected_curve_nid: i32, ) -> Result<(), KeyRejected> { @@ -446,25 +572,9 @@ pub(crate) fn public_key_from_evp_pkey( }) } -pub(crate) fn try_parse_public_key_bytes( - key_bytes: &[u8], - expected_curve_nid: i32, -) -> Result, Unspecified> { - try_parse_subject_public_key_info_bytes(key_bytes) - .and_then(|key| { - validate_evp_key(&key.as_const(), expected_curve_nid) - .map(|()| key) - .map_err(|_| Unspecified) - }) - .or(try_parse_public_key_raw_bytes( - key_bytes, - expected_curve_nid, - )) -} - -fn try_parse_subject_public_key_info_bytes( +pub(crate) fn try_parse_subject_public_key_info_bytes( key_bytes: &[u8], -) -> Result, Unspecified> { +) -> Result, KeyRejected> { // Try to parse as SubjectPublicKeyInfo first let mut cbs = { let mut cbs = MaybeUninit::::uninit(); @@ -476,10 +586,10 @@ fn try_parse_subject_public_key_info_bytes( Ok(LcPtr::new(unsafe { EVP_parse_public_key(&mut cbs) })?) } -fn try_parse_public_key_raw_bytes( +pub(crate) fn try_parse_public_key_raw_bytes( key_bytes: &[u8], expected_curve_nid: i32, -) -> Result, Unspecified> { +) -> Result, KeyRejected> { let ec_group = ec_group_from_nid(expected_curve_nid)?; let pub_key_point = ec_point_from_bytes(&ec_group, key_bytes)?; evp_pkey_from_public_point(&ec_group, &pub_key_point) @@ -489,20 +599,20 @@ fn try_parse_public_key_raw_bytes( pub(crate) fn evp_pkey_from_public_point( ec_group: &LcPtr, public_ec_point: &LcPtr, -) -> Result, Unspecified> { +) -> Result, KeyRejected> { let nid = unsafe { EC_GROUP_get_curve_name(*ec_group.as_const()) }; let ec_key = DetachableLcPtr::new(unsafe { EC_KEY_new() })?; if 1 != unsafe { EC_KEY_set_group(*ec_key, *ec_group.as_const()) } { - return Err(Unspecified); + return Err(KeyRejected::unspecified()); } if 1 != unsafe { EC_KEY_set_public_key(*ec_key, *public_ec_point.as_const()) } { - return Err(Unspecified); + return Err(KeyRejected::unspecified()); } let mut pkey = LcPtr::new(unsafe { EVP_PKEY_new() })?; if 1 != unsafe { EVP_PKEY_assign_EC_KEY(*pkey.as_mut(), *ec_key) } { - return Err(Unspecified); + return Err(KeyRejected::unspecified()); } ec_key.detach();