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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy