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 #ifndef QUICHE_QUIC_CORE_CRYPTO_WEB_TRANSPORT_FINGERPRINT_PROOF_VERIFIER_H_ 6 #define QUICHE_QUIC_CORE_CRYPTO_WEB_TRANSPORT_FINGERPRINT_PROOF_VERIFIER_H_ 7 8 #include <vector> 9 10 #include "absl/strings/string_view.h" 11 #include "quiche/quic/core/crypto/certificate_view.h" 12 #include "quiche/quic/core/crypto/proof_verifier.h" 13 #include "quiche/quic/core/quic_clock.h" 14 #include "quiche/quic/platform/api/quic_export.h" 15 16 namespace quic { 17 18 // Represents a fingerprint of an X.509 certificate in a format based on 19 // https://w3c.github.io/webrtc-pc/#dom-rtcdtlsfingerprint. 20 // TODO(vasilvv): remove this once all consumers of this API use 21 // WebTransportHash. 22 struct QUICHE_EXPORT CertificateFingerprint { 23 static constexpr char kSha256[] = "sha-256"; 24 25 // An algorithm described by one of the names in 26 // https://www.iana.org/assignments/hash-function-text-names/hash-function-text-names.xhtml 27 std::string algorithm; 28 // Hex-encoded, colon-separated fingerprint of the certificate. For example, 29 // "12:3d:5b:71:8c:54:df:85:7e:bd:e3:7c:66:da:f9:db:6a:94:8f:85:cb:6e:44:7f:09:3e:05:f2:dd:d4:f7:86" 30 std::string fingerprint; 31 }; 32 33 // Represents a fingerprint of an X.509 certificate in a format based on 34 // https://w3c.github.io/webtransport/#dictdef-webtransporthash. 35 struct QUICHE_EXPORT WebTransportHash { 36 static constexpr char kSha256[] = "sha-256"; 37 38 // An algorithm described by one of the names in 39 // https://www.iana.org/assignments/hash-function-text-names/hash-function-text-names.xhtml 40 std::string algorithm; 41 // Raw bytes of the hash. 42 std::string value; 43 }; 44 45 // WebTransportFingerprintProofVerifier verifies the server leaf certificate 46 // against a supplied list of certificate fingerprints following the procedure 47 // described in the WebTransport specification. The certificate is deemed 48 // trusted if it matches a fingerprint in the list, has expiry dates that are 49 // not too long and has not expired. Only the leaf is checked, the rest of the 50 // chain is ignored. Reference specification: 51 // https://wicg.github.io/web-transport/#dom-quictransportconfiguration-server_certificate_fingerprints 52 class QUICHE_EXPORT WebTransportFingerprintProofVerifier 53 : public ProofVerifier { 54 public: 55 // Note: the entries in this list may be logged into a UMA histogram, and thus 56 // should not be renumbered. 57 enum class Status { 58 kValidCertificate = 0, 59 kUnknownFingerprint = 1, 60 kCertificateParseFailure = 2, 61 kExpiryTooLong = 3, 62 kExpired = 4, 63 kInternalError = 5, 64 kDisallowedKeyAlgorithm = 6, 65 66 kMaxValue = kDisallowedKeyAlgorithm, 67 }; 68 69 class QUICHE_EXPORT Details : public ProofVerifyDetails { 70 public: Details(Status status)71 explicit Details(Status status) : status_(status) {} status()72 Status status() const { return status_; } 73 74 ProofVerifyDetails* Clone() const override; 75 76 private: 77 const Status status_; 78 }; 79 80 // |clock| is used to check if the certificate has expired. It is not owned 81 // and must outlive the object. |max_validity_days| is the maximum time for 82 // which the certificate is allowed to be valid. 83 WebTransportFingerprintProofVerifier(const QuicClock* clock, 84 int max_validity_days); 85 86 // Adds a certificate fingerprint to be trusted. The fingerprints are 87 // case-insensitive and are validated internally; the function returns true if 88 // the validation passes. 89 bool AddFingerprint(CertificateFingerprint fingerprint); 90 bool AddFingerprint(WebTransportHash hash); 91 92 // ProofVerifier implementation. 93 QuicAsyncStatus VerifyProof( 94 const std::string& hostname, const uint16_t port, 95 const std::string& server_config, QuicTransportVersion transport_version, 96 absl::string_view chlo_hash, const std::vector<std::string>& certs, 97 const std::string& cert_sct, const std::string& signature, 98 const ProofVerifyContext* context, std::string* error_details, 99 std::unique_ptr<ProofVerifyDetails>* details, 100 std::unique_ptr<ProofVerifierCallback> callback) override; 101 QuicAsyncStatus VerifyCertChain( 102 const std::string& hostname, const uint16_t port, 103 const std::vector<std::string>& certs, const std::string& ocsp_response, 104 const std::string& cert_sct, const ProofVerifyContext* context, 105 std::string* error_details, std::unique_ptr<ProofVerifyDetails>* details, 106 uint8_t* out_alert, 107 std::unique_ptr<ProofVerifierCallback> callback) override; 108 std::unique_ptr<ProofVerifyContext> CreateDefaultContext() override; 109 110 protected: 111 virtual bool IsKeyTypeAllowedByPolicy(const CertificateView& certificate); 112 113 private: 114 bool HasKnownFingerprint(absl::string_view der_certificate); 115 bool HasValidExpiry(const CertificateView& certificate); 116 bool IsWithinValidityPeriod(const CertificateView& certificate); 117 118 const QuicClock* clock_; // Unowned. 119 const int max_validity_days_; 120 const QuicTime::Delta max_validity_; 121 std::vector<WebTransportHash> hashes_; 122 }; 123 124 } // namespace quic 125 126 #endif // QUICHE_QUIC_CORE_CRYPTO_WEB_TRANSPORT_FINGERPRINT_PROOF_VERIFIER_H_ 127