@@ -66,10 +66,10 @@ typedef struct OSSLDigest
66
66
} OSSLDigest ;
67
67
68
68
static OSSLDigest * open_digests = NULL ;
69
- static bool resowner_callback_registered = false;
69
+ static bool digest_resowner_callback_registered = false;
70
70
71
71
static void
72
- free_openssldigest (OSSLDigest * digest )
72
+ free_openssl_digest (OSSLDigest * digest )
73
73
{
74
74
EVP_MD_CTX_destroy (digest -> ctx );
75
75
if (digest -> prev )
@@ -106,7 +106,7 @@ digest_free_callback(ResourceReleasePhase phase,
106
106
{
107
107
if (isCommit )
108
108
elog (WARNING , "pgcrypto digest reference leak: digest %p still referenced" , curr );
109
- free_openssldigest (curr );
109
+ free_openssl_digest (curr );
110
110
}
111
111
}
112
112
}
@@ -156,7 +156,7 @@ digest_free(PX_MD *h)
156
156
{
157
157
OSSLDigest * digest = (OSSLDigest * ) h -> p .ptr ;
158
158
159
- free_openssldigest (digest );
159
+ free_openssl_digest (digest );
160
160
px_free (h );
161
161
}
162
162
@@ -178,10 +178,10 @@ px_find_digest(const char *name, PX_MD **res)
178
178
OpenSSL_add_all_algorithms ();
179
179
}
180
180
181
- if (!resowner_callback_registered )
181
+ if (!digest_resowner_callback_registered )
182
182
{
183
183
RegisterResourceReleaseCallback (digest_free_callback , NULL );
184
- resowner_callback_registered = true;
184
+ digest_resowner_callback_registered = true;
185
185
}
186
186
187
187
md = EVP_get_digestbyname (name );
@@ -240,6 +240,9 @@ px_find_digest(const char *name, PX_MD **res)
240
240
*/
241
241
typedef const EVP_CIPHER * (* ossl_EVP_cipher_func )(void );
242
242
243
+ /*
244
+ * ossl_cipher contains the static information about each cipher.
245
+ */
243
246
struct ossl_cipher
244
247
{
245
248
int (* init ) (PX_Cipher * c , const uint8 * key , unsigned klen , const uint8 * iv );
@@ -248,31 +251,89 @@ struct ossl_cipher
248
251
int max_key_size ;
249
252
};
250
253
251
- typedef struct
254
+ /*
255
+ * OSSLCipher contains the state for using a cipher. A separate OSSLCipher
256
+ * object is allocated in each px_find_cipher() call.
257
+ *
258
+ * To make sure we don't leak OpenSSL handles on abort, we keep OSSLCipher
259
+ * objects in a linked list, allocated in TopMemoryContext. We use the
260
+ * ResourceOwner mechanism to free them on abort.
261
+ */
262
+ typedef struct OSSLCipher
252
263
{
253
- EVP_CIPHER_CTX evp_ctx ;
264
+ EVP_CIPHER_CTX * evp_ctx ;
254
265
const EVP_CIPHER * evp_ciph ;
255
266
uint8 key [MAX_KEY ];
256
267
uint8 iv [MAX_IV ];
257
268
unsigned klen ;
258
269
unsigned init ;
259
270
const struct ossl_cipher * ciph ;
260
- } ossldata ;
271
+
272
+ ResourceOwner owner ;
273
+ struct OSSLCipher * next ;
274
+ struct OSSLCipher * prev ;
275
+ } OSSLCipher ;
276
+
277
+ static OSSLCipher * open_ciphers = NULL ;
278
+ static bool cipher_resowner_callback_registered = false;
279
+
280
+ static void
281
+ free_openssl_cipher (OSSLCipher * od )
282
+ {
283
+ EVP_CIPHER_CTX_free (od -> evp_ctx );
284
+ if (od -> prev )
285
+ od -> prev -> next = od -> next ;
286
+ else
287
+ open_ciphers = od -> next ;
288
+ if (od -> next )
289
+ od -> next -> prev = od -> prev ;
290
+ pfree (od );
291
+ }
292
+
293
+ /*
294
+ * Close any open OpenSSL cipher handles on abort.
295
+ */
296
+ static void
297
+ cipher_free_callback (ResourceReleasePhase phase ,
298
+ bool isCommit ,
299
+ bool isTopLevel ,
300
+ void * arg )
301
+ {
302
+ OSSLCipher * curr ;
303
+ OSSLCipher * next ;
304
+
305
+ if (phase != RESOURCE_RELEASE_AFTER_LOCKS )
306
+ return ;
307
+
308
+ next = open_ciphers ;
309
+ while (next )
310
+ {
311
+ curr = next ;
312
+ next = curr -> next ;
313
+
314
+ if (curr -> owner == CurrentResourceOwner )
315
+ {
316
+ if (isCommit )
317
+ elog (WARNING , "pgcrypto cipher reference leak: cipher %p still referenced" , curr );
318
+ free_openssl_cipher (curr );
319
+ }
320
+ }
321
+ }
261
322
262
323
/* Common routines for all algorithms */
263
324
264
325
static unsigned
265
326
gen_ossl_block_size (PX_Cipher * c )
266
327
{
267
- ossldata * od = (ossldata * ) c -> ptr ;
328
+ OSSLCipher * od = (OSSLCipher * ) c -> ptr ;
268
329
269
330
return od -> ciph -> block_size ;
270
331
}
271
332
272
333
static unsigned
273
334
gen_ossl_key_size (PX_Cipher * c )
274
335
{
275
- ossldata * od = (ossldata * ) c -> ptr ;
336
+ OSSLCipher * od = (OSSLCipher * ) c -> ptr ;
276
337
277
338
return od -> ciph -> max_key_size ;
278
339
}
@@ -281,7 +342,7 @@ static unsigned
281
342
gen_ossl_iv_size (PX_Cipher * c )
282
343
{
283
344
unsigned ivlen ;
284
- ossldata * od = (ossldata * ) c -> ptr ;
345
+ OSSLCipher * od = (OSSLCipher * ) c -> ptr ;
285
346
286
347
ivlen = od -> ciph -> block_size ;
287
348
return ivlen ;
@@ -290,34 +351,31 @@ gen_ossl_iv_size(PX_Cipher *c)
290
351
static void
291
352
gen_ossl_free (PX_Cipher * c )
292
353
{
293
- ossldata * od = (ossldata * ) c -> ptr ;
354
+ OSSLCipher * od = (OSSLCipher * ) c -> ptr ;
294
355
295
- EVP_CIPHER_CTX_cleanup (& od -> evp_ctx );
296
- px_memset (od , 0 , sizeof (* od ));
297
- px_free (od );
356
+ free_openssl_cipher (od );
298
357
px_free (c );
299
358
}
300
359
301
360
static int
302
361
gen_ossl_decrypt (PX_Cipher * c , const uint8 * data , unsigned dlen ,
303
362
uint8 * res )
304
363
{
305
- ossldata * od = c -> ptr ;
364
+ OSSLCipher * od = c -> ptr ;
306
365
int outlen ;
307
366
308
367
if (!od -> init )
309
368
{
310
- EVP_CIPHER_CTX_init (& od -> evp_ctx );
311
- if (!EVP_DecryptInit_ex (& od -> evp_ctx , od -> evp_ciph , NULL , NULL , NULL ))
369
+ if (!EVP_DecryptInit_ex (od -> evp_ctx , od -> evp_ciph , NULL , NULL , NULL ))
312
370
return PXE_CIPHER_INIT ;
313
- if (!EVP_CIPHER_CTX_set_key_length (& od -> evp_ctx , od -> klen ))
371
+ if (!EVP_CIPHER_CTX_set_key_length (od -> evp_ctx , od -> klen ))
314
372
return PXE_CIPHER_INIT ;
315
- if (!EVP_DecryptInit_ex (& od -> evp_ctx , NULL , NULL , od -> key , od -> iv ))
373
+ if (!EVP_DecryptInit_ex (od -> evp_ctx , NULL , NULL , od -> key , od -> iv ))
316
374
return PXE_CIPHER_INIT ;
317
375
od -> init = true;
318
376
}
319
377
320
- if (!EVP_DecryptUpdate (& od -> evp_ctx , res , & outlen , data , dlen ))
378
+ if (!EVP_DecryptUpdate (od -> evp_ctx , res , & outlen , data , dlen ))
321
379
return PXE_DECRYPT_FAILED ;
322
380
323
381
return 0 ;
@@ -327,22 +385,21 @@ static int
327
385
gen_ossl_encrypt (PX_Cipher * c , const uint8 * data , unsigned dlen ,
328
386
uint8 * res )
329
387
{
330
- ossldata * od = c -> ptr ;
388
+ OSSLCipher * od = c -> ptr ;
331
389
int outlen ;
332
390
333
391
if (!od -> init )
334
392
{
335
- EVP_CIPHER_CTX_init (& od -> evp_ctx );
336
- if (!EVP_EncryptInit_ex (& od -> evp_ctx , od -> evp_ciph , NULL , NULL , NULL ))
393
+ if (!EVP_EncryptInit_ex (od -> evp_ctx , od -> evp_ciph , NULL , NULL , NULL ))
337
394
return PXE_CIPHER_INIT ;
338
- if (!EVP_CIPHER_CTX_set_key_length (& od -> evp_ctx , od -> klen ))
395
+ if (!EVP_CIPHER_CTX_set_key_length (od -> evp_ctx , od -> klen ))
339
396
return PXE_CIPHER_INIT ;
340
- if (!EVP_EncryptInit_ex (& od -> evp_ctx , NULL , NULL , od -> key , od -> iv ))
397
+ if (!EVP_EncryptInit_ex (od -> evp_ctx , NULL , NULL , od -> key , od -> iv ))
341
398
return PXE_CIPHER_INIT ;
342
399
od -> init = true;
343
400
}
344
401
345
- if (!EVP_EncryptUpdate (& od -> evp_ctx , res , & outlen , data , dlen ))
402
+ if (!EVP_EncryptUpdate (od -> evp_ctx , res , & outlen , data , dlen ))
346
403
return PXE_ERR_GENERIC ;
347
404
348
405
return 0 ;
@@ -370,31 +427,38 @@ bf_check_supported_key_len(void)
370
427
static const uint8 data [8 ] = {0xfe , 0xdc , 0xba , 0x98 , 0x76 , 0x54 , 0x32 , 0x10 };
371
428
static const uint8 res [8 ] = {0xc0 , 0x45 , 0x04 , 0x01 , 0x2e , 0x4e , 0x1f , 0x53 };
372
429
uint8 out [8 ];
373
- EVP_CIPHER_CTX evp_ctx ;
430
+ EVP_CIPHER_CTX * evp_ctx ;
374
431
int outlen ;
432
+ int status = 0 ;
375
433
376
434
/* encrypt with 448bits key and verify output */
377
- EVP_CIPHER_CTX_init (& evp_ctx );
378
- if (!EVP_EncryptInit_ex (& evp_ctx , EVP_bf_ecb (), NULL , NULL , NULL ))
379
- return 0 ;
380
- if (!EVP_CIPHER_CTX_set_key_length (& evp_ctx , 56 ))
381
- return 0 ;
382
- if (!EVP_EncryptInit_ex (& evp_ctx , NULL , NULL , key , NULL ))
435
+ evp_ctx = EVP_CIPHER_CTX_new ();
436
+ if (!evp_ctx )
383
437
return 0 ;
438
+ if (!EVP_EncryptInit_ex (evp_ctx , EVP_bf_ecb (), NULL , NULL , NULL ))
439
+ goto leave ;
440
+ if (!EVP_CIPHER_CTX_set_key_length (evp_ctx , 56 ))
441
+ goto leave ;
442
+ if (!EVP_EncryptInit_ex (evp_ctx , NULL , NULL , key , NULL ))
443
+ goto leave ;
384
444
385
- if (!EVP_EncryptUpdate (& evp_ctx , out , & outlen , data , 8 ))
386
- return 0 ;
445
+ if (!EVP_EncryptUpdate (evp_ctx , out , & outlen , data , 8 ))
446
+ goto leave ;
387
447
388
448
if (memcmp (out , res , 8 ) != 0 )
389
- return 0 ; /* Output does not match -> strong cipher is
449
+ goto leave ; /* Output does not match -> strong cipher is
390
450
* not supported */
391
- return 1 ;
451
+ status = 1 ;
452
+
453
+ leave :
454
+ EVP_CIPHER_CTX_free (evp_ctx );
455
+ return status ;
392
456
}
393
457
394
458
static int
395
459
bf_init (PX_Cipher * c , const uint8 * key , unsigned klen , const uint8 * iv )
396
460
{
397
- ossldata * od = c -> ptr ;
461
+ OSSLCipher * od = c -> ptr ;
398
462
unsigned bs = gen_ossl_block_size (c );
399
463
static int bf_is_strong = -1 ;
400
464
@@ -426,7 +490,7 @@ bf_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
426
490
static int
427
491
ossl_des_init (PX_Cipher * c , const uint8 * key , unsigned klen , const uint8 * iv )
428
492
{
429
- ossldata * od = c -> ptr ;
493
+ OSSLCipher * od = c -> ptr ;
430
494
unsigned bs = gen_ossl_block_size (c );
431
495
432
496
od -> klen = 8 ;
@@ -445,7 +509,7 @@ ossl_des_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
445
509
static int
446
510
ossl_des3_init (PX_Cipher * c , const uint8 * key , unsigned klen , const uint8 * iv )
447
511
{
448
- ossldata * od = c -> ptr ;
512
+ OSSLCipher * od = c -> ptr ;
449
513
unsigned bs = gen_ossl_block_size (c );
450
514
451
515
od -> klen = 24 ;
@@ -464,7 +528,7 @@ ossl_des3_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
464
528
static int
465
529
ossl_cast_init (PX_Cipher * c , const uint8 * key , unsigned klen , const uint8 * iv )
466
530
{
467
- ossldata * od = c -> ptr ;
531
+ OSSLCipher * od = c -> ptr ;
468
532
unsigned bs = gen_ossl_block_size (c );
469
533
470
534
od -> klen = klen ;
@@ -482,7 +546,7 @@ ossl_cast_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
482
546
static int
483
547
ossl_aes_init (PX_Cipher * c , const uint8 * key , unsigned klen , const uint8 * iv )
484
548
{
485
- ossldata * od = c -> ptr ;
549
+ OSSLCipher * od = c -> ptr ;
486
550
unsigned bs = gen_ossl_block_size (c );
487
551
488
552
if (klen <= 128 / 8 )
@@ -507,7 +571,7 @@ ossl_aes_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
507
571
static int
508
572
ossl_aes_ecb_init (PX_Cipher * c , const uint8 * key , unsigned klen , const uint8 * iv )
509
573
{
510
- ossldata * od = c -> ptr ;
574
+ OSSLCipher * od = c -> ptr ;
511
575
int err ;
512
576
513
577
err = ossl_aes_init (c , key , klen , iv );
@@ -537,7 +601,7 @@ ossl_aes_ecb_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv
537
601
static int
538
602
ossl_aes_cbc_init (PX_Cipher * c , const uint8 * key , unsigned klen , const uint8 * iv )
539
603
{
540
- ossldata * od = c -> ptr ;
604
+ OSSLCipher * od = c -> ptr ;
541
605
int err ;
542
606
543
607
err = ossl_aes_init (c , key , klen , iv );
@@ -683,7 +747,8 @@ px_find_cipher(const char *name, PX_Cipher **res)
683
747
{
684
748
const struct ossl_cipher_lookup * i ;
685
749
PX_Cipher * c = NULL ;
686
- ossldata * od ;
750
+ EVP_CIPHER_CTX * ctx ;
751
+ OSSLCipher * od ;
687
752
688
753
name = px_resolve_alias (ossl_aliases , name );
689
754
for (i = ossl_cipher_types ; i -> name ; i ++ )
@@ -692,13 +757,38 @@ px_find_cipher(const char *name, PX_Cipher **res)
692
757
if (i -> name == NULL )
693
758
return PXE_NO_CIPHER ;
694
759
695
- od = px_alloc (sizeof (* od ));
696
- memset (od , 0 , sizeof (* od ));
760
+ if (!cipher_resowner_callback_registered )
761
+ {
762
+ RegisterResourceReleaseCallback (cipher_free_callback , NULL );
763
+ cipher_resowner_callback_registered = true;
764
+ }
765
+
766
+ /*
767
+ * Create an OSSLCipher object, an EVP_CIPHER_CTX object and a PX_Cipher.
768
+ * The order is crucial, to make sure we don't leak anything on
769
+ * out-of-memory or other error.
770
+ */
771
+ od = MemoryContextAllocZero (TopMemoryContext , sizeof (* od ));
697
772
od -> ciph = i -> ciph ;
698
773
774
+ /* Allocate an EVP_CIPHER_CTX object. */
775
+ ctx = EVP_CIPHER_CTX_new ();
776
+ if (!ctx )
777
+ {
778
+ pfree (od );
779
+ return PXE_CIPHER_INIT ;
780
+ }
781
+
782
+ od -> evp_ctx = ctx ;
783
+ od -> owner = CurrentResourceOwner ;
784
+ od -> next = open_ciphers ;
785
+ od -> prev = NULL ;
786
+ open_ciphers = od ;
787
+
699
788
if (i -> ciph -> cipher_func )
700
789
od -> evp_ciph = i -> ciph -> cipher_func ();
701
790
791
+ /* The PX_Cipher is allocated in current memory context */
702
792
c = px_alloc (sizeof (* c ));
703
793
c -> block_size = gen_ossl_block_size ;
704
794
c -> key_size = gen_ossl_key_size ;
0 commit comments