* Move ffi type container to boring-additions
* Use boring::derive for EC and ED instead of own implementation
This commit is contained in:
parent
319029f2d4
commit
aa74b45a0f
15 changed files with 417 additions and 410 deletions
|
|
@ -1,9 +1,14 @@
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
use boring::error::ErrorStack;
|
use boring::error::ErrorStack;
|
||||||
|
use foreign_types::ForeignType;
|
||||||
|
|
||||||
|
mod types;
|
||||||
|
|
||||||
use crate::helper::{cvt, cvt_p};
|
use crate::helper::{cvt, cvt_p};
|
||||||
|
|
||||||
|
pub use self::types::*;
|
||||||
|
|
||||||
pub struct Algorithm(*const boring_sys::EVP_AEAD);
|
pub struct Algorithm(*const boring_sys::EVP_AEAD);
|
||||||
|
|
||||||
impl Algorithm {
|
impl Algorithm {
|
||||||
|
|
@ -55,14 +60,11 @@ impl Algorithm {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Crypter {
|
pub struct Crypter {
|
||||||
ctx: *mut boring_sys::EVP_AEAD_CTX,
|
ctx: EvpAeadCtx,
|
||||||
max_overhead: usize,
|
max_overhead: usize,
|
||||||
nonce_len: usize,
|
nonce_len: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for Crypter {}
|
|
||||||
unsafe impl Sync for Crypter {}
|
|
||||||
|
|
||||||
impl Crypter {
|
impl Crypter {
|
||||||
pub fn new(aead_alg: Algorithm, key: &[u8]) -> Result<Self, ErrorStack> {
|
pub fn new(aead_alg: Algorithm, key: &[u8]) -> Result<Self, ErrorStack> {
|
||||||
assert_eq!(aead_alg.key_length(), key.len());
|
assert_eq!(aead_alg.key_length(), key.len());
|
||||||
|
|
@ -70,12 +72,12 @@ impl Crypter {
|
||||||
|
|
||||||
let this = unsafe {
|
let this = unsafe {
|
||||||
Self {
|
Self {
|
||||||
ctx: cvt_p(boring_sys::EVP_AEAD_CTX_new(
|
ctx: EvpAeadCtx::from_ptr(cvt_p(boring_sys::EVP_AEAD_CTX_new(
|
||||||
aead_alg.0,
|
aead_alg.0,
|
||||||
key.as_ptr(),
|
key.as_ptr(),
|
||||||
key.len(),
|
key.len(),
|
||||||
boring_sys::EVP_AEAD_DEFAULT_TAG_LENGTH as usize,
|
boring_sys::EVP_AEAD_DEFAULT_TAG_LENGTH as usize,
|
||||||
))?,
|
))?),
|
||||||
max_overhead: aead_alg.max_overhead(),
|
max_overhead: aead_alg.max_overhead(),
|
||||||
nonce_len: aead_alg.nonce_len(),
|
nonce_len: aead_alg.nonce_len(),
|
||||||
}
|
}
|
||||||
|
|
@ -104,7 +106,7 @@ impl Crypter {
|
||||||
let mut tag_len = tag.len();
|
let mut tag_len = tag.len();
|
||||||
unsafe {
|
unsafe {
|
||||||
cvt(boring_sys::EVP_AEAD_CTX_seal_scatter(
|
cvt(boring_sys::EVP_AEAD_CTX_seal_scatter(
|
||||||
self.ctx,
|
self.ctx.as_ptr(),
|
||||||
buffer.as_mut_ptr(),
|
buffer.as_mut_ptr(),
|
||||||
tag.as_mut_ptr(),
|
tag.as_mut_ptr(),
|
||||||
&mut tag_len,
|
&mut tag_len,
|
||||||
|
|
@ -133,7 +135,7 @@ impl Crypter {
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
cvt(boring_sys::EVP_AEAD_CTX_open_gather(
|
cvt(boring_sys::EVP_AEAD_CTX_open_gather(
|
||||||
self.ctx,
|
self.ctx.as_ptr(),
|
||||||
buffer.as_mut_ptr(),
|
buffer.as_mut_ptr(),
|
||||||
nonce.as_ptr(),
|
nonce.as_ptr(),
|
||||||
nonce.len(),
|
nonce.len(),
|
||||||
|
|
@ -149,14 +151,6 @@ impl Crypter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Crypter {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
unsafe {
|
|
||||||
boring_sys::EVP_AEAD_CTX_free(self.ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::Crypter;
|
use super::Crypter;
|
||||||
|
|
|
||||||
56
boring-additions/src/aead/types.rs
Normal file
56
boring-additions/src/aead/types.rs
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
use std::{
|
||||||
|
ops::{Deref, DerefMut},
|
||||||
|
ptr::NonNull,
|
||||||
|
};
|
||||||
|
|
||||||
|
use foreign_types::{ForeignType, ForeignTypeRef, Opaque};
|
||||||
|
|
||||||
|
pub struct EvpAeadCtxRef(Opaque);
|
||||||
|
|
||||||
|
unsafe impl ForeignTypeRef for EvpAeadCtxRef {
|
||||||
|
type CType = boring_sys::EVP_AEAD_CTX;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Sync for EvpAeadCtxRef {}
|
||||||
|
unsafe impl Send for EvpAeadCtxRef {}
|
||||||
|
|
||||||
|
pub struct EvpAeadCtx(NonNull<boring_sys::EVP_AEAD_CTX>);
|
||||||
|
|
||||||
|
unsafe impl Sync for EvpAeadCtx {}
|
||||||
|
unsafe impl Send for EvpAeadCtx {}
|
||||||
|
|
||||||
|
unsafe impl ForeignType for EvpAeadCtx {
|
||||||
|
type CType = boring_sys::EVP_AEAD_CTX;
|
||||||
|
|
||||||
|
type Ref = EvpAeadCtxRef;
|
||||||
|
|
||||||
|
unsafe fn from_ptr(ptr: *mut Self::CType) -> Self {
|
||||||
|
Self(NonNull::new_unchecked(ptr))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_ptr(&self) -> *mut Self::CType {
|
||||||
|
self.0.as_ptr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for EvpAeadCtx {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
boring_sys::EVP_AEAD_CTX_free(self.0.as_ptr());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for EvpAeadCtx {
|
||||||
|
type Target = EvpAeadCtxRef;
|
||||||
|
|
||||||
|
fn deref(&self) -> &EvpAeadCtxRef {
|
||||||
|
unsafe { EvpAeadCtxRef::from_ptr(self.as_ptr()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DerefMut for EvpAeadCtx {
|
||||||
|
fn deref_mut(&mut self) -> &mut EvpAeadCtxRef {
|
||||||
|
unsafe { EvpAeadCtxRef::from_ptr_mut(self.as_ptr()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
3
boring-additions/src/evp/mod.rs
Normal file
3
boring-additions/src/evp/mod.rs
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
mod types;
|
||||||
|
|
||||||
|
pub use types::*;
|
||||||
60
boring-additions/src/evp/types.rs
Normal file
60
boring-additions/src/evp/types.rs
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
use std::{
|
||||||
|
ops::{Deref, DerefMut},
|
||||||
|
ptr::NonNull,
|
||||||
|
};
|
||||||
|
|
||||||
|
use foreign_types::{ForeignType, ForeignTypeRef, Opaque};
|
||||||
|
|
||||||
|
pub struct EvpPkeyCtxRef(Opaque);
|
||||||
|
|
||||||
|
unsafe impl ForeignTypeRef for EvpPkeyCtxRef {
|
||||||
|
type CType = boring_sys::EVP_PKEY_CTX;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Sync for EvpPkeyCtxRef {}
|
||||||
|
unsafe impl Send for EvpPkeyCtxRef {}
|
||||||
|
|
||||||
|
unsafe impl Sync for EvpPkeyCtx {}
|
||||||
|
unsafe impl Send for EvpPkeyCtx {}
|
||||||
|
|
||||||
|
pub struct EvpPkeyCtx(NonNull<boring_sys::EVP_PKEY_CTX>);
|
||||||
|
unsafe impl ForeignType for EvpPkeyCtx {
|
||||||
|
type CType = boring_sys::EVP_PKEY_CTX;
|
||||||
|
|
||||||
|
type Ref = EvpPkeyCtxRef;
|
||||||
|
|
||||||
|
unsafe fn from_ptr(ptr: *mut Self::CType) -> Self {
|
||||||
|
Self(NonNull::new_unchecked(ptr))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_ptr(&self) -> *mut Self::CType {
|
||||||
|
self.0.as_ptr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Drop for EvpPkeyCtx {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
boring_sys::EVP_PKEY_CTX_free(self.0.as_ptr());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl core::fmt::Debug for EvpPkeyCtx {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.debug_tuple("EvpPkeyCtx").field(&self.0).finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for EvpPkeyCtx {
|
||||||
|
type Target = EvpPkeyCtxRef;
|
||||||
|
|
||||||
|
fn deref(&self) -> &EvpPkeyCtxRef {
|
||||||
|
unsafe { EvpPkeyCtxRef::from_ptr(self.as_ptr()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DerefMut for EvpPkeyCtx {
|
||||||
|
fn deref_mut(&mut self) -> &mut EvpPkeyCtxRef {
|
||||||
|
unsafe { EvpPkeyCtxRef::from_ptr_mut(self.as_ptr()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
3
boring-additions/src/hmac/mod.rs
Normal file
3
boring-additions/src/hmac/mod.rs
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
mod types;
|
||||||
|
|
||||||
|
pub use types::*;
|
||||||
69
boring-additions/src/hmac/types.rs
Normal file
69
boring-additions/src/hmac/types.rs
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
use std::{
|
||||||
|
ops::{Deref, DerefMut},
|
||||||
|
ptr::NonNull,
|
||||||
|
};
|
||||||
|
|
||||||
|
use foreign_types::{ForeignType, ForeignTypeRef, Opaque};
|
||||||
|
|
||||||
|
use crate::helper::{cvt, cvt_p};
|
||||||
|
|
||||||
|
pub struct HmacCtxRef(Opaque);
|
||||||
|
|
||||||
|
unsafe impl ForeignTypeRef for HmacCtxRef {
|
||||||
|
type CType = boring_sys::HMAC_CTX;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Sync for HmacCtxRef {}
|
||||||
|
unsafe impl Send for HmacCtxRef {}
|
||||||
|
|
||||||
|
pub struct HmacCtx(NonNull<boring_sys::HMAC_CTX>);
|
||||||
|
|
||||||
|
unsafe impl Sync for HmacCtx {}
|
||||||
|
unsafe impl Send for HmacCtx {}
|
||||||
|
|
||||||
|
unsafe impl ForeignType for HmacCtx {
|
||||||
|
type CType = boring_sys::HMAC_CTX;
|
||||||
|
|
||||||
|
type Ref = HmacCtxRef;
|
||||||
|
|
||||||
|
unsafe fn from_ptr(ptr: *mut Self::CType) -> Self {
|
||||||
|
Self(NonNull::new_unchecked(ptr))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_ptr(&self) -> *mut Self::CType {
|
||||||
|
self.0.as_ptr()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for HmacCtx {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
unsafe {
|
||||||
|
let ctx = HmacCtx::from_ptr(cvt_p(boring_sys::HMAC_CTX_new()).unwrap());
|
||||||
|
|
||||||
|
cvt(boring_sys::HMAC_CTX_copy(ctx.as_ptr(), self.0.as_ptr())).unwrap();
|
||||||
|
ctx
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for HmacCtx {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
boring_sys::HMAC_CTX_free(self.0.as_ptr());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Deref for HmacCtx {
|
||||||
|
type Target = HmacCtxRef;
|
||||||
|
|
||||||
|
fn deref(&self) -> &HmacCtxRef {
|
||||||
|
unsafe { Self::Target::from_ptr(self.as_ptr()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DerefMut for HmacCtx {
|
||||||
|
fn deref_mut(&mut self) -> &mut HmacCtxRef {
|
||||||
|
unsafe { HmacCtxRef::from_ptr_mut(self.as_ptr()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,2 +1,4 @@
|
||||||
pub mod aead;
|
pub mod aead;
|
||||||
|
pub mod evp;
|
||||||
pub(crate) mod helper;
|
pub(crate) mod helper;
|
||||||
|
pub mod hmac;
|
||||||
|
|
|
||||||
|
|
@ -36,9 +36,6 @@ pub(crate) struct BoringAeadCrypter<T: BoringAead> {
|
||||||
phantom: PhantomData<T>,
|
phantom: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<T: BoringAead> Sync for BoringAeadCrypter<T> {}
|
|
||||||
unsafe impl<T: BoringAead> Send for BoringAeadCrypter<T> {}
|
|
||||||
|
|
||||||
impl<T: BoringAead> AeadCore for BoringAeadCrypter<T> {
|
impl<T: BoringAead> AeadCore for BoringAeadCrypter<T> {
|
||||||
// inherit all properties from the Algorithm
|
// inherit all properties from the Algorithm
|
||||||
|
|
||||||
|
|
@ -185,9 +182,6 @@ where
|
||||||
|
|
||||||
pub(crate) struct Aead<T: BoringCipher>(PhantomData<T>);
|
pub(crate) struct Aead<T: BoringCipher>(PhantomData<T>);
|
||||||
|
|
||||||
unsafe impl<T: BoringCipher> Sync for Aead<T> {}
|
|
||||||
unsafe impl<T: BoringCipher> Send for Aead<T> {}
|
|
||||||
|
|
||||||
impl<T: BoringCipher> Aead<T> {
|
impl<T: BoringCipher> Aead<T> {
|
||||||
pub const DEFAULT: Self = Self(PhantomData);
|
pub const DEFAULT: Self = Self(PhantomData);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
use std::{os::raw::c_void, ptr};
|
use std::{os::raw::c_void, ptr};
|
||||||
|
|
||||||
use boring::hash::MessageDigest;
|
use boring::hash::MessageDigest;
|
||||||
|
use boring_additions::hmac::HmacCtx;
|
||||||
|
use foreign_types::ForeignType;
|
||||||
use rustls::crypto;
|
use rustls::crypto;
|
||||||
|
|
||||||
use crate::helper::{cvt, cvt_p};
|
use crate::helper::{cvt, cvt_p};
|
||||||
|
|
@ -14,7 +16,7 @@ pub struct BoringHmac(pub boring::nid::Nid);
|
||||||
impl crypto::hmac::Hmac for BoringHmac {
|
impl crypto::hmac::Hmac for BoringHmac {
|
||||||
fn with_key(&self, key: &[u8]) -> Box<dyn crypto::hmac::Key> {
|
fn with_key(&self, key: &[u8]) -> Box<dyn crypto::hmac::Key> {
|
||||||
Box::new(unsafe {
|
Box::new(unsafe {
|
||||||
let ctx = cvt_p(boring_sys::HMAC_CTX_new()).unwrap();
|
let ctx = HmacCtx::from_ptr(cvt_p(boring_sys::HMAC_CTX_new()).unwrap());
|
||||||
|
|
||||||
let md = boring::hash::MessageDigest::from_nid(self.0).unwrap();
|
let md = boring::hash::MessageDigest::from_nid(self.0).unwrap();
|
||||||
|
|
||||||
|
|
@ -33,31 +35,13 @@ impl crypto::hmac::Hmac for BoringHmac {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
struct BoringHmacKey {
|
struct BoringHmacKey {
|
||||||
ctx: *mut boring_sys::HMAC_CTX,
|
ctx: HmacCtx,
|
||||||
md: MessageDigest,
|
md: MessageDigest,
|
||||||
key: Vec<u8>,
|
key: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for BoringHmacKey {
|
|
||||||
fn clone(&self) -> Self {
|
|
||||||
let ctx = unsafe {
|
|
||||||
let ctx = cvt_p(boring_sys::HMAC_CTX_new()).unwrap();
|
|
||||||
|
|
||||||
cvt(boring_sys::HMAC_CTX_copy(ctx, self.ctx)).unwrap();
|
|
||||||
ctx
|
|
||||||
};
|
|
||||||
Self {
|
|
||||||
ctx,
|
|
||||||
md: self.md.clone(),
|
|
||||||
key: self.key.clone(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe impl Sync for BoringHmacKey {}
|
|
||||||
unsafe impl Send for BoringHmacKey {}
|
|
||||||
|
|
||||||
impl crypto::hmac::Key for BoringHmacKey {
|
impl crypto::hmac::Key for BoringHmacKey {
|
||||||
fn sign_concat(&self, first: &[u8], middle: &[&[u8]], last: &[u8]) -> crypto::hmac::Tag {
|
fn sign_concat(&self, first: &[u8], middle: &[&[u8]], last: &[u8]) -> crypto::hmac::Tag {
|
||||||
let mut out = [0u8; 32];
|
let mut out = [0u8; 32];
|
||||||
|
|
@ -65,7 +49,7 @@ impl crypto::hmac::Key for BoringHmacKey {
|
||||||
crypto::hmac::Tag::new(unsafe {
|
crypto::hmac::Tag::new(unsafe {
|
||||||
// initialize a new hmac
|
// initialize a new hmac
|
||||||
cvt(boring_sys::HMAC_Init_ex(
|
cvt(boring_sys::HMAC_Init_ex(
|
||||||
self.ctx,
|
self.ctx.as_ptr(),
|
||||||
self.key.as_ptr() as *const c_void,
|
self.key.as_ptr() as *const c_void,
|
||||||
self.key.len(),
|
self.key.len(),
|
||||||
self.md.as_ptr(),
|
self.md.as_ptr(),
|
||||||
|
|
@ -74,21 +58,31 @@ impl crypto::hmac::Key for BoringHmacKey {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
cvt(boring_sys::HMAC_Update(
|
cvt(boring_sys::HMAC_Update(
|
||||||
self.ctx,
|
self.ctx.as_ptr(),
|
||||||
first.as_ptr(),
|
first.as_ptr(),
|
||||||
first.len(),
|
first.len(),
|
||||||
))
|
))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
for m in middle {
|
for m in middle {
|
||||||
cvt(boring_sys::HMAC_Update(self.ctx, m.as_ptr(), m.len())).unwrap();
|
cvt(boring_sys::HMAC_Update(
|
||||||
|
self.ctx.as_ptr(),
|
||||||
|
m.as_ptr(),
|
||||||
|
m.len(),
|
||||||
|
))
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
cvt(boring_sys::HMAC_Update(self.ctx, last.as_ptr(), last.len())).unwrap();
|
cvt(boring_sys::HMAC_Update(
|
||||||
|
self.ctx.as_ptr(),
|
||||||
|
last.as_ptr(),
|
||||||
|
last.len(),
|
||||||
|
))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let mut out_len = 0;
|
let mut out_len = 0;
|
||||||
cvt(boring_sys::HMAC_Final(
|
cvt(boring_sys::HMAC_Final(
|
||||||
self.ctx,
|
self.ctx.as_ptr(),
|
||||||
out.as_mut_ptr(),
|
out.as_mut_ptr(),
|
||||||
&mut out_len,
|
&mut out_len,
|
||||||
))
|
))
|
||||||
|
|
@ -103,14 +97,6 @@ impl crypto::hmac::Key for BoringHmacKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for BoringHmacKey {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
unsafe {
|
|
||||||
boring_sys::HMAC_CTX_free(self.ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::SHA256;
|
use super::SHA256;
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
use rustls::crypto::{self, ActiveKeyExchange};
|
use rustls::crypto::{self, ActiveKeyExchange};
|
||||||
|
|
||||||
mod dh;
|
mod dh;
|
||||||
mod evp;
|
mod ex;
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
enum DhKeyType {
|
enum DhKeyType {
|
||||||
EC(i32),
|
EC((boring::ec::EcGroup, i32)),
|
||||||
ED(i32),
|
ED(i32),
|
||||||
FFDHE2048,
|
FFDHE2048,
|
||||||
}
|
}
|
||||||
|
|
@ -16,7 +15,7 @@ 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(
|
||||||
evp::BoringEvpKey::generate_x25519().map_err(|_| crypto::GetRandomFailed)?,
|
ex::ExKeyExchange::with_x25519().map_err(|_| crypto::GetRandomFailed)?,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -31,7 +30,7 @@ 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(
|
||||||
evp::BoringEvpKey::generate_x448().map_err(|_| crypto::GetRandomFailed)?,
|
ex::ExKeyExchange::with_x448().map_err(|_| crypto::GetRandomFailed)?,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -46,7 +45,7 @@ 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(
|
||||||
evp::BoringEvpKey::generate_secp256r1().map_err(|_| crypto::GetRandomFailed)?,
|
ex::ExKeyExchange::with_secp256r1().map_err(|_| crypto::GetRandomFailed)?,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -61,7 +60,7 @@ 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(
|
||||||
evp::BoringEvpKey::generate_secp384r1().map_err(|_| crypto::GetRandomFailed)?,
|
ex::ExKeyExchange::with_secp384r1().map_err(|_| crypto::GetRandomFailed)?,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -76,7 +75,7 @@ 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(
|
||||||
evp::BoringEvpKey::generate_secp521r1().map_err(|_| crypto::GetRandomFailed)?,
|
ex::ExKeyExchange::with_secp521r1().map_err(|_| crypto::GetRandomFailed)?,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -104,28 +103,6 @@ impl crypto::SupportedKxGroup for FfDHe2048 {
|
||||||
mod tests {
|
mod tests {
|
||||||
use rustls::crypto::ActiveKeyExchange;
|
use rustls::crypto::ActiveKeyExchange;
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_derive_ed() {
|
|
||||||
let alice = super::evp::BoringEvpKey::generate_x25519().unwrap();
|
|
||||||
let bob = super::evp::BoringEvpKey::generate_x25519().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)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_derive_ec() {
|
|
||||||
let alice = super::evp::BoringEvpKey::generate_secp256r1().unwrap();
|
|
||||||
let bob = super::evp::BoringEvpKey::generate_secp256r1().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)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_derive_dh() {
|
fn test_derive_dh() {
|
||||||
let alice = super::dh::BoringDhKey::generate_ffdhe_2048().unwrap();
|
let alice = super::dh::BoringDhKey::generate_ffdhe_2048().unwrap();
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use boring::error::ErrorStack;
|
use boring::{dh::Dh, error::ErrorStack, pkey::Private};
|
||||||
use foreign_types::ForeignType;
|
use foreign_types::ForeignType;
|
||||||
use rustls::crypto;
|
use rustls::crypto;
|
||||||
|
|
||||||
|
|
@ -7,7 +7,7 @@ use crate::helper::{cvt, cvt_p};
|
||||||
use super::DhKeyType;
|
use super::DhKeyType;
|
||||||
|
|
||||||
pub struct BoringDhKey {
|
pub struct BoringDhKey {
|
||||||
dh: boring::dh::Dh<boring::pkey::Private>,
|
dh: Dh<Private>,
|
||||||
pub_bytes: Vec<u8>,
|
pub_bytes: Vec<u8>,
|
||||||
key_type: DhKeyType,
|
key_type: DhKeyType,
|
||||||
}
|
}
|
||||||
|
|
@ -15,7 +15,7 @@ pub struct BoringDhKey {
|
||||||
impl BoringDhKey {
|
impl BoringDhKey {
|
||||||
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 { boring::dh::Dh::from_ptr(cvt_p(boring_sys::DH_get_rfc7919_2048())?) },
|
dh: unsafe { Dh::from_ptr(cvt_p(boring_sys::DH_get_rfc7919_2048())?) },
|
||||||
pub_bytes: Vec::new(),
|
pub_bytes: Vec::new(),
|
||||||
key_type: DhKeyType::FFDHE2048,
|
key_type: DhKeyType::FFDHE2048,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,315 +0,0 @@
|
||||||
use std::{
|
|
||||||
mem::MaybeUninit,
|
|
||||||
ops::{Deref, DerefMut},
|
|
||||||
ptr::{self, NonNull},
|
|
||||||
};
|
|
||||||
|
|
||||||
use boring::error::ErrorStack;
|
|
||||||
use foreign_types::{ForeignType, ForeignTypeRef, Opaque};
|
|
||||||
use rustls::crypto;
|
|
||||||
use spki::der::Decode;
|
|
||||||
|
|
||||||
use crate::helper::{cvt, cvt_p};
|
|
||||||
|
|
||||||
use super::DhKeyType;
|
|
||||||
|
|
||||||
pub struct BoringEvpPkeyCtxRef(Opaque);
|
|
||||||
|
|
||||||
unsafe impl ForeignTypeRef for BoringEvpPkeyCtxRef {
|
|
||||||
type CType = boring_sys::EVP_PKEY_CTX;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe impl Sync for BoringEvpPkeyCtxRef {}
|
|
||||||
unsafe impl Send for BoringEvpPkeyCtxRef {}
|
|
||||||
|
|
||||||
unsafe impl Sync for BoringEvpPkeyCtx {}
|
|
||||||
unsafe impl Send for BoringEvpPkeyCtx {}
|
|
||||||
|
|
||||||
pub struct BoringEvpPkeyCtx(NonNull<boring_sys::EVP_PKEY_CTX>);
|
|
||||||
unsafe impl ForeignType for BoringEvpPkeyCtx {
|
|
||||||
type CType = boring_sys::EVP_PKEY_CTX;
|
|
||||||
|
|
||||||
type Ref = BoringEvpPkeyCtxRef;
|
|
||||||
|
|
||||||
unsafe fn from_ptr(ptr: *mut Self::CType) -> Self {
|
|
||||||
Self(NonNull::new_unchecked(ptr))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_ptr(&self) -> *mut Self::CType {
|
|
||||||
self.0.as_ptr()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Drop for BoringEvpPkeyCtx {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
unsafe {
|
|
||||||
boring_sys::EVP_PKEY_CTX_free(self.0.as_ptr());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl core::fmt::Debug for BoringEvpPkeyCtx {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
f.debug_tuple("BoringEvpPkeyCtx").field(&self.0).finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Deref for BoringEvpPkeyCtx {
|
|
||||||
type Target = BoringEvpPkeyCtxRef;
|
|
||||||
|
|
||||||
fn deref(&self) -> &BoringEvpPkeyCtxRef {
|
|
||||||
unsafe { BoringEvpPkeyCtxRef::from_ptr(self.as_ptr()) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DerefMut for BoringEvpPkeyCtx {
|
|
||||||
fn deref_mut(&mut self) -> &mut BoringEvpPkeyCtxRef {
|
|
||||||
unsafe { BoringEvpPkeyCtxRef::from_ptr_mut(self.as_ptr()) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct BoringEvpKey {
|
|
||||||
/// the private key context for deriving shared secrets
|
|
||||||
dctx: BoringEvpPkeyCtx,
|
|
||||||
|
|
||||||
key_type: DhKeyType,
|
|
||||||
|
|
||||||
pub_bytes: Vec<u8>,
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe impl Sync for BoringEvpKey {}
|
|
||||||
unsafe impl Send for BoringEvpKey {}
|
|
||||||
|
|
||||||
impl BoringEvpKey {
|
|
||||||
pub fn generate_x25519() -> Result<Self, ErrorStack> {
|
|
||||||
unsafe {
|
|
||||||
Self::generate_with_ctx(
|
|
||||||
DhKeyType::ED(boring_sys::NID_X25519),
|
|
||||||
Self::generate_ctx_from_nid(boring_sys::NID_X25519)?,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn generate_x448() -> Result<Self, ErrorStack> {
|
|
||||||
unsafe {
|
|
||||||
Self::generate_with_ctx(
|
|
||||||
DhKeyType::ED(boring_sys::NID_X448),
|
|
||||||
Self::generate_ctx_from_nid(boring_sys::NID_X448)?,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn generate_secp256r1() -> Result<Self, ErrorStack> {
|
|
||||||
unsafe {
|
|
||||||
let pctx = Self::generate_ctx_with_ec_curve(boring_sys::NID_X9_62_prime256v1)?;
|
|
||||||
Self::generate_with_ctx(DhKeyType::EC(boring_sys::NID_X9_62_prime256v1), pctx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn generate_secp384r1() -> Result<Self, ErrorStack> {
|
|
||||||
unsafe {
|
|
||||||
let pctx = Self::generate_ctx_with_ec_curve(boring_sys::NID_secp384r1)?;
|
|
||||||
Self::generate_with_ctx(DhKeyType::EC(boring_sys::NID_secp384r1), pctx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn generate_secp521r1() -> Result<Self, ErrorStack> {
|
|
||||||
unsafe {
|
|
||||||
let pctx = Self::generate_ctx_with_ec_curve(boring_sys::NID_secp521r1)?;
|
|
||||||
Self::generate_with_ctx(DhKeyType::EC(boring_sys::NID_secp521r1), pctx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn generate_ctx_with_ec_curve(curve_nid: i32) -> Result<BoringEvpPkeyCtx, ErrorStack> {
|
|
||||||
boring_sys::init();
|
|
||||||
|
|
||||||
let pctx = BoringEvpPkeyCtx::from_ptr(cvt_p(boring_sys::EVP_PKEY_CTX_new_id(
|
|
||||||
boring_sys::EVP_PKEY_EC,
|
|
||||||
ptr::null_mut(),
|
|
||||||
))?);
|
|
||||||
|
|
||||||
// The following function is for generating parameters
|
|
||||||
cvt(boring_sys::EVP_PKEY_paramgen_init(pctx.as_ptr()))?;
|
|
||||||
|
|
||||||
// Set the curve
|
|
||||||
cvt(boring_sys::EVP_PKEY_CTX_set_ec_paramgen_curve_nid(
|
|
||||||
pctx.as_ptr(),
|
|
||||||
curve_nid,
|
|
||||||
))?;
|
|
||||||
|
|
||||||
// Used a named curve which has max compatiblity according man page
|
|
||||||
cvt(boring_sys::EVP_PKEY_CTX_set_ec_param_enc(
|
|
||||||
pctx.as_ptr(),
|
|
||||||
boring_sys::OPENSSL_EC_NAMED_CURVE,
|
|
||||||
))?;
|
|
||||||
|
|
||||||
// generate parameters
|
|
||||||
let mut pkey = MaybeUninit::<*mut boring_sys::EVP_PKEY>::new(ptr::null_mut()).assume_init();
|
|
||||||
cvt(boring_sys::EVP_PKEY_paramgen(pctx.as_ptr(), &mut pkey))?;
|
|
||||||
let pkey: boring::pkey::PKey<boring::pkey::Params> = boring::pkey::PKey::from_ptr(pkey);
|
|
||||||
|
|
||||||
Ok(BoringEvpPkeyCtx::from_ptr(
|
|
||||||
// ctx will take ownership of pkey
|
|
||||||
cvt_p(boring_sys::EVP_PKEY_CTX_new(pkey.as_ptr(), ptr::null_mut())).expect("failed"),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn generate_ctx_from_nid(nid: i32) -> Result<BoringEvpPkeyCtx, ErrorStack> {
|
|
||||||
boring_sys::init();
|
|
||||||
Ok(unsafe {
|
|
||||||
BoringEvpPkeyCtx::from_ptr(cvt_p(boring_sys::EVP_PKEY_CTX_new_id(
|
|
||||||
nid,
|
|
||||||
ptr::null_mut(),
|
|
||||||
))?)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn generate_with_ctx(
|
|
||||||
key_type: DhKeyType,
|
|
||||||
pctx: BoringEvpPkeyCtx,
|
|
||||||
) -> Result<Self, ErrorStack> {
|
|
||||||
let mut pkey = MaybeUninit::<*mut boring_sys::EVP_PKEY>::new(ptr::null_mut()).assume_init();
|
|
||||||
|
|
||||||
cvt(boring_sys::EVP_PKEY_keygen_init(pctx.as_ptr()))?;
|
|
||||||
|
|
||||||
cvt(boring_sys::EVP_PKEY_keygen(pctx.as_ptr(), &mut pkey))?;
|
|
||||||
let pkey: boring::pkey::PKey<boring::pkey::Private> = boring::pkey::PKey::from_ptr(pkey);
|
|
||||||
|
|
||||||
let dctx = BoringEvpPkeyCtx::from_ptr(
|
|
||||||
// dctx will take ownership of pkey, we can safely drop it
|
|
||||||
cvt_p(boring_sys::EVP_PKEY_CTX_new(pkey.as_ptr(), ptr::null_mut()))?,
|
|
||||||
);
|
|
||||||
|
|
||||||
let pub_bytes = Self::raw_public_key(pkey.as_ref())?;
|
|
||||||
|
|
||||||
Ok(Self {
|
|
||||||
dctx,
|
|
||||||
key_type,
|
|
||||||
pub_bytes,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn raw_public_key(
|
|
||||||
pkey: &boring::pkey::PKeyRef<boring::pkey::Private>,
|
|
||||||
) -> Result<Vec<u8>, ErrorStack> {
|
|
||||||
let key_len = unsafe {
|
|
||||||
// figure out how many bytes we need for the key
|
|
||||||
cvt(boring_sys::i2d_PUBKEY(pkey.as_ptr(), ptr::null_mut()))? as usize
|
|
||||||
};
|
|
||||||
let mut spki = vec![0u8; key_len];
|
|
||||||
unsafe {
|
|
||||||
// write the key to spki
|
|
||||||
cvt(boring_sys::i2d_PUBKEY(
|
|
||||||
pkey.as_ptr(),
|
|
||||||
&mut spki.as_mut_ptr(),
|
|
||||||
))?;
|
|
||||||
}
|
|
||||||
// parse the key
|
|
||||||
let key = spki::SubjectPublicKeyInfoRef::from_der(spki.as_ref()).unwrap();
|
|
||||||
|
|
||||||
// return the raw public key as a new vec
|
|
||||||
Ok(Vec::from(key.subject_public_key.as_bytes().unwrap()))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn diffie_hellman(&self, raw_public_key: &[u8]) -> Result<Vec<u8>, ErrorStack> {
|
|
||||||
match self.key_type {
|
|
||||||
DhKeyType::EC(nid) => self.diffie_hellman_ec(nid, raw_public_key),
|
|
||||||
DhKeyType::ED(nid) => self.diffie_hellman_ed(nid, raw_public_key),
|
|
||||||
_ => unimplemented!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn diffie_hellman_ec(&self, nid: i32, raw_public_key: &[u8]) -> Result<Vec<u8>, ErrorStack> {
|
|
||||||
// this is only the key data not the algo identifier etc
|
|
||||||
let group = boring::ec::EcGroup::from_curve_name(boring::nid::Nid::from_raw(nid))?;
|
|
||||||
let mut bn_ctx = boring::bn::BigNumContext::new()?;
|
|
||||||
let point =
|
|
||||||
crate::verify::ec::ec_point(group.as_ref(), &mut bn_ctx, raw_public_key).unwrap();
|
|
||||||
|
|
||||||
let peerkey = crate::verify::ec::ec_public_key(group.as_ref(), point.as_ref()).unwrap();
|
|
||||||
|
|
||||||
self.diffie_hellman_common(peerkey.as_ptr())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn diffie_hellman_ed(&self, nid: i32, raw_public_key: &[u8]) -> Result<Vec<u8>, ErrorStack> {
|
|
||||||
let peerkey: boring::pkey::PKey<boring::pkey::Public> = unsafe {
|
|
||||||
boring::pkey::PKey::from_ptr(cvt_p(boring_sys::EVP_PKEY_new_raw_public_key(
|
|
||||||
nid,
|
|
||||||
ptr::null_mut(),
|
|
||||||
raw_public_key.as_ptr(),
|
|
||||||
raw_public_key.len(),
|
|
||||||
))?)
|
|
||||||
};
|
|
||||||
|
|
||||||
self.diffie_hellman_common(peerkey.as_ptr())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn diffie_hellman_common(
|
|
||||||
&self,
|
|
||||||
peerkey: *mut boring_sys::EVP_PKEY,
|
|
||||||
) -> Result<Vec<u8>, ErrorStack> {
|
|
||||||
unsafe {
|
|
||||||
// Initialize
|
|
||||||
cvt(boring_sys::EVP_PKEY_derive_init(self.dctx.as_ptr()))?;
|
|
||||||
|
|
||||||
// Provide the peer public key
|
|
||||||
cvt(boring_sys::EVP_PKEY_derive_set_peer(
|
|
||||||
self.dctx.as_ptr(),
|
|
||||||
peerkey,
|
|
||||||
))?;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine buffer length for shared secret
|
|
||||||
let mut secret_len = unsafe {
|
|
||||||
let mut secret_len = 0;
|
|
||||||
cvt(boring_sys::EVP_PKEY_derive(
|
|
||||||
self.dctx.as_ptr(),
|
|
||||||
ptr::null_mut(),
|
|
||||||
&mut secret_len,
|
|
||||||
))?;
|
|
||||||
secret_len
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut secret = vec![0u8; secret_len];
|
|
||||||
unsafe {
|
|
||||||
cvt(boring_sys::EVP_PKEY_derive(
|
|
||||||
self.dctx.as_ptr(),
|
|
||||||
secret.as_mut_ptr(),
|
|
||||||
&mut secret_len,
|
|
||||||
))?;
|
|
||||||
}
|
|
||||||
Ok(secret)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl crypto::ActiveKeyExchange for BoringEvpKey {
|
|
||||||
fn complete(
|
|
||||||
self: Box<Self>,
|
|
||||||
peer_pub_key: &[u8],
|
|
||||||
) -> Result<crypto::SharedSecret, rustls::Error> {
|
|
||||||
let expected_len = self.pub_bytes.len();
|
|
||||||
|
|
||||||
if peer_pub_key.len() != expected_len {
|
|
||||||
return Err(rustls::Error::from(rustls::PeerMisbehaved::InvalidKeyShare));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(crypto::SharedSecret::from(
|
|
||||||
self.diffie_hellman(peer_pub_key)
|
|
||||||
.map_err(|x| rustls::Error::General(x.to_string()))?
|
|
||||||
.as_ref(),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn pub_key(&self) -> &[u8] {
|
|
||||||
self.pub_bytes.as_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn group(&self) -> rustls::NamedGroup {
|
|
||||||
match self.key_type {
|
|
||||||
DhKeyType::ED(boring_sys::NID_X25519) => rustls::NamedGroup::X25519,
|
|
||||||
DhKeyType::ED(boring_sys::NID_X448) => rustls::NamedGroup::X448,
|
|
||||||
DhKeyType::EC(boring_sys::NID_X9_62_prime256v1) => rustls::NamedGroup::secp256r1,
|
|
||||||
DhKeyType::EC(boring_sys::NID_secp384r1) => rustls::NamedGroup::secp384r1,
|
|
||||||
DhKeyType::EC(boring_sys::NID_secp521r1) => rustls::NamedGroup::secp521r1,
|
|
||||||
_ => unimplemented!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
171
boring-rustls-provider/src/kx/ex.rs
Normal file
171
boring-rustls-provider/src/kx/ex.rs
Normal file
|
|
@ -0,0 +1,171 @@
|
||||||
|
use std::{
|
||||||
|
mem::MaybeUninit,
|
||||||
|
ptr::{self},
|
||||||
|
};
|
||||||
|
|
||||||
|
use boring::{
|
||||||
|
ec::{EcGroup, EcKey},
|
||||||
|
error::ErrorStack,
|
||||||
|
nid::Nid,
|
||||||
|
pkey::{PKey, PKeyRef, Private},
|
||||||
|
};
|
||||||
|
use boring_additions::evp::EvpPkeyCtx;
|
||||||
|
use foreign_types::ForeignType;
|
||||||
|
use rustls::crypto;
|
||||||
|
use spki::der::Decode;
|
||||||
|
|
||||||
|
use crate::helper::{cvt, cvt_p};
|
||||||
|
|
||||||
|
use super::DhKeyType;
|
||||||
|
|
||||||
|
pub struct ExKeyExchange {
|
||||||
|
own_key: PKey<Private>,
|
||||||
|
pub_bytes: Vec<u8>,
|
||||||
|
key_type: DhKeyType,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExKeyExchange {
|
||||||
|
pub fn with_x25519() -> Result<Self, ErrorStack> {
|
||||||
|
Self::ed_from_curve(Nid::from_raw(boring_sys::NID_X25519))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_x448() -> Result<Self, ErrorStack> {
|
||||||
|
Self::ed_from_curve(Nid::from_raw(boring_sys::NID_X448))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_secp256r1() -> Result<Self, ErrorStack> {
|
||||||
|
Self::ec_from_curve(Nid::X9_62_PRIME256V1)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_secp384r1() -> Result<Self, ErrorStack> {
|
||||||
|
Self::ec_from_curve(Nid::SECP384R1)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_secp521r1() -> Result<Self, ErrorStack> {
|
||||||
|
Self::ec_from_curve(Nid::SECP521R1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ec_from_curve(nid: Nid) -> Result<Self, ErrorStack> {
|
||||||
|
let ec_group = EcGroup::from_curve_name(nid)?;
|
||||||
|
let ec_key = EcKey::generate(&ec_group)?;
|
||||||
|
|
||||||
|
let own_key = PKey::from_ec_key(ec_key)?;
|
||||||
|
let pub_bytes = Self::raw_public_key(&own_key);
|
||||||
|
Ok(Self {
|
||||||
|
own_key,
|
||||||
|
pub_bytes,
|
||||||
|
key_type: DhKeyType::EC((ec_group, nid.as_raw())),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ed_from_curve(nid: Nid) -> Result<Self, ErrorStack> {
|
||||||
|
let pkey_ctx = unsafe {
|
||||||
|
EvpPkeyCtx::from_ptr(cvt_p(boring_sys::EVP_PKEY_CTX_new_id(
|
||||||
|
nid.as_raw(),
|
||||||
|
ptr::null_mut(),
|
||||||
|
))?)
|
||||||
|
};
|
||||||
|
|
||||||
|
let own_key: PKey<Private> = unsafe {
|
||||||
|
cvt(boring_sys::EVP_PKEY_keygen_init(pkey_ctx.as_ptr()))?;
|
||||||
|
|
||||||
|
let mut pkey =
|
||||||
|
MaybeUninit::<*mut boring_sys::EVP_PKEY>::new(ptr::null_mut()).assume_init();
|
||||||
|
cvt(boring_sys::EVP_PKEY_keygen(pkey_ctx.as_ptr(), &mut pkey))?;
|
||||||
|
|
||||||
|
PKey::from_ptr(pkey)
|
||||||
|
};
|
||||||
|
|
||||||
|
let pub_bytes = Self::raw_public_key(&own_key);
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
own_key,
|
||||||
|
pub_bytes,
|
||||||
|
key_type: DhKeyType::ED(nid.as_raw()),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn raw_public_key(pkey: &PKeyRef<Private>) -> Vec<u8> {
|
||||||
|
let spki = pkey.public_key_to_der().unwrap();
|
||||||
|
|
||||||
|
// parse the key
|
||||||
|
let key = spki::SubjectPublicKeyInfoRef::from_der(spki.as_ref()).unwrap();
|
||||||
|
|
||||||
|
// return the raw public key as a new vec
|
||||||
|
Vec::from(key.subject_public_key.as_bytes().unwrap())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl crypto::ActiveKeyExchange for ExKeyExchange {
|
||||||
|
fn complete(
|
||||||
|
self: Box<Self>,
|
||||||
|
peer_pub_key: &[u8],
|
||||||
|
) -> Result<crypto::SharedSecret, rustls::Error> {
|
||||||
|
let peerkey = match &self.key_type {
|
||||||
|
DhKeyType::EC((group, _)) => {
|
||||||
|
let mut bn_ctx = boring::bn::BigNumContext::new()
|
||||||
|
.map_err(|x| rustls::Error::General(x.to_string()))?;
|
||||||
|
|
||||||
|
let point = crate::verify::ec::ec_point(group, &mut bn_ctx, peer_pub_key)
|
||||||
|
.map_err(|_| rustls::Error::from(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] {
|
||||||
|
&self.pub_bytes
|
||||||
|
}
|
||||||
|
|
||||||
|
fn group(&self) -> rustls::NamedGroup {
|
||||||
|
match self.key_type {
|
||||||
|
DhKeyType::ED(boring_sys::NID_X25519) => rustls::NamedGroup::X25519,
|
||||||
|
DhKeyType::ED(boring_sys::NID_X448) => rustls::NamedGroup::X448,
|
||||||
|
DhKeyType::EC((_, boring_sys::NID_X9_62_prime256v1)) => rustls::NamedGroup::secp256r1,
|
||||||
|
DhKeyType::EC((_, boring_sys::NID_secp384r1)) => rustls::NamedGroup::secp384r1,
|
||||||
|
DhKeyType::EC((_, boring_sys::NID_secp521r1)) => rustls::NamedGroup::secp521r1,
|
||||||
|
_ => unimplemented!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::ExKeyExchange;
|
||||||
|
use rustls::crypto::ActiveKeyExchange;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_derive_ec() {
|
||||||
|
let kx = Box::new(ExKeyExchange::with_secp256r1().unwrap());
|
||||||
|
let kx1 = ExKeyExchange::with_secp256r1().unwrap();
|
||||||
|
|
||||||
|
kx.group();
|
||||||
|
kx.complete(kx1.pub_key()).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_derive_ed() {
|
||||||
|
let kx = Box::new(ExKeyExchange::with_x25519().unwrap());
|
||||||
|
let kx1 = ExKeyExchange::with_x25519().unwrap();
|
||||||
|
|
||||||
|
kx.group();
|
||||||
|
kx.complete(kx1.pub_key()).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use rustls::{SignatureScheme, WebPkiSupportedAlgorithms};
|
use rustls::{SignatureScheme, WebPkiSupportedAlgorithms};
|
||||||
|
|
||||||
pub(crate) mod ec;
|
pub(crate) mod ec;
|
||||||
mod ed;
|
pub(crate) mod ed;
|
||||||
pub(crate) mod rsa;
|
pub(crate) mod rsa;
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ 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(public_key, self.0)?;
|
let public_key = ed_public_key_for_scheme(public_key, self.0)?;
|
||||||
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(
|
||||||
|
|
@ -55,18 +55,25 @@ fn ed_verifier_from_params(
|
||||||
verifier
|
verifier
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ed_public_key(
|
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>, InvalidSignature> {
|
||||||
let typ = 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,
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
};
|
});
|
||||||
|
ed_public_key(spki_spk, nid)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ed_public_key(
|
||||||
|
spki_spk: &[u8],
|
||||||
|
nid: boring::nid::Nid,
|
||||||
|
) -> Result<boring::pkey::PKey<boring::pkey::Public>, InvalidSignature> {
|
||||||
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(
|
||||||
typ,
|
nid.as_raw(),
|
||||||
ptr::null_mut(),
|
ptr::null_mut(),
|
||||||
spki_spk.as_ptr(),
|
spki_spk.as_ptr(),
|
||||||
spki_spk.len(),
|
spki_spk.len(),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue