blob: f966ed2a7c1de20744da0ef810da985622371eb9 [file] [log] [blame]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/nearby_sharing/certificates/test_util.h"
#include <array>
#include <set>
#include "base/no_destructor.h"
#include "base/strings/string_view_util.h"
#include "chrome/browser/nearby_sharing/certificates/constants.h"
#include "device/bluetooth/public/cpp/bluetooth_address.h"
#include "third_party/nearby/sharing/proto/timestamp.pb.h"
namespace {
// Sample P-256 public and private keys from RFC 6979 A.2.5 in their respective
// ASN.1 formats: SubjectPublicKeyInfo (RFC 5280) and PKCS #8 PrivateKeyInfo
// (RFC 5208).
constexpr auto kTestPublicKeyBytes = std::to_array<uint8_t>(
{0x30, 0x59,
// Begin AlgorithmIdentifier: ecPublicKey, prime256v1
0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06,
0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07,
// End AlgorithmIdentifier
0x03, 0x42, 0x00, 0x04,
// Public key bytes (Ux):
0x60, 0xfe, 0xd4, 0xba, 0x25, 0x5a, 0x9d, 0x31, 0xc9, 0x61, 0xeb, 0x74,
0xc6, 0x35, 0x6d, 0x68, 0xc0, 0x49, 0xb8, 0x92, 0x3b, 0x61, 0xfa, 0x6c,
0xe6, 0x69, 0x62, 0x2e, 0x60, 0xf2, 0x9f, 0xb6,
// Public key bytes (Uy):
0x79, 0x03, 0xfe, 0x10, 0x08, 0xb8, 0xbc, 0x99, 0xa4, 0x1a, 0xe9, 0xe9,
0x56, 0x28, 0xbc, 0x64, 0xf2, 0xf1, 0xb2, 0x0c, 0x2d, 0x7e, 0x9f, 0x51,
0x77, 0xa3, 0xc2, 0x94, 0xd4, 0x46, 0x22, 0x99});
constexpr auto kTestPrivateKeyBytes = std::to_array<uint8_t>(
{0x30, 0x81, 0x87, 0x02, 0x01, 0x00,
// Begin AlgorithmIdentifier: ecPublicKey, prime256v1
0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06,
0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07,
// End AlgorithmIdentifier
0x04, 0x6d, 0x30, 0x6b, 0x02, 0x01, 0x01, 0x04, 0x20,
// Begin private key bytes
0xc9, 0xaf, 0xa9, 0xd8, 0x45, 0xba, 0x75, 0x16, 0x6b, 0x5c, 0x21, 0x57,
0x67, 0xb1, 0xd6, 0x93, 0x4e, 0x50, 0xc3, 0xdb, 0x36, 0xe8, 0x9b, 0x12,
0x7b, 0x8a, 0x62, 0x2b, 0x12, 0x0f, 0x67, 0x21,
// End private key bytes
0xa1, 0x44, 0x03, 0x42, 0x00, 0x04,
// Public key:
0x60, 0xfe, 0xd4, 0xba, 0x25, 0x5a, 0x9d, 0x31, 0xc9, 0x61, 0xeb, 0x74,
0xc6, 0x35, 0x6d, 0x68, 0xc0, 0x49, 0xb8, 0x92, 0x3b, 0x61, 0xfa, 0x6c,
0xe6, 0x69, 0x62, 0x2e, 0x60, 0xf2, 0x9f, 0xb6, 0x79, 0x03, 0xfe, 0x10,
0x08, 0xb8, 0xbc, 0x99, 0xa4, 0x1a, 0xe9, 0xe9, 0x56, 0x28, 0xbc, 0x64,
0xf2, 0xf1, 0xb2, 0x0c, 0x2d, 0x7e, 0x9f, 0x51, 0x77, 0xa3, 0xc2, 0x94,
0xd4, 0x46, 0x22, 0x99});
const uint8_t kTestMetadataEncryptionKeyTag[] = {
0x51, 0x9b, 0x16, 0xd8, 0x91, 0xb4, 0x0d, 0x81, 0x11, 0x21, 0xe3,
0x70, 0x42, 0x80, 0x8f, 0x87, 0x23, 0x6a, 0x84, 0x9b, 0xcd, 0xac,
0xbc, 0xe3, 0x54, 0xd7, 0xff, 0x53, 0xdf, 0x5d, 0x8a, 0xda};
// TODO fix
const uint8_t kTestEncryptedMetadata[] = {
0x4d, 0x59, 0x5d, 0xb6, 0xac, 0x70, 0x00, 0x8f, 0x32, 0x9d, 0x0d,
0xcf, 0xc3, 0x8b, 0x01, 0x19, 0x1d, 0xad, 0x2e, 0xb4, 0x62, 0xec,
0xf3, 0xa5, 0xe4, 0x89, 0x51, 0x37, 0x0d, 0x78, 0xad, 0x9d, 0x2e,
0xe5, 0x99, 0xd5, 0xf7, 0x1d, 0x71, 0x47, 0xef, 0x33, 0xae, 0x4f,
0xf0, 0xd0, 0x4b, 0xcf, 0x1e, 0xaf, 0x06, 0xfa, 0x08, 0x79, 0x9b,
0x76, 0x44, 0x13, 0xad, 0x08, 0x68, 0xef, 0x0a, 0xc5, 0x13, 0xd0,
0xe8, 0xaa, 0xbe, 0x52, 0x28, 0xb1, 0xb6, 0xc4, 0x20};
// Plaintext "sample" (from RFC 6979 A.2.5).
const uint8_t kTestPayloadToSign[] = {0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65};
const int64_t kTestNotBeforeMillis = 1881702000000;
const int64_t kTestValidityOffsetMillis = 1800000; // 30 minutes
} // namespace
// Do not change. Values align with kTestEncryptedMetadata.
const char kTestDeviceName[] = "device_name";
const char kTestMetadataFullName[] = "full_name";
const char kTestMetadataIconUrl[] = "icon_url";
const char kTestUnparsedBluetoothMacAddress[] = "4E:65:61:72:62:79";
const char kTestAccountName[] = "test@google.com";
const std::array<uint8_t, kNearbyShareNumBytesSecretKey>&
GetNearbyShareTestSecretKey() {
static constexpr auto kTestSecretKey = std::to_array<uint8_t>(
{0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae,
0xf0, 0x85, 0x7d, 0x77, 0x81, 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61,
0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4});
return kTestSecretKey;
}
const std::array<uint8_t, kNearbyShareNumBytesCertificateId>&
GetNearbyShareTestCertificateId() {
static constexpr auto kTestCertificateId = std::to_array<uint8_t>(
{0xb9, 0x3c, 0x72, 0xb7, 0x4b, 0xc8, 0x48, 0x7d, 0x29, 0x82, 0x70,
0x05, 0xf8, 0x0d, 0x63, 0x59, 0x18, 0xf9, 0x1b, 0xc2, 0x2b, 0x14,
0xd7, 0xed, 0x05, 0x71, 0x4d, 0x58, 0xf9, 0x67, 0x02, 0xdd});
return kTestCertificateId;
}
const std::array<uint8_t, kNearbyShareNumBytesMetadataEncryptionKey>&
GetNearbyShareTestMetadataEncryptionKey() {
static constexpr std::array<uint8_t,
kNearbyShareNumBytesMetadataEncryptionKey>
kMetadataEncryptionKey = {0x60, 0x1e, 0xc3, 0x13, 0x77, 0x57, 0x89,
0xa5, 0xb7, 0xa7, 0xf5, 0x04, 0xbb, 0xf3};
return kMetadataEncryptionKey;
}
const std::vector<uint8_t>& GetNearbyShareTestMetadataEncryptionKeyTag() {
static const base::NoDestructor<std::vector<uint8_t>> tag(
std::begin(kTestMetadataEncryptionKeyTag),
std::end(kTestMetadataEncryptionKeyTag));
return *tag;
}
const std::array<uint8_t, kNearbyShareNumBytesMetadataEncryptionKeySalt>&
GetNearbyShareTestSalt() {
static constexpr std::array<uint8_t,
kNearbyShareNumBytesMetadataEncryptionKeySalt>
kTestSalt = {0xf0, 0xf1};
return kTestSalt;
}
const NearbyShareEncryptedMetadataKey&
GetNearbyShareTestEncryptedMetadataKey() {
static const base::NoDestructor<NearbyShareEncryptedMetadataKey>
encrypted_metadata_key(
GetNearbyShareTestSalt(),
std::to_array<uint8_t>({0x52, 0x0e, 0x7e, 0x6b, 0x8e, 0xb5, 0x40,
0xe8, 0xe2, 0xbd, 0xa0, 0xee, 0x9d, 0x7b}));
return *encrypted_metadata_key;
}
base::Time GetNearbyShareTestNotBefore() {
static const base::Time not_before =
base::Time::FromMillisecondsSinceUnixEpoch(kTestNotBeforeMillis);
return not_before;
}
base::TimeDelta GetNearbyShareTestValidityOffset() {
static const base::TimeDelta offset =
base::Milliseconds(kTestValidityOffsetMillis);
return offset;
}
const nearby::sharing::proto::EncryptedMetadata& GetNearbyShareTestMetadata() {
static const base::NoDestructor<nearby::sharing::proto::EncryptedMetadata>
metadata([] {
std::array<uint8_t, 6> bytes;
device::ParseBluetoothAddress(kTestUnparsedBluetoothMacAddress, bytes);
nearby::sharing::proto::EncryptedMetadata metadata;
metadata.set_device_name(kTestDeviceName);
metadata.set_full_name(kTestMetadataFullName);
metadata.set_icon_url(kTestMetadataIconUrl);
metadata.set_bluetooth_mac_address(bytes.data(), 6u);
metadata.set_account_name(kTestAccountName);
return metadata;
}());
return *metadata;
}
const std::vector<uint8_t>& GetNearbyShareTestEncryptedMetadata() {
static const base::NoDestructor<std::vector<uint8_t>> bytes(
std::begin(kTestEncryptedMetadata), std::end(kTestEncryptedMetadata));
return *bytes;
}
const std::vector<uint8_t>& GetNearbyShareTestPayloadToSign() {
static const base::NoDestructor<std::vector<uint8_t>> payload(
std::begin(kTestPayloadToSign), std::end(kTestPayloadToSign));
return *payload;
}
const std::array<uint8_t, kNearbyShareNumBytesRandomSignature>&
GetNearbyShareTestSampleSignature() {
// One possible signature (from RFC 6979 A.2.5).
static constexpr std::array<uint8_t, kNearbyShareNumBytesRandomSignature>
kSignature = {
0x30,
0x46, // length of remaining data
0x02,
0x21, // length of r
// begin r (note 0x00 padding since leading bit of 0xEF is 1)
0x00, 0xEF, 0xD4, 0x8B, 0x2A, 0xAC, 0xB6, 0xA8, 0xFD, 0x11, 0x40,
0xDD, 0x9C, 0xD4, 0x5E, 0x81, 0xD6, 0x9D, 0x2C, 0x87, 0x7B, 0x56,
0xAA, 0xF9, 0x91, 0xC3, 0x4D, 0x0E, 0xA8, 0x4E, 0xAF, 0x37, 0x16,
// end r
0x02,
0x21, // length of s
// begin s (note 0x00 padding since leading bit of 0xF7 is 1)
0x00, 0xF7, 0xCB, 0x1C, 0x94, 0x2D, 0x65, 0x7C, 0x41, 0xD4, 0x36,
0xC7, 0xA1, 0xB6, 0xE2, 0x9F, 0x65, 0xF3, 0xE9, 0x00, 0xDB, 0xB9,
0xAF, 0xF4, 0x06, 0x4D, 0xC4, 0xAB, 0x2F, 0x84, 0x3A, 0xCD, 0xA8
// end s
};
return kSignature;
}
const std::array<uint8_t, kNearbyShareNumBytesAuthenticationTokenHash>&
GetNearbyShareTestPayloadHashUsingSecretKey() {
// The result of HKDF of kTestPayloadToSign, using kTestSecretKey as salt. A
// trivial info parameter is used, and the output length is fixed to be
// kNearbyShareNumBytesAuthenticationTokenHash.
static constexpr std::array<uint8_t,
kNearbyShareNumBytesAuthenticationTokenHash>
kHash = {0xE2, 0xCB, 0x90, 0x58, 0xDE, 0x3A};
return kHash;
}
NearbySharePrivateCertificate GetNearbyShareTestPrivateCertificate(
nearby_share::mojom::Visibility visibility,
base::Time not_before) {
auto key =
crypto::keypair::PrivateKey::FromPrivateKeyInfo(kTestPrivateKeyBytes);
NearbySharePrivateCertificate cert(
visibility, not_before,
not_before + kNearbyShareCertificateValidityPeriod, *key,
GetNearbyShareTestSecretKey(), GetNearbyShareTestMetadataEncryptionKey(),
GetNearbyShareTestCertificateId(), GetNearbyShareTestMetadata(),
/*consumed_salts=*/{});
cert.next_salts_for_testing().push(GetNearbyShareTestSalt());
return cert;
}
nearby::sharing::proto::PublicCertificate GetNearbyShareTestPublicCertificate(
nearby_share::mojom::Visibility visibility,
base::Time not_before) {
nearby::sharing::proto::PublicCertificate cert;
cert.set_secret_id(std::string(GetNearbyShareTestCertificateId().begin(),
GetNearbyShareTestCertificateId().end()));
cert.set_secret_key(std::string(GetNearbyShareTestSecretKey().begin(),
GetNearbyShareTestSecretKey().end()));
cert.set_public_key(base::as_string_view(kTestPublicKeyBytes));
cert.mutable_start_time()->set_seconds(
(not_before - GetNearbyShareTestValidityOffset())
.InMillisecondsSinceUnixEpoch() /
1000);
cert.mutable_end_time()->set_seconds((not_before +
kNearbyShareCertificateValidityPeriod +
GetNearbyShareTestValidityOffset())
.InMillisecondsSinceUnixEpoch() /
1000);
cert.set_for_selected_contacts(
visibility == nearby_share::mojom::Visibility::kSelectedContacts);
cert.set_metadata_encryption_key(
std::string(GetNearbyShareTestMetadataEncryptionKey().begin(),
GetNearbyShareTestMetadataEncryptionKey().end()));
cert.set_encrypted_metadata_bytes(
std::string(GetNearbyShareTestEncryptedMetadata().begin(),
GetNearbyShareTestEncryptedMetadata().end()));
cert.set_metadata_encryption_key_tag(
std::string(GetNearbyShareTestMetadataEncryptionKeyTag().begin(),
GetNearbyShareTestMetadataEncryptionKeyTag().end()));
return cert;
}
std::vector<NearbySharePrivateCertificate>
GetNearbyShareTestPrivateCertificateList(
nearby_share::mojom::Visibility visibility) {
std::vector<NearbySharePrivateCertificate> list;
for (size_t i = 0; i < kNearbyShareNumPrivateCertificates; ++i) {
list.push_back(GetNearbyShareTestPrivateCertificate(
visibility, GetNearbyShareTestNotBefore() +
i * kNearbyShareCertificateValidityPeriod));
}
return list;
}
std::vector<nearby::sharing::proto::PublicCertificate>
GetNearbyShareTestPublicCertificateList(
nearby_share::mojom::Visibility visibility) {
std::vector<nearby::sharing::proto::PublicCertificate> list;
for (size_t i = 0; i < kNearbyShareNumPrivateCertificates; ++i) {
list.push_back(GetNearbyShareTestPublicCertificate(
visibility, GetNearbyShareTestNotBefore() +
i * kNearbyShareCertificateValidityPeriod));
}
return list;
}
const NearbyShareDecryptedPublicCertificate&
GetNearbyShareTestDecryptedPublicCertificate() {
static const base::NoDestructor<NearbyShareDecryptedPublicCertificate> cert(
*NearbyShareDecryptedPublicCertificate::DecryptPublicCertificate(
GetNearbyShareTestPublicCertificate(
nearby_share::mojom::Visibility::kAllContacts),
GetNearbyShareTestEncryptedMetadataKey()));
return *cert;
}