mirror of
https://github.com/zerotier/crypto-glue.git
synced 2026-05-22 16:28:47 -07:00
Added support for OpenSSL<1.1.0
This commit is contained in:
@@ -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 }
|
||||
|
||||
@@ -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
@@ -52,7 +52,7 @@ macro_rules! impl_zssp_crypto {
|
||||
type SessionData = $session_data;
|
||||
type IncomingPacketBuffer = $packet_buffer;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
use ctor::ctor;
|
||||
|
||||
+44
-17
@@ -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
@@ -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()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user