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
|
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef NET_CERT_TWO_QWAC_H_
#define NET_CERT_TWO_QWAC_H_
#include <stdint.h>
#include <optional>
#include <string_view>
#include <utility>
#include <vector>
#include "crypto/hash.h"
#include "net/base/net_export.h"
#include "net/cert/x509_certificate.h"
namespace net {
// Signature algorithms used to sign a JWS, as specified in the "alg" JWS Header
// Parameter (RFC 7515, section 4.1.1) and in the JSON Web Signature and
// Encryption Algorithms IANA registry.
//
// The 2-QWAC spec does not list required algorithms to be supported. See the
// comment in ParseJades2QwacHeader regarding which algorithms we support and
// why.
enum class JwsSigAlg {
// RS256 - RSA signing using PKCS1-v1.5 with SHA-256
kRsaPkcs1Sha256,
// PS256 - RSA PSS signing using SHA-256 and MGF1 with SHA-256
kRsaPssSha256,
// ES256 - ECDSA using P-256 and SHA-256
kEcdsaP256Sha256,
};
// Contains fields from a JAdES (ETSI TS 119 182-1) signature header needed for
// verifying 2-QWAC TLS certificate bindings. While JAdES is a profile of JWS
// (RFC 7515), this is not general-purpose JWS or JWT code. It is also not
// general-purpose JAdES code, as only fields needed for 2-QWAC TLS certificate
// bindings are present here.
struct NET_EXPORT_PRIVATE Jades2QwacHeader {
Jades2QwacHeader();
Jades2QwacHeader(const Jades2QwacHeader& other);
Jades2QwacHeader(Jades2QwacHeader&& other);
~Jades2QwacHeader();
// The signature algorithm used to sign the JWS, as provided by the "alg" JWS
// Header Parameter (RFC 7515, section 4.1.1). Valid values for this field can
// be found in the JSON Web Signature and Encryption Algorithms IANA registry
// (https://www.iana.org/assignments/jose/jose.xhtml#web-signature-encryption-algorithms).
// The consumer of this struct must check that the algorithm provided in this
// field matches the signature algorithm of the leaf cert in |two_qwac_cert|.
JwsSigAlg sig_alg;
// The certificate chain with a leaf cert that is a 2-QWAC. This certificate
// chain is used to sign the JWS, which binds the 2-QWAC to a set of TLS
// serverAuth certificates.
scoped_refptr<net::X509Certificate> two_qwac_cert;
// The hash algorithm used to hash the bound certificates.
crypto::hash::HashKind hash_alg;
// The hashes of the bound certificates (base64url-encoded), hashed using
// |hash_alg|. Note: this is Digest(base64url(cert)), because that's what the
// JAdES and 2-QWAC specs require (not that it makes any sense to do that).
std::vector<std::vector<uint8_t>> bound_cert_hashes;
};
// A TwoQwacCertBinding represents a JAdES Signature (ETSI TS 119 182-1,
// clause 3.1) used for 2-QWACs (ETSI TS 119 411-5, clause 6.2.2). It comes from
// a TLS Certificate Binding (ETSI TS 119 411-5 annex B). Note that a JAdES
// Signature (which is also a JWS, a.k.a. JSON Web Signature) consists of a
// header and a cryptographic signature, not just a signature.
class NET_EXPORT_PRIVATE TwoQwacCertBinding {
public:
TwoQwacCertBinding(Jades2QwacHeader header,
std::string header_string,
std::vector<uint8_t> signature);
TwoQwacCertBinding(const TwoQwacCertBinding& other);
TwoQwacCertBinding(TwoQwacCertBinding&& other);
~TwoQwacCertBinding();
// Parses a TLS Certificate Binding structure that contains a 2-QWAC
// certificate chain. This function also performs steps 1-7 of RFC 7515
// section 5.2 (signature verification).
static std::optional<TwoQwacCertBinding> Parse(std::string_view jws);
// This function verifies the signature in the TLS Certificate Binding,
// performing steps 8-10 of RFC 7515 section 5.2 (signature verification). If
// called on a struct created with TwoQwacCertBinding::Parse, all steps of RFC
// 7515's signature verification have been performed and this function returns
// whether the JWS was successfully validated.
bool VerifySignature();
// Returns true if the 2-QWAC TLS Certificate Binding binds the 2-QWAC cert
// to the provided TLS cert (DER encoded). This performs step 6 of ETSI TS 119
// 411-5 clause 6.2.2.
//
// E.g. Chrome connects to https://example.com, sees the Link header with
// rel="tls-certificate-binding", fetches the TLS Certificate Binding at that
// location, and creates a TwoQwacCertBinding from those bytes. For the 2-QWAC
// to be valid, the TLS Certificate Binding (which contains the 2-QWAC) needs
// to bind the TLS cert used on the connection to https://example.com. By
// passing that TLS cert into this function, one can determine whether the TLS
// cert used for the connection is listed in the binding.
bool BindsTlsCert(base::span<const uint8_t> cert_der);
// Returns the parsed JWS header.
const Jades2QwacHeader& header() const { return header_; }
// Returns the unparsed JWS header as a string.
const std::string& header_string() const { return header_string_; }
private:
// The parsed JWS Header from the certificate binding structure.
Jades2QwacHeader header_;
// The unparsed JWS Header, needed for verifying the signature.
std::string header_string_;
// The JWS Signature (RFC 7515 section 2)/JAdES Signature Value (ETSI TS 119
// 182-1 clause 3.1) from the certificate binding structure.
std::vector<uint8_t> signature_;
};
} // namespace net
#endif // NET_CERT_TWO_QWAC_H_
|