1 //! X.509 `AlgorithmIdentifier`
3 use crate::{Error, Result}
;
4 use core
::cmp
::Ordering
;
6 asn1
::{AnyRef, Choice, ObjectIdentifier}
,
7 Decode
, DecodeValue
, DerOrd
, Encode
, EncodeValue
, Header
, Length
, Reader
, Sequence
, ValueOrd
,
11 #[cfg(feature = "alloc")]
14 /// X.509 `AlgorithmIdentifier` as defined in [RFC 5280 Section 4.1.1.2].
17 /// AlgorithmIdentifier ::= SEQUENCE {
18 /// algorithm OBJECT IDENTIFIER,
19 /// parameters ANY DEFINED BY algorithm OPTIONAL }
22 /// [RFC 5280 Section 4.1.1.2]: https://tools.ietf.org/html/rfc5280#section-4.1.1.2
23 #[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
24 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
25 pub struct AlgorithmIdentifier
<Params
> {
26 /// Algorithm OID, i.e. the `algorithm` field in the `AlgorithmIdentifier`
28 pub oid
: ObjectIdentifier
,
30 /// Algorithm `parameters`.
31 pub parameters
: Option
<Params
>,
34 impl<'a
, Params
> DecodeValue
<'a
> for AlgorithmIdentifier
<Params
>
38 fn decode_value
<R
: Reader
<'a
>>(reader
: &mut R
, header
: Header
) -> der
::Result
<Self> {
39 reader
.read_nested(header
.length
, |reader
| {
41 oid
: reader
.decode()?
,
42 parameters
: reader
.decode()?
,
48 impl<Params
> EncodeValue
for AlgorithmIdentifier
<Params
>
52 fn value_len(&self) -> der
::Result
<Length
> {
53 self.oid
.encoded_len()?
+ self.parameters
.encoded_len()?
56 fn encode_value(&self, writer
: &mut impl Writer
) -> der
::Result
<()> {
57 self.oid
.encode(writer
)?
;
58 self.parameters
.encode(writer
)?
;
63 impl<'a
, Params
> Sequence
<'a
> for AlgorithmIdentifier
<Params
> where Params
: Choice
<'a
> + Encode {}
65 impl<'a
, Params
> TryFrom
<&'a
[u8]> for AlgorithmIdentifier
<Params
>
67 Params
: Choice
<'a
> + Encode
,
71 fn try_from(bytes
: &'a
[u8]) -> Result
<Self> {
72 Ok(Self::from_der(bytes
)?
)
76 impl<Params
> ValueOrd
for AlgorithmIdentifier
<Params
>
80 fn value_cmp(&self, other
: &Self) -> der
::Result
<Ordering
> {
81 match self.oid
.der_cmp(&other
.oid
)?
{
82 Ordering
::Equal
=> self.parameters
.der_cmp(&other
.parameters
),
88 /// `AlgorithmIdentifier` reference which has `AnyRef` parameters.
89 pub type AlgorithmIdentifierRef
<'a
> = AlgorithmIdentifier
<AnyRef
<'a
>>;
91 /// `AlgorithmIdentifier` reference which has `Any` parameters.
92 #[cfg(feature = "alloc")]
93 pub type AlgorithmIdentifierOwned
= AlgorithmIdentifier
<Any
>;
95 impl<Params
> AlgorithmIdentifier
<Params
> {
96 /// Assert the `algorithm` OID is an expected value.
97 pub fn assert_algorithm_oid(&self, expected_oid
: ObjectIdentifier
) -> Result
<ObjectIdentifier
> {
98 if self.oid
== expected_oid
{
101 Err(Error
::OidUnknown { oid: expected_oid }
)
106 impl<'a
> AlgorithmIdentifierRef
<'a
> {
107 /// Assert `parameters` is an OID and has the expected value.
108 pub fn assert_parameters_oid(
110 expected_oid
: ObjectIdentifier
,
111 ) -> Result
<ObjectIdentifier
> {
112 let actual_oid
= self.parameters_oid()?
;
114 if actual_oid
== expected_oid
{
117 Err(Error
::OidUnknown { oid: expected_oid }
)
121 /// Assert the values of the `algorithm` and `parameters` OIDs.
124 algorithm
: ObjectIdentifier
,
125 parameters
: ObjectIdentifier
,
127 self.assert_algorithm_oid(algorithm
)?
;
128 self.assert_parameters_oid(parameters
)?
;
132 /// Get the `parameters` field as an [`AnyRef`].
134 /// Returns an error if `parameters` are `None`.
135 pub fn parameters_any(&self) -> Result
<AnyRef
<'a
>> {
136 self.parameters
.ok_or(Error
::AlgorithmParametersMissing
)
139 /// Get the `parameters` field as an [`ObjectIdentifier`].
141 /// Returns an error if it is absent or not an OID.
142 pub fn parameters_oid(&self) -> Result
<ObjectIdentifier
> {
143 Ok(ObjectIdentifier
::try_from(self.parameters_any()?
)?
)
146 /// Convert to a pair of [`ObjectIdentifier`]s.
148 /// This method is helpful for decomposing in match statements. Note in
149 /// particular that `NULL` parameters are treated the same as missing
152 /// Returns an error if parameters are present but not an OID.
153 pub fn oids(&self) -> der
::Result
<(ObjectIdentifier
, Option
<ObjectIdentifier
>)> {
156 match self.parameters
{
159 AnyRef
::NULL
=> None
,
160 _
=> Some(p
.decode_as
::<ObjectIdentifier
>()?
),
167 #[cfg(feature = "alloc")]
170 use der
::referenced
::*;
172 impl<'a
> RefToOwned
<'a
> for AlgorithmIdentifierRef
<'a
> {
173 type Owned
= AlgorithmIdentifierOwned
;
174 fn ref_to_owned(&self) -> Self::Owned
{
175 AlgorithmIdentifier
{
177 parameters
: self.parameters
.ref_to_owned(),
182 impl OwnedToRef
for AlgorithmIdentifierOwned
{
183 type Borrowed
<'a
> = AlgorithmIdentifierRef
<'a
>;
184 fn owned_to_ref(&self) -> Self::Borrowed
<'_
> {
185 AlgorithmIdentifier
{
187 parameters
: self.parameters
.owned_to_ref(),