1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
//! PKCS#10 Certification Request types
use crate::{
attr::{Attribute, AttributeValue, Attributes},
ext::Extension,
name::Name,
};
use alloc::vec::Vec;
use const_oid::db::rfc5912::ID_EXTENSION_REQ;
use const_oid::{AssociatedOid, ObjectIdentifier};
use der::asn1::BitString;
use der::{
asn1::{Any, SetOfVec},
Decode, Enumerated, Sequence,
};
use spki::{AlgorithmIdentifierOwned, SubjectPublicKeyInfoOwned};
#[cfg(feature = "pem")]
use der::pem::PemLabel;
/// Version identifier for certification request information.
///
/// (RFC 2986 designates `0` as the only valid version)
#[derive(Clone, Debug, Copy, PartialEq, Eq, Enumerated, Default)]
#[asn1(type = "INTEGER")]
#[repr(u8)]
pub enum Version {
/// Denotes PKCS#8 v1
#[default]
V1 = 0,
}
/// PKCS#10 `CertificationRequestInfo` as defined in [RFC 2986 Section 4].
///
/// ```text
/// CertificationRequestInfo ::= SEQUENCE {
/// version INTEGER { v1(0) } (v1,...),
/// subject Name,
/// subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
/// attributes [0] Attributes{{ CRIAttributes }}
/// }
/// ```
///
/// [RFC 2986 Section 4]: https://datatracker.ietf.org/doc/html/rfc2986#section-4
#[derive(Clone, Debug, PartialEq, Eq, Sequence)]
pub struct CertReqInfo {
/// Certification request version.
pub version: Version,
/// Subject name.
pub subject: Name,
/// Subject public key info.
pub public_key: SubjectPublicKeyInfoOwned,
/// Request attributes.
#[asn1(context_specific = "0", tag_mode = "IMPLICIT")]
pub attributes: Attributes,
}
/// PKCS#10 `CertificationRequest` as defined in [RFC 2986 Section 4].
///
/// ```text
/// CertificationRequest ::= SEQUENCE {
/// certificationRequestInfo CertificationRequestInfo,
/// signatureAlgorithm AlgorithmIdentifier{{ SignatureAlgorithms }},
/// signature BIT STRING
/// }
/// ```
///
/// [RFC 2986 Section 4]: https://datatracker.ietf.org/doc/html/rfc2986#section-4
#[derive(Clone, Debug, PartialEq, Eq, Sequence)]
pub struct CertReq {
/// Certification request information.
pub info: CertReqInfo,
/// Signature algorithm identifier.
pub algorithm: AlgorithmIdentifierOwned,
/// Signature.
pub signature: BitString,
}
#[cfg(feature = "pem")]
impl PemLabel for CertReq {
const PEM_LABEL: &'static str = "CERTIFICATE REQUEST";
}
impl<'a> TryFrom<&'a [u8]> for CertReq {
type Error = der::Error;
fn try_from(bytes: &'a [u8]) -> Result<Self, Self::Error> {
Self::from_der(bytes)
}
}
/// `ExtensionReq` as defined in [RFC 5272 Section 3.1].
///
/// ```text
/// ExtensionReq ::= SEQUENCE SIZE (1..MAX) OF Extension
/// ```
///
/// [RFC 5272 Section 3.1]: https://datatracker.ietf.org/doc/html/rfc5272#section-3.1
#[derive(Clone, Debug, PartialEq, Eq, Default)]
pub struct ExtensionReq(pub Vec<Extension>);
impl AssociatedOid for ExtensionReq {
const OID: ObjectIdentifier = ID_EXTENSION_REQ;
}
impl_newtype!(ExtensionReq, Vec<Extension>);
impl TryFrom<ExtensionReq> for Attribute {
type Error = der::Error;
fn try_from(extension_req: ExtensionReq) -> der::Result<Attribute> {
let mut values: SetOfVec<AttributeValue> = Default::default();
values.insert(Any::encode_from(&extension_req.0)?)?;
Ok(Attribute {
oid: ExtensionReq::OID,
values,
})
}
}
pub mod attributes {
//! Set of attributes that may be associated to a request
use alloc::vec;
use const_oid::AssociatedOid;
use der::{
asn1::{Any, ObjectIdentifier, SetOfVec},
EncodeValue, Length, Result, Tag, Tagged, Writer,
};
use crate::{attr::Attribute, ext::pkix::name::DirectoryString};
/// Trait to be implement by request attributes
pub trait AsAttribute: AssociatedOid + Tagged + EncodeValue + Sized {
/// Returns the Attribute with the content encoded.
fn to_attribute(&self) -> Result<Attribute> {
let inner: Any = der::asn1::Any::encode_from(self)?;
let values = SetOfVec::try_from(vec![inner])?;
Ok(Attribute {
oid: Self::OID,
values,
})
}
}
/// `ChallengePassword` as defined in [RFC 2985 Section 5.4.1]
///
/// ```text
/// challengePassword ATTRIBUTE ::= {
/// WITH SYNTAX DirectoryString {pkcs-9-ub-challengePassword}
/// EQUALITY MATCHING RULE caseExactMatch
/// SINGLE VALUE TRUE
/// ID pkcs-9-at-challengePassword
/// }
/// ```
///
/// [RFC 2985 Section 5.4.1]: https://www.rfc-editor.org/rfc/rfc2985#page-16
pub struct ChallengePassword(pub DirectoryString);
impl AsAttribute for ChallengePassword {}
impl AssociatedOid for ChallengePassword {
const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.1.9.7");
}
impl Tagged for ChallengePassword {
fn tag(&self) -> Tag {
self.0.tag()
}
}
impl EncodeValue for ChallengePassword {
fn value_len(&self) -> Result<Length> {
self.0.value_len()
}
fn encode_value(&self, encoder: &mut impl Writer) -> Result<()> {
self.0.encode_value(encoder)
}
}
}