aboutsummaryrefslogtreecommitdiff
path: root/src/macros.rs
blob: 0333ef7b9ca89327d5b26d8fa49ab36998a42420 (plain)
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())
                }
            }
        }
    };
}