chore: add vendor dependencies for kauma build
This commit is contained in:
parent
7c94e5d8fb
commit
067ef6141c
1758 changed files with 398473 additions and 0 deletions
1
vendor/openssl/.cargo-checksum.json
vendored
Normal file
1
vendor/openssl/.cargo-checksum.json
vendored
Normal file
File diff suppressed because one or more lines are too long
1004
vendor/openssl/CHANGELOG.md
vendored
Normal file
1004
vendor/openssl/CHANGELOG.md
vendored
Normal file
File diff suppressed because it is too large
Load diff
79
vendor/openssl/Cargo.toml
vendored
Normal file
79
vendor/openssl/Cargo.toml
vendored
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
||||
#
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g., crates.io) dependencies.
|
||||
#
|
||||
# If you are reading this file be aware that the original Cargo.toml
|
||||
# will likely look very different (and much more reasonable).
|
||||
# See Cargo.toml.orig for the original contents.
|
||||
|
||||
[package]
|
||||
edition = "2021"
|
||||
rust-version = "1.63.0"
|
||||
name = "openssl"
|
||||
version = "0.10.68"
|
||||
authors = ["Steven Fackler <sfackler@gmail.com>"]
|
||||
build = "build.rs"
|
||||
autobins = false
|
||||
autoexamples = false
|
||||
autotests = false
|
||||
autobenches = false
|
||||
description = "OpenSSL bindings"
|
||||
readme = "README.md"
|
||||
keywords = [
|
||||
"crypto",
|
||||
"tls",
|
||||
"ssl",
|
||||
"dtls",
|
||||
]
|
||||
categories = [
|
||||
"cryptography",
|
||||
"api-bindings",
|
||||
]
|
||||
license = "Apache-2.0"
|
||||
repository = "https://github.com/sfackler/rust-openssl"
|
||||
|
||||
[lib]
|
||||
name = "openssl"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[[example]]
|
||||
name = "mk_certs"
|
||||
path = "examples/mk_certs.rs"
|
||||
|
||||
[dependencies.bitflags]
|
||||
version = "2.2.1"
|
||||
|
||||
[dependencies.cfg-if]
|
||||
version = "1.0"
|
||||
|
||||
[dependencies.ffi]
|
||||
version = "0.9.104"
|
||||
package = "openssl-sys"
|
||||
|
||||
[dependencies.foreign-types]
|
||||
version = "0.3.1"
|
||||
|
||||
[dependencies.libc]
|
||||
version = "0.2"
|
||||
|
||||
[dependencies.once_cell]
|
||||
version = "1.5.2"
|
||||
|
||||
[dependencies.openssl-macros]
|
||||
version = "0.1.0"
|
||||
|
||||
[dev-dependencies.hex]
|
||||
version = "0.4"
|
||||
|
||||
[features]
|
||||
bindgen = ["ffi/bindgen"]
|
||||
default = []
|
||||
unstable_boringssl = ["ffi/unstable_boringssl"]
|
||||
v101 = []
|
||||
v102 = []
|
||||
v110 = []
|
||||
v111 = []
|
||||
vendored = ["ffi/vendored"]
|
||||
15
vendor/openssl/LICENSE
vendored
Normal file
15
vendor/openssl/LICENSE
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
Copyright 2011-2017 Google Inc.
|
||||
2013 Jack Lloyd
|
||||
2013-2014 Steven Fackler
|
||||
|
||||
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.
|
||||
22
vendor/openssl/README.md
vendored
Normal file
22
vendor/openssl/README.md
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# rust-openssl
|
||||
|
||||
[](https://crates.io/crates/openssl)
|
||||
|
||||
OpenSSL bindings for the Rust programming language.
|
||||
|
||||
[Documentation](https://docs.rs/openssl).
|
||||
|
||||
## Release Support
|
||||
|
||||
The current supported release of `openssl` is 0.10 and `openssl-sys` is 0.9.
|
||||
|
||||
New major versions will be published at most once per year. After a new
|
||||
release, the previous major version will be partially supported with bug
|
||||
fixes for 3 months, after which support will be dropped entirely.
|
||||
|
||||
### Contribution
|
||||
|
||||
Unless you explicitly state otherwise, any contribution intentionally
|
||||
submitted for inclusion in the work by you, as defined in the Apache-2.0
|
||||
license, shall be dual licensed under the terms of both the Apache License,
|
||||
Version 2.0 and the MIT license without any additional terms or conditions.
|
||||
164
vendor/openssl/build.rs
vendored
Normal file
164
vendor/openssl/build.rs
vendored
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
#![allow(
|
||||
clippy::inconsistent_digit_grouping,
|
||||
clippy::uninlined_format_args,
|
||||
clippy::unusual_byte_groupings
|
||||
)]
|
||||
|
||||
use std::env;
|
||||
|
||||
fn main() {
|
||||
println!("cargo:rustc-check-cfg=cfg(osslconf, values(\"OPENSSL_NO_OCB\", \"OPENSSL_NO_SM4\", \"OPENSSL_NO_SEED\", \"OPENSSL_NO_CHACHA\", \"OPENSSL_NO_CAST\", \"OPENSSL_NO_IDEA\", \"OPENSSL_NO_CAMELLIA\", \"OPENSSL_NO_RC4\", \"OPENSSL_NO_BF\", \"OPENSSL_NO_PSK\", \"OPENSSL_NO_DEPRECATED_3_0\", \"OPENSSL_NO_SCRYPT\", \"OPENSSL_NO_SM3\", \"OPENSSL_NO_RMD160\", \"OPENSSL_NO_EC2M\", \"OPENSSL_NO_OCSP\", \"OPENSSL_NO_CMS\", \"OPENSSL_NO_EC\", \"OPENSSL_NO_ARGON2\"))");
|
||||
|
||||
println!("cargo:rustc-check-cfg=cfg(libressl)");
|
||||
println!("cargo:rustc-check-cfg=cfg(boringssl)");
|
||||
|
||||
println!("cargo:rustc-check-cfg=cfg(libressl250)");
|
||||
println!("cargo:rustc-check-cfg=cfg(libressl251)");
|
||||
println!("cargo:rustc-check-cfg=cfg(libressl261)");
|
||||
println!("cargo:rustc-check-cfg=cfg(libressl270)");
|
||||
println!("cargo:rustc-check-cfg=cfg(libressl271)");
|
||||
println!("cargo:rustc-check-cfg=cfg(libressl273)");
|
||||
println!("cargo:rustc-check-cfg=cfg(libressl280)");
|
||||
println!("cargo:rustc-check-cfg=cfg(libressl291)");
|
||||
println!("cargo:rustc-check-cfg=cfg(libressl310)");
|
||||
println!("cargo:rustc-check-cfg=cfg(libressl321)");
|
||||
println!("cargo:rustc-check-cfg=cfg(libressl332)");
|
||||
println!("cargo:rustc-check-cfg=cfg(libressl340)");
|
||||
println!("cargo:rustc-check-cfg=cfg(libressl350)");
|
||||
println!("cargo:rustc-check-cfg=cfg(libressl360)");
|
||||
println!("cargo:rustc-check-cfg=cfg(libressl361)");
|
||||
println!("cargo:rustc-check-cfg=cfg(libressl370)");
|
||||
println!("cargo:rustc-check-cfg=cfg(libressl380)");
|
||||
println!("cargo:rustc-check-cfg=cfg(libressl382)");
|
||||
println!("cargo:rustc-check-cfg=cfg(libressl390)");
|
||||
println!("cargo:rustc-check-cfg=cfg(libressl400)");
|
||||
|
||||
println!("cargo:rustc-check-cfg=cfg(ossl101)");
|
||||
println!("cargo:rustc-check-cfg=cfg(ossl102)");
|
||||
println!("cargo:rustc-check-cfg=cfg(ossl110)");
|
||||
println!("cargo:rustc-check-cfg=cfg(ossl110g)");
|
||||
println!("cargo:rustc-check-cfg=cfg(ossl110h)");
|
||||
println!("cargo:rustc-check-cfg=cfg(ossl111)");
|
||||
println!("cargo:rustc-check-cfg=cfg(ossl111d)");
|
||||
println!("cargo:rustc-check-cfg=cfg(ossl300)");
|
||||
println!("cargo:rustc-check-cfg=cfg(ossl310)");
|
||||
println!("cargo:rustc-check-cfg=cfg(ossl320)");
|
||||
println!("cargo:rustc-check-cfg=cfg(ossl330)");
|
||||
|
||||
if env::var("DEP_OPENSSL_LIBRESSL").is_ok() {
|
||||
println!("cargo:rustc-cfg=libressl");
|
||||
}
|
||||
|
||||
if env::var("DEP_OPENSSL_BORINGSSL").is_ok() {
|
||||
println!("cargo:rustc-cfg=boringssl");
|
||||
}
|
||||
|
||||
if let Ok(v) = env::var("DEP_OPENSSL_LIBRESSL_VERSION_NUMBER") {
|
||||
let version = u64::from_str_radix(&v, 16).unwrap();
|
||||
|
||||
if version >= 0x2_05_00_00_0 {
|
||||
println!("cargo:rustc-cfg=libressl250");
|
||||
}
|
||||
if version >= 0x2_05_01_00_0 {
|
||||
println!("cargo:rustc-cfg=libressl251");
|
||||
}
|
||||
if version >= 0x2_06_01_00_0 {
|
||||
println!("cargo:rustc-cfg=libressl261");
|
||||
}
|
||||
if version >= 0x2_07_00_00_0 {
|
||||
println!("cargo:rustc-cfg=libressl270");
|
||||
}
|
||||
if version >= 0x2_07_01_00_0 {
|
||||
println!("cargo:rustc-cfg=libressl271");
|
||||
}
|
||||
if version >= 0x2_07_03_00_0 {
|
||||
println!("cargo:rustc-cfg=libressl273");
|
||||
}
|
||||
if version >= 0x2_08_00_00_0 {
|
||||
println!("cargo:rustc-cfg=libressl280");
|
||||
}
|
||||
if version >= 0x2_09_01_00_0 {
|
||||
println!("cargo:rustc-cfg=libressl291");
|
||||
}
|
||||
if version >= 0x3_01_00_00_0 {
|
||||
println!("cargo:rustc-cfg=libressl310");
|
||||
}
|
||||
if version >= 0x3_02_01_00_0 {
|
||||
println!("cargo:rustc-cfg=libressl321");
|
||||
}
|
||||
if version >= 0x3_03_02_00_0 {
|
||||
println!("cargo:rustc-cfg=libressl332");
|
||||
}
|
||||
if version >= 0x3_04_00_00_0 {
|
||||
println!("cargo:rustc-cfg=libressl340");
|
||||
}
|
||||
if version >= 0x3_05_00_00_0 {
|
||||
println!("cargo:rustc-cfg=libressl350");
|
||||
}
|
||||
if version >= 0x3_06_00_00_0 {
|
||||
println!("cargo:rustc-cfg=libressl360");
|
||||
}
|
||||
if version >= 0x3_06_01_00_0 {
|
||||
println!("cargo:rustc-cfg=libressl361");
|
||||
}
|
||||
if version >= 0x3_07_00_00_0 {
|
||||
println!("cargo:rustc-cfg=libressl370");
|
||||
}
|
||||
if version >= 0x3_08_00_00_0 {
|
||||
println!("cargo:rustc-cfg=libressl380");
|
||||
}
|
||||
if version >= 0x3_08_02_00_0 {
|
||||
println!("cargo:rustc-cfg=libressl382");
|
||||
}
|
||||
if version >= 0x3_09_00_00_0 {
|
||||
println!("cargo:rustc-cfg=libressl390");
|
||||
}
|
||||
if version >= 0x4_00_00_00_0 {
|
||||
println!("cargo:rustc-cfg=libressl400");
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(vars) = env::var("DEP_OPENSSL_CONF") {
|
||||
for var in vars.split(',') {
|
||||
println!("cargo:rustc-cfg=osslconf=\"{}\"", var);
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(version) = env::var("DEP_OPENSSL_VERSION_NUMBER") {
|
||||
let version = u64::from_str_radix(&version, 16).unwrap();
|
||||
|
||||
if version >= 0x1_00_01_00_0 {
|
||||
println!("cargo:rustc-cfg=ossl101");
|
||||
}
|
||||
if version >= 0x1_00_02_00_0 {
|
||||
println!("cargo:rustc-cfg=ossl102");
|
||||
}
|
||||
if version >= 0x1_01_00_00_0 {
|
||||
println!("cargo:rustc-cfg=ossl110");
|
||||
}
|
||||
if version >= 0x1_01_00_07_0 {
|
||||
println!("cargo:rustc-cfg=ossl110g");
|
||||
}
|
||||
if version >= 0x1_01_00_08_0 {
|
||||
println!("cargo:rustc-cfg=ossl110h");
|
||||
}
|
||||
if version >= 0x1_01_01_00_0 {
|
||||
println!("cargo:rustc-cfg=ossl111");
|
||||
}
|
||||
if version >= 0x1_01_01_04_0 {
|
||||
println!("cargo:rustc-cfg=ossl111d");
|
||||
}
|
||||
if version >= 0x3_00_00_00_0 {
|
||||
println!("cargo:rustc-cfg=ossl300");
|
||||
}
|
||||
if version >= 0x3_01_00_00_0 {
|
||||
println!("cargo:rustc-cfg=ossl310");
|
||||
}
|
||||
if version >= 0x3_02_00_00_0 {
|
||||
println!("cargo:rustc-cfg=ossl320");
|
||||
}
|
||||
if version >= 0x3_03_00_00_0 {
|
||||
println!("cargo:rustc-cfg=ossl330");
|
||||
}
|
||||
}
|
||||
}
|
||||
160
vendor/openssl/examples/mk_certs.rs
vendored
Normal file
160
vendor/openssl/examples/mk_certs.rs
vendored
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
#![allow(clippy::uninlined_format_args)]
|
||||
|
||||
//! A program that generates ca certs, certs verified by the ca, and public
|
||||
//! and private keys.
|
||||
|
||||
use openssl::asn1::Asn1Time;
|
||||
use openssl::bn::{BigNum, MsbOption};
|
||||
use openssl::error::ErrorStack;
|
||||
use openssl::hash::MessageDigest;
|
||||
use openssl::pkey::{PKey, PKeyRef, Private};
|
||||
use openssl::rsa::Rsa;
|
||||
use openssl::x509::extension::{
|
||||
AuthorityKeyIdentifier, BasicConstraints, KeyUsage, SubjectAlternativeName,
|
||||
SubjectKeyIdentifier,
|
||||
};
|
||||
use openssl::x509::{X509NameBuilder, X509Ref, X509Req, X509ReqBuilder, X509VerifyResult, X509};
|
||||
|
||||
/// Make a CA certificate and private key
|
||||
fn mk_ca_cert() -> Result<(X509, PKey<Private>), ErrorStack> {
|
||||
let rsa = Rsa::generate(2048)?;
|
||||
let key_pair = PKey::from_rsa(rsa)?;
|
||||
|
||||
let mut x509_name = X509NameBuilder::new()?;
|
||||
x509_name.append_entry_by_text("C", "US")?;
|
||||
x509_name.append_entry_by_text("ST", "TX")?;
|
||||
x509_name.append_entry_by_text("O", "Some CA organization")?;
|
||||
x509_name.append_entry_by_text("CN", "ca test")?;
|
||||
let x509_name = x509_name.build();
|
||||
|
||||
let mut cert_builder = X509::builder()?;
|
||||
cert_builder.set_version(2)?;
|
||||
let serial_number = {
|
||||
let mut serial = BigNum::new()?;
|
||||
serial.rand(159, MsbOption::MAYBE_ZERO, false)?;
|
||||
serial.to_asn1_integer()?
|
||||
};
|
||||
cert_builder.set_serial_number(&serial_number)?;
|
||||
cert_builder.set_subject_name(&x509_name)?;
|
||||
cert_builder.set_issuer_name(&x509_name)?;
|
||||
cert_builder.set_pubkey(&key_pair)?;
|
||||
let not_before = Asn1Time::days_from_now(0)?;
|
||||
cert_builder.set_not_before(¬_before)?;
|
||||
let not_after = Asn1Time::days_from_now(365)?;
|
||||
cert_builder.set_not_after(¬_after)?;
|
||||
|
||||
cert_builder.append_extension(BasicConstraints::new().critical().ca().build()?)?;
|
||||
cert_builder.append_extension(
|
||||
KeyUsage::new()
|
||||
.critical()
|
||||
.key_cert_sign()
|
||||
.crl_sign()
|
||||
.build()?,
|
||||
)?;
|
||||
|
||||
let subject_key_identifier =
|
||||
SubjectKeyIdentifier::new().build(&cert_builder.x509v3_context(None, None))?;
|
||||
cert_builder.append_extension(subject_key_identifier)?;
|
||||
|
||||
cert_builder.sign(&key_pair, MessageDigest::sha256())?;
|
||||
let cert = cert_builder.build();
|
||||
|
||||
Ok((cert, key_pair))
|
||||
}
|
||||
|
||||
/// Make a X509 request with the given private key
|
||||
fn mk_request(key_pair: &PKey<Private>) -> Result<X509Req, ErrorStack> {
|
||||
let mut req_builder = X509ReqBuilder::new()?;
|
||||
req_builder.set_pubkey(key_pair)?;
|
||||
|
||||
let mut x509_name = X509NameBuilder::new()?;
|
||||
x509_name.append_entry_by_text("C", "US")?;
|
||||
x509_name.append_entry_by_text("ST", "TX")?;
|
||||
x509_name.append_entry_by_text("O", "Some organization")?;
|
||||
x509_name.append_entry_by_text("CN", "www.example.com")?;
|
||||
let x509_name = x509_name.build();
|
||||
req_builder.set_subject_name(&x509_name)?;
|
||||
|
||||
req_builder.sign(key_pair, MessageDigest::sha256())?;
|
||||
let req = req_builder.build();
|
||||
Ok(req)
|
||||
}
|
||||
|
||||
/// Make a certificate and private key signed by the given CA cert and private key
|
||||
fn mk_ca_signed_cert(
|
||||
ca_cert: &X509Ref,
|
||||
ca_key_pair: &PKeyRef<Private>,
|
||||
) -> Result<(X509, PKey<Private>), ErrorStack> {
|
||||
let rsa = Rsa::generate(2048)?;
|
||||
let key_pair = PKey::from_rsa(rsa)?;
|
||||
|
||||
let req = mk_request(&key_pair)?;
|
||||
|
||||
let mut cert_builder = X509::builder()?;
|
||||
cert_builder.set_version(2)?;
|
||||
let serial_number = {
|
||||
let mut serial = BigNum::new()?;
|
||||
serial.rand(159, MsbOption::MAYBE_ZERO, false)?;
|
||||
serial.to_asn1_integer()?
|
||||
};
|
||||
cert_builder.set_serial_number(&serial_number)?;
|
||||
cert_builder.set_subject_name(req.subject_name())?;
|
||||
cert_builder.set_issuer_name(ca_cert.subject_name())?;
|
||||
cert_builder.set_pubkey(&key_pair)?;
|
||||
let not_before = Asn1Time::days_from_now(0)?;
|
||||
cert_builder.set_not_before(¬_before)?;
|
||||
let not_after = Asn1Time::days_from_now(365)?;
|
||||
cert_builder.set_not_after(¬_after)?;
|
||||
|
||||
cert_builder.append_extension(BasicConstraints::new().build()?)?;
|
||||
|
||||
cert_builder.append_extension(
|
||||
KeyUsage::new()
|
||||
.critical()
|
||||
.non_repudiation()
|
||||
.digital_signature()
|
||||
.key_encipherment()
|
||||
.build()?,
|
||||
)?;
|
||||
|
||||
let subject_key_identifier =
|
||||
SubjectKeyIdentifier::new().build(&cert_builder.x509v3_context(Some(ca_cert), None))?;
|
||||
cert_builder.append_extension(subject_key_identifier)?;
|
||||
|
||||
let auth_key_identifier = AuthorityKeyIdentifier::new()
|
||||
.keyid(false)
|
||||
.issuer(false)
|
||||
.build(&cert_builder.x509v3_context(Some(ca_cert), None))?;
|
||||
cert_builder.append_extension(auth_key_identifier)?;
|
||||
|
||||
let subject_alt_name = SubjectAlternativeName::new()
|
||||
.dns("*.example.com")
|
||||
.dns("hello.com")
|
||||
.build(&cert_builder.x509v3_context(Some(ca_cert), None))?;
|
||||
cert_builder.append_extension(subject_alt_name)?;
|
||||
|
||||
cert_builder.sign(ca_key_pair, MessageDigest::sha256())?;
|
||||
let cert = cert_builder.build();
|
||||
|
||||
Ok((cert, key_pair))
|
||||
}
|
||||
|
||||
fn real_main() -> Result<(), ErrorStack> {
|
||||
let (ca_cert, ca_key_pair) = mk_ca_cert()?;
|
||||
let (cert, _key_pair) = mk_ca_signed_cert(&ca_cert, &ca_key_pair)?;
|
||||
|
||||
// Verify that this cert was issued by this ca
|
||||
match ca_cert.issued(&cert) {
|
||||
X509VerifyResult::OK => println!("Certificate verified!"),
|
||||
ver_err => println!("Failed to verify certificate: {}", ver_err),
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
match real_main() {
|
||||
Ok(()) => println!("Finished."),
|
||||
Err(e) => println!("Error: {}", e),
|
||||
};
|
||||
}
|
||||
319
vendor/openssl/src/aes.rs
vendored
Normal file
319
vendor/openssl/src/aes.rs
vendored
Normal file
|
|
@ -0,0 +1,319 @@
|
|||
//! Low level AES IGE and key wrapping functionality
|
||||
//!
|
||||
//! AES ECB, CBC, XTS, CTR, CFB, GCM and other conventional symmetric encryption
|
||||
//! modes are found in [`symm`]. This is the implementation of AES IGE and key wrapping
|
||||
//!
|
||||
//! Advanced Encryption Standard (AES) provides symmetric key cipher that
|
||||
//! the same key is used to encrypt and decrypt data. This implementation
|
||||
//! uses 128, 192, or 256 bit keys. This module provides functions to
|
||||
//! create a new key with [`new_encrypt`] and perform an encryption/decryption
|
||||
//! using that key with [`aes_ige`].
|
||||
//!
|
||||
//! [`new_encrypt`]: struct.AesKey.html#method.new_encrypt
|
||||
//! [`aes_ige`]: fn.aes_ige.html
|
||||
//!
|
||||
//! The [`symm`] module should be used in preference to this module in most cases.
|
||||
//! The IGE block cipher is a non-traditional cipher mode. More traditional AES
|
||||
//! encryption methods are found in the [`Crypter`] and [`Cipher`] structs.
|
||||
//!
|
||||
//! [`symm`]: ../symm/index.html
|
||||
//! [`Crypter`]: ../symm/struct.Crypter.html
|
||||
//! [`Cipher`]: ../symm/struct.Cipher.html
|
||||
//!
|
||||
//! # Examples
|
||||
|
||||
#![cfg_attr(
|
||||
all(not(boringssl), not(osslconf = "OPENSSL_NO_DEPRECATED_3_0")),
|
||||
doc = r#"\
|
||||
## AES IGE
|
||||
```rust
|
||||
use openssl::aes::{AesKey, aes_ige};
|
||||
use openssl::symm::Mode;
|
||||
|
||||
let key = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F";
|
||||
let plaintext = b"\x12\x34\x56\x78\x90\x12\x34\x56\x12\x34\x56\x78\x90\x12\x34\x56";
|
||||
let mut iv = *b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\
|
||||
\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F";
|
||||
|
||||
let key = AesKey::new_encrypt(key).unwrap();
|
||||
let mut output = [0u8; 16];
|
||||
aes_ige(plaintext, &mut output, &key, &mut iv, Mode::Encrypt);
|
||||
assert_eq!(output, *b"\xa6\xad\x97\x4d\x5c\xea\x1d\x36\xd2\xf3\x67\x98\x09\x07\xed\x32");
|
||||
```"#
|
||||
)]
|
||||
|
||||
//!
|
||||
//! ## Key wrapping
|
||||
//! ```rust
|
||||
//! use openssl::aes::{AesKey, unwrap_key, wrap_key};
|
||||
//!
|
||||
//! let kek = b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F";
|
||||
//! let key_to_wrap = b"\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF";
|
||||
//!
|
||||
//! let enc_key = AesKey::new_encrypt(kek).unwrap();
|
||||
//! let mut ciphertext = [0u8; 24];
|
||||
//! wrap_key(&enc_key, None, &mut ciphertext, &key_to_wrap[..]).unwrap();
|
||||
//! let dec_key = AesKey::new_decrypt(kek).unwrap();
|
||||
//! let mut orig_key = [0u8; 16];
|
||||
//! unwrap_key(&dec_key, None, &mut orig_key, &ciphertext[..]).unwrap();
|
||||
//!
|
||||
//! assert_eq!(&orig_key[..], &key_to_wrap[..]);
|
||||
//! ```
|
||||
//!
|
||||
use cfg_if::cfg_if;
|
||||
use libc::{c_int, c_uint};
|
||||
use std::mem::MaybeUninit;
|
||||
use std::ptr;
|
||||
|
||||
#[cfg(not(boringssl))]
|
||||
use crate::symm::Mode;
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
/// Provides Error handling for parsing keys.
|
||||
#[derive(Debug)]
|
||||
pub struct KeyError(());
|
||||
|
||||
/// The key used to encrypt or decrypt cipher blocks.
|
||||
pub struct AesKey(ffi::AES_KEY);
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(boringssl)] {
|
||||
type AesBitType = c_uint;
|
||||
type AesSizeType = usize;
|
||||
} else {
|
||||
type AesBitType = c_int;
|
||||
type AesSizeType = c_uint;
|
||||
}
|
||||
}
|
||||
|
||||
impl AesKey {
|
||||
/// Prepares a key for encryption.
|
||||
///
|
||||
/// # Failure
|
||||
///
|
||||
/// Returns an error if the key is not 128, 192, or 256 bits.
|
||||
#[corresponds(AES_set_encrypt_key)]
|
||||
pub fn new_encrypt(key: &[u8]) -> Result<AesKey, KeyError> {
|
||||
unsafe {
|
||||
assert!(key.len() <= c_int::MAX as usize / 8);
|
||||
|
||||
let mut aes_key = MaybeUninit::uninit();
|
||||
let r = ffi::AES_set_encrypt_key(
|
||||
key.as_ptr() as *const _,
|
||||
key.len() as AesBitType * 8,
|
||||
aes_key.as_mut_ptr(),
|
||||
);
|
||||
if r == 0 {
|
||||
Ok(AesKey(aes_key.assume_init()))
|
||||
} else {
|
||||
Err(KeyError(()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Prepares a key for decryption.
|
||||
///
|
||||
/// # Failure
|
||||
///
|
||||
/// Returns an error if the key is not 128, 192, or 256 bits.
|
||||
#[corresponds(AES_set_decrypt_key)]
|
||||
pub fn new_decrypt(key: &[u8]) -> Result<AesKey, KeyError> {
|
||||
unsafe {
|
||||
assert!(key.len() <= c_int::MAX as usize / 8);
|
||||
|
||||
let mut aes_key = MaybeUninit::uninit();
|
||||
let r = ffi::AES_set_decrypt_key(
|
||||
key.as_ptr() as *const _,
|
||||
key.len() as AesBitType * 8,
|
||||
aes_key.as_mut_ptr(),
|
||||
);
|
||||
|
||||
if r == 0 {
|
||||
Ok(AesKey(aes_key.assume_init()))
|
||||
} else {
|
||||
Err(KeyError(()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Performs AES IGE encryption or decryption
|
||||
///
|
||||
/// AES IGE (Infinite Garble Extension) is a form of AES block cipher utilized in
|
||||
/// OpenSSL. Infinite Garble refers to propagating forward errors. IGE, like other
|
||||
/// block ciphers implemented for AES requires an initialization vector. The IGE mode
|
||||
/// allows a stream of blocks to be encrypted or decrypted without having the entire
|
||||
/// plaintext available. For more information, visit [AES IGE Encryption].
|
||||
///
|
||||
/// This block cipher uses 16 byte blocks. The rust implementation will panic
|
||||
/// if the input or output does not meet this 16-byte boundary. Attention must
|
||||
/// be made in this low level implementation to pad the value to the 128-bit boundary.
|
||||
///
|
||||
/// [AES IGE Encryption]: http://www.links.org/files/openssl-ige.pdf
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `in_` is not the same length as `out`, if that length is not a multiple of 16, or if
|
||||
/// `iv` is not at least 32 bytes.
|
||||
#[cfg(not(boringssl))]
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
|
||||
#[corresponds(AES_ige_encrypt)]
|
||||
pub fn aes_ige(in_: &[u8], out: &mut [u8], key: &AesKey, iv: &mut [u8], mode: Mode) {
|
||||
unsafe {
|
||||
assert!(in_.len() == out.len());
|
||||
assert!(in_.len() % ffi::AES_BLOCK_SIZE as usize == 0);
|
||||
assert!(iv.len() >= ffi::AES_BLOCK_SIZE as usize * 2);
|
||||
|
||||
let mode = match mode {
|
||||
Mode::Encrypt => ffi::AES_ENCRYPT,
|
||||
Mode::Decrypt => ffi::AES_DECRYPT,
|
||||
};
|
||||
ffi::AES_ige_encrypt(
|
||||
in_.as_ptr() as *const _,
|
||||
out.as_mut_ptr() as *mut _,
|
||||
in_.len(),
|
||||
&key.0,
|
||||
iv.as_mut_ptr() as *mut _,
|
||||
mode,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Wrap a key, according to [RFC 3394](https://tools.ietf.org/html/rfc3394)
|
||||
///
|
||||
/// * `key`: The key-encrypting-key to use. Must be a encrypting key
|
||||
/// * `iv`: The IV to use. You must use the same IV for both wrapping and unwrapping
|
||||
/// * `out`: The output buffer to store the ciphertext
|
||||
/// * `in_`: The input buffer, storing the key to be wrapped
|
||||
///
|
||||
/// Returns the number of bytes written into `out`
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if either `out` or `in_` do not have sizes that are a multiple of 8, or if
|
||||
/// `out` is not 8 bytes longer than `in_`
|
||||
#[corresponds(AES_wrap_key)]
|
||||
pub fn wrap_key(
|
||||
key: &AesKey,
|
||||
iv: Option<[u8; 8]>,
|
||||
out: &mut [u8],
|
||||
in_: &[u8],
|
||||
) -> Result<usize, KeyError> {
|
||||
unsafe {
|
||||
assert!(out.len() >= in_.len() + 8); // Ciphertext is 64 bits longer (see 2.2.1)
|
||||
|
||||
let written = ffi::AES_wrap_key(
|
||||
&key.0 as *const _ as *mut _, // this is safe, the implementation only uses the key as a const pointer.
|
||||
iv.as_ref()
|
||||
.map_or(ptr::null(), |iv| iv.as_ptr() as *const _),
|
||||
out.as_ptr() as *mut _,
|
||||
in_.as_ptr() as *const _,
|
||||
in_.len() as AesSizeType,
|
||||
);
|
||||
if written <= 0 {
|
||||
Err(KeyError(()))
|
||||
} else {
|
||||
Ok(written as usize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Unwrap a key, according to [RFC 3394](https://tools.ietf.org/html/rfc3394)
|
||||
///
|
||||
/// * `key`: The key-encrypting-key to decrypt the wrapped key. Must be a decrypting key
|
||||
/// * `iv`: The same IV used for wrapping the key
|
||||
/// * `out`: The buffer to write the unwrapped key to
|
||||
/// * `in_`: The input ciphertext
|
||||
///
|
||||
/// Returns the number of bytes written into `out`
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if either `out` or `in_` do not have sizes that are a multiple of 8, or
|
||||
/// if `in_` is not 8 bytes longer than `out`
|
||||
#[corresponds(AES_unwrap_key)]
|
||||
pub fn unwrap_key(
|
||||
key: &AesKey,
|
||||
iv: Option<[u8; 8]>,
|
||||
out: &mut [u8],
|
||||
in_: &[u8],
|
||||
) -> Result<usize, KeyError> {
|
||||
unsafe {
|
||||
assert!(out.len() + 8 <= in_.len());
|
||||
|
||||
let written = ffi::AES_unwrap_key(
|
||||
&key.0 as *const _ as *mut _, // this is safe, the implementation only uses the key as a const pointer.
|
||||
iv.as_ref()
|
||||
.map_or(ptr::null(), |iv| iv.as_ptr() as *const _),
|
||||
out.as_ptr() as *mut _,
|
||||
in_.as_ptr() as *const _,
|
||||
in_.len() as AesSizeType,
|
||||
);
|
||||
|
||||
if written <= 0 {
|
||||
Err(KeyError(()))
|
||||
} else {
|
||||
Ok(written as usize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use hex::FromHex;
|
||||
|
||||
use super::*;
|
||||
#[cfg(not(boringssl))]
|
||||
use crate::symm::Mode;
|
||||
|
||||
// From https://www.mgp25.com/AESIGE/
|
||||
#[test]
|
||||
#[cfg(not(boringssl))]
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
|
||||
fn ige_vector_1() {
|
||||
let raw_key = "000102030405060708090A0B0C0D0E0F";
|
||||
let raw_iv = "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F";
|
||||
let raw_pt = "0000000000000000000000000000000000000000000000000000000000000000";
|
||||
let raw_ct = "1A8519A6557BE652E9DA8E43DA4EF4453CF456B4CA488AA383C79C98B34797CB";
|
||||
|
||||
let key = AesKey::new_encrypt(&Vec::from_hex(raw_key).unwrap()).unwrap();
|
||||
let mut iv = Vec::from_hex(raw_iv).unwrap();
|
||||
let pt = Vec::from_hex(raw_pt).unwrap();
|
||||
let ct = Vec::from_hex(raw_ct).unwrap();
|
||||
|
||||
let mut ct_actual = vec![0; ct.len()];
|
||||
aes_ige(&pt, &mut ct_actual, &key, &mut iv, Mode::Encrypt);
|
||||
assert_eq!(ct_actual, ct);
|
||||
|
||||
let key = AesKey::new_decrypt(&Vec::from_hex(raw_key).unwrap()).unwrap();
|
||||
let mut iv = Vec::from_hex(raw_iv).unwrap();
|
||||
let mut pt_actual = vec![0; pt.len()];
|
||||
aes_ige(&ct, &mut pt_actual, &key, &mut iv, Mode::Decrypt);
|
||||
assert_eq!(pt_actual, pt);
|
||||
}
|
||||
|
||||
// from the RFC https://tools.ietf.org/html/rfc3394#section-2.2.3
|
||||
#[test]
|
||||
fn test_wrap_unwrap() {
|
||||
let raw_key = Vec::from_hex("000102030405060708090A0B0C0D0E0F").unwrap();
|
||||
let key_data = Vec::from_hex("00112233445566778899AABBCCDDEEFF").unwrap();
|
||||
let expected_ciphertext =
|
||||
Vec::from_hex("1FA68B0A8112B447AEF34BD8FB5A7B829D3E862371D2CFE5").unwrap();
|
||||
|
||||
let enc_key = AesKey::new_encrypt(&raw_key).unwrap();
|
||||
let mut wrapped = [0; 24];
|
||||
assert_eq!(
|
||||
wrap_key(&enc_key, None, &mut wrapped, &key_data).unwrap(),
|
||||
24
|
||||
);
|
||||
assert_eq!(&wrapped[..], &expected_ciphertext[..]);
|
||||
|
||||
let dec_key = AesKey::new_decrypt(&raw_key).unwrap();
|
||||
let mut unwrapped = [0; 16];
|
||||
assert_eq!(
|
||||
unwrap_key(&dec_key, None, &mut unwrapped, &wrapped).unwrap(),
|
||||
16
|
||||
);
|
||||
assert_eq!(&unwrapped[..], &key_data[..]);
|
||||
}
|
||||
}
|
||||
910
vendor/openssl/src/asn1.rs
vendored
Normal file
910
vendor/openssl/src/asn1.rs
vendored
Normal file
|
|
@ -0,0 +1,910 @@
|
|||
#![deny(missing_docs)]
|
||||
|
||||
//! Defines the format of certificates
|
||||
//!
|
||||
//! This module is used by [`x509`] and other certificate building functions
|
||||
//! to describe time, strings, and objects.
|
||||
//!
|
||||
//! Abstract Syntax Notation One is an interface description language.
|
||||
//! The specification comes from [X.208] by OSI, and rewritten in X.680.
|
||||
//! ASN.1 describes properties of an object with a type set. Those types
|
||||
//! can be atomic, structured, choice, and other (CHOICE and ANY). These
|
||||
//! types are expressed as a number and the assignment operator ::= gives
|
||||
//! the type a name.
|
||||
//!
|
||||
//! The implementation here provides a subset of the ASN.1 types that OpenSSL
|
||||
//! uses, especially in the properties of a certificate used in HTTPS.
|
||||
//!
|
||||
//! [X.208]: https://www.itu.int/rec/T-REC-X.208-198811-W/en
|
||||
//! [`x509`]: ../x509/struct.X509Builder.html
|
||||
//!
|
||||
//! ## Examples
|
||||
//!
|
||||
//! ```
|
||||
//! use openssl::asn1::Asn1Time;
|
||||
//! let tomorrow = Asn1Time::days_from_now(1);
|
||||
//! ```
|
||||
use cfg_if::cfg_if;
|
||||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
use libc::{c_char, c_int, c_long, time_t};
|
||||
use std::cmp::Ordering;
|
||||
use std::convert::TryInto;
|
||||
use std::ffi::CString;
|
||||
use std::fmt;
|
||||
use std::ptr;
|
||||
use std::str;
|
||||
|
||||
use crate::bio::MemBio;
|
||||
use crate::bn::{BigNum, BigNumRef};
|
||||
use crate::error::ErrorStack;
|
||||
use crate::nid::Nid;
|
||||
use crate::stack::Stackable;
|
||||
use crate::string::OpensslString;
|
||||
use crate::{cvt, cvt_p, util};
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::ASN1_GENERALIZEDTIME;
|
||||
fn drop = ffi::ASN1_GENERALIZEDTIME_free;
|
||||
|
||||
/// Non-UTC representation of time
|
||||
///
|
||||
/// If a time can be represented by UTCTime, UTCTime is used
|
||||
/// otherwise, ASN1_GENERALIZEDTIME is used. This would be, for
|
||||
/// example outside the year range of 1950-2049.
|
||||
///
|
||||
/// [ASN1_GENERALIZEDTIME_set] documentation from OpenSSL provides
|
||||
/// further details of implementation. Note: these docs are from the master
|
||||
/// branch as documentation on the 1.1.0 branch did not include this page.
|
||||
///
|
||||
/// [ASN1_GENERALIZEDTIME_set]: https://www.openssl.org/docs/manmaster/man3/ASN1_GENERALIZEDTIME_set.html
|
||||
pub struct Asn1GeneralizedTime;
|
||||
/// Reference to a [`Asn1GeneralizedTime`]
|
||||
///
|
||||
/// [`Asn1GeneralizedTime`]: struct.Asn1GeneralizedTime.html
|
||||
pub struct Asn1GeneralizedTimeRef;
|
||||
}
|
||||
|
||||
impl fmt::Display for Asn1GeneralizedTimeRef {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
unsafe {
|
||||
let mem_bio = match MemBio::new() {
|
||||
Err(_) => return f.write_str("error"),
|
||||
Ok(m) => m,
|
||||
};
|
||||
let print_result = cvt(ffi::ASN1_GENERALIZEDTIME_print(
|
||||
mem_bio.as_ptr(),
|
||||
self.as_ptr(),
|
||||
));
|
||||
match print_result {
|
||||
Err(_) => f.write_str("error"),
|
||||
Ok(_) => f.write_str(str::from_utf8_unchecked(mem_bio.get_buf())),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The type of an ASN.1 value.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct Asn1Type(c_int);
|
||||
|
||||
#[allow(missing_docs)] // no need to document the constants
|
||||
impl Asn1Type {
|
||||
pub const EOC: Asn1Type = Asn1Type(ffi::V_ASN1_EOC);
|
||||
|
||||
pub const BOOLEAN: Asn1Type = Asn1Type(ffi::V_ASN1_BOOLEAN);
|
||||
|
||||
pub const INTEGER: Asn1Type = Asn1Type(ffi::V_ASN1_INTEGER);
|
||||
|
||||
pub const BIT_STRING: Asn1Type = Asn1Type(ffi::V_ASN1_BIT_STRING);
|
||||
|
||||
pub const OCTET_STRING: Asn1Type = Asn1Type(ffi::V_ASN1_OCTET_STRING);
|
||||
|
||||
pub const NULL: Asn1Type = Asn1Type(ffi::V_ASN1_NULL);
|
||||
|
||||
pub const OBJECT: Asn1Type = Asn1Type(ffi::V_ASN1_OBJECT);
|
||||
|
||||
pub const OBJECT_DESCRIPTOR: Asn1Type = Asn1Type(ffi::V_ASN1_OBJECT_DESCRIPTOR);
|
||||
|
||||
pub const EXTERNAL: Asn1Type = Asn1Type(ffi::V_ASN1_EXTERNAL);
|
||||
|
||||
pub const REAL: Asn1Type = Asn1Type(ffi::V_ASN1_REAL);
|
||||
|
||||
pub const ENUMERATED: Asn1Type = Asn1Type(ffi::V_ASN1_ENUMERATED);
|
||||
|
||||
pub const UTF8STRING: Asn1Type = Asn1Type(ffi::V_ASN1_UTF8STRING);
|
||||
|
||||
pub const SEQUENCE: Asn1Type = Asn1Type(ffi::V_ASN1_SEQUENCE);
|
||||
|
||||
pub const SET: Asn1Type = Asn1Type(ffi::V_ASN1_SET);
|
||||
|
||||
pub const NUMERICSTRING: Asn1Type = Asn1Type(ffi::V_ASN1_NUMERICSTRING);
|
||||
|
||||
pub const PRINTABLESTRING: Asn1Type = Asn1Type(ffi::V_ASN1_PRINTABLESTRING);
|
||||
|
||||
pub const T61STRING: Asn1Type = Asn1Type(ffi::V_ASN1_T61STRING);
|
||||
|
||||
pub const TELETEXSTRING: Asn1Type = Asn1Type(ffi::V_ASN1_TELETEXSTRING);
|
||||
|
||||
pub const VIDEOTEXSTRING: Asn1Type = Asn1Type(ffi::V_ASN1_VIDEOTEXSTRING);
|
||||
|
||||
pub const IA5STRING: Asn1Type = Asn1Type(ffi::V_ASN1_IA5STRING);
|
||||
|
||||
pub const UTCTIME: Asn1Type = Asn1Type(ffi::V_ASN1_UTCTIME);
|
||||
|
||||
pub const GENERALIZEDTIME: Asn1Type = Asn1Type(ffi::V_ASN1_GENERALIZEDTIME);
|
||||
|
||||
pub const GRAPHICSTRING: Asn1Type = Asn1Type(ffi::V_ASN1_GRAPHICSTRING);
|
||||
|
||||
pub const ISO64STRING: Asn1Type = Asn1Type(ffi::V_ASN1_ISO64STRING);
|
||||
|
||||
pub const VISIBLESTRING: Asn1Type = Asn1Type(ffi::V_ASN1_VISIBLESTRING);
|
||||
|
||||
pub const GENERALSTRING: Asn1Type = Asn1Type(ffi::V_ASN1_GENERALSTRING);
|
||||
|
||||
pub const UNIVERSALSTRING: Asn1Type = Asn1Type(ffi::V_ASN1_UNIVERSALSTRING);
|
||||
|
||||
pub const BMPSTRING: Asn1Type = Asn1Type(ffi::V_ASN1_BMPSTRING);
|
||||
|
||||
/// Constructs an `Asn1Type` from a raw OpenSSL value.
|
||||
pub fn from_raw(value: c_int) -> Self {
|
||||
Asn1Type(value)
|
||||
}
|
||||
|
||||
/// Returns the raw OpenSSL value represented by this type.
|
||||
pub fn as_raw(&self) -> c_int {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// Difference between two ASN1 times.
|
||||
///
|
||||
/// This `struct` is created by the [`diff`] method on [`Asn1TimeRef`]. See its
|
||||
/// documentation for more.
|
||||
///
|
||||
/// [`diff`]: struct.Asn1TimeRef.html#method.diff
|
||||
/// [`Asn1TimeRef`]: struct.Asn1TimeRef.html
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
#[cfg(any(ossl102, boringssl))]
|
||||
pub struct TimeDiff {
|
||||
/// Difference in days
|
||||
pub days: c_int,
|
||||
/// Difference in seconds.
|
||||
///
|
||||
/// This is always less than the number of seconds in a day.
|
||||
pub secs: c_int,
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::ASN1_TIME;
|
||||
fn drop = ffi::ASN1_TIME_free;
|
||||
/// Time storage and comparison
|
||||
///
|
||||
/// Asn1Time should be used to store and share time information
|
||||
/// using certificates. If Asn1Time is set using a string, it must
|
||||
/// be in either YYMMDDHHMMSSZ, YYYYMMDDHHMMSSZ, or another ASN.1 format.
|
||||
///
|
||||
/// [ASN_TIME_set] documentation at OpenSSL explains the ASN.1 implementation
|
||||
/// used by OpenSSL.
|
||||
///
|
||||
/// [ASN_TIME_set]: https://www.openssl.org/docs/manmaster/crypto/ASN1_TIME_set.html
|
||||
pub struct Asn1Time;
|
||||
/// Reference to an [`Asn1Time`]
|
||||
///
|
||||
/// [`Asn1Time`]: struct.Asn1Time.html
|
||||
pub struct Asn1TimeRef;
|
||||
}
|
||||
|
||||
impl Asn1TimeRef {
|
||||
/// Find difference between two times
|
||||
#[corresponds(ASN1_TIME_diff)]
|
||||
#[cfg(any(ossl102, boringssl))]
|
||||
pub fn diff(&self, compare: &Self) -> Result<TimeDiff, ErrorStack> {
|
||||
let mut days = 0;
|
||||
let mut secs = 0;
|
||||
let other = compare.as_ptr();
|
||||
|
||||
let err = unsafe { ffi::ASN1_TIME_diff(&mut days, &mut secs, self.as_ptr(), other) };
|
||||
|
||||
match err {
|
||||
0 => Err(ErrorStack::get()),
|
||||
_ => Ok(TimeDiff { days, secs }),
|
||||
}
|
||||
}
|
||||
|
||||
/// Compare two times
|
||||
#[corresponds(ASN1_TIME_compare)]
|
||||
#[cfg(any(ossl102, boringssl))]
|
||||
pub fn compare(&self, other: &Self) -> Result<Ordering, ErrorStack> {
|
||||
let d = self.diff(other)?;
|
||||
if d.days > 0 || d.secs > 0 {
|
||||
return Ok(Ordering::Less);
|
||||
}
|
||||
if d.days < 0 || d.secs < 0 {
|
||||
return Ok(Ordering::Greater);
|
||||
}
|
||||
|
||||
Ok(Ordering::Equal)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(ossl102, boringssl))]
|
||||
impl PartialEq for Asn1TimeRef {
|
||||
fn eq(&self, other: &Asn1TimeRef) -> bool {
|
||||
self.diff(other)
|
||||
.map(|t| t.days == 0 && t.secs == 0)
|
||||
.unwrap_or(false)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(ossl102, boringssl))]
|
||||
impl PartialEq<Asn1Time> for Asn1TimeRef {
|
||||
fn eq(&self, other: &Asn1Time) -> bool {
|
||||
self.diff(other)
|
||||
.map(|t| t.days == 0 && t.secs == 0)
|
||||
.unwrap_or(false)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(ossl102, boringssl))]
|
||||
impl PartialEq<Asn1Time> for &Asn1TimeRef {
|
||||
fn eq(&self, other: &Asn1Time) -> bool {
|
||||
self.diff(other)
|
||||
.map(|t| t.days == 0 && t.secs == 0)
|
||||
.unwrap_or(false)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(ossl102, boringssl))]
|
||||
impl PartialOrd for Asn1TimeRef {
|
||||
fn partial_cmp(&self, other: &Asn1TimeRef) -> Option<Ordering> {
|
||||
self.compare(other).ok()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(ossl102, boringssl))]
|
||||
impl PartialOrd<Asn1Time> for Asn1TimeRef {
|
||||
fn partial_cmp(&self, other: &Asn1Time) -> Option<Ordering> {
|
||||
self.compare(other).ok()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(ossl102, boringssl))]
|
||||
impl PartialOrd<Asn1Time> for &Asn1TimeRef {
|
||||
fn partial_cmp(&self, other: &Asn1Time) -> Option<Ordering> {
|
||||
self.compare(other).ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Asn1TimeRef {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
unsafe {
|
||||
let mem_bio = match MemBio::new() {
|
||||
Err(_) => return f.write_str("error"),
|
||||
Ok(m) => m,
|
||||
};
|
||||
let print_result = cvt(ffi::ASN1_TIME_print(mem_bio.as_ptr(), self.as_ptr()));
|
||||
match print_result {
|
||||
Err(_) => f.write_str("error"),
|
||||
Ok(_) => f.write_str(str::from_utf8_unchecked(mem_bio.get_buf())),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Asn1TimeRef {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(&self.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl Asn1Time {
|
||||
#[corresponds(ASN1_TIME_new)]
|
||||
fn new() -> Result<Asn1Time, ErrorStack> {
|
||||
ffi::init();
|
||||
|
||||
unsafe {
|
||||
let handle = cvt_p(ffi::ASN1_TIME_new())?;
|
||||
Ok(Asn1Time::from_ptr(handle))
|
||||
}
|
||||
}
|
||||
|
||||
#[corresponds(X509_gmtime_adj)]
|
||||
fn from_period(period: c_long) -> Result<Asn1Time, ErrorStack> {
|
||||
ffi::init();
|
||||
|
||||
unsafe {
|
||||
let handle = 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, ErrorStack> {
|
||||
Asn1Time::from_period(days as c_long * 60 * 60 * 24)
|
||||
}
|
||||
|
||||
/// Creates a new time from the specified `time_t` value
|
||||
#[corresponds(ASN1_TIME_set)]
|
||||
pub fn from_unix(time: time_t) -> Result<Asn1Time, ErrorStack> {
|
||||
ffi::init();
|
||||
|
||||
unsafe {
|
||||
let handle = cvt_p(ffi::ASN1_TIME_set(ptr::null_mut(), time))?;
|
||||
Ok(Asn1Time::from_ptr(handle))
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new time corresponding to the specified ASN1 time string.
|
||||
#[corresponds(ASN1_TIME_set_string)]
|
||||
#[allow(clippy::should_implement_trait)]
|
||||
pub fn from_str(s: &str) -> Result<Asn1Time, ErrorStack> {
|
||||
unsafe {
|
||||
let s = CString::new(s).unwrap();
|
||||
|
||||
let time = Asn1Time::new()?;
|
||||
cvt(ffi::ASN1_TIME_set_string(time.as_ptr(), s.as_ptr()))?;
|
||||
|
||||
Ok(time)
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new time corresponding to the specified X509 time string.
|
||||
///
|
||||
/// Requires BoringSSL or OpenSSL 1.1.1 or newer.
|
||||
#[corresponds(ASN1_TIME_set_string_X509)]
|
||||
#[cfg(any(ossl111, boringssl))]
|
||||
pub fn from_str_x509(s: &str) -> Result<Asn1Time, ErrorStack> {
|
||||
unsafe {
|
||||
let s = CString::new(s).unwrap();
|
||||
|
||||
let time = Asn1Time::new()?;
|
||||
cvt(ffi::ASN1_TIME_set_string_X509(time.as_ptr(), s.as_ptr()))?;
|
||||
|
||||
Ok(time)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(ossl102, boringssl))]
|
||||
impl PartialEq for Asn1Time {
|
||||
fn eq(&self, other: &Asn1Time) -> bool {
|
||||
self.diff(other)
|
||||
.map(|t| t.days == 0 && t.secs == 0)
|
||||
.unwrap_or(false)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(ossl102, boringssl))]
|
||||
impl PartialEq<Asn1TimeRef> for Asn1Time {
|
||||
fn eq(&self, other: &Asn1TimeRef) -> bool {
|
||||
self.diff(other)
|
||||
.map(|t| t.days == 0 && t.secs == 0)
|
||||
.unwrap_or(false)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(ossl102, boringssl))]
|
||||
impl<'a> PartialEq<&'a Asn1TimeRef> for Asn1Time {
|
||||
fn eq(&self, other: &&'a Asn1TimeRef) -> bool {
|
||||
self.diff(other)
|
||||
.map(|t| t.days == 0 && t.secs == 0)
|
||||
.unwrap_or(false)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(ossl102, boringssl))]
|
||||
impl PartialOrd for Asn1Time {
|
||||
fn partial_cmp(&self, other: &Asn1Time) -> Option<Ordering> {
|
||||
self.compare(other).ok()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(ossl102, boringssl))]
|
||||
impl PartialOrd<Asn1TimeRef> for Asn1Time {
|
||||
fn partial_cmp(&self, other: &Asn1TimeRef) -> Option<Ordering> {
|
||||
self.compare(other).ok()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(ossl102, boringssl))]
|
||||
impl<'a> PartialOrd<&'a Asn1TimeRef> for Asn1Time {
|
||||
fn partial_cmp(&self, other: &&'a Asn1TimeRef) -> Option<Ordering> {
|
||||
self.compare(other).ok()
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::ASN1_STRING;
|
||||
fn drop = ffi::ASN1_STRING_free;
|
||||
/// Primary ASN.1 type used by OpenSSL
|
||||
///
|
||||
/// Almost all ASN.1 types in OpenSSL are represented by ASN1_STRING
|
||||
/// structures. This implementation uses [ASN1_STRING-to_UTF8] to preserve
|
||||
/// compatibility with Rust's String.
|
||||
///
|
||||
/// [ASN1_STRING-to_UTF8]: https://www.openssl.org/docs/manmaster/crypto/ASN1_STRING_to_UTF8.html
|
||||
pub struct Asn1String;
|
||||
/// A reference to an [`Asn1String`].
|
||||
pub struct Asn1StringRef;
|
||||
}
|
||||
|
||||
impl Asn1StringRef {
|
||||
/// Converts the ASN.1 underlying format to UTF8
|
||||
///
|
||||
/// ASN.1 strings may utilize UTF-16, ASCII, BMP, or UTF8. This is important to
|
||||
/// consume the string in a meaningful way without knowing the underlying
|
||||
/// format.
|
||||
#[corresponds(ASN1_STRING_to_UTF8)]
|
||||
pub fn as_utf8(&self) -> Result<OpensslString, ErrorStack> {
|
||||
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(OpensslString::from_ptr(ptr as *mut c_char))
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the string as an array of bytes.
|
||||
///
|
||||
/// The bytes do not directly correspond to UTF-8 encoding. To interact with
|
||||
/// strings in rust, it is preferable to use [`as_utf8`]
|
||||
///
|
||||
/// [`as_utf8`]: struct.Asn1String.html#method.as_utf8
|
||||
#[corresponds(ASN1_STRING_get0_data)]
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
unsafe { util::from_raw_parts(ASN1_STRING_get0_data(self.as_ptr()), self.len()) }
|
||||
}
|
||||
|
||||
/// Returns the number of bytes in the string.
|
||||
#[corresponds(ASN1_STRING_length)]
|
||||
pub fn len(&self) -> usize {
|
||||
unsafe { ffi::ASN1_STRING_length(self.as_ptr()) as usize }
|
||||
}
|
||||
|
||||
/// Determines if the string is empty.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Asn1StringRef {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.as_utf8() {
|
||||
Ok(openssl_string) => openssl_string.fmt(fmt),
|
||||
Err(_) => fmt.write_str("error"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::ASN1_INTEGER;
|
||||
fn drop = ffi::ASN1_INTEGER_free;
|
||||
|
||||
/// Numeric representation
|
||||
///
|
||||
/// Integers in ASN.1 may include BigNum, int64 or uint64. BigNum implementation
|
||||
/// can be found within [`bn`] module.
|
||||
///
|
||||
/// OpenSSL documentation includes [`ASN1_INTEGER_set`].
|
||||
///
|
||||
/// [`bn`]: ../bn/index.html
|
||||
/// [`ASN1_INTEGER_set`]: https://www.openssl.org/docs/manmaster/crypto/ASN1_INTEGER_set.html
|
||||
pub struct Asn1Integer;
|
||||
/// A reference to an [`Asn1Integer`].
|
||||
pub struct Asn1IntegerRef;
|
||||
}
|
||||
|
||||
impl Asn1Integer {
|
||||
/// Converts a bignum to an `Asn1Integer`.
|
||||
///
|
||||
/// Corresponds to [`BN_to_ASN1_INTEGER`]. Also see
|
||||
/// [`BigNumRef::to_asn1_integer`].
|
||||
///
|
||||
/// [`BN_to_ASN1_INTEGER`]: https://www.openssl.org/docs/manmaster/crypto/BN_to_ASN1_INTEGER.html
|
||||
/// [`BigNumRef::to_asn1_integer`]: ../bn/struct.BigNumRef.html#method.to_asn1_integer
|
||||
pub fn from_bn(bn: &BigNumRef) -> Result<Self, ErrorStack> {
|
||||
bn.to_asn1_integer()
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Asn1Integer {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
Asn1IntegerRef::cmp(self, other)
|
||||
}
|
||||
}
|
||||
impl PartialOrd for Asn1Integer {
|
||||
fn partial_cmp(&self, other: &Asn1Integer) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
impl Eq for Asn1Integer {}
|
||||
impl PartialEq for Asn1Integer {
|
||||
fn eq(&self, other: &Asn1Integer) -> bool {
|
||||
Asn1IntegerRef::eq(self, other)
|
||||
}
|
||||
}
|
||||
|
||||
impl Asn1IntegerRef {
|
||||
#[allow(missing_docs, clippy::unnecessary_cast)]
|
||||
#[deprecated(since = "0.10.6", note = "use to_bn instead")]
|
||||
pub fn get(&self) -> i64 {
|
||||
unsafe { ffi::ASN1_INTEGER_get(self.as_ptr()) as i64 }
|
||||
}
|
||||
|
||||
/// Converts the integer to a `BigNum`.
|
||||
#[corresponds(ASN1_INTEGER_to_BN)]
|
||||
pub fn to_bn(&self) -> Result<BigNum, ErrorStack> {
|
||||
unsafe {
|
||||
cvt_p(ffi::ASN1_INTEGER_to_BN(self.as_ptr(), ptr::null_mut()))
|
||||
.map(|p| BigNum::from_ptr(p))
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the ASN.1 value to the value of a signed 32-bit integer, for larger numbers
|
||||
/// see [`bn`].
|
||||
///
|
||||
/// [`bn`]: ../bn/struct.BigNumRef.html#method.to_asn1_integer
|
||||
#[corresponds(ASN1_INTEGER_set)]
|
||||
pub fn set(&mut self, value: i32) -> Result<(), ErrorStack> {
|
||||
unsafe { cvt(ffi::ASN1_INTEGER_set(self.as_ptr(), value as c_long)).map(|_| ()) }
|
||||
}
|
||||
|
||||
/// Creates a new Asn1Integer with the same value.
|
||||
#[corresponds(ASN1_INTEGER_dup)]
|
||||
pub fn to_owned(&self) -> Result<Asn1Integer, ErrorStack> {
|
||||
unsafe { cvt_p(ffi::ASN1_INTEGER_dup(self.as_ptr())).map(|p| Asn1Integer::from_ptr(p)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Asn1IntegerRef {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
let res = unsafe { ffi::ASN1_INTEGER_cmp(self.as_ptr(), other.as_ptr()) };
|
||||
res.cmp(&0)
|
||||
}
|
||||
}
|
||||
impl PartialOrd for Asn1IntegerRef {
|
||||
fn partial_cmp(&self, other: &Asn1IntegerRef) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
impl Eq for Asn1IntegerRef {}
|
||||
impl PartialEq for Asn1IntegerRef {
|
||||
fn eq(&self, other: &Asn1IntegerRef) -> bool {
|
||||
self.cmp(other) == Ordering::Equal
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::ASN1_BIT_STRING;
|
||||
fn drop = ffi::ASN1_BIT_STRING_free;
|
||||
/// Sequence of bytes
|
||||
///
|
||||
/// Asn1BitString is used in [`x509`] certificates for the signature.
|
||||
/// The bit string acts as a collection of bytes.
|
||||
///
|
||||
/// [`x509`]: ../x509/struct.X509.html#method.signature
|
||||
pub struct Asn1BitString;
|
||||
/// A reference to an [`Asn1BitString`].
|
||||
pub struct Asn1BitStringRef;
|
||||
}
|
||||
|
||||
impl Asn1BitStringRef {
|
||||
/// Returns the Asn1BitString as a slice.
|
||||
#[corresponds(ASN1_STRING_get0_data)]
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
unsafe { util::from_raw_parts(ASN1_STRING_get0_data(self.as_ptr() as *mut _), self.len()) }
|
||||
}
|
||||
|
||||
/// Returns the number of bytes in the string.
|
||||
#[corresponds(ASN1_STRING_length)]
|
||||
pub fn len(&self) -> usize {
|
||||
unsafe { ffi::ASN1_STRING_length(self.as_ptr() as *const _) as usize }
|
||||
}
|
||||
|
||||
/// Determines if the string is empty.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::ASN1_OCTET_STRING;
|
||||
fn drop = ffi::ASN1_OCTET_STRING_free;
|
||||
/// ASN.1 OCTET STRING type
|
||||
pub struct Asn1OctetString;
|
||||
/// A reference to an [`Asn1OctetString`].
|
||||
pub struct Asn1OctetStringRef;
|
||||
}
|
||||
|
||||
impl Asn1OctetString {
|
||||
/// Creates an Asn1OctetString from bytes
|
||||
pub fn new_from_bytes(value: &[u8]) -> Result<Self, ErrorStack> {
|
||||
ffi::init();
|
||||
unsafe {
|
||||
let s = cvt_p(ffi::ASN1_OCTET_STRING_new())?;
|
||||
ffi::ASN1_OCTET_STRING_set(s, value.as_ptr(), value.len().try_into().unwrap());
|
||||
Ok(Self::from_ptr(s))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Asn1OctetStringRef {
|
||||
/// Returns the octet string as an array of bytes.
|
||||
#[corresponds(ASN1_STRING_get0_data)]
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
unsafe { util::from_raw_parts(ASN1_STRING_get0_data(self.as_ptr().cast()), self.len()) }
|
||||
}
|
||||
|
||||
/// Returns the number of bytes in the octet string.
|
||||
#[corresponds(ASN1_STRING_length)]
|
||||
pub fn len(&self) -> usize {
|
||||
unsafe { ffi::ASN1_STRING_length(self.as_ptr().cast()) as usize }
|
||||
}
|
||||
|
||||
/// Determines if the string is empty.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::ASN1_OBJECT;
|
||||
fn drop = ffi::ASN1_OBJECT_free;
|
||||
fn clone = ffi::OBJ_dup;
|
||||
|
||||
/// Object Identifier
|
||||
///
|
||||
/// Represents an ASN.1 Object. Typically, NIDs, or numeric identifiers
|
||||
/// are stored as a table within the [`Nid`] module. These constants are
|
||||
/// used to determine attributes of a certificate, such as mapping the
|
||||
/// attribute "CommonName" to "CN" which is represented as the OID of 13.
|
||||
/// This attribute is a constant in the [`nid::COMMONNAME`].
|
||||
///
|
||||
/// OpenSSL documentation at [`OBJ_nid2obj`]
|
||||
///
|
||||
/// [`Nid`]: ../nid/index.html
|
||||
/// [`nid::COMMONNAME`]: ../nid/constant.COMMONNAME.html
|
||||
/// [`OBJ_nid2obj`]: https://www.openssl.org/docs/manmaster/crypto/OBJ_obj2nid.html
|
||||
pub struct Asn1Object;
|
||||
/// A reference to an [`Asn1Object`].
|
||||
pub struct Asn1ObjectRef;
|
||||
}
|
||||
|
||||
impl Stackable for Asn1Object {
|
||||
type StackType = ffi::stack_st_ASN1_OBJECT;
|
||||
}
|
||||
|
||||
impl Asn1Object {
|
||||
/// Constructs an ASN.1 Object Identifier from a string representation of the OID.
|
||||
#[corresponds(OBJ_txt2obj)]
|
||||
#[allow(clippy::should_implement_trait)]
|
||||
pub fn from_str(txt: &str) -> Result<Asn1Object, ErrorStack> {
|
||||
unsafe {
|
||||
ffi::init();
|
||||
let txt = CString::new(txt).unwrap();
|
||||
let obj: *mut ffi::ASN1_OBJECT = cvt_p(ffi::OBJ_txt2obj(txt.as_ptr() as *const _, 0))?;
|
||||
Ok(Asn1Object::from_ptr(obj))
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the OID as an DER encoded array of bytes. This is the ASN.1
|
||||
/// value, not including tag or length.
|
||||
///
|
||||
/// Requires OpenSSL 1.1.1 or newer.
|
||||
#[corresponds(OBJ_get0_data)]
|
||||
#[cfg(ossl111)]
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
unsafe {
|
||||
let len = ffi::OBJ_length(self.as_ptr());
|
||||
util::from_raw_parts(ffi::OBJ_get0_data(self.as_ptr()), len)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Asn1ObjectRef {
|
||||
/// Returns the NID associated with this OID.
|
||||
pub fn nid(&self) -> Nid {
|
||||
unsafe { Nid::from_raw(ffi::OBJ_obj2nid(self.as_ptr())) }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Asn1ObjectRef {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
unsafe {
|
||||
let mut buf = [0; 80];
|
||||
let len = ffi::OBJ_obj2txt(
|
||||
buf.as_mut_ptr() as *mut _,
|
||||
buf.len() as c_int,
|
||||
self.as_ptr(),
|
||||
0,
|
||||
);
|
||||
match str::from_utf8(&buf[..len as usize]) {
|
||||
Err(_) => fmt.write_str("error"),
|
||||
Ok(s) => fmt.write_str(s),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Asn1ObjectRef {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.write_str(self.to_string().as_str())
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl110, libressl273, boringssl))] {
|
||||
use ffi::ASN1_STRING_get0_data;
|
||||
} else {
|
||||
#[allow(bad_style)]
|
||||
unsafe fn ASN1_STRING_get0_data(s: *mut ffi::ASN1_STRING) -> *const ::libc::c_uchar {
|
||||
ffi::ASN1_STRING_data(s)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::ASN1_ENUMERATED;
|
||||
fn drop = ffi::ASN1_ENUMERATED_free;
|
||||
|
||||
/// An ASN.1 enumerated.
|
||||
pub struct Asn1Enumerated;
|
||||
/// A reference to an [`Asn1Enumerated`].
|
||||
pub struct Asn1EnumeratedRef;
|
||||
}
|
||||
|
||||
impl Asn1EnumeratedRef {
|
||||
/// Get the value, if it fits in the required bounds.
|
||||
#[corresponds(ASN1_ENUMERATED_get_int64)]
|
||||
#[cfg(ossl110)]
|
||||
pub fn get_i64(&self) -> Result<i64, ErrorStack> {
|
||||
let mut crl_reason = 0;
|
||||
unsafe {
|
||||
cvt(ffi::ASN1_ENUMERATED_get_int64(
|
||||
&mut crl_reason,
|
||||
self.as_ptr(),
|
||||
))?;
|
||||
}
|
||||
Ok(crl_reason)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use crate::bn::BigNum;
|
||||
use crate::nid::Nid;
|
||||
|
||||
/// Tests conversion between BigNum and Asn1Integer.
|
||||
#[test]
|
||||
fn bn_cvt() {
|
||||
fn roundtrip(bn: BigNum) {
|
||||
let large = Asn1Integer::from_bn(&bn).unwrap();
|
||||
assert_eq!(large.to_bn().unwrap(), bn);
|
||||
}
|
||||
|
||||
roundtrip(BigNum::from_dec_str("1000000000000000000000000000000000").unwrap());
|
||||
roundtrip(-BigNum::from_dec_str("1000000000000000000000000000000000").unwrap());
|
||||
roundtrip(BigNum::from_u32(1234).unwrap());
|
||||
roundtrip(-BigNum::from_u32(1234).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn time_from_str() {
|
||||
Asn1Time::from_str("99991231235959Z").unwrap();
|
||||
#[cfg(ossl111)]
|
||||
Asn1Time::from_str_x509("99991231235959Z").unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn time_from_unix() {
|
||||
let t = Asn1Time::from_unix(0).unwrap();
|
||||
assert_eq!("Jan 1 00:00:00 1970 GMT", t.to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(ossl102, boringssl))]
|
||||
fn time_eq() {
|
||||
let a = Asn1Time::from_str("99991231235959Z").unwrap();
|
||||
let b = Asn1Time::from_str("99991231235959Z").unwrap();
|
||||
let c = Asn1Time::from_str("99991231235958Z").unwrap();
|
||||
let a_ref = a.as_ref();
|
||||
let b_ref = b.as_ref();
|
||||
let c_ref = c.as_ref();
|
||||
assert!(a == b);
|
||||
assert!(a != c);
|
||||
assert!(a == b_ref);
|
||||
assert!(a != c_ref);
|
||||
assert!(b_ref == a);
|
||||
assert!(c_ref != a);
|
||||
assert!(a_ref == b_ref);
|
||||
assert!(a_ref != c_ref);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(ossl102, boringssl))]
|
||||
fn time_ord() {
|
||||
let a = Asn1Time::from_str("99991231235959Z").unwrap();
|
||||
let b = Asn1Time::from_str("99991231235959Z").unwrap();
|
||||
let c = Asn1Time::from_str("99991231235958Z").unwrap();
|
||||
let a_ref = a.as_ref();
|
||||
let b_ref = b.as_ref();
|
||||
let c_ref = c.as_ref();
|
||||
assert!(a >= b);
|
||||
assert!(a > c);
|
||||
assert!(b <= a);
|
||||
assert!(c < a);
|
||||
|
||||
assert!(a_ref >= b);
|
||||
assert!(a_ref > c);
|
||||
assert!(b_ref <= a);
|
||||
assert!(c_ref < a);
|
||||
|
||||
assert!(a >= b_ref);
|
||||
assert!(a > c_ref);
|
||||
assert!(b <= a_ref);
|
||||
assert!(c < a_ref);
|
||||
|
||||
assert!(a_ref >= b_ref);
|
||||
assert!(a_ref > c_ref);
|
||||
assert!(b_ref <= a_ref);
|
||||
assert!(c_ref < a_ref);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn integer_to_owned() {
|
||||
let a = Asn1Integer::from_bn(&BigNum::from_dec_str("42").unwrap()).unwrap();
|
||||
let b = a.to_owned().unwrap();
|
||||
assert_eq!(
|
||||
a.to_bn().unwrap().to_dec_str().unwrap().to_string(),
|
||||
b.to_bn().unwrap().to_dec_str().unwrap().to_string(),
|
||||
);
|
||||
assert_ne!(a.as_ptr(), b.as_ptr());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn integer_cmp() {
|
||||
let a = Asn1Integer::from_bn(&BigNum::from_dec_str("42").unwrap()).unwrap();
|
||||
let b = Asn1Integer::from_bn(&BigNum::from_dec_str("42").unwrap()).unwrap();
|
||||
let c = Asn1Integer::from_bn(&BigNum::from_dec_str("43").unwrap()).unwrap();
|
||||
assert!(a == b);
|
||||
assert!(a != c);
|
||||
assert!(a < c);
|
||||
assert!(c > b);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn object_from_str() {
|
||||
let object = Asn1Object::from_str("2.16.840.1.101.3.4.2.1").unwrap();
|
||||
assert_eq!(object.nid(), Nid::SHA256);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn object_from_str_with_invalid_input() {
|
||||
Asn1Object::from_str("NOT AN OID")
|
||||
.map(|object| object.to_string())
|
||||
.expect_err("parsing invalid OID should fail");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl111)]
|
||||
fn object_to_slice() {
|
||||
let object = Asn1Object::from_str("2.16.840.1.101.3.4.2.1").unwrap();
|
||||
assert_eq!(
|
||||
object.as_slice(),
|
||||
&[0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn asn1_octet_string() {
|
||||
let octet_string = Asn1OctetString::new_from_bytes(b"hello world").unwrap();
|
||||
assert_eq!(octet_string.as_slice(), b"hello world");
|
||||
assert_eq!(octet_string.len(), 11);
|
||||
}
|
||||
}
|
||||
128
vendor/openssl/src/base64.rs
vendored
Normal file
128
vendor/openssl/src/base64.rs
vendored
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
//! Base64 encoding support.
|
||||
use crate::error::ErrorStack;
|
||||
use crate::{cvt_n, LenType};
|
||||
use libc::c_int;
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
/// Encodes a slice of bytes to a base64 string.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the input length or computed output length overflow a signed C integer.
|
||||
#[corresponds(EVP_EncodeBlock)]
|
||||
pub fn encode_block(src: &[u8]) -> String {
|
||||
assert!(src.len() <= c_int::MAX as usize);
|
||||
let src_len = src.len() as LenType;
|
||||
|
||||
let len = encoded_len(src_len).unwrap();
|
||||
let mut out = Vec::with_capacity(len as usize);
|
||||
|
||||
// SAFETY: `encoded_len` ensures space for 4 output characters
|
||||
// for every 3 input bytes including padding and nul terminator.
|
||||
// `EVP_EncodeBlock` will write only single byte ASCII characters.
|
||||
// `EVP_EncodeBlock` will only write to not read from `out`.
|
||||
unsafe {
|
||||
let out_len = ffi::EVP_EncodeBlock(out.as_mut_ptr(), src.as_ptr(), src_len);
|
||||
out.set_len(out_len as usize);
|
||||
String::from_utf8_unchecked(out)
|
||||
}
|
||||
}
|
||||
|
||||
/// Decodes a base64-encoded string to bytes.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the input length or computed output length overflow a signed C integer.
|
||||
#[corresponds(EVP_DecodeBlock)]
|
||||
pub fn decode_block(src: &str) -> Result<Vec<u8>, ErrorStack> {
|
||||
let src = src.trim();
|
||||
|
||||
// https://github.com/openssl/openssl/issues/12143
|
||||
if src.is_empty() {
|
||||
return Ok(vec![]);
|
||||
}
|
||||
|
||||
assert!(src.len() <= c_int::MAX as usize);
|
||||
let src_len = src.len() as LenType;
|
||||
|
||||
let len = decoded_len(src_len).unwrap();
|
||||
let mut out = Vec::with_capacity(len as usize);
|
||||
|
||||
// SAFETY: `decoded_len` ensures space for 3 output bytes
|
||||
// for every 4 input characters including padding.
|
||||
// `EVP_DecodeBlock` can write fewer bytes after stripping
|
||||
// leading and trailing whitespace, but never more.
|
||||
// `EVP_DecodeBlock` will only write to not read from `out`.
|
||||
unsafe {
|
||||
let out_len = cvt_n(ffi::EVP_DecodeBlock(
|
||||
out.as_mut_ptr(),
|
||||
src.as_ptr(),
|
||||
src_len,
|
||||
))?;
|
||||
out.set_len(out_len as usize);
|
||||
}
|
||||
|
||||
if src.ends_with('=') {
|
||||
out.pop();
|
||||
if src.ends_with("==") {
|
||||
out.pop();
|
||||
}
|
||||
}
|
||||
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
fn encoded_len(src_len: LenType) -> Option<LenType> {
|
||||
let mut len = (src_len / 3).checked_mul(4)?;
|
||||
|
||||
if src_len % 3 != 0 {
|
||||
len = len.checked_add(4)?;
|
||||
}
|
||||
|
||||
len = len.checked_add(1)?;
|
||||
|
||||
Some(len)
|
||||
}
|
||||
|
||||
fn decoded_len(src_len: LenType) -> Option<LenType> {
|
||||
let mut len = (src_len / 4).checked_mul(3)?;
|
||||
|
||||
if src_len % 4 != 0 {
|
||||
len = len.checked_add(3)?;
|
||||
}
|
||||
|
||||
Some(len)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_encode_block() {
|
||||
assert_eq!("".to_string(), encode_block(b""));
|
||||
assert_eq!("Zg==".to_string(), encode_block(b"f"));
|
||||
assert_eq!("Zm8=".to_string(), encode_block(b"fo"));
|
||||
assert_eq!("Zm9v".to_string(), encode_block(b"foo"));
|
||||
assert_eq!("Zm9vYg==".to_string(), encode_block(b"foob"));
|
||||
assert_eq!("Zm9vYmE=".to_string(), encode_block(b"fooba"));
|
||||
assert_eq!("Zm9vYmFy".to_string(), encode_block(b"foobar"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decode_block() {
|
||||
assert_eq!(b"".to_vec(), decode_block("").unwrap());
|
||||
assert_eq!(b"f".to_vec(), decode_block("Zg==").unwrap());
|
||||
assert_eq!(b"fo".to_vec(), decode_block("Zm8=").unwrap());
|
||||
assert_eq!(b"foo".to_vec(), decode_block("Zm9v").unwrap());
|
||||
assert_eq!(b"foob".to_vec(), decode_block("Zm9vYg==").unwrap());
|
||||
assert_eq!(b"fooba".to_vec(), decode_block("Zm9vYmE=").unwrap());
|
||||
assert_eq!(b"foobar".to_vec(), decode_block("Zm9vYmFy").unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_strip_whitespace() {
|
||||
assert_eq!(b"foobar".to_vec(), decode_block(" Zm9vYmFy\n").unwrap());
|
||||
assert_eq!(b"foob".to_vec(), decode_block(" Zm9vYg==\n").unwrap());
|
||||
}
|
||||
}
|
||||
96
vendor/openssl/src/bio.rs
vendored
Normal file
96
vendor/openssl/src/bio.rs
vendored
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
use cfg_if::cfg_if;
|
||||
use libc::c_int;
|
||||
use std::marker::PhantomData;
|
||||
use std::ptr;
|
||||
|
||||
use crate::cvt_p;
|
||||
use crate::error::ErrorStack;
|
||||
use crate::util;
|
||||
|
||||
pub struct MemBioSlice<'a>(*mut ffi::BIO, PhantomData<&'a [u8]>);
|
||||
|
||||
impl Drop for MemBioSlice<'_> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
ffi::BIO_free_all(self.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> MemBioSlice<'a> {
|
||||
pub fn new(buf: &'a [u8]) -> Result<MemBioSlice<'a>, ErrorStack> {
|
||||
ffi::init();
|
||||
|
||||
assert!(buf.len() <= c_int::MAX as usize);
|
||||
let bio = unsafe {
|
||||
cvt_p(BIO_new_mem_buf(
|
||||
buf.as_ptr() as *const _,
|
||||
buf.len() as crate::SLenType,
|
||||
))?
|
||||
};
|
||||
|
||||
Ok(MemBioSlice(bio, PhantomData))
|
||||
}
|
||||
|
||||
pub fn as_ptr(&self) -> *mut ffi::BIO {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MemBio(*mut ffi::BIO);
|
||||
|
||||
impl Drop for MemBio {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
ffi::BIO_free_all(self.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MemBio {
|
||||
pub fn new() -> Result<MemBio, ErrorStack> {
|
||||
ffi::init();
|
||||
|
||||
let bio = unsafe { cvt_p(ffi::BIO_new(ffi::BIO_s_mem()))? };
|
||||
Ok(MemBio(bio))
|
||||
}
|
||||
|
||||
pub fn as_ptr(&self) -> *mut ffi::BIO {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn get_buf(&self) -> &[u8] {
|
||||
unsafe {
|
||||
let mut ptr = ptr::null_mut();
|
||||
let len = ffi::BIO_get_mem_data(self.0, &mut ptr);
|
||||
util::from_raw_parts(ptr as *const _ as *const _, len as usize)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(boringssl))]
|
||||
pub unsafe fn from_ptr(bio: *mut ffi::BIO) -> MemBio {
|
||||
MemBio(bio)
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl102, boringssl))] {
|
||||
use ffi::BIO_new_mem_buf;
|
||||
} else {
|
||||
#[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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::MemBio;
|
||||
|
||||
#[test]
|
||||
fn test_mem_bio_get_buf_empty() {
|
||||
let b = MemBio::new().unwrap();
|
||||
assert_eq!(b.get_buf(), &[]);
|
||||
}
|
||||
}
|
||||
1523
vendor/openssl/src/bn.rs
vendored
Normal file
1523
vendor/openssl/src/bn.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
597
vendor/openssl/src/cipher.rs
vendored
Normal file
597
vendor/openssl/src/cipher.rs
vendored
Normal file
|
|
@ -0,0 +1,597 @@
|
|||
//! Symmetric ciphers.
|
||||
|
||||
#[cfg(ossl300)]
|
||||
use crate::cvt_p;
|
||||
#[cfg(ossl300)]
|
||||
use crate::error::ErrorStack;
|
||||
#[cfg(ossl300)]
|
||||
use crate::lib_ctx::LibCtxRef;
|
||||
use crate::nid::Nid;
|
||||
use cfg_if::cfg_if;
|
||||
use foreign_types::{ForeignTypeRef, Opaque};
|
||||
use openssl_macros::corresponds;
|
||||
#[cfg(ossl300)]
|
||||
use std::ffi::CString;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
#[cfg(ossl300)]
|
||||
use std::ptr;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(boringssl, ossl110, libressl273))] {
|
||||
use ffi::{EVP_CIPHER_block_size, EVP_CIPHER_iv_length, EVP_CIPHER_key_length};
|
||||
} else {
|
||||
use libc::c_int;
|
||||
|
||||
#[allow(bad_style)]
|
||||
pub unsafe fn EVP_CIPHER_iv_length(ptr: *const ffi::EVP_CIPHER) -> c_int {
|
||||
(*ptr).iv_len
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
pub unsafe fn EVP_CIPHER_block_size(ptr: *const ffi::EVP_CIPHER) -> c_int {
|
||||
(*ptr).block_size
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
pub unsafe fn EVP_CIPHER_key_length(ptr: *const ffi::EVP_CIPHER) -> c_int {
|
||||
(*ptr).key_len
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(ossl300)] {
|
||||
use foreign_types::ForeignType;
|
||||
|
||||
type Inner = *mut ffi::EVP_CIPHER;
|
||||
|
||||
impl Drop for Cipher {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
ffi::EVP_CIPHER_free(self.as_ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ForeignType for Cipher {
|
||||
type CType = ffi::EVP_CIPHER;
|
||||
type Ref = CipherRef;
|
||||
|
||||
#[inline]
|
||||
unsafe fn from_ptr(ptr: *mut Self::CType) -> Self {
|
||||
Cipher(ptr)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_ptr(&self) -> *mut Self::CType {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Cipher {
|
||||
type Target = CipherRef;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unsafe {
|
||||
CipherRef::from_ptr(self.as_ptr())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Cipher {
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
unsafe {
|
||||
CipherRef::from_ptr_mut(self.as_ptr())
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
enum Inner {}
|
||||
|
||||
impl Deref for Cipher {
|
||||
type Target = CipherRef;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &Self::Target {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Cipher {
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A symmetric cipher.
|
||||
pub struct Cipher(Inner);
|
||||
|
||||
unsafe impl Sync for Cipher {}
|
||||
unsafe impl Send for Cipher {}
|
||||
|
||||
impl Cipher {
|
||||
/// Looks up the cipher for a certain nid.
|
||||
#[corresponds(EVP_get_cipherbynid)]
|
||||
pub fn from_nid(nid: Nid) -> Option<&'static CipherRef> {
|
||||
unsafe {
|
||||
let ptr = ffi::EVP_get_cipherbyname(ffi::OBJ_nid2sn(nid.as_raw()));
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(CipherRef::from_ptr(ptr as *mut _))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Fetches a cipher object corresponding to the specified algorithm name and properties.
|
||||
///
|
||||
/// Requires OpenSSL 3.0.0 or newer.
|
||||
#[corresponds(EVP_CIPHER_fetch)]
|
||||
#[cfg(ossl300)]
|
||||
pub fn fetch(
|
||||
ctx: Option<&LibCtxRef>,
|
||||
algorithm: &str,
|
||||
properties: Option<&str>,
|
||||
) -> Result<Self, ErrorStack> {
|
||||
let algorithm = CString::new(algorithm).unwrap();
|
||||
let properties = properties.map(|s| CString::new(s).unwrap());
|
||||
|
||||
unsafe {
|
||||
let ptr = cvt_p(ffi::EVP_CIPHER_fetch(
|
||||
ctx.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr),
|
||||
algorithm.as_ptr(),
|
||||
properties.map_or(ptr::null_mut(), |s| s.as_ptr()),
|
||||
))?;
|
||||
|
||||
Ok(Cipher::from_ptr(ptr))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn aes_128_ecb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_ecb() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_128_cbc() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_cbc() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(boringssl))]
|
||||
pub fn aes_128_xts() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_xts() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(boringssl))]
|
||||
pub fn aes_256_xts() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_xts() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_128_ctr() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_ctr() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(boringssl))]
|
||||
pub fn aes_128_cfb1() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_cfb1() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(boringssl))]
|
||||
pub fn aes_128_cfb128() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_cfb128() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(boringssl))]
|
||||
pub fn aes_128_cfb8() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_cfb8() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_128_gcm() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_gcm() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(boringssl))]
|
||||
pub fn aes_128_ccm() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_ccm() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_128_ofb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_ofb() as *mut _) }
|
||||
}
|
||||
|
||||
/// Requires OpenSSL 1.1.0 or newer.
|
||||
#[cfg(all(ossl110, not(osslconf = "OPENSSL_NO_OCB")))]
|
||||
pub fn aes_128_ocb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_ocb() as *mut _) }
|
||||
}
|
||||
|
||||
/// Requires OpenSSL 1.0.2 or newer.
|
||||
#[cfg(ossl102)]
|
||||
pub fn aes_128_wrap() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_wrap() as *mut _) }
|
||||
}
|
||||
|
||||
/// Requires OpenSSL 1.1.0 or newer.
|
||||
#[cfg(ossl110)]
|
||||
pub fn aes_128_wrap_pad() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_wrap_pad() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_192_ecb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_ecb() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_192_cbc() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_cbc() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_192_ctr() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_ctr() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(boringssl))]
|
||||
pub fn aes_192_cfb1() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_cfb1() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_192_cfb128() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_cfb128() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(boringssl))]
|
||||
pub fn aes_192_cfb8() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_cfb8() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_192_gcm() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_gcm() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(boringssl))]
|
||||
pub fn aes_192_ccm() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_ccm() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_192_ofb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_ofb() as *mut _) }
|
||||
}
|
||||
|
||||
/// Requires OpenSSL 1.1.0 or newer.
|
||||
#[cfg(all(ossl110, not(osslconf = "OPENSSL_NO_OCB")))]
|
||||
pub fn aes_192_ocb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_ocb() as *mut _) }
|
||||
}
|
||||
|
||||
/// Requires OpenSSL 1.0.2 or newer.
|
||||
#[cfg(ossl102)]
|
||||
pub fn aes_192_wrap() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_wrap() as *mut _) }
|
||||
}
|
||||
|
||||
/// Requires OpenSSL 1.1.0 or newer.
|
||||
#[cfg(ossl110)]
|
||||
pub fn aes_192_wrap_pad() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_wrap_pad() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_256_ecb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_ecb() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_256_cbc() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_cbc() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_256_ctr() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_ctr() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(boringssl))]
|
||||
pub fn aes_256_cfb1() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_cfb1() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_256_cfb128() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_cfb128() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(boringssl))]
|
||||
pub fn aes_256_cfb8() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_cfb8() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_256_gcm() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_gcm() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(boringssl))]
|
||||
pub fn aes_256_ccm() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_ccm() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn aes_256_ofb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_ofb() as *mut _) }
|
||||
}
|
||||
|
||||
/// Requires OpenSSL 1.1.0 or newer.
|
||||
#[cfg(all(ossl110, not(osslconf = "OPENSSL_NO_OCB")))]
|
||||
pub fn aes_256_ocb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_ocb() as *mut _) }
|
||||
}
|
||||
|
||||
/// Requires OpenSSL 1.0.2 or newer.
|
||||
#[cfg(ossl102)]
|
||||
pub fn aes_256_wrap() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_wrap() as *mut _) }
|
||||
}
|
||||
|
||||
/// Requires OpenSSL 1.1.0 or newer.
|
||||
#[cfg(ossl110)]
|
||||
pub fn aes_256_wrap_pad() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_wrap_pad() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_BF"))]
|
||||
pub fn bf_cbc() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_bf_cbc() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_BF"))]
|
||||
pub fn bf_ecb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_bf_ecb() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_BF"))]
|
||||
pub fn bf_cfb64() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_bf_cfb64() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_BF"))]
|
||||
pub fn bf_ofb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_bf_ofb() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn des_cbc() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_des_cbc() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn des_ecb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_des_ecb() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn des_ede3() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_des_ede3() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn des_ede3_ecb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_des_ede3_ecb() as *mut _) }
|
||||
}
|
||||
|
||||
pub fn des_ede3_cbc() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_des_ede3_cbc() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(boringssl))]
|
||||
pub fn des_ede3_cfb8() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_des_ede3_cfb8() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(boringssl))]
|
||||
pub fn des_ede3_cfb64() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_des_ede3_cfb64() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(boringssl))]
|
||||
pub fn des_ede3_ofb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_des_ede3_ofb() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_RC4"))]
|
||||
pub fn rc4() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_rc4() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
|
||||
pub fn camellia128_cfb128() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_camellia_128_cfb128() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
|
||||
pub fn camellia128_ecb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_camellia_128_ecb() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
|
||||
pub fn camellia128_cbc() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_camellia_128_cbc() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
|
||||
pub fn camellia128_ofb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_camellia_128_ofb() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
|
||||
pub fn camellia192_cfb128() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_camellia_192_cfb128() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
|
||||
pub fn camellia192_ecb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_camellia_192_ecb() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
|
||||
pub fn camellia192_cbc() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_camellia_192_cbc() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
|
||||
pub fn camellia192_ofb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_camellia_192_ofb() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
|
||||
pub fn camellia256_cfb128() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_camellia_256_cfb128() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
|
||||
pub fn camellia256_ecb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_camellia_256_ecb() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
|
||||
pub fn camellia256_cbc() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_camellia_256_cbc() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_CAMELLIA"))]
|
||||
pub fn camellia256_ofb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_camellia_256_ofb() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_CAST"))]
|
||||
pub fn cast5_cfb64() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_cast5_cfb64() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_CAST"))]
|
||||
pub fn cast5_ecb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_cast5_ecb() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_CAST"))]
|
||||
pub fn cast5_cbc() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_cast5_cbc() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_CAST"))]
|
||||
pub fn cast5_ofb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_cast5_ofb() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_IDEA"))]
|
||||
pub fn idea_cfb64() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_idea_cfb64() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_IDEA"))]
|
||||
pub fn idea_ecb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_idea_ecb() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_IDEA"))]
|
||||
pub fn idea_cbc() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_idea_cbc() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_IDEA"))]
|
||||
pub fn idea_ofb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_idea_ofb() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(all(any(ossl110, libressl310), not(osslconf = "OPENSSL_NO_CHACHA")))]
|
||||
pub fn chacha20() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_chacha20() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(all(any(ossl110, libressl360), not(osslconf = "OPENSSL_NO_CHACHA")))]
|
||||
pub fn chacha20_poly1305() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_chacha20_poly1305() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_SEED"))]
|
||||
pub fn seed_cbc() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_seed_cbc() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_SEED"))]
|
||||
pub fn seed_cfb128() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_seed_cfb128() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_SEED"))]
|
||||
pub fn seed_ecb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_seed_ecb() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_SEED"))]
|
||||
pub fn seed_ofb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_seed_ofb() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM4")))]
|
||||
pub fn sm4_ecb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_sm4_ecb() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM4")))]
|
||||
pub fn sm4_cbc() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_sm4_cbc() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM4")))]
|
||||
pub fn sm4_ctr() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_sm4_ctr() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM4")))]
|
||||
pub fn sm4_cfb128() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_sm4_cfb128() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM4")))]
|
||||
pub fn sm4_ofb() -> &'static CipherRef {
|
||||
unsafe { CipherRef::from_ptr(ffi::EVP_sm4_ofb() as *mut _) }
|
||||
}
|
||||
}
|
||||
|
||||
/// A reference to a [`Cipher`].
|
||||
pub struct CipherRef(Opaque);
|
||||
|
||||
impl ForeignTypeRef for CipherRef {
|
||||
type CType = ffi::EVP_CIPHER;
|
||||
}
|
||||
|
||||
unsafe impl Sync for CipherRef {}
|
||||
unsafe impl Send for CipherRef {}
|
||||
|
||||
impl CipherRef {
|
||||
/// Returns the cipher's Nid.
|
||||
#[corresponds(EVP_CIPHER_nid)]
|
||||
pub fn nid(&self) -> Nid {
|
||||
let nid = unsafe { ffi::EVP_CIPHER_nid(self.as_ptr()) };
|
||||
Nid::from_raw(nid)
|
||||
}
|
||||
|
||||
/// Returns the length of keys used with this cipher.
|
||||
#[corresponds(EVP_CIPHER_key_length)]
|
||||
pub fn key_length(&self) -> usize {
|
||||
unsafe { EVP_CIPHER_key_length(self.as_ptr()) as usize }
|
||||
}
|
||||
|
||||
/// Returns the length of the IV used with this cipher.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// Ciphers that do not use an IV have an IV length of 0.
|
||||
#[corresponds(EVP_CIPHER_iv_length)]
|
||||
pub fn iv_length(&self) -> usize {
|
||||
unsafe { EVP_CIPHER_iv_length(self.as_ptr()) as usize }
|
||||
}
|
||||
|
||||
/// Returns the block size of the cipher.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// Stream ciphers have a block size of 1.
|
||||
#[corresponds(EVP_CIPHER_block_size)]
|
||||
pub fn block_size(&self) -> usize {
|
||||
unsafe { EVP_CIPHER_block_size(self.as_ptr()) as usize }
|
||||
}
|
||||
}
|
||||
1106
vendor/openssl/src/cipher_ctx.rs
vendored
Normal file
1106
vendor/openssl/src/cipher_ctx.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
484
vendor/openssl/src/cms.rs
vendored
Normal file
484
vendor/openssl/src/cms.rs
vendored
Normal file
|
|
@ -0,0 +1,484 @@
|
|||
//! SMIME implementation using CMS
|
||||
//!
|
||||
//! CMS (PKCS#7) is an encryption standard. It allows signing and encrypting data using
|
||||
//! X.509 certificates. The OpenSSL implementation of CMS is used in email encryption
|
||||
//! generated from a `Vec` of bytes. This `Vec` follows the smime protocol standards.
|
||||
//! Data accepted by this module will be smime type `enveloped-data`.
|
||||
|
||||
use bitflags::bitflags;
|
||||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
use libc::c_uint;
|
||||
use std::ptr;
|
||||
|
||||
use crate::bio::{MemBio, MemBioSlice};
|
||||
use crate::error::ErrorStack;
|
||||
use crate::pkey::{HasPrivate, PKeyRef};
|
||||
use crate::stack::StackRef;
|
||||
use crate::symm::Cipher;
|
||||
use crate::x509::{store::X509StoreRef, X509Ref, X509};
|
||||
use crate::{cvt, cvt_p};
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
bitflags! {
|
||||
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
#[repr(transparent)]
|
||||
pub struct CMSOptions : c_uint {
|
||||
const TEXT = ffi::CMS_TEXT;
|
||||
const CMS_NOCERTS = ffi::CMS_NOCERTS;
|
||||
const NO_CONTENT_VERIFY = ffi::CMS_NO_CONTENT_VERIFY;
|
||||
const NO_ATTR_VERIFY = ffi::CMS_NO_ATTR_VERIFY;
|
||||
const NOSIGS = ffi::CMS_NOSIGS;
|
||||
const NOINTERN = ffi::CMS_NOINTERN;
|
||||
const NO_SIGNER_CERT_VERIFY = ffi::CMS_NO_SIGNER_CERT_VERIFY;
|
||||
const NOVERIFY = ffi::CMS_NOVERIFY;
|
||||
const DETACHED = ffi::CMS_DETACHED;
|
||||
const BINARY = ffi::CMS_BINARY;
|
||||
const NOATTR = ffi::CMS_NOATTR;
|
||||
const NOSMIMECAP = ffi::CMS_NOSMIMECAP;
|
||||
const NOOLDMIMETYPE = ffi::CMS_NOOLDMIMETYPE;
|
||||
const CRLFEOL = ffi::CMS_CRLFEOL;
|
||||
const STREAM = ffi::CMS_STREAM;
|
||||
const NOCRL = ffi::CMS_NOCRL;
|
||||
const PARTIAL = ffi::CMS_PARTIAL;
|
||||
const REUSE_DIGEST = ffi::CMS_REUSE_DIGEST;
|
||||
const USE_KEYID = ffi::CMS_USE_KEYID;
|
||||
const DEBUG_DECRYPT = ffi::CMS_DEBUG_DECRYPT;
|
||||
#[cfg(all(not(libressl), not(ossl101)))]
|
||||
const KEY_PARAM = ffi::CMS_KEY_PARAM;
|
||||
#[cfg(all(not(libressl), not(ossl101), not(ossl102)))]
|
||||
const ASCIICRLF = ffi::CMS_ASCIICRLF;
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::CMS_ContentInfo;
|
||||
fn drop = ffi::CMS_ContentInfo_free;
|
||||
|
||||
/// High level CMS wrapper
|
||||
///
|
||||
/// CMS supports nesting various types of data, including signatures, certificates,
|
||||
/// encrypted data, smime messages (encrypted email), and data digest. The ContentInfo
|
||||
/// content type is the encapsulation of all those content types. [`RFC 5652`] describes
|
||||
/// CMS and OpenSSL follows this RFC's implementation.
|
||||
///
|
||||
/// [`RFC 5652`]: https://tools.ietf.org/html/rfc5652#page-6
|
||||
pub struct CmsContentInfo;
|
||||
/// Reference to [`CMSContentInfo`]
|
||||
///
|
||||
/// [`CMSContentInfo`]:struct.CmsContentInfo.html
|
||||
pub struct CmsContentInfoRef;
|
||||
}
|
||||
|
||||
impl CmsContentInfoRef {
|
||||
/// Given the sender's private key, `pkey` and the recipient's certificate, `cert`,
|
||||
/// decrypt the data in `self`.
|
||||
#[corresponds(CMS_decrypt)]
|
||||
pub fn decrypt<T>(&self, pkey: &PKeyRef<T>, cert: &X509) -> Result<Vec<u8>, ErrorStack>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
unsafe {
|
||||
let pkey = pkey.as_ptr();
|
||||
let cert = cert.as_ptr();
|
||||
let out = MemBio::new()?;
|
||||
|
||||
cvt(ffi::CMS_decrypt(
|
||||
self.as_ptr(),
|
||||
pkey,
|
||||
cert,
|
||||
ptr::null_mut(),
|
||||
out.as_ptr(),
|
||||
0,
|
||||
))?;
|
||||
|
||||
Ok(out.get_buf().to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
/// Given the sender's private key, `pkey`,
|
||||
/// decrypt the data in `self` without validating the recipient certificate.
|
||||
///
|
||||
/// *Warning*: Not checking the recipient certificate may leave you vulnerable to Bleichenbacher's attack on PKCS#1 v1.5 RSA padding.
|
||||
#[corresponds(CMS_decrypt)]
|
||||
// FIXME merge into decrypt
|
||||
pub fn decrypt_without_cert_check<T>(&self, pkey: &PKeyRef<T>) -> Result<Vec<u8>, ErrorStack>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
unsafe {
|
||||
let pkey = pkey.as_ptr();
|
||||
let out = MemBio::new()?;
|
||||
|
||||
cvt(ffi::CMS_decrypt(
|
||||
self.as_ptr(),
|
||||
pkey,
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
out.as_ptr(),
|
||||
0,
|
||||
))?;
|
||||
|
||||
Ok(out.get_buf().to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
to_der! {
|
||||
/// Serializes this CmsContentInfo using DER.
|
||||
#[corresponds(i2d_CMS_ContentInfo)]
|
||||
to_der,
|
||||
ffi::i2d_CMS_ContentInfo
|
||||
}
|
||||
|
||||
to_pem! {
|
||||
/// Serializes this CmsContentInfo using DER.
|
||||
#[corresponds(PEM_write_bio_CMS)]
|
||||
to_pem,
|
||||
ffi::PEM_write_bio_CMS
|
||||
}
|
||||
}
|
||||
|
||||
impl CmsContentInfo {
|
||||
/// Parses a smime formatted `vec` of bytes into a `CmsContentInfo`.
|
||||
#[corresponds(SMIME_read_CMS)]
|
||||
pub fn smime_read_cms(smime: &[u8]) -> Result<CmsContentInfo, ErrorStack> {
|
||||
unsafe {
|
||||
let bio = MemBioSlice::new(smime)?;
|
||||
|
||||
let cms = cvt_p(ffi::SMIME_read_CMS(bio.as_ptr(), ptr::null_mut()))?;
|
||||
|
||||
Ok(CmsContentInfo::from_ptr(cms))
|
||||
}
|
||||
}
|
||||
|
||||
from_der! {
|
||||
/// Deserializes a DER-encoded ContentInfo structure.
|
||||
#[corresponds(d2i_CMS_ContentInfo)]
|
||||
from_der,
|
||||
CmsContentInfo,
|
||||
ffi::d2i_CMS_ContentInfo
|
||||
}
|
||||
|
||||
from_pem! {
|
||||
/// Deserializes a PEM-encoded ContentInfo structure.
|
||||
#[corresponds(PEM_read_bio_CMS)]
|
||||
from_pem,
|
||||
CmsContentInfo,
|
||||
ffi::PEM_read_bio_CMS
|
||||
}
|
||||
|
||||
/// Given a signing cert `signcert`, private key `pkey`, a certificate stack `certs`,
|
||||
/// data `data` and flags `flags`, create a CmsContentInfo struct.
|
||||
///
|
||||
/// All arguments are optional.
|
||||
#[corresponds(CMS_sign)]
|
||||
pub fn sign<T>(
|
||||
signcert: Option<&X509Ref>,
|
||||
pkey: Option<&PKeyRef<T>>,
|
||||
certs: Option<&StackRef<X509>>,
|
||||
data: Option<&[u8]>,
|
||||
flags: CMSOptions,
|
||||
) -> Result<CmsContentInfo, ErrorStack>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
unsafe {
|
||||
let signcert = signcert.map_or(ptr::null_mut(), |p| p.as_ptr());
|
||||
let pkey = pkey.map_or(ptr::null_mut(), |p| p.as_ptr());
|
||||
let data_bio = match data {
|
||||
Some(data) => Some(MemBioSlice::new(data)?),
|
||||
None => None,
|
||||
};
|
||||
let data_bio_ptr = data_bio.as_ref().map_or(ptr::null_mut(), |p| p.as_ptr());
|
||||
let certs = certs.map_or(ptr::null_mut(), |p| p.as_ptr());
|
||||
|
||||
let cms = cvt_p(ffi::CMS_sign(
|
||||
signcert,
|
||||
pkey,
|
||||
certs,
|
||||
data_bio_ptr,
|
||||
flags.bits(),
|
||||
))?;
|
||||
|
||||
Ok(CmsContentInfo::from_ptr(cms))
|
||||
}
|
||||
}
|
||||
|
||||
/// Given a certificate stack `certs`, data `data`, cipher `cipher` and flags `flags`,
|
||||
/// create a CmsContentInfo struct.
|
||||
///
|
||||
/// OpenSSL documentation at [`CMS_encrypt`]
|
||||
///
|
||||
/// [`CMS_encrypt`]: https://www.openssl.org/docs/manmaster/man3/CMS_encrypt.html
|
||||
#[corresponds(CMS_encrypt)]
|
||||
pub fn encrypt(
|
||||
certs: &StackRef<X509>,
|
||||
data: &[u8],
|
||||
cipher: Cipher,
|
||||
flags: CMSOptions,
|
||||
) -> Result<CmsContentInfo, ErrorStack> {
|
||||
unsafe {
|
||||
let data_bio = MemBioSlice::new(data)?;
|
||||
|
||||
let cms = cvt_p(ffi::CMS_encrypt(
|
||||
certs.as_ptr(),
|
||||
data_bio.as_ptr(),
|
||||
cipher.as_ptr(),
|
||||
flags.bits(),
|
||||
))?;
|
||||
|
||||
Ok(CmsContentInfo::from_ptr(cms))
|
||||
}
|
||||
}
|
||||
|
||||
/// Verify this CmsContentInfo's signature,
|
||||
/// This will search the 'certs' list for the signing certificate.
|
||||
/// Additional certificates, needed for building the certificate chain, may be
|
||||
/// given in 'store' as well as additional CRLs.
|
||||
/// A detached signature may be passed in `detached_data`. The signed content
|
||||
/// without signature, will be copied into output_data if it is present.
|
||||
///
|
||||
#[corresponds(CMS_verify)]
|
||||
pub fn verify(
|
||||
&mut self,
|
||||
certs: Option<&StackRef<X509>>,
|
||||
store: Option<&X509StoreRef>,
|
||||
detached_data: Option<&[u8]>,
|
||||
output_data: Option<&mut Vec<u8>>,
|
||||
flags: CMSOptions,
|
||||
) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
let certs_ptr = certs.map_or(ptr::null_mut(), |p| p.as_ptr());
|
||||
let store_ptr = store.map_or(ptr::null_mut(), |p| p.as_ptr());
|
||||
let detached_data_bio = match detached_data {
|
||||
Some(data) => Some(MemBioSlice::new(data)?),
|
||||
None => None,
|
||||
};
|
||||
let detached_data_bio_ptr = detached_data_bio
|
||||
.as_ref()
|
||||
.map_or(ptr::null_mut(), |p| p.as_ptr());
|
||||
let out_bio = MemBio::new()?;
|
||||
|
||||
cvt(ffi::CMS_verify(
|
||||
self.as_ptr(),
|
||||
certs_ptr,
|
||||
store_ptr,
|
||||
detached_data_bio_ptr,
|
||||
out_bio.as_ptr(),
|
||||
flags.bits(),
|
||||
))?;
|
||||
|
||||
if let Some(data) = output_data {
|
||||
data.clear();
|
||||
data.extend_from_slice(out_bio.get_buf());
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
use crate::pkcs12::Pkcs12;
|
||||
use crate::pkey::PKey;
|
||||
use crate::stack::Stack;
|
||||
use crate::x509::{
|
||||
store::{X509Store, X509StoreBuilder},
|
||||
X509,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn cms_encrypt_decrypt() {
|
||||
#[cfg(ossl300)]
|
||||
let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap();
|
||||
|
||||
// load cert with public key only
|
||||
let pub_cert_bytes = include_bytes!("../test/cms_pubkey.der");
|
||||
let pub_cert = X509::from_der(pub_cert_bytes).expect("failed to load pub cert");
|
||||
|
||||
// load cert with private key
|
||||
let priv_cert_bytes = include_bytes!("../test/cms.p12");
|
||||
let priv_cert = Pkcs12::from_der(priv_cert_bytes).expect("failed to load priv cert");
|
||||
let priv_cert = priv_cert
|
||||
.parse2("mypass")
|
||||
.expect("failed to parse priv cert");
|
||||
|
||||
// encrypt cms message using public key cert
|
||||
let input = String::from("My Message");
|
||||
let mut cert_stack = Stack::new().expect("failed to create stack");
|
||||
cert_stack
|
||||
.push(pub_cert)
|
||||
.expect("failed to add pub cert to stack");
|
||||
|
||||
let encrypt = CmsContentInfo::encrypt(
|
||||
&cert_stack,
|
||||
input.as_bytes(),
|
||||
Cipher::des_ede3_cbc(),
|
||||
CMSOptions::empty(),
|
||||
)
|
||||
.expect("failed create encrypted cms");
|
||||
|
||||
// decrypt cms message using private key cert (DER)
|
||||
{
|
||||
let encrypted_der = encrypt.to_der().expect("failed to create der from cms");
|
||||
let decrypt =
|
||||
CmsContentInfo::from_der(&encrypted_der).expect("failed read cms from der");
|
||||
|
||||
let decrypt_with_cert_check = decrypt
|
||||
.decrypt(
|
||||
priv_cert.pkey.as_ref().unwrap(),
|
||||
priv_cert.cert.as_ref().unwrap(),
|
||||
)
|
||||
.expect("failed to decrypt cms");
|
||||
let decrypt_with_cert_check = String::from_utf8(decrypt_with_cert_check)
|
||||
.expect("failed to create string from cms content");
|
||||
|
||||
let decrypt_without_cert_check = decrypt
|
||||
.decrypt_without_cert_check(priv_cert.pkey.as_ref().unwrap())
|
||||
.expect("failed to decrypt cms");
|
||||
let decrypt_without_cert_check = String::from_utf8(decrypt_without_cert_check)
|
||||
.expect("failed to create string from cms content");
|
||||
|
||||
assert_eq!(input, decrypt_with_cert_check);
|
||||
assert_eq!(input, decrypt_without_cert_check);
|
||||
}
|
||||
|
||||
// decrypt cms message using private key cert (PEM)
|
||||
{
|
||||
let encrypted_pem = encrypt.to_pem().expect("failed to create pem from cms");
|
||||
let decrypt =
|
||||
CmsContentInfo::from_pem(&encrypted_pem).expect("failed read cms from pem");
|
||||
|
||||
let decrypt_with_cert_check = decrypt
|
||||
.decrypt(
|
||||
priv_cert.pkey.as_ref().unwrap(),
|
||||
priv_cert.cert.as_ref().unwrap(),
|
||||
)
|
||||
.expect("failed to decrypt cms");
|
||||
let decrypt_with_cert_check = String::from_utf8(decrypt_with_cert_check)
|
||||
.expect("failed to create string from cms content");
|
||||
|
||||
let decrypt_without_cert_check = decrypt
|
||||
.decrypt_without_cert_check(priv_cert.pkey.as_ref().unwrap())
|
||||
.expect("failed to decrypt cms");
|
||||
let decrypt_without_cert_check = String::from_utf8(decrypt_without_cert_check)
|
||||
.expect("failed to create string from cms content");
|
||||
|
||||
assert_eq!(input, decrypt_with_cert_check);
|
||||
assert_eq!(input, decrypt_without_cert_check);
|
||||
}
|
||||
}
|
||||
|
||||
fn cms_sign_verify_generic_helper(is_detached: bool) {
|
||||
// load cert with private key
|
||||
let cert_bytes = include_bytes!("../test/cert.pem");
|
||||
let cert = X509::from_pem(cert_bytes).expect("failed to load cert.pem");
|
||||
|
||||
let key_bytes = include_bytes!("../test/key.pem");
|
||||
let key = PKey::private_key_from_pem(key_bytes).expect("failed to load key.pem");
|
||||
|
||||
let root_bytes = include_bytes!("../test/root-ca.pem");
|
||||
let root = X509::from_pem(root_bytes).expect("failed to load root-ca.pem");
|
||||
|
||||
// sign cms message using public key cert
|
||||
let data = b"Hello world!";
|
||||
|
||||
let (opt, ext_data): (CMSOptions, Option<&[u8]>) = if is_detached {
|
||||
(CMSOptions::DETACHED | CMSOptions::BINARY, Some(data))
|
||||
} else {
|
||||
(CMSOptions::empty(), None)
|
||||
};
|
||||
|
||||
let mut cms = CmsContentInfo::sign(Some(&cert), Some(&key), None, Some(data), opt)
|
||||
.expect("failed to CMS sign a message");
|
||||
|
||||
// check CMS signature length
|
||||
let pem_cms = cms
|
||||
.to_pem()
|
||||
.expect("failed to pack CmsContentInfo into PEM");
|
||||
assert!(!pem_cms.is_empty());
|
||||
|
||||
// verify CMS signature
|
||||
let mut builder = X509StoreBuilder::new().expect("failed to create X509StoreBuilder");
|
||||
builder
|
||||
.add_cert(root)
|
||||
.expect("failed to add root-ca into X509StoreBuilder");
|
||||
let store: X509Store = builder.build();
|
||||
let mut out_data: Vec<u8> = Vec::new();
|
||||
let res = cms.verify(
|
||||
None,
|
||||
Some(&store),
|
||||
ext_data,
|
||||
Some(&mut out_data),
|
||||
CMSOptions::empty(),
|
||||
);
|
||||
|
||||
// check verification result - valid signature
|
||||
res.unwrap();
|
||||
assert_eq!(data.to_vec(), out_data);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cms_sign_verify_ok() {
|
||||
cms_sign_verify_generic_helper(false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cms_sign_verify_detached_ok() {
|
||||
cms_sign_verify_generic_helper(true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cms_sign_verify_error() {
|
||||
#[cfg(ossl300)]
|
||||
let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap();
|
||||
|
||||
// load cert with private key
|
||||
let priv_cert_bytes = include_bytes!("../test/cms.p12");
|
||||
let priv_cert = Pkcs12::from_der(priv_cert_bytes).expect("failed to load priv cert");
|
||||
let priv_cert = priv_cert
|
||||
.parse2("mypass")
|
||||
.expect("failed to parse priv cert");
|
||||
|
||||
// sign cms message using public key cert
|
||||
let data = b"Hello world!";
|
||||
let mut cms = CmsContentInfo::sign(
|
||||
Some(&priv_cert.cert.unwrap()),
|
||||
Some(&priv_cert.pkey.unwrap()),
|
||||
None,
|
||||
Some(data),
|
||||
CMSOptions::empty(),
|
||||
)
|
||||
.expect("failed to CMS sign a message");
|
||||
|
||||
// check CMS signature length
|
||||
let pem_cms = cms
|
||||
.to_pem()
|
||||
.expect("failed to pack CmsContentInfo into PEM");
|
||||
assert!(!pem_cms.is_empty());
|
||||
|
||||
let empty_store = X509StoreBuilder::new()
|
||||
.expect("failed to create X509StoreBuilder")
|
||||
.build();
|
||||
|
||||
// verify CMS signature
|
||||
let res = cms.verify(
|
||||
None,
|
||||
Some(&empty_store),
|
||||
Some(data),
|
||||
None,
|
||||
CMSOptions::empty(),
|
||||
);
|
||||
|
||||
// check verification result - this is an invalid signature
|
||||
// defined in openssl crypto/cms/cms.h
|
||||
const CMS_R_CERTIFICATE_VERIFY_ERROR: i32 = 100;
|
||||
let es = res.unwrap_err();
|
||||
let error_array = es.errors();
|
||||
assert_eq!(1, error_array.len());
|
||||
let code = error_array[0].reason_code();
|
||||
assert_eq!(code, CMS_R_CERTIFICATE_VERIFY_ERROR);
|
||||
}
|
||||
}
|
||||
65
vendor/openssl/src/conf.rs
vendored
Normal file
65
vendor/openssl/src/conf.rs
vendored
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
//! Interface for processing OpenSSL configuration files.
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::CONF;
|
||||
fn drop = ffi::NCONF_free;
|
||||
|
||||
pub struct Conf;
|
||||
pub struct ConfRef;
|
||||
}
|
||||
|
||||
#[cfg(not(any(boringssl, libressl400)))]
|
||||
mod methods {
|
||||
use super::Conf;
|
||||
use crate::cvt_p;
|
||||
use crate::error::ErrorStack;
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
pub struct ConfMethod(*mut ffi::CONF_METHOD);
|
||||
|
||||
impl ConfMethod {
|
||||
/// Retrieve handle to the default OpenSSL configuration file processing function.
|
||||
#[corresponds(NCONF_default)]
|
||||
#[allow(clippy::should_implement_trait)]
|
||||
pub fn default() -> ConfMethod {
|
||||
unsafe {
|
||||
ffi::init();
|
||||
// `NCONF` stands for "New Conf", as described in crypto/conf/conf_lib.c. This is
|
||||
// a newer API than the "CONF classic" functions.
|
||||
ConfMethod(ffi::NCONF_default())
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct from raw pointer.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller must ensure that the pointer is valid.
|
||||
pub unsafe fn from_ptr(ptr: *mut ffi::CONF_METHOD) -> ConfMethod {
|
||||
ConfMethod(ptr)
|
||||
}
|
||||
|
||||
/// Convert to raw pointer.
|
||||
pub fn as_ptr(&self) -> *mut ffi::CONF_METHOD {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Conf {
|
||||
/// Create a configuration parser.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use openssl::conf::{Conf, ConfMethod};
|
||||
///
|
||||
/// let conf = Conf::new(ConfMethod::default());
|
||||
/// ```
|
||||
#[corresponds(NCONF_new)]
|
||||
pub fn new(method: ConfMethod) -> Result<Conf, ErrorStack> {
|
||||
unsafe { cvt_p(ffi::NCONF_new(method.as_ptr())).map(Conf) }
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(not(any(boringssl, libressl400)))]
|
||||
pub use methods::*;
|
||||
217
vendor/openssl/src/derive.rs
vendored
Normal file
217
vendor/openssl/src/derive.rs
vendored
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
//! Shared secret derivation.
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! The following example implements [ECDH] using `NIST P-384` keys:
|
||||
//!
|
||||
//! ```
|
||||
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
//! # use std::convert::TryInto;
|
||||
//! use openssl::bn::BigNumContext;
|
||||
//! use openssl::pkey::PKey;
|
||||
//! use openssl::derive::Deriver;
|
||||
//! use openssl::ec::{EcGroup, EcKey, EcPoint, PointConversionForm};
|
||||
//! use openssl::nid::Nid;
|
||||
//!
|
||||
//! let group = EcGroup::from_curve_name(Nid::SECP384R1)?;
|
||||
//!
|
||||
//! let first: PKey<_> = EcKey::generate(&group)?.try_into()?;
|
||||
//!
|
||||
//! // second party generates an ephemeral key and derives
|
||||
//! // a shared secret using first party's public key
|
||||
//! let shared_key = EcKey::generate(&group)?;
|
||||
//! // shared_public is sent to first party
|
||||
//! let mut ctx = BigNumContext::new()?;
|
||||
//! let shared_public = shared_key.public_key().to_bytes(
|
||||
//! &group,
|
||||
//! PointConversionForm::COMPRESSED,
|
||||
//! &mut ctx,
|
||||
//! )?;
|
||||
//!
|
||||
//! let shared_key: PKey<_> = shared_key.try_into()?;
|
||||
//! let mut deriver = Deriver::new(&shared_key)?;
|
||||
//! deriver.set_peer(&first)?;
|
||||
//! // secret can be used e.g. as a symmetric encryption key
|
||||
//! let secret = deriver.derive_to_vec()?;
|
||||
//! # drop(deriver);
|
||||
//!
|
||||
//! // first party derives the same shared secret using
|
||||
//! // shared_public
|
||||
//! let point = EcPoint::from_bytes(&group, &shared_public, &mut ctx)?;
|
||||
//! let recipient_key: PKey<_> = EcKey::from_public_key(&group, &point)?.try_into()?;
|
||||
//! let mut deriver = Deriver::new(&first)?;
|
||||
//! deriver.set_peer(&recipient_key)?;
|
||||
//! let first_secret = deriver.derive_to_vec()?;
|
||||
//!
|
||||
//! assert_eq!(secret, first_secret);
|
||||
//! # Ok(()) }
|
||||
//! ```
|
||||
//!
|
||||
//! [ECDH]: https://wiki.openssl.org/index.php/Elliptic_Curve_Diffie_Hellman
|
||||
|
||||
use foreign_types::ForeignTypeRef;
|
||||
use std::marker::PhantomData;
|
||||
use std::ptr;
|
||||
|
||||
use crate::error::ErrorStack;
|
||||
use crate::pkey::{HasPrivate, HasPublic, PKeyRef};
|
||||
use crate::{cvt, cvt_p};
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
/// A type used to derive a shared secret between two keys.
|
||||
pub struct Deriver<'a>(*mut ffi::EVP_PKEY_CTX, PhantomData<&'a ()>);
|
||||
|
||||
unsafe impl Sync for Deriver<'_> {}
|
||||
unsafe impl Send for Deriver<'_> {}
|
||||
|
||||
#[allow(clippy::len_without_is_empty)]
|
||||
impl<'a> Deriver<'a> {
|
||||
/// Creates a new `Deriver` using the provided private key.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_derive_init`].
|
||||
///
|
||||
/// [`EVP_PKEY_derive_init`]: https://www.openssl.org/docs/manmaster/crypto/EVP_PKEY_derive_init.html
|
||||
pub fn new<T>(key: &'a PKeyRef<T>) -> Result<Deriver<'a>, ErrorStack>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
unsafe {
|
||||
cvt_p(ffi::EVP_PKEY_CTX_new(key.as_ptr(), ptr::null_mut()))
|
||||
.map(|p| Deriver(p, PhantomData))
|
||||
.and_then(|ctx| cvt(ffi::EVP_PKEY_derive_init(ctx.0)).map(|_| ctx))
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the peer key used for secret derivation.
|
||||
#[corresponds(EVP_PKEY_derive_set_peer)]
|
||||
pub fn set_peer<T>(&mut self, key: &'a PKeyRef<T>) -> Result<(), ErrorStack>
|
||||
where
|
||||
T: HasPublic,
|
||||
{
|
||||
unsafe { cvt(ffi::EVP_PKEY_derive_set_peer(self.0, key.as_ptr())).map(|_| ()) }
|
||||
}
|
||||
|
||||
/// Sets the peer key used for secret derivation along with optionally validating the peer public key.
|
||||
///
|
||||
/// Requires OpenSSL 3.0.0 or newer.
|
||||
#[corresponds(EVP_PKEY_derive_set_peer_ex)]
|
||||
#[cfg(ossl300)]
|
||||
pub fn set_peer_ex<T>(
|
||||
&mut self,
|
||||
key: &'a PKeyRef<T>,
|
||||
validate_peer: bool,
|
||||
) -> Result<(), ErrorStack>
|
||||
where
|
||||
T: HasPublic,
|
||||
{
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_derive_set_peer_ex(
|
||||
self.0,
|
||||
key.as_ptr(),
|
||||
validate_peer as i32,
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the size of the shared secret.
|
||||
///
|
||||
/// It can be used to size the buffer passed to [`Deriver::derive`].
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_derive`].
|
||||
///
|
||||
/// [`Deriver::derive`]: #method.derive
|
||||
/// [`EVP_PKEY_derive`]: https://www.openssl.org/docs/manmaster/crypto/EVP_PKEY_derive_init.html
|
||||
pub fn len(&mut self) -> Result<usize, ErrorStack> {
|
||||
unsafe {
|
||||
let mut len = 0;
|
||||
cvt(ffi::EVP_PKEY_derive(self.0, ptr::null_mut(), &mut len)).map(|_| len)
|
||||
}
|
||||
}
|
||||
|
||||
/// Derives a shared secret between the two keys, writing it into the buffer.
|
||||
///
|
||||
/// Returns the number of bytes written.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_derive`].
|
||||
///
|
||||
/// [`EVP_PKEY_derive`]: https://www.openssl.org/docs/manmaster/crypto/EVP_PKEY_derive_init.html
|
||||
pub fn derive(&mut self, buf: &mut [u8]) -> Result<usize, ErrorStack> {
|
||||
let mut len = buf.len();
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_derive(
|
||||
self.0,
|
||||
buf.as_mut_ptr() as *mut _,
|
||||
&mut len,
|
||||
))
|
||||
.map(|_| len)
|
||||
}
|
||||
}
|
||||
|
||||
/// A convenience function which derives a shared secret and returns it in a new buffer.
|
||||
///
|
||||
/// This simply wraps [`Deriver::len`] and [`Deriver::derive`].
|
||||
///
|
||||
/// [`Deriver::len`]: #method.len
|
||||
/// [`Deriver::derive`]: #method.derive
|
||||
pub fn derive_to_vec(&mut self) -> Result<Vec<u8>, ErrorStack> {
|
||||
let len = self.len()?;
|
||||
let mut buf = vec![0; len];
|
||||
let len = self.derive(&mut buf)?;
|
||||
buf.truncate(len);
|
||||
Ok(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Deriver<'_> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
ffi::EVP_PKEY_CTX_free(self.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
use crate::ec::{EcGroup, EcKey};
|
||||
use crate::nid::Nid;
|
||||
use crate::pkey::PKey;
|
||||
|
||||
#[test]
|
||||
fn derive_without_peer() {
|
||||
let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
|
||||
let ec_key = EcKey::generate(&group).unwrap();
|
||||
let pkey = PKey::from_ec_key(ec_key).unwrap();
|
||||
let mut deriver = Deriver::new(&pkey).unwrap();
|
||||
deriver.derive_to_vec().unwrap_err();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ec_key_derive() {
|
||||
let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
|
||||
let ec_key = EcKey::generate(&group).unwrap();
|
||||
let ec_key2 = EcKey::generate(&group).unwrap();
|
||||
let pkey = PKey::from_ec_key(ec_key).unwrap();
|
||||
let pkey2 = PKey::from_ec_key(ec_key2).unwrap();
|
||||
let mut deriver = Deriver::new(&pkey).unwrap();
|
||||
deriver.set_peer(&pkey2).unwrap();
|
||||
let shared = deriver.derive_to_vec().unwrap();
|
||||
assert!(!shared.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl300)]
|
||||
fn test_ec_key_derive_ex() {
|
||||
let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
|
||||
let ec_key = EcKey::generate(&group).unwrap();
|
||||
let ec_key2 = EcKey::generate(&group).unwrap();
|
||||
let pkey = PKey::from_ec_key(ec_key).unwrap();
|
||||
let pkey2 = PKey::from_ec_key(ec_key2).unwrap();
|
||||
let mut deriver = Deriver::new(&pkey).unwrap();
|
||||
deriver.set_peer_ex(&pkey2, true).unwrap();
|
||||
let shared = deriver.derive_to_vec().unwrap();
|
||||
assert!(!shared.is_empty());
|
||||
}
|
||||
}
|
||||
499
vendor/openssl/src/dh.rs
vendored
Normal file
499
vendor/openssl/src/dh.rs
vendored
Normal file
|
|
@ -0,0 +1,499 @@
|
|||
//! Diffie-Hellman key agreement.
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
|
||||
use crate::bn::{BigNum, BigNumRef};
|
||||
use crate::error::ErrorStack;
|
||||
use crate::pkey::{HasParams, HasPrivate, HasPublic, Params, Private, Public};
|
||||
use crate::{cvt, cvt_p};
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
generic_foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::DH;
|
||||
fn drop = ffi::DH_free;
|
||||
|
||||
pub struct Dh<T>;
|
||||
|
||||
pub struct DhRef<T>;
|
||||
}
|
||||
|
||||
impl<T> DhRef<T>
|
||||
where
|
||||
T: HasParams,
|
||||
{
|
||||
to_pem! {
|
||||
/// Serializes the parameters into a PEM-encoded PKCS#3 DHparameter structure.
|
||||
///
|
||||
/// The output will have a header of `-----BEGIN DH PARAMETERS-----`.
|
||||
#[corresponds(PEM_write_bio_DHparams)]
|
||||
params_to_pem,
|
||||
ffi::PEM_write_bio_DHparams
|
||||
}
|
||||
|
||||
to_der! {
|
||||
/// Serializes the parameters into a DER-encoded PKCS#3 DHparameter structure.
|
||||
#[corresponds(i2d_DHparams)]
|
||||
params_to_der,
|
||||
ffi::i2d_DHparams
|
||||
}
|
||||
|
||||
/// Validates DH parameters for correctness
|
||||
#[corresponds(DH_check_key)]
|
||||
pub fn check_key(&self) -> Result<bool, ErrorStack> {
|
||||
unsafe {
|
||||
let mut codes = 0;
|
||||
cvt(ffi::DH_check(self.as_ptr(), &mut codes))?;
|
||||
Ok(codes == 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Dh<Params> {
|
||||
pub fn from_params(p: BigNum, g: BigNum, q: BigNum) -> Result<Dh<Params>, ErrorStack> {
|
||||
Self::from_pqg(p, Some(q), g)
|
||||
}
|
||||
|
||||
/// Creates a DH instance based upon the given primes and generator params.
|
||||
#[corresponds(DH_set0_pqg)]
|
||||
pub fn from_pqg(
|
||||
prime_p: BigNum,
|
||||
prime_q: Option<BigNum>,
|
||||
generator: BigNum,
|
||||
) -> Result<Dh<Params>, ErrorStack> {
|
||||
unsafe {
|
||||
let dh = Dh::from_ptr(cvt_p(ffi::DH_new())?);
|
||||
cvt(DH_set0_pqg(
|
||||
dh.0,
|
||||
prime_p.as_ptr(),
|
||||
prime_q.as_ref().map_or(ptr::null_mut(), |q| q.as_ptr()),
|
||||
generator.as_ptr(),
|
||||
))?;
|
||||
mem::forget((prime_p, prime_q, generator));
|
||||
Ok(dh)
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the public key on the DH object.
|
||||
pub fn set_public_key(self, pub_key: BigNum) -> Result<Dh<Public>, ErrorStack> {
|
||||
unsafe {
|
||||
let dh_ptr = self.0;
|
||||
cvt(DH_set0_key(dh_ptr, pub_key.as_ptr(), ptr::null_mut()))?;
|
||||
mem::forget((self, pub_key));
|
||||
Ok(Dh::from_ptr(dh_ptr))
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the private key on the DH object and recomputes the public key.
|
||||
pub fn set_private_key(self, priv_key: BigNum) -> Result<Dh<Private>, ErrorStack> {
|
||||
unsafe {
|
||||
let dh_ptr = self.0;
|
||||
cvt(DH_set0_key(dh_ptr, ptr::null_mut(), priv_key.as_ptr()))?;
|
||||
mem::forget(priv_key);
|
||||
|
||||
cvt(ffi::DH_generate_key(dh_ptr))?;
|
||||
mem::forget(self);
|
||||
Ok(Dh::from_ptr(dh_ptr))
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the public and private keys on the DH object.
|
||||
pub fn set_key(self, pub_key: BigNum, priv_key: BigNum) -> Result<Dh<Private>, ErrorStack> {
|
||||
unsafe {
|
||||
let dh_ptr = self.0;
|
||||
cvt(DH_set0_key(dh_ptr, pub_key.as_ptr(), priv_key.as_ptr()))?;
|
||||
mem::forget((self, pub_key, priv_key));
|
||||
Ok(Dh::from_ptr(dh_ptr))
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates DH params based on the given `prime_len` and a fixed `generator` value.
|
||||
#[corresponds(DH_generate_parameters_ex)]
|
||||
pub fn generate_params(prime_len: u32, generator: u32) -> Result<Dh<Params>, ErrorStack> {
|
||||
unsafe {
|
||||
let dh = Dh::from_ptr(cvt_p(ffi::DH_new())?);
|
||||
cvt(ffi::DH_generate_parameters_ex(
|
||||
dh.0,
|
||||
prime_len as i32,
|
||||
generator as i32,
|
||||
ptr::null_mut(),
|
||||
))?;
|
||||
Ok(dh)
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates a public and a private key based on the DH params.
|
||||
#[corresponds(DH_generate_key)]
|
||||
pub fn generate_key(self) -> Result<Dh<Private>, ErrorStack> {
|
||||
unsafe {
|
||||
let dh_ptr = self.0;
|
||||
cvt(ffi::DH_generate_key(dh_ptr))?;
|
||||
mem::forget(self);
|
||||
Ok(Dh::from_ptr(dh_ptr))
|
||||
}
|
||||
}
|
||||
|
||||
from_pem! {
|
||||
/// Deserializes a PEM-encoded PKCS#3 DHpararameters structure.
|
||||
///
|
||||
/// The input should have a header of `-----BEGIN DH PARAMETERS-----`.
|
||||
#[corresponds(PEM_read_bio_DHparams)]
|
||||
params_from_pem,
|
||||
Dh<Params>,
|
||||
ffi::PEM_read_bio_DHparams
|
||||
}
|
||||
|
||||
from_der! {
|
||||
/// Deserializes a DER-encoded PKCS#3 DHparameters structure.
|
||||
#[corresponds(d2i_DHparams)]
|
||||
params_from_der,
|
||||
Dh<Params>,
|
||||
ffi::d2i_DHparams
|
||||
}
|
||||
|
||||
/// Requires OpenSSL 1.0.2 or newer.
|
||||
#[corresponds(DH_get_1024_160)]
|
||||
#[cfg(any(ossl102, ossl110))]
|
||||
pub fn get_1024_160() -> Result<Dh<Params>, ErrorStack> {
|
||||
unsafe {
|
||||
ffi::init();
|
||||
cvt_p(ffi::DH_get_1024_160()).map(|p| Dh::from_ptr(p))
|
||||
}
|
||||
}
|
||||
|
||||
/// Requires OpenSSL 1.0.2 or newer.
|
||||
#[corresponds(DH_get_2048_224)]
|
||||
#[cfg(any(ossl102, ossl110))]
|
||||
pub fn get_2048_224() -> Result<Dh<Params>, ErrorStack> {
|
||||
unsafe {
|
||||
ffi::init();
|
||||
cvt_p(ffi::DH_get_2048_224()).map(|p| Dh::from_ptr(p))
|
||||
}
|
||||
}
|
||||
|
||||
/// Requires OpenSSL 1.0.2 or newer.
|
||||
#[corresponds(DH_get_2048_256)]
|
||||
#[cfg(any(ossl102, ossl110))]
|
||||
pub fn get_2048_256() -> Result<Dh<Params>, ErrorStack> {
|
||||
unsafe {
|
||||
ffi::init();
|
||||
cvt_p(ffi::DH_get_2048_256()).map(|p| Dh::from_ptr(p))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Dh<T>
|
||||
where
|
||||
T: HasParams,
|
||||
{
|
||||
/// Returns the prime `p` from the DH instance.
|
||||
#[corresponds(DH_get0_pqg)]
|
||||
pub fn prime_p(&self) -> &BigNumRef {
|
||||
let mut p = ptr::null();
|
||||
unsafe {
|
||||
DH_get0_pqg(self.as_ptr(), &mut p, ptr::null_mut(), ptr::null_mut());
|
||||
BigNumRef::from_ptr(p as *mut _)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the prime `q` from the DH instance.
|
||||
#[corresponds(DH_get0_pqg)]
|
||||
pub fn prime_q(&self) -> Option<&BigNumRef> {
|
||||
let mut q = ptr::null();
|
||||
unsafe {
|
||||
DH_get0_pqg(self.as_ptr(), ptr::null_mut(), &mut q, ptr::null_mut());
|
||||
if q.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(BigNumRef::from_ptr(q as *mut _))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the generator from the DH instance.
|
||||
#[corresponds(DH_get0_pqg)]
|
||||
pub fn generator(&self) -> &BigNumRef {
|
||||
let mut g = ptr::null();
|
||||
unsafe {
|
||||
DH_get0_pqg(self.as_ptr(), ptr::null_mut(), ptr::null_mut(), &mut g);
|
||||
BigNumRef::from_ptr(g as *mut _)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DhRef<T>
|
||||
where
|
||||
T: HasPublic,
|
||||
{
|
||||
/// Returns the public key from the DH instance.
|
||||
#[corresponds(DH_get0_key)]
|
||||
pub fn public_key(&self) -> &BigNumRef {
|
||||
let mut pub_key = ptr::null();
|
||||
unsafe {
|
||||
DH_get0_key(self.as_ptr(), &mut pub_key, ptr::null_mut());
|
||||
BigNumRef::from_ptr(pub_key as *mut _)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DhRef<T>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
/// Computes a shared secret from the own private key and the given `public_key`.
|
||||
#[corresponds(DH_compute_key)]
|
||||
pub fn compute_key(&self, public_key: &BigNumRef) -> Result<Vec<u8>, ErrorStack> {
|
||||
unsafe {
|
||||
let key_len = ffi::DH_size(self.as_ptr());
|
||||
let mut key = vec![0u8; key_len as usize];
|
||||
cvt(ffi::DH_compute_key(
|
||||
key.as_mut_ptr(),
|
||||
public_key.as_ptr(),
|
||||
self.as_ptr(),
|
||||
))?;
|
||||
Ok(key)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the private key from the DH instance.
|
||||
#[corresponds(DH_get0_key)]
|
||||
pub fn private_key(&self) -> &BigNumRef {
|
||||
let mut priv_key = ptr::null();
|
||||
unsafe {
|
||||
DH_get0_key(self.as_ptr(), ptr::null_mut(), &mut priv_key);
|
||||
BigNumRef::from_ptr(priv_key as *mut _)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl110, libressl270, boringssl))] {
|
||||
use ffi::{DH_set0_pqg, DH_get0_pqg, DH_get0_key, DH_set0_key};
|
||||
} else {
|
||||
#[allow(bad_style)]
|
||||
unsafe fn DH_set0_pqg(
|
||||
dh: *mut ffi::DH,
|
||||
p: *mut ffi::BIGNUM,
|
||||
q: *mut ffi::BIGNUM,
|
||||
g: *mut ffi::BIGNUM,
|
||||
) -> ::libc::c_int {
|
||||
(*dh).p = p;
|
||||
(*dh).q = q;
|
||||
(*dh).g = g;
|
||||
1
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn DH_get0_pqg(
|
||||
dh: *mut ffi::DH,
|
||||
p: *mut *const ffi::BIGNUM,
|
||||
q: *mut *const ffi::BIGNUM,
|
||||
g: *mut *const ffi::BIGNUM,
|
||||
) {
|
||||
if !p.is_null() {
|
||||
*p = (*dh).p;
|
||||
}
|
||||
if !q.is_null() {
|
||||
*q = (*dh).q;
|
||||
}
|
||||
if !g.is_null() {
|
||||
*g = (*dh).g;
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn DH_set0_key(
|
||||
dh: *mut ffi::DH,
|
||||
pub_key: *mut ffi::BIGNUM,
|
||||
priv_key: *mut ffi::BIGNUM,
|
||||
) -> ::libc::c_int {
|
||||
(*dh).pub_key = pub_key;
|
||||
(*dh).priv_key = priv_key;
|
||||
1
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn DH_get0_key(
|
||||
dh: *mut ffi::DH,
|
||||
pub_key: *mut *const ffi::BIGNUM,
|
||||
priv_key: *mut *const ffi::BIGNUM,
|
||||
) {
|
||||
if !pub_key.is_null() {
|
||||
*pub_key = (*dh).pub_key;
|
||||
}
|
||||
if !priv_key.is_null() {
|
||||
*priv_key = (*dh).priv_key;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::bn::BigNum;
|
||||
use crate::dh::Dh;
|
||||
#[cfg(all(not(boringssl), ossl110))]
|
||||
use crate::pkey::PKey;
|
||||
use crate::ssl::{SslContext, SslMethod};
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl102)]
|
||||
fn test_dh_rfc5114() {
|
||||
let mut ctx = SslContext::builder(SslMethod::tls()).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_params() {
|
||||
let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
|
||||
let prime_p = BigNum::from_hex_str(
|
||||
"87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F25D2CEED4435E3B00E00DF8F1D61957D4FAF7DF\
|
||||
4561B2AA3016C3D91134096FAA3BF4296D830E9A7C209E0C6497517ABD5A8A9D306BCF67ED91F9E6725B47\
|
||||
58C022E0B1EF4275BF7B6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF12307F5C4FDB70C581B23F76B6\
|
||||
3ACAE1CAA6B7902D52526735488A0EF13C6D9A51BFA4AB3AD8347796524D8EF6A167B5A41825D967E144E5\
|
||||
140564251CCACB83E6B486F6B3CA3F7971506026C0B857F689962856DED4010ABD0BE621C3A3960A54E710\
|
||||
C375F26375D7014103A4B54330C198AF126116D2276E11715F693877FAD7EF09CADB094AE91E1A1597",
|
||||
).unwrap();
|
||||
let prime_q = BigNum::from_hex_str(
|
||||
"3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF205407F4793A1A0BA12510DBC15077BE463FFF4FED\
|
||||
4AAC0BB555BE3A6C1B0C6B47B1BC3773BF7E8C6F62901228F8C28CBB18A55AE31341000A650196F931C77A\
|
||||
57F2DDF463E5E9EC144B777DE62AAAB8A8628AC376D282D6ED3864E67982428EBC831D14348F6F2F9193B5\
|
||||
045AF2767164E1DFC967C1FB3F2E55A4BD1BFFE83B9C80D052B985D182EA0ADB2A3B7313D3FE14C8484B1E\
|
||||
052588B9B7D2BBD2DF016199ECD06E1557CD0915B3353BBB64E0EC377FD028370DF92B52C7891428CDC67E\
|
||||
B6184B523D1DB246C32F63078490F00EF8D647D148D47954515E2327CFEF98C582664B4C0F6CC41659",
|
||||
).unwrap();
|
||||
let generator = BigNum::from_hex_str(
|
||||
"8CF83642A709A097B447997640129DA299B1A47D1EB3750BA308B0FE64F5FBD3",
|
||||
)
|
||||
.unwrap();
|
||||
let dh = Dh::from_params(
|
||||
prime_p.to_owned().unwrap(),
|
||||
generator.to_owned().unwrap(),
|
||||
prime_q.to_owned().unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
ctx.set_tmp_dh(&dh).unwrap();
|
||||
|
||||
assert_eq!(dh.prime_p(), &prime_p);
|
||||
assert_eq!(dh.prime_q().unwrap(), &prime_q);
|
||||
assert_eq!(dh.generator(), &generator);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(not(boringssl), ossl110))]
|
||||
fn test_from_dhx_serializes_q() {
|
||||
let p = BigNum::from_hex_str("00ad107e1e9123a9d0d660faa79559c51fa20d64e5683b9fd1b54b1597b61d0a75e6fa141df95a56dbaf9a3c407ba1df15eb3d688a309c180e1de6b85a1274a0a66d3f8152ad6ac2129037c9edefda4df8d91e8fef55b7394b7ad5b7d0b6c12207c9f98d11ed34dbf6c6ba0b2c8bbc27be6a00e0a0b9c49708b3bf8a317091883681286130bc8985db1602e714415d9330278273c7de31efdc7310f7121fd5a07415987d9adc0a486dcdf93acc44328387315d75e198c641a480cd86a1b9e587e8be60e69cc928b2b9c52172e413042e9b23f10b0e16e79763c9b53dcf4ba80a29e3fb73c16b8e75b97ef363e2ffa31f71cf9de5384e71b81c0ac4dffe0c10e64f").unwrap();
|
||||
let g = BigNum::from_hex_str("00ac4032ef4f2d9ae39df30b5c8ffdac506cdebe7b89998caf74866a08cfe4ffe3a6824a4e10b9a6f0dd921f01a70c4afaab739d7700c29f52c57db17c620a8652be5e9001a8d66ad7c17669101999024af4d027275ac1348bb8a762d0521bc98ae247150422ea1ed409939d54da7460cdb5f6c6b250717cbef180eb34118e98d119529a45d6f834566e3025e316a330efbb77a86f0c1ab15b051ae3d428c8f8acb70a8137150b8eeb10e183edd19963ddd9e263e4770589ef6aa21e7f5f2ff381b539cce3409d13cd566afbb48d6c019181e1bcfe94b30269edfe72fe9b6aa4bd7b5a0f1c71cfff4c19c418e1f6ec017981bc087f2a7065b384b890d3191f2bfa").unwrap();
|
||||
let q = BigNum::from_hex_str("00801c0d34c58d93fe997177101f80535a4738cebcbf389a99b36371eb")
|
||||
.unwrap();
|
||||
let y = BigNum::from_hex_str("0082c165bb576243ecf46d58c3d1501616955fca0320fa95ea11d2e6c1b9cf217676720dc1c08c85bf20c4d232b60a29a1e51c7b773bc645014587c525c86151b30d75486ec7b6c98efb5f74955b83116d01d0af1232af89213c2de574369d701aba9357300b920d3d8b98252d46c46952c16a5f33554b38317809c7b9add4701f5c158c1b7035e9fe39366ececb90d2896b78c523c4a577287ef5ba7a2663ed58aa20b5ec66e30f316610dfaa38583e495ab6af771c284387e660edbef4edb872e2e80e1d244ee95622e76d028e61c1e887c2aa792717362139f4dd26eafd49b2366eeb2350b01fe1b56022a2809e379559c37b375ba01c4eaacc14fd1b247837").unwrap();
|
||||
|
||||
let dh = Dh::from_params(p, g, q).unwrap();
|
||||
let dh = dh.set_public_key(y).unwrap();
|
||||
|
||||
// Verify that 'q' is serialized in the public key.
|
||||
let pkey = PKey::from_dhx(dh).unwrap();
|
||||
assert_eq!(pkey.public_key_to_der().unwrap(), b"\x30\x82\x03\x44\x30\x82\x02\x36\x06\x07\x2a\x86\x48\xce\x3e\x02\x01\x30\x82\x02\x29\x02\x82\x01\x01\x00\xad\x10\x7e\x1e\x91\x23\xa9\xd0\xd6\x60\xfa\xa7\x95\x59\xc5\x1f\xa2\x0d\x64\xe5\x68\x3b\x9f\xd1\xb5\x4b\x15\x97\xb6\x1d\x0a\x75\xe6\xfa\x14\x1d\xf9\x5a\x56\xdb\xaf\x9a\x3c\x40\x7b\xa1\xdf\x15\xeb\x3d\x68\x8a\x30\x9c\x18\x0e\x1d\xe6\xb8\x5a\x12\x74\xa0\xa6\x6d\x3f\x81\x52\xad\x6a\xc2\x12\x90\x37\xc9\xed\xef\xda\x4d\xf8\xd9\x1e\x8f\xef\x55\xb7\x39\x4b\x7a\xd5\xb7\xd0\xb6\xc1\x22\x07\xc9\xf9\x8d\x11\xed\x34\xdb\xf6\xc6\xba\x0b\x2c\x8b\xbc\x27\xbe\x6a\x00\xe0\xa0\xb9\xc4\x97\x08\xb3\xbf\x8a\x31\x70\x91\x88\x36\x81\x28\x61\x30\xbc\x89\x85\xdb\x16\x02\xe7\x14\x41\x5d\x93\x30\x27\x82\x73\xc7\xde\x31\xef\xdc\x73\x10\xf7\x12\x1f\xd5\xa0\x74\x15\x98\x7d\x9a\xdc\x0a\x48\x6d\xcd\xf9\x3a\xcc\x44\x32\x83\x87\x31\x5d\x75\xe1\x98\xc6\x41\xa4\x80\xcd\x86\xa1\xb9\xe5\x87\xe8\xbe\x60\xe6\x9c\xc9\x28\xb2\xb9\xc5\x21\x72\xe4\x13\x04\x2e\x9b\x23\xf1\x0b\x0e\x16\xe7\x97\x63\xc9\xb5\x3d\xcf\x4b\xa8\x0a\x29\xe3\xfb\x73\xc1\x6b\x8e\x75\xb9\x7e\xf3\x63\xe2\xff\xa3\x1f\x71\xcf\x9d\xe5\x38\x4e\x71\xb8\x1c\x0a\xc4\xdf\xfe\x0c\x10\xe6\x4f\x02\x82\x01\x01\x00\xac\x40\x32\xef\x4f\x2d\x9a\xe3\x9d\xf3\x0b\x5c\x8f\xfd\xac\x50\x6c\xde\xbe\x7b\x89\x99\x8c\xaf\x74\x86\x6a\x08\xcf\xe4\xff\xe3\xa6\x82\x4a\x4e\x10\xb9\xa6\xf0\xdd\x92\x1f\x01\xa7\x0c\x4a\xfa\xab\x73\x9d\x77\x00\xc2\x9f\x52\xc5\x7d\xb1\x7c\x62\x0a\x86\x52\xbe\x5e\x90\x01\xa8\xd6\x6a\xd7\xc1\x76\x69\x10\x19\x99\x02\x4a\xf4\xd0\x27\x27\x5a\xc1\x34\x8b\xb8\xa7\x62\xd0\x52\x1b\xc9\x8a\xe2\x47\x15\x04\x22\xea\x1e\xd4\x09\x93\x9d\x54\xda\x74\x60\xcd\xb5\xf6\xc6\xb2\x50\x71\x7c\xbe\xf1\x80\xeb\x34\x11\x8e\x98\xd1\x19\x52\x9a\x45\xd6\xf8\x34\x56\x6e\x30\x25\xe3\x16\xa3\x30\xef\xbb\x77\xa8\x6f\x0c\x1a\xb1\x5b\x05\x1a\xe3\xd4\x28\xc8\xf8\xac\xb7\x0a\x81\x37\x15\x0b\x8e\xeb\x10\xe1\x83\xed\xd1\x99\x63\xdd\xd9\xe2\x63\xe4\x77\x05\x89\xef\x6a\xa2\x1e\x7f\x5f\x2f\xf3\x81\xb5\x39\xcc\xe3\x40\x9d\x13\xcd\x56\x6a\xfb\xb4\x8d\x6c\x01\x91\x81\xe1\xbc\xfe\x94\xb3\x02\x69\xed\xfe\x72\xfe\x9b\x6a\xa4\xbd\x7b\x5a\x0f\x1c\x71\xcf\xff\x4c\x19\xc4\x18\xe1\xf6\xec\x01\x79\x81\xbc\x08\x7f\x2a\x70\x65\xb3\x84\xb8\x90\xd3\x19\x1f\x2b\xfa\x02\x1d\x00\x80\x1c\x0d\x34\xc5\x8d\x93\xfe\x99\x71\x77\x10\x1f\x80\x53\x5a\x47\x38\xce\xbc\xbf\x38\x9a\x99\xb3\x63\x71\xeb\x03\x82\x01\x06\x00\x02\x82\x01\x01\x00\x82\xc1\x65\xbb\x57\x62\x43\xec\xf4\x6d\x58\xc3\xd1\x50\x16\x16\x95\x5f\xca\x03\x20\xfa\x95\xea\x11\xd2\xe6\xc1\xb9\xcf\x21\x76\x76\x72\x0d\xc1\xc0\x8c\x85\xbf\x20\xc4\xd2\x32\xb6\x0a\x29\xa1\xe5\x1c\x7b\x77\x3b\xc6\x45\x01\x45\x87\xc5\x25\xc8\x61\x51\xb3\x0d\x75\x48\x6e\xc7\xb6\xc9\x8e\xfb\x5f\x74\x95\x5b\x83\x11\x6d\x01\xd0\xaf\x12\x32\xaf\x89\x21\x3c\x2d\xe5\x74\x36\x9d\x70\x1a\xba\x93\x57\x30\x0b\x92\x0d\x3d\x8b\x98\x25\x2d\x46\xc4\x69\x52\xc1\x6a\x5f\x33\x55\x4b\x38\x31\x78\x09\xc7\xb9\xad\xd4\x70\x1f\x5c\x15\x8c\x1b\x70\x35\xe9\xfe\x39\x36\x6e\xce\xcb\x90\xd2\x89\x6b\x78\xc5\x23\xc4\xa5\x77\x28\x7e\xf5\xba\x7a\x26\x63\xed\x58\xaa\x20\xb5\xec\x66\xe3\x0f\x31\x66\x10\xdf\xaa\x38\x58\x3e\x49\x5a\xb6\xaf\x77\x1c\x28\x43\x87\xe6\x60\xed\xbe\xf4\xed\xb8\x72\xe2\xe8\x0e\x1d\x24\x4e\xe9\x56\x22\xe7\x6d\x02\x8e\x61\xc1\xe8\x87\xc2\xaa\x79\x27\x17\x36\x21\x39\xf4\xdd\x26\xea\xfd\x49\xb2\x36\x6e\xeb\x23\x50\xb0\x1f\xe1\xb5\x60\x22\xa2\x80\x9e\x37\x95\x59\xc3\x7b\x37\x5b\xa0\x1c\x4e\xaa\xcc\x14\xfd\x1b\x24\x78\x37");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl102)]
|
||||
fn test_dh_stored_restored() {
|
||||
let dh1 = Dh::get_2048_256().unwrap();
|
||||
let key1 = dh1.generate_key().unwrap();
|
||||
|
||||
let dh2 = Dh::get_2048_256().unwrap();
|
||||
let key2 = dh2
|
||||
.set_private_key(key1.private_key().to_owned().unwrap())
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(key1.public_key(), key2.public_key());
|
||||
assert_eq!(key1.private_key(), key2.private_key());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl102)]
|
||||
fn test_set_keys() {
|
||||
let dh1 = Dh::get_2048_256().unwrap();
|
||||
let key1 = dh1.generate_key().unwrap();
|
||||
|
||||
let dh2 = Dh::get_2048_256().unwrap();
|
||||
let key2 = dh2
|
||||
.set_public_key(key1.public_key().to_owned().unwrap())
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(key1.public_key(), key2.public_key());
|
||||
|
||||
let dh3 = Dh::get_2048_256().unwrap();
|
||||
let key3 = dh3
|
||||
.set_key(
|
||||
key1.public_key().to_owned().unwrap(),
|
||||
key1.private_key().to_owned().unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(key1.public_key(), key3.public_key());
|
||||
assert_eq!(key1.private_key(), key3.private_key());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dh_from_pem() {
|
||||
let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
|
||||
let params = include_bytes!("../test/dhparams.pem");
|
||||
let dh = Dh::params_from_pem(params).unwrap();
|
||||
ctx.set_tmp_dh(&dh).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dh_from_der() {
|
||||
let params = include_bytes!("../test/dhparams.pem");
|
||||
let dh = Dh::params_from_pem(params).unwrap();
|
||||
let der = dh.params_to_der().unwrap();
|
||||
Dh::params_from_der(&der).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl102)]
|
||||
fn test_dh_generate_key_compute_key() {
|
||||
let dh1 = Dh::get_2048_224().unwrap().generate_key().unwrap();
|
||||
let dh2 = Dh::get_2048_224().unwrap().generate_key().unwrap();
|
||||
|
||||
let shared_a = dh1.compute_key(dh2.public_key()).unwrap();
|
||||
let shared_b = dh2.compute_key(dh1.public_key()).unwrap();
|
||||
|
||||
assert_eq!(shared_a, shared_b);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dh_generate_params_generate_key_compute_key() {
|
||||
let dh_params1 = Dh::generate_params(512, 2).unwrap();
|
||||
let dh_params2 = Dh::from_pqg(
|
||||
dh_params1.prime_p().to_owned().unwrap(),
|
||||
None,
|
||||
dh_params1.generator().to_owned().unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let dh1 = dh_params1.generate_key().unwrap();
|
||||
let dh2 = dh_params2.generate_key().unwrap();
|
||||
|
||||
let shared_a = dh1.compute_key(dh2.public_key()).unwrap();
|
||||
let shared_b = dh2.compute_key(dh1.public_key()).unwrap();
|
||||
|
||||
assert_eq!(shared_a, shared_b);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dh_check_key() {
|
||||
let dh1 = Dh::generate_params(512, 2).unwrap();
|
||||
let p = BigNum::from_hex_str("04").unwrap();
|
||||
let g = BigNum::from_hex_str("02").unwrap();
|
||||
let dh2 = Dh::from_pqg(p, None, g).unwrap();
|
||||
assert!(dh1.check_key().unwrap());
|
||||
assert!(matches!(dh2.check_key(), Ok(false) | Err(_)));
|
||||
}
|
||||
}
|
||||
697
vendor/openssl/src/dsa.rs
vendored
Normal file
697
vendor/openssl/src/dsa.rs
vendored
Normal file
|
|
@ -0,0 +1,697 @@
|
|||
//! Digital Signatures
|
||||
//!
|
||||
//! DSA ensures a message originated from a known sender, and was not modified.
|
||||
//! DSA uses asymmetrical keys and an algorithm to output a signature of the message
|
||||
//! using the private key that can be validated with the public key but not be generated
|
||||
//! without the private key.
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
#[cfg(not(boringssl))]
|
||||
use libc::c_int;
|
||||
use std::fmt;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
|
||||
use crate::bn::{BigNum, BigNumRef};
|
||||
use crate::error::ErrorStack;
|
||||
use crate::pkey::{HasParams, HasPrivate, HasPublic, Params, Private, Public};
|
||||
use crate::util::ForeignTypeRefExt;
|
||||
use crate::{cvt, cvt_p};
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
generic_foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::DSA;
|
||||
fn drop = ffi::DSA_free;
|
||||
|
||||
/// Object representing DSA keys.
|
||||
///
|
||||
/// A DSA object contains the parameters p, q, and g. There is a private
|
||||
/// and public key. The values p, g, and q are:
|
||||
///
|
||||
/// * `p`: DSA prime parameter
|
||||
/// * `q`: DSA sub-prime parameter
|
||||
/// * `g`: DSA base parameter
|
||||
///
|
||||
/// These values are used to calculate a pair of asymmetrical keys used for
|
||||
/// signing.
|
||||
///
|
||||
/// OpenSSL documentation at [`DSA_new`]
|
||||
///
|
||||
/// [`DSA_new`]: https://www.openssl.org/docs/manmaster/crypto/DSA_new.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use openssl::dsa::Dsa;
|
||||
/// use openssl::error::ErrorStack;
|
||||
/// use openssl::pkey::Private;
|
||||
///
|
||||
/// fn create_dsa() -> Result<Dsa<Private>, ErrorStack> {
|
||||
/// let sign = Dsa::generate(2048)?;
|
||||
/// Ok(sign)
|
||||
/// }
|
||||
/// # fn main() {
|
||||
/// # create_dsa();
|
||||
/// # }
|
||||
/// ```
|
||||
pub struct Dsa<T>;
|
||||
/// Reference to [`Dsa`].
|
||||
///
|
||||
/// [`Dsa`]: struct.Dsa.html
|
||||
pub struct DsaRef<T>;
|
||||
}
|
||||
|
||||
impl<T> Clone for Dsa<T> {
|
||||
fn clone(&self) -> Dsa<T> {
|
||||
(**self).to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ToOwned for DsaRef<T> {
|
||||
type Owned = Dsa<T>;
|
||||
|
||||
fn to_owned(&self) -> Dsa<T> {
|
||||
unsafe {
|
||||
ffi::DSA_up_ref(self.as_ptr());
|
||||
Dsa::from_ptr(self.as_ptr())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DsaRef<T>
|
||||
where
|
||||
T: HasPublic,
|
||||
{
|
||||
to_pem! {
|
||||
/// Serializes the public key into a PEM-encoded SubjectPublicKeyInfo structure.
|
||||
///
|
||||
/// The output will have a header of `-----BEGIN PUBLIC KEY-----`.
|
||||
#[corresponds(PEM_write_bio_DSA_PUBKEY)]
|
||||
public_key_to_pem,
|
||||
ffi::PEM_write_bio_DSA_PUBKEY
|
||||
}
|
||||
|
||||
to_der! {
|
||||
/// Serializes the public key into a DER-encoded SubjectPublicKeyInfo structure.
|
||||
#[corresponds(i2d_DSA_PUBKEY)]
|
||||
public_key_to_der,
|
||||
ffi::i2d_DSA_PUBKEY
|
||||
}
|
||||
|
||||
/// Returns a reference to the public key component of `self`.
|
||||
#[corresponds(DSA_get0_key)]
|
||||
pub fn pub_key(&self) -> &BigNumRef {
|
||||
unsafe {
|
||||
let mut pub_key = ptr::null();
|
||||
DSA_get0_key(self.as_ptr(), &mut pub_key, ptr::null_mut());
|
||||
BigNumRef::from_const_ptr(pub_key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DsaRef<T>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
private_key_to_pem! {
|
||||
/// Serializes the private key to a PEM-encoded DSAPrivateKey structure.
|
||||
///
|
||||
/// The output will have a header of `-----BEGIN DSA PRIVATE KEY-----`.
|
||||
#[corresponds(PEM_write_bio_DSAPrivateKey)]
|
||||
private_key_to_pem,
|
||||
/// Serializes the private key to a PEM-encoded encrypted DSAPrivateKey structure.
|
||||
///
|
||||
/// The output will have a header of `-----BEGIN DSA PRIVATE KEY-----`.
|
||||
#[corresponds(PEM_write_bio_DSAPrivateKey)]
|
||||
private_key_to_pem_passphrase,
|
||||
ffi::PEM_write_bio_DSAPrivateKey
|
||||
}
|
||||
|
||||
to_der! {
|
||||
/// Serializes the private_key to a DER-encoded `DSAPrivateKey` structure.
|
||||
#[corresponds(i2d_DSAPrivateKey)]
|
||||
private_key_to_der,
|
||||
ffi::i2d_DSAPrivateKey
|
||||
}
|
||||
|
||||
/// Returns a reference to the private key component of `self`.
|
||||
#[corresponds(DSA_get0_key)]
|
||||
pub fn priv_key(&self) -> &BigNumRef {
|
||||
unsafe {
|
||||
let mut priv_key = ptr::null();
|
||||
DSA_get0_key(self.as_ptr(), ptr::null_mut(), &mut priv_key);
|
||||
BigNumRef::from_const_ptr(priv_key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> DsaRef<T>
|
||||
where
|
||||
T: HasParams,
|
||||
{
|
||||
/// Returns the maximum size of the signature output by `self` in bytes.
|
||||
#[corresponds(DSA_size)]
|
||||
pub fn size(&self) -> u32 {
|
||||
unsafe { ffi::DSA_size(self.as_ptr()) as u32 }
|
||||
}
|
||||
|
||||
/// Returns the DSA prime parameter of `self`.
|
||||
#[corresponds(DSA_get0_pqg)]
|
||||
pub fn p(&self) -> &BigNumRef {
|
||||
unsafe {
|
||||
let mut p = ptr::null();
|
||||
DSA_get0_pqg(self.as_ptr(), &mut p, ptr::null_mut(), ptr::null_mut());
|
||||
BigNumRef::from_const_ptr(p)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the DSA sub-prime parameter of `self`.
|
||||
#[corresponds(DSA_get0_pqg)]
|
||||
pub fn q(&self) -> &BigNumRef {
|
||||
unsafe {
|
||||
let mut q = ptr::null();
|
||||
DSA_get0_pqg(self.as_ptr(), ptr::null_mut(), &mut q, ptr::null_mut());
|
||||
BigNumRef::from_const_ptr(q)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the DSA base parameter of `self`.
|
||||
#[corresponds(DSA_get0_pqg)]
|
||||
pub fn g(&self) -> &BigNumRef {
|
||||
unsafe {
|
||||
let mut g = ptr::null();
|
||||
DSA_get0_pqg(self.as_ptr(), ptr::null_mut(), ptr::null_mut(), &mut g);
|
||||
BigNumRef::from_const_ptr(g)
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(boringssl)]
|
||||
type BitType = libc::c_uint;
|
||||
#[cfg(not(boringssl))]
|
||||
type BitType = c_int;
|
||||
|
||||
impl Dsa<Params> {
|
||||
/// Creates a DSA params based upon the given parameters.
|
||||
#[corresponds(DSA_set0_pqg)]
|
||||
pub fn from_pqg(p: BigNum, q: BigNum, g: BigNum) -> Result<Dsa<Params>, ErrorStack> {
|
||||
unsafe {
|
||||
let dsa = Dsa::from_ptr(cvt_p(ffi::DSA_new())?);
|
||||
cvt(DSA_set0_pqg(dsa.0, p.as_ptr(), q.as_ptr(), g.as_ptr()))?;
|
||||
mem::forget((p, q, g));
|
||||
Ok(dsa)
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates DSA params based on the given number of bits.
|
||||
#[corresponds(DSA_generate_parameters_ex)]
|
||||
pub fn generate_params(bits: u32) -> Result<Dsa<Params>, ErrorStack> {
|
||||
ffi::init();
|
||||
unsafe {
|
||||
let dsa = Dsa::from_ptr(cvt_p(ffi::DSA_new())?);
|
||||
cvt(ffi::DSA_generate_parameters_ex(
|
||||
dsa.0,
|
||||
bits as BitType,
|
||||
ptr::null(),
|
||||
0,
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
ptr::null_mut(),
|
||||
))?;
|
||||
Ok(dsa)
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates a private key based on the DSA params.
|
||||
#[corresponds(DSA_generate_key)]
|
||||
pub fn generate_key(self) -> Result<Dsa<Private>, ErrorStack> {
|
||||
unsafe {
|
||||
let dsa_ptr = self.0;
|
||||
cvt(ffi::DSA_generate_key(dsa_ptr))?;
|
||||
mem::forget(self);
|
||||
Ok(Dsa::from_ptr(dsa_ptr))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Dsa<Private> {
|
||||
/// Generate a DSA key pair.
|
||||
///
|
||||
/// The `bits` parameter corresponds to the length of the prime `p`.
|
||||
pub fn generate(bits: u32) -> Result<Dsa<Private>, ErrorStack> {
|
||||
let params = Dsa::generate_params(bits)?;
|
||||
params.generate_key()
|
||||
}
|
||||
|
||||
/// Create a DSA key pair with the given parameters
|
||||
///
|
||||
/// `p`, `q` and `g` are the common parameters.
|
||||
/// `priv_key` is the private component of the key pair.
|
||||
/// `pub_key` is the public component of the key. Can be computed via `g^(priv_key) mod p`
|
||||
pub fn from_private_components(
|
||||
p: BigNum,
|
||||
q: BigNum,
|
||||
g: BigNum,
|
||||
priv_key: BigNum,
|
||||
pub_key: BigNum,
|
||||
) -> Result<Dsa<Private>, ErrorStack> {
|
||||
ffi::init();
|
||||
unsafe {
|
||||
let dsa = Dsa::from_ptr(cvt_p(ffi::DSA_new())?);
|
||||
cvt(DSA_set0_pqg(dsa.0, p.as_ptr(), q.as_ptr(), g.as_ptr()))?;
|
||||
mem::forget((p, q, g));
|
||||
cvt(DSA_set0_key(dsa.0, pub_key.as_ptr(), priv_key.as_ptr()))?;
|
||||
mem::forget((pub_key, priv_key));
|
||||
Ok(dsa)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Dsa<Public> {
|
||||
from_pem! {
|
||||
/// Decodes a PEM-encoded SubjectPublicKeyInfo structure containing a DSA key.
|
||||
///
|
||||
/// The input should have a header of `-----BEGIN PUBLIC KEY-----`.
|
||||
#[corresponds(PEM_read_bio_DSA_PUBKEY)]
|
||||
public_key_from_pem,
|
||||
Dsa<Public>,
|
||||
ffi::PEM_read_bio_DSA_PUBKEY
|
||||
}
|
||||
|
||||
from_der! {
|
||||
/// Decodes a DER-encoded SubjectPublicKeyInfo structure containing a DSA key.
|
||||
#[corresponds(d2i_DSA_PUBKEY)]
|
||||
public_key_from_der,
|
||||
Dsa<Public>,
|
||||
ffi::d2i_DSA_PUBKEY
|
||||
}
|
||||
|
||||
/// Create a new DSA key with only public components.
|
||||
///
|
||||
/// `p`, `q` and `g` are the common parameters.
|
||||
/// `pub_key` is the public component of the key.
|
||||
pub fn from_public_components(
|
||||
p: BigNum,
|
||||
q: BigNum,
|
||||
g: BigNum,
|
||||
pub_key: BigNum,
|
||||
) -> Result<Dsa<Public>, ErrorStack> {
|
||||
ffi::init();
|
||||
unsafe {
|
||||
let dsa = Dsa::from_ptr(cvt_p(ffi::DSA_new())?);
|
||||
cvt(DSA_set0_pqg(dsa.0, p.as_ptr(), q.as_ptr(), g.as_ptr()))?;
|
||||
mem::forget((p, q, g));
|
||||
cvt(DSA_set0_key(dsa.0, pub_key.as_ptr(), ptr::null_mut()))?;
|
||||
mem::forget(pub_key);
|
||||
Ok(dsa)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> fmt::Debug for Dsa<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "DSA")
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl110, libressl273, boringssl))] {
|
||||
use ffi::{DSA_get0_key, DSA_get0_pqg, DSA_set0_key, DSA_set0_pqg};
|
||||
} else {
|
||||
#[allow(bad_style)]
|
||||
unsafe fn DSA_get0_pqg(
|
||||
d: *mut ffi::DSA,
|
||||
p: *mut *const ffi::BIGNUM,
|
||||
q: *mut *const ffi::BIGNUM,
|
||||
g: *mut *const ffi::BIGNUM)
|
||||
{
|
||||
if !p.is_null() {
|
||||
*p = (*d).p;
|
||||
}
|
||||
if !q.is_null() {
|
||||
*q = (*d).q;
|
||||
}
|
||||
if !g.is_null() {
|
||||
*g = (*d).g;
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn DSA_get0_key(
|
||||
d: *mut ffi::DSA,
|
||||
pub_key: *mut *const ffi::BIGNUM,
|
||||
priv_key: *mut *const ffi::BIGNUM)
|
||||
{
|
||||
if !pub_key.is_null() {
|
||||
*pub_key = (*d).pub_key;
|
||||
}
|
||||
if !priv_key.is_null() {
|
||||
*priv_key = (*d).priv_key;
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn DSA_set0_key(
|
||||
d: *mut ffi::DSA,
|
||||
pub_key: *mut ffi::BIGNUM,
|
||||
priv_key: *mut ffi::BIGNUM) -> c_int
|
||||
{
|
||||
(*d).pub_key = pub_key;
|
||||
(*d).priv_key = priv_key;
|
||||
1
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn DSA_set0_pqg(
|
||||
d: *mut ffi::DSA,
|
||||
p: *mut ffi::BIGNUM,
|
||||
q: *mut ffi::BIGNUM,
|
||||
g: *mut ffi::BIGNUM) -> c_int
|
||||
{
|
||||
(*d).p = p;
|
||||
(*d).q = q;
|
||||
(*d).g = g;
|
||||
1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::DSA_SIG;
|
||||
fn drop = ffi::DSA_SIG_free;
|
||||
|
||||
/// Object representing DSA signature.
|
||||
///
|
||||
/// DSA signatures consist of two components: `r` and `s`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::convert::TryInto;
|
||||
///
|
||||
/// use openssl::bn::BigNum;
|
||||
/// use openssl::dsa::{Dsa, DsaSig};
|
||||
/// use openssl::hash::MessageDigest;
|
||||
/// use openssl::pkey::PKey;
|
||||
/// use openssl::sign::{Signer, Verifier};
|
||||
///
|
||||
/// const TEST_DATA: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
/// let dsa_ref = Dsa::generate(1024).unwrap();
|
||||
///
|
||||
/// let pub_key: PKey<_> = dsa_ref.clone().try_into().unwrap();
|
||||
/// let priv_key: PKey<_> = dsa_ref.try_into().unwrap();
|
||||
///
|
||||
/// let mut signer = if let Ok(signer) = Signer::new(MessageDigest::sha256(), &priv_key) {
|
||||
/// signer
|
||||
/// } else {
|
||||
/// // DSA signing is not supported (eg. BoringSSL)
|
||||
/// return;
|
||||
/// };
|
||||
///
|
||||
/// signer.update(TEST_DATA).unwrap();
|
||||
///
|
||||
/// let signature = signer.sign_to_vec().unwrap();
|
||||
/// // Parse DER-encoded DSA signature
|
||||
/// let signature = DsaSig::from_der(&signature).unwrap();
|
||||
///
|
||||
/// // Extract components `r` and `s`
|
||||
/// let r = BigNum::from_slice(&signature.r().to_vec()).unwrap();
|
||||
/// let s = BigNum::from_slice(&signature.s().to_vec()).unwrap();
|
||||
///
|
||||
/// // Construct new DSA signature from components
|
||||
/// let signature = DsaSig::from_private_components(r, s).unwrap();
|
||||
///
|
||||
/// // Serialize DSA signature to DER
|
||||
/// let signature = signature.to_der().unwrap();
|
||||
///
|
||||
/// let mut verifier = Verifier::new(MessageDigest::sha256(), &pub_key).unwrap();
|
||||
/// verifier.update(TEST_DATA).unwrap();
|
||||
/// assert!(verifier.verify(&signature[..]).unwrap());
|
||||
/// ```
|
||||
pub struct DsaSig;
|
||||
|
||||
/// Reference to a [`DsaSig`].
|
||||
pub struct DsaSigRef;
|
||||
}
|
||||
|
||||
impl DsaSig {
|
||||
/// Returns a new `DsaSig` by setting the `r` and `s` values associated with an DSA signature.
|
||||
#[corresponds(DSA_SIG_set0)]
|
||||
pub fn from_private_components(r: BigNum, s: BigNum) -> Result<Self, ErrorStack> {
|
||||
unsafe {
|
||||
let sig = cvt_p(ffi::DSA_SIG_new())?;
|
||||
DSA_SIG_set0(sig, r.as_ptr(), s.as_ptr());
|
||||
mem::forget((r, s));
|
||||
Ok(DsaSig::from_ptr(sig))
|
||||
}
|
||||
}
|
||||
|
||||
from_der! {
|
||||
/// Decodes a DER-encoded DSA signature.
|
||||
#[corresponds(d2i_DSA_SIG)]
|
||||
from_der,
|
||||
DsaSig,
|
||||
ffi::d2i_DSA_SIG
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for DsaSig {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("DsaSig")
|
||||
.field("r", self.r())
|
||||
.field("s", self.s())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl DsaSigRef {
|
||||
to_der! {
|
||||
/// Serializes the DSA signature into a DER-encoded `DSASignature` structure.
|
||||
#[corresponds(i2d_DSA_SIG)]
|
||||
to_der,
|
||||
ffi::i2d_DSA_SIG
|
||||
}
|
||||
|
||||
/// Returns internal component `r` of an `DsaSig`.
|
||||
#[corresponds(DSA_SIG_get0)]
|
||||
pub fn r(&self) -> &BigNumRef {
|
||||
unsafe {
|
||||
let mut r = ptr::null();
|
||||
DSA_SIG_get0(self.as_ptr(), &mut r, ptr::null_mut());
|
||||
BigNumRef::from_const_ptr(r)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns internal component `s` of an `DsaSig`.
|
||||
#[corresponds(DSA_SIG_get0)]
|
||||
pub fn s(&self) -> &BigNumRef {
|
||||
unsafe {
|
||||
let mut s = ptr::null();
|
||||
DSA_SIG_get0(self.as_ptr(), ptr::null_mut(), &mut s);
|
||||
BigNumRef::from_const_ptr(s)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl110, libressl273, boringssl))] {
|
||||
use ffi::{DSA_SIG_set0, DSA_SIG_get0};
|
||||
} else {
|
||||
#[allow(bad_style)]
|
||||
unsafe fn DSA_SIG_set0(
|
||||
sig: *mut ffi::DSA_SIG,
|
||||
r: *mut ffi::BIGNUM,
|
||||
s: *mut ffi::BIGNUM,
|
||||
) -> c_int {
|
||||
if r.is_null() || s.is_null() {
|
||||
return 0;
|
||||
}
|
||||
ffi::BN_clear_free((*sig).r);
|
||||
ffi::BN_clear_free((*sig).s);
|
||||
(*sig).r = r;
|
||||
(*sig).s = s;
|
||||
1
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn DSA_SIG_get0(
|
||||
sig: *const ffi::DSA_SIG,
|
||||
pr: *mut *const ffi::BIGNUM,
|
||||
ps: *mut *const ffi::BIGNUM)
|
||||
{
|
||||
if !pr.is_null() {
|
||||
(*pr) = (*sig).r;
|
||||
}
|
||||
if !ps.is_null() {
|
||||
(*ps) = (*sig).s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::bn::BigNumContext;
|
||||
#[cfg(not(boringssl))]
|
||||
use crate::hash::MessageDigest;
|
||||
#[cfg(not(boringssl))]
|
||||
use crate::pkey::PKey;
|
||||
#[cfg(not(boringssl))]
|
||||
use crate::sign::{Signer, Verifier};
|
||||
|
||||
#[test]
|
||||
pub fn test_generate() {
|
||||
Dsa::generate(1024).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pubkey_generation() {
|
||||
let dsa = Dsa::generate(1024).unwrap();
|
||||
let p = dsa.p();
|
||||
let g = dsa.g();
|
||||
let priv_key = dsa.priv_key();
|
||||
let pub_key = dsa.pub_key();
|
||||
let mut ctx = BigNumContext::new().unwrap();
|
||||
let mut calc = BigNum::new().unwrap();
|
||||
calc.mod_exp(g, priv_key, p, &mut ctx).unwrap();
|
||||
assert_eq!(&calc, pub_key)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_priv_key_from_parts() {
|
||||
let p = BigNum::from_u32(283).unwrap();
|
||||
let q = BigNum::from_u32(47).unwrap();
|
||||
let g = BigNum::from_u32(60).unwrap();
|
||||
let priv_key = BigNum::from_u32(15).unwrap();
|
||||
let pub_key = BigNum::from_u32(207).unwrap();
|
||||
|
||||
let dsa = Dsa::from_private_components(p, q, g, priv_key, pub_key).unwrap();
|
||||
assert_eq!(dsa.pub_key(), &BigNum::from_u32(207).unwrap());
|
||||
assert_eq!(dsa.priv_key(), &BigNum::from_u32(15).unwrap());
|
||||
assert_eq!(dsa.p(), &BigNum::from_u32(283).unwrap());
|
||||
assert_eq!(dsa.q(), &BigNum::from_u32(47).unwrap());
|
||||
assert_eq!(dsa.g(), &BigNum::from_u32(60).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pub_key_from_parts() {
|
||||
let p = BigNum::from_u32(283).unwrap();
|
||||
let q = BigNum::from_u32(47).unwrap();
|
||||
let g = BigNum::from_u32(60).unwrap();
|
||||
let pub_key = BigNum::from_u32(207).unwrap();
|
||||
|
||||
let dsa = Dsa::from_public_components(p, q, g, pub_key).unwrap();
|
||||
assert_eq!(dsa.pub_key(), &BigNum::from_u32(207).unwrap());
|
||||
assert_eq!(dsa.p(), &BigNum::from_u32(283).unwrap());
|
||||
assert_eq!(dsa.q(), &BigNum::from_u32(47).unwrap());
|
||||
assert_eq!(dsa.g(), &BigNum::from_u32(60).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_params() {
|
||||
let params = Dsa::generate_params(1024).unwrap();
|
||||
let p = params.p().to_owned().unwrap();
|
||||
let q = params.q().to_owned().unwrap();
|
||||
let g = params.g().to_owned().unwrap();
|
||||
let key = params.generate_key().unwrap();
|
||||
let params2 = Dsa::from_pqg(
|
||||
key.p().to_owned().unwrap(),
|
||||
key.q().to_owned().unwrap(),
|
||||
key.g().to_owned().unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(p, *params2.p());
|
||||
assert_eq!(q, *params2.q());
|
||||
assert_eq!(g, *params2.g());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(boringssl))]
|
||||
fn test_signature() {
|
||||
const TEST_DATA: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
let dsa_ref = Dsa::generate(1024).unwrap();
|
||||
|
||||
let p = dsa_ref.p();
|
||||
let q = dsa_ref.q();
|
||||
let g = dsa_ref.g();
|
||||
|
||||
let pub_key = dsa_ref.pub_key();
|
||||
let priv_key = dsa_ref.priv_key();
|
||||
|
||||
let priv_key = Dsa::from_private_components(
|
||||
BigNumRef::to_owned(p).unwrap(),
|
||||
BigNumRef::to_owned(q).unwrap(),
|
||||
BigNumRef::to_owned(g).unwrap(),
|
||||
BigNumRef::to_owned(priv_key).unwrap(),
|
||||
BigNumRef::to_owned(pub_key).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
let priv_key = PKey::from_dsa(priv_key).unwrap();
|
||||
|
||||
let pub_key = Dsa::from_public_components(
|
||||
BigNumRef::to_owned(p).unwrap(),
|
||||
BigNumRef::to_owned(q).unwrap(),
|
||||
BigNumRef::to_owned(g).unwrap(),
|
||||
BigNumRef::to_owned(pub_key).unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
let pub_key = PKey::from_dsa(pub_key).unwrap();
|
||||
|
||||
let mut signer = Signer::new(MessageDigest::sha256(), &priv_key).unwrap();
|
||||
signer.update(TEST_DATA).unwrap();
|
||||
|
||||
let signature = signer.sign_to_vec().unwrap();
|
||||
let mut verifier = Verifier::new(MessageDigest::sha256(), &pub_key).unwrap();
|
||||
verifier.update(TEST_DATA).unwrap();
|
||||
assert!(verifier.verify(&signature[..]).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(boringssl))]
|
||||
fn test_signature_der() {
|
||||
use std::convert::TryInto;
|
||||
|
||||
const TEST_DATA: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
let dsa_ref = Dsa::generate(1024).unwrap();
|
||||
|
||||
let pub_key: PKey<_> = dsa_ref.clone().try_into().unwrap();
|
||||
let priv_key: PKey<_> = dsa_ref.try_into().unwrap();
|
||||
|
||||
let mut signer = Signer::new(MessageDigest::sha256(), &priv_key).unwrap();
|
||||
signer.update(TEST_DATA).unwrap();
|
||||
|
||||
let signature = signer.sign_to_vec().unwrap();
|
||||
eprintln!("{:?}", signature);
|
||||
let signature = DsaSig::from_der(&signature).unwrap();
|
||||
|
||||
let r = BigNum::from_slice(&signature.r().to_vec()).unwrap();
|
||||
let s = BigNum::from_slice(&signature.s().to_vec()).unwrap();
|
||||
|
||||
let signature = DsaSig::from_private_components(r, s).unwrap();
|
||||
let signature = signature.to_der().unwrap();
|
||||
|
||||
let mut verifier = Verifier::new(MessageDigest::sha256(), &pub_key).unwrap();
|
||||
verifier.update(TEST_DATA).unwrap();
|
||||
assert!(verifier.verify(&signature[..]).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::redundant_clone)]
|
||||
fn clone() {
|
||||
let key = Dsa::generate(2048).unwrap();
|
||||
drop(key.clone());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dsa_sig_debug() {
|
||||
let sig = DsaSig::from_der(&[
|
||||
48, 46, 2, 21, 0, 135, 169, 24, 58, 153, 37, 175, 248, 200, 45, 251, 112, 238, 238, 89,
|
||||
172, 177, 182, 166, 237, 2, 21, 0, 159, 146, 151, 237, 187, 8, 82, 115, 14, 183, 103,
|
||||
12, 203, 46, 161, 208, 251, 167, 123, 131,
|
||||
])
|
||||
.unwrap();
|
||||
let s = format!("{:?}", sig);
|
||||
assert_eq!(s, "DsaSig { r: 774484690634577222213819810519929266740561094381, s: 910998676210681457251421818099943952372231273347 }");
|
||||
}
|
||||
}
|
||||
1345
vendor/openssl/src/ec.rs
vendored
Normal file
1345
vendor/openssl/src/ec.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
224
vendor/openssl/src/ecdsa.rs
vendored
Normal file
224
vendor/openssl/src/ecdsa.rs
vendored
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
//! Low level Elliptic Curve Digital Signature Algorithm (ECDSA) functions.
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
use libc::c_int;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
|
||||
use crate::bn::{BigNum, BigNumRef};
|
||||
use crate::ec::EcKeyRef;
|
||||
use crate::error::ErrorStack;
|
||||
use crate::pkey::{HasPrivate, HasPublic};
|
||||
use crate::util::ForeignTypeRefExt;
|
||||
use crate::{cvt_n, cvt_p, LenType};
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::ECDSA_SIG;
|
||||
fn drop = ffi::ECDSA_SIG_free;
|
||||
|
||||
/// A low level interface to ECDSA.
|
||||
pub struct EcdsaSig;
|
||||
/// A reference to an [`EcdsaSig`].
|
||||
pub struct EcdsaSigRef;
|
||||
}
|
||||
|
||||
impl EcdsaSig {
|
||||
/// Computes a digital signature of the hash value `data` using the private EC key eckey.
|
||||
#[corresponds(ECDSA_do_sign)]
|
||||
pub fn sign<T>(data: &[u8], eckey: &EcKeyRef<T>) -> Result<EcdsaSig, ErrorStack>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
unsafe {
|
||||
assert!(data.len() <= c_int::MAX as usize);
|
||||
let sig = cvt_p(ffi::ECDSA_do_sign(
|
||||
data.as_ptr(),
|
||||
data.len() as LenType,
|
||||
eckey.as_ptr(),
|
||||
))?;
|
||||
Ok(EcdsaSig::from_ptr(sig))
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a new `EcdsaSig` by setting the `r` and `s` values associated with an ECDSA signature.
|
||||
#[corresponds(ECDSA_SIG_set0)]
|
||||
pub fn from_private_components(r: BigNum, s: BigNum) -> Result<EcdsaSig, ErrorStack> {
|
||||
unsafe {
|
||||
let sig = cvt_p(ffi::ECDSA_SIG_new())?;
|
||||
ECDSA_SIG_set0(sig, r.as_ptr(), s.as_ptr());
|
||||
mem::forget((r, s));
|
||||
Ok(EcdsaSig::from_ptr(sig))
|
||||
}
|
||||
}
|
||||
|
||||
from_der! {
|
||||
/// Decodes a DER-encoded ECDSA signature.
|
||||
#[corresponds(d2i_ECDSA_SIG)]
|
||||
from_der,
|
||||
EcdsaSig,
|
||||
ffi::d2i_ECDSA_SIG
|
||||
}
|
||||
}
|
||||
|
||||
impl EcdsaSigRef {
|
||||
to_der! {
|
||||
/// Serializes the ECDSA signature into a DER-encoded ECDSASignature structure.
|
||||
#[corresponds(i2d_ECDSA_SIG)]
|
||||
to_der,
|
||||
ffi::i2d_ECDSA_SIG
|
||||
}
|
||||
|
||||
/// Verifies if the signature is a valid ECDSA signature using the given public key.
|
||||
#[corresponds(ECDSA_do_verify)]
|
||||
pub fn verify<T>(&self, data: &[u8], eckey: &EcKeyRef<T>) -> Result<bool, ErrorStack>
|
||||
where
|
||||
T: HasPublic,
|
||||
{
|
||||
unsafe {
|
||||
assert!(data.len() <= c_int::MAX as usize);
|
||||
cvt_n(ffi::ECDSA_do_verify(
|
||||
data.as_ptr(),
|
||||
data.len() as LenType,
|
||||
self.as_ptr(),
|
||||
eckey.as_ptr(),
|
||||
))
|
||||
.map(|x| x == 1)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns internal component: `r` of an `EcdsaSig`. (See X9.62 or FIPS 186-2)
|
||||
#[corresponds(ECDSA_SIG_get0)]
|
||||
pub fn r(&self) -> &BigNumRef {
|
||||
unsafe {
|
||||
let mut r = ptr::null();
|
||||
ECDSA_SIG_get0(self.as_ptr(), &mut r, ptr::null_mut());
|
||||
BigNumRef::from_const_ptr(r)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns internal components: `s` of an `EcdsaSig`. (See X9.62 or FIPS 186-2)
|
||||
#[corresponds(ECDSA_SIG_get0)]
|
||||
pub fn s(&self) -> &BigNumRef {
|
||||
unsafe {
|
||||
let mut s = ptr::null();
|
||||
ECDSA_SIG_get0(self.as_ptr(), ptr::null_mut(), &mut s);
|
||||
BigNumRef::from_const_ptr(s)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl110, libressl273, boringssl))] {
|
||||
use ffi::{ECDSA_SIG_set0, ECDSA_SIG_get0};
|
||||
} else {
|
||||
#[allow(bad_style)]
|
||||
unsafe fn ECDSA_SIG_set0(
|
||||
sig: *mut ffi::ECDSA_SIG,
|
||||
r: *mut ffi::BIGNUM,
|
||||
s: *mut ffi::BIGNUM,
|
||||
) -> c_int {
|
||||
if r.is_null() || s.is_null() {
|
||||
return 0;
|
||||
}
|
||||
ffi::BN_clear_free((*sig).r);
|
||||
ffi::BN_clear_free((*sig).s);
|
||||
(*sig).r = r;
|
||||
(*sig).s = s;
|
||||
1
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn ECDSA_SIG_get0(
|
||||
sig: *const ffi::ECDSA_SIG,
|
||||
pr: *mut *const ffi::BIGNUM,
|
||||
ps: *mut *const ffi::BIGNUM)
|
||||
{
|
||||
if !pr.is_null() {
|
||||
(*pr) = (*sig).r;
|
||||
}
|
||||
if !ps.is_null() {
|
||||
(*ps) = (*sig).s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::ec::EcGroup;
|
||||
use crate::ec::EcKey;
|
||||
use crate::nid::Nid;
|
||||
use crate::pkey::{Private, Public};
|
||||
|
||||
fn get_public_key(group: &EcGroup, x: &EcKey<Private>) -> Result<EcKey<Public>, ErrorStack> {
|
||||
EcKey::from_public_key(group, x.public_key())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(osslconf = "OPENSSL_NO_EC", ignore)]
|
||||
fn sign_and_verify() {
|
||||
let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
|
||||
let private_key = EcKey::generate(&group).unwrap();
|
||||
let public_key = get_public_key(&group, &private_key).unwrap();
|
||||
|
||||
let private_key2 = EcKey::generate(&group).unwrap();
|
||||
let public_key2 = get_public_key(&group, &private_key2).unwrap();
|
||||
|
||||
let data = String::from("hello");
|
||||
let res = EcdsaSig::sign(data.as_bytes(), &private_key).unwrap();
|
||||
|
||||
// Signature can be verified using the correct data & correct public key
|
||||
let verification = res.verify(data.as_bytes(), &public_key).unwrap();
|
||||
assert!(verification);
|
||||
|
||||
// Signature will not be verified using the incorrect data but the correct public key
|
||||
let verification2 = res
|
||||
.verify(String::from("hello2").as_bytes(), &public_key)
|
||||
.unwrap();
|
||||
assert!(!verification2);
|
||||
|
||||
// Signature will not be verified using the correct data but the incorrect public key
|
||||
let verification3 = res.verify(data.as_bytes(), &public_key2).unwrap();
|
||||
assert!(!verification3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(osslconf = "OPENSSL_NO_EC", ignore)]
|
||||
fn check_private_components() {
|
||||
let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
|
||||
let private_key = EcKey::generate(&group).unwrap();
|
||||
let public_key = get_public_key(&group, &private_key).unwrap();
|
||||
let data = String::from("hello");
|
||||
let res = EcdsaSig::sign(data.as_bytes(), &private_key).unwrap();
|
||||
|
||||
let verification = res.verify(data.as_bytes(), &public_key).unwrap();
|
||||
assert!(verification);
|
||||
|
||||
let r = res.r().to_owned().unwrap();
|
||||
let s = res.s().to_owned().unwrap();
|
||||
|
||||
let res2 = EcdsaSig::from_private_components(r, s).unwrap();
|
||||
let verification2 = res2.verify(data.as_bytes(), &public_key).unwrap();
|
||||
assert!(verification2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(osslconf = "OPENSSL_NO_EC", ignore)]
|
||||
fn serialize_deserialize() {
|
||||
let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
|
||||
let private_key = EcKey::generate(&group).unwrap();
|
||||
let public_key = get_public_key(&group, &private_key).unwrap();
|
||||
|
||||
let data = String::from("hello");
|
||||
let res = EcdsaSig::sign(data.as_bytes(), &private_key).unwrap();
|
||||
|
||||
let der = res.to_der().unwrap();
|
||||
let sig = EcdsaSig::from_der(&der).unwrap();
|
||||
|
||||
let verification = sig.verify(data.as_bytes(), &public_key).unwrap();
|
||||
assert!(verification);
|
||||
}
|
||||
}
|
||||
578
vendor/openssl/src/encrypt.rs
vendored
Normal file
578
vendor/openssl/src/encrypt.rs
vendored
Normal file
|
|
@ -0,0 +1,578 @@
|
|||
//! Message encryption.
|
||||
//!
|
||||
//! The [`Encrypter`] allows for encryption of data given a public key. The [`Decrypter`] can be
|
||||
//! used with the corresponding private key to decrypt the data.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! Encrypt and decrypt data given an RSA keypair:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use openssl::encrypt::{Encrypter, Decrypter};
|
||||
//! use openssl::rsa::{Rsa, Padding};
|
||||
//! use openssl::pkey::PKey;
|
||||
//!
|
||||
//! // Generate a keypair
|
||||
//! let keypair = Rsa::generate(2048).unwrap();
|
||||
//! let keypair = PKey::from_rsa(keypair).unwrap();
|
||||
//!
|
||||
//! let data = b"hello, world!";
|
||||
//!
|
||||
//! // Encrypt the data with RSA PKCS1
|
||||
//! let mut encrypter = Encrypter::new(&keypair).unwrap();
|
||||
//! encrypter.set_rsa_padding(Padding::PKCS1).unwrap();
|
||||
//! // Create an output buffer
|
||||
//! let buffer_len = encrypter.encrypt_len(data).unwrap();
|
||||
//! let mut encrypted = vec![0; buffer_len];
|
||||
//! // Encrypt and truncate the buffer
|
||||
//! let encrypted_len = encrypter.encrypt(data, &mut encrypted).unwrap();
|
||||
//! encrypted.truncate(encrypted_len);
|
||||
//!
|
||||
//! // Decrypt the data
|
||||
//! let mut decrypter = Decrypter::new(&keypair).unwrap();
|
||||
//! decrypter.set_rsa_padding(Padding::PKCS1).unwrap();
|
||||
//! // Create an output buffer
|
||||
//! let buffer_len = decrypter.decrypt_len(&encrypted).unwrap();
|
||||
//! let mut decrypted = vec![0; buffer_len];
|
||||
//! // Encrypt and truncate the buffer
|
||||
//! let decrypted_len = decrypter.decrypt(&encrypted, &mut decrypted).unwrap();
|
||||
//! decrypted.truncate(decrypted_len);
|
||||
//! assert_eq!(&*decrypted, data);
|
||||
//! ```
|
||||
#[cfg(any(ossl102, libressl310))]
|
||||
use libc::c_int;
|
||||
use std::{marker::PhantomData, ptr};
|
||||
|
||||
use crate::error::ErrorStack;
|
||||
use crate::hash::MessageDigest;
|
||||
use crate::pkey::{HasPrivate, HasPublic, PKeyRef};
|
||||
use crate::rsa::Padding;
|
||||
use crate::{cvt, cvt_p};
|
||||
use foreign_types::ForeignTypeRef;
|
||||
|
||||
/// A type which encrypts data.
|
||||
pub struct Encrypter<'a> {
|
||||
pctx: *mut ffi::EVP_PKEY_CTX,
|
||||
_p: PhantomData<&'a ()>,
|
||||
}
|
||||
|
||||
unsafe impl Sync for Encrypter<'_> {}
|
||||
unsafe impl Send for Encrypter<'_> {}
|
||||
|
||||
impl Drop for Encrypter<'_> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
ffi::EVP_PKEY_CTX_free(self.pctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Encrypter<'a> {
|
||||
/// Creates a new `Encrypter`.
|
||||
///
|
||||
/// OpenSSL documentation at [`EVP_PKEY_encrypt_init`].
|
||||
///
|
||||
/// [`EVP_PKEY_encrypt_init`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_encrypt_init.html
|
||||
pub fn new<T>(pkey: &'a PKeyRef<T>) -> Result<Encrypter<'a>, ErrorStack>
|
||||
where
|
||||
T: HasPublic,
|
||||
{
|
||||
unsafe {
|
||||
ffi::init();
|
||||
|
||||
let pctx = cvt_p(ffi::EVP_PKEY_CTX_new(pkey.as_ptr(), ptr::null_mut()))?;
|
||||
let r = ffi::EVP_PKEY_encrypt_init(pctx);
|
||||
if r != 1 {
|
||||
ffi::EVP_PKEY_CTX_free(pctx);
|
||||
return Err(ErrorStack::get());
|
||||
}
|
||||
|
||||
Ok(Encrypter {
|
||||
pctx,
|
||||
_p: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the RSA padding mode in use.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
///
|
||||
/// This corresponds to `EVP_PKEY_CTX_get_rsa_padding`.
|
||||
pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> {
|
||||
unsafe {
|
||||
let mut pad = 0;
|
||||
cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.pctx, &mut pad))
|
||||
.map(|_| Padding::from_raw(pad))
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the RSA padding mode.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_CTX_set_rsa_padding`].
|
||||
///
|
||||
/// [`EVP_PKEY_CTX_set_rsa_padding`]: https://www.openssl.org/docs/manmaster/crypto/EVP_PKEY_CTX_set_rsa_padding.html
|
||||
pub fn set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_rsa_padding(
|
||||
self.pctx,
|
||||
padding.as_raw(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the RSA MGF1 algorithm.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_CTX_set_rsa_mgf1_md`].
|
||||
///
|
||||
/// [`EVP_PKEY_CTX_set_rsa_mgf1_md`]: https://www.openssl.org/docs/manmaster/man7/RSA-PSS.html
|
||||
pub fn set_rsa_mgf1_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_rsa_mgf1_md(
|
||||
self.pctx,
|
||||
md.as_ptr() as *mut _,
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the RSA OAEP algorithm.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_CTX_set_rsa_oaep_md`].
|
||||
///
|
||||
/// [`EVP_PKEY_CTX_set_rsa_oaep_md`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_set_rsa_oaep_md.html
|
||||
#[cfg(any(ossl102, libressl310))]
|
||||
pub fn set_rsa_oaep_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_rsa_oaep_md(
|
||||
self.pctx,
|
||||
md.as_ptr() as *mut _,
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the RSA OAEP label.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_CTX_set0_rsa_oaep_label`].
|
||||
///
|
||||
/// [`EVP_PKEY_CTX_set0_rsa_oaep_label`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_set0_rsa_oaep_label.html
|
||||
#[cfg(any(ossl102, libressl310))]
|
||||
pub fn set_rsa_oaep_label(&mut self, label: &[u8]) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
let p = cvt_p(ffi::OPENSSL_malloc(label.len() as _))?;
|
||||
ptr::copy_nonoverlapping(label.as_ptr(), p as *mut u8, label.len());
|
||||
|
||||
cvt(ffi::EVP_PKEY_CTX_set0_rsa_oaep_label(
|
||||
self.pctx,
|
||||
p,
|
||||
label.len() as c_int,
|
||||
))
|
||||
.map(|_| ())
|
||||
.map_err(|e| {
|
||||
ffi::OPENSSL_free(p);
|
||||
e
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Performs public key encryption.
|
||||
///
|
||||
/// In order to know the size needed for the output buffer, use [`encrypt_len`](Encrypter::encrypt_len).
|
||||
/// Note that the length of the output buffer can be greater of the length of the encoded data.
|
||||
/// ```
|
||||
/// # use openssl::{
|
||||
/// # encrypt::Encrypter,
|
||||
/// # pkey::PKey,
|
||||
/// # rsa::{Rsa, Padding},
|
||||
/// # };
|
||||
/// #
|
||||
/// # 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 input = b"hello world".to_vec();
|
||||
/// #
|
||||
/// let mut encrypter = Encrypter::new(&pkey).unwrap();
|
||||
/// encrypter.set_rsa_padding(Padding::PKCS1).unwrap();
|
||||
///
|
||||
/// // Get the length of the output buffer
|
||||
/// let buffer_len = encrypter.encrypt_len(&input).unwrap();
|
||||
/// let mut encoded = vec![0u8; buffer_len];
|
||||
///
|
||||
/// // Encode the data and get its length
|
||||
/// let encoded_len = encrypter.encrypt(&input, &mut encoded).unwrap();
|
||||
///
|
||||
/// // Use only the part of the buffer with the encoded data
|
||||
/// let encoded = &encoded[..encoded_len];
|
||||
/// ```
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_encrypt`].
|
||||
///
|
||||
/// [`EVP_PKEY_encrypt`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_encrypt.html
|
||||
pub fn encrypt(&self, from: &[u8], to: &mut [u8]) -> Result<usize, ErrorStack> {
|
||||
let mut written = to.len();
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_encrypt(
|
||||
self.pctx,
|
||||
to.as_mut_ptr(),
|
||||
&mut written,
|
||||
from.as_ptr(),
|
||||
from.len(),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(written)
|
||||
}
|
||||
|
||||
/// Gets the size of the buffer needed to encrypt the input data.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_encrypt`] called with a null pointer as output argument.
|
||||
///
|
||||
/// [`EVP_PKEY_encrypt`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_encrypt.html
|
||||
pub fn encrypt_len(&self, from: &[u8]) -> Result<usize, ErrorStack> {
|
||||
let mut written = 0;
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_encrypt(
|
||||
self.pctx,
|
||||
ptr::null_mut(),
|
||||
&mut written,
|
||||
from.as_ptr(),
|
||||
from.len(),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(written)
|
||||
}
|
||||
}
|
||||
|
||||
/// A type which decrypts data.
|
||||
pub struct Decrypter<'a> {
|
||||
pctx: *mut ffi::EVP_PKEY_CTX,
|
||||
_p: PhantomData<&'a ()>,
|
||||
}
|
||||
|
||||
unsafe impl Sync for Decrypter<'_> {}
|
||||
unsafe impl Send for Decrypter<'_> {}
|
||||
|
||||
impl Drop for Decrypter<'_> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
ffi::EVP_PKEY_CTX_free(self.pctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Decrypter<'a> {
|
||||
/// Creates a new `Decrypter`.
|
||||
///
|
||||
/// OpenSSL documentation at [`EVP_PKEY_decrypt_init`].
|
||||
///
|
||||
/// [`EVP_PKEY_decrypt_init`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_decrypt_init.html
|
||||
pub fn new<T>(pkey: &'a PKeyRef<T>) -> Result<Decrypter<'a>, ErrorStack>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
unsafe {
|
||||
ffi::init();
|
||||
|
||||
let pctx = cvt_p(ffi::EVP_PKEY_CTX_new(pkey.as_ptr(), ptr::null_mut()))?;
|
||||
let r = ffi::EVP_PKEY_decrypt_init(pctx);
|
||||
if r != 1 {
|
||||
ffi::EVP_PKEY_CTX_free(pctx);
|
||||
return Err(ErrorStack::get());
|
||||
}
|
||||
|
||||
Ok(Decrypter {
|
||||
pctx,
|
||||
_p: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the RSA padding mode in use.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
///
|
||||
/// This corresponds to `EVP_PKEY_CTX_get_rsa_padding`.
|
||||
pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> {
|
||||
unsafe {
|
||||
let mut pad = 0;
|
||||
cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.pctx, &mut pad))
|
||||
.map(|_| Padding::from_raw(pad))
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the RSA padding mode.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_CTX_set_rsa_padding`].
|
||||
///
|
||||
/// [`EVP_PKEY_CTX_set_rsa_padding`]: https://www.openssl.org/docs/manmaster/crypto/EVP_PKEY_CTX_set_rsa_padding.html
|
||||
pub fn set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_rsa_padding(
|
||||
self.pctx,
|
||||
padding.as_raw(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the RSA MGF1 algorithm.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_CTX_set_rsa_mgf1_md`].
|
||||
///
|
||||
/// [`EVP_PKEY_CTX_set_rsa_mgf1_md`]: https://www.openssl.org/docs/manmaster/man7/RSA-PSS.html
|
||||
pub fn set_rsa_mgf1_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_rsa_mgf1_md(
|
||||
self.pctx,
|
||||
md.as_ptr() as *mut _,
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the RSA OAEP algorithm.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_CTX_set_rsa_oaep_md`].
|
||||
///
|
||||
/// [`EVP_PKEY_CTX_set_rsa_oaep_md`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_set_rsa_oaep_md.html
|
||||
#[cfg(any(ossl102, libressl310))]
|
||||
pub fn set_rsa_oaep_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_rsa_oaep_md(
|
||||
self.pctx,
|
||||
md.as_ptr() as *mut _,
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the RSA OAEP label.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_CTX_set0_rsa_oaep_label`].
|
||||
///
|
||||
/// [`EVP_PKEY_CTX_set0_rsa_oaep_label`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_set0_rsa_oaep_label.html
|
||||
#[cfg(any(ossl102, libressl310))]
|
||||
pub fn set_rsa_oaep_label(&mut self, label: &[u8]) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
let p = cvt_p(ffi::OPENSSL_malloc(label.len() as _))?;
|
||||
ptr::copy_nonoverlapping(label.as_ptr(), p as *mut u8, label.len());
|
||||
|
||||
cvt(ffi::EVP_PKEY_CTX_set0_rsa_oaep_label(
|
||||
self.pctx,
|
||||
p,
|
||||
label.len() as c_int,
|
||||
))
|
||||
.map(|_| ())
|
||||
.map_err(|e| {
|
||||
ffi::OPENSSL_free(p);
|
||||
e
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Performs public key decryption.
|
||||
///
|
||||
/// In order to know the size needed for the output buffer, use [`decrypt_len`](Decrypter::decrypt_len).
|
||||
/// Note that the length of the output buffer can be greater of the length of the decoded data.
|
||||
/// ```
|
||||
/// # use openssl::{
|
||||
/// # encrypt::Decrypter,
|
||||
/// # pkey::PKey,
|
||||
/// # rsa::{Rsa, Padding},
|
||||
/// # };
|
||||
/// #
|
||||
/// # const INPUT: &[u8] = b"\
|
||||
/// # \x26\xa1\xc1\x13\xc5\x7f\xb4\x9f\xa0\xb4\xde\x61\x5e\x2e\xc6\xfb\x76\x5c\xd1\x2b\x5f\
|
||||
/// # \x1d\x36\x60\xfa\xf8\xe8\xb3\x21\xf4\x9c\x70\xbc\x03\xea\xea\xac\xce\x4b\xb3\xf6\x45\
|
||||
/// # \xcc\xb3\x80\x9e\xa8\xf7\xc3\x5d\x06\x12\x7a\xa3\x0c\x30\x67\xf1\xe7\x94\x6c\xf6\x26\
|
||||
/// # \xac\x28\x17\x59\x69\xe1\xdc\xed\x7e\xc0\xe9\x62\x57\x49\xce\xdd\x13\x07\xde\x18\x03\
|
||||
/// # \x0f\x9d\x61\x65\xb9\x23\x8c\x78\x4b\xad\x23\x49\x75\x47\x64\xa0\xa0\xa2\x90\xc1\x49\
|
||||
/// # \x1b\x05\x24\xc2\xe9\x2c\x0d\x49\x78\x72\x61\x72\xed\x8b\x6f\x8a\xe8\xca\x05\x5c\x58\
|
||||
/// # \xd6\x95\xd6\x7b\xe3\x2d\x0d\xaa\x3e\x6d\x3c\x9a\x1c\x1d\xb4\x6c\x42\x9d\x9a\x82\x55\
|
||||
/// # \xd9\xde\xc8\x08\x7b\x17\xac\xd7\xaf\x86\x7b\x69\x9e\x3c\xf4\x5e\x1c\x39\x52\x6d\x62\
|
||||
/// # \x50\x51\xbd\xa6\xc8\x4e\xe9\x34\xf0\x37\x0d\xa9\xa9\x77\xe6\xf5\xc2\x47\x2d\xa8\xee\
|
||||
/// # \x3f\x69\x78\xff\xa9\xdc\x70\x22\x20\x9a\x5c\x9b\x70\x15\x90\xd3\xb4\x0e\x54\x9e\x48\
|
||||
/// # \xed\xb6\x2c\x88\xfc\xb4\xa9\x37\x10\xfa\x71\xb2\xec\x75\xe7\xe7\x0e\xf4\x60\x2c\x7b\
|
||||
/// # \x58\xaf\xa0\x53\xbd\x24\xf1\x12\xe3\x2e\x99\x25\x0a\x54\x54\x9d\xa1\xdb\xca\x41\x85\
|
||||
/// # \xf4\x62\x78\x64";
|
||||
/// #
|
||||
/// # 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 input = INPUT.to_vec();
|
||||
/// #
|
||||
/// let mut decrypter = Decrypter::new(&pkey).unwrap();
|
||||
/// decrypter.set_rsa_padding(Padding::PKCS1).unwrap();
|
||||
///
|
||||
/// // Get the length of the output buffer
|
||||
/// let buffer_len = decrypter.decrypt_len(&input).unwrap();
|
||||
/// let mut decoded = vec![0u8; buffer_len];
|
||||
///
|
||||
/// // Decrypt the data and get its length
|
||||
/// let decoded_len = decrypter.decrypt(&input, &mut decoded).unwrap();
|
||||
///
|
||||
/// // Use only the part of the buffer with the decrypted data
|
||||
/// let decoded = &decoded[..decoded_len];
|
||||
/// ```
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_decrypt`].
|
||||
///
|
||||
/// [`EVP_PKEY_decrypt`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_decrypt.html
|
||||
pub fn decrypt(&self, from: &[u8], to: &mut [u8]) -> Result<usize, ErrorStack> {
|
||||
let mut written = to.len();
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_decrypt(
|
||||
self.pctx,
|
||||
to.as_mut_ptr(),
|
||||
&mut written,
|
||||
from.as_ptr(),
|
||||
from.len(),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(written)
|
||||
}
|
||||
|
||||
/// Gets the size of the buffer needed to decrypt the input data.
|
||||
///
|
||||
/// This corresponds to [`EVP_PKEY_decrypt`] called with a null pointer as output argument.
|
||||
///
|
||||
/// [`EVP_PKEY_decrypt`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_decrypt.html
|
||||
pub fn decrypt_len(&self, from: &[u8]) -> Result<usize, ErrorStack> {
|
||||
let mut written = 0;
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_decrypt(
|
||||
self.pctx,
|
||||
ptr::null_mut(),
|
||||
&mut written,
|
||||
from.as_ptr(),
|
||||
from.len(),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(written)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use hex::FromHex;
|
||||
|
||||
use crate::encrypt::{Decrypter, Encrypter};
|
||||
#[cfg(any(ossl102, libressl310))]
|
||||
use crate::hash::MessageDigest;
|
||||
use crate::pkey::PKey;
|
||||
use crate::rsa::{Padding, Rsa};
|
||||
|
||||
const INPUT: &str =
|
||||
"65794a68624763694f694a53557a49314e694a392e65794a7063334d694f694a71623255694c41304b49434a6c\
|
||||
654841694f6a457a4d4441344d546b7a4f44417344516f67496d6830644841364c79396c654746746347786c4c\
|
||||
6d4e76625339706331397962323930496a7030636e566c6651";
|
||||
|
||||
#[test]
|
||||
fn rsa_encrypt_decrypt() {
|
||||
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 encrypter = Encrypter::new(&pkey).unwrap();
|
||||
encrypter.set_rsa_padding(Padding::PKCS1).unwrap();
|
||||
let input = Vec::from_hex(INPUT).unwrap();
|
||||
let buffer_len = encrypter.encrypt_len(&input).unwrap();
|
||||
let mut encoded = vec![0u8; buffer_len];
|
||||
let encoded_len = encrypter.encrypt(&input, &mut encoded).unwrap();
|
||||
let encoded = &encoded[..encoded_len];
|
||||
|
||||
let mut decrypter = Decrypter::new(&pkey).unwrap();
|
||||
decrypter.set_rsa_padding(Padding::PKCS1).unwrap();
|
||||
let buffer_len = decrypter.decrypt_len(encoded).unwrap();
|
||||
let mut decoded = vec![0u8; buffer_len];
|
||||
let decoded_len = decrypter.decrypt(encoded, &mut decoded).unwrap();
|
||||
let decoded = &decoded[..decoded_len];
|
||||
|
||||
assert_eq!(decoded, &*input);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(ossl102, libressl310))]
|
||||
fn rsa_encrypt_decrypt_with_sha256() {
|
||||
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 md = MessageDigest::sha256();
|
||||
|
||||
let mut encrypter = Encrypter::new(&pkey).unwrap();
|
||||
encrypter.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
|
||||
encrypter.set_rsa_oaep_md(md).unwrap();
|
||||
encrypter.set_rsa_mgf1_md(md).unwrap();
|
||||
let input = Vec::from_hex(INPUT).unwrap();
|
||||
let buffer_len = encrypter.encrypt_len(&input).unwrap();
|
||||
let mut encoded = vec![0u8; buffer_len];
|
||||
let encoded_len = encrypter.encrypt(&input, &mut encoded).unwrap();
|
||||
let encoded = &encoded[..encoded_len];
|
||||
|
||||
let mut decrypter = Decrypter::new(&pkey).unwrap();
|
||||
decrypter.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
|
||||
decrypter.set_rsa_oaep_md(md).unwrap();
|
||||
decrypter.set_rsa_mgf1_md(md).unwrap();
|
||||
let buffer_len = decrypter.decrypt_len(encoded).unwrap();
|
||||
let mut decoded = vec![0u8; buffer_len];
|
||||
let decoded_len = decrypter.decrypt(encoded, &mut decoded).unwrap();
|
||||
let decoded = &decoded[..decoded_len];
|
||||
|
||||
assert_eq!(decoded, &*input);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(ossl102, libressl310))]
|
||||
fn rsa_encrypt_decrypt_oaep_label() {
|
||||
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 encrypter = Encrypter::new(&pkey).unwrap();
|
||||
encrypter.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
|
||||
encrypter.set_rsa_oaep_label(b"test_oaep_label").unwrap();
|
||||
let input = Vec::from_hex(INPUT).unwrap();
|
||||
let buffer_len = encrypter.encrypt_len(&input).unwrap();
|
||||
let mut encoded = vec![0u8; buffer_len];
|
||||
let encoded_len = encrypter.encrypt(&input, &mut encoded).unwrap();
|
||||
let encoded = &encoded[..encoded_len];
|
||||
|
||||
let mut decrypter = Decrypter::new(&pkey).unwrap();
|
||||
decrypter.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
|
||||
decrypter.set_rsa_oaep_label(b"test_oaep_label").unwrap();
|
||||
let buffer_len = decrypter.decrypt_len(encoded).unwrap();
|
||||
let mut decoded = vec![0u8; buffer_len];
|
||||
let decoded_len = decrypter.decrypt(encoded, &mut decoded).unwrap();
|
||||
let decoded = &decoded[..decoded_len];
|
||||
|
||||
assert_eq!(decoded, &*input);
|
||||
|
||||
decrypter.set_rsa_oaep_label(b"wrong_oaep_label").unwrap();
|
||||
let buffer_len = decrypter.decrypt_len(encoded).unwrap();
|
||||
let mut decoded = vec![0u8; buffer_len];
|
||||
|
||||
assert!(decrypter.decrypt(encoded, &mut decoded).is_err());
|
||||
}
|
||||
}
|
||||
181
vendor/openssl/src/envelope.rs
vendored
Normal file
181
vendor/openssl/src/envelope.rs
vendored
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
//! Envelope encryption.
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! ```rust
|
||||
//! use openssl::rsa::Rsa;
|
||||
//! use openssl::envelope::Seal;
|
||||
//! use openssl::pkey::PKey;
|
||||
//! use openssl::symm::Cipher;
|
||||
//!
|
||||
//! let rsa = Rsa::generate(2048).unwrap();
|
||||
//! let key = PKey::from_rsa(rsa).unwrap();
|
||||
//!
|
||||
//! let cipher = Cipher::aes_256_cbc();
|
||||
//! let mut seal = Seal::new(cipher, &[key]).unwrap();
|
||||
//!
|
||||
//! let secret = b"My secret message";
|
||||
//! let mut encrypted = vec![0; secret.len() + cipher.block_size()];
|
||||
//!
|
||||
//! let mut enc_len = seal.update(secret, &mut encrypted).unwrap();
|
||||
//! enc_len += seal.finalize(&mut encrypted[enc_len..]).unwrap();
|
||||
//! encrypted.truncate(enc_len);
|
||||
//! ```
|
||||
use crate::cipher::CipherRef;
|
||||
use crate::cipher_ctx::CipherCtx;
|
||||
use crate::error::ErrorStack;
|
||||
use crate::pkey::{HasPrivate, HasPublic, PKey, PKeyRef};
|
||||
use crate::symm::Cipher;
|
||||
use foreign_types::ForeignTypeRef;
|
||||
|
||||
/// Represents an EVP_Seal context.
|
||||
pub struct Seal {
|
||||
ctx: CipherCtx,
|
||||
iv: Option<Vec<u8>>,
|
||||
enc_keys: Vec<Vec<u8>>,
|
||||
}
|
||||
|
||||
impl Seal {
|
||||
/// Creates a new `Seal`.
|
||||
pub fn new<T>(cipher: Cipher, pub_keys: &[PKey<T>]) -> Result<Seal, ErrorStack>
|
||||
where
|
||||
T: HasPublic,
|
||||
{
|
||||
let mut iv = cipher.iv_len().map(|len| vec![0; len]);
|
||||
let mut enc_keys = vec![vec![]; pub_keys.len()];
|
||||
|
||||
let mut ctx = CipherCtx::new()?;
|
||||
ctx.seal_init(
|
||||
Some(unsafe { CipherRef::from_ptr(cipher.as_ptr() as *mut _) }),
|
||||
pub_keys,
|
||||
&mut enc_keys,
|
||||
iv.as_deref_mut(),
|
||||
)?;
|
||||
|
||||
Ok(Seal { ctx, iv, enc_keys })
|
||||
}
|
||||
|
||||
/// Returns the initialization vector, if the cipher uses one.
|
||||
#[allow(clippy::option_as_ref_deref)]
|
||||
pub fn iv(&self) -> Option<&[u8]> {
|
||||
self.iv.as_ref().map(|v| &**v)
|
||||
}
|
||||
|
||||
/// Returns the encrypted keys.
|
||||
pub fn encrypted_keys(&self) -> &[Vec<u8>] {
|
||||
&self.enc_keys
|
||||
}
|
||||
|
||||
/// Feeds data from `input` through the cipher, writing encrypted bytes into `output`.
|
||||
///
|
||||
/// The number of bytes written to `output` is returned. Note that this may
|
||||
/// not be equal to the length of `input`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `output.len() < input.len() + block_size` where `block_size` is
|
||||
/// the block size of the cipher (see `Cipher::block_size`), or if
|
||||
/// `output.len() > c_int::MAX`.
|
||||
pub fn update(&mut self, input: &[u8], output: &mut [u8]) -> Result<usize, ErrorStack> {
|
||||
self.ctx.cipher_update(input, Some(output))
|
||||
}
|
||||
|
||||
/// Finishes the encryption process, writing any remaining data to `output`.
|
||||
///
|
||||
/// The number of bytes written to `output` is returned.
|
||||
///
|
||||
/// `update` should not be called after this method.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `output` is less than the cipher's block size.
|
||||
pub fn finalize(&mut self, output: &mut [u8]) -> Result<usize, ErrorStack> {
|
||||
self.ctx.cipher_final(output)
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents an EVP_Open context.
|
||||
pub struct Open {
|
||||
ctx: CipherCtx,
|
||||
}
|
||||
|
||||
impl Open {
|
||||
/// Creates a new `Open`.
|
||||
pub fn new<T>(
|
||||
cipher: Cipher,
|
||||
priv_key: &PKeyRef<T>,
|
||||
iv: Option<&[u8]>,
|
||||
encrypted_key: &[u8],
|
||||
) -> Result<Open, ErrorStack>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
let mut ctx = CipherCtx::new()?;
|
||||
ctx.open_init(
|
||||
Some(unsafe { CipherRef::from_ptr(cipher.as_ptr() as *mut _) }),
|
||||
encrypted_key,
|
||||
iv,
|
||||
Some(priv_key),
|
||||
)?;
|
||||
|
||||
Ok(Open { ctx })
|
||||
}
|
||||
|
||||
/// Feeds data from `input` through the cipher, writing decrypted bytes into `output`.
|
||||
///
|
||||
/// The number of bytes written to `output` is returned. Note that this may
|
||||
/// not be equal to the length of `input`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `output.len() < input.len() + block_size` where
|
||||
/// `block_size` is the block size of the cipher (see `Cipher::block_size`),
|
||||
/// or if `output.len() > c_int::MAX`.
|
||||
pub fn update(&mut self, input: &[u8], output: &mut [u8]) -> Result<usize, ErrorStack> {
|
||||
self.ctx.cipher_update(input, Some(output))
|
||||
}
|
||||
|
||||
/// Finishes the decryption process, writing any remaining data to `output`.
|
||||
///
|
||||
/// The number of bytes written to `output` is returned.
|
||||
///
|
||||
/// `update` should not be called after this method.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `output` is less than the cipher's block size.
|
||||
pub fn finalize(&mut self, output: &mut [u8]) -> Result<usize, ErrorStack> {
|
||||
self.ctx.cipher_final(output)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::pkey::PKey;
|
||||
use crate::symm::Cipher;
|
||||
|
||||
#[test]
|
||||
fn public_encrypt_private_decrypt() {
|
||||
let private_pem = include_bytes!("../test/rsa.pem");
|
||||
let public_pem = include_bytes!("../test/rsa.pem.pub");
|
||||
let private_key = PKey::private_key_from_pem(private_pem).unwrap();
|
||||
let public_key = PKey::public_key_from_pem(public_pem).unwrap();
|
||||
let cipher = Cipher::aes_256_cbc();
|
||||
let secret = b"My secret message";
|
||||
|
||||
let mut seal = Seal::new(cipher, &[public_key]).unwrap();
|
||||
let mut encrypted = vec![0; secret.len() + cipher.block_size()];
|
||||
let mut enc_len = seal.update(secret, &mut encrypted).unwrap();
|
||||
enc_len += seal.finalize(&mut encrypted[enc_len..]).unwrap();
|
||||
let iv = seal.iv();
|
||||
let encrypted_key = &seal.encrypted_keys()[0];
|
||||
|
||||
let mut open = Open::new(cipher, &private_key, iv, encrypted_key).unwrap();
|
||||
let mut decrypted = vec![0; enc_len + cipher.block_size()];
|
||||
let mut dec_len = open.update(&encrypted[..enc_len], &mut decrypted).unwrap();
|
||||
dec_len += open.finalize(&mut decrypted[dec_len..]).unwrap();
|
||||
|
||||
assert_eq!(&secret[..], &decrypted[..dec_len]);
|
||||
}
|
||||
}
|
||||
418
vendor/openssl/src/error.rs
vendored
Normal file
418
vendor/openssl/src/error.rs
vendored
Normal file
|
|
@ -0,0 +1,418 @@
|
|||
//! Errors returned by OpenSSL library.
|
||||
//!
|
||||
//! OpenSSL errors are stored in an `ErrorStack`. Most methods in the crate
|
||||
//! returns a `Result<T, ErrorStack>` 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 cfg_if::cfg_if;
|
||||
use libc::{c_char, c_int};
|
||||
use std::borrow::Cow;
|
||||
#[cfg(boringssl)]
|
||||
use std::convert::TryInto;
|
||||
use std::error;
|
||||
use std::ffi::CStr;
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
use std::ptr;
|
||||
use std::str;
|
||||
|
||||
#[cfg(not(boringssl))]
|
||||
type ErrType = libc::c_ulong;
|
||||
#[cfg(boringssl)]
|
||||
type ErrType = libc::c_uint;
|
||||
|
||||
/// Collection of [`Error`]s from OpenSSL.
|
||||
///
|
||||
/// [`Error`]: struct.Error.html
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ErrorStack(Vec<Error>);
|
||||
|
||||
impl ErrorStack {
|
||||
/// Returns the contents of the OpenSSL error stack.
|
||||
pub fn get() -> ErrorStack {
|
||||
let mut vec = vec![];
|
||||
while let Some(err) = Error::get() {
|
||||
vec.push(err);
|
||||
}
|
||||
ErrorStack(vec)
|
||||
}
|
||||
|
||||
/// Pushes the errors back onto the OpenSSL error stack.
|
||||
pub fn put(&self) {
|
||||
for error in self.errors() {
|
||||
error.put();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ErrorStack {
|
||||
/// Returns the errors in the stack.
|
||||
pub fn errors(&self) -> &[Error] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ErrorStack {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if self.0.is_empty() {
|
||||
return fmt.write_str("OpenSSL error");
|
||||
}
|
||||
|
||||
let mut first = true;
|
||||
for err in &self.0 {
|
||||
if !first {
|
||||
fmt.write_str(", ")?;
|
||||
}
|
||||
write!(fmt, "{}", err)?;
|
||||
first = false;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for ErrorStack {}
|
||||
|
||||
impl From<ErrorStack> for io::Error {
|
||||
fn from(e: ErrorStack) -> io::Error {
|
||||
io::Error::new(io::ErrorKind::Other, e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ErrorStack> for fmt::Error {
|
||||
fn from(_: ErrorStack) -> fmt::Error {
|
||||
fmt::Error
|
||||
}
|
||||
}
|
||||
|
||||
/// An error reported from OpenSSL.
|
||||
#[derive(Clone)]
|
||||
pub struct Error {
|
||||
code: ErrType,
|
||||
file: ShimStr,
|
||||
line: c_int,
|
||||
func: Option<ShimStr>,
|
||||
data: Option<Cow<'static, str>>,
|
||||
}
|
||||
|
||||
unsafe impl Sync for Error {}
|
||||
unsafe impl Send for Error {}
|
||||
|
||||
impl Error {
|
||||
/// Returns the first error on the OpenSSL error stack.
|
||||
pub fn get() -> Option<Error> {
|
||||
unsafe {
|
||||
ffi::init();
|
||||
|
||||
let mut file = ptr::null();
|
||||
let mut line = 0;
|
||||
let mut func = ptr::null();
|
||||
let mut data = ptr::null();
|
||||
let mut flags = 0;
|
||||
match ERR_get_error_all(&mut file, &mut line, &mut func, &mut data, &mut flags) {
|
||||
0 => None,
|
||||
code => {
|
||||
// The memory referenced by data is only valid until that slot is overwritten
|
||||
// in the error stack, so we'll need to copy it off if it's dynamic
|
||||
let data = if flags & ffi::ERR_TXT_STRING != 0 {
|
||||
let bytes = CStr::from_ptr(data as *const _).to_bytes();
|
||||
let data = str::from_utf8(bytes).unwrap();
|
||||
#[cfg(not(boringssl))]
|
||||
let data = if flags & ffi::ERR_TXT_MALLOCED != 0 {
|
||||
Cow::Owned(data.to_string())
|
||||
} else {
|
||||
Cow::Borrowed(data)
|
||||
};
|
||||
#[cfg(boringssl)]
|
||||
let data = Cow::Borrowed(data);
|
||||
Some(data)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let file = ShimStr::new(file);
|
||||
|
||||
let func = if func.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(ShimStr::new(func))
|
||||
};
|
||||
|
||||
Some(Error {
|
||||
code,
|
||||
file,
|
||||
line,
|
||||
func,
|
||||
data,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Pushes the error back onto the OpenSSL error stack.
|
||||
pub fn put(&self) {
|
||||
self.put_error();
|
||||
|
||||
unsafe {
|
||||
let data = match self.data {
|
||||
Some(Cow::Borrowed(data)) => Some((data.as_ptr() as *mut c_char, 0)),
|
||||
Some(Cow::Owned(ref data)) => {
|
||||
let ptr = ffi::CRYPTO_malloc(
|
||||
(data.len() + 1) as _,
|
||||
concat!(file!(), "\0").as_ptr() as _,
|
||||
line!() as _,
|
||||
) as *mut c_char;
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
ptr::copy_nonoverlapping(data.as_ptr(), ptr as *mut u8, data.len());
|
||||
*ptr.add(data.len()) = 0;
|
||||
Some((ptr, ffi::ERR_TXT_MALLOCED))
|
||||
}
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
if let Some((ptr, flags)) = data {
|
||||
ffi::ERR_set_error_data(ptr, flags | ffi::ERR_TXT_STRING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl300)]
|
||||
fn put_error(&self) {
|
||||
unsafe {
|
||||
ffi::ERR_new();
|
||||
ffi::ERR_set_debug(
|
||||
self.file.as_ptr(),
|
||||
self.line,
|
||||
self.func.as_ref().map_or(ptr::null(), |s| s.as_ptr()),
|
||||
);
|
||||
ffi::ERR_set_error(self.library_code(), self.reason_code(), ptr::null());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(ossl300))]
|
||||
fn put_error(&self) {
|
||||
#[cfg(not(boringssl))]
|
||||
let line = self.line;
|
||||
#[cfg(boringssl)]
|
||||
let line = self.line.try_into().unwrap();
|
||||
unsafe {
|
||||
ffi::ERR_put_error(
|
||||
self.library_code(),
|
||||
ffi::ERR_GET_FUNC(self.code),
|
||||
self.reason_code(),
|
||||
self.file.as_ptr(),
|
||||
line,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the raw OpenSSL error code for this error.
|
||||
pub fn code(&self) -> ErrType {
|
||||
self.code
|
||||
}
|
||||
|
||||
/// 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.code);
|
||||
if cstr.is_null() {
|
||||
return None;
|
||||
}
|
||||
let bytes = CStr::from_ptr(cstr as *const _).to_bytes();
|
||||
Some(str::from_utf8(bytes).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the raw OpenSSL error constant for the library reporting the
|
||||
/// error.
|
||||
// On BoringSSL ERR_GET_{LIB,FUNC,REASON} are `unsafe`, but on
|
||||
// OpenSSL/LibreSSL they're safe.
|
||||
#[allow(unused_unsafe)]
|
||||
pub fn library_code(&self) -> libc::c_int {
|
||||
unsafe { ffi::ERR_GET_LIB(self.code) }
|
||||
}
|
||||
|
||||
/// Returns the name of the function reporting the error.
|
||||
pub fn function(&self) -> Option<RetStr<'_>> {
|
||||
self.func.as_ref().map(|s| s.as_str())
|
||||
}
|
||||
|
||||
/// Returns the reason for the error.
|
||||
pub fn reason(&self) -> Option<&'static str> {
|
||||
unsafe {
|
||||
let cstr = ffi::ERR_reason_error_string(self.code);
|
||||
if cstr.is_null() {
|
||||
return None;
|
||||
}
|
||||
let bytes = CStr::from_ptr(cstr as *const _).to_bytes();
|
||||
Some(str::from_utf8(bytes).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the raw OpenSSL error constant for the reason for the error.
|
||||
// On BoringSSL ERR_GET_{LIB,FUNC,REASON} are `unsafe`, but on
|
||||
// OpenSSL/LibreSSL they're safe.
|
||||
#[allow(unused_unsafe)]
|
||||
pub fn reason_code(&self) -> libc::c_int {
|
||||
unsafe { ffi::ERR_GET_REASON(self.code) }
|
||||
}
|
||||
|
||||
/// Returns the name of the source file which encountered the error.
|
||||
pub fn file(&self) -> RetStr<'_> {
|
||||
self.file.as_str()
|
||||
}
|
||||
|
||||
/// Returns the line in the source file which encountered the error.
|
||||
pub fn line(&self) -> u32 {
|
||||
self.line as u32
|
||||
}
|
||||
|
||||
/// Returns additional data describing the error.
|
||||
#[allow(clippy::option_as_ref_deref)]
|
||||
pub fn data(&self) -> Option<&str> {
|
||||
self.data.as_ref().map(|s| &**s)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Error {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
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.field("file", &self.file());
|
||||
builder.field("line", &self.line());
|
||||
if let Some(data) = self.data() {
|
||||
builder.field("data", &data);
|
||||
}
|
||||
builder.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
// On BoringSSL ERR_GET_{LIB,FUNC,REASON} are `unsafe`, but on
|
||||
// OpenSSL/LibreSSL they're safe.
|
||||
#[allow(unused_unsafe)]
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(fmt, "error:{:08X}", self.code())?;
|
||||
match self.library() {
|
||||
Some(l) => write!(fmt, ":{}", l)?,
|
||||
None => write!(fmt, ":lib({})", self.library_code())?,
|
||||
}
|
||||
match self.function() {
|
||||
Some(f) => write!(fmt, ":{}", f)?,
|
||||
None => write!(fmt, ":func({})", unsafe { ffi::ERR_GET_FUNC(self.code()) })?,
|
||||
}
|
||||
match self.reason() {
|
||||
Some(r) => write!(fmt, ":{}", r)?,
|
||||
None => write!(fmt, ":reason({})", self.reason_code())?,
|
||||
}
|
||||
write!(
|
||||
fmt,
|
||||
":{}:{}:{}",
|
||||
self.file(),
|
||||
self.line(),
|
||||
self.data().unwrap_or("")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for Error {}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(ossl300)] {
|
||||
use std::ffi::{CString};
|
||||
use ffi::ERR_get_error_all;
|
||||
|
||||
type RetStr<'a> = &'a str;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct ShimStr(CString);
|
||||
|
||||
impl ShimStr {
|
||||
unsafe fn new(s: *const c_char) -> Self {
|
||||
ShimStr(CStr::from_ptr(s).to_owned())
|
||||
}
|
||||
|
||||
fn as_ptr(&self) -> *const c_char {
|
||||
self.0.as_ptr()
|
||||
}
|
||||
|
||||
fn as_str(&self) -> &str {
|
||||
self.0.to_str().unwrap()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
#[allow(bad_style)]
|
||||
unsafe extern "C" fn ERR_get_error_all(
|
||||
file: *mut *const c_char,
|
||||
line: *mut c_int,
|
||||
func: *mut *const c_char,
|
||||
data: *mut *const c_char,
|
||||
flags: *mut c_int,
|
||||
) -> ErrType {
|
||||
let code = ffi::ERR_get_error_line_data(file, line, data, flags);
|
||||
*func = ffi::ERR_func_error_string(code);
|
||||
code
|
||||
}
|
||||
|
||||
type RetStr<'a> = &'static str;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct ShimStr(*const c_char);
|
||||
|
||||
impl ShimStr {
|
||||
unsafe fn new(s: *const c_char) -> Self {
|
||||
ShimStr(s)
|
||||
}
|
||||
|
||||
fn as_ptr(&self) -> *const c_char {
|
||||
self.0
|
||||
}
|
||||
|
||||
fn as_str(&self) -> &'static str {
|
||||
unsafe {
|
||||
CStr::from_ptr(self.0).to_str().unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[cfg(not(ossl310))]
|
||||
use crate::nid::Nid;
|
||||
|
||||
#[test]
|
||||
// Due to a bug in OpenSSL 3.1.0, this test can hang there. Skip for now.
|
||||
#[cfg(not(ossl310))]
|
||||
fn test_error_library_code() {
|
||||
let stack = Nid::create("not-an-oid", "invalid", "invalid").unwrap_err();
|
||||
let errors = stack.errors();
|
||||
#[cfg(not(boringssl))]
|
||||
assert_eq!(errors[0].library_code(), ffi::ERR_LIB_ASN1);
|
||||
#[cfg(boringssl)]
|
||||
assert_eq!(errors[0].library_code(), ffi::ERR_LIB_OBJ as libc::c_int);
|
||||
}
|
||||
}
|
||||
32
vendor/openssl/src/ex_data.rs
vendored
Normal file
32
vendor/openssl/src/ex_data.rs
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
use libc::c_int;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
/// A slot in a type's "extra data" structure.
|
||||
///
|
||||
/// It is parameterized over the type containing the extra data as well as the
|
||||
/// type of the data in the slot.
|
||||
pub struct Index<T, U>(c_int, PhantomData<(T, U)>);
|
||||
|
||||
impl<T, U> Copy for Index<T, U> {}
|
||||
|
||||
impl<T, U> Clone for Index<T, U> {
|
||||
fn clone(&self) -> Index<T, U> {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Index<T, U> {
|
||||
/// Creates an `Index` from a raw integer index.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller must ensure that the index correctly maps to a `U` value stored in a `T`.
|
||||
pub unsafe fn from_raw(idx: c_int) -> Index<T, U> {
|
||||
Index(idx, PhantomData)
|
||||
}
|
||||
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub fn as_raw(&self) -> c_int {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
21
vendor/openssl/src/fips.rs
vendored
Normal file
21
vendor/openssl/src/fips.rs
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
//! FIPS 140-2 support.
|
||||
//!
|
||||
//! See [OpenSSL's documentation] for details.
|
||||
//!
|
||||
//! [OpenSSL's documentation]: https://www.openssl.org/docs/fips/UserGuide-2.0.pdf
|
||||
use crate::cvt;
|
||||
use crate::error::ErrorStack;
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
/// Moves the library into or out of the FIPS 140-2 mode of operation.
|
||||
#[corresponds(FIPS_mode_set)]
|
||||
pub fn enable(enabled: bool) -> Result<(), ErrorStack> {
|
||||
ffi::init();
|
||||
unsafe { cvt(ffi::FIPS_mode_set(enabled as _)).map(|_| ()) }
|
||||
}
|
||||
|
||||
/// Determines if the library is running in the FIPS 140-2 mode of operation.
|
||||
#[corresponds(FIPS_mode)]
|
||||
pub fn enabled() -> bool {
|
||||
unsafe { ffi::FIPS_mode() != 0 }
|
||||
}
|
||||
796
vendor/openssl/src/hash.rs
vendored
Normal file
796
vendor/openssl/src/hash.rs
vendored
Normal file
|
|
@ -0,0 +1,796 @@
|
|||
//! Message digest (hash) computation support.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! Calculate a hash in one go:
|
||||
//!
|
||||
//! ```
|
||||
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
//! 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(MessageDigest::md5(), data)?;
|
||||
//! assert_eq!(&*res, spec);
|
||||
//! # Ok(()) }
|
||||
//! ```
|
||||
//!
|
||||
//! Supply the input in chunks:
|
||||
//!
|
||||
//! ```
|
||||
//! use openssl::hash::{Hasher, MessageDigest};
|
||||
//!
|
||||
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
//! let mut hasher = Hasher::new(MessageDigest::sha256())?;
|
||||
//! hasher.update(b"test")?;
|
||||
//! hasher.update(b"this")?;
|
||||
//! let digest: &[u8] = &hasher.finish()?;
|
||||
//!
|
||||
//! let expected = hex::decode("9740e652ab5b4acd997a7cca13d6696702ccb2d441cca59fc6e285127f28cfe6")?;
|
||||
//! assert_eq!(digest, expected);
|
||||
//! # Ok(()) }
|
||||
//! ```
|
||||
use cfg_if::cfg_if;
|
||||
use std::ffi::CString;
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::ptr;
|
||||
|
||||
use crate::error::ErrorStack;
|
||||
use crate::nid::Nid;
|
||||
use crate::{cvt, cvt_p};
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl110, boringssl, libressl382))] {
|
||||
use ffi::{EVP_MD_CTX_free, EVP_MD_CTX_new};
|
||||
} else {
|
||||
use ffi::{EVP_MD_CTX_create as EVP_MD_CTX_new, EVP_MD_CTX_destroy as EVP_MD_CTX_free};
|
||||
}
|
||||
}
|
||||
|
||||
/// A message digest algorithm.
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub struct MessageDigest(*const ffi::EVP_MD);
|
||||
|
||||
impl MessageDigest {
|
||||
/// Creates a `MessageDigest` from a raw OpenSSL pointer.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The caller must ensure the pointer is valid.
|
||||
pub unsafe fn from_ptr(x: *const ffi::EVP_MD) -> Self {
|
||||
MessageDigest(x)
|
||||
}
|
||||
|
||||
/// Returns the `MessageDigest` corresponding to an `Nid`.
|
||||
#[corresponds(EVP_get_digestbynid)]
|
||||
pub fn from_nid(type_: Nid) -> Option<MessageDigest> {
|
||||
ffi::init();
|
||||
unsafe {
|
||||
let ptr = ffi::EVP_get_digestbynid(type_.as_raw());
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(MessageDigest(ptr))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the `MessageDigest` corresponding to an algorithm name.
|
||||
#[corresponds(EVP_get_digestbyname)]
|
||||
pub fn from_name(name: &str) -> Option<MessageDigest> {
|
||||
ffi::init();
|
||||
let name = CString::new(name).ok()?;
|
||||
unsafe {
|
||||
let ptr = ffi::EVP_get_digestbyname(name.as_ptr());
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(MessageDigest(ptr))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(boringssl))]
|
||||
pub fn null() -> MessageDigest {
|
||||
unsafe { MessageDigest(ffi::EVP_md_null()) }
|
||||
}
|
||||
|
||||
pub fn md5() -> MessageDigest {
|
||||
unsafe { MessageDigest(ffi::EVP_md5()) }
|
||||
}
|
||||
|
||||
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()) }
|
||||
}
|
||||
|
||||
#[cfg(any(ossl111, libressl380))]
|
||||
pub fn sha3_224() -> MessageDigest {
|
||||
unsafe { MessageDigest(ffi::EVP_sha3_224()) }
|
||||
}
|
||||
|
||||
#[cfg(any(ossl111, libressl380))]
|
||||
pub fn sha3_256() -> MessageDigest {
|
||||
unsafe { MessageDigest(ffi::EVP_sha3_256()) }
|
||||
}
|
||||
|
||||
#[cfg(any(ossl111, libressl380))]
|
||||
pub fn sha3_384() -> MessageDigest {
|
||||
unsafe { MessageDigest(ffi::EVP_sha3_384()) }
|
||||
}
|
||||
|
||||
#[cfg(any(ossl111, libressl380))]
|
||||
pub fn sha3_512() -> MessageDigest {
|
||||
unsafe { MessageDigest(ffi::EVP_sha3_512()) }
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
pub fn shake_128() -> MessageDigest {
|
||||
unsafe { MessageDigest(ffi::EVP_shake128()) }
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
pub fn shake_256() -> MessageDigest {
|
||||
unsafe { MessageDigest(ffi::EVP_shake256()) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_RMD160"))]
|
||||
pub fn ripemd160() -> MessageDigest {
|
||||
unsafe { MessageDigest(ffi::EVP_ripemd160()) }
|
||||
}
|
||||
|
||||
#[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM3")))]
|
||||
pub fn sm3() -> MessageDigest {
|
||||
unsafe { MessageDigest(ffi::EVP_sm3()) }
|
||||
}
|
||||
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub fn as_ptr(&self) -> *const ffi::EVP_MD {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// The block size of the digest in bytes.
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub fn block_size(&self) -> usize {
|
||||
unsafe { ffi::EVP_MD_block_size(self.0) as usize }
|
||||
}
|
||||
|
||||
/// The size of the digest in bytes.
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub fn size(&self) -> usize {
|
||||
unsafe { ffi::EVP_MD_size(self.0) as usize }
|
||||
}
|
||||
|
||||
/// The name of the digest.
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub fn type_(&self) -> Nid {
|
||||
Nid::from_raw(unsafe { ffi::EVP_MD_type(self.0) })
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Sync for MessageDigest {}
|
||||
unsafe impl Send for MessageDigest {}
|
||||
|
||||
#[derive(PartialEq, Copy, Clone)]
|
||||
enum State {
|
||||
Reset,
|
||||
Updated,
|
||||
Finalized,
|
||||
}
|
||||
|
||||
use self::State::*;
|
||||
|
||||
/// Provides message digest (hash) computation.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use openssl::hash::{Hasher, MessageDigest};
|
||||
///
|
||||
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// 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(MessageDigest::md5())?;
|
||||
/// h.update(data[0])?;
|
||||
/// h.update(data[1])?;
|
||||
/// let res = h.finish()?;
|
||||
/// assert_eq!(&*res, spec);
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
///
|
||||
/// # Warning
|
||||
///
|
||||
/// Don't actually use MD5 and SHA-1 hashes, they're not secure anymore.
|
||||
///
|
||||
/// Don't ever hash passwords, use the functions in the `pkcs5` module or bcrypt/scrypt instead.
|
||||
///
|
||||
/// For extendable output functions (XOFs, i.e. SHAKE128/SHAKE256),
|
||||
/// you must use [`Hasher::finish_xof`] instead of [`Hasher::finish`]
|
||||
/// and provide a `buf` to store the hash. The hash will be as long as
|
||||
/// the `buf`.
|
||||
pub struct Hasher {
|
||||
ctx: *mut ffi::EVP_MD_CTX,
|
||||
md: *const ffi::EVP_MD,
|
||||
type_: MessageDigest,
|
||||
state: State,
|
||||
}
|
||||
|
||||
unsafe impl Sync for Hasher {}
|
||||
unsafe impl Send for Hasher {}
|
||||
|
||||
impl Hasher {
|
||||
/// Creates a new `Hasher` with the specified hash type.
|
||||
pub fn new(ty: MessageDigest) -> Result<Hasher, ErrorStack> {
|
||||
ffi::init();
|
||||
|
||||
let ctx = unsafe { cvt_p(EVP_MD_CTX_new())? };
|
||||
|
||||
let mut h = Hasher {
|
||||
ctx,
|
||||
md: ty.as_ptr(),
|
||||
type_: ty,
|
||||
state: Finalized,
|
||||
};
|
||||
h.init()?;
|
||||
Ok(h)
|
||||
}
|
||||
|
||||
fn init(&mut self) -> Result<(), ErrorStack> {
|
||||
match self.state {
|
||||
Reset => return Ok(()),
|
||||
Updated => {
|
||||
self.finish()?;
|
||||
}
|
||||
Finalized => (),
|
||||
}
|
||||
unsafe {
|
||||
cvt(ffi::EVP_DigestInit_ex(self.ctx, self.md, ptr::null_mut()))?;
|
||||
}
|
||||
self.state = Reset;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Feeds data into the hasher.
|
||||
pub fn update(&mut self, data: &[u8]) -> Result<(), ErrorStack> {
|
||||
if self.state == Finalized {
|
||||
self.init()?;
|
||||
}
|
||||
unsafe {
|
||||
cvt(ffi::EVP_DigestUpdate(
|
||||
self.ctx,
|
||||
data.as_ptr() as *mut _,
|
||||
data.len(),
|
||||
))?;
|
||||
}
|
||||
self.state = Updated;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns the hash of the data written and resets the non-XOF hasher.
|
||||
pub fn finish(&mut self) -> Result<DigestBytes, ErrorStack> {
|
||||
if self.state == Finalized {
|
||||
self.init()?;
|
||||
}
|
||||
unsafe {
|
||||
#[cfg(not(boringssl))]
|
||||
let mut len = ffi::EVP_MAX_MD_SIZE;
|
||||
#[cfg(boringssl)]
|
||||
let mut len = ffi::EVP_MAX_MD_SIZE as u32;
|
||||
let mut buf = [0; ffi::EVP_MAX_MD_SIZE as usize];
|
||||
cvt(ffi::EVP_DigestFinal_ex(
|
||||
self.ctx,
|
||||
buf.as_mut_ptr(),
|
||||
&mut len,
|
||||
))?;
|
||||
self.state = Finalized;
|
||||
Ok(DigestBytes {
|
||||
buf,
|
||||
len: len as usize,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Writes the hash of the data into the supplied buf and resets the XOF hasher.
|
||||
/// The hash will be as long as the buf.
|
||||
#[cfg(ossl111)]
|
||||
pub fn finish_xof(&mut self, buf: &mut [u8]) -> Result<(), ErrorStack> {
|
||||
if self.state == Finalized {
|
||||
self.init()?;
|
||||
}
|
||||
unsafe {
|
||||
cvt(ffi::EVP_DigestFinalXOF(
|
||||
self.ctx,
|
||||
buf.as_mut_ptr(),
|
||||
buf.len(),
|
||||
))?;
|
||||
self.state = Finalized;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for Hasher {
|
||||
#[inline]
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.update(buf)?;
|
||||
Ok(buf.len())
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Hasher {
|
||||
fn clone(&self) -> Hasher {
|
||||
let ctx = unsafe {
|
||||
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);
|
||||
ctx
|
||||
};
|
||||
Hasher {
|
||||
ctx,
|
||||
md: self.md,
|
||||
type_: self.type_,
|
||||
state: self.state,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Hasher {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
if self.state != Finalized {
|
||||
drop(self.finish());
|
||||
}
|
||||
EVP_MD_CTX_free(self.ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The resulting bytes of a digest.
|
||||
///
|
||||
/// This type derefs to a byte slice - it exists to avoid allocating memory to
|
||||
/// store the digest data.
|
||||
#[derive(Copy)]
|
||||
pub struct DigestBytes {
|
||||
pub(crate) buf: [u8; ffi::EVP_MAX_MD_SIZE as usize],
|
||||
pub(crate) len: usize,
|
||||
}
|
||||
|
||||
impl Clone for DigestBytes {
|
||||
#[inline]
|
||||
fn clone(&self) -> DigestBytes {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for DigestBytes {
|
||||
type Target = [u8];
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &[u8] {
|
||||
&self.buf[..self.len]
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for DigestBytes {
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut [u8] {
|
||||
&mut self.buf[..self.len]
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for DigestBytes {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.deref()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for DigestBytes {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Debug::fmt(&**self, fmt)
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the hash of the `data` with the non-XOF hasher `t`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// 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(MessageDigest::md5(), data)?;
|
||||
/// assert_eq!(&*res, spec);
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
pub fn hash(t: MessageDigest, data: &[u8]) -> Result<DigestBytes, ErrorStack> {
|
||||
let mut h = Hasher::new(t)?;
|
||||
h.update(data)?;
|
||||
h.finish()
|
||||
}
|
||||
|
||||
/// Computes the hash of the `data` with the XOF hasher `t` and stores it in `buf`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use openssl::hash::{hash_xof, MessageDigest};
|
||||
///
|
||||
/// let data = b"\x41\x6c\x6c\x20\x79\x6f\x75\x72\x20\x62\x61\x73\x65\x20\x61\x72\x65\x20\x62\x65\x6c\x6f\x6e\x67\x20\x74\x6f\x20\x75\x73";
|
||||
/// let spec = b"\x49\xd0\x69\x7f\xf5\x08\x11\x1d\x8b\x84\xf1\x5e\x46\xda\xf1\x35";
|
||||
/// let mut buf = vec![0; 16];
|
||||
/// hash_xof(MessageDigest::shake_128(), data, buf.as_mut_slice()).unwrap();
|
||||
/// assert_eq!(buf, spec);
|
||||
/// ```
|
||||
///
|
||||
#[cfg(ossl111)]
|
||||
pub fn hash_xof(t: MessageDigest, data: &[u8], buf: &mut [u8]) -> Result<(), ErrorStack> {
|
||||
let mut h = Hasher::new(t)?;
|
||||
h.update(data)?;
|
||||
h.finish_xof(buf)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use hex::{self, FromHex};
|
||||
use std::io::prelude::*;
|
||||
|
||||
use super::*;
|
||||
|
||||
fn hash_test(hashtype: MessageDigest, hashtest: &(&str, &str)) {
|
||||
let res = hash(hashtype, &Vec::from_hex(hashtest.0).unwrap()).unwrap();
|
||||
assert_eq!(hex::encode(res), hashtest.1);
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
fn hash_xof_test(hashtype: MessageDigest, hashtest: &(&str, &str)) {
|
||||
let expected = Vec::from_hex(hashtest.1).unwrap();
|
||||
let mut buf = vec![0; expected.len()];
|
||||
hash_xof(
|
||||
hashtype,
|
||||
&Vec::from_hex(hashtest.0).unwrap(),
|
||||
buf.as_mut_slice(),
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(buf, expected);
|
||||
}
|
||||
|
||||
fn hash_recycle_test(h: &mut Hasher, hashtest: &(&str, &str)) {
|
||||
h.write_all(&Vec::from_hex(hashtest.0).unwrap()).unwrap();
|
||||
let res = h.finish().unwrap();
|
||||
assert_eq!(hex::encode(res), hashtest.1);
|
||||
}
|
||||
|
||||
// Test vectors from http://www.nsrl.nist.gov/testdata/
|
||||
const MD5_TESTS: [(&str, &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(MessageDigest::md5(), test);
|
||||
}
|
||||
|
||||
assert_eq!(MessageDigest::md5().block_size(), 64);
|
||||
assert_eq!(MessageDigest::md5().size(), 16);
|
||||
assert_eq!(MessageDigest::md5().type_().as_raw(), Nid::MD5.as_raw());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_md5_recycle() {
|
||||
let mut h = Hasher::new(MessageDigest::md5()).unwrap();
|
||||
for test in MD5_TESTS.iter() {
|
||||
hash_recycle_test(&mut h, test);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_finish_twice() {
|
||||
let mut h = Hasher::new(MessageDigest::md5()).unwrap();
|
||||
h.write_all(&Vec::from_hex(MD5_TESTS[6].0).unwrap())
|
||||
.unwrap();
|
||||
h.finish().unwrap();
|
||||
let res = h.finish().unwrap();
|
||||
let null = hash(MessageDigest::md5(), &[]).unwrap();
|
||||
assert_eq!(&*res, &*null);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::redundant_clone)]
|
||||
fn test_clone() {
|
||||
let i = 7;
|
||||
let inp = Vec::from_hex(MD5_TESTS[i].0).unwrap();
|
||||
assert!(inp.len() > 2);
|
||||
let p = inp.len() / 2;
|
||||
let h0 = Hasher::new(MessageDigest::md5()).unwrap();
|
||||
|
||||
println!("Clone a new hasher");
|
||||
let mut h1 = h0.clone();
|
||||
h1.write_all(&inp[..p]).unwrap();
|
||||
{
|
||||
println!("Clone an updated hasher");
|
||||
let mut h2 = h1.clone();
|
||||
h2.write_all(&inp[p..]).unwrap();
|
||||
let res = h2.finish().unwrap();
|
||||
assert_eq!(hex::encode(res), MD5_TESTS[i].1);
|
||||
}
|
||||
h1.write_all(&inp[p..]).unwrap();
|
||||
let res = h1.finish().unwrap();
|
||||
assert_eq!(hex::encode(res), MD5_TESTS[i].1);
|
||||
|
||||
println!("Clone a finished hasher");
|
||||
let mut h3 = h1.clone();
|
||||
h3.write_all(&Vec::from_hex(MD5_TESTS[i + 1].0).unwrap())
|
||||
.unwrap();
|
||||
let res = h3.finish().unwrap();
|
||||
assert_eq!(hex::encode(res), MD5_TESTS[i + 1].1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sha1() {
|
||||
let tests = [("616263", "a9993e364706816aba3e25717850c26c9cd0d89d")];
|
||||
|
||||
for test in tests.iter() {
|
||||
hash_test(MessageDigest::sha1(), test);
|
||||
}
|
||||
|
||||
assert_eq!(MessageDigest::sha1().block_size(), 64);
|
||||
assert_eq!(MessageDigest::sha1().size(), 20);
|
||||
assert_eq!(MessageDigest::sha1().type_().as_raw(), Nid::SHA1.as_raw());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sha256() {
|
||||
let tests = [(
|
||||
"616263",
|
||||
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
|
||||
)];
|
||||
|
||||
for test in tests.iter() {
|
||||
hash_test(MessageDigest::sha256(), test);
|
||||
}
|
||||
|
||||
assert_eq!(MessageDigest::sha256().block_size(), 64);
|
||||
assert_eq!(MessageDigest::sha256().size(), 32);
|
||||
assert_eq!(
|
||||
MessageDigest::sha256().type_().as_raw(),
|
||||
Nid::SHA256.as_raw()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sha512() {
|
||||
let tests = [(
|
||||
"737465766566696e647365766572797468696e67",
|
||||
"ba61d1f1af0f2dd80729f6cc900f19c0966bd38ba5c75e4471ef11b771dfe7551afab7fcbd300fdc4418f2\
|
||||
b07a028fcd99e7b6446a566f2d9bcd7c604a1ea801",
|
||||
)];
|
||||
|
||||
for test in tests.iter() {
|
||||
hash_test(MessageDigest::sha512(), test);
|
||||
}
|
||||
|
||||
assert_eq!(MessageDigest::sha512().block_size(), 128);
|
||||
assert_eq!(MessageDigest::sha512().size(), 64);
|
||||
assert_eq!(
|
||||
MessageDigest::sha512().type_().as_raw(),
|
||||
Nid::SHA512.as_raw()
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(any(ossl111, libressl380))]
|
||||
#[test]
|
||||
fn test_sha3_224() {
|
||||
let tests = [(
|
||||
"416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
|
||||
"1de092dd9fbcbbf450f26264f4778abd48af851f2832924554c56913",
|
||||
)];
|
||||
|
||||
for test in tests.iter() {
|
||||
hash_test(MessageDigest::sha3_224(), test);
|
||||
}
|
||||
|
||||
assert_eq!(MessageDigest::sha3_224().block_size(), 144);
|
||||
assert_eq!(MessageDigest::sha3_224().size(), 28);
|
||||
assert_eq!(
|
||||
MessageDigest::sha3_224().type_().as_raw(),
|
||||
Nid::SHA3_224.as_raw()
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(any(ossl111, libressl380))]
|
||||
#[test]
|
||||
fn test_sha3_256() {
|
||||
let tests = [(
|
||||
"416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
|
||||
"b38e38f08bc1c0091ed4b5f060fe13e86aa4179578513ad11a6e3abba0062f61",
|
||||
)];
|
||||
|
||||
for test in tests.iter() {
|
||||
hash_test(MessageDigest::sha3_256(), test);
|
||||
}
|
||||
|
||||
assert_eq!(MessageDigest::sha3_256().block_size(), 136);
|
||||
assert_eq!(MessageDigest::sha3_256().size(), 32);
|
||||
assert_eq!(
|
||||
MessageDigest::sha3_256().type_().as_raw(),
|
||||
Nid::SHA3_256.as_raw()
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(any(ossl111, libressl380))]
|
||||
#[test]
|
||||
fn test_sha3_384() {
|
||||
let tests = [("416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
|
||||
"966ee786ab3482dd811bf7c8fa8db79aa1f52f6c3c369942ef14240ebd857c6ff626ec35d9e131ff64d328\
|
||||
ef2008ff16"
|
||||
)];
|
||||
|
||||
for test in tests.iter() {
|
||||
hash_test(MessageDigest::sha3_384(), test);
|
||||
}
|
||||
|
||||
assert_eq!(MessageDigest::sha3_384().block_size(), 104);
|
||||
assert_eq!(MessageDigest::sha3_384().size(), 48);
|
||||
assert_eq!(
|
||||
MessageDigest::sha3_384().type_().as_raw(),
|
||||
Nid::SHA3_384.as_raw()
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(any(ossl111, libressl380))]
|
||||
#[test]
|
||||
fn test_sha3_512() {
|
||||
let tests = [("416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
|
||||
"c072288ef728cd53a029c47687960b9225893532f42b923156e37020bdc1eda753aafbf30af859d4f4c3a1\
|
||||
807caee3a79f8eb02dcd61589fbbdf5f40c8787a72"
|
||||
)];
|
||||
|
||||
for test in tests.iter() {
|
||||
hash_test(MessageDigest::sha3_512(), test);
|
||||
}
|
||||
|
||||
assert_eq!(MessageDigest::sha3_512().block_size(), 72);
|
||||
assert_eq!(MessageDigest::sha3_512().size(), 64);
|
||||
assert_eq!(
|
||||
MessageDigest::sha3_512().type_().as_raw(),
|
||||
Nid::SHA3_512.as_raw()
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
#[test]
|
||||
fn test_shake_128() {
|
||||
let tests = [(
|
||||
"416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
|
||||
"49d0697ff508111d8b84f15e46daf135",
|
||||
)];
|
||||
|
||||
for test in tests.iter() {
|
||||
hash_xof_test(MessageDigest::shake_128(), test);
|
||||
}
|
||||
|
||||
assert_eq!(MessageDigest::shake_128().block_size(), 168);
|
||||
assert_eq!(MessageDigest::shake_128().size(), 16);
|
||||
assert_eq!(
|
||||
MessageDigest::shake_128().type_().as_raw(),
|
||||
Nid::SHAKE128.as_raw()
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
#[test]
|
||||
fn test_shake_256() {
|
||||
let tests = [(
|
||||
"416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
|
||||
"4e2dfdaa75d1e049d0eaeffe28e76b17cea47b650fb8826fe48b94664326a697",
|
||||
)];
|
||||
|
||||
for test in tests.iter() {
|
||||
hash_xof_test(MessageDigest::shake_256(), test);
|
||||
}
|
||||
|
||||
assert_eq!(MessageDigest::shake_256().block_size(), 136);
|
||||
assert_eq!(MessageDigest::shake_256().size(), 32);
|
||||
assert_eq!(
|
||||
MessageDigest::shake_256().type_().as_raw(),
|
||||
Nid::SHAKE256.as_raw()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_RMD160"))]
|
||||
#[cfg_attr(ossl300, ignore)]
|
||||
fn test_ripemd160() {
|
||||
#[cfg(ossl300)]
|
||||
let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap();
|
||||
|
||||
let tests = [("616263", "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc")];
|
||||
|
||||
for test in tests.iter() {
|
||||
hash_test(MessageDigest::ripemd160(), test);
|
||||
}
|
||||
|
||||
assert_eq!(MessageDigest::ripemd160().block_size(), 64);
|
||||
assert_eq!(MessageDigest::ripemd160().size(), 20);
|
||||
assert_eq!(
|
||||
MessageDigest::ripemd160().type_().as_raw(),
|
||||
Nid::RIPEMD160.as_raw()
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM3")))]
|
||||
#[test]
|
||||
fn test_sm3() {
|
||||
let tests = [(
|
||||
"616263",
|
||||
"66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0",
|
||||
)];
|
||||
|
||||
for test in tests.iter() {
|
||||
hash_test(MessageDigest::sm3(), test);
|
||||
}
|
||||
|
||||
assert_eq!(MessageDigest::sm3().block_size(), 64);
|
||||
assert_eq!(MessageDigest::sm3().size(), 32);
|
||||
assert_eq!(MessageDigest::sm3().type_().as_raw(), Nid::SM3.as_raw());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_nid() {
|
||||
assert_eq!(
|
||||
MessageDigest::from_nid(Nid::SHA256).unwrap().as_ptr(),
|
||||
MessageDigest::sha256().as_ptr()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_name() {
|
||||
assert_eq!(
|
||||
MessageDigest::from_name("SHA256").unwrap().as_ptr(),
|
||||
MessageDigest::sha256().as_ptr()
|
||||
)
|
||||
}
|
||||
}
|
||||
176
vendor/openssl/src/kdf.rs
vendored
Normal file
176
vendor/openssl/src/kdf.rs
vendored
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
#[cfg(ossl320)]
|
||||
struct EvpKdf(*mut ffi::EVP_KDF);
|
||||
|
||||
#[cfg(ossl320)]
|
||||
impl Drop for EvpKdf {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
ffi::EVP_KDF_free(self.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl320)]
|
||||
struct EvpKdfCtx(*mut ffi::EVP_KDF_CTX);
|
||||
|
||||
#[cfg(ossl320)]
|
||||
impl Drop for EvpKdfCtx {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
ffi::EVP_KDF_CTX_free(self.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(all(ossl320, not(osslconf = "OPENSSL_NO_ARGON2")))] {
|
||||
use std::cmp;
|
||||
use std::ffi::c_void;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::ptr;
|
||||
use foreign_types::ForeignTypeRef;
|
||||
use libc::c_char;
|
||||
use crate::{cvt, cvt_p};
|
||||
use crate::lib_ctx::LibCtxRef;
|
||||
use crate::error::ErrorStack;
|
||||
|
||||
/// Derives a key using the argon2id algorithm.
|
||||
///
|
||||
/// To use multiple cores to process the lanes in parallel you must
|
||||
/// set a global max thread count using `OSSL_set_max_threads`. On
|
||||
/// builds with no threads all lanes will be processed sequentially.
|
||||
///
|
||||
/// Requires OpenSSL 3.2.0 or newer.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn argon2id(
|
||||
ctx: Option<&LibCtxRef>,
|
||||
pass: &[u8],
|
||||
salt: &[u8],
|
||||
ad: Option<&[u8]>,
|
||||
secret: Option<&[u8]>,
|
||||
mut iter: u32,
|
||||
mut lanes: u32,
|
||||
mut memcost: u32,
|
||||
out: &mut [u8],
|
||||
) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
ffi::init();
|
||||
let libctx = ctx.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr);
|
||||
|
||||
let max_threads = ffi::OSSL_get_max_threads(libctx);
|
||||
let mut threads = 1;
|
||||
// If max_threads is 0, then this isn't a threaded build.
|
||||
// If max_threads is > u32::MAX we need to clamp since
|
||||
// argon2id's threads parameter is a u32.
|
||||
if max_threads > 0 {
|
||||
threads = cmp::min(lanes, cmp::min(max_threads, u32::MAX as u64) as u32);
|
||||
}
|
||||
let mut params: [ffi::OSSL_PARAM; 10] =
|
||||
core::array::from_fn(|_| MaybeUninit::<ffi::OSSL_PARAM>::zeroed().assume_init());
|
||||
let mut idx = 0;
|
||||
params[idx] = ffi::OSSL_PARAM_construct_octet_string(
|
||||
b"pass\0".as_ptr() as *const c_char,
|
||||
pass.as_ptr() as *mut c_void,
|
||||
pass.len(),
|
||||
);
|
||||
idx += 1;
|
||||
params[idx] = ffi::OSSL_PARAM_construct_octet_string(
|
||||
b"salt\0".as_ptr() as *const c_char,
|
||||
salt.as_ptr() as *mut c_void,
|
||||
salt.len(),
|
||||
);
|
||||
idx += 1;
|
||||
params[idx] =
|
||||
ffi::OSSL_PARAM_construct_uint(b"threads\0".as_ptr() as *const c_char, &mut threads);
|
||||
idx += 1;
|
||||
params[idx] =
|
||||
ffi::OSSL_PARAM_construct_uint(b"lanes\0".as_ptr() as *const c_char, &mut lanes);
|
||||
idx += 1;
|
||||
params[idx] =
|
||||
ffi::OSSL_PARAM_construct_uint(b"memcost\0".as_ptr() as *const c_char, &mut memcost);
|
||||
idx += 1;
|
||||
params[idx] =
|
||||
ffi::OSSL_PARAM_construct_uint(b"iter\0".as_ptr() as *const c_char, &mut iter);
|
||||
idx += 1;
|
||||
let mut size = out.len() as u32;
|
||||
params[idx] =
|
||||
ffi::OSSL_PARAM_construct_uint(b"size\0".as_ptr() as *const c_char, &mut size);
|
||||
idx += 1;
|
||||
if let Some(ad) = ad {
|
||||
params[idx] = ffi::OSSL_PARAM_construct_octet_string(
|
||||
b"ad\0".as_ptr() as *const c_char,
|
||||
ad.as_ptr() as *mut c_void,
|
||||
ad.len(),
|
||||
);
|
||||
idx += 1;
|
||||
}
|
||||
if let Some(secret) = secret {
|
||||
params[idx] = ffi::OSSL_PARAM_construct_octet_string(
|
||||
b"secret\0".as_ptr() as *const c_char,
|
||||
secret.as_ptr() as *mut c_void,
|
||||
secret.len(),
|
||||
);
|
||||
idx += 1;
|
||||
}
|
||||
params[idx] = ffi::OSSL_PARAM_construct_end();
|
||||
|
||||
let argon2 = EvpKdf(cvt_p(ffi::EVP_KDF_fetch(
|
||||
libctx,
|
||||
b"ARGON2ID\0".as_ptr() as *const c_char,
|
||||
ptr::null(),
|
||||
))?);
|
||||
let ctx = EvpKdfCtx(cvt_p(ffi::EVP_KDF_CTX_new(argon2.0))?);
|
||||
cvt(ffi::EVP_KDF_derive(
|
||||
ctx.0,
|
||||
out.as_mut_ptr(),
|
||||
out.len(),
|
||||
params.as_ptr(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
#[cfg(all(ossl320, not(osslconf = "OPENSSL_NO_ARGON2")))]
|
||||
fn argon2id() {
|
||||
// RFC 9106 test vector for argon2id
|
||||
let pass = hex::decode("0101010101010101010101010101010101010101010101010101010101010101")
|
||||
.unwrap();
|
||||
let salt = hex::decode("02020202020202020202020202020202").unwrap();
|
||||
let secret = hex::decode("0303030303030303").unwrap();
|
||||
let ad = hex::decode("040404040404040404040404").unwrap();
|
||||
let expected = "0d640df58d78766c08c037a34a8b53c9d01ef0452d75b65eb52520e96b01e659";
|
||||
|
||||
let mut actual = [0u8; 32];
|
||||
super::argon2id(
|
||||
None,
|
||||
&pass,
|
||||
&salt,
|
||||
Some(&ad),
|
||||
Some(&secret),
|
||||
3,
|
||||
4,
|
||||
32,
|
||||
&mut actual,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(hex::encode(&actual[..]), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(ossl320, not(osslconf = "OPENSSL_NO_ARGON2")))]
|
||||
fn argon2id_no_ad_secret() {
|
||||
// Test vector from OpenSSL
|
||||
let pass = b"";
|
||||
let salt = hex::decode("02020202020202020202020202020202").unwrap();
|
||||
let expected = "0a34f1abde67086c82e785eaf17c68382259a264f4e61b91cd2763cb75ac189a";
|
||||
|
||||
let mut actual = [0u8; 32];
|
||||
super::argon2id(None, pass, &salt, None, None, 3, 4, 32, &mut actual).unwrap();
|
||||
assert_eq!(hex::encode(&actual[..]), expected);
|
||||
}
|
||||
}
|
||||
257
vendor/openssl/src/lib.rs
vendored
Normal file
257
vendor/openssl/src/lib.rs
vendored
Normal file
|
|
@ -0,0 +1,257 @@
|
|||
//! Bindings to OpenSSL
|
||||
//!
|
||||
//! This crate provides a safe interface to the popular OpenSSL cryptography library. OpenSSL versions 1.0.1 through
|
||||
//! 3.x.x and LibreSSL versions 2.5 through 3.7.x are supported.
|
||||
//!
|
||||
//! # Building
|
||||
//!
|
||||
//! Both OpenSSL libraries and headers are required to build this crate. There are multiple options available to locate
|
||||
//! OpenSSL.
|
||||
//!
|
||||
//! ## Vendored
|
||||
//!
|
||||
//! If the `vendored` Cargo feature is enabled, the `openssl-src` crate will be used to compile and statically link to
|
||||
//! a copy of OpenSSL. The build process requires a C compiler, perl (and perl-core), and make. The OpenSSL version will generally track
|
||||
//! the newest OpenSSL release, and changes to the version are *not* considered breaking changes.
|
||||
//!
|
||||
//! ```toml
|
||||
//! [dependencies]
|
||||
//! openssl = { version = "0.10", features = ["vendored"] }
|
||||
//! ```
|
||||
//!
|
||||
//! The vendored copy will be configured to automatically find a configuration and root certificates at `/usr/local/ssl`.
|
||||
//! This path can be overridden with an environment variable (see the manual section below).
|
||||
//! Alternatively, the `openssl-probe` crate can be used to find root certificates at runtime.
|
||||
//!
|
||||
//! ## Automatic
|
||||
//!
|
||||
//! The `openssl-sys` crate will automatically detect OpenSSL installations via Homebrew on macOS and vcpkg on Windows.
|
||||
//! Additionally, it will use `pkg-config` on Unix-like systems to find the system installation.
|
||||
//!
|
||||
//! ```not_rust
|
||||
//! # macOS (Homebrew)
|
||||
//! $ brew install openssl@3
|
||||
//!
|
||||
//! # macOS (MacPorts)
|
||||
//! $ sudo port install openssl
|
||||
//!
|
||||
//! # macOS (pkgsrc)
|
||||
//! $ sudo pkgin install openssl
|
||||
//!
|
||||
//! # Arch Linux
|
||||
//! $ sudo pacman -S pkgconf openssl
|
||||
//!
|
||||
//! # Debian and Ubuntu
|
||||
//! $ sudo apt-get install pkg-config libssl-dev
|
||||
//!
|
||||
//! # Fedora
|
||||
//! $ sudo dnf install pkgconf perl-FindBin perl-IPC-Cmd openssl-devel
|
||||
//!
|
||||
//! # Alpine Linux
|
||||
//! $ apk add pkgconf openssl-dev
|
||||
//!
|
||||
//! # openSUSE
|
||||
//! $ sudo zypper in libopenssl-devel
|
||||
//! ```
|
||||
//!
|
||||
//! ## Manual
|
||||
//!
|
||||
//! A set of environment variables can be used to point `openssl-sys` towards an OpenSSL installation. They will
|
||||
//! override the automatic detection logic.
|
||||
//!
|
||||
//! * `OPENSSL_DIR` - If specified, the directory of an OpenSSL installation. The directory should contain `lib` and
|
||||
//! `include` subdirectories containing the libraries and headers respectively.
|
||||
//! * `OPENSSL_LIB_DIR` and `OPENSSL_INCLUDE_DIR` - If specified, the directories containing the OpenSSL libraries and
|
||||
//! headers respectively. This can be used if the OpenSSL installation is split in a nonstandard directory layout.
|
||||
//! * `OPENSSL_STATIC` - If set, the crate will statically link to OpenSSL rather than dynamically link.
|
||||
//! * `OPENSSL_LIBS` - If set, a `:`-separated list of library names to link to (e.g. `ssl:crypto`). This can be used
|
||||
//! if nonstandard library names were used for whatever reason.
|
||||
//! * `OPENSSL_NO_VENDOR` - If set, always find OpenSSL in the system, even if the `vendored` feature is enabled.
|
||||
//!
|
||||
//! If the `vendored` Cargo feature is enabled, the following environment variable can also be used to further configure
|
||||
//! the OpenSSL build.
|
||||
//!
|
||||
//! * `OPENSSL_CONFIG_DIR` - If set, the copy of OpenSSL built by the `openssl-src` crate will be configured to look for
|
||||
//! configuration files and root certificates in this directory.
|
||||
//!
|
||||
//! Additionally, these variables can be prefixed with the upper-cased target architecture (e.g.
|
||||
//! `X86_64_UNKNOWN_LINUX_GNU_OPENSSL_DIR`), which can be useful when cross compiling.
|
||||
//!
|
||||
//! # Feature Detection
|
||||
//!
|
||||
//! APIs have been added to and removed from the various supported OpenSSL versions, and this library exposes the
|
||||
//! functionality available in the version being linked against. This means that methods, constants, and even modules
|
||||
//! will be present when building against one version of OpenSSL but not when building against another! APIs will
|
||||
//! document any version-specific availability restrictions.
|
||||
//!
|
||||
//! A build script can be used to detect the OpenSSL or LibreSSL version at compile time if needed. The `openssl-sys`
|
||||
//! crate propagates the version via the `DEP_OPENSSL_VERSION_NUMBER` and `DEP_OPENSSL_LIBRESSL_VERSION_NUMBER`
|
||||
//! environment variables to build scripts. The version format is a hex-encoding of the OpenSSL release version:
|
||||
//! `0xMNNFFPPS`. For example, version 1.0.2g's encoding is `0x1_00_02_07_0`.
|
||||
//!
|
||||
//! For example, let's say we want to adjust the TLSv1.3 cipher suites used by a client, but also want to compile
|
||||
//! against OpenSSL versions that don't support TLSv1.3:
|
||||
//!
|
||||
//! Cargo.toml:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [dependencies]
|
||||
//! openssl-sys = "0.9"
|
||||
//! openssl = "0.10"
|
||||
//! ```
|
||||
//!
|
||||
//! build.rs:
|
||||
//!
|
||||
//! ```
|
||||
//! use std::env;
|
||||
//!
|
||||
//! fn main() {
|
||||
//! if let Ok(v) = env::var("DEP_OPENSSL_VERSION_NUMBER") {
|
||||
//! let version = u64::from_str_radix(&v, 16).unwrap();
|
||||
//!
|
||||
//! if version >= 0x1_01_01_00_0 {
|
||||
//! println!("cargo:rustc-cfg=openssl111");
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! lib.rs:
|
||||
//!
|
||||
//! ```
|
||||
//! use openssl::ssl::{SslConnector, SslMethod};
|
||||
//!
|
||||
//! let mut ctx = SslConnector::builder(SslMethod::tls()).unwrap();
|
||||
//!
|
||||
//! // set_ciphersuites was added in OpenSSL 1.1.1, so we can only call it when linking against that version
|
||||
//! #[cfg(openssl111)]
|
||||
//! ctx.set_ciphersuites("TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256").unwrap();
|
||||
//! ```
|
||||
#![doc(html_root_url = "https://docs.rs/openssl/0.10")]
|
||||
#![warn(rust_2018_idioms)]
|
||||
#![allow(clippy::uninlined_format_args, clippy::needless_doctest_main)]
|
||||
|
||||
#[doc(inline)]
|
||||
pub use ffi::init;
|
||||
|
||||
use libc::c_int;
|
||||
#[cfg(ossl300)]
|
||||
use libc::c_long;
|
||||
|
||||
use crate::error::ErrorStack;
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
mod bio;
|
||||
#[macro_use]
|
||||
mod util;
|
||||
pub mod aes;
|
||||
pub mod asn1;
|
||||
pub mod base64;
|
||||
pub mod bn;
|
||||
pub mod cipher;
|
||||
pub mod cipher_ctx;
|
||||
#[cfg(all(not(libressl), not(osslconf = "OPENSSL_NO_CMS")))]
|
||||
pub mod cms;
|
||||
pub mod conf;
|
||||
pub mod derive;
|
||||
pub mod dh;
|
||||
pub mod dsa;
|
||||
pub mod ec;
|
||||
pub mod ecdsa;
|
||||
pub mod encrypt;
|
||||
#[cfg(not(boringssl))]
|
||||
pub mod envelope;
|
||||
pub mod error;
|
||||
pub mod ex_data;
|
||||
#[cfg(not(any(libressl, ossl300)))]
|
||||
pub mod fips;
|
||||
pub mod hash;
|
||||
pub mod kdf;
|
||||
#[cfg(ossl300)]
|
||||
pub mod lib_ctx;
|
||||
pub mod md;
|
||||
pub mod md_ctx;
|
||||
pub mod memcmp;
|
||||
pub mod nid;
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_OCSP"))]
|
||||
pub mod ocsp;
|
||||
pub mod pkcs12;
|
||||
pub mod pkcs5;
|
||||
#[cfg(not(boringssl))]
|
||||
pub mod pkcs7;
|
||||
pub mod pkey;
|
||||
pub mod pkey_ctx;
|
||||
#[cfg(ossl300)]
|
||||
pub mod provider;
|
||||
pub mod rand;
|
||||
pub mod rsa;
|
||||
pub mod sha;
|
||||
pub mod sign;
|
||||
pub mod srtp;
|
||||
pub mod ssl;
|
||||
pub mod stack;
|
||||
pub mod string;
|
||||
pub mod symm;
|
||||
pub mod version;
|
||||
pub mod x509;
|
||||
|
||||
#[cfg(boringssl)]
|
||||
type LenType = libc::size_t;
|
||||
#[cfg(not(boringssl))]
|
||||
type LenType = libc::c_int;
|
||||
|
||||
#[cfg(boringssl)]
|
||||
type SLenType = libc::ssize_t;
|
||||
#[cfg(not(boringssl))]
|
||||
type SLenType = libc::c_int;
|
||||
|
||||
#[inline]
|
||||
fn cvt_p<T>(r: *mut T) -> Result<*mut T, ErrorStack> {
|
||||
if r.is_null() {
|
||||
Err(ErrorStack::get())
|
||||
} else {
|
||||
Ok(r)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn cvt_p_const<T>(r: *const T) -> Result<*const T, ErrorStack> {
|
||||
if r.is_null() {
|
||||
Err(ErrorStack::get())
|
||||
} else {
|
||||
Ok(r)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn cvt(r: c_int) -> Result<c_int, ErrorStack> {
|
||||
if r <= 0 {
|
||||
Err(ErrorStack::get())
|
||||
} else {
|
||||
Ok(r)
|
||||
}
|
||||
}
|
||||
|
||||
// cvt_long is currently only used in functions that require openssl >= 3.0.0,
|
||||
// so this cfg statement is used to avoid "unused function" errors when
|
||||
// compiling with openssl < 3.0.0
|
||||
#[inline]
|
||||
#[cfg(ossl300)]
|
||||
fn cvt_long(r: c_long) -> Result<c_long, ErrorStack> {
|
||||
if r <= 0 {
|
||||
Err(ErrorStack::get())
|
||||
} else {
|
||||
Ok(r)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn cvt_n(r: c_int) -> Result<c_int, ErrorStack> {
|
||||
if r < 0 {
|
||||
Err(ErrorStack::get())
|
||||
} else {
|
||||
Ok(r)
|
||||
}
|
||||
}
|
||||
22
vendor/openssl/src/lib_ctx.rs
vendored
Normal file
22
vendor/openssl/src/lib_ctx.rs
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
use crate::cvt_p;
|
||||
use crate::error::ErrorStack;
|
||||
use foreign_types::ForeignType;
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::OSSL_LIB_CTX;
|
||||
fn drop = ffi::OSSL_LIB_CTX_free;
|
||||
|
||||
pub struct LibCtx;
|
||||
pub struct LibCtxRef;
|
||||
}
|
||||
|
||||
impl LibCtx {
|
||||
#[corresponds(OSSL_LIB_CTX_new)]
|
||||
pub fn new() -> Result<Self, ErrorStack> {
|
||||
unsafe {
|
||||
let ptr = cvt_p(ffi::OSSL_LIB_CTX_new())?;
|
||||
Ok(LibCtx::from_ptr(ptr))
|
||||
}
|
||||
}
|
||||
}
|
||||
270
vendor/openssl/src/macros.rs
vendored
Normal file
270
vendor/openssl/src/macros.rs
vendored
Normal file
|
|
@ -0,0 +1,270 @@
|
|||
macro_rules! private_key_from_pem {
|
||||
($(#[$m:meta])* $n:ident, $(#[$m2:meta])* $n2:ident, $(#[$m3:meta])* $n3:ident, $t:ty, $f:path) => {
|
||||
from_pem!($(#[$m])* $n, $t, $f);
|
||||
|
||||
$(#[$m2])*
|
||||
pub fn $n2(pem: &[u8], passphrase: &[u8]) -> Result<$t, crate::error::ErrorStack> {
|
||||
unsafe {
|
||||
ffi::init();
|
||||
let bio = crate::bio::MemBioSlice::new(pem)?;
|
||||
let passphrase = ::std::ffi::CString::new(passphrase).unwrap();
|
||||
cvt_p($f(bio.as_ptr(),
|
||||
ptr::null_mut(),
|
||||
None,
|
||||
passphrase.as_ptr() as *const _ as *mut _))
|
||||
.map(|p| ::foreign_types::ForeignType::from_ptr(p))
|
||||
}
|
||||
}
|
||||
|
||||
$(#[$m3])*
|
||||
pub fn $n3<F>(pem: &[u8], callback: F) -> Result<$t, crate::error::ErrorStack>
|
||||
where F: FnOnce(&mut [u8]) -> Result<usize, crate::error::ErrorStack>
|
||||
{
|
||||
unsafe {
|
||||
ffi::init();
|
||||
let mut cb = crate::util::CallbackState::new(callback);
|
||||
let bio = crate::bio::MemBioSlice::new(pem)?;
|
||||
cvt_p($f(bio.as_ptr(),
|
||||
ptr::null_mut(),
|
||||
Some(crate::util::invoke_passwd_cb::<F>),
|
||||
&mut cb as *mut _ as *mut _))
|
||||
.map(|p| ::foreign_types::ForeignType::from_ptr(p))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! private_key_to_pem {
|
||||
($(#[$m:meta])* $n:ident, $(#[$m2:meta])* $n2:ident, $f:path) => {
|
||||
$(#[$m])*
|
||||
pub fn $n(&self) -> Result<Vec<u8>, crate::error::ErrorStack> {
|
||||
unsafe {
|
||||
let bio = crate::bio::MemBio::new()?;
|
||||
cvt($f(bio.as_ptr(),
|
||||
self.as_ptr(),
|
||||
ptr::null(),
|
||||
ptr::null_mut(),
|
||||
-1,
|
||||
None,
|
||||
ptr::null_mut()))?;
|
||||
Ok(bio.get_buf().to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
$(#[$m2])*
|
||||
pub fn $n2(
|
||||
&self,
|
||||
cipher: crate::symm::Cipher,
|
||||
passphrase: &[u8]
|
||||
) -> Result<Vec<u8>, crate::error::ErrorStack> {
|
||||
unsafe {
|
||||
let bio = crate::bio::MemBio::new()?;
|
||||
assert!(passphrase.len() <= ::libc::c_int::MAX as usize);
|
||||
cvt($f(bio.as_ptr(),
|
||||
self.as_ptr(),
|
||||
cipher.as_ptr(),
|
||||
passphrase.as_ptr() as *const _ as *mut _,
|
||||
passphrase.len() as ::libc::c_int,
|
||||
None,
|
||||
ptr::null_mut()))?;
|
||||
Ok(bio.get_buf().to_owned())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! to_pem {
|
||||
($(#[$m:meta])* $n:ident, $f:path) => {
|
||||
$(#[$m])*
|
||||
pub fn $n(&self) -> Result<Vec<u8>, crate::error::ErrorStack> {
|
||||
unsafe {
|
||||
let bio = crate::bio::MemBio::new()?;
|
||||
cvt($f(bio.as_ptr(), self.as_ptr()))?;
|
||||
Ok(bio.get_buf().to_owned())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! to_der {
|
||||
($(#[$m:meta])* $n:ident, $f:path) => {
|
||||
$(#[$m])*
|
||||
pub fn $n(&self) -> Result<Vec<u8>, crate::error::ErrorStack> {
|
||||
unsafe {
|
||||
let len = crate::cvt($f(::foreign_types::ForeignTypeRef::as_ptr(self),
|
||||
ptr::null_mut()))?;
|
||||
let mut buf = vec![0; len as usize];
|
||||
crate::cvt($f(::foreign_types::ForeignTypeRef::as_ptr(self),
|
||||
&mut buf.as_mut_ptr()))?;
|
||||
Ok(buf)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! from_der {
|
||||
($(#[$m:meta])* $n:ident, $t:ty, $f:path) => {
|
||||
$(#[$m])*
|
||||
pub fn $n(der: &[u8]) -> Result<$t, crate::error::ErrorStack> {
|
||||
use std::convert::TryInto;
|
||||
unsafe {
|
||||
ffi::init();
|
||||
let len = ::std::cmp::min(der.len(), ::libc::c_long::MAX as usize) as ::libc::c_long;
|
||||
crate::cvt_p($f(::std::ptr::null_mut(), &mut der.as_ptr(), len.try_into().unwrap()))
|
||||
.map(|p| ::foreign_types::ForeignType::from_ptr(p))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! from_pem {
|
||||
($(#[$m:meta])* $n:ident, $t:ty, $f:path) => {
|
||||
$(#[$m])*
|
||||
pub fn $n(pem: &[u8]) -> Result<$t, crate::error::ErrorStack> {
|
||||
unsafe {
|
||||
crate::init();
|
||||
let bio = crate::bio::MemBioSlice::new(pem)?;
|
||||
cvt_p($f(bio.as_ptr(), ::std::ptr::null_mut(), None, ::std::ptr::null_mut()))
|
||||
.map(|p| ::foreign_types::ForeignType::from_ptr(p))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! foreign_type_and_impl_send_sync {
|
||||
(
|
||||
$(#[$impl_attr:meta])*
|
||||
type CType = $ctype:ty;
|
||||
fn drop = $drop:expr;
|
||||
$(fn clone = $clone:expr;)*
|
||||
|
||||
$(#[$owned_attr:meta])*
|
||||
pub struct $owned:ident;
|
||||
$(#[$borrowed_attr:meta])*
|
||||
pub struct $borrowed:ident;
|
||||
)
|
||||
=> {
|
||||
::foreign_types::foreign_type! {
|
||||
$(#[$impl_attr])*
|
||||
type CType = $ctype;
|
||||
fn drop = $drop;
|
||||
$(fn clone = $clone;)*
|
||||
$(#[$owned_attr])*
|
||||
pub struct $owned;
|
||||
$(#[$borrowed_attr])*
|
||||
pub struct $borrowed;
|
||||
}
|
||||
|
||||
unsafe impl Send for $owned{}
|
||||
unsafe impl Send for $borrowed{}
|
||||
unsafe impl Sync for $owned{}
|
||||
unsafe impl Sync for $borrowed{}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! generic_foreign_type_and_impl_send_sync {
|
||||
(
|
||||
$(#[$impl_attr:meta])*
|
||||
type CType = $ctype:ty;
|
||||
fn drop = $drop:expr;
|
||||
$(fn clone = $clone:expr;)*
|
||||
|
||||
$(#[$owned_attr:meta])*
|
||||
pub struct $owned:ident<T>;
|
||||
$(#[$borrowed_attr:meta])*
|
||||
pub struct $borrowed:ident<T>;
|
||||
) => {
|
||||
$(#[$owned_attr])*
|
||||
pub struct $owned<T>(*mut $ctype, ::std::marker::PhantomData<T>);
|
||||
|
||||
$(#[$impl_attr])*
|
||||
impl<T> ::foreign_types::ForeignType for $owned<T> {
|
||||
type CType = $ctype;
|
||||
type Ref = $borrowed<T>;
|
||||
|
||||
#[inline]
|
||||
unsafe fn from_ptr(ptr: *mut $ctype) -> $owned<T> {
|
||||
$owned(ptr, ::std::marker::PhantomData)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_ptr(&self) -> *mut $ctype {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Drop for $owned<T> {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
unsafe { $drop(self.0) }
|
||||
}
|
||||
}
|
||||
|
||||
$(
|
||||
impl<T> Clone for $owned<T> {
|
||||
#[inline]
|
||||
fn clone(&self) -> $owned<T> {
|
||||
unsafe {
|
||||
let handle: *mut $ctype = $clone(self.0);
|
||||
::foreign_types::ForeignType::from_ptr(handle)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ::std::borrow::ToOwned for $borrowed<T> {
|
||||
type Owned = $owned<T>;
|
||||
#[inline]
|
||||
fn to_owned(&self) -> $owned<T> {
|
||||
unsafe {
|
||||
let handle: *mut $ctype =
|
||||
$clone(::foreign_types::ForeignTypeRef::as_ptr(self));
|
||||
$crate::ForeignType::from_ptr(handle)
|
||||
}
|
||||
}
|
||||
}
|
||||
)*
|
||||
|
||||
impl<T> ::std::ops::Deref for $owned<T> {
|
||||
type Target = $borrowed<T>;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &$borrowed<T> {
|
||||
unsafe { ::foreign_types::ForeignTypeRef::from_ptr(self.0) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ::std::ops::DerefMut for $owned<T> {
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut $borrowed<T> {
|
||||
unsafe { ::foreign_types::ForeignTypeRef::from_ptr_mut(self.0) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ::std::borrow::Borrow<$borrowed<T>> for $owned<T> {
|
||||
#[inline]
|
||||
fn borrow(&self) -> &$borrowed<T> {
|
||||
&**self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ::std::convert::AsRef<$borrowed<T>> for $owned<T> {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &$borrowed<T> {
|
||||
&**self
|
||||
}
|
||||
}
|
||||
|
||||
$(#[$borrowed_attr])*
|
||||
pub struct $borrowed<T>(::foreign_types::Opaque, ::std::marker::PhantomData<T>);
|
||||
|
||||
$(#[$impl_attr])*
|
||||
impl<T> ::foreign_types::ForeignTypeRef for $borrowed<T> {
|
||||
type CType = $ctype;
|
||||
}
|
||||
|
||||
unsafe impl<T> Send for $owned<T>{}
|
||||
unsafe impl<T> Send for $borrowed<T>{}
|
||||
unsafe impl<T> Sync for $owned<T>{}
|
||||
unsafe impl<T> Sync for $borrowed<T>{}
|
||||
};
|
||||
}
|
||||
235
vendor/openssl/src/md.rs
vendored
Normal file
235
vendor/openssl/src/md.rs
vendored
Normal file
|
|
@ -0,0 +1,235 @@
|
|||
//! Message digest algorithms.
|
||||
|
||||
#[cfg(ossl300)]
|
||||
use crate::cvt_p;
|
||||
#[cfg(ossl300)]
|
||||
use crate::error::ErrorStack;
|
||||
#[cfg(ossl300)]
|
||||
use crate::lib_ctx::LibCtxRef;
|
||||
use crate::nid::Nid;
|
||||
use cfg_if::cfg_if;
|
||||
use foreign_types::{ForeignTypeRef, Opaque};
|
||||
use openssl_macros::corresponds;
|
||||
#[cfg(ossl300)]
|
||||
use std::ffi::CString;
|
||||
#[cfg(ossl300)]
|
||||
use std::ptr;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(ossl300)] {
|
||||
use foreign_types::ForeignType;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
type Inner = *mut ffi::EVP_MD;
|
||||
|
||||
impl Drop for Md {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
ffi::EVP_MD_free(self.as_ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ForeignType for Md {
|
||||
type CType = ffi::EVP_MD;
|
||||
type Ref = MdRef;
|
||||
|
||||
#[inline]
|
||||
unsafe fn from_ptr(ptr: *mut Self::CType) -> Self {
|
||||
Md(ptr)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_ptr(&self) -> *mut Self::CType {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Md {
|
||||
type Target = MdRef;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &Self::Target {
|
||||
unsafe {
|
||||
MdRef::from_ptr(self.as_ptr())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Md {
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
unsafe {
|
||||
MdRef::from_ptr_mut(self.as_ptr())
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
enum Inner {}
|
||||
}
|
||||
}
|
||||
|
||||
/// A message digest algorithm.
|
||||
pub struct Md(Inner);
|
||||
|
||||
unsafe impl Sync for Md {}
|
||||
unsafe impl Send for Md {}
|
||||
|
||||
impl Md {
|
||||
/// Returns the `Md` corresponding to an [`Nid`].
|
||||
#[corresponds(EVP_get_digestbynid)]
|
||||
pub fn from_nid(type_: Nid) -> Option<&'static MdRef> {
|
||||
ffi::init();
|
||||
unsafe {
|
||||
let ptr = ffi::EVP_get_digestbynid(type_.as_raw());
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(MdRef::from_ptr(ptr as *mut _))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Fetches an `Md` object corresponding to the specified algorithm name and properties.
|
||||
///
|
||||
/// Requires OpenSSL 3.0.0 or newer.
|
||||
#[corresponds(EVP_MD_fetch)]
|
||||
#[cfg(ossl300)]
|
||||
pub fn fetch(
|
||||
ctx: Option<&LibCtxRef>,
|
||||
algorithm: &str,
|
||||
properties: Option<&str>,
|
||||
) -> Result<Self, ErrorStack> {
|
||||
ffi::init();
|
||||
let algorithm = CString::new(algorithm).unwrap();
|
||||
let properties = properties.map(|s| CString::new(s).unwrap());
|
||||
|
||||
unsafe {
|
||||
let ptr = cvt_p(ffi::EVP_MD_fetch(
|
||||
ctx.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr),
|
||||
algorithm.as_ptr(),
|
||||
properties.map_or(ptr::null_mut(), |s| s.as_ptr()),
|
||||
))?;
|
||||
|
||||
Ok(Md::from_ptr(ptr))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(not(boringssl))]
|
||||
pub fn null() -> &'static MdRef {
|
||||
unsafe { MdRef::from_ptr(ffi::EVP_md_null() as *mut _) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn md5() -> &'static MdRef {
|
||||
unsafe { MdRef::from_ptr(ffi::EVP_md5() as *mut _) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn sha1() -> &'static MdRef {
|
||||
unsafe { MdRef::from_ptr(ffi::EVP_sha1() as *mut _) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn sha224() -> &'static MdRef {
|
||||
unsafe { MdRef::from_ptr(ffi::EVP_sha224() as *mut _) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn sha256() -> &'static MdRef {
|
||||
unsafe { MdRef::from_ptr(ffi::EVP_sha256() as *mut _) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn sha384() -> &'static MdRef {
|
||||
unsafe { MdRef::from_ptr(ffi::EVP_sha384() as *mut _) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn sha512() -> &'static MdRef {
|
||||
unsafe { MdRef::from_ptr(ffi::EVP_sha512() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(any(ossl111, libressl380))]
|
||||
#[inline]
|
||||
pub fn sha3_224() -> &'static MdRef {
|
||||
unsafe { MdRef::from_ptr(ffi::EVP_sha3_224() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(any(ossl111, libressl380))]
|
||||
#[inline]
|
||||
pub fn sha3_256() -> &'static MdRef {
|
||||
unsafe { MdRef::from_ptr(ffi::EVP_sha3_256() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(any(ossl111, libressl380))]
|
||||
#[inline]
|
||||
pub fn sha3_384() -> &'static MdRef {
|
||||
unsafe { MdRef::from_ptr(ffi::EVP_sha3_384() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(any(ossl111, libressl380))]
|
||||
#[inline]
|
||||
pub fn sha3_512() -> &'static MdRef {
|
||||
unsafe { MdRef::from_ptr(ffi::EVP_sha3_512() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
#[inline]
|
||||
pub fn shake128() -> &'static MdRef {
|
||||
unsafe { MdRef::from_ptr(ffi::EVP_shake128() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
#[inline]
|
||||
pub fn shake256() -> &'static MdRef {
|
||||
unsafe { MdRef::from_ptr(ffi::EVP_shake256() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_RMD160"))]
|
||||
#[inline]
|
||||
pub fn ripemd160() -> &'static MdRef {
|
||||
unsafe { MdRef::from_ptr(ffi::EVP_ripemd160() as *mut _) }
|
||||
}
|
||||
|
||||
#[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM3")))]
|
||||
#[inline]
|
||||
pub fn sm3() -> &'static MdRef {
|
||||
unsafe { MdRef::from_ptr(ffi::EVP_sm3() as *mut _) }
|
||||
}
|
||||
}
|
||||
|
||||
/// A reference to an [`Md`].
|
||||
pub struct MdRef(Opaque);
|
||||
|
||||
impl ForeignTypeRef for MdRef {
|
||||
type CType = ffi::EVP_MD;
|
||||
}
|
||||
|
||||
unsafe impl Sync for MdRef {}
|
||||
unsafe impl Send for MdRef {}
|
||||
|
||||
impl MdRef {
|
||||
/// Returns the block size of the digest in bytes.
|
||||
#[corresponds(EVP_MD_block_size)]
|
||||
#[inline]
|
||||
pub fn block_size(&self) -> usize {
|
||||
unsafe { ffi::EVP_MD_block_size(self.as_ptr()) as usize }
|
||||
}
|
||||
|
||||
/// Returns the size of the digest in bytes.
|
||||
#[corresponds(EVP_MD_size)]
|
||||
#[inline]
|
||||
pub fn size(&self) -> usize {
|
||||
unsafe { ffi::EVP_MD_size(self.as_ptr()) as usize }
|
||||
}
|
||||
|
||||
/// Returns the [`Nid`] of the digest.
|
||||
#[corresponds(EVP_MD_type)]
|
||||
#[inline]
|
||||
pub fn type_(&self) -> Nid {
|
||||
unsafe { Nid::from_raw(ffi::EVP_MD_type(self.as_ptr())) }
|
||||
}
|
||||
}
|
||||
552
vendor/openssl/src/md_ctx.rs
vendored
Normal file
552
vendor/openssl/src/md_ctx.rs
vendored
Normal file
|
|
@ -0,0 +1,552 @@
|
|||
//! The message digest context.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! Compute the SHA256 checksum of data
|
||||
//!
|
||||
//! ```
|
||||
//! use openssl::md::Md;
|
||||
//! use openssl::md_ctx::MdCtx;
|
||||
//!
|
||||
//! let mut ctx = MdCtx::new().unwrap();
|
||||
//! ctx.digest_init(Md::sha256()).unwrap();
|
||||
//! ctx.digest_update(b"Some Crypto Text").unwrap();
|
||||
//! let mut digest = [0; 32];
|
||||
//! ctx.digest_final(&mut digest).unwrap();
|
||||
//!
|
||||
//! assert_eq!(
|
||||
//! digest,
|
||||
//! *b"\x60\x78\x56\x38\x8a\xca\x5c\x51\x83\xc4\xd1\x4d\xc8\xf9\xcc\xf2\
|
||||
//! \xa5\x21\xb3\x10\x93\x72\xfa\xd6\x7c\x55\xf5\xc9\xe3\xd1\x83\x19",
|
||||
//! );
|
||||
//! ```
|
||||
//!
|
||||
//! Sign and verify data with RSA and SHA256
|
||||
//!
|
||||
//! ```
|
||||
//! use openssl::md::Md;
|
||||
//! use openssl::md_ctx::MdCtx;
|
||||
//! use openssl::pkey::PKey;
|
||||
//! use openssl::rsa::Rsa;
|
||||
//!
|
||||
//! // Generate a random RSA key.
|
||||
//! let key = Rsa::generate(4096).unwrap();
|
||||
//! let key = PKey::from_rsa(key).unwrap();
|
||||
//!
|
||||
//! let text = b"Some Crypto Text";
|
||||
//!
|
||||
//! // Create the signature.
|
||||
//! let mut ctx = MdCtx::new().unwrap();
|
||||
//! ctx.digest_sign_init(Some(Md::sha256()), &key).unwrap();
|
||||
//! ctx.digest_sign_update(text).unwrap();
|
||||
//! let mut signature = vec![];
|
||||
//! ctx.digest_sign_final_to_vec(&mut signature).unwrap();
|
||||
//!
|
||||
//! // Verify the signature.
|
||||
//! let mut ctx = MdCtx::new().unwrap();
|
||||
//! ctx.digest_verify_init(Some(Md::sha256()), &key).unwrap();
|
||||
//! ctx.digest_verify_update(text).unwrap();
|
||||
//! let valid = ctx.digest_verify_final(&signature).unwrap();
|
||||
//! assert!(valid);
|
||||
//! ```
|
||||
//!
|
||||
|
||||
#![cfg_attr(
|
||||
not(boringssl),
|
||||
doc = r#"\
|
||||
Compute and verify an HMAC-SHA256
|
||||
|
||||
```
|
||||
use openssl::md::Md;
|
||||
use openssl::md_ctx::MdCtx;
|
||||
use openssl::memcmp;
|
||||
use openssl::pkey::PKey;
|
||||
|
||||
// Create a key with the HMAC secret.
|
||||
let key = PKey::hmac(b"my secret").unwrap();
|
||||
|
||||
let text = b"Some Crypto Text";
|
||||
|
||||
// Compute the HMAC.
|
||||
let mut ctx = MdCtx::new().unwrap();
|
||||
ctx.digest_sign_init(Some(Md::sha256()), &key).unwrap();
|
||||
ctx.digest_sign_update(text).unwrap();
|
||||
let mut hmac = vec![];
|
||||
ctx.digest_sign_final_to_vec(&mut hmac).unwrap();
|
||||
|
||||
// Verify the HMAC. You can't use MdCtx to do this; instead use a constant time equality check.
|
||||
# let target = hmac.clone();
|
||||
let valid = memcmp::eq(&hmac, &target);
|
||||
assert!(valid);
|
||||
```"#
|
||||
)]
|
||||
|
||||
use crate::error::ErrorStack;
|
||||
use crate::md::MdRef;
|
||||
use crate::pkey::{HasPrivate, HasPublic, PKeyRef};
|
||||
use crate::pkey_ctx::PkeyCtxRef;
|
||||
use crate::{cvt, cvt_p};
|
||||
use cfg_if::cfg_if;
|
||||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
use openssl_macros::corresponds;
|
||||
use std::convert::TryFrom;
|
||||
use std::ptr;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl110, boringssl, libressl382))] {
|
||||
use ffi::{EVP_MD_CTX_free, EVP_MD_CTX_new};
|
||||
} else {
|
||||
use ffi::{EVP_MD_CTX_create as EVP_MD_CTX_new, EVP_MD_CTX_destroy as EVP_MD_CTX_free};
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::EVP_MD_CTX;
|
||||
fn drop = EVP_MD_CTX_free;
|
||||
|
||||
pub struct MdCtx;
|
||||
/// A reference to an [`MdCtx`].
|
||||
pub struct MdCtxRef;
|
||||
}
|
||||
|
||||
impl MdCtx {
|
||||
/// Creates a new context.
|
||||
#[corresponds(EVP_MD_CTX_new)]
|
||||
#[inline]
|
||||
pub fn new() -> Result<Self, ErrorStack> {
|
||||
ffi::init();
|
||||
|
||||
unsafe {
|
||||
let ptr = cvt_p(EVP_MD_CTX_new())?;
|
||||
Ok(MdCtx::from_ptr(ptr))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MdCtxRef {
|
||||
/// Initializes the context to compute the digest of data.
|
||||
#[corresponds(EVP_DigestInit_ex)]
|
||||
#[inline]
|
||||
pub fn digest_init(&mut self, digest: &MdRef) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_DigestInit_ex(
|
||||
self.as_ptr(),
|
||||
digest.as_ptr(),
|
||||
ptr::null_mut(),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Initializes the context to compute the signature of data.
|
||||
///
|
||||
/// A reference to the context's inner `PkeyCtx` is returned, allowing signature settings to be configured.
|
||||
#[corresponds(EVP_DigestSignInit)]
|
||||
#[inline]
|
||||
pub fn digest_sign_init<'a, T>(
|
||||
&'a mut self,
|
||||
digest: Option<&MdRef>,
|
||||
pkey: &PKeyRef<T>,
|
||||
) -> Result<&'a mut PkeyCtxRef<T>, ErrorStack>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
unsafe {
|
||||
let mut p = ptr::null_mut();
|
||||
cvt(ffi::EVP_DigestSignInit(
|
||||
self.as_ptr(),
|
||||
&mut p,
|
||||
digest.map_or(ptr::null(), |p| p.as_ptr()),
|
||||
ptr::null_mut(),
|
||||
pkey.as_ptr(),
|
||||
))?;
|
||||
Ok(PkeyCtxRef::from_ptr_mut(p))
|
||||
}
|
||||
}
|
||||
|
||||
/// Initializes the context to verify the signature of data.
|
||||
///
|
||||
/// A reference to the context's inner `PkeyCtx` is returned, allowing signature settings to be configured.
|
||||
#[corresponds(EVP_DigestVerifyInit)]
|
||||
#[inline]
|
||||
pub fn digest_verify_init<'a, T>(
|
||||
&'a mut self,
|
||||
digest: Option<&MdRef>,
|
||||
pkey: &PKeyRef<T>,
|
||||
) -> Result<&'a mut PkeyCtxRef<T>, ErrorStack>
|
||||
where
|
||||
T: HasPublic,
|
||||
{
|
||||
unsafe {
|
||||
let mut p = ptr::null_mut();
|
||||
cvt(ffi::EVP_DigestVerifyInit(
|
||||
self.as_ptr(),
|
||||
&mut p,
|
||||
digest.map_or(ptr::null(), |p| p.as_ptr()),
|
||||
ptr::null_mut(),
|
||||
pkey.as_ptr(),
|
||||
))?;
|
||||
Ok(PkeyCtxRef::from_ptr_mut(p))
|
||||
}
|
||||
}
|
||||
|
||||
/// Updates the context with more data.
|
||||
#[corresponds(EVP_DigestUpdate)]
|
||||
#[inline]
|
||||
pub fn digest_update(&mut self, data: &[u8]) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_DigestUpdate(
|
||||
self.as_ptr(),
|
||||
data.as_ptr() as *const _,
|
||||
data.len(),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Updates the context with more data.
|
||||
#[corresponds(EVP_DigestSignUpdate)]
|
||||
#[inline]
|
||||
pub fn digest_sign_update(&mut self, data: &[u8]) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_DigestSignUpdate(
|
||||
self.as_ptr(),
|
||||
data.as_ptr() as *const _,
|
||||
data.len(),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Updates the context with more data.
|
||||
#[corresponds(EVP_DigestVerifyUpdate)]
|
||||
#[inline]
|
||||
pub fn digest_verify_update(&mut self, data: &[u8]) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_DigestVerifyUpdate(
|
||||
self.as_ptr(),
|
||||
data.as_ptr() as *const _,
|
||||
data.len(),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Copies the computed digest into the buffer, returning the number of bytes written.
|
||||
#[corresponds(EVP_DigestFinal)]
|
||||
#[inline]
|
||||
pub fn digest_final(&mut self, out: &mut [u8]) -> Result<usize, ErrorStack> {
|
||||
let mut len = u32::try_from(out.len()).unwrap_or(u32::MAX);
|
||||
|
||||
unsafe {
|
||||
cvt(ffi::EVP_DigestFinal(
|
||||
self.as_ptr(),
|
||||
out.as_mut_ptr(),
|
||||
&mut len,
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(len as usize)
|
||||
}
|
||||
|
||||
/// Copies the computed digest into the buffer.
|
||||
///
|
||||
/// Requires OpenSSL 1.1.1 or newer.
|
||||
#[corresponds(EVP_DigestFinalXOF)]
|
||||
#[inline]
|
||||
#[cfg(ossl111)]
|
||||
pub fn digest_final_xof(&mut self, out: &mut [u8]) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_DigestFinalXOF(
|
||||
self.as_ptr(),
|
||||
out.as_mut_ptr(),
|
||||
out.len(),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Signs the computed digest.
|
||||
///
|
||||
/// If `out` is set to `None`, an upper bound on the number of bytes required for the output buffer will be
|
||||
/// returned.
|
||||
#[corresponds(EVP_DigestSignFinal)]
|
||||
#[inline]
|
||||
pub fn digest_sign_final(&mut self, out: Option<&mut [u8]>) -> Result<usize, ErrorStack> {
|
||||
let mut len = out.as_ref().map_or(0, |b| b.len());
|
||||
|
||||
unsafe {
|
||||
cvt(ffi::EVP_DigestSignFinal(
|
||||
self.as_ptr(),
|
||||
out.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
|
||||
&mut len,
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(len)
|
||||
}
|
||||
|
||||
/// Like [`Self::digest_sign_final`] but appends the signature to a [`Vec`].
|
||||
pub fn digest_sign_final_to_vec(&mut self, out: &mut Vec<u8>) -> Result<usize, ErrorStack> {
|
||||
let base = out.len();
|
||||
let len = self.digest_sign_final(None)?;
|
||||
out.resize(base + len, 0);
|
||||
let len = self.digest_sign_final(Some(&mut out[base..]))?;
|
||||
out.truncate(base + len);
|
||||
Ok(len)
|
||||
}
|
||||
|
||||
/// Verifies the provided signature.
|
||||
///
|
||||
/// Returns `Ok(true)` if the signature is valid, `Ok(false)` if the signature is invalid, and `Err` if an error
|
||||
/// occurred.
|
||||
#[corresponds(EVP_DigestVerifyFinal)]
|
||||
#[inline]
|
||||
pub fn digest_verify_final(&mut self, signature: &[u8]) -> Result<bool, ErrorStack> {
|
||||
unsafe {
|
||||
let r = ffi::EVP_DigestVerifyFinal(
|
||||
self.as_ptr(),
|
||||
signature.as_ptr() as *mut _,
|
||||
signature.len(),
|
||||
);
|
||||
if r == 1 {
|
||||
Ok(true)
|
||||
} else {
|
||||
let errors = ErrorStack::get();
|
||||
if errors.errors().is_empty() {
|
||||
Ok(false)
|
||||
} else {
|
||||
Err(errors)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the signature of the data in `from`.
|
||||
///
|
||||
/// If `to` is set to `None`, an upper bound on the number of bytes required for the output buffer will be
|
||||
/// returned.
|
||||
///
|
||||
/// Requires OpenSSL 1.1.1 or newer.
|
||||
#[corresponds(EVP_DigestSign)]
|
||||
#[cfg(ossl111)]
|
||||
#[inline]
|
||||
pub fn digest_sign(&mut self, from: &[u8], to: Option<&mut [u8]>) -> Result<usize, ErrorStack> {
|
||||
let mut len = to.as_ref().map_or(0, |b| b.len());
|
||||
|
||||
unsafe {
|
||||
cvt(ffi::EVP_DigestSign(
|
||||
self.as_ptr(),
|
||||
to.map_or(ptr::null_mut(), |b| b.as_mut_ptr()),
|
||||
&mut len,
|
||||
from.as_ptr(),
|
||||
from.len(),
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(len)
|
||||
}
|
||||
|
||||
/// Like [`Self::digest_sign`] but appends the signature to a [`Vec`].
|
||||
#[cfg(ossl111)]
|
||||
pub fn digest_sign_to_vec(
|
||||
&mut self,
|
||||
from: &[u8],
|
||||
to: &mut Vec<u8>,
|
||||
) -> Result<usize, ErrorStack> {
|
||||
let base = to.len();
|
||||
let len = self.digest_sign(from, None)?;
|
||||
to.resize(base + len, 0);
|
||||
let len = self.digest_sign(from, Some(&mut to[base..]))?;
|
||||
to.truncate(base + len);
|
||||
Ok(len)
|
||||
}
|
||||
|
||||
/// Verifies the signature of the data in `data`.
|
||||
///
|
||||
/// Returns `Ok(true)` if the signature is valid, `Ok(false)` if the signature is invalid, and `Err` if an error
|
||||
/// occurred.
|
||||
///
|
||||
/// Requires OpenSSL 1.1.1 or newer.
|
||||
#[corresponds(EVP_DigestVerify)]
|
||||
#[cfg(ossl111)]
|
||||
#[inline]
|
||||
pub fn digest_verify(&mut self, data: &[u8], signature: &[u8]) -> Result<bool, ErrorStack> {
|
||||
unsafe {
|
||||
let r = cvt(ffi::EVP_DigestVerify(
|
||||
self.as_ptr(),
|
||||
signature.as_ptr(),
|
||||
signature.len(),
|
||||
data.as_ptr(),
|
||||
data.len(),
|
||||
))?;
|
||||
Ok(r == 1)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the size of the message digest, i.e. the size of the hash
|
||||
#[corresponds(EVP_MD_CTX_size)]
|
||||
#[inline]
|
||||
pub fn size(&self) -> usize {
|
||||
unsafe { ffi::EVP_MD_CTX_size(self.as_ptr()) as usize }
|
||||
}
|
||||
|
||||
/// Resets the underlying EVP_MD_CTX instance
|
||||
#[corresponds(EVP_MD_CTX_reset)]
|
||||
#[cfg(ossl111)]
|
||||
#[inline]
|
||||
pub fn reset(&mut self) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
let _ = cvt(ffi::EVP_MD_CTX_reset(self.as_ptr()))?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::md::Md;
|
||||
use crate::pkey::PKey;
|
||||
use crate::rsa::Rsa;
|
||||
|
||||
#[test]
|
||||
fn verify_fail() {
|
||||
let key1 = Rsa::generate(4096).unwrap();
|
||||
let key1 = PKey::from_rsa(key1).unwrap();
|
||||
|
||||
let md = Md::sha256();
|
||||
let data = b"Some Crypto Text";
|
||||
|
||||
let mut ctx = MdCtx::new().unwrap();
|
||||
ctx.digest_sign_init(Some(md), &key1).unwrap();
|
||||
ctx.digest_sign_update(data).unwrap();
|
||||
let mut signature = vec![];
|
||||
ctx.digest_sign_final_to_vec(&mut signature).unwrap();
|
||||
|
||||
let bad_data = b"Some Crypto text";
|
||||
|
||||
ctx.digest_verify_init(Some(md), &key1).unwrap();
|
||||
ctx.digest_verify_update(bad_data).unwrap();
|
||||
assert!(matches!(
|
||||
ctx.digest_verify_final(&signature),
|
||||
Ok(false) | Err(_)
|
||||
));
|
||||
assert!(ErrorStack::get().errors().is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn verify_success() {
|
||||
let key1 = Rsa::generate(2048).unwrap();
|
||||
let key1 = PKey::from_rsa(key1).unwrap();
|
||||
|
||||
let md = Md::sha256();
|
||||
let data = b"Some Crypto Text";
|
||||
|
||||
let mut ctx = MdCtx::new().unwrap();
|
||||
ctx.digest_sign_init(Some(md), &key1).unwrap();
|
||||
ctx.digest_sign_update(data).unwrap();
|
||||
let mut signature = vec![];
|
||||
ctx.digest_sign_final_to_vec(&mut signature).unwrap();
|
||||
|
||||
let good_data = b"Some Crypto Text";
|
||||
|
||||
ctx.digest_verify_init(Some(md), &key1).unwrap();
|
||||
ctx.digest_verify_update(good_data).unwrap();
|
||||
let valid = ctx.digest_verify_final(&signature).unwrap();
|
||||
assert!(valid);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn verify_with_public_success() {
|
||||
let rsa = Rsa::generate(2048).unwrap();
|
||||
let key1 = PKey::from_rsa(rsa.clone()).unwrap();
|
||||
|
||||
let md = Md::sha256();
|
||||
let data = b"Some Crypto Text";
|
||||
|
||||
let mut ctx = MdCtx::new().unwrap();
|
||||
ctx.digest_sign_init(Some(md), &key1).unwrap();
|
||||
ctx.digest_sign_update(data).unwrap();
|
||||
let mut signature = vec![];
|
||||
ctx.digest_sign_final_to_vec(&mut signature).unwrap();
|
||||
|
||||
let good_data = b"Some Crypto Text";
|
||||
|
||||
// try to verify using only public components of the key
|
||||
let n = rsa.n().to_owned().unwrap();
|
||||
let e = rsa.e().to_owned().unwrap();
|
||||
|
||||
let rsa = Rsa::from_public_components(n, e).unwrap();
|
||||
let key1 = PKey::from_rsa(rsa).unwrap();
|
||||
|
||||
ctx.digest_verify_init(Some(md), &key1).unwrap();
|
||||
ctx.digest_verify_update(good_data).unwrap();
|
||||
let valid = ctx.digest_verify_final(&signature).unwrap();
|
||||
assert!(valid);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn verify_md_ctx_size() {
|
||||
let mut ctx = MdCtx::new().unwrap();
|
||||
ctx.digest_init(Md::sha224()).unwrap();
|
||||
assert_eq!(Md::sha224().size(), ctx.size());
|
||||
assert_eq!(Md::sha224().size(), 28);
|
||||
|
||||
let mut ctx = MdCtx::new().unwrap();
|
||||
ctx.digest_init(Md::sha256()).unwrap();
|
||||
assert_eq!(Md::sha256().size(), ctx.size());
|
||||
assert_eq!(Md::sha256().size(), 32);
|
||||
|
||||
let mut ctx = MdCtx::new().unwrap();
|
||||
ctx.digest_init(Md::sha384()).unwrap();
|
||||
assert_eq!(Md::sha384().size(), ctx.size());
|
||||
assert_eq!(Md::sha384().size(), 48);
|
||||
|
||||
let mut ctx = MdCtx::new().unwrap();
|
||||
ctx.digest_init(Md::sha512()).unwrap();
|
||||
assert_eq!(Md::sha512().size(), ctx.size());
|
||||
assert_eq!(Md::sha512().size(), 64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl111)]
|
||||
fn verify_md_ctx_reset() {
|
||||
let hello_expected =
|
||||
hex::decode("185f8db32271fe25f561a6fc938b2e264306ec304eda518007d1764826381969")
|
||||
.unwrap();
|
||||
let world_expected =
|
||||
hex::decode("78ae647dc5544d227130a0682a51e30bc7777fbb6d8a8f17007463a3ecd1d524")
|
||||
.unwrap();
|
||||
// Calculate SHA-256 digest of "Hello"
|
||||
let mut ctx = MdCtx::new().unwrap();
|
||||
ctx.digest_init(Md::sha256()).unwrap();
|
||||
ctx.digest_update(b"Hello").unwrap();
|
||||
let mut result = vec![0; 32];
|
||||
let result_len = ctx.digest_final(result.as_mut_slice()).unwrap();
|
||||
assert_eq!(result_len, result.len());
|
||||
// Validate result of "Hello"
|
||||
assert_eq!(result, hello_expected);
|
||||
|
||||
// Create new context
|
||||
let mut ctx = MdCtx::new().unwrap();
|
||||
// Initialize and update to "Hello"
|
||||
ctx.digest_init(Md::sha256()).unwrap();
|
||||
ctx.digest_update(b"Hello").unwrap();
|
||||
// Now reset, init to SHA-256 and use "World"
|
||||
ctx.reset().unwrap();
|
||||
ctx.digest_init(Md::sha256()).unwrap();
|
||||
ctx.digest_update(b"World").unwrap();
|
||||
|
||||
let mut reset_result = vec![0; 32];
|
||||
let result_len = ctx.digest_final(reset_result.as_mut_slice()).unwrap();
|
||||
assert_eq!(result_len, reset_result.len());
|
||||
// Validate result of digest of "World"
|
||||
assert_eq!(reset_result, world_expected);
|
||||
}
|
||||
}
|
||||
93
vendor/openssl/src/memcmp.rs
vendored
Normal file
93
vendor/openssl/src/memcmp.rs
vendored
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
//! Utilities to safely compare cryptographic values.
|
||||
//!
|
||||
//! Extra care must be taken when comparing values in
|
||||
//! cryptographic code. If done incorrectly, it can lead
|
||||
//! to a [timing attack](https://en.wikipedia.org/wiki/Timing_attack).
|
||||
//! By analyzing the time taken to execute parts of a cryptographic
|
||||
//! algorithm, and attacker can attempt to compromise the
|
||||
//! cryptosystem.
|
||||
//!
|
||||
//! The utilities in this module are designed to be resistant
|
||||
//! to this type of attack.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! To perform a constant-time comparison of two arrays of the same length but different
|
||||
//! values:
|
||||
//!
|
||||
//! ```
|
||||
//! use openssl::memcmp::eq;
|
||||
//!
|
||||
//! // We want to compare `a` to `b` and `c`, without giving
|
||||
//! // away through timing analysis that `c` is more similar to `a`
|
||||
//! // than `b`.
|
||||
//! let a = [0, 0, 0];
|
||||
//! let b = [1, 1, 1];
|
||||
//! let c = [0, 0, 1];
|
||||
//!
|
||||
//! // These statements will execute in the same amount of time.
|
||||
//! assert!(!eq(&a, &b));
|
||||
//! assert!(!eq(&a, &c));
|
||||
//! ```
|
||||
use libc::size_t;
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
/// Returns `true` iff `a` and `b` contain the same bytes.
|
||||
///
|
||||
/// 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.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This function will panic the current task if `a` and `b` do not have the same
|
||||
/// length.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// To perform a constant-time comparison of two arrays of the same length but different
|
||||
/// values:
|
||||
///
|
||||
/// ```
|
||||
/// use openssl::memcmp::eq;
|
||||
///
|
||||
/// // We want to compare `a` to `b` and `c`, without giving
|
||||
/// // away through timing analysis that `c` is more similar to `a`
|
||||
/// // than `b`.
|
||||
/// let a = [0, 0, 0];
|
||||
/// let b = [1, 1, 1];
|
||||
/// let c = [0, 0, 1];
|
||||
///
|
||||
/// // These statements will execute in the same amount of time.
|
||||
/// assert!(!eq(&a, &b));
|
||||
/// assert!(!eq(&a, &c));
|
||||
/// ```
|
||||
#[corresponds(CRYPTO_memcmp)]
|
||||
pub fn eq(a: &[u8], b: &[u8]) -> bool {
|
||||
assert!(a.len() == b.len());
|
||||
let ret = unsafe {
|
||||
ffi::CRYPTO_memcmp(
|
||||
a.as_ptr() as *const _,
|
||||
b.as_ptr() as *const _,
|
||||
a.len() as size_t,
|
||||
)
|
||||
};
|
||||
ret == 0
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::eq;
|
||||
|
||||
#[test]
|
||||
fn test_eq() {
|
||||
assert!(eq(&[], &[]));
|
||||
assert!(eq(&[1], &[1]));
|
||||
assert!(!eq(&[1, 2, 3], &[1, 2, 4]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_diff_lens() {
|
||||
eq(&[], &[1]);
|
||||
}
|
||||
}
|
||||
1181
vendor/openssl/src/nid.rs
vendored
Normal file
1181
vendor/openssl/src/nid.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
352
vendor/openssl/src/ocsp.rs
vendored
Normal file
352
vendor/openssl/src/ocsp.rs
vendored
Normal file
|
|
@ -0,0 +1,352 @@
|
|||
use bitflags::bitflags;
|
||||
use foreign_types::ForeignTypeRef;
|
||||
use libc::{c_int, c_long, c_ulong};
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
|
||||
use crate::asn1::Asn1GeneralizedTimeRef;
|
||||
use crate::error::ErrorStack;
|
||||
use crate::hash::MessageDigest;
|
||||
use crate::stack::StackRef;
|
||||
use crate::util::ForeignTypeRefExt;
|
||||
use crate::x509::store::X509StoreRef;
|
||||
use crate::x509::{X509Ref, X509};
|
||||
use crate::{cvt, cvt_p};
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
bitflags! {
|
||||
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
#[repr(transparent)]
|
||||
pub struct OcspFlag: c_ulong {
|
||||
const NO_CERTS = ffi::OCSP_NOCERTS;
|
||||
const NO_INTERN = ffi::OCSP_NOINTERN;
|
||||
const NO_CHAIN = ffi::OCSP_NOCHAIN;
|
||||
const NO_VERIFY = ffi::OCSP_NOVERIFY;
|
||||
const NO_EXPLICIT = ffi::OCSP_NOEXPLICIT;
|
||||
const NO_CA_SIGN = ffi::OCSP_NOCASIGN;
|
||||
const NO_DELEGATED = ffi::OCSP_NODELEGATED;
|
||||
const NO_CHECKS = ffi::OCSP_NOCHECKS;
|
||||
const TRUST_OTHER = ffi::OCSP_TRUSTOTHER;
|
||||
const RESPID_KEY = ffi::OCSP_RESPID_KEY;
|
||||
const NO_TIME = ffi::OCSP_NOTIME;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct OcspResponseStatus(c_int);
|
||||
|
||||
impl OcspResponseStatus {
|
||||
pub const SUCCESSFUL: OcspResponseStatus =
|
||||
OcspResponseStatus(ffi::OCSP_RESPONSE_STATUS_SUCCESSFUL);
|
||||
pub const MALFORMED_REQUEST: OcspResponseStatus =
|
||||
OcspResponseStatus(ffi::OCSP_RESPONSE_STATUS_MALFORMEDREQUEST);
|
||||
pub const INTERNAL_ERROR: OcspResponseStatus =
|
||||
OcspResponseStatus(ffi::OCSP_RESPONSE_STATUS_INTERNALERROR);
|
||||
pub const TRY_LATER: OcspResponseStatus =
|
||||
OcspResponseStatus(ffi::OCSP_RESPONSE_STATUS_TRYLATER);
|
||||
pub const SIG_REQUIRED: OcspResponseStatus =
|
||||
OcspResponseStatus(ffi::OCSP_RESPONSE_STATUS_SIGREQUIRED);
|
||||
pub const UNAUTHORIZED: OcspResponseStatus =
|
||||
OcspResponseStatus(ffi::OCSP_RESPONSE_STATUS_UNAUTHORIZED);
|
||||
|
||||
pub fn from_raw(raw: c_int) -> OcspResponseStatus {
|
||||
OcspResponseStatus(raw)
|
||||
}
|
||||
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub fn as_raw(&self) -> c_int {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct OcspCertStatus(c_int);
|
||||
|
||||
impl OcspCertStatus {
|
||||
pub const GOOD: OcspCertStatus = OcspCertStatus(ffi::V_OCSP_CERTSTATUS_GOOD);
|
||||
pub const REVOKED: OcspCertStatus = OcspCertStatus(ffi::V_OCSP_CERTSTATUS_REVOKED);
|
||||
pub const UNKNOWN: OcspCertStatus = OcspCertStatus(ffi::V_OCSP_CERTSTATUS_UNKNOWN);
|
||||
|
||||
pub fn from_raw(raw: c_int) -> OcspCertStatus {
|
||||
OcspCertStatus(raw)
|
||||
}
|
||||
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub fn as_raw(&self) -> c_int {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct OcspRevokedStatus(c_int);
|
||||
|
||||
impl OcspRevokedStatus {
|
||||
pub const NO_STATUS: OcspRevokedStatus = OcspRevokedStatus(ffi::OCSP_REVOKED_STATUS_NOSTATUS);
|
||||
pub const UNSPECIFIED: OcspRevokedStatus =
|
||||
OcspRevokedStatus(ffi::OCSP_REVOKED_STATUS_UNSPECIFIED);
|
||||
pub const KEY_COMPROMISE: OcspRevokedStatus =
|
||||
OcspRevokedStatus(ffi::OCSP_REVOKED_STATUS_KEYCOMPROMISE);
|
||||
pub const CA_COMPROMISE: OcspRevokedStatus =
|
||||
OcspRevokedStatus(ffi::OCSP_REVOKED_STATUS_CACOMPROMISE);
|
||||
pub const AFFILIATION_CHANGED: OcspRevokedStatus =
|
||||
OcspRevokedStatus(ffi::OCSP_REVOKED_STATUS_AFFILIATIONCHANGED);
|
||||
pub const STATUS_SUPERSEDED: OcspRevokedStatus =
|
||||
OcspRevokedStatus(ffi::OCSP_REVOKED_STATUS_SUPERSEDED);
|
||||
pub const STATUS_CESSATION_OF_OPERATION: OcspRevokedStatus =
|
||||
OcspRevokedStatus(ffi::OCSP_REVOKED_STATUS_CESSATIONOFOPERATION);
|
||||
pub const STATUS_CERTIFICATE_HOLD: OcspRevokedStatus =
|
||||
OcspRevokedStatus(ffi::OCSP_REVOKED_STATUS_CERTIFICATEHOLD);
|
||||
pub const REMOVE_FROM_CRL: OcspRevokedStatus =
|
||||
OcspRevokedStatus(ffi::OCSP_REVOKED_STATUS_REMOVEFROMCRL);
|
||||
|
||||
pub fn from_raw(raw: c_int) -> OcspRevokedStatus {
|
||||
OcspRevokedStatus(raw)
|
||||
}
|
||||
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub fn as_raw(&self) -> c_int {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub struct OcspStatus<'a> {
|
||||
/// The overall status of the response.
|
||||
pub status: OcspCertStatus,
|
||||
/// If `status` is `CERT_STATUS_REVOKED`, the reason for the revocation.
|
||||
pub reason: OcspRevokedStatus,
|
||||
/// If `status` is `CERT_STATUS_REVOKED`, the time at which the certificate was revoked.
|
||||
pub revocation_time: Option<&'a Asn1GeneralizedTimeRef>,
|
||||
/// The time that this revocation check was performed.
|
||||
pub this_update: &'a Asn1GeneralizedTimeRef,
|
||||
/// The time at which this revocation check expires.
|
||||
pub next_update: &'a Asn1GeneralizedTimeRef,
|
||||
}
|
||||
|
||||
impl OcspStatus<'_> {
|
||||
/// Checks validity of the `this_update` and `next_update` fields.
|
||||
///
|
||||
/// The `nsec` parameter specifies an amount of slack time that will be used when comparing
|
||||
/// those times with the current time to account for delays and clock skew.
|
||||
///
|
||||
/// The `maxsec` parameter limits the maximum age of the `this_update` parameter to prohibit
|
||||
/// very old responses.
|
||||
#[corresponds(OCSP_check_validity)]
|
||||
pub fn check_validity(&self, nsec: u32, maxsec: Option<u32>) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::OCSP_check_validity(
|
||||
self.this_update.as_ptr(),
|
||||
self.next_update.as_ptr(),
|
||||
nsec as c_long,
|
||||
maxsec.map(|n| n as c_long).unwrap_or(-1),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::OCSP_BASICRESP;
|
||||
fn drop = ffi::OCSP_BASICRESP_free;
|
||||
|
||||
pub struct OcspBasicResponse;
|
||||
pub struct OcspBasicResponseRef;
|
||||
}
|
||||
|
||||
impl OcspBasicResponseRef {
|
||||
/// Verifies the validity of the response.
|
||||
///
|
||||
/// The `certs` parameter contains a set of certificates that will be searched when locating the
|
||||
/// OCSP response signing certificate. Some responders do not include this in the response.
|
||||
#[corresponds(OCSP_basic_verify)]
|
||||
pub fn verify(
|
||||
&self,
|
||||
certs: &StackRef<X509>,
|
||||
store: &X509StoreRef,
|
||||
flags: OcspFlag,
|
||||
) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::OCSP_basic_verify(
|
||||
self.as_ptr(),
|
||||
certs.as_ptr(),
|
||||
store.as_ptr(),
|
||||
flags.bits(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Looks up the status for the specified certificate ID.
|
||||
#[corresponds(OCSP_resp_find_status)]
|
||||
pub fn find_status<'a>(&'a self, id: &OcspCertIdRef) -> Option<OcspStatus<'a>> {
|
||||
unsafe {
|
||||
let mut status = ffi::V_OCSP_CERTSTATUS_UNKNOWN;
|
||||
let mut reason = ffi::OCSP_REVOKED_STATUS_NOSTATUS;
|
||||
let mut revocation_time = ptr::null_mut();
|
||||
let mut this_update = ptr::null_mut();
|
||||
let mut next_update = ptr::null_mut();
|
||||
|
||||
let r = ffi::OCSP_resp_find_status(
|
||||
self.as_ptr(),
|
||||
id.as_ptr(),
|
||||
&mut status,
|
||||
&mut reason,
|
||||
&mut revocation_time,
|
||||
&mut this_update,
|
||||
&mut next_update,
|
||||
);
|
||||
if r == 1 {
|
||||
let revocation_time = Asn1GeneralizedTimeRef::from_const_ptr_opt(revocation_time);
|
||||
|
||||
Some(OcspStatus {
|
||||
status: OcspCertStatus(status),
|
||||
reason: OcspRevokedStatus(status),
|
||||
revocation_time,
|
||||
this_update: Asn1GeneralizedTimeRef::from_ptr(this_update),
|
||||
next_update: Asn1GeneralizedTimeRef::from_ptr(next_update),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::OCSP_CERTID;
|
||||
fn drop = ffi::OCSP_CERTID_free;
|
||||
|
||||
pub struct OcspCertId;
|
||||
pub struct OcspCertIdRef;
|
||||
}
|
||||
|
||||
impl OcspCertId {
|
||||
/// Constructs a certificate ID for certificate `subject`.
|
||||
#[corresponds(OCSP_cert_to_id)]
|
||||
pub fn from_cert(
|
||||
digest: MessageDigest,
|
||||
subject: &X509Ref,
|
||||
issuer: &X509Ref,
|
||||
) -> Result<OcspCertId, ErrorStack> {
|
||||
unsafe {
|
||||
cvt_p(ffi::OCSP_cert_to_id(
|
||||
digest.as_ptr(),
|
||||
subject.as_ptr(),
|
||||
issuer.as_ptr(),
|
||||
))
|
||||
.map(OcspCertId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::OCSP_RESPONSE;
|
||||
fn drop = ffi::OCSP_RESPONSE_free;
|
||||
|
||||
pub struct OcspResponse;
|
||||
pub struct OcspResponseRef;
|
||||
}
|
||||
|
||||
impl OcspResponse {
|
||||
/// Creates an OCSP response from the status and optional body.
|
||||
///
|
||||
/// A body should only be provided if `status` is `RESPONSE_STATUS_SUCCESSFUL`.
|
||||
#[corresponds(OCSP_response_create)]
|
||||
pub fn create(
|
||||
status: OcspResponseStatus,
|
||||
body: Option<&OcspBasicResponseRef>,
|
||||
) -> Result<OcspResponse, ErrorStack> {
|
||||
unsafe {
|
||||
ffi::init();
|
||||
|
||||
cvt_p(ffi::OCSP_response_create(
|
||||
status.as_raw(),
|
||||
body.map(|r| r.as_ptr()).unwrap_or(ptr::null_mut()),
|
||||
))
|
||||
.map(OcspResponse)
|
||||
}
|
||||
}
|
||||
|
||||
from_der! {
|
||||
/// Deserializes a DER-encoded OCSP response.
|
||||
#[corresponds(d2i_OCSP_RESPONSE)]
|
||||
from_der,
|
||||
OcspResponse,
|
||||
ffi::d2i_OCSP_RESPONSE
|
||||
}
|
||||
}
|
||||
|
||||
impl OcspResponseRef {
|
||||
to_der! {
|
||||
/// Serializes the response to its standard DER encoding.
|
||||
#[corresponds(i2d_OCSP_RESPONSE)]
|
||||
to_der,
|
||||
ffi::i2d_OCSP_RESPONSE
|
||||
}
|
||||
|
||||
/// Returns the status of the response.
|
||||
#[corresponds(OCSP_response_status)]
|
||||
pub fn status(&self) -> OcspResponseStatus {
|
||||
unsafe { OcspResponseStatus(ffi::OCSP_response_status(self.as_ptr())) }
|
||||
}
|
||||
|
||||
/// Returns the basic response.
|
||||
///
|
||||
/// This will only succeed if `status()` returns `RESPONSE_STATUS_SUCCESSFUL`.
|
||||
#[corresponds(OCSP_response_get1_basic)]
|
||||
pub fn basic(&self) -> Result<OcspBasicResponse, ErrorStack> {
|
||||
unsafe { cvt_p(ffi::OCSP_response_get1_basic(self.as_ptr())).map(OcspBasicResponse) }
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::OCSP_REQUEST;
|
||||
fn drop = ffi::OCSP_REQUEST_free;
|
||||
|
||||
pub struct OcspRequest;
|
||||
pub struct OcspRequestRef;
|
||||
}
|
||||
|
||||
impl OcspRequest {
|
||||
#[corresponds(OCSP_REQUEST_new)]
|
||||
pub fn new() -> Result<OcspRequest, ErrorStack> {
|
||||
unsafe {
|
||||
ffi::init();
|
||||
|
||||
cvt_p(ffi::OCSP_REQUEST_new()).map(OcspRequest)
|
||||
}
|
||||
}
|
||||
|
||||
from_der! {
|
||||
/// Deserializes a DER-encoded OCSP request.
|
||||
#[corresponds(d2i_OCSP_REQUEST)]
|
||||
from_der,
|
||||
OcspRequest,
|
||||
ffi::d2i_OCSP_REQUEST
|
||||
}
|
||||
}
|
||||
|
||||
impl OcspRequestRef {
|
||||
to_der! {
|
||||
/// Serializes the request to its standard DER encoding.
|
||||
#[corresponds(i2d_OCSP_REQUEST)]
|
||||
to_der,
|
||||
ffi::i2d_OCSP_REQUEST
|
||||
}
|
||||
|
||||
#[corresponds(OCSP_request_add0_id)]
|
||||
pub fn add_id(&mut self, id: OcspCertId) -> Result<&mut OcspOneReqRef, ErrorStack> {
|
||||
unsafe {
|
||||
let ptr = cvt_p(ffi::OCSP_request_add0_id(self.as_ptr(), id.as_ptr()))?;
|
||||
mem::forget(id);
|
||||
Ok(OcspOneReqRef::from_ptr_mut(ptr))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::OCSP_ONEREQ;
|
||||
fn drop = ffi::OCSP_ONEREQ_free;
|
||||
|
||||
pub struct OcspOneReq;
|
||||
pub struct OcspOneReqRef;
|
||||
}
|
||||
403
vendor/openssl/src/pkcs12.rs
vendored
Normal file
403
vendor/openssl/src/pkcs12.rs
vendored
Normal file
|
|
@ -0,0 +1,403 @@
|
|||
//! PKCS #12 archives.
|
||||
|
||||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
use libc::c_int;
|
||||
use std::ffi::CString;
|
||||
use std::ptr;
|
||||
|
||||
use crate::error::ErrorStack;
|
||||
#[cfg(not(boringssl))]
|
||||
use crate::hash::MessageDigest;
|
||||
use crate::nid::Nid;
|
||||
use crate::pkey::{HasPrivate, PKey, PKeyRef, Private};
|
||||
use crate::stack::Stack;
|
||||
use crate::util::ForeignTypeExt;
|
||||
use crate::x509::{X509Ref, X509};
|
||||
use crate::{cvt, cvt_p};
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::PKCS12;
|
||||
fn drop = ffi::PKCS12_free;
|
||||
|
||||
pub struct Pkcs12;
|
||||
pub struct Pkcs12Ref;
|
||||
}
|
||||
|
||||
impl Pkcs12Ref {
|
||||
to_der! {
|
||||
/// Serializes the `Pkcs12` to its standard DER encoding.
|
||||
#[corresponds(i2d_PKCS12)]
|
||||
to_der,
|
||||
ffi::i2d_PKCS12
|
||||
}
|
||||
|
||||
/// Deprecated.
|
||||
#[deprecated(note = "Use parse2 instead", since = "0.10.46")]
|
||||
#[allow(deprecated)]
|
||||
pub fn parse(&self, pass: &str) -> Result<ParsedPkcs12, ErrorStack> {
|
||||
let parsed = self.parse2(pass)?;
|
||||
|
||||
Ok(ParsedPkcs12 {
|
||||
pkey: parsed.pkey.unwrap(),
|
||||
cert: parsed.cert.unwrap(),
|
||||
chain: parsed.ca,
|
||||
})
|
||||
}
|
||||
|
||||
/// Extracts the contents of the `Pkcs12`.
|
||||
#[corresponds(PKCS12_parse)]
|
||||
pub fn parse2(&self, pass: &str) -> Result<ParsedPkcs12_2, ErrorStack> {
|
||||
unsafe {
|
||||
let pass = CString::new(pass.as_bytes()).unwrap();
|
||||
|
||||
let mut pkey = ptr::null_mut();
|
||||
let mut cert = ptr::null_mut();
|
||||
let mut ca = ptr::null_mut();
|
||||
|
||||
cvt(ffi::PKCS12_parse(
|
||||
self.as_ptr(),
|
||||
pass.as_ptr(),
|
||||
&mut pkey,
|
||||
&mut cert,
|
||||
&mut ca,
|
||||
))?;
|
||||
|
||||
let pkey = PKey::from_ptr_opt(pkey);
|
||||
let cert = X509::from_ptr_opt(cert);
|
||||
let ca = Stack::from_ptr_opt(ca);
|
||||
|
||||
Ok(ParsedPkcs12_2 { pkey, cert, ca })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Pkcs12 {
|
||||
from_der! {
|
||||
/// Deserializes a DER-encoded PKCS#12 archive.
|
||||
#[corresponds(d2i_PKCS12)]
|
||||
from_der,
|
||||
Pkcs12,
|
||||
ffi::d2i_PKCS12
|
||||
}
|
||||
|
||||
/// Creates a new builder for a protected pkcs12 certificate.
|
||||
///
|
||||
/// This uses the defaults from the OpenSSL library:
|
||||
///
|
||||
/// * `nid_key` - `AES_256_CBC` (3.0.0+) or `PBE_WITHSHA1AND3_KEY_TRIPLEDES_CBC`
|
||||
/// * `nid_cert` - `AES_256_CBC` (3.0.0+) or `PBE_WITHSHA1AND40BITRC2_CBC`
|
||||
/// * `iter` - `2048`
|
||||
/// * `mac_iter` - `2048`
|
||||
/// * `mac_md` - `SHA-256` (3.0.0+) or `SHA-1` (`SHA-1` only for BoringSSL)
|
||||
pub fn builder() -> Pkcs12Builder {
|
||||
ffi::init();
|
||||
|
||||
Pkcs12Builder {
|
||||
name: None,
|
||||
pkey: None,
|
||||
cert: None,
|
||||
ca: None,
|
||||
nid_key: Nid::UNDEF,
|
||||
nid_cert: Nid::UNDEF,
|
||||
iter: ffi::PKCS12_DEFAULT_ITER,
|
||||
mac_iter: ffi::PKCS12_DEFAULT_ITER,
|
||||
#[cfg(not(boringssl))]
|
||||
mac_md: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[deprecated(note = "Use ParsedPkcs12_2 instead", since = "0.10.46")]
|
||||
pub struct ParsedPkcs12 {
|
||||
pub pkey: PKey<Private>,
|
||||
pub cert: X509,
|
||||
pub chain: Option<Stack<X509>>,
|
||||
}
|
||||
|
||||
pub struct ParsedPkcs12_2 {
|
||||
pub pkey: Option<PKey<Private>>,
|
||||
pub cert: Option<X509>,
|
||||
pub ca: Option<Stack<X509>>,
|
||||
}
|
||||
|
||||
pub struct Pkcs12Builder {
|
||||
// FIXME borrow
|
||||
name: Option<CString>,
|
||||
pkey: Option<PKey<Private>>,
|
||||
cert: Option<X509>,
|
||||
ca: Option<Stack<X509>>,
|
||||
nid_key: Nid,
|
||||
nid_cert: Nid,
|
||||
iter: c_int,
|
||||
mac_iter: c_int,
|
||||
// FIXME remove
|
||||
#[cfg(not(boringssl))]
|
||||
mac_md: Option<MessageDigest>,
|
||||
}
|
||||
|
||||
impl Pkcs12Builder {
|
||||
/// The `friendlyName` used for the certificate and private key.
|
||||
pub fn name(&mut self, name: &str) -> &mut Self {
|
||||
self.name = Some(CString::new(name).unwrap());
|
||||
self
|
||||
}
|
||||
|
||||
/// The private key.
|
||||
pub fn pkey<T>(&mut self, pkey: &PKeyRef<T>) -> &mut Self
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
let new_pkey = unsafe { PKeyRef::from_ptr(pkey.as_ptr()) };
|
||||
self.pkey = Some(new_pkey.to_owned());
|
||||
self
|
||||
}
|
||||
|
||||
/// The certificate.
|
||||
pub fn cert(&mut self, cert: &X509Ref) -> &mut Self {
|
||||
self.cert = Some(cert.to_owned());
|
||||
self
|
||||
}
|
||||
|
||||
/// An additional set of certificates to include in the archive beyond the one provided to
|
||||
/// `build`.
|
||||
pub fn ca(&mut self, ca: Stack<X509>) -> &mut Self {
|
||||
self.ca = Some(ca);
|
||||
self
|
||||
}
|
||||
|
||||
/// The encryption algorithm that should be used for the key
|
||||
pub fn key_algorithm(&mut self, nid: Nid) -> &mut Self {
|
||||
self.nid_key = nid;
|
||||
self
|
||||
}
|
||||
|
||||
/// The encryption algorithm that should be used for the cert
|
||||
pub fn cert_algorithm(&mut self, nid: Nid) -> &mut Self {
|
||||
self.nid_cert = nid;
|
||||
self
|
||||
}
|
||||
|
||||
/// Key iteration count, default is 2048 as of this writing
|
||||
pub fn key_iter(&mut self, iter: u32) -> &mut Self {
|
||||
self.iter = iter as c_int;
|
||||
self
|
||||
}
|
||||
|
||||
/// MAC iteration count, default is the same as key_iter.
|
||||
///
|
||||
/// Old implementations don't understand MAC iterations greater than 1, (pre 1.0.1?), if such
|
||||
/// compatibility is required this should be set to 1.
|
||||
pub fn mac_iter(&mut self, mac_iter: u32) -> &mut Self {
|
||||
self.mac_iter = mac_iter as c_int;
|
||||
self
|
||||
}
|
||||
|
||||
/// MAC message digest type
|
||||
#[cfg(not(boringssl))]
|
||||
pub fn mac_md(&mut self, md: MessageDigest) -> &mut Self {
|
||||
self.mac_md = Some(md);
|
||||
self
|
||||
}
|
||||
|
||||
/// Deprecated.
|
||||
#[deprecated(
|
||||
note = "Use Self::{name, pkey, cert, build2} instead.",
|
||||
since = "0.10.46"
|
||||
)]
|
||||
pub fn build<T>(
|
||||
mut self,
|
||||
password: &str,
|
||||
friendly_name: &str,
|
||||
pkey: &PKeyRef<T>,
|
||||
cert: &X509Ref,
|
||||
) -> Result<Pkcs12, ErrorStack>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
self.name(friendly_name)
|
||||
.pkey(pkey)
|
||||
.cert(cert)
|
||||
.build2(password)
|
||||
}
|
||||
|
||||
/// Builds the PKCS#12 object.
|
||||
#[corresponds(PKCS12_create)]
|
||||
pub fn build2(&self, password: &str) -> Result<Pkcs12, ErrorStack> {
|
||||
unsafe {
|
||||
let pass = CString::new(password).unwrap();
|
||||
let pass = pass.as_ptr();
|
||||
let friendly_name = self.name.as_ref().map_or(ptr::null(), |p| p.as_ptr());
|
||||
let pkey = self.pkey.as_ref().map_or(ptr::null(), |p| p.as_ptr());
|
||||
let cert = self.cert.as_ref().map_or(ptr::null(), |p| p.as_ptr());
|
||||
let ca = self
|
||||
.ca
|
||||
.as_ref()
|
||||
.map(|ca| ca.as_ptr())
|
||||
.unwrap_or(ptr::null_mut());
|
||||
let nid_key = self.nid_key.as_raw();
|
||||
let nid_cert = self.nid_cert.as_raw();
|
||||
|
||||
// According to the OpenSSL docs, keytype is a non-standard extension for MSIE,
|
||||
// It's values are KEY_SIG or KEY_EX, see the OpenSSL docs for more information:
|
||||
// https://www.openssl.org/docs/manmaster/crypto/PKCS12_create.html
|
||||
let keytype = 0;
|
||||
|
||||
let pkcs12 = cvt_p(ffi::PKCS12_create(
|
||||
pass as *mut _,
|
||||
friendly_name as *mut _,
|
||||
pkey as *mut _,
|
||||
cert as *mut _,
|
||||
ca,
|
||||
nid_key,
|
||||
nid_cert,
|
||||
self.iter,
|
||||
self.mac_iter,
|
||||
keytype,
|
||||
))
|
||||
.map(Pkcs12)?;
|
||||
|
||||
#[cfg(not(boringssl))]
|
||||
// BoringSSL does not support overriding the MAC and will always
|
||||
// use SHA-1
|
||||
{
|
||||
let md_type = self
|
||||
.mac_md
|
||||
.map(|md_type| md_type.as_ptr())
|
||||
.unwrap_or(ptr::null());
|
||||
|
||||
cvt(ffi::PKCS12_set_mac(
|
||||
pkcs12.as_ptr(),
|
||||
pass,
|
||||
-1,
|
||||
ptr::null_mut(),
|
||||
0,
|
||||
self.mac_iter,
|
||||
md_type,
|
||||
))?;
|
||||
}
|
||||
|
||||
Ok(pkcs12)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::asn1::Asn1Time;
|
||||
use crate::hash::MessageDigest;
|
||||
use crate::nid::Nid;
|
||||
use crate::pkey::PKey;
|
||||
use crate::rsa::Rsa;
|
||||
use crate::x509::extension::KeyUsage;
|
||||
use crate::x509::{X509Name, X509};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn parse() {
|
||||
#[cfg(ossl300)]
|
||||
let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap();
|
||||
|
||||
let der = include_bytes!("../test/identity.p12");
|
||||
let pkcs12 = Pkcs12::from_der(der).unwrap();
|
||||
let parsed = pkcs12.parse2("mypass").unwrap();
|
||||
|
||||
assert_eq!(
|
||||
hex::encode(
|
||||
parsed
|
||||
.cert
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.digest(MessageDigest::sha1())
|
||||
.unwrap()
|
||||
),
|
||||
"59172d9313e84459bcff27f967e79e6e9217e584"
|
||||
);
|
||||
assert_eq!(
|
||||
parsed.cert.as_ref().unwrap().alias(),
|
||||
Some(b"foobar.com" as &[u8])
|
||||
);
|
||||
|
||||
let chain = parsed.ca.unwrap();
|
||||
assert_eq!(chain.len(), 1);
|
||||
assert_eq!(
|
||||
hex::encode(chain[0].digest(MessageDigest::sha1()).unwrap()),
|
||||
"c0cbdf7cdd03c9773e5468e1f6d2da7d5cbb1875"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_empty_chain() {
|
||||
#[cfg(ossl300)]
|
||||
let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap();
|
||||
|
||||
let der = include_bytes!("../test/keystore-empty-chain.p12");
|
||||
let pkcs12 = Pkcs12::from_der(der).unwrap();
|
||||
let parsed = pkcs12.parse2("cassandra").unwrap();
|
||||
if let Some(stack) = parsed.ca {
|
||||
assert_eq!(stack.len(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn create() {
|
||||
let subject_name = "ns.example.com";
|
||||
let rsa = Rsa::generate(2048).unwrap();
|
||||
let pkey = PKey::from_rsa(rsa).unwrap();
|
||||
|
||||
let mut name = X509Name::builder().unwrap();
|
||||
name.append_entry_by_nid(Nid::COMMONNAME, subject_name)
|
||||
.unwrap();
|
||||
let name = name.build();
|
||||
|
||||
let key_usage = KeyUsage::new().digital_signature().build().unwrap();
|
||||
|
||||
let mut builder = X509::builder().unwrap();
|
||||
builder.set_version(2).unwrap();
|
||||
builder
|
||||
.set_not_before(&Asn1Time::days_from_now(0).unwrap())
|
||||
.unwrap();
|
||||
builder
|
||||
.set_not_after(&Asn1Time::days_from_now(365).unwrap())
|
||||
.unwrap();
|
||||
builder.set_subject_name(&name).unwrap();
|
||||
builder.set_issuer_name(&name).unwrap();
|
||||
builder.append_extension(key_usage).unwrap();
|
||||
builder.set_pubkey(&pkey).unwrap();
|
||||
builder.sign(&pkey, MessageDigest::sha256()).unwrap();
|
||||
let cert = builder.build();
|
||||
|
||||
let pkcs12 = Pkcs12::builder()
|
||||
.name(subject_name)
|
||||
.pkey(&pkey)
|
||||
.cert(&cert)
|
||||
.build2("mypass")
|
||||
.unwrap();
|
||||
let der = pkcs12.to_der().unwrap();
|
||||
|
||||
let pkcs12 = Pkcs12::from_der(&der).unwrap();
|
||||
let parsed = pkcs12.parse2("mypass").unwrap();
|
||||
|
||||
assert_eq!(
|
||||
&*parsed.cert.unwrap().digest(MessageDigest::sha1()).unwrap(),
|
||||
&*cert.digest(MessageDigest::sha1()).unwrap()
|
||||
);
|
||||
assert!(parsed.pkey.unwrap().public_eq(&pkey));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn create_only_ca() {
|
||||
let ca = include_bytes!("../test/root-ca.pem");
|
||||
let ca = X509::from_pem(ca).unwrap();
|
||||
let mut chain = Stack::new().unwrap();
|
||||
chain.push(ca).unwrap();
|
||||
|
||||
let pkcs12 = Pkcs12::builder().ca(chain).build2("hunter2").unwrap();
|
||||
let parsed = pkcs12.parse2("hunter2").unwrap();
|
||||
|
||||
assert!(parsed.cert.is_none());
|
||||
assert!(parsed.pkey.is_none());
|
||||
assert_eq!(parsed.ca.unwrap().len(), 1);
|
||||
}
|
||||
}
|
||||
310
vendor/openssl/src/pkcs5.rs
vendored
Normal file
310
vendor/openssl/src/pkcs5.rs
vendored
Normal file
|
|
@ -0,0 +1,310 @@
|
|||
#[cfg(not(boringssl))]
|
||||
use libc::c_int;
|
||||
use std::convert::TryInto;
|
||||
#[cfg(not(boringssl))]
|
||||
use std::ptr;
|
||||
|
||||
use crate::cvt;
|
||||
use crate::error::ErrorStack;
|
||||
use crate::hash::MessageDigest;
|
||||
#[cfg(not(boringssl))]
|
||||
use crate::symm::Cipher;
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct KeyIvPair {
|
||||
pub key: Vec<u8>,
|
||||
pub iv: Option<Vec<u8>>,
|
||||
}
|
||||
|
||||
/// 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` or another more modern key derivation algorithm.
|
||||
#[corresponds(EVP_BytesToKey)]
|
||||
#[allow(clippy::useless_conversion)]
|
||||
#[cfg(not(boringssl))]
|
||||
pub fn bytes_to_key(
|
||||
cipher: Cipher,
|
||||
digest: MessageDigest,
|
||||
data: &[u8],
|
||||
salt: Option<&[u8]>,
|
||||
count: i32,
|
||||
) -> Result<KeyIvPair, ErrorStack> {
|
||||
unsafe {
|
||||
assert!(data.len() <= c_int::MAX 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 = 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());
|
||||
|
||||
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, iv })
|
||||
}
|
||||
}
|
||||
|
||||
/// Derives a key from a password and salt using the PBKDF2-HMAC algorithm with a digest function.
|
||||
#[corresponds(PKCS5_PBKDF2_HMAC)]
|
||||
pub fn pbkdf2_hmac(
|
||||
pass: &[u8],
|
||||
salt: &[u8],
|
||||
iter: usize,
|
||||
hash: MessageDigest,
|
||||
key: &mut [u8],
|
||||
) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
ffi::init();
|
||||
cvt(ffi::PKCS5_PBKDF2_HMAC(
|
||||
pass.as_ptr() as *const _,
|
||||
pass.len().try_into().unwrap(),
|
||||
salt.as_ptr(),
|
||||
salt.len().try_into().unwrap(),
|
||||
iter.try_into().unwrap(),
|
||||
hash.as_ptr(),
|
||||
key.len().try_into().unwrap(),
|
||||
key.as_mut_ptr(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Derives a key from a password and salt using the scrypt algorithm.
|
||||
///
|
||||
/// Requires OpenSSL 1.1.0 or newer.
|
||||
#[corresponds(EVP_PBE_scrypt)]
|
||||
#[cfg(all(any(ossl110, boringssl), not(osslconf = "OPENSSL_NO_SCRYPT")))]
|
||||
#[allow(clippy::useless_conversion)]
|
||||
pub fn scrypt(
|
||||
pass: &[u8],
|
||||
salt: &[u8],
|
||||
n: u64,
|
||||
r: u64,
|
||||
p: u64,
|
||||
maxmem: u64,
|
||||
key: &mut [u8],
|
||||
) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
ffi::init();
|
||||
cvt(ffi::EVP_PBE_scrypt(
|
||||
pass.as_ptr() as *const _,
|
||||
pass.len(),
|
||||
salt.as_ptr() as *const _,
|
||||
salt.len(),
|
||||
n,
|
||||
r,
|
||||
p,
|
||||
maxmem.try_into().unwrap(),
|
||||
key.as_mut_ptr() as *mut _,
|
||||
key.len(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::hash::MessageDigest;
|
||||
#[cfg(not(boringssl))]
|
||||
use crate::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]
|
||||
#[cfg(not(boringssl))]
|
||||
fn bytes_to_key() {
|
||||
let salt = [16_u8, 34_u8, 19_u8, 23_u8, 141_u8, 4_u8, 207_u8, 221_u8];
|
||||
|
||||
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),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(ossl110, boringssl))]
|
||||
fn scrypt() {
|
||||
let pass = "pleaseletmein";
|
||||
let salt = "SodiumChloride";
|
||||
let expected =
|
||||
"7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613\
|
||||
f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887";
|
||||
|
||||
let mut actual = [0; 64];
|
||||
super::scrypt(
|
||||
pass.as_bytes(),
|
||||
salt.as_bytes(),
|
||||
16384,
|
||||
8,
|
||||
1,
|
||||
0,
|
||||
&mut actual,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(hex::encode(&actual[..]), expected);
|
||||
}
|
||||
}
|
||||
573
vendor/openssl/src/pkcs7.rs
vendored
Normal file
573
vendor/openssl/src/pkcs7.rs
vendored
Normal file
|
|
@ -0,0 +1,573 @@
|
|||
use bitflags::bitflags;
|
||||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
use libc::c_int;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
|
||||
use crate::asn1::Asn1ObjectRef;
|
||||
use crate::bio::{MemBio, MemBioSlice};
|
||||
use crate::error::ErrorStack;
|
||||
use crate::nid::Nid;
|
||||
use crate::pkey::{HasPrivate, PKeyRef};
|
||||
use crate::stack::{Stack, StackRef, Stackable};
|
||||
use crate::symm::Cipher;
|
||||
use crate::util::ForeignTypeRefExt;
|
||||
use crate::x509::store::X509StoreRef;
|
||||
use crate::x509::{X509Ref, X509};
|
||||
use crate::{cvt, cvt_p};
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::PKCS7_SIGNER_INFO;
|
||||
fn drop = ffi::PKCS7_SIGNER_INFO_free;
|
||||
|
||||
pub struct Pkcs7SignerInfo;
|
||||
pub struct Pkcs7SignerInfoRef;
|
||||
}
|
||||
|
||||
impl Stackable for Pkcs7SignerInfo {
|
||||
type StackType = ffi::stack_st_PKCS7_SIGNER_INFO;
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::PKCS7;
|
||||
fn drop = ffi::PKCS7_free;
|
||||
|
||||
/// A PKCS#7 structure.
|
||||
///
|
||||
/// Contains signed and/or encrypted data.
|
||||
pub struct Pkcs7;
|
||||
|
||||
/// Reference to `Pkcs7`
|
||||
pub struct Pkcs7Ref;
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::PKCS7_SIGNED;
|
||||
fn drop = ffi::PKCS7_SIGNED_free;
|
||||
|
||||
/// A PKCS#7 signed data structure.
|
||||
///
|
||||
/// Contains signed data.
|
||||
pub struct Pkcs7Signed;
|
||||
|
||||
/// Reference to `Pkcs7Signed`
|
||||
pub struct Pkcs7SignedRef;
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
#[repr(transparent)]
|
||||
pub struct Pkcs7Flags: c_int {
|
||||
const TEXT = ffi::PKCS7_TEXT;
|
||||
const NOCERTS = ffi::PKCS7_NOCERTS;
|
||||
const NOSIGS = ffi::PKCS7_NOSIGS;
|
||||
const NOCHAIN = ffi::PKCS7_NOCHAIN;
|
||||
const NOINTERN = ffi::PKCS7_NOINTERN;
|
||||
const NOVERIFY = ffi::PKCS7_NOVERIFY;
|
||||
const DETACHED = ffi::PKCS7_DETACHED;
|
||||
const BINARY = ffi::PKCS7_BINARY;
|
||||
const NOATTR = ffi::PKCS7_NOATTR;
|
||||
const NOSMIMECAP = ffi::PKCS7_NOSMIMECAP;
|
||||
const NOOLDMIMETYPE = ffi::PKCS7_NOOLDMIMETYPE;
|
||||
const CRLFEOL = ffi::PKCS7_CRLFEOL;
|
||||
const STREAM = ffi::PKCS7_STREAM;
|
||||
const NOCRL = ffi::PKCS7_NOCRL;
|
||||
const PARTIAL = ffi::PKCS7_PARTIAL;
|
||||
const REUSE_DIGEST = ffi::PKCS7_REUSE_DIGEST;
|
||||
#[cfg(not(any(ossl101, ossl102, libressl)))]
|
||||
const NO_DUAL_CONTENT = ffi::PKCS7_NO_DUAL_CONTENT;
|
||||
}
|
||||
}
|
||||
|
||||
impl Pkcs7 {
|
||||
from_pem! {
|
||||
/// Deserializes a PEM-encoded PKCS#7 signature
|
||||
///
|
||||
/// The input should have a header of `-----BEGIN PKCS7-----`.
|
||||
#[corresponds(PEM_read_bio_PKCS7)]
|
||||
from_pem,
|
||||
Pkcs7,
|
||||
ffi::PEM_read_bio_PKCS7
|
||||
}
|
||||
|
||||
from_der! {
|
||||
/// Deserializes a DER-encoded PKCS#7 signature
|
||||
#[corresponds(d2i_PKCS7)]
|
||||
from_der,
|
||||
Pkcs7,
|
||||
ffi::d2i_PKCS7
|
||||
}
|
||||
|
||||
/// Parses a message in S/MIME format.
|
||||
///
|
||||
/// Returns the loaded signature, along with the cleartext message (if
|
||||
/// available).
|
||||
#[corresponds(SMIME_read_PKCS7)]
|
||||
pub fn from_smime(input: &[u8]) -> Result<(Pkcs7, Option<Vec<u8>>), ErrorStack> {
|
||||
ffi::init();
|
||||
|
||||
let input_bio = MemBioSlice::new(input)?;
|
||||
let mut bcont_bio = ptr::null_mut();
|
||||
unsafe {
|
||||
let pkcs7 =
|
||||
cvt_p(ffi::SMIME_read_PKCS7(input_bio.as_ptr(), &mut bcont_bio)).map(Pkcs7)?;
|
||||
let out = if !bcont_bio.is_null() {
|
||||
let bcont_bio = MemBio::from_ptr(bcont_bio);
|
||||
Some(bcont_bio.get_buf().to_vec())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Ok((pkcs7, out))
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates and returns a PKCS#7 `envelopedData` structure.
|
||||
///
|
||||
/// `certs` is a list of recipient certificates. `input` is the content to be
|
||||
/// encrypted. `cipher` is the symmetric cipher to use. `flags` is an optional
|
||||
/// set of flags.
|
||||
#[corresponds(PKCS7_encrypt)]
|
||||
pub fn encrypt(
|
||||
certs: &StackRef<X509>,
|
||||
input: &[u8],
|
||||
cipher: Cipher,
|
||||
flags: Pkcs7Flags,
|
||||
) -> Result<Pkcs7, ErrorStack> {
|
||||
let input_bio = MemBioSlice::new(input)?;
|
||||
|
||||
unsafe {
|
||||
cvt_p(ffi::PKCS7_encrypt(
|
||||
certs.as_ptr(),
|
||||
input_bio.as_ptr(),
|
||||
cipher.as_ptr(),
|
||||
flags.bits(),
|
||||
))
|
||||
.map(Pkcs7)
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates and returns a PKCS#7 `signedData` structure.
|
||||
///
|
||||
/// `signcert` is the certificate to sign with, `pkey` is the corresponding
|
||||
/// private key. `certs` is an optional additional set of certificates to
|
||||
/// include in the PKCS#7 structure (for example any intermediate CAs in the
|
||||
/// chain).
|
||||
#[corresponds(PKCS7_sign)]
|
||||
pub fn sign<PT>(
|
||||
signcert: &X509Ref,
|
||||
pkey: &PKeyRef<PT>,
|
||||
certs: &StackRef<X509>,
|
||||
input: &[u8],
|
||||
flags: Pkcs7Flags,
|
||||
) -> Result<Pkcs7, ErrorStack>
|
||||
where
|
||||
PT: HasPrivate,
|
||||
{
|
||||
let input_bio = MemBioSlice::new(input)?;
|
||||
unsafe {
|
||||
cvt_p(ffi::PKCS7_sign(
|
||||
signcert.as_ptr(),
|
||||
pkey.as_ptr(),
|
||||
certs.as_ptr(),
|
||||
input_bio.as_ptr(),
|
||||
flags.bits(),
|
||||
))
|
||||
.map(Pkcs7)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Pkcs7Ref {
|
||||
/// Converts PKCS#7 structure to S/MIME format
|
||||
#[corresponds(SMIME_write_PKCS7)]
|
||||
pub fn to_smime(&self, input: &[u8], flags: Pkcs7Flags) -> Result<Vec<u8>, ErrorStack> {
|
||||
let input_bio = MemBioSlice::new(input)?;
|
||||
let output = MemBio::new()?;
|
||||
unsafe {
|
||||
cvt(ffi::SMIME_write_PKCS7(
|
||||
output.as_ptr(),
|
||||
self.as_ptr(),
|
||||
input_bio.as_ptr(),
|
||||
flags.bits(),
|
||||
))
|
||||
.map(|_| output.get_buf().to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
to_pem! {
|
||||
/// Serializes the data into a PEM-encoded PKCS#7 structure.
|
||||
///
|
||||
/// The output will have a header of `-----BEGIN PKCS7-----`.
|
||||
#[corresponds(PEM_write_bio_PKCS7)]
|
||||
to_pem,
|
||||
ffi::PEM_write_bio_PKCS7
|
||||
}
|
||||
|
||||
to_der! {
|
||||
/// Serializes the data into a DER-encoded PKCS#7 structure.
|
||||
#[corresponds(i2d_PKCS7)]
|
||||
to_der,
|
||||
ffi::i2d_PKCS7
|
||||
}
|
||||
|
||||
/// Decrypts data using the provided private key.
|
||||
///
|
||||
/// `pkey` is the recipient's private key, and `cert` is the recipient's
|
||||
/// certificate.
|
||||
///
|
||||
/// Returns the decrypted message.
|
||||
#[corresponds(PKCS7_decrypt)]
|
||||
pub fn decrypt<PT>(
|
||||
&self,
|
||||
pkey: &PKeyRef<PT>,
|
||||
cert: &X509Ref,
|
||||
flags: Pkcs7Flags,
|
||||
) -> Result<Vec<u8>, ErrorStack>
|
||||
where
|
||||
PT: HasPrivate,
|
||||
{
|
||||
let output = MemBio::new()?;
|
||||
|
||||
unsafe {
|
||||
cvt(ffi::PKCS7_decrypt(
|
||||
self.as_ptr(),
|
||||
pkey.as_ptr(),
|
||||
cert.as_ptr(),
|
||||
output.as_ptr(),
|
||||
flags.bits(),
|
||||
))
|
||||
.map(|_| output.get_buf().to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
/// Verifies the PKCS#7 `signedData` structure contained by `&self`.
|
||||
///
|
||||
/// `certs` is a set of certificates in which to search for the signer's
|
||||
/// certificate. `store` is a trusted certificate store (used for chain
|
||||
/// verification). `indata` is the signed data if the content is not present
|
||||
/// in `&self`. The content is written to `out` if it is not `None`.
|
||||
#[corresponds(PKCS7_verify)]
|
||||
pub fn verify(
|
||||
&self,
|
||||
certs: &StackRef<X509>,
|
||||
store: &X509StoreRef,
|
||||
indata: Option<&[u8]>,
|
||||
out: Option<&mut Vec<u8>>,
|
||||
flags: Pkcs7Flags,
|
||||
) -> Result<(), ErrorStack> {
|
||||
let out_bio = MemBio::new()?;
|
||||
|
||||
let indata_bio = match indata {
|
||||
Some(data) => Some(MemBioSlice::new(data)?),
|
||||
None => None,
|
||||
};
|
||||
let indata_bio_ptr = indata_bio.as_ref().map_or(ptr::null_mut(), |p| p.as_ptr());
|
||||
|
||||
unsafe {
|
||||
cvt(ffi::PKCS7_verify(
|
||||
self.as_ptr(),
|
||||
certs.as_ptr(),
|
||||
store.as_ptr(),
|
||||
indata_bio_ptr,
|
||||
out_bio.as_ptr(),
|
||||
flags.bits(),
|
||||
))
|
||||
.map(|_| ())?
|
||||
}
|
||||
|
||||
if let Some(data) = out {
|
||||
data.clear();
|
||||
data.extend_from_slice(out_bio.get_buf());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Retrieve the signer's certificates from the PKCS#7 structure without verifying them.
|
||||
#[corresponds(PKCS7_get0_signers)]
|
||||
pub fn signers(
|
||||
&self,
|
||||
certs: &StackRef<X509>,
|
||||
flags: Pkcs7Flags,
|
||||
) -> Result<Stack<X509>, ErrorStack> {
|
||||
unsafe {
|
||||
let ptr = cvt_p(ffi::PKCS7_get0_signers(
|
||||
self.as_ptr(),
|
||||
certs.as_ptr(),
|
||||
flags.bits(),
|
||||
))?;
|
||||
|
||||
// The returned stack is owned by the caller, but the certs inside are not! Our stack interface can't deal
|
||||
// with that, so instead we just manually bump the refcount of the certs so that the whole stack is properly
|
||||
// owned.
|
||||
let stack = Stack::<X509>::from_ptr(ptr);
|
||||
for cert in &stack {
|
||||
mem::forget(cert.to_owned());
|
||||
}
|
||||
|
||||
Ok(stack)
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the type of a PKCS#7 structure as an Asn1Object
|
||||
pub fn type_(&self) -> Option<&Asn1ObjectRef> {
|
||||
unsafe {
|
||||
let ptr = (*self.as_ptr()).type_;
|
||||
Asn1ObjectRef::from_const_ptr_opt(ptr)
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the signed data of a PKCS#7 structure of type PKCS7_SIGNED
|
||||
pub fn signed(&self) -> Option<&Pkcs7SignedRef> {
|
||||
unsafe {
|
||||
if self.type_().map(|x| x.nid()) != Some(Nid::PKCS7_SIGNED) {
|
||||
return None;
|
||||
}
|
||||
let signed_data = (*self.as_ptr()).d.sign;
|
||||
Pkcs7SignedRef::from_const_ptr_opt(signed_data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Pkcs7SignedRef {
|
||||
/// Get the stack of certificates from the PKCS7_SIGNED object
|
||||
pub fn certificates(&self) -> Option<&StackRef<X509>> {
|
||||
unsafe {
|
||||
self.as_ptr()
|
||||
.as_ref()
|
||||
.and_then(|x| x.cert.as_mut())
|
||||
.and_then(|x| StackRef::<X509>::from_const_ptr_opt(x))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::hash::MessageDigest;
|
||||
use crate::nid::Nid;
|
||||
use crate::pkcs7::{Pkcs7, Pkcs7Flags};
|
||||
use crate::pkey::PKey;
|
||||
use crate::stack::Stack;
|
||||
use crate::symm::Cipher;
|
||||
use crate::x509::store::X509StoreBuilder;
|
||||
use crate::x509::X509;
|
||||
|
||||
#[test]
|
||||
fn encrypt_decrypt_test() {
|
||||
let cert = include_bytes!("../test/certs.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
let mut certs = Stack::new().unwrap();
|
||||
certs.push(cert.clone()).unwrap();
|
||||
let message: String = String::from("foo");
|
||||
let cipher = Cipher::des_ede3_cbc();
|
||||
let flags = Pkcs7Flags::STREAM;
|
||||
let pkey = include_bytes!("../test/key.pem");
|
||||
let pkey = PKey::private_key_from_pem(pkey).unwrap();
|
||||
|
||||
let pkcs7 =
|
||||
Pkcs7::encrypt(&certs, message.as_bytes(), cipher, flags).expect("should succeed");
|
||||
assert_eq!(
|
||||
pkcs7.type_().expect("PKCS7 should have a type").nid(),
|
||||
Nid::PKCS7_ENVELOPED
|
||||
);
|
||||
|
||||
let encrypted = pkcs7
|
||||
.to_smime(message.as_bytes(), flags)
|
||||
.expect("should succeed");
|
||||
|
||||
let (pkcs7_decoded, _) = Pkcs7::from_smime(encrypted.as_slice()).expect("should succeed");
|
||||
|
||||
let decoded = pkcs7_decoded
|
||||
.decrypt(&pkey, &cert, Pkcs7Flags::empty())
|
||||
.expect("should succeed");
|
||||
|
||||
assert_eq!(decoded, message.into_bytes());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sign_verify_test_detached() {
|
||||
let cert = include_bytes!("../test/cert.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
let certs = Stack::new().unwrap();
|
||||
let message = "foo";
|
||||
let flags = Pkcs7Flags::STREAM | Pkcs7Flags::DETACHED;
|
||||
let pkey = include_bytes!("../test/key.pem");
|
||||
let pkey = PKey::private_key_from_pem(pkey).unwrap();
|
||||
let mut store_builder = X509StoreBuilder::new().expect("should succeed");
|
||||
|
||||
let root_ca = include_bytes!("../test/root-ca.pem");
|
||||
let root_ca = X509::from_pem(root_ca).unwrap();
|
||||
store_builder.add_cert(root_ca).expect("should succeed");
|
||||
|
||||
let store = store_builder.build();
|
||||
|
||||
let pkcs7 =
|
||||
Pkcs7::sign(&cert, &pkey, &certs, message.as_bytes(), flags).expect("should succeed");
|
||||
assert_eq!(
|
||||
pkcs7.type_().expect("PKCS7 should have a type").nid(),
|
||||
Nid::PKCS7_SIGNED
|
||||
);
|
||||
|
||||
let signed = pkcs7
|
||||
.to_smime(message.as_bytes(), flags)
|
||||
.expect("should succeed");
|
||||
println!("{:?}", String::from_utf8(signed.clone()).unwrap());
|
||||
let (pkcs7_decoded, content) =
|
||||
Pkcs7::from_smime(signed.as_slice()).expect("should succeed");
|
||||
|
||||
let mut output = Vec::new();
|
||||
pkcs7_decoded
|
||||
.verify(
|
||||
&certs,
|
||||
&store,
|
||||
Some(message.as_bytes()),
|
||||
Some(&mut output),
|
||||
flags,
|
||||
)
|
||||
.expect("should succeed");
|
||||
|
||||
assert_eq!(output, message.as_bytes());
|
||||
assert_eq!(content.expect("should be non-empty"), message.as_bytes());
|
||||
}
|
||||
|
||||
/// https://marc.info/?l=openbsd-cvs&m=166602943014106&w=2
|
||||
#[test]
|
||||
#[cfg_attr(all(libressl360, not(libressl361)), ignore)]
|
||||
fn sign_verify_test_normal() {
|
||||
let cert = include_bytes!("../test/cert.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
let certs = Stack::new().unwrap();
|
||||
let message = "foo";
|
||||
let flags = Pkcs7Flags::STREAM;
|
||||
let pkey = include_bytes!("../test/key.pem");
|
||||
let pkey = PKey::private_key_from_pem(pkey).unwrap();
|
||||
let mut store_builder = X509StoreBuilder::new().expect("should succeed");
|
||||
|
||||
let root_ca = include_bytes!("../test/root-ca.pem");
|
||||
let root_ca = X509::from_pem(root_ca).unwrap();
|
||||
store_builder.add_cert(root_ca).expect("should succeed");
|
||||
|
||||
let store = store_builder.build();
|
||||
|
||||
let pkcs7 =
|
||||
Pkcs7::sign(&cert, &pkey, &certs, message.as_bytes(), flags).expect("should succeed");
|
||||
assert_eq!(
|
||||
pkcs7.type_().expect("PKCS7 should have a type").nid(),
|
||||
Nid::PKCS7_SIGNED
|
||||
);
|
||||
|
||||
let signed = pkcs7
|
||||
.to_smime(message.as_bytes(), flags)
|
||||
.expect("should succeed");
|
||||
|
||||
let (pkcs7_decoded, content) =
|
||||
Pkcs7::from_smime(signed.as_slice()).expect("should succeed");
|
||||
|
||||
let mut output = Vec::new();
|
||||
pkcs7_decoded
|
||||
.verify(&certs, &store, None, Some(&mut output), flags)
|
||||
.expect("should succeed");
|
||||
|
||||
assert_eq!(output, message.as_bytes());
|
||||
assert!(content.is_none());
|
||||
}
|
||||
|
||||
/// https://marc.info/?l=openbsd-cvs&m=166602943014106&w=2
|
||||
#[test]
|
||||
#[cfg_attr(all(libressl360, not(libressl361)), ignore)]
|
||||
fn signers() {
|
||||
let cert = include_bytes!("../test/cert.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
let cert_digest = cert.digest(MessageDigest::sha256()).unwrap();
|
||||
let certs = Stack::new().unwrap();
|
||||
let message = "foo";
|
||||
let flags = Pkcs7Flags::STREAM;
|
||||
let pkey = include_bytes!("../test/key.pem");
|
||||
let pkey = PKey::private_key_from_pem(pkey).unwrap();
|
||||
let mut store_builder = X509StoreBuilder::new().expect("should succeed");
|
||||
|
||||
let root_ca = include_bytes!("../test/root-ca.pem");
|
||||
let root_ca = X509::from_pem(root_ca).unwrap();
|
||||
store_builder.add_cert(root_ca).expect("should succeed");
|
||||
|
||||
let pkcs7 =
|
||||
Pkcs7::sign(&cert, &pkey, &certs, message.as_bytes(), flags).expect("should succeed");
|
||||
assert_eq!(
|
||||
pkcs7.type_().expect("PKCS7 should have a type").nid(),
|
||||
Nid::PKCS7_SIGNED
|
||||
);
|
||||
|
||||
let signed = pkcs7
|
||||
.to_smime(message.as_bytes(), flags)
|
||||
.expect("should succeed");
|
||||
|
||||
let (pkcs7_decoded, _) = Pkcs7::from_smime(signed.as_slice()).expect("should succeed");
|
||||
|
||||
let empty_certs = Stack::new().unwrap();
|
||||
let signer_certs = pkcs7_decoded
|
||||
.signers(&empty_certs, flags)
|
||||
.expect("should succeed");
|
||||
assert_eq!(empty_certs.len(), 0);
|
||||
assert_eq!(signer_certs.len(), 1);
|
||||
let signer_digest = signer_certs[0].digest(MessageDigest::sha256()).unwrap();
|
||||
assert_eq!(*cert_digest, *signer_digest);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_from_smime() {
|
||||
let input = String::from("Invalid SMIME Message");
|
||||
let result = Pkcs7::from_smime(input.as_bytes());
|
||||
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn signed_data_certificates() {
|
||||
let cert = include_bytes!("../test/cert.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
let mut extra_certs = Stack::<X509>::new().unwrap();
|
||||
for cert in
|
||||
X509::stack_from_pem(include_bytes!("../test/certs.pem")).expect("should succeed")
|
||||
{
|
||||
extra_certs.push(cert).expect("should succeed");
|
||||
}
|
||||
|
||||
let message = "foo";
|
||||
let flags = Pkcs7Flags::STREAM;
|
||||
let pkey = include_bytes!("../test/key.pem");
|
||||
let pkey = PKey::private_key_from_pem(pkey).unwrap();
|
||||
|
||||
let pkcs7 = Pkcs7::sign(&cert, &pkey, &extra_certs, message.as_bytes(), flags)
|
||||
.expect("should succeed");
|
||||
assert_eq!(
|
||||
pkcs7.type_().expect("PKCS7 should have a type").nid(),
|
||||
Nid::PKCS7_SIGNED
|
||||
);
|
||||
let signed_data_certs = pkcs7.signed().and_then(|x| x.certificates());
|
||||
assert_eq!(signed_data_certs.expect("should succeed").len(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn signed_data_certificates_no_signed_data() {
|
||||
let cert = include_bytes!("../test/certs.pem");
|
||||
let cert = X509::from_pem(cert).unwrap();
|
||||
let mut certs = Stack::new().unwrap();
|
||||
certs.push(cert).unwrap();
|
||||
let message: String = String::from("foo");
|
||||
let cipher = Cipher::des_ede3_cbc();
|
||||
let flags = Pkcs7Flags::STREAM;
|
||||
|
||||
// Use `Pkcs7::encrypt` since it populates the PKCS7_ENVELOPE struct rather than
|
||||
// PKCS7_SIGNED
|
||||
let pkcs7 =
|
||||
Pkcs7::encrypt(&certs, message.as_bytes(), cipher, flags).expect("should succeed");
|
||||
assert_eq!(
|
||||
pkcs7.type_().expect("PKCS7 should have a type").nid(),
|
||||
Nid::PKCS7_ENVELOPED
|
||||
);
|
||||
|
||||
let signed_data_certs = pkcs7.signed().and_then(|x| x.certificates());
|
||||
assert!(signed_data_certs.is_none())
|
||||
}
|
||||
}
|
||||
1202
vendor/openssl/src/pkey.rs
vendored
Normal file
1202
vendor/openssl/src/pkey.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
1110
vendor/openssl/src/pkey_ctx.rs
vendored
Normal file
1110
vendor/openssl/src/pkey_ctx.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
81
vendor/openssl/src/provider.rs
vendored
Normal file
81
vendor/openssl/src/provider.rs
vendored
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
use crate::error::ErrorStack;
|
||||
use crate::lib_ctx::LibCtxRef;
|
||||
use crate::{cvt, cvt_p};
|
||||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
use openssl_macros::corresponds;
|
||||
use std::ffi::CString;
|
||||
use std::ptr;
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::OSSL_PROVIDER;
|
||||
fn drop = ossl_provider_free;
|
||||
|
||||
pub struct Provider;
|
||||
/// A reference to a [`Provider`].
|
||||
pub struct ProviderRef;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn ossl_provider_free(p: *mut ffi::OSSL_PROVIDER) {
|
||||
ffi::OSSL_PROVIDER_unload(p);
|
||||
}
|
||||
|
||||
impl Provider {
|
||||
/// Loads a new provider into the specified library context, disabling the fallback providers.
|
||||
///
|
||||
/// If `ctx` is `None`, the provider will be loaded in to the default library context.
|
||||
#[corresponds(OSSL_provider_load)]
|
||||
pub fn load(ctx: Option<&LibCtxRef>, name: &str) -> Result<Self, ErrorStack> {
|
||||
let name = CString::new(name).unwrap();
|
||||
unsafe {
|
||||
let p = cvt_p(ffi::OSSL_PROVIDER_load(
|
||||
ctx.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr),
|
||||
name.as_ptr(),
|
||||
))?;
|
||||
|
||||
Ok(Provider::from_ptr(p))
|
||||
}
|
||||
}
|
||||
|
||||
/// Loads a new provider into the specified library context, disabling the fallback providers if `retain_fallbacks`
|
||||
/// is `false` and the load succeeds.
|
||||
///
|
||||
/// If `ctx` is `None`, the provider will be loaded into the default library context.
|
||||
#[corresponds(OSSL_provider_try_load)]
|
||||
pub fn try_load(
|
||||
ctx: Option<&LibCtxRef>,
|
||||
name: &str,
|
||||
retain_fallbacks: bool,
|
||||
) -> Result<Self, ErrorStack> {
|
||||
let name = CString::new(name).unwrap();
|
||||
unsafe {
|
||||
let p = cvt_p(ffi::OSSL_PROVIDER_try_load(
|
||||
ctx.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr),
|
||||
name.as_ptr(),
|
||||
retain_fallbacks as _,
|
||||
))?;
|
||||
|
||||
// OSSL_PROVIDER_try_load seems to leave errors on the stack, even
|
||||
// when it succeeds.
|
||||
let _ = ErrorStack::get();
|
||||
|
||||
Ok(Provider::from_ptr(p))
|
||||
}
|
||||
}
|
||||
|
||||
/// Specifies the default search path that is to be used for looking for providers in the specified library context.
|
||||
/// If left unspecified, an environment variable and a fall back default value will be used instead
|
||||
///
|
||||
/// If `ctx` is `None`, the provider will be loaded into the default library context.
|
||||
#[corresponds(OSSL_PROVIDER_set_default_search_path)]
|
||||
pub fn set_default_search_path(ctx: Option<&LibCtxRef>, path: &str) -> Result<(), ErrorStack> {
|
||||
let path = CString::new(path).unwrap();
|
||||
unsafe {
|
||||
cvt(ffi::OSSL_PROVIDER_set_default_search_path(
|
||||
ctx.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr),
|
||||
path.as_ptr(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
}
|
||||
90
vendor/openssl/src/rand.rs
vendored
Normal file
90
vendor/openssl/src/rand.rs
vendored
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
//! Utilities for secure random number generation.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! To generate a buffer with cryptographically strong bytes:
|
||||
//!
|
||||
//! ```
|
||||
//! use openssl::rand::rand_bytes;
|
||||
//!
|
||||
//! let mut buf = [0; 256];
|
||||
//! rand_bytes(&mut buf).unwrap();
|
||||
//! ```
|
||||
use libc::c_int;
|
||||
|
||||
use crate::error::ErrorStack;
|
||||
use crate::{cvt, LenType};
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
/// Fill buffer with cryptographically strong pseudo-random bytes.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// To generate a buffer with cryptographically strong random bytes:
|
||||
///
|
||||
/// ```
|
||||
/// use openssl::rand::rand_bytes;
|
||||
///
|
||||
/// let mut buf = [0; 256];
|
||||
/// rand_bytes(&mut buf).unwrap();
|
||||
/// ```
|
||||
#[corresponds(RAND_bytes)]
|
||||
pub fn rand_bytes(buf: &mut [u8]) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
ffi::init();
|
||||
assert!(buf.len() <= c_int::MAX as usize);
|
||||
cvt(ffi::RAND_bytes(buf.as_mut_ptr(), buf.len() as LenType)).map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Fill buffer with cryptographically strong pseudo-random bytes. It is
|
||||
/// intended to be used for generating values that should remain private.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// To generate a buffer with cryptographically strong random bytes:
|
||||
///
|
||||
/// ```
|
||||
/// use openssl::rand::rand_priv_bytes;
|
||||
///
|
||||
/// let mut buf = [0; 256];
|
||||
/// rand_priv_bytes(&mut buf).unwrap();
|
||||
/// ```
|
||||
///
|
||||
/// Requires OpenSSL 1.1.1 or newer.
|
||||
#[corresponds(RAND_priv_bytes)]
|
||||
#[cfg(ossl111)]
|
||||
pub fn rand_priv_bytes(buf: &mut [u8]) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
ffi::init();
|
||||
assert!(buf.len() <= c_int::MAX as usize);
|
||||
cvt(ffi::RAND_priv_bytes(buf.as_mut_ptr(), buf.len() as LenType)).map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Controls random device file descriptor behavior.
|
||||
///
|
||||
/// Requires OpenSSL 1.1.1 or newer.
|
||||
#[corresponds(RAND_keep_random_devices_open)]
|
||||
#[cfg(ossl111)]
|
||||
pub fn keep_random_devices_open(keep: bool) {
|
||||
unsafe {
|
||||
ffi::RAND_keep_random_devices_open(keep as LenType);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn test_rand_bytes() {
|
||||
let mut buf = [0; 32];
|
||||
super::rand_bytes(&mut buf).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl111)]
|
||||
fn test_rand_priv_bytes() {
|
||||
let mut buf = [0; 32];
|
||||
super::rand_priv_bytes(&mut buf).unwrap();
|
||||
}
|
||||
}
|
||||
873
vendor/openssl/src/rsa.rs
vendored
Normal file
873
vendor/openssl/src/rsa.rs
vendored
Normal file
|
|
@ -0,0 +1,873 @@
|
|||
//! Rivest–Shamir–Adleman cryptosystem
|
||||
//!
|
||||
//! RSA is one of the earliest asymmetric public key encryption schemes.
|
||||
//! Like many other cryptosystems, RSA relies on the presumed difficulty of a hard
|
||||
//! mathematical problem, namely factorization of the product of two large prime
|
||||
//! numbers. At the moment there does not exist an algorithm that can factor such
|
||||
//! large numbers in reasonable time. RSA is used in a wide variety of
|
||||
//! applications including digital signatures and key exchanges such as
|
||||
//! establishing a TLS/SSL connection.
|
||||
//!
|
||||
//! The RSA acronym is derived from the first letters of the surnames of the
|
||||
//! algorithm's founding trio.
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! Generate a 2048-bit RSA key pair and use the public key to encrypt some data.
|
||||
//!
|
||||
//! ```rust
|
||||
//! use openssl::rsa::{Rsa, Padding};
|
||||
//!
|
||||
//! let rsa = Rsa::generate(2048).unwrap();
|
||||
//! let data = b"foobar";
|
||||
//! let mut buf = vec![0; rsa.size() as usize];
|
||||
//! let encrypted_len = rsa.public_encrypt(data, &mut buf, Padding::PKCS1).unwrap();
|
||||
//! ```
|
||||
use cfg_if::cfg_if;
|
||||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
use libc::c_int;
|
||||
use std::fmt;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
|
||||
use crate::bn::{BigNum, BigNumRef};
|
||||
use crate::error::ErrorStack;
|
||||
use crate::pkey::{HasPrivate, HasPublic, Private, Public};
|
||||
use crate::util::ForeignTypeRefExt;
|
||||
use crate::{cvt, cvt_n, cvt_p, LenType};
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
/// Type of encryption padding to use.
|
||||
///
|
||||
/// Random length padding is primarily used to prevent attackers from
|
||||
/// predicting or knowing the exact length of a plaintext message that
|
||||
/// can possibly lead to breaking encryption.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct Padding(c_int);
|
||||
|
||||
impl Padding {
|
||||
pub const NONE: Padding = Padding(ffi::RSA_NO_PADDING);
|
||||
pub const PKCS1: Padding = Padding(ffi::RSA_PKCS1_PADDING);
|
||||
pub const PKCS1_OAEP: Padding = Padding(ffi::RSA_PKCS1_OAEP_PADDING);
|
||||
pub const PKCS1_PSS: Padding = Padding(ffi::RSA_PKCS1_PSS_PADDING);
|
||||
|
||||
/// Creates a `Padding` from an integer representation.
|
||||
pub fn from_raw(value: c_int) -> Padding {
|
||||
Padding(value)
|
||||
}
|
||||
|
||||
/// Returns the integer representation of `Padding`.
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub fn as_raw(&self) -> c_int {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
generic_foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::RSA;
|
||||
fn drop = ffi::RSA_free;
|
||||
|
||||
/// An RSA key.
|
||||
pub struct Rsa<T>;
|
||||
|
||||
/// Reference to `RSA`
|
||||
pub struct RsaRef<T>;
|
||||
}
|
||||
|
||||
impl<T> Clone for Rsa<T> {
|
||||
fn clone(&self) -> Rsa<T> {
|
||||
(**self).to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ToOwned for RsaRef<T> {
|
||||
type Owned = Rsa<T>;
|
||||
|
||||
fn to_owned(&self) -> Rsa<T> {
|
||||
unsafe {
|
||||
ffi::RSA_up_ref(self.as_ptr());
|
||||
Rsa::from_ptr(self.as_ptr())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> RsaRef<T>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
private_key_to_pem! {
|
||||
/// Serializes the private key to a PEM-encoded PKCS#1 RSAPrivateKey structure.
|
||||
///
|
||||
/// The output will have a header of `-----BEGIN RSA PRIVATE KEY-----`.
|
||||
#[corresponds(PEM_write_bio_RSAPrivateKey)]
|
||||
private_key_to_pem,
|
||||
/// Serializes the private key to a PEM-encoded encrypted PKCS#1 RSAPrivateKey structure.
|
||||
///
|
||||
/// The output will have a header of `-----BEGIN RSA PRIVATE KEY-----`.
|
||||
#[corresponds(PEM_write_bio_RSAPrivateKey)]
|
||||
private_key_to_pem_passphrase,
|
||||
ffi::PEM_write_bio_RSAPrivateKey
|
||||
}
|
||||
|
||||
to_der! {
|
||||
/// Serializes the private key to a DER-encoded PKCS#1 RSAPrivateKey structure.
|
||||
#[corresponds(i2d_RSAPrivateKey)]
|
||||
private_key_to_der,
|
||||
ffi::i2d_RSAPrivateKey
|
||||
}
|
||||
|
||||
/// 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()`.
|
||||
#[corresponds(RSA_private_decrypt)]
|
||||
pub fn private_decrypt(
|
||||
&self,
|
||||
from: &[u8],
|
||||
to: &mut [u8],
|
||||
padding: Padding,
|
||||
) -> Result<usize, ErrorStack> {
|
||||
assert!(from.len() <= i32::MAX as usize);
|
||||
assert!(to.len() >= self.size() as usize);
|
||||
|
||||
unsafe {
|
||||
let len = cvt_n(ffi::RSA_private_decrypt(
|
||||
from.len() as LenType,
|
||||
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()`.
|
||||
#[corresponds(RSA_private_encrypt)]
|
||||
pub fn private_encrypt(
|
||||
&self,
|
||||
from: &[u8],
|
||||
to: &mut [u8],
|
||||
padding: Padding,
|
||||
) -> Result<usize, ErrorStack> {
|
||||
assert!(from.len() <= i32::MAX as usize);
|
||||
assert!(to.len() >= self.size() as usize);
|
||||
|
||||
unsafe {
|
||||
let len = cvt_n(ffi::RSA_private_encrypt(
|
||||
from.len() as LenType,
|
||||
from.as_ptr(),
|
||||
to.as_mut_ptr(),
|
||||
self.as_ptr(),
|
||||
padding.0,
|
||||
))?;
|
||||
Ok(len as usize)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a reference to the private exponent of the key.
|
||||
#[corresponds(RSA_get0_key)]
|
||||
pub fn d(&self) -> &BigNumRef {
|
||||
unsafe {
|
||||
let mut d = ptr::null();
|
||||
RSA_get0_key(self.as_ptr(), ptr::null_mut(), ptr::null_mut(), &mut d);
|
||||
BigNumRef::from_const_ptr(d)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a reference to the first factor of the exponent of the key.
|
||||
#[corresponds(RSA_get0_factors)]
|
||||
pub fn p(&self) -> Option<&BigNumRef> {
|
||||
unsafe {
|
||||
let mut p = ptr::null();
|
||||
RSA_get0_factors(self.as_ptr(), &mut p, ptr::null_mut());
|
||||
BigNumRef::from_const_ptr_opt(p)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a reference to the second factor of the exponent of the key.
|
||||
#[corresponds(RSA_get0_factors)]
|
||||
pub fn q(&self) -> Option<&BigNumRef> {
|
||||
unsafe {
|
||||
let mut q = ptr::null();
|
||||
RSA_get0_factors(self.as_ptr(), ptr::null_mut(), &mut q);
|
||||
BigNumRef::from_const_ptr_opt(q)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a reference to the first exponent used for CRT calculations.
|
||||
#[corresponds(RSA_get0_crt_params)]
|
||||
pub fn dmp1(&self) -> Option<&BigNumRef> {
|
||||
unsafe {
|
||||
let mut dp = ptr::null();
|
||||
RSA_get0_crt_params(self.as_ptr(), &mut dp, ptr::null_mut(), ptr::null_mut());
|
||||
BigNumRef::from_const_ptr_opt(dp)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a reference to the second exponent used for CRT calculations.
|
||||
#[corresponds(RSA_get0_crt_params)]
|
||||
pub fn dmq1(&self) -> Option<&BigNumRef> {
|
||||
unsafe {
|
||||
let mut dq = ptr::null();
|
||||
RSA_get0_crt_params(self.as_ptr(), ptr::null_mut(), &mut dq, ptr::null_mut());
|
||||
BigNumRef::from_const_ptr_opt(dq)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a reference to the coefficient used for CRT calculations.
|
||||
#[corresponds(RSA_get0_crt_params)]
|
||||
pub fn iqmp(&self) -> Option<&BigNumRef> {
|
||||
unsafe {
|
||||
let mut qi = ptr::null();
|
||||
RSA_get0_crt_params(self.as_ptr(), ptr::null_mut(), ptr::null_mut(), &mut qi);
|
||||
BigNumRef::from_const_ptr_opt(qi)
|
||||
}
|
||||
}
|
||||
|
||||
/// Validates RSA parameters for correctness
|
||||
#[corresponds(RSA_check_key)]
|
||||
pub fn check_key(&self) -> Result<bool, ErrorStack> {
|
||||
unsafe {
|
||||
let result = ffi::RSA_check_key(self.as_ptr());
|
||||
if result != 1 {
|
||||
let errors = ErrorStack::get();
|
||||
if errors.errors().is_empty() {
|
||||
Ok(false)
|
||||
} else {
|
||||
Err(errors)
|
||||
}
|
||||
} else {
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> RsaRef<T>
|
||||
where
|
||||
T: HasPublic,
|
||||
{
|
||||
to_pem! {
|
||||
/// Serializes the public key into a PEM-encoded SubjectPublicKeyInfo structure.
|
||||
///
|
||||
/// The output will have a header of `-----BEGIN PUBLIC KEY-----`.
|
||||
#[corresponds(PEM_write_bio_RSA_PUBKEY)]
|
||||
public_key_to_pem,
|
||||
ffi::PEM_write_bio_RSA_PUBKEY
|
||||
}
|
||||
|
||||
to_der! {
|
||||
/// Serializes the public key into a DER-encoded SubjectPublicKeyInfo structure.
|
||||
#[corresponds(i2d_RSA_PUBKEY)]
|
||||
public_key_to_der,
|
||||
ffi::i2d_RSA_PUBKEY
|
||||
}
|
||||
|
||||
to_pem! {
|
||||
/// Serializes the public key into a PEM-encoded PKCS#1 RSAPublicKey structure.
|
||||
///
|
||||
/// The output will have a header of `-----BEGIN RSA PUBLIC KEY-----`.
|
||||
#[corresponds(PEM_write_bio_RSAPublicKey)]
|
||||
public_key_to_pem_pkcs1,
|
||||
ffi::PEM_write_bio_RSAPublicKey
|
||||
}
|
||||
|
||||
to_der! {
|
||||
/// Serializes the public key into a DER-encoded PKCS#1 RSAPublicKey structure.
|
||||
#[corresponds(i2d_RSAPublicKey)]
|
||||
public_key_to_der_pkcs1,
|
||||
ffi::i2d_RSAPublicKey
|
||||
}
|
||||
|
||||
/// Returns the size of the modulus in bytes.
|
||||
#[corresponds(RSA_size)]
|
||||
pub fn size(&self) -> u32 {
|
||||
unsafe { ffi::RSA_size(self.as_ptr()) as u32 }
|
||||
}
|
||||
|
||||
/// Decrypts data using the public key, returning the number of decrypted bytes.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `to` is smaller than `self.size()`.
|
||||
#[corresponds(RSA_public_decrypt)]
|
||||
pub fn public_decrypt(
|
||||
&self,
|
||||
from: &[u8],
|
||||
to: &mut [u8],
|
||||
padding: Padding,
|
||||
) -> Result<usize, ErrorStack> {
|
||||
assert!(from.len() <= i32::MAX as usize);
|
||||
assert!(to.len() >= self.size() as usize);
|
||||
|
||||
unsafe {
|
||||
let len = cvt_n(ffi::RSA_public_decrypt(
|
||||
from.len() as LenType,
|
||||
from.as_ptr(),
|
||||
to.as_mut_ptr(),
|
||||
self.as_ptr(),
|
||||
padding.0,
|
||||
))?;
|
||||
Ok(len as usize)
|
||||
}
|
||||
}
|
||||
|
||||
/// Encrypts data using the public key, returning the number of encrypted bytes.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `to` is smaller than `self.size()`.
|
||||
#[corresponds(RSA_public_encrypt)]
|
||||
pub fn public_encrypt(
|
||||
&self,
|
||||
from: &[u8],
|
||||
to: &mut [u8],
|
||||
padding: Padding,
|
||||
) -> Result<usize, ErrorStack> {
|
||||
assert!(from.len() <= i32::MAX as usize);
|
||||
assert!(to.len() >= self.size() as usize);
|
||||
|
||||
unsafe {
|
||||
let len = cvt_n(ffi::RSA_public_encrypt(
|
||||
from.len() as LenType,
|
||||
from.as_ptr(),
|
||||
to.as_mut_ptr(),
|
||||
self.as_ptr(),
|
||||
padding.0,
|
||||
))?;
|
||||
Ok(len as usize)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a reference to the modulus of the key.
|
||||
#[corresponds(RSA_get0_key)]
|
||||
pub fn n(&self) -> &BigNumRef {
|
||||
unsafe {
|
||||
let mut n = ptr::null();
|
||||
RSA_get0_key(self.as_ptr(), &mut n, ptr::null_mut(), ptr::null_mut());
|
||||
BigNumRef::from_const_ptr(n)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a reference to the public exponent of the key.
|
||||
#[corresponds(RSA_get0_key)]
|
||||
pub fn e(&self) -> &BigNumRef {
|
||||
unsafe {
|
||||
let mut e = ptr::null();
|
||||
RSA_get0_key(self.as_ptr(), ptr::null_mut(), &mut e, ptr::null_mut());
|
||||
BigNumRef::from_const_ptr(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Rsa<Public> {
|
||||
/// Creates a new RSA key with only public components.
|
||||
///
|
||||
/// `n` is the modulus common to both public and private key.
|
||||
/// `e` is the public exponent.
|
||||
///
|
||||
/// This corresponds to [`RSA_new`] and uses [`RSA_set0_key`].
|
||||
///
|
||||
/// [`RSA_new`]: https://www.openssl.org/docs/manmaster/crypto/RSA_new.html
|
||||
/// [`RSA_set0_key`]: https://www.openssl.org/docs/manmaster/crypto/RSA_set0_key.html
|
||||
pub fn from_public_components(n: BigNum, e: BigNum) -> Result<Rsa<Public>, ErrorStack> {
|
||||
unsafe {
|
||||
let rsa = cvt_p(ffi::RSA_new())?;
|
||||
RSA_set0_key(rsa, n.as_ptr(), e.as_ptr(), ptr::null_mut());
|
||||
mem::forget((n, e));
|
||||
Ok(Rsa::from_ptr(rsa))
|
||||
}
|
||||
}
|
||||
|
||||
from_pem! {
|
||||
/// Decodes a PEM-encoded SubjectPublicKeyInfo structure containing an RSA key.
|
||||
///
|
||||
/// The input should have a header of `-----BEGIN PUBLIC KEY-----`.
|
||||
#[corresponds(PEM_read_bio_RSA_PUBKEY)]
|
||||
public_key_from_pem,
|
||||
Rsa<Public>,
|
||||
ffi::PEM_read_bio_RSA_PUBKEY
|
||||
}
|
||||
|
||||
from_pem! {
|
||||
/// Decodes a PEM-encoded PKCS#1 RSAPublicKey structure.
|
||||
///
|
||||
/// The input should have a header of `-----BEGIN RSA PUBLIC KEY-----`.
|
||||
#[corresponds(PEM_read_bio_RSAPublicKey)]
|
||||
public_key_from_pem_pkcs1,
|
||||
Rsa<Public>,
|
||||
ffi::PEM_read_bio_RSAPublicKey
|
||||
}
|
||||
|
||||
from_der! {
|
||||
/// Decodes a DER-encoded SubjectPublicKeyInfo structure containing an RSA key.
|
||||
#[corresponds(d2i_RSA_PUBKEY)]
|
||||
public_key_from_der,
|
||||
Rsa<Public>,
|
||||
ffi::d2i_RSA_PUBKEY
|
||||
}
|
||||
|
||||
from_der! {
|
||||
/// Decodes a DER-encoded PKCS#1 RSAPublicKey structure.
|
||||
#[corresponds(d2i_RSAPublicKey)]
|
||||
public_key_from_der_pkcs1,
|
||||
Rsa<Public>,
|
||||
ffi::d2i_RSAPublicKey
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RsaPrivateKeyBuilder {
|
||||
rsa: Rsa<Private>,
|
||||
}
|
||||
|
||||
impl RsaPrivateKeyBuilder {
|
||||
/// Creates a new `RsaPrivateKeyBuilder`.
|
||||
///
|
||||
/// `n` is the modulus common to both public and private key.
|
||||
/// `e` is the public exponent and `d` is the private exponent.
|
||||
///
|
||||
/// This corresponds to [`RSA_new`] and uses [`RSA_set0_key`].
|
||||
///
|
||||
/// [`RSA_new`]: https://www.openssl.org/docs/manmaster/crypto/RSA_new.html
|
||||
/// [`RSA_set0_key`]: https://www.openssl.org/docs/manmaster/crypto/RSA_set0_key.html
|
||||
pub fn new(n: BigNum, e: BigNum, d: BigNum) -> Result<RsaPrivateKeyBuilder, ErrorStack> {
|
||||
unsafe {
|
||||
let rsa = cvt_p(ffi::RSA_new())?;
|
||||
RSA_set0_key(rsa, n.as_ptr(), e.as_ptr(), d.as_ptr());
|
||||
mem::forget((n, e, d));
|
||||
Ok(RsaPrivateKeyBuilder {
|
||||
rsa: Rsa::from_ptr(rsa),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the factors of the Rsa key.
|
||||
///
|
||||
/// `p` and `q` are the first and second factors of `n`.
|
||||
#[corresponds(RSA_set0_factors)]
|
||||
// FIXME should be infallible
|
||||
pub fn set_factors(self, p: BigNum, q: BigNum) -> Result<RsaPrivateKeyBuilder, ErrorStack> {
|
||||
unsafe {
|
||||
RSA_set0_factors(self.rsa.as_ptr(), p.as_ptr(), q.as_ptr());
|
||||
mem::forget((p, q));
|
||||
}
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Sets the Chinese Remainder Theorem params of the Rsa key.
|
||||
///
|
||||
/// `dmp1`, `dmq1`, and `iqmp` are the exponents and coefficient for
|
||||
/// CRT calculations which is used to speed up RSA operations.
|
||||
#[corresponds(RSA_set0_crt_params)]
|
||||
// FIXME should be infallible
|
||||
pub fn set_crt_params(
|
||||
self,
|
||||
dmp1: BigNum,
|
||||
dmq1: BigNum,
|
||||
iqmp: BigNum,
|
||||
) -> Result<RsaPrivateKeyBuilder, ErrorStack> {
|
||||
unsafe {
|
||||
RSA_set0_crt_params(
|
||||
self.rsa.as_ptr(),
|
||||
dmp1.as_ptr(),
|
||||
dmq1.as_ptr(),
|
||||
iqmp.as_ptr(),
|
||||
);
|
||||
mem::forget((dmp1, dmq1, iqmp));
|
||||
}
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
/// Returns the Rsa key.
|
||||
pub fn build(self) -> Rsa<Private> {
|
||||
self.rsa
|
||||
}
|
||||
}
|
||||
|
||||
impl Rsa<Private> {
|
||||
/// Creates a new RSA key with private components (public components are assumed).
|
||||
///
|
||||
/// This a convenience method over:
|
||||
/// ```
|
||||
/// # use openssl::rsa::RsaPrivateKeyBuilder;
|
||||
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// # let bn = || openssl::bn::BigNum::new().unwrap();
|
||||
/// # let (n, e, d, p, q, dmp1, dmq1, iqmp) = (bn(), bn(), bn(), bn(), bn(), bn(), bn(), bn());
|
||||
/// RsaPrivateKeyBuilder::new(n, e, d)?
|
||||
/// .set_factors(p, q)?
|
||||
/// .set_crt_params(dmp1, dmq1, iqmp)?
|
||||
/// .build();
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
#[allow(clippy::too_many_arguments, clippy::many_single_char_names)]
|
||||
pub fn from_private_components(
|
||||
n: BigNum,
|
||||
e: BigNum,
|
||||
d: BigNum,
|
||||
p: BigNum,
|
||||
q: BigNum,
|
||||
dmp1: BigNum,
|
||||
dmq1: BigNum,
|
||||
iqmp: BigNum,
|
||||
) -> Result<Rsa<Private>, ErrorStack> {
|
||||
Ok(RsaPrivateKeyBuilder::new(n, e, d)?
|
||||
.set_factors(p, q)?
|
||||
.set_crt_params(dmp1, dmq1, iqmp)?
|
||||
.build())
|
||||
}
|
||||
|
||||
/// Generates a public/private key pair with the specified size.
|
||||
///
|
||||
/// The public exponent will be 65537.
|
||||
#[corresponds(RSA_generate_key_ex)]
|
||||
pub fn generate(bits: u32) -> Result<Rsa<Private>, ErrorStack> {
|
||||
let e = BigNum::from_u32(ffi::RSA_F4 as u32)?;
|
||||
Rsa::generate_with_e(bits, &e)
|
||||
}
|
||||
|
||||
/// Generates a public/private key pair with the specified size and a custom exponent.
|
||||
///
|
||||
/// Unless you have specific needs and know what you're doing, use `Rsa::generate` instead.
|
||||
#[corresponds(RSA_generate_key_ex)]
|
||||
pub fn generate_with_e(bits: u32, e: &BigNumRef) -> Result<Rsa<Private>, ErrorStack> {
|
||||
unsafe {
|
||||
let rsa = Rsa::from_ptr(cvt_p(ffi::RSA_new())?);
|
||||
cvt(ffi::RSA_generate_key_ex(
|
||||
rsa.0,
|
||||
bits as c_int,
|
||||
e.as_ptr(),
|
||||
ptr::null_mut(),
|
||||
))?;
|
||||
Ok(rsa)
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME these need to identify input formats
|
||||
private_key_from_pem! {
|
||||
/// Deserializes a private key from a PEM-encoded PKCS#1 RSAPrivateKey structure.
|
||||
#[corresponds(PEM_read_bio_RSAPrivateKey)]
|
||||
private_key_from_pem,
|
||||
|
||||
/// Deserializes a private key from a PEM-encoded encrypted PKCS#1 RSAPrivateKey structure.
|
||||
#[corresponds(PEM_read_bio_RSAPrivateKey)]
|
||||
private_key_from_pem_passphrase,
|
||||
|
||||
/// Deserializes a private key from a PEM-encoded encrypted PKCS#1 RSAPrivateKey structure.
|
||||
///
|
||||
/// The callback should fill the password into the provided buffer and return its length.
|
||||
#[corresponds(PEM_read_bio_RSAPrivateKey)]
|
||||
private_key_from_pem_callback,
|
||||
Rsa<Private>,
|
||||
ffi::PEM_read_bio_RSAPrivateKey
|
||||
}
|
||||
|
||||
from_der! {
|
||||
/// Decodes a DER-encoded PKCS#1 RSAPrivateKey structure.
|
||||
#[corresponds(d2i_RSAPrivateKey)]
|
||||
private_key_from_der,
|
||||
Rsa<Private>,
|
||||
ffi::d2i_RSAPrivateKey
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> fmt::Debug for Rsa<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "Rsa")
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl110, libressl273, boringssl))] {
|
||||
use ffi::{
|
||||
RSA_get0_key, RSA_get0_factors, RSA_get0_crt_params, RSA_set0_key, RSA_set0_factors,
|
||||
RSA_set0_crt_params,
|
||||
};
|
||||
} else {
|
||||
#[allow(bad_style)]
|
||||
unsafe fn RSA_get0_key(
|
||||
r: *const ffi::RSA,
|
||||
n: *mut *const ffi::BIGNUM,
|
||||
e: *mut *const ffi::BIGNUM,
|
||||
d: *mut *const ffi::BIGNUM,
|
||||
) {
|
||||
if !n.is_null() {
|
||||
*n = (*r).n;
|
||||
}
|
||||
if !e.is_null() {
|
||||
*e = (*r).e;
|
||||
}
|
||||
if !d.is_null() {
|
||||
*d = (*r).d;
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn RSA_get0_factors(
|
||||
r: *const ffi::RSA,
|
||||
p: *mut *const ffi::BIGNUM,
|
||||
q: *mut *const ffi::BIGNUM,
|
||||
) {
|
||||
if !p.is_null() {
|
||||
*p = (*r).p;
|
||||
}
|
||||
if !q.is_null() {
|
||||
*q = (*r).q;
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn RSA_get0_crt_params(
|
||||
r: *const ffi::RSA,
|
||||
dmp1: *mut *const ffi::BIGNUM,
|
||||
dmq1: *mut *const ffi::BIGNUM,
|
||||
iqmp: *mut *const ffi::BIGNUM,
|
||||
) {
|
||||
if !dmp1.is_null() {
|
||||
*dmp1 = (*r).dmp1;
|
||||
}
|
||||
if !dmq1.is_null() {
|
||||
*dmq1 = (*r).dmq1;
|
||||
}
|
||||
if !iqmp.is_null() {
|
||||
*iqmp = (*r).iqmp;
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn RSA_set0_key(
|
||||
r: *mut ffi::RSA,
|
||||
n: *mut ffi::BIGNUM,
|
||||
e: *mut ffi::BIGNUM,
|
||||
d: *mut ffi::BIGNUM,
|
||||
) -> c_int {
|
||||
(*r).n = n;
|
||||
(*r).e = e;
|
||||
(*r).d = d;
|
||||
1
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn RSA_set0_factors(
|
||||
r: *mut ffi::RSA,
|
||||
p: *mut ffi::BIGNUM,
|
||||
q: *mut ffi::BIGNUM,
|
||||
) -> c_int {
|
||||
(*r).p = p;
|
||||
(*r).q = q;
|
||||
1
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn RSA_set0_crt_params(
|
||||
r: *mut ffi::RSA,
|
||||
dmp1: *mut ffi::BIGNUM,
|
||||
dmq1: *mut ffi::BIGNUM,
|
||||
iqmp: *mut ffi::BIGNUM,
|
||||
) -> c_int {
|
||||
(*r).dmp1 = dmp1;
|
||||
(*r).dmq1 = dmq1;
|
||||
(*r).iqmp = iqmp;
|
||||
1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::symm::Cipher;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_from_password() {
|
||||
let key = include_bytes!("../test/rsa-encrypted.pem");
|
||||
Rsa::private_key_from_pem_passphrase(key, b"mypass").unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_password_callback() {
|
||||
let mut password_queried = false;
|
||||
let key = include_bytes!("../test/rsa-encrypted.pem");
|
||||
Rsa::private_key_from_pem_callback(key, |password| {
|
||||
password_queried = true;
|
||||
password[..6].copy_from_slice(b"mypass");
|
||||
Ok(6)
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
assert!(password_queried);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_password() {
|
||||
let key = Rsa::generate(2048).unwrap();
|
||||
let pem = key
|
||||
.private_key_to_pem_passphrase(Cipher::aes_128_cbc(), b"foobar")
|
||||
.unwrap();
|
||||
Rsa::private_key_from_pem_passphrase(&pem, b"foobar").unwrap();
|
||||
assert!(Rsa::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
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() as usize];
|
||||
let original_data = b"This is test";
|
||||
let len = public_key
|
||||
.public_encrypt(original_data, &mut result, Padding::PKCS1)
|
||||
.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() as usize];
|
||||
let len = private_key
|
||||
.private_decrypt(&result, &mut dec_result, Padding::PKCS1)
|
||||
.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() as usize];
|
||||
k0.private_encrypt(&msg, &mut emesg, Padding::PKCS1)
|
||||
.unwrap();
|
||||
let mut dmesg = vec![0; k1.size() as usize];
|
||||
let len = k1
|
||||
.public_decrypt(&emesg, &mut dmesg, Padding::PKCS1)
|
||||
.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() as usize];
|
||||
k0.public_encrypt(&msg, &mut emesg, Padding::PKCS1).unwrap();
|
||||
let mut dmesg = vec![0; k1.size() as usize];
|
||||
let len = k1
|
||||
.private_decrypt(&emesg, &mut dmesg, Padding::PKCS1)
|
||||
.unwrap();
|
||||
assert_eq!(msg, &dmesg[..len]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_public_key_from_pem_pkcs1() {
|
||||
let key = include_bytes!("../test/pkcs1.pem.pub");
|
||||
Rsa::public_key_from_pem_pkcs1(key).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_public_key_from_pem_pkcs1_file_panic() {
|
||||
let key = include_bytes!("../test/key.pem.pub");
|
||||
Rsa::public_key_from_pem_pkcs1(key).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_public_key_to_pem_pkcs1() {
|
||||
let keypair = super::Rsa::generate(512).unwrap();
|
||||
let pubkey_pem = keypair.public_key_to_pem_pkcs1().unwrap();
|
||||
super::Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_public_key_from_pem_pkcs1_generate_panic() {
|
||||
let keypair = super::Rsa::generate(512).unwrap();
|
||||
let pubkey_pem = keypair.public_key_to_pem().unwrap();
|
||||
super::Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pem_pkcs1_encrypt() {
|
||||
let keypair = super::Rsa::generate(2048).unwrap();
|
||||
let pubkey_pem = keypair.public_key_to_pem_pkcs1().unwrap();
|
||||
let pubkey = super::Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap();
|
||||
let msg = b"Hello, world!";
|
||||
|
||||
let mut encrypted = vec![0; pubkey.size() as usize];
|
||||
let len = pubkey
|
||||
.public_encrypt(msg, &mut encrypted, Padding::PKCS1)
|
||||
.unwrap();
|
||||
assert!(len > msg.len());
|
||||
let mut decrypted = vec![0; keypair.size() as usize];
|
||||
let len = keypair
|
||||
.private_decrypt(&encrypted, &mut decrypted, Padding::PKCS1)
|
||||
.unwrap();
|
||||
assert_eq!(len, msg.len());
|
||||
assert_eq!(&decrypted[..len], msg);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pem_pkcs1_padding() {
|
||||
let keypair = super::Rsa::generate(2048).unwrap();
|
||||
let pubkey_pem = keypair.public_key_to_pem_pkcs1().unwrap();
|
||||
let pubkey = super::Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap();
|
||||
let msg = b"foo";
|
||||
|
||||
let mut encrypted1 = vec![0; pubkey.size() as usize];
|
||||
let mut encrypted2 = vec![0; pubkey.size() as usize];
|
||||
let len1 = pubkey
|
||||
.public_encrypt(msg, &mut encrypted1, Padding::PKCS1)
|
||||
.unwrap();
|
||||
let len2 = pubkey
|
||||
.public_encrypt(msg, &mut encrypted2, Padding::PKCS1)
|
||||
.unwrap();
|
||||
assert!(len1 > (msg.len() + 1));
|
||||
assert_eq!(len1, len2);
|
||||
assert_ne!(encrypted1, encrypted2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(clippy::redundant_clone)]
|
||||
fn clone() {
|
||||
let key = Rsa::generate(2048).unwrap();
|
||||
drop(key.clone());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generate_with_e() {
|
||||
let e = BigNum::from_u32(0x10001).unwrap();
|
||||
Rsa::generate_with_e(2048, &e).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_check_key() {
|
||||
let k = Rsa::private_key_from_pem_passphrase(
|
||||
include_bytes!("../test/rsa-encrypted.pem"),
|
||||
b"mypass",
|
||||
)
|
||||
.unwrap();
|
||||
assert!(matches!(k.check_key(), Ok(true)));
|
||||
assert!(ErrorStack::get().errors().is_empty());
|
||||
|
||||
// BoringSSL simply rejects this key, because its corrupted!
|
||||
if let Ok(k) = Rsa::private_key_from_pem(include_bytes!("../test/corrupted-rsa.pem")) {
|
||||
assert!(matches!(k.check_key(), Ok(false) | Err(_)));
|
||||
assert!(ErrorStack::get().errors().is_empty());
|
||||
}
|
||||
}
|
||||
}
|
||||
463
vendor/openssl/src/sha.rs
vendored
Normal file
463
vendor/openssl/src/sha.rs
vendored
Normal file
|
|
@ -0,0 +1,463 @@
|
|||
//! The SHA family of hashes.
|
||||
//!
|
||||
//! SHA, or Secure Hash Algorithms, are a family of cryptographic hashing algorithms published by
|
||||
//! the National Institute of Standards and Technology (NIST). Hash algorithms such as those in
|
||||
//! the SHA family are used to map data of an arbitrary size to a fixed-size string of bytes.
|
||||
//! As cryptographic hashing algorithms, these mappings have the property of being irreversible.
|
||||
//! This property makes hash algorithms like these excellent for uses such as verifying the
|
||||
//! contents of a file- if you know the hash you expect beforehand, then you can verify that the
|
||||
//! data you have is correct if it hashes to the same value.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! When dealing with data that becomes available in chunks, such as while buffering data from IO,
|
||||
//! you can create a hasher that you can repeatedly update to add bytes to.
|
||||
//!
|
||||
//! ```rust
|
||||
//! use openssl::sha;
|
||||
//!
|
||||
//! let mut hasher = sha::Sha256::new();
|
||||
//!
|
||||
//! hasher.update(b"Hello, ");
|
||||
//! hasher.update(b"world");
|
||||
//!
|
||||
//! let hash = hasher.finish();
|
||||
//! println!("Hashed \"Hello, world\" to {}", hex::encode(hash));
|
||||
//! ```
|
||||
//!
|
||||
//! On the other hand, if you already have access to all of the data you would like to hash, you
|
||||
//! may prefer to use the slightly simpler method of simply calling the hash function corresponding
|
||||
//! to the algorithm you want to use.
|
||||
//!
|
||||
//! ```rust
|
||||
//! use openssl::sha::sha256;
|
||||
//!
|
||||
//! let hash = sha256(b"your data or message");
|
||||
//! println!("Hash = {}", hex::encode(hash));
|
||||
//! ```
|
||||
use cfg_if::cfg_if;
|
||||
use libc::c_void;
|
||||
use openssl_macros::corresponds;
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
/// Computes the SHA1 hash of some data.
|
||||
///
|
||||
/// # Warning
|
||||
///
|
||||
/// SHA1 is known to be insecure - it should not be used unless required for
|
||||
/// compatibility with existing systems.
|
||||
#[corresponds(SHA1)]
|
||||
#[inline]
|
||||
pub fn sha1(data: &[u8]) -> [u8; 20] {
|
||||
unsafe {
|
||||
let mut hash = MaybeUninit::<[u8; 20]>::uninit();
|
||||
ffi::SHA1(data.as_ptr(), data.len(), hash.as_mut_ptr() as *mut _);
|
||||
hash.assume_init()
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the SHA224 hash of some data.
|
||||
#[corresponds(SHA224)]
|
||||
#[inline]
|
||||
pub fn sha224(data: &[u8]) -> [u8; 28] {
|
||||
unsafe {
|
||||
let mut hash = MaybeUninit::<[u8; 28]>::uninit();
|
||||
ffi::SHA224(data.as_ptr(), data.len(), hash.as_mut_ptr() as *mut _);
|
||||
hash.assume_init()
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the SHA256 hash of some data.
|
||||
#[corresponds(SHA256)]
|
||||
#[inline]
|
||||
pub fn sha256(data: &[u8]) -> [u8; 32] {
|
||||
unsafe {
|
||||
let mut hash = MaybeUninit::<[u8; 32]>::uninit();
|
||||
ffi::SHA256(data.as_ptr(), data.len(), hash.as_mut_ptr() as *mut _);
|
||||
hash.assume_init()
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the SHA384 hash of some data.
|
||||
#[corresponds(SHA384)]
|
||||
#[inline]
|
||||
pub fn sha384(data: &[u8]) -> [u8; 48] {
|
||||
unsafe {
|
||||
let mut hash = MaybeUninit::<[u8; 48]>::uninit();
|
||||
ffi::SHA384(data.as_ptr(), data.len(), hash.as_mut_ptr() as *mut _);
|
||||
hash.assume_init()
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes the SHA512 hash of some data.
|
||||
#[corresponds(SHA512)]
|
||||
#[inline]
|
||||
pub fn sha512(data: &[u8]) -> [u8; 64] {
|
||||
unsafe {
|
||||
let mut hash = MaybeUninit::<[u8; 64]>::uninit();
|
||||
ffi::SHA512(data.as_ptr(), data.len(), hash.as_mut_ptr() as *mut _);
|
||||
hash.assume_init()
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))] {
|
||||
/// An object which calculates a SHA1 hash of some data.
|
||||
///
|
||||
/// # Warning
|
||||
///
|
||||
/// SHA1 is known to be insecure - it should not be used unless required for
|
||||
/// compatibility with existing systems.
|
||||
#[derive(Clone)]
|
||||
pub struct Sha1(ffi::SHA_CTX);
|
||||
|
||||
impl Default for Sha1 {
|
||||
#[inline]
|
||||
fn default() -> Sha1 {
|
||||
Sha1::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Sha1 {
|
||||
/// Creates a new hasher.
|
||||
#[corresponds(SHA1_Init)]
|
||||
#[inline]
|
||||
pub fn new() -> Sha1 {
|
||||
unsafe {
|
||||
let mut ctx = MaybeUninit::uninit();
|
||||
ffi::SHA1_Init( ctx.as_mut_ptr());
|
||||
Sha1(ctx.assume_init())
|
||||
}
|
||||
}
|
||||
|
||||
/// Feeds some data into the hasher.
|
||||
///
|
||||
/// This can be called multiple times.
|
||||
#[corresponds(SHA1_Update)]
|
||||
#[inline]
|
||||
pub fn update(&mut self, buf: &[u8]) {
|
||||
unsafe {
|
||||
ffi::SHA1_Update(&mut self.0, buf.as_ptr() as *const c_void, buf.len());
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the hash of the data.
|
||||
#[corresponds(SHA1_Final)]
|
||||
#[inline]
|
||||
pub fn finish(mut self) -> [u8; 20] {
|
||||
unsafe {
|
||||
let mut hash = MaybeUninit::<[u8; 20]>::uninit();
|
||||
ffi::SHA1_Final(hash.as_mut_ptr() as *mut _, &mut self.0);
|
||||
hash.assume_init()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An object which calculates a SHA224 hash of some data.
|
||||
#[derive(Clone)]
|
||||
pub struct Sha224(ffi::SHA256_CTX);
|
||||
|
||||
impl Default for Sha224 {
|
||||
#[inline]
|
||||
fn default() -> Sha224 {
|
||||
Sha224::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Sha224 {
|
||||
/// Creates a new hasher.
|
||||
#[corresponds(SHA224_Init)]
|
||||
#[inline]
|
||||
pub fn new() -> Sha224 {
|
||||
unsafe {
|
||||
let mut ctx = MaybeUninit::uninit();
|
||||
ffi::SHA224_Init(ctx.as_mut_ptr());
|
||||
Sha224(ctx.assume_init())
|
||||
}
|
||||
}
|
||||
|
||||
/// Feeds some data into the hasher.
|
||||
///
|
||||
/// This can be called multiple times.
|
||||
#[corresponds(SHA224_Update)]
|
||||
#[inline]
|
||||
pub fn update(&mut self, buf: &[u8]) {
|
||||
unsafe {
|
||||
ffi::SHA224_Update(&mut self.0, buf.as_ptr() as *const c_void, buf.len());
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the hash of the data.
|
||||
#[corresponds(SHA224_Final)]
|
||||
#[inline]
|
||||
pub fn finish(mut self) -> [u8; 28] {
|
||||
unsafe {
|
||||
let mut hash = MaybeUninit::<[u8; 28]>::uninit();
|
||||
ffi::SHA224_Final(hash.as_mut_ptr() as *mut _, &mut self.0);
|
||||
hash.assume_init()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An object which calculates a SHA256 hash of some data.
|
||||
#[derive(Clone)]
|
||||
pub struct Sha256(ffi::SHA256_CTX);
|
||||
|
||||
impl Default for Sha256 {
|
||||
#[inline]
|
||||
fn default() -> Sha256 {
|
||||
Sha256::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Sha256 {
|
||||
/// Creates a new hasher.
|
||||
#[corresponds(SHA256_Init)]
|
||||
#[inline]
|
||||
pub fn new() -> Sha256 {
|
||||
unsafe {
|
||||
let mut ctx = MaybeUninit::uninit();
|
||||
ffi::SHA256_Init(ctx.as_mut_ptr());
|
||||
Sha256(ctx.assume_init())
|
||||
}
|
||||
}
|
||||
|
||||
/// Feeds some data into the hasher.
|
||||
///
|
||||
/// This can be called multiple times.
|
||||
#[corresponds(SHA256_Update)]
|
||||
#[inline]
|
||||
pub fn update(&mut self, buf: &[u8]) {
|
||||
unsafe {
|
||||
ffi::SHA256_Update(&mut self.0, buf.as_ptr() as *const c_void, buf.len());
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the hash of the data.
|
||||
#[corresponds(SHA256_Final)]
|
||||
#[inline]
|
||||
pub fn finish(mut self) -> [u8; 32] {
|
||||
unsafe {
|
||||
let mut hash = MaybeUninit::<[u8; 32]>::uninit();
|
||||
ffi::SHA256_Final(hash.as_mut_ptr() as *mut _, &mut self.0);
|
||||
hash.assume_init()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An object which calculates a SHA384 hash of some data.
|
||||
#[derive(Clone)]
|
||||
pub struct Sha384(ffi::SHA512_CTX);
|
||||
|
||||
impl Default for Sha384 {
|
||||
#[inline]
|
||||
fn default() -> Sha384 {
|
||||
Sha384::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Sha384 {
|
||||
/// Creates a new hasher.
|
||||
#[corresponds(SHA384_Init)]
|
||||
#[inline]
|
||||
pub fn new() -> Sha384 {
|
||||
unsafe {
|
||||
let mut ctx = MaybeUninit::uninit();
|
||||
ffi::SHA384_Init(ctx.as_mut_ptr());
|
||||
Sha384(ctx.assume_init())
|
||||
}
|
||||
}
|
||||
|
||||
/// Feeds some data into the hasher.
|
||||
///
|
||||
/// This can be called multiple times.
|
||||
#[corresponds(SHA384_Update)]
|
||||
#[inline]
|
||||
pub fn update(&mut self, buf: &[u8]) {
|
||||
unsafe {
|
||||
ffi::SHA384_Update(&mut self.0, buf.as_ptr() as *const c_void, buf.len());
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the hash of the data.
|
||||
#[corresponds(SHA384_Final)]
|
||||
#[inline]
|
||||
pub fn finish(mut self) -> [u8; 48] {
|
||||
unsafe {
|
||||
let mut hash = MaybeUninit::<[u8; 48]>::uninit();
|
||||
ffi::SHA384_Final(hash.as_mut_ptr() as *mut _, &mut self.0);
|
||||
hash.assume_init()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An object which calculates a SHA512 hash of some data.
|
||||
#[derive(Clone)]
|
||||
pub struct Sha512(ffi::SHA512_CTX);
|
||||
|
||||
impl Default for Sha512 {
|
||||
#[inline]
|
||||
fn default() -> Sha512 {
|
||||
Sha512::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Sha512 {
|
||||
/// Creates a new hasher.
|
||||
#[corresponds(SHA512_Init)]
|
||||
#[inline]
|
||||
pub fn new() -> Sha512 {
|
||||
unsafe {
|
||||
let mut ctx = MaybeUninit::uninit();
|
||||
ffi::SHA512_Init(ctx.as_mut_ptr());
|
||||
Sha512(ctx.assume_init())
|
||||
}
|
||||
}
|
||||
|
||||
/// Feeds some data into the hasher.
|
||||
///
|
||||
/// This can be called multiple times.
|
||||
#[corresponds(SHA512_Update)]
|
||||
#[inline]
|
||||
pub fn update(&mut self, buf: &[u8]) {
|
||||
unsafe {
|
||||
ffi::SHA512_Update(&mut self.0, buf.as_ptr() as *const c_void, buf.len());
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the hash of the data.
|
||||
#[corresponds(SHA512_Final)]
|
||||
#[inline]
|
||||
pub fn finish(mut self) -> [u8; 64] {
|
||||
unsafe {
|
||||
let mut hash= MaybeUninit::<[u8; 64]>::uninit();
|
||||
ffi::SHA512_Final(hash.as_mut_ptr() as *mut _, &mut self.0);
|
||||
hash.assume_init()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn standalone_1() {
|
||||
let data = b"abc";
|
||||
let expected = "a9993e364706816aba3e25717850c26c9cd0d89d";
|
||||
|
||||
assert_eq!(hex::encode(sha1(data)), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
|
||||
fn struct_1() {
|
||||
let expected = "a9993e364706816aba3e25717850c26c9cd0d89d";
|
||||
|
||||
let mut hasher = Sha1::new();
|
||||
hasher.update(b"a");
|
||||
hasher.update(b"bc");
|
||||
assert_eq!(hex::encode(hasher.finish()), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
|
||||
fn cloning_allows_incremental_hashing() {
|
||||
let expected = "a9993e364706816aba3e25717850c26c9cd0d89d";
|
||||
|
||||
let mut hasher = Sha1::new();
|
||||
hasher.update(b"a");
|
||||
|
||||
let mut incr_hasher = hasher.clone();
|
||||
incr_hasher.update(b"bc");
|
||||
|
||||
assert_eq!(hex::encode(incr_hasher.finish()), expected);
|
||||
assert_ne!(hex::encode(hasher.finish()), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn standalone_224() {
|
||||
let data = b"abc";
|
||||
let expected = "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7";
|
||||
|
||||
assert_eq!(hex::encode(sha224(data)), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
|
||||
fn struct_224() {
|
||||
let expected = "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7";
|
||||
|
||||
let mut hasher = Sha224::new();
|
||||
hasher.update(b"a");
|
||||
hasher.update(b"bc");
|
||||
assert_eq!(hex::encode(hasher.finish()), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn standalone_256() {
|
||||
let data = b"abc";
|
||||
let expected = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad";
|
||||
|
||||
assert_eq!(hex::encode(sha256(data)), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
|
||||
fn struct_256() {
|
||||
let expected = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad";
|
||||
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(b"a");
|
||||
hasher.update(b"bc");
|
||||
assert_eq!(hex::encode(hasher.finish()), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn standalone_384() {
|
||||
let data = b"abc";
|
||||
let expected =
|
||||
"cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e\
|
||||
7cc2358baeca134c825a7";
|
||||
|
||||
assert_eq!(hex::encode(&sha384(data)[..]), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
|
||||
fn struct_384() {
|
||||
let expected =
|
||||
"cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e\
|
||||
7cc2358baeca134c825a7";
|
||||
|
||||
let mut hasher = Sha384::new();
|
||||
hasher.update(b"a");
|
||||
hasher.update(b"bc");
|
||||
assert_eq!(hex::encode(&hasher.finish()[..]), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn standalone_512() {
|
||||
let data = b"abc";
|
||||
let expected =
|
||||
"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274\
|
||||
fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f";
|
||||
|
||||
assert_eq!(hex::encode(&sha512(data)[..]), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_DEPRECATED_3_0"))]
|
||||
fn struct_512() {
|
||||
let expected =
|
||||
"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274\
|
||||
fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f";
|
||||
|
||||
let mut hasher = Sha512::new();
|
||||
hasher.update(b"a");
|
||||
hasher.update(b"bc");
|
||||
assert_eq!(hex::encode(&hasher.finish()[..]), expected);
|
||||
}
|
||||
}
|
||||
834
vendor/openssl/src/sign.rs
vendored
Normal file
834
vendor/openssl/src/sign.rs
vendored
Normal file
|
|
@ -0,0 +1,834 @@
|
|||
//! 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.sign_to_vec().unwrap();
|
||||
//!
|
||||
//! // Verify the data
|
||||
//! let mut verifier = Verifier::new(MessageDigest::sha256(), &keypair).unwrap();
|
||||
//! verifier.update(data).unwrap();
|
||||
//! verifier.update(data2).unwrap();
|
||||
//! assert!(verifier.verify(&signature).unwrap());
|
||||
//! ```
|
||||
|
||||
#![cfg_attr(
|
||||
not(boringssl),
|
||||
doc = r#"\
|
||||
|
||||
Compute an HMAC:
|
||||
|
||||
```rust
|
||||
use openssl::hash::MessageDigest;
|
||||
use openssl::memcmp;
|
||||
use openssl::pkey::PKey;
|
||||
use openssl::sign::Signer;
|
||||
|
||||
// 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.sign_to_vec().unwrap();
|
||||
|
||||
// `Verifier` cannot be used with HMACs; use the `memcmp::eq` function instead
|
||||
//
|
||||
// Do not simply check for equality with `==`!
|
||||
# let target = hmac.clone();
|
||||
assert!(memcmp::eq(&hmac, &target));
|
||||
```"#
|
||||
)]
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
use foreign_types::ForeignTypeRef;
|
||||
use libc::c_int;
|
||||
use std::io::{self, Write};
|
||||
use std::marker::PhantomData;
|
||||
use std::ptr;
|
||||
|
||||
use crate::error::ErrorStack;
|
||||
use crate::hash::MessageDigest;
|
||||
use crate::pkey::{HasPrivate, HasPublic, PKeyRef};
|
||||
use crate::rsa::Padding;
|
||||
use crate::{cvt, cvt_p};
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl110, libressl382))] {
|
||||
use ffi::{EVP_MD_CTX_free, EVP_MD_CTX_new};
|
||||
} else {
|
||||
use ffi::{EVP_MD_CTX_create as EVP_MD_CTX_new, EVP_MD_CTX_destroy as EVP_MD_CTX_free};
|
||||
}
|
||||
}
|
||||
|
||||
/// Salt lengths that must be used with `set_rsa_pss_saltlen`.
|
||||
pub struct RsaPssSaltlen(c_int);
|
||||
|
||||
impl RsaPssSaltlen {
|
||||
/// Returns the integer representation of `RsaPssSaltlen`.
|
||||
pub(crate) fn as_raw(&self) -> c_int {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Sets the salt length to the given value.
|
||||
pub fn custom(val: c_int) -> RsaPssSaltlen {
|
||||
RsaPssSaltlen(val)
|
||||
}
|
||||
|
||||
/// The salt length is set to the digest length.
|
||||
/// Corresponds to the special value `-1`.
|
||||
pub const DIGEST_LENGTH: RsaPssSaltlen = RsaPssSaltlen(-1);
|
||||
/// The salt length is set to the maximum permissible value.
|
||||
/// Corresponds to the special value `-2`.
|
||||
pub const MAXIMUM_LENGTH: RsaPssSaltlen = RsaPssSaltlen(-2);
|
||||
}
|
||||
|
||||
/// A type which computes cryptographic signatures of data.
|
||||
pub struct Signer<'a> {
|
||||
md_ctx: *mut ffi::EVP_MD_CTX,
|
||||
pctx: *mut ffi::EVP_PKEY_CTX,
|
||||
_p: PhantomData<&'a ()>,
|
||||
}
|
||||
|
||||
unsafe impl Sync for Signer<'_> {}
|
||||
unsafe impl Send for Signer<'_> {}
|
||||
|
||||
impl Drop for Signer<'_> {
|
||||
fn drop(&mut self) {
|
||||
// pkey_ctx is owned by the md_ctx, so no need to explicitly free it.
|
||||
unsafe {
|
||||
EVP_MD_CTX_free(self.md_ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::len_without_is_empty)]
|
||||
impl Signer<'_> {
|
||||
/// Creates a new `Signer`.
|
||||
///
|
||||
/// This cannot be used with Ed25519 or Ed448 keys. Please refer to
|
||||
/// `new_without_digest`.
|
||||
#[corresponds(EVP_DigestSignInit)]
|
||||
pub fn new<'a, T>(type_: MessageDigest, pkey: &PKeyRef<T>) -> Result<Signer<'a>, ErrorStack>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
Self::new_intern(Some(type_), pkey)
|
||||
}
|
||||
|
||||
/// Creates a new `Signer` without a digest.
|
||||
///
|
||||
/// This is the only way to create a `Verifier` for Ed25519 or Ed448 keys.
|
||||
/// It can also be used to create a CMAC.
|
||||
#[corresponds(EVP_DigestSignInit)]
|
||||
pub fn new_without_digest<'a, T>(pkey: &PKeyRef<T>) -> Result<Signer<'a>, ErrorStack>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
Self::new_intern(None, pkey)
|
||||
}
|
||||
|
||||
fn new_intern<'a, T>(
|
||||
type_: Option<MessageDigest>,
|
||||
pkey: &PKeyRef<T>,
|
||||
) -> Result<Signer<'a>, ErrorStack>
|
||||
where
|
||||
T: HasPrivate,
|
||||
{
|
||||
unsafe {
|
||||
ffi::init();
|
||||
|
||||
let ctx = cvt_p(EVP_MD_CTX_new())?;
|
||||
let mut pctx: *mut ffi::EVP_PKEY_CTX = ptr::null_mut();
|
||||
let r = ffi::EVP_DigestSignInit(
|
||||
ctx,
|
||||
&mut pctx,
|
||||
type_.map(|t| t.as_ptr()).unwrap_or(ptr::null()),
|
||||
ptr::null_mut(),
|
||||
pkey.as_ptr(),
|
||||
);
|
||||
if r != 1 {
|
||||
EVP_MD_CTX_free(ctx);
|
||||
return Err(ErrorStack::get());
|
||||
}
|
||||
|
||||
assert!(!pctx.is_null());
|
||||
|
||||
Ok(Signer {
|
||||
md_ctx: ctx,
|
||||
pctx,
|
||||
_p: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the RSA padding mode in use.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
#[corresponds(EVP_PKEY_CTX_get_rsa_padding)]
|
||||
pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> {
|
||||
unsafe {
|
||||
let mut pad = 0;
|
||||
cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.pctx, &mut pad))
|
||||
.map(|_| Padding::from_raw(pad))
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the RSA padding mode.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
#[corresponds(EVP_PKEY_CTX_set_rsa_padding)]
|
||||
pub fn set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_rsa_padding(
|
||||
self.pctx,
|
||||
padding.as_raw(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the RSA PSS salt length.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
#[corresponds(EVP_PKEY_CTX_set_rsa_pss_saltlen)]
|
||||
pub fn set_rsa_pss_saltlen(&mut self, len: RsaPssSaltlen) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_rsa_pss_saltlen(
|
||||
self.pctx,
|
||||
len.as_raw(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the RSA MGF1 algorithm.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
#[corresponds(EVP_PKEY_CTX_set_rsa_mgf1_md)]
|
||||
pub fn set_rsa_mgf1_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_rsa_mgf1_md(
|
||||
self.pctx,
|
||||
md.as_ptr() as *mut _,
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Feeds more data into the `Signer`.
|
||||
///
|
||||
/// Please note that PureEdDSA (Ed25519 and Ed448 keys) do not support streaming.
|
||||
/// Use `sign_oneshot` instead.
|
||||
#[corresponds(EVP_DigestUpdate)]
|
||||
pub fn update(&mut self, buf: &[u8]) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_DigestUpdate(
|
||||
self.md_ctx,
|
||||
buf.as_ptr() as *const _,
|
||||
buf.len(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Computes an upper bound on the signature length.
|
||||
///
|
||||
/// The actual signature may be shorter than this value. Check the return value of
|
||||
/// `sign` to get the exact length.
|
||||
#[corresponds(EVP_DigestSignFinal)]
|
||||
pub fn len(&self) -> Result<usize, ErrorStack> {
|
||||
self.len_intern()
|
||||
}
|
||||
|
||||
#[cfg(all(not(ossl111), not(boringssl), not(libressl370)))]
|
||||
fn len_intern(&self) -> Result<usize, ErrorStack> {
|
||||
unsafe {
|
||||
let mut len = 0;
|
||||
cvt(ffi::EVP_DigestSignFinal(
|
||||
self.md_ctx,
|
||||
ptr::null_mut(),
|
||||
&mut len,
|
||||
))?;
|
||||
Ok(len)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(ossl111, boringssl, libressl370))]
|
||||
fn len_intern(&self) -> Result<usize, ErrorStack> {
|
||||
unsafe {
|
||||
let mut len = 0;
|
||||
cvt(ffi::EVP_DigestSign(
|
||||
self.md_ctx,
|
||||
ptr::null_mut(),
|
||||
&mut len,
|
||||
ptr::null(),
|
||||
0,
|
||||
))?;
|
||||
Ok(len)
|
||||
}
|
||||
}
|
||||
|
||||
/// Writes the signature into the provided buffer, returning the number of bytes written.
|
||||
///
|
||||
/// This method will fail if the buffer is not large enough for the signature. Use the `len`
|
||||
/// method to get an upper bound on the required size.
|
||||
#[corresponds(EVP_DigestSignFinal)]
|
||||
pub fn sign(&self, buf: &mut [u8]) -> Result<usize, ErrorStack> {
|
||||
unsafe {
|
||||
let mut len = buf.len();
|
||||
cvt(ffi::EVP_DigestSignFinal(
|
||||
self.md_ctx,
|
||||
buf.as_mut_ptr() as *mut _,
|
||||
&mut len,
|
||||
))?;
|
||||
Ok(len)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the signature.
|
||||
///
|
||||
/// This is a simple convenience wrapper over `len` and `sign`.
|
||||
pub fn sign_to_vec(&self) -> Result<Vec<u8>, ErrorStack> {
|
||||
let mut buf = vec![0; self.len()?];
|
||||
let len = self.sign(&mut buf)?;
|
||||
// The advertised length is not always equal to the real length for things like DSA
|
||||
buf.truncate(len);
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
/// Signs the data in `data_buf` and writes the signature into the buffer `sig_buf`, returning the
|
||||
/// number of bytes written.
|
||||
///
|
||||
/// For PureEdDSA (Ed25519 and Ed448 keys), this is the only way to sign data.
|
||||
///
|
||||
/// This method will fail if the buffer is not large enough for the signature. Use the `len`
|
||||
/// method to get an upper bound on the required size.
|
||||
#[corresponds(EVP_DigestSign)]
|
||||
#[cfg(any(ossl111, boringssl, libressl370))]
|
||||
pub fn sign_oneshot(
|
||||
&mut self,
|
||||
sig_buf: &mut [u8],
|
||||
data_buf: &[u8],
|
||||
) -> Result<usize, ErrorStack> {
|
||||
unsafe {
|
||||
let mut sig_len = sig_buf.len();
|
||||
cvt(ffi::EVP_DigestSign(
|
||||
self.md_ctx,
|
||||
sig_buf.as_mut_ptr() as *mut _,
|
||||
&mut sig_len,
|
||||
data_buf.as_ptr() as *const _,
|
||||
data_buf.len(),
|
||||
))?;
|
||||
Ok(sig_len)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the signature.
|
||||
///
|
||||
/// This is a simple convenience wrapper over `len` and `sign_oneshot`.
|
||||
#[cfg(any(ossl111, boringssl, libressl370))]
|
||||
pub fn sign_oneshot_to_vec(&mut self, data_buf: &[u8]) -> Result<Vec<u8>, ErrorStack> {
|
||||
let mut sig_buf = vec![0; self.len()?];
|
||||
let len = self.sign_oneshot(&mut sig_buf, data_buf)?;
|
||||
// The advertised length is not always equal to the real length for things like DSA
|
||||
sig_buf.truncate(len);
|
||||
Ok(sig_buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for Signer<'_> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.update(buf)?;
|
||||
Ok(buf.len())
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// A type which can be used to verify the integrity and authenticity
|
||||
/// of data given the signature.
|
||||
pub struct Verifier<'a> {
|
||||
md_ctx: *mut ffi::EVP_MD_CTX,
|
||||
pctx: *mut ffi::EVP_PKEY_CTX,
|
||||
pkey_pd: PhantomData<&'a ()>,
|
||||
}
|
||||
|
||||
unsafe impl Sync for Verifier<'_> {}
|
||||
unsafe impl Send for Verifier<'_> {}
|
||||
|
||||
impl Drop for Verifier<'_> {
|
||||
fn drop(&mut self) {
|
||||
// pkey_ctx is owned by the md_ctx, so no need to explicitly free it.
|
||||
unsafe {
|
||||
EVP_MD_CTX_free(self.md_ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A type which verifies cryptographic signatures of data.
|
||||
impl<'a> Verifier<'a> {
|
||||
/// Creates a new `Verifier`.
|
||||
///
|
||||
/// This cannot be used with Ed25519 or Ed448 keys. Please refer to
|
||||
/// [`Verifier::new_without_digest`].
|
||||
#[corresponds(EVP_DigestVerifyInit)]
|
||||
pub fn new<T>(type_: MessageDigest, pkey: &'a PKeyRef<T>) -> Result<Verifier<'a>, ErrorStack>
|
||||
where
|
||||
T: HasPublic,
|
||||
{
|
||||
Verifier::new_intern(Some(type_), pkey)
|
||||
}
|
||||
|
||||
/// Creates a new `Verifier` without a digest.
|
||||
///
|
||||
/// This is the only way to create a `Verifier` for Ed25519 or Ed448 keys.
|
||||
#[corresponds(EVP_DigestVerifyInit)]
|
||||
pub fn new_without_digest<T>(pkey: &'a PKeyRef<T>) -> Result<Verifier<'a>, ErrorStack>
|
||||
where
|
||||
T: HasPublic,
|
||||
{
|
||||
Verifier::new_intern(None, pkey)
|
||||
}
|
||||
|
||||
fn new_intern<T>(
|
||||
type_: Option<MessageDigest>,
|
||||
pkey: &'a PKeyRef<T>,
|
||||
) -> Result<Verifier<'a>, ErrorStack>
|
||||
where
|
||||
T: HasPublic,
|
||||
{
|
||||
unsafe {
|
||||
ffi::init();
|
||||
|
||||
let ctx = cvt_p(EVP_MD_CTX_new())?;
|
||||
let mut pctx: *mut ffi::EVP_PKEY_CTX = ptr::null_mut();
|
||||
let r = ffi::EVP_DigestVerifyInit(
|
||||
ctx,
|
||||
&mut pctx,
|
||||
type_.map(|t| t.as_ptr()).unwrap_or(ptr::null()),
|
||||
ptr::null_mut(),
|
||||
pkey.as_ptr(),
|
||||
);
|
||||
if r != 1 {
|
||||
EVP_MD_CTX_free(ctx);
|
||||
return Err(ErrorStack::get());
|
||||
}
|
||||
|
||||
assert!(!pctx.is_null());
|
||||
|
||||
Ok(Verifier {
|
||||
md_ctx: ctx,
|
||||
pctx,
|
||||
pkey_pd: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the RSA padding mode in use.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
#[corresponds(EVP_PKEY_CTX_get_rsa_padding)]
|
||||
pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> {
|
||||
unsafe {
|
||||
let mut pad = 0;
|
||||
cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.pctx, &mut pad))
|
||||
.map(|_| Padding::from_raw(pad))
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the RSA padding mode.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
#[corresponds(EVP_PKEY_CTX_set_rsa_padding)]
|
||||
pub fn set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_rsa_padding(
|
||||
self.pctx,
|
||||
padding.as_raw(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the RSA PSS salt length.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
#[corresponds(EVP_PKEY_CTX_set_rsa_pss_saltlen)]
|
||||
pub fn set_rsa_pss_saltlen(&mut self, len: RsaPssSaltlen) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_rsa_pss_saltlen(
|
||||
self.pctx,
|
||||
len.as_raw(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the RSA MGF1 algorithm.
|
||||
///
|
||||
/// This is only useful for RSA keys.
|
||||
#[corresponds(EVP_PKEY_CTX_set_rsa_mgf1_md)]
|
||||
pub fn set_rsa_mgf1_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_PKEY_CTX_set_rsa_mgf1_md(
|
||||
self.pctx,
|
||||
md.as_ptr() as *mut _,
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Feeds more data into the `Verifier`.
|
||||
///
|
||||
/// Please note that PureEdDSA (Ed25519 and Ed448 keys) do not support streaming.
|
||||
/// Use [`Verifier::verify_oneshot`] instead.
|
||||
#[corresponds(EVP_DigestUpdate)]
|
||||
pub fn update(&mut self, buf: &[u8]) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_DigestUpdate(
|
||||
self.md_ctx,
|
||||
buf.as_ptr() as *const _,
|
||||
buf.len(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Determines if the data fed into the `Verifier` matches the provided signature.
|
||||
#[corresponds(EVP_DigestVerifyFinal)]
|
||||
pub fn verify(&self, signature: &[u8]) -> Result<bool, ErrorStack> {
|
||||
unsafe {
|
||||
let r =
|
||||
EVP_DigestVerifyFinal(self.md_ctx, signature.as_ptr() as *mut _, signature.len());
|
||||
match r {
|
||||
1 => Ok(true),
|
||||
0 => {
|
||||
ErrorStack::get(); // discard error stack
|
||||
Ok(false)
|
||||
}
|
||||
_ => Err(ErrorStack::get()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Determines if the data given in `buf` matches the provided signature.
|
||||
#[corresponds(EVP_DigestVerify)]
|
||||
#[cfg(any(ossl111, boringssl, libressl370))]
|
||||
pub fn verify_oneshot(&mut self, signature: &[u8], buf: &[u8]) -> Result<bool, ErrorStack> {
|
||||
unsafe {
|
||||
let r = ffi::EVP_DigestVerify(
|
||||
self.md_ctx,
|
||||
signature.as_ptr() as *const _,
|
||||
signature.len(),
|
||||
buf.as_ptr() as *const _,
|
||||
buf.len(),
|
||||
);
|
||||
match r {
|
||||
1 => Ok(true),
|
||||
0 => {
|
||||
ErrorStack::get();
|
||||
Ok(false)
|
||||
}
|
||||
_ => Err(ErrorStack::get()),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for Verifier<'_> {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
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 hex::{self, FromHex};
|
||||
#[cfg(not(boringssl))]
|
||||
use std::iter;
|
||||
|
||||
use crate::ec::{EcGroup, EcKey};
|
||||
use crate::hash::MessageDigest;
|
||||
use crate::nid::Nid;
|
||||
use crate::pkey::PKey;
|
||||
use crate::rsa::{Padding, Rsa};
|
||||
#[cfg(ossl111)]
|
||||
use crate::sign::RsaPssSaltlen;
|
||||
use crate::sign::{Signer, Verifier};
|
||||
|
||||
const INPUT: &str =
|
||||
"65794a68624763694f694a53557a49314e694a392e65794a7063334d694f694a71623255694c41304b49434a6c\
|
||||
654841694f6a457a4d4441344d546b7a4f44417344516f67496d6830644841364c79396c654746746347786c4c\
|
||||
6d4e76625339706331397962323930496a7030636e566c6651";
|
||||
|
||||
const SIGNATURE: &str =
|
||||
"702e218943e88fd11eb5d82dbf7845f34106ae1b81fff7731116add1717d83656d420afd3c96eedd73a2663e51\
|
||||
66687b000b87226e0187ed1073f945e582adfcef16d85a798ee8c66ddb3db8975b17d09402beedd5d9d9700710\
|
||||
8db28160d5f8040ca7445762b81fbe7ff9d92e0ae76f24f25b33bbe6f44ae61eb1040acb20044d3ef9128ed401\
|
||||
30795bd4bd3b41eecad066ab651981fde48df77f372dc38b9fafdd3befb18b5da3cc3c2eb02f9e3a41d612caad\
|
||||
15911273a05f23b9e838faaf849d698429ef5a1e88798236c3d40e604522a544c8f27a7a2db80663d16cf7caea\
|
||||
56de405cb2215a45b2c25566b55ac1a748a070dfc8a32a469543d019eefb47";
|
||||
|
||||
#[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();
|
||||
assert_eq!(signer.rsa_padding().unwrap(), Padding::PKCS1);
|
||||
signer.set_rsa_padding(Padding::PKCS1).unwrap();
|
||||
signer.update(&Vec::from_hex(INPUT).unwrap()).unwrap();
|
||||
let result = signer.sign_to_vec().unwrap();
|
||||
|
||||
assert_eq!(hex::encode(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();
|
||||
assert_eq!(verifier.rsa_padding().unwrap(), Padding::PKCS1);
|
||||
verifier.update(&Vec::from_hex(INPUT).unwrap()).unwrap();
|
||||
assert!(verifier.verify(&Vec::from_hex(SIGNATURE).unwrap()).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(&Vec::from_hex(INPUT).unwrap()).unwrap();
|
||||
verifier.update(b"foobar").unwrap();
|
||||
assert!(!verifier.verify(&Vec::from_hex(SIGNATURE).unwrap()).unwrap());
|
||||
}
|
||||
|
||||
#[cfg(not(boringssl))]
|
||||
fn test_hmac(ty: MessageDigest, tests: &[(Vec<u8>, Vec<u8>, Vec<u8>)]) {
|
||||
for (key, data, 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.sign_to_vec().unwrap(), *res);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(boringssl))]
|
||||
fn hmac_md5() {
|
||||
// test vectors from RFC 2202
|
||||
let tests: [(Vec<u8>, Vec<u8>, Vec<u8>); 7] = [
|
||||
(
|
||||
iter::repeat(0x0b_u8).take(16).collect(),
|
||||
b"Hi There".to_vec(),
|
||||
Vec::from_hex("9294727a3638bb1c13f48ef8158bfc9d").unwrap(),
|
||||
),
|
||||
(
|
||||
b"Jefe".to_vec(),
|
||||
b"what do ya want for nothing?".to_vec(),
|
||||
Vec::from_hex("750c783e6ab0b503eaa86e310a5db738").unwrap(),
|
||||
),
|
||||
(
|
||||
iter::repeat(0xaa_u8).take(16).collect(),
|
||||
iter::repeat(0xdd_u8).take(50).collect(),
|
||||
Vec::from_hex("56be34521d144c88dbb8c733f0e8b3f6").unwrap(),
|
||||
),
|
||||
(
|
||||
Vec::from_hex("0102030405060708090a0b0c0d0e0f10111213141516171819").unwrap(),
|
||||
iter::repeat(0xcd_u8).take(50).collect(),
|
||||
Vec::from_hex("697eaf0aca3a3aea3a75164746ffaa79").unwrap(),
|
||||
),
|
||||
(
|
||||
iter::repeat(0x0c_u8).take(16).collect(),
|
||||
b"Test With Truncation".to_vec(),
|
||||
Vec::from_hex("56461ef2342edc00f9bab995690efd4c").unwrap(),
|
||||
),
|
||||
(
|
||||
iter::repeat(0xaa_u8).take(80).collect(),
|
||||
b"Test Using Larger Than Block-Size Key - Hash Key First".to_vec(),
|
||||
Vec::from_hex("6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd").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(),
|
||||
Vec::from_hex("6f630fad67cda0ee1fb1f562db3aa53e").unwrap(),
|
||||
),
|
||||
];
|
||||
|
||||
test_hmac(MessageDigest::md5(), &tests);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(boringssl))]
|
||||
fn hmac_sha1() {
|
||||
// test vectors from RFC 2202
|
||||
let tests: [(Vec<u8>, Vec<u8>, Vec<u8>); 7] = [
|
||||
(
|
||||
iter::repeat(0x0b_u8).take(20).collect(),
|
||||
b"Hi There".to_vec(),
|
||||
Vec::from_hex("b617318655057264e28bc0b6fb378c8ef146be00").unwrap(),
|
||||
),
|
||||
(
|
||||
b"Jefe".to_vec(),
|
||||
b"what do ya want for nothing?".to_vec(),
|
||||
Vec::from_hex("effcdf6ae5eb2fa2d27416d5f184df9c259a7c79").unwrap(),
|
||||
),
|
||||
(
|
||||
iter::repeat(0xaa_u8).take(20).collect(),
|
||||
iter::repeat(0xdd_u8).take(50).collect(),
|
||||
Vec::from_hex("125d7342b9ac11cd91a39af48aa17b4f63f175d3").unwrap(),
|
||||
),
|
||||
(
|
||||
Vec::from_hex("0102030405060708090a0b0c0d0e0f10111213141516171819").unwrap(),
|
||||
iter::repeat(0xcd_u8).take(50).collect(),
|
||||
Vec::from_hex("4c9007f4026250c6bc8414f9bf50c86c2d7235da").unwrap(),
|
||||
),
|
||||
(
|
||||
iter::repeat(0x0c_u8).take(20).collect(),
|
||||
b"Test With Truncation".to_vec(),
|
||||
Vec::from_hex("4c1a03424b55e07fe7f27be1d58bb9324a9a5a04").unwrap(),
|
||||
),
|
||||
(
|
||||
iter::repeat(0xaa_u8).take(80).collect(),
|
||||
b"Test Using Larger Than Block-Size Key - Hash Key First".to_vec(),
|
||||
Vec::from_hex("aa4ae5e15272d00e95705637ce8a3b55ed402112").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(),
|
||||
Vec::from_hex("e8e99d0f45237d786d6bbaa7965c7808bbff1a91").unwrap(),
|
||||
),
|
||||
];
|
||||
|
||||
test_hmac(MessageDigest::sha1(), &tests);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl110)]
|
||||
fn test_cmac() {
|
||||
let cipher = crate::symm::Cipher::aes_128_cbc();
|
||||
let key = Vec::from_hex("9294727a3638bb1c13f48ef8158bfc9d").unwrap();
|
||||
let pkey = PKey::cmac(&cipher, &key).unwrap();
|
||||
let mut signer = Signer::new_without_digest(&pkey).unwrap();
|
||||
|
||||
let data = b"Hi There";
|
||||
signer.update(data as &[u8]).unwrap();
|
||||
|
||||
let expected = vec![
|
||||
136, 101, 61, 167, 61, 30, 248, 234, 124, 166, 196, 157, 203, 52, 171, 19,
|
||||
];
|
||||
assert_eq!(signer.sign_to_vec().unwrap(), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ec() {
|
||||
let group = EcGroup::from_curve_name(Nid::X9_62_PRIME256V1).unwrap();
|
||||
let key = EcKey::generate(&group).unwrap();
|
||||
let key = PKey::from_ec_key(key).unwrap();
|
||||
|
||||
let mut signer = Signer::new(MessageDigest::sha256(), &key).unwrap();
|
||||
signer.update(b"hello world").unwrap();
|
||||
let signature = signer.sign_to_vec().unwrap();
|
||||
|
||||
let mut verifier = Verifier::new(MessageDigest::sha256(), &key).unwrap();
|
||||
verifier.update(b"hello world").unwrap();
|
||||
assert!(verifier.verify(&signature).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(ossl111, boringssl, libressl370))]
|
||||
fn eddsa() {
|
||||
let key = PKey::generate_ed25519().unwrap();
|
||||
|
||||
let mut signer = Signer::new_without_digest(&key).unwrap();
|
||||
let signature = signer.sign_oneshot_to_vec(b"hello world").unwrap();
|
||||
|
||||
let mut verifier = Verifier::new_without_digest(&key).unwrap();
|
||||
assert!(verifier.verify_oneshot(&signature, b"hello world").unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(ossl111)]
|
||||
fn rsa_sign_verify() {
|
||||
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.set_rsa_padding(Padding::PKCS1_PSS).unwrap();
|
||||
assert_eq!(signer.rsa_padding().unwrap(), Padding::PKCS1_PSS);
|
||||
signer
|
||||
.set_rsa_pss_saltlen(RsaPssSaltlen::DIGEST_LENGTH)
|
||||
.unwrap();
|
||||
signer.set_rsa_mgf1_md(MessageDigest::sha256()).unwrap();
|
||||
signer.update(&Vec::from_hex(INPUT).unwrap()).unwrap();
|
||||
let signature = signer.sign_to_vec().unwrap();
|
||||
|
||||
let mut verifier = Verifier::new(MessageDigest::sha256(), &pkey).unwrap();
|
||||
verifier.set_rsa_padding(Padding::PKCS1_PSS).unwrap();
|
||||
verifier
|
||||
.set_rsa_pss_saltlen(RsaPssSaltlen::DIGEST_LENGTH)
|
||||
.unwrap();
|
||||
verifier.set_rsa_mgf1_md(MessageDigest::sha256()).unwrap();
|
||||
verifier.update(&Vec::from_hex(INPUT).unwrap()).unwrap();
|
||||
assert!(verifier.verify(&signature).unwrap());
|
||||
}
|
||||
}
|
||||
66
vendor/openssl/src/srtp.rs
vendored
Normal file
66
vendor/openssl/src/srtp.rs
vendored
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
use crate::stack::Stackable;
|
||||
use foreign_types::ForeignTypeRef;
|
||||
use libc::c_ulong;
|
||||
use std::ffi::CStr;
|
||||
use std::str;
|
||||
|
||||
/// fake free method, since SRTP_PROTECTION_PROFILE is static
|
||||
unsafe fn free(_profile: *mut ffi::SRTP_PROTECTION_PROFILE) {}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::SRTP_PROTECTION_PROFILE;
|
||||
fn drop = free;
|
||||
|
||||
pub struct SrtpProtectionProfile;
|
||||
/// Reference to `SrtpProtectionProfile`.
|
||||
pub struct SrtpProtectionProfileRef;
|
||||
}
|
||||
|
||||
impl Stackable for SrtpProtectionProfile {
|
||||
type StackType = ffi::stack_st_SRTP_PROTECTION_PROFILE;
|
||||
}
|
||||
|
||||
impl SrtpProtectionProfileRef {
|
||||
pub fn id(&self) -> SrtpProfileId {
|
||||
SrtpProfileId::from_raw(unsafe { (*self.as_ptr()).id })
|
||||
}
|
||||
pub fn name(&self) -> &'static str {
|
||||
unsafe { CStr::from_ptr((*self.as_ptr()).name as *const _) }
|
||||
.to_str()
|
||||
.expect("should be UTF-8")
|
||||
}
|
||||
}
|
||||
|
||||
/// An identifier of an SRTP protection profile.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct SrtpProfileId(c_ulong);
|
||||
|
||||
impl SrtpProfileId {
|
||||
pub const SRTP_AES128_CM_SHA1_80: SrtpProfileId =
|
||||
SrtpProfileId(ffi::SRTP_AES128_CM_SHA1_80 as c_ulong);
|
||||
pub const SRTP_AES128_CM_SHA1_32: SrtpProfileId =
|
||||
SrtpProfileId(ffi::SRTP_AES128_CM_SHA1_32 as c_ulong);
|
||||
pub const SRTP_AES128_F8_SHA1_80: SrtpProfileId =
|
||||
SrtpProfileId(ffi::SRTP_AES128_F8_SHA1_80 as c_ulong);
|
||||
pub const SRTP_AES128_F8_SHA1_32: SrtpProfileId =
|
||||
SrtpProfileId(ffi::SRTP_AES128_F8_SHA1_32 as c_ulong);
|
||||
pub const SRTP_NULL_SHA1_80: SrtpProfileId = SrtpProfileId(ffi::SRTP_NULL_SHA1_80 as c_ulong);
|
||||
pub const SRTP_NULL_SHA1_32: SrtpProfileId = SrtpProfileId(ffi::SRTP_NULL_SHA1_32 as c_ulong);
|
||||
#[cfg(any(boringssl, ossl110))]
|
||||
pub const SRTP_AEAD_AES_128_GCM: SrtpProfileId =
|
||||
SrtpProfileId(ffi::SRTP_AEAD_AES_128_GCM as c_ulong);
|
||||
#[cfg(any(boringssl, ossl110))]
|
||||
pub const SRTP_AEAD_AES_256_GCM: SrtpProfileId =
|
||||
SrtpProfileId(ffi::SRTP_AEAD_AES_256_GCM as c_ulong);
|
||||
|
||||
/// Creates a `SrtpProfileId` from an integer representation.
|
||||
pub fn from_raw(value: c_ulong) -> SrtpProfileId {
|
||||
SrtpProfileId(value)
|
||||
}
|
||||
|
||||
/// Returns the integer representation of `SrtpProfileId`.
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub fn as_raw(&self) -> c_ulong {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
289
vendor/openssl/src/ssl/bio.rs
vendored
Normal file
289
vendor/openssl/src/ssl/bio.rs
vendored
Normal file
|
|
@ -0,0 +1,289 @@
|
|||
use cfg_if::cfg_if;
|
||||
use ffi::{
|
||||
self, BIO_clear_retry_flags, BIO_new, BIO_set_retry_read, BIO_set_retry_write, BIO,
|
||||
BIO_CTRL_DGRAM_QUERY_MTU, BIO_CTRL_FLUSH,
|
||||
};
|
||||
use libc::{c_char, c_int, c_long, c_void, strlen};
|
||||
use std::any::Any;
|
||||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
use std::panic::{catch_unwind, AssertUnwindSafe};
|
||||
use std::ptr;
|
||||
|
||||
use crate::error::ErrorStack;
|
||||
use crate::{cvt_p, util};
|
||||
|
||||
pub struct StreamState<S> {
|
||||
pub stream: S,
|
||||
pub error: Option<io::Error>,
|
||||
pub panic: Option<Box<dyn Any + Send>>,
|
||||
pub dtls_mtu_size: c_long,
|
||||
}
|
||||
|
||||
/// Safe wrapper for `BIO_METHOD`
|
||||
pub struct BioMethod(BIO_METHOD);
|
||||
|
||||
impl BioMethod {
|
||||
fn new<S: Read + Write>() -> Result<BioMethod, ErrorStack> {
|
||||
BIO_METHOD::new::<S>().map(BioMethod)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Sync for BioMethod {}
|
||||
unsafe impl Send for BioMethod {}
|
||||
|
||||
pub fn new<S: Read + Write>(stream: S) -> Result<(*mut BIO, BioMethod), ErrorStack> {
|
||||
let method = BioMethod::new::<S>()?;
|
||||
|
||||
let state = Box::new(StreamState {
|
||||
stream,
|
||||
error: None,
|
||||
panic: None,
|
||||
dtls_mtu_size: 0,
|
||||
});
|
||||
|
||||
unsafe {
|
||||
let bio = cvt_p(BIO_new(method.0.get()))?;
|
||||
BIO_set_data(bio, Box::into_raw(state) as *mut _);
|
||||
BIO_set_init(bio, 1);
|
||||
|
||||
Ok((bio, method))
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn take_error<S>(bio: *mut BIO) -> Option<io::Error> {
|
||||
let state = state::<S>(bio);
|
||||
state.error.take()
|
||||
}
|
||||
|
||||
pub unsafe fn take_panic<S>(bio: *mut BIO) -> Option<Box<dyn Any + Send>> {
|
||||
let state = state::<S>(bio);
|
||||
state.panic.take()
|
||||
}
|
||||
|
||||
pub unsafe fn get_ref<'a, S: 'a>(bio: *mut BIO) -> &'a S {
|
||||
let state = &*(BIO_get_data(bio) as *const StreamState<S>);
|
||||
&state.stream
|
||||
}
|
||||
|
||||
pub unsafe fn get_mut<'a, S: 'a>(bio: *mut BIO) -> &'a mut S {
|
||||
&mut state(bio).stream
|
||||
}
|
||||
|
||||
pub unsafe fn set_dtls_mtu_size<S>(bio: *mut BIO, mtu_size: usize) {
|
||||
if mtu_size as u64 > c_long::MAX as u64 {
|
||||
panic!(
|
||||
"Given MTU size {} can't be represented in a positive `c_long` range",
|
||||
mtu_size
|
||||
)
|
||||
}
|
||||
state::<S>(bio).dtls_mtu_size = mtu_size as c_long;
|
||||
}
|
||||
|
||||
unsafe fn state<'a, S: 'a>(bio: *mut BIO) -> &'a mut StreamState<S> {
|
||||
&mut *(BIO_get_data(bio) as *mut _)
|
||||
}
|
||||
|
||||
unsafe extern "C" fn bwrite<S: Write>(bio: *mut BIO, buf: *const c_char, len: c_int) -> c_int {
|
||||
BIO_clear_retry_flags(bio);
|
||||
|
||||
let state = state::<S>(bio);
|
||||
let buf = util::from_raw_parts(buf as *const _, len as usize);
|
||||
|
||||
match catch_unwind(AssertUnwindSafe(|| state.stream.write(buf))) {
|
||||
Ok(Ok(len)) => len as c_int,
|
||||
Ok(Err(err)) => {
|
||||
if retriable_error(&err) {
|
||||
BIO_set_retry_write(bio);
|
||||
}
|
||||
state.error = Some(err);
|
||||
-1
|
||||
}
|
||||
Err(err) => {
|
||||
state.panic = Some(err);
|
||||
-1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn bread<S: Read>(bio: *mut BIO, buf: *mut c_char, len: c_int) -> c_int {
|
||||
BIO_clear_retry_flags(bio);
|
||||
|
||||
let state = state::<S>(bio);
|
||||
let buf = util::from_raw_parts_mut(buf as *mut _, len as usize);
|
||||
|
||||
match catch_unwind(AssertUnwindSafe(|| state.stream.read(buf))) {
|
||||
Ok(Ok(len)) => len as c_int,
|
||||
Ok(Err(err)) => {
|
||||
if retriable_error(&err) {
|
||||
BIO_set_retry_read(bio);
|
||||
}
|
||||
state.error = Some(err);
|
||||
-1
|
||||
}
|
||||
Err(err) => {
|
||||
state.panic = Some(err);
|
||||
-1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::match_like_matches_macro)] // matches macro requires rust 1.42.0
|
||||
fn retriable_error(err: &io::Error) -> bool {
|
||||
match err.kind() {
|
||||
io::ErrorKind::WouldBlock | io::ErrorKind::NotConnected => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn bputs<S: Write>(bio: *mut BIO, s: *const c_char) -> c_int {
|
||||
bwrite::<S>(bio, s, strlen(s) as c_int)
|
||||
}
|
||||
|
||||
unsafe extern "C" fn ctrl<S: Write>(
|
||||
bio: *mut BIO,
|
||||
cmd: c_int,
|
||||
_num: c_long,
|
||||
_ptr: *mut c_void,
|
||||
) -> c_long {
|
||||
let state = state::<S>(bio);
|
||||
|
||||
if cmd == BIO_CTRL_FLUSH {
|
||||
match catch_unwind(AssertUnwindSafe(|| state.stream.flush())) {
|
||||
Ok(Ok(())) => 1,
|
||||
Ok(Err(err)) => {
|
||||
state.error = Some(err);
|
||||
0
|
||||
}
|
||||
Err(err) => {
|
||||
state.panic = Some(err);
|
||||
0
|
||||
}
|
||||
}
|
||||
} else if cmd == BIO_CTRL_DGRAM_QUERY_MTU {
|
||||
state.dtls_mtu_size
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn create(bio: *mut BIO) -> c_int {
|
||||
BIO_set_init(bio, 0);
|
||||
BIO_set_num(bio, 0);
|
||||
BIO_set_data(bio, ptr::null_mut());
|
||||
BIO_set_flags(bio, 0);
|
||||
1
|
||||
}
|
||||
|
||||
unsafe extern "C" fn destroy<S>(bio: *mut BIO) -> c_int {
|
||||
if bio.is_null() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let data = BIO_get_data(bio);
|
||||
assert!(!data.is_null());
|
||||
let _ = Box::<StreamState<S>>::from_raw(data as *mut _);
|
||||
BIO_set_data(bio, ptr::null_mut());
|
||||
BIO_set_init(bio, 0);
|
||||
1
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl110, libressl273))] {
|
||||
use ffi::{BIO_get_data, BIO_set_data, BIO_set_flags, BIO_set_init};
|
||||
use crate::cvt;
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn BIO_set_num(_bio: *mut ffi::BIO, _num: c_int) {}
|
||||
|
||||
#[allow(bad_style, clippy::upper_case_acronyms)]
|
||||
struct BIO_METHOD(*mut ffi::BIO_METHOD);
|
||||
|
||||
impl BIO_METHOD {
|
||||
fn new<S: Read + Write>() -> Result<BIO_METHOD, ErrorStack> {
|
||||
unsafe {
|
||||
let ptr = cvt_p(ffi::BIO_meth_new(ffi::BIO_TYPE_NONE, b"rust\0".as_ptr() as *const _))?;
|
||||
let method = BIO_METHOD(ptr);
|
||||
cvt(ffi::BIO_meth_set_write__fixed_rust(method.0, Some(bwrite::<S>)))?;
|
||||
cvt(ffi::BIO_meth_set_read__fixed_rust(method.0, Some(bread::<S>)))?;
|
||||
cvt(ffi::BIO_meth_set_puts__fixed_rust(method.0, Some(bputs::<S>)))?;
|
||||
cvt(ffi::BIO_meth_set_ctrl__fixed_rust(method.0, Some(ctrl::<S>)))?;
|
||||
cvt(ffi::BIO_meth_set_create__fixed_rust(method.0, Some(create)))?;
|
||||
cvt(ffi::BIO_meth_set_destroy__fixed_rust(method.0, Some(destroy::<S>)))?;
|
||||
Ok(method)
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
#[allow(bad_style, clippy::upper_case_acronyms)]
|
||||
struct BIO_METHOD(*mut ffi::BIO_METHOD);
|
||||
|
||||
impl BIO_METHOD {
|
||||
fn new<S: Read + Write>() -> Result<BIO_METHOD, ErrorStack> {
|
||||
let ptr = Box::new(ffi::BIO_METHOD {
|
||||
type_: ffi::BIO_TYPE_NONE,
|
||||
name: b"rust\0".as_ptr() as *const _,
|
||||
bwrite: Some(bwrite::<S>),
|
||||
bread: Some(bread::<S>),
|
||||
bputs: Some(bputs::<S>),
|
||||
bgets: None,
|
||||
ctrl: Some(ctrl::<S>),
|
||||
create: Some(create),
|
||||
destroy: Some(destroy::<S>),
|
||||
callback_ctrl: None,
|
||||
});
|
||||
|
||||
Ok(BIO_METHOD(Box::into_raw(ptr)))
|
||||
}
|
||||
|
||||
fn get(&self) -> *mut ffi::BIO_METHOD {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for BIO_METHOD {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
let _ = Box::<ffi::BIO_METHOD>::from_raw(self.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn BIO_set_init(bio: *mut ffi::BIO, init: c_int) {
|
||||
(*bio).init = init;
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn BIO_set_flags(bio: *mut ffi::BIO, flags: c_int) {
|
||||
(*bio).flags = flags;
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn BIO_get_data(bio: *mut ffi::BIO) -> *mut c_void {
|
||||
(*bio).ptr
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn BIO_set_data(bio: *mut ffi::BIO, data: *mut c_void) {
|
||||
(*bio).ptr = data;
|
||||
}
|
||||
|
||||
#[allow(bad_style)]
|
||||
unsafe fn BIO_set_num(bio: *mut ffi::BIO, num: c_int) {
|
||||
(*bio).num = num;
|
||||
}
|
||||
}
|
||||
}
|
||||
707
vendor/openssl/src/ssl/callbacks.rs
vendored
Normal file
707
vendor/openssl/src/ssl/callbacks.rs
vendored
Normal file
|
|
@ -0,0 +1,707 @@
|
|||
use cfg_if::cfg_if;
|
||||
use foreign_types::ForeignType;
|
||||
use foreign_types::ForeignTypeRef;
|
||||
#[cfg(any(ossl111, not(osslconf = "OPENSSL_NO_PSK")))]
|
||||
use libc::c_char;
|
||||
#[cfg(ossl111)]
|
||||
use libc::size_t;
|
||||
use libc::{c_int, c_uchar, c_uint, c_void};
|
||||
#[cfg(any(ossl111, not(osslconf = "OPENSSL_NO_PSK")))]
|
||||
use std::ffi::CStr;
|
||||
use std::mem;
|
||||
use std::ptr;
|
||||
#[cfg(any(ossl111, boringssl))]
|
||||
use std::str;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::dh::Dh;
|
||||
#[cfg(all(ossl101, not(ossl110)))]
|
||||
use crate::ec::EcKey;
|
||||
use crate::error::ErrorStack;
|
||||
use crate::pkey::Params;
|
||||
#[cfg(any(ossl102, libressl261))]
|
||||
use crate::ssl::AlpnError;
|
||||
use crate::ssl::{
|
||||
try_get_session_ctx_index, SniError, Ssl, SslAlert, SslContext, SslContextRef, SslRef,
|
||||
SslSession, SslSessionRef,
|
||||
};
|
||||
#[cfg(ossl111)]
|
||||
use crate::ssl::{ClientHelloResponse, ExtensionContext};
|
||||
use crate::util;
|
||||
#[cfg(any(ossl111, boringssl))]
|
||||
use crate::util::ForeignTypeRefExt;
|
||||
#[cfg(ossl111)]
|
||||
use crate::x509::X509Ref;
|
||||
use crate::x509::{X509StoreContext, X509StoreContextRef};
|
||||
|
||||
pub extern "C" fn raw_verify<F>(preverify_ok: c_int, x509_ctx: *mut ffi::X509_STORE_CTX) -> c_int
|
||||
where
|
||||
F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
|
||||
{
|
||||
unsafe {
|
||||
let ctx = X509StoreContextRef::from_ptr_mut(x509_ctx);
|
||||
let ssl_idx = X509StoreContext::ssl_idx().expect("BUG: store context ssl index missing");
|
||||
let verify_idx = SslContext::cached_ex_index::<F>();
|
||||
|
||||
// raw pointer shenanigans to break the borrow of ctx
|
||||
// the callback can't mess with its own ex_data slot so this is safe
|
||||
let verify = ctx
|
||||
.ex_data(ssl_idx)
|
||||
.expect("BUG: store context missing ssl")
|
||||
.ssl_context()
|
||||
.ex_data(verify_idx)
|
||||
.expect("BUG: verify callback missing") as *const F;
|
||||
|
||||
(*verify)(preverify_ok != 0, ctx) as c_int
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
|
||||
pub extern "C" fn raw_client_psk<F>(
|
||||
ssl: *mut ffi::SSL,
|
||||
hint: *const c_char,
|
||||
identity: *mut c_char,
|
||||
max_identity_len: c_uint,
|
||||
psk: *mut c_uchar,
|
||||
max_psk_len: c_uint,
|
||||
) -> c_uint
|
||||
where
|
||||
F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8], &mut [u8]) -> Result<usize, ErrorStack>
|
||||
+ 'static
|
||||
+ Sync
|
||||
+ Send,
|
||||
{
|
||||
unsafe {
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback_idx = SslContext::cached_ex_index::<F>();
|
||||
|
||||
let callback = ssl
|
||||
.ssl_context()
|
||||
.ex_data(callback_idx)
|
||||
.expect("BUG: psk callback missing") as *const F;
|
||||
let hint = if !hint.is_null() {
|
||||
Some(CStr::from_ptr(hint).to_bytes())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
// Give the callback mutable slices into which it can write the identity and psk.
|
||||
let identity_sl = util::from_raw_parts_mut(identity as *mut u8, max_identity_len as usize);
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
let psk_sl = util::from_raw_parts_mut(psk as *mut u8, max_psk_len as usize);
|
||||
match (*callback)(ssl, hint, identity_sl, psk_sl) {
|
||||
Ok(psk_len) => psk_len as u32,
|
||||
Err(e) => {
|
||||
e.put();
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(osslconf = "OPENSSL_NO_PSK"))]
|
||||
pub extern "C" fn raw_server_psk<F>(
|
||||
ssl: *mut ffi::SSL,
|
||||
identity: *const c_char,
|
||||
psk: *mut c_uchar,
|
||||
max_psk_len: c_uint,
|
||||
) -> c_uint
|
||||
where
|
||||
F: Fn(&mut SslRef, Option<&[u8]>, &mut [u8]) -> Result<usize, ErrorStack>
|
||||
+ 'static
|
||||
+ Sync
|
||||
+ Send,
|
||||
{
|
||||
unsafe {
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback_idx = SslContext::cached_ex_index::<F>();
|
||||
|
||||
let callback = ssl
|
||||
.ssl_context()
|
||||
.ex_data(callback_idx)
|
||||
.expect("BUG: psk callback missing") as *const F;
|
||||
let identity = if identity.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(CStr::from_ptr(identity).to_bytes())
|
||||
};
|
||||
// Give the callback mutable slices into which it can write the psk.
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
let psk_sl = util::from_raw_parts_mut(psk as *mut u8, max_psk_len as usize);
|
||||
match (*callback)(ssl, identity, psk_sl) {
|
||||
Ok(psk_len) => psk_len as u32,
|
||||
Err(e) => {
|
||||
e.put();
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub extern "C" fn ssl_raw_verify<F>(
|
||||
preverify_ok: c_int,
|
||||
x509_ctx: *mut ffi::X509_STORE_CTX,
|
||||
) -> c_int
|
||||
where
|
||||
F: Fn(bool, &mut X509StoreContextRef) -> bool + 'static + Sync + Send,
|
||||
{
|
||||
unsafe {
|
||||
let ctx = X509StoreContextRef::from_ptr_mut(x509_ctx);
|
||||
let ssl_idx = X509StoreContext::ssl_idx().expect("BUG: store context ssl index missing");
|
||||
let callback_idx = Ssl::cached_ex_index::<Arc<F>>();
|
||||
|
||||
let callback = ctx
|
||||
.ex_data(ssl_idx)
|
||||
.expect("BUG: store context missing ssl")
|
||||
.ex_data(callback_idx)
|
||||
.expect("BUG: ssl verify callback missing")
|
||||
.clone();
|
||||
|
||||
callback(preverify_ok != 0, ctx) as c_int
|
||||
}
|
||||
}
|
||||
|
||||
pub extern "C" fn raw_sni<F>(ssl: *mut ffi::SSL, al: *mut c_int, arg: *mut c_void) -> c_int
|
||||
where
|
||||
F: Fn(&mut SslRef, &mut SslAlert) -> Result<(), SniError> + 'static + Sync + Send,
|
||||
{
|
||||
unsafe {
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback = arg as *const F;
|
||||
let mut alert = SslAlert(*al);
|
||||
|
||||
let r = (*callback)(ssl, &mut alert);
|
||||
*al = alert.0;
|
||||
match r {
|
||||
Ok(()) => ffi::SSL_TLSEXT_ERR_OK,
|
||||
Err(e) => e.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(ossl102, libressl261))]
|
||||
pub extern "C" fn raw_alpn_select<F>(
|
||||
ssl: *mut ffi::SSL,
|
||||
out: *mut *const c_uchar,
|
||||
outlen: *mut c_uchar,
|
||||
inbuf: *const c_uchar,
|
||||
inlen: c_uint,
|
||||
_arg: *mut c_void,
|
||||
) -> c_int
|
||||
where
|
||||
F: for<'a> Fn(&mut SslRef, &'a [u8]) -> Result<&'a [u8], AlpnError> + 'static + Sync + Send,
|
||||
{
|
||||
unsafe {
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback = ssl
|
||||
.ssl_context()
|
||||
.ex_data(SslContext::cached_ex_index::<F>())
|
||||
.expect("BUG: alpn callback missing") as *const F;
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
let protos = util::from_raw_parts(inbuf as *const u8, inlen as usize);
|
||||
|
||||
match (*callback)(ssl, protos) {
|
||||
Ok(proto) => {
|
||||
*out = proto.as_ptr() as *const c_uchar;
|
||||
*outlen = proto.len() as c_uchar;
|
||||
ffi::SSL_TLSEXT_ERR_OK
|
||||
}
|
||||
Err(e) => e.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn raw_tmp_dh<F>(
|
||||
ssl: *mut ffi::SSL,
|
||||
is_export: c_int,
|
||||
keylength: c_int,
|
||||
) -> *mut ffi::DH
|
||||
where
|
||||
F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
|
||||
{
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback = ssl
|
||||
.ssl_context()
|
||||
.ex_data(SslContext::cached_ex_index::<F>())
|
||||
.expect("BUG: tmp dh callback missing") as *const F;
|
||||
|
||||
match (*callback)(ssl, is_export != 0, keylength as u32) {
|
||||
Ok(dh) => {
|
||||
let ptr = dh.as_ptr();
|
||||
mem::forget(dh);
|
||||
ptr
|
||||
}
|
||||
Err(e) => {
|
||||
e.put();
|
||||
ptr::null_mut()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(ossl101, not(ossl110)))]
|
||||
pub unsafe extern "C" fn raw_tmp_ecdh<F>(
|
||||
ssl: *mut ffi::SSL,
|
||||
is_export: c_int,
|
||||
keylength: c_int,
|
||||
) -> *mut ffi::EC_KEY
|
||||
where
|
||||
F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send,
|
||||
{
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback = ssl
|
||||
.ssl_context()
|
||||
.ex_data(SslContext::cached_ex_index::<F>())
|
||||
.expect("BUG: tmp ecdh callback missing") as *const F;
|
||||
|
||||
match (*callback)(ssl, is_export != 0, keylength as u32) {
|
||||
Ok(ec_key) => {
|
||||
let ptr = ec_key.as_ptr();
|
||||
mem::forget(ec_key);
|
||||
ptr
|
||||
}
|
||||
Err(e) => {
|
||||
e.put();
|
||||
ptr::null_mut()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn raw_tmp_dh_ssl<F>(
|
||||
ssl: *mut ffi::SSL,
|
||||
is_export: c_int,
|
||||
keylength: c_int,
|
||||
) -> *mut ffi::DH
|
||||
where
|
||||
F: Fn(&mut SslRef, bool, u32) -> Result<Dh<Params>, ErrorStack> + 'static + Sync + Send,
|
||||
{
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback = ssl
|
||||
.ex_data(Ssl::cached_ex_index::<Arc<F>>())
|
||||
.expect("BUG: ssl tmp dh callback missing")
|
||||
.clone();
|
||||
|
||||
match callback(ssl, is_export != 0, keylength as u32) {
|
||||
Ok(dh) => {
|
||||
let ptr = dh.as_ptr();
|
||||
mem::forget(dh);
|
||||
ptr
|
||||
}
|
||||
Err(e) => {
|
||||
e.put();
|
||||
ptr::null_mut()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(ossl101, not(ossl110)))]
|
||||
pub unsafe extern "C" fn raw_tmp_ecdh_ssl<F>(
|
||||
ssl: *mut ffi::SSL,
|
||||
is_export: c_int,
|
||||
keylength: c_int,
|
||||
) -> *mut ffi::EC_KEY
|
||||
where
|
||||
F: Fn(&mut SslRef, bool, u32) -> Result<EcKey<Params>, ErrorStack> + 'static + Sync + Send,
|
||||
{
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback = ssl
|
||||
.ex_data(Ssl::cached_ex_index::<Arc<F>>())
|
||||
.expect("BUG: ssl tmp ecdh callback missing")
|
||||
.clone();
|
||||
|
||||
match callback(ssl, is_export != 0, keylength as u32) {
|
||||
Ok(ec_key) => {
|
||||
let ptr = ec_key.as_ptr();
|
||||
mem::forget(ec_key);
|
||||
ptr
|
||||
}
|
||||
Err(e) => {
|
||||
e.put();
|
||||
ptr::null_mut()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn raw_tlsext_status<F>(ssl: *mut ffi::SSL, _: *mut c_void) -> c_int
|
||||
where
|
||||
F: Fn(&mut SslRef) -> Result<bool, ErrorStack> + 'static + Sync + Send,
|
||||
{
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback = ssl
|
||||
.ssl_context()
|
||||
.ex_data(SslContext::cached_ex_index::<F>())
|
||||
.expect("BUG: ocsp callback missing") as *const F;
|
||||
let ret = (*callback)(ssl);
|
||||
|
||||
if ssl.is_server() {
|
||||
match ret {
|
||||
Ok(true) => ffi::SSL_TLSEXT_ERR_OK,
|
||||
Ok(false) => ffi::SSL_TLSEXT_ERR_NOACK,
|
||||
Err(e) => {
|
||||
e.put();
|
||||
ffi::SSL_TLSEXT_ERR_ALERT_FATAL
|
||||
}
|
||||
}
|
||||
} else {
|
||||
match ret {
|
||||
Ok(true) => 1,
|
||||
Ok(false) => 0,
|
||||
Err(e) => {
|
||||
e.put();
|
||||
-1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn raw_new_session<F>(
|
||||
ssl: *mut ffi::SSL,
|
||||
session: *mut ffi::SSL_SESSION,
|
||||
) -> c_int
|
||||
where
|
||||
F: Fn(&mut SslRef, SslSession) + 'static + Sync + Send,
|
||||
{
|
||||
let session_ctx_index =
|
||||
try_get_session_ctx_index().expect("BUG: session context index initialization failed");
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback = ssl
|
||||
.ex_data(*session_ctx_index)
|
||||
.expect("BUG: session context missing")
|
||||
.ex_data(SslContext::cached_ex_index::<F>())
|
||||
.expect("BUG: new session callback missing") as *const F;
|
||||
let session = SslSession::from_ptr(session);
|
||||
|
||||
(*callback)(ssl, session);
|
||||
|
||||
// the return code doesn't indicate error vs success, but whether or not we consumed the session
|
||||
1
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn raw_remove_session<F>(
|
||||
ctx: *mut ffi::SSL_CTX,
|
||||
session: *mut ffi::SSL_SESSION,
|
||||
) where
|
||||
F: Fn(&SslContextRef, &SslSessionRef) + 'static + Sync + Send,
|
||||
{
|
||||
let ctx = SslContextRef::from_ptr(ctx);
|
||||
let callback = ctx
|
||||
.ex_data(SslContext::cached_ex_index::<F>())
|
||||
.expect("BUG: remove session callback missing");
|
||||
let session = SslSessionRef::from_ptr(session);
|
||||
|
||||
callback(ctx, session)
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl110, libressl280, boringssl))] {
|
||||
type DataPtr = *const c_uchar;
|
||||
} else {
|
||||
type DataPtr = *mut c_uchar;
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn raw_get_session<F>(
|
||||
ssl: *mut ffi::SSL,
|
||||
data: DataPtr,
|
||||
len: c_int,
|
||||
copy: *mut c_int,
|
||||
) -> *mut ffi::SSL_SESSION
|
||||
where
|
||||
F: Fn(&mut SslRef, &[u8]) -> Option<SslSession> + 'static + Sync + Send,
|
||||
{
|
||||
let session_ctx_index =
|
||||
try_get_session_ctx_index().expect("BUG: session context index initialization failed");
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback = ssl
|
||||
.ex_data(*session_ctx_index)
|
||||
.expect("BUG: session context missing")
|
||||
.ex_data(SslContext::cached_ex_index::<F>())
|
||||
.expect("BUG: get session callback missing") as *const F;
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
let data = util::from_raw_parts(data as *const u8, len as usize);
|
||||
|
||||
match (*callback)(ssl, data) {
|
||||
Some(session) => {
|
||||
let p = session.as_ptr();
|
||||
mem::forget(session);
|
||||
*copy = 0;
|
||||
p
|
||||
}
|
||||
None => ptr::null_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(ossl111, boringssl))]
|
||||
pub unsafe extern "C" fn raw_keylog<F>(ssl: *const ffi::SSL, line: *const c_char)
|
||||
where
|
||||
F: Fn(&SslRef, &str) + 'static + Sync + Send,
|
||||
{
|
||||
let ssl = SslRef::from_const_ptr(ssl);
|
||||
let callback = ssl
|
||||
.ssl_context()
|
||||
.ex_data(SslContext::cached_ex_index::<F>())
|
||||
.expect("BUG: get session callback missing");
|
||||
let line = CStr::from_ptr(line).to_bytes();
|
||||
let line = str::from_utf8_unchecked(line);
|
||||
|
||||
callback(ssl, line);
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
pub unsafe extern "C" fn raw_stateless_cookie_generate<F>(
|
||||
ssl: *mut ffi::SSL,
|
||||
cookie: *mut c_uchar,
|
||||
cookie_len: *mut size_t,
|
||||
) -> c_int
|
||||
where
|
||||
F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
|
||||
{
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback = ssl
|
||||
.ssl_context()
|
||||
.ex_data(SslContext::cached_ex_index::<F>())
|
||||
.expect("BUG: stateless cookie generate callback missing") as *const F;
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
let slice = util::from_raw_parts_mut(cookie as *mut u8, ffi::SSL_COOKIE_LENGTH as usize);
|
||||
match (*callback)(ssl, slice) {
|
||||
Ok(len) => {
|
||||
*cookie_len = len as size_t;
|
||||
1
|
||||
}
|
||||
Err(e) => {
|
||||
e.put();
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
pub unsafe extern "C" fn raw_stateless_cookie_verify<F>(
|
||||
ssl: *mut ffi::SSL,
|
||||
cookie: *const c_uchar,
|
||||
cookie_len: size_t,
|
||||
) -> c_int
|
||||
where
|
||||
F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
|
||||
{
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback = ssl
|
||||
.ssl_context()
|
||||
.ex_data(SslContext::cached_ex_index::<F>())
|
||||
.expect("BUG: stateless cookie verify callback missing") as *const F;
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
let slice = util::from_raw_parts(cookie as *const c_uchar as *const u8, cookie_len);
|
||||
(*callback)(ssl, slice) as c_int
|
||||
}
|
||||
|
||||
#[cfg(not(boringssl))]
|
||||
pub extern "C" fn raw_cookie_generate<F>(
|
||||
ssl: *mut ffi::SSL,
|
||||
cookie: *mut c_uchar,
|
||||
cookie_len: *mut c_uint,
|
||||
) -> c_int
|
||||
where
|
||||
F: Fn(&mut SslRef, &mut [u8]) -> Result<usize, ErrorStack> + 'static + Sync + Send,
|
||||
{
|
||||
unsafe {
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback = ssl
|
||||
.ssl_context()
|
||||
.ex_data(SslContext::cached_ex_index::<F>())
|
||||
.expect("BUG: cookie generate callback missing") as *const F;
|
||||
// We subtract 1 from DTLS1_COOKIE_LENGTH as the ostensible value, 256, is erroneous but retained for
|
||||
// compatibility. See comments in dtls1.h.
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
let slice =
|
||||
util::from_raw_parts_mut(cookie as *mut u8, ffi::DTLS1_COOKIE_LENGTH as usize - 1);
|
||||
match (*callback)(ssl, slice) {
|
||||
Ok(len) => {
|
||||
*cookie_len = len as c_uint;
|
||||
1
|
||||
}
|
||||
Err(e) => {
|
||||
e.put();
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(boringssl))]
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl110, libressl280))] {
|
||||
type CookiePtr = *const c_uchar;
|
||||
} else {
|
||||
type CookiePtr = *mut c_uchar;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(boringssl))]
|
||||
pub extern "C" fn raw_cookie_verify<F>(
|
||||
ssl: *mut ffi::SSL,
|
||||
cookie: CookiePtr,
|
||||
cookie_len: c_uint,
|
||||
) -> c_int
|
||||
where
|
||||
F: Fn(&mut SslRef, &[u8]) -> bool + 'static + Sync + Send,
|
||||
{
|
||||
unsafe {
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback = ssl
|
||||
.ssl_context()
|
||||
.ex_data(SslContext::cached_ex_index::<F>())
|
||||
.expect("BUG: cookie verify callback missing") as *const F;
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
let slice =
|
||||
util::from_raw_parts(cookie as *const c_uchar as *const u8, cookie_len as usize);
|
||||
(*callback)(ssl, slice) as c_int
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
pub struct CustomExtAddState<T>(Option<T>);
|
||||
|
||||
#[cfg(ossl111)]
|
||||
pub extern "C" fn raw_custom_ext_add<F, T>(
|
||||
ssl: *mut ffi::SSL,
|
||||
_: c_uint,
|
||||
context: c_uint,
|
||||
out: *mut *const c_uchar,
|
||||
outlen: *mut size_t,
|
||||
x: *mut ffi::X509,
|
||||
chainidx: size_t,
|
||||
al: *mut c_int,
|
||||
_: *mut c_void,
|
||||
) -> c_int
|
||||
where
|
||||
F: Fn(&mut SslRef, ExtensionContext, Option<(usize, &X509Ref)>) -> Result<Option<T>, SslAlert>
|
||||
+ 'static
|
||||
+ Sync
|
||||
+ Send,
|
||||
T: AsRef<[u8]> + 'static + Sync + Send,
|
||||
{
|
||||
unsafe {
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback = ssl
|
||||
.ssl_context()
|
||||
.ex_data(SslContext::cached_ex_index::<F>())
|
||||
.expect("BUG: custom ext add callback missing") as *const F;
|
||||
let ectx = ExtensionContext::from_bits_truncate(context);
|
||||
let cert = if ectx.contains(ExtensionContext::TLS1_3_CERTIFICATE) {
|
||||
Some((chainidx, X509Ref::from_ptr(x)))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
match (*callback)(ssl, ectx, cert) {
|
||||
Ok(None) => 0,
|
||||
Ok(Some(buf)) => {
|
||||
*outlen = buf.as_ref().len();
|
||||
*out = buf.as_ref().as_ptr();
|
||||
|
||||
let idx = Ssl::cached_ex_index::<CustomExtAddState<T>>();
|
||||
let mut buf = Some(buf);
|
||||
let new = match ssl.ex_data_mut(idx) {
|
||||
Some(state) => {
|
||||
state.0 = buf.take();
|
||||
false
|
||||
}
|
||||
None => true,
|
||||
};
|
||||
if new {
|
||||
ssl.set_ex_data(idx, CustomExtAddState(buf));
|
||||
}
|
||||
1
|
||||
}
|
||||
Err(alert) => {
|
||||
*al = alert.0;
|
||||
-1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
pub extern "C" fn raw_custom_ext_free<T>(
|
||||
ssl: *mut ffi::SSL,
|
||||
_: c_uint,
|
||||
_: c_uint,
|
||||
_: *const c_uchar,
|
||||
_: *mut c_void,
|
||||
) where
|
||||
T: 'static + Sync + Send,
|
||||
{
|
||||
unsafe {
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let idx = Ssl::cached_ex_index::<CustomExtAddState<T>>();
|
||||
if let Some(state) = ssl.ex_data_mut(idx) {
|
||||
state.0 = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
pub extern "C" fn raw_custom_ext_parse<F>(
|
||||
ssl: *mut ffi::SSL,
|
||||
_: c_uint,
|
||||
context: c_uint,
|
||||
input: *const c_uchar,
|
||||
inlen: size_t,
|
||||
x: *mut ffi::X509,
|
||||
chainidx: size_t,
|
||||
al: *mut c_int,
|
||||
_: *mut c_void,
|
||||
) -> c_int
|
||||
where
|
||||
F: Fn(&mut SslRef, ExtensionContext, &[u8], Option<(usize, &X509Ref)>) -> Result<(), SslAlert>
|
||||
+ 'static
|
||||
+ Sync
|
||||
+ Send,
|
||||
{
|
||||
unsafe {
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback = ssl
|
||||
.ssl_context()
|
||||
.ex_data(SslContext::cached_ex_index::<F>())
|
||||
.expect("BUG: custom ext parse callback missing") as *const F;
|
||||
let ectx = ExtensionContext::from_bits_truncate(context);
|
||||
#[allow(clippy::unnecessary_cast)]
|
||||
let slice = util::from_raw_parts(input as *const u8, inlen);
|
||||
let cert = if ectx.contains(ExtensionContext::TLS1_3_CERTIFICATE) {
|
||||
Some((chainidx, X509Ref::from_ptr(x)))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
match (*callback)(ssl, ectx, slice, cert) {
|
||||
Ok(()) => 1,
|
||||
Err(alert) => {
|
||||
*al = alert.0;
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(ossl111)]
|
||||
pub unsafe extern "C" fn raw_client_hello<F>(
|
||||
ssl: *mut ffi::SSL,
|
||||
al: *mut c_int,
|
||||
arg: *mut c_void,
|
||||
) -> c_int
|
||||
where
|
||||
F: Fn(&mut SslRef, &mut SslAlert) -> Result<ClientHelloResponse, ErrorStack>
|
||||
+ 'static
|
||||
+ Sync
|
||||
+ Send,
|
||||
{
|
||||
let ssl = SslRef::from_ptr_mut(ssl);
|
||||
let callback = arg as *const F;
|
||||
let mut alert = SslAlert(*al);
|
||||
|
||||
let r = (*callback)(ssl, &mut alert);
|
||||
*al = alert.0;
|
||||
match r {
|
||||
Ok(c) => c.0,
|
||||
Err(e) => {
|
||||
e.put();
|
||||
ffi::SSL_CLIENT_HELLO_ERROR
|
||||
}
|
||||
}
|
||||
}
|
||||
605
vendor/openssl/src/ssl/connector.rs
vendored
Normal file
605
vendor/openssl/src/ssl/connector.rs
vendored
Normal file
|
|
@ -0,0 +1,605 @@
|
|||
use cfg_if::cfg_if;
|
||||
use std::io::{Read, Write};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use crate::dh::Dh;
|
||||
use crate::error::ErrorStack;
|
||||
#[cfg(any(ossl111, libressl340))]
|
||||
use crate::ssl::SslVersion;
|
||||
use crate::ssl::{
|
||||
HandshakeError, Ssl, SslContext, SslContextBuilder, SslContextRef, SslMethod, SslMode,
|
||||
SslOptions, SslRef, SslStream, SslVerifyMode,
|
||||
};
|
||||
use crate::version;
|
||||
use std::net::IpAddr;
|
||||
|
||||
const FFDHE_2048: &str = "
|
||||
-----BEGIN DH PARAMETERS-----
|
||||
MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz
|
||||
+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a
|
||||
87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7
|
||||
YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi
|
||||
7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD
|
||||
ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
|
||||
-----END DH PARAMETERS-----
|
||||
";
|
||||
|
||||
#[allow(clippy::inconsistent_digit_grouping, clippy::unusual_byte_groupings)]
|
||||
fn ctx(method: SslMethod) -> Result<SslContextBuilder, ErrorStack> {
|
||||
let mut ctx = SslContextBuilder::new(method)?;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(not(boringssl))] {
|
||||
let mut opts = SslOptions::ALL
|
||||
| SslOptions::NO_COMPRESSION
|
||||
| SslOptions::NO_SSLV2
|
||||
| SslOptions::NO_SSLV3
|
||||
| SslOptions::SINGLE_DH_USE
|
||||
| SslOptions::SINGLE_ECDH_USE;
|
||||
opts &= !SslOptions::DONT_INSERT_EMPTY_FRAGMENTS;
|
||||
|
||||
ctx.set_options(opts);
|
||||
}
|
||||
}
|
||||
|
||||
let mut mode =
|
||||
SslMode::AUTO_RETRY | SslMode::ACCEPT_MOVING_WRITE_BUFFER | SslMode::ENABLE_PARTIAL_WRITE;
|
||||
|
||||
// This is quite a useful optimization for saving memory, but historically
|
||||
// caused CVEs in OpenSSL pre-1.0.1h, according to
|
||||
// https://bugs.python.org/issue25672
|
||||
if version::number() >= 0x1_00_01_08_0 {
|
||||
mode |= SslMode::RELEASE_BUFFERS;
|
||||
}
|
||||
|
||||
ctx.set_mode(mode);
|
||||
|
||||
Ok(ctx)
|
||||
}
|
||||
|
||||
/// 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.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SslConnector(SslContext);
|
||||
|
||||
impl SslConnector {
|
||||
/// Creates a new builder for TLS connections.
|
||||
///
|
||||
/// The default configuration is subject to change, and is currently derived from Python.
|
||||
pub fn builder(method: SslMethod) -> Result<SslConnectorBuilder, ErrorStack> {
|
||||
let mut ctx = ctx(method)?;
|
||||
ctx.set_default_verify_paths()?;
|
||||
ctx.set_cipher_list(
|
||||
"DEFAULT:!aNULL:!eNULL:!MD5:!3DES:!DES:!RC4:!IDEA:!SEED:!aDSS:!SRP:!PSK",
|
||||
)?;
|
||||
setup_verify(&mut ctx);
|
||||
|
||||
Ok(SslConnectorBuilder(ctx))
|
||||
}
|
||||
|
||||
/// Initiates a client-side TLS session on a stream.
|
||||
///
|
||||
/// The domain is used for SNI and hostname verification.
|
||||
pub fn connect<S>(&self, domain: &str, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
|
||||
where
|
||||
S: Read + Write,
|
||||
{
|
||||
self.configure()?.connect(domain, stream)
|
||||
}
|
||||
|
||||
/// Returns a structure allowing for configuration of a single TLS session before connection.
|
||||
pub fn configure(&self) -> Result<ConnectConfiguration, ErrorStack> {
|
||||
Ssl::new(&self.0).map(|ssl| ConnectConfiguration {
|
||||
ssl,
|
||||
sni: true,
|
||||
verify_hostname: true,
|
||||
})
|
||||
}
|
||||
|
||||
/// Consumes the `SslConnector`, returning the inner raw `SslContext`.
|
||||
pub fn into_context(self) -> SslContext {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Returns a shared reference to the inner raw `SslContext`.
|
||||
pub fn context(&self) -> &SslContextRef {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// A builder for `SslConnector`s.
|
||||
pub struct SslConnectorBuilder(SslContextBuilder);
|
||||
|
||||
impl SslConnectorBuilder {
|
||||
/// Consumes the builder, returning an `SslConnector`.
|
||||
pub fn build(self) -> SslConnector {
|
||||
SslConnector(self.0.build())
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for SslConnectorBuilder {
|
||||
type Target = SslContextBuilder;
|
||||
|
||||
fn deref(&self) -> &SslContextBuilder {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for SslConnectorBuilder {
|
||||
fn deref_mut(&mut self) -> &mut SslContextBuilder {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// A type which allows for configuration of a client-side TLS session before connection.
|
||||
pub struct ConnectConfiguration {
|
||||
ssl: Ssl,
|
||||
sni: bool,
|
||||
verify_hostname: bool,
|
||||
}
|
||||
|
||||
impl ConnectConfiguration {
|
||||
/// A builder-style version of `set_use_server_name_indication`.
|
||||
pub fn use_server_name_indication(mut self, use_sni: bool) -> ConnectConfiguration {
|
||||
self.set_use_server_name_indication(use_sni);
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures the use of Server Name Indication (SNI) when connecting.
|
||||
///
|
||||
/// Defaults to `true`.
|
||||
pub fn set_use_server_name_indication(&mut self, use_sni: bool) {
|
||||
self.sni = use_sni;
|
||||
}
|
||||
|
||||
/// A builder-style version of `set_verify_hostname`.
|
||||
pub fn verify_hostname(mut self, verify_hostname: bool) -> ConnectConfiguration {
|
||||
self.set_verify_hostname(verify_hostname);
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures the use of hostname verification when connecting.
|
||||
///
|
||||
/// Defaults to `true`.
|
||||
///
|
||||
/// # Warning
|
||||
///
|
||||
/// You should think very carefully before you use this method. If hostname verification is not
|
||||
/// used, *any* valid certificate for *any* site will be trusted for use from any other. This
|
||||
/// introduces a significant vulnerability to man-in-the-middle attacks.
|
||||
pub fn set_verify_hostname(&mut self, verify_hostname: bool) {
|
||||
self.verify_hostname = verify_hostname;
|
||||
}
|
||||
|
||||
/// Returns an `Ssl` configured to connect to the provided domain.
|
||||
///
|
||||
/// The domain is used for SNI (if it is not an IP address) and hostname verification if enabled.
|
||||
pub fn into_ssl(mut self, domain: &str) -> Result<Ssl, ErrorStack> {
|
||||
if self.sni && domain.parse::<IpAddr>().is_err() {
|
||||
self.ssl.set_hostname(domain)?;
|
||||
}
|
||||
|
||||
if self.verify_hostname {
|
||||
setup_verify_hostname(&mut self.ssl, domain)?;
|
||||
}
|
||||
|
||||
Ok(self.ssl)
|
||||
}
|
||||
|
||||
/// Initiates a client-side TLS session on a stream.
|
||||
///
|
||||
/// The domain is used for SNI and hostname verification if enabled.
|
||||
pub fn connect<S>(self, domain: &str, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
|
||||
where
|
||||
S: Read + Write,
|
||||
{
|
||||
self.into_ssl(domain)?.connect(stream)
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for ConnectConfiguration {
|
||||
type Target = SslRef;
|
||||
|
||||
fn deref(&self) -> &SslRef {
|
||||
&self.ssl
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for ConnectConfiguration {
|
||||
fn deref_mut(&mut self) -> &mut SslRef {
|
||||
&mut self.ssl
|
||||
}
|
||||
}
|
||||
|
||||
/// 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.
|
||||
#[derive(Clone)]
|
||||
pub struct SslAcceptor(SslContext);
|
||||
|
||||
impl SslAcceptor {
|
||||
/// 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 version 5 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_v5(method: SslMethod) -> Result<SslAcceptorBuilder, ErrorStack> {
|
||||
let mut ctx = ctx(method)?;
|
||||
ctx.set_options(SslOptions::NO_TLSV1 | SslOptions::NO_TLSV1_1);
|
||||
let dh = Dh::params_from_pem(FFDHE_2048.as_bytes())?;
|
||||
ctx.set_tmp_dh(&dh)?;
|
||||
setup_curves(&mut ctx)?;
|
||||
ctx.set_cipher_list(
|
||||
"ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:\
|
||||
ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:\
|
||||
DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384"
|
||||
)?;
|
||||
#[cfg(any(ossl111, libressl340))]
|
||||
ctx.set_ciphersuites(
|
||||
"TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256",
|
||||
)?;
|
||||
Ok(SslAcceptorBuilder(ctx))
|
||||
}
|
||||
|
||||
/// Creates a new builder configured to connect to modern clients.
|
||||
///
|
||||
/// This corresponds to the modern configuration of version 5 of Mozilla's server side TLS recommendations.
|
||||
/// See its [documentation][docs] for more details on specifics.
|
||||
///
|
||||
/// Requires OpenSSL 1.1.1 or LibreSSL 3.4.0 or newer.
|
||||
///
|
||||
/// [docs]: https://wiki.mozilla.org/Security/Server_Side_TLS
|
||||
#[cfg(any(ossl111, libressl340))]
|
||||
pub fn mozilla_modern_v5(method: SslMethod) -> Result<SslAcceptorBuilder, ErrorStack> {
|
||||
let mut ctx = ctx(method)?;
|
||||
ctx.set_min_proto_version(Some(SslVersion::TLS1_3))?;
|
||||
ctx.set_ciphersuites(
|
||||
"TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256",
|
||||
)?;
|
||||
Ok(SslAcceptorBuilder(ctx))
|
||||
}
|
||||
|
||||
/// 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 version 4 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
|
||||
// FIXME remove in next major version
|
||||
pub fn mozilla_intermediate(method: SslMethod) -> Result<SslAcceptorBuilder, ErrorStack> {
|
||||
let mut ctx = ctx(method)?;
|
||||
ctx.set_options(SslOptions::CIPHER_SERVER_PREFERENCE);
|
||||
#[cfg(any(ossl111, libressl340))]
|
||||
ctx.set_options(SslOptions::NO_TLSV1_3);
|
||||
let dh = Dh::params_from_pem(FFDHE_2048.as_bytes())?;
|
||||
ctx.set_tmp_dh(&dh)?;
|
||||
setup_curves(&mut ctx)?;
|
||||
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",
|
||||
)?;
|
||||
Ok(SslAcceptorBuilder(ctx))
|
||||
}
|
||||
|
||||
/// Creates a new builder configured to connect to modern clients.
|
||||
///
|
||||
/// This corresponds to the modern configuration of version 4 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
|
||||
// FIXME remove in next major version
|
||||
pub fn mozilla_modern(method: SslMethod) -> Result<SslAcceptorBuilder, ErrorStack> {
|
||||
let mut ctx = ctx(method)?;
|
||||
ctx.set_options(
|
||||
SslOptions::CIPHER_SERVER_PREFERENCE | SslOptions::NO_TLSV1 | SslOptions::NO_TLSV1_1,
|
||||
);
|
||||
#[cfg(any(ossl111, libressl340))]
|
||||
ctx.set_options(SslOptions::NO_TLSV1_3);
|
||||
setup_curves(&mut ctx)?;
|
||||
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",
|
||||
)?;
|
||||
Ok(SslAcceptorBuilder(ctx))
|
||||
}
|
||||
|
||||
/// Initiates a server-side TLS session on a stream.
|
||||
pub fn accept<S>(&self, stream: S) -> Result<SslStream<S>, HandshakeError<S>>
|
||||
where
|
||||
S: Read + Write,
|
||||
{
|
||||
let ssl = Ssl::new(&self.0)?;
|
||||
ssl.accept(stream)
|
||||
}
|
||||
|
||||
/// Consumes the `SslAcceptor`, returning the inner raw `SslContext`.
|
||||
pub fn into_context(self) -> SslContext {
|
||||
self.0
|
||||
}
|
||||
|
||||
/// Returns a shared reference to the inner raw `SslContext`.
|
||||
pub fn context(&self) -> &SslContextRef {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
/// A builder for `SslAcceptor`s.
|
||||
pub struct SslAcceptorBuilder(SslContextBuilder);
|
||||
|
||||
impl SslAcceptorBuilder {
|
||||
/// Consumes the builder, returning a `SslAcceptor`.
|
||||
pub fn build(self) -> SslAcceptor {
|
||||
SslAcceptor(self.0.build())
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for SslAcceptorBuilder {
|
||||
type Target = SslContextBuilder;
|
||||
|
||||
fn deref(&self) -> &SslContextBuilder {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for SslAcceptorBuilder {
|
||||
fn deref_mut(&mut self) -> &mut SslContextBuilder {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(ossl110)] {
|
||||
#[allow(clippy::unnecessary_wraps)]
|
||||
fn setup_curves(_: &mut SslContextBuilder) -> Result<(), ErrorStack> {
|
||||
Ok(())
|
||||
}
|
||||
} else if #[cfg(any(ossl102, libressl))] {
|
||||
fn setup_curves(ctx: &mut SslContextBuilder) -> Result<(), ErrorStack> {
|
||||
ctx.set_ecdh_auto(true)
|
||||
}
|
||||
} else {
|
||||
fn setup_curves(ctx: &mut SslContextBuilder) -> Result<(), ErrorStack> {
|
||||
use crate::ec::EcKey;
|
||||
use crate::nid::Nid;
|
||||
|
||||
let curve = EcKey::from_curve_name(Nid::X9_62_PRIME256V1)?;
|
||||
ctx.set_tmp_ecdh(&curve)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl102, libressl261))] {
|
||||
fn setup_verify(ctx: &mut SslContextBuilder) {
|
||||
ctx.set_verify(SslVerifyMode::PEER);
|
||||
}
|
||||
|
||||
fn setup_verify_hostname(ssl: &mut SslRef, domain: &str) -> Result<(), ErrorStack> {
|
||||
use crate::x509::verify::X509CheckFlags;
|
||||
|
||||
let param = ssl.param_mut();
|
||||
param.set_hostflags(X509CheckFlags::NO_PARTIAL_WILDCARDS);
|
||||
match domain.parse() {
|
||||
Ok(ip) => param.set_ip(ip),
|
||||
Err(_) => param.set_host(domain),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fn setup_verify(ctx: &mut SslContextBuilder) {
|
||||
ctx.set_verify_callback(SslVerifyMode::PEER, verify::verify_callback);
|
||||
}
|
||||
|
||||
fn setup_verify_hostname(ssl: &mut Ssl, domain: &str) -> Result<(), ErrorStack> {
|
||||
let domain = domain.to_string();
|
||||
let hostname_idx = verify::try_get_hostname_idx()?;
|
||||
ssl.set_ex_data(*hostname_idx, domain);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
mod verify {
|
||||
use std::net::IpAddr;
|
||||
use std::str;
|
||||
use once_cell::sync::OnceCell;
|
||||
|
||||
use crate::error::ErrorStack;
|
||||
use crate::ex_data::Index;
|
||||
use crate::nid::Nid;
|
||||
use crate::ssl::Ssl;
|
||||
use crate::stack::Stack;
|
||||
use crate::x509::{
|
||||
GeneralName, X509NameRef, X509Ref, X509StoreContext, X509StoreContextRef,
|
||||
X509VerifyResult,
|
||||
};
|
||||
|
||||
static HOSTNAME_IDX: OnceCell<Index<Ssl, String>> = OnceCell::new();
|
||||
|
||||
pub fn try_get_hostname_idx() -> Result<&'static Index<Ssl, String>, ErrorStack> {
|
||||
HOSTNAME_IDX.get_or_try_init(Ssl::new_ex_index)
|
||||
}
|
||||
|
||||
pub fn verify_callback(preverify_ok: bool, x509_ctx: &mut X509StoreContextRef) -> bool {
|
||||
if !preverify_ok || x509_ctx.error_depth() != 0 {
|
||||
return preverify_ok;
|
||||
}
|
||||
|
||||
let hostname_idx =
|
||||
try_get_hostname_idx().expect("failed to initialize hostname index");
|
||||
let ok = match (
|
||||
x509_ctx.current_cert(),
|
||||
X509StoreContext::ssl_idx()
|
||||
.ok()
|
||||
.and_then(|idx| x509_ctx.ex_data(idx))
|
||||
.and_then(|ssl| ssl.ex_data(*hostname_idx)),
|
||||
) {
|
||||
(Some(x509), Some(domain)) => verify_hostname(domain, &x509),
|
||||
_ => true,
|
||||
};
|
||||
|
||||
if !ok {
|
||||
x509_ctx.set_error(X509VerifyResult::APPLICATION_VERIFICATION);
|
||||
}
|
||||
|
||||
ok
|
||||
}
|
||||
|
||||
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<GeneralName>) -> 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) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
fn verify_subject_name(domain: &str, subject_name: &X509NameRef) -> bool {
|
||||
match subject_name.entries_by_nid(Nid::COMMONNAME).next() {
|
||||
Some(pattern) => {
|
||||
let pattern = match str::from_utf8(pattern.data().as_slice()) {
|
||||
Ok(pattern) => pattern,
|
||||
Err(_) => return false,
|
||||
};
|
||||
|
||||
// Unlike SANs, IP addresses in the subject name don't have a
|
||||
// different encoding.
|
||||
match domain.parse::<IpAddr>() {
|
||||
Ok(ip) => pattern
|
||||
.parse::<IpAddr>()
|
||||
.ok()
|
||||
.map_or(false, |pattern| pattern == ip),
|
||||
Err(_) => matches_dns(pattern, domain),
|
||||
}
|
||||
}
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn matches_dns(mut pattern: &str, mut hostname: &str) -> 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).unwrap_or_else(|| pattern.eq_ignore_ascii_case(hostname))
|
||||
}
|
||||
|
||||
fn matches_wildcard(pattern: &str, hostname: &str) -> Option<bool> {
|
||||
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
|
||||
// potentially 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, and must be the entire first label
|
||||
if wildcard_location != 0 || wildcard_end != wildcard_location + 1 {
|
||||
return None;
|
||||
}
|
||||
|
||||
let hostname_label_end = match hostname.find('.') {
|
||||
Some(l) => l,
|
||||
None => return None,
|
||||
};
|
||||
|
||||
let pattern_after_wildcard = &pattern[wildcard_end..];
|
||||
let hostname_after_wildcard = &hostname[hostname_label_end..];
|
||||
|
||||
Some(pattern_after_wildcard.eq_ignore_ascii_case(hostname_after_wildcard))
|
||||
}
|
||||
|
||||
fn matches_ip(expected: &IpAddr, actual: &[u8]) -> bool {
|
||||
match *expected {
|
||||
IpAddr::V4(ref addr) => actual == addr.octets(),
|
||||
IpAddr::V6(ref addr) => actual == addr.octets(),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dns_match() {
|
||||
use crate::ssl::connector::verify::matches_dns;
|
||||
assert!(matches_dns("website.tld", "website.tld")); // A name should match itself.
|
||||
assert!(matches_dns("website.tld", "wEbSiTe.tLd")); // DNS name matching ignores case of hostname.
|
||||
assert!(matches_dns("wEbSiTe.TlD", "website.tld")); // DNS name matching ignores case of subject.
|
||||
|
||||
assert!(matches_dns("xn--bcher-kva.tld", "xn--bcher-kva.tld")); // Likewise, nothing special to punycode names.
|
||||
assert!(matches_dns("xn--bcher-kva.tld", "xn--BcHer-Kva.tLd")); // And punycode must be compared similarly case-insensitively.
|
||||
|
||||
assert!(matches_dns("*.example.com", "subdomain.example.com")); // Wildcard matching works.
|
||||
assert!(matches_dns("*.eXaMpLe.cOm", "subdomain.example.com")); // Wildcard matching ignores case of subject.
|
||||
assert!(matches_dns("*.example.com", "sUbDoMaIn.eXaMpLe.cOm")); // Wildcard matching ignores case of hostname.
|
||||
|
||||
assert!(!matches_dns("prefix*.example.com", "p.example.com")); // Prefix longer than the label works and does not match.
|
||||
assert!(!matches_dns("*suffix.example.com", "s.example.com")); // Suffix longer than the label works and does not match.
|
||||
|
||||
assert!(!matches_dns("prefix*.example.com", "prefix.example.com")); // Partial wildcards do not work.
|
||||
assert!(!matches_dns("*suffix.example.com", "suffix.example.com")); // Partial wildcards do not work.
|
||||
|
||||
assert!(!matches_dns("prefix*.example.com", "prefixdomain.example.com")); // Partial wildcards do not work.
|
||||
assert!(!matches_dns("*suffix.example.com", "domainsuffix.example.com")); // Partial wildcards do not work.
|
||||
|
||||
assert!(!matches_dns("xn--*.example.com", "subdomain.example.com")); // Punycode domains with wildcard parts do not match.
|
||||
assert!(!matches_dns("xN--*.example.com", "subdomain.example.com")); // And we can't bypass a punycode test with weird casing.
|
||||
assert!(!matches_dns("Xn--*.example.com", "subdomain.example.com")); // And we can't bypass a punycode test with weird casing.
|
||||
assert!(!matches_dns("XN--*.example.com", "subdomain.example.com")); // And we can't bypass a punycode test with weird casing.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
185
vendor/openssl/src/ssl/error.rs
vendored
Normal file
185
vendor/openssl/src/ssl/error.rs
vendored
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
use libc::c_int;
|
||||
use std::error;
|
||||
use std::error::Error as StdError;
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
|
||||
use crate::error::ErrorStack;
|
||||
use crate::ssl::MidHandshakeSslStream;
|
||||
use crate::x509::X509VerifyResult;
|
||||
|
||||
/// An error code returned from SSL functions.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct ErrorCode(c_int);
|
||||
|
||||
impl ErrorCode {
|
||||
/// The SSL session has been closed.
|
||||
pub const ZERO_RETURN: ErrorCode = ErrorCode(ffi::SSL_ERROR_ZERO_RETURN);
|
||||
|
||||
/// An attempt to read data from the underlying socket returned `WouldBlock`.
|
||||
///
|
||||
/// Wait for read readiness and retry the operation.
|
||||
pub const WANT_READ: ErrorCode = ErrorCode(ffi::SSL_ERROR_WANT_READ);
|
||||
|
||||
/// An attempt to write data to the underlying socket returned `WouldBlock`.
|
||||
///
|
||||
/// Wait for write readiness and retry the operation.
|
||||
pub const WANT_WRITE: ErrorCode = ErrorCode(ffi::SSL_ERROR_WANT_WRITE);
|
||||
|
||||
/// A non-recoverable IO error occurred.
|
||||
pub const SYSCALL: ErrorCode = ErrorCode(ffi::SSL_ERROR_SYSCALL);
|
||||
|
||||
/// An error occurred in the SSL library.
|
||||
pub const SSL: ErrorCode = ErrorCode(ffi::SSL_ERROR_SSL);
|
||||
|
||||
/// The client hello callback indicated that it needed to be retried.
|
||||
///
|
||||
/// Requires OpenSSL 1.1.1 or newer.
|
||||
#[cfg(ossl111)]
|
||||
pub const WANT_CLIENT_HELLO_CB: ErrorCode = ErrorCode(ffi::SSL_ERROR_WANT_CLIENT_HELLO_CB);
|
||||
|
||||
pub fn from_raw(raw: c_int) -> ErrorCode {
|
||||
ErrorCode(raw)
|
||||
}
|
||||
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub fn as_raw(&self) -> c_int {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) enum InnerError {
|
||||
Io(io::Error),
|
||||
Ssl(ErrorStack),
|
||||
}
|
||||
|
||||
/// An SSL error.
|
||||
#[derive(Debug)]
|
||||
pub struct Error {
|
||||
pub(crate) code: ErrorCode,
|
||||
pub(crate) cause: Option<InnerError>,
|
||||
}
|
||||
|
||||
impl Error {
|
||||
pub fn code(&self) -> ErrorCode {
|
||||
self.code
|
||||
}
|
||||
|
||||
pub fn io_error(&self) -> Option<&io::Error> {
|
||||
match self.cause {
|
||||
Some(InnerError::Io(ref e)) => Some(e),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_io_error(self) -> Result<io::Error, Error> {
|
||||
match self.cause {
|
||||
Some(InnerError::Io(e)) => Ok(e),
|
||||
_ => Err(self),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ssl_error(&self) -> Option<&ErrorStack> {
|
||||
match self.cause {
|
||||
Some(InnerError::Ssl(ref e)) => Some(e),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ErrorStack> for Error {
|
||||
fn from(e: ErrorStack) -> Error {
|
||||
Error {
|
||||
code: ErrorCode::SSL,
|
||||
cause: Some(InnerError::Ssl(e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.code {
|
||||
ErrorCode::ZERO_RETURN => fmt.write_str("the SSL session has been shut down"),
|
||||
ErrorCode::WANT_READ => match self.io_error() {
|
||||
Some(_) => fmt.write_str("a nonblocking read call would have blocked"),
|
||||
None => fmt.write_str("the operation should be retried"),
|
||||
},
|
||||
ErrorCode::WANT_WRITE => match self.io_error() {
|
||||
Some(_) => fmt.write_str("a nonblocking write call would have blocked"),
|
||||
None => fmt.write_str("the operation should be retried"),
|
||||
},
|
||||
ErrorCode::SYSCALL => match self.io_error() {
|
||||
Some(err) => write!(fmt, "{}", err),
|
||||
None => fmt.write_str("unexpected EOF"),
|
||||
},
|
||||
ErrorCode::SSL => match self.ssl_error() {
|
||||
Some(e) => write!(fmt, "{}", e),
|
||||
None => fmt.write_str("OpenSSL error"),
|
||||
},
|
||||
ErrorCode(code) => write!(fmt, "unknown error code {}", code),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for Error {
|
||||
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
||||
match self.cause {
|
||||
Some(InnerError::Io(ref e)) => Some(e),
|
||||
Some(InnerError::Ssl(ref e)) => Some(e),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An error or intermediate state after a TLS handshake attempt.
|
||||
// FIXME overhaul
|
||||
#[derive(Debug)]
|
||||
pub enum HandshakeError<S> {
|
||||
/// Setup failed.
|
||||
SetupFailure(ErrorStack),
|
||||
/// The handshake failed.
|
||||
Failure(MidHandshakeSslStream<S>),
|
||||
/// The handshake encountered a `WouldBlock` error midway through.
|
||||
///
|
||||
/// This error will never be returned for blocking streams.
|
||||
WouldBlock(MidHandshakeSslStream<S>),
|
||||
}
|
||||
|
||||
impl<S: fmt::Debug> StdError for HandshakeError<S> {
|
||||
fn source(&self) -> Option<&(dyn StdError + 'static)> {
|
||||
match *self {
|
||||
HandshakeError::SetupFailure(ref e) => Some(e),
|
||||
HandshakeError::Failure(ref s) | HandshakeError::WouldBlock(ref s) => Some(s.error()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: fmt::Debug> fmt::Display for HandshakeError<S> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
HandshakeError::SetupFailure(ref e) => write!(f, "stream setup failed: {}", e)?,
|
||||
HandshakeError::Failure(ref s) => {
|
||||
write!(f, "the handshake failed: {}", s.error())?;
|
||||
let verify = s.ssl().verify_result();
|
||||
if verify != X509VerifyResult::OK {
|
||||
write!(f, ": {}", verify)?;
|
||||
}
|
||||
}
|
||||
HandshakeError::WouldBlock(ref s) => {
|
||||
write!(f, "the handshake was interrupted: {}", s.error())?;
|
||||
let verify = s.ssl().verify_result();
|
||||
if verify != X509VerifyResult::OK {
|
||||
write!(f, ": {}", verify)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> From<ErrorStack> for HandshakeError<S> {
|
||||
fn from(e: ErrorStack) -> HandshakeError<S> {
|
||||
HandshakeError::SetupFailure(e)
|
||||
}
|
||||
}
|
||||
4345
vendor/openssl/src/ssl/mod.rs
vendored
Normal file
4345
vendor/openssl/src/ssl/mod.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
1687
vendor/openssl/src/ssl/test/mod.rs
vendored
Normal file
1687
vendor/openssl/src/ssl/test/mod.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
167
vendor/openssl/src/ssl/test/server.rs
vendored
Normal file
167
vendor/openssl/src/ssl/test/server.rs
vendored
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
use std::io::{Read, Write};
|
||||
use std::net::{SocketAddr, TcpListener, TcpStream};
|
||||
use std::thread::{self, JoinHandle};
|
||||
|
||||
use crate::ssl::{Ssl, SslContext, SslContextBuilder, SslFiletype, SslMethod, SslRef, SslStream};
|
||||
|
||||
pub struct Server {
|
||||
handle: Option<JoinHandle<()>>,
|
||||
addr: SocketAddr,
|
||||
}
|
||||
|
||||
impl Drop for Server {
|
||||
fn drop(&mut self) {
|
||||
if !thread::panicking() {
|
||||
self.handle.take().unwrap().join().unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Server {
|
||||
pub fn builder() -> Builder {
|
||||
let mut ctx = SslContext::builder(SslMethod::tls()).unwrap();
|
||||
ctx.set_certificate_chain_file("test/cert.pem").unwrap();
|
||||
ctx.set_private_key_file("test/key.pem", SslFiletype::PEM)
|
||||
.unwrap();
|
||||
|
||||
Builder {
|
||||
ctx,
|
||||
ssl_cb: Box::new(|_| {}),
|
||||
io_cb: Box::new(|_| {}),
|
||||
should_error: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn client(&self) -> ClientBuilder {
|
||||
ClientBuilder {
|
||||
ctx: SslContext::builder(SslMethod::tls()).unwrap(),
|
||||
addr: self.addr,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn connect_tcp(&self) -> TcpStream {
|
||||
TcpStream::connect(self.addr).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Builder {
|
||||
ctx: SslContextBuilder,
|
||||
ssl_cb: Box<dyn FnMut(&mut SslRef) + Send>,
|
||||
io_cb: Box<dyn FnMut(SslStream<TcpStream>) + Send>,
|
||||
should_error: bool,
|
||||
}
|
||||
|
||||
impl Builder {
|
||||
pub fn ctx(&mut self) -> &mut SslContextBuilder {
|
||||
&mut self.ctx
|
||||
}
|
||||
|
||||
pub fn ssl_cb<F>(&mut self, cb: F)
|
||||
where
|
||||
F: 'static + FnMut(&mut SslRef) + Send,
|
||||
{
|
||||
self.ssl_cb = Box::new(cb);
|
||||
}
|
||||
|
||||
pub fn io_cb<F>(&mut self, cb: F)
|
||||
where
|
||||
F: 'static + FnMut(SslStream<TcpStream>) + Send,
|
||||
{
|
||||
self.io_cb = Box::new(cb);
|
||||
}
|
||||
|
||||
pub fn should_error(&mut self) {
|
||||
self.should_error = true;
|
||||
}
|
||||
|
||||
pub fn build(self) -> Server {
|
||||
let ctx = self.ctx.build();
|
||||
let socket = TcpListener::bind("127.0.0.1:0").unwrap();
|
||||
let addr = socket.local_addr().unwrap();
|
||||
let mut ssl_cb = self.ssl_cb;
|
||||
let mut io_cb = self.io_cb;
|
||||
let should_error = self.should_error;
|
||||
|
||||
let handle = thread::spawn(move || {
|
||||
let socket = socket.accept().unwrap().0;
|
||||
let mut ssl = Ssl::new(&ctx).unwrap();
|
||||
ssl_cb(&mut ssl);
|
||||
let r = ssl.accept(socket);
|
||||
if should_error {
|
||||
r.unwrap_err();
|
||||
} else {
|
||||
let mut socket = r.unwrap();
|
||||
socket.write_all(&[0]).unwrap();
|
||||
io_cb(socket);
|
||||
}
|
||||
});
|
||||
|
||||
Server {
|
||||
handle: Some(handle),
|
||||
addr,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ClientBuilder {
|
||||
ctx: SslContextBuilder,
|
||||
addr: SocketAddr,
|
||||
}
|
||||
|
||||
impl ClientBuilder {
|
||||
pub fn ctx(&mut self) -> &mut SslContextBuilder {
|
||||
&mut self.ctx
|
||||
}
|
||||
|
||||
pub fn build(self) -> Client {
|
||||
Client {
|
||||
ctx: self.ctx.build(),
|
||||
addr: self.addr,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn connect(self) -> SslStream<TcpStream> {
|
||||
self.build().builder().connect()
|
||||
}
|
||||
|
||||
pub fn connect_err(self) {
|
||||
self.build().builder().connect_err();
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Client {
|
||||
ctx: SslContext,
|
||||
addr: SocketAddr,
|
||||
}
|
||||
|
||||
impl Client {
|
||||
pub fn builder(&self) -> ClientSslBuilder {
|
||||
ClientSslBuilder {
|
||||
ssl: Ssl::new(&self.ctx).unwrap(),
|
||||
addr: self.addr,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ClientSslBuilder {
|
||||
ssl: Ssl,
|
||||
addr: SocketAddr,
|
||||
}
|
||||
|
||||
impl ClientSslBuilder {
|
||||
pub fn ssl(&mut self) -> &mut SslRef {
|
||||
&mut self.ssl
|
||||
}
|
||||
|
||||
pub fn connect(self) -> SslStream<TcpStream> {
|
||||
let socket = TcpStream::connect(self.addr).unwrap();
|
||||
let mut s = self.ssl.connect(socket).unwrap();
|
||||
s.read_exact(&mut [0]).unwrap();
|
||||
s
|
||||
}
|
||||
|
||||
pub fn connect_err(self) {
|
||||
let socket = TcpStream::connect(self.addr).unwrap();
|
||||
self.ssl.connect(socket).unwrap_err();
|
||||
}
|
||||
}
|
||||
380
vendor/openssl/src/stack.rs
vendored
Normal file
380
vendor/openssl/src/stack.rs
vendored
Normal file
|
|
@ -0,0 +1,380 @@
|
|||
use cfg_if::cfg_if;
|
||||
use foreign_types::{ForeignType, ForeignTypeRef, Opaque};
|
||||
use libc::c_int;
|
||||
use std::borrow::Borrow;
|
||||
use std::convert::AsRef;
|
||||
use std::fmt;
|
||||
use std::iter;
|
||||
use std::marker::PhantomData;
|
||||
use std::mem;
|
||||
use std::ops::{Deref, DerefMut, Index, IndexMut, Range};
|
||||
|
||||
use crate::error::ErrorStack;
|
||||
use crate::util::ForeignTypeExt;
|
||||
use crate::{cvt, cvt_p, LenType};
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl110, boringssl))] {
|
||||
use ffi::{
|
||||
OPENSSL_sk_pop, OPENSSL_sk_free, OPENSSL_sk_num, OPENSSL_sk_value, OPENSSL_STACK,
|
||||
OPENSSL_sk_new_null, OPENSSL_sk_push,
|
||||
};
|
||||
} else {
|
||||
use ffi::{
|
||||
sk_pop as OPENSSL_sk_pop, sk_free as OPENSSL_sk_free, sk_num as OPENSSL_sk_num,
|
||||
sk_value as OPENSSL_sk_value, _STACK as OPENSSL_STACK,
|
||||
sk_new_null as OPENSSL_sk_new_null, sk_push as OPENSSL_sk_push,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait implemented by types which can be placed in a stack.
|
||||
///
|
||||
/// It should not be implemented for any type outside of this crate.
|
||||
pub trait Stackable: ForeignType {
|
||||
/// 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<T: Stackable>(*mut T::StackType);
|
||||
|
||||
unsafe impl<T: Stackable + Send> Send for Stack<T> {}
|
||||
unsafe impl<T: Stackable + Sync> Sync for Stack<T> {}
|
||||
|
||||
impl<T> fmt::Debug for Stack<T>
|
||||
where
|
||||
T: Stackable,
|
||||
T::Ref: fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt.debug_list().entries(self).finish()
|
||||
}
|
||||
}
|
||||
impl<T: Stackable> Drop for Stack<T> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
while self.pop().is_some() {}
|
||||
OPENSSL_sk_free(self.0 as *mut _);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Stackable> Stack<T> {
|
||||
pub fn new() -> Result<Stack<T>, ErrorStack> {
|
||||
unsafe {
|
||||
ffi::init();
|
||||
let ptr = cvt_p(OPENSSL_sk_new_null())?;
|
||||
Ok(Stack(ptr as *mut _))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Stackable> iter::IntoIterator for Stack<T> {
|
||||
type IntoIter = IntoIter<T>;
|
||||
type Item = T;
|
||||
|
||||
fn into_iter(self) -> IntoIter<T> {
|
||||
let it = IntoIter {
|
||||
stack: self.0,
|
||||
idxs: 0..self.len() as LenType,
|
||||
};
|
||||
mem::forget(self);
|
||||
it
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Stackable> AsRef<StackRef<T>> for Stack<T> {
|
||||
fn as_ref(&self) -> &StackRef<T> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Stackable> Borrow<StackRef<T>> for Stack<T> {
|
||||
fn borrow(&self) -> &StackRef<T> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Stackable> ForeignType for Stack<T> {
|
||||
type CType = T::StackType;
|
||||
type Ref = StackRef<T>;
|
||||
|
||||
#[inline]
|
||||
unsafe fn from_ptr(ptr: *mut T::StackType) -> Stack<T> {
|
||||
assert!(
|
||||
!ptr.is_null(),
|
||||
"Must not instantiate a Stack from a null-ptr - use Stack::new() in \
|
||||
that case"
|
||||
);
|
||||
Stack(ptr)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_ptr(&self) -> *mut T::StackType {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Stackable> Deref for Stack<T> {
|
||||
type Target = StackRef<T>;
|
||||
|
||||
fn deref(&self) -> &StackRef<T> {
|
||||
unsafe { StackRef::from_ptr(self.0) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Stackable> DerefMut for Stack<T> {
|
||||
fn deref_mut(&mut self) -> &mut StackRef<T> {
|
||||
unsafe { StackRef::from_ptr_mut(self.0) }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IntoIter<T: Stackable> {
|
||||
stack: *mut T::StackType,
|
||||
idxs: Range<LenType>,
|
||||
}
|
||||
|
||||
impl<T: Stackable> Drop for IntoIter<T> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
// https://github.com/rust-lang/rust-clippy/issues/7510
|
||||
#[allow(clippy::while_let_on_iterator)]
|
||||
while let Some(_) = self.next() {}
|
||||
OPENSSL_sk_free(self.stack as *mut _);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Stackable> Iterator for IntoIter<T> {
|
||||
type Item = T;
|
||||
|
||||
fn next(&mut self) -> Option<T> {
|
||||
unsafe {
|
||||
self.idxs
|
||||
.next()
|
||||
.map(|i| T::from_ptr(OPENSSL_sk_value(self.stack as *mut _, i) as *mut _))
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.idxs.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Stackable> DoubleEndedIterator for IntoIter<T> {
|
||||
fn next_back(&mut self) -> Option<T> {
|
||||
unsafe {
|
||||
self.idxs
|
||||
.next_back()
|
||||
.map(|i| T::from_ptr(OPENSSL_sk_value(self.stack as *mut _, i) as *mut _))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Stackable> ExactSizeIterator for IntoIter<T> {}
|
||||
|
||||
pub struct StackRef<T: Stackable>(Opaque, PhantomData<T>);
|
||||
|
||||
unsafe impl<T: Stackable + Send> Send for StackRef<T> {}
|
||||
unsafe impl<T: Stackable + Sync> Sync for StackRef<T> {}
|
||||
|
||||
impl<T: Stackable> ForeignTypeRef for StackRef<T> {
|
||||
type CType = T::StackType;
|
||||
}
|
||||
|
||||
impl<T: Stackable> StackRef<T> {
|
||||
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 }
|
||||
}
|
||||
|
||||
/// Determines if the stack is empty.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> Iter<'_, T> {
|
||||
Iter {
|
||||
stack: self,
|
||||
idxs: 0..self.len() as LenType,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iter_mut(&mut self) -> IterMut<'_, T> {
|
||||
IterMut {
|
||||
idxs: 0..self.len() as LenType,
|
||||
stack: self,
|
||||
}
|
||||
}
|
||||
|
||||
/// 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)))
|
||||
}
|
||||
}
|
||||
|
||||
/// Pushes a value onto the top of the stack.
|
||||
pub fn push(&mut self, data: T) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(OPENSSL_sk_push(self.as_stack(), data.as_ptr() as *mut _) as c_int)?;
|
||||
mem::forget(data);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes the last element from the stack and returns it.
|
||||
pub fn pop(&mut self) -> Option<T> {
|
||||
unsafe {
|
||||
let ptr = OPENSSL_sk_pop(self.as_stack());
|
||||
T::from_ptr_opt(ptr as *mut _)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn _get(&self, idx: usize) -> *mut T::CType {
|
||||
OPENSSL_sk_value(self.as_stack(), idx as LenType) as *mut _
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Stackable> Index<usize> for StackRef<T> {
|
||||
type Output = T::Ref;
|
||||
|
||||
fn index(&self, index: usize) -> &T::Ref {
|
||||
self.get(index).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Stackable> IndexMut<usize> for StackRef<T> {
|
||||
fn index_mut(&mut self, index: usize) -> &mut T::Ref {
|
||||
self.get_mut(index).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Stackable> iter::IntoIterator for &'a StackRef<T> {
|
||||
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<T> {
|
||||
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<T> {
|
||||
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<T> {
|
||||
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> {
|
||||
stack: &'a StackRef<T>,
|
||||
idxs: Range<LenType>,
|
||||
}
|
||||
|
||||
impl<'a, T: Stackable> Iterator for Iter<'a, T> {
|
||||
type Item = &'a T::Ref;
|
||||
|
||||
fn next(&mut self) -> Option<&'a T::Ref> {
|
||||
unsafe {
|
||||
self.idxs
|
||||
.next()
|
||||
.map(|i| T::Ref::from_ptr(OPENSSL_sk_value(self.stack.as_stack(), i) as *mut _))
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.idxs.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Stackable> DoubleEndedIterator for Iter<'a, T> {
|
||||
fn next_back(&mut self) -> Option<&'a T::Ref> {
|
||||
unsafe {
|
||||
self.idxs
|
||||
.next_back()
|
||||
.map(|i| T::Ref::from_ptr(OPENSSL_sk_value(self.stack.as_stack(), i) as *mut _))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Stackable> ExactSizeIterator for Iter<'_, T> {}
|
||||
|
||||
/// A mutable iterator over the stack's contents.
|
||||
pub struct IterMut<'a, T: Stackable> {
|
||||
stack: &'a mut StackRef<T>,
|
||||
idxs: Range<LenType>,
|
||||
}
|
||||
|
||||
impl<'a, T: Stackable> Iterator for IterMut<'a, T> {
|
||||
type Item = &'a mut T::Ref;
|
||||
|
||||
fn next(&mut self) -> Option<&'a mut T::Ref> {
|
||||
unsafe {
|
||||
self.idxs
|
||||
.next()
|
||||
.map(|i| T::Ref::from_ptr_mut(OPENSSL_sk_value(self.stack.as_stack(), i) as *mut _))
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.idxs.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Stackable> DoubleEndedIterator for IterMut<'a, T> {
|
||||
fn next_back(&mut self) -> Option<&'a mut T::Ref> {
|
||||
unsafe {
|
||||
self.idxs
|
||||
.next_back()
|
||||
.map(|i| T::Ref::from_ptr_mut(OPENSSL_sk_value(self.stack.as_stack(), i) as *mut _))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Stackable> ExactSizeIterator for IterMut<'_, T> {}
|
||||
96
vendor/openssl/src/string.rs
vendored
Normal file
96
vendor/openssl/src/string.rs
vendored
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
use foreign_types::ForeignTypeRef;
|
||||
use libc::{c_char, c_void};
|
||||
use std::convert::AsRef;
|
||||
use std::ffi::CStr;
|
||||
use std::fmt;
|
||||
use std::ops::Deref;
|
||||
use std::str;
|
||||
|
||||
use crate::stack::Stackable;
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = c_char;
|
||||
fn drop = free;
|
||||
|
||||
pub struct OpensslString;
|
||||
pub struct OpensslStringRef;
|
||||
}
|
||||
|
||||
impl fmt::Display for OpensslString {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(&**self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for OpensslString {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Debug::fmt(&**self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Stackable for OpensslString {
|
||||
type StackType = ffi::stack_st_OPENSSL_STRING;
|
||||
}
|
||||
|
||||
impl AsRef<str> for OpensslString {
|
||||
fn as_ref(&self) -> &str {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for OpensslString {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.as_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for OpensslStringRef {
|
||||
type Target = str;
|
||||
|
||||
fn deref(&self) -> &str {
|
||||
unsafe {
|
||||
let slice = CStr::from_ptr(self.as_ptr()).to_bytes();
|
||||
str::from_utf8_unchecked(slice)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for OpensslStringRef {
|
||||
fn as_ref(&self) -> &str {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for OpensslStringRef {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.as_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for OpensslStringRef {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(&**self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for OpensslStringRef {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Debug::fmt(&**self, f)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(not(boringssl))]
|
||||
unsafe fn free(buf: *mut c_char) {
|
||||
ffi::OPENSSL_free(buf as *mut c_void);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg(boringssl)]
|
||||
unsafe fn free(buf: *mut c_char) {
|
||||
ffi::CRYPTO_free(
|
||||
buf as *mut c_void,
|
||||
concat!(file!(), "\0").as_ptr() as *const c_char,
|
||||
line!() as ::libc::c_int,
|
||||
);
|
||||
}
|
||||
1763
vendor/openssl/src/symm.rs
vendored
Normal file
1763
vendor/openssl/src/symm.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
118
vendor/openssl/src/util.rs
vendored
Normal file
118
vendor/openssl/src/util.rs
vendored
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
use crate::error::ErrorStack;
|
||||
use crate::util;
|
||||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
use libc::{c_char, c_int, c_void};
|
||||
use std::any::Any;
|
||||
use std::panic::{self, AssertUnwindSafe};
|
||||
use std::slice;
|
||||
|
||||
/// Wraps a user-supplied callback and a slot for panics thrown inside the callback (while FFI
|
||||
/// frames are on the stack).
|
||||
///
|
||||
/// When dropped, checks if the callback has panicked, and resumes unwinding if so.
|
||||
pub struct CallbackState<F> {
|
||||
/// The user callback. Taken out of the `Option` when called.
|
||||
cb: Option<F>,
|
||||
/// If the callback panics, we place the panic object here, to be re-thrown once OpenSSL
|
||||
/// returns.
|
||||
panic: Option<Box<dyn Any + Send + 'static>>,
|
||||
}
|
||||
|
||||
impl<F> CallbackState<F> {
|
||||
pub fn new(callback: F) -> Self {
|
||||
CallbackState {
|
||||
cb: Some(callback),
|
||||
panic: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> Drop for CallbackState<F> {
|
||||
fn drop(&mut self) {
|
||||
if let Some(panic) = self.panic.take() {
|
||||
panic::resume_unwind(panic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Password callback function, passed to private key loading functions.
|
||||
///
|
||||
/// `cb_state` is expected to be a pointer to a `CallbackState`.
|
||||
pub unsafe extern "C" fn invoke_passwd_cb<F>(
|
||||
buf: *mut c_char,
|
||||
size: c_int,
|
||||
_rwflag: c_int,
|
||||
cb_state: *mut c_void,
|
||||
) -> c_int
|
||||
where
|
||||
F: FnOnce(&mut [u8]) -> Result<usize, ErrorStack>,
|
||||
{
|
||||
let callback = &mut *(cb_state as *mut CallbackState<F>);
|
||||
|
||||
let result = panic::catch_unwind(AssertUnwindSafe(|| {
|
||||
let pass_slice = util::from_raw_parts_mut(buf as *mut u8, size as usize);
|
||||
callback.cb.take().unwrap()(pass_slice)
|
||||
}));
|
||||
|
||||
match result {
|
||||
Ok(Ok(len)) => len as c_int,
|
||||
Ok(Err(_)) => {
|
||||
// FIXME restore error stack
|
||||
0
|
||||
}
|
||||
Err(err) => {
|
||||
callback.panic = Some(err);
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ForeignTypeExt: ForeignType {
|
||||
unsafe fn from_ptr_opt(ptr: *mut Self::CType) -> Option<Self> {
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(Self::from_ptr(ptr))
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<FT: ForeignType> ForeignTypeExt for FT {}
|
||||
|
||||
pub trait ForeignTypeRefExt: ForeignTypeRef {
|
||||
unsafe fn from_const_ptr<'a>(ptr: *const Self::CType) -> &'a Self {
|
||||
Self::from_ptr(ptr as *mut Self::CType)
|
||||
}
|
||||
|
||||
unsafe fn from_const_ptr_opt<'a>(ptr: *const Self::CType) -> Option<&'a Self> {
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(Self::from_const_ptr(ptr as *mut Self::CType))
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<FT: ForeignTypeRef> ForeignTypeRefExt for FT {}
|
||||
|
||||
/// The same as `slice::from_raw_parts`, except that `data` may be `NULL` if
|
||||
/// `len` is 0.
|
||||
pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] {
|
||||
if len == 0 {
|
||||
&[]
|
||||
} else {
|
||||
// Using this to implement the preferred API
|
||||
#[allow(clippy::disallowed_methods)]
|
||||
slice::from_raw_parts(data, len)
|
||||
}
|
||||
}
|
||||
|
||||
/// The same as `slice::from_raw_parts_mut`, except that `data` may be `NULL`
|
||||
/// if `len` is 0.
|
||||
pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] {
|
||||
if len == 0 {
|
||||
&mut []
|
||||
} else {
|
||||
// Using this to implement the preferred API
|
||||
#[allow(clippy::disallowed_methods)]
|
||||
slice::from_raw_parts_mut(data, len)
|
||||
}
|
||||
}
|
||||
134
vendor/openssl/src/version.rs
vendored
Normal file
134
vendor/openssl/src/version.rs
vendored
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
// 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.
|
||||
//
|
||||
|
||||
//! Build and version information.
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
use openssl_macros::corresponds;
|
||||
use std::ffi::CStr;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(ossl110, libressl271))] {
|
||||
use ffi::{
|
||||
OPENSSL_VERSION, OPENSSL_CFLAGS, OPENSSL_BUILT_ON, OPENSSL_PLATFORM, OPENSSL_DIR,
|
||||
OpenSSL_version_num, OpenSSL_version,
|
||||
};
|
||||
} else {
|
||||
use ffi::{
|
||||
SSLEAY_VERSION as OPENSSL_VERSION, SSLEAY_CFLAGS as OPENSSL_CFLAGS,
|
||||
SSLEAY_BUILT_ON as OPENSSL_BUILT_ON, SSLEAY_PLATFORM as OPENSSL_PLATFORM,
|
||||
SSLEAY_DIR as OPENSSL_DIR, SSLeay as OpenSSL_version_num,
|
||||
SSLeay_version as OpenSSL_version,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// OPENSSL_VERSION_NUMBER is a numeric release version identifier:
|
||||
///
|
||||
/// `MNNFFPPS: major minor fix patch status`
|
||||
///
|
||||
/// The status nibble has one of the values 0 for development, 1 to e for betas 1 to 14, and f for release.
|
||||
///
|
||||
/// for example
|
||||
///
|
||||
/// `0x000906000 == 0.9.6 dev`
|
||||
/// `0x000906023 == 0.9.6b beta 3`
|
||||
/// `0x00090605f == 0.9.6e release`
|
||||
#[corresponds(OpenSSL_version_num)]
|
||||
pub fn number() -> 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".
|
||||
#[corresponds(OpenSSL_version)]
|
||||
pub fn version() -> &'static str {
|
||||
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.
|
||||
#[corresponds(OpenSSL_version)]
|
||||
pub fn c_flags() -> &'static str {
|
||||
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.
|
||||
#[corresponds(OpenSSL_version)]
|
||||
pub fn built_on() -> &'static str {
|
||||
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.
|
||||
#[corresponds(OpenSSL_version)]
|
||||
pub fn platform() -> &'static str {
|
||||
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.
|
||||
#[corresponds(OpenSSL_version)]
|
||||
pub fn dir() -> &'static str {
|
||||
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
|
||||
/// and that the strings respect a reasonable format.
|
||||
#[test]
|
||||
fn test_versions() {
|
||||
println!("Number: '{}'", number());
|
||||
println!("Version: '{}'", version());
|
||||
println!("C flags: '{}'", c_flags());
|
||||
println!("Built on: '{}'", built_on());
|
||||
println!("Platform: '{}'", platform());
|
||||
println!("Dir: '{}'", dir());
|
||||
|
||||
#[cfg(not(any(libressl, boringssl)))]
|
||||
fn expected_name() -> &'static str {
|
||||
"OpenSSL"
|
||||
}
|
||||
#[cfg(libressl)]
|
||||
fn expected_name() -> &'static str {
|
||||
"LibreSSL"
|
||||
}
|
||||
#[cfg(boringssl)]
|
||||
fn expected_name() -> &'static str {
|
||||
"BoringSSL"
|
||||
}
|
||||
|
||||
assert!(number() > 0);
|
||||
assert!(version().starts_with(expected_name()));
|
||||
assert!(c_flags().starts_with("compiler:"));
|
||||
// some distributions patch out dates out of openssl so that the builds are reproducible
|
||||
if !built_on().is_empty() {
|
||||
assert!(built_on().starts_with("built on:"));
|
||||
}
|
||||
}
|
||||
562
vendor/openssl/src/x509/extension.rs
vendored
Normal file
562
vendor/openssl/src/x509/extension.rs
vendored
Normal file
|
|
@ -0,0 +1,562 @@
|
|||
//! Add extensions to an `X509` certificate or certificate request.
|
||||
//!
|
||||
//! The extensions defined for X.509 v3 certificates provide methods for
|
||||
//! associating additional attributes with users or public keys and for
|
||||
//! managing relationships between CAs. The extensions created using this
|
||||
//! module can be used with `X509v3Context` objects.
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! ```rust
|
||||
//! use openssl::x509::extension::BasicConstraints;
|
||||
//! use openssl::x509::X509Extension;
|
||||
//!
|
||||
//! let mut bc = BasicConstraints::new();
|
||||
//! let bc = bc.critical().ca().pathlen(1);
|
||||
//!
|
||||
//! let extension: X509Extension = bc.build().unwrap();
|
||||
//! ```
|
||||
use std::fmt::Write;
|
||||
|
||||
use crate::asn1::Asn1Object;
|
||||
use crate::error::ErrorStack;
|
||||
use crate::nid::Nid;
|
||||
use crate::x509::{GeneralName, Stack, X509Extension, X509v3Context};
|
||||
use foreign_types::ForeignType;
|
||||
|
||||
/// An extension which indicates whether a certificate is a CA certificate.
|
||||
pub struct BasicConstraints {
|
||||
critical: bool,
|
||||
ca: bool,
|
||||
pathlen: Option<u32>,
|
||||
}
|
||||
|
||||
impl Default for BasicConstraints {
|
||||
fn default() -> BasicConstraints {
|
||||
BasicConstraints::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl BasicConstraints {
|
||||
/// Construct a new `BasicConstraints` extension.
|
||||
pub fn new() -> BasicConstraints {
|
||||
BasicConstraints {
|
||||
critical: false,
|
||||
ca: false,
|
||||
pathlen: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the `critical` flag to `true`. The extension will be critical.
|
||||
pub fn critical(&mut self) -> &mut BasicConstraints {
|
||||
self.critical = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `ca` flag to `true`.
|
||||
pub fn ca(&mut self) -> &mut BasicConstraints {
|
||||
self.ca = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `pathlen` to an optional non-negative value. The `pathlen` is the
|
||||
/// maximum number of CAs that can appear below this one in a chain.
|
||||
pub fn pathlen(&mut self, pathlen: u32) -> &mut BasicConstraints {
|
||||
self.pathlen = Some(pathlen);
|
||||
self
|
||||
}
|
||||
|
||||
/// Return the `BasicConstraints` extension as an `X509Extension`.
|
||||
// Temporarily silence the deprecation warning - this should be ported to
|
||||
// `X509Extension::new_internal`.
|
||||
#[allow(deprecated)]
|
||||
pub fn build(&self) -> Result<X509Extension, ErrorStack> {
|
||||
let mut value = String::new();
|
||||
if self.critical {
|
||||
value.push_str("critical,");
|
||||
}
|
||||
value.push_str("CA:");
|
||||
if self.ca {
|
||||
value.push_str("TRUE");
|
||||
} else {
|
||||
value.push_str("FALSE");
|
||||
}
|
||||
if let Some(pathlen) = self.pathlen {
|
||||
write!(value, ",pathlen:{}", pathlen).unwrap();
|
||||
}
|
||||
X509Extension::new_nid(None, None, Nid::BASIC_CONSTRAINTS, &value)
|
||||
}
|
||||
}
|
||||
|
||||
/// An extension consisting of a list of names of the permitted key usages.
|
||||
pub struct KeyUsage {
|
||||
critical: bool,
|
||||
digital_signature: bool,
|
||||
non_repudiation: bool,
|
||||
key_encipherment: bool,
|
||||
data_encipherment: bool,
|
||||
key_agreement: bool,
|
||||
key_cert_sign: bool,
|
||||
crl_sign: bool,
|
||||
encipher_only: bool,
|
||||
decipher_only: bool,
|
||||
}
|
||||
|
||||
impl Default for KeyUsage {
|
||||
fn default() -> KeyUsage {
|
||||
KeyUsage::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl KeyUsage {
|
||||
/// Construct a new `KeyUsage` extension.
|
||||
pub fn new() -> KeyUsage {
|
||||
KeyUsage {
|
||||
critical: false,
|
||||
digital_signature: false,
|
||||
non_repudiation: false,
|
||||
key_encipherment: false,
|
||||
data_encipherment: false,
|
||||
key_agreement: false,
|
||||
key_cert_sign: false,
|
||||
crl_sign: false,
|
||||
encipher_only: false,
|
||||
decipher_only: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the `critical` flag to `true`. The extension will be critical.
|
||||
pub fn critical(&mut self) -> &mut KeyUsage {
|
||||
self.critical = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `digitalSignature` flag to `true`.
|
||||
pub fn digital_signature(&mut self) -> &mut KeyUsage {
|
||||
self.digital_signature = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `nonRepudiation` flag to `true`.
|
||||
pub fn non_repudiation(&mut self) -> &mut KeyUsage {
|
||||
self.non_repudiation = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `keyEncipherment` flag to `true`.
|
||||
pub fn key_encipherment(&mut self) -> &mut KeyUsage {
|
||||
self.key_encipherment = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `dataEncipherment` flag to `true`.
|
||||
pub fn data_encipherment(&mut self) -> &mut KeyUsage {
|
||||
self.data_encipherment = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `keyAgreement` flag to `true`.
|
||||
pub fn key_agreement(&mut self) -> &mut KeyUsage {
|
||||
self.key_agreement = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `keyCertSign` flag to `true`.
|
||||
pub fn key_cert_sign(&mut self) -> &mut KeyUsage {
|
||||
self.key_cert_sign = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `cRLSign` flag to `true`.
|
||||
pub fn crl_sign(&mut self) -> &mut KeyUsage {
|
||||
self.crl_sign = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `encipherOnly` flag to `true`.
|
||||
pub fn encipher_only(&mut self) -> &mut KeyUsage {
|
||||
self.encipher_only = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `decipherOnly` flag to `true`.
|
||||
pub fn decipher_only(&mut self) -> &mut KeyUsage {
|
||||
self.decipher_only = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Return the `KeyUsage` extension as an `X509Extension`.
|
||||
// Temporarily silence the deprecation warning - this should be ported to
|
||||
// `X509Extension::new_internal`.
|
||||
#[allow(deprecated)]
|
||||
pub fn build(&self) -> Result<X509Extension, ErrorStack> {
|
||||
let mut value = String::new();
|
||||
let mut first = true;
|
||||
append(&mut value, &mut first, self.critical, "critical");
|
||||
append(
|
||||
&mut value,
|
||||
&mut first,
|
||||
self.digital_signature,
|
||||
"digitalSignature",
|
||||
);
|
||||
append(
|
||||
&mut value,
|
||||
&mut first,
|
||||
self.non_repudiation,
|
||||
"nonRepudiation",
|
||||
);
|
||||
append(
|
||||
&mut value,
|
||||
&mut first,
|
||||
self.key_encipherment,
|
||||
"keyEncipherment",
|
||||
);
|
||||
append(
|
||||
&mut value,
|
||||
&mut first,
|
||||
self.data_encipherment,
|
||||
"dataEncipherment",
|
||||
);
|
||||
append(&mut value, &mut first, self.key_agreement, "keyAgreement");
|
||||
append(&mut value, &mut first, self.key_cert_sign, "keyCertSign");
|
||||
append(&mut value, &mut first, self.crl_sign, "cRLSign");
|
||||
append(&mut value, &mut first, self.encipher_only, "encipherOnly");
|
||||
append(&mut value, &mut first, self.decipher_only, "decipherOnly");
|
||||
X509Extension::new_nid(None, None, Nid::KEY_USAGE, &value)
|
||||
}
|
||||
}
|
||||
|
||||
/// An extension consisting of a list of usages indicating purposes
|
||||
/// for which the certificate public key can be used for.
|
||||
pub struct ExtendedKeyUsage {
|
||||
critical: bool,
|
||||
items: Vec<String>,
|
||||
}
|
||||
|
||||
impl Default for ExtendedKeyUsage {
|
||||
fn default() -> ExtendedKeyUsage {
|
||||
ExtendedKeyUsage::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtendedKeyUsage {
|
||||
/// Construct a new `ExtendedKeyUsage` extension.
|
||||
pub fn new() -> ExtendedKeyUsage {
|
||||
ExtendedKeyUsage {
|
||||
critical: false,
|
||||
items: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the `critical` flag to `true`. The extension will be critical.
|
||||
pub fn critical(&mut self) -> &mut ExtendedKeyUsage {
|
||||
self.critical = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `serverAuth` flag to `true`.
|
||||
pub fn server_auth(&mut self) -> &mut ExtendedKeyUsage {
|
||||
self.other("serverAuth")
|
||||
}
|
||||
|
||||
/// Sets the `clientAuth` flag to `true`.
|
||||
pub fn client_auth(&mut self) -> &mut ExtendedKeyUsage {
|
||||
self.other("clientAuth")
|
||||
}
|
||||
|
||||
/// Sets the `codeSigning` flag to `true`.
|
||||
pub fn code_signing(&mut self) -> &mut ExtendedKeyUsage {
|
||||
self.other("codeSigning")
|
||||
}
|
||||
|
||||
/// Sets the `emailProtection` flag to `true`.
|
||||
pub fn email_protection(&mut self) -> &mut ExtendedKeyUsage {
|
||||
self.other("emailProtection")
|
||||
}
|
||||
|
||||
/// Sets the `timeStamping` flag to `true`.
|
||||
pub fn time_stamping(&mut self) -> &mut ExtendedKeyUsage {
|
||||
self.other("timeStamping")
|
||||
}
|
||||
|
||||
/// Sets the `msCodeInd` flag to `true`.
|
||||
pub fn ms_code_ind(&mut self) -> &mut ExtendedKeyUsage {
|
||||
self.other("msCodeInd")
|
||||
}
|
||||
|
||||
/// Sets the `msCodeCom` flag to `true`.
|
||||
pub fn ms_code_com(&mut self) -> &mut ExtendedKeyUsage {
|
||||
self.other("msCodeCom")
|
||||
}
|
||||
|
||||
/// Sets the `msCTLSign` flag to `true`.
|
||||
pub fn ms_ctl_sign(&mut self) -> &mut ExtendedKeyUsage {
|
||||
self.other("msCTLSign")
|
||||
}
|
||||
|
||||
/// Sets the `msSGC` flag to `true`.
|
||||
pub fn ms_sgc(&mut self) -> &mut ExtendedKeyUsage {
|
||||
self.other("msSGC")
|
||||
}
|
||||
|
||||
/// Sets the `msEFS` flag to `true`.
|
||||
pub fn ms_efs(&mut self) -> &mut ExtendedKeyUsage {
|
||||
self.other("msEFS")
|
||||
}
|
||||
|
||||
/// Sets the `nsSGC` flag to `true`.
|
||||
pub fn ns_sgc(&mut self) -> &mut ExtendedKeyUsage {
|
||||
self.other("nsSGC")
|
||||
}
|
||||
|
||||
/// Sets a flag not already defined.
|
||||
pub fn other(&mut self, other: &str) -> &mut ExtendedKeyUsage {
|
||||
self.items.push(other.to_string());
|
||||
self
|
||||
}
|
||||
|
||||
/// Return the `ExtendedKeyUsage` extension as an `X509Extension`.
|
||||
pub fn build(&self) -> Result<X509Extension, ErrorStack> {
|
||||
let mut stack = Stack::new()?;
|
||||
for item in &self.items {
|
||||
stack.push(Asn1Object::from_str(item)?)?;
|
||||
}
|
||||
unsafe {
|
||||
X509Extension::new_internal(Nid::EXT_KEY_USAGE, self.critical, stack.as_ptr().cast())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An extension that provides a means of identifying certificates that contain a
|
||||
/// particular public key.
|
||||
pub struct SubjectKeyIdentifier {
|
||||
critical: bool,
|
||||
}
|
||||
|
||||
impl Default for SubjectKeyIdentifier {
|
||||
fn default() -> SubjectKeyIdentifier {
|
||||
SubjectKeyIdentifier::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl SubjectKeyIdentifier {
|
||||
/// Construct a new `SubjectKeyIdentifier` extension.
|
||||
pub fn new() -> SubjectKeyIdentifier {
|
||||
SubjectKeyIdentifier { critical: false }
|
||||
}
|
||||
|
||||
/// Sets the `critical` flag to `true`. The extension will be critical.
|
||||
pub fn critical(&mut self) -> &mut SubjectKeyIdentifier {
|
||||
self.critical = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Return a `SubjectKeyIdentifier` extension as an `X509Extension`.
|
||||
// Temporarily silence the deprecation warning - this should be ported to
|
||||
// `X509Extension::new_internal`.
|
||||
#[allow(deprecated)]
|
||||
pub fn build(&self, ctx: &X509v3Context<'_>) -> Result<X509Extension, ErrorStack> {
|
||||
let mut value = String::new();
|
||||
let mut first = true;
|
||||
append(&mut value, &mut first, self.critical, "critical");
|
||||
append(&mut value, &mut first, true, "hash");
|
||||
X509Extension::new_nid(None, Some(ctx), Nid::SUBJECT_KEY_IDENTIFIER, &value)
|
||||
}
|
||||
}
|
||||
|
||||
/// An extension that provides a means of identifying the public key corresponding
|
||||
/// to the private key used to sign a CRL.
|
||||
pub struct AuthorityKeyIdentifier {
|
||||
critical: bool,
|
||||
keyid: Option<bool>,
|
||||
issuer: Option<bool>,
|
||||
}
|
||||
|
||||
impl Default for AuthorityKeyIdentifier {
|
||||
fn default() -> AuthorityKeyIdentifier {
|
||||
AuthorityKeyIdentifier::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl AuthorityKeyIdentifier {
|
||||
/// Construct a new `AuthorityKeyIdentifier` extension.
|
||||
pub fn new() -> AuthorityKeyIdentifier {
|
||||
AuthorityKeyIdentifier {
|
||||
critical: false,
|
||||
keyid: None,
|
||||
issuer: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the `critical` flag to `true`. The extension will be critical.
|
||||
pub fn critical(&mut self) -> &mut AuthorityKeyIdentifier {
|
||||
self.critical = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `keyid` flag.
|
||||
pub fn keyid(&mut self, always: bool) -> &mut AuthorityKeyIdentifier {
|
||||
self.keyid = Some(always);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `issuer` flag.
|
||||
pub fn issuer(&mut self, always: bool) -> &mut AuthorityKeyIdentifier {
|
||||
self.issuer = Some(always);
|
||||
self
|
||||
}
|
||||
|
||||
/// Return a `AuthorityKeyIdentifier` extension as an `X509Extension`.
|
||||
// Temporarily silence the deprecation warning - this should be ported to
|
||||
// `X509Extension::new_internal`.
|
||||
#[allow(deprecated)]
|
||||
pub fn build(&self, ctx: &X509v3Context<'_>) -> Result<X509Extension, ErrorStack> {
|
||||
let mut value = String::new();
|
||||
let mut first = true;
|
||||
append(&mut value, &mut first, self.critical, "critical");
|
||||
match self.keyid {
|
||||
Some(true) => append(&mut value, &mut first, true, "keyid:always"),
|
||||
Some(false) => append(&mut value, &mut first, true, "keyid"),
|
||||
None => {}
|
||||
}
|
||||
match self.issuer {
|
||||
Some(true) => append(&mut value, &mut first, true, "issuer:always"),
|
||||
Some(false) => append(&mut value, &mut first, true, "issuer"),
|
||||
None => {}
|
||||
}
|
||||
X509Extension::new_nid(None, Some(ctx), Nid::AUTHORITY_KEY_IDENTIFIER, &value)
|
||||
}
|
||||
}
|
||||
|
||||
enum RustGeneralName {
|
||||
Dns(String),
|
||||
Email(String),
|
||||
Uri(String),
|
||||
Ip(String),
|
||||
Rid(String),
|
||||
OtherName(Asn1Object, Vec<u8>),
|
||||
}
|
||||
|
||||
/// An extension that allows additional identities to be bound to the subject
|
||||
/// of the certificate.
|
||||
pub struct SubjectAlternativeName {
|
||||
critical: bool,
|
||||
items: Vec<RustGeneralName>,
|
||||
}
|
||||
|
||||
impl Default for SubjectAlternativeName {
|
||||
fn default() -> SubjectAlternativeName {
|
||||
SubjectAlternativeName::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl SubjectAlternativeName {
|
||||
/// Construct a new `SubjectAlternativeName` extension.
|
||||
pub fn new() -> SubjectAlternativeName {
|
||||
SubjectAlternativeName {
|
||||
critical: false,
|
||||
items: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the `critical` flag to `true`. The extension will be critical.
|
||||
pub fn critical(&mut self) -> &mut SubjectAlternativeName {
|
||||
self.critical = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `email` flag.
|
||||
pub fn email(&mut self, email: &str) -> &mut SubjectAlternativeName {
|
||||
self.items.push(RustGeneralName::Email(email.to_string()));
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `uri` flag.
|
||||
pub fn uri(&mut self, uri: &str) -> &mut SubjectAlternativeName {
|
||||
self.items.push(RustGeneralName::Uri(uri.to_string()));
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `dns` flag.
|
||||
pub fn dns(&mut self, dns: &str) -> &mut SubjectAlternativeName {
|
||||
self.items.push(RustGeneralName::Dns(dns.to_string()));
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `rid` flag.
|
||||
pub fn rid(&mut self, rid: &str) -> &mut SubjectAlternativeName {
|
||||
self.items.push(RustGeneralName::Rid(rid.to_string()));
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `ip` flag.
|
||||
pub fn ip(&mut self, ip: &str) -> &mut SubjectAlternativeName {
|
||||
self.items.push(RustGeneralName::Ip(ip.to_string()));
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the `dirName` flag.
|
||||
///
|
||||
/// Not currently actually supported, always panics.
|
||||
#[deprecated = "dir_name is deprecated and always panics. Please file a bug if you have a use case for this."]
|
||||
pub fn dir_name(&mut self, _dir_name: &str) -> &mut SubjectAlternativeName {
|
||||
unimplemented!(
|
||||
"This has not yet been adapted for the new internals. File a bug if you need this."
|
||||
);
|
||||
}
|
||||
|
||||
/// Sets the `otherName` flag.
|
||||
///
|
||||
/// Not currently actually supported, always panics. Please use other_name2
|
||||
#[deprecated = "other_name is deprecated and always panics. Please use other_name2."]
|
||||
pub fn other_name(&mut self, _other_name: &str) -> &mut SubjectAlternativeName {
|
||||
unimplemented!("This has not yet been adapted for the new internals. Use other_name2.");
|
||||
}
|
||||
|
||||
/// Sets the `otherName` flag.
|
||||
///
|
||||
/// `content` must be a valid der encoded ASN1_TYPE
|
||||
///
|
||||
/// If you want to add just a ia5string use `other_name_ia5string`
|
||||
pub fn other_name2(&mut self, oid: Asn1Object, content: &[u8]) -> &mut SubjectAlternativeName {
|
||||
self.items
|
||||
.push(RustGeneralName::OtherName(oid, content.into()));
|
||||
self
|
||||
}
|
||||
|
||||
/// Return a `SubjectAlternativeName` extension as an `X509Extension`.
|
||||
pub fn build(&self, _ctx: &X509v3Context<'_>) -> Result<X509Extension, ErrorStack> {
|
||||
let mut stack = Stack::new()?;
|
||||
for item in &self.items {
|
||||
let gn = match item {
|
||||
RustGeneralName::Dns(s) => GeneralName::new_dns(s.as_bytes())?,
|
||||
RustGeneralName::Email(s) => GeneralName::new_email(s.as_bytes())?,
|
||||
RustGeneralName::Uri(s) => GeneralName::new_uri(s.as_bytes())?,
|
||||
RustGeneralName::Ip(s) => {
|
||||
GeneralName::new_ip(s.parse().map_err(|_| ErrorStack::get())?)?
|
||||
}
|
||||
RustGeneralName::Rid(s) => GeneralName::new_rid(Asn1Object::from_str(s)?)?,
|
||||
RustGeneralName::OtherName(oid, content) => {
|
||||
GeneralName::new_other_name(oid.clone(), content)?
|
||||
}
|
||||
};
|
||||
stack.push(gn)?;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
X509Extension::new_internal(Nid::SUBJECT_ALT_NAME, self.critical, stack.as_ptr().cast())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn append(value: &mut String, first: &mut bool, should: bool, element: &str) {
|
||||
if !should {
|
||||
return;
|
||||
}
|
||||
|
||||
if !*first {
|
||||
value.push(',');
|
||||
}
|
||||
*first = false;
|
||||
value.push_str(element);
|
||||
}
|
||||
2546
vendor/openssl/src/x509/mod.rs
vendored
Normal file
2546
vendor/openssl/src/x509/mod.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
304
vendor/openssl/src/x509/store.rs
vendored
Normal file
304
vendor/openssl/src/x509/store.rs
vendored
Normal file
|
|
@ -0,0 +1,304 @@
|
|||
//! Describe a context in which to verify an `X509` certificate.
|
||||
//!
|
||||
//! The `X509` certificate store holds trusted CA certificates used to verify
|
||||
//! peer certificates.
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! ```rust
|
||||
//! use openssl::x509::store::{X509StoreBuilder, X509Store};
|
||||
//! use openssl::x509::{X509, X509Name};
|
||||
//! use openssl::asn1::Asn1Time;
|
||||
//! use openssl::pkey::PKey;
|
||||
//! use openssl::hash::MessageDigest;
|
||||
//! use openssl::rsa::Rsa;
|
||||
//! use openssl::nid::Nid;
|
||||
//!
|
||||
//! let rsa = Rsa::generate(2048).unwrap();
|
||||
//! let pkey = PKey::from_rsa(rsa).unwrap();
|
||||
//!
|
||||
//! let mut name = X509Name::builder().unwrap();
|
||||
//! name.append_entry_by_nid(Nid::COMMONNAME, "foobar.com").unwrap();
|
||||
//! let name = name.build();
|
||||
//!
|
||||
//! // Sep 27th, 2016
|
||||
//! let sample_time = Asn1Time::from_unix(1474934400).unwrap();
|
||||
//!
|
||||
//! let mut builder = X509::builder().unwrap();
|
||||
//! builder.set_version(2).unwrap();
|
||||
//! builder.set_subject_name(&name).unwrap();
|
||||
//! builder.set_issuer_name(&name).unwrap();
|
||||
//! builder.set_pubkey(&pkey).unwrap();
|
||||
//! builder.set_not_before(&sample_time);
|
||||
//! builder.set_not_after(&sample_time);
|
||||
//! builder.sign(&pkey, MessageDigest::sha256()).unwrap();
|
||||
//!
|
||||
//! let certificate: X509 = builder.build();
|
||||
//!
|
||||
//! let mut builder = X509StoreBuilder::new().unwrap();
|
||||
//! let _ = builder.add_cert(certificate);
|
||||
//!
|
||||
//! let store: X509Store = builder.build();
|
||||
//! ```
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
use foreign_types::{ForeignType, ForeignTypeRef};
|
||||
use std::mem;
|
||||
|
||||
use crate::error::ErrorStack;
|
||||
#[cfg(not(boringssl))]
|
||||
use crate::ssl::SslFiletype;
|
||||
#[cfg(ossl300)]
|
||||
use crate::stack::Stack;
|
||||
use crate::stack::StackRef;
|
||||
use crate::util::ForeignTypeRefExt;
|
||||
#[cfg(any(ossl102, boringssl, libressl261))]
|
||||
use crate::x509::verify::{X509VerifyFlags, X509VerifyParamRef};
|
||||
use crate::x509::{X509Object, X509PurposeId, X509};
|
||||
use crate::{cvt, cvt_p};
|
||||
use openssl_macros::corresponds;
|
||||
#[cfg(not(boringssl))]
|
||||
use std::ffi::CString;
|
||||
#[cfg(not(boringssl))]
|
||||
use std::path::Path;
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::X509_STORE;
|
||||
fn drop = ffi::X509_STORE_free;
|
||||
|
||||
/// A builder type used to construct an `X509Store`.
|
||||
pub struct X509StoreBuilder;
|
||||
/// A reference to an [`X509StoreBuilder`].
|
||||
pub struct X509StoreBuilderRef;
|
||||
}
|
||||
|
||||
impl X509StoreBuilder {
|
||||
/// Returns a builder for a certificate store.
|
||||
///
|
||||
/// The store is initially empty.
|
||||
#[corresponds(X509_STORE_new)]
|
||||
pub fn new() -> Result<X509StoreBuilder, ErrorStack> {
|
||||
unsafe {
|
||||
ffi::init();
|
||||
|
||||
cvt_p(ffi::X509_STORE_new()).map(X509StoreBuilder)
|
||||
}
|
||||
}
|
||||
|
||||
/// Constructs the `X509Store`.
|
||||
pub fn build(self) -> X509Store {
|
||||
let store = X509Store(self.0);
|
||||
mem::forget(self);
|
||||
store
|
||||
}
|
||||
}
|
||||
|
||||
impl X509StoreBuilderRef {
|
||||
/// Adds a certificate to the certificate store.
|
||||
// FIXME should take an &X509Ref
|
||||
#[corresponds(X509_STORE_add_cert)]
|
||||
pub fn add_cert(&mut self, cert: X509) -> Result<(), ErrorStack> {
|
||||
unsafe { cvt(ffi::X509_STORE_add_cert(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
|
||||
}
|
||||
|
||||
/// Load certificates from their default locations.
|
||||
///
|
||||
/// These locations are read from the `SSL_CERT_FILE` and `SSL_CERT_DIR`
|
||||
/// environment variables if present, or defaults specified at OpenSSL
|
||||
/// build time otherwise.
|
||||
#[corresponds(X509_STORE_set_default_paths)]
|
||||
pub fn set_default_paths(&mut self) -> Result<(), ErrorStack> {
|
||||
unsafe { cvt(ffi::X509_STORE_set_default_paths(self.as_ptr())).map(|_| ()) }
|
||||
}
|
||||
|
||||
/// Adds a lookup method to the store.
|
||||
#[corresponds(X509_STORE_add_lookup)]
|
||||
pub fn add_lookup<T>(
|
||||
&mut self,
|
||||
method: &'static X509LookupMethodRef<T>,
|
||||
) -> Result<&mut X509LookupRef<T>, ErrorStack> {
|
||||
let lookup = unsafe { ffi::X509_STORE_add_lookup(self.as_ptr(), method.as_ptr()) };
|
||||
cvt_p(lookup).map(|ptr| unsafe { X509LookupRef::from_ptr_mut(ptr) })
|
||||
}
|
||||
|
||||
/// Sets certificate chain validation related flags.
|
||||
#[corresponds(X509_STORE_set_flags)]
|
||||
#[cfg(any(ossl102, boringssl, libressl261))]
|
||||
pub fn set_flags(&mut self, flags: X509VerifyFlags) -> Result<(), ErrorStack> {
|
||||
unsafe { cvt(ffi::X509_STORE_set_flags(self.as_ptr(), flags.bits())).map(|_| ()) }
|
||||
}
|
||||
|
||||
/// Sets the certificate purpose.
|
||||
/// The purpose value can be obtained by `X509PurposeRef::get_by_sname()`
|
||||
#[corresponds(X509_STORE_set_purpose)]
|
||||
pub fn set_purpose(&mut self, purpose: X509PurposeId) -> Result<(), ErrorStack> {
|
||||
unsafe { cvt(ffi::X509_STORE_set_purpose(self.as_ptr(), purpose.as_raw())).map(|_| ()) }
|
||||
}
|
||||
|
||||
/// Sets certificate chain validation related parameters.
|
||||
#[corresponds[X509_STORE_set1_param]]
|
||||
#[cfg(any(ossl102, boringssl, libressl261))]
|
||||
pub fn set_param(&mut self, param: &X509VerifyParamRef) -> Result<(), ErrorStack> {
|
||||
unsafe { cvt(ffi::X509_STORE_set1_param(self.as_ptr(), param.as_ptr())).map(|_| ()) }
|
||||
}
|
||||
}
|
||||
|
||||
generic_foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::X509_LOOKUP;
|
||||
fn drop = ffi::X509_LOOKUP_free;
|
||||
|
||||
/// Information used by an `X509Store` to look up certificates and CRLs.
|
||||
pub struct X509Lookup<T>;
|
||||
/// A reference to an [`X509Lookup`].
|
||||
pub struct X509LookupRef<T>;
|
||||
}
|
||||
|
||||
/// Marker type corresponding to the [`X509_LOOKUP_hash_dir`] lookup method.
|
||||
///
|
||||
/// [`X509_LOOKUP_hash_dir`]: https://www.openssl.org/docs/manmaster/crypto/X509_LOOKUP_hash_dir.html
|
||||
// FIXME should be an enum
|
||||
pub struct HashDir;
|
||||
|
||||
impl X509Lookup<HashDir> {
|
||||
/// Lookup method that loads certificates and CRLs on demand and caches
|
||||
/// them in memory once they are loaded. It also checks for newer CRLs upon
|
||||
/// each lookup, so that newer CRLs are used as soon as they appear in the
|
||||
/// directory.
|
||||
#[corresponds(X509_LOOKUP_hash_dir)]
|
||||
pub fn hash_dir() -> &'static X509LookupMethodRef<HashDir> {
|
||||
unsafe { X509LookupMethodRef::from_const_ptr(ffi::X509_LOOKUP_hash_dir()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(boringssl))]
|
||||
impl X509LookupRef<HashDir> {
|
||||
/// Specifies a directory from which certificates and CRLs will be loaded
|
||||
/// on-demand. Must be used with `X509Lookup::hash_dir`.
|
||||
#[corresponds(X509_LOOKUP_add_dir)]
|
||||
pub fn add_dir(&mut self, name: &str, file_type: SslFiletype) -> Result<(), ErrorStack> {
|
||||
let name = CString::new(name).unwrap();
|
||||
unsafe {
|
||||
cvt(ffi::X509_LOOKUP_add_dir(
|
||||
self.as_ptr(),
|
||||
name.as_ptr(),
|
||||
file_type.as_raw(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Marker type corresponding to the [`X509_LOOKUP_file`] lookup method.
|
||||
///
|
||||
/// [`X509_LOOKUP_file`]: https://www.openssl.org/docs/man1.1.1/man3/X509_LOOKUP_file.html
|
||||
pub struct File;
|
||||
|
||||
impl X509Lookup<File> {
|
||||
/// Lookup method loads all the certificates or CRLs present in a file
|
||||
/// into memory at the time the file is added as a lookup source.
|
||||
#[corresponds(X509_LOOKUP_file)]
|
||||
pub fn file() -> &'static X509LookupMethodRef<File> {
|
||||
unsafe { X509LookupMethodRef::from_const_ptr(ffi::X509_LOOKUP_file()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(boringssl))]
|
||||
impl X509LookupRef<File> {
|
||||
/// Specifies a file from which certificates will be loaded
|
||||
#[corresponds(X509_load_cert_file)]
|
||||
// FIXME should return 'Result<i32, ErrorStack' like load_crl_file
|
||||
pub fn load_cert_file<P: AsRef<Path>>(
|
||||
&mut self,
|
||||
file: P,
|
||||
file_type: SslFiletype,
|
||||
) -> Result<(), ErrorStack> {
|
||||
let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
|
||||
unsafe {
|
||||
cvt(ffi::X509_load_cert_file(
|
||||
self.as_ptr(),
|
||||
file.as_ptr(),
|
||||
file_type.as_raw(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Specifies a file from which certificate revocation lists will be loaded
|
||||
#[corresponds(X509_load_crl_file)]
|
||||
pub fn load_crl_file<P: AsRef<Path>>(
|
||||
&mut self,
|
||||
file: P,
|
||||
file_type: SslFiletype,
|
||||
) -> Result<i32, ErrorStack> {
|
||||
let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap();
|
||||
unsafe {
|
||||
cvt(ffi::X509_load_crl_file(
|
||||
self.as_ptr(),
|
||||
file.as_ptr(),
|
||||
file_type.as_raw(),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
generic_foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::X509_LOOKUP_METHOD;
|
||||
fn drop = X509_LOOKUP_meth_free;
|
||||
|
||||
/// Method used to look up certificates and CRLs.
|
||||
pub struct X509LookupMethod<T>;
|
||||
/// A reference to an [`X509LookupMethod`].
|
||||
pub struct X509LookupMethodRef<T>;
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::X509_STORE;
|
||||
fn drop = ffi::X509_STORE_free;
|
||||
|
||||
/// A certificate store to hold trusted `X509` certificates.
|
||||
pub struct X509Store;
|
||||
/// Reference to an `X509Store`.
|
||||
pub struct X509StoreRef;
|
||||
}
|
||||
|
||||
impl X509StoreRef {
|
||||
/// Get a reference to the cache of certificates in this store.
|
||||
///
|
||||
/// This method is deprecated. It is **unsound** and will be removed in a
|
||||
/// future version of rust-openssl. `X509StoreRef::all_certificates`
|
||||
/// should be used instead.
|
||||
#[deprecated(
|
||||
note = "This method is unsound, and will be removed in a future version of rust-openssl. X509StoreRef::all_certificates should be used instead."
|
||||
)]
|
||||
#[corresponds(X509_STORE_get0_objects)]
|
||||
pub fn objects(&self) -> &StackRef<X509Object> {
|
||||
unsafe { StackRef::from_ptr(X509_STORE_get0_objects(self.as_ptr())) }
|
||||
}
|
||||
|
||||
/// Returns a stack of all the certificates in this store.
|
||||
#[corresponds(X509_STORE_get1_all_certs)]
|
||||
#[cfg(ossl300)]
|
||||
pub fn all_certificates(&self) -> Stack<X509> {
|
||||
unsafe { Stack::from_ptr(ffi::X509_STORE_get1_all_certs(self.as_ptr())) }
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(any(boringssl, ossl110, libressl270))] {
|
||||
use ffi::X509_STORE_get0_objects;
|
||||
} else {
|
||||
#[allow(bad_style)]
|
||||
unsafe fn X509_STORE_get0_objects(x: *mut ffi::X509_STORE) -> *mut ffi::stack_st_X509_OBJECT {
|
||||
(*x).objs
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(ossl110)] {
|
||||
use ffi::X509_LOOKUP_meth_free;
|
||||
} else {
|
||||
#[allow(bad_style)]
|
||||
unsafe fn X509_LOOKUP_meth_free(_x: *mut ffi::X509_LOOKUP_METHOD) {}
|
||||
}
|
||||
}
|
||||
1194
vendor/openssl/src/x509/tests.rs
vendored
Normal file
1194
vendor/openssl/src/x509/tests.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
215
vendor/openssl/src/x509/verify.rs
vendored
Normal file
215
vendor/openssl/src/x509/verify.rs
vendored
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
use bitflags::bitflags;
|
||||
use foreign_types::ForeignTypeRef;
|
||||
use libc::{c_int, c_uint, c_ulong, time_t};
|
||||
use std::net::IpAddr;
|
||||
|
||||
use crate::error::ErrorStack;
|
||||
#[cfg(any(ossl102, boringssl))]
|
||||
use crate::x509::X509PurposeId;
|
||||
use crate::{cvt, cvt_p};
|
||||
use openssl_macros::corresponds;
|
||||
|
||||
bitflags! {
|
||||
/// Flags used to check an `X509` certificate.
|
||||
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
#[repr(transparent)]
|
||||
pub struct X509CheckFlags: c_uint {
|
||||
const ALWAYS_CHECK_SUBJECT = ffi::X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT as _;
|
||||
const NO_WILDCARDS = ffi::X509_CHECK_FLAG_NO_WILDCARDS as _;
|
||||
const NO_PARTIAL_WILDCARDS = ffi::X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS as _;
|
||||
const MULTI_LABEL_WILDCARDS = ffi::X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS as _;
|
||||
const SINGLE_LABEL_SUBDOMAINS = ffi::X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS as _;
|
||||
/// Requires OpenSSL 1.1.0 or newer.
|
||||
#[cfg(any(ossl110))]
|
||||
const NEVER_CHECK_SUBJECT = ffi::X509_CHECK_FLAG_NEVER_CHECK_SUBJECT;
|
||||
|
||||
#[deprecated(since = "0.10.6", note = "renamed to NO_WILDCARDS")]
|
||||
const FLAG_NO_WILDCARDS = ffi::X509_CHECK_FLAG_NO_WILDCARDS as _;
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// Flags used to verify an `X509` certificate chain.
|
||||
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
|
||||
#[repr(transparent)]
|
||||
pub struct X509VerifyFlags: c_ulong {
|
||||
const CB_ISSUER_CHECK = ffi::X509_V_FLAG_CB_ISSUER_CHECK as _;
|
||||
const USE_CHECK_TIME = ffi::X509_V_FLAG_USE_CHECK_TIME as _;
|
||||
const CRL_CHECK = ffi::X509_V_FLAG_CRL_CHECK as _;
|
||||
const CRL_CHECK_ALL = ffi::X509_V_FLAG_CRL_CHECK_ALL as _;
|
||||
const IGNORE_CRITICAL = ffi::X509_V_FLAG_IGNORE_CRITICAL as _;
|
||||
const X509_STRICT = ffi::X509_V_FLAG_X509_STRICT as _;
|
||||
const ALLOW_PROXY_CERTS = ffi::X509_V_FLAG_ALLOW_PROXY_CERTS as _;
|
||||
const POLICY_CHECK = ffi::X509_V_FLAG_POLICY_CHECK as _;
|
||||
const EXPLICIT_POLICY = ffi::X509_V_FLAG_EXPLICIT_POLICY as _;
|
||||
const INHIBIT_ANY = ffi::X509_V_FLAG_INHIBIT_ANY as _;
|
||||
const INHIBIT_MAP = ffi::X509_V_FLAG_INHIBIT_MAP as _;
|
||||
const NOTIFY_POLICY = ffi::X509_V_FLAG_NOTIFY_POLICY as _;
|
||||
const EXTENDED_CRL_SUPPORT = ffi::X509_V_FLAG_EXTENDED_CRL_SUPPORT as _;
|
||||
const USE_DELTAS = ffi::X509_V_FLAG_USE_DELTAS as _;
|
||||
const CHECK_SS_SIGNATURE = ffi::X509_V_FLAG_CHECK_SS_SIGNATURE as _;
|
||||
#[cfg(any(ossl102, boringssl))]
|
||||
const TRUSTED_FIRST = ffi::X509_V_FLAG_TRUSTED_FIRST as _;
|
||||
#[cfg(ossl102)]
|
||||
const SUITEB_128_LOS_ONLY = ffi::X509_V_FLAG_SUITEB_128_LOS_ONLY;
|
||||
#[cfg(ossl102)]
|
||||
const SUITEB_192_LOS = ffi::X509_V_FLAG_SUITEB_128_LOS;
|
||||
#[cfg(ossl102)]
|
||||
const SUITEB_128_LOS = ffi::X509_V_FLAG_SUITEB_192_LOS;
|
||||
#[cfg(any(ossl102, boringssl))]
|
||||
const PARTIAL_CHAIN = ffi::X509_V_FLAG_PARTIAL_CHAIN as _;
|
||||
#[cfg(any(ossl110, boringssl))]
|
||||
const NO_ALT_CHAINS = ffi::X509_V_FLAG_NO_ALT_CHAINS as _;
|
||||
#[cfg(any(ossl110, boringssl))]
|
||||
const NO_CHECK_TIME = ffi::X509_V_FLAG_NO_CHECK_TIME as _;
|
||||
}
|
||||
}
|
||||
|
||||
foreign_type_and_impl_send_sync! {
|
||||
type CType = ffi::X509_VERIFY_PARAM;
|
||||
fn drop = ffi::X509_VERIFY_PARAM_free;
|
||||
|
||||
/// Adjust parameters associated with certificate verification.
|
||||
pub struct X509VerifyParam;
|
||||
/// Reference to `X509VerifyParam`.
|
||||
pub struct X509VerifyParamRef;
|
||||
}
|
||||
|
||||
impl X509VerifyParam {
|
||||
/// Create an X509VerifyParam
|
||||
#[corresponds(X509_VERIFY_PARAM_new)]
|
||||
pub fn new() -> Result<X509VerifyParam, ErrorStack> {
|
||||
unsafe {
|
||||
ffi::init();
|
||||
cvt_p(ffi::X509_VERIFY_PARAM_new()).map(X509VerifyParam)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl X509VerifyParamRef {
|
||||
/// Set the host flags.
|
||||
#[corresponds(X509_VERIFY_PARAM_set_hostflags)]
|
||||
pub fn set_hostflags(&mut self, hostflags: X509CheckFlags) {
|
||||
unsafe {
|
||||
ffi::X509_VERIFY_PARAM_set_hostflags(self.as_ptr(), hostflags.bits());
|
||||
}
|
||||
}
|
||||
|
||||
/// Set verification flags.
|
||||
#[corresponds(X509_VERIFY_PARAM_set_flags)]
|
||||
pub fn set_flags(&mut self, flags: X509VerifyFlags) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::X509_VERIFY_PARAM_set_flags(
|
||||
self.as_ptr(),
|
||||
flags.bits(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Clear verification flags.
|
||||
#[corresponds(X509_VERIFY_PARAM_clear_flags)]
|
||||
pub fn clear_flags(&mut self, flags: X509VerifyFlags) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::X509_VERIFY_PARAM_clear_flags(
|
||||
self.as_ptr(),
|
||||
flags.bits(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets verification flags.
|
||||
#[corresponds(X509_VERIFY_PARAM_get_flags)]
|
||||
pub fn flags(&mut self) -> X509VerifyFlags {
|
||||
let bits = unsafe { ffi::X509_VERIFY_PARAM_get_flags(self.as_ptr()) };
|
||||
X509VerifyFlags::from_bits_retain(bits)
|
||||
}
|
||||
|
||||
/// Set the expected DNS hostname.
|
||||
#[corresponds(X509_VERIFY_PARAM_set1_host)]
|
||||
pub fn set_host(&mut self, host: &str) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
// len == 0 means "run strlen" :(
|
||||
let raw_host = if host.is_empty() { "\0" } else { host };
|
||||
cvt(ffi::X509_VERIFY_PARAM_set1_host(
|
||||
self.as_ptr(),
|
||||
raw_host.as_ptr() as *const _,
|
||||
host.len(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the expected email address.
|
||||
#[corresponds(X509_VERIFY_PARAM_set1_email)]
|
||||
pub fn set_email(&mut self, email: &str) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
// len == 0 means "run strlen" :(
|
||||
let raw_email = if email.is_empty() { "\0" } else { email };
|
||||
cvt(ffi::X509_VERIFY_PARAM_set1_email(
|
||||
self.as_ptr(),
|
||||
raw_email.as_ptr() as *const _,
|
||||
email.len(),
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the expected IPv4 or IPv6 address.
|
||||
#[corresponds(X509_VERIFY_PARAM_set1_ip)]
|
||||
pub fn set_ip(&mut self, ip: IpAddr) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
let mut buf = [0; 16];
|
||||
let len = match ip {
|
||||
IpAddr::V4(addr) => {
|
||||
buf[..4].copy_from_slice(&addr.octets());
|
||||
4
|
||||
}
|
||||
IpAddr::V6(addr) => {
|
||||
buf.copy_from_slice(&addr.octets());
|
||||
16
|
||||
}
|
||||
};
|
||||
cvt(ffi::X509_VERIFY_PARAM_set1_ip(
|
||||
self.as_ptr(),
|
||||
buf.as_ptr() as *const _,
|
||||
len,
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the verification time, where time is of type time_t, traditionaly defined as seconds since the epoch
|
||||
#[corresponds(X509_VERIFY_PARAM_set_time)]
|
||||
pub fn set_time(&mut self, time: time_t) {
|
||||
unsafe { ffi::X509_VERIFY_PARAM_set_time(self.as_ptr(), time) }
|
||||
}
|
||||
|
||||
/// Set the verification depth
|
||||
#[corresponds(X509_VERIFY_PARAM_set_depth)]
|
||||
pub fn set_depth(&mut self, depth: c_int) {
|
||||
unsafe { ffi::X509_VERIFY_PARAM_set_depth(self.as_ptr(), depth) }
|
||||
}
|
||||
|
||||
/// Sets the authentication security level to auth_level
|
||||
#[corresponds(X509_VERIFY_PARAM_set_auth_level)]
|
||||
#[cfg(ossl110)]
|
||||
pub fn set_auth_level(&mut self, lvl: c_int) {
|
||||
unsafe { ffi::X509_VERIFY_PARAM_set_auth_level(self.as_ptr(), lvl) }
|
||||
}
|
||||
|
||||
/// Gets the current authentication security level
|
||||
#[corresponds(X509_VERIFY_PARAM_get_auth_level)]
|
||||
#[cfg(ossl110)]
|
||||
pub fn auth_level(&self) -> i32 {
|
||||
unsafe { ffi::X509_VERIFY_PARAM_get_auth_level(self.as_ptr()) }
|
||||
}
|
||||
|
||||
/// Sets the verification purpose
|
||||
#[corresponds(X509_VERIFY_PARAM_set_purpose)]
|
||||
#[cfg(any(ossl102, boringssl))]
|
||||
pub fn set_purpose(&mut self, purpose: X509PurposeId) -> Result<(), ErrorStack> {
|
||||
unsafe { cvt(ffi::X509_VERIFY_PARAM_set_purpose(self.as_ptr(), purpose.0)).map(|_| ()) }
|
||||
}
|
||||
}
|
||||
22
vendor/openssl/test/aia_test_cert.pem
vendored
Normal file
22
vendor/openssl/test/aia_test_cert.pem
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDozCCAougAwIBAgIJAJayG40CARAjMA0GCSqGSIb3DQEBCwUAMA8xDTALBgNV
|
||||
BAMMBHRlc3QwHhcNMjEwMzAyMDA1NzQ3WhcNNDgwNzE4MDA1NzQ3WjBzMQswCQYD
|
||||
VQQGEwJYWDELMAkGA1UECAwCWFgxEDAOBgNVBAcMB25vd2hlcmUxEDAOBgNVBAoM
|
||||
B3Rlc3RvcmcxEjAQBgNVBAsMCXRlc3Rncm91cDEfMB0GA1UEAwwWbWFjaGluZS0w
|
||||
Lm15aG9zdC5teW5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANKA
|
||||
3zhwC70hbxFVdC0dYk9BHaNntZ4LPUVwFSG2HBn34oO8zCp4wkH+VIi9vOhWiySK
|
||||
Gs3gW4qpjMbF82Gqc3dG2KfqUrOtWY+u54zAzqpgiJf08wmREHPoZmjqfCfgM3FO
|
||||
VMEA8g1BQxXEd+y7UEDoXhPIoeFnqzMu9sg4npnL9U5BLaQJiWnXHClnBrvAAKXW
|
||||
E8KDNmcavtFvo2xQVC09C6dJG5CrigWcZe4CaUl44rHiPaQd+jOp0HAccl/XLA0/
|
||||
QyHvW6ksjco/mb7ia1U9ohaC/3NHmzUA1S3kdq/qgnkPsjmy5v8k5vizowNc5rFO
|
||||
XsV86BIv44rh1Jut52ECAwEAAaOBnTCBmjAMBgNVHRMEBTADAQH/MAsGA1UdDwQE
|
||||
AwIF4DAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwIQYDVR0RBBowGIIW
|
||||
bWFjaGluZS0wLm15aG9zdC5teW5ldDA7BggrBgEFBQcBAQQvMC0wKwYIKwYBBQUH
|
||||
MAKGH2h0dHA6Ly93d3cuZXhhbXBsZS5jb20vY2VydC5wZW0wDQYJKoZIhvcNAQEL
|
||||
BQADggEBAH+ayx8qGvxzrG57jgXJudq+z783O6E2xGBJn1cT9Jhrg1VnlU+tHcNd
|
||||
fFcsp0gdQZCmm3pu3E0m/FsgTpfHUgdCOmZQp45QrxCz2oRdWQM71SSA/x1VfQ9w
|
||||
670iZOEY15/ss2nRl0woaYO7tBVadpZfymW5+OhsTKn5gL0pVmW3RciHuAmbIvQO
|
||||
bouUwzuZIJMfca7T1MqZYdrKoJrOBj0LaPTutjfQB7O/02vUCPjTTIH20aqsMe5K
|
||||
KXCrjiZO2jkxQ49Hz5uwfPx12dSVHNLpsnfOAH+MUToeW+SPx2OPvl/uAHcph2lj
|
||||
MLA6Wi64rSUxzkcFLFsGpKcK6QKcHUw=
|
||||
-----END CERTIFICATE-----
|
||||
22
vendor/openssl/test/alt_name_cert.pem
vendored
Normal file
22
vendor/openssl/test/alt_name_cert.pem
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDsDCCApigAwIBAgIBATANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJBVTET
|
||||
MBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQ
|
||||
dHkgTHRkMB4XDTE4MDExNTExMDcwM1oXDTI4MDExMzExMDcwM1owfDELMAkGA1UE
|
||||
BhMCVVMxCzAJBgNVBAgMAk5ZMREwDwYDVQQHDAhOZXcgWW9yazEVMBMGA1UECgwM
|
||||
RXhhbXBsZSwgTExDMTYwNAYDVQQDDC1FeGFtcGxlIENvbXBhbnkvZW1haWxBZGRy
|
||||
ZXNzPXRlc3RAZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
|
||||
AoIBAQCo9CWMRLMXo1CF/iORh9B4NhtJF/8tR9PlG95sNvyWuQQ/8jfev+8zErpl
|
||||
xfLkt0pJqcoiZG8g9NU0kU6o5T+/1QgZclCAoZaS0Jqxmoo2Yk/1Qsj16pnMBc10
|
||||
uSDk6V9aJSX1vKwONVNSwiHA1MhX+i7Wf7/K0niq+k7hOkhleFkWgZtUq41gXh1V
|
||||
fOugka7UktYnk9mrBbAMjmaloZNn2pMMAQxVg4ThiLm3zvuWqvXASWzUZc7IAd1G
|
||||
bN4AtDuhs252eqE9E4iTHk7F14wAS1JWqv666hReGHrmZJGx0xQTM9vPD1HN5t2U
|
||||
3KTfhO/mTlAUWVyg9tCtOzboKgs1AgMBAAGjdDByMAkGA1UdEwQCMAAwCwYDVR0P
|
||||
BAQDAgWgMFgGA1UdEQRRME+CC2V4YW1wbGUuY29thwR/AAABhxAAAAAAAAAAAAAA
|
||||
AAAAAAABgRB0ZXN0QGV4YW1wbGUuY29thhZodHRwOi8vd3d3LmV4YW1wbGUuY29t
|
||||
MA0GCSqGSIb3DQEBCwUAA4IBAQAx14G99z/MnSbs8h5jSos+dgLvhc2IQB/3CChE
|
||||
hPyELc7iyw1iteRs7bS1m2NZx6gv6TZ6VydDrK1dnWSatQ7sskXTO+zfC6qjMwXl
|
||||
IV+u7T8EREwciniIA82d8GWs60BGyBL3zp2iUOr5ULG4+c/S6OLdlyJv+fDKv+Xo
|
||||
fKv1UGDi5rcvUBikeNkpEPTN9UsE9/A8XJfDyq+4RKuDW19EtzOOeVx4xpHOMnAy
|
||||
VVAQVMKJzhoXtLF4k2j409na+f6FIcZSBet+plmzfB+WZNIgUUi/7MQIXOFQRkj4
|
||||
zH3SnsPm/IYpJzlH2vHhlqIBdaSoTWpGVWPq7D+H8OS3mmXF
|
||||
-----END CERTIFICATE-----
|
||||
19
vendor/openssl/test/authority_key_identifier.pem
vendored
Normal file
19
vendor/openssl/test/authority_key_identifier.pem
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDIjCCAgqgAwIBAgIBAzANBgkqhkiG9w0BAQUFADApMQ0wCwYDVQQKDARQeUNB
|
||||
MRgwFgYDVQQDDA9jcnlwdG9ncmFwaHkuaW8wHhcNMTUwNTAzMDk0OTU2WhcNMTYw
|
||||
NTAyMDk0OTU2WjApMQ0wCwYDVQQKDARQeUNBMRgwFgYDVQQDDA9jcnlwdG9ncmFw
|
||||
aHkuaW8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDCadi1UZioxdnP
|
||||
ajqlRZHeKsSxvXXhgrWvlt91P3gV0dBThRFhJsLOhjNLz6PO6KeRbjz9GhTA2hdk
|
||||
xtIpXrjvTv9dEJ1/k0xebsHWgFC43aTlgekw0U4cMwMe5NGeeg1tfzbJwldIN+cK
|
||||
vabc08ADlkmM6DMnUArkzA2yii0DErRFMSIGrkDr6E9puord3h6Mh8Jfnc3TDAq8
|
||||
Qo1DI2XM7oFSWNfecQ9KbIC5wzzT+7Shoyz7QmCk/XhRzt8Xcfc3yAXIwazvLf8b
|
||||
YP1auaSG11a5E+w6onj91h8UHKKOXu+rdq5YYPZ+qUYpxA7ZJ/VAGadMulYbXaO8
|
||||
Syi39HTpAgMBAAGjVTBTMFEGA1UdIwRKMEiAFDlFPso9Yh3qhkn2WqtAt6RwmPHs
|
||||
oS2kKzApMQ0wCwYDVQQKDARQeUNBMRgwFgYDVQQDDA9jcnlwdG9ncmFwaHkuaW+C
|
||||
AQMwDQYJKoZIhvcNAQEFBQADggEBAFbZYy6aZJUK/f7nJx2Rs/ht6hMbM32/RoXZ
|
||||
JGbYapNVqVu/vymcfc/se3FHS5OVmPsnRlo/FIKDn/r5DGl73Sn/FvDJiLJZFucT
|
||||
msyYuHZ+ZRYWzWmN2fcB3cfxj0s3qps6f5OoCOqoINOSe4HRGlw4X9keZSD+3xAt
|
||||
vHNwQdlPC7zWbPdrzLT+FqR0e/O81vFJJS6drHJWqPcR3NQVtZw+UF7A/HKwbfeL
|
||||
Nu2zj6165hzOi9HUxa2/mPr/eLUUV1sTzXp2+TFjt3rVCjW1XnpMLdwNBHzjpyAB
|
||||
dTOX3iw0+BPy3s2jtnCW1PLpc74kvSTaBwhg74sq39EXfIKax00=
|
||||
-----END CERTIFICATE-----
|
||||
88
vendor/openssl/test/ca.crt
vendored
Normal file
88
vendor/openssl/test/ca.crt
vendored
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
Certificate:
|
||||
Data:
|
||||
Version: 3 (0x2)
|
||||
Serial Number:
|
||||
13:ae:da:d8:f4:18:d7:73:b8:bd:35:c9:ce:8e:b3:fc
|
||||
Signature Algorithm: sha256WithRSAEncryption
|
||||
Issuer: CN=TestCA
|
||||
Validity
|
||||
Not Before: Jun 6 19:11:19 2019 GMT
|
||||
Not After : May 21 19:11:19 2022 GMT
|
||||
Subject: CN=SubCA
|
||||
Subject Public Key Info:
|
||||
Public Key Algorithm: rsaEncryption
|
||||
RSA Public-Key: (2048 bit)
|
||||
Modulus:
|
||||
00:b0:09:fc:54:e7:6a:9f:0c:bd:ad:5a:8d:ef:94:
|
||||
4e:11:a6:87:19:4f:bf:a6:e1:62:a5:2d:b7:17:df:
|
||||
67:53:70:da:fe:7d:99:17:ee:13:47:0b:40:0b:a2:
|
||||
34:32:a9:d3:bf:20:fc:13:77:a1:d5:26:60:1f:f0:
|
||||
d4:be:dc:76:7c:1e:6c:b4:4c:01:7c:56:cd:5c:53:
|
||||
ec:81:b3:81:2a:b2:35:26:06:5a:79:e0:b3:9e:e4:
|
||||
57:e1:09:de:ad:7f:c8:cd:87:ee:49:93:30:52:58:
|
||||
b2:bc:0f:c1:b6:10:44:f8:85:d5:5b:0a:9b:28:fe:
|
||||
f4:f4:4a:16:a6:f7:25:e9:96:47:69:73:5b:33:77:
|
||||
92:7d:61:8d:2a:3d:d5:04:89:40:bf:6b:d2:fd:5d:
|
||||
e2:1a:80:a9:8e:c8:92:f6:e5:4c:00:84:f9:6e:2a:
|
||||
93:a3:23:ee:28:23:81:f4:54:f0:18:2c:ee:32:8e:
|
||||
38:9c:a0:c8:33:04:b0:fc:4c:43:1a:5c:04:84:9f:
|
||||
73:c6:08:c7:1d:64:39:fe:72:19:3b:cc:a5:fd:0b:
|
||||
43:25:0d:2b:a9:88:77:9e:62:e6:ac:c2:9a:60:42:
|
||||
4f:4a:54:47:bc:a0:29:72:7c:38:52:c9:ea:27:c5:
|
||||
3d:d0:81:4a:3e:b8:78:79:4b:89:b8:4e:6d:1b:24:
|
||||
15:bd
|
||||
Exponent: 65537 (0x10001)
|
||||
X509v3 extensions:
|
||||
X509v3 CRL Distribution Points:
|
||||
|
||||
Full Name:
|
||||
URI:http://127.0.0.1:8081/pki/test.crl
|
||||
|
||||
X509v3 Basic Constraints:
|
||||
CA:TRUE
|
||||
X509v3 Subject Key Identifier:
|
||||
FD:82:45:39:A1:91:41:F2:66:CC:0D:75:D5:0D:40:D5:81:A7:A1:43
|
||||
X509v3 Authority Key Identifier:
|
||||
keyid:C5:CC:F5:A1:8C:D9:E4:A7:BA:EC:21:F5:D1:84:23:EA:0D:C2:C7:30
|
||||
DirName:/CN=TestCA
|
||||
serial:33:E7:04:87:09:32:87:21:D9:CD:7C:AA:4C:5A:BB:2C:6C:7B:54:28
|
||||
|
||||
X509v3 Key Usage:
|
||||
Certificate Sign, CRL Sign
|
||||
Signature Algorithm: sha256WithRSAEncryption
|
||||
96:a0:ff:8a:4b:bd:45:96:c9:72:3c:63:e3:48:c4:ab:ef:7e:
|
||||
db:76:3f:d9:02:9e:69:c8:d9:36:55:e1:f5:9b:c9:69:d8:69:
|
||||
02:ac:50:8c:60:94:2c:2e:b9:a8:65:ac:f5:00:b0:8b:96:25:
|
||||
0b:8a:ef:94:21:57:e2:04:c2:c3:86:bf:06:4e:91:5c:e6:bc:
|
||||
1b:03:31:8b:64:ea:c5:79:c3:5c:94:e5:aa:67:7e:74:12:07:
|
||||
14:fd:cd:32:02:26:26:c9:0a:ed:d4:da:ee:2a:84:e3:f1:60:
|
||||
b3:09:77:27:a1:3c:ac:ec:61:18:30:b5:6d:1f:16:0a:24:1a:
|
||||
cf:1c:1b:60:a5:60:e5:2c:8b:cf:37:83:0c:15:e7:79:30:3f:
|
||||
ee:50:45:7c:4b:c6:2c:cd:2c:81:0a:98:f1:65:44:7a:ca:2a:
|
||||
20:1a:de:19:d9:4b:ca:a1:e2:a4:b5:14:47:bf:b4:68:15:03:
|
||||
c0:55:e5:f4:47:0e:55:9f:fe:85:d8:2c:7d:d0:1a:96:11:b9:
|
||||
68:b7:74:1e:61:94:c1:ae:87:52:2d:c6:26:ba:51:ed:f1:91:
|
||||
c0:e6:4c:f8:ad:02:23:75:51:fc:f8:69:05:ec:cf:31:50:5a:
|
||||
41:78:eb:3d:27:4d:9b:68:ef:ba:0e:ba:3a:7d:60:00:9d:53:
|
||||
a5:08:3d:c6
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDbDCCAlSgAwIBAgIQE67a2PQY13O4vTXJzo6z/DANBgkqhkiG9w0BAQsFADAR
|
||||
MQ8wDQYDVQQDDAZUZXN0Q0EwHhcNMTkwNjA2MTkxMTE5WhcNMjIwNTIxMTkxMTE5
|
||||
WjAQMQ4wDAYDVQQDDAVTdWJDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
|
||||
ggEBALAJ/FTnap8Mva1aje+UThGmhxlPv6bhYqUttxffZ1Nw2v59mRfuE0cLQAui
|
||||
NDKp078g/BN3odUmYB/w1L7cdnwebLRMAXxWzVxT7IGzgSqyNSYGWnngs57kV+EJ
|
||||
3q1/yM2H7kmTMFJYsrwPwbYQRPiF1VsKmyj+9PRKFqb3JemWR2lzWzN3kn1hjSo9
|
||||
1QSJQL9r0v1d4hqAqY7IkvblTACE+W4qk6Mj7igjgfRU8Bgs7jKOOJygyDMEsPxM
|
||||
QxpcBISfc8YIxx1kOf5yGTvMpf0LQyUNK6mId55i5qzCmmBCT0pUR7ygKXJ8OFLJ
|
||||
6ifFPdCBSj64eHlLibhObRskFb0CAwEAAaOBwDCBvTAzBgNVHR8ELDAqMCigJqAk
|
||||
hiJodHRwOi8vMTI3LjAuMC4xOjgwODEvcGtpL3Rlc3QuY3JsMAwGA1UdEwQFMAMB
|
||||
Af8wHQYDVR0OBBYEFP2CRTmhkUHyZswNddUNQNWBp6FDMEwGA1UdIwRFMEOAFMXM
|
||||
9aGM2eSnuuwh9dGEI+oNwscwoRWkEzARMQ8wDQYDVQQDDAZUZXN0Q0GCFDPnBIcJ
|
||||
Moch2c18qkxauyxse1QoMAsGA1UdDwQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEA
|
||||
lqD/iku9RZbJcjxj40jEq+9+23Y/2QKeacjZNlXh9ZvJadhpAqxQjGCULC65qGWs
|
||||
9QCwi5YlC4rvlCFX4gTCw4a/Bk6RXOa8GwMxi2TqxXnDXJTlqmd+dBIHFP3NMgIm
|
||||
JskK7dTa7iqE4/Fgswl3J6E8rOxhGDC1bR8WCiQazxwbYKVg5SyLzzeDDBXneTA/
|
||||
7lBFfEvGLM0sgQqY8WVEesoqIBreGdlLyqHipLUUR7+0aBUDwFXl9EcOVZ/+hdgs
|
||||
fdAalhG5aLd0HmGUwa6HUi3GJrpR7fGRwOZM+K0CI3VR/PhpBezPMVBaQXjrPSdN
|
||||
m2jvug66On1gAJ1TpQg9xg==
|
||||
-----END CERTIFICATE-----
|
||||
19
vendor/openssl/test/cert.pem
vendored
Normal file
19
vendor/openssl/test/cert.pem
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDGzCCAgMCCQCHcfe97pgvpTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB
|
||||
VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0
|
||||
cyBQdHkgTHRkMB4XDTE2MDgxNDE3MDAwM1oXDTI2MDgxMjE3MDAwM1owWjELMAkG
|
||||
A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0
|
||||
IFdpZGdpdHMgUHR5IEx0ZDETMBEGA1UEAwwKZm9vYmFyLmNvbTCCASIwDQYJKoZI
|
||||
hvcNAQEBBQADggEPADCCAQoCggEBAKj0JYxEsxejUIX+I5GH0Hg2G0kX/y1H0+Ub
|
||||
3mw2/Ja5BD/yN96/7zMSumXF8uS3SkmpyiJkbyD01TSRTqjlP7/VCBlyUIChlpLQ
|
||||
mrGaijZiT/VCyPXqmcwFzXS5IOTpX1olJfW8rA41U1LCIcDUyFf6LtZ/v8rSeKr6
|
||||
TuE6SGV4WRaBm1SrjWBeHVV866CRrtSS1ieT2asFsAyOZqWhk2fakwwBDFWDhOGI
|
||||
ubfO+5aq9cBJbNRlzsgB3UZs3gC0O6GzbnZ6oT0TiJMeTsXXjABLUlaq/rrqFF4Y
|
||||
euZkkbHTFBMz288PUc3m3ZTcpN+E7+ZOUBRZXKD20K07NugqCzUCAwEAATANBgkq
|
||||
hkiG9w0BAQsFAAOCAQEASvYHuIl5C0NHBELPpVHNuLbQsDQNKVj3a54+9q1JkiMM
|
||||
6taEJYfw7K1Xjm4RoiFSHpQBh+PWZS3hToToL2Zx8JfMR5MuAirdPAy1Sia/J/qE
|
||||
wQdJccqmvuLkLTSlsGbEJ/LUUgOAgrgHOZM5lUgIhCneA0/dWJ3PsN0zvn69/faY
|
||||
oo1iiolWiIHWWBUSdr3jM2AJaVAsTmLh00cKaDNk37JB940xConBGSl98JPrNrf9
|
||||
dUAiT0iIBngDBdHnn/yTj+InVEFyZSKrNtiDSObFHxPcxGteHNrCPJdP1e+GqkHp
|
||||
HJMRZVCQpSMzvHlofHSNgzWV1MX5h1CP4SGZdBDTfA==
|
||||
-----END CERTIFICATE-----
|
||||
40
vendor/openssl/test/certs.pem
vendored
Normal file
40
vendor/openssl/test/certs.pem
vendored
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDGzCCAgMCCQCHcfe97pgvpTANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB
|
||||
VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0
|
||||
cyBQdHkgTHRkMB4XDTE2MDgxNDE3MDAwM1oXDTI2MDgxMjE3MDAwM1owWjELMAkG
|
||||
A1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0
|
||||
IFdpZGdpdHMgUHR5IEx0ZDETMBEGA1UEAwwKZm9vYmFyLmNvbTCCASIwDQYJKoZI
|
||||
hvcNAQEBBQADggEPADCCAQoCggEBAKj0JYxEsxejUIX+I5GH0Hg2G0kX/y1H0+Ub
|
||||
3mw2/Ja5BD/yN96/7zMSumXF8uS3SkmpyiJkbyD01TSRTqjlP7/VCBlyUIChlpLQ
|
||||
mrGaijZiT/VCyPXqmcwFzXS5IOTpX1olJfW8rA41U1LCIcDUyFf6LtZ/v8rSeKr6
|
||||
TuE6SGV4WRaBm1SrjWBeHVV866CRrtSS1ieT2asFsAyOZqWhk2fakwwBDFWDhOGI
|
||||
ubfO+5aq9cBJbNRlzsgB3UZs3gC0O6GzbnZ6oT0TiJMeTsXXjABLUlaq/rrqFF4Y
|
||||
euZkkbHTFBMz288PUc3m3ZTcpN+E7+ZOUBRZXKD20K07NugqCzUCAwEAATANBgkq
|
||||
hkiG9w0BAQsFAAOCAQEASvYHuIl5C0NHBELPpVHNuLbQsDQNKVj3a54+9q1JkiMM
|
||||
6taEJYfw7K1Xjm4RoiFSHpQBh+PWZS3hToToL2Zx8JfMR5MuAirdPAy1Sia/J/qE
|
||||
wQdJccqmvuLkLTSlsGbEJ/LUUgOAgrgHOZM5lUgIhCneA0/dWJ3PsN0zvn69/faY
|
||||
oo1iiolWiIHWWBUSdr3jM2AJaVAsTmLh00cKaDNk37JB940xConBGSl98JPrNrf9
|
||||
dUAiT0iIBngDBdHnn/yTj+InVEFyZSKrNtiDSObFHxPcxGteHNrCPJdP1e+GqkHp
|
||||
HJMRZVCQpSMzvHlofHSNgzWV1MX5h1CP4SGZdBDTfA==
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDXTCCAkWgAwIBAgIJAOIvDiVb18eVMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
|
||||
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
|
||||
aWRnaXRzIFB0eSBMdGQwHhcNMTYwODE0MTY1NjExWhcNMjYwODEyMTY1NjExWjBF
|
||||
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
|
||||
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
|
||||
CgKCAQEArVHWFn52Lbl1l59exduZntVSZyDYpzDND+S2LUcO6fRBWhV/1Kzox+2G
|
||||
ZptbuMGmfI3iAnb0CFT4uC3kBkQQlXonGATSVyaFTFR+jq/lc0SP+9Bd7SBXieIV
|
||||
eIXlY1TvlwIvj3Ntw9zX+scTA4SXxH6M0rKv9gTOub2vCMSHeF16X8DQr4XsZuQr
|
||||
7Cp7j1I4aqOJyap5JTl5ijmG8cnu0n+8UcRlBzy99dLWJG0AfI3VRJdWpGTNVZ92
|
||||
aFff3RpK3F/WI2gp3qV1ynRAKuvmncGC3LDvYfcc2dgsc1N6Ffq8GIrkgRob6eBc
|
||||
klDHp1d023Lwre+VaVDSo1//Y72UFwIDAQABo1AwTjAdBgNVHQ4EFgQUbNOlA6sN
|
||||
XyzJjYqciKeId7g3/ZowHwYDVR0jBBgwFoAUbNOlA6sNXyzJjYqciKeId7g3/Zow
|
||||
DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAVVaR5QWLZIRR4Dw6TSBn
|
||||
BQiLpBSXN6oAxdDw6n4PtwW6CzydaA+creiK6LfwEsiifUfQe9f+T+TBSpdIYtMv
|
||||
Z2H2tjlFX8VrjUFvPrvn5c28CuLI0foBgY8XGSkR2YMYzWw2jPEq3Th/KM5Catn3
|
||||
AFm3bGKWMtGPR4v+90chEN0jzaAmJYRrVUh9vea27bOCn31Nse6XXQPmSI6Gyncy
|
||||
OAPUsvPClF3IjeL1tmBotWqSGn1cYxLo+Lwjk22A9h6vjcNQRyZF2VLVvtwYrNU3
|
||||
mwJ6GCLsLHpwW/yjyvn8iEltnJvByM/eeRnfXV6WDObyiZsE/n6DxIRJodQzFqy9
|
||||
GA==
|
||||
-----END CERTIFICATE-----
|
||||
23
vendor/openssl/test/certv3.pem
vendored
Normal file
23
vendor/openssl/test/certv3.pem
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDwTCCAqmgAwIBAgIUDeCGNunyJfBd3U/qUtmCcvbMyZwwDQYJKoZIhvcNAQEL
|
||||
BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
|
||||
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMzAxMjMxMzMzNTJaFw0zMzAx
|
||||
MjAxMzMzNTJaMFoxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
|
||||
HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxEzARBgNVBAMMCmZvb2Jh
|
||||
ci5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCo9CWMRLMXo1CF
|
||||
/iORh9B4NhtJF/8tR9PlG95sNvyWuQQ/8jfev+8zErplxfLkt0pJqcoiZG8g9NU0
|
||||
kU6o5T+/1QgZclCAoZaS0Jqxmoo2Yk/1Qsj16pnMBc10uSDk6V9aJSX1vKwONVNS
|
||||
wiHA1MhX+i7Wf7/K0niq+k7hOkhleFkWgZtUq41gXh1VfOugka7UktYnk9mrBbAM
|
||||
jmaloZNn2pMMAQxVg4ThiLm3zvuWqvXASWzUZc7IAd1GbN4AtDuhs252eqE9E4iT
|
||||
Hk7F14wAS1JWqv666hReGHrmZJGx0xQTM9vPD1HN5t2U3KTfhO/mTlAUWVyg9tCt
|
||||
OzboKgs1AgMBAAGjgZMwgZAwTgYDVR0fBEcwRTAgoB6gHIYaaHR0cDovL2V4YW1w
|
||||
bGUuY29tL2NybC5wZW0wIaAfoB2GG2h0dHA6Ly9leGFtcGxlLmNvbS9jcmwyLnBl
|
||||
bTAdBgNVHQ4EFgQUtnMvYaVLoe9ILBWxn/PcNC+8rDAwHwYDVR0jBBgwFoAUbNOl
|
||||
A6sNXyzJjYqciKeId7g3/ZowDQYJKoZIhvcNAQELBQADggEBAJZyk6Eo4p3JIyOt
|
||||
7t6ET3K18BKvlRilze+zrGkaQYvKRsP6YzbZWgcIq59hy5VeFCX5O2WP91CPG3MU
|
||||
I9eRiih66/ry3G4I8QEdpRKnn0N5unbGjb5qPT5wXrhU4IO+vn3sGZGM4uIM1/3K
|
||||
N/bOh9CTsu9YqrdHSGeDyNzCy/XZ/j5bP4aNm31ZDNCZDFsbjr3/yTLcpHPL0UP3
|
||||
mCX8D16BDu1Nep+wK9VRuOEw6Z9tlT/VjTImzoOUoJO/o2UHfSHahX+n2aC5OpI6
|
||||
BdhaFBuJ1vn+yTWf3zIjhWUdp9TlzgRyFiyetP2FcKwremVVGdDq/Y6dfXaq8CA1
|
||||
6Fr9KTY=
|
||||
-----END CERTIFICATE-----
|
||||
1
vendor/openssl/test/certv3_extfile
vendored
Normal file
1
vendor/openssl/test/certv3_extfile
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
crlDistributionPoints=URI:http://example.com/crl.pem,URI:http://example.com/crl2.pem
|
||||
BIN
vendor/openssl/test/cms.p12
vendored
Normal file
BIN
vendor/openssl/test/cms.p12
vendored
Normal file
Binary file not shown.
BIN
vendor/openssl/test/cms_pubkey.der
vendored
Normal file
BIN
vendor/openssl/test/cms_pubkey.der
vendored
Normal file
Binary file not shown.
28
vendor/openssl/test/corrupted-rsa.pem
vendored
Normal file
28
vendor/openssl/test/corrupted-rsa.pem
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCyiHMQLLOSG6T6
|
||||
AYpMTJj9f4WzXQF0+T0Ri/Mk6vcJMQdnLMrlEMIJA/4iCn32zvpQ0raYcuZZoyso
|
||||
/Svqg7tAeC3aQ/iFopYWfaR+SDMEnpKMl26qwiIxlPcj9J8hAQw/9WA7YneBXq+T
|
||||
ypONX4EeDn+bsp/mSNSZKYJBmwXevQ9xbnOOxmBrVd5OS07ZwYuQXy8uVsYe4IXX
|
||||
7/F+BIyULnIlUxRcVRjKp9++PeS53KLJX04H6HeqUiWC8Ntd+DuD3df0a067L38o
|
||||
sc+CVzwKXqvh75RwlXCR4/B3D9qEqSYmY7lxp9vA3hirWcSJn0xUIbHb7q1hzE0H
|
||||
rL65mLwnAgMBAAECggEADePYJpKBGBAm35KTcB3ngJWAJp/I92ZVbieNb7peJOzC
|
||||
btsJIBWT2xVgm2+7NCK5+Tl486xrfTQuLUlhNiTbQof3HUumKr4nCjHqmdlD1YtW
|
||||
yzG+7kceAkMyOoMThwL+Bn3bPP42CQPVCjJmahyGPvs8H2DK2E+jRr/4KTgxQTki
|
||||
s/MXmJa4+xhvfF4CmFVj8imkKCyUTFoaqvYevHDMrJ3cohXFONBPv0MT8X/Y0sgw
|
||||
UVaZ1aw3dbLC2PBpZFotILGxch2rODXgOcer/GBC41aGQTBB8mLPwKb6KMh0xdPd
|
||||
1E5NwyODA3YJ6W3fGe8WE0MIHoYlOkX+ukf4W4+U0wKBgQDhueBkZwrd1HdhqwhG
|
||||
QKt1/itCx24Go75G/+5vJUCB4bcdaJP49aH0/H4BiSsKI8r+GVsVJcrKP8h3tgjw
|
||||
hhuLLPSaWi9TiUsWeDTw0JrAJc7w6hwL1EYbnwcto5mRQdbfugitlkhh17yUmgdj
|
||||
gczAKLfV3igxslnR67iNOEYrlwKBgQDKejyWNnxhBJoXerpR/hijoXhMaHqV6Z7T
|
||||
gUy6F0BiJ5CqN+TOTaC17CEnsMmI28o1rWJ6bIKwOUPFXOE9Z5gyxuIJhY9M8n30
|
||||
iwm/Ug2oBTFAdZQyyCuCmPiNURnGo+Hhu1EtVwMWLt3Z0L+/DdI6pgPX8mG0NNZm
|
||||
+pS96Lg9owKBgHOzCslr5638kZSGTh90Vm6McTAxeLv+gjFyTYy6022/fFSenfom
|
||||
LXWdVhkDbgQshIfqBz23uVIhj2eM7tgaZVPZHydewpNW9B34T2qAAlIrDv99gBKw
|
||||
I59UzCEgkj5aOQFEId6YAVHlesvQh6kBhymXtWLyFDgk6tUmtdns1krRAoGBAJj0
|
||||
pnhDSMpxk4ZRLBdsgGh8PkhaVOCSz2yvrKqXjgeYI+yytKI0ekdzzcgSAOzmPGc4
|
||||
R8B74G4HlG6vr2eXrp4NKAxRXOOf/A6UShTBg5d99KrhJ8cE9/l8XadDsNkiTC0e
|
||||
OECsDqTfWrCExZUqd7neV+D2NWDQ2XaJrXuZJjVJAoGAIGA5ktXIxWIDeXkxo06b
|
||||
nHeTEmOAgER/5UIikHnoSAnXo5JNZyFxqoylthWuA1fMPQw/UphAeawDwEXVKp1J
|
||||
NEhLUfVAO/p1RBUsQi8LQVoO9Nql5u5dFjqoCnlRv5tbeAAzZH5magZk7/1rOS5T
|
||||
Cj7WW2zW+iL20suUmXfCQGU=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
20
vendor/openssl/test/crl-ca.crt
vendored
Normal file
20
vendor/openssl/test/crl-ca.crt
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDPDCCAiSgAwIBAgIUM+cEhwkyhyHZzXyqTFq7LGx7VCgwDQYJKoZIhvcNAQEL
|
||||
BQAwETEPMA0GA1UEAwwGVGVzdENBMB4XDTE5MDYwNjE5MTA1NVoXDTI5MDYwMzE5
|
||||
MTA1NVowETEPMA0GA1UEAwwGVGVzdENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
|
||||
MIIBCgKCAQEAtNcFPtD1MHcolhgTHIAx/b9OyawCbVzvgasv8R9+94ZMhoGc/tNc
|
||||
dVg271pCSmj+zYAFYsIwjxW+iq2e5A/fiBc6uqtNfEbU7+77QzxFG5wIbXtmmqEb
|
||||
dVbqBT28NeKTR6X+EHlNgbw90CHy7byA7LMewxbTt2q1eY1RnB0ji8zdGZmIUPeC
|
||||
WxzkxXEd0fg+KwBFN3YHV9CJX2KJ10qv7DvbKHeIVBU7osm6tzvNglNnnT90GFSY
|
||||
zc59b+zS00axcY3Kn08Vt+1qWB9Sl8tixCTGqR538y/ambDr3NCWsiQYWys9KE1L
|
||||
g0nEaIjb84R7b+qNmPtOezd9tanx7j9UzQIDAQABo4GLMIGIMB0GA1UdDgQWBBTF
|
||||
zPWhjNnkp7rsIfXRhCPqDcLHMDBMBgNVHSMERTBDgBTFzPWhjNnkp7rsIfXRhCPq
|
||||
DcLHMKEVpBMwETEPMA0GA1UEAwwGVGVzdENBghQz5wSHCTKHIdnNfKpMWrssbHtU
|
||||
KDAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEA
|
||||
gdyQq6F8DO5rn7rZSLehTFx6tbtfncC/BOXZEGLZO0ciTrQ9Q8xHwRhz0W09QE1A
|
||||
/GsBzb++PuvAl9i82WvunyPB5KZh+GPiaaqf466MdQrXj+IyqxeC9Lg9wEUjwRgp
|
||||
ANVd3moKap5IZ9WDvhyEng2Oy8/btP2iqVEmd58rGAodd671eOPD8QkIxSquiIwy
|
||||
Cu5s3IBZ0BOuSG9fWoyPTGMKAhzQPFiXGvWOabCkMz3TsPYVY5ENpq2K8cWn2D/r
|
||||
TD1yPPdINg6HrALGD3S0sD+k588oS7U5oj1L8V4KJQTLSbh6/XcBpasa5Jdv7ZZe
|
||||
lVgt69Gsn5Cf2BkbwhbF2Q==
|
||||
-----END CERTIFICATE-----
|
||||
62
vendor/openssl/test/csr.pem
vendored
Normal file
62
vendor/openssl/test/csr.pem
vendored
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
Certificate Request:
|
||||
Data:
|
||||
Version: 1 (0x0)
|
||||
Subject: C = AU, ST = Some-State, O = Internet Widgits Pty Ltd, CN = foobar.com
|
||||
Subject Public Key Info:
|
||||
Public Key Algorithm: rsaEncryption
|
||||
RSA Public-Key: (2048 bit)
|
||||
Modulus:
|
||||
00:a8:f4:25:8c:44:b3:17:a3:50:85:fe:23:91:87:
|
||||
d0:78:36:1b:49:17:ff:2d:47:d3:e5:1b:de:6c:36:
|
||||
fc:96:b9:04:3f:f2:37:de:bf:ef:33:12:ba:65:c5:
|
||||
f2:e4:b7:4a:49:a9:ca:22:64:6f:20:f4:d5:34:91:
|
||||
4e:a8:e5:3f:bf:d5:08:19:72:50:80:a1:96:92:d0:
|
||||
9a:b1:9a:8a:36:62:4f:f5:42:c8:f5:ea:99:cc:05:
|
||||
cd:74:b9:20:e4:e9:5f:5a:25:25:f5:bc:ac:0e:35:
|
||||
53:52:c2:21:c0:d4:c8:57:fa:2e:d6:7f:bf:ca:d2:
|
||||
78:aa:fa:4e:e1:3a:48:65:78:59:16:81:9b:54:ab:
|
||||
8d:60:5e:1d:55:7c:eb:a0:91:ae:d4:92:d6:27:93:
|
||||
d9:ab:05:b0:0c:8e:66:a5:a1:93:67:da:93:0c:01:
|
||||
0c:55:83:84:e1:88:b9:b7:ce:fb:96:aa:f5:c0:49:
|
||||
6c:d4:65:ce:c8:01:dd:46:6c:de:00:b4:3b:a1:b3:
|
||||
6e:76:7a:a1:3d:13:88:93:1e:4e:c5:d7:8c:00:4b:
|
||||
52:56:aa:fe:ba:ea:14:5e:18:7a:e6:64:91:b1:d3:
|
||||
14:13:33:db:cf:0f:51:cd:e6:dd:94:dc:a4:df:84:
|
||||
ef:e6:4e:50:14:59:5c:a0:f6:d0:ad:3b:36:e8:2a:
|
||||
0b:35
|
||||
Exponent: 65537 (0x10001)
|
||||
Attributes:
|
||||
a0:00
|
||||
Signature Algorithm: sha256WithRSAEncryption
|
||||
95:26:e1:84:56:e7:80:da:2c:a4:c0:b5:85:43:61:85:34:84:
|
||||
37:83:c0:bc:cf:70:20:89:46:ce:3d:7e:23:8a:40:a4:a5:fa:
|
||||
c5:e3:3d:ee:e5:05:16:58:93:f9:6c:f3:86:ee:99:cc:e1:04:
|
||||
5c:68:99:da:66:72:a1:95:31:cd:13:6f:a5:6f:fc:a9:ec:75:
|
||||
6a:f7:e5:cf:0e:7b:5f:2f:db:8d:45:e6:66:52:12:1d:c9:ac:
|
||||
3a:86:35:bd:1f:7b:6e:b5:e1:f3:4f:80:6a:06:73:1c:a0:0d:
|
||||
a3:63:b6:40:76:25:b0:e9:96:33:7a:9d:18:7e:5e:93:c0:47:
|
||||
d7:0b:da:b3:03:17:94:d0:0c:78:18:f3:0e:cd:3c:f7:e8:25:
|
||||
08:c2:13:0a:af:1e:5c:48:5f:17:41:b2:2d:d2:0f:37:2e:b3:
|
||||
10:fd:2b:c0:77:e1:17:8a:57:0c:95:5e:c8:03:eb:63:14:2e:
|
||||
46:fd:1e:14:13:9f:38:c1:2f:e9:9b:47:c3:60:a9:d7:6e:a3:
|
||||
d0:af:0b:6f:df:6e:37:f6:d9:a0:1b:dd:1f:a5:a5:33:89:1f:
|
||||
a5:a3:44:14:91:83:c3:c8:b2:6e:fb:3f:f1:6d:d2:51:21:f7:
|
||||
98:20:0a:40:75:a5:60:c3:59:53:08:62:3d:39:e8:83:55:90:
|
||||
1a:bf:51:57
|
||||
-----BEGIN CERTIFICATE REQUEST-----
|
||||
MIICnzCCAYcCAQAwWjELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx
|
||||
ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDETMBEGA1UEAwwKZm9v
|
||||
YmFyLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKj0JYxEsxej
|
||||
UIX+I5GH0Hg2G0kX/y1H0+Ub3mw2/Ja5BD/yN96/7zMSumXF8uS3SkmpyiJkbyD0
|
||||
1TSRTqjlP7/VCBlyUIChlpLQmrGaijZiT/VCyPXqmcwFzXS5IOTpX1olJfW8rA41
|
||||
U1LCIcDUyFf6LtZ/v8rSeKr6TuE6SGV4WRaBm1SrjWBeHVV866CRrtSS1ieT2asF
|
||||
sAyOZqWhk2fakwwBDFWDhOGIubfO+5aq9cBJbNRlzsgB3UZs3gC0O6GzbnZ6oT0T
|
||||
iJMeTsXXjABLUlaq/rrqFF4YeuZkkbHTFBMz288PUc3m3ZTcpN+E7+ZOUBRZXKD2
|
||||
0K07NugqCzUCAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQCVJuGEVueA2iykwLWF
|
||||
Q2GFNIQ3g8C8z3AgiUbOPX4jikCkpfrF4z3u5QUWWJP5bPOG7pnM4QRcaJnaZnKh
|
||||
lTHNE2+lb/yp7HVq9+XPDntfL9uNReZmUhIdyaw6hjW9H3tuteHzT4BqBnMcoA2j
|
||||
Y7ZAdiWw6ZYzep0Yfl6TwEfXC9qzAxeU0Ax4GPMOzTz36CUIwhMKrx5cSF8XQbIt
|
||||
0g83LrMQ/SvAd+EXilcMlV7IA+tjFC5G/R4UE584wS/pm0fDYKnXbqPQrwtv3243
|
||||
9tmgG90fpaUziR+lo0QUkYPDyLJu+z/xbdJRIfeYIApAdaVgw1lTCGI9OeiDVZAa
|
||||
v1FX
|
||||
-----END CERTIFICATE REQUEST-----
|
||||
8
vendor/openssl/test/dhparams.pem
vendored
Normal file
8
vendor/openssl/test/dhparams.pem
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
-----BEGIN DH PARAMETERS-----
|
||||
MIIBCAKCAQEAh3Betv+hf5jNsOmGXU8oxuABD2B8r0yU8FVgjnCZBSVo61qJ0A2d
|
||||
J6r8rYKbjtolnrZN/V4IPSzYvxurHbu8nbiFVyhOySPchI2Fu+YT/HsSe/0MH9bW
|
||||
gJTNzmutWoy9VxtWLCmXnOSZHep3MZ1ZNimno6Kh2qQ7VJr0+KF8GbxUKOPv4SqK
|
||||
NBwouIQXFc0pE9kGhcGKbr7TnHhyJFCRLNP1OVDQZbcoKjk1Vh+5sy7vM2VUTQmM
|
||||
yOToT2LEZVAUJXNumcYMki9MIwfYCwYZbNt0ZEolyHzUEesuyHfU1eJd6+sKEjUz
|
||||
5GteQIR7AehxZIS+cytu7BXO7B0owLJ2awIBAg==
|
||||
-----END DH PARAMETERS-----
|
||||
12
vendor/openssl/test/dsa.pem
vendored
Normal file
12
vendor/openssl/test/dsa.pem
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
-----BEGIN DSA PRIVATE KEY-----
|
||||
MIIBuwIBAAKBgQCkKe/jtYKJNQafaE7kg2aaJOEPUV0Doi451jkXHp5UfLh6+t42
|
||||
eabSGkE9WBAlILgaB8yHckLe9+zozN39+SUDp94kb2r38/8w/9Ffhbsep9uiyOj2
|
||||
ZRQur6SkpKQDKcnAd6IMZXZcvdSgPC90A6qraYUZKq7Csjn63gbC+IvXHwIVAIgS
|
||||
PE43lXD8/rGYxos4cxCgGGAxAoGASMV56WhLvVQtWMVI36WSIxbZnC2EsnNIKeVW
|
||||
yXnP/OmPJ2mdezG7i1alcwsO2TnSLbvjvGPlyzIqZzHvWC8EmDqsfbU+n8we/Eal
|
||||
sm5nloC8m9ECWpbTzbNdvrAAj9UPVWjcDwg7grAGGysh6lGbBv5P+4zL/niq1UiE
|
||||
LnKcifgCgYEAo6mAasO0+MVcu8shxxUXXNeTLsZ8NB/BIx9EZ/dzE23ivNW8dq1A
|
||||
eecAAYhssI2m/CspQvyKw+seCvg4FccxJgB3+mGOe+blFHwO3eAwoyRn/t3DZDHh
|
||||
FjxKKRsQdy4BkZv+vhTyIYYCw0iPZ5Wfln+pyGGTveIDED1MPG+J6c8CFCJAUlEl
|
||||
4nHvbC15xLXXpd46zycY
|
||||
-----END DSA PRIVATE KEY-----
|
||||
12
vendor/openssl/test/dsa.pem.pub
vendored
Normal file
12
vendor/openssl/test/dsa.pem.pub
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBtzCCASsGByqGSM44BAEwggEeAoGBAKQp7+O1gok1Bp9oTuSDZpok4Q9RXQOi
|
||||
LjnWORcenlR8uHr63jZ5ptIaQT1YECUguBoHzIdyQt737OjM3f35JQOn3iRvavfz
|
||||
/zD/0V+Fux6n26LI6PZlFC6vpKSkpAMpycB3ogxldly91KA8L3QDqqtphRkqrsKy
|
||||
OfreBsL4i9cfAhUAiBI8TjeVcPz+sZjGizhzEKAYYDECgYBIxXnpaEu9VC1YxUjf
|
||||
pZIjFtmcLYSyc0gp5VbJec/86Y8naZ17MbuLVqVzCw7ZOdItu+O8Y+XLMipnMe9Y
|
||||
LwSYOqx9tT6fzB78RqWybmeWgLyb0QJaltPNs12+sACP1Q9VaNwPCDuCsAYbKyHq
|
||||
UZsG/k/7jMv+eKrVSIQucpyJ+AOBhQACgYEAo6mAasO0+MVcu8shxxUXXNeTLsZ8
|
||||
NB/BIx9EZ/dzE23ivNW8dq1AeecAAYhssI2m/CspQvyKw+seCvg4FccxJgB3+mGO
|
||||
e+blFHwO3eAwoyRn/t3DZDHhFjxKKRsQdy4BkZv+vhTyIYYCw0iPZ5Wfln+pyGGT
|
||||
veIDED1MPG+J6c8=
|
||||
-----END PUBLIC KEY-----
|
||||
9
vendor/openssl/test/dsaparam.pem
vendored
Normal file
9
vendor/openssl/test/dsaparam.pem
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
-----BEGIN DSA PARAMETERS-----
|
||||
MIIBHgKBgQCkKe/jtYKJNQafaE7kg2aaJOEPUV0Doi451jkXHp5UfLh6+t42eabS
|
||||
GkE9WBAlILgaB8yHckLe9+zozN39+SUDp94kb2r38/8w/9Ffhbsep9uiyOj2ZRQu
|
||||
r6SkpKQDKcnAd6IMZXZcvdSgPC90A6qraYUZKq7Csjn63gbC+IvXHwIVAIgSPE43
|
||||
lXD8/rGYxos4cxCgGGAxAoGASMV56WhLvVQtWMVI36WSIxbZnC2EsnNIKeVWyXnP
|
||||
/OmPJ2mdezG7i1alcwsO2TnSLbvjvGPlyzIqZzHvWC8EmDqsfbU+n8we/Ealsm5n
|
||||
loC8m9ECWpbTzbNdvrAAj9UPVWjcDwg7grAGGysh6lGbBv5P+4zL/niq1UiELnKc
|
||||
ifg=
|
||||
-----END DSA PARAMETERS-----
|
||||
11
vendor/openssl/test/entry_extensions.crl
vendored
Normal file
11
vendor/openssl/test/entry_extensions.crl
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
-----BEGIN X509 CRL-----
|
||||
MIIBojCCAUkCAQEwCgYIKoZIzj0EAwIwHTEbMBkGA1UEAwwSY3J5cHRvZ3JhcGh5
|
||||
LmlvIENBFw0yMzA3MjUxNDA1MzlaFw0yMzA4MDExNDA1MzlaMIGAMH4CFE+Y95/1
|
||||
pOqa6c9fUEJ8c04kxu2PFw0yMzA3MjUxNDA1MzlaMFcwLwYDVR0dAQH/BCUwI6Qh
|
||||
MB8xCzAJBgNVBAYTAkdCMRAwDgYDVQQDDAdUZXN0IENBMAoGA1UdFQQDCgEBMBgG
|
||||
A1UdGAQRGA8yMDIzMDcyNTE0MDUzOVqgeDB2MB8GA1UdIwQYMBaAFK6qKNgsGefh
|
||||
XexO9WsIwiQ/73R8MAoGA1UdFAQDAgEUMAwGA1UdHAQFMAOEAf8wOQYIKwYBBQUH
|
||||
AQEELTArMCkGCCsGAQUFBzAChh1odHRwOi8vd3d3LmV4YW1wbGUuY29tL2NhLmNy
|
||||
dDAKBggqhkjOPQQDAgNHADBEAiB22SXxFnQUB41uxfyCvg2dAs2nFiR0r8jft/cd
|
||||
G8zcKAIgeYkNOzRn4lyopK6J94rhm8jIIuJRj3Ns9XcH+91N370=
|
||||
-----END X509 CRL-----
|
||||
BIN
vendor/openssl/test/identity.p12
vendored
Normal file
BIN
vendor/openssl/test/identity.p12
vendored
Normal file
Binary file not shown.
27
vendor/openssl/test/intermediate-ca.key
vendored
Normal file
27
vendor/openssl/test/intermediate-ca.key
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEA1HsHFTpgKeWL/y6oKtARZm0Dy6J/08E0CujmdpVp0xnkXi/A
|
||||
RARnbMEbOPfmBUMOkVtQT3+l5aCgIAX+Kg6K7sQvio8nQUgOxuO1YpGlYu9EMtc7
|
||||
5fNxA1T0CuXXx8ClfEqW1ZV7ziQV0J4gzvuI26A7XyUhdk1oP/Al3F/94TmH6dtP
|
||||
SQ2K901O2zknU+bpPheQy08SE20k/nUOJAsiwtsxqY8hHOL1sXZ4K+I311hl0QpD
|
||||
OYf7eBcBdo2Mc5Nzjd9LPGLk1lE3itAXpayFMmfuuA0IdH1gNfy18axFEEVnj6CS
|
||||
2epGpmAckUEWUOse1WBhDEt6ddowT1iw7X4mWwIDAQABAoIBAGMGXzuudAiymTc5
|
||||
OFiTlbhlkAJEXkyC201GU7nqUmJ2y651lKZeYxEVQimfpszG/rARnXEfbWKCJH4o
|
||||
LNbO5kL2na12n/XVrkVU9EDW3fwoxGDpXFoDxaSm4AGAMrs+diFh5b/upb9ho+UQ
|
||||
/PtZ0OOCXokuFdU7qB08P3jgJ8LhooqWnZ4AC0rhN85CMNIKs/nrUrnmS3FZLVd/
|
||||
NWI9Vfjsndd41Gkho0A7tgOSnwRupk/Bv1b0px31h8ucp9/nLuR8vbGSdS/R9Sta
|
||||
pB9KNYYQ3LrhQGjddnEU0gj8qsuWgnoPf7eaWsLVunPLHQzL2hNNKL1eBADm7Lhh
|
||||
avIlnrkCgYEA8Q8UhOeIO0sMU8sB4NPTUf2UT9xjURoowGsGgbDEk21eABH6VC33
|
||||
VYt5r5xwbZFQvVaTbe+EI1YDpjH1cvpmorEWI47Nm4Vbf9JujW/hoQwuwpzOpdUT
|
||||
2G4tfMQrmTw/9HJ0l9+1Ib+A93dB8GvR0NE1uueaWanWvXARInwGiscCgYEA4aZ9
|
||||
mbhuwx88sSRMXwxSZw+R5BRrjdC0CeoimGg4/P84bKgc0YsjAha5jWaC/h8xN2Pb
|
||||
w45b3hQ0/FP8xohP0bp/5eeiDbqb6JuO5bI3CnfBrVpu1CAuIrf7lhkar3a0wluB
|
||||
k03fVHuVLtydACDJBKrZm1F39lpiZiEqlBIp080CgYEAwRwYjwPAEefkHzhQ7+Ah
|
||||
uNwQtQ1TjsQLA2J5mumWAJirphjA1jDgo+oQ+Iq1UkEIUjWJ85bd30TntXruK0bH
|
||||
c+uzVZbvxXfGvhZAtBN9x/svdn4R2a1hsY9J51prpt0qStRp7MSsoTV9xkEGVOi6
|
||||
87K1fV5OOyggvC+Lunlq8D8CgYAVSCOObPOdWYPa3SaKzFm1OKW00iw2qtlgGgH7
|
||||
R9EgI14J+W0GYk4B82y6plFycDSvGa7vaazGbDd3GOC9RLvqduF7KHaDPvdXX9yB
|
||||
U2aXiSXuGJpdTU+snJeQ13tJ0zNHJWQ6JV0L1cADNHFmQrFSzF5LpMpgpLOlGDmw
|
||||
z2m8fQKBgQDclFeonyn0zcXqznun9kAKkMij4s6lSdRgi/5Zh1WbJwOso9oWfwz9
|
||||
SSTP2KBO8B+/yFvuo5SWrbNaTz9/KuzMTv4HXz5ukLbyN9Jjtk73fdBBRSjL+zF5
|
||||
jU56oXHrwBhEqWQ77Ps60r+FmDjUgUhyJl14ZfkzICUK7NLFxKrvMQ==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
22
vendor/openssl/test/intermediate-ca.pem
vendored
Normal file
22
vendor/openssl/test/intermediate-ca.pem
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDszCCApugAwIBAgIEFSQSITANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJB
|
||||
VTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0
|
||||
cyBQdHkgTHRkMB4XDTIyMTEwMzA3MDc0OVoXDTI2MDgxMTA3MDc0OVowgYkxCzAJ
|
||||
BgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5l
|
||||
dCBXaWRnaXRzIFB0eSBMdGQxIDAeBgNVBAsMF0ludGVybWVkaWF0ZSBEZXBhcnRt
|
||||
ZW50MSAwHgYDVQQDDBdpbnRlcm1lZGlhdGUuZm9vYmFyLmNvbTCCASIwDQYJKoZI
|
||||
hvcNAQEBBQADggEPADCCAQoCggEBANR7BxU6YCnli/8uqCrQEWZtA8uif9PBNAro
|
||||
5naVadMZ5F4vwEQEZ2zBGzj35gVDDpFbUE9/peWgoCAF/ioOiu7EL4qPJ0FIDsbj
|
||||
tWKRpWLvRDLXO+XzcQNU9Arl18fApXxKltWVe84kFdCeIM77iNugO18lIXZNaD/w
|
||||
Jdxf/eE5h+nbT0kNivdNTts5J1Pm6T4XkMtPEhNtJP51DiQLIsLbMamPIRzi9bF2
|
||||
eCviN9dYZdEKQzmH+3gXAXaNjHOTc43fSzxi5NZRN4rQF6WshTJn7rgNCHR9YDX8
|
||||
tfGsRRBFZ4+gktnqRqZgHJFBFlDrHtVgYQxLenXaME9YsO1+JlsCAwEAAaNmMGQw
|
||||
HQYDVR0OBBYEFAXJImmmxYXx6L1SRRhgP3Tyq2J6MB8GA1UdIwQYMBaAFGzTpQOr
|
||||
DV8syY2KnIiniHe4N/2aMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQD
|
||||
AgGGMA0GCSqGSIb3DQEBCwUAA4IBAQCnUh7iNbnFBjVa4sFx02r65syxUhcvM/ya
|
||||
DcSe1esGUwjZLyKVl9BTfQ6kfNa/6Z/t5cprp0R3etalN31dxka7xSDwzFNdBczB
|
||||
zYDIVOVlcGLL1Xjozacm6YHo773dqxZS36rVMk3NqNUY6GJJ+CGso2xZShcBg2KG
|
||||
fPlNPiRz3847E3dwouDYcP1MXf2ql/Y7dRbE+8kb3bWkSusJVb/4EHjpR7yZjKmh
|
||||
eXHVVx1dKnCGRldn3+dSNhN6mxNaSeBE2hb158+diQvL5u3f//va7SOpCi0f4d8E
|
||||
UCnLhieyrDlr42XXfz42BqRpqBO1SDjQwzIIc9Fbevwb916OSExp
|
||||
-----END CERTIFICATE-----
|
||||
BIN
vendor/openssl/test/key.der
vendored
Normal file
BIN
vendor/openssl/test/key.der
vendored
Normal file
Binary file not shown.
BIN
vendor/openssl/test/key.der.pub
vendored
Normal file
BIN
vendor/openssl/test/key.der.pub
vendored
Normal file
Binary file not shown.
28
vendor/openssl/test/key.pem
vendored
Normal file
28
vendor/openssl/test/key.pem
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCo9CWMRLMXo1CF
|
||||
/iORh9B4NhtJF/8tR9PlG95sNvyWuQQ/8jfev+8zErplxfLkt0pJqcoiZG8g9NU0
|
||||
kU6o5T+/1QgZclCAoZaS0Jqxmoo2Yk/1Qsj16pnMBc10uSDk6V9aJSX1vKwONVNS
|
||||
wiHA1MhX+i7Wf7/K0niq+k7hOkhleFkWgZtUq41gXh1VfOugka7UktYnk9mrBbAM
|
||||
jmaloZNn2pMMAQxVg4ThiLm3zvuWqvXASWzUZc7IAd1GbN4AtDuhs252eqE9E4iT
|
||||
Hk7F14wAS1JWqv666hReGHrmZJGx0xQTM9vPD1HN5t2U3KTfhO/mTlAUWVyg9tCt
|
||||
OzboKgs1AgMBAAECggEBAKLj6IOJBKXolczpzb8UkyAjAkGBektcseV07gelJ/fk
|
||||
3z0LuWPv5p12E/HlXB24vU2x/ikUbbP3eMsawRzDEahQqmNmPEkYAYUAy/Qpi9GN
|
||||
DYvn3LqDec4jVgeQKS+p9H2DzUpTogp8zR2//yzbuWBg2+F//xh7vU0S0RQCziPM
|
||||
x7RSBgbhxSfChfEJbS2sDnzfh0jRQmoY95iFv7puet1FJtzdZ4fgCd1RqmC2lFM5
|
||||
H0eZtN/Cz19lieVs0b996DErdEBqClVZO00eYbRozCDaBzRU3ybB/dMrGJxhkkXm
|
||||
wb3kWMtziH9qOYsostuHIFu8eKFLloKxFnq2R4DGxOECgYEA2KUIZISOeGJSBcLJ
|
||||
JAUK2gvgXPNo4HHWIwOA9xeN3ZJlsnPlffXQNnm6t1st1V2gfMm9I2n0m/F0y2B/
|
||||
n/XGSa8bghfPA9l0c2h58lkL3JQJR/paa8ycTz+YZPrznEyN7Qa0RrJXUvZv9lQL
|
||||
Hc3+FHcSHgMqDV2f2bHAEu9YGi0CgYEAx6VEIPNvrHFgjo/jk1RTuk+m0xEWQsZL
|
||||
Cs+izQMr2TaeJn8LG+93AvFuYn0J0nT3WuStLPrUg8i4IhSS6lf1tId5ivIZPm4r
|
||||
YwMyblBJXhnHbk7Uqodjfw/3s6V2HAu++B7hTdyVr9DFuST9uv4m8bkPV8rfX1jE
|
||||
I2rAPVWvgikCgYB+wNAQP547wQrMZBLbCDg5KwmyWJfb+b6X7czexOEz6humNTjo
|
||||
YZHYzY/5B1fhpk3ntQD8X1nGg5caBvOk21+QbOtjShrM3cXMYCw5JvBRtitX+Zo9
|
||||
yBEMLOE0877ki8XeEDYZxu5gk98d+D4oygUGZEQtWxyXhVepPt5qNa8OYQKBgQDH
|
||||
RVgZI6KFlqzv3wMh3PutbS9wYQ+9GrtwUQuIYe/0YSW9+vSVr5E0qNKrD28sV39F
|
||||
hBauXLady0yvB6YUrjMbPFW+sCMuQzyfGWPO4+g3OrfqjFiM1ZIkE0YEU9Tt7XNx
|
||||
qTDtTI1D7bhNMnTnniI1B6ge0und+3XafAThs5L48QKBgQCTTpfqMt8kU3tcI9sf
|
||||
0MK03y7kA76d5uw0pZbWFy7KI4qnzWutCzb+FMPWWsoFtLJLPZy//u/ZCUVFVa4d
|
||||
0Y/ASNQIESVPXFLAltlLo4MSmsg1vCBsbviEEaPeEjvMrgki93pYtd/aOSgkYC1T
|
||||
mEq154s5rmqh+h+XRIf7Au0SLw==
|
||||
-----END PRIVATE KEY-----
|
||||
9
vendor/openssl/test/key.pem.pub
vendored
Normal file
9
vendor/openssl/test/key.pem.pub
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr1bXMptaIgOL9PVL8a7W
|
||||
KG/C8+IbxP018eMBQZT0SnPQmXp0Q8Aai/F+AEDE7b5sO5U7WdxU4GRYw0wqkQNF
|
||||
si78KNfoj2ZMlx6NRfl4UKuzrpGTPgQxuKDYedngPpWcbmW4P3zEL2Y7b18n9NJr
|
||||
atRUzH1Zh/ReRO525Xadu58aviPw1Mzgse7cKyzb03Gll9noLnYNIIpO8jL+QyrD
|
||||
8qNmfacmR20U0a6XDTtmsmk7AitGETICbTT0KRf+oAP0yIHoonllPpNLUEPZQjrp
|
||||
ClS/S/wKdj7gaq9TaMbHULhFMjbCV8cuPu//rUAuWp3riaznZGOVQyn3Dp2CB3ad
|
||||
yQIDAQAB
|
||||
-----END PUBLIC KEY-----
|
||||
BIN
vendor/openssl/test/keystore-empty-chain.p12
vendored
Normal file
BIN
vendor/openssl/test/keystore-empty-chain.p12
vendored
Normal file
Binary file not shown.
21
vendor/openssl/test/leaf.pem
vendored
Normal file
21
vendor/openssl/test/leaf.pem
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDejCCAmICBBUkEiQwDQYJKoZIhvcNAQELBQAwgYkxCzAJBgNVBAYTAkFVMRMw
|
||||
EQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0
|
||||
eSBMdGQxIDAeBgNVBAsMF0ludGVybWVkaWF0ZSBEZXBhcnRtZW50MSAwHgYDVQQD
|
||||
DBdpbnRlcm1lZGlhdGUuZm9vYmFyLmNvbTAeFw0yMjExMDMwNzE3NTJaFw0yNjA4
|
||||
MTEwNzE3NTJaMHkxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
|
||||
HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxGDAWBgNVBAsMD0xlYWYg
|
||||
RGVwYXJ0bWVudDEYMBYGA1UEAwwPbGVhZi5mb29iYXIuY29tMIIBIjANBgkqhkiG
|
||||
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs9STUHGIcSOtioK6+02k9Jx4JuYVJ0SB7Ebd
|
||||
FAhGiOxBSoOljRVmmALti89QMmRiRqlyJnGJch7AloCCRsLJA0MfUYvauqmKHZFk
|
||||
iqtZ1HocHQ/LGNKfkILcclb4xp2nGYntKAyEqer3Qc6aPWAnQAV/+BshU1vlMfwU
|
||||
T6vOJRG69mft6dkHEWSzZd7++7HmFQGnDmIs5jBJVCOgKVttkN8Bk2EsTvJi9zl2
|
||||
SXLTcVrTAxEvuawv2ZXvdI/Cpt1WW0litXlFLcYBGwt/N93TX/L3Iyw5HcNd/xf9
|
||||
QwOr6RR66krQJzKxwcIY934uq6cyTQhexgnffb65qXL4bbV5fwIDAQABMA0GCSqG
|
||||
SIb3DQEBCwUAA4IBAQAZf0/r04AeKN2QhQ7Z0o2Iu/Yj3OD2tnbxVoltYk8CRfp3
|
||||
7VGl/5PUbmXXBSwMc4Udj88JlreU7iNEPAKtBqFczw0pwNfvxKG4Eh3vsfKrP+5g
|
||||
gtVwDG0mWeKJ7udrmFt8N0uwxVYDKp/gv5+Bw2eMew9Eoyenj6k2yg0nbFKzA3EH
|
||||
DqngETzX0dhdiYwVcoJFUK5ni3tVl9qi6FpmaTE6C5nTQLyH4CI+vo2x/QHINGaJ
|
||||
OzY/rx35iyVqXVqxN/gO/hp6g0nT5zLuMg2rfvcAhdDsD7htYcHiNkofrC8s0oQE
|
||||
W+r01EhxdEVvY1nYWanBCF6tktc5v5qf2WMS4ye5
|
||||
-----END CERTIFICATE-----
|
||||
12
vendor/openssl/test/nid_test_cert.pem
vendored
Normal file
12
vendor/openssl/test/nid_test_cert.pem
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIB1DCCAX6gAwIBAgIJAMzXWZGWHleWMA0GCSqGSIb3DQEBCwUAMFYxHzAdBgkq
|
||||
hkiG9w0BCQEWEHRlc3RAZXhhbXBsZS5jb20xFDASBgNVBAMMC2V4YW1wbGUuY29t
|
||||
MR0wGwYJKoZIhvcNAQkUHg4ARQB4AGEAbQBwAGwAZTAeFw0xNTA3MDEwNjQ3NDRa
|
||||
Fw0xNTA3MzEwNjQ3NDRaMFYxHzAdBgkqhkiG9w0BCQEWEHRlc3RAZXhhbXBsZS5j
|
||||
b20xFDASBgNVBAMMC2V4YW1wbGUuY29tMR0wGwYJKoZIhvcNAQkUHg4ARQB4AGEA
|
||||
bQBwAGwAZTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCmejzp4+o35FD0hAnx2trL
|
||||
08h07X5jZca9DgZH35hWXPh7fMucLt/IPXIRnz2zKEa/Mo6D2V/fx03Mqo0epid7
|
||||
AgMBAAGjLzAtMB0GA1UdDgQWBBRQa57tXz3rZNRz+fTbo3w3jQJMBTAMBgNVHRME
|
||||
BTADAQH/MA0GCSqGSIb3DQEBCwUAA0EAm0iY9cr+gvC+vcQIebdofpQ4GcDW8U6W
|
||||
Bxs8ZXinLl69P0jYLum3+XITNFRiyQqcivaxdxthxDNOX7P+aKwkJA==
|
||||
-----END CERTIFICATE-----
|
||||
24
vendor/openssl/test/nid_uid_test_cert.pem
vendored
Normal file
24
vendor/openssl/test/nid_uid_test_cert.pem
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIEGTCCAwGgAwIBAgIJAItKTzcGfL1lMA0GCSqGSIb3DQEBCwUAMIGiMSIwIAYK
|
||||
CZImiZPyLGQBAQwSdGhpcyBpcyB0aGUgdXNlcklkMQswCQYDVQQGEwJVUzETMBEG
|
||||
A1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJU3Vubnl2YWxlMRUwEwYDVQQKDAxS
|
||||
dXN0IE9wZW5TU0wxDDAKBgNVBAsMA09TUzEhMB8GA1UEAwwYcnVzdC1vcGVuc3Ns
|
||||
LmV4YW1wbGUuY29tMB4XDTE2MDIwMjE3MjIwMVoXDTE2MDMwMzE3MjIwMVowgaIx
|
||||
IjAgBgoJkiaJk/IsZAEBDBJ0aGlzIGlzIHRoZSB1c2VySWQxCzAJBgNVBAYTAlVT
|
||||
MRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlTdW5ueXZhbGUxFTATBgNV
|
||||
BAoMDFJ1c3QgT3BlblNTTDEMMAoGA1UECwwDT1NTMSEwHwYDVQQDDBhydXN0LW9w
|
||||
ZW5zc2wuZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
|
||||
AQDa3Gc+IE5DOhTv1m5DZW8qKiyNLd7v4DaAYLXSsDuLs+9wJ+Bs+wlBfrg+PT0t
|
||||
EJlPaLL9IfD5eR3WpFu62TUexYhnJh+3vhCGsFHOXcTjtM+wy/dzZtOVh2wTzvqE
|
||||
/FHBGw1eG3Ww+RkSFbwYmtm8JhIN8ffYxGn2O0yQpxypf5hNPYrC81zX+52X2w1h
|
||||
jDYLpYt55w+e6q+iRRFk0tKiWHEqqh/r6UQQRpj2EeS+xTloZlO6h0nl2NPkVF3r
|
||||
CXBoT8Ittxr7sqcYqf8TAA0I4qZRYXKYehFmv/VkSt85CcURJ/zXeoJ1TpxSvQie
|
||||
2R9cRDkYROrIOAFbB/0mmHLBAgMBAAGjUDBOMB0GA1UdDgQWBBRKfPqtgrbdbTmH
|
||||
XR6RC/p8t/65GjAfBgNVHSMEGDAWgBRKfPqtgrbdbTmHXR6RC/p8t/65GjAMBgNV
|
||||
HRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCKfeGRduGsIwKNiGcDUNkNrc7Z
|
||||
f8SWAmb/R6xiDfgjbhrtfBDowIZ5natEkTgf6kQPMJKyjg2NEM2uJWBc55rLOHIv
|
||||
es1wQOlYjfEUmFD3lTIt2TM/IUgXn2j+zV1CRkJthQLVFChXsidd0Bqq2fBjd3ad
|
||||
Yjzrxf3uOTBAs27koh2INNHfcUZCRsx8hP739zz2kw/r5NB/9iyENEyJKQvxo0jb
|
||||
oN0JK2joGZrWetDukQrqf032TsdkboW5JresYybbAD3326Ljp+hlT/3WINc+3nZJ
|
||||
Dn+pPMdpuZ5BUZ+u+XyNEPum3k3P3K19AF+zWYGooX0J1cmuCBrrqce20Lwy
|
||||
-----END CERTIFICATE-----
|
||||
8
vendor/openssl/test/pkcs1.pem.pub
vendored
Normal file
8
vendor/openssl/test/pkcs1.pem.pub
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
-----BEGIN RSA PUBLIC KEY-----
|
||||
MIIBCgKCAQEAyrcf7lv42BCoiDd3LYmF8eaGO4rhmGzGgi+NSZowkEuLhibHGQle
|
||||
FkZC7h1VKsxKFgy7Fx+GYHkv9OLm9H5fdp3HhYlo19bZVGvSJ66OJe/Bc4S02bBb
|
||||
Y8vwpc/N5O77m5J/nHLuL7XJtpfSKkX+3NPiX1X2L99iipt7F0a7hNws3G3Lxg6t
|
||||
P3Yc55TPjXzXvDIgjt/fag6iF8L/bR3augJJdDhLzNucR8A5HcvPtIVo51R631Zq
|
||||
MCh+dZvgz9zGCXwsvSky/iOJTHN3wnpsWuCAzS1iJMfjR783Tfv6sWFs19FH7pHP
|
||||
xBA3b2enPM9KBzINGOly0eM4h0fh+VBltQIDAQAB
|
||||
-----END RSA PUBLIC KEY-----
|
||||
BIN
vendor/openssl/test/pkcs8-nocrypt.der
vendored
Normal file
BIN
vendor/openssl/test/pkcs8-nocrypt.der
vendored
Normal file
Binary file not shown.
BIN
vendor/openssl/test/pkcs8.der
vendored
Normal file
BIN
vendor/openssl/test/pkcs8.der
vendored
Normal file
Binary file not shown.
27
vendor/openssl/test/root-ca.key
vendored
Normal file
27
vendor/openssl/test/root-ca.key
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpQIBAAKCAQEArVHWFn52Lbl1l59exduZntVSZyDYpzDND+S2LUcO6fRBWhV/
|
||||
1Kzox+2GZptbuMGmfI3iAnb0CFT4uC3kBkQQlXonGATSVyaFTFR+jq/lc0SP+9Bd
|
||||
7SBXieIVeIXlY1TvlwIvj3Ntw9zX+scTA4SXxH6M0rKv9gTOub2vCMSHeF16X8DQ
|
||||
r4XsZuQr7Cp7j1I4aqOJyap5JTl5ijmG8cnu0n+8UcRlBzy99dLWJG0AfI3VRJdW
|
||||
pGTNVZ92aFff3RpK3F/WI2gp3qV1ynRAKuvmncGC3LDvYfcc2dgsc1N6Ffq8GIrk
|
||||
gRob6eBcklDHp1d023Lwre+VaVDSo1//Y72UFwIDAQABAoIBAGZrnd/dC2kp11uq
|
||||
Sg8SHk3GMdPPjTf/lq51sVJAU4fdV2Eso0XCiCzdKDcqR6F+jiu8jHp4YO0riW8N
|
||||
b1pkjohGjyOaddIaaVsZ80/OkgDz20Ird9XQ7uoEODvopA12+755BDH5PDwqHVeM
|
||||
nKfPiwAK6Jz6CxGO9bq9ZNoBiSyO1uofaB4Cpp8t74XVeAuPiI/Bb6WJ8TW5K5dt
|
||||
x0Jihdo46QgZR+z4PnyWIoACkhSoQmtTb9NUrpKceBcxdCrZ/kEmYpnPq/PuSw6g
|
||||
6HthjYP/H9Xulz69UR5Ez6z+1pU1rKFmQ46qK7X3zVHg233MlGekMzxdmShEjzCP
|
||||
BMGYpQECgYEA5tqTZsUJwx3HDhkaZ/XOtaQqwOnZm9wPwTjGbV1t4+NUJzsl5gjP
|
||||
ho+I8ZSGZ6MnNSh+ClpYhUHYBq0rTuAAYL2arcMOuOs1GrMmiZJbXm8zq8M7gYr5
|
||||
V99H/7akSx66WV/agPkLIvh/BWxlWgQcoVAIzZibbLUxr7Ye50pCLfECgYEAwDLn
|
||||
mFz0mFMvGtaSp8RnTDTFCz9czCeDt0GujCxG1epdvtuxlg/S1QH+mGzA/AHkiu7z
|
||||
uzCwGKWozNTdRkqVwYoJTB+AYHseSkuGP+a1zr39w+xBW/vESb2oP95GIwprXcG2
|
||||
b/qdeQVzuLQhYoqWI2u8CBwlHFfpQO4Bp2ea+ocCgYEAurIgLSfCqlpFpiAlG9hN
|
||||
8NYwgU1d4E+LKj+JMd8yRO+PGh8amjub4X3pST5NqDjpN3Nk42iHWFWUqGmZsbM0
|
||||
ewg7tLUgDeqiStKBoxaK8AdMqWc9k5lZ53e6mZISsnHKUQdVBaLjH8gJqdAs8yyK
|
||||
HudEB0mYwMSUxz6pJXIHrXECgYEAhJkaCpXm8chB8UQj/baUhZDKeI4IWZjRWHbq
|
||||
Ey7g1+hPMMOk6yCTlf1ARqyRH8u2ftuIL5bRhs+Te21IE5yVYOb4rxn0mZuXNC6S
|
||||
ujdTKwUMtESkeu9hZnaAQz/4J2ii1hY05WCDj+DhC4bKmY9/MYS8PuQb/kfwVqld
|
||||
Xr8tvrUCgYEAmslHocXBUFXyRDkEOx/aKo+t9fPBr95PBZzFUt9ejrTP4PXsLa46
|
||||
3/PNOCGdrQxh5qHHcvLwR4bPL++Dj+qMUTJXANrArKPDpE2WqH6pqWIC6yaZvzUk
|
||||
17QbpXR6bHcdJV045pWpw40UCStTocVynY1lBfOw8VqxBIBlpVBBzew=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
21
vendor/openssl/test/root-ca.pem
vendored
Normal file
21
vendor/openssl/test/root-ca.pem
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDXTCCAkWgAwIBAgIJAOIvDiVb18eVMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
|
||||
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
|
||||
aWRnaXRzIFB0eSBMdGQwHhcNMTYwODE0MTY1NjExWhcNMjYwODEyMTY1NjExWjBF
|
||||
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
|
||||
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
|
||||
CgKCAQEArVHWFn52Lbl1l59exduZntVSZyDYpzDND+S2LUcO6fRBWhV/1Kzox+2G
|
||||
ZptbuMGmfI3iAnb0CFT4uC3kBkQQlXonGATSVyaFTFR+jq/lc0SP+9Bd7SBXieIV
|
||||
eIXlY1TvlwIvj3Ntw9zX+scTA4SXxH6M0rKv9gTOub2vCMSHeF16X8DQr4XsZuQr
|
||||
7Cp7j1I4aqOJyap5JTl5ijmG8cnu0n+8UcRlBzy99dLWJG0AfI3VRJdWpGTNVZ92
|
||||
aFff3RpK3F/WI2gp3qV1ynRAKuvmncGC3LDvYfcc2dgsc1N6Ffq8GIrkgRob6eBc
|
||||
klDHp1d023Lwre+VaVDSo1//Y72UFwIDAQABo1AwTjAdBgNVHQ4EFgQUbNOlA6sN
|
||||
XyzJjYqciKeId7g3/ZowHwYDVR0jBBgwFoAUbNOlA6sNXyzJjYqciKeId7g3/Zow
|
||||
DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAVVaR5QWLZIRR4Dw6TSBn
|
||||
BQiLpBSXN6oAxdDw6n4PtwW6CzydaA+creiK6LfwEsiifUfQe9f+T+TBSpdIYtMv
|
||||
Z2H2tjlFX8VrjUFvPrvn5c28CuLI0foBgY8XGSkR2YMYzWw2jPEq3Th/KM5Catn3
|
||||
AFm3bGKWMtGPR4v+90chEN0jzaAmJYRrVUh9vea27bOCn31Nse6XXQPmSI6Gyncy
|
||||
OAPUsvPClF3IjeL1tmBotWqSGn1cYxLo+Lwjk22A9h6vjcNQRyZF2VLVvtwYrNU3
|
||||
mwJ6GCLsLHpwW/yjyvn8iEltnJvByM/eeRnfXV6WDObyiZsE/n6DxIRJodQzFqy9
|
||||
GA==
|
||||
-----END CERTIFICATE-----
|
||||
30
vendor/openssl/test/rsa-encrypted.pem
vendored
Normal file
30
vendor/openssl/test/rsa-encrypted.pem
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: AES-128-CBC,E2F16153E2BA3D617285A68C896BA6AF
|
||||
|
||||
vO9SnhtGjGe8pG1pN//vsONnvJr+DjU+lFCiSqGMPT7tezDnbehLfS+9kus2HV7r
|
||||
HmI14JvVG9O7NpF7zMyBRlHYdWcCCWED9Yar0NsWN9419e5pMe/bqIXAzAiJbtT4
|
||||
OB9U5XF3m+349zjN1dVXPPLGRmMC1pcHAlofeb5nIUFTvUi5xcsbe1itGjgkkvHb
|
||||
Bt8NioHTBun8kKrlsFQOuB55ylBU/eWG8DQBtvFOmQ7iWp0RnGQfh8k5e5rcZNpQ
|
||||
fD9ygc7UVISl0xTrIG4IH15g34H+nrBauKtIPOpNPuXQPOMHCZv3XH8wnhrWHHwT
|
||||
ZFnQBdXbSpQtMsRh0phG2G+VIlyCgSn4+CxjCJ+TgFtsoK/tU0unmRYc59QnTxxb
|
||||
qkHYsPs3E0NApQAgH1ENEGl1M+FGLYQH7gftjc3ophBTeRA17sRmD7Y4QBInggsq
|
||||
Gv6tImPVBdekAjz/Ls/EyMwjAvvrL5eAokqrIsAarGo+zmbJKHzknw2KUz2En0+k
|
||||
YYaxB4oy9u7bzuQlvio6xYHJEb4K197bby4Dldmqv7YCCJBJwhOBAInMD687viKv
|
||||
vcUwL8YuS6cW5E8MbvEENlY4+lvKKj3M8Bnyb79cYIPQe92EuCwXU9DZXPRMLwwM
|
||||
oFEJpF5E/PmNJzu+B52ahHtDrh83WSx71fWqjdTqwkPZhAYo3ztsfFkb/UqUcq8u
|
||||
rBSebeUjZh0XZ9B04eshZQ5vJUcXGtYIe/77beV3Pv89/fw+zTZjpiP9Q3sZALzf
|
||||
Qt0YGp0/6qBuqR1tcqdu65AS2hun7yFw7uRavqYKvww4axRiz2do+xWmZFuoCAwD
|
||||
EWktaUujltpvAc1lo7lg4C6nByefJB9Xqk22N/vpqOsWr1NbAntT42Qj/HF9BVWR
|
||||
osvN3yMnKYWYe6oSTVnNBDM5obWAIHd3I9gcxTOTb1KsEwt2RrDs5EpB5ptS3Fjo
|
||||
JfBRhNZQ3cXttrIIhsHgDn9BDNg865/xpIgktKj0gEd60Abx0PqkAIm6IZTh4Efg
|
||||
7uZwfzxB+saOcddbrW2gNdzVZMC0s2Ye3sqHhtLbAJ3BlXYTxE4CAvTg54Ny+5hF
|
||||
IjvjlOKgXceSG1cSfk21/wyp9RY3Ft0AEYvvp0kZScWZaoA2aSFDUrchXVhgrEbn
|
||||
lJ7UptjefwRFIreAlwbKSbIDDNWnyzvIWyHfQ2aYqgnb7W7XqNPSgH9cALCfzirI
|
||||
dlRHjha0bMUtrjPCC/YfMXzJBVniy0gG6Pd5uC7vz/Awn6/6HRQVNaTQASphPBQ7
|
||||
bJuz+JTfzI9OUVCMRMdnb6b35U4P9tibFmnPvzTIPe+3WUmf8aRsLS3NN3G1Webd
|
||||
PMYVZpMycPaAI0Ht87axhsOzlxCWHYWjdHa+WoNNc1J90TxLCmAHquh5BDaWvjMK
|
||||
0DySftJZjV7Tf1p2KosmU83LRl39B5NHMbZb1xOEZl9IWwhT/PVKTVZ25xdxWLfb
|
||||
hF4l8rfvKehIp5r4t8zW1bvI2Hl6vrUvmcUVWt3BfKjxlgwRVD0vvwonMt1INesF
|
||||
204vUBeXbDsUUicLwOyUgaFvJ3XU3dOyvL9MhOgM5OgoFRRhG+4AS8a5JCD8iLtq
|
||||
-----END RSA PRIVATE KEY-----
|
||||
27
vendor/openssl/test/rsa.pem
vendored
Normal file
27
vendor/openssl/test/rsa.pem
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAofgWCuLjybRlzo0tZWJjNiuSfb4p4fAkd/wWJcyQoTbji9k0
|
||||
l8W26mPddxHmfHQp+Vaw+4qPCJrcS2mJPMEzP1Pt0Bm4d4QlL+yRT+SFd2lZS+pC
|
||||
gNMsD1W/YpRPEwOWvG6b32690r2jZ47soMZo9wGzjb/7OMg0LOL+bSf63kpaSHSX
|
||||
ndS5z5rexMdbBYUsLA9e+KXBdQOS+UTo7WTBEMa2R2CapHg665xsmtdVMTBQY4uD
|
||||
Zlxvb3qCo5ZwKh9kG4LT6/I5IhlJH7aGhyxXFvUK+DWNmoudF8NAco9/h9iaGNj8
|
||||
q2ethFkMLs91kzk2PAcDTW9gb54h4FRWyuXpoQIDAQABAoIBABKucaRpzQorw35S
|
||||
bEUAVx8dYXUdZOlJcHtiWQ+dC6V8ljxAHj/PLyzTveyI5QO/xkObCyjIL303l2cf
|
||||
UhPu2MFaJdjVzqACXuOrLot/eSFvxjvqVidTtAZExqFRJ9mylUVAoLvhowVWmC1O
|
||||
n95fZCXxTUtxNEG1Xcc7m0rtzJKs45J+N/V9DP1edYH6USyPSWGp6wuA+KgHRnKK
|
||||
Vf9GRx80JQY7nVNkL17eHoTWEwga+lwi0FEoW9Y7lDtWXYmKBWhUE+U8PGxlJf8f
|
||||
40493HDw1WRQ/aSLoS4QTp3rn7gYgeHEvfJdkkf0UMhlknlo53M09EFPdadQ4TlU
|
||||
bjqKc50CgYEA4BzEEOtIpmVdVEZNCqS7baC4crd0pqnRH/5IB3jw3bcxGn6QLvnE
|
||||
tfdUdiYrqBdss1l58BQ3KhooKeQTa9AB0Hw/Py5PJdTJNPY8cQn7ouZ2KKDcmnPG
|
||||
BY5t7yLc1QlQ5xHdwW1VhvKn+nXqhJTBgIPgtldC+KDV5z+y2XDwGUcCgYEAuQPE
|
||||
fgmVtjL0Uyyx88GZFF1fOunH3+7cepKmtH4pxhtCoHqpWmT8YAmZxaewHgHAjLYs
|
||||
p1ZSe7zFYHj7C6ul7TjeLQeZD/YwD66t62wDmpe/HlB+TnBA+njbglfIsRLtXlnD
|
||||
zQkv5dTltRJ11BKBBypeeF6689rjcJIDEz9RWdcCgYAHAp9XcCSrn8wVkMVkKdb7
|
||||
DOX4IKjzdahm+ctDAJN4O/y7OW5FKebvUjdAIt2GuoTZ71iTG+7F0F+lP88jtjP4
|
||||
U4qe7VHoewl4MKOfXZKTe+YCS1XbNvfgwJ3Ltyl1OH9hWvu2yza7q+d5PCsDzqtm
|
||||
27kxuvULVeya+TEdAB1ijQKBgQCH/3r6YrVH/uCWGy6bzV1nGNOdjKc9tmkfOJmN
|
||||
54dxdixdpozCQ6U4OxZrsj3FcOhHBsqAHvX2uuYjagqvo3cOj1TRqNocX40omfCC
|
||||
Mx3bD1yPPf/6TI2XECva/ggqEY2mYzmIiA5LVVmc5nrybr+lssFKneeyxN2Wq93S
|
||||
0iJMdQKBgCGHewxzoa1r8ZMD0LETNrToK423K377UCYqXfg5XMclbrjPbEC3YI1Z
|
||||
NqMtuhdBJqUnBi6tjKMF+34Xf0CUN8ncuXGO2CAYvO8PdyCixHX52ybaDjy1FtCE
|
||||
6yUXjoKNXKvUm7MWGsAYH6f4IegOetN5NvmUMFStCSkh7ixZLkN1
|
||||
-----END RSA PRIVATE KEY-----
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue