diff --git a/.circleci/config.yml b/.circleci/config.yml index 39ef6c5325206c2438c30d362fcaeab30a738d2b..4e8695e81a451fc08de77dab054ed5c6b8d15303 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -35,6 +35,7 @@ job: &JOB steps: - checkout - run: apt-get update + - run: apt-get remove -y libssl-dev - run: ./test/add_target.sh - *RESTORE_REGISTRY - run: cargo generate-lockfile @@ -68,10 +69,10 @@ job: &JOB openssl_110: &OPENSSL_110 LIBRARY: openssl - VERSION: 1.1.0f + VERSION: 1.1.0g openssl_102: &OPENSSL_102 LIBRARY: openssl - VERSION: 1.0.2l + VERSION: 1.0.2m openssl_101: &OPENSSL_101 LIBRARY: openssl VERSION: 1.0.1u diff --git a/appveyor.yml b/appveyor.yml index d9ba75582dcbe397bb4df81fd7da942bf944d7bf..bae5d621e35178897704911c5aaa5e31e2fcb1f1 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -5,20 +5,20 @@ environment: - TARGET: i686-pc-windows-gnu BITS: 32 MSYS2: 1 - OPENSSL_VERSION: 1_1_0f + OPENSSL_VERSION: 1_1_0g - TARGET: x86_64-pc-windows-msvc BITS: 64 - OPENSSL_VERSION: 1_1_0f + OPENSSL_VERSION: 1_1_0g OPENSSL_DIR: C:\OpenSSL # 1.0.2, 64/32 bit - TARGET: x86_64-pc-windows-gnu BITS: 64 MSYS2: 1 - OPENSSL_VERSION: 1_0_2L + OPENSSL_VERSION: 1_0_2m - TARGET: i686-pc-windows-msvc BITS: 32 - OPENSSL_VERSION: 1_0_2L + OPENSSL_VERSION: 1_0_2m OPENSSL_DIR: C:\OpenSSL - TARGET: x86_64-pc-windows-msvc VCPKG_DEFAULT_TRIPLET: x64-windows @@ -48,7 +48,3 @@ build: false test_script: - 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/Cargo.toml b/openssl/Cargo.toml index c93f75819c1629251fd7f9a460c183b8f9a55cf9..4f956c8e373dd832f17b8e5710f8d9540e4691f8 100644 --- a/openssl/Cargo.toml +++ b/openssl/Cargo.toml @@ -31,4 +31,4 @@ tempdir = "0.3" winapi = "0.2" ws2_32-sys = "0.2" hex = "0.2" -data-encoding = "1.2" +data-encoding = "2.0" diff --git a/openssl/LICENSE b/openssl/LICENSE index 808903ae0be21971b2eaf5b18c8aac2b37025e8a..f259067e9a54ac652802c9eb80788ddfe5bf7335 100644 --- a/openssl/LICENSE +++ b/openssl/LICENSE @@ -1,4 +1,4 @@ -Copyright 2011 Google Inc. +Copyright 2011-2017 Google Inc. 2013 Jack Lloyd 2013-2014 Steven Fackler diff --git a/openssl/examples/mk_certs.rs b/openssl/examples/mk_certs.rs index 0e1dc2a08c3ad84d3eb1e9ffb260dbda543a3f20..c64dc007ff9348a07c1371d538fae241edd420d4 100644 --- a/openssl/examples/mk_certs.rs +++ b/openssl/examples/mk_certs.rs @@ -4,11 +4,10 @@ extern crate openssl; use openssl::asn1::Asn1Time; -use openssl::bn::BigNum; +use openssl::bn::{BigNum, MSB_MAYBE_ZERO}; use openssl::error::ErrorStack; use openssl::hash::MessageDigest; use openssl::pkey::{PKey, PKeyRef}; -use openssl::rand::rand_bytes; use openssl::rsa::Rsa; use openssl::x509::{X509, X509Ref}; use openssl::x509::{X509NameBuilder, X509Req, X509ReqBuilder}; @@ -30,9 +29,9 @@ fn mk_ca_cert() -> Result<(X509, PKey), ErrorStack> { let mut cert_builder = X509::builder()?; cert_builder.set_version(2)?; let serial_number = { - let mut buf = [0;20]; - rand_bytes(&mut buf)?; - BigNum::from_slice(&buf)?.to_asn1_integer()? + let mut serial = BigNum::new()?; + serial.rand(159, MSB_MAYBE_ZERO, false)?; + serial.to_asn1_integer()? }; cert_builder.set_serial_number(&serial_number)?; cert_builder.set_subject_name(&x509_name)?; @@ -88,9 +87,9 @@ fn mk_ca_signed_cert(ca_cert: &X509Ref, ca_privkey: &PKeyRef) -> Result<(X509, P let mut cert_builder = X509::builder()?; cert_builder.set_version(2)?; let serial_number = { - let mut buf = [0;20]; - rand_bytes(&mut buf)?; - BigNum::from_slice(&buf)?.to_asn1_integer()? + let mut serial = BigNum::new()?; + serial.rand(159, MSB_MAYBE_ZERO, false)?; + serial.to_asn1_integer()? }; cert_builder.set_serial_number(&serial_number)?; cert_builder.set_subject_name(req.subject_name())?; diff --git a/openssl/src/ec.rs b/openssl/src/ec.rs index 02be6d22e710bdcc1b803665cc36661888f9faa3..ddf8c0290c7bc3f860ccea84a856e8997264ed2e 100644 --- a/openssl/src/ec.rs +++ b/openssl/src/ec.rs @@ -1,3 +1,36 @@ +//! Elliptic Curve +//! +//! Cryptology relies on the difficulty of solving mathematical problems, such as the factor +//! of large integers composed of two large prime numbers and the discrete logarithm of a +//! random eliptic curve. This module provides low-level features of the latter. +//! Elliptic Curve protocols can provide the same security with smaller keys. +//! +//! There are 2 forms of elliptic curves, `Fp` and `F2^m`. These curves use irreducible +//! trinomial or pentanomial . Being a generic interface to a wide range of algorithms, +//! the cuves are generally referenced by [`EcGroup`]. There are many built in groups +//! found in [`Nid`]. +//! +//! OpenSSL Wiki explains the fields and curves in detail at [Eliptic Curve Cryptography]. +//! +//! [`EcGroup`]: struct.EcGroup.html +//! [`Nid`]: ../nid/struct.Nid.html +//! [Eliptic Curve Cryptography]: https://wiki.openssl.org/index.php/Elliptic_Curve_Cryptography +//! +//! # Examples +//! +//! ``` +//! use openssl::ec::{EcGroup, EcPoint}; +//! use openssl::nid; +//! use openssl::error::ErrorStack; +//! fn get_ec_point() -> Result< EcPoint, ErrorStack > { +//! let group = EcGroup::from_curve_name(nid::SECP224R1)?; +//! let point = EcPoint::new(&group)?; +//! Ok(point) +//! } +//! # fn main() { +//! # let _ = get_ec_point(); +//! # } +//! ``` use ffi; use foreign_types::{ForeignType, ForeignTypeRef}; use std::ptr; @@ -9,23 +42,59 @@ use bn::{BigNumRef, BigNumContextRef}; use error::ErrorStack; use nid::Nid; +/// Compressed conversion from point value (Default) pub const POINT_CONVERSION_COMPRESSED: PointConversionForm = PointConversionForm(ffi::point_conversion_form_t::POINT_CONVERSION_COMPRESSED); +/// Uncompressed conversion from point value (Binary curve default) pub const POINT_CONVERSION_UNCOMPRESSED: PointConversionForm = PointConversionForm(ffi::point_conversion_form_t::POINT_CONVERSION_UNCOMPRESSED); +/// Performs both compressed and uncompressed conversions pub const POINT_CONVERSION_HYBRID: PointConversionForm = PointConversionForm(ffi::point_conversion_form_t::POINT_CONVERSION_HYBRID); -// OPENSSL_EC_EXPLICIT_CURVE, but that was only added in 1.1. -// Man page documents that 0 can be used in older versions. +/// Curve defined using polynomial parameters +/// +/// Most applications use a named EC_GROUP curve, however, support +/// is included to explicitly define the curve used to calculate keys +/// This information would need to be known by both endpoint to make communication +/// effective. +/// +/// OPENSSL_EC_EXPLICIT_CURVE, but that was only added in 1.1. +/// Man page documents that 0 can be used in older versions. +/// +/// OpenSSL documentation at [`EC_GROUP`] +/// +/// [`EC_GROUP`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_GROUP_get_seed_len.html pub const EXPLICIT_CURVE: Asn1Flag = Asn1Flag(0); + +/// Standard Curves +/// +/// Curves that make up the typical encryption use cases. The collection of curves +/// are well known but extensible. +/// +/// OpenSSL documentation at [`EC_GROUP`] +/// +/// [`EC_GROUP`]: https://www.openssl.org/docs/manmaster/man3/EC_GROUP_order_bits.html pub const NAMED_CURVE: Asn1Flag = Asn1Flag(ffi::OPENSSL_EC_NAMED_CURVE); +/// Compressed or Uncompressed conversion +/// +/// Conversion from the binary value of the point on the curve is performed in one of +/// compressed, uncompressed, or hybrid conversions. The default is compressed, except +/// for binary curves. +/// +/// Further documentation is available in the [X9.62] standard. +/// +/// [X9.62]: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.202.2977&rep=rep1&type=pdf #[derive(Copy, Clone)] pub struct PointConversionForm(ffi::point_conversion_form_t); +/// Named Curve or Explicit +/// +/// This type acts as a boolean as to whether the EC_Group is named or +/// explicit. #[derive(Copy, Clone)] pub struct Asn1Flag(c_int); @@ -33,12 +102,35 @@ foreign_type! { type CType = ffi::EC_GROUP; fn drop = ffi::EC_GROUP_free; + /// Describes the curve + /// + /// A curve can be of the named curve type. These curves can be discovered + /// using openssl binary `openssl ecparam -list_curves`. Other operations + /// are available in the [wiki]. These named curves are available in the + /// [`Nid`] module. + /// + /// Curves can also be generated using prime field parameters or a binary field. + /// + /// Prime fields use the formula `y^2 mod p = x^3 + ax + b mod p`. Binary + /// fields use the formula `y^2 + xy = x^3 + ax^2 + b`. Named curves have + /// assured security. To prevent accidental vulnerabilities, they should + /// be prefered. + /// + /// [wiki]: https://wiki.openssl.org/index.php/Command_Line_Elliptic_Curve_Operations + /// [`Nid`]: ../nid/index.html pub struct EcGroup; + /// Reference to [`EcGroup`] + /// + /// [`EcGroup`]: struct.EcGroup.html pub struct EcGroupRef; } impl EcGroup { /// Returns the group of a standard named curve. + /// + /// OpenSSL documentation at [`EC_GROUP_new`]. + /// + /// [`EC_GROUP_new`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_GROUP_new.html pub fn from_curve_name(nid: Nid) -> Result { unsafe { init(); @@ -49,6 +141,11 @@ impl EcGroup { impl EcGroupRef { /// Places the components of a curve over a prime field in the provided `BigNum`s. + /// The components make up the formula `y^2 mod p = x^3 + ax + b mod p`. + /// + /// OpenSSL documentation available at [`EC_GROUP_get_curve_GFp`] + /// + /// [`EC_GROUP_get_curve_GFp`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_GROUP_get_curve_GFp.html pub fn components_gfp( &self, p: &mut BigNumRef, @@ -68,6 +165,15 @@ impl EcGroupRef { } /// Places the components of a curve over a binary field in the provided `BigNum`s. + /// The components make up the formula `y^2 + xy = x^3 + ax^2 + b`. + /// + /// In this form `p` relates to the irreducible polynomial. Each bit represents + /// a term in the polynomial. It will be set to 3 `1`s or 5 `1`s depending on + /// using a trinomial or pentanomial. + /// + /// OpenSSL documentation at [`EC_GROUP_get_curve_GF2m`]. + /// + /// [`EC_GROUP_get_curve_GF2m`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_GROUP_get_curve_GF2m.html #[cfg(not(osslconf = "OPENSSL_NO_EC2M"))] pub fn components_gf2m( &self, @@ -88,11 +194,19 @@ impl EcGroupRef { } /// Returns the degree of the curve. + /// + /// OpenSSL documentation at [`EC_GROUP_get_degree`] + /// + /// [`EC_GROUP_get_degree`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_GROUP_get_degree.html pub fn degree(&self) -> u32 { unsafe { ffi::EC_GROUP_get_degree(self.as_ptr()) as u32 } } /// Places the order of the curve in the provided `BigNum`. + /// + /// OpenSSL documentation at [`EC_GROUP_get_order`] + /// + /// [`EC_GROUP_get_order`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_GROUP_get_order.html pub fn order( &self, order: &mut BigNumRef, @@ -123,12 +237,24 @@ foreign_type! { type CType = ffi::EC_POINT; fn drop = ffi::EC_POINT_free; + /// Represents a point on the curve + /// + /// OpenSSL documentation at [`EC_POINT_new`] + /// + /// [`EC_POINT_new`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_POINT_new.html pub struct EcPoint; + /// Reference to [`EcPoint`] + /// + /// [`EcPoint`]: struct.EcPoint.html pub struct EcPointRef; } impl EcPointRef { /// Computes `a + b`, storing the result in `self`. + /// + /// OpenSSL documentation at [`EC_POINT_add`] + /// + /// [`EC_POINT_add`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_POINT_add.html pub fn add( &mut self, group: &EcGroupRef, @@ -148,6 +274,10 @@ impl EcPointRef { } /// Computes `q * m`, storing the result in `self`. + /// + /// OpenSSL documentation at [`EC_POINT_mul`] + /// + /// [`EC_POINT_mul`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_POINT_mul.html pub fn mul( &mut self, group: &EcGroupRef, @@ -208,6 +338,10 @@ impl EcPointRef { } /// Inverts `self`. + /// + /// OpenSSL documentation at [`EC_POINT_invert`] + /// + /// [`EC_POINT_invert`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_POINT_invert.html pub fn invert(&mut self, group: &EcGroupRef, ctx: &BigNumContextRef) -> Result<(), ErrorStack> { unsafe { cvt(ffi::EC_POINT_invert( @@ -219,6 +353,10 @@ impl EcPointRef { } /// Serializes the point to a binary representation. + /// + /// OpenSSL documentation at [`EC_POINT_point2oct`] + /// + /// [`EC_POINT_point2oct`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_POINT_point2oct.html pub fn to_bytes( &self, group: &EcGroupRef, @@ -255,6 +393,10 @@ impl EcPointRef { } /// Determines if this point is equal to another. + /// + /// OpenSSL doucmentation at [`EC_POINT_cmp`] + /// + /// [`EC_POINT_cmp`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_POINT_cmp.html pub fn eq( &self, group: &EcGroupRef, @@ -272,7 +414,12 @@ impl EcPointRef { } } - /// Place affine coordinates of a curve over a prime field in the provided x and y BigNum's + /// Place affine coordinates of a curve over a prime field in the provided + /// `x` and `y` `BigNum`s + /// + /// OpenSSL documentation at [`EC_POINT_get_affine_coordinates_GFp`] + /// + /// [`EC_POINT_get_affine_coordinates_GFp`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_POINT_get_affine_coordinates_GFp.html pub fn affine_coordinates_gfp( &self, group: &EcGroupRef, @@ -291,7 +438,12 @@ impl EcPointRef { } } - /// Place affine coordinates of a curve over a binary field in the provided x and y BigNum's + /// Place affine coordinates of a curve over a binary field in the provided + /// `x` and `y` `BigNum`s + /// + /// OpenSSL documentation at [`EC_POINT_get_affine_coordinates_GF2m`] + /// + /// [`EC_POINT_get_affine_coordinates_GF2m`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_POINT_get_affine_coordinates_GF2m.html #[cfg(not(osslconf = "OPENSSL_NO_EC2M"))] pub fn affine_coordinates_gf2m( &self, @@ -314,10 +466,19 @@ impl EcPointRef { impl EcPoint { /// Creates a new point on the specified curve. + /// + /// OpenSSL documentation at [`EC_POINT_new`] + /// + /// [`EC_POINT_new`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_POINT_new.html pub fn new(group: &EcGroupRef) -> Result { unsafe { cvt_p(ffi::EC_POINT_new(group.as_ptr())).map(EcPoint) } } + /// Creates point from a binary representation + /// + /// OpenSSL documentation at [`EC_POINT_oct2point`] + /// + /// [`EC_POINT_oct2point`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_POINT_oct2point.html pub fn from_bytes( group: &EcGroupRef, buf: &[u8], @@ -341,7 +502,15 @@ foreign_type! { type CType = ffi::EC_KEY; fn drop = ffi::EC_KEY_free; + /// Public and optional Private key on the given curve + /// + /// OpenSSL documentation at [`EC_KEY_new`] + /// + /// [`EC_KEY_new`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_KEY_new.html pub struct EcKey; + /// Reference to [`EcKey`] + /// + /// [`EcKey`]: struct.EcKey.html pub struct EcKeyRef; } @@ -349,6 +518,11 @@ impl EcKeyRef { private_key_to_pem!(ffi::PEM_write_bio_ECPrivateKey); private_key_to_der!(ffi::i2d_ECPrivateKey); + /// Return [`EcGroup`] of the `EcKey` + /// + /// OpenSSL documentation at [`EC_KEY_get0_group`] + /// + /// [`EC_KEY_get0_group`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_KEY_get0_group.html pub fn group(&self) -> Option<&EcGroupRef> { unsafe { let ptr = ffi::EC_KEY_get0_group(self.as_ptr()); @@ -360,6 +534,11 @@ impl EcKeyRef { } } + /// Return [`EcPoint`] associated with the public key + /// + /// OpenSSL documentation at [`EC_KEY_get0_pubic_key`] + /// + /// [`EC_KEY_get0_pubic_key`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_KEY_get0_public_key.html pub fn public_key(&self) -> Option<&EcPointRef> { unsafe { let ptr = ffi::EC_KEY_get0_public_key(self.as_ptr()); @@ -371,6 +550,11 @@ impl EcKeyRef { } } + /// Return [`EcPoint`] associated with the private key + /// + /// OpenSSL documentation at [`EC_KEY_get0_private_key`] + /// + /// [`EC_KEY_get0_private_key`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_KEY_get0_private_key.html pub fn private_key(&self) -> Option<&BigNumRef> { unsafe { let ptr = ffi::EC_KEY_get0_private_key(self.as_ptr()); @@ -383,10 +567,15 @@ impl EcKeyRef { } /// Checks the key for validity. + /// + /// OpenSSL documenation at [`EC_KEY_check_key`] + /// + /// [`EC_KEY_check_key`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_KEY_check_key.html pub fn check_key(&self) -> Result<(), ErrorStack> { unsafe { cvt(ffi::EC_KEY_check_key(self.as_ptr())).map(|_| ()) } } + /// Create a copy of the `EcKey` to allow modification pub fn to_owned(&self) -> Result { unsafe { cvt_p(ffi::EC_KEY_dup(self.as_ptr())).map(EcKey) } } @@ -397,6 +586,10 @@ impl EcKey { /// /// It will not have an associated public or private key. This kind of key is primarily useful /// to be provided to the `set_tmp_ecdh` methods on `Ssl` and `SslContextBuilder`. + /// + /// OpenSSL documenation at [`EC_KEY_new_by_curve_name`] + /// + /// [`EC_KEY_new_by_curve_name`]: https://www.openssl.org/docs/man1.1.0/crypto/EC_KEY_new_by_curve_name.html pub fn from_curve_name(nid: Nid) -> Result { unsafe { init(); @@ -457,11 +650,18 @@ foreign_type! { type CType = ffi::EC_KEY; fn drop = ffi::EC_KEY_free; + /// Builder pattern for key generation + /// + /// Returns a `EcKeyBuilder` to be consumed by `build` pub struct EcKeyBuilder; + /// Reference to [`EcKeyBuilder`] + /// + /// [`EcKeyBuilder`]: struct.EcKeyBuilder.html pub struct EcKeyBuilderRef; } impl EcKeyBuilder { + /// Creates an empty `EcKeyBuilder` to be chained with additonal methods pub fn new() -> Result { unsafe { init(); @@ -469,6 +669,9 @@ impl EcKeyBuilder { } } + /// Consume the `EcKeyBuilder` and return [`EcKey`] + /// + /// [`EcKey`]: struct.EcKey.html pub fn build(self) -> EcKey { unsafe { let key = EcKey::from_ptr(self.as_ptr()); @@ -479,10 +682,14 @@ impl EcKeyBuilder { } impl EcKeyBuilderRef { + /// Set the [`EcGroup`] explicitly + /// + /// [`EcGroup`]: struct.EcGroup.html pub fn set_group(&mut self, group: &EcGroupRef) -> Result<&mut EcKeyBuilderRef, ErrorStack> { unsafe { cvt(ffi::EC_KEY_set_group(self.as_ptr(), group.as_ptr())).map(|_| self) } } + /// Set public key to given `EcPoint` pub fn set_public_key( &mut self, public_key: &EcPointRef, @@ -495,6 +702,7 @@ impl EcKeyBuilderRef { } } + /// Generate public and private keys. pub fn generate_key(&mut self) -> Result<&mut EcKeyBuilderRef, ErrorStack> { unsafe { cvt(ffi::EC_KEY_generate_key(self.as_ptr())).map(|_| self) } } @@ -524,7 +732,7 @@ impl EcKeyBuilderRef { mod test { use bn::{BigNum, BigNumContext}; use nid; - use data_encoding; + use data_encoding::BASE64URL_NOPAD; use super::*; #[test] @@ -603,10 +811,10 @@ mod test { #[test] fn key_from_affine_coordinates() { let group = EcGroup::from_curve_name(nid::X9_62_PRIME256V1).unwrap(); - let x = data_encoding::base64url::decode_nopad( + let x = BASE64URL_NOPAD.decode( "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4".as_bytes(), ).unwrap(); - let y = data_encoding::base64url::decode_nopad( + let y = BASE64URL_NOPAD.decode( "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM".as_bytes(), ).unwrap(); @@ -627,7 +835,7 @@ mod test { #[test] fn set_private_key() { let group = EcGroup::from_curve_name(nid::X9_62_PRIME256V1).unwrap(); - let d = data_encoding::base64url::decode_nopad( + let d = BASE64URL_NOPAD.decode( "870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE".as_bytes(), ).unwrap(); @@ -643,11 +851,13 @@ mod test { #[test] fn get_affine_coordinates() { - let raw_x = "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4"; - let raw_y = "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM"; let group = EcGroup::from_curve_name(nid::X9_62_PRIME256V1).unwrap(); - let x = data_encoding::base64url::decode_nopad(raw_x.as_bytes()).unwrap(); - let y = data_encoding::base64url::decode_nopad(raw_y.as_bytes()).unwrap(); + let x = BASE64URL_NOPAD.decode( + "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4".as_bytes(), + ).unwrap(); + let y = BASE64URL_NOPAD.decode( + "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM".as_bytes(), + ).unwrap(); let xbn = BigNum::from_slice(&x).unwrap(); let ybn = BigNum::from_slice(&y).unwrap(); diff --git a/openssl/src/error.rs b/openssl/src/error.rs index 9151c01b6d864c8d17226c79639939f2e611014d..5f3e21709c521b512fc83057d396ed6b044ddae3 100644 --- a/openssl/src/error.rs +++ b/openssl/src/error.rs @@ -1,3 +1,20 @@ +//! Errors returned by OpenSSL library. +//! +//! OpenSSL errors are stored in an `ErrorStack`. Most methods in the crate +//! returns a `Result` type. +//! +//! # Examples +//! +//! ``` +//! use openssl::error::ErrorStack; +//! use openssl::bn::BigNum; +//! +//! let an_error = BigNum::from_dec_str("Cannot parse letters"); +//! match an_error { +//! Ok(_) => (), +//! Err(e) => println!("Parsing Error: {:?}", e), +//! } +//! ``` use libc::{c_ulong, c_char, c_int}; use std::fmt; use std::error; @@ -9,6 +26,9 @@ use std::borrow::Cow; use ffi; +/// Collection of [`Error`]s from OpenSSL. +/// +/// [`Error`]: struct.Error.html #[derive(Debug, Clone)] pub struct ErrorStack(Vec); diff --git a/openssl/src/ssl/error.rs b/openssl/src/ssl/error.rs index db78e2c83020fd53c4148c2efc0dff761d8a670b..2244fd7f11b5254123a03bcc8535f7ae4b4e8c11 100644 --- a/openssl/src/ssl/error.rs +++ b/openssl/src/ssl/error.rs @@ -66,6 +66,33 @@ impl From for Error { } } +/// An error indicating that the operation can be immediately retried. +/// +/// OpenSSL's [`SSL_read`] and [`SSL_write`] functions can return `SSL_ERROR_WANT_READ` even when +/// the underlying socket is performing blocking IO in certain cases. When this happens, the +/// the operation can be immediately retried. +/// +/// To signal this event, the `io::Error` inside of [`Error::WantRead`] will be constructed around +/// a `RetryError`. +/// +/// [`SSL_read`]: https://www.openssl.org/docs/manmaster/man3/SSL_read.html +/// [`SSL_write`]: https://www.openssl.org/docs/manmaster/man3/SSL_write.html +/// [`Error::WantRead`]: enum.Error.html#variant.WantRead +#[derive(Debug)] +pub struct RetryError; + +impl fmt::Display for RetryError { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.write_str(error::Error::description(self)) + } +} + +impl error::Error for RetryError { + fn description(&self) -> &str { + "operation must be retried" + } +} + /// An error or intermediate state after a TLS handshake attempt. #[derive(Debug)] pub enum HandshakeError { diff --git a/openssl/src/ssl/mod.rs b/openssl/src/ssl/mod.rs index 01b49cb89428298c1ffdb591c5a8efd2bc6e3986..d3a5e428d65e583143205fa6f7979b91b3fc2774 100644 --- a/openssl/src/ssl/mod.rs +++ b/openssl/src/ssl/mod.rs @@ -72,7 +72,7 @@ //! ``` use ffi; use foreign_types::{ForeignType, ForeignTypeRef, Opaque}; -use libc::{c_int, c_void, c_long, c_ulong}; +use libc::{c_int, c_long, c_ulong, c_void}; use libc::{c_uchar, c_uint}; use std::any::Any; use std::any::TypeId; @@ -93,12 +93,12 @@ use std::slice; use std::str; use std::sync::Mutex; -use {init, cvt, cvt_p, cvt_n}; +use {cvt, cvt_n, cvt_p, init}; use dh::{Dh, DhRef}; use ec::EcKeyRef; #[cfg(any(all(feature = "v101", ossl101), all(feature = "v102", ossl102)))] use ec::EcKey; -use x509::{X509StoreContextRef, X509FileType, X509, X509Ref, X509VerifyError, X509Name}; +use x509::{X509, X509FileType, X509Name, X509Ref, X509StoreContextRef, X509VerifyError}; use x509::store::{X509StoreBuilderRef, X509StoreRef}; #[cfg(any(all(feature = "v102", ossl102), all(feature = "v110", ossl110)))] use x509::store::X509Store; @@ -111,9 +111,9 @@ use stack::{Stack, StackRef}; use ssl::bio::BioMethod; use ssl::callbacks::*; -pub use ssl::connector::{SslConnectorBuilder, SslConnector, SslAcceptorBuilder, SslAcceptor, - ConnectConfiguration}; -pub use ssl::error::{Error, HandshakeError}; +pub use ssl::connector::{ConnectConfiguration, SslAcceptor, SslAcceptorBuilder, SslConnector, + SslConnectorBuilder}; +pub use ssl::error::{Error, HandshakeError, RetryError}; mod error; mod callbacks; @@ -368,6 +368,7 @@ impl SslContextBuilder { /// registers a verification callback. pub fn set_verify_callback(&mut self, mode: SslVerifyMode, verify: F) where + // FIXME should take a mutable reference to the store F: Fn(bool, &X509StoreContextRef) -> bool + Any + 'static + Sync + Send, { unsafe { @@ -416,10 +417,8 @@ impl SslContextBuilder { pub fn set_verify_cert_store(&mut self, cert_store: X509Store) -> Result<(), ErrorStack> { unsafe { let ptr = cert_store.as_ptr(); - cvt( - ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), ptr) as - c_int, - )?; + cvt(ffi::SSL_CTX_set0_verify_cert_store(self.as_ptr(), ptr) + as c_int)?; mem::forget(cert_store); Ok(()) @@ -461,8 +460,9 @@ impl SslContextBuilder { 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(|_| ()) + cvt(ffi::SSL_CTX_set_tmp_ecdh(self.as_ptr(), key.as_ptr()) + as c_int) + .map(|_| ()) } } @@ -579,10 +579,7 @@ impl SslContextBuilder { /// `set_certificate` to a trusted root. pub fn add_extra_chain_cert(&mut self, cert: X509) -> Result<(), ErrorStack> { unsafe { - cvt(ffi::SSL_CTX_add_extra_chain_cert( - self.as_ptr(), - cert.as_ptr(), - ) as c_int)?; + cvt(ffi::SSL_CTX_add_extra_chain_cert(self.as_ptr(), cert.as_ptr()) as c_int)?; mem::forget(cert); Ok(()) } @@ -766,10 +763,9 @@ impl SslContextBuilder { Box::into_raw(callback) as *mut c_void, ); let f: unsafe extern "C" fn(_, _) -> _ = raw_tlsext_status::; - cvt(ffi::SSL_CTX_set_tlsext_status_cb( - self.as_ptr(), - Some(f), - ) as c_int).map(|_| ()) + cvt(ffi::SSL_CTX_set_tlsext_status_cb(self.as_ptr(), Some(f)) + as c_int) + .map(|_| ()) } } @@ -781,7 +777,8 @@ impl SslContextBuilder { #[cfg(not(osslconf = "OPENSSL_NO_PSK"))] pub fn set_psk_callback(&mut self, callback: F) where - F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result + F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) + -> Result + Any + 'static + Sync @@ -1140,6 +1137,7 @@ impl SslRef { /// chain is valid and `false` otherwise. pub fn set_verify_callback(&mut self, mode: SslVerifyMode, verify: F) where + // FIXME should take a mutable reference to the x509 store F: Fn(bool, &X509StoreContextRef) -> bool + Any + 'static + Sync + Send, { unsafe { @@ -1239,10 +1237,8 @@ impl SslRef { pub fn set_hostname(&mut self, hostname: &str) -> Result<(), ErrorStack> { let cstr = CString::new(hostname).unwrap(); unsafe { - cvt(ffi::SSL_set_tlsext_host_name( - self.as_ptr(), - cstr.as_ptr() as *mut _, - ) as c_int).map(|_| ()) + cvt(ffi::SSL_set_tlsext_host_name(self.as_ptr(), cstr.as_ptr() as *mut _) as c_int) + .map(|_| ()) } } @@ -1373,9 +1369,7 @@ impl SslRef { return None; } let meth = ffi::SSL_COMP_get_name(ptr); - Some( - str::from_utf8(CStr::from_ptr(meth as *const _).to_bytes()).unwrap(), - ) + Some(str::from_utf8(CStr::from_ptr(meth as *const _).to_bytes()).unwrap()) } } @@ -1392,9 +1386,7 @@ impl SslRef { return None; } - Some( - str::from_utf8(CStr::from_ptr(name as *const _).to_bytes()).unwrap(), - ) + Some(str::from_utf8(CStr::from_ptr(name as *const _).to_bytes()).unwrap()) } } @@ -1459,10 +1451,7 @@ impl SslRef { /// Sets the status response a client wishes the server to reply with. pub fn set_status_type(&mut self, type_: StatusType) -> Result<(), ErrorStack> { unsafe { - cvt(ffi::SSL_set_tlsext_status_type( - self.as_ptr(), - type_.as_raw(), - ) as c_int).map(|_| ()) + cvt(ffi::SSL_set_tlsext_status_type(self.as_ptr(), type_.as_raw()) as c_int).map(|_| ()) } } @@ -1494,7 +1483,8 @@ impl SslRef { self.as_ptr(), p as *mut c_uchar, response.len() as c_long, - ) as c_int).map(|_| ()) + ) as c_int) + .map(|_| ()) } } @@ -1561,19 +1551,16 @@ impl Ssl { Ok(stream) } else { match stream.make_error(ret) { - e @ Error::WantWrite(_) | - e @ Error::WantRead(_) => { + e @ Error::WantWrite(_) | e @ Error::WantRead(_) => { Err(HandshakeError::Interrupted(MidHandshakeSslStream { stream: stream, error: e, })) } - err => { - Err(HandshakeError::Failure(MidHandshakeSslStream { - stream: stream, - error: err, - })) - } + err => Err(HandshakeError::Failure(MidHandshakeSslStream { + stream: stream, + error: err, + })), } } } @@ -1594,19 +1581,16 @@ impl Ssl { Ok(stream) } else { match stream.make_error(ret) { - e @ Error::WantWrite(_) | - e @ Error::WantRead(_) => { + e @ Error::WantWrite(_) | e @ Error::WantRead(_) => { Err(HandshakeError::Interrupted(MidHandshakeSslStream { stream: stream, error: e, })) } - err => { - Err(HandshakeError::Failure(MidHandshakeSslStream { - stream: stream, - error: err, - })) - } + err => Err(HandshakeError::Failure(MidHandshakeSslStream { + stream: stream, + error: err, + })), } } } @@ -1652,8 +1636,7 @@ impl MidHandshakeSslStream { Ok(self.stream) } else { match self.stream.make_error(ret) { - e @ Error::WantWrite(_) | - e @ Error::WantRead(_) => { + e @ Error::WantWrite(_) | e @ Error::WantRead(_) => { self.error = e; Err(HandshakeError::Interrupted(self)) } @@ -1668,6 +1651,7 @@ impl MidHandshakeSslStream { /// A stream wrapper which handles SSL encryption for an underlying stream. pub struct SslStream { + // FIXME use ManuallyDrop ssl: Ssl, _method: BioMethod, // NOTE: this *must* be after the Ssl field so things drop right _p: PhantomData, @@ -1718,6 +1702,7 @@ impl SslStream { Ok(ret as usize) } else { match self.make_error(ret) { + // FIXME only do this in read // Don't treat unexpected EOFs as errors when reading Error::Stream(ref e) if e.kind() == io::ErrorKind::ConnectionAborted => Ok(0), e => Err(e), @@ -1775,12 +1760,10 @@ impl SslStream { if errs.errors().is_empty() { match self.get_bio_error() { Some(err) => Error::Stream(err), - None => { - Error::Stream(io::Error::new( - io::ErrorKind::ConnectionAborted, - "unexpected EOF observed", - )) - } + None => Error::Stream(io::Error::new( + io::ErrorKind::ConnectionAborted, + "unexpected EOF observed", + )), } } else { Error::Ssl(errs) @@ -1790,33 +1773,24 @@ impl SslStream { ffi::SSL_ERROR_WANT_WRITE => { let err = match self.get_bio_error() { Some(err) => err, - None => { - io::Error::new( - io::ErrorKind::Other, - "BUG: got an SSL_ERROR_WANT_WRITE with no error in the BIO", - ) - } + None => io::Error::new( + io::ErrorKind::Other, + "BUG: got an SSL_ERROR_WANT_WRITE with no error in the BIO", + ), }; Error::WantWrite(err) } ffi::SSL_ERROR_WANT_READ => { let err = match self.get_bio_error() { Some(err) => err, - None => { - io::Error::new( - io::ErrorKind::Other, - "BUG: got an SSL_ERROR_WANT_WRITE with no error in the BIO", - ) - } + None => io::Error::new(io::ErrorKind::Other, RetryError), }; Error::WantRead(err) } - err => { - Error::Stream(io::Error::new( - io::ErrorKind::InvalidData, - format!("unexpected error {}", err), - )) - } + err => Error::Stream(io::Error::new( + io::ErrorKind::InvalidData, + format!("unexpected error {}", err), + )), } } @@ -1859,25 +1833,34 @@ impl SslStream { impl Read for SslStream { fn read(&mut self, buf: &mut [u8]) -> io::Result { - match self.ssl_read(buf) { - Ok(n) => Ok(n), - Err(Error::ZeroReturn) => Ok(0), - Err(Error::Stream(e)) => Err(e), - Err(Error::WantRead(e)) => Err(e), - Err(Error::WantWrite(e)) => Err(e), - Err(e) => Err(io::Error::new(io::ErrorKind::Other, e)), + loop { + match self.ssl_read(buf) { + Ok(n) => return Ok(n), + Err(Error::ZeroReturn) => return Ok(0), + Err(Error::WantRead(ref e)) + if e.get_ref().map_or(false, |e| e.is::()) => {} + Err(Error::Stream(e)) | Err(Error::WantRead(e)) | Err(Error::WantWrite(e)) => { + return Err(e); + } + Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)), + } } } } impl Write for SslStream { fn write(&mut self, buf: &[u8]) -> io::Result { - self.ssl_write(buf).map_err(|e| match e { - Error::Stream(e) => e, - Error::WantRead(e) => e, - Error::WantWrite(e) => e, - e => io::Error::new(io::ErrorKind::Other, e), - }) + loop { + match self.ssl_write(buf) { + Ok(n) => return Ok(n), + Err(Error::WantRead(ref e)) + if e.get_ref().map_or(false, |e| e.is::()) => {} + Err(Error::Stream(e)) | Err(Error::WantRead(e)) | Err(Error::WantWrite(e)) => { + return Err(e); + } + Err(e) => return Err(io::Error::new(io::ErrorKind::Other, e)), + } + } } fn flush(&mut self) -> io::Result<()> { @@ -1902,8 +1885,8 @@ mod compat { use ffi; use libc::c_int; - pub use ffi::{SSL_CTX_get_options, SSL_CTX_set_options, SSL_CTX_clear_options, SSL_CTX_up_ref, - SSL_SESSION_get_master_key, SSL_is_server, SSL_SESSION_up_ref}; + pub use ffi::{SSL_CTX_clear_options, SSL_CTX_get_options, SSL_CTX_set_options, SSL_CTX_up_ref, + SSL_SESSION_get_master_key, SSL_SESSION_up_ref, SSL_is_server}; pub unsafe fn get_new_idx(f: ffi::CRYPTO_EX_free) -> c_int { ffi::CRYPTO_get_ex_new_index( @@ -1942,7 +1925,7 @@ mod compat { use std::ptr; use ffi; - use libc::{self, c_long, c_ulong, c_int, size_t, c_uchar}; + use libc::{self, c_int, c_long, c_uchar, c_ulong, size_t}; pub unsafe fn SSL_CTX_get_options(ctx: *const ffi::SSL_CTX) -> c_ulong { ffi::SSL_CTX_ctrl(ctx as *mut _, ffi::SSL_CTRL_OPTIONS, 0, ptr::null_mut()) as c_ulong diff --git a/openssl/src/symm.rs b/openssl/src/symm.rs index 6fb61996d98e674910a085f5df0f237abc4967f2..e109b2a7d527d81d8a8ac84662b2eb5ec1151e36 100644 --- a/openssl/src/symm.rs +++ b/openssl/src/symm.rs @@ -1,3 +1,27 @@ +//! High level interface to certain symmetric ciphers. +//! +//! # Examples +//! +//! Encrypt data in AES128 CBC mode +//! +//! ``` +//! use openssl::symm::{encrypt, Cipher}; +//! +//! let cipher = Cipher::aes_128_cbc(); +//! let data = b"Some Crypto Text"; +//! let key = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"; +//! let iv = b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07"; +//! let ciphertext = encrypt( +//! cipher, +//! key, +//! Some(iv), +//! data).unwrap(); +//! +//! assert_eq!( +//! b"\xB4\xB9\xE7\x30\xD6\xD6\xF7\xDE\x77\x3F\x1C\xFF\xB3\x3E\x44\x5A\x91\xD7\x27\x62\x87\x4D\ +//! \xFB\x3C\x5E\xC4\x59\x72\x4A\xF4\x7C\xA1", +//! &ciphertext[..]); +//! ``` use std::cmp; use std::ptr; use libc::c_int; @@ -12,6 +36,11 @@ pub enum Mode { Decrypt, } +/// Represents a particular cipher algorithm. +/// +/// See OpenSSL doc at [`EVP_EncryptInit`] for more information on each algorithms. +/// +/// [`EVP_EncryptInit`]: https://www.openssl.org/docs/man1.1.0/crypto/EVP_EncryptInit.html #[derive(Copy, Clone)] pub struct Cipher(*const ffi::EVP_CIPHER); @@ -153,17 +182,78 @@ impl Cipher { } /// Represents a symmetric cipher context. +/// +/// Padding is enabled by default. +/// +/// # Examples +/// +/// Encrypt some plaintext in chunks, then decrypt the ciphertext back into plaintext, in AES 128 +/// CBC mode. +/// +/// ``` +/// use openssl::symm::{Cipher, Mode, Crypter}; +/// +/// let plaintexts: [&[u8]; 2] = [b"Some Stream of", b" Crypto Text"]; +/// let key = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"; +/// let iv = b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07"; +/// let data_len = plaintexts.iter().fold(0, |sum, x| sum + x.len()); +/// +/// // Create a cipher context for encryption. +/// let mut encrypter = Crypter::new( +/// Cipher::aes_128_cbc(), +/// Mode::Encrypt, +/// key, +/// Some(iv)).unwrap(); +/// +/// let block_size = Cipher::aes_128_cbc().block_size(); +/// let mut ciphertext = vec![0; data_len + block_size]; +/// +/// // Encrypt 2 chunks of plaintexts successively. +/// let mut count = encrypter.update(plaintexts[0], &mut ciphertext).unwrap(); +/// count += encrypter.update(plaintexts[1], &mut ciphertext[count..]).unwrap(); +/// count += encrypter.finalize(&mut ciphertext[count..]).unwrap(); +/// ciphertext.truncate(count); +/// +/// assert_eq!( +/// b"\x0F\x21\x83\x7E\xB2\x88\x04\xAF\xD9\xCC\xE2\x03\x49\xB4\x88\xF6\xC4\x61\x0E\x32\x1C\xF9\ +/// \x0D\x66\xB1\xE6\x2C\x77\x76\x18\x8D\x99", +/// &ciphertext[..] +/// ); +/// +/// +/// // Let's pretend we don't know the plaintext, and now decrypt the ciphertext. +/// let data_len = ciphertext.len(); +/// let ciphertexts = [&ciphertext[..9], &ciphertext[9..]]; +/// +/// // Create a cipher context for decryption. +/// let mut decrypter = Crypter::new( +/// Cipher::aes_128_cbc(), +/// Mode::Decrypt, +/// key, +/// Some(iv)).unwrap(); +/// let mut plaintext = vec![0; data_len + block_size]; +/// +/// // Decrypt 2 chunks of ciphertexts successively. +/// let mut count = decrypter.update(ciphertexts[0], &mut plaintext).unwrap(); +/// count += decrypter.update(ciphertexts[1], &mut plaintext[count..]).unwrap(); +/// count += decrypter.finalize(&mut plaintext[count..]).unwrap(); +/// plaintext.truncate(count); +/// +/// assert_eq!(b"Some Stream of Crypto Text", &plaintext[..]); +/// ``` pub struct Crypter { ctx: *mut ffi::EVP_CIPHER_CTX, block_size: usize, } impl Crypter { - /// Creates a new `Crypter`. + /// Creates a new `Crypter`. The initialisation vector, `iv`, is not necesarry for certain + /// types of `Cipher`. /// /// # Panics /// - /// Panics if an IV is required by the cipher but not provided. + /// Panics if an IV is required by the cipher but not provided. Also make sure that the key + /// and IV size are appropriate for your cipher. pub fn new( t: Cipher, mode: Mode, @@ -358,8 +448,36 @@ 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. +/// Encrypts data in one go, and returns the encrypted data. +/// +/// Data is encrypted using the specified cipher type `t` in encrypt mode with the specified `key` +/// and initailization vector `iv`. +/// +/// This is a convenient interface to `Crypter` to encrypt all data in one go. To encrypt a stream +/// of data increamentally , use `Crypter` instead. +/// +/// # Examples +/// +/// Encrypt data in AES128 CBC mode +/// +/// ``` +/// use openssl::symm::{encrypt, Cipher}; +/// +/// let cipher = Cipher::aes_128_cbc(); +/// let data = b"Some Crypto Text"; +/// let key = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"; +/// let iv = b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07"; +/// let ciphertext = encrypt( +/// cipher, +/// key, +/// Some(iv), +/// data).unwrap(); +/// +/// assert_eq!( +/// b"\xB4\xB9\xE7\x30\xD6\xD6\xF7\xDE\x77\x3F\x1C\xFF\xB3\x3E\x44\x5A\x91\xD7\x27\x62\x87\x4D\ +/// \xFB\x3C\x5E\xC4\x59\x72\x4A\xF4\x7C\xA1", +/// &ciphertext[..]); +/// ``` pub fn encrypt( t: Cipher, key: &[u8], @@ -369,8 +487,36 @@ pub fn encrypt( cipher(t, Mode::Encrypt, key, iv, data) } -/// Decrypts data, using the specified crypter type in decrypt mode with the -/// specified key and iv; returns the resulting (decrypted) data. +/// Decrypts data in one go, and returns the decrypted data. +/// +/// Data is decrypted using the specified cipher type `t` in decrypt mode with the specified `key` +/// and initailization vector `iv`. +/// +/// This is a convenient interface to `Crypter` to decrypt all data in one go. To decrypt a stream +/// of data increamentally , use `Crypter` instead. +/// +/// # Examples +/// +/// Decrypt data in AES256 ECB mode +/// +/// ``` +/// use openssl::symm::{decrypt, Cipher}; +/// +/// let cipher = Cipher::aes_128_cbc(); +/// let data = b"\xB4\xB9\xE7\x30\xD6\xD6\xF7\xDE\x77\x3F\x1C\xFF\xB3\x3E\x44\x5A\x91\xD7\x27\x62\ +/// \x87\x4D\xFB\x3C\x5E\xC4\x59\x72\x4A\xF4\x7C\xA1"; +/// let key = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"; +/// let iv = b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07"; +/// let ciphertext = decrypt( +/// cipher, +/// key, +/// Some(iv), +/// data).unwrap(); +/// +/// assert_eq!( +/// b"Some Crypto Text", +/// &ciphertext[..]); +/// ``` pub fn decrypt( t: Cipher, key: &[u8], diff --git a/systest/build.rs b/systest/build.rs index 7418cca0dbcd6f23ea4ca18176f7428421b3a29a..af8ebbc145bef813b818f3eb4d90bb426a492c32 100644 --- a/systest/build.rs +++ b/systest/build.rs @@ -5,6 +5,7 @@ use std::env; fn main() { let mut cfg = ctest::TestGenerator::new(); let target = env::var("TARGET").unwrap(); + let mut is_libressl = false; if let Ok(out) = env::var("DEP_OPENSSL_INCLUDE") { cfg.include(&out); @@ -24,6 +25,7 @@ fn main() { if let Ok(_) = env::var("DEP_OPENSSL_LIBRESSL") { cfg.cfg("libressl", None); + is_libressl = true; } else if let Ok(version) = env::var("DEP_OPENSSL_VERSION") { cfg.cfg(&format!("ossl{}", version), None); } @@ -41,12 +43,6 @@ fn main() { } } - let has_cms_h = if let Ok(version) = env::var("DEP_OPENSSL_LIBRESSL_VERSION") { - version != "261" && version != "262" - } else { - true - }; - cfg.header("openssl/comp.h") .header("openssl/dh.h") .header("openssl/ossl_typ.h") @@ -64,7 +60,7 @@ fn main() { .header("openssl/aes.h") .header("openssl/ocsp.h"); - if has_cms_h { + if !is_libressl { cfg.header("openssl/cms.h"); }