xref: /aosp_15_r20/external/tink/cc/examples/walkthrough/write_keyset_test.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1 // Copyright 2022 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 //     http://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 ///////////////////////////////////////////////////////////////////////////////
16 
17 #include "walkthrough/write_keyset.h"
18 
19 #include <memory>
20 #include <ostream>
21 #include <sstream>
22 #include <string>
23 #include <utility>
24 
25 #include "gmock/gmock.h"
26 #include "absl/memory/memory.h"
27 #include "absl/status/status.h"
28 #include "absl/strings/string_view.h"
29 #include "tink/aead.h"
30 #include "tink/aead/aead_config.h"
31 #include "walkthrough/load_cleartext_keyset.h"
32 #include "walkthrough/load_encrypted_keyset.h"
33 #include "walkthrough/test_util.h"
34 #include "tink/kms_clients.h"
35 #include "tink/util/status.h"
36 #include "tink/util/statusor.h"
37 #include "tink/util/test_matchers.h"
38 
39 namespace tink_walkthrough {
40 namespace {
41 
42 constexpr absl::string_view kSerializedMasterKeyKeyset = R"json({
43   "key": [
44     {
45       "keyData": {
46         "keyMaterialType": "SYMMETRIC",
47         "typeUrl": "type.googleapis.com/google.crypto.tink.AesGcmKey",
48         "value": "GiBWyUfGgYk3RTRhj/LIUzSudIWlyjCftCOypTr0jCNSLg=="
49       },
50       "keyId": 294406504,
51       "outputPrefixType": "TINK",
52       "status": "ENABLED"
53     }
54   ],
55   "primaryKeyId": 294406504
56 })json";
57 
58 constexpr absl::string_view kSerializedKeysetToEncrypt = R"json({
59   "key": [
60     {
61       "keyData": {
62         "keyMaterialType": "SYMMETRIC",
63         "typeUrl": "type.googleapis.com/google.crypto.tink.AesGcmKey",
64         "value": "GhD+9l0RANZjzZEZ8PDp7LRW"
65       },
66       "keyId": 1931667682,
67       "outputPrefixType": "TINK",
68       "status": "ENABLED"
69     }
70   ],
71   "primaryKeyId": 1931667682
72 })json";
73 
74 using ::crypto::tink::Aead;
75 using ::crypto::tink::KeysetHandle;
76 using ::crypto::tink::test::IsOk;
77 using ::crypto::tink::test::IsOkAndHolds;
78 using ::crypto::tink::test::StatusIs;
79 using ::crypto::tink::util::Status;
80 using ::crypto::tink::util::StatusOr;
81 using ::testing::Not;
82 
InitFakeKms()83 Status InitFakeKms() {
84   static Status* status = new Status([]() {
85     Status status = crypto::tink::AeadConfig::Register();
86     if (!status.ok()) {
87       return status;
88     }
89     return crypto::tink::KmsClients::Add(
90         absl::make_unique<FakeKmsClient>(kSerializedMasterKeyKeyset));
91   }());
92   return *status;
93 }
94 
95 class WriteKeysetTest : public testing::Test {
96  protected:
SetUp()97   void SetUp() override {
98     ASSERT_THAT(InitFakeKms(), IsOk());
99     StatusOr<std::unique_ptr<KeysetHandle>> keyset_handle_to_encrypt =
100         LoadKeyset(kSerializedKeysetToEncrypt);
101     ASSERT_THAT(keyset_handle_to_encrypt, IsOk());
102     keyset_handle_to_encrypt_ = std::move(*keyset_handle_to_encrypt);
103   }
104 
105   std::unique_ptr<KeysetHandle> keyset_handle_to_encrypt_;
106 };
107 
TEST_F(WriteKeysetTest,WriteEncryptedKeysetFailsWithNullOutputStream)108 TEST_F(WriteKeysetTest, WriteEncryptedKeysetFailsWithNullOutputStream) {
109   EXPECT_THAT(WriteEncryptedKeyset(*keyset_handle_to_encrypt_, nullptr,
110                                    /*master_kms_key_uri=*/"fake://some_key"),
111               StatusIs(absl::StatusCode::kInvalidArgument));
112 }
113 
TEST_F(WriteKeysetTest,WriteEncryptedKeysetFailsWhenStreamFails)114 TEST_F(WriteKeysetTest, WriteEncryptedKeysetFailsWhenStreamFails) {
115   auto output_stream = absl::make_unique<std::ostream>(nullptr);
116   EXPECT_THAT(
117       WriteEncryptedKeyset(*keyset_handle_to_encrypt_, std::move(output_stream),
118                            /*master_kms_key_uri=*/"fake://some_key"),
119       Not(IsOk()));
120 }
121 
TEST_F(WriteKeysetTest,WriteEncryptedKeysetFailsNoKmsAvailable)122 TEST_F(WriteKeysetTest, WriteEncryptedKeysetFailsNoKmsAvailable) {
123   std::stringbuf buffer;
124   auto output_stream = absl::make_unique<std::ostream>(&buffer);
125   EXPECT_THAT(WriteEncryptedKeyset(
126                   *keyset_handle_to_encrypt_, std::move(output_stream),
127                   /*master_kms_key_uri=*/"does_not_exist://does_not_exist"),
128               StatusIs(absl::StatusCode::kNotFound));
129 }
130 
TEST_F(WriteKeysetTest,WriteEncryptedKeysetWithValidInputs)131 TEST_F(WriteKeysetTest, WriteEncryptedKeysetWithValidInputs) {
132   std::stringbuf buffer;
133   auto output_stream = absl::make_unique<std::ostream>(&buffer);
134   constexpr absl::string_view master_kms_key_uri = "fake://some_key";
135   ASSERT_THAT(
136       WriteEncryptedKeyset(*keyset_handle_to_encrypt_, std::move(output_stream),
137                            master_kms_key_uri),
138       IsOk());
139   StatusOr<std::unique_ptr<Aead>> expected_aead =
140       keyset_handle_to_encrypt_->GetPrimitive<Aead>();
141   ASSERT_THAT(expected_aead, IsOk());
142   constexpr absl::string_view associated_data = "Some associated data";
143   constexpr absl::string_view plaintext = "Some plaintext";
144 
145   StatusOr<std::string> ciphertext =
146       (*expected_aead)->Encrypt(plaintext, associated_data);
147   ASSERT_THAT(ciphertext, IsOk());
148 
149   // Make sure the encrypted keyset was written correctly by loading it and
150   // trying to decrypt ciphertext.
151   StatusOr<std::unique_ptr<KeysetHandle>> loaded_keyset =
152       LoadKeyset(buffer.str(), master_kms_key_uri);
153   ASSERT_THAT(loaded_keyset, IsOk());
154   StatusOr<std::unique_ptr<Aead>> loaded_keyset_aead =
155       (*loaded_keyset)->GetPrimitive<Aead>();
156   ASSERT_THAT(loaded_keyset_aead, IsOk());
157   EXPECT_THAT((*loaded_keyset_aead)->Decrypt(*ciphertext, associated_data),
158               IsOkAndHolds(plaintext));
159 }
160 
161 }  // namespace
162 }  // namespace tink_walkthrough
163