1 // Copyright 2023 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <algorithm>
16 #include <array>
17 #include <cstdint>
18 #include <span>
19 #include <string>
20
21 #include "absl/status/status.h"
22 #include "gtest/gtest.h"
23 #include "nearby_protocol.h"
24 #include "np_cpp_ffi_types.h"
25 #include "np_cpp_test.h"
26 #include "shared_test_util.h"
27
28 // NOLINTBEGIN(readability-magic-numbers)
TEST_F(NpCppTest,V0PrivateIdentityDeserializationSimpleCase)29 TEST_F(NpCppTest, V0PrivateIdentityDeserializationSimpleCase) {
30 nearby_protocol::CredentialSlab slab;
31 const std::span<uint8_t> metadata_span(V0AdvEncryptedMetadata);
32 const nearby_protocol::MatchedCredentialData match_data(123, metadata_span);
33 std::array<uint8_t, 32> key_seed = {};
34 std::fill_n(key_seed.begin(), 32, 0x11);
35 const nearby_protocol::V0MatchableCredential v0_cred(
36 key_seed, V0AdvLegacyIdentityTokenHmac, match_data);
37 slab.AddV0Credential(v0_cred);
38 nearby_protocol::CredentialBook book(slab);
39
40 auto deserialize_result =
41 nearby_protocol::Deserializer::DeserializeAdvertisement(
42 V0AdvEncryptedPayload, book);
43 ASSERT_EQ(deserialize_result.GetKind(),
44 nearby_protocol::DeserializeAdvertisementResultKind::V0);
45
46 auto v0_adv = deserialize_result.IntoV0();
47 auto kind = v0_adv.GetKind();
48 ASSERT_EQ(kind, nearby_protocol::DeserializedV0AdvertisementKind::Legible);
49
50 auto legible_adv = v0_adv.IntoLegible();
51 auto identity_kind = legible_adv.GetIdentityKind();
52 ASSERT_EQ(identity_kind,
53 nearby_protocol::DeserializedV0IdentityKind::Decrypted);
54 ASSERT_EQ(legible_adv.GetNumberOfDataElements(), 1);
55
56 auto payload = legible_adv.IntoPayload();
57 auto de = payload.TryGetDataElement(0);
58 ASSERT_TRUE(de.ok());
59
60 auto metadata = payload.TryDecryptMetadata();
61 ASSERT_TRUE(metadata.ok());
62 ASSERT_EQ(ExpectedV0DecryptedMetadata,
63 std::string(metadata->begin(), metadata->end()));
64
65 auto identity_details = payload.TryGetIdentityDetails();
66 ASSERT_TRUE(identity_details.ok());
67 ASSERT_EQ(identity_details->cred_id, 123u);
68
69 auto de_type = de->GetKind();
70 ASSERT_EQ(de_type, nearby_protocol::V0DataElementKind::TxPower);
71
72 auto tx_power_de = de->AsTxPower();
73 ASSERT_EQ(tx_power_de.GetAsI8(), 3);
74 }
75
CreateEmptyCredBook()76 nearby_protocol::CredentialBook CreateEmptyCredBook() {
77 nearby_protocol::CredentialSlab slab;
78 nearby_protocol::CredentialBook book(slab);
79 return book;
80 }
81
TEST_F(NpCppTest,V0PrivateIdentityEmptyBook)82 TEST_F(NpCppTest, V0PrivateIdentityEmptyBook) {
83 auto book = CreateEmptyCredBook();
84 auto deserialize_result =
85 nearby_protocol::Deserializer::DeserializeAdvertisement(
86 V0AdvEncryptedPayload, book);
87 ASSERT_EQ(deserialize_result.GetKind(),
88 nearby_protocol::DeserializeAdvertisementResultKind::V0);
89
90 auto v0_adv = deserialize_result.IntoV0();
91 ASSERT_EQ(
92 v0_adv.GetKind(),
93 nearby_protocol::DeserializedV0AdvertisementKind::NoMatchingCredentials);
94
95 // Should not be able to actually access contents
96 ASSERT_DEATH([[maybe_unused]] auto failure = v0_adv.IntoLegible(), "");
97 }
98
TEST_F(NpCppTest,V0PrivateIdentityNoMatchingCreds)99 TEST_F(NpCppTest, V0PrivateIdentityNoMatchingCreds) {
100 nearby_protocol::CredentialSlab slab;
101 uint8_t metadata[] = {0};
102 const std::span<uint8_t> metadata_span(metadata);
103 const nearby_protocol::MatchedCredentialData match_data(123, metadata_span);
104 // A randomly picked key seed, does NOT match what was used for the canned adv
105 std::array<uint8_t, 32> key_seed = {};
106 std::fill_n(key_seed.begin(), 31, 0x11);
107 const nearby_protocol::V0MatchableCredential v0_cred(
108 key_seed, V0AdvLegacyIdentityTokenHmac, match_data);
109 slab.AddV0Credential(v0_cred);
110
111 nearby_protocol::CredentialBook book(slab);
112
113 auto deserialize_result =
114 nearby_protocol::Deserializer::DeserializeAdvertisement(
115 V0AdvEncryptedPayload, book);
116 ASSERT_EQ(deserialize_result.GetKind(),
117 nearby_protocol::DeserializeAdvertisementResultKind::V0);
118
119 auto v0_adv = deserialize_result.IntoV0();
120 ASSERT_EQ(
121 v0_adv.GetKind(),
122 nearby_protocol::DeserializedV0AdvertisementKind::NoMatchingCredentials);
123
124 // Should not be able to actually access contents
125 ASSERT_DEATH([[maybe_unused]] auto failure = v0_adv.IntoLegible(), "");
126 }
127
128 // Make sure the correct credential is matched out of multiple provided
TEST_F(NpCppTest,V0PrivateIdentityMultipleCredentials)129 TEST_F(NpCppTest, V0PrivateIdentityMultipleCredentials) {
130 nearby_protocol::CredentialSlab slab;
131 const std::span<uint8_t> metadata_span(V0AdvEncryptedMetadata);
132 std::array<uint8_t, 32> key_seed = {};
133 // Non matching credential
134 const nearby_protocol::MatchedCredentialData match_data(123, metadata_span);
135 std::fill_n(key_seed.begin(), 32, 0x12);
136 const nearby_protocol::V0MatchableCredential v0_cred(
137 key_seed, V0AdvLegacyIdentityTokenHmac, match_data);
138 slab.AddV0Credential(v0_cred);
139
140 // Matching credential
141 const nearby_protocol::MatchedCredentialData match_data2(456, metadata_span);
142 std::fill_n(key_seed.begin(), 32, 0x11);
143 const nearby_protocol::V0MatchableCredential v0_cred2(
144 key_seed, V0AdvLegacyIdentityTokenHmac, match_data2);
145 slab.AddV0Credential(v0_cred2);
146
147 // Non matching credential
148 const nearby_protocol::MatchedCredentialData match_data3(789, metadata_span);
149 std::fill_n(key_seed.begin(), 32, 0x13);
150 const nearby_protocol::V0MatchableCredential v0_cred3(
151 key_seed, V0AdvLegacyIdentityTokenHmac, match_data3);
152 slab.AddV0Credential(v0_cred3);
153
154 nearby_protocol::CredentialBook book(slab);
155 auto legible_adv = nearby_protocol::Deserializer::DeserializeAdvertisement(
156 V0AdvEncryptedPayload, book)
157 .IntoV0()
158 .IntoLegible();
159 ASSERT_EQ(legible_adv.GetIdentityKind(),
160 nearby_protocol::DeserializedV0IdentityKind::Decrypted);
161 ASSERT_EQ(legible_adv.GetNumberOfDataElements(), 1);
162
163 auto payload = legible_adv.IntoPayload();
164 ASSERT_TRUE(payload.TryGetDataElement(0).ok());
165
166 // Make sure the correct credential matches
167 auto identity_details = payload.TryGetIdentityDetails();
168 ASSERT_TRUE(identity_details.ok());
169 ASSERT_EQ(identity_details->cred_id, 456u);
170 }
171 // NOLINTEND(readability-magic-numbers)
172