@@ -245,95 +245,143 @@ char const* cfs_algorithm()
245
245
246
246
#endif
247
247
248
-
249
- /* ----------------------------------------------------------------
250
- * Section 2: Encryption related functionality.
251
- *
252
- * TODO
253
- * - replace rc4 algrithm with something more appropriate
254
- * - add more comments
255
- * ----------------------------------------------------------------
256
- */
257
- static void cfs_rc4_encrypt_block (void * block , uint32 offs , uint32 block_size )
258
- {
259
- uint32 i ;
260
- uint8 temp ;
261
- uint8 * dst = (uint8 * )block ;
262
- int next_state ;
263
- uint8 state [CFS_CIPHER_KEY_SIZE ];
264
- int x = 0 , y = 0 ;
265
- uint32 skip = (offs / BLCKSZ + block_size ) % CFS_CIPHER_KEY_SIZE ;
266
-
267
- memcpy (state , cfs_state -> cipher_key , CFS_CIPHER_KEY_SIZE );
268
- for (i = 0 ; i < skip ; i ++ ) {
269
- x = (x + 1 ) % CFS_CIPHER_KEY_SIZE ;
270
- y = (y + state [x ]) % CFS_CIPHER_KEY_SIZE ;
271
- temp = state [x ];
272
- state [x ] = state [y ];
273
- state [y ] = temp ;
274
- }
275
- for (i = 0 ; i < block_size ; i ++ ) {
276
- x = (x + 1 ) % CFS_CIPHER_KEY_SIZE ;
277
- y = (y + state [x ]) % CFS_CIPHER_KEY_SIZE ;
278
- temp = state [x ];
279
- state [x ] = state [y ];
280
- state [y ] = temp ;
281
- next_state = (state [x ] + state [y ]) % CFS_CIPHER_KEY_SIZE ;
282
- dst [i ] ^= state [next_state ];
283
- }
284
- }
285
-
286
248
/*
287
249
* Get env variable PG_CIPHER_KEY and initialize encryption state.
288
250
* Unset variable afterward.
289
- * Now implements cf4.
290
251
*/
291
- static void cfs_encrypt_init (void )
252
+ static void cfs_crypto_init (void )
292
253
{
293
- int index1 = 0 ;
294
- int index2 = 0 ;
295
- int i ;
296
- uint8 temp ;
297
254
int key_length ;
298
- int x = 0 , y = 0 ;
299
255
char * cipher_key ;
300
- uint8 * rc4_init_state = cfs_state -> cipher_key ;
256
+ uint8 aes_key [ 32 ] = { 0 }; /* at most 256 bits */
301
257
302
258
cipher_key = getenv ("PG_CIPHER_KEY" );
303
259
if (cipher_key == NULL ) {
304
260
elog (ERROR , "PG_CIPHER_KEY environment variable is not set" );
305
261
}
306
262
unsetenv ("PG_CIPHER_KEY" ); /* disable inspection of this environment variable */
307
263
key_length = strlen (cipher_key );
308
- for (i = 0 ; i < CFS_CIPHER_KEY_SIZE ; ++ i ) {
309
- rc4_init_state [i ] = (uint8 )i ;
310
- }
311
- for (i = 0 ; i < CFS_CIPHER_KEY_SIZE ; ++ i ) {
312
- index2 = (cipher_key [index1 ] + rc4_init_state [i ] + index2 ) % CFS_CIPHER_KEY_SIZE ;
313
- temp = rc4_init_state [i ];
314
- rc4_init_state [i ] = rc4_init_state [index2 ];
315
- rc4_init_state [index2 ] = temp ;
316
- index1 = (index1 + 1 ) % key_length ;
317
- }
318
- for (i = 0 ; i < CFS_RC4_DROP_N ; i ++ ) {
319
- x = (x + 1 ) % CFS_CIPHER_KEY_SIZE ;
320
- y = (y + rc4_init_state [x ]) % CFS_CIPHER_KEY_SIZE ;
321
- temp = rc4_init_state [x ];
322
- rc4_init_state [x ] = rc4_init_state [y ];
323
- rc4_init_state [y ] = temp ;
324
- }
264
+
265
+ memcpy (& aes_key , cipher_key , key_length > sizeof (aes_key ) ? sizeof (aes_key ) : key_length );
266
+ rijndael_set_key (
267
+ & cfs_state -> aes_context , /* context */
268
+ (u4byte * )& aes_key , /* key */
269
+ sizeof (aes_key ) * 8 /* key size in bits */ ,
270
+ 1 /* for CTR mode we need only encryption */
271
+ );
272
+ }
273
+
274
+ /*
275
+ * For a file name like 'path/to/16384/16401[.123]' return part1 = 16384, part2 = 16401 and part3 = 123.
276
+ * Returns 0 on success and negative value on error.
277
+ */
278
+ static int extract_fname_parts (const char * fname , uint32 * part1 , uint32 * part2 , uint32 * part3 )
279
+ {
280
+ int idx = strlen (fname );
281
+ if (idx == 0 )
282
+ return -1 ;
283
+ idx -- ;
284
+
285
+ while (idx >= 0 && isdigit (fname [idx ]))
286
+ idx -- ;
287
+
288
+ if (idx == 0 )
289
+ return -2 ;
290
+
291
+ if (fname [idx ] != '.' )
292
+ {
293
+ * part3 = 0 ;
294
+ goto assign_part2 ;
295
+ }
296
+
297
+ * part3 = atoi (& fname [idx + 1 ]);
298
+
299
+ idx -- ;
300
+ while (idx >= 0 && isdigit (fname [idx ]))
301
+ idx -- ;
302
+
303
+ if (idx == 0 )
304
+ return -3 ;
305
+
306
+ assign_part2 :
307
+ * part2 = atoi (& fname [idx + 1 ]);
308
+
309
+ idx -- ;
310
+ while (idx >= 0 && isdigit (fname [idx ]))
311
+ idx -- ;
312
+
313
+ if (idx == 0 )
314
+ return -4 ;
315
+
316
+ * part1 = atoi (& fname [idx + 1 ]);
317
+ return 0 ;
318
+ }
319
+
320
+ /* Encryption and decryption using AES in CTR mode */
321
+ static void cfs_aes_crypt_block (const char * fname , void * block , uint32 offs , uint32 size )
322
+ {
323
+ /*
324
+ #define AES_DEBUG 1
325
+ */
326
+ uint32 aes_in [4 ]; /* 16 bytes, 128 bits */
327
+ uint32 aes_out [4 ];
328
+ uint8 * plaintext = (uint8 * )block ;
329
+ uint8 * gamma = (uint8 * )& aes_out ;
330
+ uint32 i , fname_part1 , fname_part2 , fname_part3 ;
331
+
332
+ if (extract_fname_parts (fname , & fname_part1 , & fname_part2 , & fname_part3 ) < 0 )
333
+ fname_part1 = fname_part2 = fname_part3 = 0 ;
334
+
335
+ #ifdef AES_DEBUG
336
+ elog (LOG , "cfs_aes_crypt_block, fname = %s, part1 = %d, part2 = %d, part3 = %d, offs = %d, size = %d" ,
337
+ fname , fname_part1 , fname_part2 , fname_part3 , offs , size );
338
+ #endif
339
+
340
+ aes_in [0 ] = fname_part1 ;
341
+ aes_in [1 ] = fname_part2 ;
342
+ aes_in [2 ] = fname_part3 ;
343
+ aes_in [3 ] = offs & 0xFFFFFFF0 ;
344
+ rijndael_encrypt (& cfs_state -> aes_context , (u4byte * )& aes_in , (u4byte * )& aes_out );
345
+
346
+ #ifdef AES_DEBUG
347
+ elog (LOG , "cfs_aes_crypt_block, in = %08X %08X %08X %08X, out = %08X %08X %08X %08X" ,
348
+ aes_in [0 ], aes_in [1 ], aes_in [2 ], aes_in [3 ],
349
+ aes_out [0 ], aes_out [1 ], aes_out [2 ], aes_out [3 ]);
350
+ #endif
351
+
352
+ for (i = 0 ; i < size ; i ++ )
353
+ {
354
+ plaintext [i ] ^= gamma [offs & 0xF ];
355
+ offs ++ ;
356
+ if ((offs & 0xF ) == 0 )
357
+ {
358
+ /* Prepare next gamma part */
359
+ aes_in [3 ] = offs ;
360
+ rijndael_encrypt (& cfs_state -> aes_context , (u4byte * )& aes_in , (u4byte * )& aes_out );
361
+
362
+ #ifdef AES_DEBUG
363
+ elog (LOG , "cfs_aes_crypt_block, in = %08X %08X %08X %08X, out = %08X %08X %08X %08X" ,
364
+ aes_in [0 ], aes_in [1 ], aes_in [2 ], aes_in [3 ],
365
+ aes_out [0 ], aes_out [1 ], aes_out [2 ], aes_out [3 ]);
366
+ #endif
367
+ }
368
+ }
325
369
}
326
370
327
- void cfs_encrypt (void * block , uint32 offs , uint32 size )
371
+ void cfs_encrypt (const char * fname , void * block , uint32 offs , uint32 size )
328
372
{
329
373
if (cfs_encryption )
330
- cfs_rc4_encrypt_block (block , offs , size );
374
+ {
375
+ cfs_aes_crypt_block (fname , block , offs , size );
376
+ }
331
377
}
332
378
333
- void cfs_decrypt (void * block , uint32 offs , uint32 size )
379
+ void cfs_decrypt (const char * fname , void * block , uint32 offs , uint32 size )
334
380
{
335
381
if (cfs_encryption )
336
- cfs_rc4_encrypt_block (block , offs , size );
382
+ {
383
+ cfs_aes_crypt_block (fname , block , offs , size );
384
+ }
337
385
}
338
386
339
387
/* ----------------------------------------------------------------
@@ -351,7 +399,7 @@ void cfs_initialize()
351
399
cfs_state -> max_iterations = 0 ;
352
400
353
401
if (cfs_encryption )
354
- cfs_encrypt_init ();
402
+ cfs_crypto_init ();
355
403
356
404
elog (LOG , "Start CFS version %s compression algorithm %s encryption %s" ,
357
405
CFS_VERSION , cfs_algorithm (), cfs_encryption ? "enabled" : "disabled" );
@@ -827,7 +875,7 @@ static bool cfs_gc_file(char* map_path)
827
875
Assert (res == (off_t )CFS_INODE_OFFS (inode ));
828
876
rc = cfs_read_file (fd , block , size );
829
877
Assert (rc );
830
- cfs_decrypt (block , (off_t )i * BLCKSZ , size );
878
+ cfs_decrypt (file_bck_path , block , (off_t )i * BLCKSZ , size );
831
879
res = cfs_decompress (decomressedBlock , BLCKSZ , block , size );
832
880
833
881
if (res != BLCKSZ )
0 commit comments