Merge remote-tracking branch 'origin/master'

This commit is contained in:
Benjamin Cheng 2018-06-02 10:56:31 -04:00
commit b1eb1224f5
No known key found for this signature in database
GPG Key ID: 4FE22E7528E97BD8
42 changed files with 1846 additions and 1165 deletions

View File

@ -2,6 +2,50 @@
## [Unreleased] ## [Unreleased]
## [v0.10.9] - 2018-06-01
### Fixed
* Fixed a use-after-free in `CmsContentInfo::sign`.
* `SslRef::servername` now returns `None` rather than panicking on a non-UTF8 name.
### Added
* Added `MessageDigest::from_nid`.
* Added `Nid::signature_algorithms`, `Nid::long_name`, and `Nid::short_name`.
* Added early data and early keying material export support for TLS 1.3.
* Added `SslRef::verified_chain`.
* Added `SslRef::servername_raw` which returns a `&[u8]` rather than `&str`.
* Added `SslRef::finished` and `SslRef::peer_finished`.
* Added `X509Ref::digest` to replace `X509Ref::fingerprint`.
* `X509StoreBuilder` and `X509Store` now implement `Sync` and `Send`.
### Deprecated
* `X509Ref::fingerprint` has been deprecated in favor of `X509Ref::digest`.
## [v0.10.8] - 2018-05-20
### Fixed
* `openssl-sys` will now detect Homebrew-installed OpenSSL when installed to a non-default
directory.
* The `X509_V_ERR_INVALID_CALL`, `X509_V_ERR_STORE_LOOKUP`, and
`X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION` constants in `openssl-sys` are now only present when
building against 1.1.0g and up rather than 1.1.0.
* `SslContextBuilder::max_proto_version` and `SslContextBuilder::min_proto_version` are only present
when building against 1.1.0g and up rather than 1.1.0.
### Added
* Added `CmsContentInfo::sign`.
* Added `Clone` and `ToOwned` implementations to `Rsa` and `RsaRef` respectively.
* The `min_proto_version` and `max_proto_version` methods are available when linking against
LibreSSL 2.6.1 and up in addition to OpenSSL.
* `X509VerifyParam` is available when linking against LibreSSL 2.6.1 and up in addition to OpenSSL.
* ALPN support is available when linking against LibreSSL 2.6.1 and up in addition to OpenSSL.
* `Stack` and `StackRef` are now `Sync` and `Send`.
## [v0.10.7] - 2018-04-30 ## [v0.10.7] - 2018-04-30
### Added ### Added
@ -183,7 +227,9 @@
Look at the [release tags] for information about older releases. Look at the [release tags] for information about older releases.
[Unreleased]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.7...master [Unreleased]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.9...master
[v0.10.9]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.8...openssl-v0.10.9
[v0.10.8]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.7...openssl-v0.10.8
[v0.10.7]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.6...openssl-v0.10.7 [v0.10.7]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.6...openssl-v0.10.7
[v0.10.6]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.5...openssl-v0.10.6 [v0.10.6]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.5...openssl-v0.10.6
[v0.10.5]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.4...openssl-v0.10.5 [v0.10.5]: https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.4...openssl-v0.10.5

View File

@ -48,25 +48,25 @@ make -j$(nproc)
make install make install
``` ```
### OSX ### macOS
Although OpenSSL 0.9.8 is preinstalled on OSX this library is being phased out Although OpenSSL 0.9.8 is preinstalled on macOS this library is being phased out
of OSX and this crate also does not support that version of OpenSSL. To use this of macOS and this crate also does not support that version of OpenSSL. To use this
crate on OSX you'll need to install OpenSSL via some alternate means, typically crate on macOS you'll need to install OpenSSL via some alternate means, typically
Homebrew: Homebrew:
```bash ```bash
brew install openssl brew install openssl
``` ```
Occasionally an update of XCode or MacOS will cause the linker to fail after compilation, to rectify this you may want to try and run: Occasionally an update of XCode or macOS will cause the linker to fail after compilation, to rectify this you may want to try and run:
```bash ```bash
xcode-select --install xcode-select --install
``` ```
If Homebrew is installed to the default location of `/usr/local`, OpenSSL will be If you're using latest version of Homebrew which supports `--prefix` command,
automatically detected. OpenSSL will be automatically detected.
### Windows MSVC ### Windows MSVC

View File

@ -1,6 +1,6 @@
[package] [package]
name = "openssl-sys" name = "openssl-sys"
version = "0.9.30" version = "0.9.32"
authors = ["Alex Crichton <alex@alexcrichton.com>", authors = ["Alex Crichton <alex@alexcrichton.com>",
"Steven Fackler <sfackler@gmail.com>"] "Steven Fackler <sfackler@gmail.com>"]
license = "MIT" license = "MIT"
@ -9,6 +9,7 @@ repository = "https://github.com/sfackler/rust-openssl"
readme = "README.md" readme = "README.md"
categories = ["cryptography", "external-ffi-bindings"] categories = ["cryptography", "external-ffi-bindings"]
links = "openssl" links = "openssl"
build = "build/main.rs"
[dependencies] [dependencies]
libc = "0.2" libc = "0.2"

43
openssl-sys/build/cfgs.rs Normal file
View File

@ -0,0 +1,43 @@
pub fn get(openssl_version: Option<u64>, libressl_version: Option<u64>) -> Vec<&'static str> {
let mut cfgs = vec![];
if let Some(libressl_version) = libressl_version {
cfgs.push("libressl");
if libressl_version >= 0x2_05_01_00_0 {
cfgs.push("libressl251");
}
if libressl_version >= 0x2_06_01_00_0 {
cfgs.push("libressl261");
}
if libressl_version >= 0x2_07_00_00_0 {
cfgs.push("libressl270");
}
} else {
let openssl_version = openssl_version.unwrap();
if openssl_version >= 0x1_00_01_00_0 {
cfgs.push("ossl101");
}
if openssl_version >= 0x1_00_02_00_0 {
cfgs.push("ossl102");
}
if openssl_version >= 0x1_00_02_08_0 {
cfgs.push("ossl102h");
}
if openssl_version >= 0x1_01_00_00_0 {
cfgs.push("ossl110");
}
if openssl_version >= 0x1_01_00_06_0 {
cfgs.push("ossl110f");
}
if openssl_version >= 0x1_01_00_07_0 {
cfgs.push("ossl110g");
}
if openssl_version >= 0x1_01_01_00_0 {
cfgs.push("ossl111");
}
}
cfgs
}

View File

@ -11,6 +11,8 @@ use std::io::{BufWriter, Write};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::process::Command; use std::process::Command;
mod cfgs;
// The set of `OPENSSL_NO_<FOO>`s that we care about. // The set of `OPENSSL_NO_<FOO>`s that we care about.
const DEFINES: &'static [&'static str] = &[ const DEFINES: &'static [&'static str] = &[
"OPENSSL_NO_BUF_FREELISTS", "OPENSSL_NO_BUF_FREELISTS",
@ -104,6 +106,8 @@ fn find_openssl_dir(target: &str) -> OsString {
let host = env::var("HOST").unwrap(); let host = env::var("HOST").unwrap();
if host == target && target.contains("apple-darwin") { if host == target && target.contains("apple-darwin") {
// Check up default Homebrew installation location first
// for quick resolution if possible.
let homebrew = Path::new("/usr/local/opt/openssl@1.1"); let homebrew = Path::new("/usr/local/opt/openssl@1.1");
if homebrew.exists() { if homebrew.exists() {
return homebrew.to_path_buf().into(); return homebrew.to_path_buf().into();
@ -112,6 +116,22 @@ fn find_openssl_dir(target: &str) -> OsString {
if homebrew.exists() { if homebrew.exists() {
return homebrew.to_path_buf().into(); return homebrew.to_path_buf().into();
} }
// Calling `brew --prefix <package>` command usually slow and
// takes seconds, and will be used only as a last resort.
let output = execute_command_and_get_output("brew", &["--prefix", "openssl@1.1"]);
if let Some(ref output) = output {
let homebrew = Path::new(&output);
if homebrew.exists() {
return homebrew.to_path_buf().into();
}
}
let output = execute_command_and_get_output("brew", &["--prefix", "openssl"]);
if let Some(ref output) = output {
let homebrew = Path::new(&output);
if homebrew.exists() {
return homebrew.to_path_buf().into();
}
}
} }
try_pkg_config(); try_pkg_config();
@ -409,6 +429,10 @@ See rust-openssl README for more information:
} }
println!("cargo:conf={}", enabled.join(",")); println!("cargo:conf={}", enabled.join(","));
for cfg in cfgs::get(openssl_version, libressl_version) {
println!("cargo:rustc-cfg={}", cfg);
}
if let Some(libressl_version) = libressl_version { if let Some(libressl_version) = libressl_version {
println!("cargo:libressl_version_number={:x}", libressl_version); println!("cargo:libressl_version_number={:x}", libressl_version);
@ -427,8 +451,6 @@ See rust-openssl README for more information:
_ => version_error(), _ => version_error(),
}; };
println!("cargo:rustc-cfg=libressl");
println!("cargo:rustc-cfg=libressl2{}{}", minor, fix);
println!("cargo:libressl=true"); println!("cargo:libressl=true");
println!("cargo:libressl_version=2{}{}", minor, fix); println!("cargo:libressl_version=2{}{}", minor, fix);
println!("cargo:version=101"); println!("cargo:version=101");
@ -437,37 +459,22 @@ See rust-openssl README for more information:
let openssl_version = openssl_version.unwrap(); let openssl_version = openssl_version.unwrap();
println!("cargo:version_number={:x}", openssl_version); println!("cargo:version_number={:x}", openssl_version);
if openssl_version >= 0x1_00_02_08_0 {
println!("cargo:rustc-cfg=ossl102h");
}
if openssl_version >= 0x1_01_00_07_0 {
println!("cargo:rustc-cfg=ossl110g");
}
if openssl_version >= 0x1_01_02_00_0 { if openssl_version >= 0x1_01_02_00_0 {
version_error() version_error()
} else if openssl_version >= 0x1_01_01_00_0 { } else if openssl_version >= 0x1_01_01_00_0 {
println!("cargo:rustc-cfg=ossl111");
println!("cargo:rustc-cfg=ossl110");
println!("cargo:version=111"); println!("cargo:version=111");
Version::Openssl11x Version::Openssl11x
} else if openssl_version >= 0x1_01_00_06_0 { } else if openssl_version >= 0x1_01_00_06_0 {
println!("cargo:rustc-cfg=ossl110");
println!("cargo:rustc-cfg=ossl110f");
println!("cargo:version=110"); println!("cargo:version=110");
println!("cargo:patch=f"); println!("cargo:patch=f");
Version::Openssl11x Version::Openssl11x
} else if openssl_version >= 0x1_01_00_00_0 { } else if openssl_version >= 0x1_01_00_00_0 {
println!("cargo:rustc-cfg=ossl110");
println!("cargo:version=110"); println!("cargo:version=110");
Version::Openssl11x Version::Openssl11x
} else if openssl_version >= 0x1_00_02_00_0 { } else if openssl_version >= 0x1_00_02_00_0 {
println!("cargo:rustc-cfg=ossl102");
println!("cargo:version=102"); println!("cargo:version=102");
Version::Openssl10x Version::Openssl10x
} else if openssl_version >= 0x1_00_01_00_0 { } else if openssl_version >= 0x1_00_01_00_0 {
println!("cargo:rustc-cfg=ossl101");
println!("cargo:version=101"); println!("cargo:version=101");
Version::Openssl10x Version::Openssl10x
} else { } else {
@ -524,10 +531,12 @@ fn determine_mode(libdir: &Path, libs: &[&str]) -> &'static str {
.map(|e| e.file_name()) .map(|e| e.file_name())
.filter_map(|e| e.into_string().ok()) .filter_map(|e| e.into_string().ok())
.collect::<HashSet<_>>(); .collect::<HashSet<_>>();
let can_static = libs.iter() let can_static = libs
.iter()
.all(|l| files.contains(&format!("lib{}.a", l)) || files.contains(&format!("{}.lib", l))); .all(|l| files.contains(&format!("lib{}.a", l)) || files.contains(&format!("{}.lib", l)));
let can_dylib = libs.iter().all(|l| { let can_dylib = libs.iter().all(|l| {
files.contains(&format!("lib{}.so", l)) || files.contains(&format!("{}.dll", l)) files.contains(&format!("lib{}.so", l))
|| files.contains(&format!("{}.dll", l))
|| files.contains(&format!("lib{}.dylib", l)) || files.contains(&format!("lib{}.dylib", l))
}); });
match (can_static, can_dylib) { match (can_static, can_dylib) {
@ -548,3 +557,16 @@ fn determine_mode(libdir: &Path, libs: &[&str]) -> &'static str {
// practices with security libs", let's link dynamically. // practices with security libs", let's link dynamically.
"dylib" "dylib"
} }
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 {
if r1.status.success() {
let r2 = String::from_utf8(r1.stdout.clone());
if let Ok(r3) = r2 {
return Some(r3.trim().to_string());
}
}
}
return None;
}

View File

@ -236,8 +236,10 @@ pub const EVP_PKEY_OP_VERIFYCTX: c_int = 1 << 7;
pub const EVP_PKEY_OP_ENCRYPT: c_int = 1 << 8; pub const EVP_PKEY_OP_ENCRYPT: c_int = 1 << 8;
pub const EVP_PKEY_OP_DECRYPT: c_int = 1 << 9; pub const EVP_PKEY_OP_DECRYPT: c_int = 1 << 9;
pub const EVP_PKEY_OP_TYPE_SIG: c_int = EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY pub const EVP_PKEY_OP_TYPE_SIG: c_int = EVP_PKEY_OP_SIGN
| EVP_PKEY_OP_VERIFYRECOVER | EVP_PKEY_OP_SIGNCTX | EVP_PKEY_OP_VERIFY
| EVP_PKEY_OP_VERIFYRECOVER
| EVP_PKEY_OP_SIGNCTX
| EVP_PKEY_OP_VERIFYCTX; | EVP_PKEY_OP_VERIFYCTX;
pub const EVP_PKEY_OP_TYPE_CRYPT: c_int = EVP_PKEY_OP_ENCRYPT | EVP_PKEY_OP_DECRYPT; pub const EVP_PKEY_OP_TYPE_CRYPT: c_int = EVP_PKEY_OP_ENCRYPT | EVP_PKEY_OP_DECRYPT;
@ -1259,21 +1261,23 @@ pub const SSL_VERIFY_NONE: c_int = 0;
pub const SSL_VERIFY_PEER: c_int = 1; pub const SSL_VERIFY_PEER: c_int = 1;
pub const SSL_VERIFY_FAIL_IF_NO_PEER_CERT: c_int = 2; pub const SSL_VERIFY_FAIL_IF_NO_PEER_CERT: c_int = 2;
#[cfg(not(any(libressl261, libressl262, libressl26x, libressl27x, ossl101)))] #[cfg(any(ossl102, all(libressl, not(libressl261))))]
pub const SSL_OP_TLSEXT_PADDING: c_ulong = 0x00000010; pub const SSL_OP_TLSEXT_PADDING: c_ulong = 0x00000010;
#[cfg(any(libressl261, libressl262, libressl26x, libressl27x))] #[cfg(libressl261)]
pub const SSL_OP_TLSEXT_PADDING: c_ulong = 0x0; pub const SSL_OP_TLSEXT_PADDING: c_ulong = 0x0;
pub const SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS: c_ulong = 0x00000800; pub const SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS: c_ulong = 0x00000800;
#[cfg(not(any(libressl261, libressl262, libressl26x, libressl27x)))] #[cfg(not(libressl261))]
pub const SSL_OP_CRYPTOPRO_TLSEXT_BUG: c_ulong = 0x80000000; pub const SSL_OP_CRYPTOPRO_TLSEXT_BUG: c_ulong = 0x80000000;
#[cfg(any(libressl261, libressl262, libressl26x, libressl27x))] #[cfg(libressl261)]
pub const SSL_OP_CRYPTOPRO_TLSEXT_BUG: c_ulong = 0x0; pub const SSL_OP_CRYPTOPRO_TLSEXT_BUG: c_ulong = 0x0;
pub const SSL_OP_LEGACY_SERVER_CONNECT: c_ulong = 0x00000004; pub const SSL_OP_LEGACY_SERVER_CONNECT: c_ulong = 0x00000004;
#[cfg(not(any(libressl, ossl110f, ossl111)))] #[cfg(not(any(libressl, ossl110f)))]
pub const SSL_OP_ALL: c_ulong = 0x80000BFF; pub const SSL_OP_ALL: c_ulong = 0x80000BFF;
#[cfg(any(ossl110f, ossl111))] #[cfg(ossl110f)]
pub const SSL_OP_ALL: c_ulong = SSL_OP_CRYPTOPRO_TLSEXT_BUG | SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS pub const SSL_OP_ALL: c_ulong = SSL_OP_CRYPTOPRO_TLSEXT_BUG
| SSL_OP_LEGACY_SERVER_CONNECT | SSL_OP_TLSEXT_PADDING | SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
| SSL_OP_LEGACY_SERVER_CONNECT
| SSL_OP_TLSEXT_PADDING
| SSL_OP_SAFARI_ECDHE_ECDSA_BUG; | SSL_OP_SAFARI_ECDHE_ECDSA_BUG;
pub const SSL_OP_NO_QUERY_MTU: c_ulong = 0x00001000; pub const SSL_OP_NO_QUERY_MTU: c_ulong = 0x00001000;
pub const SSL_OP_COOKIE_EXCHANGE: c_ulong = 0x00002000; pub const SSL_OP_COOKIE_EXCHANGE: c_ulong = 0x00002000;
@ -1285,12 +1289,15 @@ pub const SSL_OP_NO_TLSv1: c_ulong = 0x04000000;
pub const SSL_OP_NO_TLSv1_1: c_ulong = 0x10000000; pub const SSL_OP_NO_TLSv1_1: c_ulong = 0x10000000;
pub const SSL_OP_NO_TLSv1_2: c_ulong = 0x08000000; pub const SSL_OP_NO_TLSv1_2: c_ulong = 0x08000000;
#[cfg(not(any(ossl101, libressl, ossl111)))] #[cfg(all(ossl102, not(ossl111)))]
pub const SSL_OP_NO_SSL_MASK: c_ulong = pub const SSL_OP_NO_SSL_MASK: c_ulong =
SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2; SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2;
#[cfg(ossl111)] #[cfg(ossl111)]
pub const SSL_OP_NO_SSL_MASK: c_ulong = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 pub const SSL_OP_NO_SSL_MASK: c_ulong = SSL_OP_NO_SSLv2
| SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2 | SSL_OP_NO_SSLv3
| SSL_OP_NO_TLSv1
| SSL_OP_NO_TLSv1_1
| SSL_OP_NO_TLSv1_2
| SSL_OP_NO_TLSv1_3; | SSL_OP_NO_TLSv1_3;
pub const SSL_FILETYPE_PEM: c_int = X509_FILETYPE_PEM; pub const SSL_FILETYPE_PEM: c_int = X509_FILETYPE_PEM;
@ -1386,35 +1393,35 @@ pub const X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX: c_int = 52;
pub const X509_V_ERR_UNSUPPORTED_NAME_SYNTAX: c_int = 53; pub const X509_V_ERR_UNSUPPORTED_NAME_SYNTAX: c_int = 53;
pub const X509_V_ERR_CRL_PATH_VALIDATION_ERROR: c_int = 54; pub const X509_V_ERR_CRL_PATH_VALIDATION_ERROR: c_int = 54;
#[cfg(not(any(ossl101, libressl)))] #[cfg(ossl102)]
pub const X509_V_ERR_SUITE_B_INVALID_VERSION: c_int = 56; pub const X509_V_ERR_SUITE_B_INVALID_VERSION: c_int = 56;
#[cfg(not(any(ossl101, libressl)))] #[cfg(ossl102)]
pub const X509_V_ERR_SUITE_B_INVALID_ALGORITHM: c_int = 57; pub const X509_V_ERR_SUITE_B_INVALID_ALGORITHM: c_int = 57;
#[cfg(not(any(ossl101, libressl)))] #[cfg(ossl102)]
pub const X509_V_ERR_SUITE_B_INVALID_CURVE: c_int = 58; pub const X509_V_ERR_SUITE_B_INVALID_CURVE: c_int = 58;
#[cfg(not(any(ossl101, libressl)))] #[cfg(ossl102)]
pub const X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM: c_int = 59; pub const X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM: c_int = 59;
#[cfg(not(any(ossl101, libressl)))] #[cfg(ossl102)]
pub const X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED: c_int = 60; pub const X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED: c_int = 60;
#[cfg(not(any(ossl101, libressl)))] #[cfg(ossl102)]
pub const X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256: c_int = 61; pub const X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256: c_int = 61;
#[cfg(not(any(ossl101, libressl)))] #[cfg(ossl102)]
pub const X509_V_ERR_HOSTNAME_MISMATCH: c_int = 62; pub const X509_V_ERR_HOSTNAME_MISMATCH: c_int = 62;
#[cfg(not(any(ossl101, libressl)))] #[cfg(ossl102)]
pub const X509_V_ERR_EMAIL_MISMATCH: c_int = 63; pub const X509_V_ERR_EMAIL_MISMATCH: c_int = 63;
#[cfg(not(any(ossl101, libressl)))] #[cfg(ossl102)]
pub const X509_V_ERR_IP_ADDRESS_MISMATCH: c_int = 64; pub const X509_V_ERR_IP_ADDRESS_MISMATCH: c_int = 64;
#[cfg(not(any(ossl101, libressl)))] #[cfg(any(ossl102, libressl261))]
pub const X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT: c_uint = 0x1; pub const X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT: c_uint = 0x1;
#[cfg(not(any(ossl101, libressl)))] #[cfg(any(ossl102, libressl261))]
pub const X509_CHECK_FLAG_NO_WILDCARDS: c_uint = 0x2; pub const X509_CHECK_FLAG_NO_WILDCARDS: c_uint = 0x2;
#[cfg(not(any(ossl101, libressl)))] #[cfg(any(ossl102, libressl261))]
pub const X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS: c_uint = 0x4; pub const X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS: c_uint = 0x4;
#[cfg(not(any(ossl101, libressl)))] #[cfg(any(ossl102, libressl261))]
pub const X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS: c_uint = 0x8; pub const X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS: c_uint = 0x8;
#[cfg(not(any(ossl101, libressl)))] #[cfg(any(ossl102, libressl261))]
pub const X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS: c_uint = 0x10; pub const X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS: c_uint = 0x10;
pub const GEN_OTHERNAME: c_int = 0; pub const GEN_OTHERNAME: c_int = 0;
@ -1446,6 +1453,10 @@ pub unsafe fn BIO_set_retry_write(b: *mut BIO) {
BIO_set_flags(b, BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY) BIO_set_flags(b, BIO_FLAGS_WRITE | BIO_FLAGS_SHOULD_RETRY)
} }
pub unsafe fn EVP_get_digestbynid(type_: c_int) -> *const EVP_MD {
EVP_get_digestbyname(OBJ_nid2sn(type_))
}
// EVP_PKEY_CTX_ctrl macros // EVP_PKEY_CTX_ctrl macros
pub unsafe fn EVP_PKEY_CTX_set_rsa_padding(ctx: *mut EVP_PKEY_CTX, pad: c_int) -> c_int { pub unsafe fn EVP_PKEY_CTX_set_rsa_padding(ctx: *mut EVP_PKEY_CTX, pad: c_int) -> c_int {
EVP_PKEY_CTX_ctrl( EVP_PKEY_CTX_ctrl(
@ -1519,7 +1530,7 @@ pub unsafe fn SSL_CTX_add_extra_chain_cert(ctx: *mut SSL_CTX, x509: *mut X509) -
SSL_CTX_ctrl(ctx, SSL_CTRL_EXTRA_CHAIN_CERT, 0, x509 as *mut c_void) SSL_CTX_ctrl(ctx, SSL_CTRL_EXTRA_CHAIN_CERT, 0, x509 as *mut c_void)
} }
#[cfg(not(any(ossl101, libressl)))] #[cfg(ossl102)]
pub unsafe fn SSL_CTX_set0_verify_cert_store(ctx: *mut SSL_CTX, st: *mut X509_STORE) -> c_long { pub unsafe fn SSL_CTX_set0_verify_cert_store(ctx: *mut SSL_CTX, st: *mut X509_STORE) -> c_long {
SSL_CTX_ctrl(ctx, SSL_CTRL_SET_VERIFY_CERT_STORE, 0, st as *mut c_void) SSL_CTX_ctrl(ctx, SSL_CTRL_SET_VERIFY_CERT_STORE, 0, st as *mut c_void)
} }
@ -1634,9 +1645,9 @@ extern "C" {
pub fn BIO_new_socket(sock: c_int, close_flag: c_int) -> *mut BIO; pub fn BIO_new_socket(sock: c_int, close_flag: c_int) -> *mut BIO;
pub fn BIO_read(b: *mut BIO, buf: *mut c_void, len: c_int) -> c_int; pub fn BIO_read(b: *mut BIO, buf: *mut c_void, len: c_int) -> c_int;
pub fn BIO_write(b: *mut BIO, buf: *const c_void, len: c_int) -> c_int; pub fn BIO_write(b: *mut BIO, buf: *const c_void, len: c_int) -> c_int;
#[cfg(any(ossl101, libressl))] #[cfg(not(ossl102))]
pub fn BIO_new_mem_buf(buf: *mut c_void, len: c_int) -> *mut BIO; pub fn BIO_new_mem_buf(buf: *mut c_void, len: c_int) -> *mut BIO;
#[cfg(not(any(ossl101, libressl)))] #[cfg(ossl102)]
pub fn BIO_new_mem_buf(buf: *const c_void, len: c_int) -> *mut BIO; pub fn BIO_new_mem_buf(buf: *const c_void, len: c_int) -> *mut BIO;
pub fn BIO_set_flags(b: *mut BIO, flags: c_int); pub fn BIO_set_flags(b: *mut BIO, flags: c_int);
pub fn BIO_clear_flags(b: *mut BIO, flags: c_int); pub fn BIO_clear_flags(b: *mut BIO, flags: c_int);
@ -1767,11 +1778,11 @@ extern "C" {
pub fn DH_new() -> *mut DH; pub fn DH_new() -> *mut DH;
pub fn DH_free(dh: *mut DH); pub fn DH_free(dh: *mut DH);
#[cfg(not(any(ossl101, libressl)))] #[cfg(ossl102)]
pub fn DH_get_1024_160() -> *mut DH; pub fn DH_get_1024_160() -> *mut DH;
#[cfg(not(any(ossl101, libressl)))] #[cfg(ossl102)]
pub fn DH_get_2048_224() -> *mut DH; pub fn DH_get_2048_224() -> *mut DH;
#[cfg(not(any(ossl101, libressl)))] #[cfg(ossl102)]
pub fn DH_get_2048_256() -> *mut DH; pub fn DH_get_2048_256() -> *mut DH;
pub fn EC_KEY_new() -> *mut EC_KEY; pub fn EC_KEY_new() -> *mut EC_KEY;
@ -2029,13 +2040,13 @@ extern "C" {
e: *mut ENGINE, e: *mut ENGINE,
pkey: *mut EVP_PKEY, pkey: *mut EVP_PKEY,
) -> c_int; ) -> c_int;
#[cfg(any(ossl101, libressl))] #[cfg(not(ossl102))]
pub fn EVP_DigestVerifyFinal( pub fn EVP_DigestVerifyFinal(
ctx: *mut EVP_MD_CTX, ctx: *mut EVP_MD_CTX,
sigret: *mut c_uchar, sigret: *mut c_uchar,
siglen: size_t, siglen: size_t,
) -> c_int; ) -> c_int;
#[cfg(not(any(ossl101, libressl)))] #[cfg(ossl102)]
pub fn EVP_DigestVerifyFinal( pub fn EVP_DigestVerifyFinal(
ctx: *mut EVP_MD_CTX, ctx: *mut EVP_MD_CTX,
sigret: *const c_uchar, sigret: *const c_uchar,
@ -2095,7 +2106,10 @@ extern "C" {
a: *const ASN1_OBJECT, a: *const ASN1_OBJECT,
no_name: c_int, no_name: c_int,
) -> c_int; ) -> c_int;
pub fn OBJ_nid2ln(nid: c_int) -> *const c_char;
pub fn OBJ_nid2sn(nid: c_int) -> *const c_char; pub fn OBJ_nid2sn(nid: c_int) -> *const c_char;
pub fn OBJ_find_sigid_algs(signid: c_int, pdig_nid: *mut c_int, ppkey_nid: *mut c_int)
-> c_int;
pub fn OCSP_BASICRESP_new() -> *mut OCSP_BASICRESP; pub fn OCSP_BASICRESP_new() -> *mut OCSP_BASICRESP;
pub fn OCSP_BASICRESP_free(r: *mut OCSP_BASICRESP); pub fn OCSP_BASICRESP_free(r: *mut OCSP_BASICRESP);
@ -2351,6 +2365,14 @@ extern "C" {
k: *mut RSA, k: *mut RSA,
) -> c_int; ) -> c_int;
pub fn RSA_padding_check_PKCS1_type_2(
to: *mut c_uchar,
tlen: c_int,
f: *const c_uchar,
fl: c_int,
rsa_len: c_int,
) -> c_int;
pub fn DSA_new() -> *mut DSA; pub fn DSA_new() -> *mut DSA;
pub fn DSA_free(dsa: *mut DSA); pub fn DSA_free(dsa: *mut DSA);
pub fn DSA_size(dsa: *const DSA) -> c_int; pub fn DSA_size(dsa: *const DSA) -> c_int;
@ -2439,14 +2461,14 @@ extern "C" {
pub fn SSL_get_ex_data(ssl: *const SSL, idx: c_int) -> *mut c_void; pub fn SSL_get_ex_data(ssl: *const SSL, idx: c_int) -> *mut c_void;
pub fn SSL_get_servername(ssl: *const SSL, name_type: c_int) -> *const c_char; pub fn SSL_get_servername(ssl: *const SSL, name_type: c_int) -> *const c_char;
pub fn SSL_get_current_cipher(ssl: *const SSL) -> *const SSL_CIPHER; pub fn SSL_get_current_cipher(ssl: *const SSL) -> *const SSL_CIPHER;
#[cfg(not(any(ossl101, libressl)))] #[cfg(any(ossl102, libressl261))]
pub fn SSL_get0_param(ssl: *mut SSL) -> *mut X509_VERIFY_PARAM; pub fn SSL_get0_param(ssl: *mut SSL) -> *mut X509_VERIFY_PARAM;
pub fn SSL_get_verify_result(ssl: *const SSL) -> c_long; pub fn SSL_get_verify_result(ssl: *const SSL) -> c_long;
pub fn SSL_shutdown(ssl: *mut SSL) -> c_int; pub fn SSL_shutdown(ssl: *mut SSL) -> c_int;
pub fn SSL_get_certificate(ssl: *const SSL) -> *mut X509; pub fn SSL_get_certificate(ssl: *const SSL) -> *mut X509;
#[cfg(any(ossl101, libressl))] #[cfg(not(ossl102))]
pub fn SSL_get_privatekey(ssl: *mut SSL) -> *mut EVP_PKEY; pub fn SSL_get_privatekey(ssl: *mut SSL) -> *mut EVP_PKEY;
#[cfg(not(any(ossl101, libressl)))] #[cfg(ossl102)]
pub fn SSL_get_privatekey(ssl: *const SSL) -> *mut EVP_PKEY; pub fn SSL_get_privatekey(ssl: *const SSL) -> *mut EVP_PKEY;
pub fn SSL_load_client_CA_file(file: *const c_char) -> *mut stack_st_X509_NAME; pub fn SSL_load_client_CA_file(file: *const c_char) -> *mut stack_st_X509_NAME;
pub fn SSL_set_tmp_dh_callback( pub fn SSL_set_tmp_dh_callback(
@ -2539,9 +2561,9 @@ extern "C" {
remove_session_cb: Option<unsafe extern "C" fn(*mut SSL_CTX, *mut SSL_SESSION)>, remove_session_cb: Option<unsafe extern "C" fn(*mut SSL_CTX, *mut SSL_SESSION)>,
); );
#[cfg(not(any(ossl101, libressl)))] #[cfg(ossl102)]
pub fn SSL_CTX_get0_certificate(ctx: *const SSL_CTX) -> *mut X509; pub fn SSL_CTX_get0_certificate(ctx: *const SSL_CTX) -> *mut X509;
#[cfg(not(any(ossl101, libressl)))] #[cfg(ossl102)]
pub fn SSL_CTX_get0_privatekey(ctx: *const SSL_CTX) -> *mut EVP_PKEY; pub fn SSL_CTX_get0_privatekey(ctx: *const SSL_CTX) -> *mut EVP_PKEY;
pub fn SSL_CTX_set_cipher_list(ssl: *mut SSL_CTX, s: *const c_char) -> c_int; pub fn SSL_CTX_set_cipher_list(ssl: *mut SSL_CTX, s: *const c_char) -> c_int;
@ -2600,10 +2622,12 @@ extern "C" {
); );
pub fn SSL_get_session(s: *const SSL) -> *mut SSL_SESSION; pub fn SSL_get_session(s: *const SSL) -> *mut SSL_SESSION;
pub fn SSL_set_session(ssl: *mut SSL, session: *mut SSL_SESSION) -> c_int; pub fn SSL_set_session(ssl: *mut SSL, session: *mut SSL_SESSION) -> c_int;
#[cfg(not(any(ossl101, libressl, ossl110f, ossl111)))] #[cfg(all(ossl102, not(ossl110f)))]
pub fn SSL_is_server(s: *mut SSL) -> c_int; pub fn SSL_is_server(s: *mut SSL) -> c_int;
#[cfg(any(ossl110f, ossl111))] #[cfg(ossl110f)]
pub fn SSL_is_server(s: *const SSL) -> c_int; pub fn SSL_is_server(s: *const SSL) -> c_int;
pub fn SSL_get_finished(s: *const SSL, buf: *mut c_void, count: size_t) -> size_t;
pub fn SSL_get_peer_finished(s: *const SSL, buf: *mut c_void, count: size_t) -> size_t;
pub fn SSL_SESSION_free(s: *mut SSL_SESSION); pub fn SSL_SESSION_free(s: *mut SSL_SESSION);
pub fn SSL_SESSION_get_id(s: *const SSL_SESSION, len: *mut c_uint) -> *const c_uchar; pub fn SSL_SESSION_get_id(s: *const SSL_SESSION, len: *mut c_uint) -> *const c_uchar;
@ -2615,14 +2639,14 @@ extern "C" {
) -> *mut SSL_SESSION; ) -> *mut SSL_SESSION;
pub fn i2d_SSL_SESSION(s: *mut SSL_SESSION, pp: *mut *mut c_uchar) -> c_int; pub fn i2d_SSL_SESSION(s: *mut SSL_SESSION, pp: *mut *mut c_uchar) -> c_int;
#[cfg(not(ossl101))] #[cfg(any(ossl102, libressl261))]
pub fn SSL_CTX_set_alpn_protos(s: *mut SSL_CTX, data: *const c_uchar, len: c_uint) -> c_int; pub fn SSL_CTX_set_alpn_protos(s: *mut SSL_CTX, data: *const c_uchar, len: c_uint) -> c_int;
#[cfg(not(ossl101))] #[cfg(any(ossl102, libressl261))]
pub fn SSL_set_alpn_protos(s: *mut SSL, data: *const c_uchar, len: c_uint) -> c_int; pub fn SSL_set_alpn_protos(s: *mut SSL, data: *const c_uchar, len: c_uint) -> c_int;
// FIXME should take an Option<unsafe extern "C" fn> // FIXME should take an Option<unsafe extern "C" fn>
#[cfg(not(ossl101))] #[cfg(any(ossl102, libressl261))]
pub fn SSL_CTX_set_alpn_select_cb( pub fn SSL_CTX_set_alpn_select_cb(
ssl: *mut SSL_CTX, ssl: *mut SSL_CTX,
cb: extern "C" fn( cb: extern "C" fn(
@ -2635,7 +2659,7 @@ extern "C" {
) -> c_int, ) -> c_int,
arg: *mut c_void, arg: *mut c_void,
); );
#[cfg(not(ossl101))] #[cfg(any(ossl102, libressl261))]
pub fn SSL_get0_alpn_selected(s: *const SSL, data: *mut *const c_uchar, len: *mut c_uint); pub fn SSL_get0_alpn_selected(s: *const SSL, data: *mut *const c_uchar, len: *mut c_uint);
pub fn X509_add_ext(x: *mut X509, ext: *mut X509_EXTENSION, loc: c_int) -> c_int; pub fn X509_add_ext(x: *mut X509, ext: *mut X509_EXTENSION, loc: c_int) -> c_int;
@ -2727,17 +2751,17 @@ extern "C" {
pub fn X509_REQ_get_extensions(req: *mut X509_REQ) -> *mut stack_st_X509_EXTENSION; pub fn X509_REQ_get_extensions(req: *mut X509_REQ) -> *mut stack_st_X509_EXTENSION;
pub fn X509_REQ_sign(x: *mut X509_REQ, pkey: *mut EVP_PKEY, md: *const EVP_MD) -> c_int; pub fn X509_REQ_sign(x: *mut X509_REQ, pkey: *mut EVP_PKEY, md: *const EVP_MD) -> c_int;
#[cfg(not(ossl101))] #[cfg(any(ossl102, libressl261))]
pub fn X509_VERIFY_PARAM_free(param: *mut X509_VERIFY_PARAM); pub fn X509_VERIFY_PARAM_free(param: *mut X509_VERIFY_PARAM);
#[cfg(not(any(ossl101, libressl)))] #[cfg(any(ossl102, libressl261))]
pub fn X509_VERIFY_PARAM_set_hostflags(param: *mut X509_VERIFY_PARAM, flags: c_uint); pub fn X509_VERIFY_PARAM_set_hostflags(param: *mut X509_VERIFY_PARAM, flags: c_uint);
#[cfg(not(any(ossl101, libressl)))] #[cfg(any(ossl102, libressl261))]
pub fn X509_VERIFY_PARAM_set1_host( pub fn X509_VERIFY_PARAM_set1_host(
param: *mut X509_VERIFY_PARAM, param: *mut X509_VERIFY_PARAM,
name: *const c_char, name: *const c_char,
namelen: size_t, namelen: size_t,
) -> c_int; ) -> c_int;
#[cfg(not(any(ossl101, libressl)))] #[cfg(any(ossl102, libressl261))]
pub fn X509_VERIFY_PARAM_set1_ip( pub fn X509_VERIFY_PARAM_set1_ip(
param: *mut X509_VERIFY_PARAM, param: *mut X509_VERIFY_PARAM,
ip: *const c_uchar, ip: *const c_uchar,
@ -2839,5 +2863,9 @@ extern "C" {
); );
pub fn EVP_MD_size(md: *const EVP_MD) -> c_int; pub fn EVP_MD_size(md: *const EVP_MD) -> c_int;
pub fn EVP_get_digestbyname(name: *const c_char) -> *const EVP_MD;
pub fn EVP_get_cipherbyname(name: *const c_char) -> *const EVP_CIPHER; pub fn EVP_get_cipherbyname(name: *const c_char) -> *const EVP_CIPHER;
pub fn SSL_set_connect_state(s: *mut SSL);
pub fn SSL_set_accept_state(s: *mut SSL);
} }

View File

@ -1,19 +1,18 @@
use libc::{c_char, c_int, c_long, c_uchar, c_uint, c_ulong, c_void, size_t};
use std::mem; use std::mem;
use std::ptr; use std::ptr;
use std::sync::{Mutex, MutexGuard}; use std::sync::{Mutex, MutexGuard};
use std::sync::{Once, ONCE_INIT}; use std::sync::{Once, ONCE_INIT};
#[cfg(libressl250)] #[cfg(not(libressl251))]
pub use libressl::v250::*; pub use libressl::v250::*;
#[cfg(not(libressl250))] #[cfg(libressl251)]
pub use libressl::v25x::*; pub use libressl::v251::*;
use libc::{c_char, c_int, c_long, c_uchar, c_uint, c_ulong, c_void, size_t}; #[cfg(not(libressl251))]
#[cfg(libressl250)]
mod v250; mod v250;
#[cfg(not(libressl250))] #[cfg(libressl251)]
mod v25x; mod v251;
#[repr(C)] #[repr(C)]
pub struct stack_st_ASN1_OBJECT { pub struct stack_st_ASN1_OBJECT {
@ -337,9 +336,9 @@ pub const SSL_CTRL_OPTIONS: c_int = 32;
pub const SSL_CTRL_CLEAR_OPTIONS: c_int = 77; pub const SSL_CTRL_CLEAR_OPTIONS: c_int = 77;
pub const SSL_CTRL_SET_ECDH_AUTO: c_int = 94; pub const SSL_CTRL_SET_ECDH_AUTO: c_int = 94;
#[cfg(any(libressl261, libressl262, libressl26x, libressl27x))] #[cfg(libressl261)]
pub const SSL_OP_ALL: c_ulong = 0x4; pub const SSL_OP_ALL: c_ulong = 0x4;
#[cfg(not(any(libressl261, libressl262, libressl26x, libressl27x)))] #[cfg(not(libressl261))]
pub const SSL_OP_ALL: c_ulong = 0x80000014; pub const SSL_OP_ALL: c_ulong = 0x80000014;
pub const SSL_OP_CISCO_ANYCONNECT: c_ulong = 0x0; pub const SSL_OP_CISCO_ANYCONNECT: c_ulong = 0x0;
pub const SSL_OP_NO_COMPRESSION: c_ulong = 0x0; pub const SSL_OP_NO_COMPRESSION: c_ulong = 0x0;
@ -352,9 +351,9 @@ pub const SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER: c_ulong = 0x0;
pub const SSL_OP_SSLEAY_080_CLIENT_DH_BUG: c_ulong = 0x0; pub const SSL_OP_SSLEAY_080_CLIENT_DH_BUG: c_ulong = 0x0;
pub const SSL_OP_TLS_D5_BUG: c_ulong = 0x0; pub const SSL_OP_TLS_D5_BUG: c_ulong = 0x0;
pub const SSL_OP_TLS_BLOCK_PADDING_BUG: c_ulong = 0x0; pub const SSL_OP_TLS_BLOCK_PADDING_BUG: c_ulong = 0x0;
#[cfg(any(libressl261, libressl262, libressl26x, libressl27x))] #[cfg(libressl261)]
pub const SSL_OP_SINGLE_ECDH_USE: c_ulong = 0x0; pub const SSL_OP_SINGLE_ECDH_USE: c_ulong = 0x0;
#[cfg(not(any(libressl261, libressl262, libressl26x, libressl27x)))] #[cfg(not(libressl261))]
pub const SSL_OP_SINGLE_ECDH_USE: c_ulong = 0x00080000; pub const SSL_OP_SINGLE_ECDH_USE: c_ulong = 0x00080000;
pub const SSL_OP_SINGLE_DH_USE: c_ulong = 0x00100000; pub const SSL_OP_SINGLE_DH_USE: c_ulong = 0x00100000;
pub const SSL_OP_NO_SSLv2: c_ulong = 0x0; pub const SSL_OP_NO_SSLv2: c_ulong = 0x0;
@ -448,6 +447,28 @@ pub unsafe fn SSL_session_reused(ssl: *mut ::SSL) -> c_int {
::SSL_ctrl(ssl, SSL_CTRL_GET_SESSION_REUSED, 0, ptr::null_mut()) as c_int ::SSL_ctrl(ssl, SSL_CTRL_GET_SESSION_REUSED, 0, ptr::null_mut()) as c_int
} }
pub unsafe fn SSL_CTX_get_options(ctx: *const ::SSL_CTX) -> c_ulong {
::SSL_CTX_ctrl(ctx as *mut _, ::SSL_CTRL_OPTIONS, 0, ptr::null_mut()) as c_ulong
}
pub unsafe fn SSL_CTX_set_options(ctx: *const ::SSL_CTX, op: c_ulong) -> c_ulong {
::SSL_CTX_ctrl(
ctx as *mut _,
::SSL_CTRL_OPTIONS,
op as c_long,
ptr::null_mut(),
) as c_ulong
}
pub unsafe fn SSL_CTX_clear_options(ctx: *const ::SSL_CTX, op: c_ulong) -> c_ulong {
::SSL_CTX_ctrl(
ctx as *mut _,
::SSL_CTRL_CLEAR_OPTIONS,
op as c_long,
ptr::null_mut(),
) as c_ulong
}
extern "C" { extern "C" {
pub fn BIO_new(type_: *mut BIO_METHOD) -> *mut BIO; pub fn BIO_new(type_: *mut BIO_METHOD) -> *mut BIO;
pub fn BIO_s_file() -> *mut BIO_METHOD; pub fn BIO_s_file() -> *mut BIO_METHOD;
@ -540,6 +561,15 @@ extern "C" {
unsafe extern "C" fn(*mut ::SSL, *mut c_uchar, c_int, *mut c_int) -> *mut SSL_SESSION, unsafe extern "C" fn(*mut ::SSL, *mut c_uchar, c_int, *mut c_int) -> *mut SSL_SESSION,
>, >,
); );
#[cfg(libressl261)]
pub fn SSL_CTX_set_min_proto_version(ctx: *mut ::SSL_CTX, version: u16) -> c_int;
#[cfg(libressl261)]
pub fn SSL_CTX_set_max_proto_version(ctx: *mut ::SSL_CTX, version: u16) -> c_int;
#[cfg(libressl270)]
pub fn SSL_CTX_get_min_proto_version(ctx: *mut ::SSL_CTX) -> c_int;
#[cfg(libressl270)]
pub fn SSL_CTX_get_max_proto_version(ctx: *mut ::SSL_CTX) -> c_int;
pub fn X509_get_subject_name(x: *mut ::X509) -> *mut ::X509_NAME; pub fn X509_get_subject_name(x: *mut ::X509) -> *mut ::X509_NAME;
pub fn X509_get_issuer_name(x: *mut ::X509) -> *mut ::X509_NAME; pub fn X509_get_issuer_name(x: *mut ::X509) -> *mut ::X509_NAME;
pub fn X509_set_notAfter(x: *mut ::X509, tm: *const ::ASN1_TIME) -> c_int; pub fn X509_set_notAfter(x: *mut ::X509, tm: *const ::ASN1_TIME) -> c_int;

View File

@ -1,4 +1,4 @@
use libc::{c_int, c_char, c_void, c_long, c_uchar, size_t, c_uint, c_ulong, time_t}; use libc::{c_char, c_int, c_long, c_uchar, c_uint, c_ulong, c_void, size_t, time_t};
use super::*; use super::*;
@ -84,6 +84,6 @@ pub struct X509_VERIFY_PARAM {
pub purpose: c_int, pub purpose: c_int,
pub trust: c_int, pub trust: c_int,
pub depth: c_int, pub depth: c_int,
policies: *mut stack_st_ASN1_OBJECT, pub policies: *mut stack_st_ASN1_OBJECT,
id: *mut c_void, id: *mut c_void,
} }

View File

@ -1,8 +1,8 @@
use libc::{c_int, c_long, c_uchar, c_uint, c_ulong}; use libc::{c_int, c_long, c_uchar, c_uint, c_ulong};
#[cfg(any(ossl101, ossl102))] #[cfg(not(ossl110))]
mod v10x; mod v10x;
#[cfg(any(ossl101, ossl102))] #[cfg(not(ossl110))]
pub use openssl::v10x::*; pub use openssl::v10x::*;
#[cfg(ossl110)] #[cfg(ossl110)]
@ -15,7 +15,7 @@ mod v111;
#[cfg(ossl111)] #[cfg(ossl111)]
pub use openssl::v111::*; pub use openssl::v111::*;
#[cfg(not(ossl101))] #[cfg(ossl102)]
pub const SSL_CTRL_SET_VERIFY_CERT_STORE: c_int = 106; pub const SSL_CTRL_SET_VERIFY_CERT_STORE: c_int = 106;
pub const SSL_MODE_SEND_CLIENTHELLO_TIME: c_long = 0x20; pub const SSL_MODE_SEND_CLIENTHELLO_TIME: c_long = 0x20;
@ -28,9 +28,9 @@ pub const SSL_OP_CISCO_ANYCONNECT: c_ulong = 0x00008000;
pub const SSL_OP_NO_COMPRESSION: c_ulong = 0x00020000; pub const SSL_OP_NO_COMPRESSION: c_ulong = 0x00020000;
pub const SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION: c_ulong = 0x00040000; pub const SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION: c_ulong = 0x00040000;
pub const SSL_OP_NO_SSLv3: c_ulong = 0x02000000; pub const SSL_OP_NO_SSLv3: c_ulong = 0x02000000;
#[cfg(not(ossl101))] #[cfg(ossl102)]
pub const SSL_OP_NO_DTLSv1: c_ulong = 0x04000000; pub const SSL_OP_NO_DTLSv1: c_ulong = 0x04000000;
#[cfg(not(ossl101))] #[cfg(ossl102)]
pub const SSL_OP_NO_DTLSv1_2: c_ulong = 0x08000000; pub const SSL_OP_NO_DTLSv1_2: c_ulong = 0x08000000;
pub const X509_V_ERR_UNSPECIFIED: c_int = 1; pub const X509_V_ERR_UNSPECIFIED: c_int = 1;
@ -55,7 +55,7 @@ pub const CMS_PARTIAL: c_uint = 0x4000;
pub const CMS_REUSE_DIGEST: c_uint = 0x8000; pub const CMS_REUSE_DIGEST: c_uint = 0x8000;
pub const CMS_USE_KEYID: c_uint = 0x10000; pub const CMS_USE_KEYID: c_uint = 0x10000;
pub const CMS_DEBUG_DECRYPT: c_uint = 0x20000; pub const CMS_DEBUG_DECRYPT: c_uint = 0x20000;
#[cfg(not(ossl101))] #[cfg(ossl102)]
pub const CMS_KEY_PARAM: c_uint = 0x40000; pub const CMS_KEY_PARAM: c_uint = 0x40000;
extern "C" { extern "C" {

View File

@ -5,7 +5,7 @@ use std::ptr;
use std::sync::{Mutex, MutexGuard}; use std::sync::{Mutex, MutexGuard};
use std::sync::{Once, ONCE_INIT}; use std::sync::{Once, ONCE_INIT};
#[cfg(not(ossl101))] #[cfg(ossl102)]
use libc::time_t; use libc::time_t;
use libc::{c_char, c_int, c_long, c_uchar, c_uint, c_ulong, c_void, size_t}; use libc::{c_char, c_int, c_long, c_uchar, c_uint, c_ulong, c_void, size_t};
@ -573,9 +573,6 @@ pub struct SSL_CTX {
#[cfg(all(not(osslconf = "OPENSSL_NO_TLSEXT"), ossl101))] #[cfg(all(not(osslconf = "OPENSSL_NO_TLSEXT"), ossl101))]
srtp_profiles: *mut c_void, srtp_profiles: *mut c_void,
#[cfg(all(not(osslconf = "OPENSSL_NO_TLSEXT"), ossl102))]
srtp_profiles: *mut c_void,
#[cfg(all(not(osslconf = "OPENSSL_NO_TLSEXT"), ossl102))] #[cfg(all(not(osslconf = "OPENSSL_NO_TLSEXT"), ossl102))]
alpn_select_cb: *mut c_void, alpn_select_cb: *mut c_void,
#[cfg(all(not(osslconf = "OPENSSL_NO_TLSEXT"), ossl102))] #[cfg(all(not(osslconf = "OPENSSL_NO_TLSEXT"), ossl102))]
@ -669,7 +666,7 @@ pub struct SRP_CTX {
} }
#[repr(C)] #[repr(C)]
#[cfg(not(ossl101))] #[cfg(ossl102)]
pub struct X509_VERIFY_PARAM { pub struct X509_VERIFY_PARAM {
pub name: *mut c_char, pub name: *mut c_char,
pub check_time: time_t, pub check_time: time_t,
@ -682,7 +679,7 @@ pub struct X509_VERIFY_PARAM {
pub id: *mut X509_VERIFY_PARAM_ID, pub id: *mut X509_VERIFY_PARAM_ID,
} }
#[cfg(not(ossl101))] #[cfg(ossl102)]
pub enum X509_VERIFY_PARAM_ID {} pub enum X509_VERIFY_PARAM_ID {}
pub enum PKCS12 {} pub enum PKCS12 {}
@ -810,6 +807,28 @@ pub unsafe fn SSL_session_reused(ssl: *mut ::SSL) -> c_int {
::SSL_ctrl(ssl, SSL_CTRL_GET_SESSION_REUSED, 0, ptr::null_mut()) as c_int ::SSL_ctrl(ssl, SSL_CTRL_GET_SESSION_REUSED, 0, ptr::null_mut()) as c_int
} }
pub unsafe fn SSL_CTX_get_options(ctx: *const ::SSL_CTX) -> c_ulong {
::SSL_CTX_ctrl(ctx as *mut _, ::SSL_CTRL_OPTIONS, 0, ptr::null_mut()) as c_ulong
}
pub unsafe fn SSL_CTX_set_options(ctx: *const ::SSL_CTX, op: c_ulong) -> c_ulong {
::SSL_CTX_ctrl(
ctx as *mut _,
::SSL_CTRL_OPTIONS,
op as c_long,
ptr::null_mut(),
) as c_ulong
}
pub unsafe fn SSL_CTX_clear_options(ctx: *const ::SSL_CTX, op: c_ulong) -> c_ulong {
::SSL_CTX_ctrl(
ctx as *mut _,
::SSL_CTRL_CLEAR_OPTIONS,
op as c_long,
ptr::null_mut(),
) as c_ulong
}
extern "C" { extern "C" {
pub fn BIO_new(type_: *mut BIO_METHOD) -> *mut BIO; pub fn BIO_new(type_: *mut BIO_METHOD) -> *mut BIO;
pub fn BIO_s_file() -> *mut BIO_METHOD; pub fn BIO_s_file() -> *mut BIO_METHOD;
@ -925,15 +944,15 @@ extern "C" {
loc: c_int, loc: c_int,
set: c_int, set: c_int,
) -> c_int; ) -> c_int;
#[cfg(not(ossl101))] #[cfg(ossl102)]
pub fn X509_get0_signature( pub fn X509_get0_signature(
psig: *mut *mut ::ASN1_BIT_STRING, psig: *mut *mut ::ASN1_BIT_STRING,
palg: *mut *mut ::X509_ALGOR, palg: *mut *mut ::X509_ALGOR,
x: *const ::X509, x: *const ::X509,
); );
#[cfg(not(ossl101))] #[cfg(ossl102)]
pub fn X509_get_signature_nid(x: *const X509) -> c_int; pub fn X509_get_signature_nid(x: *const X509) -> c_int;
#[cfg(not(ossl101))] #[cfg(ossl102)]
pub fn X509_ALGOR_get0( pub fn X509_ALGOR_get0(
paobj: *mut *mut ::ASN1_OBJECT, paobj: *mut *mut ::ASN1_OBJECT,
pptype: *mut c_int, pptype: *mut c_int,

View File

@ -280,6 +280,7 @@ extern "C" {
); );
pub fn SSL_get_client_random(ssl: *const SSL, out: *mut c_uchar, len: size_t) -> size_t; pub fn SSL_get_client_random(ssl: *const SSL, out: *mut c_uchar, len: size_t) -> size_t;
pub fn SSL_get_server_random(ssl: *const SSL, out: *mut c_uchar, len: size_t) -> size_t; pub fn SSL_get_server_random(ssl: *const SSL, out: *mut c_uchar, len: size_t) -> size_t;
pub fn SSL_get0_verified_chain(ssl: *const SSL) -> *mut stack_st_X509;
pub fn X509_getm_notAfter(x: *const ::X509) -> *mut ::ASN1_TIME; pub fn X509_getm_notAfter(x: *const ::X509) -> *mut ::ASN1_TIME;
pub fn X509_getm_notBefore(x: *const ::X509) -> *mut ::ASN1_TIME; pub fn X509_getm_notBefore(x: *const ::X509) -> *mut ::ASN1_TIME;
pub fn X509_get0_signature( pub fn X509_get0_signature(

View File

@ -55,6 +55,9 @@ pub const SSL_EXT_TLS1_3_CERTIFICATE: c_uint = 0x1000;
pub const SSL_EXT_TLS1_3_NEW_SESSION_TICKET: c_uint = 0x2000; pub const SSL_EXT_TLS1_3_NEW_SESSION_TICKET: c_uint = 0x2000;
pub const SSL_EXT_TLS1_3_CERTIFICATE_REQUEST: c_uint = 0x4000; pub const SSL_EXT_TLS1_3_CERTIFICATE_REQUEST: c_uint = 0x4000;
pub const SSL_READ_EARLY_DATA_ERROR: c_int = 0;
pub const SSL_READ_EARLY_DATA_SUCCESS: c_int = 1;
pub const SSL_READ_EARLY_DATA_FINISH: c_int = 2;
extern "C" { extern "C" {
pub fn SSL_CTX_set_keylog_callback(ctx: *mut ::SSL_CTX, cb: SSL_CTX_keylog_cb_func); pub fn SSL_CTX_set_keylog_callback(ctx: *mut ::SSL_CTX, cb: SSL_CTX_keylog_cb_func);
@ -82,4 +85,24 @@ extern "C" {
cookie_len: size_t cookie_len: size_t
) -> c_int> ) -> c_int>
); );
pub fn SSL_CTX_set_max_early_data(ctx: *mut ::SSL_CTX, max_early_data: u32) -> c_int;
pub fn SSL_CTX_get_max_early_data(ctx: *const ::SSL_CTX) -> u32;
pub fn SSL_set_max_early_data(ctx: *mut ::SSL, max_early_data: u32) -> c_int;
pub fn SSL_get_max_early_data(ctx: *const ::SSL) -> u32;
pub fn SSL_SESSION_set_max_early_data(ctx: *mut ::SSL_SESSION, max_early_data: u32) -> c_int;
pub fn SSL_SESSION_get_max_early_data(ctx: *const ::SSL_SESSION) -> u32;
pub fn SSL_export_keying_material_early(
s: *mut ::SSL,
out: *mut c_uchar,
olen: size_t,
label: *const c_char,
llen: size_t,
context: *const c_uchar,
contextlen: size_t,
) -> c_int;
pub fn SSL_write_early_data(s: *mut ::SSL, buf: *const c_void, num: size_t, written: *mut size_t) -> c_int;
pub fn SSL_read_early_data(s: *mut ::SSL, buf: *mut c_void, num: size_t, readbytes: *mut size_t) -> c_int;
} }

View File

@ -1,6 +1,6 @@
[package] [package]
name = "openssl" name = "openssl"
version = "0.10.7" version = "0.10.9"
authors = ["Steven Fackler <sfackler@gmail.com>"] authors = ["Steven Fackler <sfackler@gmail.com>"]
license = "Apache-2.0" license = "Apache-2.0"
description = "OpenSSL bindings" description = "OpenSSL bindings"
@ -18,10 +18,12 @@ v111 = []
[dependencies] [dependencies]
bitflags = "1.0" bitflags = "1.0"
cfg-if = "0.1"
foreign-types = "0.3.1" foreign-types = "0.3.1"
lazy_static = "1" lazy_static = "1"
libc = "0.2" libc = "0.2"
openssl-sys = { version = "0.9.30", path = "../openssl-sys" }
openssl-sys = { version = "0.9.32", path = "../openssl-sys" }
[dev-dependencies] [dev-dependencies]
tempdir = "0.3" tempdir = "0.3"

View File

@ -1,25 +1,6 @@
use std::env; use std::env;
fn main() { fn main() {
match env::var("DEP_OPENSSL_VERSION") {
Ok(ref v) if v == "101" => {
println!("cargo:rustc-cfg=ossl101");
println!("cargo:rustc-cfg=ossl10x");
}
Ok(ref v) if v == "102" => {
println!("cargo:rustc-cfg=ossl102");
println!("cargo:rustc-cfg=ossl10x");
}
Ok(ref v) if v == "110" => {
println!("cargo:rustc-cfg=ossl110");
}
Ok(ref v) if v == "111" => {
println!("cargo:rustc-cfg=ossl110");
println!("cargo:rustc-cfg=ossl111");
}
_ => panic!("Unable to detect OpenSSL version"),
}
if let Ok(_) = env::var("DEP_OPENSSL_LIBRESSL") { if let Ok(_) = env::var("DEP_OPENSSL_LIBRESSL") {
println!("cargo:rustc-cfg=libressl"); println!("cargo:rustc-cfg=libressl");
} }
@ -37,8 +18,32 @@ fn main() {
if let Ok(version) = env::var("DEP_OPENSSL_VERSION_NUMBER") { if let Ok(version) = env::var("DEP_OPENSSL_VERSION_NUMBER") {
let version = u64::from_str_radix(&version, 16).unwrap(); let version = u64::from_str_radix(&version, 16).unwrap();
if version >= 0x1_00_01_00_0 {
println!("cargo:rustc-cfg=ossl101");
}
if version >= 0x1_00_02_00_0 {
println!("cargo:rustc-cfg=ossl102");
}
if version >= 0x1_01_00_00_0 {
println!("cargo:rustc-cfg=ossl110");
}
if version >= 0x1_01_00_07_0 { if version >= 0x1_01_00_07_0 {
println!("cargo:rustc-cfg=ossl110g"); println!("cargo:rustc-cfg=ossl110g");
} }
if version >= 0x1_01_01_00_0 {
println!("cargo:rustc-cfg=ossl111");
}
}
if let Ok(version) = env::var("DEP_OPENSSL_LIBRESSL_VERSION_NUMBER") {
let version = u64::from_str_radix(&version, 16).unwrap();
if version >= 0x2_06_01_00_0 {
println!("cargo:rustc-cfg=libressl261");
}
if version >= 0x2_07_00_00_0 {
println!("cargo:rustc-cfg=libressl270");
}
} }
} }

View File

@ -32,12 +32,12 @@ use std::ptr;
use std::slice; use std::slice;
use std::str; use std::str;
use {cvt, cvt_p};
use bio::MemBio; use bio::MemBio;
use bn::BigNum; use bn::BigNum;
use error::ErrorStack; use error::ErrorStack;
use nid::Nid; use nid::Nid;
use string::OpensslString; use string::OpensslString;
use {cvt, cvt_p};
foreign_type_and_impl_send_sync! { foreign_type_and_impl_send_sync! {
type CType = ffi::ASN1_GENERALIZEDTIME; type CType = ffi::ASN1_GENERALIZEDTIME;
@ -162,7 +162,7 @@ impl Asn1StringRef {
/// ///
/// [`as_utf8`]: struct.Asn1String.html#method.as_utf8 /// [`as_utf8`]: struct.Asn1String.html#method.as_utf8
pub fn as_slice(&self) -> &[u8] { pub fn as_slice(&self) -> &[u8] {
unsafe { slice::from_raw_parts(ASN1_STRING_data(self.as_ptr()), self.len()) } unsafe { slice::from_raw_parts(ASN1_STRING_get0_data(self.as_ptr()), self.len()) }
} }
/// Return the length of the Asn1String (number of bytes) /// Return the length of the Asn1String (number of bytes)
@ -241,11 +241,11 @@ foreign_type_and_impl_send_sync! {
impl Asn1BitStringRef { impl Asn1BitStringRef {
/// Returns the Asn1BitString as a slice /// Returns the Asn1BitString as a slice
pub fn as_slice(&self) -> &[u8] { pub fn as_slice(&self) -> &[u8] {
unsafe { slice::from_raw_parts(ASN1_STRING_data(self.as_ptr() as *mut _), self.len()) } unsafe { slice::from_raw_parts(ASN1_STRING_get0_data(self.as_ptr() as *mut _), self.len()) }
} }
/// Length of Asn1BitString in number of bytes. /// Length of Asn1BitString in number of bytes.
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
unsafe { ffi::ASN1_STRING_length(self.as_ptr() as *mut _) as usize } unsafe { ffi::ASN1_STRING_length(self.as_ptr() as *const _) as usize }
} }
} }
@ -296,11 +296,13 @@ impl fmt::Display for Asn1ObjectRef {
} }
} }
#[cfg(any(ossl101, ossl102))] cfg_if! {
use ffi::ASN1_STRING_data; if #[cfg(ossl110)] {
use ffi::ASN1_STRING_get0_data;
#[cfg(ossl110)] } else {
#[allow(bad_style)] #[allow(bad_style)]
unsafe fn ASN1_STRING_data(s: *mut ffi::ASN1_STRING) -> *mut ::libc::c_uchar { unsafe fn ASN1_STRING_get0_data(s: *mut ffi::ASN1_STRING) -> *const ::libc::c_uchar {
ffi::ASN1_STRING_get0_data(s) as *mut _ ffi::ASN1_STRING_data(s)
}
}
} }

View File

@ -1,8 +1,8 @@
use ffi;
use libc::c_int;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::ptr; use std::ptr;
use std::slice; use std::slice;
use libc::c_int;
use ffi;
use cvt_p; use cvt_p;
use error::ErrorStack; use error::ErrorStack;
@ -68,11 +68,13 @@ impl MemBio {
} }
} }
#[cfg(not(ossl101))] cfg_if! {
use ffi::BIO_new_mem_buf; if #[cfg(ossl102)] {
use ffi::BIO_new_mem_buf;
#[cfg(ossl101)] } else {
#[allow(bad_style)] #[allow(bad_style)]
unsafe fn BIO_new_mem_buf(buf: *const ::libc::c_void, len: ::libc::c_int) -> *mut ffi::BIO { unsafe fn BIO_new_mem_buf(buf: *const ::libc::c_void, len: ::libc::c_int) -> *mut ffi::BIO {
ffi::BIO_new_mem_buf(buf as *mut _, len) ffi::BIO_new_mem_buf(buf as *mut _, len)
}
}
} }

View File

@ -30,28 +30,39 @@ use foreign_types::{ForeignType, ForeignTypeRef};
use libc::c_int; use libc::c_int;
use std::cmp::Ordering; use std::cmp::Ordering;
use std::ffi::CString; use std::ffi::CString;
use std::{fmt, ptr};
use std::ops::{Add, Deref, Div, Mul, Neg, Rem, Shl, Shr, Sub}; use std::ops::{Add, Deref, Div, Mul, Neg, Rem, Shl, Shr, Sub};
use std::{fmt, ptr};
use {cvt, cvt_n, cvt_p};
use asn1::Asn1Integer; use asn1::Asn1Integer;
use error::ErrorStack; use error::ErrorStack;
use string::OpensslString; use string::OpensslString;
use {cvt, cvt_n, cvt_p};
#[cfg(ossl10x)] cfg_if! {
use ffi::{get_rfc2409_prime_1024 as BN_get_rfc2409_prime_1024, if #[cfg(ossl110)] {
use ffi::{
BN_get_rfc2409_prime_1024, BN_get_rfc2409_prime_768, BN_get_rfc3526_prime_1536,
BN_get_rfc3526_prime_2048, BN_get_rfc3526_prime_3072, BN_get_rfc3526_prime_4096,
BN_get_rfc3526_prime_6144, BN_get_rfc3526_prime_8192, BN_is_negative,
};
} else {
use ffi::{
get_rfc2409_prime_1024 as BN_get_rfc2409_prime_1024,
get_rfc2409_prime_768 as BN_get_rfc2409_prime_768, get_rfc2409_prime_768 as BN_get_rfc2409_prime_768,
get_rfc3526_prime_1536 as BN_get_rfc3526_prime_1536, get_rfc3526_prime_1536 as BN_get_rfc3526_prime_1536,
get_rfc3526_prime_2048 as BN_get_rfc3526_prime_2048, get_rfc3526_prime_2048 as BN_get_rfc3526_prime_2048,
get_rfc3526_prime_3072 as BN_get_rfc3526_prime_3072, get_rfc3526_prime_3072 as BN_get_rfc3526_prime_3072,
get_rfc3526_prime_4096 as BN_get_rfc3526_prime_4096, get_rfc3526_prime_4096 as BN_get_rfc3526_prime_4096,
get_rfc3526_prime_6144 as BN_get_rfc3526_prime_6144, get_rfc3526_prime_6144 as BN_get_rfc3526_prime_6144,
get_rfc3526_prime_8192 as BN_get_rfc3526_prime_8192}; get_rfc3526_prime_8192 as BN_get_rfc3526_prime_8192,
};
#[cfg(ossl110)] #[allow(bad_style)]
use ffi::{BN_get_rfc2409_prime_1024, BN_get_rfc2409_prime_768, BN_get_rfc3526_prime_1536, unsafe fn BN_is_negative(bn: *const ffi::BIGNUM) -> c_int {
BN_get_rfc3526_prime_2048, BN_get_rfc3526_prime_3072, BN_get_rfc3526_prime_4096, (*bn).neg
BN_get_rfc3526_prime_6144, BN_get_rfc3526_prime_8192}; }
}
}
/// Options for the most significant bits of a randomly generated `BigNum`. /// Options for the most significant bits of a randomly generated `BigNum`.
pub struct MsbOption(c_int); pub struct MsbOption(c_int);
@ -361,17 +372,7 @@ impl BigNumRef {
/// Returns `true` if `self` is negative. /// Returns `true` if `self` is negative.
pub fn is_negative(&self) -> bool { pub fn is_negative(&self) -> bool {
self._is_negative() unsafe { BN_is_negative(self.as_ptr()) == 1 }
}
#[cfg(ossl10x)]
fn _is_negative(&self) -> bool {
unsafe { (*self.as_ptr()).neg == 1 }
}
#[cfg(ossl110)]
fn _is_negative(&self) -> bool {
unsafe { ffi::BN_is_negative(self.as_ptr()) == 1 }
} }
/// Returns the number of significant bits in `self`. /// Returns the number of significant bits in `self`.
@ -1218,7 +1219,7 @@ macro_rules! delegate {
$t::$m(self.deref(), oth.deref()) $t::$m(self.deref(), oth.deref())
} }
} }
} };
} }
impl<'a, 'b> Add<&'b BigNumRef> for &'a BigNumRef { impl<'a, 'b> Add<&'b BigNumRef> for &'a BigNumRef {

View File

@ -13,8 +13,8 @@ use bio::{MemBio, MemBioSlice};
use error::ErrorStack; use error::ErrorStack;
use libc::c_uint; use libc::c_uint;
use pkey::{HasPrivate, PKeyRef}; use pkey::{HasPrivate, PKeyRef};
use stack::Stack; use stack::StackRef;
use x509::X509; use x509::{X509, X509Ref};
use {cvt, cvt_p}; use {cvt, cvt_p};
bitflags! { bitflags! {
@ -130,30 +130,25 @@ impl CmsContentInfo {
/// OpenSSL documentation at [`CMS_sign`] /// OpenSSL documentation at [`CMS_sign`]
/// ///
/// [`CMS_sign`]: https://www.openssl.org/docs/manmaster/man3/CMS_sign.html /// [`CMS_sign`]: https://www.openssl.org/docs/manmaster/man3/CMS_sign.html
pub fn sign<T: HasPrivate>( pub fn sign<T>(
signcert: Option<&X509>, signcert: Option<&X509Ref>,
pkey: Option<&PKeyRef<T>>, pkey: Option<&PKeyRef<T>>,
certs: Option<&Stack<X509>>, certs: Option<&StackRef<X509>>,
data: Option<&[u8]>, data: Option<&[u8]>,
flags: CMSOptions, flags: CMSOptions,
) -> Result<CmsContentInfo, ErrorStack> { ) -> Result<CmsContentInfo, ErrorStack>
where
T: HasPrivate,
{
unsafe { unsafe {
let signcert = match signcert { let signcert = signcert.map_or(ptr::null_mut(), |p| p.as_ptr());
Some(cert) => cert.as_ptr(), let pkey = pkey.map_or(ptr::null_mut(), |p| p.as_ptr());
None => ptr::null_mut(), let data_bio = match data {
}; Some(data) => Some(MemBioSlice::new(data)?),
let pkey = match pkey { None => None,
Some(pkey) => pkey.as_ptr(),
None => ptr::null_mut(),
};
let data_bio_ptr = match data {
Some(data) => MemBioSlice::new(data)?.as_ptr(),
None => ptr::null_mut(),
};
let certs = match certs {
Some(certs) => certs.as_ptr(),
None => ptr::null_mut(),
}; };
let data_bio_ptr = data_bio.as_ref().map_or(ptr::null_mut(), |p| p.as_ptr());
let certs = certs.map_or(ptr::null_mut(), |p| p.as_ptr());
let cms = cvt_p(ffi::CMS_sign( let cms = cvt_p(ffi::CMS_sign(
signcert, signcert,

View File

@ -4,9 +4,9 @@ use foreign_types::{ForeignType, ForeignTypeRef};
use std::mem; use std::mem;
use std::ptr; use std::ptr;
use {cvt, cvt_p};
use bn::BigNum; use bn::BigNum;
use pkey::{HasParams, Params}; use pkey::{HasParams, Params};
use {cvt, cvt_p};
generic_foreign_type_and_impl_send_sync! { generic_foreign_type_and_impl_send_sync! {
type CType = ffi::DH; type CType = ffi::DH;
@ -48,12 +48,7 @@ impl Dh<Params> {
pub fn from_params(p: BigNum, g: BigNum, q: BigNum) -> Result<Dh<Params>, ErrorStack> { pub fn from_params(p: BigNum, g: BigNum, q: BigNum) -> Result<Dh<Params>, ErrorStack> {
unsafe { unsafe {
let dh = Dh::from_ptr(cvt_p(ffi::DH_new())?); let dh = Dh::from_ptr(cvt_p(ffi::DH_new())?);
cvt(compat::DH_set0_pqg( cvt(DH_set0_pqg(dh.0, p.as_ptr(), q.as_ptr(), g.as_ptr()))?;
dh.0,
p.as_ptr(),
q.as_ptr(),
g.as_ptr(),
))?;
mem::forget((p, g, q)); mem::forget((p, g, q));
Ok(dh) Ok(dh)
} }
@ -111,34 +106,29 @@ impl Dh<Params> {
} }
} }
#[cfg(ossl110)] cfg_if! {
mod compat { if #[cfg(ossl110)] {
pub use ffi::DH_set0_pqg; use ffi::DH_set0_pqg;
} } else {
#[allow(bad_style)]
#[cfg(ossl10x)] unsafe fn DH_set0_pqg(
#[allow(bad_style)]
mod compat {
use ffi;
use libc::c_int;
pub unsafe fn DH_set0_pqg(
dh: *mut ffi::DH, dh: *mut ffi::DH,
p: *mut ffi::BIGNUM, p: *mut ffi::BIGNUM,
q: *mut ffi::BIGNUM, q: *mut ffi::BIGNUM,
g: *mut ffi::BIGNUM, g: *mut ffi::BIGNUM,
) -> c_int { ) -> ::libc::c_int {
(*dh).p = p; (*dh).p = p;
(*dh).q = q; (*dh).q = q;
(*dh).g = g; (*dh).g = g;
1 1
} }
}
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use dh::Dh;
use bn::BigNum; use bn::BigNum;
use dh::Dh;
use ssl::{SslContext, SslMethod}; use ssl::{SslContext, SslMethod};
#[test] #[test]

View File

@ -11,10 +11,10 @@ use libc::c_int;
use std::fmt; use std::fmt;
use std::ptr; use std::ptr;
use {cvt, cvt_p};
use bn::BigNumRef; use bn::BigNumRef;
use error::ErrorStack; use error::ErrorStack;
use pkey::{HasParams, HasPublic, Private, Public}; use pkey::{HasParams, HasPublic, Private, Public};
use {cvt, cvt_p};
generic_foreign_type_and_impl_send_sync! { generic_foreign_type_and_impl_send_sync! {
type CType = ffi::DSA; type CType = ffi::DSA;
@ -101,7 +101,8 @@ where
/// Returns the DSA prime parameter of `self`. /// Returns the DSA prime parameter of `self`.
pub fn p(&self) -> &BigNumRef { pub fn p(&self) -> &BigNumRef {
unsafe { unsafe {
let p = compat::pqg(self.as_ptr())[0]; let mut p = ptr::null();
DSA_get0_pqg(self.as_ptr(), &mut p, ptr::null_mut(), ptr::null_mut());
BigNumRef::from_ptr(p as *mut _) BigNumRef::from_ptr(p as *mut _)
} }
} }
@ -109,7 +110,8 @@ where
/// Returns the DSA sub-prime parameter of `self`. /// Returns the DSA sub-prime parameter of `self`.
pub fn q(&self) -> &BigNumRef { pub fn q(&self) -> &BigNumRef {
unsafe { unsafe {
let q = compat::pqg(self.as_ptr())[1]; let mut q = ptr::null();
DSA_get0_pqg(self.as_ptr(), ptr::null_mut(), &mut q, ptr::null_mut());
BigNumRef::from_ptr(q as *mut _) BigNumRef::from_ptr(q as *mut _)
} }
} }
@ -117,7 +119,8 @@ where
/// Returns the DSA base parameter of `self`. /// Returns the DSA base parameter of `self`.
pub fn g(&self) -> &BigNumRef { pub fn g(&self) -> &BigNumRef {
unsafe { unsafe {
let g = compat::pqg(self.as_ptr())[2]; let mut g = ptr::null();
DSA_get0_pqg(self.as_ptr(), ptr::null_mut(), ptr::null_mut(), &mut g);
BigNumRef::from_ptr(g as *mut _) BigNumRef::from_ptr(g as *mut _)
} }
} }
@ -184,24 +187,27 @@ impl<T> fmt::Debug for Dsa<T> {
} }
} }
#[cfg(ossl110)] cfg_if! {
mod compat { if #[cfg(ossl110)] {
use std::ptr; use ffi::DSA_get0_pqg;
use ffi::{self, BIGNUM, DSA}; } else {
#[allow(bad_style)]
pub unsafe fn pqg(d: *const DSA) -> [*const BIGNUM; 3] { unsafe fn DSA_get0_pqg(
let (mut p, mut q, mut g) = (ptr::null(), ptr::null(), ptr::null()); d: *mut ffi::DSA,
ffi::DSA_get0_pqg(d, &mut p, &mut q, &mut g); p: *mut *const ffi::BIGNUM,
[p, q, g] q: *mut *const ffi::BIGNUM,
g: *mut *const ffi::BIGNUM)
{
if !p.is_null() {
*p = (*d).p;
}
if !q.is_null() {
*q = (*d).q;
}
if !g.is_null() {
*g = (*d).g;
}
} }
}
#[cfg(ossl10x)]
mod compat {
use ffi::{BIGNUM, DSA};
pub unsafe fn pqg(d: *const DSA) -> [*const BIGNUM; 3] {
[(*d).p, (*d).q, (*d).g]
} }
} }

View File

@ -33,14 +33,14 @@
//! ``` //! ```
use ffi; use ffi;
use foreign_types::{ForeignType, ForeignTypeRef}; use foreign_types::{ForeignType, ForeignTypeRef};
use std::ptr;
use libc::c_int; use libc::c_int;
use std::ptr;
use {cvt, cvt_n, cvt_p, init};
use bn::{BigNumContextRef, BigNumRef}; use bn::{BigNumContextRef, BigNumRef};
use error::ErrorStack; use error::ErrorStack;
use nid::Nid; use nid::Nid;
use pkey::{HasParams, HasPrivate, HasPublic, Params, Private, Public}; use pkey::{HasParams, HasPrivate, HasPublic, Params, Private, Public};
use {cvt, cvt_n, cvt_p, init};
/// Compressed or Uncompressed conversion /// Compressed or Uncompressed conversion
/// ///
@ -803,10 +803,10 @@ impl<T> Clone for EcKey<T> {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use bn::{BigNum, BigNumContext};
use nid::Nid;
use data_encoding::BASE64URL_NOPAD;
use super::*; use super::*;
use bn::{BigNum, BigNumContext};
use data_encoding::BASE64URL_NOPAD;
use nid::Nid;
#[test] #[test]
fn key_new_by_curve_name() { fn key_new_by_curve_name() {
@ -823,7 +823,7 @@ mod test {
fn dup() { fn dup() {
let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
let key = EcKey::generate(&group).unwrap(); let key = EcKey::generate(&group).unwrap();
key.clone(); drop(key.clone());
} }
#[test] #[test]
@ -862,7 +862,8 @@ mod test {
let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
let key = EcKey::generate(&group).unwrap(); let key = EcKey::generate(&group).unwrap();
let mut ctx = BigNumContext::new().unwrap(); let mut ctx = BigNumContext::new().unwrap();
let bytes = key.public_key() let bytes = key
.public_key()
.to_bytes(&group, PointConversionForm::COMPRESSED, &mut ctx) .to_bytes(&group, PointConversionForm::COMPRESSED, &mut ctx)
.unwrap(); .unwrap();
@ -877,7 +878,8 @@ mod test {
let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap(); let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
let key = EcKey::generate(&group).unwrap(); let key = EcKey::generate(&group).unwrap();
let dup_key = EcKey::from_private_components(&group, key.private_key(), key.public_key()).unwrap(); let dup_key =
EcKey::from_private_components(&group, key.private_key(), key.public_key()).unwrap();
let res = dup_key.check_key().unwrap(); let res = dup_key.check_key().unwrap();
assert!(res == ()); assert!(res == ());

View File

@ -3,12 +3,13 @@ use ffi;
use foreign_types::{ForeignType, ForeignTypeRef}; use foreign_types::{ForeignType, ForeignTypeRef};
use libc::c_int; use libc::c_int;
use std::mem; use std::mem;
use std::ptr;
use bn::{BigNum, BigNumRef}; use bn::{BigNum, BigNumRef};
use {cvt, cvt_n, cvt_p};
use ec::EcKeyRef; use ec::EcKeyRef;
use error::ErrorStack; use error::ErrorStack;
use pkey::{Private, Public}; use pkey::{Private, Public};
use {cvt_n, cvt_p};
foreign_type_and_impl_send_sync! { foreign_type_and_impl_send_sync! {
type CType = ffi::ECDSA_SIG; type CType = ffi::ECDSA_SIG;
@ -53,7 +54,7 @@ impl EcdsaSig {
pub fn from_private_components(r: BigNum, s: BigNum) -> Result<EcdsaSig, ErrorStack> { pub fn from_private_components(r: BigNum, s: BigNum) -> Result<EcdsaSig, ErrorStack> {
unsafe { unsafe {
let sig = cvt_p(ffi::ECDSA_SIG_new())?; let sig = cvt_p(ffi::ECDSA_SIG_new())?;
cvt(compat::set_numbers(sig, r.as_ptr(), s.as_ptr()))?; ECDSA_SIG_set0(sig, r.as_ptr(), s.as_ptr());
mem::forget((r, s)); mem::forget((r, s));
Ok(EcdsaSig::from_ptr(sig as *mut _)) Ok(EcdsaSig::from_ptr(sig as *mut _))
} }
@ -83,8 +84,9 @@ impl EcdsaSig {
/// [`ECDSA_SIG_get0`]: https://www.openssl.org/docs/man1.1.0/crypto/ECDSA_SIG_get0.html /// [`ECDSA_SIG_get0`]: https://www.openssl.org/docs/man1.1.0/crypto/ECDSA_SIG_get0.html
pub fn r(&self) -> &BigNumRef { pub fn r(&self) -> &BigNumRef {
unsafe { unsafe {
let xs = compat::get_numbers(self.as_ptr()); let mut r = ptr::null();
BigNumRef::from_ptr(xs[0] as *mut _) ECDSA_SIG_get0(self.as_ptr(), &mut r, ptr::null_mut());
BigNumRef::from_ptr(r as *mut _)
} }
} }
@ -95,53 +97,50 @@ impl EcdsaSig {
/// [`ECDSA_SIG_get0`]: https://www.openssl.org/docs/man1.1.0/crypto/ECDSA_SIG_get0.html /// [`ECDSA_SIG_get0`]: https://www.openssl.org/docs/man1.1.0/crypto/ECDSA_SIG_get0.html
pub fn s(&self) -> &BigNumRef { pub fn s(&self) -> &BigNumRef {
unsafe { unsafe {
let xs = compat::get_numbers(self.as_ptr()); let mut s = ptr::null();
BigNumRef::from_ptr(xs[1] as *mut _) ECDSA_SIG_get0(self.as_ptr(), ptr::null_mut(), &mut s);
BigNumRef::from_ptr(s as *mut _)
} }
} }
} }
#[cfg(ossl110)] cfg_if! {
mod compat { if #[cfg(ossl110)] {
use std::ptr; use ffi::{ECDSA_SIG_set0, ECDSA_SIG_get0};
} else {
use libc::c_int; #[allow(bad_style)]
use ffi::{self, BIGNUM, ECDSA_SIG}; unsafe fn ECDSA_SIG_set0(
sig: *mut ffi::ECDSA_SIG,
pub unsafe fn set_numbers(sig: *mut ECDSA_SIG, r: *mut BIGNUM, s: *mut BIGNUM) -> c_int { r: *mut ffi::BIGNUM,
ffi::ECDSA_SIG_set0(sig, r, s) s: *mut ffi::BIGNUM,
} ) -> c_int {
pub unsafe fn get_numbers(sig: *mut ECDSA_SIG) -> [*const BIGNUM; 2] {
let (mut r, mut s) = (ptr::null(), ptr::null());
ffi::ECDSA_SIG_get0(sig, &mut r, &mut s);
[r, s]
}
}
#[cfg(ossl10x)]
mod compat {
use libc::c_int;
use ffi::{BIGNUM, ECDSA_SIG};
pub unsafe fn set_numbers(sig: *mut ECDSA_SIG, r: *mut BIGNUM, s: *mut BIGNUM) -> c_int {
(*sig).r = r; (*sig).r = r;
(*sig).s = s; (*sig).s = s;
1 1
} }
pub unsafe fn get_numbers(sig: *mut ECDSA_SIG) -> [*const BIGNUM; 2] { #[allow(bad_style)]
[(*sig).r, (*sig).s] unsafe fn ECDSA_SIG_get0(
sig: *const ffi::ECDSA_SIG,
pr: *mut *const ffi::BIGNUM,
ps: *mut *const ffi::BIGNUM)
{
if !pr.is_null() {
(*pr) = (*sig).r;
}
if !ps.is_null() {
(*ps) = (*sig).s;
}
}
} }
} }
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use nid::Nid; use super::*;
use ec::EcGroup; use ec::EcGroup;
use ec::EcKey; use ec::EcKey;
use super::*; use nid::Nid;
#[cfg(not(osslconf = "OPENSSL_NO_EC2M"))] #[cfg(not(osslconf = "OPENSSL_NO_EC2M"))]
static CURVE_IDENTIFER: Nid = Nid::X9_62_PRIME192V1; static CURVE_IDENTIFER: Nid = Nid::X9_62_PRIME192V1;
@ -171,7 +170,8 @@ mod test {
assert!(verification); assert!(verification);
// Signature will not be verified using the incorrect data but the correct public key // Signature will not be verified using the incorrect data but the correct public key
let verification2 = res.verify(String::from("hello2").as_bytes(), &public_key) let verification2 = res
.verify(String::from("hello2").as_bytes(), &public_key)
.unwrap(); .unwrap();
assert!(verification2 == false); assert!(verification2 == false);

View File

@ -1,22 +1,44 @@
use std::io::prelude::*;
use std::io;
use std::ops::{Deref, DerefMut};
use std::fmt;
use ffi; use ffi;
use std::fmt;
use std::io;
use std::io::prelude::*;
use std::ops::{Deref, DerefMut};
#[cfg(ossl110)]
use ffi::{EVP_MD_CTX_free, EVP_MD_CTX_new};
#[cfg(any(ossl101, ossl102))]
use ffi::{EVP_MD_CTX_create as EVP_MD_CTX_new, EVP_MD_CTX_destroy as EVP_MD_CTX_free};
use {cvt, cvt_p};
use error::ErrorStack; use error::ErrorStack;
use nid::Nid;
use {cvt, cvt_p};
cfg_if! {
if #[cfg(ossl110)] {
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};
}
}
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct MessageDigest(*const ffi::EVP_MD); pub struct MessageDigest(*const ffi::EVP_MD);
impl MessageDigest { impl MessageDigest {
pub unsafe fn from_ptr(x: *const ffi::EVP_MD) -> Self { MessageDigest(x) } pub unsafe fn from_ptr(x: *const ffi::EVP_MD) -> Self {
MessageDigest(x)
}
/// Returns the `MessageDigest` corresponding to an `Nid`.
///
/// This corresponds to [`EVP_get_digestbynid`].
///
/// [`EVP_get_digestbynid`]: https://www.openssl.org/docs/man1.1.0/crypto/EVP_DigestInit.html
pub fn from_nid(type_: Nid) -> Option<MessageDigest> {
unsafe {
let ptr = ffi::EVP_get_digestbynid(type_.as_raw());
if ptr.is_null() {
None
} else {
Some(MessageDigest(ptr))
}
}
}
pub fn md5() -> MessageDigest { pub fn md5() -> MessageDigest {
unsafe { MessageDigest(ffi::EVP_md5()) } unsafe { MessageDigest(ffi::EVP_md5()) }
@ -229,8 +251,8 @@ impl Drop for Hasher {
/// store the digest data. /// store the digest data.
#[derive(Copy)] #[derive(Copy)]
pub struct DigestBytes { pub struct DigestBytes {
buf: [u8; ffi::EVP_MAX_MD_SIZE as usize], pub(crate) buf: [u8; ffi::EVP_MAX_MD_SIZE as usize],
len: usize, pub(crate) len: usize,
} }
impl Clone for DigestBytes { impl Clone for DigestBytes {
@ -382,12 +404,10 @@ mod tests {
#[test] #[test]
fn test_sha256() { fn test_sha256() {
let tests = [ let tests = [(
(
"616263", "616263",
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
), )];
];
for test in tests.iter() { for test in tests.iter() {
hash_test(MessageDigest::sha256(), test); hash_test(MessageDigest::sha256(), test);
@ -402,4 +422,12 @@ mod tests {
hash_test(MessageDigest::ripemd160(), test); hash_test(MessageDigest::ripemd160(), test);
} }
} }
#[test]
fn from_nid() {
assert_eq!(
MessageDigest::from_nid(Nid::SHA256).unwrap().as_ptr(),
MessageDigest::sha256().as_ptr()
);
}
} }

View File

@ -3,6 +3,8 @@
#[macro_use] #[macro_use]
extern crate bitflags; extern crate bitflags;
#[macro_use] #[macro_use]
extern crate cfg_if;
#[macro_use]
extern crate foreign_types; extern crate foreign_types;
#[macro_use] #[macro_use]
extern crate lazy_static; extern crate lazy_static;
@ -53,8 +55,8 @@ pub mod pkcs5;
pub mod pkey; pub mod pkey;
pub mod rand; pub mod rand;
pub mod rsa; pub mod rsa;
pub mod sign;
pub mod sha; pub mod sha;
pub mod sign;
pub mod ssl; pub mod ssl;
pub mod stack; pub mod stack;
pub mod string; pub mod string;

View File

@ -1,6 +1,23 @@
//! A collection of numerical identifiers for OpenSSL objects. //! A collection of numerical identifiers for OpenSSL objects.
use ffi; use ffi;
use libc::c_int; use libc::{c_char, c_int};
use std::ffi::CStr;
use std::str;
use cvt_p;
use error::ErrorStack;
/// The digest and public-key algorithms associated with a signature.
pub struct SignatureAlgorithms {
/// The signature's digest.
///
/// If the signature does not specify a digest, this will be `NID::UNDEF`.
pub digest: Nid,
/// The signature's public-key.
pub pkey: Nid,
}
/// A numerical identifier for an OpenSSL object. /// A numerical identifier for an OpenSSL object.
/// ///
@ -42,6 +59,46 @@ impl Nid {
self.0 self.0
} }
/// Returns the `Nid`s of the digest and public key algorithms associated with a signature ID.
///
/// This corresponds to `OBJ_find_sigid_algs`.
pub fn signature_algorithms(&self) -> Option<SignatureAlgorithms> {
unsafe {
let mut digest = 0;
let mut pkey = 0;
if ffi::OBJ_find_sigid_algs(self.0, &mut digest, &mut pkey) == 1 {
Some(SignatureAlgorithms {
digest: Nid(digest),
pkey: Nid(pkey),
})
} else {
None
}
}
}
/// Return the string representation of a `Nid` (long)
/// This corresponds to [`OBJ_nid2ln`]
///
/// [`OBJ_nid2ln`]: https://www.openssl.org/docs/man1.1.0/crypto/OBJ_nid2ln.html
pub fn long_name(&self) -> Result<&'static str, ErrorStack> {
unsafe {
cvt_p(ffi::OBJ_nid2ln(self.0) as *mut c_char)
.map(|nameptr| str::from_utf8(CStr::from_ptr(nameptr).to_bytes()).unwrap())
}
}
/// Return the string representation of a `Nid` (short)
/// This corresponds to [`OBJ_nid2sn`]
///
/// [`OBJ_nid2sn`]: https://www.openssl.org/docs/man1.1.0/crypto/OBJ_nid2sn.html
pub fn short_name(&self) -> Result<&'static str, ErrorStack> {
unsafe {
cvt_p(ffi::OBJ_nid2sn(self.0) as *mut c_char)
.map(|nameptr| str::from_utf8(CStr::from_ptr(nameptr).to_bytes()).unwrap())
}
}
pub const UNDEF: Nid = Nid(ffi::NID_undef); pub const UNDEF: Nid = Nid(ffi::NID_undef);
pub const ITU_T: Nid = Nid(ffi::NID_itu_t); pub const ITU_T: Nid = Nid(ffi::NID_itu_t);
pub const CCITT: Nid = Nid(ffi::NID_ccitt); pub const CCITT: Nid = Nid(ffi::NID_ccitt);
@ -991,3 +1048,73 @@ impl Nid {
pub const AES_192_CBC_HMAC_SHA1: Nid = Nid(ffi::NID_aes_192_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); pub const AES_256_CBC_HMAC_SHA1: Nid = Nid(ffi::NID_aes_256_cbc_hmac_sha1);
} }
#[cfg(test)]
mod test {
use super::Nid;
#[test]
fn signature_digest() {
let algs = Nid::SHA256WITHRSAENCRYPTION.signature_algorithms().unwrap();
assert_eq!(algs.digest, Nid::SHA256);
assert_eq!(algs.pkey, Nid::RSAENCRYPTION);
}
#[test]
fn test_long_name_conversion() {
let common_name = Nid::COMMONNAME;
let organizational_unit_name = Nid::ORGANIZATIONALUNITNAME;
let aes256_cbc_hmac_sha1 = Nid::AES_256_CBC_HMAC_SHA1;
let id_cmc_lrapopwitness = Nid::ID_CMC_LRAPOPWITNESS;
let ms_ctl_sign = Nid::MS_CTL_SIGN;
let undefined_nid = Nid::from_raw(118);
assert_eq!(common_name.long_name().unwrap(), "commonName");
assert_eq!(
organizational_unit_name.long_name().unwrap(),
"organizationalUnitName"
);
assert_eq!(
aes256_cbc_hmac_sha1.long_name().unwrap(),
"aes-256-cbc-hmac-sha1"
);
assert_eq!(
id_cmc_lrapopwitness.long_name().unwrap(),
"id-cmc-lraPOPWitness"
);
assert_eq!(
ms_ctl_sign.long_name().unwrap(),
"Microsoft Trust List Signing"
);
assert!(
undefined_nid.long_name().is_err(),
"undefined_nid should not return a valid value"
);
}
#[test]
fn test_short_name_conversion() {
let common_name = Nid::COMMONNAME;
let organizational_unit_name = Nid::ORGANIZATIONALUNITNAME;
let aes256_cbc_hmac_sha1 = Nid::AES_256_CBC_HMAC_SHA1;
let id_cmc_lrapopwitness = Nid::ID_CMC_LRAPOPWITNESS;
let ms_ctl_sign = Nid::MS_CTL_SIGN;
let undefined_nid = Nid::from_raw(118);
assert_eq!(common_name.short_name().unwrap(), "CN");
assert_eq!(organizational_unit_name.short_name().unwrap(), "OU");
assert_eq!(
aes256_cbc_hmac_sha1.short_name().unwrap(),
"AES-256-CBC-HMAC-SHA1"
);
assert_eq!(
id_cmc_lrapopwitness.short_name().unwrap(),
"id-cmc-lraPOPWitness"
);
assert_eq!(ms_ctl_sign.short_name().unwrap(), "msCTLSign");
assert!(
undefined_nid.short_name().is_err(),
"undefined_nid should not return a valid value"
);
}
}

View File

@ -3,15 +3,15 @@
use ffi; use ffi;
use foreign_types::{ForeignType, ForeignTypeRef}; use foreign_types::{ForeignType, ForeignTypeRef};
use libc::c_int; use libc::c_int;
use std::ptr;
use std::ffi::CString; use std::ffi::CString;
use std::ptr;
use {cvt, cvt_p};
use pkey::{HasPrivate, PKey, PKeyRef, Private};
use error::ErrorStack; use error::ErrorStack;
use x509::{X509, X509Ref};
use stack::Stack;
use nid::Nid; use nid::Nid;
use pkey::{HasPrivate, PKey, PKeyRef, Private};
use stack::Stack;
use x509::{X509, X509Ref};
use {cvt, cvt_p};
foreign_type_and_impl_send_sync! { foreign_type_and_impl_send_sync! {
type CType = ffi::PKCS12; type CType = ffi::PKCS12;
@ -172,7 +172,8 @@ impl Pkcs12Builder {
let friendly_name = CString::new(friendly_name).unwrap(); let friendly_name = CString::new(friendly_name).unwrap();
let pkey = pkey.as_ptr(); let pkey = pkey.as_ptr();
let cert = cert.as_ptr(); let cert = cert.as_ptr();
let ca = self.ca let ca = self
.ca
.as_ref() .as_ref()
.map(|ca| ca.as_ptr()) .map(|ca| ca.as_ptr())
.unwrap_or(ptr::null_mut()); .unwrap_or(ptr::null_mut());
@ -206,11 +207,11 @@ mod test {
use hex; use hex;
use asn1::Asn1Time; use asn1::Asn1Time;
use rsa::Rsa;
use pkey::PKey;
use nid::Nid; use nid::Nid;
use x509::{X509, X509Name}; use pkey::PKey;
use rsa::Rsa;
use x509::extension::KeyUsage; use x509::extension::KeyUsage;
use x509::{X509, X509Name};
use super::*; use super::*;
@ -221,14 +222,14 @@ mod test {
let parsed = pkcs12.parse("mypass").unwrap(); let parsed = pkcs12.parse("mypass").unwrap();
assert_eq!( assert_eq!(
hex::encode(parsed.cert.fingerprint(MessageDigest::sha1()).unwrap()), hex::encode(parsed.cert.digest(MessageDigest::sha1()).unwrap()),
"59172d9313e84459bcff27f967e79e6e9217e584" "59172d9313e84459bcff27f967e79e6e9217e584"
); );
let chain = parsed.chain.unwrap(); let chain = parsed.chain.unwrap();
assert_eq!(chain.len(), 1); assert_eq!(chain.len(), 1);
assert_eq!( assert_eq!(
hex::encode(chain[0].fingerprint(MessageDigest::sha1()).unwrap()), hex::encode(chain[0].digest(MessageDigest::sha1()).unwrap()),
"c0cbdf7cdd03c9773e5468e1f6d2da7d5cbb1875" "c0cbdf7cdd03c9773e5468e1f6d2da7d5cbb1875"
); );
} }
@ -279,8 +280,8 @@ mod test {
let parsed = pkcs12.parse("mypass").unwrap(); let parsed = pkcs12.parse("mypass").unwrap();
assert_eq!( assert_eq!(
parsed.cert.fingerprint(MessageDigest::sha1()).unwrap(), &*parsed.cert.digest(MessageDigest::sha1()).unwrap(),
cert.fingerprint(MessageDigest::sha1()).unwrap() &*cert.digest(MessageDigest::sha1()).unwrap()
); );
assert!(parsed.pkey.public_eq(&pkey)); assert!(parsed.pkey.public_eq(&pkey));
} }

View File

@ -189,7 +189,8 @@ where
/// [`RSA_get0_key`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_get0_key.html /// [`RSA_get0_key`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_get0_key.html
pub fn d(&self) -> &BigNumRef { pub fn d(&self) -> &BigNumRef {
unsafe { unsafe {
let d = compat::key(self.as_ptr())[2]; let mut d = ptr::null();
RSA_get0_key(self.as_ptr(), ptr::null_mut(), ptr::null_mut(), &mut d);
BigNumRef::from_ptr(d as *mut _) BigNumRef::from_ptr(d as *mut _)
} }
} }
@ -201,7 +202,8 @@ where
/// [`RSA_get0_factors`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_get0_key.html /// [`RSA_get0_factors`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_get0_key.html
pub fn p(&self) -> Option<&BigNumRef> { pub fn p(&self) -> Option<&BigNumRef> {
unsafe { unsafe {
let p = compat::factors(self.as_ptr())[0]; let mut p = ptr::null();
RSA_get0_factors(self.as_ptr(), &mut p, ptr::null_mut());
if p.is_null() { if p.is_null() {
None None
} else { } else {
@ -217,7 +219,8 @@ where
/// [`RSA_get0_factors`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_get0_key.html /// [`RSA_get0_factors`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_get0_key.html
pub fn q(&self) -> Option<&BigNumRef> { pub fn q(&self) -> Option<&BigNumRef> {
unsafe { unsafe {
let q = compat::factors(self.as_ptr())[1]; let mut q = ptr::null();
RSA_get0_factors(self.as_ptr(), ptr::null_mut(), &mut q);
if q.is_null() { if q.is_null() {
None None
} else { } else {
@ -233,7 +236,8 @@ where
/// [`RSA_get0_crt_params`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_get0_key.html /// [`RSA_get0_crt_params`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_get0_key.html
pub fn dmp1(&self) -> Option<&BigNumRef> { pub fn dmp1(&self) -> Option<&BigNumRef> {
unsafe { unsafe {
let dp = compat::crt_params(self.as_ptr())[0]; let mut dp = ptr::null();
RSA_get0_crt_params(self.as_ptr(), &mut dp, ptr::null_mut(), ptr::null_mut());
if dp.is_null() { if dp.is_null() {
None None
} else { } else {
@ -249,7 +253,8 @@ where
/// [`RSA_get0_crt_params`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_get0_key.html /// [`RSA_get0_crt_params`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_get0_key.html
pub fn dmq1(&self) -> Option<&BigNumRef> { pub fn dmq1(&self) -> Option<&BigNumRef> {
unsafe { unsafe {
let dq = compat::crt_params(self.as_ptr())[1]; let mut dq = ptr::null();
RSA_get0_crt_params(self.as_ptr(), ptr::null_mut(), &mut dq, ptr::null_mut());
if dq.is_null() { if dq.is_null() {
None None
} else { } else {
@ -265,7 +270,8 @@ where
/// [`RSA_get0_crt_params`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_get0_key.html /// [`RSA_get0_crt_params`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_get0_key.html
pub fn iqmp(&self) -> Option<&BigNumRef> { pub fn iqmp(&self) -> Option<&BigNumRef> {
unsafe { unsafe {
let qi = compat::crt_params(self.as_ptr())[2]; let mut qi = ptr::null();
RSA_get0_crt_params(self.as_ptr(), ptr::null_mut(), ptr::null_mut(), &mut qi);
if qi.is_null() { if qi.is_null() {
None None
} else { } else {
@ -391,7 +397,8 @@ where
/// [`RSA_get0_key`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_get0_key.html /// [`RSA_get0_key`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_get0_key.html
pub fn n(&self) -> &BigNumRef { pub fn n(&self) -> &BigNumRef {
unsafe { unsafe {
let n = compat::key(self.as_ptr())[0]; let mut n = ptr::null();
RSA_get0_key(self.as_ptr(), &mut n, ptr::null_mut(), ptr::null_mut());
BigNumRef::from_ptr(n as *mut _) BigNumRef::from_ptr(n as *mut _)
} }
} }
@ -403,7 +410,8 @@ where
/// [`RSA_get0_key`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_get0_key.html /// [`RSA_get0_key`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_get0_key.html
pub fn e(&self) -> &BigNumRef { pub fn e(&self) -> &BigNumRef {
unsafe { unsafe {
let e = compat::key(self.as_ptr())[1]; let mut e = ptr::null();
RSA_get0_key(self.as_ptr(), ptr::null_mut(), &mut e, ptr::null_mut());
BigNumRef::from_ptr(e as *mut _) BigNumRef::from_ptr(e as *mut _)
} }
} }
@ -421,15 +429,10 @@ impl Rsa<Public> {
/// [`RSA_set0_key`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_set0_key.html /// [`RSA_set0_key`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_set0_key.html
pub fn from_public_components(n: BigNum, e: BigNum) -> Result<Rsa<Public>, ErrorStack> { pub fn from_public_components(n: BigNum, e: BigNum) -> Result<Rsa<Public>, ErrorStack> {
unsafe { unsafe {
let rsa = Rsa::from_ptr(cvt_p(ffi::RSA_new())?); let rsa = cvt_p(ffi::RSA_new())?;
cvt(compat::set_key( RSA_set0_key(rsa, n.as_ptr(), e.as_ptr(), ptr::null_mut());
rsa.0,
n.as_ptr(),
e.as_ptr(),
ptr::null_mut(),
))?;
mem::forget((n, e)); mem::forget((n, e));
Ok(rsa) Ok(Rsa::from_ptr(rsa))
} }
} }
@ -498,10 +501,12 @@ impl RsaPrivateKeyBuilder {
/// [`RSA_set0_key`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_set0_key.html /// [`RSA_set0_key`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_set0_key.html
pub fn new(n: BigNum, e: BigNum, d: BigNum) -> Result<RsaPrivateKeyBuilder, ErrorStack> { pub fn new(n: BigNum, e: BigNum, d: BigNum) -> Result<RsaPrivateKeyBuilder, ErrorStack> {
unsafe { unsafe {
let rsa = Rsa::from_ptr(cvt_p(ffi::RSA_new())?); let rsa = cvt_p(ffi::RSA_new())?;
cvt(compat::set_key(rsa.0, n.as_ptr(), e.as_ptr(), d.as_ptr()))?; RSA_set0_key(rsa, n.as_ptr(), e.as_ptr(), d.as_ptr());
mem::forget((n, e, d)); mem::forget((n, e, d));
Ok(RsaPrivateKeyBuilder { rsa }) Ok(RsaPrivateKeyBuilder {
rsa: Rsa::from_ptr(rsa),
})
} }
} }
@ -512,9 +517,10 @@ impl RsaPrivateKeyBuilder {
/// This correspond to [`RSA_set0_factors`]. /// This correspond to [`RSA_set0_factors`].
/// ///
/// [`RSA_set0_factors`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_set0_factors.html /// [`RSA_set0_factors`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_set0_factors.html
// FIXME should be infallible
pub fn set_factors(self, p: BigNum, q: BigNum) -> Result<RsaPrivateKeyBuilder, ErrorStack> { pub fn set_factors(self, p: BigNum, q: BigNum) -> Result<RsaPrivateKeyBuilder, ErrorStack> {
unsafe { unsafe {
cvt(compat::set_factors(self.rsa.0, p.as_ptr(), q.as_ptr()))?; RSA_set0_factors(self.rsa.as_ptr(), p.as_ptr(), q.as_ptr());
mem::forget((p, q)); mem::forget((p, q));
} }
Ok(self) Ok(self)
@ -528,6 +534,7 @@ impl RsaPrivateKeyBuilder {
/// This correspond to [`RSA_set0_crt_params`]. /// This correspond to [`RSA_set0_crt_params`].
/// ///
/// [`RSA_set0_crt_params`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_set0_crt_params.html /// [`RSA_set0_crt_params`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_set0_crt_params.html
// FIXME should be infallible
pub fn set_crt_params( pub fn set_crt_params(
self, self,
dmp1: BigNum, dmp1: BigNum,
@ -535,12 +542,12 @@ impl RsaPrivateKeyBuilder {
iqmp: BigNum, iqmp: BigNum,
) -> Result<RsaPrivateKeyBuilder, ErrorStack> { ) -> Result<RsaPrivateKeyBuilder, ErrorStack> {
unsafe { unsafe {
cvt(compat::set_crt_params( RSA_set0_crt_params(
self.rsa.0, self.rsa.as_ptr(),
dmp1.as_ptr(), dmp1.as_ptr(),
dmq1.as_ptr(), dmq1.as_ptr(),
iqmp.as_ptr(), iqmp.as_ptr(),
))?; );
mem::forget((dmp1, dmq1, iqmp)); mem::forget((dmp1, dmq1, iqmp));
} }
Ok(self) Ok(self)
@ -637,89 +644,99 @@ impl<T> fmt::Debug for Rsa<T> {
} }
} }
#[cfg(ossl110)] cfg_if! {
mod compat { if #[cfg(ossl110)] {
use std::ptr; use ffi::{
RSA_get0_key, RSA_get0_factors, RSA_get0_crt_params, RSA_set0_key, RSA_set0_factors,
use ffi::{self, BIGNUM, RSA}; RSA_set0_crt_params,
use libc::c_int; };
} else {
pub unsafe fn key(r: *const RSA) -> [*const BIGNUM; 3] { #[allow(bad_style)]
let (mut n, mut e, mut d) = (ptr::null(), ptr::null(), ptr::null()); unsafe fn RSA_get0_key(
ffi::RSA_get0_key(r, &mut n, &mut e, &mut d); r: *const ffi::RSA,
[n, e, d] n: *mut *const ffi::BIGNUM,
e: *mut *const ffi::BIGNUM,
d: *mut *const ffi::BIGNUM,
) {
if !n.is_null() {
*n = (*r).n;
}
if !e.is_null() {
*e = (*r).e;
}
if !d.is_null() {
*d = (*r).d;
}
} }
pub unsafe fn factors(r: *const RSA) -> [*const BIGNUM; 2] { #[allow(bad_style)]
let (mut p, mut q) = (ptr::null(), ptr::null()); unsafe fn RSA_get0_factors(
ffi::RSA_get0_factors(r, &mut p, &mut q); r: *const ffi::RSA,
[p, q] p: *mut *const ffi::BIGNUM,
q: *mut *const ffi::BIGNUM,
) {
if !p.is_null() {
*p = (*r).p;
}
if !q.is_null() {
*q = (*r).q;
}
} }
pub unsafe fn crt_params(r: *const RSA) -> [*const BIGNUM; 3] { #[allow(bad_style)]
let (mut dp, mut dq, mut qi) = (ptr::null(), ptr::null(), ptr::null()); unsafe fn RSA_get0_crt_params(
ffi::RSA_get0_crt_params(r, &mut dp, &mut dq, &mut qi); r: *const ffi::RSA,
[dp, dq, qi] dmp1: *mut *const ffi::BIGNUM,
dmq1: *mut *const ffi::BIGNUM,
iqmp: *mut *const ffi::BIGNUM,
) {
if !dmp1.is_null() {
*dmp1 = (*r).dmp1;
}
if !dmq1.is_null() {
*dmq1 = (*r).dmq1;
}
if !iqmp.is_null() {
*iqmp = (*r).iqmp;
}
} }
pub unsafe fn set_key(r: *mut RSA, n: *mut BIGNUM, e: *mut BIGNUM, d: *mut BIGNUM) -> c_int { #[allow(bad_style)]
ffi::RSA_set0_key(r, n, e, d) unsafe fn RSA_set0_key(
} r: *mut ffi::RSA,
n: *mut ffi::BIGNUM,
pub unsafe fn set_factors(r: *mut RSA, p: *mut BIGNUM, q: *mut BIGNUM) -> c_int { e: *mut ffi::BIGNUM,
ffi::RSA_set0_factors(r, p, q) d: *mut ffi::BIGNUM,
}
pub unsafe fn set_crt_params(
r: *mut RSA,
dmp1: *mut BIGNUM,
dmq1: *mut BIGNUM,
iqmp: *mut BIGNUM,
) -> c_int { ) -> c_int {
ffi::RSA_set0_crt_params(r, dmp1, dmq1, iqmp)
}
}
#[cfg(ossl10x)]
mod compat {
use ffi::{BIGNUM, RSA};
use libc::c_int;
pub unsafe fn key(r: *const RSA) -> [*const BIGNUM; 3] {
[(*r).n, (*r).e, (*r).d]
}
pub unsafe fn factors(r: *const RSA) -> [*const BIGNUM; 2] {
[(*r).p, (*r).q]
}
pub unsafe fn crt_params(r: *const RSA) -> [*const BIGNUM; 3] {
[(*r).dmp1, (*r).dmq1, (*r).iqmp]
}
pub unsafe fn set_key(r: *mut RSA, n: *mut BIGNUM, e: *mut BIGNUM, d: *mut BIGNUM) -> c_int {
(*r).n = n; (*r).n = n;
(*r).e = e; (*r).e = e;
(*r).d = d; (*r).d = d;
1 // TODO: is this right? should it be 0? what's success? 1
} }
pub unsafe fn set_factors(r: *mut RSA, p: *mut BIGNUM, q: *mut BIGNUM) -> c_int { #[allow(bad_style)]
unsafe fn RSA_set0_factors(
r: *mut ffi::RSA,
p: *mut ffi::BIGNUM,
q: *mut ffi::BIGNUM,
) -> c_int {
(*r).p = p; (*r).p = p;
(*r).q = q; (*r).q = q;
1 // TODO: is this right? should it be 0? what's success? 1
} }
pub unsafe fn set_crt_params( #[allow(bad_style)]
r: *mut RSA, unsafe fn RSA_set0_crt_params(
dmp1: *mut BIGNUM, r: *mut ffi::RSA,
dmq1: *mut BIGNUM, dmp1: *mut ffi::BIGNUM,
iqmp: *mut BIGNUM, dmq1: *mut ffi::BIGNUM,
iqmp: *mut ffi::BIGNUM,
) -> c_int { ) -> c_int {
(*r).dmp1 = dmp1; (*r).dmp1 = dmp1;
(*r).dmq1 = dmq1; (*r).dmq1 = dmq1;
(*r).iqmp = iqmp; (*r).iqmp = iqmp;
1 // TODO: is this right? should it be 0? what's success? 1
}
} }
} }
@ -751,7 +768,8 @@ mod test {
#[test] #[test]
fn test_to_password() { fn test_to_password() {
let key = Rsa::generate(2048).unwrap(); let key = Rsa::generate(2048).unwrap();
let pem = key.private_key_to_pem_passphrase(Cipher::aes_128_cbc(), b"foobar") let pem = key
.private_key_to_pem_passphrase(Cipher::aes_128_cbc(), b"foobar")
.unwrap(); .unwrap();
Rsa::private_key_from_pem_passphrase(&pem, b"foobar").unwrap(); Rsa::private_key_from_pem_passphrase(&pem, b"foobar").unwrap();
assert!(Rsa::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err()); assert!(Rsa::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err());
@ -791,7 +809,8 @@ mod test {
k0.private_encrypt(&msg, &mut emesg, Padding::PKCS1) k0.private_encrypt(&msg, &mut emesg, Padding::PKCS1)
.unwrap(); .unwrap();
let mut dmesg = vec![0; k1.size() as usize]; let mut dmesg = vec![0; k1.size() as usize];
let len = k1.public_decrypt(&emesg, &mut dmesg, Padding::PKCS1) let len = k1
.public_decrypt(&emesg, &mut dmesg, Padding::PKCS1)
.unwrap(); .unwrap();
assert_eq!(msg, &dmesg[..len]); assert_eq!(msg, &dmesg[..len]);
} }
@ -807,7 +826,8 @@ mod test {
let mut emesg = vec![0; k0.size() as usize]; let mut emesg = vec![0; k0.size() as usize];
k0.public_encrypt(&msg, &mut emesg, Padding::PKCS1).unwrap(); k0.public_encrypt(&msg, &mut emesg, Padding::PKCS1).unwrap();
let mut dmesg = vec![0; k1.size() as usize]; let mut dmesg = vec![0; k1.size() as usize];
let len = k1.private_decrypt(&emesg, &mut dmesg, Padding::PKCS1) let len = k1
.private_decrypt(&emesg, &mut dmesg, Padding::PKCS1)
.unwrap(); .unwrap();
assert_eq!(msg, &dmesg[..len]); assert_eq!(msg, &dmesg[..len]);
} }
@ -883,6 +903,6 @@ mod test {
#[test] #[test]
fn clone() { fn clone() {
let key = Rsa::generate(2048).unwrap(); let key = Rsa::generate(2048).unwrap();
key.clone(); drop(key.clone());
} }
} }

View File

@ -63,21 +63,24 @@
//! ``` //! ```
use ffi; use ffi;
use foreign_types::ForeignTypeRef; use foreign_types::ForeignTypeRef;
use libc::c_int;
use std::io::{self, Write}; use std::io::{self, Write};
use std::marker::PhantomData; use std::marker::PhantomData;
use std::ptr; use std::ptr;
use libc::c_int;
use {cvt, cvt_p}; use error::ErrorStack;
use hash::MessageDigest; use hash::MessageDigest;
use pkey::{HasPrivate, HasPublic, PKeyRef}; use pkey::{HasPrivate, HasPublic, PKeyRef};
use error::ErrorStack;
use rsa::Padding; use rsa::Padding;
use {cvt, cvt_p};
#[cfg(ossl110)] cfg_if! {
use ffi::{EVP_MD_CTX_free, EVP_MD_CTX_new}; if #[cfg(ossl110)] {
#[cfg(any(ossl101, ossl102))] use ffi::{EVP_MD_CTX_free, EVP_MD_CTX_new};
use ffi::{EVP_MD_CTX_create as EVP_MD_CTX_new, EVP_MD_CTX_destroy as EVP_MD_CTX_free}; } else {
use ffi::{EVP_MD_CTX_create as EVP_MD_CTX_new, EVP_MD_CTX_destroy as EVP_MD_CTX_free};
}
}
/// Salt lengths that must be used with `set_rsa_pss_saltlen`. /// Salt lengths that must be used with `set_rsa_pss_saltlen`.
pub struct RsaPssSaltlen(c_int); pub struct RsaPssSaltlen(c_int);
@ -459,7 +462,7 @@ impl<'a> Verifier<'a> {
pub fn verify(&self, signature: &[u8]) -> Result<bool, ErrorStack> { pub fn verify(&self, signature: &[u8]) -> Result<bool, ErrorStack> {
unsafe { unsafe {
let r = let r =
EVP_DigestVerifyFinal(self.md_ctx, signature.as_ptr() as *const _, signature.len()); EVP_DigestVerifyFinal(self.md_ctx, signature.as_ptr() as *mut _, signature.len());
match r { match r {
1 => Ok(true), 1 => Ok(true),
0 => { 0 => {
@ -501,12 +504,12 @@ mod test {
use hex::{self, FromHex}; use hex::{self, FromHex};
use std::iter; use std::iter;
use hash::MessageDigest;
use sign::{RsaPssSaltlen, Signer, Verifier};
use ec::{EcGroup, EcKey}; use ec::{EcGroup, EcKey};
use hash::MessageDigest;
use nid::Nid; use nid::Nid;
use rsa::{Padding, Rsa};
use pkey::PKey; use pkey::PKey;
use rsa::{Padding, Rsa};
use sign::{RsaPssSaltlen, Signer, Verifier};
const INPUT: &'static str = const INPUT: &'static str =
"65794a68624763694f694a53557a49314e694a392e65794a7063334d694f694a71623255694c41304b49434a6c\ "65794a68624763694f694a53557a49314e694a392e65794a7063334d694f694a71623255694c41304b49434a6c\
@ -673,7 +676,7 @@ mod test {
signer.update(data as &[u8]).unwrap(); signer.update(data as &[u8]).unwrap();
let expected = vec![ let expected = vec![
136, 101, 61, 167, 61, 30, 248, 234, 124, 166, 196, 157, 203, 52, 171, 19 136, 101, 61, 167, 61, 30, 248, 234, 124, 166, 196, 157, 203, 52, 171, 19,
]; ];
assert_eq!(signer.sign_to_vec().unwrap(), expected); assert_eq!(signer.sign_to_vec().unwrap(), expected);
} }

View File

@ -1,11 +1,13 @@
use ffi::{
self, BIO_clear_retry_flags, BIO_new, BIO_set_retry_read, BIO_set_retry_write, BIO,
BIO_CTRL_FLUSH,
};
use libc::{c_char, c_int, c_long, c_void, strlen}; use libc::{c_char, c_int, c_long, c_void, strlen};
use ffi::{BIO, BIO_CTRL_FLUSH, BIO_new, BIO_clear_retry_flags, BIO_set_retry_read,
BIO_set_retry_write};
use std::any::Any; use std::any::Any;
use std::io; use std::io;
use std::io::prelude::*; use std::io::prelude::*;
use std::mem; use std::mem;
use std::panic::{AssertUnwindSafe, catch_unwind}; use std::panic::{catch_unwind, AssertUnwindSafe};
use std::ptr; use std::ptr;
use std::slice; use std::slice;
@ -19,11 +21,11 @@ pub struct StreamState<S> {
} }
/// Safe wrapper for BIO_METHOD /// Safe wrapper for BIO_METHOD
pub struct BioMethod(compat::BIO_METHOD); pub struct BioMethod(BIO_METHOD);
impl BioMethod { impl BioMethod {
fn new<S: Read + Write>() -> BioMethod { fn new<S: Read + Write>() -> BioMethod {
BioMethod(compat::BIO_METHOD::new::<S>()) BioMethod(BIO_METHOD::new::<S>())
} }
} }
@ -41,8 +43,8 @@ pub fn new<S: Read + Write>(stream: S) -> Result<(*mut BIO, BioMethod), ErrorSta
unsafe { unsafe {
let bio = cvt_p(BIO_new(method.0.get()))?; let bio = cvt_p(BIO_new(method.0.get()))?;
compat::BIO_set_data(bio, Box::into_raw(state) as *mut _); BIO_set_data(bio, Box::into_raw(state) as *mut _);
compat::BIO_set_init(bio, 1); BIO_set_init(bio, 1);
return Ok((bio, method)); return Ok((bio, method));
} }
@ -59,7 +61,7 @@ pub unsafe fn take_panic<S>(bio: *mut BIO) -> Option<Box<Any + Send>> {
} }
pub unsafe fn get_ref<'a, S: 'a>(bio: *mut BIO) -> &'a S { pub unsafe fn get_ref<'a, S: 'a>(bio: *mut BIO) -> &'a S {
let state: &'a StreamState<S> = mem::transmute(compat::BIO_get_data(bio)); let state: &'a StreamState<S> = mem::transmute(BIO_get_data(bio));
&state.stream &state.stream
} }
@ -68,7 +70,7 @@ pub unsafe fn get_mut<'a, S: 'a>(bio: *mut BIO) -> &'a mut S {
} }
unsafe fn state<'a, S: 'a>(bio: *mut BIO) -> &'a mut StreamState<S> { unsafe fn state<'a, S: 'a>(bio: *mut BIO) -> &'a mut StreamState<S> {
&mut *(compat::BIO_get_data(bio) as *mut _) &mut *(BIO_get_data(bio) as *mut _)
} }
unsafe extern "C" fn bwrite<S: Write>(bio: *mut BIO, buf: *const c_char, len: c_int) -> c_int { unsafe extern "C" fn bwrite<S: Write>(bio: *mut BIO, buf: *const c_char, len: c_int) -> c_int {
@ -117,8 +119,7 @@ unsafe extern "C" fn bread<S: Read>(bio: *mut BIO, buf: *mut c_char, len: c_int)
fn retriable_error(err: &io::Error) -> bool { fn retriable_error(err: &io::Error) -> bool {
match err.kind() { match err.kind() {
io::ErrorKind::WouldBlock | io::ErrorKind::WouldBlock | io::ErrorKind::NotConnected => true,
io::ErrorKind::NotConnected => true,
_ => false, _ => false,
} }
} }
@ -153,10 +154,10 @@ unsafe extern "C" fn ctrl<S: Write>(
} }
unsafe extern "C" fn create(bio: *mut BIO) -> c_int { unsafe extern "C" fn create(bio: *mut BIO) -> c_int {
compat::BIO_set_init(bio, 0); BIO_set_init(bio, 0);
compat::BIO_set_num(bio, 0); BIO_set_num(bio, 0);
compat::BIO_set_data(bio, ptr::null_mut()); BIO_set_data(bio, ptr::null_mut());
compat::BIO_set_flags(bio, 0); BIO_set_flags(bio, 0);
1 1
} }
@ -165,44 +166,41 @@ unsafe extern "C" fn destroy<S>(bio: *mut BIO) -> c_int {
return 0; return 0;
} }
let data = compat::BIO_get_data(bio); let data = BIO_get_data(bio);
assert!(!data.is_null()); assert!(!data.is_null());
Box::<StreamState<S>>::from_raw(data as *mut _); Box::<StreamState<S>>::from_raw(data as *mut _);
compat::BIO_set_data(bio, ptr::null_mut()); BIO_set_data(bio, ptr::null_mut());
compat::BIO_set_init(bio, 0); BIO_set_init(bio, 0);
1 1
} }
#[cfg(ossl110)] cfg_if! {
#[allow(bad_style)] if #[cfg(ossl110)] {
mod compat { use ffi::{BIO_get_data, BIO_set_data, BIO_set_flags, BIO_set_init};
use std::io::{Read, Write};
use libc::c_int; #[allow(bad_style)]
use ffi; unsafe fn BIO_set_num(_bio: *mut ffi::BIO, _num: c_int) {}
pub use ffi::{BIO_set_init, BIO_set_flags, BIO_set_data, BIO_get_data};
pub unsafe fn BIO_set_num(_bio: *mut ffi::BIO, _num: c_int) {} #[allow(bad_style)]
struct BIO_METHOD(*mut ffi::BIO_METHOD);
pub struct BIO_METHOD(*mut ffi::BIO_METHOD);
impl BIO_METHOD { impl BIO_METHOD {
pub fn new<S: Read + Write>() -> BIO_METHOD { fn new<S: Read + Write>() -> BIO_METHOD {
unsafe { unsafe {
let ptr = ffi::BIO_meth_new(ffi::BIO_TYPE_NONE, b"rust\0".as_ptr() as *const _); let ptr = ffi::BIO_meth_new(ffi::BIO_TYPE_NONE, b"rust\0".as_ptr() as *const _);
assert!(!ptr.is_null()); assert!(!ptr.is_null());
let ret = BIO_METHOD(ptr); let ret = BIO_METHOD(ptr);
assert!(ffi::BIO_meth_set_write(ptr, super::bwrite::<S>) != 0); assert!(ffi::BIO_meth_set_write(ptr, bwrite::<S>) != 0);
assert!(ffi::BIO_meth_set_read(ptr, super::bread::<S>) != 0); assert!(ffi::BIO_meth_set_read(ptr, bread::<S>) != 0);
assert!(ffi::BIO_meth_set_puts(ptr, super::bputs::<S>) != 0); assert!(ffi::BIO_meth_set_puts(ptr, bputs::<S>) != 0);
assert!(ffi::BIO_meth_set_ctrl(ptr, super::ctrl::<S>) != 0); assert!(ffi::BIO_meth_set_ctrl(ptr, ctrl::<S>) != 0);
assert!(ffi::BIO_meth_set_create(ptr, super::create) != 0); assert!(ffi::BIO_meth_set_create(ptr, create) != 0);
assert!(ffi::BIO_meth_set_destroy(ptr, super::destroy::<S>) != 0); assert!(ffi::BIO_meth_set_destroy(ptr, destroy::<S>) != 0);
return ret; return ret;
} }
} }
pub fn get(&self) -> *mut ffi::BIO_METHOD { fn get(&self) -> *mut ffi::BIO_METHOD {
self.0 self.0
} }
} }
@ -214,37 +212,29 @@ mod compat {
} }
} }
} }
} } else {
#[allow(bad_style)]
#[cfg(ossl10x)] struct BIO_METHOD(*mut ffi::BIO_METHOD);
#[allow(bad_style)]
mod compat {
use std::io::{Read, Write};
use ffi;
use libc::{c_int, c_void};
pub struct BIO_METHOD(*mut ffi::BIO_METHOD);
impl BIO_METHOD { impl BIO_METHOD {
pub fn new<S: Read + Write>() -> BIO_METHOD { fn new<S: Read + Write>() -> BIO_METHOD {
let ptr = Box::new(ffi::BIO_METHOD { let ptr = Box::new(ffi::BIO_METHOD {
type_: ffi::BIO_TYPE_NONE, type_: ffi::BIO_TYPE_NONE,
name: b"rust\0".as_ptr() as *const _, name: b"rust\0".as_ptr() as *const _,
bwrite: Some(super::bwrite::<S>), bwrite: Some(bwrite::<S>),
bread: Some(super::bread::<S>), bread: Some(bread::<S>),
bputs: Some(super::bputs::<S>), bputs: Some(bputs::<S>),
bgets: None, bgets: None,
ctrl: Some(super::ctrl::<S>), ctrl: Some(ctrl::<S>),
create: Some(super::create), create: Some(create),
destroy: Some(super::destroy::<S>), destroy: Some(destroy::<S>),
callback_ctrl: None, callback_ctrl: None,
}); });
BIO_METHOD(Box::into_raw(ptr)) BIO_METHOD(Box::into_raw(ptr))
} }
pub fn get(&self) -> *mut ffi::BIO_METHOD { fn get(&self) -> *mut ffi::BIO_METHOD {
self.0 self.0
} }
} }
@ -257,23 +247,29 @@ mod compat {
} }
} }
pub unsafe fn BIO_set_init(bio: *mut ffi::BIO, init: c_int) { #[allow(bad_style)]
unsafe fn BIO_set_init(bio: *mut ffi::BIO, init: c_int) {
(*bio).init = init; (*bio).init = init;
} }
pub unsafe fn BIO_set_flags(bio: *mut ffi::BIO, flags: c_int) { #[allow(bad_style)]
unsafe fn BIO_set_flags(bio: *mut ffi::BIO, flags: c_int) {
(*bio).flags = flags; (*bio).flags = flags;
} }
pub unsafe fn BIO_get_data(bio: *mut ffi::BIO) -> *mut c_void { #[allow(bad_style)]
unsafe fn BIO_get_data(bio: *mut ffi::BIO) -> *mut c_void {
(*bio).ptr (*bio).ptr
} }
pub unsafe fn BIO_set_data(bio: *mut ffi::BIO, data: *mut c_void) { #[allow(bad_style)]
unsafe fn BIO_set_data(bio: *mut ffi::BIO, data: *mut c_void) {
(*bio).ptr = data; (*bio).ptr = data;
} }
pub unsafe fn BIO_set_num(bio: *mut ffi::BIO, num: c_int) { #[allow(bad_style)]
unsafe fn BIO_set_num(bio: *mut ffi::BIO, num: c_int) {
(*bio).num = num; (*bio).num = num;
} }
}
} }

View File

@ -1,9 +1,12 @@
use ffi; use ffi;
use foreign_types::ForeignType; use foreign_types::ForeignType;
use foreign_types::ForeignTypeRef; use foreign_types::ForeignTypeRef;
#[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
use libc::c_char;
#[cfg(ossl111)] #[cfg(ossl111)]
use libc::size_t; use libc::size_t;
use libc::{c_char, c_int, c_uchar, c_uint, c_void}; use libc::{c_int, c_uchar, c_uint, c_void};
#[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
use std::ffi::CStr; use std::ffi::CStr;
use std::mem; use std::mem;
use std::ptr; use std::ptr;
@ -13,11 +16,11 @@ use std::str;
use std::sync::Arc; use std::sync::Arc;
use dh::Dh; use dh::Dh;
#[cfg(any(ossl101, ossl102))] #[cfg(all(ossl101, not(ossl110)))]
use ec::EcKey; use ec::EcKey;
use error::ErrorStack; use error::ErrorStack;
use pkey::Params; use pkey::Params;
#[cfg(any(ossl102, ossl110))] #[cfg(any(ossl102, libressl261))]
use ssl::AlpnError; use ssl::AlpnError;
#[cfg(ossl111)] #[cfg(ossl111)]
use ssl::ExtensionContext; use ssl::ExtensionContext;
@ -37,7 +40,8 @@ where
// raw pointer shenanigans to break the borrow of ctx // raw pointer shenanigans to break the borrow of ctx
// the callback can't mess with its own ex_data slot so this is safe // the callback can't mess with its own ex_data slot so this is safe
let verify = ctx.ex_data(ssl_idx) let verify = ctx
.ex_data(ssl_idx)
.expect("BUG: store context missing ssl") .expect("BUG: store context missing ssl")
.ssl_context() .ssl_context()
.ex_data(verify_idx) .ex_data(verify_idx)
@ -66,7 +70,8 @@ where
let ssl = SslRef::from_ptr_mut(ssl); let ssl = SslRef::from_ptr_mut(ssl);
let callback_idx = SslContext::cached_ex_index::<F>(); let callback_idx = SslContext::cached_ex_index::<F>();
let callback = ssl.ssl_context() let callback = ssl
.ssl_context()
.ex_data(callback_idx) .ex_data(callback_idx)
.expect("BUG: psk callback missing") as *const F; .expect("BUG: psk callback missing") as *const F;
let hint = if hint != ptr::null() { let hint = if hint != ptr::null() {
@ -130,7 +135,8 @@ where
let ssl_idx = X509StoreContext::ssl_idx().expect("BUG: store context ssl index missing"); let ssl_idx = X509StoreContext::ssl_idx().expect("BUG: store context ssl index missing");
let callback_idx = Ssl::cached_ex_index::<Arc<F>>(); let callback_idx = Ssl::cached_ex_index::<Arc<F>>();
let callback = ctx.ex_data(ssl_idx) let callback = ctx
.ex_data(ssl_idx)
.expect("BUG: store context missing ssl") .expect("BUG: store context missing ssl")
.ex_data(callback_idx) .ex_data(callback_idx)
.expect("BUG: ssl verify callback missing") .expect("BUG: ssl verify callback missing")
@ -146,7 +152,8 @@ where
{ {
unsafe { unsafe {
let ssl = SslRef::from_ptr_mut(ssl); let ssl = SslRef::from_ptr_mut(ssl);
let callback = ssl.ssl_context() let callback = ssl
.ssl_context()
.ex_data(SslContext::cached_ex_index::<F>()) .ex_data(SslContext::cached_ex_index::<F>())
.expect("BUG: sni callback missing") as *const F; .expect("BUG: sni callback missing") as *const F;
let mut alert = SslAlert(*al); let mut alert = SslAlert(*al);
@ -160,7 +167,7 @@ where
} }
} }
#[cfg(any(ossl102, ossl110))] #[cfg(any(ossl102, libressl261))]
pub extern "C" fn raw_alpn_select<F>( pub extern "C" fn raw_alpn_select<F>(
ssl: *mut ffi::SSL, ssl: *mut ffi::SSL,
out: *mut *const c_uchar, out: *mut *const c_uchar,
@ -174,7 +181,8 @@ where
{ {
unsafe { unsafe {
let ssl = SslRef::from_ptr_mut(ssl); let ssl = SslRef::from_ptr_mut(ssl);
let callback = ssl.ssl_context() let callback = ssl
.ssl_context()
.ex_data(SslContext::cached_ex_index::<F>()) .ex_data(SslContext::cached_ex_index::<F>())
.expect("BUG: alpn callback missing") as *const F; .expect("BUG: alpn callback missing") as *const F;
let protos = slice::from_raw_parts(inbuf as *const u8, inlen as usize); let protos = slice::from_raw_parts(inbuf as *const u8, inlen as usize);
@ -199,7 +207,8 @@ where
F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send, F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
{ {
let ssl = SslRef::from_ptr_mut(ssl); let ssl = SslRef::from_ptr_mut(ssl);
let callback = ssl.ssl_context() let callback = ssl
.ssl_context()
.ex_data(SslContext::cached_ex_index::<F>()) .ex_data(SslContext::cached_ex_index::<F>())
.expect("BUG: tmp dh callback missing") as *const F; .expect("BUG: tmp dh callback missing") as *const F;
@ -216,7 +225,7 @@ where
} }
} }
#[cfg(any(ossl101, ossl102))] #[cfg(all(ossl101, not(ossl110)))]
pub unsafe extern "C" fn raw_tmp_ecdh<F>( pub unsafe extern "C" fn raw_tmp_ecdh<F>(
ssl: *mut ffi::SSL, ssl: *mut ffi::SSL,
is_export: c_int, is_export: c_int,
@ -226,7 +235,8 @@ where
F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send, F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send,
{ {
let ssl = SslRef::from_ptr_mut(ssl); let ssl = SslRef::from_ptr_mut(ssl);
let callback = ssl.ssl_context() let callback = ssl
.ssl_context()
.ex_data(SslContext::cached_ex_index::<F>()) .ex_data(SslContext::cached_ex_index::<F>())
.expect("BUG: tmp ecdh callback missing") as *const F; .expect("BUG: tmp ecdh callback missing") as *const F;
@ -252,7 +262,8 @@ where
F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send, F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
{ {
let ssl = SslRef::from_ptr_mut(ssl); let ssl = SslRef::from_ptr_mut(ssl);
let callback = ssl.ex_data(Ssl::cached_ex_index::<Arc<F>>()) let callback = ssl
.ex_data(Ssl::cached_ex_index::<Arc<F>>())
.expect("BUG: ssl tmp dh callback missing") .expect("BUG: ssl tmp dh callback missing")
.clone(); .clone();
@ -269,7 +280,7 @@ where
} }
} }
#[cfg(any(ossl101, ossl102))] #[cfg(all(ossl101, not(ossl110)))]
pub unsafe extern "C" fn raw_tmp_ecdh_ssl<F>( pub unsafe extern "C" fn raw_tmp_ecdh_ssl<F>(
ssl: *mut ffi::SSL, ssl: *mut ffi::SSL,
is_export: c_int, is_export: c_int,
@ -279,7 +290,8 @@ where
F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send, F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send,
{ {
let ssl = SslRef::from_ptr_mut(ssl); let ssl = SslRef::from_ptr_mut(ssl);
let callback = ssl.ex_data(Ssl::cached_ex_index::<Arc<F>>()) let callback = ssl
.ex_data(Ssl::cached_ex_index::<Arc<F>>())
.expect("BUG: ssl tmp ecdh callback missing") .expect("BUG: ssl tmp ecdh callback missing")
.clone(); .clone();
@ -301,7 +313,8 @@ where
F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send, F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
{ {
let ssl = SslRef::from_ptr_mut(ssl); let ssl = SslRef::from_ptr_mut(ssl);
let callback = ssl.ssl_context() let callback = ssl
.ssl_context()
.ex_data(SslContext::cached_ex_index::<F>()) .ex_data(SslContext::cached_ex_index::<F>())
.expect("BUG: ocsp callback missing") as *const F; .expect("BUG: ocsp callback missing") as *const F;
let ret = (*callback)(ssl); let ret = (*callback)(ssl);
@ -335,7 +348,8 @@ where
F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send, F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
{ {
let ssl = SslRef::from_ptr_mut(ssl); let ssl = SslRef::from_ptr_mut(ssl);
let callback = ssl.ssl_context() let callback = ssl
.ssl_context()
.ex_data(SslContext::cached_ex_index::<F>()) .ex_data(SslContext::cached_ex_index::<F>())
.expect("BUG: new session callback missing") as *const F; .expect("BUG: new session callback missing") as *const F;
let session = SslSession::from_ptr(session); let session = SslSession::from_ptr(session);
@ -353,7 +367,8 @@ pub unsafe extern "C" fn raw_remove_session<F>(
F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send, F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
{ {
let ctx = SslContextRef::from_ptr(ctx); let ctx = SslContextRef::from_ptr(ctx);
let callback = ctx.ex_data(SslContext::cached_ex_index::<F>()) let callback = ctx
.ex_data(SslContext::cached_ex_index::<F>())
.expect("BUG: remove session callback missing"); .expect("BUG: remove session callback missing");
let session = SslSessionRef::from_ptr(session); let session = SslSessionRef::from_ptr(session);
@ -375,7 +390,8 @@ where
F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send, F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send,
{ {
let ssl = SslRef::from_ptr_mut(ssl); let ssl = SslRef::from_ptr_mut(ssl);
let callback = ssl.ssl_context() let callback = ssl
.ssl_context()
.ex_data(SslContext::cached_ex_index::<F>()) .ex_data(SslContext::cached_ex_index::<F>())
.expect("BUG: get session callback missing") as *const F; .expect("BUG: get session callback missing") as *const F;
let data = slice::from_raw_parts(data as *const u8, len as usize); let data = slice::from_raw_parts(data as *const u8, len as usize);
@ -397,7 +413,8 @@ where
F: Fn(&SslRef, &str) + 'static + Sync + Send, F: Fn(&SslRef, &str) + 'static + Sync + Send,
{ {
let ssl = SslRef::from_ptr(ssl as *mut _); let ssl = SslRef::from_ptr(ssl as *mut _);
let callback = ssl.ssl_context() let callback = ssl
.ssl_context()
.ex_data(SslContext::cached_ex_index::<F>()) .ex_data(SslContext::cached_ex_index::<F>())
.expect("BUG: get session callback missing"); .expect("BUG: get session callback missing");
let line = CStr::from_ptr(line).to_bytes(); let line = CStr::from_ptr(line).to_bytes();
@ -416,7 +433,8 @@ where
F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send, F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
{ {
let ssl = SslRef::from_ptr_mut(ssl); let ssl = SslRef::from_ptr_mut(ssl);
let callback = ssl.ssl_context() let callback = ssl
.ssl_context()
.ex_data(SslContext::cached_ex_index::<F>()) .ex_data(SslContext::cached_ex_index::<F>())
.expect("BUG: stateless cookie generate callback missing") as *const F; .expect("BUG: stateless cookie generate callback missing") as *const F;
let slice = slice::from_raw_parts_mut(cookie as *mut u8, ffi::SSL_COOKIE_LENGTH as usize); let slice = slice::from_raw_parts_mut(cookie as *mut u8, ffi::SSL_COOKIE_LENGTH as usize);
@ -442,7 +460,8 @@ where
F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send, F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
{ {
let ssl = SslRef::from_ptr_mut(ssl); let ssl = SslRef::from_ptr_mut(ssl);
let callback = ssl.ssl_context() let callback = ssl
.ssl_context()
.ex_data(SslContext::cached_ex_index::<F>()) .ex_data(SslContext::cached_ex_index::<F>())
.expect("BUG: stateless cookie verify callback missing") as *const F; .expect("BUG: stateless cookie verify callback missing") as *const F;
let slice = slice::from_raw_parts(cookie as *const c_uchar as *const u8, cookie_len as usize); let slice = slice::from_raw_parts(cookie as *const c_uchar as *const u8, cookie_len as usize);
@ -459,7 +478,8 @@ where
{ {
unsafe { unsafe {
let ssl = SslRef::from_ptr_mut(ssl); let ssl = SslRef::from_ptr_mut(ssl);
let callback = ssl.ssl_context() let callback = ssl
.ssl_context()
.ex_data(SslContext::cached_ex_index::<F>()) .ex_data(SslContext::cached_ex_index::<F>())
.expect("BUG: cookie generate callback missing") as *const F; .expect("BUG: cookie generate callback missing") as *const F;
// We subtract 1 from DTLS1_COOKIE_LENGTH as the ostensible value, 256, is erroneous but retained for // We subtract 1 from DTLS1_COOKIE_LENGTH as the ostensible value, 256, is erroneous but retained for
@ -495,7 +515,8 @@ where
{ {
unsafe { unsafe {
let ssl = SslRef::from_ptr_mut(ssl); let ssl = SslRef::from_ptr_mut(ssl);
let callback = ssl.ssl_context() let callback = ssl
.ssl_context()
.ex_data(SslContext::cached_ex_index::<F>()) .ex_data(SslContext::cached_ex_index::<F>())
.expect("BUG: cookie verify callback missing") as *const F; .expect("BUG: cookie verify callback missing") as *const F;
let slice = let slice =
@ -528,7 +549,8 @@ where
{ {
unsafe { unsafe {
let ssl = SslRef::from_ptr_mut(ssl); let ssl = SslRef::from_ptr_mut(ssl);
let callback = ssl.ssl_context() let callback = ssl
.ssl_context()
.ex_data(SslContext::cached_ex_index::<F>()) .ex_data(SslContext::cached_ex_index::<F>())
.expect("BUG: custom ext add callback missing") as *const F; .expect("BUG: custom ext add callback missing") as *const F;
let ectx = ExtensionContext::from_bits_truncate(context); let ectx = ExtensionContext::from_bits_truncate(context);
@ -604,7 +626,8 @@ where
{ {
unsafe { unsafe {
let ssl = SslRef::from_ptr_mut(ssl); let ssl = SslRef::from_ptr_mut(ssl);
let callback = ssl.ssl_context() let callback = ssl
.ssl_context()
.ex_data(SslContext::cached_ex_index::<F>()) .ex_data(SslContext::cached_ex_index::<F>())
.expect("BUG: custom ext parse callback missing") as *const F; .expect("BUG: custom ext parse callback missing") as *const F;
let ectx = ExtensionContext::from_bits_truncate(context); let ectx = ExtensionContext::from_bits_truncate(context);

View File

@ -3,16 +3,22 @@ use std::ops::{Deref, DerefMut};
use dh::Dh; use dh::Dh;
use error::ErrorStack; use error::ErrorStack;
use ssl::{HandshakeError, Ssl, SslContext, SslContextBuilder, SslMethod, SslMode, SslOptions, use ssl::{
SslRef, SslStream, SslVerifyMode}; HandshakeError, Ssl, SslContext, SslContextBuilder, SslMethod, SslMode, SslOptions, SslRef,
SslStream, SslVerifyMode,
};
use version; use version;
fn ctx(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> { fn ctx(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
let mut ctx = SslContextBuilder::new(method)?; let mut ctx = SslContextBuilder::new(method)?;
let mut opts = SslOptions::ALL | SslOptions::NO_COMPRESSION | SslOptions::NO_SSLV2 let mut opts = SslOptions::ALL
| SslOptions::NO_SSLV3 | SslOptions::SINGLE_DH_USE | SslOptions::NO_COMPRESSION
| SslOptions::SINGLE_ECDH_USE | SslOptions::CIPHER_SERVER_PREFERENCE; | SslOptions::NO_SSLV2
| SslOptions::NO_SSLV3
| SslOptions::SINGLE_DH_USE
| SslOptions::SINGLE_ECDH_USE
| SslOptions::CIPHER_SERVER_PREFERENCE;
opts &= !SslOptions::DONT_INSERT_EMPTY_FRAGMENTS; opts &= !SslOptions::DONT_INSERT_EMPTY_FRAGMENTS;
ctx.set_options(opts); ctx.set_options(opts);
@ -23,7 +29,7 @@ fn ctx(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
// This is quite a useful optimization for saving memory, but historically // This is quite a useful optimization for saving memory, but historically
// caused CVEs in OpenSSL pre-1.0.1h, according to // caused CVEs in OpenSSL pre-1.0.1h, according to
// https://bugs.python.org/issue25672 // https://bugs.python.org/issue25672
if version::number() >= 0x1000108f { if version::number() >= 0x1_00_01_08_0 {
mode |= SslMode::RELEASE_BUFFERS; mode |= SslMode::RELEASE_BUFFERS;
} }
@ -277,37 +283,33 @@ impl DerefMut for SslAcceptorBuilder {
} }
} }
#[cfg(ossl101)] cfg_if! {
fn setup_curves(ctx: &mut SslContextBuilder) -> Result<(), ErrorStack> { if #[cfg(ossl110)] {
fn setup_curves(_: &mut SslContextBuilder) -> Result<(), ErrorStack> {
Ok(())
}
} else if #[cfg(any(ossl102, libressl))] {
fn setup_curves(ctx: &mut SslContextBuilder) -> Result<(), ErrorStack> {
ctx.set_ecdh_auto(true)
}
} else {
fn setup_curves(ctx: &mut SslContextBuilder) -> Result<(), ErrorStack> {
use ec::EcKey; use ec::EcKey;
use nid::Nid; use nid::Nid;
let curve = EcKey::from_curve_name(Nid::X9_62_PRIME256V1)?; let curve = EcKey::from_curve_name(Nid::X9_62_PRIME256V1)?;
ctx.set_tmp_ecdh(&curve) ctx.set_tmp_ecdh(&curve)
}
}
} }
#[cfg(ossl102)] cfg_if! {
fn setup_curves(ctx: &mut SslContextBuilder) -> Result<(), ErrorStack> { if #[cfg(any(ossl102, libressl261))] {
ctx.set_ecdh_auto(true) fn setup_verify(ctx: &mut SslContextBuilder) {
}
#[cfg(ossl110)]
fn setup_curves(_: &mut SslContextBuilder) -> Result<(), ErrorStack> {
Ok(())
}
#[cfg(any(ossl102, ossl110))]
fn setup_verify(ctx: &mut SslContextBuilder) {
ctx.set_verify(SslVerifyMode::PEER); ctx.set_verify(SslVerifyMode::PEER);
} }
#[cfg(ossl101)] fn setup_verify_hostname(ssl: &mut SslRef, domain: &str) -> Result<(), ErrorStack> {
fn setup_verify(ctx: &mut SslContextBuilder) {
ctx.set_verify_callback(SslVerifyMode::PEER, verify::verify_callback);
}
#[cfg(any(ossl102, ossl110))]
fn setup_verify_hostname(ssl: &mut Ssl, domain: &str) -> Result<(), ErrorStack> {
use x509::verify::X509CheckFlags; use x509::verify::X509CheckFlags;
let param = ssl.param_mut(); let param = ssl.param_mut();
@ -316,26 +318,30 @@ fn setup_verify_hostname(ssl: &mut Ssl, domain: &str) -> Result<(), ErrorStack>
Ok(ip) => param.set_ip(ip), Ok(ip) => param.set_ip(ip),
Err(_) => param.set_host(domain), Err(_) => param.set_host(domain),
} }
} }
} else {
fn setup_verify(ctx: &mut SslContextBuilder) {
ctx.set_verify_callback(SslVerifyMode::PEER, verify::verify_callback);
}
#[cfg(ossl101)] fn setup_verify_hostname(ssl: &mut Ssl, domain: &str) -> Result<(), ErrorStack> {
fn setup_verify_hostname(ssl: &mut Ssl, domain: &str) -> Result<(), ErrorStack> {
let domain = domain.to_string(); let domain = domain.to_string();
ssl.set_ex_data(*verify::HOSTNAME_IDX, domain); ssl.set_ex_data(*verify::HOSTNAME_IDX, domain);
Ok(()) Ok(())
} }
#[cfg(ossl101)] mod verify {
mod verify {
use std::net::IpAddr; use std::net::IpAddr;
use std::str; use std::str;
use ex_data::Index; use ex_data::Index;
use nid::Nid; use nid::Nid;
use x509::{GeneralName, X509NameRef, X509Ref, X509StoreContext, X509StoreContextRef,
X509VerifyResult};
use stack::Stack;
use ssl::Ssl; use ssl::Ssl;
use stack::Stack;
use x509::{
GeneralName, X509NameRef, X509Ref, X509StoreContext, X509StoreContextRef,
X509VerifyResult,
};
lazy_static! { lazy_static! {
pub static ref HOSTNAME_IDX: Index<Ssl, String> = Ssl::new_ex_index().unwrap(); pub static ref HOSTNAME_IDX: Index<Ssl, String> = Ssl::new_ex_index().unwrap();
@ -499,4 +505,6 @@ mod verify {
IpAddr::V6(ref addr) => actual == addr.octets(), IpAddr::V6(ref addr) => actual == addr.octets(),
} }
} }
}
}
} }

View File

@ -99,17 +99,18 @@ impl fmt::Display for Error {
Some(_) => fmt.write_str("a nonblocking read call would have blocked"), Some(_) => fmt.write_str("a nonblocking read call would have blocked"),
None => fmt.write_str("the operation should be retried"), None => fmt.write_str("the operation should be retried"),
}, },
ErrorCode::WANT_WRITE => match self.io_error() {
Some(_) => fmt.write_str("a nonblocking write call would have blocked"),
None => fmt.write_str("the operation should be retried"),
},
ErrorCode::SYSCALL => match self.io_error() { ErrorCode::SYSCALL => match self.io_error() {
Some(err) => write!(fmt, "the inner stream returned an error: {}", err), Some(err) => write!(fmt, "{}", err),
None => fmt.write_str("unexpected EOF"), None => fmt.write_str("unexpected EOF"),
}, },
ErrorCode::SSL => { ErrorCode::SSL => match self.ssl_error() {
fmt.write_str("OpenSSL error")?; Some(e) => write!(fmt, "{}", e),
if let Some(ref err) = self.ssl_error() { None => fmt.write_str("OpenSSL error"),
write!(fmt, ": {}", err)? },
}
Ok(())
}
ErrorCode(code) => write!(fmt, "unknown error code {}", code), ErrorCode(code) => write!(fmt, "unknown error code {}", code),
} }
} }

View File

@ -78,23 +78,24 @@ use std::str;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use dh::{Dh, DhRef}; use dh::{Dh, DhRef};
#[cfg(any(ossl101, ossl102))] #[cfg(all(ossl101, not(ossl110)))]
use ec::EcKey; use ec::EcKey;
use ec::EcKeyRef; use ec::EcKeyRef;
use error::ErrorStack; use error::ErrorStack;
use ex_data::Index; use ex_data::Index;
#[cfg(ossl111)] #[cfg(ossl111)]
use hash::MessageDigest; use hash::MessageDigest;
#[cfg(ossl110)]
use nid::Nid; use nid::Nid;
use pkey::{HasPrivate, PKeyRef, Params, Private}; use pkey::{HasPrivate, PKeyRef, Params, Private};
use ssl::bio::BioMethod; use ssl::bio::BioMethod;
use ssl::callbacks::*; use ssl::callbacks::*;
use ssl::error::InnerError; use ssl::error::InnerError;
use stack::{Stack, StackRef}; use stack::{Stack, StackRef};
#[cfg(any(ossl102, ossl110))] #[cfg(ossl102)]
use x509::store::X509Store; use x509::store::X509Store;
use x509::store::{X509StoreBuilderRef, X509StoreRef}; use x509::store::{X509StoreBuilderRef, X509StoreRef};
#[cfg(any(ossl102, ossl110))] #[cfg(any(ossl102, libressl261))]
use x509::verify::X509VerifyParamRef; use x509::verify::X509VerifyParamRef;
use x509::{X509, X509Name, X509Ref, X509StoreContextRef, X509VerifyResult}; use x509::{X509, X509Name, X509Ref, X509StoreContextRef, X509VerifyResult};
use {cvt, cvt_n, cvt_p, init}; use {cvt, cvt_n, cvt_p, init};
@ -284,7 +285,7 @@ impl SslMethod {
/// This corresponds to `TLS_method` on OpenSSL 1.1.0 and `SSLv23_method` /// This corresponds to `TLS_method` on OpenSSL 1.1.0 and `SSLv23_method`
/// on OpenSSL 1.0.x. /// on OpenSSL 1.0.x.
pub fn tls() -> SslMethod { pub fn tls() -> SslMethod {
SslMethod(compat::tls_method()) unsafe { SslMethod(TLS_method()) }
} }
/// Support all versions of the DTLS protocol. /// Support all versions of the DTLS protocol.
@ -292,7 +293,7 @@ impl SslMethod {
/// This corresponds to `DTLS_method` on OpenSSL 1.1.0 and `DTLSv1_method` /// This corresponds to `DTLS_method` on OpenSSL 1.1.0 and `DTLSv1_method`
/// on OpenSSL 1.0.x. /// on OpenSSL 1.0.x.
pub fn dtls() -> SslMethod { pub fn dtls() -> SslMethod {
SslMethod(compat::dtls_method()) unsafe { SslMethod(DTLS_method()) }
} }
/// Constructs an `SslMethod` from a pointer to the underlying OpenSSL value. /// Constructs an `SslMethod` from a pointer to the underlying OpenSSL value.
@ -506,12 +507,12 @@ impl SslAlert {
/// An error returned from an ALPN selection callback. /// An error returned from an ALPN selection callback.
/// ///
/// Requires OpenSSL 1.0.2 or newer. /// Requires OpenSSL 1.0.2 or LibreSSL 2.6.1 or newer.
#[cfg(any(ossl102, ossl110))] #[cfg(any(ossl102, libressl261))]
#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct AlpnError(c_int); pub struct AlpnError(c_int);
#[cfg(any(ossl102, ossl110))] #[cfg(any(ossl102, libressl261))]
impl AlpnError { impl AlpnError {
/// Terminate the handshake with a fatal alert. /// Terminate the handshake with a fatal alert.
/// ///
@ -767,7 +768,7 @@ impl SslContextBuilder {
/// Requires OpenSSL 1.0.1 or 1.0.2. /// Requires OpenSSL 1.0.1 or 1.0.2.
/// ///
/// This corresponds to `SSL_CTX_set_tmp_ecdh_callback`. /// This corresponds to `SSL_CTX_set_tmp_ecdh_callback`.
#[cfg(any(ossl101, ossl102))] #[cfg(all(ossl101, not(ossl110)))]
pub fn set_tmp_ecdh_callback<F>(&mut self, callback: F) pub fn set_tmp_ecdh_callback<F>(&mut self, callback: F)
where where
F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send, F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send,
@ -976,7 +977,7 @@ impl SslContextBuilder {
/// This corresponds to [`SSL_CTX_set_ecdh_auto`]. /// This corresponds to [`SSL_CTX_set_ecdh_auto`].
/// ///
/// [`SSL_CTX_set_ecdh_auto`]: https://www.openssl.org/docs/man1.0.2/ssl/SSL_CTX_set_ecdh_auto.html /// [`SSL_CTX_set_ecdh_auto`]: https://www.openssl.org/docs/man1.0.2/ssl/SSL_CTX_set_ecdh_auto.html
#[cfg(any(ossl102, libressl))] #[cfg(any(libressl, all(ossl102, not(ossl110))))]
pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> { pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
unsafe { cvt(ffi::SSL_CTX_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) } unsafe { cvt(ffi::SSL_CTX_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
} }
@ -992,7 +993,7 @@ impl SslContextBuilder {
/// ///
/// [`SSL_CTX_set_options`]: https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_options.html /// [`SSL_CTX_set_options`]: https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_options.html
pub fn set_options(&mut self, option: SslOptions) -> SslOptions { pub fn set_options(&mut self, option: SslOptions) -> SslOptions {
let bits = unsafe { compat::SSL_CTX_set_options(self.as_ptr(), option.bits()) }; let bits = unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) };
SslOptions { bits } SslOptions { bits }
} }
@ -1002,7 +1003,7 @@ impl SslContextBuilder {
/// ///
/// [`SSL_CTX_get_options`]: https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_options.html /// [`SSL_CTX_get_options`]: https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_options.html
pub fn options(&self) -> SslOptions { pub fn options(&self) -> SslOptions {
let bits = unsafe { compat::SSL_CTX_get_options(self.as_ptr()) }; let bits = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) };
SslOptions { bits } SslOptions { bits }
} }
@ -1012,7 +1013,7 @@ impl SslContextBuilder {
/// ///
/// [`SSL_CTX_clear_options`]: https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_options.html /// [`SSL_CTX_clear_options`]: https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_options.html
pub fn clear_options(&mut self, option: SslOptions) -> SslOptions { pub fn clear_options(&mut self, option: SslOptions) -> SslOptions {
let bits = unsafe { compat::SSL_CTX_clear_options(self.as_ptr(), option.bits()) }; let bits = unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) };
SslOptions { bits } SslOptions { bits }
} }
@ -1023,15 +1024,15 @@ impl SslContextBuilder {
/// ///
/// This corresponds to [`SSL_CTX_set_min_proto_version`]. /// This corresponds to [`SSL_CTX_set_min_proto_version`].
/// ///
/// Requires OpenSSL 1.1.0 or newer. /// Requires OpenSSL 1.1.0 or LibreSSL 2.6.1 or newer.
/// ///
/// [`SSL_CTX_set_min_proto_version`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_set_min_proto_version.html /// [`SSL_CTX_set_min_proto_version`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_set_min_proto_version.html
#[cfg(any(ossl110))] #[cfg(any(ossl110, libressl261))]
pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> { pub fn set_min_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
unsafe { unsafe {
cvt(ffi::SSL_CTX_set_min_proto_version( cvt(ffi::SSL_CTX_set_min_proto_version(
self.as_ptr(), self.as_ptr(),
version.map_or(0, |v| v.0), version.map_or(0, |v| v.0 as _),
)).map(|_| ()) )).map(|_| ())
} }
} }
@ -1043,15 +1044,15 @@ impl SslContextBuilder {
/// ///
/// This corresponds to [`SSL_CTX_set_max_proto_version`]. /// This corresponds to [`SSL_CTX_set_max_proto_version`].
/// ///
/// Requires OpenSSL 1.1.0 or newer. /// Requires OpenSSL 1.1.0 or or LibreSSL 2.6.1 or newer.
/// ///
/// [`SSL_CTX_set_max_proto_version`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_set_min_proto_version.html /// [`SSL_CTX_set_max_proto_version`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_set_min_proto_version.html
#[cfg(any(ossl110))] #[cfg(any(ossl110, libressl261))]
pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> { pub fn set_max_proto_version(&mut self, version: Option<SslVersion>) -> Result<(), ErrorStack> {
unsafe { unsafe {
cvt(ffi::SSL_CTX_set_max_proto_version( cvt(ffi::SSL_CTX_set_max_proto_version(
self.as_ptr(), self.as_ptr(),
version.map_or(0, |v| v.0), version.map_or(0, |v| v.0 as _),
)).map(|_| ()) )).map(|_| ())
} }
} }
@ -1063,10 +1064,10 @@ impl SslContextBuilder {
/// ///
/// This corresponds to [`SSL_CTX_get_min_proto_version`]. /// This corresponds to [`SSL_CTX_get_min_proto_version`].
/// ///
/// Requires OpenSSL 1.1.0g or newer. /// Requires OpenSSL 1.1.0g or LibreSSL 2.7.0 or newer.
/// ///
/// [`SSL_CTX_get_min_proto_version`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_set_min_proto_version.html /// [`SSL_CTX_get_min_proto_version`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_set_min_proto_version.html
#[cfg(any(ossl110g))] #[cfg(any(ossl110g, libressl270))]
pub fn min_proto_version(&mut self) -> Option<SslVersion> { pub fn min_proto_version(&mut self) -> Option<SslVersion> {
unsafe { unsafe {
let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr()); let r = ffi::SSL_CTX_get_min_proto_version(self.as_ptr());
@ -1085,10 +1086,10 @@ impl SslContextBuilder {
/// ///
/// This corresponds to [`SSL_CTX_get_max_proto_version`]. /// This corresponds to [`SSL_CTX_get_max_proto_version`].
/// ///
/// Requires OpenSSL 1.1.0g or newer. /// Requires OpenSSL 1.1.0g or LibreSSL 2.7.0 or newer.
/// ///
/// [`SSL_CTX_get_max_proto_version`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_set_min_proto_version.html /// [`SSL_CTX_get_max_proto_version`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_set_min_proto_version.html
#[cfg(any(ossl110g))] #[cfg(any(ossl110g, libressl270))]
pub fn max_proto_version(&mut self) -> Option<SslVersion> { pub fn max_proto_version(&mut self) -> Option<SslVersion> {
unsafe { unsafe {
let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr()); let r = ffi::SSL_CTX_get_max_proto_version(self.as_ptr());
@ -1109,10 +1110,10 @@ impl SslContextBuilder {
/// ///
/// This corresponds to [`SSL_CTX_set_alpn_protos`]. /// This corresponds to [`SSL_CTX_set_alpn_protos`].
/// ///
/// Requires OpenSSL 1.0.2 or newer. /// Requires OpenSSL 1.0.2 or LibreSSL 2.6.1 or newer.
/// ///
/// [`SSL_CTX_set_alpn_protos`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_CTX_set_alpn_protos.html /// [`SSL_CTX_set_alpn_protos`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_CTX_set_alpn_protos.html
#[cfg(any(ossl102, ossl110))] #[cfg(any(ossl102, libressl261))]
pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> { pub fn set_alpn_protos(&mut self, protocols: &[u8]) -> Result<(), ErrorStack> {
unsafe { unsafe {
assert!(protocols.len() <= c_uint::max_value() as usize); assert!(protocols.len() <= c_uint::max_value() as usize);
@ -1140,12 +1141,12 @@ impl SslContextBuilder {
/// ///
/// This corresponds to [`SSL_CTX_set_alpn_select_cb`]. /// This corresponds to [`SSL_CTX_set_alpn_select_cb`].
/// ///
/// Requires OpenSSL 1.0.2 or newer. /// Requires OpenSSL 1.0.2 or LibreSSL 2.6.1 or newer.
/// ///
/// [`SslContextBuilder::set_alpn_protos`]: struct.SslContextBuilder.html#method.set_alpn_protos /// [`SslContextBuilder::set_alpn_protos`]: struct.SslContextBuilder.html#method.set_alpn_protos
/// [`select_next_proto`]: fn.select_next_proto.html /// [`select_next_proto`]: fn.select_next_proto.html
/// [`SSL_CTX_set_alpn_select_cb`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_CTX_set_alpn_protos.html /// [`SSL_CTX_set_alpn_select_cb`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_CTX_set_alpn_protos.html
#[cfg(any(ossl102, ossl110))] #[cfg(any(ossl102, libressl261))]
pub fn set_alpn_select_callback<F>(&mut self, callback: F) pub fn set_alpn_select_callback<F>(&mut self, callback: F)
where where
F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send, F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
@ -1512,6 +1513,24 @@ impl SslContextBuilder {
} }
} }
/// Sets the maximum amount of early data that will be accepted on incoming connections.
///
/// Defaults to 0.
///
/// Requires OpenSSL 1.1.1 or newer.
///
/// This corresponds to [`SSL_CTX_set_max_early_data`].
///
/// [`SSL_CTX_set_max_early_data`]: https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_max_early_data.html
#[cfg(ossl111)]
pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
if unsafe { ffi::SSL_CTX_set_max_early_data(self.as_ptr(), bytes) } == 1 {
Ok(())
} else {
Err(ErrorStack::get())
}
}
/// Consumes the builder, returning a new `SslContext`. /// Consumes the builder, returning a new `SslContext`.
pub fn build(self) -> SslContext { pub fn build(self) -> SslContext {
self.0 self.0
@ -1537,7 +1556,7 @@ foreign_type_and_impl_send_sync! {
impl Clone for SslContext { impl Clone for SslContext {
fn clone(&self) -> Self { fn clone(&self) -> Self {
unsafe { unsafe {
compat::SSL_CTX_up_ref(self.as_ptr()); SSL_CTX_up_ref(self.as_ptr());
SslContext::from_ptr(self.as_ptr()) SslContext::from_ptr(self.as_ptr())
} }
} }
@ -1570,7 +1589,7 @@ impl SslContext {
{ {
unsafe { unsafe {
ffi::init(); ffi::init();
let idx = cvt_n(compat::get_new_idx(free_data_box::<T>))?; let idx = cvt_n(get_new_idx(free_data_box::<T>))?;
Ok(Index::from_raw(idx)) Ok(Index::from_raw(idx))
} }
} }
@ -1666,6 +1685,18 @@ impl SslContextRef {
} }
} }
} }
/// Gets the maximum amount of early data that will be accepted on incoming connections.
///
/// Requires OpenSSL 1.1.1 or newer.
///
/// This corresponds to [`SSL_CTX_get_max_early_data`].
///
/// [`SSL_CTX_get_max_early_data`]: https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_get_max_early_data.html
#[cfg(ossl111)]
pub fn max_early_data(&self) -> u32 {
unsafe { ffi::SSL_CTX_get_max_early_data(self.as_ptr()) }
}
} }
/// Information about the state of a cipher. /// Information about the state of a cipher.
@ -1814,7 +1845,7 @@ impl SslCipherRef {
} }
} }
foreign_type! { foreign_type_and_impl_send_sync! {
type CType = ffi::SSL_SESSION; type CType = ffi::SSL_SESSION;
fn drop = ffi::SSL_SESSION_free; fn drop = ffi::SSL_SESSION_free;
@ -1829,9 +1860,6 @@ foreign_type! {
pub struct SslSessionRef; pub struct SslSessionRef;
} }
unsafe impl Sync for SslSession {}
unsafe impl Send for SslSession {}
impl Clone for SslSession { impl Clone for SslSession {
fn clone(&self) -> SslSession { fn clone(&self) -> SslSession {
SslSessionRef::to_owned(self) SslSessionRef::to_owned(self)
@ -1856,7 +1884,7 @@ impl ToOwned for SslSessionRef {
fn to_owned(&self) -> SslSession { fn to_owned(&self) -> SslSession {
unsafe { unsafe {
compat::SSL_SESSION_up_ref(self.as_ptr()); SSL_SESSION_up_ref(self.as_ptr());
SslSession(self.as_ptr()) SslSession(self.as_ptr())
} }
} }
@ -1882,7 +1910,7 @@ impl SslSessionRef {
/// ///
/// [`SSL_SESSION_get_master_key`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_SESSION_get_master_key.html /// [`SSL_SESSION_get_master_key`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_SESSION_get_master_key.html
pub fn master_key_len(&self) -> usize { pub fn master_key_len(&self) -> usize {
unsafe { compat::SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) } unsafe { SSL_SESSION_get_master_key(self.as_ptr(), ptr::null_mut(), 0) }
} }
/// Copies the master key into the provided buffer. /// Copies the master key into the provided buffer.
@ -1893,7 +1921,19 @@ impl SslSessionRef {
/// ///
/// [`SSL_SESSION_get_master_key`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_SESSION_get_master_key.html /// [`SSL_SESSION_get_master_key`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_SESSION_get_master_key.html
pub fn master_key(&self, buf: &mut [u8]) -> usize { pub fn master_key(&self, buf: &mut [u8]) -> usize {
unsafe { compat::SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) } unsafe { SSL_SESSION_get_master_key(self.as_ptr(), buf.as_mut_ptr(), buf.len()) }
}
/// Gets the maximum amount of early data that can be sent on this session.
///
/// Requires OpenSSL 1.1.1 or newer.
///
/// This corresponds to [`SSL_SESSION_get_max_early_data`].
///
/// [`SSL_SESSION_get_max_early_data`]: https://www.openssl.org/docs/man1.1.1/man3/SSL_SESSION_get_max_early_data.html
#[cfg(ossl111)]
pub fn max_early_data(&self) -> u32 {
unsafe { ffi::SSL_SESSION_get_max_early_data(self.as_ptr()) }
} }
to_der! { to_der! {
@ -1907,7 +1947,7 @@ impl SslSessionRef {
} }
} }
foreign_type! { foreign_type_and_impl_send_sync! {
type CType = ffi::SSL; type CType = ffi::SSL;
fn drop = ffi::SSL_free; fn drop = ffi::SSL_free;
@ -1925,9 +1965,6 @@ foreign_type! {
pub struct SslRef; pub struct SslRef;
} }
unsafe impl Sync for Ssl {}
unsafe impl Send for Ssl {}
impl fmt::Debug for Ssl { impl fmt::Debug for Ssl {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&**self, fmt) fmt::Debug::fmt(&**self, fmt)
@ -1949,7 +1986,7 @@ impl Ssl {
{ {
unsafe { unsafe {
ffi::init(); ffi::init();
let idx = cvt_n(compat::get_new_ssl_idx(free_data_box::<T>))?; let idx = cvt_n(get_new_ssl_idx(free_data_box::<T>))?;
Ok(Index::from_raw(idx)) Ok(Index::from_raw(idx))
} }
} }
@ -2114,7 +2151,7 @@ impl SslRef {
/// This corresponds to `SSL_set_tmp_ecdh_callback`. /// This corresponds to `SSL_set_tmp_ecdh_callback`.
/// ///
/// [`SslContextBuilder::set_tmp_ecdh_callback`]: struct.SslContextBuilder.html#method.set_tmp_ecdh_callback /// [`SslContextBuilder::set_tmp_ecdh_callback`]: struct.SslContextBuilder.html#method.set_tmp_ecdh_callback
#[cfg(any(ossl101, ossl102))] #[cfg(any(all(ossl101, not(ossl110))))]
pub fn set_tmp_ecdh_callback<F>(&mut self, callback: F) pub fn set_tmp_ecdh_callback<F>(&mut self, callback: F)
where where
F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send, F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send,
@ -2134,7 +2171,7 @@ impl SslRef {
/// ///
/// [`SslContextBuilder::set_tmp_ecdh`]: struct.SslContextBuilder.html#method.set_tmp_ecdh /// [`SslContextBuilder::set_tmp_ecdh`]: struct.SslContextBuilder.html#method.set_tmp_ecdh
/// [`SSL_set_ecdh_auto`]: https://www.openssl.org/docs/man1.0.2/ssl/SSL_set_ecdh_auto.html /// [`SSL_set_ecdh_auto`]: https://www.openssl.org/docs/man1.0.2/ssl/SSL_set_ecdh_auto.html
#[cfg(ossl102)] #[cfg(all(ossl102, not(ossl110)))]
pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> { pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
unsafe { cvt(ffi::SSL_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) } unsafe { cvt(ffi::SSL_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) }
} }
@ -2234,6 +2271,30 @@ impl SslRef {
} }
} }
/// Returns the verified certificate chani of the peer, including the leaf certificate.
///
/// If verification was not successful (i.e. [`verify_result`] does not return
/// [`X509VerifyResult::OK`]), this chain may be incomplete or invalid.
///
/// Requires OpenSSL 1.1.0 or newer.
///
/// This corresponds to [`SSL_get0_verified_chain`].
///
/// [`verify_result`]: #method.verify_result
/// [`X509VerifyResult::OK`]: ../x509/struct.X509VerifyResult.html#associatedconstant.OK
/// [`SSL_get0_verified_chain`]: https://www.openssl.org/docs/man1.1.0/ssl/SSL_get0_verified_chain.html
#[cfg(ossl110)]
pub fn verified_chain(&self) -> Option<&StackRef<X509>> {
unsafe {
let ptr = ffi::SSL_get0_verified_chain(self.as_ptr());
if ptr.is_null() {
None
} else {
Some(StackRef::from_ptr(ptr))
}
}
}
/// Like [`SslContext::certificate`]. /// Like [`SslContext::certificate`].
/// ///
/// This corresponds to `SSL_get_certificate`. /// This corresponds to `SSL_get_certificate`.
@ -2306,12 +2367,12 @@ impl SslRef {
/// The protocol's name is returned is an opaque sequence of bytes. It is up to the client /// The protocol's name is returned is an opaque sequence of bytes. It is up to the client
/// to interpret it. /// to interpret it.
/// ///
/// Requires OpenSSL 1.0.2 or newer. /// Requires OpenSSL 1.0.2 or LibreSSL 2.6.1 or newer.
/// ///
/// This corresponds to [`SSL_get0_alpn_selected`]. /// This corresponds to [`SSL_get0_alpn_selected`].
/// ///
/// [`SSL_get0_alpn_selected`]: https://www.openssl.org/docs/manmaster/man3/SSL_get0_next_proto_negotiated.html /// [`SSL_get0_alpn_selected`]: https://www.openssl.org/docs/manmaster/man3/SSL_get0_next_proto_negotiated.html
#[cfg(any(ossl102, ossl110))] #[cfg(any(ossl102, libressl261))]
pub fn selected_alpn_protocol(&self) -> Option<&[u8]> { pub fn selected_alpn_protocol(&self) -> Option<&[u8]> {
unsafe { unsafe {
let mut data: *const c_uchar = ptr::null(); let mut data: *const c_uchar = ptr::null();
@ -2346,14 +2407,38 @@ impl SslRef {
/// ///
/// This corresponds to [`SSL_get_servername`]. /// This corresponds to [`SSL_get_servername`].
/// ///
/// # Note
///
/// While the SNI specification requires that servernames be valid domain names (and therefore
/// ASCII), OpenSSL does not enforce this restriction. If the servername provided by the client
/// is not valid UTF-8, this function will return `None`. The `servername_raw` method returns
/// the raw bytes and does not have this restriction.
///
/// [`SSL_get_servername`]: https://www.openssl.org/docs/manmaster/man3/SSL_get_servername.html /// [`SSL_get_servername`]: https://www.openssl.org/docs/manmaster/man3/SSL_get_servername.html
// FIXME maybe rethink in 0.11?
pub fn servername(&self, type_: NameType) -> Option<&str> { pub fn servername(&self, type_: NameType) -> Option<&str> {
self.servername_raw(type_)
.and_then(|b| str::from_utf8(b).ok())
}
/// Returns the servername sent by the client via Server Name Indication (SNI).
///
/// It is only useful on the server side.
///
/// This corresponds to [`SSL_get_servername`].
///
/// # Note
///
/// Unlike `servername`, this method does not require the name be valid UTF-8.
///
/// [`SSL_get_servername`]: https://www.openssl.org/docs/manmaster/man3/SSL_get_servername.html
pub fn servername_raw(&self, type_: NameType) -> Option<&[u8]> {
unsafe { unsafe {
let name = ffi::SSL_get_servername(self.as_ptr(), type_.0); let name = ffi::SSL_get_servername(self.as_ptr(), type_.0);
if name == ptr::null() { if name == ptr::null() {
None None
} else { } else {
Some(str::from_utf8(CStr::from_ptr(name as *const _).to_bytes()).unwrap()) Some(CStr::from_ptr(name as *const _).to_bytes())
} }
} }
} }
@ -2386,7 +2471,7 @@ impl SslRef {
/// This corresponds to [`SSL_get0_param`]. /// This corresponds to [`SSL_get0_param`].
/// ///
/// [`SSL_get0_param`]: https://www.openssl.org/docs/man1.0.2/ssl/SSL_get0_param.html /// [`SSL_get0_param`]: https://www.openssl.org/docs/man1.0.2/ssl/SSL_get0_param.html
#[cfg(any(ossl102, ossl110))] #[cfg(any(ossl102, libressl261))]
pub fn param_mut(&mut self) -> &mut X509VerifyParamRef { pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) } unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) }
} }
@ -2479,6 +2564,36 @@ impl SslRef {
} }
} }
/// Derives keying material for application use in accordance to RFC 5705.
///
/// This function is only usable with TLSv1.3, wherein there is no distinction between an empty context and no
/// context. Therefore, unlike `export_keying_material`, `context` must always be supplied.
///
/// Requires OpenSSL 1.1.1 or newer.
///
/// This corresponds to [`SSL_export_keying_material_early`].
///
/// [`SSL_export_keying_material_early`]: https://www.openssl.org/docs/manmaster/man3/SSL_export_keying_material_early.html
#[cfg(ossl111)]
pub fn export_keying_material_early(
&self,
out: &mut [u8],
label: &str,
context: &[u8],
) -> Result<(), ErrorStack> {
unsafe {
cvt(ffi::SSL_export_keying_material_early(
self.as_ptr(),
out.as_mut_ptr() as *mut c_uchar,
out.len(),
label.as_ptr() as *const c_char,
label.len(),
context.as_ptr() as *const c_uchar,
context.len(),
)).map(|_| ())
}
}
/// Sets the session to be used. /// Sets the session to be used.
/// ///
/// This should be called before the handshake to attempt to reuse a previously established /// This should be called before the handshake to attempt to reuse a previously established
@ -2564,7 +2679,7 @@ impl SslRef {
/// ///
/// [`SSL_is_server`]: https://www.openssl.org/docs/manmaster/man3/SSL_is_server.html /// [`SSL_is_server`]: https://www.openssl.org/docs/manmaster/man3/SSL_is_server.html
pub fn is_server(&self) -> bool { pub fn is_server(&self) -> bool {
unsafe { compat::SSL_is_server(self.as_ptr()) != 0 } unsafe { SSL_is_server(self.as_ptr()) != 0 }
} }
/// Sets the extra data at the specified index. /// Sets the extra data at the specified index.
@ -2617,6 +2732,57 @@ impl SslRef {
} }
} }
} }
/// Sets the maximum amount of early data that will be accepted on this connection.
///
/// Requires OpenSSL 1.1.1 or newer.
///
/// This corresponds to [`SSL_set_max_early_data`].
///
/// [`SSL_set_max_early_data`]: https://www.openssl.org/docs/man1.1.1/man3/SSL_set_max_early_data.html
#[cfg(ossl111)]
pub fn set_max_early_data(&mut self, bytes: u32) -> Result<(), ErrorStack> {
if unsafe { ffi::SSL_set_max_early_data(self.as_ptr(), bytes) } == 1 {
Ok(())
} else {
Err(ErrorStack::get())
}
}
/// Gets the maximum amount of early data that can be sent on this connection.
///
/// Requires OpenSSL 1.1.1 or newer.
///
/// This corresponds to [`SSL_get_max_early_data`].
///
/// [`SSL_get_max_early_data`]: https://www.openssl.org/docs/man1.1.1/man3/SSL_get_max_early_data.html
#[cfg(ossl111)]
pub fn max_early_data(&self) -> u32 {
unsafe { ffi::SSL_get_max_early_data(self.as_ptr()) }
}
/// Copies the contents of the last Finished message sent to the peer into the provided buffer.
///
/// The total size of the message is returned, so this can be used to determine the size of the
/// buffer required.
///
/// This corresponds to `SSL_get_finished`.
pub fn finished(&self, buf: &mut [u8]) -> usize {
unsafe { ffi::SSL_get_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len()) }
}
/// Copies the contents of the last Finished message received from the peer into the provided
/// buffer.
///
/// The total size of the message is returned, so this can be used to determine the size of the
/// buffer required.
///
/// This corresponds to `SSL_get_finished`.
pub fn peer_finished(&self, buf: &mut [u8]) -> usize {
unsafe {
ffi::SSL_get_peer_finished(self.as_ptr(), buf.as_mut_ptr() as *mut c_void, buf.len())
}
}
} }
/// An SSL stream midway through the handshake process. /// An SSL stream midway through the handshake process.
@ -2860,7 +3026,8 @@ impl<S: Read + Write> Read for SslStream<S> {
} }
Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {} Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
Err(e) => { Err(e) => {
return Err(e.into_io_error() return Err(e
.into_io_error()
.unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e))) .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)))
} }
} }
@ -2875,7 +3042,8 @@ impl<S: Read + Write> Write for SslStream<S> {
Ok(n) => return Ok(n), Ok(n) => return Ok(n),
Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {} Err(ref e) if e.code() == ErrorCode::WANT_READ && e.io_error().is_none() => {}
Err(e) => { Err(e) => {
return Err(e.into_io_error() return Err(e
.into_io_error()
.unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e))) .unwrap_or_else(|e| io::Error::new(io::ErrorKind::Other, e)))
} }
} }
@ -2927,6 +3095,24 @@ where
} }
} }
/// Configure as an outgoing stream from a client.
///
/// This corresponds to [`SSL_set_connect_state`].
///
/// [`SSL_set_connect_state`]: https://www.openssl.org/docs/manmaster/man3/SSL_set_connect_state.html
pub fn set_connect_state(&mut self) {
unsafe { ffi::SSL_set_connect_state(self.inner.ssl.as_ptr()) }
}
/// Configure as an incoming stream to a server.
///
/// This corresponds to [`SSL_set_accept_state`].
///
/// [`SSL_set_accept_state`]: https://www.openssl.org/docs/manmaster/man3/SSL_set_accept_state.html
pub fn set_accept_state(&mut self) {
unsafe { ffi::SSL_set_accept_state(self.inner.ssl.as_ptr()) }
}
/// See `Ssl::connect` /// See `Ssl::connect`
pub fn connect(self) -> Result<SslStream<S>, HandshakeError<S>> { pub fn connect(self) -> Result<SslStream<S>, HandshakeError<S>> {
let mut stream = self.inner; let mut stream = self.inner;
@ -2967,7 +3153,91 @@ where
} }
} }
// Future work: early IO methods /// Initiates the handshake.
///
/// This will fail if `set_accept_state` or `set_connect_state` was not called first.
///
/// This corresponds to [`SSL_do_handshake`].
///
/// [`SSL_do_handshake`]: https://www.openssl.org/docs/manmaster/man3/SSL_do_handshake.html
pub fn handshake(self) -> Result<SslStream<S>, HandshakeError<S>> {
let mut stream = self.inner;
let ret = unsafe { ffi::SSL_do_handshake(stream.ssl.as_ptr()) };
if ret > 0 {
Ok(stream)
} else {
let error = stream.make_error(ret);
match error.code() {
ErrorCode::WANT_READ | ErrorCode::WANT_WRITE => Err(HandshakeError::WouldBlock(
MidHandshakeSslStream { stream, error },
)),
_ => Err(HandshakeError::Failure(MidHandshakeSslStream {
stream,
error,
})),
}
}
}
/// Read application data transmitted by a client before handshake
/// completion.
///
/// Useful for reducing latency, but vulnerable to replay attacks. Call
/// `set_accept_state` first.
///
/// Returns `Ok(0)` if all early data has been read.
///
/// Requires OpenSSL 1.1.1 or newer.
///
/// This corresponds to [`SSL_read_early_data`].
///
/// [`SSL_read_early_data`]: https://www.openssl.org/docs/manmaster/man3/SSL_read_early_data.html
#[cfg(ossl111)]
pub fn read_early_data(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
let mut read = 0;
let ret = unsafe {
ffi::SSL_read_early_data(
self.inner.ssl.as_ptr(),
buf.as_ptr() as *mut c_void,
buf.len(),
&mut read,
)
};
match ret {
ffi::SSL_READ_EARLY_DATA_ERROR => Err(self.inner.make_error(ret)),
ffi::SSL_READ_EARLY_DATA_SUCCESS => Ok(read),
ffi::SSL_READ_EARLY_DATA_FINISH => Ok(0),
_ => unreachable!(),
}
}
/// Send data to the server without blocking on handshake completion.
///
/// Useful for reducing latency, but vulnerable to replay attacks. Call
/// `set_connect_state` first.
///
/// Requires OpenSSL 1.1.1 or newer.
///
/// This corresponds to [`SSL_write_early_data`].
///
/// [`SSL_write_early_data`]: https://www.openssl.org/docs/manmaster/man3/SSL_write_early_data.html
#[cfg(ossl111)]
pub fn write_early_data(&mut self, buf: &[u8]) -> Result<usize, Error> {
let mut written = 0;
let ret = unsafe {
ffi::SSL_write_early_data(
self.inner.ssl.as_ptr(),
buf.as_ptr() as *const c_void,
buf.len(),
&mut written,
)
};
if ret > 0 {
Ok(written as usize)
} else {
Err(self.inner.make_error(ret))
}
}
} }
impl<S> SslStreamBuilder<S> { impl<S> SslStreamBuilder<S> {
@ -3008,16 +3278,11 @@ pub enum ShutdownResult {
Received, Received,
} }
#[cfg(ossl110)] cfg_if! {
mod compat { if #[cfg(ossl110)] {
use std::ptr; use ffi::{
SSL_CTX_up_ref,
use ffi; SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server, TLS_method, DTLS_method,
use libc::c_int;
pub use ffi::{
SSL_CTX_clear_options, SSL_CTX_get_options, SSL_CTX_set_options, SSL_CTX_up_ref,
SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server,
}; };
pub unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int { pub unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
@ -3041,45 +3306,8 @@ mod compat {
Some(f), Some(f),
) )
} }
} else {
pub fn tls_method() -> *const ffi::SSL_METHOD { use ffi::{SSLv23_method as TLS_method, DTLSv1_method as DTLS_method};
unsafe { ffi::TLS_method() }
}
pub fn dtls_method() -> *const ffi::SSL_METHOD {
unsafe { ffi::DTLS_method() }
}
}
#[cfg(ossl10x)]
#[allow(bad_style)]
mod compat {
use std::ptr;
use ffi;
use libc::{self, c_int, c_long, c_uchar, c_ulong, size_t};
pub unsafe fn SSL_CTX_get_options(ctx: *const ffi::SSL_CTX) -> c_ulong {
ffi::SSL_CTX_ctrl(ctx as *mut _, ffi::SSL_CTRL_OPTIONS, 0, ptr::null_mut()) as c_ulong
}
pub unsafe fn SSL_CTX_set_options(ctx: *const ffi::SSL_CTX, op: c_ulong) -> c_ulong {
ffi::SSL_CTX_ctrl(
ctx as *mut _,
ffi::SSL_CTRL_OPTIONS,
op as c_long,
ptr::null_mut(),
) as c_ulong
}
pub unsafe fn SSL_CTX_clear_options(ctx: *const ffi::SSL_CTX, op: c_ulong) -> c_ulong {
ffi::SSL_CTX_ctrl(
ctx as *mut _,
ffi::SSL_CTRL_CLEAR_OPTIONS,
op as c_long,
ptr::null_mut(),
) as c_ulong
}
pub unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int { pub unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, Some(f)) ffi::SSL_CTX_get_ex_new_index(0, ptr::null_mut(), None, None, Some(f))
@ -3089,52 +3317,49 @@ mod compat {
ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, Some(f)) ffi::SSL_get_ex_new_index(0, ptr::null_mut(), None, None, Some(f))
} }
pub unsafe fn SSL_CTX_up_ref(ssl: *mut ffi::SSL_CTX) -> libc::c_int { #[allow(bad_style)]
pub unsafe fn SSL_CTX_up_ref(ssl: *mut ffi::SSL_CTX) -> c_int {
ffi::CRYPTO_add_lock( ffi::CRYPTO_add_lock(
&mut (*ssl).references, &mut (*ssl).references,
1, 1,
ffi::CRYPTO_LOCK_SSL_CTX, ffi::CRYPTO_LOCK_SSL_CTX,
"mod.rs\0".as_ptr() as *const _, "mod.rs\0".as_ptr() as *const _,
line!() as libc::c_int, line!() as c_int,
); );
0 0
} }
#[allow(bad_style)]
pub unsafe fn SSL_SESSION_get_master_key( pub unsafe fn SSL_SESSION_get_master_key(
session: *const ffi::SSL_SESSION, session: *const ffi::SSL_SESSION,
out: *mut c_uchar, out: *mut c_uchar,
mut outlen: size_t, mut outlen: usize,
) -> size_t { ) -> usize {
if outlen == 0 { if outlen == 0 {
return (*session).master_key_length as size_t; return (*session).master_key_length as usize;
} }
if outlen > (*session).master_key_length as size_t { if outlen > (*session).master_key_length as usize {
outlen = (*session).master_key_length as size_t; outlen = (*session).master_key_length as usize;
} }
ptr::copy_nonoverlapping((*session).master_key.as_ptr(), out, outlen); ptr::copy_nonoverlapping((*session).master_key.as_ptr(), out, outlen);
outlen outlen
} }
pub fn tls_method() -> *const ffi::SSL_METHOD { #[allow(bad_style)]
unsafe { ffi::SSLv23_method() }
}
pub fn dtls_method() -> *const ffi::SSL_METHOD {
unsafe { ffi::DTLSv1_method() }
}
pub unsafe fn SSL_is_server(s: *mut ffi::SSL) -> c_int { pub unsafe fn SSL_is_server(s: *mut ffi::SSL) -> c_int {
(*s).server (*s).server
} }
#[allow(bad_style)]
pub unsafe fn SSL_SESSION_up_ref(ses: *mut ffi::SSL_SESSION) -> c_int { pub unsafe fn SSL_SESSION_up_ref(ses: *mut ffi::SSL_SESSION) -> c_int {
ffi::CRYPTO_add_lock( ffi::CRYPTO_add_lock(
&mut (*ses).references, &mut (*ses).references,
1, 1,
ffi::CRYPTO_LOCK_SSL_CTX, ffi::CRYPTO_LOCK_SSL_CTX,
"mod.rs\0".as_ptr() as *const _, "mod.rs\0".as_ptr() as *const _,
line!() as libc::c_int, line!() as c_int,
); );
0 0
} }
}
} }

View File

@ -19,7 +19,7 @@ use hash::MessageDigest;
use ocsp::{OcspResponse, OcspResponseStatus}; use ocsp::{OcspResponse, OcspResponseStatus};
use pkey::PKey; use pkey::PKey;
use ssl; use ssl;
#[cfg(any(ossl110, ossl111))] #[cfg(any(ossl110, ossl111, libressl261))]
use ssl::SslVersion; use ssl::SslVersion;
use ssl::{ use ssl::{
Error, HandshakeError, MidHandshakeSslStream, ShutdownResult, Ssl, SslAcceptor, SslConnector, Error, HandshakeError, MidHandshakeSslStream, ShutdownResult, Ssl, SslAcceptor, SslConnector,
@ -295,8 +295,8 @@ run_test!(verify_callback_data, |method, stream| {
match cert { match cert {
None => false, None => false,
Some(cert) => { Some(cert) => {
let fingerprint = cert.fingerprint(MessageDigest::sha1()).unwrap(); let fingerprint = cert.digest(MessageDigest::sha1()).unwrap();
fingerprint == node_id node_id == &*fingerprint
} }
} }
}); });
@ -323,8 +323,8 @@ run_test!(ssl_verify_callback, |method, stream| {
match x509.current_cert() { match x509.current_cert() {
None => false, None => false,
Some(cert) => { Some(cert) => {
let fingerprint = cert.fingerprint(MessageDigest::sha1()).unwrap(); let fingerprint = cert.digest(MessageDigest::sha1()).unwrap();
fingerprint == node_id node_id == &*fingerprint
} }
} }
}); });
@ -424,10 +424,10 @@ run_test!(get_peer_certificate, |method, stream| {
let ctx = SslContext::builder(method).unwrap(); let ctx = SslContext::builder(method).unwrap();
let stream = Ssl::new(&ctx.build()).unwrap().connect(stream).unwrap(); let stream = Ssl::new(&ctx.build()).unwrap().connect(stream).unwrap();
let cert = stream.ssl().peer_certificate().unwrap(); let cert = stream.ssl().peer_certificate().unwrap();
let fingerprint = cert.fingerprint(MessageDigest::sha1()).unwrap(); let fingerprint = cert.digest(MessageDigest::sha1()).unwrap();
let node_hash_str = "59172d9313e84459bcff27f967e79e6e9217e584"; let node_hash_str = "59172d9313e84459bcff27f967e79e6e9217e584";
let node_id = Vec::from_hex(node_hash_str).unwrap(); let node_id = Vec::from_hex(node_hash_str).unwrap();
assert_eq!(node_id, fingerprint) assert_eq!(node_id, &*fingerprint)
}); });
#[test] #[test]
@ -481,7 +481,7 @@ fn test_state() {
/// Tests that connecting with the client using ALPN, but the server not does not /// Tests that connecting with the client using ALPN, but the server not does not
/// break the existing connection behavior. /// break the existing connection behavior.
#[test] #[test]
#[cfg(any(ossl102, ossl110))] #[cfg(any(ossl102, libressl261))]
fn test_connect_with_unilateral_alpn() { fn test_connect_with_unilateral_alpn() {
let (_s, stream) = Server::new(); let (_s, stream) = Server::new();
let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
@ -503,7 +503,7 @@ fn test_connect_with_unilateral_alpn() {
/// Tests that when both the client as well as the server use ALPN and their /// Tests that when both the client as well as the server use ALPN and their
/// lists of supported protocols have an overlap, the correct protocol is chosen. /// lists of supported protocols have an overlap, the correct protocol is chosen.
#[test] #[test]
#[cfg(any(ossl102, ossl110))] #[cfg(any(ossl102, libressl261))]
fn test_connect_with_alpn_successful_multiple_matching() { fn test_connect_with_alpn_successful_multiple_matching() {
let (_s, stream) = Server::new_alpn(); let (_s, stream) = Server::new_alpn();
let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
@ -526,7 +526,7 @@ fn test_connect_with_alpn_successful_multiple_matching() {
/// lists of supported protocols have an overlap -- with only ONE protocol /// lists of supported protocols have an overlap -- with only ONE protocol
/// being valid for both. /// being valid for both.
#[test] #[test]
#[cfg(any(ossl102, ossl110))] #[cfg(any(ossl102, libressl261))]
fn test_connect_with_alpn_successful_single_match() { fn test_connect_with_alpn_successful_single_match() {
let (_s, stream) = Server::new_alpn(); let (_s, stream) = Server::new_alpn();
let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
@ -548,7 +548,7 @@ fn test_connect_with_alpn_successful_single_match() {
/// Tests that when the `SslStream` is created as a server stream, the protocols /// Tests that when the `SslStream` is created as a server stream, the protocols
/// are correctly advertised to the client. /// are correctly advertised to the client.
#[test] #[test]
#[cfg(any(ossl102, ossl110))] #[cfg(any(ossl102, libressl261))]
fn test_alpn_server_advertise_multiple() { fn test_alpn_server_advertise_multiple() {
let listener = TcpListener::bind("127.0.0.1:0").unwrap(); let listener = TcpListener::bind("127.0.0.1:0").unwrap();
let localhost = listener.local_addr().unwrap(); let localhost = listener.local_addr().unwrap();
@ -624,7 +624,7 @@ fn test_alpn_server_select_none_fatal() {
} }
#[test] #[test]
#[cfg(any(ossl102, ossl110))] #[cfg(any(ossl102, libressl261))]
fn test_alpn_server_select_none() { fn test_alpn_server_select_none() {
let listener = TcpListener::bind("127.0.0.1:0").unwrap(); let listener = TcpListener::bind("127.0.0.1:0").unwrap();
let localhost = listener.local_addr().unwrap(); let localhost = listener.local_addr().unwrap();
@ -1063,7 +1063,7 @@ fn tmp_dh_callback() {
} }
#[test] #[test]
#[cfg(any(all(ossl101, not(libressl)), ossl102))] #[cfg(all(ossl101, not(ossl110)))]
fn tmp_ecdh_callback() { fn tmp_ecdh_callback() {
use ec::EcKey; use ec::EcKey;
use nid::Nid; use nid::Nid;
@ -1137,7 +1137,7 @@ fn tmp_dh_callback_ssl() {
} }
#[test] #[test]
#[cfg(any(all(ossl101, not(libressl)), ossl102))] #[cfg(all(ossl101, not(ossl110)))]
fn tmp_ecdh_callback_ssl() { fn tmp_ecdh_callback_ssl() {
use ec::EcKey; use ec::EcKey;
use nid::Nid; use nid::Nid;
@ -1315,7 +1315,7 @@ fn keying_export() {
} }
#[test] #[test]
#[cfg(any(ossl110))] #[cfg(any(ossl110, libressl261))]
fn no_version_overlap() { fn no_version_overlap() {
let listener = TcpListener::bind("127.0.0.1:0").unwrap(); let listener = TcpListener::bind("127.0.0.1:0").unwrap();
let addr = listener.local_addr().unwrap(); let addr = listener.local_addr().unwrap();
@ -1330,7 +1330,7 @@ fn no_version_overlap() {
ctx.set_max_proto_version(Some(SslVersion::TLS1_1)).unwrap(); ctx.set_max_proto_version(Some(SslVersion::TLS1_1)).unwrap();
#[cfg(ossl110g)] #[cfg(ossl110g)]
assert_eq!(ctx.min_proto_version(), None); assert_eq!(ctx.min_proto_version(), None);
#[cfg(ossl110g)] #[cfg(any(ossl110g, libressl270))]
assert_eq!(ctx.max_proto_version(), Some(SslVersion::TLS1_1)); assert_eq!(ctx.max_proto_version(), Some(SslVersion::TLS1_1));
let ssl = Ssl::new(&ctx.build()).unwrap(); let ssl = Ssl::new(&ctx.build()).unwrap();
ssl.accept(stream).unwrap_err(); ssl.accept(stream).unwrap_err();
@ -1339,7 +1339,7 @@ fn no_version_overlap() {
let stream = TcpStream::connect(addr).unwrap(); let stream = TcpStream::connect(addr).unwrap();
let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
ctx.set_min_proto_version(Some(SslVersion::TLS1_2)).unwrap(); ctx.set_min_proto_version(Some(SslVersion::TLS1_2)).unwrap();
#[cfg(ossl110g)] #[cfg(any(ossl110g, libressl270))]
assert_eq!(ctx.min_proto_version(), Some(SslVersion::TLS1_2)); assert_eq!(ctx.min_proto_version(), Some(SslVersion::TLS1_2));
#[cfg(ossl110g)] #[cfg(ossl110g)]
assert_eq!(ctx.max_proto_version(), None); assert_eq!(ctx.max_proto_version(), None);

View File

@ -1,23 +1,30 @@
use foreign_types::{ForeignTypeRef, ForeignType, Opaque}; use ffi;
use foreign_types::{ForeignType, ForeignTypeRef, Opaque};
use libc::c_int; use libc::c_int;
use std::borrow::Borrow; use std::borrow::Borrow;
use std::convert::AsRef; use std::convert::AsRef;
use std::iter; use std::iter;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem; use std::mem;
use ffi;
use {cvt, cvt_p};
use error::ErrorStack; use error::ErrorStack;
use std::ops::{Deref, DerefMut, Index, IndexMut}; use std::ops::{Deref, DerefMut, Index, IndexMut};
use {cvt, cvt_p};
#[cfg(ossl10x)] cfg_if! {
use ffi::{sk_pop as OPENSSL_sk_pop, sk_free as OPENSSL_sk_free, sk_num as OPENSSL_sk_num, if #[cfg(ossl110)] {
use ffi::{
OPENSSL_sk_pop, OPENSSL_sk_free, OPENSSL_sk_num, OPENSSL_sk_value, OPENSSL_STACK,
OPENSSL_sk_new_null, OPENSSL_sk_push,
};
} else {
use ffi::{
sk_pop as OPENSSL_sk_pop, sk_free as OPENSSL_sk_free, sk_num as OPENSSL_sk_num,
sk_value as OPENSSL_sk_value, _STACK as OPENSSL_STACK, sk_value as OPENSSL_sk_value, _STACK as OPENSSL_STACK,
sk_new_null as OPENSSL_sk_new_null, sk_push as OPENSSL_sk_push}; sk_new_null as OPENSSL_sk_new_null, sk_push as OPENSSL_sk_push,
#[cfg(ossl110)] };
use ffi::{OPENSSL_sk_pop, OPENSSL_sk_free, OPENSSL_sk_num, OPENSSL_sk_value, OPENSSL_STACK, }
OPENSSL_sk_new_null, OPENSSL_sk_push}; }
/// Trait implemented by types which can be placed in a stack. /// Trait implemented by types which can be placed in a stack.
/// ///
@ -33,15 +40,8 @@ pub trait Stackable: ForeignType {
/// An owned stack of `T`. /// An owned stack of `T`.
pub struct Stack<T: Stackable>(*mut T::StackType); pub struct Stack<T: Stackable>(*mut T::StackType);
impl<T: Stackable> Stack<T> { unsafe impl<T: Stackable + Send> Send for Stack<T> {}
pub fn new() -> Result<Stack<T>, ErrorStack> { unsafe impl<T: Stackable + Sync> Sync for Stack<T> {}
unsafe {
ffi::init();
let ptr = cvt_p(OPENSSL_sk_new_null())?;
Ok(Stack(ptr as *mut _))
}
}
}
impl<T: Stackable> Drop for Stack<T> { impl<T: Stackable> Drop for Stack<T> {
fn drop(&mut self) { fn drop(&mut self) {
@ -52,6 +52,16 @@ impl<T: Stackable> Drop for Stack<T> {
} }
} }
impl<T: Stackable> Stack<T> {
pub fn new() -> Result<Stack<T>, ErrorStack> {
unsafe {
ffi::init();
let ptr = cvt_p(OPENSSL_sk_new_null())?;
Ok(Stack(ptr as *mut _))
}
}
}
impl<T: Stackable> iter::IntoIterator for Stack<T> { impl<T: Stackable> iter::IntoIterator for Stack<T> {
type IntoIter = IntoIter<T>; type IntoIter = IntoIter<T>;
type Item = T; type Item = T;
@ -157,6 +167,9 @@ impl<T: Stackable> ExactSizeIterator for IntoIter<T> {}
pub struct StackRef<T: Stackable>(Opaque, PhantomData<T>); pub struct StackRef<T: Stackable>(Opaque, PhantomData<T>);
unsafe impl<T: Stackable + Send> Send for StackRef<T> {}
unsafe impl<T: Stackable + Sync> Sync for StackRef<T> {}
impl<T: Stackable> ForeignTypeRef for StackRef<T> { impl<T: Stackable> ForeignTypeRef for StackRef<T> {
type CType = T::StackType; type CType = T::StackType;
} }
@ -218,9 +231,7 @@ impl<T: Stackable> StackRef<T> {
/// Pushes a value onto the top of the stack. /// Pushes a value onto the top of the stack.
pub fn push(&mut self, data: T) -> Result<(), ErrorStack> { pub fn push(&mut self, data: T) -> Result<(), ErrorStack> {
unsafe { unsafe {
cvt( cvt(OPENSSL_sk_push(self.as_stack(), data.as_ptr() as *mut _))?;
OPENSSL_sk_push(self.as_stack(), data.as_ptr() as *mut _),
)?;
mem::forget(data); mem::forget(data);
Ok(()) Ok(())
} }

View File

@ -52,14 +52,14 @@
//! println!("Decrypted: '{}'", output_string); //! println!("Decrypted: '{}'", output_string);
//! ``` //! ```
use ffi;
use libc::c_int;
use std::cmp; use std::cmp;
use std::ptr; use std::ptr;
use libc::c_int;
use ffi;
use {cvt, cvt_p};
use error::ErrorStack; use error::ErrorStack;
use nid::Nid; use nid::Nid;
use {cvt, cvt_p};
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub enum Mode { pub enum Mode {
@ -718,34 +718,31 @@ pub fn decrypt_aead(
Ok(out) Ok(out)
} }
#[cfg(ossl110)] cfg_if! {
use ffi::{EVP_CIPHER_block_size, EVP_CIPHER_iv_length, EVP_CIPHER_key_length}; if #[cfg(ossl110)] {
use ffi::{EVP_CIPHER_block_size, EVP_CIPHER_iv_length, EVP_CIPHER_key_length};
#[cfg(ossl10x)] } else {
#[allow(bad_style)] #[allow(bad_style)]
mod compat { pub unsafe fn EVP_CIPHER_iv_length(ptr: *const ffi::EVP_CIPHER) -> c_int {
use libc::c_int;
use ffi::EVP_CIPHER;
pub unsafe fn EVP_CIPHER_iv_length(ptr: *const EVP_CIPHER) -> c_int {
(*ptr).iv_len (*ptr).iv_len
} }
pub unsafe fn EVP_CIPHER_block_size(ptr: *const EVP_CIPHER) -> c_int { #[allow(bad_style)]
pub unsafe fn EVP_CIPHER_block_size(ptr: *const ffi::EVP_CIPHER) -> c_int {
(*ptr).block_size (*ptr).block_size
} }
pub unsafe fn EVP_CIPHER_key_length(ptr: *const EVP_CIPHER) -> c_int { #[allow(bad_style)]
pub unsafe fn EVP_CIPHER_key_length(ptr: *const ffi::EVP_CIPHER) -> c_int {
(*ptr).key_len (*ptr).key_len
} }
}
} }
#[cfg(ossl10x)]
use self::compat::*;
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use hex::{self, FromHex};
use super::*; use super::*;
use hex::{self, FromHex};
// Test vectors from FIPS-197: // Test vectors from FIPS-197:
// http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf // http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf

View File

@ -13,15 +13,21 @@
use std::ffi::CStr; use std::ffi::CStr;
#[cfg(ossl10x)] cfg_if! {
use ffi::{SSLEAY_VERSION as OPENSSL_VERSION, SSLEAY_CFLAGS as OPENSSL_CFLAGS, if #[cfg(ossl110)] {
use ffi::{
OPENSSL_VERSION, OPENSSL_CFLAGS, OPENSSL_BUILT_ON, OPENSSL_PLATFORM, OPENSSL_DIR,
OpenSSL_version_num, OpenSSL_version,
};
} else {
use ffi::{
SSLEAY_VERSION as OPENSSL_VERSION, SSLEAY_CFLAGS as OPENSSL_CFLAGS,
SSLEAY_BUILT_ON as OPENSSL_BUILT_ON, SSLEAY_PLATFORM as OPENSSL_PLATFORM, SSLEAY_BUILT_ON as OPENSSL_BUILT_ON, SSLEAY_PLATFORM as OPENSSL_PLATFORM,
SSLEAY_DIR as OPENSSL_DIR, SSLeay as OpenSSL_version_num, SSLEAY_DIR as OPENSSL_DIR, SSLeay as OpenSSL_version_num,
SSLeay_version as OpenSSL_version}; SSLeay_version as OpenSSL_version,
};
#[cfg(ossl110)] }
use ffi::{OPENSSL_VERSION, OPENSSL_CFLAGS, OPENSSL_BUILT_ON, OPENSSL_PLATFORM, OPENSSL_DIR, }
OpenSSL_version_num, OpenSSL_version};
/// OPENSSL_VERSION_NUMBER is a numeric release version identifier: /// OPENSSL_VERSION_NUMBER is a numeric release version identifier:
/// ///
@ -51,7 +57,6 @@ pub fn number() -> i64 {
unsafe { OpenSSL_version_num() as i64 } unsafe { OpenSSL_version_num() as i64 }
} }
/// The text variant of the version number and the release date. For example, "OpenSSL 0.9.5a 1 Apr 2000". /// The text variant of the version number and the release date. For example, "OpenSSL 0.9.5a 1 Apr 2000".
pub fn version() -> &'static str { pub fn version() -> &'static str {
unsafe { unsafe {

View File

@ -7,9 +7,9 @@
//! Internet protocols, including SSL/TLS, which is the basis for HTTPS, //! Internet protocols, including SSL/TLS, which is the basis for HTTPS,
//! the secure protocol for browsing the web. //! the secure protocol for browsing the web.
use libc::{c_int, c_long};
use ffi; use ffi;
use foreign_types::{ForeignType, ForeignTypeRef}; use foreign_types::{ForeignType, ForeignTypeRef};
use libc::{c_int, c_long};
use std::error::Error; use std::error::Error;
use std::ffi::{CStr, CString}; use std::ffi::{CStr, CString};
use std::fmt; use std::fmt;
@ -20,27 +20,20 @@ use std::ptr;
use std::slice; use std::slice;
use std::str; use std::str;
use {cvt, cvt_n, cvt_p};
use asn1::{Asn1BitStringRef, Asn1IntegerRef, Asn1ObjectRef, Asn1StringRef, Asn1TimeRef}; use asn1::{Asn1BitStringRef, Asn1IntegerRef, Asn1ObjectRef, Asn1StringRef, Asn1TimeRef};
use bio::MemBioSlice; use bio::MemBioSlice;
use conf::ConfRef; use conf::ConfRef;
use error::ErrorStack; use error::ErrorStack;
use ex_data::Index; use ex_data::Index;
use hash::MessageDigest; use hash::{DigestBytes, MessageDigest};
use nid::Nid; use nid::Nid;
use pkey::{HasPrivate, HasPublic, PKey, PKeyRef, Public}; use pkey::{HasPrivate, HasPublic, PKey, PKeyRef, Public};
use ssl::SslRef;
use stack::{Stack, StackRef, Stackable}; use stack::{Stack, StackRef, Stackable};
use string::OpensslString; use string::OpensslString;
use ssl::SslRef; use {cvt, cvt_n, cvt_p};
#[cfg(ossl10x)] #[cfg(any(ossl102, libressl261))]
use ffi::{ASN1_STRING_data, X509_STORE_CTX_get_chain, X509_set_notAfter, X509_set_notBefore};
#[cfg(ossl110)]
use ffi::{ASN1_STRING_get0_data as ASN1_STRING_data,
X509_STORE_CTX_get0_chain as X509_STORE_CTX_get_chain,
X509_set1_notAfter as X509_set_notAfter, X509_set1_notBefore as X509_set_notBefore};
#[cfg(any(ossl102, ossl110))]
pub mod verify; pub mod verify;
pub mod extension; pub mod extension;
@ -215,7 +208,7 @@ impl X509StoreContextRef {
/// [`X509_STORE_CTX_get0_chain`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_STORE_CTX_get0_chain.html /// [`X509_STORE_CTX_get0_chain`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_STORE_CTX_get0_chain.html
pub fn chain(&self) -> Option<&StackRef<X509>> { pub fn chain(&self) -> Option<&StackRef<X509>> {
unsafe { unsafe {
let chain = X509_STORE_CTX_get_chain(self.as_ptr()); let chain = X509_STORE_CTX_get0_chain(self.as_ptr());
if chain.is_null() { if chain.is_null() {
None None
@ -240,12 +233,12 @@ impl X509Builder {
/// Sets the notAfter constraint on the certificate. /// Sets the notAfter constraint on the certificate.
pub fn set_not_after(&mut self, not_after: &Asn1TimeRef) -> Result<(), ErrorStack> { pub fn set_not_after(&mut self, not_after: &Asn1TimeRef) -> Result<(), ErrorStack> {
unsafe { cvt(X509_set_notAfter(self.0.as_ptr(), not_after.as_ptr())).map(|_| ()) } unsafe { cvt(X509_set1_notAfter(self.0.as_ptr(), not_after.as_ptr())).map(|_| ()) }
} }
/// Sets the notBefore constraint on the certificate. /// Sets the notBefore constraint on the certificate.
pub fn set_not_before(&mut self, not_before: &Asn1TimeRef) -> Result<(), ErrorStack> { pub fn set_not_before(&mut self, not_before: &Asn1TimeRef) -> Result<(), ErrorStack> {
unsafe { cvt(X509_set_notBefore(self.0.as_ptr(), not_before.as_ptr())).map(|_| ()) } unsafe { cvt(X509_set1_notBefore(self.0.as_ptr(), not_before.as_ptr())).map(|_| ()) }
} }
/// Sets the version of the certificate. /// Sets the version of the certificate.
@ -454,27 +447,39 @@ impl X509Ref {
} }
} }
/// Returns certificate fingerprint calculated using provided hash /// Returns a digest of the DER representation of the certificate.
pub fn fingerprint(&self, hash_type: MessageDigest) -> Result<Vec<u8>, ErrorStack> { ///
/// This corresponds to [`X509_digest`].
///
/// [`X509_digest`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_digest.html
pub fn digest(&self, hash_type: MessageDigest) -> Result<DigestBytes, ErrorStack> {
unsafe { unsafe {
let evp = hash_type.as_ptr(); let mut digest = DigestBytes {
buf: [0; ffi::EVP_MAX_MD_SIZE as usize],
len: ffi::EVP_MAX_MD_SIZE as usize,
};
let mut len = ffi::EVP_MAX_MD_SIZE; let mut len = ffi::EVP_MAX_MD_SIZE;
let mut buf = vec![0u8; len as usize];
cvt(ffi::X509_digest( cvt(ffi::X509_digest(
self.as_ptr(), self.as_ptr(),
evp, hash_type.as_ptr(),
buf.as_mut_ptr() as *mut _, digest.buf.as_mut_ptr() as *mut _,
&mut len, &mut len,
))?; ))?;
buf.truncate(len as usize); digest.len = len as usize;
Ok(buf)
Ok(digest)
} }
} }
#[deprecated(since = "0.10.9", note = "renamed to digest")]
pub fn fingerprint(&self, hash_type: MessageDigest) -> Result<Vec<u8>, ErrorStack> {
self.digest(hash_type).map(|b| b.to_vec())
}
/// Returns the certificate's Not After validity period. /// Returns the certificate's Not After validity period.
pub fn not_after(&self) -> &Asn1TimeRef { pub fn not_after(&self) -> &Asn1TimeRef {
unsafe { unsafe {
let date = compat::X509_get_notAfter(self.as_ptr()); let date = X509_getm_notAfter(self.as_ptr());
assert!(!date.is_null()); assert!(!date.is_null());
Asn1TimeRef::from_ptr(date) Asn1TimeRef::from_ptr(date)
} }
@ -483,7 +488,7 @@ impl X509Ref {
/// Returns the certificate's Not Before validity period. /// Returns the certificate's Not Before validity period.
pub fn not_before(&self) -> &Asn1TimeRef { pub fn not_before(&self) -> &Asn1TimeRef {
unsafe { unsafe {
let date = compat::X509_get_notBefore(self.as_ptr()); let date = X509_getm_notBefore(self.as_ptr());
assert!(!date.is_null()); assert!(!date.is_null());
Asn1TimeRef::from_ptr(date) Asn1TimeRef::from_ptr(date)
} }
@ -493,7 +498,7 @@ impl X509Ref {
pub fn signature(&self) -> &Asn1BitStringRef { pub fn signature(&self) -> &Asn1BitStringRef {
unsafe { unsafe {
let mut signature = ptr::null(); let mut signature = ptr::null();
compat::X509_get0_signature(&mut signature, ptr::null_mut(), self.as_ptr()); X509_get0_signature(&mut signature, ptr::null_mut(), self.as_ptr());
assert!(!signature.is_null()); assert!(!signature.is_null());
Asn1BitStringRef::from_ptr(signature as *mut _) Asn1BitStringRef::from_ptr(signature as *mut _)
} }
@ -503,7 +508,7 @@ impl X509Ref {
pub fn signature_algorithm(&self) -> &X509AlgorithmRef { pub fn signature_algorithm(&self) -> &X509AlgorithmRef {
unsafe { unsafe {
let mut algor = ptr::null(); let mut algor = ptr::null();
compat::X509_get0_signature(ptr::null_mut(), &mut algor, self.as_ptr()); X509_get0_signature(ptr::null_mut(), &mut algor, self.as_ptr());
assert!(!algor.is_null()); assert!(!algor.is_null());
X509AlgorithmRef::from_ptr(algor as *mut _) X509AlgorithmRef::from_ptr(algor as *mut _)
} }
@ -564,7 +569,7 @@ impl ToOwned for X509Ref {
fn to_owned(&self) -> X509 { fn to_owned(&self) -> X509 {
unsafe { unsafe {
compat::X509_up_ref(self.as_ptr()); X509_up_ref(self.as_ptr());
X509::from_ptr(self.as_ptr()) X509::from_ptr(self.as_ptr())
} }
} }
@ -1054,7 +1059,7 @@ impl X509ReqRef {
/// ///
/// [`X509_REQ_get_version`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_get_version.html /// [`X509_REQ_get_version`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_get_version.html
pub fn version(&self) -> i32 { pub fn version(&self) -> i32 {
unsafe { compat::X509_REQ_get_version(self.as_ptr()) as i32 } unsafe { X509_REQ_get_version(self.as_ptr()) as i32 }
} }
/// Returns the subject name of the certificate request. /// Returns the subject name of the certificate request.
@ -1064,7 +1069,7 @@ impl X509ReqRef {
/// [`X509_REQ_get_subject_name`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_get_subject_name.html /// [`X509_REQ_get_subject_name`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_get_subject_name.html
pub fn subject_name(&self) -> &X509NameRef { pub fn subject_name(&self) -> &X509NameRef {
unsafe { unsafe {
let name = compat::X509_REQ_get_subject_name(self.as_ptr()); let name = X509_REQ_get_subject_name(self.as_ptr());
assert!(!name.is_null()); assert!(!name.is_null());
X509NameRef::from_ptr(name) X509NameRef::from_ptr(name)
} }
@ -1172,7 +1177,7 @@ impl GeneralNameRef {
return None; return None;
} }
let ptr = ASN1_STRING_data((*self.as_ptr()).d as *mut _); let ptr = ASN1_STRING_get0_data((*self.as_ptr()).d as *mut _);
let len = ffi::ASN1_STRING_length((*self.as_ptr()).d as *mut _); let len = ffi::ASN1_STRING_length((*self.as_ptr()).d as *mut _);
let slice = slice::from_raw_parts(ptr as *const u8, len as usize); let slice = slice::from_raw_parts(ptr as *const u8, len as usize);
@ -1205,7 +1210,7 @@ impl GeneralNameRef {
return None; return None;
} }
let ptr = ASN1_STRING_data((*self.as_ptr()).d as *mut _); let ptr = ASN1_STRING_get0_data((*self.as_ptr()).d as *mut _);
let len = ffi::ASN1_STRING_length((*self.as_ptr()).d as *mut _); let len = ffi::ASN1_STRING_length((*self.as_ptr()).d as *mut _);
Some(slice::from_raw_parts(ptr as *const u8, len as usize)) Some(slice::from_raw_parts(ptr as *const u8, len as usize))
@ -1232,39 +1237,41 @@ impl X509AlgorithmRef {
pub fn object(&self) -> &Asn1ObjectRef { pub fn object(&self) -> &Asn1ObjectRef {
unsafe { unsafe {
let mut oid = ptr::null(); let mut oid = ptr::null();
compat::X509_ALGOR_get0(&mut oid, ptr::null_mut(), ptr::null_mut(), self.as_ptr()); X509_ALGOR_get0(&mut oid, ptr::null_mut(), ptr::null_mut(), self.as_ptr());
assert!(!oid.is_null()); assert!(!oid.is_null());
Asn1ObjectRef::from_ptr(oid as *mut _) Asn1ObjectRef::from_ptr(oid as *mut _)
} }
} }
} }
#[cfg(ossl110)] cfg_if! {
mod compat { if #[cfg(ossl110)] {
pub use ffi::X509_getm_notAfter as X509_get_notAfter; use ffi::{
pub use ffi::X509_getm_notBefore as X509_get_notBefore; X509_ALGOR_get0, X509_REQ_get_subject_name, X509_REQ_get_version,
pub use ffi::X509_up_ref; X509_get0_signature, X509_getm_notAfter, X509_getm_notBefore, X509_up_ref,
pub use ffi::X509_REQ_get_version; ASN1_STRING_get0_data, X509_STORE_CTX_get0_chain, X509_set1_notAfter,
pub use ffi::X509_REQ_get_subject_name; X509_set1_notBefore,
pub use ffi::X509_get0_signature; };
pub use ffi::X509_ALGOR_get0; } else {
} use ffi::{
ASN1_STRING_data as ASN1_STRING_get0_data,
X509_STORE_CTX_get_chain as X509_STORE_CTX_get0_chain,
X509_set_notAfter as X509_set1_notAfter,
X509_set_notBefore as X509_set1_notBefore,
};
#[cfg(ossl10x)] #[allow(bad_style)]
#[allow(bad_style)] unsafe fn X509_getm_notAfter(x: *mut ffi::X509) -> *mut ffi::ASN1_TIME {
mod compat {
use libc::{c_int, c_void};
use ffi;
pub unsafe fn X509_get_notAfter(x: *mut ffi::X509) -> *mut ffi::ASN1_TIME {
(*(*(*x).cert_info).validity).notAfter (*(*(*x).cert_info).validity).notAfter
} }
pub unsafe fn X509_get_notBefore(x: *mut ffi::X509) -> *mut ffi::ASN1_TIME { #[allow(bad_style)]
unsafe fn X509_getm_notBefore(x: *mut ffi::X509) -> *mut ffi::ASN1_TIME {
(*(*(*x).cert_info).validity).notBefore (*(*(*x).cert_info).validity).notBefore
} }
pub unsafe fn X509_up_ref(x: *mut ffi::X509) { #[allow(bad_style)]
unsafe fn X509_up_ref(x: *mut ffi::X509) {
ffi::CRYPTO_add_lock( ffi::CRYPTO_add_lock(
&mut (*x).references, &mut (*x).references,
1, 1,
@ -1274,15 +1281,18 @@ mod compat {
); );
} }
pub unsafe fn X509_REQ_get_version(x: *mut ffi::X509_REQ) -> ::libc::c_long { #[allow(bad_style)]
::ffi::ASN1_INTEGER_get((*(*x).req_info).version) unsafe fn X509_REQ_get_version(x: *mut ffi::X509_REQ) -> ::libc::c_long {
ffi::ASN1_INTEGER_get((*(*x).req_info).version)
} }
pub unsafe fn X509_REQ_get_subject_name(x: *mut ffi::X509_REQ) -> *mut ::ffi::X509_NAME { #[allow(bad_style)]
unsafe fn X509_REQ_get_subject_name(x: *mut ffi::X509_REQ) -> *mut ::ffi::X509_NAME {
(*(*x).req_info).subject (*(*x).req_info).subject
} }
pub unsafe fn X509_get0_signature( #[allow(bad_style)]
unsafe fn X509_get0_signature(
psig: *mut *const ffi::ASN1_BIT_STRING, psig: *mut *const ffi::ASN1_BIT_STRING,
palg: *mut *const ffi::X509_ALGOR, palg: *mut *const ffi::X509_ALGOR,
x: *const ffi::X509, x: *const ffi::X509,
@ -1295,10 +1305,11 @@ mod compat {
} }
} }
pub unsafe fn X509_ALGOR_get0( #[allow(bad_style)]
unsafe fn X509_ALGOR_get0(
paobj: *mut *const ffi::ASN1_OBJECT, paobj: *mut *const ffi::ASN1_OBJECT,
pptype: *mut c_int, pptype: *mut c_int,
pval: *mut *mut c_void, pval: *mut *mut ::libc::c_void,
alg: *const ffi::X509_ALGOR, alg: *const ffi::X509_ALGOR,
) { ) {
if !paobj.is_null() { if !paobj.is_null() {
@ -1307,4 +1318,5 @@ mod compat {
assert!(pptype.is_null()); assert!(pptype.is_null());
assert!(pval.is_null()); assert!(pval.is_null());
} }
}
} }

View File

@ -44,11 +44,11 @@ use ffi;
use foreign_types::ForeignTypeRef; use foreign_types::ForeignTypeRef;
use std::mem; use std::mem;
use {cvt, cvt_p};
use error::ErrorStack; use error::ErrorStack;
use x509::X509; use x509::X509;
use {cvt, cvt_p};
foreign_type! { foreign_type_and_impl_send_sync! {
type CType = ffi::X509_STORE; type CType = ffi::X509_STORE;
fn drop = ffi::X509_STORE_free; fn drop = ffi::X509_STORE_free;
@ -82,9 +82,7 @@ impl X509StoreBuilderRef {
/// Adds a certificate to the certificate store. /// Adds a certificate to the certificate store.
// FIXME should take an &X509Ref // FIXME should take an &X509Ref
pub fn add_cert(&mut self, cert: X509) -> Result<(), ErrorStack> { pub fn add_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
unsafe { unsafe { cvt(ffi::X509_STORE_add_cert(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
cvt(ffi::X509_STORE_add_cert(self.as_ptr(), cert.as_ptr())).map(|_| ())
}
} }
/// Load certificates from their default locations. /// Load certificates from their default locations.
@ -97,7 +95,7 @@ impl X509StoreBuilderRef {
} }
} }
foreign_type! { foreign_type_and_impl_send_sync! {
type CType = ffi::X509_STORE; type CType = ffi::X509_STORE;
fn drop = ffi::X509_STORE_free; fn drop = ffi::X509_STORE_free;

View File

@ -7,10 +7,12 @@ use nid::Nid;
use pkey::{PKey, Private}; use pkey::{PKey, Private};
use rsa::Rsa; use rsa::Rsa;
use stack::Stack; use stack::Stack;
use x509::{X509, X509Name, X509Req, X509StoreContext, X509VerifyResult}; use x509::extension::{
use x509::extension::{AuthorityKeyIdentifier, BasicConstraints, ExtendedKeyUsage, KeyUsage, AuthorityKeyIdentifier, BasicConstraints, ExtendedKeyUsage, KeyUsage, SubjectAlternativeName,
SubjectAlternativeName, SubjectKeyIdentifier}; SubjectKeyIdentifier,
};
use x509::store::X509StoreBuilder; use x509::store::X509StoreBuilder;
use x509::{X509, X509Name, X509Req, X509StoreContext, X509VerifyResult};
fn pkey() -> PKey<Private> { fn pkey() -> PKey<Private> {
let rsa = Rsa::generate(2048).unwrap(); let rsa = Rsa::generate(2048).unwrap();
@ -21,12 +23,12 @@ fn pkey() -> PKey<Private> {
fn test_cert_loading() { fn test_cert_loading() {
let cert = include_bytes!("../../test/cert.pem"); let cert = include_bytes!("../../test/cert.pem");
let cert = X509::from_pem(cert).ok().expect("Failed to load PEM"); let cert = X509::from_pem(cert).ok().expect("Failed to load PEM");
let fingerprint = cert.fingerprint(MessageDigest::sha1()).unwrap(); let fingerprint = cert.digest(MessageDigest::sha1()).unwrap();
let hash_str = "59172d9313e84459bcff27f967e79e6e9217e584"; let hash_str = "59172d9313e84459bcff27f967e79e6e9217e584";
let hash_vec = Vec::from_hex(hash_str).unwrap(); let hash_vec = Vec::from_hex(hash_str).unwrap();
assert_eq!(fingerprint, hash_vec); assert_eq!(hash_vec, &*fingerprint);
} }
#[test] #[test]
@ -197,7 +199,8 @@ fn x509_builder() {
assert!(pkey.public_eq(&x509.public_key().unwrap())); assert!(pkey.public_eq(&x509.public_key().unwrap()));
let cn = x509.subject_name() let cn = x509
.subject_name()
.entries_by_nid(Nid::COMMONNAME) .entries_by_nid(Nid::COMMONNAME)
.next() .next()
.unwrap(); .unwrap();
@ -247,11 +250,11 @@ fn test_stack_from_pem() {
assert_eq!(certs.len(), 2); assert_eq!(certs.len(), 2);
assert_eq!( assert_eq!(
hex::encode(certs[0].fingerprint(MessageDigest::sha1()).unwrap()), hex::encode(certs[0].digest(MessageDigest::sha1()).unwrap()),
"59172d9313e84459bcff27f967e79e6e9217e584" "59172d9313e84459bcff27f967e79e6e9217e584"
); );
assert_eq!( assert_eq!(
hex::encode(certs[1].fingerprint(MessageDigest::sha1()).unwrap()), hex::encode(certs[1].digest(MessageDigest::sha1()).unwrap()),
"c0cbdf7cdd03c9773e5468e1f6d2da7d5cbb1875" "c0cbdf7cdd03c9773e5468e1f6d2da7d5cbb1875"
); );
} }
@ -291,7 +294,7 @@ fn signature() {
fn clone_x509() { fn clone_x509() {
let cert = include_bytes!("../../test/cert.pem"); let cert = include_bytes!("../../test/cert.pem");
let cert = X509::from_pem(cert).unwrap(); let cert = X509::from_pem(cert).unwrap();
cert.clone(); drop(cert.clone());
} }
#[test] #[test]

View File

@ -1,6 +1,6 @@
use libc::c_uint;
use ffi; use ffi;
use foreign_types::ForeignTypeRef; use foreign_types::ForeignTypeRef;
use libc::c_uint;
use std::net::IpAddr; use std::net::IpAddr;
use cvt; use cvt;

View File

@ -2,10 +2,12 @@ extern crate ctest;
use std::env; use std::env;
#[path = "../openssl-sys/build/cfgs.rs"]
mod cfgs;
fn main() { fn main() {
let mut cfg = ctest::TestGenerator::new(); let mut cfg = ctest::TestGenerator::new();
let target = env::var("TARGET").unwrap(); let target = env::var("TARGET").unwrap();
let mut is_libressl = false;
if let Ok(out) = env::var("DEP_OPENSSL_INCLUDE") { if let Ok(out) = env::var("DEP_OPENSSL_INCLUDE") {
cfg.include(&out); cfg.include(&out);
@ -26,21 +28,17 @@ fn main() {
cfg.define("WIN32_LEAN_AND_MEAN", None); cfg.define("WIN32_LEAN_AND_MEAN", None);
} }
if let Ok(_) = env::var("DEP_OPENSSL_LIBRESSL") { let openssl_version = env::var("DEP_OPENSSL_VERSION_NUMBER")
cfg.cfg("libressl", None); .ok()
is_libressl = true; .map(|v| u64::from_str_radix(&v, 16).unwrap());
} else if let Ok(version) = env::var("DEP_OPENSSL_VERSION") { let libressl_version = env::var("DEP_OPENSSL_LIBRESSL_VERSION_NUMBER")
cfg.cfg(&format!("ossl{}", version), None); .ok()
if version == "111" { .map(|v| u64::from_str_radix(&v, 16).unwrap());
cfg.cfg("ossl110", None);
} for c in cfgs::get(openssl_version, libressl_version) {
} cfg.cfg(c, None);
if let (Ok(version), Ok(patch)) = (
env::var("DEP_OPENSSL_VERSION"),
env::var("DEP_OPENSSL_PATCH"),
) {
cfg.cfg(&format!("ossl{}{}", version, patch), None);
} }
if let Ok(vars) = env::var("DEP_OPENSSL_CONF") { if let Ok(vars) = env::var("DEP_OPENSSL_CONF") {
for var in vars.split(",") { for var in vars.split(",") {
cfg.cfg("osslconf", Some(var)); cfg.cfg("osslconf", Some(var));
@ -65,7 +63,7 @@ fn main() {
.header("openssl/ocsp.h") .header("openssl/ocsp.h")
.header("openssl/evp.h"); .header("openssl/evp.h");
if !is_libressl { if openssl_version.is_some() {
cfg.header("openssl/cms.h"); cfg.header("openssl/cms.h");
} }
@ -79,7 +77,8 @@ fn main() {
} else if s == "_STACK" { } else if s == "_STACK" {
format!("struct stack_st") format!("struct stack_st")
// This logic should really be cleaned up // This logic should really be cleaned up
} else if is_struct && s != "point_conversion_form_t" } else if is_struct
&& s != "point_conversion_form_t"
&& s.chars().next().unwrap().is_lowercase() && s.chars().next().unwrap().is_lowercase()
{ {
format!("struct {}", s) format!("struct {}", s)
@ -111,9 +110,13 @@ fn main() {
(s == "GENERAL_NAME" && field == "d") // union (s == "GENERAL_NAME" && field == "d") // union
}); });
cfg.skip_signededness(|s| { cfg.skip_signededness(|s| {
s.ends_with("_cb") || s.ends_with("_CB") || s.ends_with("_cb_fn") s.ends_with("_cb")
|| s.starts_with("CRYPTO_") || s == "PasswordCallback" || s.ends_with("_CB")
|| s.ends_with("_cb_func") || s.ends_with("_cb_ex") || s.ends_with("_cb_fn")
|| s.starts_with("CRYPTO_")
|| s == "PasswordCallback"
|| s.ends_with("_cb_func")
|| s.ends_with("_cb_ex")
}); });
cfg.field_name(|_s, field| { cfg.field_name(|_s, field| {
if field == "type_" { if field == "type_" {