Skip to content

Commit e514ac5

Browse files
authored
Enhance pg_tde SMGR handling: (#316)
* Enhance pg_tde SMGR handling: Store the encryption key for tde_heap relations in the SmgrRelation to reduce frequent key lookups. Additionally, avoid encrypting relation forks other than MAIN and INIT forks.
1 parent 5ca8ede commit e514ac5

File tree

2 files changed

+82
-30
lines changed

2 files changed

+82
-30
lines changed

src/pg_tde.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ void on_ext_install(pg_tde_on_ext_install_callback function, void *arg)
163163
}
164164

165165
/* ------------------
166-
* Run all of the on_ext_install routines and exexute those one by one
166+
* Run all of the on_ext_install routines and execute those one by one
167167
* ------------------
168168
*/
169169
static void

src/smgr/pg_tde_smgr.c

+81-29
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,32 @@
1010

1111
#ifdef PERCONA_EXT
1212

13+
typedef struct TDESMgrRelationData
14+
{
15+
/* parent data */
16+
SMgrRelationData reln;
17+
/*
18+
* for md.c; per-fork arrays of the number of open segments
19+
* (md_num_open_segs) and the segments themselves (md_seg_fds).
20+
*/
21+
int md_num_open_segs[MAX_FORKNUM + 1];
22+
struct _MdfdVec *md_seg_fds[MAX_FORKNUM + 1];
23+
24+
bool encrypted_relation;
25+
RelKeyData relKey;
26+
} TDESMgrRelationData;
27+
28+
typedef TDESMgrRelationData *TDESMgrRelation;
29+
30+
/*
31+
* we only encrypt main and init forks
32+
*/
33+
static inline bool
34+
tde_is_encryption_required(TDESMgrRelation tdereln, ForkNumber forknum)
35+
{
36+
return (tdereln->encrypted_relation && (forknum == MAIN_FORKNUM || forknum == INIT_FORKNUM));
37+
}
38+
1339
static RelKeyData*
1440
tde_smgr_get_key(SMgrRelation reln)
1541
{
@@ -62,22 +88,21 @@ static void
6288
tde_mdwritev(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
6389
const void **buffers, BlockNumber nblocks, bool skipFsync)
6490
{
65-
AesInit();
66-
67-
RelKeyData* rkd = tde_smgr_get_key(reln);
91+
TDESMgrRelation tdereln = (TDESMgrRelation)reln;
92+
RelKeyData *rkd = &tdereln->relKey;
6893

69-
if(rkd == NULL)
94+
if (!tde_is_encryption_required(tdereln, forknum))
7095
{
7196
mdwritev(reln, forknum, blocknum, buffers, nblocks, skipFsync);
72-
73-
return;
7497
}
7598
else
7699
{
77100
char *local_blocks = palloc(BLCKSZ * (nblocks + 1));
78101
char *local_blocks_aligned = (char *)TYPEALIGN(PG_IO_ALIGN_SIZE, local_blocks);
79102
const void **local_buffers = palloc(sizeof(void *) * nblocks);
80103

104+
AesInit();
105+
81106
for(int i = 0; i < nblocks; ++i )
82107
{
83108
int out_len = BLCKSZ;
@@ -102,29 +127,26 @@ static void
102127
tde_mdextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
103128
const void *buffer, bool skipFsync)
104129
{
105-
RelKeyData *rkd;
130+
TDESMgrRelation tdereln = (TDESMgrRelation)reln;
131+
RelKeyData *rkd = &tdereln->relKey;
106132

107-
AesInit();
108-
109-
rkd = tde_smgr_get_key(reln);
110-
111-
if(rkd == NULL)
133+
if (!tde_is_encryption_required(tdereln, forknum))
112134
{
113135
mdextend(reln, forknum, blocknum, buffer, skipFsync);
114-
115-
return;
116136
}
117137
else
118138
{
119-
120139
char *local_blocks = palloc(BLCKSZ * (1 + 1));
121140
char *local_blocks_aligned = (char *)TYPEALIGN(PG_IO_ALIGN_SIZE, local_blocks);
122141
int out_len = BLCKSZ;
142+
unsigned char iv[16] = {
143+
0,
144+
};
123145

124-
unsigned char iv[16] = {0,};
125-
memcpy(iv+4, &blocknum, sizeof(BlockNumber));
146+
AesInit();
147+
memcpy(iv + 4, &blocknum, sizeof(BlockNumber));
126148

127-
AesEncrypt(rkd->internal_key.key, iv, ((char*)buffer), BLCKSZ, local_blocks_aligned, &out_len);
149+
AesEncrypt(rkd->internal_key.key, iv, ((char *)buffer), BLCKSZ, local_blocks_aligned, &out_len);
128150

129151
mdextend(reln, forknum, blocknum, local_blocks_aligned, skipFsync);
130152

@@ -136,21 +158,23 @@ static void
136158
tde_mdreadv(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
137159
void **buffers, BlockNumber nblocks)
138160
{
139-
RelKeyData *rkd;
140161
int out_len = BLCKSZ;
141-
142-
AesInit();
162+
TDESMgrRelation tdereln = (TDESMgrRelation)reln;
163+
RelKeyData *rkd = &tdereln->relKey;
143164

144165
mdreadv(reln, forknum, blocknum, buffers, nblocks);
145166

146-
rkd = tde_smgr_get_key(reln);
147-
148-
if(rkd == NULL)
167+
if (!tde_is_encryption_required(tdereln, forknum))
149168
return;
150169

170+
AesInit();
171+
151172
for(int i = 0; i < nblocks; ++i)
152173
{
153174
bool allZero = true;
175+
BlockNumber bn = blocknum + i;
176+
unsigned char iv[16] = {0,};
177+
154178
for(int j = 0; j < 32; ++j)
155179
{
156180
if(((char**)buffers)[i][j] != 0)
@@ -167,8 +191,6 @@ tde_mdreadv(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
167191
if(allZero)
168192
continue;
169193

170-
BlockNumber bn = blocknum + i;
171-
unsigned char iv[16] = {0,};
172194
memcpy(iv+4, &bn, sizeof(BlockNumber));
173195

174196
AesDecrypt(rkd->internal_key.key, iv, ((char **)buffers)[i], BLCKSZ, ((char **)buffers)[i], &out_len);
@@ -178,20 +200,50 @@ tde_mdreadv(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum,
178200
static void
179201
tde_mdcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
180202
{
203+
TDESMgrRelation tdereln = (TDESMgrRelation)reln;
181204
// This is the only function that gets called during actual CREATE TABLE/INDEX (EVENT TRIGGER)
182205
// so we create the key here by loading it
183206
// Later calls then decide to encrypt or not based on the existence of the key
184-
tde_smgr_get_key(reln);
207+
RelKeyData* key = tde_smgr_get_key(reln);
208+
if (key)
209+
{
210+
tdereln->encrypted_relation = true;
211+
memcpy(&tdereln->relKey, key, sizeof(RelKeyData));
212+
}
213+
else
214+
{
215+
tdereln->encrypted_relation = false;
216+
}
217+
185218
return mdcreate(reln, forknum, isRedo);
186219
}
187220

221+
/*
222+
* mdopen() -- Initialize newly-opened relation.
223+
*/
224+
static void
225+
tde_mdopen(SMgrRelation reln)
226+
{
227+
TDESMgrRelation tdereln = (TDESMgrRelation)reln;
228+
RelKeyData *key = tde_smgr_get_key(reln);
229+
if (key)
230+
{
231+
tdereln->encrypted_relation = true;
232+
memcpy(&tdereln->relKey, key, sizeof(RelKeyData));
233+
}
234+
else
235+
{
236+
tdereln->encrypted_relation = false;
237+
}
238+
mdopen(reln);
239+
}
188240

189241
static SMgrId tde_smgr_id;
190242
static const struct f_smgr tde_smgr = {
191243
.name = "tde",
192244
.smgr_init = mdinit,
193245
.smgr_shutdown = NULL,
194-
.smgr_open = mdopen,
246+
.smgr_open = tde_mdopen,
195247
.smgr_close = mdclose,
196248
.smgr_create = tde_mdcreate,
197249
.smgr_exists = mdexists,
@@ -210,7 +262,7 @@ static const struct f_smgr tde_smgr = {
210262

211263
void RegisterStorageMgr(void)
212264
{
213-
tde_smgr_id = smgr_register(&tde_smgr, 0);
265+
tde_smgr_id = smgr_register(&tde_smgr, sizeof(TDESMgrRelationData));
214266

215267
// TODO: figure out how this part should work in a real extension
216268
storage_manager_id = tde_smgr_id;

0 commit comments

Comments
 (0)