1 // Copyright 2019 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 #ifndef TINK_SUBTLE_AES_GCM_HKDF_STREAM_SEGMENT_ENCRYPTER_H_ 18 #define TINK_SUBTLE_AES_GCM_HKDF_STREAM_SEGMENT_ENCRYPTER_H_ 19 20 #include <memory> 21 #include <string> 22 #include <vector> 23 24 #include "tink/aead/internal/ssl_aead.h" 25 #include "tink/subtle/stream_segment_encrypter.h" 26 #include "tink/util/secret_data.h" 27 #include "tink/util/statusor.h" 28 29 namespace crypto { 30 namespace tink { 31 namespace subtle { 32 33 // StreamSegmentEncrypter for streaming encryption using AES-GCM with HKDF as 34 // key derivation function. 35 // 36 // Each ciphertext uses a new AES-GCM key that is derived from the key 37 // derivation key, a randomly chosen salt of the same size as the key and a 38 // nonce prefix. 39 // 40 // The format of a ciphertext is 41 // header || segment_0 || segment_1 || ... || segment_k. 42 // where: 43 // - segment_i is the i-th segment of the ciphertext. 44 // - the size of segment_1 .. segment_{k-1} is get_ciphertext_segment_size() 45 // - segment_0 is shorter, so that segment_0, the header and other information 46 // of size get_ciphertext_offset() align with get_ciphertext_segment_size(). 47 // 48 // The format of the header is 49 // header_size || salt || nonce_prefix 50 // where 51 // - header_size is 1 byte determining the size of the header 52 // - salt is a salt used in the key derivation 53 // - nonce_prefix is the prefix of the nonce 54 // 55 // In principle header_size is redundant information, since the length of the 56 // header can be determined from the key size. 57 58 class AesGcmHkdfStreamSegmentEncrypter : public StreamSegmentEncrypter { 59 public: 60 // The size of the IVs for GCM. 61 static constexpr int kNonceSizeInBytes = 12; 62 63 // The nonce has the format nonce_prefix || ctr || last_block, where: 64 // - nonce_prefix is a constant of kNoncePrefixSizeInBytes bytes 65 // for the whole file 66 // - ctr is a 32 bit counter 67 // - last_block is a byte equal to 1 for the last block of the file 68 // and 0 otherwise. 69 static constexpr int kNoncePrefixSizeInBytes = 7; 70 71 // The size of the tags of each ciphertext segment. 72 static constexpr int kTagSizeInBytes = 16; 73 74 struct Params { 75 util::SecretData key; 76 std::string salt; 77 int ciphertext_offset; 78 int ciphertext_segment_size; 79 }; 80 81 static util::StatusOr<std::unique_ptr<StreamSegmentEncrypter>> New( 82 Params params); 83 84 util::Status EncryptSegment(const std::vector<uint8_t>& plaintext, 85 bool is_last_segment, 86 std::vector<uint8_t>* ciphertext_buffer) override; 87 get_header()88 const std::vector<uint8_t>& get_header() const override { return header_; } get_segment_number()89 int64_t get_segment_number() const override { return segment_number_; } 90 int get_plaintext_segment_size() const override; get_ciphertext_segment_size()91 int get_ciphertext_segment_size() const override { 92 return ciphertext_segment_size_; 93 } get_ciphertext_offset()94 int get_ciphertext_offset() const override { return ciphertext_offset_; } 95 96 protected: IncSegmentNumber()97 void IncSegmentNumber() override { segment_number_++; } 98 99 private: 100 AesGcmHkdfStreamSegmentEncrypter( 101 std::unique_ptr<internal::SslOneShotAead> aead, const Params& params); 102 103 // When OpenSSL is used, this uses a thread-safe implementation that makes a 104 // copy of the context for each EncryptSegment call, which may result in some 105 // extra latency compared to BoringSSL. 106 const std::unique_ptr<internal::SslOneShotAead> aead_; 107 108 const std::string nonce_prefix_; 109 const std::vector<uint8_t> header_; 110 const int ciphertext_segment_size_; 111 const int ciphertext_offset_; 112 113 int64_t segment_number_ = 0; 114 }; 115 116 } // namespace subtle 117 } // namespace tink 118 } // namespace crypto 119 120 #endif // TINK_SUBTLE_AES_GCM_HKDF_STREAM_SEGMENT_ENCRYPTER_H_ 121