xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/crypto/certificate_view.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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, &not_before, &not_before_tag) ||
359       !CBS_get_any_asn1(&validity, &not_after, &not_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