Added support for OpenSSL<1.1.0

This commit is contained in:
Monica Moniot
2023-10-05 17:55:37 -04:00
parent 95899db0b1
commit 33d9460b4d
5 changed files with 65 additions and 25 deletions
+2
View File
@@ -7,10 +7,12 @@ readme = "README.md"
categories = ["cryptography", "api-bindings"]
edition = "2021"
version = "0.2.0"
build = "build.rs"
[features]
[dependencies]
openssl-sys = "0.9.91"
x25519-dalek = { version = "2.0.0", features = ["static_secrets"], default-features = false }
ed25519-dalek = { version = "2.0.0", features = ["digest", "rand_core"], default-features = false }
poly1305 = { version = "0.8.0", features = [], default-features = false }
+11
View File
@@ -0,0 +1,11 @@
use std::env;
fn main() {
if let Ok(v) = env::var("DEP_OPENSSL_VERSION_NUMBER") {
let version = u64::from_str_radix(&v, 16).unwrap();
if version < 0x1_01_00_00_0 {
println!("cargo:rustc-cfg=no_get0set0");
}
}
}
+1 -1
View File
@@ -52,7 +52,7 @@ macro_rules! impl_zssp_crypto {
type SessionData = $session_data;
type IncomingPacketBuffer = $packet_buffer;
}
}
};
}
use ctor::ctor;
+44 -17
View File
@@ -128,21 +128,32 @@ impl P384PublicKey {
if let (Ok(r), Ok(s)) = (r, s) {
// Create the OpenSSL object that actually supports verification.
if let Ok(sig) = check_ptr(ffi::ECDSA_SIG_new()) {
let is_valid = if ffi::ECDSA_SIG_set0(sig, r.0, s.0) == 1 {
// For some reason this one random function, `ECDSA_SIG_set0`, takes
// ownership of its parameters. I've double checked and it is the only one
// we call that does that. We `forget` the memory so we don't double free.
mem::forget(r);
mem::forget(s);
// Digest the message.
let digest = create_digest(domain, data);
cfg_if::cfg_if! {
if #[cfg(no_get0set0)] {
let sig_deref = sig.as_mut().unwrap();
if !sig_deref.r.is_null() {
ffi::BN_free(sig_deref.r);
}
if !sig_deref.s.is_null() {
ffi::BN_free(sig_deref.s);
}
sig_deref.r = r.0;
sig_deref.s = s.0;
} else {
assert!(ffi::ECDSA_SIG_set0(sig, r.0, s.0) == 1);
}
}
// For some reason this one random function, `ECDSA_SIG_set0`, takes
// ownership of its parameters. I've double checked and it is the only one
// we call that does that. We `forget` the memory so we don't double free.
mem::forget(r);
mem::forget(s);
// Digest the message.
let digest = create_digest(domain, data);
let key = self.key.lock().unwrap();
// Actually perform the verification.
ffi::ECDSA_do_verify(digest.as_ptr(), digest.len() as c_int, sig, key.0) == 1
} else {
false
};
let key = self.key.lock().unwrap();
// Actually perform the verification.
let is_valid = ffi::ECDSA_do_verify(digest.as_ptr(), digest.len() as c_int, sig, key.0) == 1;
// Guarantee signature free.
ffi::ECDSA_SIG_free(sig);
return is_valid;
@@ -209,7 +220,10 @@ impl P384KeyPair {
/// Create a p384 keypair from raw bytes.
/// `public_bytes` should have length `P384_PUBLIC_KEY_SIZE` and `secret_bytes` should have length
/// `P384_SECRET_KEY_SIZE`.
pub fn from_bytes(public_bytes: &[u8; P384_PUBLIC_KEY_SIZE], secret_bytes: &[u8; P384_SECRET_KEY_SIZE]) -> Option<P384KeyPair> {
pub fn from_bytes(
public_bytes: &[u8; P384_PUBLIC_KEY_SIZE],
secret_bytes: &[u8; P384_SECRET_KEY_SIZE],
) -> Option<P384KeyPair> {
unsafe {
// Write the raw bytes into OpenSSL.
let pair = OSSLKey::pub_from_slice(public_bytes).ok()?;
@@ -285,6 +299,7 @@ impl P384KeyPair {
/// The signature will only be valid when verified with the same "domain".
/// Restricting signatures to domains reduces the risk of a valid signature being used for a
/// purpose the signer did not intend.
#[allow(unused_assignments)]
pub fn sign_all(&self, domain: &[u8], data: &[&[u8]]) -> [u8; P384_ECDSA_SIGNATURE_SIZE] {
let digest = create_digest(domain, data);
unsafe {
@@ -297,7 +312,16 @@ impl P384KeyPair {
// Get handles to the OpenSSL objects that actually support reading out into bytes.
let mut r = ptr::null();
let mut s = ptr::null();
ffi::ECDSA_SIG_get0(sig, &mut r, &mut s);
cfg_if::cfg_if! {
if #[cfg(no_get0set0)] {
let sig_deref = sig.as_ref().unwrap();
r = sig_deref.r;
s = sig_deref.s;
} else {
ffi::ECDSA_SIG_get0(sig, &mut r, &mut s);
}
}
if r.is_null() || s.is_null() {
ffi::ECDSA_SIG_free(sig);
assert!(false);
@@ -479,7 +503,10 @@ impl<Rng: RngCore + CryptoRng> zssp::crypto::P384KeyPair<Rng> for P384KeyPair {
#[cfg(test)]
mod tests {
use crate::{
p384::{P384KeyPair, P384_ECDH_SHARED_SECRET_SIZE, P384_PUBLIC_KEY_SIZE, P384_SECRET_KEY_SIZE, P384_ECDSA_SIGNATURE_SIZE},
p384::{
P384KeyPair, P384_ECDH_SHARED_SECRET_SIZE, P384_ECDSA_SIGNATURE_SIZE, P384_PUBLIC_KEY_SIZE,
P384_SECRET_KEY_SIZE,
},
secure_eq,
};
+7 -7
View File
@@ -13,7 +13,6 @@ use libc::c_int;
use once_cell::unsync::Lazy;
use zssp::crypto::rand_core::{CryptoRng, Error, RngCore, SeedableRng};
pub use zssp::crypto::rand_core;
/// This crate contains the most modern, feature rich and high-quality variants of the Xorshift family of random
/// number generators.
/// While they are not cryptographically secure, they are also faster and several times harder to
@@ -23,6 +22,7 @@ pub use rand_xoshiro;
/// Xoshiro256** according to my benchmarking is surprisingly twice as fast as vanilla
/// Xorshift64 because there are fewer dependency chains in Xoshiro256** compared to Xorshift64.
pub use rand_xoshiro::Xoshiro256StarStar;
pub use zssp::crypto::rand_core;
/// The cryptographically secure random number generator of OpenSSL.
#[derive(Default, Clone, Copy)]
@@ -113,31 +113,31 @@ impl RngCore for XorshiftRandom {
}
}
#[deprecated(since="0.2.0", note="please use `SecureRandom.next_u32()` instead")]
#[deprecated(since = "0.2.0", note = "please use `SecureRandom.next_u32()` instead")]
pub fn next_u32_secure() -> u32 {
SecureRandom.next_u32()
}
#[deprecated(since="0.2.0", note="please use `SecureRandom.next_u64()` instead")]
#[deprecated(since = "0.2.0", note = "please use `SecureRandom.next_u64()` instead")]
pub fn next_u64_secure() -> u64 {
SecureRandom.next_u64()
}
#[deprecated(since="0.2.0", note="please use `SecureRandom.next_u128()` instead")]
#[deprecated(since = "0.2.0", note = "please use `SecureRandom.next_u128()` instead")]
pub fn next_u128_secure() -> u128 {
SecureRandom.next_u128()
}
#[deprecated(since="0.2.0", note="please use `SecureRandom.fill_bytes(dest)` instead")]
#[deprecated(since = "0.2.0", note = "please use `SecureRandom.fill_bytes(dest)` instead")]
pub fn fill_bytes_secure(dest: &mut [u8]) {
SecureRandom.fill_bytes(dest)
}
#[deprecated(since="0.2.0", note="please use `SecureRandom.get_bytes()` instead")]
#[deprecated(since = "0.2.0", note = "please use `SecureRandom.get_bytes()` instead")]
pub fn get_bytes_secure<const COUNT: usize>() -> [u8; COUNT] {
SecureRandom.get_bytes()
}
#[deprecated(since="0.2.0", note="please use `XorshiftRandom.next_u64()` instead")]
#[deprecated(since = "0.2.0", note = "please use `XorshiftRandom.next_u64()` instead")]
pub fn xorshift64_random() -> u64 {
XorshiftRandom.next_u64()
}