1 // Copyright 2020 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 "chrome/browser/nearby_sharing/certificates/nearby_share_decrypted_public_certificate.h"
6 
7 #include "base/optional.h"
8 #include "chrome/browser/nearby_sharing/certificates/constants.h"
9 #include "chrome/browser/nearby_sharing/certificates/test_util.h"
10 #include "chrome/browser/nearby_sharing/proto/rpc_resources.pb.h"
11 #include "chrome/browser/ui/webui/nearby_share/public/mojom/nearby_share_settings.mojom.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 
14 namespace {
15 
16 // The for_selected_contacts field of a public certificate proto is irrelevant
17 // for remote device certificates. Even if set, it is meaningless. It only has
18 // meaning for private certificates converted to public certificates and
19 // uploaded to the Nearby server.
20 const nearby_share::mojom::Visibility kTestPublicCertificateVisibility =
21     nearby_share::mojom::Visibility::kNoOne;
22 
23 }  // namespace
24 
TEST(NearbyShareDecryptedPublicCertificateTest,Decrypt)25 TEST(NearbyShareDecryptedPublicCertificateTest, Decrypt) {
26   nearbyshare::proto::PublicCertificate proto_cert =
27       GetNearbyShareTestPublicCertificate(kTestPublicCertificateVisibility);
28 
29   base::Optional<NearbyShareDecryptedPublicCertificate> cert =
30       NearbyShareDecryptedPublicCertificate::DecryptPublicCertificate(
31           proto_cert, GetNearbyShareTestEncryptedMetadataKey());
32   EXPECT_TRUE(cert);
33   EXPECT_EQ(base::Time::FromJavaTime(proto_cert.start_time().seconds() * 1000),
34             cert->not_before());
35   EXPECT_EQ(base::Time::FromJavaTime(proto_cert.end_time().seconds() * 1000),
36             cert->not_after());
37   EXPECT_EQ(std::vector<uint8_t>(proto_cert.secret_id().begin(),
38                                  proto_cert.secret_id().end()),
39             cert->id());
40   EXPECT_EQ(GetNearbyShareTestMetadata().SerializeAsString(),
41             cert->unencrypted_metadata().SerializeAsString());
42 }
43 
TEST(NearbyShareDecryptedPublicCertificateTest,Decrypt_IncorrectKeyFailure)44 TEST(NearbyShareDecryptedPublicCertificateTest, Decrypt_IncorrectKeyFailure) {
45   // Input incorrect metadata encryption key.
46   EXPECT_FALSE(NearbyShareDecryptedPublicCertificate::DecryptPublicCertificate(
47       GetNearbyShareTestPublicCertificate(kTestPublicCertificateVisibility),
48       NearbyShareEncryptedMetadataKey(
49           std::vector<uint8_t>(kNearbyShareNumBytesMetadataEncryptionKeySalt,
50                                0x00),
51           std::vector<uint8_t>(kNearbyShareNumBytesMetadataEncryptionKey,
52                                0x00))));
53 }
54 
TEST(NearbyShareDecryptedPublicCertificateTest,Decrypt_MetadataDecryptionFailure)55 TEST(NearbyShareDecryptedPublicCertificateTest,
56      Decrypt_MetadataDecryptionFailure) {
57   // Use metadata that cannot be decrypted with the given key.
58   nearbyshare::proto::PublicCertificate proto_cert =
59       GetNearbyShareTestPublicCertificate(kTestPublicCertificateVisibility);
60   proto_cert.set_encrypted_metadata_bytes("invalid metadata");
61   EXPECT_FALSE(NearbyShareDecryptedPublicCertificate::DecryptPublicCertificate(
62       proto_cert, GetNearbyShareTestEncryptedMetadataKey()));
63 }
64 
TEST(NearbyShareDecryptedPublicCertificateTest,Decrypt_InvalidDataFailure)65 TEST(NearbyShareDecryptedPublicCertificateTest, Decrypt_InvalidDataFailure) {
66   // Do not accept the input PublicCertificate because the validity period does
67   // not make sense.
68   nearbyshare::proto::PublicCertificate proto_cert =
69       GetNearbyShareTestPublicCertificate(kTestPublicCertificateVisibility);
70   proto_cert.mutable_end_time()->set_seconds(proto_cert.start_time().seconds() -
71                                              1);
72   EXPECT_FALSE(NearbyShareDecryptedPublicCertificate::DecryptPublicCertificate(
73       proto_cert, GetNearbyShareTestEncryptedMetadataKey()));
74 }
75 
TEST(NearbyShareDecryptedPublicCertificateTest,Verify)76 TEST(NearbyShareDecryptedPublicCertificateTest, Verify) {
77   base::Optional<NearbyShareDecryptedPublicCertificate> cert =
78       NearbyShareDecryptedPublicCertificate::DecryptPublicCertificate(
79           GetNearbyShareTestPublicCertificate(kTestPublicCertificateVisibility),
80           GetNearbyShareTestEncryptedMetadataKey());
81   EXPECT_TRUE(cert->VerifySignature(GetNearbyShareTestPayloadToSign(),
82                                     GetNearbyShareTestSampleSignature()));
83 }
84 
TEST(NearbyShareDecryptedPublicCertificateTest,Verify_InitFailure)85 TEST(NearbyShareDecryptedPublicCertificateTest, Verify_InitFailure) {
86   // Public key has invalid SubjectPublicKeyInfo format.
87   nearbyshare::proto::PublicCertificate proto_cert =
88       GetNearbyShareTestPublicCertificate(kTestPublicCertificateVisibility);
89   proto_cert.set_public_key("invalid public key");
90 
91   base::Optional<NearbyShareDecryptedPublicCertificate> cert =
92       NearbyShareDecryptedPublicCertificate::DecryptPublicCertificate(
93           proto_cert, GetNearbyShareTestEncryptedMetadataKey());
94   ASSERT_TRUE(cert);
95   EXPECT_FALSE(cert->VerifySignature(GetNearbyShareTestPayloadToSign(),
96                                      GetNearbyShareTestSampleSignature()));
97 }
98 
TEST(NearbyShareDecryptedPublicCertificateTest,Verify_WrongSignature)99 TEST(NearbyShareDecryptedPublicCertificateTest, Verify_WrongSignature) {
100   base::Optional<NearbyShareDecryptedPublicCertificate> cert =
101       NearbyShareDecryptedPublicCertificate::DecryptPublicCertificate(
102           GetNearbyShareTestPublicCertificate(kTestPublicCertificateVisibility),
103           GetNearbyShareTestEncryptedMetadataKey());
104   EXPECT_FALSE(
105       cert->VerifySignature(GetNearbyShareTestPayloadToSign(),
106                             /*signature=*/base::span<const uint8_t>()));
107 }
108 
TEST(NearbyShareDecryptedPublicCertificateTest,HashAuthenticationToken)109 TEST(NearbyShareDecryptedPublicCertificateTest, HashAuthenticationToken) {
110   base::Optional<NearbyShareDecryptedPublicCertificate> cert =
111       NearbyShareDecryptedPublicCertificate::DecryptPublicCertificate(
112           GetNearbyShareTestPublicCertificate(kTestPublicCertificateVisibility),
113           GetNearbyShareTestEncryptedMetadataKey());
114   EXPECT_EQ(GetNearbyShareTestPayloadHashUsingSecretKey(),
115             cert->HashAuthenticationToken(GetNearbyShareTestPayloadToSign()));
116 }
117