1*e7b1675dSTing-Kang Chang // Copyright 2019 Google Inc. 2*e7b1675dSTing-Kang Chang // 3*e7b1675dSTing-Kang Chang // Licensed under the Apache License, Version 2.0 (the "License"); 4*e7b1675dSTing-Kang Chang // you may not use this file except in compliance with the License. 5*e7b1675dSTing-Kang Chang // You may obtain a copy of the License at 6*e7b1675dSTing-Kang Chang // 7*e7b1675dSTing-Kang Chang // http://www.apache.org/licenses/LICENSE-2.0 8*e7b1675dSTing-Kang Chang // 9*e7b1675dSTing-Kang Chang // Unless required by applicable law or agreed to in writing, software 10*e7b1675dSTing-Kang Chang // distributed under the License is distributed on an "AS IS" BASIS, 11*e7b1675dSTing-Kang Chang // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*e7b1675dSTing-Kang Chang // See the License for the specific language governing permissions and 13*e7b1675dSTing-Kang Chang // limitations under the License. 14*e7b1675dSTing-Kang Chang // 15*e7b1675dSTing-Kang Chang /////////////////////////////////////////////////////////////////////////////// 16*e7b1675dSTing-Kang Chang 17*e7b1675dSTing-Kang Chang #ifndef TINK_SUBTLE_STREAM_SEGMENT_ENCRYPTER_H_ 18*e7b1675dSTing-Kang Chang #define TINK_SUBTLE_STREAM_SEGMENT_ENCRYPTER_H_ 19*e7b1675dSTing-Kang Chang 20*e7b1675dSTing-Kang Chang #include <cstdint> 21*e7b1675dSTing-Kang Chang #include <vector> 22*e7b1675dSTing-Kang Chang 23*e7b1675dSTing-Kang Chang #include "tink/util/status.h" 24*e7b1675dSTing-Kang Chang 25*e7b1675dSTing-Kang Chang namespace crypto { 26*e7b1675dSTing-Kang Chang namespace tink { 27*e7b1675dSTing-Kang Chang namespace subtle { 28*e7b1675dSTing-Kang Chang 29*e7b1675dSTing-Kang Chang // StreamSegmentEncrypter is a helper class that encrypts individual 30*e7b1675dSTing-Kang Chang // segments of a stream. 31*e7b1675dSTing-Kang Chang // 32*e7b1675dSTing-Kang Chang // Instances of this are passed to an ...EncryptingStream. Each instance 33*e7b1675dSTing-Kang Chang // of a segment encrypter is used to encrypt one stream. 34*e7b1675dSTing-Kang Chang // 35*e7b1675dSTing-Kang Chang // Typically, construction of a new StreamSegmentEncrypter results 36*e7b1675dSTing-Kang Chang // in a generation of a new symmetric key, which is used to 37*e7b1675dSTing-Kang Chang // the segments of the stream. The key itself wrapped with or derived 38*e7b1675dSTing-Kang Chang // from the key from StreamingAead instance. The wrapped key or the salt 39*e7b1675dSTing-Kang Chang // used to derive the symmetric key is part of the header. 40*e7b1675dSTing-Kang Chang // 41*e7b1675dSTing-Kang Chang // StreamSegmentEncrypter has a state: it keeps the number of segments 42*e7b1675dSTing-Kang Chang // encrypted so far. This state is used to encrypt each segment with different 43*e7b1675dSTing-Kang Chang // parameters, so that segments in the ciphertext cannot be switched. 44*e7b1675dSTing-Kang Chang // 45*e7b1675dSTing-Kang Chang // Values returned by StreamSegmentEncrypter's methods effectively define 46*e7b1675dSTing-Kang Chang // the layout of the resulting ciphertext stream: 47*e7b1675dSTing-Kang Chang // 48*e7b1675dSTing-Kang Chang // | other | header | 1st ciphertext segment | 49*e7b1675dSTing-Kang Chang // | ...... 2nd ciphertext segment ..... | 50*e7b1675dSTing-Kang Chang // | ...... 3rd ciphertext segment ..... | 51*e7b1675dSTing-Kang Chang // | ...... ... ..... | 52*e7b1675dSTing-Kang Chang // | ...... last ciphertext segment | 53*e7b1675dSTing-Kang Chang // 54*e7b1675dSTing-Kang Chang // where the following holds: 55*e7b1675dSTing-Kang Chang // * each line above, except for the last one, 56*e7b1675dSTing-Kang Chang // contains get_ciphertext_segment_size() bytes 57*e7b1675dSTing-Kang Chang // * each segment, except for the 1st and the last one, 58*e7b1675dSTing-Kang Chang // encrypts get_plaintext_segment_size() bytes of plaintext 59*e7b1675dSTing-Kang Chang // * if the ciphertext stream encrypts at least one byte of plaintext, 60*e7b1675dSTing-Kang Chang // then the last segment encrypts at least one byte of plaintext 61*e7b1675dSTing-Kang Chang // * 'other' is get_ciphertext_offset() bytes long, and represents potential 62*e7b1675dSTing-Kang Chang // other bytes already written to the stream; the purpose of ciphertext 63*e7b1675dSTing-Kang Chang // offset is to allow alignment of ciphertext segments with segments 64*e7b1675dSTing-Kang Chang // of the underlying storage or transmission stream. 65*e7b1675dSTing-Kang Chang class StreamSegmentEncrypter { 66*e7b1675dSTing-Kang Chang public: 67*e7b1675dSTing-Kang Chang // Encrypts 'plaintext' as a segment, and writes the resulting ciphertext 68*e7b1675dSTing-Kang Chang // to 'ciphertext_buffer', adjusting its size as needed. 69*e7b1675dSTing-Kang Chang // 'plaintext' and 'ciphertext_buffer' must refer to distinct and 70*e7b1675dSTing-Kang Chang // non-overlapping space. 71*e7b1675dSTing-Kang Chang // Encryption uses the current value returned by get_segment_number() 72*e7b1675dSTing-Kang Chang // as the segment number, and subsequently increments the current 73*e7b1675dSTing-Kang Chang // segment number. 74*e7b1675dSTing-Kang Chang virtual util::Status EncryptSegment( 75*e7b1675dSTing-Kang Chang const std::vector<uint8_t>& plaintext, 76*e7b1675dSTing-Kang Chang bool is_last_segment, 77*e7b1675dSTing-Kang Chang std::vector<uint8_t>* ciphertext_buffer) = 0; 78*e7b1675dSTing-Kang Chang 79*e7b1675dSTing-Kang Chang // Returns the header of the ciphertext stream. 80*e7b1675dSTing-Kang Chang virtual const std::vector<uint8_t>& get_header() const = 0; 81*e7b1675dSTing-Kang Chang 82*e7b1675dSTing-Kang Chang // Returns the segment number that will be used for encryption 83*e7b1675dSTing-Kang Chang // of the next segment. 84*e7b1675dSTing-Kang Chang virtual int64_t get_segment_number() const = 0; 85*e7b1675dSTing-Kang Chang 86*e7b1675dSTing-Kang Chang // Returns the size (in bytes) of a plaintext segment. 87*e7b1675dSTing-Kang Chang virtual int get_plaintext_segment_size() const = 0; 88*e7b1675dSTing-Kang Chang 89*e7b1675dSTing-Kang Chang // Returns the size (in bytes) of a ciphertext segment. 90*e7b1675dSTing-Kang Chang virtual int get_ciphertext_segment_size() const = 0; 91*e7b1675dSTing-Kang Chang 92*e7b1675dSTing-Kang Chang // Returns the offset (in bytes) of the ciphertext within an encrypted stream. 93*e7b1675dSTing-Kang Chang // The offset is non-negative, and not larger than 94*e7b1675dSTing-Kang Chang // ciphertext_segment_size - (header_size + segment_overhead) 95*e7b1675dSTing-Kang Chang // where 96*e7b1675dSTing-Kang Chang // ciphertext_segment_size = get_ciphertext_segment_size() 97*e7b1675dSTing-Kang Chang // header_size = get_header().size() 98*e7b1675dSTing-Kang Chang // segment_overhead = ciphertext_segment_size - get_plaintext_segment_size() 99*e7b1675dSTing-Kang Chang virtual int get_ciphertext_offset() const = 0; 100*e7b1675dSTing-Kang Chang 101*e7b1675dSTing-Kang Chang virtual ~StreamSegmentEncrypter() = default; 102*e7b1675dSTing-Kang Chang 103*e7b1675dSTing-Kang Chang protected: 104*e7b1675dSTing-Kang Chang // Increments the segment number. 105*e7b1675dSTing-Kang Chang virtual void IncSegmentNumber() = 0; 106*e7b1675dSTing-Kang Chang }; 107*e7b1675dSTing-Kang Chang 108*e7b1675dSTing-Kang Chang } // namespace subtle 109*e7b1675dSTing-Kang Chang } // namespace tink 110*e7b1675dSTing-Kang Chang } // namespace crypto 111*e7b1675dSTing-Kang Chang 112*e7b1675dSTing-Kang Chang #endif // TINK_SUBTLE_STREAM_SEGMENT_ENCRYPTER_H_ 113