1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "content/browser/webauth/authenticator_mojom_traits.h"
6 
7 #include <vector>
8 
9 #include "base/optional.h"
10 #include "device/fido/authenticator_selection_criteria.h"
11 #include "device/fido/cable/cable_discovery_data.h"
12 #include "device/fido/fido_constants.h"
13 #include "device/fido/fido_transport_protocol.h"
14 #include "device/fido/public_key_credential_descriptor.h"
15 #include "device/fido/public_key_credential_params.h"
16 #include "device/fido/public_key_credential_rp_entity.h"
17 #include "device/fido/public_key_credential_user_entity.h"
18 #include "mojo/public/cpp/test_support/test_utils.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "third_party/blink/public/mojom/webauthn/authenticator.mojom.h"
21 #include "url/gurl.h"
22 #include "url/mojom/url_gurl_mojom_traits.h"
23 
24 namespace mojo {
25 
26 using device::AuthenticatorAttachment;
27 using device::AuthenticatorSelectionCriteria;
28 using device::CableDiscoveryData;
29 using device::CableEidArray;
30 using device::CableSessionPreKeyArray;
31 using device::CoseAlgorithmIdentifier;
32 using device::CredentialType;
33 using device::FidoTransportProtocol;
34 using device::PublicKeyCredentialDescriptor;
35 using device::PublicKeyCredentialParams;
36 using device::PublicKeyCredentialRpEntity;
37 using device::PublicKeyCredentialUserEntity;
38 using device::UserVerificationRequirement;
39 
40 const std::vector<uint8_t> kDescriptorId = {'d', 'e', 's', 'c'};
41 constexpr char kRpId[] = "google.com";
42 constexpr char kRpName[] = "Google";
43 constexpr char kTestURL[] = "https://gstatic.com/fakeurl2.png";
44 constexpr CableEidArray kClientEid = {{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
45                                        0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13,
46                                        0x14, 0x15}};
47 constexpr CableEidArray kAuthenticatorEid = {
48     {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
49      0x01, 0x01, 0x01, 0x01}};
50 constexpr CableSessionPreKeyArray kSessionPreKey = {
51     {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
52      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
53      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
54 
55 namespace {
56 
57 template <typename MojomType, typename UserType>
AssertSerializeAndDeserializeSucceeds(std::vector<UserType> test_cases)58 void AssertSerializeAndDeserializeSucceeds(std::vector<UserType> test_cases) {
59   for (auto original : test_cases) {
60     UserType copied;
61     EXPECT_TRUE(
62         mojo::test::SerializeAndDeserialize<MojomType>(&original, &copied));
63     EXPECT_EQ(original, copied);
64   }
65 }
66 
67 }  // namespace
68 
69 // Verify serialization and deserialization of PublicKeyCredentialParams.
TEST(AuthenticatorMojomTraitsTest,SerializeCredentialParams)70 TEST(AuthenticatorMojomTraitsTest, SerializeCredentialParams) {
71   std::vector<PublicKeyCredentialParams::CredentialInfo> success_cases = {
72       {CredentialType::kPublicKey,
73        base::strict_cast<int>(CoseAlgorithmIdentifier::kCoseEs256)}};
74 
75   AssertSerializeAndDeserializeSucceeds<
76       blink::mojom::PublicKeyCredentialParameters,
77       PublicKeyCredentialParams::CredentialInfo>(success_cases);
78 }
79 
80 // Verify serialization and deserialization of PublicKeyCredentialDescriptor.
TEST(AuthenticatorMojomTraitsTest,SerializeCredentialDescriptors)81 TEST(AuthenticatorMojomTraitsTest, SerializeCredentialDescriptors) {
82   std::vector<PublicKeyCredentialDescriptor> success_cases = {
83       PublicKeyCredentialDescriptor(CredentialType::kPublicKey, kDescriptorId),
84       PublicKeyCredentialDescriptor(CredentialType::kPublicKey, kDescriptorId),
85       PublicKeyCredentialDescriptor(CredentialType::kPublicKey, kDescriptorId)};
86   success_cases[1].GetTransportsForTesting().emplace(
87       FidoTransportProtocol::kInternal);
88   success_cases[2].GetTransportsForTesting().emplace(
89       FidoTransportProtocol::kInternal);
90   success_cases[2].GetTransportsForTesting().emplace(
91       FidoTransportProtocol::kUsbHumanInterfaceDevice);
92   success_cases[2].GetTransportsForTesting().emplace(
93       FidoTransportProtocol::kNearFieldCommunication);
94   success_cases[2].GetTransportsForTesting().emplace(
95       FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy);
96   success_cases[2].GetTransportsForTesting().emplace(
97       FidoTransportProtocol::kBluetoothLowEnergy);
98 
99   AssertSerializeAndDeserializeSucceeds<
100       blink::mojom::PublicKeyCredentialDescriptor,
101       PublicKeyCredentialDescriptor>(success_cases);
102 }
103 
104 // Verify serialization and deserialization of AuthenticatorSelectionCriteria.
TEST(AuthenticatorMojomTraitsTest,SerializeAuthenticatorSelectionCriteria)105 TEST(AuthenticatorMojomTraitsTest, SerializeAuthenticatorSelectionCriteria) {
106   std::vector<AuthenticatorSelectionCriteria> success_cases = {
107       AuthenticatorSelectionCriteria(AuthenticatorAttachment::kAny, true,
108                                      UserVerificationRequirement::kRequired),
109       AuthenticatorSelectionCriteria(AuthenticatorAttachment::kPlatform, false,
110                                      UserVerificationRequirement::kPreferred),
111       AuthenticatorSelectionCriteria(
112           AuthenticatorAttachment::kCrossPlatform, true,
113           UserVerificationRequirement::kDiscouraged)};
114 
115   AssertSerializeAndDeserializeSucceeds<
116       blink::mojom::AuthenticatorSelectionCriteria,
117       AuthenticatorSelectionCriteria>(success_cases);
118 }
119 
120 // Verify serialization and deserialization of PublicKeyCredentialRpEntity.
TEST(AuthenticatorMojomTraitsTest,SerializePublicKeyCredentialRpEntity)121 TEST(AuthenticatorMojomTraitsTest, SerializePublicKeyCredentialRpEntity) {
122   std::vector<PublicKeyCredentialRpEntity> success_cases = {
123       PublicKeyCredentialRpEntity(std::string(kRpId)),
124       PublicKeyCredentialRpEntity(std::string(kRpId))};
125   // TODO(kenrb): There is a mismatch between the types, where
126   // device::PublicKeyCredentialRpEntity can have base::nullopt for
127   // the name but the mapped mojom type is not optional. This should
128   // be corrected at some point. We can't currently test base::nullopt
129   // because it won't serialize.
130   success_cases[0].name = std::string(kRpName);
131   success_cases[0].icon_url = base::nullopt;
132   success_cases[1].name = std::string(kRpName);
133   success_cases[1].icon_url = GURL(kTestURL);
134 
135   AssertSerializeAndDeserializeSucceeds<
136       blink::mojom::PublicKeyCredentialRpEntity, PublicKeyCredentialRpEntity>(
137       success_cases);
138 }
139 
140 // Verify serialization and deserialization of PublicKeyCredentialUserEntity.
TEST(AuthenticatorMojomTraitsTest,SerializePublicKeyCredentialUserEntity)141 TEST(AuthenticatorMojomTraitsTest, SerializePublicKeyCredentialUserEntity) {
142   std::vector<PublicKeyCredentialUserEntity> success_cases = {
143       PublicKeyCredentialUserEntity(kDescriptorId),
144       PublicKeyCredentialUserEntity(kDescriptorId)};
145   // TODO(kenrb): |name| and |display_name| have the same issue as
146   // PublicKeyCredentialRpEntity::name above.
147   success_cases[0].name = std::string(kRpName);
148   success_cases[0].display_name = std::string(kRpName);
149   success_cases[0].icon_url = base::nullopt;
150   success_cases[1].name = std::string(kRpName);
151   success_cases[1].display_name = std::string(kRpName);
152   success_cases[1].icon_url = GURL(kTestURL);
153 
154   AssertSerializeAndDeserializeSucceeds<
155       blink::mojom::PublicKeyCredentialUserEntity,
156       PublicKeyCredentialUserEntity>(success_cases);
157 }
158 
159 // Verify serialization and deserialization of CableDiscoveryData.
TEST(AuthenticatorMojomTraitsTest,SerializeCableDiscoveryData)160 TEST(AuthenticatorMojomTraitsTest, SerializeCableDiscoveryData) {
161   std::vector<CableDiscoveryData> success_cases = {
162       CableDiscoveryData(CableDiscoveryData::Version::V1, kClientEid,
163                          kAuthenticatorEid, kSessionPreKey)};
164 
165   AssertSerializeAndDeserializeSucceeds<blink::mojom::CableAuthentication,
166                                         CableDiscoveryData>(success_cases);
167 }
168 
169 }  // namespace mojo
170