• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 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 //     https://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 "securegcm/d2d_connection_context_v1.h"
16 
17 #include "securegcm/d2d_crypto_ops.h"
18 #include "gtest/gtest.h"
19 
20 namespace securegcm {
21 
22 using securemessage::CryptoOps;
23 
24 namespace {
25 
26 // The encode and decode keys should be 32 bytes.
27 const char kEncodeKeyData[] = "initiator_encode_key_for_aes_256";
28 const char kDecodeKeyData[] = "initiator_decode_key_for_aes_256";
29 
30 }  // namespace
31 
32 // A friend to access the private variables of D2DConnectionContextV1.
33 class D2DConnectionContextV1Peer {
34  public:
D2DConnectionContextV1Peer(const std::string & savedSessionInfo)35   explicit D2DConnectionContextV1Peer(const std::string& savedSessionInfo) {
36     context_ = D2DConnectionContextV1::FromSavedSession(savedSessionInfo);
37   }
38 
GetContext()39   D2DConnectionContextV1* GetContext() { return context_.get(); }
40 
GetEncodeSequenceNumber()41   uint32_t GetEncodeSequenceNumber() {
42     return context_->encode_sequence_number_;
43   }
44 
GetDecodeSequenceNumber()45   uint32_t GetDecodeSequenceNumber() {
46     return context_->decode_sequence_number_;
47   }
48 
49  private:
50   std::unique_ptr<D2DConnectionContextV1> context_;
51 };
52 
TEST(D2DConnectionContextionV1Test,SaveSession)53 TEST(D2DConnectionContextionV1Test, SaveSession) {
54   CryptoOps::SecretKey encodeKey = CryptoOps::SecretKey(
55       kEncodeKeyData, CryptoOps::KeyAlgorithm::AES_256_KEY);
56   CryptoOps::SecretKey decodeKey = CryptoOps::SecretKey(
57       kDecodeKeyData, CryptoOps::KeyAlgorithm::AES_256_KEY);
58 
59   D2DConnectionContextV1 initiator =
60       D2DConnectionContextV1(encodeKey, decodeKey, 0, 1);
61   D2DConnectionContextV1 responder =
62       D2DConnectionContextV1(decodeKey, encodeKey, 1, 0);
63 
64   std::unique_ptr<std::string> initiatorSavedSessionState =
65       initiator.SaveSession();
66   std::unique_ptr<std::string> responderSavedSessionState =
67       responder.SaveSession();
68 
69   D2DConnectionContextV1Peer restoredInitiator =
70       D2DConnectionContextV1Peer(*initiatorSavedSessionState);
71   D2DConnectionContextV1Peer restoredResponder =
72       D2DConnectionContextV1Peer(*responderSavedSessionState);
73 
74   // Verify internal state matches initialization.
75   EXPECT_EQ(0, restoredInitiator.GetEncodeSequenceNumber());
76   EXPECT_EQ(1, restoredInitiator.GetDecodeSequenceNumber());
77   EXPECT_EQ(1, restoredResponder.GetEncodeSequenceNumber());
78   EXPECT_EQ(0, restoredResponder.GetDecodeSequenceNumber());
79 
80   EXPECT_EQ(*restoredInitiator.GetContext()->GetSessionUnique(),
81             *restoredResponder.GetContext()->GetSessionUnique());
82 
83   const std::string message = "ping";
84 
85   // Ensure that they can still talk to one another.
86   std::string encodedMessage =
87       *restoredInitiator.GetContext()->EncodeMessageToPeer(message);
88   std::string decodedMessage =
89       *restoredResponder.GetContext()->DecodeMessageFromPeer(encodedMessage);
90 
91   EXPECT_EQ(message, decodedMessage);
92 
93   encodedMessage =
94       *restoredResponder.GetContext()->EncodeMessageToPeer(message);
95   decodedMessage =
96       *restoredInitiator.GetContext()->DecodeMessageFromPeer(encodedMessage);
97 
98   EXPECT_EQ(message, decodedMessage);
99 }
100 
TEST(D2DConnectionContextionV1Test,SaveSession_TooShort)101 TEST(D2DConnectionContextionV1Test, SaveSession_TooShort) {
102   CryptoOps::SecretKey encodeKey = CryptoOps::SecretKey(
103       kEncodeKeyData, CryptoOps::KeyAlgorithm::AES_256_KEY);
104   CryptoOps::SecretKey decodeKey = CryptoOps::SecretKey(
105       kDecodeKeyData, CryptoOps::KeyAlgorithm::AES_256_KEY);
106 
107   D2DConnectionContextV1 initiator =
108       D2DConnectionContextV1(encodeKey, decodeKey, 0, 1);
109 
110   std::unique_ptr<std::string> initiatorSavedSessionState =
111       initiator.SaveSession();
112 
113   // Try to rebuild the context with a shorter session state.
114   std::string shortSessionState = initiatorSavedSessionState->substr(
115       0, initiatorSavedSessionState->size() - 1);
116 
117   D2DConnectionContextV1Peer restoredInitiator =
118       D2DConnectionContextV1Peer(shortSessionState);
119 
120   // nullptr is returned on error. It should not crash.
121   EXPECT_EQ(restoredInitiator.GetContext(), nullptr);
122 }
123 
124 }  // namespace securegcm
125