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