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
//! Macros used by this crate
/// Implements the following traits for a newtype of a `der` decodable/encodable type:
///
/// - `From` conversions to/from the inner type
/// - `AsRef` and `AsMut`
/// - `DecodeValue` and `EncodeValue`
/// - `FixedTag` mapping to the inner value's `FixedTag::TAG`
///
/// The main case is simplifying newtypes which need an `AssociatedOid`
#[macro_export]
macro_rules! impl_newtype {
($newtype:ty, $inner:ty) => {
#[allow(unused_lifetimes)]
impl<'a> From<$inner> for $newtype {
#[inline]
fn from(value: $inner) -> Self {
Self(value)
}
}
#[allow(unused_lifetimes)]
impl<'a> From<$newtype> for $inner {
#[inline]
fn from(value: $newtype) -> Self {
value.0
}
}
#[allow(unused_lifetimes)]
impl<'a> AsRef<$inner> for $newtype {
#[inline]
fn as_ref(&self) -> &$inner {
&self.0
}
}
#[allow(unused_lifetimes)]
impl<'a> AsMut<$inner> for $newtype {
#[inline]
fn as_mut(&mut self) -> &mut $inner {
&mut self.0
}
}
#[allow(unused_lifetimes)]
impl<'a> ::der::FixedTag for $newtype {
const TAG: ::der::Tag = <$inner as ::der::FixedTag>::TAG;
}
impl<'a> ::der::DecodeValue<'a> for $newtype {
fn decode_value<R: ::der::Reader<'a>>(
decoder: &mut R,
header: ::der::Header,
) -> ::der::Result<Self> {
Ok(Self(<$inner as ::der::DecodeValue>::decode_value(
decoder, header,
)?))
}
}
#[allow(unused_lifetimes)]
impl<'a> ::der::EncodeValue for $newtype {
fn encode_value(&self, encoder: &mut impl ::der::Writer) -> ::der::Result<()> {
self.0.encode_value(encoder)
}
fn value_len(&self) -> ::der::Result<::der::Length> {
self.0.value_len()
}
}
#[allow(unused_lifetimes)]
impl<'a> ::der::ValueOrd for $newtype {
fn value_cmp(&self, other: &Self) -> ::der::Result<::core::cmp::Ordering> {
self.0.value_cmp(&other.0)
}
}
};
}
/// Implements the AsExtension traits for every defined Extension paylooad
macro_rules! impl_extension {
($newtype:ty) => {
impl_extension!($newtype, critical = false);
};
($newtype:ty, critical = $critical:expr) => {
impl crate::ext::AsExtension for $newtype {
fn critical(
&self,
_subject: &crate::name::Name,
_extensions: &[crate::ext::Extension],
) -> bool {
$critical
}
}
};
}
/// Implements conversions between [`spki::SubjectPublicKeyInfo`] and [`SubjectKeyIdentifier`] or [`AuthorityKeyIdentifier`]
macro_rules! impl_key_identifier {
($newtype:ty, $out:expr) => {
#[cfg(feature = "builder")]
mod builder_key_identifier {
use super::*;
use der::asn1::OctetString;
use sha1::{Digest, Sha1};
use spki::SubjectPublicKeyInfoRef;
impl<'a> TryFrom<SubjectPublicKeyInfoRef<'a>> for $newtype {
type Error = der::Error;
fn try_from(issuer: SubjectPublicKeyInfoRef<'a>) -> Result<Self, Self::Error> {
// https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.2
//
// For CA certificates, subject key identifiers SHOULD be derived from
// the public key or a method that generates unique values. Two common
// methods for generating key identifiers from the public key are:
// (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the
// value of the BIT STRING subjectPublicKey (excluding the tag,
// length, and number of unused bits).
// (2) The keyIdentifier is composed of a four-bit type field with
// the value 0100 followed by the least significant 60 bits of
// the SHA-1 hash of the value of the BIT STRING
// subjectPublicKey (excluding the tag, length, and number of
// unused bits).
// Here we're using the first method
let result = Sha1::digest(issuer.subject_public_key.raw_bytes());
$out(result.as_slice())
}
}
}
};
}