xref: /aosp_15_r20/external/tink/cc/hybrid/ecies_aead_hkdf_dem_helper.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1 // Copyright 2017 Google Inc.
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/hybrid/ecies_aead_hkdf_dem_helper.h"
18 
19 #include <stdint.h>
20 
21 #include <memory>
22 #include <string>
23 #include <utility>
24 
25 #include "absl/memory/memory.h"
26 #include "absl/status/status.h"
27 #include "absl/status/statusor.h"
28 #include "absl/strings/string_view.h"
29 #include "tink/aead.h"
30 #include "tink/aead/aes_ctr_hmac_aead_key_manager.h"
31 #include "tink/deterministic_aead.h"
32 #include "tink/subtle/aes_gcm_boringssl.h"
33 #include "tink/subtle/aes_siv_boringssl.h"
34 #include "tink/subtle/xchacha20_poly1305_boringssl.h"
35 #include "tink/util/errors.h"
36 #include "tink/util/protobuf_helper.h"
37 #include "tink/util/statusor.h"
38 #include "proto/aes_ctr.pb.h"
39 #include "proto/aes_ctr_hmac_aead.pb.h"
40 #include "proto/aes_gcm.pb.h"
41 #include "proto/aes_siv.pb.h"
42 #include "proto/hmac.pb.h"
43 #include "proto/tink.pb.h"
44 #include "proto/xchacha20_poly1305.pb.h"
45 
46 namespace crypto {
47 namespace tink {
48 namespace {
49 
50 using ::crypto::tink::subtle::AeadOrDaead;
51 using ::google::crypto::tink::AesCtrHmacAeadKey;
52 using ::google::crypto::tink::AesCtrHmacAeadKeyFormat;
53 using ::google::crypto::tink::AesGcmKeyFormat;
54 using ::google::crypto::tink::AesSivKeyFormat;
55 using ::google::crypto::tink::KeyTemplate;
56 using ::google::crypto::tink::XChaCha20Poly1305KeyFormat;
57 
Wrap(crypto::tink::util::StatusOr<std::unique_ptr<crypto::tink::Aead>> aead_or)58 crypto::tink::util::StatusOr<std::unique_ptr<AeadOrDaead>> Wrap(
59     crypto::tink::util::StatusOr<std::unique_ptr<crypto::tink::Aead>> aead_or) {
60   if (!aead_or.ok()) {
61     return aead_or.status();
62   }
63   return std::make_unique<AeadOrDaead>(std::move(aead_or.value()));
64 }
65 
Wrap(crypto::tink::util::StatusOr<std::unique_ptr<crypto::tink::DeterministicAead>> daead_or)66 crypto::tink::util::StatusOr<std::unique_ptr<AeadOrDaead>> Wrap(
67     crypto::tink::util::StatusOr<
68         std::unique_ptr<crypto::tink::DeterministicAead>>
69         daead_or) {
70   if (!daead_or.ok()) {
71     return daead_or.status();
72   }
73   return std::make_unique<AeadOrDaead>(std::move(daead_or.value()));
74 }
75 
76 }  // namespace
77 
78 util::StatusOr<EciesAeadHkdfDemHelper::DemKeyParams>
GetKeyParams(const KeyTemplate & key_template)79 EciesAeadHkdfDemHelper::GetKeyParams(const KeyTemplate& key_template) {
80   const std::string& type_url = key_template.type_url();
81   if (type_url == "type.googleapis.com/google.crypto.tink.AesGcmKey") {
82     AesGcmKeyFormat key_format;
83     if (!key_format.ParseFromString(key_template.value())) {
84       return util::Status(absl::StatusCode::kInvalidArgument,
85                           "Invalid AesGcmKeyFormat in DEM key template");
86     }
87     return {{AES_GCM_KEY, key_format.key_size()}};
88   }
89   if (type_url == "type.googleapis.com/google.crypto.tink.AesCtrHmacAeadKey") {
90     AesCtrHmacAeadKeyFormat key_format;
91     if (!key_format.ParseFromString(key_template.value())) {
92       return util::Status(absl::StatusCode::kInvalidArgument,
93                           "Invalid AesCtrHmacKeyFormat in DEM key template");
94     }
95     uint32_t dem_key_size = key_format.aes_ctr_key_format().key_size() +
96                             key_format.hmac_key_format().key_size();
97     return {{AES_CTR_HMAC_AEAD_KEY, dem_key_size,
98              key_format.aes_ctr_key_format().key_size(),
99              key_format.aes_ctr_key_format().params().iv_size(),
100              key_format.hmac_key_format().params().hash(),
101              key_format.hmac_key_format().params().tag_size()}};
102   }
103   if (type_url ==
104       "type.googleapis.com/google.crypto.tink.XChaCha20Poly1305Key") {
105     if (!XChaCha20Poly1305KeyFormat().ParseFromString(key_template.value())) {
106       return util::Status(absl::StatusCode::kInvalidArgument,
107                           "Invalid XChaCha20KeyFormat in DEM key template");
108     }
109     return {{XCHACHA20_POLY1305_KEY, 32}};
110   }
111   if (type_url == "type.googleapis.com/google.crypto.tink.AesSivKey") {
112     AesSivKeyFormat key_format;
113 
114     if (!key_format.ParseFromString(key_template.value())) {
115       return util::Status(absl::StatusCode::kInvalidArgument,
116                           "Invalid AesSiveKeyFormat in DEM key template");
117     }
118     return {{AES_SIV_KEY, key_format.key_size()}};
119   }
120   return ToStatusF(absl::StatusCode::kInvalidArgument,
121                    "Unsupported DEM key type '%s'.", type_url);
122 }
123 
124 // static
125 util::StatusOr<std::unique_ptr<const EciesAeadHkdfDemHelper>>
New(const KeyTemplate & dem_key_template)126 EciesAeadHkdfDemHelper::New(const KeyTemplate& dem_key_template) {
127   auto key_params_or = GetKeyParams(dem_key_template);
128   if (!key_params_or.ok()) return key_params_or.status();
129   DemKeyParams key_params = key_params_or.value();
130   return absl::WrapUnique<const EciesAeadHkdfDemHelper>(
131       new EciesAeadHkdfDemHelper(dem_key_template, key_params));
132 }
133 
134 crypto::tink::util::StatusOr<std::unique_ptr<AeadOrDaead>>
GetAeadOrDaead(const util::SecretData & symmetric_key_value) const135 EciesAeadHkdfDemHelper::GetAeadOrDaead(
136     const util::SecretData& symmetric_key_value) const {
137   if (symmetric_key_value.size() != key_params_.key_size_in_bytes) {
138     return util::Status(absl::StatusCode::kInternal,
139                         "Wrong length of symmetric key.");
140   }
141   switch (key_params_.key_type) {
142     case AES_GCM_KEY:
143       return Wrap(subtle::AesGcmBoringSsl::New(symmetric_key_value));
144     case AES_CTR_HMAC_AEAD_KEY: {
145       AesCtrHmacAeadKey key;
146       auto aes_ctr_key = key.mutable_aes_ctr_key();
147       aes_ctr_key->mutable_params()->set_iv_size(
148           key_params_.aes_ctr_key_iv_size_in_bytes);
149       aes_ctr_key->set_key_value(
150           std::string(util::SecretDataAsStringView(symmetric_key_value)
151                           .substr(0, key_params_.aes_ctr_key_size_in_bytes)));
152       auto hmac_key = key.mutable_hmac_key();
153       hmac_key->mutable_params()->set_tag_size(
154           key_params_.hmac_key_tag_size_in_bytes);
155       hmac_key->mutable_params()->set_hash(key_params_.hmac_key_hash);
156       hmac_key->set_key_value(
157           std::string(util::SecretDataAsStringView(symmetric_key_value)
158                           .substr(key_params_.aes_ctr_key_size_in_bytes)));
159       return Wrap(AesCtrHmacAeadKeyManager().GetPrimitive<Aead>(key));
160     }
161     case XCHACHA20_POLY1305_KEY:
162       return Wrap(subtle::XChacha20Poly1305BoringSsl::New(symmetric_key_value));
163     case AES_SIV_KEY:
164       return Wrap(subtle::AesSivBoringSsl::New(symmetric_key_value));
165   }
166 }
167 
168 }  // namespace tink
169 }  // namespace crypto
170