summaryrefslogtreecommitdiff
path: root/contrib/pgcrypto
diff options
context:
space:
mode:
authorPavan Deolasee2016-10-27 15:02:55 +0000
committerPavan Deolasee2016-10-27 15:02:55 +0000
commitc52792488cd87e67e62ec61f5b56f461900353b4 (patch)
tree02b4a719f979659de8f73fce6c1ca65cef2e323f /contrib/pgcrypto
parent891e6be57e5580b54a9df9fd42cb9bd10d0e7b21 (diff)
parentb5bce6c1ec6061c8a4f730d927e162db7e2ce365 (diff)
Merge commit 'b5bce6c1ec6061c8a4f730d927e162db7e2ce365'
Diffstat (limited to 'contrib/pgcrypto')
-rw-r--r--contrib/pgcrypto/Makefile4
-rw-r--r--contrib/pgcrypto/crypt-blowfish.c22
-rw-r--r--contrib/pgcrypto/crypt-des.c27
-rw-r--r--contrib/pgcrypto/expected/crypt-blowfish.out9
-rw-r--r--contrib/pgcrypto/expected/crypt-des.out4
-rw-r--r--contrib/pgcrypto/expected/crypt-xdes.out24
-rw-r--r--contrib/pgcrypto/expected/pgp-encrypt.out19
-rw-r--r--contrib/pgcrypto/fortuna.c2
-rw-r--r--contrib/pgcrypto/pgcrypto--1.2--1.3.sql41
-rw-r--r--contrib/pgcrypto/pgcrypto--1.3.sql (renamed from contrib/pgcrypto/pgcrypto--1.2.sql)74
-rw-r--r--contrib/pgcrypto/pgcrypto.control2
-rw-r--r--contrib/pgcrypto/pgp-decrypt.c1
-rw-r--r--contrib/pgcrypto/pgp-encrypt.c2
-rw-r--r--contrib/pgcrypto/pgp-pgsql.c10
-rw-r--r--contrib/pgcrypto/pgp-s2k.c37
-rw-r--r--contrib/pgcrypto/pgp.c13
-rw-r--r--contrib/pgcrypto/pgp.h10
-rw-r--r--contrib/pgcrypto/px-crypt.c2
-rw-r--r--contrib/pgcrypto/px.c2
-rw-r--r--contrib/pgcrypto/sha1.h2
-rw-r--r--contrib/pgcrypto/sql/crypt-blowfish.sql9
-rw-r--r--contrib/pgcrypto/sql/crypt-des.sql4
-rw-r--r--contrib/pgcrypto/sql/crypt-xdes.sql16
-rw-r--r--contrib/pgcrypto/sql/pgp-encrypt.sql9
24 files changed, 280 insertions, 65 deletions
diff --git a/contrib/pgcrypto/Makefile b/contrib/pgcrypto/Makefile
index 18bad1a05f..805db7626b 100644
--- a/contrib/pgcrypto/Makefile
+++ b/contrib/pgcrypto/Makefile
@@ -26,8 +26,8 @@ MODULE_big = pgcrypto
OBJS = $(SRCS:.c=.o) $(WIN32RES)
EXTENSION = pgcrypto
-DATA = pgcrypto--1.2.sql pgcrypto--1.1--1.2.sql pgcrypto--1.0--1.1.sql \
- pgcrypto--unpackaged--1.0.sql
+DATA = pgcrypto--1.3.sql pgcrypto--1.2--1.3.sql pgcrypto--1.1--1.2.sql \
+ pgcrypto--1.0--1.1.sql pgcrypto--unpackaged--1.0.sql
PGFILEDESC = "pgcrypto - cryptographic functions"
REGRESS = init md5 sha1 hmac-md5 hmac-sha1 blowfish rijndael \
diff --git a/contrib/pgcrypto/crypt-blowfish.c b/contrib/pgcrypto/crypt-blowfish.c
index fbaa3d776a..6feaefcf7b 100644
--- a/contrib/pgcrypto/crypt-blowfish.c
+++ b/contrib/pgcrypto/crypt-blowfish.c
@@ -33,6 +33,7 @@
*/
#include "postgres.h"
+#include "miscadmin.h"
#include "px-crypt.h"
#include "px.h"
@@ -602,6 +603,17 @@ _crypt_blowfish_rn(const char *key, const char *setting,
if (size < 7 + 22 + 31 + 1)
return NULL;
+ /*
+ * Blowfish salt value must be formatted as follows: "$2a$" or "$2x$", a
+ * two digit cost parameter, "$", and 22 digits from the alphabet
+ * "./0-9A-Za-z". -- from the PHP crypt docs. Apparently we enforce a few
+ * more restrictions on the count in the salt as well.
+ */
+ if (strlen(setting) < 29)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid salt")));
+
if (setting[0] != '$' ||
setting[1] != '2' ||
(setting[2] != 'a' && setting[2] != 'x') ||
@@ -611,14 +623,18 @@ _crypt_blowfish_rn(const char *key, const char *setting,
(setting[4] == '3' && setting[5] > '1') ||
setting[6] != '$')
{
- return NULL;
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid salt")));
}
count = (BF_word) 1 << ((setting[4] - '0') * 10 + (setting[5] - '0'));
if (count < 16 || BF_decode(data.binary.salt, &setting[7], 16))
{
px_memset(data.binary.salt, 0, sizeof(data.binary.salt));
- return NULL;
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid salt")));
}
BF_swap(data.binary.salt, 4);
@@ -655,6 +671,8 @@ _crypt_blowfish_rn(const char *key, const char *setting,
do
{
+ CHECK_FOR_INTERRUPTS();
+
data.ctx.P[0] ^= data.expanded_key[0];
data.ctx.P[1] ^= data.expanded_key[1];
data.ctx.P[2] ^= data.expanded_key[2];
diff --git a/contrib/pgcrypto/crypt-des.c b/contrib/pgcrypto/crypt-des.c
index b43141fed5..a4aa4966bf 100644
--- a/contrib/pgcrypto/crypt-des.c
+++ b/contrib/pgcrypto/crypt-des.c
@@ -61,6 +61,7 @@
*/
#include "postgres.h"
+#include "miscadmin.h"
#include "px-crypt.h"
@@ -540,6 +541,8 @@ do_des(uint32 l_in, uint32 r_in, uint32 *l_out, uint32 *r_out, int count)
while (count--)
{
+ CHECK_FOR_INTERRUPTS();
+
/*
* Do each round.
*/
@@ -635,6 +638,8 @@ des_cipher(const char *in, char *out, long salt, int count)
rawr = ntohl(buffer[1]);
retval = do_des(rawl, rawr, &l_out, &r_out, count);
+ if (retval)
+ return (retval);
buffer[0] = htonl(l_out);
buffer[1] = htonl(r_out);
@@ -681,9 +686,19 @@ px_crypt_des(const char *key, const char *setting)
if (*setting == _PASSWORD_EFMT1)
{
/*
- * "new"-style: setting - underscore, 4 bytes of count, 4 bytes of
- * salt key - unlimited characters
+ * "new"-style: setting must be a 9-character (underscore, then 4
+ * bytes of count, then 4 bytes of salt) string. See CRYPT(3) under
+ * the "Extended crypt" heading for further details.
+ *
+ * Unlimited characters of the input key are used. This is known as
+ * the "Extended crypt" DES method.
+ *
*/
+ if (strlen(setting) < 9)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid salt")));
+
for (i = 1, count = 0L; i < 5; i++)
count |= ascii_to_bin(setting[i]) << (i - 1) * 6;
@@ -722,10 +737,16 @@ px_crypt_des(const char *key, const char *setting)
#endif /* !DISABLE_XDES */
{
/*
- * "old"-style: setting - 2 bytes of salt key - up to 8 characters
+ * "old"-style: setting - 2 bytes of salt key - only up to the first 8
+ * characters of the input key are used.
*/
count = 25;
+ if (strlen(setting) < 2)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid salt")));
+
salt = (ascii_to_bin(setting[1]) << 6)
| ascii_to_bin(setting[0]);
diff --git a/contrib/pgcrypto/expected/crypt-blowfish.out b/contrib/pgcrypto/expected/crypt-blowfish.out
index 329d78f625..d79b0c047b 100644
--- a/contrib/pgcrypto/expected/crypt-blowfish.out
+++ b/contrib/pgcrypto/expected/crypt-blowfish.out
@@ -13,6 +13,15 @@ SELECT crypt('foox', '$2a$06$RQiOJ.3ELirrXwxIZY8q0O');
$2a$06$RQiOJ.3ELirrXwxIZY8q0OR3CVJrAfda1z26CCHPnB6mmVZD8p0/C
(1 row)
+-- error, salt too short:
+SELECT crypt('foox', '$2a$');
+ERROR: invalid salt
+-- error, first digit of count in salt invalid
+SELECT crypt('foox', '$2a$40$RQiOJ.3ELirrXwxIZY8q0O');
+ERROR: invalid salt
+-- error, count in salt too small
+SELECT crypt('foox', '$2a$00$RQiOJ.3ELirrXwxIZY8q0O');
+ERROR: invalid salt
CREATE TABLE ctest (data text, res text, salt text);
INSERT INTO ctest VALUES ('password', '', '');
UPDATE ctest SET salt = gen_salt('bf', 8);
diff --git a/contrib/pgcrypto/expected/crypt-des.out b/contrib/pgcrypto/expected/crypt-des.out
index b8b605037d..a462dcd580 100644
--- a/contrib/pgcrypto/expected/crypt-des.out
+++ b/contrib/pgcrypto/expected/crypt-des.out
@@ -13,6 +13,10 @@ SELECT crypt('foox', 'NB');
NB53EGGqrrb5E
(1 row)
+-- We are supposed to pass in a 2-character salt.
+-- error since salt is too short:
+SELECT crypt('password', 'a');
+ERROR: invalid salt
CREATE TABLE ctest (data text, res text, salt text);
INSERT INTO ctest VALUES ('password', '', '');
UPDATE ctest SET salt = gen_salt('des');
diff --git a/contrib/pgcrypto/expected/crypt-xdes.out b/contrib/pgcrypto/expected/crypt-xdes.out
index cdcdefb199..8cf907512f 100644
--- a/contrib/pgcrypto/expected/crypt-xdes.out
+++ b/contrib/pgcrypto/expected/crypt-xdes.out
@@ -13,6 +13,30 @@ SELECT crypt('foox', '_J9..j2zz');
_J9..j2zzAYKMvO2BYRY
(1 row)
+-- check XDES handling of keys longer than 8 chars
+SELECT crypt('longlongpassword', '_J9..j2zz');
+ crypt
+----------------------
+ _J9..j2zz4BeseiQNwUg
+(1 row)
+
+-- error, salt too short
+SELECT crypt('foox', '_J9..BWH');
+ERROR: invalid salt
+-- error, count specified in the second argument is 0
+SELECT crypt('password', '_........');
+ERROR: crypt(3) returned NULL
+-- error, count will wind up still being 0 due to invalid encoding
+-- of the count: only chars ``./0-9A-Za-z' are valid
+SELECT crypt('password', '_..!!!!!!');
+ERROR: crypt(3) returned NULL
+-- count should be non-zero here, will work
+SELECT crypt('password', '_/!!!!!!!');
+ crypt
+----------------------
+ _/!!!!!!!zqM49hRzxko
+(1 row)
+
CREATE TABLE ctest (data text, res text, salt text);
INSERT INTO ctest VALUES ('password', '', '');
UPDATE ctest SET salt = gen_salt('xdes', 1001);
diff --git a/contrib/pgcrypto/expected/pgp-encrypt.out b/contrib/pgcrypto/expected/pgp-encrypt.out
index b35de79afa..8fc558c402 100644
--- a/contrib/pgcrypto/expected/pgp-encrypt.out
+++ b/contrib/pgcrypto/expected/pgp-encrypt.out
@@ -103,6 +103,25 @@ select pgp_sym_decrypt(
Secret.
(1 row)
+-- s2k count change
+select pgp_sym_decrypt(
+ pgp_sym_encrypt('Secret.', 'key', 's2k-count=1024'),
+ 'key', 'expect-s2k-count=1024');
+ pgp_sym_decrypt
+-----------------
+ Secret.
+(1 row)
+
+-- s2k_count rounds up
+select pgp_sym_decrypt(
+ pgp_sym_encrypt('Secret.', 'key', 's2k-count=65000000'),
+ 'key', 'expect-s2k-count=65000000');
+NOTICE: pgp_decrypt: unexpected s2k_count: expected 65000000 got 65011712
+ pgp_sym_decrypt
+-----------------
+ Secret.
+(1 row)
+
-- s2k digest change
select pgp_sym_decrypt(
pgp_sym_encrypt('Secret.', 'key', 's2k-digest-algo=md5'),
diff --git a/contrib/pgcrypto/fortuna.c b/contrib/pgcrypto/fortuna.c
index 7ab888fb98..5028203479 100644
--- a/contrib/pgcrypto/fortuna.c
+++ b/contrib/pgcrypto/fortuna.c
@@ -304,7 +304,7 @@ get_rand_pool(FState *st)
unsigned rnd;
/*
- * This slightly prefers lower pools - thats OK.
+ * This slightly prefers lower pools - that is OK.
*/
rnd = st->key[st->rnd_pos] % NUM_POOLS;
diff --git a/contrib/pgcrypto/pgcrypto--1.2--1.3.sql b/contrib/pgcrypto/pgcrypto--1.2--1.3.sql
new file mode 100644
index 0000000000..525a03759f
--- /dev/null
+++ b/contrib/pgcrypto/pgcrypto--1.2--1.3.sql
@@ -0,0 +1,41 @@
+/* contrib/pgcrypto/pgcrypto--1.2--1.3.sql */
+
+-- complain if script is sourced in psql, rather than via ALTER EXTENSION
+\echo Use "ALTER EXTENSION pgcrypto UPDATE TO '1.3'" to load this file. \quit
+
+ALTER FUNCTION digest(text, text) PARALLEL SAFE;
+ALTER FUNCTION digest(bytea, text) PARALLEL SAFE;
+ALTER FUNCTION hmac(text, text, text) PARALLEL SAFE;
+ALTER FUNCTION hmac(bytea, bytea, text) PARALLEL SAFE;
+ALTER FUNCTION crypt(text, text) PARALLEL SAFE;
+ALTER FUNCTION gen_salt(text) PARALLEL SAFE;
+ALTER FUNCTION gen_salt(text, int4) PARALLEL SAFE;
+ALTER FUNCTION encrypt(bytea, bytea, text) PARALLEL SAFE;
+ALTER FUNCTION decrypt(bytea, bytea, text) PARALLEL SAFE;
+ALTER FUNCTION encrypt_iv(bytea, bytea, bytea, text) PARALLEL SAFE;
+ALTER FUNCTION decrypt_iv(bytea, bytea, bytea, text) PARALLEL SAFE;
+ALTER FUNCTION gen_random_bytes(int4) PARALLEL SAFE;
+ALTER FUNCTION gen_random_uuid() PARALLEL SAFE;
+ALTER FUNCTION pgp_sym_encrypt(text, text) PARALLEL SAFE;
+ALTER FUNCTION pgp_sym_encrypt_bytea(bytea, text) PARALLEL SAFE;
+ALTER FUNCTION pgp_sym_encrypt(text, text, text) PARALLEL SAFE;
+ALTER FUNCTION pgp_sym_encrypt_bytea(bytea, text, text) PARALLEL SAFE;
+ALTER FUNCTION pgp_sym_decrypt(bytea, text) PARALLEL SAFE;
+ALTER FUNCTION pgp_sym_decrypt_bytea(bytea, text) PARALLEL SAFE;
+ALTER FUNCTION pgp_sym_decrypt(bytea, text, text) PARALLEL SAFE;
+ALTER FUNCTION pgp_sym_decrypt_bytea(bytea, text, text) PARALLEL SAFE;
+ALTER FUNCTION pgp_pub_encrypt(text, bytea) PARALLEL SAFE;
+ALTER FUNCTION pgp_pub_encrypt_bytea(bytea, bytea) PARALLEL SAFE;
+ALTER FUNCTION pgp_pub_encrypt(text, bytea, text) PARALLEL SAFE;
+ALTER FUNCTION pgp_pub_encrypt_bytea(bytea, bytea, text) PARALLEL SAFE;
+ALTER FUNCTION pgp_pub_decrypt(bytea, bytea) PARALLEL SAFE;
+ALTER FUNCTION pgp_pub_decrypt_bytea(bytea, bytea) PARALLEL SAFE;
+ALTER FUNCTION pgp_pub_decrypt(bytea, bytea, text) PARALLEL SAFE;
+ALTER FUNCTION pgp_pub_decrypt_bytea(bytea, bytea, text) PARALLEL SAFE;
+ALTER FUNCTION pgp_pub_decrypt(bytea, bytea, text, text) PARALLEL SAFE;
+ALTER FUNCTION pgp_pub_decrypt_bytea(bytea, bytea, text, text) PARALLEL SAFE;
+ALTER FUNCTION pgp_key_id(bytea) PARALLEL SAFE;
+ALTER FUNCTION armor(bytea) PARALLEL SAFE;
+ALTER FUNCTION armor(bytea, text[], text[]) PARALLEL SAFE;
+ALTER FUNCTION dearmor(text) PARALLEL SAFE;
+ALTER FUNCTION pgp_armor_headers(text) PARALLEL SAFE;
diff --git a/contrib/pgcrypto/pgcrypto--1.2.sql b/contrib/pgcrypto/pgcrypto--1.3.sql
index d6d5e7de34..c2628caceb 100644
--- a/contrib/pgcrypto/pgcrypto--1.2.sql
+++ b/contrib/pgcrypto/pgcrypto--1.3.sql
@@ -1,4 +1,4 @@
-/* contrib/pgcrypto/pgcrypto--1.2.sql */
+/* contrib/pgcrypto/pgcrypto--1.3.sql */
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "CREATE EXTENSION pgcrypto" to load this file. \quit
@@ -6,67 +6,67 @@
CREATE FUNCTION digest(text, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pg_digest'
-LANGUAGE C IMMUTABLE STRICT;
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION digest(bytea, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pg_digest'
-LANGUAGE C IMMUTABLE STRICT;
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION hmac(text, text, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pg_hmac'
-LANGUAGE C IMMUTABLE STRICT;
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION hmac(bytea, bytea, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pg_hmac'
-LANGUAGE C IMMUTABLE STRICT;
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION crypt(text, text)
RETURNS text
AS 'MODULE_PATHNAME', 'pg_crypt'
-LANGUAGE C IMMUTABLE STRICT;
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION gen_salt(text)
RETURNS text
AS 'MODULE_PATHNAME', 'pg_gen_salt'
-LANGUAGE C VOLATILE STRICT;
+LANGUAGE C VOLATILE STRICT PARALLEL SAFE;
CREATE FUNCTION gen_salt(text, int4)
RETURNS text
AS 'MODULE_PATHNAME', 'pg_gen_salt_rounds'
-LANGUAGE C VOLATILE STRICT;
+LANGUAGE C VOLATILE STRICT PARALLEL SAFE;
CREATE FUNCTION encrypt(bytea, bytea, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pg_encrypt'
-LANGUAGE C IMMUTABLE STRICT;
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION decrypt(bytea, bytea, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pg_decrypt'
-LANGUAGE C IMMUTABLE STRICT;
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION encrypt_iv(bytea, bytea, bytea, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pg_encrypt_iv'
-LANGUAGE C IMMUTABLE STRICT;
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION decrypt_iv(bytea, bytea, bytea, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pg_decrypt_iv'
-LANGUAGE C IMMUTABLE STRICT;
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION gen_random_bytes(int4)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pg_random_bytes'
-LANGUAGE C VOLATILE STRICT;
+LANGUAGE C VOLATILE STRICT PARALLEL SAFE;
CREATE FUNCTION gen_random_uuid()
RETURNS uuid
AS 'MODULE_PATHNAME', 'pg_random_uuid'
-LANGUAGE C VOLATILE;
+LANGUAGE C VOLATILE PARALLEL SAFE;
--
-- pgp_sym_encrypt(data, key)
@@ -74,12 +74,12 @@ LANGUAGE C VOLATILE;
CREATE FUNCTION pgp_sym_encrypt(text, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pgp_sym_encrypt_text'
-LANGUAGE C STRICT;
+LANGUAGE C STRICT PARALLEL SAFE;
CREATE FUNCTION pgp_sym_encrypt_bytea(bytea, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pgp_sym_encrypt_bytea'
-LANGUAGE C STRICT;
+LANGUAGE C STRICT PARALLEL SAFE;
--
-- pgp_sym_encrypt(data, key, args)
@@ -87,12 +87,12 @@ LANGUAGE C STRICT;
CREATE FUNCTION pgp_sym_encrypt(text, text, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pgp_sym_encrypt_text'
-LANGUAGE C STRICT;
+LANGUAGE C STRICT PARALLEL SAFE;
CREATE FUNCTION pgp_sym_encrypt_bytea(bytea, text, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pgp_sym_encrypt_bytea'
-LANGUAGE C STRICT;
+LANGUAGE C STRICT PARALLEL SAFE;
--
-- pgp_sym_decrypt(data, key)
@@ -100,12 +100,12 @@ LANGUAGE C STRICT;
CREATE FUNCTION pgp_sym_decrypt(bytea, text)
RETURNS text
AS 'MODULE_PATHNAME', 'pgp_sym_decrypt_text'
-LANGUAGE C IMMUTABLE STRICT;
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION pgp_sym_decrypt_bytea(bytea, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pgp_sym_decrypt_bytea'
-LANGUAGE C IMMUTABLE STRICT;
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
--
-- pgp_sym_decrypt(data, key, args)
@@ -113,12 +113,12 @@ LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION pgp_sym_decrypt(bytea, text, text)
RETURNS text
AS 'MODULE_PATHNAME', 'pgp_sym_decrypt_text'
-LANGUAGE C IMMUTABLE STRICT;
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION pgp_sym_decrypt_bytea(bytea, text, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pgp_sym_decrypt_bytea'
-LANGUAGE C IMMUTABLE STRICT;
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
--
-- pgp_pub_encrypt(data, key)
@@ -126,12 +126,12 @@ LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION pgp_pub_encrypt(text, bytea)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pgp_pub_encrypt_text'
-LANGUAGE C STRICT;
+LANGUAGE C STRICT PARALLEL SAFE;
CREATE FUNCTION pgp_pub_encrypt_bytea(bytea, bytea)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pgp_pub_encrypt_bytea'
-LANGUAGE C STRICT;
+LANGUAGE C STRICT PARALLEL SAFE;
--
-- pgp_pub_encrypt(data, key, args)
@@ -139,12 +139,12 @@ LANGUAGE C STRICT;
CREATE FUNCTION pgp_pub_encrypt(text, bytea, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pgp_pub_encrypt_text'
-LANGUAGE C STRICT;
+LANGUAGE C STRICT PARALLEL SAFE;
CREATE FUNCTION pgp_pub_encrypt_bytea(bytea, bytea, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pgp_pub_encrypt_bytea'
-LANGUAGE C STRICT;
+LANGUAGE C STRICT PARALLEL SAFE;
--
-- pgp_pub_decrypt(data, key)
@@ -152,12 +152,12 @@ LANGUAGE C STRICT;
CREATE FUNCTION pgp_pub_decrypt(bytea, bytea)
RETURNS text
AS 'MODULE_PATHNAME', 'pgp_pub_decrypt_text'
-LANGUAGE C IMMUTABLE STRICT;
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION pgp_pub_decrypt_bytea(bytea, bytea)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pgp_pub_decrypt_bytea'
-LANGUAGE C IMMUTABLE STRICT;
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
--
-- pgp_pub_decrypt(data, key, psw)
@@ -165,12 +165,12 @@ LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION pgp_pub_decrypt(bytea, bytea, text)
RETURNS text
AS 'MODULE_PATHNAME', 'pgp_pub_decrypt_text'
-LANGUAGE C IMMUTABLE STRICT;
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION pgp_pub_decrypt_bytea(bytea, bytea, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pgp_pub_decrypt_bytea'
-LANGUAGE C IMMUTABLE STRICT;
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
--
-- pgp_pub_decrypt(data, key, psw, arg)
@@ -178,12 +178,12 @@ LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION pgp_pub_decrypt(bytea, bytea, text, text)
RETURNS text
AS 'MODULE_PATHNAME', 'pgp_pub_decrypt_text'
-LANGUAGE C IMMUTABLE STRICT;
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION pgp_pub_decrypt_bytea(bytea, bytea, text, text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pgp_pub_decrypt_bytea'
-LANGUAGE C IMMUTABLE STRICT;
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
--
-- PGP key ID
@@ -191,7 +191,7 @@ LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION pgp_key_id(bytea)
RETURNS text
AS 'MODULE_PATHNAME', 'pgp_key_id_w'
-LANGUAGE C IMMUTABLE STRICT;
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
--
-- pgp armor
@@ -199,19 +199,19 @@ LANGUAGE C IMMUTABLE STRICT;
CREATE FUNCTION armor(bytea)
RETURNS text
AS 'MODULE_PATHNAME', 'pg_armor'
-LANGUAGE C IMMUTABLE STRICT;
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION armor(bytea, text[], text[])
RETURNS text
AS 'MODULE_PATHNAME', 'pg_armor'
-LANGUAGE C IMMUTABLE STRICT;
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION dearmor(text)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pg_dearmor'
-LANGUAGE C IMMUTABLE STRICT;
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
CREATE FUNCTION pgp_armor_headers(text, key OUT text, value OUT text)
RETURNS SETOF record
AS 'MODULE_PATHNAME', 'pgp_armor_headers'
-LANGUAGE C IMMUTABLE STRICT;
+LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
diff --git a/contrib/pgcrypto/pgcrypto.control b/contrib/pgcrypto/pgcrypto.control
index bb6885bc1b..583983257a 100644
--- a/contrib/pgcrypto/pgcrypto.control
+++ b/contrib/pgcrypto/pgcrypto.control
@@ -1,5 +1,5 @@
# pgcrypto extension
comment = 'cryptographic functions'
-default_version = '1.2'
+default_version = '1.3'
module_pathname = '$libdir/pgcrypto'
relocatable = true
diff --git a/contrib/pgcrypto/pgp-decrypt.c b/contrib/pgcrypto/pgp-decrypt.c
index 5c69745156..9ea60c4c47 100644
--- a/contrib/pgcrypto/pgp-decrypt.c
+++ b/contrib/pgcrypto/pgp-decrypt.c
@@ -643,6 +643,7 @@ parse_symenc_sesskey(PGP_Context *ctx, PullFilter *src)
if (res < 0)
return res;
ctx->s2k_mode = ctx->s2k.mode;
+ ctx->s2k_count = s2k_decode_count(ctx->s2k.iter);
ctx->s2k_digest_algo = ctx->s2k.digest_algo;
/*
diff --git a/contrib/pgcrypto/pgp-encrypt.c b/contrib/pgcrypto/pgp-encrypt.c
index 2320c7574b..c9148fd2fc 100644
--- a/contrib/pgcrypto/pgp-encrypt.c
+++ b/contrib/pgcrypto/pgp-encrypt.c
@@ -567,7 +567,7 @@ init_s2k_key(PGP_Context *ctx)
if (ctx->s2k_cipher_algo < 0)
ctx->s2k_cipher_algo = ctx->cipher_algo;
- res = pgp_s2k_fill(&ctx->s2k, ctx->s2k_mode, ctx->s2k_digest_algo);
+ res = pgp_s2k_fill(&ctx->s2k, ctx->s2k_mode, ctx->s2k_digest_algo, ctx->s2k_count);
if (res < 0)
return res;
diff --git a/contrib/pgcrypto/pgp-pgsql.c b/contrib/pgcrypto/pgp-pgsql.c
index 1842985e53..1f65b667ca 100644
--- a/contrib/pgcrypto/pgp-pgsql.c
+++ b/contrib/pgcrypto/pgp-pgsql.c
@@ -181,6 +181,7 @@ struct debug_expect
int expect;
int cipher_algo;
int s2k_mode;
+ int s2k_count;
int s2k_cipher_algo;
int s2k_digest_algo;
int compress_algo;
@@ -196,6 +197,7 @@ fill_expect(struct debug_expect * ex, int text_mode)
ex->expect = 0;
ex->cipher_algo = -1;
ex->s2k_mode = -1;
+ ex->s2k_count = -1;
ex->s2k_cipher_algo = -1;
ex->s2k_digest_algo = -1;
ex->compress_algo = -1;
@@ -218,6 +220,7 @@ check_expect(PGP_Context *ctx, struct debug_expect * ex)
{
EX_CHECK(cipher_algo);
EX_CHECK(s2k_mode);
+ EX_CHECK(s2k_count);
EX_CHECK(s2k_digest_algo);
EX_CHECK(use_sess_key);
if (ctx->use_sess_key)
@@ -247,6 +250,8 @@ set_arg(PGP_Context *ctx, char *key, char *val,
res = pgp_set_sess_key(ctx, atoi(val));
else if (strcmp(key, "s2k-mode") == 0)
res = pgp_set_s2k_mode(ctx, atoi(val));
+ else if (strcmp(key, "s2k-count") == 0)
+ res = pgp_set_s2k_count(ctx, atoi(val));
else if (strcmp(key, "s2k-digest-algo") == 0)
res = pgp_set_s2k_digest_algo(ctx, val);
else if (strcmp(key, "s2k-cipher-algo") == 0)
@@ -286,6 +291,11 @@ set_arg(PGP_Context *ctx, char *key, char *val,
ex->expect = 1;
ex->s2k_mode = atoi(val);
}
+ else if (ex != NULL && strcmp(key, "expect-s2k-count") == 0)
+ {
+ ex->expect = 1;
+ ex->s2k_count = atoi(val);
+ }
else if (ex != NULL && strcmp(key, "expect-s2k-digest-algo") == 0)
{
ex->expect = 1;
diff --git a/contrib/pgcrypto/pgp-s2k.c b/contrib/pgcrypto/pgp-s2k.c
index 193dd95173..9937d154f2 100644
--- a/contrib/pgcrypto/pgp-s2k.c
+++ b/contrib/pgcrypto/pgp-s2k.c
@@ -132,12 +132,10 @@ calc_s2k_iter_salted(PGP_S2K *s2k, PX_MD *md, const uint8 *key,
unsigned preload = 0;
unsigned remain,
c,
- cval,
curcnt,
count;
- cval = s2k->iter;
- count = ((unsigned) 16 + (cval & 15)) << ((cval >> 4) + 6);
+ count = s2k_decode_count(s2k->iter);
md_rlen = px_md_result_size(md);
@@ -195,21 +193,34 @@ calc_s2k_iter_salted(PGP_S2K *s2k, PX_MD *md, const uint8 *key,
}
/*
- * Decide S2K_ISALTED iteration count
+ * Decide PGP_S2K_ISALTED iteration count (in OpenPGP one-byte representation)
*
* Too small: weak
* Too big: slow
* gpg defaults to 96 => 65536 iters
- * let it float a bit: 96 + 32 => 262144 iters
+ *
+ * For our default (count=-1) we let it float a bit: 96 + 32 => between 65536
+ * and 262144 iterations.
+ *
+ * Otherwise, find the smallest number which provides at least the specified
+ * iteration count.
*/
-static int
-decide_count(unsigned rand_byte)
+static uint8
+decide_s2k_iter(unsigned rand_byte, int count)
{
- return 96 + (rand_byte & 0x1F);
+ int iter;
+
+ if (count == -1)
+ return 96 + (rand_byte & 0x1F);
+ /* this is a bit brute-force, but should be quick enough */
+ for (iter = 0; iter <= 255; iter++)
+ if (s2k_decode_count(iter) >= count)
+ return iter;
+ return 255;
}
int
-pgp_s2k_fill(PGP_S2K *s2k, int mode, int digest_algo)
+pgp_s2k_fill(PGP_S2K *s2k, int mode, int digest_algo, int count)
{
int res = 0;
uint8 tmp;
@@ -219,19 +230,19 @@ pgp_s2k_fill(PGP_S2K *s2k, int mode, int digest_algo)
switch (s2k->mode)
{
- case 0:
+ case PGP_S2K_SIMPLE:
break;
- case 1:
+ case PGP_S2K_SALTED:
res = px_get_pseudo_random_bytes(s2k->salt, PGP_S2K_SALT);
break;
- case 3:
+ case PGP_S2K_ISALTED:
res = px_get_pseudo_random_bytes(s2k->salt, PGP_S2K_SALT);
if (res < 0)
break;
res = px_get_pseudo_random_bytes(&tmp, 1);
if (res < 0)
break;
- s2k->iter = decide_count(tmp);
+ s2k->iter = decide_s2k_iter(tmp, count);
break;
default:
res = PXE_PGP_BAD_S2K_MODE;
diff --git a/contrib/pgcrypto/pgp.c b/contrib/pgcrypto/pgp.c
index 03fe48fb64..0800fc325d 100644
--- a/contrib/pgcrypto/pgp.c
+++ b/contrib/pgcrypto/pgp.c
@@ -40,6 +40,7 @@
static int def_cipher_algo = PGP_SYM_AES_128;
static int def_s2k_cipher_algo = -1;
static int def_s2k_mode = PGP_S2K_ISALTED;
+static int def_s2k_count = -1;
static int def_s2k_digest_algo = PGP_DIGEST_SHA1;
static int def_compress_algo = PGP_COMPR_NONE;
static int def_compress_level = 6;
@@ -206,6 +207,7 @@ pgp_init(PGP_Context **ctx_p)
ctx->cipher_algo = def_cipher_algo;
ctx->s2k_cipher_algo = def_s2k_cipher_algo;
ctx->s2k_mode = def_s2k_mode;
+ ctx->s2k_count = def_s2k_count;
ctx->s2k_digest_algo = def_s2k_digest_algo;
ctx->compress_algo = def_compress_algo;
ctx->compress_level = def_compress_level;
@@ -270,6 +272,17 @@ pgp_set_s2k_mode(PGP_Context *ctx, int mode)
}
int
+pgp_set_s2k_count(PGP_Context *ctx, int count)
+{
+ if (ctx->s2k_mode == PGP_S2K_ISALTED && count >= 1024 && count <= 65011712)
+ {
+ ctx->s2k_count = count;
+ return PXE_OK;
+ }
+ return PXE_ARGUMENT_ERROR;
+}
+
+int
pgp_set_compress_algo(PGP_Context *ctx, int algo)
{
switch (algo)
diff --git a/contrib/pgcrypto/pgp.h b/contrib/pgcrypto/pgp.h
index 62b8517c27..804a27018a 100644
--- a/contrib/pgcrypto/pgp.h
+++ b/contrib/pgcrypto/pgp.h
@@ -124,7 +124,7 @@ struct PGP_S2K
uint8 mode;
uint8 digest_algo;
uint8 salt[8];
- uint8 iter;
+ uint8 iter; /* encoded (one-octet) count */
/* calculated: */
uint8 key[PGP_MAX_KEY];
uint8 key_len;
@@ -138,6 +138,7 @@ struct PGP_Context
*/
PGP_S2K s2k;
int s2k_mode;
+ int s2k_count; /* 4-byte decoded count */
int s2k_digest_algo;
int s2k_cipher_algo;
int cipher_algo;
@@ -171,6 +172,10 @@ struct PGP_Context
unsigned sess_key_len;
};
+/* from RFC 4880 3.7.1.3 */
+#define s2k_decode_count(cval) \
+ (((unsigned) 16 + (cval & 15)) << ((cval >> 4) + 6))
+
struct PGP_MPI
{
uint8 *data;
@@ -243,6 +248,7 @@ const char *pgp_get_cipher_name(int code);
int pgp_set_cipher_algo(PGP_Context *ctx, const char *name);
int pgp_set_s2k_mode(PGP_Context *ctx, int type);
+int pgp_set_s2k_count(PGP_Context *ctx, int count);
int pgp_set_s2k_cipher_algo(PGP_Context *ctx, const char *name);
int pgp_set_s2k_digest_algo(PGP_Context *ctx, const char *name);
int pgp_set_convert_crlf(PGP_Context *ctx, int doit);
@@ -267,7 +273,7 @@ int pgp_load_cipher(int c, PX_Cipher **res);
int pgp_get_cipher_key_size(int c);
int pgp_get_cipher_block_size(int c);
-int pgp_s2k_fill(PGP_S2K *s2k, int mode, int digest_algo);
+int pgp_s2k_fill(PGP_S2K *s2k, int mode, int digest_algo, int count);
int pgp_s2k_read(PullFilter *src, PGP_S2K *s2k);
int pgp_s2k_process(PGP_S2K *s2k, int cipher, const uint8 *key, int klen);
diff --git a/contrib/pgcrypto/px-crypt.c b/contrib/pgcrypto/px-crypt.c
index 7b003a76ca..e3246fc5b9 100644
--- a/contrib/pgcrypto/px-crypt.c
+++ b/contrib/pgcrypto/px-crypt.c
@@ -42,7 +42,7 @@ run_crypt_des(const char *psw, const char *salt,
char *res;
res = px_crypt_des(psw, salt);
- if (strlen(res) > len - 1)
+ if (res == NULL || strlen(res) > len - 1)
return NULL;
strcpy(buf, res);
return buf;
diff --git a/contrib/pgcrypto/px.c b/contrib/pgcrypto/px.c
index cfb3b50985..7e69da696f 100644
--- a/contrib/pgcrypto/px.c
+++ b/contrib/pgcrypto/px.c
@@ -48,7 +48,7 @@ static const struct error_desc px_err_list[] = {
{PXE_BAD_OPTION, "Unknown option"},
{PXE_BAD_FORMAT, "Badly formatted type"},
{PXE_KEY_TOO_BIG, "Key was too big"},
- {PXE_CIPHER_INIT, "Cipher cannot be initalized ?"},
+ {PXE_CIPHER_INIT, "Cipher cannot be initialized ?"},
{PXE_HASH_UNUSABLE_FOR_HMAC, "This hash algorithm is unusable for HMAC"},
{PXE_DEV_READ_ERROR, "Error reading from random device"},
{PXE_OSSL_RAND_ERROR, "OpenSSL PRNG error"},
diff --git a/contrib/pgcrypto/sha1.h b/contrib/pgcrypto/sha1.h
index 5532ca160d..2f61e454ba 100644
--- a/contrib/pgcrypto/sha1.h
+++ b/contrib/pgcrypto/sha1.h
@@ -63,7 +63,7 @@ extern void sha1_pad(struct sha1_ctxt *);
extern void sha1_loop(struct sha1_ctxt *, const uint8 *, size_t);
extern void sha1_result(struct sha1_ctxt *, uint8 *);
-/* compatibilty with other SHA1 source codes */
+/* compatibility with other SHA1 source codes */
typedef struct sha1_ctxt SHA1_CTX;
#define SHA1Init(x) sha1_init((x))
diff --git a/contrib/pgcrypto/sql/crypt-blowfish.sql b/contrib/pgcrypto/sql/crypt-blowfish.sql
index 60c1140055..3b5a681c3f 100644
--- a/contrib/pgcrypto/sql/crypt-blowfish.sql
+++ b/contrib/pgcrypto/sql/crypt-blowfish.sql
@@ -6,6 +6,15 @@ SELECT crypt('', '$2a$06$RQiOJ.3ELirrXwxIZY8q0O');
SELECT crypt('foox', '$2a$06$RQiOJ.3ELirrXwxIZY8q0O');
+-- error, salt too short:
+SELECT crypt('foox', '$2a$');
+
+-- error, first digit of count in salt invalid
+SELECT crypt('foox', '$2a$40$RQiOJ.3ELirrXwxIZY8q0O');
+
+-- error, count in salt too small
+SELECT crypt('foox', '$2a$00$RQiOJ.3ELirrXwxIZY8q0O');
+
CREATE TABLE ctest (data text, res text, salt text);
INSERT INTO ctest VALUES ('password', '', '');
diff --git a/contrib/pgcrypto/sql/crypt-des.sql b/contrib/pgcrypto/sql/crypt-des.sql
index fabdc652fc..a85ec1e655 100644
--- a/contrib/pgcrypto/sql/crypt-des.sql
+++ b/contrib/pgcrypto/sql/crypt-des.sql
@@ -6,6 +6,10 @@ SELECT crypt('', 'NB');
SELECT crypt('foox', 'NB');
+-- We are supposed to pass in a 2-character salt.
+-- error since salt is too short:
+SELECT crypt('password', 'a');
+
CREATE TABLE ctest (data text, res text, salt text);
INSERT INTO ctest VALUES ('password', '', '');
diff --git a/contrib/pgcrypto/sql/crypt-xdes.sql b/contrib/pgcrypto/sql/crypt-xdes.sql
index d4a74f76bd..8171cd872b 100644
--- a/contrib/pgcrypto/sql/crypt-xdes.sql
+++ b/contrib/pgcrypto/sql/crypt-xdes.sql
@@ -6,6 +6,22 @@ SELECT crypt('', '_J9..j2zz');
SELECT crypt('foox', '_J9..j2zz');
+-- check XDES handling of keys longer than 8 chars
+SELECT crypt('longlongpassword', '_J9..j2zz');
+
+-- error, salt too short
+SELECT crypt('foox', '_J9..BWH');
+
+-- error, count specified in the second argument is 0
+SELECT crypt('password', '_........');
+
+-- error, count will wind up still being 0 due to invalid encoding
+-- of the count: only chars ``./0-9A-Za-z' are valid
+SELECT crypt('password', '_..!!!!!!');
+
+-- count should be non-zero here, will work
+SELECT crypt('password', '_/!!!!!!!');
+
CREATE TABLE ctest (data text, res text, salt text);
INSERT INTO ctest VALUES ('password', '', '');
diff --git a/contrib/pgcrypto/sql/pgp-encrypt.sql b/contrib/pgcrypto/sql/pgp-encrypt.sql
index a9ac0b924b..ed9d2c8127 100644
--- a/contrib/pgcrypto/sql/pgp-encrypt.sql
+++ b/contrib/pgcrypto/sql/pgp-encrypt.sql
@@ -55,6 +55,15 @@ select pgp_sym_decrypt(
pgp_sym_encrypt('Secret.', 'key', 's2k-mode=3'),
'key', 'expect-s2k-mode=3');
+-- s2k count change
+select pgp_sym_decrypt(
+ pgp_sym_encrypt('Secret.', 'key', 's2k-count=1024'),
+ 'key', 'expect-s2k-count=1024');
+-- s2k_count rounds up
+select pgp_sym_decrypt(
+ pgp_sym_encrypt('Secret.', 'key', 's2k-count=65000000'),
+ 'key', 'expect-s2k-count=65000000');
+
-- s2k digest change
select pgp_sym_decrypt(
pgp_sym_encrypt('Secret.', 'key', 's2k-digest-algo=md5'),