192f3ab15Sopenharmony_ci#![deny(missing_docs)] 292f3ab15Sopenharmony_ci 392f3ab15Sopenharmony_ci//! Defines the format of certificates 492f3ab15Sopenharmony_ci//! 592f3ab15Sopenharmony_ci//! This module is used by [`x509`] and other certificate building functions 692f3ab15Sopenharmony_ci//! to describe time, strings, and objects. 792f3ab15Sopenharmony_ci//! 892f3ab15Sopenharmony_ci//! Abstract Syntax Notation One is an interface description language. 992f3ab15Sopenharmony_ci//! The specification comes from [X.208] by OSI, and rewritten in X.680. 1092f3ab15Sopenharmony_ci//! ASN.1 describes properties of an object with a type set. Those types 1192f3ab15Sopenharmony_ci//! can be atomic, structured, choice, and other (CHOICE and ANY). These 1292f3ab15Sopenharmony_ci//! types are expressed as a number and the assignment operator ::= gives 1392f3ab15Sopenharmony_ci//! the type a name. 1492f3ab15Sopenharmony_ci//! 1592f3ab15Sopenharmony_ci//! The implementation here provides a subset of the ASN.1 types that OpenSSL 1692f3ab15Sopenharmony_ci//! uses, especially in the properties of a certificate used in HTTPS. 1792f3ab15Sopenharmony_ci//! 1892f3ab15Sopenharmony_ci//! [X.208]: https://www.itu.int/rec/T-REC-X.208-198811-W/en 1992f3ab15Sopenharmony_ci//! [`x509`]: ../x509/struct.X509Builder.html 2092f3ab15Sopenharmony_ci//! 2192f3ab15Sopenharmony_ci//! ## Examples 2292f3ab15Sopenharmony_ci//! 2392f3ab15Sopenharmony_ci//! ``` 2492f3ab15Sopenharmony_ci//! use openssl::asn1::Asn1Time; 2592f3ab15Sopenharmony_ci//! let tomorrow = Asn1Time::days_from_now(1); 2692f3ab15Sopenharmony_ci//! ``` 2792f3ab15Sopenharmony_ciuse cfg_if::cfg_if; 2892f3ab15Sopenharmony_ciuse foreign_types::{ForeignType, ForeignTypeRef}; 2992f3ab15Sopenharmony_ciuse libc::{c_char, c_int, c_long, time_t}; 3092f3ab15Sopenharmony_ciuse std::cmp::Ordering; 3192f3ab15Sopenharmony_ciuse std::convert::TryInto; 3292f3ab15Sopenharmony_ciuse std::ffi::CString; 3392f3ab15Sopenharmony_ciuse std::fmt; 3492f3ab15Sopenharmony_ciuse std::ptr; 3592f3ab15Sopenharmony_ciuse std::slice; 3692f3ab15Sopenharmony_ciuse std::str; 3792f3ab15Sopenharmony_ci 3892f3ab15Sopenharmony_ciuse crate::bio::MemBio; 3992f3ab15Sopenharmony_ciuse crate::bn::{BigNum, BigNumRef}; 4092f3ab15Sopenharmony_ciuse crate::error::ErrorStack; 4192f3ab15Sopenharmony_ciuse crate::nid::Nid; 4292f3ab15Sopenharmony_ciuse crate::stack::Stackable; 4392f3ab15Sopenharmony_ciuse crate::string::OpensslString; 4492f3ab15Sopenharmony_ciuse crate::{cvt, cvt_p}; 4592f3ab15Sopenharmony_ciuse openssl_macros::corresponds; 4692f3ab15Sopenharmony_ci 4792f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! { 4892f3ab15Sopenharmony_ci type CType = ffi::ASN1_GENERALIZEDTIME; 4992f3ab15Sopenharmony_ci fn drop = ffi::ASN1_GENERALIZEDTIME_free; 5092f3ab15Sopenharmony_ci 5192f3ab15Sopenharmony_ci /// Non-UTC representation of time 5292f3ab15Sopenharmony_ci /// 5392f3ab15Sopenharmony_ci /// If a time can be represented by UTCTime, UTCTime is used 5492f3ab15Sopenharmony_ci /// otherwise, ASN1_GENERALIZEDTIME is used. This would be, for 5592f3ab15Sopenharmony_ci /// example outside the year range of 1950-2049. 5692f3ab15Sopenharmony_ci /// 5792f3ab15Sopenharmony_ci /// [ASN1_GENERALIZEDTIME_set] documentation from OpenSSL provides 5892f3ab15Sopenharmony_ci /// further details of implementation. Note: these docs are from the master 5992f3ab15Sopenharmony_ci /// branch as documentation on the 1.1.0 branch did not include this page. 6092f3ab15Sopenharmony_ci /// 6192f3ab15Sopenharmony_ci /// [ASN1_GENERALIZEDTIME_set]: https://www.openssl.org/docs/manmaster/man3/ASN1_GENERALIZEDTIME_set.html 6292f3ab15Sopenharmony_ci pub struct Asn1GeneralizedTime; 6392f3ab15Sopenharmony_ci /// Reference to a [`Asn1GeneralizedTime`] 6492f3ab15Sopenharmony_ci /// 6592f3ab15Sopenharmony_ci /// [`Asn1GeneralizedTime`]: struct.Asn1GeneralizedTime.html 6692f3ab15Sopenharmony_ci pub struct Asn1GeneralizedTimeRef; 6792f3ab15Sopenharmony_ci} 6892f3ab15Sopenharmony_ci 6992f3ab15Sopenharmony_ciimpl fmt::Display for Asn1GeneralizedTimeRef { 7092f3ab15Sopenharmony_ci fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 7192f3ab15Sopenharmony_ci unsafe { 7292f3ab15Sopenharmony_ci let mem_bio = match MemBio::new() { 7392f3ab15Sopenharmony_ci Err(_) => return f.write_str("error"), 7492f3ab15Sopenharmony_ci Ok(m) => m, 7592f3ab15Sopenharmony_ci }; 7692f3ab15Sopenharmony_ci let print_result = cvt(ffi::ASN1_GENERALIZEDTIME_print( 7792f3ab15Sopenharmony_ci mem_bio.as_ptr(), 7892f3ab15Sopenharmony_ci self.as_ptr(), 7992f3ab15Sopenharmony_ci )); 8092f3ab15Sopenharmony_ci match print_result { 8192f3ab15Sopenharmony_ci Err(_) => f.write_str("error"), 8292f3ab15Sopenharmony_ci Ok(_) => f.write_str(str::from_utf8_unchecked(mem_bio.get_buf())), 8392f3ab15Sopenharmony_ci } 8492f3ab15Sopenharmony_ci } 8592f3ab15Sopenharmony_ci } 8692f3ab15Sopenharmony_ci} 8792f3ab15Sopenharmony_ci 8892f3ab15Sopenharmony_ci/// The type of an ASN.1 value. 8992f3ab15Sopenharmony_ci#[derive(Debug, Copy, Clone, PartialEq, Eq)] 9092f3ab15Sopenharmony_cipub struct Asn1Type(c_int); 9192f3ab15Sopenharmony_ci 9292f3ab15Sopenharmony_ci#[allow(missing_docs)] // no need to document the constants 9392f3ab15Sopenharmony_ciimpl Asn1Type { 9492f3ab15Sopenharmony_ci pub const EOC: Asn1Type = Asn1Type(ffi::V_ASN1_EOC); 9592f3ab15Sopenharmony_ci 9692f3ab15Sopenharmony_ci pub const BOOLEAN: Asn1Type = Asn1Type(ffi::V_ASN1_BOOLEAN); 9792f3ab15Sopenharmony_ci 9892f3ab15Sopenharmony_ci pub const INTEGER: Asn1Type = Asn1Type(ffi::V_ASN1_INTEGER); 9992f3ab15Sopenharmony_ci 10092f3ab15Sopenharmony_ci pub const BIT_STRING: Asn1Type = Asn1Type(ffi::V_ASN1_BIT_STRING); 10192f3ab15Sopenharmony_ci 10292f3ab15Sopenharmony_ci pub const OCTET_STRING: Asn1Type = Asn1Type(ffi::V_ASN1_OCTET_STRING); 10392f3ab15Sopenharmony_ci 10492f3ab15Sopenharmony_ci pub const NULL: Asn1Type = Asn1Type(ffi::V_ASN1_NULL); 10592f3ab15Sopenharmony_ci 10692f3ab15Sopenharmony_ci pub const OBJECT: Asn1Type = Asn1Type(ffi::V_ASN1_OBJECT); 10792f3ab15Sopenharmony_ci 10892f3ab15Sopenharmony_ci pub const OBJECT_DESCRIPTOR: Asn1Type = Asn1Type(ffi::V_ASN1_OBJECT_DESCRIPTOR); 10992f3ab15Sopenharmony_ci 11092f3ab15Sopenharmony_ci pub const EXTERNAL: Asn1Type = Asn1Type(ffi::V_ASN1_EXTERNAL); 11192f3ab15Sopenharmony_ci 11292f3ab15Sopenharmony_ci pub const REAL: Asn1Type = Asn1Type(ffi::V_ASN1_REAL); 11392f3ab15Sopenharmony_ci 11492f3ab15Sopenharmony_ci pub const ENUMERATED: Asn1Type = Asn1Type(ffi::V_ASN1_ENUMERATED); 11592f3ab15Sopenharmony_ci 11692f3ab15Sopenharmony_ci pub const UTF8STRING: Asn1Type = Asn1Type(ffi::V_ASN1_UTF8STRING); 11792f3ab15Sopenharmony_ci 11892f3ab15Sopenharmony_ci pub const SEQUENCE: Asn1Type = Asn1Type(ffi::V_ASN1_SEQUENCE); 11992f3ab15Sopenharmony_ci 12092f3ab15Sopenharmony_ci pub const SET: Asn1Type = Asn1Type(ffi::V_ASN1_SET); 12192f3ab15Sopenharmony_ci 12292f3ab15Sopenharmony_ci pub const NUMERICSTRING: Asn1Type = Asn1Type(ffi::V_ASN1_NUMERICSTRING); 12392f3ab15Sopenharmony_ci 12492f3ab15Sopenharmony_ci pub const PRINTABLESTRING: Asn1Type = Asn1Type(ffi::V_ASN1_PRINTABLESTRING); 12592f3ab15Sopenharmony_ci 12692f3ab15Sopenharmony_ci pub const T61STRING: Asn1Type = Asn1Type(ffi::V_ASN1_T61STRING); 12792f3ab15Sopenharmony_ci 12892f3ab15Sopenharmony_ci pub const TELETEXSTRING: Asn1Type = Asn1Type(ffi::V_ASN1_TELETEXSTRING); 12992f3ab15Sopenharmony_ci 13092f3ab15Sopenharmony_ci pub const VIDEOTEXSTRING: Asn1Type = Asn1Type(ffi::V_ASN1_VIDEOTEXSTRING); 13192f3ab15Sopenharmony_ci 13292f3ab15Sopenharmony_ci pub const IA5STRING: Asn1Type = Asn1Type(ffi::V_ASN1_IA5STRING); 13392f3ab15Sopenharmony_ci 13492f3ab15Sopenharmony_ci pub const UTCTIME: Asn1Type = Asn1Type(ffi::V_ASN1_UTCTIME); 13592f3ab15Sopenharmony_ci 13692f3ab15Sopenharmony_ci pub const GENERALIZEDTIME: Asn1Type = Asn1Type(ffi::V_ASN1_GENERALIZEDTIME); 13792f3ab15Sopenharmony_ci 13892f3ab15Sopenharmony_ci pub const GRAPHICSTRING: Asn1Type = Asn1Type(ffi::V_ASN1_GRAPHICSTRING); 13992f3ab15Sopenharmony_ci 14092f3ab15Sopenharmony_ci pub const ISO64STRING: Asn1Type = Asn1Type(ffi::V_ASN1_ISO64STRING); 14192f3ab15Sopenharmony_ci 14292f3ab15Sopenharmony_ci pub const VISIBLESTRING: Asn1Type = Asn1Type(ffi::V_ASN1_VISIBLESTRING); 14392f3ab15Sopenharmony_ci 14492f3ab15Sopenharmony_ci pub const GENERALSTRING: Asn1Type = Asn1Type(ffi::V_ASN1_GENERALSTRING); 14592f3ab15Sopenharmony_ci 14692f3ab15Sopenharmony_ci pub const UNIVERSALSTRING: Asn1Type = Asn1Type(ffi::V_ASN1_UNIVERSALSTRING); 14792f3ab15Sopenharmony_ci 14892f3ab15Sopenharmony_ci pub const BMPSTRING: Asn1Type = Asn1Type(ffi::V_ASN1_BMPSTRING); 14992f3ab15Sopenharmony_ci 15092f3ab15Sopenharmony_ci /// Constructs an `Asn1Type` from a raw OpenSSL value. 15192f3ab15Sopenharmony_ci pub fn from_raw(value: c_int) -> Self { 15292f3ab15Sopenharmony_ci Asn1Type(value) 15392f3ab15Sopenharmony_ci } 15492f3ab15Sopenharmony_ci 15592f3ab15Sopenharmony_ci /// Returns the raw OpenSSL value represented by this type. 15692f3ab15Sopenharmony_ci pub fn as_raw(&self) -> c_int { 15792f3ab15Sopenharmony_ci self.0 15892f3ab15Sopenharmony_ci } 15992f3ab15Sopenharmony_ci} 16092f3ab15Sopenharmony_ci 16192f3ab15Sopenharmony_ci/// Difference between two ASN1 times. 16292f3ab15Sopenharmony_ci/// 16392f3ab15Sopenharmony_ci/// This `struct` is created by the [`diff`] method on [`Asn1TimeRef`]. See its 16492f3ab15Sopenharmony_ci/// documentation for more. 16592f3ab15Sopenharmony_ci/// 16692f3ab15Sopenharmony_ci/// [`diff`]: struct.Asn1TimeRef.html#method.diff 16792f3ab15Sopenharmony_ci/// [`Asn1TimeRef`]: struct.Asn1TimeRef.html 16892f3ab15Sopenharmony_ci#[derive(Debug, Clone, PartialEq, Eq, Hash)] 16992f3ab15Sopenharmony_ci#[cfg(ossl102)] 17092f3ab15Sopenharmony_cipub struct TimeDiff { 17192f3ab15Sopenharmony_ci /// Difference in days 17292f3ab15Sopenharmony_ci pub days: c_int, 17392f3ab15Sopenharmony_ci /// Difference in seconds. 17492f3ab15Sopenharmony_ci /// 17592f3ab15Sopenharmony_ci /// This is always less than the number of seconds in a day. 17692f3ab15Sopenharmony_ci pub secs: c_int, 17792f3ab15Sopenharmony_ci} 17892f3ab15Sopenharmony_ci 17992f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! { 18092f3ab15Sopenharmony_ci type CType = ffi::ASN1_TIME; 18192f3ab15Sopenharmony_ci fn drop = ffi::ASN1_TIME_free; 18292f3ab15Sopenharmony_ci /// Time storage and comparison 18392f3ab15Sopenharmony_ci /// 18492f3ab15Sopenharmony_ci /// Asn1Time should be used to store and share time information 18592f3ab15Sopenharmony_ci /// using certificates. If Asn1Time is set using a string, it must 18692f3ab15Sopenharmony_ci /// be in either YYMMDDHHMMSSZ, YYYYMMDDHHMMSSZ, or another ASN.1 format. 18792f3ab15Sopenharmony_ci /// 18892f3ab15Sopenharmony_ci /// [ASN_TIME_set] documentation at OpenSSL explains the ASN.1 implementation 18992f3ab15Sopenharmony_ci /// used by OpenSSL. 19092f3ab15Sopenharmony_ci /// 19192f3ab15Sopenharmony_ci /// [ASN_TIME_set]: https://www.openssl.org/docs/manmaster/crypto/ASN1_TIME_set.html 19292f3ab15Sopenharmony_ci pub struct Asn1Time; 19392f3ab15Sopenharmony_ci /// Reference to an [`Asn1Time`] 19492f3ab15Sopenharmony_ci /// 19592f3ab15Sopenharmony_ci /// [`Asn1Time`]: struct.Asn1Time.html 19692f3ab15Sopenharmony_ci pub struct Asn1TimeRef; 19792f3ab15Sopenharmony_ci} 19892f3ab15Sopenharmony_ci 19992f3ab15Sopenharmony_ciimpl Asn1TimeRef { 20092f3ab15Sopenharmony_ci /// Find difference between two times 20192f3ab15Sopenharmony_ci #[corresponds(ASN1_TIME_diff)] 20292f3ab15Sopenharmony_ci #[cfg(ossl102)] 20392f3ab15Sopenharmony_ci pub fn diff(&self, compare: &Self) -> Result<TimeDiff, ErrorStack> { 20492f3ab15Sopenharmony_ci let mut days = 0; 20592f3ab15Sopenharmony_ci let mut secs = 0; 20692f3ab15Sopenharmony_ci let other = compare.as_ptr(); 20792f3ab15Sopenharmony_ci 20892f3ab15Sopenharmony_ci let err = unsafe { ffi::ASN1_TIME_diff(&mut days, &mut secs, self.as_ptr(), other) }; 20992f3ab15Sopenharmony_ci 21092f3ab15Sopenharmony_ci match err { 21192f3ab15Sopenharmony_ci 0 => Err(ErrorStack::get()), 21292f3ab15Sopenharmony_ci _ => Ok(TimeDiff { days, secs }), 21392f3ab15Sopenharmony_ci } 21492f3ab15Sopenharmony_ci } 21592f3ab15Sopenharmony_ci 21692f3ab15Sopenharmony_ci /// Compare two times 21792f3ab15Sopenharmony_ci #[corresponds(ASN1_TIME_compare)] 21892f3ab15Sopenharmony_ci #[cfg(ossl102)] 21992f3ab15Sopenharmony_ci pub fn compare(&self, other: &Self) -> Result<Ordering, ErrorStack> { 22092f3ab15Sopenharmony_ci let d = self.diff(other)?; 22192f3ab15Sopenharmony_ci if d.days > 0 || d.secs > 0 { 22292f3ab15Sopenharmony_ci return Ok(Ordering::Less); 22392f3ab15Sopenharmony_ci } 22492f3ab15Sopenharmony_ci if d.days < 0 || d.secs < 0 { 22592f3ab15Sopenharmony_ci return Ok(Ordering::Greater); 22692f3ab15Sopenharmony_ci } 22792f3ab15Sopenharmony_ci 22892f3ab15Sopenharmony_ci Ok(Ordering::Equal) 22992f3ab15Sopenharmony_ci } 23092f3ab15Sopenharmony_ci} 23192f3ab15Sopenharmony_ci 23292f3ab15Sopenharmony_ci#[cfg(ossl102)] 23392f3ab15Sopenharmony_ciimpl PartialEq for Asn1TimeRef { 23492f3ab15Sopenharmony_ci fn eq(&self, other: &Asn1TimeRef) -> bool { 23592f3ab15Sopenharmony_ci self.diff(other) 23692f3ab15Sopenharmony_ci .map(|t| t.days == 0 && t.secs == 0) 23792f3ab15Sopenharmony_ci .unwrap_or(false) 23892f3ab15Sopenharmony_ci } 23992f3ab15Sopenharmony_ci} 24092f3ab15Sopenharmony_ci 24192f3ab15Sopenharmony_ci#[cfg(ossl102)] 24292f3ab15Sopenharmony_ciimpl PartialEq<Asn1Time> for Asn1TimeRef { 24392f3ab15Sopenharmony_ci fn eq(&self, other: &Asn1Time) -> bool { 24492f3ab15Sopenharmony_ci self.diff(other) 24592f3ab15Sopenharmony_ci .map(|t| t.days == 0 && t.secs == 0) 24692f3ab15Sopenharmony_ci .unwrap_or(false) 24792f3ab15Sopenharmony_ci } 24892f3ab15Sopenharmony_ci} 24992f3ab15Sopenharmony_ci 25092f3ab15Sopenharmony_ci#[cfg(ossl102)] 25192f3ab15Sopenharmony_ciimpl<'a> PartialEq<Asn1Time> for &'a Asn1TimeRef { 25292f3ab15Sopenharmony_ci fn eq(&self, other: &Asn1Time) -> bool { 25392f3ab15Sopenharmony_ci self.diff(other) 25492f3ab15Sopenharmony_ci .map(|t| t.days == 0 && t.secs == 0) 25592f3ab15Sopenharmony_ci .unwrap_or(false) 25692f3ab15Sopenharmony_ci } 25792f3ab15Sopenharmony_ci} 25892f3ab15Sopenharmony_ci 25992f3ab15Sopenharmony_ci#[cfg(ossl102)] 26092f3ab15Sopenharmony_ciimpl PartialOrd for Asn1TimeRef { 26192f3ab15Sopenharmony_ci fn partial_cmp(&self, other: &Asn1TimeRef) -> Option<Ordering> { 26292f3ab15Sopenharmony_ci self.compare(other).ok() 26392f3ab15Sopenharmony_ci } 26492f3ab15Sopenharmony_ci} 26592f3ab15Sopenharmony_ci 26692f3ab15Sopenharmony_ci#[cfg(ossl102)] 26792f3ab15Sopenharmony_ciimpl PartialOrd<Asn1Time> for Asn1TimeRef { 26892f3ab15Sopenharmony_ci fn partial_cmp(&self, other: &Asn1Time) -> Option<Ordering> { 26992f3ab15Sopenharmony_ci self.compare(other).ok() 27092f3ab15Sopenharmony_ci } 27192f3ab15Sopenharmony_ci} 27292f3ab15Sopenharmony_ci 27392f3ab15Sopenharmony_ci#[cfg(ossl102)] 27492f3ab15Sopenharmony_ciimpl<'a> PartialOrd<Asn1Time> for &'a Asn1TimeRef { 27592f3ab15Sopenharmony_ci fn partial_cmp(&self, other: &Asn1Time) -> Option<Ordering> { 27692f3ab15Sopenharmony_ci self.compare(other).ok() 27792f3ab15Sopenharmony_ci } 27892f3ab15Sopenharmony_ci} 27992f3ab15Sopenharmony_ci 28092f3ab15Sopenharmony_ciimpl fmt::Display for Asn1TimeRef { 28192f3ab15Sopenharmony_ci fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 28292f3ab15Sopenharmony_ci unsafe { 28392f3ab15Sopenharmony_ci let mem_bio = match MemBio::new() { 28492f3ab15Sopenharmony_ci Err(_) => return f.write_str("error"), 28592f3ab15Sopenharmony_ci Ok(m) => m, 28692f3ab15Sopenharmony_ci }; 28792f3ab15Sopenharmony_ci let print_result = cvt(ffi::ASN1_TIME_print(mem_bio.as_ptr(), self.as_ptr())); 28892f3ab15Sopenharmony_ci match print_result { 28992f3ab15Sopenharmony_ci Err(_) => f.write_str("error"), 29092f3ab15Sopenharmony_ci Ok(_) => f.write_str(str::from_utf8_unchecked(mem_bio.get_buf())), 29192f3ab15Sopenharmony_ci } 29292f3ab15Sopenharmony_ci } 29392f3ab15Sopenharmony_ci } 29492f3ab15Sopenharmony_ci} 29592f3ab15Sopenharmony_ci 29692f3ab15Sopenharmony_ciimpl fmt::Debug for Asn1TimeRef { 29792f3ab15Sopenharmony_ci fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 29892f3ab15Sopenharmony_ci f.write_str(&self.to_string()) 29992f3ab15Sopenharmony_ci } 30092f3ab15Sopenharmony_ci} 30192f3ab15Sopenharmony_ci 30292f3ab15Sopenharmony_ciimpl Asn1Time { 30392f3ab15Sopenharmony_ci #[corresponds(ASN1_TIME_new)] 30492f3ab15Sopenharmony_ci fn new() -> Result<Asn1Time, ErrorStack> { 30592f3ab15Sopenharmony_ci ffi::init(); 30692f3ab15Sopenharmony_ci 30792f3ab15Sopenharmony_ci unsafe { 30892f3ab15Sopenharmony_ci let handle = cvt_p(ffi::ASN1_TIME_new())?; 30992f3ab15Sopenharmony_ci Ok(Asn1Time::from_ptr(handle)) 31092f3ab15Sopenharmony_ci } 31192f3ab15Sopenharmony_ci } 31292f3ab15Sopenharmony_ci 31392f3ab15Sopenharmony_ci #[corresponds(X509_gmtime_adj)] 31492f3ab15Sopenharmony_ci fn from_period(period: c_long) -> Result<Asn1Time, ErrorStack> { 31592f3ab15Sopenharmony_ci ffi::init(); 31692f3ab15Sopenharmony_ci 31792f3ab15Sopenharmony_ci unsafe { 31892f3ab15Sopenharmony_ci let handle = cvt_p(ffi::X509_gmtime_adj(ptr::null_mut(), period))?; 31992f3ab15Sopenharmony_ci Ok(Asn1Time::from_ptr(handle)) 32092f3ab15Sopenharmony_ci } 32192f3ab15Sopenharmony_ci } 32292f3ab15Sopenharmony_ci 32392f3ab15Sopenharmony_ci /// Creates a new time on specified interval in days from now 32492f3ab15Sopenharmony_ci pub fn days_from_now(days: u32) -> Result<Asn1Time, ErrorStack> { 32592f3ab15Sopenharmony_ci Asn1Time::from_period(days as c_long * 60 * 60 * 24) 32692f3ab15Sopenharmony_ci } 32792f3ab15Sopenharmony_ci 32892f3ab15Sopenharmony_ci /// Creates a new time from the specified `time_t` value 32992f3ab15Sopenharmony_ci #[corresponds(ASN1_TIME_set)] 33092f3ab15Sopenharmony_ci pub fn from_unix(time: time_t) -> Result<Asn1Time, ErrorStack> { 33192f3ab15Sopenharmony_ci ffi::init(); 33292f3ab15Sopenharmony_ci 33392f3ab15Sopenharmony_ci unsafe { 33492f3ab15Sopenharmony_ci let handle = cvt_p(ffi::ASN1_TIME_set(ptr::null_mut(), time))?; 33592f3ab15Sopenharmony_ci Ok(Asn1Time::from_ptr(handle)) 33692f3ab15Sopenharmony_ci } 33792f3ab15Sopenharmony_ci } 33892f3ab15Sopenharmony_ci 33992f3ab15Sopenharmony_ci /// Creates a new time corresponding to the specified ASN1 time string. 34092f3ab15Sopenharmony_ci #[corresponds(ASN1_TIME_set_string)] 34192f3ab15Sopenharmony_ci #[allow(clippy::should_implement_trait)] 34292f3ab15Sopenharmony_ci pub fn from_str(s: &str) -> Result<Asn1Time, ErrorStack> { 34392f3ab15Sopenharmony_ci unsafe { 34492f3ab15Sopenharmony_ci let s = CString::new(s).unwrap(); 34592f3ab15Sopenharmony_ci 34692f3ab15Sopenharmony_ci let time = Asn1Time::new()?; 34792f3ab15Sopenharmony_ci cvt(ffi::ASN1_TIME_set_string(time.as_ptr(), s.as_ptr()))?; 34892f3ab15Sopenharmony_ci 34992f3ab15Sopenharmony_ci Ok(time) 35092f3ab15Sopenharmony_ci } 35192f3ab15Sopenharmony_ci } 35292f3ab15Sopenharmony_ci 35392f3ab15Sopenharmony_ci /// Creates a new time corresponding to the specified X509 time string. 35492f3ab15Sopenharmony_ci /// 35592f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or newer. 35692f3ab15Sopenharmony_ci #[corresponds(ASN1_TIME_set_string_X509)] 35792f3ab15Sopenharmony_ci #[cfg(ossl111)] 35892f3ab15Sopenharmony_ci pub fn from_str_x509(s: &str) -> Result<Asn1Time, ErrorStack> { 35992f3ab15Sopenharmony_ci unsafe { 36092f3ab15Sopenharmony_ci let s = CString::new(s).unwrap(); 36192f3ab15Sopenharmony_ci 36292f3ab15Sopenharmony_ci let time = Asn1Time::new()?; 36392f3ab15Sopenharmony_ci cvt(ffi::ASN1_TIME_set_string_X509(time.as_ptr(), s.as_ptr()))?; 36492f3ab15Sopenharmony_ci 36592f3ab15Sopenharmony_ci Ok(time) 36692f3ab15Sopenharmony_ci } 36792f3ab15Sopenharmony_ci } 36892f3ab15Sopenharmony_ci} 36992f3ab15Sopenharmony_ci 37092f3ab15Sopenharmony_ci#[cfg(ossl102)] 37192f3ab15Sopenharmony_ciimpl PartialEq for Asn1Time { 37292f3ab15Sopenharmony_ci fn eq(&self, other: &Asn1Time) -> bool { 37392f3ab15Sopenharmony_ci self.diff(other) 37492f3ab15Sopenharmony_ci .map(|t| t.days == 0 && t.secs == 0) 37592f3ab15Sopenharmony_ci .unwrap_or(false) 37692f3ab15Sopenharmony_ci } 37792f3ab15Sopenharmony_ci} 37892f3ab15Sopenharmony_ci 37992f3ab15Sopenharmony_ci#[cfg(ossl102)] 38092f3ab15Sopenharmony_ciimpl PartialEq<Asn1TimeRef> for Asn1Time { 38192f3ab15Sopenharmony_ci fn eq(&self, other: &Asn1TimeRef) -> bool { 38292f3ab15Sopenharmony_ci self.diff(other) 38392f3ab15Sopenharmony_ci .map(|t| t.days == 0 && t.secs == 0) 38492f3ab15Sopenharmony_ci .unwrap_or(false) 38592f3ab15Sopenharmony_ci } 38692f3ab15Sopenharmony_ci} 38792f3ab15Sopenharmony_ci 38892f3ab15Sopenharmony_ci#[cfg(ossl102)] 38992f3ab15Sopenharmony_ciimpl<'a> PartialEq<&'a Asn1TimeRef> for Asn1Time { 39092f3ab15Sopenharmony_ci fn eq(&self, other: &&'a Asn1TimeRef) -> bool { 39192f3ab15Sopenharmony_ci self.diff(other) 39292f3ab15Sopenharmony_ci .map(|t| t.days == 0 && t.secs == 0) 39392f3ab15Sopenharmony_ci .unwrap_or(false) 39492f3ab15Sopenharmony_ci } 39592f3ab15Sopenharmony_ci} 39692f3ab15Sopenharmony_ci 39792f3ab15Sopenharmony_ci#[cfg(ossl102)] 39892f3ab15Sopenharmony_ciimpl PartialOrd for Asn1Time { 39992f3ab15Sopenharmony_ci fn partial_cmp(&self, other: &Asn1Time) -> Option<Ordering> { 40092f3ab15Sopenharmony_ci self.compare(other).ok() 40192f3ab15Sopenharmony_ci } 40292f3ab15Sopenharmony_ci} 40392f3ab15Sopenharmony_ci 40492f3ab15Sopenharmony_ci#[cfg(ossl102)] 40592f3ab15Sopenharmony_ciimpl PartialOrd<Asn1TimeRef> for Asn1Time { 40692f3ab15Sopenharmony_ci fn partial_cmp(&self, other: &Asn1TimeRef) -> Option<Ordering> { 40792f3ab15Sopenharmony_ci self.compare(other).ok() 40892f3ab15Sopenharmony_ci } 40992f3ab15Sopenharmony_ci} 41092f3ab15Sopenharmony_ci 41192f3ab15Sopenharmony_ci#[cfg(ossl102)] 41292f3ab15Sopenharmony_ciimpl<'a> PartialOrd<&'a Asn1TimeRef> for Asn1Time { 41392f3ab15Sopenharmony_ci fn partial_cmp(&self, other: &&'a Asn1TimeRef) -> Option<Ordering> { 41492f3ab15Sopenharmony_ci self.compare(other).ok() 41592f3ab15Sopenharmony_ci } 41692f3ab15Sopenharmony_ci} 41792f3ab15Sopenharmony_ci 41892f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! { 41992f3ab15Sopenharmony_ci type CType = ffi::ASN1_STRING; 42092f3ab15Sopenharmony_ci fn drop = ffi::ASN1_STRING_free; 42192f3ab15Sopenharmony_ci /// Primary ASN.1 type used by OpenSSL 42292f3ab15Sopenharmony_ci /// 42392f3ab15Sopenharmony_ci /// Almost all ASN.1 types in OpenSSL are represented by ASN1_STRING 42492f3ab15Sopenharmony_ci /// structures. This implementation uses [ASN1_STRING-to_UTF8] to preserve 42592f3ab15Sopenharmony_ci /// compatibility with Rust's String. 42692f3ab15Sopenharmony_ci /// 42792f3ab15Sopenharmony_ci /// [ASN1_STRING-to_UTF8]: https://www.openssl.org/docs/manmaster/crypto/ASN1_STRING_to_UTF8.html 42892f3ab15Sopenharmony_ci pub struct Asn1String; 42992f3ab15Sopenharmony_ci /// A reference to an [`Asn1String`]. 43092f3ab15Sopenharmony_ci pub struct Asn1StringRef; 43192f3ab15Sopenharmony_ci} 43292f3ab15Sopenharmony_ci 43392f3ab15Sopenharmony_ciimpl Asn1StringRef { 43492f3ab15Sopenharmony_ci /// Converts the ASN.1 underlying format to UTF8 43592f3ab15Sopenharmony_ci /// 43692f3ab15Sopenharmony_ci /// ASN.1 strings may utilize UTF-16, ASCII, BMP, or UTF8. This is important to 43792f3ab15Sopenharmony_ci /// consume the string in a meaningful way without knowing the underlying 43892f3ab15Sopenharmony_ci /// format. 43992f3ab15Sopenharmony_ci #[corresponds(ASN1_STRING_to_UTF8)] 44092f3ab15Sopenharmony_ci pub fn as_utf8(&self) -> Result<OpensslString, ErrorStack> { 44192f3ab15Sopenharmony_ci unsafe { 44292f3ab15Sopenharmony_ci let mut ptr = ptr::null_mut(); 44392f3ab15Sopenharmony_ci let len = ffi::ASN1_STRING_to_UTF8(&mut ptr, self.as_ptr()); 44492f3ab15Sopenharmony_ci if len < 0 { 44592f3ab15Sopenharmony_ci return Err(ErrorStack::get()); 44692f3ab15Sopenharmony_ci } 44792f3ab15Sopenharmony_ci 44892f3ab15Sopenharmony_ci Ok(OpensslString::from_ptr(ptr as *mut c_char)) 44992f3ab15Sopenharmony_ci } 45092f3ab15Sopenharmony_ci } 45192f3ab15Sopenharmony_ci 45292f3ab15Sopenharmony_ci /// Return the string as an array of bytes. 45392f3ab15Sopenharmony_ci /// 45492f3ab15Sopenharmony_ci /// The bytes do not directly correspond to UTF-8 encoding. To interact with 45592f3ab15Sopenharmony_ci /// strings in rust, it is preferable to use [`as_utf8`] 45692f3ab15Sopenharmony_ci /// 45792f3ab15Sopenharmony_ci /// [`as_utf8`]: struct.Asn1String.html#method.as_utf8 45892f3ab15Sopenharmony_ci #[corresponds(ASN1_STRING_get0_data)] 45992f3ab15Sopenharmony_ci pub fn as_slice(&self) -> &[u8] { 46092f3ab15Sopenharmony_ci unsafe { slice::from_raw_parts(ASN1_STRING_get0_data(self.as_ptr()), self.len()) } 46192f3ab15Sopenharmony_ci } 46292f3ab15Sopenharmony_ci 46392f3ab15Sopenharmony_ci /// Returns the number of bytes in the string. 46492f3ab15Sopenharmony_ci #[corresponds(ASN1_STRING_length)] 46592f3ab15Sopenharmony_ci pub fn len(&self) -> usize { 46692f3ab15Sopenharmony_ci unsafe { ffi::ASN1_STRING_length(self.as_ptr()) as usize } 46792f3ab15Sopenharmony_ci } 46892f3ab15Sopenharmony_ci 46992f3ab15Sopenharmony_ci /// Determines if the string is empty. 47092f3ab15Sopenharmony_ci pub fn is_empty(&self) -> bool { 47192f3ab15Sopenharmony_ci self.len() == 0 47292f3ab15Sopenharmony_ci } 47392f3ab15Sopenharmony_ci} 47492f3ab15Sopenharmony_ci 47592f3ab15Sopenharmony_ciimpl fmt::Debug for Asn1StringRef { 47692f3ab15Sopenharmony_ci fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 47792f3ab15Sopenharmony_ci match self.as_utf8() { 47892f3ab15Sopenharmony_ci Ok(openssl_string) => openssl_string.fmt(fmt), 47992f3ab15Sopenharmony_ci Err(_) => fmt.write_str("error"), 48092f3ab15Sopenharmony_ci } 48192f3ab15Sopenharmony_ci } 48292f3ab15Sopenharmony_ci} 48392f3ab15Sopenharmony_ci 48492f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! { 48592f3ab15Sopenharmony_ci type CType = ffi::ASN1_INTEGER; 48692f3ab15Sopenharmony_ci fn drop = ffi::ASN1_INTEGER_free; 48792f3ab15Sopenharmony_ci 48892f3ab15Sopenharmony_ci /// Numeric representation 48992f3ab15Sopenharmony_ci /// 49092f3ab15Sopenharmony_ci /// Integers in ASN.1 may include BigNum, int64 or uint64. BigNum implementation 49192f3ab15Sopenharmony_ci /// can be found within [`bn`] module. 49292f3ab15Sopenharmony_ci /// 49392f3ab15Sopenharmony_ci /// OpenSSL documentation includes [`ASN1_INTEGER_set`]. 49492f3ab15Sopenharmony_ci /// 49592f3ab15Sopenharmony_ci /// [`bn`]: ../bn/index.html 49692f3ab15Sopenharmony_ci /// [`ASN1_INTEGER_set`]: https://www.openssl.org/docs/manmaster/crypto/ASN1_INTEGER_set.html 49792f3ab15Sopenharmony_ci pub struct Asn1Integer; 49892f3ab15Sopenharmony_ci /// A reference to an [`Asn1Integer`]. 49992f3ab15Sopenharmony_ci pub struct Asn1IntegerRef; 50092f3ab15Sopenharmony_ci} 50192f3ab15Sopenharmony_ci 50292f3ab15Sopenharmony_ciimpl Asn1Integer { 50392f3ab15Sopenharmony_ci /// Converts a bignum to an `Asn1Integer`. 50492f3ab15Sopenharmony_ci /// 50592f3ab15Sopenharmony_ci /// Corresponds to [`BN_to_ASN1_INTEGER`]. Also see 50692f3ab15Sopenharmony_ci /// [`BigNumRef::to_asn1_integer`]. 50792f3ab15Sopenharmony_ci /// 50892f3ab15Sopenharmony_ci /// [`BN_to_ASN1_INTEGER`]: https://www.openssl.org/docs/manmaster/crypto/BN_to_ASN1_INTEGER.html 50992f3ab15Sopenharmony_ci /// [`BigNumRef::to_asn1_integer`]: ../bn/struct.BigNumRef.html#method.to_asn1_integer 51092f3ab15Sopenharmony_ci pub fn from_bn(bn: &BigNumRef) -> Result<Self, ErrorStack> { 51192f3ab15Sopenharmony_ci bn.to_asn1_integer() 51292f3ab15Sopenharmony_ci } 51392f3ab15Sopenharmony_ci} 51492f3ab15Sopenharmony_ci 51592f3ab15Sopenharmony_ciimpl Ord for Asn1Integer { 51692f3ab15Sopenharmony_ci fn cmp(&self, other: &Self) -> Ordering { 51792f3ab15Sopenharmony_ci Asn1IntegerRef::cmp(self, other) 51892f3ab15Sopenharmony_ci } 51992f3ab15Sopenharmony_ci} 52092f3ab15Sopenharmony_ciimpl PartialOrd for Asn1Integer { 52192f3ab15Sopenharmony_ci fn partial_cmp(&self, other: &Asn1Integer) -> Option<Ordering> { 52292f3ab15Sopenharmony_ci Some(self.cmp(other)) 52392f3ab15Sopenharmony_ci } 52492f3ab15Sopenharmony_ci} 52592f3ab15Sopenharmony_ciimpl Eq for Asn1Integer {} 52692f3ab15Sopenharmony_ciimpl PartialEq for Asn1Integer { 52792f3ab15Sopenharmony_ci fn eq(&self, other: &Asn1Integer) -> bool { 52892f3ab15Sopenharmony_ci Asn1IntegerRef::eq(self, other) 52992f3ab15Sopenharmony_ci } 53092f3ab15Sopenharmony_ci} 53192f3ab15Sopenharmony_ci 53292f3ab15Sopenharmony_ciimpl Asn1IntegerRef { 53392f3ab15Sopenharmony_ci #[allow(missing_docs, clippy::unnecessary_cast)] 53492f3ab15Sopenharmony_ci #[deprecated(since = "0.10.6", note = "use to_bn instead")] 53592f3ab15Sopenharmony_ci pub fn get(&self) -> i64 { 53692f3ab15Sopenharmony_ci unsafe { ffi::ASN1_INTEGER_get(self.as_ptr()) as i64 } 53792f3ab15Sopenharmony_ci } 53892f3ab15Sopenharmony_ci 53992f3ab15Sopenharmony_ci /// Converts the integer to a `BigNum`. 54092f3ab15Sopenharmony_ci #[corresponds(ASN1_INTEGER_to_BN)] 54192f3ab15Sopenharmony_ci pub fn to_bn(&self) -> Result<BigNum, ErrorStack> { 54292f3ab15Sopenharmony_ci unsafe { 54392f3ab15Sopenharmony_ci cvt_p(ffi::ASN1_INTEGER_to_BN(self.as_ptr(), ptr::null_mut())) 54492f3ab15Sopenharmony_ci .map(|p| BigNum::from_ptr(p)) 54592f3ab15Sopenharmony_ci } 54692f3ab15Sopenharmony_ci } 54792f3ab15Sopenharmony_ci 54892f3ab15Sopenharmony_ci /// Sets the ASN.1 value to the value of a signed 32-bit integer, for larger numbers 54992f3ab15Sopenharmony_ci /// see [`bn`]. 55092f3ab15Sopenharmony_ci /// 55192f3ab15Sopenharmony_ci /// [`bn`]: ../bn/struct.BigNumRef.html#method.to_asn1_integer 55292f3ab15Sopenharmony_ci #[corresponds(ASN1_INTEGER_set)] 55392f3ab15Sopenharmony_ci pub fn set(&mut self, value: i32) -> Result<(), ErrorStack> { 55492f3ab15Sopenharmony_ci unsafe { cvt(ffi::ASN1_INTEGER_set(self.as_ptr(), value as c_long)).map(|_| ()) } 55592f3ab15Sopenharmony_ci } 55692f3ab15Sopenharmony_ci 55792f3ab15Sopenharmony_ci /// Creates a new Asn1Integer with the same value. 55892f3ab15Sopenharmony_ci #[corresponds(ASN1_INTEGER_dup)] 55992f3ab15Sopenharmony_ci pub fn to_owned(&self) -> Result<Asn1Integer, ErrorStack> { 56092f3ab15Sopenharmony_ci unsafe { cvt_p(ffi::ASN1_INTEGER_dup(self.as_ptr())).map(|p| Asn1Integer::from_ptr(p)) } 56192f3ab15Sopenharmony_ci } 56292f3ab15Sopenharmony_ci} 56392f3ab15Sopenharmony_ci 56492f3ab15Sopenharmony_ciimpl Ord for Asn1IntegerRef { 56592f3ab15Sopenharmony_ci fn cmp(&self, other: &Self) -> Ordering { 56692f3ab15Sopenharmony_ci let res = unsafe { ffi::ASN1_INTEGER_cmp(self.as_ptr(), other.as_ptr()) }; 56792f3ab15Sopenharmony_ci res.cmp(&0) 56892f3ab15Sopenharmony_ci } 56992f3ab15Sopenharmony_ci} 57092f3ab15Sopenharmony_ciimpl PartialOrd for Asn1IntegerRef { 57192f3ab15Sopenharmony_ci fn partial_cmp(&self, other: &Asn1IntegerRef) -> Option<Ordering> { 57292f3ab15Sopenharmony_ci Some(self.cmp(other)) 57392f3ab15Sopenharmony_ci } 57492f3ab15Sopenharmony_ci} 57592f3ab15Sopenharmony_ciimpl Eq for Asn1IntegerRef {} 57692f3ab15Sopenharmony_ciimpl PartialEq for Asn1IntegerRef { 57792f3ab15Sopenharmony_ci fn eq(&self, other: &Asn1IntegerRef) -> bool { 57892f3ab15Sopenharmony_ci self.cmp(other) == Ordering::Equal 57992f3ab15Sopenharmony_ci } 58092f3ab15Sopenharmony_ci} 58192f3ab15Sopenharmony_ci 58292f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! { 58392f3ab15Sopenharmony_ci type CType = ffi::ASN1_BIT_STRING; 58492f3ab15Sopenharmony_ci fn drop = ffi::ASN1_BIT_STRING_free; 58592f3ab15Sopenharmony_ci /// Sequence of bytes 58692f3ab15Sopenharmony_ci /// 58792f3ab15Sopenharmony_ci /// Asn1BitString is used in [`x509`] certificates for the signature. 58892f3ab15Sopenharmony_ci /// The bit string acts as a collection of bytes. 58992f3ab15Sopenharmony_ci /// 59092f3ab15Sopenharmony_ci /// [`x509`]: ../x509/struct.X509.html#method.signature 59192f3ab15Sopenharmony_ci pub struct Asn1BitString; 59292f3ab15Sopenharmony_ci /// A reference to an [`Asn1BitString`]. 59392f3ab15Sopenharmony_ci pub struct Asn1BitStringRef; 59492f3ab15Sopenharmony_ci} 59592f3ab15Sopenharmony_ci 59692f3ab15Sopenharmony_ciimpl Asn1BitStringRef { 59792f3ab15Sopenharmony_ci /// Returns the Asn1BitString as a slice. 59892f3ab15Sopenharmony_ci #[corresponds(ASN1_STRING_get0_data)] 59992f3ab15Sopenharmony_ci pub fn as_slice(&self) -> &[u8] { 60092f3ab15Sopenharmony_ci unsafe { slice::from_raw_parts(ASN1_STRING_get0_data(self.as_ptr() as *mut _), self.len()) } 60192f3ab15Sopenharmony_ci } 60292f3ab15Sopenharmony_ci 60392f3ab15Sopenharmony_ci /// Returns the number of bytes in the string. 60492f3ab15Sopenharmony_ci #[corresponds(ASN1_STRING_length)] 60592f3ab15Sopenharmony_ci pub fn len(&self) -> usize { 60692f3ab15Sopenharmony_ci unsafe { ffi::ASN1_STRING_length(self.as_ptr() as *const _) as usize } 60792f3ab15Sopenharmony_ci } 60892f3ab15Sopenharmony_ci 60992f3ab15Sopenharmony_ci /// Determines if the string is empty. 61092f3ab15Sopenharmony_ci pub fn is_empty(&self) -> bool { 61192f3ab15Sopenharmony_ci self.len() == 0 61292f3ab15Sopenharmony_ci } 61392f3ab15Sopenharmony_ci} 61492f3ab15Sopenharmony_ci 61592f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! { 61692f3ab15Sopenharmony_ci type CType = ffi::ASN1_OCTET_STRING; 61792f3ab15Sopenharmony_ci fn drop = ffi::ASN1_OCTET_STRING_free; 61892f3ab15Sopenharmony_ci /// ASN.1 OCTET STRING type 61992f3ab15Sopenharmony_ci pub struct Asn1OctetString; 62092f3ab15Sopenharmony_ci /// A reference to an [`Asn1OctetString`]. 62192f3ab15Sopenharmony_ci pub struct Asn1OctetStringRef; 62292f3ab15Sopenharmony_ci} 62392f3ab15Sopenharmony_ci 62492f3ab15Sopenharmony_ciimpl Asn1OctetString { 62592f3ab15Sopenharmony_ci /// Creates an Asn1OctetString from bytes 62692f3ab15Sopenharmony_ci pub fn new_from_bytes(value: &[u8]) -> Result<Self, ErrorStack> { 62792f3ab15Sopenharmony_ci ffi::init(); 62892f3ab15Sopenharmony_ci unsafe { 62992f3ab15Sopenharmony_ci let s = cvt_p(ffi::ASN1_OCTET_STRING_new())?; 63092f3ab15Sopenharmony_ci ffi::ASN1_OCTET_STRING_set(s, value.as_ptr(), value.len().try_into().unwrap()); 63192f3ab15Sopenharmony_ci Ok(Self::from_ptr(s)) 63292f3ab15Sopenharmony_ci } 63392f3ab15Sopenharmony_ci } 63492f3ab15Sopenharmony_ci} 63592f3ab15Sopenharmony_ci 63692f3ab15Sopenharmony_ciimpl Asn1OctetStringRef { 63792f3ab15Sopenharmony_ci /// Returns the octet string as an array of bytes. 63892f3ab15Sopenharmony_ci #[corresponds(ASN1_STRING_get0_data)] 63992f3ab15Sopenharmony_ci pub fn as_slice(&self) -> &[u8] { 64092f3ab15Sopenharmony_ci unsafe { slice::from_raw_parts(ASN1_STRING_get0_data(self.as_ptr().cast()), self.len()) } 64192f3ab15Sopenharmony_ci } 64292f3ab15Sopenharmony_ci 64392f3ab15Sopenharmony_ci /// Returns the number of bytes in the octet string. 64492f3ab15Sopenharmony_ci #[corresponds(ASN1_STRING_length)] 64592f3ab15Sopenharmony_ci pub fn len(&self) -> usize { 64692f3ab15Sopenharmony_ci unsafe { ffi::ASN1_STRING_length(self.as_ptr().cast()) as usize } 64792f3ab15Sopenharmony_ci } 64892f3ab15Sopenharmony_ci 64992f3ab15Sopenharmony_ci /// Determines if the string is empty. 65092f3ab15Sopenharmony_ci pub fn is_empty(&self) -> bool { 65192f3ab15Sopenharmony_ci self.len() == 0 65292f3ab15Sopenharmony_ci } 65392f3ab15Sopenharmony_ci} 65492f3ab15Sopenharmony_ci 65592f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! { 65692f3ab15Sopenharmony_ci type CType = ffi::ASN1_OBJECT; 65792f3ab15Sopenharmony_ci fn drop = ffi::ASN1_OBJECT_free; 65892f3ab15Sopenharmony_ci fn clone = ffi::OBJ_dup; 65992f3ab15Sopenharmony_ci 66092f3ab15Sopenharmony_ci /// Object Identifier 66192f3ab15Sopenharmony_ci /// 66292f3ab15Sopenharmony_ci /// Represents an ASN.1 Object. Typically, NIDs, or numeric identifiers 66392f3ab15Sopenharmony_ci /// are stored as a table within the [`Nid`] module. These constants are 66492f3ab15Sopenharmony_ci /// used to determine attributes of a certificate, such as mapping the 66592f3ab15Sopenharmony_ci /// attribute "CommonName" to "CN" which is represented as the OID of 13. 66692f3ab15Sopenharmony_ci /// This attribute is a constant in the [`nid::COMMONNAME`]. 66792f3ab15Sopenharmony_ci /// 66892f3ab15Sopenharmony_ci /// OpenSSL documentation at [`OBJ_nid2obj`] 66992f3ab15Sopenharmony_ci /// 67092f3ab15Sopenharmony_ci /// [`Nid`]: ../nid/index.html 67192f3ab15Sopenharmony_ci /// [`nid::COMMONNAME`]: ../nid/constant.COMMONNAME.html 67292f3ab15Sopenharmony_ci /// [`OBJ_nid2obj`]: https://www.openssl.org/docs/manmaster/crypto/OBJ_obj2nid.html 67392f3ab15Sopenharmony_ci pub struct Asn1Object; 67492f3ab15Sopenharmony_ci /// A reference to an [`Asn1Object`]. 67592f3ab15Sopenharmony_ci pub struct Asn1ObjectRef; 67692f3ab15Sopenharmony_ci} 67792f3ab15Sopenharmony_ci 67892f3ab15Sopenharmony_ciimpl Stackable for Asn1Object { 67992f3ab15Sopenharmony_ci type StackType = ffi::stack_st_ASN1_OBJECT; 68092f3ab15Sopenharmony_ci} 68192f3ab15Sopenharmony_ci 68292f3ab15Sopenharmony_ciimpl Asn1Object { 68392f3ab15Sopenharmony_ci /// Constructs an ASN.1 Object Identifier from a string representation of the OID. 68492f3ab15Sopenharmony_ci #[corresponds(OBJ_txt2obj)] 68592f3ab15Sopenharmony_ci #[allow(clippy::should_implement_trait)] 68692f3ab15Sopenharmony_ci pub fn from_str(txt: &str) -> Result<Asn1Object, ErrorStack> { 68792f3ab15Sopenharmony_ci unsafe { 68892f3ab15Sopenharmony_ci ffi::init(); 68992f3ab15Sopenharmony_ci let txt = CString::new(txt).unwrap(); 69092f3ab15Sopenharmony_ci let obj: *mut ffi::ASN1_OBJECT = cvt_p(ffi::OBJ_txt2obj(txt.as_ptr() as *const _, 0))?; 69192f3ab15Sopenharmony_ci Ok(Asn1Object::from_ptr(obj)) 69292f3ab15Sopenharmony_ci } 69392f3ab15Sopenharmony_ci } 69492f3ab15Sopenharmony_ci 69592f3ab15Sopenharmony_ci /// Return the OID as an DER encoded array of bytes. This is the ASN.1 69692f3ab15Sopenharmony_ci /// value, not including tag or length. 69792f3ab15Sopenharmony_ci /// 69892f3ab15Sopenharmony_ci /// Requires OpenSSL 1.1.1 or newer. 69992f3ab15Sopenharmony_ci #[corresponds(OBJ_get0_data)] 70092f3ab15Sopenharmony_ci #[cfg(ossl111)] 70192f3ab15Sopenharmony_ci pub fn as_slice(&self) -> &[u8] { 70292f3ab15Sopenharmony_ci unsafe { 70392f3ab15Sopenharmony_ci let len = ffi::OBJ_length(self.as_ptr()); 70492f3ab15Sopenharmony_ci slice::from_raw_parts(ffi::OBJ_get0_data(self.as_ptr()), len) 70592f3ab15Sopenharmony_ci } 70692f3ab15Sopenharmony_ci } 70792f3ab15Sopenharmony_ci} 70892f3ab15Sopenharmony_ci 70992f3ab15Sopenharmony_ciimpl Asn1ObjectRef { 71092f3ab15Sopenharmony_ci /// Returns the NID associated with this OID. 71192f3ab15Sopenharmony_ci pub fn nid(&self) -> Nid { 71292f3ab15Sopenharmony_ci unsafe { Nid::from_raw(ffi::OBJ_obj2nid(self.as_ptr())) } 71392f3ab15Sopenharmony_ci } 71492f3ab15Sopenharmony_ci} 71592f3ab15Sopenharmony_ci 71692f3ab15Sopenharmony_ciimpl fmt::Display for Asn1ObjectRef { 71792f3ab15Sopenharmony_ci fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 71892f3ab15Sopenharmony_ci unsafe { 71992f3ab15Sopenharmony_ci let mut buf = [0; 80]; 72092f3ab15Sopenharmony_ci let len = ffi::OBJ_obj2txt( 72192f3ab15Sopenharmony_ci buf.as_mut_ptr() as *mut _, 72292f3ab15Sopenharmony_ci buf.len() as c_int, 72392f3ab15Sopenharmony_ci self.as_ptr(), 72492f3ab15Sopenharmony_ci 0, 72592f3ab15Sopenharmony_ci ); 72692f3ab15Sopenharmony_ci match str::from_utf8(&buf[..len as usize]) { 72792f3ab15Sopenharmony_ci Err(_) => fmt.write_str("error"), 72892f3ab15Sopenharmony_ci Ok(s) => fmt.write_str(s), 72992f3ab15Sopenharmony_ci } 73092f3ab15Sopenharmony_ci } 73192f3ab15Sopenharmony_ci } 73292f3ab15Sopenharmony_ci} 73392f3ab15Sopenharmony_ci 73492f3ab15Sopenharmony_ciimpl fmt::Debug for Asn1ObjectRef { 73592f3ab15Sopenharmony_ci fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 73692f3ab15Sopenharmony_ci fmt.write_str(self.to_string().as_str()) 73792f3ab15Sopenharmony_ci } 73892f3ab15Sopenharmony_ci} 73992f3ab15Sopenharmony_ci 74092f3ab15Sopenharmony_cicfg_if! { 74192f3ab15Sopenharmony_ci if #[cfg(any(ossl110, libressl273, boringssl))] { 74292f3ab15Sopenharmony_ci use ffi::ASN1_STRING_get0_data; 74392f3ab15Sopenharmony_ci } else { 74492f3ab15Sopenharmony_ci #[allow(bad_style)] 74592f3ab15Sopenharmony_ci unsafe fn ASN1_STRING_get0_data(s: *mut ffi::ASN1_STRING) -> *const ::libc::c_uchar { 74692f3ab15Sopenharmony_ci ffi::ASN1_STRING_data(s) 74792f3ab15Sopenharmony_ci } 74892f3ab15Sopenharmony_ci } 74992f3ab15Sopenharmony_ci} 75092f3ab15Sopenharmony_ci 75192f3ab15Sopenharmony_ciforeign_type_and_impl_send_sync! { 75292f3ab15Sopenharmony_ci type CType = ffi::ASN1_ENUMERATED; 75392f3ab15Sopenharmony_ci fn drop = ffi::ASN1_ENUMERATED_free; 75492f3ab15Sopenharmony_ci 75592f3ab15Sopenharmony_ci /// An ASN.1 enumerated. 75692f3ab15Sopenharmony_ci pub struct Asn1Enumerated; 75792f3ab15Sopenharmony_ci /// A reference to an [`Asn1Enumerated`]. 75892f3ab15Sopenharmony_ci pub struct Asn1EnumeratedRef; 75992f3ab15Sopenharmony_ci} 76092f3ab15Sopenharmony_ci 76192f3ab15Sopenharmony_ciimpl Asn1EnumeratedRef { 76292f3ab15Sopenharmony_ci /// Get the value, if it fits in the required bounds. 76392f3ab15Sopenharmony_ci #[corresponds(ASN1_ENUMERATED_get_int64)] 76492f3ab15Sopenharmony_ci #[cfg(ossl110)] 76592f3ab15Sopenharmony_ci pub fn get_i64(&self) -> Result<i64, ErrorStack> { 76692f3ab15Sopenharmony_ci let mut crl_reason = 0; 76792f3ab15Sopenharmony_ci unsafe { 76892f3ab15Sopenharmony_ci cvt(ffi::ASN1_ENUMERATED_get_int64( 76992f3ab15Sopenharmony_ci &mut crl_reason, 77092f3ab15Sopenharmony_ci self.as_ptr(), 77192f3ab15Sopenharmony_ci ))?; 77292f3ab15Sopenharmony_ci } 77392f3ab15Sopenharmony_ci Ok(crl_reason) 77492f3ab15Sopenharmony_ci } 77592f3ab15Sopenharmony_ci} 77692f3ab15Sopenharmony_ci 77792f3ab15Sopenharmony_ci#[cfg(test)] 77892f3ab15Sopenharmony_cimod tests { 77992f3ab15Sopenharmony_ci use super::*; 78092f3ab15Sopenharmony_ci 78192f3ab15Sopenharmony_ci use crate::bn::BigNum; 78292f3ab15Sopenharmony_ci use crate::nid::Nid; 78392f3ab15Sopenharmony_ci 78492f3ab15Sopenharmony_ci /// Tests conversion between BigNum and Asn1Integer. 78592f3ab15Sopenharmony_ci #[test] 78692f3ab15Sopenharmony_ci fn bn_cvt() { 78792f3ab15Sopenharmony_ci fn roundtrip(bn: BigNum) { 78892f3ab15Sopenharmony_ci let large = Asn1Integer::from_bn(&bn).unwrap(); 78992f3ab15Sopenharmony_ci assert_eq!(large.to_bn().unwrap(), bn); 79092f3ab15Sopenharmony_ci } 79192f3ab15Sopenharmony_ci 79292f3ab15Sopenharmony_ci roundtrip(BigNum::from_dec_str("1000000000000000000000000000000000").unwrap()); 79392f3ab15Sopenharmony_ci roundtrip(-BigNum::from_dec_str("1000000000000000000000000000000000").unwrap()); 79492f3ab15Sopenharmony_ci roundtrip(BigNum::from_u32(1234).unwrap()); 79592f3ab15Sopenharmony_ci roundtrip(-BigNum::from_u32(1234).unwrap()); 79692f3ab15Sopenharmony_ci } 79792f3ab15Sopenharmony_ci 79892f3ab15Sopenharmony_ci #[test] 79992f3ab15Sopenharmony_ci fn time_from_str() { 80092f3ab15Sopenharmony_ci Asn1Time::from_str("99991231235959Z").unwrap(); 80192f3ab15Sopenharmony_ci #[cfg(ossl111)] 80292f3ab15Sopenharmony_ci Asn1Time::from_str_x509("99991231235959Z").unwrap(); 80392f3ab15Sopenharmony_ci } 80492f3ab15Sopenharmony_ci 80592f3ab15Sopenharmony_ci #[test] 80692f3ab15Sopenharmony_ci fn time_from_unix() { 80792f3ab15Sopenharmony_ci let t = Asn1Time::from_unix(0).unwrap(); 80892f3ab15Sopenharmony_ci assert_eq!("Jan 1 00:00:00 1970 GMT", t.to_string()); 80992f3ab15Sopenharmony_ci } 81092f3ab15Sopenharmony_ci 81192f3ab15Sopenharmony_ci #[test] 81292f3ab15Sopenharmony_ci #[cfg(ossl102)] 81392f3ab15Sopenharmony_ci fn time_eq() { 81492f3ab15Sopenharmony_ci let a = Asn1Time::from_str("99991231235959Z").unwrap(); 81592f3ab15Sopenharmony_ci let b = Asn1Time::from_str("99991231235959Z").unwrap(); 81692f3ab15Sopenharmony_ci let c = Asn1Time::from_str("99991231235958Z").unwrap(); 81792f3ab15Sopenharmony_ci let a_ref = a.as_ref(); 81892f3ab15Sopenharmony_ci let b_ref = b.as_ref(); 81992f3ab15Sopenharmony_ci let c_ref = c.as_ref(); 82092f3ab15Sopenharmony_ci assert!(a == b); 82192f3ab15Sopenharmony_ci assert!(a != c); 82292f3ab15Sopenharmony_ci assert!(a == b_ref); 82392f3ab15Sopenharmony_ci assert!(a != c_ref); 82492f3ab15Sopenharmony_ci assert!(b_ref == a); 82592f3ab15Sopenharmony_ci assert!(c_ref != a); 82692f3ab15Sopenharmony_ci assert!(a_ref == b_ref); 82792f3ab15Sopenharmony_ci assert!(a_ref != c_ref); 82892f3ab15Sopenharmony_ci } 82992f3ab15Sopenharmony_ci 83092f3ab15Sopenharmony_ci #[test] 83192f3ab15Sopenharmony_ci #[cfg(ossl102)] 83292f3ab15Sopenharmony_ci fn time_ord() { 83392f3ab15Sopenharmony_ci let a = Asn1Time::from_str("99991231235959Z").unwrap(); 83492f3ab15Sopenharmony_ci let b = Asn1Time::from_str("99991231235959Z").unwrap(); 83592f3ab15Sopenharmony_ci let c = Asn1Time::from_str("99991231235958Z").unwrap(); 83692f3ab15Sopenharmony_ci let a_ref = a.as_ref(); 83792f3ab15Sopenharmony_ci let b_ref = b.as_ref(); 83892f3ab15Sopenharmony_ci let c_ref = c.as_ref(); 83992f3ab15Sopenharmony_ci assert!(a >= b); 84092f3ab15Sopenharmony_ci assert!(a > c); 84192f3ab15Sopenharmony_ci assert!(b <= a); 84292f3ab15Sopenharmony_ci assert!(c < a); 84392f3ab15Sopenharmony_ci 84492f3ab15Sopenharmony_ci assert!(a_ref >= b); 84592f3ab15Sopenharmony_ci assert!(a_ref > c); 84692f3ab15Sopenharmony_ci assert!(b_ref <= a); 84792f3ab15Sopenharmony_ci assert!(c_ref < a); 84892f3ab15Sopenharmony_ci 84992f3ab15Sopenharmony_ci assert!(a >= b_ref); 85092f3ab15Sopenharmony_ci assert!(a > c_ref); 85192f3ab15Sopenharmony_ci assert!(b <= a_ref); 85292f3ab15Sopenharmony_ci assert!(c < a_ref); 85392f3ab15Sopenharmony_ci 85492f3ab15Sopenharmony_ci assert!(a_ref >= b_ref); 85592f3ab15Sopenharmony_ci assert!(a_ref > c_ref); 85692f3ab15Sopenharmony_ci assert!(b_ref <= a_ref); 85792f3ab15Sopenharmony_ci assert!(c_ref < a_ref); 85892f3ab15Sopenharmony_ci } 85992f3ab15Sopenharmony_ci 86092f3ab15Sopenharmony_ci #[test] 86192f3ab15Sopenharmony_ci fn integer_to_owned() { 86292f3ab15Sopenharmony_ci let a = Asn1Integer::from_bn(&BigNum::from_dec_str("42").unwrap()).unwrap(); 86392f3ab15Sopenharmony_ci let b = a.to_owned().unwrap(); 86492f3ab15Sopenharmony_ci assert_eq!( 86592f3ab15Sopenharmony_ci a.to_bn().unwrap().to_dec_str().unwrap().to_string(), 86692f3ab15Sopenharmony_ci b.to_bn().unwrap().to_dec_str().unwrap().to_string(), 86792f3ab15Sopenharmony_ci ); 86892f3ab15Sopenharmony_ci assert_ne!(a.as_ptr(), b.as_ptr()); 86992f3ab15Sopenharmony_ci } 87092f3ab15Sopenharmony_ci 87192f3ab15Sopenharmony_ci #[test] 87292f3ab15Sopenharmony_ci fn integer_cmp() { 87392f3ab15Sopenharmony_ci let a = Asn1Integer::from_bn(&BigNum::from_dec_str("42").unwrap()).unwrap(); 87492f3ab15Sopenharmony_ci let b = Asn1Integer::from_bn(&BigNum::from_dec_str("42").unwrap()).unwrap(); 87592f3ab15Sopenharmony_ci let c = Asn1Integer::from_bn(&BigNum::from_dec_str("43").unwrap()).unwrap(); 87692f3ab15Sopenharmony_ci assert!(a == b); 87792f3ab15Sopenharmony_ci assert!(a != c); 87892f3ab15Sopenharmony_ci assert!(a < c); 87992f3ab15Sopenharmony_ci assert!(c > b); 88092f3ab15Sopenharmony_ci } 88192f3ab15Sopenharmony_ci 88292f3ab15Sopenharmony_ci #[test] 88392f3ab15Sopenharmony_ci fn object_from_str() { 88492f3ab15Sopenharmony_ci let object = Asn1Object::from_str("2.16.840.1.101.3.4.2.1").unwrap(); 88592f3ab15Sopenharmony_ci assert_eq!(object.nid(), Nid::SHA256); 88692f3ab15Sopenharmony_ci } 88792f3ab15Sopenharmony_ci 88892f3ab15Sopenharmony_ci #[test] 88992f3ab15Sopenharmony_ci fn object_from_str_with_invalid_input() { 89092f3ab15Sopenharmony_ci Asn1Object::from_str("NOT AN OID") 89192f3ab15Sopenharmony_ci .map(|object| object.to_string()) 89292f3ab15Sopenharmony_ci .expect_err("parsing invalid OID should fail"); 89392f3ab15Sopenharmony_ci } 89492f3ab15Sopenharmony_ci 89592f3ab15Sopenharmony_ci #[test] 89692f3ab15Sopenharmony_ci #[cfg(ossl111)] 89792f3ab15Sopenharmony_ci fn object_to_slice() { 89892f3ab15Sopenharmony_ci let object = Asn1Object::from_str("2.16.840.1.101.3.4.2.1").unwrap(); 89992f3ab15Sopenharmony_ci assert_eq!( 90092f3ab15Sopenharmony_ci object.as_slice(), 90192f3ab15Sopenharmony_ci &[0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01], 90292f3ab15Sopenharmony_ci ); 90392f3ab15Sopenharmony_ci } 90492f3ab15Sopenharmony_ci 90592f3ab15Sopenharmony_ci #[test] 90692f3ab15Sopenharmony_ci fn asn1_octet_string() { 90792f3ab15Sopenharmony_ci let octet_string = Asn1OctetString::new_from_bytes(b"hello world").unwrap(); 90892f3ab15Sopenharmony_ci assert_eq!(octet_string.as_slice(), b"hello world"); 90992f3ab15Sopenharmony_ci assert_eq!(octet_string.len(), 11); 91092f3ab15Sopenharmony_ci } 91192f3ab15Sopenharmony_ci} 912