diff --git a/Cargo.lock b/Cargo.lock index 18787e99c..1fd1cb333 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1710,6 +1710,17 @@ dependencies = [ "spki 0.6.0-pre.3", ] +[[package]] +name = "x509-ocsp" +version = "0.0.1" +dependencies = [ + "const-oid 0.9.0", + "der 0.6.0-pre.4", + "hex-literal", + "spki 0.6.0-pre.3", + "x509-cert", +] + [[package]] name = "zeroize" version = "1.5.2" diff --git a/Cargo.toml b/Cargo.toml index 6d6c27db3..e311c46ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,8 @@ members = [ "tai64", "tls_codec", "tls_codec/derive", - "x509" + "x509", + "x509-ocsp" ] [profile.dev] diff --git a/x509-ocsp/Cargo.toml b/x509-ocsp/Cargo.toml new file mode 100644 index 000000000..9b393cde1 --- /dev/null +++ b/x509-ocsp/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "x509-ocsp" +version = "0.0.1" +description = """ +Pure Rust implementation of the X.509 Internet Public Key Infrastructure +Online Certificate Status Protocol - OCSP formats as described in RFC 6960 +""" +authors = ["RustCrypto Developers"] +license = "Apache-2.0 OR MIT" +repository = "https://github.com/RustCrypto/formats/tree/master/x509-ocsp" +categories = ["cryptography", "data-structures", "encoding", "no-std"] +keywords = ["crypto", "x.509"] +readme = "README.md" +edition = "2021" +rust-version = "1.57" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +der = { version = "0.6.0-pre.3", features = ["oid", "derive", "alloc"], path = "../der" } +x509-cert = { version = "0.0.2", path = "../x509" } +const-oid = { version = "0.9.0", path = "../const-oid" } +spki = { version = "=0.6.0-pre.3", path = "../spki" } + +[dev-dependencies] +hex-literal = "0.3" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] diff --git a/x509-ocsp/README.md b/x509-ocsp/README.md new file mode 100644 index 000000000..c21da764a --- /dev/null +++ b/x509-ocsp/README.md @@ -0,0 +1,60 @@ +# [RustCrypto]: X.509 Online Certificate Status Protocol (OCSP) + +[![crate][crate-image]][crate-link] +[![Docs][docs-image]][docs-link] +[![Build Status][build-image]][build-link] +![Apache2/MIT licensed][license-image] +![Rust Version][rustc-image] +[![Project Chat][chat-image]][chat-link] + +Pure Rust implementation of the X.509 Internet Public Key Infrastructure +Online Certificate Status Protocol - OCSP formats as described in [RFC 6960]. + +[Documentation][docs-link] + +## Status + +tl;dr: not ready to use. + +This is a work-in-progress implementation which is at an early stage of +development. + +## Minimum Supported Rust Version + +This crate requires **Rust 1.57** at a minimum. + +We may change the MSRV in the future, but it will be accompanied by a minor +version bump. + +## License + +Licensed under either of: + +- [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) +- [MIT license](http://opensource.org/licenses/MIT) + +at your option. + +### 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 as above, without any additional terms or conditions. + +[//]: # (badges) + +[crate-image]: https://img.shields.io/crates/v/x509.svg +[crate-link]: https://crates.io/crates/x509 +[docs-image]: https://docs.rs/x509/badge.svg +[docs-link]: https://docs.rs/x509/ +[build-image]: https://github.com/RustCrypto/formats/actions/workflows/x509.yml/badge.svg +[build-link]: https://github.com/RustCrypto/formats/actions/workflows/x509.yml +[license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg +[rustc-image]: https://img.shields.io/badge/rustc-1.57+-blue.svg +[chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg +[chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/300570-formats + +[//]: # (links) + +[RustCrypto]: https://github.com/rustcrypto +[RFC 6960]: https://datatracker.ietf.org/doc/html/rfc6960 diff --git a/x509-ocsp/src/lib.rs b/x509-ocsp/src/lib.rs new file mode 100644 index 000000000..9e7a01b39 --- /dev/null +++ b/x509-ocsp/src/lib.rs @@ -0,0 +1,458 @@ +//! The ocsp module features encoders and decoders for the structures defined in [RFC 6960](https://datatracker.ietf.org/doc/html/rfc6960). +#![no_std] + +extern crate alloc; + +use der::asn1::{BitStringRef, Ia5StringRef, ObjectIdentifier, OctetStringRef, UIntRef}; +use der::asn1::{GeneralizedTime, Null}; +use der::{AnyRef, Choice, Enumerated, Sequence}; +use spki::AlgorithmIdentifier; +use x509_cert::ext::pkix::name::GeneralName; +use x509_cert::ext::pkix::{AuthorityInfoAccessSyntax, CrlReason}; +use x509_cert::ext::Extensions; +use x509_cert::name::Name; +use x509_cert::Certificate; + +use alloc::vec::Vec; +use core::default::Default; +use core::option::Option; + +/// OcspNoCheck as defined in [RFC 6960 Section 4.2.2.2.1]. +/// +/// This extension is identified by the ID_PKIX_OCSP_NOCHECK OID. +/// +/// ```text +/// OcspNoCheck ::= NULL +/// ``` +/// +/// [RFC 6960 Section 4.2.2.2.1]: https://datatracker.ietf.org/doc/html/rfc6960#section-4.2.2.2.1 +pub type OcspNoCheck = Null; + +/// OCSPRequest structure as defined in [RFC 6960 Section 4.1.1]. +/// +/// ```text +/// OCSPRequest ::= SEQUENCE { +/// tbsRequest TBSRequest, +/// optionalSignature [0] EXPLICIT Signature OPTIONAL } +/// ``` +/// +/// [RFC 6960 Section 4.1.1]: https://datatracker.ietf.org/doc/html/rfc6960#section-4.1.1 +#[derive(Clone, Debug, Eq, PartialEq, Sequence)] +#[allow(missing_docs)] +pub struct OcspRequest<'a> { + pub tbs_request: TbsRequest<'a>, + + #[asn1(context_specific = "0", optional = "true", tag_mode = "EXPLICIT")] + pub optional_signature: Option>, +} + +/// TBSRequest structure as defined in [RFC 6960 Section 4.1.1]. +/// +/// ```text +/// TBSRequest ::= SEQUENCE { +/// version [0] EXPLICIT Version DEFAULT v1, +/// requestorName [1] EXPLICIT GeneralName OPTIONAL, +/// requestList SEQUENCE OF Request, +/// requestExtensions [2] EXPLICIT Extensions OPTIONAL } +/// ``` +/// +/// [RFC 6960 Section 4.1.1]: https://datatracker.ietf.org/doc/html/rfc6960#section-4.1.1 +#[derive(Clone, Debug, Eq, PartialEq, Sequence)] +#[allow(missing_docs)] +pub struct TbsRequest<'a> { + #[asn1( + context_specific = "0", + default = "Default::default", + tag_mode = "EXPLICIT" + )] + pub version: Version, + + #[asn1(context_specific = "1", optional = "true", tag_mode = "EXPLICIT")] + pub requestor_name: Option>, + + pub request_list: alloc::vec::Vec>, + + #[asn1(context_specific = "2", optional = "true", tag_mode = "EXPLICIT")] + pub request_extensions: Option>, +} + +/// Signature structure as defined in [RFC 6960 Section 4.1.1]. +/// +/// ```text +/// Signature ::= SEQUENCE { +/// signatureAlgorithm AlgorithmIdentifier, +/// signature BIT STRING, +/// certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } +/// ``` +/// +/// [RFC 6960 Section 4.1.1]: https://datatracker.ietf.org/doc/html/rfc6960#section-4.1.1 +#[derive(Clone, Debug, Eq, PartialEq, Sequence)] +#[allow(missing_docs)] +pub struct Signature<'a> { + pub signature_algorithm: AlgorithmIdentifier<'a>, + pub signature: BitStringRef<'a>, + + #[asn1(context_specific = "0", optional = "true", tag_mode = "EXPLICIT")] + pub certs: Option>>, +} + +/// OCSP `Version` as defined in [RFC 6960 Section 4.1.1]. +/// +/// ```text +/// Version ::= INTEGER { v1(0) } +/// ``` +/// +/// [RFC 6960 Section 4.1.1]: https://datatracker.ietf.org/doc/html/rfc6960#section-4.1.1 +#[derive(Clone, Debug, Copy, PartialEq, Eq, Enumerated)] +#[asn1(type = "INTEGER")] +#[repr(u8)] +#[allow(missing_docs)] +pub enum Version { + V1 = 0, +} + +impl Default for Version { + fn default() -> Self { + Self::V1 + } +} + +/// Request structure as defined in [RFC 6960 Section 4.1.1]. +/// +/// ```text +/// Request ::= SEQUENCE { +/// reqCert CertID, +/// singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL } +/// ``` +/// +/// [RFC 6960 Section 4.1.1]: https://datatracker.ietf.org/doc/html/rfc6960#section-4.1.1 +#[derive(Clone, Debug, Eq, PartialEq, Sequence)] +#[allow(missing_docs)] +pub struct Request<'a> { + pub req_cert: CertId<'a>, + + #[asn1(context_specific = "0", optional = "true", tag_mode = "EXPLICIT")] + pub single_request_extensions: Option>, +} + +/// CertID structure as defined in [RFC 6960 Section 4.1.1]. +/// +/// ```text +/// CertID ::= SEQUENCE { +/// hashAlgorithm AlgorithmIdentifier, +/// issuerNameHash OCTET STRING, -- Hash of issuer's DN +/// issuerKeyHash OCTET STRING, -- Hash of issuer's public key +/// serialNumber CertificateSerialNumber } +/// ``` +/// +/// [RFC 6960 Section 4.1.1]: https://datatracker.ietf.org/doc/html/rfc6960#section-4.1.1 +#[derive(Clone, Debug, Eq, PartialEq, Sequence)] +#[allow(missing_docs)] +pub struct CertId<'a> { + pub hash_algorithm: AlgorithmIdentifier<'a>, + pub issuer_name_hash: OctetStringRef<'a>, + pub issuer_key_hash: OctetStringRef<'a>, + pub serial_number: UIntRef<'a>, +} + +/// OCSPResponse structure as defined in [RFC 6960 Section 4.2.1]. +/// +/// ```text +/// OCSPResponse ::= SEQUENCE { +/// responseStatus OCSPResponseStatus, +/// responseBytes [0] EXPLICIT ResponseBytes OPTIONAL } +/// ``` +/// +/// [RFC 6960 Section 4.2.1]: https://datatracker.ietf.org/doc/html/rfc6960#section-4.2.1 +#[derive(Clone, Debug, Eq, PartialEq, Sequence)] +#[allow(missing_docs)] +pub struct OcspResponse<'a> { + pub response_status: OcspResponseStatus, + + #[asn1(context_specific = "0", optional = "true", tag_mode = "EXPLICIT")] + pub response_bytes: Option>, +} + +/// OCSPResponseStatus structure as defined in [RFC 6960 Section 4.2.1]. +/// +/// ```text +/// OCSPResponseStatus ::= ENUMERATED { +/// successful (0), -- Response has valid confirmations +/// malformedRequest (1), -- Illegal confirmation request +/// internalError (2), -- Internal error in issuer +/// tryLater (3), -- Try again later +/// -- (4) is not used +/// sigRequired (5), -- Must sign the request +/// unauthorized (6) -- Request unauthorized +/// } +/// ``` +/// +/// [RFC 6960 Section 4.2.1]: https://datatracker.ietf.org/doc/html/rfc6960#section-4.2.1 +#[derive(Enumerated, Copy, Clone, Debug, Eq, PartialEq)] +#[repr(u32)] +#[allow(missing_docs)] +pub enum OcspResponseStatus { + Successful = 0, + MalformedRequest = 1, + InternalError = 2, + TryLater = 3, + SigRequired = 5, + Unauthorized = 6, +} + +/// ResponseBytes structure as defined in [RFC 6960 Section 4.2.1]. +/// +/// ```text +/// ResponseBytes ::= SEQUENCE { +/// responseType OBJECT IDENTIFIER, +/// response OCTET STRING } +/// ``` +/// +/// [RFC 6960 Section 4.2.1]: https://datatracker.ietf.org/doc/html/rfc6960#section-4.2.1 +#[derive(Clone, Debug, Eq, PartialEq, Sequence)] +#[allow(missing_docs)] +pub struct ResponseBytes<'a> { + pub response_type: ObjectIdentifier, + pub response: OctetStringRef<'a>, +} + +/// BasicOcspResponse structure as defined in [RFC 6960 Section 4.2.1]. +/// +/// ```text +/// BasicOCSPResponse ::= SEQUENCE { +/// tbsResponseData ResponseData, +/// signatureAlgorithm AlgorithmIdentifier, +/// signature BIT STRING, +/// certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL } +/// ``` +/// +/// [RFC 6960 Section 4.2.1]: https://datatracker.ietf.org/doc/html/rfc6960#section-4.2.1 +#[derive(Clone, Debug, Eq, PartialEq, Sequence)] +#[allow(missing_docs)] +pub struct BasicOcspResponse<'a> { + pub tbs_response_data: ResponseData<'a>, + pub signature_algorithm: AlgorithmIdentifier<'a>, + pub signature: BitStringRef<'a>, + + #[asn1(context_specific = "0", optional = "true", tag_mode = "EXPLICIT")] + pub certs: Option>>, +} + +/// ResponseData structure as defined in [RFC 6960 Section 4.2.1]. +/// +/// ```text +// ResponseData ::= SEQUENCE { +/// version [0] EXPLICIT Version DEFAULT v1, +/// responderID ResponderID, +/// producedAt GeneralizedTime, +/// responses SEQUENCE OF SingleResponse, +/// responseExtensions [1] EXPLICIT Extensions OPTIONAL } +/// ``` +/// +/// [RFC 6960 Section 4.2.1]: https://datatracker.ietf.org/doc/html/rfc6960#section-4.2.1 +#[derive(Clone, Debug, Eq, PartialEq, Sequence)] +#[allow(missing_docs)] +pub struct ResponseData<'a> { + #[asn1( + context_specific = "0", + default = "Default::default", + tag_mode = "EXPLICIT" + )] + pub version: Version, + pub responder_id: ResponderId<'a>, + pub produced_at: GeneralizedTime, + pub responses: Vec>, + + #[asn1(context_specific = "1", optional = "true", tag_mode = "EXPLICIT")] + pub response_extensions: Option>, +} + +/// ResponderID structure as defined in [RFC 6960 Section 4.2.1]. +/// +/// ```text +// ResponderID ::= CHOICE { +/// byName [1] Name, +/// byKey [2] KeyHash } +/// ``` +/// +/// [RFC 6960 Section 4.2.1]: https://datatracker.ietf.org/doc/html/rfc6960#section-4.2.1 +#[derive(Clone, Debug, Eq, PartialEq, Choice)] +#[allow(missing_docs)] +pub enum ResponderId<'a> { + #[asn1(context_specific = "1", tag_mode = "EXPLICIT", constructed = "true")] + ByName(Name<'a>), + + #[asn1(context_specific = "2", tag_mode = "EXPLICIT", constructed = "true")] + ByKey(KeyHash<'a>), +} + +/// KeyHash structure as defined in [RFC 6960 Section 4.2.1]. +/// +/// ```text +/// KeyHash ::= OCTET STRING -- SHA-1 hash of responder's public key +/// -- (i.e., the SHA-1 hash of the value of the +/// -- BIT STRING subjectPublicKey [excluding +/// -- the tag, length, and number of unused +/// -- bits] in the responder's certificate) +/// ``` +/// +/// [RFC 6960 Section 4.2.1]: https://datatracker.ietf.org/doc/html/rfc6960#section-4.2.1 +pub type KeyHash<'a> = OctetStringRef<'a>; + +/// SingleResponse structure as defined in [RFC 6960 Section 4.2.1]. +/// +/// ```text +// SingleResponse ::= SEQUENCE { +/// certID CertID, +/// certStatus CertStatus, +/// thisUpdate GeneralizedTime, +/// nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL, +/// singleExtensions [1] EXPLICIT Extensions OPTIONAL } +/// ``` +/// +/// [RFC 6960 Section 4.2.1]: https://datatracker.ietf.org/doc/html/rfc6960#section-4.2.1 +#[derive(Clone, Debug, Eq, PartialEq, Sequence)] +#[allow(missing_docs)] +pub struct SingleResponse<'a> { + pub cert_id: CertId<'a>, + pub cert_status: CertStatus, + pub this_update: GeneralizedTime, + + #[asn1(context_specific = "0", optional = "true", tag_mode = "EXPLICIT")] + pub next_update: Option, + + #[asn1(context_specific = "1", optional = "true", tag_mode = "EXPLICIT")] + pub single_request_extensions: Option>, +} + +/// CertStatus structure as defined in [RFC 6960 Section 4.2.1]. +/// +/// ```text +/// CertStatus ::= CHOICE { +/// good [0] IMPLICIT NULL, +/// revoked [1] IMPLICIT RevokedInfo, +/// unknown [2] IMPLICIT UnknownInfo } +/// ``` +/// +/// [RFC 6960 Section 4.2.1]: https://datatracker.ietf.org/doc/html/rfc6960#section-4.2.1 +#[derive(Clone, Debug, Eq, PartialEq, Choice)] +#[allow(missing_docs)] +pub enum CertStatus { + #[asn1(context_specific = "0", tag_mode = "IMPLICIT")] + Good(Null), + + #[asn1(context_specific = "1", tag_mode = "IMPLICIT", constructed = "true")] + Revoked(RevokedInfo), + + #[asn1(context_specific = "2", tag_mode = "IMPLICIT")] + Unknown(UnknownInfo), +} + +/// RevokedInfo structure as defined in [RFC 6960 Section 4.2.1]. +/// +/// ```text +// RevokedInfo ::= SEQUENCE { +/// revocationTime GeneralizedTime, +/// revocationReason [0] EXPLICIT CRLReason OPTIONAL } +/// ``` +/// +/// [RFC 6960 Section 4.2.1]: https://datatracker.ietf.org/doc/html/rfc6960#section-4.2.1 +#[derive(Clone, Debug, Eq, PartialEq, Sequence)] +#[allow(missing_docs)] +pub struct RevokedInfo { + pub revocation_time: GeneralizedTime, + + #[asn1(context_specific = "0", optional = "true", tag_mode = "EXPLICIT")] + pub revocation_reason: Option, +} + +/// RevokedInfo structure as defined in [RFC 6960 Section 4.2.1]. +/// +/// ```text +/// UnknownInfo ::= NULL +/// ``` +/// +/// [RFC 6960 Section 4.2.1]: https://datatracker.ietf.org/doc/html/rfc6960#section-4.2.1 +pub type UnknownInfo = Null; + +/// ArchiveCutoff structure as defined in [RFC 6960 Section 4.4.4]. +/// +/// ```text +// ArchiveCutoff ::= GeneralizedTime +/// ``` +/// +/// [RFC 6960 Section 4.4.4]: https://datatracker.ietf.org/doc/html/rfc6960#section-4.4.4 +pub type ArchiveCutoff = GeneralizedTime; + +/// AcceptableResponses structure as defined in [RFC 6960 Section 4.4.3]. +/// +/// ```text +// AcceptableResponses ::= SEQUENCE OF OBJECT IDENTIFIER +/// ``` +/// +/// [RFC 6960 Section 4.4.3]: https://datatracker.ietf.org/doc/html/rfc6960#section-4.4.3 +pub type AcceptableResponses = Vec; + +/// ServiceLocator structure as defined in [RFC 6960 Section 4.4.6]. +/// +/// ```text +/// ServiceLocator ::= SEQUENCE { +/// issuer Name, +/// locator AuthorityInfoAccessSyntax } +/// ``` +/// +/// [RFC 6960 Section 4.4.6]: https://datatracker.ietf.org/doc/html/rfc6960#section-4.4.6 +#[derive(Clone, Debug, Eq, PartialEq, Sequence)] +#[allow(missing_docs)] +pub struct ServiceLocator<'a> { + pub issuer: Name<'a>, + pub locator: AuthorityInfoAccessSyntax<'a>, +} + +/// CrlID structure as defined in [RFC 6960 Section 4.4.2]. +/// +/// ```text +/// CrlID ::= SEQUENCE { +/// crlUrl [0] EXPLICIT IA5String OPTIONAL, +/// crlNum [1] EXPLICIT INTEGER OPTIONAL, +/// crlTime [2] EXPLICIT GeneralizedTime OPTIONAL } +/// ``` +/// +/// [RFC 6960 Section 4.4.2]: https://datatracker.ietf.org/doc/html/rfc6960#section-4.4.2 +#[derive(Clone, Debug, Eq, PartialEq, Sequence)] +#[allow(missing_docs)] +pub struct CrlId<'a> { + #[asn1(context_specific = "0", optional = "true", tag_mode = "EXPLICIT")] + pub crl_url: Option>, + + #[asn1(context_specific = "1", optional = "true", tag_mode = "EXPLICIT")] + pub crl_num: Option>, + + #[asn1(context_specific = "2", optional = "true", tag_mode = "EXPLICIT")] + pub crl_time: Option, +} + +/// PreferredSignatureAlgorithms structure as defined in [RFC 6960 Section 4.4.7.1]. +/// +/// ```text +/// PreferredSignatureAlgorithms ::= SEQUENCE OF PreferredSignatureAlgorithm +/// ``` +/// +/// [RFC 6960 Section 4.4.7.1]: https://datatracker.ietf.org/doc/html/rfc6960#section-4.4.7.1 +pub type PreferredSignatureAlgorithms<'a> = Vec>; + +/// PreferredSignatureAlgorithm structure as defined in [RFC 6960 Section 4.4.7.1]. +/// +/// ```text +/// PreferredSignatureAlgorithm ::= SEQUENCE { +/// sigIdentifier AlgorithmIdentifier, +/// certIdentifier AlgorithmIdentifier OPTIONAL } +/// ``` +/// +/// [RFC 6960 Section 4.4.7.1]: https://datatracker.ietf.org/doc/html/rfc6960#section-4.4.7.1 +#[derive(Clone, Debug, Eq, PartialEq, Sequence)] +#[allow(missing_docs)] +pub struct PreferredSignatureAlgorithm<'a> { + pub sig_identifier: AlgorithmIdentifier<'a>, + pub cert_identifier: Option>, +} diff --git a/x509-ocsp/tests/ocsp.rs b/x509-ocsp/tests/ocsp.rs new file mode 100644 index 000000000..c88320d45 --- /dev/null +++ b/x509-ocsp/tests/ocsp.rs @@ -0,0 +1,297 @@ +use const_oid::db::rfc6960::ID_PKIX_OCSP_BASIC; +use der::asn1::{Null, ObjectIdentifier}; +use der::{Decode, Encode}; +use hex_literal::hex; +use x509_cert::ext::pkix::CrlReason; +use x509_ocsp::Version::V1; +use x509_ocsp::*; + +#[test] +fn decode_ocsp_req_ca_signed() { + // request generated using openssl via this command: + // openssl ocsp -noverify -no_nonce -respout ~/Desktop/ocspdigicert.resp + // -reqout ~/Desktop/ocspdigicert.req -issuer ~/Desktop/DigiCertGlobalCAG2.crt + // -cert ~/Desktop/amazon.der -url http://ocsp.digicert.com -header "HOST" "ocsp.digicert.com" -text + + pub const PKIXALG_SHA1: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.3.14.3.2.26"); + + let ocsp_req = + OcspRequest::from_der(&hex!("3051304F304D304B3049300906052B0E03021A05000414A87E303106E4E88565CFE952598FA6DA7C00532F0414246E2B2DD06A925151256901AA9A47A689E7402002100E4239AB85E2E6A27C52C6DE9B9078D9")[..]).unwrap(); + assert_eq!(ocsp_req.tbs_request.version, V1); + //assert!(ocsp_req.tbs_request.requestor_name.is_none()); + assert_eq!(ocsp_req.tbs_request.request_list.len(), 1); + let req = &ocsp_req.tbs_request.request_list[0]; + assert_eq!(req.req_cert.hash_algorithm.oid, PKIXALG_SHA1); + assert!(req.req_cert.hash_algorithm.parameters.is_some()); + assert_eq!( + req.req_cert + .hash_algorithm + .parameters + .to_vec() + .unwrap() + .as_slice(), + Null.to_vec().unwrap().as_slice() + ); + assert_eq!( + req.req_cert.issuer_name_hash.as_bytes(), + &hex!("A87E303106E4E88565CFE952598FA6DA7C00532F") + ); + assert_eq!( + req.req_cert.issuer_key_hash.as_bytes(), + &hex!("246E2B2DD06A925151256901AA9A47A689E74020") + ); + assert_eq!( + req.req_cert.serial_number.as_bytes(), + &hex!("0E4239AB85E2E6A27C52C6DE9B9078D9") + ); + + let reenc = ocsp_req.to_vec().unwrap(); + assert_eq!(reenc, &hex!("3051304F304D304B3049300906052B0E03021A05000414A87E303106E4E88565CFE952598FA6DA7C00532F0414246E2B2DD06A925151256901AA9A47A689E7402002100E4239AB85E2E6A27C52C6DE9B9078D9")[..]) +} + +#[test] +fn decode_ocsp_resp_ca_signed() { + // response generated using openssl via this command: + // openssl ocsp -noverify -no_nonce -respout ~/Desktop/ocspdigicert.resp + // -reqout ~/Desktop/ocspdigicert.req -issuer ~/Desktop/DigiCertGlobalCAG2.crt + // -cert ~/Desktop/amazon.der -url http://ocsp.digicert.com -header "HOST" "ocsp.digicert.com" -text + + // 308201D30A0100A08201CC308201C806092B0601050507300101048201B9308201B530819EA2160414246E2B2DD06A925151256901AA9A47A689E74020180F32303232303230323034313232355A307330713049300906052B0E03021A05000414A87E303106E4E88565CFE952598FA6DA7C00532F0414246E2B2DD06A925151256901AA9A47A689E7402002100E4239AB85E2E6A27C52C6DE9B9078D98000180F32303232303230323033353730315AA011180F32303232303230393033313230315A300D06092A864886F70D01010B0500038201010089DC0913BD91DB172C314AE8F78E6574950353618FFBBF2F12B1F134F21EC20063E66C60AC463BDB926A9D5B699EB39689032659D43C441863BAC9D8B7CC84137B558503D2631348EDA79AEC9FD4B69AE988F68A752470D3D4BA46F41B9FD41A974A5311BAA191AFBA370F0B051F035297FA76A2133B98FF471BDA4BFBFDA275B4FA1CF8377EEB2B2141F9C998ACE27C60F11E221D6732A5D538FEDF9A01D776E1877BCF70A8C953630B2C66752A66DF087C075794F5A2C0023C964CD73476EA2556F091F6C191B30B74E2523F668F32CE10AFB3D51CE053D4D41E62214B60171093AB915DBBA497F09B3C279127E1D25C7AA6A7048BBEA41A23F4F827BD108F + let ocsp_resp = + OcspResponse::from_der(&hex!("308201D30A0100A08201CC308201C806092B0601050507300101048201B9308201B530819EA2160414246E2B2DD06A925151256901AA9A47A689E74020180F32303232303230323034313232355A307330713049300906052B0E03021A05000414A87E303106E4E88565CFE952598FA6DA7C00532F0414246E2B2DD06A925151256901AA9A47A689E7402002100E4239AB85E2E6A27C52C6DE9B9078D98000180F32303232303230323033353730315AA011180F32303232303230393033313230315A300D06092A864886F70D01010B0500038201010089DC0913BD91DB172C314AE8F78E6574950353618FFBBF2F12B1F134F21EC20063E66C60AC463BDB926A9D5B699EB39689032659D43C441863BAC9D8B7CC84137B558503D2631348EDA79AEC9FD4B69AE988F68A752470D3D4BA46F41B9FD41A974A5311BAA191AFBA370F0B051F035297FA76A2133B98FF471BDA4BFBFDA275B4FA1CF8377EEB2B2141F9C998ACE27C60F11E221D6732A5D538FEDF9A01D776E1877BCF70A8C953630B2C66752A66DF087C075794F5A2C0023C964CD73476EA2556F091F6C191B30B74E2523F668F32CE10AFB3D51CE053D4D41E62214B60171093AB915DBBA497F09B3C279127E1D25C7AA6A7048BBEA41A23F4F827BD108F")[..]).unwrap(); + + assert_eq!(ocsp_resp.response_status, OcspResponseStatus::Successful); + assert!(ocsp_resp.response_bytes.is_some()); + let response_bytes = ocsp_resp.response_bytes.as_ref().unwrap(); + assert_eq!(response_bytes.response_type, ID_PKIX_OCSP_BASIC); + + pub const PKIXALG_SHA256_WITH_RSA_ENCRYPTION: ObjectIdentifier = + ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.11"); + pub const PKIXALG_SHA1: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.3.14.3.2.26"); + + let bor = BasicOcspResponse::from_der(response_bytes.response.as_bytes()).unwrap(); + assert_eq!( + bor.signature_algorithm.oid, + PKIXALG_SHA256_WITH_RSA_ENCRYPTION + ); + assert!(bor.signature_algorithm.parameters.is_some()); + assert_eq!( + bor.signature_algorithm + .parameters + .to_vec() + .unwrap() + .as_slice(), + Null.to_vec().unwrap().as_slice() + ); + + assert_eq!(bor.tbs_response_data.version, V1); + + match bor.tbs_response_data.responder_id { + ResponderId::ByKey(kh) => { + assert_eq!( + kh.as_bytes(), + &hex!("246E2B2DD06A925151256901AA9A47A689E74020") + ); + } + _ => { + panic!("Expected ByKey and got something else") + } + } + + assert_eq!( + bor.tbs_response_data + .produced_at + .to_unix_duration() + .as_secs(), + 1643775145 + ); + assert_eq!(bor.tbs_response_data.responses.len(), 1); + let sr = &bor.tbs_response_data.responses[0]; + assert_eq!(sr.cert_id.hash_algorithm.oid, PKIXALG_SHA1); + assert!(sr.cert_id.hash_algorithm.parameters.is_some()); + assert_eq!( + sr.cert_id + .hash_algorithm + .parameters + .to_vec() + .unwrap() + .as_slice(), + Null.to_vec().unwrap().as_slice() + ); + assert_eq!( + sr.cert_id.issuer_name_hash.as_bytes(), + &hex!("A87E303106E4E88565CFE952598FA6DA7C00532F") + ); + assert_eq!( + sr.cert_id.issuer_key_hash.as_bytes(), + &hex!("246E2B2DD06A925151256901AA9A47A689E74020") + ); + assert_eq!( + sr.cert_id.serial_number.as_bytes(), + &hex!("0E4239AB85E2E6A27C52C6DE9B9078D9") + ); + + match sr.cert_status { + CertStatus::Good(g) => { + assert_eq!( + g.to_vec().unwrap().as_slice(), + Null.to_vec().unwrap().as_slice() + ); + } + _ => { + panic!("Expected Good and got something other") + } + } + + assert_eq!(sr.this_update.to_unix_duration().as_secs(), 1643774221); + assert!(sr.next_update.is_some()); + assert_eq!( + sr.next_update.unwrap().to_unix_duration().as_secs(), + 1644376321 + ); + + let reenc = ocsp_resp.to_vec().unwrap(); + assert_eq!(reenc, &hex!("308201D30A0100A08201CC308201C806092B0601050507300101048201B9308201B530819EA2160414246E2B2DD06A925151256901AA9A47A689E74020180F32303232303230323034313232355A307330713049300906052B0E03021A05000414A87E303106E4E88565CFE952598FA6DA7C00532F0414246E2B2DD06A925151256901AA9A47A689E7402002100E4239AB85E2E6A27C52C6DE9B9078D98000180F32303232303230323033353730315AA011180F32303232303230393033313230315A300D06092A864886F70D01010B0500038201010089DC0913BD91DB172C314AE8F78E6574950353618FFBBF2F12B1F134F21EC20063E66C60AC463BDB926A9D5B699EB39689032659D43C441863BAC9D8B7CC84137B558503D2631348EDA79AEC9FD4B69AE988F68A752470D3D4BA46F41B9FD41A974A5311BAA191AFBA370F0B051F035297FA76A2133B98FF471BDA4BFBFDA275B4FA1CF8377EEB2B2141F9C998ACE27C60F11E221D6732A5D538FEDF9A01D776E1877BCF70A8C953630B2C66752A66DF087C075794F5A2C0023C964CD73476EA2556F091F6C191B30B74E2523F668F32CE10AFB3D51CE053D4D41E62214B60171093AB915DBBA497F09B3C279127E1D25C7AA6A7048BBEA41A23F4F827BD108F")[..]) +} + +#[test] +fn decode_ocsp_req_delegated() { + // request generated using openssl via this command: + // openssl ocsp -noverify -no_nonce -respout ~/Desktop/ocspdod.resp -reqout ~/Desktop/ocspdod.req + // -issuer ~/Desktop/email_ca_59.der -cert ~/Desktop/ee.der -url http://ocsp.disa.mil + // -header "HOST" "ocsp.disa.mil" -text + + pub const PKIXALG_SHA1: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.3.14.3.2.26"); + + let ocsp_req = + OcspRequest::from_der(&hex!("304530433041303F303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B92020401017467")[..]).unwrap(); + assert_eq!(ocsp_req.tbs_request.version, V1); + //assert!(ocsp_req.tbs_request.requestor_name.is_none()); + assert_eq!(ocsp_req.tbs_request.request_list.len(), 1); + let req = &ocsp_req.tbs_request.request_list[0]; + assert_eq!(req.req_cert.hash_algorithm.oid, PKIXALG_SHA1); + assert!(req.req_cert.hash_algorithm.parameters.is_some()); + assert_eq!( + req.req_cert + .hash_algorithm + .parameters + .to_vec() + .unwrap() + .as_slice(), + Null.to_vec().unwrap().as_slice() + ); + assert_eq!( + req.req_cert.issuer_name_hash.as_bytes(), + &hex!("0F0D5890F551D42ACF5431B7F42A321F7B74A473") + ); + assert_eq!( + req.req_cert.issuer_key_hash.as_bytes(), + &hex!("771441A65D9526D01DFF953B628CEAB7B55D3B92") + ); + assert_eq!(req.req_cert.serial_number.as_bytes(), &hex!("01017467")); + + let reenc = ocsp_req.to_vec().unwrap(); + assert_eq!(reenc, &hex!("304530433041303F303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B92020401017467")[..]) +} + +#[test] +fn decode_ocsp_resp_delegated() { + // response generated using openssl via this command: + // openssl ocsp -noverify -no_nonce -respout ~/Desktop/ocspdod.resp -reqout ~/Desktop/ocspdod.req + // -issuer ~/Desktop/email_ca_59.der -cert ~/Desktop/ee.der -url http://ocsp.disa.mil + // -header "HOST" "ocsp.disa.mil" -text + + // 308201D30A0100A08201CC308201C806092B0601050507300101048201B9308201B530819EA2160414246E2B2DD06A925151256901AA9A47A689E74020180F32303232303230323034313232355A307330713049300906052B0E03021A05000414A87E303106E4E88565CFE952598FA6DA7C00532F0414246E2B2DD06A925151256901AA9A47A689E7402002100E4239AB85E2E6A27C52C6DE9B9078D98000180F32303232303230323033353730315AA011180F32303232303230393033313230315A300D06092A864886F70D01010B0500038201010089DC0913BD91DB172C314AE8F78E6574950353618FFBBF2F12B1F134F21EC20063E66C60AC463BDB926A9D5B699EB39689032659D43C441863BAC9D8B7CC84137B558503D2631348EDA79AEC9FD4B69AE988F68A752470D3D4BA46F41B9FD41A974A5311BAA191AFBA370F0B051F035297FA76A2133B98FF471BDA4BFBFDA275B4FA1CF8377EEB2B2141F9C998ACE27C60F11E221D6732A5D538FEDF9A01D776E1877BCF70A8C953630B2C66752A66DF087C075794F5A2C0023C964CD73476EA2556F091F6C191B30B74E2523F668F32CE10AFB3D51CE053D4D41E62214B60171093AB915DBBA497F09B3C279127E1D25C7AA6A7048BBEA41A23F4F827BD108F + let ocsp_resp = + OcspResponse::from_der(&hex!("30820FA10A0100A0820F9A30820F9606092B060105050730010104820F8730820F83308209F1A2160414ADB0A9B2DDE9D444B4DF80F599598E84AC5EC687180F32303232303230333135303233365A308209C4307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B92020401017456A116180F32303231303532303138303635305AA0030A0104180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B92020401017457A116180F32303231303730373139353830355AA0030A0104180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B92020401017459A116180F32303231303532303138303634395AA0030A0104180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B9202040101745AA116180F32303231303132323136303832375AA0030A0104180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B9202040101745BA116180F32303231303731393138353734355AA0030A0101180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B9202040101745CA116180F32303231303132323136303832365AA0030A0104180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B9202040101745EA116180F32303231303432323132323332335AA0030A0104180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B92020401017460A116180F32303231303731393138353734335AA0030A0101180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B92020401017462A116180F32303231303932393136353734375AA0030A0103180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B92020401017464A116180F32303231303432323132323332325AA0030A0104180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B92020401017467A116180F32303231303932393136353734375AA0030A0103180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B92020401017477A116180F32303231303730313138313934365AA0030A0103180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B92020401017479A116180F32303232303130353138313532325AA0030A0103180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B9202040101747AA116180F32303231313130343131353932395AA0030A0101180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B9202040101747BA116180F32303231303730313138313934325AA0030A0103180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B9202040101747CA116180F32303232303130353138313532325AA0030A0103180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B9202040101747DA116180F32303231303231303136333032315AA0030A0104180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B9202040101747EA116180F32303231313130343131353932325AA0030A0101180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B92020401017480A116180F32303231303231303136333032305AA0030A0104180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B92020401017481A116180F32303231303132323133353031395AA0030A0104180F32303232303230333030333030305AA011180F32303232303231303031333030305A300D06092A864886F70D01010B050003820101008946FF8FF3009FC7265CB687D56960190379BEF6537FAC541A2306ED709B51AACD79B313331E297495AC4E26ABD94030CC407FDCE26CFC0B7A2BE1F226906182863FF1F140D628FA02B1D0BE1A1697E2F9C17AEF5FEC32AA4D120FAF0F58474AC2718964033076286DC358F5E96B08A5C83323CA4CA2B881D8FFA8E0EA3DB9A90863D378A3349EBF189030DA11891C6695950C5B93CBD440D998E67C0137655AC9DA40826B51211AD5985918336939131A4D1BF9E9A2A88CFB3C5059E3D1CE0D9B19F487EC018C60A0279E24270C7090006A4EC728E5C4A1F86829AFA236AF9979165DF1E7F0F5544217864F9C348ABF2B17C2FCD7DDE35838A99BC4A7256821A0820476308204723082046E30820356A0030201020203358762300D06092A864886F70D01010B0500305D310B300906035504061302555331183016060355040A130F552E532E20476F7665726E6D656E74310C300A060355040B1303446F44310C300A060355040B1303504B49311830160603550403130F444F4420454D41494C2043412D3539301E170D3232303132353030303035315A170D3232303331313030303035315A3064310B300906035504061302555331183016060355040A130F552E532E20476F7665726E6D656E74310C300A060355040B1303446F44310C300A060355040B1303504B49311F301D06035504031316444F44204E4950524E4554204F43535020313244203230820122300D06092A864886F70D01010105000382010F003082010A0282010100BF8A691DDB447562EFCDCB6C4DED76DDB200D1A188E01A3BA4EEEE1C42A7E5E78C0784C512F5CF64DD1A407A2EBC1F280761C1372351E03AED90C2DA0556066398E555EEE91C92988A62CDA1FD1F4E2E5F6EC6C022821C0D7C8B0E90E7CCF203CE8F102CBF4756D9B8CD09A2F16CF08F1E944311C8CD2120B98F6BCAEA1E60D1841A933815C8936BD20CC984FA1F5BF7AFFFFF2886DE53FDF3AE80E8394E09D441AE615693A78FE0051942B724147595DF049382897E26BBEA4E6902376C494F31141D1693005AA4E8AEBE4FEC342D10BFD90661935FB00D61A1FF7CB3B8FF45E473B3FFDD6D2C692FA8C0DE23373F1A6AD84109E7A9274008C5E94E28CE91850203010001A382012E3082012A301F0603551D23041830168014771441A65D9526D01DFF953B628CEAB7B55D3B92304606082B06010505070101043A3038303606082B06010505073002862A687474703A2F2F63726C2E646973612E6D696C2F7369676E2F444F44454D41494C43415F35392E63657230160603551D250101FF040C300A06082B06010505070309300E0603551D0F0101FF040403020780300F06092B060105050730010504020500301D0603551D0E04160414ADB0A9B2DDE9D444B4DF80F599598E84AC5EC68730670603551D200460305E300B0609608648016502010B24300B0609608648016502010B27300B0609608648016502010B2A300B0609608648016502010B3B300C060A6086480165030201030D300C060A60864801650302010311300C060A60864801650302010327300D06092A864886F70D01010B0500038201010047FE1DF6D439EF205C931F34B8C802B6E6D9C4EFEAFA7228FD07E56DFF17EEC18C250941EB46D5F416A02F2706A951A2A16435C589EE1059BB86EC38C7F07C2C6660C4B25C8918115FFD21A0D9798B860F878122B3781DCA004AFE869B4B88E0B8ABB4C3A255BC034B36ED82E4692AB765667E3036FC4BB2A53EF9B4654D5C8FDA62E1F6B9DFC7382FA9A3BEAC5EB35A105CB6FFD7B33D561DA77B886D17F58F9D6EDC722C9786E7C664598116F9ACB41282FB0C75EF6BA87BAE97249A42DF45FEC6AEB724C03D8EE5FF4FD7753AC0FE50CB6B746544D4A4DB977946D29183295B160538338FA2FB27F6BC84B5CBD658A431A8B87A9E20A57753BC8AB964B486")[..]).unwrap(); + + assert_eq!(ocsp_resp.response_status, OcspResponseStatus::Successful); + assert!(ocsp_resp.response_bytes.is_some()); + let response_bytes = ocsp_resp.response_bytes.as_ref().unwrap(); + assert_eq!(response_bytes.response_type, ID_PKIX_OCSP_BASIC); + + pub const PKIXALG_SHA256_WITH_RSA_ENCRYPTION: ObjectIdentifier = + ObjectIdentifier::new_unwrap("1.2.840.113549.1.1.11"); + pub const PKIXALG_SHA1: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.3.14.3.2.26"); + + let bor = BasicOcspResponse::from_der(response_bytes.response.as_bytes()).unwrap(); + assert_eq!( + bor.signature_algorithm.oid, + PKIXALG_SHA256_WITH_RSA_ENCRYPTION + ); + assert!(bor.signature_algorithm.parameters.is_some()); + assert_eq!( + bor.signature_algorithm + .parameters + .to_vec() + .unwrap() + .as_slice(), + Null.to_vec().unwrap().as_slice() + ); + + assert_eq!(bor.tbs_response_data.version, V1); + + match bor.tbs_response_data.responder_id { + ResponderId::ByKey(kh) => { + assert_eq!( + kh.as_bytes(), + &hex!("ADB0A9B2DDE9D444B4DF80F599598E84AC5EC687") + ); + } + _ => { + panic!("Expected ByKey and got something else") + } + } + + assert_eq!( + bor.tbs_response_data + .produced_at + .to_unix_duration() + .as_secs(), + 1643900556 + ); + assert_eq!(bor.tbs_response_data.responses.len(), 20); + let sr = &bor.tbs_response_data.responses[10]; + + assert_eq!(sr.cert_id.hash_algorithm.oid, PKIXALG_SHA1); + assert!(sr.cert_id.hash_algorithm.parameters.is_some()); + assert_eq!( + sr.cert_id + .hash_algorithm + .parameters + .to_vec() + .unwrap() + .as_slice(), + Null.to_vec().unwrap().as_slice() + ); + assert_eq!( + sr.cert_id.issuer_name_hash.as_bytes(), + &hex!("0F0D5890F551D42ACF5431B7F42A321F7B74A473") + ); + assert_eq!( + sr.cert_id.issuer_key_hash.as_bytes(), + &hex!("771441A65D9526D01DFF953B628CEAB7B55D3B92") + ); + assert_eq!(sr.cert_id.serial_number.as_bytes(), &hex!("01017467")); + + match &sr.cert_status { + CertStatus::Revoked(ri) => { + assert!(ri.revocation_reason.is_some()); + assert_eq!(ri.revocation_reason.unwrap(), CrlReason::AffiliationChanged,); + assert_eq!(ri.revocation_time.to_unix_duration().as_secs(), 1632934667,); + } + _ => { + panic!("Expected Good and got something other") + } + } + + assert_eq!(sr.this_update.to_unix_duration().as_secs(), 1643848200); + assert!(sr.next_update.is_some()); + assert_eq!( + sr.next_update.unwrap().to_unix_duration().as_secs(), + 1644456600 + ); + + let reenc = ocsp_resp.to_vec().unwrap(); + assert_eq!(reenc, &hex!("30820FA10A0100A0820F9A30820F9606092B060105050730010104820F8730820F83308209F1A2160414ADB0A9B2DDE9D444B4DF80F599598E84AC5EC687180F32303232303230333135303233365A308209C4307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B92020401017456A116180F32303231303532303138303635305AA0030A0104180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B92020401017457A116180F32303231303730373139353830355AA0030A0104180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B92020401017459A116180F32303231303532303138303634395AA0030A0104180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B9202040101745AA116180F32303231303132323136303832375AA0030A0104180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B9202040101745BA116180F32303231303731393138353734355AA0030A0101180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B9202040101745CA116180F32303231303132323136303832365AA0030A0104180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B9202040101745EA116180F32303231303432323132323332335AA0030A0104180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B92020401017460A116180F32303231303731393138353734335AA0030A0101180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B92020401017462A116180F32303231303932393136353734375AA0030A0103180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B92020401017464A116180F32303231303432323132323332325AA0030A0104180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B92020401017467A116180F32303231303932393136353734375AA0030A0103180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B92020401017477A116180F32303231303730313138313934365AA0030A0103180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B92020401017479A116180F32303232303130353138313532325AA0030A0103180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B9202040101747AA116180F32303231313130343131353932395AA0030A0101180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B9202040101747BA116180F32303231303730313138313934325AA0030A0103180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B9202040101747CA116180F32303232303130353138313532325AA0030A0103180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B9202040101747DA116180F32303231303231303136333032315AA0030A0104180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B9202040101747EA116180F32303231313130343131353932325AA0030A0101180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B92020401017480A116180F32303231303231303136333032305AA0030A0104180F32303232303230333030333030305AA011180F32303232303231303031333030305A307B303D300906052B0E03021A050004140F0D5890F551D42ACF5431B7F42A321F7B74A4730414771441A65D9526D01DFF953B628CEAB7B55D3B92020401017481A116180F32303231303132323133353031395AA0030A0104180F32303232303230333030333030305AA011180F32303232303231303031333030305A300D06092A864886F70D01010B050003820101008946FF8FF3009FC7265CB687D56960190379BEF6537FAC541A2306ED709B51AACD79B313331E297495AC4E26ABD94030CC407FDCE26CFC0B7A2BE1F226906182863FF1F140D628FA02B1D0BE1A1697E2F9C17AEF5FEC32AA4D120FAF0F58474AC2718964033076286DC358F5E96B08A5C83323CA4CA2B881D8FFA8E0EA3DB9A90863D378A3349EBF189030DA11891C6695950C5B93CBD440D998E67C0137655AC9DA40826B51211AD5985918336939131A4D1BF9E9A2A88CFB3C5059E3D1CE0D9B19F487EC018C60A0279E24270C7090006A4EC728E5C4A1F86829AFA236AF9979165DF1E7F0F5544217864F9C348ABF2B17C2FCD7DDE35838A99BC4A7256821A0820476308204723082046E30820356A0030201020203358762300D06092A864886F70D01010B0500305D310B300906035504061302555331183016060355040A130F552E532E20476F7665726E6D656E74310C300A060355040B1303446F44310C300A060355040B1303504B49311830160603550403130F444F4420454D41494C2043412D3539301E170D3232303132353030303035315A170D3232303331313030303035315A3064310B300906035504061302555331183016060355040A130F552E532E20476F7665726E6D656E74310C300A060355040B1303446F44310C300A060355040B1303504B49311F301D06035504031316444F44204E4950524E4554204F43535020313244203230820122300D06092A864886F70D01010105000382010F003082010A0282010100BF8A691DDB447562EFCDCB6C4DED76DDB200D1A188E01A3BA4EEEE1C42A7E5E78C0784C512F5CF64DD1A407A2EBC1F280761C1372351E03AED90C2DA0556066398E555EEE91C92988A62CDA1FD1F4E2E5F6EC6C022821C0D7C8B0E90E7CCF203CE8F102CBF4756D9B8CD09A2F16CF08F1E944311C8CD2120B98F6BCAEA1E60D1841A933815C8936BD20CC984FA1F5BF7AFFFFF2886DE53FDF3AE80E8394E09D441AE615693A78FE0051942B724147595DF049382897E26BBEA4E6902376C494F31141D1693005AA4E8AEBE4FEC342D10BFD90661935FB00D61A1FF7CB3B8FF45E473B3FFDD6D2C692FA8C0DE23373F1A6AD84109E7A9274008C5E94E28CE91850203010001A382012E3082012A301F0603551D23041830168014771441A65D9526D01DFF953B628CEAB7B55D3B92304606082B06010505070101043A3038303606082B06010505073002862A687474703A2F2F63726C2E646973612E6D696C2F7369676E2F444F44454D41494C43415F35392E63657230160603551D250101FF040C300A06082B06010505070309300E0603551D0F0101FF040403020780300F06092B060105050730010504020500301D0603551D0E04160414ADB0A9B2DDE9D444B4DF80F599598E84AC5EC68730670603551D200460305E300B0609608648016502010B24300B0609608648016502010B27300B0609608648016502010B2A300B0609608648016502010B3B300C060A6086480165030201030D300C060A60864801650302010311300C060A60864801650302010327300D06092A864886F70D01010B0500038201010047FE1DF6D439EF205C931F34B8C802B6E6D9C4EFEAFA7228FD07E56DFF17EEC18C250941EB46D5F416A02F2706A951A2A16435C589EE1059BB86EC38C7F07C2C6660C4B25C8918115FFD21A0D9798B860F878122B3781DCA004AFE869B4B88E0B8ABB4C3A255BC034B36ED82E4692AB765667E3036FC4BB2A53EF9B4654D5C8FDA62E1F6B9DFC7382FA9A3BEAC5EB35A105CB6FFD7B33D561DA77B886D17F58F9D6EDC722C9786E7C664598116F9ACB41282FB0C75EF6BA87BAE97249A42DF45FEC6AEB724C03D8EE5FF4FD7753AC0FE50CB6B746544D4A4DB977946D29183295B160538338FA2FB27F6BC84B5CBD658A431A8B87A9E20A57753BC8AB964B486")[..]) +}