webauthn_rp

WebAuthn RP library.
git clone https://git.philomathiclife.com/repos/webauthn_rp
Log | Files | Refs | README

spki.rs (47638B)


      1 use super::super::{
      2     Ed25519PubKey, MlDsa44PubKey, MlDsa65PubKey, MlDsa87PubKey, RsaPubKey, RsaPubKeyErr,
      3     UncompressedP256PubKey, UncompressedP384PubKey, UncompressedPubKey,
      4 };
      5 use core::fmt::{self, Display, Formatter};
      6 use p256::{
      7     NistP256,
      8     elliptic_curve::{Curve, common::typenum::type_operators::ToInt as _},
      9 };
     10 use p384::NistP384;
     11 /// Value assigned to the integer type under the universal tag class per
     12 /// [ITU-T X.680](https://www.itu.int/rec/T-REC-X.680-202102-I/en).
     13 const INTEGER: u8 = 2;
     14 /// Value assigned to the bitstring type under the universal tag class per
     15 /// [ITU-T X.680](https://www.itu.int/rec/T-REC-X.680-202102-I/en).
     16 const BITSTRING: u8 = 3;
     17 /// Value assigned to the null type under the universal tag class per
     18 /// [ITU-T X.680](https://www.itu.int/rec/T-REC-X.680-202102-I/en).
     19 const NULL: u8 = 5;
     20 /// Value assigned to the object identifier type under the universal tag class per
     21 /// [ITU-T X.680](https://www.itu.int/rec/T-REC-X.680-202102-I/en).
     22 const OID: u8 = 6;
     23 /// Value assigned to the sequence type under the universal tag class per
     24 /// [ITU-T X.680](https://www.itu.int/rec/T-REC-X.680-202102-I/en).
     25 const SEQUENCE: u8 = 16;
     26 /// Value assigned to a constructed [`SEQUENCE`] per
     27 /// [ITU-T X.690](https://www.itu.int/rec/T-REC-X.690-202102-I/en).
     28 ///
     29 /// All sequences are constructed once encoded, so this will likely always be used instead of
     30 /// `SEQUENCE`.
     31 const CONSTRUCTED_SEQUENCE: u8 = SEQUENCE | 0b0010_0000;
     32 /// Length of the header before the encoded key in a DER-encoded ASN.1 `SubjectPublicKeyInfo`
     33 /// for an ML-DSA-87 public key.
     34 const MLDSA87_HEADER_LEN: usize = 22;
     35 /// Length of a DER-encoded ASN.1 `SubjectPublicKeyInfo` for ML-DSA-87 public key.
     36 const MLDSA87_LEN: usize = MLDSA87_HEADER_LEN + 2592;
     37 /// Length of the header before the encoded key in a DER-encoded ASN.1 `SubjectPublicKeyInfo`
     38 /// for an ML-DSA-65 public key.
     39 const MLDSA65_HEADER_LEN: usize = 22;
     40 /// Length of a DER-encoded ASN.1 `SubjectPublicKeyInfo` for ML-DSA-65 public key.
     41 const MLDSA65_LEN: usize = MLDSA65_HEADER_LEN + 1952;
     42 /// Length of the header before the encoded key in a DER-encoded ASN.1 `SubjectPublicKeyInfo`
     43 /// for an ML-DSA-44 public key.
     44 const MLDSA44_HEADER_LEN: usize = 22;
     45 /// Length of a DER-encoded ASN.1 `SubjectPublicKeyInfo` for ML-DSA-44 public key.
     46 const MLDSA44_LEN: usize = MLDSA44_HEADER_LEN + 1312;
     47 /// Length of the header before the compressed y-coordinate in a DER-encoded ASN.1 `SubjectPublicKeyInfo`
     48 /// for an Ed25519 public key.
     49 const ED25519_HEADER_LEN: usize = 12;
     50 /// Length of a DER-encoded ASN.1 `SubjectPublicKeyInfo` for Ed25519 public key.
     51 const ED25519_LEN: usize = ED25519_HEADER_LEN + ed25519_dalek::PUBLIC_KEY_LENGTH;
     52 /// `ED25519_LEN` as a `u8`.
     53 // `44 as u8` is clearly OK.
     54 #[expect(
     55     clippy::as_conversions,
     56     clippy::cast_possible_truncation,
     57     reason = "comments above justify their correctness"
     58 )]
     59 const ED25519_LEN_U8: u8 = ED25519_LEN as u8;
     60 /// Length of the header before the uncompressed SEC- 1 pubic key in a DER-encoded ASN.1 `SubjectPublicKeyInfo`
     61 /// for an uncompressed ECDSA public key based on secp256r1/P-256.
     62 const P256_HEADER_LEN: usize = 27;
     63 /// Number of bytes the x-coordinate takes in an uncompressed P-256 public key.
     64 const P256_X_LEN: usize = <NistP256 as Curve>::FieldBytesSize::INT;
     65 /// Number of bytes the y-coordinate takes in an uncompressed P-256 public key.
     66 const P256_Y_LEN: usize = <NistP256 as Curve>::FieldBytesSize::INT;
     67 /// Number of bytes the x and y coordinates take in an uncompressed P-256 public key when concatenated together.
     68 const P256_COORD_LEN: usize = P256_X_LEN + P256_Y_LEN;
     69 /// Length of a DER-encoded ASN.1 `SubjectPublicKeyInfo` for an uncompressed SEC-1 ECDSA public key
     70 /// based on secp256r1/P-256.
     71 const P256_LEN: usize = P256_HEADER_LEN + P256_COORD_LEN;
     72 /// `P256_LEN` as a `u8`.
     73 // `91 as u8` is clearly OK.
     74 #[expect(
     75     clippy::as_conversions,
     76     clippy::cast_possible_truncation,
     77     reason = "comments above justify their correctness"
     78 )]
     79 const P256_LEN_U8: u8 = P256_LEN as u8;
     80 /// Length of the header before the uncompressed SEC- 1 pubic key in a DER-encoded ASN.1 `SubjectPublicKeyInfo`
     81 /// for an uncompressed ECDSA public key based on secp384r1/P-384.
     82 const P384_HEADER_LEN: usize = 24;
     83 /// Number of bytes the x-coordinate takes in an uncompressed P-384 public key.
     84 const P384_X_LEN: usize = <NistP384 as Curve>::FieldBytesSize::INT;
     85 /// Number of bytes the y-coordinate takes in an uncompressed P-384 public key.
     86 const P384_Y_LEN: usize = <NistP384 as Curve>::FieldBytesSize::INT;
     87 /// Number of bytes the x and y coordinates take in an uncompressed P-384 public key when concatenated together.
     88 const P384_COORD_LEN: usize = P384_X_LEN + P384_Y_LEN;
     89 /// Length of a DER-encoded ASN.1 `SubjectPublicKeyInfo` for an uncompressed SEC-1 ECDSA public key
     90 /// based on secp384r1/P-384.
     91 const P384_LEN: usize = P384_HEADER_LEN + P384_COORD_LEN;
     92 /// `P384_LEN` as a `u8`.
     93 // `120 as u8` is clearly OK.
     94 #[expect(
     95     clippy::as_conversions,
     96     clippy::cast_possible_truncation,
     97     reason = "comments above justify their correctness"
     98 )]
     99 const P384_LEN_U8: u8 = P384_LEN as u8;
    100 /// Error returned from [`SubjectPublicKeyInfo::from_der`].
    101 pub(super) enum SubjectPublicKeyInfoErr {
    102     /// The length of the DER-encoded ML-DSA-87 key was invalid.
    103     MlDsa87Len,
    104     /// The header of the DER-encoded ML-DSA-87 key was invalid.
    105     MlDsa87Header,
    106     /// The length of the DER-encoded ML-DSA-65 key was invalid.
    107     MlDsa65Len,
    108     /// The header of the DER-encoded ML-DSA-65 key was invalid.
    109     MlDsa65Header,
    110     /// The length of the DER-encoded ML-DSA-44 key was invalid.
    111     MlDsa44Len,
    112     /// The header of the DER-encoded ML-DSA-44 key was invalid.
    113     MlDsa44Header,
    114     /// The length of the DER-encoded Ed25519 key was invalid.
    115     Ed25519Len,
    116     /// The header of the DER-encoded Ed25519 key was invalid.
    117     Ed25519Header,
    118     /// The length of the DER-encoded P-256 key was invalid.
    119     P256Len,
    120     /// The header of the DER-encoded P-256 key was invalid.
    121     P256Header,
    122     /// The length of the DER-encoded P-384 key was invalid.
    123     P384Len,
    124     /// The header of the DER-encoded P-384 key was invalid.
    125     P384Header,
    126     /// The length of the DER-encoded RSA key was invalid.
    127     RsaLen,
    128     /// The DER-encoding of the RSA key was invalid.
    129     RsaEncoding,
    130     /// The exponent of the DER-encoded RSA key was too large.
    131     RsaExponentTooLarge,
    132     /// The DER-encoded RSA key was not a valid [`RsaPubKey`].
    133     RsaPubKey(RsaPubKeyErr),
    134 }
    135 impl Display for SubjectPublicKeyInfoErr {
    136     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
    137         match *self {
    138             Self::MlDsa87Len => f.write_str("length of the DER-encoded ML-DSA-87 key was invalid"),
    139             Self::MlDsa87Header => {
    140                 f.write_str("header of the DER-encoded ML-DSA-87 key was invalid")
    141             }
    142             Self::MlDsa65Len => f.write_str("length of the DER-encoded ML-DSA-65 key was invalid"),
    143             Self::MlDsa65Header => {
    144                 f.write_str("header of the DER-encoded ML-DSA-65 key was invalid")
    145             }
    146             Self::MlDsa44Len => f.write_str("length of the DER-encoded ML-DSA-44 key was invalid"),
    147             Self::MlDsa44Header => {
    148                 f.write_str("header of the DER-encoded ML-DSA-44 key was invalid")
    149             }
    150             Self::Ed25519Len => f.write_str("length of the DER-encoded Ed25519 key was invalid"),
    151             Self::Ed25519Header => f.write_str("header of the DER-encoded Ed25519 key was invalid"),
    152             Self::P256Len => f.write_str("length of the DER-encoded P-256 key was invalid"),
    153             Self::P256Header => f.write_str("header of the DER-encoded P-256 key was invalid"),
    154             Self::P384Len => f.write_str("length of the DER-encoded P-384 key was invalid"),
    155             Self::P384Header => f.write_str("header of the DER-encoded P-384 key was invalid"),
    156             Self::RsaLen => f.write_str("length of the DER-encoded RSA key was invalid"),
    157             Self::RsaEncoding => f.write_str("the DER-encoding of the RSA public key was invalid"),
    158             Self::RsaExponentTooLarge => {
    159                 f.write_str("the DER-encoded RSA public key had an exponent that was too large")
    160             }
    161             Self::RsaPubKey(err) => {
    162                 write!(f, "the DER-encoded RSA public was not valid: {err}")
    163             }
    164         }
    165     }
    166 }
    167 /// Types that can be deserialized from the DER-encoded ASN.1 `SubjectPublicKeyInfo` as defined in
    168 /// [RFC 5280](https://datatracker.ietf.org/doc/html/rfc5280#appendix-A.1) and other applicable RFCs
    169 /// and documents (e.g., [ITU-T X.690](https://www.itu.int/rec/T-REC-X.690-202102-I/en)).
    170 pub(super) trait SubjectPublicKeyInfo<'a>: Sized {
    171     /// Transforms the DER-encoded ASN.1 `SubjectPublicKeyInfo` into `Self`.
    172     ///
    173     /// # Errors
    174     ///
    175     /// Errors iff `der` does not conform.
    176     #[expect(single_use_lifetimes, reason = "false positive")]
    177     fn from_der<'b: 'a>(der: &'b [u8]) -> Result<Self, SubjectPublicKeyInfoErr>;
    178 }
    179 impl<'a> SubjectPublicKeyInfo<'a> for MlDsa87PubKey<&'a [u8]> {
    180     #[expect(single_use_lifetimes, reason = "false positive")]
    181     fn from_der<'b: 'a>(der: &'b [u8]) -> Result<Self, SubjectPublicKeyInfoErr> {
    182         /// ```asn
    183         /// SubjectPublicKeyInfo ::= SEQUENCE {
    184         ///     algorithm           AlgorithmIdentifier,
    185         ///     subjectPublicKey    BIT STRING
    186         /// }
    187         ///
    188         /// AlgorithmIdentifier ::= SEQUENCE {
    189         ///     algorithm     OBJECT IDENTIFIER,
    190         ///     parameters    ANY DEFINED BY algorithm OPTIONAL
    191         /// }
    192         /// ```
    193         ///
    194         /// [RFC 9882](https://www.rfc-editor.org/rfc/rfc9882.html) requires parameters to not exist
    195         /// in `AlgorithmIdentifier`.
    196         ///
    197         /// RFC 9882 defines the OID as 2.16.840.1.101.3.4.3.19 which is encoded as 96.134.72.1.101.3.4.3.19
    198         /// per [X.690](https://www.itu.int/rec/T-REC-X.690-202102-I/en).
    199         ///
    200         /// [FIPS 204](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.204.pdf) defines the bitstring as a reinterpretation of the byte string.
    201         const HEADER: [u8; MLDSA87_HEADER_LEN] = [
    202             CONSTRUCTED_SEQUENCE,
    203             130,
    204             10,
    205             50,
    206             CONSTRUCTED_SEQUENCE,
    207             9 + 2,
    208             OID,
    209             9,
    210             96,
    211             134,
    212             72,
    213             1,
    214             101,
    215             3,
    216             4,
    217             3,
    218             19,
    219             BITSTRING,
    220             130,
    221             10,
    222             33,
    223             // The number of unused bits.
    224             0,
    225         ];
    226         der.split_at_checked(HEADER.len())
    227             .ok_or(SubjectPublicKeyInfoErr::MlDsa87Len)
    228             .and_then(|(header, rem)| {
    229                 if header == HEADER {
    230                     if rem.len() == 2592 {
    231                         Ok(Self(rem))
    232                     } else {
    233                         Err(SubjectPublicKeyInfoErr::MlDsa87Len)
    234                     }
    235                 } else {
    236                     Err(SubjectPublicKeyInfoErr::MlDsa87Header)
    237                 }
    238             })
    239     }
    240 }
    241 impl<'a> SubjectPublicKeyInfo<'a> for MlDsa65PubKey<&'a [u8]> {
    242     #[expect(single_use_lifetimes, reason = "false positive")]
    243     fn from_der<'b: 'a>(der: &'b [u8]) -> Result<Self, SubjectPublicKeyInfoErr> {
    244         /// ```asn
    245         /// SubjectPublicKeyInfo ::= SEQUENCE {
    246         ///     algorithm           AlgorithmIdentifier,
    247         ///     subjectPublicKey    BIT STRING
    248         /// }
    249         ///
    250         /// AlgorithmIdentifier ::= SEQUENCE {
    251         ///     algorithm     OBJECT IDENTIFIER,
    252         ///     parameters    ANY DEFINED BY algorithm OPTIONAL
    253         /// }
    254         /// ```
    255         ///
    256         /// [RFC 9882](https://www.rfc-editor.org/rfc/rfc9882.html) requires parameters to not exist
    257         /// in `AlgorithmIdentifier`.
    258         ///
    259         /// RFC 9882 defines the OID as 2.16.840.1.101.3.4.3.18 which is encoded as 96.134.72.1.101.3.4.3.18
    260         /// per [X.690](https://www.itu.int/rec/T-REC-X.690-202102-I/en).
    261         ///
    262         /// [FIPS 204](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.204.pdf) defines the bitstring as a reinterpretation of the byte string.
    263         const HEADER: [u8; MLDSA65_HEADER_LEN] = [
    264             CONSTRUCTED_SEQUENCE,
    265             130,
    266             7,
    267             178,
    268             CONSTRUCTED_SEQUENCE,
    269             9 + 2,
    270             OID,
    271             9,
    272             96,
    273             134,
    274             72,
    275             1,
    276             101,
    277             3,
    278             4,
    279             3,
    280             18,
    281             BITSTRING,
    282             130,
    283             7,
    284             161,
    285             // The number of unused bits.
    286             0,
    287         ];
    288         der.split_at_checked(HEADER.len())
    289             .ok_or(SubjectPublicKeyInfoErr::MlDsa65Len)
    290             .and_then(|(header, rem)| {
    291                 if header == HEADER {
    292                     if rem.len() == 1952 {
    293                         Ok(Self(rem))
    294                     } else {
    295                         Err(SubjectPublicKeyInfoErr::MlDsa65Len)
    296                     }
    297                 } else {
    298                     Err(SubjectPublicKeyInfoErr::MlDsa65Header)
    299                 }
    300             })
    301     }
    302 }
    303 impl<'a> SubjectPublicKeyInfo<'a> for MlDsa44PubKey<&'a [u8]> {
    304     #[expect(single_use_lifetimes, reason = "false positive")]
    305     fn from_der<'b: 'a>(der: &'b [u8]) -> Result<Self, SubjectPublicKeyInfoErr> {
    306         /// ```asn
    307         /// SubjectPublicKeyInfo ::= SEQUENCE {
    308         ///     algorithm           AlgorithmIdentifier,
    309         ///     subjectPublicKey    BIT STRING
    310         /// }
    311         ///
    312         /// AlgorithmIdentifier ::= SEQUENCE {
    313         ///     algorithm     OBJECT IDENTIFIER,
    314         ///     parameters    ANY DEFINED BY algorithm OPTIONAL
    315         /// }
    316         /// ```
    317         ///
    318         /// [RFC 9882](https://www.rfc-editor.org/rfc/rfc9882.html) requires parameters to not exist
    319         /// in `AlgorithmIdentifier`.
    320         ///
    321         /// RFC 9882 defines the OID as 2.16.840.1.101.3.4.3.17 which is encoded as 96.134.72.1.101.3.4.3.17
    322         /// per [X.690](https://www.itu.int/rec/T-REC-X.690-202102-I/en).
    323         ///
    324         /// [FIPS 204](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.204.pdf) defines the bitstring as a reinterpretation of the byte string.
    325         const HEADER: [u8; MLDSA44_HEADER_LEN] = [
    326             CONSTRUCTED_SEQUENCE,
    327             130,
    328             5,
    329             50,
    330             CONSTRUCTED_SEQUENCE,
    331             9 + 2,
    332             OID,
    333             9,
    334             96,
    335             134,
    336             72,
    337             1,
    338             101,
    339             3,
    340             4,
    341             3,
    342             17,
    343             BITSTRING,
    344             130,
    345             5,
    346             33,
    347             // The number of unused bits.
    348             0,
    349         ];
    350         der.split_at_checked(HEADER.len())
    351             .ok_or(SubjectPublicKeyInfoErr::MlDsa44Len)
    352             .and_then(|(header, rem)| {
    353                 if header == HEADER {
    354                     if rem.len() == 1312 {
    355                         Ok(Self(rem))
    356                     } else {
    357                         Err(SubjectPublicKeyInfoErr::MlDsa44Len)
    358                     }
    359                 } else {
    360                     Err(SubjectPublicKeyInfoErr::MlDsa44Header)
    361                 }
    362             })
    363     }
    364 }
    365 impl<'a> SubjectPublicKeyInfo<'a> for Ed25519PubKey<&'a [u8]> {
    366     #[expect(single_use_lifetimes, reason = "false positive")]
    367     fn from_der<'b: 'a>(der: &'b [u8]) -> Result<Self, SubjectPublicKeyInfoErr> {
    368         /// ```asn
    369         /// SubjectPublicKeyInfo ::= SEQUENCE {
    370         ///     algorithm           AlgorithmIdentifier,
    371         ///     subjectPublicKey    BIT STRING
    372         /// }
    373         ///
    374         /// AlgorithmIdentifier ::= SEQUENCE {
    375         ///     algorithm     OBJECT IDENTIFIER,
    376         ///     parameters    ANY DEFINED BY algorithm OPTIONAL
    377         /// }
    378         /// ```
    379         ///
    380         /// [RFC 8410](https://www.rfc-editor.org/rfc/rfc8410#section-3) requires parameters to not exist
    381         /// in `AlgorithmIdentifier`.
    382         ///
    383         /// RFC 8410 defines the OID as 1.3.101.112 which is encoded as 43.101.112
    384         /// per [X.690](https://www.itu.int/rec/T-REC-X.690-202102-I/en).
    385         ///
    386         /// RFC 8410 defines the bitstring as a reinterpretation of the byte string.
    387         const HEADER: [u8; ED25519_HEADER_LEN] = [
    388             CONSTRUCTED_SEQUENCE,
    389             // `ED25519_LEN_U8` is the length of the entire payload; thus we subtract
    390             // the "consumed" length.
    391             ED25519_LEN_U8 - 2,
    392             CONSTRUCTED_SEQUENCE,
    393             // AlgorithmIdentifier only contains the OID; thus it's length is 5.
    394             3 + 2,
    395             OID,
    396             3,
    397             43,
    398             101,
    399             112,
    400             BITSTRING,
    401             // `ED25519_LEN_U8` is the length of the entire payload; thus we subtract
    402             // the "consumed" length.
    403             ED25519_LEN_U8 - 11,
    404             // The number of unused bits.
    405             0,
    406         ];
    407         der.split_at_checked(HEADER.len())
    408             .ok_or(SubjectPublicKeyInfoErr::Ed25519Len)
    409             .and_then(|(header, rem)| {
    410                 if header == HEADER {
    411                     if rem.len() == ed25519_dalek::PUBLIC_KEY_LENGTH {
    412                         Ok(Self(rem))
    413                     } else {
    414                         Err(SubjectPublicKeyInfoErr::Ed25519Len)
    415                     }
    416                 } else {
    417                     Err(SubjectPublicKeyInfoErr::Ed25519Header)
    418                 }
    419             })
    420     }
    421 }
    422 impl<'a> SubjectPublicKeyInfo<'a> for UncompressedP256PubKey<'a> {
    423     #[expect(single_use_lifetimes, reason = "false positive")]
    424     fn from_der<'b: 'a>(der: &'b [u8]) -> Result<Self, SubjectPublicKeyInfoErr> {
    425         // ```asn
    426         // SubjectPublicKeyInfo ::= SEQUENCE {
    427         //     algorithm           AlgorithmIdentifier,
    428         //     subjectPublicKey    BIT STRING
    429         // }
    430         //
    431         // AlgorithmIdentifier ::= SEQUENCE {
    432         //     algorithm     OBJECT IDENTIFIER,
    433         //     parameters    ANY DEFINED BY algorithm OPTIONAL
    434         // }
    435         //
    436         // ECParameters ::= CHOICE {
    437         //     namedCurve         OBJECT IDENTIFIER
    438         //     -- implicitCurve   NULL
    439         //     -- specifiedCurve  SpecifiedECDomain
    440         // }
    441         // ```
    442         // [RFC 5480](https://www.rfc-editor.org/rfc/rfc5480#section-2.1.1) requires parameters to exist and
    443         // be of the `ECParameters` form with the requirement that `namedCurve` is chosen.
    444         //
    445         // RFC 5480 defines the OID for id-ecPublicKey as 1.2.840.10045.2.1 and the OID for the namedCurve
    446         // secp256r1 as 1.2.840.10045.3.1.7. The former OID is encoded as 42.134.72.206.61.2.1 and the latter
    447         // is encoded as 42.134.72.206.61.3.1.7 per [X.690](https://www.itu.int/rec/T-REC-X.690-202102-I/en).
    448         //
    449         // [RFC 5480](https://www.rfc-editor.org/rfc/rfc5480#section-5) only requires support for the
    450         // uncompressed form and only states that the compressed form MAY be supported. In practice this means
    451         // DER-encoded payloads almost always are of the uncompressed form for compatibility reasons. This in
    452         // conjunction with the fact the COSE key is required to be in the uncompressed form means we only support
    453         // DER-encoded payloads containing uncompressed keys.
    454         //
    455         // [SEC 1](https://secg.org/sec1-v2.pdf) defines the point as an octet string, and the conversion
    456         // to a bitstring simply requires reinterpreting the octet string as a bitstring.
    457 
    458         /// Header of the DER-encoded payload before the public key.
    459         const HEADER: [u8; P256_HEADER_LEN] = [
    460             CONSTRUCTED_SEQUENCE,
    461             // `P256_LEN_U8` is the length of the entire payload; thus we subtract
    462             // the "consumed" length.
    463             P256_LEN_U8 - 2,
    464             CONSTRUCTED_SEQUENCE,
    465             7 + 2 + 8 + 2,
    466             OID,
    467             7,
    468             42,
    469             134,
    470             72,
    471             206,
    472             61,
    473             2,
    474             1,
    475             OID,
    476             8,
    477             42,
    478             134,
    479             72,
    480             206,
    481             61,
    482             3,
    483             1,
    484             7,
    485             BITSTRING,
    486             // `P256_LEN_U8` is the length of the entire payload; thus we subtract
    487             // the "consumed" length.
    488             P256_LEN_U8 - 25,
    489             // The number of unused bits.
    490             0,
    491             // SEC-1 tag for an uncompressed key.
    492             4,
    493         ];
    494         der.split_at_checked(HEADER.len())
    495             .ok_or(SubjectPublicKeyInfoErr::P256Len)
    496             .and_then(|(header, header_rem)| {
    497                 if header == HEADER {
    498                     header_rem
    499                         .split_at_checked(P256_X_LEN)
    500                         .ok_or(SubjectPublicKeyInfoErr::P256Len)
    501                         .and_then(|(x, y)| {
    502                             if y.len() == P256_Y_LEN {
    503                                 Ok(Self(x, y))
    504                             } else {
    505                                 Err(SubjectPublicKeyInfoErr::P256Len)
    506                             }
    507                         })
    508                 } else {
    509                     Err(SubjectPublicKeyInfoErr::P256Header)
    510                 }
    511             })
    512     }
    513 }
    514 impl<'a> SubjectPublicKeyInfo<'a> for UncompressedP384PubKey<'a> {
    515     #[expect(single_use_lifetimes, reason = "false positive")]
    516     fn from_der<'b: 'a>(der: &'b [u8]) -> Result<Self, SubjectPublicKeyInfoErr> {
    517         // ```asn
    518         // SubjectPublicKeyInfo ::= SEQUENCE {
    519         //     algorithm           AlgorithmIdentifier,
    520         //     subjectPublicKey    BIT STRING
    521         // }
    522         //
    523         // AlgorithmIdentifier ::= SEQUENCE {
    524         //     algorithm     OBJECT IDENTIFIER,
    525         //     parameters    ANY DEFINED BY algorithm OPTIONAL
    526         // }
    527         //
    528         // ECParameters ::= CHOICE {
    529         //     namedCurve         OBJECT IDENTIFIER
    530         //     -- implicitCurve   NULL
    531         //     -- specifiedCurve  SpecifiedECDomain
    532         // }
    533         // ```
    534         // [RFC 5480](https://www.rfc-editor.org/rfc/rfc5480#section-2.1.1) requires parameters to exist and
    535         // be of the `ECParameters` form with the requirement that `namedCurve` is chosen.
    536         //
    537         // RFC 5480 defines the OID for id-ecPublicKey as 1.2.840.10045.2.1 and the OID for the namedCurve
    538         // secp384r1 as 1.3.132.0.34. The former OID is encoded as 42.134.72.206.61.2.1 and the latter
    539         // is encoded as 43.129.4.0.34 per [X.690](https://www.itu.int/rec/T-REC-X.690-202102-I/en).
    540         //
    541         // [RFC 5480](https://www.rfc-editor.org/rfc/rfc5480#section-5) only requires support for the
    542         // uncompressed form and only states that the compressed form MAY be supported. In practice this means
    543         // DER-encoded payloads almost always are of the uncompressed form for compatibility reasons. This in
    544         // conjunction with the fact the COSE key is required to be in the uncompressed form means we only support
    545         // DER-encoded payloads containing uncompressed keys.
    546         //
    547         // [SEC 1](https://secg.org/sec1-v2.pdf) defines the point as an octet string, and the conversion
    548         // to a bitstring simply requires reinterpreting the octet string as a bitstring.
    549 
    550         /// Header of the DER-encoded payload before the public key.
    551         const HEADER: [u8; P384_HEADER_LEN] = [
    552             CONSTRUCTED_SEQUENCE,
    553             // `P384_LEN_U8` is the length of the entire payload; thus we subtract
    554             // the "consumed" length.
    555             P384_LEN_U8 - 2,
    556             CONSTRUCTED_SEQUENCE,
    557             7 + 2 + 5 + 2,
    558             OID,
    559             7,
    560             42,
    561             134,
    562             72,
    563             206,
    564             61,
    565             2,
    566             1,
    567             OID,
    568             5,
    569             43,
    570             129,
    571             4,
    572             0,
    573             34,
    574             BITSTRING,
    575             // `P384_LEN_U8` is the length of the entire payload; thus we subtract
    576             // the "consumed" length.
    577             P384_LEN_U8 - 22,
    578             // The number of unused bits.
    579             0,
    580             // SEC-1 tag for an uncompressed key.
    581             4,
    582         ];
    583         der.split_at_checked(HEADER.len())
    584             .ok_or(SubjectPublicKeyInfoErr::P384Len)
    585             .and_then(|(header, header_rem)| {
    586                 if header == HEADER {
    587                     header_rem
    588                         .split_at_checked(P384_X_LEN)
    589                         .ok_or(SubjectPublicKeyInfoErr::P384Len)
    590                         .and_then(|(x, y)| {
    591                             if y.len() == P384_Y_LEN {
    592                                 Ok(Self(x, y))
    593                             } else {
    594                                 Err(SubjectPublicKeyInfoErr::P384Len)
    595                             }
    596                         })
    597                 } else {
    598                     Err(SubjectPublicKeyInfoErr::P384Header)
    599                 }
    600             })
    601     }
    602 }
    603 impl<'a> SubjectPublicKeyInfo<'a> for RsaPubKey<&'a [u8]> {
    604     #[expect(single_use_lifetimes, reason = "false positive")]
    605     #[expect(
    606         clippy::arithmetic_side_effects,
    607         clippy::big_endian_bytes,
    608         clippy::indexing_slicing,
    609         clippy::missing_asserts_for_indexing,
    610         reason = "comments justify their correctness"
    611     )]
    612     #[expect(
    613         clippy::too_many_lines,
    614         reason = "rsa keys are the only type that would benefit from a modular SubjectPublicKeyInfo (similar to FromCbor). if more types benefit in the future, then this will be done."
    615     )]
    616     fn from_der<'b: 'a>(der: &'b [u8]) -> Result<Self, SubjectPublicKeyInfoErr> {
    617         // ```asn
    618         // SubjectPublicKeyInfo ::= SEQUENCE {
    619         //     algorithm           AlgorithmIdentifier,
    620         //     subjectPublicKey    BIT STRING
    621         // }
    622         //
    623         // AlgorithmIdentifier ::= SEQUENCE {
    624         //     algorithm     OBJECT IDENTIFIER,
    625         //     parameters    ANY DEFINED BY algorithm OPTIONAL
    626         // }
    627         //
    628         // RSAPublicKey ::= SEQUENCE {
    629         //     modulus          INTEGER, -- n
    630         //     publicExponent   INTEGER  --e
    631         // }
    632         //
    633         // pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840)
    634         //     rsadsi(113549) pkcs(1) 1
    635         // }
    636         //
    637         // rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1}
    638         // ```
    639         // [RFC 3279](https://www.rfc-editor.org/rfc/rfc3279#section-2.3.1) requires parameters to exist and
    640         // be null.
    641         //
    642         // RFC 3279 defines the OID for rsaEncryption as 1.2.840.113549.1.1.1 which is encoded as
    643         // 42.134.72.134.247.13.1.1.1 per [X.690](https://www.itu.int/rec/T-REC-X.690-202102-I/en).
    644         //
    645         // Note we only allow moduli that are 256 to 2048 bytes in length inclusively. Additionally
    646         // we only allow `u32` exponents; consequently all lengths that include the modulus will always be
    647         // encoded with two bytes.
    648 
    649         /// `AlgorithmIdentifier` header including the `BITSTRING` and number of bytes the length
    650         /// is encoded in of the `BITSTRING` type of `subjectPublicKey`
    651         /// (130-128 = 2 bytes to encode the length).
    652         const ALG_OID_HEADER: [u8; 17] = [
    653             CONSTRUCTED_SEQUENCE,
    654             9 + 2 + 2,
    655             OID,
    656             9,
    657             42,
    658             134,
    659             72,
    660             134,
    661             247,
    662             13,
    663             1,
    664             1,
    665             1,
    666             NULL,
    667             0,
    668             BITSTRING,
    669             130,
    670         ];
    671         /// `CONSTRUCTED_SEQUENCE` whose length is encoded in two bytes.
    672         const SEQ_LONG: [u8; 2] = [CONSTRUCTED_SEQUENCE, 130];
    673         /// `INTEGER` whose length is encoded in two bytes.
    674         const INT_LONG: [u8; 2] = [INTEGER, 130];
    675         der.split_at_checked(SEQ_LONG.len())
    676                 .ok_or(SubjectPublicKeyInfoErr::RsaLen)
    677                 .and_then(|(seq, seq_rem)| {
    678                     if seq == SEQ_LONG {
    679                         seq_rem
    680                             .split_at_checked(2)
    681                             .ok_or(SubjectPublicKeyInfoErr::RsaLen)
    682                             .and_then(|(seq_len, seq_len_rem)| {
    683                                 let mut len = [0; 2];
    684                                 len.copy_from_slice(seq_len);
    685                                 let rem_len = usize::from(u16::from_be_bytes(len));
    686                                 if rem_len == seq_len_rem.len() {
    687                                     if rem_len > 255 {
    688                                         // We can safely split here since we know `seq_len_rem` is at least
    689                                         // 256 which is greater than `ALG_OID_HEADER.len()`.
    690                                         let (a_oid, a_oid_rem) = seq_len_rem.split_at(ALG_OID_HEADER.len());
    691                                         if a_oid == ALG_OID_HEADER {
    692                                             // `a_oid_rem.len()` is at least 239, so splitting is fine.
    693                                             let (bit_str_len_enc, bit_str_val) = a_oid_rem.split_at(2);
    694                                             let mut bit_string_len = [0; 2];
    695                                             bit_string_len.copy_from_slice(bit_str_len_enc);
    696                                             let bit_str_val_len = usize::from(u16::from_be_bytes(bit_string_len));
    697                                             if bit_str_val_len == bit_str_val.len() {
    698                                                 if bit_str_val_len > 255 {
    699                                                     // `bit_str_val.len() > 255`, so splitting is fine.
    700                                                     let (unused_bits, bits_rem) = bit_str_val.split_at(1);
    701                                                     if unused_bits == [0] {
    702                                                         // We can safely split here since we know `bits_rem.len()` is at least
    703                                                         // 255.
    704                                                         let (rsa_seq, rsa_seq_rem) = bits_rem.split_at(SEQ_LONG.len());
    705                                                         if rsa_seq == SEQ_LONG {
    706                                                             // `rsa_seq_rem.len()` is at least 253, so splitting is fine.
    707                                                             let (rsa_seq_len_enc, rsa_seq_len_enc_rem) = rsa_seq_rem.split_at(2);
    708                                                             let mut rsa_seq_len = [0; 2];
    709                                                             rsa_seq_len.copy_from_slice(rsa_seq_len_enc);
    710                                                             let rsa_key_info_len = usize::from(u16::from_be_bytes(rsa_seq_len));
    711                                                             if rsa_key_info_len == rsa_seq_len_enc_rem.len() {
    712                                                                 if rsa_key_info_len > 255 {
    713                                                                     // We can safely split here since we know `rsa_seq_len_enc_rem.len()`
    714                                                                     // is at least 256.
    715                                                                     let (n_meta, n_meta_rem) = rsa_seq_len_enc_rem.split_at(INT_LONG.len());
    716                                                                     if n_meta == INT_LONG {
    717                                                                         // `n_meta_rem.len()` is at least 254, so splitting is fine.
    718                                                                         let (n_len_enc, n_len_enc_rem) = n_meta_rem.split_at(2);
    719                                                                         let mut n_len = [0; 2];
    720                                                                         n_len.copy_from_slice(n_len_enc);
    721                                                                         let mod_len = usize::from(u16::from_be_bytes(n_len));
    722                                                                         if mod_len > 255 {
    723                                                                             n_len_enc_rem.split_at_checked(mod_len).ok_or(SubjectPublicKeyInfoErr::RsaLen).and_then(|(mut n, n_rem)| {
    724                                                                                 // `n.len() > 255`, so indexing is fine.
    725                                                                                 let n_first = n[0];
    726                                                                                 // DER integers are signed; thus the most significant bit must be 0.
    727                                                                                 // DER integers are minimally encoded; thus when a leading 0 exists,
    728                                                                                 // the second byte must be at least 128.
    729                                                                                 // `n.len() > 255`, so indexing is fine.
    730                                                                                 if n_first < 128 && (n_first != 0 || n[1] > 127) {
    731                                                                                     if n_first == 0 {
    732                                                                                         // `n.len() > 255`, so indexing is fine.
    733                                                                                         // We must remove the leading 0.
    734                                                                                         n = &n[1..];
    735                                                                                     }
    736                                                                                     n_rem.split_first().ok_or(SubjectPublicKeyInfoErr::RsaLen).and_then(|(e_type, e_type_rem)| {
    737                                                                                         if *e_type == INTEGER {
    738                                                                                             e_type_rem.split_first().ok_or(SubjectPublicKeyInfoErr::RsaLen).and_then(|(e_len, e_len_rem)| {
    739                                                                                                 let e_len_usize = usize::from(*e_len);
    740                                                                                                 if e_len_usize == e_len_rem.len() {
    741                                                                                                     e_len_rem.first().ok_or(SubjectPublicKeyInfoErr::RsaLen).and_then(|&e_first| {
    742                                                                                                         // DER integers are signed; thus the most significant bit must be 0.
    743                                                                                                         if e_first < 128 {
    744                                                                                                             // `RsaPubKey` only allows `u32` exponents, which means we only care
    745                                                                                                             // about lengths up to 5.
    746                                                                                                             match e_len_usize {
    747                                                                                                                 1 => Ok(u32::from(e_first)),
    748                                                                                                                 2..=5 => if e_first == 0 {
    749                                                                                                                     // DER integers are minimally encoded; thus when a leading
    750                                                                                                                     // 0 exists, the second byte must be at least 128.
    751                                                                                                                     // We know the length is at least 2; thus this won't `panic`.
    752                                                                                                                     if e_len_rem[1] > 127 {
    753                                                                                                                         let mut e = [0; 4];
    754                                                                                                                         if e_len_usize == 5 {
    755                                                                                                                             // We know the length is at least 2; thus this won't `panic`.
    756                                                                                                                             e.copy_from_slice(&e_len_rem[1..]);
    757                                                                                                                         } else {
    758                                                                                                                             // `e.len() == 4` and `e_len_usize` is at most 4; thus underflow
    759                                                                                                                             // won't occur nor will indexing `panic`. `e` is big-endian,
    760                                                                                                                             // so we start from the right.
    761                                                                                                                             e[4 - e_len_usize..].copy_from_slice(e_len_rem);
    762                                                                                                                         }
    763                                                                                                                         Ok(u32::from_be_bytes(e))
    764                                                                                                                     } else {
    765                                                                                                                         Err(SubjectPublicKeyInfoErr::RsaEncoding)
    766                                                                                                                     }
    767                                                                                                                 } else if e_len_usize == 5 {
    768                                                                                                                     // 5 bytes are only possible for `INTEGER`s that
    769                                                                                                                     // are greater than `i32::MAX`, which will be encoded
    770                                                                                                                     // with a leading 0.
    771                                                                                                                     Err(SubjectPublicKeyInfoErr::RsaEncoding)
    772                                                                                                                 } else {
    773                                                                                                                     let mut e = [0; 4];
    774                                                                                                                     // `e.len() == 4` and `e_len_usize` is at most 4; thus underflow
    775                                                                                                                     // won't occur nor will indexing `panic`. `e` is big-endian,
    776                                                                                                                     // so we start from the right.
    777                                                                                                                     e[4 - e_len_usize..].copy_from_slice(e_len_rem);
    778                                                                                                                     Ok(u32::from_be_bytes(e))
    779                                                                                                                 },
    780                                                                                                                 _ => Err(SubjectPublicKeyInfoErr::RsaExponentTooLarge),
    781                                                                                                             }.and_then(|e| Self::try_from((n, e)).map_err(SubjectPublicKeyInfoErr::RsaPubKey))
    782                                                                                                         } else {
    783                                                                                                             Err(SubjectPublicKeyInfoErr::RsaEncoding)
    784                                                                                                         }
    785                                                                                                     })
    786                                                                                                 } else {
    787                                                                                                     Err(SubjectPublicKeyInfoErr::RsaLen)
    788                                                                                                 }
    789                                                                                             })
    790                                                                                         } else {
    791                                                                                             Err(SubjectPublicKeyInfoErr::RsaEncoding)
    792                                                                                         }
    793                                                                                     })
    794                                                                                 } else {
    795                                                                                     Err(SubjectPublicKeyInfoErr::RsaEncoding)
    796                                                                                 }
    797                                                                             })
    798                                                                         } else {
    799                                                                             Err(SubjectPublicKeyInfoErr::RsaEncoding)
    800                                                                         }
    801                                                                     } else {
    802                                                                         Err(SubjectPublicKeyInfoErr::RsaEncoding)
    803                                                                     }
    804                                                                 } else {
    805                                                                     Err(SubjectPublicKeyInfoErr::RsaEncoding)
    806                                                                 }
    807                                                             } else {
    808                                                                 Err(SubjectPublicKeyInfoErr::RsaLen)
    809                                                             }
    810                                                         } else {
    811                                                             Err(SubjectPublicKeyInfoErr::RsaEncoding)
    812                                                         }
    813                                                     } else {
    814                                                         Err(SubjectPublicKeyInfoErr::RsaEncoding)
    815                                                     }
    816                                                 } else {
    817                                                     Err(SubjectPublicKeyInfoErr::RsaEncoding)
    818                                                 }
    819                                             } else {
    820                                                 Err(SubjectPublicKeyInfoErr::RsaLen)
    821                                             }
    822                                         } else {
    823                                             Err(SubjectPublicKeyInfoErr::RsaEncoding)
    824                                         }
    825                                     } else {
    826                                         Err(SubjectPublicKeyInfoErr::RsaEncoding)
    827                                     }
    828                                 } else {
    829                                     Err(SubjectPublicKeyInfoErr::RsaLen)
    830                                 }
    831                             })
    832                     } else {
    833                         Err(SubjectPublicKeyInfoErr::RsaEncoding)
    834                     }
    835                 })
    836     }
    837 }
    838 impl<'a> SubjectPublicKeyInfo<'a> for UncompressedPubKey<'a> {
    839     #[expect(clippy::indexing_slicing, reason = "comments justify correctness")]
    840     #[expect(single_use_lifetimes, reason = "false positive")]
    841     fn from_der<'b: 'a>(der: &'b [u8]) -> Result<Self, SubjectPublicKeyInfoErr> {
    842         /// Index in a DER-encoded payload of the ML-DSA-* public key that corresponds
    843         /// to the OID length.
    844         const ML_DSA_OID_LEN_IDX: usize = 5;
    845         /// Length of the OID for the DER-encoded ML-DSA-* public keys.
    846         ///
    847         /// Note this is _not_ the same as the OID length for an RSA public key (i.e., 13).
    848         const ML_DSA_OID_LEN: u8 = 11;
    849         // The only lengths that overlap is RSA with ML-DSA-44 and ML-DSA-65.
    850         match der.len() {
    851             // The minimum modulus we support for RSA is 2048 bits which is 256 bytes;
    852             // thus clearly its encoding will be at least 256 which is greater than
    853             // all of the non-ML-DSA-* values and less than the ML-DSA-* values.
    854             // The maximum modulus we support for RSA is 16K bits which is 2048 bytes and the maximum
    855             // exponent we support for RSA is 4 bytes which is hundreds of bytes less than 2614
    856             // (i.e., the length of a DER-encoded ML-DSAS-87 public key).
    857             ED25519_LEN => Ed25519PubKey::from_der(der).map(Self::Ed25519),
    858             P256_LEN => UncompressedP256PubKey::from_der(der).map(Self::P256),
    859             P384_LEN => UncompressedP384PubKey::from_der(der).map(Self::P384),
    860             MLDSA44_LEN => {
    861                 // `ML_DSA_OID_LEN_IDX < MLDSA44_LEN = der.len()` so indexing
    862                 // won't `panic`.
    863                 if der[ML_DSA_OID_LEN_IDX] == ML_DSA_OID_LEN {
    864                     MlDsa44PubKey::from_der(der).map(Self::MlDsa44)
    865                 } else {
    866                     RsaPubKey::from_der(der).map(Self::Rsa)
    867                 }
    868             }
    869             MLDSA65_LEN => {
    870                 // `ML_DSA_OID_LEN_IDX < MLDSA65_LEN = der.len()` so indexing
    871                 // won't `panic`.
    872                 if der[ML_DSA_OID_LEN_IDX] == ML_DSA_OID_LEN {
    873                     MlDsa65PubKey::from_der(der).map(Self::MlDsa65)
    874                 } else {
    875                     RsaPubKey::from_der(der).map(Self::Rsa)
    876                 }
    877             }
    878             MLDSA87_LEN => MlDsa87PubKey::from_der(der).map(Self::MlDsa87),
    879             _ => RsaPubKey::from_der(der).map(Self::Rsa),
    880         }
    881     }
    882 }