1 // 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 "quiche/quic/core/crypto/certificate_view.h"
6
7 #include <algorithm>
8 #include <cstdint>
9 #include <memory>
10 #include <optional>
11 #include <string>
12
13 #include "absl/strings/escaping.h"
14 #include "absl/strings/match.h"
15 #include "absl/strings/str_cat.h"
16 #include "absl/strings/str_join.h"
17 #include "absl/strings/string_view.h"
18 #include "openssl/base.h"
19 #include "openssl/bytestring.h"
20 #include "openssl/digest.h"
21 #include "openssl/ec.h"
22 #include "openssl/ec_key.h"
23 #include "openssl/evp.h"
24 #include "openssl/nid.h"
25 #include "openssl/rsa.h"
26 #include "openssl/ssl.h"
27 #include "quiche/quic/core/crypto/boring_utils.h"
28 #include "quiche/quic/core/quic_time.h"
29 #include "quiche/quic/core/quic_types.h"
30 #include "quiche/quic/platform/api/quic_bug_tracker.h"
31 #include "quiche/quic/platform/api/quic_ip_address.h"
32 #include "quiche/quic/platform/api/quic_logging.h"
33 #include "quiche/common/platform/api/quiche_time_utils.h"
34 #include "quiche/common/quiche_data_reader.h"
35 #include "quiche/common/quiche_text_utils.h"
36
37 namespace quic {
38 namespace {
39
40 using ::quiche::QuicheTextUtils;
41
42 // The literals below were encoded using `ascii2der | xxd -i`. The comments
43 // above the literals are the contents in the der2ascii syntax.
44
45 // X.509 version 3 (version numbering starts with zero).
46 // INTEGER { 2 }
47 constexpr uint8_t kX509Version[] = {0x02, 0x01, 0x02};
48
49 // 2.5.29.17
50 constexpr uint8_t kSubjectAltNameOid[] = {0x55, 0x1d, 0x11};
51
PublicKeyTypeFromKey(EVP_PKEY * public_key)52 PublicKeyType PublicKeyTypeFromKey(EVP_PKEY* public_key) {
53 switch (EVP_PKEY_id(public_key)) {
54 case EVP_PKEY_RSA:
55 return PublicKeyType::kRsa;
56 case EVP_PKEY_EC: {
57 const EC_KEY* key = EVP_PKEY_get0_EC_KEY(public_key);
58 if (key == nullptr) {
59 return PublicKeyType::kUnknown;
60 }
61 const EC_GROUP* group = EC_KEY_get0_group(key);
62 if (group == nullptr) {
63 return PublicKeyType::kUnknown;
64 }
65 const int curve_nid = EC_GROUP_get_curve_name(group);
66 switch (curve_nid) {
67 case NID_X9_62_prime256v1:
68 return PublicKeyType::kP256;
69 case NID_secp384r1:
70 return PublicKeyType::kP384;
71 default:
72 return PublicKeyType::kUnknown;
73 }
74 }
75 case EVP_PKEY_ED25519:
76 return PublicKeyType::kEd25519;
77 default:
78 return PublicKeyType::kUnknown;
79 }
80 }
81
82 } // namespace
83
PublicKeyTypeFromSignatureAlgorithm(uint16_t signature_algorithm)84 PublicKeyType PublicKeyTypeFromSignatureAlgorithm(
85 uint16_t signature_algorithm) {
86 // This should be kept in sync with the list in
87 // SupportedSignatureAlgorithmsForQuic().
88 switch (signature_algorithm) {
89 case SSL_SIGN_RSA_PSS_RSAE_SHA256:
90 return PublicKeyType::kRsa;
91 case SSL_SIGN_ECDSA_SECP256R1_SHA256:
92 return PublicKeyType::kP256;
93 case SSL_SIGN_ECDSA_SECP384R1_SHA384:
94 return PublicKeyType::kP384;
95 case SSL_SIGN_ED25519:
96 return PublicKeyType::kEd25519;
97 default:
98 return PublicKeyType::kUnknown;
99 }
100 }
101
102 QUICHE_EXPORT QuicSignatureAlgorithmVector
SupportedSignatureAlgorithmsForQuic()103 SupportedSignatureAlgorithmsForQuic() {
104 // This should be kept in sync with the list in
105 // PublicKeyTypeFromSignatureAlgorithm().
106 return QuicSignatureAlgorithmVector{
107 SSL_SIGN_ED25519, SSL_SIGN_ECDSA_SECP256R1_SHA256,
108 SSL_SIGN_ECDSA_SECP384R1_SHA384, SSL_SIGN_RSA_PSS_RSAE_SHA256};
109 }
110
111 namespace {
112
AttributeNameToString(const CBS & oid_cbs)113 std::string AttributeNameToString(const CBS& oid_cbs) {
114 absl::string_view oid = CbsToStringPiece(oid_cbs);
115
116 // We only handle OIDs of form 2.5.4.N, which have binary encoding of
117 // "55 04 0N".
118 if (oid.length() == 3 && absl::StartsWith(oid, "\x55\x04")) {
119 // clang-format off
120 switch (oid[2]) {
121 case '\x3': return "CN";
122 case '\x7': return "L";
123 case '\x8': return "ST";
124 case '\xa': return "O";
125 case '\xb': return "OU";
126 case '\x6': return "C";
127 }
128 // clang-format on
129 }
130
131 bssl::UniquePtr<char> oid_representation(CBS_asn1_oid_to_text(&oid_cbs));
132 if (oid_representation == nullptr) {
133 return absl::StrCat("(", absl::BytesToHexString(oid), ")");
134 }
135 return std::string(oid_representation.get());
136 }
137
138 } // namespace
139
X509NameAttributeToString(CBS input)140 std::optional<std::string> X509NameAttributeToString(CBS input) {
141 CBS name, value;
142 unsigned value_tag;
143 if (!CBS_get_asn1(&input, &name, CBS_ASN1_OBJECT) ||
144 !CBS_get_any_asn1(&input, &value, &value_tag) || CBS_len(&input) != 0) {
145 return std::nullopt;
146 }
147 // Note that this does not process encoding of |input| in any way. This works
148 // fine for the most cases.
149 return absl::StrCat(AttributeNameToString(name), "=",
150 absl::CHexEscape(CbsToStringPiece(value)));
151 }
152
153 namespace {
154
155 template <unsigned inner_tag, char separator,
156 std::optional<std::string> (*parser)(CBS)>
ParseAndJoin(CBS input)157 std::optional<std::string> ParseAndJoin(CBS input) {
158 std::vector<std::string> pieces;
159 while (CBS_len(&input) != 0) {
160 CBS attribute;
161 if (!CBS_get_asn1(&input, &attribute, inner_tag)) {
162 return std::nullopt;
163 }
164 std::optional<std::string> formatted = parser(attribute);
165 if (!formatted.has_value()) {
166 return std::nullopt;
167 }
168 pieces.push_back(*formatted);
169 }
170
171 return absl::StrJoin(pieces, std::string({separator}));
172 }
173
RelativeDistinguishedNameToString(CBS input)174 std::optional<std::string> RelativeDistinguishedNameToString(CBS input) {
175 return ParseAndJoin<CBS_ASN1_SEQUENCE, '+', X509NameAttributeToString>(input);
176 }
177
DistinguishedNameToString(CBS input)178 std::optional<std::string> DistinguishedNameToString(CBS input) {
179 return ParseAndJoin<CBS_ASN1_SET, ',', RelativeDistinguishedNameToString>(
180 input);
181 }
182
183 } // namespace
184
PublicKeyTypeToString(PublicKeyType type)185 std::string PublicKeyTypeToString(PublicKeyType type) {
186 switch (type) {
187 case PublicKeyType::kRsa:
188 return "RSA";
189 case PublicKeyType::kP256:
190 return "ECDSA P-256";
191 case PublicKeyType::kP384:
192 return "ECDSA P-384";
193 case PublicKeyType::kEd25519:
194 return "Ed25519";
195 case PublicKeyType::kUnknown:
196 return "unknown";
197 }
198 return "";
199 }
200
ParseDerTime(unsigned tag,absl::string_view payload)201 std::optional<quic::QuicWallTime> ParseDerTime(unsigned tag,
202 absl::string_view payload) {
203 if (tag != CBS_ASN1_GENERALIZEDTIME && tag != CBS_ASN1_UTCTIME) {
204 QUIC_DLOG(WARNING) << "Invalid tag supplied for a DER timestamp";
205 return std::nullopt;
206 }
207
208 const size_t year_length = tag == CBS_ASN1_GENERALIZEDTIME ? 4 : 2;
209 uint64_t year, month, day, hour, minute, second;
210 quiche::QuicheDataReader reader(payload);
211 if (!reader.ReadDecimal64(year_length, &year) ||
212 !reader.ReadDecimal64(2, &month) || !reader.ReadDecimal64(2, &day) ||
213 !reader.ReadDecimal64(2, &hour) || !reader.ReadDecimal64(2, &minute) ||
214 !reader.ReadDecimal64(2, &second) ||
215 reader.ReadRemainingPayload() != "Z") {
216 QUIC_DLOG(WARNING) << "Failed to parse the DER timestamp";
217 return std::nullopt;
218 }
219
220 if (tag == CBS_ASN1_UTCTIME) {
221 QUICHE_DCHECK_LE(year, 100u);
222 year += (year >= 50) ? 1900 : 2000;
223 }
224
225 const std::optional<int64_t> unix_time =
226 quiche::QuicheUtcDateTimeToUnixSeconds(year, month, day, hour, minute,
227 second);
228 if (!unix_time.has_value() || *unix_time < 0) {
229 return std::nullopt;
230 }
231 return QuicWallTime::FromUNIXSeconds(*unix_time);
232 }
233
ReadNextPemMessage(std::istream * input)234 PemReadResult ReadNextPemMessage(std::istream* input) {
235 constexpr absl::string_view kPemBegin = "-----BEGIN ";
236 constexpr absl::string_view kPemEnd = "-----END ";
237 constexpr absl::string_view kPemDashes = "-----";
238
239 std::string line_buffer, encoded_message_contents, expected_end;
240 bool pending_message = false;
241 PemReadResult result;
242 while (std::getline(*input, line_buffer)) {
243 absl::string_view line(line_buffer);
244 QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(&line);
245
246 // Handle BEGIN lines.
247 if (!pending_message && absl::StartsWith(line, kPemBegin) &&
248 absl::EndsWith(line, kPemDashes)) {
249 result.type = std::string(
250 line.substr(kPemBegin.size(),
251 line.size() - kPemDashes.size() - kPemBegin.size()));
252 expected_end = absl::StrCat(kPemEnd, result.type, kPemDashes);
253 pending_message = true;
254 continue;
255 }
256
257 // Handle END lines.
258 if (pending_message && line == expected_end) {
259 std::optional<std::string> data =
260 QuicheTextUtils::Base64Decode(encoded_message_contents);
261 if (data.has_value()) {
262 result.status = PemReadResult::kOk;
263 result.contents = *data;
264 } else {
265 result.status = PemReadResult::kError;
266 }
267 return result;
268 }
269
270 if (pending_message) {
271 encoded_message_contents.append(std::string(line));
272 }
273 }
274 bool eof_reached = input->eof() && !pending_message;
275 return PemReadResult{
276 (eof_reached ? PemReadResult::kEof : PemReadResult::kError), "", ""};
277 }
278
ParseSingleCertificate(absl::string_view certificate)279 std::unique_ptr<CertificateView> CertificateView::ParseSingleCertificate(
280 absl::string_view certificate) {
281 std::unique_ptr<CertificateView> result(new CertificateView());
282 CBS top = StringPieceToCbs(certificate);
283
284 CBS top_certificate, tbs_certificate, signature_algorithm, signature;
285 if (!CBS_get_asn1(&top, &top_certificate, CBS_ASN1_SEQUENCE) ||
286 CBS_len(&top) != 0) {
287 return nullptr;
288 }
289
290 // Certificate ::= SEQUENCE {
291 if (
292 // tbsCertificate TBSCertificate,
293 !CBS_get_asn1(&top_certificate, &tbs_certificate, CBS_ASN1_SEQUENCE) ||
294
295 // signatureAlgorithm AlgorithmIdentifier,
296 !CBS_get_asn1(&top_certificate, &signature_algorithm,
297 CBS_ASN1_SEQUENCE) ||
298
299 // signature BIT STRING }
300 !CBS_get_asn1(&top_certificate, &signature, CBS_ASN1_BITSTRING) ||
301 CBS_len(&top_certificate) != 0) {
302 return nullptr;
303 }
304
305 int has_version, has_extensions;
306 CBS version, serial, signature_algorithm_inner, issuer, validity, subject,
307 spki, issuer_id, subject_id, extensions_outer;
308 // TBSCertificate ::= SEQUENCE {
309 if (
310 // version [0] Version DEFAULT v1,
311 !CBS_get_optional_asn1(
312 &tbs_certificate, &version, &has_version,
313 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0) ||
314
315 // serialNumber CertificateSerialNumber,
316 !CBS_get_asn1(&tbs_certificate, &serial, CBS_ASN1_INTEGER) ||
317
318 // signature AlgorithmIdentifier,
319 !CBS_get_asn1(&tbs_certificate, &signature_algorithm_inner,
320 CBS_ASN1_SEQUENCE) ||
321
322 // issuer Name,
323 !CBS_get_asn1(&tbs_certificate, &issuer, CBS_ASN1_SEQUENCE) ||
324
325 // validity Validity,
326 !CBS_get_asn1(&tbs_certificate, &validity, CBS_ASN1_SEQUENCE) ||
327
328 // subject Name,
329 !CBS_get_asn1(&tbs_certificate, &subject, CBS_ASN1_SEQUENCE) ||
330
331 // subjectPublicKeyInfo SubjectPublicKeyInfo,
332 !CBS_get_asn1_element(&tbs_certificate, &spki, CBS_ASN1_SEQUENCE) ||
333
334 // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
335 // -- If present, version MUST be v2 or v3
336 !CBS_get_optional_asn1(&tbs_certificate, &issuer_id, nullptr,
337 CBS_ASN1_CONTEXT_SPECIFIC | 1) ||
338
339 // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
340 // -- If present, version MUST be v2 or v3
341 !CBS_get_optional_asn1(&tbs_certificate, &subject_id, nullptr,
342 CBS_ASN1_CONTEXT_SPECIFIC | 2) ||
343
344 // extensions [3] Extensions OPTIONAL
345 // -- If present, version MUST be v3 -- }
346 !CBS_get_optional_asn1(
347 &tbs_certificate, &extensions_outer, &has_extensions,
348 CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 3) ||
349
350 CBS_len(&tbs_certificate) != 0) {
351 return nullptr;
352 }
353
354 result->subject_der_ = CbsToStringPiece(subject);
355
356 unsigned not_before_tag, not_after_tag;
357 CBS not_before, not_after;
358 if (!CBS_get_any_asn1(&validity, ¬_before, ¬_before_tag) ||
359 !CBS_get_any_asn1(&validity, ¬_after, ¬_after_tag) ||
360 CBS_len(&validity) != 0) {
361 QUIC_DLOG(WARNING) << "Failed to extract the validity dates";
362 return nullptr;
363 }
364 std::optional<QuicWallTime> not_before_parsed =
365 ParseDerTime(not_before_tag, CbsToStringPiece(not_before));
366 std::optional<QuicWallTime> not_after_parsed =
367 ParseDerTime(not_after_tag, CbsToStringPiece(not_after));
368 if (!not_before_parsed.has_value() || !not_after_parsed.has_value()) {
369 QUIC_DLOG(WARNING) << "Failed to parse validity dates";
370 return nullptr;
371 }
372 result->validity_start_ = *not_before_parsed;
373 result->validity_end_ = *not_after_parsed;
374
375 result->public_key_.reset(EVP_parse_public_key(&spki));
376 if (result->public_key_ == nullptr) {
377 QUIC_DLOG(WARNING) << "Failed to parse the public key";
378 return nullptr;
379 }
380 if (!result->ValidatePublicKeyParameters()) {
381 QUIC_DLOG(WARNING) << "Public key has invalid parameters";
382 return nullptr;
383 }
384
385 // Only support X.509v3.
386 if (!has_version ||
387 !CBS_mem_equal(&version, kX509Version, sizeof(kX509Version))) {
388 QUIC_DLOG(WARNING) << "Bad X.509 version";
389 return nullptr;
390 }
391
392 if (!has_extensions) {
393 return nullptr;
394 }
395
396 CBS extensions;
397 if (!CBS_get_asn1(&extensions_outer, &extensions, CBS_ASN1_SEQUENCE) ||
398 CBS_len(&extensions_outer) != 0) {
399 QUIC_DLOG(WARNING) << "Failed to extract the extension sequence";
400 return nullptr;
401 }
402 if (!result->ParseExtensions(extensions)) {
403 QUIC_DLOG(WARNING) << "Failed to parse extensions";
404 return nullptr;
405 }
406
407 return result;
408 }
409
ParseExtensions(CBS extensions)410 bool CertificateView::ParseExtensions(CBS extensions) {
411 while (CBS_len(&extensions) != 0) {
412 CBS extension, oid, critical, payload;
413 if (
414 // Extension ::= SEQUENCE {
415 !CBS_get_asn1(&extensions, &extension, CBS_ASN1_SEQUENCE) ||
416 // extnID OBJECT IDENTIFIER,
417 !CBS_get_asn1(&extension, &oid, CBS_ASN1_OBJECT) ||
418 // critical BOOLEAN DEFAULT FALSE,
419 !CBS_get_optional_asn1(&extension, &critical, nullptr,
420 CBS_ASN1_BOOLEAN) ||
421 // extnValue OCTET STRING
422 // -- contains the DER encoding of an ASN.1 value
423 // -- corresponding to the extension type identified
424 // -- by extnID
425 !CBS_get_asn1(&extension, &payload, CBS_ASN1_OCTETSTRING) ||
426 CBS_len(&extension) != 0) {
427 QUIC_DLOG(WARNING) << "Bad extension entry";
428 return false;
429 }
430
431 if (CBS_mem_equal(&oid, kSubjectAltNameOid, sizeof(kSubjectAltNameOid))) {
432 CBS alt_names;
433 if (!CBS_get_asn1(&payload, &alt_names, CBS_ASN1_SEQUENCE) ||
434 CBS_len(&payload) != 0) {
435 QUIC_DLOG(WARNING) << "Failed to parse subjectAltName";
436 return false;
437 }
438 while (CBS_len(&alt_names) != 0) {
439 CBS alt_name_cbs;
440 unsigned int alt_name_tag;
441 if (!CBS_get_any_asn1(&alt_names, &alt_name_cbs, &alt_name_tag)) {
442 QUIC_DLOG(WARNING) << "Failed to parse subjectAltName";
443 return false;
444 }
445
446 absl::string_view alt_name = CbsToStringPiece(alt_name_cbs);
447 QuicIpAddress ip_address;
448 // GeneralName ::= CHOICE {
449 switch (alt_name_tag) {
450 // dNSName [2] IA5String,
451 case CBS_ASN1_CONTEXT_SPECIFIC | 2:
452 subject_alt_name_domains_.push_back(alt_name);
453 break;
454
455 // iPAddress [7] OCTET STRING,
456 case CBS_ASN1_CONTEXT_SPECIFIC | 7:
457 if (!ip_address.FromPackedString(alt_name.data(),
458 alt_name.size())) {
459 QUIC_DLOG(WARNING) << "Failed to parse subjectAltName IP address";
460 return false;
461 }
462 subject_alt_name_ips_.push_back(ip_address);
463 break;
464
465 default:
466 QUIC_DLOG(INFO) << "Unknown subjectAltName tag " << alt_name_tag;
467 continue;
468 }
469 }
470 }
471 }
472
473 return true;
474 }
475
LoadPemFromStream(std::istream * input)476 std::vector<std::string> CertificateView::LoadPemFromStream(
477 std::istream* input) {
478 std::vector<std::string> result;
479 for (;;) {
480 PemReadResult read_result = ReadNextPemMessage(input);
481 if (read_result.status == PemReadResult::kEof) {
482 return result;
483 }
484 if (read_result.status != PemReadResult::kOk) {
485 return std::vector<std::string>();
486 }
487 if (read_result.type != "CERTIFICATE") {
488 continue;
489 }
490 result.emplace_back(std::move(read_result.contents));
491 }
492 }
493
public_key_type() const494 PublicKeyType CertificateView::public_key_type() const {
495 return PublicKeyTypeFromKey(public_key_.get());
496 }
497
ValidatePublicKeyParameters()498 bool CertificateView::ValidatePublicKeyParameters() {
499 // The profile here affects what certificates can be used when QUIC is used as
500 // a server library without any custom certificate provider logic.
501 // The goal is to allow at minimum any certificate that would be allowed on a
502 // regular Web session over TLS 1.3 while ensuring we do not expose any
503 // algorithms we don't want to support long-term.
504 PublicKeyType key_type = PublicKeyTypeFromKey(public_key_.get());
505 switch (key_type) {
506 case PublicKeyType::kRsa:
507 return EVP_PKEY_bits(public_key_.get()) >= 2048;
508 case PublicKeyType::kP256:
509 case PublicKeyType::kP384:
510 case PublicKeyType::kEd25519:
511 return true;
512 default:
513 return false;
514 }
515 }
516
VerifySignature(absl::string_view data,absl::string_view signature,uint16_t signature_algorithm) const517 bool CertificateView::VerifySignature(absl::string_view data,
518 absl::string_view signature,
519 uint16_t signature_algorithm) const {
520 if (PublicKeyTypeFromSignatureAlgorithm(signature_algorithm) !=
521 PublicKeyTypeFromKey(public_key_.get())) {
522 QUIC_BUG(quic_bug_10640_1)
523 << "Mismatch between the requested signature algorithm and the "
524 "type of the public key.";
525 return false;
526 }
527
528 bssl::ScopedEVP_MD_CTX md_ctx;
529 EVP_PKEY_CTX* pctx;
530 if (!EVP_DigestVerifyInit(
531 md_ctx.get(), &pctx,
532 SSL_get_signature_algorithm_digest(signature_algorithm), nullptr,
533 public_key_.get())) {
534 return false;
535 }
536 if (SSL_is_signature_algorithm_rsa_pss(signature_algorithm)) {
537 if (!EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) ||
538 !EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1)) {
539 return false;
540 }
541 }
542 return EVP_DigestVerify(
543 md_ctx.get(), reinterpret_cast<const uint8_t*>(signature.data()),
544 signature.size(), reinterpret_cast<const uint8_t*>(data.data()),
545 data.size());
546 }
547
GetHumanReadableSubject() const548 std::optional<std::string> CertificateView::GetHumanReadableSubject() const {
549 CBS input = StringPieceToCbs(subject_der_);
550 return DistinguishedNameToString(input);
551 }
552
LoadFromDer(absl::string_view private_key)553 std::unique_ptr<CertificatePrivateKey> CertificatePrivateKey::LoadFromDer(
554 absl::string_view private_key) {
555 std::unique_ptr<CertificatePrivateKey> result(new CertificatePrivateKey());
556 CBS private_key_cbs = StringPieceToCbs(private_key);
557 result->private_key_.reset(EVP_parse_private_key(&private_key_cbs));
558 if (result->private_key_ == nullptr || CBS_len(&private_key_cbs) != 0) {
559 return nullptr;
560 }
561 return result;
562 }
563
LoadPemFromStream(std::istream * input)564 std::unique_ptr<CertificatePrivateKey> CertificatePrivateKey::LoadPemFromStream(
565 std::istream* input) {
566 skip:
567 PemReadResult result = ReadNextPemMessage(input);
568 if (result.status != PemReadResult::kOk) {
569 return nullptr;
570 }
571 // RFC 5958 OneAsymmetricKey message.
572 if (result.type == "PRIVATE KEY") {
573 return LoadFromDer(result.contents);
574 }
575 // Legacy OpenSSL format: PKCS#1 (RFC 8017) RSAPrivateKey message.
576 if (result.type == "RSA PRIVATE KEY") {
577 CBS private_key_cbs = StringPieceToCbs(result.contents);
578 bssl::UniquePtr<RSA> rsa(RSA_parse_private_key(&private_key_cbs));
579 if (rsa == nullptr || CBS_len(&private_key_cbs) != 0) {
580 return nullptr;
581 }
582
583 std::unique_ptr<CertificatePrivateKey> key(new CertificatePrivateKey());
584 key->private_key_.reset(EVP_PKEY_new());
585 EVP_PKEY_assign_RSA(key->private_key_.get(), rsa.release());
586 return key;
587 }
588 // EC keys are sometimes generated with "openssl ecparam -genkey". If the user
589 // forgets -noout, OpenSSL will output a redundant copy of the EC parameters.
590 // Skip those.
591 if (result.type == "EC PARAMETERS") {
592 goto skip;
593 }
594 // Legacy OpenSSL format: RFC 5915 ECPrivateKey message.
595 if (result.type == "EC PRIVATE KEY") {
596 CBS private_key_cbs = StringPieceToCbs(result.contents);
597 bssl::UniquePtr<EC_KEY> ec_key(
598 EC_KEY_parse_private_key(&private_key_cbs, /*group=*/nullptr));
599 if (ec_key == nullptr || CBS_len(&private_key_cbs) != 0) {
600 return nullptr;
601 }
602
603 std::unique_ptr<CertificatePrivateKey> key(new CertificatePrivateKey());
604 key->private_key_.reset(EVP_PKEY_new());
605 EVP_PKEY_assign_EC_KEY(key->private_key_.get(), ec_key.release());
606 return key;
607 }
608 // Unknown format.
609 return nullptr;
610 }
611
Sign(absl::string_view input,uint16_t signature_algorithm) const612 std::string CertificatePrivateKey::Sign(absl::string_view input,
613 uint16_t signature_algorithm) const {
614 if (!ValidForSignatureAlgorithm(signature_algorithm)) {
615 QUIC_BUG(quic_bug_10640_2)
616 << "Mismatch between the requested signature algorithm and the "
617 "type of the private key.";
618 return "";
619 }
620
621 bssl::ScopedEVP_MD_CTX md_ctx;
622 EVP_PKEY_CTX* pctx;
623 if (!EVP_DigestSignInit(
624 md_ctx.get(), &pctx,
625 SSL_get_signature_algorithm_digest(signature_algorithm),
626 /*e=*/nullptr, private_key_.get())) {
627 return "";
628 }
629 if (SSL_is_signature_algorithm_rsa_pss(signature_algorithm)) {
630 if (!EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) ||
631 !EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1)) {
632 return "";
633 }
634 }
635
636 std::string output;
637 size_t output_size;
638 if (!EVP_DigestSign(md_ctx.get(), /*out_sig=*/nullptr, &output_size,
639 reinterpret_cast<const uint8_t*>(input.data()),
640 input.size())) {
641 return "";
642 }
643 output.resize(output_size);
644 if (!EVP_DigestSign(
645 md_ctx.get(), reinterpret_cast<uint8_t*>(&output[0]), &output_size,
646 reinterpret_cast<const uint8_t*>(input.data()), input.size())) {
647 return "";
648 }
649 output.resize(output_size);
650 return output;
651 }
652
MatchesPublicKey(const CertificateView & view) const653 bool CertificatePrivateKey::MatchesPublicKey(
654 const CertificateView& view) const {
655 return EVP_PKEY_cmp(view.public_key(), private_key_.get()) == 1;
656 }
657
ValidForSignatureAlgorithm(uint16_t signature_algorithm) const658 bool CertificatePrivateKey::ValidForSignatureAlgorithm(
659 uint16_t signature_algorithm) const {
660 return PublicKeyTypeFromSignatureAlgorithm(signature_algorithm) ==
661 PublicKeyTypeFromKey(private_key_.get());
662 }
663
664 } // namespace quic
665