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(
verification_key.data());
}
std::string Ed25519TrustTokenRequestSigner::GetAlgorithmIdentifier() {
return "ed25519";
}
} // namespace network
......@@ -26,6 +26,8 @@ class Ed25519TrustTokenRequestSigner
bool Verify(base::span<const uint8_t> data,
base::span<const uint8_t> signature,
base::span<const uint8_t> verification_key) override;
std::string GetAlgorithmIdentifier() override;
};
} // namespace network
......
......@@ -55,11 +55,12 @@ bool ReconstructSigningDataAndVerifyForIndividualIssuer(
const net::HttpRequestHeaders& headers,
base::RepeatingCallback<bool(base::span<const uint8_t> data,
base::span<const uint8_t> signature,
base::span<const uint8_t> verification_key)>
verifier,
base::span<const uint8_t> verification_key,
const std::string& sig_alg)> verifier,
mojom::TrustTokenSignRequestData sign_request_data,
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()) {
*error_out = "type-unsafe issuer in Sec-Signature header";
return false;
......@@ -121,14 +122,20 @@ bool ReconstructSigningDataAndVerifyForIndividualIssuer(
written_reconstructed_cbor->end());
if (!verifier) {
verifier =
base::BindRepeating(&Ed25519TrustTokenRequestSigner::Verify,
std::make_unique<Ed25519TrustTokenRequestSigner>());
verifier = base::BindRepeating(
[](base::span<const uint8_t> data, base::span<const uint8_t> signature,
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),
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";
return false;
}
......@@ -195,13 +202,33 @@ bool ExtractIssuersAndParametersFromSignatureHeaderMap(
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(
const SignatureHeaderMap& map,
std::vector<net::structured_headers::ParameterizedItem>*
issuers_and_parameters_out,
mojom::TrustTokenSignRequestData* sign_request_data_out,
std::string* sig_alg_out,
std::string* error_out) {
if (map.size() != 2) {
if (map.size() != 3) {
*error_out = "Unexpected number of members in Sec-Signature header map";
return false;
}
......@@ -216,6 +243,11 @@ bool ValidateSignatureHeaderMapAndExtractFields(
return false;
}
if (!ExtractSigningAlgorithmIdentifierFromSignatureHeaderMap(map, sig_alg_out,
error_out)) {
return false;
}
return true;
}
......@@ -264,8 +296,8 @@ bool ReconstructSigningDataAndVerifySignatures(
const net::HttpRequestHeaders& headers,
base::RepeatingCallback<bool(base::span<const uint8_t> data,
base::span<const uint8_t> signature,
base::span<const uint8_t> verification_key)>
verifier,
base::span<const uint8_t> verification_key,
const std::string& sig_alg)> verifier,
std::string* error_out,
std::map<std::string, std::string>* verification_keys_out) {
// Make it possible to set the error without needing to check for
......@@ -292,9 +324,10 @@ bool ReconstructSigningDataAndVerifySignatures(
std::vector<net::structured_headers::ParameterizedItem>
issuers_and_parameters;
mojom::TrustTokenSignRequestData sign_request_data;
std::string sig_alg;
if (!ValidateSignatureHeaderMapAndExtractFields(
*signature_header_map, &issuers_and_parameters, &sign_request_data,
error_out)) {
&sig_alg, error_out)) {
return false;
}
......@@ -304,7 +337,7 @@ bool ReconstructSigningDataAndVerifySignatures(
// |error_out| on failure.
if (!ReconstructSigningDataAndVerifyForIndividualIssuer(
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;
}
}
......
......@@ -53,8 +53,9 @@ bool ReconstructSigningDataAndVerifySignatures(
const net::HttpRequestHeaders& headers,
base::RepeatingCallback<bool(base::span<const uint8_t> data,
base::span<const uint8_t> signature,
base::span<const uint8_t> verification_key)>
verifier = {}, // defaults to Ed25519
base::span<const uint8_t> verification_key,
const std::string& sig_alg)> verifier =
{}, // defaults to Ed25519
std::string* error_out = nullptr,
std::map<std::string, std::string>* verification_keys_out = nullptr);
......
......@@ -97,6 +97,7 @@ const char kSignatureHeaderSignRequestDataIncludeValue[] = "include";
const char kSignatureHeaderSignRequestDataHeadersOnlyValue[] = "headers-only";
const char kSignatureHeaderSignaturesKey[] = "signatures";
const char kSignatureHeaderSignRequestDataKey[] = "sign-request-data";
const char kSignatureHeaderAlgorithmKey[] = "alg";
const char kSignatureHeaderPublicKeyKey[] = "public-key";
const char kSignatureHeaderSignatureKey[] = "sig";
const char kRedemptionRecordHeaderRedemptionRecordKey[] = "redemption-record";
......@@ -517,6 +518,10 @@ base::Optional<std::string> TrustTokenRequestSigningHelper::
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;
for (const auto& kv : signatures_per_issuer) {
const SuitableTrustTokenOrigin& issuer = kv.first;
......
......@@ -150,6 +150,10 @@ class TrustTokenRequestSigningHelper : public TrustTokenRequestHelper {
virtual bool Verify(base::span<const uint8_t> data,
base::span<const uint8_t> signature,
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|,
......
......@@ -69,6 +69,8 @@ class FakeSigner : public TrustTokenRequestSigningHelper::Signer {
NOTREACHED();
return false;
}
std::string GetAlgorithmIdentifier() override { return "fake-signer"; }
};
// IdentitySigner returns a "signature" over given signing data whose value
......@@ -87,6 +89,7 @@ class IdentitySigner : public TrustTokenRequestSigningHelper::Signer {
base::span<const uint8_t> verification_key) override {
return std::equal(data.begin(), data.end(), signature.begin());
}
std::string GetAlgorithmIdentifier() override { return "identity-signer"; }
};
// FailingSigner always fails the Sign and Verify options.
......@@ -102,6 +105,7 @@ class FailingSigner : public TrustTokenRequestSigningHelper::Signer {
base::span<const uint8_t> verification_key) override {
return false;
}
std::string GetAlgorithmIdentifier() override { return "failing-signer"; }
};
// Reconstructs |request|'s canonical request data, extracts the signatures from
......@@ -119,8 +123,10 @@ void ReconstructSigningDataAndAssertSignaturesVerify(
request->url(), request->extra_request_headers(),
base::BindRepeating([](base::span<const uint8_t> data,
base::span<const uint8_t> signature,
base::span<const uint8_t> verification_key) {
return Signer().Verify(data, signature, verification_key);
base::span<const uint8_t> verification_key,
const std::string& signing_alg) {
return Signer().Verify(data, signature, verification_key) &&
signing_alg == Signer().GetAlgorithmIdentifier();
}),
&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