summaryrefslogtreecommitdiffstats
path: root/vendor/openssl/src/ocsp.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/openssl/src/ocsp.rs')
-rw-r--r--vendor/openssl/src/ocsp.rs350
1 files changed, 350 insertions, 0 deletions
diff --git a/vendor/openssl/src/ocsp.rs b/vendor/openssl/src/ocsp.rs
new file mode 100644
index 000000000..7506d34fb
--- /dev/null
+++ b/vendor/openssl/src/ocsp.rs
@@ -0,0 +1,350 @@
+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! {
+ 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<'a> OcspStatus<'a> {
+ /// 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;
+}