blob: dc95287fbb5b0fb6fc2072a32469996ee0f21784 [file] [log] [blame]
vasilvv796f3662020-02-12 14:50:12 -08001// Copyright 2020 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/third_party/quiche/src/quic/core/crypto/certificate_view.h"
6
7#include <cstdint>
8#include <memory>
9
10#include "third_party/boringssl/src/include/openssl/bytestring.h"
11#include "third_party/boringssl/src/include/openssl/ec.h"
12#include "third_party/boringssl/src/include/openssl/evp.h"
13#include "third_party/boringssl/src/include/openssl/nid.h"
14#include "net/third_party/quiche/src/quic/core/crypto/boring_utils.h"
15#include "net/third_party/quiche/src/quic/platform/api/quic_ip_address.h"
16#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
17#include "net/third_party/quiche/src/quic/platform/api/quic_optional.h"
18#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
19
20// The literals below were encoded using `ascii2der | xxd -i`. The comments
21// above the literals are the contents in the der2ascii syntax.
22namespace {
23
24// X.509 version 3 (version numbering starts with zero).
25// INTEGER { 2 }
26constexpr uint8_t kX509Version[] = {0x02, 0x01, 0x02};
27
28// 2.5.29.17
29constexpr uint8_t kSubjectAltNameOid[] = {0x55, 0x1d, 0x11};
30
31} // namespace
32
33namespace quic {
34
35std::unique_ptr<CertificateView> CertificateView::ParseSingleCertificate(
36 quiche::QuicheStringPiece certificate) {
37 std::unique_ptr<CertificateView> result(new CertificateView());
38 CBS top = StringPieceToCbs(certificate);
39
40 CBS top_certificate, tbs_certificate, signature_algorithm, signature;
41 if (!CBS_get_asn1(&top, &top_certificate, CBS_ASN1_SEQUENCE) ||
42 CBS_len(&top) != 0) {
43 return nullptr;
44 }
45
46 // Certificate ::= SEQUENCE {
47 if (
48 // tbsCertificate TBSCertificate,
49 !CBS_get_asn1(&top_certificate, &tbs_certificate, CBS_ASN1_SEQUENCE) ||
50
51 // signatureAlgorithm AlgorithmIdentifier,
52 !CBS_get_asn1(&top_certificate, &signature_algorithm,
53 CBS_ASN1_SEQUENCE) ||
54
55 // signature BIT STRING }
56 !CBS_get_asn1(&top_certificate, &signature, CBS_ASN1_BITSTRING) ||
57 CBS_len(&top_certificate) != 0) {
58 return nullptr;
59 }
60
61 int has_version, has_extensions;
62 CBS version, serial, signature_algorithm_inner, issuer, validity, subject,
63 spki, issuer_id, subject_id, extensions_outer;
64 // TBSCertificate ::= SEQUENCE {
65 if (
66 // version [0] Version DEFAULT v1,
67 !CBS_get_optional_asn1(
68 &tbs_certificate, &version, &has_version,
69 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0) ||
70
71 // serialNumber CertificateSerialNumber,
72 !CBS_get_asn1(&tbs_certificate, &serial, CBS_ASN1_INTEGER) ||
73
74 // signature AlgorithmIdentifier,
75 !CBS_get_asn1(&tbs_certificate, &signature_algorithm_inner,
76 CBS_ASN1_SEQUENCE) ||
77
78 // issuer Name,
79 !CBS_get_asn1(&tbs_certificate, &issuer, CBS_ASN1_SEQUENCE) ||
80
81 // validity Validity,
82 !CBS_get_asn1(&tbs_certificate, &validity, CBS_ASN1_SEQUENCE) ||
83
84 // subject Name,
85 !CBS_get_asn1(&tbs_certificate, &subject, CBS_ASN1_SEQUENCE) ||
86
87 // subjectPublicKeyInfo SubjectPublicKeyInfo,
88 !CBS_get_asn1_element(&tbs_certificate, &spki, CBS_ASN1_SEQUENCE) ||
89
90 // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
91 // -- If present, version MUST be v2 or v3
92 !CBS_get_optional_asn1(&tbs_certificate, &issuer_id, nullptr,
93 CBS_ASN1_CONTEXT_SPECIFIC | 1) ||
94
95 // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
96 // -- If present, version MUST be v2 or v3
97 !CBS_get_optional_asn1(&tbs_certificate, &subject_id, nullptr,
98 CBS_ASN1_CONTEXT_SPECIFIC | 2) ||
99
100 // extensions [3] Extensions OPTIONAL
101 // -- If present, version MUST be v3 -- }
102 !CBS_get_optional_asn1(
103 &tbs_certificate, &extensions_outer, &has_extensions,
104 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 3) ||
105
106 CBS_len(&tbs_certificate) != 0) {
107 return nullptr;
108 }
109
110 result->public_key_.reset(EVP_parse_public_key(&spki));
111 if (result->public_key_ == nullptr) {
112 QUIC_DLOG(WARNING) << "Failed to parse the public key";
113 return nullptr;
114 }
115 if (!result->ValidatePublicKeyParameters()) {
116 QUIC_DLOG(WARNING) << "Public key has invalid parameters";
117 return nullptr;
118 }
119
120 // Only support X.509v3.
121 if (!has_version ||
122 !CBS_mem_equal(&version, kX509Version, sizeof(kX509Version))) {
123 QUIC_DLOG(WARNING) << "Bad X.509 version";
124 return nullptr;
125 }
126
127 if (!has_extensions) {
128 return nullptr;
129 }
130
131 CBS extensions;
132 if (!CBS_get_asn1(&extensions_outer, &extensions, CBS_ASN1_SEQUENCE) ||
133 CBS_len(&extensions_outer) != 0) {
134 QUIC_DLOG(WARNING) << "Failed to extract the extension sequence";
135 return nullptr;
136 }
137 if (!result->ParseExtensions(extensions)) {
138 QUIC_DLOG(WARNING) << "Failed to parse extensions";
139 return nullptr;
140 }
141
142 return result;
143}
144
145bool CertificateView::ParseExtensions(CBS extensions) {
146 while (CBS_len(&extensions) != 0) {
147 CBS extension, oid, critical, payload;
148 if (
149 // Extension ::= SEQUENCE {
150 !CBS_get_asn1(&extensions, &extension, CBS_ASN1_SEQUENCE) ||
151 // extnID OBJECT IDENTIFIER,
152 !CBS_get_asn1(&extension, &oid, CBS_ASN1_OBJECT) ||
153 // critical BOOLEAN DEFAULT FALSE,
154 !CBS_get_optional_asn1(&extension, &critical, nullptr,
155 CBS_ASN1_BOOLEAN) ||
156 // extnValue OCTET STRING
157 // -- contains the DER encoding of an ASN.1 value
158 // -- corresponding to the extension type identified
159 // -- by extnID
160 !CBS_get_asn1(&extension, &payload, CBS_ASN1_OCTETSTRING) ||
161 CBS_len(&extension) != 0) {
162 QUIC_DLOG(WARNING) << "Bad extension entry";
163 return false;
164 }
165
166 if (CBS_mem_equal(&oid, kSubjectAltNameOid, sizeof(kSubjectAltNameOid))) {
167 CBS alt_names;
168 if (!CBS_get_asn1(&payload, &alt_names, CBS_ASN1_SEQUENCE) ||
169 CBS_len(&payload) != 0) {
170 QUIC_DLOG(WARNING) << "Failed to parse subjectAltName";
171 return false;
172 }
173 while (CBS_len(&alt_names) != 0) {
174 CBS alt_name_cbs;
175 unsigned int alt_name_tag;
176 if (!CBS_get_any_asn1(&alt_names, &alt_name_cbs, &alt_name_tag)) {
177 QUIC_DLOG(WARNING) << "Failed to parse subjectAltName";
178 return false;
179 }
180
181 quiche::QuicheStringPiece alt_name = CbsToStringPiece(alt_name_cbs);
182 QuicIpAddress ip_address;
183 // GeneralName ::= CHOICE {
184 switch (alt_name_tag) {
185 // dNSName [2] IA5String,
186 case CBS_ASN1_CONTEXT_SPECIFIC | 2:
187 subject_alt_name_domains_.push_back(alt_name);
188 break;
189
190 // iPAddress [7] OCTET STRING,
191 case CBS_ASN1_CONTEXT_SPECIFIC | 7:
192 if (!ip_address.FromPackedString(alt_name.data(),
193 alt_name.size())) {
194 QUIC_DLOG(WARNING) << "Failed to parse subjectAltName IP address";
195 return false;
196 }
197 subject_alt_name_ips_.push_back(ip_address);
198 break;
199
200 default:
201 QUIC_DLOG(WARNING) << "Invalid subjectAltName tag";
202 return false;
203 }
204 }
205 }
206 }
207
208 return true;
209}
210
211bool CertificateView::ValidatePublicKeyParameters() {
212 // The profile here affects what certificates can be used:
213 // (1) when QUIC is used as a server library without any custom certificate
214 // provider logic,
215 // (2) when QuicTransport is handling self-signed certificates.
216 // The goal is to allow at minimum any certificate that would be allowed on a
217 // regular Web session over TLS 1.3 while ensuring we do not expose any
218 // algorithms we don't want to support long-term.
219 switch (EVP_PKEY_id(public_key_.get())) {
220 case EVP_PKEY_RSA:
221 return EVP_PKEY_bits(public_key_.get()) >= 2048;
222 case EVP_PKEY_EC: {
223 const EC_KEY* key = EVP_PKEY_get0_EC_KEY(public_key_.get());
224 if (key == nullptr) {
225 return false;
226 }
227 const EC_GROUP* group = EC_KEY_get0_group(key);
228 if (group == nullptr) {
229 return false;
230 }
231 const int curve_nid = EC_GROUP_get_curve_name(group);
232 switch (curve_nid) {
233 case NID_X9_62_prime256v1:
234 case NID_secp384r1:
235 return true;
236 default:
237 return false;
238 }
239 }
240 case EVP_PKEY_ED25519:
241 return true;
242 default:
243 return false;
244 }
245}
246
247} // namespace quic