1 // Copyright (c) 2013 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 "net/third_party/quiche/src/quic/core/crypto/crypto_secret_boxer.h"
6 
7 #include <string>
8 
9 #include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
10 #include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
11 #include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
12 
13 namespace quic {
14 namespace test {
15 
16 class CryptoSecretBoxerTest : public QuicTest {};
17 
TEST_F(CryptoSecretBoxerTest,BoxAndUnbox)18 TEST_F(CryptoSecretBoxerTest, BoxAndUnbox) {
19   quiche::QuicheStringPiece message("hello world");
20 
21   CryptoSecretBoxer boxer;
22   boxer.SetKeys({std::string(CryptoSecretBoxer::GetKeySize(), 0x11)});
23 
24   const std::string box = boxer.Box(QuicRandom::GetInstance(), message);
25 
26   std::string storage;
27   quiche::QuicheStringPiece result;
28   EXPECT_TRUE(boxer.Unbox(box, &storage, &result));
29   EXPECT_EQ(result, message);
30 
31   EXPECT_FALSE(boxer.Unbox(std::string(1, 'X') + box, &storage, &result));
32   EXPECT_FALSE(
33       boxer.Unbox(box.substr(1, std::string::npos), &storage, &result));
34   EXPECT_FALSE(boxer.Unbox(std::string(), &storage, &result));
35   EXPECT_FALSE(boxer.Unbox(
36       std::string(1, box[0] ^ 0x80) + box.substr(1, std::string::npos),
37       &storage, &result));
38 }
39 
40 // Helper function to test whether one boxer can decode the output of another.
CanDecode(const CryptoSecretBoxer & decoder,const CryptoSecretBoxer & encoder)41 static bool CanDecode(const CryptoSecretBoxer& decoder,
42                       const CryptoSecretBoxer& encoder) {
43   quiche::QuicheStringPiece message("hello world");
44   const std::string boxed = encoder.Box(QuicRandom::GetInstance(), message);
45   std::string storage;
46   quiche::QuicheStringPiece result;
47   bool ok = decoder.Unbox(boxed, &storage, &result);
48   if (ok) {
49     EXPECT_EQ(result, message);
50   }
51   return ok;
52 }
53 
TEST_F(CryptoSecretBoxerTest,MultipleKeys)54 TEST_F(CryptoSecretBoxerTest, MultipleKeys) {
55   std::string key_11(CryptoSecretBoxer::GetKeySize(), 0x11);
56   std::string key_12(CryptoSecretBoxer::GetKeySize(), 0x12);
57 
58   CryptoSecretBoxer boxer_11, boxer_12, boxer;
59   boxer_11.SetKeys({key_11});
60   boxer_12.SetKeys({key_12});
61   boxer.SetKeys({key_12, key_11});
62 
63   // Neither single-key boxer can decode the other's tokens.
64   EXPECT_FALSE(CanDecode(boxer_11, boxer_12));
65   EXPECT_FALSE(CanDecode(boxer_12, boxer_11));
66 
67   // |boxer| encodes with the first key, which is key_12.
68   EXPECT_TRUE(CanDecode(boxer_12, boxer));
69   EXPECT_FALSE(CanDecode(boxer_11, boxer));
70 
71   // The boxer with both keys can decode tokens from either single-key boxer.
72   EXPECT_TRUE(CanDecode(boxer, boxer_11));
73   EXPECT_TRUE(CanDecode(boxer, boxer_12));
74 
75   // After we flush key_11 from |boxer|, it can no longer decode tokens from
76   // |boxer_11|.
77   boxer.SetKeys({key_12});
78   EXPECT_FALSE(CanDecode(boxer, boxer_11));
79 }
80 
81 }  // namespace test
82 }  // namespace quic
83