Serenity Operating System
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}