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 #ifndef TINK_HYBRID_INTERNAL_HPKE_CONTEXT_H_ 18 #define TINK_HYBRID_INTERNAL_HPKE_CONTEXT_H_ 19 20 #include <stddef.h> 21 22 #include <memory> 23 #include <string> 24 #include <utility> 25 26 #include "absl/strings/string_view.h" 27 #include "tink/hybrid/internal/hpke_context_boringssl.h" 28 #include "tink/hybrid/internal/hpke_util.h" 29 #include "tink/util/secret_data.h" 30 #include "tink/util/statusor.h" 31 32 namespace crypto { 33 namespace tink { 34 namespace internal { 35 36 // Pair of string views for an HPKE payload (encapsulated key and ciphertext). 37 struct HpkePayloadView { HpkePayloadViewHpkePayloadView38 HpkePayloadView(absl::string_view encapsulated_key, 39 absl::string_view ciphertext) 40 : encapsulated_key(encapsulated_key), ciphertext(ciphertext) {} 41 42 absl::string_view encapsulated_key; 43 absl::string_view ciphertext; 44 }; 45 46 // Creates HPKE payload `encapsulated_key` || `ciphertext` (i.e., Tink hybrid 47 // encryption wire format described at 48 // https://developers.google.com/tink/wire-format#hybrid_encryption). 49 std::string ConcatenatePayload(absl::string_view encapsulated_key, 50 absl::string_view ciphertext); 51 52 // Splits `payload` into an `HpkePayloadView` struct. The `kem` parameter is 53 // used to determine how to split the payload. 54 // 55 // WARNING: The string pointed to by `payload` must outlive the returned object. 56 crypto::tink::util::StatusOr<HpkePayloadView> SplitPayload( 57 const HpkeKem& kem, absl::string_view payload); 58 59 // Represents an HPKE context for either a sender or a recipient. 60 class HpkeContext { 61 public: 62 // Sets up an HPKE sender context. Returns an error if initialization 63 // fails. Otherwise, returns a unique pointer to the sender context. 64 // 65 // `params`: HPKE parameters (KEM, KDF, and AEAD). 66 // `recipient_public_key`: KEM-encoding of recipient public key. 67 // `info`: Application-specific context for key derivation. 68 static crypto::tink::util::StatusOr<std::unique_ptr<HpkeContext>> SetupSender( 69 const HpkeParams& params, absl::string_view recipient_public_key, 70 absl::string_view info); 71 72 // Sets up an HPKE recipient context. Returns an error if initialization 73 // fails. Otherwise, returns a unique pointer to the recipient context. 74 // 75 // `params`: HPKE parameters (KEM, KDF, and AEAD). 76 // `recipient_private_key`: Recipient private key. 77 // `encapsulated_key`: Encapsulated key. 78 // `info`: Application-specific context for key derivation. 79 static crypto::tink::util::StatusOr<std::unique_ptr<HpkeContext>> 80 SetupRecipient(const HpkeParams& params, 81 const util::SecretData& recipient_private_key, 82 absl::string_view encapsulated_key, absl::string_view info); 83 EncapsulatedKey()84 absl::string_view EncapsulatedKey() const { 85 return encapsulated_key_; 86 } 87 88 // Performs an AEAD encryption of `plaintext` with `associated_data`. Returns 89 // an error if encryption fails. Otherwise, returns the ciphertext. Seal(absl::string_view plaintext,absl::string_view associated_data)90 crypto::tink::util::StatusOr<std::string> Seal( 91 absl::string_view plaintext, absl::string_view associated_data) { 92 return context_->Seal(plaintext, associated_data); 93 } 94 95 // Performs an AEAD decryption of `ciphertext` with `associated_data`. Returns 96 // an error if decryption fails. Otherwise, returns the plaintext. Open(absl::string_view ciphertext,absl::string_view associated_data)97 crypto::tink::util::StatusOr<std::string> Open( 98 absl::string_view ciphertext, absl::string_view associated_data) { 99 return context_->Open(ciphertext, associated_data); 100 } 101 102 // Exports `secret_length` bytes of secret material using `exporter_context` 103 // for the input context. Returns an error if export fails. Otherwise, 104 // returns a secret of the requested length. Export(absl::string_view exporter_context,size_t secret_length)105 crypto::tink::util::StatusOr<util::SecretData> Export( 106 absl::string_view exporter_context, size_t secret_length) { 107 return context_->Export(exporter_context, secret_length); 108 } 109 110 private: HpkeContext(absl::string_view encapsulated_key,std::unique_ptr<HpkeContextBoringSsl> context)111 explicit HpkeContext(absl::string_view encapsulated_key, 112 std::unique_ptr<HpkeContextBoringSsl> context) 113 : encapsulated_key_(encapsulated_key), context_(std::move(context)) {} 114 115 const std::string encapsulated_key_; 116 const std::unique_ptr<HpkeContextBoringSsl> context_; 117 }; 118 119 } // namespace internal 120 } // namespace tink 121 } // namespace crypto 122 123 #endif // TINK_HYBRID_INTERNAL_HPKE_CONTEXT_H_ 124