zuluCrypt  5.7.1
About: zuluCrypt is a simple but feature rich solution for hard drives encryption. It can manage PLAIN dm-crypt, LUKS, TrueCrypt and VeraCrypt encrypted volumes.
  Fossies Dox: zuluCrypt-5.7.1.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

file_encryption.c
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2012-2015
4  * name : Francis Banyikwa
5  * email: mhogomchungu@gmail.com
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "includes.h"
21 #include "../bin/includes.h"
22 
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <stdlib.h>
32 #include <stdio.h>
33 
34 #include <libcryptsetup.h>
35 
36 #define SIZE 512
37 
38 static void _write( int x,const void * y,size_t z )
39 {
40  if( write( x,y,z ) ){;}
41 }
42 static void _read( int x,void * y,size_t z )
43 {
44  if( read( x,y,z ) ){;}
45 }
46 
47 /*
48  * routines for encrypting and decrypting stand alone files.
49  *
50  * Basic idea of the operation:
51  *
52  * basic concept:
53  *
54  * to create an encrypted file:
55  *
56  * create a "shell" file, attach a mapper to it and then copy the content of plain text file
57  * to the shell file through the mapper to create a cypher text file.
58  *
59  * to create a decrypted file:
60  *
61  * create a container file, attach a mapper to the container file and copy contents ofthe file to be encrypted to the container file through
62  * the mapper .
63  *
64  * The container file has a simple format.
65  * 1. The file will be a multiple of 512,if the plain text file has a file size that is not a multiple of 512,then
66  * encrypted file will be padded to the next file size of 512 mupltiple.
67  *
68  * 2. The encrypted file will have an addition size of 512 bytes added to the beginning of the encrypted file.This is the header
69  * of the encrypted file.
70  *
71  * 100 bytes of data are read from "/dev/urandom" and added at offset 100 and offset 200.These two 100 bytes data chunks will bo
72  * compared to check if the decryption key is the same as encrypting key.The offsett should math if thhe keys are the same.
73  *
74  * The first 100 bytes will contain the size of the load and the format should be a format atoll() can correctly undestand. ie
75  * the size must be a null terminated string of digits representing the size of the load.
76  *
77  *
78  * If for example, a 100 bytes file is to be encrypted,the encrypted file will have a file size of 1024 bytes. First, the 100 bytes
79  * will be padded to 512 and then 512 bytes will be added to store the size of the plain text file,useful when decrypting the file.
80  *
81  */
82 
83 static string_t crypt_mapper( const char * path,const char * key,u_int64_t key_len )
84 {
85  string_t p ;
86 
87  char * mpath = realpath( path,NULL ) ;
88 
89  if( mpath == NULL ){
90  return StringVoid ;
91  }
92 
93  /*
94  * ZULUCRYPTshortMapperPath is set in ../constants.h
95  * zuluCryptCreateMapperName() is defined at ../lib/create_mapper_name.c
96  */
97  p = zuluCryptCreateMapperName( mpath,strrchr( mpath,'/' ) + 1,0,ZULUCRYPTshortMapperPath ) ;
98 
99  if( zuluCryptOpenPlain( mpath,StringContent( p ),"rw",key,key_len ) != 0 ){
100  StringDelete( &p ) ;
101  }else{
102  StringMultiplePrepend( p,"/",crypt_get_dir(),NULL ) ;
103  }
104 
105  StringFree( mpath ) ;
106  return p ;
107 }
108 
109 static int zuluExit( int st,int f_in,int f_out,string_t p )
110 {
111  if( f_out != -1 ){
112  close( f_out ) ;
113  }
114  close( f_in ) ;
115 
117 
118  StringDelete( &p ) ;
119 
120  return st ;
121 }
122 
123 /*
124  * function responsible for creating a decrypted file
125  */
126 int zuluCryptDecryptFile( const char * source,const char * dest,const char * key,u_int64_t key_len )
127 {
128  struct stat st ;
129 
130  char buffer[ SIZE ] ;
131 
132  u_int64_t size ;
133  u_int64_t len ;
134  u_int64_t i ;
135 
136  int f_in ;
137  int f_out = -1 ;
138 
139  int test ;
140 
141  /*
142  * attach a mapper to the file containing encrypted data
143  */
144  string_t p = crypt_mapper( source,key,key_len ) ;
145 
146  if( p == StringVoid ){
147  return 1 ;
148  }
149  f_in = open( StringContent( p ),O_RDONLY ) ;
150 
151  /*
152  * 100 bytes from offset 100 and 100 bytes from offset 200 are supposed to be te same if
153  * the right key is used.
154  */
155  _read( f_in,buffer,SIZE ) ;
156 
157  if( memcmp( buffer + 100,buffer + 200,100 ) != 0 ){
158  return zuluExit( 2,f_in,f_out,p ) ;
159  }
160 
161  /*
162  * get the size of encrypted data
163  */
164  size = atoll( buffer ) ;
165 
166  /*
167  * Make sure the size of the encrypted file is with in expected range.
168  * It being out of range means either a wrong encrypted key was used or the encrypted file is corrupted.
169  *
170  * Because the padding can be up to 511 bytes and the header takes 512 bytes, the encrypted file will be
171  * larger and the different will be >= 512 and < 1024.
172  */
173  stat( source,&st ) ;
174 
175  test = st.st_size - size ;
176 
177  if( test < SIZE || test >= ( SIZE * 2 ) ){
178  return zuluExit( 2,f_in,f_out,p ) ;
179  }
180 
181  f_out = open( dest,O_WRONLY | O_CREAT,S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ) ;
182 
183  if( size <= SIZE ){
184  _read( f_in,buffer,size ) ;
185  _write( f_out,buffer,size ) ;
186  }else{
187  len = size / SIZE ;
188 
189  for( i = 0 ; i < len ; i++ ){
190 
191  _read( f_in,buffer,SIZE ) ;
192  _write( f_out,buffer,SIZE ) ;
193  }
194 
195  len = size - ( i * SIZE ) ;
196 
197  _read( f_in,buffer,len ) ;
198  _write( f_out,buffer,len ) ;
199  }
200 
201  return zuluExit( 0,f_in,f_out,p ) ;
202 }
203 
204 /*
205  * function responsible for creating an encrypted file
206  */
207 int zuluCryptEncryptFile( const char * source,const char * dest,const char * key,u_int64_t key_len )
208 {
209  string_t p ;
210  string_t q ;
211 
212  char buffer[ SIZE ] ;
213 
214  char r = '\0' ;
215 
216  int f_in ;
217  int f_out ;
218 
219  u_int64_t size ;
220  u_int64_t size_1 ;
221 
222  const char * mapper ;
223 
224  struct stat st ;
225 
226  stat( source,&st ) ;
227 
228  size = st.st_size ;
229 
230  /*
231  * make sure the encrypted file is a multiple of 512, important because data will be read/written in chunks of 512 bytes.
232  */
233  while( size % SIZE != 0 ){
234  size++ ;
235  }
236 
237  /*
238  * add 512 bytes to encrypted file, the exta space will be used to store the content size of the data to be encrypted.
239  */
240  size += SIZE ;
241 
242  memset( buffer,0,SIZE ) ;
243 
244  f_out = open( dest,O_WRONLY | O_CREAT,S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ) ;
245 
246  size_1 = 0 ;
247 
248  /*
249  * create a file to be used to store encrypted data.
250  */
251  while( 1 ){
252  _write( f_out,buffer,SIZE );
253 
254  size_1 += SIZE ;
255 
256  if( size_1 == size ){
257  break ;
258  }
259  }
260 
261  close( f_out ) ;
262 
263  /*
264  * attach a mapper to the file that will contain encrypted data
265  */
266  p = crypt_mapper( dest,key,key_len ) ;
267  if( p == StringVoid ){
268  remove( dest ) ;
269  return 1 ;
270  }
271 
272  mapper = StringContent( p ) ;
273 
274  f_out = open( mapper,O_WRONLY ) ;
275 
276  q = StringIntToString( st.st_size ) ;
277 
278  /*
279  * write the size of plain text file to the encrypted file. This information is important when decrypting the data
280  * because it tells us how much padding was applied if any.
281  *
282  */
283  _write( f_out,StringContent( q ),StringLength( q ) ) ;
284  _write( f_out,&r,1 ) ;
285 
286  /*
287  * write the same 100 byte random data in two locations to be used to check the decrypting key during decryption. *
288  */
289  f_in = open( "/dev/urandom",O_RDONLY ) ;
290  _read( f_in,buffer,100 ) ;
291  close( f_in ) ;
292 
293  lseek( f_out,100,SEEK_SET ) ;
294 
295  _write( f_out,buffer,100 ) ;
296  _write( f_out,buffer,100 ) ;
297 
298  /*
299  * set the beginning of the payload,The cypher text will start at byte 512.
300  */
301  lseek( f_out,SIZE,SEEK_SET ) ;
302 
303  f_in = open( source,O_RDONLY ) ;
304 
305  /*
306  * Copy over plain text data to the "shell" file through the mapper, creating an encrypted file.
307  */
308  while( read( f_in,buffer,SIZE ) > 0 ){
309  _write( f_out,buffer,SIZE ) ;
310  }
311  close( f_in ) ;
312  close( f_out ) ;
313 
314  zuluCryptCloseMapper( mapper ) ;
315 
316  StringMultipleDelete( &q,&p,NULL ) ;
317 
318  return 0 ;
319 }
320 
StringLength
size_t StringLength(string_t st)
Definition: String.c:678
zuluCryptEncryptFile
int zuluCryptEncryptFile(const char *source, const char *dest, const char *key, u_int64_t key_len)
Definition: file_encryption.c:207
SIZE
#define SIZE
Definition: file_encryption.c:36
zuluCryptCreateMapperName
string_t zuluCryptCreateMapperName(const char *device, const char *mapping_name, uid_t uid, int i)
Definition: create_mapper_name.c:42
zuluCryptOpenPlain
int zuluCryptOpenPlain(const char *device, const char *mapping_name, const char *mode, const char *passphrase, size_t passphrase_size)
Definition: open_plain.c:222
_write
static void _write(int x, const void *y, size_t z)
Definition: file_encryption.c:38
crypt_mapper
static string_t crypt_mapper(const char *path, const char *key, u_int64_t key_len)
Definition: file_encryption.c:83
StringContent
static const __inline__ char * StringContent(string_t st)
Definition: String.h:1011
StringType
Definition: String.c:49
StringMultipleDelete
void StringMultipleDelete(string_t *xt,...)
Definition: String.c:195
StringIntToString
string_t StringIntToString(u_int64_t z)
Definition: String.c:1404
zuluCryptCloseMapper
int zuluCryptCloseMapper(const char *mapper)
Definition: close_mapper.c:84
StringMultiplePrepend
const char * StringMultiplePrepend(string_t st,...)
Definition: String.c:1159
zuluCryptDecryptFile
int zuluCryptDecryptFile(const char *source, const char *dest, const char *key, u_int64_t key_len)
Definition: file_encryption.c:126
StringDelete
void StringDelete(string_t *st)
Definition: String.c:162
zuluExit
static int zuluExit(int st, int f_in, int f_out, string_t p)
Definition: file_encryption.c:109
includes.h
ZULUCRYPTshortMapperPath
#define ZULUCRYPTshortMapperPath
Definition: constants.h:35
StringFree
static __inline__ void StringFree(const void *str)
Definition: String.h:823
_read
static void _read(int x, void *y, size_t z)
Definition: file_encryption.c:42
StringVoid
#define StringVoid
Definition: String.h:47