diff --git a/openssl-sys/src/ec.rs b/openssl-sys/src/ec.rs index 22b7218a3d5669a655775e61455d49d970e957da..d7427918613f4a39a0abf330d69ae0eeaa28444b 100644 --- a/openssl-sys/src/ec.rs +++ b/openssl-sys/src/ec.rs @@ -1,4 +1,5 @@ use libc::*; +use std::ptr; use *; @@ -241,3 +242,13 @@ extern "C" { pub fn i2d_ECDSA_SIG(sig: *const ECDSA_SIG, out: *mut *mut c_uchar) -> c_int; } + +#[cfg(ossl300)] +pub unsafe fn EVP_EC_gen(curve: *const c_char) -> *mut EVP_PKEY { + EVP_PKEY_Q_keygen( + ptr::null_mut(), + ptr::null_mut(), + "EC\0".as_ptr().cast(), + curve, + ) +} diff --git a/openssl-sys/src/evp.rs b/openssl-sys/src/evp.rs index e5c2595d262c21b13da63ac9c40fb0e1379e8554..80146c316ba874eaa48b8095f84fd34e19ff5132 100644 --- a/openssl-sys/src/evp.rs +++ b/openssl-sys/src/evp.rs @@ -525,6 +525,13 @@ extern "C" { pub fn EVP_PKEY_derive_set_peer(ctx: *mut EVP_PKEY_CTX, peer: *mut EVP_PKEY) -> c_int; pub fn EVP_PKEY_derive(ctx: *mut EVP_PKEY_CTX, key: *mut c_uchar, size: *mut size_t) -> c_int; + #[cfg(ossl300)] + pub fn EVP_PKEY_Q_keygen( + libctx: *mut OSSL_LIB_CTX, + propq: *const c_char, + type_: *const c_char, + ... + ) -> *mut EVP_PKEY; pub fn EVP_PKEY_keygen_init(ctx: *mut EVP_PKEY_CTX) -> c_int; pub fn EVP_PKEY_keygen(ctx: *mut EVP_PKEY_CTX, key: *mut *mut EVP_PKEY) -> c_int; diff --git a/openssl/src/pkey.rs b/openssl/src/pkey.rs index 9d55e617c56a297b38ab1ac0132d63a17ccd1a53..2dbb6022ae8030a9109aa4e898cf7b3f0c61915d 100644 --- a/openssl/src/pkey.rs +++ b/openssl/src/pkey.rs @@ -602,6 +602,22 @@ impl PKey { PKey::generate_eddsa(ffi::EVP_PKEY_ED448) } + /// Generates a new EC key using the provided curve. + /// + /// This corresponds to [`EVP_EC_gen`]. + /// + /// Requires OpenSSL 3.0.0 or newer. + /// + /// [`EVP_EC_gen`]: https://www.openssl.org/docs/manmaster/man3/EVP_EC_gen.html + #[cfg(ossl300)] + pub fn ec_gen(curve: &str) -> Result, ErrorStack> { + let curve = CString::new(curve).unwrap(); + unsafe { + let ptr = cvt_p(ffi::EVP_EC_gen(curve.as_ptr()))?; + Ok(PKey::from_ptr(ptr)) + } + } + private_key_from_pem! { /// Deserializes a private key from a PEM-encoded key type specific format. /// @@ -1128,4 +1144,11 @@ mod tests { assert!(pkey.raw_private_key().is_err()); assert!(pkey.raw_public_key().is_err()); } + + #[cfg(ossl300)] + #[test] + fn test_ec_gen() { + let key = PKey::ec_gen("prime256v1").unwrap(); + assert!(key.ec_key().is_ok()); + } }