1 // Copyright (c) 2012-2014 Konstantin Isakov <ikm@zbackup.org> and ZBackup contributors, see CONTRIBUTORS
2 // Part of ZBackup. Licensed under GNU GPLv2 or later + OpenSSL, see LICENSE
3 
4 #include <string.h>
5 #include <algorithm>
6 
7 #include "check.hh"
8 #include "encrypted_file.hh"
9 #include "endian.hh"
10 #include "page_size.hh"
11 #include "random.hh"
12 
13 namespace EncryptedFile {
14 
15 using Encryption::BlockSize;
16 
InputStream(char const * fileName,EncryptionKey const & key,void const * iv_)17 InputStream::InputStream( char const * fileName, EncryptionKey const & key,
18                           void const * iv_ ):
19   file( fileName, UnbufferedFile::ReadOnly ), filePos( 0 ), key( key ),
20   // Our buffer must be larger than BlockSize, as otherwise we won't be able
21   // to handle PKCS#7 padding properly
22   buffer( std::max( getPageSize(), ( unsigned ) BlockSize * 2 ) ),
23   fill( 0 ), remainder( 0 ), backedUp( false )
24 {
25   if ( key.hasKey() )
26   {
27     memcpy( iv, iv_, sizeof( iv ) );
28     // Since we use padding, file size should be evenly dividable by the cipher
29     // block size, and we should have at least one block
30     UnbufferedFile::Offset size = file.size();
31     if ( !size || size % BlockSize )
32       throw exIncorrectFileSize();
33   }
34 }
35 
Next(void const ** data,int * size)36 bool InputStream::Next( void const ** data, int * size )
37 {
38   // If we backed up, return the unconsumed data
39   if ( backedUp )
40     backedUp = false;
41   else
42   {
43     try
44     {
45       // Update adler32 for the previous block
46       adler32.add( start, fill );
47 
48       // Read more data
49       if ( filePos && !remainder )
50       {
51         // Once we're read a full block, we always have a remainder. If not,
52         // this means we've hit the end of file already
53         fill = 0;
54         return false;
55       }
56 
57       // If we have a remainder, move it to the beginning of buffer and make
58       // it start the next block
59       memmove( buffer.data(), start + fill, remainder );
60       start = buffer.data();
61       fill = file.read( start + remainder, buffer.size() - remainder ) +
62              remainder;
63       // remainder should techically be 0 now, but decrypt() will update it
64       // anyway
65       // remainder = 0;
66       decrypt();
67     }
68     catch( UnbufferedFile::exReadError & )
69     {
70       fill = 0; // To make sure state is remaining consistent
71       return false;
72     }
73   }
74   *data = start;
75   *size = fill;
76   filePos += fill;
77   return *size;
78 }
79 
BackUp(int count)80 void InputStream::BackUp( int count )
81 {
82   ZBACKUP_CHECK( count >= 0, "count is negative" );
83   if ( !backedUp )
84   {
85     ZBACKUP_CHECK( (size_t) count <= fill, "Backing up too much" );
86     size_t consumed = fill - count;
87     adler32.add( start, consumed );
88     start += consumed;
89     fill = count;
90     filePos -= count;
91     backedUp = fill; // Don't make the next Next() return 0 bytes
92   }
93   else
94   {
95     ZBACKUP_CHECK( count == 0, "backing up after being backed up already" );
96   }
97 }
98 
Skip(int count)99 bool InputStream::Skip( int count )
100 {
101   ZBACKUP_CHECK( count >= 0, "count is negative" );
102 
103   // We always need to read and decrypt data, as otherwise both the state of
104   // CBC and adler32 would be incorrect
105   void const * data;
106   int size;
107   while( count )
108   {
109     if ( !Next( &data, &size ) )
110       return false;
111     else
112     if ( size > count )
113     {
114       BackUp( size - count );
115       break;
116     }
117     else
118       count -= size;
119   }
120   return true;
121 }
122 
ByteCount() const123 int64_t InputStream::ByteCount() const
124 {
125   return filePos;
126 }
127 
getAdler32()128 Adler32::Value InputStream::getAdler32()
129 {
130   // This makes all data consumed, if not already
131   BackUp( 0 );
132   return adler32.result();
133 }
134 
read(void * buf,size_t size)135 void InputStream::read( void * buf, size_t size )
136 {
137   void const * data;
138   int avail;
139   char * n = ( char * ) buf;
140   while( size )
141   {
142     if ( !Next( &data, &avail ) )
143       throw exReadFailed();
144     else
145     if ( avail > ( ssize_t ) size )
146     {
147       memcpy( n, data, size );
148       BackUp( avail - size );
149       break;
150     }
151     else
152     {
153       memcpy( n, data, avail );
154       n += avail;
155       size -= avail;
156     }
157   }
158 }
159 
checkAdler32()160 void InputStream::checkAdler32()
161 {
162   Adler32::Value ours = getAdler32();
163   Adler32::Value r;
164   read( &r, sizeof( r ) );
165   if ( ours != fromLittleEndian( r ) )
166     throw exAdlerMismatch();
167 }
168 
consumeRandomIv()169 void InputStream::consumeRandomIv()
170 {
171   if ( key.hasKey() )
172   {
173     char iv[ Encryption::IvSize ];
174     read( iv, sizeof( iv ) ); // read() can throw exceptions, Skip() can't
175   }
176 }
177 
decrypt()178 void InputStream::decrypt()
179 {
180   if ( fill == buffer.size() )
181   {
182     // When we have the full buffer, we set the last block of it aside and
183     // treat the rest as the normal CBC sequence. The last block in the buffer
184     // may be the last block of file, in which case we would need to handle
185     // padding. That may happen the next time the function is called
186     remainder = BlockSize;
187     fill -= BlockSize;
188     doDecrypt();
189   }
190   else
191   {
192     // This is an end of file. Decrypt data treating the last block being
193     // padded
194 
195     // Since we always have padding in the file and the last block is always
196     // set apart when reading full buffers, we must have at least one block
197     // to decrypt here
198     doDecrypt();
199 
200     // Unpad the last block
201     if ( key.hasKey() )
202       fill -= BlockSize - Encryption::unpad( start + fill - BlockSize );
203 
204     // We have not left any remainder this time
205     remainder = 0;
206   }
207 }
208 
doDecrypt()209 void InputStream::doDecrypt()
210 {
211   if ( !key.hasKey() )
212     return;
213 
214   // Since we use padding, file size should be evenly dividable by the cipher's
215   // block size, and we should always have at least one block. When we get here,
216   // we would always get the proper fill value unless those characteristics are
217   // not met. We check for the same condition on construction, but the file
218   // size can change while we are reading it
219 
220   // We don't throw an exception here as the interface we implement doesn't
221   // support them
222   ZBACKUP_CHECK( fill > 0 && !( fill % BlockSize ), "incorrect size of the encrypted "
223          "file - must be non-zero and in multiples of %u",
224          ( unsigned ) BlockSize );
225 
226   // Copy the next iv prior to decrypting the data in place, as it will
227   // not be available afterwards
228   char newIv[ Encryption::IvSize ];
229   memcpy( newIv, Encryption::getNextDecryptionIv( start, fill ),
230           sizeof( newIv ) );
231   // Decrypt the data
232   Encryption::decrypt( iv, key.getKey(), start, start, fill );
233   // Copy the new iv
234   memcpy( iv, newIv, sizeof( iv ) );
235 }
236 
OutputStream(char const * fileName,EncryptionKey const & key,void const * iv_)237 OutputStream::OutputStream( char const * fileName, EncryptionKey const & key,
238                             void const * iv_ ):
239   file( fileName, UnbufferedFile::WriteOnly ), filePos( 0 ), key( key ),
240   buffer( getPageSize() ), start( buffer.data() ), avail( 0 ), backedUp( false )
241 {
242   if ( key.hasKey() )
243     memcpy( iv, iv_, sizeof( iv ) );
244 }
245 
Next(void ** data,int * size)246 bool OutputStream::Next( void ** data, int * size )
247 {
248   // If we backed up, return the unconsumed data
249   if ( backedUp )
250     backedUp = false;
251   else
252   {
253     try
254     {
255       // Update adler32 for the previous block
256       adler32.add( start, avail );
257 
258       // Encrypt and write the buffer if it had data
259       if ( filePos )
260         encryptAndWrite( buffer.size() );
261 
262       start = buffer.data();
263       avail = buffer.size();
264     }
265     catch( UnbufferedFile::exWriteError & )
266     {
267       avail = 0; // To make sure state is remaining consistent
268       return false;
269     }
270   }
271   *data = start;
272   *size = avail;
273   filePos += avail;
274   return *size;
275 }
276 
BackUp(int count)277 void OutputStream::BackUp( int count )
278 {
279   ZBACKUP_CHECK( count >= 0, "count is negative" );
280   if ( !backedUp )
281   {
282     ZBACKUP_CHECK( (size_t) count <= avail, "Backing up too much" );
283     size_t consumed = avail - count;
284     adler32.add( start, consumed );
285     start += consumed;
286     avail = count;
287     filePos -= count;
288     backedUp = avail; // Don't make the next Next() return 0 bytes
289   }
290   else
291   {
292     ZBACKUP_CHECK( count == 0, "backing up after being backed up already" );
293   }
294 }
295 
ByteCount() const296 int64_t OutputStream::ByteCount() const
297 {
298   return filePos;
299 }
300 
getAdler32()301 Adler32::Value OutputStream::getAdler32()
302 {
303   // This makes all data consumed, if not already
304   BackUp( 0 );
305   return adler32.result();
306 }
307 
write(void const * buf,size_t size)308 void OutputStream::write( void const * buf, size_t size )
309 {
310   void * data;
311   int avail;
312   char const * n = ( char const * ) buf;
313   while( size )
314   {
315     if ( !Next( &data, &avail ) )
316       throw exReadFailed();
317     else
318     if ( avail > ( ssize_t ) size )
319     {
320       memcpy( data, n, size );
321       BackUp( avail - size );
322       break;
323     }
324     else
325     {
326       memcpy( data, n, avail );
327       n += avail;
328       size -= avail;
329     }
330   }
331 }
332 
writeAdler32()333 void OutputStream::writeAdler32()
334 {
335   Adler32::Value v = toLittleEndian( getAdler32() );
336   write( &v, sizeof( v ) );
337 }
338 
writeRandomIv()339 void OutputStream::writeRandomIv()
340 {
341   if ( key.hasKey() )
342   {
343     char iv[ Encryption::IvSize ];
344     Random::genaratePseudo( iv, sizeof( iv ) );
345     write( iv, sizeof( iv ) );
346   }
347 }
348 
encryptAndWrite(size_t bytes)349 void OutputStream::encryptAndWrite( size_t bytes )
350 {
351   if ( key.hasKey() )
352   {
353     ZBACKUP_CHECK( bytes > 0 && !( bytes % BlockSize ), "incorrect number of bytes to "
354            "encrypt and write - must be non-zero and in multiples of %u",
355            ( unsigned ) BlockSize );
356 
357     void const * nextIv = Encryption::encrypt( iv, key.getKey(), buffer.data(),
358                                                buffer.data(), bytes );
359     memcpy( iv, nextIv, sizeof( iv ) );
360   }
361 
362   file.write( buffer.data(), bytes );
363 }
364 
~OutputStream()365 OutputStream::~OutputStream()
366 {
367   // This makes all data consumed, if not already
368   BackUp( 0 );
369 
370   // If we have the full buffer, write it first
371   if ( start == buffer.data() + buffer.size() )
372   {
373     encryptAndWrite( buffer.size() );
374     start = buffer.data();
375   }
376 
377   size_t bytesToWrite = start - buffer.data();
378 
379   if ( key.hasKey() )
380   {
381     // Perform padding
382     size_t remainderSize = bytesToWrite % BlockSize;
383 
384     Encryption::pad( start - remainderSize, remainderSize );
385     bytesToWrite += BlockSize - remainderSize;
386   }
387 
388   encryptAndWrite( bytesToWrite );
389 }
390 
391 }
392