1 // Copyright 2021 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 ///////////////////////////////////////////////////////////////////////////////
16
17 #include "tink/experimental/pqcrypto/kem/cecpq2_aead_hkdf_dem_helper.h"
18
19 #include <memory>
20 #include <sstream>
21 #include <string>
22 #include <utility>
23
24 #include "absl/memory/memory.h"
25 #include "absl/status/status.h"
26 #include "tink/aead.h"
27 #include "tink/deterministic_aead.h"
28 #include "tink/registry.h"
29 #include "tink/util/errors.h"
30 #include "tink/util/istream_input_stream.h"
31 #include "tink/util/protobuf_helper.h"
32 #include "tink/util/secret_data.h"
33 #include "tink/util/statusor.h"
34 #include "proto/tink.pb.h"
35
36 namespace crypto {
37 namespace tink {
38 namespace {
39
40 using ::crypto::tink::subtle::AeadOrDaead;
41 using ::google::crypto::tink::KeyTemplate;
42
43 // Internal implementaton of the Cecpq2AeadHkdfDemHelper class, parametrized by
44 // the Primitive used for data encapsulation (i.e Aead or DeterministicAead).
45 template <class EncryptionPrimitive>
46 class Cecpq2AeadHkdfDemHelperImpl : public Cecpq2AeadHkdfDemHelper {
47 public:
Cecpq2AeadHkdfDemHelperImpl(const google::crypto::tink::KeyTemplate & key_template)48 explicit Cecpq2AeadHkdfDemHelperImpl(
49 const google::crypto::tink::KeyTemplate& key_template)
50 : key_template_(key_template) {}
51
52 crypto::tink::util::StatusOr<
53 std::unique_ptr<crypto::tink::subtle::AeadOrDaead>>
GetAeadOrDaead(const util::SecretData & seed) const54 GetAeadOrDaead(const util::SecretData& seed) const override {
55 if (seed.size() < 32) {
56 return util::Status(absl::StatusCode::kInternal,
57 "Seed length is smaller than 32 bytes "
58 "and thus not post-quantum secure.");
59 }
60 std::string seed_str(util::SecretDataAsStringView(seed));
61 util::IstreamInputStream input_stream{
62 absl::make_unique<std::stringstream>(seed_str)};
63 auto key_or = internal::RegistryImpl::GlobalInstance().DeriveKey(
64 key_template_, &input_stream);
65 if (!key_or.ok()) return key_or.status();
66 auto key = std::move(key_or).value();
67 util::StatusOr<std::unique_ptr<EncryptionPrimitive>> primitive_or =
68 Registry::GetPrimitive<EncryptionPrimitive>(key);
69 if (!primitive_or.ok()) return primitive_or.status();
70 return absl::make_unique<AeadOrDaead>(std::move(primitive_or.value()));
71 }
72
GetKeyMaterialSize() const73 crypto::tink::util::StatusOr<uint32_t> GetKeyMaterialSize() const override {
74 absl::string_view dem_type_url = key_template_.type_url();
75 // For AES-SIV, two keys of 32 bytes each are needed
76 if (dem_type_url == "type.googleapis.com/google.crypto.tink.AesSivKey") {
77 return 64;
78 } else if (
79 dem_type_url == "type.googleapis.com/google.crypto.tink.AesGcmKey" ||
80 dem_type_url ==
81 "type.googleapis.com/google.crypto.tink.XChaCha20Poly1305Key") {
82 return 32;
83 } else {
84 return ToStatusF(absl::StatusCode::kInvalidArgument,
85 "Unsupported DEM key type '%s'.", dem_type_url);
86 }
87 }
88
89 private:
90 const google::crypto::tink::KeyTemplate key_template_;
91 };
92 } // namespace
93
94 // static
95 util::StatusOr<std::unique_ptr<const Cecpq2AeadHkdfDemHelper>>
New(const KeyTemplate & dem_key_template)96 Cecpq2AeadHkdfDemHelper::New(const KeyTemplate& dem_key_template) {
97 const std::string& dem_type_url = dem_key_template.type_url();
98 if (dem_type_url == "type.googleapis.com/google.crypto.tink.AesGcmKey" ||
99 dem_type_url ==
100 "type.googleapis.com/google.crypto.tink.XChaCha20Poly1305Key") {
101 return {
102 absl::make_unique<Cecpq2AeadHkdfDemHelperImpl<Aead>>(dem_key_template)};
103 } else if (dem_type_url ==
104 "type.googleapis.com/google.crypto.tink.AesSivKey") {
105 return {absl::make_unique<Cecpq2AeadHkdfDemHelperImpl<DeterministicAead>>(
106 dem_key_template)};
107 }
108 return ToStatusF(absl::StatusCode::kInvalidArgument,
109 "Unsupported DEM key type '%s'.", dem_type_url);
110 }
111
112 } // namespace tink
113 } // namespace crypto
114