diff --git a/contrib/pgcrypto/Makefile b/contrib/pgcrypto/Makefile
index 148df11306b151b771d6f4eed4dd404f423cc0e8..657e6d236fac9925b6796ea5fb5da2829d13fd57 100644
--- a/contrib/pgcrypto/Makefile
+++ b/contrib/pgcrypto/Makefile
@@ -1,5 +1,5 @@
 #
-# $PostgreSQL: pgsql/contrib/pgcrypto/Makefile,v 1.21 2005/07/10 18:32:55 momjian Exp $
+# $PostgreSQL: pgsql/contrib/pgcrypto/Makefile,v 1.22 2005/08/13 02:06:20 momjian Exp $
 #
 
 INT_SRCS = md5.c sha1.c sha2.c internal.c blf.c rijndael.c \
@@ -56,17 +56,13 @@ endif
 # Add libraries that pgcrypto depends (or might depend) on into the
 # shared library link.  (The order in which you list them here doesn't
 # matter.)
-SHLIB_LINK += $(filter -lcrypt -ldes -lcrypto -lssl -lz, $(LIBS))
+SHLIB_LINK += $(filter -lcrypto -lz, $(LIBS))
 ifeq ($(PORTNAME), win32)
-SHLIB_LINK += $(filter -leay32 -lssleay32 -lz, $(LIBS))
-endif
-
-# to make ws2_32.lib the last library (must occur after definition of PORTNAME)
-ifeq ($(PORTNAME),win32)
+SHLIB_LINK += $(filter -leay32, $(LIBS))
+# those must be at the end
 SHLIB_LINK += -lwsock32 -lws2_32
 endif
 
-
 rijndael.o: rijndael.tbl
 
 rijndael.tbl:
diff --git a/contrib/pgcrypto/README.pgcrypto b/contrib/pgcrypto/README.pgcrypto
index a6ef003f215ec8e36093f1a2db20821fad0714a8..58836c5dabb717effc02592ef426b04289084160 100644
--- a/contrib/pgcrypto/README.pgcrypto
+++ b/contrib/pgcrypto/README.pgcrypto
@@ -1,4 +1,3 @@
-$PostgreSQL: pgsql/contrib/pgcrypto/README.pgcrypto,v 1.12 2005/07/18 17:17:12 tgl Exp $
 
 pgcrypto - cryptographic functions for PostgreSQL
 =================================================
@@ -278,7 +277,7 @@ cracking.  Or may not.
 -------------------
 
 The functions here implement the encryption part of OpenPGP (RFC2440)
-standard.
+standard.   Supported are both symmetric-key and public-key encryption.
 
 
 5.1.  Overview
@@ -334,6 +333,10 @@ Options are described in section 5.7.
 
 Decrypt a symmetric-key encrypted PGP message.
 
+Decrypting bytea data with `pgp_sym_decrypt` is disallowed.
+This is to avoid outputting invalid character data.  Decrypting
+originally textual data with `pgp_sym_decrypt_bytea` is fine.
+
 Options are described in section 5.7.
 
 
@@ -362,6 +365,10 @@ key is password-protected, you must give the password in `psw`.  If
 there is no password, but you want to specify option for function, you
 need to give empty password.
 
+Decrypting bytea data with `pgp_pub_decrypt` is disallowed.
+This is to avoid outputting invalid character data.  Decrypting
+originally textual data with `pgp_pub_decrypt_bytea` is fine.
+
 Options are described in section 5.7.
 
 
@@ -422,7 +429,6 @@ cipher-algo::
   Default: aes128
   Applies: pgp_sym_encrypt, pgp_pub_encrypt
 
-
 compress-algo::
   Which compression algorithm to use.  Needs building with zlib.
 
@@ -492,7 +498,7 @@ s2k-cipher-algo::
   Which cipher to use for encrypting separate session key.
 
   Values: bf, aes, aes128, aes192, aes256
-  Default: same as cipher-algo.
+  Default: use cipher-algo.
   Applies: pgp_sym_encrypt
 
 unicode-mode::
@@ -513,7 +519,10 @@ Generate a new key:
 
     gpg --gen-key
 
-You need to pick "DSA and Elgamal" key type, others are sign-only.
+The preferred key type is "DSA and Elgamal".
+
+For RSA encryption you must create either DSA or RSA sign-only key
+as master and then add RSA encryption subkey with `gpg --edit-key`.
 
 List keys:
 
@@ -531,6 +540,9 @@ You need to use `dearmor()` on them before giving giving them to
 pgp_pub_* functions.  Or if you can handle binary data, you can drop
 "-a" from gpg.
 
+For more details see `man gpg`, http://www.gnupg.org/gph/en/manual.html[
+The GNU Privacy Handbook] and other docs on http://www.gnupg.org[] site.
+
 
 5.10.  Limitations of PGP code
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -538,9 +550,13 @@ pgp_pub_* functions.  Or if you can handle binary data, you can drop
 - No support for signing.  That also means that it is not checked
   whether the encryption subkey belongs to master key.
 
-- No support for RSA keys.  Only Elgamal encryption keys are supported
+- No support for encryption key as master key.  As such practice
+  is generally discouraged, it should not be a problem.
 
-- No support for several encryption subkeys.
+- No support for several subkeys.  This may seem like a problem, as this
+  is common practice.  On the other hand, you should not use your regular
+  GPG/PGP keys with pgcrypto, but create new ones, as the usage scenario
+  is rather different.
 
 
 6.  Raw encryption
@@ -631,6 +647,9 @@ I have used code from following sources:
 9.1.  Useful reading
 ~~~~~~~~~~~~~~~~~~~~~
 
+http://www.gnupg.org/gph/en/manual.html[]::
+	The GNU Privacy Handbook
+
 http://www.openwall.com/crypt/[]::
 	Describes the crypt-blowfish algorithm.
 
@@ -673,3 +692,7 @@ http://jlcooke.ca/random/[]::
 
 http://www.cs.ut.ee/~helger/crypto/[]::
 	Collection of cryptology pointers.
+
+
+// $PostgreSQL: pgsql/contrib/pgcrypto/README.pgcrypto,v 1.13 2005/08/13 02:06:20 momjian Exp $
+
diff --git a/contrib/pgcrypto/expected/pgp-armor.out b/contrib/pgcrypto/expected/pgp-armor.out
index ba7d4262377875b2e2b3746db0f58741f4026531..60a89e5c48871837d094226cf68dcc12b4a83a72 100644
--- a/contrib/pgcrypto/expected/pgp-armor.out
+++ b/contrib/pgcrypto/expected/pgp-armor.out
@@ -99,4 +99,4 @@ em9va2E=
 =ZZZZ
 -----END PGP MESSAGE-----
 ');
-ERROR:  dearmor: Corrupt ascii-armor
+ERROR:  Corrupt ascii-armor
diff --git a/contrib/pgcrypto/expected/pgp-encrypt.out b/contrib/pgcrypto/expected/pgp-encrypt.out
index b04bae5720737a3bc5a2f96b1af420d2bea7ae39..ab33a04eec3319de634707acc64692df2a63fcac 100644
--- a/contrib/pgcrypto/expected/pgp-encrypt.out
+++ b/contrib/pgcrypto/expected/pgp-encrypt.out
@@ -43,7 +43,7 @@ NOTICE:  pgp_decrypt: unexpected compress_algo: expected 1 got 0
 
 -- bytea as text
 select pgp_sym_decrypt(pgp_sym_encrypt_bytea('Binary', 'baz'), 'baz');
-ERROR:  pgp_decrypt error: Not text data
+ERROR:  Not text data
 -- text as bytea
 select pgp_sym_decrypt_bytea(pgp_sym_encrypt('Text', 'baz'), 'baz');
  pgp_sym_decrypt_bytea 
diff --git a/contrib/pgcrypto/expected/pgp-info.out b/contrib/pgcrypto/expected/pgp-info.out
index 300d41adcd1885ce76a1fe3e00d18ea7dfc9773c..1fe008890fbd1e273415f7a0e74fbaeaa9af3979 100644
--- a/contrib/pgcrypto/expected/pgp-info.out
+++ b/contrib/pgcrypto/expected/pgp-info.out
@@ -21,13 +21,19 @@ select pgp_key_id(dearmor(pubkey)) from keytbl where id=3;
 (1 row)
 
 select pgp_key_id(dearmor(pubkey)) from keytbl where id=4; -- should fail
-ERROR:  No usable key found (expecting Elgamal key)
+ERROR:  No encryption key found
 select pgp_key_id(dearmor(pubkey)) from keytbl where id=5;
     pgp_key_id    
 ------------------
  D936CF64BB73F466
 (1 row)
 
+select pgp_key_id(dearmor(pubkey)) from keytbl where id=6;
+    pgp_key_id    
+------------------
+ FD0206C409B74875
+(1 row)
+
 select pgp_key_id(dearmor(seckey)) from keytbl where id=1;
     pgp_key_id    
 ------------------
@@ -47,13 +53,19 @@ select pgp_key_id(dearmor(seckey)) from keytbl where id=3;
 (1 row)
 
 select pgp_key_id(dearmor(seckey)) from keytbl where id=4; -- should fail
-ERROR:  No usable key found (expecting Elgamal key)
+ERROR:  No encryption key found
 select pgp_key_id(dearmor(seckey)) from keytbl where id=5;
     pgp_key_id    
 ------------------
  D936CF64BB73F466
 (1 row)
 
+select pgp_key_id(dearmor(seckey)) from keytbl where id=6;
+    pgp_key_id    
+------------------
+ FD0206C409B74875
+(1 row)
+
 select pgp_key_id(dearmor(data)) as data_key_id
 from encdata order by id;
    data_key_id    
@@ -61,5 +73,6 @@ from encdata order by id;
  D936CF64BB73F466
  2C226E1FFE5CC7D4
  B68504FD128E1FF9
-(3 rows)
+ FD0206C409B74875
+(4 rows)
 
diff --git a/contrib/pgcrypto/expected/pgp-pubkey-decrypt.out b/contrib/pgcrypto/expected/pgp-pubkey-decrypt.out
index 28881ad3479a73c052a7136d8b6c5e594f18a739..7d16a43279d97b2e7dded1137d506ebb7e35a651 100644
--- a/contrib/pgcrypto/expected/pgp-pubkey-decrypt.out
+++ b/contrib/pgcrypto/expected/pgp-pubkey-decrypt.out
@@ -326,6 +326,97 @@ saCh6QCfR1O48O8nYN93SPSfIFZK5rEmdv8=
 =Y6Qv
 -----END PGP PRIVATE KEY BLOCK-----
 ');
+insert into keytbl (id, name, pubkey, seckey)
+values (6, 'rsaenc2048', '
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1.4.1 (GNU/Linux)
+
+mQELBELr2m0BCADOrnknlnXI0EzRExf/TgoHvK7Xx/E0keWqV3KrOyC3/tY2KOrj
+UVxaAX5pkFX9wdQObGPIJm06u6D16CH6CildX/vxG7YgvvKzK8JGAbwrXAfk7OIW
+czO2zRaZGDynoK3mAxHRBReyTKtNv8rDQhuZs6AOozJNARdbyUO/yqUnqNNygWuT
+4htFDEuLPIJwAbMSD0BvFW6YQaPdxzaAZm3EWVNbwDzjgbBUdBiUUwRdZIFUhsjJ
+dirFdy5+uuZru6y6CNC1OERkJ7P8EyoFiZckAIE5gshVZzNuyLOZjc5DhWBvLbX4
+NZElAnfiv+4nA6y8wQLSIbmHA3nqJaBklj85AAYptCVSU0EgMjA0OCBFbmMgPHJz
+YTIwNDhlbmNAZXhhbXBsZS5vcmc+iQE0BBMBAgAeBQJC69ptAhsDBgsJCAcDAgMV
+AgMDFgIBAh4BAheAAAoJEMiZ6pNEGVVZHMkIAJtGHHZ9iM8Yq1rr0zl1L6SvlQP8
+JCaxHa31wH3PKqGtq2M+cpb2rXf7gAY/doHJPXggfVzkyFrysmQ1gPbDGYLyOutw
++IkhihEb5bWxQBNj+3zAFs1YX6v2HXWbSUSmyY1V9/+NTtKk03olDc/swd3lXzku
+UOhcgfpBgIt3Q+MpT6M2+OIF7lVfSb1rWdpwTfGhZzW9szQOeoS4gPvxCCRyuabQ
+RJ6DWH61F8fFIDJg1z+A/Obx4fqX6GOA69RzgZ3oukFBIXxNwV9PZNnAmHtZVYO8
+0g/oVYBbuvOYedffDBeQarhERZ5W2TnIE+nqY61YOLBqosliygdZTXULzNi5AQsE
+QuvaugEIAOuCJZdkzORA6e1lr81Lnr4JzMsVBFA+X/yIkBbV6qX/A4nVSLAZKNPX
+z1YIrMTu+1rMIiy10IWbA6zgMTpzPhJRfgePONgdnCYyK5Ksh5/C5ntzKwwGwxfK
+lAXIxJurCHXTbEa+YvPdn76vJ3HsXOXVEL+fLb4U3l3Ng87YM202Lh1Ha2MeS2zE
+FZcAoKbFqAAjDLEai64SoOFh0W3CsD1DL4zmfp+YZrUPHTtZadsi53i4KKW/ws9U
+rHlolqYNhYze/uRLyfnUx9PN4r/GhEzauyDMV0smo91uB3aewPft+eCpmeWnu0PF
+JVK4xyRmhIq2rVCw16a1pBJirvGM+y0ABimJAR8EGAECAAkFAkLr2roCGwwACgkQ
+yJnqk0QZVVku1wgAg1bLSjPkhw+ldG5HzumpqR84+JKyozdJaJzefu2+1iqYE0B0
+WLz2PJVIiK41xiEkKhBvTOQYuXmtWqAWXptD91P5SoXoNJWLQO3TNwarANhHxkWg
+w/TOUxQqoctlRUej5NDD+4eW5G9lcS1FEGuKDWtX096u80vO+TbyJjvx2eVM1k+X
+dmeYsGOiNgDimCreJGYc14G7eY9jt24gw10n1sMAKI1qm6lcoHqZ9OOyla+wJdro
+PYZGO7R8+1O9R22WrK6BYDT5j/1JwMZqbOESjNvDEVT0yOHClCHRN4CChbt6LhKh
+CLUNdz/udIt0JAC6c/HdPLSW3HnmM3+iNj+Kug==
+=pwU2
+-----END PGP PUBLIC KEY BLOCK-----
+', '
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+Version: GnuPG v1.4.1 (GNU/Linux)
+
+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
+=UKh3
+-----END PGP PRIVATE KEY BLOCK-----
+');
 -- elg1024 / aes128
 insert into encdata (id, data) values (1, '
 -----BEGIN PGP MESSAGE-----
@@ -393,6 +484,22 @@ DYKcOy60/OHMWVvpw6trAoA+iP+cVWPtrbRvLglTVTfYmi1ToZDDipkALBhndQ==
 =L/M/
 -----END PGP MESSAGE-----
 ');
+-- rsaenc2048 / aes128
+insert into encdata (id, data) values (4, '
+-----BEGIN PGP MESSAGE-----
+Version: GnuPG v1.4.1 (GNU/Linux)
+
+hQEMA/0CBsQJt0h1AQf+JyYnCiortj26P11zk28MKOGfWpWyAhuIgwbJXsdQ+e6r
+pEyyqs9GC6gI7SNF6+J8B/gsMwvkAL4FHAQCvA4ZZ6eeXR1Of4YG22JQGmpWVWZg
+DTyfhA2vkczuqfAD2tgUpMT6sdyGkQ/fnQ0lknlfHgC5GRx7aavOoAKtMqiZW5PR
+yae/qR48mjX7Mb+mLvbagv9mHEgQSmHwFpaq2k456BbcZ23bvCmBnCvqV/90Ggfb
+VP6gkSoFVsJ19RHsOhW1dk9ehbl51WB3zUOO5FZWwUTY9DJvKblRK/frF0+CXjE4
+HfcZXHSpSjx4haGGTsMvEJ85qFjZpr0eTGOdY5cFhNJAAVP8MZfji7OhPRAoOOIK
+eRGOCkao12pvPyFTFnPd5vqmyBbdNpK4Q0hS82ljugMJvM0p3vJZVzW402Kz6iBL
+GQ==
+=XHkF
+-----END PGP MESSAGE-----
+');
 -- successful decrypt
 select pgp_pub_decrypt(dearmor(data), dearmor(seckey))
 from keytbl, encdata where keytbl.id=1 and encdata.id=1;
@@ -415,22 +522,29 @@ from keytbl, encdata where keytbl.id=3 and encdata.id=3;
  Secret msg
 (1 row)
 
+select pgp_pub_decrypt(dearmor(data), dearmor(seckey))
+from keytbl, encdata where keytbl.id=6 and encdata.id=4;
+ pgp_pub_decrypt 
+-----------------
+ Secret message.
+(1 row)
+
 -- wrong key
 select pgp_pub_decrypt(dearmor(data), dearmor(seckey))
 from keytbl, encdata where keytbl.id=2 and encdata.id=1;
-ERROR:  pgp_decrypt error: Data is not encrypted with this key
+ERROR:  Wrong key
 -- sign-only key
 select pgp_pub_decrypt(dearmor(data), dearmor(seckey))
 from keytbl, encdata where keytbl.id=4 and encdata.id=1;
-ERROR:  pgp_decrypt error: No usable key found (expecting Elgamal key)
+ERROR:  No encryption key found
 -- password-protected secret key, no password
 select pgp_pub_decrypt(dearmor(data), dearmor(seckey))
 from keytbl, encdata where keytbl.id=5 and encdata.id=1;
-ERROR:  pgp_decrypt error: Need password for secret key
+ERROR:  Need password for secret key
 -- password-protected secret key, wrong password
 select pgp_pub_decrypt(dearmor(data), dearmor(seckey), 'foo')
 from keytbl, encdata where keytbl.id=5 and encdata.id=1;
-ERROR:  pgp_decrypt error: Corrupt data
+ERROR:  Corrupt data
 -- password-protected secret key, right password
 select pgp_pub_decrypt(dearmor(data), dearmor(seckey), 'parool')
 from keytbl, encdata where keytbl.id=5 and encdata.id=1;
diff --git a/contrib/pgcrypto/expected/pgp-pubkey-encrypt.out b/contrib/pgcrypto/expected/pgp-pubkey-encrypt.out
index a7b1c027eef669e87838918f01979c9277198c57..e222541c24c8b2e463380bd4f37ce30929ecc31e 100644
--- a/contrib/pgcrypto/expected/pgp-pubkey-encrypt.out
+++ b/contrib/pgcrypto/expected/pgp-pubkey-encrypt.out
@@ -29,18 +29,27 @@ from keytbl where keytbl.id=3;
  Secret msg
 (1 row)
 
+select pgp_pub_decrypt(
+		pgp_pub_encrypt('Secret msg', dearmor(pubkey)),
+		dearmor(seckey))
+from keytbl where keytbl.id=6;
+ pgp_pub_decrypt 
+-----------------
+ Secret msg
+(1 row)
+
 -- try with rsa-sign only
 select pgp_pub_decrypt(
 		pgp_pub_encrypt('Secret msg', dearmor(pubkey)),
 		dearmor(seckey))
 from keytbl where keytbl.id=4;
-ERROR:  pgp_encrypt error: No usable key found (expecting Elgamal key)
+ERROR:  No encryption key found
 -- try with secret key
 select pgp_pub_decrypt(
 		pgp_pub_encrypt('Secret msg', dearmor(seckey)),
 		dearmor(seckey))
 from keytbl where keytbl.id=1;
-ERROR:  pgp_encrypt error: Refusing to encrypt with secret key
+ERROR:  Refusing to encrypt with secret key
 -- does text-to-bytea works
 select pgp_pub_decrypt_bytea(
 		pgp_pub_encrypt('Secret msg', dearmor(pubkey)),
@@ -56,4 +65,4 @@ select pgp_pub_decrypt(
 		pgp_pub_encrypt_bytea('Secret msg', dearmor(pubkey)),
 		dearmor(seckey))
 from keytbl where keytbl.id=1;
-ERROR:  pgp_decrypt error: Not text data
+ERROR:  Not text data
diff --git a/contrib/pgcrypto/pgp-info.c b/contrib/pgcrypto/pgp-info.c
index 58752b7c83d6eedcd0324bd86a3b079a6b2776ca..89737f51f6efdcffffac8b344b49e2b1d539e81c 100644
--- a/contrib/pgcrypto/pgp-info.c
+++ b/contrib/pgcrypto/pgp-info.c
@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-info.c,v 1.2 2005/07/11 15:07:59 tgl Exp $
+ * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-info.c,v 1.3 2005/08/13 02:06:20 momjian Exp $
  */
 #include "postgres.h"
 
@@ -36,26 +36,31 @@
 
 static int read_pubkey_keyid(PullFilter *pkt, uint8 *keyid_buf)
 {
-	int res = 0;
-	PGP_PubKey *pk;
-
-	res = pgp_key_alloc(&pk);
-	if (res < 0)
-		return res;
+	int res;
+	PGP_PubKey *pk = NULL;
 
-	res = _pgp_read_public_key(pkt, pk);
+	res = _pgp_read_public_key(pkt, &pk);
 	if (res < 0)
 		goto err;
+
+	/* skip secret key part, if it exists */
 	res = pgp_skip_packet(pkt);
 	if (res < 0)
 		goto err;
 
-	res = 0;
-	if (pk->algo == PGP_PUB_ELG_ENCRYPT)
+	/* is it encryption key */
+	switch (pk->algo)
 	{
-		memcpy(keyid_buf, pk->key_id, 8);
-		res = 1;
+		case PGP_PUB_ELG_ENCRYPT:
+		case PGP_PUB_RSA_ENCRYPT:
+		case PGP_PUB_RSA_ENCRYPT_SIGN:
+			memcpy(keyid_buf, pk->key_id, 8);
+			res = 1;
+			break;
+		default:
+			res = 0;
 	}
+
 err:
 	pgp_key_free(pk);
 	return res;
@@ -110,6 +115,7 @@ pgp_get_keyid(MBuf *pgp_data, char *dst)
 	int got_pub_key=0, got_symenc_key=0, got_pubenc_key=0;
 	int got_data=0;
 	uint8 keyid_buf[8];
+	int got_main_key=0;
 
 
 	res = pullf_create_mbuf_reader(&src, pgp_data);
@@ -128,6 +134,15 @@ pgp_get_keyid(MBuf *pgp_data, char *dst)
 		{
 			case PGP_PKT_SECRET_KEY:
 			case PGP_PKT_PUBLIC_KEY:
+				/* main key is for signing, so ignore it */
+				if (!got_main_key)
+				{
+					got_main_key = 1;
+					res = pgp_skip_packet(pkt);
+				}
+				else
+					res = PXE_PGP_MULTIPLE_KEYS;
+				break;
 			case PGP_PKT_SECRET_SUBKEY:
 			case PGP_PKT_PUBLIC_SUBKEY:
 				res = read_pubkey_keyid(pkt, keyid_buf);
@@ -142,6 +157,7 @@ pgp_get_keyid(MBuf *pgp_data, char *dst)
 				break;
 			case PGP_PKT_SYMENCRYPTED_DATA:
 			case PGP_PKT_SYMENCRYPTED_DATA_MDC:
+				/* don't skip it, just stop */
 				got_data = 1;
 				break;
 			case PGP_PKT_SYMENCRYPTED_SESSKEY:
@@ -179,10 +195,10 @@ pgp_get_keyid(MBuf *pgp_data, char *dst)
 		res = PXE_PGP_CORRUPT_DATA;
 
 	if (got_pub_key > 1)
-		res = -1;
+		res = PXE_PGP_MULTIPLE_KEYS;
 
 	if (got_pubenc_key > 1)
-		res = -1;
+		res = PXE_PGP_MULTIPLE_KEYS;
 
 	/*
 	 * if still ok, look what we got
diff --git a/contrib/pgcrypto/pgp-mpi-internal.c b/contrib/pgcrypto/pgp-mpi-internal.c
index 626700e2c9e68f7d06de2ba4cd7fdf0bfb60d204..5cdc0e1b9d00c5ff6bf6ca13f21a9a0ebcf9671c 100644
--- a/contrib/pgcrypto/pgp-mpi-internal.c
+++ b/contrib/pgcrypto/pgp-mpi-internal.c
@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-mpi-internal.c,v 1.2 2005/07/11 15:07:59 tgl Exp $
+ * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-mpi-internal.c,v 1.3 2005/08/13 02:06:20 momjian Exp $
  */
 #include "postgres.h"
 
@@ -48,3 +48,14 @@ pgp_elgamal_decrypt(PGP_PubKey *pk, PGP_MPI *_c1, PGP_MPI *_c2,
 	return PXE_PGP_NO_BIGNUM;
 }
 
+int pgp_rsa_encrypt(PGP_PubKey *pk, PGP_MPI *m, PGP_MPI **c)
+{
+	return PXE_PGP_NO_BIGNUM;
+}
+
+int pgp_rsa_decrypt(PGP_PubKey *pk, PGP_MPI *c, PGP_MPI **m)
+{
+	return PXE_PGP_NO_BIGNUM;
+}
+
+
diff --git a/contrib/pgcrypto/pgp-mpi-openssl.c b/contrib/pgcrypto/pgp-mpi-openssl.c
index 61ef6f3943e364c8dab20c337f7a7536412145be..3ae40ee07543574ddb36993500fc46f017d31cb7 100644
--- a/contrib/pgcrypto/pgp-mpi-openssl.c
+++ b/contrib/pgcrypto/pgp-mpi-openssl.c
@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-mpi-openssl.c,v 1.2 2005/07/11 15:07:59 tgl Exp $
+ * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-mpi-openssl.c,v 1.3 2005/08/13 02:06:20 momjian Exp $
  */
 #include "postgres.h"
 
@@ -104,9 +104,9 @@ pgp_elgamal_encrypt(PGP_PubKey *pk, PGP_MPI *_m,
 	int res = PXE_PGP_MATH_FAILED;
 	int k_bits;
 	BIGNUM *m = mpi_to_bn(_m);
-	BIGNUM *p = mpi_to_bn(pk->elg_p);
-	BIGNUM *g = mpi_to_bn(pk->elg_g);
-	BIGNUM *y = mpi_to_bn(pk->elg_y);
+	BIGNUM *p = mpi_to_bn(pk->pub.elg.p);
+	BIGNUM *g = mpi_to_bn(pk->pub.elg.g);
+	BIGNUM *y = mpi_to_bn(pk->pub.elg.y);
 	BIGNUM *k = BN_new();
 	BIGNUM *yk = BN_new();
 	BIGNUM *c1 = BN_new();
@@ -120,7 +120,7 @@ pgp_elgamal_encrypt(PGP_PubKey *pk, PGP_MPI *_m,
 	 * generate k
 	 */
 	k_bits = decide_k_bits(BN_num_bits(p));
-	if (!BN_generate_prime(k, k_bits, 0, NULL, NULL, NULL, NULL))
+	if (!BN_rand(k, k_bits, 0, 0))
 		goto err;
 
 	/*
@@ -159,8 +159,8 @@ pgp_elgamal_decrypt(PGP_PubKey *pk, PGP_MPI *_c1, PGP_MPI *_c2,
 	int res = PXE_PGP_MATH_FAILED;
 	BIGNUM *c1 = mpi_to_bn(_c1);
 	BIGNUM *c2 = mpi_to_bn(_c2);
-	BIGNUM *p = mpi_to_bn(pk->elg_p);
-	BIGNUM *x = mpi_to_bn(pk->elg_x);
+	BIGNUM *p = mpi_to_bn(pk->pub.elg.p);
+	BIGNUM *x = mpi_to_bn(pk->sec.elg.x);
 	BIGNUM *c1x = BN_new();
 	BIGNUM *div = BN_new();
 	BIGNUM *m = BN_new();
@@ -195,3 +195,65 @@ err:
 	return res;
 }
 
+int
+pgp_rsa_encrypt(PGP_PubKey *pk, PGP_MPI *_m, PGP_MPI **c_p)
+{
+	int res = PXE_PGP_MATH_FAILED;
+	BIGNUM *m = mpi_to_bn(_m);
+	BIGNUM *e = mpi_to_bn(pk->pub.rsa.e);
+	BIGNUM *n = mpi_to_bn(pk->pub.rsa.n);
+	BIGNUM *c = BN_new();
+	BN_CTX *tmp = BN_CTX_new();
+
+	if (!m || !e || !n || !c || !tmp)
+		goto err;
+
+	/*
+	 * c = m ^ e
+	 */
+	if (!BN_mod_exp(c, m, e, n, tmp))
+		goto err;
+
+	*c_p = bn_to_mpi(c);
+	if (*c_p)
+		res = 0;
+err:
+	if (tmp) BN_CTX_free(tmp);
+	if (c) BN_clear_free(c);
+	if (n) BN_clear_free(n);
+	if (e) BN_clear_free(e);
+	if (m) BN_clear_free(m);
+	return res;
+}
+
+int
+pgp_rsa_decrypt(PGP_PubKey *pk, PGP_MPI *_c, PGP_MPI **m_p)
+{
+	int res = PXE_PGP_MATH_FAILED;
+	BIGNUM *c = mpi_to_bn(_c);
+	BIGNUM *d = mpi_to_bn(pk->sec.rsa.d);
+	BIGNUM *n = mpi_to_bn(pk->pub.rsa.n);
+	BIGNUM *m = BN_new();
+	BN_CTX *tmp = BN_CTX_new();
+
+	if (!m || !d || !n || !c || !tmp)
+		goto err;
+
+	/*
+	 * m = c ^ d
+	 */
+	if (!BN_mod_exp(m, c, d, n, tmp))
+		goto err;
+
+	*m_p = bn_to_mpi(m);
+	if (*m_p)
+		res = 0;
+err:
+	if (tmp) BN_CTX_free(tmp);
+	if (m) BN_clear_free(m);
+	if (n) BN_clear_free(n);
+	if (d) BN_clear_free(d);
+	if (c) BN_clear_free(c);
+	return res;
+}
+
diff --git a/contrib/pgcrypto/pgp-mpi.c b/contrib/pgcrypto/pgp-mpi.c
index 9ae9363bfc52562e487c406d27fd403211788eb8..1e19ed7fb46591cf69f4ddfd36494c9a317eaf8c 100644
--- a/contrib/pgcrypto/pgp-mpi.c
+++ b/contrib/pgcrypto/pgp-mpi.c
@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-mpi.c,v 1.2 2005/07/11 15:07:59 tgl Exp $
+ * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-mpi.c,v 1.3 2005/08/13 02:06:20 momjian Exp $
  */
 #include "postgres.h"
 
@@ -66,6 +66,8 @@ int pgp_mpi_create(uint8 *data, int bits, PGP_MPI **mpi)
 
 int pgp_mpi_free(PGP_MPI *mpi)
 {
+	if (mpi == NULL)
+		return 0;
 	memset(mpi, 0, sizeof(*mpi) + mpi->bytes);
 	px_free(mpi);
 	return 0;
@@ -129,6 +131,6 @@ unsigned pgp_mpi_cksum(unsigned cksum, PGP_MPI *n)
 	for (i = 0; i < n->bytes; i++)
 		cksum += n->data[i];
 
-	return cksum;
+	return cksum & 0xFFFF;
 }
 
diff --git a/contrib/pgcrypto/pgp-pgsql.c b/contrib/pgcrypto/pgp-pgsql.c
index b64027b73e8db015f2770c57279697bce1070adc..9e8b30795fc9185fd0db337a420e7e213ed91083 100644
--- a/contrib/pgcrypto/pgp-pgsql.c
+++ b/contrib/pgcrypto/pgp-pgsql.c
@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-pgsql.c,v 1.3 2005/07/18 17:12:54 tgl Exp $
+ * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-pgsql.c,v 1.4 2005/08/13 02:06:20 momjian Exp $
  */
 
 #include "postgres.h"
@@ -496,7 +496,7 @@ encrypt_internal(int is_pubenc, int is_text,
 		mbuf_free(dst);
 		ereport(ERROR,
 				(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
-				 errmsg("pgp_encrypt error: %s", px_strerror(err))));
+				 errmsg("%s", px_strerror(err))));
 	}
 
 	/* res_len includes VARHDRSZ */
@@ -591,7 +591,7 @@ out:
 			mbuf_free(dst);
 		ereport(ERROR,
 				(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
-				 errmsg("pgp_decrypt error: %s", px_strerror(err))));
+				 errmsg("%s", px_strerror(err))));
 	}
 
 	res_len = mbuf_steal_data(dst, &restmp);
@@ -879,7 +879,7 @@ pg_dearmor(PG_FUNCTION_ARGS)
 	if (res_len < 0)
 		ereport(ERROR,
 				(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
-				 errmsg("dearmor: %s", px_strerror(res_len))));
+				 errmsg("%s", px_strerror(res_len))));
 	if (res_len > guess_len)
 		ereport(ERROR,
 				(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
@@ -909,9 +909,7 @@ pgp_key_id_w(PG_FUNCTION_ARGS)
 	buf = create_mbuf_from_vardata(data);
 	res = palloc(VARHDRSZ + 17);
 
-	px_set_debug_handler(show_debug);
 	res_len = pgp_get_keyid(buf, VARDATA(res));
-	px_set_debug_handler(NULL);
 	mbuf_free(buf);
 	if (res_len < 0)
 		ereport(ERROR,
diff --git a/contrib/pgcrypto/pgp-pubdec.c b/contrib/pgcrypto/pgp-pubdec.c
index 32cae7f71681f200e182f82afe38ba4fc153b2d9..04e98ceacbbe57ce4b35c598effa59afe0a2152d 100644
--- a/contrib/pgcrypto/pgp-pubdec.c
+++ b/contrib/pgcrypto/pgp-pubdec.c
@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-pubdec.c,v 1.3 2005/07/11 15:07:59 tgl Exp $
+ * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-pubdec.c,v 1.4 2005/08/13 02:06:20 momjian Exp $
  */
 #include "postgres.h"
 
@@ -77,7 +77,7 @@ control_cksum(uint8 *msg, int msglen)
 	unsigned my_cksum, got_cksum;
 
 	if (msglen < 3)
-		return PXE_PGP_CORRUPT_DATA;
+		return PXE_PGP_WRONG_KEY;
 
 	my_cksum = 0;
 	for (i = 1; i < msglen - 2; i++)
@@ -86,11 +86,60 @@ control_cksum(uint8 *msg, int msglen)
 	got_cksum = ((unsigned)(msg[msglen-2]) << 8) + msg[msglen-1];
 	if (my_cksum != got_cksum) {
 		px_debug("pubenc cksum failed");
-		return PXE_PGP_CORRUPT_DATA;
+		return PXE_PGP_WRONG_KEY;
 	}
 	return 0;
 }
 
+static int
+decrypt_elgamal(PGP_PubKey *pk, PullFilter *pkt, PGP_MPI **m_p)
+{
+	int res;
+	PGP_MPI *c1 = NULL;
+	PGP_MPI *c2 = NULL;
+
+	if (pk->algo != PGP_PUB_ELG_ENCRYPT)
+		return PXE_PGP_WRONG_KEY;
+
+	/* read elgamal encrypted data */
+	res = pgp_mpi_read(pkt, &c1);
+	if (res < 0)
+		goto out;
+	res = pgp_mpi_read(pkt, &c2);
+	if (res < 0)
+		goto out;
+
+	/* decrypt */
+	res = pgp_elgamal_decrypt(pk, c1, c2, m_p);
+
+out:
+	pgp_mpi_free(c1);
+	pgp_mpi_free(c2);
+	return res;
+}
+
+static int
+decrypt_rsa(PGP_PubKey *pk, PullFilter *pkt, PGP_MPI **m_p)
+{
+	int res;
+	PGP_MPI *c;
+
+	if (pk->algo != PGP_PUB_RSA_ENCRYPT
+			&& pk->algo != PGP_PUB_RSA_ENCRYPT_SIGN)
+		return PXE_PGP_WRONG_KEY;
+
+	/* read rsa encrypted data */
+	res = pgp_mpi_read(pkt, &c);
+	if (res < 0)
+		return res;
+
+	/* decrypt */
+	res = pgp_rsa_decrypt(pk, c, m_p);
+
+	pgp_mpi_free(c);
+	return res;
+}
+
 /* key id is missing - user is expected to try all keys */
 static const uint8
 any_key[] = {0, 0, 0, 0, 0, 0, 0, 0};
@@ -102,7 +151,6 @@ pgp_parse_pubenc_sesskey(PGP_Context *ctx, PullFilter *pkt)
 	int algo;
 	int res;
 	uint8 key_id[8];
-	PGP_MPI *c1, *c2;
 	PGP_PubKey *pk;
 	uint8 *msg;
 	int msglen;
@@ -113,11 +161,7 @@ pgp_parse_pubenc_sesskey(PGP_Context *ctx, PullFilter *pkt)
 		px_debug("no pubkey?");
 		return PXE_BUG;
 	}
-	if (!pk->elg_p || !pk->elg_g || !pk->elg_y || !pk->elg_x) {
-		px_debug("seckey not loaded?");
-		return PXE_BUG;
-	}
-	
+
 	GETBYTE(pkt, ver);
 	if (ver != 3) {
 		px_debug("unknown pubenc_sesskey pkt ver=%d", ver);
@@ -134,33 +178,25 @@ pgp_parse_pubenc_sesskey(PGP_Context *ctx, PullFilter *pkt)
 	 && memcmp(key_id, pk->key_id, 8) != 0)
 	{
 		px_debug("key_id's does not match");
-		return PXE_PGP_WRONG_KEYID;
+		return PXE_PGP_WRONG_KEY;
 	}
 
+	/*
+	 * Decrypt
+	 */
 	GETBYTE(pkt, algo);
-	if (algo != PGP_PUB_ELG_ENCRYPT)
+	switch (algo)
 	{
-		px_debug("unknown public-key algo=%d", algo);
-		if (algo == PGP_PUB_RSA_ENCRYPT || algo == PGP_PUB_RSA_ENCRYPT_SIGN)
-			return PXE_PGP_RSA_UNSUPPORTED;
-		else
-			return PXE_PGP_UNKNOWN_PUBALGO;
+		case PGP_PUB_ELG_ENCRYPT:
+			res = decrypt_elgamal(pk, pkt, &m);
+			break;
+		case PGP_PUB_RSA_ENCRYPT:
+		case PGP_PUB_RSA_ENCRYPT_SIGN:
+			res = decrypt_rsa(pk, pkt, &m);
+			break;
+		default:
+			res = PXE_PGP_UNKNOWN_PUBALGO;
 	}
-
-	/*
-	 * read elgamal encrypted data
-	 */
-	res = pgp_mpi_read(pkt, &c1);
-	if (res < 0)
-		return res;
-	res = pgp_mpi_read(pkt, &c2);
-	if (res < 0)
-		return res;
-
-	/*
-	 * decrypt
-	 */
-	res = pgp_elgamal_decrypt(pk, c1, c2, &m);
 	if (res < 0)
 		return res;
 
@@ -170,13 +206,14 @@ pgp_parse_pubenc_sesskey(PGP_Context *ctx, PullFilter *pkt)
 	msg = check_eme_pkcs1_v15(m->data, m->bytes);
 	if (msg == NULL) {
 		px_debug("check_eme_pkcs1_v15 failed");
-		return PXE_PGP_CORRUPT_DATA;
+		res = PXE_PGP_WRONG_KEY;
+		goto out;
 	}
 	msglen = m->bytes - (msg - m->data);
 
 	res = control_cksum(msg, msglen);
 	if (res < 0)
-		return res;
+		goto out;
 
 	/*
 	 * got sesskey
@@ -185,6 +222,10 @@ pgp_parse_pubenc_sesskey(PGP_Context *ctx, PullFilter *pkt)
 	ctx->sess_key_len = msglen - 3;
 	memcpy(ctx->sess_key, msg + 1, ctx->sess_key_len);
 
+out:
+	pgp_mpi_free(m);
+	if (res < 0)
+		return res;
 	return pgp_expect_packet_end(pkt);
 }
 
diff --git a/contrib/pgcrypto/pgp-pubenc.c b/contrib/pgcrypto/pgp-pubenc.c
index 3585e16b0be13469aca2423fcaf6f1e163852710..3b2dd85c48ac30524db2cd3e3494c7a380b91eae 100644
--- a/contrib/pgcrypto/pgp-pubenc.c
+++ b/contrib/pgcrypto/pgp-pubenc.c
@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-pubenc.c,v 1.2 2005/07/11 15:07:59 tgl Exp $
+ * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-pubenc.c,v 1.3 2005/08/13 02:06:20 momjian Exp $
  */
 #include "postgres.h"
 
@@ -84,39 +84,16 @@ pad_eme_pkcs1_v15(uint8 *data, int data_len, int res_len, uint8 **res_p)
 	return 0;
 }
 
-/*
- * Decide the padded message length in bytes.
- * It should be as large as possible, but not larger
- * than p.
- *
- * To get max size (and assuming p may have weird sizes):
- * ((p->bytes * 8 - 6) > p->bits) ? (p->bytes - 1) : p->bytes
- *
- * Following mirrors gnupg behaviour.
- */
 static int
-decide_msglen(PGP_MPI *p)
-{
-	return p->bytes - 1;
-}
-
-static int
-create_secmsg(PGP_Context *ctx, PGP_MPI **msg_p)
+create_secmsg(PGP_Context *ctx, PGP_MPI **msg_p, int full_bytes)
 {
 	uint8 *secmsg;
-	int res, i, full_bytes;
+	int res, i;
 	unsigned cksum = 0;
 	int klen = ctx->sess_key_len;
 	uint8 *padded = NULL;
 	PGP_MPI *m = NULL;
-	PGP_PubKey *pk = ctx->pub_key;
 
-	/*
-	 * Refuse to operate with keys < 1024
-	 */
-	if (pk->elg_p->bits < 1024)
-		return PXE_PGP_SHORT_ELGAMAL_KEY;
-	
 	/* calc checksum */
 	for (i = 0; i < klen; i++)
 		cksum += ctx->sess_key[i];
@@ -133,7 +110,6 @@ create_secmsg(PGP_Context *ctx, PGP_MPI **msg_p)
 	/*
 	 * now create a large integer of it
 	 */
-	full_bytes = decide_msglen(pk->elg_p);
 	res = pad_eme_pkcs1_v15(secmsg, klen + 3, full_bytes, &padded);
 	if (res >= 0)
 	{
@@ -156,37 +132,72 @@ create_secmsg(PGP_Context *ctx, PGP_MPI **msg_p)
 	return res;
 }
 
+static int
+encrypt_and_write_elgamal(PGP_Context *ctx, PGP_PubKey *pk, PushFilter *pkt)
+{
+	int res;
+	PGP_MPI *m = NULL, *c1 = NULL, *c2 = NULL;
+
+	/* create padded msg */
+	res = create_secmsg(ctx, &m, pk->pub.elg.p->bytes - 1);
+	if (res < 0)
+		goto err;
+
+	/* encrypt it */
+	res = pgp_elgamal_encrypt(pk, m, &c1, &c2);
+	if (res < 0)
+		goto err;
+
+	/* write out */
+	res = pgp_mpi_write(pkt, c1);
+	if (res < 0)
+		goto err;
+	res = pgp_mpi_write(pkt, c2);
+
+err:
+	pgp_mpi_free(m);
+	pgp_mpi_free(c1);
+	pgp_mpi_free(c2);
+	return res;
+}
+
+static int
+encrypt_and_write_rsa(PGP_Context *ctx, PGP_PubKey *pk, PushFilter *pkt)
+{
+	int res;
+	PGP_MPI *m = NULL, *c = NULL;
+
+	/* create padded msg */
+	res = create_secmsg(ctx, &m, pk->pub.rsa.n->bytes - 1);
+	if (res < 0)
+		goto err;
+
+	/* encrypt it */
+	res = pgp_rsa_encrypt(pk, m, &c);
+	if (res < 0)
+		goto err;
+
+	/* write out */
+	res = pgp_mpi_write(pkt, c);
+
+err:
+	pgp_mpi_free(m);
+	pgp_mpi_free(c);
+	return res;
+}
+
 int pgp_write_pubenc_sesskey(PGP_Context *ctx, PushFilter *dst)
 {
 	int res;
 	PGP_PubKey *pk = ctx->pub_key;
-	PGP_MPI *m = NULL, *c1 = NULL, *c2 = NULL;
 	uint8 ver = 3;
-	uint8 algo = PGP_PUB_ELG_ENCRYPT;
 	PushFilter *pkt = NULL;
+	uint8 algo = pk->algo;
 
 	if (pk == NULL) {
 		px_debug("no pubkey?\n");
 		return PXE_BUG;
 	}
-	if (!pk->elg_p || !pk->elg_g || !pk->elg_y) {
-		px_debug("pubkey not loaded?\n");
-		return PXE_BUG;
-	}
-
-	/*
-	 * sesskey packet
-	 */
-	res = create_secmsg(ctx, &m);
-	if (res < 0)
-		goto err;
-
-	/*
-	 * encrypt it
-	 */
-	res = pgp_elgamal_encrypt(pk, m, &c1, &c2);
-	if (res < 0)
-		goto err;
 
 	/*
 	 * now write packet
@@ -203,10 +214,17 @@ int pgp_write_pubenc_sesskey(PGP_Context *ctx, PushFilter *dst)
 	res = pushf_write(pkt, &algo, 1);
 	if (res < 0)
 		goto err;
-	res = pgp_mpi_write(pkt, c1);
-	if (res < 0)
-		goto err;
-	res = pgp_mpi_write(pkt, c2);
+
+	switch (algo)
+	{
+		case PGP_PUB_ELG_ENCRYPT:
+			res = encrypt_and_write_elgamal(ctx, pk, pkt);
+			break;
+		case PGP_PUB_RSA_ENCRYPT:
+		case PGP_PUB_RSA_ENCRYPT_SIGN:
+			res = encrypt_and_write_rsa(ctx, pk, pkt);
+			break;
+	}
 	if (res < 0)
 		goto err;
 
@@ -217,12 +235,6 @@ int pgp_write_pubenc_sesskey(PGP_Context *ctx, PushFilter *dst)
 err:
 	if (pkt)
 		pushf_free(pkt);
-	if (m)
-		pgp_mpi_free(m);
-	if (c1)
-		pgp_mpi_free(c1);
-	if (c2)
-		pgp_mpi_free(c2);
 
 	return res;
 }
diff --git a/contrib/pgcrypto/pgp-pubkey.c b/contrib/pgcrypto/pgp-pubkey.c
index ec5c148b530722cbdfd536cb0464d23be67b6be8..9eb3c23c087eccdd606c6604f4185353e64559ad 100644
--- a/contrib/pgcrypto/pgp-pubkey.c
+++ b/contrib/pgcrypto/pgp-pubkey.c
@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-pubkey.c,v 1.2 2005/07/11 15:07:59 tgl Exp $
+ * $PostgreSQL: pgsql/contrib/pgcrypto/pgp-pubkey.c,v 1.3 2005/08/13 02:06:20 momjian Exp $
  */
 #include "postgres.h"
 
@@ -34,8 +34,6 @@
 #include "mbuf.h"
 #include "pgp.h"
 
-#define PXE_PGP_BAD_KEY -90
-
 int pgp_key_alloc(PGP_PubKey **pk_p)
 {
 	PGP_PubKey *pk;
@@ -47,14 +45,35 @@ int pgp_key_alloc(PGP_PubKey **pk_p)
 
 void pgp_key_free(PGP_PubKey *pk)
 {
-	if (pk->elg_p)
-		pgp_mpi_free(pk->elg_p);
-	if (pk->elg_g)
-		pgp_mpi_free(pk->elg_g);
-	if (pk->elg_y)
-		pgp_mpi_free(pk->elg_y);
-	if (pk->elg_x)
-		pgp_mpi_free(pk->elg_x);
+	if (pk == NULL)
+		return;
+
+	switch (pk->algo)
+	{
+		case PGP_PUB_ELG_ENCRYPT:
+			pgp_mpi_free(pk->pub.elg.p);
+			pgp_mpi_free(pk->pub.elg.g);
+			pgp_mpi_free(pk->pub.elg.y);
+			pgp_mpi_free(pk->sec.elg.x);
+			break;
+		case PGP_PUB_RSA_SIGN:
+		case PGP_PUB_RSA_ENCRYPT:
+		case PGP_PUB_RSA_ENCRYPT_SIGN:
+			pgp_mpi_free(pk->pub.rsa.n);
+			pgp_mpi_free(pk->pub.rsa.e);
+			pgp_mpi_free(pk->sec.rsa.d);
+			pgp_mpi_free(pk->sec.rsa.p);
+			pgp_mpi_free(pk->sec.rsa.q);
+			pgp_mpi_free(pk->sec.rsa.u);
+			break;
+		case PGP_PUB_DSA_SIGN:
+			pgp_mpi_free(pk->pub.dsa.p);
+			pgp_mpi_free(pk->pub.dsa.q);
+			pgp_mpi_free(pk->pub.dsa.g);
+			pgp_mpi_free(pk->pub.dsa.y);
+			pgp_mpi_free(pk->sec.dsa.x);
+			break;
+	}
 	memset(pk, 0, sizeof(*pk));
 	px_free(pk);
 }
@@ -76,9 +95,21 @@ calc_key_id(PGP_PubKey *pk)
 	switch (pk->algo)
 	{
 		case PGP_PUB_ELG_ENCRYPT:
-			len += 2 + pk->elg_p->bytes;
-			len += 2 + pk->elg_g->bytes;
-			len += 2 + pk->elg_y->bytes;
+			len += 2 + pk->pub.elg.p->bytes;
+			len += 2 + pk->pub.elg.g->bytes;
+			len += 2 + pk->pub.elg.y->bytes;
+			break;
+		case PGP_PUB_RSA_SIGN:
+		case PGP_PUB_RSA_ENCRYPT:
+		case PGP_PUB_RSA_ENCRYPT_SIGN:
+			len += 2 + pk->pub.rsa.n->bytes;
+			len += 2 + pk->pub.rsa.e->bytes;
+			break;
+		case PGP_PUB_DSA_SIGN:
+			len += 2 + pk->pub.dsa.p->bytes;
+			len += 2 + pk->pub.dsa.q->bytes;
+			len += 2 + pk->pub.dsa.g->bytes;
+			len += 2 + pk->pub.dsa.y->bytes;
 			break;
 	}
 
@@ -94,9 +125,21 @@ calc_key_id(PGP_PubKey *pk)
 	switch (pk->algo)
 	{
 		case PGP_PUB_ELG_ENCRYPT:
-			pgp_mpi_hash(md, pk->elg_p);
-			pgp_mpi_hash(md, pk->elg_g);
-			pgp_mpi_hash(md, pk->elg_y);
+			pgp_mpi_hash(md, pk->pub.elg.p);
+			pgp_mpi_hash(md, pk->pub.elg.g);
+			pgp_mpi_hash(md, pk->pub.elg.y);
+			break;
+		case PGP_PUB_RSA_SIGN:
+		case PGP_PUB_RSA_ENCRYPT:
+		case PGP_PUB_RSA_ENCRYPT_SIGN:
+			pgp_mpi_hash(md, pk->pub.rsa.n);
+			pgp_mpi_hash(md, pk->pub.rsa.e);
+			break;
+		case PGP_PUB_DSA_SIGN:
+			pgp_mpi_hash(md, pk->pub.dsa.p);
+			pgp_mpi_hash(md, pk->pub.dsa.q);
+			pgp_mpi_hash(md, pk->pub.dsa.g);
+			pgp_mpi_hash(md, pk->pub.dsa.y);
 			break;
 	}
 
@@ -109,47 +152,82 @@ calc_key_id(PGP_PubKey *pk)
 	return 0;
 }
 
-int _pgp_read_public_key(PullFilter *pkt, PGP_PubKey *pk)
+int _pgp_read_public_key(PullFilter *pkt, PGP_PubKey **pk_p)
 {
 	int res;
+	PGP_PubKey *pk;
+
+	res = pgp_key_alloc(&pk);
+	if (res < 0)
+		return res;
 
 	/* get version */
 	GETBYTE(pkt, pk->ver);
 	if (pk->ver != 4) {
-		px_debug("\tunsupported version: %d", pk->ver);
-		return PXE_PGP_NOT_V4_KEYPKT;
+		res = PXE_PGP_NOT_V4_KEYPKT;
+		goto out;
 	}
 	
 	/* read time */
 	res = pullf_read_fixed(pkt, 4, pk->time);
 	if (res < 0)
-		return res;
+		goto out;
 
 	/* pubkey algorithm */
 	GETBYTE(pkt, pk->algo);
 
 	switch (pk->algo) {
-		case PGP_PUB_RSA_ENCRYPT_SIGN:
-		case PGP_PUB_RSA_ENCRYPT:
-		case PGP_PUB_RSA_SIGN:
 		case PGP_PUB_DSA_SIGN:
-			res = pgp_skip_packet(pkt);
+			res = pgp_mpi_read(pkt, &pk->pub.dsa.p);
+			if (res < 0) break;
+			res = pgp_mpi_read(pkt, &pk->pub.dsa.q);
+			if (res < 0) break;
+			res = pgp_mpi_read(pkt, &pk->pub.dsa.g);
+			if (res < 0) break;
+			res = pgp_mpi_read(pkt, &pk->pub.dsa.y);
+			if (res < 0) break;
+
+			res = calc_key_id(pk);
 			break;
+
+		case PGP_PUB_RSA_SIGN:
+		case PGP_PUB_RSA_ENCRYPT:
+		case PGP_PUB_RSA_ENCRYPT_SIGN:
+			res = pgp_mpi_read(pkt, &pk->pub.rsa.n);
+			if (res < 0) break;
+			res = pgp_mpi_read(pkt, &pk->pub.rsa.e);
+			if (res < 0) break;
+
+			res = calc_key_id(pk);
+
+			if (pk->algo != PGP_PUB_RSA_SIGN)
+				pk->can_encrypt = 1;
+			break;
+
 		case PGP_PUB_ELG_ENCRYPT:
-			res = pgp_mpi_read(pkt, &pk->elg_p);
+			res = pgp_mpi_read(pkt, &pk->pub.elg.p);
 			if (res < 0) break;
-			res = pgp_mpi_read(pkt, &pk->elg_g);
+			res = pgp_mpi_read(pkt, &pk->pub.elg.g);
 			if (res < 0) break;
-			res = pgp_mpi_read(pkt, &pk->elg_y);
+			res = pgp_mpi_read(pkt, &pk->pub.elg.y);
 			if (res < 0) break;
 
 			res = calc_key_id(pk);
+
+			pk->can_encrypt = 1;
 			break;
+
 		default:
 			px_debug("unknown public algo: %d", pk->algo);
 			res = PXE_PGP_UNKNOWN_PUBALGO;
 	}
 
+out:
+	if (res < 0)
+		pgp_key_free(pk);
+	else
+		*pk_p = pk;
+
 	return res;
 }
 
@@ -175,7 +253,18 @@ check_key_sha1(PullFilter *src, PGP_PubKey *pk)
 	switch (pk->algo)
 	{
 		case PGP_PUB_ELG_ENCRYPT:
-			pgp_mpi_hash(md, pk->elg_x);
+			pgp_mpi_hash(md, pk->sec.elg.x);
+			break;
+		case PGP_PUB_RSA_SIGN:
+		case PGP_PUB_RSA_ENCRYPT:
+		case PGP_PUB_RSA_ENCRYPT_SIGN:
+			pgp_mpi_hash(md, pk->sec.rsa.d);
+			pgp_mpi_hash(md, pk->sec.rsa.p);
+			pgp_mpi_hash(md, pk->sec.rsa.q);
+			pgp_mpi_hash(md, pk->sec.rsa.u);
+			break;
+		case PGP_PUB_DSA_SIGN:
+			pgp_mpi_hash(md, pk->sec.dsa.x);
 			break;
 	}
 	px_md_finish(md, my_sha1);
@@ -207,7 +296,18 @@ check_key_cksum(PullFilter *src, PGP_PubKey *pk)
 	switch (pk->algo)
 	{
 		case PGP_PUB_ELG_ENCRYPT:
-			my_cksum = pgp_mpi_cksum(0, pk->elg_x);
+			my_cksum = pgp_mpi_cksum(0, pk->sec.elg.x);
+			break;
+		case PGP_PUB_RSA_SIGN:
+		case PGP_PUB_RSA_ENCRYPT:
+		case PGP_PUB_RSA_ENCRYPT_SIGN:
+			my_cksum = pgp_mpi_cksum(0, pk->sec.rsa.d);
+			my_cksum = pgp_mpi_cksum(my_cksum, pk->sec.rsa.p);
+			my_cksum = pgp_mpi_cksum(my_cksum, pk->sec.rsa.q);
+			my_cksum = pgp_mpi_cksum(my_cksum, pk->sec.rsa.u);
+			break;
+		case PGP_PUB_DSA_SIGN:
+			my_cksum = pgp_mpi_cksum(0, pk->sec.dsa.x);
 			break;
 	}
 	if (my_cksum != got_cksum)
@@ -218,7 +318,7 @@ check_key_cksum(PullFilter *src, PGP_PubKey *pk)
 	return 0;
 }
 
-static int process_secret_key(PullFilter *pkt, PGP_PubKey *pk,
+static int process_secret_key(PullFilter *pkt, PGP_PubKey **pk_p,
 		const uint8 *key, int key_len)
 {
 	int res;
@@ -229,16 +329,13 @@ static int process_secret_key(PullFilter *pkt, PGP_PubKey *pk,
 	PullFilter *pf_decrypt = NULL, *pf_key;
 	PGP_CFB *cfb = NULL;
 	PGP_S2K s2k;
+	PGP_PubKey *pk;
 
 	/* first read public key part */
-	res = _pgp_read_public_key(pkt, pk);
+	res = _pgp_read_public_key(pkt, &pk);
 	if (res < 0)
 		return res;
 
-	/* skip key? */
-	if (pk->algo != PGP_PUB_ELG_ENCRYPT)
-		return 0;
-
 	/*
 	 * is secret key encrypted?
 	 */
@@ -282,15 +379,23 @@ static int process_secret_key(PullFilter *pkt, PGP_PubKey *pk,
 
 	/* read secret key */
 	switch (pk->algo) {
-		case PGP_PUB_RSA_ENCRYPT_SIGN:
-		case PGP_PUB_RSA_ENCRYPT:
 		case PGP_PUB_RSA_SIGN:
-		case PGP_PUB_DSA_SIGN:
-			px_debug("unsupported public algo: %d", pk->algo);
-			res = PXE_PGP_UNSUPPORTED_PUBALGO;
+		case PGP_PUB_RSA_ENCRYPT:
+		case PGP_PUB_RSA_ENCRYPT_SIGN:
+			res = pgp_mpi_read(pkt, &pk->sec.rsa.d);
+			if (res < 0) break;
+			res = pgp_mpi_read(pkt, &pk->sec.rsa.p);
+			if (res < 0) break;
+			res = pgp_mpi_read(pkt, &pk->sec.rsa.q);
+			if (res < 0) break;
+			res = pgp_mpi_read(pkt, &pk->sec.rsa.u);
+			if (res < 0) break;
 			break;
 		case PGP_PUB_ELG_ENCRYPT:
-			res = pgp_mpi_read(pf_key, &pk->elg_x);
+			res = pgp_mpi_read(pf_key, &pk->sec.elg.x);
+			break;
+		case PGP_PUB_DSA_SIGN:
+			res = pgp_mpi_read(pf_key, &pk->sec.dsa.x);
 			break;
 		default:
 			px_debug("unknown public algo: %d", pk->algo);
@@ -312,31 +417,31 @@ static int process_secret_key(PullFilter *pkt, PGP_PubKey *pk,
 	if (cfb)
 		pgp_cfb_free(cfb);
 
+	if (res < 0)
+		pgp_key_free(pk);
+	else
+		*pk_p = pk;
+
 	return res;
 }
 
 static int
 internal_read_key(PullFilter *src, PGP_PubKey **pk_p,
-					const uint8 *key, int key_len, int pubtype)
+					const uint8 *psw, int psw_len, int pubtype)
 {
 	PullFilter *pkt = NULL;
 	int res;
 	uint8 tag;
 	int len;
+	PGP_PubKey *enc_key = NULL;
 	PGP_PubKey *pk = NULL;
-	int got_key = 0;
-	int n_subkey = 0;
-
-	res = pgp_key_alloc(&pk);
-	if (res < 0)
-		return res;
+	int got_main_key = 0;
 
 	/*
-	 * Search for Elgamal key.
+	 * Search for encryption key.
 	 *
 	 * Error out on anything fancy.
 	 */
-	res = PXE_PGP_KEYPKT_CORRUPT;
 	while (1) {
 		res = pgp_parse_pkt_hdr(src, &tag, &len, 0);
 		if (res <= 0)
@@ -346,46 +451,31 @@ internal_read_key(PullFilter *src, PGP_PubKey **pk_p,
 			break;
 		
 		switch (tag) {
+			case PGP_PKT_PUBLIC_KEY:
 			case PGP_PKT_SECRET_KEY:
-				if (got_key)
+				if (got_main_key)
 				{
 					res = PXE_PGP_MULTIPLE_KEYS;
 					break;
 				}
-				got_key = 1;
-				n_subkey = 0;
-				/* fallthru */
-			case PGP_PKT_SECRET_SUBKEY:
-				if (tag == PGP_PKT_SECRET_SUBKEY)
-					n_subkey++;
+				got_main_key = 1;
+				res = pgp_skip_packet(pkt);
+				break;
 
-				if (n_subkey > 1)
-					res = PXE_PGP_MULTIPLE_SUBKEYS;
-				else if (pubtype == 1)
-					res = process_secret_key(pkt, pk, key, key_len);
+			case PGP_PKT_PUBLIC_SUBKEY:
+				if (pubtype != 0)
+					res = PXE_PGP_EXPECT_SECRET_KEY;
 				else
-					res = PXE_PGP_EXPECT_PUBLIC_KEY;
+					res = _pgp_read_public_key(pkt, &pk);
 				break;
-			case PGP_PKT_PUBLIC_KEY:
-				if (got_key)
-				{
-					res = PXE_PGP_MULTIPLE_KEYS;
-					break;
-				}
-				got_key = 1;
-				n_subkey = 0;
-				/* fallthru */
-			case PGP_PKT_PUBLIC_SUBKEY:
-				if (tag == PGP_PKT_PUBLIC_SUBKEY)
-					n_subkey++;
 
-				if (n_subkey > 1)
-					res = PXE_PGP_MULTIPLE_SUBKEYS;
-				else if (pubtype == 0)
-					res = _pgp_read_public_key(pkt, pk);
+			case PGP_PKT_SECRET_SUBKEY:
+				if (pubtype != 1)
+					res = PXE_PGP_EXPECT_PUBLIC_KEY;
 				else
-					res = PXE_PGP_EXPECT_SECRET_KEY;
+					res = process_secret_key(pkt, &pk, psw, psw_len);
 				break;
+
 			case PGP_PKT_SIGNATURE:
 			case PGP_PKT_MARKER:
 			case PGP_PKT_TRUST:
@@ -401,10 +491,25 @@ internal_read_key(PullFilter *src, PGP_PubKey **pk_p,
 		pullf_free(pkt);
 	   	pkt = NULL;
 
-		if (res < 0)
-			break;
+		if (pk != NULL)
+		{
+			if (res >= 0 && pk->can_encrypt)
+			{
+				if (enc_key == NULL)
+				{
+					enc_key = pk;
+					pk = NULL;
+				}
+				else
+					res = PXE_PGP_MULTIPLE_SUBKEYS;
+			}
+
+			if (pk)
+				pgp_key_free(pk);
+			pk = NULL;
+		}
 
-		if (pk->algo == PGP_PUB_ELG_ENCRYPT)
+		if (res < 0)
 			break;
 	}
 
@@ -412,17 +517,17 @@ internal_read_key(PullFilter *src, PGP_PubKey **pk_p,
 		pullf_free(pkt);
 
 	if (res < 0)
-		pgp_key_free(pk);
-	else {
-		if (pk->algo == PGP_PUB_ELG_ENCRYPT)
-			*pk_p = pk;
-		else {
-			pgp_key_free(pk);
-			px_debug("non-elg");
-			res = PXE_PGP_NO_USABLE_KEY;
-		}
+	{
+		if (enc_key)
+			pgp_key_free(enc_key);
+		return res;
 	}
-	return res < 0 ? res : 0;
+
+	if (!enc_key)
+		res = PXE_PGP_NO_USABLE_KEY;
+	else
+		*pk_p = enc_key;
+	return res;
 }
 
 int
diff --git a/contrib/pgcrypto/pgp.h b/contrib/pgcrypto/pgp.h
index 93a06d46f222e1cf396f43fb97eac412fe9e2aaa..769a248d18ed1512e9ac533f3fb162bdf3c1d8d9 100644
--- a/contrib/pgcrypto/pgp.h
+++ b/contrib/pgcrypto/pgp.h
@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $PostgreSQL: pgsql/contrib/pgcrypto/pgp.h,v 1.2 2005/07/18 17:09:01 tgl Exp $
+ * $PostgreSQL: pgsql/contrib/pgcrypto/pgp.h,v 1.3 2005/08/13 02:06:20 momjian Exp $
  */
 
 enum
@@ -173,14 +173,44 @@ struct PGP_PubKey {
 	uint8 ver;
 	uint8 time[4];
 	uint8 algo;
-	/* public */
-	PGP_MPI *elg_p;
-	PGP_MPI *elg_g;
-	PGP_MPI *elg_y;
-	/* secret */
-	PGP_MPI *elg_x;
+
+	/* public part */
+	union {
+		struct {
+			PGP_MPI *p;
+			PGP_MPI *g;
+			PGP_MPI *y;
+		} elg;
+		struct {
+			PGP_MPI *n;
+			PGP_MPI *e;
+		} rsa;
+		struct {
+			PGP_MPI *p;
+			PGP_MPI *q;
+			PGP_MPI *g;
+			PGP_MPI *y;
+		} dsa;
+	} pub;
+
+	/* secret part */
+	union {
+		struct {
+			PGP_MPI *x;
+		} elg;
+		struct {
+			PGP_MPI *d;
+			PGP_MPI *p;
+			PGP_MPI *q;
+			PGP_MPI *u;
+		} rsa;
+		struct {
+			PGP_MPI *x;
+		} dsa;
+	} sec;
 
 	uint8 key_id[8];
+	int can_encrypt;
 };
 
 int			pgp_init(PGP_Context ** ctx);
@@ -240,7 +270,7 @@ int pgp_decompress_filter(PullFilter **res, PGP_Context *ctx, PullFilter *src);
 
 int pgp_key_alloc(PGP_PubKey **pk_p);
 void pgp_key_free(PGP_PubKey *pk);
-int _pgp_read_public_key(PullFilter *pkt, PGP_PubKey *pk);
+int _pgp_read_public_key(PullFilter *pkt, PGP_PubKey **pk_p);
 
 int pgp_parse_pubenc_sesskey(PGP_Context *ctx, PullFilter *pkt);
 int pgp_create_pkt_reader(PullFilter **pf_p, PullFilter *src, int len,
@@ -266,6 +296,8 @@ int pgp_elgamal_encrypt(PGP_PubKey *pk, PGP_MPI *m,
 						PGP_MPI **c1, PGP_MPI **c2);
 int pgp_elgamal_decrypt(PGP_PubKey *pk, PGP_MPI *c1, PGP_MPI *c2,
 						PGP_MPI **m);
+int pgp_rsa_encrypt(PGP_PubKey *pk, PGP_MPI *m, PGP_MPI **c);
+int pgp_rsa_decrypt(PGP_PubKey *pk, PGP_MPI *c, PGP_MPI **m);
 
 extern struct PullFilterOps pgp_decrypt_filter;
 
diff --git a/contrib/pgcrypto/px-crypt.c b/contrib/pgcrypto/px-crypt.c
index 82b7deb87003c36c7c113b3c2a0c41770ff1de69..c934f306059a14c5f39fea514e6a5210830d9c49 100644
--- a/contrib/pgcrypto/px-crypt.c
+++ b/contrib/pgcrypto/px-crypt.c
@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $PostgreSQL: pgsql/contrib/pgcrypto/px-crypt.c,v 1.12 2005/07/11 15:07:59 tgl Exp $
+ * $PostgreSQL: pgsql/contrib/pgcrypto/px-crypt.c,v 1.13 2005/08/13 02:06:20 momjian Exp $
  */
 
 #include "postgres.h"
@@ -35,8 +35,6 @@
 #include "px-crypt.h"
 
 
-#ifndef PX_SYSTEM_CRYPT
-
 static char *
 run_crypt_des(const char *psw, const char *salt,
 			  char *buf, unsigned len)
@@ -107,24 +105,6 @@ px_crypt(const char *psw, const char *salt, char *buf, unsigned len)
 	return c->crypt(psw, salt, buf, len);
 }
 
-#else							/* PX_SYSTEM_CRYPT */
-
-extern char *crypt(const char *psw, const char *salt);
-
-char *
-px_crypt(const char *psw, const char *salt,
-		 char *buf, unsigned len)
-{
-	char	   *res;
-
-	res = crypt(psw, salt);
-	if (!res || strlen(res) >= len)
-		return NULL;
-	strcpy(buf, res);
-	return buf;
-}
-#endif
-
 /*
  * salt generators
  */
diff --git a/contrib/pgcrypto/px-crypt.h b/contrib/pgcrypto/px-crypt.h
index 98a5647b8274d4acc1afb639195451f7c50bade2..94f5232ec25fcc9fdb34eda63279b9c27932ef75 100644
--- a/contrib/pgcrypto/px-crypt.h
+++ b/contrib/pgcrypto/px-crypt.h
@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $PostgreSQL: pgsql/contrib/pgcrypto/px-crypt.h,v 1.7 2005/03/21 05:19:55 neilc Exp $
+ * $PostgreSQL: pgsql/contrib/pgcrypto/px-crypt.h,v 1.8 2005/08/13 02:06:20 momjian Exp $
  */
 
 #ifndef _PX_CRYPT_H
@@ -73,8 +73,6 @@ char *_crypt_gensalt_md5_rn(unsigned long count,
 char *_crypt_gensalt_blowfish_rn(unsigned long count,
 			 const char *input, int size, char *output, int output_size);
 
-#ifndef PX_SYSTEM_CRYPT
-
 /* disable 'extended DES crypt' */
 /* #define DISABLE_XDES */
 
@@ -88,6 +86,5 @@ char	   *px_crypt_des(const char *key, const char *setting);
 /* crypt-md5.c */
 char *px_crypt_md5(const char *pw, const char *salt,
 			 char *dst, unsigned dstlen);
-#endif   /* !PX_SYSTEM_CRYPT */
 
 #endif   /* _PX_CRYPT_H */
diff --git a/contrib/pgcrypto/px.c b/contrib/pgcrypto/px.c
index 74b006688b545c8bb2ee9884cd1b5fb982ab71ff..2b1fd2fe580db0e0297a628528f3dea1bab9aab4 100644
--- a/contrib/pgcrypto/px.c
+++ b/contrib/pgcrypto/px.c
@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $PostgreSQL: pgsql/contrib/pgcrypto/px.c,v 1.13 2005/07/11 15:07:59 tgl Exp $
+ * $PostgreSQL: pgsql/contrib/pgcrypto/px.c,v 1.14 2005/08/13 02:06:20 momjian Exp $
  */
 
 #include "postgres.h"
@@ -72,14 +72,14 @@ static const struct error_desc px_err_list[] = {
 	{PXE_PGP_SHORT_ELGAMAL_KEY, "Elgamal keys must be at least 1024 bits long"},
 	{PXE_PGP_RSA_UNSUPPORTED, "pgcrypto does not support RSA keys"},
 	{PXE_PGP_UNKNOWN_PUBALGO, "Unknown public-key encryption algorithm"},
-	{PXE_PGP_WRONG_KEYID, "Data is not encrypted with this key"},
+	{PXE_PGP_WRONG_KEY, "Wrong key"},
 	{PXE_PGP_MULTIPLE_KEYS,
 		"Several keys given - pgcrypto does not handle keyring"},
 	{PXE_PGP_EXPECT_PUBLIC_KEY, "Refusing to encrypt with secret key"},
 	{PXE_PGP_EXPECT_SECRET_KEY, "Cannot decrypt with public key"},
 	{PXE_PGP_NOT_V4_KEYPKT, "Only V4 key packets are supported"},
 	{PXE_PGP_KEYPKT_CORRUPT, "Corrupt key packet"},
-	{PXE_PGP_NO_USABLE_KEY, "No usable key found (expecting Elgamal key)"},
+	{PXE_PGP_NO_USABLE_KEY, "No encryption key found"},
 	{PXE_PGP_NEED_SECRET_PSW, "Need password for secret key"},
 	{PXE_PGP_BAD_S2K_MODE, "Bad S2K mode"},
 	{PXE_PGP_UNSUPPORTED_PUBALGO, "Unsupported public key algorithm"},
diff --git a/contrib/pgcrypto/px.h b/contrib/pgcrypto/px.h
index bf45705c5daef814411f7e6511faea755fa0f633..a58b51e711916f819c8edc05ff030cb6adb90132 100644
--- a/contrib/pgcrypto/px.h
+++ b/contrib/pgcrypto/px.h
@@ -26,7 +26,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $PostgreSQL: pgsql/contrib/pgcrypto/px.h,v 1.14 2005/07/10 03:57:55 momjian Exp $
+ * $PostgreSQL: pgsql/contrib/pgcrypto/px.h,v 1.15 2005/08/13 02:06:20 momjian Exp $
  */
 
 #ifndef __PX_H
@@ -101,7 +101,7 @@ void		px_free(void *p);
 #define PXE_PGP_SHORT_ELGAMAL_KEY	-110
 #define PXE_PGP_RSA_UNSUPPORTED		-111
 #define PXE_PGP_UNKNOWN_PUBALGO		-112
-#define PXE_PGP_WRONG_KEYID			-113
+#define PXE_PGP_WRONG_KEY			-113
 #define PXE_PGP_MULTIPLE_KEYS		-114
 #define PXE_PGP_EXPECT_PUBLIC_KEY	-115
 #define PXE_PGP_EXPECT_SECRET_KEY	-116
diff --git a/contrib/pgcrypto/sql/pgp-info.sql b/contrib/pgcrypto/sql/pgp-info.sql
index d979bb93d97e2862cb45ae35e5f0724484513050..c525ce307e908576263b6a2ab8761629f073a460 100644
--- a/contrib/pgcrypto/sql/pgp-info.sql
+++ b/contrib/pgcrypto/sql/pgp-info.sql
@@ -9,12 +9,14 @@ select pgp_key_id(dearmor(pubkey)) from keytbl where id=2;
 select pgp_key_id(dearmor(pubkey)) from keytbl where id=3;
 select pgp_key_id(dearmor(pubkey)) from keytbl where id=4; -- should fail
 select pgp_key_id(dearmor(pubkey)) from keytbl where id=5;
+select pgp_key_id(dearmor(pubkey)) from keytbl where id=6;
 
 select pgp_key_id(dearmor(seckey)) from keytbl where id=1;
 select pgp_key_id(dearmor(seckey)) from keytbl where id=2;
 select pgp_key_id(dearmor(seckey)) from keytbl where id=3;
 select pgp_key_id(dearmor(seckey)) from keytbl where id=4; -- should fail
 select pgp_key_id(dearmor(seckey)) from keytbl where id=5;
+select pgp_key_id(dearmor(seckey)) from keytbl where id=6;
 
 select pgp_key_id(dearmor(data)) as data_key_id
 from encdata order by id;
diff --git a/contrib/pgcrypto/sql/pgp-pubkey-decrypt.sql b/contrib/pgcrypto/sql/pgp-pubkey-decrypt.sql
index 13fe090c6749d5fe4cbac1638a93bb4265cb8b07..82c6086ce582534fba49373b3f6a79653be9268c 100644
--- a/contrib/pgcrypto/sql/pgp-pubkey-decrypt.sql
+++ b/contrib/pgcrypto/sql/pgp-pubkey-decrypt.sql
@@ -334,6 +334,98 @@ saCh6QCfR1O48O8nYN93SPSfIFZK5rEmdv8=
 -----END PGP PRIVATE KEY BLOCK-----
 ');
 
+insert into keytbl (id, name, pubkey, seckey)
+values (6, 'rsaenc2048', '
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1.4.1 (GNU/Linux)
+
+mQELBELr2m0BCADOrnknlnXI0EzRExf/TgoHvK7Xx/E0keWqV3KrOyC3/tY2KOrj
+UVxaAX5pkFX9wdQObGPIJm06u6D16CH6CildX/vxG7YgvvKzK8JGAbwrXAfk7OIW
+czO2zRaZGDynoK3mAxHRBReyTKtNv8rDQhuZs6AOozJNARdbyUO/yqUnqNNygWuT
+4htFDEuLPIJwAbMSD0BvFW6YQaPdxzaAZm3EWVNbwDzjgbBUdBiUUwRdZIFUhsjJ
+dirFdy5+uuZru6y6CNC1OERkJ7P8EyoFiZckAIE5gshVZzNuyLOZjc5DhWBvLbX4
+NZElAnfiv+4nA6y8wQLSIbmHA3nqJaBklj85AAYptCVSU0EgMjA0OCBFbmMgPHJz
+YTIwNDhlbmNAZXhhbXBsZS5vcmc+iQE0BBMBAgAeBQJC69ptAhsDBgsJCAcDAgMV
+AgMDFgIBAh4BAheAAAoJEMiZ6pNEGVVZHMkIAJtGHHZ9iM8Yq1rr0zl1L6SvlQP8
+JCaxHa31wH3PKqGtq2M+cpb2rXf7gAY/doHJPXggfVzkyFrysmQ1gPbDGYLyOutw
++IkhihEb5bWxQBNj+3zAFs1YX6v2HXWbSUSmyY1V9/+NTtKk03olDc/swd3lXzku
+UOhcgfpBgIt3Q+MpT6M2+OIF7lVfSb1rWdpwTfGhZzW9szQOeoS4gPvxCCRyuabQ
+RJ6DWH61F8fFIDJg1z+A/Obx4fqX6GOA69RzgZ3oukFBIXxNwV9PZNnAmHtZVYO8
+0g/oVYBbuvOYedffDBeQarhERZ5W2TnIE+nqY61YOLBqosliygdZTXULzNi5AQsE
+QuvaugEIAOuCJZdkzORA6e1lr81Lnr4JzMsVBFA+X/yIkBbV6qX/A4nVSLAZKNPX
+z1YIrMTu+1rMIiy10IWbA6zgMTpzPhJRfgePONgdnCYyK5Ksh5/C5ntzKwwGwxfK
+lAXIxJurCHXTbEa+YvPdn76vJ3HsXOXVEL+fLb4U3l3Ng87YM202Lh1Ha2MeS2zE
+FZcAoKbFqAAjDLEai64SoOFh0W3CsD1DL4zmfp+YZrUPHTtZadsi53i4KKW/ws9U
+rHlolqYNhYze/uRLyfnUx9PN4r/GhEzauyDMV0smo91uB3aewPft+eCpmeWnu0PF
+JVK4xyRmhIq2rVCw16a1pBJirvGM+y0ABimJAR8EGAECAAkFAkLr2roCGwwACgkQ
+yJnqk0QZVVku1wgAg1bLSjPkhw+ldG5HzumpqR84+JKyozdJaJzefu2+1iqYE0B0
+WLz2PJVIiK41xiEkKhBvTOQYuXmtWqAWXptD91P5SoXoNJWLQO3TNwarANhHxkWg
+w/TOUxQqoctlRUej5NDD+4eW5G9lcS1FEGuKDWtX096u80vO+TbyJjvx2eVM1k+X
+dmeYsGOiNgDimCreJGYc14G7eY9jt24gw10n1sMAKI1qm6lcoHqZ9OOyla+wJdro
+PYZGO7R8+1O9R22WrK6BYDT5j/1JwMZqbOESjNvDEVT0yOHClCHRN4CChbt6LhKh
+CLUNdz/udIt0JAC6c/HdPLSW3HnmM3+iNj+Kug==
+=pwU2
+-----END PGP PUBLIC KEY BLOCK-----
+', '
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+Version: GnuPG v1.4.1 (GNU/Linux)
+
+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
+=UKh3
+-----END PGP PRIVATE KEY BLOCK-----
+');
+
 
 -- elg1024 / aes128
 insert into encdata (id, data) values (1, '
@@ -405,6 +497,23 @@ DYKcOy60/OHMWVvpw6trAoA+iP+cVWPtrbRvLglTVTfYmi1ToZDDipkALBhndQ==
 -----END PGP MESSAGE-----
 ');
 
+-- rsaenc2048 / aes128
+insert into encdata (id, data) values (4, '
+-----BEGIN PGP MESSAGE-----
+Version: GnuPG v1.4.1 (GNU/Linux)
+
+hQEMA/0CBsQJt0h1AQf+JyYnCiortj26P11zk28MKOGfWpWyAhuIgwbJXsdQ+e6r
+pEyyqs9GC6gI7SNF6+J8B/gsMwvkAL4FHAQCvA4ZZ6eeXR1Of4YG22JQGmpWVWZg
+DTyfhA2vkczuqfAD2tgUpMT6sdyGkQ/fnQ0lknlfHgC5GRx7aavOoAKtMqiZW5PR
+yae/qR48mjX7Mb+mLvbagv9mHEgQSmHwFpaq2k456BbcZ23bvCmBnCvqV/90Ggfb
+VP6gkSoFVsJ19RHsOhW1dk9ehbl51WB3zUOO5FZWwUTY9DJvKblRK/frF0+CXjE4
+HfcZXHSpSjx4haGGTsMvEJ85qFjZpr0eTGOdY5cFhNJAAVP8MZfji7OhPRAoOOIK
+eRGOCkao12pvPyFTFnPd5vqmyBbdNpK4Q0hS82ljugMJvM0p3vJZVzW402Kz6iBL
+GQ==
+=XHkF
+-----END PGP MESSAGE-----
+');
+
 -- successful decrypt
 select pgp_pub_decrypt(dearmor(data), dearmor(seckey))
 from keytbl, encdata where keytbl.id=1 and encdata.id=1;
@@ -415,6 +524,9 @@ from keytbl, encdata where keytbl.id=2 and encdata.id=2;
 select pgp_pub_decrypt(dearmor(data), dearmor(seckey))
 from keytbl, encdata where keytbl.id=3 and encdata.id=3;
 
+select pgp_pub_decrypt(dearmor(data), dearmor(seckey))
+from keytbl, encdata where keytbl.id=6 and encdata.id=4;
+
 -- wrong key
 select pgp_pub_decrypt(dearmor(data), dearmor(seckey))
 from keytbl, encdata where keytbl.id=2 and encdata.id=1;
diff --git a/contrib/pgcrypto/sql/pgp-pubkey-encrypt.sql b/contrib/pgcrypto/sql/pgp-pubkey-encrypt.sql
index 89d05a7a36488d6119643d0809a764ad89a46852..62dd487c10ff70afa52a2bc5072911be058e402b 100644
--- a/contrib/pgcrypto/sql/pgp-pubkey-encrypt.sql
+++ b/contrib/pgcrypto/sql/pgp-pubkey-encrypt.sql
@@ -18,6 +18,11 @@ select pgp_pub_decrypt(
 		dearmor(seckey))
 from keytbl where keytbl.id=3;
 
+select pgp_pub_decrypt(
+		pgp_pub_encrypt('Secret msg', dearmor(pubkey)),
+		dearmor(seckey))
+from keytbl where keytbl.id=6;
+
 -- try with rsa-sign only
 select pgp_pub_decrypt(
 		pgp_pub_encrypt('Secret msg', dearmor(pubkey)),