1 //! Signed Certificate Timestamp list extension as defined in the 2 //! [Certificate Transparency RFC 6962]. 3 //! 4 //! [Certificate Transparency RFC 6962]: https://datatracker.ietf.org/doc/html/rfc6962 5 6 #![cfg(feature = "sct")] 7 8 use alloc::{format, vec::Vec}; 9 use const_oid::{AssociatedOid, ObjectIdentifier}; 10 use der::asn1::OctetString; 11 use tls_codec::{ 12 DeserializeBytes, SerializeBytes, TlsByteVecU16, TlsDeserializeBytes, TlsSerializeBytes, 13 TlsSize, 14 }; 15 16 /// A signed certificate timestamp list (SCT list) as defined in [RFC 6962 Section 3.3]. 17 /// 18 /// ```text 19 /// SignedCertificateTimestampList ::= OCTET STRING 20 /// ``` 21 /// 22 /// [RFC 6962 Section 3.3]: https://datatracker.ietf.org/doc/html/rfc6962#section-3.3 23 #[derive(Debug, PartialEq)] 24 pub struct SignedCertificateTimestampList(OctetString); 25 26 //TODO: Remove this and use const-oid's rfc6962::CT_PRECERT_SCTS once a const-oid version 27 // containing it is published 28 const CT_PRECERT_SCTS: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.3.6.1.4.1.11129.2.4.2"); 29 30 impl AssociatedOid for SignedCertificateTimestampList { 31 const OID: ObjectIdentifier = CT_PRECERT_SCTS; 32 } 33 34 impl_newtype!(SignedCertificateTimestampList, OctetString); 35 impl_extension!(SignedCertificateTimestampList, critical = false); 36 37 /// Errors that are thrown by this module. 38 #[derive(PartialEq, Debug)] 39 pub enum Error { 40 /// [Errors][der::Error] from the `der` crate. 41 Der(der::Error), 42 /// [Errors][tls_codec::Error] from the `tls_codec` crate. 43 Tls(tls_codec::Error), 44 } 45 46 impl From<der::Error> for Error { from(value: der::Error) -> Self47 fn from(value: der::Error) -> Self { 48 Error::Der(value) 49 } 50 } 51 52 impl From<tls_codec::Error> for Error { from(value: tls_codec::Error) -> Self53 fn from(value: tls_codec::Error) -> Self { 54 Error::Tls(value) 55 } 56 } 57 58 impl SignedCertificateTimestampList { 59 /// Creates a new [`SignedCertificateTimestampList`] from a slice of [`SerializedSct`]s. new(serialized_scts: &[SerializedSct]) -> Result<Self, Error>60 pub fn new(serialized_scts: &[SerializedSct]) -> Result<Self, Error> { 61 let mut result: Vec<u8> = Vec::new(); 62 for timestamp in serialized_scts { 63 let buffer = timestamp.tls_serialize()?; 64 result.extend(buffer); 65 } 66 let tls_vec = TlsByteVecU16::new(result); 67 let buffer = tls_vec.tls_serialize()?; 68 Ok(SignedCertificateTimestampList(OctetString::new(buffer)?)) 69 } 70 71 /// Parses the encoded [SerializedSct]s and returns a [Vec] containing them. 72 /// 73 /// Returns an [error][Error] if a [SerializedSct] can't be 74 /// deserialized or if there are trailing bytes after all [SerializedSct]s 75 /// are deserialized. parse_timestamps(&self) -> Result<Vec<SerializedSct>, Error>76 pub fn parse_timestamps(&self) -> Result<Vec<SerializedSct>, Error> { 77 let (tls_vec, rest) = TlsByteVecU16::tls_deserialize_bytes(self.0.as_bytes())?; 78 if !rest.is_empty() { 79 return Err(tls_codec::Error::TrailingData)?; 80 } 81 let mut bytes = tls_vec.as_slice(); 82 let mut result = Vec::new(); 83 while !bytes.is_empty() { 84 let (serialized_sct, rest) = SerializedSct::tls_deserialize_bytes(bytes)?; 85 result.push(serialized_sct); 86 bytes = rest; 87 } 88 Ok(result) 89 } 90 } 91 92 /// A byte string that contains a serialized [SignedCertificateTimestamp] as 93 /// defined in [RFC 6962 section 3.3]. 94 /// 95 /// [RFC 6962 section 3.3]: https://datatracker.ietf.org/doc/html/rfc6962#section-3.3 96 #[derive(PartialEq, Debug, TlsDeserializeBytes, TlsSerializeBytes, TlsSize)] 97 pub struct SerializedSct { 98 data: TlsByteVecU16, 99 } 100 101 impl SerializedSct { 102 /// Creates a new [SerializedSct] from a [SignedCertificateTimestamp]. 103 /// 104 /// Returns [tls_codec Error][tls_codec::Error] if the given [SignedCertificateTimestamp] 105 /// can't be serialized. new(timestamp: SignedCertificateTimestamp) -> Result<Self, tls_codec::Error>106 pub fn new(timestamp: SignedCertificateTimestamp) -> Result<Self, tls_codec::Error> { 107 let buffer = timestamp.tls_serialize()?; 108 Ok(SerializedSct { 109 data: TlsByteVecU16::from_slice(&buffer), 110 }) 111 } 112 113 /// Parses a [SignedCertificateTimestamp] from a this [SerializedSct]. 114 /// 115 /// Returns an [error][Error] if a [SignedCertificateTimestamp] can't be 116 /// deserialized or if there are trailing bytes after a 117 /// [SignedCertificateTimestamp] has been deserialized. parse_timestamp(&self) -> Result<SignedCertificateTimestamp, Error>118 pub fn parse_timestamp(&self) -> Result<SignedCertificateTimestamp, Error> { 119 let (sct, rest) = SignedCertificateTimestamp::tls_deserialize_bytes(self.data.as_slice())?; 120 if !rest.is_empty() { 121 return Err(tls_codec::Error::TrailingData)?; 122 } 123 Ok(sct) 124 } 125 } 126 127 /// A signed certificate timestamp (SCT) as defined in [RFC 6962 section 3.2]. 128 /// 129 /// [RFC 6962 section 3.2]: https://datatracker.ietf.org/doc/html/rfc6962#section-3.2 130 #[derive(PartialEq, Debug, TlsDeserializeBytes, TlsSerializeBytes, TlsSize)] 131 pub struct SignedCertificateTimestamp { 132 /// The version of the protocol to which the SCT conforms. 133 /// Currently, it is always v1. 134 pub version: Version, 135 /// The SHA-256 hash of the log's public key, calculated over 136 /// the DER encoding of the key represented as [SubjectPublicKeyInfo][spki::SubjectPublicKeyInfo]. 137 pub log_id: LogId, 138 /// the current NTP Time measured since the `UNIX_EPOCH` 139 /// (January 1, 1970, 00:00), ignoring leap seconds, in milliseconds. 140 pub timestamp: u64, 141 /// The future extensions to protocol version v1. 142 /// Currently, no extensions are specified. 143 pub extensions: TlsByteVecU16, 144 /// A digital signature over many fields including 145 /// version, timestamp, extensions and others. See [RFC 6962 section 3.2] 146 /// for a complete list. 147 /// 148 /// [RFC 6962 section 3.2]:https://datatracker.ietf.org/doc/html/rfc6962#section-3.2 149 pub signature: DigitallySigned, 150 } 151 152 impl SignedCertificateTimestamp { 153 /// Creates a [DateTime][der::DateTime] from the timestamp field since the `UNIX_EPOCH`. 154 /// 155 /// Returns an error if timestamp is outside the supported date range. timestamp(&self) -> Result<der::DateTime, der::Error>156 pub fn timestamp(&self) -> Result<der::DateTime, der::Error> { 157 der::DateTime::from_unix_duration(core::time::Duration::from_millis(self.timestamp)) 158 } 159 } 160 161 /// The version of the protocol to which the SCT conforms 162 /// as defined in [RFC 6962 section 3.2]. Currently, it is always v1. 163 /// 164 /// [RFC 6962 section 3.2]: https://datatracker.ietf.org/doc/html/rfc6962#section-3.2 165 #[derive(PartialEq, Debug, TlsDeserializeBytes, TlsSerializeBytes, TlsSize)] 166 #[repr(u8)] 167 pub enum Version { 168 /// Version 1. 169 V1 = 0, 170 } 171 172 /// The SHA-256 hash of the log's public key, calculated over 173 /// the DER encoding of the key represented as [SubjectPublicKeyInfo][spki::SubjectPublicKeyInfo] 174 /// as defined in [RFC 6962 section 3.2]. 175 /// 176 /// [RFC 6962 section 3.2]: https://datatracker.ietf.org/doc/html/rfc6962#section-3.2 177 #[derive(PartialEq, Debug, TlsDeserializeBytes, TlsSerializeBytes, TlsSize)] 178 pub struct LogId { 179 /// Hash of the log's public key. 180 pub key_id: [u8; 32], 181 } 182 183 /// Digital signature as defined in [RFC 5246 section 4.7]. 184 /// 185 /// [RFC 5246 section 4.7]: https://datatracker.ietf.org/doc/html/rfc5246#section-4.7 186 #[derive(PartialEq, Debug, TlsDeserializeBytes, TlsSerializeBytes, TlsSize)] 187 pub struct DigitallySigned { 188 /// [SignatureAndHashAlgorithm] as defined in [RFC 5246 section 7.4.1.4.1]. 189 /// 190 /// [RFC 5246 section 7.4.1.4.1]: https://datatracker.ietf.org/doc/html/rfc5246#section-7.4.1.4.1 191 pub algorithm: SignatureAndHashAlgorithm, 192 /// Digital signature over some contents using the [SignatureAndHashAlgorithm]. 193 pub signature: TlsByteVecU16, 194 } 195 196 /// A combination of signature and hashing algorithms as defined in [RFC 5246 section 7.4.1.4.1]. 197 /// 198 /// [RFC 5246 section 7.4.1.4.1]: https://datatracker.ietf.org/doc/html/rfc5246#section-7.4.1.4.1 199 #[derive(PartialEq, Debug, TlsDeserializeBytes, TlsSerializeBytes, TlsSize)] 200 pub struct SignatureAndHashAlgorithm { 201 /// The hashing algorithm. 202 pub hash: HashAlgorithm, 203 /// The signature algorithm. 204 pub signature: SignatureAlgorithm, 205 } 206 207 /// Signature algorithm as defined in [RFC 5246 section 7.4.1.4.1]. 208 /// 209 /// [RFC 5246 section 7.4.1.4.1]: https://datatracker.ietf.org/doc/html/rfc5246#section-7.4.1.4.1 210 #[derive(PartialEq, Debug, TlsDeserializeBytes, TlsSerializeBytes, TlsSize)] 211 #[repr(u8)] 212 pub enum SignatureAlgorithm { 213 /// Anonymous signature algorithm. 214 Anonymous = 0, 215 /// RSA signature algorithm. 216 Rsa = 1, 217 /// DSA signature algorithm. 218 Dsa = 2, 219 /// ECDSA signature algorithm. 220 Ecdsa = 3, 221 /// ED25519 signature algorithm. 222 Ed25519 = 7, 223 /// ED448 signature algorithm. 224 Ed448 = 8, 225 } 226 227 /// Hashing algorithm as defined in [RFC 5246 section 7.4.1.4.1]. 228 /// 229 /// [RFC 5246 section 7.4.1.4.1]: https://datatracker.ietf.org/doc/html/rfc5246#section-7.4.1.4.1 230 #[derive(PartialEq, Debug, TlsDeserializeBytes, TlsSerializeBytes, TlsSize)] 231 #[repr(u8)] 232 pub enum HashAlgorithm { 233 /// No algorithm. 234 None = 0, 235 /// MD5 algorithm. 236 Md5 = 1, 237 /// SHA1 algorithm. 238 Sha1 = 2, 239 /// SHA224 algorithm. 240 Sha224 = 3, 241 /// SHA256 algorithm. 242 Sha256 = 4, 243 /// SHA384 algorithm. 244 Sha384 = 5, 245 /// SHA512 algorithm. 246 Sha512 = 6, 247 /// Intrinsic algorithm. 248 Intrinsic = 8, 249 } 250 251 #[cfg(test)] 252 mod tests { 253 use der::{asn1::OctetString, Decode, Encode}; 254 use tls_codec::{DeserializeBytes, SerializeBytes, TlsByteVecU16}; 255 256 use crate::ext::pkix::sct::LogId; 257 258 use super::{ 259 DigitallySigned, HashAlgorithm, SerializedSct, SignatureAlgorithm, 260 SignatureAndHashAlgorithm, SignedCertificateTimestamp, SignedCertificateTimestampList, 261 Version, 262 }; 263 run_deserialization_test<'a, T: DeserializeBytes + PartialEq + core::fmt::Debug>( bytes: &'a [u8], expected_result: Result<(T, &[u8]), tls_codec::Error>, ) -> Result<(T, &'a [u8]), tls_codec::Error>264 fn run_deserialization_test<'a, T: DeserializeBytes + PartialEq + core::fmt::Debug>( 265 bytes: &'a [u8], 266 expected_result: Result<(T, &[u8]), tls_codec::Error>, 267 ) -> Result<(T, &'a [u8]), tls_codec::Error> { 268 let actual_result = T::tls_deserialize_bytes(bytes); 269 assert_eq!(actual_result, expected_result); 270 actual_result 271 } 272 run_serialization_test<T: SerializeBytes>(value: T, expected_bytes: &[u8])273 fn run_serialization_test<T: SerializeBytes>(value: T, expected_bytes: &[u8]) { 274 let result = value.tls_serialize().expect("failed to serialize value"); 275 assert_eq!(expected_bytes, &result); 276 } 277 278 #[test] test_hash_algorithm_deserialization()279 fn test_hash_algorithm_deserialization() { 280 let bytes = [0, 1, 2, 3, 4, 5, 6, 8]; 281 282 let result = run_deserialization_test( 283 &bytes, 284 Ok((HashAlgorithm::None, [1, 2, 3, 4, 5, 6, 8].as_slice())), 285 ); 286 let result = run_deserialization_test( 287 result.expect("run_deserialization_test failed").1, 288 Ok((HashAlgorithm::Md5, [2, 3, 4, 5, 6, 8].as_slice())), 289 ); 290 let result = run_deserialization_test( 291 result.expect("run_deserialization_test failed").1, 292 Ok((HashAlgorithm::Sha1, [3, 4, 5, 6, 8].as_slice())), 293 ); 294 let result = run_deserialization_test( 295 result.expect("run_deserialization_test failed").1, 296 Ok((HashAlgorithm::Sha224, [4, 5, 6, 8].as_slice())), 297 ); 298 let result = run_deserialization_test( 299 result.expect("run_deserialization_test failed").1, 300 Ok((HashAlgorithm::Sha256, [5, 6, 8].as_slice())), 301 ); 302 let result = run_deserialization_test( 303 result.expect("run_deserialization_test failed").1, 304 Ok((HashAlgorithm::Sha384, [6, 8].as_slice())), 305 ); 306 let result = run_deserialization_test( 307 result.expect("run_deserialization_test failed").1, 308 Ok((HashAlgorithm::Sha512, [8].as_slice())), 309 ); 310 let result = run_deserialization_test( 311 result.expect("run_deserialization_test failed").1, 312 Ok((HashAlgorithm::Intrinsic, [].as_slice())), 313 ); 314 let _ = run_deserialization_test::<HashAlgorithm>( 315 result.expect("run_deserialization_test failed").1, 316 Err(tls_codec::Error::EndOfStream), 317 ); 318 let _ = 319 run_deserialization_test::<HashAlgorithm>(&[7], Err(tls_codec::Error::UnknownValue(7))); 320 let _ = 321 run_deserialization_test::<HashAlgorithm>(&[9], Err(tls_codec::Error::UnknownValue(9))); 322 } 323 324 #[test] test_hash_algorithm_serialization()325 fn test_hash_algorithm_serialization() { 326 run_serialization_test(HashAlgorithm::None, &[0]); 327 run_serialization_test(HashAlgorithm::Md5, &[1]); 328 run_serialization_test(HashAlgorithm::Sha1, &[2]); 329 run_serialization_test(HashAlgorithm::Sha224, &[3]); 330 run_serialization_test(HashAlgorithm::Sha256, &[4]); 331 run_serialization_test(HashAlgorithm::Sha384, &[5]); 332 run_serialization_test(HashAlgorithm::Sha512, &[6]); 333 run_serialization_test(HashAlgorithm::Intrinsic, &[8]); 334 } 335 336 #[test] test_signature_algorithm_deserialization()337 fn test_signature_algorithm_deserialization() { 338 let bytes = [0, 1, 2, 3, 7, 8]; 339 340 let result = run_deserialization_test( 341 &bytes, 342 Ok((SignatureAlgorithm::Anonymous, [1, 2, 3, 7, 8].as_slice())), 343 ); 344 let result = run_deserialization_test( 345 result.expect("run_deserialization_test failed").1, 346 Ok((SignatureAlgorithm::Rsa, [2, 3, 7, 8].as_slice())), 347 ); 348 let result = run_deserialization_test( 349 result.expect("run_deserialization_test failed").1, 350 Ok((SignatureAlgorithm::Dsa, [3, 7, 8].as_slice())), 351 ); 352 let result = run_deserialization_test( 353 result.expect("run_deserialization_test failed").1, 354 Ok((SignatureAlgorithm::Ecdsa, [7, 8].as_slice())), 355 ); 356 let result = run_deserialization_test( 357 result.expect("run_deserialization_test failed").1, 358 Ok((SignatureAlgorithm::Ed25519, [8].as_slice())), 359 ); 360 let result = run_deserialization_test( 361 result.expect("run_deserialization_test failed").1, 362 Ok((SignatureAlgorithm::Ed448, [].as_slice())), 363 ); 364 let _ = run_deserialization_test::<SignatureAlgorithm>( 365 result.expect("run_deserialization_test failed").1, 366 Err(tls_codec::Error::EndOfStream), 367 ); 368 let _ = run_deserialization_test::<SignatureAlgorithm>( 369 &[4], 370 Err(tls_codec::Error::UnknownValue(4)), 371 ); 372 let _ = run_deserialization_test::<SignatureAlgorithm>( 373 &[5], 374 Err(tls_codec::Error::UnknownValue(5)), 375 ); 376 let _ = run_deserialization_test::<SignatureAlgorithm>( 377 &[6], 378 Err(tls_codec::Error::UnknownValue(6)), 379 ); 380 let _ = run_deserialization_test::<SignatureAlgorithm>( 381 &[9], 382 Err(tls_codec::Error::UnknownValue(9)), 383 ); 384 } 385 386 #[test] test_signature_algorithm_serialization()387 fn test_signature_algorithm_serialization() { 388 run_serialization_test(SignatureAlgorithm::Anonymous, &[0]); 389 run_serialization_test(SignatureAlgorithm::Rsa, &[1]); 390 run_serialization_test(SignatureAlgorithm::Dsa, &[2]); 391 run_serialization_test(SignatureAlgorithm::Ecdsa, &[3]); 392 run_serialization_test(SignatureAlgorithm::Ed25519, &[7]); 393 run_serialization_test(SignatureAlgorithm::Ed448, &[8]); 394 } 395 396 #[test] test_signature_and_hash_algorithm_deserialization()397 fn test_signature_and_hash_algorithm_deserialization() { 398 let bytes = [4, 3, 2, 1]; 399 400 let result = run_deserialization_test( 401 &bytes, 402 Ok(( 403 SignatureAndHashAlgorithm { 404 hash: HashAlgorithm::Sha256, 405 signature: SignatureAlgorithm::Ecdsa, 406 }, 407 [2, 1].as_slice(), 408 )), 409 ); 410 411 let _ = run_deserialization_test( 412 result.expect("run_deserialization_test failed").1, 413 Ok(( 414 SignatureAndHashAlgorithm { 415 hash: HashAlgorithm::Sha1, 416 signature: SignatureAlgorithm::Rsa, 417 }, 418 [].as_slice(), 419 )), 420 ); 421 } 422 423 #[test] test_signature_and_hash_algorithm_serialization()424 fn test_signature_and_hash_algorithm_serialization() { 425 run_serialization_test( 426 SignatureAndHashAlgorithm { 427 hash: HashAlgorithm::Sha1, 428 signature: SignatureAlgorithm::Rsa, 429 }, 430 &[2, 1], 431 ); 432 run_serialization_test( 433 SignatureAndHashAlgorithm { 434 hash: HashAlgorithm::Sha256, 435 signature: SignatureAlgorithm::Ecdsa, 436 }, 437 &[4, 3], 438 ); 439 } 440 441 #[test] test_digitally_signed_deserialization()442 fn test_digitally_signed_deserialization() { 443 let bytes = [4, 3, 0, 3, 2, 1, 0, 2, 1, 0, 1, 9]; 444 445 let result = run_deserialization_test( 446 &bytes, 447 Ok(( 448 DigitallySigned { 449 algorithm: SignatureAndHashAlgorithm { 450 hash: HashAlgorithm::Sha256, 451 signature: SignatureAlgorithm::Ecdsa, 452 }, 453 signature: TlsByteVecU16::from_slice(&[2, 1, 0]), 454 }, 455 [2, 1, 0, 1, 9].as_slice(), 456 )), 457 ); 458 459 let _ = run_deserialization_test( 460 result.expect("run_deserialization_test failed").1, 461 Ok(( 462 DigitallySigned { 463 algorithm: SignatureAndHashAlgorithm { 464 hash: HashAlgorithm::Sha1, 465 signature: SignatureAlgorithm::Rsa, 466 }, 467 signature: TlsByteVecU16::from_slice(&[9]), 468 }, 469 [].as_slice(), 470 )), 471 ); 472 } 473 474 #[test] test_digitally_signed_serialization()475 fn test_digitally_signed_serialization() { 476 run_serialization_test( 477 DigitallySigned { 478 algorithm: SignatureAndHashAlgorithm { 479 hash: HashAlgorithm::Sha256, 480 signature: SignatureAlgorithm::Ecdsa, 481 }, 482 signature: TlsByteVecU16::from_slice(&[0, 1, 2]), 483 }, 484 &[4, 3, 0, 3, 0, 1, 2], 485 ); 486 run_serialization_test( 487 DigitallySigned { 488 algorithm: SignatureAndHashAlgorithm { 489 hash: HashAlgorithm::Sha1, 490 signature: SignatureAlgorithm::Rsa, 491 }, 492 signature: TlsByteVecU16::from_slice(&[0, 1, 2]), 493 }, 494 &[2, 1, 0, 3, 0, 1, 2], 495 ); 496 } 497 498 #[test] test_version_deserialization()499 fn test_version_deserialization() { 500 let bytes = [0, 0]; 501 502 let result = run_deserialization_test(&bytes, Ok((Version::V1, [0].as_slice()))); 503 504 let _ = run_deserialization_test( 505 result.expect("run_deserialization_test failed").1, 506 Ok((Version::V1, [].as_slice())), 507 ); 508 let _ = run_deserialization_test::<Version>(&[1], Err(tls_codec::Error::UnknownValue(1))); 509 } 510 511 #[test] test_version_serialization()512 fn test_version_serialization() { 513 run_serialization_test(Version::V1, &[0]); 514 } 515 516 #[test] test_log_id_deserialization()517 fn test_log_id_deserialization() { 518 let bytes = [42; 36]; 519 520 let _ = 521 run_deserialization_test(&bytes, Ok((LogId { key_id: [42; 32] }, [42; 4].as_slice()))); 522 } 523 524 #[test] test_log_id_serialization()525 fn test_log_id_serialization() { 526 run_serialization_test(LogId { key_id: [3; 32] }, &[3; 32]); 527 } 528 529 const TLS_SCT_EXAMPLE: [u8; 119] = [ 530 0, 122, 50, 140, 84, 216, 183, 45, 182, 32, 234, 56, 224, 82, 30, 233, 132, 22, 112, 50, 531 19, 133, 77, 59, 210, 43, 193, 58, 87, 163, 82, 235, 82, 0, 0, 1, 135, 224, 74, 186, 106, 532 0, 0, 4, 3, 0, 72, 48, 70, 2, 33, 0, 170, 82, 81, 162, 157, 234, 14, 189, 167, 13, 247, 533 211, 97, 112, 248, 172, 149, 125, 58, 18, 238, 60, 150, 157, 124, 245, 188, 138, 102, 212, 534 244, 187, 2, 33, 0, 209, 79, 31, 63, 208, 79, 240, 233, 193, 187, 28, 33, 190, 95, 130, 66, 535 183, 222, 187, 42, 22, 83, 0, 119, 226, 246, 19, 197, 47, 237, 198, 149, 536 ]; 537 538 #[test] test_sct_deserialization()539 fn test_sct_deserialization() { 540 let _ = run_deserialization_test( 541 &TLS_SCT_EXAMPLE, 542 Ok(( 543 SignedCertificateTimestamp { 544 version: Version::V1, 545 log_id: LogId { 546 key_id: TLS_SCT_EXAMPLE[1..33] 547 .try_into() 548 .expect("failed to convert to u8 array"), 549 }, 550 timestamp: u64::from_be_bytes( 551 TLS_SCT_EXAMPLE[33..41] 552 .try_into() 553 .expect("failed to convert to u8 array"), 554 ), 555 extensions: TlsByteVecU16::from_slice(&[]), 556 signature: DigitallySigned { 557 algorithm: SignatureAndHashAlgorithm { 558 hash: HashAlgorithm::Sha256, 559 signature: SignatureAlgorithm::Ecdsa, 560 }, 561 signature: TlsByteVecU16::from_slice(&TLS_SCT_EXAMPLE[47..]), 562 }, 563 }, 564 &[], 565 )), 566 ); 567 } 568 569 #[test] test_sct_serialization()570 fn test_sct_serialization() { 571 run_serialization_test( 572 SignedCertificateTimestamp { 573 version: Version::V1, 574 log_id: LogId { 575 key_id: TLS_SCT_EXAMPLE[1..33] 576 .try_into() 577 .expect("failed to convert to u8 array"), 578 }, 579 timestamp: u64::from_be_bytes( 580 TLS_SCT_EXAMPLE[33..41] 581 .try_into() 582 .expect("failed to convert to u8 array"), 583 ), 584 extensions: TlsByteVecU16::from_slice(&[]), 585 signature: DigitallySigned { 586 algorithm: SignatureAndHashAlgorithm { 587 hash: HashAlgorithm::Sha256, 588 signature: SignatureAlgorithm::Ecdsa, 589 }, 590 signature: TlsByteVecU16::from_slice(&TLS_SCT_EXAMPLE[47..]), 591 }, 592 }, 593 &TLS_SCT_EXAMPLE, 594 ); 595 } 596 597 const SCT_EXAMPLE: [u8; 245] = [ 598 4, 129, 242, 0, 240, 0, 119, 0, 122, 50, 140, 84, 216, 183, 45, 182, 32, 234, 56, 224, 82, 599 30, 233, 132, 22, 112, 50, 19, 133, 77, 59, 210, 43, 193, 58, 87, 163, 82, 235, 82, 0, 0, 600 1, 135, 224, 74, 186, 106, 0, 0, 4, 3, 0, 72, 48, 70, 2, 33, 0, 170, 82, 81, 162, 157, 234, 601 14, 189, 167, 13, 247, 211, 97, 112, 248, 172, 149, 125, 58, 18, 238, 60, 150, 157, 124, 602 245, 188, 138, 102, 212, 244, 187, 2, 33, 0, 209, 79, 31, 63, 208, 79, 240, 233, 193, 187, 603 28, 33, 190, 95, 130, 66, 183, 222, 187, 42, 22, 83, 0, 119, 226, 246, 19, 197, 47, 237, 604 198, 149, 0, 117, 0, 173, 247, 190, 250, 124, 255, 16, 200, 139, 157, 61, 156, 30, 62, 24, 605 106, 180, 103, 41, 93, 207, 177, 12, 36, 202, 133, 134, 52, 235, 220, 130, 138, 0, 0, 1, 606 135, 224, 74, 186, 164, 0, 0, 4, 3, 0, 70, 48, 68, 2, 32, 29, 110, 144, 37, 157, 227, 170, 607 70, 67, 16, 68, 195, 212, 168, 246, 37, 94, 69, 210, 136, 42, 113, 217, 230, 34, 152, 253, 608 116, 13, 174, 232, 191, 2, 32, 16, 25, 200, 223, 59, 176, 40, 145, 76, 85, 242, 133, 130, 609 212, 61, 216, 83, 238, 115, 130, 82, 240, 196, 162, 249, 54, 199, 120, 175, 72, 223, 14, 610 ]; 611 612 #[test] test_sct_list_deserialization()613 fn test_sct_list_deserialization() { 614 fn run_test( 615 bytes: &[u8], 616 expected_result: Result<SignedCertificateTimestampList, der::Error>, 617 ) -> Result<SignedCertificateTimestampList, der::Error> { 618 let actual_result = SignedCertificateTimestampList::from_der(bytes); 619 assert_eq!(actual_result, expected_result); 620 actual_result 621 } 622 623 let result = run_test( 624 &SCT_EXAMPLE, 625 Ok(SignedCertificateTimestampList( 626 OctetString::new(&SCT_EXAMPLE[3..]).expect("failed to convert to u8 array"), 627 )), 628 ); 629 let scts = result 630 .expect("run_test failed") 631 .parse_timestamps() 632 .expect("parse_timestamps failed"); 633 assert_eq!( 634 scts[0].parse_timestamp(), 635 Ok(SignedCertificateTimestamp { 636 version: Version::V1, 637 log_id: LogId { 638 key_id: SCT_EXAMPLE[8..40] 639 .try_into() 640 .expect("failed to convert to u8 array"), 641 }, 642 timestamp: u64::from_be_bytes( 643 SCT_EXAMPLE[40..48] 644 .try_into() 645 .expect("failed to convert to u8 array") 646 ), 647 extensions: TlsByteVecU16::from_slice(&[]), 648 signature: DigitallySigned { 649 algorithm: SignatureAndHashAlgorithm { 650 hash: HashAlgorithm::Sha256, 651 signature: SignatureAlgorithm::Ecdsa, 652 }, 653 signature: TlsByteVecU16::from_slice(&SCT_EXAMPLE[54..126]), 654 }, 655 }) 656 ); 657 assert_eq!( 658 scts[1].parse_timestamp(), 659 Ok(SignedCertificateTimestamp { 660 version: Version::V1, 661 log_id: LogId { 662 key_id: SCT_EXAMPLE[129..161] 663 .try_into() 664 .expect("failed to convert to u8 array"), 665 }, 666 timestamp: u64::from_be_bytes( 667 SCT_EXAMPLE[161..169] 668 .try_into() 669 .expect("failed to convert to u8 array") 670 ), 671 extensions: TlsByteVecU16::from_slice(&[]), 672 signature: DigitallySigned { 673 algorithm: SignatureAndHashAlgorithm { 674 hash: HashAlgorithm::Sha256, 675 signature: SignatureAlgorithm::Ecdsa, 676 }, 677 signature: TlsByteVecU16::from_slice(&SCT_EXAMPLE[175..]), 678 }, 679 }) 680 ); 681 } 682 683 #[test] test_sct_list_serialization()684 fn test_sct_list_serialization() { 685 let serialized_sct1 = SerializedSct::new(SignedCertificateTimestamp { 686 version: Version::V1, 687 log_id: LogId { 688 key_id: SCT_EXAMPLE[8..40] 689 .try_into() 690 .expect("failed to convert to u8 array"), 691 }, 692 timestamp: u64::from_be_bytes( 693 SCT_EXAMPLE[40..48] 694 .try_into() 695 .expect("failed to convert to u8 array"), 696 ), 697 extensions: TlsByteVecU16::from_slice(&[]), 698 signature: DigitallySigned { 699 algorithm: SignatureAndHashAlgorithm { 700 hash: HashAlgorithm::Sha256, 701 signature: SignatureAlgorithm::Ecdsa, 702 }, 703 signature: TlsByteVecU16::from_slice(&SCT_EXAMPLE[54..126]), 704 }, 705 }) 706 .expect("failed to create SerializedSct"); 707 let serialized_sct2 = SerializedSct::new(SignedCertificateTimestamp { 708 version: Version::V1, 709 log_id: LogId { 710 key_id: SCT_EXAMPLE[129..161] 711 .try_into() 712 .expect("failed to convert to u8 array"), 713 }, 714 timestamp: u64::from_be_bytes( 715 SCT_EXAMPLE[161..169] 716 .try_into() 717 .expect("failed to convert to u8 array"), 718 ), 719 extensions: TlsByteVecU16::from_slice(&[]), 720 signature: DigitallySigned { 721 algorithm: SignatureAndHashAlgorithm { 722 hash: HashAlgorithm::Sha256, 723 signature: SignatureAlgorithm::Ecdsa, 724 }, 725 signature: TlsByteVecU16::from_slice(&SCT_EXAMPLE[175..]), 726 }, 727 }) 728 .expect("failed to create SerializedSct"); 729 let list = SignedCertificateTimestampList::new(&[serialized_sct1, serialized_sct2]) 730 .expect("failed to create SignedCertificateTimestampList"); 731 let der = list.to_der().expect("failed to convert to der"); 732 assert_eq!(der.as_slice(), SCT_EXAMPLE.as_slice()); 733 } 734 } 735