Serenity Operating System
at master 540 lines 29 kB view raw
1/* 2 * Copyright (c) 2020, Ali Mohammad Pur <mpfard@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include "Certificate.h" 8#include <AK/Debug.h> 9#include <AK/IPv4Address.h> 10#include <LibCrypto/ASN1/ASN1.h> 11#include <LibCrypto/ASN1/DER.h> 12#include <LibCrypto/ASN1/PEM.h> 13 14namespace TLS { 15 16constexpr static Array<int, 4> 17 common_name_oid { 2, 5, 4, 3 }, 18 country_name_oid { 2, 5, 4, 6 }, 19 locality_name_oid { 2, 5, 4, 7 }, 20 organization_name_oid { 2, 5, 4, 10 }, 21 organizational_unit_name_oid { 2, 5, 4, 11 }; 22 23constexpr static Array<int, 7> 24 rsa_encryption_oid { 1, 2, 840, 113549, 1, 1, 1 }, 25 rsa_md5_encryption_oid { 1, 2, 840, 113549, 1, 1, 4 }, 26 rsa_sha1_encryption_oid { 1, 2, 840, 113549, 1, 1, 5 }, 27 rsa_sha256_encryption_oid { 1, 2, 840, 113549, 1, 1, 11 }, 28 rsa_sha384_encryption_oid { 1, 2, 840, 113549, 1, 1, 12 }, 29 rsa_sha512_encryption_oid { 1, 2, 840, 113549, 1, 1, 13 }; 30 31constexpr static Array<int, 4> 32 key_usage_oid { 2, 5, 29, 15 }, 33 subject_alternative_name_oid { 2, 5, 29, 17 }, 34 basic_constraints_oid { 2, 5, 29, 19 }; 35 36Optional<Certificate> Certificate::parse_asn1(ReadonlyBytes buffer, bool) 37{ 38#define ENTER_SCOPE_WITHOUT_TYPECHECK(scope) \ 39 do { \ 40 if (auto result = decoder.enter(); result.is_error()) { \ 41 dbgln_if(TLS_DEBUG, "Failed to enter object (" scope "): {}", result.error()); \ 42 return {}; \ 43 } \ 44 } while (0) 45 46#define ENTER_SCOPE_OR_FAIL(kind_name, scope) \ 47 do { \ 48 if (auto tag = decoder.peek(); tag.is_error() || tag.value().kind != Crypto::ASN1::Kind::kind_name) { \ 49 if constexpr (TLS_DEBUG) { \ 50 if (tag.is_error()) \ 51 dbgln(scope " data was invalid: {}", tag.error()); \ 52 else \ 53 dbgln(scope " data was not of kind " #kind_name); \ 54 } \ 55 return {}; \ 56 } \ 57 ENTER_SCOPE_WITHOUT_TYPECHECK(scope); \ 58 } while (0) 59 60#define EXIT_SCOPE(scope) \ 61 do { \ 62 if (auto error = decoder.leave(); error.is_error()) { \ 63 dbgln_if(TLS_DEBUG, "Error while exiting scope " scope ": {}", error.error()); \ 64 return {}; \ 65 } \ 66 } while (0) 67 68#define ENSURE_OBJECT_KIND(_kind_name, scope) \ 69 do { \ 70 if (auto tag = decoder.peek(); tag.is_error() || tag.value().kind != Crypto::ASN1::Kind::_kind_name) { \ 71 if constexpr (TLS_DEBUG) { \ 72 if (tag.is_error()) \ 73 dbgln(scope " data was invalid: {}", tag.error()); \ 74 else \ 75 dbgln(scope " data was not of kind " #_kind_name ", it was {}", Crypto::ASN1::kind_name(tag.value().kind)); \ 76 } \ 77 return {}; \ 78 } \ 79 } while (0) 80 81#define READ_OBJECT_OR_FAIL(kind_name, type_name, value_name, scope) \ 82 auto value_name##_result = decoder.read<type_name>(Crypto::ASN1::Class::Universal, Crypto::ASN1::Kind::kind_name); \ 83 if (value_name##_result.is_error()) { \ 84 dbgln_if(TLS_DEBUG, scope " read of kind " #kind_name " failed: {}", value_name##_result.error()); \ 85 return {}; \ 86 } \ 87 auto value_name = value_name##_result.release_value(); 88 89#define DROP_OBJECT_OR_FAIL(scope) \ 90 do { \ 91 if (auto error = decoder.drop(); error.is_error()) { \ 92 dbgln_if(TLS_DEBUG, scope " read failed: {}", error.error()); \ 93 } \ 94 } while (0) 95 96 Certificate certificate; 97 auto copy_buffer_result = ByteBuffer::copy(buffer.data(), buffer.size()); 98 if (copy_buffer_result.is_error()) 99 return {}; 100 certificate.original_asn1 = copy_buffer_result.release_value(); 101 102 Crypto::ASN1::Decoder decoder { buffer }; 103 // Certificate ::= Sequence { 104 // certificate TBSCertificate, 105 // signature_algorithm AlgorithmIdentifier, 106 // signature_value BitString 107 // } 108 ENTER_SCOPE_OR_FAIL(Sequence, "Certificate"); 109 110 // TBSCertificate ::= Sequence { 111 // version (0) EXPLICIT Version DEFAULT v1, 112 // serial_number CertificateSerialNumber, 113 // signature AlgorithmIdentifier, 114 // issuer Name, 115 // validity Validity, 116 // subject Name, 117 // subject_public_key_info SubjectPublicKeyInfo, 118 // issuer_unique_id (1) IMPLICIT UniqueIdentifier OPTIONAL (if present, version > v1), 119 // subject_unique_id (2) IMPLICIT UniqueIdentifier OPTIONAL (if present, version > v1), 120 // extensions (3) EXPLICIT Extensions OPTIONAL (if present, version > v2) 121 // } 122 ENTER_SCOPE_OR_FAIL(Sequence, "Certificate::TBSCertificate"); 123 124 // version 125 { 126 // Version :: Integer { v1(0), v2(1), v3(2) } (Optional) 127 if (auto tag = decoder.peek(); !tag.is_error() && tag.value().type == Crypto::ASN1::Type::Constructed) { 128 ENTER_SCOPE_WITHOUT_TYPECHECK("Certificate::version"); 129 READ_OBJECT_OR_FAIL(Integer, Crypto::UnsignedBigInteger, value, "Certificate::version"); 130 if (!(value < 3)) { 131 dbgln_if(TLS_DEBUG, "Certificate::version Invalid value for version: {}", value.to_base_deprecated(10)); 132 return {}; 133 } 134 certificate.version = value.words()[0]; 135 EXIT_SCOPE("Certificate::version"); 136 } else { 137 certificate.version = 0; 138 } 139 } 140 141 // serial_number 142 { 143 // CertificateSerialNumber :: Integer 144 READ_OBJECT_OR_FAIL(Integer, Crypto::UnsignedBigInteger, value, "Certificate::serial_number"); 145 certificate.serial_number = move(value); 146 } 147 148 auto parse_algorithm_identifier = [&](CertificateKeyAlgorithm& field) -> Optional<bool> { 149 // AlgorithmIdentifier ::= Sequence { 150 // algorithm ObjectIdentifier, 151 // parameters ANY OPTIONAL 152 // } 153 ENTER_SCOPE_OR_FAIL(Sequence, "AlgorithmIdentifier"); 154 READ_OBJECT_OR_FAIL(ObjectIdentifier, Vector<int>, identifier, "AlgorithmIdentifier::algorithm"); 155 if (identifier == rsa_encryption_oid) 156 field = CertificateKeyAlgorithm ::RSA_RSA; 157 else if (identifier == rsa_md5_encryption_oid) 158 field = CertificateKeyAlgorithm ::RSA_MD5; 159 else if (identifier == rsa_sha1_encryption_oid) 160 field = CertificateKeyAlgorithm ::RSA_SHA1; 161 else if (identifier == rsa_sha256_encryption_oid) 162 field = CertificateKeyAlgorithm ::RSA_SHA256; 163 else if (identifier == rsa_sha384_encryption_oid) 164 field = CertificateKeyAlgorithm ::RSA_SHA384; 165 else if (identifier == rsa_sha512_encryption_oid) 166 field = CertificateKeyAlgorithm ::RSA_SHA512; 167 else 168 return {}; 169 170 EXIT_SCOPE("AlgorithmIdentifier"); 171 return true; 172 }; 173 174 // signature 175 { 176 if (!parse_algorithm_identifier(certificate.algorithm).has_value()) 177 return {}; 178 } 179 180 auto parse_name = [&](auto& name_struct) -> Optional<bool> { 181 // Name ::= Choice { 182 // rdn_sequence RDNSequence 183 // } // NOTE: since this is the only alternative, there's no index 184 // RDNSequence ::= Sequence OF RelativeDistinguishedName 185 ENTER_SCOPE_OR_FAIL(Sequence, "Certificate::TBSCertificate::issuer/subject"); 186 187 // RelativeDistinguishedName ::= Set OF AttributeTypeAndValue 188 // AttributeTypeAndValue ::= Sequence { 189 // type AttributeType, 190 // value AttributeValue 191 // } 192 // AttributeType ::= ObjectIdentifier 193 // AttributeValue ::= Any 194 while (!decoder.eof()) { 195 // Parse only the required fields, and ignore the rest. 196 ENTER_SCOPE_OR_FAIL(Set, "Certificate::TBSCertificate::issuer/subject::$::RelativeDistinguishedName"); 197 while (!decoder.eof()) { 198 ENTER_SCOPE_OR_FAIL(Sequence, "Certificate::TBSCertificate::issuer/subject::$::RelativeDistinguishedName::$::AttributeTypeAndValue"); 199 ENSURE_OBJECT_KIND(ObjectIdentifier, "Certificate::TBSCertificate::issuer/subject::$::RelativeDistinguishedName::$::AttributeTypeAndValue::type"); 200 201 if (auto type_identifier_or_error = decoder.read<Vector<int>>(); !type_identifier_or_error.is_error()) { 202 // Figure out what type of identifier this is 203 auto& identifier = type_identifier_or_error.value(); 204 if (identifier == common_name_oid) { 205 READ_OBJECT_OR_FAIL(PrintableString, StringView, name, 206 "Certificate::TBSCertificate::issuer/subject::$::RelativeDistinguishedName::$::AttributeTypeAndValue::Value"); 207 name_struct.subject = name; 208 } else if (identifier == country_name_oid) { 209 READ_OBJECT_OR_FAIL(PrintableString, StringView, name, 210 "Certificate::TBSCertificate::issuer/subject::$::RelativeDistinguishedName::$::AttributeTypeAndValue::Value"); 211 name_struct.country = name; 212 } else if (identifier == locality_name_oid) { 213 READ_OBJECT_OR_FAIL(PrintableString, StringView, name, 214 "Certificate::TBSCertificate::issuer/subject::$::RelativeDistinguishedName::$::AttributeTypeAndValue::Value"); 215 name_struct.location = name; 216 } else if (identifier == organization_name_oid) { 217 READ_OBJECT_OR_FAIL(PrintableString, StringView, name, 218 "Certificate::TBSCertificate::issuer/subject::$::RelativeDistinguishedName::$::AttributeTypeAndValue::Value"); 219 name_struct.entity = name; 220 } else if (identifier == organizational_unit_name_oid) { 221 READ_OBJECT_OR_FAIL(PrintableString, StringView, name, 222 "Certificate::TBSCertificate::issuer/subject::$::RelativeDistinguishedName::$::AttributeTypeAndValue::Value"); 223 name_struct.unit = name; 224 } 225 } else { 226 dbgln_if(TLS_DEBUG, "Certificate::TBSCertificate::issuer/subject::$::RelativeDistinguishedName::$::AttributeTypeAndValue::type data was invalid: {}", type_identifier_or_error.error()); 227 return {}; 228 } 229 230 EXIT_SCOPE("Certificate::TBSCertificate::issuer/subject::$::RelativeDistinguishedName::$::AttributeTypeAndValue"); 231 } 232 EXIT_SCOPE("Certificate::TBSCertificate::issuer/subject::$::RelativeDistinguishedName"); 233 } 234 235 EXIT_SCOPE("Certificate::TBSCertificate::issuer/subject"); 236 return true; 237 }; 238 239 // issuer 240 { 241 if (!parse_name(certificate.issuer).has_value()) 242 return {}; 243 } 244 245 // validity 246 { 247 ENTER_SCOPE_OR_FAIL(Sequence, "Certificate::TBSCertificate::Validity"); 248 249 auto parse_time = [&](Core::DateTime& datetime) -> Optional<bool> { 250 // Time ::= Choice { 251 // utc_time UTCTime, 252 // general_time GeneralizedTime 253 // } 254 auto tag = decoder.peek(); 255 if (tag.is_error()) { 256 dbgln_if(1, "Certificate::TBSCertificate::Validity::$::Time failed to read tag: {}", tag.error()); 257 return {}; 258 }; 259 260 if (tag.value().kind == Crypto::ASN1::Kind::UTCTime) { 261 READ_OBJECT_OR_FAIL(UTCTime, StringView, time, "Certificate::TBSCertificate::Validity::$"); 262 auto result = Crypto::ASN1::parse_utc_time(time); 263 if (!result.has_value()) { 264 dbgln_if(1, "Certificate::TBSCertificate::Validity::$::Time Invalid UTC Time: {}", time); 265 return {}; 266 } 267 datetime = result.release_value(); 268 return true; 269 } 270 271 if (tag.value().kind == Crypto::ASN1::Kind::GeneralizedTime) { 272 READ_OBJECT_OR_FAIL(UTCTime, StringView, time, "Certificate::TBSCertificate::Validity::$"); 273 auto result = Crypto::ASN1::parse_generalized_time(time); 274 if (!result.has_value()) { 275 dbgln_if(1, "Certificate::TBSCertificate::Validity::$::Time Invalid Generalized Time: {}", time); 276 return {}; 277 } 278 datetime = result.release_value(); 279 return true; 280 } 281 282 dbgln_if(1, "Unrecognised Time format {}", Crypto::ASN1::kind_name(tag.value().kind)); 283 return {}; 284 }; 285 286 if (!parse_time(certificate.not_before).has_value()) 287 return {}; 288 289 if (!parse_time(certificate.not_after).has_value()) 290 return {}; 291 292 EXIT_SCOPE("Certificate::TBSCertificate::Validity"); 293 } 294 295 // subject 296 { 297 if (!parse_name(certificate.subject).has_value()) 298 return {}; 299 } 300 301 // subject_public_key_info 302 { 303 // SubjectPublicKeyInfo ::= Sequence { 304 // algorithm AlgorithmIdentifier, 305 // subject_public_key BitString 306 // } 307 ENTER_SCOPE_OR_FAIL(Sequence, "Certificate::TBSCertificate::subject_public_key_info"); 308 309 if (!parse_algorithm_identifier(certificate.key_algorithm).has_value()) 310 return {}; 311 312 READ_OBJECT_OR_FAIL(BitString, Crypto::ASN1::BitStringView, value, "Certificate::TBSCertificate::subject_public_key_info::subject_public_key_info"); 313 // Note: Once we support other kinds of keys, make sure to check the kind here! 314 auto key = Crypto::PK::RSA::parse_rsa_key(value.raw_bytes()); 315 if (!key.public_key.length()) { 316 dbgln_if(TLS_DEBUG, "Certificate::TBSCertificate::subject_public_key_info::subject_public_key_info: Invalid key"); 317 return {}; 318 } 319 certificate.public_key = move(key.public_key); 320 EXIT_SCOPE("Certificate::TBSCertificate::subject_public_key_info"); 321 } 322 323 auto parse_unique_identifier = [&]() -> Optional<bool> { 324 if (certificate.version == 0) 325 return true; 326 327 auto tag = decoder.peek(); 328 if (tag.is_error()) { 329 dbgln_if(TLS_DEBUG, "Certificate::TBSCertificate::*::UniqueIdentifier could not read tag: {}", tag.error()); 330 return {}; 331 } 332 333 // The spec says to just ignore these. 334 if (static_cast<u8>(tag.value().kind) == 1 || static_cast<u8>(tag.value().kind) == 2) 335 DROP_OBJECT_OR_FAIL("UniqueIdentifier"); 336 337 return true; 338 }; 339 340 // issuer_unique_identifier 341 { 342 if (!parse_unique_identifier().has_value()) 343 return {}; 344 } 345 346 // subject_unique_identifier 347 { 348 if (!parse_unique_identifier().has_value()) 349 return {}; 350 } 351 352 // extensions 353 { 354 if (certificate.version == 2) { 355 auto tag = decoder.peek(); 356 if (tag.is_error()) { 357 dbgln_if(TLS_DEBUG, "Certificate::TBSCertificate::*::UniqueIdentifier could not read tag: {}", tag.error()); 358 return {}; 359 } 360 if (static_cast<u8>(tag.value().kind) == 3) { 361 // Extensions ::= Sequence OF Extension 362 // Extension ::= Sequence { 363 // extension_id ObjectIdentifier, 364 // critical Boolean DEFAULT false, 365 // extension_value OctetString (DER-encoded) 366 // } 367 ENTER_SCOPE_WITHOUT_TYPECHECK("Certificate::TBSCertificate::Extensions(IMPLICIT)"); 368 ENTER_SCOPE_OR_FAIL(Sequence, "Certificate::TBSCertificate::Extensions"); 369 370 while (!decoder.eof()) { 371 ENTER_SCOPE_OR_FAIL(Sequence, "Certificate::TBSCertificate::Extensions::$::Extension"); 372 READ_OBJECT_OR_FAIL(ObjectIdentifier, Vector<int>, extension_id, "Certificate::TBSCertificate::Extensions::$::Extension::extension_id"); 373 bool is_critical = false; 374 if (auto tag = decoder.peek(); !tag.is_error() && tag.value().kind == Crypto::ASN1::Kind::Boolean) { 375 // Read the 'critical' property 376 READ_OBJECT_OR_FAIL(Boolean, bool, critical, "Certificate::TBSCertificate::Extensions::$::Extension::critical"); 377 is_critical = critical; 378 } 379 READ_OBJECT_OR_FAIL(OctetString, StringView, extension_value, "Certificate::TBSCertificate::Extensions::$::Extension::extension_value"); 380 381 // Figure out what this extension is. 382 if (extension_id == subject_alternative_name_oid) { 383 Crypto::ASN1::Decoder decoder { extension_value.bytes() }; 384 // SubjectAlternativeName ::= GeneralNames 385 // GeneralNames ::= Sequence OF GeneralName 386 // GeneralName ::= CHOICE { 387 // other_name (0) OtherName, 388 // rfc_822_name (1) IA5String, 389 // dns_name (2) IA5String, 390 // x400Address (3) ORAddress, 391 // directory_name (4) Name, 392 // edi_party_name (5) EDIPartyName, 393 // uri (6) IA5String, 394 // ip_address (7) OctetString, 395 // registered_id (8) ObjectIdentifier, 396 // } 397 ENTER_SCOPE_OR_FAIL(Sequence, "Certificate::TBSCertificate::Extensions::$::Extension::extension_value::SubjectAlternativeName"); 398 399 while (!decoder.eof()) { 400 auto tag = decoder.peek(); 401 if (tag.is_error()) { 402 dbgln_if(TLS_DEBUG, "Certificate::TBSCertificate::Extensions::$::Extension::extension_value::SubjectAlternativeName::$ could not read tag: {}", tag.error()); 403 return {}; 404 } 405 406 auto tag_value = static_cast<u8>(tag.value().kind); 407 switch (tag_value) { 408 case 0: 409 // OtherName 410 // We don't know how to use this. 411 DROP_OBJECT_OR_FAIL("Certificate::TBSCertificate::Extensions::$::Extension::extension_value::SubjectAlternativeName::$::OtherName"); 412 break; 413 case 1: 414 // RFC 822 name 415 // We don't know how to use this. 416 DROP_OBJECT_OR_FAIL("Certificate::TBSCertificate::Extensions::$::Extension::extension_value::SubjectAlternativeName::$::RFC822Name"); 417 break; 418 case 2: { 419 // DNS Name 420 READ_OBJECT_OR_FAIL(IA5String, StringView, name, "Certificate::TBSCertificate::Extensions::$::Extension::extension_value::SubjectAlternativeName::$::Name"); 421 certificate.SAN.append(name); 422 break; 423 } 424 case 3: 425 // x400Address 426 // We don't know how to use this. 427 DROP_OBJECT_OR_FAIL("Certificate::TBSCertificate::Extensions::$::Extension::extension_value::SubjectAlternativeName::$::X400Address"); 428 break; 429 case 4: 430 // Directory name 431 // We don't know how to use this. 432 DROP_OBJECT_OR_FAIL("Certificate::TBSCertificate::Extensions::$::Extension::extension_value::SubjectAlternativeName::$::DirectoryName"); 433 break; 434 case 5: 435 // edi party name 436 // We don't know how to use this. 437 DROP_OBJECT_OR_FAIL("Certificate::TBSCertificate::Extensions::$::Extension::extension_value::SubjectAlternativeName::$::EDIPartyName"); 438 break; 439 case 6: { 440 // URI 441 READ_OBJECT_OR_FAIL(IA5String, StringView, name, "Certificate::TBSCertificate::Extensions::$::Extension::extension_value::SubjectAlternativeName::$::URI"); 442 certificate.SAN.append(name); 443 break; 444 } 445 case 7: { 446 // IP Address 447 READ_OBJECT_OR_FAIL(OctetString, StringView, ip_addr_sv, "Certificate::TBSCertificate::Extensions::$::Extension::extension_value::SubjectAlternativeName::$::IPAddress"); 448 IPv4Address ip_addr { ip_addr_sv.bytes().data() }; 449 certificate.SAN.append(ip_addr.to_deprecated_string()); 450 break; 451 } 452 case 8: 453 // Registered ID 454 // We can't handle these. 455 DROP_OBJECT_OR_FAIL("Certificate::TBSCertificate::Extensions::$::Extension::extension_value::SubjectAlternativeName::$::RegisteredID"); 456 break; 457 default: 458 dbgln_if(TLS_DEBUG, "Unknown tag in SAN choice {}", tag_value); 459 if (is_critical) 460 return {}; 461 else 462 DROP_OBJECT_OR_FAIL("Certificate::TBSCertificate::Extensions::$::Extension::extension_value::SubjectAlternativeName::$::???"); 463 } 464 } 465 } else if (extension_id == key_usage_oid) { 466 // RFC5280 section 4.2.1.3: The keyCertSign bit is asserted when the subject public key is used 467 // for verifying signatures on public key certificates. If the keyCertSign bit is asserted, 468 // then the cA bit in the basic constraints extension MUST also be asserted. 469 Crypto::ASN1::Decoder decoder { extension_value.bytes() }; 470 READ_OBJECT_OR_FAIL(BitString, Crypto::ASN1::BitStringView, usage, "Certificate::TBSCertificate::Extensions::$::Extension::extension_value::KeyUsage"); 471 472 // keyCertSign (5) 473 certificate.is_allowed_to_sign_certificate = usage.get(5); 474 } else if (extension_id == basic_constraints_oid) { 475 // RFC5280 section 4.2.1.9: The cA boolean indicates whether the certified public key may be 476 // used to verify certificate signatures. If the cA boolean is not asserted, then the keyCertSign 477 // bit in the key usage extension MUST NOT be asserted. If the basic constraints extension is 478 // not present in a version 3 certificate, or the extension is present but the cA boolean is 479 // not asserted, then the certified public key MUST NOT be used to verify certificate signatures. 480 Crypto::ASN1::Decoder decoder { extension_value.bytes() }; 481 ENTER_SCOPE_OR_FAIL(Sequence, "Certificate::TBSCertificate::Extensions::$::Extension::extension_value::BasicConstraints"); 482 483 if (auto tag = decoder.peek(); !tag.is_error() && tag.value().kind == Crypto::ASN1::Kind::Boolean) { 484 READ_OBJECT_OR_FAIL(Boolean, bool, is_certificate_authority, "Certificate::TBSCertificate::Extensions::$::Extension::extension_value::BasicConstraints::cA"); 485 certificate.is_certificate_authority = is_certificate_authority; 486 487 if (auto tag = decoder.peek(); !tag.is_error() && tag.value().kind == Crypto::ASN1::Kind::Integer) { 488 READ_OBJECT_OR_FAIL(Integer, Crypto::UnsignedBigInteger, path_length_constraint, "Certificate::TBSCertificate::Extensions::$::Extension::extension_value::BasicConstraints::pathLenConstraint"); 489 certificate.path_length_constraint = path_length_constraint.to_u64(); 490 } 491 } 492 } else { 493 dbgln_if(TLS_DEBUG, "Certificate::TBSCertificate::Extensions::$::Extension::extension_id: unknown extension {} (critical: {})", extension_id, is_critical); 494 if (is_critical) 495 return {}; 496 } 497 498 EXIT_SCOPE("Certificate::TBSCertificate::Extensions::$::Extension"); 499 } 500 501 EXIT_SCOPE("Certificate::TBSCertificate::Extensions"); 502 EXIT_SCOPE("Certificate::TBSCertificate::Extensions(IMPLICIT)"); 503 } 504 } 505 } 506 507 EXIT_SCOPE("Certificate::TBSCertificate"); 508 509 // signature_algorithm 510 { 511 if (!parse_algorithm_identifier(certificate.signature_algorithm).has_value()) 512 return {}; 513 } 514 515 // signature_value 516 { 517 READ_OBJECT_OR_FAIL(BitString, Crypto::ASN1::BitStringView, value, "Certificate"); 518 auto signature_data_result = ByteBuffer::copy(value.raw_bytes()); 519 if (signature_data_result.is_error()) { 520 dbgln("Certificate::signature_value: out of memory"); 521 return {}; 522 } 523 certificate.signature_value = signature_data_result.release_value(); 524 } 525 526 EXIT_SCOPE("Certificate"); 527 528 dbgln_if(TLS_DEBUG, "Certificate issued for {} by {}", certificate.subject.subject, certificate.issuer.subject); 529 530 return certificate; 531 532#undef DROP_OBJECT_OR_FAIL 533#undef ENSURE_OBJECT_KIND 534#undef ENTER_SCOPE_OR_FAIL 535#undef ENTER_SCOPE_WITHOUT_TYPECHECK 536#undef EXIT_SCOPE 537#undef READ_OBJECT_OR_FAIL 538} 539 540}