Commit 23bef1af authored by Jun Choi's avatar Jun Choi Committed by Commit Bot

Check RP ID hash returned from CTAP tokens

CTAP HID transport protocol uses 4 byte channel ID to check that the
message sent by the authenticator is only received and processed by the
correct client process. On the other hand, CTAP BLE transport protocol
defines no such mechanism to differentiate incoming BLE fragments. This,
under some circumstances, enables relying parties to receive
response from authenticators that was intended for different site.

In order to prevent malicious RP from receiving authenticator response
intended for different site, check relying party ID hash returned from
the authenticator in response to MakeCredential and GetAssertion
response.

Bug: 828507
Change-Id: I3b743fc9b9f79284ab4b979d17c75ccc9e5a889c
Reviewed-on: https://chromium-review.googlesource.com/1004118
Commit-Queue: Jun Choi <hongjunchoi@chromium.org>
Reviewed-by: default avatarBalazs Engedy <engedy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#551789}
parent 5fe14697
...@@ -59,7 +59,7 @@ using TestGetCallbackReceiver = ::device::test::StatusAndValueCallbackReceiver< ...@@ -59,7 +59,7 @@ using TestGetCallbackReceiver = ::device::test::StatusAndValueCallbackReceiver<
constexpr char kRelyingPartySecurityErrorMessage[] = constexpr char kRelyingPartySecurityErrorMessage[] =
"SecurityError: The relying party ID 'localhost' is not a registrable " "SecurityError: The relying party ID 'localhost' is not a registrable "
"domain suffix of, nor equal to 'https://www.example.com"; "domain suffix of, nor equal to 'https://www.acme.com";
constexpr char kAlgorithmUnsupportedErrorMessage[] = constexpr char kAlgorithmUnsupportedErrorMessage[] =
"NotSupportedError: None of the algorithms specified in " "NotSupportedError: None of the algorithms specified in "
...@@ -114,7 +114,7 @@ constexpr char kRequiredVerification[] = "required"; ...@@ -114,7 +114,7 @@ constexpr char kRequiredVerification[] = "required";
// Default values for kCreatePublicKeyTemplate. // Default values for kCreatePublicKeyTemplate.
struct CreateParameters { struct CreateParameters {
const char* rp_id = "example.com"; const char* rp_id = "acme.com";
bool require_resident_key = false; bool require_resident_key = false;
const char* user_verification = kPreferredVerification; const char* user_verification = kPreferredVerification;
const char* authenticator_attachment = kCrossPlatform; const char* authenticator_attachment = kCrossPlatform;
...@@ -135,7 +135,7 @@ std::string BuildCreateCallWithParameters(const CreateParameters& parameters) { ...@@ -135,7 +135,7 @@ std::string BuildCreateCallWithParameters(const CreateParameters& parameters) {
constexpr char kGetPublicKeyTemplate[] = constexpr char kGetPublicKeyTemplate[] =
"navigator.credentials.get({ publicKey: {" "navigator.credentials.get({ publicKey: {"
" challenge: new TextEncoder().encode('climb a mountain')," " challenge: new TextEncoder().encode('climb a mountain'),"
" rp: 'example.com'," " rp: 'acme.com',"
" timeout: 60000," " timeout: 60000,"
" userVerification: '$1'," " userVerification: '$1',"
" $2}" " $2}"
...@@ -234,7 +234,7 @@ class WebAuthBrowserTestBase : public content::ContentBrowserTest { ...@@ -234,7 +234,7 @@ class WebAuthBrowserTestBase : public content::ContentBrowserTest {
https_server().ServeFilesFromSourceDirectory("content/test/data"); https_server().ServeFilesFromSourceDirectory("content/test/data");
ASSERT_TRUE(https_server().Start()); ASSERT_TRUE(https_server().Start());
NavigateToURL(shell(), GetHttpsURL("www.example.com", "/title1.html")); NavigateToURL(shell(), GetHttpsURL("www.acme.com", "/title1.html"));
} }
GURL GetHttpsURL(const std::string& hostname, GURL GetHttpsURL(const std::string& hostname,
...@@ -293,7 +293,7 @@ class WebAuthLocalClientBrowserTest : public WebAuthBrowserTestBase { ...@@ -293,7 +293,7 @@ class WebAuthLocalClientBrowserTest : public WebAuthBrowserTestBase {
webauth::mojom::PublicKeyCredentialCreationOptionsPtr webauth::mojom::PublicKeyCredentialCreationOptionsPtr
BuildBasicCreateOptions() { BuildBasicCreateOptions() {
auto rp = webauth::mojom::PublicKeyCredentialRpEntity::New( auto rp = webauth::mojom::PublicKeyCredentialRpEntity::New(
"example.com", "example.com", base::nullopt); "acme.com", "acme.com", base::nullopt);
std::vector<uint8_t> kTestUserId{0, 0, 0}; std::vector<uint8_t> kTestUserId{0, 0, 0};
auto user = webauth::mojom::PublicKeyCredentialUserEntity::New( auto user = webauth::mojom::PublicKeyCredentialUserEntity::New(
...@@ -331,7 +331,7 @@ class WebAuthLocalClientBrowserTest : public WebAuthBrowserTestBase { ...@@ -331,7 +331,7 @@ class WebAuthLocalClientBrowserTest : public WebAuthBrowserTestBase {
std::vector<uint8_t> kTestChallenge{0, 0, 0}; std::vector<uint8_t> kTestChallenge{0, 0, 0};
auto mojo_options = webauth::mojom::PublicKeyCredentialRequestOptions::New( auto mojo_options = webauth::mojom::PublicKeyCredentialRequestOptions::New(
kTestChallenge, base::TimeDelta::FromSeconds(30), "example.com", kTestChallenge, base::TimeDelta::FromSeconds(30), "acme.com",
std::move(credentials), std::move(credentials),
webauth::mojom::UserVerificationRequirement::PREFERRED, base::nullopt); webauth::mojom::UserVerificationRequirement::PREFERRED, base::nullopt);
...@@ -367,7 +367,7 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest, ...@@ -367,7 +367,7 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
create_callback_receiver.callback()); create_callback_receiver.callback());
fake_hid_discovery->WaitForCallToStartAndSimulateSuccess(); fake_hid_discovery->WaitForCallToStartAndSimulateSuccess();
NavigateToURL(shell(), GetHttpsURL("www.example.com", "/title2.html")); NavigateToURL(shell(), GetHttpsURL("www.acme.com", "/title2.html"));
WaitForConnectionError(); WaitForConnectionError();
// The next active document should be able to successfully call // The next active document should be able to successfully call
...@@ -389,7 +389,7 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest, ...@@ -389,7 +389,7 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
get_callback_receiver.callback()); get_callback_receiver.callback());
fake_hid_discovery->WaitForCallToStartAndSimulateSuccess(); fake_hid_discovery->WaitForCallToStartAndSimulateSuccess();
NavigateToURL(shell(), GetHttpsURL("www.example.com", "/title2.html")); NavigateToURL(shell(), GetHttpsURL("www.acme.com", "/title2.html"));
WaitForConnectionError(); WaitForConnectionError();
// The next active document should be able to successfully call // The next active document should be able to successfully call
...@@ -408,7 +408,7 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest, ...@@ -408,7 +408,7 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
ScopedNavigationCancellingThrottleInstaller navigation_canceller( ScopedNavigationCancellingThrottleInstaller navigation_canceller(
shell()->web_contents()); shell()->web_contents());
NavigateToURL(shell(), GetHttpsURL("www.example.com", "/title2.html")); NavigateToURL(shell(), GetHttpsURL("www.acme.com", "/title2.html"));
auto* fake_hid_discovery = discovery_factory()->ForgeNextHidDiscovery(); auto* fake_hid_discovery = discovery_factory()->ForgeNextHidDiscovery();
TestCreateCallbackReceiver create_callback_receiver; TestCreateCallbackReceiver create_callback_receiver;
...@@ -432,7 +432,7 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest, ...@@ -432,7 +432,7 @@ IN_PROC_BROWSER_TEST_F(WebAuthLocalClientBrowserTest,
})); }));
auto* fake_hid_discovery = discovery_factory()->ForgeNextHidDiscovery(); auto* fake_hid_discovery = discovery_factory()->ForgeNextHidDiscovery();
NavigateToURL(shell(), GetHttpsURL("www.example.com", "/title2.html")); NavigateToURL(shell(), GetHttpsURL("www.acme.com", "/title2.html"));
WaitForConnectionError(); WaitForConnectionError();
// Normally, when the request is serviced, the implementation retrieves the // Normally, when the request is serviced, the implementation retrieves the
......
...@@ -50,6 +50,10 @@ class COMPONENT_EXPORT(DEVICE_FIDO) AttestationObject { ...@@ -50,6 +50,10 @@ class COMPONENT_EXPORT(DEVICE_FIDO) AttestationObject {
// "attStmt": attestation statement bytes } // "attStmt": attestation statement bytes }
std::vector<uint8_t> SerializeToCBOREncodedBytes() const; std::vector<uint8_t> SerializeToCBOREncodedBytes() const;
const std::vector<uint8_t>& rp_id_hash() const {
return authenticator_data_.application_parameter();
}
private: private:
AuthenticatorData authenticator_data_; AuthenticatorData authenticator_data_;
std::unique_ptr<AttestationStatement> attestation_statement_; std::unique_ptr<AttestationStatement> attestation_statement_;
......
...@@ -60,6 +60,10 @@ class COMPONENT_EXPORT(DEVICE_FIDO) AuthenticatorData { ...@@ -60,6 +60,10 @@ class COMPONENT_EXPORT(DEVICE_FIDO) AuthenticatorData {
return attested_data_; return attested_data_;
} }
const std::vector<uint8_t>& application_parameter() const {
return application_parameter_;
}
bool obtained_user_presence() const { bool obtained_user_presence() const {
return flags_ & base::strict_cast<uint8_t>(Flag::kTestOfUserPresence); return flags_ & base::strict_cast<uint8_t>(Flag::kTestOfUserPresence);
} }
...@@ -79,6 +83,7 @@ class COMPONENT_EXPORT(DEVICE_FIDO) AuthenticatorData { ...@@ -79,6 +83,7 @@ class COMPONENT_EXPORT(DEVICE_FIDO) AuthenticatorData {
private: private:
// The application parameter: a SHA-256 hash of either the RP ID or the AppID // The application parameter: a SHA-256 hash of either the RP ID or the AppID
// associated with the credential. // associated with the credential.
// TODO(hongjunchoi): Replace fixed size vector components with std::array.
std::vector<uint8_t> application_parameter_; std::vector<uint8_t> application_parameter_;
// Flags (bit 0 is the least significant bit): // Flags (bit 0 is the least significant bit):
......
...@@ -48,8 +48,8 @@ AuthenticatorGetAssertionResponse::CreateFromU2fSignResponse( ...@@ -48,8 +48,8 @@ AuthenticatorGetAssertionResponse::CreateFromU2fSignResponse(
if (signature.empty()) if (signature.empty())
return base::nullopt; return base::nullopt;
auto response = AuthenticatorGetAssertionResponse( AuthenticatorGetAssertionResponse response(std::move(authenticator_data),
std::move(authenticator_data), std::move(signature)); std::move(signature));
response.SetCredential(PublicKeyCredentialDescriptor( response.SetCredential(PublicKeyCredentialDescriptor(
to_string(CredentialType::kPublicKey), key_handle)); to_string(CredentialType::kPublicKey), key_handle));
...@@ -71,6 +71,11 @@ AuthenticatorGetAssertionResponse& AuthenticatorGetAssertionResponse::operator=( ...@@ -71,6 +71,11 @@ AuthenticatorGetAssertionResponse& AuthenticatorGetAssertionResponse::operator=(
AuthenticatorGetAssertionResponse::~AuthenticatorGetAssertionResponse() = AuthenticatorGetAssertionResponse::~AuthenticatorGetAssertionResponse() =
default; default;
const std::vector<uint8_t>& AuthenticatorGetAssertionResponse::GetRpIdHash()
const {
return authenticator_data_.application_parameter();
}
AuthenticatorGetAssertionResponse& AuthenticatorGetAssertionResponse&
AuthenticatorGetAssertionResponse::SetCredential( AuthenticatorGetAssertionResponse::SetCredential(
PublicKeyCredentialDescriptor credential) { PublicKeyCredentialDescriptor credential) {
......
...@@ -36,7 +36,10 @@ class COMPONENT_EXPORT(DEVICE_FIDO) AuthenticatorGetAssertionResponse ...@@ -36,7 +36,10 @@ class COMPONENT_EXPORT(DEVICE_FIDO) AuthenticatorGetAssertionResponse
AuthenticatorGetAssertionResponse(AuthenticatorGetAssertionResponse&& that); AuthenticatorGetAssertionResponse(AuthenticatorGetAssertionResponse&& that);
AuthenticatorGetAssertionResponse& operator=( AuthenticatorGetAssertionResponse& operator=(
AuthenticatorGetAssertionResponse&& other); AuthenticatorGetAssertionResponse&& other);
~AuthenticatorGetAssertionResponse(); ~AuthenticatorGetAssertionResponse() override;
// ResponseData:
const std::vector<uint8_t>& GetRpIdHash() const override;
AuthenticatorGetAssertionResponse& SetCredential( AuthenticatorGetAssertionResponse& SetCredential(
PublicKeyCredentialDescriptor credential); PublicKeyCredentialDescriptor credential);
......
...@@ -85,4 +85,9 @@ bool AuthenticatorMakeCredentialResponse:: ...@@ -85,4 +85,9 @@ bool AuthenticatorMakeCredentialResponse::
.IsAttestationCertificateInappropriatelyIdentifying(); .IsAttestationCertificateInappropriatelyIdentifying();
} }
const std::vector<uint8_t>& AuthenticatorMakeCredentialResponse::GetRpIdHash()
const {
return attestation_object_.rp_id_hash();
}
} // namespace device } // namespace device
...@@ -36,7 +36,7 @@ class COMPONENT_EXPORT(DEVICE_FIDO) AuthenticatorMakeCredentialResponse ...@@ -36,7 +36,7 @@ class COMPONENT_EXPORT(DEVICE_FIDO) AuthenticatorMakeCredentialResponse
AuthenticatorMakeCredentialResponse&& that); AuthenticatorMakeCredentialResponse&& that);
AuthenticatorMakeCredentialResponse& operator=( AuthenticatorMakeCredentialResponse& operator=(
AuthenticatorMakeCredentialResponse&& other); AuthenticatorMakeCredentialResponse&& other);
~AuthenticatorMakeCredentialResponse(); ~AuthenticatorMakeCredentialResponse() override;
std::vector<uint8_t> GetCBOREncodedAttestationObject() const; std::vector<uint8_t> GetCBOREncodedAttestationObject() const;
...@@ -51,6 +51,9 @@ class COMPONENT_EXPORT(DEVICE_FIDO) AuthenticatorMakeCredentialResponse ...@@ -51,6 +51,9 @@ class COMPONENT_EXPORT(DEVICE_FIDO) AuthenticatorMakeCredentialResponse
// not indended to be trackable.) // not indended to be trackable.)
bool IsAttestationCertificateInappropriatelyIdentifying(); bool IsAttestationCertificateInappropriatelyIdentifying();
// ResponseData:
const std::vector<uint8_t>& GetRpIdHash() const override;
private: private:
AttestationObject attestation_object_; AttestationObject attestation_object_;
......
This diff is collapsed.
...@@ -24,7 +24,7 @@ namespace device { ...@@ -24,7 +24,7 @@ namespace device {
namespace { namespace {
constexpr uint8_t kClientDataHash[] = {0x01, 0x02, 0x03}; constexpr uint8_t kClientDataHash[] = {0x01, 0x02, 0x03};
constexpr char kRpId[] = "google.com"; constexpr char kRpId[] = "acme.com";
using TestGetAssertionRequestCallback = test::StatusAndValueCallbackReceiver< using TestGetAssertionRequestCallback = test::StatusAndValueCallbackReceiver<
FidoReturnCode, FidoReturnCode,
......
...@@ -121,7 +121,7 @@ void GetAssertionTask::OnCtapGetAssertionResponseReceived( ...@@ -121,7 +121,7 @@ void GetAssertionTask::OnCtapGetAssertionResponseReceived(
} }
auto parsed_response = ReadCTAPGetAssertionResponse(*device_response); auto parsed_response = ReadCTAPGetAssertionResponse(*device_response);
if (!parsed_response || if (!parsed_response || !parsed_response->CheckRpIdHash(request_.rp_id()) ||
!CheckRequirementsOnReturnedCredentialId(*parsed_response) || !CheckRequirementsOnReturnedCredentialId(*parsed_response) ||
!CheckRequirementsOnReturnedUserEntities(*parsed_response)) { !CheckRequirementsOnReturnedUserEntities(*parsed_response)) {
std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOther, std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOther,
......
...@@ -28,7 +28,7 @@ namespace device { ...@@ -28,7 +28,7 @@ namespace device {
namespace { namespace {
constexpr uint8_t kClientDataHash[] = {0x01, 0x02, 0x03}; constexpr uint8_t kClientDataHash[] = {0x01, 0x02, 0x03};
constexpr char kRpId[] = "google.com"; constexpr char kRpId[] = "acme.com";
using TestGetAssertionTaskCallbackReceiver = using TestGetAssertionTaskCallbackReceiver =
::device::test::StatusAndValueCallbackReceiver< ::device::test::StatusAndValueCallbackReceiver<
...@@ -127,6 +127,30 @@ TEST_F(FidoGetAssertionTaskTest, TestGetAsserionIncorrectUserEntity) { ...@@ -127,6 +127,30 @@ TEST_F(FidoGetAssertionTaskTest, TestGetAsserionIncorrectUserEntity) {
EXPECT_FALSE(get_assertion_callback_receiver().value()); EXPECT_FALSE(get_assertion_callback_receiver().value());
} }
TEST_F(FidoGetAssertionTaskTest, TestGetAsserionIncorrectRpIdHash) {
auto device = std::make_unique<MockFidoDevice>();
device->ExpectCtap2CommandAndRespondWith(
CtapRequestCommand::kAuthenticatorGetInfo,
test_data::kTestAuthenticatorGetInfoResponse);
device->ExpectCtap2CommandAndRespondWith(
CtapRequestCommand::kAuthenticatorGetAssertion,
test_data::kTestGetAssertionResponseWithIncorrectRpIdHash);
auto task = std::make_unique<GetAssertionTask>(
device.get(),
CtapGetAssertionRequest(kRpId,
u2f_parsing_utils::Materialize(kClientDataHash)),
get_assertion_callback_receiver().callback());
get_assertion_callback_receiver().WaitForCallback();
EXPECT_EQ(device->supported_protocol(), ProtocolVersion::kCtap);
EXPECT_TRUE(device->device_info());
EXPECT_EQ(CtapDeviceResponseCode::kCtap2ErrOther,
get_assertion_callback_receiver().status());
EXPECT_FALSE(get_assertion_callback_receiver().value());
}
TEST_F(FidoGetAssertionTaskTest, TestIncorrectGetAssertionResponse) { TEST_F(FidoGetAssertionTaskTest, TestIncorrectGetAssertionResponse) {
auto device = std::make_unique<MockFidoDevice>(); auto device = std::make_unique<MockFidoDevice>();
......
...@@ -29,7 +29,7 @@ namespace { ...@@ -29,7 +29,7 @@ namespace {
constexpr uint8_t kClientDataHash[] = {0x01, 0x02, 0x03}; constexpr uint8_t kClientDataHash[] = {0x01, 0x02, 0x03};
constexpr uint8_t kUserId[] = {0x01, 0x02, 0x03}; constexpr uint8_t kUserId[] = {0x01, 0x02, 0x03};
constexpr char kRpId[] = "google.com"; constexpr char kRpId[] = "acme.com";
using TestMakeCredentialRequestCallback = test::StatusAndValueCallbackReceiver< using TestMakeCredentialRequestCallback = test::StatusAndValueCallbackReceiver<
FidoReturnCode, FidoReturnCode,
......
...@@ -63,8 +63,21 @@ void MakeCredentialTask::OnCtapMakeCredentialResponseReceived( ...@@ -63,8 +63,21 @@ void MakeCredentialTask::OnCtapMakeCredentialResponseReceived(
return; return;
} }
std::move(callback_).Run(GetResponseCode(*device_response), auto response_code = GetResponseCode(*device_response);
ReadCTAPMakeCredentialResponse(*device_response)); if (response_code != CtapDeviceResponseCode::kSuccess) {
std::move(callback_).Run(response_code, base::nullopt);
return;
}
auto parsed_response = ReadCTAPMakeCredentialResponse(*device_response);
if (!parsed_response ||
!parsed_response->CheckRpIdHash(request_parameter_.rp().rp_id())) {
std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOther,
base::nullopt);
return;
}
std::move(callback_).Run(response_code, std::move(parsed_response));
} }
bool MakeCredentialTask::CheckIfAuthenticatorSelectionCriteriaAreSatisfied() { bool MakeCredentialTask::CheckIfAuthenticatorSelectionCriteriaAreSatisfied() {
......
...@@ -29,7 +29,7 @@ namespace { ...@@ -29,7 +29,7 @@ namespace {
constexpr uint8_t kClientDataHash[] = {0x01, 0x02, 0x03}; constexpr uint8_t kClientDataHash[] = {0x01, 0x02, 0x03};
constexpr uint8_t kUserId[] = {0x01, 0x02, 0x03}; constexpr uint8_t kUserId[] = {0x01, 0x02, 0x03};
constexpr char kRpId[] = "google.com"; constexpr char kRpId[] = "acme.com";
using TestMakeCredentialTaskCallback = using TestMakeCredentialTaskCallback =
::device::test::StatusAndValueCallbackReceiver< ::device::test::StatusAndValueCallbackReceiver<
...@@ -117,6 +117,23 @@ TEST_F(FidoMakeCredentialTaskTest, TestIncorrectAuthenticatorGetInfoResponse) { ...@@ -117,6 +117,23 @@ TEST_F(FidoMakeCredentialTaskTest, TestIncorrectAuthenticatorGetInfoResponse) {
EXPECT_FALSE(device->device_info()); EXPECT_FALSE(device->device_info());
} }
TEST_F(FidoMakeCredentialTaskTest, TestMakeCredentialWithIncorrectRpIdHash) {
auto device = std::make_unique<MockFidoDevice>();
device->ExpectCtap2CommandAndRespondWith(
CtapRequestCommand::kAuthenticatorGetInfo,
test_data::kTestAuthenticatorGetInfoResponse);
device->ExpectCtap2CommandAndRespondWith(
CtapRequestCommand::kAuthenticatorMakeCredential,
test_data::kTestMakeCredentialResponseWithIncorrectRpIdHash);
const auto task = CreateMakeCredentialTask(device.get());
make_credential_callback_receiver().WaitForCallback();
EXPECT_EQ(CtapDeviceResponseCode::kCtap2ErrOther,
make_credential_callback_receiver().status());
}
TEST_F(FidoMakeCredentialTaskTest, TEST_F(FidoMakeCredentialTaskTest,
TestUserVerificationAuthenticatorSelectionCriteria) { TestUserVerificationAuthenticatorSelectionCriteria) {
auto device = std::make_unique<MockFidoDevice>(); auto device = std::make_unique<MockFidoDevice>();
......
...@@ -8,9 +8,12 @@ ...@@ -8,9 +8,12 @@
#include "base/base64url.h" #include "base/base64url.h"
#include "base/strings/string_piece.h" #include "base/strings/string_piece.h"
#include "crypto/sha2.h"
namespace device { namespace device {
ResponseData::~ResponseData() = default;
ResponseData::ResponseData() = default; ResponseData::ResponseData() = default;
ResponseData::ResponseData(std::vector<uint8_t> raw_credential_id) ResponseData::ResponseData(std::vector<uint8_t> raw_credential_id)
...@@ -20,8 +23,6 @@ ResponseData::ResponseData(ResponseData&& other) = default; ...@@ -20,8 +23,6 @@ ResponseData::ResponseData(ResponseData&& other) = default;
ResponseData& ResponseData::operator=(ResponseData&& other) = default; ResponseData& ResponseData::operator=(ResponseData&& other) = default;
ResponseData::~ResponseData() = default;
std::string ResponseData::GetId() const { std::string ResponseData::GetId() const {
std::string id; std::string id;
base::Base64UrlEncode(base::StringPiece(reinterpret_cast<const char*>( base::Base64UrlEncode(base::StringPiece(reinterpret_cast<const char*>(
...@@ -31,4 +32,12 @@ std::string ResponseData::GetId() const { ...@@ -31,4 +32,12 @@ std::string ResponseData::GetId() const {
return id; return id;
} }
bool ResponseData::CheckRpIdHash(const std::string& rp_id) const {
const auto& response_rp_id_hash = GetRpIdHash();
std::vector<uint8_t> request_rp_id_hash(crypto::kSHA256Length);
crypto::SHA256HashString(rp_id, request_rp_id_hash.data(),
request_rp_id_hash.size());
return response_rp_id_hash == request_rp_id_hash;
}
} // namespace device } // namespace device
...@@ -15,10 +15,21 @@ ...@@ -15,10 +15,21 @@
namespace device { namespace device {
// Base class for RegisterResponseData and SignResponseData. // Base class for AuthenticatorMakeCredentialResponse and
// AuthenticatorGetAssertionResponse.
class COMPONENT_EXPORT(DEVICE_FIDO) ResponseData { class COMPONENT_EXPORT(DEVICE_FIDO) ResponseData {
public: public:
virtual ~ResponseData();
virtual const std::vector<uint8_t>& GetRpIdHash() const = 0;
std::string GetId() const; std::string GetId() const;
// Checks that the SHA256 hash of the relying party id obtained from the
// request parameter matches the application parameter returned from the
// authenticator.
bool CheckRpIdHash(const std::string& rp_id) const;
const std::vector<uint8_t>& raw_credential_id() const { const std::vector<uint8_t>& raw_credential_id() const {
return raw_credential_id_; return raw_credential_id_;
} }
...@@ -31,8 +42,6 @@ class COMPONENT_EXPORT(DEVICE_FIDO) ResponseData { ...@@ -31,8 +42,6 @@ class COMPONENT_EXPORT(DEVICE_FIDO) ResponseData {
ResponseData(ResponseData&& other); ResponseData(ResponseData&& other);
ResponseData& operator=(ResponseData&& other); ResponseData& operator=(ResponseData&& other);
~ResponseData();
std::vector<uint8_t> raw_credential_id_; std::vector<uint8_t> raw_credential_id_;
private: private:
......
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