@@ -66,10 +66,10 @@ typedef struct OSSLDigest
6666}OSSLDigest ;
6767
6868static OSSLDigest * open_digests = NULL ;
69- static bool resowner_callback_registered = false;
69+ static bool digest_resowner_callback_registered = false;
7070
7171static void
72- free_openssldigest (OSSLDigest * digest )
72+ free_openssl_digest (OSSLDigest * digest )
7373{
7474EVP_MD_CTX_destroy (digest -> ctx );
7575if (digest -> prev )
@@ -106,7 +106,7 @@ digest_free_callback(ResourceReleasePhase phase,
106106{
107107if (isCommit )
108108elog (WARNING ,"pgcrypto digest reference leak: digest %p still referenced" ,curr );
109- free_openssldigest (curr );
109+ free_openssl_digest (curr );
110110}
111111}
112112}
@@ -156,7 +156,7 @@ digest_free(PX_MD *h)
156156{
157157OSSLDigest * digest = (OSSLDigest * )h -> p .ptr ;
158158
159- free_openssldigest (digest );
159+ free_openssl_digest (digest );
160160px_free (h );
161161}
162162
@@ -178,10 +178,10 @@ px_find_digest(const char *name, PX_MD **res)
178178OpenSSL_add_all_algorithms ();
179179}
180180
181- if (!resowner_callback_registered )
181+ if (!digest_resowner_callback_registered )
182182{
183183RegisterResourceReleaseCallback (digest_free_callback ,NULL );
184- resowner_callback_registered = true;
184+ digest_resowner_callback_registered = true;
185185}
186186
187187md = EVP_get_digestbyname (name );
@@ -240,6 +240,9 @@ px_find_digest(const char *name, PX_MD **res)
240240 */
241241typedef const EVP_CIPHER * (* ossl_EVP_cipher_func )(void );
242242
243+ /*
244+ * ossl_cipher contains the static information about each cipher.
245+ */
243246struct ossl_cipher
244247{
245248int (* init ) (PX_Cipher * c ,const uint8 * key ,unsigned klen ,const uint8 * iv );
@@ -248,31 +251,89 @@ struct ossl_cipher
248251int max_key_size ;
249252};
250253
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
252263{
253- EVP_CIPHER_CTX evp_ctx ;
264+ EVP_CIPHER_CTX * evp_ctx ;
254265const EVP_CIPHER * evp_ciph ;
255266uint8 key [MAX_KEY ];
256267uint8 iv [MAX_IV ];
257268unsigned klen ;
258269unsigned init ;
259270const 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+ }
261322
262323/* Common routines for all algorithms */
263324
264325static unsigned
265326gen_ossl_block_size (PX_Cipher * c )
266327{
267- ossldata * od = (ossldata * )c -> ptr ;
328+ OSSLCipher * od = (OSSLCipher * )c -> ptr ;
268329
269330return od -> ciph -> block_size ;
270331}
271332
272333static unsigned
273334gen_ossl_key_size (PX_Cipher * c )
274335{
275- ossldata * od = (ossldata * )c -> ptr ;
336+ OSSLCipher * od = (OSSLCipher * )c -> ptr ;
276337
277338return od -> ciph -> max_key_size ;
278339}
@@ -281,7 +342,7 @@ static unsigned
281342gen_ossl_iv_size (PX_Cipher * c )
282343{
283344unsigned ivlen ;
284- ossldata * od = (ossldata * )c -> ptr ;
345+ OSSLCipher * od = (OSSLCipher * )c -> ptr ;
285346
286347ivlen = od -> ciph -> block_size ;
287348return ivlen ;
@@ -290,34 +351,31 @@ gen_ossl_iv_size(PX_Cipher *c)
290351static void
291352gen_ossl_free (PX_Cipher * c )
292353{
293- ossldata * od = (ossldata * )c -> ptr ;
354+ OSSLCipher * od = (OSSLCipher * )c -> ptr ;
294355
295- EVP_CIPHER_CTX_cleanup (& od -> evp_ctx );
296- px_memset (od ,0 ,sizeof (* od ));
297- px_free (od );
356+ free_openssl_cipher (od );
298357px_free (c );
299358}
300359
301360static int
302361gen_ossl_decrypt (PX_Cipher * c ,const uint8 * data ,unsigned dlen ,
303362uint8 * res )
304363{
305- ossldata * od = c -> ptr ;
364+ OSSLCipher * od = c -> ptr ;
306365int outlen ;
307366
308367if (!od -> init )
309368{
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 ))
312370return 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 ))
314372return 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 ))
316374return PXE_CIPHER_INIT ;
317375od -> init = true;
318376}
319377
320- if (!EVP_DecryptUpdate (& od -> evp_ctx ,res ,& outlen ,data ,dlen ))
378+ if (!EVP_DecryptUpdate (od -> evp_ctx ,res ,& outlen ,data ,dlen ))
321379return PXE_DECRYPT_FAILED ;
322380
323381return 0 ;
@@ -327,22 +385,21 @@ static int
327385gen_ossl_encrypt (PX_Cipher * c ,const uint8 * data ,unsigned dlen ,
328386uint8 * res )
329387{
330- ossldata * od = c -> ptr ;
388+ OSSLCipher * od = c -> ptr ;
331389int outlen ;
332390
333391if (!od -> init )
334392{
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 ))
337394return 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 ))
339396return 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 ))
341398return PXE_CIPHER_INIT ;
342399od -> init = true;
343400}
344401
345- if (!EVP_EncryptUpdate (& od -> evp_ctx ,res ,& outlen ,data ,dlen ))
402+ if (!EVP_EncryptUpdate (od -> evp_ctx ,res ,& outlen ,data ,dlen ))
346403return PXE_ERR_GENERIC ;
347404
348405return 0 ;
@@ -370,31 +427,38 @@ bf_check_supported_key_len(void)
370427static const uint8 data [8 ]= {0xfe ,0xdc ,0xba ,0x98 ,0x76 ,0x54 ,0x32 ,0x10 };
371428static const uint8 res [8 ]= {0xc0 ,0x45 ,0x04 ,0x01 ,0x2e ,0x4e ,0x1f ,0x53 };
372429uint8 out [8 ];
373- EVP_CIPHER_CTX evp_ctx ;
430+ EVP_CIPHER_CTX * evp_ctx ;
374431int outlen ;
432+ int status = 0 ;
375433
376434/* 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 )
383437return 0 ;
438+ if (!EVP_EncryptInit_ex (evp_ctx ,EVP_bf_ecb (),NULL ,NULL ,NULL ))
439+ gotoleave ;
440+ if (!EVP_CIPHER_CTX_set_key_length (evp_ctx ,56 ))
441+ gotoleave ;
442+ if (!EVP_EncryptInit_ex (evp_ctx ,NULL ,NULL ,key ,NULL ))
443+ gotoleave ;
384444
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 ;
387447
388448if (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
390450 * not supported */
391- return 1 ;
451+ status = 1 ;
452+
453+ leave :
454+ EVP_CIPHER_CTX_free (evp_ctx );
455+ return status ;
392456}
393457
394458static int
395459bf_init (PX_Cipher * c ,const uint8 * key ,unsigned klen ,const uint8 * iv )
396460{
397- ossldata * od = c -> ptr ;
461+ OSSLCipher * od = c -> ptr ;
398462unsigned bs = gen_ossl_block_size (c );
399463static int bf_is_strong = -1 ;
400464
@@ -426,7 +490,7 @@ bf_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
426490static int
427491ossl_des_init (PX_Cipher * c ,const uint8 * key ,unsigned klen ,const uint8 * iv )
428492{
429- ossldata * od = c -> ptr ;
493+ OSSLCipher * od = c -> ptr ;
430494unsigned bs = gen_ossl_block_size (c );
431495
432496od -> klen = 8 ;
@@ -445,7 +509,7 @@ ossl_des_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
445509static int
446510ossl_des3_init (PX_Cipher * c ,const uint8 * key ,unsigned klen ,const uint8 * iv )
447511{
448- ossldata * od = c -> ptr ;
512+ OSSLCipher * od = c -> ptr ;
449513unsigned bs = gen_ossl_block_size (c );
450514
451515od -> klen = 24 ;
@@ -464,7 +528,7 @@ ossl_des3_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
464528static int
465529ossl_cast_init (PX_Cipher * c ,const uint8 * key ,unsigned klen ,const uint8 * iv )
466530{
467- ossldata * od = c -> ptr ;
531+ OSSLCipher * od = c -> ptr ;
468532unsigned bs = gen_ossl_block_size (c );
469533
470534od -> klen = klen ;
@@ -482,7 +546,7 @@ ossl_cast_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
482546static int
483547ossl_aes_init (PX_Cipher * c ,const uint8 * key ,unsigned klen ,const uint8 * iv )
484548{
485- ossldata * od = c -> ptr ;
549+ OSSLCipher * od = c -> ptr ;
486550unsigned bs = gen_ossl_block_size (c );
487551
488552if (klen <=128 /8 )
@@ -507,7 +571,7 @@ ossl_aes_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
507571static int
508572ossl_aes_ecb_init (PX_Cipher * c ,const uint8 * key ,unsigned klen ,const uint8 * iv )
509573{
510- ossldata * od = c -> ptr ;
574+ OSSLCipher * od = c -> ptr ;
511575int err ;
512576
513577err = 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
537601static int
538602ossl_aes_cbc_init (PX_Cipher * c ,const uint8 * key ,unsigned klen ,const uint8 * iv )
539603{
540- ossldata * od = c -> ptr ;
604+ OSSLCipher * od = c -> ptr ;
541605int err ;
542606
543607err = ossl_aes_init (c ,key ,klen ,iv );
@@ -683,7 +747,8 @@ px_find_cipher(const char *name, PX_Cipher **res)
683747{
684748const struct ossl_cipher_lookup * i ;
685749PX_Cipher * c = NULL ;
686- ossldata * od ;
750+ EVP_CIPHER_CTX * ctx ;
751+ OSSLCipher * od ;
687752
688753name = px_resolve_alias (ossl_aliases ,name );
689754for (i = ossl_cipher_types ;i -> name ;i ++ )
@@ -692,13 +757,38 @@ px_find_cipher(const char *name, PX_Cipher **res)
692757if (i -> name == NULL )
693758return PXE_NO_CIPHER ;
694759
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 ));
697772od -> ciph = i -> ciph ;
698773
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+
699788if (i -> ciph -> cipher_func )
700789od -> evp_ciph = i -> ciph -> cipher_func ();
701790
791+ /* The PX_Cipher is allocated in current memory context */
702792c = px_alloc (sizeof (* c ));
703793c -> block_size = gen_ossl_block_size ;
704794c -> key_size = gen_ossl_key_size ;