-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
initial implemention of openssl crypto provider
- Loading branch information
0 parents
commit 62b0c76
Showing
19 changed files
with
2,166 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
target/ | ||
Cargo.lock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
[package] | ||
name = "rustls-openssl" | ||
authors = ["Tom Fay <[email protected]>"] | ||
version = "0.1.0" | ||
edition = "2021" | ||
license = "MIT" | ||
description = "Rustls crypto provider for OpenSSL" | ||
homepage = "https://github.com/tofay/rustls-openssl" | ||
repository = "https://github.com/tofay/rustls-openssl" | ||
readme = "README.md" | ||
|
||
[dependencies] | ||
openssl = { version = "0.10.68" } | ||
rustls = { version = "0.23.0", features = [ | ||
"tls12", | ||
"std", | ||
], default-features = false } | ||
rustls-webpki = "0.102.2" | ||
|
||
[features] | ||
default = [] | ||
x25519 = [] | ||
chacha = [] | ||
|
||
[dev-dependencies] | ||
lazy_static = "1.4.0" | ||
once_cell = "1.8.0" | ||
rstest = "0.23.0" | ||
rustls-pemfile = "2" | ||
webpki-roots = "0.26" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# rustls-openssl | ||
An experimental [rustls Crypto Provider](https://docs.rs/rustls/latest/rustls/crypto/struct.CryptoProvider.html) that uses OpenSSL for cryptographic operations. | ||
|
||
## Usage | ||
The main entry points are the `rustls_openssl::default_provider` and `rustls_openssl::custom_provider` functions. | ||
See the [rustls documentation]((https://docs.rs/rustls/latest/rustls/crypto/struct.CryptoProvider.html)) for how to use them. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
use crate::hash::HashAlgorithm; | ||
use crate::hmac::{HmacSha256, HmacSha384}; | ||
use crate::tls12::{AesGcm, Tls12Gcm}; | ||
use rustls::crypto::{CipherSuiteCommon, KeyExchangeAlgorithm}; | ||
use rustls::{ | ||
CipherSuite, SignatureScheme, SupportedCipherSuite, Tls12CipherSuite, Tls13CipherSuite, | ||
}; | ||
|
||
use rustls::crypto::tls12::PrfUsingHmac; | ||
use rustls::crypto::tls13::HkdfUsingHmac; | ||
|
||
use crate::tls13::AeadAlgorithm; | ||
|
||
/// The TLS1.3 ciphersuite TLS_CHACHA20_POLY1305_SHA256 | ||
#[cfg(feature = "chacha")] | ||
pub static TLS13_CHACHA20_POLY1305_SHA256: SupportedCipherSuite = | ||
SupportedCipherSuite::Tls13(&Tls13CipherSuite { | ||
common: CipherSuiteCommon { | ||
suite: CipherSuite::TLS13_CHACHA20_POLY1305_SHA256, | ||
hash_provider: &HashAlgorithm::SHA256, | ||
confidentiality_limit: u64::MAX, | ||
}, | ||
hkdf_provider: &HkdfUsingHmac(&HmacSha256), | ||
aead_alg: &AeadAlgorithm::ChaCha20Poly1305, | ||
quic: None, | ||
}); | ||
|
||
/// The TLS1.3 ciphersuite TLS_AES_256_GCM_SHA384 | ||
pub static TLS13_AES_256_GCM_SHA384: SupportedCipherSuite = | ||
SupportedCipherSuite::Tls13(&Tls13CipherSuite { | ||
common: CipherSuiteCommon { | ||
suite: CipherSuite::TLS13_AES_256_GCM_SHA384, | ||
hash_provider: &HashAlgorithm::SHA384, | ||
confidentiality_limit: 1 << 23, | ||
}, | ||
hkdf_provider: &HkdfUsingHmac(&HmacSha384), | ||
aead_alg: &AeadAlgorithm::Aes256Gcm, | ||
quic: None, | ||
}); | ||
|
||
/// The TLS1.3 ciphersuite TLS_AES_128_GCM_SHA256 | ||
pub static TLS13_AES_128_GCM_SHA256: SupportedCipherSuite = | ||
SupportedCipherSuite::Tls13(&Tls13CipherSuite { | ||
common: CipherSuiteCommon { | ||
suite: CipherSuite::TLS13_AES_128_GCM_SHA256, | ||
hash_provider: &HashAlgorithm::SHA256, | ||
confidentiality_limit: 1 << 23, | ||
}, | ||
hkdf_provider: &HkdfUsingHmac(&HmacSha256), | ||
aead_alg: &AeadAlgorithm::Aes128Gcm, | ||
quic: None, | ||
}); | ||
|
||
/// TLS 1.2 | ||
// /// The TLS1.2 ciphersuite TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256. | ||
// #[cfg(feature = "chacha")] | ||
// pub static TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: SupportedCipherSuite = | ||
// SupportedCipherSuite::Tls12(&Tls12CipherSuite { | ||
// common: CipherSuiteCommon { | ||
// suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, | ||
// hash_provider: &HashAlgorithm::SHA256, | ||
// confidentiality_limit: u64::MAX, | ||
// }, | ||
// kx: KeyExchangeAlgorithm::ECDHE, | ||
// sign: TLS12_ECDSA_SCHEMES, | ||
// aead_alg: &crate::tls12::Tls12ChaCha, | ||
// prf_provider: &PrfUsingHmac(&HmacSha256), | ||
// }); | ||
|
||
/// The TLS1.2 ciphersuite TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 | ||
#[cfg(feature = "chacha")] | ||
pub static TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: SupportedCipherSuite = | ||
SupportedCipherSuite::Tls12(&Tls12CipherSuite { | ||
common: CipherSuiteCommon { | ||
suite: CipherSuite::TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, | ||
hash_provider: &HashAlgorithm::SHA256, | ||
confidentiality_limit: u64::MAX, | ||
}, | ||
kx: KeyExchangeAlgorithm::ECDHE, | ||
sign: TLS12_RSA_SCHEMES, | ||
aead_alg: &crate::tls12::Tls12ChaCha, | ||
prf_provider: &PrfUsingHmac(&HmacSha256), | ||
}); | ||
|
||
/// The TLS1.2 ciphersuite TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 | ||
pub static TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: SupportedCipherSuite = | ||
SupportedCipherSuite::Tls12(&Tls12CipherSuite { | ||
common: CipherSuiteCommon { | ||
suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, | ||
hash_provider: &HashAlgorithm::SHA256, | ||
confidentiality_limit: 1 << 23, | ||
}, | ||
kx: KeyExchangeAlgorithm::ECDHE, | ||
sign: TLS12_RSA_SCHEMES, | ||
aead_alg: &Tls12Gcm { | ||
algo_type: AesGcm::Aes128Gcm, | ||
}, | ||
prf_provider: &PrfUsingHmac(&HmacSha256), | ||
}); | ||
|
||
/// The TLS1.2 ciphersuite TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 | ||
pub static TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: SupportedCipherSuite = | ||
SupportedCipherSuite::Tls12(&Tls12CipherSuite { | ||
common: CipherSuiteCommon { | ||
suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, | ||
hash_provider: &HashAlgorithm::SHA384, | ||
confidentiality_limit: 1 << 23, | ||
}, | ||
kx: KeyExchangeAlgorithm::ECDHE, | ||
sign: TLS12_RSA_SCHEMES, | ||
aead_alg: &Tls12Gcm { | ||
algo_type: AesGcm::Aes256Gcm, | ||
}, | ||
prf_provider: &PrfUsingHmac(&HmacSha384), | ||
}); | ||
|
||
// /// The TLS1.2 ciphersuite TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 | ||
// pub static TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: SupportedCipherSuite = | ||
// SupportedCipherSuite::Tls12(&Tls12CipherSuite { | ||
// common: CipherSuiteCommon { | ||
// suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, | ||
// hash_provider: &HashAlgorithm::SHA256, | ||
// confidentiality_limit: 1 << 23, | ||
// }, | ||
// kx: KeyExchangeAlgorithm::ECDHE, | ||
// sign: TLS12_ECDSA_SCHEMES, | ||
// aead_alg: &Tls12Gcm { | ||
// algo_type: AesGcm::Aes128Gcm, | ||
// }, | ||
// prf_provider: &PrfUsingHmac(&HmacSha256), | ||
// }); | ||
|
||
// /// The TLS1.2 ciphersuite TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 | ||
// pub static TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: SupportedCipherSuite = | ||
// SupportedCipherSuite::Tls12(&Tls12CipherSuite { | ||
// common: CipherSuiteCommon { | ||
// suite: CipherSuite::TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, | ||
// hash_provider: &HashAlgorithm::SHA384, | ||
// confidentiality_limit: 1 << 23, | ||
// }, | ||
// kx: KeyExchangeAlgorithm::ECDHE, | ||
// sign: TLS12_ECDSA_SCHEMES, | ||
// aead_alg: &Tls12Gcm { | ||
// algo_type: AesGcm::Aes256Gcm, | ||
// }, | ||
// prf_provider: &PrfUsingHmac(&HmacSha384), | ||
// }); | ||
|
||
// static TLS12_ECDSA_SCHEMES: &[SignatureScheme] = &[ | ||
// SignatureScheme::ECDSA_NISTP521_SHA512, | ||
// SignatureScheme::ECDSA_NISTP384_SHA384, | ||
// SignatureScheme::ECDSA_NISTP256_SHA256, | ||
// ]; | ||
|
||
/// RSA schemes in descending order of preference | ||
pub(crate) static TLS12_RSA_SCHEMES: &[SignatureScheme] = &[ | ||
SignatureScheme::RSA_PSS_SHA512, | ||
SignatureScheme::RSA_PSS_SHA384, | ||
SignatureScheme::RSA_PSS_SHA256, | ||
SignatureScheme::RSA_PKCS1_SHA512, | ||
SignatureScheme::RSA_PKCS1_SHA384, | ||
SignatureScheme::RSA_PKCS1_SHA256, | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
use openssl::bn::BigNumContext; | ||
use openssl::derive::Deriver; | ||
use openssl::ec::{EcGroup, EcKey, EcPoint, PointConversionForm}; | ||
use openssl::nid::Nid; | ||
#[cfg(feature = "x25519")] | ||
use openssl::pkey::Id; | ||
use openssl::pkey::{PKey, Private, Public}; | ||
use rustls::crypto::{ActiveKeyExchange, SharedSecret, SupportedKxGroup}; | ||
use rustls::{Error, NamedGroup}; | ||
|
||
/// Supported KeyExchange groups. | ||
/// ```ignore | ||
/// SECP384R1 | ||
/// SECP256R1 | ||
/// X25519 // Enabled with the `x25519` feature | ||
/// ``` | ||
pub const ALL_KX_GROUPS: &[&dyn SupportedKxGroup] = &[ | ||
SECP256R1, | ||
SECP384R1, | ||
#[cfg(feature = "x25519")] | ||
X25519, | ||
]; | ||
|
||
/// KXGroup's that use openssl::ec module with Nid's for key exchange. | ||
#[derive(Debug)] | ||
struct EcKxGroup { | ||
name: NamedGroup, | ||
nid: Nid, | ||
} | ||
|
||
struct EcKeyExchange { | ||
priv_key: EcKey<Private>, | ||
name: NamedGroup, | ||
group: EcGroup, | ||
pub_key: Vec<u8>, | ||
} | ||
|
||
#[cfg(feature = "x25519")] | ||
/// KXGroup for X25519 | ||
#[derive(Debug)] | ||
struct X25519KxGroup {} | ||
|
||
#[cfg(feature = "x25519")] | ||
#[derive(Debug)] | ||
struct X25519KeyExchange { | ||
private_key: PKey<Private>, | ||
public_key: Vec<u8>, | ||
} | ||
|
||
#[cfg(feature = "x25519")] | ||
pub const X25519: &dyn SupportedKxGroup = &X25519KxGroup {}; | ||
|
||
pub const SECP256R1: &dyn SupportedKxGroup = &EcKxGroup { | ||
name: NamedGroup::secp256r1, | ||
nid: Nid::X9_62_PRIME256V1, | ||
}; | ||
|
||
pub const SECP384R1: &dyn SupportedKxGroup = &EcKxGroup { | ||
name: NamedGroup::secp384r1, | ||
nid: Nid::SECP384R1, | ||
}; | ||
|
||
impl SupportedKxGroup for EcKxGroup { | ||
fn start(&self) -> Result<Box<(dyn ActiveKeyExchange)>, Error> { | ||
let group = EcGroup::from_curve_name(self.nid).unwrap(); | ||
let priv_key = EcKey::generate(&group).unwrap(); | ||
let mut ctx = BigNumContext::new().unwrap(); | ||
let pub_key = priv_key | ||
.public_key() | ||
.to_bytes(&group, PointConversionForm::UNCOMPRESSED, &mut ctx) | ||
.unwrap(); | ||
|
||
Ok(Box::new(EcKeyExchange { | ||
priv_key, | ||
name: self.name, | ||
group, | ||
pub_key, | ||
})) | ||
} | ||
|
||
fn name(&self) -> NamedGroup { | ||
self.name | ||
} | ||
} | ||
|
||
impl EcKeyExchange { | ||
fn load_peer_key(&self, peer_pub_key: &[u8]) -> Result<PKey<Public>, Error> { | ||
let mut ctx = BigNumContext::new().unwrap(); | ||
let point = EcPoint::from_bytes(&self.group, peer_pub_key, &mut ctx).unwrap(); | ||
let peer_key = EcKey::from_public_key(&self.group, &point).unwrap(); | ||
peer_key.check_key().unwrap(); | ||
let peer_key: PKey<_> = peer_key.try_into().unwrap(); | ||
Ok(peer_key) | ||
} | ||
} | ||
|
||
impl ActiveKeyExchange for EcKeyExchange { | ||
fn complete(self: Box<Self>, peer_pub_key: &[u8]) -> Result<SharedSecret, Error> { | ||
let peer_key = self.load_peer_key(peer_pub_key).unwrap(); | ||
let key: PKey<_> = self.priv_key.try_into().unwrap(); | ||
let mut deriver = Deriver::new(&key).unwrap(); | ||
deriver.set_peer(&peer_key).unwrap(); | ||
let secret = deriver.derive_to_vec().unwrap(); | ||
Ok(SharedSecret::from(secret.as_slice())) | ||
} | ||
|
||
fn pub_key(&self) -> &[u8] { | ||
&self.pub_key | ||
} | ||
|
||
fn group(&self) -> NamedGroup { | ||
self.name | ||
} | ||
} | ||
|
||
#[cfg(feature = "x25519")] | ||
impl SupportedKxGroup for X25519KxGroup { | ||
fn start(&self) -> Result<Box<dyn ActiveKeyExchange>, Error> { | ||
let private_key = PKey::generate_x25519().unwrap(); | ||
let public_key = private_key.raw_public_key().unwrap(); | ||
Ok(Box::new(X25519KeyExchange { | ||
private_key, | ||
public_key, | ||
})) | ||
} | ||
|
||
fn name(&self) -> NamedGroup { | ||
NamedGroup::X25519 | ||
} | ||
} | ||
|
||
#[cfg(feature = "x25519")] | ||
impl ActiveKeyExchange for X25519KeyExchange { | ||
fn complete(self: Box<Self>, peer_pub_key: &[u8]) -> Result<SharedSecret, Error> { | ||
let peer_public_key = PKey::public_key_from_raw_bytes(peer_pub_key, Id::X25519).unwrap(); | ||
let mut deriver = Deriver::new(&self.private_key).unwrap(); | ||
deriver.set_peer(&peer_public_key).unwrap(); | ||
let secret = deriver.derive_to_vec().unwrap(); | ||
Ok(SharedSecret::from(secret.as_slice())) | ||
} | ||
|
||
fn pub_key(&self) -> &[u8] { | ||
&self.public_key | ||
} | ||
|
||
fn group(&self) -> NamedGroup { | ||
NamedGroup::X25519 | ||
} | ||
} |
Oops, something went wrong.