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 }