Commit 09664c03 authored by Jun Choi's avatar Jun Choi Committed by Commit Bot

Implement parsing logic for MakeCredentialRequest

In order to implement virtual CTAP2 security key, we need to be able to
parse and validate serialized MakeCredential request bytes that the
client sends to the device. Add the corresponding parsing/validation
logic.

Bug: 829413
Change-Id: Ibbb2800a444d844b01ce7a35eba50a4541b0da02
Reviewed-on: https://chromium-review.googlesource.com/1104956
Commit-Queue: Jun Choi <hongjunchoi@chromium.org>
Reviewed-by: default avatarJan Wilken Dörrie <jdoerrie@chromium.org>
Cr-Commit-Position: refs/heads/master@{#569871}
parent c90892e4
......@@ -4,15 +4,47 @@
#include "device/fido/ctap_make_credential_request.h"
#include <algorithm>
#include <limits>
#include <utility>
#include "base/numerics/safe_conversions.h"
#include "components/cbor/cbor_reader.h"
#include "components/cbor/cbor_writer.h"
#include "device/fido/fido_constants.h"
#include "device/fido/fido_parsing_utils.h"
namespace device {
namespace {
bool AreMakeCredentialRequestMapKeysCorrect(
const cbor::CBORValue::MapValue& request_map) {
return std::all_of(request_map.begin(), request_map.end(),
[](const auto& param) {
if (!param.first.is_integer())
return false;
const auto& key = param.first.GetInteger();
return (key <= 9u && key >= 1u);
});
}
bool IsMakeCredentialOptionMapFormatCorrect(
const cbor::CBORValue::MapValue& option_map) {
return std::all_of(
option_map.begin(), option_map.end(), [](const auto& param) {
if (!param.first.is_string())
return false;
const auto& key = param.first.GetString();
return ((key == kResidentKeyMapKey || key == kUserVerificationMapKey) &&
param.second.is_bool());
});
}
} // namespace
CtapMakeCredentialRequest::CtapMakeCredentialRequest(
base::span<const uint8_t, kClientDataHashLength> client_data_hash,
PublicKeyCredentialRpEntity rp,
......@@ -126,4 +158,112 @@ CtapMakeCredentialRequest::SetIsIndividualAttestation(
return *this;
}
base::Optional<CtapMakeCredentialRequest> ParseCtapMakeCredentialRequest(
base::span<const uint8_t> request_bytes) {
const auto& cbor_request = cbor::CBORReader::Read(request_bytes);
if (!cbor_request || !cbor_request->is_map())
return base::nullopt;
const auto& request_map = cbor_request->GetMap();
if (!AreMakeCredentialRequestMapKeysCorrect(request_map))
return base::nullopt;
const auto client_data_hash_it = request_map.find(cbor::CBORValue(1));
if (client_data_hash_it == request_map.end() ||
!client_data_hash_it->second.is_bytestring())
return base::nullopt;
const auto client_data_hash =
base::make_span(client_data_hash_it->second.GetBytestring())
.subspan<0, kClientDataHashLength>();
const auto rp_entity_it = request_map.find(cbor::CBORValue(2));
if (rp_entity_it == request_map.end() || !rp_entity_it->second.is_map())
return base::nullopt;
auto rp_entity =
PublicKeyCredentialRpEntity::CreateFromCBORValue(rp_entity_it->second);
if (!rp_entity)
return base::nullopt;
const auto user_entity_it = request_map.find(cbor::CBORValue(3));
if (user_entity_it == request_map.end() || !user_entity_it->second.is_map())
return base::nullopt;
auto user_entity = PublicKeyCredentialUserEntity::CreateFromCBORValue(
user_entity_it->second);
if (!user_entity)
return base::nullopt;
const auto credential_params_it = request_map.find(cbor::CBORValue(4));
if (credential_params_it == request_map.end())
return base::nullopt;
auto credential_params = PublicKeyCredentialParams::CreateFromCBORValue(
credential_params_it->second);
if (!credential_params)
return base::nullopt;
CtapMakeCredentialRequest request(client_data_hash, std::move(*rp_entity),
std::move(*user_entity),
std::move(*credential_params));
const auto exclude_list_it = request_map.find(cbor::CBORValue(5));
if (exclude_list_it != request_map.end()) {
if (!exclude_list_it->second.is_array())
return base::nullopt;
const auto& credential_descriptors = exclude_list_it->second.GetArray();
std::vector<PublicKeyCredentialDescriptor> exclude_list;
for (const auto& credential_descriptor : credential_descriptors) {
auto excluded_credential =
PublicKeyCredentialDescriptor::CreateFromCBORValue(
credential_descriptor);
if (!excluded_credential)
return base::nullopt;
exclude_list.push_back(std::move(*excluded_credential));
}
request.SetExcludeList(std::move(exclude_list));
}
const auto option_it = request_map.find(cbor::CBORValue(7));
if (option_it != request_map.end()) {
if (!option_it->second.is_map())
return base::nullopt;
const auto& option_map = option_it->second.GetMap();
if (!IsMakeCredentialOptionMapFormatCorrect(option_map))
return base::nullopt;
const auto resident_key_option =
option_map.find(cbor::CBORValue(kResidentKeyMapKey));
if (resident_key_option != option_map.end())
request.SetResidentKeySupported(resident_key_option->second.GetBool());
const auto uv_option =
option_map.find(cbor::CBORValue(kUserVerificationMapKey));
if (uv_option != option_map.end())
request.SetUserVerificationRequired(uv_option->second.GetBool());
}
const auto pin_auth_it = request_map.find(cbor::CBORValue(8));
if (pin_auth_it != request_map.end()) {
if (!pin_auth_it->second.is_bytestring())
return base::nullopt;
request.SetPinAuth(pin_auth_it->second.GetBytestring());
}
const auto pin_protocol_it = request_map.find(cbor::CBORValue(9));
if (pin_protocol_it != request_map.end()) {
if (!pin_protocol_it->second.is_unsigned() ||
pin_protocol_it->second.GetUnsigned() >
std::numeric_limits<uint8_t>::max())
return base::nullopt;
request.SetPinProtocol(pin_auth_it->second.GetUnsigned());
}
return request;
}
} // namespace device
......@@ -85,6 +85,10 @@ class COMPONENT_EXPORT(DEVICE_FIDO) CtapMakeCredentialRequest {
base::Optional<uint8_t> pin_protocol_;
};
COMPONENT_EXPORT(DEVICE_FIDO)
base::Optional<CtapMakeCredentialRequest> ParseCtapMakeCredentialRequest(
base::span<const uint8_t> request_bytes);
} // namespace device
#endif // DEVICE_FIDO_CTAP_MAKE_CREDENTIAL_REQUEST_H_
......@@ -16,88 +16,6 @@ namespace device {
// Leveraging example 4 of section 6.1 of the spec
// https://fidoalliance.org/specs/fido-v2.0-rd-20170927/fido-client-to-authenticator-protocol-v2.0-rd-20170927.html
TEST(CTAPRequestTest, TestConstructMakeCredentialRequestParam) {
static constexpr uint8_t kSerializedRequest[] = {
// clang-format off
0x01, // authenticatorMakeCredential command
0xa5, // map(5)
0x01, // clientDataHash
0x58, 0x20, // bytes(32)
0x68, 0x71, 0x34, 0x96, 0x82, 0x22, 0xec, 0x17, 0x20, 0x2e, 0x42, 0x50,
0x5f, 0x8e, 0xd2, 0xb1, 0x6a, 0xe2, 0x2f, 0x16, 0xbb, 0x05, 0xb8, 0x8c,
0x25, 0xdb, 0x9e, 0x60, 0x26, 0x45, 0xf1, 0x41,
0x02, // unsigned(2) - rp
0xa2, // map(2)
0x62, // text(2)
0x69, 0x64, // "id"
0x68, // text(8)
// "acme.com"
0x61, 0x63, 0x6d, 0x65, 0x2e, 0x63, 0x6f, 0x6d,
0x64, // text(4)
0x6e, 0x61, 0x6d, 0x65, // "name"
0x64, // text(4)
0x41, 0x63, 0x6d, 0x65, // "Acme"
0x03, // unsigned(3) - user
0xa4, // map(4)
0x62, // text(2)
0x69, 0x64, // "id"
0x48, // bytes(8) - user id
0x10, 0x98, 0x23, 0x72, 0x35, 0x40, 0x98, 0x72,
0x64, // text(4)
0x69, 0x63, 0x6f, 0x6e, // "icon"
0x78, 0x28, // text(40)
// "https://pics.acme.com/00/p/aBjjjpqPb.png"
0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x70, 0x69, 0x63, 0x73,
0x2e, 0x61, 0x63, 0x6d, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x30, 0x30,
0x2f, 0x70, 0x2f, 0x61, 0x42, 0x6a, 0x6a, 0x6a, 0x70, 0x71, 0x50, 0x62,
0x2e, 0x70, 0x6e, 0x67,
0x64, // text(4)
0x6e, 0x61, 0x6d, 0x65, // "name"
0x76, // text(22)
// "johnpsmith@example.com"
0x6a, 0x6f, 0x68, 0x6e, 0x70, 0x73, 0x6d, 0x69, 0x74, 0x68, 0x40, 0x65,
0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d,
0x6b, // text(11)
// "displayName"
0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65,
0x6d, // text(13)
// "John P. Smith"
0x4a, 0x6f, 0x68, 0x6e, 0x20, 0x50, 0x2e, 0x20, 0x53, 0x6d, 0x69, 0x74,
0x68,
0x04, // unsigned(4) - pubKeyCredParams
0x82, // array(2)
0xa2, // map(2)
0x63, // text(3)
0x61, 0x6c, 0x67, // "alg"
0x07, // 7
0x64, // text(4)
0x74, 0x79, 0x70, 0x65, // "type"
0x6a, // text(10)
// "public-key"
0x70, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x2D, 0x6B, 0x65, 0x79,
0xa2, // map(2)
0x63, // text(3)
0x61, 0x6c, 0x67, // "alg"
0x19, 0x01, 0x01, // 257
0x64, // text(4)
0x74, 0x79, 0x70, 0x65, // "type"
0x6a, // text(10)
// "public-key"
0x70, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x2D, 0x6B, 0x65, 0x79,
0x07, // unsigned(7) - options
0xa2, // map(2)
0x62, // text(2)
0x72, 0x6b, // "rk"
0xf5, // True(21)
0x62, // text(2)
0x75, 0x76, // "uv"
0xf5 // True(21)
// clang-format on
};
PublicKeyCredentialRpEntity rp("acme.com");
rp.SetRpName("Acme");
......@@ -114,7 +32,8 @@ TEST(CTAPRequestTest, TestConstructMakeCredentialRequestParam) {
auto serialized_data = make_credential_param.SetResidentKeySupported(true)
.SetUserVerificationRequired(true)
.EncodeAsCBOR();
EXPECT_THAT(serialized_data, ::testing::ElementsAreArray(kSerializedRequest));
EXPECT_THAT(serialized_data, ::testing::ElementsAreArray(
test_data::kCtapMakeCredentialRequest));
}
TEST(CTAPRequestTest, TestConstructGetAssertionRequest) {
......@@ -222,4 +141,36 @@ TEST(CTAPRequestTest, TestConstructCtapAuthenticatorRequestParam) {
::testing::ElementsAre(kSerializedResetCmd));
}
TEST(CTAPRequestTest, ParseMakeCredentialRequestForVirtualCtapKey) {
const auto request = ParseCtapMakeCredentialRequest(
base::make_span(test_data::kCtapMakeCredentialRequest).subspan(1));
ASSERT_TRUE(request);
EXPECT_THAT(request->client_data_hash(),
::testing::ElementsAreArray(test_data::kClientDataHash));
EXPECT_EQ(test_data::kRelyingPartyId, request->rp().rp_id());
EXPECT_EQ("Acme", request->rp().rp_name());
EXPECT_THAT(request->user().user_id(),
::testing::ElementsAreArray(test_data::kUserId));
ASSERT_TRUE(request->user().user_name());
EXPECT_EQ("johnpsmith@example.com", *request->user().user_name());
ASSERT_TRUE(request->user().user_display_name());
EXPECT_EQ("John P. Smith", *request->user().user_display_name());
ASSERT_TRUE(request->user().user_icon_url());
EXPECT_EQ("https://pics.acme.com/00/p/aBjjjpqPb.png",
request->user().user_icon_url()->spec());
ASSERT_EQ(2u, request->public_key_credential_params()
.public_key_credential_params()
.size());
EXPECT_EQ(7, request->public_key_credential_params()
.public_key_credential_params()
.at(0)
.algorithm);
EXPECT_EQ(257, request->public_key_credential_params()
.public_key_credential_params()
.at(1)
.algorithm);
EXPECT_TRUE(request->user_verification_required());
EXPECT_TRUE(request->resident_key_supported());
}
} // namespace device
......@@ -21,6 +21,12 @@ const char kUserVerificationMapKey[] = "uv";
const char kUserPresenceMapKey[] = "up";
const char kClientPinMapKey[] = "clientPin";
const char kPlatformDeviceMapKey[] = "plat";
const char kEntityIdMapKey[] = "id";
const char kEntityNameMapKey[] = "name";
const char kDisplayNameMapKey[] = "displayName";
const char kIconUrlMapKey[] = "icon";
const char kCredentialTypeMapKey[] = "type";
const char kCredentialAlgorithmMapKey[] = "alg";
const size_t kHidPacketSize = 64;
const uint32_t kHidBroadcastChannel = 0xffffffff;
......
......@@ -282,6 +282,12 @@ COMPONENT_EXPORT(DEVICE_FIDO) extern const char kUserVerificationMapKey[];
COMPONENT_EXPORT(DEVICE_FIDO) extern const char kUserPresenceMapKey[];
COMPONENT_EXPORT(DEVICE_FIDO) extern const char kClientPinMapKey[];
COMPONENT_EXPORT(DEVICE_FIDO) extern const char kPlatformDeviceMapKey[];
COMPONENT_EXPORT(DEVICE_FIDO) extern const char kEntityIdMapKey[];
COMPONENT_EXPORT(DEVICE_FIDO) extern const char kEntityNameMapKey[];
COMPONENT_EXPORT(DEVICE_FIDO) extern const char kDisplayNameMapKey[];
COMPONENT_EXPORT(DEVICE_FIDO) extern const char kIconUrlMapKey[];
COMPONENT_EXPORT(DEVICE_FIDO) extern const char kCredentialTypeMapKey[];
COMPONENT_EXPORT(DEVICE_FIDO) extern const char kCredentialAlgorithmMapKey[];
// HID transport specific constants.
COMPONENT_EXPORT(DEVICE_FIDO) extern const size_t kHidPacketSize;
......
......@@ -723,6 +723,92 @@ constexpr uint8_t kTestSignAuthenticatorData[] = {
constexpr uint8_t kTestCorruptedU2fSignResponse[] = {0x01, 0x00, 0x00,
0x00, 0x90, 0x00};
// CTAP requests ---------------------------------------------------------------
constexpr uint8_t kCtapMakeCredentialRequest[] = {
// authenticatorMakeCredential command
0x01,
// map(5)
0xa5,
// key(1) - clientDataHash
0x01,
// bytes(32)
0x58, 0x20, 0x68, 0x71, 0x34, 0x96, 0x82, 0x22, 0xec, 0x17, 0x20, 0x2e,
0x42, 0x50, 0x5f, 0x8e, 0xd2, 0xb1, 0x6a, 0xe2, 0x2f, 0x16, 0xbb, 0x05,
0xb8, 0x8c, 0x25, 0xdb, 0x9e, 0x60, 0x26, 0x45, 0xf1, 0x41,
// key(2) - rp
0x02,
// map(2)
0xa2,
// key - "id"
0x62, 0x69, 0x64,
// value - "acme.com"
0x68, 0x61, 0x63, 0x6d, 0x65, 0x2e, 0x63, 0x6f, 0x6d,
// key - "name"
0x64, 0x6e, 0x61, 0x6d, 0x65,
// value - "Acme"
0x64, 0x41, 0x63, 0x6d, 0x65,
// key(3) - user
0x03,
// map(4)
0xa4,
// key - "id"
0x62, 0x69, 0x64,
// value - user id
0x48, 0x10, 0x98, 0x23, 0x72, 0x35, 0x40, 0x98, 0x72,
// key - "icon"
0x64, 0x69, 0x63, 0x6f, 0x6e,
// value - "https://pics.acme.com/00/p/aBjjjpqPb.png"
0x78, 0x28, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x70, 0x69,
0x63, 0x73, 0x2e, 0x61, 0x63, 0x6d, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
0x30, 0x30, 0x2f, 0x70, 0x2f, 0x61, 0x42, 0x6a, 0x6a, 0x6a, 0x70, 0x71,
0x50, 0x62, 0x2e, 0x70, 0x6e, 0x67,
// key - "name"
0x64, 0x6e, 0x61, 0x6d, 0x65,
// value - "johnpsmith@example.com"
0x76, 0x6a, 0x6f, 0x68, 0x6e, 0x70, 0x73, 0x6d, 0x69, 0x74, 0x68, 0x40,
0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d,
// key - "displayName"
0x6b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65,
// value - "John P. Smith"
0x6d, 0x4a, 0x6f, 0x68, 0x6e, 0x20, 0x50, 0x2e, 0x20, 0x53, 0x6d, 0x69,
0x74, 0x68,
// key(4) - pubKeyCredParams
0x04,
// array(2)
0x82,
// map(2)
0xa2,
// key - "alg"
0x63, 0x61, 0x6c, 0x67,
// value - 7
0x07,
// key - "type"
0x64, 0x74, 0x79, 0x70, 0x65,
// value - "public-key"
0x6a, 0x70, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x2D, 0x6B, 0x65, 0x79,
// map(2)
0xa2,
// key - "alg"
0x63, 0x61, 0x6c, 0x67,
// value - 257
0x19, 0x01, 0x01,
// key - "type"
0x64, 0x74, 0x79, 0x70, 0x65, // "type"
// value - "public-key"
0x6a, 0x70, 0x75, 0x62, 0x6C, 0x69, 0x63, 0x2D, 0x6B, 0x65, 0x79,
// key(7) - options
0x07,
// map(2)
0xa2,
// key - "rk"
0x62, 0x72, 0x6b,
// True(21)
0xf5,
// key - "uv"
0x62, 0x75, 0x76,
// True(21)
0xf5};
// CTAP responses --------------------------------------------------------------
// A sample well formed response to CTAP AuthenticatorGetInfo request. Supports
......
......@@ -8,6 +8,39 @@
namespace device {
// static
base::Optional<PublicKeyCredentialParams>
PublicKeyCredentialParams::CreateFromCBORValue(
const cbor::CBORValue& cbor_value) {
if (!cbor_value.is_array())
return base::nullopt;
std::vector<PublicKeyCredentialParams::CredentialInfo> credential_params;
for (const auto& credential : cbor_value.GetArray()) {
if (!credential.is_map() || credential.GetMap().size() != 2)
return base::nullopt;
const auto& credential_map = credential.GetMap();
const auto credential_type_it =
credential_map.find(cbor::CBORValue(kCredentialTypeMapKey));
const auto algorithm_type_it =
credential_map.find(cbor::CBORValue(kCredentialAlgorithmMapKey));
if (credential_type_it == credential_map.end() ||
!credential_type_it->second.is_string() ||
credential_type_it->second.GetString() != kPublicKey ||
algorithm_type_it == credential_map.end() ||
!algorithm_type_it->second.is_integer()) {
return base::nullopt;
}
credential_params.push_back(PublicKeyCredentialParams::CredentialInfo{
CredentialType::kPublicKey, algorithm_type_it->second.GetInteger()});
}
return PublicKeyCredentialParams(std::move(credential_params));
}
PublicKeyCredentialParams::PublicKeyCredentialParams(
std::vector<CredentialInfo> credential_params)
: public_key_credential_params_(std::move(credential_params)) {}
......@@ -32,10 +65,10 @@ cbor::CBORValue PublicKeyCredentialParams::ConvertToCBOR() const {
for (const auto& credential : public_key_credential_params_) {
cbor::CBORValue::MapValue cbor_credential_map;
cbor_credential_map[cbor::CBORValue("type")] =
cbor::CBORValue(CredentialTypeToString(credential.type));
cbor_credential_map[cbor::CBORValue("alg")] =
cbor::CBORValue(credential.algorithm);
cbor_credential_map.emplace(kCredentialTypeMapKey,
CredentialTypeToString(credential.type));
cbor_credential_map.emplace(kCredentialAlgorithmMapKey,
credential.algorithm);
credential_param_array.emplace_back(std::move(cbor_credential_map));
}
return cbor::CBORValue(std::move(credential_param_array));
......
......@@ -12,6 +12,7 @@
#include "base/component_export.h"
#include "base/macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/optional.h"
#include "components/cbor/cbor_values.h"
#include "device/fido/fido_constants.h"
......@@ -27,6 +28,9 @@ class COMPONENT_EXPORT(DEVICE_FIDO) PublicKeyCredentialParams {
int algorithm = base::strict_cast<int>(CoseAlgorithmIdentifier::kCoseEs256);
};
static base::Optional<PublicKeyCredentialParams> CreateFromCBORValue(
const cbor::CBORValue& cbor_value);
explicit PublicKeyCredentialParams(
std::vector<CredentialInfo> credential_params);
PublicKeyCredentialParams(const PublicKeyCredentialParams& other);
......
......@@ -4,10 +4,49 @@
#include "device/fido/public_key_credential_rp_entity.h"
#include <algorithm>
#include <utility>
#include "device/fido/fido_constants.h"
namespace device {
// static
base::Optional<PublicKeyCredentialRpEntity>
PublicKeyCredentialRpEntity::CreateFromCBORValue(const cbor::CBORValue& cbor) {
if (!cbor.is_map() || cbor.GetMap().size() > 3)
return base::nullopt;
const auto& rp_map = cbor.GetMap();
bool is_rp_map_format_correct =
std::all_of(rp_map.begin(), rp_map.end(), [](const auto& element) {
if (!element.first.is_string() || !element.second.is_string())
return false;
const auto& key = element.first.GetString();
return (key == kEntityIdMapKey || key == kEntityNameMapKey ||
key == kIconUrlMapKey);
});
if (!is_rp_map_format_correct)
return base::nullopt;
const auto& id_it = rp_map.find(cbor::CBORValue(kEntityIdMapKey));
const auto& name_it = rp_map.find(cbor::CBORValue(kEntityNameMapKey));
const auto& icon_it = rp_map.find(cbor::CBORValue(kIconUrlMapKey));
if (id_it == rp_map.end())
return base::nullopt;
PublicKeyCredentialRpEntity rp(id_it->second.GetString());
if (name_it != rp_map.end())
rp.SetRpName(name_it->second.GetString());
if (icon_it != rp_map.end())
rp.SetRpIconUrl(GURL(icon_it->second.GetString()));
return rp;
}
PublicKeyCredentialRpEntity::PublicKeyCredentialRpEntity(std::string rp_id)
: rp_id_(std::move(rp_id)) {}
......@@ -39,11 +78,13 @@ PublicKeyCredentialRpEntity& PublicKeyCredentialRpEntity::SetRpIconUrl(
cbor::CBORValue PublicKeyCredentialRpEntity::ConvertToCBOR() const {
cbor::CBORValue::MapValue rp_map;
rp_map[cbor::CBORValue("id")] = cbor::CBORValue(rp_id_);
rp_map.emplace(kEntityIdMapKey, rp_id_);
if (rp_name_)
rp_map[cbor::CBORValue("name")] = cbor::CBORValue(*rp_name_);
rp_map.emplace(kEntityNameMapKey, *rp_name_);
if (rp_icon_url_)
rp_map[cbor::CBORValue("icon")] = cbor::CBORValue(rp_icon_url_->spec());
rp_map.emplace(kIconUrlMapKey, rp_icon_url_->spec());
return cbor::CBORValue(std::move(rp_map));
}
......
......@@ -21,6 +21,9 @@ namespace device {
// and optional relying party display image url.
class COMPONENT_EXPORT(DEVICE_FIDO) PublicKeyCredentialRpEntity {
public:
static base::Optional<PublicKeyCredentialRpEntity> CreateFromCBORValue(
const cbor::CBORValue& cbor);
explicit PublicKeyCredentialRpEntity(std::string rp_id);
PublicKeyCredentialRpEntity(const PublicKeyCredentialRpEntity& other);
PublicKeyCredentialRpEntity(PublicKeyCredentialRpEntity&& other);
......
......@@ -6,17 +6,9 @@
#include <utility>
namespace device {
namespace {
#include "device/fido/fido_constants.h"
// Keys for storing user entity information in CBOR map.
constexpr char kUserIdKey[] = "id";
constexpr char kUserNameKey[] = "name";
constexpr char kUserDisplayNameKey[] = "displayName";
constexpr char kUserIconUrlKey[] = "icon";
} // namespace
namespace device {
// static
base::Optional<PublicKeyCredentialUserEntity>
......@@ -27,24 +19,24 @@ PublicKeyCredentialUserEntity::CreateFromCBORValue(
const cbor::CBORValue::MapValue& cbor_map = cbor.GetMap();
auto user_id = cbor_map.find(cbor::CBORValue(kUserIdKey));
auto user_id = cbor_map.find(cbor::CBORValue(kEntityIdMapKey));
if (user_id == cbor_map.end() || !user_id->second.is_bytestring())
return base::nullopt;
PublicKeyCredentialUserEntity user(user_id->second.GetBytestring());
auto user_name = cbor_map.find(cbor::CBORValue(kUserNameKey));
auto user_name = cbor_map.find(cbor::CBORValue(kEntityNameMapKey));
if (user_name != cbor_map.end() && user_name->second.is_string()) {
user.SetUserName(user_name->second.GetString());
}
auto user_display_name = cbor_map.find(cbor::CBORValue(kUserDisplayNameKey));
auto user_display_name = cbor_map.find(cbor::CBORValue(kDisplayNameMapKey));
if (user_display_name != cbor_map.end() &&
user_display_name->second.is_string()) {
user.SetDisplayName(user_display_name->second.GetString());
}
auto user_icon_url = cbor_map.find(cbor::CBORValue(kUserIconUrlKey));
auto user_icon_url = cbor_map.find(cbor::CBORValue(kIconUrlMapKey));
if (user_icon_url != cbor_map.end() && user_icon_url->second.is_string()) {
user.SetIconUrl(GURL(user_icon_url->second.GetString()));
}
......@@ -72,15 +64,13 @@ PublicKeyCredentialUserEntity::~PublicKeyCredentialUserEntity() = default;
cbor::CBORValue PublicKeyCredentialUserEntity::ConvertToCBOR() const {
cbor::CBORValue::MapValue user_map;
user_map[cbor::CBORValue(kUserIdKey)] = cbor::CBORValue(user_id_);
user_map.emplace(kEntityIdMapKey, user_id_);
if (user_name_)
user_map[cbor::CBORValue(kUserNameKey)] = cbor::CBORValue(*user_name_);
user_map.emplace(kEntityNameMapKey, *user_name_);
if (user_icon_url_)
user_map[cbor::CBORValue(kUserIconUrlKey)] =
cbor::CBORValue(user_icon_url_->spec());
user_map.emplace(kIconUrlMapKey, user_icon_url_->spec());
if (user_display_name_) {
user_map[cbor::CBORValue(kUserDisplayNameKey)] =
cbor::CBORValue(*user_display_name_);
user_map.emplace(kDisplayNameMapKey, *user_display_name_);
}
return cbor::CBORValue(std::move(user_map));
}
......
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