mirror of
https://github.com/openharmony/third_party_rust_rust-openssl.git
synced 2026-07-19 05:30:08 -04:00
+1
-1
@@ -3,7 +3,7 @@
|
||||
"Name": "openssl",
|
||||
"License": "Apache License V2.0",
|
||||
"License File": "THIRD_PARTY",
|
||||
"Version Number": "0.10.48",
|
||||
"Version Number": "0.10.56",
|
||||
"Owner": "xuelei3@huawei.com",
|
||||
"Upstream URL": "https://github.com/sfackler/rust-openssl",
|
||||
"Description": "OpenSSL bindings."
|
||||
|
||||
@@ -3,7 +3,7 @@ name = "openssl-errors"
|
||||
version = "0.2.0"
|
||||
authors = ["Steven Fackler <sfackler@gmail.com>"]
|
||||
edition = "2018"
|
||||
license = "MIT/Apache-2.0"
|
||||
license = "MIT OR Apache-2.0"
|
||||
description = "Custom error library support for the openssl crate."
|
||||
repository = "https://github.com/sfackler/rust-openssl"
|
||||
readme = "README.md"
|
||||
|
||||
@@ -20,7 +20,7 @@ ohos_cargo_crate("lib") {
|
||||
|
||||
sources = [ "src/lib.rs" ]
|
||||
edition = "2018"
|
||||
cargo_pkg_version = "0.1.0"
|
||||
cargo_pkg_version = "0.1.1"
|
||||
cargo_pkg_name = "openssl-macros"
|
||||
cargo_pkg_description = "Internal macros used by the openssl crate."
|
||||
deps = [
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
[package]
|
||||
name = "openssl-macros"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
edition = "2018"
|
||||
license = "MIT/Apache-2.0"
|
||||
license = "MIT OR Apache-2.0"
|
||||
description = "Internal macros used by the openssl crate."
|
||||
|
||||
[lib]
|
||||
@@ -11,4 +11,4 @@ proc-macro = true
|
||||
[dependencies]
|
||||
proc-macro2 = "1"
|
||||
quote = "1"
|
||||
syn = { version = "1", features = ["full"] }
|
||||
syn = { version = "2", features = ["full"] }
|
||||
|
||||
@@ -20,7 +20,7 @@ ohos_cargo_crate("lib") {
|
||||
|
||||
sources = [ "src/lib.rs" ]
|
||||
edition = "2018"
|
||||
cargo_pkg_version = "0.9.82"
|
||||
cargo_pkg_version = "0.9.91"
|
||||
cargo_pkg_authors = "Alex Crichton <alex@alexcrichton.com>, Steven Fackler <sfackler@gmail.com>"
|
||||
cargo_pkg_name = "openssl-sys"
|
||||
cargo_pkg_description = "FFI bindings to OpenSSL"
|
||||
|
||||
@@ -2,6 +2,86 @@
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [v0.9.91] - 2023-08-06
|
||||
|
||||
### Added
|
||||
|
||||
* Expose `poly1305_state`, `CRYPTO_poly1305_init`, `CRYPTO_poly1305_update`, and `CRYPTO_poly1305_finish` on BoringSSL and LibreSSL.
|
||||
* Fix detection of libraries on OpenBSD.
|
||||
* Added `EC_POINT_point2hex` and `EC_POINT_hex2point`.
|
||||
* Added `EVP_PKEY_verify_recover_init`, `EVP_PKEY_verify_recover`, and `EVP_PKEY_CTX_set_signature_md`.
|
||||
* Added `EVP_CIPHER_CTX_FLAG_WRAP_ALLOW` and `EVP_CTX_set_flags`.
|
||||
* Added `BN_mod_sqrt`.
|
||||
|
||||
## [v0.9.90] - 2023-06-20
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fixed compilation with BoringSSL when building with the bindgen CLI.
|
||||
|
||||
## [v0.9.89] - 2023-06-20
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fixed compilation with recent versions of BoringSSL.
|
||||
|
||||
### Added
|
||||
|
||||
* Added support for detecting OpenSSL compiled with `OPENSSL_NO_OCB`.
|
||||
* Added `EVP_PKEY_SM2` and `NID_sm2`.
|
||||
* Added `EVP_PKEY_assign_RSA`, `EVP_PKEY_assign_DSA`, `EVP_PKEY_assign_DH`, and `EVP_PKEY_assign_EC_KEY`.
|
||||
* Added `EC_GROUP_get_asn1_flag`.
|
||||
* Expose `EC_POINT_get_affine_coordinates` on BoringSSL and LibreSSL.
|
||||
* Added `EVP_PKEY_derive_set_peer_ex`.
|
||||
|
||||
## [v0.9.88] - 2023-05-30
|
||||
|
||||
### Added
|
||||
|
||||
* Added support for the LibreSSL 3.8.0.
|
||||
* Added support for detecting `OPENSSL_NO_RC4`.
|
||||
* Added `OBJ_dup`.
|
||||
* Added `ASN1_TYPE_new`, `ASN1_TYPE_set`, `d2i_ASN1_TYPE`, and `i2d_ASN1_TYPE`.
|
||||
* Added `SSL_bytes_to_cipher_list`, `SSL_CTX_get_num_tickets`, and `SSL_get_num_tickets`.
|
||||
* Added `GENERAL_NAME_set0_othername`.
|
||||
* Added `X509_get_pathlen`.
|
||||
|
||||
## [v0.9.87] - 2023-04-24
|
||||
|
||||
### Added
|
||||
|
||||
* Added `DH_CHECK`.
|
||||
* Added `CMAC_CTX_new`, `CMAC_CTX_free`, `CMAC_Init`, `CMAC_Update`, `CMAC_Final`, and `CMAC_CTX_copy`.
|
||||
* Added `EVP_default_properties_is_fips_enabled`.
|
||||
* Added `X509_get0_subject_key_id`, `X509_get0_authority_key_id`, `X509_get0_authority_issuer`, and `X509_get0_authority_serial`.
|
||||
* Added `NID_poly1305`.
|
||||
|
||||
|
||||
## [v0.9.86] - 2023-04-20
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fixed BoringSSL support with the latest bindgen release.
|
||||
|
||||
### Added
|
||||
|
||||
* Added bindings for PKCS#7 functions and more X.509 functions.
|
||||
|
||||
|
||||
## [v0.9.85] - 2023-04-09
|
||||
|
||||
### Added
|
||||
|
||||
* Added support for LibreSSL 3.7.x.
|
||||
|
||||
## [v0.9.84] - 2023-04-01
|
||||
|
||||
### Added
|
||||
|
||||
* Added `ASN1_INTEGER_dup` and `ASN1_INTEGER_cmp`.
|
||||
* Added `stack_st_X509_NAME_ENTRY`.
|
||||
* Added `DIST_POINT_NAME`, `DIST_POINT`, `stack_st_DIST_POINT`, `DIST_POINT_free`, and `DIST_POINT_NAME_free`.
|
||||
|
||||
## [v0.9.83] - 2023-03-23
|
||||
|
||||
### Fixed
|
||||
@@ -410,7 +490,15 @@ 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.83..master
|
||||
[Unreleased]: https://github.com/sfackler/rust-openssl/compare/openssl-sys-v0.9.91..master
|
||||
[v0.9.91]: https://github.com/sfackler/rust-openssl/compare/openssl-sys-v0.9.90...openssl-sys-v0.9.91
|
||||
[v0.9.90]: https://github.com/sfackler/rust-openssl/compare/openssl-sys-v0.9.89...openssl-sys-v0.9.90
|
||||
[v0.9.89]: https://github.com/sfackler/rust-openssl/compare/openssl-sys-v0.9.88...openssl-sys-v0.9.89
|
||||
[v0.9.88]: https://github.com/sfackler/rust-openssl/compare/openssl-sys-v0.9.87...openssl-sys-v0.9.88
|
||||
[v0.9.87]: https://github.com/sfackler/rust-openssl/compare/openssl-sys-v0.9.86...openssl-sys-v0.9.87
|
||||
[v0.9.86]: https://github.com/sfackler/rust-openssl/compare/openssl-sys-v0.9.85...openssl-sys-v0.9.86
|
||||
[v0.9.85]: https://github.com/sfackler/rust-openssl/compare/openssl-sys-v0.9.84...openssl-sys-v0.9.85
|
||||
[v0.9.84]: https://github.com/sfackler/rust-openssl/compare/openssl-sys-v0.9.83...openssl-sys-v0.9.84
|
||||
[v0.9.83]: https://github.com/sfackler/rust-openssl/compare/openssl-sys-v0.9.82...openssl-sys-v0.9.83
|
||||
[v0.9.82]: https://github.com/sfackler/rust-openssl/compare/openssl-sys-v0.9.81...openssl-sys-v0.9.82
|
||||
[v0.9.81]: https://github.com/sfackler/rust-openssl/compare/openssl-sys-v0.9.80...openssl-sys-v0.9.81
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "openssl-sys"
|
||||
version = "0.9.83"
|
||||
version = "0.9.91"
|
||||
authors = [
|
||||
"Alex Crichton <alex@alexcrichton.com>",
|
||||
"Steven Fackler <sfackler@gmail.com>",
|
||||
@@ -24,12 +24,9 @@ bssl-sys = { version = "0.1.0", optional = true }
|
||||
|
||||
[build-dependencies]
|
||||
bindgen = { version = "0.64.0", optional = true, features = ["experimental"] }
|
||||
cc = "1.0"
|
||||
cc = "1.0.61"
|
||||
openssl-src = { version = "111", optional = true }
|
||||
pkg-config = "0.3.9"
|
||||
autocfg = "1.0"
|
||||
|
||||
[target.'cfg(target_env = "msvc")'.build-dependencies]
|
||||
vcpkg = "0.2.8"
|
||||
|
||||
# We don't actually use metadeps for annoying reasons but this is still here for tooling
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#[allow(clippy::unusual_byte_groupings)]
|
||||
pub fn get(openssl_version: Option<u64>, libressl_version: Option<u64>) -> Vec<&'static str> {
|
||||
let mut cfgs = vec![];
|
||||
|
||||
@@ -91,6 +92,9 @@ pub fn get(openssl_version: Option<u64>, libressl_version: Option<u64>) -> Vec<&
|
||||
if openssl_version >= 0x1_01_01_03_0 {
|
||||
cfgs.push("ossl111c");
|
||||
}
|
||||
if openssl_version >= 0x1_01_01_04_0 {
|
||||
cfgs.push("ossl111d");
|
||||
}
|
||||
}
|
||||
|
||||
cfgs
|
||||
|
||||
@@ -75,10 +75,18 @@ RUST_CONF_OPENSSL_NO_NEXTPROTONEG
|
||||
RUST_CONF_OPENSSL_NO_OCSP
|
||||
#endif
|
||||
|
||||
#ifdef OPENSSL_NO_OCB
|
||||
RUST_CONF_OPENSSL_NO_OCB
|
||||
#endif
|
||||
|
||||
#ifdef OPENSSL_NO_PSK
|
||||
RUST_CONF_OPENSSL_NO_PSK
|
||||
#endif
|
||||
|
||||
#ifdef OPENSSL_NO_RC4
|
||||
RUST_CONF_OPENSSL_NO_RC4
|
||||
#endif
|
||||
|
||||
#ifdef OPENSSL_NO_RFC3779
|
||||
RUST_CONF_OPENSSL_NO_RFC3779
|
||||
#endif
|
||||
@@ -103,6 +111,10 @@ RUST_CONF_OPENSSL_NO_SSL3_METHOD
|
||||
RUST_CONF_OPENSSL_NO_TLSEXT
|
||||
#endif
|
||||
|
||||
#ifdef OPENSSL_NO_SOCK
|
||||
RUST_CONF_OPENSSL_NO_SOCK
|
||||
#endif
|
||||
|
||||
#ifdef OPENSSL_NO_STDIO
|
||||
RUST_CONF_OPENSSL_NO_STDIO
|
||||
#endif
|
||||
|
||||
@@ -92,8 +92,8 @@ fn find_openssl_dir(target: &str) -> OsString {
|
||||
try_pkg_config();
|
||||
try_vcpkg();
|
||||
|
||||
// FreeBSD ships with OpenSSL but doesn't include a pkg-config file :(
|
||||
if host == target && target.contains("freebsd") {
|
||||
// FreeBSD and OpenBSD ship with Libre|OpenSSL but don't include a pkg-config file
|
||||
if host == target && (target.contains("freebsd") || target.contains("openbsd")) {
|
||||
return OsString::from("/usr");
|
||||
}
|
||||
|
||||
@@ -198,13 +198,11 @@ fn try_pkg_config() {
|
||||
let target = env::var("TARGET").unwrap();
|
||||
let host = env::var("HOST").unwrap();
|
||||
|
||||
// If we're going to windows-gnu we can use pkg-config, but only so long as
|
||||
// we're coming from a windows host.
|
||||
//
|
||||
// Otherwise if we're going to windows we probably can't use pkg-config.
|
||||
// FIXME we really shouldn't be automatically enabling this
|
||||
if target.contains("windows-gnu") && host.contains("windows") {
|
||||
env::set_var("PKG_CONFIG_ALLOW_CROSS", "1");
|
||||
} else if target.contains("windows") {
|
||||
} else if target.contains("windows-msvc") {
|
||||
// MSVC targets use vcpkg instead.
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -232,8 +230,12 @@ fn try_pkg_config() {
|
||||
///
|
||||
/// Note that if this succeeds then the function does not return as vcpkg
|
||||
/// should emit all of the cargo metadata that we need.
|
||||
#[cfg(target_env = "msvc")]
|
||||
fn try_vcpkg() {
|
||||
let target = env::var("TARGET").unwrap();
|
||||
if !target.contains("windows") {
|
||||
return;
|
||||
}
|
||||
|
||||
// vcpkg will not emit any metadata if it can not find libraries
|
||||
// appropriate for the target triple with the desired linkage.
|
||||
|
||||
@@ -257,9 +259,6 @@ fn try_vcpkg() {
|
||||
process::exit(0);
|
||||
}
|
||||
|
||||
#[cfg(not(target_env = "msvc"))]
|
||||
fn try_vcpkg() {}
|
||||
|
||||
fn execute_command_and_get_output(cmd: &str, args: &[&str]) -> Option<String> {
|
||||
let out = Command::new(cmd).args(args).output();
|
||||
if let Ok(ref r1) = out {
|
||||
|
||||
+11
-38
@@ -1,17 +1,9 @@
|
||||
#![allow(
|
||||
clippy::inconsistent_digit_grouping,
|
||||
clippy::uninlined_format_args,
|
||||
clippy::unusual_byte_groupings
|
||||
)]
|
||||
|
||||
extern crate autocfg;
|
||||
#[cfg(feature = "bindgen")]
|
||||
extern crate bindgen;
|
||||
extern crate cc;
|
||||
#[cfg(feature = "vendored")]
|
||||
extern crate openssl_src;
|
||||
extern crate pkg_config;
|
||||
#[cfg(target_env = "msvc")]
|
||||
extern crate vcpkg;
|
||||
|
||||
use std::collections::HashSet;
|
||||
@@ -74,8 +66,6 @@ fn check_ssl_kind() {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
check_rustc_versions();
|
||||
|
||||
check_ssl_kind();
|
||||
|
||||
let target = env::var("TARGET").unwrap();
|
||||
@@ -134,15 +124,6 @@ fn main() {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_rustc_versions() {
|
||||
let cfg = autocfg::new();
|
||||
|
||||
if cfg.probe_rustc_version(1, 31) {
|
||||
println!("cargo:rustc-cfg=const_fn");
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::let_and_return)]
|
||||
fn postprocess(include_dirs: &[PathBuf]) -> Version {
|
||||
let version = validate_headers(include_dirs);
|
||||
|
||||
@@ -157,7 +138,7 @@ fn postprocess(include_dirs: &[PathBuf]) -> Version {
|
||||
|
||||
/// Validates the header files found in `include_dir` and then returns the
|
||||
/// version string of OpenSSL.
|
||||
#[allow(clippy::manual_strip)] // we need to support pre-1.45.0
|
||||
#[allow(clippy::unusual_byte_groupings)]
|
||||
fn validate_headers(include_dirs: &[PathBuf]) -> Version {
|
||||
// This `*-sys` crate only works with OpenSSL 1.0.1, 1.0.2, 1.1.0, 1.1.1 and 3.0.0.
|
||||
// To correctly expose the right API from this crate, take a look at
|
||||
@@ -173,9 +154,7 @@ fn validate_headers(include_dirs: &[PathBuf]) -> Version {
|
||||
// account for compile differences and such.
|
||||
println!("cargo:rerun-if-changed=build/expando.c");
|
||||
let mut gcc = cc::Build::new();
|
||||
for include_dir in include_dirs {
|
||||
gcc.include(include_dir);
|
||||
}
|
||||
gcc.includes(include_dirs);
|
||||
let expanded = match gcc.file("build/expando.c").try_expand() {
|
||||
Ok(expanded) => expanded,
|
||||
Err(e) => {
|
||||
@@ -221,17 +200,14 @@ See rust-openssl documentation for more information:
|
||||
let libressl_prefix = "RUST_VERSION_LIBRESSL_";
|
||||
let boringsl_prefix = "RUST_OPENSSL_IS_BORINGSSL";
|
||||
let conf_prefix = "RUST_CONF_";
|
||||
if line.starts_with(openssl_prefix) {
|
||||
let version = &line[openssl_prefix.len()..];
|
||||
if let Some(version) = line.strip_prefix(openssl_prefix) {
|
||||
openssl_version = Some(parse_version(version));
|
||||
} else if line.starts_with(new_openssl_prefix) {
|
||||
let version = &line[new_openssl_prefix.len()..];
|
||||
} else if let Some(version) = line.strip_prefix(new_openssl_prefix) {
|
||||
openssl_version = Some(parse_new_version(version));
|
||||
} else if line.starts_with(libressl_prefix) {
|
||||
let version = &line[libressl_prefix.len()..];
|
||||
} else if let Some(version) = line.strip_prefix(libressl_prefix) {
|
||||
libressl_version = Some(parse_version(version));
|
||||
} else if line.starts_with(conf_prefix) {
|
||||
enabled.push(&line[conf_prefix.len()..]);
|
||||
} else if let Some(conf) = line.strip_prefix(conf_prefix) {
|
||||
enabled.push(conf);
|
||||
} else if line.starts_with(boringsl_prefix) {
|
||||
is_boringssl = true;
|
||||
}
|
||||
@@ -295,6 +271,8 @@ See rust-openssl documentation for more information:
|
||||
(3, 6, _) => ('3', '6', 'x'),
|
||||
(3, 7, 0) => ('3', '7', '0'),
|
||||
(3, 7, 1) => ('3', '7', '1'),
|
||||
(3, 7, _) => ('3', '7', 'x'),
|
||||
(3, 8, 0) => ('3', '8', '0'),
|
||||
_ => version_error(),
|
||||
};
|
||||
|
||||
@@ -337,7 +315,7 @@ fn version_error() -> ! {
|
||||
"
|
||||
|
||||
This crate is only compatible with OpenSSL (version 1.0.1 through 1.1.1, or 3.0.0), or LibreSSL 2.5
|
||||
through 3.7.1, but a different version of OpenSSL was found. The build is now aborting
|
||||
through 3.8.0, but a different version of OpenSSL was found. The build is now aborting
|
||||
due to this version mismatch.
|
||||
|
||||
"
|
||||
@@ -345,18 +323,13 @@ due to this version mismatch.
|
||||
}
|
||||
|
||||
// parses a string that looks like "0x100020cfL"
|
||||
#[allow(deprecated)] // trim_right_matches is now trim_end_matches
|
||||
#[allow(clippy::match_like_matches_macro)] // matches macro requires rust 1.42.0
|
||||
fn parse_version(version: &str) -> u64 {
|
||||
// cut off the 0x prefix
|
||||
assert!(version.starts_with("0x"));
|
||||
let version = &version[2..];
|
||||
|
||||
// and the type specifier suffix
|
||||
let version = version.trim_right_matches(|c: char| match c {
|
||||
'0'..='9' | 'a'..='f' | 'A'..='F' => false,
|
||||
_ => true,
|
||||
});
|
||||
let version = version.trim_end_matches(|c: char| !c.is_ascii_hexdigit());
|
||||
|
||||
u64::from_str_radix(version, 16).unwrap()
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ const INCLUDES: &str = "
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/cmac.h>
|
||||
#include <openssl/conf.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/dh.h>
|
||||
@@ -54,6 +55,10 @@ const INCLUDES: &str = "
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x30000000
|
||||
#include <openssl/provider.h>
|
||||
#endif
|
||||
|
||||
#if defined(LIBRESSL_VERSION_NUMBER) || defined(OPENSSL_IS_BORINGSSL)
|
||||
#include <openssl/poly1305.h>
|
||||
#endif
|
||||
";
|
||||
|
||||
#[cfg(feature = "bindgen")]
|
||||
@@ -109,12 +114,15 @@ pub fn run_boringssl(include_dirs: &[PathBuf]) {
|
||||
let mut builder = bindgen::builder()
|
||||
.rust_target(RustTarget::Stable_1_47)
|
||||
.ctypes_prefix("::libc")
|
||||
.raw_line("use libc::*;")
|
||||
.derive_default(false)
|
||||
.enable_function_attribute_detection()
|
||||
.size_t_is_usize(true)
|
||||
.default_macro_constant_type(MacroTypeVariation::Signed)
|
||||
.rustified_enum("point_conversion_form_t")
|
||||
.allowlist_file(".*/openssl/[^/]+\\.h")
|
||||
.allowlist_recursively(false)
|
||||
.blocklist_function("BIO_vsnprintf")
|
||||
.blocklist_function("OPENSSL_vasprintf")
|
||||
.wrap_static_fns(true)
|
||||
.wrap_static_fns_path(out_dir.join("boring_static_wrapper").display().to_string())
|
||||
.layout_tests(false)
|
||||
@@ -163,14 +171,19 @@ pub fn run_boringssl(include_dirs: &[PathBuf]) {
|
||||
bindgen_cmd
|
||||
.arg("-o")
|
||||
.arg(out_dir.join("bindgen.rs"))
|
||||
// Must be a valid version from
|
||||
// https://docs.rs/bindgen/latest/bindgen/enum.RustTarget.html
|
||||
.arg("--rust-target=1.47")
|
||||
.arg("--ctypes-prefix=::libc")
|
||||
.arg("--raw-line=use libc::*;")
|
||||
.arg("--no-derive-default")
|
||||
.arg("--enable-function-attribute-detection")
|
||||
.arg("--size_t-is-usize")
|
||||
.arg("--default-macro-constant-type=signed")
|
||||
.arg("--rustified-enum=point_conversion_form_t")
|
||||
.arg("--allowlist-file=.*/openssl/[^/]+\\.h")
|
||||
.arg("--no-recursive-allowlist")
|
||||
.arg("--blocklist-function=BIO_vsnprintf")
|
||||
.arg("--blocklist-function=OPENSSL_vasprintf")
|
||||
.arg("--experimental")
|
||||
.arg("--wrap-static-fns")
|
||||
.arg("--wrap-static-fns-path")
|
||||
|
||||
+32
-36
@@ -20,51 +20,47 @@ cfg_if! {
|
||||
|
||||
pub const ERR_RFLAG_FATAL: c_ulong = 0x1 << ERR_RFLAGS_OFFSET;
|
||||
|
||||
const_fn! {
|
||||
pub const fn ERR_SYSTEM_ERROR(errcode: c_ulong) -> bool {
|
||||
errcode & ERR_SYSTEM_FLAG != 0
|
||||
}
|
||||
pub const fn ERR_SYSTEM_ERROR(errcode: c_ulong) -> bool {
|
||||
errcode & ERR_SYSTEM_FLAG != 0
|
||||
}
|
||||
|
||||
pub const fn ERR_GET_LIB(errcode: c_ulong) -> c_int {
|
||||
// hacks since `if` isn't yet stable in const functions :(
|
||||
((ERR_LIB_SYS as c_ulong * (ERR_SYSTEM_ERROR(errcode) as c_ulong)) |
|
||||
(((errcode >> ERR_LIB_OFFSET) & ERR_LIB_MASK) * (!ERR_SYSTEM_ERROR(errcode) as c_ulong))) as c_int
|
||||
}
|
||||
pub const fn ERR_GET_LIB(errcode: c_ulong) -> c_int {
|
||||
// hacks since `if` isn't yet stable in const functions :(
|
||||
((ERR_LIB_SYS as c_ulong * (ERR_SYSTEM_ERROR(errcode) as c_ulong)) |
|
||||
(((errcode >> ERR_LIB_OFFSET) & ERR_LIB_MASK) * (!ERR_SYSTEM_ERROR(errcode) as c_ulong))) as c_int
|
||||
}
|
||||
|
||||
pub const fn ERR_GET_FUNC(_errcode: c_ulong) -> c_int {
|
||||
0
|
||||
}
|
||||
pub const fn ERR_GET_FUNC(_errcode: c_ulong) -> c_int {
|
||||
0
|
||||
}
|
||||
|
||||
pub const fn ERR_GET_REASON(errcode: c_ulong) -> c_int {
|
||||
// hacks since `if` isn't yet stable in const functions :(
|
||||
((ERR_LIB_SYS as c_ulong * (ERR_SYSTEM_ERROR(errcode) as c_ulong)) |
|
||||
((errcode & ERR_REASON_MASK) * (!ERR_SYSTEM_ERROR(errcode) as c_ulong))) as c_int
|
||||
}
|
||||
pub const fn ERR_GET_REASON(errcode: c_ulong) -> c_int {
|
||||
// hacks since `if` isn't yet stable in const functions :(
|
||||
((ERR_LIB_SYS as c_ulong * (ERR_SYSTEM_ERROR(errcode) as c_ulong)) |
|
||||
((errcode & ERR_REASON_MASK) * (!ERR_SYSTEM_ERROR(errcode) as c_ulong))) as c_int
|
||||
}
|
||||
|
||||
pub const fn ERR_PACK(lib: c_int, _func: c_int, reason: c_int) -> c_ulong {
|
||||
((lib as c_ulong & ERR_LIB_MASK) << ERR_LIB_OFFSET) |
|
||||
(reason as c_ulong & ERR_REASON_MASK)
|
||||
}
|
||||
pub const fn ERR_PACK(lib: c_int, _func: c_int, reason: c_int) -> c_ulong {
|
||||
((lib as c_ulong & ERR_LIB_MASK) << ERR_LIB_OFFSET) |
|
||||
(reason as c_ulong & ERR_REASON_MASK)
|
||||
}
|
||||
} else {
|
||||
const_fn! {
|
||||
pub const fn ERR_PACK(l: c_int, f: c_int, r: c_int) -> c_ulong {
|
||||
((l as c_ulong & 0x0FF) << 24) |
|
||||
((f as c_ulong & 0xFFF) << 12) |
|
||||
(r as c_ulong & 0xFFF)
|
||||
}
|
||||
pub const fn ERR_PACK(l: c_int, f: c_int, r: c_int) -> c_ulong {
|
||||
((l as c_ulong & 0x0FF) << 24) |
|
||||
((f as c_ulong & 0xFFF) << 12) |
|
||||
(r as c_ulong & 0xFFF)
|
||||
}
|
||||
|
||||
pub const fn ERR_GET_LIB(l: c_ulong) -> c_int {
|
||||
((l >> 24) & 0x0FF) as c_int
|
||||
}
|
||||
pub const fn ERR_GET_LIB(l: c_ulong) -> c_int {
|
||||
((l >> 24) & 0x0FF) as c_int
|
||||
}
|
||||
|
||||
pub const fn ERR_GET_FUNC(l: c_ulong) -> c_int {
|
||||
((l >> 12) & 0xFFF) as c_int
|
||||
}
|
||||
pub const fn ERR_GET_FUNC(l: c_ulong) -> c_int {
|
||||
((l >> 12) & 0xFFF) as c_int
|
||||
}
|
||||
|
||||
pub const fn ERR_GET_REASON(l: c_ulong) -> c_int {
|
||||
(l & 0xFFF) as c_int
|
||||
}
|
||||
pub const fn ERR_GET_REASON(l: c_ulong) -> c_int {
|
||||
(l & 0xFFF) as c_int
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ pub const EVP_PKEY_RSA: c_int = NID_rsaEncryption;
|
||||
pub const EVP_PKEY_DSA: c_int = NID_dsa;
|
||||
pub const EVP_PKEY_DH: c_int = NID_dhKeyAgreement;
|
||||
pub const EVP_PKEY_EC: c_int = NID_X9_62_id_ecPublicKey;
|
||||
#[cfg(ossl111)]
|
||||
pub const EVP_PKEY_SM2: c_int = NID_sm2;
|
||||
#[cfg(any(ossl111, libressl370))]
|
||||
pub const EVP_PKEY_X25519: c_int = NID_X25519;
|
||||
#[cfg(any(ossl111, libressl370))]
|
||||
@@ -20,9 +22,14 @@ pub const EVP_PKEY_X448: c_int = NID_X448;
|
||||
pub const EVP_PKEY_ED448: c_int = NID_ED448;
|
||||
pub const EVP_PKEY_HMAC: c_int = NID_hmac;
|
||||
pub const EVP_PKEY_CMAC: c_int = NID_cmac;
|
||||
#[cfg(ossl111)]
|
||||
pub const EVP_PKEY_POLY1305: c_int = NID_poly1305;
|
||||
#[cfg(ossl110)]
|
||||
pub const EVP_PKEY_HKDF: c_int = NID_hkdf;
|
||||
|
||||
#[cfg(ossl102)]
|
||||
pub const EVP_CIPHER_CTX_FLAG_WRAP_ALLOW: c_int = 0x1;
|
||||
|
||||
pub const EVP_CTRL_GCM_SET_IVLEN: c_int = 0x9;
|
||||
pub const EVP_CTRL_GCM_GET_TAG: c_int = 0x10;
|
||||
pub const EVP_CTRL_GCM_SET_TAG: c_int = 0x11;
|
||||
@@ -182,6 +189,8 @@ pub const EVP_PKEY_OP_TYPE_SIG: c_int = EVP_PKEY_OP_SIGN
|
||||
|
||||
pub const EVP_PKEY_OP_TYPE_CRYPT: c_int = EVP_PKEY_OP_ENCRYPT | EVP_PKEY_OP_DECRYPT;
|
||||
|
||||
pub const EVP_PKEY_CTRL_MD: c_int = 1;
|
||||
|
||||
pub const EVP_PKEY_CTRL_SET_MAC_KEY: c_int = 6;
|
||||
|
||||
pub const EVP_PKEY_CTRL_CIPHER: c_int = 12;
|
||||
@@ -283,3 +292,31 @@ pub unsafe fn EVP_PKEY_CTX_add1_hkdf_info(
|
||||
info as *mut c_void,
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(all(not(ossl300), not(boringssl)))]
|
||||
pub unsafe fn EVP_PKEY_CTX_set_signature_md(cxt: *mut EVP_PKEY_CTX, md: *mut EVP_MD) -> c_int {
|
||||
EVP_PKEY_CTX_ctrl(
|
||||
cxt,
|
||||
-1,
|
||||
EVP_PKEY_OP_TYPE_SIG,
|
||||
EVP_PKEY_CTRL_MD,
|
||||
0,
|
||||
md as *mut c_void,
|
||||
)
|
||||
}
|
||||
|
||||
pub unsafe fn EVP_PKEY_assign_RSA(pkey: *mut EVP_PKEY, rsa: *mut RSA) -> c_int {
|
||||
EVP_PKEY_assign(pkey, EVP_PKEY_RSA, rsa as *mut c_void)
|
||||
}
|
||||
|
||||
pub unsafe fn EVP_PKEY_assign_DSA(pkey: *mut EVP_PKEY, dsa: *mut DSA) -> c_int {
|
||||
EVP_PKEY_assign(pkey, EVP_PKEY_DSA, dsa as *mut c_void)
|
||||
}
|
||||
|
||||
pub unsafe fn EVP_PKEY_assign_DH(pkey: *mut EVP_PKEY, dh: *mut DH) -> c_int {
|
||||
EVP_PKEY_assign(pkey, EVP_PKEY_DH, dh as *mut c_void)
|
||||
}
|
||||
|
||||
pub unsafe fn EVP_PKEY_assign_EC_KEY(pkey: *mut EVP_PKEY, ec_key: *mut EC_KEY) -> c_int {
|
||||
EVP_PKEY_assign(pkey, EVP_PKEY_EC, ec_key as *mut c_void)
|
||||
}
|
||||
|
||||
@@ -10,23 +10,60 @@ pub struct ASN1_ENCODING {
|
||||
|
||||
extern "C" {
|
||||
pub fn ASN1_OBJECT_free(x: *mut ASN1_OBJECT);
|
||||
pub fn OBJ_dup(x: *const ASN1_OBJECT) -> *mut ASN1_OBJECT;
|
||||
}
|
||||
|
||||
stack!(stack_st_ASN1_OBJECT);
|
||||
|
||||
#[repr(C)]
|
||||
pub struct ASN1_TYPE {
|
||||
pub type_: c_int,
|
||||
pub value: ASN1_TYPE_value,
|
||||
}
|
||||
#[repr(C)]
|
||||
pub union ASN1_TYPE_value {
|
||||
pub ptr: *mut c_char,
|
||||
pub boolean: ASN1_BOOLEAN,
|
||||
pub asn1_string: *mut ASN1_STRING,
|
||||
pub object: *mut ASN1_OBJECT,
|
||||
pub integer: *mut ASN1_INTEGER,
|
||||
pub enumerated: *mut ASN1_ENUMERATED,
|
||||
pub bit_string: *mut ASN1_BIT_STRING,
|
||||
pub octet_string: *mut ASN1_OCTET_STRING,
|
||||
pub printablestring: *mut ASN1_PRINTABLESTRING,
|
||||
pub t61string: *mut ASN1_T61STRING,
|
||||
pub ia5string: *mut ASN1_IA5STRING,
|
||||
pub generalstring: *mut ASN1_GENERALSTRING,
|
||||
pub bmpstring: *mut ASN1_BMPSTRING,
|
||||
pub universalstring: *mut ASN1_UNIVERSALSTRING,
|
||||
pub utctime: *mut ASN1_UTCTIME,
|
||||
pub generalizedtime: *mut ASN1_GENERALIZEDTIME,
|
||||
pub visiblestring: *mut ASN1_VISIBLESTRING,
|
||||
pub utf8string: *mut ASN1_UTF8STRING,
|
||||
pub set: *mut ASN1_STRING,
|
||||
pub sequence: *mut ASN1_STRING,
|
||||
pub asn1_value: *mut ASN1_VALUE,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub fn ASN1_STRING_type_new(ty: c_int) -> *mut ASN1_STRING;
|
||||
#[cfg(any(ossl110, libressl273))]
|
||||
pub fn ASN1_STRING_get0_data(x: *const ASN1_STRING) -> *const c_uchar;
|
||||
#[cfg(any(all(ossl101, not(ossl110)), libressl))]
|
||||
pub fn ASN1_STRING_data(x: *mut ASN1_STRING) -> *mut c_uchar;
|
||||
|
||||
pub fn ASN1_BIT_STRING_free(x: *mut ASN1_BIT_STRING);
|
||||
|
||||
pub fn ASN1_STRING_new() -> *mut ASN1_STRING;
|
||||
pub fn ASN1_OCTET_STRING_new() -> *mut ASN1_OCTET_STRING;
|
||||
pub fn ASN1_STRING_free(x: *mut ASN1_STRING);
|
||||
pub fn ASN1_STRING_length(x: *const ASN1_STRING) -> c_int;
|
||||
pub fn ASN1_STRING_set(x: *mut ASN1_STRING, data: *const c_void, len_in: c_int) -> c_int;
|
||||
pub fn ASN1_OCTET_STRING_set(
|
||||
x: *mut ASN1_OCTET_STRING,
|
||||
data: *const c_uchar,
|
||||
len_in: c_int,
|
||||
) -> c_int;
|
||||
|
||||
pub fn ASN1_STRING_set(x: *mut ASN1_STRING, data: *const c_void, len: c_int) -> c_int;
|
||||
pub fn ASN1_BIT_STRING_free(x: *mut ASN1_BIT_STRING);
|
||||
pub fn ASN1_OCTET_STRING_free(x: *mut ASN1_OCTET_STRING);
|
||||
|
||||
pub fn ASN1_GENERALIZEDTIME_free(tm: *mut ASN1_GENERALIZEDTIME);
|
||||
pub fn ASN1_GENERALIZEDTIME_print(b: *mut BIO, tm: *const ASN1_GENERALIZEDTIME) -> c_int;
|
||||
@@ -43,18 +80,36 @@ extern "C" {
|
||||
pub fn ASN1_TIME_set(from: *mut ASN1_TIME, to: time_t) -> *mut ASN1_TIME;
|
||||
|
||||
pub fn ASN1_INTEGER_free(x: *mut ASN1_INTEGER);
|
||||
pub fn ASN1_INTEGER_dup(a: *const ASN1_INTEGER) -> *mut ASN1_INTEGER;
|
||||
pub fn ASN1_INTEGER_get(dest: *const ASN1_INTEGER) -> c_long;
|
||||
pub fn ASN1_INTEGER_set(dest: *mut ASN1_INTEGER, value: c_long) -> c_int;
|
||||
pub fn ASN1_INTEGER_cmp(a: *const ASN1_INTEGER, b: *const ASN1_INTEGER) -> c_int;
|
||||
pub fn BN_to_ASN1_INTEGER(bn: *const BIGNUM, ai: *mut ASN1_INTEGER) -> *mut ASN1_INTEGER;
|
||||
pub fn ASN1_INTEGER_to_BN(ai: *const ASN1_INTEGER, bn: *mut BIGNUM) -> *mut BIGNUM;
|
||||
|
||||
pub fn ASN1_TIME_set_string(s: *mut ASN1_TIME, str: *const c_char) -> c_int;
|
||||
#[cfg(ossl111)]
|
||||
pub fn ASN1_TIME_set_string_X509(s: *mut ASN1_TIME, str: *const c_char) -> c_int;
|
||||
|
||||
pub fn ASN1_ENUMERATED_free(a: *mut ASN1_ENUMERATED);
|
||||
#[cfg(ossl110)]
|
||||
pub fn ASN1_ENUMERATED_get_int64(pr: *mut i64, a: *const ASN1_ENUMERATED) -> c_int;
|
||||
|
||||
pub fn ASN1_TYPE_new() -> *mut ASN1_TYPE;
|
||||
pub fn ASN1_TYPE_set(a: *mut ASN1_TYPE, type_: c_int, value: *mut c_void);
|
||||
pub fn ASN1_TYPE_free(x: *mut ASN1_TYPE);
|
||||
pub fn d2i_ASN1_TYPE(
|
||||
k: *mut *mut ASN1_TYPE,
|
||||
buf: *mut *const u8,
|
||||
len: c_long,
|
||||
) -> *mut ASN1_TYPE;
|
||||
}
|
||||
|
||||
const_ptr_api! {
|
||||
extern "C" {
|
||||
pub fn ASN1_STRING_to_UTF8(out: *mut *mut c_uchar, s: #[const_ptr_if(any(ossl110, libressl280))] ASN1_STRING) -> c_int;
|
||||
pub fn ASN1_STRING_type(x: #[const_ptr_if(any(ossl110, libressl280))] ASN1_STRING) -> c_int;
|
||||
pub fn ASN1_generate_v3(str: #[const_ptr_if(any(ossl110, libressl280))] c_char, cnf: *mut X509V3_CTX) -> *mut ASN1_TYPE;
|
||||
pub fn i2d_ASN1_TYPE(a: #[const_ptr_if(ossl300)] ASN1_TYPE, pp: *mut *mut c_uchar) -> c_int;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@ const_ptr_api! {
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_SOCK"))]
|
||||
pub fn BIO_new_socket(sock: c_int, close_flag: c_int) -> *mut BIO;
|
||||
|
||||
#[cfg(any(ossl110, libressl273))]
|
||||
|
||||
@@ -23,7 +23,7 @@ extern "C" {
|
||||
pub fn BN_clear_free(bn: *mut BIGNUM);
|
||||
pub fn BN_bin2bn(s: *const u8, size: c_int, ret: *mut BIGNUM) -> *mut BIGNUM;
|
||||
pub fn BN_bn2bin(a: *const BIGNUM, to: *mut u8) -> c_int;
|
||||
#[cfg(ossl110)]
|
||||
#[cfg(any(ossl110, libressl340))]
|
||||
pub fn BN_bn2binpad(a: *const BIGNUM, to: *mut u8, tolen: c_int) -> c_int;
|
||||
pub fn BN_sub(r: *mut BIGNUM, a: *const BIGNUM, b: *const BIGNUM) -> c_int;
|
||||
pub fn BN_add(r: *mut BIGNUM, a: *const BIGNUM, b: *const BIGNUM) -> c_int;
|
||||
@@ -32,6 +32,8 @@ extern "C" {
|
||||
pub fn BN_set_negative(bn: *mut BIGNUM, n: c_int);
|
||||
#[cfg(any(ossl110, libressl350))]
|
||||
pub fn BN_is_negative(b: *const BIGNUM) -> c_int;
|
||||
#[cfg(any(ossl110, libressl350))]
|
||||
pub fn BN_is_odd(b: *const BIGNUM) -> c_int;
|
||||
|
||||
pub fn BN_div(
|
||||
dv: *mut BIGNUM,
|
||||
@@ -73,6 +75,13 @@ extern "C" {
|
||||
m: *const BIGNUM,
|
||||
ctx: *mut BN_CTX,
|
||||
) -> c_int;
|
||||
#[cfg(ossl110)]
|
||||
pub fn BN_mod_sqrt(
|
||||
ret: *mut BIGNUM,
|
||||
a: *const BIGNUM,
|
||||
p: *const BIGNUM,
|
||||
ctx: *mut BN_CTX,
|
||||
) -> *mut BIGNUM;
|
||||
|
||||
pub fn BN_mod_word(r: *const BIGNUM, w: BN_ULONG) -> BN_ULONG;
|
||||
pub fn BN_div_word(r: *mut BIGNUM, w: BN_ULONG) -> BN_ULONG;
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
use libc::*;
|
||||
|
||||
use super::super::*;
|
||||
|
||||
extern "C" {
|
||||
pub fn CMAC_CTX_new() -> *mut CMAC_CTX;
|
||||
pub fn CMAC_CTX_free(ctx: *mut CMAC_CTX);
|
||||
pub fn CMAC_Init(
|
||||
ctx: *mut CMAC_CTX,
|
||||
key: *const c_void,
|
||||
len: size_t,
|
||||
cipher: *const EVP_CIPHER,
|
||||
impl_: *mut ENGINE,
|
||||
) -> c_int;
|
||||
pub fn CMAC_Update(ctx: *mut CMAC_CTX, data: *const c_void, len: size_t) -> c_int;
|
||||
pub fn CMAC_Final(ctx: *mut CMAC_CTX, out: *mut c_uchar, len: *mut size_t) -> c_int;
|
||||
pub fn CMAC_CTX_copy(dst: *mut CMAC_CTX, src: *const CMAC_CTX) -> c_int;
|
||||
}
|
||||
@@ -3,6 +3,7 @@ use super::super::*;
|
||||
extern "C" {
|
||||
pub fn DH_new() -> *mut DH;
|
||||
pub fn DH_free(dh: *mut DH);
|
||||
pub fn DH_check(dh: *const DH, codes: *mut c_int) -> c_int;
|
||||
|
||||
pub fn DH_generate_parameters(
|
||||
prime_len: c_int,
|
||||
|
||||
@@ -46,6 +46,8 @@ extern "C" {
|
||||
|
||||
pub fn EC_GROUP_set_asn1_flag(key: *mut EC_GROUP, flag: c_int);
|
||||
|
||||
pub fn EC_GROUP_get_asn1_flag(group: *const EC_GROUP) -> c_int;
|
||||
|
||||
pub fn EC_GROUP_get_curve_GFp(
|
||||
group: *const EC_GROUP,
|
||||
p: *mut BIGNUM,
|
||||
@@ -99,7 +101,7 @@ extern "C" {
|
||||
|
||||
pub fn EC_POINT_dup(p: *const EC_POINT, group: *const EC_GROUP) -> *mut EC_POINT;
|
||||
|
||||
#[cfg(ossl111)]
|
||||
#[cfg(any(ossl111, boringssl, libressl350))]
|
||||
pub fn EC_POINT_get_affine_coordinates(
|
||||
group: *const EC_GROUP,
|
||||
p: *const EC_POINT,
|
||||
@@ -150,6 +152,20 @@ extern "C" {
|
||||
ctx: *mut BN_CTX,
|
||||
) -> c_int;
|
||||
|
||||
pub fn EC_POINT_point2hex(
|
||||
group: *const EC_GROUP,
|
||||
p: *const EC_POINT,
|
||||
form: point_conversion_form_t,
|
||||
ctx: *mut BN_CTX,
|
||||
) -> *mut c_char;
|
||||
|
||||
pub fn EC_POINT_hex2point(
|
||||
group: *const EC_GROUP,
|
||||
s: *const c_char,
|
||||
p: *mut EC_POINT,
|
||||
ctx: *mut BN_CTX,
|
||||
) -> *mut EC_POINT;
|
||||
|
||||
pub fn EC_POINT_add(
|
||||
group: *const EC_GROUP,
|
||||
r: *mut EC_POINT,
|
||||
|
||||
@@ -65,6 +65,14 @@ cfg_if! {
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(ossl300)] {
|
||||
extern "C" {
|
||||
pub fn EVP_default_properties_is_fips_enabled(libctx: *mut OSSL_LIB_CTX) -> c_int;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub fn EVP_DigestInit_ex(ctx: *mut EVP_MD_CTX, typ: *const EVP_MD, imple: *mut ENGINE)
|
||||
-> c_int;
|
||||
@@ -275,6 +283,7 @@ extern "C" {
|
||||
ptr: *mut c_void,
|
||||
) -> c_int;
|
||||
pub fn EVP_CIPHER_CTX_rand_key(ctx: *mut EVP_CIPHER_CTX, key: *mut c_uchar) -> c_int;
|
||||
pub fn EVP_CIPHER_CTX_set_flags(ctx: *mut EVP_CIPHER_CTX, flags: c_int);
|
||||
|
||||
pub fn EVP_md_null() -> *const EVP_MD;
|
||||
pub fn EVP_md5() -> *const EVP_MD;
|
||||
@@ -303,6 +312,7 @@ extern "C" {
|
||||
pub fn EVP_des_ede3_cbc() -> *const EVP_CIPHER;
|
||||
pub fn EVP_des_ede3_cfb64() -> *const EVP_CIPHER;
|
||||
pub fn EVP_des_cbc() -> *const EVP_CIPHER;
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_RC4"))]
|
||||
pub fn EVP_rc4() -> *const EVP_CIPHER;
|
||||
pub fn EVP_bf_ecb() -> *const EVP_CIPHER;
|
||||
pub fn EVP_bf_cbc() -> *const EVP_CIPHER;
|
||||
@@ -320,6 +330,10 @@ extern "C" {
|
||||
pub fn EVP_aes_128_ofb() -> *const EVP_CIPHER;
|
||||
#[cfg(ossl110)]
|
||||
pub fn EVP_aes_128_ocb() -> *const EVP_CIPHER;
|
||||
#[cfg(ossl102)]
|
||||
pub fn EVP_aes_128_wrap() -> *const EVP_CIPHER;
|
||||
#[cfg(ossl110)]
|
||||
pub fn EVP_aes_128_wrap_pad() -> *const EVP_CIPHER;
|
||||
pub fn EVP_aes_192_ecb() -> *const EVP_CIPHER;
|
||||
pub fn EVP_aes_192_cbc() -> *const EVP_CIPHER;
|
||||
pub fn EVP_aes_192_cfb1() -> *const EVP_CIPHER;
|
||||
@@ -331,6 +345,10 @@ extern "C" {
|
||||
pub fn EVP_aes_192_ofb() -> *const EVP_CIPHER;
|
||||
#[cfg(ossl110)]
|
||||
pub fn EVP_aes_192_ocb() -> *const EVP_CIPHER;
|
||||
#[cfg(ossl102)]
|
||||
pub fn EVP_aes_192_wrap() -> *const EVP_CIPHER;
|
||||
#[cfg(ossl110)]
|
||||
pub fn EVP_aes_192_wrap_pad() -> *const EVP_CIPHER;
|
||||
pub fn EVP_aes_256_ecb() -> *const EVP_CIPHER;
|
||||
pub fn EVP_aes_256_cbc() -> *const EVP_CIPHER;
|
||||
pub fn EVP_aes_256_cfb1() -> *const EVP_CIPHER;
|
||||
@@ -343,6 +361,10 @@ extern "C" {
|
||||
pub fn EVP_aes_256_ofb() -> *const EVP_CIPHER;
|
||||
#[cfg(ossl110)]
|
||||
pub fn EVP_aes_256_ocb() -> *const EVP_CIPHER;
|
||||
#[cfg(ossl102)]
|
||||
pub fn EVP_aes_256_wrap() -> *const EVP_CIPHER;
|
||||
#[cfg(ossl110)]
|
||||
pub fn EVP_aes_256_wrap_pad() -> *const EVP_CIPHER;
|
||||
#[cfg(all(ossl110, not(osslconf = "OPENSSL_NO_CHACHA")))]
|
||||
pub fn EVP_chacha20() -> *const EVP_CIPHER;
|
||||
#[cfg(all(ossl110, not(osslconf = "OPENSSL_NO_CHACHA")))]
|
||||
@@ -404,22 +426,6 @@ cfg_if! {
|
||||
pub fn EVP_PKEY_get_bits(key: *const EVP_PKEY) -> c_int;
|
||||
pub fn EVP_PKEY_get_security_bits(key: *const EVP_PKEY) -> c_int;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn EVP_PKEY_id(pkey: *const EVP_PKEY) -> c_int {
|
||||
EVP_PKEY_get_id(pkey)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn EVP_PKEY_bits(pkey: *const EVP_PKEY) -> c_int {
|
||||
EVP_PKEY_get_bits(pkey)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn EVP_PKEY_security_bits(pkey: *const EVP_PKEY) -> c_int {
|
||||
EVP_PKEY_get_security_bits(pkey)
|
||||
}
|
||||
|
||||
} else {
|
||||
extern "C" {
|
||||
pub fn EVP_PKEY_id(pkey: *const EVP_PKEY) -> c_int;
|
||||
@@ -504,6 +510,9 @@ extern "C" {
|
||||
p2: *mut c_void,
|
||||
) -> c_int;
|
||||
|
||||
#[cfg(ossl300)]
|
||||
pub fn EVP_PKEY_CTX_set_signature_md(ctx: *mut EVP_PKEY_CTX, md: *const EVP_MD) -> c_int;
|
||||
|
||||
pub fn EVP_PKEY_new_mac_key(
|
||||
type_: c_int,
|
||||
e: *mut ENGINE,
|
||||
@@ -513,6 +522,12 @@ extern "C" {
|
||||
|
||||
pub fn EVP_PKEY_derive_init(ctx: *mut EVP_PKEY_CTX) -> c_int;
|
||||
pub fn EVP_PKEY_derive_set_peer(ctx: *mut EVP_PKEY_CTX, peer: *mut EVP_PKEY) -> c_int;
|
||||
#[cfg(ossl300)]
|
||||
pub fn EVP_PKEY_derive_set_peer_ex(
|
||||
ctx: *mut EVP_PKEY_CTX,
|
||||
peer: *mut EVP_PKEY,
|
||||
validate_peer: c_int,
|
||||
) -> c_int;
|
||||
pub fn EVP_PKEY_derive(ctx: *mut EVP_PKEY_CTX, key: *mut c_uchar, size: *mut size_t) -> c_int;
|
||||
|
||||
#[cfg(ossl300)]
|
||||
@@ -557,6 +572,14 @@ extern "C" {
|
||||
pin: *const c_uchar,
|
||||
pinlen: size_t,
|
||||
) -> c_int;
|
||||
pub fn EVP_PKEY_verify_recover_init(ctx: *mut EVP_PKEY_CTX) -> c_int;
|
||||
pub fn EVP_PKEY_verify_recover(
|
||||
ctx: *mut EVP_PKEY_CTX,
|
||||
rout: *mut c_uchar,
|
||||
routlen: *mut size_t,
|
||||
sig: *const c_uchar,
|
||||
siglen: size_t,
|
||||
) -> c_int;
|
||||
}
|
||||
|
||||
const_ptr_api! {
|
||||
|
||||
@@ -2,6 +2,7 @@ pub use self::aes::*;
|
||||
pub use self::asn1::*;
|
||||
pub use self::bio::*;
|
||||
pub use self::bn::*;
|
||||
pub use self::cmac::*;
|
||||
pub use self::cms::*;
|
||||
pub use self::conf::*;
|
||||
pub use self::crypto::*;
|
||||
@@ -17,6 +18,8 @@ pub use self::ocsp::*;
|
||||
pub use self::pem::*;
|
||||
pub use self::pkcs12::*;
|
||||
pub use self::pkcs7::*;
|
||||
#[cfg(libressl)]
|
||||
pub use self::poly1305::*;
|
||||
pub use self::provider::*;
|
||||
pub use self::rand::*;
|
||||
pub use self::rsa::*;
|
||||
@@ -35,6 +38,7 @@ mod aes;
|
||||
mod asn1;
|
||||
mod bio;
|
||||
mod bn;
|
||||
mod cmac;
|
||||
mod cms;
|
||||
mod conf;
|
||||
mod crypto;
|
||||
@@ -50,6 +54,8 @@ mod ocsp;
|
||||
mod pem;
|
||||
mod pkcs12;
|
||||
mod pkcs7;
|
||||
#[cfg(libressl)]
|
||||
mod poly1305;
|
||||
mod provider;
|
||||
mod rand;
|
||||
mod rsa;
|
||||
|
||||
@@ -27,4 +27,5 @@ extern "C" {
|
||||
pub fn OBJ_length(obj: *const ASN1_OBJECT) -> libc::size_t;
|
||||
#[cfg(ossl111)]
|
||||
pub fn OBJ_get0_data(obj: *const ASN1_OBJECT) -> *const c_uchar;
|
||||
pub fn OBJ_cmp(a: *const ASN1_OBJECT, b: *const ASN1_OBJECT) -> c_int;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,149 @@
|
||||
use super::super::*;
|
||||
use libc::*;
|
||||
|
||||
pub enum PKCS7_SIGNED {}
|
||||
pub enum PKCS7_ENVELOPE {}
|
||||
pub enum PKCS7_SIGN_ENVELOPE {}
|
||||
pub enum PKCS7_DIGEST {}
|
||||
pub enum PKCS7_ENCRYPT {}
|
||||
pub enum PKCS7 {}
|
||||
#[cfg(ossl300)]
|
||||
#[repr(C)]
|
||||
pub struct PKCS7_CTX {
|
||||
libctx: *mut OSSL_LIB_CTX,
|
||||
propq: *mut c_char,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct PKCS7_SIGNED {
|
||||
pub version: *mut ASN1_INTEGER, /* version 1 */
|
||||
pub md_algs: *mut stack_st_X509_ALGOR, /* md used */
|
||||
pub cert: *mut stack_st_X509, /* [ 0 ] */
|
||||
pub crl: *mut stack_st_X509_CRL, /* [ 1 ] */
|
||||
pub signer_info: *mut stack_st_PKCS7_SIGNER_INFO,
|
||||
pub contents: *mut PKCS7,
|
||||
}
|
||||
#[repr(C)]
|
||||
pub struct PKCS7_ENC_CONTENT {
|
||||
pub content_type: *mut ASN1_OBJECT,
|
||||
pub algorithm: *mut X509_ALGOR,
|
||||
pub enc_data: *mut ASN1_OCTET_STRING, /* [ 0 ] */
|
||||
pub cipher: *const EVP_CIPHER,
|
||||
#[cfg(ossl300)]
|
||||
pub ctx: *const PKCS7_CTX,
|
||||
}
|
||||
#[repr(C)]
|
||||
pub struct PKCS7_ENVELOPE {
|
||||
pub version: *mut ASN1_INTEGER, /* version 0 */
|
||||
pub recipientinfo: *mut stack_st_PKCS7_RECIP_INFO,
|
||||
pub enc_data: *mut PKCS7_ENC_CONTENT,
|
||||
}
|
||||
#[repr(C)]
|
||||
pub struct PKCS7_SIGN_ENVELOPE {
|
||||
pub version: *mut ASN1_INTEGER, /* version 1 */
|
||||
pub md_algs: *mut stack_st_X509_ALGOR, /* md used */
|
||||
pub cert: *mut stack_st_X509, /* [ 0 ] */
|
||||
pub crl: *mut stack_st_X509_CRL, /* [ 1 ] */
|
||||
pub signer_info: *mut stack_st_PKCS7_SIGNER_INFO,
|
||||
pub enc_data: *mut PKCS7_ENC_CONTENT,
|
||||
pub recipientinfo: *mut stack_st_PKCS7_RECIP_INFO,
|
||||
}
|
||||
#[repr(C)]
|
||||
pub struct PKCS7_DIGEST {
|
||||
pub version: *mut ASN1_INTEGER, /* version 0 */
|
||||
pub md: *mut X509_ALGOR, /* md used */
|
||||
pub contents: *mut PKCS7,
|
||||
pub digest: *mut ASN1_OCTET_STRING,
|
||||
}
|
||||
#[repr(C)]
|
||||
pub struct PKCS7_ENCRYPT {
|
||||
pub version: *mut ASN1_INTEGER, /* version 0 */
|
||||
pub enc_data: *mut PKCS7_ENC_CONTENT,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub fn PKCS7_SIGNED_free(info: *mut PKCS7_SIGNED);
|
||||
pub fn PKCS7_ENC_CONTENT_free(info: *mut PKCS7_ENC_CONTENT);
|
||||
pub fn PKCS7_ENVELOPE_free(info: *mut PKCS7_ENVELOPE);
|
||||
pub fn PKCS7_SIGN_ENVELOPE_free(info: *mut PKCS7_SIGN_ENVELOPE);
|
||||
pub fn PKCS7_DIGEST_free(info: *mut PKCS7_DIGEST);
|
||||
pub fn PKCS7_SIGNER_INFO_free(info: *mut PKCS7_SIGNER_INFO);
|
||||
pub fn PKCS7_ENCRYPT_free(enc: *mut PKCS7_ENCRYPT);
|
||||
pub fn PKCS7_ISSUER_AND_SERIAL_free(ias: *mut PKCS7_ISSUER_AND_SERIAL);
|
||||
pub fn PKCS7_RECIP_INFO_free(info: *mut PKCS7_RECIP_INFO);
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct PKCS7 {
|
||||
/*
|
||||
* The following is non NULL if it contains ASN1 encoding of this
|
||||
* structure
|
||||
*/
|
||||
pub asn1: *mut c_uchar,
|
||||
pub length: c_long,
|
||||
// # define PKCS7_S_HEADER 0
|
||||
// # define PKCS7_S_BODY 1
|
||||
// # define PKCS7_S_TAIL 2
|
||||
pub state: c_int, /* used during processing */
|
||||
pub detached: c_int,
|
||||
pub type_: *mut ASN1_OBJECT,
|
||||
/* content as defined by the type */
|
||||
/*
|
||||
* all encryption/message digests are applied to the 'contents', leaving
|
||||
* out the 'type' field.
|
||||
*/
|
||||
pub d: PKCS7_data,
|
||||
#[cfg(ossl300)]
|
||||
pub ctx: PKCS7_CTX,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub union PKCS7_data {
|
||||
pub ptr: *mut c_char,
|
||||
/* NID_pkcs7_data */
|
||||
pub data: *mut ASN1_OCTET_STRING,
|
||||
/* NID_pkcs7_signed */
|
||||
pub sign: *mut PKCS7_SIGNED,
|
||||
/* NID_pkcs7_enveloped */
|
||||
pub enveloped: *mut PKCS7_ENVELOPE,
|
||||
/* NID_pkcs7_signedAndEnveloped */
|
||||
pub signed_and_enveloped: *mut PKCS7_SIGN_ENVELOPE,
|
||||
/* NID_pkcs7_digest */
|
||||
pub digest: *mut PKCS7_DIGEST,
|
||||
/* NID_pkcs7_encrypted */
|
||||
pub encrypted: *mut PKCS7_ENCRYPT,
|
||||
/* Anything else */
|
||||
pub other: *mut ASN1_TYPE,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct PKCS7_ISSUER_AND_SERIAL {
|
||||
pub issuer: *mut X509_NAME,
|
||||
pub serial: *mut ASN1_INTEGER,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct PKCS7_SIGNER_INFO {
|
||||
pub version: *mut ASN1_INTEGER, /* version 1 */
|
||||
pub issuer_and_serial: *mut PKCS7_ISSUER_AND_SERIAL,
|
||||
pub digest_alg: *mut X509_ALGOR,
|
||||
pub auth_attr: *mut stack_st_X509_ATTRIBUTE, /* [ 0 ] */
|
||||
pub digest_enc_alg: *mut X509_ALGOR,
|
||||
pub enc_digest: *mut ASN1_OCTET_STRING,
|
||||
pub unauth_attr: *mut stack_st_X509_ATTRIBUTE, /* [ 1 ] */
|
||||
pub pkey: *mut EVP_PKEY, /* The private key to sign with */
|
||||
#[cfg(ossl300)]
|
||||
pub ctx: *const PKCS7_CTX,
|
||||
}
|
||||
|
||||
stack!(stack_st_PKCS7_SIGNER_INFO);
|
||||
|
||||
#[repr(C)]
|
||||
pub struct PKCS7_RECIP_INFO {
|
||||
pub version: *mut ASN1_INTEGER, /* version 0 */
|
||||
pub issuer_and_serial: *mut PKCS7_ISSUER_AND_SERIAL,
|
||||
pub key_enc_algor: *mut X509_ALGOR,
|
||||
pub enc_key: *mut ASN1_OCTET_STRING,
|
||||
pub cert: *mut X509, /* get the pub-key from this */
|
||||
#[cfg(ossl300)]
|
||||
pub ctx: *const PKCS7_CTX,
|
||||
}
|
||||
|
||||
stack!(stack_st_PKCS7_RECIP_INFO);
|
||||
|
||||
extern "C" {
|
||||
pub fn d2i_PKCS7(a: *mut *mut PKCS7, pp: *mut *const c_uchar, length: c_long) -> *mut PKCS7;
|
||||
@@ -15,6 +152,7 @@ extern "C" {
|
||||
const_ptr_api! {
|
||||
extern "C" {
|
||||
pub fn i2d_PKCS7(a: #[const_ptr_if(ossl300)] PKCS7, buf: *mut *mut u8) -> c_int;
|
||||
pub fn i2d_PKCS7_bio(bio: *mut BIO, p7: #[const_ptr_if(ossl300)] PKCS7) -> c_int;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,4 +205,53 @@ extern "C" {
|
||||
) -> c_int;
|
||||
|
||||
pub fn SMIME_read_PKCS7(bio: *mut BIO, bcont: *mut *mut BIO) -> *mut PKCS7;
|
||||
|
||||
pub fn PKCS7_new() -> *mut PKCS7;
|
||||
|
||||
pub fn PKCS7_set_type(p7: *mut PKCS7, nid_pkcs7: c_int) -> c_int;
|
||||
|
||||
pub fn PKCS7_add_certificate(p7: *mut PKCS7, x509: *mut X509) -> c_int;
|
||||
|
||||
pub fn PKCS7_add_signature(
|
||||
p7: *mut PKCS7,
|
||||
x509: *mut X509,
|
||||
pkey: *mut EVP_PKEY,
|
||||
digest: *const EVP_MD,
|
||||
) -> *mut PKCS7_SIGNER_INFO;
|
||||
|
||||
pub fn PKCS7_set_signed_attributes(
|
||||
p7si: *mut PKCS7_SIGNER_INFO,
|
||||
attributes: *mut stack_st_X509_ATTRIBUTE,
|
||||
) -> c_int;
|
||||
|
||||
pub fn PKCS7_add_signed_attribute(
|
||||
p7si: *mut PKCS7_SIGNER_INFO,
|
||||
nid: c_int,
|
||||
attrtype: c_int,
|
||||
data: *mut c_void,
|
||||
) -> c_int;
|
||||
|
||||
pub fn PKCS7_content_new(p7: *mut PKCS7, nid_pkcs7: c_int) -> c_int;
|
||||
|
||||
pub fn PKCS7_dataInit(p7: *mut PKCS7, bio: *mut BIO) -> *mut BIO;
|
||||
|
||||
pub fn PKCS7_dataFinal(p7: *mut PKCS7, bio: *mut BIO) -> c_int;
|
||||
|
||||
pub fn PKCS7_get_signer_info(p7: *mut PKCS7) -> *mut stack_st_PKCS7_SIGNER_INFO;
|
||||
|
||||
pub fn PKCS7_SIGNER_INFO_get0_algs(
|
||||
si: *mut PKCS7_SIGNER_INFO,
|
||||
pk: *mut *mut EVP_PKEY,
|
||||
pdig: *mut *mut X509_ALGOR,
|
||||
psig: *mut *mut X509_ALGOR,
|
||||
);
|
||||
}
|
||||
|
||||
const_ptr_api! {
|
||||
extern "C" {
|
||||
pub fn PKCS7_get_signed_attribute(
|
||||
si: #[const_ptr_if(ossl300)] PKCS7_SIGNER_INFO,
|
||||
nid: c_int
|
||||
) -> *mut ASN1_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
use super::super::*;
|
||||
use libc::*;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(libressl)] {
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct poly1305_context {
|
||||
pub aligner: usize,
|
||||
pub opaque: [::libc::c_uchar; 136usize],
|
||||
}
|
||||
pub type poly1305_state = poly1305_context;
|
||||
extern "C" {
|
||||
pub fn CRYPTO_poly1305_init(ctx: *mut poly1305_context, key: *const ::libc::c_uchar);
|
||||
pub fn CRYPTO_poly1305_update(
|
||||
ctx: *mut poly1305_context,
|
||||
in_: *const ::libc::c_uchar,
|
||||
len: usize,
|
||||
);
|
||||
pub fn CRYPTO_poly1305_finish(ctx: *mut poly1305_context, mac: *mut ::libc::c_uchar);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -648,6 +648,15 @@ extern "C" {
|
||||
num: size_t,
|
||||
readbytes: *mut size_t,
|
||||
) -> c_int;
|
||||
#[cfg(ossl111)]
|
||||
pub fn SSL_bytes_to_cipher_list(
|
||||
s: *mut SSL,
|
||||
bytes: *const c_uchar,
|
||||
len: size_t,
|
||||
isv2format: c_int,
|
||||
sk: *mut *mut stack_st_SSL_CIPHER,
|
||||
scsvs: *mut *mut stack_st_SSL_CIPHER,
|
||||
) -> c_int;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
@@ -905,9 +914,13 @@ extern "C" {
|
||||
#[cfg(ossl111)]
|
||||
pub fn SSL_set_num_tickets(s: *mut SSL, num_tickets: size_t) -> c_int;
|
||||
|
||||
#[cfg(ossl111)]
|
||||
#[cfg(ossl111b)]
|
||||
pub fn SSL_CTX_get_num_tickets(ctx: *const SSL_CTX) -> size_t;
|
||||
#[cfg(all(ossl111, not(ossl111b)))]
|
||||
pub fn SSL_CTX_get_num_tickets(ctx: *mut SSL_CTX) -> size_t;
|
||||
|
||||
#[cfg(ossl111)]
|
||||
#[cfg(ossl111b)]
|
||||
pub fn SSL_get_num_tickets(s: *const SSL) -> size_t;
|
||||
#[cfg(all(ossl111, not(ossl111b)))]
|
||||
pub fn SSL_get_num_tickets(s: *mut SSL) -> size_t;
|
||||
}
|
||||
|
||||
@@ -3,14 +3,27 @@ use libc::*;
|
||||
#[allow(unused_imports)]
|
||||
use super::super::*;
|
||||
|
||||
pub enum ASN1_OBJECT {}
|
||||
pub enum ASN1_VALUE {}
|
||||
|
||||
pub type ASN1_BOOLEAN = c_int;
|
||||
pub enum ASN1_INTEGER {}
|
||||
pub enum ASN1_ENUMERATED {}
|
||||
pub enum ASN1_GENERALIZEDTIME {}
|
||||
pub enum ASN1_STRING {}
|
||||
pub enum ASN1_BIT_STRING {}
|
||||
pub enum ASN1_TIME {}
|
||||
pub enum ASN1_TYPE {}
|
||||
pub enum ASN1_OBJECT {}
|
||||
pub enum ASN1_OCTET_STRING {}
|
||||
pub enum ASN1_NULL {}
|
||||
pub enum ASN1_PRINTABLESTRING {}
|
||||
pub enum ASN1_T61STRING {}
|
||||
pub enum ASN1_IA5STRING {}
|
||||
pub enum ASN1_GENERALSTRING {}
|
||||
pub enum ASN1_BMPSTRING {}
|
||||
pub enum ASN1_UNIVERSALSTRING {}
|
||||
pub enum ASN1_UTCTIME {}
|
||||
pub enum ASN1_VISIBLESTRING {}
|
||||
pub enum ASN1_UTF8STRING {}
|
||||
|
||||
pub enum bio_st {} // FIXME remove
|
||||
cfg_if! {
|
||||
@@ -112,6 +125,8 @@ pub enum EVP_PKEY_ASN1_METHOD {}
|
||||
|
||||
pub enum EVP_PKEY_CTX {}
|
||||
|
||||
pub enum CMAC_CTX {}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl110, libressl280))] {
|
||||
pub enum HMAC_CTX {}
|
||||
@@ -325,6 +340,8 @@ cfg_if! {
|
||||
}
|
||||
}
|
||||
|
||||
stack!(stack_st_X509_ALGOR);
|
||||
|
||||
pub enum X509_LOOKUP_METHOD {}
|
||||
|
||||
pub enum X509_NAME {}
|
||||
|
||||
@@ -9,12 +9,16 @@ pub struct X509_VAL {
|
||||
|
||||
pub enum X509_NAME_ENTRY {}
|
||||
|
||||
stack!(stack_st_X509_NAME_ENTRY);
|
||||
|
||||
stack!(stack_st_X509_NAME);
|
||||
|
||||
pub enum X509_EXTENSION {}
|
||||
|
||||
stack!(stack_st_X509_EXTENSION);
|
||||
|
||||
pub enum X509_ATTRIBUTE {}
|
||||
|
||||
stack!(stack_st_X509_ATTRIBUTE);
|
||||
|
||||
cfg_if! {
|
||||
@@ -274,6 +278,7 @@ extern "C" {
|
||||
pub fn X509_NAME_ENTRY_free(x: *mut X509_NAME_ENTRY);
|
||||
|
||||
pub fn X509_NAME_new() -> *mut X509_NAME;
|
||||
pub fn X509_NAME_cmp(x: *const X509_NAME, y: *const X509_NAME) -> c_int;
|
||||
pub fn X509_NAME_free(x: *mut X509_NAME);
|
||||
|
||||
pub fn X509_new() -> *mut X509;
|
||||
@@ -359,6 +364,33 @@ const_ptr_api! {
|
||||
-> c_int;
|
||||
}
|
||||
}
|
||||
extern "C" {
|
||||
pub fn X509_REQ_get_attr_count(req: *const X509_REQ) -> c_int;
|
||||
pub fn X509_REQ_get_attr_by_NID(req: *const X509_REQ, nid: c_int, lastpos: c_int) -> c_int;
|
||||
pub fn X509_REQ_get_attr(req: *const X509_REQ, loc: c_int) -> *mut X509_ATTRIBUTE;
|
||||
pub fn X509_REQ_delete_attr(req: *mut X509_REQ, loc: c_int) -> *mut X509_ATTRIBUTE;
|
||||
pub fn X509_REQ_add1_attr_by_txt(
|
||||
req: *mut X509_REQ,
|
||||
attrname: *const c_char,
|
||||
chtype: c_int,
|
||||
bytes: *const c_uchar,
|
||||
len: c_int,
|
||||
) -> c_int;
|
||||
pub fn X509_REQ_add1_attr_by_NID(
|
||||
req: *mut X509_REQ,
|
||||
nid: c_int,
|
||||
chtype: c_int,
|
||||
bytes: *const c_uchar,
|
||||
len: c_int,
|
||||
) -> c_int;
|
||||
pub fn X509_REQ_add1_attr_by_OBJ(
|
||||
req: *mut X509_REQ,
|
||||
obj: *const ASN1_OBJECT,
|
||||
chtype: c_int,
|
||||
bytes: *const c_uchar,
|
||||
len: c_int,
|
||||
) -> c_int;
|
||||
}
|
||||
extern "C" {
|
||||
pub fn X509_set_pubkey(x: *mut X509, pkey: *mut EVP_PKEY) -> c_int;
|
||||
pub fn X509_REQ_verify(req: *mut X509_REQ, pkey: *mut EVP_PKEY) -> c_int;
|
||||
@@ -612,10 +644,9 @@ const_ptr_api! {
|
||||
extern "C" {
|
||||
#[cfg(any(ossl110, libressl270))]
|
||||
pub fn X509_STORE_get0_objects(ctx: #[const_ptr_if(ossl300)] X509_STORE) -> *mut stack_st_X509_OBJECT;
|
||||
#[cfg(ossl300)]
|
||||
pub fn X509_STORE_get1_all_certs(ctx: *mut X509_STORE) -> *mut stack_st_X509;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(ossl110, libressl270))]
|
||||
extern "C" {
|
||||
pub fn X509_OBJECT_get0_X509(x: *const X509_OBJECT) -> *mut X509;
|
||||
@@ -642,7 +673,6 @@ extern "C" {
|
||||
|
||||
extern "C" {
|
||||
pub fn X509_cmp(a: *const X509, b: *const X509) -> c_int;
|
||||
pub fn X509_NAME_cmp(a: *const X509_NAME, b: *const X509_NAME) -> c_int;
|
||||
pub fn X509_issuer_and_serial_cmp(a: *const X509, b: *const X509) -> c_int;
|
||||
pub fn X509_issuer_name_cmp(a: *const X509, b: *const X509) -> c_int;
|
||||
pub fn X509_subject_name_cmp(a: *const X509, b: *const X509) -> c_int;
|
||||
@@ -670,6 +700,68 @@ pub struct X509_PURPOSE {
|
||||
const_ptr_api! {
|
||||
extern "C" {
|
||||
pub fn X509_PURPOSE_get_by_sname(sname: #[const_ptr_if(any(ossl110, libressl280))] c_char) -> c_int;
|
||||
pub fn X509_PURPOSE_get0(idx: c_int) -> *mut X509_PURPOSE;
|
||||
}
|
||||
}
|
||||
extern "C" {
|
||||
pub fn X509_PURPOSE_get0(idx: c_int) -> *mut X509_PURPOSE;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
pub fn X509_ATTRIBUTE_new() -> *mut X509_ATTRIBUTE;
|
||||
pub fn X509_ATTRIBUTE_free(attr: *mut X509_ATTRIBUTE);
|
||||
pub fn X509_ATTRIBUTE_create(
|
||||
nid: c_int,
|
||||
atrtype: c_int,
|
||||
value: *mut c_void,
|
||||
) -> *mut X509_ATTRIBUTE;
|
||||
pub fn X509_ATTRIBUTE_create_by_NID(
|
||||
attr: *mut *mut X509_ATTRIBUTE,
|
||||
nid: c_int,
|
||||
atrtype: c_int,
|
||||
data: *const c_void,
|
||||
len: c_int,
|
||||
) -> *mut X509_ATTRIBUTE;
|
||||
pub fn X509_ATTRIBUTE_create_by_OBJ(
|
||||
attr: *mut *mut X509_ATTRIBUTE,
|
||||
obj: *const ASN1_OBJECT,
|
||||
atrtype: c_int,
|
||||
data: *const c_void,
|
||||
len: c_int,
|
||||
) -> *mut X509_ATTRIBUTE;
|
||||
pub fn X509_ATTRIBUTE_create_by_txt(
|
||||
attr: *mut *mut X509_ATTRIBUTE,
|
||||
atrname: *const c_char,
|
||||
atrtype: c_int,
|
||||
bytes: *const c_uchar,
|
||||
len: c_int,
|
||||
) -> *mut X509_ATTRIBUTE;
|
||||
pub fn X509_ATTRIBUTE_set1_object(attr: *mut X509_ATTRIBUTE, obj: *const ASN1_OBJECT) -> c_int;
|
||||
pub fn X509_ATTRIBUTE_set1_data(
|
||||
attr: *mut X509_ATTRIBUTE,
|
||||
attrtype: c_int,
|
||||
data: *const c_void,
|
||||
len: c_int,
|
||||
) -> c_int;
|
||||
pub fn X509_ATTRIBUTE_get0_data(
|
||||
attr: *mut X509_ATTRIBUTE,
|
||||
idx: c_int,
|
||||
atrtype: c_int,
|
||||
data: *mut c_void,
|
||||
) -> *mut c_void;
|
||||
pub fn X509_ATTRIBUTE_get0_object(attr: *mut X509_ATTRIBUTE) -> *mut ASN1_OBJECT;
|
||||
pub fn X509_ATTRIBUTE_get0_type(attr: *mut X509_ATTRIBUTE, idx: c_int) -> *mut ASN1_TYPE;
|
||||
pub fn d2i_X509_ATTRIBUTE(
|
||||
a: *mut *mut X509_ATTRIBUTE,
|
||||
pp: *mut *const c_uchar,
|
||||
length: c_long,
|
||||
) -> *mut X509_ATTRIBUTE;
|
||||
}
|
||||
const_ptr_api! {
|
||||
extern "C" {
|
||||
pub fn X509_ATTRIBUTE_count(
|
||||
attr: #[const_ptr_if(any(ossl110, libressl280))] X509_ATTRIBUTE // const since OpenSSL v1.1.0
|
||||
) -> c_int;
|
||||
pub fn i2d_X509_ATTRIBUTE(x: #[const_ptr_if(ossl300)] X509_ATTRIBUTE, buf: *mut *mut u8) -> c_int;
|
||||
pub fn X509_ATTRIBUTE_dup(x: #[const_ptr_if(ossl300)] X509_ATTRIBUTE) -> *mut X509_ATTRIBUTE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,11 @@ pub enum CONF_METHOD {}
|
||||
extern "C" {
|
||||
pub fn GENERAL_NAME_new() -> *mut GENERAL_NAME;
|
||||
pub fn GENERAL_NAME_free(name: *mut GENERAL_NAME);
|
||||
pub fn GENERAL_NAME_set0_othername(
|
||||
gen: *mut GENERAL_NAME,
|
||||
oid: *mut ASN1_OBJECT,
|
||||
value: *mut ASN1_TYPE,
|
||||
) -> c_int;
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
@@ -96,10 +101,47 @@ extern "C" {
|
||||
indent: c_int,
|
||||
) -> c_int;
|
||||
|
||||
#[cfg(ossl110)]
|
||||
pub fn X509_get_pathlen(x: *mut X509) -> c_long;
|
||||
#[cfg(ossl110)]
|
||||
pub fn X509_get_extension_flags(x: *mut X509) -> u32;
|
||||
#[cfg(ossl110)]
|
||||
pub fn X509_get_key_usage(x: *mut X509) -> u32;
|
||||
#[cfg(ossl110)]
|
||||
pub fn X509_get_extended_key_usage(x: *mut X509) -> u32;
|
||||
#[cfg(ossl110)]
|
||||
pub fn X509_get0_subject_key_id(x: *mut X509) -> *const ASN1_OCTET_STRING;
|
||||
#[cfg(ossl110)]
|
||||
pub fn X509_get0_authority_key_id(x: *mut X509) -> *const ASN1_OCTET_STRING;
|
||||
#[cfg(ossl111d)]
|
||||
pub fn X509_get0_authority_issuer(x: *mut X509) -> *const stack_st_GENERAL_NAME;
|
||||
#[cfg(ossl111d)]
|
||||
pub fn X509_get0_authority_serial(x: *mut X509) -> *const ASN1_INTEGER;
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct DIST_POINT_NAME {
|
||||
pub type_: c_int,
|
||||
pub name: DIST_POINT_NAME_st_anon_union,
|
||||
pub dpname: *mut X509_NAME,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub union DIST_POINT_NAME_st_anon_union {
|
||||
pub fullname: *mut stack_st_GENERAL_NAME,
|
||||
pub relativename: *mut stack_st_X509_NAME_ENTRY,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct DIST_POINT {
|
||||
pub distpoint: *mut DIST_POINT_NAME,
|
||||
pub reasons: *mut ASN1_BIT_STRING,
|
||||
pub CRLissuer: *mut stack_st_GENERAL_NAME,
|
||||
pub dp_reasons: c_int,
|
||||
}
|
||||
stack!(stack_st_DIST_POINT);
|
||||
|
||||
extern "C" {
|
||||
pub fn DIST_POINT_free(dist_point: *mut DIST_POINT);
|
||||
pub fn DIST_POINT_NAME_free(dist_point: *mut DIST_POINT_NAME);
|
||||
}
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
#![allow(
|
||||
clippy::missing_safety_doc,
|
||||
clippy::unreadable_literal,
|
||||
clippy::uninlined_format_args,
|
||||
clippy::upper_case_acronyms,
|
||||
dead_code,
|
||||
non_camel_case_types,
|
||||
non_snake_case,
|
||||
non_upper_case_globals,
|
||||
overflowing_literals,
|
||||
unused_imports
|
||||
)]
|
||||
#![cfg_attr(feature = "unstable_boringssl", allow(ambiguous_glob_reexports))]
|
||||
#![doc(html_root_url = "https://docs.rs/openssl-sys/0.9")]
|
||||
#![recursion_limit = "128"] // configure fixed limit across all rust versions
|
||||
|
||||
|
||||
@@ -70,24 +70,6 @@ macro_rules! stack {
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(const_fn)]
|
||||
macro_rules! const_fn {
|
||||
($(pub const fn $name:ident($($arg:ident: $t:ty),*) -> $ret:ty $b:block)*) => {
|
||||
$(
|
||||
pub const fn $name($($arg: $t),*) -> $ret $b
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(const_fn))]
|
||||
macro_rules! const_fn {
|
||||
($(pub const fn $name:ident($($arg:ident: $t:ty),*) -> $ret:ty $b:block)*) => {
|
||||
$(
|
||||
pub fn $name($($arg: $t),*) -> $ret $b
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
// openssl changes `*mut` to `*const` in certain parameters in certain versions;
|
||||
// in C this is ABI and (mostly) API compatible.
|
||||
//
|
||||
|
||||
@@ -927,12 +927,16 @@ pub const NID_X448: c_int = 1035;
|
||||
#[cfg(ossl110)]
|
||||
pub const NID_hkdf: c_int = 1036;
|
||||
#[cfg(ossl111)]
|
||||
pub const NID_poly1305: c_int = 1061;
|
||||
#[cfg(ossl111)]
|
||||
pub const NID_ED25519: c_int = 1087;
|
||||
#[cfg(libressl370)]
|
||||
pub const NID_ED25519: c_int = 952;
|
||||
#[cfg(ossl111)]
|
||||
pub const NID_ED448: c_int = 1088;
|
||||
#[cfg(ossl111)]
|
||||
pub const NID_sm2: c_int = 1172;
|
||||
#[cfg(ossl111)]
|
||||
pub const NID_sm3: c_int = 1143;
|
||||
#[cfg(libressl291)]
|
||||
pub const NID_sm3: c_int = 968;
|
||||
|
||||
@@ -10,6 +10,10 @@ pub const TLS1_2_VERSION: c_int = 0x303;
|
||||
#[cfg(any(ossl111, libressl340))]
|
||||
pub const TLS1_3_VERSION: c_int = 0x304;
|
||||
|
||||
pub const DTLS1_VERSION: c_int = 0xFEFF;
|
||||
#[cfg(any(ossl102, libressl332))]
|
||||
pub const DTLS1_2_VERSION: c_int = 0xFEFD;
|
||||
|
||||
pub const TLS1_AD_DECODE_ERROR: c_int = 50;
|
||||
pub const TLS1_AD_UNRECOGNIZED_NAME: c_int = 112;
|
||||
|
||||
|
||||
@@ -91,3 +91,14 @@ pub const X509_PURPOSE_OCSP_HELPER: c_int = 8;
|
||||
pub const X509_PURPOSE_TIMESTAMP_SIGN: c_int = 9;
|
||||
pub const X509_PURPOSE_MIN: c_int = 1;
|
||||
pub const X509_PURPOSE_MAX: c_int = 9;
|
||||
|
||||
pub const CRL_REASON_UNSPECIFIED: c_int = 0;
|
||||
pub const CRL_REASON_KEY_COMPROMISE: c_int = 1;
|
||||
pub const CRL_REASON_CA_COMPROMISE: c_int = 2;
|
||||
pub const CRL_REASON_AFFILIATION_CHANGED: c_int = 3;
|
||||
pub const CRL_REASON_SUPERSEDED: c_int = 4;
|
||||
pub const CRL_REASON_CESSATION_OF_OPERATION: c_int = 5;
|
||||
pub const CRL_REASON_CERTIFICATE_HOLD: c_int = 6;
|
||||
pub const CRL_REASON_REMOVE_FROM_CRL: c_int = 8;
|
||||
pub const CRL_REASON_PRIVILEGE_WITHDRAWN: c_int = 9;
|
||||
pub const CRL_REASON_AA_COMPROMISE: c_int = 10;
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ ohos_cargo_crate("lib") {
|
||||
|
||||
sources = [ "src/lib.rs" ]
|
||||
edition = "2018"
|
||||
cargo_pkg_version = "0.10.47"
|
||||
cargo_pkg_version = "0.10.56"
|
||||
cargo_pkg_authors = "Steven Fackler <sfackler@gmail.com>"
|
||||
cargo_pkg_name = "openssl"
|
||||
cargo_pkg_description = "OpenSSL bindings"
|
||||
|
||||
+89
-1
@@ -2,6 +2,86 @@
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [v0.10.56] - 2023-08-06
|
||||
|
||||
## Added
|
||||
|
||||
* Added `BigNumRef::mod_sqrt`.
|
||||
* Added `PkeyCtxRef::set_signature_md` and `PkeyCtxRef::set_rsa_pss_saltlen`.
|
||||
* Added `PkeyCtxRef::verify_recover_init` and `PkeyCtxRef::verify_recover`.
|
||||
* Added `BigNumRef::is_even` and `BigNumRef::is_odd`.
|
||||
* Added `EcPointRef::to_hex_str` and `EcPoint::from_hex_str`.
|
||||
* Added support for AES key wrap and wrap pad.
|
||||
|
||||
## [v0.10.55] - 2023-06-20
|
||||
|
||||
### Fixed
|
||||
|
||||
* Fixed compilation with the latest version of BoringSSL.
|
||||
* Fixed compilation when OpenSSL is compiled with `OPENSSL_NO_OCB`.
|
||||
* Fixed a segfault in `X509VerifyParamRef::set_host` when called with an empty string.
|
||||
|
||||
### Added
|
||||
|
||||
* Added `Deriver::set_peer_ex`.
|
||||
* Added `EcGroupRef::asn1_flag`.
|
||||
* Exposed `EcPointRef::affine_coordinates` on BoringSSL and LibreSSL.
|
||||
* Added `Nid::SM2` and `Id::SM2`
|
||||
|
||||
## [v0.10.54] - 2023-05-31
|
||||
|
||||
### Fixed
|
||||
|
||||
* `PKey::private_key_to_pkcs8_passphrase` no longer panics if a `passphrase` contains a NUL byte.
|
||||
|
||||
## [v0.10.53] - 2023-05-30
|
||||
|
||||
### Added
|
||||
|
||||
* Added `Dsa::from_pqg`, `Dsa::generate_key`, and `Dsa::generate_params`.
|
||||
* Added `SslRef::bytes_to_cipher_list`.
|
||||
* Added `SubjectAlternativeName::other_name2`
|
||||
|
||||
## [v0.10.52] - 2023-04-24
|
||||
|
||||
### Added
|
||||
|
||||
* Added `DhRef::check_key`.
|
||||
* Added `Id::POLY1305`.
|
||||
* Added `X509Ref::subject_key_id`, `X509Ref::authority_key_id`, `X509Ref::authority_issuer`, and `X509Ref::authority_serial`.
|
||||
|
||||
|
||||
## [v0.10.51] - 2023-04-20
|
||||
|
||||
### Added
|
||||
|
||||
* Added `X509RevokedRef::issuer_name` and `X509RevokedRef::reason_code`.
|
||||
* Added `Dh::set_key` and `Dh::set_public_key`
|
||||
* Added `Asn1OctetString` and `Asn1OctetStringRef1`
|
||||
* Added `X509Extension::new_from_der`
|
||||
|
||||
### Deprecated
|
||||
|
||||
* Deprecated `X509Extension::new` and `X509Extension::new_nid` in favor of `X509Extension::new_from_der` and the `extensions` module.
|
||||
* Deprecated `X509Extension::add_alias`, it is not required with `new_from_der` or the `extensions` module.
|
||||
|
||||
## [v0.10.50] - 2023-04-09
|
||||
|
||||
### Added
|
||||
|
||||
* Added `CipherCtxRef::cipher_update_inplace`.
|
||||
|
||||
## [v0.10.49] - 2023-04-01
|
||||
|
||||
### Fixed
|
||||
|
||||
* `SslConnector` no longer sets the SNI extension when connecting to an IP address.
|
||||
|
||||
### Added
|
||||
|
||||
* Implemented `Ord`, `PartialOrd`, `Eq`, and `PartialEq` for `Asn1Integer` and `Asn1IntegerRef`.
|
||||
* Added `X509Ref::crl_distribution_points`, and `DistPoint`.
|
||||
|
||||
## [v0.10.48] - 2023-03-23
|
||||
|
||||
### Fixed
|
||||
@@ -707,7 +787,15 @@
|
||||
|
||||
Look at the [release tags] for information about older releases.
|
||||
|
||||
[Unreleased]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.48...master
|
||||
[Unreleased]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.56...master
|
||||
[v0.10.56]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.55...openssl-v0.10.56
|
||||
[v0.10.55]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.54...openssl-v0.10.55
|
||||
[v0.10.54]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.53...openssl-v0.10.54
|
||||
[v0.10.53]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.52...openssl-v0.10.53
|
||||
[v0.10.52]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.51...openssl-v0.10.52
|
||||
[v0.10.51]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.50...openssl-v0.10.51
|
||||
[v0.10.50]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.49...openssl-v0.10.50
|
||||
[v0.10.49]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.48...openssl-v0.10.49
|
||||
[v0.10.48]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.47...openssl-v0.10.48
|
||||
[v0.10.47]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.46...openssl-v0.10.47
|
||||
[v0.10.46]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.45...openssl-v0.10.46
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "openssl"
|
||||
version = "0.10.48"
|
||||
version = "0.10.56"
|
||||
authors = ["Steven Fackler <sfackler@gmail.com>"]
|
||||
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.83", path = "../openssl-sys" }
|
||||
ffi = { package = "openssl-sys", version = "0.9.91", path = "../openssl-sys" }
|
||||
|
||||
[dev-dependencies]
|
||||
hex = "0.3"
|
||||
|
||||
+139
-2
@@ -27,8 +27,8 @@
|
||||
use cfg_if::cfg_if;
|
||||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
use libc::{c_char, c_int, c_long, time_t};
|
||||
#[cfg(ossl102)]
|
||||
use std::cmp::Ordering;
|
||||
use std::convert::TryInto;
|
||||
use std::ffi::CString;
|
||||
use std::fmt;
|
||||
use std::ptr;
|
||||
@@ -512,6 +512,23 @@ impl Asn1Integer {
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Asn1Integer {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
Asn1IntegerRef::cmp(self, other)
|
||||
}
|
||||
}
|
||||
impl PartialOrd for Asn1Integer {
|
||||
fn partial_cmp(&self, other: &Asn1Integer) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
impl Eq for Asn1Integer {}
|
||||
impl PartialEq for Asn1Integer {
|
||||
fn eq(&self, other: &Asn1Integer) -> bool {
|
||||
Asn1IntegerRef::eq(self, other)
|
||||
}
|
||||
}
|
||||
|
||||
impl Asn1IntegerRef {
|
||||
#[allow(missing_docs, clippy::unnecessary_cast)]
|
||||
#[deprecated(since = "0.10.6", note = "use to_bn instead")]
|
||||
@@ -536,6 +553,30 @@ impl Asn1IntegerRef {
|
||||
pub fn set(&mut self, value: i32) -> Result<(), ErrorStack> {
|
||||
unsafe { cvt(ffi::ASN1_INTEGER_set(self.as_ptr(), value as c_long)).map(|_| ()) }
|
||||
}
|
||||
|
||||
/// Creates a new Asn1Integer with the same value.
|
||||
#[corresponds(ASN1_INTEGER_dup)]
|
||||
pub fn to_owned(&self) -> Result<Asn1Integer, ErrorStack> {
|
||||
unsafe { cvt_p(ffi::ASN1_INTEGER_dup(self.as_ptr())).map(|p| Asn1Integer::from_ptr(p)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Asn1IntegerRef {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
let res = unsafe { ffi::ASN1_INTEGER_cmp(self.as_ptr(), other.as_ptr()) };
|
||||
res.cmp(&0)
|
||||
}
|
||||
}
|
||||
impl PartialOrd for Asn1IntegerRef {
|
||||
fn partial_cmp(&self, other: &Asn1IntegerRef) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
impl Eq for Asn1IntegerRef {}
|
||||
impl PartialEq for Asn1IntegerRef {
|
||||
fn eq(&self, other: &Asn1IntegerRef) -> bool {
|
||||
self.cmp(other) == Ordering::Equal
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
@@ -571,9 +612,50 @@ impl Asn1BitStringRef {
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::ASN1_OCTET_STRING;
|
||||
fn drop = ffi::ASN1_OCTET_STRING_free;
|
||||
/// ASN.1 OCTET STRING type
|
||||
pub struct Asn1OctetString;
|
||||
/// A reference to an [`Asn1OctetString`].
|
||||
pub struct Asn1OctetStringRef;
|
||||
}
|
||||
|
||||
impl Asn1OctetString {
|
||||
/// Creates an Asn1OctetString from bytes
|
||||
pub fn new_from_bytes(value: &[u8]) -> Result<Self, ErrorStack> {
|
||||
ffi::init();
|
||||
unsafe {
|
||||
let s = cvt_p(ffi::ASN1_OCTET_STRING_new())?;
|
||||
ffi::ASN1_OCTET_STRING_set(s, value.as_ptr(), value.len().try_into().unwrap());
|
||||
Ok(Self::from_ptr(s))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Asn1OctetStringRef {
|
||||
/// Returns the octet string as an array of bytes.
|
||||
#[corresponds(ASN1_STRING_get0_data)]
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
unsafe { slice::from_raw_parts(ASN1_STRING_get0_data(self.as_ptr().cast()), self.len()) }
|
||||
}
|
||||
|
||||
/// Returns the number of bytes in the octet string.
|
||||
#[corresponds(ASN1_STRING_length)]
|
||||
pub fn len(&self) -> usize {
|
||||
unsafe { ffi::ASN1_STRING_length(self.as_ptr().cast()) as usize }
|
||||
}
|
||||
|
||||
/// Determines if the string is empty.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::ASN1_OBJECT;
|
||||
fn drop = ffi::ASN1_OBJECT_free;
|
||||
fn clone = ffi::OBJ_dup;
|
||||
|
||||
/// Object Identifier
|
||||
///
|
||||
@@ -656,7 +738,7 @@ impl fmt::Debug for Asn1ObjectRef {
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl110, libressl273))] {
|
||||
if #[cfg(any(ossl110, libressl273, boringssl))] {
|
||||
use ffi::ASN1_STRING_get0_data;
|
||||
} else {
|
||||
#[allow(bad_style)]
|
||||
@@ -666,6 +748,32 @@ cfg_if! {
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::ASN1_ENUMERATED;
|
||||
fn drop = ffi::ASN1_ENUMERATED_free;
|
||||
|
||||
/// An ASN.1 enumerated.
|
||||
pub struct Asn1Enumerated;
|
||||
/// A reference to an [`Asn1Enumerated`].
|
||||
pub struct Asn1EnumeratedRef;
|
||||
}
|
||||
|
||||
impl Asn1EnumeratedRef {
|
||||
/// Get the value, if it fits in the required bounds.
|
||||
#[corresponds(ASN1_ENUMERATED_get_int64)]
|
||||
#[cfg(ossl110)]
|
||||
pub fn get_i64(&self) -> Result<i64, ErrorStack> {
|
||||
let mut crl_reason = 0;
|
||||
unsafe {
|
||||
cvt(ffi::ASN1_ENUMERATED_get_int64(
|
||||
&mut crl_reason,
|
||||
self.as_ptr(),
|
||||
))?;
|
||||
}
|
||||
Ok(crl_reason)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -749,6 +857,28 @@ mod tests {
|
||||
assert!(c_ref < a_ref);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn integer_to_owned() {
|
||||
let a = Asn1Integer::from_bn(&BigNum::from_dec_str("42").unwrap()).unwrap();
|
||||
let b = a.to_owned().unwrap();
|
||||
assert_eq!(
|
||||
a.to_bn().unwrap().to_dec_str().unwrap().to_string(),
|
||||
b.to_bn().unwrap().to_dec_str().unwrap().to_string(),
|
||||
);
|
||||
assert_ne!(a.as_ptr(), b.as_ptr());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn integer_cmp() {
|
||||
let a = Asn1Integer::from_bn(&BigNum::from_dec_str("42").unwrap()).unwrap();
|
||||
let b = Asn1Integer::from_bn(&BigNum::from_dec_str("42").unwrap()).unwrap();
|
||||
let c = Asn1Integer::from_bn(&BigNum::from_dec_str("43").unwrap()).unwrap();
|
||||
assert!(a == b);
|
||||
assert!(a != c);
|
||||
assert!(a < c);
|
||||
assert!(c > b);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn object_from_str() {
|
||||
let object = Asn1Object::from_str("2.16.840.1.101.3.4.2.1").unwrap();
|
||||
@@ -771,4 +901,11 @@ mod tests {
|
||||
&[0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn asn1_octet_string() {
|
||||
let octet_string = Asn1OctetString::new_from_bytes(b"hello world").unwrap();
|
||||
assert_eq!(octet_string.as_slice(), b"hello world");
|
||||
assert_eq!(octet_string.len(), 11);
|
||||
}
|
||||
}
|
||||
|
||||
+61
-1
@@ -335,6 +335,20 @@ impl BigNumRef {
|
||||
unsafe { BN_is_negative(self.as_ptr()) == 1 }
|
||||
}
|
||||
|
||||
/// Returns `true` is `self` is even.
|
||||
#[corresponds(BN_is_even)]
|
||||
#[cfg(any(ossl110, boringssl, libressl350))]
|
||||
pub fn is_even(&self) -> bool {
|
||||
!self.is_odd()
|
||||
}
|
||||
|
||||
/// Returns `true` is `self` is odd.
|
||||
#[corresponds(BN_is_odd)]
|
||||
#[cfg(any(ossl110, boringssl, libressl350))]
|
||||
pub fn is_odd(&self) -> bool {
|
||||
unsafe { ffi::BN_is_odd(self.as_ptr()) == 1 }
|
||||
}
|
||||
|
||||
/// Returns the number of significant bits in `self`.
|
||||
#[corresponds(BN_num_bits)]
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
@@ -639,6 +653,26 @@ impl BigNumRef {
|
||||
}
|
||||
}
|
||||
|
||||
/// Places into `self` the modular square root of `a` such that `self^2 = a (mod p)`
|
||||
#[corresponds(BN_mod_sqrt)]
|
||||
#[cfg(ossl110)]
|
||||
pub fn mod_sqrt(
|
||||
&mut self,
|
||||
a: &BigNumRef,
|
||||
p: &BigNumRef,
|
||||
ctx: &mut BigNumContextRef,
|
||||
) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt_p(ffi::BN_mod_sqrt(
|
||||
self.as_ptr(),
|
||||
a.as_ptr(),
|
||||
p.as_ptr(),
|
||||
ctx.as_ptr(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Places the result of `a^p` in `self`.
|
||||
#[corresponds(BN_exp)]
|
||||
pub fn exp(
|
||||
@@ -814,7 +848,7 @@ impl BigNumRef {
|
||||
/// assert_eq!(&bn_vec, &[0, 0, 0x45, 0x43]);
|
||||
/// ```
|
||||
#[corresponds(BN_bn2binpad)]
|
||||
#[cfg(ossl110)]
|
||||
#[cfg(any(ossl110, libressl340, boringssl))]
|
||||
pub fn to_vec_padded(&self, pad_to: i32) -> Result<Vec<u8>, ErrorStack> {
|
||||
let mut v = Vec::with_capacity(pad_to as usize);
|
||||
unsafe {
|
||||
@@ -1455,4 +1489,30 @@ mod tests {
|
||||
b.set_const_time();
|
||||
assert!(b.is_const_time())
|
||||
}
|
||||
|
||||
#[cfg(ossl110)]
|
||||
#[test]
|
||||
fn test_mod_sqrt() {
|
||||
let mut ctx = BigNumContext::new().unwrap();
|
||||
|
||||
let s = BigNum::from_hex_str("47A8DD7626B9908C80ACD7E0D3344D69").unwrap();
|
||||
let p = BigNum::from_hex_str("81EF47265B58BCE5").unwrap();
|
||||
let mut out = BigNum::new().unwrap();
|
||||
|
||||
out.mod_sqrt(&s, &p, &mut ctx).unwrap();
|
||||
assert_eq!(out, BigNum::from_hex_str("7C6D179E19B97BDD").unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(ossl110, boringssl, libressl350))]
|
||||
fn test_odd_even() {
|
||||
let a = BigNum::from_u32(17).unwrap();
|
||||
let b = BigNum::from_u32(18).unwrap();
|
||||
|
||||
assert!(a.is_odd());
|
||||
assert!(!b.is_odd());
|
||||
|
||||
assert!(!a.is_even());
|
||||
assert!(b.is_even());
|
||||
}
|
||||
}
|
||||
|
||||
+54
-2
@@ -12,6 +12,7 @@ use foreign_types::{ForeignTypeRef, Opaque};
|
||||
use openssl_macros::corresponds;
|
||||
#[cfg(ossl300)]
|
||||
use std::ffi::CString;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
#[cfg(ossl300)]
|
||||
use std::ptr;
|
||||
|
||||
@@ -41,7 +42,6 @@ cfg_if! {
|
||||
cfg_if! {
|
||||
if #[cfg(ossl300)] {
|
||||
use foreign_types::ForeignType;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
type Inner = *mut ffi::EVP_CIPHER;
|
||||
|
||||
@@ -90,6 +90,22 @@ cfg_if! {
|
||||
}
|
||||
} else {
|
||||
enum Inner {}
|
||||
|
||||
impl Deref for Cipher {
|
||||
type Target = CipherRef;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &Self::Target {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Cipher {
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,7 +186,6 @@ impl Cipher {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_cfb8() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(boringssl))]
|
||||
pub fn aes_128_gcm() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_gcm() as *mut _) }
|
||||
}
|
||||
@@ -191,6 +206,18 @@ impl Cipher {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_ocb() as *mut _) }
|
||||
}
|
||||
|
||||
/// Requires OpenSSL 1.0.2 or newer.
|
||||
#[cfg(ossl102)]
|
||||
pub fn aes_128_wrap() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_wrap() as *mut _) }
|
||||
}
|
||||
|
||||
/// Requires OpenSSL 1.1.0 or newer.
|
||||
#[cfg(ossl110)]
|
||||
pub fn aes_128_wrap_pad() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_wrap_pad() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_192_ecb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_ecb() as *mut _) }
|
||||
}
|
||||
@@ -236,6 +263,18 @@ impl Cipher {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_ocb() as *mut _) }
|
||||
}
|
||||
|
||||
/// Requires OpenSSL 1.0.2 or newer.
|
||||
#[cfg(ossl102)]
|
||||
pub fn aes_192_wrap() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_wrap() as *mut _) }
|
||||
}
|
||||
|
||||
/// Requires OpenSSL 1.1.0 or newer.
|
||||
#[cfg(ossl110)]
|
||||
pub fn aes_192_wrap_pad() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_wrap_pad() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_256_ecb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_ecb() as *mut _) }
|
||||
}
|
||||
@@ -281,6 +320,18 @@ impl Cipher {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_ocb() as *mut _) }
|
||||
}
|
||||
|
||||
/// Requires OpenSSL 1.0.2 or newer.
|
||||
#[cfg(ossl102)]
|
||||
pub fn aes_256_wrap() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_wrap() as *mut _) }
|
||||
}
|
||||
|
||||
/// Requires OpenSSL 1.1.0 or newer.
|
||||
#[cfg(ossl110)]
|
||||
pub fn aes_256_wrap_pad() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_wrap_pad() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_BF"))]
|
||||
pub fn bf_cbc() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_bf_cbc() as *mut _) }
|
||||
@@ -324,6 +375,7 @@ impl Cipher {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_des_ede3_cfb64() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_RC4"))]
|
||||
pub fn rc4() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_rc4() as *mut _) }
|
||||
}
|
||||
|
||||
+259
-4
@@ -55,6 +55,8 @@ use crate::error::ErrorStack;
|
||||
#[cfg(not(boringssl))]
|
||||
use crate::pkey::{HasPrivate, HasPublic, PKey, PKeyRef};
|
||||
use crate::{cvt, cvt_p};
|
||||
#[cfg(ossl102)]
|
||||
use bitflags::bitflags;
|
||||
use cfg_if::cfg_if;
|
||||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
use libc::{c_int, c_uchar};
|
||||
@@ -80,6 +82,15 @@ foreign_type_and_impl_send_sync! {
|
||||
pub struct CipherCtxRef;
|
||||
}
|
||||
|
||||
#[cfg(ossl102)]
|
||||
bitflags! {
|
||||
/// Flags for `EVP_CIPHER_CTX`.
|
||||
pub struct CipherCtxFlags : c_int {
|
||||
/// The flag used to opt into AES key wrap ciphers.
|
||||
const FLAG_WRAP_ALLOW = ffi::EVP_CIPHER_CTX_FLAG_WRAP_ALLOW;
|
||||
}
|
||||
}
|
||||
|
||||
impl CipherCtx {
|
||||
/// Creates a new context.
|
||||
#[corresponds(EVP_CIPHER_CTX_new)]
|
||||
@@ -509,6 +520,17 @@ impl CipherCtxRef {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Set ctx flags.
|
||||
///
|
||||
/// This function is currently used to enable AES key wrap feature supported by OpenSSL 1.0.2 or newer.
|
||||
#[corresponds(EVP_CIPHER_CTX_set_flags)]
|
||||
#[cfg(ossl102)]
|
||||
pub fn set_flags(&mut self, flags: CipherCtxFlags) {
|
||||
unsafe {
|
||||
ffi::EVP_CIPHER_CTX_set_flags(self.as_ptr(), flags.bits());
|
||||
}
|
||||
}
|
||||
|
||||
/// Writes data into the context.
|
||||
///
|
||||
/// Providing no output buffer will cause the input to be considered additional authenticated data (AAD).
|
||||
@@ -551,8 +573,7 @@ impl CipherCtxRef {
|
||||
/// output size check removed. It can be used when the exact
|
||||
/// buffer size control is maintained by the caller.
|
||||
///
|
||||
/// # Safety
|
||||
/// The caller is expected to provide `output` buffer
|
||||
/// SAFETY: The caller is expected to provide `output` buffer
|
||||
/// large enough to contain correct number of bytes. For streaming
|
||||
/// ciphers the output buffer size should be at least as big as
|
||||
/// the input buffer. For block ciphers the size of the output
|
||||
@@ -592,6 +613,50 @@ impl CipherCtxRef {
|
||||
Ok(len)
|
||||
}
|
||||
|
||||
/// Like [`Self::cipher_update`] except that it writes output into the
|
||||
/// `data` buffer. The `inlen` parameter specifies the number of bytes in
|
||||
/// `data` that are considered the input. For streaming ciphers, the size of
|
||||
/// `data` must be at least the input size. Otherwise, it must be at least
|
||||
/// an additional block size larger.
|
||||
///
|
||||
/// Note: Use [`Self::cipher_update`] with no output argument to write AAD.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function panics if the input size cannot be represented as `int` or
|
||||
/// exceeds the buffer size, or if the output buffer does not contain enough
|
||||
/// additional space.
|
||||
#[corresponds(EVP_CipherUpdate)]
|
||||
pub fn cipher_update_inplace(
|
||||
&mut self,
|
||||
data: &mut [u8],
|
||||
inlen: usize,
|
||||
) -> Result<usize, ErrorStack> {
|
||||
assert!(inlen <= data.len(), "Input size may not exceed buffer size");
|
||||
let block_size = self.block_size();
|
||||
if block_size != 1 {
|
||||
assert!(
|
||||
data.len() >= inlen + block_size,
|
||||
"Output buffer size must be at least {} bytes.",
|
||||
inlen + block_size
|
||||
);
|
||||
}
|
||||
|
||||
let inlen = c_int::try_from(inlen).unwrap();
|
||||
let mut outlen = 0;
|
||||
unsafe {
|
||||
cvt(ffi::EVP_CipherUpdate(
|
||||
self.as_ptr(),
|
||||
data.as_mut_ptr(),
|
||||
&mut outlen,
|
||||
data.as_ptr(),
|
||||
inlen,
|
||||
))
|
||||
}?;
|
||||
|
||||
Ok(outlen as usize)
|
||||
}
|
||||
|
||||
/// Finalizes the encryption or decryption process.
|
||||
///
|
||||
/// Any remaining data will be written to the output buffer.
|
||||
@@ -620,8 +685,7 @@ impl CipherCtxRef {
|
||||
/// This function is the same as [`Self::cipher_final`] but with
|
||||
/// the output buffer size check removed.
|
||||
///
|
||||
/// # Safety
|
||||
/// The caller is expected to provide `output` buffer
|
||||
/// SAFETY: The caller is expected to provide `output` buffer
|
||||
/// large enough to contain correct number of bytes. For streaming
|
||||
/// ciphers the output buffer can be empty, for block ciphers the
|
||||
/// output buffer should be at least as big as the block.
|
||||
@@ -780,6 +844,26 @@ mod test {
|
||||
|
||||
ctx.cipher_final_vec(&mut vec![0; 0]).unwrap();
|
||||
|
||||
// encrypt again, but use in-place encryption this time
|
||||
// First reset the IV
|
||||
ctx.encrypt_init(None, None, Some(&iv)).unwrap();
|
||||
ctx.set_padding(false);
|
||||
let mut data_inplace: [u8; 32] = [1; 32];
|
||||
let outlen = ctx
|
||||
.cipher_update_inplace(&mut data_inplace[0..15], 15)
|
||||
.unwrap();
|
||||
assert_eq!(15, outlen);
|
||||
|
||||
let outlen = ctx
|
||||
.cipher_update_inplace(&mut data_inplace[15..32], 17)
|
||||
.unwrap();
|
||||
assert_eq!(17, outlen);
|
||||
|
||||
ctx.cipher_final(&mut [0u8; 0]).unwrap();
|
||||
|
||||
// Check that the resulting data is encrypted in the same manner
|
||||
assert_eq!(data_inplace.as_slice(), output.as_slice());
|
||||
|
||||
// try to decrypt
|
||||
ctx.decrypt_init(Some(cipher), Some(&key), Some(&iv))
|
||||
.unwrap();
|
||||
@@ -802,6 +886,19 @@ mod test {
|
||||
ctx.cipher_final_vec(&mut vec![0; 0]).unwrap();
|
||||
// check if the decrypted blocks are the same as input (all ones)
|
||||
assert_eq!(output_decrypted, vec![1; 32]);
|
||||
|
||||
// decrypt again, but now the output in-place
|
||||
ctx.decrypt_init(None, None, Some(&iv)).unwrap();
|
||||
ctx.set_padding(false);
|
||||
|
||||
let outlen = ctx.cipher_update_inplace(&mut output[0..15], 15).unwrap();
|
||||
assert_eq!(15, outlen);
|
||||
|
||||
let outlen = ctx.cipher_update_inplace(&mut output[15..], 17).unwrap();
|
||||
assert_eq!(17, outlen);
|
||||
|
||||
ctx.cipher_final_vec(&mut vec![0; 0]).unwrap();
|
||||
assert_eq!(output_decrypted, output);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -840,4 +937,162 @@ mod test {
|
||||
ctx.cipher_update(&vec![0; block_size + 1], Some(&mut vec![0; block_size - 1]))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[cfg(ossl102)]
|
||||
fn cipher_wrap_test(cipher: &CipherRef, pt: &str, ct: &str, key: &str, iv: Option<&str>) {
|
||||
let pt = hex::decode(pt).unwrap();
|
||||
let key = hex::decode(key).unwrap();
|
||||
let expected = hex::decode(ct).unwrap();
|
||||
let iv = iv.map(|v| hex::decode(v).unwrap());
|
||||
let padding = 8 - pt.len() % 8;
|
||||
let mut computed = vec![0; pt.len() + padding + cipher.block_size() * 2];
|
||||
let mut ctx = CipherCtx::new().unwrap();
|
||||
|
||||
ctx.set_flags(CipherCtxFlags::FLAG_WRAP_ALLOW);
|
||||
ctx.encrypt_init(Some(cipher), Some(&key), iv.as_deref())
|
||||
.unwrap();
|
||||
|
||||
let count = ctx.cipher_update(&pt, Some(&mut computed)).unwrap();
|
||||
let rest = ctx.cipher_final(&mut computed[count..]).unwrap();
|
||||
computed.truncate(count + rest);
|
||||
|
||||
if computed != expected {
|
||||
println!("Computed: {}", hex::encode(&computed));
|
||||
println!("Expected: {}", hex::encode(&expected));
|
||||
if computed.len() != expected.len() {
|
||||
println!(
|
||||
"Lengths differ: {} in computed vs {} expected",
|
||||
computed.len(),
|
||||
expected.len()
|
||||
);
|
||||
}
|
||||
panic!("test failure");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl102)]
|
||||
fn test_aes128_wrap() {
|
||||
let pt = "00112233445566778899aabbccddeeff";
|
||||
let ct = "7940ff694448b5bb5139c959a4896832e55d69aa04daa27e";
|
||||
let key = "2b7e151628aed2a6abf7158809cf4f3c";
|
||||
let iv = "0001020304050607";
|
||||
|
||||
cipher_wrap_test(Cipher::aes_128_wrap(), pt, ct, key, Some(iv));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl102)]
|
||||
fn test_aes128_wrap_default_iv() {
|
||||
let pt = "00112233445566778899aabbccddeeff";
|
||||
let ct = "38f1215f0212526f8a70b51955b9fbdc9fe3041d9832306e";
|
||||
let key = "2b7e151628aed2a6abf7158809cf4f3c";
|
||||
|
||||
cipher_wrap_test(Cipher::aes_128_wrap(), pt, ct, key, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl110)]
|
||||
fn test_aes128_wrap_pad() {
|
||||
let pt = "00112233445566778899aabbccddee";
|
||||
let ct = "f13998f5ab32ef82a1bdbcbe585e1d837385b529572a1e1b";
|
||||
let key = "2b7e151628aed2a6abf7158809cf4f3c";
|
||||
let iv = "00010203";
|
||||
|
||||
cipher_wrap_test(Cipher::aes_128_wrap_pad(), pt, ct, key, Some(iv));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl110)]
|
||||
fn test_aes128_wrap_pad_default_iv() {
|
||||
let pt = "00112233445566778899aabbccddee";
|
||||
let ct = "3a501085fb8cf66f4186b7df851914d471ed823411598add";
|
||||
let key = "2b7e151628aed2a6abf7158809cf4f3c";
|
||||
|
||||
cipher_wrap_test(Cipher::aes_128_wrap_pad(), pt, ct, key, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl102)]
|
||||
fn test_aes192_wrap() {
|
||||
let pt = "9f6dee187d35302116aecbfd059657efd9f7589c4b5e7f5b";
|
||||
let ct = "83b89142dfeeb4871e078bfb81134d33e23fedc19b03a1cf689973d3831b6813";
|
||||
let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
|
||||
let iv = "0001020304050607";
|
||||
|
||||
cipher_wrap_test(Cipher::aes_192_wrap(), pt, ct, key, Some(iv));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl102)]
|
||||
fn test_aes192_wrap_default_iv() {
|
||||
let pt = "9f6dee187d35302116aecbfd059657efd9f7589c4b5e7f5b";
|
||||
let ct = "c02c2cf11505d3e4851030d5534cbf5a1d7eca7ba8839adbf239756daf1b43e6";
|
||||
let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
|
||||
|
||||
cipher_wrap_test(Cipher::aes_192_wrap(), pt, ct, key, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl110)]
|
||||
fn test_aes192_wrap_pad() {
|
||||
let pt = "00112233445566778899aabbccddee";
|
||||
let ct = "b4f6bb167ef7caf061a74da82b36ad038ca057ab51e98d3a";
|
||||
let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
|
||||
let iv = "00010203";
|
||||
|
||||
cipher_wrap_test(Cipher::aes_192_wrap_pad(), pt, ct, key, Some(iv));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl110)]
|
||||
fn test_aes192_wrap_pad_default_iv() {
|
||||
let pt = "00112233445566778899aabbccddee";
|
||||
let ct = "b2c37a28cc602753a7c944a4c2555a2df9c98b2eded5312e";
|
||||
let key = "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b";
|
||||
|
||||
cipher_wrap_test(Cipher::aes_192_wrap_pad(), pt, ct, key, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl102)]
|
||||
fn test_aes256_wrap() {
|
||||
let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51";
|
||||
let ct = "cc05da2a7f56f7dd0c144231f90bce58648fa20a8278f5a6b7d13bba6aa57a33229d4333866b7fd6";
|
||||
let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
|
||||
let iv = "0001020304050607";
|
||||
|
||||
cipher_wrap_test(Cipher::aes_256_wrap(), pt, ct, key, Some(iv));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl102)]
|
||||
fn test_aes256_wrap_default_iv() {
|
||||
let pt = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51";
|
||||
let ct = "0b24f068b50e52bc6987868411c36e1b03900866ed12af81eb87cef70a8d1911731c1d7abf789d88";
|
||||
let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
|
||||
|
||||
cipher_wrap_test(Cipher::aes_256_wrap(), pt, ct, key, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl110)]
|
||||
fn test_aes256_wrap_pad() {
|
||||
let pt = "00112233445566778899aabbccddee";
|
||||
let ct = "91594e044ccc06130d60e6c84a996aa4f96a9faff8c5f6e7";
|
||||
let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
|
||||
let iv = "00010203";
|
||||
|
||||
cipher_wrap_test(Cipher::aes_256_wrap_pad(), pt, ct, key, Some(iv));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl110)]
|
||||
fn test_aes256_wrap_pad_default_iv() {
|
||||
let pt = "00112233445566778899aabbccddee";
|
||||
let ct = "dc3c166a854afd68aea624a4272693554bf2e4fcbae602cd";
|
||||
let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
|
||||
|
||||
cipher_wrap_test(Cipher::aes_256_wrap_pad(), pt, ct, key, None);
|
||||
}
|
||||
}
|
||||
|
||||
+39
-4
@@ -56,6 +56,7 @@ use std::ptr;
|
||||
use crate::error::ErrorStack;
|
||||
use crate::pkey::{HasPrivate, HasPublic, PKeyRef};
|
||||
use crate::{cvt, cvt_p};
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
/// A type used to derive a shared secret between two keys.
|
||||
pub struct Deriver<'a>(*mut ffi::EVP_PKEY_CTX, PhantomData<&'a ()>);
|
||||
@@ -82,10 +83,7 @@ impl<'a> Deriver<'a> {
|
||||
}
|
||||
|
||||
/// Sets the peer key used for secret derivation.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_derive_set_peer`]:
|
||||
///
|
||||
/// [`EVP_PKEY_derive_set_peer`]: https://www.openssl.org/docs/manmaster/crypto/EVP_PKEY_derive_init.html
|
||||
#[corresponds(EVP_PKEY_derive_set_peer)]
|
||||
pub fn set_peer<T>(&mut self, key: &'a PKeyRef<T>) -> Result<(), ErrorStack>
|
||||
where
|
||||
T: HasPublic,
|
||||
@@ -93,6 +91,29 @@ impl<'a> Deriver<'a> {
|
||||
unsafe { cvt(ffi::EVP_PKEY_derive_set_peer(self.0, key.as_ptr())).map(|_| ()) }
|
||||
}
|
||||
|
||||
/// Sets the peer key used for secret derivation along with optionally validating the peer public key.
|
||||
///
|
||||
/// Requires OpenSSL 3.0.0 or newer.
|
||||
#[corresponds(EVP_PKEY_derive_set_peer_ex)]
|
||||
#[cfg(ossl300)]
|
||||
pub fn set_peer_ex<T>(
|
||||
&mut self,
|
||||
key: &'a PKeyRef<T>,
|
||||
validate_peer: bool,
|
||||
) -> Result<(), ErrorStack>
|
||||
where
|
||||
T: HasPublic,
|
||||
{
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_derive_set_peer_ex(
|
||||
self.0,
|
||||
key.as_ptr(),
|
||||
validate_peer as i32,
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the size of the shared secret.
|
||||
///
|
||||
/// It can be used to size the buffer passed to [`Deriver::derive`].
|
||||
@@ -179,4 +200,18 @@ mod test {
|
||||
let shared = deriver.derive_to_vec().unwrap();
|
||||
assert!(!shared.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl300)]
|
||||
fn test_ec_key_derive_ex() {
|
||||
let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
|
||||
let ec_key = EcKey::generate(&group).unwrap();
|
||||
let ec_key2 = EcKey::generate(&group).unwrap();
|
||||
let pkey = PKey::from_ec_key(ec_key).unwrap();
|
||||
let pkey2 = PKey::from_ec_key(ec_key2).unwrap();
|
||||
let mut deriver = Deriver::new(&pkey).unwrap();
|
||||
deriver.set_peer_ex(&pkey2, true).unwrap();
|
||||
let shared = deriver.derive_to_vec().unwrap();
|
||||
assert!(!shared.is_empty());
|
||||
}
|
||||
}
|
||||
|
||||
+65
-1
@@ -7,7 +7,7 @@ use std::ptr;
|
||||
|
||||
use crate::bn::{BigNum, BigNumRef};
|
||||
use crate::error::ErrorStack;
|
||||
use crate::pkey::{HasParams, HasPrivate, HasPublic, Params, Private};
|
||||
use crate::pkey::{HasParams, HasPrivate, HasPublic, Params, Private, Public};
|
||||
use crate::{cvt, cvt_p};
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
@@ -39,6 +39,16 @@ where
|
||||
params_to_der,
|
||||
ffi::i2d_DHparams
|
||||
}
|
||||
|
||||
/// Validates DH parameters for correctness
|
||||
#[corresponds(DH_check_key)]
|
||||
pub fn check_key(&self) -> Result<bool, ErrorStack> {
|
||||
unsafe {
|
||||
let mut codes = 0;
|
||||
cvt(ffi::DH_check(self.as_ptr(), &mut codes))?;
|
||||
Ok(codes == 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Dh<Params> {
|
||||
@@ -66,6 +76,16 @@ impl Dh<Params> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the public key on the DH object.
|
||||
pub fn set_public_key(self, pub_key: BigNum) -> Result<Dh<Public>, ErrorStack> {
|
||||
unsafe {
|
||||
let dh_ptr = self.0;
|
||||
cvt(DH_set0_key(dh_ptr, pub_key.as_ptr(), ptr::null_mut()))?;
|
||||
mem::forget((self, pub_key));
|
||||
Ok(Dh::from_ptr(dh_ptr))
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the private key on the DH object and recomputes the public key.
|
||||
pub fn set_private_key(self, priv_key: BigNum) -> Result<Dh<Private>, ErrorStack> {
|
||||
unsafe {
|
||||
@@ -79,6 +99,16 @@ impl Dh<Params> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the public and private keys on the DH object.
|
||||
pub fn set_key(self, pub_key: BigNum, priv_key: BigNum) -> Result<Dh<Private>, ErrorStack> {
|
||||
unsafe {
|
||||
let dh_ptr = self.0;
|
||||
cvt(DH_set0_key(dh_ptr, pub_key.as_ptr(), priv_key.as_ptr()))?;
|
||||
mem::forget((self, pub_key, priv_key));
|
||||
Ok(Dh::from_ptr(dh_ptr))
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates DH params based on the given `prime_len` and a fixed `generator` value.
|
||||
#[corresponds(DH_generate_parameters_ex)]
|
||||
pub fn generate_params(prime_len: u32, generator: u32) -> Result<Dh<Params>, ErrorStack> {
|
||||
@@ -367,6 +397,30 @@ mod tests {
|
||||
assert_eq!(key1.private_key(), key2.private_key());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl102)]
|
||||
fn test_set_keys() {
|
||||
let dh1 = Dh::get_2048_256().unwrap();
|
||||
let key1 = dh1.generate_key().unwrap();
|
||||
|
||||
let dh2 = Dh::get_2048_256().unwrap();
|
||||
let key2 = dh2
|
||||
.set_public_key(key1.public_key().to_owned().unwrap())
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(key1.public_key(), key2.public_key());
|
||||
|
||||
let dh3 = Dh::get_2048_256().unwrap();
|
||||
let key3 = dh3
|
||||
.set_key(
|
||||
key1.public_key().to_owned().unwrap(),
|
||||
key1.private_key().to_owned().unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(key1.public_key(), key3.public_key());
|
||||
assert_eq!(key1.private_key(), key3.private_key());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dh_from_pem() {
|
||||
let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
|
||||
@@ -413,4 +467,14 @@ mod tests {
|
||||
|
||||
assert_eq!(shared_a, shared_b);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dh_check_key() {
|
||||
let dh1 = Dh::generate_params(512, 2).unwrap();
|
||||
let p = BigNum::from_hex_str("04").unwrap();
|
||||
let g = BigNum::from_hex_str("02").unwrap();
|
||||
let dh2 = Dh::from_pqg(p, None, g).unwrap();
|
||||
assert!(dh1.check_key().unwrap());
|
||||
assert!(!dh2.check_key().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
+65
-15
@@ -7,6 +7,7 @@
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
#[cfg(not(boringssl))]
|
||||
use libc::c_int;
|
||||
use std::fmt;
|
||||
use std::mem;
|
||||
@@ -14,7 +15,7 @@ use std::ptr;
|
||||
|
||||
use crate::bn::{BigNum, BigNumRef};
|
||||
use crate::error::ErrorStack;
|
||||
use crate::pkey::{HasParams, HasPrivate, HasPublic, Private, Public};
|
||||
use crate::pkey::{HasParams, HasPrivate, HasPublic, Params, Private, Public};
|
||||
use crate::util::ForeignTypeRefExt;
|
||||
use crate::{cvt, cvt_p};
|
||||
use openssl_macros::corresponds;
|
||||
@@ -127,6 +128,13 @@ where
|
||||
ffi::PEM_write_bio_DSAPrivateKey
|
||||
}
|
||||
|
||||
to_der! {
|
||||
/// Serializes the private_key to a DER-encoded `DSAPrivateKey` structure.
|
||||
#[corresponds(i2d_DSAPrivateKey)]
|
||||
private_key_to_der,
|
||||
ffi::i2d_DSAPrivateKey
|
||||
}
|
||||
|
||||
/// Returns a reference to the private key component of `self`.
|
||||
#[corresponds(DSA_get0_key)]
|
||||
pub fn priv_key(&self) -> &BigNumRef {
|
||||
@@ -183,17 +191,21 @@ type BitType = libc::c_uint;
|
||||
#[cfg(not(boringssl))]
|
||||
type BitType = c_int;
|
||||
|
||||
impl Dsa<Private> {
|
||||
/// Generate a DSA key pair.
|
||||
///
|
||||
/// Calls [`DSA_generate_parameters_ex`] to populate the `p`, `g`, and `q` values.
|
||||
/// These values are used to generate the key pair with [`DSA_generate_key`].
|
||||
///
|
||||
/// The `bits` parameter corresponds to the length of the prime `p`.
|
||||
///
|
||||
/// [`DSA_generate_parameters_ex`]: https://www.openssl.org/docs/manmaster/crypto/DSA_generate_parameters_ex.html
|
||||
/// [`DSA_generate_key`]: https://www.openssl.org/docs/manmaster/crypto/DSA_generate_key.html
|
||||
pub fn generate(bits: u32) -> Result<Dsa<Private>, ErrorStack> {
|
||||
impl Dsa<Params> {
|
||||
/// Creates a DSA params based upon the given parameters.
|
||||
#[corresponds(DSA_set0_pqg)]
|
||||
pub fn from_pqg(p: BigNum, q: BigNum, g: BigNum) -> Result<Dsa<Params>, ErrorStack> {
|
||||
unsafe {
|
||||
let dsa = Dsa::from_ptr(cvt_p(ffi::DSA_new())?);
|
||||
cvt(DSA_set0_pqg(dsa.0, p.as_ptr(), q.as_ptr(), g.as_ptr()))?;
|
||||
mem::forget((p, q, g));
|
||||
Ok(dsa)
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates DSA params based on the given number of bits.
|
||||
#[corresponds(DSA_generate_parameters_ex)]
|
||||
pub fn generate_params(bits: u32) -> Result<Dsa<Params>, ErrorStack> {
|
||||
ffi::init();
|
||||
unsafe {
|
||||
let dsa = Dsa::from_ptr(cvt_p(ffi::DSA_new())?);
|
||||
@@ -206,11 +218,31 @@ impl Dsa<Private> {
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
))?;
|
||||
cvt(ffi::DSA_generate_key(dsa.0))?;
|
||||
Ok(dsa)
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates a private key based on the DSA params.
|
||||
#[corresponds(DSA_generate_key)]
|
||||
pub fn generate_key(self) -> Result<Dsa<Private>, ErrorStack> {
|
||||
unsafe {
|
||||
let dsa_ptr = self.0;
|
||||
cvt(ffi::DSA_generate_key(dsa_ptr))?;
|
||||
mem::forget(self);
|
||||
Ok(Dsa::from_ptr(dsa_ptr))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Dsa<Private> {
|
||||
/// Generate a DSA key pair.
|
||||
///
|
||||
/// The `bits` parameter corresponds to the length of the prime `p`.
|
||||
pub fn generate(bits: u32) -> Result<Dsa<Private>, ErrorStack> {
|
||||
let params = Dsa::generate_params(bits)?;
|
||||
params.generate_key()
|
||||
}
|
||||
|
||||
/// Create a DSA key pair with the given parameters
|
||||
///
|
||||
/// `p`, `q` and `g` are the common parameters.
|
||||
@@ -283,7 +315,7 @@ impl<T> fmt::Debug for Dsa<T> {
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl110, libressl273))] {
|
||||
if #[cfg(any(ossl110, libressl273, boringssl))] {
|
||||
use ffi::{DSA_get0_key, DSA_get0_pqg, DSA_set0_key, DSA_set0_pqg};
|
||||
} else {
|
||||
#[allow(bad_style)]
|
||||
@@ -462,7 +494,7 @@ impl DsaSigRef {
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl110, libressl273))] {
|
||||
if #[cfg(any(ossl110, libressl273, boringssl))] {
|
||||
use ffi::{DSA_SIG_set0, DSA_SIG_get0};
|
||||
} else {
|
||||
#[allow(bad_style)]
|
||||
@@ -556,6 +588,24 @@ mod test {
|
||||
assert_eq!(dsa.g(), &BigNum::from_u32(60).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_params() {
|
||||
let params = Dsa::generate_params(1024).unwrap();
|
||||
let p = params.p().to_owned().unwrap();
|
||||
let q = params.q().to_owned().unwrap();
|
||||
let g = params.g().to_owned().unwrap();
|
||||
let key = params.generate_key().unwrap();
|
||||
let params2 = Dsa::from_pqg(
|
||||
key.p().to_owned().unwrap(),
|
||||
key.q().to_owned().unwrap(),
|
||||
key.g().to_owned().unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(p, *params2.p());
|
||||
assert_eq!(q, *params2.q());
|
||||
assert_eq!(g, *params2.g());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(boringssl))]
|
||||
fn test_signature() {
|
||||
|
||||
+80
-3
@@ -15,6 +15,7 @@
|
||||
//! [`EcGroup`]: struct.EcGroup.html
|
||||
//! [`Nid`]: ../nid/struct.Nid.html
|
||||
//! [Elliptic Curve Cryptography]: https://wiki.openssl.org/index.php/Elliptic_Curve_Cryptography
|
||||
use cfg_if::cfg_if;
|
||||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
use libc::c_int;
|
||||
use std::fmt;
|
||||
@@ -28,6 +29,13 @@ use crate::util::ForeignTypeRefExt;
|
||||
use crate::{cvt, cvt_n, cvt_p, init};
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(not(boringssl))] {
|
||||
use std::ffi::CString;
|
||||
use crate::string::OpensslString;
|
||||
}
|
||||
}
|
||||
|
||||
/// Compressed or Uncompressed conversion
|
||||
///
|
||||
/// Conversion from the binary value of the point on the curve is performed in one of
|
||||
@@ -57,7 +65,7 @@ impl PointConversionForm {
|
||||
/// Named Curve or Explicit
|
||||
///
|
||||
/// This type acts as a boolean as to whether the `EcGroup` is named or explicit.
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub struct Asn1Flag(c_int);
|
||||
|
||||
impl Asn1Flag {
|
||||
@@ -294,6 +302,12 @@ impl EcGroupRef {
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the flag determining if the group corresponds to a named curve.
|
||||
#[corresponds(EC_GROUP_get_asn1_flag)]
|
||||
pub fn asn1_flag(&self) -> Asn1Flag {
|
||||
unsafe { Asn1Flag(ffi::EC_GROUP_get_asn1_flag(self.as_ptr())) }
|
||||
}
|
||||
|
||||
/// Returns the name of the curve, if a name is associated.
|
||||
#[corresponds(EC_GROUP_get_curve_name)]
|
||||
pub fn curve_name(&self) -> Option<Nid> {
|
||||
@@ -457,6 +471,26 @@ impl EcPointRef {
|
||||
}
|
||||
}
|
||||
|
||||
/// Serializes the point to a hexadecimal string representation.
|
||||
#[corresponds(EC_POINT_point2hex)]
|
||||
#[cfg(not(boringssl))]
|
||||
pub fn to_hex_str(
|
||||
&self,
|
||||
group: &EcGroupRef,
|
||||
form: PointConversionForm,
|
||||
ctx: &mut BigNumContextRef,
|
||||
) -> Result<OpensslString, ErrorStack> {
|
||||
unsafe {
|
||||
let buf = cvt_p(ffi::EC_POINT_point2hex(
|
||||
group.as_ptr(),
|
||||
self.as_ptr(),
|
||||
form.0,
|
||||
ctx.as_ptr(),
|
||||
))?;
|
||||
Ok(OpensslString::from_ptr(buf))
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new point on the specified curve with the same value.
|
||||
#[corresponds(EC_POINT_dup)]
|
||||
pub fn to_owned(&self, group: &EcGroupRef) -> Result<EcPoint, ErrorStack> {
|
||||
@@ -485,7 +519,7 @@ impl EcPointRef {
|
||||
/// Places affine coordinates of a curve over a prime field in the provided
|
||||
/// `x` and `y` `BigNum`s.
|
||||
#[corresponds(EC_POINT_get_affine_coordinates)]
|
||||
#[cfg(ossl111)]
|
||||
#[cfg(any(ossl111, boringssl, libressl350))]
|
||||
pub fn affine_coordinates(
|
||||
&self,
|
||||
group: &EcGroupRef,
|
||||
@@ -625,6 +659,27 @@ impl EcPoint {
|
||||
}
|
||||
Ok(point)
|
||||
}
|
||||
|
||||
/// Creates point from a hexadecimal string representation
|
||||
#[corresponds(EC_POINT_hex2point)]
|
||||
#[cfg(not(boringssl))]
|
||||
pub fn from_hex_str(
|
||||
group: &EcGroupRef,
|
||||
s: &str,
|
||||
ctx: &mut BigNumContextRef,
|
||||
) -> Result<EcPoint, ErrorStack> {
|
||||
let point = EcPoint::new(group)?;
|
||||
unsafe {
|
||||
let c_str = CString::new(s.as_bytes()).unwrap();
|
||||
cvt_p(ffi::EC_POINT_hex2point(
|
||||
group.as_ptr(),
|
||||
c_str.as_ptr() as *const _,
|
||||
point.as_ptr(),
|
||||
ctx.as_ptr(),
|
||||
))?;
|
||||
}
|
||||
Ok(point)
|
||||
}
|
||||
}
|
||||
|
||||
generic_foreign_type_and_impl_send_sync! {
|
||||
@@ -1115,6 +1170,20 @@ mod test {
|
||||
assert!(point.eq(&group, &point2, &mut ctx).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(boringssl))]
|
||||
fn point_hex_str() {
|
||||
let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
|
||||
let key = EcKey::generate(&group).unwrap();
|
||||
let point = key.public_key();
|
||||
let mut ctx = BigNumContext::new().unwrap();
|
||||
let hex = point
|
||||
.to_hex_str(&group, PointConversionForm::COMPRESSED, &mut ctx)
|
||||
.unwrap();
|
||||
let point2 = EcPoint::from_hex_str(&group, &hex, &mut ctx).unwrap();
|
||||
assert!(point.eq(&group, &point2, &mut ctx).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn point_owned() {
|
||||
let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
|
||||
@@ -1191,7 +1260,7 @@ mod test {
|
||||
assert!(ec_key.check_key().is_ok());
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
#[cfg(any(ossl111, boringssl, libressl350))]
|
||||
#[test]
|
||||
fn get_affine_coordinates() {
|
||||
let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
|
||||
@@ -1265,4 +1334,12 @@ mod test {
|
||||
let group2 = EcGroup::from_curve_name(Nid::X9_62_PRIME239V3).unwrap();
|
||||
assert!(!g.is_on_curve(&group2, &mut ctx).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(boringssl, ossl111, libressl350))]
|
||||
fn asn1_flag() {
|
||||
let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
|
||||
let flag = group.asn1_flag();
|
||||
assert_eq!(flag, Asn1Flag::NAMED_CURVE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ impl EcdsaSigRef {
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl110, libressl273))] {
|
||||
if #[cfg(any(ossl110, libressl273, boringssl))] {
|
||||
use ffi::{ECDSA_SIG_set0, ECDSA_SIG_get0};
|
||||
} else {
|
||||
#[allow(bad_style)]
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@ use crate::nid::Nid;
|
||||
use crate::{cvt, cvt_p};
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(ossl110)] {
|
||||
if #[cfg(any(ossl110, boringssl))] {
|
||||
use ffi::{EVP_MD_CTX_free, EVP_MD_CTX_new};
|
||||
} else {
|
||||
use ffi::{EVP_MD_CTX_create as EVP_MD_CTX_new, EVP_MD_CTX_destroy as EVP_MD_CTX_free};
|
||||
|
||||
+2
-3
@@ -1,7 +1,7 @@
|
||||
//! Bindings to OpenSSL
|
||||
//!
|
||||
//! This crate provides a safe interface to the popular OpenSSL cryptography library. OpenSSL versions 1.0.1 through
|
||||
//! 3.x.x and LibreSSL versions 2.5 through 3.4.1 are supported.
|
||||
//! 3.x.x and LibreSSL versions 2.5 through 3.7.x are supported.
|
||||
//!
|
||||
//! # Building
|
||||
//!
|
||||
@@ -119,7 +119,7 @@
|
||||
//! ```
|
||||
#![doc(html_root_url = "https://docs.rs/openssl/0.10")]
|
||||
#![warn(rust_2018_idioms)]
|
||||
#![allow(clippy::uninlined_format_args, clippy::needless_doctest_main)]
|
||||
#![allow(clippy::uninlined_format_args)]
|
||||
|
||||
#[doc(inline)]
|
||||
pub use ffi::init;
|
||||
@@ -166,7 +166,6 @@ pub mod nid;
|
||||
#[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_OCSP")))]
|
||||
pub mod ocsp;
|
||||
pub mod pkcs12;
|
||||
#[cfg(not(boringssl))]
|
||||
pub mod pkcs5;
|
||||
#[cfg(not(boringssl))]
|
||||
pub mod pkcs7;
|
||||
|
||||
@@ -93,7 +93,7 @@ use std::convert::TryFrom;
|
||||
use std::ptr;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(ossl110)] {
|
||||
if #[cfg(any(ossl110, boringssl))] {
|
||||
use ffi::{EVP_MD_CTX_free, EVP_MD_CTX_new};
|
||||
} else {
|
||||
use ffi::{EVP_MD_CTX_create as EVP_MD_CTX_new, EVP_MD_CTX_destroy as EVP_MD_CTX_free};
|
||||
|
||||
+12
-7
@@ -51,13 +51,13 @@ pub struct Nid(c_int);
|
||||
#[allow(non_snake_case)]
|
||||
impl Nid {
|
||||
/// Create a `Nid` from an integer representation.
|
||||
pub fn from_raw(raw: c_int) -> Nid {
|
||||
pub const fn from_raw(raw: c_int) -> Nid {
|
||||
Nid(raw)
|
||||
}
|
||||
|
||||
/// Return the integer representation of a `Nid`.
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub fn as_raw(&self) -> c_int {
|
||||
pub const fn as_raw(&self) -> c_int {
|
||||
self.0
|
||||
}
|
||||
|
||||
@@ -1074,6 +1074,8 @@ impl Nid {
|
||||
pub const AES_128_CBC_HMAC_SHA1: Nid = Nid(ffi::NID_aes_128_cbc_hmac_sha1);
|
||||
pub const AES_192_CBC_HMAC_SHA1: Nid = Nid(ffi::NID_aes_192_cbc_hmac_sha1);
|
||||
pub const AES_256_CBC_HMAC_SHA1: Nid = Nid(ffi::NID_aes_256_cbc_hmac_sha1);
|
||||
#[cfg(ossl111)]
|
||||
pub const SM2: Nid = Nid(ffi::NID_sm2);
|
||||
#[cfg(any(ossl111, libressl291))]
|
||||
pub const SM3: Nid = Nid(ffi::NID_sm3);
|
||||
#[cfg(ossl111)]
|
||||
@@ -1165,10 +1167,13 @@ mod test {
|
||||
assert_eq!(nid.short_name().unwrap(), "foo");
|
||||
assert_eq!(nid.long_name().unwrap(), "foobar");
|
||||
|
||||
let invalid_oid = Nid::create("invalid_oid", "invalid", "invalid");
|
||||
assert!(
|
||||
invalid_oid.is_err(),
|
||||
"invalid_oid should not return a valid value"
|
||||
);
|
||||
// Due to a bug in OpenSSL 3.1.0, this test crashes on Windows
|
||||
if !cfg!(ossl310) {
|
||||
let invalid_oid = Nid::create("invalid_oid", "invalid", "invalid");
|
||||
assert!(
|
||||
invalid_oid.is_err(),
|
||||
"invalid_oid should not return a valid value"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-11
@@ -1,9 +1,13 @@
|
||||
#[cfg(not(boringssl))]
|
||||
use libc::c_int;
|
||||
use std::convert::TryInto;
|
||||
#[cfg(not(boringssl))]
|
||||
use std::ptr;
|
||||
|
||||
use crate::cvt;
|
||||
use crate::error::ErrorStack;
|
||||
use crate::hash::MessageDigest;
|
||||
#[cfg(not(boringssl))]
|
||||
use crate::symm::Cipher;
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
@@ -25,6 +29,7 @@ pub struct KeyIvPair {
|
||||
/// `pbkdf2_hmac` or another more modern key derivation algorithm.
|
||||
#[corresponds(EVP_BytesToKey)]
|
||||
#[allow(clippy::useless_conversion)]
|
||||
#[cfg(not(boringssl))]
|
||||
pub fn bytes_to_key(
|
||||
cipher: Cipher,
|
||||
digest: MessageDigest,
|
||||
@@ -91,19 +96,15 @@ pub fn pbkdf2_hmac(
|
||||
key: &mut [u8],
|
||||
) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
assert!(pass.len() <= c_int::max_value() as usize);
|
||||
assert!(salt.len() <= c_int::max_value() as usize);
|
||||
assert!(key.len() <= c_int::max_value() as usize);
|
||||
|
||||
ffi::init();
|
||||
cvt(ffi::PKCS5_PBKDF2_HMAC(
|
||||
pass.as_ptr() as *const _,
|
||||
pass.len() as c_int,
|
||||
pass.len().try_into().unwrap(),
|
||||
salt.as_ptr(),
|
||||
salt.len() as c_int,
|
||||
iter as c_int,
|
||||
salt.len().try_into().unwrap(),
|
||||
iter.try_into().unwrap(),
|
||||
hash.as_ptr(),
|
||||
key.len() as c_int,
|
||||
key.len().try_into().unwrap(),
|
||||
key.as_mut_ptr(),
|
||||
))
|
||||
.map(|_| ())
|
||||
@@ -114,7 +115,8 @@ pub fn pbkdf2_hmac(
|
||||
///
|
||||
/// Requires OpenSSL 1.1.0 or newer.
|
||||
#[corresponds(EVP_PBE_scrypt)]
|
||||
#[cfg(any(ossl110))]
|
||||
#[cfg(any(ossl110, boringssl))]
|
||||
#[allow(clippy::useless_conversion)]
|
||||
pub fn scrypt(
|
||||
pass: &[u8],
|
||||
salt: &[u8],
|
||||
@@ -134,7 +136,7 @@ pub fn scrypt(
|
||||
n,
|
||||
r,
|
||||
p,
|
||||
maxmem,
|
||||
maxmem.try_into().unwrap(),
|
||||
key.as_mut_ptr() as *mut _,
|
||||
key.len(),
|
||||
))
|
||||
@@ -145,6 +147,7 @@ pub fn scrypt(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::hash::MessageDigest;
|
||||
#[cfg(not(boringssl))]
|
||||
use crate::symm::Cipher;
|
||||
|
||||
// Test vectors from
|
||||
@@ -246,6 +249,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(boringssl))]
|
||||
fn bytes_to_key() {
|
||||
let salt = [16_u8, 34_u8, 19_u8, 23_u8, 141_u8, 4_u8, 207_u8, 221_u8];
|
||||
|
||||
@@ -282,7 +286,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(ossl110))]
|
||||
#[cfg(any(ossl110, boringssl))]
|
||||
fn scrypt() {
|
||||
let pass = "pleaseletmein";
|
||||
let salt = "SodiumChloride";
|
||||
|
||||
+32
-30
@@ -57,7 +57,7 @@ use cfg_if::cfg_if;
|
||||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
use libc::{c_int, c_long};
|
||||
use openssl_macros::corresponds;
|
||||
use std::convert::TryFrom;
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use std::ffi::CString;
|
||||
use std::fmt;
|
||||
use std::mem;
|
||||
@@ -85,8 +85,10 @@ impl Id {
|
||||
pub const DSA: Id = Id(ffi::EVP_PKEY_DSA);
|
||||
pub const DH: Id = Id(ffi::EVP_PKEY_DH);
|
||||
pub const EC: Id = Id(ffi::EVP_PKEY_EC);
|
||||
#[cfg(ossl111)]
|
||||
pub const SM2: Id = Id(ffi::EVP_PKEY_SM2);
|
||||
|
||||
#[cfg(ossl110)]
|
||||
#[cfg(any(ossl110, boringssl))]
|
||||
pub const HKDF: Id = Id(ffi::EVP_PKEY_HKDF);
|
||||
|
||||
#[cfg(any(ossl111, boringssl, libressl370))]
|
||||
@@ -97,6 +99,8 @@ impl Id {
|
||||
pub const X25519: Id = Id(ffi::EVP_PKEY_X25519);
|
||||
#[cfg(ossl111)]
|
||||
pub const X448: Id = Id(ffi::EVP_PKEY_X448);
|
||||
#[cfg(ossl111)]
|
||||
pub const POLY1305: Id = Id(ffi::EVP_PKEY_POLY1305);
|
||||
|
||||
/// Creates a `Id` from an integer representation.
|
||||
pub fn from_raw(value: c_int) -> Id {
|
||||
@@ -244,7 +248,11 @@ where
|
||||
where
|
||||
U: HasPublic,
|
||||
{
|
||||
unsafe { ffi::EVP_PKEY_cmp(self.as_ptr(), other.as_ptr()) == 1 }
|
||||
let res = unsafe { ffi::EVP_PKEY_cmp(self.as_ptr(), other.as_ptr()) == 1 };
|
||||
// Clear the stack. OpenSSL will put an error on the stack when the
|
||||
// keys are different types in some situations.
|
||||
let _ = ErrorStack::get();
|
||||
res
|
||||
}
|
||||
|
||||
/// Raw byte representation of a public key.
|
||||
@@ -344,10 +352,6 @@ where
|
||||
|
||||
/// Serializes a private key into a DER-formatted PKCS#8, using the supplied password to
|
||||
/// encrypt the key.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `passphrase` contains an embedded null.
|
||||
#[corresponds(i2d_PKCS8PrivateKey_bio)]
|
||||
pub fn private_key_to_pkcs8_passphrase(
|
||||
&self,
|
||||
@@ -356,14 +360,12 @@ where
|
||||
) -> Result<Vec<u8>, ErrorStack> {
|
||||
unsafe {
|
||||
let bio = MemBio::new()?;
|
||||
let len = passphrase.len();
|
||||
let passphrase = CString::new(passphrase).unwrap();
|
||||
cvt(ffi::i2d_PKCS8PrivateKey_bio(
|
||||
bio.as_ptr(),
|
||||
self.as_ptr(),
|
||||
cipher.as_ptr(),
|
||||
passphrase.as_ptr() as *const _ as *mut _,
|
||||
len as ::libc::c_int,
|
||||
passphrase.len().try_into().unwrap(),
|
||||
None,
|
||||
ptr::null_mut(),
|
||||
))?;
|
||||
@@ -406,11 +408,7 @@ impl<T> PKey<T> {
|
||||
unsafe {
|
||||
let evp = cvt_p(ffi::EVP_PKEY_new())?;
|
||||
let pkey = PKey::from_ptr(evp);
|
||||
cvt(ffi::EVP_PKEY_assign(
|
||||
pkey.0,
|
||||
ffi::EVP_PKEY_RSA,
|
||||
rsa.as_ptr() as *mut _,
|
||||
))?;
|
||||
cvt(ffi::EVP_PKEY_assign_RSA(pkey.0, rsa.as_ptr()))?;
|
||||
mem::forget(rsa);
|
||||
Ok(pkey)
|
||||
}
|
||||
@@ -422,11 +420,7 @@ impl<T> PKey<T> {
|
||||
unsafe {
|
||||
let evp = cvt_p(ffi::EVP_PKEY_new())?;
|
||||
let pkey = PKey::from_ptr(evp);
|
||||
cvt(ffi::EVP_PKEY_assign(
|
||||
pkey.0,
|
||||
ffi::EVP_PKEY_DSA,
|
||||
dsa.as_ptr() as *mut _,
|
||||
))?;
|
||||
cvt(ffi::EVP_PKEY_assign_DSA(pkey.0, dsa.as_ptr()))?;
|
||||
mem::forget(dsa);
|
||||
Ok(pkey)
|
||||
}
|
||||
@@ -434,15 +428,12 @@ impl<T> PKey<T> {
|
||||
|
||||
/// Creates a new `PKey` containing a Diffie-Hellman key.
|
||||
#[corresponds(EVP_PKEY_assign_DH)]
|
||||
#[cfg(not(boringssl))]
|
||||
pub fn from_dh(dh: Dh<T>) -> Result<PKey<T>, ErrorStack> {
|
||||
unsafe {
|
||||
let evp = cvt_p(ffi::EVP_PKEY_new())?;
|
||||
let pkey = PKey::from_ptr(evp);
|
||||
cvt(ffi::EVP_PKEY_assign(
|
||||
pkey.0,
|
||||
ffi::EVP_PKEY_DH,
|
||||
dh.as_ptr() as *mut _,
|
||||
))?;
|
||||
cvt(ffi::EVP_PKEY_assign_DH(pkey.0, dh.as_ptr()))?;
|
||||
mem::forget(dh);
|
||||
Ok(pkey)
|
||||
}
|
||||
@@ -454,11 +445,7 @@ impl<T> PKey<T> {
|
||||
unsafe {
|
||||
let evp = cvt_p(ffi::EVP_PKEY_new())?;
|
||||
let pkey = PKey::from_ptr(evp);
|
||||
cvt(ffi::EVP_PKEY_assign(
|
||||
pkey.0,
|
||||
ffi::EVP_PKEY_EC,
|
||||
ec_key.as_ptr() as *mut _,
|
||||
))?;
|
||||
cvt(ffi::EVP_PKEY_assign_EC_KEY(pkey.0, ec_key.as_ptr()))?;
|
||||
mem::forget(ec_key);
|
||||
Ok(pkey)
|
||||
}
|
||||
@@ -861,6 +848,7 @@ impl<T> TryFrom<PKey<T>> for Dsa<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(boringssl))]
|
||||
impl<T> TryFrom<Dh<T>> for PKey<T> {
|
||||
type Error = ErrorStack;
|
||||
|
||||
@@ -885,6 +873,7 @@ mod tests {
|
||||
use crate::dh::Dh;
|
||||
use crate::dsa::Dsa;
|
||||
use crate::ec::EcKey;
|
||||
use crate::error::Error;
|
||||
use crate::nid::Nid;
|
||||
use crate::rsa::Rsa;
|
||||
use crate::symm::Cipher;
|
||||
@@ -1168,4 +1157,17 @@ mod tests {
|
||||
let key = PKey::ec_gen("prime256v1").unwrap();
|
||||
assert!(key.ec_key().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_public_eq() {
|
||||
let rsa = Rsa::generate(2048).unwrap();
|
||||
let pkey1 = PKey::from_rsa(rsa).unwrap();
|
||||
|
||||
let group = crate::ec::EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
|
||||
let ec_key = EcKey::generate(&group).unwrap();
|
||||
let pkey2 = PKey::from_ec_key(ec_key).unwrap();
|
||||
|
||||
assert!(!pkey1.public_eq(&pkey2));
|
||||
assert!(Error::get().is_none());
|
||||
}
|
||||
}
|
||||
|
||||
+211
-13
@@ -70,7 +70,8 @@ use crate::error::ErrorStack;
|
||||
use crate::md::MdRef;
|
||||
use crate::pkey::{HasPrivate, HasPublic, Id, PKey, PKeyRef, Private};
|
||||
use crate::rsa::Padding;
|
||||
use crate::{cvt, cvt_n, cvt_p};
|
||||
use crate::sign::RsaPssSaltlen;
|
||||
use crate::{cvt, cvt_p};
|
||||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
#[cfg(not(boringssl))]
|
||||
use libc::c_int;
|
||||
@@ -164,6 +165,17 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Prepares the context for signature recovery using the public key.
|
||||
#[corresponds(EVP_PKEY_verify_recover_init)]
|
||||
#[inline]
|
||||
pub fn verify_recover_init(&mut self) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_verify_recover_init(self.as_ptr()))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Encrypts data using the public key.
|
||||
///
|
||||
/// If `to` is set to `None`, an upper bound on the number of bytes required for the output buffer will be
|
||||
@@ -209,16 +221,54 @@ where
|
||||
#[inline]
|
||||
pub fn verify(&mut self, data: &[u8], sig: &[u8]) -> Result<bool, ErrorStack> {
|
||||
unsafe {
|
||||
let r = cvt_n(ffi::EVP_PKEY_verify(
|
||||
let r = ffi::EVP_PKEY_verify(
|
||||
self.as_ptr(),
|
||||
sig.as_ptr(),
|
||||
sig.len(),
|
||||
data.as_ptr(),
|
||||
data.len(),
|
||||
))?;
|
||||
);
|
||||
// `EVP_PKEY_verify` is not terribly consistent about how it,
|
||||
// reports errors. It does not clearly distinguish between 0 and
|
||||
// -1, and may put errors on the stack in both cases. If there's
|
||||
// errors on the stack, we return `Err()`, else we return
|
||||
// `Ok(false)`.
|
||||
if r <= 0 {
|
||||
let errors = ErrorStack::get();
|
||||
if !errors.errors().is_empty() {
|
||||
return Err(errors);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(r == 1)
|
||||
}
|
||||
}
|
||||
|
||||
/// Recovers the original data signed by the private key. You almost
|
||||
/// always want `verify` instead.
|
||||
///
|
||||
/// Returns the number of bytes written to `to`, or the number of bytes
|
||||
/// that would be written, if `to` is `None.
|
||||
#[corresponds(EVP_PKEY_verify_recover)]
|
||||
#[inline]
|
||||
pub fn verify_recover(
|
||||
&mut self,
|
||||
sig: &[u8],
|
||||
to: Option<&mut [u8]>,
|
||||
) -> Result<usize, ErrorStack> {
|
||||
let mut written = to.as_ref().map_or(0, |b| b.len());
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_verify_recover(
|
||||
self.as_ptr(),
|
||||
to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
|
||||
&mut written,
|
||||
sig.as_ptr(),
|
||||
sig.len(),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(written)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> PkeyCtxRef<T>
|
||||
@@ -351,6 +401,22 @@ impl<T> PkeyCtxRef<T> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sets which algorithm was used to compute the digest used in a
|
||||
/// signature. With RSA signatures this causes the signature to be wrapped
|
||||
/// in a `DigestInfo` structure. This is almost always what you want with
|
||||
/// RSA signatures.
|
||||
#[corresponds(EVP_PKEY_CTX_set_signature_md)]
|
||||
#[inline]
|
||||
pub fn set_signature_md(&self, md: &MdRef) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_signature_md(
|
||||
self.as_ptr(),
|
||||
md.as_ptr(),
|
||||
))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns the RSA padding mode in use.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
@@ -381,6 +447,21 @@ impl<T> PkeyCtxRef<T> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sets the RSA PSS salt length.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
#[corresponds(EVP_PKEY_CTX_set_rsa_pss_saltlen)]
|
||||
#[inline]
|
||||
pub fn set_rsa_pss_saltlen(&mut self, len: RsaPssSaltlen) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_rsa_pss_saltlen(
|
||||
self.as_ptr(),
|
||||
len.as_raw(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the RSA MGF1 algorithm.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
@@ -401,7 +482,7 @@ impl<T> PkeyCtxRef<T> {
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
#[corresponds(EVP_PKEY_CTX_set_rsa_oaep_md)]
|
||||
#[cfg(any(ossl102, libressl310))]
|
||||
#[cfg(any(ossl102, libressl310, boringssl))]
|
||||
#[inline]
|
||||
pub fn set_rsa_oaep_md(&mut self, md: &MdRef) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
@@ -485,7 +566,7 @@ impl<T> PkeyCtxRef<T> {
|
||||
///
|
||||
/// Requires OpenSSL 1.1.0 or newer.
|
||||
#[corresponds(EVP_PKEY_CTX_set_hkdf_md)]
|
||||
#[cfg(ossl110)]
|
||||
#[cfg(any(ossl110, boringssl))]
|
||||
#[inline]
|
||||
pub fn set_hkdf_md(&mut self, digest: &MdRef) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
@@ -527,10 +608,13 @@ impl<T> PkeyCtxRef<T> {
|
||||
///
|
||||
/// Requires OpenSSL 1.1.0 or newer.
|
||||
#[corresponds(EVP_PKEY_CTX_set1_hkdf_key)]
|
||||
#[cfg(ossl110)]
|
||||
#[cfg(any(ossl110, boringssl))]
|
||||
#[inline]
|
||||
pub fn set_hkdf_key(&mut self, key: &[u8]) -> Result<(), ErrorStack> {
|
||||
#[cfg(not(boringssl))]
|
||||
let len = c_int::try_from(key.len()).unwrap();
|
||||
#[cfg(boringssl)]
|
||||
let len = key.len();
|
||||
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set1_hkdf_key(
|
||||
@@ -549,10 +633,13 @@ impl<T> PkeyCtxRef<T> {
|
||||
///
|
||||
/// Requires OpenSSL 1.1.0 or newer.
|
||||
#[corresponds(EVP_PKEY_CTX_set1_hkdf_salt)]
|
||||
#[cfg(ossl110)]
|
||||
#[cfg(any(ossl110, boringssl))]
|
||||
#[inline]
|
||||
pub fn set_hkdf_salt(&mut self, salt: &[u8]) -> Result<(), ErrorStack> {
|
||||
#[cfg(not(boringssl))]
|
||||
let len = c_int::try_from(salt.len()).unwrap();
|
||||
#[cfg(boringssl)]
|
||||
let len = salt.len();
|
||||
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set1_hkdf_salt(
|
||||
@@ -571,10 +658,13 @@ impl<T> PkeyCtxRef<T> {
|
||||
///
|
||||
/// Requires OpenSSL 1.1.0 or newer.
|
||||
#[corresponds(EVP_PKEY_CTX_add1_hkdf_info)]
|
||||
#[cfg(ossl110)]
|
||||
#[cfg(any(ossl110, boringssl))]
|
||||
#[inline]
|
||||
pub fn add_hkdf_info(&mut self, info: &[u8]) -> Result<(), ErrorStack> {
|
||||
#[cfg(not(boringssl))]
|
||||
let len = c_int::try_from(info.len()).unwrap();
|
||||
#[cfg(boringssl)]
|
||||
let len = info.len();
|
||||
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_add1_hkdf_info(
|
||||
@@ -632,11 +722,12 @@ mod test {
|
||||
#[cfg(not(boringssl))]
|
||||
use crate::cipher::Cipher;
|
||||
use crate::ec::{EcGroup, EcKey};
|
||||
#[cfg(any(ossl102, libressl310))]
|
||||
use crate::hash::{hash, MessageDigest};
|
||||
use crate::md::Md;
|
||||
use crate::nid::Nid;
|
||||
use crate::pkey::PKey;
|
||||
use crate::rsa::Rsa;
|
||||
use crate::sign::Verifier;
|
||||
|
||||
#[test]
|
||||
fn rsa() {
|
||||
@@ -662,7 +753,7 @@ mod test {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(ossl102, libressl310))]
|
||||
#[cfg(any(ossl102, libressl310, boringssl))]
|
||||
fn rsa_oaep() {
|
||||
let key = include_bytes!("../test/rsa.pem");
|
||||
let rsa = Rsa::private_key_from_pem(key).unwrap();
|
||||
@@ -689,6 +780,53 @@ mod test {
|
||||
assert_eq!(pt, out);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rsa_sign() {
|
||||
let key = include_bytes!("../test/rsa.pem");
|
||||
let rsa = Rsa::private_key_from_pem(key).unwrap();
|
||||
let pkey = PKey::from_rsa(rsa).unwrap();
|
||||
|
||||
let mut ctx = PkeyCtx::new(&pkey).unwrap();
|
||||
ctx.sign_init().unwrap();
|
||||
ctx.set_rsa_padding(Padding::PKCS1).unwrap();
|
||||
ctx.set_signature_md(Md::sha384()).unwrap();
|
||||
|
||||
let msg = b"hello world";
|
||||
let digest = hash(MessageDigest::sha384(), msg).unwrap();
|
||||
let mut signature = vec![];
|
||||
ctx.sign_to_vec(&digest, &mut signature).unwrap();
|
||||
|
||||
let mut verifier = Verifier::new(MessageDigest::sha384(), &pkey).unwrap();
|
||||
verifier.update(msg).unwrap();
|
||||
assert!(matches!(verifier.verify(&signature), Ok(true)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rsa_sign_pss() {
|
||||
let key = include_bytes!("../test/rsa.pem");
|
||||
let rsa = Rsa::private_key_from_pem(key).unwrap();
|
||||
let pkey = PKey::from_rsa(rsa).unwrap();
|
||||
|
||||
let mut ctx = PkeyCtx::new(&pkey).unwrap();
|
||||
ctx.sign_init().unwrap();
|
||||
ctx.set_rsa_padding(Padding::PKCS1_PSS).unwrap();
|
||||
ctx.set_signature_md(Md::sha384()).unwrap();
|
||||
ctx.set_rsa_pss_saltlen(RsaPssSaltlen::custom(14)).unwrap();
|
||||
|
||||
let msg = b"hello world";
|
||||
let digest = hash(MessageDigest::sha384(), msg).unwrap();
|
||||
let mut signature = vec![];
|
||||
ctx.sign_to_vec(&digest, &mut signature).unwrap();
|
||||
|
||||
let mut verifier = Verifier::new(MessageDigest::sha384(), &pkey).unwrap();
|
||||
verifier.set_rsa_padding(Padding::PKCS1_PSS).unwrap();
|
||||
verifier
|
||||
.set_rsa_pss_saltlen(RsaPssSaltlen::custom(14))
|
||||
.unwrap();
|
||||
verifier.update(msg).unwrap();
|
||||
assert!(matches!(verifier.verify(&signature), Ok(true)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn derive() {
|
||||
let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
|
||||
@@ -717,7 +855,7 @@ mod test {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl110)]
|
||||
#[cfg(any(ossl110, boringssl))]
|
||||
fn hkdf() {
|
||||
let mut ctx = PkeyCtx::new_id(Id::HKDF).unwrap();
|
||||
ctx.derive_init().unwrap();
|
||||
@@ -798,7 +936,67 @@ mod test {
|
||||
let bad_data = b"Some Crypto text";
|
||||
|
||||
ctx.verify_init().unwrap();
|
||||
let valid = ctx.verify(bad_data, &signature).unwrap();
|
||||
assert!(!valid);
|
||||
let valid = ctx.verify(bad_data, &signature);
|
||||
assert!(matches!(valid, Ok(false) | Err(_)));
|
||||
assert!(ErrorStack::get().errors().is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn verify_fail_ec() {
|
||||
let key1 =
|
||||
EcKey::generate(&EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap()).unwrap();
|
||||
let key1 = PKey::from_ec_key(key1).unwrap();
|
||||
|
||||
let data = b"Some Crypto Text";
|
||||
let mut ctx = PkeyCtx::new(&key1).unwrap();
|
||||
ctx.verify_init().unwrap();
|
||||
assert!(matches!(ctx.verify(data, &[0; 64]), Ok(false) | Err(_)));
|
||||
assert!(ErrorStack::get().errors().is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_verify_recover() {
|
||||
let key = Rsa::generate(2048).unwrap();
|
||||
let key = PKey::from_rsa(key).unwrap();
|
||||
|
||||
let digest = [
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
|
||||
24, 25, 26, 27, 28, 29, 30, 31,
|
||||
];
|
||||
|
||||
let mut ctx = PkeyCtx::new(&key).unwrap();
|
||||
ctx.sign_init().unwrap();
|
||||
ctx.set_rsa_padding(Padding::PKCS1).unwrap();
|
||||
ctx.set_signature_md(Md::sha256()).unwrap();
|
||||
let mut signature = vec![];
|
||||
ctx.sign_to_vec(&digest, &mut signature).unwrap();
|
||||
|
||||
// Attempt recovery of just the digest.
|
||||
let mut ctx = PkeyCtx::new(&key).unwrap();
|
||||
ctx.verify_recover_init().unwrap();
|
||||
ctx.set_rsa_padding(Padding::PKCS1).unwrap();
|
||||
ctx.set_signature_md(Md::sha256()).unwrap();
|
||||
let length = ctx.verify_recover(&signature, None).unwrap();
|
||||
let mut result_buf = vec![0; length];
|
||||
let length = ctx
|
||||
.verify_recover(&signature, Some(&mut result_buf))
|
||||
.unwrap();
|
||||
assert_eq!(length, digest.len());
|
||||
// result_buf contains the digest
|
||||
assert_eq!(result_buf[..length], digest);
|
||||
|
||||
// Attempt recovery of teh entire DigestInfo
|
||||
let mut ctx = PkeyCtx::new(&key).unwrap();
|
||||
ctx.verify_recover_init().unwrap();
|
||||
ctx.set_rsa_padding(Padding::PKCS1).unwrap();
|
||||
let length = ctx.verify_recover(&signature, None).unwrap();
|
||||
let mut result_buf = vec![0; length];
|
||||
let length = ctx
|
||||
.verify_recover(&signature, Some(&mut result_buf))
|
||||
.unwrap();
|
||||
// 32-bytes of SHA256 digest + the ASN.1 DigestInfo structure == 51 bytes
|
||||
assert_eq!(length, 51);
|
||||
// The digest is the end of the DigestInfo structure.
|
||||
assert_eq!(result_buf[length - digest.len()..length], digest);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -581,7 +581,7 @@ impl<T> fmt::Debug for Rsa<T> {
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl110, libressl273))] {
|
||||
if #[cfg(any(ossl110, libressl273, boringssl))] {
|
||||
use ffi::{
|
||||
RSA_get0_key, RSA_get0_factors, RSA_get0_crt_params, RSA_set0_key, RSA_set0_factors,
|
||||
RSA_set0_crt_params,
|
||||
|
||||
+9
-9
@@ -93,7 +93,7 @@ pub struct RsaPssSaltlen(c_int);
|
||||
|
||||
impl RsaPssSaltlen {
|
||||
/// Returns the integer representation of `RsaPssSaltlen`.
|
||||
fn as_raw(&self) -> c_int {
|
||||
pub(crate) fn as_raw(&self) -> c_int {
|
||||
self.0
|
||||
}
|
||||
|
||||
@@ -117,10 +117,10 @@ pub struct Signer<'a> {
|
||||
_p: PhantomData<&'a ()>,
|
||||
}
|
||||
|
||||
unsafe impl<'a> Sync for Signer<'a> {}
|
||||
unsafe impl<'a> Send for Signer<'a> {}
|
||||
unsafe impl Sync for Signer<'_> {}
|
||||
unsafe impl Send for Signer<'_> {}
|
||||
|
||||
impl<'a> Drop for Signer<'a> {
|
||||
impl Drop for Signer<'_> {
|
||||
fn drop(&mut self) {
|
||||
// pkey_ctx is owned by the md_ctx, so no need to explicitly free it.
|
||||
unsafe {
|
||||
@@ -130,7 +130,7 @@ impl<'a> Drop for Signer<'a> {
|
||||
}
|
||||
|
||||
#[allow(clippy::len_without_is_empty)]
|
||||
impl<'a> Signer<'a> {
|
||||
impl Signer<'_> {
|
||||
/// Creates a new `Signer`.
|
||||
///
|
||||
/// This cannot be used with Ed25519 or Ed448 keys. Please refer to
|
||||
@@ -139,7 +139,7 @@ impl<'a> Signer<'a> {
|
||||
/// OpenSSL documentation at [`EVP_DigestSignInit`].
|
||||
///
|
||||
/// [`EVP_DigestSignInit`]: https://www.openssl.org/docs/manmaster/man3/EVP_DigestSignInit.html
|
||||
pub fn new<T>(type_: MessageDigest, pkey: &'a PKeyRef<T>) -> Result<Signer<'a>, ErrorStack>
|
||||
pub fn new<'a, T>(type_: MessageDigest, pkey: &PKeyRef<T>) -> Result<Signer<'a>, ErrorStack>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
@@ -154,16 +154,16 @@ impl<'a> Signer<'a> {
|
||||
/// OpenSSL documentation at [`EVP_DigestSignInit`].
|
||||
///
|
||||
/// [`EVP_DigestSignInit`]: https://www.openssl.org/docs/manmaster/man3/EVP_DigestSignInit.html
|
||||
pub fn new_without_digest<T>(pkey: &'a PKeyRef<T>) -> Result<Signer<'a>, ErrorStack>
|
||||
pub fn new_without_digest<'a, T>(pkey: &PKeyRef<T>) -> Result<Signer<'a>, ErrorStack>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
Self::new_intern(None, pkey)
|
||||
}
|
||||
|
||||
fn new_intern<T>(
|
||||
fn new_intern<'a, T>(
|
||||
type_: Option<MessageDigest>,
|
||||
pkey: &'a PKeyRef<T>,
|
||||
pkey: &PKeyRef<T>,
|
||||
) -> Result<Signer<'a>, ErrorStack>
|
||||
where
|
||||
T: HasPrivate,
|
||||
|
||||
@@ -11,6 +11,7 @@ use crate::ssl::{
|
||||
SslOptions, SslRef, SslStream, SslVerifyMode,
|
||||
};
|
||||
use crate::version;
|
||||
use std::net::IpAddr;
|
||||
|
||||
const FFDHE_2048: &str = "
|
||||
-----BEGIN DH PARAMETERS-----
|
||||
@@ -177,9 +178,9 @@ impl ConnectConfiguration {
|
||||
|
||||
/// Returns an `Ssl` configured to connect to the provided domain.
|
||||
///
|
||||
/// The domain is used for SNI and hostname verification if enabled.
|
||||
/// The domain is used for SNI (if it is not an IP address) and hostname verification if enabled.
|
||||
pub fn into_ssl(mut self, domain: &str) -> Result<Ssl, ErrorStack> {
|
||||
if self.sni {
|
||||
if self.sni && domain.parse::<IpAddr>().is_err() {
|
||||
self.ssl.set_hostname(domain)?;
|
||||
}
|
||||
|
||||
|
||||
+72
-9
@@ -72,7 +72,7 @@ use crate::srtp::{SrtpProtectionProfile, SrtpProtectionProfileRef};
|
||||
use crate::ssl::bio::BioMethod;
|
||||
use crate::ssl::callbacks::*;
|
||||
use crate::ssl::error::InnerError;
|
||||
use crate::stack::{Stack, StackRef};
|
||||
use crate::stack::{Stack, StackRef, Stackable};
|
||||
use crate::util::{ForeignTypeExt, ForeignTypeRefExt};
|
||||
use crate::x509::store::{X509Store, X509StoreBuilderRef, X509StoreRef};
|
||||
#[cfg(any(ossl102, libressl261))]
|
||||
@@ -599,7 +599,7 @@ impl AlpnError {
|
||||
/// Terminate the handshake with a fatal alert.
|
||||
///
|
||||
/// Requires OpenSSL 1.1.0 or newer.
|
||||
#[cfg(any(ossl110))]
|
||||
#[cfg(ossl110)]
|
||||
pub const ALERT_FATAL: AlpnError = AlpnError(ffi::SSL_TLSEXT_ERR_ALERT_FATAL);
|
||||
|
||||
/// Do not select a protocol, but continue the handshake.
|
||||
@@ -644,6 +644,17 @@ impl SslVersion {
|
||||
/// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.
|
||||
#[cfg(any(ossl111, libressl340))]
|
||||
pub const TLS1_3: SslVersion = SslVersion(ffi::TLS1_3_VERSION);
|
||||
|
||||
/// DTLSv1.0
|
||||
///
|
||||
/// DTLS 1.0 corresponds to TLS 1.1.
|
||||
pub const DTLS1: SslVersion = SslVersion(ffi::DTLS1_VERSION);
|
||||
|
||||
/// DTLSv1.2
|
||||
///
|
||||
/// DTLS 1.2 corresponds to TLS 1.2 to harmonize versions. There was never a DTLS 1.1.
|
||||
#[cfg(any(ossl102, libressl332))]
|
||||
pub const DTLS1_2: SslVersion = SslVersion(ffi::DTLS1_2_VERSION);
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
@@ -1120,7 +1131,7 @@ impl SslContextBuilder {
|
||||
|
||||
/// Sets the minimum supported protocol version.
|
||||
///
|
||||
/// A value of `None` will enable protocol versions down the the lowest version supported by
|
||||
/// A value of `None` will enable protocol versions down to the lowest version supported by
|
||||
/// OpenSSL.
|
||||
///
|
||||
/// Requires OpenSSL 1.1.0 or LibreSSL 2.6.1 or newer.
|
||||
@@ -1138,7 +1149,7 @@ impl SslContextBuilder {
|
||||
|
||||
/// Sets the maximum supported protocol version.
|
||||
///
|
||||
/// A value of `None` will enable protocol versions down the the highest version supported by
|
||||
/// A value of `None` will enable protocol versions up to the highest version supported by
|
||||
/// OpenSSL.
|
||||
///
|
||||
/// Requires OpenSSL 1.1.0 or or LibreSSL 2.6.1 or newer.
|
||||
@@ -1156,7 +1167,7 @@ impl SslContextBuilder {
|
||||
|
||||
/// Gets the minimum supported protocol version.
|
||||
///
|
||||
/// A value of `None` indicates that all versions down the the lowest version supported by
|
||||
/// A value of `None` indicates that all versions down to the lowest version supported by
|
||||
/// OpenSSL are enabled.
|
||||
///
|
||||
/// Requires OpenSSL 1.1.0g or LibreSSL 2.7.0 or newer.
|
||||
@@ -1175,7 +1186,7 @@ impl SslContextBuilder {
|
||||
|
||||
/// Gets the maximum supported protocol version.
|
||||
///
|
||||
/// A value of `None` indicates that all versions down the the highest version supported by
|
||||
/// A value of `None` indicates that all versions up to the highest version supported by
|
||||
/// OpenSSL are enabled.
|
||||
///
|
||||
/// Requires OpenSSL 1.1.0g or LibreSSL 2.7.0 or newer.
|
||||
@@ -1929,6 +1940,10 @@ impl ForeignType for SslCipher {
|
||||
}
|
||||
}
|
||||
|
||||
impl Stackable for SslCipher {
|
||||
type StackType = ffi::stack_st_SSL_CIPHER;
|
||||
}
|
||||
|
||||
impl Deref for SslCipher {
|
||||
type Target = SslCipherRef;
|
||||
|
||||
@@ -2045,6 +2060,19 @@ impl SslCipherRef {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for SslCipherRef {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(fmt, "{}", self.name())
|
||||
}
|
||||
}
|
||||
|
||||
/// A stack of selected ciphers, and a stack of selected signalling cipher suites
|
||||
#[derive(Debug)]
|
||||
pub struct CipherLists {
|
||||
pub suites: Stack<SslCipher>,
|
||||
pub signalling_suites: Stack<SslCipher>,
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::SSL_SESSION;
|
||||
fn drop = ffi::SSL_SESSION_free;
|
||||
@@ -2385,7 +2413,7 @@ impl SslRef {
|
||||
///
|
||||
/// Requires OpenSSL 1.0.1 or 1.0.2.
|
||||
#[corresponds(SSL_set_tmp_ecdh_callback)]
|
||||
#[cfg(any(all(ossl101, not(ossl110))))]
|
||||
#[cfg(all(ossl101, not(ossl110)))]
|
||||
#[deprecated(note = "this function leaks memory and does not exist on newer OpenSSL versions")]
|
||||
pub fn set_tmp_ecdh_callback<F>(&mut self, callback: F)
|
||||
where
|
||||
@@ -3072,6 +3100,41 @@ impl SslRef {
|
||||
}
|
||||
}
|
||||
|
||||
/// Decodes a slice of wire-format cipher suite specification bytes. Unsupported cipher suites
|
||||
/// are ignored.
|
||||
///
|
||||
/// Requires OpenSSL 1.1.1 or newer.
|
||||
#[corresponds(SSL_bytes_to_cipher_list)]
|
||||
#[cfg(ossl111)]
|
||||
pub fn bytes_to_cipher_list(
|
||||
&self,
|
||||
bytes: &[u8],
|
||||
isv2format: bool,
|
||||
) -> Result<CipherLists, ErrorStack> {
|
||||
unsafe {
|
||||
let ptr = bytes.as_ptr();
|
||||
let len = bytes.len();
|
||||
let mut sk = ptr::null_mut();
|
||||
let mut scsvs = ptr::null_mut();
|
||||
let res = ffi::SSL_bytes_to_cipher_list(
|
||||
self.as_ptr(),
|
||||
ptr,
|
||||
len,
|
||||
isv2format as c_int,
|
||||
&mut sk,
|
||||
&mut scsvs,
|
||||
);
|
||||
if res == 1 {
|
||||
Ok(CipherLists {
|
||||
suites: Stack::from_ptr(sk),
|
||||
signalling_suites: Stack::from_ptr(scsvs),
|
||||
})
|
||||
} else {
|
||||
Err(ErrorStack::get())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the compression methods field of the client's hello message.
|
||||
///
|
||||
/// This can only be used inside of the client hello callback. Otherwise, `None` is returned.
|
||||
@@ -3223,7 +3286,7 @@ impl SslRef {
|
||||
|
||||
/// Sets the minimum supported protocol version.
|
||||
///
|
||||
/// A value of `None` will enable protocol versions down the the lowest version supported by
|
||||
/// A value of `None` will enable protocol versions down to the lowest version supported by
|
||||
/// OpenSSL.
|
||||
///
|
||||
/// Requires OpenSSL 1.1.0 or LibreSSL 2.6.1 or newer.
|
||||
@@ -3241,7 +3304,7 @@ impl SslRef {
|
||||
|
||||
/// Sets the maximum supported protocol version.
|
||||
///
|
||||
/// A value of `None` will enable protocol versions down the the highest version supported by
|
||||
/// A value of `None` will enable protocol versions up to the highest version supported by
|
||||
/// OpenSSL.
|
||||
///
|
||||
/// Requires OpenSSL 1.1.0 or or LibreSSL 2.6.1 or newer.
|
||||
|
||||
@@ -21,10 +21,10 @@ use crate::hash::MessageDigest;
|
||||
use crate::ocsp::{OcspResponse, OcspResponseStatus};
|
||||
use crate::pkey::PKey;
|
||||
use crate::srtp::SrtpProfileId;
|
||||
use crate::ssl;
|
||||
use crate::ssl::test::server::Server;
|
||||
#[cfg(any(ossl110, ossl111, libressl261))]
|
||||
use crate::ssl::SslVersion;
|
||||
use crate::ssl::{self, NameType, SslConnectorBuilder};
|
||||
#[cfg(ossl111)]
|
||||
use crate::ssl::{ClientHelloResponse, ExtensionContext};
|
||||
use crate::ssl::{
|
||||
@@ -467,7 +467,7 @@ fn test_alpn_server_advertise_multiple() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(ossl110))]
|
||||
#[cfg(ossl110)]
|
||||
fn test_alpn_server_select_none_fatal() {
|
||||
let mut server = Server::builder();
|
||||
server.ctx().set_alpn_select_callback(|_, client| {
|
||||
@@ -767,6 +767,61 @@ fn connector_can_disable_verify() {
|
||||
s.read_exact(&mut [0]).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn connector_does_use_sni_with_dnsnames() {
|
||||
static CALLED_BACK: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
let mut builder = Server::builder();
|
||||
builder.ctx().set_servername_callback(|ssl, _| {
|
||||
assert_eq!(ssl.servername(NameType::HOST_NAME), Some("foobar.com"));
|
||||
CALLED_BACK.store(true, Ordering::SeqCst);
|
||||
Ok(())
|
||||
});
|
||||
let server = builder.build();
|
||||
|
||||
let mut connector = SslConnector::builder(SslMethod::tls()).unwrap();
|
||||
connector.set_ca_file("test/root-ca.pem").unwrap();
|
||||
|
||||
let s = server.connect_tcp();
|
||||
let mut s = connector
|
||||
.build()
|
||||
.configure()
|
||||
.unwrap()
|
||||
.connect("foobar.com", s)
|
||||
.unwrap();
|
||||
s.read_exact(&mut [0]).unwrap();
|
||||
|
||||
assert!(CALLED_BACK.load(Ordering::SeqCst));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn connector_doesnt_use_sni_with_ips() {
|
||||
static CALLED_BACK: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
let mut builder = Server::builder();
|
||||
builder.ctx().set_servername_callback(|ssl, _| {
|
||||
assert_eq!(ssl.servername(NameType::HOST_NAME), None);
|
||||
CALLED_BACK.store(true, Ordering::SeqCst);
|
||||
Ok(())
|
||||
});
|
||||
let server = builder.build();
|
||||
|
||||
let mut connector = SslConnector::builder(SslMethod::tls()).unwrap();
|
||||
// The server's cert isn't issued for 127.0.0.1 but we don't care for this test.
|
||||
connector.set_verify(SslVerifyMode::NONE);
|
||||
|
||||
let s = server.connect_tcp();
|
||||
let mut s = connector
|
||||
.build()
|
||||
.configure()
|
||||
.unwrap()
|
||||
.connect("127.0.0.1", s)
|
||||
.unwrap();
|
||||
s.read_exact(&mut [0]).unwrap();
|
||||
|
||||
assert!(CALLED_BACK.load(Ordering::SeqCst));
|
||||
}
|
||||
|
||||
fn test_mozilla_server(new: fn(SslMethod) -> Result<SslAcceptorBuilder, ErrorStack>) {
|
||||
let listener = TcpListener::bind("127.0.0.1:0").unwrap();
|
||||
let port = listener.local_addr().unwrap().port();
|
||||
@@ -1403,6 +1458,9 @@ fn client_hello() {
|
||||
assert!(ssl.client_hello_session_id().is_some());
|
||||
assert!(ssl.client_hello_ciphers().is_some());
|
||||
assert!(ssl.client_hello_compression_methods().is_some());
|
||||
assert!(ssl
|
||||
.bytes_to_cipher_list(ssl.client_hello_ciphers().unwrap(), ssl.client_hello_isv2())
|
||||
.is_ok());
|
||||
|
||||
CALLED_BACK.store(true, Ordering::SeqCst);
|
||||
Ok(ClientHelloResponse::SUCCESS)
|
||||
|
||||
+10
-9
@@ -142,7 +142,7 @@ impl Cipher {
|
||||
}
|
||||
|
||||
/// Requires OpenSSL 1.1.0 or newer.
|
||||
#[cfg(ossl110)]
|
||||
#[cfg(all(ossl110, not(osslconf = "OPENSSL_NO_OCB")))]
|
||||
pub fn aes_128_ocb() -> Cipher {
|
||||
unsafe { Cipher(ffi::EVP_aes_128_ocb()) }
|
||||
}
|
||||
@@ -187,7 +187,7 @@ impl Cipher {
|
||||
}
|
||||
|
||||
/// Requires OpenSSL 1.1.0 or newer.
|
||||
#[cfg(ossl110)]
|
||||
#[cfg(all(ossl110, not(osslconf = "OPENSSL_NO_OCB")))]
|
||||
pub fn aes_192_ocb() -> Cipher {
|
||||
unsafe { Cipher(ffi::EVP_aes_192_ocb()) }
|
||||
}
|
||||
@@ -237,7 +237,7 @@ impl Cipher {
|
||||
}
|
||||
|
||||
/// Requires OpenSSL 1.1.0 or newer.
|
||||
#[cfg(ossl110)]
|
||||
#[cfg(all(ossl110, not(osslconf = "OPENSSL_NO_OCB")))]
|
||||
pub fn aes_256_ocb() -> Cipher {
|
||||
unsafe { Cipher(ffi::EVP_aes_256_ocb()) }
|
||||
}
|
||||
@@ -283,6 +283,7 @@ impl Cipher {
|
||||
unsafe { Cipher(ffi::EVP_des_ede3_cfb64()) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_RC4"))]
|
||||
pub fn rc4() -> Cipher {
|
||||
unsafe { Cipher(ffi::EVP_rc4()) }
|
||||
}
|
||||
@@ -401,14 +402,14 @@ impl Cipher {
|
||||
}
|
||||
|
||||
/// Determines whether the cipher is using OCB mode
|
||||
#[cfg(ossl110)]
|
||||
#[cfg(all(ossl110, not(osslconf = "OPENSSL_NO_OCB")))]
|
||||
fn is_ocb(self) -> bool {
|
||||
self == Cipher::aes_128_ocb()
|
||||
|| self == Cipher::aes_192_ocb()
|
||||
|| self == Cipher::aes_256_ocb()
|
||||
}
|
||||
|
||||
#[cfg(not(ossl110))]
|
||||
#[cfg(any(not(ossl110), osslconf = "OPENSSL_NO_OCB"))]
|
||||
const fn is_ocb(self) -> bool {
|
||||
false
|
||||
}
|
||||
@@ -1421,7 +1422,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl110)]
|
||||
#[cfg(all(ossl110, not(osslconf = "OPENSSL_NO_OCB")))]
|
||||
fn test_aes_128_ocb() {
|
||||
let key = "000102030405060708090a0b0c0d0e0f";
|
||||
let aad = "0001020304050607";
|
||||
@@ -1457,7 +1458,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl110)]
|
||||
#[cfg(all(ossl110, not(osslconf = "OPENSSL_NO_OCB")))]
|
||||
fn test_aes_128_ocb_fail() {
|
||||
let key = "000102030405060708090a0b0c0d0e0f";
|
||||
let aad = "0001020304050607";
|
||||
@@ -1477,7 +1478,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(ossl110))]
|
||||
#[cfg(ossl110)]
|
||||
fn test_chacha20() {
|
||||
let key = "0000000000000000000000000000000000000000000000000000000000000000";
|
||||
let iv = "00000000000000000000000000000000";
|
||||
@@ -1492,7 +1493,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(ossl110))]
|
||||
#[cfg(ossl110)]
|
||||
fn test_chacha20_poly1305() {
|
||||
let key = "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f";
|
||||
let iv = "070000004041424344454647";
|
||||
|
||||
@@ -67,6 +67,9 @@ impl BasicConstraints {
|
||||
}
|
||||
|
||||
/// Return the `BasicConstraints` extension as an `X509Extension`.
|
||||
// Temporarily silence the deprecation warning - this should be ported to
|
||||
// `X509Extension::new_internal`.
|
||||
#[allow(deprecated)]
|
||||
pub fn build(&self) -> Result<X509Extension, ErrorStack> {
|
||||
let mut value = String::new();
|
||||
if self.critical {
|
||||
@@ -183,6 +186,9 @@ impl KeyUsage {
|
||||
}
|
||||
|
||||
/// Return the `KeyUsage` extension as an `X509Extension`.
|
||||
// Temporarily silence the deprecation warning - this should be ported to
|
||||
// `X509Extension::new_internal`.
|
||||
#[allow(deprecated)]
|
||||
pub fn build(&self) -> Result<X509Extension, ErrorStack> {
|
||||
let mut value = String::new();
|
||||
let mut first = true;
|
||||
@@ -346,6 +352,9 @@ impl SubjectKeyIdentifier {
|
||||
}
|
||||
|
||||
/// Return a `SubjectKeyIdentifier` extension as an `X509Extension`.
|
||||
// Temporarily silence the deprecation warning - this should be ported to
|
||||
// `X509Extension::new_internal`.
|
||||
#[allow(deprecated)]
|
||||
pub fn build(&self, ctx: &X509v3Context<'_>) -> Result<X509Extension, ErrorStack> {
|
||||
let mut value = String::new();
|
||||
let mut first = true;
|
||||
@@ -398,6 +407,9 @@ impl AuthorityKeyIdentifier {
|
||||
}
|
||||
|
||||
/// Return a `AuthorityKeyIdentifier` extension as an `X509Extension`.
|
||||
// Temporarily silence the deprecation warning - this should be ported to
|
||||
// `X509Extension::new_internal`.
|
||||
#[allow(deprecated)]
|
||||
pub fn build(&self, ctx: &X509v3Context<'_>) -> Result<X509Extension, ErrorStack> {
|
||||
let mut value = String::new();
|
||||
let mut first = true;
|
||||
@@ -422,6 +434,7 @@ enum RustGeneralName {
|
||||
Uri(String),
|
||||
Ip(String),
|
||||
Rid(String),
|
||||
OtherName(Asn1Object, Vec<u8>),
|
||||
}
|
||||
|
||||
/// An extension that allows additional identities to be bound to the subject
|
||||
@@ -494,12 +507,21 @@ impl SubjectAlternativeName {
|
||||
|
||||
/// Sets the `otherName` flag.
|
||||
///
|
||||
/// Not currently actually supported, always panics.
|
||||
#[deprecated = "other_name is deprecated and always panics. Please file a bug if you have a use case for this."]
|
||||
/// Not currently actually supported, always panics. Please use other_name2
|
||||
#[deprecated = "other_name is deprecated and always panics. Please use other_name2."]
|
||||
pub fn other_name(&mut self, _other_name: &str) -> &mut SubjectAlternativeName {
|
||||
unimplemented!(
|
||||
"This has not yet been adapted for the new internals. File a bug if you need this."
|
||||
);
|
||||
unimplemented!("This has not yet been adapted for the new internals. Use other_name2.");
|
||||
}
|
||||
|
||||
/// Sets the `otherName` flag.
|
||||
///
|
||||
/// `content` must be a valid der encoded ASN1_TYPE
|
||||
///
|
||||
/// If you want to add just a ia5string use `other_name_ia5string`
|
||||
pub fn other_name2(&mut self, oid: Asn1Object, content: &[u8]) -> &mut SubjectAlternativeName {
|
||||
self.items
|
||||
.push(RustGeneralName::OtherName(oid, content.into()));
|
||||
self
|
||||
}
|
||||
|
||||
/// Return a `SubjectAlternativeName` extension as an `X509Extension`.
|
||||
@@ -514,6 +536,9 @@ impl SubjectAlternativeName {
|
||||
GeneralName::new_ip(s.parse().map_err(|_| ErrorStack::get())?)?
|
||||
}
|
||||
RustGeneralName::Rid(s) => GeneralName::new_rid(Asn1Object::from_str(s)?)?,
|
||||
RustGeneralName::OtherName(oid, content) => {
|
||||
GeneralName::new_other_name(oid.clone(), content)?
|
||||
}
|
||||
};
|
||||
stack.push(gn)?;
|
||||
}
|
||||
|
||||
+317
-15
@@ -24,8 +24,8 @@ use std::slice;
|
||||
use std::str;
|
||||
|
||||
use crate::asn1::{
|
||||
Asn1BitStringRef, Asn1IntegerRef, Asn1Object, Asn1ObjectRef, Asn1StringRef, Asn1TimeRef,
|
||||
Asn1Type,
|
||||
Asn1BitStringRef, Asn1Enumerated, Asn1IntegerRef, Asn1Object, Asn1ObjectRef,
|
||||
Asn1OctetStringRef, Asn1StringRef, Asn1TimeRef, Asn1Type,
|
||||
};
|
||||
use crate::bio::MemBioSlice;
|
||||
use crate::conf::ConfRef;
|
||||
@@ -50,6 +50,16 @@ pub mod store;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
/// A type of X509 extension.
|
||||
///
|
||||
/// # Safety
|
||||
/// The value of NID and Output must match those in OpenSSL so that
|
||||
/// `Output::from_ptr_opt(*_get_ext_d2i(*, NID, ...))` is valid.
|
||||
pub unsafe trait ExtensionType {
|
||||
const NID: Nid;
|
||||
type Output: ForeignType;
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::X509_STORE_CTX;
|
||||
fn drop = ffi::X509_STORE_CTX_free;
|
||||
@@ -391,7 +401,10 @@ impl X509Ref {
|
||||
/// Returns the hash of the certificates subject
|
||||
#[corresponds(X509_subject_name_hash)]
|
||||
pub fn subject_name_hash(&self) -> u32 {
|
||||
unsafe { ffi::X509_subject_name_hash(self.as_ptr()) as u32 }
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
unsafe {
|
||||
ffi::X509_subject_name_hash(self.as_ptr()) as u32
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns this certificate's issuer name.
|
||||
@@ -406,7 +419,10 @@ impl X509Ref {
|
||||
/// Returns the hash of the certificates issuer
|
||||
#[corresponds(X509_issuer_name_hash)]
|
||||
pub fn issuer_name_hash(&self) -> u32 {
|
||||
unsafe { ffi::X509_issuer_name_hash(self.as_ptr()) as u32 }
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
unsafe {
|
||||
ffi::X509_issuer_name_hash(self.as_ptr()) as u32
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns this certificate's subject alternative name entries, if they exist.
|
||||
@@ -423,6 +439,20 @@ impl X509Ref {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns this certificate's CRL distribution points, if they exist.
|
||||
#[corresponds(X509_get_ext_d2i)]
|
||||
pub fn crl_distribution_points(&self) -> Option<Stack<DistPoint>> {
|
||||
unsafe {
|
||||
let stack = ffi::X509_get_ext_d2i(
|
||||
self.as_ptr(),
|
||||
ffi::NID_crl_distribution_points,
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
);
|
||||
Stack::from_ptr_opt(stack as *mut _)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns this certificate's issuer alternative name entries, if they exist.
|
||||
#[corresponds(X509_get_ext_d2i)]
|
||||
pub fn issuer_alt_names(&self) -> Option<Stack<GeneralName>> {
|
||||
@@ -453,6 +483,54 @@ impl X509Ref {
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the path length extension from a certificate, if it exists.
|
||||
#[corresponds(X509_get_pathlen)]
|
||||
#[cfg(ossl110)]
|
||||
pub fn pathlen(&self) -> Option<u32> {
|
||||
let v = unsafe { ffi::X509_get_pathlen(self.as_ptr()) };
|
||||
u32::try_from(v).ok()
|
||||
}
|
||||
|
||||
/// Returns this certificate's subject key id, if it exists.
|
||||
#[corresponds(X509_get0_subject_key_id)]
|
||||
#[cfg(ossl110)]
|
||||
pub fn subject_key_id(&self) -> Option<&Asn1OctetStringRef> {
|
||||
unsafe {
|
||||
let data = ffi::X509_get0_subject_key_id(self.as_ptr());
|
||||
Asn1OctetStringRef::from_const_ptr_opt(data)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns this certificate's authority key id, if it exists.
|
||||
#[corresponds(X509_get0_authority_key_id)]
|
||||
#[cfg(ossl110)]
|
||||
pub fn authority_key_id(&self) -> Option<&Asn1OctetStringRef> {
|
||||
unsafe {
|
||||
let data = ffi::X509_get0_authority_key_id(self.as_ptr());
|
||||
Asn1OctetStringRef::from_const_ptr_opt(data)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns this certificate's authority issuer name entries, if they exist.
|
||||
#[corresponds(X509_get0_authority_issuer)]
|
||||
#[cfg(ossl111d)]
|
||||
pub fn authority_issuer(&self) -> Option<&StackRef<GeneralName>> {
|
||||
unsafe {
|
||||
let stack = ffi::X509_get0_authority_issuer(self.as_ptr());
|
||||
StackRef::from_const_ptr_opt(stack)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns this certificate's authority serial number, if it exists.
|
||||
#[corresponds(X509_get0_authority_serial)]
|
||||
#[cfg(ossl111d)]
|
||||
pub fn authority_serial(&self) -> Option<&Asn1IntegerRef> {
|
||||
unsafe {
|
||||
let r = ffi::X509_get0_authority_serial(self.as_ptr());
|
||||
Asn1IntegerRef::from_const_ptr_opt(r)
|
||||
}
|
||||
}
|
||||
|
||||
#[corresponds(X509_get_pubkey)]
|
||||
pub fn public_key(&self) -> Result<PKey<Public>, ErrorStack> {
|
||||
unsafe {
|
||||
@@ -548,6 +626,7 @@ impl X509Ref {
|
||||
/// Note that `0` return value stands for version 1, `1` for version 2 and so on.
|
||||
#[corresponds(X509_get_version)]
|
||||
#[cfg(ossl110)]
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
pub fn version(&self) -> i32 {
|
||||
unsafe { ffi::X509_get_version(self.as_ptr()) as i32 }
|
||||
}
|
||||
@@ -811,6 +890,13 @@ impl X509Extension {
|
||||
/// mini-language that can read arbitrary files.
|
||||
///
|
||||
/// See the extension module for builder types which will construct certain common extensions.
|
||||
///
|
||||
/// This function is deprecated, `X509Extension::new_from_der` or the
|
||||
/// types in `x509::extension` should be used in its place.
|
||||
#[deprecated(
|
||||
note = "Use x509::extension types or new_from_der instead",
|
||||
since = "0.10.51"
|
||||
)]
|
||||
pub fn new(
|
||||
conf: Option<&ConfRef>,
|
||||
context: Option<&X509v3Context<'_>>,
|
||||
@@ -856,6 +942,13 @@ impl X509Extension {
|
||||
/// mini-language that can read arbitrary files.
|
||||
///
|
||||
/// See the extension module for builder types which will construct certain common extensions.
|
||||
///
|
||||
/// This function is deprecated, `X509Extension::new_from_der` or the
|
||||
/// types in `x509::extension` should be used in its place.
|
||||
#[deprecated(
|
||||
note = "Use x509::extension types or new_from_der instead",
|
||||
since = "0.10.51"
|
||||
)]
|
||||
pub fn new_nid(
|
||||
conf: Option<&ConfRef>,
|
||||
context: Option<&X509v3Context<'_>>,
|
||||
@@ -890,6 +983,31 @@ impl X509Extension {
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs a new X509 extension value from its OID, whether it's
|
||||
/// critical, and its DER contents.
|
||||
///
|
||||
/// The extent structure of the DER value will vary based on the
|
||||
/// extension type, and can generally be found in the RFC defining the
|
||||
/// extension.
|
||||
///
|
||||
/// For common extension types, there are Rust APIs provided in
|
||||
/// `openssl::x509::extensions` which are more ergonomic.
|
||||
pub fn new_from_der(
|
||||
oid: &Asn1ObjectRef,
|
||||
critical: bool,
|
||||
der_contents: &Asn1OctetStringRef,
|
||||
) -> Result<X509Extension, ErrorStack> {
|
||||
unsafe {
|
||||
cvt_p(ffi::X509_EXTENSION_create_by_OBJ(
|
||||
ptr::null_mut(),
|
||||
oid.as_ptr(),
|
||||
critical as _,
|
||||
der_contents.as_ptr(),
|
||||
))
|
||||
.map(X509Extension)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn new_internal(
|
||||
nid: Nid,
|
||||
critical: bool,
|
||||
@@ -905,6 +1023,10 @@ impl X509Extension {
|
||||
///
|
||||
/// This method modifies global state without locking and therefore is not thread safe
|
||||
#[corresponds(X509V3_EXT_add_alias)]
|
||||
#[deprecated(
|
||||
note = "Use x509::extension types or new_from_der and then this is not necessary",
|
||||
since = "0.10.51"
|
||||
)]
|
||||
pub unsafe fn add_alias(to: Nid, from: Nid) -> Result<(), ErrorStack> {
|
||||
ffi::init();
|
||||
cvt(ffi::X509V3_EXT_add_alias(to.as_raw(), from.as_raw())).map(|_| ())
|
||||
@@ -955,13 +1077,13 @@ impl X509NameBuilder {
|
||||
pub fn append_entry_by_text(&mut self, field: &str, value: &str) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
let field = CString::new(field).unwrap();
|
||||
assert!(value.len() <= c_int::max_value() as usize);
|
||||
assert!(value.len() <= crate::SLenType::max_value() as usize);
|
||||
cvt(ffi::X509_NAME_add_entry_by_txt(
|
||||
self.0.as_ptr(),
|
||||
field.as_ptr() as *mut _,
|
||||
ffi::MBSTRING_UTF8,
|
||||
value.as_ptr(),
|
||||
value.len() as c_int,
|
||||
value.len() as crate::SLenType,
|
||||
-1,
|
||||
0,
|
||||
))
|
||||
@@ -982,13 +1104,13 @@ impl X509NameBuilder {
|
||||
) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
let field = CString::new(field).unwrap();
|
||||
assert!(value.len() <= c_int::max_value() as usize);
|
||||
assert!(value.len() <= crate::SLenType::max_value() as usize);
|
||||
cvt(ffi::X509_NAME_add_entry_by_txt(
|
||||
self.0.as_ptr(),
|
||||
field.as_ptr() as *mut _,
|
||||
ty.as_raw(),
|
||||
value.as_ptr(),
|
||||
value.len() as c_int,
|
||||
value.len() as crate::SLenType,
|
||||
-1,
|
||||
0,
|
||||
))
|
||||
@@ -1003,13 +1125,13 @@ impl X509NameBuilder {
|
||||
/// [`X509_NAME_add_entry_by_NID`]: https://www.openssl.org/docs/manmaster/crypto/X509_NAME_add_entry_by_NID.html
|
||||
pub fn append_entry_by_nid(&mut self, field: Nid, value: &str) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
assert!(value.len() <= c_int::max_value() as usize);
|
||||
assert!(value.len() <= crate::SLenType::max_value() as usize);
|
||||
cvt(ffi::X509_NAME_add_entry_by_NID(
|
||||
self.0.as_ptr(),
|
||||
field.as_raw(),
|
||||
ffi::MBSTRING_UTF8,
|
||||
value.as_ptr() as *mut _,
|
||||
value.len() as c_int,
|
||||
value.len() as crate::SLenType,
|
||||
-1,
|
||||
0,
|
||||
))
|
||||
@@ -1029,13 +1151,13 @@ impl X509NameBuilder {
|
||||
ty: Asn1Type,
|
||||
) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
assert!(value.len() <= c_int::max_value() as usize);
|
||||
assert!(value.len() <= crate::SLenType::max_value() as usize);
|
||||
cvt(ffi::X509_NAME_add_entry_by_NID(
|
||||
self.0.as_ptr(),
|
||||
field.as_raw(),
|
||||
ty.as_raw(),
|
||||
value.as_ptr() as *mut _,
|
||||
value.len() as c_int,
|
||||
value.len() as crate::SLenType,
|
||||
-1,
|
||||
0,
|
||||
))
|
||||
@@ -1428,6 +1550,7 @@ impl X509ReqRef {
|
||||
/// This corresponds to [`X509_REQ_get_version`]
|
||||
///
|
||||
/// [`X509_REQ_get_version`]: https://www.openssl.org/docs/manmaster/crypto/X509_REQ_get_version.html
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
pub fn version(&self) -> i32 {
|
||||
unsafe { X509_REQ_get_version(self.as_ptr()) as i32 }
|
||||
}
|
||||
@@ -1481,13 +1604,41 @@ impl X509ReqRef {
|
||||
}
|
||||
}
|
||||
|
||||
/// The reason that a certificate was revoked.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct CrlReason(c_int);
|
||||
|
||||
#[allow(missing_docs)] // no need to document the constants
|
||||
impl CrlReason {
|
||||
pub const UNSPECIFIED: CrlReason = CrlReason(ffi::CRL_REASON_UNSPECIFIED);
|
||||
pub const KEY_COMPROMISE: CrlReason = CrlReason(ffi::CRL_REASON_KEY_COMPROMISE);
|
||||
pub const CA_COMPROMISE: CrlReason = CrlReason(ffi::CRL_REASON_CA_COMPROMISE);
|
||||
pub const AFFILIATION_CHANGED: CrlReason = CrlReason(ffi::CRL_REASON_AFFILIATION_CHANGED);
|
||||
pub const SUPERSEDED: CrlReason = CrlReason(ffi::CRL_REASON_SUPERSEDED);
|
||||
pub const CESSATION_OF_OPERATION: CrlReason = CrlReason(ffi::CRL_REASON_CESSATION_OF_OPERATION);
|
||||
pub const CERTIFICATE_HOLD: CrlReason = CrlReason(ffi::CRL_REASON_CERTIFICATE_HOLD);
|
||||
pub const REMOVE_FROM_CRL: CrlReason = CrlReason(ffi::CRL_REASON_REMOVE_FROM_CRL);
|
||||
pub const PRIVILEGE_WITHDRAWN: CrlReason = CrlReason(ffi::CRL_REASON_PRIVILEGE_WITHDRAWN);
|
||||
pub const AA_COMPROMISE: CrlReason = CrlReason(ffi::CRL_REASON_AA_COMPROMISE);
|
||||
|
||||
/// Constructs an `CrlReason` from a raw OpenSSL value.
|
||||
pub const fn from_raw(value: c_int) -> Self {
|
||||
CrlReason(value)
|
||||
}
|
||||
|
||||
/// Returns the raw OpenSSL value represented by this type.
|
||||
pub const fn as_raw(&self) -> c_int {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::X509_REVOKED;
|
||||
fn drop = ffi::X509_REVOKED_free;
|
||||
|
||||
/// An `X509` certificate request.
|
||||
/// An `X509` certificate revocation status.
|
||||
pub struct X509Revoked;
|
||||
/// Reference to `X509Crl`.
|
||||
/// Reference to `X509Revoked`.
|
||||
pub struct X509RevokedRef;
|
||||
}
|
||||
|
||||
@@ -1513,6 +1664,13 @@ impl X509RevokedRef {
|
||||
ffi::i2d_X509_REVOKED
|
||||
}
|
||||
|
||||
/// Copies the entry to a new `X509Revoked`.
|
||||
#[corresponds(X509_NAME_dup)]
|
||||
#[cfg(any(boringssl, ossl110, libressl270))]
|
||||
pub fn to_owned(&self) -> Result<X509Revoked, ErrorStack> {
|
||||
unsafe { cvt_p(ffi::X509_REVOKED_dup(self.as_ptr())).map(|n| X509Revoked::from_ptr(n)) }
|
||||
}
|
||||
|
||||
/// Get the date that the certificate was revoked
|
||||
#[corresponds(X509_REVOKED_get0_revocationDate)]
|
||||
pub fn revocation_date(&self) -> &Asn1TimeRef {
|
||||
@@ -1532,13 +1690,67 @@ impl X509RevokedRef {
|
||||
Asn1IntegerRef::from_ptr(r as *mut _)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the criticality and value of an extension.
|
||||
///
|
||||
/// This returns None if the extension is not present or occurs multiple times.
|
||||
#[corresponds(X509_REVOKED_get_ext_d2i)]
|
||||
pub fn extension<T: ExtensionType>(&self) -> Result<Option<(bool, T::Output)>, ErrorStack> {
|
||||
let mut critical = -1;
|
||||
let out = unsafe {
|
||||
// SAFETY: self.as_ptr() is a valid pointer to an X509_REVOKED.
|
||||
let ext = ffi::X509_REVOKED_get_ext_d2i(
|
||||
self.as_ptr(),
|
||||
T::NID.as_raw(),
|
||||
&mut critical as *mut _,
|
||||
ptr::null_mut(),
|
||||
);
|
||||
// SAFETY: Extensions's contract promises that the type returned by
|
||||
// OpenSSL here is T::Output.
|
||||
T::Output::from_ptr_opt(ext as *mut _)
|
||||
};
|
||||
match (critical, out) {
|
||||
(0, Some(out)) => Ok(Some((false, out))),
|
||||
(1, Some(out)) => Ok(Some((true, out))),
|
||||
// -1 means the extension wasn't found, -2 means multiple were found.
|
||||
(-1 | -2, _) => Ok(None),
|
||||
// A critical value of 0 or 1 suggests success, but a null pointer
|
||||
// was returned so something went wrong.
|
||||
(0 | 1, None) => Err(ErrorStack::get()),
|
||||
(c_int::MIN..=-2 | 2.., _) => panic!("OpenSSL should only return -2, -1, 0, or 1 for an extension's criticality but it returned {}", critical),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The CRL entry extension identifying the reason for revocation see [`CrlReason`],
|
||||
/// this is as defined in RFC 5280 Section 5.3.1.
|
||||
pub enum ReasonCode {}
|
||||
|
||||
// SAFETY: CertificateIssuer is defined to be a stack of GeneralName in the RFC
|
||||
// and in OpenSSL.
|
||||
unsafe impl ExtensionType for ReasonCode {
|
||||
const NID: Nid = Nid::from_raw(ffi::NID_crl_reason);
|
||||
|
||||
type Output = Asn1Enumerated;
|
||||
}
|
||||
|
||||
/// The CRL entry extension identifying the issuer of a certificate used in
|
||||
/// indirect CRLs, as defined in RFC 5280 Section 5.3.3.
|
||||
pub enum CertificateIssuer {}
|
||||
|
||||
// SAFETY: CertificateIssuer is defined to be a stack of GeneralName in the RFC
|
||||
// and in OpenSSL.
|
||||
unsafe impl ExtensionType for CertificateIssuer {
|
||||
const NID: Nid = Nid::from_raw(ffi::NID_certificate_issuer);
|
||||
|
||||
type Output = Stack<GeneralName>;
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::X509_CRL;
|
||||
fn drop = ffi::X509_CRL_free;
|
||||
|
||||
/// An `X509` certificate request.
|
||||
/// An `X509` certificate revocation list.
|
||||
pub struct X509Crl;
|
||||
/// Reference to `X509Crl`.
|
||||
pub struct X509CrlRef;
|
||||
@@ -1842,6 +2054,37 @@ impl GeneralName {
|
||||
Ok(GeneralName::from_ptr(gn))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn new_other_name(
|
||||
oid: Asn1Object,
|
||||
value: &Vec<u8>,
|
||||
) -> Result<GeneralName, ErrorStack> {
|
||||
unsafe {
|
||||
ffi::init();
|
||||
|
||||
let typ = cvt_p(ffi::d2i_ASN1_TYPE(
|
||||
ptr::null_mut(),
|
||||
&mut value.as_ptr().cast(),
|
||||
value.len().try_into().unwrap(),
|
||||
))?;
|
||||
|
||||
let gn = cvt_p(ffi::GENERAL_NAME_new())?;
|
||||
(*gn).type_ = ffi::GEN_OTHERNAME;
|
||||
|
||||
if let Err(e) = cvt(ffi::GENERAL_NAME_set0_othername(
|
||||
gn,
|
||||
oid.as_ptr().cast(),
|
||||
typ,
|
||||
)) {
|
||||
ffi::GENERAL_NAME_free(gn);
|
||||
return Err(e);
|
||||
}
|
||||
|
||||
mem::forget(oid);
|
||||
|
||||
Ok(GeneralName::from_ptr(gn))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GeneralNameRef {
|
||||
@@ -1872,6 +2115,22 @@ impl GeneralNameRef {
|
||||
self.ia5_string(ffi::GEN_EMAIL)
|
||||
}
|
||||
|
||||
/// Returns the contents of this `GeneralName` if it is a `directoryName`.
|
||||
pub fn directory_name(&self) -> Option<&X509NameRef> {
|
||||
unsafe {
|
||||
if (*self.as_ptr()).type_ != ffi::GEN_DIRNAME {
|
||||
return None;
|
||||
}
|
||||
|
||||
#[cfg(boringssl)]
|
||||
let d = (*self.as_ptr()).d.ptr;
|
||||
#[cfg(not(boringssl))]
|
||||
let d = (*self.as_ptr()).d;
|
||||
|
||||
Some(X509NameRef::from_const_ptr(d as *const _))
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the contents of this `GeneralName` if it is a `dNSName`.
|
||||
pub fn dnsname(&self) -> Option<&str> {
|
||||
self.ia5_string(ffi::GEN_DNS)
|
||||
@@ -1927,6 +2186,49 @@ impl Stackable for GeneralName {
|
||||
type StackType = ffi::stack_st_GENERAL_NAME;
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::DIST_POINT;
|
||||
fn drop = ffi::DIST_POINT_free;
|
||||
|
||||
/// A `X509` distribution point.
|
||||
pub struct DistPoint;
|
||||
/// Reference to `DistPoint`.
|
||||
pub struct DistPointRef;
|
||||
}
|
||||
|
||||
impl DistPointRef {
|
||||
/// Returns the name of this distribution point if it exists
|
||||
pub fn distpoint(&self) -> Option<&DistPointNameRef> {
|
||||
unsafe { DistPointNameRef::from_const_ptr_opt((*self.as_ptr()).distpoint) }
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::DIST_POINT_NAME;
|
||||
fn drop = ffi::DIST_POINT_NAME_free;
|
||||
|
||||
/// A `X509` distribution point.
|
||||
pub struct DistPointName;
|
||||
/// Reference to `DistPointName`.
|
||||
pub struct DistPointNameRef;
|
||||
}
|
||||
|
||||
impl DistPointNameRef {
|
||||
/// Returns the contents of this DistPointName if it is a fullname.
|
||||
pub fn fullname(&self) -> Option<&StackRef<GeneralName>> {
|
||||
unsafe {
|
||||
if (*self.as_ptr()).type_ != 0 {
|
||||
return None;
|
||||
}
|
||||
StackRef::from_const_ptr_opt((*self.as_ptr()).name.fullname)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Stackable for DistPoint {
|
||||
type StackType = ffi::stack_st_DIST_POINT;
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::ACCESS_DESCRIPTION;
|
||||
fn drop = ffi::ACCESS_DESCRIPTION_free;
|
||||
|
||||
@@ -42,13 +42,13 @@
|
||||
//! ```
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
use foreign_types::ForeignTypeRef;
|
||||
use std::mem;
|
||||
|
||||
use crate::error::ErrorStack;
|
||||
#[cfg(not(boringssl))]
|
||||
use crate::ssl::SslFiletype;
|
||||
use crate::stack::{Stack, StackRef};
|
||||
use crate::stack::StackRef;
|
||||
#[cfg(any(ossl102, libressl261))]
|
||||
use crate::x509::verify::{X509VerifyFlags, X509VerifyParamRef};
|
||||
use crate::x509::{X509Object, X509PurposeId, X509};
|
||||
@@ -260,24 +260,10 @@ foreign_type_and_impl_send_sync! {
|
||||
|
||||
impl X509StoreRef {
|
||||
/// Get a reference to the cache of certificates in this store.
|
||||
///
|
||||
/// This method is deprecated. It is **unsound** and will be removed in a
|
||||
/// future version of rust-openssl. `X509StoreRef::all_certificates`
|
||||
/// should be used instead.
|
||||
#[deprecated(
|
||||
note = "This method is unsound, and will be removed in a future version of rust-openssl. X509StoreRef::all_certificates should be used instead."
|
||||
)]
|
||||
#[corresponds(X509_STORE_get0_objects)]
|
||||
pub fn objects(&self) -> &StackRef<X509Object> {
|
||||
unsafe { StackRef::from_ptr(X509_STORE_get0_objects(self.as_ptr())) }
|
||||
}
|
||||
|
||||
/// Returns a stack of all the certificates in this store.
|
||||
#[corresponds(X509_STORE_get1_all_certs)]
|
||||
#[cfg(ossl300)]
|
||||
pub fn all_certificates(&self) -> Stack<X509> {
|
||||
unsafe { Stack::from_ptr(ffi::X509_STORE_get1_all_certs(self.as_ptr())) }
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
|
||||
+171
-13
@@ -1,6 +1,6 @@
|
||||
use std::cmp::Ordering;
|
||||
|
||||
use crate::asn1::Asn1Time;
|
||||
use crate::asn1::{Asn1Object, Asn1OctetString, Asn1Time};
|
||||
use crate::bn::{BigNum, MsbOption};
|
||||
use crate::hash::MessageDigest;
|
||||
use crate::nid::Nid;
|
||||
@@ -18,19 +18,24 @@ use crate::x509::store::X509Lookup;
|
||||
use crate::x509::store::X509StoreBuilder;
|
||||
#[cfg(any(ossl102, libressl261))]
|
||||
use crate::x509::verify::{X509VerifyFlags, X509VerifyParam};
|
||||
#[cfg(ossl110)]
|
||||
use crate::x509::X509Builder;
|
||||
#[cfg(ossl102)]
|
||||
use crate::x509::X509PurposeId;
|
||||
#[cfg(any(ossl102, libressl261))]
|
||||
use crate::x509::X509PurposeRef;
|
||||
#[cfg(ossl110)]
|
||||
use crate::x509::{CrlReason, X509Builder};
|
||||
use crate::x509::{
|
||||
CrlStatus, X509Crl, X509Extension, X509Name, X509Req, X509StoreContext, X509VerifyResult, X509,
|
||||
};
|
||||
|
||||
#[cfg(ossl110)]
|
||||
use foreign_types::ForeignType;
|
||||
use hex::{self, FromHex};
|
||||
#[cfg(any(ossl102, libressl261))]
|
||||
use libc::time_t;
|
||||
|
||||
use super::{CertificateIssuer, ReasonCode};
|
||||
|
||||
fn pkey() -> PKey<Private> {
|
||||
let rsa = Rsa::generate(2048).unwrap();
|
||||
PKey::from_rsa(rsa).unwrap()
|
||||
@@ -166,6 +171,70 @@ fn test_subject_alt_name() {
|
||||
assert_eq!(Some("http://www.example.com"), subject_alt_names[4].uri());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl110)]
|
||||
fn test_retrieve_pathlen() {
|
||||
let cert = include_bytes!("../../test/root-ca.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
assert_eq!(cert.pathlen(), None);
|
||||
|
||||
let cert = include_bytes!("../../test/intermediate-ca.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
assert_eq!(cert.pathlen(), Some(0));
|
||||
|
||||
let cert = include_bytes!("../../test/alt_name_cert.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
assert_eq!(cert.pathlen(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl110)]
|
||||
fn test_subject_key_id() {
|
||||
let cert = include_bytes!("../../test/certv3.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
|
||||
let subject_key_id = cert.subject_key_id().unwrap();
|
||||
assert_eq!(
|
||||
subject_key_id.as_slice(),
|
||||
&b"\xB6\x73\x2F\x61\xA5\x4B\xA1\xEF\x48\x2C\x15\xB1\x9F\xF3\xDC\x34\x2F\xBC\xAC\x30"[..]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl110)]
|
||||
fn test_authority_key_id() {
|
||||
let cert = include_bytes!("../../test/certv3.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
|
||||
let authority_key_id = cert.authority_key_id().unwrap();
|
||||
assert_eq!(
|
||||
authority_key_id.as_slice(),
|
||||
&b"\x6C\xD3\xA5\x03\xAB\x0D\x5F\x2C\xC9\x8D\x8A\x9C\x88\xA7\x88\x77\xB8\x37\xFD\x9A"[..]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl111d)]
|
||||
fn test_authority_issuer_and_serial() {
|
||||
let cert = include_bytes!("../../test/authority_key_identifier.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
|
||||
let authority_issuer = cert.authority_issuer().unwrap();
|
||||
assert_eq!(1, authority_issuer.len());
|
||||
let dn = authority_issuer[0].directory_name().unwrap();
|
||||
let mut o = dn.entries_by_nid(Nid::ORGANIZATIONNAME);
|
||||
let o = o.next().unwrap().data().as_utf8().unwrap();
|
||||
assert_eq!(o.as_bytes(), b"PyCA");
|
||||
let mut cn = dn.entries_by_nid(Nid::COMMONNAME);
|
||||
let cn = cn.next().unwrap().data().as_utf8().unwrap();
|
||||
assert_eq!(cn.as_bytes(), b"cryptography.io");
|
||||
|
||||
let authority_serial = cert.authority_serial().unwrap();
|
||||
let serial = authority_serial.to_bn().unwrap();
|
||||
let expected = BigNum::from_u32(3).unwrap();
|
||||
assert_eq!(serial, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_subject_alt_name_iter() {
|
||||
let cert = include_bytes!("../../test/alt_name_cert.pem");
|
||||
@@ -288,6 +357,8 @@ fn x509_builder() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
// This tests `X509Extension::new`, even though its deprecated.
|
||||
#[allow(deprecated)]
|
||||
fn x509_extension_new() {
|
||||
assert!(X509Extension::new(None, None, "crlDistributionPoints", "section").is_err());
|
||||
assert!(X509Extension::new(None, None, "proxyCertInfo", "").is_err());
|
||||
@@ -295,6 +366,20 @@ fn x509_extension_new() {
|
||||
assert!(X509Extension::new(None, None, "subjectAltName", "dirName:section").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn x509_extension_new_from_der() {
|
||||
let ext = X509Extension::new_from_der(
|
||||
&Asn1Object::from_str("2.5.29.19").unwrap(),
|
||||
true,
|
||||
&Asn1OctetString::new_from_bytes(b"\x30\x03\x01\x01\xff").unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
ext.to_der().unwrap(),
|
||||
b"0\x0f\x06\x03U\x1d\x13\x01\x01\xff\x04\x050\x03\x01\x01\xff"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn x509_extension_to_der() {
|
||||
let builder = X509::builder().unwrap();
|
||||
@@ -611,6 +696,42 @@ fn test_load_crl() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_crl_entry_extensions() {
|
||||
let crl = include_bytes!("../../test/entry_extensions.crl");
|
||||
let crl = X509Crl::from_pem(crl).unwrap();
|
||||
|
||||
let revoked_certs = crl.get_revoked().unwrap();
|
||||
let entry = &revoked_certs[0];
|
||||
|
||||
let (critical, issuer) = entry
|
||||
.extension::<CertificateIssuer>()
|
||||
.unwrap()
|
||||
.expect("Certificate issuer extension should be present");
|
||||
assert!(critical, "Certificate issuer extension is critical");
|
||||
assert_eq!(issuer.len(), 1, "Certificate issuer should have one entry");
|
||||
let issuer = issuer[0]
|
||||
.directory_name()
|
||||
.expect("Issuer should be a directory name");
|
||||
assert_eq!(
|
||||
format!("{:?}", issuer),
|
||||
r#"[countryName = "GB", commonName = "Test CA"]"#
|
||||
);
|
||||
|
||||
// reason_code can't be inspected without ossl110
|
||||
#[allow(unused_variables)]
|
||||
let (critical, reason_code) = entry
|
||||
.extension::<ReasonCode>()
|
||||
.unwrap()
|
||||
.expect("Reason code extension should be present");
|
||||
assert!(!critical, "Reason code extension is not critical");
|
||||
#[cfg(ossl110)]
|
||||
assert_eq!(
|
||||
CrlReason::KEY_COMPROMISE,
|
||||
CrlReason::from_raw(reason_code.get_i64().unwrap() as ffi::c_int)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_save_subject_der() {
|
||||
let cert = include_bytes!("../../test/cert.pem");
|
||||
@@ -987,17 +1108,54 @@ fn ipv6_as_subject_alternative_name_is_formatted_in_debug() {
|
||||
]);
|
||||
}
|
||||
|
||||
#[cfg(ossl110)]
|
||||
#[test]
|
||||
#[cfg(ossl300)]
|
||||
fn test_store_all_certificates() {
|
||||
let cert = include_bytes!("../../test/cert.pem");
|
||||
fn other_name_as_subject_alternative_name() {
|
||||
let oid = Asn1Object::from_str("1.3.6.1.5.5.7.8.11").unwrap();
|
||||
// this is the hex representation of "test" encoded as a ia5string
|
||||
let content = [0x16, 0x04, 0x74, 0x65, 0x73, 0x74];
|
||||
|
||||
let mut builder = X509Builder::new().unwrap();
|
||||
let san = SubjectAlternativeName::new()
|
||||
.other_name2(oid, &content)
|
||||
.build(&builder.x509v3_context(None, None))
|
||||
.unwrap();
|
||||
builder.append_extension(san).unwrap();
|
||||
let cert = builder.build();
|
||||
let general_name = cert
|
||||
.subject_alt_names()
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.next()
|
||||
.unwrap();
|
||||
unsafe {
|
||||
assert_eq!((*general_name.as_ptr()).type_, 0);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dist_point() {
|
||||
let cert = include_bytes!("../../test/certv3.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
|
||||
let store = {
|
||||
let mut b = X509StoreBuilder::new().unwrap();
|
||||
b.add_cert(cert).unwrap();
|
||||
b.build()
|
||||
};
|
||||
let dps = cert.crl_distribution_points().unwrap();
|
||||
let dp = dps.get(0).unwrap();
|
||||
let dp_nm = dp.distpoint().unwrap();
|
||||
let dp_gns = dp_nm.fullname().unwrap();
|
||||
let dp_gn = dp_gns.get(0).unwrap();
|
||||
assert_eq!(dp_gn.uri().unwrap(), "http://example.com/crl.pem");
|
||||
|
||||
assert_eq!(store.all_certificates().len(), 1);
|
||||
}
|
||||
let dp = dps.get(1).unwrap();
|
||||
let dp_nm = dp.distpoint().unwrap();
|
||||
let dp_gns = dp_nm.fullname().unwrap();
|
||||
let dp_gn = dp_gns.get(0).unwrap();
|
||||
assert_eq!(dp_gn.uri().unwrap(), "http://example.com/crl2.pem");
|
||||
assert!(dps.get(2).is_none())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dist_point_null() {
|
||||
let cert = include_bytes!("../../test/cert.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
assert!(cert.crl_distribution_points().is_none());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDIjCCAgqgAwIBAgIBAzANBgkqhkiG9w0BAQUFADApMQ0wCwYDVQQKDARQeUNB
|
||||
MRgwFgYDVQQDDA9jcnlwdG9ncmFwaHkuaW8wHhcNMTUwNTAzMDk0OTU2WhcNMTYw
|
||||
NTAyMDk0OTU2WjApMQ0wCwYDVQQKDARQeUNBMRgwFgYDVQQDDA9jcnlwdG9ncmFw
|
||||
aHkuaW8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDCadi1UZioxdnP
|
||||
ajqlRZHeKsSxvXXhgrWvlt91P3gV0dBThRFhJsLOhjNLz6PO6KeRbjz9GhTA2hdk
|
||||
xtIpXrjvTv9dEJ1/k0xebsHWgFC43aTlgekw0U4cMwMe5NGeeg1tfzbJwldIN+cK
|
||||
vabc08ADlkmM6DMnUArkzA2yii0DErRFMSIGrkDr6E9puord3h6Mh8Jfnc3TDAq8
|
||||
Qo1DI2XM7oFSWNfecQ9KbIC5wzzT+7Shoyz7QmCk/XhRzt8Xcfc3yAXIwazvLf8b
|
||||
YP1auaSG11a5E+w6onj91h8UHKKOXu+rdq5YYPZ+qUYpxA7ZJ/VAGadMulYbXaO8
|
||||
Syi39HTpAgMBAAGjVTBTMFEGA1UdIwRKMEiAFDlFPso9Yh3qhkn2WqtAt6RwmPHs
|
||||
oS2kKzApMQ0wCwYDVQQKDARQeUNBMRgwFgYDVQQDDA9jcnlwdG9ncmFwaHkuaW+C
|
||||
AQMwDQYJKoZIhvcNAQEFBQADggEBAFbZYy6aZJUK/f7nJx2Rs/ht6hMbM32/RoXZ
|
||||
JGbYapNVqVu/vymcfc/se3FHS5OVmPsnRlo/FIKDn/r5DGl73Sn/FvDJiLJZFucT
|
||||
msyYuHZ+ZRYWzWmN2fcB3cfxj0s3qps6f5OoCOqoINOSe4HRGlw4X9keZSD+3xAt
|
||||
vHNwQdlPC7zWbPdrzLT+FqR0e/O81vFJJS6drHJWqPcR3NQVtZw+UF7A/HKwbfeL
|
||||
Nu2zj6165hzOi9HUxa2/mPr/eLUUV1sTzXp2+TFjt3rVCjW1XnpMLdwNBHzjpyAB
|
||||
dTOX3iw0+BPy3s2jtnCW1PLpc74kvSTaBwhg74sq39EXfIKax00=
|
||||
-----END CERTIFICATE-----
|
||||
@@ -0,0 +1,23 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDwTCCAqmgAwIBAgIUDeCGNunyJfBd3U/qUtmCcvbMyZwwDQYJKoZIhvcNAQEL
|
||||
BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
|
||||
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMzAxMjMxMzMzNTJaFw0zMzAx
|
||||
MjAxMzMzNTJaMFoxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
|
||||
HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxEzARBgNVBAMMCmZvb2Jh
|
||||
ci5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCo9CWMRLMXo1CF
|
||||
/iORh9B4NhtJF/8tR9PlG95sNvyWuQQ/8jfev+8zErplxfLkt0pJqcoiZG8g9NU0
|
||||
kU6o5T+/1QgZclCAoZaS0Jqxmoo2Yk/1Qsj16pnMBc10uSDk6V9aJSX1vKwONVNS
|
||||
wiHA1MhX+i7Wf7/K0niq+k7hOkhleFkWgZtUq41gXh1VfOugka7UktYnk9mrBbAM
|
||||
jmaloZNn2pMMAQxVg4ThiLm3zvuWqvXASWzUZc7IAd1GbN4AtDuhs252eqE9E4iT
|
||||
Hk7F14wAS1JWqv666hReGHrmZJGx0xQTM9vPD1HN5t2U3KTfhO/mTlAUWVyg9tCt
|
||||
OzboKgs1AgMBAAGjgZMwgZAwTgYDVR0fBEcwRTAgoB6gHIYaaHR0cDovL2V4YW1w
|
||||
bGUuY29tL2NybC5wZW0wIaAfoB2GG2h0dHA6Ly9leGFtcGxlLmNvbS9jcmwyLnBl
|
||||
bTAdBgNVHQ4EFgQUtnMvYaVLoe9ILBWxn/PcNC+8rDAwHwYDVR0jBBgwFoAUbNOl
|
||||
A6sNXyzJjYqciKeId7g3/ZowDQYJKoZIhvcNAQELBQADggEBAJZyk6Eo4p3JIyOt
|
||||
7t6ET3K18BKvlRilze+zrGkaQYvKRsP6YzbZWgcIq59hy5VeFCX5O2WP91CPG3MU
|
||||
I9eRiih66/ry3G4I8QEdpRKnn0N5unbGjb5qPT5wXrhU4IO+vn3sGZGM4uIM1/3K
|
||||
N/bOh9CTsu9YqrdHSGeDyNzCy/XZ/j5bP4aNm31ZDNCZDFsbjr3/yTLcpHPL0UP3
|
||||
mCX8D16BDu1Nep+wK9VRuOEw6Z9tlT/VjTImzoOUoJO/o2UHfSHahX+n2aC5OpI6
|
||||
BdhaFBuJ1vn+yTWf3zIjhWUdp9TlzgRyFiyetP2FcKwremVVGdDq/Y6dfXaq8CA1
|
||||
6Fr9KTY=
|
||||
-----END CERTIFICATE-----
|
||||
@@ -0,0 +1 @@
|
||||
crlDistributionPoints=URI:http://example.com/crl.pem,URI:http://example.com/crl2.pem
|
||||
@@ -0,0 +1,10 @@
|
||||
-----BEGIN X509 CRL-----
|
||||
MIIBXDCCAQICAQEwCgYIKoZIzj0EAwIwETEPMA0GA1UEAwwGQ1JMIENBFw0yMzAz
|
||||
MjgwOTQ5MThaFw0yMzA0MDQwOTUwMDdaMIGAMH4CFE+Y95/1pOqa6c9fUEJ8c04k
|
||||
xu2PFw0yMzAzMjgwOTQ3MzNaMFcwLwYDVR0dAQH/BCUwI6QhMB8xCzAJBgNVBAYT
|
||||
AkdCMRAwDgYDVQQDDAdUZXN0IENBMAoGA1UdFQQDCgEBMBgGA1UdGAQRGA8yMDIz
|
||||
MDMyODA5NDQ0MFqgPTA7MB8GA1UdIwQYMBaAFNX1GZ0RWuC+4gz1wuy5H32T2W+R
|
||||
MAoGA1UdFAQDAgEUMAwGA1UdHAQFMAOEAf8wCgYIKoZIzj0EAwIDSAAwRQIgbl7x
|
||||
W+WVAb+zlvKcJLmHVuC+gbqR4jqwGIHHgQl2J8kCIQCo/sAF5sDqy/cL+fbzBeUe
|
||||
YoY2h6lIkj9ENwU8ZCt03w==
|
||||
-----END X509 CRL-----
|
||||
+14
-2
@@ -56,6 +56,7 @@ fn main() {
|
||||
.header("openssl/bio.h")
|
||||
.header("openssl/x509v3.h")
|
||||
.header("openssl/safestack.h")
|
||||
.header("openssl/cmac.h")
|
||||
.header("openssl/hmac.h")
|
||||
.header("openssl/obj_mac.h")
|
||||
.header("openssl/ssl.h")
|
||||
@@ -68,6 +69,10 @@ fn main() {
|
||||
.header("openssl/evp.h")
|
||||
.header("openssl/x509_vfy.h");
|
||||
|
||||
if libressl_version.is_some() {
|
||||
cfg.header("openssl/poly1305.h");
|
||||
}
|
||||
|
||||
if let Some(version) = openssl_version {
|
||||
cfg.header("openssl/cms.h");
|
||||
if version >= 0x10100000 {
|
||||
@@ -110,7 +115,11 @@ fn main() {
|
||||
|| s.starts_with("CRYPTO_EX_")
|
||||
});
|
||||
cfg.skip_struct(|s| {
|
||||
s == "ProbeResult" || s == "X509_OBJECT_data" // inline union
|
||||
s == "ProbeResult" ||
|
||||
s == "X509_OBJECT_data" || // inline union
|
||||
s == "DIST_POINT_NAME_st_anon_union" || // inline union
|
||||
s == "PKCS7_data" ||
|
||||
s == "ASN1_TYPE_value"
|
||||
});
|
||||
cfg.skip_fn(move |s| {
|
||||
s == "CRYPTO_memcmp" || // uses volatile
|
||||
@@ -130,7 +139,10 @@ fn main() {
|
||||
cfg.skip_field_type(|s, field| {
|
||||
(s == "EVP_PKEY" && field == "pkey") || // union
|
||||
(s == "GENERAL_NAME" && field == "d") || // union
|
||||
(s == "X509_OBJECT" && field == "data") // union
|
||||
(s == "DIST_POINT_NAME" && field == "name") || // union
|
||||
(s == "X509_OBJECT" && field == "data") || // union
|
||||
(s == "PKCS7" && field == "d") || // union
|
||||
(s == "ASN1_TYPE" && field == "value") // union
|
||||
});
|
||||
cfg.skip_signededness(|s| {
|
||||
s.ends_with("_cb")
|
||||
|
||||
Reference in New Issue
Block a user