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