• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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