diff options
author | Pavan Deolasee | 2016-10-27 15:02:55 +0000 |
---|---|---|
committer | Pavan Deolasee | 2016-10-27 15:02:55 +0000 |
commit | c52792488cd87e67e62ec61f5b56f461900353b4 (patch) | |
tree | 02b4a719f979659de8f73fce6c1ca65cef2e323f /contrib/pgcrypto | |
parent | 891e6be57e5580b54a9df9fd42cb9bd10d0e7b21 (diff) | |
parent | b5bce6c1ec6061c8a4f730d927e162db7e2ce365 (diff) |
Merge commit 'b5bce6c1ec6061c8a4f730d927e162db7e2ce365'
Diffstat (limited to 'contrib/pgcrypto')
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'), |