Skip to content

Commit c8770a6

Browse files
committed
Add support for 32 byte keys
It's a draft. Only Principal and WAL keys work so far
1 parent e5376c7 commit c8770a6

File tree

17 files changed

+149
-75
lines changed

17 files changed

+149
-75
lines changed

contrib/pg_tde/src/access/pg_tde_tdemap.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ typedef struct TDEMapEntry
7070
uint32 type; /* Part of AAD */
7171
uint32 _unused3; /* Part of AAD */
7272

73-
uint8 encrypted_key_data[INTERNAL_KEY_LEN];
73+
uint8 encrypted_key_data[INTERNAL_KEY_MAX_LEN];
7474
uint8 key_base_iv[INTERNAL_KEY_IV_LEN];
7575

7676
uint32 _unused1; /* Will be 1 in existing files entries. */
@@ -380,7 +380,7 @@ pg_tde_sign_principal_key_info(TDESignedPrincipalKeyInfo *signed_key_info, const
380380
errcode(ERRCODE_INTERNAL_ERROR),
381381
errmsg("could not generate iv for key map: %s", ERR_error_string(ERR_get_error(), NULL)));
382382

383-
AesGcmEncrypt(principal_key->keyData,
383+
AesGcmEncrypt(principal_key->keyData, principal_key->keyLength,
384384
signed_key_info->sign_iv, MAP_ENTRY_IV_SIZE,
385385
(unsigned char *) &signed_key_info->data, sizeof(signed_key_info->data),
386386
NULL, 0,
@@ -409,10 +409,10 @@ pg_tde_initialize_map_entry(TDEMapEntry *map_entry, const TDEPrincipalKey *princ
409409
errcode(ERRCODE_INTERNAL_ERROR),
410410
errmsg("could not generate iv for key map: %s", ERR_error_string(ERR_get_error(), NULL)));
411411

412-
AesGcmEncrypt(principal_key->keyData,
412+
AesGcmEncrypt(principal_key->keyData, principal_key->keyLength,
413413
map_entry->entry_iv, MAP_ENTRY_IV_SIZE,
414414
(unsigned char *) map_entry, offsetof(TDEMapEntry, encrypted_key_data),
415-
rel_key_data->key, INTERNAL_KEY_LEN,
415+
rel_key_data->key, INTERNAL_KEY_MAX_LEN,
416416
map_entry->encrypted_key_data,
417417
map_entry->aead_tag, MAP_ENTRY_AEAD_TAG_SIZE);
418418
}
@@ -573,7 +573,7 @@ pg_tde_count_encryption_keys(Oid dbOid)
573573
bool
574574
pg_tde_verify_principal_key_info(TDESignedPrincipalKeyInfo *signed_key_info, const KeyData *principal_key_data)
575575
{
576-
return AesGcmDecrypt(principal_key_data->data,
576+
return AesGcmDecrypt(principal_key_data->data, principal_key_data->len,
577577
signed_key_info->sign_iv, MAP_ENTRY_IV_SIZE,
578578
(unsigned char *) &signed_key_info->data, sizeof(signed_key_info->data),
579579
NULL, 0,
@@ -588,10 +588,10 @@ tde_decrypt_rel_key(const TDEPrincipalKey *principal_key, TDEMapEntry *map_entry
588588

589589
Assert(principal_key);
590590

591-
if (!AesGcmDecrypt(principal_key->keyData,
591+
if (!AesGcmDecrypt(principal_key->keyData, principal_key->keyLength,
592592
map_entry->entry_iv, MAP_ENTRY_IV_SIZE,
593593
(unsigned char *) map_entry, offsetof(TDEMapEntry, encrypted_key_data),
594-
map_entry->encrypted_key_data, INTERNAL_KEY_LEN,
594+
map_entry->encrypted_key_data, INTERNAL_KEY_MAX_LEN,
595595
key->key,
596596
map_entry->aead_tag, MAP_ENTRY_AEAD_TAG_SIZE))
597597
ereport(ERROR,

contrib/pg_tde/src/access/pg_tde_xlog_keys.c

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
#include "pg_tde_fe.h"
2323
#endif
2424

25-
#define PG_TDE_WAL_KEY_FILE_MAGIC 0x014B4557 /* version ID value = WEK 01 */
25+
#define PG_TDE_WAL_KEY_FILE_MAGIC_OLD 0x014B4557 /* old version ID value = WEK 01 */
26+
#define PG_TDE_WAL_KEY_FILE_MAGIC 0x024B4557 /* version ID value = WEK 02 */
2627
#define PG_TDE_WAL_KEY_FILE_NAME "wal_keys"
2728

2829
typedef struct WalKeyFileHeader
@@ -40,12 +41,12 @@ typedef struct WalKeyFileHeader
4041
* encrypting/decrypting existing keys from the key files, so any changes here
4142
* might break existing clusters.
4243
*/
43-
typedef struct WalKeyFileEntry
44+
typedef struct WalKeyFileEntryOld
4445
{
4546
uint32 _unused1; /* Part of AAD, is 1 or 2 in existing entries */
4647
uint32 _unused2; /* Part of AAD */
4748

48-
uint8 encrypted_key_data[INTERNAL_KEY_LEN];
49+
uint8 encrypted_key_data[INTERNAL_KEY_OLD_LEN];
4950
uint8 key_base_iv[INTERNAL_KEY_IV_LEN];
5051

5152
uint32 range_type; /* WalEncryptionRangeType */
@@ -55,6 +56,20 @@ typedef struct WalKeyFileEntry
5556
/* IV and tag used when encrypting the key itself */
5657
unsigned char entry_iv[MAP_ENTRY_IV_SIZE];
5758
unsigned char aead_tag[MAP_ENTRY_AEAD_TAG_SIZE];
59+
} WalKeyFileEntryOld;
60+
61+
typedef struct WalKeyFileEntry
62+
{
63+
uint32 key_len;
64+
uint32 range_type; /* WalEncryptionRangeType */
65+
WalLocation range_start;
66+
67+
/* IV and tag used when encrypting the key itself */
68+
unsigned char entry_iv[MAP_ENTRY_IV_SIZE];
69+
unsigned char aead_tag[MAP_ENTRY_AEAD_TAG_SIZE];
70+
71+
uint8 key_base_iv[INTERNAL_KEY_IV_LEN];
72+
uint8 encrypted_key_data[INTERNAL_KEY_MAX_LEN];
5873
} WalKeyFileEntry;
5974

6075
static WALKeyCacheRec *tde_wal_key_cache = NULL;
@@ -178,7 +193,7 @@ pg_tde_wal_last_range_set_location(WalLocation loc)
178193
* with the actual lsn by the first WAL write.
179194
*/
180195
void
181-
pg_tde_create_wal_range(WalEncryptionRange *range, WalEncryptionRangeType type)
196+
pg_tde_create_wal_range(WalEncryptionRange *range, WalEncryptionRangeType type, int key_len)
182197
{
183198
TDEPrincipalKey *principal_key;
184199

@@ -199,7 +214,7 @@ pg_tde_create_wal_range(WalEncryptionRange *range, WalEncryptionRangeType type)
199214
range->end.lsn = MaxXLogRecPtr;
200215
range->end.tli = MaxTimeLineID;
201216

202-
pg_tde_generate_internal_key(&range->key);
217+
pg_tde_generate_internal_key(&range->key, key_len);
203218

204219
pg_tde_write_wal_key_file_entry(range, principal_key);
205220

@@ -615,12 +630,13 @@ pg_tde_wal_range_from_entry(const TDEPrincipalKey *principal_key, WalKeyFileEntr
615630
range->start = entry->range_start;
616631
range->end.tli = MaxTimeLineID;
617632
range->end.lsn = MaxXLogRecPtr;
633+
range->key.key_len = entry->key_len;
618634

619635
memcpy(range->key.base_iv, entry->key_base_iv, INTERNAL_KEY_IV_LEN);
620-
if (!AesGcmDecrypt(principal_key->keyData,
636+
if (!AesGcmDecrypt(principal_key->keyData, principal_key->keyLength,
621637
entry->entry_iv, MAP_ENTRY_IV_SIZE,
622-
(unsigned char *) entry, offsetof(WalKeyFileEntry, encrypted_key_data),
623-
entry->encrypted_key_data, INTERNAL_KEY_LEN,
638+
(unsigned char *) entry, offsetof(WalKeyFileEntry, range_start),
639+
entry->encrypted_key_data, entry->key_len,
624640
range->key.key,
625641
entry->aead_tag, MAP_ENTRY_AEAD_TAG_SIZE))
626642
ereport(ERROR,
@@ -664,13 +680,7 @@ pg_tde_initialize_wal_key_file_entry(WalKeyFileEntry *entry,
664680

665681
memset(entry, 0, sizeof(WalKeyFileEntry));
666682

667-
/*
668-
* We set this field here so that existing file entries will be consistent
669-
* and future use of this field easier. Some existing entries will have 2
670-
* here.
671-
*/
672-
entry->_unused1 = 1;
673-
683+
entry->key_len = range->key.key_len;
674684
entry->range_type = range->type;
675685
entry->range_start = range->start;
676686
memcpy(entry->key_base_iv, range->key.base_iv, INTERNAL_KEY_IV_LEN);
@@ -680,10 +690,10 @@ pg_tde_initialize_wal_key_file_entry(WalKeyFileEntry *entry,
680690
errcode(ERRCODE_INTERNAL_ERROR),
681691
errmsg("could not generate iv for wal key file entry: %s", ERR_error_string(ERR_get_error(), NULL)));
682692

683-
AesGcmEncrypt(principal_key->keyData,
693+
AesGcmEncrypt(principal_key->keyData, principal_key->keyLength,
684694
entry->entry_iv, MAP_ENTRY_IV_SIZE,
685-
(unsigned char *) entry, offsetof(WalKeyFileEntry, encrypted_key_data),
686-
range->key.key, INTERNAL_KEY_LEN,
695+
(unsigned char *) entry, offsetof(WalKeyFileEntry, range_start),
696+
range->key.key, range->key.key_len,
687697
entry->encrypted_key_data,
688698
entry->aead_tag, MAP_ENTRY_AEAD_TAG_SIZE);
689699
}

contrib/pg_tde/src/access/pg_tde_xlog_smgr.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ TDEXLogSmgrInit()
221221
}
222222

223223
void
224-
TDEXLogSmgrInitWrite(bool encrypt_xlog)
224+
TDEXLogSmgrInitWrite(bool encrypt_xlog, int key_len)
225225
{
226226
WalEncryptionRange *range;
227227
WALKeyCacheRec *keys;
@@ -242,11 +242,11 @@ TDEXLogSmgrInitWrite(bool encrypt_xlog)
242242
*/
243243
if (encrypt_xlog)
244244
{
245-
pg_tde_create_wal_range(&CurrentWalEncryptionRange, WAL_ENCRYPTION_RANGE_ENCRYPTED);
245+
pg_tde_create_wal_range(&CurrentWalEncryptionRange, WAL_ENCRYPTION_RANGE_ENCRYPTED, key_len);
246246
}
247247
else if (range && range->type == WAL_ENCRYPTION_RANGE_ENCRYPTED)
248248
{
249-
pg_tde_create_wal_range(&CurrentWalEncryptionRange, WAL_ENCRYPTION_RANGE_UNENCRYPTED);
249+
pg_tde_create_wal_range(&CurrentWalEncryptionRange, WAL_ENCRYPTION_RANGE_UNENCRYPTED, key_len);
250250
}
251251
else if (range)
252252
{
@@ -353,6 +353,7 @@ TDEXLogWriteEncryptedPages(int fd, const void *buf, size_t count, off_t offset,
353353
count,
354354
enc_buff,
355355
range->key.key,
356+
range->key.key_len,
356357
&EncryptionCryptCtx);
357358

358359
return pg_pwrite(fd, enc_buff, count, offset);
@@ -584,6 +585,7 @@ TDEXLogCryptBuffer(const void *buf, void *out_buf, size_t count, off_t offset,
584585
dec_sz,
585586
o_buf,
586587
curr_key->range.key.key,
588+
curr_key->range.key.key_len,
587589
&curr_key->crypt_ctx);
588590
}
589591
}

contrib/pg_tde/src/catalog/tde_principal_key.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,6 @@ typedef struct TdePrincipalKeylocalState
6262
dshash_table *sharedHash;
6363
} TdePrincipalKeylocalState;
6464

65-
/* Length of newly generated principal keys */
66-
#define PRINCIPAL_KEY_LEN 16
67-
6865
/* Parameters for the principal key info shared hash */
6966
static dshash_parameters principal_key_dsh_params = {
7067
.key_size = sizeof(Oid),
@@ -534,7 +531,7 @@ pg_tde_create_principal_key_internal(Oid providerOid,
534531
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
535532
errmsg("cannot create key \"%s\" because it already exists", key_name));
536533

537-
key_info = KeyringGenerateNewKeyAndStore(provider, key_name, PRINCIPAL_KEY_LEN);
534+
key_info = KeyringGenerateNewKeyAndStore(provider, key_name, TdeKeyLength);
538535

539536
pfree(key_info);
540537
pfree(provider);

contrib/pg_tde/src/encryption/enc_aes.c

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ static const EVP_CIPHER *cipher_cbc = NULL;
3636
static const EVP_CIPHER *cipher_gcm = NULL;
3737
static const EVP_CIPHER *cipher_ctr_ecb = NULL;
3838

39+
static const EVP_CIPHER *cipher_cbc_256 = NULL;
40+
static const EVP_CIPHER *cipher_gcm_256 = NULL;
41+
static const EVP_CIPHER *cipher_ctr_ecb_256 = NULL;
42+
3943
void
4044
AesInit(void)
4145
{
@@ -45,21 +49,26 @@ AesInit(void)
4549
cipher_cbc = EVP_aes_128_cbc();
4650
cipher_gcm = EVP_aes_128_gcm();
4751
cipher_ctr_ecb = EVP_aes_128_ecb();
52+
53+
cipher_cbc_256 = EVP_aes_256_cbc();
54+
cipher_gcm_256 = EVP_aes_256_gcm();
55+
cipher_ctr_ecb_256 = EVP_aes_256_ecb();
4856
}
4957

5058
static void
51-
AesEcbEncrypt(EVP_CIPHER_CTX **ctxPtr, const unsigned char *key, const unsigned char *in, int in_len, unsigned char *out)
59+
AesEcbEncrypt(EVP_CIPHER_CTX **ctxPtr, const unsigned char *key, int key_len, const unsigned char *in, int in_len, unsigned char *out)
5260
{
5361
int out_len;
62+
const EVP_CIPHER *cipher = key_len == 32 ? cipher_ctr_ecb_256 : cipher_ctr_ecb;
5463

5564
if (*ctxPtr == NULL)
5665
{
57-
Assert(cipher_ctr_ecb != NULL);
66+
Assert(cipher != NULL);
5867

5968
*ctxPtr = EVP_CIPHER_CTX_new();
6069
EVP_CIPHER_CTX_init(*ctxPtr);
6170

62-
if (EVP_CipherInit_ex(*ctxPtr, cipher_ctr_ecb, NULL, key, NULL, 1) == 0)
71+
if (EVP_CipherInit_ex(*ctxPtr, cipher, NULL, key, NULL, 1) == 0)
6372
ereport(ERROR,
6473
errmsg("EVP_CipherInit_ex failed. OpenSSL error: %s", ERR_error_string(ERR_get_error(), NULL)));
6574

@@ -74,19 +83,20 @@ AesEcbEncrypt(EVP_CIPHER_CTX **ctxPtr, const unsigned char *key, const unsigned
7483
}
7584

7685
static void
77-
AesRunCbc(int enc, const unsigned char *key, const unsigned char *iv, const unsigned char *in, int in_len, unsigned char *out)
86+
AesRunCbc(int enc, const unsigned char *key, int key_len, const unsigned char *iv, const unsigned char *in, int in_len, unsigned char *out)
7887
{
7988
int out_len;
8089
int out_len_final;
8190
EVP_CIPHER_CTX *ctx = NULL;
91+
const EVP_CIPHER *cipher = key_len == 32 ? cipher_cbc_256 : cipher_cbc;
8292

83-
Assert(cipher_cbc != NULL);
84-
Assert(in_len % EVP_CIPHER_block_size(cipher_cbc) == 0);
93+
Assert(cipher != NULL);
94+
Assert(in_len % EVP_CIPHER_block_size(cipher) == 0);
8595

8696
ctx = EVP_CIPHER_CTX_new();
8797
EVP_CIPHER_CTX_init(ctx);
8898

89-
if (EVP_CipherInit_ex(ctx, cipher_cbc, NULL, key, iv, enc) == 0)
99+
if (EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc) == 0)
90100
ereport(ERROR,
91101
errmsg("EVP_CipherInit_ex failed. OpenSSL error: %s", ERR_error_string(ERR_get_error(), NULL)));
92102

@@ -112,31 +122,32 @@ AesRunCbc(int enc, const unsigned char *key, const unsigned char *iv, const unsi
112122
}
113123

114124
void
115-
AesEncrypt(const unsigned char *key, const unsigned char *iv, const unsigned char *in, int in_len, unsigned char *out)
125+
AesEncrypt(const unsigned char *key, int key_len, const unsigned char *iv, const unsigned char *in, int in_len, unsigned char *out)
116126
{
117-
AesRunCbc(1, key, iv, in, in_len, out);
127+
AesRunCbc(1, key, key_len, iv, in, in_len, out);
118128
}
119129

120130
void
121-
AesDecrypt(const unsigned char *key, const unsigned char *iv, const unsigned char *in, int in_len, unsigned char *out)
131+
AesDecrypt(const unsigned char *key, int key_len, const unsigned char *iv, const unsigned char *in, int in_len, unsigned char *out)
122132
{
123-
AesRunCbc(0, key, iv, in, in_len, out);
133+
AesRunCbc(0, key, key_len, iv, in, in_len, out);
124134
}
125135

126136
void
127-
AesGcmEncrypt(const unsigned char *key, const unsigned char *iv, int iv_len, const unsigned char *aad, int aad_len, const unsigned char *in, int in_len, unsigned char *out, unsigned char *tag, int tag_len)
137+
AesGcmEncrypt(const unsigned char *key, int key_len, const unsigned char *iv, int iv_len, const unsigned char *aad, int aad_len, const unsigned char *in, int in_len, unsigned char *out, unsigned char *tag, int tag_len)
128138
{
129139
int out_len;
130140
int out_len_final;
131141
EVP_CIPHER_CTX *ctx;
142+
const EVP_CIPHER *cipher = key_len == 32 ? cipher_gcm_256 : cipher_gcm;
132143

133-
Assert(cipher_gcm != NULL);
134-
Assert(in_len % EVP_CIPHER_block_size(cipher_gcm) == 0);
144+
Assert(cipher != NULL);
145+
Assert(in_len % EVP_CIPHER_block_size(cipher) == 0);
135146

136147
ctx = EVP_CIPHER_CTX_new();
137148
EVP_CIPHER_CTX_init(ctx);
138149

139-
if (EVP_EncryptInit_ex(ctx, cipher_gcm, NULL, NULL, NULL) == 0)
150+
if (EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL) == 0)
140151
ereport(ERROR,
141152
errmsg("EVP_EncryptInit_ex failed. OpenSSL error: %s", ERR_error_string(ERR_get_error(), NULL)));
142153

@@ -180,18 +191,19 @@ AesGcmEncrypt(const unsigned char *key, const unsigned char *iv, int iv_len, con
180191
}
181192

182193
bool
183-
AesGcmDecrypt(const unsigned char *key, const unsigned char *iv, int iv_len, const unsigned char *aad, int aad_len, const unsigned char *in, int in_len, unsigned char *out, unsigned char *tag, int tag_len)
194+
AesGcmDecrypt(const unsigned char *key, int key_len, const unsigned char *iv, int iv_len, const unsigned char *aad, int aad_len, const unsigned char *in, int in_len, unsigned char *out, unsigned char *tag, int tag_len)
184195
{
185196
int out_len;
186197
int out_len_final;
187198
EVP_CIPHER_CTX *ctx;
199+
const EVP_CIPHER *cipher = key_len == 32 ? cipher_gcm_256 : cipher_gcm;
188200

189-
Assert(in_len % EVP_CIPHER_block_size(cipher_gcm) == 0);
201+
Assert(in_len % EVP_CIPHER_block_size(cipher) == 0);
190202

191203
ctx = EVP_CIPHER_CTX_new();
192204
EVP_CIPHER_CTX_init(ctx);
193205

194-
if (EVP_DecryptInit_ex(ctx, cipher_gcm, NULL, NULL, NULL) == 0)
206+
if (EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL) == 0)
195207
ereport(ERROR,
196208
errmsg("EVP_EncryptInit_ex failed. OpenSSL error: %s", ERR_error_string(ERR_get_error(), NULL)));
197209

@@ -243,7 +255,7 @@ AesGcmDecrypt(const unsigned char *key, const unsigned char *iv, int iv_len, con
243255
* This function assumes that the out buffer is big enough: at least (blockNumber2 - blockNumber1) * 16 bytes
244256
*/
245257
void
246-
AesCtrEncryptedZeroBlocks(void *ctxPtr, const unsigned char *key, const char *iv_prefix, uint64_t blockNumber1, uint64_t blockNumber2, unsigned char *out)
258+
AesCtrEncryptedZeroBlocks(void *ctxPtr, const unsigned char *key, int key_len, const char *iv_prefix, uint64_t blockNumber1, uint64_t blockNumber2, unsigned char *out)
247259
{
248260
unsigned char *p;
249261

@@ -265,5 +277,5 @@ AesCtrEncryptedZeroBlocks(void *ctxPtr, const unsigned char *key, const char *iv
265277
p += sizeof(j);
266278
}
267279

268-
AesEcbEncrypt(ctxPtr, key, out, p - out, out);
280+
AesEcbEncrypt(ctxPtr, key, key_len, out, p - out, out);
269281
}

0 commit comments

Comments
 (0)