xref: /aosp_15_r20/external/tink/cc/util/test_util.h (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1*e7b1675dSTing-Kang Chang // Copyright 2017 Google Inc.
2*e7b1675dSTing-Kang Chang //
3*e7b1675dSTing-Kang Chang // Licensed under the Apache License, Version 2.0 (the "License");
4*e7b1675dSTing-Kang Chang // you may not use this file except in compliance with the License.
5*e7b1675dSTing-Kang Chang // You may obtain a copy of the License at
6*e7b1675dSTing-Kang Chang //
7*e7b1675dSTing-Kang Chang //     http://www.apache.org/licenses/LICENSE-2.0
8*e7b1675dSTing-Kang Chang //
9*e7b1675dSTing-Kang Chang // Unless required by applicable law or agreed to in writing, software
10*e7b1675dSTing-Kang Chang // distributed under the License is distributed on an "AS IS" BASIS,
11*e7b1675dSTing-Kang Chang // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*e7b1675dSTing-Kang Chang // See the License for the specific language governing permissions and
13*e7b1675dSTing-Kang Chang // limitations under the License.
14*e7b1675dSTing-Kang Chang //
15*e7b1675dSTing-Kang Chang ///////////////////////////////////////////////////////////////////////////////
16*e7b1675dSTing-Kang Chang 
17*e7b1675dSTing-Kang Chang #ifndef TINK_UTIL_TEST_UTIL_H_
18*e7b1675dSTing-Kang Chang #define TINK_UTIL_TEST_UTIL_H_
19*e7b1675dSTing-Kang Chang 
20*e7b1675dSTing-Kang Chang #include <limits>
21*e7b1675dSTing-Kang Chang #include <memory>
22*e7b1675dSTing-Kang Chang #include <ostream>
23*e7b1675dSTing-Kang Chang #include <string>
24*e7b1675dSTing-Kang Chang #include <utility>
25*e7b1675dSTing-Kang Chang 
26*e7b1675dSTing-Kang Chang #include "absl/base/thread_annotations.h"
27*e7b1675dSTing-Kang Chang #include "absl/status/status.h"
28*e7b1675dSTing-Kang Chang #include "absl/strings/cord.h"
29*e7b1675dSTing-Kang Chang #include "absl/strings/match.h"
30*e7b1675dSTing-Kang Chang #include "absl/strings/str_cat.h"
31*e7b1675dSTing-Kang Chang #include "absl/strings/string_view.h"
32*e7b1675dSTing-Kang Chang #include "absl/synchronization/mutex.h"
33*e7b1675dSTing-Kang Chang #include "tink/aead.h"
34*e7b1675dSTing-Kang Chang #include "tink/aead/cord_aead.h"
35*e7b1675dSTing-Kang Chang #include "tink/deterministic_aead.h"
36*e7b1675dSTing-Kang Chang #include "tink/hybrid_decrypt.h"
37*e7b1675dSTing-Kang Chang #include "tink/hybrid_encrypt.h"
38*e7b1675dSTing-Kang Chang #include "tink/input_stream.h"
39*e7b1675dSTing-Kang Chang #include "tink/keyset_handle.h"
40*e7b1675dSTing-Kang Chang #include "tink/kms_client.h"
41*e7b1675dSTing-Kang Chang #include "tink/mac.h"
42*e7b1675dSTing-Kang Chang #include "tink/output_stream.h"
43*e7b1675dSTing-Kang Chang #include "tink/public_key_sign.h"
44*e7b1675dSTing-Kang Chang #include "tink/public_key_verify.h"
45*e7b1675dSTing-Kang Chang #include "tink/random_access_stream.h"
46*e7b1675dSTing-Kang Chang #include "tink/streaming_aead.h"
47*e7b1675dSTing-Kang Chang #include "tink/subtle/common_enums.h"
48*e7b1675dSTing-Kang Chang #include "tink/subtle/mac/stateful_mac.h"
49*e7b1675dSTing-Kang Chang #include "tink/util/buffer.h"
50*e7b1675dSTing-Kang Chang #include "tink/util/constants.h"
51*e7b1675dSTing-Kang Chang #include "tink/util/protobuf_helper.h"
52*e7b1675dSTing-Kang Chang #include "tink/util/status.h"
53*e7b1675dSTing-Kang Chang #include "tink/util/statusor.h"
54*e7b1675dSTing-Kang Chang #include "proto/common.pb.h"
55*e7b1675dSTing-Kang Chang #include "proto/ecdsa.pb.h"
56*e7b1675dSTing-Kang Chang #include "proto/ecies_aead_hkdf.pb.h"
57*e7b1675dSTing-Kang Chang #include "proto/ed25519.pb.h"
58*e7b1675dSTing-Kang Chang #include "proto/tink.pb.h"
59*e7b1675dSTing-Kang Chang 
60*e7b1675dSTing-Kang Chang namespace crypto {
61*e7b1675dSTing-Kang Chang namespace tink {
62*e7b1675dSTing-Kang Chang namespace test {
63*e7b1675dSTing-Kang Chang 
64*e7b1675dSTing-Kang Chang // Various utilities for testing.
65*e7b1675dSTing-Kang Chang ///////////////////////////////////////////////////////////////////////////////
66*e7b1675dSTing-Kang Chang 
67*e7b1675dSTing-Kang Chang // Reads the test file specified by `filename`, and returns its contents.
68*e7b1675dSTing-Kang Chang std::string ReadTestFile(absl::string_view filename);
69*e7b1675dSTing-Kang Chang 
70*e7b1675dSTing-Kang Chang // Converts a hexadecimal string into a string of bytes.
71*e7b1675dSTing-Kang Chang // Returns a status if the size of the input is odd or if the input contains
72*e7b1675dSTing-Kang Chang // characters that are not hexadecimal.
73*e7b1675dSTing-Kang Chang crypto::tink::util::StatusOr<std::string> HexDecode(absl::string_view hex);
74*e7b1675dSTing-Kang Chang 
75*e7b1675dSTing-Kang Chang // Converts a hexadecimal string into a string of bytes.
76*e7b1675dSTing-Kang Chang // Dies if the input is not a valid hexadecimal string.
77*e7b1675dSTing-Kang Chang std::string HexDecodeOrDie(absl::string_view hex);
78*e7b1675dSTing-Kang Chang 
79*e7b1675dSTing-Kang Chang // Converts a string of bytes into a hexadecimal string.
80*e7b1675dSTing-Kang Chang std::string HexEncode(absl::string_view bytes);
81*e7b1675dSTing-Kang Chang 
82*e7b1675dSTing-Kang Chang // Returns a temporary directory suitable for temporary testing files.
83*e7b1675dSTing-Kang Chang std::string TmpDir();
84*e7b1675dSTing-Kang Chang 
85*e7b1675dSTing-Kang Chang // Adds the given 'keyData' with specified status, key_id, and
86*e7b1675dSTing-Kang Chang // output_prefix_type to the keyset.
87*e7b1675dSTing-Kang Chang void AddKeyData(const google::crypto::tink::KeyData& key_data, uint32_t key_id,
88*e7b1675dSTing-Kang Chang                 google::crypto::tink::OutputPrefixType output_prefix,
89*e7b1675dSTing-Kang Chang                 google::crypto::tink::KeyStatusType key_status,
90*e7b1675dSTing-Kang Chang                 google::crypto::tink::Keyset* keyset);
91*e7b1675dSTing-Kang Chang 
92*e7b1675dSTing-Kang Chang // Adds the given 'key' with specified parameters and output_prefix_type=TINK
93*e7b1675dSTing-Kang Chang // to the specified 'keyset'.
94*e7b1675dSTing-Kang Chang void AddTinkKey(const std::string& key_type, uint32_t key_id,
95*e7b1675dSTing-Kang Chang                 const portable_proto::MessageLite& key,
96*e7b1675dSTing-Kang Chang                 google::crypto::tink::KeyStatusType key_status,
97*e7b1675dSTing-Kang Chang                 google::crypto::tink::KeyData::KeyMaterialType material_type,
98*e7b1675dSTing-Kang Chang                 google::crypto::tink::Keyset* keyset);
99*e7b1675dSTing-Kang Chang 
100*e7b1675dSTing-Kang Chang // Adds the given 'key' with specified parameters and output_prefix_type=LEGACY
101*e7b1675dSTing-Kang Chang // to the specified 'keyset'.
102*e7b1675dSTing-Kang Chang void AddLegacyKey(const std::string& key_type, uint32_t key_id,
103*e7b1675dSTing-Kang Chang                   const portable_proto::MessageLite& key,
104*e7b1675dSTing-Kang Chang                   google::crypto::tink::KeyStatusType key_status,
105*e7b1675dSTing-Kang Chang                   google::crypto::tink::KeyData::KeyMaterialType material_type,
106*e7b1675dSTing-Kang Chang                   google::crypto::tink::Keyset* keyset);
107*e7b1675dSTing-Kang Chang 
108*e7b1675dSTing-Kang Chang // Adds the given 'key' with specified parameters and output_prefix_type=RAW
109*e7b1675dSTing-Kang Chang // to the specified 'keyset'.
110*e7b1675dSTing-Kang Chang void AddRawKey(const std::string& key_type, uint32_t key_id,
111*e7b1675dSTing-Kang Chang                const portable_proto::MessageLite& key,
112*e7b1675dSTing-Kang Chang                google::crypto::tink::KeyStatusType key_status,
113*e7b1675dSTing-Kang Chang                google::crypto::tink::KeyData::KeyMaterialType material_type,
114*e7b1675dSTing-Kang Chang                google::crypto::tink::Keyset* keyset);
115*e7b1675dSTing-Kang Chang 
116*e7b1675dSTing-Kang Chang // Generates a fresh test key for ECIES-AEAD-HKDF for the given curve,
117*e7b1675dSTing-Kang Chang // using AesGcm with the specified key size as AEAD, and HKDF with 'hash_type'.
118*e7b1675dSTing-Kang Chang google::crypto::tink::EciesAeadHkdfPrivateKey GetEciesAesGcmHkdfTestKey(
119*e7b1675dSTing-Kang Chang     subtle::EllipticCurveType curve_type, subtle::EcPointFormat ec_point_format,
120*e7b1675dSTing-Kang Chang     subtle::HashType hash_type, uint32_t aes_gcm_key_size);
121*e7b1675dSTing-Kang Chang 
122*e7b1675dSTing-Kang Chang // Generates a fresh test key for ECIES-AEAD-HKDF for the given curve,
123*e7b1675dSTing-Kang Chang // using AesGcm with the specified key size as AEAD, and HKDF with 'hash_type'.
124*e7b1675dSTing-Kang Chang google::crypto::tink::EciesAeadHkdfPrivateKey GetEciesAesGcmHkdfTestKey(
125*e7b1675dSTing-Kang Chang     google::crypto::tink::EllipticCurveType curve_type,
126*e7b1675dSTing-Kang Chang     google::crypto::tink::EcPointFormat ec_point_format,
127*e7b1675dSTing-Kang Chang     google::crypto::tink::HashType hash_type, uint32_t aes_gcm_key_size);
128*e7b1675dSTing-Kang Chang 
129*e7b1675dSTing-Kang Chang // Generates a fresh test key for ECIES-AEAD-HKDF for the given curve,
130*e7b1675dSTing-Kang Chang // using XChaCha20Poly1305 as AEAD, and HKDF with 'hash_type'.
131*e7b1675dSTing-Kang Chang google::crypto::tink::EciesAeadHkdfPrivateKey
132*e7b1675dSTing-Kang Chang GetEciesXChaCha20Poly1305HkdfTestKey(
133*e7b1675dSTing-Kang Chang     google::crypto::tink::EllipticCurveType curve_type,
134*e7b1675dSTing-Kang Chang     google::crypto::tink::EcPointFormat ec_point_format,
135*e7b1675dSTing-Kang Chang     google::crypto::tink::HashType hash_type);
136*e7b1675dSTing-Kang Chang 
137*e7b1675dSTing-Kang Chang // Generates a fresh test key for ECIES-AEAD-HKDF for the given curve,
138*e7b1675dSTing-Kang Chang // using AesCtrHmac with the specified AEAD params, and HKDF with 'hash_type'.
139*e7b1675dSTing-Kang Chang google::crypto::tink::EciesAeadHkdfPrivateKey GetEciesAesCtrHmacHkdfTestKey(
140*e7b1675dSTing-Kang Chang     google::crypto::tink::EllipticCurveType curve_type,
141*e7b1675dSTing-Kang Chang     google::crypto::tink::EcPointFormat ec_point_format,
142*e7b1675dSTing-Kang Chang     google::crypto::tink::HashType hash_type, uint32_t aes_ctr_key_size,
143*e7b1675dSTing-Kang Chang     uint32_t aes_ctr_iv_size, google::crypto::tink::HashType hmac_hash_type,
144*e7b1675dSTing-Kang Chang     uint32_t hmac_tag_size, uint32_t hmac_key_size);
145*e7b1675dSTing-Kang Chang 
146*e7b1675dSTing-Kang Chang // Generates a fresh test key for ECIES-AEAD-HKDF for the given curve,
147*e7b1675dSTing-Kang Chang // using AesSiv as the determinisitic AEAD, and HKDF with 'hash_type'.
148*e7b1675dSTing-Kang Chang google::crypto::tink::EciesAeadHkdfPrivateKey GetEciesAesSivHkdfTestKey(
149*e7b1675dSTing-Kang Chang     google::crypto::tink::EllipticCurveType curve_type,
150*e7b1675dSTing-Kang Chang     google::crypto::tink::EcPointFormat ec_point_format,
151*e7b1675dSTing-Kang Chang     google::crypto::tink::HashType hash_type);
152*e7b1675dSTing-Kang Chang 
153*e7b1675dSTing-Kang Chang // Generates a fresh test key for EC DSA for the given 'curve_type', 'hash_type'
154*e7b1675dSTing-Kang Chang // and 'encoding'.
155*e7b1675dSTing-Kang Chang google::crypto::tink::EcdsaPrivateKey GetEcdsaTestPrivateKey(
156*e7b1675dSTing-Kang Chang     subtle::EllipticCurveType curve_type, subtle::HashType hash_type,
157*e7b1675dSTing-Kang Chang     subtle::EcdsaSignatureEncoding encoding);
158*e7b1675dSTing-Kang Chang 
159*e7b1675dSTing-Kang Chang // Generates a fresh test key for EC DSA for the given 'curve_type', 'hash_type'
160*e7b1675dSTing-Kang Chang // and 'encoding'.
161*e7b1675dSTing-Kang Chang google::crypto::tink::EcdsaPrivateKey GetEcdsaTestPrivateKey(
162*e7b1675dSTing-Kang Chang     google::crypto::tink::EllipticCurveType curve_type,
163*e7b1675dSTing-Kang Chang     google::crypto::tink::HashType hash_type,
164*e7b1675dSTing-Kang Chang     google::crypto::tink::EcdsaSignatureEncoding encoding);
165*e7b1675dSTing-Kang Chang 
166*e7b1675dSTing-Kang Chang // TODO(ambrosin): Remove because it is unused.
167*e7b1675dSTing-Kang Chang // Generates a fresh test key for ED25519.
168*e7b1675dSTing-Kang Chang google::crypto::tink::Ed25519PrivateKey GetEd25519TestPrivateKey();
169*e7b1675dSTing-Kang Chang 
170*e7b1675dSTing-Kang Chang // Embeds the given Proto into a KeyData proto.
171*e7b1675dSTing-Kang Chang template <typename Proto>
AsKeyData(const Proto & proto,google::crypto::tink::KeyData::KeyMaterialType key_material_type)172*e7b1675dSTing-Kang Chang google::crypto::tink::KeyData AsKeyData(
173*e7b1675dSTing-Kang Chang     const Proto& proto,
174*e7b1675dSTing-Kang Chang     google::crypto::tink::KeyData::KeyMaterialType key_material_type) {
175*e7b1675dSTing-Kang Chang   google::crypto::tink::KeyData result;
176*e7b1675dSTing-Kang Chang   result.set_value(proto.SerializeAsString());
177*e7b1675dSTing-Kang Chang   result.set_type_url(absl::StrCat(kTypeGoogleapisCom, proto.GetTypeName()));
178*e7b1675dSTing-Kang Chang   result.set_key_material_type(key_material_type);
179*e7b1675dSTing-Kang Chang   return result;
180*e7b1675dSTing-Kang Chang }
181*e7b1675dSTing-Kang Chang 
182*e7b1675dSTing-Kang Chang // Uses a z test on the given byte string, expecting all bits to be uniformly
183*e7b1675dSTing-Kang Chang // set with probability 1/2. Returns non ok status if the z test fails by more
184*e7b1675dSTing-Kang Chang // than 10 standard deviations.
185*e7b1675dSTing-Kang Chang //
186*e7b1675dSTing-Kang Chang // With less statistics jargon: This counts the number of bits set and expects
187*e7b1675dSTing-Kang Chang // the number to be roughly half of the length of the string. The law of large
188*e7b1675dSTing-Kang Chang // numbers suggests that we can assume that the longer the string is, the more
189*e7b1675dSTing-Kang Chang // accurate that estimate becomes for a random string. This test is useful to
190*e7b1675dSTing-Kang Chang // detect things like strings that are entirely zero.
191*e7b1675dSTing-Kang Chang //
192*e7b1675dSTing-Kang Chang // Note: By itself, this is a very weak test for randomness.
193*e7b1675dSTing-Kang Chang util::Status ZTestUniformString(absl::string_view bytes);
194*e7b1675dSTing-Kang Chang // Tests that the crosscorrelation of two strings of equal length points to
195*e7b1675dSTing-Kang Chang // independent and uniformly distributed strings. Returns non ok status if the z
196*e7b1675dSTing-Kang Chang // test fails by more than 10 standard deviations.
197*e7b1675dSTing-Kang Chang //
198*e7b1675dSTing-Kang Chang // With less statistics jargon: This xors two strings and then performs the
199*e7b1675dSTing-Kang Chang // ZTestUniformString on the result. If the two strings are independent and
200*e7b1675dSTing-Kang Chang // uniformly distributed, the xor'ed string is as well. A cross correlation test
201*e7b1675dSTing-Kang Chang // will find whether two strings overlap more or less than it would be expected.
202*e7b1675dSTing-Kang Chang //
203*e7b1675dSTing-Kang Chang // Note: Having a correlation of zero is only a necessary but not sufficient
204*e7b1675dSTing-Kang Chang // condition for independence.
205*e7b1675dSTing-Kang Chang util::Status ZTestCrosscorrelationUniformStrings(absl::string_view bytes1,
206*e7b1675dSTing-Kang Chang                                                  absl::string_view bytes2);
207*e7b1675dSTing-Kang Chang // Tests that the autocorrelation of a string points to the bits being
208*e7b1675dSTing-Kang Chang // independent and uniformly distributed. Rotates the string in a cyclic
209*e7b1675dSTing-Kang Chang // fashion. Returns non ok status if the z test fails by more than 10 standard
210*e7b1675dSTing-Kang Chang // deviations.
211*e7b1675dSTing-Kang Chang //
212*e7b1675dSTing-Kang Chang // With less statistics jargon: This rotates the string bit by bit and performs
213*e7b1675dSTing-Kang Chang // ZTestCrosscorrelationUniformStrings on each of the rotated strings and the
214*e7b1675dSTing-Kang Chang // original. This will find self similarity of the input string, especially
215*e7b1675dSTing-Kang Chang // periodic self similarity. For example, it is a decent test to find English
216*e7b1675dSTing-Kang Chang // text (needs about 180 characters with the current settings).
217*e7b1675dSTing-Kang Chang //
218*e7b1675dSTing-Kang Chang // Note: Having a correlation of zero is only a necessary but not sufficient
219*e7b1675dSTing-Kang Chang // condition for independence.
220*e7b1675dSTing-Kang Chang util::Status ZTestAutocorrelationUniformString(absl::string_view bytes);
221*e7b1675dSTing-Kang Chang 
222*e7b1675dSTing-Kang Chang // A dummy implementation of Aead-interface.
223*e7b1675dSTing-Kang Chang // An instance of DummyAead can be identified by a name specified
224*e7b1675dSTing-Kang Chang // as a parameter of the constructor.
225*e7b1675dSTing-Kang Chang class DummyAead : public Aead {
226*e7b1675dSTing-Kang Chang  public:
DummyAead(absl::string_view aead_name)227*e7b1675dSTing-Kang Chang   explicit DummyAead(absl::string_view aead_name) : aead_name_(aead_name) {}
228*e7b1675dSTing-Kang Chang 
229*e7b1675dSTing-Kang Chang   // Computes a dummy ciphertext, which is concatenation of provided 'plaintext'
230*e7b1675dSTing-Kang Chang   // with the name of this DummyAead.
Encrypt(absl::string_view plaintext,absl::string_view associated_data)231*e7b1675dSTing-Kang Chang   crypto::tink::util::StatusOr<std::string> Encrypt(
232*e7b1675dSTing-Kang Chang       absl::string_view plaintext,
233*e7b1675dSTing-Kang Chang       absl::string_view associated_data) const override {
234*e7b1675dSTing-Kang Chang     return absl::StrCat(aead_name_.size(), ":", associated_data.size(), ":",
235*e7b1675dSTing-Kang Chang                         aead_name_, associated_data, plaintext);
236*e7b1675dSTing-Kang Chang   }
237*e7b1675dSTing-Kang Chang 
Decrypt(absl::string_view ciphertext,absl::string_view associated_data)238*e7b1675dSTing-Kang Chang   crypto::tink::util::StatusOr<std::string> Decrypt(
239*e7b1675dSTing-Kang Chang       absl::string_view ciphertext,
240*e7b1675dSTing-Kang Chang       absl::string_view associated_data) const override {
241*e7b1675dSTing-Kang Chang     std::string prefix =
242*e7b1675dSTing-Kang Chang         absl::StrCat(aead_name_.size(), ":", associated_data.size(), ":",
243*e7b1675dSTing-Kang Chang                      aead_name_, associated_data);
244*e7b1675dSTing-Kang Chang     if (!absl::StartsWith(ciphertext, prefix)) {
245*e7b1675dSTing-Kang Chang       return crypto::tink::util::Status(absl::StatusCode::kInvalidArgument,
246*e7b1675dSTing-Kang Chang                                         "Dummy operation failed.");
247*e7b1675dSTing-Kang Chang     }
248*e7b1675dSTing-Kang Chang     ciphertext.remove_prefix(prefix.size());
249*e7b1675dSTing-Kang Chang     return std::string(ciphertext);
250*e7b1675dSTing-Kang Chang   }
251*e7b1675dSTing-Kang Chang 
252*e7b1675dSTing-Kang Chang  private:
253*e7b1675dSTing-Kang Chang   std::string aead_name_;
254*e7b1675dSTing-Kang Chang };
255*e7b1675dSTing-Kang Chang 
256*e7b1675dSTing-Kang Chang // A dummy implementation of CordAead-interface.
257*e7b1675dSTing-Kang Chang // An instance of DummyCordAead can be identified by a name specified
258*e7b1675dSTing-Kang Chang // as a parameter of the constructor.
259*e7b1675dSTing-Kang Chang class DummyCordAead : public CordAead {
260*e7b1675dSTing-Kang Chang  public:
DummyCordAead(absl::string_view aead_name)261*e7b1675dSTing-Kang Chang   explicit DummyCordAead(absl::string_view aead_name) : aead_(aead_name) {}
262*e7b1675dSTing-Kang Chang 
263*e7b1675dSTing-Kang Chang   // Computes a dummy ciphertext, which is concatenation of provided 'plaintext'
264*e7b1675dSTing-Kang Chang   // with the name of this DummyCordAead.
Encrypt(absl::Cord plaintext,absl::Cord associated_data)265*e7b1675dSTing-Kang Chang   crypto::tink::util::StatusOr<absl::Cord> Encrypt(
266*e7b1675dSTing-Kang Chang       absl::Cord plaintext, absl::Cord associated_data) const override {
267*e7b1675dSTing-Kang Chang     auto ciphertext =
268*e7b1675dSTing-Kang Chang         aead_.Encrypt(plaintext.Flatten(), associated_data.Flatten());
269*e7b1675dSTing-Kang Chang 
270*e7b1675dSTing-Kang Chang     if (!ciphertext.ok()) return ciphertext.status();
271*e7b1675dSTing-Kang Chang 
272*e7b1675dSTing-Kang Chang     absl::Cord ciphertext_cord;
273*e7b1675dSTing-Kang Chang     ciphertext_cord.Append(ciphertext.value());
274*e7b1675dSTing-Kang Chang     return ciphertext_cord;
275*e7b1675dSTing-Kang Chang   }
276*e7b1675dSTing-Kang Chang 
Decrypt(absl::Cord ciphertext,absl::Cord associated_data)277*e7b1675dSTing-Kang Chang   crypto::tink::util::StatusOr<absl::Cord> Decrypt(
278*e7b1675dSTing-Kang Chang       absl::Cord ciphertext, absl::Cord associated_data) const override {
279*e7b1675dSTing-Kang Chang     auto plaintext =
280*e7b1675dSTing-Kang Chang         aead_.Decrypt(ciphertext.Flatten(), associated_data.Flatten());
281*e7b1675dSTing-Kang Chang 
282*e7b1675dSTing-Kang Chang     if (!plaintext.ok()) return plaintext.status();
283*e7b1675dSTing-Kang Chang 
284*e7b1675dSTing-Kang Chang     absl::Cord plaintext_cord;
285*e7b1675dSTing-Kang Chang     plaintext_cord.Append(plaintext.value());
286*e7b1675dSTing-Kang Chang     return plaintext_cord;
287*e7b1675dSTing-Kang Chang   }
288*e7b1675dSTing-Kang Chang 
289*e7b1675dSTing-Kang Chang  private:
290*e7b1675dSTing-Kang Chang   DummyAead aead_;
291*e7b1675dSTing-Kang Chang };
292*e7b1675dSTing-Kang Chang 
293*e7b1675dSTing-Kang Chang // A dummy implementation of DeterministicAead-interface.
294*e7b1675dSTing-Kang Chang // An instance of DummyDeterministicAead can be identified by a name specified
295*e7b1675dSTing-Kang Chang // as a parameter of the constructor.
296*e7b1675dSTing-Kang Chang // The implementation is the same as DummyAead.
297*e7b1675dSTing-Kang Chang class DummyDeterministicAead : public DeterministicAead {
298*e7b1675dSTing-Kang Chang  public:
DummyDeterministicAead(absl::string_view daead_name)299*e7b1675dSTing-Kang Chang   explicit DummyDeterministicAead(absl::string_view daead_name)
300*e7b1675dSTing-Kang Chang       : aead_(daead_name) {}
301*e7b1675dSTing-Kang Chang 
EncryptDeterministically(absl::string_view plaintext,absl::string_view associated_data)302*e7b1675dSTing-Kang Chang   crypto::tink::util::StatusOr<std::string> EncryptDeterministically(
303*e7b1675dSTing-Kang Chang       absl::string_view plaintext,
304*e7b1675dSTing-Kang Chang       absl::string_view associated_data) const override {
305*e7b1675dSTing-Kang Chang     return aead_.Encrypt(plaintext, associated_data);
306*e7b1675dSTing-Kang Chang   }
307*e7b1675dSTing-Kang Chang 
DecryptDeterministically(absl::string_view ciphertext,absl::string_view associated_data)308*e7b1675dSTing-Kang Chang   crypto::tink::util::StatusOr<std::string> DecryptDeterministically(
309*e7b1675dSTing-Kang Chang       absl::string_view ciphertext,
310*e7b1675dSTing-Kang Chang       absl::string_view associated_data) const override {
311*e7b1675dSTing-Kang Chang     return aead_.Decrypt(ciphertext, associated_data);
312*e7b1675dSTing-Kang Chang   }
313*e7b1675dSTing-Kang Chang 
314*e7b1675dSTing-Kang Chang  private:
315*e7b1675dSTing-Kang Chang   DummyAead aead_;
316*e7b1675dSTing-Kang Chang };
317*e7b1675dSTing-Kang Chang 
318*e7b1675dSTing-Kang Chang // A dummy implementation of StreamingAead-interface.  An instance of
319*e7b1675dSTing-Kang Chang // DummyStreamingAead can be identified by a name specified as a parameter of
320*e7b1675dSTing-Kang Chang // the constructor.  This name concatenated with 'associated_data' for a
321*e7b1675dSTing-Kang Chang // specific stream yields a header of an encrypted stream produced/consumed
322*e7b1675dSTing-Kang Chang // by DummyStreamingAead.
323*e7b1675dSTing-Kang Chang class DummyStreamingAead : public StreamingAead {
324*e7b1675dSTing-Kang Chang  public:
DummyStreamingAead(absl::string_view streaming_aead_name)325*e7b1675dSTing-Kang Chang   explicit DummyStreamingAead(absl::string_view streaming_aead_name)
326*e7b1675dSTing-Kang Chang       : streaming_aead_name_(streaming_aead_name) {}
327*e7b1675dSTing-Kang Chang 
328*e7b1675dSTing-Kang Chang   crypto::tink::util::StatusOr<std::unique_ptr<crypto::tink::OutputStream>>
NewEncryptingStream(std::unique_ptr<crypto::tink::OutputStream> ciphertext_destination,absl::string_view associated_data)329*e7b1675dSTing-Kang Chang   NewEncryptingStream(
330*e7b1675dSTing-Kang Chang       std::unique_ptr<crypto::tink::OutputStream> ciphertext_destination,
331*e7b1675dSTing-Kang Chang       absl::string_view associated_data) const override {
332*e7b1675dSTing-Kang Chang     return {absl::make_unique<DummyEncryptingStream>(
333*e7b1675dSTing-Kang Chang         std::move(ciphertext_destination),
334*e7b1675dSTing-Kang Chang         absl::StrCat(streaming_aead_name_, associated_data))};
335*e7b1675dSTing-Kang Chang   }
336*e7b1675dSTing-Kang Chang 
337*e7b1675dSTing-Kang Chang   crypto::tink::util::StatusOr<std::unique_ptr<crypto::tink::InputStream>>
NewDecryptingStream(std::unique_ptr<crypto::tink::InputStream> ciphertext_source,absl::string_view associated_data)338*e7b1675dSTing-Kang Chang   NewDecryptingStream(
339*e7b1675dSTing-Kang Chang       std::unique_ptr<crypto::tink::InputStream> ciphertext_source,
340*e7b1675dSTing-Kang Chang       absl::string_view associated_data) const override {
341*e7b1675dSTing-Kang Chang     return {absl::make_unique<DummyDecryptingStream>(
342*e7b1675dSTing-Kang Chang         std::move(ciphertext_source),
343*e7b1675dSTing-Kang Chang         absl::StrCat(streaming_aead_name_, associated_data))};
344*e7b1675dSTing-Kang Chang   }
345*e7b1675dSTing-Kang Chang 
346*e7b1675dSTing-Kang Chang   crypto::tink::util::StatusOr<
347*e7b1675dSTing-Kang Chang       std::unique_ptr<crypto::tink::RandomAccessStream>>
NewDecryptingRandomAccessStream(std::unique_ptr<crypto::tink::RandomAccessStream> ciphertext_source,absl::string_view associated_data)348*e7b1675dSTing-Kang Chang   NewDecryptingRandomAccessStream(
349*e7b1675dSTing-Kang Chang       std::unique_ptr<crypto::tink::RandomAccessStream> ciphertext_source,
350*e7b1675dSTing-Kang Chang       absl::string_view associated_data) const override {
351*e7b1675dSTing-Kang Chang     return {absl::make_unique<DummyDecryptingRandomAccessStream>(
352*e7b1675dSTing-Kang Chang         std::move(ciphertext_source),
353*e7b1675dSTing-Kang Chang         absl::StrCat(streaming_aead_name_, associated_data))};
354*e7b1675dSTing-Kang Chang   }
355*e7b1675dSTing-Kang Chang 
356*e7b1675dSTing-Kang Chang   // Upon first call to Next() writes to 'ct_dest' the specifed 'header',
357*e7b1675dSTing-Kang Chang   // and subsequently forwards all methods calls to the corresponding
358*e7b1675dSTing-Kang Chang   // methods of 'cd_dest'.
359*e7b1675dSTing-Kang Chang   class DummyEncryptingStream : public crypto::tink::OutputStream {
360*e7b1675dSTing-Kang Chang    public:
DummyEncryptingStream(std::unique_ptr<crypto::tink::OutputStream> ct_dest,absl::string_view header)361*e7b1675dSTing-Kang Chang     DummyEncryptingStream(std::unique_ptr<crypto::tink::OutputStream> ct_dest,
362*e7b1675dSTing-Kang Chang                           absl::string_view header)
363*e7b1675dSTing-Kang Chang         : ct_dest_(std::move(ct_dest)),
364*e7b1675dSTing-Kang Chang           header_(header),
365*e7b1675dSTing-Kang Chang           after_init_(false),
366*e7b1675dSTing-Kang Chang           status_(util::OkStatus()) {}
367*e7b1675dSTing-Kang Chang 
Next(void ** data)368*e7b1675dSTing-Kang Chang     crypto::tink::util::StatusOr<int> Next(void** data) override {
369*e7b1675dSTing-Kang Chang       if (!after_init_) {  // Try to initialize.
370*e7b1675dSTing-Kang Chang         after_init_ = true;
371*e7b1675dSTing-Kang Chang         auto next_result = ct_dest_->Next(data);
372*e7b1675dSTing-Kang Chang         if (!next_result.ok()) {
373*e7b1675dSTing-Kang Chang           status_ = next_result.status();
374*e7b1675dSTing-Kang Chang           return status_;
375*e7b1675dSTing-Kang Chang         }
376*e7b1675dSTing-Kang Chang         if (next_result.value() < header_.size()) {
377*e7b1675dSTing-Kang Chang           status_ =
378*e7b1675dSTing-Kang Chang               util::Status(absl::StatusCode::kInternal, "Buffer too small");
379*e7b1675dSTing-Kang Chang         } else {
380*e7b1675dSTing-Kang Chang           memcpy(*data, header_.data(), static_cast<int>(header_.size()));
381*e7b1675dSTing-Kang Chang           ct_dest_->BackUp(next_result.value() - header_.size());
382*e7b1675dSTing-Kang Chang         }
383*e7b1675dSTing-Kang Chang       }
384*e7b1675dSTing-Kang Chang       if (!status_.ok()) return status_;
385*e7b1675dSTing-Kang Chang       return ct_dest_->Next(data);
386*e7b1675dSTing-Kang Chang     }
387*e7b1675dSTing-Kang Chang 
BackUp(int count)388*e7b1675dSTing-Kang Chang     void BackUp(int count) override {
389*e7b1675dSTing-Kang Chang       if (after_init_ && status_.ok()) {
390*e7b1675dSTing-Kang Chang         ct_dest_->BackUp(count);
391*e7b1675dSTing-Kang Chang       }
392*e7b1675dSTing-Kang Chang     }
393*e7b1675dSTing-Kang Chang 
Position()394*e7b1675dSTing-Kang Chang     int64_t Position() const override {
395*e7b1675dSTing-Kang Chang       if (after_init_ && status_.ok()) {
396*e7b1675dSTing-Kang Chang         return ct_dest_->Position() - header_.size();
397*e7b1675dSTing-Kang Chang       } else {
398*e7b1675dSTing-Kang Chang         return 0;
399*e7b1675dSTing-Kang Chang       }
400*e7b1675dSTing-Kang Chang     }
Close()401*e7b1675dSTing-Kang Chang     util::Status Close() override {
402*e7b1675dSTing-Kang Chang       if (!after_init_) {  // Call Next() to write the header to ct_dest_.
403*e7b1675dSTing-Kang Chang         void* buf;
404*e7b1675dSTing-Kang Chang         auto next_result = Next(&buf);
405*e7b1675dSTing-Kang Chang         if (next_result.ok()) {
406*e7b1675dSTing-Kang Chang           BackUp(next_result.value());
407*e7b1675dSTing-Kang Chang         } else {
408*e7b1675dSTing-Kang Chang           status_ = next_result.status();
409*e7b1675dSTing-Kang Chang           return status_;
410*e7b1675dSTing-Kang Chang         }
411*e7b1675dSTing-Kang Chang       }
412*e7b1675dSTing-Kang Chang       return ct_dest_->Close();
413*e7b1675dSTing-Kang Chang     }
414*e7b1675dSTing-Kang Chang 
415*e7b1675dSTing-Kang Chang    private:
416*e7b1675dSTing-Kang Chang     std::unique_ptr<crypto::tink::OutputStream> ct_dest_;
417*e7b1675dSTing-Kang Chang     std::string header_;
418*e7b1675dSTing-Kang Chang     bool after_init_;
419*e7b1675dSTing-Kang Chang     util::Status status_;
420*e7b1675dSTing-Kang Chang   };  // class DummyEncryptingStream
421*e7b1675dSTing-Kang Chang 
422*e7b1675dSTing-Kang Chang   // Upon first call to Next() tries to read from 'ct_source' a header
423*e7b1675dSTing-Kang Chang   // that is expected to be equal to 'expected_header'.  If this
424*e7b1675dSTing-Kang Chang   // header matching succeeds, all subsequent method calls are forwarded
425*e7b1675dSTing-Kang Chang   // to the corresponding methods of 'cd_source'.
426*e7b1675dSTing-Kang Chang   class DummyDecryptingStream : public crypto::tink::InputStream {
427*e7b1675dSTing-Kang Chang    public:
DummyDecryptingStream(std::unique_ptr<crypto::tink::InputStream> ct_source,absl::string_view expected_header)428*e7b1675dSTing-Kang Chang     DummyDecryptingStream(std::unique_ptr<crypto::tink::InputStream> ct_source,
429*e7b1675dSTing-Kang Chang                           absl::string_view expected_header)
430*e7b1675dSTing-Kang Chang         : ct_source_(std::move(ct_source)),
431*e7b1675dSTing-Kang Chang           exp_header_(expected_header),
432*e7b1675dSTing-Kang Chang           after_init_(false),
433*e7b1675dSTing-Kang Chang           status_(util::OkStatus()) {}
434*e7b1675dSTing-Kang Chang 
Next(const void ** data)435*e7b1675dSTing-Kang Chang     crypto::tink::util::StatusOr<int> Next(const void** data) override {
436*e7b1675dSTing-Kang Chang       if (!after_init_) {  // Try to initialize.
437*e7b1675dSTing-Kang Chang         after_init_ = true;
438*e7b1675dSTing-Kang Chang         auto next_result = ct_source_->Next(data);
439*e7b1675dSTing-Kang Chang         if (!next_result.ok()) {
440*e7b1675dSTing-Kang Chang           status_ = next_result.status();
441*e7b1675dSTing-Kang Chang           if (status_.code() == absl::StatusCode::kOutOfRange) {
442*e7b1675dSTing-Kang Chang             status_ = util::Status(absl::StatusCode::kInvalidArgument,
443*e7b1675dSTing-Kang Chang                                    "Could not read header");
444*e7b1675dSTing-Kang Chang           }
445*e7b1675dSTing-Kang Chang           return status_;
446*e7b1675dSTing-Kang Chang         }
447*e7b1675dSTing-Kang Chang         if (next_result.value() < exp_header_.size()) {
448*e7b1675dSTing-Kang Chang           status_ =
449*e7b1675dSTing-Kang Chang               util::Status(absl::StatusCode::kInternal, "Buffer too small");
450*e7b1675dSTing-Kang Chang         } else if (memcmp((*data), exp_header_.data(),
451*e7b1675dSTing-Kang Chang                           static_cast<int>(exp_header_.size()))) {
452*e7b1675dSTing-Kang Chang           status_ = util::Status(absl::StatusCode::kInvalidArgument,
453*e7b1675dSTing-Kang Chang                                  "Corrupted header");
454*e7b1675dSTing-Kang Chang         }
455*e7b1675dSTing-Kang Chang         if (status_.ok()) {
456*e7b1675dSTing-Kang Chang           ct_source_->BackUp(next_result.value() - exp_header_.size());
457*e7b1675dSTing-Kang Chang         }
458*e7b1675dSTing-Kang Chang       }
459*e7b1675dSTing-Kang Chang       if (!status_.ok()) return status_;
460*e7b1675dSTing-Kang Chang       return ct_source_->Next(data);
461*e7b1675dSTing-Kang Chang     }
462*e7b1675dSTing-Kang Chang 
BackUp(int count)463*e7b1675dSTing-Kang Chang     void BackUp(int count) override {
464*e7b1675dSTing-Kang Chang       if (after_init_ && status_.ok()) {
465*e7b1675dSTing-Kang Chang         ct_source_->BackUp(count);
466*e7b1675dSTing-Kang Chang       }
467*e7b1675dSTing-Kang Chang     }
468*e7b1675dSTing-Kang Chang 
Position()469*e7b1675dSTing-Kang Chang     int64_t Position() const override {
470*e7b1675dSTing-Kang Chang       if (after_init_ && status_.ok()) {
471*e7b1675dSTing-Kang Chang         return ct_source_->Position() - exp_header_.size();
472*e7b1675dSTing-Kang Chang       } else {
473*e7b1675dSTing-Kang Chang         return 0;
474*e7b1675dSTing-Kang Chang       }
475*e7b1675dSTing-Kang Chang     }
476*e7b1675dSTing-Kang Chang 
477*e7b1675dSTing-Kang Chang    private:
478*e7b1675dSTing-Kang Chang     std::unique_ptr<crypto::tink::InputStream> ct_source_;
479*e7b1675dSTing-Kang Chang     std::string exp_header_;
480*e7b1675dSTing-Kang Chang     bool after_init_;
481*e7b1675dSTing-Kang Chang     util::Status status_;
482*e7b1675dSTing-Kang Chang   };  // class DummyDecryptingStream
483*e7b1675dSTing-Kang Chang 
484*e7b1675dSTing-Kang Chang   // Upon first call to PRead() tries to read from `ct_source` a header
485*e7b1675dSTing-Kang Chang   // that is expected to be equal to `expected_header`.  If this
486*e7b1675dSTing-Kang Chang   // header matching succeeds, all subsequent method calls are forwarded
487*e7b1675dSTing-Kang Chang   // to `ct_source->PRead`.
488*e7b1675dSTing-Kang Chang   class DummyDecryptingRandomAccessStream
489*e7b1675dSTing-Kang Chang       : public crypto::tink::RandomAccessStream {
490*e7b1675dSTing-Kang Chang    public:
DummyDecryptingRandomAccessStream(std::unique_ptr<crypto::tink::RandomAccessStream> ct_source,absl::string_view expected_header)491*e7b1675dSTing-Kang Chang     DummyDecryptingRandomAccessStream(
492*e7b1675dSTing-Kang Chang         std::unique_ptr<crypto::tink::RandomAccessStream> ct_source,
493*e7b1675dSTing-Kang Chang         absl::string_view expected_header)
494*e7b1675dSTing-Kang Chang         : ct_source_(std::move(ct_source)), exp_header_(expected_header) {}
495*e7b1675dSTing-Kang Chang 
PRead(int64_t position,int count,crypto::tink::util::Buffer * dest_buffer)496*e7b1675dSTing-Kang Chang     crypto::tink::util::Status PRead(
497*e7b1675dSTing-Kang Chang         int64_t position, int count,
498*e7b1675dSTing-Kang Chang         crypto::tink::util::Buffer* dest_buffer) override {
499*e7b1675dSTing-Kang Chang       util::Status status = CheckHeader();
500*e7b1675dSTing-Kang Chang       if (!status.ok()) {
501*e7b1675dSTing-Kang Chang         return status;
502*e7b1675dSTing-Kang Chang       }
503*e7b1675dSTing-Kang Chang       status = dest_buffer->set_size(0);
504*e7b1675dSTing-Kang Chang       if (!status.ok()) return status;
505*e7b1675dSTing-Kang Chang       return ct_source_->PRead(position + exp_header_.size(), count,
506*e7b1675dSTing-Kang Chang                                dest_buffer);
507*e7b1675dSTing-Kang Chang     }
508*e7b1675dSTing-Kang Chang 
size()509*e7b1675dSTing-Kang Chang     util::StatusOr<int64_t> size() override {
510*e7b1675dSTing-Kang Chang       util::Status status = CheckHeader();
511*e7b1675dSTing-Kang Chang       if (!status.ok()) {
512*e7b1675dSTing-Kang Chang         return status;
513*e7b1675dSTing-Kang Chang       }
514*e7b1675dSTing-Kang Chang       auto ct_size_result = ct_source_->size();
515*e7b1675dSTing-Kang Chang       if (!ct_size_result.ok()) return ct_size_result.status();
516*e7b1675dSTing-Kang Chang       auto pt_size = ct_size_result.value() - exp_header_.size();
517*e7b1675dSTing-Kang Chang       if (pt_size >= 0) return pt_size;
518*e7b1675dSTing-Kang Chang       return util::Status(absl::StatusCode::kUnavailable, "size not available");
519*e7b1675dSTing-Kang Chang     }
520*e7b1675dSTing-Kang Chang 
521*e7b1675dSTing-Kang Chang    private:
CheckHeader()522*e7b1675dSTing-Kang Chang     util::Status CheckHeader()
523*e7b1675dSTing-Kang Chang         ABSL_LOCKS_EXCLUDED(header_check_status_mutex_) {
524*e7b1675dSTing-Kang Chang       absl::MutexLock lock(&header_check_status_mutex_);
525*e7b1675dSTing-Kang Chang       if (header_check_status_.code() != absl::StatusCode::kUnavailable) {
526*e7b1675dSTing-Kang Chang         return header_check_status_;
527*e7b1675dSTing-Kang Chang       }
528*e7b1675dSTing-Kang Chang       auto buf = std::move(util::Buffer::New(exp_header_.size()).value());
529*e7b1675dSTing-Kang Chang       header_check_status_ =
530*e7b1675dSTing-Kang Chang           ct_source_->PRead(0, exp_header_.size(), buf.get());
531*e7b1675dSTing-Kang Chang       if (!header_check_status_.ok() &&
532*e7b1675dSTing-Kang Chang           header_check_status_.code() != absl::StatusCode::kOutOfRange) {
533*e7b1675dSTing-Kang Chang         return header_check_status_;
534*e7b1675dSTing-Kang Chang       }
535*e7b1675dSTing-Kang Chang       // EOF or Ok indicate a valid read has happened.
536*e7b1675dSTing-Kang Chang       header_check_status_ = util::OkStatus();
537*e7b1675dSTing-Kang Chang       // Invalid header.
538*e7b1675dSTing-Kang Chang       if (buf->size() < exp_header_.size()) {
539*e7b1675dSTing-Kang Chang         header_check_status_ = util::Status(absl::StatusCode::kInvalidArgument,
540*e7b1675dSTing-Kang Chang                                "Could not read header");
541*e7b1675dSTing-Kang Chang       } else if (memcmp(buf->get_mem_block(), exp_header_.data(),
542*e7b1675dSTing-Kang Chang                         static_cast<int>(exp_header_.size()))) {
543*e7b1675dSTing-Kang Chang         header_check_status_ = util::Status(absl::StatusCode::kInvalidArgument,
544*e7b1675dSTing-Kang Chang                                "Corrupted header");
545*e7b1675dSTing-Kang Chang       }
546*e7b1675dSTing-Kang Chang       return header_check_status_;
547*e7b1675dSTing-Kang Chang     }
548*e7b1675dSTing-Kang Chang 
549*e7b1675dSTing-Kang Chang     std::unique_ptr<crypto::tink::RandomAccessStream> ct_source_;
550*e7b1675dSTing-Kang Chang     std::string exp_header_;
551*e7b1675dSTing-Kang Chang     mutable absl::Mutex header_check_status_mutex_;
552*e7b1675dSTing-Kang Chang     util::Status header_check_status_
553*e7b1675dSTing-Kang Chang         ABSL_GUARDED_BY(header_check_status_mutex_) =
554*e7b1675dSTing-Kang Chang             util::Status(absl::StatusCode::kUnavailable, "Uninitialized");
555*e7b1675dSTing-Kang Chang   };  // class DummyDecryptingRandomAccessStream
556*e7b1675dSTing-Kang Chang 
557*e7b1675dSTing-Kang Chang  private:
558*e7b1675dSTing-Kang Chang   std::string streaming_aead_name_;
559*e7b1675dSTing-Kang Chang };  // class DummyStreamingAead
560*e7b1675dSTing-Kang Chang 
561*e7b1675dSTing-Kang Chang // A dummy implementation of HybridEncrypt-interface.
562*e7b1675dSTing-Kang Chang // An instance of DummyHybridEncrypt can be identified by a name specified
563*e7b1675dSTing-Kang Chang // as a parameter of the constructor.
564*e7b1675dSTing-Kang Chang class DummyHybridEncrypt : public HybridEncrypt {
565*e7b1675dSTing-Kang Chang  public:
DummyHybridEncrypt(absl::string_view hybrid_name)566*e7b1675dSTing-Kang Chang   explicit DummyHybridEncrypt(absl::string_view hybrid_name)
567*e7b1675dSTing-Kang Chang       : dummy_aead_(absl::StrCat("DummyHybrid:", hybrid_name)) {}
568*e7b1675dSTing-Kang Chang 
569*e7b1675dSTing-Kang Chang   // Computes a dummy ciphertext, which is concatenation of provided 'plaintext'
570*e7b1675dSTing-Kang Chang   // with the name of this DummyHybridEncrypt.
Encrypt(absl::string_view plaintext,absl::string_view context_info)571*e7b1675dSTing-Kang Chang   crypto::tink::util::StatusOr<std::string> Encrypt(
572*e7b1675dSTing-Kang Chang       absl::string_view plaintext,
573*e7b1675dSTing-Kang Chang       absl::string_view context_info) const override {
574*e7b1675dSTing-Kang Chang     return dummy_aead_.Encrypt(plaintext, context_info);
575*e7b1675dSTing-Kang Chang   }
576*e7b1675dSTing-Kang Chang 
577*e7b1675dSTing-Kang Chang  private:
578*e7b1675dSTing-Kang Chang   DummyAead dummy_aead_;
579*e7b1675dSTing-Kang Chang };
580*e7b1675dSTing-Kang Chang 
581*e7b1675dSTing-Kang Chang // A dummy implementation of HybridDecrypt-interface.
582*e7b1675dSTing-Kang Chang // An instance of DummyHybridDecrypt can be identified by a name specified
583*e7b1675dSTing-Kang Chang // as a parameter of the constructor.
584*e7b1675dSTing-Kang Chang class DummyHybridDecrypt : public HybridDecrypt {
585*e7b1675dSTing-Kang Chang  public:
DummyHybridDecrypt(absl::string_view hybrid_name)586*e7b1675dSTing-Kang Chang   explicit DummyHybridDecrypt(absl::string_view hybrid_name)
587*e7b1675dSTing-Kang Chang       : dummy_aead_(absl::StrCat("DummyHybrid:", hybrid_name)) {}
588*e7b1675dSTing-Kang Chang 
589*e7b1675dSTing-Kang Chang   // Decrypts a dummy ciphertext, which should be a concatenation
590*e7b1675dSTing-Kang Chang   // of a plaintext with the name of this DummyHybridDecrypt.
Decrypt(absl::string_view ciphertext,absl::string_view context_info)591*e7b1675dSTing-Kang Chang   crypto::tink::util::StatusOr<std::string> Decrypt(
592*e7b1675dSTing-Kang Chang       absl::string_view ciphertext,
593*e7b1675dSTing-Kang Chang       absl::string_view context_info) const override {
594*e7b1675dSTing-Kang Chang     return dummy_aead_.Decrypt(ciphertext, context_info);
595*e7b1675dSTing-Kang Chang   }
596*e7b1675dSTing-Kang Chang 
597*e7b1675dSTing-Kang Chang  private:
598*e7b1675dSTing-Kang Chang   DummyAead dummy_aead_;
599*e7b1675dSTing-Kang Chang };
600*e7b1675dSTing-Kang Chang 
601*e7b1675dSTing-Kang Chang // A dummy implementation of PublicKeySign-interface.
602*e7b1675dSTing-Kang Chang // An instance of DummyPublicKeySign can be identified by a name specified
603*e7b1675dSTing-Kang Chang // as a parameter of the constructor.
604*e7b1675dSTing-Kang Chang class DummyPublicKeySign : public PublicKeySign {
605*e7b1675dSTing-Kang Chang  public:
DummyPublicKeySign(absl::string_view signature_name)606*e7b1675dSTing-Kang Chang   explicit DummyPublicKeySign(absl::string_view signature_name)
607*e7b1675dSTing-Kang Chang       : dummy_aead_(absl::StrCat("DummySign:", signature_name)) {}
608*e7b1675dSTing-Kang Chang 
609*e7b1675dSTing-Kang Chang   // Computes a dummy signature, which is a concatenation of 'data'
610*e7b1675dSTing-Kang Chang   // with the name of this DummyPublicKeySign.
Sign(absl::string_view data)611*e7b1675dSTing-Kang Chang   crypto::tink::util::StatusOr<std::string> Sign(
612*e7b1675dSTing-Kang Chang       absl::string_view data) const override {
613*e7b1675dSTing-Kang Chang     return dummy_aead_.Encrypt("", data);
614*e7b1675dSTing-Kang Chang   }
615*e7b1675dSTing-Kang Chang 
616*e7b1675dSTing-Kang Chang  private:
617*e7b1675dSTing-Kang Chang   DummyAead dummy_aead_;
618*e7b1675dSTing-Kang Chang };
619*e7b1675dSTing-Kang Chang 
620*e7b1675dSTing-Kang Chang // A dummy implementation of PublicKeyVerify-interface.
621*e7b1675dSTing-Kang Chang // An instance of DummyPublicKeyVerify can be identified by a name specified
622*e7b1675dSTing-Kang Chang // as a parameter of the constructor.
623*e7b1675dSTing-Kang Chang class DummyPublicKeyVerify : public PublicKeyVerify {
624*e7b1675dSTing-Kang Chang  public:
DummyPublicKeyVerify(absl::string_view signature_name)625*e7b1675dSTing-Kang Chang   explicit DummyPublicKeyVerify(absl::string_view signature_name)
626*e7b1675dSTing-Kang Chang       : dummy_aead_(absl::StrCat("DummySign:", signature_name)) {}
627*e7b1675dSTing-Kang Chang 
628*e7b1675dSTing-Kang Chang   // Verifies a dummy signature, should be a concatenation of the name
629*e7b1675dSTing-Kang Chang   // of this DummyPublicKeyVerify with the provided 'data'.
Verify(absl::string_view signature,absl::string_view data)630*e7b1675dSTing-Kang Chang   crypto::tink::util::Status Verify(absl::string_view signature,
631*e7b1675dSTing-Kang Chang                                     absl::string_view data) const override {
632*e7b1675dSTing-Kang Chang     return dummy_aead_.Decrypt(signature, data).status();
633*e7b1675dSTing-Kang Chang   }
634*e7b1675dSTing-Kang Chang 
635*e7b1675dSTing-Kang Chang  private:
636*e7b1675dSTing-Kang Chang   DummyAead dummy_aead_;
637*e7b1675dSTing-Kang Chang };
638*e7b1675dSTing-Kang Chang 
639*e7b1675dSTing-Kang Chang // A dummy implementation of Mac-interface.
640*e7b1675dSTing-Kang Chang // An instance of DummyMac can be identified by a name specified
641*e7b1675dSTing-Kang Chang // as a parameter of the constructor.
642*e7b1675dSTing-Kang Chang class DummyMac : public Mac {
643*e7b1675dSTing-Kang Chang  public:
DummyMac(const std::string & mac_name)644*e7b1675dSTing-Kang Chang   explicit DummyMac(const std::string& mac_name)
645*e7b1675dSTing-Kang Chang       : dummy_aead_(absl::StrCat("DummyMac:", mac_name)) {}
646*e7b1675dSTing-Kang Chang 
647*e7b1675dSTing-Kang Chang   // Computes a dummy MAC, which is concatenation of provided 'data'
648*e7b1675dSTing-Kang Chang   // with the name of this DummyMac.
ComputeMac(absl::string_view data)649*e7b1675dSTing-Kang Chang   crypto::tink::util::StatusOr<std::string> ComputeMac(
650*e7b1675dSTing-Kang Chang       absl::string_view data) const override {
651*e7b1675dSTing-Kang Chang     return dummy_aead_.Encrypt("", data);
652*e7b1675dSTing-Kang Chang   }
653*e7b1675dSTing-Kang Chang 
VerifyMac(absl::string_view mac,absl::string_view data)654*e7b1675dSTing-Kang Chang   crypto::tink::util::Status VerifyMac(absl::string_view mac,
655*e7b1675dSTing-Kang Chang                                        absl::string_view data) const override {
656*e7b1675dSTing-Kang Chang     return dummy_aead_.Decrypt(mac, data).status();
657*e7b1675dSTing-Kang Chang   }
658*e7b1675dSTing-Kang Chang 
659*e7b1675dSTing-Kang Chang  private:
660*e7b1675dSTing-Kang Chang   DummyAead dummy_aead_;
661*e7b1675dSTing-Kang Chang };
662*e7b1675dSTing-Kang Chang 
663*e7b1675dSTing-Kang Chang // A dummy implementation of Stateful Mac interface.
664*e7b1675dSTing-Kang Chang // An instance of DummyStatefulMac can be identified by a name specified
665*e7b1675dSTing-Kang Chang // as a parameter of the constructor.
666*e7b1675dSTing-Kang Chang // Over the same inputs, the DummyStatefulMac and DummyMac should give the same
667*e7b1675dSTing-Kang Chang // output; DummyStatefulMac builds and internal_state_ and calls DummyMac.
668*e7b1675dSTing-Kang Chang class DummyStatefulMac : public subtle::StatefulMac {
669*e7b1675dSTing-Kang Chang  public:
DummyStatefulMac(const std::string & mac_name)670*e7b1675dSTing-Kang Chang   explicit DummyStatefulMac(const std::string& mac_name)
671*e7b1675dSTing-Kang Chang       : dummy_aead_(absl::StrCat("DummyMac:", mac_name)), buffer_("") {}
672*e7b1675dSTing-Kang Chang 
Update(absl::string_view data)673*e7b1675dSTing-Kang Chang   util::Status Update(absl::string_view data) override {
674*e7b1675dSTing-Kang Chang     absl::StrAppend(&buffer_, data);
675*e7b1675dSTing-Kang Chang     return util::OkStatus();
676*e7b1675dSTing-Kang Chang   }
Finalize()677*e7b1675dSTing-Kang Chang   util::StatusOr<std::string> Finalize() override {
678*e7b1675dSTing-Kang Chang     return dummy_aead_.Encrypt("", buffer_);
679*e7b1675dSTing-Kang Chang   }
680*e7b1675dSTing-Kang Chang 
681*e7b1675dSTing-Kang Chang  private:
682*e7b1675dSTing-Kang Chang   DummyAead dummy_aead_;
683*e7b1675dSTing-Kang Chang   std::string buffer_;
684*e7b1675dSTing-Kang Chang };
685*e7b1675dSTing-Kang Chang 
686*e7b1675dSTing-Kang Chang // A dummy implementation of KeysetWriter-interface.
687*e7b1675dSTing-Kang Chang class DummyKeysetWriter : public KeysetWriter {
688*e7b1675dSTing-Kang Chang  public:
New(std::unique_ptr<std::ostream> destination_stream)689*e7b1675dSTing-Kang Chang   static crypto::tink::util::StatusOr<std::unique_ptr<DummyKeysetWriter>> New(
690*e7b1675dSTing-Kang Chang       std::unique_ptr<std::ostream> destination_stream) {
691*e7b1675dSTing-Kang Chang     std::unique_ptr<DummyKeysetWriter> writer(
692*e7b1675dSTing-Kang Chang         new DummyKeysetWriter(std::move(destination_stream)));
693*e7b1675dSTing-Kang Chang     return std::move(writer);
694*e7b1675dSTing-Kang Chang   }
695*e7b1675dSTing-Kang Chang 
Write(const google::crypto::tink::Keyset & keyset)696*e7b1675dSTing-Kang Chang   crypto::tink::util::Status Write(
697*e7b1675dSTing-Kang Chang       const google::crypto::tink::Keyset& keyset) override {
698*e7b1675dSTing-Kang Chang     return crypto::tink::util::OkStatus();
699*e7b1675dSTing-Kang Chang   }
700*e7b1675dSTing-Kang Chang 
Write(const google::crypto::tink::EncryptedKeyset & encrypted_keyset)701*e7b1675dSTing-Kang Chang   crypto::tink::util::Status Write(
702*e7b1675dSTing-Kang Chang       const google::crypto::tink::EncryptedKeyset& encrypted_keyset) override {
703*e7b1675dSTing-Kang Chang     return crypto::tink::util::OkStatus();
704*e7b1675dSTing-Kang Chang   }
705*e7b1675dSTing-Kang Chang 
706*e7b1675dSTing-Kang Chang  private:
DummyKeysetWriter(std::unique_ptr<std::ostream> destination_stream)707*e7b1675dSTing-Kang Chang   explicit DummyKeysetWriter(std::unique_ptr<std::ostream> destination_stream)
708*e7b1675dSTing-Kang Chang       : destination_stream_(std::move(destination_stream)) {}
709*e7b1675dSTing-Kang Chang 
710*e7b1675dSTing-Kang Chang   std::unique_ptr<std::ostream> destination_stream_;
711*e7b1675dSTing-Kang Chang };
712*e7b1675dSTing-Kang Chang 
713*e7b1675dSTing-Kang Chang // A dummy implementation of KmsClient-interface.
714*e7b1675dSTing-Kang Chang class DummyKmsClient : public KmsClient {
715*e7b1675dSTing-Kang Chang  public:
DummyKmsClient(absl::string_view uri_prefix,absl::string_view key_uri)716*e7b1675dSTing-Kang Chang   DummyKmsClient(absl::string_view uri_prefix, absl::string_view key_uri)
717*e7b1675dSTing-Kang Chang       : uri_prefix_(uri_prefix), key_uri_(key_uri) {}
718*e7b1675dSTing-Kang Chang 
DoesSupport(absl::string_view key_uri)719*e7b1675dSTing-Kang Chang   bool DoesSupport(absl::string_view key_uri) const override {
720*e7b1675dSTing-Kang Chang     if (key_uri.empty()) return false;
721*e7b1675dSTing-Kang Chang     if (key_uri_.empty()) return absl::StartsWith(key_uri, uri_prefix_);
722*e7b1675dSTing-Kang Chang     return key_uri == key_uri_;
723*e7b1675dSTing-Kang Chang   }
724*e7b1675dSTing-Kang Chang 
GetAead(absl::string_view key_uri)725*e7b1675dSTing-Kang Chang   crypto::tink::util::StatusOr<std::unique_ptr<Aead>> GetAead(
726*e7b1675dSTing-Kang Chang       absl::string_view key_uri) const override {
727*e7b1675dSTing-Kang Chang     if (!DoesSupport(key_uri))
728*e7b1675dSTing-Kang Chang       return crypto::tink::util::Status(absl::StatusCode::kInvalidArgument,
729*e7b1675dSTing-Kang Chang                                         "key_uri not supported");
730*e7b1675dSTing-Kang Chang     return {absl::make_unique<DummyAead>(key_uri)};
731*e7b1675dSTing-Kang Chang   }
732*e7b1675dSTing-Kang Chang 
733*e7b1675dSTing-Kang Chang   ~DummyKmsClient() override = default;
734*e7b1675dSTing-Kang Chang 
735*e7b1675dSTing-Kang Chang  private:
736*e7b1675dSTing-Kang Chang   std::string uri_prefix_;
737*e7b1675dSTing-Kang Chang   std::string key_uri_;
738*e7b1675dSTing-Kang Chang };
739*e7b1675dSTing-Kang Chang 
740*e7b1675dSTing-Kang Chang }  // namespace test
741*e7b1675dSTing-Kang Chang }  // namespace tink
742*e7b1675dSTing-Kang Chang }  // namespace crypto
743*e7b1675dSTing-Kang Chang 
744*e7b1675dSTing-Kang Chang #endif  // TINK_UTIL_TEST_UTIL_H_
745