Rework KeyExchange types

This commit is contained in:
Jan Rüth 2023-11-24 12:55:57 +01:00 committed by Jan
commit dfda846989
7 changed files with 150 additions and 120 deletions

View file

@ -30,13 +30,17 @@ pub(crate) fn cvt(r: c_int) -> Result<i32, ErrorStack> {
} }
} }
#[cfg(feature = "log")]
pub(crate) fn error_stack_to_aead_error(func: &'static str, e: ErrorStack) -> aead::Error { pub(crate) fn error_stack_to_aead_error(func: &'static str, e: ErrorStack) -> aead::Error {
map_error_stack(func, e, aead::Error)
}
#[cfg(feature = "log")]
pub(crate) fn map_error_stack<T>(func: &'static str, e: ErrorStack, mapped: T) -> T {
trace!("failed {}, error: {}", func, e); trace!("failed {}, error: {}", func, e);
aead::Error mapped
} }
#[cfg(not(feature = "log"))] #[cfg(not(feature = "log"))]
pub(crate) fn error_stack_to_aead_error(_: &'static str, _: ErrorStack) -> aead::Error { pub(crate) fn map_error_stack<T>(func: &'static str, e: ErrorStack, mapped: T) -> T {
aead::Error mapped
} }

View file

@ -1,5 +1,7 @@
use rustls::crypto::{self, ActiveKeyExchange}; use rustls::crypto::{self, ActiveKeyExchange};
use crate::helper::map_error_stack;
mod dh; mod dh;
mod ex; mod ex;
@ -14,9 +16,9 @@ pub struct X25519;
impl crypto::SupportedKxGroup for X25519 { impl crypto::SupportedKxGroup for X25519 {
fn start(&self) -> Result<Box<(dyn ActiveKeyExchange + 'static)>, rustls::Error> { fn start(&self) -> Result<Box<(dyn ActiveKeyExchange + 'static)>, rustls::Error> {
Ok(Box::new( Ok(Box::new(ex::ExKeyExchange::with_x25519().map_err(|e| {
ex::ExKeyExchange::with_x25519().map_err(|_| crypto::GetRandomFailed)?, map_error_stack("X25519.start", e, crypto::GetRandomFailed)
)) })?))
} }
fn name(&self) -> rustls::NamedGroup { fn name(&self) -> rustls::NamedGroup {
@ -29,9 +31,9 @@ pub struct X448;
impl crypto::SupportedKxGroup for X448 { impl crypto::SupportedKxGroup for X448 {
fn start(&self) -> Result<Box<(dyn ActiveKeyExchange + 'static)>, rustls::Error> { fn start(&self) -> Result<Box<(dyn ActiveKeyExchange + 'static)>, rustls::Error> {
Ok(Box::new( Ok(Box::new(ex::ExKeyExchange::with_x448().map_err(|e| {
ex::ExKeyExchange::with_x448().map_err(|_| crypto::GetRandomFailed)?, map_error_stack("X448.start", e, crypto::GetRandomFailed)
)) })?))
} }
fn name(&self) -> rustls::NamedGroup { fn name(&self) -> rustls::NamedGroup {
@ -44,9 +46,9 @@ pub struct Secp256r1;
impl crypto::SupportedKxGroup for Secp256r1 { impl crypto::SupportedKxGroup for Secp256r1 {
fn start(&self) -> Result<Box<(dyn ActiveKeyExchange + 'static)>, rustls::Error> { fn start(&self) -> Result<Box<(dyn ActiveKeyExchange + 'static)>, rustls::Error> {
Ok(Box::new( Ok(Box::new(ex::ExKeyExchange::with_secp256r1().map_err(
ex::ExKeyExchange::with_secp256r1().map_err(|_| crypto::GetRandomFailed)?, |e| map_error_stack("Secp256r1.start", e, crypto::GetRandomFailed),
)) )?))
} }
fn name(&self) -> rustls::NamedGroup { fn name(&self) -> rustls::NamedGroup {
@ -59,9 +61,9 @@ pub struct Secp384r1;
impl crypto::SupportedKxGroup for Secp384r1 { impl crypto::SupportedKxGroup for Secp384r1 {
fn start(&self) -> Result<Box<(dyn ActiveKeyExchange + 'static)>, rustls::Error> { fn start(&self) -> Result<Box<(dyn ActiveKeyExchange + 'static)>, rustls::Error> {
Ok(Box::new( Ok(Box::new(ex::ExKeyExchange::with_secp384r1().map_err(
ex::ExKeyExchange::with_secp384r1().map_err(|_| crypto::GetRandomFailed)?, |e| map_error_stack("Secp384r1.start", e, crypto::GetRandomFailed),
)) )?))
} }
fn name(&self) -> rustls::NamedGroup { fn name(&self) -> rustls::NamedGroup {
@ -74,9 +76,9 @@ pub struct Secp521r1;
impl crypto::SupportedKxGroup for Secp521r1 { impl crypto::SupportedKxGroup for Secp521r1 {
fn start(&self) -> Result<Box<(dyn ActiveKeyExchange + 'static)>, rustls::Error> { fn start(&self) -> Result<Box<(dyn ActiveKeyExchange + 'static)>, rustls::Error> {
Ok(Box::new( Ok(Box::new(ex::ExKeyExchange::with_secp521r1().map_err(
ex::ExKeyExchange::with_secp521r1().map_err(|_| crypto::GetRandomFailed)?, |e| map_error_stack("Secp521r1.start", e, crypto::GetRandomFailed),
)) )?))
} }
fn name(&self) -> rustls::NamedGroup { fn name(&self) -> rustls::NamedGroup {
@ -89,28 +91,12 @@ pub struct FfDHe2048;
impl crypto::SupportedKxGroup for FfDHe2048 { impl crypto::SupportedKxGroup for FfDHe2048 {
fn start(&self) -> Result<Box<(dyn ActiveKeyExchange + 'static)>, rustls::Error> { fn start(&self) -> Result<Box<(dyn ActiveKeyExchange + 'static)>, rustls::Error> {
Ok(Box::new( Ok(Box::new(dh::DhKeyExchange::generate_ffdhe_2048().map_err(
dh::BoringDhKey::generate_ffdhe_2048().map_err(|_| crypto::GetRandomFailed)?, |e| map_error_stack("FfDHe2048.start", e, crypto::GetRandomFailed),
)) )?))
} }
fn name(&self) -> rustls::NamedGroup { fn name(&self) -> rustls::NamedGroup {
rustls::NamedGroup::FFDHE2048 rustls::NamedGroup::FFDHE2048
} }
} }
#[cfg(test)]
mod tests {
use rustls::crypto::ActiveKeyExchange;
#[test]
fn test_derive_dh() {
let alice = super::dh::BoringDhKey::generate_ffdhe_2048().unwrap();
let bob = super::dh::BoringDhKey::generate_ffdhe_2048().unwrap();
let shared_secret1 = alice.diffie_hellman(&bob.pub_key()).unwrap();
let shared_secret2 = bob.diffie_hellman(&alice.pub_key()).unwrap();
assert_eq!(shared_secret1, shared_secret2)
}
}

View file

@ -2,17 +2,18 @@ use boring::{dh::Dh, error::ErrorStack, pkey::Private};
use foreign_types::ForeignType; use foreign_types::ForeignType;
use rustls::crypto; use rustls::crypto;
use crate::helper::{cvt, cvt_p}; use crate::helper::{cvt, cvt_p, map_error_stack};
use super::DhKeyType; use super::DhKeyType;
pub struct BoringDhKey { pub struct DhKeyExchange {
dh: Dh<Private>, dh: Dh<Private>,
pub_bytes: Vec<u8>, pub_bytes: Vec<u8>,
key_type: DhKeyType, key_type: DhKeyType,
} }
impl BoringDhKey { impl DhKeyExchange {
// Generate a new KeyExchange with a random FFDHE_2048 private key
pub fn generate_ffdhe_2048() -> Result<Self, ErrorStack> { pub fn generate_ffdhe_2048() -> Result<Self, ErrorStack> {
let mut me = Self { let mut me = Self {
dh: unsafe { Dh::from_ptr(cvt_p(boring_sys::DH_get_rfc7919_2048())?) }, dh: unsafe { Dh::from_ptr(cvt_p(boring_sys::DH_get_rfc7919_2048())?) },
@ -46,7 +47,8 @@ impl BoringDhKey {
Ok(me) Ok(me)
} }
pub fn diffie_hellman(&self, raw_public_key: &[u8]) -> Result<Vec<u8>, ErrorStack> { /// Generate a shared secret with the other's raw public key
fn diffie_hellman(&self, raw_public_key: &[u8]) -> Result<Vec<u8>, ErrorStack> {
let peer = boring::bn::BigNum::from_slice(raw_public_key).unwrap(); let peer = boring::bn::BigNum::from_slice(raw_public_key).unwrap();
let secret_len = unsafe { cvt(boring_sys::DH_size(self.dh.as_ptr()))? } as usize; let secret_len = unsafe { cvt(boring_sys::DH_size(self.dh.as_ptr()))? } as usize;
let mut secret = vec![0u8; secret_len]; let mut secret = vec![0u8; secret_len];
@ -60,14 +62,9 @@ impl BoringDhKey {
secret.truncate(secret_len); secret.truncate(secret_len);
Ok(secret) Ok(secret)
} }
#[allow(unused)]
fn pub_key(&self) -> &[u8] {
self.pub_bytes.as_ref()
}
} }
impl crypto::ActiveKeyExchange for BoringDhKey { impl crypto::ActiveKeyExchange for DhKeyExchange {
fn complete( fn complete(
self: Box<Self>, self: Box<Self>,
peer_pub_key: &[u8], peer_pub_key: &[u8],
@ -80,7 +77,13 @@ impl crypto::ActiveKeyExchange for BoringDhKey {
Ok(crypto::SharedSecret::from( Ok(crypto::SharedSecret::from(
self.diffie_hellman(peer_pub_key) self.diffie_hellman(peer_pub_key)
.map_err(|x| rustls::Error::General(x.to_string()))? .map_err(|e| {
map_error_stack(
"dh.diffie_hellman",
e,
rustls::PeerMisbehaved::InvalidKeyShare,
)
})?
.as_ref(), .as_ref(),
)) ))
} }
@ -96,3 +99,20 @@ impl crypto::ActiveKeyExchange for BoringDhKey {
} }
} }
} }
#[cfg(test)]
mod tests {
use crate::kx::dh::DhKeyExchange;
use rustls::crypto::ActiveKeyExchange;
#[test]
fn test_derive_dh() {
let alice = DhKeyExchange::generate_ffdhe_2048().unwrap();
let bob = DhKeyExchange::generate_ffdhe_2048().unwrap();
let shared_secret1 = alice.diffie_hellman(&bob.pub_key()).unwrap();
let shared_secret2 = bob.diffie_hellman(&alice.pub_key()).unwrap();
assert_eq!(shared_secret1, shared_secret2)
}
}

View file

@ -14,7 +14,7 @@ use foreign_types::ForeignType;
use rustls::crypto; use rustls::crypto;
use spki::der::Decode; use spki::der::Decode;
use crate::helper::{cvt, cvt_p}; use crate::helper::{cvt, cvt_p, map_error_stack};
use super::DhKeyType; use super::DhKeyType;
@ -25,26 +25,39 @@ pub struct ExKeyExchange {
} }
impl ExKeyExchange { impl ExKeyExchange {
/// Creates a new KeyExchange using a random
/// private key for the X25519 Edwards curve
pub fn with_x25519() -> Result<Self, ErrorStack> { pub fn with_x25519() -> Result<Self, ErrorStack> {
Self::ed_from_curve(Nid::from_raw(boring_sys::NID_X25519)) Self::ed_from_curve(Nid::from_raw(boring_sys::NID_X25519))
} }
/// Creates a new KeyExchange using a random
/// private key for the X448 Edwards curve
pub fn with_x448() -> Result<Self, ErrorStack> { pub fn with_x448() -> Result<Self, ErrorStack> {
Self::ed_from_curve(Nid::from_raw(boring_sys::NID_X448)) Self::ed_from_curve(Nid::from_raw(boring_sys::NID_X448))
} }
/// Creates a new KeyExchange using a random
/// private key for sepc256r1 curve
/// Also known as X9_62_PRIME256V1
pub fn with_secp256r1() -> Result<Self, ErrorStack> { pub fn with_secp256r1() -> Result<Self, ErrorStack> {
Self::ec_from_curve(Nid::X9_62_PRIME256V1) Self::ec_from_curve(Nid::X9_62_PRIME256V1)
} }
/// Creates a new KeyExchange using a random
/// private key for sepc384r1 curve
pub fn with_secp384r1() -> Result<Self, ErrorStack> { pub fn with_secp384r1() -> Result<Self, ErrorStack> {
Self::ec_from_curve(Nid::SECP384R1) Self::ec_from_curve(Nid::SECP384R1)
} }
/// Creates a new KeyExchange using a random
/// private key for sep521r1 curve
pub fn with_secp521r1() -> Result<Self, ErrorStack> { pub fn with_secp521r1() -> Result<Self, ErrorStack> {
Self::ec_from_curve(Nid::SECP521R1) Self::ec_from_curve(Nid::SECP521R1)
} }
/// Allows getting a new KeyExchange using Eliptic Curves
/// on the specified curve
fn ec_from_curve(nid: Nid) -> Result<Self, ErrorStack> { fn ec_from_curve(nid: Nid) -> Result<Self, ErrorStack> {
let ec_group = EcGroup::from_curve_name(nid)?; let ec_group = EcGroup::from_curve_name(nid)?;
let ec_key = EcKey::generate(&ec_group)?; let ec_key = EcKey::generate(&ec_group)?;
@ -58,6 +71,8 @@ impl ExKeyExchange {
}) })
} }
/// Allows getting a new KeyExchange using Edwards Curves
/// on the specified curve
fn ed_from_curve(nid: Nid) -> Result<Self, ErrorStack> { fn ed_from_curve(nid: Nid) -> Result<Self, ErrorStack> {
let pkey_ctx = unsafe { let pkey_ctx = unsafe {
EvpPkeyCtx::from_ptr(cvt_p(boring_sys::EVP_PKEY_CTX_new_id( EvpPkeyCtx::from_ptr(cvt_p(boring_sys::EVP_PKEY_CTX_new_id(
@ -85,6 +100,7 @@ impl ExKeyExchange {
}) })
} }
/// Decodes a SPKI public key to it's raw public key component
fn raw_public_key(pkey: &PKeyRef<Private>) -> Vec<u8> { fn raw_public_key(pkey: &PKeyRef<Private>) -> Vec<u8> {
let spki = pkey.public_key_to_der().unwrap(); let spki = pkey.public_key_to_der().unwrap();
@ -94,6 +110,29 @@ impl ExKeyExchange {
// return the raw public key as a new vec // return the raw public key as a new vec
Vec::from(key.subject_public_key.as_bytes().unwrap()) Vec::from(key.subject_public_key.as_bytes().unwrap())
} }
/// Derives a shared secret using the peer's raw public key
fn diffie_hellman(&self, peer_pub_key: &[u8]) -> Result<Vec<u8>, ErrorStack> {
let peerkey = match &self.key_type {
DhKeyType::EC((group, _)) => {
let mut bn_ctx = boring::bn::BigNumContext::new()?;
let point = crate::verify::ec::ec_point(group, &mut bn_ctx, peer_pub_key)?;
crate::verify::ec::ec_public_key(group, point.as_ref())?
}
DhKeyType::ED(nid) => {
crate::verify::ed::ed_public_key(peer_pub_key, Nid::from_raw(*nid))?
}
_ => unimplemented!(),
};
let mut deriver = boring::derive::Deriver::new(&self.own_key)?;
deriver.set_peer(&peerkey)?;
deriver.derive_to_vec()
}
} }
impl crypto::ActiveKeyExchange for ExKeyExchange { impl crypto::ActiveKeyExchange for ExKeyExchange {
@ -101,33 +140,15 @@ impl crypto::ActiveKeyExchange for ExKeyExchange {
self: Box<Self>, self: Box<Self>,
peer_pub_key: &[u8], peer_pub_key: &[u8],
) -> Result<crypto::SharedSecret, rustls::Error> { ) -> Result<crypto::SharedSecret, rustls::Error> {
let peerkey = match &self.key_type { self.diffie_hellman(peer_pub_key)
DhKeyType::EC((group, _)) => { .map(|x| crypto::SharedSecret::from(x.as_slice()))
let mut bn_ctx = boring::bn::BigNumContext::new() .map_err(|e| {
.map_err(|x| rustls::Error::General(x.to_string()))?; map_error_stack(
"ex.diffie_hellman",
let point = crate::verify::ec::ec_point(group, &mut bn_ctx, peer_pub_key) e,
.map_err(|_| rustls::Error::from(rustls::PeerMisbehaved::InvalidKeyShare))?; rustls::Error::PeerMisbehaved(rustls::PeerMisbehaved::InvalidKeyShare),
)
crate::verify::ec::ec_public_key(group, point.as_ref()) })
.map_err(|_| rustls::Error::from(rustls::PeerMisbehaved::InvalidKeyShare))?
}
DhKeyType::ED(nid) => {
crate::verify::ed::ed_public_key(peer_pub_key, Nid::from_raw(*nid))
.map_err(|_| rustls::Error::from(rustls::PeerMisbehaved::InvalidKeyShare))?
}
_ => unimplemented!(),
};
let mut deriver = boring::derive::Deriver::new(&self.own_key).unwrap();
deriver
.set_peer(&peerkey)
.map_err(|_| rustls::Error::from(rustls::PeerMisbehaved::InvalidKeyShare))?;
Ok(crypto::SharedSecret::from(
deriver.derive_to_vec().unwrap().as_slice(),
))
} }
fn pub_key(&self) -> &[u8] { fn pub_key(&self) -> &[u8] {
@ -153,19 +174,23 @@ mod tests {
#[test] #[test]
fn test_derive_ec() { fn test_derive_ec() {
let kx = Box::new(ExKeyExchange::with_secp256r1().unwrap()); let alice = Box::new(ExKeyExchange::with_secp256r1().unwrap());
let kx1 = ExKeyExchange::with_secp256r1().unwrap(); let bob = ExKeyExchange::with_secp256r1().unwrap();
kx.group(); assert_eq!(
kx.complete(kx1.pub_key()).unwrap(); alice.diffie_hellman(bob.pub_key()).unwrap(),
bob.diffie_hellman(alice.pub_key()).unwrap()
);
} }
#[test] #[test]
fn test_derive_ed() { fn test_derive_ed() {
let kx = Box::new(ExKeyExchange::with_x25519().unwrap()); let alice = Box::new(ExKeyExchange::with_x25519().unwrap());
let kx1 = ExKeyExchange::with_x25519().unwrap(); let bob = ExKeyExchange::with_x25519().unwrap();
kx.group(); assert_eq!(
kx.complete(kx1.pub_key()).unwrap(); alice.diffie_hellman(bob.pub_key()).unwrap(),
bob.diffie_hellman(alice.pub_key()).unwrap()
);
} }
} }

View file

@ -1,10 +1,12 @@
use std::sync::Arc; use std::sync::Arc;
use boring::{hash::MessageDigest, pkey::Id, rsa::Padding, sign::RsaPssSaltlen}; use boring::{
use rustls::{ hash::MessageDigest,
sign::{Signer, SigningKey}, pkey::{Id, PKeyRef, Private},
SignatureScheme, rsa::Padding,
sign::{RsaPssSaltlen, Signer},
}; };
use rustls::{sign::SigningKey, SignatureScheme};
use rustls_pki_types::PrivateKeyDer; use rustls_pki_types::PrivateKeyDer;
const ALL_RSA_SCHEMES: &[SignatureScheme] = &[ const ALL_RSA_SCHEMES: &[SignatureScheme] = &[
@ -23,10 +25,7 @@ const ALL_EC_SCHEMES: &[SignatureScheme] = &[
]; ];
#[derive(Debug)] #[derive(Debug)]
pub struct BoringPrivateKey( pub struct BoringPrivateKey(Arc<boring::pkey::PKey<Private>>, rustls::SignatureAlgorithm);
Arc<boring::pkey::PKey<boring::pkey::Private>>,
rustls::SignatureAlgorithm,
);
impl TryFrom<PrivateKeyDer<'static>> for BoringPrivateKey { impl TryFrom<PrivateKeyDer<'static>> for BoringPrivateKey {
type Error = rustls::Error; type Error = rustls::Error;
@ -55,11 +54,11 @@ impl TryFrom<PrivateKeyDer<'static>> for BoringPrivateKey {
} }
fn rsa_signer_from_params( fn rsa_signer_from_params(
key: &boring::pkey::PKeyRef<boring::pkey::Private>, key: &PKeyRef<Private>,
digest: MessageDigest, digest: MessageDigest,
padding: Padding, padding: Padding,
) -> boring::sign::Signer { ) -> Signer {
let mut signer = boring::sign::Signer::new(digest.clone(), key).expect("failed getting signer"); let mut signer = Signer::new(digest.clone(), key).expect("failed getting signer");
signer signer
.set_rsa_padding(padding) .set_rsa_padding(padding)
.expect("failed setting padding"); .expect("failed setting padding");
@ -75,11 +74,8 @@ fn rsa_signer_from_params(
signer signer
} }
fn ec_signer_from_params( fn ec_signer_from_params(key: &PKeyRef<Private>, digest: MessageDigest) -> Signer {
key: &boring::pkey::PKeyRef<boring::pkey::Private>, let signer = Signer::new(digest, key).expect("failed getting signer");
digest: MessageDigest,
) -> boring::sign::Signer {
let signer = boring::sign::Signer::new(digest, key).expect("failed getting signer");
signer signer
} }
@ -125,13 +121,10 @@ impl SigningKey for BoringPrivateKey {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct BoringSigner( pub struct BoringSigner(Arc<boring::pkey::PKey<Private>>, rustls::SignatureScheme);
Arc<boring::pkey::PKey<boring::pkey::Private>>,
rustls::SignatureScheme,
);
impl BoringSigner { impl BoringSigner {
fn get_signer(&self) -> boring::sign::Signer { fn get_signer(&self) -> Signer {
match self.1 { match self.1 {
SignatureScheme::RSA_PKCS1_SHA256 => { SignatureScheme::RSA_PKCS1_SHA256 => {
rsa_signer_from_params(self.0.as_ref(), MessageDigest::sha256(), Padding::PKCS1) rsa_signer_from_params(self.0.as_ref(), MessageDigest::sha256(), Padding::PKCS1)
@ -163,17 +156,19 @@ impl BoringSigner {
ec_signer_from_params(self.0.as_ref(), MessageDigest::sha512()) ec_signer_from_params(self.0.as_ref(), MessageDigest::sha512())
} }
SignatureScheme::ED25519 => boring::sign::Signer::new_without_digest(self.0.as_ref()) SignatureScheme::ED25519 => {
.expect("failed getting signer"), Signer::new_without_digest(self.0.as_ref()).expect("failed getting signer")
SignatureScheme::ED448 => boring::sign::Signer::new_without_digest(self.0.as_ref()) }
.expect("failed getting signer"), SignatureScheme::ED448 => {
Signer::new_without_digest(self.0.as_ref()).expect("failed getting signer")
}
_ => unimplemented!(), _ => unimplemented!(),
} }
} }
} }
impl Signer for BoringSigner { impl rustls::sign::Signer for BoringSigner {
fn sign(&self, message: &[u8]) -> Result<Vec<u8>, rustls::Error> { fn sign(&self, message: &[u8]) -> Result<Vec<u8>, rustls::Error> {
let signer = self.get_signer(); let signer = self.get_signer();
let mut msg_with_sig = let mut msg_with_sig =

View file

@ -1,4 +1,4 @@
use boring::hash::MessageDigest; use boring::{error::ErrorStack, hash::MessageDigest};
use rustls::SignatureScheme; use rustls::SignatureScheme;
use rustls_pki_types::{InvalidSignature, SignatureVerificationAlgorithm}; use rustls_pki_types::{InvalidSignature, SignatureVerificationAlgorithm};
@ -18,8 +18,10 @@ impl SignatureVerificationAlgorithm for BoringEcVerifier {
signature: &[u8], signature: &[u8],
) -> Result<(), rustls_pki_types::InvalidSignature> { ) -> Result<(), rustls_pki_types::InvalidSignature> {
let (group, mut bn_ctx) = setup_ec_key(self.0); let (group, mut bn_ctx) = setup_ec_key(self.0);
let ec_point = ec_point(group.as_ref(), bn_ctx.as_mut(), public_key)?; let ec_point =
let public_key = ec_public_key(group.as_ref(), ec_point.as_ref())?; ec_point(group.as_ref(), bn_ctx.as_mut(), public_key).map_err(|_| InvalidSignature)?;
let public_key =
ec_public_key(group.as_ref(), ec_point.as_ref()).map_err(|_| InvalidSignature)?;
let mut verifier = match self.0 { let mut verifier = match self.0 {
SignatureScheme::ECDSA_NISTP256_SHA256 => { SignatureScheme::ECDSA_NISTP256_SHA256 => {
ec_verifier_from_params(public_key.as_ref(), MessageDigest::sha256()) ec_verifier_from_params(public_key.as_ref(), MessageDigest::sha256())
@ -100,16 +102,13 @@ pub(crate) fn ec_point(
group: &boring::ec::EcGroupRef, group: &boring::ec::EcGroupRef,
bignum_ctx: &mut boring::bn::BigNumContextRef, bignum_ctx: &mut boring::bn::BigNumContextRef,
spki_spk: &[u8], spki_spk: &[u8],
) -> Result<boring::ec::EcPoint, InvalidSignature> { ) -> Result<boring::ec::EcPoint, ErrorStack> {
boring::ec::EcPoint::from_bytes(group, spki_spk, bignum_ctx).map_err(|_| InvalidSignature) boring::ec::EcPoint::from_bytes(group, spki_spk, bignum_ctx)
} }
pub(crate) fn ec_public_key( pub(crate) fn ec_public_key(
group: &boring::ec::EcGroupRef, group: &boring::ec::EcGroupRef,
ec_point: &boring::ec::EcPointRef, ec_point: &boring::ec::EcPointRef,
) -> Result<boring::pkey::PKey<boring::pkey::Public>, InvalidSignature> { ) -> Result<boring::pkey::PKey<boring::pkey::Public>, ErrorStack> {
boring::pkey::PKey::from_ec_key( boring::pkey::PKey::from_ec_key(boring::ec::EcKey::from_public_key(group, ec_point)?)
boring::ec::EcKey::from_public_key(group, ec_point).map_err(|_| InvalidSignature)?,
)
.map_err(|_| InvalidSignature)
} }

View file

@ -1,5 +1,6 @@
use std::ptr; use std::ptr;
use boring::error::ErrorStack;
use foreign_types::ForeignType; use foreign_types::ForeignType;
use rustls::SignatureScheme; use rustls::SignatureScheme;
use rustls_pki_types::{InvalidSignature, SignatureVerificationAlgorithm}; use rustls_pki_types::{InvalidSignature, SignatureVerificationAlgorithm};
@ -20,7 +21,8 @@ impl SignatureVerificationAlgorithm for BoringEdVerifier {
message: &[u8], message: &[u8],
signature: &[u8], signature: &[u8],
) -> Result<(), rustls_pki_types::InvalidSignature> { ) -> Result<(), rustls_pki_types::InvalidSignature> {
let public_key = ed_public_key_for_scheme(public_key, self.0)?; let public_key =
ed_public_key_for_scheme(public_key, self.0).map_err(|_| InvalidSignature)?;
let mut verifier = ed_verifier_from_params(public_key.as_ref()); let mut verifier = ed_verifier_from_params(public_key.as_ref());
verifier.verify_oneshot(signature, message).map_or_else( verifier.verify_oneshot(signature, message).map_or_else(
@ -58,7 +60,7 @@ fn ed_verifier_from_params(
fn ed_public_key_for_scheme( fn ed_public_key_for_scheme(
spki_spk: &[u8], spki_spk: &[u8],
scheme: SignatureScheme, scheme: SignatureScheme,
) -> Result<boring::pkey::PKey<boring::pkey::Public>, InvalidSignature> { ) -> Result<boring::pkey::PKey<boring::pkey::Public>, ErrorStack> {
let nid = boring::nid::Nid::from_raw(match scheme { let nid = boring::nid::Nid::from_raw(match scheme {
SignatureScheme::ED25519 => boring_sys::EVP_PKEY_ED25519, SignatureScheme::ED25519 => boring_sys::EVP_PKEY_ED25519,
SignatureScheme::ED448 => boring_sys::EVP_PKEY_ED448, SignatureScheme::ED448 => boring_sys::EVP_PKEY_ED448,
@ -70,15 +72,14 @@ fn ed_public_key_for_scheme(
pub fn ed_public_key( pub fn ed_public_key(
spki_spk: &[u8], spki_spk: &[u8],
nid: boring::nid::Nid, nid: boring::nid::Nid,
) -> Result<boring::pkey::PKey<boring::pkey::Public>, InvalidSignature> { ) -> Result<boring::pkey::PKey<boring::pkey::Public>, ErrorStack> {
Ok(unsafe { Ok(unsafe {
let pkey = cvt_p(boring_sys::EVP_PKEY_new_raw_public_key( let pkey = cvt_p(boring_sys::EVP_PKEY_new_raw_public_key(
nid.as_raw(), nid.as_raw(),
ptr::null_mut(), ptr::null_mut(),
spki_spk.as_ptr(), spki_spk.as_ptr(),
spki_spk.len(), spki_spk.len(),
)) ))?;
.map_err(|_| InvalidSignature)?;
boring::pkey::PKey::from_ptr(pkey) boring::pkey::PKey::from_ptr(pkey)
}) })