diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..65861fc08 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,7 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" + open-pull-requests-limit: 1024 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ab80ae61e..588296d49 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: name: rustfmt runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: sfackler/actions/rustup@master - uses: sfackler/actions/rustfmt@master @@ -32,23 +32,23 @@ jobs: name: clippy runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: sfackler/actions/rustup@master - run: echo "version=$(rustc --version)" >> $GITHUB_OUTPUT id: rust-version - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: ~/.cargo/registry/index key: index-${{ runner.os }}-${{ github.run_number }} restore-keys: | index-${{ runner.os }}- - run: cargo generate-lockfile - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: ~/.cargo/registry/cache key: registry-${{ runner.os }}-${{ steps.rust-version.outputs.version }}-${{ hashFiles('Cargo.lock') }} - run: cargo fetch - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: target key: target-${{ github.job }}-${{ steps.rust-version.outputs.version }}-${{ hashFiles('Cargo.lock') }} @@ -58,26 +58,26 @@ jobs: name: min-version runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 # Remember to also update `--rust-target` in `openssl-sys/build/run_bindgen.rs` - uses: sfackler/actions/rustup@master with: version: 1.56.0 - run: echo "version=$(rustc --version)" >> $GITHUB_OUTPUT id: rust-version - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: ~/.cargo/registry/index key: index-${{ runner.os }}-${{ github.run_number }} restore-keys: | index-${{ runner.os }}- - run: cargo generate-lockfile - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: ~/.cargo/registry/cache key: registry-${{ runner.os }}-${{ steps.rust-version.outputs.version }}-${{ hashFiles('Cargo.lock') }} - run: cargo fetch - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: target key: target-${{ github.job }}-${{ steps.rust-version.outputs.version }}-${{ hashFiles('Cargo.lock') }} @@ -87,25 +87,25 @@ jobs: name: windows-vcpkg runs-on: windows-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: sfackler/actions/rustup@master - run: echo "version=$(rustc --version)" >> $GITHUB_OUTPUT id: rust-version - run: echo "VCPKG_ROOT=$env:VCPKG_INSTALLATION_ROOT" | Out-File -FilePath $env:GITHUB_ENV -Append - run: vcpkg install openssl:x64-windows-static-md - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: ~/.cargo/registry/index key: index-${{ runner.os }}-${{ github.run_number }} restore-keys: | index-${{ runner.os }}- - run: cargo generate-lockfile - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: ~/.cargo/registry/cache key: registry-${{ runner.os }}-${{ steps.rust-version.outputs.version }}-${{ hashFiles('Cargo.lock') }} - run: cargo fetch - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: target key: target-${{ github.job }}-${{ steps.rust-version.outputs.version }}-${{ hashFiles('Cargo.lock') }} @@ -117,26 +117,22 @@ jobs: name: macos-homebrew runs-on: macos-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: sfackler/actions/rustup@master - run: echo "version=$(rustc --version)" >> $GITHUB_OUTPUT id: rust-version - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: ~/.cargo/registry/index key: index-${{ runner.os }}-${{ github.run_number }} restore-keys: | index-${{ runner.os }}- - run: cargo generate-lockfile - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: ~/.cargo/registry/cache key: registry-${{ runner.os }}-${{ steps.rust-version.outputs.version }}-${{ hashFiles('Cargo.lock') }} - run: cargo fetch - # - uses: actions/cache@v3 - # with: - # path: target - # key: target-${{ github.job }}-${{ steps.rust-version.outputs.version }}-${{ hashFiles('Cargo.lock') }} - run: cargo run -p systest - run: cargo test -p openssl - run: cargo test -p openssl-errors @@ -211,7 +207,7 @@ jobs: CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_AR: arm-linux-gnueabihf-ar CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_RUNNER: qemu-arm -L /usr/arm-linux-gnueabihf steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: sfackler/actions/rustup@master - run: echo "version=$(rustc --version)" >> $GITHUB_OUTPUT id: rust-version @@ -233,7 +229,7 @@ jobs: sudo apt-get update sudo apt-get install -y $packages - run: sudo apt-get remove -y libssl-dev - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: /opt/openssl key: openssl-${{ matrix.target }}-${{ matrix.library.name }}-${{ matrix.library.version }}-6 @@ -320,19 +316,19 @@ jobs: echo '[patch.crates-io]' > .cargo/config.toml echo 'bssl-sys = { path = "'$OPENSSL_DIR'/rust/bssl-sys" }' >> .cargo/config.toml if: matrix.library.name == 'boringssl' && !matrix.bindgen - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: ~/.cargo/registry/index key: index-${{ runner.os }}-${{ github.run_number }} restore-keys: | index-${{ runner.os }}- - run: cargo generate-lockfile - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: ~/.cargo/registry/cache key: registry-${{ runner.os }}-${{ steps.rust-version.outputs.version }}-${{ hashFiles('Cargo.lock') }} - run: cargo fetch - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: target key: target-${{ matrix.target }}-${{ matrix.bindgen }}-${{ matrix.library.name }}-${{ matrix.library.version }}-${{ steps.rust-version.outputs.version }}-${{ hashFiles('Cargo.lock') }} diff --git a/openssl-sys/CHANGELOG.md b/openssl-sys/CHANGELOG.md index ba024b68e..0dcc2e561 100644 --- a/openssl-sys/CHANGELOG.md +++ b/openssl-sys/CHANGELOG.md @@ -2,6 +2,15 @@ ## [Unreleased] +## [v0.9.100] - 2024-02-19 + +### Added + +* Added `OSSL_PARAM`, `OSSL_PARAM_construct_uint` , `OSSL_PARAM_construct_end`. +* Added `EVP_PKEY_CTX_set_params` and `EVP_PKEY_CTX_get_params`. +* Added `X509_alias_get0`. +* Added `EVP_default_properties_enable_fips`. + ## [v0.9.99] - 2024-01-19 ### Added @@ -578,7 +587,8 @@ Fixed builds against OpenSSL built with `no-cast`. * Added `X509_verify` and `X509_REQ_verify`. * Added `EVP_MD_type` and `EVP_GROUP_get_curve_name`. -[Unreleased]: https://github.com/sfackler/rust-openssl/compare/openssl-sys-v0.9.99..master +[Unreleased]: https://github.com/sfackler/rust-openssl/compare/openssl-sys-v0.9.100..master +[v0.9.100]: https://github.com/sfackler/rust-openssl/compare/openssl-sys-v0.9.99...openssl-sys-v0.9.100 [v0.9.99]: https://github.com/sfackler/rust-openssl/compare/openssl-sys-v0.9.98...openssl-sys-v0.9.99 [v0.9.98]: https://github.com/sfackler/rust-openssl/compare/openssl-sys-v0.9.97...openssl-sys-v0.9.98 [v0.9.97]: https://github.com/sfackler/rust-openssl/compare/openssl-sys-v0.9.96...openssl-sys-v0.9.97 diff --git a/openssl-sys/Cargo.toml b/openssl-sys/Cargo.toml index 11dc7f346..02513d1ad 100644 --- a/openssl-sys/Cargo.toml +++ b/openssl-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "openssl-sys" -version = "0.9.99" +version = "0.9.100" authors = [ "Alex Crichton ", "Steven Fackler ", diff --git a/openssl-sys/build/main.rs b/openssl-sys/build/main.rs index 692ff7250..0ab823cdb 100644 --- a/openssl-sys/build/main.rs +++ b/openssl-sys/build/main.rs @@ -9,7 +9,7 @@ extern crate vcpkg; use std::collections::HashSet; use std::env; use std::ffi::OsString; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; mod cfgs; mod find_normal; @@ -79,11 +79,14 @@ fn main() { let target = env::var("TARGET").unwrap(); let (lib_dirs, include_dir) = find_openssl(&target); + if let Some(printable_include) = include_dir.join("openssl").to_str() { + println!("cargo:rerun-if-changed={}", printable_include); + } - if !lib_dirs.iter().all(|p| Path::new(p).exists()) { + if !lib_dirs.iter().all(|p| p.exists()) { panic!("OpenSSL library directory does not exist: {:?}", lib_dirs); } - if !Path::new(&include_dir).exists() { + if !include_dir.exists() { panic!( "OpenSSL include directory does not exist: {}", include_dir.to_string_lossy() diff --git a/openssl-sys/src/crypto.rs b/openssl-sys/src/crypto.rs index bdc0add15..7eff6a847 100644 --- a/openssl-sys/src/crypto.rs +++ b/openssl-sys/src/crypto.rs @@ -57,7 +57,7 @@ pub type CRYPTO_EX_free = unsafe extern "C" fn( argp: *mut c_void, ); -#[cfg(ossl110)] +#[cfg(any(ossl110, libressl390))] #[inline] #[track_caller] pub unsafe fn OPENSSL_malloc(num: usize) -> *mut c_void { @@ -68,7 +68,7 @@ pub unsafe fn OPENSSL_malloc(num: usize) -> *mut c_void { ) } -#[cfg(not(ossl110))] +#[cfg(not(any(ossl110, libressl390)))] #[inline] #[track_caller] pub unsafe fn OPENSSL_malloc(num: c_int) -> *mut c_void { @@ -79,7 +79,7 @@ pub unsafe fn OPENSSL_malloc(num: c_int) -> *mut c_void { ) } -#[cfg(ossl110)] +#[cfg(any(ossl110, libressl390))] #[inline] #[track_caller] pub unsafe fn OPENSSL_free(addr: *mut c_void) { @@ -90,7 +90,7 @@ pub unsafe fn OPENSSL_free(addr: *mut c_void) { ) } -#[cfg(not(ossl110))] +#[cfg(not(any(ossl110, libressl390)))] #[inline] pub unsafe fn OPENSSL_free(addr: *mut c_void) { CRYPTO_free(addr) diff --git a/openssl-sys/src/handwritten/crypto.rs b/openssl-sys/src/handwritten/crypto.rs index 62ccbce1e..0b3f24a42 100644 --- a/openssl-sys/src/handwritten/crypto.rs +++ b/openssl-sys/src/handwritten/crypto.rs @@ -57,7 +57,7 @@ extern "C" { } cfg_if! { - if #[cfg(ossl110)] { + if #[cfg(any(ossl110, libressl390))] { extern "C" { pub fn CRYPTO_malloc(num: size_t, file: *const c_char, line: c_int) -> *mut c_void; pub fn CRYPTO_free(buf: *mut c_void, file: *const c_char, line: c_int); diff --git a/openssl-sys/src/handwritten/evp.rs b/openssl-sys/src/handwritten/evp.rs index fabb13383..e9a7413c2 100644 --- a/openssl-sys/src/handwritten/evp.rs +++ b/openssl-sys/src/handwritten/evp.rs @@ -69,6 +69,7 @@ cfg_if! { if #[cfg(ossl300)] { extern "C" { pub fn EVP_default_properties_is_fips_enabled(libctx: *mut OSSL_LIB_CTX) -> c_int; + pub fn EVP_default_properties_enable_fips(libctx: *mut OSSL_LIB_CTX, enable: c_int) -> c_int; } } } @@ -538,6 +539,12 @@ extern "C" { #[cfg(ossl300)] pub fn EVP_PKEY_CTX_set_signature_md(ctx: *mut EVP_PKEY_CTX, md: *const EVP_MD) -> c_int; + #[cfg(ossl300)] + pub fn EVP_PKEY_CTX_set_params(ctx: *mut EVP_PKEY_CTX, params: *const OSSL_PARAM) -> c_int; + + #[cfg(ossl300)] + pub fn EVP_PKEY_CTX_get_params(ctx: *mut EVP_PKEY_CTX, params: *mut OSSL_PARAM) -> c_int; + pub fn EVP_PKEY_new_mac_key( type_: c_int, e: *mut ENGINE, diff --git a/openssl-sys/src/handwritten/mod.rs b/openssl-sys/src/handwritten/mod.rs index d3adfa5a1..f54ec9be5 100644 --- a/openssl-sys/src/handwritten/mod.rs +++ b/openssl-sys/src/handwritten/mod.rs @@ -15,6 +15,7 @@ pub use self::hmac::*; pub use self::kdf::*; pub use self::object::*; pub use self::ocsp::*; +pub use self::params::*; pub use self::pem::*; pub use self::pkcs12::*; pub use self::pkcs7::*; @@ -51,6 +52,7 @@ mod hmac; mod kdf; mod object; mod ocsp; +mod params; mod pem; mod pkcs12; mod pkcs7; diff --git a/openssl-sys/src/handwritten/params.rs b/openssl-sys/src/handwritten/params.rs new file mode 100644 index 000000000..3ed00c048 --- /dev/null +++ b/openssl-sys/src/handwritten/params.rs @@ -0,0 +1,9 @@ +use super::super::*; +use libc::*; + +extern "C" { + #[cfg(ossl300)] + pub fn OSSL_PARAM_construct_uint(key: *const c_char, buf: *mut c_uint) -> OSSL_PARAM; + #[cfg(ossl300)] + pub fn OSSL_PARAM_construct_end() -> OSSL_PARAM; +} diff --git a/openssl-sys/src/handwritten/stack.rs b/openssl-sys/src/handwritten/stack.rs index 7f2feef6d..7bc81359d 100644 --- a/openssl-sys/src/handwritten/stack.rs +++ b/openssl-sys/src/handwritten/stack.rs @@ -3,6 +3,8 @@ use libc::*; cfg_if! { if #[cfg(ossl110)] { pub enum OPENSSL_STACK {} + } else if #[cfg(libressl390)] { + pub enum _STACK {} } else { #[repr(C)] pub struct _STACK { diff --git a/openssl-sys/src/handwritten/types.rs b/openssl-sys/src/handwritten/types.rs index a03a87830..57c8113aa 100644 --- a/openssl-sys/src/handwritten/types.rs +++ b/openssl-sys/src/handwritten/types.rs @@ -1093,3 +1093,13 @@ pub enum OSSL_PROVIDER {} #[cfg(ossl300)] pub enum OSSL_LIB_CTX {} + +#[cfg(ossl300)] +#[repr(C)] +pub struct OSSL_PARAM { + key: *const c_char, + data_type: c_uchar, + data: *mut c_void, + data_size: size_t, + return_size: size_t, +} diff --git a/openssl-sys/src/handwritten/x509.rs b/openssl-sys/src/handwritten/x509.rs index 15f527e65..7642dcd3b 100644 --- a/openssl-sys/src/handwritten/x509.rs +++ b/openssl-sys/src/handwritten/x509.rs @@ -311,6 +311,7 @@ extern "C" { pub fn X509_get_version(x: *const X509) -> c_long; pub fn X509_set_serialNumber(x: *mut X509, sn: *mut ASN1_INTEGER) -> c_int; pub fn X509_get_serialNumber(x: *mut X509) -> *mut ASN1_INTEGER; + pub fn X509_alias_get0(x: *mut X509, len: *mut c_int) -> *mut c_uchar; } const_ptr_api! { extern "C" { diff --git a/openssl-sys/src/macros.rs b/openssl-sys/src/macros.rs index 96523db8f..e1c1427c6 100644 --- a/openssl-sys/src/macros.rs +++ b/openssl-sys/src/macros.rs @@ -58,7 +58,7 @@ macro_rules! cfg_if { macro_rules! stack { ($t:ident) => { cfg_if! { - if #[cfg(ossl110)] { + if #[cfg(any(ossl110, libressl390))] { pub enum $t {} } else { #[repr(C)] diff --git a/openssl/CHANGELOG.md b/openssl/CHANGELOG.md index 8b34e48ca..2f72808a8 100644 --- a/openssl/CHANGELOG.md +++ b/openssl/CHANGELOG.md @@ -2,6 +2,14 @@ ## [Unreleased] +## [v0.10.64] - 2024-02-19 + +### Added + +* Added `PkeyCtxRef::{nonce_type, set_nonce_type}`. +* Added `X509Ref::alias`. + + ## [v0.10.63] - 2024-01-19 ### Added @@ -884,7 +892,8 @@ Look at the [release tags] for information about older releases. -[Unreleased]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.63...master +[Unreleased]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.64...master +[v0.10.64]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.63...openssl-v0.10.64 [v0.10.63]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.62...openssl-v0.10.63 [v0.10.62]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.61...openssl-v0.10.62 [v0.10.61]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.60...openssl-v0.10.61 diff --git a/openssl/Cargo.toml b/openssl/Cargo.toml index 422142248..b85254916 100644 --- a/openssl/Cargo.toml +++ b/openssl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "openssl" -version = "0.10.63" +version = "0.10.64" authors = ["Steven Fackler "] license = "Apache-2.0" description = "OpenSSL bindings" @@ -30,7 +30,7 @@ libc = "0.2" once_cell = "1.5.2" openssl-macros = { version = "0.1.0", path = "../openssl-macros" } -ffi = { package = "openssl-sys", version = "0.9.99", path = "../openssl-sys" } +ffi = { package = "openssl-sys", version = "0.9.100", path = "../openssl-sys" } [dev-dependencies] hex = "0.3" diff --git a/openssl/src/pkcs12.rs b/openssl/src/pkcs12.rs index d74705eaa..5f171da9b 100644 --- a/openssl/src/pkcs12.rs +++ b/openssl/src/pkcs12.rs @@ -304,9 +304,20 @@ mod test { let parsed = pkcs12.parse2("mypass").unwrap(); assert_eq!( - hex::encode(parsed.cert.unwrap().digest(MessageDigest::sha1()).unwrap()), + hex::encode( + parsed + .cert + .as_ref() + .unwrap() + .digest(MessageDigest::sha1()) + .unwrap() + ), "59172d9313e84459bcff27f967e79e6e9217e584" ); + assert_eq!( + parsed.cert.as_ref().unwrap().alias(), + Some(b"foobar.com" as &[u8]) + ); let chain = parsed.ca.unwrap(); assert_eq!(chain.len(), 1); diff --git a/openssl/src/pkey_ctx.rs b/openssl/src/pkey_ctx.rs index 85778e216..add783048 100644 --- a/openssl/src/pkey_ctx.rs +++ b/openssl/src/pkey_ctx.rs @@ -75,8 +75,12 @@ use crate::{cvt, cvt_p}; use foreign_types::{ForeignType, ForeignTypeRef}; #[cfg(not(boringssl))] use libc::c_int; +#[cfg(ossl320)] +use libc::c_uint; use openssl_macros::corresponds; use std::convert::TryFrom; +#[cfg(ossl320)] +use std::ffi::CStr; use std::ptr; /// HKDF modes of operation. @@ -105,6 +109,21 @@ impl HkdfMode { pub const EXPAND_ONLY: Self = HkdfMode(ffi::EVP_PKEY_HKDEF_MODE_EXPAND_ONLY); } +/// Nonce type for ECDSA and DSA. +#[cfg(ossl320)] +#[derive(Debug, PartialEq)] +pub struct NonceType(c_uint); + +#[cfg(ossl320)] +impl NonceType { + /// This is the default mode. It uses a random value for the nonce k as defined in FIPS 186-4 Section 6.3 + /// “Secret Number Generation”. + pub const RANDOM_K: Self = NonceType(0); + + /// Uses a deterministic value for the nonce k as defined in RFC #6979 (See Section 3.2 “Generation of k”). + pub const DETERMINISTIC_K: Self = NonceType(1); +} + generic_foreign_type_and_impl_send_sync! { type CType = ffi::EVP_PKEY_CTX; fn drop = ffi::EVP_PKEY_CTX_free; @@ -714,6 +733,53 @@ impl PkeyCtxRef { Ok(PKey::from_ptr(key)) } } + + /// Sets the nonce type for a private key context. + /// + /// The nonce for DSA and ECDSA can be either random (the default) or deterministic (as defined by RFC 6979). + /// + /// This is only useful for DSA and ECDSA. + /// Requires OpenSSL 3.2.0 or newer. + #[cfg(ossl320)] + #[corresponds(EVP_PKEY_CTX_set_params)] + pub fn set_nonce_type(&mut self, nonce_type: NonceType) -> Result<(), ErrorStack> { + let nonce_field_name = CStr::from_bytes_with_nul(b"nonce-type\0").unwrap(); + let mut nonce_type = nonce_type.0; + unsafe { + let param_nonce = + ffi::OSSL_PARAM_construct_uint(nonce_field_name.as_ptr(), &mut nonce_type); + let param_end = ffi::OSSL_PARAM_construct_end(); + + let params = [param_nonce, param_end]; + cvt(ffi::EVP_PKEY_CTX_set_params(self.as_ptr(), params.as_ptr()))?; + } + Ok(()) + } + + /// Gets the nonce type for a private key context. + /// + /// The nonce for DSA and ECDSA can be either random (the default) or deterministic (as defined by RFC 6979). + /// + /// This is only useful for DSA and ECDSA. + /// Requires OpenSSL 3.2.0 or newer. + #[cfg(ossl320)] + #[corresponds(EVP_PKEY_CTX_get_params)] + pub fn nonce_type(&mut self) -> Result { + let nonce_field_name = CStr::from_bytes_with_nul(b"nonce-type\0").unwrap(); + let mut nonce_type: c_uint = 0; + unsafe { + let param_nonce = + ffi::OSSL_PARAM_construct_uint(nonce_field_name.as_ptr(), &mut nonce_type); + let param_end = ffi::OSSL_PARAM_construct_end(); + + let mut params = [param_nonce, param_end]; + cvt(ffi::EVP_PKEY_CTX_get_params( + self.as_ptr(), + params.as_mut_ptr(), + ))?; + } + Ok(NonceType(nonce_type)) + } } #[cfg(test)] @@ -999,4 +1065,46 @@ mod test { // The digest is the end of the DigestInfo structure. assert_eq!(result_buf[length - digest.len()..length], digest); } + + #[test] + #[cfg(ossl320)] + fn set_nonce_type() { + let key1 = + EcKey::generate(&EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap()).unwrap(); + let key1 = PKey::from_ec_key(key1).unwrap(); + + let mut ctx = PkeyCtx::new(&key1).unwrap(); + ctx.sign_init().unwrap(); + ctx.set_nonce_type(NonceType::DETERMINISTIC_K).unwrap(); + let nonce_type = ctx.nonce_type().unwrap(); + assert_eq!(nonce_type, NonceType::DETERMINISTIC_K); + assert!(ErrorStack::get().errors().is_empty()); + } + + // Test vector from + // https://github.com/openssl/openssl/blob/openssl-3.2.0/test/recipes/30-test_evp_data/evppkey_ecdsa_rfc6979.txt + #[test] + #[cfg(ossl320)] + fn ecdsa_deterministic_signature() { + let private_key_pem = "-----BEGIN PRIVATE KEY----- +MDkCAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQEEHzAdAgEBBBhvqwNJNOTA/Jrmf1tWWanX0f79GH7g +n9Q= +-----END PRIVATE KEY-----"; + + let key1 = EcKey::private_key_from_pem(private_key_pem.as_bytes()).unwrap(); + let key1 = PKey::from_ec_key(key1).unwrap(); + let input = "sample"; + let expected_output = hex::decode("303502190098C6BD12B23EAF5E2A2045132086BE3EB8EBD62ABF6698FF021857A22B07DEA9530F8DE9471B1DC6624472E8E2844BC25B64").unwrap(); + + let hashed_input = hash(MessageDigest::sha1(), input.as_bytes()).unwrap(); + let mut ctx = PkeyCtx::new(&key1).unwrap(); + ctx.sign_init().unwrap(); + ctx.set_signature_md(Md::sha1()).unwrap(); + ctx.set_nonce_type(NonceType::DETERMINISTIC_K).unwrap(); + + let mut output = vec![]; + ctx.sign_to_vec(&hashed_input, &mut output).unwrap(); + assert_eq!(output, expected_output); + assert!(ErrorStack::get().errors().is_empty()); + } } diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 30fd23665..2ff9dac1f 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -79,7 +79,7 @@ use crate::ssl::error::InnerError; use crate::stack::{Stack, StackRef, Stackable}; use crate::util::{ForeignTypeExt, ForeignTypeRefExt}; use crate::x509::store::{X509Store, X509StoreBuilderRef, X509StoreRef}; -#[cfg(any(ossl102, libressl261))] +#[cfg(any(ossl102, boringssl, libressl261))] use crate::x509::verify::X509VerifyParamRef; use crate::x509::{X509Name, X509Ref, X509StoreContextRef, X509VerifyResult, X509}; use crate::{cvt, cvt_n, cvt_p, init}; @@ -1307,18 +1307,18 @@ impl SslContextBuilder { /// Returns a reference to the X509 verification configuration. /// - /// Requires OpenSSL 1.0.2 or newer. + /// Requires BoringSSL or OpenSSL 1.0.2 or newer. #[corresponds(SSL_CTX_get0_param)] - #[cfg(any(ossl102, libressl261))] + #[cfg(any(ossl102, boringssl, libressl261))] pub fn verify_param(&self) -> &X509VerifyParamRef { unsafe { X509VerifyParamRef::from_ptr(ffi::SSL_CTX_get0_param(self.as_ptr())) } } /// Returns a mutable reference to the X509 verification configuration. /// - /// Requires OpenSSL 1.0.2 or newer. + /// Requires BoringSSL or OpenSSL 1.0.2 or newer. #[corresponds(SSL_CTX_get0_param)] - #[cfg(any(ossl102, libressl261))] + #[cfg(any(ossl102, boringssl, libressl261))] pub fn verify_param_mut(&mut self) -> &mut X509VerifyParamRef { unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_CTX_get0_param(self.as_ptr())) } } @@ -1719,9 +1719,9 @@ impl SslContextBuilder { /// Sets the context's supported elliptic curve groups. /// - /// Requires OpenSSL 1.1.1 or LibreSSL 2.5.1 or newer. + /// Requires BoringSSL or OpenSSL 1.1.1 or LibreSSL 2.5.1 or newer. #[corresponds(SSL_CTX_set1_groups_list)] - #[cfg(any(ossl111, libressl251))] + #[cfg(any(ossl111, boringssl, libressl251))] pub fn set_groups_list(&mut self, groups: &str) -> Result<(), ErrorStack> { let groups = CString::new(groups).unwrap(); unsafe { @@ -2769,9 +2769,9 @@ impl SslRef { /// Returns a mutable reference to the X509 verification configuration. /// - /// Requires OpenSSL 1.0.2 or newer. + /// Requires BoringSSL or OpenSSL 1.0.2 or newer. #[corresponds(SSL_get0_param)] - #[cfg(any(ossl102, libressl261))] + #[cfg(any(ossl102, boringssl, libressl261))] pub fn param_mut(&mut self) -> &mut X509VerifyParamRef { unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) } } diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index cf3e3c76f..a64524cbe 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -41,7 +41,7 @@ use crate::util::{ForeignTypeExt, ForeignTypeRefExt}; use crate::{cvt, cvt_n, cvt_p, cvt_p_const}; use openssl_macros::corresponds; -#[cfg(any(ossl102, libressl261))] +#[cfg(any(ossl102, boringssl, libressl261))] pub mod verify; pub mod extension; @@ -649,6 +649,24 @@ impl X509Ref { } } + /// Returns this certificate's "alias". This field is populated by + /// OpenSSL in some situations -- specifically OpenSSL will store a + /// PKCS#12 `friendlyName` in this field. This is not a part of the X.509 + /// certificate itself, OpenSSL merely attaches it to this structure in + /// memory. + #[corresponds(X509_alias_get0)] + pub fn alias(&self) -> Option<&[u8]> { + unsafe { + let mut len = 0; + let ptr = ffi::X509_alias_get0(self.as_ptr(), &mut len); + if ptr.is_null() { + None + } else { + Some(slice::from_raw_parts(ptr, len as usize)) + } + } + } + to_pem! { /// Serializes the certificate into a PEM-encoded X509 structure. /// @@ -2094,10 +2112,7 @@ impl GeneralName { } } - pub(crate) fn new_other_name( - oid: Asn1Object, - value: &Vec, - ) -> Result { + pub(crate) fn new_other_name(oid: Asn1Object, value: &[u8]) -> Result { unsafe { ffi::init(); diff --git a/openssl/src/x509/store.rs b/openssl/src/x509/store.rs index 944a2803e..3a173bea7 100644 --- a/openssl/src/x509/store.rs +++ b/openssl/src/x509/store.rs @@ -52,7 +52,7 @@ use crate::ssl::SslFiletype; use crate::stack::Stack; use crate::stack::StackRef; use crate::util::ForeignTypeRefExt; -#[cfg(any(ossl102, libressl261))] +#[cfg(any(ossl102, boringssl, libressl261))] use crate::x509::verify::{X509VerifyFlags, X509VerifyParamRef}; use crate::x509::{X509Object, X509PurposeId, X509}; use crate::{cvt, cvt_p}; @@ -123,7 +123,7 @@ impl X509StoreBuilderRef { /// Sets certificate chain validation related flags. #[corresponds(X509_STORE_set_flags)] - #[cfg(any(ossl102, libressl261))] + #[cfg(any(ossl102, boringssl, libressl261))] pub fn set_flags(&mut self, flags: X509VerifyFlags) -> Result<(), ErrorStack> { unsafe { cvt(ffi::X509_STORE_set_flags(self.as_ptr(), flags.bits())).map(|_| ()) } } @@ -137,7 +137,7 @@ impl X509StoreBuilderRef { /// Sets certificate chain validation related parameters. #[corresponds[X509_STORE_set1_param]] - #[cfg(any(ossl102, libressl261))] + #[cfg(any(ossl102, boringssl, libressl261))] pub fn set_param(&mut self, param: &X509VerifyParamRef) -> Result<(), ErrorStack> { unsafe { cvt(ffi::X509_STORE_set1_param(self.as_ptr(), param.as_ptr())).map(|_| ()) } } diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index 7d6611281..ae61a2ad3 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -16,11 +16,11 @@ use crate::x509::extension::{ #[cfg(not(boringssl))] use crate::x509::store::X509Lookup; use crate::x509::store::X509StoreBuilder; -#[cfg(any(ossl102, libressl261))] +#[cfg(any(ossl102, boringssl, libressl261))] use crate::x509::verify::{X509VerifyFlags, X509VerifyParam}; -#[cfg(ossl102)] +#[cfg(any(ossl102, boringssl))] use crate::x509::X509PurposeId; -#[cfg(any(ossl102, libressl261))] +#[cfg(any(ossl102, boringssl, libressl261))] use crate::x509::X509PurposeRef; #[cfg(ossl110)] use crate::x509::{CrlReason, X509Builder}; @@ -31,7 +31,7 @@ use crate::x509::{ #[cfg(ossl110)] use foreign_types::ForeignType; use hex::{self, FromHex}; -#[cfg(any(ossl102, libressl261))] +#[cfg(any(ossl102, boringssl, libressl261))] use libc::time_t; use super::{AuthorityInformationAccess, CertificateIssuer, ReasonCode}; @@ -557,7 +557,7 @@ fn test_verify_fails() { } #[test] -#[cfg(any(ossl102, libressl261))] +#[cfg(any(ossl102, boringssl, libressl261))] fn test_verify_fails_with_crl_flag_set_and_no_crl() { let cert = include_bytes!("../../test/cert.pem"); let cert = X509::from_pem(cert).unwrap(); @@ -584,7 +584,7 @@ fn test_verify_fails_with_crl_flag_set_and_no_crl() { } #[test] -#[cfg(any(ossl102, libressl261))] +#[cfg(any(ossl102, boringssl, libressl261))] fn test_verify_cert_with_purpose() { let cert = include_bytes!("../../test/cert.pem"); let cert = X509::from_pem(cert).unwrap(); @@ -611,7 +611,7 @@ fn test_verify_cert_with_purpose() { } #[test] -#[cfg(any(ossl102, libressl261))] +#[cfg(any(ossl102, boringssl, libressl261))] fn test_verify_cert_with_wrong_purpose_fails() { let cert = include_bytes!("../../test/cert.pem"); let cert = X509::from_pem(cert).unwrap(); @@ -846,7 +846,7 @@ fn test_name_to_owned() { } #[test] -#[cfg(any(ossl102, libressl261))] +#[cfg(any(ossl102, boringssl, libressl261))] fn test_verify_param_set_time_fails_verification() { const TEST_T_2030: time_t = 1893456000; @@ -877,7 +877,7 @@ fn test_verify_param_set_time_fails_verification() { } #[test] -#[cfg(any(ossl102, libressl261))] +#[cfg(any(ossl102, boringssl, libressl261))] fn test_verify_param_set_time() { const TEST_T_2020: time_t = 1577836800; @@ -901,7 +901,7 @@ fn test_verify_param_set_time() { } #[test] -#[cfg(any(ossl102, libressl261))] +#[cfg(any(ossl102, boringssl, libressl261))] fn test_verify_param_set_depth() { let cert = include_bytes!("../../test/leaf.pem"); let cert = X509::from_pem(cert).unwrap(); @@ -928,7 +928,7 @@ fn test_verify_param_set_depth() { } #[test] -#[cfg(any(ossl102, libressl261))] +#[cfg(any(ossl102, boringssl, libressl261))] #[allow(clippy::bool_to_int_with_if)] fn test_verify_param_set_depth_fails_verification() { let cert = include_bytes!("../../test/leaf.pem"); @@ -1003,7 +1003,7 @@ fn test_verify_param_auth_level() { } #[test] -#[cfg(ossl102)] +#[cfg(any(ossl102, boringssl))] fn test_set_purpose() { let cert = include_bytes!("../../test/leaf.pem"); let cert = X509::from_pem(cert).unwrap(); @@ -1028,7 +1028,7 @@ fn test_set_purpose() { } #[test] -#[cfg(ossl102)] +#[cfg(any(ossl102, boringssl))] fn test_set_purpose_fails_verification() { let cert = include_bytes!("../../test/leaf.pem"); let cert = X509::from_pem(cert).unwrap(); diff --git a/openssl/src/x509/verify.rs b/openssl/src/x509/verify.rs index 541cd8266..2cde93f28 100644 --- a/openssl/src/x509/verify.rs +++ b/openssl/src/x509/verify.rs @@ -4,7 +4,7 @@ use libc::{c_int, c_uint, c_ulong, time_t}; use std::net::IpAddr; use crate::error::ErrorStack; -#[cfg(ossl102)] +#[cfg(any(ossl102, boringssl))] use crate::x509::X509PurposeId; use crate::{cvt, cvt_p}; use openssl_macros::corresponds; @@ -14,17 +14,17 @@ bitflags! { #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] #[repr(transparent)] pub struct X509CheckFlags: c_uint { - const ALWAYS_CHECK_SUBJECT = ffi::X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT; - const NO_WILDCARDS = ffi::X509_CHECK_FLAG_NO_WILDCARDS; - const NO_PARTIAL_WILDCARDS = ffi::X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS; - const MULTI_LABEL_WILDCARDS = ffi::X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS; - const SINGLE_LABEL_SUBDOMAINS = ffi::X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS; + const ALWAYS_CHECK_SUBJECT = ffi::X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT as _; + const NO_WILDCARDS = ffi::X509_CHECK_FLAG_NO_WILDCARDS as _; + const NO_PARTIAL_WILDCARDS = ffi::X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS as _; + const MULTI_LABEL_WILDCARDS = ffi::X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS as _; + const SINGLE_LABEL_SUBDOMAINS = ffi::X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS as _; /// Requires OpenSSL 1.1.0 or newer. #[cfg(any(ossl110))] const NEVER_CHECK_SUBJECT = ffi::X509_CHECK_FLAG_NEVER_CHECK_SUBJECT; #[deprecated(since = "0.10.6", note = "renamed to NO_WILDCARDS")] - const FLAG_NO_WILDCARDS = ffi::X509_CHECK_FLAG_NO_WILDCARDS; + const FLAG_NO_WILDCARDS = ffi::X509_CHECK_FLAG_NO_WILDCARDS as _; } } @@ -33,35 +33,35 @@ bitflags! { #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] #[repr(transparent)] pub struct X509VerifyFlags: c_ulong { - const CB_ISSUER_CHECK = ffi::X509_V_FLAG_CB_ISSUER_CHECK; - const USE_CHECK_TIME = ffi::X509_V_FLAG_USE_CHECK_TIME; - const CRL_CHECK = ffi::X509_V_FLAG_CRL_CHECK; - const CRL_CHECK_ALL = ffi::X509_V_FLAG_CRL_CHECK_ALL; - const IGNORE_CRITICAL = ffi::X509_V_FLAG_IGNORE_CRITICAL; - const X509_STRICT = ffi::X509_V_FLAG_X509_STRICT; - const ALLOW_PROXY_CERTS = ffi::X509_V_FLAG_ALLOW_PROXY_CERTS; - const POLICY_CHECK = ffi::X509_V_FLAG_POLICY_CHECK; - const EXPLICIT_POLICY = ffi::X509_V_FLAG_EXPLICIT_POLICY; - const INHIBIT_ANY = ffi::X509_V_FLAG_INHIBIT_ANY; - const INHIBIT_MAP = ffi::X509_V_FLAG_INHIBIT_MAP; - const NOTIFY_POLICY = ffi::X509_V_FLAG_NOTIFY_POLICY; - const EXTENDED_CRL_SUPPORT = ffi::X509_V_FLAG_EXTENDED_CRL_SUPPORT; - const USE_DELTAS = ffi::X509_V_FLAG_USE_DELTAS; - const CHECK_SS_SIGNATURE = ffi::X509_V_FLAG_CHECK_SS_SIGNATURE; - #[cfg(ossl102)] - const TRUSTED_FIRST = ffi::X509_V_FLAG_TRUSTED_FIRST; + const CB_ISSUER_CHECK = ffi::X509_V_FLAG_CB_ISSUER_CHECK as _; + const USE_CHECK_TIME = ffi::X509_V_FLAG_USE_CHECK_TIME as _; + const CRL_CHECK = ffi::X509_V_FLAG_CRL_CHECK as _; + const CRL_CHECK_ALL = ffi::X509_V_FLAG_CRL_CHECK_ALL as _; + const IGNORE_CRITICAL = ffi::X509_V_FLAG_IGNORE_CRITICAL as _; + const X509_STRICT = ffi::X509_V_FLAG_X509_STRICT as _; + const ALLOW_PROXY_CERTS = ffi::X509_V_FLAG_ALLOW_PROXY_CERTS as _; + const POLICY_CHECK = ffi::X509_V_FLAG_POLICY_CHECK as _; + const EXPLICIT_POLICY = ffi::X509_V_FLAG_EXPLICIT_POLICY as _; + const INHIBIT_ANY = ffi::X509_V_FLAG_INHIBIT_ANY as _; + const INHIBIT_MAP = ffi::X509_V_FLAG_INHIBIT_MAP as _; + const NOTIFY_POLICY = ffi::X509_V_FLAG_NOTIFY_POLICY as _; + const EXTENDED_CRL_SUPPORT = ffi::X509_V_FLAG_EXTENDED_CRL_SUPPORT as _; + const USE_DELTAS = ffi::X509_V_FLAG_USE_DELTAS as _; + const CHECK_SS_SIGNATURE = ffi::X509_V_FLAG_CHECK_SS_SIGNATURE as _; + #[cfg(any(ossl102, boringssl))] + const TRUSTED_FIRST = ffi::X509_V_FLAG_TRUSTED_FIRST as _; #[cfg(ossl102)] const SUITEB_128_LOS_ONLY = ffi::X509_V_FLAG_SUITEB_128_LOS_ONLY; #[cfg(ossl102)] const SUITEB_192_LOS = ffi::X509_V_FLAG_SUITEB_128_LOS; #[cfg(ossl102)] const SUITEB_128_LOS = ffi::X509_V_FLAG_SUITEB_192_LOS; - #[cfg(ossl102)] - const PARTIAL_CHAIN = ffi::X509_V_FLAG_PARTIAL_CHAIN; - #[cfg(ossl110)] - const NO_ALT_CHAINS = ffi::X509_V_FLAG_NO_ALT_CHAINS; - #[cfg(ossl110)] - const NO_CHECK_TIME = ffi::X509_V_FLAG_NO_CHECK_TIME; + #[cfg(any(ossl102, boringssl))] + const PARTIAL_CHAIN = ffi::X509_V_FLAG_PARTIAL_CHAIN as _; + #[cfg(any(ossl110, boringssl))] + const NO_ALT_CHAINS = ffi::X509_V_FLAG_NO_ALT_CHAINS as _; + #[cfg(any(ossl110, boringssl))] + const NO_CHECK_TIME = ffi::X509_V_FLAG_NO_CHECK_TIME as _; } } @@ -208,7 +208,7 @@ impl X509VerifyParamRef { /// Sets the verification purpose #[corresponds(X509_VERIFY_PARAM_set_purpose)] - #[cfg(ossl102)] + #[cfg(any(ossl102, boringssl))] pub fn set_purpose(&mut self, purpose: X509PurposeId) -> Result<(), ErrorStack> { unsafe { cvt(ffi::X509_VERIFY_PARAM_set_purpose(self.as_ptr(), purpose.0)).map(|_| ()) } }