Compare commits

...

41 Commits

Author SHA1 Message Date
Andrew
bf47801a78 Merge branch 'andrew/update-actions-v4' into test/signal/v4.15.0 2025-03-10 11:13:32 -04:00
Andrew
6919e9765e Update to actions/cache@v4 2025-03-10 11:08:05 -04:00
Andrew
58ed4a72e2 Merge tag 'v4.15.0' into signal/v4.15.0 2025-03-07 23:45:24 -05:00
Andrew
615af5aafb Add history back from upstream so future merges apply cleanly 2024-12-04 22:14:22 -05:00
Andrew
1af143f509 Revert 12d00aa166
This reverts commit 12d00aa166.

We do not use this flag, so revert this commit to get back closer to upstream.
2024-12-04 18:48:37 -05:00
Andrew
f7b6f5dfa1 Merge upstream 4.13.0; resolve conflicts 2024-12-04 18:48:15 -05:00
Jordan Rose
3d4180b232 Skip bindgen 0.70's layout tests before Rust 1.77 2024-10-22 16:08:26 -07:00
Mike Aizatsky
889ad0f41e Update bindgen to 0.70.1
bindgen has had a lot of improvements since 0.68, and this newer version seems to able to compile libbssl from within edgeworker
2024-10-22 10:55:12 -07:00
Jordan Rose
59883d7e23 CI: Adjust CI branch to "main" instead of "master" and "libsignal" 2024-08-02 10:29:53 -07:00
Jordan Rose
fbea17998a Merge tag 'v4.9.0' into libsignal 2024-08-02 10:21:51 -07:00
Rushil Mehra
6c4a02f131 Actually Release 4.9.0 2024-08-02 01:49:23 -07:00
Jordan Rose
b9a75167dc Merge tag 'v4.6.0' into libsignal
chore: Release boring-sys version 4.6.0
2024-04-11 16:16:29 -07:00
Jordan Rose
7c88181568 boring-sys: Don't use CMake cross-compilation for macOS->iOS
(or macOS->macOS)
2023-11-10 16:34:06 -08:00
Jordan Rose
e17586365c Drop Android 19 feature flag, part 2 2023-11-10 16:09:32 -08:00
Jordan Rose
e8e6122545 Merge tag 'v4.0.0' into libsignal 2023-11-10 16:08:07 -08:00
Anthony Ramine
2f63b8affd Introduce struct Config in build script
Using a struct improves navigation of the build script,
as we can rely on rust-analyzer to help us check how
a feature flag or an environment variable is used,
as opposed to grepping for multiple env::var calls
or #[cfg] attributes.

This commit also removes some obsolete blocks of code
related to the now defunct ndk-old-gcc and fuzzing features.
2023-11-10 15:48:50 -08:00
Jordan Rose
7f4dca3405 Drop Android 19 feature flag 2023-11-10 15:48:50 -08:00
Chris Eager
8245063ae6 Update CI to build all matrix targets
This adds the matrix `--target` to relevant `cargo` commands. Some
targets are now “check-only”, which confirms cross-compilation succeeds,
without doing a full test run, because running these tests may require
emulation.

musl and MinGW have been dropped, because musl has no standard C++
setup, and MinGW isn’t a target for us.

All this requires some adjustments to boring-sys:

- Blocklist max_align_t in bindgen
   - https://github.com/rust-lang/rust-bindgen/issues/1823
- Don't check for MSVC with target_env
   - x86_64-pc-windows-gnu is identified as `target_env = "msvc"` too,
but doesn't use the Visual Studio CMake generator.
2023-10-18 15:50:51 -05:00
Anthony Ramine
8d4822be72 Fix clippy lints 2023-10-12 15:27:55 -07:00
Jordan Rose
02e4a3f9aa Merge upstream release 3.1.0 into libsignal branch 2023-10-12 15:19:22 -07:00
Jordan Rose
3c50b28a61 Remove Catalyst support 2023-10-10 16:14:12 -07:00
Jordan Rose
3809a7e1ca Update to a more recent BoringSSL 2023-05-08 16:39:30 -07:00
Jordan Rose
9534656269
Merge branch 'cloudflare:master' into libsignal 2023-05-08 15:29:47 -07:00
Lauren N. Liberda
bdf9d2ac06 upgrade bindgen build-dependency to 0.62.0
fixes build error on too new clang: https://github.com/cloudflare/boring/issues/109
2023-04-24 09:55:14 -07:00
Jordan Rose
25e1dd8fa5 boring-sys: Update Android NDK sysroot path
This longer path (inside the prebuilt toolchain included in the NDK)
has been the preferred sysroot since NDK r19. Newer NDKs no longer
have a top-level "sysroot" directory at all.
2022-11-30 15:32:47 -08:00
morph027
73ee9d7085 boring-sys: Add support for Linux ARM(v7)
Signed-off-by: morph027 <stefan.heitmueller@gmx.com>
2022-11-10 14:17:08 -08:00
Jordan Rose
81eeaab77a Merge remote-tracking branch 'origin/master' into libsignal 2022-11-10 14:16:43 -08:00
Jordan Rose
b95cb545b9 boring-sys: Add an android-api-19 feature for compat with Android 4.4 2022-08-22 12:40:38 -07:00
Jordan Rose
e1c719c096 boring-sys: Always treat macOS targets as a cross-compile, like iOS
This fixes actual cross-compile cases, like compiling for Apple
Silicon on an Intel Mac. It also makes builds more consistent by using
the SDK in the installed Xcode instead of the host root headers, which
is how Apple recommends people build anyway. (If you only have the
command line tools installed, though, it should fall back to those
without a problem.)
2022-07-29 17:42:43 -07:00
Jordan Rose
8a2d686286 boring: Expose PKey::private_key_to_der_pkcs8(_passphrase) 2022-07-28 16:28:31 -07:00
Jordan Rose
8e6f19aa9a boring-sys: Use the Android NDK sysroot when running bindgen 2022-07-25 15:04:01 -07:00
Jordan Rose
879ffef1b5 boring: Expose X509VerifyParamRef::set_time 2022-07-19 15:29:21 -07:00
Jordan Rose
a04d27b0c4 Put BoringSSL's SSL/TLS support behind a new feature 'ssl'
BoringSSL vends two libraries: libcrypto and libssl. Some clients
don't need the libssl part. With a feature flag, we can skip building
it (saving on compile time) and initializing it (saving on code size
and a tiny bit of run time).

The new feature is on by default for backwards compatibility.
2022-07-12 14:56:46 -07:00
Ravi Khadiwala
7451d82bb2 boring: use the right no_name value for oid_string 2022-07-05 14:57:27 -05:00
Chris Eager
b73043e51b boring: add Asn1Object::oid_string 2022-07-05 14:57:27 -05:00
Chris Eager
7afa7798cf boring: add X509Ref::extensions
This corresponds to `X509_get0_extensions`.
2022-07-05 14:57:27 -05:00
Ravi Khadiwala
29b7ed4cbd boring: add bindings to validate against CRLs
Adds CRL types and the ability to verify certificates against CRLs with
an X509StoreContext
2022-07-01 14:35:24 -05:00
Ravi Khadiwala
1e2df380d9 Enable CI on pushes to libsignal 2022-07-01 14:15:42 -05:00
Ravi Khadiwala
2dbdb97351 boring: Fix memory leak in Deriver 2022-07-01 12:30:42 -05:00
Jordan Rose
ea59de3542 Add minimal cross-compilation support for Windows and AArch64 Linux
Cross-compiling to AArch64 Linux can be done with a CMake toolchain
file, along with setting the correct compiler and include paths in the
environment.

Cross-compiling from X64 Windows to ARM64 Windows doesn't look at the
toolchain at all, because CMake + Visual Studio can already
cross-compile. Unfortunately, the Visual Studio CMake generator
doesn't set CMAKE_SYSTEM_PROCESSOR, which is what the BoringSSL
CMakeLists.txt is looking at to choose the architecture. For now,
disable the use of assembly when cross-compiling on Windows (assuming
that the Visual Studio generator will be used there).
2022-06-27 17:57:53 -07:00
Jordan Rose
ceb140105b Add support for Mac Catalyst (on Intel and Apple Silicon chips)
This is a Tier 3 target, but apart from working around a hardcoded
version in the 'cc' crate everything does work.
2022-06-16 12:30:46 -07:00
13 changed files with 1031 additions and 20 deletions

View File

@ -3,10 +3,10 @@ name: CI
on:
pull_request:
branches:
- master
- main
push:
branches:
- master
- main
env:
RUSTFLAGS: -Dwarnings
@ -36,7 +36,7 @@ jobs:
id: rust-version
run: echo "::set-output name=version::$(rustc --version)"
- name: Cache cargo index
uses: actions/cache@v1
uses: actions/cache@v4
with:
path: ~/.cargo/registry/index
key: index-${{ runner.os }}-${{ github.run_number }}
@ -45,14 +45,14 @@ jobs:
- name: Create lockfile
run: cargo generate-lockfile
- name: Cache cargo registry
uses: actions/cache@v1
uses: actions/cache@v4
with:
path: ~/.cargo/registry/cache
key: registry-${{ runner.os }}-${{ steps.rust-version.outputs.version }}-${{ hashFiles('Cargo.lock') }}
- name: Fetch dependencies
run: cargo fetch
- name: Cache target directory
uses: actions/cache@v1
uses: actions/cache@v4
with:
path: target
key: clippy-target-${{ runner.os }}-${{ steps.rust-version.outputs.version }}-${{ hashFiles('Cargo.lock') }}

View File

@ -572,26 +572,37 @@ impl Asn1ObjectRef {
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 {
/// Returns the numerical string OID of this object.
///
/// This corresponds to [`OBJ_obj2txt`] with `no_name = 1`.
///
/// [`OBJ_obj2txt`]: https://www.openssl.org/docs/man1.1.1/man3/OBJ_obj2txt.html
pub fn oid_string(&self) -> String {
self.to_text(true)
}
// To promote this to `pub`, the call-site parameter meaning ought to be clearer
fn to_text(&self, no_name: bool) -> String {
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,
no_name as c_int,
);
match str::from_utf8(&buf[..len as usize]) {
Err(_) => fmt.write_str("error"),
Ok(s) => fmt.write_str(s),
}
String::from_utf8_lossy(&buf[..len as usize]).into_owned()
}
}
}
impl fmt::Display for Asn1ObjectRef {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.write_str(&self.to_text(false))
}
}
impl fmt::Debug for Asn1ObjectRef {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
fmt.write_str(self.to_string().as_str())
@ -691,4 +702,13 @@ mod tests {
.map(|object| object.to_string())
.expect_err("parsing invalid OID should fail");
}
#[test]
fn object_to_text() {
let oid = "2.16.840.1.101.3.4.2.1";
let object = Asn1Object::from_str(oid).unwrap();
assert_eq!(object.to_text(false), Nid::SHA256.long_name().unwrap());
assert_eq!(object.to_text(true), oid.to_string());
assert_eq!(object.oid_string(), oid.to_string());
}
}

View File

@ -253,6 +253,16 @@ impl<T: Stackable> StackRef<T> {
}
}
impl<T> fmt::Debug for StackRef<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> Index<usize> for StackRef<T> {
type Output = T::Ref;

509
boring/src/x509/crl.rs Normal file
View File

@ -0,0 +1,509 @@
//! Certificate revocation lists describe certificates that have been revoked
//! by their issuer and should no longer be trusted.
//!
//! An `X509CRL` can be provided along with an issuing `X509` to verify that
//! issued certificates have not been revoked.
//!
//! # Example
//!
//! ```rust
//! use boring::hash::MessageDigest;
//! use boring::pkey::{PKey, Private};
//! use boring::x509::crl::{X509CRLBuilder, X509Revoked};
//! use boring::x509::extension::BasicConstraints;
//! use boring::x509::verify::X509VerifyFlags;
//! use boring::x509::X509Extension;
//! use boring::x509::X509;
//! use boring::x509::store::{X509Store, X509StoreBuilder};
//! use boring::asn1::Asn1Time;
//! use boring::bn::BigNum;
//! use boring::error::ErrorStack;
//!
//! fn crl_checking_store(issuer: X509, pkey: PKey<Private>) -> Result<X509Store, ErrorStack> {
//! let mut builder = X509CRLBuilder::new()?;
//! builder.set_issuer_name(issuer.subject_name())?;
//! builder.add_revoked(X509Revoked::from_parts(
//! &*BigNum::from_u32(1)?.to_asn1_integer()?,
//! &*Asn1Time::days_from_now(0)?
//! )?)?;
//! builder.set_last_update(&*Asn1Time::days_from_now(0)?)?;
//! builder.set_next_update(&*Asn1Time::days_from_now(30)?)?;
//! builder.sign(&pkey, MessageDigest::sha256())?;
//!
//! let mut store_builder = X509StoreBuilder::new()?;
//! store_builder.add_cert(issuer)?;
//! store_builder.add_crl(builder.build())?;
//! store_builder
//! .param_mut()
//! .set_flags(X509VerifyFlags::CRL_CHECK | X509VerifyFlags::CRL_CHECK_ALL);
//! Ok(store_builder.build())
//! }
//! ```
use crate::asn1::{Asn1BitStringRef, Asn1IntegerRef, Asn1TimeRef};
use crate::foreign_types::ForeignType;
use crate::foreign_types::ForeignTypeRef;
use crate::hash::{DigestBytes, MessageDigest};
use crate::pkey::{HasPrivate, HasPublic, PKeyRef};
use crate::stack::{StackRef, Stackable};
use crate::x509::X509ExtensionRef;
use crate::x509::{X509AlgorithmRef, X509Extension, X509NameRef};
use crate::{cvt, cvt_n, cvt_p, ErrorStack};
use std::convert::TryInto;
use std::fmt::Formatter;
use std::{fmt, mem, ptr};
foreign_type_and_impl_send_sync! {
type CType = ffi::X509_REVOKED;
fn drop = ffi::X509_REVOKED_free;
/// An `X509_REVOKED` containing information about a revoked certificate
pub struct X509Revoked;
}
impl Stackable for X509Revoked {
type StackType = ffi::stack_st_X509_REVOKED;
}
impl X509Revoked {
/// Create an `X509Revoked`
///
/// This corresponds to [`X509_REVOKED_new`] followed by calls to
/// [`X509_REVOKED_set_serialNumber`] and [`X509_REVOKED_set_revocationDate`]
/// with the provided parameters
///
/// [`X509_REVOKED_new`]: https://www.openssl.org/docs/man1.1.1/man3/X509_REVOKED_new.html
/// [`X509_REVOKED_set_serialNumber`]: https://www.openssl.org/docs/man1.1.1/man3/X509_REVOKED_set_serialNumber.html
/// [`X509_REVOKED_set_revocationDate`]: https://www.openssl.org/docs/man1.1.1/man3/X509_REVOKED_set_revocationDate.html
pub fn from_parts(
serial_number: &Asn1IntegerRef,
revocation_date: &Asn1TimeRef,
) -> Result<X509Revoked, ErrorStack> {
unsafe {
ffi::init();
let revoked = cvt_p(ffi::X509_REVOKED_new())?;
cvt(ffi::X509_REVOKED_set_serialNumber(
revoked,
serial_number.as_ptr(),
))?;
cvt(ffi::X509_REVOKED_set_revocationDate(
revoked,
revocation_date.as_ptr(),
))?;
Ok(X509Revoked::from_ptr(revoked))
}
}
}
impl X509RevokedRef {
/// Returns the serial number of the revoked certificate
///
/// This corresponds to [`X509_REVOKED_get0_serialNumber`].
///
/// [`X509_REVOKED_get0_serialNumber`]: https://www.openssl.org/docs/man1.1.1/man3/X509_REVOKED_get0_serialNumber.html
pub fn serial_number(&self) -> &Asn1IntegerRef {
unsafe {
let r = ffi::X509_REVOKED_get0_serialNumber(self.as_ptr());
assert!(!r.is_null());
Asn1IntegerRef::from_ptr(r as *mut _)
}
}
/// Returns certificate's revocation date
///
/// This corresponds to [`X509_REVOKED_get0_revocationDate`].
///
/// [`X509_REVOKED_get0_revocationDate`]: https://www.openssl.org/docs/man1.1.1/man3/X509_REVOKED_get0_revocationDate
pub fn revocation_date(&self) -> &Asn1TimeRef {
unsafe {
let date = ffi::X509_REVOKED_get0_revocationDate(self.as_ptr());
assert!(!date.is_null());
Asn1TimeRef::from_ptr(date as *mut _)
}
}
}
impl fmt::Debug for X509RevokedRef {
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
let sn = self.serial_number().to_bn().and_then(|bn| bn.to_hex_str());
let sn = sn.as_ref().map(|x| &***x).unwrap_or("");
fmt.debug_struct("X509Revoked")
.field("serial_number", &sn)
.field("revocation_date", self.revocation_date())
.finish()
}
}
foreign_type_and_impl_send_sync! {
type CType = ffi::X509_CRL;
fn drop = ffi::X509_CRL_free;
/// An `X509CRL` certificate revocation list
pub struct X509CRL;
}
impl Stackable for X509CRL {
type StackType = ffi::stack_st_X509_CRL;
}
impl X509CRL {
from_pem! {
/// Deserializes a PEM-encoded X509CRL structure.
///
/// The input should have a header of `-----BEGIN X509 CRL-----`
///
/// This corresponds to [`PEM_read_bio_X509_CRL`].
///
/// [`PEM_read_bio_X509_CRL`]: https://www.openssl.org/docs/man1.1.1/man3/PEM_read_bio_X509_CRL
from_pem,
X509CRL,
ffi::PEM_read_bio_X509_CRL
}
from_der! {
/// Deserializes a DER-encoded X509 structure.
///
/// This corresponds to [`d2i_X509_CRL`].
///
/// [`d2i_X509_CRL`]: https://www.openssl.org/docs/man1.1.1/man3/d2i_X509_CRL.html
from_der,
X509CRL,
ffi::d2i_X509_CRL,
::libc::c_long
}
}
impl X509CRLRef {
/// Returns the CRL's last update time
///
/// This corresponds to [`X509_CRL_get0_lastUpdate`]
///
/// [`X509_CRL_get0_lastUpdate`]: https://www.openssl.org/docs/man1.1.1/man3/X509_CRL_get0_lastUpdate
pub fn last_update(&self) -> Option<&Asn1TimeRef> {
unsafe {
let date = ffi::X509_CRL_get0_lastUpdate(self.as_ptr());
if date.is_null() {
None
} else {
Some(Asn1TimeRef::from_ptr(date as *mut _))
}
}
}
/// Returns the CRL's next update time
///
/// This corresponds to [`X509_CRL_get0_nextUpdate`]
///
/// [`X509_CRL_get0_nextUpdate`]: https://www.openssl.org/docs/man1.1.1/man3/X509_CRL_get0_nextUpdate
pub fn next_update(&self) -> Option<&Asn1TimeRef> {
unsafe {
let date = ffi::X509_CRL_get0_nextUpdate(self.as_ptr());
if date.is_null() {
None
} else {
Some(Asn1TimeRef::from_ptr(date as *mut _))
}
}
}
/// Returns the CRL's issuer name
///
/// This corresponds to [`X509_CRL_get_issuer`]
///
/// [`X509_CRL_get_issuer`]: https://www.openssl.org/docs/man1.1.1/man3/X509_CRL_get_issuer
pub fn issuer(&self) -> &X509NameRef {
unsafe {
let name = ffi::X509_CRL_get_issuer(self.as_ptr());
assert!(!name.is_null());
X509NameRef::from_ptr(name)
}
}
/// Returns the CRL's extensions
///
/// This corresponds to [`X509_CRL_get0_extensions`]
///
/// [`X509_CRL_get0_extensions`]: https://www.openssl.org/docs/man1.1.1/man3/X509_CRL_get0_extensions
pub fn extensions(&self) -> Option<&StackRef<X509Extension>> {
unsafe {
let extensions = ffi::X509_CRL_get0_extensions(self.as_ptr());
if extensions.is_null() {
None
} else {
Some(StackRef::from_ptr(extensions as *mut _))
}
}
}
/// Returns the revoked certificates in this CRL
///
/// This corresponds to [`X509_CRL_get_REVOKED`]
///
/// [`X509_CRL_get_REVOKED`]: https://www.openssl.org/docs/man1.1.1/man3/X509_CRL_get_REVOKED
pub fn revoked(&self) -> Option<&StackRef<X509Revoked>> {
unsafe {
let revoked = ffi::X509_CRL_get_REVOKED(self.as_ptr());
if revoked.is_null() {
None
} else {
Some(StackRef::from_ptr(revoked))
}
}
}
/// Returns the CRL's signature and signature algorithm
///
/// This corresponds to [`X509_CRL_get0_signature`]
///
/// [`X509_CRL_get0_signature`]: https://www.openssl.org/docs/man1.1.1/man3/X509_CRL_get0_signature
pub fn signature(&self) -> (&Asn1BitStringRef, &X509AlgorithmRef) {
unsafe {
let mut signature = ptr::null();
let mut algor = ptr::null();
ffi::X509_CRL_get0_signature(self.as_ptr(), &mut signature, &mut algor);
assert!(!algor.is_null());
assert!(!signature.is_null());
(
Asn1BitStringRef::from_ptr(signature as *mut _),
X509AlgorithmRef::from_ptr(algor as *mut _),
)
}
}
/// Returns a digest of the DER representation of the CRL
///
/// This corresponds to [`X509_CRL_digest`]
///
/// [`X509_CRL_digest`]: https://www.openssl.org/docs/man1.1.1/man3/X509_CRL_digest
pub fn digest(&self, hash_type: MessageDigest) -> Result<DigestBytes, ErrorStack> {
unsafe {
let mut digest = DigestBytes {
buf: [0; ffi::EVP_MAX_MD_SIZE as usize],
len: ffi::EVP_MAX_MD_SIZE as usize,
};
let mut len = ffi::EVP_MAX_MD_SIZE.try_into().unwrap();
cvt(ffi::X509_CRL_digest(
self.as_ptr(),
hash_type.as_ptr(),
digest.buf.as_mut_ptr() as *mut _,
&mut len,
))?;
digest.len = len as usize;
Ok(digest)
}
}
/// Check if the CRL is signed using the given public key.
///
/// Only the signature is checked: no other checks (such as certificate chain validity)
/// are performed.
///
/// Returns `true` if verification succeeds.
///
/// This corresponds to [`X509_CRL_verify"].
///
/// [`X509_CRL_verify`]: https://www.openssl.org/docs/man1.1.1/man3/X509_CRL_verify
pub fn verify<T>(&self, key: &PKeyRef<T>) -> Result<bool, ErrorStack>
where
T: HasPublic,
{
unsafe { cvt_n(ffi::X509_CRL_verify(self.as_ptr(), key.as_ptr())).map(|n| n != 0) }
}
to_pem! {
/// Serializes the CRL into a PEM-encoded X509 CRL structure.
///
/// The output will have a header of `-----BEGIN X509 CRL-----`
///
/// This corresponds to [`PEM_write_bio_X509_CRL`]
///
/// [`PEM_write_bio_X509_CRL`]: https://www.openssl.org/docs/man1.1.1/man3/PEM_write_bio_X509_CRL
to_pem,
ffi::PEM_write_bio_X509_CRL
}
to_der! {
/// Serializes the CRL into a DER-encoded X509 CRL structure
///
/// This corresponds to `i2d_X509_CRL`
///
/// [`i2d_X509_CRL`]: https://www.openssl.org/docs/man1.1.1/man3/i2d_X509_CRL
to_der,
ffi::i2d_X509_CRL
}
}
impl ToOwned for X509CRLRef {
type Owned = X509CRL;
fn to_owned(&self) -> X509CRL {
unsafe {
ffi::X509_CRL_up_ref(self.as_ptr());
X509CRL::from_ptr(self.as_ptr())
}
}
}
impl Clone for X509CRL {
fn clone(&self) -> X509CRL {
X509CRLRef::to_owned(self)
}
}
impl fmt::Debug for X509CRLRef {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
let mut debug_struct = formatter.debug_struct("X509CRL");
debug_struct.field("issuer", self.issuer());
debug_struct.field("signature_algorithm", &self.signature().1.object());
if let Some(next_update) = self.next_update() {
debug_struct.field("next_update", next_update);
}
if let Some(last_update) = self.last_update() {
debug_struct.field("last_update", last_update);
}
if let Some(revoked) = self.revoked() {
debug_struct.field("revoked", &revoked);
}
if let Some(extensions) = self.extensions() {
debug_struct.field("extensions", &extensions);
}
debug_struct.finish()
}
}
impl fmt::Debug for X509CRL {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
let x: &X509CRLRef = self;
x.fmt(formatter)
}
}
/// A builder used to construct an `X509CRL`
pub struct X509CRLBuilder(X509CRL);
impl X509CRLBuilder {
/// Creates a new builder.
pub fn new() -> Result<X509CRLBuilder, ErrorStack> {
unsafe {
ffi::init();
cvt_p(ffi::X509_CRL_new()).map(|p| X509CRLBuilder(X509CRL::from_ptr(p)))
}
}
/// Append an `X509Extension` to the certificate revocation list
///
/// This corresponds to [`X509_CRL_add_ext`]
///
/// [`X509_CRL_add_ext`]: https://www.openssl.org/docs/man1.1.1/man3/X509_CRL_add_ext
pub fn append_extension(&mut self, extension: &X509ExtensionRef) -> Result<(), ErrorStack> {
unsafe {
// -1 indicates append to end
cvt(ffi::X509_CRL_add_ext(
self.0.as_ptr(),
extension.as_ptr(),
-1,
))?;
Ok(())
}
}
/// Signs the certificate revocation list with a private key.
///
/// This corresponds to [`X509_CRL_sign`]
///
/// [`X509_CRL_sign`]: https://www.openssl.org/docs/man1.1.1/man3/X509_CRL_sign
pub fn sign<T>(&mut self, key: &PKeyRef<T>, hash: MessageDigest) -> Result<(), ErrorStack>
where
T: HasPrivate,
{
unsafe {
cvt(ffi::X509_CRL_sign(
self.0.as_ptr(),
key.as_ptr(),
hash.as_ptr(),
))
.map(|_| ())
}
}
/// Add a revoked certificate to the certificate revocation list
///
/// This corresponds to [`X509_CRL_add0_revoked`]
///
/// [`X509_CRL_add0_revoked`]: https://www.openssl.org/docs/man1.1.1/man3/X509_CRL_add0_revoked
pub fn add_revoked(&mut self, revoked: X509Revoked) -> Result<(), ErrorStack> {
unsafe {
cvt(ffi::X509_CRL_add0_revoked(
self.0.as_ptr(),
revoked.as_ptr(),
))?;
mem::forget(revoked);
Ok(())
}
}
/// Sets the issuer name of the certificate revocation list.
///
/// This corresponds to [`X509_CRL_set_issuer_name`]
///
/// [`X509_CRL_set_issuer_name`]: https://www.openssl.org/docs/man1.1.1/man3/X509_CRL_set_issuer_name
pub fn set_issuer_name(&mut self, issuer_name: &X509NameRef) -> Result<(), ErrorStack> {
unsafe {
cvt(ffi::X509_CRL_set_issuer_name(
self.0.as_ptr(),
issuer_name.as_ptr(),
))
.map(|_| ())
}
}
/// Sets the version of the certificate revocation list.
///
/// Note that the version is zero-indexed; that is, a certificate corresponding to version 3 of
/// the X.509 standard should pass `2` to this method.
///
/// This corresponds to [`X509_CRL_set_version`]
///
/// [`X509_CRL_set_version`]: https://www.openssl.org/docs/man1.1.1/man3/X509_CRL_set_version
pub fn set_version(&mut self, version: i32) -> Result<(), ErrorStack> {
unsafe { cvt(ffi::X509_CRL_set_version(self.0.as_ptr(), version.into())).map(|_| ()) }
}
/// Sets the last update time on the certificate revocation list.
///
/// This corresponds to [`X509_CRL_set1_lastUpdate`]
///
/// [`X509_CRL_set1_lastUpdate`]: https://www.openssl.org/docs/man1.1.1/man3/X509_CRL_set1_lastUpdate
pub fn set_last_update(&mut self, last_update: &Asn1TimeRef) -> Result<(), ErrorStack> {
unsafe {
cvt(ffi::X509_CRL_set1_lastUpdate(
self.0.as_ptr(),
last_update.as_ptr(),
))
.map(|_| ())
}
}
/// Sets the next update time on the certificate revocation list.
///
/// This corresponds to [`X509_CRL_set1_nextUpdate`]
///
/// [`X509_CRL_set1_nextUpdate`]: https://www.openssl.org/docs/man1.1.1/man3/X509_CRL_set1_nextUpdate
pub fn set_next_update(&mut self, next_update: &Asn1TimeRef) -> Result<(), ErrorStack> {
unsafe {
cvt(ffi::X509_CRL_set1_nextUpdate(
self.0.as_ptr(),
next_update.as_ptr(),
))
.map(|_| ())
}
}
/// Consumes the builder, returning the certificate revocation list
pub fn build(self) -> X509CRL {
self.0
}
}

View File

@ -38,9 +38,11 @@ use crate::ssl::SslRef;
use crate::stack::{Stack, StackRef, Stackable};
use crate::string::OpensslString;
use crate::util::ForeignTypeRefExt;
use crate::x509::crl::X509CRL;
use crate::x509::verify::X509VerifyParamRef;
use crate::{cvt, cvt_n, cvt_p};
pub mod crl;
pub mod extension;
pub mod store;
pub mod verify;
@ -159,6 +161,32 @@ impl X509StoreContextRef {
unsafe { cvt_n(ffi::X509_verify_cert(self.as_ptr())).map(|n| n != 0) }
}
/// Verifies the stored certificate with additional untrusted CRLs
///
/// Returns `true` if verification succeeds. The `error` method will return the specific
/// validation error if the certificate was not valid.
///
/// This will only work inside of a call to `init`.
///
/// This corresponds to [`X509_STORE_CTX_set0_crls`] followed by [`X509_verify_cert`].
///
/// [`X509_STORE_CTX_set0_crls`]: https://www.openssl.org/docs/man1.0.2/crypto/X509_STORE_CTX_set0_crls.html
/// [`X509_verify_cert`]: https://www.openssl.org/docs/man1.0.2/crypto/X509_verify_cert.html
pub fn verify_cert_with_crls(
&mut self,
untrusted_crls: Stack<X509CRL>,
) -> Result<bool, ErrorStack> {
unsafe {
ffi::X509_STORE_CTX_set0_crls(self.as_ptr(), untrusted_crls.as_ptr());
let res = cvt_n(ffi::X509_verify_cert(self.as_ptr())).map(|n| n != 0);
// set0_crls does not take ownership of the stack, so we'll drop and free
// untrusted_crls after this method. null out the crls in ctx to make sure
// no one has a reference to it.
ffi::X509_STORE_CTX_set0_crls(self.as_ptr(), ptr::null_mut());
res
}
}
/// Set the verify result of the context.
#[corresponds(X509_STORE_CTX_set_error)]
pub fn set_error(&mut self, result: X509VerifyResult) {
@ -576,6 +604,21 @@ impl X509Ref {
}
}
/// Returns the extensions of the certificate.
///
/// This corresponds to [`X509_get0_extensions`].
///
/// [`X509_get0_extensions`]: https://www.openssl.org/docs/man1.1.1/man3/X509_get0_extensions.html
pub fn extensions(&self) -> Option<&StackRef<X509Extension>> {
unsafe {
let stack = ffi::X509_get0_extensions(self.as_ptr());
if stack.is_null() {
return None;
}
Some(StackRef::from_ptr(stack as *mut _))
}
}
pub fn check_host(&self, host: &str) -> Result<bool, ErrorStack> {
unsafe {
cvt_n(ffi::X509_check_host(
@ -851,6 +894,47 @@ impl X509ExtensionRef {
}
}
impl X509ExtensionRef {
/// Returns whether this extension is critical
///
/// This corresponds to [`X509_EXTENSION_get_critical`].
///
/// [`X509_EXTENSION_get_critical`]: https://www.openssl.org/docs/man1.1.1/man3/X509_EXTENSION_get_critical
pub fn critical(&self) -> bool {
unsafe { ffi::X509_EXTENSION_get_critical(self.as_ptr()) != 0 }
}
/// Returns the `Asn1Object` of this `X509Extension`
///
/// This can be used to determine the `Nid` of this extension
///
/// This corresponds to [`X509_EXTENSION_get_object`].
///
/// [`X509_EXTENSION_get_object`]: https://www.openssl.org/docs/man1.1.1/man3/X509_EXTENSION_get_object
pub fn object(&self) -> &Asn1ObjectRef {
unsafe { Asn1ObjectRef::from_ptr(ffi::X509_EXTENSION_get_object(self.as_ptr())) }
}
/// Returns the `data` of this `X509Extension`
///
/// This corresponds to [`X509_EXTENSION_get_data`].
///
/// [`X509_EXTENSION_get_data`]: https://www.openssl.org/docs/man1.1.1/man3/X509_EXTENSION_get_data
pub fn data(&self) -> &Asn1StringRef {
unsafe { Asn1StringRef::from_ptr(ffi::X509_EXTENSION_get_data(self.as_ptr())) }
}
}
impl fmt::Debug for X509ExtensionRef {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter
.debug_struct("X509Extension")
.field("critical", &self.critical())
.field("object_nid", &self.object())
.finish()
}
}
/// A builder used to construct an `X509Name`.
pub struct X509NameBuilder(X509Name);

View File

@ -43,6 +43,7 @@
use crate::error::ErrorStack;
use crate::ffi;
use crate::stack::StackRef;
use crate::x509::crl::X509CRL;
use crate::x509::verify::{X509VerifyFlags, X509VerifyParamRef};
use crate::x509::{X509Object, X509};
use crate::{cvt, cvt_p};
@ -86,6 +87,24 @@ impl X509StoreBuilderRef {
unsafe { cvt(ffi::X509_STORE_add_cert(self.as_ptr(), cert.as_ptr())).map(|_| ()) }
}
/// Adds a CRL to the certificate store.
///
/// This corresponds to [`X509_STORE_add_crl`].
///
/// [`X509_STORE_add_crl`]: https://www.openssl.org/docs/man1.1.1/man3/X509_STORE_add_crl
pub fn add_crl(&mut self, crl: X509CRL) -> Result<(), ErrorStack> {
unsafe { cvt(ffi::X509_STORE_add_crl(self.as_ptr(), crl.as_ptr())).map(|_| ()) }
}
/// Returns a mutable reference to the X509 verification configuration.
///
/// This corresponds to [`X509_STORE_get0_param`].
///
/// [`X509_STORE_add_crl`]: https://www.openssl.org/docs/man1.1.1/man3/X509_STORE_get0_param
pub fn param_mut(&mut self) -> &mut X509VerifyParamRef {
unsafe { X509VerifyParamRef::from_ptr_mut(ffi::X509_STORE_get0_param(self.as_ptr())) }
}
/// Load certificates from their default locations.
///
/// These locations are read from the `SSL_CERT_FILE` and `SSL_CERT_DIR`

View File

@ -6,13 +6,15 @@ use crate::hash::MessageDigest;
use crate::nid::Nid;
use crate::pkey::{PKey, Private};
use crate::rsa::Rsa;
use crate::stack::Stack;
use crate::stack::{Stack, Stackable};
use crate::x509::crl::{X509CRLBuilder, X509Revoked, X509CRL};
use crate::x509::extension::{
AuthorityKeyIdentifier, BasicConstraints, ExtendedKeyUsage, KeyUsage, SubjectAlternativeName,
SubjectKeyIdentifier,
};
use crate::x509::store::X509StoreBuilder;
use crate::x509::{X509Extension, X509Name, X509Req, X509StoreContext, X509};
use crate::x509::verify::X509VerifyFlags;
use crate::x509::{X509Extension, X509Name, X509Req, X509StoreContext, X509VerifyError, X509};
mod trusted_first;
@ -21,6 +23,15 @@ fn pkey() -> PKey<Private> {
PKey::from_rsa(rsa).unwrap()
}
fn stack_of<T>(item: T) -> Stack<T>
where
T: Stackable,
{
let mut stack = Stack::new().expect("unable to initialize stack");
stack.push(item).expect("failed to add to stack");
stack
}
#[test]
fn test_cert_loading() {
let cert = include_bytes!("../../../test/cert.pem");
@ -285,6 +296,7 @@ fn x509_builder() {
assert!(pkey.public_eq(&x509.public_key().unwrap()));
assert!(x509.verify(&pkey).unwrap());
assert_eq!(x509.extensions().unwrap().len(), 6);
let cn = x509
.subject_name()
@ -295,6 +307,48 @@ fn x509_builder() {
assert_eq!(serial, x509.serial_number().to_bn().unwrap());
}
#[test]
fn x509_crl_builder() {
let mut builder = X509CRLBuilder::new().unwrap();
let mut name = X509Name::builder().unwrap();
name.append_entry_by_nid(Nid::COMMONNAME, "foobar.com")
.unwrap();
let name = name.build();
builder.set_issuer_name(&name).unwrap();
let mut serial = BigNum::new().unwrap();
serial.rand(128, MsbOption::MAYBE_ZERO, false).unwrap();
let serial_asn = serial.to_asn1_integer().unwrap();
let revoked =
X509Revoked::from_parts(&serial_asn, &Asn1Time::days_from_now(0).unwrap()).unwrap();
builder.add_revoked(revoked).unwrap();
builder
.set_last_update(&Asn1Time::days_from_now(0).unwrap())
.unwrap();
builder
.set_next_update(&Asn1Time::days_from_now(30).unwrap())
.unwrap();
let pkey = pkey();
builder.sign(&pkey, MessageDigest::sha256()).unwrap();
let crl = builder.build();
let cn = crl.issuer().entries_by_nid(Nid::COMMONNAME).next().unwrap();
assert_eq!(cn.data().as_slice(), b"foobar.com");
let revoked_sn = crl
.revoked()
.unwrap()
.iter()
.next()
.unwrap()
.serial_number();
assert_eq!(serial, revoked_sn.to_bn().unwrap());
assert!(crl.verify(&pkey).unwrap());
}
#[test]
fn x509_extension_new() {
assert!(X509Extension::new(None, None, "crlDistributionPoints", "section").is_err());
@ -479,6 +533,275 @@ fn test_verify_fails() {
.unwrap());
}
#[test]
fn test_verify_revoked() {
let cert = include_bytes!("../../../test/cert.pem");
let cert = X509::from_pem(cert).unwrap();
let ca = include_bytes!("../../../test/root-ca.pem");
let ca = X509::from_pem(ca).unwrap();
let crl = include_bytes!("../../../test/crl.pem");
let crl = X509CRL::from_pem(crl).unwrap();
let chain = Stack::new().unwrap();
let mut store_bldr = X509StoreBuilder::new().unwrap();
store_bldr.add_cert(ca).unwrap();
store_bldr.add_crl(crl).unwrap();
store_bldr
.param_mut()
.set_flags(X509VerifyFlags::CRL_CHECK | X509VerifyFlags::CRL_CHECK_ALL);
let store = store_bldr.build();
let mut context = X509StoreContext::new().unwrap();
assert!(!context
.init(&store, &cert, &chain, |c| c.verify_cert())
.unwrap());
}
#[test]
fn test_crl_signature() {
let ca = include_bytes!("../../../test/root-ca.pem");
let ca = X509::from_pem(ca).unwrap();
let crl = include_bytes!("../../../test/bad_sig.pem");
let crl = X509CRL::from_pem(crl).unwrap();
assert!(!crl.verify(&ca.public_key().unwrap()).unwrap());
let crl = include_bytes!("../../../test/crl.pem");
let crl = X509CRL::from_pem(crl).unwrap();
assert!(crl.verify(&ca.public_key().unwrap()).unwrap());
}
#[test]
fn test_untrusted_valid_crl() {
let cert = include_bytes!("../../../test/cert.pem");
let cert = X509::from_pem(cert).unwrap();
let ca = include_bytes!("../../../test/root-ca.pem");
let ca = X509::from_pem(ca).unwrap();
let chain = Stack::new().unwrap();
let mut store_bldr = X509StoreBuilder::new().unwrap();
store_bldr.add_cert(ca).unwrap();
store_bldr
.param_mut()
.set_flags(X509VerifyFlags::CRL_CHECK | X509VerifyFlags::CRL_CHECK_ALL);
store_bldr.param_mut().set_time(1656633600); // 2022-07-01, everything is valid
let store = store_bldr.build();
// cert is not revoked
let crl = include_bytes!("../../../test/empty_crl.pem");
let crl = X509CRL::from_pem(crl).unwrap();
let mut context = X509StoreContext::new().unwrap();
assert!(context
.init(&store, &cert, &chain, |c| c
.verify_cert_with_crls(stack_of(crl)))
.unwrap());
// cert is revoked
let crl = include_bytes!("../../../test/crl.pem");
let crl = X509CRL::from_pem(crl).unwrap();
let mut context = X509StoreContext::new().unwrap();
assert!(!context
.init(&store, &cert, &chain, |c| c
.verify_cert_with_crls(stack_of(crl)))
.unwrap());
assert_eq!(context.verify_result(), Err(X509VerifyError::CERT_REVOKED));
}
#[test]
fn test_untrusted_invalid_crl() {
let cert = include_bytes!("../../../test/cert.pem");
let cert = X509::from_pem(cert).unwrap();
let ca = include_bytes!("../../../test/root-ca.pem");
let ca = X509::from_pem(ca).unwrap();
let chain = Stack::new().unwrap();
let mut store_bldr = X509StoreBuilder::new().unwrap();
store_bldr.add_cert(ca).unwrap();
store_bldr
.param_mut()
.set_flags(X509VerifyFlags::CRL_CHECK | X509VerifyFlags::CRL_CHECK_ALL);
store_bldr.param_mut().set_time(1656633600); // 2022-07-01, everything is valid
let store = store_bldr.build();
// this CRL was issued by a different CA (not in the trusted store)
let crl = include_bytes!("../../../test/invalid_crl.pem");
let crl = X509CRL::from_pem(crl).unwrap();
let mut context = X509StoreContext::new().unwrap();
assert!(!context
.init(&store, &cert, &chain, |c| c
.verify_cert_with_crls(stack_of(crl)))
.unwrap());
assert_eq!(
context.verify_result(),
Err(X509VerifyError::UNABLE_TO_GET_CRL)
);
// this CRL has an invalid signature
let crl = include_bytes!("../../../test/bad_sig.pem");
let crl = X509CRL::from_pem(crl).unwrap();
let mut context = X509StoreContext::new().unwrap();
assert!(!context
.init(&store, &cert, &chain, |c| c
.verify_cert_with_crls(stack_of(crl)))
.unwrap());
assert_eq!(
context.verify_result(),
Err(X509VerifyError::CRL_SIGNATURE_FAILURE)
);
}
#[test]
fn test_revoked_serial_numbers() {
let cert = include_bytes!("../../../test/cert.pem");
let cert = X509::from_pem(cert).unwrap();
let cert_sn = cert.serial_number().to_bn().unwrap();
let crl = include_bytes!("../../../test/crl.pem");
let crl = X509CRL::from_pem(crl).unwrap();
assert_eq!(
crl.revoked()
.unwrap()
.iter()
.filter(|revoked| revoked.serial_number().to_bn().unwrap() == cert_sn)
.count(),
1
);
}
#[test]
fn test_serialize_crl() {
let crl = include_bytes!("../../../test/crl.pem");
let crl = X509CRL::from_pem(crl).unwrap();
let digest = hex::encode(crl.digest(MessageDigest::sha1()).unwrap());
let serialized = crl.to_pem().unwrap();
let crl_deserialized = X509CRL::from_pem(&serialized).unwrap();
let new_digest = crl_deserialized.digest(MessageDigest::sha1()).unwrap();
assert_eq!(digest, hex::encode(new_digest));
}
#[test]
fn test_crl_extensions() {
let crl = include_bytes!("../../../test/crl.pem");
let crl = X509CRL::from_pem(crl).unwrap();
let extensions = crl.extensions();
assert_eq!(
extensions
.unwrap()
.iter()
.filter(|ext| ext.object().nid() == Nid::AUTHORITY_KEY_IDENTIFIER)
.count(),
1
);
assert_eq!(
extensions
.unwrap()
.iter()
.filter(|ext| ext.object().nid() == Nid::CRL_NUMBER)
.count(),
1
);
}
#[test]
fn test_debug_crl() {
let crl = include_bytes!("../../../test/crl.pem");
let crl = X509CRL::from_pem(crl).unwrap();
let debugged = format!("{:#?}", crl);
assert!(debugged.contains(r#"countryName = "AU""#));
assert!(debugged.contains(r#"stateOrProvinceName = "Some-State""#));
assert!(debugged.contains(r#"organizationName = "Internet Widgits Pty Ltd""#));
assert!(debugged.contains(r#"last_update: Jun 21 20:22:02 2022 GMT"#));
assert!(debugged.contains(r#"next_update: Jun 18 20:22:02 2032 GMT"#));
assert!(debugged.contains(r#"revocation_date: Jun 21 20:21:55 2022 GMT"#));
assert!(debugged.contains(r#"serial_number: "8771f7bdee982fa5""#));
assert!(debugged.contains(r#"object_nid: X509v3 Authority Key Identifier"#));
assert!(debugged.contains(r#"object_nid: X509v3 CRL Number"#));
}
#[test]
fn test_custom_time_valid() {
let cert = include_bytes!("../../../test/cert.pem");
let cert = X509::from_pem(cert).unwrap();
let ca = include_bytes!("../../../test/root-ca.pem");
let ca = X509::from_pem(ca).unwrap();
let chain = Stack::new().unwrap();
let mut store_bldr = X509StoreBuilder::new().unwrap();
store_bldr.add_cert(ca).unwrap();
store_bldr.param_mut().set_time(1656633600); // 2022-07-01, everything is valid
let store = store_bldr.build();
let mut context = X509StoreContext::new().unwrap();
assert!(context
.init(&store, &cert, &chain, |c| c.verify_cert())
.unwrap());
}
#[test]
fn test_custom_time_expired() {
let cert = include_bytes!("../../../test/cert.pem");
let cert = X509::from_pem(cert).unwrap();
let ca = include_bytes!("../../../test/root-ca.pem");
let ca = X509::from_pem(ca).unwrap();
let chain = Stack::new().unwrap();
let mut store_bldr = X509StoreBuilder::new().unwrap();
store_bldr.add_cert(ca).unwrap();
store_bldr.param_mut().set_time(1786838400); // 2026-08-16, after the root and leaf expiration
let store = store_bldr.build();
let mut context = X509StoreContext::new().unwrap();
assert!(!context
.init(&store, &cert, &chain, |c| c.verify_cert())
.unwrap());
}
#[test]
fn test_custom_time_too_soon() {
let cert = include_bytes!("../../../test/cert.pem");
let cert = X509::from_pem(cert).unwrap();
let ca = include_bytes!("../../../test/root-ca.pem");
let ca = X509::from_pem(ca).unwrap();
let chain = Stack::new().unwrap();
let mut store_bldr = X509StoreBuilder::new().unwrap();
store_bldr.add_cert(ca).unwrap();
store_bldr.param_mut().set_time(1262304000); // 2010-01-01, before the root and leaf issuance
let store = store_bldr.build();
let mut context = X509StoreContext::new().unwrap();
assert!(!context
.init(&store, &cert, &chain, |c| c.verify_cert())
.unwrap());
}
#[test]
fn test_custom_time_crl() {
let cert = include_bytes!("../../../test/cert.pem");
let cert = X509::from_pem(cert).unwrap();
let ca = include_bytes!("../../../test/root-ca.pem");
let ca = X509::from_pem(ca).unwrap();
let crl = include_bytes!("../../../test/crl.pem");
let crl = X509CRL::from_pem(crl).unwrap();
let chain = Stack::new().unwrap();
let mut store_bldr = X509StoreBuilder::new().unwrap();
store_bldr.add_cert(ca).unwrap();
store_bldr
.param_mut()
.set_flags(X509VerifyFlags::CRL_CHECK | X509VerifyFlags::CRL_CHECK_ALL);
store_bldr.param_mut().set_time(1640995200); // 2022-01-01, before the CRL's issue date
let store = store_bldr.build();
let mut context = X509StoreContext::new().unwrap();
assert!(!context
.init(&store, &cert, &chain, |c| c
.verify_cert_with_crls(stack_of(crl)))
.unwrap());
}
#[test]
fn test_save_subject_der() {
let cert = include_bytes!("../../../test/cert.pem");

View File

@ -2,7 +2,7 @@
use crate::stack::Stack;
use crate::x509::store::X509StoreBuilder;
use crate::x509::verify::{X509Flags, X509VerifyParamRef};
use crate::x509::verify::{X509VerifyFlags, X509VerifyParamRef};
use crate::x509::{X509Ref, X509StoreContext, X509VerifyError, X509VerifyResult, X509};
#[test]
@ -43,7 +43,7 @@ fn test_verify_cert() {
&leaf,
&[&root1, &root2],
&[&intermediate, &root1_cross],
|param| param.set_flags(X509Flags::TRUSTED_FIRST),
|param| param.set_flags(X509VerifyFlags::TRUSTED_FIRST),
)
);
@ -53,14 +53,14 @@ fn test_verify_cert() {
&leaf,
&[&root1, &root2],
&[&intermediate, &root1_cross],
|param| param.clear_flags(X509Flags::TRUSTED_FIRST),
|param| param.clear_flags(X509VerifyFlags::TRUSTED_FIRST),
)
);
assert_eq!(
Ok(()),
verify(&leaf, &[&root1], &[&intermediate, &root1_cross], |param| {
param.clear_flags(X509Flags::TRUSTED_FIRST)
param.clear_flags(X509VerifyFlags::TRUSTED_FIRST)
},)
);
}

View File

@ -31,7 +31,7 @@ bitflags! {
pub use X509VerifyFlags as X509Flags;
bitflags! {
/// Flags used to check an `X509` certificate.
/// Flags used to configure verification of an `X509` certificate
#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct X509VerifyFlags: c_ulong {

11
boring/test/bad_sig.pem Normal file
View File

@ -0,0 +1,11 @@
-----BEGIN X509 CRL-----
MIIBqTCBkjANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJBVTETMBEGA1UECAwK
U29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkFw0y
MjA2MTYyMjQ0NDFaFw0yMzA2MTYyMjQ0NDFaMBwwGgIJAIdx973umC+lFw0yMjA2
MTYyMjIxMDVaMA0GCSqGSIb3DQEBBQUAA4IBAQApqFdwm46jxkJK8J5kprGm6cp8
b7XMKB1epvhJGIkXHjp7O+2rxYGIExcNlM7jPcwqnUE0E50qGrqSMEupmtaBH03a
fmmDKyhLema7KD64UaERLqWjaW2DPeX9VX6vL4ECc6zTVLxfmYzxVt6A9hhqCm3b
fu8klWczGTa79r/WhTbA7uVf5+OI98da5tlxw+DlAQfqd34L2qq5aFg2dcTGqIdz
3pxP6UlTyj0ZPK3tUtTpIURVO2/MX3j5V+QjWz81UeCv0gQcmOiIVSRUGwi9c6JY
jDqBIvDY6df0riz5is1SS+D94sp1iovBlluwpq4kB8xyDuwt7vblkzleS2YU
-----END X509 CRL-----

13
boring/test/crl.pem Normal file
View File

@ -0,0 +1,13 @@
-----BEGIN X509 CRL-----
MIIB3jCBxwIBATANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJBVTETMBEGA1UE
CAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRk
Fw0yMjA2MjEyMDIyMDJaFw0zMjA2MTgyMDIyMDJaMBwwGgIJAIdx973umC+lFw0y
MjA2MjEyMDIxNTVaoDAwLjAfBgNVHSMEGDAWgBRs06UDqw1fLMmNipyIp4h3uDf9
mjALBgNVHRQEBAICEAEwDQYJKoZIhvcNAQELBQADggEBABgsWr/sVZqXm1AzgGCJ
JBMJW1oUY18aqroxo4kAIoI4QveLmHxi1Wm2I4dqdc6pM09SJhU5v5CfqpJ2BDc0
JBfEk8KKi5O/OYyLcUKa4dEpAlYPgeDyLc6zF8rGLtJoDIYuk4JUeuuByoXt0Sh+
7vx6UzuI7EH+mr4ZjnyAkD3f9jZy+mDcTm/+0REuh4iZ1AotE2YuQWQgxc1Y8TlD
eK+ks1zBKI23s0hPBxJQunmz2k3Uu9Yf+Sg0KxCiDgJZWFiGSw/6DtnT0oYAFGaD
mCyQWtwmS6zGBg+p76wNXkwyJMVvSDgrXSZ55bmImNmA38yKqOLOpB5i+FAS3r4V
ApQ=
-----END X509 CRL-----

11
boring/test/empty_crl.pem Normal file
View File

@ -0,0 +1,11 @@
-----BEGIN X509 CRL-----
MIIBijB0MA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApT
b21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQXDTIy
MDYxNjIyNDU1NVoXDTIzMDYxNjIyNDU1NVowDQYJKoZIhvcNAQEFBQADggEBAEtx
nBr3aI0qlegMVJsJn3GfkMzaPVTSTHuw76Dzdl9eGDj0hXzAzZW5k4WBHvaInzNT
NKkeISoQJHLH981R9sQU2zA8sTESLTJGyCFu05Y6XhdmqX4ywmzVRjL6p/aoHNdZ
H1mxgK16wG+Sv0pd+9qNJgC/cNFmNbWzbiEAi5kID4IUxSmId/FZsXsms1EjqDH4
DFIwLIQO/kR5zwE5fZ5EjqUBdAxoSVHfD+OPKl4x2t8CHMmao+ih2FOfd70+NLBD
2oxaJMjZL/SIf8vYxjpjimMR+7yJ5J5P1j/RBfG3LwwUDP0RtWLIvRQo/dZUyXTg
LuC1vNuUoObe12z/NQ4=
-----END X509 CRL-----

View File

@ -0,0 +1,11 @@
-----BEGIN X509 CRL-----
MIIBmTCBggIBATANBgkqhkiG9w0BAQsFADAhMQ0wCwYDVQQKDARGQUtFMRAwDgYD
VQQDDAdGQUtFIENBFw0yMjA2MjcyMTQ3NTBaFw0zMjA2MjQyMTQ3NTBaMBwwGgIJ
AIdx973umC+lFw0yMjA2MjcyMTQ2MjhaoA8wDTALBgNVHRQEBAICEAMwDQYJKoZI
hvcNAQELBQADggEBAMXZRqTG28rnJSUPnVaqkmePSH15iz5Q/e4MdrM0cipXGuzX
z5C8Oh0D2uT3ddawBxTosnbjuzlT7Tanbp3xCRBm9spRPxFbGaFWysBlG1aLTDka
e9t9YeErg7wpwU6Qar0dzkLL5IkW3NArgbe8gP9PkYQxz/B0ESdHIPYJP1YBMNG6
tLgEhg74Xs9UhOBInNsQB8qMGsEeOnzfiuvfspU/yvKHHzvjAcjeIrONLJaZcu2Y
Dsfm5gOXGkHEm5/qJZ/IILoY0GSsSBekCAZda5+v3nvyjfRaBPyhx3Zv+rXh7u5z
77bIzPZP60rslomacgEr4p/Y52E4GmKGV+X2+Hc=
-----END X509 CRL-----