File: x509_certificate_model.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (145 lines) | stat: -rw-r--r-- 5,919 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_COMMON_NET_X509_CERTIFICATE_MODEL_H_
#define CHROME_COMMON_NET_X509_CERTIFICATE_MODEL_H_

#include <string>
#include <string_view>
#include <variant>
#include <vector>

#include "base/containers/span.h"
#include "base/time/time.h"
#include "third_party/boringssl/src/include/openssl/pool.h"
#include "third_party/boringssl/src/pki/parse_certificate.h"
#include "third_party/boringssl/src/pki/parse_name.h"

// This namespace defines a set of functions to be used in UI-related bits of
// X509 certificates.
namespace x509_certificate_model {

struct Extension {
  std::string name;
  std::string value;
};

struct NotPresent : std::monostate {};
struct Error : std::monostate {};
using OptionalStringOrError = std::variant<Error, NotPresent, std::string>;

class X509CertificateModel {
 public:
  // Construct an X509CertificateModel from |cert_data|, which must must not be
  // nullptr.
  explicit X509CertificateModel(bssl::UniquePtr<CRYPTO_BUFFER> cert_data);
  X509CertificateModel(X509CertificateModel&& other);
  X509CertificateModel& operator=(X509CertificateModel&& other) = default;
  ~X509CertificateModel();

  // ---------------------------------------------------------------------------
  // These methods are always safe to call even if |cert_data| could not be
  // parsed.

  // Returns lower case hex SHA256 hash of the certificate data.
  std::string HashCertSHA256() const;

  // Get something that can be used as a title for the certificate, using the
  // following priority:
  //   subject commonName
  //   full subject
  //   dnsName or email address from subjectAltNames
  // If none of those are present, or certificate could not be parsed,
  // the hex SHA256 hash of the certificate data will be returned.
  std::string GetTitle() const;

  CRYPTO_BUFFER* cert_buffer() const { return cert_data_.get(); }
  bool is_valid() const { return parsed_successfully_; }

  // ---------------------------------------------------------------------------
  // The rest of the methods should only be called if |is_valid()| returns true.

  // Returns lower case hex SHA256 hash of the SPKI.
  std::string HashSpkiSHA256() const;

  std::string GetVersion() const;
  std::string GetSerialNumberHexified() const;

  // Get the validity notBefore and notAfter times, returning true on success
  // or false on error in parsing or converting to a base::Time.
  bool GetTimes(base::Time* not_before, base::Time* not_after) const;

  // These methods returns the issuer/subject commonName/orgName/orgUnitName
  // formatted as a string, if present. Returns NotPresent if the attribute
  // type was not present, or Error if there was a parsing error.
  // The Get{Issuer,Subject}CommonName methods return the last (most specific)
  // commonName, while the other methods return the first (most general) value.
  // This matches the NSS behaviour of CERT_GetCommonName, CERT_GetOrgName,
  // CERT_GetOrgUnitName.
  OptionalStringOrError GetIssuerCommonName() const;
  OptionalStringOrError GetIssuerOrgName() const;
  OptionalStringOrError GetIssuerOrgUnitName() const;
  OptionalStringOrError GetSubjectCommonName() const;
  OptionalStringOrError GetSubjectOrgName() const;
  OptionalStringOrError GetSubjectOrgUnitName() const;

  // Get the issuer/subject name as a text block with one line per
  // attribute-value pair. Will process IDN in commonName, showing original and
  // decoded forms. Returns NotPresent if the Name was an empty sequence.
  // (Although note that technically an empty issuer name is invalid.)
  OptionalStringOrError GetIssuerName() const;
  OptionalStringOrError GetSubjectName() const;

  // Returns textual representations of the certificate's extensions, if any.
  // |critical_label| and |non_critical_label| will be used in the returned
  // extension.value fields to describe extensions that are critical or
  // non-critical.
  std::vector<Extension> GetExtensions(
      std::string_view critical_label,
      std::string_view non_critical_label) const;

  std::string ProcessSecAlgorithmSignature() const;
  std::string ProcessSecAlgorithmSubjectPublicKey() const;
  std::string ProcessSecAlgorithmSignatureWrap() const;

  std::string ProcessSubjectPublicKeyInfo() const;

  std::string ProcessRawBitsSignatureWrap() const;

 private:
  bool ParseExtensions(const bssl::der::Input& extensions_tlv);
  std::string ProcessExtension(std::string_view critical_label,
                               std::string_view non_critical_label,
                               const bssl::ParsedExtension& extension) const;
  std::optional<std::string> ProcessExtensionData(
      const bssl::ParsedExtension& extension) const;

  bool parsed_successfully_ = false;
  bssl::UniquePtr<CRYPTO_BUFFER> cert_data_;
  bssl::der::Input tbs_certificate_tlv_;
  bssl::der::Input signature_algorithm_tlv_;
  bssl::der::BitString signature_value_;
  bssl::ParsedTbsCertificate tbs_;

  bssl::RDNSequence subject_rdns_;
  bssl::RDNSequence issuer_rdns_;
  std::vector<bssl::ParsedExtension> extensions_;

  // Parsed SubjectAltName extension.
  std::unique_ptr<bssl::GeneralNames> subject_alt_names_;
};

// For host values, if they contain IDN Punycode-encoded A-labels, this will
// return a string suitable for display that contains both the original and the
// decoded U-label form.  Otherwise, the string will be returned as is.
std::string ProcessIDN(const std::string& input);

// Parses |public_key_spki_der| as a DER-encoded X.509 SubjectPublicKeyInfo,
// then formats the public key as a string for displaying. Returns an empty
// string on error.
std::string ProcessRawSubjectPublicKeyInfo(base::span<const uint8_t> spki_der);

}  // namespace x509_certificate_model

#endif  // CHROME_COMMON_NET_X509_CERTIFICATE_MODEL_H_