Add support for OpenSSL 1.1.0
This commit is relatively major refactoring of the `openssl-sys` crate as well
as the `openssl` crate itself. The end goal here was to support OpenSSL 1.1.0,
and lots of other various tweaks happened along the way. The major new features
are:
* OpenSSL 1.1.0 is supported
* OpenSSL 0.9.8 is no longer supported (aka all OSX users by default)
* All FFI bindings are verified with the `ctest` crate (same way as the `libc`
crate)
* CI matrixes are vastly expanded to include 32/64 of all platforms, more
OpenSSL version coverage, as well as ARM coverage on Linux
* The `c_helpers` module is completely removed along with the `gcc` dependency.
* The `openssl-sys` build script was completely rewritten
* Now uses `OPENSSL_DIR` to find the installation, not include/lib env vars.
* Better error messages for mismatched versions.
* Better error messages for failing to find OpenSSL on a platform (more can be
done here)
* Probing of OpenSSL build-time configuration to inform the API of the `*-sys`
crate.
* Many Cargo features have been removed as they're now enabled by default.
As this is a breaking change to both the `openssl` and `openssl-sys` crates this
will necessitate a major version bump of both. There's still a few more API
questions remaining but let's hash that out on a PR!
Closes #452
This commit is contained in:
parent
c1e41349fb
commit
43c951f743
94
.travis.yml
94
.travis.yml
|
|
@ -1,28 +1,86 @@
|
|||
language: rust
|
||||
sudo: false
|
||||
sudo: required
|
||||
rust: stable
|
||||
dist: trusty
|
||||
|
||||
env:
|
||||
global:
|
||||
- TARGET=x86_64-unknown-linux-gnu
|
||||
matrix:
|
||||
include:
|
||||
# ARM-bit version compat
|
||||
- env: >
|
||||
TARGET=arm-unknown-linux-gnueabihf
|
||||
BUILD_OPENSSL_VERSION=1.0.2h
|
||||
CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER=arm-linux-gnueabihf-gcc
|
||||
QEMU_LD_PREFIX=/usr/arm-linux-gnueabihf
|
||||
RUST_TEST_THREADS=1
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- gcc-arm-linux-gnueabihf
|
||||
rust:
|
||||
- nightly
|
||||
- 1.9.0
|
||||
os:
|
||||
- osx
|
||||
- linux
|
||||
env:
|
||||
matrix:
|
||||
- TEST_FEATURES=false
|
||||
- TEST_FEATURES=true
|
||||
matrix:
|
||||
# include:
|
||||
# - os: linux
|
||||
# env: TARGET=arm-unknown-linux-gnueabihf TEST_FEATURES=true
|
||||
# rust: 1.7.0
|
||||
exclude:
|
||||
- qemu-user-static
|
||||
- libc6-dev-armhf-cross
|
||||
- binfmt-support
|
||||
- env: >
|
||||
TARGET=arm-unknown-linux-gnueabihf
|
||||
BUILD_OPENSSL_VERSION=1.1.0b
|
||||
CARGO_TARGET_ARM_UNKNOWN_LINUX_GNUEABIHF_LINKER=arm-linux-gnueabihf-gcc
|
||||
QEMU_LD_PREFIX=/usr/arm-linux-gnueabihf
|
||||
RUST_TEST_THREADS=1
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- gcc-arm-linux-gnueabihf
|
||||
- qemu-user-static
|
||||
- libc6-dev-armhf-cross
|
||||
- binfmt-support
|
||||
|
||||
# Minimum version supported
|
||||
- rust: 1.9.0
|
||||
|
||||
# beta/nightly channels
|
||||
- rust: beta
|
||||
- rust: nightly
|
||||
|
||||
# 64-bit version compat
|
||||
- env: BUILD_OPENSSL_VERSION=1.0.1u
|
||||
- env: BUILD_OPENSSL_VERSION=1.0.2h
|
||||
- env: BUILD_OPENSSL_VERSION=1.1.0b
|
||||
|
||||
# 32-bit version compat
|
||||
- env: TARGET=i686-unknown-linux-gnu BUILD_OPENSSL_VERSION=1.0.1u
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- gcc-multilib
|
||||
- env: TARGET=i686-unknown-linux-gnu BUILD_OPENSSL_VERSION=1.0.2h
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- gcc-multilib
|
||||
- env: TARGET=i686-unknown-linux-gnu BUILD_OPENSSL_VERSION=1.1.0b
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- gcc-multilib
|
||||
|
||||
# osx 32/64
|
||||
- os: osx
|
||||
env: TEST_FEATURES=true
|
||||
env: TARGET=x86_64-apple-darwin
|
||||
- os: osx
|
||||
env: TARGET=i686-apple-darwin
|
||||
install: brew uninstall openssl && brew install openssl --universal
|
||||
|
||||
|
||||
before_install:
|
||||
- ./openssl/test/build.sh
|
||||
- curl https://static.rust-lang.org/rustup.sh |
|
||||
sh -s -- --add-target=$TARGET --disable-sudo -y --prefix=`rustc --print sysroot`
|
||||
script:
|
||||
- ./openssl/test/run.sh
|
||||
|
||||
cache:
|
||||
cargo: true
|
||||
directories:
|
||||
- $HOME/openssl
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
[workspace]
|
||||
members = ["openssl", "openssl-sys"]
|
||||
members = ["openssl", "openssl-sys", "systest"]
|
||||
|
|
|
|||
112
README.md
112
README.md
|
|
@ -6,13 +6,16 @@
|
|||
|
||||
## Building
|
||||
|
||||
rust-openssl depends on both the OpenSSL runtime libraries and headers.
|
||||
rust-openssl depends on the OpenSSL runtime libraries version 1.0.1 or above.
|
||||
Currently the libraries need to be present in the build environment before this
|
||||
crate is compiled, and some instructions of how to do this are in the sections
|
||||
below.
|
||||
|
||||
### Linux
|
||||
|
||||
On Linux, you can install OpenSSL via your package manager. The headers are
|
||||
sometimes provided in a separate package than the runtime libraries - look for
|
||||
something like `openssl-devel` or `libssl-dev`.
|
||||
On Linux, you can typically install OpenSSL via your package manager. The
|
||||
headers are sometimes provided in a separate package than the runtime libraries
|
||||
- look for something like `openssl-devel` or `libssl-dev`.
|
||||
|
||||
```bash
|
||||
# On Ubuntu
|
||||
|
|
@ -23,79 +26,78 @@ sudo pacman -S openssl
|
|||
sudo dnf install openssl-devel
|
||||
```
|
||||
|
||||
If installation via a package manager is not possible, or if you're cross
|
||||
compiling to a separate target, you'll typically need to compile OpenSSL from
|
||||
source. That can normally be done with:
|
||||
|
||||
```
|
||||
curl -O https://www.openssl.org/source/openssl-1.1.0b.tar.gz
|
||||
tar xf openssl-1.1.0b.tar.gz
|
||||
cd openssl-1.1.0b
|
||||
export CC=...
|
||||
./Configure --prefix=... linux-x86_64 -fPIC
|
||||
make -j$(nproc)
|
||||
make install
|
||||
```
|
||||
|
||||
### OSX
|
||||
|
||||
OpenSSL 0.9.8 is preinstalled on OSX. Some features are only available when
|
||||
linking against OpenSSL 1.0.0 or greater; see below on how to point
|
||||
rust-openssl to a separate installation. OSX releases starting at 10.11, "El
|
||||
Capitan", no longer include OpenSSL headers which will prevent the `openssl`
|
||||
crate from compiling.
|
||||
Although OpenSSL 0.9.8 is preinstalled on OSX this library is being phased out
|
||||
of OSX and this crate also does not support this version of OpenSSL. To use this
|
||||
crate on OSX you'll need to install OpenSSL via some alternate means, typically
|
||||
homebrew:
|
||||
|
||||
For OSX 10.11 you can use brew to install OpenSSL and then set the environment variables
|
||||
as described below.
|
||||
```bash
|
||||
brew install openssl
|
||||
export OPENSSL_INCLUDE_DIR=`brew --prefix openssl`/include
|
||||
export OPENSSL_LIB_DIR=`brew --prefix openssl`/lib
|
||||
```
|
||||
|
||||
May be necessary clean the repository with `cargo clean` before build again.
|
||||
### Windows MSVC
|
||||
|
||||
### Windows
|
||||
On MSVC it's unfortunately not always a trivial process acquiring OpenSSL.
|
||||
Perhaps the easiest way to do this right now is to download [precompiled
|
||||
binaries] and install them on your system. Currently it's recommended to
|
||||
install the 1.1.0b light installation if you're choosing this route.
|
||||
|
||||
On Windows, consider building with [mingw-w64](http://mingw-w64.org/).
|
||||
Build script will try to find mingw in `PATH` environment variable to provide
|
||||
Cargo with location where openssl libs from mingw-w64 package may be found.
|
||||
[precompiled binaries]: http://slproweb.com/products/Win32OpenSSL.html
|
||||
|
||||
mingw-w64 can be easily installed by using [MSYS2](http://msys2.github.io/). Install MSYS2 according to the instructions, and then, from an MSYS2 Shell, install mingw-w64:
|
||||
Once a precompiled binary is installed you can configure this crate to find the
|
||||
installation via an environment variable:
|
||||
|
||||
32-bit:
|
||||
```bash
|
||||
pacman -S mingw-w64-i686-gcc
|
||||
```
|
||||
set OPENSSL_DIR=C:\OpenSSL-Win64
|
||||
```
|
||||
|
||||
64-bit
|
||||
```bash
|
||||
pacman -S mingw-w64-x86_64-gcc
|
||||
After that, you're just a `cargo build` away!
|
||||
|
||||
### Windows GNU (MinGW)
|
||||
|
||||
The easiest way to acquire OpenSSL when working with MinGW is to ensure you're
|
||||
using [MSYS2](http://msys2.github.io) and to then execute:
|
||||
|
||||
```
|
||||
# 32-bit
|
||||
pacman -S mingw-w64-i686-openssl
|
||||
|
||||
# 64-bit
|
||||
pacman -S mingw-w64-x86_64-openssl
|
||||
```
|
||||
|
||||
and then install the mingw-w64 toolchain.
|
||||
|
||||
32-bit:
|
||||
```bash
|
||||
pacman -S mingw-w64-i686-toolchain
|
||||
```
|
||||
|
||||
64-bit:
|
||||
```bash
|
||||
pacman -S mingw-w64-x86_64-toolchain
|
||||
```
|
||||
|
||||
Alternatively, install OpenSSL from [here][1]. Cargo will not be able to find OpenSSL if it's
|
||||
installed to the default location. You can either copy the `include/openssl`
|
||||
directory, `libssl32.dll`, and `libeay32.dll` to locations that Cargo can find
|
||||
or pass the location to Cargo via environment variables:
|
||||
|
||||
```bash
|
||||
env OPENSSL_LIB_DIR=C:/OpenSSL-Win64 OPENSSL_INCLUDE_DIR=C:/OpenSSL-Win64/include cargo build
|
||||
```
|
||||
And after that, a `cargo build` should be all you need!
|
||||
|
||||
### Manual configuration
|
||||
|
||||
rust-openssl's build script will by default attempt to locate OpenSSL via
|
||||
pkg-config. This will not work in some situations, for example, on systems that
|
||||
don't have pkg-config, when cross compiling, or when using a copy of OpenSSL
|
||||
pkg-config or other system-specific mechanisms. This will not work in some
|
||||
situations however, for example cross compiling or when using a copy of OpenSSL
|
||||
other than the normal system install.
|
||||
|
||||
The build script can be configured via environment variables:
|
||||
* `OPENSSL_LIB_DIR` - If specified, a directory that will be used to find
|
||||
OpenSSL runtime libraries.
|
||||
* `OPENSSL_INCLUDE_DIR` - If specified, a directory that will be used to find
|
||||
OpenSSL headers.
|
||||
|
||||
* `OPENSSL_DIR` - If specified, a directory that will be used to find
|
||||
OpenSSL installation. It's expected that under this directory the `include`
|
||||
folder has header files and a `lib` folder has the runtime libraries.
|
||||
* `OPENSSL_STATIC` - If specified, OpenSSL libraries will be statically rather
|
||||
than dynamically linked.
|
||||
|
||||
If either `OPENSSL_LIB_DIR` or `OPENSSL_INCLUDE_DIR` are specified, then the
|
||||
build script will skip the pkg-config step.
|
||||
|
||||
[1]: http://slproweb.com/products/Win32OpenSSL.html
|
||||
If `OPENSSL_DIR` is specified, then the build script will skip the pkg-config
|
||||
step.
|
||||
|
|
|
|||
40
appveyor.yml
40
appveyor.yml
|
|
@ -1,25 +1,43 @@
|
|||
environment:
|
||||
OPENSSL_INCLUDE_DIR: C:\OpenSSL\include
|
||||
OPENSSL_LIB_DIR: C:\OpenSSL\lib
|
||||
OPENSSL_LIBS: ssleay32:libeay32
|
||||
matrix:
|
||||
# 1.1.0, 64/32 bit
|
||||
- TARGET: i686-pc-windows-gnu
|
||||
BITS: 32
|
||||
MSYS2: 1
|
||||
OPENSSL_VERSION: 1_1_0b
|
||||
- TARGET: x86_64-pc-windows-msvc
|
||||
BITS: 64
|
||||
OPENSSL_VERSION: 1_1_0b
|
||||
OPENSSL_DIR: C:\OpenSSL
|
||||
|
||||
# 1.0.2, 64/32 bit
|
||||
- TARGET: x86_64-pc-windows-gnu
|
||||
BITS: 64
|
||||
MSYS2: 1
|
||||
OPENSSL_VERSION: 1_0_2j
|
||||
- TARGET: i686-pc-windows-msvc
|
||||
BITS: 32
|
||||
OPENSSL_VERSION: 1_0_2j
|
||||
OPENSSL_DIR: C:\OpenSSL
|
||||
install:
|
||||
- ps: Start-FileDownload "http://slproweb.com/download/Win${env:BITS}OpenSSL-1_0_2h.exe"
|
||||
- Win%BITS%OpenSSL-1_0_2h.exe /SILENT /VERYSILENT /SP- /DIR="C:\OpenSSL"
|
||||
- ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-1.9.0-${env:TARGET}.exe"
|
||||
- rust-1.9.0-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust"
|
||||
- SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin
|
||||
- SET PATH=%PATH%;C:\MinGW\bin
|
||||
# install OpenSSL
|
||||
- ps: Start-FileDownload "http://slproweb.com/download/Win${env:BITS}OpenSSL-${env:OPENSSL_VERSION}.exe"
|
||||
- Win%BITS%OpenSSL-%OPENSSL_VERSION%.exe /SILENT /VERYSILENT /SP- /DIR="C:\OpenSSL"
|
||||
|
||||
# Install Rust
|
||||
- curl -sSf -o rustup-init.exe https://win.rustup.rs/
|
||||
- rustup-init.exe -y --default-host %TARGET%
|
||||
- set PATH=%PATH%;C:\Users\appveyor\.cargo\bin
|
||||
- if defined MSYS2 set PATH=C:\msys64\mingw%BITS%\bin;%PATH%
|
||||
- rustc -V
|
||||
- cargo -V
|
||||
|
||||
build: false
|
||||
|
||||
# Don't run doctests due to rust-lang/cargo#1592
|
||||
test_script:
|
||||
- cargo test --lib --manifest-path openssl/Cargo.toml
|
||||
- cargo run --manifest-path systest/Cargo.toml --target %TARGET%
|
||||
- cargo test --manifest-path openssl/Cargo.toml --target %TARGET%
|
||||
|
||||
cache:
|
||||
- target
|
||||
- C:\Users\appveyor\.cargo\registry
|
||||
|
|
|
|||
|
|
@ -10,38 +10,12 @@ documentation = "https://sfackler.github.io/rust-openssl/doc/v0.7.17/openssl_sys
|
|||
links = "openssl"
|
||||
build = "build.rs"
|
||||
|
||||
[features]
|
||||
tlsv1_2 = []
|
||||
tlsv1_1 = []
|
||||
dtlsv1 = []
|
||||
dtlsv1_2 = []
|
||||
sslv2 = []
|
||||
sslv3 = []
|
||||
aes_xts = []
|
||||
aes_ctr = []
|
||||
npn = []
|
||||
alpn = []
|
||||
rfc5114 = []
|
||||
pkcs5_pbkdf2_hmac = []
|
||||
ecdh_auto = []
|
||||
hmac_clone = []
|
||||
|
||||
[dependencies]
|
||||
libc = "0.2"
|
||||
|
||||
[build-dependencies]
|
||||
pkg-config = "0.3"
|
||||
|
||||
[target.le32-unknown-nacl.dependencies]
|
||||
libressl-pnacl-sys = "2.1.0"
|
||||
[target.x86_64-unknown-nacl.dependencies]
|
||||
libressl-pnacl-sys = "2.1.0"
|
||||
[target.i686-unknown-nacl.dependencies]
|
||||
libressl-pnacl-sys = "2.1.0"
|
||||
[target.arm-unknown-nacl.dependencies]
|
||||
libressl-pnacl-sys = "2.1.0"
|
||||
|
||||
# Only here to make sure we link to these in a static build on Windows
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
user32-sys = "0.2"
|
||||
gdi32-sys = "0.2"
|
||||
|
|
|
|||
|
|
@ -1,86 +1,344 @@
|
|||
extern crate pkg_config;
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::env;
|
||||
use std::ffi::OsString;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
fn main() {
|
||||
let target = env::var("TARGET").unwrap();
|
||||
|
||||
// libressl_pnacl_sys links the libs needed.
|
||||
if target.ends_with("nacl") { return; }
|
||||
let openssl_dir = env::var_os("OPENSSL_DIR").unwrap_or_else(|| {
|
||||
find_openssl_dir(&target)
|
||||
});
|
||||
|
||||
let lib_dir = env::var("OPENSSL_LIB_DIR").ok();
|
||||
let include_dir = env::var("OPENSSL_INCLUDE_DIR").ok();
|
||||
|
||||
if lib_dir.is_none() && include_dir.is_none() {
|
||||
// rustc doesn't seem to work with pkg-config's output in mingw64
|
||||
if !target.contains("windows") {
|
||||
if let Ok(info) = pkg_config::find_library("openssl") {
|
||||
// avoid empty include paths as they are not supported by GCC
|
||||
if info.include_paths.len() > 0 {
|
||||
let paths = env::join_paths(info.include_paths).unwrap();
|
||||
println!("cargo:include={}", paths.to_str().unwrap());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if let Some(mingw_paths) = get_mingw_in_path() {
|
||||
for path in mingw_paths {
|
||||
println!("cargo:rustc-link-search=native={}", path);
|
||||
}
|
||||
}
|
||||
let lib_dir = Path::new(&openssl_dir).join("lib");
|
||||
let include_dir = Path::new(&openssl_dir).join("include");
|
||||
if !Path::new(&lib_dir).exists() {
|
||||
panic!("OpenSSL library directory does not exist: {}",
|
||||
lib_dir.to_string_lossy());
|
||||
}
|
||||
|
||||
let libs_env = env::var("OPENSSL_LIBS").ok();
|
||||
let libs = match libs_env {
|
||||
Some(ref v) => v.split(":").collect(),
|
||||
None => if target.contains("windows") {
|
||||
if get_mingw_in_path().is_some() && lib_dir.is_none() && include_dir.is_none() {
|
||||
vec!["ssleay32", "eay32"]
|
||||
if !Path::new(&include_dir).exists() {
|
||||
panic!("OpenSSL include directory does not exist: {}",
|
||||
include_dir.to_string_lossy());
|
||||
}
|
||||
|
||||
println!("cargo:rustc-link-search=native={}", lib_dir.to_string_lossy());
|
||||
println!("cargo:include={}", include_dir.to_string_lossy());
|
||||
|
||||
let version = validate_headers(&[include_dir.clone().into()],
|
||||
&[lib_dir.clone().into()]);
|
||||
|
||||
let libs = if (version.contains("0x10001") ||
|
||||
version.contains("0x10002")) &&
|
||||
target.contains("windows") {
|
||||
["ssleay32", "libeay32"]
|
||||
} else if target.contains("windows") {
|
||||
["libssl", "libcrypto"]
|
||||
} else {
|
||||
vec!["ssl32", "eay32"]
|
||||
}
|
||||
} else {
|
||||
vec!["ssl", "crypto"]
|
||||
}
|
||||
["ssl", "crypto"]
|
||||
};
|
||||
|
||||
let mode = if env::var_os("OPENSSL_STATIC").is_some() {
|
||||
"static"
|
||||
let kind = determine_mode(Path::new(&lib_dir), &libs);
|
||||
for lib in libs.iter() {
|
||||
println!("cargo:rustc-link-lib={}={}", kind, lib);
|
||||
}
|
||||
}
|
||||
|
||||
fn find_openssl_dir(target: &str) -> OsString {
|
||||
let host = env::var("HOST").unwrap();
|
||||
|
||||
if host.contains("apple-darwin") && target.contains("apple-darwin") {
|
||||
let homebrew = Path::new("/usr/local/opt/openssl");
|
||||
if homebrew.exists() {
|
||||
return homebrew.to_path_buf().into()
|
||||
}
|
||||
let homebrew = Path::new("/usr/local/opt/openssl@1.1");
|
||||
if homebrew.exists() {
|
||||
return homebrew.to_path_buf().into()
|
||||
}
|
||||
}
|
||||
|
||||
try_pkg_config();
|
||||
|
||||
let mut msg = format!("
|
||||
|
||||
Could not find directory of OpenSSL installation, and this `-sys` crate cannot
|
||||
proceed without this knowledge. If OpenSSL is installed and this crate had
|
||||
trouble finding it, you can set the `OPENSSL_DIR` environment variable for the
|
||||
compilation process.
|
||||
|
||||
If you're in a situation where you think the directory *should* be found
|
||||
automatically, please open a bug at https://github.com/sfackler/rust-openssl
|
||||
and include information about your system as well as this message.
|
||||
|
||||
$HOST = {}
|
||||
$TARGET = {}
|
||||
openssl-sys = {}
|
||||
|
||||
",
|
||||
host, target, env!("CARGO_PKG_VERSION"));
|
||||
|
||||
if host.contains("apple-darwin") && target.contains("apple-darwin") {
|
||||
let system = Path::new("/usr/lib/libssl.0.9.8.dylib");
|
||||
if system.exists() {
|
||||
msg.push_str(&format!("
|
||||
|
||||
It looks like you're compiling on macOS, where the system contains a version of
|
||||
OpenSSL 0.9.8. This crate no longer supports OpenSSL 0.9.8.
|
||||
|
||||
As a consumer of this crate, you can fix this error by using Homebrew to
|
||||
install the `openssl` package, or as a maintainer you can use the openssl-sys
|
||||
0.7 crate for support with OpenSSL 0.9.8.
|
||||
|
||||
Unfortunately though the compile cannot continue, so aborting.
|
||||
|
||||
"));
|
||||
}
|
||||
}
|
||||
|
||||
if host.contains("windows") && target.contains("windows-gnu") {
|
||||
msg.push_str(&format!("
|
||||
It looks like you're compiling for MinGW but you may not have either OpenSSL or
|
||||
pkg-config installed. You can install these two dependencies with:
|
||||
|
||||
pacman -S openssl pkg-config
|
||||
|
||||
and try building this crate again.
|
||||
|
||||
"
|
||||
));
|
||||
}
|
||||
|
||||
if host.contains("windows") && target.contains("windows-msvc") {
|
||||
msg.push_str(&format!("
|
||||
It looks like you're compiling for MSVC but we couldn't detect an OpenSSL
|
||||
installation. If there isn't one installed then you can try the rust-openssl
|
||||
README for more information about how to download precompiled binaries of
|
||||
OpenSSL:
|
||||
|
||||
https://github.com/sfackler/rust-openssl#windows
|
||||
|
||||
"
|
||||
));
|
||||
}
|
||||
|
||||
panic!(msg);
|
||||
}
|
||||
|
||||
/// Attempt to find OpenSSL through pkg-config.
|
||||
///
|
||||
/// Note that if this succeeds then the function does not return as pkg-config
|
||||
/// typically tells us all the information that we need.
|
||||
fn try_pkg_config() {
|
||||
let target = env::var("TARGET").unwrap();
|
||||
let host = env::var("HOST").unwrap();
|
||||
|
||||
// If we're going to windows-gnu we can use pkg-config, but only so long as
|
||||
// we're coming from a windows host.
|
||||
//
|
||||
// Otherwise if we're going to windows we probably can't use pkg-config.
|
||||
if target.contains("windows-gnu") && host.contains("windows") {
|
||||
env::set_var("PKG_CONFIG_ALLOW_CROSS", "1");
|
||||
} else if target.contains("windows") {
|
||||
return
|
||||
}
|
||||
|
||||
// We're going to be looking at header files, so show us all the system
|
||||
// cflags dirs for showing us lots of `-I`.
|
||||
env::set_var("PKG_CONFIG_ALLOW_SYSTEM_CFLAGS", "1");
|
||||
|
||||
let lib = match pkg_config::find_library("openssl") {
|
||||
Ok(lib) => lib,
|
||||
Err(_) => return,
|
||||
};
|
||||
|
||||
if lib.include_paths.len() == 0 {
|
||||
panic!("
|
||||
|
||||
Used pkg-config to discover the OpenSSL installation, but pkg-config did not
|
||||
return any include paths for the installation. This crate needs to take a peek
|
||||
at the header files so it cannot proceed unless they're found.
|
||||
|
||||
You can try fixing this by setting the `OPENSSL_DIR` environment variable
|
||||
pointing to your OpenSSL installation.
|
||||
|
||||
");
|
||||
}
|
||||
|
||||
validate_headers(&lib.include_paths, &lib.link_paths);
|
||||
|
||||
for include in lib.include_paths.iter() {
|
||||
println!("cargo:include={}", include.display());
|
||||
}
|
||||
|
||||
std::process::exit(0);
|
||||
}
|
||||
|
||||
/// Validates the header files found in `include_dir` and then returns the
|
||||
/// version string of OpenSSL.
|
||||
fn validate_headers(include_dirs: &[PathBuf],
|
||||
libdirs: &[PathBuf]) -> String {
|
||||
// This `*-sys` crate only works with OpenSSL 1.0.1, 1.0.2, and 1.1.0. To
|
||||
// correctly expose the right API from this crate, take a look at
|
||||
// `opensslv.h` to see what version OpenSSL claims to be.
|
||||
let mut version_header = String::new();
|
||||
let mut include = include_dirs.iter()
|
||||
.map(|p| p.join("openssl/opensslv.h"))
|
||||
.filter(|p| p.exists());
|
||||
let mut f = match include.next() {
|
||||
Some(f) => File::open(f).unwrap(),
|
||||
None => {
|
||||
panic!("failed to open header file at `openssl/opensslv.h` to learn
|
||||
about OpenSSL's version number, looked inside:\n\n{:#?}\n\n",
|
||||
include_dirs);
|
||||
}
|
||||
};
|
||||
f.read_to_string(&mut version_header).unwrap();
|
||||
|
||||
// Do a bit of string parsing to find `#define OPENSSL_VERSION_NUMBER ...`
|
||||
let version_line = version_header.lines().find(|l| {
|
||||
l.contains("define ") && l.contains("OPENSSL_VERSION_NUMBER")
|
||||
}).and_then(|line| {
|
||||
let start = match line.find("0x") {
|
||||
Some(start) => start,
|
||||
None => return None,
|
||||
};
|
||||
Some(line[start..].trim())
|
||||
});
|
||||
let version_text = match version_line {
|
||||
Some(text) => text,
|
||||
None => {
|
||||
panic!("header file at `{}` did not include `OPENSSL_VERSION_NUMBER` \
|
||||
that this crate recognized, failed to learn about the \
|
||||
OpenSSL version number");
|
||||
}
|
||||
};
|
||||
if version_text.contains("0x10001") {
|
||||
println!("cargo:rustc-cfg=ossl101");
|
||||
println!("cargo:is_101=1");
|
||||
} else if version_text.contains("0x10002") {
|
||||
println!("cargo:rustc-cfg=ossl102");
|
||||
println!("cargo:is_102=1");
|
||||
} else if version_text.contains("0x10100") {
|
||||
println!("cargo:rustc-cfg=ossl110");
|
||||
println!("cargo:is_110=1");
|
||||
} else {
|
||||
panic!("
|
||||
|
||||
This crate is only compatible with OpenSSL 1.0.1, 1.0.2, and 1.1.0, but a
|
||||
different version of OpenSSL was found:
|
||||
|
||||
{}
|
||||
|
||||
The build is now aborting due to this version mismatch.
|
||||
|
||||
", version_text);
|
||||
}
|
||||
|
||||
// OpenSSL has a number of build-time configuration options which affect
|
||||
// various structs and such. Since OpenSSL 1.1.0 this isn't really a problem
|
||||
// as the library is much more FFI-friendly, but 1.0.{1,2} suffer this problem.
|
||||
//
|
||||
// To handle all this conditional compilation we slurp up the configuration
|
||||
// file of OpenSSL, `opensslconf.h`, and then dump out everything it defines
|
||||
// as our own #[cfg] directives. That way the `ossl10x.rs` bindings can
|
||||
// account for compile differences and such.
|
||||
if version_text.contains("0x1000") {
|
||||
let mut conf_header = String::new();
|
||||
let mut include = include_dirs.iter()
|
||||
.map(|p| p.join("openssl/opensslconf.h"))
|
||||
.filter(|p| p.exists());
|
||||
let mut f = match include.next() {
|
||||
Some(f) => File::open(f).unwrap(),
|
||||
None => {
|
||||
// It's been seen that on linux the include dir printed out by
|
||||
// `pkg-config` doesn't actually have opensslconf.h. Instead
|
||||
// it's in an architecture-specific include directory.
|
||||
//
|
||||
// Try to detect that case to see if it exists.
|
||||
let mut libdirs = libdirs.iter().map(|p| {
|
||||
p.iter()
|
||||
.map(|p| if p == "lib" {"include".as_ref()} else {p})
|
||||
.collect::<PathBuf>()
|
||||
}).map(|p| {
|
||||
p.join("openssl/opensslconf.h")
|
||||
}).filter(|p| p.exists());
|
||||
match libdirs.next() {
|
||||
Some(f) => File::open(f).unwrap(),
|
||||
None => {
|
||||
panic!("failed to open header file at
|
||||
`openssl/opensslconf.h` to learn about \
|
||||
OpenSSL's version number, looked \
|
||||
inside:\n\n{:#?}\n\n",
|
||||
include_dirs);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
f.read_to_string(&mut conf_header).unwrap();
|
||||
|
||||
// Look for `#define OPENSSL_FOO`, print out everything as our own
|
||||
// #[cfg] flag.
|
||||
for line in conf_header.lines() {
|
||||
let i = match line.find("define ") {
|
||||
Some(i) => i,
|
||||
None => continue,
|
||||
};
|
||||
let var = line[i + "define ".len()..].trim();
|
||||
if var.starts_with("OPENSSL") && !var.contains(" ") {
|
||||
println!("cargo:rustc-cfg=osslconf=\"{}\"", var);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return version_text.to_string()
|
||||
}
|
||||
|
||||
/// Given a libdir for OpenSSL (where artifacts are located) as well as the name
|
||||
/// of the libraries we're linking to, figure out whether we should link them
|
||||
/// statically or dynamically.
|
||||
fn determine_mode(libdir: &Path, libs: &[&str]) -> &'static str {
|
||||
// First see if a mode was explicitly requested
|
||||
let kind = env::var("OPENSSL_STATIC").ok();
|
||||
match kind.as_ref().map(|s| &s[..]) {
|
||||
Some("0") => return "dylib",
|
||||
Some(_) => return "static",
|
||||
None => {}
|
||||
}
|
||||
|
||||
// Next, see what files we actually have to link against, and see what our
|
||||
// possibilities even are.
|
||||
let files = libdir.read_dir().unwrap()
|
||||
.map(|e| e.unwrap())
|
||||
.map(|e| e.file_name())
|
||||
.filter_map(|e| e.into_string().ok())
|
||||
.collect::<HashSet<_>>();
|
||||
let can_static = libs.iter().all(|l| {
|
||||
files.contains(&format!("lib{}.a", l)) ||
|
||||
files.contains(&format!("{}.lib", l))
|
||||
});
|
||||
let can_dylib = libs.iter().all(|l| {
|
||||
files.contains(&format!("lib{}.so", l)) ||
|
||||
files.contains(&format!("{}.dll", l)) ||
|
||||
files.contains(&format!("lib{}.dylib", l))
|
||||
});
|
||||
match (can_static, can_dylib) {
|
||||
(true, false) => return "static",
|
||||
(false, true) => return "dylib",
|
||||
(false, false) => {
|
||||
panic!("OpenSSL libdir at `{}` does not contain the required files \
|
||||
to either statically or dynamically link OpenSSL",
|
||||
libdir.display());
|
||||
}
|
||||
(true, true) => {}
|
||||
}
|
||||
|
||||
// Ok, we've got not explicit preference and can *either* link statically or
|
||||
// link dynamically. In the interest of "security upgrades" and/or "best
|
||||
// practices with security libs", let's link dynamically.
|
||||
"dylib"
|
||||
};
|
||||
|
||||
if let Some(lib_dir) = lib_dir {
|
||||
println!("cargo:rustc-link-search=native={}", lib_dir);
|
||||
}
|
||||
|
||||
for lib in libs {
|
||||
println!("cargo:rustc-link-lib={}={}", mode, lib);
|
||||
}
|
||||
|
||||
if let Some(include_dir) = include_dir {
|
||||
println!("cargo:include={}", include_dir);
|
||||
}
|
||||
}
|
||||
|
||||
fn get_mingw_in_path() -> Option<Vec<String>> {
|
||||
match env::var_os("PATH") {
|
||||
Some(env_path) => {
|
||||
let paths: Vec<String> = env::split_paths(&env_path).filter_map(|path| {
|
||||
use std::ascii::AsciiExt;
|
||||
|
||||
match path.to_str() {
|
||||
Some(path_str) => {
|
||||
if path_str.to_ascii_lowercase().contains("mingw") {
|
||||
Some(path_str.to_string())
|
||||
} else { None }
|
||||
},
|
||||
None => None
|
||||
}
|
||||
}).collect();
|
||||
|
||||
if paths.len() > 0 { Some(paths) } else { None }
|
||||
},
|
||||
None => None
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,569 @@
|
|||
use std::sync::{Mutex, MutexGuard};
|
||||
use std::sync::{Once, ONCE_INIT};
|
||||
use std::mem;
|
||||
|
||||
use libc::{c_int, c_char, c_void, c_long, c_uchar, size_t, c_uint, c_ulong};
|
||||
|
||||
#[repr(C)]
|
||||
pub struct stack_st_X509 {
|
||||
pub stack: _STACK,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct stack_st_X509_ATTRIBUTE {
|
||||
pub stack: _STACK,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct stack_st_X509_EXTENSION {
|
||||
pub stack: _STACK,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct stack_st_GENERAL_NAME {
|
||||
pub stack: _STACK,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct stack_st_void {
|
||||
pub stack: _STACK,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct _STACK {
|
||||
pub num: c_int,
|
||||
pub data: *mut *mut c_char,
|
||||
pub sorted: c_int,
|
||||
pub num_alloc: c_int,
|
||||
pub comp: Option<unsafe extern fn(*const c_void, *const c_void) -> c_int>,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct BIO_METHOD {
|
||||
pub type_: c_int,
|
||||
pub name: *const c_char,
|
||||
pub bwrite: Option<unsafe extern fn(*mut ::BIO, *const c_char, c_int) -> c_int>,
|
||||
pub bread: Option<unsafe extern fn(*mut ::BIO, *mut c_char, c_int) -> c_int>,
|
||||
pub bputs: Option<unsafe extern fn(*mut ::BIO, *const c_char) -> c_int>,
|
||||
pub bgets: Option<unsafe extern fn(*mut ::BIO, *mut c_char, c_int) -> c_int>,
|
||||
pub ctrl: Option<unsafe extern fn(*mut ::BIO, c_int, c_long, *mut c_void) -> c_long>,
|
||||
pub create: Option<unsafe extern fn(*mut ::BIO) -> c_int>,
|
||||
pub destroy: Option<unsafe extern fn(*mut ::BIO) -> c_int>,
|
||||
pub callback_ctrl: Option<unsafe extern fn(*mut ::BIO, c_int, ::bio_info_cb) -> c_long>,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct RSA {
|
||||
pub pad: c_int,
|
||||
pub version: c_long,
|
||||
pub meth: *const ::RSA_METHOD,
|
||||
|
||||
pub engine: *mut ::ENGINE,
|
||||
pub n: *mut ::BIGNUM,
|
||||
pub e: *mut ::BIGNUM,
|
||||
pub d: *mut ::BIGNUM,
|
||||
pub p: *mut ::BIGNUM,
|
||||
pub q: *mut ::BIGNUM,
|
||||
pub dmp1: *mut ::BIGNUM,
|
||||
pub dmq1: *mut ::BIGNUM,
|
||||
pub iqmp: *mut ::BIGNUM,
|
||||
|
||||
pub ex_data: ::CRYPTO_EX_DATA,
|
||||
pub references: c_int,
|
||||
pub flags: c_int,
|
||||
|
||||
pub _method_mod_n: *mut ::BN_MONT_CTX,
|
||||
pub _method_mod_p: *mut ::BN_MONT_CTX,
|
||||
pub _method_mod_q: *mut ::BN_MONT_CTX,
|
||||
|
||||
pub bignum_data: *mut c_char,
|
||||
pub blinding: *mut ::BN_BLINDING,
|
||||
pub mt_blinding: *mut ::BN_BLINDING,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct DSA {
|
||||
pub pad: c_int,
|
||||
pub version: c_long,
|
||||
pub write_params: c_int,
|
||||
|
||||
pub p: *mut ::BIGNUM,
|
||||
pub q: *mut ::BIGNUM,
|
||||
pub g: *mut ::BIGNUM,
|
||||
pub pub_key: *mut ::BIGNUM,
|
||||
pub priv_key: *mut ::BIGNUM,
|
||||
pub kinv: *mut ::BIGNUM,
|
||||
pub r: *mut ::BIGNUM,
|
||||
|
||||
pub flags: c_int,
|
||||
pub method_mont_p: *mut ::BN_MONT_CTX,
|
||||
pub references: c_int,
|
||||
pub ex_data: ::CRYPTO_EX_DATA,
|
||||
pub meth: *const ::DSA_METHOD,
|
||||
pub engine: *mut ::ENGINE,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct EVP_PKEY {
|
||||
pub type_: c_int,
|
||||
pub save_type: c_int,
|
||||
pub references: c_int,
|
||||
pub ameth: *const ::EVP_PKEY_ASN1_METHOD,
|
||||
pub engine: *mut ::ENGINE,
|
||||
pub pkey: *mut c_void,
|
||||
pub save_parameters: c_int,
|
||||
pub attributes: *mut stack_st_X509_ATTRIBUTE,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct BIO {
|
||||
pub method: *mut ::BIO_METHOD,
|
||||
pub callback: Option<unsafe extern fn(*mut ::BIO,
|
||||
c_int,
|
||||
*const c_char,
|
||||
c_int,
|
||||
c_long,
|
||||
c_long)
|
||||
-> c_long>,
|
||||
pub cb_arg: *mut c_char,
|
||||
pub init: c_int,
|
||||
pub shutdown: c_int,
|
||||
pub flags: c_int,
|
||||
pub retry_reason: c_int,
|
||||
pub num: c_int,
|
||||
pub ptr: *mut c_void,
|
||||
pub next_bio: *mut ::BIO,
|
||||
pub prev_bio: *mut ::BIO,
|
||||
pub references: c_int,
|
||||
pub num_read: c_ulong,
|
||||
pub num_write: c_ulong,
|
||||
pub ex_data: ::CRYPTO_EX_DATA,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct CRYPTO_EX_DATA {
|
||||
pub sk: *mut ::stack_st_void,
|
||||
pub dummy: c_int,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct EVP_MD_CTX {
|
||||
digest: *mut ::EVP_MD,
|
||||
engine: *mut ::ENGINE,
|
||||
flags: c_ulong,
|
||||
md_data: *mut c_void,
|
||||
pctx: *mut ::EVP_PKEY_CTX,
|
||||
update: *mut c_void
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct EVP_CIPHER {
|
||||
pub nid: c_int,
|
||||
pub block_size: c_int,
|
||||
pub key_len: c_int,
|
||||
pub iv_len: c_int,
|
||||
pub flags: c_ulong,
|
||||
pub init: Option<unsafe extern fn(*mut ::EVP_CIPHER_CTX,
|
||||
*const c_uchar,
|
||||
*const c_uchar,
|
||||
c_int) -> c_int>,
|
||||
pub do_cipher: Option<unsafe extern fn(*mut ::EVP_CIPHER_CTX,
|
||||
*mut c_uchar,
|
||||
*const c_uchar,
|
||||
size_t) -> c_int>,
|
||||
pub cleanup: Option<unsafe extern fn(*mut ::EVP_CIPHER_CTX) -> c_int>,
|
||||
pub ctx_size: c_int,
|
||||
pub set_asn1_parameters: Option<unsafe extern fn(*mut ::EVP_CIPHER_CTX,
|
||||
*mut ::ASN1_TYPE) -> c_int>,
|
||||
pub get_asn1_parameters: Option<unsafe extern fn(*mut ::EVP_CIPHER_CTX,
|
||||
*mut ::ASN1_TYPE) -> c_int>,
|
||||
pub ctrl: Option<unsafe extern fn(*mut ::EVP_CIPHER_CTX,
|
||||
c_int,
|
||||
c_int,
|
||||
*mut c_void) -> c_int>,
|
||||
pub app_data: *mut c_void,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct HMAC_CTX {
|
||||
md: *mut ::EVP_MD,
|
||||
md_ctx: ::EVP_MD_CTX,
|
||||
i_ctx: ::EVP_MD_CTX,
|
||||
o_ctx: ::EVP_MD_CTX,
|
||||
key_length: c_uint,
|
||||
key: [c_uchar; 128]
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct BIGNUM {
|
||||
pub d: *mut ::BN_ULONG,
|
||||
pub top: c_int,
|
||||
pub dmax: c_int,
|
||||
pub neg: c_int,
|
||||
pub flags: c_int,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct DH {
|
||||
pub pad: c_int,
|
||||
pub version: c_int,
|
||||
pub p: *mut ::BIGNUM,
|
||||
pub g: *mut ::BIGNUM,
|
||||
pub length: c_long,
|
||||
pub pub_key: *mut ::BIGNUM,
|
||||
pub priv_key: *mut ::BIGNUM,
|
||||
pub flags: c_int,
|
||||
pub method_mont_p: *mut ::BN_MONT_CTX,
|
||||
pub q: *mut ::BIGNUM,
|
||||
pub j: *mut ::BIGNUM,
|
||||
pub seed: *mut c_uchar,
|
||||
pub seedlen: c_int,
|
||||
pub counter: *mut ::BIGNUM,
|
||||
pub references: c_int,
|
||||
pub ex_data: ::CRYPTO_EX_DATA,
|
||||
pub meth: *const ::DH_METHOD,
|
||||
pub engine: *mut ::ENGINE,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct X509 {
|
||||
pub cert_info: *mut X509_CINF,
|
||||
sig_alg: *mut c_void,
|
||||
signature: *mut c_void,
|
||||
pub valid: c_int,
|
||||
pub references: c_int,
|
||||
pub name: *mut c_char,
|
||||
pub ex_data: ::CRYPTO_EX_DATA,
|
||||
pub ex_pathlen: c_long,
|
||||
pub ex_pcpathlen: c_long,
|
||||
pub ex_flags: c_ulong,
|
||||
pub ex_kusage: c_ulong,
|
||||
pub ex_xkusage: c_ulong,
|
||||
pub ex_nscert: c_ulong,
|
||||
skid: *mut c_void,
|
||||
akid: *mut c_void,
|
||||
policy_cache: *mut c_void,
|
||||
crldp: *mut c_void,
|
||||
altname: *mut c_void,
|
||||
nc: *mut c_void,
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_RFC3779"))]
|
||||
rfc3779_addr: *mut c_void,
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_RFC3779"))]
|
||||
rfc3779_asid: *mut c_void,
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_SHA"))]
|
||||
sha1_hash: [c_uchar; 20],
|
||||
aux: *mut c_void,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct X509_CINF {
|
||||
version: *mut c_void,
|
||||
serialNumber: *mut c_void,
|
||||
signature: *mut c_void,
|
||||
issuer: *mut c_void,
|
||||
pub validity: *mut X509_VAL,
|
||||
subject: *mut c_void,
|
||||
key: *mut c_void,
|
||||
issuerUID: *mut c_void,
|
||||
subjectUID: *mut c_void,
|
||||
pub extensions: *mut stack_st_X509_EXTENSION,
|
||||
enc: ASN1_ENCODING,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct ASN1_ENCODING {
|
||||
pub enc: *mut c_uchar,
|
||||
pub len: c_long,
|
||||
pub modified: c_int,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct X509_VAL {
|
||||
pub notBefore: *mut ::ASN1_TIME,
|
||||
pub notAfter: *mut ::ASN1_TIME,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct SSL_CTX {
|
||||
method: *mut c_void,
|
||||
cipher_list: *mut c_void,
|
||||
cipher_list_by_id: *mut c_void,
|
||||
cert_store: *mut c_void,
|
||||
sessions: *mut c_void,
|
||||
session_cache_size: c_ulong,
|
||||
session_cache_head: *mut c_void,
|
||||
session_cache_tail: *mut c_void,
|
||||
session_cache_mode: c_int,
|
||||
session_timeout: c_long,
|
||||
new_session_cb: *mut c_void,
|
||||
remove_session_cb: *mut c_void,
|
||||
get_session_cb: *mut c_void,
|
||||
stats: [c_int; 11],
|
||||
pub references: c_int,
|
||||
app_verify_callback: *mut c_void,
|
||||
app_verify_arg: *mut c_void,
|
||||
default_passwd_callback: *mut c_void,
|
||||
default_passwd_callback_userdata: *mut c_void,
|
||||
client_cert_cb: *mut c_void,
|
||||
app_gen_cookie_cb: *mut c_void,
|
||||
app_verify_cookie_cb: *mut c_void,
|
||||
ex_dat: ::CRYPTO_EX_DATA,
|
||||
rsa_md5: *mut c_void,
|
||||
md5: *mut c_void,
|
||||
sha1: *mut c_void,
|
||||
extra_certs: *mut c_void,
|
||||
comp_methods: *mut c_void,
|
||||
info_callback: *mut c_void,
|
||||
client_CA: *mut c_void,
|
||||
options: c_ulong,
|
||||
mode: c_ulong,
|
||||
max_cert_list: c_long,
|
||||
cert: *mut c_void,
|
||||
read_ahead: c_int,
|
||||
msg_callback: *mut c_void,
|
||||
msg_callback_arg: *mut c_void,
|
||||
verify_mode: c_int,
|
||||
sid_ctx_length: c_uint,
|
||||
sid_ctx: [c_uchar; 32],
|
||||
default_verify_callback: *mut c_void,
|
||||
generate_session_id: *mut c_void,
|
||||
param: *mut c_void,
|
||||
quiet_shutdown: c_int,
|
||||
max_send_fragment: c_uint,
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_ENGINE"))]
|
||||
client_cert_engine: *mut c_void,
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_TLSEXT"))]
|
||||
tlsext_servername_callback: *mut c_void,
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_TLSEXT"))]
|
||||
tlsect_servername_arg: *mut c_void,
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_TLSEXT"))]
|
||||
tlsext_tick_key_name: [c_uchar; 16],
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_TLSEXT"))]
|
||||
tlsext_tick_hmac_key: [c_uchar; 16],
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_TLSEXT"))]
|
||||
tlsext_tick_aes_key: [c_uchar; 16],
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_TLSEXT"))]
|
||||
tlsext_ticket_key_cb: *mut c_void,
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_TLSEXT"))]
|
||||
tlsext_status_cb: *mut c_void,
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_TLSEXT"))]
|
||||
tlsext_status_arg: *mut c_void,
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_TLSEXT"))]
|
||||
tlsext_opaque_prf_input_callback: *mut c_void,
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_TLSEXT"))]
|
||||
tlsext_opaque_prf_input_callback_arg: *mut c_void,
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
|
||||
psk_identity_hint: *mut c_void,
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
|
||||
psk_client_callback: *mut c_void,
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
|
||||
psk_server_callback: *mut c_void,
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_BUF_FREELISTS"))]
|
||||
freelist_max_len: c_uint,
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_BUF_FREELISTS"))]
|
||||
wbuf_freelist: *mut c_void,
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_BUF_FREELISTS"))]
|
||||
rbuf_freelist: *mut c_void,
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_SRP"))]
|
||||
srp_ctx: SRP_CTX,
|
||||
|
||||
#[cfg(all(not(osslconf = "OPENSSL_NO_TLSEXT"), not(osslconf = "OPENSSL_NO_NEXTPROTONEG")))]
|
||||
next_protos_advertised_cb: *mut c_void,
|
||||
#[cfg(all(not(osslconf = "OPENSSL_NO_TLSEXT"), not(osslconf = "OPENSSL_NO_NEXTPROTONEG")))]
|
||||
next_protos_advertised_cb_arg: *mut c_void,
|
||||
#[cfg(all(not(osslconf = "OPENSSL_NO_TLSEXT"), not(osslconf = "OPENSSL_NO_NEXTPROTONEG")))]
|
||||
next_proto_select_cb: *mut c_void,
|
||||
#[cfg(all(not(osslconf = "OPENSSL_NO_TLSEXT"), not(osslconf = "OPENSSL_NO_NEXTPROTONEG")))]
|
||||
next_proto_select_cb_arg: *mut c_void,
|
||||
|
||||
#[cfg(all(not(osslconf = "OPENSSL_NO_TLSEXT"), ossl101))]
|
||||
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))]
|
||||
alpn_select_cb: *mut c_void,
|
||||
#[cfg(all(not(osslconf = "OPENSSL_NO_TLSEXT"), ossl102))]
|
||||
alpn_select_cb_arg: *mut c_void,
|
||||
#[cfg(all(not(osslconf = "OPENSSL_NO_TLSEXT"), ossl102))]
|
||||
alpn_client_proto_list: *mut c_void,
|
||||
#[cfg(all(not(osslconf = "OPENSSL_NO_TLSEXT"), ossl102))]
|
||||
alpn_client_proto_list_len: c_uint,
|
||||
|
||||
#[cfg(all(not(osslconf = "OPENSSL_NO_TLSEXT"), not(osslconf = "OPENSSL_NO_EC"), ossl102))]
|
||||
tlsext_ecpointformatlist_length: size_t,
|
||||
#[cfg(all(not(osslconf = "OPENSSL_NO_TLSEXT"), not(osslconf = "OPENSSL_NO_EC"), ossl102))]
|
||||
tlsext_ecpointformatlist: *mut c_uchar,
|
||||
#[cfg(all(not(osslconf = "OPENSSL_NO_TLSEXT"), not(osslconf = "OPENSSL_NO_EC"), ossl102))]
|
||||
tlsext_ellipticcurvelist_length: size_t,
|
||||
#[cfg(all(not(osslconf = "OPENSSL_NO_TLSEXT"), not(osslconf = "OPENSSL_NO_EC"), ossl102))]
|
||||
tlsext_ellipticcurvelist: *mut c_uchar,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct SRP_CTX {
|
||||
SRP_cb_arg: *mut c_void,
|
||||
TLS_ext_srp_username_callback: *mut c_void,
|
||||
SRP_verify_param_callback: *mut c_void,
|
||||
SRP_give_srp_client_pwd_callback: *mut c_void,
|
||||
login: *mut c_void,
|
||||
N: *mut c_void,
|
||||
g: *mut c_void,
|
||||
s: *mut c_void,
|
||||
B: *mut c_void,
|
||||
A: *mut c_void,
|
||||
a: *mut c_void,
|
||||
b: *mut c_void,
|
||||
v: *mut c_void,
|
||||
info: *mut c_void,
|
||||
stringth: c_int,
|
||||
srp_Mask: c_ulong,
|
||||
}
|
||||
|
||||
pub const SSL_CTRL_OPTIONS: c_int = 32;
|
||||
pub const SSL_CTRL_CLEAR_OPTIONS: c_int = 77;
|
||||
#[cfg(ossl102)]
|
||||
pub const SSL_CTRL_SET_ECDH_AUTO: c_int = 94;
|
||||
|
||||
pub const SSL_OP_MICROSOFT_SESS_ID_BUG: c_ulong = 0x00000001;
|
||||
pub const SSL_OP_NETSCAPE_CHALLENGE_BUG: c_ulong = 0x00000002;
|
||||
pub const SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG: c_ulong = 0x00000008;
|
||||
pub const SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER: c_ulong = 0x00000020;
|
||||
pub const SSL_OP_SSLEAY_080_CLIENT_DH_BUG: c_ulong = 0x00000080;
|
||||
pub const SSL_OP_TLS_D5_BUG: c_ulong = 0x00000100;
|
||||
pub const SSL_OP_TLS_BLOCK_PADDING_BUG: c_ulong = 0x00000200;
|
||||
pub const SSL_OP_SINGLE_ECDH_USE: c_ulong = 0x00080000;
|
||||
pub const SSL_OP_SINGLE_DH_USE: c_ulong = 0x00100000;
|
||||
pub const SSL_OP_NO_SSLv2: c_ulong = 0x01000000;
|
||||
|
||||
pub const SSLEAY_VERSION : c_int = 0;
|
||||
pub const SSLEAY_CFLAGS : c_int = 2;
|
||||
pub const SSLEAY_BUILT_ON : c_int = 3;
|
||||
pub const SSLEAY_PLATFORM : c_int = 4;
|
||||
pub const SSLEAY_DIR : c_int = 5;
|
||||
|
||||
pub const CRYPTO_LOCK_X509: c_int = 3;
|
||||
pub const CRYPTO_LOCK_SSL_CTX: c_int = 12;
|
||||
|
||||
static mut MUTEXES: *mut Vec<Mutex<()>> = 0 as *mut Vec<Mutex<()>>;
|
||||
static mut GUARDS: *mut Vec<Option<MutexGuard<'static, ()>>> = 0 as *mut Vec<Option<MutexGuard<'static, ()>>>;
|
||||
|
||||
unsafe extern fn locking_function(mode: c_int, n: c_int, _file: *const c_char,
|
||||
_line: c_int) {
|
||||
let mutex = &(*MUTEXES)[n as usize];
|
||||
|
||||
if mode & ::CRYPTO_LOCK != 0 {
|
||||
(*GUARDS)[n as usize] = Some(mutex.lock().unwrap());
|
||||
} else {
|
||||
&(*GUARDS)[n as usize].take();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init() {
|
||||
static INIT: Once = ONCE_INIT;
|
||||
|
||||
INIT.call_once(|| {
|
||||
unsafe {
|
||||
SSL_library_init();
|
||||
SSL_load_error_strings();
|
||||
OPENSSL_add_all_algorithms_noconf();
|
||||
|
||||
let num_locks = ::CRYPTO_num_locks();
|
||||
let mut mutexes = Box::new(Vec::new());
|
||||
for _ in 0..num_locks {
|
||||
mutexes.push(Mutex::new(()));
|
||||
}
|
||||
MUTEXES = mem::transmute(mutexes);
|
||||
let guards: Box<Vec<Option<MutexGuard<()>>>> =
|
||||
Box::new((0..num_locks).map(|_| None).collect());
|
||||
GUARDS = mem::transmute(guards);
|
||||
|
||||
CRYPTO_set_locking_callback(locking_function);
|
||||
set_id_callback();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn set_id_callback() {
|
||||
unsafe extern fn thread_id() -> c_ulong {
|
||||
::libc::pthread_self() as c_ulong
|
||||
}
|
||||
|
||||
unsafe {
|
||||
CRYPTO_set_id_callback(thread_id);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
fn set_id_callback() {}
|
||||
|
||||
extern {
|
||||
pub fn BIO_new(type_: *mut BIO_METHOD) -> *mut BIO;
|
||||
pub fn BIO_s_file() -> *mut BIO_METHOD;
|
||||
pub fn BIO_s_mem() -> *mut BIO_METHOD;
|
||||
pub fn CRYPTO_free(buf: *mut c_void);
|
||||
pub fn CRYPTO_num_locks() -> c_int;
|
||||
pub fn CRYPTO_set_locking_callback(func: unsafe extern "C" fn(mode: c_int,
|
||||
n: c_int,
|
||||
file: *const c_char,
|
||||
line: c_int));
|
||||
pub fn CRYPTO_set_id_callback(func: unsafe extern "C" fn() -> c_ulong);
|
||||
|
||||
pub fn ERR_load_crypto_strings();
|
||||
|
||||
pub fn RSA_generate_key(modsz: c_int,
|
||||
e: c_ulong,
|
||||
cb: Option<extern fn(c_int, c_int, *mut c_void)>,
|
||||
cbarg: *mut c_void) -> *mut RSA;
|
||||
|
||||
pub fn SSL_library_init() -> c_int;
|
||||
pub fn SSL_load_error_strings();
|
||||
pub fn OPENSSL_add_all_algorithms_noconf();
|
||||
pub fn HMAC_CTX_init(ctx: *mut ::HMAC_CTX);
|
||||
pub fn HMAC_CTX_cleanup(ctx: *mut ::HMAC_CTX);
|
||||
pub fn SSLv3_method() -> *const ::SSL_METHOD;
|
||||
pub fn TLSv1_method() -> *const ::SSL_METHOD;
|
||||
pub fn SSLv23_method() -> *const ::SSL_METHOD;
|
||||
pub fn TLSv1_1_method() -> *const ::SSL_METHOD;
|
||||
pub fn TLSv1_2_method() -> *const ::SSL_METHOD;
|
||||
pub fn DTLSv1_method() -> *const ::SSL_METHOD;
|
||||
#[cfg(ossl102)]
|
||||
pub fn DTLSv1_2_method() -> *const ::SSL_METHOD;
|
||||
pub fn SSL_get_ex_new_index(argl: c_long, argp: *mut c_void,
|
||||
new_func: Option<::CRYPTO_EX_new>,
|
||||
dup_func: Option<::CRYPTO_EX_dup>,
|
||||
free_func: Option<::CRYPTO_EX_free>)
|
||||
-> c_int;
|
||||
pub fn SSL_CIPHER_get_version(cipher: *const ::SSL_CIPHER) -> *mut c_char;
|
||||
pub fn SSL_CTX_get_ex_new_index(argl: c_long, argp: *mut c_void,
|
||||
new_func: Option<::CRYPTO_EX_new>,
|
||||
dup_func: Option<::CRYPTO_EX_dup>,
|
||||
free_func: Option<::CRYPTO_EX_free>)
|
||||
-> c_int;
|
||||
pub fn X509_get_subject_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_notBefore(x: *mut ::X509, tm: *const ::ASN1_TIME) -> c_int;
|
||||
pub fn X509_get_ext_d2i(x: *mut ::X509, nid: c_int, crit: *mut c_int, idx: *mut c_int) -> *mut c_void;
|
||||
pub fn X509_NAME_get_entry(n: *mut ::X509_NAME, loc: c_int) -> *mut ::X509_NAME_ENTRY;
|
||||
pub fn X509_NAME_ENTRY_get_data(ne: *mut ::X509_NAME_ENTRY) -> *mut ::ASN1_STRING;
|
||||
pub fn ASN1_STRING_to_UTF8(out: *mut *mut c_uchar, s: *mut ::ASN1_STRING) -> c_int;
|
||||
pub fn ASN1_STRING_data(x: *mut ::ASN1_STRING) -> *mut c_uchar;
|
||||
pub fn CRYPTO_add_lock(pointer: *mut c_int,
|
||||
amount: c_int,
|
||||
type_: c_int,
|
||||
file: *const c_char,
|
||||
line: c_int) -> c_int;
|
||||
|
||||
pub fn sk_free(st: *mut _STACK);
|
||||
pub fn sk_pop_free(st: *mut _STACK, free: Option<unsafe extern "C" fn (*mut c_void)>);
|
||||
pub fn sk_pop(st: *mut _STACK) -> *mut c_void;
|
||||
|
||||
pub fn SSLeay() -> c_ulong;
|
||||
pub fn SSLeay_version(key: c_int) -> *const c_char;
|
||||
}
|
||||
|
|
@ -0,0 +1,146 @@
|
|||
use libc::{c_int, c_void, c_char, c_uchar, c_ulong, c_long};
|
||||
|
||||
pub enum stack_st_X509 {}
|
||||
pub enum stack_st_X509_ATTRIBUTE {}
|
||||
pub enum stack_st_X509_EXTENSION {}
|
||||
pub enum stack_st_GENERAL_NAME {}
|
||||
pub enum stack_st_void {}
|
||||
pub enum _STACK {}
|
||||
pub enum BIO_METHOD {}
|
||||
pub enum RSA {}
|
||||
pub enum DSA {}
|
||||
pub enum EVP_PKEY {}
|
||||
pub enum BIO {}
|
||||
pub enum CRYPTO_EX_DATA {}
|
||||
pub enum EVP_MD_CTX {}
|
||||
pub enum EVP_CIPHER {}
|
||||
pub enum HMAC_CTX {}
|
||||
pub enum BIGNUM {}
|
||||
pub enum OPENSSL_STACK {}
|
||||
pub enum DH {}
|
||||
pub enum X509 {}
|
||||
pub enum SSL_CTX {}
|
||||
|
||||
pub const SSL_OP_MICROSOFT_SESS_ID_BUG: c_ulong = 0x00000000;
|
||||
pub const SSL_OP_NETSCAPE_CHALLENGE_BUG: c_ulong = 0x00000000;
|
||||
pub const SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG: c_ulong = 0x00000000;
|
||||
pub const SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER: c_ulong = 0x00000000;
|
||||
pub const SSL_OP_SSLEAY_080_CLIENT_DH_BUG: c_ulong = 0x00000000;
|
||||
pub const SSL_OP_TLS_D5_BUG: c_ulong = 0x00000000;
|
||||
pub const SSL_OP_TLS_BLOCK_PADDING_BUG: c_ulong = 0x00000000;
|
||||
pub const SSL_OP_SINGLE_ECDH_USE: c_ulong = 0x00000000;
|
||||
pub const SSL_OP_SINGLE_DH_USE: c_ulong = 0x00000000;
|
||||
pub const SSL_OP_NO_SSLv2: c_ulong = 0x00000000;
|
||||
|
||||
pub const OPENSSL_VERSION: c_int = 0;
|
||||
pub const OPENSSL_CFLAGS: c_int = 1;
|
||||
pub const OPENSSL_BUILT_ON: c_int = 2;
|
||||
pub const OPENSSL_PLATFORM: c_int = 3;
|
||||
pub const OPENSSL_DIR: c_int = 4;
|
||||
|
||||
pub const CRYPTO_EX_INDEX_SSL: c_int = 0;
|
||||
pub const CRYPTO_EX_INDEX_SSL_CTX: c_int = 1;
|
||||
|
||||
pub fn init() {}
|
||||
|
||||
extern {
|
||||
pub fn BIO_new(type_: *const BIO_METHOD) -> *mut BIO;
|
||||
pub fn BIO_s_file() -> *const BIO_METHOD;
|
||||
pub fn BIO_s_mem() -> *const BIO_METHOD;
|
||||
pub fn CRYPTO_free(buf: *mut c_void, file: *const c_char, line: c_int);
|
||||
pub fn HMAC_CTX_new() -> *mut HMAC_CTX;
|
||||
pub fn HMAC_CTX_free(ctx: *mut HMAC_CTX);
|
||||
pub fn TLS_method() -> *const ::SSL_METHOD;
|
||||
pub fn DTLS_method() -> *const ::SSL_METHOD;
|
||||
pub fn SSL_CIPHER_get_version(cipher: *const ::SSL_CIPHER) -> *const c_char;
|
||||
pub fn X509_get_subject_name(x: *const ::X509) -> *mut ::X509_NAME;
|
||||
pub fn X509_set1_notAfter(x: *mut ::X509, tm: *const ::ASN1_TIME) -> c_int;
|
||||
pub fn X509_set1_notBefore(x: *mut ::X509, tm: *const ::ASN1_TIME) -> c_int;
|
||||
pub fn X509_get_ext_d2i(x: *const ::X509, nid: c_int, crit: *mut c_int, idx: *mut c_int) -> *mut c_void;
|
||||
pub fn X509_NAME_get_entry(n: *const ::X509_NAME, loc: c_int) -> *mut ::X509_NAME_ENTRY;
|
||||
pub fn X509_NAME_ENTRY_get_data(ne: *const ::X509_NAME_ENTRY) -> *mut ::ASN1_STRING;
|
||||
pub fn ASN1_STRING_to_UTF8(out: *mut *mut c_uchar, s: *const ::ASN1_STRING) -> c_int;
|
||||
pub fn BN_is_negative(b: *const ::BIGNUM) -> c_int;
|
||||
pub fn EVP_CIPHER_key_length(cipher: *const EVP_CIPHER) -> c_int;
|
||||
pub fn EVP_CIPHER_block_size(cipher: *const EVP_CIPHER) -> c_int;
|
||||
pub fn EVP_CIPHER_iv_length(cipher: *const EVP_CIPHER) -> c_int;
|
||||
pub fn DSA_get0_pqg(d: *const ::DSA,
|
||||
p: *mut *const ::BIGNUM,
|
||||
q: *mut *const ::BIGNUM,
|
||||
q: *mut *const ::BIGNUM);
|
||||
pub fn DSA_get0_key(d: *const ::DSA,
|
||||
pub_key: *mut *const ::BIGNUM,
|
||||
priv_key: *mut *const ::BIGNUM);
|
||||
pub fn RSA_get0_key(r: *const ::RSA,
|
||||
n: *mut *const ::BIGNUM,
|
||||
e: *mut *const ::BIGNUM,
|
||||
d: *mut *const ::BIGNUM);
|
||||
pub fn RSA_get0_factors(r: *const ::RSA,
|
||||
p: *mut *const ::BIGNUM,
|
||||
q: *mut *const ::BIGNUM);
|
||||
pub fn RSA_set0_key(r: *mut ::RSA,
|
||||
n: *mut ::BIGNUM,
|
||||
e: *mut ::BIGNUM,
|
||||
d: *mut ::BIGNUM) -> c_int;
|
||||
pub fn RSA_set0_factors(r: *mut ::RSA,
|
||||
p: *mut ::BIGNUM,
|
||||
q: *mut ::BIGNUM) -> c_int;
|
||||
pub fn RSA_set0_crt_params(r: *mut ::RSA,
|
||||
dmp1: *mut ::BIGNUM,
|
||||
dmq1: *mut ::BIGNUM,
|
||||
iqmp: *mut ::BIGNUM) -> c_int;
|
||||
pub fn ASN1_STRING_get0_data(x: *const ::ASN1_STRING) -> *const c_uchar;
|
||||
pub fn OPENSSL_sk_num(stack: *const ::OPENSSL_STACK) -> c_int;
|
||||
pub fn OPENSSL_sk_value(stack: *const ::OPENSSL_STACK,
|
||||
idx: c_int) -> *mut c_void;
|
||||
pub fn SSL_CTX_get_options(ctx: *const ::SSL_CTX) -> c_ulong;
|
||||
pub fn SSL_CTX_set_options(ctx: *mut ::SSL_CTX, op: c_ulong) -> c_ulong;
|
||||
pub fn SSL_CTX_clear_options(ctx: *mut ::SSL_CTX, op: c_ulong) -> c_ulong;
|
||||
pub fn X509_getm_notAfter(x: *const ::X509) -> *mut ::ASN1_TIME;
|
||||
pub fn X509_getm_notBefore(x: *const ::X509) -> *mut ::ASN1_TIME;
|
||||
pub fn DH_set0_pqg(dh: *mut ::DH,
|
||||
p: *mut ::BIGNUM,
|
||||
q: *mut ::BIGNUM,
|
||||
g: *mut ::BIGNUM) -> c_int;
|
||||
pub fn BIO_set_init(a: *mut ::BIO, init: c_int);
|
||||
pub fn BIO_set_data(a: *mut ::BIO, data: *mut c_void);
|
||||
pub fn BIO_get_data(a: *mut ::BIO) -> *mut c_void;
|
||||
pub fn BIO_meth_new(type_: c_int, name: *const c_char) -> *mut ::BIO_METHOD;
|
||||
pub fn BIO_meth_free(biom: *mut ::BIO_METHOD);
|
||||
pub fn BIO_meth_set_write(biom: *mut ::BIO_METHOD,
|
||||
write: unsafe extern fn(*mut ::BIO,
|
||||
*const c_char,
|
||||
c_int) -> c_int) -> c_int;
|
||||
pub fn BIO_meth_set_read(biom: *mut ::BIO_METHOD,
|
||||
read: unsafe extern fn(*mut ::BIO,
|
||||
*mut c_char,
|
||||
c_int) -> c_int) -> c_int;
|
||||
pub fn BIO_meth_set_puts(biom: *mut ::BIO_METHOD,
|
||||
read: unsafe extern fn(*mut ::BIO,
|
||||
*const c_char) -> c_int) -> c_int;
|
||||
pub fn BIO_meth_set_ctrl(biom: *mut ::BIO_METHOD,
|
||||
read: unsafe extern fn(*mut ::BIO,
|
||||
c_int,
|
||||
c_long,
|
||||
*mut c_void) -> c_long) -> c_int;
|
||||
pub fn BIO_meth_set_create(biom: *mut ::BIO_METHOD,
|
||||
create: unsafe extern fn(*mut ::BIO) -> c_int) -> c_int;
|
||||
pub fn BIO_meth_set_destroy(biom: *mut ::BIO_METHOD,
|
||||
destroy: unsafe extern fn(*mut ::BIO) -> c_int) -> c_int;
|
||||
pub fn CRYPTO_get_ex_new_index(class_index: c_int,
|
||||
argl: c_long,
|
||||
argp: *mut c_void,
|
||||
new_func: Option<::CRYPTO_EX_new>,
|
||||
dup_func: Option<::CRYPTO_EX_dup>,
|
||||
free_func: Option<::CRYPTO_EX_free>)
|
||||
-> c_int;
|
||||
pub fn X509_up_ref(x: *mut X509) -> c_int;
|
||||
pub fn SSL_CTX_up_ref(x: *mut SSL_CTX) -> c_int;
|
||||
pub fn X509_get0_extensions(req: *const ::X509) -> *const stack_st_X509_EXTENSION;
|
||||
|
||||
pub fn OpenSSL_version_num() -> c_ulong;
|
||||
pub fn OpenSSL_version(key: c_int) -> *const c_char;
|
||||
pub fn OPENSSL_sk_free(st: *mut _STACK);
|
||||
pub fn OPENSSL_sk_pop_free(st: *mut _STACK, free: Option<unsafe extern "C" fn (*mut c_void)>);
|
||||
pub fn OPENSSL_sk_pop(st: *mut _STACK) -> *mut c_void;
|
||||
}
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
use std::env;
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub struct ProbeResult {
|
||||
pub cert_file: Option<PathBuf>,
|
||||
pub cert_dir: Option<PathBuf>,
|
||||
}
|
||||
|
||||
/// Probe the system for the directory in which CA certificates should likely be
|
||||
/// found.
|
||||
///
|
||||
/// This will only search known system locations.
|
||||
pub fn find_certs_dirs() -> Vec<PathBuf> {
|
||||
// see http://gagravarr.org/writing/openssl-certs/others.shtml
|
||||
[
|
||||
"/var/ssl",
|
||||
"/usr/share/ssl",
|
||||
"/usr/local/ssl",
|
||||
"/usr/local/openssl",
|
||||
"/usr/local/share",
|
||||
"/usr/lib/ssl",
|
||||
"/usr/ssl",
|
||||
"/etc/openssl",
|
||||
"/etc/pki/tls",
|
||||
"/etc/ssl",
|
||||
].iter().map(|s| PathBuf::from(*s)).filter(|p| {
|
||||
fs::metadata(p).is_ok()
|
||||
}).collect()
|
||||
}
|
||||
|
||||
pub fn init_ssl_cert_env_vars() {
|
||||
let ProbeResult { cert_file, cert_dir } = probe();
|
||||
match cert_file {
|
||||
Some(path) => put("SSL_CERT_FILE", path),
|
||||
None => {}
|
||||
}
|
||||
match cert_dir {
|
||||
Some(path) => put("SSL_CERT_DIR", path),
|
||||
None => {}
|
||||
}
|
||||
|
||||
fn put(var: &str, path: PathBuf) {
|
||||
// Don't stomp over what anyone else has set
|
||||
match env::var(var) {
|
||||
Ok(..) => {}
|
||||
Err(..) => env::set_var(var, &path),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn probe() -> ProbeResult {
|
||||
let mut result = ProbeResult {
|
||||
cert_file: env::var_os("SSL_CERT_FILE").map(PathBuf::from),
|
||||
cert_dir: env::var_os("SSL_CERT_DIR").map(PathBuf::from),
|
||||
};
|
||||
for certs_dir in find_certs_dirs().iter() {
|
||||
// cert.pem looks to be an openssl 1.0.1 thing, while
|
||||
// certs/ca-certificates.crt appears to be a 0.9.8 thing
|
||||
for cert in [
|
||||
"cert.pem",
|
||||
"certs.pem",
|
||||
"certs/ca-certificates.crt",
|
||||
"certs/ca-root-nss.crt"
|
||||
].iter() {
|
||||
try(&mut result.cert_file, certs_dir.join(cert));
|
||||
}
|
||||
try(&mut result.cert_dir, certs_dir.join("certs"));
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
fn try(dst: &mut Option<PathBuf>, val: PathBuf) {
|
||||
if dst.is_none() && fs::metadata(&val).is_ok() {
|
||||
*dst = Some(val);
|
||||
}
|
||||
}
|
||||
|
|
@ -12,28 +12,23 @@ build = "build.rs"
|
|||
exclude = ["test/*"]
|
||||
|
||||
[features]
|
||||
tlsv1_2 = ["openssl-sys/tlsv1_2"]
|
||||
tlsv1_1 = ["openssl-sys/tlsv1_1"]
|
||||
dtlsv1 = ["openssl-sys/dtlsv1"]
|
||||
dtlsv1_2 = ["openssl-sys/dtlsv1_2"]
|
||||
sslv2 = ["openssl-sys/sslv2"]
|
||||
sslv3 = ["openssl-sys/sslv3"]
|
||||
aes_xts = ["openssl-sys/aes_xts"]
|
||||
aes_ctr = ["openssl-sys/aes_ctr"]
|
||||
npn = ["openssl-sys/npn"]
|
||||
alpn = ["openssl-sys/alpn"]
|
||||
rfc5114 = ["openssl-sys/rfc5114"]
|
||||
ecdh_auto = ["openssl-sys/ecdh_auto"]
|
||||
pkcs5_pbkdf2_hmac = ["openssl-sys/pkcs5_pbkdf2_hmac"]
|
||||
hmac_clone = ["openssl-sys/hmac_clone"]
|
||||
aes_xts = []
|
||||
aes_ctr = []
|
||||
|
||||
c_helpers = ["gcc"]
|
||||
x509_clone = ["c_helpers"]
|
||||
x509_generator_request = ["c_helpers"]
|
||||
x509_expiry = ["c_helpers"]
|
||||
ssl_context_clone = ["c_helpers"]
|
||||
hmac = ["c_helpers"]
|
||||
dh_from_params = ["c_helpers"]
|
||||
# Added in OpenSSL 1.0.2
|
||||
rfc5114 = []
|
||||
|
||||
# TODO: what to do about these features?
|
||||
# tlsv1_2 = []
|
||||
# tlsv1_1 = []
|
||||
# dtlsv1 = []
|
||||
# dtlsv1_2 = []
|
||||
# sslv2 = []
|
||||
# sslv3 = []
|
||||
|
||||
npn = []
|
||||
alpn = []
|
||||
ecdh_auto = []
|
||||
|
||||
[dependencies]
|
||||
bitflags = "0.7"
|
||||
|
|
@ -41,11 +36,9 @@ lazy_static = "0.2"
|
|||
libc = "0.2"
|
||||
openssl-sys = { version = "0.7.17", path = "../openssl-sys" }
|
||||
|
||||
[build-dependencies]
|
||||
gcc = { version = "0.3", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
rustc-serialize = "0.3"
|
||||
net2 = "0.2.16"
|
||||
rustc-serialize = "0.3"
|
||||
tempdir = "0.3"
|
||||
winapi = "0.2"
|
||||
ws2_32-sys = "0.2"
|
||||
|
|
|
|||
|
|
@ -1,28 +1,15 @@
|
|||
#[cfg(feature = "c_helpers")]
|
||||
mod imp {
|
||||
extern crate gcc;
|
||||
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub fn main() {
|
||||
let mut config = gcc::Config::new();
|
||||
|
||||
if let Some(paths) = env::var_os("DEP_OPENSSL_INCLUDE") {
|
||||
for path in env::split_paths(&paths) {
|
||||
config.include(PathBuf::from(path));
|
||||
}
|
||||
}
|
||||
|
||||
config.file("src/c_helpers.c").compile("libc_helpers.a");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "c_helpers"))]
|
||||
mod imp {
|
||||
pub fn main() {}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
imp::main()
|
||||
if env::var("DEP_OPENSSL_IS_101").is_ok() {
|
||||
println!("cargo:rustc-cfg=ossl101");
|
||||
println!("cargo:rustc-cfg=ossl10x");
|
||||
}
|
||||
if env::var("DEP_OPENSSL_IS_102").is_ok() {
|
||||
println!("cargo:rustc-cfg=ossl102");
|
||||
println!("cargo:rustc-cfg=ossl10x");
|
||||
}
|
||||
if env::var("DEP_OPENSSL_IS_110").is_ok() {
|
||||
println!("cargo:rustc-cfg=ossl110");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use libc::{c_int, c_ulong, c_void};
|
||||
use libc::{c_int, c_void};
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::cmp::Ordering;
|
||||
use std::{fmt, ptr};
|
||||
|
|
@ -185,10 +185,11 @@ impl<'a> BigNumRef<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Add an `unsigned long` to `self`. This is more efficient than adding a `BigNum`.
|
||||
pub fn add_word(&mut self, w: c_ulong) -> Result<(), ErrorStack> {
|
||||
/// Add a `u32` to `self`. This is more efficient than adding a
|
||||
/// `BigNum`.
|
||||
pub fn add_word(&mut self, w: u32) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
if ffi::BN_add_word(self.as_ptr(), w) == 1 {
|
||||
if ffi::BN_add_word(self.as_ptr(), w as ffi::BN_ULONG) == 1 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ErrorStack::get())
|
||||
|
|
@ -196,9 +197,9 @@ impl<'a> BigNumRef<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn sub_word(&mut self, w: c_ulong) -> Result<(), ErrorStack> {
|
||||
pub fn sub_word(&mut self, w: u32) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
if ffi::BN_sub_word(self.as_ptr(), w) == 1 {
|
||||
if ffi::BN_sub_word(self.as_ptr(), w as ffi::BN_ULONG) == 1 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ErrorStack::get())
|
||||
|
|
@ -206,9 +207,9 @@ impl<'a> BigNumRef<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn mul_word(&mut self, w: c_ulong) -> Result<(), ErrorStack> {
|
||||
pub fn mul_word(&mut self, w: u32) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
if ffi::BN_mul_word(self.as_ptr(), w) == 1 {
|
||||
if ffi::BN_mul_word(self.as_ptr(), w as ffi::BN_ULONG) == 1 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ErrorStack::get())
|
||||
|
|
@ -216,22 +217,22 @@ impl<'a> BigNumRef<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn div_word(&mut self, w: c_ulong) -> Result<c_ulong, ErrorStack> {
|
||||
pub fn div_word(&mut self, w: u32) -> Result<u64, ErrorStack> {
|
||||
unsafe {
|
||||
let result = ffi::BN_div_word(self.as_ptr(), w);
|
||||
if result != !0 as c_ulong {
|
||||
Ok(result)
|
||||
let result = ffi::BN_div_word(self.as_ptr(), w as ffi::BN_ULONG);
|
||||
if result != !0 {
|
||||
Ok(result.into())
|
||||
} else {
|
||||
Err(ErrorStack::get())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mod_word(&self, w: c_ulong) -> Result<c_ulong, ErrorStack> {
|
||||
pub fn mod_word(&self, w: u32) -> Result<u64, ErrorStack> {
|
||||
unsafe {
|
||||
let result = ffi::BN_mod_word(self.as_ptr(), w);
|
||||
if result != !0 as c_ulong {
|
||||
Ok(result)
|
||||
let result = ffi::BN_mod_word(self.as_ptr(), w as ffi::BN_ULONG);
|
||||
if result != !0 {
|
||||
Ok(result as u64)
|
||||
} else {
|
||||
Err(ErrorStack::get())
|
||||
}
|
||||
|
|
@ -257,7 +258,10 @@ impl<'a> BigNumRef<'a> {
|
|||
pub fn is_prime(&self, checks: i32) -> Result<bool, ErrorStack> {
|
||||
unsafe {
|
||||
with_ctx!(ctx, {
|
||||
Ok(ffi::BN_is_prime_ex(self.as_ptr(), checks as c_int, ctx, ptr::null()) == 1)
|
||||
Ok(ffi::BN_is_prime_ex(self.as_ptr(),
|
||||
checks as c_int,
|
||||
ctx,
|
||||
ptr::null_mut()) == 1)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -278,7 +282,7 @@ impl<'a> BigNumRef<'a> {
|
|||
checks as c_int,
|
||||
ctx,
|
||||
do_trial_division as c_int,
|
||||
ptr::null()) == 1)
|
||||
ptr::null_mut()) == 1)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -483,9 +487,19 @@ impl<'a> BigNumRef<'a> {
|
|||
}
|
||||
|
||||
pub fn is_negative(&self) -> bool {
|
||||
self._is_negative()
|
||||
}
|
||||
|
||||
#[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`.
|
||||
pub fn num_bits(&self) -> i32 {
|
||||
unsafe { ffi::BN_num_bits(self.as_ptr()) as i32 }
|
||||
|
|
@ -536,7 +550,7 @@ impl<'a> BigNumRef<'a> {
|
|||
assert!(!buf.is_null());
|
||||
let str = String::from_utf8(CStr::from_ptr(buf as *const _).to_bytes().to_vec())
|
||||
.unwrap();
|
||||
ffi::CRYPTO_free(buf as *mut c_void);
|
||||
CRYPTO_free!(buf as *mut c_void);
|
||||
str
|
||||
}
|
||||
}
|
||||
|
|
@ -555,7 +569,7 @@ impl<'a> BigNumRef<'a> {
|
|||
assert!(!buf.is_null());
|
||||
let str = String::from_utf8(CStr::from_ptr(buf as *const _).to_bytes().to_vec())
|
||||
.unwrap();
|
||||
ffi::CRYPTO_free(buf as *mut c_void);
|
||||
CRYPTO_free!(buf as *mut c_void);
|
||||
str
|
||||
}
|
||||
}
|
||||
|
|
@ -580,27 +594,27 @@ impl BigNum {
|
|||
}
|
||||
|
||||
/// Creates a new `BigNum` with the given value.
|
||||
pub fn new_from(n: c_ulong) -> Result<BigNum, ErrorStack> {
|
||||
pub fn new_from(n: u32) -> Result<BigNum, ErrorStack> {
|
||||
BigNum::new().and_then(|v| unsafe {
|
||||
try_ssl!(ffi::BN_set_word(v.as_ptr(), n));
|
||||
try_ssl!(ffi::BN_set_word(v.as_ptr(), n as ffi::BN_ULONG));
|
||||
Ok(v)
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a `BigNum` from a decimal string.
|
||||
pub fn from_dec_str(s: &str) -> Result<BigNum, ErrorStack> {
|
||||
BigNum::new().and_then(|v| unsafe {
|
||||
BigNum::new().and_then(|mut v| unsafe {
|
||||
let c_str = CString::new(s.as_bytes()).unwrap();
|
||||
try_ssl!(ffi::BN_dec2bn(&(v.0).0, c_str.as_ptr() as *const _));
|
||||
try_ssl!(ffi::BN_dec2bn(&mut (v.0).0, c_str.as_ptr() as *const _));
|
||||
Ok(v)
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a `BigNum` from a hexadecimal string.
|
||||
pub fn from_hex_str(s: &str) -> Result<BigNum, ErrorStack> {
|
||||
BigNum::new().and_then(|v| unsafe {
|
||||
BigNum::new().and_then(|mut v| unsafe {
|
||||
let c_str = CString::new(s.as_bytes()).unwrap();
|
||||
try_ssl!(ffi::BN_hex2bn(&(v.0).0, c_str.as_ptr() as *const _));
|
||||
try_ssl!(ffi::BN_hex2bn(&mut (v.0).0, c_str.as_ptr() as *const _));
|
||||
Ok(v)
|
||||
})
|
||||
}
|
||||
|
|
@ -646,7 +660,7 @@ impl BigNum {
|
|||
safe as c_int,
|
||||
add_arg,
|
||||
rem_arg,
|
||||
ptr::null()) == 1
|
||||
ptr::null_mut()) == 1
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,67 +0,0 @@
|
|||
#include <openssl/hmac.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/bn.h>
|
||||
|
||||
void rust_0_8_SSL_CTX_clone(SSL_CTX *ctx) {
|
||||
CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX);
|
||||
}
|
||||
|
||||
void rust_0_8_X509_clone(X509 *x509) {
|
||||
CRYPTO_add(&x509->references,1,CRYPTO_LOCK_X509);
|
||||
}
|
||||
|
||||
STACK_OF(X509_EXTENSION) *rust_0_8_X509_get_extensions(X509 *x) {
|
||||
return x->cert_info ? x->cert_info->extensions : NULL;
|
||||
}
|
||||
|
||||
ASN1_TIME* rust_0_8_X509_get_notAfter(X509 *x) {
|
||||
return X509_get_notAfter(x);
|
||||
}
|
||||
|
||||
ASN1_TIME* rust_0_8_X509_get_notBefore(X509 *x) {
|
||||
return X509_get_notBefore(x);
|
||||
}
|
||||
|
||||
DH *rust_0_8_DH_new_from_params(BIGNUM *p, BIGNUM *g, BIGNUM *q) {
|
||||
DH *dh;
|
||||
|
||||
if ((dh = DH_new()) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
dh->p = p;
|
||||
dh->g = g;
|
||||
dh->q = q;
|
||||
return dh;
|
||||
}
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10000000L
|
||||
int rust_0_8_HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int key_len, const EVP_MD *md, ENGINE *impl) {
|
||||
HMAC_Init_ex(ctx, key, key_len, md, impl);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int rust_0_8_HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, int len) {
|
||||
HMAC_Update(ctx, data, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int rust_0_8_HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len) {
|
||||
HMAC_Final(ctx, md, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int rust_0_8_HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int key_len, const EVP_MD *md, ENGINE *impl) {
|
||||
return HMAC_Init_ex(ctx, key, key_len, md, impl);
|
||||
}
|
||||
|
||||
int rust_0_8_HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, int len) {
|
||||
return HMAC_Update(ctx, data, len);
|
||||
}
|
||||
|
||||
int rust_0_8_HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len) {
|
||||
return HMAC_Final(ctx, md, len);
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
use ffi;
|
||||
use libc::{c_int, c_void, c_uint, c_uchar};
|
||||
|
||||
#[allow(dead_code)]
|
||||
extern "C" {
|
||||
pub fn rust_0_8_SSL_CTX_clone(cxt: *mut ffi::SSL_CTX);
|
||||
pub fn rust_0_8_X509_clone(x509: *mut ffi::X509);
|
||||
pub fn rust_0_8_X509_get_extensions(x: *mut ffi::X509) -> *mut ffi::stack_st_X509_EXTENSION;
|
||||
pub fn rust_0_8_X509_get_notAfter(x: *mut ffi::X509) -> *mut ffi::ASN1_TIME;
|
||||
pub fn rust_0_8_X509_get_notBefore(x: *mut ffi::X509) -> *mut ffi::ASN1_TIME;
|
||||
pub fn rust_0_8_HMAC_Init_ex(ctx: *mut ffi::HMAC_CTX, key: *const c_void, keylen: c_int, md: *const ffi::EVP_MD, impl_: *mut ffi::ENGINE) -> c_int;
|
||||
pub fn rust_0_8_HMAC_Final(ctx: *mut ffi::HMAC_CTX, output: *mut c_uchar, len: *mut c_uint) -> c_int;
|
||||
pub fn rust_0_8_HMAC_Update(ctx: *mut ffi::HMAC_CTX, input: *const c_uchar, len: c_uint) -> c_int;
|
||||
pub fn rust_0_8_DH_new_from_params(p: *mut ffi::BIGNUM, g: *mut ffi::BIGNUM, q: *mut ffi::BIGNUM) -> *mut ffi::DH;
|
||||
}
|
||||
|
|
@ -19,8 +19,13 @@ impl DSAParams {
|
|||
unsafe {
|
||||
// Wrap it so that if we panic we'll call the dtor
|
||||
let dsa = DSAParams(try_ssl_null!(ffi::DSA_new()));
|
||||
try_ssl!(ffi::DSA_generate_parameters_ex(dsa.0, size as c_int, ptr::null(), 0,
|
||||
ptr::null_mut(), ptr::null_mut(), ptr::null()));
|
||||
try_ssl!(ffi::DSA_generate_parameters_ex(dsa.0,
|
||||
size as c_int,
|
||||
ptr::null(),
|
||||
0,
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut()));
|
||||
Ok(dsa)
|
||||
}
|
||||
}
|
||||
|
|
@ -190,43 +195,74 @@ impl DSA {
|
|||
|
||||
pub fn p<'a>(&'a self) -> Option<BigNumRef<'a>> {
|
||||
unsafe {
|
||||
let p = (*self.0).p;
|
||||
let p = compat::pqg(self.0)[0];
|
||||
if p.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(BigNumRef::from_ptr((*self.0).p))
|
||||
Some(BigNumRef::from_ptr(p as *mut _))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn q<'a>(&'a self) -> Option<BigNumRef<'a>> {
|
||||
unsafe {
|
||||
let q = (*self.0).q;
|
||||
let q = compat::pqg(self.0)[1];
|
||||
if q.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(BigNumRef::from_ptr((*self.0).q))
|
||||
Some(BigNumRef::from_ptr(q as *mut _))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn g<'a>(&'a self) -> Option<BigNumRef<'a>> {
|
||||
unsafe {
|
||||
let g = (*self.0).g;
|
||||
let g = compat::pqg(self.0)[2];
|
||||
if g.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(BigNumRef::from_ptr((*self.0).g))
|
||||
Some(BigNumRef::from_ptr(g as *mut _))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn has_public_key(&self) -> bool {
|
||||
unsafe { !(*self.0).pub_key.is_null() }
|
||||
unsafe { !compat::keys(self.0)[0].is_null() }
|
||||
}
|
||||
|
||||
pub fn has_private_key(&self) -> bool {
|
||||
unsafe { !(*self.0).priv_key.is_null() }
|
||||
unsafe { !compat::keys(self.0)[1].is_null() }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl110)]
|
||||
mod compat {
|
||||
use std::ptr;
|
||||
use ffi::{self, BIGNUM, DSA};
|
||||
|
||||
pub unsafe fn pqg(d: *const DSA) -> [*const BIGNUM; 3] {
|
||||
let (mut p, mut q, mut g) = (ptr::null(), ptr::null(), ptr::null());
|
||||
ffi::DSA_get0_pqg(d, &mut p, &mut q, &mut g);
|
||||
[p, q, g]
|
||||
}
|
||||
|
||||
pub unsafe fn keys(d: *const DSA) -> [*const BIGNUM; 2] {
|
||||
let (mut pub_key, mut priv_key) = (ptr::null(), ptr::null());
|
||||
ffi::DSA_get0_key(d, &mut pub_key, &mut priv_key);
|
||||
[pub_key, priv_key]
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl10x)]
|
||||
mod compat {
|
||||
use ffi::{BIGNUM, DSA};
|
||||
|
||||
pub unsafe fn pqg(d: *const DSA) -> [*const BIGNUM; 3] {
|
||||
[(*d).p, (*d).q, (*d).g]
|
||||
}
|
||||
|
||||
pub unsafe fn keys(d: *const DSA) -> [*const BIGNUM; 2] {
|
||||
[(*d).pub_key, (*d).priv_key]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
use libc::c_uint;
|
||||
use std::io::prelude::*;
|
||||
use std::io;
|
||||
use std::ptr;
|
||||
use std::cmp;
|
||||
use ffi;
|
||||
|
||||
use HashTypeInternals;
|
||||
|
|
@ -102,7 +100,7 @@ impl Hasher {
|
|||
pub fn new(ty: Type) -> Result<Hasher, ErrorStack> {
|
||||
ffi::init();
|
||||
|
||||
let ctx = unsafe { try_ssl_null!(ffi::EVP_MD_CTX_create()) };
|
||||
let ctx = unsafe { try_ssl_null!(ffi::EVP_MD_CTX_new()) };
|
||||
let md = ty.evp_md();
|
||||
|
||||
let mut h = Hasher {
|
||||
|
|
@ -123,22 +121,20 @@ impl Hasher {
|
|||
}
|
||||
Finalized => (),
|
||||
}
|
||||
unsafe { try_ssl!(ffi::EVP_DigestInit_ex(self.ctx, self.md, 0 as *const _)); }
|
||||
unsafe { try_ssl!(ffi::EVP_DigestInit_ex(self.ctx, self.md, 0 as *mut _)); }
|
||||
self.state = Reset;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Feeds data into the hasher.
|
||||
pub fn update(&mut self, mut data: &[u8]) -> Result<(), ErrorStack> {
|
||||
pub fn update(&mut self, data: &[u8]) -> Result<(), ErrorStack> {
|
||||
if self.state == Finalized {
|
||||
try!(self.init());
|
||||
}
|
||||
while !data.is_empty() {
|
||||
let len = cmp::min(data.len(), c_uint::max_value() as usize);
|
||||
unsafe {
|
||||
try_ssl!(ffi::EVP_DigestUpdate(self.ctx, data.as_ptr(), len as c_uint));
|
||||
}
|
||||
data = &data[len..];
|
||||
try_ssl!(ffi::EVP_DigestUpdate(self.ctx,
|
||||
data.as_ptr() as *mut _,
|
||||
data.len()));
|
||||
}
|
||||
self.state = Updated;
|
||||
Ok(())
|
||||
|
|
@ -176,7 +172,7 @@ impl Write for Hasher {
|
|||
impl Clone for Hasher {
|
||||
fn clone(&self) -> Hasher {
|
||||
let ctx = unsafe {
|
||||
let ctx = ffi::EVP_MD_CTX_create();
|
||||
let ctx = ffi::EVP_MD_CTX_new();
|
||||
assert!(!ctx.is_null());
|
||||
let r = ffi::EVP_MD_CTX_copy_ex(ctx, self.ctx);
|
||||
assert_eq!(r, 1);
|
||||
|
|
@ -197,7 +193,7 @@ impl Drop for Hasher {
|
|||
if self.state != Finalized {
|
||||
drop(self.finish());
|
||||
}
|
||||
ffi::EVP_MD_CTX_destroy(self.ctx);
|
||||
ffi::EVP_MD_CTX_free(self.ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,16 +13,14 @@
|
|||
// limitations under the License.
|
||||
//
|
||||
|
||||
use libc::{c_int, c_uint};
|
||||
use libc::{c_int};
|
||||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
use std::cmp;
|
||||
use ffi;
|
||||
|
||||
use HashTypeInternals;
|
||||
use crypto::hash::Type;
|
||||
use error::ErrorStack;
|
||||
use c_helpers;
|
||||
|
||||
#[derive(PartialEq, Copy, Clone)]
|
||||
enum State {
|
||||
|
|
@ -66,7 +64,7 @@ use self::State::*;
|
|||
/// assert_eq!(res, spec);
|
||||
/// ```
|
||||
pub struct HMAC {
|
||||
ctx: ffi::HMAC_CTX,
|
||||
ctx: compat::HMAC_CTX,
|
||||
state: State,
|
||||
}
|
||||
|
||||
|
|
@ -75,11 +73,7 @@ impl HMAC {
|
|||
pub fn new(ty: Type, key: &[u8]) -> Result<HMAC, ErrorStack> {
|
||||
ffi::init();
|
||||
|
||||
let ctx = unsafe {
|
||||
let mut ctx = ::std::mem::uninitialized();
|
||||
ffi::HMAC_CTX_init(&mut ctx);
|
||||
ctx
|
||||
};
|
||||
let ctx = compat::HMAC_CTX::new();
|
||||
let md = ty.evp_md();
|
||||
|
||||
let mut h = HMAC {
|
||||
|
|
@ -92,7 +86,7 @@ impl HMAC {
|
|||
|
||||
fn init_once(&mut self, md: *const ffi::EVP_MD, key: &[u8]) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
try_ssl!(c_helpers::rust_0_8_HMAC_Init_ex(&mut self.ctx,
|
||||
try_ssl!(ffi::HMAC_Init_ex(self.ctx.get(),
|
||||
key.as_ptr() as *const _,
|
||||
key.len() as c_int,
|
||||
md,
|
||||
|
|
@ -113,7 +107,7 @@ impl HMAC {
|
|||
// If the key and/or md is not supplied it's reused from the last time
|
||||
// avoiding redundant initializations
|
||||
unsafe {
|
||||
try_ssl!(c_helpers::rust_0_8_HMAC_Init_ex(&mut self.ctx,
|
||||
try_ssl!(ffi::HMAC_Init_ex(self.ctx.get(),
|
||||
0 as *const _,
|
||||
0,
|
||||
0 as *const _,
|
||||
|
|
@ -123,16 +117,14 @@ impl HMAC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn update(&mut self, mut data: &[u8]) -> Result<(), ErrorStack> {
|
||||
pub fn update(&mut self, data: &[u8]) -> Result<(), ErrorStack> {
|
||||
if self.state == Finalized {
|
||||
try!(self.init());
|
||||
}
|
||||
while !data.is_empty() {
|
||||
let len = cmp::min(data.len(), c_uint::max_value() as usize);
|
||||
unsafe {
|
||||
try_ssl!(c_helpers::rust_0_8_HMAC_Update(&mut self.ctx, data.as_ptr(), len as c_uint));
|
||||
}
|
||||
data = &data[len..];
|
||||
try_ssl!(ffi::HMAC_Update(self.ctx.get(),
|
||||
data.as_ptr(),
|
||||
data.len()));
|
||||
}
|
||||
self.state = Updated;
|
||||
Ok(())
|
||||
|
|
@ -147,7 +139,9 @@ impl HMAC {
|
|||
unsafe {
|
||||
let mut len = ffi::EVP_MAX_MD_SIZE;
|
||||
let mut res = vec![0; len as usize];
|
||||
try_ssl!(c_helpers::rust_0_8_HMAC_Final(&mut self.ctx, res.as_mut_ptr(), &mut len));
|
||||
try_ssl!(ffi::HMAC_Final(self.ctx.get(),
|
||||
res.as_mut_ptr(),
|
||||
&mut len));
|
||||
res.truncate(len as usize);
|
||||
self.state = Finalized;
|
||||
Ok(res)
|
||||
|
|
@ -167,14 +161,11 @@ impl Write for HMAC {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "hmac_clone")]
|
||||
impl Clone for HMAC {
|
||||
/// Requires the `hmac_clone` feature.
|
||||
fn clone(&self) -> HMAC {
|
||||
let mut ctx: ffi::HMAC_CTX;
|
||||
let ctx = compat::HMAC_CTX::new();
|
||||
unsafe {
|
||||
ctx = ::std::mem::uninitialized();
|
||||
let r = ffi::HMAC_CTX_copy(&mut ctx, &self.ctx);
|
||||
let r = ffi::HMAC_CTX_copy(ctx.get(), self.ctx.get());
|
||||
assert_eq!(r, 1);
|
||||
}
|
||||
HMAC {
|
||||
|
|
@ -186,12 +177,9 @@ impl Clone for HMAC {
|
|||
|
||||
impl Drop for HMAC {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
if self.state != Finalized {
|
||||
drop(self.finish());
|
||||
}
|
||||
ffi::HMAC_CTX_cleanup(&mut self.ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -202,6 +190,73 @@ pub fn hmac(t: Type, key: &[u8], data: &[u8]) -> Result<Vec<u8>, ErrorStack> {
|
|||
h.finish()
|
||||
}
|
||||
|
||||
#[cfg(ossl110)]
|
||||
#[allow(bad_style)]
|
||||
mod compat {
|
||||
use ffi;
|
||||
|
||||
pub struct HMAC_CTX {
|
||||
ctx: *mut ffi::HMAC_CTX,
|
||||
}
|
||||
|
||||
impl HMAC_CTX {
|
||||
pub fn new() -> HMAC_CTX {
|
||||
unsafe {
|
||||
let ctx = ffi::HMAC_CTX_new();
|
||||
assert!(!ctx.is_null());
|
||||
HMAC_CTX { ctx: ctx }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self) -> *mut ffi::HMAC_CTX {
|
||||
self.ctx
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for HMAC_CTX {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
ffi::HMAC_CTX_free(self.ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl10x)]
|
||||
#[allow(bad_style)]
|
||||
mod compat {
|
||||
use std::mem;
|
||||
use std::cell::UnsafeCell;
|
||||
|
||||
use ffi;
|
||||
|
||||
pub struct HMAC_CTX {
|
||||
ctx: UnsafeCell<ffi::HMAC_CTX>,
|
||||
}
|
||||
|
||||
impl HMAC_CTX {
|
||||
pub fn new() -> HMAC_CTX {
|
||||
unsafe {
|
||||
let mut ctx = mem::zeroed();
|
||||
ffi::HMAC_CTX_init(&mut ctx);
|
||||
HMAC_CTX { ctx: UnsafeCell::new(ctx) }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self) -> *mut ffi::HMAC_CTX {
|
||||
self.ctx.get()
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for HMAC_CTX {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
ffi::HMAC_CTX_cleanup(self.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::iter::repeat;
|
||||
|
|
@ -289,7 +344,6 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "hmac_clone")]
|
||||
fn test_clone() {
|
||||
let tests: [(Vec<u8>, Vec<u8>, Vec<u8>); 2] =
|
||||
[(repeat(0xaa_u8).take(80).collect(),
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@
|
|||
//
|
||||
|
||||
pub mod hash;
|
||||
#[cfg(feature = "hmac")]
|
||||
pub mod hmac;
|
||||
pub mod pkcs5;
|
||||
pub mod pkcs12;
|
||||
|
|
|
|||
|
|
@ -44,13 +44,14 @@ impl Pkcs12 {
|
|||
|
||||
let pkey = PKey::from_ptr(pkey);
|
||||
let cert = X509::from_ptr(cert);
|
||||
let chain = chain as *mut _;
|
||||
|
||||
let mut chain_out = vec![];
|
||||
for i in 0..(*chain).stack.num {
|
||||
let x509 = *(*chain).stack.data.offset(i as isize) as *mut _;
|
||||
chain_out.push(X509::from_ptr(x509));
|
||||
for i in 0..compat::OPENSSL_sk_num(chain) {
|
||||
let x509 = compat::OPENSSL_sk_value(chain, i);
|
||||
chain_out.push(X509::from_ptr(x509 as *mut _));
|
||||
}
|
||||
ffi::sk_free(&mut (*chain).stack);
|
||||
compat::OPENSSL_sk_free(chain as *mut _);
|
||||
|
||||
Ok(ParsedPkcs12 {
|
||||
pkey: pkey,
|
||||
|
|
@ -69,6 +70,31 @@ pub struct ParsedPkcs12 {
|
|||
_p: (),
|
||||
}
|
||||
|
||||
#[cfg(ossl110)]
|
||||
mod compat {
|
||||
pub use ffi::OPENSSL_sk_free;
|
||||
pub use ffi::OPENSSL_sk_num;
|
||||
pub use ffi::OPENSSL_sk_value;
|
||||
}
|
||||
|
||||
#[cfg(ossl10x)]
|
||||
#[allow(bad_style)]
|
||||
mod compat {
|
||||
use libc::{c_int, c_void};
|
||||
use ffi;
|
||||
|
||||
pub use ffi::sk_free as OPENSSL_sk_free;
|
||||
|
||||
pub unsafe fn OPENSSL_sk_num(stack: *mut ffi::_STACK) -> c_int {
|
||||
(*stack).num
|
||||
}
|
||||
|
||||
pub unsafe fn OPENSSL_sk_value(stack: *const ffi::_STACK, idx: c_int)
|
||||
-> *mut c_void {
|
||||
*(*stack).data.offset(idx as isize) as *mut c_void
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crypto::hash::Type::SHA1;
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ pub fn pbkdf2_hmac_sha1(pass: &[u8],
|
|||
|
||||
ffi::init();
|
||||
|
||||
try_ssl!(ffi::PKCS5_PBKDF2_HMAC_SHA1(pass.as_ptr(),
|
||||
try_ssl!(ffi::PKCS5_PBKDF2_HMAC_SHA1(pass.as_ptr() as *const _,
|
||||
pass.len() as c_int,
|
||||
salt.as_ptr(),
|
||||
salt.len() as c_int,
|
||||
|
|
@ -94,7 +94,6 @@ pub fn pbkdf2_hmac_sha1(pass: &[u8],
|
|||
}
|
||||
|
||||
/// Derives a key from a password and salt using the PBKDF2-HMAC algorithm with a digest function.
|
||||
#[cfg(feature = "pkcs5_pbkdf2_hmac")]
|
||||
pub fn pbkdf2_hmac(pass: &[u8],
|
||||
salt: &[u8],
|
||||
iter: usize,
|
||||
|
|
@ -104,7 +103,7 @@ pub fn pbkdf2_hmac(pass: &[u8],
|
|||
unsafe {
|
||||
let mut out = vec![0; keylen];
|
||||
ffi::init();
|
||||
try_ssl!(ffi::PKCS5_PBKDF2_HMAC(pass.as_ptr(),
|
||||
try_ssl!(ffi::PKCS5_PBKDF2_HMAC(pass.as_ptr() as *const _,
|
||||
pass.len() as c_int,
|
||||
salt.as_ptr(),
|
||||
salt.len() as c_int,
|
||||
|
|
@ -162,7 +161,6 @@ mod tests {
|
|||
// Test vectors from
|
||||
// https://git.lysator.liu.se/nettle/nettle/blob/nettle_3.1.1_release_20150424/testsuite/pbkdf2-test.c
|
||||
#[test]
|
||||
#[cfg(feature = "pkcs5_pbkdf2_hmac")]
|
||||
fn test_pbkdf2_hmac_sha256() {
|
||||
assert_eq!(super::pbkdf2_hmac(b"passwd", b"salt", 1, hash::Type::SHA256, 16).unwrap(),
|
||||
vec![0x55_u8, 0xac_u8, 0x04_u8, 0x6e_u8, 0x56_u8, 0xe3_u8, 0x08_u8, 0x9f_u8,
|
||||
|
|
@ -176,7 +174,6 @@ mod tests {
|
|||
// Test vectors from
|
||||
// https://git.lysator.liu.se/nettle/nettle/blob/nettle_3.1.1_release_20150424/testsuite/pbkdf2-test.c
|
||||
#[test]
|
||||
#[cfg(feature = "pkcs5_pbkdf2_hmac")]
|
||||
fn test_pbkdf2_hmac_sha512() {
|
||||
assert_eq!(super::pbkdf2_hmac(b"password", b"NaCL", 1, hash::Type::SHA512, 64).unwrap(),
|
||||
vec![0x73_u8, 0xde_u8, 0xcf_u8, 0xa5_u8, 0x8a_u8, 0xa2_u8, 0xe8_u8, 0x4f_u8,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use ffi;
|
|||
use std::fmt;
|
||||
use std::ptr;
|
||||
use std::mem;
|
||||
use libc::{c_int, c_void, c_char, c_ulong};
|
||||
use libc::{c_int, c_void, c_char};
|
||||
|
||||
use bn::{BigNum, BigNumRef};
|
||||
use bio::{MemBio, MemBioSlice};
|
||||
|
|
@ -44,12 +44,13 @@ impl RSA {
|
|||
/// the supplied load and save methods for DER formatted keys.
|
||||
pub fn from_public_components(n: BigNum, e: BigNum) -> Result<RSA, ErrorStack> {
|
||||
unsafe {
|
||||
let rsa = try_ssl_null!(ffi::RSA_new());
|
||||
(*rsa).n = n.as_ptr();
|
||||
(*rsa).e = e.as_ptr();
|
||||
mem::forget(n);
|
||||
mem::forget(e);
|
||||
Ok(RSA(rsa))
|
||||
let rsa = RSA(try_ssl_null!(ffi::RSA_new()));
|
||||
try_ssl!(compat::set_key(rsa.0,
|
||||
n.as_ptr(),
|
||||
e.as_ptr(),
|
||||
ptr::null_mut()));
|
||||
mem::forget((n, e));
|
||||
Ok(rsa)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -63,24 +64,15 @@ impl RSA {
|
|||
qi: BigNum)
|
||||
-> Result<RSA, ErrorStack> {
|
||||
unsafe {
|
||||
let rsa = try_ssl_null!(ffi::RSA_new());
|
||||
(*rsa).n = n.as_ptr();
|
||||
(*rsa).e = e.as_ptr();
|
||||
(*rsa).d = d.as_ptr();
|
||||
(*rsa).p = p.as_ptr();
|
||||
(*rsa).q = q.as_ptr();
|
||||
(*rsa).dmp1 = dp.as_ptr();
|
||||
(*rsa).dmq1 = dq.as_ptr();
|
||||
(*rsa).iqmp = qi.as_ptr();
|
||||
mem::forget(n);
|
||||
mem::forget(e);
|
||||
mem::forget(d);
|
||||
mem::forget(p);
|
||||
mem::forget(q);
|
||||
mem::forget(dp);
|
||||
mem::forget(dq);
|
||||
mem::forget(qi);
|
||||
Ok(RSA(rsa))
|
||||
let rsa = RSA(try_ssl_null!(ffi::RSA_new()));
|
||||
try_ssl!(compat::set_key(rsa.0, n.as_ptr(), e.as_ptr(), d.as_ptr()));
|
||||
mem::forget((n, e, d));
|
||||
try_ssl!(compat::set_factors(rsa.0, p.as_ptr(), q.as_ptr()));
|
||||
mem::forget((p, q));
|
||||
try_ssl!(compat::set_crt_params(rsa.0, dp.as_ptr(), dq.as_ptr(),
|
||||
qi.as_ptr()));
|
||||
mem::forget((dp, dq, qi));
|
||||
Ok(rsa)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -95,7 +87,7 @@ impl RSA {
|
|||
unsafe {
|
||||
let rsa = try_ssl_null!(ffi::RSA_new());
|
||||
let rsa = RSA(rsa);
|
||||
let e = try!(BigNum::new_from(ffi::RSA_F4 as c_ulong));
|
||||
let e = try!(BigNum::new_from(ffi::RSA_F4 as u32));
|
||||
|
||||
try_ssl!(ffi::RSA_generate_key_ex(rsa.0, bits as c_int, e.as_ptr(), ptr::null_mut()));
|
||||
|
||||
|
|
@ -292,55 +284,55 @@ impl RSA {
|
|||
|
||||
pub fn n<'a>(&'a self) -> Option<BigNumRef<'a>> {
|
||||
unsafe {
|
||||
let n = (*self.0).n;
|
||||
let n = compat::key(self.0)[0];
|
||||
if n.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(BigNumRef::from_ptr(n))
|
||||
Some(BigNumRef::from_ptr(n as *mut _))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn d<'a>(&self) -> Option<BigNumRef<'a>> {
|
||||
unsafe {
|
||||
let d = (*self.0).d;
|
||||
let d = compat::key(self.0)[2];
|
||||
if d.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(BigNumRef::from_ptr(d))
|
||||
Some(BigNumRef::from_ptr(d as *mut _))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn e<'a>(&'a self) -> Option<BigNumRef<'a>> {
|
||||
unsafe {
|
||||
let e = (*self.0).e;
|
||||
let e = compat::key(self.0)[1];
|
||||
if e.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(BigNumRef::from_ptr(e))
|
||||
Some(BigNumRef::from_ptr(e as *mut _))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn p<'a>(&'a self) -> Option<BigNumRef<'a>> {
|
||||
unsafe {
|
||||
let p = (*self.0).p;
|
||||
let p = compat::factors(self.0)[0];
|
||||
if p.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(BigNumRef::from_ptr(p))
|
||||
Some(BigNumRef::from_ptr(p as *mut _))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn q<'a>(&'a self) -> Option<BigNumRef<'a>> {
|
||||
unsafe {
|
||||
let q = (*self.0).q;
|
||||
let q = compat::factors(self.0)[1];
|
||||
if q.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(BigNumRef::from_ptr(q))
|
||||
Some(BigNumRef::from_ptr(q as *mut _))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -352,6 +344,89 @@ impl fmt::Debug for RSA {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl110)]
|
||||
mod compat {
|
||||
use std::ptr;
|
||||
|
||||
use ffi::{self, BIGNUM, RSA};
|
||||
use libc::c_int;
|
||||
|
||||
pub unsafe fn key(r: *const RSA) -> [*const BIGNUM; 3] {
|
||||
let (mut n, mut e, mut d) = (ptr::null(), ptr::null(), ptr::null());
|
||||
ffi::RSA_get0_key(r, &mut n, &mut e, &mut d);
|
||||
[n, e, d]
|
||||
}
|
||||
|
||||
pub unsafe fn factors(r: *const RSA) -> [*const BIGNUM; 2] {
|
||||
let (mut p, mut q) = (ptr::null(), ptr::null());
|
||||
ffi::RSA_get0_factors(r, &mut p, &mut q);
|
||||
[p, q]
|
||||
}
|
||||
|
||||
pub unsafe fn set_key(r: *mut RSA,
|
||||
n: *mut BIGNUM,
|
||||
e: *mut BIGNUM,
|
||||
d: *mut BIGNUM) -> c_int {
|
||||
ffi::RSA_set0_key(r, n, e, d)
|
||||
}
|
||||
|
||||
pub unsafe fn set_factors(r: *mut RSA,
|
||||
p: *mut BIGNUM,
|
||||
q: *mut BIGNUM) -> c_int {
|
||||
ffi::RSA_set0_factors(r, p, q)
|
||||
}
|
||||
|
||||
pub unsafe fn set_crt_params(r: *mut RSA,
|
||||
dmp1: *mut BIGNUM,
|
||||
dmq1: *mut BIGNUM,
|
||||
iqmp: *mut BIGNUM) -> c_int {
|
||||
ffi::RSA_set0_crt_params(r, dmp1, dmq1, iqmp)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl10x)]
|
||||
mod compat {
|
||||
use libc::c_int;
|
||||
use ffi::{BIGNUM, RSA};
|
||||
|
||||
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 set_key(r: *mut RSA,
|
||||
n: *mut BIGNUM,
|
||||
e: *mut BIGNUM,
|
||||
d: *mut BIGNUM) -> c_int {
|
||||
(*r).n = n;
|
||||
(*r).e = e;
|
||||
(*r).d = d;
|
||||
1 // TODO: is this right? should it be 0? what's success?
|
||||
}
|
||||
|
||||
pub unsafe fn set_factors(r: *mut RSA,
|
||||
p: *mut BIGNUM,
|
||||
q: *mut BIGNUM) -> c_int {
|
||||
(*r).p = p;
|
||||
(*r).q = q;
|
||||
1 // TODO: is this right? should it be 0? what's success?
|
||||
}
|
||||
|
||||
pub unsafe fn set_crt_params(r: *mut RSA,
|
||||
dmp1: *mut BIGNUM,
|
||||
dmq1: *mut BIGNUM,
|
||||
iqmp: *mut BIGNUM) -> c_int {
|
||||
(*r).dmp1 = dmp1;
|
||||
(*r).dmq1 = dmq1;
|
||||
(*r).iqmp = iqmp;
|
||||
1 // TODO: is this right? should it be 0? what's success?
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::io::Write;
|
||||
|
|
@ -449,9 +524,9 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn test_private_encrypt() {
|
||||
let mut k0 = super::RSA::generate(512).unwrap();
|
||||
let k0 = super::RSA::generate(512).unwrap();
|
||||
let k0pkey = k0.public_key_to_pem().unwrap();
|
||||
let mut k1 = super::RSA::public_key_from_pem(&k0pkey).unwrap();
|
||||
let k1 = super::RSA::public_key_from_pem(&k0pkey).unwrap();
|
||||
|
||||
let msg = vec!(0xdeu8, 0xadu8, 0xd0u8, 0x0du8);
|
||||
|
||||
|
|
@ -462,9 +537,9 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn test_public_encrypt() {
|
||||
let mut k0 = super::RSA::generate(512).unwrap();
|
||||
let k0 = super::RSA::generate(512).unwrap();
|
||||
let k0pkey = k0.public_key_to_pem().unwrap();
|
||||
let mut k1 = super::RSA::public_key_from_pem(&k0pkey).unwrap();
|
||||
let k1 = super::RSA::public_key_from_pem(&k0pkey).unwrap();
|
||||
|
||||
let msg = vec!(0xdeu8, 0xadu8, 0xd0u8, 0x0du8);
|
||||
|
||||
|
|
@ -475,9 +550,9 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn test_public_encrypt_pkcs() {
|
||||
let mut k0 = super::RSA::generate(512).unwrap();
|
||||
let k0 = super::RSA::generate(512).unwrap();
|
||||
let k0pkey = k0.public_key_to_pem().unwrap();
|
||||
let mut k1 = super::RSA::public_key_from_pem(&k0pkey).unwrap();
|
||||
let k1 = super::RSA::public_key_from_pem(&k0pkey).unwrap();
|
||||
|
||||
let msg = vec!(0xdeu8, 0xadu8, 0xd0u8, 0x0du8);
|
||||
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ impl Type {
|
|||
/// Returns the length of keys used with this cipher.
|
||||
pub fn key_len(&self) -> usize {
|
||||
unsafe {
|
||||
ffi::EVP_CIPHER_key_length(self.as_ptr()) as usize
|
||||
EVP_CIPHER_key_length(self.as_ptr()) as usize
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -89,7 +89,7 @@ impl Type {
|
|||
/// cipher does not use an IV.
|
||||
pub fn iv_len(&self) -> Option<usize> {
|
||||
unsafe {
|
||||
let len = ffi::EVP_CIPHER_iv_length(self.as_ptr()) as usize;
|
||||
let len = EVP_CIPHER_iv_length(self.as_ptr()) as usize;
|
||||
if len == 0 {
|
||||
None
|
||||
} else {
|
||||
|
|
@ -105,7 +105,7 @@ impl Type {
|
|||
/// Stream ciphers such as RC4 have a block size of 1.
|
||||
pub fn block_size(&self) -> usize {
|
||||
unsafe {
|
||||
ffi::EVP_CIPHER_block_size(self.as_ptr()) as usize
|
||||
EVP_CIPHER_block_size(self.as_ptr()) as usize
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -272,6 +272,30 @@ fn cipher(t: Type,
|
|||
Ok(out)
|
||||
}
|
||||
|
||||
#[cfg(ossl110)]
|
||||
use ffi::{EVP_CIPHER_iv_length, EVP_CIPHER_block_size, EVP_CIPHER_key_length};
|
||||
|
||||
#[cfg(ossl10x)]
|
||||
#[allow(bad_style)]
|
||||
mod compat {
|
||||
use libc::c_int;
|
||||
use ffi::EVP_CIPHER;
|
||||
|
||||
pub unsafe fn EVP_CIPHER_iv_length(ptr: *const EVP_CIPHER) -> c_int {
|
||||
(*ptr).iv_len
|
||||
}
|
||||
|
||||
pub unsafe fn EVP_CIPHER_block_size(ptr: *const EVP_CIPHER) -> c_int {
|
||||
(*ptr).block_size
|
||||
}
|
||||
|
||||
pub unsafe fn EVP_CIPHER_key_length(ptr: *const EVP_CIPHER) -> c_int {
|
||||
(*ptr).key_len
|
||||
}
|
||||
}
|
||||
#[cfg(ossl10x)]
|
||||
use self::compat::*;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use serialize::hex::{FromHex, ToHex};
|
||||
|
|
|
|||
|
|
@ -3,24 +3,22 @@ use error::ErrorStack;
|
|||
use bio::MemBioSlice;
|
||||
use std::ptr;
|
||||
|
||||
#[cfg(feature = "dh_from_params")]
|
||||
use bn::BigNum;
|
||||
#[cfg(feature = "dh_from_params")]
|
||||
use std::mem;
|
||||
|
||||
pub struct DH(*mut ffi::DH);
|
||||
|
||||
impl DH {
|
||||
/// Requires the `dh_from_params` feature.
|
||||
#[cfg(feature = "dh_from_params")]
|
||||
pub fn from_params(p: BigNum, g: BigNum, q: BigNum) -> Result<DH, ErrorStack> {
|
||||
let dh = unsafe {
|
||||
try_ssl_null!(::c_helpers::rust_0_8_DH_new_from_params(p.as_ptr(), g.as_ptr(), q.as_ptr()))
|
||||
};
|
||||
mem::forget(p);
|
||||
mem::forget(g);
|
||||
mem::forget(q);
|
||||
Ok(DH(dh))
|
||||
unsafe {
|
||||
let dh = DH(try_ssl_null!(ffi::DH_new()));
|
||||
try_ssl!(compat::DH_set0_pqg(dh.0,
|
||||
p.as_ptr(),
|
||||
q.as_ptr(),
|
||||
g.as_ptr()));
|
||||
mem::forget((p, g, q));
|
||||
Ok(dh)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_pem(buf: &[u8]) -> Result<DH, ErrorStack> {
|
||||
|
|
@ -32,19 +30,19 @@ impl DH {
|
|||
Ok(DH(dh))
|
||||
}
|
||||
|
||||
#[cfg(feature = "rfc5114")]
|
||||
#[cfg(all(feature = "rfc5114", not(ossl101)))]
|
||||
pub fn get_1024_160() -> Result<DH, ErrorStack> {
|
||||
let dh = try_ssl_null!(unsafe { ffi::DH_get_1024_160() });
|
||||
Ok(DH(dh))
|
||||
}
|
||||
|
||||
#[cfg(feature = "rfc5114")]
|
||||
#[cfg(all(feature = "rfc5114", not(ossl101)))]
|
||||
pub fn get_2048_224() -> Result<DH, ErrorStack> {
|
||||
let dh = try_ssl_null!(unsafe { ffi::DH_get_2048_224() });
|
||||
Ok(DH(dh))
|
||||
}
|
||||
|
||||
#[cfg(feature = "rfc5114")]
|
||||
#[cfg(all(feature = "rfc5114", not(ossl101)))]
|
||||
pub fn get_2048_256() -> Result<DH, ErrorStack> {
|
||||
let dh = try_ssl_null!(unsafe { ffi::DH_get_2048_256() });
|
||||
Ok(DH(dh))
|
||||
|
|
@ -64,17 +62,39 @@ impl Drop for DH {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl110)]
|
||||
mod compat {
|
||||
pub use ffi::DH_set0_pqg;
|
||||
}
|
||||
|
||||
#[cfg(ossl10x)]
|
||||
#[allow(bad_style)]
|
||||
mod compat {
|
||||
use ffi;
|
||||
use libc::c_int;
|
||||
|
||||
pub unsafe fn DH_set0_pqg(dh: *mut ffi::DH,
|
||||
p: *mut ffi::BIGNUM,
|
||||
q: *mut ffi::BIGNUM,
|
||||
g: *mut ffi::BIGNUM) -> c_int {
|
||||
(*dh).p = p;
|
||||
(*dh).q = q;
|
||||
(*dh).g = g;
|
||||
1
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::DH;
|
||||
use bn::BigNum;
|
||||
use ssl::SslContext;
|
||||
use ssl::SslMethod::Sslv23;
|
||||
use ssl::SslMethod::Tls;
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "rfc5114")]
|
||||
#[cfg(all(feature = "rfc5114", not(ossl101)))]
|
||||
fn test_dh_rfc5114() {
|
||||
let mut ctx = SslContext::new(Sslv23).unwrap();
|
||||
let mut ctx = SslContext::new(Tls).unwrap();
|
||||
let dh1 = DH::get_1024_160().unwrap();
|
||||
ctx.set_tmp_dh(&dh1).unwrap();
|
||||
let dh2 = DH::get_2048_224().unwrap();
|
||||
|
|
@ -84,9 +104,8 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "dh_from_params")]
|
||||
fn test_dh() {
|
||||
let mut ctx = SslContext::new(Sslv23).unwrap();
|
||||
let mut ctx = SslContext::new(Tls).unwrap();
|
||||
let p = BigNum::from_hex_str("87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435\
|
||||
E3B00E00DF8F1D61957D4FAF7DF4561B2AA3016C3D91134096FAA3BF429\
|
||||
6D830E9A7C209E0C6497517ABD5A8A9D306BCF67ED91F9E6725B4758C02\
|
||||
|
|
@ -116,7 +135,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_dh_from_pem() {
|
||||
let mut ctx = SslContext::new(Sslv23).unwrap();
|
||||
let mut ctx = SslContext::new(Tls).unwrap();
|
||||
let params = include_bytes!("../../test/dhparams.pem");
|
||||
let dh = DH::from_pem(params).ok().expect("Failed to load PEM");
|
||||
ctx.set_tmp_dh(&dh).unwrap();
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ impl Error {
|
|||
|
||||
match unsafe { ffi::ERR_get_error() } {
|
||||
0 => None,
|
||||
err => Some((Error(err))),
|
||||
err => Some(Error(err)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -121,6 +121,7 @@ impl error::Error for Error {
|
|||
fn get_lib(err: c_ulong) -> &'static str {
|
||||
unsafe {
|
||||
let cstr = ffi::ERR_lib_error_string(err);
|
||||
assert!(!cstr.is_null(), "bad lib: {}", err);
|
||||
let bytes = CStr::from_ptr(cstr as *const _).to_bytes();
|
||||
str::from_utf8(bytes).unwrap()
|
||||
}
|
||||
|
|
@ -129,6 +130,7 @@ fn get_lib(err: c_ulong) -> &'static str {
|
|||
fn get_func(err: c_ulong) -> &'static str {
|
||||
unsafe {
|
||||
let cstr = ffi::ERR_func_error_string(err);
|
||||
assert!(!cstr.is_null(), "bad func: {}", err);
|
||||
let bytes = CStr::from_ptr(cstr as *const _).to_bytes();
|
||||
str::from_utf8(bytes).unwrap()
|
||||
}
|
||||
|
|
@ -137,6 +139,7 @@ fn get_func(err: c_ulong) -> &'static str {
|
|||
fn get_reason(err: c_ulong) -> &'static str {
|
||||
unsafe {
|
||||
let cstr = ffi::ERR_reason_error_string(err);
|
||||
assert!(!cstr.is_null(), "bad reason: {}", err);
|
||||
let bytes = CStr::from_ptr(cstr as *const _).to_bytes();
|
||||
str::from_utf8(bytes).unwrap()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,9 @@ extern crate rustc_serialize as serialize;
|
|||
#[cfg(test)]
|
||||
extern crate net2;
|
||||
|
||||
#[cfg(test)]
|
||||
extern crate tempdir;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use ffi::init;
|
||||
|
||||
|
|
@ -23,8 +26,6 @@ mod macros;
|
|||
pub mod asn1;
|
||||
mod bio;
|
||||
pub mod bn;
|
||||
#[cfg(feature = "c_helpers")]
|
||||
mod c_helpers;
|
||||
pub mod crypto;
|
||||
pub mod dh;
|
||||
pub mod error;
|
||||
|
|
|
|||
|
|
@ -80,3 +80,17 @@ macro_rules! lift_ssl_returns_size {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(ossl10x)]
|
||||
macro_rules! CRYPTO_free {
|
||||
($e:expr) => (::ffi::CRYPTO_free($e))
|
||||
}
|
||||
|
||||
#[cfg(ossl110)]
|
||||
macro_rules! CRYPTO_free {
|
||||
($e:expr) => (
|
||||
::ffi::CRYPTO_free($e,
|
||||
concat!(file!(), "\0").as_ptr() as *const _,
|
||||
line!() as i32)
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use libc::{c_char, c_int, c_long, c_void, strlen};
|
||||
use ffi::{self, BIO, BIO_CTRL_FLUSH, BIO_TYPE_NONE, BIO_new, BIO_clear_retry_flags,
|
||||
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::io;
|
||||
|
|
@ -18,22 +18,11 @@ pub struct StreamState<S> {
|
|||
}
|
||||
|
||||
/// Safe wrapper for BIO_METHOD
|
||||
pub struct BioMethod(ffi::BIO_METHOD);
|
||||
pub struct BioMethod(compat::BIO_METHOD);
|
||||
|
||||
impl BioMethod {
|
||||
pub fn new<S: Read + Write>() -> BioMethod {
|
||||
BioMethod(ffi::BIO_METHOD {
|
||||
type_: BIO_TYPE_NONE,
|
||||
name: b"rust\0".as_ptr() as *const _,
|
||||
bwrite: Some(bwrite::<S>),
|
||||
bread: Some(bread::<S>),
|
||||
bputs: Some(bputs::<S>),
|
||||
bgets: None,
|
||||
ctrl: Some(ctrl::<S>),
|
||||
create: Some(create),
|
||||
destroy: Some(destroy::<S>),
|
||||
callback_ctrl: None,
|
||||
})
|
||||
BioMethod(compat::BIO_METHOD::new::<S>())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -49,9 +38,9 @@ pub fn new<S: Read + Write>(stream: S) -> Result<(*mut BIO, Arc<BioMethod>), Err
|
|||
});
|
||||
|
||||
unsafe {
|
||||
let bio = try_ssl_null!(BIO_new(&method.0));
|
||||
(*bio).ptr = Box::into_raw(state) as *mut _;
|
||||
(*bio).init = 1;
|
||||
let bio = try_ssl_null!(BIO_new(method.0.get()));
|
||||
compat::BIO_set_data(bio, Box::into_raw(state) as *mut _);
|
||||
compat::BIO_set_init(bio, 1);
|
||||
|
||||
return Ok((bio, method));
|
||||
}
|
||||
|
|
@ -62,14 +51,13 @@ pub unsafe fn take_error<S>(bio: *mut BIO) -> Option<io::Error> {
|
|||
state.error.take()
|
||||
}
|
||||
|
||||
#[cfg_attr(not(feature = "nightly"), allow(dead_code))]
|
||||
pub unsafe fn take_panic<S>(bio: *mut BIO) -> Option<Box<Any + Send>> {
|
||||
let state = state::<S>(bio);
|
||||
state.panic.take()
|
||||
}
|
||||
|
||||
pub unsafe fn get_ref<'a, S: 'a>(bio: *mut BIO) -> &'a S {
|
||||
let state: &'a StreamState<S> = mem::transmute((*bio).ptr);
|
||||
let state: &'a StreamState<S> = mem::transmute(compat::BIO_get_data(bio));
|
||||
&state.stream
|
||||
}
|
||||
|
||||
|
|
@ -78,24 +66,16 @@ 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> {
|
||||
mem::transmute((*bio).ptr)
|
||||
mem::transmute(compat::BIO_get_data(bio))
|
||||
}
|
||||
|
||||
#[cfg(feature = "nightly")]
|
||||
fn catch_unwind<F, T>(f: F) -> Result<T, Box<Any + Send>>
|
||||
where F: FnOnce() -> T
|
||||
{
|
||||
::std::panic::catch_unwind(::std::panic::AssertUnwindSafe(f))
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "nightly"))]
|
||||
fn catch_unwind<F, T>(f: F) -> Result<T, Box<Any + Send>>
|
||||
where F: FnOnce() -> T
|
||||
{
|
||||
Ok(f())
|
||||
}
|
||||
|
||||
unsafe extern "C" fn bwrite<S: Write>(bio: *mut BIO, buf: *const c_char, len: c_int) -> c_int {
|
||||
unsafe extern fn bwrite<S: Write>(bio: *mut BIO, buf: *const c_char, len: c_int) -> c_int {
|
||||
BIO_clear_retry_flags(bio);
|
||||
|
||||
let state = state::<S>(bio);
|
||||
|
|
@ -117,7 +97,7 @@ unsafe extern "C" fn bwrite<S: Write>(bio: *mut BIO, buf: *const c_char, len: c_
|
|||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn bread<S: Read>(bio: *mut BIO, buf: *mut c_char, len: c_int) -> c_int {
|
||||
unsafe extern fn bread<S: Read>(bio: *mut BIO, buf: *mut c_char, len: c_int) -> c_int {
|
||||
BIO_clear_retry_flags(bio);
|
||||
|
||||
let state = state::<S>(bio);
|
||||
|
|
@ -147,11 +127,11 @@ fn retriable_error(err: &io::Error) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn bputs<S: Write>(bio: *mut BIO, s: *const c_char) -> c_int {
|
||||
unsafe extern fn bputs<S: Write>(bio: *mut BIO, s: *const c_char) -> c_int {
|
||||
bwrite::<S>(bio, s, strlen(s) as c_int)
|
||||
}
|
||||
|
||||
unsafe extern "C" fn ctrl<S: Write>(bio: *mut BIO,
|
||||
unsafe extern fn ctrl<S: Write>(bio: *mut BIO,
|
||||
cmd: c_int,
|
||||
_num: c_long,
|
||||
_ptr: *mut c_void)
|
||||
|
|
@ -175,22 +155,126 @@ unsafe extern "C" fn ctrl<S: Write>(bio: *mut BIO,
|
|||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn create(bio: *mut BIO) -> c_int {
|
||||
(*bio).init = 0;
|
||||
(*bio).num = 0;
|
||||
(*bio).ptr = ptr::null_mut();
|
||||
(*bio).flags = 0;
|
||||
unsafe extern fn create(bio: *mut BIO) -> c_int {
|
||||
compat::BIO_set_init(bio, 0);
|
||||
compat::BIO_set_num(bio, 0);
|
||||
compat::BIO_set_data(bio, ptr::null_mut());
|
||||
compat::BIO_set_flags(bio, 0);
|
||||
1
|
||||
}
|
||||
|
||||
unsafe extern "C" fn destroy<S>(bio: *mut BIO) -> c_int {
|
||||
unsafe extern fn destroy<S>(bio: *mut BIO) -> c_int {
|
||||
if bio.is_null() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert!(!(*bio).ptr.is_null());
|
||||
Box::<StreamState<S>>::from_raw((*bio).ptr as *mut _);
|
||||
(*bio).ptr = ptr::null_mut();
|
||||
(*bio).init = 0;
|
||||
let data = compat::BIO_get_data(bio);
|
||||
assert!(!data.is_null());
|
||||
Box::<StreamState<S>>::from_raw(data as *mut _);
|
||||
compat::BIO_set_data(bio, ptr::null_mut());
|
||||
compat::BIO_set_init(bio, 0);
|
||||
1
|
||||
}
|
||||
|
||||
#[cfg(ossl110)]
|
||||
#[allow(bad_style)]
|
||||
mod compat {
|
||||
use std::io::{Read, Write};
|
||||
|
||||
use libc::c_int;
|
||||
use ffi;
|
||||
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) {}
|
||||
|
||||
pub struct BIO_METHOD {
|
||||
inner: *mut ffi::BIO_METHOD,
|
||||
}
|
||||
|
||||
impl BIO_METHOD {
|
||||
pub fn new<S: Read + Write>() -> BIO_METHOD {
|
||||
unsafe {
|
||||
let ptr = ffi::BIO_meth_new(ffi::BIO_TYPE_NONE,
|
||||
b"rust\0".as_ptr() as *const _);
|
||||
assert!(!ptr.is_null());
|
||||
let ret = BIO_METHOD { inner: ptr };
|
||||
assert!(ffi::BIO_meth_set_write(ptr, super::bwrite::<S>) != 0);
|
||||
assert!(ffi::BIO_meth_set_read(ptr, super::bread::<S>) != 0);
|
||||
assert!(ffi::BIO_meth_set_puts(ptr, super::bputs::<S>) != 0);
|
||||
assert!(ffi::BIO_meth_set_ctrl(ptr, super::ctrl::<S>) != 0);
|
||||
assert!(ffi::BIO_meth_set_create(ptr, super::create) != 0);
|
||||
assert!(ffi::BIO_meth_set_destroy(ptr, super::destroy::<S>) != 0);
|
||||
return ret
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self) -> *mut ffi::BIO_METHOD {
|
||||
self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for BIO_METHOD {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
ffi::BIO_meth_free(self.inner);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl10x)]
|
||||
#[allow(bad_style)]
|
||||
mod compat {
|
||||
use std::io::{Read, Write};
|
||||
use std::cell::UnsafeCell;
|
||||
|
||||
use ffi;
|
||||
use libc::{c_int, c_void};
|
||||
|
||||
pub struct BIO_METHOD {
|
||||
inner: UnsafeCell<ffi::BIO_METHOD>,
|
||||
}
|
||||
|
||||
impl BIO_METHOD {
|
||||
pub fn new<S: Read + Write>() -> BIO_METHOD {
|
||||
BIO_METHOD {
|
||||
inner: UnsafeCell::new(ffi::BIO_METHOD {
|
||||
type_: ffi::BIO_TYPE_NONE,
|
||||
name: b"rust\0".as_ptr() as *const _,
|
||||
bwrite: Some(super::bwrite::<S>),
|
||||
bread: Some(super::bread::<S>),
|
||||
bputs: Some(super::bputs::<S>),
|
||||
bgets: None,
|
||||
ctrl: Some(super::ctrl::<S>),
|
||||
create: Some(super::create),
|
||||
destroy: Some(super::destroy::<S>),
|
||||
callback_ctrl: None,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self) -> *mut ffi::BIO_METHOD {
|
||||
self.inner.get()
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn BIO_set_init(bio: *mut ffi::BIO, init: c_int) {
|
||||
(*bio).init = init;
|
||||
}
|
||||
|
||||
pub unsafe fn BIO_set_flags(bio: *mut ffi::BIO, flags: c_int) {
|
||||
(*bio).flags = flags;
|
||||
}
|
||||
|
||||
pub unsafe fn BIO_get_data(bio: *mut ffi::BIO) -> *mut c_void {
|
||||
(*bio).ptr
|
||||
}
|
||||
|
||||
pub unsafe fn BIO_set_data(bio: *mut ffi::BIO, data: *mut c_void) {
|
||||
(*bio).ptr = data;
|
||||
}
|
||||
|
||||
pub unsafe fn BIO_set_num(bio: *mut ffi::BIO, num: c_int) {
|
||||
(*bio).num = num;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use libc::{c_int, c_void, c_long};
|
||||
use libc::{c_int, c_void, c_long, c_ulong};
|
||||
use std::any::Any;
|
||||
use std::any::TypeId;
|
||||
use std::cmp;
|
||||
|
|
@ -38,12 +38,11 @@ use self::bio::BioMethod;
|
|||
pub use ssl::error::Error;
|
||||
|
||||
bitflags! {
|
||||
pub flags SslContextOptions: c_long {
|
||||
pub flags SslContextOptions: c_ulong {
|
||||
const SSL_OP_MICROSOFT_SESS_ID_BUG = ffi::SSL_OP_MICROSOFT_SESS_ID_BUG,
|
||||
const SSL_OP_NETSCAPE_CHALLENGE_BUG = ffi::SSL_OP_NETSCAPE_CHALLENGE_BUG,
|
||||
const SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG =
|
||||
ffi::SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG,
|
||||
const SSL_OP_TLSEXT_PADDING = ffi::SSL_OP_TLSEXT_PADDING,
|
||||
const SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER = ffi::SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER,
|
||||
const SSL_OP_SSLEAY_080_CLIENT_DH_BUG = ffi::SSL_OP_SSLEAY_080_CLIENT_DH_BUG,
|
||||
const SSL_OP_TLS_D5_BUG = ffi::SSL_OP_TLS_D5_BUG,
|
||||
|
|
@ -73,74 +72,11 @@ bitflags! {
|
|||
#[allow(non_camel_case_types)]
|
||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
|
||||
pub enum SslMethod {
|
||||
#[cfg(feature = "sslv2")]
|
||||
/// Only support the SSLv2 protocol, requires the `sslv2` feature.
|
||||
Sslv2,
|
||||
/// Support the SSLv2, SSLv3, TLSv1, TLSv1.1, and TLSv1.2 protocols depending on what the
|
||||
/// linked OpenSSL library supports.
|
||||
Sslv23,
|
||||
#[cfg(feature = "sslv3")]
|
||||
/// Only support the SSLv3 protocol.
|
||||
Sslv3,
|
||||
/// Only support the TLSv1 protocol.
|
||||
Tlsv1,
|
||||
#[cfg(feature = "tlsv1_1")]
|
||||
/// Support TLSv1.1 protocol, requires the `tlsv1_1` feature.
|
||||
Tlsv1_1,
|
||||
#[cfg(feature = "tlsv1_2")]
|
||||
/// Support TLSv1.2 protocol, requires the `tlsv1_2` feature.
|
||||
Tlsv1_2,
|
||||
#[cfg(feature = "dtlsv1")]
|
||||
/// Support DTLSv1 protocol, requires the `dtlsv1` feature.
|
||||
Dtlsv1,
|
||||
#[cfg(feature = "dtlsv1_2")]
|
||||
/// Support DTLSv1.2 protocol, requires the `dtlsv1_2` feature.
|
||||
Dtlsv1_2,
|
||||
}
|
||||
|
||||
impl SslMethod {
|
||||
fn to_raw(&self) -> *const ffi::SSL_METHOD {
|
||||
unsafe {
|
||||
match *self {
|
||||
#[cfg(feature = "sslv2")]
|
||||
SslMethod::Sslv2 => ffi::SSLv2_method(),
|
||||
#[cfg(feature = "sslv3")]
|
||||
SslMethod::Sslv3 => ffi::SSLv3_method(),
|
||||
SslMethod::Tlsv1 => ffi::TLSv1_method(),
|
||||
SslMethod::Sslv23 => ffi::SSLv23_method(),
|
||||
#[cfg(feature = "tlsv1_1")]
|
||||
SslMethod::Tlsv1_1 => ffi::TLSv1_1_method(),
|
||||
#[cfg(feature = "tlsv1_2")]
|
||||
SslMethod::Tlsv1_2 => ffi::TLSv1_2_method(),
|
||||
#[cfg(feature = "dtlsv1")]
|
||||
SslMethod::Dtlsv1 => ffi::DTLSv1_method(),
|
||||
#[cfg(feature = "dtlsv1_2")]
|
||||
SslMethod::Dtlsv1_2 => ffi::DTLSv1_2_method(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn from_raw(method: *const ffi::SSL_METHOD) -> Option<SslMethod> {
|
||||
unsafe {
|
||||
match method {
|
||||
#[cfg(feature = "sslv2")]
|
||||
x if x == ffi::SSLv2_method() => Some(SslMethod::Sslv2),
|
||||
#[cfg(feature = "sslv3")]
|
||||
x if x == ffi::SSLv3_method() => Some(SslMethod::Sslv3),
|
||||
x if x == ffi::TLSv1_method() => Some(SslMethod::Tlsv1),
|
||||
x if x == ffi::SSLv23_method() => Some(SslMethod::Sslv23),
|
||||
#[cfg(feature = "tlsv1_1")]
|
||||
x if x == ffi::TLSv1_1_method() => Some(SslMethod::Tlsv1_1),
|
||||
#[cfg(feature = "tlsv1_2")]
|
||||
x if x == ffi::TLSv1_2_method() => Some(SslMethod::Tlsv1_2),
|
||||
#[cfg(feature = "dtlsv1")]
|
||||
x if x == ffi::DTLSv1_method() => Some(SslMethod::Dtlsv1),
|
||||
#[cfg(feature = "dtlsv1_2")]
|
||||
x if x == ffi::DTLSv1_2_method() => Some(SslMethod::Dtlsv1_2),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: support more methods
|
||||
/// Support the TLS protocol
|
||||
Tls,
|
||||
/// Support DTLS protocol
|
||||
Dtls,
|
||||
}
|
||||
|
||||
/// Determines the type of certificate verification used
|
||||
|
|
@ -172,11 +108,11 @@ fn get_ssl_verify_data_idx<T: Any + 'static>() -> c_int {
|
|||
*SSL_INDEXES.lock().unwrap().entry(TypeId::of::<T>()).or_insert_with(|| get_new_ssl_idx::<T>())
|
||||
}
|
||||
|
||||
#[cfg(feature = "npn")]
|
||||
#[cfg(all(feature = "npn", not(ossl101)))]
|
||||
lazy_static! {
|
||||
static ref NPN_PROTOS_IDX: c_int = get_new_idx::<Vec<u8>>();
|
||||
}
|
||||
#[cfg(feature = "alpn")]
|
||||
#[cfg(all(feature = "alpn", not(ossl101)))]
|
||||
lazy_static! {
|
||||
static ref ALPN_PROTOS_IDX: c_int = get_new_idx::<Vec<u8>>();
|
||||
}
|
||||
|
|
@ -184,7 +120,7 @@ lazy_static! {
|
|||
/// Determine a new index to use for SSL CTX ex data.
|
||||
/// Registers a destruct for the data which will be called by openssl when the context is freed.
|
||||
fn get_new_idx<T>() -> c_int {
|
||||
extern "C" fn free_data_box<T>(_parent: *mut c_void,
|
||||
extern fn free_data_box<T>(_parent: *mut c_void,
|
||||
ptr: *mut c_void,
|
||||
_ad: *mut ffi::CRYPTO_EX_DATA,
|
||||
_idx: c_int,
|
||||
|
|
@ -196,15 +132,14 @@ fn get_new_idx<T>() -> c_int {
|
|||
}
|
||||
|
||||
unsafe {
|
||||
let f: ffi::CRYPTO_EX_free = free_data_box::<T>;
|
||||
let idx = ffi::SSL_CTX_get_ex_new_index(0, ptr::null(), None, None, Some(f));
|
||||
let idx = compat::get_new_idx(free_data_box::<T>);
|
||||
assert!(idx >= 0);
|
||||
idx
|
||||
}
|
||||
}
|
||||
|
||||
fn get_new_ssl_idx<T>() -> c_int {
|
||||
extern "C" fn free_data_box<T>(_parent: *mut c_void,
|
||||
extern fn free_data_box<T>(_parent: *mut c_void,
|
||||
ptr: *mut c_void,
|
||||
_ad: *mut ffi::CRYPTO_EX_DATA,
|
||||
_idx: c_int,
|
||||
|
|
@ -216,20 +151,19 @@ fn get_new_ssl_idx<T>() -> c_int {
|
|||
}
|
||||
|
||||
unsafe {
|
||||
let f: ffi::CRYPTO_EX_free = free_data_box::<T>;
|
||||
let idx = ffi::SSL_get_ex_new_index(0, ptr::null(), None, None, Some(f));
|
||||
let idx = compat::get_new_ssl_idx(free_data_box::<T>);
|
||||
assert!(idx >= 0);
|
||||
idx
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn raw_verify<F>(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int
|
||||
extern fn raw_verify<F>(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int
|
||||
where F: Fn(bool, &X509StoreContext) -> bool + Any + 'static + Sync + Send
|
||||
{
|
||||
unsafe {
|
||||
let idx = ffi::SSL_get_ex_data_X509_STORE_CTX_idx();
|
||||
let ssl = ffi::X509_STORE_CTX_get_ex_data(x509_ctx, idx);
|
||||
let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl);
|
||||
let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl as *const _);
|
||||
let verify = ffi::SSL_CTX_get_ex_data(ssl_ctx, get_verify_data_idx::<F>());
|
||||
let verify: &F = mem::transmute(verify);
|
||||
|
||||
|
|
@ -239,13 +173,14 @@ extern "C" fn raw_verify<F>(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_
|
|||
}
|
||||
}
|
||||
|
||||
extern "C" fn ssl_raw_verify<F>(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int
|
||||
extern fn ssl_raw_verify<F>(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int
|
||||
where F: Fn(bool, &X509StoreContext) -> bool + Any + 'static + Sync + Send
|
||||
{
|
||||
unsafe {
|
||||
let idx = ffi::SSL_get_ex_data_X509_STORE_CTX_idx();
|
||||
let ssl = ffi::X509_STORE_CTX_get_ex_data(x509_ctx, idx);
|
||||
let verify = ffi::SSL_get_ex_data(ssl, get_ssl_verify_data_idx::<F>());
|
||||
let verify = ffi::SSL_get_ex_data(ssl as *const _,
|
||||
get_ssl_verify_data_idx::<F>());
|
||||
let verify: &F = mem::transmute(verify);
|
||||
|
||||
let ctx = X509StoreContext::new(x509_ctx);
|
||||
|
|
@ -254,7 +189,7 @@ extern "C" fn ssl_raw_verify<F>(preverify_ok: c_int, x509_ctx: *mut ffi::X509_ST
|
|||
}
|
||||
}
|
||||
|
||||
extern "C" fn raw_sni<F>(ssl: *mut ffi::SSL, al: *mut c_int, _arg: *mut c_void) -> c_int
|
||||
extern fn raw_sni<F>(ssl: *mut ffi::SSL, al: *mut c_int, _arg: *mut c_void) -> c_int
|
||||
where F: Fn(&mut SslRef) -> Result<(), SniError> + Any + 'static + Sync + Send
|
||||
{
|
||||
unsafe {
|
||||
|
|
@ -278,7 +213,7 @@ extern "C" fn raw_sni<F>(ssl: *mut ffi::SSL, al: *mut c_int, _arg: *mut c_void)
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "npn", feature = "alpn"))]
|
||||
#[cfg(all(any(feature = "npn", feature = "alpn"), not(ossl101)))]
|
||||
unsafe fn select_proto_using(ssl: *mut ffi::SSL,
|
||||
out: *mut *mut c_uchar,
|
||||
outlen: *mut c_uchar,
|
||||
|
|
@ -311,8 +246,8 @@ unsafe fn select_proto_using(ssl: *mut ffi::SSL,
|
|||
/// supported by the server. It achieves this by delegating to the `SSL_select_next_proto`
|
||||
/// function. The list of protocols supported by the client is found in the extra data of the
|
||||
/// OpenSSL context.
|
||||
#[cfg(feature = "npn")]
|
||||
extern "C" fn raw_next_proto_select_cb(ssl: *mut ffi::SSL,
|
||||
#[cfg(all(feature = "npn", not(ossl101)))]
|
||||
extern fn raw_next_proto_select_cb(ssl: *mut ffi::SSL,
|
||||
out: *mut *mut c_uchar,
|
||||
outlen: *mut c_uchar,
|
||||
inbuf: *const c_uchar,
|
||||
|
|
@ -322,15 +257,15 @@ extern "C" fn raw_next_proto_select_cb(ssl: *mut ffi::SSL,
|
|||
unsafe { select_proto_using(ssl, out, outlen, inbuf, inlen, *NPN_PROTOS_IDX) }
|
||||
}
|
||||
|
||||
#[cfg(feature = "alpn")]
|
||||
extern "C" fn raw_alpn_select_cb(ssl: *mut ffi::SSL,
|
||||
out: *mut *mut c_uchar,
|
||||
#[cfg(all(feature = "alpn", not(ossl101)))]
|
||||
extern fn raw_alpn_select_cb(ssl: *mut ffi::SSL,
|
||||
out: *mut *const c_uchar,
|
||||
outlen: *mut c_uchar,
|
||||
inbuf: *const c_uchar,
|
||||
inlen: c_uint,
|
||||
_arg: *mut c_void)
|
||||
-> c_int {
|
||||
unsafe { select_proto_using(ssl, out, outlen, inbuf, inlen, *ALPN_PROTOS_IDX) }
|
||||
unsafe { select_proto_using(ssl, out as *mut _, outlen, inbuf, inlen, *ALPN_PROTOS_IDX) }
|
||||
}
|
||||
|
||||
/// The function is given as the callback to `SSL_CTX_set_next_protos_advertised_cb`.
|
||||
|
|
@ -340,8 +275,8 @@ extern "C" fn raw_alpn_select_cb(ssl: *mut ffi::SSL,
|
|||
/// that it supports.
|
||||
/// The list of supported protocols is found in the extra data of the OpenSSL
|
||||
/// context.
|
||||
#[cfg(feature = "npn")]
|
||||
extern "C" fn raw_next_protos_advertise_cb(ssl: *mut ffi::SSL,
|
||||
#[cfg(all(feature = "npn", not(ossl101)))]
|
||||
extern fn raw_next_protos_advertise_cb(ssl: *mut ffi::SSL,
|
||||
out: *mut *const c_uchar,
|
||||
outlen: *mut c_uint,
|
||||
_arg: *mut c_void)
|
||||
|
|
@ -367,7 +302,7 @@ extern "C" fn raw_next_protos_advertise_cb(ssl: *mut ffi::SSL,
|
|||
|
||||
/// Convert a set of byte slices into a series of byte strings encoded for SSL. Encoding is a byte
|
||||
/// containing the length followed by the string.
|
||||
#[cfg(any(feature = "npn", feature = "alpn"))]
|
||||
#[cfg(all(any(feature = "alpn", feature = "npn"), not(ossl101)))]
|
||||
fn ssl_encode_byte_strings(strings: &[&[u8]]) -> Vec<u8> {
|
||||
let mut enc = Vec::new();
|
||||
for string in strings {
|
||||
|
|
@ -442,8 +377,8 @@ impl<'a> SslContextRef<'a> {
|
|||
ffi::SSL_CTX_set_ex_data(self.as_ptr(),
|
||||
get_verify_data_idx::<F>(),
|
||||
mem::transmute(callback));
|
||||
let f: extern "C" fn(_, _, _) -> _ = raw_sni::<F>;
|
||||
let f: extern "C" fn() = mem::transmute(f);
|
||||
let f: extern fn(_, _, _) -> _ = raw_sni::<F>;
|
||||
let f: extern fn() = mem::transmute(f);
|
||||
ffi::SSL_CTX_set_tlsext_servername_callback(self.as_ptr(), Some(f));
|
||||
}
|
||||
}
|
||||
|
|
@ -515,15 +450,12 @@ impl<'a> SslContextRef<'a> {
|
|||
}
|
||||
|
||||
/// Specifies the file that contains certificate chain
|
||||
pub fn set_certificate_chain_file<P: AsRef<Path>>(&mut self,
|
||||
file: P,
|
||||
file_type: X509FileType)
|
||||
pub fn set_certificate_chain_file<P: AsRef<Path>>(&mut self, file: P)
|
||||
-> Result<(), ErrorStack> {
|
||||
let file = CString::new(file.as_ref().as_os_str().to_str().expect("invalid utf8")).unwrap();
|
||||
wrap_ssl_result(unsafe {
|
||||
ffi::SSL_CTX_use_certificate_chain_file(self.as_ptr(),
|
||||
file.as_ptr() as *const _,
|
||||
file_type as c_int)
|
||||
file.as_ptr() as *const _)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -575,27 +507,44 @@ impl<'a> SslContextRef<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
/// If `onoff` is set to `true`, enable ECDHE for key exchange with compatible
|
||||
/// clients, and automatically select an appropriate elliptic curve.
|
||||
/// If `onoff` is set to `true`, enable ECDHE for key exchange with
|
||||
/// compatible clients, and automatically select an appropriate elliptic
|
||||
/// curve.
|
||||
///
|
||||
/// This method requires OpenSSL >= 1.0.2 or LibreSSL and the `ecdh_auto` feature.
|
||||
#[cfg(feature = "ecdh_auto")]
|
||||
/// This method requires OpenSSL >= 1.0.2 or LibreSSL and the `ecdh_auto`
|
||||
/// feature.
|
||||
#[cfg(all(feature = "ecdh_auto", not(ossl101)))]
|
||||
pub fn set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
|
||||
wrap_ssl_result(unsafe { ffi::SSL_CTX_set_ecdh_auto(self.as_ptr(), onoff as c_long) as c_int })
|
||||
self._set_ecdh_auto(onoff)
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "ecdh_auto", ossl102))]
|
||||
fn _set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> {
|
||||
wrap_ssl_result(unsafe {
|
||||
ffi::SSL_CTX_ctrl(self.as_ptr(),
|
||||
ffi::SSL_CTRL_SET_ECDH_AUTO,
|
||||
onoff as c_long,
|
||||
ptr::null_mut()) as c_int
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "ecdh_auto", ossl110))]
|
||||
fn _set_ecdh_auto(&mut self, _onoff: bool) -> Result<(), ErrorStack> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn set_options(&mut self, option: SslContextOptions) -> SslContextOptions {
|
||||
let ret = unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) };
|
||||
let ret = unsafe { compat::SSL_CTX_set_options(self.as_ptr(), option.bits()) };
|
||||
SslContextOptions::from_bits(ret).unwrap()
|
||||
}
|
||||
|
||||
pub fn options(&self) -> SslContextOptions {
|
||||
let ret = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) };
|
||||
let ret = unsafe { compat::SSL_CTX_get_options(self.as_ptr()) };
|
||||
SslContextOptions::from_bits(ret).unwrap()
|
||||
}
|
||||
|
||||
pub fn clear_options(&mut self, option: SslContextOptions) -> SslContextOptions {
|
||||
let ret = unsafe { ffi::SSL_CTX_clear_options(self.as_ptr(), option.bits()) };
|
||||
let ret = unsafe { compat::SSL_CTX_clear_options(self.as_ptr(), option.bits()) };
|
||||
SslContextOptions::from_bits(ret).unwrap()
|
||||
}
|
||||
|
||||
|
|
@ -603,7 +552,7 @@ impl<'a> SslContextRef<'a> {
|
|||
/// supported by the application).
|
||||
///
|
||||
/// This method needs the `npn` feature.
|
||||
#[cfg(feature = "npn")]
|
||||
#[cfg(all(feature = "npn", not(ossl101)))]
|
||||
pub fn set_npn_protocols(&mut self, protocols: &[&[u8]]) {
|
||||
// Firstly, convert the list of protocols to a byte-array that can be passed to OpenSSL
|
||||
// APIs -- a list of length-prefixed strings.
|
||||
|
|
@ -635,7 +584,7 @@ impl<'a> SslContextRef<'a> {
|
|||
/// Note that ordering of the protocols controls the priority with which they are chosen.
|
||||
///
|
||||
/// This method needs the `alpn` feature.
|
||||
#[cfg(feature = "alpn")]
|
||||
#[cfg(all(feature = "alpn", not(ossl101)))]
|
||||
pub fn set_alpn_protocols(&mut self, protocols: &[&[u8]]) {
|
||||
let protocols: Box<Vec<u8>> = Box::new(ssl_encode_byte_strings(protocols));
|
||||
unsafe {
|
||||
|
|
@ -662,12 +611,10 @@ pub struct SslContext(SslContextRef<'static>);
|
|||
unsafe impl Send for SslContext {}
|
||||
unsafe impl Sync for SslContext {}
|
||||
|
||||
#[cfg(feature = "ssl_context_clone")]
|
||||
impl Clone for SslContext {
|
||||
/// Requires the `ssl_context_clone` feature.
|
||||
fn clone(&self) -> Self {
|
||||
unsafe {
|
||||
::c_helpers::rust_0_8_SSL_CTX_clone(self.as_ptr());
|
||||
compat::SSL_CTX_up_ref(self.as_ptr());
|
||||
SslContext::from_ptr(self.as_ptr())
|
||||
}
|
||||
}
|
||||
|
|
@ -706,15 +653,13 @@ impl SslContext {
|
|||
init();
|
||||
|
||||
let mut ctx = unsafe {
|
||||
let ctx = try_ssl_null!(ffi::SSL_CTX_new(method.to_raw()));
|
||||
let method = compat::get_method(method);
|
||||
let ctx = try_ssl_null!(ffi::SSL_CTX_new(method));
|
||||
SslContext::from_ptr(ctx)
|
||||
};
|
||||
|
||||
match method {
|
||||
#[cfg(feature = "dtlsv1")]
|
||||
SslMethod::Dtlsv1 => ctx.set_read_ahead(1),
|
||||
#[cfg(feature = "dtlsv1_2")]
|
||||
SslMethod::Dtlsv1_2 => ctx.set_read_ahead(1),
|
||||
SslMethod::Dtls => ctx.set_read_ahead(1),
|
||||
_ => {}
|
||||
}
|
||||
// this is a bit dubious (?)
|
||||
|
|
@ -982,7 +927,7 @@ impl<'a> SslRef<'a> {
|
|||
/// to interpret it.
|
||||
///
|
||||
/// This method needs the `alpn` feature.
|
||||
#[cfg(feature = "alpn")]
|
||||
#[cfg(all(feature = "alpn", not(ossl101)))]
|
||||
pub fn selected_alpn_protocol(&self) -> Option<&[u8]> {
|
||||
unsafe {
|
||||
let mut data: *const c_uchar = ptr::null();
|
||||
|
|
@ -1023,13 +968,6 @@ impl<'a> SslRef<'a> {
|
|||
Some(s)
|
||||
}
|
||||
|
||||
pub fn ssl_method(&self) -> SslMethod {
|
||||
unsafe {
|
||||
let method = ffi::SSL_get_ssl_method(self.as_ptr());
|
||||
SslMethod::from_raw(method).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the server's name for the current connection
|
||||
pub fn servername(&self) -> Option<String> {
|
||||
let name = unsafe { ffi::SSL_get_servername(self.as_ptr(), ffi::TLSEXT_NAMETYPE_host_name) };
|
||||
|
|
@ -1319,16 +1257,12 @@ impl<S> SslStream<S> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "nightly")]
|
||||
fn check_panic(&mut self) {
|
||||
if let Some(err) = unsafe { bio::take_panic::<S>(self.ssl.get_raw_rbio()) } {
|
||||
::std::panic::resume_unwind(err)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "nightly"))]
|
||||
fn check_panic(&mut self) {}
|
||||
|
||||
fn get_bio_error(&mut self) -> io::Error {
|
||||
let error = unsafe { bio::take_error::<S>(self.ssl.get_raw_rbio()) };
|
||||
match error {
|
||||
|
|
@ -1412,3 +1346,107 @@ impl<'a> IntoSsl for &'a SslContext {
|
|||
Ssl::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl110)]
|
||||
mod compat {
|
||||
use std::ptr;
|
||||
|
||||
use ffi;
|
||||
use libc::c_int;
|
||||
|
||||
pub use ffi::{SSL_CTX_get_options, SSL_CTX_set_options};
|
||||
pub use ffi::{SSL_CTX_clear_options, SSL_CTX_up_ref};
|
||||
|
||||
use super::SslMethod;
|
||||
|
||||
pub unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int {
|
||||
ffi::CRYPTO_get_ex_new_index(ffi::CRYPTO_EX_INDEX_SSL_CTX,
|
||||
0,
|
||||
ptr::null_mut(),
|
||||
None,
|
||||
None,
|
||||
Some(f))
|
||||
}
|
||||
|
||||
pub unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
|
||||
ffi::CRYPTO_get_ex_new_index(ffi::CRYPTO_EX_INDEX_SSL,
|
||||
0,
|
||||
ptr::null_mut(),
|
||||
None,
|
||||
None,
|
||||
Some(f))
|
||||
}
|
||||
|
||||
pub unsafe fn get_method(method: SslMethod) -> *const ffi::SSL_METHOD {
|
||||
match method {
|
||||
SslMethod::Tls => ffi::TLS_method(),
|
||||
SslMethod::Dtls => ffi::DTLS_method(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl10x)]
|
||||
#[allow(bad_style)]
|
||||
mod compat {
|
||||
use std::ptr;
|
||||
|
||||
use ffi;
|
||||
use libc::{self, c_long, c_ulong, c_int};
|
||||
|
||||
use super::SslMethod;
|
||||
|
||||
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 {
|
||||
ffi::SSL_CTX_get_ex_new_index(0,
|
||||
ptr::null_mut(),
|
||||
None,
|
||||
None,
|
||||
Some(f))
|
||||
}
|
||||
|
||||
pub unsafe fn get_new_ssl_idx(f: ffi::CRYPTO_EX_free) -> c_int {
|
||||
ffi::SSL_get_ex_new_index(0,
|
||||
ptr::null_mut(),
|
||||
None,
|
||||
None,
|
||||
Some(f))
|
||||
}
|
||||
|
||||
pub unsafe fn get_method(method: SslMethod) -> *const ffi::SSL_METHOD {
|
||||
match method {
|
||||
SslMethod::Tls => ffi::SSLv23_method(),
|
||||
SslMethod::Dtls => ffi::DTLSv1_method(),
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn SSL_CTX_up_ref(ssl: *mut ffi::SSL_CTX) -> libc::c_int {
|
||||
ffi::CRYPTO_add_lock(&mut (*ssl).references,
|
||||
1,
|
||||
ffi::CRYPTO_LOCK_SSL_CTX,
|
||||
"mod.rs\0".as_ptr() as *const _,
|
||||
line!() as libc::c_int);
|
||||
0
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#![allow(unused_imports)]
|
||||
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
use std::io::{self, BufReader};
|
||||
|
|
@ -12,11 +13,12 @@ use std::thread;
|
|||
use std::time::Duration;
|
||||
|
||||
use net2::TcpStreamExt;
|
||||
use tempdir::TempDir;
|
||||
|
||||
use crypto::hash::Type::SHA256;
|
||||
use ssl;
|
||||
use ssl::SSL_VERIFY_PEER;
|
||||
use ssl::SslMethod::Sslv23;
|
||||
use ssl::SslMethod::Tls;
|
||||
use ssl::{SslMethod, HandshakeError};
|
||||
use ssl::error::Error;
|
||||
use ssl::{SslContext, SslStream};
|
||||
|
|
@ -46,10 +48,21 @@ fn next_addr() -> SocketAddr {
|
|||
|
||||
struct Server {
|
||||
p: Child,
|
||||
_temp: TempDir,
|
||||
}
|
||||
|
||||
impl Server {
|
||||
fn spawn(args: &[&str], input: Option<Box<FnMut(ChildStdin) + Send>>) -> (Server, SocketAddr) {
|
||||
static CERT: &'static [u8] = include_bytes!("../../../test/cert.pem");
|
||||
static KEY: &'static [u8] = include_bytes!("../../../test/key.pem");
|
||||
|
||||
|
||||
let td = TempDir::new("openssl").unwrap();
|
||||
let cert = td.path().join("cert.pem");
|
||||
let key = td.path().join("key.pem");
|
||||
File::create(&cert).unwrap().write_all(CERT).unwrap();
|
||||
File::create(&key).unwrap().write_all(KEY).unwrap();
|
||||
|
||||
let addr = next_addr();
|
||||
let mut child = Command::new("openssl")
|
||||
.arg("s_server")
|
||||
|
|
@ -57,11 +70,10 @@ impl Server {
|
|||
.arg(addr.port().to_string())
|
||||
.args(args)
|
||||
.arg("-cert")
|
||||
.arg("cert.pem")
|
||||
.arg(&cert)
|
||||
.arg("-key")
|
||||
.arg("key.pem")
|
||||
.arg(&key)
|
||||
.arg("-no_dhe")
|
||||
.current_dir("test")
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.stdin(Stdio::piped())
|
||||
|
|
@ -71,7 +83,7 @@ impl Server {
|
|||
if let Some(mut input) = input {
|
||||
thread::spawn(move || input(stdin));
|
||||
}
|
||||
(Server { p: child }, addr)
|
||||
(Server { p: child, _temp: td }, addr)
|
||||
}
|
||||
|
||||
fn new_tcp(args: &[&str]) -> (Server, TcpStream) {
|
||||
|
|
@ -92,7 +104,7 @@ impl Server {
|
|||
Server::new_tcp(&["-www"])
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "alpn", feature = "npn"))]
|
||||
#[cfg(all(any(feature = "alpn", feature = "npn"), not(ossl101)))]
|
||||
fn new_alpn() -> (Server, TcpStream) {
|
||||
Server::new_tcp(&["-www",
|
||||
"-nextprotoneg",
|
||||
|
|
@ -119,7 +131,7 @@ impl Server {
|
|||
// but don't currently have a great way to do that so just wait for a
|
||||
// bit.
|
||||
thread::sleep(Duration::from_millis(100));
|
||||
let socket = UdpSocket::bind(next_addr()).unwrap();
|
||||
let socket = UdpSocket::bind("127.0.0.1:0").unwrap();
|
||||
socket.connect(&addr).unwrap();
|
||||
(s, UdpConnected(socket))
|
||||
}
|
||||
|
|
@ -205,7 +217,7 @@ macro_rules! run_test(
|
|||
#[test]
|
||||
fn sslv23() {
|
||||
let (_s, stream) = Server::new();
|
||||
$blk(SslMethod::Sslv23, stream);
|
||||
$blk(SslMethod::Tls, stream);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -226,11 +238,6 @@ run_test!(new_sslstream, |method, stream| {
|
|||
SslStream::connect(&SslContext::new(method).unwrap(), stream).unwrap();
|
||||
});
|
||||
|
||||
run_test!(get_ssl_method, |method, _| {
|
||||
let ssl = Ssl::new(&SslContext::new(method).unwrap()).unwrap();
|
||||
assert_eq!(ssl.ssl_method(), method);
|
||||
});
|
||||
|
||||
run_test!(verify_untrusted, |method, stream| {
|
||||
let mut ctx = SslContext::new(method).unwrap();
|
||||
ctx.set_verify(SSL_VERIFY_PEER);
|
||||
|
|
@ -391,11 +398,11 @@ run_test!(ssl_verify_callback, |method, stream| {
|
|||
// Make sure every write call translates to a write call to the underlying socket.
|
||||
#[test]
|
||||
fn test_write_hits_stream() {
|
||||
let listener = TcpListener::bind(next_addr()).unwrap();
|
||||
let listener = TcpListener::bind("127.0.0.1:0").unwrap();
|
||||
let addr = listener.local_addr().unwrap();
|
||||
|
||||
let guard = thread::spawn(move || {
|
||||
let ctx = SslContext::new(Sslv23).unwrap();
|
||||
let ctx = SslContext::new(Tls).unwrap();
|
||||
let stream = TcpStream::connect(addr).unwrap();
|
||||
let mut stream = SslStream::connect(&ctx, stream).unwrap();
|
||||
|
||||
|
|
@ -403,7 +410,7 @@ fn test_write_hits_stream() {
|
|||
stream
|
||||
});
|
||||
|
||||
let mut ctx = SslContext::new(Sslv23).unwrap();
|
||||
let mut ctx = SslContext::new(Tls).unwrap();
|
||||
ctx.set_verify(SSL_VERIFY_PEER);
|
||||
ctx.set_certificate_file(&Path::new("test/cert.pem"), X509FileType::PEM).unwrap();
|
||||
ctx.set_private_key_file(&Path::new("test/key.pem"), X509FileType::PEM).unwrap();
|
||||
|
|
@ -423,7 +430,7 @@ fn test_set_certificate_and_private_key() {
|
|||
let cert = include_bytes!("../../../test/cert.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
|
||||
let mut ctx = SslContext::new(Sslv23).unwrap();
|
||||
let mut ctx = SslContext::new(Tls).unwrap();
|
||||
ctx.set_private_key(&key).unwrap();
|
||||
ctx.set_certificate(&cert).unwrap();
|
||||
|
||||
|
|
@ -451,7 +458,7 @@ run_test!(clear_ctx_options, |method, _| {
|
|||
#[test]
|
||||
fn test_write() {
|
||||
let (_s, stream) = Server::new();
|
||||
let mut stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), stream).unwrap();
|
||||
let mut stream = SslStream::connect(&SslContext::new(Tls).unwrap(), stream).unwrap();
|
||||
stream.write_all("hello".as_bytes()).unwrap();
|
||||
stream.flush().unwrap();
|
||||
stream.write_all(" there".as_bytes()).unwrap();
|
||||
|
|
@ -461,7 +468,7 @@ fn test_write() {
|
|||
#[test]
|
||||
fn test_write_direct() {
|
||||
let (_s, stream) = Server::new();
|
||||
let mut stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), stream).unwrap();
|
||||
let mut stream = SslStream::connect(&SslContext::new(Tls).unwrap(), stream).unwrap();
|
||||
stream.write_all("hello".as_bytes()).unwrap();
|
||||
stream.flush().unwrap();
|
||||
stream.write_all(" there".as_bytes()).unwrap();
|
||||
|
|
@ -492,7 +499,7 @@ fn test_write_dtlsv1() {
|
|||
#[test]
|
||||
fn test_read() {
|
||||
let (_s, tcp) = Server::new();
|
||||
let mut stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), tcp).unwrap();
|
||||
let mut stream = SslStream::connect(&SslContext::new(Tls).unwrap(), tcp).unwrap();
|
||||
stream.write_all("GET /\r\n\r\n".as_bytes()).unwrap();
|
||||
stream.flush().unwrap();
|
||||
io::copy(&mut stream, &mut io::sink()).ok().expect("read error");
|
||||
|
|
@ -501,7 +508,7 @@ fn test_read() {
|
|||
#[test]
|
||||
fn test_read_direct() {
|
||||
let (_s, tcp) = Server::new();
|
||||
let mut stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), tcp).unwrap();
|
||||
let mut stream = SslStream::connect(&SslContext::new(Tls).unwrap(), tcp).unwrap();
|
||||
stream.write_all("GET /\r\n\r\n".as_bytes()).unwrap();
|
||||
stream.flush().unwrap();
|
||||
io::copy(&mut stream, &mut io::sink()).ok().expect("read error");
|
||||
|
|
@ -510,7 +517,7 @@ fn test_read_direct() {
|
|||
#[test]
|
||||
fn test_pending() {
|
||||
let (_s, tcp) = Server::new();
|
||||
let mut stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), tcp).unwrap();
|
||||
let mut stream = SslStream::connect(&SslContext::new(Tls).unwrap(), tcp).unwrap();
|
||||
stream.write_all("GET /\r\n\r\n".as_bytes()).unwrap();
|
||||
stream.flush().unwrap();
|
||||
|
||||
|
|
@ -533,7 +540,7 @@ fn test_pending() {
|
|||
#[test]
|
||||
fn test_state() {
|
||||
let (_s, tcp) = Server::new();
|
||||
let stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), tcp).unwrap();
|
||||
let stream = SslStream::connect(&SslContext::new(Tls).unwrap(), tcp).unwrap();
|
||||
assert_eq!(stream.ssl().state_string(), "SSLOK ");
|
||||
assert_eq!(stream.ssl().state_string_long(),
|
||||
"SSL negotiation finished successfully");
|
||||
|
|
@ -542,10 +549,10 @@ fn test_state() {
|
|||
/// Tests that connecting with the client using ALPN, but the server not does not
|
||||
/// break the existing connection behavior.
|
||||
#[test]
|
||||
#[cfg(feature = "alpn")]
|
||||
#[cfg(all(feature = "alpn", not(ossl101)))]
|
||||
fn test_connect_with_unilateral_alpn() {
|
||||
let (_s, stream) = Server::new();
|
||||
let mut ctx = SslContext::new(Sslv23).unwrap();
|
||||
let mut ctx = SslContext::new(Tls).unwrap();
|
||||
ctx.set_verify(SSL_VERIFY_PEER);
|
||||
ctx.set_alpn_protocols(&[b"http/1.1", b"spdy/3.1"]);
|
||||
match ctx.set_CA_file(&Path::new("test/root-ca.pem")) {
|
||||
|
|
@ -564,10 +571,10 @@ fn test_connect_with_unilateral_alpn() {
|
|||
/// Tests that connecting with the client using NPN, but the server not does not
|
||||
/// break the existing connection behavior.
|
||||
#[test]
|
||||
#[cfg(feature = "npn")]
|
||||
#[cfg(all(feature = "npn", not(ossl101)))]
|
||||
fn test_connect_with_unilateral_npn() {
|
||||
let (_s, stream) = Server::new();
|
||||
let mut ctx = SslContext::new(Sslv23).unwrap();
|
||||
let mut ctx = SslContext::new(Tls).unwrap();
|
||||
ctx.set_verify(SSL_VERIFY_PEER);
|
||||
ctx.set_npn_protocols(&[b"http/1.1", b"spdy/3.1"]);
|
||||
match ctx.set_CA_file(&Path::new("test/root-ca.pem")) {
|
||||
|
|
@ -586,10 +593,10 @@ fn test_connect_with_unilateral_npn() {
|
|||
/// 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.
|
||||
#[test]
|
||||
#[cfg(feature = "alpn")]
|
||||
#[cfg(all(feature = "alpn", not(ossl101)))]
|
||||
fn test_connect_with_alpn_successful_multiple_matching() {
|
||||
let (_s, stream) = Server::new_alpn();
|
||||
let mut ctx = SslContext::new(Sslv23).unwrap();
|
||||
let mut ctx = SslContext::new(Tls).unwrap();
|
||||
ctx.set_verify(SSL_VERIFY_PEER);
|
||||
ctx.set_alpn_protocols(&[b"spdy/3.1", b"http/1.1"]);
|
||||
match ctx.set_CA_file(&Path::new("test/root-ca.pem")) {
|
||||
|
|
@ -608,10 +615,10 @@ fn test_connect_with_alpn_successful_multiple_matching() {
|
|||
/// Tests that when both the client as well as the server use NPN and their
|
||||
/// lists of supported protocols have an overlap, the correct protocol is chosen.
|
||||
#[test]
|
||||
#[cfg(feature = "npn")]
|
||||
#[cfg(all(feature = "npn", not(ossl101)))]
|
||||
fn test_connect_with_npn_successful_multiple_matching() {
|
||||
let (_s, stream) = Server::new_alpn();
|
||||
let mut ctx = SslContext::new(Sslv23).unwrap();
|
||||
let mut ctx = SslContext::new(Tls).unwrap();
|
||||
ctx.set_verify(SSL_VERIFY_PEER);
|
||||
ctx.set_npn_protocols(&[b"spdy/3.1", b"http/1.1"]);
|
||||
match ctx.set_CA_file(&Path::new("test/root-ca.pem")) {
|
||||
|
|
@ -631,10 +638,10 @@ fn test_connect_with_npn_successful_multiple_matching() {
|
|||
/// lists of supported protocols have an overlap -- with only ONE protocol
|
||||
/// being valid for both.
|
||||
#[test]
|
||||
#[cfg(feature = "alpn")]
|
||||
#[cfg(all(feature = "alpn", not(ossl101)))]
|
||||
fn test_connect_with_alpn_successful_single_match() {
|
||||
let (_s, stream) = Server::new_alpn();
|
||||
let mut ctx = SslContext::new(Sslv23).unwrap();
|
||||
let mut ctx = SslContext::new(Tls).unwrap();
|
||||
ctx.set_verify(SSL_VERIFY_PEER);
|
||||
ctx.set_alpn_protocols(&[b"spdy/3.1"]);
|
||||
match ctx.set_CA_file(&Path::new("test/root-ca.pem")) {
|
||||
|
|
@ -655,10 +662,10 @@ fn test_connect_with_alpn_successful_single_match() {
|
|||
/// lists of supported protocols have an overlap -- with only ONE protocol
|
||||
/// being valid for both.
|
||||
#[test]
|
||||
#[cfg(feature = "npn")]
|
||||
#[cfg(all(feature = "npn", not(ossl101)))]
|
||||
fn test_connect_with_npn_successful_single_match() {
|
||||
let (_s, stream) = Server::new_alpn();
|
||||
let mut ctx = SslContext::new(Sslv23).unwrap();
|
||||
let mut ctx = SslContext::new(Tls).unwrap();
|
||||
ctx.set_verify(SSL_VERIFY_PEER);
|
||||
ctx.set_npn_protocols(&[b"spdy/3.1"]);
|
||||
match ctx.set_CA_file(&Path::new("test/root-ca.pem")) {
|
||||
|
|
@ -677,13 +684,13 @@ fn test_connect_with_npn_successful_single_match() {
|
|||
/// Tests that when the `SslStream` is created as a server stream, the protocols
|
||||
/// are correctly advertised to the client.
|
||||
#[test]
|
||||
#[cfg(feature = "npn")]
|
||||
#[cfg(all(feature = "npn", not(ossl101)))]
|
||||
fn test_npn_server_advertise_multiple() {
|
||||
let listener = TcpListener::bind(next_addr()).unwrap();
|
||||
let listener = TcpListener::bind("127.0.0.1:0").unwrap();
|
||||
let localhost = listener.local_addr().unwrap();
|
||||
// We create a different context instance for the server...
|
||||
let listener_ctx = {
|
||||
let mut ctx = SslContext::new(Sslv23).unwrap();
|
||||
let mut ctx = SslContext::new(Tls).unwrap();
|
||||
ctx.set_verify(SSL_VERIFY_PEER);
|
||||
ctx.set_npn_protocols(&[b"http/1.1", b"spdy/3.1"]);
|
||||
assert!(ctx.set_certificate_file(&Path::new("test/cert.pem"), X509FileType::PEM)
|
||||
|
|
@ -698,7 +705,7 @@ fn test_npn_server_advertise_multiple() {
|
|||
let _ = SslStream::accept(&listener_ctx, stream).unwrap();
|
||||
});
|
||||
|
||||
let mut ctx = SslContext::new(Sslv23).unwrap();
|
||||
let mut ctx = SslContext::new(Tls).unwrap();
|
||||
ctx.set_verify(SSL_VERIFY_PEER);
|
||||
ctx.set_npn_protocols(&[b"spdy/3.1"]);
|
||||
match ctx.set_CA_file(&Path::new("test/root-ca.pem")) {
|
||||
|
|
@ -718,13 +725,13 @@ fn test_npn_server_advertise_multiple() {
|
|||
/// Tests that when the `SslStream` is created as a server stream, the protocols
|
||||
/// are correctly advertised to the client.
|
||||
#[test]
|
||||
#[cfg(feature = "alpn")]
|
||||
#[cfg(all(feature = "alpn", not(ossl101)))]
|
||||
fn test_alpn_server_advertise_multiple() {
|
||||
let listener = TcpListener::bind(next_addr()).unwrap();
|
||||
let listener = TcpListener::bind("127.0.0.1:0").unwrap();
|
||||
let localhost = listener.local_addr().unwrap();
|
||||
// We create a different context instance for the server...
|
||||
let listener_ctx = {
|
||||
let mut ctx = SslContext::new(Sslv23).unwrap();
|
||||
let mut ctx = SslContext::new(Tls).unwrap();
|
||||
ctx.set_verify(SSL_VERIFY_PEER);
|
||||
ctx.set_alpn_protocols(&[b"http/1.1", b"spdy/3.1"]);
|
||||
assert!(ctx.set_certificate_file(&Path::new("test/cert.pem"), X509FileType::PEM)
|
||||
|
|
@ -739,7 +746,7 @@ fn test_alpn_server_advertise_multiple() {
|
|||
let _ = SslStream::accept(&listener_ctx, stream).unwrap();
|
||||
});
|
||||
|
||||
let mut ctx = SslContext::new(Sslv23).unwrap();
|
||||
let mut ctx = SslContext::new(Tls).unwrap();
|
||||
ctx.set_verify(SSL_VERIFY_PEER);
|
||||
ctx.set_alpn_protocols(&[b"spdy/3.1"]);
|
||||
match ctx.set_CA_file(&Path::new("test/root-ca.pem")) {
|
||||
|
|
@ -759,13 +766,13 @@ fn test_alpn_server_advertise_multiple() {
|
|||
/// Test that Servers supporting ALPN don't report a protocol when none of their protocols match
|
||||
/// the client's reported protocol.
|
||||
#[test]
|
||||
#[cfg(feature = "alpn")]
|
||||
#[cfg(all(feature = "alpn", not(ossl101)))]
|
||||
fn test_alpn_server_select_none() {
|
||||
let listener = TcpListener::bind(next_addr()).unwrap();
|
||||
let listener = TcpListener::bind("127.0.0.1:0").unwrap();
|
||||
let localhost = listener.local_addr().unwrap();
|
||||
// We create a different context instance for the server...
|
||||
let listener_ctx = {
|
||||
let mut ctx = SslContext::new(Sslv23).unwrap();
|
||||
let mut ctx = SslContext::new(Tls).unwrap();
|
||||
ctx.set_verify(SSL_VERIFY_PEER);
|
||||
ctx.set_alpn_protocols(&[b"http/1.1", b"spdy/3.1"]);
|
||||
assert!(ctx.set_certificate_file(&Path::new("test/cert.pem"), X509FileType::PEM)
|
||||
|
|
@ -780,7 +787,7 @@ fn test_alpn_server_select_none() {
|
|||
let _ = SslStream::accept(&listener_ctx, stream).unwrap();
|
||||
});
|
||||
|
||||
let mut ctx = SslContext::new(Sslv23).unwrap();
|
||||
let mut ctx = SslContext::new(Tls).unwrap();
|
||||
ctx.set_verify(SSL_VERIFY_PEER);
|
||||
ctx.set_alpn_protocols(&[b"http/2"]);
|
||||
match ctx.set_CA_file(&Path::new("test/root-ca.pem")) {
|
||||
|
|
@ -875,7 +882,7 @@ fn handshake(res: Result<SslStream<TcpStream>, HandshakeError<TcpStream>>)
|
|||
fn test_write_nonblocking() {
|
||||
let (_s, stream) = Server::new();
|
||||
stream.set_nonblocking(true).unwrap();
|
||||
let cx = SslContext::new(Sslv23).unwrap();
|
||||
let cx = SslContext::new(Tls).unwrap();
|
||||
let mut stream = handshake(SslStream::connect(&cx, stream));
|
||||
|
||||
let mut iterations = 0;
|
||||
|
|
@ -913,7 +920,7 @@ fn test_write_nonblocking() {
|
|||
fn test_read_nonblocking() {
|
||||
let (_s, stream) = Server::new();
|
||||
stream.set_nonblocking(true).unwrap();
|
||||
let cx = SslContext::new(Sslv23).unwrap();
|
||||
let cx = SslContext::new(Tls).unwrap();
|
||||
let mut stream = handshake(SslStream::connect(&cx, stream));
|
||||
|
||||
let mut iterations = 0;
|
||||
|
|
@ -965,7 +972,6 @@ fn test_read_nonblocking() {
|
|||
|
||||
#[test]
|
||||
#[should_panic(expected = "blammo")]
|
||||
#[cfg(feature = "nightly")]
|
||||
fn write_panic() {
|
||||
struct ExplodingStream(TcpStream);
|
||||
|
||||
|
|
@ -988,13 +994,12 @@ fn write_panic() {
|
|||
let (_s, stream) = Server::new();
|
||||
let stream = ExplodingStream(stream);
|
||||
|
||||
let ctx = SslContext::new(SslMethod::Sslv23).unwrap();
|
||||
let ctx = SslContext::new(SslMethod::Tls).unwrap();
|
||||
let _ = SslStream::connect(&ctx, stream);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "blammo")]
|
||||
#[cfg(feature = "nightly")]
|
||||
fn read_panic() {
|
||||
struct ExplodingStream(TcpStream);
|
||||
|
||||
|
|
@ -1017,13 +1022,12 @@ fn read_panic() {
|
|||
let (_s, stream) = Server::new();
|
||||
let stream = ExplodingStream(stream);
|
||||
|
||||
let ctx = SslContext::new(SslMethod::Sslv23).unwrap();
|
||||
let ctx = SslContext::new(SslMethod::Tls).unwrap();
|
||||
let _ = SslStream::connect(&ctx, stream);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "blammo")]
|
||||
#[cfg(feature = "nightly")]
|
||||
fn flush_panic() {
|
||||
struct ExplodingStream(TcpStream);
|
||||
|
||||
|
|
@ -1046,20 +1050,20 @@ fn flush_panic() {
|
|||
let (_s, stream) = Server::new();
|
||||
let stream = ExplodingStream(stream);
|
||||
|
||||
let ctx = SslContext::new(SslMethod::Sslv23).unwrap();
|
||||
let mut stream = SslStream::connect(&ctx, stream).unwrap();
|
||||
let ctx = SslContext::new(SslMethod::Tls).unwrap();
|
||||
let mut stream = SslStream::connect(&ctx, stream).ok().unwrap();
|
||||
let _ = stream.flush();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn refcount_ssl_context() {
|
||||
let mut ssl = {
|
||||
let ctx = SslContext::new(SslMethod::Sslv23).unwrap();
|
||||
let ctx = SslContext::new(SslMethod::Tls).unwrap();
|
||||
ssl::Ssl::new(&ctx).unwrap()
|
||||
};
|
||||
|
||||
{
|
||||
let new_ctx_a = SslContext::new(SslMethod::Sslv23).unwrap();
|
||||
let new_ctx_a = SslContext::new(SslMethod::Tls).unwrap();
|
||||
let _new_ctx_b = ssl.set_ssl_context(&new_ctx_a);
|
||||
}
|
||||
}
|
||||
|
|
@ -1067,7 +1071,7 @@ fn refcount_ssl_context() {
|
|||
#[test]
|
||||
#[cfg_attr(windows, ignore)] // don't have a trusted CA list easily available :(
|
||||
fn default_verify_paths() {
|
||||
let mut ctx = SslContext::new(SslMethod::Sslv23).unwrap();
|
||||
let mut ctx = SslContext::new(SslMethod::Tls).unwrap();
|
||||
ctx.set_default_verify_paths().unwrap();
|
||||
ctx.set_verify(SSL_VERIFY_PEER);
|
||||
let s = TcpStream::connect("google.com:443").unwrap();
|
||||
|
|
@ -1086,6 +1090,6 @@ fn default_verify_paths() {
|
|||
fn add_extra_chain_cert() {
|
||||
let cert = include_bytes!("../../../test/cert.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
let mut ctx = SslContext::new(SslMethod::Sslv23).unwrap();
|
||||
let mut ctx = SslContext::new(SslMethod::Tls).unwrap();
|
||||
ctx.add_extra_chain_cert(&cert).unwrap();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,9 +11,26 @@
|
|||
// limitations under the License.
|
||||
//
|
||||
|
||||
use ffi;
|
||||
use std::ffi::CStr;
|
||||
|
||||
#[cfg(ossl10x)]
|
||||
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_DIR as OPENSSL_DIR,
|
||||
SSLeay as OpenSSL_version_num,
|
||||
SSLeay_version as OpenSSL_version,
|
||||
};
|
||||
|
||||
#[cfg(ossl110)]
|
||||
use ffi::{OPENSSL_VERSION, OPENSSL_CFLAGS};
|
||||
#[cfg(ossl110)]
|
||||
use ffi::{OPENSSL_BUILT_ON, OPENSSL_PLATFORM, OPENSSL_DIR};
|
||||
#[cfg(ossl110)]
|
||||
use ffi::{OpenSSL_version_num, OpenSSL_version};
|
||||
|
||||
/// OPENSSL_VERSION_NUMBER is a numeric release version identifier:
|
||||
///
|
||||
/// `MNNFFPPS: major minor fix patch status`
|
||||
|
|
@ -39,34 +56,34 @@ use std::ffi::CStr;
|
|||
///
|
||||
/// The return value of this function can be compared to the macro to make sure that the correct version of the library has been loaded, especially when using DLLs on Windows systems.
|
||||
pub fn number() -> i64 {
|
||||
unsafe { ffi::SSLeay() 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".
|
||||
pub fn version() -> &'static str {
|
||||
unsafe { CStr::from_ptr(ffi::SSLeay_version(ffi::SSLEAY_VERSION)).to_str().unwrap() }
|
||||
unsafe { CStr::from_ptr(OpenSSL_version(OPENSSL_VERSION)).to_str().unwrap() }
|
||||
}
|
||||
|
||||
/// The compiler flags set for the compilation process in the form "compiler: ..." if available or
|
||||
/// "compiler: information not available" otherwise.
|
||||
pub fn c_flags() -> &'static str {
|
||||
unsafe { CStr::from_ptr(ffi::SSLeay_version(ffi::SSLEAY_CFLAGS)).to_str().unwrap() }
|
||||
unsafe { CStr::from_ptr(OpenSSL_version(OPENSSL_CFLAGS)).to_str().unwrap() }
|
||||
}
|
||||
|
||||
/// The date of the build process in the form "built on: ..." if available or "built on: date not available" otherwise.
|
||||
pub fn built_on() -> &'static str {
|
||||
unsafe { CStr::from_ptr(ffi::SSLeay_version(ffi::SSLEAY_BUILT_ON)).to_str().unwrap() }
|
||||
unsafe { CStr::from_ptr(OpenSSL_version(OPENSSL_BUILT_ON)).to_str().unwrap() }
|
||||
}
|
||||
|
||||
/// The "Configure" target of the library build in the form "platform: ..." if available or "platform: information not available" otherwise.
|
||||
pub fn platform() -> &'static str {
|
||||
unsafe { CStr::from_ptr(ffi::SSLeay_version(ffi::SSLEAY_PLATFORM)).to_str().unwrap() }
|
||||
unsafe { CStr::from_ptr(OpenSSL_version(OPENSSL_PLATFORM)).to_str().unwrap() }
|
||||
}
|
||||
|
||||
/// The "OPENSSLDIR" setting of the library build in the form "OPENSSLDIR: "..."" if available or "OPENSSLDIR: N/A" otherwise.
|
||||
pub fn dir() -> &'static str {
|
||||
unsafe { CStr::from_ptr(ffi::SSLeay_version(ffi::SSLEAY_DIR)).to_str().unwrap() }
|
||||
unsafe { CStr::from_ptr(OpenSSL_version(OPENSSL_DIR)).to_str().unwrap() }
|
||||
}
|
||||
|
||||
/// This test ensures that we do not segfault when calling the functions of this module
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ use std::marker::PhantomData;
|
|||
|
||||
use HashTypeInternals;
|
||||
use asn1::Asn1Time;
|
||||
#[cfg(feature = "x509_expiry")]
|
||||
use asn1::Asn1TimeRef;
|
||||
|
||||
use bio::{MemBio, MemBioSlice};
|
||||
|
|
@ -24,6 +23,19 @@ use ffi;
|
|||
use nid::Nid;
|
||||
use error::ErrorStack;
|
||||
|
||||
#[cfg(ossl10x)]
|
||||
use ffi::{
|
||||
X509_set_notBefore,
|
||||
X509_set_notAfter,
|
||||
ASN1_STRING_data,
|
||||
};
|
||||
#[cfg(ossl110)]
|
||||
use ffi::{
|
||||
X509_set1_notBefore as X509_set_notBefore,
|
||||
X509_set1_notAfter as X509_set_notAfter,
|
||||
ASN1_STRING_get0_data as ASN1_STRING_data,
|
||||
};
|
||||
|
||||
pub mod extension;
|
||||
|
||||
use self::extension::{ExtensionType, Extension};
|
||||
|
|
@ -36,7 +48,7 @@ pub struct SslString(&'static str);
|
|||
impl<'s> Drop for SslString {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
ffi::CRYPTO_free(self.0.as_ptr() as *mut c_void);
|
||||
CRYPTO_free!(self.0.as_ptr() as *mut c_void);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -50,8 +62,8 @@ impl Deref for SslString {
|
|||
}
|
||||
|
||||
impl SslString {
|
||||
unsafe fn new(buf: *const c_char, len: c_int) -> SslString {
|
||||
let slice = slice::from_raw_parts(buf as *const _, len as usize);
|
||||
unsafe fn new(buf: *const u8, len: c_int) -> SslString {
|
||||
let slice = slice::from_raw_parts(buf, len as usize);
|
||||
SslString(str::from_utf8_unchecked(slice))
|
||||
}
|
||||
}
|
||||
|
|
@ -311,11 +323,11 @@ impl X509Generator {
|
|||
let not_before = try!(Asn1Time::days_from_now(0));
|
||||
let not_after = try!(Asn1Time::days_from_now(self.days));
|
||||
|
||||
try_ssl!(ffi::X509_set_notBefore(x509.as_ptr(), not_before.as_ptr() as *const _));
|
||||
try_ssl!(X509_set_notBefore(x509.as_ptr(), not_before.as_ptr() as *const _));
|
||||
// If prev line succeded - ownership should go to cert
|
||||
mem::forget(not_before);
|
||||
|
||||
try_ssl!(ffi::X509_set_notAfter(x509.as_ptr(), not_after.as_ptr() as *const _));
|
||||
try_ssl!(X509_set_notAfter(x509.as_ptr(), not_after.as_ptr() as *const _));
|
||||
// If prev line succeded - ownership should go to cert
|
||||
mem::forget(not_after);
|
||||
|
||||
|
|
@ -350,9 +362,6 @@ impl X509Generator {
|
|||
}
|
||||
|
||||
/// Obtain a certificate signing request (CSR)
|
||||
///
|
||||
/// Requries the `x509_generator_request` feature.
|
||||
#[cfg(feature = "x509_generator_request")]
|
||||
pub fn request(&self, p_key: &PKey) -> Result<X509Req, ErrorStack> {
|
||||
let cert = match self.sign(p_key) {
|
||||
Ok(c) => c,
|
||||
|
|
@ -363,9 +372,9 @@ impl X509Generator {
|
|||
let req = ffi::X509_to_X509_REQ(cert.as_ptr(), ptr::null_mut(), ptr::null());
|
||||
try_ssl_null!(req);
|
||||
|
||||
let exts = ::c_helpers::rust_0_8_X509_get_extensions(cert.as_ptr());
|
||||
let exts = compat::X509_get0_extensions(cert.as_ptr());
|
||||
if exts != ptr::null_mut() {
|
||||
try_ssl!(ffi::X509_REQ_add_extensions(req, exts));
|
||||
try_ssl!(ffi::X509_REQ_add_extensions(req, exts as *mut _));
|
||||
}
|
||||
|
||||
let hash_fn = self.hash_type.evp_md();
|
||||
|
|
@ -438,22 +447,18 @@ impl<'a> X509Ref<'a> {
|
|||
}
|
||||
|
||||
/// Returns certificate Not After validity period.
|
||||
/// Requires the `x509_expiry` feature.
|
||||
#[cfg(feature = "x509_expiry")]
|
||||
pub fn not_after<'b>(&'b self) -> Asn1TimeRef<'b> {
|
||||
unsafe {
|
||||
let date = ::c_helpers::rust_0_8_X509_get_notAfter(self.0);
|
||||
let date = compat::X509_get_notAfter(self.0);
|
||||
assert!(!date.is_null());
|
||||
Asn1TimeRef::from_ptr(date)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns certificate Not Before validity period.
|
||||
/// Requires the `x509_expiry` feature.
|
||||
#[cfg(feature = "x509_expiry")]
|
||||
pub fn not_before<'b>(&'b self) -> Asn1TimeRef<'b> {
|
||||
unsafe {
|
||||
let date = ::c_helpers::rust_0_8_X509_get_notBefore(self.0);
|
||||
let date = compat::X509_get_notBefore(self.0);
|
||||
assert!(!date.is_null());
|
||||
Asn1TimeRef::from_ptr(date)
|
||||
}
|
||||
|
|
@ -496,7 +501,7 @@ impl X509 {
|
|||
/// Reads a certificate from DER.
|
||||
pub fn from_der(buf: &[u8]) -> Result<X509, ErrorStack> {
|
||||
unsafe {
|
||||
let mut ptr = buf.as_ptr() as *mut _;
|
||||
let mut ptr = buf.as_ptr();
|
||||
let len = cmp::min(buf.len(), c_long::max_value() as usize) as c_long;
|
||||
let x509 = try_ssl_null!(ffi::d2i_X509(ptr::null_mut(), &mut ptr, len));
|
||||
Ok(X509::from_ptr(x509))
|
||||
|
|
@ -524,13 +529,11 @@ impl Deref for X509 {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "x509_clone")]
|
||||
impl Clone for X509 {
|
||||
/// Requires the `x509_clone` feature.
|
||||
fn clone(&self) -> X509 {
|
||||
unsafe {
|
||||
::c_helpers::rust_0_8_X509_clone(self.as_ptr());
|
||||
X509::new(self.as_ptr())
|
||||
compat::X509_up_ref(self.as_ptr());
|
||||
X509::from_ptr(self.as_ptr())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -561,7 +564,7 @@ impl<'x> X509Name<'x> {
|
|||
return None;
|
||||
}
|
||||
|
||||
let mut str_from_asn1: *mut c_char = ptr::null_mut();
|
||||
let mut str_from_asn1: *mut u8 = ptr::null_mut();
|
||||
let len = ffi::ASN1_STRING_to_UTF8(&mut str_from_asn1, asn1_str);
|
||||
|
||||
if len < 0 {
|
||||
|
|
@ -779,22 +782,43 @@ pub struct GeneralNames<'a> {
|
|||
}
|
||||
|
||||
impl<'a> Drop for GeneralNames<'a> {
|
||||
#[cfg(ossl10x)]
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
// This transmute is dubious but it's what openssl itself does...
|
||||
let free: unsafe extern "C" fn(*mut ffi::GENERAL_NAME) = ffi::GENERAL_NAME_free;
|
||||
let free: unsafe extern "C" fn(*mut c_void) = mem::transmute(free);
|
||||
let free: unsafe extern fn(*mut ffi::GENERAL_NAME) = ffi::GENERAL_NAME_free;
|
||||
let free: unsafe extern fn(*mut c_void) = mem::transmute(free);
|
||||
ffi::sk_pop_free(&mut (*self.stack).stack, Some(free));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl110)]
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
// This transmute is dubious but it's what openssl itself does...
|
||||
let free: unsafe extern fn(*mut ffi::GENERAL_NAME) = ffi::GENERAL_NAME_free;
|
||||
let free: unsafe extern fn(*mut c_void) = mem::transmute(free);
|
||||
ffi::OPENSSL_sk_pop_free(self.stack as *mut _, Some(free));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> GeneralNames<'a> {
|
||||
/// Returns the number of `GeneralName`s in this structure.
|
||||
pub fn len(&self) -> usize {
|
||||
self._len()
|
||||
}
|
||||
|
||||
#[cfg(ossl10x)]
|
||||
fn _len(&self) -> usize {
|
||||
unsafe { (*self.stack).stack.num as usize }
|
||||
}
|
||||
|
||||
#[cfg(ossl110)]
|
||||
fn _len(&self) -> usize {
|
||||
unsafe { ffi::OPENSSL_sk_num(self.stack as *const _) as usize }
|
||||
}
|
||||
|
||||
/// Returns the specified `GeneralName`.
|
||||
///
|
||||
/// # Panics
|
||||
|
|
@ -803,14 +827,23 @@ impl<'a> GeneralNames<'a> {
|
|||
pub fn get(&self, idx: usize) -> GeneralName<'a> {
|
||||
unsafe {
|
||||
assert!(idx < self.len());
|
||||
|
||||
GeneralName {
|
||||
name: *(*self.stack).stack.data.offset(idx as isize) as *const ffi::GENERAL_NAME,
|
||||
name: self._get(idx),
|
||||
m: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl10x)]
|
||||
unsafe fn _get(&self, idx: usize) -> *const ffi::GENERAL_NAME {
|
||||
*(*self.stack).stack.data.offset(idx as isize) as *const ffi::GENERAL_NAME
|
||||
}
|
||||
|
||||
#[cfg(ossl110)]
|
||||
unsafe fn _get(&self, idx: usize) -> *const ffi::GENERAL_NAME {
|
||||
ffi::OPENSSL_sk_value(self.stack as *const _, idx as c_int) as *mut _
|
||||
}
|
||||
|
||||
/// Returns an iterator over the `GeneralName`s in this structure.
|
||||
pub fn iter(&self) -> GeneralNamesIter {
|
||||
GeneralNamesIter {
|
||||
|
|
@ -870,7 +903,7 @@ impl<'a> GeneralName<'a> {
|
|||
return None;
|
||||
}
|
||||
|
||||
let ptr = ffi::ASN1_STRING_data((*self.name).d as *mut _);
|
||||
let ptr = ASN1_STRING_data((*self.name).d as *mut _);
|
||||
let len = ffi::ASN1_STRING_length((*self.name).d as *mut _);
|
||||
|
||||
let slice = slice::from_raw_parts(ptr as *const u8, len as usize);
|
||||
|
|
@ -888,7 +921,7 @@ impl<'a> GeneralName<'a> {
|
|||
return None;
|
||||
}
|
||||
|
||||
let ptr = ffi::ASN1_STRING_data((*self.name).d as *mut _);
|
||||
let ptr = ASN1_STRING_data((*self.name).d as *mut _);
|
||||
let len = ffi::ASN1_STRING_length((*self.name).d as *mut _);
|
||||
|
||||
Some(slice::from_raw_parts(ptr as *const u8, len as usize))
|
||||
|
|
@ -904,3 +937,44 @@ fn test_negative_serial() {
|
|||
"All serials should be positive");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl110)]
|
||||
mod compat {
|
||||
pub use ffi::X509_getm_notAfter as X509_get_notAfter;
|
||||
pub use ffi::X509_getm_notBefore as X509_get_notBefore;
|
||||
pub use ffi::X509_up_ref;
|
||||
pub use ffi::X509_get0_extensions;
|
||||
}
|
||||
|
||||
#[cfg(ossl10x)]
|
||||
#[allow(bad_style)]
|
||||
mod compat {
|
||||
use libc::c_int;
|
||||
use ffi;
|
||||
|
||||
pub unsafe fn X509_get_notAfter(x: *mut ffi::X509) -> *mut ffi::ASN1_TIME {
|
||||
(*(*(*x).cert_info).validity).notAfter
|
||||
}
|
||||
|
||||
pub unsafe fn X509_get_notBefore(x: *mut ffi::X509) -> *mut ffi::ASN1_TIME {
|
||||
(*(*(*x).cert_info).validity).notBefore
|
||||
}
|
||||
|
||||
pub unsafe fn X509_up_ref(x: *mut ffi::X509) {
|
||||
ffi::CRYPTO_add_lock(&mut (*x).references,
|
||||
1,
|
||||
ffi::CRYPTO_LOCK_X509,
|
||||
"mod.rs\0".as_ptr() as *const _,
|
||||
line!() as c_int);
|
||||
}
|
||||
|
||||
pub unsafe fn X509_get0_extensions(cert: *const ffi::X509)
|
||||
-> *const ffi::stack_st_X509_EXTENSION {
|
||||
let info = (*cert).cert_info;
|
||||
if info.is_null() {
|
||||
0 as *mut _
|
||||
} else {
|
||||
(*info).extensions
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,7 +69,6 @@ fn test_cert_gen_extension_bad_ordering() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "x509_generator_request")]
|
||||
fn test_req_gen() {
|
||||
let pkey = pkey();
|
||||
|
||||
|
|
@ -93,7 +92,6 @@ fn test_cert_loading() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "x509_expiry")]
|
||||
fn test_cert_issue_validity() {
|
||||
let cert = include_bytes!("../../test/cert.pem");
|
||||
let cert = X509::from_pem(cert).ok().expect("Failed to load PEM");
|
||||
|
|
|
|||
|
|
@ -1,33 +1,48 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
set -ex
|
||||
|
||||
MAX_REDIRECTS=5
|
||||
OPENSSL=openssl-1.0.2h.tar.gz
|
||||
OPENSSL=openssl-$BUILD_OPENSSL_VERSION.tar.gz
|
||||
OUT=/tmp/$OPENSSL
|
||||
SHA1="577585f5f5d299c44dd3c993d3c0ac7a219e4949"
|
||||
|
||||
me=$0
|
||||
myname=`basename $me`
|
||||
|
||||
cmp --silent $me $HOME/openssl/$myname && exit 0 || echo "cache is busted"
|
||||
|
||||
rm -rf $HOME/openssl
|
||||
|
||||
if [ "$TRAVIS_OS_NAME" == "osx" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$TARGET" == "arm-unknown-linux-gnueabihf" ]; then
|
||||
export C_INCLUDE_PATH=/usr/arm-linux-gnueabihf/include
|
||||
CROSS=arm-linux-gnueabihf-
|
||||
if [ "$BUILD_OPENSSL_VERSION" == "" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$TARGET" == "i686-unknown-linux-gnu" ]; then
|
||||
OS_COMPILER=linux-elf
|
||||
OS_FLAGS=-m32
|
||||
elif [ "$TARGET" == "arm-unknown-linux-gnueabihf" ]; then
|
||||
OS_COMPILER=linux-armv4
|
||||
export AR=arm-linux-gnueabihf-ar
|
||||
export CC=arm-linux-gnueabihf-gcc
|
||||
else
|
||||
OS_COMPILER=linux-x86_64
|
||||
fi
|
||||
|
||||
mkdir -p /tmp/openssl
|
||||
cp $me /tmp/openssl/$myname
|
||||
cd /tmp/openssl
|
||||
|
||||
curl -o $OUT -L --max-redirs $MAX_REDIRECTS https://openssl.org/source/$OPENSSL \
|
||||
|| curl -o $OUT -L --max-redirs ${MAX_REDIRECTS} http://mirrors.ibiblio.org/openssl/source/$OPENSSL
|
||||
|
||||
echo "$SHA1 $OUT" | sha1sum -c -
|
||||
|
||||
tar --strip-components=1 -xzf $OUT
|
||||
|
||||
./Configure --prefix=$HOME/openssl shared --cross-compile-prefix=$CROSS $OS_COMPILER
|
||||
make
|
||||
./Configure --prefix=$HOME/openssl $OS_COMPILER -fPIC $OS_FLAGS
|
||||
|
||||
make -j$(nproc)
|
||||
make install
|
||||
cp $myname $HOME/openssl/$myname
|
||||
|
|
|
|||
|
|
@ -1,32 +1,15 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
MAIN_TARGETS=https://static.rust-lang.org/dist
|
||||
|
||||
if [ "$TEST_FEATURES" == "true" ]; then
|
||||
FEATURES="tlsv1_2 tlsv1_1 dtlsv1 dtlsv1_2 sslv3 aes_xts aes_ctr npn alpn rfc5114 ecdh_auto pkcs5_pbkdf2_hmac x509_clone ssl_context_clone x509_generator_request hmac hmac_clone dh_from_params x509_expiry"
|
||||
fi
|
||||
|
||||
if [ "$TRAVIS_OS_NAME" != "osx" ]; then
|
||||
export OPENSSL_LIB_DIR=$HOME/openssl/lib
|
||||
export OPENSSL_INCLUDE_DIR=$HOME/openssl/include
|
||||
export LD_LIBRARY_PATH=$HOME/openssl/lib:$LD_LIBRARY_PATH
|
||||
fi
|
||||
|
||||
if [ -n "$TARGET" ]; then
|
||||
FLAGS="--target=$TARGET"
|
||||
COMMAND="build"
|
||||
|
||||
# Download the rustlib folder from the relevant portion of main distribution's
|
||||
# tarballs.
|
||||
dir=rust-std-$TARGET
|
||||
pkg=rust-std
|
||||
curl -s $MAIN_TARGETS/$pkg-$TRAVIS_RUST_VERSION-$TARGET.tar.gz | \
|
||||
tar xzf - -C $HOME/rust/lib/rustlib --strip-components=4 \
|
||||
$pkg-$TRAVIS_RUST_VERSION-$TARGET/$dir/lib/rustlib/$TARGET
|
||||
else
|
||||
COMMAND="test"
|
||||
if [ "$BUILD_OPENSSL_VERSION" != "" ]; then
|
||||
FEATURES="aes_xts aes_ctr npn alpn rfc5114 ecdh_auto"
|
||||
fi
|
||||
|
||||
if [ -d "$HOME/openssl/lib" ]; then
|
||||
export OPENSSL_DIR=$HOME/openssl
|
||||
export PATH=$HOME/openssl/bin:$PATH
|
||||
(cd openssl && RUST_BACKTRACE=1 cargo $COMMAND $FLAGS --features "$FEATURES")
|
||||
fi
|
||||
|
||||
cargo run --manifest-path systest/Cargo.toml --target $TARGET
|
||||
exec cargo test --manifest-path openssl/Cargo.toml --target $TARGET \
|
||||
--features "$FEATURES"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
[package]
|
||||
name = "systest"
|
||||
version = "0.1.0"
|
||||
authors = ["Alex Crichton <alex@alexcrichton.com>"]
|
||||
build = "build.rs"
|
||||
|
||||
[dependencies]
|
||||
libc = "0.2"
|
||||
openssl-sys = { path = "../openssl-sys" }
|
||||
|
||||
[build-dependencies]
|
||||
ctest = "0.1"
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
extern crate ctest;
|
||||
|
||||
use std::env;
|
||||
|
||||
fn main() {
|
||||
let mut cfg = ctest::TestGenerator::new();
|
||||
let target = env::var("TARGET").unwrap();
|
||||
|
||||
if let Ok(out) = env::var("DEP_OPENSSL_INCLUDE") {
|
||||
cfg.include(&out);
|
||||
}
|
||||
|
||||
// Needed to get OpenSSL to correctly undef symbols that are already on
|
||||
// Windows like X509_NAME
|
||||
if target.contains("windows") {
|
||||
cfg.header("windows.h");
|
||||
|
||||
// weird "different 'const' qualifiers" error on Windows, maybe a cl.exe
|
||||
// thing?
|
||||
if target.contains("msvc") {
|
||||
cfg.flag("/wd4090");
|
||||
}
|
||||
}
|
||||
|
||||
if env::var("DEP_OPENSSL_IS_101").is_ok() {
|
||||
cfg.cfg("ossl101", None);
|
||||
}
|
||||
if env::var("DEP_OPENSSL_IS_102").is_ok() {
|
||||
cfg.cfg("ossl102", None);
|
||||
}
|
||||
if env::var("DEP_OPENSSL_IS_110").is_ok() {
|
||||
cfg.cfg("ossl110", None);
|
||||
}
|
||||
|
||||
cfg.header("openssl/comp.h")
|
||||
.header("openssl/dh.h")
|
||||
.header("openssl/ossl_typ.h")
|
||||
.header("openssl/stack.h")
|
||||
.header("openssl/x509.h")
|
||||
.header("openssl/bio.h")
|
||||
.header("openssl/x509v3.h")
|
||||
.header("openssl/safestack.h")
|
||||
.header("openssl/hmac.h")
|
||||
.header("openssl/ssl.h")
|
||||
.header("openssl/err.h")
|
||||
.header("openssl/rand.h")
|
||||
.header("openssl/pkcs12.h")
|
||||
.header("openssl/bn.h");
|
||||
cfg.type_name(|s, is_struct| {
|
||||
// Add some `*` on some callback parameters to get function pointer to
|
||||
// typecheck in C, especially on MSVC.
|
||||
if s == "PasswordCallback" {
|
||||
format!("pem_password_cb*")
|
||||
} else if s == "bio_info_cb" {
|
||||
format!("bio_info_cb*")
|
||||
} else if s == "_STACK" {
|
||||
format!("struct stack_st")
|
||||
} else if is_struct && s.chars().next().unwrap().is_lowercase() {
|
||||
format!("struct {}", s)
|
||||
} else {
|
||||
format!("{}", s)
|
||||
}
|
||||
});
|
||||
cfg.skip_type(|s| {
|
||||
// function pointers are declared without a `*` in openssl so their
|
||||
// sizeof is 1 which isn't what we want.
|
||||
s == "PasswordCallback" ||
|
||||
s == "bio_info_cb" ||
|
||||
s.starts_with("CRYPTO_EX_")
|
||||
});
|
||||
cfg.skip_struct(|s| {
|
||||
s == "ProbeResult"
|
||||
});
|
||||
cfg.skip_fn(move |s| {
|
||||
s == "CRYPTO_memcmp" || // uses volatile
|
||||
s == "X509V3_EXT_conf_nid" || // weird lhash first param
|
||||
s == "X509V3_EXT_conf" || // weird lhash first param
|
||||
|
||||
// one parameter is `const` in OpenSSL 1.0.1, no need for a new
|
||||
// definition or a new file here.
|
||||
(s == "BIO_new_mem_buf" && env::var("DEP_OPENSSL_IS_101").is_ok()) ||
|
||||
|
||||
// Skip some functions with function pointers on windows, not entirely
|
||||
// sure how to get them to work out...
|
||||
(target.contains("windows") && {
|
||||
s == "SSL_get_ex_new_index" ||
|
||||
s == "SSL_CTX_get_ex_new_index" ||
|
||||
s == "CRYPTO_get_ex_new_index"
|
||||
})
|
||||
});
|
||||
cfg.skip_field_type(|s, field| {
|
||||
(s == "EVP_PKEY" && field == "pkey") || // union
|
||||
(s == "GENERAL_NAME" && field == "d") // union
|
||||
});
|
||||
cfg.skip_signededness(|s| {
|
||||
s.ends_with("_cb") ||
|
||||
s.starts_with("CRYPTO_") ||
|
||||
s == "PasswordCallback"
|
||||
});
|
||||
cfg.field_name(|_s, field| {
|
||||
if field == "type_" {
|
||||
format!("type")
|
||||
} else {
|
||||
format!("{}", field)
|
||||
}
|
||||
});
|
||||
cfg.fn_cname(|rust, link_name| link_name.unwrap_or(rust).to_string());
|
||||
cfg.generate("../openssl-sys/src/lib.rs", "all.rs");
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
#![allow(bad_style)]
|
||||
|
||||
extern crate openssl_sys;
|
||||
extern crate libc;
|
||||
|
||||
use libc::*;
|
||||
use openssl_sys::*;
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/all.rs"));
|
||||
Loading…
Reference in New Issue