Commit 8e919b58 authored by Callum May's avatar Callum May Committed by Commit Bot

[Trust Tokens] Add alg field to Sec-Signature header

As specified in https://github.com/WICG/trust-token-api/pull/48, the
Sec-Signature header now includes the algorithm identifier of the
signing algorithm used to sign the header. We add this alg
identifier to align with the spec.

Change-Id: I90023b3f40fdb18d18aa73edbbecdcc25cf5aacf
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2505813Reviewed-by: default avatarSteven Valdez <svaldez@chromium.org>
Commit-Queue: Callum May <camay@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#825967}
parent ff1d9dd5
...@@ -38,4 +38,8 @@ bool Ed25519TrustTokenRequestSigner::Verify( ...@@ -38,4 +38,8 @@ bool Ed25519TrustTokenRequestSigner::Verify(
verification_key.data()); verification_key.data());
} }
std::string Ed25519TrustTokenRequestSigner::GetAlgorithmIdentifier() {
return "ed25519";
}
} // namespace network } // namespace network
...@@ -26,6 +26,8 @@ class Ed25519TrustTokenRequestSigner ...@@ -26,6 +26,8 @@ class Ed25519TrustTokenRequestSigner
bool Verify(base::span<const uint8_t> data, bool Verify(base::span<const uint8_t> data,
base::span<const uint8_t> signature, base::span<const uint8_t> signature,
base::span<const uint8_t> verification_key) override; base::span<const uint8_t> verification_key) override;
std::string GetAlgorithmIdentifier() override;
}; };
} // namespace network } // namespace network
......
...@@ -55,11 +55,12 @@ bool ReconstructSigningDataAndVerifyForIndividualIssuer( ...@@ -55,11 +55,12 @@ bool ReconstructSigningDataAndVerifyForIndividualIssuer(
const net::HttpRequestHeaders& headers, const net::HttpRequestHeaders& headers,
base::RepeatingCallback<bool(base::span<const uint8_t> data, base::RepeatingCallback<bool(base::span<const uint8_t> data,
base::span<const uint8_t> signature, base::span<const uint8_t> signature,
base::span<const uint8_t> verification_key)> base::span<const uint8_t> verification_key,
verifier, const std::string& sig_alg)> verifier,
mojom::TrustTokenSignRequestData sign_request_data, mojom::TrustTokenSignRequestData sign_request_data,
std::string* error_out, std::string* error_out,
std::map<std::string, std::string>* verification_keys_out) { std::map<std::string, std::string>* verification_keys_out,
const std::string& sig_alg) {
if (!issuer_and_params.item.is_string()) { if (!issuer_and_params.item.is_string()) {
*error_out = "type-unsafe issuer in Sec-Signature header"; *error_out = "type-unsafe issuer in Sec-Signature header";
return false; return false;
...@@ -121,14 +122,20 @@ bool ReconstructSigningDataAndVerifyForIndividualIssuer( ...@@ -121,14 +122,20 @@ bool ReconstructSigningDataAndVerifyForIndividualIssuer(
written_reconstructed_cbor->end()); written_reconstructed_cbor->end());
if (!verifier) { if (!verifier) {
verifier = verifier = base::BindRepeating(
base::BindRepeating(&Ed25519TrustTokenRequestSigner::Verify, [](base::span<const uint8_t> data, base::span<const uint8_t> signature,
std::make_unique<Ed25519TrustTokenRequestSigner>()); base::span<const uint8_t> verification_key,
const std::string& signing_alg) {
std::unique_ptr<Ed25519TrustTokenRequestSigner> signer =
std::make_unique<Ed25519TrustTokenRequestSigner>();
return signer->Verify(data, signature, verification_key) &&
signing_alg == signer->GetAlgorithmIdentifier();
});
} }
if (!verifier.Run(base::make_span(reconstructed_signing_data), if (!verifier.Run(base::make_span(reconstructed_signing_data),
base::as_bytes(base::make_span(signature)), base::as_bytes(base::make_span(signature)),
base::as_bytes(base::make_span(public_key)))) { base::as_bytes(base::make_span(public_key)), sig_alg)) {
*error_out = "Error verifying signature"; *error_out = "Error verifying signature";
return false; return false;
} }
...@@ -195,13 +202,33 @@ bool ExtractIssuersAndParametersFromSignatureHeaderMap( ...@@ -195,13 +202,33 @@ bool ExtractIssuersAndParametersFromSignatureHeaderMap(
return true; return true;
} }
bool ExtractSigningAlgorithmIdentifierFromSignatureHeaderMap(
const SignatureHeaderMap& map,
std::string* sig_alg_out,
std::string* error_out) {
auto it = map.find("alg");
if (it == map.end()) {
*error_out = "Missing 'alg' element in the Sec-Signature header";
return false;
}
if (it->second.member_is_inner_list) {
*error_out = "'alg' element should not be a list";
return false;
}
*sig_alg_out = it->second.member.front().item.GetString();
return true;
}
bool ValidateSignatureHeaderMapAndExtractFields( bool ValidateSignatureHeaderMapAndExtractFields(
const SignatureHeaderMap& map, const SignatureHeaderMap& map,
std::vector<net::structured_headers::ParameterizedItem>* std::vector<net::structured_headers::ParameterizedItem>*
issuers_and_parameters_out, issuers_and_parameters_out,
mojom::TrustTokenSignRequestData* sign_request_data_out, mojom::TrustTokenSignRequestData* sign_request_data_out,
std::string* sig_alg_out,
std::string* error_out) { std::string* error_out) {
if (map.size() != 2) { if (map.size() != 3) {
*error_out = "Unexpected number of members in Sec-Signature header map"; *error_out = "Unexpected number of members in Sec-Signature header map";
return false; return false;
} }
...@@ -216,6 +243,11 @@ bool ValidateSignatureHeaderMapAndExtractFields( ...@@ -216,6 +243,11 @@ bool ValidateSignatureHeaderMapAndExtractFields(
return false; return false;
} }
if (!ExtractSigningAlgorithmIdentifierFromSignatureHeaderMap(map, sig_alg_out,
error_out)) {
return false;
}
return true; return true;
} }
...@@ -264,8 +296,8 @@ bool ReconstructSigningDataAndVerifySignatures( ...@@ -264,8 +296,8 @@ bool ReconstructSigningDataAndVerifySignatures(
const net::HttpRequestHeaders& headers, const net::HttpRequestHeaders& headers,
base::RepeatingCallback<bool(base::span<const uint8_t> data, base::RepeatingCallback<bool(base::span<const uint8_t> data,
base::span<const uint8_t> signature, base::span<const uint8_t> signature,
base::span<const uint8_t> verification_key)> base::span<const uint8_t> verification_key,
verifier, const std::string& sig_alg)> verifier,
std::string* error_out, std::string* error_out,
std::map<std::string, std::string>* verification_keys_out) { std::map<std::string, std::string>* verification_keys_out) {
// Make it possible to set the error without needing to check for // Make it possible to set the error without needing to check for
...@@ -292,9 +324,10 @@ bool ReconstructSigningDataAndVerifySignatures( ...@@ -292,9 +324,10 @@ bool ReconstructSigningDataAndVerifySignatures(
std::vector<net::structured_headers::ParameterizedItem> std::vector<net::structured_headers::ParameterizedItem>
issuers_and_parameters; issuers_and_parameters;
mojom::TrustTokenSignRequestData sign_request_data; mojom::TrustTokenSignRequestData sign_request_data;
std::string sig_alg;
if (!ValidateSignatureHeaderMapAndExtractFields( if (!ValidateSignatureHeaderMapAndExtractFields(
*signature_header_map, &issuers_and_parameters, &sign_request_data, *signature_header_map, &issuers_and_parameters, &sign_request_data,
error_out)) { &sig_alg, error_out)) {
return false; return false;
} }
...@@ -304,7 +337,7 @@ bool ReconstructSigningDataAndVerifySignatures( ...@@ -304,7 +337,7 @@ bool ReconstructSigningDataAndVerifySignatures(
// |error_out| on failure. // |error_out| on failure.
if (!ReconstructSigningDataAndVerifyForIndividualIssuer( if (!ReconstructSigningDataAndVerifyForIndividualIssuer(
issuer_and_parameters, destination, headers, verifier, issuer_and_parameters, destination, headers, verifier,
sign_request_data, error_out, verification_keys_out)) { sign_request_data, error_out, verification_keys_out, sig_alg)) {
return false; return false;
} }
} }
......
...@@ -53,8 +53,9 @@ bool ReconstructSigningDataAndVerifySignatures( ...@@ -53,8 +53,9 @@ bool ReconstructSigningDataAndVerifySignatures(
const net::HttpRequestHeaders& headers, const net::HttpRequestHeaders& headers,
base::RepeatingCallback<bool(base::span<const uint8_t> data, base::RepeatingCallback<bool(base::span<const uint8_t> data,
base::span<const uint8_t> signature, base::span<const uint8_t> signature,
base::span<const uint8_t> verification_key)> base::span<const uint8_t> verification_key,
verifier = {}, // defaults to Ed25519 const std::string& sig_alg)> verifier =
{}, // defaults to Ed25519
std::string* error_out = nullptr, std::string* error_out = nullptr,
std::map<std::string, std::string>* verification_keys_out = nullptr); std::map<std::string, std::string>* verification_keys_out = nullptr);
......
...@@ -97,6 +97,7 @@ const char kSignatureHeaderSignRequestDataIncludeValue[] = "include"; ...@@ -97,6 +97,7 @@ const char kSignatureHeaderSignRequestDataIncludeValue[] = "include";
const char kSignatureHeaderSignRequestDataHeadersOnlyValue[] = "headers-only"; const char kSignatureHeaderSignRequestDataHeadersOnlyValue[] = "headers-only";
const char kSignatureHeaderSignaturesKey[] = "signatures"; const char kSignatureHeaderSignaturesKey[] = "signatures";
const char kSignatureHeaderSignRequestDataKey[] = "sign-request-data"; const char kSignatureHeaderSignRequestDataKey[] = "sign-request-data";
const char kSignatureHeaderAlgorithmKey[] = "alg";
const char kSignatureHeaderPublicKeyKey[] = "public-key"; const char kSignatureHeaderPublicKeyKey[] = "public-key";
const char kSignatureHeaderSignatureKey[] = "sig"; const char kSignatureHeaderSignatureKey[] = "sig";
const char kRedemptionRecordHeaderRedemptionRecordKey[] = "redemption-record"; const char kRedemptionRecordHeaderRedemptionRecordKey[] = "redemption-record";
...@@ -517,6 +518,10 @@ base::Optional<std::string> TrustTokenRequestSigningHelper:: ...@@ -517,6 +518,10 @@ base::Optional<std::string> TrustTokenRequestSigningHelper::
net::structured_headers::Dictionary header_items; net::structured_headers::Dictionary header_items;
header_items[kSignatureHeaderAlgorithmKey] =
net::structured_headers::ParameterizedMember(
net::structured_headers::Item(signer_->GetAlgorithmIdentifier()), {});
std::vector<net::structured_headers::ParameterizedItem> keys_and_signatures; std::vector<net::structured_headers::ParameterizedItem> keys_and_signatures;
for (const auto& kv : signatures_per_issuer) { for (const auto& kv : signatures_per_issuer) {
const SuitableTrustTokenOrigin& issuer = kv.first; const SuitableTrustTokenOrigin& issuer = kv.first;
......
...@@ -150,6 +150,10 @@ class TrustTokenRequestSigningHelper : public TrustTokenRequestHelper { ...@@ -150,6 +150,10 @@ class TrustTokenRequestSigningHelper : public TrustTokenRequestHelper {
virtual bool Verify(base::span<const uint8_t> data, virtual bool Verify(base::span<const uint8_t> data,
base::span<const uint8_t> signature, base::span<const uint8_t> signature,
base::span<const uint8_t> verification_key) = 0; base::span<const uint8_t> verification_key) = 0;
// Returns the short-form name of the signing algorithm that this Signer
// uses.
virtual std::string GetAlgorithmIdentifier() = 0;
}; };
// Creates a request signing helper with behavior determined by |params|, // Creates a request signing helper with behavior determined by |params|,
......
...@@ -69,6 +69,8 @@ class FakeSigner : public TrustTokenRequestSigningHelper::Signer { ...@@ -69,6 +69,8 @@ class FakeSigner : public TrustTokenRequestSigningHelper::Signer {
NOTREACHED(); NOTREACHED();
return false; return false;
} }
std::string GetAlgorithmIdentifier() override { return "fake-signer"; }
}; };
// IdentitySigner returns a "signature" over given signing data whose value // IdentitySigner returns a "signature" over given signing data whose value
...@@ -87,6 +89,7 @@ class IdentitySigner : public TrustTokenRequestSigningHelper::Signer { ...@@ -87,6 +89,7 @@ class IdentitySigner : public TrustTokenRequestSigningHelper::Signer {
base::span<const uint8_t> verification_key) override { base::span<const uint8_t> verification_key) override {
return std::equal(data.begin(), data.end(), signature.begin()); return std::equal(data.begin(), data.end(), signature.begin());
} }
std::string GetAlgorithmIdentifier() override { return "identity-signer"; }
}; };
// FailingSigner always fails the Sign and Verify options. // FailingSigner always fails the Sign and Verify options.
...@@ -102,6 +105,7 @@ class FailingSigner : public TrustTokenRequestSigningHelper::Signer { ...@@ -102,6 +105,7 @@ class FailingSigner : public TrustTokenRequestSigningHelper::Signer {
base::span<const uint8_t> verification_key) override { base::span<const uint8_t> verification_key) override {
return false; return false;
} }
std::string GetAlgorithmIdentifier() override { return "failing-signer"; }
}; };
// Reconstructs |request|'s canonical request data, extracts the signatures from // Reconstructs |request|'s canonical request data, extracts the signatures from
...@@ -119,8 +123,10 @@ void ReconstructSigningDataAndAssertSignaturesVerify( ...@@ -119,8 +123,10 @@ void ReconstructSigningDataAndAssertSignaturesVerify(
request->url(), request->extra_request_headers(), request->url(), request->extra_request_headers(),
base::BindRepeating([](base::span<const uint8_t> data, base::BindRepeating([](base::span<const uint8_t> data,
base::span<const uint8_t> signature, base::span<const uint8_t> signature,
base::span<const uint8_t> verification_key) { base::span<const uint8_t> verification_key,
return Signer().Verify(data, signature, verification_key); const std::string& signing_alg) {
return Signer().Verify(data, signature, verification_key) &&
signing_alg == Signer().GetAlgorithmIdentifier();
}), }),
&error, &verification_keys_per_issuer); &error, &verification_keys_per_issuer);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment