1 /*
2  * rsyncrypto - an rsync friendly encryption
3  * Copyright (C) 2005-2008 Shachar Shemesh for Lingnu Open Source Consulting ltd.
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  * In addition, as a special exception, the rsyncrypto authors give permission
20  * to link the code of this program with the OpenSSL library (or with modified
21  * versions of OpenSSL that use the same license as OpenSSL), and distribute
22  * linked combinations including the two. You must obey the GNU General Public
23  * License in all respects for all of the code used other than OpenSSL. If you
24  * modify this file, you may extend this exception to your version of the file,
25  * but you are not obligated to do so. If you do not wish to do so, delete this
26  * exception statement from your version.
27  *
28  * The project's homepage is at http://rsyncrypto.lingnu.com/
29  */
30 
31 #include <precomp.h>
32 #include "rsyncrypto.h"
33 #include "crypto.h"
34 #include "process.h"
35 #include "autopipe.h"
36 #include "redir.h"
37 
38 /* Cyclic add and subtract */
39 #define MOD_ADD(a,b,mod) (((a)+(b))%(mod))
40 #define MOD_SUB(a,b,mod) MOD_ADD((a), (mod)-(b), (mod))
41 
42 #define VERSION_MAGIC_1 0xD657EA1Cul
43 
44 /* Public/Private key handling */
extract_public_key(const char * pem_filename)45 RSA *extract_public_key( const char *pem_filename )
46 {
47     BIO *in;
48     X509 *x509;
49     EVP_PKEY *pkey;
50     RSA *rsa=NULL;
51 
52     /* We pull the public key out of the certificate. It's much like pulling teeth */
53     /* First, get the certificate loaded into a stream */
54     in=BIO_new(BIO_s_file()); /* NULL is error */
55     if( in==NULL )
56         throw rscerror( "Error allocating public key", ENOMEM );
57 
58     if( BIO_read_filename(in, pem_filename)<=0 ) /* <=0 is error */
59         throw rscerror( "Error reading public key file", errno, pem_filename );
60 
61     /* Next, extract the X509 certificate from it */
62     x509=PEM_read_bio_X509(in, NULL, NULL, NULL );
63     if( x509==NULL )
64         throw rscerror( "Error parsing certificate" );
65 
66     /* And the public key in generic format */
67     pkey=X509_get_pubkey(x509);
68     /* And finally, we get the actual RSA key */
69     rsa=EVP_PKEY_get1_RSA(pkey);
70     /* Lastly, release all the resources we've allocated */
71     X509_free(x509);
72     EVP_PKEY_free(pkey);
73     BIO_free_all(in);
74 
75     return rsa;
76 }
77 
extract_private_key(const char * key_filename)78 RSA *extract_private_key( const char *key_filename )
79 {
80     BIO *in;
81     RSA *rsa=NULL;
82 
83     /* We pull the public key out of the certificate. It's much like pulling teeth */
84     /* First, get the certificate loaded into a stream */
85     in=BIO_new(BIO_s_file()); /* NULL is error */
86     if( in==NULL )
87         throw rscerror( "Error allocating private key" );
88     if( BIO_read_filename(in, key_filename)<=0 ) /* <=0 is error */
89         throw rscerror( "Error reading private key file", errno, key_filename );
90 
91     /* And finally, we get the actual RSA key */
92     rsa=PEM_read_bio_RSAPrivateKey(in,NULL,NULL,NULL);
93     /* Lastly, release all the resources we've allocated */
94     BIO_free_all(in);
95 
96     return rsa;
97 }
98 
read_header(const autofd & headfd)99 std::unique_ptr<key> read_header( const autofd &headfd )
100 {
101     autommap headmap( headfd, PROT_READ );
102     return key::read_key( headmap.get_uc() );
103 }
104 
write_header(const char * filename,const key * head)105 void write_header( const char *filename, const key *head )
106 {
107     autofd::mkpath( std::string(filename, autofd::dirpart(filename)).c_str(), 0700 );
108     autofd newhead(filename, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
109     off_t headsize=head->exported_length();
110 
111     if( newhead.lseek( headsize-1, SEEK_SET )!=headsize-1 ||
112             newhead.write( filename, 1 )!=1 )
113         throw rscerror("write failed", errno, filename );
114 
115     autommap headfilemap( NULL, static_cast<size_t>(headsize), PROT_WRITE|PROT_READ, MAP_SHARED,
116         newhead, 0 );
117     head->export_key( headfilemap.get() );
118 }
119 
120 const uint32_t HEADER_ENCRYPTION_VERSION=0;
121 
header_size(const RSA * rsa)122 size_t header_size( const RSA *rsa )
123 {
124     return RSA_size(rsa)+sizeof(HEADER_ENCRYPTION_VERSION);
125 }
126 
127 /* Encrypt the file's header */
encrypt_header(const key * header,RSA * rsa,unsigned char * to)128 void encrypt_header( const key *header, RSA *rsa, unsigned char *to )
129 {
130     size_t export_size=header->exported_length();
131 
132     *reinterpret_cast<uint32_t *>(to)=htonl(HEADER_ENCRYPTION_VERSION);
133 
134     to+=sizeof(HEADER_ENCRYPTION_VERSION);
135 
136     header->export_key( to );
137 
138     /* Encrypt the whole thing in place */
139     if( RSA_public_encrypt(export_size, to, to, rsa, RSA_PKCS1_OAEP_PADDING)==-1 ) {
140         unsigned long rsaerr=ERR_get_error();
141         throw rscerror(ERR_error_string(rsaerr, NULL));
142     }
143 }
144 
145 /* Decrypt the file's header */
decrypt_header(file_t fromfd,RSA * prv)146 std::unique_ptr<key> decrypt_header( file_t fromfd, RSA *prv )
147 {
148     const size_t key_size=RSA_size(prv);
149     size_t headsize=header_size(prv);
150     autommap filemap(NULL, headsize, PROT_READ, MAP_PRIVATE, fromfd, 0);
151 
152     if( *static_cast<uint32_t *>(filemap.get())!=htonl(HEADER_ENCRYPTION_VERSION) )
153         throw rscerror("Wrong file or header encrypted with wrong encryption");
154 
155     unsigned char *buff=filemap.get_uc()+sizeof(HEADER_ENCRYPTION_VERSION);
156     auto_array<unsigned char> decrypted(new unsigned char[headsize]);
157 
158 #if OPENSSL_VERSION_NUMBER < 0x10100000L
159     if( (prv->p==nullptr || prv->q==nullptr) ) {
160 #else
161     const BIGNUM *p, *q;
162     RSA_get0_factors(prv, &p, &q);
163     if( (p==nullptr || q==nullptr) ) {
164 #endif
165         // This is not a private key!
166         throw rscerror("Neither AES session key nor RSA private key present - cannot decrypt using only public key");
167     }
168 
169     if( RSA_private_decrypt(key_size, buff, decrypted.get(), prv, RSA_PKCS1_OAEP_PADDING)==-1 ) {
170         unsigned long rsaerr=ERR_get_error();
171         throw rscerror(ERR_error_string(rsaerr, NULL));
172     }
173 
174     std::unique_ptr<key> ret(key::read_key( decrypted.get() ));
175 
176     // Let's verify that we have read the correct data from the file, by reencoding the key we got and comparing
177     // the cyphertexts.
178     // On second thought - let's not. You never know if we don't change encoding at some future point.
179 
180     return ret;
181 }
182 
183 // "encrypt_file" will also close the from and to file handles.
184 void encrypt_file( key *header, RSA *rsa, read_bufferfd &fromfd, write_bufferfd &tofd )
185 {
186     const size_t key_size=RSA_size(rsa);
187 
188     /* Skip the header. We'll only write it out once the file itself is written */
189     autofd::lseek(tofd, header_size(rsa), SEEK_SET);
190 
191     redir_pipe ipipe(8000);
192     redir_fd redir_from(fromfd);
193     process_ctl gzip_process( const_cast<char *>(FILENAME(gzip)), &redir_from, &ipipe, NULL,  "--rsyncable", NULL );
194 
195     // Run through gzip's output, and encrypt it
196     const size_t block_size=header->block_size(); // Let's cache the block size
197     auto_array<unsigned char> buffer(new unsigned char [block_size]);
198     unsigned int i=0;
199     int numread=1;
200     bool new_block=true;
201 
202     read_bufferfd *readfd=new read_bufferfd(ipipe.get_read());
203     while( (numread=readfd->read(buffer.get()+i, 1))!=0 ) {
204         if( new_block ) {
205             header->init_encrypt();
206             new_block=false;
207         }
208 
209         new_block=header->calc_boundry( buffer[i] );
210         i+=numread;
211         if( i>=block_size || new_block ) {
212             header->encrypt_block( buffer.get(), i );
213             tofd.write( buffer.get(), block_size );
214 
215             i=0;
216         }
217     }
218 
219     delete readfd;
220 
221     if( i>0 ) {
222         // Still some leftover bytes to encrypt
223         header->encrypt_block( buffer.get(), i );
224         tofd.write( buffer.get(), block_size );
225     }
226 
227     // Report how many bytes of last block are relevant.
228     bzero( buffer.get(), block_size );
229     buffer[0]=i;
230     header->init_encrypt();
231     header->encrypt_block( buffer.get(), 1 );
232     tofd.write( buffer.get(), block_size );
233 
234     tofd.flush();
235 
236     // Wait for gzip to return, and check whether it succeeded
237     int childstatus=gzip_process.wait();
238 
239     if( childstatus==0 ) {
240         /* gzip was successful - write out the header, encrypted */
241         autommap buffer( NULL, key_size, PROT_READ|PROT_WRITE, MAP_SHARED, tofd, 0 );
242         encrypt_header( header, rsa, buffer.get_uc() );
243     } else {
244         throw rscerror("Error in running gzip");
245     }
246 
247     tofd.clear();
248 }
249 
250 // "decrypt_file" will also close the from and to file handles.
251 std::unique_ptr<key> decrypt_file( std::unique_ptr<key> header, RSA *prv, read_bufferfd &fromfd, write_bufferfd &tofd )
252 {
253     if( header==NULL ) {
254         /* Need to reconstruct the header from the encrypted file */
255         header=decrypt_header( fromfd, prv );
256     }
257 
258     /* If file does not contain a valid header - abort */
259     if( header==NULL )
260         throw rscerror("Couldn't extract encryption header");
261 
262     struct stat filestat;
263     off_t currpos;
264 
265     filestat=fromfd.fstat();
266 
267     /* Skip the header */
268     currpos=fromfd.lseek(header_size(prv), SEEK_SET);
269 
270     redir_pipe opipe;
271     redir_fd redir_to(tofd);
272     process_ctl gzip_process( const_cast<char *>(FILENAME(gzip)), &opipe, &redir_to, NULL, "-d", NULL );
273 
274     size_t numread;
275     const size_t block_size=header->block_size();
276     auto_array<unsigned char> buffer(new unsigned char [block_size]);
277     bool done=false;
278     bool new_block=true;
279     write_bufferfd *writefd=new write_bufferfd(opipe.get_write());
280 
281     /* Read the file one AES_BLOCK_SIZE at a time, decrypt and write to the pipe */
282     while( !done && (numread=fromfd.read( buffer.get(), block_size))!=0 ) {
283         currpos+=numread;
284         if( numread>0 && numread<block_size )
285             throw rscerror("Unexpected file end");
286 
287         if( new_block ) {
288             header->init_encrypt();
289             new_block=false;
290         }
291 
292         header->decrypt_block( buffer.get(), block_size );
293 
294         unsigned int i;
295         for( i=0; i<block_size && !new_block; ++i ) {
296             new_block=header->calc_boundry(buffer[i]);
297         }
298 
299         if( currpos>=filestat.st_size-static_cast<off_t>(block_size) ) {
300             done=true;
301 
302             // Oops - file is not a whole multiple of block size
303             if( currpos>filestat.st_size-static_cast<off_t>(block_size) )
304                 throw rscerror("Uneven file end");
305         } else {
306             writefd->write( buffer.get(), i );
307         }
308 
309         // If this was not a full block, the remaining bytes should be zero
310         for( ; i<block_size; ++i )
311             if( buffer[i]!=0 )
312                 throw rscerror("Error in encrypted stream");
313     }
314 
315     // The next block will tell us how many bytes of the last block should be written.
316     auto_array<unsigned char> buffer2(new unsigned char [block_size]);
317     if( fromfd.read( buffer2.get(), block_size)!=static_cast<ssize_t>(block_size) )
318         throw rscerror("Unexcpeted end of file past sanity checks");
319 
320     header->init_encrypt();
321     header->decrypt_block( buffer2.get(), block_size );
322     for( unsigned int i=1; i<block_size; ++i )
323         if( buffer2[i]!=0 )
324             throw rscerror("Error in encrypted stream (trailer)");
325     if( buffer2[0]>=block_size )
326         throw rscerror("Error in encrypted stream (trailer 2)");
327 
328     if( buffer2[0]==0 )
329         buffer2[0]=block_size;
330 
331     writefd->write( buffer.get(), buffer2[0] );
332     writefd->flush();
333     delete writefd;
334     opipe.clear();
335 
336     int child_status=gzip_process.wait();
337 
338     if( child_status!=0 )
339         throw rscerror("gunzip failed to run");
340 
341     fromfd.clear();
342 
343     return header;
344 }
345