Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 64ce7bb

Browse files
committed
Merge branch 'PGPRO-242-aes-ctr-encr' into PGPROEE9_6
2 parents cef538d + 7dfab09 commit 64ce7bb

File tree

7 files changed

+2006
-87
lines changed

7 files changed

+2006
-87
lines changed

src/backend/storage/file/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ subdir = src/backend/storage/file
1212
top_builddir = ../../../..
1313
include $(top_builddir)/src/Makefile.global
1414

15-
OBJS = fd.o cfs.o buffile.o copydir.o reinit.o
15+
OBJS = fd.o cfs.o buffile.o copydir.o reinit.o rijndael.o
1616

1717
include $(top_srcdir)/src/backend/common.mk

src/backend/storage/file/cfs.c

Lines changed: 117 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -245,95 +245,143 @@ char const* cfs_algorithm()
245245

246246
#endif
247247

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-
286248
/*
287249
* Get env variable PG_CIPHER_KEY and initialize encryption state.
288250
* Unset variable afterward.
289-
* Now implements cf4.
290251
*/
291-
static void cfs_encrypt_init(void)
252+
static void cfs_crypto_init(void)
292253
{
293-
int index1 = 0;
294-
int index2 = 0;
295-
int i;
296-
uint8 temp;
297254
int key_length;
298-
int x = 0, y = 0;
299255
char* cipher_key;
300-
uint8* rc4_init_state = cfs_state->cipher_key;
256+
uint8 aes_key[32] = {0}; /* at most 256 bits */
301257

302258
cipher_key = getenv("PG_CIPHER_KEY");
303259
if (cipher_key == NULL) {
304260
elog(ERROR, "PG_CIPHER_KEY environment variable is not set");
305261
}
306262
unsetenv("PG_CIPHER_KEY"); /* disable inspection of this environment variable */
307263
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+
}
325369
}
326370

327-
void cfs_encrypt(void* block, uint32 offs, uint32 size)
371+
void cfs_encrypt(const char* fname, void* block, uint32 offs, uint32 size)
328372
{
329373
if (cfs_encryption)
330-
cfs_rc4_encrypt_block(block, offs, size);
374+
{
375+
cfs_aes_crypt_block(fname, block, offs, size);
376+
}
331377
}
332378

333-
void cfs_decrypt(void* block, uint32 offs, uint32 size)
379+
void cfs_decrypt(const char* fname, void* block, uint32 offs, uint32 size)
334380
{
335381
if (cfs_encryption)
336-
cfs_rc4_encrypt_block(block, offs, size);
382+
{
383+
cfs_aes_crypt_block(fname, block, offs, size);
384+
}
337385
}
338386

339387
/* ----------------------------------------------------------------
@@ -351,7 +399,7 @@ void cfs_initialize()
351399
cfs_state->max_iterations = 0;
352400

353401
if (cfs_encryption)
354-
cfs_encrypt_init();
402+
cfs_crypto_init();
355403

356404
elog(LOG, "Start CFS version %s compression algorithm %s encryption %s",
357405
CFS_VERSION, cfs_algorithm(), cfs_encryption ? "enabled" : "disabled");
@@ -827,7 +875,7 @@ static bool cfs_gc_file(char* map_path)
827875
Assert(res == (off_t)CFS_INODE_OFFS(inode));
828876
rc = cfs_read_file(fd, block, size);
829877
Assert(rc);
830-
cfs_decrypt(block, (off_t)i*BLCKSZ, size);
878+
cfs_decrypt(file_bck_path, block, (off_t)i*BLCKSZ, size);
831879
res = cfs_decompress(decomressedBlock, BLCKSZ, block, size);
832880

833881
if (res != BLCKSZ)

src/backend/storage/file/fd.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1760,7 +1760,7 @@ FileRead(File file, char *buffer, int amount)
17601760
}
17611761
} while (size != 0);
17621762

1763-
cfs_decrypt(compressedBuffer, VfdCache[file].seekPos, amount);
1763+
cfs_decrypt(VfdCache[file].fileName, compressedBuffer, VfdCache[file].seekPos, amount);
17641764

17651765
returnCode = cfs_decompress(buffer, BLCKSZ, compressedBuffer, amount);
17661766
if (returnCode != BLCKSZ)
@@ -1786,9 +1786,10 @@ FileRead(File file, char *buffer, int amount)
17861786
returnCode = read(VfdCache[file].fd, buffer, amount);
17871787
if (returnCode >= 0)
17881788
{
1789-
if (VfdCache[file].fileFlags & PG_COMPRESSION)
1790-
cfs_decrypt(buffer, VfdCache[file].seekPos, amount);
1791-
1789+
if (VfdCache[file].fileFlags & PG_COMPRESSION)
1790+
{
1791+
cfs_decrypt(VfdCache[file].fileName, buffer, VfdCache[file].seekPos, amount);
1792+
}
17921793
VfdCache[file].seekPos += returnCode;
17931794
}
17941795
else
@@ -1901,16 +1902,17 @@ FileWrite(File file, char *buffer, int amount)
19011902
inode = CFS_INODE(compressedSize, pos);
19021903
buffer = compressedBuffer;
19031904
amount = compressedSize;
1905+
19041906
/* cfs_encrypt will check if encryption is actually needed */
1905-
cfs_encrypt(buffer, VfdCache[file].seekPos, amount);
1907+
cfs_encrypt(VfdCache[file].fileName, buffer, VfdCache[file].seekPos, amount);
19061908
}
19071909
else
19081910
{
19091911
if (cfs_encryption) /* we need to use buffer to perform encryption, so check if it is required */
19101912
{
19111913
memcpy(compressedBuffer, buffer, BLCKSZ);
19121914
buffer = compressedBuffer;
1913-
cfs_encrypt(buffer, VfdCache[file].seekPos, amount);
1915+
cfs_encrypt(VfdCache[file].fileName, buffer, VfdCache[file].seekPos, amount);
19141916
}
19151917

19161918
if (CFS_INODE_SIZE(inode) != BLCKSZ)

0 commit comments

Comments
 (0)