1// Copyright 2014 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 "components/rappor/byte_vector_utils.h"
6
7#include "base/rand_util.h"
8#include "base/strings/string_number_conversions.h"
9#include "testing/gtest/include/gtest/gtest.h"
10
11namespace rappor {
12
13namespace {
14
15class SecondRequest : public HmacByteVectorGenerator {
16 public:
17  SecondRequest(const HmacByteVectorGenerator& first_request)
18      : HmacByteVectorGenerator(first_request) {}
19};
20
21std::string HexToString(const char* hex) {
22  ByteVector bv;
23  base::HexStringToBytes(hex, &bv);
24  return std::string(bv.begin(), bv.end());
25}
26
27}  // namespace
28
29TEST(ByteVectorTest, ByteVectorAnd) {
30  ByteVector lhs(2);
31  lhs[1] = 0x12;
32  ByteVector rhs(2);
33  rhs[1] = 0x03;
34
35  EXPECT_EQ(0x02, (*ByteVectorAnd(lhs, &rhs))[1]);
36}
37
38TEST(ByteVectorTest, ByteVectorOr) {
39  ByteVector lhs(2);
40  lhs[1] = 0x12;
41  ByteVector rhs(2);
42  rhs[1] = 0x03;
43
44  EXPECT_EQ(0x13, (*ByteVectorOr(lhs, &rhs))[1]);
45}
46
47TEST(ByteVectorTest, ByteVectorMerge) {
48  ByteVector lhs(2);
49  lhs[1] = 0x33;
50  ByteVector rhs(2);
51  rhs[1] = 0x55;
52  ByteVector mask(2);
53  mask[1] = 0x0f;
54
55  EXPECT_EQ(0x35, (*ByteVectorMerge(mask, lhs, &rhs))[1]);
56}
57
58TEST(ByteVectorTest, ByteVectorGenerator) {
59  ByteVectorGenerator generator(2u);
60  ByteVector random_50 = generator.GetWeightedRandomByteVector(PROBABILITY_50);
61  EXPECT_EQ(random_50.size(), 2u);
62  ByteVector random_75 = generator.GetWeightedRandomByteVector(PROBABILITY_75);
63  EXPECT_EQ(random_75.size(), 2u);
64}
65
66TEST(ByteVectorTest, HmacByteVectorGenerator) {
67  HmacByteVectorGenerator generator(1u,
68      std::string(HmacByteVectorGenerator::kEntropyInputSize, 0x00), "");
69  ByteVector random_50 = generator.GetWeightedRandomByteVector(PROBABILITY_50);
70  EXPECT_EQ(random_50.size(), 1u);
71  EXPECT_EQ(random_50[0], 0x0B);
72  ByteVector random_75 = generator.GetWeightedRandomByteVector(PROBABILITY_75);
73  EXPECT_EQ(random_75.size(), 1u);
74  EXPECT_EQ(random_75[0], 0xdf);
75}
76
77TEST(ByteVectorTest, HmacNist) {
78  // Test case 0 for SHA-256 HMAC_DRBG no reseed tests from
79  // http://csrc.nist.gov/groups/STM/cavp/
80  const char entropy[] =
81      "ca851911349384bffe89de1cbdc46e6831e44d34a4fb935ee285dd14b71a7488";
82  const char nonce[] = "659ba96c601dc69fc902940805ec0ca8";
83  const char expected[] =
84      "e528e9abf2dece54d47c7e75e5fe302149f817ea9fb4bee6f4199697d04d5b89"
85      "d54fbb978a15b5c443c9ec21036d2460b6f73ebad0dc2aba6e624abf07745bc1"
86      "07694bb7547bb0995f70de25d6b29e2d3011bb19d27676c07162c8b5ccde0668"
87      "961df86803482cb37ed6d5c0bb8d50cf1f50d476aa0458bdaba806f48be9dcb8";
88
89  std::string entropy_input = HexToString(entropy) + HexToString(nonce);
90  HmacByteVectorGenerator generator(1024u / 8, entropy_input, "");
91  generator.GetWeightedRandomByteVector(PROBABILITY_50);
92  SecondRequest generator2(generator);
93  ByteVector random_50 = generator2.GetWeightedRandomByteVector(PROBABILITY_50);
94
95  EXPECT_EQ(HexToString(expected),
96      std::string(random_50.begin(), random_50.end()));
97}
98
99TEST(ByteVectorTest, WeightedRandomStatistics50) {
100  ByteVectorGenerator generator(50u);
101  ByteVector random = generator.GetWeightedRandomByteVector(PROBABILITY_50);
102  int bit_count = CountBits(random);
103  // Check bounds on bit counts that are true with 99.999% probability.
104  EXPECT_GT(bit_count, 155); // Binomial(400, .5) CDF(155) ~= 0.000004
105  EXPECT_LE(bit_count, 244); // Binomial(400, .5) CDF(244) ~= 0.999996
106}
107
108TEST(ByteVectorTest, WeightedRandomStatistics75) {
109  ByteVectorGenerator generator(50u);
110  ByteVector random = generator.GetWeightedRandomByteVector(PROBABILITY_75);
111  int bit_count = CountBits(random);
112  // Check bounds on bit counts that are true with 99.999% probability.
113  EXPECT_GT(bit_count, 259); // Binomial(400, .75) CDF(259) ~= 0.000003
114  EXPECT_LE(bit_count, 337); // Binomial(400, .75) CDF(337) ~= 0.999997
115}
116
117TEST(ByteVectorTest, HmacWeightedRandomStatistics50) {
118  HmacByteVectorGenerator generator(50u,
119      HmacByteVectorGenerator::GenerateEntropyInput(), "");
120  ByteVector random = generator.GetWeightedRandomByteVector(PROBABILITY_50);
121  int bit_count = CountBits(random);
122  // Check bounds on bit counts that are true with 99.999% probability.
123  EXPECT_GT(bit_count, 155); // Binomial(400, .5) CDF(155) ~= 0.000004
124  EXPECT_LE(bit_count, 244); // Binomial(400, .5) CDF(244) ~= 0.999996
125}
126
127TEST(ByteVectorTest, HmacWeightedRandomStatistics75) {
128  HmacByteVectorGenerator generator(50u,
129      HmacByteVectorGenerator::GenerateEntropyInput(), "");
130  ByteVector random = generator.GetWeightedRandomByteVector(PROBABILITY_75);
131  int bit_count = CountBits(random);
132  // Check bounds on bit counts that are true with 99.999% probability.
133  EXPECT_GT(bit_count, 259); // Binomial(400, .75) CDF(259) ~= 0.000003
134  EXPECT_LE(bit_count, 337); // Binomial(400, .75) CDF(337) ~= 0.999997
135}
136
137}  // namespace rappor
138