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::ResidentKeyRequirement;
39 using device::UserVerificationRequirement;
40 
41 const std::vector<uint8_t> kDescriptorId = {'d', 'e', 's', 'c'};
42 constexpr char kRpId[] = "google.com";
43 constexpr char kRpName[] = "Google";
44 constexpr char kTestURL[] = "https://gstatic.com/fakeurl2.png";
45 constexpr CableEidArray kClientEid = {{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
46                                        0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13,
47                                        0x14, 0x15}};
48 constexpr CableEidArray kAuthenticatorEid = {
49     {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
50      0x01, 0x01, 0x01, 0x01}};
51 constexpr CableSessionPreKeyArray kSessionPreKey = {
52     {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
53      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
54      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
55 
56 namespace {
57 
58 template <typename MojomType, typename UserType>
AssertSerializeAndDeserializeSucceeds(std::vector<UserType> test_cases)59 void AssertSerializeAndDeserializeSucceeds(std::vector<UserType> test_cases) {
60   for (auto original : test_cases) {
61     UserType copied;
62     EXPECT_TRUE(
63         mojo::test::SerializeAndDeserialize<MojomType>(&original, &copied));
64     EXPECT_EQ(original, copied);
65   }
66 }
67 
68 }  // namespace
69 
70 // Verify serialization and deserialization of PublicKeyCredentialParams.
TEST(AuthenticatorMojomTraitsTest,SerializeCredentialParams)71 TEST(AuthenticatorMojomTraitsTest, SerializeCredentialParams) {
72   std::vector<PublicKeyCredentialParams::CredentialInfo> success_cases = {
73       {CredentialType::kPublicKey,
74        base::strict_cast<int>(CoseAlgorithmIdentifier::kEs256)}};
75 
76   AssertSerializeAndDeserializeSucceeds<
77       blink::mojom::PublicKeyCredentialParameters,
78       PublicKeyCredentialParams::CredentialInfo>(success_cases);
79 }
80 
81 // Verify serialization and deserialization of PublicKeyCredentialDescriptor.
TEST(AuthenticatorMojomTraitsTest,SerializeCredentialDescriptors)82 TEST(AuthenticatorMojomTraitsTest, SerializeCredentialDescriptors) {
83   std::vector<PublicKeyCredentialDescriptor> success_cases = {
84       PublicKeyCredentialDescriptor(CredentialType::kPublicKey, kDescriptorId),
85       PublicKeyCredentialDescriptor(CredentialType::kPublicKey, kDescriptorId),
86       PublicKeyCredentialDescriptor(CredentialType::kPublicKey, kDescriptorId)};
87   success_cases[1].GetTransportsForTesting().emplace(
88       FidoTransportProtocol::kInternal);
89   success_cases[2].GetTransportsForTesting().emplace(
90       FidoTransportProtocol::kInternal);
91   success_cases[2].GetTransportsForTesting().emplace(
92       FidoTransportProtocol::kUsbHumanInterfaceDevice);
93   success_cases[2].GetTransportsForTesting().emplace(
94       FidoTransportProtocol::kNearFieldCommunication);
95   success_cases[2].GetTransportsForTesting().emplace(
96       FidoTransportProtocol::kCloudAssistedBluetoothLowEnergy);
97   success_cases[2].GetTransportsForTesting().emplace(
98       FidoTransportProtocol::kBluetoothLowEnergy);
99 
100   AssertSerializeAndDeserializeSucceeds<
101       blink::mojom::PublicKeyCredentialDescriptor,
102       PublicKeyCredentialDescriptor>(success_cases);
103 }
104 
105 // Verify serialization and deserialization of AuthenticatorSelectionCriteria.
TEST(AuthenticatorMojomTraitsTest,SerializeAuthenticatorSelectionCriteria)106 TEST(AuthenticatorMojomTraitsTest, SerializeAuthenticatorSelectionCriteria) {
107   std::vector<AuthenticatorSelectionCriteria> success_cases = {
108       AuthenticatorSelectionCriteria(AuthenticatorAttachment::kAny,
109                                      ResidentKeyRequirement::kRequired,
110                                      UserVerificationRequirement::kRequired),
111       AuthenticatorSelectionCriteria(AuthenticatorAttachment::kPlatform,
112                                      ResidentKeyRequirement::kPreferred,
113                                      UserVerificationRequirement::kPreferred),
114       AuthenticatorSelectionCriteria(AuthenticatorAttachment::kPlatform,
115                                      ResidentKeyRequirement::kDiscouraged,
116                                      UserVerificationRequirement::kPreferred),
117       AuthenticatorSelectionCriteria(
118           AuthenticatorAttachment::kCrossPlatform,
119           ResidentKeyRequirement::kRequired,
120           UserVerificationRequirement::kDiscouraged)};
121 
122   AssertSerializeAndDeserializeSucceeds<
123       blink::mojom::AuthenticatorSelectionCriteria,
124       AuthenticatorSelectionCriteria>(success_cases);
125 }
126 
127 // Verify serialization and deserialization of PublicKeyCredentialRpEntity.
TEST(AuthenticatorMojomTraitsTest,SerializePublicKeyCredentialRpEntity)128 TEST(AuthenticatorMojomTraitsTest, SerializePublicKeyCredentialRpEntity) {
129   std::vector<PublicKeyCredentialRpEntity> success_cases = {
130       PublicKeyCredentialRpEntity(std::string(kRpId)),
131       PublicKeyCredentialRpEntity(std::string(kRpId))};
132   // TODO(kenrb): There is a mismatch between the types, where
133   // device::PublicKeyCredentialRpEntity can have base::nullopt for
134   // the name but the mapped mojom type is not optional. This should
135   // be corrected at some point. We can't currently test base::nullopt
136   // because it won't serialize.
137   success_cases[0].name = std::string(kRpName);
138   success_cases[0].icon_url = base::nullopt;
139   success_cases[1].name = std::string(kRpName);
140   success_cases[1].icon_url = GURL(kTestURL);
141 
142   AssertSerializeAndDeserializeSucceeds<
143       blink::mojom::PublicKeyCredentialRpEntity, PublicKeyCredentialRpEntity>(
144       success_cases);
145 }
146 
147 // Verify serialization and deserialization of PublicKeyCredentialUserEntity.
TEST(AuthenticatorMojomTraitsTest,SerializePublicKeyCredentialUserEntity)148 TEST(AuthenticatorMojomTraitsTest, SerializePublicKeyCredentialUserEntity) {
149   std::vector<PublicKeyCredentialUserEntity> success_cases = {
150       PublicKeyCredentialUserEntity(kDescriptorId),
151       PublicKeyCredentialUserEntity(kDescriptorId)};
152   // TODO(kenrb): |name| and |display_name| have the same issue as
153   // PublicKeyCredentialRpEntity::name above.
154   success_cases[0].name = std::string(kRpName);
155   success_cases[0].display_name = std::string(kRpName);
156   success_cases[0].icon_url = base::nullopt;
157   success_cases[1].name = std::string(kRpName);
158   success_cases[1].display_name = std::string(kRpName);
159   success_cases[1].icon_url = GURL(kTestURL);
160 
161   AssertSerializeAndDeserializeSucceeds<
162       blink::mojom::PublicKeyCredentialUserEntity,
163       PublicKeyCredentialUserEntity>(success_cases);
164 }
165 
166 // Verify serialization and deserialization of CableDiscoveryData.
TEST(AuthenticatorMojomTraitsTest,SerializeCableDiscoveryData)167 TEST(AuthenticatorMojomTraitsTest, SerializeCableDiscoveryData) {
168   std::vector<CableDiscoveryData> success_cases = {
169       CableDiscoveryData(CableDiscoveryData::Version::V1, kClientEid,
170                          kAuthenticatorEid, kSessionPreKey)};
171 
172   AssertSerializeAndDeserializeSucceeds<blink::mojom::CableAuthentication,
173                                         CableDiscoveryData>(success_cases);
174 }
175 
176 }  // namespace mojo
177