diff --git a/.travis.yml b/.travis.yml index 0d76be3d..55ba716d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,28 +1,86 @@ language: rust -sudo: false -addons: - apt: - packages: - - gcc-arm-linux-gnueabihf -rust: -- nightly -- 1.9.0 -os: -- osx -- linux +sudo: required +rust: stable +dist: trusty + env: - matrix: - - TEST_FEATURES=false - - TEST_FEATURES=true + global: + - TARGET=x86_64-unknown-linux-gnu + - BUILD_OPENSSL_VERSION=1.0.1u matrix: - # include: - # - os: linux - # env: TARGET=arm-unknown-linux-gnueabihf TEST_FEATURES=true - # rust: 1.7.0 - exclude: - - os: osx - env: TEST_FEATURES=true + 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 + - 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.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: 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 + - ./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 + - ./openssl/test/run.sh + +cache: + cargo: true + directories: + - $HOME/openssl diff --git a/Cargo.toml b/Cargo.toml index 0bd2c005..2ef99c17 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,2 +1,2 @@ [workspace] -members = ["openssl", "openssl-sys"] +members = ["openssl", "openssl-sys", "systest"] diff --git a/README.md b/README.md index d919cff1..3f17a571 100644 --- a/README.md +++ b/README.md @@ -2,17 +2,26 @@ [![Build Status](https://travis-ci.org/sfackler/rust-openssl.svg?branch=master)](https://travis-ci.org/sfackler/rust-openssl) -[Documentation](https://sfackler.github.io/rust-openssl/doc/v0.8.3/openssl). +[Documentation](https://sfackler.github.io/rust-openssl/doc/v0.9.0/openssl). + +## Warning + +This README does not correspond to rust-openssl 0.7.x. See +[here](https://github.com/sfackler/rust-openssl/blob/b8fb29db5c246175a096260eacca38180cd77dd0/README.md) +for that README. ## 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 +32,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 -``` - -64-bit -```bash -pacman -S mingw-w64-x86_64-gcc +``` +set OPENSSL_DIR=C:\OpenSSL-Win64 ``` -and then install the mingw-w64 toolchain. +After that, you're just a `cargo build` away! -32-bit: -```bash -pacman -S mingw-w64-i686-toolchain +### 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 ``` -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. + 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. diff --git a/appveyor.yml b/appveyor.yml index 4cd6c231..3e23044e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,25 +1,45 @@ environment: - OPENSSL_INCLUDE_DIR: C:\OpenSSL\include - OPENSSL_LIB_DIR: C:\OpenSSL\lib - OPENSSL_LIBS: ssleay32:libeay32 + SSL_CERT_FILE: "C:\\OpenSSL\\cacert.pem" matrix: - - TARGET: i686-pc-windows-gnu - BITS: 32 - - TARGET: x86_64-pc-windows-msvc - BITS: 64 + # 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" + - ps: Start-FileDownload "https://curl.haxx.se/ca/cacert.pem" -FileName "C:\OpenSSL\cacert.pem" + + # 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 diff --git a/openssl-sys/Cargo.toml b/openssl-sys/Cargo.toml index dcdf9d1a..11c20a1c 100644 --- a/openssl-sys/Cargo.toml +++ b/openssl-sys/Cargo.toml @@ -1,47 +1,21 @@ [package] name = "openssl-sys" -version = "0.7.17" +version = "0.9.0" authors = ["Alex Crichton ", "Steven Fackler "] license = "MIT" description = "FFI bindings to OpenSSL" repository = "https://github.com/sfackler/rust-openssl" -documentation = "https://sfackler.github.io/rust-openssl/doc/v0.7.17/openssl_sys" +documentation = "https://sfackler.github.io/rust-openssl/doc/v0.9.0/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" diff --git a/openssl-sys/build.rs b/openssl-sys/build.rs index 0e3a76d2..a435b192 100644 --- a/openssl-sys/build.rs +++ b/openssl-sys/build.rs @@ -1,86 +1,345 @@ 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"] - } else { - vec!["ssl32", "eay32"] - } - } else { - vec!["ssl", "crypto"] - } - }; + if !Path::new(&include_dir).exists() { + panic!("OpenSSL include directory does not exist: {}", + include_dir.to_string_lossy()); + } - let mode = if env::var_os("OPENSSL_STATIC").is_some() { - "static" + 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 { - "dylib" + ["ssl", "crypto"] }; - 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); + let kind = determine_mode(Path::new(&lib_dir), &libs); + for lib in libs.iter() { + println!("cargo:rustc-link-lib={}={}", kind, lib); } } -fn get_mingw_in_path() -> Option> { - match env::var_os("PATH") { - Some(env_path) => { - let paths: Vec = env::split_paths(&env_path).filter_map(|path| { - use std::ascii::AsciiExt; +fn find_openssl_dir(target: &str) -> OsString { + let host = env::var("HOST").unwrap(); - match path.to_str() { - Some(path_str) => { - if path_str.to_ascii_lowercase().contains("mingw") { - Some(path_str.to_string()) - } else { None } - }, - None => None + if host.contains("apple-darwin") && target.contains("apple-darwin") { + let homebrew = Path::new("/usr/local/opt/openssl@1.1"); + if homebrew.exists() { + return homebrew.to_path_buf().into() + } + let homebrew = Path::new("/usr/local/opt/openssl"); + 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:version=101"); + } else if version_text.contains("0x10002") { + println!("cargo:rustc-cfg=ossl102"); + println!("cargo:version=102"); + } else if version_text.contains("0x10100") { + println!("cargo:rustc-cfg=ossl110"); + println!("cargo:version=110"); + } 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. + 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::() + }).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); } - }).collect(); + } + } + }; + f.read_to_string(&mut conf_header).unwrap(); - if paths.len() > 0 { Some(paths) } else { None } - }, - None => None + // Look for `#define OPENSSL_FOO`, print out everything as our own + // #[cfg] flag. + let mut vars = vec![]; + 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); + vars.push(var); + } } + println!("cargo:conf={}", vars.join(",")); + + 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::>(); + 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" } diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 380f0058..4ffd1f64 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -1,64 +1,47 @@ #![allow(non_camel_case_types, non_upper_case_globals, non_snake_case)] -#![allow(dead_code)] -#![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.7.17")] +#![allow(dead_code, overflowing_literals)] +#![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.9.0")] extern crate libc; -#[cfg(target_os = "nacl")] -extern crate libressl_pnacl_sys; - use libc::{c_void, c_int, c_char, c_ulong, c_long, c_uint, c_uchar, size_t, FILE}; -use std::mem; use std::ptr; -use std::sync::{Mutex, MutexGuard}; -use std::sync::{Once, ONCE_INIT}; -pub type ASN1_INTEGER = c_void; -pub type ASN1_STRING = c_void; -pub type ASN1_TIME = c_void; -pub type ASN1_TYPE = c_void; -pub type BN_CTX = c_void; -pub type BN_GENCB = c_void; -pub type COMP_METHOD = c_void; -pub type DH = c_void; -pub type ENGINE = c_void; -pub type EVP_CIPHER_CTX = c_void; -pub type EVP_MD = c_void; -pub type EVP_PKEY_CTX = c_void; -pub type SSL = c_void; -pub type SSL_CIPHER = c_void; -pub type SSL_CTX = c_void; -pub type SSL_METHOD = c_void; -pub type X509 = c_void; -pub type X509_CRL = c_void; -pub type X509_EXTENSION = c_void; -pub type X509_NAME = c_void; -pub type X509_NAME_ENTRY = c_void; -pub type X509_REQ = c_void; -pub type X509_STORE_CTX = c_void; -pub type bio_st = c_void; -#[repr(C)] -pub struct PKCS12(c_void); +#[cfg(any(ossl101, ossl102))] +mod ossl10x; +#[cfg(any(ossl101, ossl102))] +pub use ossl10x::*; -#[repr(C)] -pub struct stack_st_X509 { - pub stack: _STACK, -} +#[cfg(ossl110)] +mod ossl110; +#[cfg(ossl110)] +pub use ossl110::*; -#[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, -} +pub enum ASN1_INTEGER {} +pub enum ASN1_STRING {} +pub enum ASN1_TIME {} +pub enum ASN1_TYPE {} +pub enum BN_CTX {} +pub enum BN_GENCB {} +pub enum CONF {} +pub enum COMP_METHOD {} +pub enum EC_KEY {} +pub enum ENGINE {} +pub enum EVP_CIPHER_CTX {} +pub enum EVP_MD {} +pub enum EVP_PKEY_CTX {} +pub enum SSL {} +pub enum SSL_CIPHER {} +pub enum SSL_METHOD {} +pub enum X509_CRL {} +pub enum X509_EXTENSION {} +pub enum X509_NAME {} +pub enum X509_NAME_ENTRY {} +pub enum X509_REQ {} +pub enum X509_STORE_CTX {} +pub enum bio_st {} +pub enum PKCS12 {} +pub enum DH_METHOD {} pub type bio_info_cb = Option; +pub enum RSA_METHOD {} +pub enum BN_MONT_CTX {} +pub enum BN_BLINDING {} +pub enum DSA_METHOD {} +pub enum EVP_PKEY_ASN1_METHOD {} + #[repr(C)] -#[derive(Copy, Clone)] -pub struct BIO_METHOD { +pub struct GENERAL_NAME { pub type_: c_int, - pub name: *const c_char, - pub bwrite: Option c_int>, - pub bread: Option c_int>, - pub bputs: Option c_int>, - pub bgets: Option c_int>, - pub ctrl: Option c_long>, - pub create: Option c_int>, - pub destroy: Option c_int>, - pub callback_ctrl: Option c_long>, -} - -// so we can create static BIO_METHODs -unsafe impl Sync for BIO_METHOD {} - -#[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, -} - -#[repr(C)] -pub struct RSA { - pub pad: c_int, - pub version: c_long, - pub meth: *const c_void, - - pub engine: *mut c_void, - 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: *mut c_void, - pub references: c_int, - pub flags: c_int, - - pub _method_mod_n: *mut c_void, - pub _method_mod_p: *mut c_void, - pub _method_mod_q: *mut c_void, - - pub bignum_data: *mut c_char, - pub blinding: *mut c_void, - pub mt_blinding: *mut c_void, -} - -#[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 c_void, - pub references: c_int, - pub ex_data: *mut c_void, - pub meth: *const c_void, - pub engine: *const c_void, -} - -#[repr(C)] -pub struct EVP_PKEY { - pub type_: c_int, - pub save_type: c_int, - pub references: c_int, - pub ameth: *const c_void, - pub engine: *mut ENGINE, - pub pkey: *mut c_void, - pub save_parameters: c_int, - pub attributes: *mut c_void, -} - -#[repr(C)] -pub struct BIO { - pub method: *mut BIO_METHOD, - pub callback: Option 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 c_void, - flags: c_ulong, - md_data: *mut c_void, - pctx: *mut EVP_PKEY_CTX, - update: *mut c_void -} - -impl Copy for EVP_MD_CTX {} -impl Clone for EVP_MD_CTX { - fn clone(&self) -> EVP_MD_CTX { *self } -} - -#[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 c_int>, - pub do_cipher: Option c_int>, - pub cleanup: Option c_int>, - pub ctx_size: c_int, - pub set_asn1_parameters: Option c_int>, - pub get_asn1_parameters: Option c_int>, - pub ctrl: Option c_int>, - pub app_data: *mut c_void, -} - -impl Copy for EVP_CIPHER {} -impl Clone for EVP_CIPHER { - fn clone(&self) -> EVP_CIPHER { *self } -} - -#[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] -} - -impl Copy for HMAC_CTX {} -impl Clone for HMAC_CTX { - fn clone(&self) -> HMAC_CTX { *self } + pub d: *mut c_void, } #[repr(C)] @@ -264,49 +75,24 @@ pub struct X509V3_CTX { // Maybe more here } -#[repr(C)] -pub struct GENERAL_NAME { - pub type_: c_int, - pub d: *mut c_void, -} +#[cfg(target_pointer_width = "64")] +pub type BN_ULONG = libc::c_ulonglong; +#[cfg(target_pointer_width = "32")] +pub type BN_ULONG = c_uint; -impl Copy for GENERAL_NAME {} -impl Clone for GENERAL_NAME { - fn clone(&self) -> GENERAL_NAME { *self } -} - -impl Copy for X509V3_CTX {} -impl Clone for X509V3_CTX { - fn clone(&self) -> X509V3_CTX { *self } -} - -#[repr(C)] -pub struct BIGNUM { - pub d: *mut c_void, - pub top: c_int, - pub dmax: c_int, - pub neg: c_int, - pub flags: c_int, -} - -impl Copy for BIGNUM {} -impl Clone for BIGNUM { - fn clone(&self) -> BIGNUM { *self } -} - -pub type CRYPTO_EX_new = extern "C" fn(parent: *mut c_void, ptr: *mut c_void, - ad: *const CRYPTO_EX_DATA, idx: c_int, - argl: c_long, argp: *const c_void) -> c_int; -pub type CRYPTO_EX_dup = extern "C" fn(to: *mut CRYPTO_EX_DATA, - from: *mut CRYPTO_EX_DATA, from_d: *mut c_void, - idx: c_int, argl: c_long, argp: *mut c_void) - -> c_int; -pub type CRYPTO_EX_free = extern "C" fn(parent: *mut c_void, ptr: *mut c_void, - ad: *mut CRYPTO_EX_DATA, idx: c_int, - argl: c_long, argp: *mut c_void); -pub type PasswordCallback = extern "C" fn(buf: *mut c_char, size: c_int, - rwflag: c_int, user_data: *mut c_void) +pub type CRYPTO_EX_new = unsafe extern fn(parent: *mut c_void, ptr: *mut c_void, + ad: *const CRYPTO_EX_DATA, idx: c_int, + argl: c_long, argp: *const c_void) -> c_int; +pub type CRYPTO_EX_dup = unsafe extern fn(to: *mut CRYPTO_EX_DATA, + from: *mut CRYPTO_EX_DATA, from_d: *mut c_void, + idx: c_int, argl: c_long, argp: *mut c_void) -> c_int; +pub type CRYPTO_EX_free = unsafe extern fn(parent: *mut c_void, ptr: *mut c_void, + ad: *mut CRYPTO_EX_DATA, idx: c_int, + argl: c_long, argp: *mut c_void); +pub type PasswordCallback = unsafe extern fn(buf: *mut c_char, size: c_int, + rwflag: c_int, user_data: *mut c_void) + -> c_int; pub const BIO_TYPE_NONE: c_int = 0; @@ -325,6 +111,8 @@ pub const CRYPTO_LOCK: c_int = 1; pub const EVP_MAX_MD_SIZE: c_uint = 64; pub const EVP_PKEY_RSA: c_int = NID_rsaEncryption; +pub const EVP_PKEY_HMAC: c_int = NID_hmac; +pub const EVP_PKEY_DSA: c_int = NID_dsa; pub const MBSTRING_ASC: c_int = MBSTRING_FLAG | 1; pub const MBSTRING_BMP: c_int = MBSTRING_FLAG | 2; @@ -332,28 +120,946 @@ pub const MBSTRING_FLAG: c_int = 0x1000; pub const MBSTRING_UNIV: c_int = MBSTRING_FLAG | 4; pub const MBSTRING_UTF8: c_int = MBSTRING_FLAG; +pub const NID_undef: c_int = 0; +pub const NID_itu_t: c_int = 645; +pub const NID_ccitt: c_int = 404; +pub const NID_iso: c_int = 181; +pub const NID_joint_iso_itu_t: c_int = 646; +pub const NID_joint_iso_ccitt: c_int = 393; +pub const NID_member_body: c_int = 182; +pub const NID_identified_organization: c_int = 676; +pub const NID_hmac_md5: c_int = 780; +pub const NID_hmac_sha1: c_int = 781; +pub const NID_certicom_arc: c_int = 677; +pub const NID_international_organizations: c_int = 647; +pub const NID_wap: c_int = 678; +pub const NID_wap_wsg: c_int = 679; +pub const NID_selected_attribute_types: c_int = 394; +pub const NID_clearance: c_int = 395; +pub const NID_ISO_US: c_int = 183; +pub const NID_X9_57: c_int = 184; +pub const NID_X9cm: c_int = 185; +pub const NID_dsa: c_int = 116; +pub const NID_dsaWithSHA1: c_int = 113; +pub const NID_ansi_X9_62: c_int = 405; +pub const NID_X9_62_prime_field: c_int = 406; +pub const NID_X9_62_characteristic_two_field: c_int = 407; +pub const NID_X9_62_id_characteristic_two_basis: c_int = 680; +pub const NID_X9_62_onBasis: c_int = 681; +pub const NID_X9_62_tpBasis: c_int = 682; +pub const NID_X9_62_ppBasis: c_int = 683; +pub const NID_X9_62_id_ecPublicKey: c_int = 408; +pub const NID_X9_62_c2pnb163v1: c_int = 684; +pub const NID_X9_62_c2pnb163v2: c_int = 685; +pub const NID_X9_62_c2pnb163v3: c_int = 686; +pub const NID_X9_62_c2pnb176v1: c_int = 687; +pub const NID_X9_62_c2tnb191v1: c_int = 688; +pub const NID_X9_62_c2tnb191v2: c_int = 689; +pub const NID_X9_62_c2tnb191v3: c_int = 690; +pub const NID_X9_62_c2onb191v4: c_int = 691; +pub const NID_X9_62_c2onb191v5: c_int = 692; +pub const NID_X9_62_c2pnb208w1: c_int = 693; +pub const NID_X9_62_c2tnb239v1: c_int = 694; +pub const NID_X9_62_c2tnb239v2: c_int = 695; +pub const NID_X9_62_c2tnb239v3: c_int = 696; +pub const NID_X9_62_c2onb239v4: c_int = 697; +pub const NID_X9_62_c2onb239v5: c_int = 698; +pub const NID_X9_62_c2pnb272w1: c_int = 699; +pub const NID_X9_62_c2pnb304w1: c_int = 700; +pub const NID_X9_62_c2tnb359v1: c_int = 701; +pub const NID_X9_62_c2pnb368w1: c_int = 702; +pub const NID_X9_62_c2tnb431r1: c_int = 703; +pub const NID_X9_62_prime192v1: c_int = 409; +pub const NID_X9_62_prime192v2: c_int = 410; +pub const NID_X9_62_prime192v3: c_int = 411; +pub const NID_X9_62_prime239v1: c_int = 412; +pub const NID_X9_62_prime239v2: c_int = 413; +pub const NID_X9_62_prime239v3: c_int = 414; +pub const NID_X9_62_prime256v1: c_int = 415; +pub const NID_ecdsa_with_SHA1: c_int = 416; +pub const NID_ecdsa_with_Recommended: c_int = 791; +pub const NID_ecdsa_with_Specified: c_int = 792; +pub const NID_ecdsa_with_SHA224: c_int = 793; +pub const NID_ecdsa_with_SHA256: c_int = 794; +pub const NID_ecdsa_with_SHA384: c_int = 795; +pub const NID_ecdsa_with_SHA512: c_int = 796; +pub const NID_secp112r1: c_int = 704; +pub const NID_secp112r2: c_int = 705; +pub const NID_secp128r1: c_int = 706; +pub const NID_secp128r2: c_int = 707; +pub const NID_secp160k1: c_int = 708; +pub const NID_secp160r1: c_int = 709; +pub const NID_secp160r2: c_int = 710; +pub const NID_secp192k1: c_int = 711; +pub const NID_secp224k1: c_int = 712; +pub const NID_secp224r1: c_int = 713; +pub const NID_secp256k1: c_int = 714; +pub const NID_secp384r1: c_int = 715; +pub const NID_secp521r1: c_int = 716; +pub const NID_sect113r1: c_int = 717; +pub const NID_sect113r2: c_int = 718; +pub const NID_sect131r1: c_int = 719; +pub const NID_sect131r2: c_int = 720; +pub const NID_sect163k1: c_int = 721; +pub const NID_sect163r1: c_int = 722; +pub const NID_sect163r2: c_int = 723; +pub const NID_sect193r1: c_int = 724; +pub const NID_sect193r2: c_int = 725; +pub const NID_sect233k1: c_int = 726; +pub const NID_sect233r1: c_int = 727; +pub const NID_sect239k1: c_int = 728; +pub const NID_sect283k1: c_int = 729; +pub const NID_sect283r1: c_int = 730; +pub const NID_sect409k1: c_int = 731; +pub const NID_sect409r1: c_int = 732; +pub const NID_sect571k1: c_int = 733; +pub const NID_sect571r1: c_int = 734; +pub const NID_wap_wsg_idm_ecid_wtls1: c_int = 735; +pub const NID_wap_wsg_idm_ecid_wtls3: c_int = 736; +pub const NID_wap_wsg_idm_ecid_wtls4: c_int = 737; +pub const NID_wap_wsg_idm_ecid_wtls5: c_int = 738; +pub const NID_wap_wsg_idm_ecid_wtls6: c_int = 739; +pub const NID_wap_wsg_idm_ecid_wtls7: c_int = 740; +pub const NID_wap_wsg_idm_ecid_wtls8: c_int = 741; +pub const NID_wap_wsg_idm_ecid_wtls9: c_int = 742; +pub const NID_wap_wsg_idm_ecid_wtls10: c_int = 743; +pub const NID_wap_wsg_idm_ecid_wtls11: c_int = 744; +pub const NID_wap_wsg_idm_ecid_wtls12: c_int = 745; +pub const NID_cast5_cbc: c_int = 108; +pub const NID_cast5_ecb: c_int = 109; +pub const NID_cast5_cfb64: c_int = 110; +pub const NID_cast5_ofb64: c_int = 111; +pub const NID_pbeWithMD5AndCast5_CBC: c_int = 112; +pub const NID_id_PasswordBasedMAC: c_int = 782; +pub const NID_id_DHBasedMac: c_int = 783; +pub const NID_rsadsi: c_int = 1; +pub const NID_pkcs: c_int = 2; +pub const NID_pkcs1: c_int = 186; pub const NID_rsaEncryption: c_int = 6; +pub const NID_md2WithRSAEncryption: c_int = 7; +pub const NID_md4WithRSAEncryption: c_int = 396; +pub const NID_md5WithRSAEncryption: c_int = 8; +pub const NID_sha1WithRSAEncryption: c_int = 65; +pub const NID_rsaesOaep: c_int = 919; +pub const NID_mgf1: c_int = 911; +pub const NID_rsassaPss: c_int = 912; +pub const NID_sha256WithRSAEncryption: c_int = 668; +pub const NID_sha384WithRSAEncryption: c_int = 669; +pub const NID_sha512WithRSAEncryption: c_int = 670; +pub const NID_sha224WithRSAEncryption: c_int = 671; +pub const NID_pkcs3: c_int = 27; +pub const NID_dhKeyAgreement: c_int = 28; +pub const NID_pkcs5: c_int = 187; +pub const NID_pbeWithMD2AndDES_CBC: c_int = 9; +pub const NID_pbeWithMD5AndDES_CBC: c_int = 10; +pub const NID_pbeWithMD2AndRC2_CBC: c_int = 168; +pub const NID_pbeWithMD5AndRC2_CBC: c_int = 169; +pub const NID_pbeWithSHA1AndDES_CBC: c_int = 170; +pub const NID_pbeWithSHA1AndRC2_CBC: c_int = 68; +pub const NID_id_pbkdf2: c_int = 69; +pub const NID_pbes2: c_int = 161; +pub const NID_pbmac1: c_int = 162; +pub const NID_pkcs7: c_int = 20; +pub const NID_pkcs7_data: c_int = 21; +pub const NID_pkcs7_signed: c_int = 22; +pub const NID_pkcs7_enveloped: c_int = 23; +pub const NID_pkcs7_signedAndEnveloped: c_int = 24; +pub const NID_pkcs7_digest: c_int = 25; +pub const NID_pkcs7_encrypted: c_int = 26; +pub const NID_pkcs9: c_int = 47; +pub const NID_pkcs9_emailAddress: c_int = 48; +pub const NID_pkcs9_unstructuredName: c_int = 49; +pub const NID_pkcs9_contentType: c_int = 50; +pub const NID_pkcs9_messageDigest: c_int = 51; +pub const NID_pkcs9_signingTime: c_int = 52; +pub const NID_pkcs9_countersignature: c_int = 53; +pub const NID_pkcs9_challengePassword: c_int = 54; +pub const NID_pkcs9_unstructuredAddress: c_int = 55; +pub const NID_pkcs9_extCertAttributes: c_int = 56; +pub const NID_ext_req: c_int = 172; +pub const NID_SMIMECapabilities: c_int = 167; +pub const NID_SMIME: c_int = 188; +pub const NID_id_smime_mod: c_int = 189; +pub const NID_id_smime_ct: c_int = 190; +pub const NID_id_smime_aa: c_int = 191; +pub const NID_id_smime_alg: c_int = 192; +pub const NID_id_smime_cd: c_int = 193; +pub const NID_id_smime_spq: c_int = 194; +pub const NID_id_smime_cti: c_int = 195; +pub const NID_id_smime_mod_cms: c_int = 196; +pub const NID_id_smime_mod_ess: c_int = 197; +pub const NID_id_smime_mod_oid: c_int = 198; +pub const NID_id_smime_mod_msg_v3: c_int = 199; +pub const NID_id_smime_mod_ets_eSignature_88: c_int = 200; +pub const NID_id_smime_mod_ets_eSignature_97: c_int = 201; +pub const NID_id_smime_mod_ets_eSigPolicy_88: c_int = 202; +pub const NID_id_smime_mod_ets_eSigPolicy_97: c_int = 203; +pub const NID_id_smime_ct_receipt: c_int = 204; +pub const NID_id_smime_ct_authData: c_int = 205; +pub const NID_id_smime_ct_publishCert: c_int = 206; +pub const NID_id_smime_ct_TSTInfo: c_int = 207; +pub const NID_id_smime_ct_TDTInfo: c_int = 208; +pub const NID_id_smime_ct_contentInfo: c_int = 209; +pub const NID_id_smime_ct_DVCSRequestData: c_int = 210; +pub const NID_id_smime_ct_DVCSResponseData: c_int = 211; +pub const NID_id_smime_ct_compressedData: c_int = 786; +pub const NID_id_ct_asciiTextWithCRLF: c_int = 787; +pub const NID_id_smime_aa_receiptRequest: c_int = 212; +pub const NID_id_smime_aa_securityLabel: c_int = 213; +pub const NID_id_smime_aa_mlExpandHistory: c_int = 214; +pub const NID_id_smime_aa_contentHint: c_int = 215; +pub const NID_id_smime_aa_msgSigDigest: c_int = 216; +pub const NID_id_smime_aa_encapContentType: c_int = 217; +pub const NID_id_smime_aa_contentIdentifier: c_int = 218; +pub const NID_id_smime_aa_macValue: c_int = 219; +pub const NID_id_smime_aa_equivalentLabels: c_int = 220; +pub const NID_id_smime_aa_contentReference: c_int = 221; +pub const NID_id_smime_aa_encrypKeyPref: c_int = 222; +pub const NID_id_smime_aa_signingCertificate: c_int = 223; +pub const NID_id_smime_aa_smimeEncryptCerts: c_int = 224; +pub const NID_id_smime_aa_timeStampToken: c_int = 225; +pub const NID_id_smime_aa_ets_sigPolicyId: c_int = 226; +pub const NID_id_smime_aa_ets_commitmentType: c_int = 227; +pub const NID_id_smime_aa_ets_signerLocation: c_int = 228; +pub const NID_id_smime_aa_ets_signerAttr: c_int = 229; +pub const NID_id_smime_aa_ets_otherSigCert: c_int = 230; +pub const NID_id_smime_aa_ets_contentTimestamp: c_int = 231; +pub const NID_id_smime_aa_ets_CertificateRefs: c_int = 232; +pub const NID_id_smime_aa_ets_RevocationRefs: c_int = 233; +pub const NID_id_smime_aa_ets_certValues: c_int = 234; +pub const NID_id_smime_aa_ets_revocationValues: c_int = 235; +pub const NID_id_smime_aa_ets_escTimeStamp: c_int = 236; +pub const NID_id_smime_aa_ets_certCRLTimestamp: c_int = 237; +pub const NID_id_smime_aa_ets_archiveTimeStamp: c_int = 238; +pub const NID_id_smime_aa_signatureType: c_int = 239; +pub const NID_id_smime_aa_dvcs_dvc: c_int = 240; +pub const NID_id_smime_alg_ESDHwith3DES: c_int = 241; +pub const NID_id_smime_alg_ESDHwithRC2: c_int = 242; +pub const NID_id_smime_alg_3DESwrap: c_int = 243; +pub const NID_id_smime_alg_RC2wrap: c_int = 244; +pub const NID_id_smime_alg_ESDH: c_int = 245; +pub const NID_id_smime_alg_CMS3DESwrap: c_int = 246; +pub const NID_id_smime_alg_CMSRC2wrap: c_int = 247; +pub const NID_id_alg_PWRI_KEK: c_int = 893; +pub const NID_id_smime_cd_ldap: c_int = 248; +pub const NID_id_smime_spq_ets_sqt_uri: c_int = 249; +pub const NID_id_smime_spq_ets_sqt_unotice: c_int = 250; +pub const NID_id_smime_cti_ets_proofOfOrigin: c_int = 251; +pub const NID_id_smime_cti_ets_proofOfReceipt: c_int = 252; +pub const NID_id_smime_cti_ets_proofOfDelivery: c_int = 253; +pub const NID_id_smime_cti_ets_proofOfSender: c_int = 254; +pub const NID_id_smime_cti_ets_proofOfApproval: c_int = 255; +pub const NID_id_smime_cti_ets_proofOfCreation: c_int = 256; +pub const NID_friendlyName: c_int = 156; +pub const NID_localKeyID: c_int = 157; +pub const NID_ms_csp_name: c_int = 417; +pub const NID_LocalKeySet: c_int = 856; +pub const NID_x509Certificate: c_int = 158; +pub const NID_sdsiCertificate: c_int = 159; +pub const NID_x509Crl: c_int = 160; +pub const NID_pbe_WithSHA1And128BitRC4: c_int = 144; +pub const NID_pbe_WithSHA1And40BitRC4: c_int = 145; +pub const NID_pbe_WithSHA1And3_Key_TripleDES_CBC: c_int = 146; +pub const NID_pbe_WithSHA1And2_Key_TripleDES_CBC: c_int = 147; +pub const NID_pbe_WithSHA1And128BitRC2_CBC: c_int = 148; +pub const NID_pbe_WithSHA1And40BitRC2_CBC: c_int = 149; +pub const NID_keyBag: c_int = 150; +pub const NID_pkcs8ShroudedKeyBag: c_int = 151; +pub const NID_certBag: c_int = 152; +pub const NID_crlBag: c_int = 153; +pub const NID_secretBag: c_int = 154; +pub const NID_safeContentsBag: c_int = 155; +pub const NID_md2: c_int = 3; +pub const NID_md4: c_int = 257; +pub const NID_md5: c_int = 4; +pub const NID_md5_sha1: c_int = 114; +pub const NID_hmacWithMD5: c_int = 797; +pub const NID_hmacWithSHA1: c_int = 163; +pub const NID_hmacWithSHA224: c_int = 798; +pub const NID_hmacWithSHA256: c_int = 799; +pub const NID_hmacWithSHA384: c_int = 800; +pub const NID_hmacWithSHA512: c_int = 801; +pub const NID_rc2_cbc: c_int = 37; +pub const NID_rc2_ecb: c_int = 38; +pub const NID_rc2_cfb64: c_int = 39; +pub const NID_rc2_ofb64: c_int = 40; +pub const NID_rc2_40_cbc: c_int = 98; +pub const NID_rc2_64_cbc: c_int = 166; +pub const NID_rc4: c_int = 5; +pub const NID_rc4_40: c_int = 97; +pub const NID_des_ede3_cbc: c_int = 44; +pub const NID_rc5_cbc: c_int = 120; +pub const NID_rc5_ecb: c_int = 121; +pub const NID_rc5_cfb64: c_int = 122; +pub const NID_rc5_ofb64: c_int = 123; +pub const NID_ms_ext_req: c_int = 171; +pub const NID_ms_code_ind: c_int = 134; +pub const NID_ms_code_com: c_int = 135; +pub const NID_ms_ctl_sign: c_int = 136; +pub const NID_ms_sgc: c_int = 137; +pub const NID_ms_efs: c_int = 138; +pub const NID_ms_smartcard_login: c_int = 648; +pub const NID_ms_upn: c_int = 649; +pub const NID_idea_cbc: c_int = 34; +pub const NID_idea_ecb: c_int = 36; +pub const NID_idea_cfb64: c_int = 35; +pub const NID_idea_ofb64: c_int = 46; +pub const NID_bf_cbc: c_int = 91; +pub const NID_bf_ecb: c_int = 92; +pub const NID_bf_cfb64: c_int = 93; +pub const NID_bf_ofb64: c_int = 94; +pub const NID_id_pkix: c_int = 127; +pub const NID_id_pkix_mod: c_int = 258; +pub const NID_id_pe: c_int = 175; +pub const NID_id_qt: c_int = 259; +pub const NID_id_kp: c_int = 128; +pub const NID_id_it: c_int = 260; +pub const NID_id_pkip: c_int = 261; +pub const NID_id_alg: c_int = 262; +pub const NID_id_cmc: c_int = 263; +pub const NID_id_on: c_int = 264; +pub const NID_id_pda: c_int = 265; +pub const NID_id_aca: c_int = 266; +pub const NID_id_qcs: c_int = 267; +pub const NID_id_cct: c_int = 268; +pub const NID_id_ppl: c_int = 662; +pub const NID_id_ad: c_int = 176; +pub const NID_id_pkix1_explicit_88: c_int = 269; +pub const NID_id_pkix1_implicit_88: c_int = 270; +pub const NID_id_pkix1_explicit_93: c_int = 271; +pub const NID_id_pkix1_implicit_93: c_int = 272; +pub const NID_id_mod_crmf: c_int = 273; +pub const NID_id_mod_cmc: c_int = 274; +pub const NID_id_mod_kea_profile_88: c_int = 275; +pub const NID_id_mod_kea_profile_93: c_int = 276; +pub const NID_id_mod_cmp: c_int = 277; +pub const NID_id_mod_qualified_cert_88: c_int = 278; +pub const NID_id_mod_qualified_cert_93: c_int = 279; +pub const NID_id_mod_attribute_cert: c_int = 280; +pub const NID_id_mod_timestamp_protocol: c_int = 281; +pub const NID_id_mod_ocsp: c_int = 282; +pub const NID_id_mod_dvcs: c_int = 283; +pub const NID_id_mod_cmp2000: c_int = 284; +pub const NID_info_access: c_int = 177; +pub const NID_biometricInfo: c_int = 285; +pub const NID_qcStatements: c_int = 286; +pub const NID_ac_auditEntity: c_int = 287; +pub const NID_ac_targeting: c_int = 288; +pub const NID_aaControls: c_int = 289; +pub const NID_sbgp_ipAddrBlock: c_int = 290; +pub const NID_sbgp_autonomousSysNum: c_int = 291; +pub const NID_sbgp_routerIdentifier: c_int = 292; +pub const NID_ac_proxying: c_int = 397; +pub const NID_sinfo_access: c_int = 398; +pub const NID_proxyCertInfo: c_int = 663; +pub const NID_id_qt_cps: c_int = 164; +pub const NID_id_qt_unotice: c_int = 165; +pub const NID_textNotice: c_int = 293; +pub const NID_server_auth: c_int = 129; +pub const NID_client_auth: c_int = 130; +pub const NID_code_sign: c_int = 131; +pub const NID_email_protect: c_int = 132; +pub const NID_ipsecEndSystem: c_int = 294; +pub const NID_ipsecTunnel: c_int = 295; +pub const NID_ipsecUser: c_int = 296; +pub const NID_time_stamp: c_int = 133; +pub const NID_OCSP_sign: c_int = 180; +pub const NID_dvcs: c_int = 297; +pub const NID_id_it_caProtEncCert: c_int = 298; +pub const NID_id_it_signKeyPairTypes: c_int = 299; +pub const NID_id_it_encKeyPairTypes: c_int = 300; +pub const NID_id_it_preferredSymmAlg: c_int = 301; +pub const NID_id_it_caKeyUpdateInfo: c_int = 302; +pub const NID_id_it_currentCRL: c_int = 303; +pub const NID_id_it_unsupportedOIDs: c_int = 304; +pub const NID_id_it_subscriptionRequest: c_int = 305; +pub const NID_id_it_subscriptionResponse: c_int = 306; +pub const NID_id_it_keyPairParamReq: c_int = 307; +pub const NID_id_it_keyPairParamRep: c_int = 308; +pub const NID_id_it_revPassphrase: c_int = 309; +pub const NID_id_it_implicitConfirm: c_int = 310; +pub const NID_id_it_confirmWaitTime: c_int = 311; +pub const NID_id_it_origPKIMessage: c_int = 312; +pub const NID_id_it_suppLangTags: c_int = 784; +pub const NID_id_regCtrl: c_int = 313; +pub const NID_id_regInfo: c_int = 314; +pub const NID_id_regCtrl_regToken: c_int = 315; +pub const NID_id_regCtrl_authenticator: c_int = 316; +pub const NID_id_regCtrl_pkiPublicationInfo: c_int = 317; +pub const NID_id_regCtrl_pkiArchiveOptions: c_int = 318; +pub const NID_id_regCtrl_oldCertID: c_int = 319; +pub const NID_id_regCtrl_protocolEncrKey: c_int = 320; +pub const NID_id_regInfo_utf8Pairs: c_int = 321; +pub const NID_id_regInfo_certReq: c_int = 322; +pub const NID_id_alg_des40: c_int = 323; +pub const NID_id_alg_noSignature: c_int = 324; +pub const NID_id_alg_dh_sig_hmac_sha1: c_int = 325; +pub const NID_id_alg_dh_pop: c_int = 326; +pub const NID_id_cmc_statusInfo: c_int = 327; +pub const NID_id_cmc_identification: c_int = 328; +pub const NID_id_cmc_identityProof: c_int = 329; +pub const NID_id_cmc_dataReturn: c_int = 330; +pub const NID_id_cmc_transactionId: c_int = 331; +pub const NID_id_cmc_senderNonce: c_int = 332; +pub const NID_id_cmc_recipientNonce: c_int = 333; +pub const NID_id_cmc_addExtensions: c_int = 334; +pub const NID_id_cmc_encryptedPOP: c_int = 335; +pub const NID_id_cmc_decryptedPOP: c_int = 336; +pub const NID_id_cmc_lraPOPWitness: c_int = 337; +pub const NID_id_cmc_getCert: c_int = 338; +pub const NID_id_cmc_getCRL: c_int = 339; +pub const NID_id_cmc_revokeRequest: c_int = 340; +pub const NID_id_cmc_regInfo: c_int = 341; +pub const NID_id_cmc_responseInfo: c_int = 342; +pub const NID_id_cmc_queryPending: c_int = 343; +pub const NID_id_cmc_popLinkRandom: c_int = 344; +pub const NID_id_cmc_popLinkWitness: c_int = 345; +pub const NID_id_cmc_confirmCertAcceptance: c_int = 346; +pub const NID_id_on_personalData: c_int = 347; +pub const NID_id_on_permanentIdentifier: c_int = 858; +pub const NID_id_pda_dateOfBirth: c_int = 348; +pub const NID_id_pda_placeOfBirth: c_int = 349; +pub const NID_id_pda_gender: c_int = 351; +pub const NID_id_pda_countryOfCitizenship: c_int = 352; +pub const NID_id_pda_countryOfResidence: c_int = 353; +pub const NID_id_aca_authenticationInfo: c_int = 354; +pub const NID_id_aca_accessIdentity: c_int = 355; +pub const NID_id_aca_chargingIdentity: c_int = 356; +pub const NID_id_aca_group: c_int = 357; +pub const NID_id_aca_role: c_int = 358; +pub const NID_id_aca_encAttrs: c_int = 399; +pub const NID_id_qcs_pkixQCSyntax_v1: c_int = 359; +pub const NID_id_cct_crs: c_int = 360; +pub const NID_id_cct_PKIData: c_int = 361; +pub const NID_id_cct_PKIResponse: c_int = 362; +pub const NID_id_ppl_anyLanguage: c_int = 664; +pub const NID_id_ppl_inheritAll: c_int = 665; +pub const NID_Independent: c_int = 667; +pub const NID_ad_OCSP: c_int = 178; +pub const NID_ad_ca_issuers: c_int = 179; +pub const NID_ad_timeStamping: c_int = 363; +pub const NID_ad_dvcs: c_int = 364; +pub const NID_caRepository: c_int = 785; +pub const NID_id_pkix_OCSP_basic: c_int = 365; +pub const NID_id_pkix_OCSP_Nonce: c_int = 366; +pub const NID_id_pkix_OCSP_CrlID: c_int = 367; +pub const NID_id_pkix_OCSP_acceptableResponses: c_int = 368; +pub const NID_id_pkix_OCSP_noCheck: c_int = 369; +pub const NID_id_pkix_OCSP_archiveCutoff: c_int = 370; +pub const NID_id_pkix_OCSP_serviceLocator: c_int = 371; +pub const NID_id_pkix_OCSP_extendedStatus: c_int = 372; +pub const NID_id_pkix_OCSP_valid: c_int = 373; +pub const NID_id_pkix_OCSP_path: c_int = 374; +pub const NID_id_pkix_OCSP_trustRoot: c_int = 375; +pub const NID_algorithm: c_int = 376; +pub const NID_md5WithRSA: c_int = 104; +pub const NID_des_ecb: c_int = 29; +pub const NID_des_cbc: c_int = 31; +pub const NID_des_ofb64: c_int = 45; +pub const NID_des_cfb64: c_int = 30; +pub const NID_rsaSignature: c_int = 377; +pub const NID_dsa_2: c_int = 67; +pub const NID_dsaWithSHA: c_int = 66; +pub const NID_shaWithRSAEncryption: c_int = 42; +pub const NID_des_ede_ecb: c_int = 32; +pub const NID_des_ede3_ecb: c_int = 33; +pub const NID_des_ede_cbc: c_int = 43; +pub const NID_des_ede_cfb64: c_int = 60; +pub const NID_des_ede3_cfb64: c_int = 61; +pub const NID_des_ede_ofb64: c_int = 62; +pub const NID_des_ede3_ofb64: c_int = 63; +pub const NID_desx_cbc: c_int = 80; +pub const NID_sha: c_int = 41; +pub const NID_sha1: c_int = 64; +pub const NID_dsaWithSHA1_2: c_int = 70; +pub const NID_sha1WithRSA: c_int = 115; +pub const NID_ripemd160: c_int = 117; +pub const NID_ripemd160WithRSA: c_int = 119; +pub const NID_sxnet: c_int = 143; +pub const NID_X500: c_int = 11; +pub const NID_X509: c_int = 12; +pub const NID_commonName: c_int = 13; +pub const NID_surname: c_int = 100; +pub const NID_serialNumber: c_int = 105; +pub const NID_countryName: c_int = 14; +pub const NID_localityName: c_int = 15; +pub const NID_stateOrProvinceName: c_int = 16; +pub const NID_streetAddress: c_int = 660; +pub const NID_organizationName: c_int = 17; +pub const NID_organizationalUnitName: c_int = 18; +pub const NID_title: c_int = 106; +pub const NID_description: c_int = 107; +pub const NID_searchGuide: c_int = 859; +pub const NID_businessCategory: c_int = 860; +pub const NID_postalAddress: c_int = 861; +pub const NID_postalCode: c_int = 661; +pub const NID_postOfficeBox: c_int = 862; +pub const NID_physicalDeliveryOfficeName: c_int = 863; +pub const NID_telephoneNumber: c_int = 864; +pub const NID_telexNumber: c_int = 865; +pub const NID_teletexTerminalIdentifier: c_int = 866; +pub const NID_facsimileTelephoneNumber: c_int = 867; +pub const NID_x121Address: c_int = 868; +pub const NID_internationaliSDNNumber: c_int = 869; +pub const NID_registeredAddress: c_int = 870; +pub const NID_destinationIndicator: c_int = 871; +pub const NID_preferredDeliveryMethod: c_int = 872; +pub const NID_presentationAddress: c_int = 873; +pub const NID_supportedApplicationContext: c_int = 874; +pub const NID_member: c_int = 875; +pub const NID_owner: c_int = 876; +pub const NID_roleOccupant: c_int = 877; +pub const NID_seeAlso: c_int = 878; +pub const NID_userPassword: c_int = 879; +pub const NID_userCertificate: c_int = 880; +pub const NID_cACertificate: c_int = 881; +pub const NID_authorityRevocationList: c_int = 882; +pub const NID_certificateRevocationList: c_int = 883; +pub const NID_crossCertificatePair: c_int = 884; +pub const NID_name: c_int = 173; +pub const NID_givenName: c_int = 99; +pub const NID_initials: c_int = 101; +pub const NID_generationQualifier: c_int = 509; +pub const NID_x500UniqueIdentifier: c_int = 503; +pub const NID_dnQualifier: c_int = 174; +pub const NID_enhancedSearchGuide: c_int = 885; +pub const NID_protocolInformation: c_int = 886; +pub const NID_distinguishedName: c_int = 887; +pub const NID_uniqueMember: c_int = 888; +pub const NID_houseIdentifier: c_int = 889; +pub const NID_supportedAlgorithms: c_int = 890; +pub const NID_deltaRevocationList: c_int = 891; +pub const NID_dmdName: c_int = 892; +pub const NID_pseudonym: c_int = 510; +pub const NID_role: c_int = 400; +pub const NID_X500algorithms: c_int = 378; +pub const NID_rsa: c_int = 19; +pub const NID_mdc2WithRSA: c_int = 96; +pub const NID_mdc2: c_int = 95; +pub const NID_id_ce: c_int = 81; +pub const NID_subject_directory_attributes: c_int = 769; +pub const NID_subject_key_identifier: c_int = 82; +pub const NID_key_usage: c_int = 83; +pub const NID_private_key_usage_period: c_int = 84; +pub const NID_subject_alt_name: c_int = 85; +pub const NID_issuer_alt_name: c_int = 86; +pub const NID_basic_constraints: c_int = 87; +pub const NID_crl_number: c_int = 88; +pub const NID_crl_reason: c_int = 141; +pub const NID_invalidity_date: c_int = 142; +pub const NID_delta_crl: c_int = 140; +pub const NID_issuing_distribution_point: c_int = 770; +pub const NID_certificate_issuer: c_int = 771; +pub const NID_name_constraints: c_int = 666; +pub const NID_crl_distribution_points: c_int = 103; +pub const NID_certificate_policies: c_int = 89; +pub const NID_any_policy: c_int = 746; +pub const NID_policy_mappings: c_int = 747; +pub const NID_authority_key_identifier: c_int = 90; +pub const NID_policy_constraints: c_int = 401; pub const NID_ext_key_usage: c_int = 126; -pub const NID_key_usage: c_int = 83; +pub const NID_freshest_crl: c_int = 857; +pub const NID_inhibit_any_policy: c_int = 748; +pub const NID_target_information: c_int = 402; +pub const NID_no_rev_avail: c_int = 403; +pub const NID_anyExtendedKeyUsage: c_int = 910; +pub const NID_netscape: c_int = 57; +pub const NID_netscape_cert_extension: c_int = 58; +pub const NID_netscape_data_type: c_int = 59; +pub const NID_netscape_cert_type: c_int = 71; +pub const NID_netscape_base_url: c_int = 72; +pub const NID_netscape_revocation_url: c_int = 73; +pub const NID_netscape_ca_revocation_url: c_int = 74; +pub const NID_netscape_renewal_url: c_int = 75; +pub const NID_netscape_ca_policy_url: c_int = 76; +pub const NID_netscape_ssl_server_name: c_int = 77; +pub const NID_netscape_comment: c_int = 78; +pub const NID_netscape_cert_sequence: c_int = 79; +pub const NID_ns_sgc: c_int = 139; +pub const NID_org: c_int = 379; +pub const NID_dod: c_int = 380; +pub const NID_iana: c_int = 381; +pub const NID_Directory: c_int = 382; +pub const NID_Management: c_int = 383; +pub const NID_Experimental: c_int = 384; +pub const NID_Private: c_int = 385; +pub const NID_Security: c_int = 386; +pub const NID_SNMPv2: c_int = 387; +pub const NID_Mail: c_int = 388; +pub const NID_Enterprises: c_int = 389; +pub const NID_dcObject: c_int = 390; +pub const NID_mime_mhs: c_int = 504; +pub const NID_mime_mhs_headings: c_int = 505; +pub const NID_mime_mhs_bodies: c_int = 506; +pub const NID_id_hex_partial_message: c_int = 507; +pub const NID_id_hex_multipart_message: c_int = 508; +pub const NID_zlib_compression: c_int = 125; +pub const NID_aes_128_ecb: c_int = 418; +pub const NID_aes_128_cbc: c_int = 419; +pub const NID_aes_128_ofb128: c_int = 420; +pub const NID_aes_128_cfb128: c_int = 421; +pub const NID_id_aes128_wrap: c_int = 788; +pub const NID_aes_128_gcm: c_int = 895; +pub const NID_aes_128_ccm: c_int = 896; +pub const NID_id_aes128_wrap_pad: c_int = 897; +pub const NID_aes_192_ecb: c_int = 422; +pub const NID_aes_192_cbc: c_int = 423; +pub const NID_aes_192_ofb128: c_int = 424; +pub const NID_aes_192_cfb128: c_int = 425; +pub const NID_id_aes192_wrap: c_int = 789; +pub const NID_aes_192_gcm: c_int = 898; +pub const NID_aes_192_ccm: c_int = 899; +pub const NID_id_aes192_wrap_pad: c_int = 900; +pub const NID_aes_256_ecb: c_int = 426; +pub const NID_aes_256_cbc: c_int = 427; +pub const NID_aes_256_ofb128: c_int = 428; +pub const NID_aes_256_cfb128: c_int = 429; +pub const NID_id_aes256_wrap: c_int = 790; +pub const NID_aes_256_gcm: c_int = 901; +pub const NID_aes_256_ccm: c_int = 902; +pub const NID_id_aes256_wrap_pad: c_int = 903; +pub const NID_aes_128_cfb1: c_int = 650; +pub const NID_aes_192_cfb1: c_int = 651; +pub const NID_aes_256_cfb1: c_int = 652; +pub const NID_aes_128_cfb8: c_int = 653; +pub const NID_aes_192_cfb8: c_int = 654; +pub const NID_aes_256_cfb8: c_int = 655; +pub const NID_aes_128_ctr: c_int = 904; +pub const NID_aes_192_ctr: c_int = 905; +pub const NID_aes_256_ctr: c_int = 906; +pub const NID_aes_128_xts: c_int = 913; +pub const NID_aes_256_xts: c_int = 914; +pub const NID_des_cfb1: c_int = 656; +pub const NID_des_cfb8: c_int = 657; +pub const NID_des_ede3_cfb1: c_int = 658; +pub const NID_des_ede3_cfb8: c_int = 659; +pub const NID_sha256: c_int = 672; +pub const NID_sha384: c_int = 673; +pub const NID_sha512: c_int = 674; +pub const NID_sha224: c_int = 675; +pub const NID_dsa_with_SHA224: c_int = 802; +pub const NID_dsa_with_SHA256: c_int = 803; +pub const NID_hold_instruction_code: c_int = 430; +pub const NID_hold_instruction_none: c_int = 431; +pub const NID_hold_instruction_call_issuer: c_int = 432; +pub const NID_hold_instruction_reject: c_int = 433; +pub const NID_data: c_int = 434; +pub const NID_pss: c_int = 435; +pub const NID_ucl: c_int = 436; +pub const NID_pilot: c_int = 437; +pub const NID_pilotAttributeType: c_int = 438; +pub const NID_pilotAttributeSyntax: c_int = 439; +pub const NID_pilotObjectClass: c_int = 440; +pub const NID_pilotGroups: c_int = 441; +pub const NID_iA5StringSyntax: c_int = 442; +pub const NID_caseIgnoreIA5StringSyntax: c_int = 443; +pub const NID_pilotObject: c_int = 444; +pub const NID_pilotPerson: c_int = 445; +pub const NID_account: c_int = 446; +pub const NID_document: c_int = 447; +pub const NID_room: c_int = 448; +pub const NID_documentSeries: c_int = 449; +pub const NID_Domain: c_int = 392; +pub const NID_rFC822localPart: c_int = 450; +pub const NID_dNSDomain: c_int = 451; +pub const NID_domainRelatedObject: c_int = 452; +pub const NID_friendlyCountry: c_int = 453; +pub const NID_simpleSecurityObject: c_int = 454; +pub const NID_pilotOrganization: c_int = 455; +pub const NID_pilotDSA: c_int = 456; +pub const NID_qualityLabelledData: c_int = 457; +pub const NID_userId: c_int = 458; +pub const NID_textEncodedORAddress: c_int = 459; +pub const NID_rfc822Mailbox: c_int = 460; +pub const NID_info: c_int = 461; +pub const NID_favouriteDrink: c_int = 462; +pub const NID_roomNumber: c_int = 463; +pub const NID_photo: c_int = 464; +pub const NID_userClass: c_int = 465; +pub const NID_host: c_int = 466; +pub const NID_manager: c_int = 467; +pub const NID_documentIdentifier: c_int = 468; +pub const NID_documentTitle: c_int = 469; +pub const NID_documentVersion: c_int = 470; +pub const NID_documentAuthor: c_int = 471; +pub const NID_documentLocation: c_int = 472; +pub const NID_homeTelephoneNumber: c_int = 473; +pub const NID_secretary: c_int = 474; +pub const NID_otherMailbox: c_int = 475; +pub const NID_lastModifiedTime: c_int = 476; +pub const NID_lastModifiedBy: c_int = 477; +pub const NID_domainComponent: c_int = 391; +pub const NID_aRecord: c_int = 478; +pub const NID_pilotAttributeType27: c_int = 479; +pub const NID_mXRecord: c_int = 480; +pub const NID_nSRecord: c_int = 481; +pub const NID_sOARecord: c_int = 482; +pub const NID_cNAMERecord: c_int = 483; +pub const NID_associatedDomain: c_int = 484; +pub const NID_associatedName: c_int = 485; +pub const NID_homePostalAddress: c_int = 486; +pub const NID_personalTitle: c_int = 487; +pub const NID_mobileTelephoneNumber: c_int = 488; +pub const NID_pagerTelephoneNumber: c_int = 489; +pub const NID_friendlyCountryName: c_int = 490; +pub const NID_organizationalStatus: c_int = 491; +pub const NID_janetMailbox: c_int = 492; +pub const NID_mailPreferenceOption: c_int = 493; +pub const NID_buildingName: c_int = 494; +pub const NID_dSAQuality: c_int = 495; +pub const NID_singleLevelQuality: c_int = 496; +pub const NID_subtreeMinimumQuality: c_int = 497; +pub const NID_subtreeMaximumQuality: c_int = 498; +pub const NID_personalSignature: c_int = 499; +pub const NID_dITRedirect: c_int = 500; +pub const NID_audio: c_int = 501; +pub const NID_documentPublisher: c_int = 502; +pub const NID_id_set: c_int = 512; +pub const NID_set_ctype: c_int = 513; +pub const NID_set_msgExt: c_int = 514; +pub const NID_set_attr: c_int = 515; +pub const NID_set_policy: c_int = 516; +pub const NID_set_certExt: c_int = 517; +pub const NID_set_brand: c_int = 518; +pub const NID_setct_PANData: c_int = 519; +pub const NID_setct_PANToken: c_int = 520; +pub const NID_setct_PANOnly: c_int = 521; +pub const NID_setct_OIData: c_int = 522; +pub const NID_setct_PI: c_int = 523; +pub const NID_setct_PIData: c_int = 524; +pub const NID_setct_PIDataUnsigned: c_int = 525; +pub const NID_setct_HODInput: c_int = 526; +pub const NID_setct_AuthResBaggage: c_int = 527; +pub const NID_setct_AuthRevReqBaggage: c_int = 528; +pub const NID_setct_AuthRevResBaggage: c_int = 529; +pub const NID_setct_CapTokenSeq: c_int = 530; +pub const NID_setct_PInitResData: c_int = 531; +pub const NID_setct_PI_TBS: c_int = 532; +pub const NID_setct_PResData: c_int = 533; +pub const NID_setct_AuthReqTBS: c_int = 534; +pub const NID_setct_AuthResTBS: c_int = 535; +pub const NID_setct_AuthResTBSX: c_int = 536; +pub const NID_setct_AuthTokenTBS: c_int = 537; +pub const NID_setct_CapTokenData: c_int = 538; +pub const NID_setct_CapTokenTBS: c_int = 539; +pub const NID_setct_AcqCardCodeMsg: c_int = 540; +pub const NID_setct_AuthRevReqTBS: c_int = 541; +pub const NID_setct_AuthRevResData: c_int = 542; +pub const NID_setct_AuthRevResTBS: c_int = 543; +pub const NID_setct_CapReqTBS: c_int = 544; +pub const NID_setct_CapReqTBSX: c_int = 545; +pub const NID_setct_CapResData: c_int = 546; +pub const NID_setct_CapRevReqTBS: c_int = 547; +pub const NID_setct_CapRevReqTBSX: c_int = 548; +pub const NID_setct_CapRevResData: c_int = 549; +pub const NID_setct_CredReqTBS: c_int = 550; +pub const NID_setct_CredReqTBSX: c_int = 551; +pub const NID_setct_CredResData: c_int = 552; +pub const NID_setct_CredRevReqTBS: c_int = 553; +pub const NID_setct_CredRevReqTBSX: c_int = 554; +pub const NID_setct_CredRevResData: c_int = 555; +pub const NID_setct_PCertReqData: c_int = 556; +pub const NID_setct_PCertResTBS: c_int = 557; +pub const NID_setct_BatchAdminReqData: c_int = 558; +pub const NID_setct_BatchAdminResData: c_int = 559; +pub const NID_setct_CardCInitResTBS: c_int = 560; +pub const NID_setct_MeAqCInitResTBS: c_int = 561; +pub const NID_setct_RegFormResTBS: c_int = 562; +pub const NID_setct_CertReqData: c_int = 563; +pub const NID_setct_CertReqTBS: c_int = 564; +pub const NID_setct_CertResData: c_int = 565; +pub const NID_setct_CertInqReqTBS: c_int = 566; +pub const NID_setct_ErrorTBS: c_int = 567; +pub const NID_setct_PIDualSignedTBE: c_int = 568; +pub const NID_setct_PIUnsignedTBE: c_int = 569; +pub const NID_setct_AuthReqTBE: c_int = 570; +pub const NID_setct_AuthResTBE: c_int = 571; +pub const NID_setct_AuthResTBEX: c_int = 572; +pub const NID_setct_AuthTokenTBE: c_int = 573; +pub const NID_setct_CapTokenTBE: c_int = 574; +pub const NID_setct_CapTokenTBEX: c_int = 575; +pub const NID_setct_AcqCardCodeMsgTBE: c_int = 576; +pub const NID_setct_AuthRevReqTBE: c_int = 577; +pub const NID_setct_AuthRevResTBE: c_int = 578; +pub const NID_setct_AuthRevResTBEB: c_int = 579; +pub const NID_setct_CapReqTBE: c_int = 580; +pub const NID_setct_CapReqTBEX: c_int = 581; +pub const NID_setct_CapResTBE: c_int = 582; +pub const NID_setct_CapRevReqTBE: c_int = 583; +pub const NID_setct_CapRevReqTBEX: c_int = 584; +pub const NID_setct_CapRevResTBE: c_int = 585; +pub const NID_setct_CredReqTBE: c_int = 586; +pub const NID_setct_CredReqTBEX: c_int = 587; +pub const NID_setct_CredResTBE: c_int = 588; +pub const NID_setct_CredRevReqTBE: c_int = 589; +pub const NID_setct_CredRevReqTBEX: c_int = 590; +pub const NID_setct_CredRevResTBE: c_int = 591; +pub const NID_setct_BatchAdminReqTBE: c_int = 592; +pub const NID_setct_BatchAdminResTBE: c_int = 593; +pub const NID_setct_RegFormReqTBE: c_int = 594; +pub const NID_setct_CertReqTBE: c_int = 595; +pub const NID_setct_CertReqTBEX: c_int = 596; +pub const NID_setct_CertResTBE: c_int = 597; +pub const NID_setct_CRLNotificationTBS: c_int = 598; +pub const NID_setct_CRLNotificationResTBS: c_int = 599; +pub const NID_setct_BCIDistributionTBS: c_int = 600; +pub const NID_setext_genCrypt: c_int = 601; +pub const NID_setext_miAuth: c_int = 602; +pub const NID_setext_pinSecure: c_int = 603; +pub const NID_setext_pinAny: c_int = 604; +pub const NID_setext_track2: c_int = 605; +pub const NID_setext_cv: c_int = 606; +pub const NID_set_policy_root: c_int = 607; +pub const NID_setCext_hashedRoot: c_int = 608; +pub const NID_setCext_certType: c_int = 609; +pub const NID_setCext_merchData: c_int = 610; +pub const NID_setCext_cCertRequired: c_int = 611; +pub const NID_setCext_tunneling: c_int = 612; +pub const NID_setCext_setExt: c_int = 613; +pub const NID_setCext_setQualf: c_int = 614; +pub const NID_setCext_PGWYcapabilities: c_int = 615; +pub const NID_setCext_TokenIdentifier: c_int = 616; +pub const NID_setCext_Track2Data: c_int = 617; +pub const NID_setCext_TokenType: c_int = 618; +pub const NID_setCext_IssuerCapabilities: c_int = 619; +pub const NID_setAttr_Cert: c_int = 620; +pub const NID_setAttr_PGWYcap: c_int = 621; +pub const NID_setAttr_TokenType: c_int = 622; +pub const NID_setAttr_IssCap: c_int = 623; +pub const NID_set_rootKeyThumb: c_int = 624; +pub const NID_set_addPolicy: c_int = 625; +pub const NID_setAttr_Token_EMV: c_int = 626; +pub const NID_setAttr_Token_B0Prime: c_int = 627; +pub const NID_setAttr_IssCap_CVM: c_int = 628; +pub const NID_setAttr_IssCap_T2: c_int = 629; +pub const NID_setAttr_IssCap_Sig: c_int = 630; +pub const NID_setAttr_GenCryptgrm: c_int = 631; +pub const NID_setAttr_T2Enc: c_int = 632; +pub const NID_setAttr_T2cleartxt: c_int = 633; +pub const NID_setAttr_TokICCsig: c_int = 634; +pub const NID_setAttr_SecDevSig: c_int = 635; +pub const NID_set_brand_IATA_ATA: c_int = 636; +pub const NID_set_brand_Diners: c_int = 637; +pub const NID_set_brand_AmericanExpress: c_int = 638; +pub const NID_set_brand_JCB: c_int = 639; +pub const NID_set_brand_Visa: c_int = 640; +pub const NID_set_brand_MasterCard: c_int = 641; +pub const NID_set_brand_Novus: c_int = 642; +pub const NID_des_cdmf: c_int = 643; +pub const NID_rsaOAEPEncryptionSET: c_int = 644; +pub const NID_ipsec3: c_int = 749; +pub const NID_ipsec4: c_int = 750; +pub const NID_whirlpool: c_int = 804; +pub const NID_cryptopro: c_int = 805; +pub const NID_cryptocom: c_int = 806; +pub const NID_id_GostR3411_94_with_GostR3410_2001: c_int = 807; +pub const NID_id_GostR3411_94_with_GostR3410_94: c_int = 808; +pub const NID_id_GostR3411_94: c_int = 809; +pub const NID_id_HMACGostR3411_94: c_int = 810; +pub const NID_id_GostR3410_2001: c_int = 811; +pub const NID_id_GostR3410_94: c_int = 812; +pub const NID_id_Gost28147_89: c_int = 813; +pub const NID_gost89_cnt: c_int = 814; +pub const NID_id_Gost28147_89_MAC: c_int = 815; +pub const NID_id_GostR3411_94_prf: c_int = 816; +pub const NID_id_GostR3410_2001DH: c_int = 817; +pub const NID_id_GostR3410_94DH: c_int = 818; +pub const NID_id_Gost28147_89_CryptoPro_KeyMeshing: c_int = 819; +pub const NID_id_Gost28147_89_None_KeyMeshing: c_int = 820; +pub const NID_id_GostR3411_94_TestParamSet: c_int = 821; +pub const NID_id_GostR3411_94_CryptoProParamSet: c_int = 822; +pub const NID_id_Gost28147_89_TestParamSet: c_int = 823; +pub const NID_id_Gost28147_89_CryptoPro_A_ParamSet: c_int = 824; +pub const NID_id_Gost28147_89_CryptoPro_B_ParamSet: c_int = 825; +pub const NID_id_Gost28147_89_CryptoPro_C_ParamSet: c_int = 826; +pub const NID_id_Gost28147_89_CryptoPro_D_ParamSet: c_int = 827; +pub const NID_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet: c_int = 828; +pub const NID_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet: c_int = 829; +pub const NID_id_Gost28147_89_CryptoPro_RIC_1_ParamSet: c_int = 830; +pub const NID_id_GostR3410_94_TestParamSet: c_int = 831; +pub const NID_id_GostR3410_94_CryptoPro_A_ParamSet: c_int = 832; +pub const NID_id_GostR3410_94_CryptoPro_B_ParamSet: c_int = 833; +pub const NID_id_GostR3410_94_CryptoPro_C_ParamSet: c_int = 834; +pub const NID_id_GostR3410_94_CryptoPro_D_ParamSet: c_int = 835; +pub const NID_id_GostR3410_94_CryptoPro_XchA_ParamSet: c_int = 836; +pub const NID_id_GostR3410_94_CryptoPro_XchB_ParamSet: c_int = 837; +pub const NID_id_GostR3410_94_CryptoPro_XchC_ParamSet: c_int = 838; +pub const NID_id_GostR3410_2001_TestParamSet: c_int = 839; +pub const NID_id_GostR3410_2001_CryptoPro_A_ParamSet: c_int = 840; +pub const NID_id_GostR3410_2001_CryptoPro_B_ParamSet: c_int = 841; +pub const NID_id_GostR3410_2001_CryptoPro_C_ParamSet: c_int = 842; +pub const NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet: c_int = 843; +pub const NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet: c_int = 844; +pub const NID_id_GostR3410_94_a: c_int = 845; +pub const NID_id_GostR3410_94_aBis: c_int = 846; +pub const NID_id_GostR3410_94_b: c_int = 847; +pub const NID_id_GostR3410_94_bBis: c_int = 848; +pub const NID_id_Gost28147_89_cc: c_int = 849; +pub const NID_id_GostR3410_94_cc: c_int = 850; +pub const NID_id_GostR3410_2001_cc: c_int = 851; +pub const NID_id_GostR3411_94_with_GostR3410_94_cc: c_int = 852; +pub const NID_id_GostR3411_94_with_GostR3410_2001_cc: c_int = 853; +pub const NID_id_GostR3410_2001_ParamSet_cc: c_int = 854; +pub const NID_camellia_128_cbc: c_int = 751; +pub const NID_camellia_192_cbc: c_int = 752; +pub const NID_camellia_256_cbc: c_int = 753; +pub const NID_id_camellia128_wrap: c_int = 907; +pub const NID_id_camellia192_wrap: c_int = 908; +pub const NID_id_camellia256_wrap: c_int = 909; +pub const NID_camellia_128_ecb: c_int = 754; +pub const NID_camellia_128_ofb128: c_int = 766; +pub const NID_camellia_128_cfb128: c_int = 757; +pub const NID_camellia_192_ecb: c_int = 755; +pub const NID_camellia_192_ofb128: c_int = 767; +pub const NID_camellia_192_cfb128: c_int = 758; +pub const NID_camellia_256_ecb: c_int = 756; +pub const NID_camellia_256_ofb128: c_int = 768; +pub const NID_camellia_256_cfb128: c_int = 759; +pub const NID_camellia_128_cfb1: c_int = 760; +pub const NID_camellia_192_cfb1: c_int = 761; +pub const NID_camellia_256_cfb1: c_int = 762; +pub const NID_camellia_128_cfb8: c_int = 763; +pub const NID_camellia_192_cfb8: c_int = 764; +pub const NID_camellia_256_cfb8: c_int = 765; +pub const NID_kisa: c_int = 773; +pub const NID_seed_ecb: c_int = 776; +pub const NID_seed_cbc: c_int = 777; +pub const NID_seed_cfb128: c_int = 779; +pub const NID_seed_ofb128: c_int = 778; +pub const NID_hmac: c_int = 855; +pub const NID_cmac: c_int = 894; +pub const NID_rc4_hmac_md5: c_int = 915; +pub const NID_aes_128_cbc_hmac_sha1: c_int = 916; +pub const NID_aes_192_cbc_hmac_sha1: c_int = 917; +pub const NID_aes_256_cbc_hmac_sha1: c_int = 918; pub const PKCS5_SALT_LEN: c_int = 8; pub const RSA_F4: c_long = 0x10001; +pub const RSA_PKCS1_PADDING: c_int = 1; +pub const RSA_SSLV23_PADDING: c_int = 2; +pub const RSA_NO_PADDING: c_int = 3; +pub const RSA_PKCS1_OAEP_PADDING: c_int = 4; +pub const RSA_X931_PADDING: c_int = 5; + pub const SSL_CTRL_SET_TMP_DH: c_int = 3; +pub const SSL_CTRL_SET_TMP_ECDH: c_int = 4; pub const SSL_CTRL_EXTRA_CHAIN_CERT: c_int = 14; -pub const SSL_CTRL_OPTIONS: c_int = 32; pub const SSL_CTRL_MODE: c_int = 33; pub const SSL_CTRL_SET_READ_AHEAD: c_int = 41; pub const SSL_CTRL_SET_TLSEXT_SERVERNAME_CB: c_int = 53; pub const SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG: c_int = 54; pub const SSL_CTRL_SET_TLSEXT_HOSTNAME: c_int = 55; -pub const SSL_CTRL_CLEAR_OPTIONS: c_int = 77; -#[cfg(feature = "ecdh_auto")] -pub const SSL_CTRL_SET_ECDH_AUTO: c_int = 94; -pub const SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER: c_long = 2; -pub const SSL_MODE_AUTO_RETRY: c_long = 4; +pub const SSL_MODE_ENABLE_PARTIAL_WRITE: c_long = 0x1; +pub const SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER: c_long = 0x2; +pub const SSL_MODE_AUTO_RETRY: c_long = 0x4; +pub const SSL_MODE_NO_AUTO_CHAIN: c_long = 0x8; +pub const SSL_MODE_RELEASE_BUFFERS: c_long = 0x10; +pub const SSL_MODE_SEND_CLIENTHELLO_TIME: c_long = 0x20; +pub const SSL_MODE_SEND_SERVERHELLO_TIME: c_long = 0x40; +pub const SSL_MODE_SEND_FALLBACK_SCSV: c_long = 0x80; pub const SSL_ERROR_NONE: c_int = 0; pub const SSL_ERROR_SSL: c_int = 1; @@ -368,60 +1074,41 @@ pub const SSL_VERIFY_NONE: c_int = 0; pub const SSL_VERIFY_PEER: c_int = 1; pub const SSL_VERIFY_FAIL_IF_NO_PEER_CERT: c_int = 2; -pub const SSL_OP_MICROSOFT_SESS_ID_BUG: c_long = 0x00000001; -pub const SSL_OP_NETSCAPE_CHALLENGE_BUG: c_long = 0x00000002; -pub const SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG: c_long = 0x00000008; -pub const SSL_OP_TLSEXT_PADDING: c_long = 0x00000010; -pub const SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER: c_long = 0x00000020; -pub const SSL_OP_SSLEAY_080_CLIENT_DH_BUG: c_long = 0x00000080; -pub const SSL_OP_TLS_D5_BUG: c_long = 0x00000100; -pub const SSL_OP_TLS_BLOCK_PADDING_BUG: c_long = 0x00000200; -pub const SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS: c_long = 0x00000800; -pub const SSL_OP_ALL: c_long = 0x80000BFF; -pub const SSL_OP_NO_QUERY_MTU: c_long = 0x00001000; -pub const SSL_OP_COOKIE_EXCHANGE: c_long = 0x00002000; -pub const SSL_OP_NO_TICKET: c_long = 0x00004000; -pub const SSL_OP_CISCO_ANYCONNECT: c_long = 0x00008000; -pub const SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION: c_long = 0x00010000; -pub const SSL_OP_NO_COMPRESSION: c_long = 0x00020000; -pub const SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION: c_long = 0x00040000; -pub const SSL_OP_SINGLE_ECDH_USE: c_long = 0x00080000; -pub const SSL_OP_SINGLE_DH_USE: c_long = 0x00100000; -pub const SSL_OP_CIPHER_SERVER_PREFERENCE: c_long = 0x00400000; -pub const SSL_OP_TLS_ROLLBACK_BUG: c_long = 0x00800000; -pub const SSL_OP_NO_SSLv2: c_long = 0x01000000; -pub const SSL_OP_NO_SSLv3: c_long = 0x02000000; -pub const SSL_OP_NO_TLSv1: c_long = 0x04000000; +#[cfg(not(ossl101))] +pub const SSL_OP_TLSEXT_PADDING: c_ulong = 0x00000010; +pub const SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS: c_ulong = 0x00000800; +pub const SSL_OP_ALL: c_ulong = 0x80000BFF; +pub const SSL_OP_NO_QUERY_MTU: c_ulong = 0x00001000; +pub const SSL_OP_COOKIE_EXCHANGE: c_ulong = 0x00002000; +pub const SSL_OP_NO_TICKET: c_ulong = 0x00004000; +pub const SSL_OP_CISCO_ANYCONNECT: c_ulong = 0x00008000; +pub const SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION: c_ulong = 0x00010000; +pub const SSL_OP_NO_COMPRESSION: c_ulong = 0x00020000; +pub const SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION: c_ulong = 0x00040000; +pub const SSL_OP_CIPHER_SERVER_PREFERENCE: c_ulong = 0x00400000; +pub const SSL_OP_TLS_ROLLBACK_BUG: c_ulong = 0x00800000; +pub const SSL_OP_NO_SSLv3: c_ulong = 0x02000000; +pub const SSL_OP_NO_TLSv1: c_ulong = 0x04000000; +pub const SSL_OP_NO_TLSv1_2: c_ulong = 0x08000000; +pub const SSL_OP_NO_TLSv1_1: c_ulong = 0x10000000; -// Intentionally not bound since they conflict with SSL_OP_PKCS1_CHECK_1 and -// SSL_OP_PKCS1_CHECK_2 on 0.9.8 :( -/* -pub const SSL_OP_NO_TLSv1_2: c_long = 0x08000000; -pub const SSL_OP_NO_TLSv1_1: c_long = 0x10000000; -pub const SSL_OP_NO_DTLSv1: c_long = 0x04000000; -pub const SSL_OP_NO_DTLSv1_2: c_long = 0x08000000; -pub const SSL_OP_NO_SSL_MASK: c_long = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | +#[cfg(not(ossl101))] +pub const SSL_OP_NO_DTLSv1: c_ulong = 0x04000000; +#[cfg(not(ossl101))] +pub const SSL_OP_NO_DTLSv1_2: c_ulong = 0x08000000; +#[cfg(not(ossl101))] +pub const SSL_OP_NO_SSL_MASK: c_ulong = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2; -*/ -pub const TLSEXT_NAMETYPE_host_name: c_long = 0; +pub const TLSEXT_NAMETYPE_host_name: c_int = 0; pub const SSL_TLSEXT_ERR_OK: c_int = 0; pub const SSL_TLSEXT_ERR_ALERT_WARNING: c_int = 1; pub const SSL_TLSEXT_ERR_ALERT_FATAL: c_int = 2; pub const SSL_TLSEXT_ERR_NOACK: c_int = 3; -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; - -#[cfg(any(feature = "npn", feature = "alpn"))] pub const OPENSSL_NPN_UNSUPPORTED: c_int = 0; -#[cfg(any(feature = "npn", feature = "alpn"))] pub const OPENSSL_NPN_NEGOTIATED: c_int = 1; -#[cfg(any(feature = "npn", feature = "alpn"))] pub const OPENSSL_NPN_NO_OVERLAP: c_int = 2; pub const V_ASN1_GENERALIZEDTIME: c_int = 24; @@ -485,6 +1172,17 @@ pub const X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE: c_int = 45; pub const X509_V_ERR_UNSUPPORTED_NAME_SYNTAX: c_int = 53; pub const X509_V_OK: c_int = 0; +#[cfg(not(ossl101))] +pub const X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT: c_uint = 0x1; +#[cfg(not(ossl101))] +pub const X509_CHECK_FLAG_NO_WILDCARDS: c_uint = 0x2; +#[cfg(not(ossl101))] +pub const X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS: c_uint = 0x4; +#[cfg(not(ossl101))] +pub const X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS: c_uint = 0x8; +#[cfg(not(ossl101))] +pub const X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS: c_uint = 0x10; + pub const GEN_OTHERNAME: c_int = 0; pub const GEN_EMAIL: c_int = 1; pub const GEN_DNS: c_int = 2; @@ -495,59 +1193,6 @@ pub const GEN_URI: c_int = 6; pub const GEN_IPADD: c_int = 7; pub const GEN_RID: c_int = 8; -static mut MUTEXES: *mut Vec> = 0 as *mut Vec>; -static mut GUARDS: *mut Vec>> = 0 as *mut Vec>>; - -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>>> = - 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 "C" 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() {} - // macros pub unsafe fn BIO_get_mem_data(b: *mut BIO, pp: *mut *mut c_char) -> c_long { BIO_ctrl(b, BIO_CTRL_INFO, 0, pp as *mut c_void) @@ -569,18 +1214,6 @@ pub unsafe fn SSL_CTX_set_mode(ctx: *mut SSL_CTX, op: c_long) -> c_long { SSL_CTX_ctrl(ctx, SSL_CTRL_MODE, op, ptr::null_mut()) } -pub unsafe fn SSL_CTX_set_options(ctx: *mut SSL_CTX, op: c_long) -> c_long { - SSL_CTX_ctrl(ctx, SSL_CTRL_OPTIONS, op, ptr::null_mut()) -} - -pub unsafe fn SSL_CTX_clear_options(ctx: *mut SSL_CTX, op: c_long) -> c_long { - SSL_CTX_ctrl(ctx, SSL_CTRL_CLEAR_OPTIONS, op, ptr::null_mut()) -} - -pub unsafe fn SSL_CTX_get_options(ctx: *mut SSL_CTX) -> c_long { - SSL_CTX_ctrl(ctx, SSL_CTRL_OPTIONS, 0, ptr::null_mut()) -} - pub unsafe fn SSL_CTX_set_read_ahead(ctx: *mut SSL_CTX, m: c_long) -> c_long { SSL_CTX_ctrl(ctx, SSL_CTRL_SET_READ_AHEAD, m, ptr::null_mut()) } @@ -589,13 +1222,12 @@ pub unsafe fn SSL_CTX_set_tmp_dh(ctx: *mut SSL_CTX, dh: *mut DH) -> c_long { SSL_CTX_ctrl(ctx, SSL_CTRL_SET_TMP_DH, 0, dh as *mut c_void) } -pub unsafe fn SSL_CTX_add_extra_chain_cert(ctx: *mut SSL_CTX, x509: *mut X509) -> c_long { - SSL_CTX_ctrl(ctx, SSL_CTRL_EXTRA_CHAIN_CERT, 0, x509 as *mut c_void) +pub unsafe fn SSL_CTX_set_tmp_ecdh(ctx: *mut SSL_CTX, key: *mut EC_KEY) -> c_long { + SSL_CTX_ctrl(ctx, SSL_CTRL_SET_TMP_ECDH, 0, key as *mut c_void) } -#[cfg(feature = "ecdh_auto")] -pub unsafe fn SSL_CTX_set_ecdh_auto(ctx: *mut SSL_CTX, onoff: c_long) -> c_long { - SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, onoff, ptr::null_mut()) +pub unsafe fn SSL_CTX_add_extra_chain_cert(ctx: *mut SSL_CTX, x509: *mut X509) -> c_long { + SSL_CTX_ctrl(ctx, SSL_CTRL_EXTRA_CHAIN_CERT, 0, x509 as *mut c_void) } pub unsafe fn SSL_CTX_set_tlsext_servername_callback(ctx: *mut SSL_CTX, @@ -605,23 +1237,24 @@ pub unsafe fn SSL_CTX_set_tlsext_servername_callback(ctx: *mut SSL_CTX, } pub unsafe fn SSL_set_tlsext_host_name(s: *mut SSL, name: *mut c_char) -> c_long { - SSL_ctrl(s, SSL_CTRL_SET_TLSEXT_HOSTNAME, TLSEXT_NAMETYPE_host_name, name as *mut c_void) + SSL_ctrl(s, SSL_CTRL_SET_TLSEXT_HOSTNAME, + TLSEXT_NAMETYPE_host_name as c_long, + name as *mut c_void) } -pub unsafe fn EVP_CIPHER_block_size(e: *const EVP_CIPHER) -> c_int { - (*e).block_size +pub fn ERR_GET_LIB(l: c_ulong) -> c_int { + ((l >> 24) & 0x0FF) as c_int } -pub unsafe fn EVP_CIPHER_key_length(e: *const EVP_CIPHER) -> c_int { - (*e).key_len +pub fn ERR_GET_FUNC(l: c_ulong) -> c_int { + ((l >> 12) & 0xFFF) as c_int } -pub unsafe fn EVP_CIPHER_iv_length(e: *const EVP_CIPHER) -> c_int { - (*e).iv_len +pub fn ERR_GET_REASON(l: c_ulong) -> c_int { + (l & 0xFFF) as c_int } -// True functions -extern "C" { +extern { pub fn ASN1_INTEGER_set(dest: *mut ASN1_INTEGER, value: c_long) -> c_int; pub fn ASN1_STRING_type_new(ty: c_int) -> *mut ASN1_STRING; pub fn ASN1_TIME_free(tm: *mut ASN1_TIME); @@ -629,116 +1262,108 @@ extern "C" { pub fn BIO_ctrl(b: *mut BIO, cmd: c_int, larg: c_long, parg: *mut c_void) -> c_long; pub fn BIO_free_all(b: *mut BIO); - pub fn BIO_new(type_: *const BIO_METHOD) -> *mut BIO; pub fn BIO_new_fp(stream: *mut FILE, close_flag: c_int) -> *mut BIO; pub fn BIO_new_socket(sock: c_int, close_flag: c_int) -> *mut BIO; pub fn BIO_read(b: *mut BIO, buf: *mut c_void, len: c_int) -> c_int; pub fn BIO_write(b: *mut BIO, buf: *const c_void, len: c_int) -> c_int; - pub fn BIO_s_file() -> *const BIO_METHOD; - pub fn BIO_s_mem() -> *const BIO_METHOD; + #[cfg(ossl101)] + pub fn BIO_new_mem_buf(buf: *mut c_void, len: c_int) -> *mut BIO; + #[cfg(not(ossl101))] pub fn BIO_new_mem_buf(buf: *const c_void, len: c_int) -> *mut BIO; pub fn BIO_set_flags(b: *mut BIO, flags: c_int); pub fn BIO_clear_flags(b: *mut BIO, flags: c_int); pub fn BN_new() -> *mut BIGNUM; - pub fn BN_dup(n: *mut BIGNUM) -> *mut BIGNUM; + pub fn BN_dup(n: *const BIGNUM) -> *mut BIGNUM; + pub fn BN_clear(bn: *mut BIGNUM); + pub fn BN_free(bn: *mut BIGNUM); pub fn BN_clear_free(bn: *mut BIGNUM); pub fn BN_CTX_new() -> *mut BN_CTX; pub fn BN_CTX_free(ctx: *mut BN_CTX); - pub fn BN_num_bits(bn: *mut BIGNUM) -> c_int; + pub fn BN_num_bits(bn: *const BIGNUM) -> c_int; pub fn BN_set_negative(bn: *mut BIGNUM, n: c_int); - pub fn BN_set_word(bn: *mut BIGNUM, n: c_ulong) -> c_int; + pub fn BN_set_word(bn: *mut BIGNUM, n: BN_ULONG) -> c_int; /* Arithmetic operations on BIGNUMs */ - pub fn BN_add(r: *mut BIGNUM, a: *mut BIGNUM, b: *mut BIGNUM) -> c_int; - pub fn BN_div(dv: *mut BIGNUM, rem: *mut BIGNUM, a: *mut BIGNUM, b: *mut BIGNUM, ctx: *mut BN_CTX) -> c_int; - pub fn BN_exp(r: *mut BIGNUM, a: *mut BIGNUM, p: *mut BIGNUM, ctx: *mut BN_CTX) -> c_int; - pub fn BN_gcd(r: *mut BIGNUM, a: *mut BIGNUM, b: *mut BIGNUM, ctx: *mut BN_CTX) -> c_int; - pub fn BN_mod_add(r: *mut BIGNUM, a: *mut BIGNUM, b: *mut BIGNUM, m: *mut BIGNUM, ctx: *mut BN_CTX) -> c_int; - pub fn BN_mod_exp(r: *mut BIGNUM, a: *mut BIGNUM, p: *mut BIGNUM, m: *mut BIGNUM, ctx: *mut BN_CTX) -> c_int; - pub fn BN_mod_inverse(r: *mut BIGNUM, a: *mut BIGNUM, n: *mut BIGNUM, ctx: *mut BN_CTX) -> *const BIGNUM; - pub fn BN_mod_mul(r: *mut BIGNUM, a: *mut BIGNUM, b: *mut BIGNUM, m: *mut BIGNUM, ctx: *mut BN_CTX) -> c_int; - pub fn BN_mod_sqr(r: *mut BIGNUM, a: *mut BIGNUM, m: *mut BIGNUM, ctx: *mut BN_CTX) -> c_int; - pub fn BN_mod_sub(r: *mut BIGNUM, a: *mut BIGNUM, b: *mut BIGNUM, m: *mut BIGNUM, ctx: *mut BN_CTX) -> c_int; - pub fn BN_mul(r: *mut BIGNUM, a: *mut BIGNUM, b: *mut BIGNUM, ctx: *mut BN_CTX) -> c_int; - pub fn BN_nnmod(rem: *mut BIGNUM, a: *mut BIGNUM, m: *mut BIGNUM, ctx: *mut BN_CTX) -> c_int; - pub fn BN_add_word(r: *mut BIGNUM, w: c_ulong) -> c_int; - pub fn BN_sub_word(r: *mut BIGNUM, w: c_ulong) -> c_int; - pub fn BN_mul_word(r: *mut BIGNUM, w: c_ulong) -> c_int; - pub fn BN_div_word(r: *mut BIGNUM, w: c_ulong) -> c_ulong; - pub fn BN_mod_word(r: *const BIGNUM, w: c_ulong) -> c_ulong; - pub fn BN_sqr(r: *mut BIGNUM, a: *mut BIGNUM, ctx: *mut BN_CTX) -> c_int; - pub fn BN_sub(r: *mut BIGNUM, a: *mut BIGNUM, b: *mut BIGNUM) -> c_int; + pub fn BN_add(r: *mut BIGNUM, a: *const BIGNUM, b: *const BIGNUM) -> c_int; + pub fn BN_div(dv: *mut BIGNUM, rem: *mut BIGNUM, a: *const BIGNUM, b: *const BIGNUM, ctx: *mut BN_CTX) -> c_int; + pub fn BN_exp(r: *mut BIGNUM, a: *const BIGNUM, p: *const BIGNUM, ctx: *mut BN_CTX) -> c_int; + pub fn BN_gcd(r: *mut BIGNUM, a: *const BIGNUM, b: *const BIGNUM, ctx: *mut BN_CTX) -> c_int; + pub fn BN_mod_add(r: *mut BIGNUM, a: *const BIGNUM, b: *const BIGNUM, m: *const BIGNUM, ctx: *mut BN_CTX) -> c_int; + pub fn BN_mod_exp(r: *mut BIGNUM, a: *const BIGNUM, p: *const BIGNUM, m: *const BIGNUM, ctx: *mut BN_CTX) -> c_int; + pub fn BN_mod_inverse(r: *mut BIGNUM, a: *const BIGNUM, n: *const BIGNUM, ctx: *mut BN_CTX) -> *mut BIGNUM; + pub fn BN_mod_mul(r: *mut BIGNUM, a: *const BIGNUM, b: *const BIGNUM, m: *const BIGNUM, ctx: *mut BN_CTX) -> c_int; + pub fn BN_mod_sqr(r: *mut BIGNUM, a: *const BIGNUM, m: *const BIGNUM, ctx: *mut BN_CTX) -> c_int; + pub fn BN_mod_sub(r: *mut BIGNUM, a: *const BIGNUM, b: *const BIGNUM, m: *const BIGNUM, ctx: *mut BN_CTX) -> c_int; + pub fn BN_mul(r: *mut BIGNUM, a: *const BIGNUM, b: *const BIGNUM, ctx: *mut BN_CTX) -> c_int; + pub fn BN_nnmod(rem: *mut BIGNUM, a: *const BIGNUM, m: *const BIGNUM, ctx: *mut BN_CTX) -> c_int; + pub fn BN_add_word(r: *mut BIGNUM, w: BN_ULONG) -> c_int; + pub fn BN_sub_word(r: *mut BIGNUM, w: BN_ULONG) -> c_int; + pub fn BN_mul_word(r: *mut BIGNUM, w: BN_ULONG) -> c_int; + pub fn BN_div_word(r: *mut BIGNUM, w: BN_ULONG) -> BN_ULONG; + pub fn BN_mod_word(r: *const BIGNUM, w: BN_ULONG) -> BN_ULONG; + pub fn BN_sqr(r: *mut BIGNUM, a: *const BIGNUM, ctx: *mut BN_CTX) -> c_int; + pub fn BN_sub(r: *mut BIGNUM, a: *const BIGNUM, b: *const BIGNUM) -> c_int; /* Bit operations on BIGNUMs */ pub fn BN_clear_bit(a: *mut BIGNUM, n: c_int) -> c_int; - pub fn BN_is_bit_set(a: *mut BIGNUM, n: c_int) -> c_int; - pub fn BN_lshift(r: *mut BIGNUM, a: *mut BIGNUM, n: c_int) -> c_int; - pub fn BN_lshift1(r: *mut BIGNUM, a: *mut BIGNUM) -> c_int; + pub fn BN_is_bit_set(a: *const BIGNUM, n: c_int) -> c_int; + pub fn BN_lshift(r: *mut BIGNUM, a: *const BIGNUM, n: c_int) -> c_int; + pub fn BN_lshift1(r: *mut BIGNUM, a: *const BIGNUM) -> c_int; pub fn BN_mask_bits(a: *mut BIGNUM, n: c_int) -> c_int; - pub fn BN_rshift(r: *mut BIGNUM, a: *mut BIGNUM, n: c_int) -> c_int; + pub fn BN_rshift(r: *mut BIGNUM, a: *const BIGNUM, n: c_int) -> c_int; pub fn BN_set_bit(a: *mut BIGNUM, n: c_int) -> c_int; - pub fn BN_rshift1(r: *mut BIGNUM, a: *mut BIGNUM) -> c_int; + pub fn BN_rshift1(r: *mut BIGNUM, a: *const BIGNUM) -> c_int; /* Comparisons on BIGNUMs */ - pub fn BN_cmp(a: *mut BIGNUM, b: *mut BIGNUM) -> c_int; - pub fn BN_ucmp(a: *mut BIGNUM, b: *mut BIGNUM) -> c_int; + pub fn BN_cmp(a: *const BIGNUM, b: *const BIGNUM) -> c_int; + pub fn BN_ucmp(a: *const BIGNUM, b: *const BIGNUM) -> c_int; /* Prime handling */ - pub fn BN_generate_prime_ex(r: *mut BIGNUM, bits: c_int, safe: c_int, add: *mut BIGNUM, rem: *mut BIGNUM, cb: *const c_void) -> c_int; - pub fn BN_is_prime_ex(p: *mut BIGNUM, checks: c_int, ctx: *mut BN_CTX, cb: *const c_void) -> c_int; - pub fn BN_is_prime_fasttest_ex(p: *mut BIGNUM, checks: c_int, ctx: *mut BN_CTX, do_trial_division: c_int, cb: *const c_void) -> c_int; + pub fn BN_generate_prime_ex(r: *mut BIGNUM, bits: c_int, safe: c_int, add: *const BIGNUM, rem: *const BIGNUM, cb: *mut BN_GENCB) -> c_int; + pub fn BN_is_prime_ex(p: *const BIGNUM, checks: c_int, ctx: *mut BN_CTX, cb: *mut BN_GENCB) -> c_int; + pub fn BN_is_prime_fasttest_ex(p: *const BIGNUM, checks: c_int, ctx: *mut BN_CTX, do_trial_division: c_int, cb: *mut BN_GENCB) -> c_int; /* Random number handling */ pub fn BN_rand(r: *mut BIGNUM, bits: c_int, top: c_int, bottom: c_int) -> c_int; pub fn BN_pseudo_rand(r: *mut BIGNUM, bits: c_int, top: c_int, bottom: c_int) -> c_int; - pub fn BN_rand_range(r: *mut BIGNUM, range: *mut BIGNUM) -> c_int; - pub fn BN_pseudo_rand_range(r: *mut BIGNUM, range: *mut BIGNUM) -> c_int; + pub fn BN_rand_range(r: *mut BIGNUM, range: *const BIGNUM) -> c_int; + pub fn BN_pseudo_rand_range(r: *mut BIGNUM, range: *const BIGNUM) -> c_int; /* Conversion from/to binary representation */ pub fn BN_bin2bn(s: *const u8, size: c_int, ret: *mut BIGNUM) -> *mut BIGNUM; - pub fn BN_bn2bin(a: *mut BIGNUM, to: *mut u8) -> c_int; + pub fn BN_bn2bin(a: *const BIGNUM, to: *mut u8) -> c_int; /* Conversion from/to decimal string representation */ - pub fn BN_dec2bn(a: *const *mut BIGNUM, s: *const c_char) -> c_int; - pub fn BN_bn2dec(a: *mut BIGNUM) -> *const c_char; + pub fn BN_dec2bn(a: *mut *mut BIGNUM, s: *const c_char) -> c_int; + pub fn BN_bn2dec(a: *const BIGNUM) -> *mut c_char; /* Conversion from/to hexidecimal string representation */ - pub fn BN_hex2bn(a: *const *mut BIGNUM, s: *const c_char) -> c_int; - pub fn BN_bn2hex(a: *mut BIGNUM) -> *const c_char; + pub fn BN_hex2bn(a: *mut *mut BIGNUM, s: *const c_char) -> c_int; + pub fn BN_bn2hex(a: *const BIGNUM) -> *mut c_char; - 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 CRYPTO_free(buf: *mut c_void); pub fn CRYPTO_memcmp(a: *const c_void, b: *const c_void, len: size_t) -> c_int; + pub fn DH_new() -> *mut DH; pub fn DH_free(dh: *mut DH); - - #[cfg(feature = "rfc5114")] + #[cfg(not(ossl101))] pub fn DH_get_1024_160() -> *mut DH; - #[cfg(feature = "rfc5114")] + #[cfg(not(ossl101))] pub fn DH_get_2048_224() -> *mut DH; - #[cfg(feature = "rfc5114")] + #[cfg(not(ossl101))] pub fn DH_get_2048_256() -> *mut DH; - // FIXME delete on next version bump - pub fn DH_new_from_params(p: *mut BIGNUM, g: *mut BIGNUM, q: *mut BIGNUM) -> *mut DH; + pub fn EC_KEY_new_by_curve_name(nid: c_int) -> *mut EC_KEY; + pub fn EC_KEY_free(key: *mut EC_KEY); pub fn ERR_get_error() -> c_ulong; - pub fn ERR_lib_error_string(err: c_ulong) -> *const c_char; pub fn ERR_func_error_string(err: c_ulong) -> *const c_char; pub fn ERR_reason_error_string(err: c_ulong) -> *const c_char; - pub fn ERR_load_crypto_strings(); - pub fn EVP_md5() -> *const EVP_MD; pub fn EVP_ripemd160() -> *const EVP_MD; pub fn EVP_sha1() -> *const EVP_MD; @@ -749,21 +1374,17 @@ extern "C" { pub fn EVP_aes_128_cbc() -> *const EVP_CIPHER; pub fn EVP_aes_128_ecb() -> *const EVP_CIPHER; - #[cfg(feature = "aes_xts")] pub fn EVP_aes_128_xts() -> *const EVP_CIPHER; - #[cfg(feature = "aes_ctr")] pub fn EVP_aes_128_ctr() -> *const EVP_CIPHER; - // fn EVP_aes_128_gcm() -> EVP_CIPHER; + pub fn EVP_aes_128_gcm() -> *const EVP_CIPHER; pub fn EVP_aes_128_cfb1() -> *const EVP_CIPHER; pub fn EVP_aes_128_cfb128() -> *const EVP_CIPHER; pub fn EVP_aes_128_cfb8() -> *const EVP_CIPHER; pub fn EVP_aes_256_cbc() -> *const EVP_CIPHER; pub fn EVP_aes_256_ecb() -> *const EVP_CIPHER; - #[cfg(feature = "aes_xts")] pub fn EVP_aes_256_xts() -> *const EVP_CIPHER; - #[cfg(feature = "aes_ctr")] pub fn EVP_aes_256_ctr() -> *const EVP_CIPHER; - // fn EVP_aes_256_gcm() -> EVP_CIPHER; + pub fn EVP_aes_256_gcm() -> *const EVP_CIPHER; pub fn EVP_aes_256_cfb1() -> *const EVP_CIPHER; pub fn EVP_aes_256_cfb128() -> *const EVP_CIPHER; pub fn EVP_aes_256_cfb8() -> *const EVP_CIPHER; @@ -786,35 +1407,56 @@ extern "C" { pub fn EVP_CipherInit_ex(ctx: *mut EVP_CIPHER_CTX, type_: *const EVP_CIPHER, impl_: *mut ENGINE, - key: *mut c_uchar, - iv: *mut c_uchar, + key: *const c_uchar, + iv: *const c_uchar, enc: c_int) -> c_int; pub fn EVP_CipherUpdate(ctx: *mut EVP_CIPHER_CTX, outbuf: *mut u8, - outlen: &mut c_int, inbuf: *const u8, inlen: c_int) -> c_int; - pub fn EVP_CipherFinal(ctx: *mut EVP_CIPHER_CTX, res: *mut u8, len: &mut c_int) -> c_int; + outlen: *mut c_int, inbuf: *const u8, inlen: c_int) -> c_int; + pub fn EVP_CipherFinal(ctx: *mut EVP_CIPHER_CTX, res: *mut u8, len: *mut c_int) -> c_int; pub fn EVP_DigestInit(ctx: *mut EVP_MD_CTX, typ: *const EVP_MD) -> c_int; - pub fn EVP_DigestInit_ex(ctx: *mut EVP_MD_CTX, typ: *const EVP_MD, imple: *const ENGINE) -> c_int; - pub fn EVP_DigestUpdate(ctx: *mut EVP_MD_CTX, data: *const u8, n: c_uint) -> c_int; + pub fn EVP_DigestInit_ex(ctx: *mut EVP_MD_CTX, typ: *const EVP_MD, imple: *mut ENGINE) -> c_int; + pub fn EVP_DigestUpdate(ctx: *mut EVP_MD_CTX, data: *const c_void, n: size_t) -> c_int; pub fn EVP_DigestFinal(ctx: *mut EVP_MD_CTX, res: *mut u8, n: *mut u32) -> c_int; pub fn EVP_DigestFinal_ex(ctx: *mut EVP_MD_CTX, res: *mut u8, n: *mut u32) -> c_int; - pub fn EVP_MD_CTX_create() -> *mut EVP_MD_CTX; + pub fn EVP_DigestSignInit(ctx: *mut EVP_MD_CTX, + pctx: *mut *mut EVP_PKEY_CTX, + type_: *const EVP_MD, + e: *mut ENGINE, + pkey: *mut EVP_PKEY) -> c_int; + pub fn EVP_DigestSignFinal(ctx: *mut EVP_MD_CTX, + sig: *mut c_uchar, + siglen: *mut size_t) -> c_int; + pub fn EVP_DigestVerifyInit(ctx: *mut EVP_MD_CTX, + pctx: *mut *mut EVP_PKEY_CTX, + type_: *const EVP_MD, + e: *mut ENGINE, + pkey: *mut EVP_PKEY) -> c_int; + #[cfg(ossl101)] + pub fn EVP_DigestVerifyFinal(ctx: *mut EVP_MD_CTX, + sigret: *mut c_uchar, + siglen: size_t) -> c_int; + #[cfg(not(ossl101))] + pub fn EVP_DigestVerifyFinal(ctx: *mut EVP_MD_CTX, + sigret: *const c_uchar, + siglen: size_t) -> c_int; + pub fn EVP_MD_CTX_copy_ex(dst: *mut EVP_MD_CTX, src: *const EVP_MD_CTX) -> c_int; - pub fn EVP_MD_CTX_destroy(ctx: *mut EVP_MD_CTX); pub fn EVP_PKEY_new() -> *mut EVP_PKEY; pub fn EVP_PKEY_free(k: *mut EVP_PKEY); - pub fn EVP_PKEY_assign(pkey: *mut EVP_PKEY, typ: c_int, key: *const c_void) -> c_int; + pub fn EVP_PKEY_assign(pkey: *mut EVP_PKEY, typ: c_int, key: *mut c_void) -> c_int; pub fn EVP_PKEY_copy_parameters(to: *mut EVP_PKEY, from: *const EVP_PKEY) -> c_int; pub fn EVP_PKEY_get1_RSA(k: *mut EVP_PKEY) -> *mut RSA; pub fn EVP_PKEY_set1_RSA(k: *mut EVP_PKEY, r: *mut RSA) -> c_int; pub fn EVP_PKEY_cmp(a: *const EVP_PKEY, b: *const EVP_PKEY) -> c_int; + pub fn EVP_PKEY_new_mac_key(type_: c_int, + e: *mut ENGINE, + key: *const c_uchar, + keylen: c_int) -> *mut EVP_PKEY; - pub fn HMAC_CTX_init(ctx: *mut HMAC_CTX); - pub fn HMAC_CTX_cleanup(ctx: *mut HMAC_CTX); - #[cfg(feature = "hmac_clone")] - pub fn HMAC_CTX_copy(dst: *mut HMAC_CTX, src: *const HMAC_CTX) -> c_int; + pub fn HMAC_CTX_copy(dst: *mut HMAC_CTX, src: *mut HMAC_CTX) -> c_int; pub fn PEM_read_bio_DHparams(bio: *mut BIO, out: *mut *mut DH, callback: Option, user_data: *mut c_void) -> *mut DH; @@ -830,6 +1472,7 @@ extern "C" { pub fn PEM_read_bio_RSAPrivateKey(bio: *mut BIO, rsa: *mut *mut RSA, callback: Option, user_data: *mut c_void) -> *mut RSA; pub fn PEM_read_bio_RSA_PUBKEY(bio: *mut BIO, rsa: *mut *mut RSA, callback: Option, user_data: *mut c_void) -> *mut RSA; + pub fn PEM_write_bio_DHparams(bio: *mut BIO, x: *const DH) -> c_int; pub fn PEM_write_bio_PrivateKey(bio: *mut BIO, pkey: *mut EVP_PKEY, cipher: *const EVP_CIPHER, kstr: *mut c_uchar, klen: c_int, callback: Option, @@ -839,7 +1482,7 @@ extern "C" { kstr: *mut c_uchar, klen: c_int, callback: Option, user_data: *mut c_void) -> c_int; - pub fn PEM_write_bio_RSAPublicKey(bp: *mut BIO, rsa: *mut RSA) -> c_int; + pub fn PEM_write_bio_RSAPublicKey(bp: *mut BIO, rsa: *const RSA) -> c_int; pub fn PEM_write_bio_RSA_PUBKEY(bp: *mut BIO, rsa: *mut RSA) -> c_int; pub fn PEM_read_bio_DSAPrivateKey(bp: *mut BIO, dsa: *mut *mut DSA, callback: Option, @@ -856,21 +1499,20 @@ extern "C" { pub fn PEM_write_bio_X509(bio: *mut BIO, x509: *mut X509) -> c_int; pub fn PEM_write_bio_X509_REQ(bio: *mut BIO, x509: *mut X509_REQ) -> c_int; - pub fn PKCS5_PBKDF2_HMAC_SHA1(pass: *const u8, passlen: c_int, + pub fn PKCS5_PBKDF2_HMAC_SHA1(pass: *const c_char, passlen: c_int, salt: *const u8, saltlen: c_int, iter: c_int, keylen: c_int, out: *mut u8) -> c_int; - #[cfg(feature = "pkcs5_pbkdf2_hmac")] - pub fn PKCS5_PBKDF2_HMAC(pass: *const u8, passlen: c_int, - salt: *const u8, saltlen: c_int, + pub fn PKCS5_PBKDF2_HMAC(pass: *const c_char, passlen: c_int, + salt: *const c_uchar, saltlen: c_int, iter: c_int, digest: *const EVP_MD, keylen: c_int, out: *mut u8) -> c_int; pub fn RAND_bytes(buf: *mut u8, num: c_int) -> c_int; + pub fn RAND_status() -> c_int; pub fn RSA_new() -> *mut RSA; pub fn RSA_free(rsa: *mut RSA); - pub fn RSA_generate_key(modsz: c_int, e: c_ulong, cb: *const c_void, cbarg: *const c_void) -> *mut RSA; pub fn RSA_generate_key_ex(rsa: *mut RSA, bits: c_int, e: *mut BIGNUM, cb: *mut BN_GENCB) -> c_int; pub fn RSA_private_decrypt(flen: c_int, from: *const u8, to: *mut u8, k: *mut RSA, pad: c_int) -> c_int; @@ -882,7 +1524,7 @@ extern "C" { pad: c_int) -> c_int; pub fn RSA_sign(t: c_int, m: *const u8, mlen: c_uint, sig: *mut u8, siglen: *mut c_uint, k: *mut RSA) -> c_int; - pub fn RSA_size(k: *mut RSA) -> c_int; + pub fn RSA_size(k: *const RSA) -> c_int; pub fn RSA_verify(t: c_int, m: *const u8, mlen: c_uint, sig: *const u8, siglen: c_uint, k: *mut RSA) -> c_int; @@ -891,75 +1533,55 @@ extern "C" { pub fn DSA_size(dsa: *const DSA) -> c_int; pub fn DSA_generate_parameters_ex(dsa: *mut DSA, bits: c_int, seed: *const c_uchar, seed_len: c_int, counter_ref: *mut c_int, h_ret: *mut c_ulong, - cb: *const c_void) -> c_int; + cb: *mut BN_GENCB) -> c_int; pub fn DSA_generate_key(dsa: *mut DSA) -> c_int; pub fn DSA_sign(dummy: c_int, dgst: *const c_uchar, len: c_int, sigret: *mut c_uchar, siglen: *mut c_uint, dsa: *mut DSA) -> c_int; pub fn DSA_verify(dummy: c_int, dgst: *const c_uchar, len: c_int, sigbuf: *const c_uchar, siglen: c_int, dsa: *mut DSA) -> c_int; - pub fn SSL_library_init() -> c_int; - pub fn SSL_load_error_strings(); - pub fn OPENSSL_add_all_algorithms_noconf(); - - #[cfg(feature = "sslv2")] - pub fn SSLv2_method() -> *const SSL_METHOD; - pub fn SSLv3_method() -> *const SSL_METHOD; - pub fn TLSv1_method() -> *const SSL_METHOD; - #[cfg(feature = "tlsv1_1")] - pub fn TLSv1_1_method() -> *const SSL_METHOD; - #[cfg(feature = "tlsv1_2")] - pub fn TLSv1_2_method() -> *const SSL_METHOD; - #[cfg(feature = "dtlsv1")] - pub fn DTLSv1_method() -> *const SSL_METHOD; - #[cfg(feature = "dtlsv1_2")] - pub fn DTLSv1_2_method() -> *const SSL_METHOD; - pub fn SSLv23_method() -> *const SSL_METHOD; - pub fn SSL_new(ctx: *mut SSL_CTX) -> *mut SSL; pub fn SSL_pending(ssl: *const SSL) -> c_int; pub fn SSL_free(ssl: *mut SSL); pub fn SSL_set_bio(ssl: *mut SSL, rbio: *mut BIO, wbio: *mut BIO); - pub fn SSL_get_rbio(ssl: *mut SSL) -> *mut BIO; - pub fn SSL_get_wbio(ssl: *mut SSL) -> *mut BIO; + pub fn SSL_get_rbio(ssl: *const SSL) -> *mut BIO; + pub fn SSL_get_wbio(ssl: *const SSL) -> *mut BIO; pub fn SSL_accept(ssl: *mut SSL) -> c_int; pub fn SSL_connect(ssl: *mut SSL) -> c_int; pub fn SSL_do_handshake(ssl: *mut SSL) -> c_int; pub fn SSL_ctrl(ssl: *mut SSL, cmd: c_int, larg: c_long, parg: *mut c_void) -> c_long; - pub fn SSL_get_error(ssl: *mut SSL, ret: c_int) -> c_int; + pub fn SSL_get_error(ssl: *const SSL, ret: c_int) -> c_int; pub fn SSL_read(ssl: *mut SSL, buf: *mut c_void, num: c_int) -> c_int; pub fn SSL_write(ssl: *mut SSL, buf: *const c_void, num: c_int) -> c_int; pub fn SSL_get_ex_data_X509_STORE_CTX_idx() -> c_int; - pub fn SSL_get_SSL_CTX(ssl: *mut SSL) -> *mut SSL_CTX; + pub fn SSL_get_SSL_CTX(ssl: *const SSL) -> *mut SSL_CTX; pub fn SSL_set_SSL_CTX(ssl: *mut SSL, ctx: *mut SSL_CTX) -> *mut SSL_CTX; + #[cfg(not(osslconf = "OPENSSL_NO_COMP"))] pub fn SSL_get_current_compression(ssl: *mut SSL) -> *const COMP_METHOD; - pub fn SSL_get_peer_certificate(ssl: *mut SSL) -> *mut X509; + pub fn SSL_get_peer_certificate(ssl: *const SSL) -> *mut X509; pub fn SSL_get_ssl_method(ssl: *mut SSL) -> *const SSL_METHOD; - pub fn SSL_get_version(ssl: *mut SSL) -> *const c_char; - pub fn SSL_state_string(ssl: *mut SSL) -> *const c_char; - pub fn SSL_state_string_long(ssl: *mut SSL) -> *const c_char; + pub fn SSL_get_version(ssl: *const SSL) -> *const c_char; + pub fn SSL_state_string(ssl: *const SSL) -> *const c_char; + pub fn SSL_state_string_long(ssl: *const SSL) -> *const c_char; pub fn SSL_set_verify(ssl: *mut SSL, mode: c_int, verify_callback: Option c_int>); - pub fn SSL_get_ex_new_index(argl: c_long, argp: *const c_void, - new_func: Option, - dup_func: Option, - free_func: Option) - -> c_int; pub fn SSL_set_ex_data(ssl: *mut SSL, idx: c_int, data: *mut c_void) -> c_int; - pub fn SSL_get_ex_data(ssl: *mut SSL, idx: c_int) -> *mut c_void; - - pub fn SSL_get_servername(ssl: *const SSL, name_type: c_long) -> *const c_char; + pub fn SSL_get_ex_data(ssl: *const SSL, idx: c_int) -> *mut c_void; + pub fn SSL_get_servername(ssl: *const SSL, name_type: c_int) -> *const c_char; + pub fn SSL_get_current_cipher(ssl: *const SSL) -> *const SSL_CIPHER; + #[cfg(not(ossl101))] + pub fn SSL_get0_param(ssl: *mut SSL) -> *mut X509_VERIFY_PARAM; + pub fn SSL_get_verify_result(ssl: *const SSL) -> c_long; + pub fn SSL_shutdown(ssl: *mut SSL) -> c_int; + #[cfg(not(osslconf = "OPENSSL_NO_COMP"))] pub fn SSL_COMP_get_name(comp: *const COMP_METHOD) -> *const c_char; - pub fn SSL_get_current_cipher(ssl: *const SSL) -> *const SSL_CIPHER; - pub fn SSL_CIPHER_get_name(cipher: *const SSL_CIPHER) -> *const c_char; - pub fn SSL_CIPHER_get_bits(cipher: *const SSL_CIPHER, alg_bits: *const c_int) -> c_int; - pub fn SSL_CIPHER_get_version(cipher: *const SSL_CIPHER) -> *const c_char; - pub fn SSL_CIPHER_description(cipher: *const SSL_CIPHER, buf: *mut c_char, size: c_int) -> *const c_char; + pub fn SSL_CIPHER_get_bits(cipher: *const SSL_CIPHER, alg_bits: *mut c_int) -> c_int; + pub fn SSL_CIPHER_description(cipher: *const SSL_CIPHER, buf: *mut c_char, size: c_int) -> *mut c_char; pub fn SSL_CTX_new(method: *const SSL_METHOD) -> *mut SSL_CTX; pub fn SSL_CTX_free(ctx: *mut SSL_CTX); @@ -971,34 +1593,27 @@ extern "C" { pub fn SSL_CTX_load_verify_locations(ctx: *mut SSL_CTX, CAfile: *const c_char, CApath: *const c_char) -> c_int; pub fn SSL_CTX_set_default_verify_paths(ctx: *mut SSL_CTX) -> c_int; - pub fn SSL_CTX_get_ex_new_index(argl: c_long, argp: *const c_void, - new_func: Option, - dup_func: Option, - free_func: Option) - -> c_int; pub fn SSL_CTX_set_ex_data(ctx: *mut SSL_CTX, idx: c_int, data: *mut c_void) -> c_int; - pub fn SSL_CTX_get_ex_data(ctx: *mut SSL_CTX, idx: c_int) -> *mut c_void; + pub fn SSL_CTX_get_ex_data(ctx: *const SSL_CTX, idx: c_int) -> *mut c_void; pub fn SSL_CTX_set_session_id_context(ssl: *mut SSL_CTX, sid_ctx: *const c_uchar, sid_ctx_len: c_uint) -> c_int; pub fn SSL_CTX_use_certificate_file(ctx: *mut SSL_CTX, cert_file: *const c_char, file_type: c_int) -> c_int; - pub fn SSL_CTX_use_certificate_chain_file(ctx: *mut SSL_CTX, cert_chain_file: *const c_char, file_type: c_int) -> c_int; + pub fn SSL_CTX_use_certificate_chain_file(ctx: *mut SSL_CTX, cert_chain_file: *const c_char) -> c_int; pub fn SSL_CTX_use_certificate(ctx: *mut SSL_CTX, cert: *mut X509) -> c_int; pub fn SSL_CTX_use_PrivateKey_file(ctx: *mut SSL_CTX, key_file: *const c_char, file_type: c_int) -> c_int; pub fn SSL_CTX_use_PrivateKey(ctx: *mut SSL_CTX, key: *mut EVP_PKEY) -> c_int; - pub fn SSL_CTX_check_private_key(ctx: *mut SSL_CTX) -> c_int; + pub fn SSL_CTX_check_private_key(ctx: *const SSL_CTX) -> c_int; pub fn SSL_CTX_set_cipher_list(ssl: *mut SSL_CTX, s: *const c_char) -> c_int; - #[cfg(feature = "npn")] pub fn SSL_CTX_set_next_protos_advertised_cb(ssl: *mut SSL_CTX, cb: extern "C" fn(ssl: *mut SSL, out: *mut *const c_uchar, outlen: *mut c_uint, arg: *mut c_void) -> c_int, arg: *mut c_void); - #[cfg(feature = "npn")] pub fn SSL_CTX_set_next_proto_select_cb(ssl: *mut SSL_CTX, cb: extern "C" fn(ssl: *mut SSL, out: *mut *mut c_uchar, @@ -1007,80 +1622,85 @@ extern "C" { inlen: c_uint, arg: *mut c_void) -> c_int, arg: *mut c_void); - #[cfg(any(feature = "alpn", feature = "npn"))] pub fn SSL_select_next_proto(out: *mut *mut c_uchar, outlen: *mut c_uchar, inbuf: *const c_uchar, inlen: c_uint, client: *const c_uchar, client_len: c_uint) -> c_int; - #[cfg(feature = "npn")] pub fn SSL_get0_next_proto_negotiated(s: *const SSL, data: *mut *const c_uchar, len: *mut c_uint); - #[cfg(feature = "alpn")] + #[cfg(not(ossl101))] pub fn SSL_CTX_set_alpn_protos(s: *mut SSL_CTX, data: *const c_uchar, len: c_uint) -> c_int; - #[cfg(feature = "alpn")] + #[cfg(not(ossl101))] pub fn SSL_set_alpn_protos(s: *mut SSL, data: *const c_uchar, len: c_uint) -> c_int; - #[cfg(feature = "alpn")] + #[cfg(not(ossl101))] pub fn SSL_CTX_set_alpn_select_cb(ssl: *mut SSL_CTX, - cb: extern "C" fn(ssl: *mut SSL, - out: *mut *mut c_uchar, - outlen: *mut c_uchar, - inbuf: *const c_uchar, - inlen: c_uint, - arg: *mut c_void) -> c_int, - arg: *mut c_void); - #[cfg(feature = "alpn")] + cb: extern fn(ssl: *mut SSL, + out: *mut *const c_uchar, + outlen: *mut c_uchar, + inbuf: *const c_uchar, + inlen: c_uint, + arg: *mut c_void) -> c_int, + arg: *mut c_void); + #[cfg(not(ossl101))] pub fn SSL_get0_alpn_selected(s: *const SSL, data: *mut *const c_uchar, len: *mut c_uint); pub fn X509_add_ext(x: *mut X509, ext: *mut X509_EXTENSION, loc: c_int) -> c_int; - pub fn X509_digest(x: *mut X509, digest: *const EVP_MD, buf: *mut c_char, len: *mut c_uint) -> c_int; + pub fn X509_digest(x: *const X509, digest: *const EVP_MD, buf: *mut c_uchar, len: *mut c_uint) -> c_int; pub fn X509_free(x: *mut X509); pub fn X509_REQ_free(x: *mut X509_REQ); pub fn X509_get_serialNumber(x: *mut X509) -> *mut ASN1_INTEGER; - pub fn X509_get_subject_name(x: *mut X509) -> *mut X509_NAME; pub fn X509_gmtime_adj(time: *mut ASN1_TIME, adj: c_long) -> *mut ASN1_TIME; pub fn X509_new() -> *mut X509; pub fn X509_set_issuer_name(x: *mut X509, name: *mut X509_NAME) -> c_int; - 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_set_version(x: *mut X509, version: c_ulong) -> c_int; + pub fn X509_set_version(x: *mut X509, version: c_long) -> c_int; pub fn X509_set_pubkey(x: *mut X509, pkey: *mut EVP_PKEY) -> c_int; pub fn X509_sign(x: *mut X509, pkey: *mut EVP_PKEY, md: *const EVP_MD) -> c_int; pub fn X509_get_pubkey(x: *mut X509) -> *mut EVP_PKEY; pub fn X509_to_X509_REQ(x: *mut X509, pkey: *mut EVP_PKEY, md: *const EVP_MD) -> *mut X509_REQ; - 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_verify_cert_error_string(n: c_long) -> *const c_char; pub fn X509_EXTENSION_free(ext: *mut X509_EXTENSION); - pub fn X509_NAME_add_entry_by_txt(x: *mut X509, field: *const c_char, ty: c_int, bytes: *const c_char, len: c_int, loc: c_int, set: c_int) -> c_int; - pub fn X509_NAME_get_index_by_NID(n: *mut X509_NAME, nid: c_int, last_pos: c_int) ->c_int; - 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 X509_NAME_free(x: *mut X509_NAME); + pub fn X509_NAME_add_entry_by_txt(x: *mut X509_NAME, field: *const c_char, ty: c_int, bytes: *const c_uchar, len: c_int, loc: c_int, set: c_int) -> c_int; + pub fn X509_NAME_get_index_by_NID(n: *mut X509_NAME, nid: c_int, last_pos: c_int) -> c_int; - pub fn ASN1_STRING_to_UTF8(out: *mut *mut c_char, s: *mut ASN1_STRING) -> c_int; - pub fn ASN1_STRING_length(x: *mut ASN1_STRING) -> c_int; - pub fn ASN1_STRING_data(x: *mut ASN1_STRING) -> *mut c_uchar; + pub fn X509_NAME_ENTRY_free(x: *mut X509_NAME_ENTRY); - pub fn X509_STORE_CTX_get_current_cert(ct: *mut X509_STORE_CTX) -> *mut X509; + pub fn ASN1_STRING_free(x: *mut ASN1_STRING); + pub fn ASN1_STRING_length(x: *const ASN1_STRING) -> c_int; + + pub fn X509_STORE_CTX_free(ctx: *mut X509_STORE_CTX); + pub fn X509_STORE_CTX_get_current_cert(ctx: *mut X509_STORE_CTX) -> *mut X509; pub fn X509_STORE_CTX_get_error(ctx: *mut X509_STORE_CTX) -> c_int; pub fn X509_STORE_CTX_get_ex_data(ctx: *mut X509_STORE_CTX, idx: c_int) -> *mut c_void; pub fn X509_STORE_CTX_get_error_depth(ctx: *mut X509_STORE_CTX) -> c_int; - pub fn X509V3_EXT_conf_nid(conf: *mut c_void, ctx: *mut X509V3_CTX, ext_nid: c_int, value: *mut c_char) -> *mut X509_EXTENSION; - pub fn X509V3_EXT_conf(conf: *mut c_void, ctx: *mut X509V3_CTX, name: *mut c_char, value: *mut c_char) -> *mut X509_EXTENSION; pub fn X509V3_set_ctx(ctx: *mut X509V3_CTX, issuer: *mut X509, subject: *mut X509, req: *mut X509_REQ, crl: *mut X509_CRL, flags: c_int); pub fn X509_REQ_add_extensions(req: *mut X509_REQ, exts: *mut stack_st_X509_EXTENSION) -> c_int; pub fn X509_REQ_sign(x: *mut X509_REQ, pkey: *mut EVP_PKEY, md: *const EVP_MD) -> c_int; - pub fn d2i_X509(a: *mut *mut X509, pp: *mut *mut c_uchar, length: c_long) -> *mut X509; + #[cfg(not(ossl101))] + pub fn X509_VERIFY_PARAM_free(param: *mut X509_VERIFY_PARAM); + #[cfg(not(ossl101))] + pub fn X509_VERIFY_PARAM_set_hostflags(param: *mut X509_VERIFY_PARAM, flags: c_uint); + #[cfg(not(ossl101))] + pub fn X509_VERIFY_PARAM_set1_host(param: *mut X509_VERIFY_PARAM, + name: *const c_char, + namelen: size_t) -> c_int; + + pub fn d2i_X509(a: *mut *mut X509, pp: *mut *const c_uchar, length: c_long) -> *mut X509; pub fn i2d_X509_bio(b: *mut BIO, x: *mut X509) -> c_int; pub fn i2d_X509_REQ_bio(b: *mut BIO, x: *mut X509_REQ) -> c_int; - pub fn i2d_RSA_PUBKEY(k: *mut RSA, buf: *const *mut u8) -> c_int; - pub fn d2i_RSA_PUBKEY(k: *const *mut RSA, buf: *const *const u8, len: c_uint) -> *mut RSA; - pub fn i2d_RSAPrivateKey(k: *mut RSA, buf: *const *mut u8) -> c_int; - pub fn d2i_RSAPrivateKey(k: *const *mut RSA, buf: *const *const u8, len: c_uint) -> *mut RSA; + pub fn i2d_PUBKEY_bio(b: *mut BIO, x: *mut EVP_PKEY) -> c_int; + + pub fn i2d_RSA_PUBKEY(k: *mut RSA, buf: *mut *mut u8) -> c_int; + pub fn d2i_RSA_PUBKEY(k: *mut *mut RSA, buf: *mut *const u8, len: c_long) -> *mut RSA; + pub fn i2d_RSAPrivateKey(k: *const RSA, buf: *mut *mut u8) -> c_int; + pub fn d2i_RSAPrivateKey(k: *mut *mut RSA, buf: *mut *const u8, len: c_long) -> *mut RSA; pub fn d2i_PKCS12(a: *mut *mut PKCS12, pp: *mut *const u8, length: c_long) -> *mut PKCS12; pub fn PKCS12_parse(p12: *mut PKCS12, @@ -1091,14 +1711,17 @@ extern "C" { -> c_int; pub fn PKCS12_free(p12: *mut PKCS12); - pub fn sk_free(st: *mut _STACK); - pub fn sk_pop_free(st: *mut _STACK, free: Option); - pub fn sk_pop(st: *mut _STACK) -> *mut c_char; - pub fn GENERAL_NAME_free(name: *mut GENERAL_NAME); - pub fn SSLeay() -> c_long; - pub fn SSLeay_version(key: c_int) -> *const c_char; + pub fn HMAC_Init_ex(ctx: *mut HMAC_CTX, + key: *const c_void, + len: c_int, + md: *const EVP_MD, + impl_: *mut ENGINE) -> c_int; + pub fn HMAC_Update(ctx: *mut HMAC_CTX, + data: *const c_uchar, + len: size_t) -> c_int; + pub fn HMAC_Final(ctx: *mut HMAC_CTX, + md: *mut c_uchar, + len: *mut c_uint) -> c_int; } - -pub mod probe; diff --git a/openssl-sys/src/ossl10x.rs b/openssl-sys/src/ossl10x.rs new file mode 100644 index 00000000..2b066446 --- /dev/null +++ b/openssl-sys/src/ossl10x.rs @@ -0,0 +1,607 @@ +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}; +#[cfg(not(ossl101))] +use libc::time_t; + +#[repr(C)] +pub struct stack_st_ASN1_OBJECT { + pub stack: _STACK, +} + +#[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 c_int>, +} + +#[repr(C)] +pub struct BIO_METHOD { + pub type_: c_int, + pub name: *const c_char, + pub bwrite: Option c_int>, + pub bread: Option c_int>, + pub bputs: Option c_int>, + pub bgets: Option c_int>, + pub ctrl: Option c_long>, + pub create: Option c_int>, + pub destroy: Option c_int>, + pub callback_ctrl: Option 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 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 c_int>, + pub do_cipher: Option c_int>, + pub cleanup: Option c_int>, + pub ctx_size: c_int, + pub set_asn1_parameters: Option c_int>, + pub get_asn1_parameters: Option c_int>, + pub ctrl: Option 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, +} + +#[repr(C)] +#[cfg(not(ossl101))] +pub struct X509_VERIFY_PARAM { + pub name: *mut c_char, + pub check_time: time_t, + pub inh_flags: c_ulong, + pub flags: c_ulong, + pub purpose: c_int, + pub trust: c_int, + pub depth: c_int, + pub policies: *mut stack_st_ASN1_OBJECT, + pub id: *mut X509_VERIFY_PARAM_ID, +} + +#[cfg(not(ossl101))] +pub enum X509_VERIFY_PARAM_ID {} + +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> = 0 as *mut Vec>; +static mut GUARDS: *mut Vec>> = 0 as *mut Vec>>; + +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>>> = + 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() {} + +// macros +#[cfg(ossl102)] +pub unsafe fn SSL_CTX_set_ecdh_auto(ctx: *mut SSL_CTX, onoff: c_int) -> c_int { + ::SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, onoff as c_long, ::std::ptr::null_mut()) as c_int +} + +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, + 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); + #[cfg(not(osslconf = "OPENSSL_NO_SSL3_METHOD"))] + 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 X509_STORE_CTX_get_chain(ctx: *mut ::X509_STORE_CTX) -> *mut stack_st_X509; + pub fn X509V3_EXT_nconf_nid(conf: *mut ::CONF, ctx: *mut ::X509V3_CTX, ext_nid: c_int, value: *mut c_char) -> *mut ::X509_EXTENSION; + pub fn X509V3_EXT_nconf(conf: *mut ::CONF, ctx: *mut ::X509V3_CTX, name: *mut c_char, value: *mut c_char) -> *mut ::X509_EXTENSION; + 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 EVP_MD_CTX_create() -> *mut EVP_MD_CTX; + pub fn EVP_MD_CTX_destroy(ctx: *mut EVP_MD_CTX); + + pub fn sk_num(st: *const _STACK) -> c_int; + pub fn sk_value(st: *const _STACK, n: c_int) -> *mut c_void; + pub fn sk_free(st: *mut _STACK); + pub fn sk_pop_free(st: *mut _STACK, free: Option); + 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; +} diff --git a/openssl-sys/src/ossl110.rs b/openssl-sys/src/ossl110.rs new file mode 100644 index 00000000..a2259fc6 --- /dev/null +++ b/openssl-sys/src/ossl110.rs @@ -0,0 +1,155 @@ +use libc::{c_int, c_void, c_char, c_uchar, c_ulong, c_long, c_uint}; + +pub enum BIGNUM {} +pub enum BIO {} +pub enum BIO_METHOD {} +pub enum CRYPTO_EX_DATA {} +pub enum DH {} +pub enum DSA {} +pub enum EVP_CIPHER {} +pub enum EVP_MD_CTX {} +pub enum EVP_PKEY {} +pub enum HMAC_CTX {} +pub enum OPENSSL_STACK {} +pub enum RSA {} +pub enum SSL_CTX {} +pub enum stack_st_ASN1_OBJECT {} +pub enum stack_st_GENERAL_NAME {} +pub enum stack_st_OPENSSL_STRING {} +pub enum stack_st_void {} +pub enum stack_st_X509 {} +pub enum stack_st_X509_ATTRIBUTE {} +pub enum stack_st_X509_EXTENSION {} +pub enum X509 {} +pub enum X509_VERIFY_PARAM {} + +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 const X509_CHECK_FLAG_NEVER_CHECK_SUBJECT: c_uint = 0x20; + +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 X509V3_EXT_nconf_nid(conf: *mut ::CONF, ctx: *mut ::X509V3_CTX, ext_nid: c_int, value: *const c_char) -> *mut ::X509_EXTENSION; + pub fn X509V3_EXT_nconf(conf: *mut ::CONF, ctx: *mut ::X509V3_CTX, name: *const c_char, value: *const c_char) -> *mut ::X509_EXTENSION; + 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 X509_STORE_CTX_get0_chain(ctx: *mut ::X509_STORE_CTX) -> *mut stack_st_X509; + pub fn EVP_MD_CTX_new() -> *mut EVP_MD_CTX; + pub fn EVP_MD_CTX_free(ctx: *mut EVP_MD_CTX); + + pub fn OpenSSL_version_num() -> c_ulong; + pub fn OpenSSL_version(key: c_int) -> *const c_char; + pub fn OPENSSL_sk_free(st: *mut ::OPENSSL_STACK); + pub fn OPENSSL_sk_pop_free(st: *mut ::OPENSSL_STACK, free: Option); + pub fn OPENSSL_sk_pop(st: *mut ::OPENSSL_STACK) -> *mut c_void; +} diff --git a/openssl-sys/src/probe.rs b/openssl-sys/src/probe.rs deleted file mode 100644 index e3711b54..00000000 --- a/openssl-sys/src/probe.rs +++ /dev/null @@ -1,77 +0,0 @@ -use std::env; -use std::fs; -use std::path::PathBuf; - -pub struct ProbeResult { - pub cert_file: Option, - pub cert_dir: Option, -} - -/// 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 { - // 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, val: PathBuf) { - if dst.is_none() && fs::metadata(&val).is_ok() { - *dst = Some(val); - } -} diff --git a/openssl/Cargo.toml b/openssl/Cargo.toml index 3fd46c4b..1417bea7 100644 --- a/openssl/Cargo.toml +++ b/openssl/Cargo.toml @@ -1,51 +1,29 @@ [package] name = "openssl" -version = "0.8.3" +version = "0.9.0" authors = ["Steven Fackler "] license = "Apache-2.0" description = "OpenSSL bindings" repository = "https://github.com/sfackler/rust-openssl" -documentation = "https://sfackler.github.io/rust-openssl/doc/v0.8.3/openssl" +documentation = "https://sfackler.github.io/rust-openssl/doc/v0.9.0/openssl" readme = "../README.md" keywords = ["crypto", "tls", "ssl", "dtls"] 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"] - -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"] +v101 = [] +v102 = [] +v110 = [] [dependencies] bitflags = "0.7" lazy_static = "0.2" libc = "0.2" -openssl-sys = { version = "0.7.17", path = "../openssl-sys" } - -[build-dependencies] -gcc = { version = "0.3", optional = true } +openssl-sys = { version = "0.9", path = "../openssl-sys" } [dev-dependencies] rustc-serialize = "0.3" -net2 = "0.2.16" +tempdir = "0.3" winapi = "0.2" ws2_32-sys = "0.2" diff --git a/openssl/build.rs b/openssl/build.rs index b07c1b3e..7a0c60dc 100644 --- a/openssl/build.rs +++ b/openssl/build.rs @@ -1,28 +1,24 @@ -#[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() {} -} +use std::env; fn main() { - imp::main() + match env::var("DEP_OPENSSL_VERSION") { + Ok(ref v) if v == "101" => { + println!("cargo:rustc-cfg=ossl101"); + println!("cargo:rustc-cfg=ossl10x"); + } + Ok(ref v) if v == "102" => { + println!("cargo:rustc-cfg=ossl102"); + println!("cargo:rustc-cfg=ossl10x"); + } + Ok(ref v) if v == "110" => { + println!("cargo:rustc-cfg=ossl110"); + } + _ => panic!("Unable to detect OpenSSL version"), + } + + if let Ok(vars) = env::var("DEP_OPENSSL_CONF") { + for var in vars.split(",") { + println!("cargo:rustc-cfg=osslconf=\"{}\"", var); + } + } } diff --git a/openssl/src/asn1.rs b/openssl/src/asn1.rs new file mode 100644 index 00000000..c0a23591 --- /dev/null +++ b/openssl/src/asn1.rs @@ -0,0 +1,73 @@ +use ffi; +use libc::c_long; +use std::fmt; +use std::ptr; +use std::slice; +use std::str; + +use {cvt, cvt_p}; +use bio::MemBio; +use crypto::CryptoString; +use error::ErrorStack; +use types::{OpenSslType, OpenSslTypeRef}; + +type_!(Asn1Time, Asn1TimeRef, ffi::ASN1_TIME, ffi::ASN1_TIME_free); + +impl fmt::Display for Asn1TimeRef { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + unsafe { + let mem_bio = try!(MemBio::new()); + try!(cvt(ffi::ASN1_TIME_print(mem_bio.as_ptr(), self.as_ptr()))); + write!(f, "{}", str::from_utf8_unchecked(mem_bio.get_buf())) + } + } +} + +impl Asn1Time { + fn from_period(period: c_long) -> Result { + ffi::init(); + + unsafe { + let handle = try!(cvt_p(ffi::X509_gmtime_adj(ptr::null_mut(), period))); + Ok(Asn1Time::from_ptr(handle)) + } + } + + /// Creates a new time on specified interval in days from now + pub fn days_from_now(days: u32) -> Result { + Asn1Time::from_period(days as c_long * 60 * 60 * 24) + } +} + +type_!(Asn1String, Asn1StringRef, ffi::ASN1_STRING, ffi::ASN1_STRING_free); + +impl Asn1StringRef { + pub fn as_utf8(&self) -> Result { + unsafe { + let mut ptr = ptr::null_mut(); + let len = ffi::ASN1_STRING_to_UTF8(&mut ptr, self.as_ptr()); + if len < 0 { + return Err(ErrorStack::get()); + } + + Ok(CryptoString::from_raw_parts(ptr, len as usize)) + } + } + + pub fn as_slice(&self) -> &[u8] { + unsafe { slice::from_raw_parts(ASN1_STRING_data(self.as_ptr()), self.len()) } + } + + pub fn len(&self) -> usize { + unsafe { ffi::ASN1_STRING_length(self.as_ptr()) as usize } + } +} + +#[cfg(any(ossl101, ossl102))] +use ffi::ASN1_STRING_data; + +#[cfg(ossl110)] +#[allow(bad_style)] +unsafe fn ASN1_STRING_data(s: *mut ffi::ASN1_STRING) -> *mut ::libc::c_uchar { + ffi::ASN1_STRING_get0_data(s) as *mut _ +} diff --git a/openssl/src/asn1/mod.rs b/openssl/src/asn1/mod.rs deleted file mode 100644 index 1eab9f04..00000000 --- a/openssl/src/asn1/mod.rs +++ /dev/null @@ -1,72 +0,0 @@ -use libc::c_long; -use std::{ptr, fmt}; -use std::marker::PhantomData; -use std::ops::Deref; - -use bio::MemBio; -use ffi; -use error::ErrorStack; - -/// Corresponds to the ASN.1 structure Time defined in RFC5280 -pub struct Asn1Time(Asn1TimeRef<'static>); - -impl Asn1Time { - /// Wraps existing ASN1_TIME and takes ownership - pub unsafe fn from_ptr(handle: *mut ffi::ASN1_TIME) -> Asn1Time { - Asn1Time(Asn1TimeRef::from_ptr(handle)) - } - - fn from_period(period: c_long) -> Result { - ffi::init(); - - unsafe { - let handle = try_ssl_null!(ffi::X509_gmtime_adj(ptr::null_mut(), period)); - Ok(Asn1Time::from_ptr(handle)) - } - } - - /// Creates a new time on specified interval in days from now - pub fn days_from_now(days: u32) -> Result { - Asn1Time::from_period(days as c_long * 60 * 60 * 24) - } -} - -impl Deref for Asn1Time { - type Target = Asn1TimeRef<'static>; - - fn deref(&self) -> &Asn1TimeRef<'static> { - &self.0 - } -} - -/// A borrowed Asn1Time -pub struct Asn1TimeRef<'a>(*mut ffi::ASN1_TIME, PhantomData<&'a ()>); - -impl<'a> Asn1TimeRef<'a> { - /// Creates a new `Asn1TimeRef` wrapping the provided handle. - pub unsafe fn from_ptr(handle: *mut ffi::ASN1_TIME) -> Asn1TimeRef<'a> { - Asn1TimeRef(handle, PhantomData) - } - - /// Returns the raw handle - pub fn as_ptr(&self) -> *mut ffi::ASN1_TIME { - self.0 - } -} - -impl<'a> fmt::Display for Asn1TimeRef<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mem_bio = try!(MemBio::new()); - let as_str = unsafe { - try_ssl!(ffi::ASN1_TIME_print(mem_bio.as_ptr(), self.0)); - String::from_utf8_unchecked(mem_bio.get_buf().to_owned()) - }; - write!(f, "{}", as_str) - } -} - -impl Drop for Asn1Time { - fn drop(&mut self) { - unsafe { ffi::ASN1_TIME_free(self.as_ptr()) }; - } -} diff --git a/openssl/src/bio.rs b/openssl/src/bio.rs index 0d82a6c3..5fc4f31f 100644 --- a/openssl/src/bio.rs +++ b/openssl/src/bio.rs @@ -4,6 +4,7 @@ use std::slice; use libc::c_int; use ffi; +use cvt_p; use error::ErrorStack; pub struct MemBioSlice<'a>(*mut ffi::BIO, PhantomData<&'a [u8]>); @@ -21,9 +22,8 @@ impl<'a> MemBioSlice<'a> { ffi::init(); assert!(buf.len() <= c_int::max_value() as usize); - let bio = unsafe { - try_ssl_null!(ffi::BIO_new_mem_buf(buf.as_ptr() as *const _, buf.len() as c_int)) - }; + let bio = + unsafe { try!(cvt_p(BIO_new_mem_buf(buf.as_ptr() as *const _, buf.len() as c_int))) }; Ok(MemBioSlice(bio, PhantomData)) } @@ -47,9 +47,7 @@ impl MemBio { pub fn new() -> Result { ffi::init(); - let bio = unsafe { - try_ssl_null!(ffi::BIO_new(ffi::BIO_s_mem())) - }; + let bio = unsafe { try!(cvt_p(ffi::BIO_new(ffi::BIO_s_mem()))) }; Ok(MemBio(bio)) } @@ -65,3 +63,12 @@ impl MemBio { } } } + +#[cfg(not(ossl101))] +use ffi::BIO_new_mem_buf; + +#[cfg(ossl101)] +#[allow(bad_style)] +unsafe fn BIO_new_mem_buf(buf: *const ::libc::c_void, len: ::libc::c_int) -> *mut ffi::BIO { + ffi::BIO_new_mem_buf(buf as *mut _, len) +} diff --git a/openssl/src/bn.rs b/openssl/src/bn.rs new file mode 100644 index 00000000..d52be884 --- /dev/null +++ b/openssl/src/bn.rs @@ -0,0 +1,843 @@ +use ffi; +use libc::c_int; +use std::cmp::Ordering; +use std::ffi::CString; +use std::{fmt, ptr}; +use std::ops::{Add, Div, Mul, Neg, Rem, Shl, Shr, Sub, Deref}; + +use {cvt, cvt_p, cvt_n}; +use crypto::CryptoString; +use error::ErrorStack; +use types::{OpenSslType, OpenSslTypeRef}; + +/// Options for the most significant bits of a randomly generated `BigNum`. +pub struct MsbOption(c_int); + +/// The most significant bit of the number may be 0. +pub const MSB_MAYBE_ZERO: MsbOption = MsbOption(-1); + +/// The most significant bit of the number must be 1. +pub const MSB_ONE: MsbOption = MsbOption(0); + +/// The most significant two bits of the number must be 1. +/// +/// The number of bits in the product of two such numbers will always be exactly twice the number +/// of bits in the original numbers. +pub const TWO_MSB_ONE: MsbOption = MsbOption(1); + +type_!(BigNumContext, BigNumContextRef, ffi::BN_CTX, ffi::BN_CTX_free); + +impl BigNumContext { + /// Returns a new `BigNumContext`. + pub fn new() -> Result { + unsafe { cvt_p(ffi::BN_CTX_new()).map(BigNumContext) } + } +} + +impl BigNumRef { + /// Erases the memory used by this `BigNum`, resetting its value to 0. + /// + /// This can be used to destroy sensitive data such as keys when they are no longer needed. + pub fn clear(&mut self) { + unsafe { ffi::BN_clear(self.as_ptr()) } + } + + /// Adds a `u32` to `self`. + pub fn add_word(&mut self, w: u32) -> Result<(), ErrorStack> { + unsafe { cvt(ffi::BN_add_word(self.as_ptr(), w as ffi::BN_ULONG)).map(|_| ()) } + } + + /// Subtracts a `u32` from `self`. + pub fn sub_word(&mut self, w: u32) -> Result<(), ErrorStack> { + unsafe { cvt(ffi::BN_sub_word(self.as_ptr(), w as ffi::BN_ULONG)).map(|_| ()) } + } + + /// Multiplies a `u32` by `self`. + pub fn mul_word(&mut self, w: u32) -> Result<(), ErrorStack> { + unsafe { cvt(ffi::BN_mul_word(self.as_ptr(), w as ffi::BN_ULONG)).map(|_| ()) } + } + + /// Divides `self` by a `u32`, returning the remainder. + pub fn div_word(&mut self, w: u32) -> Result { + unsafe { + let r = ffi::BN_div_word(self.as_ptr(), w.into()); + if r == ffi::BN_ULONG::max_value() { + Err(ErrorStack::get()) + } else { + Ok(r.into()) + } + } + } + + /// Returns the result of `self` modulo `w`. + pub fn mod_word(&self, w: u32) -> Result { + unsafe { + let r = ffi::BN_mod_word(self.as_ptr(), w.into()); + if r == ffi::BN_ULONG::max_value() { + Err(ErrorStack::get()) + } else { + Ok(r.into()) + } + } + } + + /// Places a cryptographically-secure pseudo-random number nonnegative + /// number less than `self` in `rnd`. + pub fn rand_range(&self, rnd: &mut BigNumRef) -> Result<(), ErrorStack> { + unsafe { cvt(ffi::BN_rand_range(self.as_ptr(), rnd.as_ptr())).map(|_| ()) } + } + + /// The cryptographically weak counterpart to `rand_in_range`. + pub fn pseudo_rand_range(&self, rnd: &mut BigNumRef) -> Result<(), ErrorStack> { + unsafe { cvt(ffi::BN_pseudo_rand_range(self.as_ptr(), rnd.as_ptr())).map(|_| ()) } + } + + /// Sets bit `n`. Equivalent to `self |= (1 << n)`. + /// + /// When setting a bit outside of `self`, it is expanded. + pub fn set_bit(&mut self, n: i32) -> Result<(), ErrorStack> { + unsafe { cvt(ffi::BN_set_bit(self.as_ptr(), n.into())).map(|_| ()) } + } + + /// Clears bit `n`, setting it to 0. Equivalent to `self &= ~(1 << n)`. + /// + /// When clearing a bit outside of `self`, an error is returned. + pub fn clear_bit(&mut self, n: i32) -> Result<(), ErrorStack> { + unsafe { cvt(ffi::BN_clear_bit(self.as_ptr(), n.into())).map(|_| ()) } + } + + /// Returns `true` if the `n`th bit of `self` is set to 1, `false` otherwise. + pub fn is_bit_set(&self, n: i32) -> bool { + unsafe { ffi::BN_is_bit_set(self.as_ptr(), n.into()) == 1 } + } + + /// Truncates `self` to the lowest `n` bits. + /// + /// An error occurs if `self` is already shorter than `n` bits. + pub fn mask_bits(&mut self, n: i32) -> Result<(), ErrorStack> { + unsafe { cvt(ffi::BN_mask_bits(self.as_ptr(), n.into())).map(|_| ()) } + } + + /// Places `a << 1` in `self`. + pub fn lshift1(&mut self, a: &BigNumRef) -> Result<(), ErrorStack> { + unsafe { cvt(ffi::BN_lshift1(self.as_ptr(), a.as_ptr())).map(|_| ()) } + } + + /// Places `a >> 1` in `self`. + pub fn rshift1(&mut self, a: &BigNumRef) -> Result<(), ErrorStack> { + unsafe { cvt(ffi::BN_rshift1(self.as_ptr(), a.as_ptr())).map(|_| ()) } + } + + /// Places `a + b` in `self`. + pub fn checked_add(&mut self, a: &BigNumRef, b: &BigNumRef) -> Result<(), ErrorStack> { + unsafe { cvt(ffi::BN_add(self.as_ptr(), a.as_ptr(), b.as_ptr())).map(|_| ()) } + } + + /// Places `a - b` in `self`. + pub fn checked_sub(&mut self, a: &BigNumRef, b: &BigNumRef) -> Result<(), ErrorStack> { + unsafe { cvt(ffi::BN_sub(self.as_ptr(), a.as_ptr(), b.as_ptr())).map(|_| ()) } + } + + /// Places `a << n` in `self`. + pub fn lshift(&mut self, a: &BigNumRef, n: i32) -> Result<(), ErrorStack> { + unsafe { cvt(ffi::BN_lshift(self.as_ptr(), a.as_ptr(), n.into())).map(|_| ()) } + } + + /// Places `a >> n` in `self`. + pub fn rshift(&mut self, a: &BigNumRef, n: i32) -> Result<(), ErrorStack> { + unsafe { cvt(ffi::BN_rshift(self.as_ptr(), a.as_ptr(), n.into())).map(|_| ()) } + } + + pub fn to_owned(&self) -> Result { + unsafe { cvt_p(ffi::BN_dup(self.as_ptr())).map(|b| BigNum::from_ptr(b)) } + } + + /// Sets the sign of `self`. + pub fn set_negative(&mut self, negative: bool) { + unsafe { ffi::BN_set_negative(self.as_ptr(), negative as c_int) } + } + + /// Compare the absolute values of `self` and `oth`. + /// + /// ``` + /// # use openssl::bn::BigNum; + /// # use std::cmp::Ordering; + /// let s = -BigNum::from_u32(8).unwrap(); + /// let o = BigNum::from_u32(8).unwrap(); + /// + /// assert_eq!(s.ucmp(&o), Ordering::Equal); + /// ``` + pub fn ucmp(&self, oth: &BigNumRef) -> Ordering { + unsafe { ffi::BN_ucmp(self.as_ptr(), oth.as_ptr()).cmp(&0) } + } + + 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 } + } + + /// Returns the size of `self` in bytes. + pub fn num_bytes(&self) -> i32 { + (self.num_bits() + 7) / 8 + } + + /// Generates a cryptographically strong pseudo-random `BigNum`, placing it in `self`. + /// + /// # Parameters + /// + /// * `bits`: Length of the number in bits. + /// * `msb`: The desired properties of the number. + /// * `odd`: If `true`, the generated number will be odd. + pub fn rand(&mut self, bits: i32, msb: MsbOption, odd: bool) -> Result<(), ErrorStack> { + unsafe { cvt(ffi::BN_rand(self.as_ptr(), bits.into(), msb.0, odd as c_int)).map(|_| ()) } + } + + /// The cryptographically weak counterpart to `rand`. + pub fn pseudo_rand(&mut self, bits: i32, msb: MsbOption, odd: bool) -> Result<(), ErrorStack> { + unsafe { + cvt(ffi::BN_pseudo_rand(self.as_ptr(), bits.into(), msb.0, odd as c_int)).map(|_| ()) + } + } + + /// Generates a prime number, placing it in `self`. + /// + /// # Parameters + /// + /// * `bits`: The length of the prime in bits (lower bound). + /// * `safe`: If true, returns a "safe" prime `p` so that `(p-1)/2` is also prime. + /// * `add`/`rem`: If `add` is set to `Some(add)`, `p % add == rem` will hold, where `p` is the + /// generated prime and `rem` is `1` if not specified (`None`). + pub fn generate_prime(&mut self, + bits: i32, + safe: bool, + add: Option<&BigNumRef>, + rem: Option<&BigNumRef>) + -> Result<(), ErrorStack> { + unsafe { + cvt(ffi::BN_generate_prime_ex(self.as_ptr(), + bits as c_int, + safe as c_int, + add.map(|n| n.as_ptr()).unwrap_or(ptr::null_mut()), + rem.map(|n| n.as_ptr()).unwrap_or(ptr::null_mut()), + ptr::null_mut())) + .map(|_| ()) + } + } + + /// Places the result of `a * b` in `self`. + pub fn checked_mul(&mut self, + a: &BigNumRef, + b: &BigNumRef, + ctx: &mut BigNumContextRef) + -> Result<(), ErrorStack> { + unsafe { cvt(ffi::BN_mul(self.as_ptr(), a.as_ptr(), b.as_ptr(), ctx.as_ptr())).map(|_| ()) } + } + + /// Places the result of `a / b` in `self`. + pub fn checked_div(&mut self, + a: &BigNumRef, + b: &BigNumRef, + ctx: &mut BigNumContextRef) + -> Result<(), ErrorStack> { + unsafe { + cvt(ffi::BN_div(self.as_ptr(), + ptr::null_mut(), + a.as_ptr(), + b.as_ptr(), + ctx.as_ptr())) + .map(|_| ()) + } + } + + /// Places the result of `a % b` in `self`. + pub fn checked_rem(&mut self, + a: &BigNumRef, + b: &BigNumRef, + ctx: &mut BigNumContextRef) + -> Result<(), ErrorStack> { + unsafe { + cvt(ffi::BN_div(ptr::null_mut(), + self.as_ptr(), + a.as_ptr(), + b.as_ptr(), + ctx.as_ptr())) + .map(|_| ()) + } + } + + /// Places the result of `a / b` in `self` and `a % b` in `rem`. + pub fn div_rem(&mut self, + rem: &mut BigNumRef, + a: &BigNumRef, + b: &BigNumRef, + ctx: &mut BigNumContextRef) + -> Result<(), ErrorStack> { + unsafe { + cvt(ffi::BN_div(self.as_ptr(), + rem.as_ptr(), + a.as_ptr(), + b.as_ptr(), + ctx.as_ptr())) + .map(|_| ()) + } + } + + /// Places the result of `a²` in `self`. + pub fn sqr(&mut self, a: &BigNumRef, ctx: &mut BigNumContextRef) -> Result<(), ErrorStack> { + unsafe { cvt(ffi::BN_sqr(self.as_ptr(), a.as_ptr(), ctx.as_ptr())).map(|_| ()) } + } + + /// Places the result of `a mod m` in `self`. + pub fn nnmod(&mut self, + a: &BigNumRef, + m: &BigNumRef, + ctx: &mut BigNumContextRef) + -> Result<(), ErrorStack> { + unsafe { + cvt(ffi::BN_nnmod(self.as_ptr(), a.as_ptr(), m.as_ptr(), ctx.as_ptr())).map(|_| ()) + } + } + + /// Places the result of `(a + b) mod m` in `self`. + pub fn mod_add(&mut self, + a: &BigNumRef, + b: &BigNumRef, + m: &BigNumRef, + ctx: &mut BigNumContextRef) + -> Result<(), ErrorStack> { + unsafe { + cvt(ffi::BN_mod_add(self.as_ptr(), a.as_ptr(), b.as_ptr(), m.as_ptr(), ctx.as_ptr())) + .map(|_| ()) + } + } + + /// Places the result of `(a - b) mod m` in `self`. + pub fn mod_sub(&mut self, + a: &BigNumRef, + b: &BigNumRef, + m: &BigNumRef, + ctx: &mut BigNumContextRef) + -> Result<(), ErrorStack> { + unsafe { + cvt(ffi::BN_mod_sub(self.as_ptr(), a.as_ptr(), b.as_ptr(), m.as_ptr(), ctx.as_ptr())) + .map(|_| ()) + } + } + + /// Places the result of `(a * b) mod m` in `self`. + pub fn mod_mul(&mut self, + a: &BigNumRef, + b: &BigNumRef, + m: &BigNumRef, + ctx: &mut BigNumContextRef) + -> Result<(), ErrorStack> { + unsafe { + cvt(ffi::BN_mod_mul(self.as_ptr(), a.as_ptr(), b.as_ptr(), m.as_ptr(), ctx.as_ptr())) + .map(|_| ()) + } + } + + /// Places the result of `a² mod m` in `self`. + pub fn mod_sqr(&mut self, + a: &BigNumRef, + m: &BigNumRef, + ctx: &mut BigNumContextRef) + -> Result<(), ErrorStack> { + unsafe { + cvt(ffi::BN_mod_sqr(self.as_ptr(), a.as_ptr(), m.as_ptr(), ctx.as_ptr())).map(|_| ()) + } + } + + /// Places the result of `a^p` in `self`. + pub fn exp(&mut self, + a: &BigNumRef, + p: &BigNumRef, + ctx: &mut BigNumContextRef) + -> Result<(), ErrorStack> { + unsafe { cvt(ffi::BN_exp(self.as_ptr(), a.as_ptr(), p.as_ptr(), ctx.as_ptr())).map(|_| ()) } + } + + /// Places the result of `a^p mod m` in `self`. + pub fn mod_exp(&mut self, + a: &BigNumRef, + p: &BigNumRef, + m: &BigNumRef, + ctx: &mut BigNumContextRef) + -> Result<(), ErrorStack> { + unsafe { + cvt(ffi::BN_mod_exp(self.as_ptr(), a.as_ptr(), p.as_ptr(), m.as_ptr(), ctx.as_ptr())) + .map(|_| ()) + } + } + + /// Places the inverse of `a` modulo `n` in `self`. + pub fn mod_inverse(&mut self, + a: &BigNumRef, + n: &BigNumRef, + ctx: &mut BigNumContextRef) + -> Result<(), ErrorStack> { + unsafe { + cvt_p(ffi::BN_mod_inverse(self.as_ptr(), a.as_ptr(), n.as_ptr(), ctx.as_ptr())) + .map(|_| ()) + } + } + + /// Places the greatest common denominator of `a` and `b` in `self`. + pub fn gcd(&mut self, + a: &BigNumRef, + b: &BigNumRef, + ctx: &mut BigNumContextRef) + -> Result<(), ErrorStack> { + unsafe { cvt(ffi::BN_gcd(self.as_ptr(), a.as_ptr(), b.as_ptr(), ctx.as_ptr())).map(|_| ()) } + } + + /// Checks whether `self` is prime. + /// + /// Performs a Miller-Rabin probabilistic primality test with `checks` iterations. + /// + /// Returns `true` if `self` is prime with an error probability of less than `0.25 ^ checks`. + pub fn is_prime(&self, checks: i32, ctx: &mut BigNumContextRef) -> Result { + unsafe { + cvt_n(ffi::BN_is_prime_ex(self.as_ptr(), checks.into(), ctx.as_ptr(), ptr::null_mut())) + .map(|r| r != 0) + } + } + + /// Checks whether `self` is prime with optional trial division. + /// + /// If `do_trial_division` is `true`, first performs trial division by a number of small primes. + /// Then, like `is_prime`, performs a Miller-Rabin probabilistic primality test with `checks` + /// iterations. + /// + /// # Return Value + /// + /// Returns `true` if `self` is prime with an error probability of less than `0.25 ^ checks`. + pub fn is_prime_fasttest(&self, + checks: i32, + ctx: &mut BigNumContextRef, + do_trial_division: bool) + -> Result { + unsafe { + cvt_n(ffi::BN_is_prime_fasttest_ex(self.as_ptr(), + checks.into(), + ctx.as_ptr(), + do_trial_division as c_int, + ptr::null_mut())) + .map(|r| r != 0) + } + } + + /// Returns a big-endian byte vector representation of the absolute value of `self`. + /// + /// `self` can be recreated by using `new_from_slice`. + /// + /// ``` + /// # use openssl::bn::BigNum; + /// let s = -BigNum::from_u32(4543).unwrap(); + /// let r = BigNum::from_u32(4543).unwrap(); + /// + /// let s_vec = s.to_vec(); + /// assert_eq!(BigNum::from_slice(&s_vec).unwrap(), r); + /// ``` + pub fn to_vec(&self) -> Vec { + let size = self.num_bytes() as usize; + let mut v = Vec::with_capacity(size); + unsafe { + ffi::BN_bn2bin(self.as_ptr(), v.as_mut_ptr()); + v.set_len(size); + } + v + } + + /// Returns a decimal string representation of `self`. + /// + /// ``` + /// # use openssl::bn::BigNum; + /// let s = -BigNum::from_u32(12345).unwrap(); + /// + /// assert_eq!(&*s.to_dec_str().unwrap(), "-12345"); + /// ``` + pub fn to_dec_str(&self) -> Result { + unsafe { + let buf = try!(cvt_p(ffi::BN_bn2dec(self.as_ptr()))); + Ok(CryptoString::from_null_terminated(buf)) + } + } + + /// Returns a hexadecimal string representation of `self`. + /// + /// ``` + /// # use openssl::bn::BigNum; + /// let s = -BigNum::from_u32(0x99ff).unwrap(); + /// + /// assert_eq!(&*s.to_hex_str().unwrap(), "-99FF"); + /// ``` + pub fn to_hex_str(&self) -> Result { + unsafe { + let buf = try!(cvt_p(ffi::BN_bn2hex(self.as_ptr()))); + Ok(CryptoString::from_null_terminated(buf)) + } + } +} + +type_!(BigNum, BigNumRef, ffi::BIGNUM, ffi::BN_free); + +impl BigNum { + /// Creates a new `BigNum` with the value 0. + pub fn new() -> Result { + unsafe { + ffi::init(); + let v = try!(cvt_p(ffi::BN_new())); + Ok(BigNum::from_ptr(v)) + } + } + + /// Creates a new `BigNum` with the given value. + pub fn from_u32(n: u32) -> Result { + BigNum::new().and_then(|v| unsafe { + cvt(ffi::BN_set_word(v.as_ptr(), n as ffi::BN_ULONG)).map(|_| v) + }) + } + + /// Creates a `BigNum` from a decimal string. + pub fn from_dec_str(s: &str) -> Result { + unsafe { + let c_str = CString::new(s.as_bytes()).unwrap(); + let mut bn = ptr::null_mut(); + try!(cvt(ffi::BN_dec2bn(&mut bn, c_str.as_ptr() as *const _))); + Ok(BigNum::from_ptr(bn)) + } + } + + /// Creates a `BigNum` from a hexadecimal string. + pub fn from_hex_str(s: &str) -> Result { + unsafe { + let c_str = CString::new(s.as_bytes()).unwrap(); + let mut bn = ptr::null_mut(); + try!(cvt(ffi::BN_hex2bn(&mut bn, c_str.as_ptr() as *const _))); + Ok(BigNum::from_ptr(bn)) + } + } + + /// Creates a new `BigNum` from an unsigned, big-endian encoded number of arbitrary length. + /// + /// ``` + /// # use openssl::bn::BigNum; + /// let bignum = BigNum::from_slice(&[0x12, 0x00, 0x34]).unwrap(); + /// + /// assert_eq!(bignum, BigNum::from_u32(0x120034).unwrap()); + /// ``` + pub fn from_slice(n: &[u8]) -> Result { + unsafe { + assert!(n.len() <= c_int::max_value() as usize); + cvt_p(ffi::BN_bin2bn(n.as_ptr(), n.len() as c_int, ptr::null_mut())) + .map(|p| BigNum::from_ptr(p)) + } + } +} + +impl AsRef for BigNum { + fn as_ref(&self) -> &BigNumRef { + self.deref() + } +} + +impl fmt::Debug for BigNumRef { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.to_dec_str() { + Ok(s) => f.write_str(&s), + Err(e) => Err(e.into()), + } + } +} + +impl fmt::Debug for BigNum { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.to_dec_str() { + Ok(s) => f.write_str(&s), + Err(e) => Err(e.into()), + } + } +} + +impl fmt::Display for BigNumRef { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.to_dec_str() { + Ok(s) => f.write_str(&s), + Err(e) => Err(e.into()), + } + } +} + +impl fmt::Display for BigNum { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.to_dec_str() { + Ok(s) => f.write_str(&s), + Err(e) => Err(e.into()), + } + } +} + +impl PartialEq for BigNumRef { + fn eq(&self, oth: &BigNumRef) -> bool { + self.cmp(oth) == Ordering::Equal + } +} + +impl PartialEq for BigNumRef { + fn eq(&self, oth: &BigNum) -> bool { + self.eq(oth.deref()) + } +} + +impl Eq for BigNumRef {} + +impl PartialEq for BigNum { + fn eq(&self, oth: &BigNum) -> bool { + self.deref().eq(oth) + } +} + +impl PartialEq for BigNum { + fn eq(&self, oth: &BigNumRef) -> bool { + self.deref().eq(oth) + } +} + +impl Eq for BigNum {} + +impl PartialOrd for BigNumRef { + fn partial_cmp(&self, oth: &BigNumRef) -> Option { + Some(self.cmp(oth)) + } +} + +impl PartialOrd for BigNumRef { + fn partial_cmp(&self, oth: &BigNum) -> Option { + Some(self.cmp(oth.deref())) + } +} + +impl Ord for BigNumRef { + fn cmp(&self, oth: &BigNumRef) -> Ordering { + unsafe { ffi::BN_cmp(self.as_ptr(), oth.as_ptr()).cmp(&0) } + } +} + +impl PartialOrd for BigNum { + fn partial_cmp(&self, oth: &BigNum) -> Option { + self.deref().partial_cmp(oth.deref()) + } +} + +impl PartialOrd for BigNum { + fn partial_cmp(&self, oth: &BigNumRef) -> Option { + self.deref().partial_cmp(oth) + } +} + +impl Ord for BigNum { + fn cmp(&self, oth: &BigNum) -> Ordering { + self.deref().cmp(oth.deref()) + } +} + +macro_rules! delegate { + ($t:ident, $m:ident) => { + impl<'a, 'b> $t<&'b BigNum> for &'a BigNumRef { + type Output = BigNum; + + fn $m(self, oth: &BigNum) -> BigNum { + $t::$m(self, oth.deref()) + } + } + + impl<'a, 'b> $t<&'b BigNumRef> for &'a BigNum { + type Output = BigNum; + + fn $m(self, oth: &BigNumRef) -> BigNum { + $t::$m(self.deref(), oth) + } + } + + impl<'a, 'b> $t<&'b BigNum> for &'a BigNum { + type Output = BigNum; + + fn $m(self, oth: &BigNum) -> BigNum { + $t::$m(self.deref(), oth.deref()) + } + } + } +} + +impl<'a, 'b> Add<&'b BigNumRef> for &'a BigNumRef { + type Output = BigNum; + + fn add(self, oth: &BigNumRef) -> BigNum { + let mut r = BigNum::new().unwrap(); + r.checked_add(self, oth).unwrap(); + r + } +} + +delegate!(Add, add); + +impl<'a, 'b> Sub<&'b BigNumRef> for &'a BigNumRef { + type Output = BigNum; + + fn sub(self, oth: &BigNumRef) -> BigNum { + let mut r = BigNum::new().unwrap(); + r.checked_sub(self, oth).unwrap(); + r + } +} + +delegate!(Sub, sub); + +impl<'a, 'b> Mul<&'b BigNumRef> for &'a BigNumRef { + type Output = BigNum; + + fn mul(self, oth: &BigNumRef) -> BigNum { + let mut ctx = BigNumContext::new().unwrap(); + let mut r = BigNum::new().unwrap(); + r.checked_mul(self, oth, &mut ctx).unwrap(); + r + } +} + +delegate!(Mul, mul); + +impl<'a, 'b> Div<&'b BigNumRef> for &'a BigNumRef { + type Output = BigNum; + + fn div(self, oth: &'b BigNumRef) -> BigNum { + let mut ctx = BigNumContext::new().unwrap(); + let mut r = BigNum::new().unwrap(); + r.checked_div(self, oth, &mut ctx).unwrap(); + r + } +} + +delegate!(Div, div); + +impl<'a, 'b> Rem<&'b BigNumRef> for &'a BigNumRef { + type Output = BigNum; + + fn rem(self, oth: &'b BigNumRef) -> BigNum { + let mut ctx = BigNumContext::new().unwrap(); + let mut r = BigNum::new().unwrap(); + r.checked_rem(self, oth, &mut ctx).unwrap(); + r + } +} + +delegate!(Rem, rem); + +impl<'a> Shl for &'a BigNumRef { + type Output = BigNum; + + fn shl(self, n: i32) -> BigNum { + let mut r = BigNum::new().unwrap(); + r.lshift(self, n).unwrap(); + r + } +} + +impl<'a> Shl for &'a BigNum { + type Output = BigNum; + + fn shl(self, n: i32) -> BigNum { + self.deref().shl(n) + } +} + +impl<'a> Shr for &'a BigNumRef { + type Output = BigNum; + + fn shr(self, n: i32) -> BigNum { + let mut r = BigNum::new().unwrap(); + r.rshift(self, n).unwrap(); + r + } +} + +impl<'a> Shr for &'a BigNum { + type Output = BigNum; + + fn shr(self, n: i32) -> BigNum { + self.deref().shl(n) + } +} + +impl<'a> Neg for &'a BigNumRef { + type Output = BigNum; + + fn neg(self) -> BigNum { + self.to_owned().unwrap().neg() + } +} + +impl<'a> Neg for &'a BigNum { + type Output = BigNum; + + fn neg(self) -> BigNum { + self.deref().neg() + } +} + +impl Neg for BigNum { + type Output = BigNum; + + fn neg(mut self) -> BigNum { + let negative = self.is_negative(); + self.set_negative(!negative); + self + } +} + +#[cfg(test)] +mod tests { + use bn::{BigNumContext, BigNum}; + + #[test] + fn test_to_from_slice() { + let v0 = BigNum::from_u32(10203004).unwrap(); + let vec = v0.to_vec(); + let v1 = BigNum::from_slice(&vec).unwrap(); + + assert!(v0 == v1); + } + + #[test] + fn test_negation() { + let a = BigNum::from_u32(909829283).unwrap(); + + assert!(!a.is_negative()); + assert!((-a).is_negative()); + } + + #[test] + fn test_prime_numbers() { + let a = BigNum::from_u32(19029017).unwrap(); + let mut p = BigNum::new().unwrap(); + p.generate_prime(128, true, None, Some(&a)).unwrap(); + + let mut ctx = BigNumContext::new().unwrap(); + assert!(p.is_prime(100, &mut ctx).unwrap()); + assert!(p.is_prime_fasttest(100, &mut ctx, true).unwrap()); + } +} diff --git a/openssl/src/bn/mod.rs b/openssl/src/bn/mod.rs deleted file mode 100644 index de9d0d2a..00000000 --- a/openssl/src/bn/mod.rs +++ /dev/null @@ -1,1023 +0,0 @@ -use libc::{c_int, c_ulong, c_void}; -use std::ffi::{CStr, CString}; -use std::cmp::Ordering; -use std::{fmt, ptr}; -use std::marker::PhantomData; -use std::ops::{Add, Div, Mul, Neg, Rem, Shl, Shr, Sub, Deref, DerefMut}; - -use ffi; -use error::ErrorStack; - -/// Specifies the desired properties of a randomly generated `BigNum`. -#[derive(Copy, Clone)] -#[repr(C)] -pub enum RNGProperty { - /// The most significant bit of the number is allowed to be 0. - MsbMaybeZero = -1, - /// The MSB should be set to 1. - MsbOne = 0, - /// The two most significant bits of the number will be set to 1, so that the product of two - /// such random numbers will always have `2 * bits` length. - TwoMsbOne = 1, -} - -macro_rules! with_ctx( - ($name:ident, $action:block) => ({ - let $name = ffi::BN_CTX_new(); - if ($name).is_null() { - Err(ErrorStack::get()) - } else { - let r = $action; - ffi::BN_CTX_free($name); - r - } - }); -); - -macro_rules! with_bn( - ($name:ident, $action:block) => ({ - let tmp = BigNum::new(); - match tmp { - Ok($name) => { - if $action { - Ok($name) - } else { - Err(ErrorStack::get()) - } - }, - Err(err) => Err(err), - } - }); -); - -macro_rules! with_bn_in_ctx( - ($name:ident, $ctx_name:ident, $action:block) => ({ - let tmp = BigNum::new(); - match tmp { - Ok($name) => { - let $ctx_name = ffi::BN_CTX_new(); - if ($ctx_name).is_null() { - Err(ErrorStack::get()) - } else { - let r = - if $action { - Ok($name) - } else { - Err(ErrorStack::get()) - }; - ffi::BN_CTX_free($ctx_name); - r - } - }, - Err(err) => Err(err), - } - }); -); - -/// A borrowed, signed, arbitrary-precision integer. -#[derive(Copy, Clone)] -pub struct BigNumRef<'a>(*mut ffi::BIGNUM, PhantomData<&'a ()>); - - -impl<'a> BigNumRef<'a> { - pub unsafe fn from_ptr(handle: *mut ffi::BIGNUM) -> BigNumRef<'a> { - BigNumRef(handle, PhantomData) - } - - /// Returns the square of `self`. - /// - /// ``` - /// # use openssl::bn::BigNum; - /// let ref n = BigNum::new_from(10).unwrap(); - /// let squared = BigNum::new_from(100).unwrap(); - /// - /// assert_eq!(n.checked_sqr().unwrap(), squared); - /// assert_eq!(n * n, squared); - /// ``` - pub fn checked_sqr(&self) -> Result { - unsafe { - with_bn_in_ctx!(r, ctx, { - ffi::BN_sqr(r.as_ptr(), self.as_ptr(), ctx) == 1 - }) - } - } - - /// Returns the unsigned remainder of the division `self / n`. - pub fn checked_nnmod(&self, n: &BigNumRef) -> Result { - unsafe { - with_bn_in_ctx!(r, ctx, { - ffi::BN_nnmod(r.as_ptr(), self.as_ptr(), n.as_ptr(), ctx) == 1 - }) - } - } - - /// Equivalent to `(self + a) mod n`. - /// - /// ``` - /// # use openssl::bn::BigNum; - /// let ref s = BigNum::new_from(10).unwrap(); - /// let ref a = BigNum::new_from(20).unwrap(); - /// let ref n = BigNum::new_from(29).unwrap(); - /// let result = BigNum::new_from(1).unwrap(); - /// - /// assert_eq!(s.checked_mod_add(a, n).unwrap(), result); - /// ``` - pub fn checked_mod_add(&self, a: &BigNumRef, n: &BigNumRef) -> Result { - unsafe { - with_bn_in_ctx!(r, ctx, { - ffi::BN_mod_add(r.as_ptr(), self.as_ptr(), a.as_ptr(), n.as_ptr(), ctx) == 1 - }) - } - } - - /// Equivalent to `(self - a) mod n`. - pub fn checked_mod_sub(&self, a: &BigNumRef, n: &BigNumRef) -> Result { - unsafe { - with_bn_in_ctx!(r, ctx, { - ffi::BN_mod_sub(r.as_ptr(), self.as_ptr(), a.as_ptr(), n.as_ptr(), ctx) == 1 - }) - } - } - - /// Equivalent to `(self * a) mod n`. - pub fn checked_mod_mul(&self, a: &BigNumRef, n: &BigNumRef) -> Result { - unsafe { - with_bn_in_ctx!(r, ctx, { - ffi::BN_mod_mul(r.as_ptr(), self.as_ptr(), a.as_ptr(), n.as_ptr(), ctx) == 1 - }) - } - } - - /// Equivalent to `self² mod n`. - pub fn checked_mod_sqr(&self, n: &BigNumRef) -> Result { - unsafe { - with_bn_in_ctx!(r, ctx, { - ffi::BN_mod_sqr(r.as_ptr(), self.as_ptr(), n.as_ptr(), ctx) == 1 - }) - } - } - - /// Raises `self` to the `p`th power. - pub fn checked_exp(&self, p: &BigNumRef) -> Result { - unsafe { - with_bn_in_ctx!(r, ctx, { - ffi::BN_exp(r.as_ptr(), self.as_ptr(), p.as_ptr(), ctx) == 1 - }) - } - } - - /// Equivalent to `self.checked_exp(p) mod n`. - pub fn checked_mod_exp(&self, p: &BigNumRef, n: &BigNumRef) -> Result { - unsafe { - with_bn_in_ctx!(r, ctx, { - ffi::BN_mod_exp(r.as_ptr(), self.as_ptr(), p.as_ptr(), n.as_ptr(), ctx) == 1 - }) - } - } - - /// Calculates the modular multiplicative inverse of `self` modulo `n`, that is, an integer `r` - /// such that `(self * r) % n == 1`. - pub fn checked_mod_inv(&self, n: &BigNumRef) -> Result { - unsafe { - with_bn_in_ctx!(r, ctx, { - !ffi::BN_mod_inverse(r.as_ptr(), self.as_ptr(), n.as_ptr(), ctx).is_null() - }) - } - } - - /// 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> { - unsafe { - if ffi::BN_add_word(self.as_ptr(), w) == 1 { - Ok(()) - } else { - Err(ErrorStack::get()) - } - } - } - - pub fn sub_word(&mut self, w: c_ulong) -> Result<(), ErrorStack> { - unsafe { - if ffi::BN_sub_word(self.as_ptr(), w) == 1 { - Ok(()) - } else { - Err(ErrorStack::get()) - } - } - } - - pub fn mul_word(&mut self, w: c_ulong) -> Result<(), ErrorStack> { - unsafe { - if ffi::BN_mul_word(self.as_ptr(), w) == 1 { - Ok(()) - } else { - Err(ErrorStack::get()) - } - } - } - - pub fn div_word(&mut self, w: c_ulong) -> Result { - unsafe { - let result = ffi::BN_div_word(self.as_ptr(), w); - if result != !0 as c_ulong { - Ok(result) - } else { - Err(ErrorStack::get()) - } - } - } - - pub fn mod_word(&self, w: c_ulong) -> Result { - unsafe { - let result = ffi::BN_mod_word(self.as_ptr(), w); - if result != !0 as c_ulong { - Ok(result) - } else { - Err(ErrorStack::get()) - } - } - } - - /// Computes the greatest common denominator of `self` and `a`. - pub fn checked_gcd(&self, a: &BigNumRef) -> Result { - unsafe { - with_bn_in_ctx!(r, ctx, { - ffi::BN_gcd(r.as_ptr(), self.as_ptr(), a.as_ptr(), ctx) == 1 - }) - } - } - - /// Checks whether `self` is prime. - /// - /// Performs a Miller-Rabin probabilistic primality test with `checks` iterations. - /// - /// # Return Value - /// - /// Returns `true` if `self` is prime with an error probability of less than `0.25 ^ checks`. - pub fn is_prime(&self, checks: i32) -> Result { - unsafe { - with_ctx!(ctx, { - Ok(ffi::BN_is_prime_ex(self.as_ptr(), checks as c_int, ctx, ptr::null()) == 1) - }) - } - } - - /// Checks whether `self` is prime with optional trial division. - /// - /// If `do_trial_division` is `true`, first performs trial division by a number of small primes. - /// Then, like `is_prime`, performs a Miller-Rabin probabilistic primality test with `checks` - /// iterations. - /// - /// # Return Value - /// - /// Returns `true` if `self` is prime with an error probability of less than `0.25 ^ checks`. - pub fn is_prime_fast(&self, checks: i32, do_trial_division: bool) -> Result { - unsafe { - with_ctx!(ctx, { - Ok(ffi::BN_is_prime_fasttest_ex(self.as_ptr(), - checks as c_int, - ctx, - do_trial_division as c_int, - ptr::null()) == 1) - }) - } - } - - /// Generates a cryptographically strong pseudo-random `BigNum` `r` in the range - /// `0 <= r < self`. - pub fn checked_rand_in_range(&self) -> Result { - unsafe { - with_bn_in_ctx!(r, ctx, { - ffi::BN_rand_range(r.as_ptr(), self.as_ptr()) == 1 - }) - } - } - - /// The cryptographically weak counterpart to `checked_rand_in_range`. - pub fn checked_pseudo_rand_in_range(&self) -> Result { - unsafe { - with_bn_in_ctx!(r, ctx, { - ffi::BN_pseudo_rand_range(r.as_ptr(), self.as_ptr()) == 1 - }) - } - } - - /// Sets bit `n`. Equivalent to `self |= (1 << n)`. - /// - /// When setting a bit outside of `self`, it is expanded. - pub fn set_bit(&mut self, n: i32) -> Result<(), ErrorStack> { - unsafe { - if ffi::BN_set_bit(self.as_ptr(), n as c_int) == 1 { - Ok(()) - } else { - Err(ErrorStack::get()) - } - } - } - - /// Clears bit `n`, setting it to 0. Equivalent to `self &= ~(1 << n)`. - /// - /// When clearing a bit outside of `self`, an error is returned. - pub fn clear_bit(&mut self, n: i32) -> Result<(), ErrorStack> { - unsafe { - if ffi::BN_clear_bit(self.as_ptr(), n as c_int) == 1 { - Ok(()) - } else { - Err(ErrorStack::get()) - } - } - } - - /// Returns `true` if the `n`th bit of `self` is set to 1, `false` otherwise. - pub fn is_bit_set(&self, n: i32) -> bool { - unsafe { ffi::BN_is_bit_set(self.as_ptr(), n as c_int) == 1 } - } - - /// Truncates `self` to the lowest `n` bits. - /// - /// An error occurs if `self` is already shorter than `n` bits. - pub fn mask_bits(&mut self, n: i32) -> Result<(), ErrorStack> { - unsafe { - if ffi::BN_mask_bits(self.as_ptr(), n as c_int) == 1 { - Ok(()) - } else { - Err(ErrorStack::get()) - } - } - } - - /// Returns `self`, shifted left by 1 bit. `self` may be negative. - /// - /// ``` - /// # use openssl::bn::BigNum; - /// let ref s = BigNum::new_from(0b0100).unwrap(); - /// let result = BigNum::new_from(0b1000).unwrap(); - /// - /// assert_eq!(s.checked_shl1().unwrap(), result); - /// ``` - /// - /// ``` - /// # use openssl::bn::BigNum; - /// let ref s = -BigNum::new_from(8).unwrap(); - /// let result = -BigNum::new_from(16).unwrap(); - /// - /// // (-8) << 1 == -16 - /// assert_eq!(s.checked_shl1().unwrap(), result); - /// ``` - pub fn checked_shl1(&self) -> Result { - unsafe { - with_bn!(r, { - ffi::BN_lshift1(r.as_ptr(), self.as_ptr()) == 1 - }) - } - } - - /// Returns `self`, shifted right by 1 bit. `self` may be negative. - pub fn checked_shr1(&self) -> Result { - unsafe { - with_bn!(r, { - ffi::BN_rshift1(r.as_ptr(), self.as_ptr()) == 1 - }) - } - } - - pub fn checked_add(&self, a: &BigNumRef) -> Result { - unsafe { - with_bn!(r, { - ffi::BN_add(r.as_ptr(), self.as_ptr(), a.as_ptr()) == 1 - }) - } - } - - pub fn checked_sub(&self, a: &BigNumRef) -> Result { - unsafe { - with_bn!(r, { - ffi::BN_sub(r.as_ptr(), self.as_ptr(), a.as_ptr()) == 1 - }) - } - } - - pub fn checked_mul(&self, a: &BigNumRef) -> Result { - unsafe { - with_bn_in_ctx!(r, ctx, { - ffi::BN_mul(r.as_ptr(), self.as_ptr(), a.as_ptr(), ctx) == 1 - }) - } - } - - pub fn checked_div(&self, a: &BigNumRef) -> Result { - unsafe { - with_bn_in_ctx!(r, ctx, { - ffi::BN_div(r.as_ptr(), ptr::null_mut(), self.as_ptr(), a.as_ptr(), ctx) == 1 - }) - } - } - - pub fn checked_mod(&self, a: &BigNumRef) -> Result { - unsafe { - with_bn_in_ctx!(r, ctx, { - ffi::BN_div(ptr::null_mut(), r.as_ptr(), self.as_ptr(), a.as_ptr(), ctx) == 1 - }) - } - } - - pub fn checked_shl(&self, a: &i32) -> Result { - unsafe { - with_bn!(r, { - ffi::BN_lshift(r.as_ptr(), self.as_ptr(), *a as c_int) == 1 - }) - } - } - - pub fn checked_shr(&self, a: &i32) -> Result { - unsafe { - with_bn!(r, { - ffi::BN_rshift(r.as_ptr(), self.as_ptr(), *a as c_int) == 1 - }) - } - } - - pub fn to_owned(&self) -> Result { - unsafe { - let r = try_ssl_null!(ffi::BN_dup(self.as_ptr())); - Ok(BigNum::from_ptr(r)) - } - } - - /// Inverts the sign of `self`. - /// - /// ``` - /// # use openssl::bn::BigNum; - /// let mut s = BigNum::new_from(8).unwrap(); - /// - /// s.negate(); - /// assert_eq!(s, -BigNum::new_from(8).unwrap()); - /// s.negate(); - /// assert_eq!(s, BigNum::new_from(8).unwrap()); - /// ``` - pub fn negate(&mut self) { - unsafe { ffi::BN_set_negative(self.as_ptr(), !self.is_negative() as c_int) } - } - - /// Compare the absolute values of `self` and `oth`. - /// - /// ``` - /// # use openssl::bn::BigNum; - /// # use std::cmp::Ordering; - /// let s = -BigNum::new_from(8).unwrap(); - /// let o = BigNum::new_from(8).unwrap(); - /// - /// assert_eq!(s.abs_cmp(&o), Ordering::Equal); - /// ``` - pub fn abs_cmp(&self, oth: &BigNumRef) -> Ordering { - unsafe { - let res = ffi::BN_ucmp(self.as_ptr(), oth.as_ptr()) as i32; - if res < 0 { - Ordering::Less - } else if res > 0 { - Ordering::Greater - } else { - Ordering::Equal - } - } - } - - pub fn is_negative(&self) -> bool { - unsafe { (*self.as_ptr()).neg == 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 } - } - - /// Returns the size of `self` in bytes. - pub fn num_bytes(&self) -> i32 { - (self.num_bits() + 7) / 8 - } - - pub fn as_ptr(&self) -> *mut ffi::BIGNUM { - self.0 - } - - /// Returns a big-endian byte vector representation of the absolute value of `self`. - /// - /// `self` can be recreated by using `new_from_slice`. - /// - /// ``` - /// # use openssl::bn::BigNum; - /// let s = -BigNum::new_from(4543).unwrap(); - /// let r = BigNum::new_from(4543).unwrap(); - /// - /// let s_vec = s.to_vec(); - /// assert_eq!(BigNum::new_from_slice(&s_vec).unwrap(), r); - /// ``` - pub fn to_vec(&self) -> Vec { - let size = self.num_bytes() as usize; - let mut v = Vec::with_capacity(size); - unsafe { - ffi::BN_bn2bin(self.as_ptr(), v.as_mut_ptr()); - v.set_len(size); - } - v - } - - /// Returns a decimal string representation of `self`. - /// - /// ``` - /// # use openssl::bn::BigNum; - /// let s = -BigNum::new_from(12345).unwrap(); - /// - /// assert_eq!(s.to_dec_str(), "-12345"); - /// ``` - pub fn to_dec_str(&self) -> String { - unsafe { - let buf = ffi::BN_bn2dec(self.as_ptr()); - 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); - str - } - } - - /// Returns a hexadecimal string representation of `self`. - /// - /// ``` - /// # use openssl::bn::BigNum; - /// let s = -BigNum::new_from(0x99ff).unwrap(); - /// - /// assert_eq!(s.to_hex_str(), "-99FF"); - /// ``` - pub fn to_hex_str(&self) -> String { - unsafe { - let buf = ffi::BN_bn2hex(self.as_ptr()); - 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); - str - } - } -} - -/// An owned, signed, arbitrary-precision integer. -/// -/// `BigNum` provides wrappers around OpenSSL's checked arithmetic functions. -/// Additionally, it implements the standard operators (`std::ops`), which -/// perform unchecked arithmetic, unwrapping the returned `Result` of the -/// checked operations. -pub struct BigNum(BigNumRef<'static>); - -impl BigNum { - /// Creates a new `BigNum` with the value 0. - pub fn new() -> Result { - unsafe { - ffi::init(); - let v = try_ssl_null!(ffi::BN_new()); - Ok(BigNum::from_ptr(v)) - } - } - - /// Creates a new `BigNum` with the given value. - pub fn new_from(n: c_ulong) -> Result { - BigNum::new().and_then(|v| unsafe { - try_ssl!(ffi::BN_set_word(v.as_ptr(), n)); - Ok(v) - }) - } - - /// Creates a `BigNum` from a decimal string. - pub fn from_dec_str(s: &str) -> Result { - BigNum::new().and_then(|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 _)); - Ok(v) - }) - } - - /// Creates a `BigNum` from a hexadecimal string. - pub fn from_hex_str(s: &str) -> Result { - BigNum::new().and_then(|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 _)); - Ok(v) - }) - } - - pub unsafe fn from_ptr(handle: *mut ffi::BIGNUM) -> BigNum { - BigNum(BigNumRef::from_ptr(handle)) - } - - /// Creates a new `BigNum` from an unsigned, big-endian encoded number of arbitrary length. - /// - /// ``` - /// # use openssl::bn::BigNum; - /// let bignum = BigNum::new_from_slice(&[0x12, 0x00, 0x34]).unwrap(); - /// - /// assert_eq!(bignum, BigNum::new_from(0x120034).unwrap()); - /// ``` - pub fn new_from_slice(n: &[u8]) -> Result { - BigNum::new().and_then(|v| unsafe { - try_ssl_null!(ffi::BN_bin2bn(n.as_ptr(), n.len() as c_int, v.as_ptr())); - Ok(v) - }) - } - /// Generates a prime number. - /// - /// # Parameters - /// - /// * `bits`: The length of the prime in bits (lower bound). - /// * `safe`: If true, returns a "safe" prime `p` so that `(p-1)/2` is also prime. - /// * `add`/`rem`: If `add` is set to `Some(add)`, `p % add == rem` will hold, where `p` is the - /// generated prime and `rem` is `1` if not specified (`None`). - pub fn checked_generate_prime(bits: i32, - safe: bool, - add: Option<&BigNum>, - rem: Option<&BigNum>) - -> Result { - unsafe { - with_bn_in_ctx!(r, ctx, { - let add_arg = add.map(|a| a.as_ptr()).unwrap_or(ptr::null_mut()); - let rem_arg = rem.map(|r| r.as_ptr()).unwrap_or(ptr::null_mut()); - - ffi::BN_generate_prime_ex(r.as_ptr(), - bits as c_int, - safe as c_int, - add_arg, - rem_arg, - ptr::null()) == 1 - }) - } - } - - /// Generates a cryptographically strong pseudo-random `BigNum`. - /// - /// # Parameters - /// - /// * `bits`: Length of the number in bits. - /// * `prop`: The desired properties of the number. - /// * `odd`: If `true`, the generated number will be odd. - pub fn checked_new_random(bits: i32, prop: RNGProperty, odd: bool) -> Result { - unsafe { - with_bn_in_ctx!(r, ctx, { - ffi::BN_rand(r.as_ptr(), bits as c_int, prop as c_int, odd as c_int) == 1 - }) - } - } - - /// The cryptographically weak counterpart to `checked_new_random`. - pub fn checked_new_pseudo_random(bits: i32, - prop: RNGProperty, - odd: bool) - -> Result { - unsafe { - with_bn_in_ctx!(r, ctx, { - ffi::BN_pseudo_rand(r.as_ptr(), bits as c_int, prop as c_int, odd as c_int) == 1 - }) - } - } -} - -impl Drop for BigNum { - fn drop(&mut self) { - unsafe { ffi::BN_clear_free(self.as_ptr()); } - } -} - -impl Deref for BigNum { - type Target = BigNumRef<'static>; - - fn deref(&self) -> &BigNumRef<'static> { - &self.0 - } -} - -impl DerefMut for BigNum { - fn deref_mut(&mut self) -> &mut BigNumRef<'static> { - &mut self.0 - } -} - -impl AsRef> for BigNum { - fn as_ref(&self) -> &BigNumRef<'static> { - self.deref() - } -} - -impl<'a> fmt::Debug for BigNumRef<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.to_dec_str()) - } -} - -impl fmt::Debug for BigNum { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.to_dec_str()) - } -} - -impl<'a> fmt::Display for BigNumRef<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.to_dec_str()) - } -} - -impl fmt::Display for BigNum { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.to_dec_str()) - } -} - -impl<'a, 'b> PartialEq> for BigNumRef<'a> { - fn eq(&self, oth: &BigNumRef) -> bool { - unsafe { ffi::BN_cmp(self.as_ptr(), oth.as_ptr()) == 0 } - } -} - -impl<'a> PartialEq for BigNumRef<'a> { - fn eq(&self, oth: &BigNum) -> bool { - self.eq(oth.deref()) - } -} - -impl<'a> Eq for BigNumRef<'a> {} - -impl PartialEq for BigNum { - fn eq(&self, oth: &BigNum) -> bool { - self.deref().eq(oth) - } -} - -impl<'a> PartialEq> for BigNum { - fn eq(&self, oth: &BigNumRef) -> bool { - self.deref().eq(oth) - } -} - -impl Eq for BigNum {} - -impl<'a, 'b> PartialOrd> for BigNumRef<'a> { - fn partial_cmp(&self, oth: &BigNumRef) -> Option { - Some(self.cmp(oth)) - } -} - -impl<'a> PartialOrd for BigNumRef<'a> { - fn partial_cmp(&self, oth: &BigNum) -> Option { - Some(self.cmp(oth.deref())) - } -} - -impl<'a> Ord for BigNumRef<'a> { - fn cmp(&self, oth: &BigNumRef) -> Ordering { - unsafe { ffi::BN_cmp(self.as_ptr(), oth.as_ptr()).cmp(&0) } - } -} - -impl PartialOrd for BigNum { - fn partial_cmp(&self, oth: &BigNum) -> Option { - self.deref().partial_cmp(oth.deref()) - } -} - -impl<'a> PartialOrd> for BigNum { - fn partial_cmp(&self, oth: &BigNumRef) -> Option { - self.deref().partial_cmp(oth) - } -} - -impl Ord for BigNum { - fn cmp(&self, oth: &BigNum) -> Ordering { - self.deref().cmp(oth.deref()) - } -} - -impl<'a, 'b> Add<&'b BigNumRef<'b>> for &'a BigNumRef<'a> { - type Output = BigNum; - - fn add(self, oth: &BigNumRef) -> BigNum { - self.checked_add(oth).unwrap() - } -} - -impl<'a, 'b> Sub<&'b BigNumRef<'b>> for &'a BigNumRef<'a> { - type Output = BigNum; - - fn sub(self, oth: &BigNumRef) -> BigNum { - self.checked_sub(oth).unwrap() - } -} - -impl<'a, 'b> Sub<&'b BigNum> for &'a BigNumRef<'a> { - type Output = BigNum; - - fn sub(self, oth: &BigNum) -> BigNum { - self.checked_sub(oth).unwrap() - } -} - -impl<'a, 'b> Sub<&'b BigNum> for &'a BigNum { - type Output = BigNum; - - fn sub(self, oth: &BigNum) -> BigNum { - self.checked_sub(oth).unwrap() - } -} - -impl<'a, 'b> Sub<&'b BigNumRef<'b>> for &'a BigNum { - type Output = BigNum; - - fn sub(self, oth: &BigNumRef) -> BigNum { - self.checked_sub(oth).unwrap() - } -} - -impl<'a, 'b> Mul<&'b BigNumRef<'b>> for &'a BigNumRef<'a> { - type Output = BigNum; - - fn mul(self, oth: &BigNumRef) -> BigNum { - self.checked_mul(oth).unwrap() - } -} - -impl<'a, 'b> Mul<&'b BigNum> for &'a BigNumRef<'a> { - type Output = BigNum; - - fn mul(self, oth: &BigNum) -> BigNum { - self.checked_mul(oth).unwrap() - } -} - -impl<'a, 'b> Mul<&'b BigNum> for &'a BigNum { - type Output = BigNum; - - fn mul(self, oth: &BigNum) -> BigNum { - self.checked_mul(oth).unwrap() - } -} - -impl<'a, 'b> Mul<&'b BigNumRef<'b>> for &'a BigNum { - type Output = BigNum; - - fn mul(self, oth: &BigNumRef) -> BigNum { - self.checked_mul(oth).unwrap() - } -} - -impl<'a, 'b> Div<&'b BigNumRef<'b>> for &'a BigNumRef<'a> { - type Output = BigNum; - - fn div(self, oth: &'b BigNumRef<'b>) -> BigNum { - self.checked_div(oth).unwrap() - } -} - -impl<'a, 'b> Div<&'b BigNum> for &'a BigNumRef<'a> { - type Output = BigNum; - - fn div(self, oth: &'b BigNum) -> BigNum { - self.checked_div(oth).unwrap() - } -} - -impl<'a, 'b> Div<&'b BigNum> for &'a BigNum { - type Output = BigNum; - - fn div(self, oth: &'b BigNum) -> BigNum { - self.checked_div(oth).unwrap() - } -} - -impl<'a, 'b> Div<&'b BigNumRef<'b>> for &'a BigNum { - type Output = BigNum; - - fn div(self, oth: &'b BigNumRef<'b>) -> BigNum { - self.checked_div(oth).unwrap() - } -} - -impl<'a, 'b> Rem<&'b BigNumRef<'b>> for &'a BigNumRef<'a> { - type Output = BigNum; - - fn rem(self, oth: &'b BigNumRef<'b>) -> BigNum { - self.checked_mod(oth).unwrap() - } -} - -impl<'a, 'b> Rem<&'b BigNum> for &'a BigNumRef<'a> { - type Output = BigNum; - - fn rem(self, oth: &'b BigNum) -> BigNum { - self.checked_mod(oth).unwrap() - } -} - -impl<'a, 'b> Rem<&'b BigNumRef<'b>> for &'a BigNum { - type Output = BigNum; - - fn rem(self, oth: &'b BigNumRef<'b>) -> BigNum { - self.checked_mod(oth).unwrap() - } -} - -impl<'a, 'b> Rem<&'b BigNum> for &'a BigNum { - type Output = BigNum; - - fn rem(self, oth: &'b BigNum) -> BigNum { - self.checked_mod(oth).unwrap() - } -} - -impl<'a> Shl for &'a BigNumRef<'a> { - type Output = BigNum; - - fn shl(self, n: i32) -> BigNum { - self.checked_shl(&n).unwrap() - } -} - -impl<'a> Shl for &'a BigNum { - type Output = BigNum; - - fn shl(self, n: i32) -> BigNum { - self.checked_shl(&n).unwrap() - } -} - -impl<'a> Shr for &'a BigNumRef<'a> { - type Output = BigNum; - - fn shr(self, n: i32) -> BigNum { - self.checked_shr(&n).unwrap() - } -} - -impl<'a> Shr for &'a BigNum { - type Output = BigNum; - - fn shr(self, n: i32) -> BigNum { - self.checked_shr(&n).unwrap() - } -} - -impl<'a> Neg for &'a BigNumRef<'a> { - type Output = BigNum; - - fn neg(self) -> BigNum { - let mut n = self.to_owned().unwrap(); - n.negate(); - n - } -} - -impl<'a> Neg for &'a BigNum { - type Output = BigNum; - - fn neg(self) -> BigNum { - let mut n = self.deref().to_owned().unwrap(); - n.negate(); - n - } -} - -impl Neg for BigNum { - type Output = BigNum; - - fn neg(mut self) -> BigNum { - self.negate(); - self - } -} - -#[cfg(test)] -mod tests { - use bn::BigNum; - - #[test] - fn test_to_from_slice() { - let v0 = BigNum::new_from(10203004).unwrap(); - let vec = v0.to_vec(); - let v1 = BigNum::new_from_slice(&vec).unwrap(); - - assert!(v0 == v1); - } - - #[test] - fn test_negation() { - let a = BigNum::new_from(909829283).unwrap(); - - assert!(!a.is_negative()); - assert!((-a).is_negative()); - } - - - #[test] - fn test_prime_numbers() { - let a = BigNum::new_from(19029017).unwrap(); - let p = BigNum::checked_generate_prime(128, true, None, Some(&a)).unwrap(); - - assert!(p.is_prime(100).unwrap()); - assert!(p.is_prime_fast(100, true).unwrap()); - } -} diff --git a/openssl/src/c_helpers.c b/openssl/src/c_helpers.c deleted file mode 100644 index 6e6a5021..00000000 --- a/openssl/src/c_helpers.c +++ /dev/null @@ -1,67 +0,0 @@ -#include -#include -#include -#include - -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 diff --git a/openssl/src/c_helpers.rs b/openssl/src/c_helpers.rs deleted file mode 100644 index d16c3125..00000000 --- a/openssl/src/c_helpers.rs +++ /dev/null @@ -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; -} diff --git a/openssl/src/crypto.rs b/openssl/src/crypto.rs new file mode 100644 index 00000000..ce83cbae --- /dev/null +++ b/openssl/src/crypto.rs @@ -0,0 +1,59 @@ +use libc::{c_char, c_int, c_void}; +use std::fmt; +use std::ffi::CStr; +use std::slice; +use std::ops::Deref; +use std::str; + +pub struct CryptoString(&'static str); + +impl Drop for CryptoString { + fn drop(&mut self) { + unsafe { + CRYPTO_free(self.0.as_ptr() as *mut c_void, + concat!(file!(), "\0").as_ptr() as *const c_char, + line!() as c_int); + } + } +} + +impl Deref for CryptoString { + type Target = str; + + fn deref(&self) -> &str { + self.0 + } +} + +impl CryptoString { + pub unsafe fn from_raw_parts(buf: *mut u8, len: usize) -> CryptoString { + let slice = slice::from_raw_parts(buf, len); + CryptoString(str::from_utf8_unchecked(slice)) + } + + pub unsafe fn from_null_terminated(buf: *mut c_char) -> CryptoString { + let slice = CStr::from_ptr(buf).to_bytes(); + CryptoString(str::from_utf8_unchecked(slice)) + } +} + +impl fmt::Display for CryptoString { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(self.0, f) + } +} + +impl fmt::Debug for CryptoString { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(self.0, f) + } +} + +#[cfg(not(ossl110))] +#[allow(non_snake_case)] +unsafe fn CRYPTO_free(buf: *mut c_void, _: *const c_char, _: c_int) { + ::ffi::CRYPTO_free(buf); +} + +#[cfg(ossl110)] +use ffi::CRYPTO_free; diff --git a/openssl/src/crypto/dsa.rs b/openssl/src/crypto/dsa.rs deleted file mode 100644 index 97ba7a97..00000000 --- a/openssl/src/crypto/dsa.rs +++ /dev/null @@ -1,338 +0,0 @@ -use ffi; -use std::fmt; -use error::ErrorStack; -use std::ptr; -use libc::{c_uint, c_int, c_char, c_void}; - -use bn::BigNumRef; -use bio::{MemBio, MemBioSlice}; -use crypto::hash; -use HashTypeInternals; -use crypto::util::{CallbackState, invoke_passwd_cb}; - - -/// Builder for upfront DSA parameter generateration -pub struct DSAParams(*mut ffi::DSA); - -impl DSAParams { - pub fn with_size(size: u32) -> Result { - 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())); - Ok(dsa) - } - } - - /// Generate a key pair from the initialized parameters - pub fn generate(self) -> Result { - unsafe { - try_ssl!(ffi::DSA_generate_key(self.0)); - let dsa = DSA(self.0); - ::std::mem::forget(self); - Ok(dsa) - } - } -} - -impl Drop for DSAParams { - fn drop(&mut self) { - unsafe { - ffi::DSA_free(self.0); - } - } -} - -pub struct DSA(*mut ffi::DSA); - -impl Drop for DSA { - fn drop(&mut self) { - unsafe { - ffi::DSA_free(self.0); - } - } -} - -impl DSA { - pub unsafe fn from_ptr(dsa: *mut ffi::DSA) -> DSA { - DSA(dsa) - } - - /// Generate a DSA key pair - /// For more complicated key generation scenarios see the `DSAParams` type - pub fn generate(size: u32) -> Result { - let params = try!(DSAParams::with_size(size)); - params.generate() - } - - /// Reads a DSA private key from PEM formatted data. - pub fn private_key_from_pem(buf: &[u8]) -> Result { - ffi::init(); - let mem_bio = try!(MemBioSlice::new(buf)); - - unsafe { - let dsa = try_ssl_null!(ffi::PEM_read_bio_DSAPrivateKey(mem_bio.as_ptr(), - ptr::null_mut(), - None, - ptr::null_mut())); - let dsa = DSA(dsa); - assert!(dsa.has_private_key()); - Ok(dsa) - } - } - - /// Read a private key from PEM supplying a password callback to be invoked if the private key - /// is encrypted. - /// - /// The callback will be passed the password buffer and should return the number of characters - /// placed into the buffer. - pub fn private_key_from_pem_cb(buf: &[u8], pass_cb: F) -> Result - where F: FnOnce(&mut [c_char]) -> usize - { - ffi::init(); - let mut cb = CallbackState::new(pass_cb); - let mem_bio = try!(MemBioSlice::new(buf)); - - unsafe { - let cb_ptr = &mut cb as *mut _ as *mut c_void; - let dsa = try_ssl_null!(ffi::PEM_read_bio_DSAPrivateKey(mem_bio.as_ptr(), - ptr::null_mut(), - Some(invoke_passwd_cb::), - cb_ptr)); - let dsa = DSA(dsa); - assert!(dsa.has_private_key()); - Ok(dsa) - } - } - - /// Writes an DSA private key as unencrypted PEM formatted data - pub fn private_key_to_pem(&self) -> Result, ErrorStack> - { - assert!(self.has_private_key()); - let mem_bio = try!(MemBio::new()); - - unsafe { - try_ssl!(ffi::PEM_write_bio_DSAPrivateKey(mem_bio.as_ptr(), self.0, - ptr::null(), ptr::null_mut(), 0, - None, ptr::null_mut())) - }; - - Ok(mem_bio.get_buf().to_owned()) - } - - /// Reads an DSA public key from PEM formatted data. - pub fn public_key_from_pem(buf: &[u8]) -> Result - { - ffi::init(); - - let mem_bio = try!(MemBioSlice::new(buf)); - unsafe { - let dsa = try_ssl_null!(ffi::PEM_read_bio_DSA_PUBKEY(mem_bio.as_ptr(), - ptr::null_mut(), - None, - ptr::null_mut())); - Ok(DSA(dsa)) - } - } - - /// Writes an DSA public key as PEM formatted data - pub fn public_key_to_pem(&self) -> Result, ErrorStack> { - let mem_bio = try!(MemBio::new()); - unsafe { try_ssl!(ffi::PEM_write_bio_DSA_PUBKEY(mem_bio.as_ptr(), self.0)) }; - Ok(mem_bio.get_buf().to_owned()) - } - - pub fn size(&self) -> Option { - if self.q().is_some() { - unsafe { Some(ffi::DSA_size(self.0) as u32) } - } else { - None - } - } - - pub fn sign(&self, hash: hash::Type, message: &[u8]) -> Result, ErrorStack> { - let k_len = self.size().expect("DSA missing a q") as c_uint; - let mut sig = vec![0; k_len as usize]; - let mut sig_len = k_len; - assert!(self.has_private_key()); - - unsafe { - try_ssl!(ffi::DSA_sign(hash.as_nid() as c_int, - message.as_ptr(), - message.len() as c_int, - sig.as_mut_ptr(), - &mut sig_len, - self.0)); - sig.set_len(sig_len as usize); - sig.shrink_to_fit(); - Ok(sig) - } - } - - pub fn verify(&self, hash: hash::Type, message: &[u8], sig: &[u8]) -> Result { - unsafe { - let result = ffi::DSA_verify(hash.as_nid() as c_int, - message.as_ptr(), - message.len() as c_int, - sig.as_ptr(), - sig.len() as c_int, - self.0); - - try_ssl_if!(result == -1); - Ok(result == 1) - } - } - - pub fn as_ptr(&self) -> *mut ffi::DSA { - self.0 - } - - pub fn p<'a>(&'a self) -> Option> { - unsafe { - let p = (*self.0).p; - if p.is_null() { - None - } else { - Some(BigNumRef::from_ptr((*self.0).p)) - } - } - } - - pub fn q<'a>(&'a self) -> Option> { - unsafe { - let q = (*self.0).q; - if q.is_null() { - None - } else { - Some(BigNumRef::from_ptr((*self.0).q)) - } - } - } - - pub fn g<'a>(&'a self) -> Option> { - unsafe { - let g = (*self.0).g; - if g.is_null() { - None - } else { - Some(BigNumRef::from_ptr((*self.0).g)) - } - } - } - - pub fn has_public_key(&self) -> bool { - unsafe { !(*self.0).pub_key.is_null() } - } - - pub fn has_private_key(&self) -> bool { - unsafe { !(*self.0).priv_key.is_null() } - } -} - -impl fmt::Debug for DSA { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "DSA") - } -} - -#[cfg(test)] -mod test { - use std::io::Write; - use libc::c_char; - - use super::*; - use crypto::hash::*; - - #[test] - pub fn test_generate() { - let key = DSA::generate(1024).unwrap(); - - key.public_key_to_pem().unwrap(); - key.private_key_to_pem().unwrap(); - - let input: Vec = (0..25).cycle().take(1024).collect(); - - let digest = { - let mut sha = Hasher::new(Type::SHA1).unwrap(); - sha.write_all(&input).unwrap(); - sha.finish().unwrap() - }; - - let sig = key.sign(Type::SHA1, &digest).unwrap(); - let verified = key.verify(Type::SHA1, &digest, &sig).unwrap(); - assert!(verified); - } - - #[test] - pub fn test_sign_verify() { - let input: Vec = (0..25).cycle().take(1024).collect(); - - let private_key = { - let key = include_bytes!("../../test/dsa.pem"); - DSA::private_key_from_pem(key).unwrap() - }; - - let public_key = { - let key = include_bytes!("../../test/dsa.pem.pub"); - DSA::public_key_from_pem(key).unwrap() - }; - - let digest = { - let mut sha = Hasher::new(Type::SHA1).unwrap(); - sha.write_all(&input).unwrap(); - sha.finish().unwrap() - }; - - let sig = private_key.sign(Type::SHA1, &digest).unwrap(); - let verified = public_key.verify(Type::SHA1, &digest, &sig).unwrap(); - assert!(verified); - } - - #[test] - pub fn test_sign_verify_fail() { - let input: Vec = (0..25).cycle().take(128).collect(); - let private_key = { - let key = include_bytes!("../../test/dsa.pem"); - DSA::private_key_from_pem(key).unwrap() - }; - - let public_key = { - let key = include_bytes!("../../test/dsa.pem.pub"); - DSA::public_key_from_pem(key).unwrap() - }; - - let digest = { - let mut sha = Hasher::new(Type::SHA1).unwrap(); - sha.write_all(&input).unwrap(); - sha.finish().unwrap() - }; - - let mut sig = private_key.sign(Type::SHA1, &digest).unwrap(); - // tamper with the sig this should cause a failure - let len = sig.len(); - sig[len / 2] = 0; - sig[len - 1] = 0; - if let Ok(true) = public_key.verify(Type::SHA1, &digest, &sig) { - panic!("Tampered with signatures should not verify!"); - } - } - - #[test] - pub fn test_password() { - let mut password_queried = false; - let key = include_bytes!("../../test/dsa-encrypted.pem"); - DSA::private_key_from_pem_cb(key, |password| { - password_queried = true; - password[0] = b'm' as c_char; - password[1] = b'y' as c_char; - password[2] = b'p' as c_char; - password[3] = b'a' as c_char; - password[4] = b's' as c_char; - password[5] = b's' as c_char; - 6 - }).unwrap(); - - assert!(password_queried); - } -} diff --git a/openssl/src/crypto/hmac.rs b/openssl/src/crypto/hmac.rs deleted file mode 100644 index 1847d6b1..00000000 --- a/openssl/src/crypto/hmac.rs +++ /dev/null @@ -1,511 +0,0 @@ -// Copyright 2013 Jack Lloyd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -use libc::{c_int, c_uint}; -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 { - Reset, - Updated, - Finalized, -} - -use self::State::*; - -/// Provides HMAC computation. -/// -/// Requires the `hmac` feature. -/// -/// # Examples -/// -/// Calculate a HMAC in one go. -/// -/// ``` -/// use openssl::crypto::hash::Type; -/// use openssl::crypto::hmac::hmac; -/// let key = b"Jefe"; -/// let data = b"what do ya want for nothing?"; -/// let spec = b"\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7\x38"; -/// let res = hmac(Type::MD5, key, data).unwrap(); -/// assert_eq!(res, spec); -/// ``` -/// -/// Use the `Write` trait to supply the input in chunks. -/// -/// ``` -/// use openssl::crypto::hash::Type; -/// use openssl::crypto::hmac::HMAC; -/// let key = b"Jefe"; -/// let data: &[&[u8]] = &[b"what do ya ", b"want for nothing?"]; -/// let spec = b"\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7\x38"; -/// let mut h = HMAC::new(Type::MD5, &*key).unwrap(); -/// h.update(data[0]).unwrap(); -/// h.update(data[1]).unwrap(); -/// let res = h.finish().unwrap(); -/// assert_eq!(res, spec); -/// ``` -pub struct HMAC { - ctx: ffi::HMAC_CTX, - state: State, -} - -impl HMAC { - /// Creates a new `HMAC` with the specified hash type using the `key`. - pub fn new(ty: Type, key: &[u8]) -> Result { - ffi::init(); - - let ctx = unsafe { - let mut ctx = ::std::mem::uninitialized(); - ffi::HMAC_CTX_init(&mut ctx); - ctx - }; - let md = ty.evp_md(); - - let mut h = HMAC { - ctx: ctx, - state: Finalized, - }; - try!(h.init_once(md, key)); - Ok(h) - } - - 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, - key.as_ptr() as *const _, - key.len() as c_int, - md, - 0 as *mut _)); - } - self.state = Reset; - Ok(()) - } - - fn init(&mut self) -> Result<(), ErrorStack> { - match self.state { - Reset => return Ok(()), - Updated => { - try!(self.finish()); - } - Finalized => (), - } - // 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, - 0 as *const _, - 0, - 0 as *const _, - 0 as *mut _)); - } - self.state = Reset; - Ok(()) - } - - pub fn update(&mut self, mut 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..]; - } - self.state = Updated; - Ok(()) - } - - /// Returns the hash of the data written since creation or - /// the last `finish` and resets the hasher. - pub fn finish(&mut self) -> Result, ErrorStack> { - if self.state == Finalized { - try!(self.init()); - } - 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)); - res.truncate(len as usize); - self.state = Finalized; - Ok(res) - } - } -} - -impl Write for HMAC { - #[inline] - fn write(&mut self, buf: &[u8]) -> io::Result { - try!(self.update(buf)); - Ok(buf.len()) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} - -#[cfg(feature = "hmac_clone")] -impl Clone for HMAC { - /// Requires the `hmac_clone` feature. - fn clone(&self) -> HMAC { - let mut ctx: ffi::HMAC_CTX; - unsafe { - ctx = ::std::mem::uninitialized(); - let r = ffi::HMAC_CTX_copy(&mut ctx, &self.ctx); - assert_eq!(r, 1); - } - HMAC { - ctx: ctx, - state: self.state, - } - } -} - -impl Drop for HMAC { - fn drop(&mut self) { - unsafe { - if self.state != Finalized { - drop(self.finish()); - } - ffi::HMAC_CTX_cleanup(&mut self.ctx); - } - } -} - -/// Computes the HMAC of the `data` with the hash `t` and `key`. -pub fn hmac(t: Type, key: &[u8], data: &[u8]) -> Result, ErrorStack> { - let mut h = try!(HMAC::new(t, key)); - try!(h.update(data)); - h.finish() -} - -#[cfg(test)] -mod tests { - use std::iter::repeat; - use serialize::hex::FromHex; - use crypto::hash::Type; - use crypto::hash::Type::*; - use super::{hmac, HMAC}; - use std::io::prelude::*; - - fn test_hmac(ty: Type, tests: &[(Vec, Vec, Vec)]) { - for &(ref key, ref data, ref res) in tests.iter() { - assert_eq!(hmac(ty, &**key, &**data).unwrap(), *res); - } - } - - fn test_hmac_recycle(h: &mut HMAC, test: &(Vec, Vec, Vec)) { - let &(_, ref data, ref res) = test; - h.write_all(&**data).unwrap(); - assert_eq!(h.finish().unwrap(), *res); - } - - #[test] - fn test_hmac_md5() { - // test vectors from RFC 2202 - let tests: [(Vec, Vec, Vec); 7] = - [(repeat(0x0b_u8).take(16).collect(), - b"Hi There".to_vec(), - "9294727a3638bb1c13f48ef8158bfc9d".from_hex().unwrap()), - (b"Jefe".to_vec(), - b"what do ya want for nothing?".to_vec(), - "750c783e6ab0b503eaa86e310a5db738".from_hex().unwrap()), - (repeat(0xaa_u8).take(16).collect(), - repeat(0xdd_u8).take(50).collect(), - "56be34521d144c88dbb8c733f0e8b3f6".from_hex().unwrap()), - ("0102030405060708090a0b0c0d0e0f10111213141516171819".from_hex().unwrap(), - repeat(0xcd_u8).take(50).collect(), - "697eaf0aca3a3aea3a75164746ffaa79".from_hex().unwrap()), - (repeat(0x0c_u8).take(16).collect(), - b"Test With Truncation".to_vec(), - "56461ef2342edc00f9bab995690efd4c".from_hex().unwrap()), - (repeat(0xaa_u8).take(80).collect(), - b"Test Using Larger Than Block-Size Key - Hash Key First".to_vec(), - "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd".from_hex().unwrap()), - (repeat(0xaa_u8).take(80).collect(), - b"Test Using Larger Than Block-Size Key \ - and Larger Than One Block-Size Data" - .to_vec(), - "6f630fad67cda0ee1fb1f562db3aa53e".from_hex().unwrap())]; - - test_hmac(MD5, &tests); - } - - #[test] - fn test_hmac_md5_recycle() { - let tests: [(Vec, Vec, Vec); 2] = - [(repeat(0xaa_u8).take(80).collect(), - b"Test Using Larger Than Block-Size Key - Hash Key First".to_vec(), - "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd".from_hex().unwrap()), - (repeat(0xaa_u8).take(80).collect(), - b"Test Using Larger Than Block-Size Key \ - and Larger Than One Block-Size Data" - .to_vec(), - "6f630fad67cda0ee1fb1f562db3aa53e".from_hex().unwrap())]; - - let mut h = HMAC::new(MD5, &*tests[0].0).unwrap(); - for i in 0..100usize { - let test = &tests[i % 2]; - test_hmac_recycle(&mut h, test); - } - } - - #[test] - fn test_finish_twice() { - let test: (Vec, Vec, Vec) = - (repeat(0xaa_u8).take(80).collect(), - b"Test Using Larger Than Block-Size Key - Hash Key First".to_vec(), - "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd".from_hex().unwrap()); - - let mut h = HMAC::new(Type::MD5, &*test.0).unwrap(); - h.write_all(&*test.1).unwrap(); - h.finish().unwrap(); - let res = h.finish().unwrap(); - let null = hmac(Type::MD5, &*test.0, &[]).unwrap(); - assert_eq!(res, null); - } - - #[test] - #[cfg(feature = "hmac_clone")] - fn test_clone() { - let tests: [(Vec, Vec, Vec); 2] = - [(repeat(0xaa_u8).take(80).collect(), - b"Test Using Larger Than Block-Size Key - Hash Key First".to_vec(), - "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd".from_hex().unwrap()), - (repeat(0xaa_u8).take(80).collect(), - b"Test Using Larger Than Block-Size Key \ - and Larger Than One Block-Size Data" - .to_vec(), - "6f630fad67cda0ee1fb1f562db3aa53e".from_hex().unwrap())]; - let p = tests[0].0.len() / 2; - let h0 = HMAC::new(Type::MD5, &*tests[0].0).unwrap(); - - println!("Clone a new hmac"); - let mut h1 = h0.clone(); - h1.write_all(&tests[0].1[..p]).unwrap(); - { - println!("Clone an updated hmac"); - let mut h2 = h1.clone(); - h2.write_all(&tests[0].1[p..]).unwrap(); - let res = h2.finish().unwrap(); - assert_eq!(res, tests[0].2); - } - h1.write_all(&tests[0].1[p..]).unwrap(); - let res = h1.finish().unwrap(); - assert_eq!(res, tests[0].2); - - println!("Clone a finished hmac"); - let mut h3 = h1.clone(); - h3.write_all(&*tests[1].1).unwrap(); - let res = h3.finish().unwrap(); - assert_eq!(res, tests[1].2); - } - - #[test] - fn test_hmac_sha1() { - // test vectors from RFC 2202 - let tests: [(Vec, Vec, Vec); 7] = - [(repeat(0x0b_u8).take(20).collect(), - b"Hi There".to_vec(), - "b617318655057264e28bc0b6fb378c8ef146be00".from_hex().unwrap()), - (b"Jefe".to_vec(), - b"what do ya want for nothing?".to_vec(), - "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79".from_hex().unwrap()), - (repeat(0xaa_u8).take(20).collect(), - repeat(0xdd_u8).take(50).collect(), - "125d7342b9ac11cd91a39af48aa17b4f63f175d3".from_hex().unwrap()), - ("0102030405060708090a0b0c0d0e0f10111213141516171819".from_hex().unwrap(), - repeat(0xcd_u8).take(50).collect(), - "4c9007f4026250c6bc8414f9bf50c86c2d7235da".from_hex().unwrap()), - (repeat(0x0c_u8).take(20).collect(), - b"Test With Truncation".to_vec(), - "4c1a03424b55e07fe7f27be1d58bb9324a9a5a04".from_hex().unwrap()), - (repeat(0xaa_u8).take(80).collect(), - b"Test Using Larger Than Block-Size Key - Hash Key First".to_vec(), - "aa4ae5e15272d00e95705637ce8a3b55ed402112".from_hex().unwrap()), - (repeat(0xaa_u8).take(80).collect(), - b"Test Using Larger Than Block-Size Key \ - and Larger Than One Block-Size Data" - .to_vec(), - "e8e99d0f45237d786d6bbaa7965c7808bbff1a91".from_hex().unwrap())]; - - test_hmac(SHA1, &tests); - } - - #[test] - fn test_hmac_sha1_recycle() { - let tests: [(Vec, Vec, Vec); 2] = - [(repeat(0xaa_u8).take(80).collect(), - b"Test Using Larger Than Block-Size Key - Hash Key First".to_vec(), - "aa4ae5e15272d00e95705637ce8a3b55ed402112".from_hex().unwrap()), - (repeat(0xaa_u8).take(80).collect(), - b"Test Using Larger Than Block-Size Key \ - and Larger Than One Block-Size Data" - .to_vec(), - "e8e99d0f45237d786d6bbaa7965c7808bbff1a91".from_hex().unwrap())]; - - let mut h = HMAC::new(SHA1, &*tests[0].0).unwrap(); - for i in 0..100usize { - let test = &tests[i % 2]; - test_hmac_recycle(&mut h, test); - } - } - - - - fn test_sha2(ty: Type, results: &[Vec]) { - // test vectors from RFC 4231 - let tests: [(Vec, Vec); 6] = - [(repeat(0xb_u8).take(20).collect(), b"Hi There".to_vec()), - (b"Jefe".to_vec(), b"what do ya want for nothing?".to_vec()), - (repeat(0xaa_u8).take(20).collect(), repeat(0xdd_u8).take(50).collect()), - ("0102030405060708090a0b0c0d0e0f10111213141516171819".from_hex().unwrap(), - repeat(0xcd_u8).take(50).collect()), - (repeat(0xaa_u8).take(131).collect(), - b"Test Using Larger Than Block-Size Key - Hash Key First".to_vec()), - (repeat(0xaa_u8).take(131).collect(), - b"This is a test using a larger than block-size key and a \ - larger than block-size data. The key needs to be hashed \ - before being used by the HMAC algorithm." - .to_vec())]; - - for (&(ref key, ref data), res) in tests.iter().zip(results.iter()) { - assert_eq!(hmac(ty, &**key, &**data).unwrap(), *res); - } - - // recycle test - let mut h = HMAC::new(ty, &*tests[5].0).unwrap(); - for i in 0..100usize { - let test = &tests[4 + i % 2]; - let tup = (test.0.clone(), test.1.clone(), results[4 + i % 2].clone()); - test_hmac_recycle(&mut h, &tup); - } - } - - #[test] - fn test_hmac_sha224() { - let results = ["896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22" - .from_hex() - .unwrap(), - "a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44" - .from_hex() - .unwrap(), - "7fb3cb3588c6c1f6ffa9694d7d6ad2649365b0c1f65d69d1ec8333ea" - .from_hex() - .unwrap(), - "6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a" - .from_hex() - .unwrap(), - "95e9a0db962095adaebe9b2d6f0dbce2d499f112f2d2b7273fa6870e" - .from_hex() - .unwrap(), - "3a854166ac5d9f023f54d517d0b39dbd946770db9c2b95c9f6f565d1" - .from_hex() - .unwrap()]; - test_sha2(SHA224, &results); - } - - #[test] - fn test_hmac_sha256() { - let results = ["b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7" - .from_hex() - .unwrap(), - "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843" - .from_hex() - .unwrap(), - "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe" - .from_hex() - .unwrap(), - "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b" - .from_hex() - .unwrap(), - "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54" - .from_hex() - .unwrap(), - "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2" - .from_hex() - .unwrap()]; - test_sha2(SHA256, &results); - } - - #[test] - fn test_hmac_sha384() { - let results = ["afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59cfaea9ea90\ - 76ede7f4af152e8b2fa9cb6" - .from_hex() - .unwrap(), - "af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5\ - e69e2c78b3239ecfab21649" - .from_hex() - .unwrap(), - "88062608d3e6ad8a0aa2ace014c8a86f0aa635d947ac9febe83ef4e55966144b2a5ab39dc\ - 13814b94e3ab6e101a34f27" - .from_hex() - .unwrap(), - "3e8a69b7783c25851933ab6290af6ca77a9981480850009cc5577c6e1f573b4e6801dd23c\ - 4a7d679ccf8a386c674cffb" - .from_hex() - .unwrap(), - "4ece084485813e9088d2c63a041bc5b44f9ef1012a2b588f3cd11f05033ac4c60c2ef6ab4\ - 030fe8296248df163f44952" - .from_hex() - .unwrap(), - "6617178e941f020d351e2f254e8fd32c602420feb0b8fb9adccebb82461e99c5a678cc31e\ - 799176d3860e6110c46523e" - .from_hex() - .unwrap()]; - test_sha2(SHA384, &results); - } - - #[test] - fn test_hmac_sha512() { - let results = ["87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d\ - 6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854" - .from_hex() - .unwrap(), - "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c\ - 05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737" - .from_hex() - .unwrap(), - "fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e84827\ - 9a722c806b485a47e67c807b946a337bee8942674278859e13292fb" - .from_hex() - .unwrap(), - "b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11\ - aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd" - .from_hex() - .unwrap(), - "80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f3526b56d037e\ - 05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598" - .from_hex() - .unwrap(), - "e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944b6022cac3\ - c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58" - .from_hex() - .unwrap()]; - test_sha2(SHA512, &results); - } -} diff --git a/openssl/src/crypto/mod.rs b/openssl/src/crypto/mod.rs deleted file mode 100644 index b8b109a2..00000000 --- a/openssl/src/crypto/mod.rs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2011 Google Inc. -// 2013 Jack Lloyd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -pub mod hash; -#[cfg(feature = "hmac")] -pub mod hmac; -pub mod pkcs5; -pub mod pkcs12; -pub mod pkey; -pub mod rand; -pub mod symm; -pub mod memcmp; -pub mod rsa; -pub mod dsa; -mod util; diff --git a/openssl/src/crypto/pkcs5.rs b/openssl/src/crypto/pkcs5.rs deleted file mode 100644 index ef84fbe1..00000000 --- a/openssl/src/crypto/pkcs5.rs +++ /dev/null @@ -1,245 +0,0 @@ -use libc::c_int; -use std::ptr; -use ffi; - -use HashTypeInternals; -use crypto::hash; -use crypto::symm; -use error::ErrorStack; - -#[derive(Clone, Eq, PartialEq, Hash, Debug)] -pub struct KeyIvPair { - pub key: Vec, - pub iv: Vec, -} - -/// Derives a key and an IV from various parameters. -/// -/// If specified `salt` must be 8 bytes in length. -/// -/// If the total key and IV length is less than 16 bytes and MD5 is used then -/// the algorithm is compatible with the key derivation algorithm from PKCS#5 -/// v1.5 or PBKDF1 from PKCS#5 v2.0. -/// -/// New applications should not use this and instead use `pbkdf2_hmac_sha1` or -/// another more modern key derivation algorithm. -pub fn evp_bytes_to_key_pbkdf1_compatible(typ: symm::Type, - message_digest_type: hash::Type, - data: &[u8], - salt: Option<&[u8]>, - count: u32) - -> Result { - unsafe { - let salt_ptr = match salt { - Some(salt) => { - assert_eq!(salt.len(), ffi::PKCS5_SALT_LEN as usize); - salt.as_ptr() - } - None => ptr::null(), - }; - - ffi::init(); - - let typ = typ.as_ptr(); - let message_digest_type = message_digest_type.evp_md(); - - let len = ffi::EVP_BytesToKey(typ, - message_digest_type, - salt_ptr, - data.as_ptr(), - data.len() as c_int, - count as c_int, - ptr::null_mut(), - ptr::null_mut()); - if len == 0 { - return Err(ErrorStack::get()); - } - - let mut key = vec![0; len as usize]; - let mut iv = vec![0; len as usize]; - - try_ssl!(ffi::EVP_BytesToKey(typ, - message_digest_type, - salt_ptr, - data.as_ptr(), - data.len() as c_int, - count as c_int, - key.as_mut_ptr(), - iv.as_mut_ptr())); - - Ok(KeyIvPair { key: key, iv: iv }) - } -} - -/// Derives a key from a password and salt using the PBKDF2-HMAC-SHA1 algorithm. -pub fn pbkdf2_hmac_sha1(pass: &[u8], - salt: &[u8], - iter: usize, - keylen: usize) - -> Result, ErrorStack> { - unsafe { - let mut out = vec![0; keylen]; - - ffi::init(); - - try_ssl!(ffi::PKCS5_PBKDF2_HMAC_SHA1(pass.as_ptr(), - pass.len() as c_int, - salt.as_ptr(), - salt.len() as c_int, - iter as c_int, - keylen as c_int, - out.as_mut_ptr())); - Ok(out) - } -} - -/// 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, - hash: hash::Type, - keylen: usize) - -> Result, ErrorStack> { - unsafe { - let mut out = vec![0; keylen]; - ffi::init(); - try_ssl!(ffi::PKCS5_PBKDF2_HMAC(pass.as_ptr(), - pass.len() as c_int, - salt.as_ptr(), - salt.len() as c_int, - iter as c_int, - hash.evp_md(), - keylen as c_int, - out.as_mut_ptr())); - Ok(out) - } -} - -#[cfg(test)] -mod tests { - use crypto::hash; - use crypto::symm; - - // Test vectors from - // http://tools.ietf.org/html/draft-josefsson-pbkdf2-test-vectors-06 - #[test] - fn test_pbkdf2_hmac_sha1() { - assert_eq!(super::pbkdf2_hmac_sha1(b"password", b"salt", 1, 20).unwrap(), - vec![0x0c_u8, 0x60_u8, 0xc8_u8, 0x0f_u8, 0x96_u8, 0x1f_u8, 0x0e_u8, 0x71_u8, - 0xf3_u8, 0xa9_u8, 0xb5_u8, 0x24_u8, 0xaf_u8, 0x60_u8, 0x12_u8, 0x06_u8, - 0x2f_u8, 0xe0_u8, 0x37_u8, 0xa6_u8]); - - assert_eq!(super::pbkdf2_hmac_sha1(b"password", b"salt", 2, 20).unwrap(), - vec![0xea_u8, 0x6c_u8, 0x01_u8, 0x4d_u8, 0xc7_u8, 0x2d_u8, 0x6f_u8, 0x8c_u8, - 0xcd_u8, 0x1e_u8, 0xd9_u8, 0x2a_u8, 0xce_u8, 0x1d_u8, 0x41_u8, 0xf0_u8, - 0xd8_u8, 0xde_u8, 0x89_u8, 0x57_u8]); - - assert_eq!(super::pbkdf2_hmac_sha1(b"password", b"salt", 4096, 20).unwrap(), - vec![0x4b_u8, 0x00_u8, 0x79_u8, 0x01_u8, 0xb7_u8, 0x65_u8, 0x48_u8, 0x9a_u8, - 0xbe_u8, 0xad_u8, 0x49_u8, 0xd9_u8, 0x26_u8, 0xf7_u8, 0x21_u8, 0xd0_u8, - 0x65_u8, 0xa4_u8, 0x29_u8, 0xc1_u8]); - - assert_eq!(super::pbkdf2_hmac_sha1(b"password", b"salt", 16777216, 20).unwrap(), - vec![0xee_u8, 0xfe_u8, 0x3d_u8, 0x61_u8, 0xcd_u8, 0x4d_u8, 0xa4_u8, 0xe4_u8, - 0xe9_u8, 0x94_u8, 0x5b_u8, 0x3d_u8, 0x6b_u8, 0xa2_u8, 0x15_u8, 0x8c_u8, - 0x26_u8, 0x34_u8, 0xe9_u8, 0x84_u8]); - - assert_eq!(super::pbkdf2_hmac_sha1(b"passwordPASSWORDpassword", - b"saltSALTsaltSALTsaltSALTsaltSALTsalt", - 4096, - 25).unwrap(), - vec![0x3d_u8, 0x2e_u8, 0xec_u8, 0x4f_u8, 0xe4_u8, 0x1c_u8, 0x84_u8, 0x9b_u8, - 0x80_u8, 0xc8_u8, 0xd8_u8, 0x36_u8, 0x62_u8, 0xc0_u8, 0xe4_u8, 0x4a_u8, - 0x8b_u8, 0x29_u8, 0x1a_u8, 0x96_u8, 0x4c_u8, 0xf2_u8, 0xf0_u8, 0x70_u8, - 0x38_u8]); - - assert_eq!(super::pbkdf2_hmac_sha1(b"pass\x00word", b"sa\x00lt", 4096, 16).unwrap(), - vec![0x56_u8, 0xfa_u8, 0x6a_u8, 0xa7_u8, 0x55_u8, 0x48_u8, 0x09_u8, 0x9d_u8, - 0xcc_u8, 0x37_u8, 0xd7_u8, 0xf0_u8, 0x34_u8, 0x25_u8, 0xe0_u8, 0xc3_u8]); - } - - // 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, - 0xec_u8, 0x16_u8, 0x91_u8, 0xc2_u8, 0x25_u8, 0x44_u8, 0xb6_u8, 0x05_u8]); - - assert_eq!(super::pbkdf2_hmac(b"Password", b"NaCl", 80000, hash::Type::SHA256, 16).unwrap(), - vec![0x4d_u8, 0xdc_u8, 0xd8_u8, 0xf6_u8, 0x0b_u8, 0x98_u8, 0xbe_u8, 0x21_u8, - 0x83_u8, 0x0c_u8, 0xee_u8, 0x5e_u8, 0xf2_u8, 0x27_u8, 0x01_u8, 0xf9_u8]); - } - - // 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, - 0x94_u8, 0x77_u8, 0x1a_u8, 0x75_u8, 0x73_u8, 0x6b_u8, 0xb8_u8, 0x8b_u8, - 0xd3_u8, 0xc7_u8, 0xb3_u8, 0x82_u8, 0x70_u8, 0xcf_u8, 0xb5_u8, 0x0c_u8, - 0xb3_u8, 0x90_u8, 0xed_u8, 0x78_u8, 0xb3_u8, 0x05_u8, 0x65_u8, 0x6a_u8, - 0xf8_u8, 0x14_u8, 0x8e_u8, 0x52_u8, 0x45_u8, 0x2b_u8, 0x22_u8, 0x16_u8, - 0xb2_u8, 0xb8_u8, 0x09_u8, 0x8b_u8, 0x76_u8, 0x1f_u8, 0xc6_u8, 0x33_u8, - 0x60_u8, 0x60_u8, 0xa0_u8, 0x9f_u8, 0x76_u8, 0x41_u8, 0x5e_u8, 0x9f_u8, - 0x71_u8, 0xea_u8, 0x47_u8, 0xf9_u8, 0xe9_u8, 0x06_u8, 0x43_u8, 0x06_u8]); - - assert_eq!(super::pbkdf2_hmac(b"pass\0word", b"sa\0lt", 1, hash::Type::SHA512, 64).unwrap(), - vec![0x71_u8, 0xa0_u8, 0xec_u8, 0x84_u8, 0x2a_u8, 0xbd_u8, 0x5c_u8, 0x67_u8, - 0x8b_u8, 0xcf_u8, 0xd1_u8, 0x45_u8, 0xf0_u8, 0x9d_u8, 0x83_u8, 0x52_u8, - 0x2f_u8, 0x93_u8, 0x36_u8, 0x15_u8, 0x60_u8, 0x56_u8, 0x3c_u8, 0x4d_u8, - 0x0d_u8, 0x63_u8, 0xb8_u8, 0x83_u8, 0x29_u8, 0x87_u8, 0x10_u8, 0x90_u8, - 0xe7_u8, 0x66_u8, 0x04_u8, 0xa4_u8, 0x9a_u8, 0xf0_u8, 0x8f_u8, 0xe7_u8, - 0xc9_u8, 0xf5_u8, 0x71_u8, 0x56_u8, 0xc8_u8, 0x79_u8, 0x09_u8, 0x96_u8, - 0xb2_u8, 0x0f_u8, 0x06_u8, 0xbc_u8, 0x53_u8, 0x5e_u8, 0x5a_u8, 0xb5_u8, - 0x44_u8, 0x0d_u8, 0xf7_u8, 0xe8_u8, 0x78_u8, 0x29_u8, 0x6f_u8, 0xa7_u8]); - - assert_eq!(super::pbkdf2_hmac(b"passwordPASSWORDpassword", - b"salt\0\0\0", - 50, - hash::Type::SHA512, - 64).unwrap(), - vec![0x01_u8, 0x68_u8, 0x71_u8, 0xa4_u8, 0xc4_u8, 0xb7_u8, 0x5f_u8, 0x96_u8, - 0x85_u8, 0x7f_u8, 0xd2_u8, 0xb9_u8, 0xf8_u8, 0xca_u8, 0x28_u8, 0x02_u8, - 0x3b_u8, 0x30_u8, 0xee_u8, 0x2a_u8, 0x39_u8, 0xf5_u8, 0xad_u8, 0xca_u8, - 0xc8_u8, 0xc9_u8, 0x37_u8, 0x5f_u8, 0x9b_u8, 0xda_u8, 0x1c_u8, 0xcd_u8, - 0x1b_u8, 0x6f_u8, 0x0b_u8, 0x2f_u8, 0xc3_u8, 0xad_u8, 0xda_u8, 0x50_u8, - 0x54_u8, 0x12_u8, 0xe7_u8, 0x9d_u8, 0x89_u8, 0x00_u8, 0x56_u8, 0xc6_u8, - 0x2e_u8, 0x52_u8, 0x4c_u8, 0x7d_u8, 0x51_u8, 0x15_u8, 0x4b_u8, 0x1a_u8, - 0x85_u8, 0x34_u8, 0x57_u8, 0x5b_u8, 0xd0_u8, 0x2d_u8, 0xee_u8, 0x39_u8]); - } - #[test] - fn test_evp_bytes_to_key_pbkdf1_compatible() { - let salt = [16_u8, 34_u8, 19_u8, 23_u8, 141_u8, 4_u8, 207_u8, 221_u8]; - - let data = [143_u8, 210_u8, 75_u8, 63_u8, 214_u8, 179_u8, 155_u8, 241_u8, 242_u8, 31_u8, - 154_u8, 56_u8, 198_u8, 145_u8, 192_u8, 64_u8, 2_u8, 245_u8, 167_u8, 220_u8, - 55_u8, 119_u8, 233_u8, 136_u8, 139_u8, 27_u8, 71_u8, 242_u8, 119_u8, 175_u8, - 65_u8, 207_u8]; - - - - let expected_key = vec![249_u8, 115_u8, 114_u8, 97_u8, 32_u8, 213_u8, 165_u8, 146_u8, - 58_u8, 87_u8, 234_u8, 3_u8, 43_u8, 250_u8, 97_u8, 114_u8, 26_u8, - 98_u8, 245_u8, 246_u8, 238_u8, 177_u8, 229_u8, 161_u8, 183_u8, - 224_u8, 174_u8, 3_u8, 6_u8, 244_u8, 236_u8, 255_u8]; - let expected_iv = vec![4_u8, 223_u8, 153_u8, 219_u8, 28_u8, 142_u8, 234_u8, 68_u8, 227_u8, - 69_u8, 98_u8, 107_u8, 208_u8, 14_u8, 236_u8, 60_u8, 0_u8, 0_u8, - 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, - 0_u8, 0_u8, 0_u8]; - - assert_eq!(super::evp_bytes_to_key_pbkdf1_compatible(symm::Type::AES_256_CBC, - hash::Type::SHA1, - &data, - Some(&salt), - 1).unwrap(), - super::KeyIvPair { - key: expected_key, - iv: expected_iv, - }); - } -} diff --git a/openssl/src/crypto/pkey.rs b/openssl/src/crypto/pkey.rs deleted file mode 100644 index a2a6f9c1..00000000 --- a/openssl/src/crypto/pkey.rs +++ /dev/null @@ -1,166 +0,0 @@ -use libc::{c_void, c_char}; -use std::ptr; -use std::mem; -use ffi; - -use bio::{MemBio, MemBioSlice}; -use crypto::rsa::RSA; -use error::ErrorStack; -use crypto::util::{CallbackState, invoke_passwd_cb}; - -pub struct PKey(*mut ffi::EVP_PKEY); - -unsafe impl Send for PKey {} -unsafe impl Sync for PKey {} - -/// Represents a public key, optionally with a private key attached. -impl PKey { - /// Create a new `PKey` containing an RSA key. - pub fn from_rsa(rsa: RSA) -> Result { - unsafe { - let evp = try_ssl_null!(ffi::EVP_PKEY_new()); - let pkey = PKey(evp); - try_ssl!(ffi::EVP_PKEY_assign(pkey.0, ffi::EVP_PKEY_RSA, rsa.as_ptr() as *mut _)); - mem::forget(rsa); - Ok(pkey) - } - } - - pub unsafe fn from_ptr(handle: *mut ffi::EVP_PKEY) -> PKey { - PKey(handle) - } - - /// Reads private key from PEM, takes ownership of handle - pub fn private_key_from_pem(buf: &[u8]) -> Result { - ffi::init(); - let mem_bio = try!(MemBioSlice::new(buf)); - unsafe { - let evp = try_ssl_null!(ffi::PEM_read_bio_PrivateKey(mem_bio.as_ptr(), - ptr::null_mut(), - None, - ptr::null_mut())); - Ok(PKey::from_ptr(evp)) - } - } - - /// Read a private key from PEM, supplying a password callback to be invoked if the private key - /// is encrypted. - /// - /// The callback will be passed the password buffer and should return the number of characters - /// placed into the buffer. - pub fn private_key_from_pem_cb(buf: &[u8], pass_cb: F) -> Result - where F: FnOnce(&mut [c_char]) -> usize - { - ffi::init(); - let mut cb = CallbackState::new(pass_cb); - let mem_bio = try!(MemBioSlice::new(buf)); - unsafe { - let evp = try_ssl_null!(ffi::PEM_read_bio_PrivateKey(mem_bio.as_ptr(), - ptr::null_mut(), - Some(invoke_passwd_cb::), - &mut cb as *mut _ as *mut c_void)); - Ok(PKey::from_ptr(evp)) - } - } - - /// Reads public key from PEM, takes ownership of handle - pub fn public_key_from_pem(buf: &[u8]) -> Result { - ffi::init(); - let mem_bio = try!(MemBioSlice::new(buf)); - unsafe { - let evp = try_ssl_null!(ffi::PEM_read_bio_PUBKEY(mem_bio.as_ptr(), - ptr::null_mut(), - None, - ptr::null_mut())); - Ok(PKey::from_ptr(evp)) - } - } - - /// assign RSA key to this pkey - pub fn set_rsa(&mut self, rsa: &RSA) -> Result<(), ErrorStack> { - unsafe { - // this needs to be a reference as the set1_RSA ups the reference count - let rsa_ptr = rsa.as_ptr(); - try_ssl!(ffi::EVP_PKEY_set1_RSA(self.0, rsa_ptr)); - Ok(()) - } - } - - /// Get a reference to the interal RSA key for direct access to the key components - pub fn get_rsa(&self) -> Result { - unsafe { - let rsa = try_ssl_null!(ffi::EVP_PKEY_get1_RSA(self.0)); - // this is safe as the ffi increments a reference counter to the internal key - Ok(RSA::from_ptr(rsa)) - } - } - - /// Stores private key as a PEM - // FIXME: also add password and encryption - pub fn private_key_to_pem(&self) -> Result, ErrorStack> { - let mem_bio = try!(MemBio::new()); - unsafe { - try_ssl!(ffi::PEM_write_bio_PrivateKey(mem_bio.as_ptr(), - self.0, - ptr::null(), - ptr::null_mut(), - -1, - None, - ptr::null_mut())); - - } - Ok(mem_bio.get_buf().to_owned()) - } - - /// Stores public key as a PEM - pub fn public_key_to_pem(&self) -> Result, ErrorStack> { - let mem_bio = try!(MemBio::new()); - unsafe { try_ssl!(ffi::PEM_write_bio_PUBKEY(mem_bio.as_ptr(), self.0)) } - Ok(mem_bio.get_buf().to_owned()) - } - - pub fn as_ptr(&self) -> *mut ffi::EVP_PKEY { - return self.0; - } - - pub fn public_eq(&self, other: &PKey) -> bool { - unsafe { ffi::EVP_PKEY_cmp(self.0, other.0) == 1 } - } -} - -impl Drop for PKey { - fn drop(&mut self) { - unsafe { - ffi::EVP_PKEY_free(self.0); - } - } -} - -#[cfg(test)] -mod tests { - #[test] - fn test_private_key_from_pem() { - let key = include_bytes!("../../test/key.pem"); - super::PKey::private_key_from_pem(key).unwrap(); - } - - #[test] - fn test_public_key_from_pem() { - let key = include_bytes!("../../test/key.pem.pub"); - super::PKey::public_key_from_pem(key).unwrap(); - } - - #[test] - fn test_pem() { - let key = include_bytes!("../../test/key.pem"); - let key = super::PKey::private_key_from_pem(key).unwrap(); - - let priv_key = key.private_key_to_pem().unwrap(); - let pub_key = key.public_key_to_pem().unwrap(); - - // As a super-simple verification, just check that the buffers contain - // the `PRIVATE KEY` or `PUBLIC KEY` strings. - assert!(priv_key.windows(11).any(|s| s == b"PRIVATE KEY")); - assert!(pub_key.windows(10).any(|s| s == b"PUBLIC KEY")); - } -} diff --git a/openssl/src/crypto/rsa.rs b/openssl/src/crypto/rsa.rs deleted file mode 100644 index feb66a6f..00000000 --- a/openssl/src/crypto/rsa.rs +++ /dev/null @@ -1,337 +0,0 @@ -use ffi; -use std::fmt; -use std::ptr; -use std::mem; -use libc::{c_int, c_void, c_char, c_ulong}; - -use bn::{BigNum, BigNumRef}; -use bio::{MemBio, MemBioSlice}; -use error::ErrorStack; -use HashTypeInternals; -use crypto::hash; -use crypto::util::{CallbackState, invoke_passwd_cb}; - -pub struct RSA(*mut ffi::RSA); - -impl Drop for RSA { - fn drop(&mut self) { - unsafe { - ffi::RSA_free(self.0); - } - } -} - -impl RSA { - /// only useful for associating the key material directly with the key, it's safer to use - /// the supplied load and save methods for DER formatted keys. - pub fn from_public_components(n: BigNum, e: BigNum) -> Result { - 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)) - } - } - - pub fn from_private_components(n: BigNum, - e: BigNum, - d: BigNum, - p: BigNum, - q: BigNum, - dp: BigNum, - dq: BigNum, - qi: BigNum) - -> Result { - 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)) - } - } - - pub unsafe fn from_ptr(rsa: *mut ffi::RSA) -> RSA { - RSA(rsa) - } - - /// Generates a public/private key pair with the specified size. - /// - /// The public exponent will be 65537. - pub fn generate(bits: u32) -> Result { - 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)); - - try_ssl!(ffi::RSA_generate_key_ex(rsa.0, bits as c_int, e.as_ptr(), ptr::null_mut())); - - Ok(rsa) - } - } - - /// Reads an RSA private key from PEM formatted data. - pub fn private_key_from_pem(buf: &[u8]) -> Result { - let mem_bio = try!(MemBioSlice::new(buf)); - unsafe { - let rsa = try_ssl_null!(ffi::PEM_read_bio_RSAPrivateKey(mem_bio.as_ptr(), - ptr::null_mut(), - None, - ptr::null_mut())); - Ok(RSA(rsa)) - } - } - - /// Reads an RSA private key from PEM formatted data and supplies a password callback. - pub fn private_key_from_pem_cb(buf: &[u8], pass_cb: F) -> Result - where F: FnOnce(&mut [c_char]) -> usize - { - let mut cb = CallbackState::new(pass_cb); - let mem_bio = try!(MemBioSlice::new(buf)); - - unsafe { - let cb_ptr = &mut cb as *mut _ as *mut c_void; - let rsa = try_ssl_null!(ffi::PEM_read_bio_RSAPrivateKey(mem_bio.as_ptr(), - ptr::null_mut(), - Some(invoke_passwd_cb::), - cb_ptr)); - - Ok(RSA(rsa)) - } - } - - /// Reads an RSA public key from PEM formatted data. - pub fn public_key_from_pem(buf: &[u8]) -> Result { - let mem_bio = try!(MemBioSlice::new(buf)); - unsafe { - let rsa = try_ssl_null!(ffi::PEM_read_bio_RSA_PUBKEY(mem_bio.as_ptr(), - ptr::null_mut(), - None, - ptr::null_mut())); - Ok(RSA(rsa)) - } - } - - /// Writes an RSA private key as unencrypted PEM formatted data - pub fn private_key_to_pem(&self) -> Result, ErrorStack> { - let mem_bio = try!(MemBio::new()); - - unsafe { - try_ssl!(ffi::PEM_write_bio_RSAPrivateKey(mem_bio.as_ptr(), - self.0, - ptr::null(), - ptr::null_mut(), - 0, - None, - ptr::null_mut())); - } - Ok(mem_bio.get_buf().to_owned()) - } - - /// Writes an RSA public key as PEM formatted data - pub fn public_key_to_pem(&self) -> Result, ErrorStack> { - let mem_bio = try!(MemBio::new()); - - unsafe { - try_ssl!(ffi::PEM_write_bio_RSA_PUBKEY(mem_bio.as_ptr(), self.0)) - }; - - Ok(mem_bio.get_buf().to_owned()) - } - - pub fn size(&self) -> Option { - if self.n().is_some() { - unsafe { Some(ffi::RSA_size(self.0) as u32) } - } else { - None - } - } - - pub fn sign(&self, hash: hash::Type, message: &[u8]) -> Result, ErrorStack> { - let k_len = self.size().expect("RSA missing an n"); - let mut sig = vec![0; k_len as usize]; - let mut sig_len = k_len; - - unsafe { - try_ssl!(ffi::RSA_sign(hash.as_nid() as c_int, - message.as_ptr(), - message.len() as u32, - sig.as_mut_ptr(), - &mut sig_len, - self.0)); - assert!(sig_len == k_len); - Ok(sig) - } - } - - pub fn verify(&self, hash: hash::Type, message: &[u8], sig: &[u8]) -> Result<(), ErrorStack> { - unsafe { - try_ssl!(ffi::RSA_verify(hash.as_nid() as c_int, - message.as_ptr(), - message.len() as u32, - sig.as_ptr(), - sig.len() as u32, - self.0)); - } - Ok(()) - } - - pub fn as_ptr(&self) -> *mut ffi::RSA { - self.0 - } - - pub fn n<'a>(&'a self) -> Option> { - unsafe { - let n = (*self.0).n; - if n.is_null() { - None - } else { - Some(BigNumRef::from_ptr(n)) - } - } - } - - pub fn d<'a>(&self) -> Option> { - unsafe { - let d = (*self.0).d; - if d.is_null() { - None - } else { - Some(BigNumRef::from_ptr(d)) - } - } - } - - pub fn e<'a>(&'a self) -> Option> { - unsafe { - let e = (*self.0).e; - if e.is_null() { - None - } else { - Some(BigNumRef::from_ptr(e)) - } - } - } - - pub fn p<'a>(&'a self) -> Option> { - unsafe { - let p = (*self.0).p; - if p.is_null() { - None - } else { - Some(BigNumRef::from_ptr(p)) - } - } - } - - pub fn q<'a>(&'a self) -> Option> { - unsafe { - let q = (*self.0).q; - if q.is_null() { - None - } else { - Some(BigNumRef::from_ptr(q)) - } - } - } -} - -impl fmt::Debug for RSA { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "RSA") - } -} - -#[cfg(test)] -mod test { - use std::io::Write; - use libc::c_char; - - use super::*; - use crypto::hash::*; - - fn signing_input_rs256() -> Vec { - vec![101, 121, 74, 104, 98, 71, 99, 105, 79, 105, 74, 83, 85, 122, 73, 49, 78, 105, 74, 57, - 46, 101, 121, 74, 112, 99, 51, 77, 105, 79, 105, 74, 113, 98, 50, 85, 105, 76, 65, 48, - 75, 73, 67, 74, 108, 101, 72, 65, 105, 79, 106, 69, 122, 77, 68, 65, 52, 77, 84, 107, - 122, 79, 68, 65, 115, 68, 81, 111, 103, 73, 109, 104, 48, 100, 72, 65, 54, 76, 121, - 57, 108, 101, 71, 70, 116, 99, 71, 120, 108, 76, 109, 78, 118, 98, 83, 57, 112, 99, - 49, 57, 121, 98, 50, 57, 48, 73, 106, 112, 48, 99, 110, 86, 108, 102, 81] - } - - fn signature_rs256() -> Vec { - vec![112, 46, 33, 137, 67, 232, 143, 209, 30, 181, 216, 45, 191, 120, 69, 243, 65, 6, 174, - 27, 129, 255, 247, 115, 17, 22, 173, 209, 113, 125, 131, 101, 109, 66, 10, 253, 60, - 150, 238, 221, 115, 162, 102, 62, 81, 102, 104, 123, 0, 11, 135, 34, 110, 1, 135, 237, - 16, 115, 249, 69, 229, 130, 173, 252, 239, 22, 216, 90, 121, 142, 232, 198, 109, 219, - 61, 184, 151, 91, 23, 208, 148, 2, 190, 237, 213, 217, 217, 112, 7, 16, 141, 178, 129, - 96, 213, 248, 4, 12, 167, 68, 87, 98, 184, 31, 190, 127, 249, 217, 46, 10, 231, 111, - 36, 242, 91, 51, 187, 230, 244, 74, 230, 30, 177, 4, 10, 203, 32, 4, 77, 62, 249, 18, - 142, 212, 1, 48, 121, 91, 212, 189, 59, 65, 238, 202, 208, 102, 171, 101, 25, 129, - 253, 228, 141, 247, 127, 55, 45, 195, 139, 159, 175, 221, 59, 239, 177, 139, 93, 163, - 204, 60, 46, 176, 47, 158, 58, 65, 214, 18, 202, 173, 21, 145, 18, 115, 160, 95, 35, - 185, 232, 56, 250, 175, 132, 157, 105, 132, 41, 239, 90, 30, 136, 121, 130, 54, 195, - 212, 14, 96, 69, 34, 165, 68, 200, 242, 122, 122, 45, 184, 6, 99, 209, 108, 247, 202, - 234, 86, 222, 64, 92, 178, 33, 90, 69, 178, 194, 85, 102, 181, 90, 193, 167, 72, 160, - 112, 223, 200, 163, 42, 70, 149, 67, 208, 25, 238, 251, 71] - } - - #[test] - pub fn test_sign() { - let key = include_bytes!("../../test/rsa.pem"); - let private_key = RSA::private_key_from_pem(key).unwrap(); - - let mut sha = Hasher::new(Type::SHA256).unwrap(); - sha.write_all(&signing_input_rs256()).unwrap(); - let digest = sha.finish().unwrap(); - - let result = private_key.sign(Type::SHA256, &digest).unwrap(); - - assert_eq!(result, signature_rs256()); - } - - #[test] - pub fn test_verify() { - let key = include_bytes!("../../test/rsa.pem.pub"); - let public_key = RSA::public_key_from_pem(key).unwrap(); - - let mut sha = Hasher::new(Type::SHA256).unwrap(); - sha.write_all(&signing_input_rs256()).unwrap(); - let digest = sha.finish().unwrap(); - - assert!(public_key.verify(Type::SHA256, &digest, &signature_rs256()).is_ok()); - } - - #[test] - pub fn test_password() { - let mut password_queried = false; - let key = include_bytes!("../../test/rsa-encrypted.pem"); - RSA::private_key_from_pem_cb(key, |password| { - password_queried = true; - password[0] = b'm' as c_char; - password[1] = b'y' as c_char; - password[2] = b'p' as c_char; - password[3] = b'a' as c_char; - password[4] = b's' as c_char; - password[5] = b's' as c_char; - 6 - }).unwrap(); - - assert!(password_queried); - } -} diff --git a/openssl/src/dh.rs b/openssl/src/dh.rs new file mode 100644 index 00000000..5a07e50f --- /dev/null +++ b/openssl/src/dh.rs @@ -0,0 +1,145 @@ +use ffi; +use error::ErrorStack; +use bio::MemBioSlice; +use std::ptr; +use std::mem; + +use {cvt, cvt_p}; +use bio::MemBio; +use bn::BigNum; +use types::OpenSslTypeRef; + +type_!(Dh, DhRef, ffi::DH, ffi::DH_free); + +impl DhRef { + /// Encodes the parameters to PEM. + pub fn to_pem(&self) -> Result, ErrorStack> { + let mem_bio = try!(MemBio::new()); + + unsafe { + try!(cvt(ffi::PEM_write_bio_DHparams(mem_bio.as_ptr(), self.as_ptr()))); + } + + Ok(mem_bio.get_buf().to_owned()) + } +} + +impl Dh { + pub fn from_params(p: BigNum, g: BigNum, q: BigNum) -> Result { + unsafe { + let dh = Dh(try!(cvt_p(ffi::DH_new()))); + try!(cvt(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 { + let mem_bio = try!(MemBioSlice::new(buf)); + unsafe { + cvt_p(ffi::PEM_read_bio_DHparams(mem_bio.as_ptr(), + ptr::null_mut(), + None, + ptr::null_mut())) + .map(Dh) + } + } + + /// Requires the `v102` or `v110` features and OpenSSL 1.0.2 or OpenSSL 1.1.0. + #[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] + pub fn get_1024_160() -> Result { + unsafe { cvt_p(ffi::DH_get_1024_160()).map(Dh) } + } + + /// Requires the `v102` or `v110` features and OpenSSL 1.0.2 or OpenSSL 1.1.0. + #[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] + pub fn get_2048_224() -> Result { + unsafe { cvt_p(ffi::DH_get_2048_224()).map(Dh) } + } + + /// Requires the `v102` or `v110` features and OpenSSL 1.0.2 or OpenSSL 1.1.0. + #[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] + pub fn get_2048_256() -> Result { + unsafe { cvt_p(ffi::DH_get_2048_256()).map(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 dh::Dh; + use bn::BigNum; + use ssl::{SslMethod, SslContext}; + + #[test] + #[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] + fn test_dh_rfc5114() { + let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); + let dh1 = Dh::get_1024_160().unwrap(); + ctx.set_tmp_dh(&dh1).unwrap(); + let dh2 = Dh::get_2048_224().unwrap(); + ctx.set_tmp_dh(&dh2).unwrap(); + let dh3 = Dh::get_2048_256().unwrap(); + ctx.set_tmp_dh(&dh3).unwrap(); + } + + #[test] + fn test_dh() { + let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); + let p = BigNum::from_hex_str("87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435\ + E3B00E00DF8F1D61957D4FAF7DF4561B2AA3016C3D91134096FAA3BF429\ + 6D830E9A7C209E0C6497517ABD5A8A9D306BCF67ED91F9E6725B4758C02\ + 2E0B1EF4275BF7B6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF1230\ + 7F5C4FDB70C581B23F76B63ACAE1CAA6B7902D52526735488A0EF13C6D9\ + A51BFA4AB3AD8347796524D8EF6A167B5A41825D967E144E5140564251C\ + CACB83E6B486F6B3CA3F7971506026C0B857F689962856DED4010ABD0BE\ + 621C3A3960A54E710C375F26375D7014103A4B54330C198AF126116D227\ + 6E11715F693877FAD7EF09CADB094AE91E1A1597") + .unwrap(); + let g = BigNum::from_hex_str("3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF205407F4793A1A0\ + BA12510DBC15077BE463FFF4FED4AAC0BB555BE3A6C1B0C6B47B1BC3773\ + BF7E8C6F62901228F8C28CBB18A55AE31341000A650196F931C77A57F2D\ + DF463E5E9EC144B777DE62AAAB8A8628AC376D282D6ED3864E67982428E\ + BC831D14348F6F2F9193B5045AF2767164E1DFC967C1FB3F2E55A4BD1BF\ + FE83B9C80D052B985D182EA0ADB2A3B7313D3FE14C8484B1E052588B9B7\ + D2BBD2DF016199ECD06E1557CD0915B3353BBB64E0EC377FD028370DF92\ + B52C7891428CDC67EB6184B523D1DB246C32F63078490F00EF8D647D148\ + D47954515E2327CFEF98C582664B4C0F6CC41659") + .unwrap(); + let q = BigNum::from_hex_str("8CF83642A709A097B447997640129DA299B1A47D1EB3750BA308B0FE64F\ + 5FBD3") + .unwrap(); + let dh = Dh::from_params(p, g, q).unwrap(); + ctx.set_tmp_dh(&dh).unwrap(); + } + + #[test] + fn test_dh_from_pem() { + let mut ctx = SslContext::builder(SslMethod::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(); + } +} diff --git a/openssl/src/dh/mod.rs b/openssl/src/dh/mod.rs deleted file mode 100644 index e0cf885a..00000000 --- a/openssl/src/dh/mod.rs +++ /dev/null @@ -1,124 +0,0 @@ -use ffi; -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 { - 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)) - } - - pub fn from_pem(buf: &[u8]) -> Result { - let mem_bio = try!(MemBioSlice::new(buf)); - let dh = unsafe { - ffi::PEM_read_bio_DHparams(mem_bio.as_ptr(), ptr::null_mut(), None, ptr::null_mut()) - }; - try_ssl_null!(dh); - Ok(DH(dh)) - } - - #[cfg(feature = "rfc5114")] - pub fn get_1024_160() -> Result { - let dh = try_ssl_null!(unsafe { ffi::DH_get_1024_160() }); - Ok(DH(dh)) - } - - #[cfg(feature = "rfc5114")] - pub fn get_2048_224() -> Result { - let dh = try_ssl_null!(unsafe { ffi::DH_get_2048_224() }); - Ok(DH(dh)) - } - - #[cfg(feature = "rfc5114")] - pub fn get_2048_256() -> Result { - let dh = try_ssl_null!(unsafe { ffi::DH_get_2048_256() }); - Ok(DH(dh)) - } - - pub unsafe fn as_ptr(&self) -> *mut ffi::DH { - let DH(n) = *self; - n - } -} - -impl Drop for DH { - fn drop(&mut self) { - unsafe { - ffi::DH_free(self.as_ptr()) - } - } -} - -#[cfg(test)] -mod tests { - use super::DH; - use bn::BigNum; - use ssl::SslContext; - use ssl::SslMethod::Sslv23; - - #[test] - #[cfg(feature = "rfc5114")] - fn test_dh_rfc5114() { - let mut ctx = SslContext::new(Sslv23).unwrap(); - let dh1 = DH::get_1024_160().unwrap(); - ctx.set_tmp_dh(&dh1).unwrap(); - let dh2 = DH::get_2048_224().unwrap(); - ctx.set_tmp_dh(&dh2).unwrap(); - let dh3 = DH::get_2048_256().unwrap(); - ctx.set_tmp_dh(&dh3).unwrap(); - } - - #[test] - #[cfg(feature = "dh_from_params")] - fn test_dh() { - let mut ctx = SslContext::new(Sslv23).unwrap(); - let p = BigNum::from_hex_str("87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435\ - E3B00E00DF8F1D61957D4FAF7DF4561B2AA3016C3D91134096FAA3BF429\ - 6D830E9A7C209E0C6497517ABD5A8A9D306BCF67ED91F9E6725B4758C02\ - 2E0B1EF4275BF7B6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF1230\ - 7F5C4FDB70C581B23F76B63ACAE1CAA6B7902D52526735488A0EF13C6D9\ - A51BFA4AB3AD8347796524D8EF6A167B5A41825D967E144E5140564251C\ - CACB83E6B486F6B3CA3F7971506026C0B857F689962856DED4010ABD0BE\ - 621C3A3960A54E710C375F26375D7014103A4B54330C198AF126116D227\ - 6E11715F693877FAD7EF09CADB094AE91E1A1597") - .unwrap(); - let g = BigNum::from_hex_str("3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF205407F4793A1A0\ - BA12510DBC15077BE463FFF4FED4AAC0BB555BE3A6C1B0C6B47B1BC3773\ - BF7E8C6F62901228F8C28CBB18A55AE31341000A650196F931C77A57F2D\ - DF463E5E9EC144B777DE62AAAB8A8628AC376D282D6ED3864E67982428E\ - BC831D14348F6F2F9193B5045AF2767164E1DFC967C1FB3F2E55A4BD1BF\ - FE83B9C80D052B985D182EA0ADB2A3B7313D3FE14C8484B1E052588B9B7\ - D2BBD2DF016199ECD06E1557CD0915B3353BBB64E0EC377FD028370DF92\ - B52C7891428CDC67EB6184B523D1DB246C32F63078490F00EF8D647D148\ - D47954515E2327CFEF98C582664B4C0F6CC41659") - .unwrap(); - let q = BigNum::from_hex_str("8CF83642A709A097B447997640129DA299B1A47D1EB3750BA308B0FE64F\ - 5FBD3") - .unwrap(); - let dh = DH::from_params(p, g, q).unwrap(); - ctx.set_tmp_dh(&dh).unwrap(); - } - - #[test] - fn test_dh_from_pem() { - let mut ctx = SslContext::new(Sslv23).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(); - } -} diff --git a/openssl/src/dsa.rs b/openssl/src/dsa.rs new file mode 100644 index 00000000..9dd5669c --- /dev/null +++ b/openssl/src/dsa.rs @@ -0,0 +1,223 @@ +use error::ErrorStack; +use ffi; +use libc::{c_int, c_char, c_void}; +use std::fmt; +use std::ptr; + +use bio::{MemBio, MemBioSlice}; +use bn::BigNumRef; +use {cvt, cvt_p}; +use types::OpenSslTypeRef; +use util::{CallbackState, invoke_passwd_cb}; + +type_!(Dsa, DsaRef, ffi::DSA, ffi::DSA_free); + +impl DsaRef { + /// Writes an DSA private key as unencrypted PEM formatted data + pub fn private_key_to_pem(&self) -> Result, ErrorStack> { + assert!(self.has_private_key()); + let mem_bio = try!(MemBio::new()); + + unsafe { + try!(cvt(ffi::PEM_write_bio_DSAPrivateKey(mem_bio.as_ptr(), self.as_ptr(), + ptr::null(), ptr::null_mut(), 0, + None, ptr::null_mut()))) + }; + + Ok(mem_bio.get_buf().to_owned()) + } + + /// Writes an DSA public key as PEM formatted data + pub fn public_key_to_pem(&self) -> Result, ErrorStack> { + let mem_bio = try!(MemBio::new()); + unsafe { + try!(cvt(ffi::PEM_write_bio_DSA_PUBKEY(mem_bio.as_ptr(), self.as_ptr()))); + } + Ok(mem_bio.get_buf().to_owned()) + } + + pub fn size(&self) -> Option { + if self.q().is_some() { + unsafe { Some(ffi::DSA_size(self.as_ptr()) as u32) } + } else { + None + } + } + + pub fn p(&self) -> Option<&BigNumRef> { + unsafe { + let p = compat::pqg(self.as_ptr())[0]; + if p.is_null() { + None + } else { + Some(BigNumRef::from_ptr(p as *mut _)) + } + } + } + + pub fn q(&self) -> Option<&BigNumRef> { + unsafe { + let q = compat::pqg(self.as_ptr())[1]; + if q.is_null() { + None + } else { + Some(BigNumRef::from_ptr(q as *mut _)) + } + } + } + + pub fn g(&self) -> Option<&BigNumRef> { + unsafe { + let g = compat::pqg(self.as_ptr())[2]; + if g.is_null() { + None + } else { + Some(BigNumRef::from_ptr(g as *mut _)) + } + } + } + + pub fn has_public_key(&self) -> bool { + unsafe { !compat::keys(self.as_ptr())[0].is_null() } + } + + pub fn has_private_key(&self) -> bool { + unsafe { !compat::keys(self.as_ptr())[1].is_null() } + } +} + +impl Dsa { + /// Generate a DSA key pair. + pub fn generate(bits: u32) -> Result { + unsafe { + let dsa = Dsa(try!(cvt_p(ffi::DSA_new()))); + try!(cvt(ffi::DSA_generate_parameters_ex(dsa.0, + bits as c_int, + ptr::null(), + 0, + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut()))); + try!(cvt(ffi::DSA_generate_key(dsa.0))); + Ok(dsa) + } + } + + /// Reads a DSA private key from PEM formatted data. + pub fn private_key_from_pem(buf: &[u8]) -> Result { + ffi::init(); + let mem_bio = try!(MemBioSlice::new(buf)); + + unsafe { + let dsa = try!(cvt_p(ffi::PEM_read_bio_DSAPrivateKey(mem_bio.as_ptr(), + ptr::null_mut(), + None, + ptr::null_mut()))); + Ok(Dsa(dsa)) + } + } + + /// Read a private key from PEM supplying a password callback to be invoked if the private key + /// is encrypted. + /// + /// The callback will be passed the password buffer and should return the number of characters + /// placed into the buffer. + pub fn private_key_from_pem_cb(buf: &[u8], pass_cb: F) -> Result + where F: FnOnce(&mut [c_char]) -> usize + { + ffi::init(); + let mut cb = CallbackState::new(pass_cb); + let mem_bio = try!(MemBioSlice::new(buf)); + + unsafe { + let cb_ptr = &mut cb as *mut _ as *mut c_void; + let dsa = try!(cvt_p(ffi::PEM_read_bio_DSAPrivateKey(mem_bio.as_ptr(), + ptr::null_mut(), + Some(invoke_passwd_cb::), + cb_ptr))); + Ok(Dsa(dsa)) + } + } + + /// Reads an DSA public key from PEM formatted data. + pub fn public_key_from_pem(buf: &[u8]) -> Result { + ffi::init(); + + let mem_bio = try!(MemBioSlice::new(buf)); + unsafe { + let dsa = try!(cvt_p(ffi::PEM_read_bio_DSA_PUBKEY(mem_bio.as_ptr(), + ptr::null_mut(), + None, + ptr::null_mut()))); + Ok(Dsa(dsa)) + } + } +} + +impl fmt::Debug for Dsa { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "DSA") + } +} + +#[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] + } +} + +#[cfg(test)] +mod test { + use libc::c_char; + + use super::*; + + #[test] + pub fn test_generate() { + Dsa::generate(1024).unwrap(); + } + + #[test] + pub fn test_password() { + let mut password_queried = false; + let key = include_bytes!("../test/dsa-encrypted.pem"); + Dsa::private_key_from_pem_cb(key, |password| { + password_queried = true; + password[0] = b'm' as c_char; + password[1] = b'y' as c_char; + password[2] = b'p' as c_char; + password[3] = b'a' as c_char; + password[4] = b's' as c_char; + password[5] = b's' as c_char; + 6 + }) + .unwrap(); + + assert!(password_queried); + } +} diff --git a/openssl/src/ec_key.rs b/openssl/src/ec_key.rs new file mode 100644 index 00000000..41501c14 --- /dev/null +++ b/openssl/src/ec_key.rs @@ -0,0 +1,24 @@ +use ffi; + +use cvt_p; +use error::ErrorStack; +use nid::Nid; + +type_!(EcKey, EcKeyRef, ffi::EC_KEY, ffi::EC_KEY_free); + +impl EcKey { + pub fn new_by_curve_name(nid: Nid) -> Result { + unsafe { cvt_p(ffi::EC_KEY_new_by_curve_name(nid.as_raw())).map(EcKey) } + } +} + +#[cfg(test)] +mod test { + use nid; + use super::*; + + #[test] + fn new_by_curve_name() { + EcKey::new_by_curve_name(nid::X9_62_PRIME256V1).unwrap(); + } +} diff --git a/openssl/src/error.rs b/openssl/src/error.rs index d76e7cbd..4dd219af 100644 --- a/openssl/src/error.rs +++ b/openssl/src/error.rs @@ -71,44 +71,84 @@ impl Error { match unsafe { ffi::ERR_get_error() } { 0 => None, - err => Some((Error(err))), + err => Some(Error(err)), } } /// Returns the raw OpenSSL error code for this error. - pub fn error_code(&self) -> c_ulong { + pub fn code(&self) -> c_ulong { self.0 } - /// Returns the name of the library reporting the error. - pub fn library(&self) -> &'static str { - get_lib(self.0) + /// Returns the name of the library reporting the error, if available. + pub fn library(&self) -> Option<&'static str> { + unsafe { + let cstr = ffi::ERR_lib_error_string(self.0); + if cstr.is_null() { + return None; + } + let bytes = CStr::from_ptr(cstr as *const _).to_bytes(); + Some(str::from_utf8(bytes).unwrap()) + } } /// Returns the name of the function reporting the error. - pub fn function(&self) -> &'static str { - get_func(self.0) + pub fn function(&self) -> Option<&'static str> { + unsafe { + let cstr = ffi::ERR_func_error_string(self.0); + if cstr.is_null() { + return None; + } + let bytes = CStr::from_ptr(cstr as *const _).to_bytes(); + Some(str::from_utf8(bytes).unwrap()) + } } /// Returns the reason for the error. - pub fn reason(&self) -> &'static str { - get_reason(self.0) + pub fn reason(&self) -> Option<&'static str> { + unsafe { + let cstr = ffi::ERR_reason_error_string(self.0); + if cstr.is_null() { + return None; + } + let bytes = CStr::from_ptr(cstr as *const _).to_bytes(); + Some(str::from_utf8(bytes).unwrap()) + } } } impl fmt::Debug for Error { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_struct("Error") - .field("library", &self.library()) - .field("function", &self.function()) - .field("reason", &self.reason()) - .finish() + let mut builder = fmt.debug_struct("Error"); + builder.field("code", &self.code()); + if let Some(library) = self.library() { + builder.field("library", &library); + } + if let Some(function) = self.function() { + builder.field("function", &function); + } + if let Some(reason) = self.reason() { + builder.field("reason", &reason); + } + builder.finish() } } impl fmt::Display for Error { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.write_str(&self.reason()) + try!(write!(fmt, "error:{:08X}", self.0)); + match self.library() { + Some(l) => try!(write!(fmt, ":{}", l)), + None => try!(write!(fmt, ":lib({})", ffi::ERR_GET_LIB(self.0))), + } + match self.function() { + Some(f) => try!(write!(fmt, ":{}", f)), + None => try!(write!(fmt, ":func({})", ffi::ERR_GET_FUNC(self.0))), + } + match self.reason() { + Some(r) => write!(fmt, ":{}", r), + None => write!(fmt, ":reason({})", ffi::ERR_GET_FUNC(self.0)), + } } } @@ -117,28 +157,3 @@ impl error::Error for Error { "An OpenSSL error" } } - -fn get_lib(err: c_ulong) -> &'static str { - unsafe { - let cstr = ffi::ERR_lib_error_string(err); - let bytes = CStr::from_ptr(cstr as *const _).to_bytes(); - str::from_utf8(bytes).unwrap() - } -} - -fn get_func(err: c_ulong) -> &'static str { - unsafe { - let cstr = ffi::ERR_func_error_string(err); - let bytes = CStr::from_ptr(cstr as *const _).to_bytes(); - str::from_utf8(bytes).unwrap() - } -} - -fn get_reason(err: c_ulong) -> &'static str { - unsafe { - let cstr = ffi::ERR_reason_error_string(err); - let bytes = CStr::from_ptr(cstr as *const _).to_bytes(); - str::from_utf8(bytes).unwrap() - } -} - diff --git a/openssl/src/crypto/hash.rs b/openssl/src/hash.rs similarity index 54% rename from openssl/src/crypto/hash.rs rename to openssl/src/hash.rs index 207a55f5..6a13371d 100644 --- a/openssl/src/crypto/hash.rs +++ b/openssl/src/hash.rs @@ -1,51 +1,49 @@ -use libc::c_uint; use std::io::prelude::*; use std::io; -use std::ptr; -use std::cmp; use ffi; -use HashTypeInternals; +#[cfg(ossl110)] +use ffi::{EVP_MD_CTX_new, EVP_MD_CTX_free}; +#[cfg(any(ossl101, ossl102))] +use ffi::{EVP_MD_CTX_create as EVP_MD_CTX_new, EVP_MD_CTX_destroy as EVP_MD_CTX_free}; + +use {cvt, cvt_p}; use error::ErrorStack; -use nid::Nid; -/// Message digest (hash) type. #[derive(Copy, Clone)] -pub enum Type { - MD5, - SHA1, - SHA224, - SHA256, - SHA384, - SHA512, - RIPEMD160, -} +pub struct MessageDigest(*const ffi::EVP_MD); -impl HashTypeInternals for Type { - fn as_nid(&self) -> Nid { - match *self { - Type::MD5 => Nid::MD5, - Type::SHA1 => Nid::SHA1, - Type::SHA224 => Nid::SHA224, - Type::SHA256 => Nid::SHA256, - Type::SHA384 => Nid::SHA384, - Type::SHA512 => Nid::SHA512, - Type::RIPEMD160 => Nid::RIPEMD160, - } +impl MessageDigest { + pub fn md5() -> MessageDigest { + unsafe { MessageDigest(ffi::EVP_md5()) } } - fn evp_md(&self) -> *const ffi::EVP_MD { - unsafe { - match *self { - Type::MD5 => ffi::EVP_md5(), - Type::SHA1 => ffi::EVP_sha1(), - Type::SHA224 => ffi::EVP_sha224(), - Type::SHA256 => ffi::EVP_sha256(), - Type::SHA384 => ffi::EVP_sha384(), - Type::SHA512 => ffi::EVP_sha512(), - Type::RIPEMD160 => ffi::EVP_ripemd160(), - } - } + pub fn sha1() -> MessageDigest { + unsafe { MessageDigest(ffi::EVP_sha1()) } + } + + pub fn sha224() -> MessageDigest { + unsafe { MessageDigest(ffi::EVP_sha224()) } + } + + pub fn sha256() -> MessageDigest { + unsafe { MessageDigest(ffi::EVP_sha256()) } + } + + pub fn sha384() -> MessageDigest { + unsafe { MessageDigest(ffi::EVP_sha384()) } + } + + pub fn sha512() -> MessageDigest { + unsafe { MessageDigest(ffi::EVP_sha512()) } + } + + pub fn ripemd160() -> MessageDigest { + unsafe { MessageDigest(ffi::EVP_ripemd160()) } + } + + pub fn as_ptr(&self) -> *const ffi::EVP_MD { + self.0 } } @@ -65,20 +63,22 @@ use self::State::*; /// Calculate a hash in one go. /// /// ``` -/// use openssl::crypto::hash::{hash, Type}; +/// use openssl::hash::{hash, MessageDigest}; +/// /// let data = b"\x42\xF4\x97\xE0"; /// let spec = b"\x7c\x43\x0f\x17\x8a\xef\xdf\x14\x87\xfe\xe7\x14\x4e\x96\x41\xe2"; -/// let res = hash(Type::MD5, data).unwrap(); +/// let res = hash(MessageDigest::md5(), data).unwrap(); /// assert_eq!(res, spec); /// ``` /// /// Use the `Write` trait to supply the input in chunks. /// /// ``` -/// use openssl::crypto::hash::{Hasher, Type}; +/// use openssl::hash::{Hasher, MessageDigest}; +/// /// let data = [b"\x42\xF4", b"\x97\xE0"]; /// let spec = b"\x7c\x43\x0f\x17\x8a\xef\xdf\x14\x87\xfe\xe7\x14\x4e\x96\x41\xe2"; -/// let mut h = Hasher::new(Type::MD5).unwrap(); +/// let mut h = Hasher::new(MessageDigest::md5()).unwrap(); /// h.update(data[0]).unwrap(); /// h.update(data[1]).unwrap(); /// let res = h.finish().unwrap(); @@ -89,25 +89,24 @@ use self::State::*; /// /// Don't actually use MD5 and SHA-1 hashes, they're not secure anymore. /// -/// Don't ever hash passwords, use `crypto::pkcs5` or bcrypt/scrypt instead. +/// Don't ever hash passwords, use the functions in the `pkcs5` module or bcrypt/scrypt instead. pub struct Hasher { ctx: *mut ffi::EVP_MD_CTX, md: *const ffi::EVP_MD, - type_: Type, + type_: MessageDigest, state: State, } impl Hasher { /// Creates a new `Hasher` with the specified hash type. - pub fn new(ty: Type) -> Result { + pub fn new(ty: MessageDigest) -> Result { ffi::init(); - let ctx = unsafe { try_ssl_null!(ffi::EVP_MD_CTX_create()) }; - let md = ty.evp_md(); + let ctx = unsafe { try!(cvt_p(EVP_MD_CTX_new())) }; let mut h = Hasher { ctx: ctx, - md: md, + md: ty.as_ptr(), type_: ty, state: Finalized, }; @@ -123,22 +122,20 @@ impl Hasher { } Finalized => (), } - unsafe { try_ssl!(ffi::EVP_DigestInit_ex(self.ctx, self.md, 0 as *const _)); } + unsafe { + try!(cvt(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..]; + unsafe { + try!(cvt(ffi::EVP_DigestUpdate(self.ctx, data.as_ptr() as *mut _, data.len()))); } self.state = Updated; Ok(()) @@ -153,7 +150,7 @@ impl Hasher { unsafe { let mut len = ffi::EVP_MAX_MD_SIZE; let mut res = vec![0; len as usize]; - try_ssl!(ffi::EVP_DigestFinal_ex(self.ctx, res.as_mut_ptr(), &mut len)); + try!(cvt(ffi::EVP_DigestFinal_ex(self.ctx, res.as_mut_ptr(), &mut len))); res.truncate(len as usize); self.state = Finalized; Ok(res) @@ -176,7 +173,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 = EVP_MD_CTX_new(); assert!(!ctx.is_null()); let r = ffi::EVP_MD_CTX_copy_ex(ctx, self.ctx); assert_eq!(r, 1); @@ -197,13 +194,13 @@ impl Drop for Hasher { if self.state != Finalized { drop(self.finish()); } - ffi::EVP_MD_CTX_destroy(self.ctx); + EVP_MD_CTX_free(self.ctx); } } } /// Computes the hash of the `data` with the hash `t`. -pub fn hash(t: Type, data: &[u8]) -> Result, ErrorStack> { +pub fn hash(t: MessageDigest, data: &[u8]) -> Result, ErrorStack> { let mut h = try!(Hasher::new(t)); try!(h.update(data)); h.finish() @@ -212,10 +209,10 @@ pub fn hash(t: Type, data: &[u8]) -> Result, ErrorStack> { #[cfg(test)] mod tests { use serialize::hex::{FromHex, ToHex}; - use super::{hash, Hasher, Type}; + use super::{hash, Hasher, MessageDigest}; use std::io::prelude::*; - fn hash_test(hashtype: Type, hashtest: &(&str, &str)) { + fn hash_test(hashtype: MessageDigest, hashtest: &(&str, &str)) { let res = hash(hashtype, &*hashtest.0.from_hex().unwrap()).unwrap(); assert_eq!(res.to_hex(), hashtest.1); } @@ -228,43 +225,31 @@ mod tests { // Test vectors from http://www.nsrl.nist.gov/testdata/ #[allow(non_upper_case_globals)] - const md5_tests: [(&'static str, &'static str); 13] = [("", - "d41d8cd98f00b204e9800998ecf8427e"), - ("7F", - "83acb6e67e50e31db6ed341dd2de1595"), - ("EC9C", - "0b07f0d4ca797d8ac58874f887cb0b68"), - ("FEE57A", - "e0d583171eb06d56198fc0ef22173907"), - ("42F497E0", - "7c430f178aefdf1487fee7144e9641e2"), - ("C53B777F1C", - "75ef141d64cb37ec423da2d9d440c925"), - ("89D5B576327B", - "ebbaf15eb0ed784c6faa9dc32831bf33"), - ("5D4CCE781EB190", - "ce175c4b08172019f05e6b5279889f2c"), - ("81901FE94932D7B9", - "cd4d2f62b8cdb3a0cf968a735a239281"), - ("C9FFDEE7788EFB4EC9", - "e0841a231ab698db30c6c0f3f246c014"), - ("66AC4B7EBA95E53DC10B", - "a3b3cea71910d9af56742aa0bb2fe329"), - ("A510CD18F7A56852EB0319", - "577e216843dd11573574d3fb209b97d8"), - ("AAED18DBE8938C19ED734A8D", - "6f80fb775f27e0a4ce5c2f42fc72c5f1")]; + const md5_tests: [(&'static str, &'static str); 13] = + [("", "d41d8cd98f00b204e9800998ecf8427e"), + ("7F", "83acb6e67e50e31db6ed341dd2de1595"), + ("EC9C", "0b07f0d4ca797d8ac58874f887cb0b68"), + ("FEE57A", "e0d583171eb06d56198fc0ef22173907"), + ("42F497E0", "7c430f178aefdf1487fee7144e9641e2"), + ("C53B777F1C", "75ef141d64cb37ec423da2d9d440c925"), + ("89D5B576327B", "ebbaf15eb0ed784c6faa9dc32831bf33"), + ("5D4CCE781EB190", "ce175c4b08172019f05e6b5279889f2c"), + ("81901FE94932D7B9", "cd4d2f62b8cdb3a0cf968a735a239281"), + ("C9FFDEE7788EFB4EC9", "e0841a231ab698db30c6c0f3f246c014"), + ("66AC4B7EBA95E53DC10B", "a3b3cea71910d9af56742aa0bb2fe329"), + ("A510CD18F7A56852EB0319", "577e216843dd11573574d3fb209b97d8"), + ("AAED18DBE8938C19ED734A8D", "6f80fb775f27e0a4ce5c2f42fc72c5f1")]; #[test] fn test_md5() { for test in md5_tests.iter() { - hash_test(Type::MD5, test); + hash_test(MessageDigest::md5(), test); } } #[test] fn test_md5_recycle() { - let mut h = Hasher::new(Type::MD5).unwrap(); + let mut h = Hasher::new(MessageDigest::md5()).unwrap(); for test in md5_tests.iter() { hash_recycle_test(&mut h, test); } @@ -272,11 +257,11 @@ mod tests { #[test] fn test_finish_twice() { - let mut h = Hasher::new(Type::MD5).unwrap(); + let mut h = Hasher::new(MessageDigest::md5()).unwrap(); h.write_all(&*md5_tests[6].0.from_hex().unwrap()).unwrap(); h.finish().unwrap(); let res = h.finish().unwrap(); - let null = hash(Type::MD5, &[]).unwrap(); + let null = hash(MessageDigest::md5(), &[]).unwrap(); assert_eq!(res, null); } @@ -286,7 +271,7 @@ mod tests { let inp = md5_tests[i].0.from_hex().unwrap(); assert!(inp.len() > 2); let p = inp.len() / 2; - let h0 = Hasher::new(Type::MD5).unwrap(); + let h0 = Hasher::new(MessageDigest::md5()).unwrap(); println!("Clone a new hasher"); let mut h1 = h0.clone(); @@ -314,7 +299,7 @@ mod tests { let tests = [("616263", "a9993e364706816aba3e25717850c26c9cd0d89d")]; for test in tests.iter() { - hash_test(Type::SHA1, test); + hash_test(MessageDigest::sha1(), test); } } @@ -324,7 +309,7 @@ mod tests { "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad")]; for test in tests.iter() { - hash_test(Type::SHA256, test); + hash_test(MessageDigest::sha256(), test); } } @@ -333,7 +318,7 @@ mod tests { let tests = [("616263", "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc")]; for test in tests.iter() { - hash_test(Type::RIPEMD160, test); + hash_test(MessageDigest::ripemd160(), test); } } } diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs index 879681f4..a9d937ba 100644 --- a/openssl/src/lib.rs +++ b/openssl/src/lib.rs @@ -1,4 +1,4 @@ -#![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.8.3")] +#![doc(html_root_url="https://sfackler.github.io/rust-openssl/doc/v0.9.0")] #[macro_use] extern crate bitflags; @@ -11,29 +11,99 @@ extern crate openssl_sys as ffi; extern crate rustc_serialize as serialize; #[cfg(test)] -extern crate net2; +extern crate tempdir; #[doc(inline)] pub use ffi::init; -use nid::Nid; +use libc::c_int; -mod macros; +use error::ErrorStack; + +macro_rules! type_ { + ($n:ident, $r:ident, $c:path, $d:path) => { + pub struct $n(*mut $c); + + impl ::types::OpenSslType for $n { + type CType = $c; + type Ref = $r; + + unsafe fn from_ptr(ptr: *mut $c) -> $n { + $n(ptr) + } + } + + impl Drop for $n { + fn drop(&mut self) { + unsafe { $d(self.0) } + } + } + + impl ::std::ops::Deref for $n { + type Target = $r; + + fn deref(&self) -> &$r { + unsafe { ::types::OpenSslTypeRef::from_ptr(self.0) } + } + } + + impl ::std::ops::DerefMut for $n { + fn deref_mut(&mut self) -> &mut $r { + unsafe { ::types::OpenSslTypeRef::from_ptr_mut(self.0) } + } + } + + pub struct $r(::util::Opaque); + + impl ::types::OpenSslTypeRef for $r { + type CType = $c; + } + } +} -pub mod asn1; mod bio; +mod util; +pub mod asn1; pub mod bn; -#[cfg(feature = "c_helpers")] -mod c_helpers; pub mod crypto; pub mod dh; +pub mod dsa; +pub mod ec_key; pub mod error; +pub mod hash; +pub mod memcmp; pub mod nid; +pub mod pkcs12; +pub mod pkcs5; +pub mod pkey; +pub mod rand; +pub mod types; +pub mod rsa; +pub mod sign; pub mod ssl; +pub mod symm; pub mod version; pub mod x509; +pub mod stack; +#[cfg(any(ossl102, ossl110))] +mod verify; -trait HashTypeInternals { - fn as_nid(&self) -> Nid; - fn evp_md(&self) -> *const ffi::EVP_MD; +fn cvt_p(r: *mut T) -> Result<*mut T, ErrorStack> { + if r.is_null() { + Err(ErrorStack::get()) + } else { + Ok(r) + } +} + +fn cvt(r: c_int) -> Result { + if r <= 0 { + Err(ErrorStack::get()) + } else { + Ok(r) + } +} + +fn cvt_n(r: c_int) -> Result { + if r < 0 { Err(ErrorStack::get()) } else { Ok(r) } } diff --git a/openssl/src/macros.rs b/openssl/src/macros.rs deleted file mode 100644 index 35221f1c..00000000 --- a/openssl/src/macros.rs +++ /dev/null @@ -1,59 +0,0 @@ -#![macro_use] - -macro_rules! try_ssl_stream { - ($e:expr) => ( - match $e { - Ok(ok) => ok, - Err(err) => return Err(StreamError(err)) - } - ) -} - -/// Shortcut return with SSL error if something went wrong -macro_rules! try_ssl_if { - ($e:expr) => ( - if $e { - return Err(::error::ErrorStack::get().into()) - } - ) -} - -/// Shortcut return with SSL error if last error result is 0 -/// (default) -macro_rules! try_ssl{ - ($e:expr) => (try_ssl_if!($e == 0)) -} - -/// Shortcut return with SSL if got a null result -macro_rules! try_ssl_null{ - ($e:expr) => ({ - let t = $e; - try_ssl_if!(t == ptr::null_mut()); - t - }) -} - - -/// Lifts current SSL error code into Result<(), Error> -/// if expression is true -/// Lifting is actually a shortcut of the following form: -/// -/// ```ignore -/// let _ = try!(something) -/// Ok(()) -/// ``` -macro_rules! lift_ssl_if{ - ($e:expr) => ( { - if $e { - Err(::error::ErrorStack::get().into()) - } else { - Ok(()) - } - }) -} - -/// Lifts current SSL error code into Result<(), Error> -/// if SSL returned 0 (default error indication) -macro_rules! lift_ssl { - ($e:expr) => (lift_ssl_if!($e == 0)) -} diff --git a/openssl/src/crypto/memcmp.rs b/openssl/src/memcmp.rs similarity index 98% rename from openssl/src/crypto/memcmp.rs rename to openssl/src/memcmp.rs index cf08bdb5..0a7124bd 100644 --- a/openssl/src/crypto/memcmp.rs +++ b/openssl/src/memcmp.rs @@ -6,7 +6,7 @@ use ffi; /// This operation takes an amount of time dependent on the length of the two /// arrays given, but is independent of the contents of a and b. /// -/// # Failure +/// # Panics /// /// This function will panic the current task if `a` and `b` do not have the same /// length. diff --git a/openssl/src/nid.rs b/openssl/src/nid.rs index 874d4a6f..afbd60a5 100644 --- a/openssl/src/nid.rs +++ b/openssl/src/nid.rs @@ -1,196 +1,954 @@ -#[allow(non_camel_case_types)] -#[derive(Copy, Clone, Hash, PartialEq, Eq)] -#[repr(usize)] -pub enum Nid { - Undefined, // 0 - Rsadsi, - Pkcs, - MD2, - MD4, - MD5, - RC4, - RsaEncryption, - RSA_MD2, - RSA_MD5, - PBE_MD2_DES, // 10 - X500, - x509, - CN, - C, - L, - ST, - O, - OU, - RSA, - Pkcs7, // 20 - Pkcs7_data, - Pkcs7_signedData, - Pkcs7_envelopedData, - Pkcs7_signedAndEnvelopedData, - Pkcs7_digestData, - Pkcs7_encryptedData, - Pkcs3, - DhKeyAgreement, - DES_ECB, - DES_CFB, // 30 - DES_CBC, - DES_EDE, - DES_EDE3, - IDEA_CBC, - IDEA_CFB, - IDEA_ECB, - RC2_CBC, - RC2_ECB, - RC2_CFB, - RC2_OFB, // 40 - SHA, - RSA_SHA, - DES_EDE_CBC, - DES_EDE3_CBC, - DES_OFB, - IDEA_OFB, - Pkcs9, - Email, - UnstructuredName, - ContentType, // 50 - MessageDigest, - SigningTime, - CounterSignature, - ChallengePassword, - UnstructuredAddress, - ExtendedCertificateAttributes, - Netscape, - NetscapeCertExtention, - NetscapeDatatype, - DES_EDE_CFB64, // 60 - DES_EDE3_CFB64, - DES_EDE_OFB64, - DES_EDE3_OFB64, - SHA1, - RSA_SHA1, - DSA_SHA, - DSA_OLD, - PBE_SHA1_RC2_64, - PBKDF2, - DSA_SHA1_OLD, // 70 - NetscapeCertType, - NetscapeBaseUrl, - NetscapeRevocationUrl, - NetscapeCARevocationUrl, - NetscapeRenewalUrl, - NetscapeCAPolicyUrl, - NetscapeSSLServerName, - NetscapeComment, - NetscapeCertSequence, - DESX_CBC, // 80 - ID_CE, - SubjectKeyIdentifier, - KeyUsage, - PrivateKeyUsagePeriod, - SubjectAltName, - IssuerAltName, - BasicConstraints, - CrlNumber, - CertificatePolicies, - AuthorityKeyIdentifier, // 90 - BF_CBC, - BF_ECB, - BF_CFB, - BF_OFB, - MDC2, - RSA_MDC2, - RC4_40, - RC2_40_CBC, - G, - S, // 100 - I, - /// uniqueIdentifier - UID, - CrlDistributionPoints, - RSA_NP_MD5, - SN, - T, - D, - CAST5_CBC, - CAST5_ECB, - CAST5_CFB, // 110 - CAST5_OFB, - PbeWithMD5AndCast5CBC, - DSA_SHA1, - MD5_SHA1, - RSA_SHA1_2, - DSA, - RIPEMD160, - // 118 missing - RSA_RIPEMD160 = 119, - RC5_CBC, // 120 - RC5_ECB, - RC5_CFB, - RC5_OFB, - RLE, - ZLIB, - ExtendedKeyUsage, - PKIX, - ID_KP, - ServerAuth, - ClientAuth, // 130 - CodeSigning, - EmailProtection, - TimeStamping, - MsCodeInd, - MsCodeCom, - MsCtlSigh, - MsSGC, - MsEFS, - NsSGC, - DeltaCRL, // 140 - CRLReason, - InvalidityDate, - SXNetID, - PBE_SHA1_RC4_128, - PBE_SHA1_RC4_40, - PBE_SHA1_3DES, - PBE_SHA1_2DES, - PBE_SHA1_RC2_128, - PBE_SHA1_RC2_40, - KeyBag, // 150 - Pkcs8ShroudedKeyBag, - CertBag, - CrlBag, - SecretBag, - SafeContentsBag, - FriendlyName, - LocalKeyID, - X509Certificate, - SdsiCertificate, - X509Crl, // 160 - PBES2, - PBMAC1, - HmacWithSha1, - ID_QT_CPS, - ID_QT_UNOTICE, - RC2_64_CBC, - SMIMECaps, - PBE_MD2_RC2_64, - PBE_MD5_RC2_64, - PBE_SHA1_DES, - MicrosoftExtensionRequest, - ExtensionRequest, - Name, - DnQualifier, - IdPe, - IdAd, - AuthorityInfoAccess, - OCSP, - CaIssuers, - OCSPSigning, // 180 +use ffi; +use libc::c_int; - // 181 and up are from openssl's obj_mac.h - /// Shown as UID in cert subject - UserId = 458, +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct Nid(c_int); - SHA256 = 672, - SHA384, - SHA512, - SHA224, +#[allow(non_snake_case)] +impl Nid { + pub fn from_raw(raw: c_int) -> Nid { + Nid(raw) + } + + pub fn as_raw(&self) -> c_int { + self.0 + } } + +pub const UNDEF: Nid = Nid(ffi::NID_undef); +pub const ITU_T: Nid = Nid(ffi::NID_itu_t); +pub const CCITT: Nid = Nid(ffi::NID_ccitt); +pub const ISO: Nid = Nid(ffi::NID_iso); +pub const JOINT_ISO_ITU_T: Nid = Nid(ffi::NID_joint_iso_itu_t); +pub const JOINT_ISO_CCITT: Nid = Nid(ffi::NID_joint_iso_ccitt); +pub const MEMBER_BODY: Nid = Nid(ffi::NID_member_body); +pub const IDENTIFIED_ORGANIZATION: Nid = Nid(ffi::NID_identified_organization); +pub const HMAC_MD5: Nid = Nid(ffi::NID_hmac_md5); +pub const HMAC_SHA1: Nid = Nid(ffi::NID_hmac_sha1); +pub const CERTICOM_ARC: Nid = Nid(ffi::NID_certicom_arc); +pub const INTERNATIONAL_ORGANIZATIONS: Nid = Nid(ffi::NID_international_organizations); +pub const WAP: Nid = Nid(ffi::NID_wap); +pub const WAP_WSG: Nid = Nid(ffi::NID_wap_wsg); +pub const SELECTED_ATTRIBUTE_TYPES: Nid = Nid(ffi::NID_selected_attribute_types); +pub const CLEARANCE: Nid = Nid(ffi::NID_clearance); +pub const ISO_US: Nid = Nid(ffi::NID_ISO_US); +pub const X9_57: Nid = Nid(ffi::NID_X9_57); +pub const X9CM: Nid = Nid(ffi::NID_X9cm); +pub const DSA: Nid = Nid(ffi::NID_dsa); +pub const DSAWITHSHA1: Nid = Nid(ffi::NID_dsaWithSHA1); +pub const ANSI_X9_62: Nid = Nid(ffi::NID_ansi_X9_62); +pub const X9_62_PRIME_FIELD: Nid = Nid(ffi::NID_X9_62_prime_field); +pub const X9_62_CHARACTERISTIC_TWO_FIELD: Nid = Nid(ffi::NID_X9_62_characteristic_two_field); +pub const X9_62_ID_CHARACTERISTIC_TWO_BASIS: Nid = Nid(ffi::NID_X9_62_id_characteristic_two_basis); +pub const X9_62_ONBASIS: Nid = Nid(ffi::NID_X9_62_onBasis); +pub const X9_62_TPBASIS: Nid = Nid(ffi::NID_X9_62_tpBasis); +pub const X9_62_PPBASIS: Nid = Nid(ffi::NID_X9_62_ppBasis); +pub const X9_62_ID_ECPUBLICKEY: Nid = Nid(ffi::NID_X9_62_id_ecPublicKey); +pub const X9_62_C2PNB163V1: Nid = Nid(ffi::NID_X9_62_c2pnb163v1); +pub const X9_62_C2PNB163V2: Nid = Nid(ffi::NID_X9_62_c2pnb163v2); +pub const X9_62_C2PNB163V3: Nid = Nid(ffi::NID_X9_62_c2pnb163v3); +pub const X9_62_C2PNB176V1: Nid = Nid(ffi::NID_X9_62_c2pnb176v1); +pub const X9_62_C2TNB191V1: Nid = Nid(ffi::NID_X9_62_c2tnb191v1); +pub const X9_62_C2TNB191V2: Nid = Nid(ffi::NID_X9_62_c2tnb191v2); +pub const X9_62_C2TNB191V3: Nid = Nid(ffi::NID_X9_62_c2tnb191v3); +pub const X9_62_C2ONB191V4: Nid = Nid(ffi::NID_X9_62_c2onb191v4); +pub const X9_62_C2ONB191V5: Nid = Nid(ffi::NID_X9_62_c2onb191v5); +pub const X9_62_C2PNB208W1: Nid = Nid(ffi::NID_X9_62_c2pnb208w1); +pub const X9_62_C2TNB239V1: Nid = Nid(ffi::NID_X9_62_c2tnb239v1); +pub const X9_62_C2TNB239V2: Nid = Nid(ffi::NID_X9_62_c2tnb239v2); +pub const X9_62_C2TNB239V3: Nid = Nid(ffi::NID_X9_62_c2tnb239v3); +pub const X9_62_C2ONB239V4: Nid = Nid(ffi::NID_X9_62_c2onb239v4); +pub const X9_62_C2ONB239V5: Nid = Nid(ffi::NID_X9_62_c2onb239v5); +pub const X9_62_C2PNB272W1: Nid = Nid(ffi::NID_X9_62_c2pnb272w1); +pub const X9_62_C2PNB304W1: Nid = Nid(ffi::NID_X9_62_c2pnb304w1); +pub const X9_62_C2TNB359V1: Nid = Nid(ffi::NID_X9_62_c2tnb359v1); +pub const X9_62_C2PNB368W1: Nid = Nid(ffi::NID_X9_62_c2pnb368w1); +pub const X9_62_C2TNB431R1: Nid = Nid(ffi::NID_X9_62_c2tnb431r1); +pub const X9_62_PRIME192V1: Nid = Nid(ffi::NID_X9_62_prime192v1); +pub const X9_62_PRIME192V2: Nid = Nid(ffi::NID_X9_62_prime192v2); +pub const X9_62_PRIME192V3: Nid = Nid(ffi::NID_X9_62_prime192v3); +pub const X9_62_PRIME239V1: Nid = Nid(ffi::NID_X9_62_prime239v1); +pub const X9_62_PRIME239V2: Nid = Nid(ffi::NID_X9_62_prime239v2); +pub const X9_62_PRIME239V3: Nid = Nid(ffi::NID_X9_62_prime239v3); +pub const X9_62_PRIME256V1: Nid = Nid(ffi::NID_X9_62_prime256v1); +pub const ECDSA_WITH_SHA1: Nid = Nid(ffi::NID_ecdsa_with_SHA1); +pub const ECDSA_WITH_RECOMMENDED: Nid = Nid(ffi::NID_ecdsa_with_Recommended); +pub const ECDSA_WITH_SPECIFIED: Nid = Nid(ffi::NID_ecdsa_with_Specified); +pub const ECDSA_WITH_SHA224: Nid = Nid(ffi::NID_ecdsa_with_SHA224); +pub const ECDSA_WITH_SHA256: Nid = Nid(ffi::NID_ecdsa_with_SHA256); +pub const ECDSA_WITH_SHA384: Nid = Nid(ffi::NID_ecdsa_with_SHA384); +pub const ECDSA_WITH_SHA512: Nid = Nid(ffi::NID_ecdsa_with_SHA512); +pub const SECP112R1: Nid = Nid(ffi::NID_secp112r1); +pub const SECP112R2: Nid = Nid(ffi::NID_secp112r2); +pub const SECP128R1: Nid = Nid(ffi::NID_secp128r1); +pub const SECP128R2: Nid = Nid(ffi::NID_secp128r2); +pub const SECP160K1: Nid = Nid(ffi::NID_secp160k1); +pub const SECP160R1: Nid = Nid(ffi::NID_secp160r1); +pub const SECP160R2: Nid = Nid(ffi::NID_secp160r2); +pub const SECP192K1: Nid = Nid(ffi::NID_secp192k1); +pub const SECP224K1: Nid = Nid(ffi::NID_secp224k1); +pub const SECP224R1: Nid = Nid(ffi::NID_secp224r1); +pub const SECP256K1: Nid = Nid(ffi::NID_secp256k1); +pub const SECP384R1: Nid = Nid(ffi::NID_secp384r1); +pub const SECP521R1: Nid = Nid(ffi::NID_secp521r1); +pub const SECT113R1: Nid = Nid(ffi::NID_sect113r1); +pub const SECT113R2: Nid = Nid(ffi::NID_sect113r2); +pub const SECT131R1: Nid = Nid(ffi::NID_sect131r1); +pub const SECT131R2: Nid = Nid(ffi::NID_sect131r2); +pub const SECT163K1: Nid = Nid(ffi::NID_sect163k1); +pub const SECT163R1: Nid = Nid(ffi::NID_sect163r1); +pub const SECT163R2: Nid = Nid(ffi::NID_sect163r2); +pub const SECT193R1: Nid = Nid(ffi::NID_sect193r1); +pub const SECT193R2: Nid = Nid(ffi::NID_sect193r2); +pub const SECT233K1: Nid = Nid(ffi::NID_sect233k1); +pub const SECT233R1: Nid = Nid(ffi::NID_sect233r1); +pub const SECT239K1: Nid = Nid(ffi::NID_sect239k1); +pub const SECT283K1: Nid = Nid(ffi::NID_sect283k1); +pub const SECT283R1: Nid = Nid(ffi::NID_sect283r1); +pub const SECT409K1: Nid = Nid(ffi::NID_sect409k1); +pub const SECT409R1: Nid = Nid(ffi::NID_sect409r1); +pub const SECT571K1: Nid = Nid(ffi::NID_sect571k1); +pub const SECT571R1: Nid = Nid(ffi::NID_sect571r1); +pub const WAP_WSG_IDM_ECID_WTLS1: Nid = Nid(ffi::NID_wap_wsg_idm_ecid_wtls1); +pub const WAP_WSG_IDM_ECID_WTLS3: Nid = Nid(ffi::NID_wap_wsg_idm_ecid_wtls3); +pub const WAP_WSG_IDM_ECID_WTLS4: Nid = Nid(ffi::NID_wap_wsg_idm_ecid_wtls4); +pub const WAP_WSG_IDM_ECID_WTLS5: Nid = Nid(ffi::NID_wap_wsg_idm_ecid_wtls5); +pub const WAP_WSG_IDM_ECID_WTLS6: Nid = Nid(ffi::NID_wap_wsg_idm_ecid_wtls6); +pub const WAP_WSG_IDM_ECID_WTLS7: Nid = Nid(ffi::NID_wap_wsg_idm_ecid_wtls7); +pub const WAP_WSG_IDM_ECID_WTLS8: Nid = Nid(ffi::NID_wap_wsg_idm_ecid_wtls8); +pub const WAP_WSG_IDM_ECID_WTLS9: Nid = Nid(ffi::NID_wap_wsg_idm_ecid_wtls9); +pub const WAP_WSG_IDM_ECID_WTLS10: Nid = Nid(ffi::NID_wap_wsg_idm_ecid_wtls10); +pub const WAP_WSG_IDM_ECID_WTLS11: Nid = Nid(ffi::NID_wap_wsg_idm_ecid_wtls11); +pub const WAP_WSG_IDM_ECID_WTLS12: Nid = Nid(ffi::NID_wap_wsg_idm_ecid_wtls12); +pub const CAST5_CBC: Nid = Nid(ffi::NID_cast5_cbc); +pub const CAST5_ECB: Nid = Nid(ffi::NID_cast5_ecb); +pub const CAST5_CFB64: Nid = Nid(ffi::NID_cast5_cfb64); +pub const CAST5_OFB64: Nid = Nid(ffi::NID_cast5_ofb64); +pub const PBEWITHMD5ANDCAST5_CBC: Nid = Nid(ffi::NID_pbeWithMD5AndCast5_CBC); +pub const ID_PASSWORDBASEDMAC: Nid = Nid(ffi::NID_id_PasswordBasedMAC); +pub const ID_DHBASEDMAC: Nid = Nid(ffi::NID_id_DHBasedMac); +pub const RSADSI: Nid = Nid(ffi::NID_rsadsi); +pub const PKCS: Nid = Nid(ffi::NID_pkcs); +pub const PKCS1: Nid = Nid(ffi::NID_pkcs1); +pub const RSAENCRYPTION: Nid = Nid(ffi::NID_rsaEncryption); +pub const MD2WITHRSAENCRYPTION: Nid = Nid(ffi::NID_md2WithRSAEncryption); +pub const MD4WITHRSAENCRYPTION: Nid = Nid(ffi::NID_md4WithRSAEncryption); +pub const MD5WITHRSAENCRYPTION: Nid = Nid(ffi::NID_md5WithRSAEncryption); +pub const SHA1WITHRSAENCRYPTION: Nid = Nid(ffi::NID_sha1WithRSAEncryption); +pub const RSAESOAEP: Nid = Nid(ffi::NID_rsaesOaep); +pub const MGF1: Nid = Nid(ffi::NID_mgf1); +pub const RSASSAPSS: Nid = Nid(ffi::NID_rsassaPss); +pub const SHA256WITHRSAENCRYPTION: Nid = Nid(ffi::NID_sha256WithRSAEncryption); +pub const SHA384WITHRSAENCRYPTION: Nid = Nid(ffi::NID_sha384WithRSAEncryption); +pub const SHA512WITHRSAENCRYPTION: Nid = Nid(ffi::NID_sha512WithRSAEncryption); +pub const SHA224WITHRSAENCRYPTION: Nid = Nid(ffi::NID_sha224WithRSAEncryption); +pub const PKCS3: Nid = Nid(ffi::NID_pkcs3); +pub const DHKEYAGREEMENT: Nid = Nid(ffi::NID_dhKeyAgreement); +pub const PKCS5: Nid = Nid(ffi::NID_pkcs5); +pub const PBEWITHMD2ANDDES_CBC: Nid = Nid(ffi::NID_pbeWithMD2AndDES_CBC); +pub const PBEWITHMD5ANDDES_CBC: Nid = Nid(ffi::NID_pbeWithMD5AndDES_CBC); +pub const PBEWITHMD2ANDRC2_CBC: Nid = Nid(ffi::NID_pbeWithMD2AndRC2_CBC); +pub const PBEWITHMD5ANDRC2_CBC: Nid = Nid(ffi::NID_pbeWithMD5AndRC2_CBC); +pub const PBEWITHSHA1ANDDES_CBC: Nid = Nid(ffi::NID_pbeWithSHA1AndDES_CBC); +pub const PBEWITHSHA1ANDRC2_CBC: Nid = Nid(ffi::NID_pbeWithSHA1AndRC2_CBC); +pub const ID_PBKDF2: Nid = Nid(ffi::NID_id_pbkdf2); +pub const PBES2: Nid = Nid(ffi::NID_pbes2); +pub const PBMAC1: Nid = Nid(ffi::NID_pbmac1); +pub const PKCS7: Nid = Nid(ffi::NID_pkcs7); +pub const PKCS7_DATA: Nid = Nid(ffi::NID_pkcs7_data); +pub const PKCS7_SIGNED: Nid = Nid(ffi::NID_pkcs7_signed); +pub const PKCS7_ENVELOPED: Nid = Nid(ffi::NID_pkcs7_enveloped); +pub const PKCS7_SIGNEDANDENVELOPED: Nid = Nid(ffi::NID_pkcs7_signedAndEnveloped); +pub const PKCS7_DIGEST: Nid = Nid(ffi::NID_pkcs7_digest); +pub const PKCS7_ENCRYPTED: Nid = Nid(ffi::NID_pkcs7_encrypted); +pub const PKCS9: Nid = Nid(ffi::NID_pkcs9); +pub const PKCS9_EMAILADDRESS: Nid = Nid(ffi::NID_pkcs9_emailAddress); +pub const PKCS9_UNSTRUCTUREDNAME: Nid = Nid(ffi::NID_pkcs9_unstructuredName); +pub const PKCS9_CONTENTTYPE: Nid = Nid(ffi::NID_pkcs9_contentType); +pub const PKCS9_MESSAGEDIGEST: Nid = Nid(ffi::NID_pkcs9_messageDigest); +pub const PKCS9_SIGNINGTIME: Nid = Nid(ffi::NID_pkcs9_signingTime); +pub const PKCS9_COUNTERSIGNATURE: Nid = Nid(ffi::NID_pkcs9_countersignature); +pub const PKCS9_CHALLENGEPASSWORD: Nid = Nid(ffi::NID_pkcs9_challengePassword); +pub const PKCS9_UNSTRUCTUREDADDRESS: Nid = Nid(ffi::NID_pkcs9_unstructuredAddress); +pub const PKCS9_EXTCERTATTRIBUTES: Nid = Nid(ffi::NID_pkcs9_extCertAttributes); +pub const EXT_REQ: Nid = Nid(ffi::NID_ext_req); +pub const SMIMECAPABILITIES: Nid = Nid(ffi::NID_SMIMECapabilities); +pub const SMIME: Nid = Nid(ffi::NID_SMIME); +pub const ID_SMIME_MOD: Nid = Nid(ffi::NID_id_smime_mod); +pub const ID_SMIME_CT: Nid = Nid(ffi::NID_id_smime_ct); +pub const ID_SMIME_AA: Nid = Nid(ffi::NID_id_smime_aa); +pub const ID_SMIME_ALG: Nid = Nid(ffi::NID_id_smime_alg); +pub const ID_SMIME_CD: Nid = Nid(ffi::NID_id_smime_cd); +pub const ID_SMIME_SPQ: Nid = Nid(ffi::NID_id_smime_spq); +pub const ID_SMIME_CTI: Nid = Nid(ffi::NID_id_smime_cti); +pub const ID_SMIME_MOD_CMS: Nid = Nid(ffi::NID_id_smime_mod_cms); +pub const ID_SMIME_MOD_ESS: Nid = Nid(ffi::NID_id_smime_mod_ess); +pub const ID_SMIME_MOD_OID: Nid = Nid(ffi::NID_id_smime_mod_oid); +pub const ID_SMIME_MOD_MSG_V3: Nid = Nid(ffi::NID_id_smime_mod_msg_v3); +pub const ID_SMIME_MOD_ETS_ESIGNATURE_88: Nid = Nid(ffi::NID_id_smime_mod_ets_eSignature_88); +pub const ID_SMIME_MOD_ETS_ESIGNATURE_97: Nid = Nid(ffi::NID_id_smime_mod_ets_eSignature_97); +pub const ID_SMIME_MOD_ETS_ESIGPOLICY_88: Nid = Nid(ffi::NID_id_smime_mod_ets_eSigPolicy_88); +pub const ID_SMIME_MOD_ETS_ESIGPOLICY_97: Nid = Nid(ffi::NID_id_smime_mod_ets_eSigPolicy_97); +pub const ID_SMIME_CT_RECEIPT: Nid = Nid(ffi::NID_id_smime_ct_receipt); +pub const ID_SMIME_CT_AUTHDATA: Nid = Nid(ffi::NID_id_smime_ct_authData); +pub const ID_SMIME_CT_PUBLISHCERT: Nid = Nid(ffi::NID_id_smime_ct_publishCert); +pub const ID_SMIME_CT_TSTINFO: Nid = Nid(ffi::NID_id_smime_ct_TSTInfo); +pub const ID_SMIME_CT_TDTINFO: Nid = Nid(ffi::NID_id_smime_ct_TDTInfo); +pub const ID_SMIME_CT_CONTENTINFO: Nid = Nid(ffi::NID_id_smime_ct_contentInfo); +pub const ID_SMIME_CT_DVCSREQUESTDATA: Nid = Nid(ffi::NID_id_smime_ct_DVCSRequestData); +pub const ID_SMIME_CT_DVCSRESPONSEDATA: Nid = Nid(ffi::NID_id_smime_ct_DVCSResponseData); +pub const ID_SMIME_CT_COMPRESSEDDATA: Nid = Nid(ffi::NID_id_smime_ct_compressedData); +pub const ID_CT_ASCIITEXTWITHCRLF: Nid = Nid(ffi::NID_id_ct_asciiTextWithCRLF); +pub const ID_SMIME_AA_RECEIPTREQUEST: Nid = Nid(ffi::NID_id_smime_aa_receiptRequest); +pub const ID_SMIME_AA_SECURITYLABEL: Nid = Nid(ffi::NID_id_smime_aa_securityLabel); +pub const ID_SMIME_AA_MLEXPANDHISTORY: Nid = Nid(ffi::NID_id_smime_aa_mlExpandHistory); +pub const ID_SMIME_AA_CONTENTHINT: Nid = Nid(ffi::NID_id_smime_aa_contentHint); +pub const ID_SMIME_AA_MSGSIGDIGEST: Nid = Nid(ffi::NID_id_smime_aa_msgSigDigest); +pub const ID_SMIME_AA_ENCAPCONTENTTYPE: Nid = Nid(ffi::NID_id_smime_aa_encapContentType); +pub const ID_SMIME_AA_CONTENTIDENTIFIER: Nid = Nid(ffi::NID_id_smime_aa_contentIdentifier); +pub const ID_SMIME_AA_MACVALUE: Nid = Nid(ffi::NID_id_smime_aa_macValue); +pub const ID_SMIME_AA_EQUIVALENTLABELS: Nid = Nid(ffi::NID_id_smime_aa_equivalentLabels); +pub const ID_SMIME_AA_CONTENTREFERENCE: Nid = Nid(ffi::NID_id_smime_aa_contentReference); +pub const ID_SMIME_AA_ENCRYPKEYPREF: Nid = Nid(ffi::NID_id_smime_aa_encrypKeyPref); +pub const ID_SMIME_AA_SIGNINGCERTIFICATE: Nid = Nid(ffi::NID_id_smime_aa_signingCertificate); +pub const ID_SMIME_AA_SMIMEENCRYPTCERTS: Nid = Nid(ffi::NID_id_smime_aa_smimeEncryptCerts); +pub const ID_SMIME_AA_TIMESTAMPTOKEN: Nid = Nid(ffi::NID_id_smime_aa_timeStampToken); +pub const ID_SMIME_AA_ETS_SIGPOLICYID: Nid = Nid(ffi::NID_id_smime_aa_ets_sigPolicyId); +pub const ID_SMIME_AA_ETS_COMMITMENTTYPE: Nid = Nid(ffi::NID_id_smime_aa_ets_commitmentType); +pub const ID_SMIME_AA_ETS_SIGNERLOCATION: Nid = Nid(ffi::NID_id_smime_aa_ets_signerLocation); +pub const ID_SMIME_AA_ETS_SIGNERATTR: Nid = Nid(ffi::NID_id_smime_aa_ets_signerAttr); +pub const ID_SMIME_AA_ETS_OTHERSIGCERT: Nid = Nid(ffi::NID_id_smime_aa_ets_otherSigCert); +pub const ID_SMIME_AA_ETS_CONTENTTIMESTAMP: Nid = Nid(ffi::NID_id_smime_aa_ets_contentTimestamp); +pub const ID_SMIME_AA_ETS_CERTIFICATEREFS: Nid = Nid(ffi::NID_id_smime_aa_ets_CertificateRefs); +pub const ID_SMIME_AA_ETS_REVOCATIONREFS: Nid = Nid(ffi::NID_id_smime_aa_ets_RevocationRefs); +pub const ID_SMIME_AA_ETS_CERTVALUES: Nid = Nid(ffi::NID_id_smime_aa_ets_certValues); +pub const ID_SMIME_AA_ETS_REVOCATIONVALUES: Nid = Nid(ffi::NID_id_smime_aa_ets_revocationValues); +pub const ID_SMIME_AA_ETS_ESCTIMESTAMP: Nid = Nid(ffi::NID_id_smime_aa_ets_escTimeStamp); +pub const ID_SMIME_AA_ETS_CERTCRLTIMESTAMP: Nid = Nid(ffi::NID_id_smime_aa_ets_certCRLTimestamp); +pub const ID_SMIME_AA_ETS_ARCHIVETIMESTAMP: Nid = Nid(ffi::NID_id_smime_aa_ets_archiveTimeStamp); +pub const ID_SMIME_AA_SIGNATURETYPE: Nid = Nid(ffi::NID_id_smime_aa_signatureType); +pub const ID_SMIME_AA_DVCS_DVC: Nid = Nid(ffi::NID_id_smime_aa_dvcs_dvc); +pub const ID_SMIME_ALG_ESDHWITH3DES: Nid = Nid(ffi::NID_id_smime_alg_ESDHwith3DES); +pub const ID_SMIME_ALG_ESDHWITHRC2: Nid = Nid(ffi::NID_id_smime_alg_ESDHwithRC2); +pub const ID_SMIME_ALG_3DESWRAP: Nid = Nid(ffi::NID_id_smime_alg_3DESwrap); +pub const ID_SMIME_ALG_RC2WRAP: Nid = Nid(ffi::NID_id_smime_alg_RC2wrap); +pub const ID_SMIME_ALG_ESDH: Nid = Nid(ffi::NID_id_smime_alg_ESDH); +pub const ID_SMIME_ALG_CMS3DESWRAP: Nid = Nid(ffi::NID_id_smime_alg_CMS3DESwrap); +pub const ID_SMIME_ALG_CMSRC2WRAP: Nid = Nid(ffi::NID_id_smime_alg_CMSRC2wrap); +pub const ID_ALG_PWRI_KEK: Nid = Nid(ffi::NID_id_alg_PWRI_KEK); +pub const ID_SMIME_CD_LDAP: Nid = Nid(ffi::NID_id_smime_cd_ldap); +pub const ID_SMIME_SPQ_ETS_SQT_URI: Nid = Nid(ffi::NID_id_smime_spq_ets_sqt_uri); +pub const ID_SMIME_SPQ_ETS_SQT_UNOTICE: Nid = Nid(ffi::NID_id_smime_spq_ets_sqt_unotice); +pub const ID_SMIME_CTI_ETS_PROOFOFORIGIN: Nid = Nid(ffi::NID_id_smime_cti_ets_proofOfOrigin); +pub const ID_SMIME_CTI_ETS_PROOFOFRECEIPT: Nid = Nid(ffi::NID_id_smime_cti_ets_proofOfReceipt); +pub const ID_SMIME_CTI_ETS_PROOFOFDELIVERY: Nid = Nid(ffi::NID_id_smime_cti_ets_proofOfDelivery); +pub const ID_SMIME_CTI_ETS_PROOFOFSENDER: Nid = Nid(ffi::NID_id_smime_cti_ets_proofOfSender); +pub const ID_SMIME_CTI_ETS_PROOFOFAPPROVAL: Nid = Nid(ffi::NID_id_smime_cti_ets_proofOfApproval); +pub const ID_SMIME_CTI_ETS_PROOFOFCREATION: Nid = Nid(ffi::NID_id_smime_cti_ets_proofOfCreation); +pub const FRIENDLYNAME: Nid = Nid(ffi::NID_friendlyName); +pub const LOCALKEYID: Nid = Nid(ffi::NID_localKeyID); +pub const MS_CSP_NAME: Nid = Nid(ffi::NID_ms_csp_name); +pub const LOCALKEYSET: Nid = Nid(ffi::NID_LocalKeySet); +pub const X509CERTIFICATE: Nid = Nid(ffi::NID_x509Certificate); +pub const SDSICERTIFICATE: Nid = Nid(ffi::NID_sdsiCertificate); +pub const X509CRL: Nid = Nid(ffi::NID_x509Crl); +pub const PBE_WITHSHA1AND128BITRC4: Nid = Nid(ffi::NID_pbe_WithSHA1And128BitRC4); +pub const PBE_WITHSHA1AND40BITRC4: Nid = Nid(ffi::NID_pbe_WithSHA1And40BitRC4); +pub const PBE_WITHSHA1AND3_KEY_TRIPLEDES_CBC: Nid = + Nid(ffi::NID_pbe_WithSHA1And3_Key_TripleDES_CBC); +pub const PBE_WITHSHA1AND2_KEY_TRIPLEDES_CBC: Nid = + Nid(ffi::NID_pbe_WithSHA1And2_Key_TripleDES_CBC); +pub const PBE_WITHSHA1AND128BITRC2_CBC: Nid = Nid(ffi::NID_pbe_WithSHA1And128BitRC2_CBC); +pub const PBE_WITHSHA1AND40BITRC2_CBC: Nid = Nid(ffi::NID_pbe_WithSHA1And40BitRC2_CBC); +pub const KEYBAG: Nid = Nid(ffi::NID_keyBag); +pub const PKCS8SHROUDEDKEYBAG: Nid = Nid(ffi::NID_pkcs8ShroudedKeyBag); +pub const CERTBAG: Nid = Nid(ffi::NID_certBag); +pub const CRLBAG: Nid = Nid(ffi::NID_crlBag); +pub const SECRETBAG: Nid = Nid(ffi::NID_secretBag); +pub const SAFECONTENTSBAG: Nid = Nid(ffi::NID_safeContentsBag); +pub const MD2: Nid = Nid(ffi::NID_md2); +pub const MD4: Nid = Nid(ffi::NID_md4); +pub const MD5: Nid = Nid(ffi::NID_md5); +pub const MD5_SHA1: Nid = Nid(ffi::NID_md5_sha1); +pub const HMACWITHMD5: Nid = Nid(ffi::NID_hmacWithMD5); +pub const HMACWITHSHA1: Nid = Nid(ffi::NID_hmacWithSHA1); +pub const HMACWITHSHA224: Nid = Nid(ffi::NID_hmacWithSHA224); +pub const HMACWITHSHA256: Nid = Nid(ffi::NID_hmacWithSHA256); +pub const HMACWITHSHA384: Nid = Nid(ffi::NID_hmacWithSHA384); +pub const HMACWITHSHA512: Nid = Nid(ffi::NID_hmacWithSHA512); +pub const RC2_CBC: Nid = Nid(ffi::NID_rc2_cbc); +pub const RC2_ECB: Nid = Nid(ffi::NID_rc2_ecb); +pub const RC2_CFB64: Nid = Nid(ffi::NID_rc2_cfb64); +pub const RC2_OFB64: Nid = Nid(ffi::NID_rc2_ofb64); +pub const RC2_40_CBC: Nid = Nid(ffi::NID_rc2_40_cbc); +pub const RC2_64_CBC: Nid = Nid(ffi::NID_rc2_64_cbc); +pub const RC4: Nid = Nid(ffi::NID_rc4); +pub const RC4_40: Nid = Nid(ffi::NID_rc4_40); +pub const DES_EDE3_CBC: Nid = Nid(ffi::NID_des_ede3_cbc); +pub const RC5_CBC: Nid = Nid(ffi::NID_rc5_cbc); +pub const RC5_ECB: Nid = Nid(ffi::NID_rc5_ecb); +pub const RC5_CFB64: Nid = Nid(ffi::NID_rc5_cfb64); +pub const RC5_OFB64: Nid = Nid(ffi::NID_rc5_ofb64); +pub const MS_EXT_REQ: Nid = Nid(ffi::NID_ms_ext_req); +pub const MS_CODE_IND: Nid = Nid(ffi::NID_ms_code_ind); +pub const MS_CODE_COM: Nid = Nid(ffi::NID_ms_code_com); +pub const MS_CTL_SIGN: Nid = Nid(ffi::NID_ms_ctl_sign); +pub const MS_SGC: Nid = Nid(ffi::NID_ms_sgc); +pub const MS_EFS: Nid = Nid(ffi::NID_ms_efs); +pub const MS_SMARTCARD_LOGIN: Nid = Nid(ffi::NID_ms_smartcard_login); +pub const MS_UPN: Nid = Nid(ffi::NID_ms_upn); +pub const IDEA_CBC: Nid = Nid(ffi::NID_idea_cbc); +pub const IDEA_ECB: Nid = Nid(ffi::NID_idea_ecb); +pub const IDEA_CFB64: Nid = Nid(ffi::NID_idea_cfb64); +pub const IDEA_OFB64: Nid = Nid(ffi::NID_idea_ofb64); +pub const BF_CBC: Nid = Nid(ffi::NID_bf_cbc); +pub const BF_ECB: Nid = Nid(ffi::NID_bf_ecb); +pub const BF_CFB64: Nid = Nid(ffi::NID_bf_cfb64); +pub const BF_OFB64: Nid = Nid(ffi::NID_bf_ofb64); +pub const ID_PKIX: Nid = Nid(ffi::NID_id_pkix); +pub const ID_PKIX_MOD: Nid = Nid(ffi::NID_id_pkix_mod); +pub const ID_PE: Nid = Nid(ffi::NID_id_pe); +pub const ID_QT: Nid = Nid(ffi::NID_id_qt); +pub const ID_KP: Nid = Nid(ffi::NID_id_kp); +pub const ID_IT: Nid = Nid(ffi::NID_id_it); +pub const ID_PKIP: Nid = Nid(ffi::NID_id_pkip); +pub const ID_ALG: Nid = Nid(ffi::NID_id_alg); +pub const ID_CMC: Nid = Nid(ffi::NID_id_cmc); +pub const ID_ON: Nid = Nid(ffi::NID_id_on); +pub const ID_PDA: Nid = Nid(ffi::NID_id_pda); +pub const ID_ACA: Nid = Nid(ffi::NID_id_aca); +pub const ID_QCS: Nid = Nid(ffi::NID_id_qcs); +pub const ID_CCT: Nid = Nid(ffi::NID_id_cct); +pub const ID_PPL: Nid = Nid(ffi::NID_id_ppl); +pub const ID_AD: Nid = Nid(ffi::NID_id_ad); +pub const ID_PKIX1_EXPLICIT_88: Nid = Nid(ffi::NID_id_pkix1_explicit_88); +pub const ID_PKIX1_IMPLICIT_88: Nid = Nid(ffi::NID_id_pkix1_implicit_88); +pub const ID_PKIX1_EXPLICIT_93: Nid = Nid(ffi::NID_id_pkix1_explicit_93); +pub const ID_PKIX1_IMPLICIT_93: Nid = Nid(ffi::NID_id_pkix1_implicit_93); +pub const ID_MOD_CRMF: Nid = Nid(ffi::NID_id_mod_crmf); +pub const ID_MOD_CMC: Nid = Nid(ffi::NID_id_mod_cmc); +pub const ID_MOD_KEA_PROFILE_88: Nid = Nid(ffi::NID_id_mod_kea_profile_88); +pub const ID_MOD_KEA_PROFILE_93: Nid = Nid(ffi::NID_id_mod_kea_profile_93); +pub const ID_MOD_CMP: Nid = Nid(ffi::NID_id_mod_cmp); +pub const ID_MOD_QUALIFIED_CERT_88: Nid = Nid(ffi::NID_id_mod_qualified_cert_88); +pub const ID_MOD_QUALIFIED_CERT_93: Nid = Nid(ffi::NID_id_mod_qualified_cert_93); +pub const ID_MOD_ATTRIBUTE_CERT: Nid = Nid(ffi::NID_id_mod_attribute_cert); +pub const ID_MOD_TIMESTAMP_PROTOCOL: Nid = Nid(ffi::NID_id_mod_timestamp_protocol); +pub const ID_MOD_OCSP: Nid = Nid(ffi::NID_id_mod_ocsp); +pub const ID_MOD_DVCS: Nid = Nid(ffi::NID_id_mod_dvcs); +pub const ID_MOD_CMP2000: Nid = Nid(ffi::NID_id_mod_cmp2000); +pub const INFO_ACCESS: Nid = Nid(ffi::NID_info_access); +pub const BIOMETRICINFO: Nid = Nid(ffi::NID_biometricInfo); +pub const QCSTATEMENTS: Nid = Nid(ffi::NID_qcStatements); +pub const AC_AUDITENTITY: Nid = Nid(ffi::NID_ac_auditEntity); +pub const AC_TARGETING: Nid = Nid(ffi::NID_ac_targeting); +pub const AACONTROLS: Nid = Nid(ffi::NID_aaControls); +pub const SBGP_IPADDRBLOCK: Nid = Nid(ffi::NID_sbgp_ipAddrBlock); +pub const SBGP_AUTONOMOUSSYSNUM: Nid = Nid(ffi::NID_sbgp_autonomousSysNum); +pub const SBGP_ROUTERIDENTIFIER: Nid = Nid(ffi::NID_sbgp_routerIdentifier); +pub const AC_PROXYING: Nid = Nid(ffi::NID_ac_proxying); +pub const SINFO_ACCESS: Nid = Nid(ffi::NID_sinfo_access); +pub const PROXYCERTINFO: Nid = Nid(ffi::NID_proxyCertInfo); +pub const ID_QT_CPS: Nid = Nid(ffi::NID_id_qt_cps); +pub const ID_QT_UNOTICE: Nid = Nid(ffi::NID_id_qt_unotice); +pub const TEXTNOTICE: Nid = Nid(ffi::NID_textNotice); +pub const SERVER_AUTH: Nid = Nid(ffi::NID_server_auth); +pub const CLIENT_AUTH: Nid = Nid(ffi::NID_client_auth); +pub const CODE_SIGN: Nid = Nid(ffi::NID_code_sign); +pub const EMAIL_PROTECT: Nid = Nid(ffi::NID_email_protect); +pub const IPSECENDSYSTEM: Nid = Nid(ffi::NID_ipsecEndSystem); +pub const IPSECTUNNEL: Nid = Nid(ffi::NID_ipsecTunnel); +pub const IPSECUSER: Nid = Nid(ffi::NID_ipsecUser); +pub const TIME_STAMP: Nid = Nid(ffi::NID_time_stamp); +pub const OCSP_SIGN: Nid = Nid(ffi::NID_OCSP_sign); +pub const DVCS: Nid = Nid(ffi::NID_dvcs); +pub const ID_IT_CAPROTENCCERT: Nid = Nid(ffi::NID_id_it_caProtEncCert); +pub const ID_IT_SIGNKEYPAIRTYPES: Nid = Nid(ffi::NID_id_it_signKeyPairTypes); +pub const ID_IT_ENCKEYPAIRTYPES: Nid = Nid(ffi::NID_id_it_encKeyPairTypes); +pub const ID_IT_PREFERREDSYMMALG: Nid = Nid(ffi::NID_id_it_preferredSymmAlg); +pub const ID_IT_CAKEYUPDATEINFO: Nid = Nid(ffi::NID_id_it_caKeyUpdateInfo); +pub const ID_IT_CURRENTCRL: Nid = Nid(ffi::NID_id_it_currentCRL); +pub const ID_IT_UNSUPPORTEDOIDS: Nid = Nid(ffi::NID_id_it_unsupportedOIDs); +pub const ID_IT_SUBSCRIPTIONREQUEST: Nid = Nid(ffi::NID_id_it_subscriptionRequest); +pub const ID_IT_SUBSCRIPTIONRESPONSE: Nid = Nid(ffi::NID_id_it_subscriptionResponse); +pub const ID_IT_KEYPAIRPARAMREQ: Nid = Nid(ffi::NID_id_it_keyPairParamReq); +pub const ID_IT_KEYPAIRPARAMREP: Nid = Nid(ffi::NID_id_it_keyPairParamRep); +pub const ID_IT_REVPASSPHRASE: Nid = Nid(ffi::NID_id_it_revPassphrase); +pub const ID_IT_IMPLICITCONFIRM: Nid = Nid(ffi::NID_id_it_implicitConfirm); +pub const ID_IT_CONFIRMWAITTIME: Nid = Nid(ffi::NID_id_it_confirmWaitTime); +pub const ID_IT_ORIGPKIMESSAGE: Nid = Nid(ffi::NID_id_it_origPKIMessage); +pub const ID_IT_SUPPLANGTAGS: Nid = Nid(ffi::NID_id_it_suppLangTags); +pub const ID_REGCTRL: Nid = Nid(ffi::NID_id_regCtrl); +pub const ID_REGINFO: Nid = Nid(ffi::NID_id_regInfo); +pub const ID_REGCTRL_REGTOKEN: Nid = Nid(ffi::NID_id_regCtrl_regToken); +pub const ID_REGCTRL_AUTHENTICATOR: Nid = Nid(ffi::NID_id_regCtrl_authenticator); +pub const ID_REGCTRL_PKIPUBLICATIONINFO: Nid = Nid(ffi::NID_id_regCtrl_pkiPublicationInfo); +pub const ID_REGCTRL_PKIARCHIVEOPTIONS: Nid = Nid(ffi::NID_id_regCtrl_pkiArchiveOptions); +pub const ID_REGCTRL_OLDCERTID: Nid = Nid(ffi::NID_id_regCtrl_oldCertID); +pub const ID_REGCTRL_PROTOCOLENCRKEY: Nid = Nid(ffi::NID_id_regCtrl_protocolEncrKey); +pub const ID_REGINFO_UTF8PAIRS: Nid = Nid(ffi::NID_id_regInfo_utf8Pairs); +pub const ID_REGINFO_CERTREQ: Nid = Nid(ffi::NID_id_regInfo_certReq); +pub const ID_ALG_DES40: Nid = Nid(ffi::NID_id_alg_des40); +pub const ID_ALG_NOSIGNATURE: Nid = Nid(ffi::NID_id_alg_noSignature); +pub const ID_ALG_DH_SIG_HMAC_SHA1: Nid = Nid(ffi::NID_id_alg_dh_sig_hmac_sha1); +pub const ID_ALG_DH_POP: Nid = Nid(ffi::NID_id_alg_dh_pop); +pub const ID_CMC_STATUSINFO: Nid = Nid(ffi::NID_id_cmc_statusInfo); +pub const ID_CMC_IDENTIFICATION: Nid = Nid(ffi::NID_id_cmc_identification); +pub const ID_CMC_IDENTITYPROOF: Nid = Nid(ffi::NID_id_cmc_identityProof); +pub const ID_CMC_DATARETURN: Nid = Nid(ffi::NID_id_cmc_dataReturn); +pub const ID_CMC_TRANSACTIONID: Nid = Nid(ffi::NID_id_cmc_transactionId); +pub const ID_CMC_SENDERNONCE: Nid = Nid(ffi::NID_id_cmc_senderNonce); +pub const ID_CMC_RECIPIENTNONCE: Nid = Nid(ffi::NID_id_cmc_recipientNonce); +pub const ID_CMC_ADDEXTENSIONS: Nid = Nid(ffi::NID_id_cmc_addExtensions); +pub const ID_CMC_ENCRYPTEDPOP: Nid = Nid(ffi::NID_id_cmc_encryptedPOP); +pub const ID_CMC_DECRYPTEDPOP: Nid = Nid(ffi::NID_id_cmc_decryptedPOP); +pub const ID_CMC_LRAPOPWITNESS: Nid = Nid(ffi::NID_id_cmc_lraPOPWitness); +pub const ID_CMC_GETCERT: Nid = Nid(ffi::NID_id_cmc_getCert); +pub const ID_CMC_GETCRL: Nid = Nid(ffi::NID_id_cmc_getCRL); +pub const ID_CMC_REVOKEREQUEST: Nid = Nid(ffi::NID_id_cmc_revokeRequest); +pub const ID_CMC_REGINFO: Nid = Nid(ffi::NID_id_cmc_regInfo); +pub const ID_CMC_RESPONSEINFO: Nid = Nid(ffi::NID_id_cmc_responseInfo); +pub const ID_CMC_QUERYPENDING: Nid = Nid(ffi::NID_id_cmc_queryPending); +pub const ID_CMC_POPLINKRANDOM: Nid = Nid(ffi::NID_id_cmc_popLinkRandom); +pub const ID_CMC_POPLINKWITNESS: Nid = Nid(ffi::NID_id_cmc_popLinkWitness); +pub const ID_CMC_CONFIRMCERTACCEPTANCE: Nid = Nid(ffi::NID_id_cmc_confirmCertAcceptance); +pub const ID_ON_PERSONALDATA: Nid = Nid(ffi::NID_id_on_personalData); +pub const ID_ON_PERMANENTIDENTIFIER: Nid = Nid(ffi::NID_id_on_permanentIdentifier); +pub const ID_PDA_DATEOFBIRTH: Nid = Nid(ffi::NID_id_pda_dateOfBirth); +pub const ID_PDA_PLACEOFBIRTH: Nid = Nid(ffi::NID_id_pda_placeOfBirth); +pub const ID_PDA_GENDER: Nid = Nid(ffi::NID_id_pda_gender); +pub const ID_PDA_COUNTRYOFCITIZENSHIP: Nid = Nid(ffi::NID_id_pda_countryOfCitizenship); +pub const ID_PDA_COUNTRYOFRESIDENCE: Nid = Nid(ffi::NID_id_pda_countryOfResidence); +pub const ID_ACA_AUTHENTICATIONINFO: Nid = Nid(ffi::NID_id_aca_authenticationInfo); +pub const ID_ACA_ACCESSIDENTITY: Nid = Nid(ffi::NID_id_aca_accessIdentity); +pub const ID_ACA_CHARGINGIDENTITY: Nid = Nid(ffi::NID_id_aca_chargingIdentity); +pub const ID_ACA_GROUP: Nid = Nid(ffi::NID_id_aca_group); +pub const ID_ACA_ROLE: Nid = Nid(ffi::NID_id_aca_role); +pub const ID_ACA_ENCATTRS: Nid = Nid(ffi::NID_id_aca_encAttrs); +pub const ID_QCS_PKIXQCSYNTAX_V1: Nid = Nid(ffi::NID_id_qcs_pkixQCSyntax_v1); +pub const ID_CCT_CRS: Nid = Nid(ffi::NID_id_cct_crs); +pub const ID_CCT_PKIDATA: Nid = Nid(ffi::NID_id_cct_PKIData); +pub const ID_CCT_PKIRESPONSE: Nid = Nid(ffi::NID_id_cct_PKIResponse); +pub const ID_PPL_ANYLANGUAGE: Nid = Nid(ffi::NID_id_ppl_anyLanguage); +pub const ID_PPL_INHERITALL: Nid = Nid(ffi::NID_id_ppl_inheritAll); +pub const INDEPENDENT: Nid = Nid(ffi::NID_Independent); +pub const AD_OCSP: Nid = Nid(ffi::NID_ad_OCSP); +pub const AD_CA_ISSUERS: Nid = Nid(ffi::NID_ad_ca_issuers); +pub const AD_TIMESTAMPING: Nid = Nid(ffi::NID_ad_timeStamping); +pub const AD_DVCS: Nid = Nid(ffi::NID_ad_dvcs); +pub const CAREPOSITORY: Nid = Nid(ffi::NID_caRepository); +pub const ID_PKIX_OCSP_BASIC: Nid = Nid(ffi::NID_id_pkix_OCSP_basic); +pub const ID_PKIX_OCSP_NONCE: Nid = Nid(ffi::NID_id_pkix_OCSP_Nonce); +pub const ID_PKIX_OCSP_CRLID: Nid = Nid(ffi::NID_id_pkix_OCSP_CrlID); +pub const ID_PKIX_OCSP_ACCEPTABLERESPONSES: Nid = Nid(ffi::NID_id_pkix_OCSP_acceptableResponses); +pub const ID_PKIX_OCSP_NOCHECK: Nid = Nid(ffi::NID_id_pkix_OCSP_noCheck); +pub const ID_PKIX_OCSP_ARCHIVECUTOFF: Nid = Nid(ffi::NID_id_pkix_OCSP_archiveCutoff); +pub const ID_PKIX_OCSP_SERVICELOCATOR: Nid = Nid(ffi::NID_id_pkix_OCSP_serviceLocator); +pub const ID_PKIX_OCSP_EXTENDEDSTATUS: Nid = Nid(ffi::NID_id_pkix_OCSP_extendedStatus); +pub const ID_PKIX_OCSP_VALID: Nid = Nid(ffi::NID_id_pkix_OCSP_valid); +pub const ID_PKIX_OCSP_PATH: Nid = Nid(ffi::NID_id_pkix_OCSP_path); +pub const ID_PKIX_OCSP_TRUSTROOT: Nid = Nid(ffi::NID_id_pkix_OCSP_trustRoot); +pub const ALGORITHM: Nid = Nid(ffi::NID_algorithm); +pub const MD5WITHRSA: Nid = Nid(ffi::NID_md5WithRSA); +pub const DES_ECB: Nid = Nid(ffi::NID_des_ecb); +pub const DES_CBC: Nid = Nid(ffi::NID_des_cbc); +pub const DES_OFB64: Nid = Nid(ffi::NID_des_ofb64); +pub const DES_CFB64: Nid = Nid(ffi::NID_des_cfb64); +pub const RSASIGNATURE: Nid = Nid(ffi::NID_rsaSignature); +pub const DSA_2: Nid = Nid(ffi::NID_dsa_2); +pub const DSAWITHSHA: Nid = Nid(ffi::NID_dsaWithSHA); +pub const SHAWITHRSAENCRYPTION: Nid = Nid(ffi::NID_shaWithRSAEncryption); +pub const DES_EDE_ECB: Nid = Nid(ffi::NID_des_ede_ecb); +pub const DES_EDE3_ECB: Nid = Nid(ffi::NID_des_ede3_ecb); +pub const DES_EDE_CBC: Nid = Nid(ffi::NID_des_ede_cbc); +pub const DES_EDE_CFB64: Nid = Nid(ffi::NID_des_ede_cfb64); +pub const DES_EDE3_CFB64: Nid = Nid(ffi::NID_des_ede3_cfb64); +pub const DES_EDE_OFB64: Nid = Nid(ffi::NID_des_ede_ofb64); +pub const DES_EDE3_OFB64: Nid = Nid(ffi::NID_des_ede3_ofb64); +pub const DESX_CBC: Nid = Nid(ffi::NID_desx_cbc); +pub const SHA: Nid = Nid(ffi::NID_sha); +pub const SHA1: Nid = Nid(ffi::NID_sha1); +pub const DSAWITHSHA1_2: Nid = Nid(ffi::NID_dsaWithSHA1_2); +pub const SHA1WITHRSA: Nid = Nid(ffi::NID_sha1WithRSA); +pub const RIPEMD160: Nid = Nid(ffi::NID_ripemd160); +pub const RIPEMD160WITHRSA: Nid = Nid(ffi::NID_ripemd160WithRSA); +pub const SXNET: Nid = Nid(ffi::NID_sxnet); +pub const X500: Nid = Nid(ffi::NID_X500); +pub const X509: Nid = Nid(ffi::NID_X509); +pub const COMMONNAME: Nid = Nid(ffi::NID_commonName); +pub const SURNAME: Nid = Nid(ffi::NID_surname); +pub const SERIALNUMBER: Nid = Nid(ffi::NID_serialNumber); +pub const COUNTRYNAME: Nid = Nid(ffi::NID_countryName); +pub const LOCALITYNAME: Nid = Nid(ffi::NID_localityName); +pub const STATEORPROVINCENAME: Nid = Nid(ffi::NID_stateOrProvinceName); +pub const STREETADDRESS: Nid = Nid(ffi::NID_streetAddress); +pub const ORGANIZATIONNAME: Nid = Nid(ffi::NID_organizationName); +pub const ORGANIZATIONALUNITNAME: Nid = Nid(ffi::NID_organizationalUnitName); +pub const TITLE: Nid = Nid(ffi::NID_title); +pub const DESCRIPTION: Nid = Nid(ffi::NID_description); +pub const SEARCHGUIDE: Nid = Nid(ffi::NID_searchGuide); +pub const BUSINESSCATEGORY: Nid = Nid(ffi::NID_businessCategory); +pub const POSTALADDRESS: Nid = Nid(ffi::NID_postalAddress); +pub const POSTALCODE: Nid = Nid(ffi::NID_postalCode); +pub const POSTOFFICEBOX: Nid = Nid(ffi::NID_postOfficeBox); +pub const PHYSICALDELIVERYOFFICENAME: Nid = Nid(ffi::NID_physicalDeliveryOfficeName); +pub const TELEPHONENUMBER: Nid = Nid(ffi::NID_telephoneNumber); +pub const TELEXNUMBER: Nid = Nid(ffi::NID_telexNumber); +pub const TELETEXTERMINALIDENTIFIER: Nid = Nid(ffi::NID_teletexTerminalIdentifier); +pub const FACSIMILETELEPHONENUMBER: Nid = Nid(ffi::NID_facsimileTelephoneNumber); +pub const X121ADDRESS: Nid = Nid(ffi::NID_x121Address); +pub const INTERNATIONALISDNNUMBER: Nid = Nid(ffi::NID_internationaliSDNNumber); +pub const REGISTEREDADDRESS: Nid = Nid(ffi::NID_registeredAddress); +pub const DESTINATIONINDICATOR: Nid = Nid(ffi::NID_destinationIndicator); +pub const PREFERREDDELIVERYMETHOD: Nid = Nid(ffi::NID_preferredDeliveryMethod); +pub const PRESENTATIONADDRESS: Nid = Nid(ffi::NID_presentationAddress); +pub const SUPPORTEDAPPLICATIONCONTEXT: Nid = Nid(ffi::NID_supportedApplicationContext); +pub const MEMBER: Nid = Nid(ffi::NID_member); +pub const OWNER: Nid = Nid(ffi::NID_owner); +pub const ROLEOCCUPANT: Nid = Nid(ffi::NID_roleOccupant); +pub const SEEALSO: Nid = Nid(ffi::NID_seeAlso); +pub const USERPASSWORD: Nid = Nid(ffi::NID_userPassword); +pub const USERCERTIFICATE: Nid = Nid(ffi::NID_userCertificate); +pub const CACERTIFICATE: Nid = Nid(ffi::NID_cACertificate); +pub const AUTHORITYREVOCATIONLIST: Nid = Nid(ffi::NID_authorityRevocationList); +pub const CERTIFICATEREVOCATIONLIST: Nid = Nid(ffi::NID_certificateRevocationList); +pub const CROSSCERTIFICATEPAIR: Nid = Nid(ffi::NID_crossCertificatePair); +pub const NAME: Nid = Nid(ffi::NID_name); +pub const GIVENNAME: Nid = Nid(ffi::NID_givenName); +pub const INITIALS: Nid = Nid(ffi::NID_initials); +pub const GENERATIONQUALIFIER: Nid = Nid(ffi::NID_generationQualifier); +pub const X500UNIQUEIDENTIFIER: Nid = Nid(ffi::NID_x500UniqueIdentifier); +pub const DNQUALIFIER: Nid = Nid(ffi::NID_dnQualifier); +pub const ENHANCEDSEARCHGUIDE: Nid = Nid(ffi::NID_enhancedSearchGuide); +pub const PROTOCOLINFORMATION: Nid = Nid(ffi::NID_protocolInformation); +pub const DISTINGUISHEDNAME: Nid = Nid(ffi::NID_distinguishedName); +pub const UNIQUEMEMBER: Nid = Nid(ffi::NID_uniqueMember); +pub const HOUSEIDENTIFIER: Nid = Nid(ffi::NID_houseIdentifier); +pub const SUPPORTEDALGORITHMS: Nid = Nid(ffi::NID_supportedAlgorithms); +pub const DELTAREVOCATIONLIST: Nid = Nid(ffi::NID_deltaRevocationList); +pub const DMDNAME: Nid = Nid(ffi::NID_dmdName); +pub const PSEUDONYM: Nid = Nid(ffi::NID_pseudonym); +pub const ROLE: Nid = Nid(ffi::NID_role); +pub const X500ALGORITHMS: Nid = Nid(ffi::NID_X500algorithms); +pub const RSA: Nid = Nid(ffi::NID_rsa); +pub const MDC2WITHRSA: Nid = Nid(ffi::NID_mdc2WithRSA); +pub const MDC2: Nid = Nid(ffi::NID_mdc2); +pub const ID_CE: Nid = Nid(ffi::NID_id_ce); +pub const SUBJECT_DIRECTORY_ATTRIBUTES: Nid = Nid(ffi::NID_subject_directory_attributes); +pub const SUBJECT_KEY_IDENTIFIER: Nid = Nid(ffi::NID_subject_key_identifier); +pub const KEY_USAGE: Nid = Nid(ffi::NID_key_usage); +pub const PRIVATE_KEY_USAGE_PERIOD: Nid = Nid(ffi::NID_private_key_usage_period); +pub const SUBJECT_ALT_NAME: Nid = Nid(ffi::NID_subject_alt_name); +pub const ISSUER_ALT_NAME: Nid = Nid(ffi::NID_issuer_alt_name); +pub const BASIC_CONSTRAINTS: Nid = Nid(ffi::NID_basic_constraints); +pub const CRL_NUMBER: Nid = Nid(ffi::NID_crl_number); +pub const CRL_REASON: Nid = Nid(ffi::NID_crl_reason); +pub const INVALIDITY_DATE: Nid = Nid(ffi::NID_invalidity_date); +pub const DELTA_CRL: Nid = Nid(ffi::NID_delta_crl); +pub const ISSUING_DISTRIBUTION_POINT: Nid = Nid(ffi::NID_issuing_distribution_point); +pub const CERTIFICATE_ISSUER: Nid = Nid(ffi::NID_certificate_issuer); +pub const NAME_CONSTRAINTS: Nid = Nid(ffi::NID_name_constraints); +pub const CRL_DISTRIBUTION_POINTS: Nid = Nid(ffi::NID_crl_distribution_points); +pub const CERTIFICATE_POLICIES: Nid = Nid(ffi::NID_certificate_policies); +pub const ANY_POLICY: Nid = Nid(ffi::NID_any_policy); +pub const POLICY_MAPPINGS: Nid = Nid(ffi::NID_policy_mappings); +pub const AUTHORITY_KEY_IDENTIFIER: Nid = Nid(ffi::NID_authority_key_identifier); +pub const POLICY_CONSTRAINTS: Nid = Nid(ffi::NID_policy_constraints); +pub const EXT_KEY_USAGE: Nid = Nid(ffi::NID_ext_key_usage); +pub const FRESHEST_CRL: Nid = Nid(ffi::NID_freshest_crl); +pub const INHIBIT_ANY_POLICY: Nid = Nid(ffi::NID_inhibit_any_policy); +pub const TARGET_INFORMATION: Nid = Nid(ffi::NID_target_information); +pub const NO_REV_AVAIL: Nid = Nid(ffi::NID_no_rev_avail); +pub const ANYEXTENDEDKEYUSAGE: Nid = Nid(ffi::NID_anyExtendedKeyUsage); +pub const NETSCAPE: Nid = Nid(ffi::NID_netscape); +pub const NETSCAPE_CERT_EXTENSION: Nid = Nid(ffi::NID_netscape_cert_extension); +pub const NETSCAPE_DATA_TYPE: Nid = Nid(ffi::NID_netscape_data_type); +pub const NETSCAPE_CERT_TYPE: Nid = Nid(ffi::NID_netscape_cert_type); +pub const NETSCAPE_BASE_URL: Nid = Nid(ffi::NID_netscape_base_url); +pub const NETSCAPE_REVOCATION_URL: Nid = Nid(ffi::NID_netscape_revocation_url); +pub const NETSCAPE_CA_REVOCATION_URL: Nid = Nid(ffi::NID_netscape_ca_revocation_url); +pub const NETSCAPE_RENEWAL_URL: Nid = Nid(ffi::NID_netscape_renewal_url); +pub const NETSCAPE_CA_POLICY_URL: Nid = Nid(ffi::NID_netscape_ca_policy_url); +pub const NETSCAPE_SSL_SERVER_NAME: Nid = Nid(ffi::NID_netscape_ssl_server_name); +pub const NETSCAPE_COMMENT: Nid = Nid(ffi::NID_netscape_comment); +pub const NETSCAPE_CERT_SEQUENCE: Nid = Nid(ffi::NID_netscape_cert_sequence); +pub const NS_SGC: Nid = Nid(ffi::NID_ns_sgc); +pub const ORG: Nid = Nid(ffi::NID_org); +pub const DOD: Nid = Nid(ffi::NID_dod); +pub const IANA: Nid = Nid(ffi::NID_iana); +pub const DIRECTORY: Nid = Nid(ffi::NID_Directory); +pub const MANAGEMENT: Nid = Nid(ffi::NID_Management); +pub const EXPERIMENTAL: Nid = Nid(ffi::NID_Experimental); +pub const PRIVATE: Nid = Nid(ffi::NID_Private); +pub const SECURITY: Nid = Nid(ffi::NID_Security); +pub const SNMPV2: Nid = Nid(ffi::NID_SNMPv2); +pub const MAIL: Nid = Nid(ffi::NID_Mail); +pub const ENTERPRISES: Nid = Nid(ffi::NID_Enterprises); +pub const DCOBJECT: Nid = Nid(ffi::NID_dcObject); +pub const MIME_MHS: Nid = Nid(ffi::NID_mime_mhs); +pub const MIME_MHS_HEADINGS: Nid = Nid(ffi::NID_mime_mhs_headings); +pub const MIME_MHS_BODIES: Nid = Nid(ffi::NID_mime_mhs_bodies); +pub const ID_HEX_PARTIAL_MESSAGE: Nid = Nid(ffi::NID_id_hex_partial_message); +pub const ID_HEX_MULTIPART_MESSAGE: Nid = Nid(ffi::NID_id_hex_multipart_message); +pub const ZLIB_COMPRESSION: Nid = Nid(ffi::NID_zlib_compression); +pub const AES_128_ECB: Nid = Nid(ffi::NID_aes_128_ecb); +pub const AES_128_CBC: Nid = Nid(ffi::NID_aes_128_cbc); +pub const AES_128_OFB128: Nid = Nid(ffi::NID_aes_128_ofb128); +pub const AES_128_CFB128: Nid = Nid(ffi::NID_aes_128_cfb128); +pub const ID_AES128_WRAP: Nid = Nid(ffi::NID_id_aes128_wrap); +pub const AES_128_GCM: Nid = Nid(ffi::NID_aes_128_gcm); +pub const AES_128_CCM: Nid = Nid(ffi::NID_aes_128_ccm); +pub const ID_AES128_WRAP_PAD: Nid = Nid(ffi::NID_id_aes128_wrap_pad); +pub const AES_192_ECB: Nid = Nid(ffi::NID_aes_192_ecb); +pub const AES_192_CBC: Nid = Nid(ffi::NID_aes_192_cbc); +pub const AES_192_OFB128: Nid = Nid(ffi::NID_aes_192_ofb128); +pub const AES_192_CFB128: Nid = Nid(ffi::NID_aes_192_cfb128); +pub const ID_AES192_WRAP: Nid = Nid(ffi::NID_id_aes192_wrap); +pub const AES_192_GCM: Nid = Nid(ffi::NID_aes_192_gcm); +pub const AES_192_CCM: Nid = Nid(ffi::NID_aes_192_ccm); +pub const ID_AES192_WRAP_PAD: Nid = Nid(ffi::NID_id_aes192_wrap_pad); +pub const AES_256_ECB: Nid = Nid(ffi::NID_aes_256_ecb); +pub const AES_256_CBC: Nid = Nid(ffi::NID_aes_256_cbc); +pub const AES_256_OFB128: Nid = Nid(ffi::NID_aes_256_ofb128); +pub const AES_256_CFB128: Nid = Nid(ffi::NID_aes_256_cfb128); +pub const ID_AES256_WRAP: Nid = Nid(ffi::NID_id_aes256_wrap); +pub const AES_256_GCM: Nid = Nid(ffi::NID_aes_256_gcm); +pub const AES_256_CCM: Nid = Nid(ffi::NID_aes_256_ccm); +pub const ID_AES256_WRAP_PAD: Nid = Nid(ffi::NID_id_aes256_wrap_pad); +pub const AES_128_CFB1: Nid = Nid(ffi::NID_aes_128_cfb1); +pub const AES_192_CFB1: Nid = Nid(ffi::NID_aes_192_cfb1); +pub const AES_256_CFB1: Nid = Nid(ffi::NID_aes_256_cfb1); +pub const AES_128_CFB8: Nid = Nid(ffi::NID_aes_128_cfb8); +pub const AES_192_CFB8: Nid = Nid(ffi::NID_aes_192_cfb8); +pub const AES_256_CFB8: Nid = Nid(ffi::NID_aes_256_cfb8); +pub const AES_128_CTR: Nid = Nid(ffi::NID_aes_128_ctr); +pub const AES_192_CTR: Nid = Nid(ffi::NID_aes_192_ctr); +pub const AES_256_CTR: Nid = Nid(ffi::NID_aes_256_ctr); +pub const AES_128_XTS: Nid = Nid(ffi::NID_aes_128_xts); +pub const AES_256_XTS: Nid = Nid(ffi::NID_aes_256_xts); +pub const DES_CFB1: Nid = Nid(ffi::NID_des_cfb1); +pub const DES_CFB8: Nid = Nid(ffi::NID_des_cfb8); +pub const DES_EDE3_CFB1: Nid = Nid(ffi::NID_des_ede3_cfb1); +pub const DES_EDE3_CFB8: Nid = Nid(ffi::NID_des_ede3_cfb8); +pub const SHA256: Nid = Nid(ffi::NID_sha256); +pub const SHA384: Nid = Nid(ffi::NID_sha384); +pub const SHA512: Nid = Nid(ffi::NID_sha512); +pub const SHA224: Nid = Nid(ffi::NID_sha224); +pub const DSA_WITH_SHA224: Nid = Nid(ffi::NID_dsa_with_SHA224); +pub const DSA_WITH_SHA256: Nid = Nid(ffi::NID_dsa_with_SHA256); +pub const HOLD_INSTRUCTION_CODE: Nid = Nid(ffi::NID_hold_instruction_code); +pub const HOLD_INSTRUCTION_NONE: Nid = Nid(ffi::NID_hold_instruction_none); +pub const HOLD_INSTRUCTION_CALL_ISSUER: Nid = Nid(ffi::NID_hold_instruction_call_issuer); +pub const HOLD_INSTRUCTION_REJECT: Nid = Nid(ffi::NID_hold_instruction_reject); +pub const DATA: Nid = Nid(ffi::NID_data); +pub const PSS: Nid = Nid(ffi::NID_pss); +pub const UCL: Nid = Nid(ffi::NID_ucl); +pub const PILOT: Nid = Nid(ffi::NID_pilot); +pub const PILOTATTRIBUTETYPE: Nid = Nid(ffi::NID_pilotAttributeType); +pub const PILOTATTRIBUTESYNTAX: Nid = Nid(ffi::NID_pilotAttributeSyntax); +pub const PILOTOBJECTCLASS: Nid = Nid(ffi::NID_pilotObjectClass); +pub const PILOTGROUPS: Nid = Nid(ffi::NID_pilotGroups); +pub const IA5STRINGSYNTAX: Nid = Nid(ffi::NID_iA5StringSyntax); +pub const CASEIGNOREIA5STRINGSYNTAX: Nid = Nid(ffi::NID_caseIgnoreIA5StringSyntax); +pub const PILOTOBJECT: Nid = Nid(ffi::NID_pilotObject); +pub const PILOTPERSON: Nid = Nid(ffi::NID_pilotPerson); +pub const ACCOUNT: Nid = Nid(ffi::NID_account); +pub const DOCUMENT: Nid = Nid(ffi::NID_document); +pub const ROOM: Nid = Nid(ffi::NID_room); +pub const DOCUMENTSERIES: Nid = Nid(ffi::NID_documentSeries); +pub const DOMAIN: Nid = Nid(ffi::NID_Domain); +pub const RFC822LOCALPART: Nid = Nid(ffi::NID_rFC822localPart); +pub const DNSDOMAIN: Nid = Nid(ffi::NID_dNSDomain); +pub const DOMAINRELATEDOBJECT: Nid = Nid(ffi::NID_domainRelatedObject); +pub const FRIENDLYCOUNTRY: Nid = Nid(ffi::NID_friendlyCountry); +pub const SIMPLESECURITYOBJECT: Nid = Nid(ffi::NID_simpleSecurityObject); +pub const PILOTORGANIZATION: Nid = Nid(ffi::NID_pilotOrganization); +pub const PILOTDSA: Nid = Nid(ffi::NID_pilotDSA); +pub const QUALITYLABELLEDDATA: Nid = Nid(ffi::NID_qualityLabelledData); +pub const USERID: Nid = Nid(ffi::NID_userId); +pub const TEXTENCODEDORADDRESS: Nid = Nid(ffi::NID_textEncodedORAddress); +pub const RFC822MAILBOX: Nid = Nid(ffi::NID_rfc822Mailbox); +pub const INFO: Nid = Nid(ffi::NID_info); +pub const FAVOURITEDRINK: Nid = Nid(ffi::NID_favouriteDrink); +pub const ROOMNUMBER: Nid = Nid(ffi::NID_roomNumber); +pub const PHOTO: Nid = Nid(ffi::NID_photo); +pub const USERCLASS: Nid = Nid(ffi::NID_userClass); +pub const HOST: Nid = Nid(ffi::NID_host); +pub const MANAGER: Nid = Nid(ffi::NID_manager); +pub const DOCUMENTIDENTIFIER: Nid = Nid(ffi::NID_documentIdentifier); +pub const DOCUMENTTITLE: Nid = Nid(ffi::NID_documentTitle); +pub const DOCUMENTVERSION: Nid = Nid(ffi::NID_documentVersion); +pub const DOCUMENTAUTHOR: Nid = Nid(ffi::NID_documentAuthor); +pub const DOCUMENTLOCATION: Nid = Nid(ffi::NID_documentLocation); +pub const HOMETELEPHONENUMBER: Nid = Nid(ffi::NID_homeTelephoneNumber); +pub const SECRETARY: Nid = Nid(ffi::NID_secretary); +pub const OTHERMAILBOX: Nid = Nid(ffi::NID_otherMailbox); +pub const LASTMODIFIEDTIME: Nid = Nid(ffi::NID_lastModifiedTime); +pub const LASTMODIFIEDBY: Nid = Nid(ffi::NID_lastModifiedBy); +pub const DOMAINCOMPONENT: Nid = Nid(ffi::NID_domainComponent); +pub const ARECORD: Nid = Nid(ffi::NID_aRecord); +pub const PILOTATTRIBUTETYPE27: Nid = Nid(ffi::NID_pilotAttributeType27); +pub const MXRECORD: Nid = Nid(ffi::NID_mXRecord); +pub const NSRECORD: Nid = Nid(ffi::NID_nSRecord); +pub const SOARECORD: Nid = Nid(ffi::NID_sOARecord); +pub const CNAMERECORD: Nid = Nid(ffi::NID_cNAMERecord); +pub const ASSOCIATEDDOMAIN: Nid = Nid(ffi::NID_associatedDomain); +pub const ASSOCIATEDNAME: Nid = Nid(ffi::NID_associatedName); +pub const HOMEPOSTALADDRESS: Nid = Nid(ffi::NID_homePostalAddress); +pub const PERSONALTITLE: Nid = Nid(ffi::NID_personalTitle); +pub const MOBILETELEPHONENUMBER: Nid = Nid(ffi::NID_mobileTelephoneNumber); +pub const PAGERTELEPHONENUMBER: Nid = Nid(ffi::NID_pagerTelephoneNumber); +pub const FRIENDLYCOUNTRYNAME: Nid = Nid(ffi::NID_friendlyCountryName); +pub const ORGANIZATIONALSTATUS: Nid = Nid(ffi::NID_organizationalStatus); +pub const JANETMAILBOX: Nid = Nid(ffi::NID_janetMailbox); +pub const MAILPREFERENCEOPTION: Nid = Nid(ffi::NID_mailPreferenceOption); +pub const BUILDINGNAME: Nid = Nid(ffi::NID_buildingName); +pub const DSAQUALITY: Nid = Nid(ffi::NID_dSAQuality); +pub const SINGLELEVELQUALITY: Nid = Nid(ffi::NID_singleLevelQuality); +pub const SUBTREEMINIMUMQUALITY: Nid = Nid(ffi::NID_subtreeMinimumQuality); +pub const SUBTREEMAXIMUMQUALITY: Nid = Nid(ffi::NID_subtreeMaximumQuality); +pub const PERSONALSIGNATURE: Nid = Nid(ffi::NID_personalSignature); +pub const DITREDIRECT: Nid = Nid(ffi::NID_dITRedirect); +pub const AUDIO: Nid = Nid(ffi::NID_audio); +pub const DOCUMENTPUBLISHER: Nid = Nid(ffi::NID_documentPublisher); +pub const ID_SET: Nid = Nid(ffi::NID_id_set); +pub const SET_CTYPE: Nid = Nid(ffi::NID_set_ctype); +pub const SET_MSGEXT: Nid = Nid(ffi::NID_set_msgExt); +pub const SET_ATTR: Nid = Nid(ffi::NID_set_attr); +pub const SET_POLICY: Nid = Nid(ffi::NID_set_policy); +pub const SET_CERTEXT: Nid = Nid(ffi::NID_set_certExt); +pub const SET_BRAND: Nid = Nid(ffi::NID_set_brand); +pub const SETCT_PANDATA: Nid = Nid(ffi::NID_setct_PANData); +pub const SETCT_PANTOKEN: Nid = Nid(ffi::NID_setct_PANToken); +pub const SETCT_PANONLY: Nid = Nid(ffi::NID_setct_PANOnly); +pub const SETCT_OIDATA: Nid = Nid(ffi::NID_setct_OIData); +pub const SETCT_PI: Nid = Nid(ffi::NID_setct_PI); +pub const SETCT_PIDATA: Nid = Nid(ffi::NID_setct_PIData); +pub const SETCT_PIDATAUNSIGNED: Nid = Nid(ffi::NID_setct_PIDataUnsigned); +pub const SETCT_HODINPUT: Nid = Nid(ffi::NID_setct_HODInput); +pub const SETCT_AUTHRESBAGGAGE: Nid = Nid(ffi::NID_setct_AuthResBaggage); +pub const SETCT_AUTHREVREQBAGGAGE: Nid = Nid(ffi::NID_setct_AuthRevReqBaggage); +pub const SETCT_AUTHREVRESBAGGAGE: Nid = Nid(ffi::NID_setct_AuthRevResBaggage); +pub const SETCT_CAPTOKENSEQ: Nid = Nid(ffi::NID_setct_CapTokenSeq); +pub const SETCT_PINITRESDATA: Nid = Nid(ffi::NID_setct_PInitResData); +pub const SETCT_PI_TBS: Nid = Nid(ffi::NID_setct_PI_TBS); +pub const SETCT_PRESDATA: Nid = Nid(ffi::NID_setct_PResData); +pub const SETCT_AUTHREQTBS: Nid = Nid(ffi::NID_setct_AuthReqTBS); +pub const SETCT_AUTHRESTBS: Nid = Nid(ffi::NID_setct_AuthResTBS); +pub const SETCT_AUTHRESTBSX: Nid = Nid(ffi::NID_setct_AuthResTBSX); +pub const SETCT_AUTHTOKENTBS: Nid = Nid(ffi::NID_setct_AuthTokenTBS); +pub const SETCT_CAPTOKENDATA: Nid = Nid(ffi::NID_setct_CapTokenData); +pub const SETCT_CAPTOKENTBS: Nid = Nid(ffi::NID_setct_CapTokenTBS); +pub const SETCT_ACQCARDCODEMSG: Nid = Nid(ffi::NID_setct_AcqCardCodeMsg); +pub const SETCT_AUTHREVREQTBS: Nid = Nid(ffi::NID_setct_AuthRevReqTBS); +pub const SETCT_AUTHREVRESDATA: Nid = Nid(ffi::NID_setct_AuthRevResData); +pub const SETCT_AUTHREVRESTBS: Nid = Nid(ffi::NID_setct_AuthRevResTBS); +pub const SETCT_CAPREQTBS: Nid = Nid(ffi::NID_setct_CapReqTBS); +pub const SETCT_CAPREQTBSX: Nid = Nid(ffi::NID_setct_CapReqTBSX); +pub const SETCT_CAPRESDATA: Nid = Nid(ffi::NID_setct_CapResData); +pub const SETCT_CAPREVREQTBS: Nid = Nid(ffi::NID_setct_CapRevReqTBS); +pub const SETCT_CAPREVREQTBSX: Nid = Nid(ffi::NID_setct_CapRevReqTBSX); +pub const SETCT_CAPREVRESDATA: Nid = Nid(ffi::NID_setct_CapRevResData); +pub const SETCT_CREDREQTBS: Nid = Nid(ffi::NID_setct_CredReqTBS); +pub const SETCT_CREDREQTBSX: Nid = Nid(ffi::NID_setct_CredReqTBSX); +pub const SETCT_CREDRESDATA: Nid = Nid(ffi::NID_setct_CredResData); +pub const SETCT_CREDREVREQTBS: Nid = Nid(ffi::NID_setct_CredRevReqTBS); +pub const SETCT_CREDREVREQTBSX: Nid = Nid(ffi::NID_setct_CredRevReqTBSX); +pub const SETCT_CREDREVRESDATA: Nid = Nid(ffi::NID_setct_CredRevResData); +pub const SETCT_PCERTREQDATA: Nid = Nid(ffi::NID_setct_PCertReqData); +pub const SETCT_PCERTRESTBS: Nid = Nid(ffi::NID_setct_PCertResTBS); +pub const SETCT_BATCHADMINREQDATA: Nid = Nid(ffi::NID_setct_BatchAdminReqData); +pub const SETCT_BATCHADMINRESDATA: Nid = Nid(ffi::NID_setct_BatchAdminResData); +pub const SETCT_CARDCINITRESTBS: Nid = Nid(ffi::NID_setct_CardCInitResTBS); +pub const SETCT_MEAQCINITRESTBS: Nid = Nid(ffi::NID_setct_MeAqCInitResTBS); +pub const SETCT_REGFORMRESTBS: Nid = Nid(ffi::NID_setct_RegFormResTBS); +pub const SETCT_CERTREQDATA: Nid = Nid(ffi::NID_setct_CertReqData); +pub const SETCT_CERTREQTBS: Nid = Nid(ffi::NID_setct_CertReqTBS); +pub const SETCT_CERTRESDATA: Nid = Nid(ffi::NID_setct_CertResData); +pub const SETCT_CERTINQREQTBS: Nid = Nid(ffi::NID_setct_CertInqReqTBS); +pub const SETCT_ERRORTBS: Nid = Nid(ffi::NID_setct_ErrorTBS); +pub const SETCT_PIDUALSIGNEDTBE: Nid = Nid(ffi::NID_setct_PIDualSignedTBE); +pub const SETCT_PIUNSIGNEDTBE: Nid = Nid(ffi::NID_setct_PIUnsignedTBE); +pub const SETCT_AUTHREQTBE: Nid = Nid(ffi::NID_setct_AuthReqTBE); +pub const SETCT_AUTHRESTBE: Nid = Nid(ffi::NID_setct_AuthResTBE); +pub const SETCT_AUTHRESTBEX: Nid = Nid(ffi::NID_setct_AuthResTBEX); +pub const SETCT_AUTHTOKENTBE: Nid = Nid(ffi::NID_setct_AuthTokenTBE); +pub const SETCT_CAPTOKENTBE: Nid = Nid(ffi::NID_setct_CapTokenTBE); +pub const SETCT_CAPTOKENTBEX: Nid = Nid(ffi::NID_setct_CapTokenTBEX); +pub const SETCT_ACQCARDCODEMSGTBE: Nid = Nid(ffi::NID_setct_AcqCardCodeMsgTBE); +pub const SETCT_AUTHREVREQTBE: Nid = Nid(ffi::NID_setct_AuthRevReqTBE); +pub const SETCT_AUTHREVRESTBE: Nid = Nid(ffi::NID_setct_AuthRevResTBE); +pub const SETCT_AUTHREVRESTBEB: Nid = Nid(ffi::NID_setct_AuthRevResTBEB); +pub const SETCT_CAPREQTBE: Nid = Nid(ffi::NID_setct_CapReqTBE); +pub const SETCT_CAPREQTBEX: Nid = Nid(ffi::NID_setct_CapReqTBEX); +pub const SETCT_CAPRESTBE: Nid = Nid(ffi::NID_setct_CapResTBE); +pub const SETCT_CAPREVREQTBE: Nid = Nid(ffi::NID_setct_CapRevReqTBE); +pub const SETCT_CAPREVREQTBEX: Nid = Nid(ffi::NID_setct_CapRevReqTBEX); +pub const SETCT_CAPREVRESTBE: Nid = Nid(ffi::NID_setct_CapRevResTBE); +pub const SETCT_CREDREQTBE: Nid = Nid(ffi::NID_setct_CredReqTBE); +pub const SETCT_CREDREQTBEX: Nid = Nid(ffi::NID_setct_CredReqTBEX); +pub const SETCT_CREDRESTBE: Nid = Nid(ffi::NID_setct_CredResTBE); +pub const SETCT_CREDREVREQTBE: Nid = Nid(ffi::NID_setct_CredRevReqTBE); +pub const SETCT_CREDREVREQTBEX: Nid = Nid(ffi::NID_setct_CredRevReqTBEX); +pub const SETCT_CREDREVRESTBE: Nid = Nid(ffi::NID_setct_CredRevResTBE); +pub const SETCT_BATCHADMINREQTBE: Nid = Nid(ffi::NID_setct_BatchAdminReqTBE); +pub const SETCT_BATCHADMINRESTBE: Nid = Nid(ffi::NID_setct_BatchAdminResTBE); +pub const SETCT_REGFORMREQTBE: Nid = Nid(ffi::NID_setct_RegFormReqTBE); +pub const SETCT_CERTREQTBE: Nid = Nid(ffi::NID_setct_CertReqTBE); +pub const SETCT_CERTREQTBEX: Nid = Nid(ffi::NID_setct_CertReqTBEX); +pub const SETCT_CERTRESTBE: Nid = Nid(ffi::NID_setct_CertResTBE); +pub const SETCT_CRLNOTIFICATIONTBS: Nid = Nid(ffi::NID_setct_CRLNotificationTBS); +pub const SETCT_CRLNOTIFICATIONRESTBS: Nid = Nid(ffi::NID_setct_CRLNotificationResTBS); +pub const SETCT_BCIDISTRIBUTIONTBS: Nid = Nid(ffi::NID_setct_BCIDistributionTBS); +pub const SETEXT_GENCRYPT: Nid = Nid(ffi::NID_setext_genCrypt); +pub const SETEXT_MIAUTH: Nid = Nid(ffi::NID_setext_miAuth); +pub const SETEXT_PINSECURE: Nid = Nid(ffi::NID_setext_pinSecure); +pub const SETEXT_PINANY: Nid = Nid(ffi::NID_setext_pinAny); +pub const SETEXT_TRACK2: Nid = Nid(ffi::NID_setext_track2); +pub const SETEXT_CV: Nid = Nid(ffi::NID_setext_cv); +pub const SET_POLICY_ROOT: Nid = Nid(ffi::NID_set_policy_root); +pub const SETCEXT_HASHEDROOT: Nid = Nid(ffi::NID_setCext_hashedRoot); +pub const SETCEXT_CERTTYPE: Nid = Nid(ffi::NID_setCext_certType); +pub const SETCEXT_MERCHDATA: Nid = Nid(ffi::NID_setCext_merchData); +pub const SETCEXT_CCERTREQUIRED: Nid = Nid(ffi::NID_setCext_cCertRequired); +pub const SETCEXT_TUNNELING: Nid = Nid(ffi::NID_setCext_tunneling); +pub const SETCEXT_SETEXT: Nid = Nid(ffi::NID_setCext_setExt); +pub const SETCEXT_SETQUALF: Nid = Nid(ffi::NID_setCext_setQualf); +pub const SETCEXT_PGWYCAPABILITIES: Nid = Nid(ffi::NID_setCext_PGWYcapabilities); +pub const SETCEXT_TOKENIDENTIFIER: Nid = Nid(ffi::NID_setCext_TokenIdentifier); +pub const SETCEXT_TRACK2DATA: Nid = Nid(ffi::NID_setCext_Track2Data); +pub const SETCEXT_TOKENTYPE: Nid = Nid(ffi::NID_setCext_TokenType); +pub const SETCEXT_ISSUERCAPABILITIES: Nid = Nid(ffi::NID_setCext_IssuerCapabilities); +pub const SETATTR_CERT: Nid = Nid(ffi::NID_setAttr_Cert); +pub const SETATTR_PGWYCAP: Nid = Nid(ffi::NID_setAttr_PGWYcap); +pub const SETATTR_TOKENTYPE: Nid = Nid(ffi::NID_setAttr_TokenType); +pub const SETATTR_ISSCAP: Nid = Nid(ffi::NID_setAttr_IssCap); +pub const SET_ROOTKEYTHUMB: Nid = Nid(ffi::NID_set_rootKeyThumb); +pub const SET_ADDPOLICY: Nid = Nid(ffi::NID_set_addPolicy); +pub const SETATTR_TOKEN_EMV: Nid = Nid(ffi::NID_setAttr_Token_EMV); +pub const SETATTR_TOKEN_B0PRIME: Nid = Nid(ffi::NID_setAttr_Token_B0Prime); +pub const SETATTR_ISSCAP_CVM: Nid = Nid(ffi::NID_setAttr_IssCap_CVM); +pub const SETATTR_ISSCAP_T2: Nid = Nid(ffi::NID_setAttr_IssCap_T2); +pub const SETATTR_ISSCAP_SIG: Nid = Nid(ffi::NID_setAttr_IssCap_Sig); +pub const SETATTR_GENCRYPTGRM: Nid = Nid(ffi::NID_setAttr_GenCryptgrm); +pub const SETATTR_T2ENC: Nid = Nid(ffi::NID_setAttr_T2Enc); +pub const SETATTR_T2CLEARTXT: Nid = Nid(ffi::NID_setAttr_T2cleartxt); +pub const SETATTR_TOKICCSIG: Nid = Nid(ffi::NID_setAttr_TokICCsig); +pub const SETATTR_SECDEVSIG: Nid = Nid(ffi::NID_setAttr_SecDevSig); +pub const SET_BRAND_IATA_ATA: Nid = Nid(ffi::NID_set_brand_IATA_ATA); +pub const SET_BRAND_DINERS: Nid = Nid(ffi::NID_set_brand_Diners); +pub const SET_BRAND_AMERICANEXPRESS: Nid = Nid(ffi::NID_set_brand_AmericanExpress); +pub const SET_BRAND_JCB: Nid = Nid(ffi::NID_set_brand_JCB); +pub const SET_BRAND_VISA: Nid = Nid(ffi::NID_set_brand_Visa); +pub const SET_BRAND_MASTERCARD: Nid = Nid(ffi::NID_set_brand_MasterCard); +pub const SET_BRAND_NOVUS: Nid = Nid(ffi::NID_set_brand_Novus); +pub const DES_CDMF: Nid = Nid(ffi::NID_des_cdmf); +pub const RSAOAEPENCRYPTIONSET: Nid = Nid(ffi::NID_rsaOAEPEncryptionSET); +pub const IPSEC3: Nid = Nid(ffi::NID_ipsec3); +pub const IPSEC4: Nid = Nid(ffi::NID_ipsec4); +pub const WHIRLPOOL: Nid = Nid(ffi::NID_whirlpool); +pub const CRYPTOPRO: Nid = Nid(ffi::NID_cryptopro); +pub const CRYPTOCOM: Nid = Nid(ffi::NID_cryptocom); +pub const ID_GOSTR3411_94_WITH_GOSTR3410_2001: Nid = + Nid(ffi::NID_id_GostR3411_94_with_GostR3410_2001); +pub const ID_GOSTR3411_94_WITH_GOSTR3410_94: Nid = Nid(ffi::NID_id_GostR3411_94_with_GostR3410_94); +pub const ID_GOSTR3411_94: Nid = Nid(ffi::NID_id_GostR3411_94); +pub const ID_HMACGOSTR3411_94: Nid = Nid(ffi::NID_id_HMACGostR3411_94); +pub const ID_GOSTR3410_2001: Nid = Nid(ffi::NID_id_GostR3410_2001); +pub const ID_GOSTR3410_94: Nid = Nid(ffi::NID_id_GostR3410_94); +pub const ID_GOST28147_89: Nid = Nid(ffi::NID_id_Gost28147_89); +pub const GOST89_CNT: Nid = Nid(ffi::NID_gost89_cnt); +pub const ID_GOST28147_89_MAC: Nid = Nid(ffi::NID_id_Gost28147_89_MAC); +pub const ID_GOSTR3411_94_PRF: Nid = Nid(ffi::NID_id_GostR3411_94_prf); +pub const ID_GOSTR3410_2001DH: Nid = Nid(ffi::NID_id_GostR3410_2001DH); +pub const ID_GOSTR3410_94DH: Nid = Nid(ffi::NID_id_GostR3410_94DH); +pub const ID_GOST28147_89_CRYPTOPRO_KEYMESHING: Nid = + Nid(ffi::NID_id_Gost28147_89_CryptoPro_KeyMeshing); +pub const ID_GOST28147_89_NONE_KEYMESHING: Nid = Nid(ffi::NID_id_Gost28147_89_None_KeyMeshing); +pub const ID_GOSTR3411_94_TESTPARAMSET: Nid = Nid(ffi::NID_id_GostR3411_94_TestParamSet); +pub const ID_GOSTR3411_94_CRYPTOPROPARAMSET: Nid = Nid(ffi::NID_id_GostR3411_94_CryptoProParamSet); +pub const ID_GOST28147_89_TESTPARAMSET: Nid = Nid(ffi::NID_id_Gost28147_89_TestParamSet); +pub const ID_GOST28147_89_CRYPTOPRO_A_PARAMSET: Nid = + Nid(ffi::NID_id_Gost28147_89_CryptoPro_A_ParamSet); +pub const ID_GOST28147_89_CRYPTOPRO_B_PARAMSET: Nid = + Nid(ffi::NID_id_Gost28147_89_CryptoPro_B_ParamSet); +pub const ID_GOST28147_89_CRYPTOPRO_C_PARAMSET: Nid = + Nid(ffi::NID_id_Gost28147_89_CryptoPro_C_ParamSet); +pub const ID_GOST28147_89_CRYPTOPRO_D_PARAMSET: Nid = + Nid(ffi::NID_id_Gost28147_89_CryptoPro_D_ParamSet); +pub const ID_GOST28147_89_CRYPTOPRO_OSCAR_1_1_PARAMSET: Nid = + Nid(ffi::NID_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet); +pub const ID_GOST28147_89_CRYPTOPRO_OSCAR_1_0_PARAMSET: Nid = + Nid(ffi::NID_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet); +pub const ID_GOST28147_89_CRYPTOPRO_RIC_1_PARAMSET: Nid = + Nid(ffi::NID_id_Gost28147_89_CryptoPro_RIC_1_ParamSet); +pub const ID_GOSTR3410_94_TESTPARAMSET: Nid = Nid(ffi::NID_id_GostR3410_94_TestParamSet); +pub const ID_GOSTR3410_94_CRYPTOPRO_A_PARAMSET: Nid = + Nid(ffi::NID_id_GostR3410_94_CryptoPro_A_ParamSet); +pub const ID_GOSTR3410_94_CRYPTOPRO_B_PARAMSET: Nid = + Nid(ffi::NID_id_GostR3410_94_CryptoPro_B_ParamSet); +pub const ID_GOSTR3410_94_CRYPTOPRO_C_PARAMSET: Nid = + Nid(ffi::NID_id_GostR3410_94_CryptoPro_C_ParamSet); +pub const ID_GOSTR3410_94_CRYPTOPRO_D_PARAMSET: Nid = + Nid(ffi::NID_id_GostR3410_94_CryptoPro_D_ParamSet); +pub const ID_GOSTR3410_94_CRYPTOPRO_XCHA_PARAMSET: Nid = + Nid(ffi::NID_id_GostR3410_94_CryptoPro_XchA_ParamSet); +pub const ID_GOSTR3410_94_CRYPTOPRO_XCHB_PARAMSET: Nid = + Nid(ffi::NID_id_GostR3410_94_CryptoPro_XchB_ParamSet); +pub const ID_GOSTR3410_94_CRYPTOPRO_XCHC_PARAMSET: Nid = + Nid(ffi::NID_id_GostR3410_94_CryptoPro_XchC_ParamSet); +pub const ID_GOSTR3410_2001_TESTPARAMSET: Nid = Nid(ffi::NID_id_GostR3410_2001_TestParamSet); +pub const ID_GOSTR3410_2001_CRYPTOPRO_A_PARAMSET: Nid = + Nid(ffi::NID_id_GostR3410_2001_CryptoPro_A_ParamSet); +pub const ID_GOSTR3410_2001_CRYPTOPRO_B_PARAMSET: Nid = + Nid(ffi::NID_id_GostR3410_2001_CryptoPro_B_ParamSet); +pub const ID_GOSTR3410_2001_CRYPTOPRO_C_PARAMSET: Nid = + Nid(ffi::NID_id_GostR3410_2001_CryptoPro_C_ParamSet); +pub const ID_GOSTR3410_2001_CRYPTOPRO_XCHA_PARAMSET: Nid = + Nid(ffi::NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet); +pub const ID_GOSTR3410_2001_CRYPTOPRO_XCHB_PARAMSET: Nid = + Nid(ffi::NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet); +pub const ID_GOSTR3410_94_A: Nid = Nid(ffi::NID_id_GostR3410_94_a); +pub const ID_GOSTR3410_94_ABIS: Nid = Nid(ffi::NID_id_GostR3410_94_aBis); +pub const ID_GOSTR3410_94_B: Nid = Nid(ffi::NID_id_GostR3410_94_b); +pub const ID_GOSTR3410_94_BBIS: Nid = Nid(ffi::NID_id_GostR3410_94_bBis); +pub const ID_GOST28147_89_CC: Nid = Nid(ffi::NID_id_Gost28147_89_cc); +pub const ID_GOSTR3410_94_CC: Nid = Nid(ffi::NID_id_GostR3410_94_cc); +pub const ID_GOSTR3410_2001_CC: Nid = Nid(ffi::NID_id_GostR3410_2001_cc); +pub const ID_GOSTR3411_94_WITH_GOSTR3410_94_CC: Nid = + Nid(ffi::NID_id_GostR3411_94_with_GostR3410_94_cc); +pub const ID_GOSTR3411_94_WITH_GOSTR3410_2001_CC: Nid = + Nid(ffi::NID_id_GostR3411_94_with_GostR3410_2001_cc); +pub const ID_GOSTR3410_2001_PARAMSET_CC: Nid = Nid(ffi::NID_id_GostR3410_2001_ParamSet_cc); +pub const CAMELLIA_128_CBC: Nid = Nid(ffi::NID_camellia_128_cbc); +pub const CAMELLIA_192_CBC: Nid = Nid(ffi::NID_camellia_192_cbc); +pub const CAMELLIA_256_CBC: Nid = Nid(ffi::NID_camellia_256_cbc); +pub const ID_CAMELLIA128_WRAP: Nid = Nid(ffi::NID_id_camellia128_wrap); +pub const ID_CAMELLIA192_WRAP: Nid = Nid(ffi::NID_id_camellia192_wrap); +pub const ID_CAMELLIA256_WRAP: Nid = Nid(ffi::NID_id_camellia256_wrap); +pub const CAMELLIA_128_ECB: Nid = Nid(ffi::NID_camellia_128_ecb); +pub const CAMELLIA_128_OFB128: Nid = Nid(ffi::NID_camellia_128_ofb128); +pub const CAMELLIA_128_CFB128: Nid = Nid(ffi::NID_camellia_128_cfb128); +pub const CAMELLIA_192_ECB: Nid = Nid(ffi::NID_camellia_192_ecb); +pub const CAMELLIA_192_OFB128: Nid = Nid(ffi::NID_camellia_192_ofb128); +pub const CAMELLIA_192_CFB128: Nid = Nid(ffi::NID_camellia_192_cfb128); +pub const CAMELLIA_256_ECB: Nid = Nid(ffi::NID_camellia_256_ecb); +pub const CAMELLIA_256_OFB128: Nid = Nid(ffi::NID_camellia_256_ofb128); +pub const CAMELLIA_256_CFB128: Nid = Nid(ffi::NID_camellia_256_cfb128); +pub const CAMELLIA_128_CFB1: Nid = Nid(ffi::NID_camellia_128_cfb1); +pub const CAMELLIA_192_CFB1: Nid = Nid(ffi::NID_camellia_192_cfb1); +pub const CAMELLIA_256_CFB1: Nid = Nid(ffi::NID_camellia_256_cfb1); +pub const CAMELLIA_128_CFB8: Nid = Nid(ffi::NID_camellia_128_cfb8); +pub const CAMELLIA_192_CFB8: Nid = Nid(ffi::NID_camellia_192_cfb8); +pub const CAMELLIA_256_CFB8: Nid = Nid(ffi::NID_camellia_256_cfb8); +pub const KISA: Nid = Nid(ffi::NID_kisa); +pub const SEED_ECB: Nid = Nid(ffi::NID_seed_ecb); +pub const SEED_CBC: Nid = Nid(ffi::NID_seed_cbc); +pub const SEED_CFB128: Nid = Nid(ffi::NID_seed_cfb128); +pub const SEED_OFB128: Nid = Nid(ffi::NID_seed_ofb128); +pub const HMAC: Nid = Nid(ffi::NID_hmac); +pub const CMAC: Nid = Nid(ffi::NID_cmac); +pub const RC4_HMAC_MD5: Nid = Nid(ffi::NID_rc4_hmac_md5); +pub const AES_128_CBC_HMAC_SHA1: Nid = Nid(ffi::NID_aes_128_cbc_hmac_sha1); +pub const AES_192_CBC_HMAC_SHA1: Nid = Nid(ffi::NID_aes_192_cbc_hmac_sha1); +pub const AES_256_CBC_HMAC_SHA1: Nid = Nid(ffi::NID_aes_256_cbc_hmac_sha1); diff --git a/openssl/src/crypto/pkcs12.rs b/openssl/src/pkcs12.rs similarity index 60% rename from openssl/src/crypto/pkcs12.rs rename to openssl/src/pkcs12.rs index 89bcbd5c..1ef0bf3f 100644 --- a/openssl/src/crypto/pkcs12.rs +++ b/openssl/src/pkcs12.rs @@ -6,18 +6,14 @@ use std::cmp; use std::ptr; use std::ffi::CString; -use crypto::pkey::PKey; +use {cvt, cvt_p}; +use pkey::PKey; use error::ErrorStack; use x509::X509; +use types::{OpenSslType, OpenSslTypeRef}; +use stack::Stack; -/// A PKCS #12 archive. -pub struct Pkcs12(*mut ffi::PKCS12); - -impl Drop for Pkcs12 { - fn drop(&mut self) { - unsafe { ffi::PKCS12_free(self.0); } - } -} +type_!(Pkcs12, Pkcs12Ref, ffi::PKCS12, ffi::PKCS12_free); impl Pkcs12 { /// Deserializes a `Pkcs12` structure from DER-encoded data. @@ -26,11 +22,13 @@ impl Pkcs12 { ffi::init(); let mut ptr = der.as_ptr() as *const c_uchar; let length = cmp::min(der.len(), c_long::max_value() as usize) as c_long; - let p12 = try_ssl_null!(ffi::d2i_PKCS12(ptr::null_mut(), &mut ptr, length)); + let p12 = try!(cvt_p(ffi::d2i_PKCS12(ptr::null_mut(), &mut ptr, length))); Ok(Pkcs12(p12)) } } +} +impl Pkcs12Ref { /// Extracts the contents of the `Pkcs12`. pub fn parse(&self, pass: &str) -> Result { unsafe { @@ -40,23 +38,20 @@ impl Pkcs12 { let mut cert = ptr::null_mut(); let mut chain = ptr::null_mut(); - try_ssl!(ffi::PKCS12_parse(self.0, pass.as_ptr(), &mut pkey, &mut cert, &mut chain)); + try!(cvt(ffi::PKCS12_parse(self.as_ptr(), + pass.as_ptr(), + &mut pkey, + &mut cert, + &mut chain))); let pkey = PKey::from_ptr(pkey); let cert = X509::from_ptr(cert); - - 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)); - } - ffi::sk_free(&mut (*chain).stack); + let chain = Stack::from_ptr(chain); Ok(ParsedPkcs12 { pkey: pkey, cert: cert, - chain: chain_out, - _p: (), + chain: chain, }) } } @@ -65,28 +60,27 @@ impl Pkcs12 { pub struct ParsedPkcs12 { pub pkey: PKey, pub cert: X509, - pub chain: Vec, - _p: (), + pub chain: Stack, } #[cfg(test)] mod test { - use crypto::hash::Type::SHA1; + use hash::MessageDigest; use serialize::hex::ToHex; use super::*; #[test] fn parse() { - let der = include_bytes!("../../test/identity.p12"); + let der = include_bytes!("../test/identity.p12"); let pkcs12 = Pkcs12::from_der(der).unwrap(); let parsed = pkcs12.parse("mypass").unwrap(); - assert_eq!(parsed.cert.fingerprint(SHA1).unwrap().to_hex(), + assert_eq!(parsed.cert.fingerprint(MessageDigest::sha1()).unwrap().to_hex(), "59172d9313e84459bcff27f967e79e6e9217e584"); assert_eq!(parsed.chain.len(), 1); - assert_eq!(parsed.chain[0].fingerprint(SHA1).unwrap().to_hex(), + assert_eq!(parsed.chain[0].fingerprint(MessageDigest::sha1()).unwrap().to_hex(), "c0cbdf7cdd03c9773e5468e1f6d2da7d5cbb1875"); } } diff --git a/openssl/src/pkcs5.rs b/openssl/src/pkcs5.rs new file mode 100644 index 00000000..8d6dcce8 --- /dev/null +++ b/openssl/src/pkcs5.rs @@ -0,0 +1,203 @@ +use libc::c_int; +use std::ptr; +use ffi; + +use cvt; +use hash::MessageDigest; +use symm::Cipher; +use error::ErrorStack; + +#[derive(Clone, Eq, PartialEq, Hash, Debug)] +pub struct KeyIvPair { + pub key: Vec, + pub iv: Option>, +} + +/// Derives a key and an IV from various parameters. +/// +/// If specified, `salt` must be 8 bytes in length. +/// +/// If the total key and IV length is less than 16 bytes and MD5 is used then +/// the algorithm is compatible with the key derivation algorithm from PKCS#5 +/// v1.5 or PBKDF1 from PKCS#5 v2.0. +/// +/// New applications should not use this and instead use +/// `pkcs5_pbkdf2_hmac_sha1` or another more modern key derivation algorithm. +pub fn bytes_to_key(cipher: Cipher, + digest: MessageDigest, + data: &[u8], + salt: Option<&[u8]>, + count: i32) + -> Result { + unsafe { + assert!(data.len() <= c_int::max_value() as usize); + let salt_ptr = match salt { + Some(salt) => { + assert_eq!(salt.len(), ffi::PKCS5_SALT_LEN as usize); + salt.as_ptr() + } + None => ptr::null(), + }; + + ffi::init(); + + let mut iv = cipher.iv_len().map(|l| vec![0; l]); + + let cipher = cipher.as_ptr(); + let digest = digest.as_ptr(); + + let len = try!(cvt(ffi::EVP_BytesToKey(cipher, + digest, + salt_ptr, + ptr::null(), + data.len() as c_int, + count.into(), + ptr::null_mut(), + ptr::null_mut()))); + + let mut key = vec![0; len as usize]; + let iv_ptr = iv.as_mut().map(|v| v.as_mut_ptr()).unwrap_or(ptr::null_mut()); + + try!(cvt(ffi::EVP_BytesToKey(cipher, + digest, + salt_ptr, + data.as_ptr(), + data.len() as c_int, + count as c_int, + key.as_mut_ptr(), + iv_ptr))); + + Ok(KeyIvPair { key: key, iv: iv }) + } +} + +/// Derives a key from a password and salt using the PBKDF2-HMAC algorithm with a digest function. +pub fn pbkdf2_hmac(pass: &[u8], + salt: &[u8], + iter: usize, + hash: MessageDigest, + key: &mut [u8]) + -> Result<(), ErrorStack> { + unsafe { + assert!(pass.len() <= c_int::max_value() as usize); + assert!(salt.len() <= c_int::max_value() as usize); + assert!(key.len() <= c_int::max_value() as usize); + + ffi::init(); + cvt(ffi::PKCS5_PBKDF2_HMAC(pass.as_ptr() as *const _, + pass.len() as c_int, + salt.as_ptr(), + salt.len() as c_int, + iter as c_int, + hash.as_ptr(), + key.len() as c_int, + key.as_mut_ptr())) + .map(|_| ()) + } +} + +#[cfg(test)] +mod tests { + use hash::MessageDigest; + use symm::Cipher; + + // Test vectors from + // https://git.lysator.liu.se/nettle/nettle/blob/nettle_3.1.1_release_20150424/testsuite/pbkdf2-test.c + #[test] + fn pbkdf2_hmac_sha256() { + let mut buf = [0; 16]; + + super::pbkdf2_hmac(b"passwd", b"salt", 1, MessageDigest::sha256(), &mut buf).unwrap(); + assert_eq!(buf, + &[0x55_u8, 0xac_u8, 0x04_u8, 0x6e_u8, 0x56_u8, 0xe3_u8, 0x08_u8, 0x9f_u8, + 0xec_u8, 0x16_u8, 0x91_u8, 0xc2_u8, 0x25_u8, 0x44_u8, 0xb6_u8, 0x05_u8][..]); + + super::pbkdf2_hmac(b"Password", + b"NaCl", + 80000, + MessageDigest::sha256(), + &mut buf) + .unwrap(); + assert_eq!(buf, + &[0x4d_u8, 0xdc_u8, 0xd8_u8, 0xf6_u8, 0x0b_u8, 0x98_u8, 0xbe_u8, 0x21_u8, + 0x83_u8, 0x0c_u8, 0xee_u8, 0x5e_u8, 0xf2_u8, 0x27_u8, 0x01_u8, 0xf9_u8][..]); + } + + // Test vectors from + // https://git.lysator.liu.se/nettle/nettle/blob/nettle_3.1.1_release_20150424/testsuite/pbkdf2-test.c + #[test] + fn pbkdf2_hmac_sha512() { + let mut buf = [0; 64]; + + super::pbkdf2_hmac(b"password", b"NaCL", 1, MessageDigest::sha512(), &mut buf).unwrap(); + assert_eq!(&buf[..], + &[0x73_u8, 0xde_u8, 0xcf_u8, 0xa5_u8, 0x8a_u8, 0xa2_u8, 0xe8_u8, 0x4f_u8, + 0x94_u8, 0x77_u8, 0x1a_u8, 0x75_u8, 0x73_u8, 0x6b_u8, 0xb8_u8, 0x8b_u8, + 0xd3_u8, 0xc7_u8, 0xb3_u8, 0x82_u8, 0x70_u8, 0xcf_u8, 0xb5_u8, 0x0c_u8, + 0xb3_u8, 0x90_u8, 0xed_u8, 0x78_u8, 0xb3_u8, 0x05_u8, 0x65_u8, 0x6a_u8, + 0xf8_u8, 0x14_u8, 0x8e_u8, 0x52_u8, 0x45_u8, 0x2b_u8, 0x22_u8, 0x16_u8, + 0xb2_u8, 0xb8_u8, 0x09_u8, 0x8b_u8, 0x76_u8, 0x1f_u8, 0xc6_u8, 0x33_u8, + 0x60_u8, 0x60_u8, 0xa0_u8, 0x9f_u8, 0x76_u8, 0x41_u8, 0x5e_u8, 0x9f_u8, + 0x71_u8, 0xea_u8, 0x47_u8, 0xf9_u8, 0xe9_u8, 0x06_u8, 0x43_u8, 0x06_u8][..]); + + super::pbkdf2_hmac(b"pass\0word", + b"sa\0lt", + 1, + MessageDigest::sha512(), + &mut buf) + .unwrap(); + assert_eq!(&buf[..], + &[0x71_u8, 0xa0_u8, 0xec_u8, 0x84_u8, 0x2a_u8, 0xbd_u8, 0x5c_u8, 0x67_u8, + 0x8b_u8, 0xcf_u8, 0xd1_u8, 0x45_u8, 0xf0_u8, 0x9d_u8, 0x83_u8, 0x52_u8, + 0x2f_u8, 0x93_u8, 0x36_u8, 0x15_u8, 0x60_u8, 0x56_u8, 0x3c_u8, 0x4d_u8, + 0x0d_u8, 0x63_u8, 0xb8_u8, 0x83_u8, 0x29_u8, 0x87_u8, 0x10_u8, 0x90_u8, + 0xe7_u8, 0x66_u8, 0x04_u8, 0xa4_u8, 0x9a_u8, 0xf0_u8, 0x8f_u8, 0xe7_u8, + 0xc9_u8, 0xf5_u8, 0x71_u8, 0x56_u8, 0xc8_u8, 0x79_u8, 0x09_u8, 0x96_u8, + 0xb2_u8, 0x0f_u8, 0x06_u8, 0xbc_u8, 0x53_u8, 0x5e_u8, 0x5a_u8, 0xb5_u8, + 0x44_u8, 0x0d_u8, 0xf7_u8, 0xe8_u8, 0x78_u8, 0x29_u8, 0x6f_u8, 0xa7_u8][..]); + + super::pbkdf2_hmac(b"passwordPASSWORDpassword", + b"salt\0\0\0", + 50, + MessageDigest::sha512(), + &mut buf) + .unwrap(); + assert_eq!(&buf[..], + &[0x01_u8, 0x68_u8, 0x71_u8, 0xa4_u8, 0xc4_u8, 0xb7_u8, 0x5f_u8, 0x96_u8, + 0x85_u8, 0x7f_u8, 0xd2_u8, 0xb9_u8, 0xf8_u8, 0xca_u8, 0x28_u8, 0x02_u8, + 0x3b_u8, 0x30_u8, 0xee_u8, 0x2a_u8, 0x39_u8, 0xf5_u8, 0xad_u8, 0xca_u8, + 0xc8_u8, 0xc9_u8, 0x37_u8, 0x5f_u8, 0x9b_u8, 0xda_u8, 0x1c_u8, 0xcd_u8, + 0x1b_u8, 0x6f_u8, 0x0b_u8, 0x2f_u8, 0xc3_u8, 0xad_u8, 0xda_u8, 0x50_u8, + 0x54_u8, 0x12_u8, 0xe7_u8, 0x9d_u8, 0x89_u8, 0x00_u8, 0x56_u8, 0xc6_u8, + 0x2e_u8, 0x52_u8, 0x4c_u8, 0x7d_u8, 0x51_u8, 0x15_u8, 0x4b_u8, 0x1a_u8, + 0x85_u8, 0x34_u8, 0x57_u8, 0x5b_u8, 0xd0_u8, 0x2d_u8, 0xee_u8, 0x39_u8][..]); + } + #[test] + fn bytes_to_key() { + let salt = [16_u8, 34_u8, 19_u8, 23_u8, 141_u8, 4_u8, 207_u8, 221_u8]; + + let data = [143_u8, 210_u8, 75_u8, 63_u8, 214_u8, 179_u8, 155_u8, 241_u8, 242_u8, 31_u8, + 154_u8, 56_u8, 198_u8, 145_u8, 192_u8, 64_u8, 2_u8, 245_u8, 167_u8, 220_u8, + 55_u8, 119_u8, 233_u8, 136_u8, 139_u8, 27_u8, 71_u8, 242_u8, 119_u8, 175_u8, + 65_u8, 207_u8]; + + + + let expected_key = vec![249_u8, 115_u8, 114_u8, 97_u8, 32_u8, 213_u8, 165_u8, 146_u8, + 58_u8, 87_u8, 234_u8, 3_u8, 43_u8, 250_u8, 97_u8, 114_u8, 26_u8, + 98_u8, 245_u8, 246_u8, 238_u8, 177_u8, 229_u8, 161_u8, 183_u8, + 224_u8, 174_u8, 3_u8, 6_u8, 244_u8, 236_u8, 255_u8]; + let expected_iv = vec![4_u8, 223_u8, 153_u8, 219_u8, 28_u8, 142_u8, 234_u8, 68_u8, 227_u8, + 69_u8, 98_u8, 107_u8, 208_u8, 14_u8, 236_u8, 60_u8]; + + assert_eq!(super::bytes_to_key(Cipher::aes_256_cbc(), + MessageDigest::sha1(), + &data, + Some(&salt), + 1).unwrap(), + super::KeyIvPair { + key: expected_key, + iv: Some(expected_iv), + }); + } +} diff --git a/openssl/src/pkey.rs b/openssl/src/pkey.rs new file mode 100644 index 00000000..a1ebd695 --- /dev/null +++ b/openssl/src/pkey.rs @@ -0,0 +1,178 @@ +use libc::{c_void, c_char, c_int}; +use std::ptr; +use std::mem; +use ffi; + +use {cvt, cvt_p}; +use bio::{MemBio, MemBioSlice}; +use dsa::Dsa; +use rsa::Rsa; +use error::ErrorStack; +use util::{CallbackState, invoke_passwd_cb}; +use types::{OpenSslType, OpenSslTypeRef}; + +type_!(PKey, PKeyRef, ffi::EVP_PKEY, ffi::EVP_PKEY_free); + +impl PKeyRef { + /// Get a reference to the interal RSA key for direct access to the key components + pub fn rsa(&self) -> Result { + unsafe { + let rsa = try!(cvt_p(ffi::EVP_PKEY_get1_RSA(self.as_ptr()))); + // this is safe as the ffi increments a reference counter to the internal key + Ok(Rsa::from_ptr(rsa)) + } + } + + /// Stores private key as a PEM + // FIXME: also add password and encryption + pub fn private_key_to_pem(&self) -> Result, ErrorStack> { + let mem_bio = try!(MemBio::new()); + unsafe { + try!(cvt(ffi::PEM_write_bio_PrivateKey(mem_bio.as_ptr(), + self.as_ptr(), + ptr::null(), + ptr::null_mut(), + -1, + None, + ptr::null_mut()))); + + } + Ok(mem_bio.get_buf().to_owned()) + } + + /// Encode public key in PEM format + pub fn public_key_to_pem(&self) -> Result, ErrorStack> { + let mem_bio = try!(MemBio::new()); + unsafe { + try!(cvt(ffi::PEM_write_bio_PUBKEY(mem_bio.as_ptr(), self.as_ptr()))); + } + Ok(mem_bio.get_buf().to_owned()) + } + + /// Encode public key in DER format + pub fn public_key_to_der(&self) -> Result, ErrorStack> { + let mem_bio = try!(MemBio::new()); + unsafe { + try!(cvt(ffi::i2d_PUBKEY_bio(mem_bio.as_ptr(), self.as_ptr()))); + } + Ok(mem_bio.get_buf().to_owned()) + } + + pub fn public_eq(&self, other: &PKeyRef) -> bool { + unsafe { ffi::EVP_PKEY_cmp(self.as_ptr(), other.as_ptr()) == 1 } + } +} + +unsafe impl Send for PKey {} +unsafe impl Sync for PKey {} + +impl PKey { + /// Create a new `PKey` containing an RSA key. + pub fn from_rsa(rsa: Rsa) -> Result { + unsafe { + let evp = try!(cvt_p(ffi::EVP_PKEY_new())); + let pkey = PKey(evp); + try!(cvt(ffi::EVP_PKEY_assign(pkey.0, ffi::EVP_PKEY_RSA, rsa.as_ptr() as *mut _))); + mem::forget(rsa); + Ok(pkey) + } + } + + /// Create a new `PKey` containing a DSA key. + pub fn from_dsa(dsa: Dsa) -> Result { + unsafe { + let evp = try!(cvt_p(ffi::EVP_PKEY_new())); + let pkey = PKey(evp); + try!(cvt(ffi::EVP_PKEY_assign(pkey.0, ffi::EVP_PKEY_DSA, dsa.as_ptr() as *mut _))); + mem::forget(dsa); + Ok(pkey) + } + } + + /// Create a new `PKey` containing an HMAC key. + pub fn hmac(key: &[u8]) -> Result { + unsafe { + assert!(key.len() <= c_int::max_value() as usize); + let key = try!(cvt_p(ffi::EVP_PKEY_new_mac_key(ffi::EVP_PKEY_HMAC, + ptr::null_mut(), + key.as_ptr() as *const _, + key.len() as c_int))); + Ok(PKey(key)) + } + } + + /// Reads private key from PEM, takes ownership of handle + pub fn private_key_from_pem(buf: &[u8]) -> Result { + ffi::init(); + let mem_bio = try!(MemBioSlice::new(buf)); + unsafe { + let evp = try!(cvt_p(ffi::PEM_read_bio_PrivateKey(mem_bio.as_ptr(), + ptr::null_mut(), + None, + ptr::null_mut()))); + Ok(PKey::from_ptr(evp)) + } + } + + /// Read a private key from PEM, supplying a password callback to be invoked if the private key + /// is encrypted. + /// + /// The callback will be passed the password buffer and should return the number of characters + /// placed into the buffer. + pub fn private_key_from_pem_cb(buf: &[u8], pass_cb: F) -> Result + where F: FnOnce(&mut [c_char]) -> usize + { + ffi::init(); + let mut cb = CallbackState::new(pass_cb); + let mem_bio = try!(MemBioSlice::new(buf)); + unsafe { + let evp = try!(cvt_p(ffi::PEM_read_bio_PrivateKey(mem_bio.as_ptr(), + ptr::null_mut(), + Some(invoke_passwd_cb::), + &mut cb as *mut _ as *mut c_void))); + Ok(PKey::from_ptr(evp)) + } + } + + /// Reads public key from PEM, takes ownership of handle + pub fn public_key_from_pem(buf: &[u8]) -> Result { + ffi::init(); + let mem_bio = try!(MemBioSlice::new(buf)); + unsafe { + let evp = try!(cvt_p(ffi::PEM_read_bio_PUBKEY(mem_bio.as_ptr(), + ptr::null_mut(), + None, + ptr::null_mut()))); + Ok(PKey::from_ptr(evp)) + } + } +} + +#[cfg(test)] +mod tests { + #[test] + fn test_private_key_from_pem() { + let key = include_bytes!("../test/key.pem"); + super::PKey::private_key_from_pem(key).unwrap(); + } + + #[test] + fn test_public_key_from_pem() { + let key = include_bytes!("../test/key.pem.pub"); + super::PKey::public_key_from_pem(key).unwrap(); + } + + #[test] + fn test_pem() { + let key = include_bytes!("../test/key.pem"); + let key = super::PKey::private_key_from_pem(key).unwrap(); + + let priv_key = key.private_key_to_pem().unwrap(); + let pub_key = key.public_key_to_pem().unwrap(); + + // As a super-simple verification, just check that the buffers contain + // the `PRIVATE KEY` or `PUBLIC KEY` strings. + assert!(priv_key.windows(11).any(|s| s == b"PRIVATE KEY")); + assert!(pub_key.windows(10).any(|s| s == b"PUBLIC KEY")); + } +} diff --git a/openssl/src/crypto/rand.rs b/openssl/src/rand.rs similarity index 80% rename from openssl/src/crypto/rand.rs rename to openssl/src/rand.rs index 519449e9..c1c49e7b 100644 --- a/openssl/src/crypto/rand.rs +++ b/openssl/src/rand.rs @@ -1,13 +1,14 @@ use libc::c_int; use ffi; + +use cvt; use error::ErrorStack; pub fn rand_bytes(buf: &mut [u8]) -> Result<(), ErrorStack> { unsafe { ffi::init(); assert!(buf.len() <= c_int::max_value() as usize); - try_ssl_if!(ffi::RAND_bytes(buf.as_mut_ptr(), buf.len() as c_int) != 1); - Ok(()) + cvt(ffi::RAND_bytes(buf.as_mut_ptr(), buf.len() as c_int)).map(|_| ()) } } diff --git a/openssl/src/rsa.rs b/openssl/src/rsa.rs new file mode 100644 index 00000000..bd1d16d3 --- /dev/null +++ b/openssl/src/rsa.rs @@ -0,0 +1,457 @@ +use ffi; +use std::fmt; +use std::ptr; +use std::mem; +use libc::{c_int, c_void, c_char}; + +use {cvt, cvt_p, cvt_n}; +use bn::{BigNum, BigNumRef}; +use bio::{MemBio, MemBioSlice}; +use error::ErrorStack; +use util::{CallbackState, invoke_passwd_cb}; +use types::OpenSslTypeRef; + +/// Type of encryption padding to use. +#[derive(Copy, Clone)] +pub struct Padding(c_int); + +pub const NO_PADDING: Padding = Padding(ffi::RSA_NO_PADDING); +pub const PKCS1_PADDING: Padding = Padding(ffi::RSA_PKCS1_PADDING); +pub const PKCS1_OAEP_PADDING: Padding = Padding(ffi::RSA_PKCS1_OAEP_PADDING); + +type_!(Rsa, RsaRef, ffi::RSA, ffi::RSA_free); + +impl RsaRef { + /// Writes an RSA private key as unencrypted PEM formatted data + pub fn private_key_to_pem(&self) -> Result, ErrorStack> { + let mem_bio = try!(MemBio::new()); + + unsafe { + try!(cvt(ffi::PEM_write_bio_RSAPrivateKey(mem_bio.as_ptr(), + self.as_ptr(), + ptr::null(), + ptr::null_mut(), + 0, + None, + ptr::null_mut()))); + } + Ok(mem_bio.get_buf().to_owned()) + } + + /// Writes an RSA public key as PEM formatted data + pub fn public_key_to_pem(&self) -> Result, ErrorStack> { + let mem_bio = try!(MemBio::new()); + + unsafe { + try!(cvt(ffi::PEM_write_bio_RSA_PUBKEY(mem_bio.as_ptr(), self.as_ptr()))); + } + + Ok(mem_bio.get_buf().to_owned()) + } + + pub fn size(&self) -> usize { + unsafe { + assert!(self.n().is_some()); + + ffi::RSA_size(self.as_ptr()) as usize + } + } + + /// Decrypts data using the private key, returning the number of decrypted bytes. + /// + /// # Panics + /// + /// Panics if `self` has no private components, or if `to` is smaller + /// than `self.size()`. + pub fn private_decrypt(&self, + from: &[u8], + to: &mut [u8], + padding: Padding) + -> Result { + assert!(self.d().is_some(), "private components missing"); + assert!(from.len() <= i32::max_value() as usize); + assert!(to.len() >= self.size()); + + unsafe { + let len = try!(cvt_n(ffi::RSA_private_decrypt(from.len() as c_int, + from.as_ptr(), + to.as_mut_ptr(), + self.as_ptr(), + padding.0))); + Ok(len as usize) + } + } + + /// Encrypts data using the private key, returning the number of encrypted bytes. + /// + /// # Panics + /// + /// Panics if `self` has no private components, or if `to` is smaller + /// than `self.size()`. + pub fn private_encrypt(&self, + from: &[u8], + to: &mut [u8], + padding: Padding) + -> Result { + assert!(self.d().is_some(), "private components missing"); + assert!(from.len() <= i32::max_value() as usize); + assert!(to.len() >= self.size()); + + unsafe { + let len = try!(cvt_n(ffi::RSA_private_encrypt(from.len() as c_int, + from.as_ptr(), + to.as_mut_ptr(), + self.as_ptr(), + padding.0))); + Ok(len as usize) + } + } + + /// Decrypts data using the public key, returning the number of decrypted bytes. + /// + /// # Panics + /// + /// Panics if `to` is smaller than `self.size()`. + pub fn public_decrypt(&self, + from: &[u8], + to: &mut [u8], + padding: Padding) + -> Result { + assert!(from.len() <= i32::max_value() as usize); + assert!(to.len() >= self.size()); + + unsafe { + let len = try!(cvt_n(ffi::RSA_public_decrypt(from.len() as c_int, + from.as_ptr(), + to.as_mut_ptr(), + self.as_ptr(), + padding.0))); + Ok(len as usize) + } + } + + /// Encrypts data using the private key, returning the number of encrypted bytes. + /// + /// # Panics + /// + /// Panics if `to` is smaller than `self.size()`. + pub fn public_encrypt(&self, + from: &[u8], + to: &mut [u8], + padding: Padding) + -> Result { + assert!(from.len() <= i32::max_value() as usize); + assert!(to.len() >= self.size()); + + unsafe { + let len = try!(cvt_n(ffi::RSA_public_encrypt(from.len() as c_int, + from.as_ptr(), + to.as_mut_ptr(), + self.as_ptr(), + padding.0))); + Ok(len as usize) + } + } + + pub fn n(&self) -> Option<&BigNumRef> { + unsafe { + let n = compat::key(self.as_ptr())[0]; + if n.is_null() { + None + } else { + Some(BigNumRef::from_ptr(n as *mut _)) + } + } + } + + pub fn d(&self) -> Option<&BigNumRef> { + unsafe { + let d = compat::key(self.as_ptr())[2]; + if d.is_null() { + None + } else { + Some(BigNumRef::from_ptr(d as *mut _)) + } + } + } + + pub fn e(&self) -> Option<&BigNumRef> { + unsafe { + let e = compat::key(self.as_ptr())[1]; + if e.is_null() { + None + } else { + Some(BigNumRef::from_ptr(e as *mut _)) + } + } + } + + pub fn p(&self) -> Option<&BigNumRef> { + unsafe { + let p = compat::factors(self.as_ptr())[0]; + if p.is_null() { + None + } else { + Some(BigNumRef::from_ptr(p as *mut _)) + } + } + } + + pub fn q(&self) -> Option<&BigNumRef> { + unsafe { + let q = compat::factors(self.as_ptr())[1]; + if q.is_null() { + None + } else { + Some(BigNumRef::from_ptr(q as *mut _)) + } + } + } +} + +impl Rsa { + /// only useful for associating the key material directly with the key, it's safer to use + /// the supplied load and save methods for DER formatted keys. + pub fn from_public_components(n: BigNum, e: BigNum) -> Result { + unsafe { + let rsa = Rsa(try!(cvt_p(ffi::RSA_new()))); + try!(cvt(compat::set_key(rsa.0, + n.as_ptr(), + e.as_ptr(), + ptr::null_mut()))); + mem::forget((n, e)); + Ok(rsa) + } + } + + pub fn from_private_components(n: BigNum, + e: BigNum, + d: BigNum, + p: BigNum, + q: BigNum, + dp: BigNum, + dq: BigNum, + qi: BigNum) + -> Result { + unsafe { + let rsa = Rsa(try!(cvt_p(ffi::RSA_new()))); + try!(cvt(compat::set_key(rsa.0, n.as_ptr(), e.as_ptr(), d.as_ptr()))); + mem::forget((n, e, d)); + try!(cvt(compat::set_factors(rsa.0, p.as_ptr(), q.as_ptr()))); + mem::forget((p, q)); + try!(cvt(compat::set_crt_params(rsa.0, dp.as_ptr(), dq.as_ptr(), + qi.as_ptr()))); + mem::forget((dp, dq, qi)); + Ok(rsa) + } + } + + /// Generates a public/private key pair with the specified size. + /// + /// The public exponent will be 65537. + pub fn generate(bits: u32) -> Result { + unsafe { + let rsa = Rsa(try!(cvt_p(ffi::RSA_new()))); + let e = try!(BigNum::from_u32(ffi::RSA_F4 as u32)); + try!(cvt(ffi::RSA_generate_key_ex(rsa.0, bits as c_int, e.as_ptr(), ptr::null_mut()))); + Ok(rsa) + } + } + + /// Reads an RSA private key from PEM formatted data. + pub fn private_key_from_pem(buf: &[u8]) -> Result { + let mem_bio = try!(MemBioSlice::new(buf)); + unsafe { + let rsa = try!(cvt_p(ffi::PEM_read_bio_RSAPrivateKey(mem_bio.as_ptr(), + ptr::null_mut(), + None, + ptr::null_mut()))); + Ok(Rsa(rsa)) + } + } + + /// Reads an RSA private key from PEM formatted data and supplies a password callback. + pub fn private_key_from_pem_cb(buf: &[u8], pass_cb: F) -> Result + where F: FnOnce(&mut [c_char]) -> usize + { + let mut cb = CallbackState::new(pass_cb); + let mem_bio = try!(MemBioSlice::new(buf)); + + unsafe { + let cb_ptr = &mut cb as *mut _ as *mut c_void; + let rsa = try!(cvt_p(ffi::PEM_read_bio_RSAPrivateKey(mem_bio.as_ptr(), + ptr::null_mut(), + Some(invoke_passwd_cb::), + cb_ptr))); + Ok(Rsa(rsa)) + } + } + + /// Reads an RSA public key from PEM formatted data. + pub fn public_key_from_pem(buf: &[u8]) -> Result { + let mem_bio = try!(MemBioSlice::new(buf)); + unsafe { + let rsa = try!(cvt_p(ffi::PEM_read_bio_RSA_PUBKEY(mem_bio.as_ptr(), + ptr::null_mut(), + None, + ptr::null_mut()))); + Ok(Rsa(rsa)) + } + } +} + +impl fmt::Debug for Rsa { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "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 libc::c_char; + + use super::*; + + #[test] + pub fn test_password() { + let mut password_queried = false; + let key = include_bytes!("../test/rsa-encrypted.pem"); + Rsa::private_key_from_pem_cb(key, |password| { + password_queried = true; + password[0] = b'm' as c_char; + password[1] = b'y' as c_char; + password[2] = b'p' as c_char; + password[3] = b'a' as c_char; + password[4] = b's' as c_char; + password[5] = b's' as c_char; + 6 + }) + .unwrap(); + + assert!(password_queried); + } + + #[test] + pub fn test_public_encrypt_private_decrypt_with_padding() { + let key = include_bytes!("../test/rsa.pem.pub"); + let public_key = Rsa::public_key_from_pem(key).unwrap(); + + let mut result = vec![0; public_key.size()]; + let original_data = b"This is test"; + let len = public_key.public_encrypt(original_data, &mut result, PKCS1_PADDING).unwrap(); + assert_eq!(len, 256); + + let pkey = include_bytes!("../test/rsa.pem"); + let private_key = Rsa::private_key_from_pem(pkey).unwrap(); + let mut dec_result = vec![0; private_key.size()]; + let len = private_key.private_decrypt(&result, &mut dec_result, PKCS1_PADDING).unwrap(); + + assert_eq!(&dec_result[..len], original_data); + } + + #[test] + fn test_private_encrypt() { + let k0 = super::Rsa::generate(512).unwrap(); + let k0pkey = k0.public_key_to_pem().unwrap(); + let k1 = super::Rsa::public_key_from_pem(&k0pkey).unwrap(); + + let msg = vec![0xdeu8, 0xadu8, 0xd0u8, 0x0du8]; + + let mut emesg = vec![0; k0.size()]; + k0.private_encrypt(&msg, &mut emesg, PKCS1_PADDING).unwrap(); + let mut dmesg = vec![0; k1.size()]; + let len = k1.public_decrypt(&emesg, &mut dmesg, PKCS1_PADDING).unwrap(); + assert_eq!(msg, &dmesg[..len]); + } + + #[test] + fn test_public_encrypt() { + let k0 = super::Rsa::generate(512).unwrap(); + let k0pkey = k0.private_key_to_pem().unwrap(); + let k1 = super::Rsa::private_key_from_pem(&k0pkey).unwrap(); + + let msg = vec![0xdeu8, 0xadu8, 0xd0u8, 0x0du8]; + + let mut emesg = vec![0; k0.size()]; + k0.public_encrypt(&msg, &mut emesg, PKCS1_PADDING).unwrap(); + let mut dmesg = vec![0; k1.size()]; + let len = k1.private_decrypt(&emesg, &mut dmesg, PKCS1_PADDING).unwrap(); + assert_eq!(msg, &dmesg[..len]); + } + +} diff --git a/openssl/src/sign.rs b/openssl/src/sign.rs new file mode 100644 index 00000000..4ca551b6 --- /dev/null +++ b/openssl/src/sign.rs @@ -0,0 +1,397 @@ +//! Message signatures. +//! +//! The `Signer` allows for the computation of cryptographic signatures of +//! data given a private key. The `Verifier` can then be used with the +//! corresponding public key to verify the integrity and authenticity of that +//! data given the signature. +//! +//! # Examples +//! +//! Sign and verify data given an RSA keypair: +//! +//! ```rust +//! use openssl::sign::{Signer, Verifier}; +//! use openssl::rsa::Rsa; +//! use openssl::pkey::PKey; +//! use openssl::hash::MessageDigest; +//! +//! // Generate a keypair +//! let keypair = Rsa::generate(2048).unwrap(); +//! let keypair = PKey::from_rsa(keypair).unwrap(); +//! +//! let data = b"hello, world!"; +//! let data2 = b"hola, mundo!"; +//! +//! // Sign the data +//! let mut signer = Signer::new(MessageDigest::sha256(), &keypair).unwrap(); +//! signer.update(data).unwrap(); +//! signer.update(data2).unwrap(); +//! let signature = signer.finish().unwrap(); +//! +//! // Verify the data +//! let mut verifier = Verifier::new(MessageDigest::sha256(), &keypair).unwrap(); +//! verifier.update(data).unwrap(); +//! verifier.update(data2).unwrap(); +//! assert!(verifier.finish(&signature).unwrap()); +//! ``` +//! +//! Compute an HMAC (note that `Verifier` cannot be used with HMACs): +//! +//! ```rust +//! use openssl::sign::Signer; +//! use openssl::pkey::PKey; +//! use openssl::hash::MessageDigest; +//! +//! // Create a PKey +//! let key = PKey::hmac(b"my secret").unwrap(); +//! +//! let data = b"hello, world!"; +//! let data2 = b"hola, mundo!"; +//! +//! // Compute the HMAC +//! let mut signer = Signer::new(MessageDigest::sha256(), &key).unwrap(); +//! signer.update(data).unwrap(); +//! signer.update(data2).unwrap(); +//! let hmac = signer.finish().unwrap(); +//! ``` +use ffi; +use std::io::{self, Write}; +use std::marker::PhantomData; +use std::ptr; + +use {cvt, cvt_p}; +use hash::MessageDigest; +use pkey::PKeyRef; +use error::ErrorStack; +use types::OpenSslTypeRef; + +#[cfg(ossl110)] +use ffi::{EVP_MD_CTX_new, EVP_MD_CTX_free}; +#[cfg(any(ossl101, ossl102))] +use ffi::{EVP_MD_CTX_create as EVP_MD_CTX_new, EVP_MD_CTX_destroy as EVP_MD_CTX_free}; + +pub struct Signer<'a>(*mut ffi::EVP_MD_CTX, PhantomData<&'a PKeyRef>); + +impl<'a> Drop for Signer<'a> { + fn drop(&mut self) { + unsafe { + EVP_MD_CTX_free(self.0); + } + } +} + +impl<'a> Signer<'a> { + pub fn new(type_: MessageDigest, pkey: &'a PKeyRef) -> Result, ErrorStack> { + unsafe { + ffi::init(); + + let ctx = try!(cvt_p(EVP_MD_CTX_new())); + let r = ffi::EVP_DigestSignInit(ctx, + ptr::null_mut(), + type_.as_ptr(), + ptr::null_mut(), + pkey.as_ptr()); + if r != 1 { + EVP_MD_CTX_free(ctx); + return Err(ErrorStack::get()); + } + Ok(Signer(ctx, PhantomData)) + } + } + + pub fn update(&mut self, buf: &[u8]) -> Result<(), ErrorStack> { + unsafe { + cvt(ffi::EVP_DigestUpdate(self.0, buf.as_ptr() as *const _, buf.len())).map(|_| ()) + } + } + + pub fn finish(&self) -> Result, ErrorStack> { + unsafe { + let mut len = 0; + try!(cvt(ffi::EVP_DigestSignFinal(self.0, ptr::null_mut(), &mut len))); + let mut buf = vec![0; len]; + try!(cvt(ffi::EVP_DigestSignFinal(self.0, buf.as_mut_ptr() as *mut _, &mut len))); + // The advertised length is not always equal to the real length for things like DSA + buf.truncate(len); + Ok(buf) + } + } +} + +impl<'a> Write for Signer<'a> { + fn write(&mut self, buf: &[u8]) -> io::Result { + try!(self.update(buf)); + Ok(buf.len()) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +pub struct Verifier<'a>(*mut ffi::EVP_MD_CTX, PhantomData<&'a PKeyRef>); + +impl<'a> Drop for Verifier<'a> { + fn drop(&mut self) { + unsafe { + EVP_MD_CTX_free(self.0); + } + } +} + +impl<'a> Verifier<'a> { + pub fn new(type_: MessageDigest, pkey: &'a PKeyRef) -> Result, ErrorStack> { + unsafe { + ffi::init(); + + let ctx = try!(cvt_p(EVP_MD_CTX_new())); + let r = ffi::EVP_DigestVerifyInit(ctx, + ptr::null_mut(), + type_.as_ptr(), + ptr::null_mut(), + pkey.as_ptr()); + if r != 1 { + EVP_MD_CTX_free(ctx); + return Err(ErrorStack::get()); + } + + Ok(Verifier(ctx, PhantomData)) + } + } + + pub fn update(&mut self, buf: &[u8]) -> Result<(), ErrorStack> { + unsafe { + cvt(ffi::EVP_DigestUpdate(self.0, buf.as_ptr() as *const _, buf.len())).map(|_| ()) + } + } + + pub fn finish(&self, signature: &[u8]) -> Result { + unsafe { + let r = EVP_DigestVerifyFinal(self.0, signature.as_ptr() as *const _, signature.len()); + match r { + 1 => Ok(true), + 0 => { + ErrorStack::get(); // discard error stack + Ok(false) + } + _ => Err(ErrorStack::get()), + } + } + } +} + +impl<'a> Write for Verifier<'a> { + fn write(&mut self, buf: &[u8]) -> io::Result { + try!(self.update(buf)); + Ok(buf.len()) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +#[cfg(not(ossl101))] +use ffi::EVP_DigestVerifyFinal; + +#[cfg(ossl101)] +#[allow(bad_style)] +unsafe fn EVP_DigestVerifyFinal(ctx: *mut ffi::EVP_MD_CTX, + sigret: *const ::libc::c_uchar, + siglen: ::libc::size_t) + -> ::libc::c_int { + ffi::EVP_DigestVerifyFinal(ctx, sigret as *mut _, siglen) +} + +#[cfg(test)] +mod test { + use serialize::hex::FromHex; + use std::iter; + + use hash::MessageDigest; + use sign::{Signer, Verifier}; + use rsa::Rsa; + use dsa::Dsa; + use pkey::PKey; + + static INPUT: &'static [u8] = + &[101, 121, 74, 104, 98, 71, 99, 105, 79, 105, 74, 83, 85, 122, 73, 49, 78, 105, 74, 57, + 46, 101, 121, 74, 112, 99, 51, 77, 105, 79, 105, 74, 113, 98, 50, 85, 105, 76, 65, 48, + 75, 73, 67, 74, 108, 101, 72, 65, 105, 79, 106, 69, 122, 77, 68, 65, 52, 77, 84, 107, + 122, 79, 68, 65, 115, 68, 81, 111, 103, 73, 109, 104, 48, 100, 72, 65, 54, 76, 121, 57, + 108, 101, 71, 70, 116, 99, 71, 120, 108, 76, 109, 78, 118, 98, 83, 57, 112, 99, 49, 57, + 121, 98, 50, 57, 48, 73, 106, 112, 48, 99, 110, 86, 108, 102, 81]; + + static SIGNATURE: &'static [u8] = + &[112, 46, 33, 137, 67, 232, 143, 209, 30, 181, 216, 45, 191, 120, 69, 243, 65, 6, 174, + 27, 129, 255, 247, 115, 17, 22, 173, 209, 113, 125, 131, 101, 109, 66, 10, 253, 60, 150, + 238, 221, 115, 162, 102, 62, 81, 102, 104, 123, 0, 11, 135, 34, 110, 1, 135, 237, 16, + 115, 249, 69, 229, 130, 173, 252, 239, 22, 216, 90, 121, 142, 232, 198, 109, 219, 61, + 184, 151, 91, 23, 208, 148, 2, 190, 237, 213, 217, 217, 112, 7, 16, 141, 178, 129, 96, + 213, 248, 4, 12, 167, 68, 87, 98, 184, 31, 190, 127, 249, 217, 46, 10, 231, 111, 36, + 242, 91, 51, 187, 230, 244, 74, 230, 30, 177, 4, 10, 203, 32, 4, 77, 62, 249, 18, 142, + 212, 1, 48, 121, 91, 212, 189, 59, 65, 238, 202, 208, 102, 171, 101, 25, 129, 253, 228, + 141, 247, 127, 55, 45, 195, 139, 159, 175, 221, 59, 239, 177, 139, 93, 163, 204, 60, 46, + 176, 47, 158, 58, 65, 214, 18, 202, 173, 21, 145, 18, 115, 160, 95, 35, 185, 232, 56, + 250, 175, 132, 157, 105, 132, 41, 239, 90, 30, 136, 121, 130, 54, 195, 212, 14, 96, 69, + 34, 165, 68, 200, 242, 122, 122, 45, 184, 6, 99, 209, 108, 247, 202, 234, 86, 222, 64, + 92, 178, 33, 90, 69, 178, 194, 85, 102, 181, 90, 193, 167, 72, 160, 112, 223, 200, 163, + 42, 70, 149, 67, 208, 25, 238, 251, 71]; + + #[test] + fn rsa_sign() { + let key = include_bytes!("../test/rsa.pem"); + let private_key = Rsa::private_key_from_pem(key).unwrap(); + let pkey = PKey::from_rsa(private_key).unwrap(); + + let mut signer = Signer::new(MessageDigest::sha256(), &pkey).unwrap(); + signer.update(INPUT).unwrap(); + let result = signer.finish().unwrap(); + + assert_eq!(result, SIGNATURE); + } + + #[test] + fn rsa_verify_ok() { + let key = include_bytes!("../test/rsa.pem"); + let private_key = Rsa::private_key_from_pem(key).unwrap(); + let pkey = PKey::from_rsa(private_key).unwrap(); + + let mut verifier = Verifier::new(MessageDigest::sha256(), &pkey).unwrap(); + verifier.update(INPUT).unwrap(); + assert!(verifier.finish(SIGNATURE).unwrap()); + } + + #[test] + fn rsa_verify_invalid() { + let key = include_bytes!("../test/rsa.pem"); + let private_key = Rsa::private_key_from_pem(key).unwrap(); + let pkey = PKey::from_rsa(private_key).unwrap(); + + let mut verifier = Verifier::new(MessageDigest::sha256(), &pkey).unwrap(); + verifier.update(INPUT).unwrap(); + verifier.update(b"foobar").unwrap(); + assert!(!verifier.finish(SIGNATURE).unwrap()); + } + + #[test] + pub fn dsa_sign_verify() { + let input: Vec = (0..25).cycle().take(1024).collect(); + + let private_key = { + let key = include_bytes!("../test/dsa.pem"); + PKey::from_dsa(Dsa::private_key_from_pem(key).unwrap()).unwrap() + }; + + let public_key = { + let key = include_bytes!("../test/dsa.pem.pub"); + PKey::from_dsa(Dsa::public_key_from_pem(key).unwrap()).unwrap() + }; + + let mut signer = Signer::new(MessageDigest::sha1(), &private_key).unwrap(); + signer.update(&input).unwrap(); + let sig = signer.finish().unwrap(); + + let mut verifier = Verifier::new(MessageDigest::sha1(), &public_key).unwrap(); + verifier.update(&input).unwrap(); + assert!(verifier.finish(&sig).unwrap()); + } + + #[test] + pub fn dsa_sign_verify_fail() { + let input: Vec = (0..25).cycle().take(1024).collect(); + + let private_key = { + let key = include_bytes!("../test/dsa.pem"); + PKey::from_dsa(Dsa::private_key_from_pem(key).unwrap()).unwrap() + }; + + let public_key = { + let key = include_bytes!("../test/dsa.pem.pub"); + PKey::from_dsa(Dsa::public_key_from_pem(key).unwrap()).unwrap() + }; + + let mut signer = Signer::new(MessageDigest::sha1(), &private_key).unwrap(); + signer.update(&input).unwrap(); + let mut sig = signer.finish().unwrap(); + sig[0] -= 1; + + let mut verifier = Verifier::new(MessageDigest::sha1(), &public_key).unwrap(); + verifier.update(&input).unwrap(); + match verifier.finish(&sig) { + Ok(true) => panic!("unexpected success"), + Ok(false) | Err(_) => {} + } + } + + fn test_hmac(ty: MessageDigest, tests: &[(Vec, Vec, Vec)]) { + for &(ref key, ref data, ref res) in tests.iter() { + let pkey = PKey::hmac(key).unwrap(); + let mut signer = Signer::new(ty, &pkey).unwrap(); + signer.update(data).unwrap(); + assert_eq!(signer.finish().unwrap(), *res); + } + } + + #[test] + fn hmac_md5() { + // test vectors from RFC 2202 + let tests: [(Vec, Vec, Vec); 7] = + [(iter::repeat(0x0b_u8).take(16).collect(), + b"Hi There".to_vec(), + "9294727a3638bb1c13f48ef8158bfc9d".from_hex().unwrap()), + (b"Jefe".to_vec(), + b"what do ya want for nothing?".to_vec(), + "750c783e6ab0b503eaa86e310a5db738".from_hex().unwrap()), + (iter::repeat(0xaa_u8).take(16).collect(), + iter::repeat(0xdd_u8).take(50).collect(), + "56be34521d144c88dbb8c733f0e8b3f6".from_hex().unwrap()), + ("0102030405060708090a0b0c0d0e0f10111213141516171819".from_hex().unwrap(), + iter::repeat(0xcd_u8).take(50).collect(), + "697eaf0aca3a3aea3a75164746ffaa79".from_hex().unwrap()), + (iter::repeat(0x0c_u8).take(16).collect(), + b"Test With Truncation".to_vec(), + "56461ef2342edc00f9bab995690efd4c".from_hex().unwrap()), + (iter::repeat(0xaa_u8).take(80).collect(), + b"Test Using Larger Than Block-Size Key - Hash Key First".to_vec(), + "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd".from_hex().unwrap()), + (iter::repeat(0xaa_u8).take(80).collect(), + b"Test Using Larger Than Block-Size Key \ + and Larger Than One Block-Size Data" + .to_vec(), + "6f630fad67cda0ee1fb1f562db3aa53e".from_hex().unwrap())]; + + test_hmac(MessageDigest::md5(), &tests); + } + + #[test] + fn hmac_sha1() { + // test vectors from RFC 2202 + let tests: [(Vec, Vec, Vec); 7] = + [(iter::repeat(0x0b_u8).take(20).collect(), + b"Hi There".to_vec(), + "b617318655057264e28bc0b6fb378c8ef146be00".from_hex().unwrap()), + (b"Jefe".to_vec(), + b"what do ya want for nothing?".to_vec(), + "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79".from_hex().unwrap()), + (iter::repeat(0xaa_u8).take(20).collect(), + iter::repeat(0xdd_u8).take(50).collect(), + "125d7342b9ac11cd91a39af48aa17b4f63f175d3".from_hex().unwrap()), + ("0102030405060708090a0b0c0d0e0f10111213141516171819".from_hex().unwrap(), + iter::repeat(0xcd_u8).take(50).collect(), + "4c9007f4026250c6bc8414f9bf50c86c2d7235da".from_hex().unwrap()), + (iter::repeat(0x0c_u8).take(20).collect(), + b"Test With Truncation".to_vec(), + "4c1a03424b55e07fe7f27be1d58bb9324a9a5a04".from_hex().unwrap()), + (iter::repeat(0xaa_u8).take(80).collect(), + b"Test Using Larger Than Block-Size Key - Hash Key First".to_vec(), + "aa4ae5e15272d00e95705637ce8a3b55ed402112".from_hex().unwrap()), + (iter::repeat(0xaa_u8).take(80).collect(), + b"Test Using Larger Than Block-Size Key \ + and Larger Than One Block-Size Data" + .to_vec(), + "e8e99d0f45237d786d6bbaa7965c7808bbff1a91".from_hex().unwrap())]; + + test_hmac(MessageDigest::sha1(), &tests); + } +} diff --git a/openssl/src/ssl/bio.rs b/openssl/src/ssl/bio.rs index c5663eb1..486b4dba 100644 --- a/openssl/src/ssl/bio.rs +++ b/openssl/src/ssl/bio.rs @@ -1,14 +1,14 @@ 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, - BIO_set_retry_read, BIO_set_retry_write}; +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; use std::io::prelude::*; use std::mem; use std::ptr; use std::slice; -use std::sync::Arc; +use cvt_p; use error::ErrorStack; pub struct StreamState { @@ -18,29 +18,19 @@ pub struct StreamState { } /// Safe wrapper for BIO_METHOD -pub struct BioMethod(ffi::BIO_METHOD); +pub struct BioMethod(compat::BIO_METHOD); impl BioMethod { - pub fn new() -> BioMethod { - BioMethod(ffi::BIO_METHOD { - type_: BIO_TYPE_NONE, - name: b"rust\0".as_ptr() as *const _, - bwrite: Some(bwrite::), - bread: Some(bread::), - bputs: Some(bputs::), - bgets: None, - ctrl: Some(ctrl::), - create: Some(create), - destroy: Some(destroy::), - callback_ctrl: None, - }) + fn new() -> BioMethod { + BioMethod(compat::BIO_METHOD::new::()) } } +unsafe impl Sync for BioMethod {} unsafe impl Send for BioMethod {} -pub fn new(stream: S) -> Result<(*mut BIO, Arc), ErrorStack> { - let method = Arc::new(BioMethod::new::()); +pub fn new(stream: S) -> Result<(*mut BIO, BioMethod), ErrorStack> { + let method = BioMethod::new::(); let state = Box::new(StreamState { stream: stream, @@ -49,9 +39,9 @@ pub fn new(stream: S) -> Result<(*mut BIO, Arc), 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!(cvt_p(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 +52,13 @@ pub unsafe fn take_error(bio: *mut BIO) -> Option { state.error.take() } -#[cfg_attr(not(feature = "nightly"), allow(dead_code))] pub unsafe fn take_panic(bio: *mut BIO) -> Option> { let state = state::(bio); state.panic.take() } pub unsafe fn get_ref<'a, S: 'a>(bio: *mut BIO) -> &'a S { - let state: &'a StreamState = mem::transmute((*bio).ptr); + let state: &'a StreamState = mem::transmute(compat::BIO_get_data(bio)); &state.stream } @@ -78,23 +67,15 @@ 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 { - mem::transmute((*bio).ptr) + mem::transmute(compat::BIO_get_data(bio)) } -#[cfg(feature = "nightly")] fn catch_unwind(f: F) -> Result> where F: FnOnce() -> T { ::std::panic::catch_unwind(::std::panic::AssertUnwindSafe(f)) } -#[cfg(not(feature = "nightly"))] -fn catch_unwind(f: F) -> Result> - where F: FnOnce() -> T -{ - Ok(f()) -} - unsafe extern "C" fn bwrite(bio: *mut BIO, buf: *const c_char, len: c_int) -> c_int { BIO_clear_retry_flags(bio); @@ -176,10 +157,10 @@ unsafe extern "C" fn ctrl(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; + 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 } @@ -188,9 +169,115 @@ unsafe extern "C" fn destroy(bio: *mut BIO) -> c_int { return 0; } - assert!(!(*bio).ptr.is_null()); - Box::>::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::>::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(*mut ffi::BIO_METHOD); + + impl BIO_METHOD { + pub fn new() -> 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(ptr); + assert!(ffi::BIO_meth_set_write(ptr, super::bwrite::) != 0); + assert!(ffi::BIO_meth_set_read(ptr, super::bread::) != 0); + assert!(ffi::BIO_meth_set_puts(ptr, super::bputs::) != 0); + assert!(ffi::BIO_meth_set_ctrl(ptr, super::ctrl::) != 0); + assert!(ffi::BIO_meth_set_create(ptr, super::create) != 0); + assert!(ffi::BIO_meth_set_destroy(ptr, super::destroy::) != 0); + return ret; + } + } + + pub fn get(&self) -> *mut ffi::BIO_METHOD { + self.0 + } + } + + impl Drop for BIO_METHOD { + fn drop(&mut self) { + unsafe { + ffi::BIO_meth_free(self.0); + } + } + } +} + +#[cfg(ossl10x)] +#[allow(bad_style)] +mod compat { + use std::io::{Read, Write}; + + use ffi; + use libc::{c_int, c_void}; + + pub struct BIO_METHOD(*mut ffi::BIO_METHOD); + + impl BIO_METHOD { + pub fn new() -> BIO_METHOD { + let ptr = Box::new(ffi::BIO_METHOD { + type_: ffi::BIO_TYPE_NONE, + name: b"rust\0".as_ptr() as *const _, + bwrite: Some(super::bwrite::), + bread: Some(super::bread::), + bputs: Some(super::bputs::), + bgets: None, + ctrl: Some(super::ctrl::), + create: Some(super::create), + destroy: Some(super::destroy::), + callback_ctrl: None, + }); + + BIO_METHOD(Box::into_raw(ptr)) + } + + pub fn get(&self) -> *mut ffi::BIO_METHOD { + self.0 + } + } + + impl Drop for BIO_METHOD { + fn drop(&mut self) { + unsafe { + Box::::from_raw(self.0); + } + } + } + + 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; + } +} diff --git a/openssl/src/ssl/connector.rs b/openssl/src/ssl/connector.rs new file mode 100644 index 00000000..0d92529d --- /dev/null +++ b/openssl/src/ssl/connector.rs @@ -0,0 +1,452 @@ +use std::io::{Read, Write}; + +use dh::Dh; +use error::ErrorStack; +use ssl::{self, SslMethod, SslContextBuilder, SslContext, Ssl, SSL_VERIFY_PEER, SslStream, + HandshakeError}; +use pkey::PKeyRef; +use x509::X509Ref; + +// Serialized form of DH_get_2048_256 +#[cfg(any(ossl101, all(test, any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))))] +const DHPARAM_PEM: &'static str = r#" +-----BEGIN DH PARAMETERS----- +MIICCQKCAQEAh6jmHbS2Zjz/u9GcZRlZmYzu9ghmDdDyXSzu1ENeOwDgDfjx1hlX +1Pr330VhsqowFsPZETQJb6o79Cltgw6afCCeDGSXUXq9WoqdMGvPZ+2R+eZyW0dY +wCLgse9Cdb97bFv8EdRfkIi5QfVOseWbuLw5oL8SMH9cT9twxYGyP3a2Osrhyqa3 +kC1SUmc1SIoO8TxtmlG/pKs62DR3llJNjvahZ7WkGCXZZ+FE5RQFZCUcysuD5rSG +9rPKP3lxUGAmwLhX9omWKFbe1AEKvQvmIcOjlgpU5xDDdfJjddcBQQOktUMwwZiv +EmEW0iduEXFfaTh3+tfvCcrbCUrpHhoVlwKCAQA/syybcxNNCy53UGZg7b1ITKex +jyHvIFQH9Hk6GguhJRDbwVB3vkY//0/tSqwLtVW+OmwbDGtHsbw3c79+jG9ikBIo ++MKMuxilWuMTQQAKZQGW+THHelfy3fRj5ensFEt3feYqqrioYorDdtKC1u04ZOZ5 +gkKOvIMdFDSPby+Rk7UEWvJ2cWTh38lnwfs/LlWkvRv/6DucgNBSuYXRguoK2yo7 +cxPT/hTISEseBSWIubfSu9LfAWGZ7NBuFVfNCRWzNTu7ZODsN3/QKDcN+StSx4kU +KM3GfrYYS1I9HbJGwy9jB4SQ8A741kfRSNR5VFFeIyfP75jFgmZLTA9sxBZZ +-----END DH PARAMETERS----- +"#; + +fn ctx(method: SslMethod) -> Result { + let mut ctx = try!(SslContextBuilder::new(method)); + + let mut opts = ssl::SSL_OP_ALL; + opts |= ssl::SSL_OP_NO_TICKET; + opts |= ssl::SSL_OP_NO_COMPRESSION; + opts &= !ssl::SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG; + opts &= !ssl::SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; + opts |= ssl::SSL_OP_NO_SSLV2; + opts |= ssl::SSL_OP_NO_SSLV3; + opts |= ssl::SSL_OP_SINGLE_DH_USE; + opts |= ssl::SSL_OP_SINGLE_ECDH_USE; + opts |= ssl::SSL_OP_CIPHER_SERVER_PREFERENCE; + ctx.set_options(opts); + + let mode = ssl::SSL_MODE_AUTO_RETRY | ssl::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER | + ssl::SSL_MODE_ENABLE_PARTIAL_WRITE; + ctx.set_mode(mode); + + Ok(ctx) +} + +/// A builder for `SslConnector`s. +pub struct SslConnectorBuilder(SslContextBuilder); + +impl SslConnectorBuilder { + /// Creates a new builder for TLS connections. + /// + /// The default configuration is subject to change, and is currently derived from Python. + pub fn new(method: SslMethod) -> Result { + let mut ctx = try!(ctx(method)); + try!(ctx.set_default_verify_paths()); + // From https://github.com/python/cpython/blob/c30098c8c6014f3340a369a31df9c74bdbacc269/Lib/ssl.py#L191 + try!(ctx.set_cipher_list("ECDH+AESGCM:ECDH+CHACHA20:DH+AESGCM:DH+CHACHA20:ECDH+AES256:\ + DH+AES256:ECDH+AES128:DH+AES:ECDH+HIGH:DH+HIGH:RSA+AESGCM:\ + RSA+AES:RSA+HIGH:!aNULL:!eNULL:!MD5:!3DES")); + + Ok(SslConnectorBuilder(ctx)) + } + + /// Returns a shared reference to the inner `SslContextBuilder`. + pub fn builder(&self) -> &SslContextBuilder { + &self.0 + } + + /// Returns a mutable reference to the inner `SslContextBuilder`. + pub fn builder_mut(&mut self) -> &mut SslContextBuilder { + &mut self.0 + } + + /// Consumes the builder, returning a `SslConnector`. + pub fn build(self) -> SslConnector { + SslConnector(self.0.build()) + } +} + +/// A type which wraps client-side streams in a TLS session. +/// +/// OpenSSL's default configuration is highly insecure. This connector manages the OpenSSL +/// structures, configuring cipher suites, session options, hostname verification, and more. +/// +/// OpenSSL's built in hostname verification is used when linking against OpenSSL 1.0.2 or 1.1.0, +/// and a custom implementation is used when linking against OpenSSL 1.0.1. +pub struct SslConnector(SslContext); + +impl SslConnector { + /// Initiates a client-side TLS session on a stream. + /// + /// The domain is used for SNI and hostname verification. + pub fn connect(&self, domain: &str, stream: S) -> Result, HandshakeError> + where S: Read + Write + { + let mut ssl = try!(Ssl::new(&self.0)); + try!(ssl.set_hostname(domain)); + try!(setup_verify(&mut ssl, domain)); + + ssl.connect(stream) + } +} + +/// A builder for `SslAcceptor`s. +pub struct SslAcceptorBuilder(SslContextBuilder); + +impl SslAcceptorBuilder { + /// Creates a new builder configured to connect to non-legacy clients. This should generally be + /// considered a reasonable default choice. + /// + /// This corresponds to the intermediate configuration of Mozilla's server side TLS + /// recommendations. See its [documentation][docs] for more details on specifics. + /// + /// [docs]: https://wiki.mozilla.org/Security/Server_Side_TLS + pub fn mozilla_intermediate(method: SslMethod, + private_key: &PKeyRef, + certificate: &X509Ref, + chain: I) + -> Result + where I: IntoIterator, + I::Item: AsRef + { + let mut ctx = try!(ctx(method)); + let dh = try!(get_dh()); + try!(ctx.set_tmp_dh(&dh)); + try!(setup_curves(&mut ctx)); + try!(ctx.set_cipher_list("ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:\ + ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:\ + ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:\ + DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:\ + ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:\ + ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:\ + ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:\ + ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:\ + DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:\ + DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:\ + ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:\ + EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:\ + AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:\ + DES-CBC3-SHA:!DSS")); + SslAcceptorBuilder::finish_setup(ctx, private_key, certificate, chain) + } + + /// Creates a new builder configured to connect to modern clients. + /// + /// This corresponds to the modern configuration of Mozilla's server side TLS recommendations. + /// See its [documentation][docs] for more details on specifics. + /// + /// [docs]: https://wiki.mozilla.org/Security/Server_Side_TLS + pub fn mozilla_modern(method: SslMethod, + private_key: &PKeyRef, + certificate: &X509Ref, + chain: I) + -> Result + where I: IntoIterator, + I::Item: AsRef + { + let mut ctx = try!(ctx(method)); + try!(setup_curves(&mut ctx)); + try!(ctx.set_cipher_list("ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:\ + ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:\ + ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:\ + ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:\ + ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256")); + SslAcceptorBuilder::finish_setup(ctx, private_key, certificate, chain) + } + + fn finish_setup(mut ctx: SslContextBuilder, + private_key: &PKeyRef, + certificate: &X509Ref, + chain: I) + -> Result + where I: IntoIterator, + I::Item: AsRef + { + try!(ctx.set_private_key(private_key)); + try!(ctx.set_certificate(certificate)); + try!(ctx.check_private_key()); + for cert in chain { + try!(ctx.add_extra_chain_cert(cert.as_ref().to_owned())); + } + Ok(SslAcceptorBuilder(ctx)) + } + + /// Returns a shared reference to the inner `SslContextBuilder`. + pub fn builder(&self) -> &SslContextBuilder { + &self.0 + } + + /// Returns a mutable reference to the inner `SslContextBuilder`. + pub fn builder_mut(&mut self) -> &mut SslContextBuilder { + &mut self.0 + } + + /// Consumes the builder, returning a `SslAcceptor`. + pub fn build(self) -> SslAcceptor { + SslAcceptor(self.0.build()) + } +} + +#[cfg(ossl101)] +fn get_dh() -> Result { + Dh::from_pem(DHPARAM_PEM.as_bytes()) +} + +#[cfg(not(ossl101))] +fn get_dh() -> Result { + use ffi; + + use cvt_p; + use types::OpenSslType; + + // manually call into ffi to avoid forcing the features + unsafe { cvt_p(ffi::DH_get_2048_256()).map(|p| Dh::from_ptr(p)) } +} + +#[cfg(ossl101)] +fn setup_curves(ctx: &mut SslContextBuilder) -> Result<(), ErrorStack> { + use ec_key::EcKey; + use nid; + + let curve = try!(EcKey::new_by_curve_name(nid::X9_62_PRIME256V1)); + ctx.set_tmp_ecdh(&curve) +} + +#[cfg(ossl102)] +fn setup_curves(ctx: &mut SslContextBuilder) -> Result<(), ErrorStack> { + ctx._set_ecdh_auto(true) +} + +#[cfg(ossl110)] +fn setup_curves(_: &mut SslContextBuilder) -> Result<(), ErrorStack> { + Ok(()) +} + +/// A type which wraps server-side streams in a TLS session. +/// +/// OpenSSL's default configuration is highly insecure. This connector manages the OpenSSL +/// structures, configuring cipher suites, session options, and more. +pub struct SslAcceptor(SslContext); + +impl SslAcceptor { + /// Initiates a server-side TLS session on a stream. + pub fn accept(&self, stream: S) -> Result, HandshakeError> + where S: Read + Write + { + let ssl = try!(Ssl::new(&self.0)); + ssl.accept(stream) + } +} + +#[cfg(any(ossl102, ossl110))] +fn setup_verify(ssl: &mut Ssl, domain: &str) -> Result<(), ErrorStack> { + ssl.set_verify(SSL_VERIFY_PEER); + let param = ssl._param_mut(); + param.set_hostflags(::verify::X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); + param.set_host(domain) +} + +#[cfg(ossl101)] +fn setup_verify(ssl: &mut Ssl, domain: &str) -> Result<(), ErrorStack> { + let domain = domain.to_owned(); + ssl.set_verify_callback(SSL_VERIFY_PEER, + move |p, x| verify::verify_callback(&domain, p, x)); + Ok(()) +} + +#[cfg(ossl101)] +mod verify { + use std::net::IpAddr; + use std::str; + + use nid; + use x509::{X509StoreContextRef, X509Ref, X509NameRef, GeneralName}; + use stack::Stack; + use types::OpenSslTypeRef; + + pub fn verify_callback(domain: &str, + preverify_ok: bool, + x509_ctx: &X509StoreContextRef) + -> bool { + if !preverify_ok || x509_ctx.error_depth() != 0 { + return preverify_ok; + } + + match x509_ctx.current_cert() { + Some(x509) => verify_hostname(domain, &x509), + None => true, + } + } + + fn verify_hostname(domain: &str, cert: &X509Ref) -> bool { + match cert.subject_alt_names() { + Some(names) => verify_subject_alt_names(domain, names), + None => verify_subject_name(domain, &cert.subject_name()), + } + } + + fn verify_subject_alt_names(domain: &str, names: Stack) -> bool { + let ip = domain.parse(); + + for name in &names { + match ip { + Ok(ip) => { + if let Some(actual) = name.ipaddress() { + if matches_ip(&ip, actual) { + return true; + } + } + } + Err(_) => { + if let Some(pattern) = name.dnsname() { + if matches_dns(pattern, domain, false) { + return true; + } + } + } + } + } + + false + } + + fn verify_subject_name(domain: &str, subject_name: &X509NameRef) -> bool { + if let Some(pattern) = subject_name.entries_by_nid(nid::COMMONNAME).next() { + let pattern = match str::from_utf8(pattern.data().as_slice()) { + Ok(pattern) => pattern, + Err(_) => return false, + }; + + // Unlike with SANs, IP addresses in the subject name don't have a + // different encoding. We need to pass this down to matches_dns to + // disallow wildcard matches with bogus patterns like *.0.0.1 + let is_ip = domain.parse::().is_ok(); + + if matches_dns(&pattern, domain, is_ip) { + return true; + } + } + + false + } + + fn matches_dns(mut pattern: &str, mut hostname: &str, is_ip: bool) -> bool { + // first strip trailing . off of pattern and hostname to normalize + if pattern.ends_with('.') { + pattern = &pattern[..pattern.len() - 1]; + } + if hostname.ends_with('.') { + hostname = &hostname[..hostname.len() - 1]; + } + + matches_wildcard(pattern, hostname, is_ip).unwrap_or_else(|| pattern == hostname) + } + + fn matches_wildcard(pattern: &str, hostname: &str, is_ip: bool) -> Option { + // IP addresses and internationalized domains can't involved in wildcards + if is_ip || pattern.starts_with("xn--") { + return None; + } + + let wildcard_location = match pattern.find('*') { + Some(l) => l, + None => return None, + }; + + let mut dot_idxs = pattern.match_indices('.').map(|(l, _)| l); + let wildcard_end = match dot_idxs.next() { + Some(l) => l, + None => return None, + }; + + // Never match wildcards if the pattern has less than 2 '.'s (no *.com) + // + // This is a bit dubious, as it doesn't disallow other TLDs like *.co.uk. + // Chrome has a black- and white-list for this, but Firefox (via NSS) does + // the same thing we do here. + // + // The Public Suffix (https://www.publicsuffix.org/) list could + // potentically be used here, but it's both huge and updated frequently + // enough that management would be a PITA. + if dot_idxs.next().is_none() { + return None; + } + + // Wildcards can only be in the first component + if wildcard_location > wildcard_end { + return None; + } + + let hostname_label_end = match hostname.find('.') { + Some(l) => l, + None => return None, + }; + + // check that the non-wildcard parts are identical + if pattern[wildcard_end..] != hostname[hostname_label_end..] { + return Some(false); + } + + let wildcard_prefix = &pattern[..wildcard_location]; + let wildcard_suffix = &pattern[wildcard_location + 1..wildcard_end]; + + let hostname_label = &hostname[..hostname_label_end]; + + // check the prefix of the first label + if !hostname_label.starts_with(wildcard_prefix) { + return Some(false); + } + + // and the suffix + if !hostname_label[wildcard_prefix.len()..].ends_with(wildcard_suffix) { + return Some(false); + } + + Some(true) + } + + fn matches_ip(expected: &IpAddr, actual: &[u8]) -> bool { + match (expected, actual.len()) { + (&IpAddr::V4(ref addr), 4) => actual == addr.octets(), + (&IpAddr::V6(ref addr), 16) => { + let segments = [((actual[0] as u16) << 8) | actual[1] as u16, + ((actual[2] as u16) << 8) | actual[3] as u16, + ((actual[4] as u16) << 8) | actual[5] as u16, + ((actual[6] as u16) << 8) | actual[7] as u16, + ((actual[8] as u16) << 8) | actual[9] as u16, + ((actual[10] as u16) << 8) | actual[11] as u16, + ((actual[12] as u16) << 8) | actual[13] as u16, + ((actual[14] as u16) << 8) | actual[15] as u16]; + segments == addr.segments() + } + _ => false, + } + } +} + +#[cfg(test)] +mod test { + #[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] + #[test] + fn check_dhparam() { + use dh::Dh; + + let expected = String::from_utf8(Dh::get_2048_256().unwrap().to_pem().unwrap()).unwrap(); + assert_eq!(expected.trim(), super::DHPARAM_PEM.trim()); + } +} diff --git a/openssl/src/ssl/error.rs b/openssl/src/ssl/error.rs index 95213361..518ae90f 100644 --- a/openssl/src/ssl/error.rs +++ b/openssl/src/ssl/error.rs @@ -1,8 +1,11 @@ +use std::any::Any; use std::error; use std::error::Error as StdError; use std::fmt; use std::io; + use error::ErrorStack; +use ssl::MidHandshakeSslStream; /// An SSL error. #[derive(Debug)] @@ -62,3 +65,55 @@ impl From for Error { Error::Ssl(e) } } + +/// An error or intermediate state after a TLS handshake attempt. +#[derive(Debug)] +pub enum HandshakeError { + /// Setup failed. + SetupFailure(ErrorStack), + /// The handshake failed. + Failure(MidHandshakeSslStream), + /// The handshake was interrupted midway through. + Interrupted(MidHandshakeSslStream), +} + +impl StdError for HandshakeError { + fn description(&self) -> &str { + match *self { + HandshakeError::SetupFailure(_) => "stream setup failed", + HandshakeError::Failure(_) => "the handshake failed", + HandshakeError::Interrupted(_) => "the handshake was interrupted", + } + } + + fn cause(&self) -> Option<&StdError> { + match *self { + HandshakeError::SetupFailure(ref e) => Some(e), + HandshakeError::Failure(ref s) | + HandshakeError::Interrupted(ref s) => Some(s.error()), + } + } +} + +impl fmt::Display for HandshakeError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + try!(f.write_str(StdError::description(self))); + match *self { + HandshakeError::SetupFailure(ref e) => try!(write!(f, ": {}", e)), + HandshakeError::Failure(ref s) | + HandshakeError::Interrupted(ref s) => { + try!(write!(f, ": {}", s.error())); + if let Some(err) = s.ssl().verify_result() { + try!(write!(f, ": {}", err)); + } + } + } + Ok(()) + } +} + +impl From for HandshakeError { + fn from(e: ErrorStack) -> HandshakeError { + HandshakeError::SetupFailure(e) + } +} diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 6e365af6..9a477993 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -1,49 +1,123 @@ -use libc::{c_int, c_void, c_long}; +//! SSL/TLS support. +//! +//! `SslConnector` and `SslAcceptor` should be used in most cases - they handle +//! configuration of the OpenSSL primitives for you. +//! +//! # Examples +//! +//! To connect as a client to a remote server: +//! +//! ``` +//! use openssl::ssl::{SslMethod, SslConnectorBuilder}; +//! use std::io::{Read, Write}; +//! use std::net::TcpStream; +//! +//! let connector = SslConnectorBuilder::new(SslMethod::tls()).unwrap().build(); +//! +//! let stream = TcpStream::connect("google.com:443").unwrap(); +//! let mut stream = connector.connect("google.com", stream).unwrap(); +//! +//! stream.write_all(b"GET / HTTP/1.0\r\n\r\n").unwrap(); +//! let mut res = vec![]; +//! stream.read_to_end(&mut res).unwrap(); +//! println!("{}", String::from_utf8_lossy(&res)); +//! ``` +//! +//! To accept connections as a server from remote clients: +//! +//! ```no_run +//! use openssl::pkcs12::Pkcs12; +//! use openssl::ssl::{SslMethod, SslAcceptorBuilder, SslStream}; +//! use std::fs::File; +//! use std::io::{Read, Write}; +//! use std::net::{TcpListener, TcpStream}; +//! use std::sync::Arc; +//! use std::thread; +//! +//! // In this example we retrieve our keypair and certificate chain from a PKCS #12 archive, +//! // but but they can also be retrieved from, for example, individual PEM- or DER-formatted +//! // files. See the documentation for the `PKey` and `X509` types for more details. +//! let mut file = File::open("identity.pfx").unwrap(); +//! let mut pkcs12 = vec![]; +//! file.read_to_end(&mut pkcs12).unwrap(); +//! let pkcs12 = Pkcs12::from_der(&pkcs12).unwrap(); +//! let identity = pkcs12.parse("password123").unwrap(); +//! +//! let acceptor = SslAcceptorBuilder::mozilla_intermediate(SslMethod::tls(), +//! &identity.pkey, +//! &identity.cert, +//! &identity.chain) +//! .unwrap() +//! .build(); +//! let acceptor = Arc::new(acceptor); +//! +//! let listener = TcpListener::bind("0.0.0.0:8443").unwrap(); +//! +//! fn handle_client(stream: SslStream) { +//! // ... +//! } +//! +//! for stream in listener.incoming() { +//! match stream { +//! Ok(stream) => { +//! let acceptor = acceptor.clone(); +//! thread::spawn(move || { +//! let stream = acceptor.accept(stream).unwrap(); +//! handle_client(stream); +//! }); +//! } +//! Err(e) => { /* connection failed */ } +//! } +//! } +//! ``` +use ffi; +use libc::{c_int, c_void, c_long, c_ulong}; +use libc::{c_uchar, c_uint}; use std::any::Any; use std::any::TypeId; use std::cmp; use std::collections::HashMap; -use std::error as stderror; use std::ffi::{CStr, CString}; use std::fmt; use std::io; use std::io::prelude::*; +use std::marker::PhantomData; use std::mem; use std::ops::{Deref, DerefMut}; use std::path::Path; use std::ptr; -use std::str; -use std::sync::{Mutex, Arc}; -#[cfg(any(feature = "npn", feature = "alpn"))] -use libc::{c_uchar, c_uint}; -#[cfg(any(feature = "npn", feature = "alpn"))] use std::slice; -use std::marker::PhantomData; -use ffi; +use std::str; +use std::sync::Mutex; -use init; -use dh::DH; -use x509::{X509StoreContext, X509FileType, X509, X509Ref}; -use crypto::pkey::PKey; +use {init, cvt, cvt_p}; +use dh::DhRef; +use ec_key::EcKeyRef; +use x509::{X509StoreContextRef, X509FileType, X509, X509Ref, X509VerifyError}; +#[cfg(any(ossl102, ossl110))] +use verify::X509VerifyParamRef; +use pkey::PKeyRef; use error::ErrorStack; +use types::{OpenSslType, OpenSslTypeRef}; +use util::Opaque; -pub mod error; +mod error; +mod connector; mod bio; #[cfg(test)] mod tests; use self::bio::BioMethod; -#[doc(inline)] -pub use ssl::error::Error; +pub use ssl::connector::{SslConnectorBuilder, SslConnector, SslAcceptorBuilder, SslAcceptor}; +pub use ssl::error::{Error, HandshakeError}; bitflags! { - pub flags SslContextOptions: c_long { + pub flags SslOption: 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, @@ -66,80 +140,59 @@ bitflags! { const SSL_OP_NO_SSLV2 = ffi::SSL_OP_NO_SSLv2, const SSL_OP_NO_SSLV3 = ffi::SSL_OP_NO_SSLv3, const SSL_OP_NO_TLSV1 = ffi::SSL_OP_NO_TLSv1, + const SSL_OP_NO_TLSV1_2 = ffi::SSL_OP_NO_TLSv1_2, + const SSL_OP_NO_TLSV1_1 = ffi::SSL_OP_NO_TLSv1_1, + /// Requires the `v102` or `v110` features and OpenSSL 1.0.2 or OpenSSL 1.1.0. + #[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] + const SSL_OP_NO_DTLSV1 = ffi::SSL_OP_NO_DTLSv1, + /// Requires the `v102` or `v110` features and OpenSSL 1.0.2 or OpenSSL 1.1.0. + #[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] + const SSL_OP_NO_DTLSV1_2 = ffi::SSL_OP_NO_DTLSv1_2, + /// Requires the `v102` or `v110` features and OpenSSL 1.0.2 or OpenSSL 1.1.0. + #[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] + const SSL_OP_NO_SSL_MASK = ffi::SSL_OP_NO_SSL_MASK, } } -/// Determines the SSL method supported -#[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, +bitflags! { + pub flags SslMode: c_long { + const SSL_MODE_ENABLE_PARTIAL_WRITE = ffi::SSL_MODE_ENABLE_PARTIAL_WRITE, + const SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER = ffi::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER, + const SSL_MODE_AUTO_RETRY = ffi::SSL_MODE_AUTO_RETRY, + const SSL_MODE_NO_AUTO_CHAIN = ffi::SSL_MODE_NO_AUTO_CHAIN, + const SSL_MODE_RELEASE_BUFFERS = ffi::SSL_MODE_RELEASE_BUFFERS, + const SSL_MODE_SEND_CLIENTHELLO_TIME = ffi::SSL_MODE_SEND_CLIENTHELLO_TIME, + const SSL_MODE_SEND_SERVERHELLO_TIME = ffi::SSL_MODE_SEND_SERVERHELLO_TIME, + const SSL_MODE_SEND_FALLBACK_SCSV = ffi::SSL_MODE_SEND_FALLBACK_SCSV, + } } +#[derive(Copy, Clone)] +pub struct SslMethod(*const ffi::SSL_METHOD); + 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(), - } - } + /// Support all versions of the TLS protocol. + /// + /// This corresponds to `TLS_method` on OpenSSL 1.1.0 and `SSLv23_method` + /// on OpenSSL 1.0.x. + pub fn tls() -> SslMethod { + SslMethod(compat::tls_method()) } - fn from_raw(method: *const ffi::SSL_METHOD) -> Option { - 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, - } - } + /// Support all versions of the DTLS protocol. + /// + /// This corresponds to `DTLS_method` on OpenSSL 1.1.0 and `DTLSv1_method` + /// on OpenSSL 1.0.x. + pub fn dtls() -> SslMethod { + SslMethod(compat::dtls_method()) + } + + pub unsafe fn from_ptr(ptr: *const ffi::SSL_METHOD) -> SslMethod { + SslMethod(ptr) + } + + pub fn as_ptr(&self) -> *const ffi::SSL_METHOD { + self.0 } } @@ -172,85 +225,72 @@ fn get_ssl_verify_data_idx() -> c_int { *SSL_INDEXES.lock().unwrap().entry(TypeId::of::()).or_insert_with(|| get_new_ssl_idx::()) } -#[cfg(feature = "npn")] lazy_static! { static ref NPN_PROTOS_IDX: c_int = get_new_idx::>(); } -#[cfg(feature = "alpn")] + +#[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] lazy_static! { static ref ALPN_PROTOS_IDX: c_int = get_new_idx::>(); } +unsafe extern "C" fn free_data_box(_parent: *mut c_void, + ptr: *mut c_void, + _ad: *mut ffi::CRYPTO_EX_DATA, + _idx: c_int, + _argl: c_long, + _argp: *mut c_void) { + if !ptr.is_null() { + Box::::from_raw(ptr as *mut T); + } +} + /// 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() -> c_int { - extern "C" fn free_data_box(_parent: *mut c_void, - ptr: *mut c_void, - _ad: *mut ffi::CRYPTO_EX_DATA, - _idx: c_int, - _argl: c_long, - _argp: *mut c_void) { - if !ptr.is_null() { - let _: Box = unsafe { mem::transmute(ptr) }; - } - } - unsafe { - let f: ffi::CRYPTO_EX_free = free_data_box::; - 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::); assert!(idx >= 0); idx } } fn get_new_ssl_idx() -> c_int { - extern "C" fn free_data_box(_parent: *mut c_void, - ptr: *mut c_void, - _ad: *mut ffi::CRYPTO_EX_DATA, - _idx: c_int, - _argl: c_long, - _argp: *mut c_void) { - if !ptr.is_null() { - let _: Box = unsafe { mem::transmute(ptr) }; - } - } - unsafe { - let f: ffi::CRYPTO_EX_free = free_data_box::; - 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::); assert!(idx >= 0); idx } } extern "C" fn raw_verify(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int - where F: Fn(bool, &X509StoreContext) -> bool + Any + 'static + Sync + Send + where F: Fn(bool, &X509StoreContextRef) -> 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::()); - let verify: &F = mem::transmute(verify); + let verify: &F = &*(verify as *mut F); - let ctx = X509StoreContext::new(x509_ctx); + let ctx = X509StoreContextRef::from_ptr(x509_ctx); - verify(preverify_ok != 0, &ctx) as c_int + verify(preverify_ok != 0, ctx) as c_int } } extern "C" fn ssl_raw_verify(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int - where F: Fn(bool, &X509StoreContext) -> bool + Any + 'static + Sync + Send + where F: Fn(bool, &X509StoreContextRef) -> 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::()); - let verify: &F = mem::transmute(verify); + let verify = ffi::SSL_get_ex_data(ssl as *const _, get_ssl_verify_data_idx::()); + let verify: &F = &*(verify as *mut F); - let ctx = X509StoreContext::new(x509_ctx); + let ctx = X509StoreContextRef::from_ptr(x509_ctx); - verify(preverify_ok != 0, &ctx) as c_int + verify(preverify_ok != 0, ctx) as c_int } } @@ -260,10 +300,10 @@ extern "C" fn raw_sni(ssl: *mut ffi::SSL, al: *mut c_int, _arg: *mut c_void) unsafe { let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl); let callback = ffi::SSL_CTX_get_ex_data(ssl_ctx, get_verify_data_idx::()); - let callback: &F = mem::transmute(callback); - let mut ssl = SslRef::from_ptr(ssl); + let callback: &F = &*(callback as *mut F); + let ssl = SslRef::from_ptr_mut(ssl); - match callback(&mut ssl) { + match callback(ssl) { Ok(()) => ffi::SSL_TLSEXT_ERR_OK, Err(SniError::Fatal(e)) => { *al = e; @@ -278,7 +318,6 @@ extern "C" fn raw_sni(ssl: *mut ffi::SSL, al: *mut c_int, _arg: *mut c_void) } } -#[cfg(any(feature = "npn", feature = "alpn"))] unsafe fn select_proto_using(ssl: *mut ffi::SSL, out: *mut *mut c_uchar, outlen: *mut c_uchar, @@ -291,7 +330,7 @@ unsafe fn select_proto_using(ssl: *mut ffi::SSL, // extra data. let ssl_ctx = ffi::SSL_get_SSL_CTX(ssl); let protocols = ffi::SSL_CTX_get_ex_data(ssl_ctx, ex_data); - let protocols: &Vec = mem::transmute(protocols); + let protocols: &Vec = &*(protocols as *mut Vec); // Prepare the client list parameters to be passed to the OpenSSL function... let client = protocols.as_ptr(); let client_len = protocols.len() as c_uint; @@ -311,7 +350,6 @@ 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, out: *mut *mut c_uchar, outlen: *mut c_uchar, @@ -322,15 +360,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")] +#[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] extern "C" fn raw_alpn_select_cb(ssl: *mut ffi::SSL, - out: *mut *mut c_uchar, + 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,7 +378,6 @@ 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, out: *mut *const c_uchar, outlen: *mut c_uint, @@ -356,7 +393,7 @@ extern "C" fn raw_next_protos_advertise_cb(ssl: *mut ffi::SSL, } else { // If the pointer is valid, put the pointer to the actual byte array into the // output parameter `out`, as well as its length into `outlen`. - let protocols: &Vec = mem::transmute(protocols); + let protocols: &Vec = &*(protocols as *mut Vec); *out = protocols.as_ptr(); *outlen = protocols.len() as c_uint; } @@ -367,7 +404,6 @@ 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"))] fn ssl_encode_byte_strings(strings: &[&[u8]]) -> Vec { let mut enc = Vec::new(); for string in strings { @@ -389,22 +425,30 @@ pub enum SniError { NoAck, } -// FIXME: macro may be instead of inlining? -#[inline] -fn wrap_ssl_result(res: c_int) -> Result<(), ErrorStack> { - if res == 0 { - Err(ErrorStack::get()) - } else { - Ok(()) +/// A builder for `SslContext`s. +pub struct SslContextBuilder(*mut ffi::SSL_CTX); + +unsafe impl Sync for SslContextBuilder {} +unsafe impl Send for SslContextBuilder {} + +impl Drop for SslContextBuilder { + fn drop(&mut self) { + unsafe { ffi::SSL_CTX_free(self.as_ptr()) } } } -/// A borrowed SSL context object. -pub struct SslContextRef<'a>(*mut ffi::SSL_CTX, PhantomData<&'a ()>); +impl SslContextBuilder { + pub fn new(method: SslMethod) -> Result { + unsafe { + init(); + let ctx = try!(cvt_p(ffi::SSL_CTX_new(method.as_ptr()))); -impl<'a> SslContextRef<'a> { - pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextRef<'a> { - SslContextRef(ctx, PhantomData) + Ok(SslContextBuilder::from_ptr(ctx)) + } + } + + pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContextBuilder { + SslContextBuilder(ctx) } pub fn as_ptr(&self) -> *mut ffi::SSL_CTX { @@ -421,11 +465,13 @@ impl<'a> SslContextRef<'a> { /// Configures the certificate verification method for new connections and /// registers a verification callback. pub fn set_verify_callback(&mut self, mode: SslVerifyMode, verify: F) - where F: Fn(bool, &X509StoreContext) -> bool + Any + 'static + Sync + Send + where F: Fn(bool, &X509StoreContextRef) -> bool + Any + 'static + Sync + Send { unsafe { let verify = Box::new(verify); - ffi::SSL_CTX_set_ex_data(self.as_ptr(), get_verify_data_idx::(), mem::transmute(verify)); + ffi::SSL_CTX_set_ex_data(self.as_ptr(), + get_verify_data_idx::(), + mem::transmute(verify)); ffi::SSL_CTX_set_verify(self.as_ptr(), mode.bits as c_int, Some(raw_verify::)); } } @@ -455,18 +501,25 @@ impl<'a> SslContextRef<'a> { } } - pub fn set_read_ahead(&mut self, m: u32) { + pub fn set_read_ahead(&mut self, read_ahead: bool) { unsafe { - ffi::SSL_CTX_set_read_ahead(self.as_ptr(), m as c_long); + ffi::SSL_CTX_set_read_ahead(self.as_ptr(), read_ahead as c_long); } } - fn set_mode(&mut self, mode: c_long) -> Result<(), ErrorStack> { - wrap_ssl_result(unsafe { ffi::SSL_CTX_set_mode(self.as_ptr(), mode) as c_int }) + pub fn set_mode(&mut self, mode: SslMode) -> SslMode { + unsafe { + let mode = ffi::SSL_CTX_set_mode(self.as_ptr(), mode.bits()); + SslMode::from_bits(mode).unwrap() + } } - pub fn set_tmp_dh(&mut self, dh: &DH) -> Result<(), ErrorStack> { - wrap_ssl_result(unsafe { ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as i32 }) + pub fn set_tmp_dh(&mut self, dh: &DhRef) -> Result<(), ErrorStack> { + unsafe { cvt(ffi::SSL_CTX_set_tmp_dh(self.as_ptr(), dh.as_ptr()) as c_int).map(|_| ()) } + } + + pub fn set_tmp_ecdh(&mut self, key: &EcKeyRef) -> Result<(), ErrorStack> { + unsafe { cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) as c_int).map(|_| ()) } } /// Use the default locations of trusted certificates for verification. @@ -475,16 +528,18 @@ impl<'a> SslContextRef<'a> { /// environment variables if present, or defaults specified at OpenSSL /// build time otherwise. pub fn set_default_verify_paths(&mut self) -> Result<(), ErrorStack> { - wrap_ssl_result(unsafe { ffi::SSL_CTX_set_default_verify_paths(self.as_ptr()) }) + unsafe { cvt(ffi::SSL_CTX_set_default_verify_paths(self.as_ptr())).map(|_| ()) } } - #[allow(non_snake_case)] /// Specifies the file that contains trusted CA certificates. - pub fn set_CA_file>(&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_load_verify_locations(self.as_ptr(), file.as_ptr() as *const _, ptr::null()) - }) + pub fn set_ca_file>(&mut self, file: P) -> Result<(), ErrorStack> { + let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap(); + unsafe { + cvt(ffi::SSL_CTX_load_verify_locations(self.as_ptr(), + file.as_ptr() as *const _, + ptr::null())) + .map(|_| ()) + } } /// Set the context identifier for sessions @@ -496,9 +551,13 @@ impl<'a> SslContextRef<'a> { /// This value should be set when using client certificates, or each request will fail /// handshake and need to be restarted. pub fn set_session_id_context(&mut self, sid_ctx: &[u8]) -> Result<(), ErrorStack> { - wrap_ssl_result(unsafe { - ffi::SSL_CTX_set_session_id_context(self.as_ptr(), sid_ctx.as_ptr(), sid_ctx.len() as u32) - }) + unsafe { + assert!(sid_ctx.len() <= c_uint::max_value() as usize); + cvt(ffi::SSL_CTX_set_session_id_context(self.as_ptr(), + sid_ctx.as_ptr(), + sid_ctx.len() as c_uint)) + .map(|_| ()) + } } /// Specifies the file that contains certificate @@ -506,43 +565,39 @@ impl<'a> SslContextRef<'a> { file: P, file_type: X509FileType) -> 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_file(self.as_ptr(), - file.as_ptr() as *const _, - file_type as c_int) - }) + let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap(); + unsafe { + cvt(ffi::SSL_CTX_use_certificate_file(self.as_ptr(), + file.as_ptr() as *const _, + file_type.as_raw())) + .map(|_| ()) + } } /// Specifies the file that contains certificate chain pub fn set_certificate_chain_file>(&mut self, - file: P, - file_type: X509FileType) + 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) - }) + let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap(); + unsafe { + cvt(ffi::SSL_CTX_use_certificate_chain_file(self.as_ptr(), file.as_ptr() as *const _)) + .map(|_| ()) + } } /// Specifies the certificate pub fn set_certificate(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> { - wrap_ssl_result(unsafe { ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr()) }) + unsafe { cvt(ffi::SSL_CTX_use_certificate(self.as_ptr(), cert.as_ptr())).map(|_| ()) } } /// Adds a certificate to the certificate chain presented together with the /// certificate specified using set_certificate() - pub fn add_extra_chain_cert(&mut self, cert: &X509Ref) -> Result<(), ErrorStack> { - // FIXME this should really just take an X509 by value - let der = try!(cert.to_der()); - let cert = try!(X509::from_der(&der)); + pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> { unsafe { - try_ssl!(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.as_ptr())); + try!(cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.as_ptr()) as c_int)); + mem::forget(cert); + Ok(()) } - mem::forget(cert); - Ok(()) } /// Specifies the file that contains private key @@ -550,61 +605,61 @@ impl<'a> SslContextRef<'a> { file: P, file_type: X509FileType) -> 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_PrivateKey_file(self.as_ptr(), - file.as_ptr() as *const _, - file_type as c_int) - }) + let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap(); + unsafe { + cvt(ffi::SSL_CTX_use_PrivateKey_file(self.as_ptr(), + file.as_ptr() as *const _, + file_type.as_raw())) + .map(|_| ()) + } } /// Specifies the private key - pub fn set_private_key(&mut self, key: &PKey) -> Result<(), ErrorStack> { - wrap_ssl_result(unsafe { ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr()) }) - } - - /// Check consistency of private key and certificate - pub fn check_private_key(&mut self) -> Result<(), ErrorStack> { - wrap_ssl_result(unsafe { ffi::SSL_CTX_check_private_key(self.as_ptr()) }) + pub fn set_private_key(&mut self, key: &PKeyRef) -> Result<(), ErrorStack> { + unsafe { cvt(ffi::SSL_CTX_use_PrivateKey(self.as_ptr(), key.as_ptr())).map(|_| ()) } } pub fn set_cipher_list(&mut self, cipher_list: &str) -> Result<(), ErrorStack> { - wrap_ssl_result(unsafe { - let cipher_list = CString::new(cipher_list).unwrap(); - ffi::SSL_CTX_set_cipher_list(self.as_ptr(), cipher_list.as_ptr() as *const _) - }) + let cipher_list = CString::new(cipher_list).unwrap(); + unsafe { + cvt(ffi::SSL_CTX_set_cipher_list(self.as_ptr(), cipher_list.as_ptr() as *const _)) + .map(|_| ()) + } } - /// 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")] + /// Requires the `v102` feature and OpenSSL 1.0.2. + #[cfg(all(feature = "v102", ossl102))] 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) } - pub fn set_options(&mut self, option: SslContextOptions) -> SslContextOptions { - let ret = unsafe { ffi::SSL_CTX_set_options(self.as_ptr(), option.bits()) }; - SslContextOptions::from_bits(ret).unwrap() + #[cfg(ossl102)] + fn _set_ecdh_auto(&mut self, onoff: bool) -> Result<(), ErrorStack> { + unsafe { cvt(ffi::SSL_CTX_set_ecdh_auto(self.as_ptr(), onoff as c_int)).map(|_| ()) } } - pub fn options(&self) -> SslContextOptions { - let ret = unsafe { ffi::SSL_CTX_get_options(self.as_ptr()) }; - SslContextOptions::from_bits(ret).unwrap() + pub fn set_options(&mut self, option: SslOption) -> SslOption { + let ret = unsafe { compat::SSL_CTX_set_options(self.as_ptr(), option.bits()) }; + SslOption::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()) }; - SslContextOptions::from_bits(ret).unwrap() + pub fn options(&self) -> SslOption { + let ret = unsafe { compat::SSL_CTX_get_options(self.as_ptr()) }; + SslOption::from_bits(ret).unwrap() + } + + pub fn clear_options(&mut self, option: SslOption) -> SslOption { + let ret = unsafe { compat::SSL_CTX_clear_options(self.as_ptr(), option.bits()) }; + SslOption::from_bits(ret).unwrap() } /// Set the protocols to be used during Next Protocol Negotiation (the protocols /// supported by the application). - /// - /// This method needs the `npn` feature. - #[cfg(feature = "npn")] - pub fn set_npn_protocols(&mut self, protocols: &[&[u8]]) { + pub fn set_npn_protocols(&mut self, protocols: &[&[u8]]) -> Result<(), ErrorStack> { // Firstly, convert the list of protocols to a byte-array that can be passed to OpenSSL // APIs -- a list of length-prefixed strings. let protocols: Box> = Box::new(ssl_encode_byte_strings(protocols)); @@ -612,7 +667,9 @@ impl<'a> SslContextRef<'a> { unsafe { // Attach the protocol list to the OpenSSL context structure, // so that we can refer to it within the callback. - ffi::SSL_CTX_set_ex_data(self.as_ptr(), *NPN_PROTOS_IDX, mem::transmute(protocols)); + try!(cvt(ffi::SSL_CTX_set_ex_data(self.as_ptr(), + *NPN_PROTOS_IDX, + Box::into_raw(protocols) as *mut c_void))); // Now register the callback that performs the default protocol // matching based on the client-supported list of protocols that // has been saved. @@ -624,6 +681,7 @@ impl<'a> SslContextRef<'a> { ffi::SSL_CTX_set_next_protos_advertised_cb(self.as_ptr(), raw_next_protos_advertise_cb, ptr::null_mut()); + Ok(()) } } @@ -634,40 +692,58 @@ 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")] - pub fn set_alpn_protocols(&mut self, protocols: &[&[u8]]) { + /// Requires the `v102` or `v110` features and OpenSSL 1.0.2 or OpenSSL 1.1.0. + #[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] + pub fn set_alpn_protocols(&mut self, protocols: &[&[u8]]) -> Result<(), ErrorStack> { let protocols: Box> = Box::new(ssl_encode_byte_strings(protocols)); unsafe { // Set the context's internal protocol list for use if we are a server - ffi::SSL_CTX_set_alpn_protos(self.as_ptr(), protocols.as_ptr(), protocols.len() as c_uint); + let r = ffi::SSL_CTX_set_alpn_protos(self.as_ptr(), + protocols.as_ptr(), + protocols.len() as c_uint); + // fun fact, SSL_CTX_set_alpn_protos has a reversed return code D: + if r != 0 { + return Err(ErrorStack::get()); + } // Rather than use the argument to the callback to contain our data, store it in the // ssl ctx's ex_data so that we can configure a function to free it later. In the // future, it might make sense to pull this into our internal struct Ssl instead of // leaning on openssl and using function pointers. - ffi::SSL_CTX_set_ex_data(self.as_ptr(), *ALPN_PROTOS_IDX, mem::transmute(protocols)); + try!(cvt(ffi::SSL_CTX_set_ex_data(self.as_ptr(), + *ALPN_PROTOS_IDX, + Box::into_raw(protocols) as *mut c_void))); // Now register the callback that performs the default protocol // matching based on the client-supported list of protocols that // has been saved. ffi::SSL_CTX_set_alpn_select_cb(self.as_ptr(), raw_alpn_select_cb, ptr::null_mut()); + + Ok(()) } } + + /// Checks consistency between the private key and certificate. + pub fn check_private_key(&self) -> Result<(), ErrorStack> { + unsafe { cvt(ffi::SSL_CTX_check_private_key(self.as_ptr())).map(|_| ()) } + } + + pub fn build(self) -> SslContext { + let ctx = SslContext(self.0); + mem::forget(self); + ctx + } } -/// An owned SSL context object. -pub struct SslContext(SslContextRef<'static>); +type_!(SslContext, SslContextRef, ffi::SSL_CTX, ffi::SSL_CTX_free); 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()) } } @@ -680,55 +756,9 @@ impl fmt::Debug for SslContext { } } -impl Drop for SslContext { - fn drop(&mut self) { - unsafe { ffi::SSL_CTX_free(self.as_ptr()) } - } -} - -impl Deref for SslContext { - type Target = SslContextRef<'static>; - - fn deref(&self) -> &SslContextRef<'static> { - &self.0 - } -} - -impl DerefMut for SslContext { - fn deref_mut(&mut self) -> &mut SslContextRef<'static> { - &mut self.0 - } -} - impl SslContext { - /// Creates a new SSL context. - pub fn new(method: SslMethod) -> Result { - init(); - - let mut ctx = unsafe { - let ctx = try_ssl_null!(ffi::SSL_CTX_new(method.to_raw())); - 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), - _ => {} - } - // this is a bit dubious (?) - try!(ctx.set_mode(ffi::SSL_MODE_AUTO_RETRY | ffi::SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER)); - - Ok(ctx) - } - - pub unsafe fn from_ptr(ctx: *mut ffi::SSL_CTX) -> SslContext { - SslContext(SslContextRef::from_ptr(ctx)) - } - - pub fn as_ptr(&self) -> *mut ffi::SSL_CTX { - (**self).as_ptr() + pub fn builder(method: SslMethod) -> Result { + SslContextBuilder::new(method) } } @@ -736,22 +766,47 @@ impl SslContext { pub struct CipherBits { /// The number of secret bits used for the cipher. pub secret: i32, - /// The number of bits processed by the chosen algorithm, if not None. - pub algorithm: Option, - _p: (), + + /// The number of bits processed by the chosen algorithm. + pub algorithm: i32, } +pub struct SslCipher(*mut ffi::SSL_CIPHER); -pub struct SslCipher<'a> { - cipher: *const ffi::SSL_CIPHER, - ph: PhantomData<&'a ()>, +impl OpenSslType for SslCipher { + type CType = ffi::SSL_CIPHER; + type Ref = SslCipherRef; + + unsafe fn from_ptr(ptr: *mut ffi::SSL_CIPHER) -> SslCipher { + SslCipher(ptr) + } } -impl<'a> SslCipher<'a> { +impl Deref for SslCipher { + type Target = SslCipherRef; + + fn deref(&self) -> &SslCipherRef { + unsafe { SslCipherRef::from_ptr(self.0) } + } +} + +impl DerefMut for SslCipher { + fn deref_mut(&mut self) -> &mut SslCipherRef { + unsafe { SslCipherRef::from_ptr_mut(self.0) } + } +} + +pub struct SslCipherRef(Opaque); + +impl OpenSslTypeRef for SslCipherRef { + type CType = ffi::SSL_CIPHER; +} + +impl SslCipherRef { /// Returns the name of cipher. - pub fn name(&self) -> &'static str { + pub fn name(&self) -> &str { let name = unsafe { - let ptr = ffi::SSL_CIPHER_get_name(self.cipher); + let ptr = ffi::SSL_CIPHER_get_name(self.as_ptr()); CStr::from_ptr(ptr as *const _) }; @@ -759,9 +814,9 @@ impl<'a> SslCipher<'a> { } /// Returns the SSL/TLS protocol version that first defined the cipher. - pub fn version(&self) -> &'static str { + pub fn version(&self) -> &str { let version = unsafe { - let ptr = ffi::SSL_CIPHER_get_version(self.cipher); + let ptr = ffi::SSL_CIPHER_get_version(self.as_ptr()); CStr::from_ptr(ptr as *const _) }; @@ -771,78 +826,44 @@ impl<'a> SslCipher<'a> { /// Returns the number of bits used for the cipher. pub fn bits(&self) -> CipherBits { unsafe { - let algo_bits: *mut c_int = ptr::null_mut(); - let secret_bits = ffi::SSL_CIPHER_get_bits(self.cipher, algo_bits); - if !algo_bits.is_null() { - CipherBits { - secret: secret_bits, - algorithm: Some(*algo_bits), - _p: (), - } - } else { - CipherBits { - secret: secret_bits, - algorithm: None, - _p: (), - } + let mut algo_bits = 0; + let secret_bits = ffi::SSL_CIPHER_get_bits(self.as_ptr(), &mut algo_bits); + CipherBits { + secret: secret_bits.into(), + algorithm: algo_bits.into(), } } } /// Returns a textual description of the cipher used - pub fn description(&self) -> Option { + pub fn description(&self) -> String { unsafe { // SSL_CIPHER_description requires a buffer of at least 128 bytes. let mut buf = [0; 128]; - let desc_ptr = ffi::SSL_CIPHER_description(self.cipher, buf.as_mut_ptr(), 128); - - if !desc_ptr.is_null() { - String::from_utf8(CStr::from_ptr(desc_ptr as *const _).to_bytes().to_vec()).ok() - } else { - None - } + let ptr = ffi::SSL_CIPHER_description(self.as_ptr(), buf.as_mut_ptr(), 128); + String::from_utf8(CStr::from_ptr(ptr as *const _).to_bytes().to_vec()).unwrap() } } } -pub struct SslRef<'a>(*mut ffi::SSL, PhantomData<&'a ()>); +type_!(Ssl, SslRef, ffi::SSL, ffi::SSL_free); -unsafe impl<'a> Send for SslRef<'a> {} -unsafe impl<'a> Sync for SslRef<'a> {} - -impl<'a> fmt::Debug for SslRef<'a> { +impl fmt::Debug for SslRef { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_struct("SslRef") - .field("state", &self.state_string_long()) - .finish() + let mut builder = fmt.debug_struct("Ssl"); + builder.field("state", &self.state_string_long()); + if let Some(err) = self.verify_result() { + builder.field("verify_result", &err); + } + builder.finish() } } -impl<'a> SslRef<'a> { - pub unsafe fn from_ptr(ssl: *mut ffi::SSL) -> SslRef<'a> { - SslRef(ssl, PhantomData) - } - - pub fn as_ptr(&self) -> *mut ffi::SSL { - self.0 - } - +impl SslRef { fn get_raw_rbio(&self) -> *mut ffi::BIO { unsafe { ffi::SSL_get_rbio(self.as_ptr()) } } - fn connect(&mut self) -> c_int { - unsafe { ffi::SSL_connect(self.as_ptr()) } - } - - fn accept(&mut self) -> c_int { - unsafe { ffi::SSL_accept(self.as_ptr()) } - } - - fn handshake(&mut self) -> c_int { - unsafe { ffi::SSL_do_handshake(self.as_ptr()) } - } - fn read(&mut self, buf: &mut [u8]) -> c_int { let len = cmp::min(c_int::max_value() as usize, buf.len()) as c_int; unsafe { ffi::SSL_read(self.as_ptr(), buf.as_ptr() as *mut c_void, len) } @@ -872,7 +893,7 @@ impl<'a> SslRef<'a> { /// to the certificate chain. It should return `true` if the certificate /// chain is valid and `false` otherwise. pub fn set_verify_callback(&mut self, mode: SslVerifyMode, verify: F) - where F: Fn(bool, &X509StoreContext) -> bool + Any + 'static + Sync + Send + where F: Fn(bool, &X509StoreContextRef) -> bool + Any + 'static + Sync + Send { unsafe { let verify = Box::new(verify); @@ -883,17 +904,14 @@ impl<'a> SslRef<'a> { } } - pub fn current_cipher(&self) -> Option> { + pub fn current_cipher(&self) -> Option<&SslCipherRef> { unsafe { let ptr = ffi::SSL_get_current_cipher(self.as_ptr()); if ptr.is_null() { None } else { - Some(SslCipher { - cipher: ptr, - ph: PhantomData, - }) + Some(SslCipherRef::from_ptr(ptr as *mut _)) } } } @@ -919,15 +937,9 @@ impl<'a> SslRef<'a> { /// Sets the host name to be used with SNI (Server Name Indication). pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> { let cstr = CString::new(hostname).unwrap(); - let ret = unsafe { - ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) - }; - - // For this case, 0 indicates failure. - if ret == 0 { - Err(ErrorStack::get()) - } else { - Ok(()) + unsafe { + cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) as c_int) + .map(|_| ()) } } @@ -957,9 +969,6 @@ impl<'a> SslRef<'a> { /// /// The protocol's name is returned is an opaque sequence of bytes. It is up to the client /// to interpret it. - /// - /// This method needs the `npn` feature. - #[cfg(feature = "npn")] pub fn selected_npn_protocol(&self) -> Option<&[u8]> { unsafe { let mut data: *const c_uchar = ptr::null(); @@ -981,8 +990,8 @@ impl<'a> SslRef<'a> { /// The protocol's name is returned is an opaque sequence of bytes. It is up to the client /// to interpret it. /// - /// This method needs the `alpn` feature. - #[cfg(feature = "alpn")] + /// Requires the `v102` or `v110` features and OpenSSL 1.0.2 or OpenSSL 1.1.0. + #[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] pub fn selected_alpn_protocol(&self) -> Option<&[u8]> { unsafe { let mut data: *const c_uchar = ptr::null(); @@ -1009,114 +1018,222 @@ impl<'a> SslRef<'a> { /// /// The result will be either None, indicating no compression is in use, or /// a string with the compression name. - pub fn compression(&self) -> Option { - let ptr = unsafe { ffi::SSL_get_current_compression(self.as_ptr()) }; - if ptr == ptr::null() { - return None; - } - - let meth = unsafe { ffi::SSL_COMP_get_name(ptr) }; - let s = unsafe { - String::from_utf8(CStr::from_ptr(meth as *const _).to_bytes().to_vec()).unwrap() - }; - - Some(s) + pub fn compression(&self) -> Option<&str> { + self._compression() } - pub fn ssl_method(&self) -> SslMethod { + #[cfg(not(osslconf = "OPENSSL_NO_COMP"))] + fn _compression(&self) -> Option<&str> { unsafe { - let method = ffi::SSL_get_ssl_method(self.as_ptr()); - SslMethod::from_raw(method).unwrap() + let ptr = ffi::SSL_get_current_compression(self.as_ptr()); + if ptr == ptr::null() { + return None; + } + let meth = ffi::SSL_COMP_get_name(ptr); + Some(str::from_utf8(CStr::from_ptr(meth as *const _).to_bytes()).unwrap()) } } + #[cfg(osslconf = "OPENSSL_NO_COMP")] + fn _compression(&self) -> Option<&str> { + None + } + /// Returns the server's name for the current connection - pub fn servername(&self) -> Option { - let name = unsafe { ffi::SSL_get_servername(self.as_ptr(), ffi::TLSEXT_NAMETYPE_host_name) }; - if name == ptr::null() { - return None; - } + pub fn servername(&self) -> Option<&str> { + unsafe { + let name = ffi::SSL_get_servername(self.as_ptr(), ffi::TLSEXT_NAMETYPE_host_name); + if name == ptr::null() { + return None; + } - unsafe { String::from_utf8(CStr::from_ptr(name as *const _).to_bytes().to_vec()).ok() } + Some(str::from_utf8(CStr::from_ptr(name as *const _).to_bytes()).unwrap()) + } } /// Changes the context corresponding to the current connection. pub fn set_ssl_context(&mut self, ctx: &SslContextRef) -> Result<(), ErrorStack> { - unsafe { - try_ssl_null!(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())); - } - Ok(()) + unsafe { cvt_p(ffi::SSL_set_SSL_CTX(self.as_ptr(), ctx.as_ptr())).map(|_| ()) } } /// Returns the context corresponding to the current connection - pub fn ssl_context(&self) -> SslContextRef<'a> { + pub fn ssl_context(&self) -> &SslContextRef { unsafe { let ssl_ctx = ffi::SSL_get_SSL_CTX(self.as_ptr()); SslContextRef::from_ptr(ssl_ctx) } } + + /// Returns the X509 verification configuration. + /// + /// Requires the `v102` or `v110` features and OpenSSL 1.0.2 or 1.1.0. + #[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] + pub fn param_mut(&mut self) -> &mut X509VerifyParamRef { + self._param_mut() + } + + #[cfg(any(ossl102, ossl110))] + fn _param_mut(&mut self) -> &mut X509VerifyParamRef { + unsafe { X509VerifyParamRef::from_ptr_mut(ffi::SSL_get0_param(self.as_ptr())) } + } + + /// Returns the result of X509 certificate verification. + pub fn verify_result(&self) -> Option { + unsafe { X509VerifyError::from_raw(ffi::SSL_get_verify_result(self.as_ptr())) } + } } -pub struct Ssl(SslRef<'static>); +unsafe impl Sync for Ssl {} +unsafe impl Send for Ssl {} impl fmt::Debug for Ssl { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_struct("Ssl") - .field("state", &self.state_string_long()) - .finish() - } -} - -impl Drop for Ssl { - fn drop(&mut self) { - unsafe { ffi::SSL_free(self.as_ptr()) } - } -} - -impl Deref for Ssl { - type Target = SslRef<'static>; - - fn deref(&self) -> &SslRef<'static> { - &self.0 - } -} - -impl DerefMut for Ssl { - fn deref_mut(&mut self) -> &mut SslRef<'static> { - &mut self.0 + fmt::Debug::fmt(&**self, fmt) } } impl Ssl { pub fn new(ctx: &SslContext) -> Result { unsafe { - let ssl = try_ssl_null!(ffi::SSL_new(ctx.as_ptr())); + let ssl = try!(cvt_p(ffi::SSL_new(ctx.as_ptr()))); Ok(Ssl::from_ptr(ssl)) } } - pub unsafe fn from_ptr(ssl: *mut ffi::SSL) -> Ssl { - Ssl(SslRef::from_ptr(ssl)) + /// Creates an SSL/TLS client operating over the provided stream. + /// + /// # Warning + /// + /// OpenSSL's default configuration is insecure. It is highly recommended to use + /// `SslConnector` rather than `Ssl` directly, as it manages that configuration. + pub fn connect(self, stream: S) -> Result, HandshakeError> + where S: Read + Write + { + let mut stream = SslStream::new_base(self, stream); + let ret = unsafe { ffi::SSL_connect(stream.ssl.as_ptr()) }; + if ret > 0 { + Ok(stream) + } else { + match stream.make_error(ret) { + e @ Error::WantWrite(_) | + e @ Error::WantRead(_) => { + Err(HandshakeError::Interrupted(MidHandshakeSslStream { + stream: stream, + error: e, + })) + } + err => { + Err(HandshakeError::Failure(MidHandshakeSslStream { + stream: stream, + error: err, + })) + } + } + } + } + + /// Creates an SSL/TLS server operating over the provided stream. + /// + /// # Warning + /// + /// OpenSSL's default configuration is insecure. It is highly recommended to use + /// `SslAcceptor` rather than `Ssl` directly, as it manages that configuration. + pub fn accept(self, stream: S) -> Result, HandshakeError> + where S: Read + Write + { + let mut stream = SslStream::new_base(self, stream); + let ret = unsafe { ffi::SSL_accept(stream.ssl.as_ptr()) }; + if ret > 0 { + Ok(stream) + } else { + match stream.make_error(ret) { + e @ Error::WantWrite(_) | + e @ Error::WantRead(_) => { + Err(HandshakeError::Interrupted(MidHandshakeSslStream { + stream: stream, + error: e, + })) + } + err => { + Err(HandshakeError::Failure(MidHandshakeSslStream { + stream: stream, + error: err, + })) + } + } + } + } +} + +/// An SSL stream midway through the handshake process. +#[derive(Debug)] +pub struct MidHandshakeSslStream { + stream: SslStream, + error: Error, +} + +impl MidHandshakeSslStream { + /// Returns a shared reference to the inner stream. + pub fn get_ref(&self) -> &S { + self.stream.get_ref() + } + + /// Returns a mutable reference to the inner stream. + pub fn get_mut(&mut self) -> &mut S { + self.stream.get_mut() + } + + /// Returns a shared reference to the `Ssl` of the stream. + pub fn ssl(&self) -> &SslRef { + self.stream.ssl() + } + + /// Returns the underlying error which interrupted this handshake. + pub fn error(&self) -> &Error { + &self.error + } + + /// Consumes `self`, returning its error. + pub fn into_error(self) -> Error { + self.error + } + + /// Restarts the handshake process. + pub fn handshake(mut self) -> Result, HandshakeError> { + let ret = unsafe { ffi::SSL_do_handshake(self.stream.ssl.as_ptr()) }; + if ret > 0 { + Ok(self.stream) + } else { + match self.stream.make_error(ret) { + e @ Error::WantWrite(_) | + e @ Error::WantRead(_) => { + self.error = e; + Err(HandshakeError::Interrupted(self)) + } + err => { + self.error = err; + Err(HandshakeError::Failure(self)) + } + } + } } } /// A stream wrapper which handles SSL encryption for an underlying stream. pub struct SslStream { ssl: Ssl, - _method: Arc, // NOTE: this *must* be after the Ssl field so things drop right + _method: BioMethod, // NOTE: this *must* be after the Ssl field so things drop right _p: PhantomData, } -unsafe impl Send for SslStream {} - impl fmt::Debug for SslStream where S: fmt::Debug { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.debug_struct("SslStream") - .field("stream", &self.get_ref()) - .field("ssl", &self.ssl()) - .finish() + .field("stream", &self.get_ref()) + .field("ssl", &self.ssl()) + .finish() } } @@ -1134,54 +1251,6 @@ impl SslStream { } } - /// Creates an SSL/TLS client operating over the provided stream. - pub fn connect(ssl: T, stream: S) - -> Result>{ - let ssl = try!(ssl.into_ssl().map_err(|e| { - HandshakeError::Failure(Error::Ssl(e)) - })); - let mut stream = Self::new_base(ssl, stream); - let ret = stream.ssl.connect(); - if ret > 0 { - Ok(stream) - } else { - match stream.make_error(ret) { - e @ Error::WantWrite(_) | - e @ Error::WantRead(_) => { - Err(HandshakeError::Interrupted(MidHandshakeSslStream { - stream: stream, - error: e, - })) - } - err => Err(HandshakeError::Failure(err)), - } - } - } - - /// Creates an SSL/TLS server operating over the provided stream. - pub fn accept(ssl: T, stream: S) - -> Result> { - let ssl = try!(ssl.into_ssl().map_err(|e| { - HandshakeError::Failure(Error::Ssl(e)) - })); - let mut stream = Self::new_base(ssl, stream); - let ret = stream.ssl.accept(); - if ret > 0 { - Ok(stream) - } else { - match stream.make_error(ret) { - e @ Error::WantWrite(_) | - e @ Error::WantRead(_) => { - Err(HandshakeError::Interrupted(MidHandshakeSslStream { - stream: stream, - error: e, - })) - } - err => Err(HandshakeError::Failure(err)), - } - } - } - /// Like `read`, but returns an `ssl::Error` rather than an `io::Error`. /// /// This is particularly useful with a nonblocking socket, where the error @@ -1207,85 +1276,24 @@ impl SslStream { Err(self.make_error(ret)) } } -} -/// An error or intermediate state after a TLS handshake attempt. -#[derive(Debug)] -pub enum HandshakeError { - /// The handshake failed. - Failure(Error), - /// The handshake was interrupted midway through. - Interrupted(MidHandshakeSslStream), -} - -impl stderror::Error for HandshakeError { - fn description(&self) -> &str { - match *self { - HandshakeError::Failure(ref e) => e.description(), - HandshakeError::Interrupted(ref e) => e.error.description(), - } - } - - fn cause(&self) -> Option<&stderror::Error> { - match *self { - HandshakeError::Failure(ref e) => Some(e), - HandshakeError::Interrupted(ref e) => Some(&e.error), - } - } -} - -impl fmt::Display for HandshakeError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(f.write_str(stderror::Error::description(self))); - if let Some(e) = stderror::Error::cause(self) { - try!(write!(f, ": {}", e)); - } - Ok(()) - } -} - -/// An SSL stream midway through the handshake process. -#[derive(Debug)] -pub struct MidHandshakeSslStream { - stream: SslStream, - error: Error, -} - -impl MidHandshakeSslStream { - /// Returns a shared reference to the inner stream. - pub fn get_ref(&self) -> &S { - self.stream.get_ref() - } - - /// Returns a mutable reference to the inner stream. - pub fn get_mut(&mut self) -> &mut S { - self.stream.get_mut() - } - - /// Returns a shared reference to the `Ssl` of the stream. - pub fn ssl(&self) -> &Ssl { - self.stream.ssl() - } - - /// Returns the underlying error which interrupted this handshake. - pub fn error(&self) -> &Error { - &self.error - } - - /// Restarts the handshake process. - pub fn handshake(mut self) -> Result, HandshakeError> { - let ret = self.stream.ssl.handshake(); - if ret > 0 { - Ok(self.stream) - } else { - match self.stream.make_error(ret) { - e @ Error::WantWrite(_) | - e @ Error::WantRead(_) => { - self.error = e; - Err(HandshakeError::Interrupted(self)) - } - err => Err(HandshakeError::Failure(err)), - } + /// Shuts down the session. + /// + /// The shutdown process consists of two steps. The first step sends a + /// close notify message to the peer, after which `ShutdownResult::Sent` + /// is returned. The second step awaits the receipt of a close notify + /// message from the peer, after which `ShutdownResult::Received` is + /// returned. + /// + /// While the connection may be closed after the first step, it is + /// recommended to fully shut the session down. In particular, it must + /// be fully shut down if the connection is to be used for further + /// communication in the future. + pub fn shutdown(&mut self) -> Result { + match unsafe { ffi::SSL_shutdown(self.ssl.as_ptr()) } { + 0 => Ok(ShutdownResult::Sent), + 1 => Ok(ShutdownResult::Received), + n => Err(self.make_error(n)), } } } @@ -1319,16 +1327,12 @@ impl SslStream { } } - #[cfg(feature = "nightly")] fn check_panic(&mut self) { if let Some(err) = unsafe { bio::take_panic::(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::(self.ssl.get_raw_rbio()) }; match error { @@ -1362,7 +1366,7 @@ impl SslStream { } /// Returns the OpenSSL `Ssl` object associated with this stream. - pub fn ssl(&self) -> &Ssl { + pub fn ssl(&self) -> &SslRef { &self.ssl } } @@ -1397,18 +1401,101 @@ impl Write for SslStream { } } -pub trait IntoSsl { - fn into_ssl(self) -> Result; +/// The result of a shutdown request. +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum ShutdownResult { + /// A close notify message has been sent to the peer. + Sent, + + /// A close notify response message has been received from the peer. + Received, } -impl IntoSsl for Ssl { - fn into_ssl(self) -> Result { - Ok(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}; + + 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 fn tls_method() -> *const ffi::SSL_METHOD { + unsafe { ffi::TLS_method() } + } + + pub fn dtls_method() -> *const ffi::SSL_METHOD { + unsafe { ffi::DTLS_method() } } } -impl<'a> IntoSsl for &'a SslContext { - fn into_ssl(self) -> Result { - Ssl::new(self) +#[cfg(ossl10x)] +#[allow(bad_style)] +mod compat { + use std::ptr; + + use ffi; + use libc::{self, c_long, c_ulong, c_int}; + + 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 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 + } + + pub fn tls_method() -> *const ffi::SSL_METHOD { + unsafe { ffi::SSLv23_method() } + } + + pub fn dtls_method() -> *const ffi::SSL_METHOD { + unsafe { ffi::DTLSv1_method() } } } diff --git a/openssl/src/ssl/tests/mod.rs b/openssl/src/ssl/tests/mod.rs index 3bbbed03..a84f6b25 100644 --- a/openssl/src/ssl/tests/mod.rs +++ b/openssl/src/ssl/tests/mod.rs @@ -1,5 +1,6 @@ #![allow(unused_imports)] +use std::env; use std::fs::File; use std::io::prelude::*; use std::io::{self, BufReader}; @@ -11,31 +12,26 @@ use std::process::{Command, Child, Stdio, ChildStdin}; use std::thread; use std::time::Duration; -use net2::TcpStreamExt; +use tempdir::TempDir; -use crypto::hash::Type::SHA256; +use hash::MessageDigest; use ssl; use ssl::SSL_VERIFY_PEER; -use ssl::SslMethod::Sslv23; use ssl::{SslMethod, HandshakeError}; -use ssl::error::Error; -use ssl::{SslContext, SslStream}; -use x509::X509StoreContext; -use x509::X509FileType; -use x509::X509; -use crypto::pkey::PKey; +use ssl::{SslContext, SslStream, Ssl, ShutdownResult, SslConnectorBuilder, SslAcceptorBuilder, + Error}; +use x509::{X509StoreContext, X509, X509_FILETYPE_PEM}; +#[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] +use x509::verify::X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS; +use pkey::PKey; -#[cfg(feature="dtlsv1")] use std::net::UdpSocket; -#[cfg(feature="dtlsv1")] -use ssl::SslMethod::Dtlsv1; -#[cfg(feature="sslv2")] -use ssl::SslMethod::Sslv2; -#[cfg(feature="dtlsv1")] -use net2::UdpSocketExt; mod select; +static CERT: &'static [u8] = include_bytes!("../../../test/cert.pem"); +static KEY: &'static [u8] = include_bytes!("../../../test/key.pem"); + fn next_addr() -> SocketAddr { use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; static PORT: AtomicUsize = ATOMIC_USIZE_INIT; @@ -46,32 +42,42 @@ fn next_addr() -> SocketAddr { struct Server { p: Child, + _temp: TempDir, } impl Server { fn spawn(args: &[&str], input: Option>) -> (Server, SocketAddr) { + 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") - .arg("-accept") - .arg(addr.port().to_string()) - .args(args) - .arg("-cert") - .arg("cert.pem") - .arg("-key") - .arg("key.pem") - .arg("-no_dhe") - .current_dir("test") - .stdout(Stdio::null()) - .stderr(Stdio::null()) - .stdin(Stdio::piped()) - .spawn() - .unwrap(); + .arg("s_server") + .arg("-accept") + .arg(addr.port().to_string()) + .args(args) + .arg("-cert") + .arg(&cert) + .arg("-key") + .arg(&key) + .arg("-no_dhe") + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .stdin(Stdio::piped()) + .spawn() + .unwrap(); let stdin = child.stdin.take().unwrap(); 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 +98,6 @@ impl Server { Server::new_tcp(&["-www"]) } - #[cfg(any(feature = "alpn", feature = "npn"))] fn new_alpn() -> (Server, TcpStream) { Server::new_tcp(&["-www", "-nextprotoneg", @@ -101,7 +106,6 @@ impl Server { "http/1.1,spdy/3.1"]) } - #[cfg(feature = "dtlsv1")] fn new_dtlsv1(input: I) -> (Server, UdpConnected) where I: IntoIterator, I::IntoIter: Send + 'static @@ -109,17 +113,17 @@ impl Server { let mut input = input.into_iter(); let (s, addr) = Server::spawn(&["-dtls1"], Some(Box::new(move |mut io| { - for s in input.by_ref() { - if io.write_all(s.as_bytes()).is_err() { - break; - } - } - }))); + for s in input.by_ref() { + if io.write_all(s.as_bytes()).is_err() { + break; + } + } + }))); // Need to wait for the UDP socket to get bound in our child process, // 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)) } @@ -132,51 +136,18 @@ impl Drop for Server { } } -#[cfg(feature = "dtlsv1")] #[derive(Debug)] struct UdpConnected(UdpSocket); -#[cfg(feature = "dtlsv1")] impl Read for UdpConnected { fn read(&mut self, buf: &mut [u8]) -> io::Result { - self.0.recv_from(buf).map(|(s, _)| s) + self.0.recv(buf) } } -#[cfg(feature = "dtlsv1")] impl Write for UdpConnected { - #[cfg(unix)] fn write(&mut self, buf: &[u8]) -> io::Result { - use std::os::unix::prelude::*; - use libc; - let n = unsafe { - libc::send(self.0.as_raw_fd(), - buf.as_ptr() as *const _, - buf.len() as libc::size_t, - 0) - }; - if n < 0 { - Err(io::Error::last_os_error()) - } else { - Ok(n as usize) - } - } - - #[cfg(windows)] - fn write(&mut self, buf: &[u8]) -> io::Result { - use std::os::windows::prelude::*; - use libc; - let n = unsafe { - libc::send(self.0.as_raw_socket(), - buf.as_ptr() as *const _, - buf.len() as libc::c_int, - 0) - }; - if n < 0 { - Err(io::Error::last_os_error()) - } else { - Ok(n as usize) - } + self.0.send(buf) } fn flush(&mut self) -> io::Result<()> { @@ -197,147 +168,139 @@ macro_rules! run_test( use ssl::SslMethod; use ssl::{SslContext, Ssl, SslStream}; use ssl::SSL_VERIFY_PEER; - use crypto::hash::Type::{SHA1, SHA256}; + use hash::MessageDigest; use x509::X509StoreContext; use serialize::hex::FromHex; + use types::OpenSslTypeRef; use super::Server; #[test] fn sslv23() { let (_s, stream) = Server::new(); - $blk(SslMethod::Sslv23, stream); + $blk(SslMethod::tls(), stream); } #[test] - #[cfg(feature="dtlsv1")] + #[cfg_attr(any(windows, target_arch = "arm"), ignore)] // FIXME(#467) fn dtlsv1() { let (_s, stream) = Server::new_dtlsv1(Some("hello")); - $blk(SslMethod::Dtlsv1, stream); + $blk(SslMethod::dtls(), stream); } } ); ); run_test!(new_ctx, |method, _| { - SslContext::new(method).unwrap(); -}); - -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); + SslContext::builder(method).unwrap(); }); run_test!(verify_untrusted, |method, stream| { - let mut ctx = SslContext::new(method).unwrap(); + let mut ctx = SslContext::builder(method).unwrap(); ctx.set_verify(SSL_VERIFY_PEER); - match SslStream::connect(&ctx, stream) { + match Ssl::new(&ctx.build()).unwrap().connect(stream) { Ok(_) => panic!("expected failure"), Err(err) => println!("error {:?}", err), } }); run_test!(verify_trusted, |method, stream| { - let mut ctx = SslContext::new(method).unwrap(); + let mut ctx = SslContext::builder(method).unwrap(); ctx.set_verify(SSL_VERIFY_PEER); - match ctx.set_CA_file(&Path::new("test/root-ca.pem")) { + match ctx.set_ca_file(&Path::new("test/root-ca.pem")) { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err), } - match SslStream::connect(&ctx, stream) { + match Ssl::new(&ctx.build()).unwrap().connect(stream) { Ok(_) => (), Err(err) => panic!("Expected success, got {:?}", err), } }); run_test!(verify_untrusted_callback_override_ok, |method, stream| { - let mut ctx = SslContext::new(method).unwrap(); + let mut ctx = SslContext::builder(method).unwrap(); ctx.set_verify_callback(SSL_VERIFY_PEER, |_, _| true); - match SslStream::connect(&ctx, stream) { + match Ssl::new(&ctx.build()).unwrap().connect(stream) { Ok(_) => (), Err(err) => panic!("Expected success, got {:?}", err), } }); run_test!(verify_untrusted_callback_override_bad, |method, stream| { - let mut ctx = SslContext::new(method).unwrap(); + let mut ctx = SslContext::builder(method).unwrap(); ctx.set_verify_callback(SSL_VERIFY_PEER, |_, _| false); - assert!(SslStream::connect(&ctx, stream).is_err()); + assert!(Ssl::new(&ctx.build()).unwrap().connect(stream).is_err()); }); run_test!(verify_trusted_callback_override_ok, |method, stream| { - let mut ctx = SslContext::new(method).unwrap(); + let mut ctx = SslContext::builder(method).unwrap(); ctx.set_verify_callback(SSL_VERIFY_PEER, |_, _| true); - match ctx.set_CA_file(&Path::new("test/cert.pem")) { + match ctx.set_ca_file(&Path::new("test/cert.pem")) { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err), } - match SslStream::connect(&ctx, stream) { + match Ssl::new(&ctx.build()).unwrap().connect(stream) { Ok(_) => (), Err(err) => panic!("Expected success, got {:?}", err), } }); run_test!(verify_trusted_callback_override_bad, |method, stream| { - let mut ctx = SslContext::new(method).unwrap(); + let mut ctx = SslContext::builder(method).unwrap(); ctx.set_verify_callback(SSL_VERIFY_PEER, |_, _| false); - match ctx.set_CA_file(&Path::new("test/cert.pem")) { + match ctx.set_ca_file(&Path::new("test/cert.pem")) { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err), } - assert!(SslStream::connect(&ctx, stream).is_err()); + assert!(Ssl::new(&ctx.build()).unwrap().connect(stream).is_err()); }); run_test!(verify_callback_load_certs, |method, stream| { - let mut ctx = SslContext::new(method).unwrap(); + let mut ctx = SslContext::builder(method).unwrap(); ctx.set_verify_callback(SSL_VERIFY_PEER, |_, x509_ctx| { assert!(x509_ctx.current_cert().is_some()); true }); - assert!(SslStream::connect(&ctx, stream).is_ok()); + assert!(Ssl::new(&ctx.build()).unwrap().connect(stream).is_ok()); }); run_test!(verify_trusted_get_error_ok, |method, stream| { - let mut ctx = SslContext::new(method).unwrap(); + let mut ctx = SslContext::builder(method).unwrap(); ctx.set_verify_callback(SSL_VERIFY_PEER, |_, x509_ctx| { assert!(x509_ctx.error().is_none()); true }); - match ctx.set_CA_file(&Path::new("test/root-ca.pem")) { + match ctx.set_ca_file(&Path::new("test/root-ca.pem")) { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err), } - assert!(SslStream::connect(&ctx, stream).is_ok()); + assert!(Ssl::new(&ctx.build()).unwrap().connect(stream).is_ok()); }); run_test!(verify_trusted_get_error_err, |method, stream| { - let mut ctx = SslContext::new(method).unwrap(); + let mut ctx = SslContext::builder(method).unwrap(); ctx.set_verify_callback(SSL_VERIFY_PEER, |_, x509_ctx| { assert!(x509_ctx.error().is_some()); false }); - assert!(SslStream::connect(&ctx, stream).is_err()); + assert!(Ssl::new(&ctx.build()).unwrap().connect(stream).is_err()); }); run_test!(verify_callback_data, |method, stream| { - let mut ctx = SslContext::new(method).unwrap(); + let mut ctx = SslContext::builder(method).unwrap(); - // Node id was generated as SHA256 hash of certificate "test/cert.pem" - // in DER format. - // Command: openssl x509 -in test/cert.pem -outform DER | openssl dgst -sha256 - // Please update if "test/cert.pem" will ever change +// Node id was generated as SHA256 hash of certificate "test/cert.pem" +// in DER format. +// Command: openssl x509 -in test/cert.pem -outform DER | openssl dgst -sha256 +// Please update if "test/cert.pem" will ever change let node_hash_str = "59172d9313e84459bcff27f967e79e6e9217e584"; let node_id = node_hash_str.from_hex().unwrap(); ctx.set_verify_callback(SSL_VERIFY_PEER, move |_preverify_ok, x509_ctx| { @@ -345,14 +308,14 @@ run_test!(verify_callback_data, |method, stream| { match cert { None => false, Some(cert) => { - let fingerprint = cert.fingerprint(SHA1).unwrap(); + let fingerprint = cert.fingerprint(MessageDigest::sha1()).unwrap(); fingerprint == node_id } } }); ctx.set_verify_depth(1); - match SslStream::connect(&ctx, stream) { + match Ssl::new(&ctx.build()).unwrap().connect(stream) { Ok(_) => (), Err(err) => panic!("Expected success, got {:?}", err), } @@ -360,12 +323,11 @@ run_test!(verify_callback_data, |method, stream| { run_test!(ssl_verify_callback, |method, stream| { use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; - use ssl::IntoSsl; static CHECKED: AtomicUsize = ATOMIC_USIZE_INIT; - let ctx = SslContext::new(method).unwrap(); - let mut ssl = ctx.into_ssl().unwrap(); + let ctx = SslContext::builder(method).unwrap(); + let mut ssl = Ssl::new(&ctx.build()).unwrap(); let node_hash_str = "59172d9313e84459bcff27f967e79e6e9217e584"; let node_id = node_hash_str.from_hex().unwrap(); @@ -374,13 +336,13 @@ run_test!(ssl_verify_callback, |method, stream| { match x509.current_cert() { None => false, Some(cert) => { - let fingerprint = cert.fingerprint(SHA1).unwrap(); + let fingerprint = cert.fingerprint(MessageDigest::sha1()).unwrap(); fingerprint == node_id } } }); - match SslStream::connect(ssl, stream) { + match ssl.connect(stream) { Ok(_) => (), Err(err) => panic!("Expected success, got {:?}", err), } @@ -391,24 +353,24 @@ 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::builder(SslMethod::tls()).unwrap(); let stream = TcpStream::connect(addr).unwrap(); - let mut stream = SslStream::connect(&ctx, stream).unwrap(); + let mut stream = Ssl::new(&ctx.build()).unwrap().connect(stream).unwrap(); stream.write_all(b"hello").unwrap(); stream }); - let mut ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::builder(SslMethod::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(); + ctx.set_certificate_file(&Path::new("test/cert.pem"), X509_FILETYPE_PEM).unwrap(); + ctx.set_private_key_file(&Path::new("test/key.pem"), X509_FILETYPE_PEM).unwrap(); let stream = listener.accept().unwrap().0; - let mut stream = SslStream::accept(&ctx, stream).unwrap(); + let mut stream = Ssl::new(&ctx.build()).unwrap().accept(stream).unwrap(); let mut buf = [0; 5]; assert_eq!(5, stream.read(&mut buf).unwrap()); @@ -423,7 +385,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::builder(SslMethod::tls()).unwrap(); ctx.set_private_key(&key).unwrap(); ctx.set_certificate(&cert).unwrap(); @@ -431,18 +393,18 @@ fn test_set_certificate_and_private_key() { } run_test!(get_ctx_options, |method, _| { - let ctx = SslContext::new(method).unwrap(); + let ctx = SslContext::builder(method).unwrap(); ctx.options(); }); run_test!(set_ctx_options, |method, _| { - let mut ctx = SslContext::new(method).unwrap(); + let mut ctx = SslContext::builder(method).unwrap(); let opts = ctx.set_options(ssl::SSL_OP_NO_TICKET); assert!(opts.contains(ssl::SSL_OP_NO_TICKET)); }); run_test!(clear_ctx_options, |method, _| { - let mut ctx = SslContext::new(method).unwrap(); + let mut ctx = SslContext::builder(method).unwrap(); ctx.set_options(ssl::SSL_OP_ALL); let opts = ctx.clear_options(ssl::SSL_OP_ALL); assert!(!opts.contains(ssl::SSL_OP_ALL)); @@ -451,17 +413,8 @@ 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(); - stream.write_all("hello".as_bytes()).unwrap(); - stream.flush().unwrap(); - stream.write_all(" there".as_bytes()).unwrap(); - stream.flush().unwrap(); -} - -#[test] -fn test_write_direct() { - let (_s, stream) = Server::new(); - let mut stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), stream).unwrap(); + let ctx = SslContext::builder(SslMethod::tls()).unwrap(); + let mut stream = Ssl::new(&ctx.build()).unwrap().connect(stream).unwrap(); stream.write_all("hello".as_bytes()).unwrap(); stream.flush().unwrap(); stream.write_all(" there".as_bytes()).unwrap(); @@ -469,20 +422,21 @@ fn test_write_direct() { } run_test!(get_peer_certificate, |method, stream| { - let stream = SslStream::connect(&SslContext::new(method).unwrap(), stream).unwrap(); + let ctx = SslContext::builder(method).unwrap(); + let stream = Ssl::new(&ctx.build()).unwrap().connect(stream).unwrap(); let cert = stream.ssl().peer_certificate().unwrap(); - let fingerprint = cert.fingerprint(SHA1).unwrap(); + let fingerprint = cert.fingerprint(MessageDigest::sha1()).unwrap(); let node_hash_str = "59172d9313e84459bcff27f967e79e6e9217e584"; let node_id = node_hash_str.from_hex().unwrap(); assert_eq!(node_id, fingerprint) }); #[test] -#[cfg(feature = "dtlsv1")] +#[cfg_attr(any(windows, target_arch = "arm"), ignore)] // FIXME(#467) fn test_write_dtlsv1() { let (_s, stream) = Server::new_dtlsv1(iter::repeat("y\n")); - - let mut stream = SslStream::connect(&SslContext::new(Dtlsv1).unwrap(), stream).unwrap(); + let ctx = SslContext::builder(SslMethod::dtls()).unwrap(); + let mut stream = Ssl::new(&ctx.build()).unwrap().connect(stream).unwrap(); stream.write_all(b"hello").unwrap(); stream.flush().unwrap(); stream.write_all(b" there").unwrap(); @@ -492,16 +446,8 @@ fn test_write_dtlsv1() { #[test] fn test_read() { let (_s, tcp) = Server::new(); - let mut stream = SslStream::connect(&SslContext::new(Sslv23).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"); -} - -#[test] -fn test_read_direct() { - let (_s, tcp) = Server::new(); - let mut stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); + let ctx = SslContext::builder(SslMethod::tls()).unwrap(); + let mut stream = Ssl::new(&ctx.build()).unwrap().connect(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 +456,8 @@ 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 ctx = SslContext::builder(SslMethod::tls()).unwrap(); + let mut stream = Ssl::new(&ctx.build()).unwrap().connect(tcp).unwrap(); stream.write_all("GET /\r\n\r\n".as_bytes()).unwrap(); stream.flush().unwrap(); @@ -533,7 +480,8 @@ fn test_pending() { #[test] fn test_state() { let (_s, tcp) = Server::new(); - let stream = SslStream::connect(&SslContext::new(Sslv23).unwrap(), tcp).unwrap(); + let ctx = SslContext::builder(SslMethod::tls()).unwrap(); + let stream = Ssl::new(&ctx.build()).unwrap().connect(tcp).unwrap(); assert_eq!(stream.ssl().state_string(), "SSLOK "); assert_eq!(stream.ssl().state_string_long(), "SSL negotiation finished successfully"); @@ -542,17 +490,17 @@ 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(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] fn test_connect_with_unilateral_alpn() { let (_s, stream) = Server::new(); - let mut ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::builder(SslMethod::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")) { + ctx.set_alpn_protocols(&[b"http/1.1", b"spdy/3.1"]).unwrap(); + match ctx.set_ca_file(&Path::new("test/root-ca.pem")) { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err), } - let stream = match SslStream::connect(&ctx, stream) { + let stream = match Ssl::new(&ctx.build()).unwrap().connect(stream) { Ok(stream) => stream, Err(err) => panic!("Expected success, got {:?}", err), }; @@ -564,17 +512,16 @@ 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")] fn test_connect_with_unilateral_npn() { let (_s, stream) = Server::new(); - let mut ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::builder(SslMethod::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")) { + ctx.set_npn_protocols(&[b"http/1.1", b"spdy/3.1"]).unwrap(); + match ctx.set_ca_file(&Path::new("test/root-ca.pem")) { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err), } - let stream = match SslStream::connect(&ctx, stream) { + let stream = match Ssl::new(&ctx.build()).unwrap().connect(stream) { Ok(stream) => stream, Err(err) => panic!("Expected success, got {:?}", err), }; @@ -586,17 +533,17 @@ 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(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] 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::builder(SslMethod::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")) { + ctx.set_alpn_protocols(&[b"spdy/3.1", b"http/1.1"]).unwrap(); + match ctx.set_ca_file(&Path::new("test/root-ca.pem")) { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err), } - let stream = match SslStream::connect(&ctx, stream) { + let stream = match Ssl::new(&ctx.build()).unwrap().connect(stream) { Ok(stream) => stream, Err(err) => panic!("Expected success, got {:?}", err), }; @@ -608,17 +555,17 @@ 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(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] 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::builder(SslMethod::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")) { + ctx.set_npn_protocols(&[b"spdy/3.1", b"http/1.1"]).unwrap(); + match ctx.set_ca_file(&Path::new("test/root-ca.pem")) { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err), } - let stream = match SslStream::connect(&ctx, stream) { + let stream = match Ssl::new(&ctx.build()).unwrap().connect(stream) { Ok(stream) => stream, Err(err) => panic!("Expected success, got {:?}", err), }; @@ -631,17 +578,17 @@ 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(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] 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::builder(SslMethod::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")) { + ctx.set_alpn_protocols(&[b"spdy/3.1"]).unwrap(); + match ctx.set_ca_file(&Path::new("test/root-ca.pem")) { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err), } - let stream = match SslStream::connect(&ctx, stream) { + let stream = match Ssl::new(&ctx.build()).unwrap().connect(stream) { Ok(stream) => stream, Err(err) => panic!("Expected success, got {:?}", err), }; @@ -655,17 +602,17 @@ 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(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] 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::builder(SslMethod::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")) { + ctx.set_npn_protocols(&[b"spdy/3.1"]).unwrap(); + match ctx.set_ca_file(&Path::new("test/root-ca.pem")) { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err), } - let stream = match SslStream::connect(&ctx, stream) { + let stream = match Ssl::new(&ctx.build()).unwrap().connect(stream) { Ok(stream) => stream, Err(err) => panic!("Expected success, got {:?}", err), }; @@ -677,37 +624,36 @@ 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")] 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::builder(SslMethod::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) + ctx.set_npn_protocols(&[b"http/1.1", b"spdy/3.1"]).unwrap(); + assert!(ctx.set_certificate_file(&Path::new("test/cert.pem"), X509_FILETYPE_PEM) .is_ok()); - ctx.set_private_key_file(&Path::new("test/key.pem"), X509FileType::PEM) - .unwrap(); - ctx + ctx.set_private_key_file(&Path::new("test/key.pem"), X509_FILETYPE_PEM) + .unwrap(); + ctx.build() }; // Have the listener wait on the connection in a different thread. thread::spawn(move || { let (stream, _) = listener.accept().unwrap(); - let _ = SslStream::accept(&listener_ctx, stream).unwrap(); + Ssl::new(&listener_ctx).unwrap().accept(stream).unwrap(); }); - let mut ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::builder(SslMethod::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")) { + ctx.set_npn_protocols(&[b"spdy/3.1"]).unwrap(); + match ctx.set_ca_file(&Path::new("test/root-ca.pem")) { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err), } // Now connect to the socket and make sure the protocol negotiation works... let stream = TcpStream::connect(localhost).unwrap(); - let stream = match SslStream::connect(&ctx, stream) { + let stream = match Ssl::new(&ctx.build()).unwrap().connect(stream) { Ok(stream) => stream, Err(err) => panic!("Expected success, got {:?}", err), }; @@ -718,37 +664,37 @@ 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(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] 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::builder(SslMethod::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) + ctx.set_alpn_protocols(&[b"http/1.1", b"spdy/3.1"]).unwrap(); + assert!(ctx.set_certificate_file(&Path::new("test/cert.pem"), X509_FILETYPE_PEM) .is_ok()); - ctx.set_private_key_file(&Path::new("test/key.pem"), X509FileType::PEM) - .unwrap(); - ctx + ctx.set_private_key_file(&Path::new("test/key.pem"), X509_FILETYPE_PEM) + .unwrap(); + ctx.build() }; // Have the listener wait on the connection in a different thread. thread::spawn(move || { let (stream, _) = listener.accept().unwrap(); - let _ = SslStream::accept(&listener_ctx, stream).unwrap(); + Ssl::new(&listener_ctx).unwrap().accept(stream).unwrap(); }); - let mut ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::builder(SslMethod::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")) { + ctx.set_alpn_protocols(&[b"spdy/3.1"]).unwrap(); + match ctx.set_ca_file(&Path::new("test/root-ca.pem")) { Ok(_) => {} Err(err) => panic!("Unexpected error {:?}", err), } // Now connect to the socket and make sure the protocol negotiation works... let stream = TcpStream::connect(localhost).unwrap(); - let stream = match SslStream::connect(&ctx, stream) { + let stream = match Ssl::new(&ctx.build()).unwrap().connect(stream) { Ok(stream) => stream, Err(err) => panic!("Expected success, got {:?}", err), }; @@ -759,87 +705,82 @@ 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 = "v102", ossl102))] 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::builder(SslMethod::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) + ctx.set_alpn_protocols(&[b"http/1.1", b"spdy/3.1"]).unwrap(); + assert!(ctx.set_certificate_file(&Path::new("test/cert.pem"), X509_FILETYPE_PEM) .is_ok()); - ctx.set_private_key_file(&Path::new("test/key.pem"), X509FileType::PEM) - .unwrap(); - ctx + ctx.set_private_key_file(&Path::new("test/key.pem"), X509_FILETYPE_PEM) + .unwrap(); + ctx.build() }; // Have the listener wait on the connection in a different thread. thread::spawn(move || { let (stream, _) = listener.accept().unwrap(); - let _ = SslStream::accept(&listener_ctx, stream).unwrap(); + Ssl::new(&listener_ctx).unwrap().accept(stream).unwrap(); }); - let mut ctx = SslContext::new(Sslv23).unwrap(); + let mut ctx = SslContext::builder(SslMethod::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")) { - Ok(_) => {} - Err(err) => panic!("Unexpected error {:?}", err), - } + ctx.set_alpn_protocols(&[b"http/2"]).unwrap(); + ctx.set_ca_file(&Path::new("test/root-ca.pem")).unwrap(); // Now connect to the socket and make sure the protocol negotiation works... let stream = TcpStream::connect(localhost).unwrap(); - let stream = match SslStream::connect(&ctx, stream) { - Ok(stream) => stream, - Err(err) => panic!("Expected success, got {:?}", err), - }; + let stream = Ssl::new(&ctx.build()).unwrap().connect(stream).unwrap(); // Since the protocols from the server and client don't overlap at all, no protocol is selected assert_eq!(None, stream.ssl().selected_alpn_protocol()); } +// In 1.1.0, ALPN negotiation failure is a fatal error +#[test] +#[cfg(all(feature = "v110", ossl110))] +fn test_alpn_server_select_none() { + 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::builder(SslMethod::tls()).unwrap(); + ctx.set_verify(SSL_VERIFY_PEER); + ctx.set_alpn_protocols(&[b"http/1.1", b"spdy/3.1"]).unwrap(); + assert!(ctx.set_certificate_file(&Path::new("test/cert.pem"), X509_FILETYPE_PEM) + .is_ok()); + ctx.set_private_key_file(&Path::new("test/key.pem"), X509_FILETYPE_PEM) + .unwrap(); + ctx.build() + }; + // Have the listener wait on the connection in a different thread. + thread::spawn(move || { + let (stream, _) = listener.accept().unwrap(); + assert!(Ssl::new(&listener_ctx).unwrap().accept(stream).is_err()); + }); -#[cfg(feature="dtlsv1")] -#[cfg(test)] -mod dtlsv1 { - use serialize::hex::FromHex; - use std::net::TcpStream; - use std::thread; - - use crypto::hash::Type::SHA256; - use ssl::SslMethod; - use ssl::SslMethod::Dtlsv1; - use ssl::{SslContext, SslStream}; - use ssl::SSL_VERIFY_PEER; - use x509::X509StoreContext; - - const PROTOCOL: SslMethod = Dtlsv1; - - #[test] - fn test_new_ctx() { - SslContext::new(PROTOCOL).unwrap(); - } + let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); + ctx.set_verify(SSL_VERIFY_PEER); + ctx.set_alpn_protocols(&[b"http/2"]).unwrap(); + ctx.set_ca_file(&Path::new("test/root-ca.pem")).unwrap(); + // Now connect to the socket and make sure the protocol negotiation works... + let stream = TcpStream::connect(localhost).unwrap(); + assert!(Ssl::new(&ctx.build()).unwrap().connect(stream).is_err()); } #[test] -#[cfg(feature = "dtlsv1")] +#[cfg_attr(any(windows, target_arch = "arm"), ignore)] // FIXME(#467) fn test_read_dtlsv1() { let (_s, stream) = Server::new_dtlsv1(Some("hello")); - let mut stream = SslStream::connect(&SslContext::new(Dtlsv1).unwrap(), stream).unwrap(); + let ctx = SslContext::builder(SslMethod::dtls()).unwrap(); + let mut stream = Ssl::new(&ctx.build()).unwrap().connect(stream).unwrap(); let mut buf = [0u8; 100]; assert!(stream.read(&mut buf).is_ok()); } -#[test] -#[cfg(feature = "sslv2")] -fn test_sslv2_connect_failure() { - let (_s, tcp) = Server::new_tcp(&["-no_ssl2", "-www"]); - SslStream::connect(&SslContext::new(Sslv2).unwrap(), tcp) - .err() - .unwrap(); -} - fn wait_io(stream: &TcpStream, read: bool, timeout_ms: u32) -> bool { unsafe { let mut set: select::fd_set = mem::zeroed(); @@ -859,8 +800,7 @@ fn wait_io(stream: &TcpStream, read: bool, timeout_ms: u32) -> bool { } } -fn handshake(res: Result, HandshakeError>) - -> SslStream { +fn handshake(res: Result, HandshakeError>) -> SslStream { match res { Ok(s) => s, Err(HandshakeError::Interrupted(s)) => { @@ -875,8 +815,8 @@ fn handshake(res: Result, HandshakeError>) fn test_write_nonblocking() { let (_s, stream) = Server::new(); stream.set_nonblocking(true).unwrap(); - let cx = SslContext::new(Sslv23).unwrap(); - let mut stream = handshake(SslStream::connect(&cx, stream)); + let cx = SslContext::builder(SslMethod::tls()).unwrap().build(); + let mut stream = handshake(Ssl::new(&cx).unwrap().connect(stream)); let mut iterations = 0; loop { @@ -909,12 +849,12 @@ fn test_write_nonblocking() { } #[test] -#[cfg_attr(windows, ignore)] // FIXME flickers on appveyor +#[cfg_attr(any(windows, target_arch = "arm"), ignore)] // FIXME(#467) fn test_read_nonblocking() { let (_s, stream) = Server::new(); stream.set_nonblocking(true).unwrap(); - let cx = SslContext::new(Sslv23).unwrap(); - let mut stream = handshake(SslStream::connect(&cx, stream)); + let cx = SslContext::builder(SslMethod::tls()).unwrap().build(); + let mut stream = handshake(Ssl::new(&cx).unwrap().connect(stream)); let mut iterations = 0; loop { @@ -965,7 +905,6 @@ fn test_read_nonblocking() { #[test] #[should_panic(expected = "blammo")] -#[cfg(feature = "nightly")] fn write_panic() { struct ExplodingStream(TcpStream); @@ -988,13 +927,12 @@ fn write_panic() { let (_s, stream) = Server::new(); let stream = ExplodingStream(stream); - let ctx = SslContext::new(SslMethod::Sslv23).unwrap(); - let _ = SslStream::connect(&ctx, stream); + let ctx = SslContext::builder(SslMethod::tls()).unwrap(); + let _ = Ssl::new(&ctx.build()).unwrap().connect(stream); } #[test] #[should_panic(expected = "blammo")] -#[cfg(feature = "nightly")] fn read_panic() { struct ExplodingStream(TcpStream); @@ -1017,13 +955,12 @@ fn read_panic() { let (_s, stream) = Server::new(); let stream = ExplodingStream(stream); - let ctx = SslContext::new(SslMethod::Sslv23).unwrap(); - let _ = SslStream::connect(&ctx, stream); + let ctx = SslContext::builder(SslMethod::tls()).unwrap(); + let _ = Ssl::new(&ctx.build()).unwrap().connect(stream); } #[test] #[should_panic(expected = "blammo")] -#[cfg(feature = "nightly")] fn flush_panic() { struct ExplodingStream(TcpStream); @@ -1046,32 +983,31 @@ 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::builder(SslMethod::tls()).unwrap(); + let mut stream = Ssl::new(&ctx.build()).unwrap().connect(stream).ok().unwrap(); let _ = stream.flush(); } #[test] fn refcount_ssl_context() { let mut ssl = { - let ctx = SslContext::new(SslMethod::Sslv23).unwrap(); - ssl::Ssl::new(&ctx).unwrap() + let ctx = SslContext::builder(SslMethod::tls()).unwrap(); + ssl::Ssl::new(&ctx.build()).unwrap() }; { - let new_ctx_a = SslContext::new(SslMethod::Sslv23).unwrap(); + let new_ctx_a = SslContext::builder(SslMethod::tls()).unwrap().build(); let _new_ctx_b = ssl.set_ssl_context(&new_ctx_a); } } #[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::builder(SslMethod::tls()).unwrap(); ctx.set_default_verify_paths().unwrap(); ctx.set_verify(SSL_VERIFY_PEER); let s = TcpStream::connect("google.com:443").unwrap(); - let mut socket = SslStream::connect(&ctx, s).unwrap(); + let mut socket = Ssl::new(&ctx.build()).unwrap().connect(s).unwrap(); socket.write_all(b"GET / HTTP/1.0\r\n\r\n").unwrap(); let mut result = vec![]; @@ -1086,6 +1022,172 @@ 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(); - ctx.add_extra_chain_cert(&cert).unwrap(); + let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); + ctx.add_extra_chain_cert(cert).unwrap(); +} + +#[test] +#[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] +fn verify_valid_hostname() { + let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); + ctx.set_default_verify_paths().unwrap(); + ctx.set_verify(SSL_VERIFY_PEER); + + let mut ssl = Ssl::new(&ctx.build()).unwrap(); + ssl.param_mut().set_hostflags(X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); + ssl.param_mut().set_host("google.com").unwrap(); + + let s = TcpStream::connect("google.com:443").unwrap(); + let mut socket = ssl.connect(s).unwrap(); + + socket.write_all(b"GET / HTTP/1.0\r\n\r\n").unwrap(); + let mut result = vec![]; + socket.read_to_end(&mut result).unwrap(); + + println!("{}", String::from_utf8_lossy(&result)); + assert!(result.starts_with(b"HTTP/1.0")); + assert!(result.ends_with(b"\r\n") || result.ends_with(b"")); +} + +#[test] +#[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] +fn verify_invalid_hostname() { + let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); + ctx.set_default_verify_paths().unwrap(); + ctx.set_verify(SSL_VERIFY_PEER); + + let mut ssl = Ssl::new(&ctx.build()).unwrap(); + ssl.param_mut().set_hostflags(X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); + ssl.param_mut().set_host("foobar.com").unwrap(); + + let s = TcpStream::connect("google.com:443").unwrap(); + assert!(ssl.connect(s).is_err()); +} + +#[test] +fn connector_valid_hostname() { + let connector = SslConnectorBuilder::new(SslMethod::tls()).unwrap().build(); + + let s = TcpStream::connect("google.com:443").unwrap(); + let mut socket = connector.connect("google.com", s).unwrap(); + + socket.write_all(b"GET / HTTP/1.0\r\n\r\n").unwrap(); + let mut result = vec![]; + socket.read_to_end(&mut result).unwrap(); + + println!("{}", String::from_utf8_lossy(&result)); + assert!(result.starts_with(b"HTTP/1.0")); + assert!(result.ends_with(b"\r\n") || result.ends_with(b"")); +} + +#[test] +fn connector_invalid_hostname() { + let connector = SslConnectorBuilder::new(SslMethod::tls()).unwrap().build(); + + let s = TcpStream::connect("google.com:443").unwrap(); + assert!(connector.connect("foobar.com", s).is_err()); +} + +#[test] +fn connector_client_server_mozilla_intermediate() { + let listener = TcpListener::bind("127.0.0.1:0").unwrap(); + let port = listener.local_addr().unwrap().port(); + + let t = thread::spawn(move || { + let key = PKey::private_key_from_pem(KEY).unwrap(); + let cert = X509::from_pem(CERT).unwrap(); + let connector = + SslAcceptorBuilder::mozilla_intermediate(SslMethod::tls(), &key, &cert, None::) + .unwrap() + .build(); + let stream = listener.accept().unwrap().0; + let mut stream = connector.accept(stream).unwrap(); + + stream.write_all(b"hello").unwrap(); + }); + + let mut connector = SslConnectorBuilder::new(SslMethod::tls()).unwrap(); + connector.builder_mut().set_ca_file("test/root-ca.pem").unwrap(); + let connector = connector.build(); + + let stream = TcpStream::connect(("127.0.0.1", port)).unwrap(); + let mut stream = connector.connect("foobar.com", stream).unwrap(); + + let mut buf = [0; 5]; + stream.read_exact(&mut buf).unwrap(); + assert_eq!(b"hello", &buf); + + t.join().unwrap(); +} + +#[test] +fn connector_client_server_mozilla_modern() { + let listener = TcpListener::bind("127.0.0.1:0").unwrap(); + let port = listener.local_addr().unwrap().port(); + + let t = thread::spawn(move || { + let key = PKey::private_key_from_pem(KEY).unwrap(); + let cert = X509::from_pem(CERT).unwrap(); + let connector = + SslAcceptorBuilder::mozilla_modern(SslMethod::tls(), &key, &cert, None::) + .unwrap() + .build(); + let stream = listener.accept().unwrap().0; + let mut stream = connector.accept(stream).unwrap(); + + stream.write_all(b"hello").unwrap(); + }); + + let mut connector = SslConnectorBuilder::new(SslMethod::tls()).unwrap(); + connector.builder_mut().set_ca_file("test/root-ca.pem").unwrap(); + let connector = connector.build(); + + let stream = TcpStream::connect(("127.0.0.1", port)).unwrap(); + let mut stream = connector.connect("foobar.com", stream).unwrap(); + + let mut buf = [0; 5]; + stream.read_exact(&mut buf).unwrap(); + assert_eq!(b"hello", &buf); + + t.join().unwrap(); +} + +#[test] +fn shutdown() { + let listener = TcpListener::bind("127.0.0.1:0").unwrap(); + let port = listener.local_addr().unwrap().port(); + + thread::spawn(move || { + let stream = listener.accept().unwrap().0; + let mut ctx = SslContext::builder(SslMethod::tls()).unwrap(); + ctx.set_certificate_file(&Path::new("test/cert.pem"), X509_FILETYPE_PEM).unwrap(); + ctx.set_private_key_file(&Path::new("test/key.pem"), X509_FILETYPE_PEM).unwrap(); + let ssl = Ssl::new(&ctx.build()).unwrap(); + let mut stream = ssl.accept(stream).unwrap(); + + stream.write_all(b"hello").unwrap(); + let mut buf = [0; 1]; + assert_eq!(stream.read(&mut buf).unwrap(), 0); + assert_eq!(stream.shutdown().unwrap(), ShutdownResult::Received); + }); + + let stream = TcpStream::connect(("127.0.0.1", port)).unwrap(); + let ctx = SslContext::builder(SslMethod::tls()).unwrap(); + let ssl = Ssl::new(&ctx.build()).unwrap(); + let mut stream = ssl.connect(stream).unwrap(); + + let mut buf = [0; 5]; + stream.read_exact(&mut buf).unwrap(); + assert_eq!(b"hello", &buf); + + assert_eq!(stream.shutdown().unwrap(), ShutdownResult::Sent); + assert_eq!(stream.shutdown().unwrap(), ShutdownResult::Received); +} + +fn _check_kinds() { + fn is_send() {} + fn is_sync() {} + + is_send::>(); + is_sync::>(); } diff --git a/openssl/src/stack.rs b/openssl/src/stack.rs new file mode 100644 index 00000000..dae42ca8 --- /dev/null +++ b/openssl/src/stack.rs @@ -0,0 +1,331 @@ +use std::ops::{Deref, DerefMut, Index, IndexMut}; +use std::iter; +use std::borrow::Borrow; +use std::convert::AsRef; +use std::marker::PhantomData; +use libc::c_int; +use std::mem; + +use types::{OpenSslType, OpenSslTypeRef}; +use util::Opaque; + +#[cfg(ossl10x)] +use ffi::{sk_pop as OPENSSL_sk_pop, sk_free as OPENSSL_sk_free, sk_num as OPENSSL_sk_num, + sk_value as OPENSSL_sk_value, _STACK as OPENSSL_STACK}; +#[cfg(ossl110)] +use ffi::{OPENSSL_sk_pop, OPENSSL_sk_free, OPENSSL_sk_num, OPENSSL_sk_value, OPENSSL_STACK}; + +/// Trait implemented by types which can be placed in a stack. +/// +/// Like `OpenSslType`, it should not be implemented for any type outside +/// of this crate. +pub trait Stackable: OpenSslType { + /// The C stack type for this element. + /// + /// Generally called `stack_st_{ELEMENT_TYPE}`, normally hidden by the + /// `STACK_OF(ELEMENT_TYPE)` macro in the OpenSSL API. + type StackType; +} + +/// An owned stack of `T`. +pub struct Stack(*mut T::StackType); + +impl Stack { + /// Return a new Stack, taking ownership of the handle + pub unsafe fn from_ptr(stack: *mut T::StackType) -> Stack { + Stack(stack) + } +} + +impl Drop for Stack { + fn drop(&mut self) { + unsafe { + while let Some(_) = self.pop() {} + OPENSSL_sk_free(self.0 as *mut _); + } + } +} + +impl iter::IntoIterator for Stack { + type IntoIter = IntoIter; + type Item = T; + + fn into_iter(self) -> IntoIter { + let it = IntoIter { + stack: self.0, + idx: 0, + }; + mem::forget(self); + it + } +} + +impl AsRef> for Stack { + fn as_ref(&self) -> &StackRef { + &*self + } +} + +impl Borrow> for Stack { + fn borrow(&self) -> &StackRef { + &*self + } +} + +impl OpenSslType for Stack { + type CType = T::StackType; + type Ref = StackRef; + + unsafe fn from_ptr(ptr: *mut T::StackType) -> Stack { + Stack(ptr) + } +} + +impl Deref for Stack { + type Target = StackRef; + + fn deref(&self) -> &StackRef { + unsafe { StackRef::from_ptr(self.0) } + } +} + +impl DerefMut for Stack { + fn deref_mut(&mut self) -> &mut StackRef { + unsafe { StackRef::from_ptr_mut(self.0) } + } +} + +pub struct IntoIter { + stack: *mut T::StackType, + idx: c_int, +} + +impl IntoIter { + fn stack_len(&self) -> c_int { + unsafe { OPENSSL_sk_num(self.stack as *mut _) } + } +} + +impl Drop for IntoIter { + fn drop(&mut self) { + unsafe { + while let Some(_) = self.next() {} + OPENSSL_sk_free(self.stack as *mut _); + } + } +} + +impl Iterator for IntoIter { + type Item = T; + + fn next(&mut self) -> Option { + unsafe { + if self.idx == self.stack_len() { + None + } else { + let ptr = OPENSSL_sk_value(self.stack as *mut _, self.idx); + self.idx += 1; + Some(T::from_ptr(ptr as *mut _)) + } + } + } + + fn size_hint(&self) -> (usize, Option) { + let size = (self.stack_len() - self.idx) as usize; + (size, Some(size)) + } +} + +impl ExactSizeIterator for IntoIter {} + +pub struct StackRef(Opaque, PhantomData); + +impl OpenSslTypeRef for StackRef { + type CType = T::StackType; +} + +impl StackRef { + fn as_stack(&self) -> *mut OPENSSL_STACK { + self.as_ptr() as *mut _ + } + + /// Returns the number of items in the stack + pub fn len(&self) -> usize { + unsafe { OPENSSL_sk_num(self.as_stack()) as usize } + } + + pub fn iter(&self) -> Iter { + // Unfortunately we can't simply convert the stack into a + // slice and use that because OpenSSL 1.1.0 doesn't directly + // expose the stack data (we have to use `OPENSSL_sk_value` + // instead). We have to rewrite the entire iteration framework + // instead. + + Iter { + stack: self, + pos: 0, + } + } + + pub fn iter_mut(&mut self) -> IterMut { + IterMut { + stack: self, + pos: 0, + } + } + + /// Returns a reference to the element at the given index in the + /// stack or `None` if the index is out of bounds + pub fn get(&self, idx: usize) -> Option<&T::Ref> { + unsafe { + if idx >= self.len() { + return None; + } + + Some(T::Ref::from_ptr(self._get(idx))) + } + } + + /// Returns a mutable reference to the element at the given index in the + /// stack or `None` if the index is out of bounds + pub fn get_mut(&mut self, idx: usize) -> Option<&mut T::Ref> { + unsafe { + if idx >= self.len() { + return None; + } + + Some(T::Ref::from_ptr_mut(self._get(idx))) + } + } + + /// Removes the last element from the stack and returns it. + pub fn pop(&mut self) -> Option { + unsafe { + let ptr = OPENSSL_sk_pop(self.as_stack()); + if ptr.is_null() { + None + } else { + Some(T::from_ptr(ptr as *mut _)) + } + } + } + + unsafe fn _get(&self, idx: usize) -> *mut T::CType { + OPENSSL_sk_value(self.as_stack(), idx as c_int) as *mut _ + } +} + +impl Index for StackRef { + type Output = T::Ref; + + fn index(&self, index: usize) -> &T::Ref { + self.get(index).unwrap() + } +} + +impl IndexMut for StackRef { + fn index_mut(&mut self, index: usize) -> &mut T::Ref { + self.get_mut(index).unwrap() + } +} + +impl<'a, T: Stackable> iter::IntoIterator for &'a StackRef { + type Item = &'a T::Ref; + type IntoIter = Iter<'a, T>; + + fn into_iter(self) -> Iter<'a, T> { + self.iter() + } +} + +impl<'a, T: Stackable> iter::IntoIterator for &'a mut StackRef { + type Item = &'a mut T::Ref; + type IntoIter = IterMut<'a, T>; + + fn into_iter(self) -> IterMut<'a, T> { + self.iter_mut() + } +} + +impl<'a, T: Stackable> iter::IntoIterator for &'a Stack { + type Item = &'a T::Ref; + type IntoIter = Iter<'a, T>; + + fn into_iter(self) -> Iter<'a, T> { + self.iter() + } +} + +impl<'a, T: Stackable> iter::IntoIterator for &'a mut Stack { + type Item = &'a mut T::Ref; + type IntoIter = IterMut<'a, T>; + + fn into_iter(self) -> IterMut<'a, T> { + self.iter_mut() + } +} + +/// An iterator over the stack's contents. +pub struct Iter<'a, T: Stackable> + where T: 'a +{ + stack: &'a StackRef, + pos: usize, +} + +impl<'a, T: Stackable> iter::Iterator for Iter<'a, T> { + type Item = &'a T::Ref; + + fn next(&mut self) -> Option<&'a T::Ref> { + let n = self.stack.get(self.pos); + + if n.is_some() { + self.pos += 1; + } + + n + } + + fn size_hint(&self) -> (usize, Option) { + let rem = self.stack.len() - self.pos; + + (rem, Some(rem)) + } +} + +impl<'a, T: Stackable> iter::ExactSizeIterator for Iter<'a, T> {} + +/// A mutable iterator over the stack's contents. +pub struct IterMut<'a, T: Stackable + 'a> { + stack: &'a mut StackRef, + pos: usize, +} + +impl<'a, T: Stackable> iter::Iterator for IterMut<'a, T> { + type Item = &'a mut T::Ref; + + fn next(&mut self) -> Option<&'a mut T::Ref> { + if self.pos >= self.stack.len() { + None + } else { + // Rust won't allow us to get a mutable reference into + // `stack` in this situation since it can't statically + // guarantee that we won't return several references to + // the same object, so we have to use unsafe code for + // mutable iterators. + let n = unsafe { Some(T::Ref::from_ptr_mut(self.stack._get(self.pos))) }; + + self.pos += 1; + + n + } + } + + fn size_hint(&self) -> (usize, Option) { + let rem = self.stack.len() - self.pos; + + (rem, Some(rem)) + } +} + +impl<'a, T: Stackable> iter::ExactSizeIterator for IterMut<'a, T> {} diff --git a/openssl/src/crypto/symm.rs b/openssl/src/symm.rs similarity index 68% rename from openssl/src/crypto/symm.rs rename to openssl/src/symm.rs index 93764e4d..d4b15f28 100644 --- a/openssl/src/crypto/symm.rs +++ b/openssl/src/symm.rs @@ -3,6 +3,7 @@ use std::ptr; use libc::c_int; use ffi; +use {cvt, cvt_p}; use error::ErrorStack; #[derive(Copy, Clone)] @@ -11,90 +12,105 @@ pub enum Mode { Decrypt, } -#[allow(non_camel_case_types)] #[derive(Copy, Clone)] -pub enum Type { - AES_128_ECB, - AES_128_CBC, - /// Requires the `aes_xts` feature - #[cfg(feature = "aes_xts")] - AES_128_XTS, - #[cfg(feature = "aes_ctr")] - AES_128_CTR, - // AES_128_GCM, - AES_128_CFB1, - AES_128_CFB128, - AES_128_CFB8, +pub struct Cipher(*const ffi::EVP_CIPHER); - AES_256_ECB, - AES_256_CBC, - /// Requires the `aes_xts` feature - #[cfg(feature = "aes_xts")] - AES_256_XTS, - #[cfg(feature = "aes_ctr")] - AES_256_CTR, - // AES_256_GCM, - AES_256_CFB1, - AES_256_CFB128, - AES_256_CFB8, +impl Cipher { + pub fn aes_128_ecb() -> Cipher { + unsafe { Cipher(ffi::EVP_aes_128_ecb()) } + } - DES_CBC, - DES_ECB, + pub fn aes_128_cbc() -> Cipher { + unsafe { Cipher(ffi::EVP_aes_128_cbc()) } + } - RC4_128, -} + pub fn aes_128_xts() -> Cipher { + unsafe { Cipher(ffi::EVP_aes_128_xts()) } + } + + pub fn aes_128_ctr() -> Cipher { + unsafe { Cipher(ffi::EVP_aes_128_ctr()) } + } + + pub fn aes_128_cfb1() -> Cipher { + unsafe { Cipher(ffi::EVP_aes_128_cfb1()) } + } + + pub fn aes_128_cfb128() -> Cipher { + unsafe { Cipher(ffi::EVP_aes_128_cfb128()) } + } + + pub fn aes_128_cfb8() -> Cipher { + unsafe { Cipher(ffi::EVP_aes_128_cfb8()) } + } + + pub fn aes_128_gcm() -> Cipher { + unsafe { Cipher(ffi::EVP_aes_128_gcm()) } + } + + pub fn aes_256_ecb() -> Cipher { + unsafe { Cipher(ffi::EVP_aes_256_ecb()) } + } + + pub fn aes_256_cbc() -> Cipher { + unsafe { Cipher(ffi::EVP_aes_256_cbc()) } + } + + pub fn aes_256_xts() -> Cipher { + unsafe { Cipher(ffi::EVP_aes_256_xts()) } + } + + pub fn aes_256_ctr() -> Cipher { + unsafe { Cipher(ffi::EVP_aes_256_ctr()) } + } + + pub fn aes_256_cfb1() -> Cipher { + unsafe { Cipher(ffi::EVP_aes_256_cfb1()) } + } + + pub fn aes_256_cfb128() -> Cipher { + unsafe { Cipher(ffi::EVP_aes_256_cfb128()) } + } + + pub fn aes_256_cfb8() -> Cipher { + unsafe { Cipher(ffi::EVP_aes_256_cfb8()) } + } + + pub fn aes_256_gcm() -> Cipher { + unsafe { Cipher(ffi::EVP_aes_256_gcm()) } + } + + pub fn des_cbc() -> Cipher { + unsafe { Cipher(ffi::EVP_des_cbc()) } + } + + pub fn des_ecb() -> Cipher { + unsafe { Cipher(ffi::EVP_des_ecb()) } + } + + pub fn rc4() -> Cipher { + unsafe { Cipher(ffi::EVP_rc4()) } + } + + pub unsafe fn from_ptr(ptr: *const ffi::EVP_CIPHER) -> Cipher { + Cipher(ptr) + } -impl Type { pub fn as_ptr(&self) -> *const ffi::EVP_CIPHER { - unsafe { - match *self { - Type::AES_128_ECB => ffi::EVP_aes_128_ecb(), - Type::AES_128_CBC => ffi::EVP_aes_128_cbc(), - #[cfg(feature = "aes_xts")] - Type::AES_128_XTS => ffi::EVP_aes_128_xts(), - #[cfg(feature = "aes_ctr")] - Type::AES_128_CTR => ffi::EVP_aes_128_ctr(), - // AES_128_GCM => (EVP_aes_128_gcm(), 16, 16), - Type::AES_128_CFB1 => ffi::EVP_aes_128_cfb1(), - Type::AES_128_CFB128 => ffi::EVP_aes_128_cfb128(), - Type::AES_128_CFB8 => ffi::EVP_aes_128_cfb8(), - - Type::AES_256_ECB => ffi::EVP_aes_256_ecb(), - Type::AES_256_CBC => ffi::EVP_aes_256_cbc(), - #[cfg(feature = "aes_xts")] - Type::AES_256_XTS => ffi::EVP_aes_256_xts(), - #[cfg(feature = "aes_ctr")] - Type::AES_256_CTR => ffi::EVP_aes_256_ctr(), - // AES_256_GCM => (EVP_aes_256_gcm(), 32, 16), - Type::AES_256_CFB1 => ffi::EVP_aes_256_cfb1(), - Type::AES_256_CFB128 => ffi::EVP_aes_256_cfb128(), - Type::AES_256_CFB8 => ffi::EVP_aes_256_cfb8(), - - Type::DES_CBC => ffi::EVP_des_cbc(), - Type::DES_ECB => ffi::EVP_des_ecb(), - - Type::RC4_128 => ffi::EVP_rc4(), - } - } + self.0 } /// 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 - } + unsafe { EVP_CIPHER_key_length(self.0) as usize } } /// Returns the length of the IV used with this cipher, or `None` if the /// cipher does not use an IV. pub fn iv_len(&self) -> Option { unsafe { - let len = ffi::EVP_CIPHER_iv_length(self.as_ptr()) as usize; - if len == 0 { - None - } else { - Some(len) - } + let len = EVP_CIPHER_iv_length(self.0) as usize; + if len == 0 { None } else { Some(len) } } } @@ -104,9 +120,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 - } + unsafe { EVP_CIPHER_block_size(self.0) as usize } } } @@ -122,12 +136,16 @@ impl Crypter { /// # Panics /// /// Panics if an IV is required by the cipher but not provided, or if the - /// IV's length does not match the expected length (see `Type::iv_len`). - pub fn new(t: Type, mode: Mode, key: &[u8], iv: Option<&[u8]>) -> Result { + /// IV's length does not match the expected length (see `Cipher::iv_len`). + pub fn new(t: Cipher, + mode: Mode, + key: &[u8], + iv: Option<&[u8]>) + -> Result { ffi::init(); unsafe { - let ctx = try_ssl_null!(ffi::EVP_CIPHER_CTX_new()); + let ctx = try!(cvt_p(ffi::EVP_CIPHER_CTX_new())); let crypter = Crypter { ctx: ctx, block_size: t.block_size(), @@ -138,15 +156,15 @@ impl Crypter { Mode::Decrypt => 0, }; - try_ssl!(ffi::EVP_CipherInit_ex(crypter.ctx, - t.as_ptr(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - mode)); + try!(cvt(ffi::EVP_CipherInit_ex(crypter.ctx, + t.as_ptr(), + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + mode))); assert!(key.len() <= c_int::max_value() as usize); - try_ssl!(ffi::EVP_CIPHER_CTX_set_key_length(crypter.ctx, key.len() as c_int)); + try!(cvt(ffi::EVP_CIPHER_CTX_set_key_length(crypter.ctx, key.len() as c_int))); let key = key.as_ptr() as *mut _; let iv = match (iv, t.iv_len()) { @@ -157,12 +175,12 @@ impl Crypter { (Some(_), None) | (None, None) => ptr::null_mut(), (None, Some(_)) => panic!("an IV is required for this cipher"), }; - try_ssl!(ffi::EVP_CipherInit_ex(crypter.ctx, + try!(cvt(ffi::EVP_CipherInit_ex(crypter.ctx, ptr::null(), ptr::null_mut(), key, iv, - mode)); + mode))); Ok(crypter) } @@ -173,7 +191,9 @@ impl Crypter { /// If padding is disabled, total amount of data encrypted/decrypted must /// be a multiple of the cipher's block size. pub fn pad(&mut self, padding: bool) { - unsafe { ffi::EVP_CIPHER_CTX_set_padding(self.ctx, padding as c_int); } + unsafe { + ffi::EVP_CIPHER_CTX_set_padding(self.ctx, padding as c_int); + } } /// Feeds data from `input` through the cipher, writing encrypted/decrypted @@ -185,7 +205,7 @@ impl Crypter { /// # Panics /// /// Panics if `output.len() < input.len() + block_size` where - /// `block_size` is the block size of the cipher (see `Type::block_size`), + /// `block_size` is the block size of the cipher (see `Cipher::block_size`), /// or if `output.len() > c_int::max_value()`. pub fn update(&mut self, input: &[u8], output: &mut [u8]) -> Result { unsafe { @@ -194,11 +214,11 @@ impl Crypter { let mut outl = output.len() as c_int; let inl = input.len() as c_int; - try_ssl!(ffi::EVP_CipherUpdate(self.ctx, + try!(cvt(ffi::EVP_CipherUpdate(self.ctx, output.as_mut_ptr(), &mut outl, input.as_ptr(), - inl)); + inl))); Ok(outl as usize) } @@ -219,7 +239,7 @@ impl Crypter { assert!(output.len() >= self.block_size); let mut outl = cmp::min(output.len(), c_int::max_value() as usize) as c_int; - try_ssl!(ffi::EVP_CipherFinal(self.ctx, output.as_mut_ptr(), &mut outl)); + try!(cvt(ffi::EVP_CipherFinal(self.ctx, output.as_mut_ptr(), &mut outl))); Ok(outl as usize) } @@ -238,7 +258,7 @@ impl Drop for Crypter { * Encrypts data, using the specified crypter type in encrypt mode with the * specified key and iv; returns the resulting (encrypted) data. */ -pub fn encrypt(t: Type, +pub fn encrypt(t: Cipher, key: &[u8], iv: Option<&[u8]>, data: &[u8]) @@ -250,7 +270,7 @@ pub fn encrypt(t: Type, * Decrypts data, using the specified crypter type in decrypt mode with the * specified key and iv; returns the resulting (decrypted) data. */ -pub fn decrypt(t: Type, +pub fn decrypt(t: Cipher, key: &[u8], iv: Option<&[u8]>, data: &[u8]) @@ -258,7 +278,7 @@ pub fn decrypt(t: Type, cipher(t, Mode::Decrypt, key, iv, data) } -fn cipher(t: Type, +fn cipher(t: Cipher, mode: Mode, key: &[u8], iv: Option<&[u8]>, @@ -272,6 +292,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}; @@ -288,23 +332,25 @@ mod tests { 0xaau8, 0xbbu8, 0xccu8, 0xddu8, 0xeeu8, 0xffu8]; let c0 = [0x8eu8, 0xa2u8, 0xb7u8, 0xcau8, 0x51u8, 0x67u8, 0x45u8, 0xbfu8, 0xeau8, 0xfcu8, 0x49u8, 0x90u8, 0x4bu8, 0x49u8, 0x60u8, 0x89u8]; - let mut c = super::Crypter::new(super::Type::AES_256_ECB, + let mut c = super::Crypter::new(super::Cipher::aes_256_ecb(), super::Mode::Encrypt, &k0, - None).unwrap(); + None) + .unwrap(); c.pad(false); - let mut r0 = vec![0; c0.len() + super::Type::AES_256_ECB.block_size()]; + let mut r0 = vec![0; c0.len() + super::Cipher::aes_256_ecb().block_size()]; let count = c.update(&p0, &mut r0).unwrap(); let rest = c.finalize(&mut r0[count..]).unwrap(); r0.truncate(count + rest); assert_eq!(r0.to_hex(), c0.to_hex()); - let mut c = super::Crypter::new(super::Type::AES_256_ECB, + let mut c = super::Crypter::new(super::Cipher::aes_256_ecb(), super::Mode::Decrypt, &k0, - None).unwrap(); + None) + .unwrap(); c.pad(false); - let mut p1 = vec![0; r0.len() + super::Type::AES_256_ECB.block_size()]; + let mut p1 = vec![0; r0.len() + super::Cipher::aes_256_ecb().block_size()]; let count = c.update(&r0, &mut p1).unwrap(); let rest = c.finalize(&mut p1[count..]).unwrap(); p1.truncate(count + rest); @@ -322,12 +368,13 @@ mod tests { let ciphered_data = [0x4a_u8, 0x2e_u8, 0xe5_u8, 0x6_u8, 0xbf_u8, 0xcf_u8, 0xf2_u8, 0xd7_u8, 0xea_u8, 0x2d_u8, 0xb1_u8, 0x85_u8, 0x6c_u8, 0x93_u8, 0x65_u8, 0x6f_u8]; - let mut cr = super::Crypter::new(super::Type::AES_256_CBC, + let mut cr = super::Crypter::new(super::Cipher::aes_256_cbc(), super::Mode::Decrypt, &data, - Some(&iv)).unwrap(); + Some(&iv)) + .unwrap(); cr.pad(false); - let mut unciphered_data = vec![0; data.len() + super::Type::AES_256_CBC.block_size()]; + let mut unciphered_data = vec![0; data.len() + super::Cipher::aes_256_cbc().block_size()]; let count = cr.update(&ciphered_data, &mut unciphered_data).unwrap(); let rest = cr.finalize(&mut unciphered_data[count..]).unwrap(); unciphered_data.truncate(count + rest); @@ -337,7 +384,7 @@ mod tests { assert_eq!(&unciphered_data, expected_unciphered_data); } - fn cipher_test(ciphertype: super::Type, pt: &str, ct: &str, key: &str, iv: &str) { + fn cipher_test(ciphertype: super::Cipher, pt: &str, ct: &str, key: &str, iv: &str) { use serialize::hex::ToHex; let pt = pt.from_hex().unwrap(); @@ -368,11 +415,10 @@ mod tests { let key = "97CD440324DA5FD1F7955C1C13B6B466"; let iv = ""; - cipher_test(super::Type::RC4_128, pt, ct, key, iv); + cipher_test(super::Cipher::rc4(), pt, ct, key, iv); } #[test] - #[cfg(feature = "aes_xts")] fn test_aes256_xts() { // Test case 174 from // http://csrc.nist.gov/groups/STM/cavp/documents/aes/XTSTestVectors.zip @@ -384,11 +430,10 @@ mod tests { 4180026ad640b74243b3133e7b9fae629403f6733423dae28"; let iv = "db200efb7eaaa737dbdf40babb68953f"; - cipher_test(super::Type::AES_256_XTS, pt, ct, key, iv); + cipher_test(super::Cipher::aes_256_xts(), pt, ct, key, iv); } #[test] - #[cfg(feature = "aes_ctr")] fn test_aes128_ctr() { let pt = "6BC1BEE22E409F96E93D7E117393172AAE2D8A571E03AC9C9EB76FAC45AF8E5130C81C46A35CE411\ @@ -398,20 +443,9 @@ mod tests { let key = "2B7E151628AED2A6ABF7158809CF4F3C"; let iv = "F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF"; - cipher_test(super::Type::AES_128_CTR, pt, ct, key, iv); + cipher_test(super::Cipher::aes_128_ctr(), pt, ct, key, iv); } - // #[test] - // fn test_aes128_gcm() { - // Test case 3 in GCM spec - // let pt = ~"d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255"; - // let ct = ~"42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f59854d5c2af327cd64a62cf35abd2ba6fab4"; - // let key = ~"feffe9928665731c6d6a8f9467308308"; - // let iv = ~"cafebabefacedbaddecaf888"; - // - // cipher_test(super::AES_128_GCM, pt, ct, key, iv); - // } - #[test] fn test_aes128_cfb1() { // Lifted from http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf @@ -421,7 +455,7 @@ mod tests { let key = "2b7e151628aed2a6abf7158809cf4f3c"; let iv = "000102030405060708090a0b0c0d0e0f"; - cipher_test(super::Type::AES_128_CFB1, pt, ct, key, iv); + cipher_test(super::Cipher::aes_128_cfb1(), pt, ct, key, iv); } #[test] @@ -432,7 +466,7 @@ mod tests { let key = "2b7e151628aed2a6abf7158809cf4f3c"; let iv = "000102030405060708090a0b0c0d0e0f"; - cipher_test(super::Type::AES_128_CFB128, pt, ct, key, iv); + cipher_test(super::Cipher::aes_128_cfb128(), pt, ct, key, iv); } #[test] @@ -443,7 +477,7 @@ mod tests { let key = "2b7e151628aed2a6abf7158809cf4f3c"; let iv = "000102030405060708090a0b0c0d0e0f"; - cipher_test(super::Type::AES_128_CFB8, pt, ct, key, iv); + cipher_test(super::Cipher::aes_128_cfb8(), pt, ct, key, iv); } #[test] @@ -454,7 +488,7 @@ mod tests { let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"; let iv = "000102030405060708090a0b0c0d0e0f"; - cipher_test(super::Type::AES_256_CFB1, pt, ct, key, iv); + cipher_test(super::Cipher::aes_256_cfb1(), pt, ct, key, iv); } #[test] @@ -465,7 +499,7 @@ mod tests { let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"; let iv = "000102030405060708090a0b0c0d0e0f"; - cipher_test(super::Type::AES_256_CFB128, pt, ct, key, iv); + cipher_test(super::Cipher::aes_256_cfb128(), pt, ct, key, iv); } #[test] @@ -476,7 +510,7 @@ mod tests { let key = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4"; let iv = "000102030405060708090a0b0c0d0e0f"; - cipher_test(super::Type::AES_256_CFB8, pt, ct, key, iv); + cipher_test(super::Cipher::aes_256_cfb8(), pt, ct, key, iv); } #[test] @@ -487,7 +521,7 @@ mod tests { let key = "7cb66337f3d3c0fe"; let iv = "0001020304050607"; - cipher_test(super::Type::DES_CBC, pt, ct, key, iv); + cipher_test(super::Cipher::des_cbc(), pt, ct, key, iv); } #[test] @@ -498,6 +532,6 @@ mod tests { let key = "7cb66337f3d3c0fe"; let iv = "0001020304050607"; - cipher_test(super::Type::DES_ECB, pt, ct, key, iv); + cipher_test(super::Cipher::des_ecb(), pt, ct, key, iv); } } diff --git a/openssl/src/types.rs b/openssl/src/types.rs new file mode 100644 index 00000000..2fadfd42 --- /dev/null +++ b/openssl/src/types.rs @@ -0,0 +1,40 @@ +//! Items used by other types. + +/// A type implemented by wrappers over OpenSSL types. +/// +/// This should not be implemented by anything outside of this crate; new methods may be added at +/// any time. +pub trait OpenSslType: Sized { + /// The raw C type. + type CType; + + /// The type representing a reference to this type. + type Ref: OpenSslTypeRef; + + /// Constructs an instance of this type from its raw type. + unsafe fn from_ptr(ptr: *mut Self::CType) -> Self; +} + +/// A trait implemented by types which reference borrowed OpenSSL types. +/// +/// This should not be implemented by anything outside of this crate; new methods may be added at +/// any time. +pub trait OpenSslTypeRef: Sized { + /// The raw C type. + type CType; + + /// Constructs a shared instance of this type from its raw type. + unsafe fn from_ptr<'a>(ptr: *mut Self::CType) -> &'a Self { + &*(ptr as *mut _) + } + + /// Constructs a mutable reference of this type from its raw type. + unsafe fn from_ptr_mut<'a>(ptr: *mut Self::CType) -> &'a mut Self { + &mut *(ptr as *mut _) + } + + /// Returns a raw pointer to the wrapped value. + fn as_ptr(&self) -> *mut Self::CType { + self as *const _ as *mut _ + } +} diff --git a/openssl/src/crypto/util.rs b/openssl/src/util.rs similarity index 52% rename from openssl/src/crypto/util.rs rename to openssl/src/util.rs index c11285f8..302bd316 100644 --- a/openssl/src/crypto/util.rs +++ b/openssl/src/util.rs @@ -1,7 +1,7 @@ use libc::{c_int, c_char, c_void}; - use std::any::Any; -use std::panic; +use std::cell::UnsafeCell; +use std::panic::{self, AssertUnwindSafe}; use std::slice; /// Wraps a user-supplied callback and a slot for panics thrown inside the callback (while FFI @@ -36,23 +36,32 @@ impl Drop for CallbackState { /// Password callback function, passed to private key loading functions. /// /// `cb_state` is expected to be a pointer to a `CallbackState`. -pub extern "C" fn invoke_passwd_cb(buf: *mut c_char, - size: c_int, - _rwflag: c_int, - cb_state: *mut c_void) - -> c_int - where F: FnOnce(&mut [c_char]) -> usize { - let result = panic::catch_unwind(|| { +pub unsafe extern "C" fn invoke_passwd_cb(buf: *mut c_char, + size: c_int, + _rwflag: c_int, + cb_state: *mut c_void) + -> c_int + where F: FnOnce(&mut [c_char]) -> usize +{ + let callback = &mut *(cb_state as *mut CallbackState); + + let result = panic::catch_unwind(AssertUnwindSafe(|| { // build a `i8` slice to pass to the user callback - let pass_slice = unsafe { slice::from_raw_parts_mut(buf, size as usize) }; - let callback = unsafe { &mut *(cb_state as *mut CallbackState) }; + let pass_slice = slice::from_raw_parts_mut(buf, size as usize); callback.cb.take().unwrap()(pass_slice) - }); + })); - if let Ok(len) = result { - return len as c_int; - } else { - return 0; + match result { + Ok(len) => len as c_int, + Err(err) => { + callback.panic = Some(err); + 0 + } } } + +/// This is intended to be used as the inner type for `FooRef` types converted from raw C pointers. +/// It has an `UnsafeCell` internally to inform the compiler about aliasability and doesn't +/// implement `Copy`, so it can't be dereferenced. +pub struct Opaque(UnsafeCell<()>); diff --git a/openssl/src/verify.rs b/openssl/src/verify.rs new file mode 100644 index 00000000..2f070fe5 --- /dev/null +++ b/openssl/src/verify.rs @@ -0,0 +1,39 @@ +use libc::c_uint; +use ffi; + +use cvt; +use error::ErrorStack; +use types::OpenSslTypeRef; + +bitflags! { + pub flags X509CheckFlags: c_uint { + const X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT = ffi::X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT, + const X509_CHECK_FLAG_NO_WILDCARDS = ffi::X509_CHECK_FLAG_NO_WILDCARDS, + const X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS = ffi::X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS, + const X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS = ffi::X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS, + const X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS + = ffi::X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS, + /// Requires the `v110` feature and OpenSSL 1.1.0. + #[cfg(all(feature = "v110", ossl110))] + const X509_CHECK_FLAG_NEVER_CHECK_SUBJECT = ffi::X509_CHECK_FLAG_NEVER_CHECK_SUBJECT, + } +} + +type_!(X509VerifyParam, X509VerifyParamRef, ffi::X509_VERIFY_PARAM, ffi::X509_VERIFY_PARAM_free); + +impl X509VerifyParamRef { + pub fn set_hostflags(&mut self, hostflags: X509CheckFlags) { + unsafe { + ffi::X509_VERIFY_PARAM_set_hostflags(self.as_ptr(), hostflags.bits); + } + } + + pub fn set_host(&mut self, host: &str) -> Result<(), ErrorStack> { + unsafe { + cvt(ffi::X509_VERIFY_PARAM_set1_host(self.as_ptr(), + host.as_ptr() as *const _, + host.len())) + .map(|_| ()) + } + } +} diff --git a/openssl/src/version.rs b/openssl/src/version.rs index 0e9f61d8..d7db39a7 100644 --- a/openssl/src/version.rs +++ b/openssl/src/version.rs @@ -11,9 +11,21 @@ // 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 +51,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 diff --git a/openssl/src/x509/extension.rs b/openssl/src/x509/extension.rs index 99ef62c1..398bbb3e 100644 --- a/openssl/src/x509/extension.rs +++ b/openssl/src/x509/extension.rs @@ -1,6 +1,6 @@ use std::fmt; -use nid::Nid; +use nid::{self, Nid}; /// Type-only version of the `Extension` enum. /// @@ -36,10 +36,10 @@ pub enum Extension { /// /// ``` /// use openssl::x509::extension::Extension::*; - /// use openssl::nid::Nid; + /// use openssl::nid; /// /// # let generator = openssl::x509::X509Generator::new(); - /// generator.add_extension(OtherNid(Nid::BasicConstraints,"critical,CA:TRUE".to_owned())); + /// generator.add_extension(OtherNid(nid::BASIC_CONSTRAINTS,"critical,CA:TRUE".to_owned())); /// ``` OtherNid(Nid, String), /// Arbitrary extensions by OID string. See `man ASN1_generate_nconf` for value syntax. @@ -71,10 +71,10 @@ impl Extension { impl ExtensionType { pub fn get_nid(&self) -> Option { match self { - &ExtensionType::KeyUsage => Some(Nid::KeyUsage), - &ExtensionType::ExtKeyUsage => Some(Nid::ExtendedKeyUsage), - &ExtensionType::SubjectAltName => Some(Nid::SubjectAltName), - &ExtensionType::IssuerAltName => Some(Nid::IssuerAltName), + &ExtensionType::KeyUsage => Some(nid::KEY_USAGE), + &ExtensionType::ExtKeyUsage => Some(nid::EXT_KEY_USAGE), + &ExtensionType::SubjectAltName => Some(nid::SUBJECT_ALT_NAME), + &ExtensionType::IssuerAltName => Some(nid::ISSUER_ALT_NAME), &ExtensionType::OtherNid(nid) => Some(nid), &ExtensionType::OtherStr(_) => None, } diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index f5369447..eb517f80 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -1,100 +1,66 @@ -use libc::{c_char, c_int, c_long, c_ulong, c_void}; +use libc::{c_char, c_int, c_long, c_ulong}; +use std::borrow::Borrow; use std::cmp; -use std::ffi::CString; +use std::collections::HashMap; +use std::error::Error; +use std::ffi::{CStr, CString}; +use std::fmt; use std::mem; use std::ptr; -use std::ops::Deref; -use std::fmt; -use std::str; use std::slice; -use std::collections::HashMap; -use std::marker::PhantomData; - -use HashTypeInternals; -use asn1::Asn1Time; -#[cfg(feature = "x509_expiry")] -use asn1::Asn1TimeRef; +use std::str; +use {cvt, cvt_p}; +use asn1::{Asn1StringRef, Asn1Time, Asn1TimeRef}; use bio::{MemBio, MemBioSlice}; -use crypto::hash; -use crypto::hash::Type as HashType; -use crypto::pkey::PKey; -use crypto::rand::rand_bytes; +use hash::MessageDigest; +use pkey::{PKey, PKeyRef}; +use rand::rand_bytes; +use error::ErrorStack; use ffi; use nid::Nid; -use error::ErrorStack; +use types::{OpenSslType, OpenSslTypeRef}; +use stack::{Stack, StackRef, Stackable}; + +#[cfg(ossl10x)] +use ffi::{X509_set_notBefore, X509_set_notAfter, ASN1_STRING_data, X509_STORE_CTX_get_chain}; +#[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, + X509_STORE_CTX_get0_chain as X509_STORE_CTX_get_chain}; + +#[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] +pub mod verify; + +use x509::extension::{ExtensionType, Extension}; pub mod extension; -use self::extension::{ExtensionType, Extension}; - #[cfg(test)] mod tests; -pub struct SslString(&'static str); +pub struct X509FileType(c_int); -impl<'s> Drop for SslString { - fn drop(&mut self) { - unsafe { - ffi::CRYPTO_free(self.0.as_ptr() as *mut c_void); - } - } -} - -impl Deref for SslString { - type Target = str; - - fn deref(&self) -> &str { +impl X509FileType { + pub fn as_raw(&self) -> c_int { self.0 } } -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); - SslString(str::from_utf8_unchecked(slice)) - } -} +pub const X509_FILETYPE_PEM: X509FileType = X509FileType(ffi::X509_FILETYPE_PEM); +pub const X509_FILETYPE_ASN1: X509FileType = X509FileType(ffi::X509_FILETYPE_ASN1); +pub const X509_FILETYPE_DEFAULT: X509FileType = X509FileType(ffi::X509_FILETYPE_DEFAULT); -impl fmt::Display for SslString { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(self.0, f) - } -} +type_!(X509StoreContext, X509StoreContextRef, ffi::X509_STORE_CTX, ffi::X509_STORE_CTX_free); -impl fmt::Debug for SslString { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(self.0, f) - } -} - -#[derive(Copy, Clone)] -#[repr(i32)] -pub enum X509FileType { - PEM = ffi::X509_FILETYPE_PEM, - ASN1 = ffi::X509_FILETYPE_ASN1, - Default = ffi::X509_FILETYPE_DEFAULT, -} - -#[allow(missing_copy_implementations)] -pub struct X509StoreContext { - ctx: *mut ffi::X509_STORE_CTX, -} - -impl X509StoreContext { - pub fn new(ctx: *mut ffi::X509_STORE_CTX) -> X509StoreContext { - X509StoreContext { ctx: ctx } +impl X509StoreContextRef { + pub fn error(&self) -> Option { + unsafe { X509VerifyError::from_raw(ffi::X509_STORE_CTX_get_error(self.as_ptr()) as c_long) } } - pub fn error(&self) -> Option { - let err = unsafe { ffi::X509_STORE_CTX_get_error(self.ctx) }; - X509ValidationError::from_raw(err) - } - - pub fn current_cert<'a>(&'a self) -> Option> { + pub fn current_cert(&self) -> Option<&X509Ref> { unsafe { - let ptr = ffi::X509_STORE_CTX_get_current_cert(self.ctx); - + let ptr = ffi::X509_STORE_CTX_get_current_cert(self.as_ptr()); if ptr.is_null() { None } else { @@ -104,7 +70,19 @@ impl X509StoreContext { } pub fn error_depth(&self) -> u32 { - unsafe { ffi::X509_STORE_CTX_get_error_depth(self.ctx) as u32 } + unsafe { ffi::X509_STORE_CTX_get_error_depth(self.as_ptr()) as u32 } + } + + pub fn chain(&self) -> Option<&StackRef> { + unsafe { + let chain = X509_STORE_CTX_get_chain(self.as_ptr()); + + if chain.is_null() { + return None; + } + + Some(StackRef::from_ptr(chain)) + } } } @@ -114,19 +92,19 @@ impl X509StoreContext { /// # Example /// /// ``` -/// use openssl::crypto::hash::Type; -/// use openssl::crypto::pkey::PKey; -/// use openssl::crypto::rsa::RSA; +/// use openssl::hash::MessageDigest; +/// use openssl::pkey::PKey; +/// use openssl::rsa::Rsa; /// use openssl::x509::X509Generator; /// use openssl::x509::extension::{Extension, KeyUsageOption}; /// -/// let rsa = RSA::generate(2048).unwrap(); +/// let rsa = Rsa::generate(2048).unwrap(); /// let pkey = PKey::from_rsa(rsa).unwrap(); /// /// let gen = X509Generator::new() /// .set_valid_period(365*2) /// .add_name("CN".to_owned(), "SuperMegaCorp Inc.".to_owned()) -/// .set_sign_hash(Type::SHA256) +/// .set_sign_hash(MessageDigest::sha256()) /// .add_extension(Extension::KeyUsage(vec![KeyUsageOption::DigitalSignature])); /// /// let cert = gen.sign(&pkey).unwrap(); @@ -137,7 +115,7 @@ pub struct X509Generator { days: u32, names: Vec<(String, String)>, extensions: Extensions, - hash_type: HashType, + hash_type: MessageDigest, } impl X509Generator { @@ -153,7 +131,7 @@ impl X509Generator { days: 365, names: vec![], extensions: Extensions::new(), - hash_type: HashType::SHA1, + hash_type: MessageDigest::sha1(), } } @@ -224,7 +202,7 @@ impl X509Generator { self } - pub fn set_sign_hash(mut self, hash_type: hash::Type) -> X509Generator { + pub fn set_sign_hash(mut self, hash_type: MessageDigest) -> X509Generator { self.hash_type = hash_type; self } @@ -239,25 +217,25 @@ impl X509Generator { let value = CString::new(value.as_bytes()).unwrap(); let ext = match exttype.get_nid() { Some(nid) => { - ffi::X509V3_EXT_conf_nid(ptr::null_mut(), - mem::transmute(&ctx), - nid as c_int, - value.as_ptr() as *mut c_char) + try!(cvt_p(ffi::X509V3_EXT_nconf_nid(ptr::null_mut(), + &mut ctx, + nid.as_raw(), + value.as_ptr() as *mut c_char))) } None => { let name = CString::new(exttype.get_name().unwrap().as_bytes()).unwrap(); - ffi::X509V3_EXT_conf(ptr::null_mut(), - mem::transmute(&ctx), - name.as_ptr() as *mut c_char, - value.as_ptr() as *mut c_char) + try!(cvt_p(ffi::X509V3_EXT_nconf(ptr::null_mut(), + &mut ctx, + name.as_ptr() as *mut c_char, + value.as_ptr() as *mut c_char))) } }; - let mut success = false; - if ext != ptr::null_mut() { - success = ffi::X509_add_ext(x509, ext, -1) != 0; + if ffi::X509_add_ext(x509, ext, -1) != 1 { ffi::X509_EXTENSION_free(ext); + Err(ErrorStack::get()) + } else { + Ok(()) } - lift_ssl_if!(!success) } } @@ -266,17 +244,18 @@ impl X509Generator { value: &str) -> Result<(), ErrorStack> { let value_len = value.len() as c_int; - lift_ssl!(unsafe { + unsafe { let key = CString::new(key.as_bytes()).unwrap(); let value = CString::new(value.as_bytes()).unwrap(); - ffi::X509_NAME_add_entry_by_txt(name, - key.as_ptr() as *const _, - ffi::MBSTRING_UTF8, - value.as_ptr() as *const _, - value_len, - -1, - 0) - }) + cvt(ffi::X509_NAME_add_entry_by_txt(name, + key.as_ptr() as *const _, + ffi::MBSTRING_UTF8, + value.as_ptr() as *const _, + value_len, + -1, + 0)) + .map(|_| ()) + } } fn random_serial() -> Result { @@ -296,32 +275,30 @@ impl X509Generator { } /// Sets the certificate public-key, then self-sign and return it - /// Note: That the bit-length of the private key is used (set_bitlength is ignored) - pub fn sign(&self, p_key: &PKey) -> Result { + pub fn sign(&self, p_key: &PKeyRef) -> Result { ffi::init(); unsafe { - let x509 = try_ssl_null!(ffi::X509_new()); - let x509 = X509::from_ptr(x509); + let x509 = X509::from_ptr(try!(cvt_p(ffi::X509_new()))); - try_ssl!(ffi::X509_set_version(x509.as_ptr(), 2)); - try_ssl!(ffi::ASN1_INTEGER_set(ffi::X509_get_serialNumber(x509.as_ptr()), - try!(X509Generator::random_serial()))); + try!(cvt(ffi::X509_set_version(x509.as_ptr(), 2))); + try!(cvt(ffi::ASN1_INTEGER_set(ffi::X509_get_serialNumber(x509.as_ptr()), + try!(X509Generator::random_serial())))); 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!(cvt(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!(cvt(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); - try_ssl!(ffi::X509_set_pubkey(x509.as_ptr(), p_key.as_ptr())); + try!(cvt(ffi::X509_set_pubkey(x509.as_ptr(), p_key.as_ptr()))); - let name = try_ssl_null!(ffi::X509_get_subject_name(x509.as_ptr())); + let name = try!(cvt_p(ffi::X509_get_subject_name(x509.as_ptr()))); let default = [("CN", "rust-openssl")]; let default_iter = &mut default.iter().map(|&(k, v)| (k, v)); @@ -335,7 +312,7 @@ impl X509Generator { for (key, val) in iter { try!(X509Generator::add_name_internal(name, &key, &val)); } - try_ssl!(ffi::X509_set_issuer_name(x509.as_ptr(), name)); + try!(cvt(ffi::X509_set_issuer_name(x509.as_ptr(), name))); for (exttype, ext) in self.extensions.iter() { try!(X509Generator::add_extension_internal(x509.as_ptr(), @@ -343,117 +320,95 @@ impl X509Generator { &ext.to_string())); } - let hash_fn = self.hash_type.evp_md(); - try_ssl!(ffi::X509_sign(x509.as_ptr(), p_key.as_ptr(), hash_fn)); + let hash_fn = self.hash_type.as_ptr(); + try!(cvt(ffi::X509_sign(x509.as_ptr(), p_key.as_ptr(), hash_fn))); Ok(x509) } } /// 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 { + pub fn request(&self, p_key: &PKeyRef) -> Result { let cert = match self.sign(p_key) { Ok(c) => c, Err(x) => return Err(x), }; unsafe { - let req = ffi::X509_to_X509_REQ(cert.as_ptr(), ptr::null_mut(), ptr::null()); - try_ssl_null!(req); + let req = try!(cvt_p(ffi::X509_to_X509_REQ(cert.as_ptr(), + ptr::null_mut(), + ptr::null()))); + let req = X509Req::from_ptr(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!(cvt(ffi::X509_REQ_add_extensions(req.as_ptr(), exts as *mut _))); } - let hash_fn = self.hash_type.evp_md(); - try_ssl!(ffi::X509_REQ_sign(req, p_key.as_ptr(), hash_fn)); + let hash_fn = self.hash_type.as_ptr(); + try!(cvt(ffi::X509_REQ_sign(req.as_ptr(), p_key.as_ptr(), hash_fn))); - Ok(X509Req::new(req)) + Ok(req) } } } -/// A borrowed public key certificate. -pub struct X509Ref<'a>(*mut ffi::X509, PhantomData<&'a ()>); +type_!(X509, X509Ref, ffi::X509, ffi::X509_free); -impl<'a> X509Ref<'a> { - /// Creates a new `X509Ref` wrapping the provided handle. - pub unsafe fn from_ptr(x509: *mut ffi::X509) -> X509Ref<'a> { - X509Ref(x509, PhantomData) - } - - /// - #[deprecated(note = "renamed to `X509::from_ptr`", since = "0.8.1")] - pub unsafe fn new(x509: *mut ffi::X509) -> X509Ref<'a> { - X509Ref::from_ptr(x509) - } - - pub fn as_ptr(&self) -> *mut ffi::X509 { - self.0 - } - - pub fn subject_name<'b>(&'b self) -> X509Name<'b> { - let name = unsafe { ffi::X509_get_subject_name(self.0) }; - X509Name(name, PhantomData) +impl X509Ref { + pub fn subject_name(&self) -> &X509NameRef { + unsafe { + let name = ffi::X509_get_subject_name(self.as_ptr()); + X509NameRef::from_ptr(name) + } } /// Returns this certificate's SAN entries, if they exist. - pub fn subject_alt_names<'b>(&'b self) -> Option> { + pub fn subject_alt_names(&self) -> Option> { unsafe { - let stack = ffi::X509_get_ext_d2i(self.0, - Nid::SubjectAltName as c_int, + let stack = ffi::X509_get_ext_d2i(self.as_ptr(), + ffi::NID_subject_alt_name, ptr::null_mut(), ptr::null_mut()); if stack.is_null() { return None; } - Some(GeneralNames { - stack: stack as *mut _, - m: PhantomData, - }) + Some(Stack::from_ptr(stack as *mut _)) } } pub fn public_key(&self) -> Result { unsafe { - let pkey = try_ssl_null!(ffi::X509_get_pubkey(self.0)); + let pkey = try!(cvt_p(ffi::X509_get_pubkey(self.as_ptr()))); Ok(PKey::from_ptr(pkey)) } } /// Returns certificate fingerprint calculated using provided hash - pub fn fingerprint(&self, hash_type: hash::Type) -> Result, ErrorStack> { + pub fn fingerprint(&self, hash_type: MessageDigest) -> Result, ErrorStack> { unsafe { - let evp = hash_type.evp_md(); + let evp = hash_type.as_ptr(); let mut len = ffi::EVP_MAX_MD_SIZE; let mut buf = vec![0u8; len as usize]; - try_ssl!(ffi::X509_digest(self.0, evp, buf.as_mut_ptr() as *mut _, &mut len)); + try!(cvt(ffi::X509_digest(self.as_ptr(), evp, buf.as_mut_ptr() as *mut _, &mut len))); buf.truncate(len as usize); Ok(buf) } } /// Returns certificate Not After validity period. - /// Requires the `x509_expiry` feature. - #[cfg(feature = "x509_expiry")] - pub fn not_after<'b>(&'b self) -> Asn1TimeRef<'b> { + pub fn not_after<'a>(&'a self) -> &'a Asn1TimeRef { unsafe { - let date = ::c_helpers::rust_0_8_X509_get_notAfter(self.0); + let date = compat::X509_get_notAfter(self.as_ptr()); 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> { + pub fn not_before<'a>(&'a self) -> &'a Asn1TimeRef { unsafe { - let date = ::c_helpers::rust_0_8_X509_get_notBefore(self.0); + let date = compat::X509_get_notBefore(self.as_ptr()); assert!(!date.is_null()); Asn1TimeRef::from_ptr(date) } @@ -463,7 +418,7 @@ impl<'a> X509Ref<'a> { pub fn to_pem(&self) -> Result, ErrorStack> { let mem_bio = try!(MemBio::new()); unsafe { - try_ssl!(ffi::PEM_write_bio_X509(mem_bio.as_ptr(), self.0)); + try!(cvt(ffi::PEM_write_bio_X509(mem_bio.as_ptr(), self.as_ptr()))); } Ok(mem_bio.get_buf().to_owned()) } @@ -472,33 +427,30 @@ impl<'a> X509Ref<'a> { pub fn to_der(&self) -> Result, ErrorStack> { let mem_bio = try!(MemBio::new()); unsafe { - ffi::i2d_X509_bio(mem_bio.as_ptr(), self.0); + ffi::i2d_X509_bio(mem_bio.as_ptr(), self.as_ptr()); } Ok(mem_bio.get_buf().to_owned()) } } -/// An owned public key certificate. -pub struct X509(X509Ref<'static>); +impl ToOwned for X509Ref { + type Owned = X509; + + fn to_owned(&self) -> X509 { + unsafe { + compat::X509_up_ref(self.as_ptr()); + X509::from_ptr(self.as_ptr()) + } + } +} impl X509 { - /// Returns a new `X509`, taking ownership of the handle. - pub unsafe fn from_ptr(x509: *mut ffi::X509) -> X509 { - X509(X509Ref::from_ptr(x509)) - } - - /// - #[deprecated(note = "renamed to `X509::from_ptr`", since = "0.8.1")] - pub unsafe fn new(x509: *mut ffi::X509) -> X509 { - X509::from_ptr(x509) - } - /// Reads a certificate from DER. pub fn from_der(buf: &[u8]) -> Result { 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)); + let x509 = try!(cvt_p(ffi::d2i_X509(ptr::null_mut(), &mut ptr, len))); Ok(X509::from_ptr(x509)) } } @@ -507,103 +459,99 @@ impl X509 { pub fn from_pem(buf: &[u8]) -> Result { let mem_bio = try!(MemBioSlice::new(buf)); unsafe { - let handle = try_ssl_null!(ffi::PEM_read_bio_X509(mem_bio.as_ptr(), - ptr::null_mut(), - None, - ptr::null_mut())); + let handle = try!(cvt_p(ffi::PEM_read_bio_X509(mem_bio.as_ptr(), + ptr::null_mut(), + None, + ptr::null_mut()))); Ok(X509::from_ptr(handle)) } } } -impl Deref for X509 { - type Target = X509Ref<'static>; - - fn deref(&self) -> &X509Ref<'static> { - &self.0 - } -} - -#[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()) + self.to_owned() + } +} + +impl AsRef for X509 { + fn as_ref(&self) -> &X509Ref { + &*self + } +} + +impl AsRef for X509Ref { + fn as_ref(&self) -> &X509Ref { + self + } +} + +impl Borrow for X509 { + fn borrow(&self) -> &X509Ref { + &*self + } +} + +impl Stackable for X509 { + type StackType = ffi::stack_st_X509; +} + +type_!(X509Name, X509NameRef, ffi::X509_NAME, ffi::X509_NAME_free); + +impl X509NameRef { + pub fn entries_by_nid<'a>(&'a self, nid: Nid) -> X509NameEntries<'a> { + X509NameEntries { + name: self, + nid: nid, + loc: -1, } } } -impl Drop for X509 { - fn drop(&mut self) { - unsafe { ffi::X509_free(self.as_ptr()) }; - } +pub struct X509NameEntries<'a> { + name: &'a X509NameRef, + nid: Nid, + loc: c_int, } -pub struct X509Name<'x>(*mut ffi::X509_NAME, PhantomData<&'x ()>); +impl<'a> Iterator for X509NameEntries<'a> { + type Item = &'a X509NameEntryRef; -impl<'x> X509Name<'x> { - pub fn text_by_nid(&self, nid: Nid) -> Option { + fn next(&mut self) -> Option<&'a X509NameEntryRef> { unsafe { - let loc = ffi::X509_NAME_get_index_by_NID(self.0, nid as c_int, -1); - if loc == -1 { + self.loc = + ffi::X509_NAME_get_index_by_NID(self.name.as_ptr(), self.nid.as_raw(), self.loc); + + if self.loc == -1 { return None; } - let ne = ffi::X509_NAME_get_entry(self.0, loc); - if ne.is_null() { - return None; - } + let entry = ffi::X509_NAME_get_entry(self.name.as_ptr(), self.loc); + assert!(!entry.is_null()); - let asn1_str = ffi::X509_NAME_ENTRY_get_data(ne); - if asn1_str.is_null() { - return None; - } - - let mut str_from_asn1: *mut c_char = ptr::null_mut(); - let len = ffi::ASN1_STRING_to_UTF8(&mut str_from_asn1, asn1_str); - - if len < 0 { - return None; - } - - assert!(!str_from_asn1.is_null()); - - Some(SslString::new(str_from_asn1, len)) + Some(X509NameEntryRef::from_ptr(entry)) } } } -/// A certificate signing request -pub struct X509Req(*mut ffi::X509_REQ); +type_!(X509NameEntry, X509NameEntryRef, ffi::X509_NAME_ENTRY, ffi::X509_NAME_ENTRY_free); -impl X509Req { - /// Creates new from handle - pub unsafe fn new(handle: *mut ffi::X509_REQ) -> X509Req { - X509Req(handle) - } - - pub fn as_ptr(&self) -> *mut ffi::X509_REQ { - self.0 - } - - /// Reads CSR from PEM - pub fn from_pem(buf: &[u8]) -> Result { - let mem_bio = try!(MemBioSlice::new(buf)); +impl X509NameEntryRef { + pub fn data(&self) -> &Asn1StringRef { unsafe { - let handle = try_ssl_null!(ffi::PEM_read_bio_X509_REQ(mem_bio.as_ptr(), - ptr::null_mut(), - None, - ptr::null_mut())); - Ok(X509Req::new(handle)) + let data = ffi::X509_NAME_ENTRY_get_data(self.as_ptr()); + Asn1StringRef::from_ptr(data) } } +} +type_!(X509Req, X509ReqRef, ffi::X509_REQ, ffi::X509_REQ_free); + +impl X509ReqRef { /// Writes CSR as PEM pub fn to_pem(&self) -> Result, ErrorStack> { let mem_bio = try!(MemBio::new()); - if unsafe { ffi::PEM_write_bio_X509_REQ(mem_bio.as_ptr(), self.0) } != 1 { + if unsafe { ffi::PEM_write_bio_X509_REQ(mem_bio.as_ptr(), self.as_ptr()) } != 1 { return Err(ErrorStack::get()); } Ok(mem_bio.get_buf().to_owned()) @@ -613,15 +561,23 @@ impl X509Req { pub fn to_der(&self) -> Result, ErrorStack> { let mem_bio = try!(MemBio::new()); unsafe { - ffi::i2d_X509_REQ_bio(mem_bio.as_ptr(), self.0); + ffi::i2d_X509_REQ_bio(mem_bio.as_ptr(), self.as_ptr()); } Ok(mem_bio.get_buf().to_owned()) } } -impl Drop for X509Req { - fn drop(&mut self) { - unsafe { ffi::X509_REQ_free(self.0) }; +impl X509Req { + /// Reads CSR from PEM + pub fn from_pem(buf: &[u8]) -> Result { + let mem_bio = try!(MemBioSlice::new(buf)); + unsafe { + let handle = try!(cvt_p(ffi::PEM_read_bio_X509_REQ(mem_bio.as_ptr(), + ptr::null_mut(), + None, + ptr::null_mut()))); + Ok(X509Req::from_ptr(handle)) + } } } @@ -694,184 +650,72 @@ impl<'a> Iterator for ExtensionsIter<'a> { } } -macro_rules! make_validation_error( - ($ok_val:ident, $($name:ident = $val:ident,)+) => ( - #[derive(Copy, Clone)] - pub enum X509ValidationError { - $($name,)+ - X509UnknownError(c_int) - } +pub struct X509VerifyError(c_long); - impl X509ValidationError { - #[doc(hidden)] - pub fn from_raw(err: c_int) -> Option { - match err { - ffi::$ok_val => None, - $(ffi::$val => Some(X509ValidationError::$name),)+ - err => Some(X509ValidationError::X509UnknownError(err)) - } - } - } - ) -); - -make_validation_error!(X509_V_OK, - X509UnableToGetIssuerCert = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT, - X509UnableToGetCrl = X509_V_ERR_UNABLE_TO_GET_CRL, - X509UnableToDecryptCertSignature = X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE, - X509UnableToDecryptCrlSignature = X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE, - X509UnableToDecodeIssuerPublicKey = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY, - X509CertSignatureFailure = X509_V_ERR_CERT_SIGNATURE_FAILURE, - X509CrlSignatureFailure = X509_V_ERR_CRL_SIGNATURE_FAILURE, - X509CertNotYetValid = X509_V_ERR_CERT_NOT_YET_VALID, - X509CertHasExpired = X509_V_ERR_CERT_HAS_EXPIRED, - X509CrlNotYetValid = X509_V_ERR_CRL_NOT_YET_VALID, - X509CrlHasExpired = X509_V_ERR_CRL_HAS_EXPIRED, - X509ErrorInCertNotBeforeField = X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD, - X509ErrorInCertNotAfterField = X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD, - X509ErrorInCrlLastUpdateField = X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD, - X509ErrorInCrlNextUpdateField = X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD, - X509OutOfMem = X509_V_ERR_OUT_OF_MEM, - X509DepthZeroSelfSignedCert = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT, - X509SelfSignedCertInChain = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN, - X509UnableToGetIssuerCertLocally = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, - X509UnableToVerifyLeafSignature = X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE, - X509CertChainTooLong = X509_V_ERR_CERT_CHAIN_TOO_LONG, - X509CertRevoked = X509_V_ERR_CERT_REVOKED, - X509InvalidCA = X509_V_ERR_INVALID_CA, - X509PathLengthExceeded = X509_V_ERR_PATH_LENGTH_EXCEEDED, - X509InvalidPurpose = X509_V_ERR_INVALID_PURPOSE, - X509CertUntrusted = X509_V_ERR_CERT_UNTRUSTED, - X509CertRejected = X509_V_ERR_CERT_REJECTED, - X509SubjectIssuerMismatch = X509_V_ERR_SUBJECT_ISSUER_MISMATCH, - X509AkidSkidMismatch = X509_V_ERR_AKID_SKID_MISMATCH, - X509AkidIssuerSerialMismatch = X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH, - X509KeyusageNoCertsign = X509_V_ERR_KEYUSAGE_NO_CERTSIGN, - X509UnableToGetCrlIssuer = X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER, - X509UnhandledCriticalExtension = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION, - X509KeyusageNoCrlSign = X509_V_ERR_KEYUSAGE_NO_CRL_SIGN, - X509UnhandledCriticalCrlExtension = X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION, - X509InvalidNonCA = X509_V_ERR_INVALID_NON_CA, - X509ProxyPathLengthExceeded = X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED, - X509KeyusageNoDigitalSignature = X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE, - X509ProxyCertificatesNotAllowed = X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED, - X509InvalidExtension = X509_V_ERR_INVALID_EXTENSION, - X509InavlidPolicyExtension = X509_V_ERR_INVALID_POLICY_EXTENSION, - X509NoExplicitPolicy = X509_V_ERR_NO_EXPLICIT_POLICY, - X509DifferentCrlScope = X509_V_ERR_DIFFERENT_CRL_SCOPE, - X509UnsupportedExtensionFeature = X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE, - X509UnnestedResource = X509_V_ERR_UNNESTED_RESOURCE, - X509PermittedVolation = X509_V_ERR_PERMITTED_VIOLATION, - X509ExcludedViolation = X509_V_ERR_EXCLUDED_VIOLATION, - X509SubtreeMinmax = X509_V_ERR_SUBTREE_MINMAX, - X509UnsupportedConstraintType = X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE, - X509UnsupportedConstraintSyntax = X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX, - X509UnsupportedNameSyntax = X509_V_ERR_UNSUPPORTED_NAME_SYNTAX, - X509CrlPathValidationError= X509_V_ERR_CRL_PATH_VALIDATION_ERROR, - X509ApplicationVerification = X509_V_ERR_APPLICATION_VERIFICATION, -); - -// FIXME remove lifetime param for 0.9 -/// A collection of OpenSSL `GENERAL_NAME`s. -pub struct GeneralNames<'a> { - stack: *mut ffi::stack_st_GENERAL_NAME, - m: PhantomData<&'a ()>, -} - -impl<'a> Drop for GeneralNames<'a> { - 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); - ffi::sk_pop_free(&mut (*self.stack).stack, Some(free)); - } +impl fmt::Debug for X509VerifyError { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.debug_struct("X509VerifyError") + .field("code", &self.0) + .field("error", &self.error_string()) + .finish() } } -impl<'a> GeneralNames<'a> { - /// Returns the number of `GeneralName`s in this structure. - pub fn len(&self) -> usize { - unsafe { (*self.stack).stack.num as usize } +impl fmt::Display for X509VerifyError { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.write_str(self.error_string()) } +} - /// Returns the specified `GeneralName`. +impl Error for X509VerifyError { + fn description(&self) -> &str { + "an X509 validation error" + } +} + +impl X509VerifyError { + /// Creates an `X509VerifyError` from a raw error number. /// - /// # Panics + /// `None` will be returned if `err` is `X509_V_OK`. /// - /// Panics if `idx` is not less than `len()`. - 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, - m: PhantomData, - } - } - } - - /// Returns an iterator over the `GeneralName`s in this structure. - pub fn iter(&self) -> GeneralNamesIter { - GeneralNamesIter { - names: self, - idx: 0, - } - } -} - -impl<'a> IntoIterator for &'a GeneralNames<'a> { - type Item = GeneralName<'a>; - type IntoIter = GeneralNamesIter<'a>; - - fn into_iter(self) -> GeneralNamesIter<'a> { - self.iter() - } -} - -/// An iterator over OpenSSL `GENERAL_NAME`s. -pub struct GeneralNamesIter<'a> { - names: &'a GeneralNames<'a>, - idx: usize, -} - -impl<'a> Iterator for GeneralNamesIter<'a> { - type Item = GeneralName<'a>; - - fn next(&mut self) -> Option { - if self.idx < self.names.len() { - let name = self.names.get(self.idx); - self.idx += 1; - Some(name) - } else { + /// # Safety + /// + /// Some methods on `X509VerifyError` are not thread safe if the error + /// number is invalid. + pub unsafe fn from_raw(err: c_long) -> Option { + if err == ffi::X509_V_OK as c_long { None + } else { + Some(X509VerifyError(err)) } } - fn size_hint(&self) -> (usize, Option) { - let size = self.names.len() - self.idx; - (size, Some(size)) + pub fn as_raw(&self) -> c_long { + self.0 + } + + pub fn error_string(&self) -> &'static str { + ffi::init(); + + unsafe { + let s = ffi::X509_verify_cert_error_string(self.0); + str::from_utf8(CStr::from_ptr(s).to_bytes()).unwrap() + } } } -impl<'a> ExactSizeIterator for GeneralNamesIter<'a> {} +type_!(GeneralName, GeneralNameRef, ffi::GENERAL_NAME, ffi::GENERAL_NAME_free); -/// An OpenSSL `GENERAL_NAME`. -pub struct GeneralName<'a> { - name: *const ffi::GENERAL_NAME, - m: PhantomData<&'a ()>, -} - -impl<'a> GeneralName<'a> { +impl GeneralNameRef { /// Returns the contents of this `GeneralName` if it is a `dNSName`. pub fn dnsname(&self) -> Option<&str> { unsafe { - if (*self.name).type_ != ffi::GEN_DNS { + if (*self.as_ptr()).type_ != ffi::GEN_DNS { return None; } - let ptr = ffi::ASN1_STRING_data((*self.name).d as *mut _); - let len = ffi::ASN1_STRING_length((*self.name).d as *mut _); + let ptr = ASN1_STRING_data((*self.as_ptr()).d as *mut _); + let len = ffi::ASN1_STRING_length((*self.as_ptr()).d as *mut _); let slice = slice::from_raw_parts(ptr as *const u8, len as usize); // dNSNames are stated to be ASCII (specifically IA5). Hopefully @@ -884,18 +728,22 @@ impl<'a> GeneralName<'a> { /// Returns the contents of this `GeneralName` if it is an `iPAddress`. pub fn ipaddress(&self) -> Option<&[u8]> { unsafe { - if (*self.name).type_ != ffi::GEN_IPADD { + if (*self.as_ptr()).type_ != ffi::GEN_IPADD { return None; } - let ptr = ffi::ASN1_STRING_data((*self.name).d as *mut _); - let len = ffi::ASN1_STRING_length((*self.name).d as *mut _); + let ptr = ASN1_STRING_data((*self.as_ptr()).d as *mut _); + let len = ffi::ASN1_STRING_length((*self.as_ptr()).d as *mut _); Some(slice::from_raw_parts(ptr as *const u8, len as usize)) } } } +impl Stackable for GeneralName { + type StackType = ffi::stack_st_GENERAL_NAME; +} + #[test] fn test_negative_serial() { // I guess that's enough to get a random negative number @@ -904,3 +752,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 + } + } +} diff --git a/openssl/src/x509/tests.rs b/openssl/src/x509/tests.rs index eac08941..2527d538 100644 --- a/openssl/src/x509/tests.rs +++ b/openssl/src/x509/tests.rs @@ -1,31 +1,31 @@ use serialize::hex::FromHex; -use crypto::hash::Type::SHA1; -use crypto::pkey::PKey; -use crypto::rsa::RSA; +use hash::MessageDigest; +use pkey::PKey; +use rsa::Rsa; use x509::{X509, X509Generator}; use x509::extension::Extension::{KeyUsage, ExtKeyUsage, SubjectAltName, OtherNid, OtherStr}; use x509::extension::AltNameOption as SAN; use x509::extension::KeyUsageOption::{DigitalSignature, KeyEncipherment}; use x509::extension::ExtKeyUsageOption::{self, ClientAuth, ServerAuth}; -use nid::Nid; +use nid; fn get_generator() -> X509Generator { X509Generator::new() .set_valid_period(365 * 2) .add_name("CN".to_string(), "test_me".to_string()) - .set_sign_hash(SHA1) + .set_sign_hash(MessageDigest::sha1()) .add_extension(KeyUsage(vec![DigitalSignature, KeyEncipherment])) .add_extension(ExtKeyUsage(vec![ClientAuth, ServerAuth, ExtKeyUsageOption::Other("2.999.1".to_owned())])) .add_extension(SubjectAltName(vec![(SAN::DNS, "example.com".to_owned())])) - .add_extension(OtherNid(Nid::BasicConstraints, "critical,CA:TRUE".to_owned())) + .add_extension(OtherNid(nid::BASIC_CONSTRAINTS, "critical,CA:TRUE".to_owned())) .add_extension(OtherStr("2.999.2".to_owned(), "ASN1:UTF8:example value".to_owned())) } fn pkey() -> PKey { - let rsa = RSA::generate(2048).unwrap(); + let rsa = Rsa::generate(2048).unwrap(); PKey::from_rsa(rsa).unwrap() } @@ -48,8 +48,8 @@ fn test_cert_gen() { fn test_cert_gen_extension_ordering() { let pkey = pkey(); get_generator() - .add_extension(OtherNid(Nid::SubjectKeyIdentifier, "hash".to_owned())) - .add_extension(OtherNid(Nid::AuthorityKeyIdentifier, "keyid:always".to_owned())) + .add_extension(OtherNid(nid::SUBJECT_KEY_IDENTIFIER, "hash".to_owned())) + .add_extension(OtherNid(nid::AUTHORITY_KEY_IDENTIFIER, "keyid:always".to_owned())) .sign(&pkey) .expect("Failed to generate cert with order-dependent extensions"); } @@ -60,16 +60,14 @@ fn test_cert_gen_extension_ordering() { fn test_cert_gen_extension_bad_ordering() { let pkey = pkey(); let result = get_generator() - .add_extension(OtherNid(Nid::AuthorityKeyIdentifier, - "keyid:always".to_owned())) - .add_extension(OtherNid(Nid::SubjectKeyIdentifier, "hash".to_owned())) - .sign(&pkey); + .add_extension(OtherNid(nid::AUTHORITY_KEY_IDENTIFIER, "keyid:always".to_owned())) + .add_extension(OtherNid(nid::SUBJECT_KEY_IDENTIFIER, "hash".to_owned())) + .sign(&pkey); assert!(result.is_err()); } #[test] -#[cfg(feature = "x509_generator_request")] fn test_req_gen() { let pkey = pkey(); @@ -84,7 +82,7 @@ fn test_req_gen() { fn test_cert_loading() { let cert = include_bytes!("../../test/cert.pem"); let cert = X509::from_pem(cert).ok().expect("Failed to load PEM"); - let fingerprint = cert.fingerprint(SHA1).unwrap(); + let fingerprint = cert.fingerprint(MessageDigest::sha1()).unwrap(); let hash_str = "59172d9313e84459bcff27f967e79e6e9217e584"; let hash_vec = hash_str.from_hex().unwrap(); @@ -93,7 +91,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"); @@ -116,65 +113,49 @@ fn test_save_der() { #[test] fn test_subject_read_cn() { let cert = include_bytes!("../../test/cert.pem"); - let cert = X509::from_pem(cert).ok().expect("Failed to load PEM"); + let cert = X509::from_pem(cert).unwrap(); let subject = cert.subject_name(); - let cn = match subject.text_by_nid(Nid::CN) { - Some(x) => x, - None => panic!("Failed to read CN from cert"), - }; - - assert_eq!(&cn as &str, "foobar.com") + let cn = subject.entries_by_nid(nid::COMMONNAME).next().unwrap(); + assert_eq!(cn.data().as_slice(), b"foobar.com") } #[test] fn test_nid_values() { let cert = include_bytes!("../../test/nid_test_cert.pem"); - let cert = X509::from_pem(cert).ok().expect("Failed to load PEM"); + let cert = X509::from_pem(cert).unwrap(); let subject = cert.subject_name(); - let cn = match subject.text_by_nid(Nid::CN) { - Some(x) => x, - None => panic!("Failed to read CN from cert"), - }; - assert_eq!(&cn as &str, "example.com"); + let cn = subject.entries_by_nid(nid::COMMONNAME).next().unwrap(); + assert_eq!(cn.data().as_slice(), b"example.com"); - let email = match subject.text_by_nid(Nid::Email) { - Some(x) => x, - None => panic!("Failed to read subject email address from cert"), - }; - assert_eq!(&email as &str, "test@example.com"); + let email = subject.entries_by_nid(nid::PKCS9_EMAILADDRESS).next().unwrap(); + assert_eq!(email.data().as_slice(), b"test@example.com"); - let friendly = match subject.text_by_nid(Nid::FriendlyName) { - Some(x) => x, - None => panic!("Failed to read subject friendly name from cert"), - }; - assert_eq!(&friendly as &str, "Example"); + let friendly = subject.entries_by_nid(nid::FRIENDLYNAME).next().unwrap(); + assert_eq!(&*friendly.data().as_utf8().unwrap(), "Example"); } #[test] fn test_nid_uid_value() { let cert = include_bytes!("../../test/nid_uid_test_cert.pem"); - let cert = X509::from_pem(cert).ok().expect("Failed to load PEM"); + let cert = X509::from_pem(cert).unwrap(); let subject = cert.subject_name(); - let cn = match subject.text_by_nid(Nid::UserId) { - Some(x) => x, - None => panic!("Failed to read UID from cert"), - }; - assert_eq!(&cn as &str, "this is the userId"); + let cn = subject.entries_by_nid(nid::USERID).next().unwrap(); + assert_eq!(cn.data().as_slice(), b"this is the userId"); } #[test] fn test_subject_alt_name() { let cert = include_bytes!("../../test/alt_name_cert.pem"); - let cert = X509::from_pem(cert).ok().expect("Failed to load PEM"); + let cert = X509::from_pem(cert).unwrap(); let subject_alt_names = cert.subject_alt_names().unwrap(); assert_eq!(3, subject_alt_names.len()); - assert_eq!(Some("foobar.com"), subject_alt_names.get(0).dnsname()); - assert_eq!(subject_alt_names.get(1).ipaddress(), + assert_eq!(Some("foobar.com"), subject_alt_names[0].dnsname()); + assert_eq!(subject_alt_names[1].ipaddress(), Some(&[127, 0, 0, 1][..])); - assert_eq!(subject_alt_names.get(2).ipaddress(), + assert_eq!(subject_alt_names[2].ipaddress(), Some(&b"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01"[..])); } diff --git a/openssl/src/x509/verify.rs b/openssl/src/x509/verify.rs new file mode 100644 index 00000000..8cb123e6 --- /dev/null +++ b/openssl/src/x509/verify.rs @@ -0,0 +1,5 @@ +//! X509 certificate verification +//! +//! Requires the `v102` or `v110` features and OpenSSL 1.0.2 or 1.1.0. + +pub use ::verify::*; diff --git a/openssl/test/build.sh b/openssl/test/build.sh index 2c38f3a3..106a38d3 100755 --- a/openssl/test/build.sh +++ b/openssl/test/build.sh @@ -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 diff --git a/openssl/test/run.sh b/openssl/test/run.sh index 2c2473b1..4d3397a6 100755 --- a/openssl/test/run.sh +++ b/openssl/test/run.sh @@ -1,32 +1,26 @@ #!/bin/bash set -e -MAIN_TARGETS=https://static.rust-lang.org/dist +case "$BUILD_OPENSSL_VERSION" in + 1.0.2*) + FEATURES="v102" + ;; + 1.1.0*) + FEATURES="v110" + ;; +esac -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" +echo Using features: $FEATURES + +if [ -d "$HOME/openssl/lib" ]; then + export OPENSSL_DIR=$HOME/openssl + export PATH=$HOME/openssl/bin:$PATH 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 +if [ "$TARGET" == "arm-unknown-linux-gnueabihf" ]; then + FLAGS="--no-run" 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" -fi - -export PATH=$HOME/openssl/bin:$PATH -(cd openssl && RUST_BACKTRACE=1 cargo $COMMAND $FLAGS --features "$FEATURES") +cargo run --manifest-path systest/Cargo.toml --target $TARGET +exec cargo test --manifest-path openssl/Cargo.toml --target $TARGET \ + --features "$FEATURES" $FLAGS diff --git a/systest/Cargo.toml b/systest/Cargo.toml new file mode 100644 index 00000000..3997bf35 --- /dev/null +++ b/systest/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "systest" +version = "0.1.0" +authors = ["Alex Crichton "] +build = "build.rs" + +[dependencies] +libc = "0.2" +openssl-sys = { path = "../openssl-sys" } + +[build-dependencies] +ctest = "0.1" diff --git a/systest/build.rs b/systest/build.rs new file mode 100644 index 00000000..81907a57 --- /dev/null +++ b/systest/build.rs @@ -0,0 +1,101 @@ +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"); + } + } + + cfg.cfg(&format!("ossl{}", env::var("DEP_OPENSSL_VERSION").unwrap()), None); + if let Ok(vars) = env::var("DEP_OPENSSL_CONF") { + for var in vars.split(",") { + cfg.cfg("osslconf", Some(var)); + } + } + + 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 + + // 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"); +} + diff --git a/systest/src/main.rs b/systest/src/main.rs new file mode 100644 index 00000000..39d31b2f --- /dev/null +++ b/systest/src/main.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"));