2626 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2727 * SUCH DAMAGE.
2828 *
29- * $PostgreSQL: pgsql/contrib/pgcrypto/openssl.c,v 1.30 2006/10/04 00:29:46 momjian Exp $
29+ * $PostgreSQL: pgsql/contrib/pgcrypto/openssl.c,v 1.31 2007/09/29 02:18:15 tgl Exp $
3030 */
3131
3232#include "postgres.h"
7070#define AES_DECRYPT 0
7171#define AES_KEY rijndael_ctx
7272
73- #define AES_set_encrypt_key (key , kbits , ctx ) \
74- aes_set_key((ctx), (key), (kbits), 1)
75-
76- #define AES_set_decrypt_key (key , kbits , ctx ) \
77- aes_set_key((ctx), (key), (kbits), 0)
78-
79- #define AES_ecb_encrypt (src , dst , ctx , enc ) \
80- do { \
81- memcpy((dst), (src), 16); \
82- if (enc) \
83- aes_ecb_encrypt((ctx), (dst), 16); \
84- else \
85- aes_ecb_decrypt((ctx), (dst), 16); \
86- } while (0)
87-
88- #define AES_cbc_encrypt (src , dst , len , ctx , iv , enc ) \
89- do { \
90- memcpy((dst), (src), (len)); \
91- if (enc) { \
92- aes_cbc_encrypt((ctx), (iv), (dst), (len)); \
93- memcpy((iv), (dst) + (len) - 16, 16); \
94- } else { \
95- aes_cbc_decrypt((ctx), (iv), (dst), (len)); \
96- memcpy(iv, (src) + (len) - 16, 16); \
97- } \
98- } while (0)
73+ static int
74+ AES_set_encrypt_key (const uint8 * key , int kbits , AES_KEY * ctx )
75+ {
76+ aes_set_key (ctx , key , kbits , 1 );
77+ return 0 ;
78+ }
79+
80+ static int
81+ AES_set_decrypt_key (const uint8 * key , int kbits , AES_KEY * ctx )
82+ {
83+ aes_set_key (ctx , key , kbits , 0 );
84+ return 0 ;
85+ }
86+
87+ static void
88+ AES_ecb_encrypt (const uint8 * src , uint8 * dst , AES_KEY * ctx , int enc )
89+ {
90+ memcpy (dst , src , 16 );
91+ if (enc )
92+ aes_ecb_encrypt (ctx , dst , 16 );
93+ else
94+ aes_ecb_decrypt (ctx , dst , 16 );
95+ }
96+
97+ static void
98+ AES_cbc_encrypt (const uint8 * src , uint8 * dst , int len , AES_KEY * ctx , uint8 * iv , int enc )
99+ {
100+ memcpy (dst , src , len );
101+ if (enc ) {
102+ aes_cbc_encrypt (ctx , iv , dst , len );
103+ memcpy (iv , dst + len - 16 , 16 );
104+ } else {
105+ aes_cbc_decrypt (ctx , iv , dst , len );
106+ memcpy (iv , src + len - 16 , 16 );
107+ }
108+ }
99109
100110/*
101111 * Emulate DES_* API
@@ -375,11 +385,56 @@ gen_ossl_free(PX_Cipher * c)
375385
376386/* Blowfish */
377387
388+ /*
389+ * Check if strong crypto is supported. Some openssl installations
390+ * support only short keys and unfortunately BF_set_key does not return any
391+ * error value. This function tests if is possible to use strong key.
392+ */
393+ static int
394+ bf_check_supported_key_len (void )
395+ {
396+ static const uint8 key [56 ] = {
397+ 0xf0 ,0xe1 ,0xd2 ,0xc3 ,0xb4 ,0xa5 ,0x96 ,0x87 ,0x78 ,0x69 ,
398+ 0x5a ,0x4b ,0x3c ,0x2d ,0x1e ,0x0f ,0x00 ,0x11 ,0x22 ,0x33 ,
399+ 0x44 ,0x55 ,0x66 ,0x77 ,0x04 ,0x68 ,0x91 ,0x04 ,0xc2 ,0xfd ,
400+ 0x3b ,0x2f ,0x58 ,0x40 ,0x23 ,0x64 ,0x1a ,0xba ,0x61 ,0x76 ,
401+ 0x1f ,0x1f ,0x1f ,0x1f ,0x0e ,0x0e ,0x0e ,0x0e ,0xff ,0xff ,
402+ 0xff ,0xff ,0xff ,0xff ,0xff ,0xff
403+ };
404+
405+ static const uint8 data [8 ] = {0xfe ,0xdc ,0xba ,0x98 ,0x76 ,0x54 ,0x32 ,0x10 };
406+ static const uint8 res [8 ] = {0xc0 ,0x45 ,0x04 ,0x01 ,0x2e ,0x4e ,0x1f ,0x53 };
407+ static uint8 out [8 ];
408+
409+ BF_KEY bf_key ;
410+
411+ /* encrypt with 448bits key and verify output */
412+ BF_set_key (& bf_key , 56 , key );
413+ BF_ecb_encrypt (data , out , & bf_key , BF_ENCRYPT );
414+
415+ if (memcmp (out , res , 8 ) != 0 )
416+ return 0 ; /* Output does not match -> strong cipher is not supported */
417+ return 1 ;
418+ }
419+
378420static int
379421bf_init (PX_Cipher * c , const uint8 * key , unsigned klen , const uint8 * iv )
380422{
381423 ossldata * od = c -> ptr ;
424+ static int bf_is_strong = -1 ;
425+
426+ /*
427+ * Test if key len is supported. BF_set_key silently cut large keys and it could be
428+ * be a problem when user transfer crypted data from one server to another.
429+ */
430+
431+ if ( bf_is_strong == -1 )
432+ bf_is_strong = bf_check_supported_key_len ();
433+
434+ if ( !bf_is_strong && klen > 16 )
435+ return PXE_KEY_TOO_BIG ;
382436
437+ /* Key len is supported. We can use it. */
383438 BF_set_key (& od -> u .bf .key , klen , key );
384439 if (iv )
385440 memcpy (od -> iv , iv , BF_BLOCK );
@@ -692,14 +747,26 @@ ossl_aes_init(PX_Cipher * c, const uint8 *key, unsigned klen, const uint8 *iv)
692747 return 0 ;
693748}
694749
695- static void
750+ static int
696751ossl_aes_key_init (ossldata * od , int type )
697752{
753+ int err ;
754+ /*
755+ * Strong key support could be missing on some openssl installations.
756+ * We must check return value from set key function.
757+ */
698758 if (type == AES_ENCRYPT )
699- AES_set_encrypt_key (od -> key , od -> klen * 8 , & od -> u .aes_key );
759+ err = AES_set_encrypt_key (od -> key , od -> klen * 8 , & od -> u .aes_key );
700760 else
701- AES_set_decrypt_key (od -> key , od -> klen * 8 , & od -> u .aes_key );
702- od -> init = 1 ;
761+ err = AES_set_decrypt_key (od -> key , od -> klen * 8 , & od -> u .aes_key );
762+
763+ if (err == 0 )
764+ {
765+ od -> init = 1 ;
766+ return 0 ;
767+ }
768+ od -> init = 0 ;
769+ return PXE_KEY_TOO_BIG ;
703770}
704771
705772static int
@@ -709,9 +776,11 @@ ossl_aes_ecb_encrypt(PX_Cipher * c, const uint8 *data, unsigned dlen,
709776 unsigned bs = gen_ossl_block_size (c );
710777 ossldata * od = c -> ptr ;
711778 const uint8 * end = data + dlen - bs ;
779+ int err ;
712780
713781 if (!od -> init )
714- ossl_aes_key_init (od , AES_ENCRYPT );
782+ if ((err = ossl_aes_key_init (od , AES_ENCRYPT )) != 0 )
783+ return err ;
715784
716785 for (; data <= end ; data += bs , res += bs )
717786 AES_ecb_encrypt (data , res , & od -> u .aes_key , AES_ENCRYPT );
@@ -725,9 +794,11 @@ ossl_aes_ecb_decrypt(PX_Cipher * c, const uint8 *data, unsigned dlen,
725794 unsigned bs = gen_ossl_block_size (c );
726795 ossldata * od = c -> ptr ;
727796 const uint8 * end = data + dlen - bs ;
797+ int err ;
728798
729799 if (!od -> init )
730- ossl_aes_key_init (od , AES_DECRYPT );
800+ if ((err = ossl_aes_key_init (od , AES_DECRYPT )) != 0 )
801+ return err ;
731802
732803 for (; data <= end ; data += bs , res += bs )
733804 AES_ecb_encrypt (data , res , & od -> u .aes_key , AES_DECRYPT );
@@ -739,10 +810,12 @@ ossl_aes_cbc_encrypt(PX_Cipher * c, const uint8 *data, unsigned dlen,
739810 uint8 * res )
740811{
741812 ossldata * od = c -> ptr ;
813+ int err ;
742814
743815 if (!od -> init )
744- ossl_aes_key_init (od , AES_ENCRYPT );
745-
816+ if ((err = ossl_aes_key_init (od , AES_ENCRYPT )) != 0 )
817+ return err ;
818+
746819 AES_cbc_encrypt (data , res , dlen , & od -> u .aes_key , od -> iv , AES_ENCRYPT );
747820 return 0 ;
748821}
@@ -752,9 +825,11 @@ ossl_aes_cbc_decrypt(PX_Cipher * c, const uint8 *data, unsigned dlen,
752825 uint8 * res )
753826{
754827 ossldata * od = c -> ptr ;
828+ int err ;
755829
756830 if (!od -> init )
757- ossl_aes_key_init (od , AES_DECRYPT );
831+ if ((err = ossl_aes_key_init (od , AES_DECRYPT )) != 0 )
832+ return err ;
758833
759834 AES_cbc_encrypt (data , res , dlen , & od -> u .aes_key , od -> iv , AES_DECRYPT );
760835 return 0 ;
0 commit comments