Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 6e7e0b5

Browse files
committed
Defend against openssl libraries that fail on keys longer than 128 bits;
which is the case at least on some Solaris versions. Marko Kreen
1 parent b46bd55 commit 6e7e0b5

File tree

1 file changed

+111
-36
lines changed

1 file changed

+111
-36
lines changed

contrib/pgcrypto/openssl.c

Lines changed: 111 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
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"
@@ -70,32 +70,42 @@
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+
378420
static int
379421
bf_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
696751
ossl_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

705772
static 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

Comments
 (0)