1 // Copyright 2022 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_context.h"
18
19 #include <memory>
20 #include <string>
21 #include <utility>
22
23 #include "absl/status/status.h"
24 #include "absl/strings/string_view.h"
25 #include "tink/hybrid/internal/hpke_context_boringssl.h"
26 #include "tink/util/secret_data.h"
27 #include "tink/util/status.h"
28 #include "tink/util/statusor.h"
29
30 namespace crypto {
31 namespace tink {
32 namespace internal {
33
34 constexpr int kX25519KemEncodingLengthInBytes = 32;
35
ConcatenatePayload(absl::string_view encapsulated_key,absl::string_view ciphertext)36 std::string ConcatenatePayload(absl::string_view encapsulated_key,
37 absl::string_view ciphertext) {
38 return absl::StrCat(encapsulated_key, ciphertext);
39 }
40
SplitPayload(const HpkeKem & kem,absl::string_view payload)41 util::StatusOr<HpkePayloadView> SplitPayload(const HpkeKem& kem,
42 absl::string_view payload) {
43 if (kem == HpkeKem::kX25519HkdfSha256) {
44 return HpkePayloadView(payload.substr(0, kX25519KemEncodingLengthInBytes),
45 payload.substr(kX25519KemEncodingLengthInBytes));
46 }
47 return util::Status(
48 absl::StatusCode::kInvalidArgument,
49 absl::StrCat("Unable to split HPKE payload for KEM type ", kem));
50 }
51
SetupSender(const HpkeParams & params,absl::string_view recipient_public_key,absl::string_view info)52 util::StatusOr<std::unique_ptr<HpkeContext>> HpkeContext::SetupSender(
53 const HpkeParams& params, absl::string_view recipient_public_key,
54 absl::string_view info) {
55 if (recipient_public_key.empty()) {
56 return util::Status(absl::StatusCode::kInvalidArgument,
57 "Recipient public key is empty.");
58 }
59 util::StatusOr<SenderHpkeContextBoringSsl> sender_context =
60 HpkeContextBoringSsl::SetupSender(params, recipient_public_key, info);
61 if (!sender_context.ok()) {
62 return sender_context.status();
63 }
64 return {absl::WrapUnique(new HpkeContext(
65 sender_context->encapsulated_key, std::move(sender_context->context)))};
66 }
67
SetupRecipient(const HpkeParams & params,const util::SecretData & recipient_private_key,absl::string_view encapsulated_key,absl::string_view info)68 util::StatusOr<std::unique_ptr<HpkeContext>> HpkeContext::SetupRecipient(
69 const HpkeParams& params, const util::SecretData& recipient_private_key,
70 absl::string_view encapsulated_key, absl::string_view info) {
71 if (recipient_private_key.empty()) {
72 return util::Status(absl::StatusCode::kInvalidArgument,
73 "Recipient private key is empty.");
74 }
75 if (encapsulated_key.empty()) {
76 return util::Status(absl::StatusCode::kInvalidArgument,
77 "Encapsulated key is empty.");
78 }
79 util::StatusOr<std::unique_ptr<HpkeContextBoringSsl>> context =
80 HpkeContextBoringSsl::SetupRecipient(params, recipient_private_key,
81 encapsulated_key, info);
82 if (!context.ok()) {
83 return context.status();
84 }
85 return {absl::WrapUnique(
86 new HpkeContext(encapsulated_key, *std::move(context)))};
87 }
88
89 } // namespace internal
90 } // namespace tink
91 } // namespace crypto
92