xref: /aosp_15_r20/external/tink/cc/hybrid/internal/hpke_decrypt.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
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/hybrid/internal/hpke_decrypt.h"
18 
19 #include <memory>
20 #include <string>
21 #include <utility>
22 
23 #include "absl/status/status.h"
24 #include "tink/hybrid/internal/hpke_context.h"
25 #include "tink/hybrid/internal/hpke_util.h"
26 #include "tink/util/secret_data.h"
27 #include "tink/util/status.h"
28 #include "tink/util/statusor.h"
29 #include "proto/hpke.pb.h"
30 
31 namespace crypto {
32 namespace tink {
33 namespace {
34 
35 using ::google::crypto::tink::HpkePrivateKey;
36 
37 }  // namespace
38 
New(const HpkePrivateKey & recipient_private_key)39 util::StatusOr<std::unique_ptr<HybridDecrypt>> HpkeDecrypt::New(
40     const HpkePrivateKey& recipient_private_key) {
41   if (recipient_private_key.private_key().empty()) {
42     return util::Status(absl::StatusCode::kInvalidArgument,
43                         "Recipient private key is empty.");
44   }
45   if (!recipient_private_key.has_public_key()) {
46     return util::Status(absl::StatusCode::kInvalidArgument,
47                         "Recipient private key is missing public key.");
48   }
49   if (!recipient_private_key.public_key().has_params()) {
50     return util::Status(absl::StatusCode::kInvalidArgument,
51                         "Recipient private key is missing HPKE parameters.");
52   }
53   return {absl::WrapUnique(new HpkeDecrypt(
54       recipient_private_key.public_key().params(),
55       util::SecretDataFromStringView(recipient_private_key.private_key())))};
56 }
57 
Decrypt(absl::string_view ciphertext,absl::string_view context_info) const58 util::StatusOr<std::string> HpkeDecrypt::Decrypt(
59     absl::string_view ciphertext, absl::string_view context_info) const {
60   util::StatusOr<int32_t> encoding_size =
61       internal::HpkeEncapsulatedKeyLength(hpke_params_.kem());
62   if (!encoding_size.ok()) return encoding_size.status();
63 
64   // Verify that ciphertext length is at least the encapsulated key length.
65   if (ciphertext.size() < *encoding_size) {
66     return util::Status(absl::StatusCode::kInvalidArgument,
67                         "Ciphertext is too short.");
68   }
69   absl::string_view encapsulated_key = ciphertext.substr(0, *encoding_size);
70   absl::string_view ciphertext_payload = ciphertext.substr(*encoding_size);
71 
72   util::StatusOr<internal::HpkeParams> params =
73       internal::HpkeParamsProtoToStruct(hpke_params_);
74   if (!params.ok()) return params.status();
75 
76   util::StatusOr<std::unique_ptr<internal::HpkeContext>> recipient_context =
77       internal::HpkeContext::SetupRecipient(*params, recipient_private_key_,
78                                             encapsulated_key, context_info);
79   if (!recipient_context.ok()) return recipient_context.status();
80 
81   return (*recipient_context)->Open(ciphertext_payload, /*associated_data=*/"");
82 }
83 
84 }  // namespace tink
85 }  // namespace crypto
86