summaryrefslogtreecommitdiff
path: root/chromium/net/cert/internal/parsed_certificate.h
blob: a5ad843e0015fd351b05da8a414138c0dfc090b7 (plain)
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef NET_CERT_INTERNAL_PARSED_CERTIFICATE_H_
#define NET_CERT_INTERNAL_PARSED_CERTIFICATE_H_

#include <map>
#include <memory>
#include <vector>

#include "base/check.h"
#include "base/memory/ref_counted.h"
#include "net/base/net_export.h"
#include "net/cert/internal/certificate_policies.h"
#include "net/cert/internal/parse_certificate.h"
#include "net/der/input.h"
#include "third_party/boringssl/src/include/openssl/base.h"

namespace net {

struct GeneralNames;
class NameConstraints;
class ParsedCertificate;
class SignatureAlgorithm;
class CertErrors;

using ParsedCertificateList = std::vector<scoped_refptr<ParsedCertificate>>;

// Represents an X.509 certificate, including Certificate, TBSCertificate, and
// standard extensions.
// Creating a ParsedCertificate does not completely parse and validate the
// certificate data. Presence of a member in this class implies the DER was
// parsed successfully to that level, but does not imply the contents of that
// member are valid, unless otherwise specified. See the documentation for each
// member or the documentation of the type it returns.
class NET_EXPORT ParsedCertificate
    : public base::RefCountedThreadSafe<ParsedCertificate> {
 public:
  // Map from OID to ParsedExtension.
  using ExtensionsMap = std::map<der::Input, ParsedExtension>;

  // Creates a ParsedCertificate given a DER-encoded Certificate. Returns
  // nullptr on failure. Failure will occur if the standard certificate fields
  // and supported extensions cannot be parsed.
  // On either success or failure, if |errors| is non-null it may have error
  // information added to it.
  static scoped_refptr<ParsedCertificate> Create(
      bssl::UniquePtr<CRYPTO_BUFFER> cert_data,
      const ParseCertificateOptions& options,
      CertErrors* errors);

  // Creates a ParsedCertificate by copying the provided |data|, and appends it
  // to |chain|. Returns true if the certificate was successfully parsed and
  // added. If false is return, |chain| is unmodified.
  //
  // On either success or failure, if |errors| is non-null it may have error
  // information added to it.
  static bool CreateAndAddToVector(
      bssl::UniquePtr<CRYPTO_BUFFER> cert_data,
      const ParseCertificateOptions& options,
      std::vector<scoped_refptr<net::ParsedCertificate>>* chain,
      CertErrors* errors);

  // Like Create() this builds a ParsedCertificate given a DER-encoded
  // Certificate and returns nullptr on failure.
  //
  // However a copy of |data| is NOT made.
  //
  // This is a dangerous way to create as ParsedCertificate and should only be
  // used with care when saving a copy is really worth it, or the data is known
  // to come from static storage (and hence remain valid for entire life of
  // process).
  //
  // ParsedCertificate is reference counted, so it is easy to extend the life
  // and and end up with a ParsedCertificate referencing feed memory.
  //
  // On either success or failure, if |errors| is non-null it may have error
  // information added to it.
  static scoped_refptr<ParsedCertificate> CreateWithoutCopyingUnsafe(
      const uint8_t* data,
      size_t length,
      const ParseCertificateOptions& options,
      CertErrors* errors);

  // Returns the DER-encoded certificate data for this cert.
  const der::Input& der_cert() const { return cert_; }

  // Accessors for raw fields of the Certificate.
  const der::Input& tbs_certificate_tlv() const { return tbs_certificate_tlv_; }

  const der::Input& signature_algorithm_tlv() const {
    return signature_algorithm_tlv_;
  }

  const der::BitString& signature_value() const { return signature_value_; }

  // Accessor for struct containing raw fields of the TbsCertificate.
  const ParsedTbsCertificate& tbs() const { return tbs_; }

  // Returns the signatureAlgorithm of the Certificate (not the tbsCertificate).
  const SignatureAlgorithm& signature_algorithm() const {
    DCHECK(signature_algorithm_);
    return *signature_algorithm_;
  }

  // Returns the DER-encoded normalized subject value (not including outer
  // Sequence tag). This is gauranteed to be valid DER, though the contents of
  // unhandled string types are treated as raw bytes.
  der::Input normalized_subject() const {
    return der::Input(&normalized_subject_);
  }
  // Returns the DER-encoded normalized issuer value (not including outer
  // Sequence tag). This is gauranteed to be valid DER, though the contents of
  // unhandled string types are treated as raw bytes.
  der::Input normalized_issuer() const {
    return der::Input(&normalized_issuer_);
  }

  // Returns true if the certificate has a BasicConstraints extension.
  bool has_basic_constraints() const { return has_basic_constraints_; }

  // Returns the ParsedBasicConstraints struct. Caller must check
  // has_basic_constraints() before accessing this.
  const ParsedBasicConstraints& basic_constraints() const {
    DCHECK(has_basic_constraints_);
    return basic_constraints_;
  }

  // Returns true if the certificate has a KeyUsage extension.
  bool has_key_usage() const { return has_key_usage_; }

  // Returns the KeyUsage BitString. Caller must check
  // has_key_usage() before accessing this.
  const der::BitString& key_usage() const {
    DCHECK(has_key_usage_);
    return key_usage_;
  }

  // Returns true if the certificate has a ExtendedKeyUsage extension.
  bool has_extended_key_usage() const { return has_extended_key_usage_; }

  // Returns the ExtendedKeyUsage key purpose OIDs. Caller must check
  // has_extended_key_usage() before accessing this.
  const std::vector<der::Input>& extended_key_usage() const {
    DCHECK(has_extended_key_usage_);
    return extended_key_usage_;
  }

  // Returns true if the certificate has a SubjectAltName extension.
  bool has_subject_alt_names() const { return subject_alt_names_ != nullptr; }

  // Returns the ParsedExtension struct for the SubjectAltName extension.
  // If the cert did not have a SubjectAltName extension, this will be a
  // default-initialized ParsedExtension struct.
  const ParsedExtension& subject_alt_names_extension() const {
    return subject_alt_names_extension_;
  }

  // Returns the GeneralNames class parsed from SubjectAltName extension, or
  // nullptr if no SubjectAltName extension was present.
  const GeneralNames* subject_alt_names() const {
    return subject_alt_names_.get();
  }

  // Returns true if the certificate has a NameConstraints extension.
  bool has_name_constraints() const { return name_constraints_ != nullptr; }

  // Returns the parsed NameConstraints extension. Must not be called if
  // has_name_constraints() is false.
  const NameConstraints& name_constraints() const {
    DCHECK(name_constraints_);
    return *name_constraints_;
  }

  // Returns true if the certificate has an AuthorityInfoAccess extension.
  bool has_authority_info_access() const { return has_authority_info_access_; }

  // Returns the ParsedExtension struct for the AuthorityInfoAccess extension.
  const ParsedExtension& authority_info_access_extension() const {
    return authority_info_access_extension_;
  }

  // Returns any caIssuers URIs from the AuthorityInfoAccess extension.
  const std::vector<base::StringPiece>& ca_issuers_uris() const {
    return ca_issuers_uris_;
  }

  // Returns any OCSP URIs from the AuthorityInfoAccess extension.
  const std::vector<base::StringPiece>& ocsp_uris() const { return ocsp_uris_; }

  // Returns true if the certificate has a Policies extension.
  bool has_policy_oids() const { return has_policy_oids_; }

  // Returns the policy OIDs. Caller must check has_policy_oids() before
  // accessing this.
  const std::vector<der::Input>& policy_oids() const {
    DCHECK(has_policy_oids());
    return policy_oids_;
  }

  // Returns true if the certificate has a PolicyConstraints extension.
  bool has_policy_constraints() const { return has_policy_constraints_; }

  // Returns the ParsedPolicyConstraints struct. Caller must check
  // has_policy_constraints() before accessing this.
  const ParsedPolicyConstraints& policy_constraints() const {
    DCHECK(has_policy_constraints_);
    return policy_constraints_;
  }

  // Returns true if the certificate has a PolicyMappings extension.
  bool has_policy_mappings() const { return has_policy_mappings_; }

  // Returns the PolicyMappings extension. Caller must check
  // has_policy_mappings() before accessing this.
  const std::vector<ParsedPolicyMapping>& policy_mappings() const {
    DCHECK(has_policy_mappings_);
    return policy_mappings_;
  }

  // Returns true if the certificate has a InhibitAnyPolicy extension.
  bool has_inhibit_any_policy() const { return has_inhibit_any_policy_; }

  // Returns the Inhibit Any Policy extension. Caller must check
  // has_inhibit_any_policy() before accessing this.
  uint8_t inhibit_any_policy() const {
    DCHECK(has_inhibit_any_policy_);
    return inhibit_any_policy_;
  }

  // Returns the AuthorityKeyIdentifier extension, or nullopt if there wasn't
  // one.
  const base::Optional<ParsedAuthorityKeyIdentifier>& authority_key_identifier()
      const {
    return authority_key_identifier_;
  }

  // Returns the SubjectKeyIdentifier extension, or nullopt if there wasn't
  // one.
  const base::Optional<der::Input>& subject_key_identifier() const {
    return subject_key_identifier_;
  }

  // Returns a map of all the extensions in the certificate.
  const ExtensionsMap& extensions() const { return extensions_; }

  // Gets the value for extension matching |extension_oid|. Returns false if the
  // extension is not present.
  bool GetExtension(const der::Input& extension_oid,
                    ParsedExtension* parsed_extension) const;

 private:
  friend class base::RefCountedThreadSafe<ParsedCertificate>;
  ParsedCertificate();
  ~ParsedCertificate();

  // Creates a ParsedCertificate.  If |backing_data| is non-null, the
  // certificate's DER-encoded data will be referenced from here. Otherwise the
  // certificate's data will be |static_data|, and the pointer MUST remain
  // valid and its data unmodified for the entirety of the program.
  static scoped_refptr<ParsedCertificate> CreateInternal(
      bssl::UniquePtr<CRYPTO_BUFFER> backing_data,
      der::Input static_data,
      const ParseCertificateOptions& options,
      CertErrors* errors);

  // The backing store for the certificate data. May be null if created by
  // CreateWithoutCopyingUnsafe.
  bssl::UniquePtr<CRYPTO_BUFFER> cert_data_;

  // Points to the raw certificate DER.
  der::Input cert_;

  der::Input tbs_certificate_tlv_;
  der::Input signature_algorithm_tlv_;
  der::BitString signature_value_;
  ParsedTbsCertificate tbs_;

  // The signatureAlgorithm from the Certificate.
  std::unique_ptr<SignatureAlgorithm> signature_algorithm_;

  // Normalized DER-encoded Subject (not including outer Sequence tag).
  std::string normalized_subject_;
  // Normalized DER-encoded Issuer (not including outer Sequence tag).
  std::string normalized_issuer_;

  // BasicConstraints extension.
  bool has_basic_constraints_ = false;
  ParsedBasicConstraints basic_constraints_;

  // KeyUsage extension.
  bool has_key_usage_ = false;
  der::BitString key_usage_;

  // ExtendedKeyUsage extension.
  bool has_extended_key_usage_ = false;
  std::vector<der::Input> extended_key_usage_;

  // Raw SubjectAltName extension.
  ParsedExtension subject_alt_names_extension_;
  // Parsed SubjectAltName extension.
  std::unique_ptr<GeneralNames> subject_alt_names_;

  // NameConstraints extension.
  std::unique_ptr<NameConstraints> name_constraints_;

  // AuthorityInfoAccess extension.
  bool has_authority_info_access_ = false;
  ParsedExtension authority_info_access_extension_;
  // CaIssuers and Ocsp URIs parsed from the AuthorityInfoAccess extension. Note
  // that the AuthorityInfoAccess may have contained other AccessDescriptions
  // which are not represented here.
  std::vector<base::StringPiece> ca_issuers_uris_;
  std::vector<base::StringPiece> ocsp_uris_;

  // Policies extension.
  bool has_policy_oids_ = false;
  std::vector<der::Input> policy_oids_;

  // Policy constraints extension.
  bool has_policy_constraints_ = false;
  ParsedPolicyConstraints policy_constraints_;

  // Policy mappings extension.
  bool has_policy_mappings_ = false;
  std::vector<ParsedPolicyMapping> policy_mappings_;

  // Inhibit Any Policy extension.
  bool has_inhibit_any_policy_ = false;
  uint8_t inhibit_any_policy_;

  // AuthorityKeyIdentifier extension.
  base::Optional<ParsedAuthorityKeyIdentifier> authority_key_identifier_;

  // SubjectKeyIdentifier extension.
  base::Optional<der::Input> subject_key_identifier_;

  // All of the extensions.
  ExtensionsMap extensions_;

  DISALLOW_COPY_AND_ASSIGN(ParsedCertificate);
};

}  // namespace net

#endif  // NET_CERT_INTERNAL_PARSED_CERTIFICATE_H_