Thread: [patch 5/7] support for RSA, pubkey reorg

[patch 5/7] support for RSA, pubkey reorg

From
Marko Kreen
Date:
o  Support for RSA encryption
o  Big reorg to better separate generic and algorithm-specific code.
o  Regression tests for RSA.


Index: pgsql/contrib/pgcrypto/pgp-mpi-openssl.c
===================================================================
*** pgsql.orig/contrib/pgcrypto/pgp-mpi-openssl.c
--- pgsql/contrib/pgcrypto/pgp-mpi-openssl.c
*************** pgp_elgamal_encrypt(PGP_PubKey *pk, PGP_
*** 104,112 ****
      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 *k = BN_new();
      BIGNUM *yk = BN_new();
      BIGNUM *c1 = BN_new();
--- 104,112 ----
      int res = PXE_PGP_MATH_FAILED;
      int k_bits;
      BIGNUM *m = mpi_to_bn(_m);
!     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();
*************** pgp_elgamal_decrypt(PGP_PubKey *pk, PGP_
*** 159,166 ****
      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 *c1x = BN_new();
      BIGNUM *div = BN_new();
      BIGNUM *m = BN_new();
--- 159,166 ----
      int res = PXE_PGP_MATH_FAILED;
      BIGNUM *c1 = mpi_to_bn(_c1);
      BIGNUM *c2 = mpi_to_bn(_c2);
!     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();
*************** err:
*** 195,197 ****
--- 195,259 ----
      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;
+ }
+
Index: pgsql/contrib/pgcrypto/pgp-pubdec.c
===================================================================
*** pgsql.orig/contrib/pgcrypto/pgp-pubdec.c
--- pgsql/contrib/pgcrypto/pgp-pubdec.c
*************** control_cksum(uint8 *msg, int msglen)
*** 91,96 ****
--- 91,145 ----
      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};
*************** pgp_parse_pubenc_sesskey(PGP_Context *ct
*** 102,108 ****
      int algo;
      int res;
      uint8 key_id[8];
-     PGP_MPI *c1, *c2;
      PGP_PubKey *pk;
      uint8 *msg;
      int msglen;
--- 151,156 ----
*************** pgp_parse_pubenc_sesskey(PGP_Context *ct
*** 113,123 ****
          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);
--- 161,167 ----
          px_debug("no pubkey?");
          return PXE_BUG;
      }
!
      GETBYTE(pkt, ver);
      if (ver != 3) {
          px_debug("unknown pubenc_sesskey pkt ver=%d", ver);
*************** pgp_parse_pubenc_sesskey(PGP_Context *ct
*** 137,166 ****
          return PXE_PGP_WRONG_KEY;
      }

      GETBYTE(pkt, algo);
!     if (algo != PGP_PUB_ELG_ENCRYPT)
      {
!         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;
      }
-
-     /*
-      * 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;

--- 181,202 ----
          return PXE_PGP_WRONG_KEY;
      }

+     /*
+      * Decrypt
+      */
      GETBYTE(pkt, algo);
!     switch (algo)
      {
!         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;
      }
      if (res < 0)
          return res;

*************** pgp_parse_pubenc_sesskey(PGP_Context *ct
*** 170,182 ****
      msg = check_eme_pkcs1_v15(m->data, m->bytes);
      if (msg == NULL) {
          px_debug("check_eme_pkcs1_v15 failed");
!         return PXE_PGP_WRONG_KEY;
      }
      msglen = m->bytes - (msg - m->data);

      res = control_cksum(msg, msglen);
      if (res < 0)
!         return res;

      /*
       * got sesskey
--- 206,219 ----
      msg = check_eme_pkcs1_v15(m->data, m->bytes);
      if (msg == NULL) {
          px_debug("check_eme_pkcs1_v15 failed");
!         res = PXE_PGP_WRONG_KEY;
!         goto out;
      }
      msglen = m->bytes - (msg - m->data);

      res = control_cksum(msg, msglen);
      if (res < 0)
!         goto out;

      /*
       * got sesskey
*************** pgp_parse_pubenc_sesskey(PGP_Context *ct
*** 185,190 ****
--- 222,231 ----
      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);
  }

Index: pgsql/contrib/pgcrypto/pgp-pubenc.c
===================================================================
*** pgsql.orig/contrib/pgcrypto/pgp-pubenc.c
--- pgsql/contrib/pgcrypto/pgp-pubenc.c
*************** pad_eme_pkcs1_v15(uint8 *data, int data_
*** 84,122 ****
      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)
  {
      uint8 *secmsg;
!     int res, i, full_bytes;
      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];
--- 84,99 ----
      return 0;
  }

  static int
! create_secmsg(PGP_Context *ctx, PGP_MPI **msg_p, int full_bytes)
  {
      uint8 *secmsg;
!     int res, i;
      unsigned cksum = 0;
      int klen = ctx->sess_key_len;
      uint8 *padded = NULL;
      PGP_MPI *m = NULL;

      /* calc checksum */
      for (i = 0; i < klen; i++)
          cksum += ctx->sess_key[i];
*************** create_secmsg(PGP_Context *ctx, PGP_MPI
*** 133,139 ****
      /*
       * 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)
      {
--- 110,115 ----
*************** create_secmsg(PGP_Context *ctx, PGP_MPI
*** 156,192 ****
      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;

      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
--- 132,203 ----
      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;
      uint8 ver = 3;
      PushFilter *pkt = NULL;
+     uint8 algo = pk->algo;

      if (pk == NULL) {
          px_debug("no pubkey?\n");
          return PXE_BUG;
      }

      /*
       * now write packet
*************** int pgp_write_pubenc_sesskey(PGP_Context
*** 203,212 ****
      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);
      if (res < 0)
          goto err;

--- 214,230 ----
      res = pushf_write(pkt, &algo, 1);
      if (res < 0)
          goto err;
!
!     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;

*************** int pgp_write_pubenc_sesskey(PGP_Context
*** 217,228 ****
  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;
  }
--- 235,240 ----
Index: pgsql/contrib/pgcrypto/pgp-pubkey.c
===================================================================
*** pgsql.orig/contrib/pgcrypto/pgp-pubkey.c
--- pgsql/contrib/pgcrypto/pgp-pubkey.c
*************** int pgp_key_alloc(PGP_PubKey **pk_p)
*** 45,58 ****

  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);
      memset(pk, 0, sizeof(*pk));
      px_free(pk);
  }
--- 45,79 ----

  void pgp_key_free(PGP_PubKey *pk)
  {
!     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);
  }
*************** calc_key_id(PGP_PubKey *pk)
*** 74,82 ****
      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;
              break;
      }

--- 95,115 ----
      switch (pk->algo)
      {
          case PGP_PUB_ELG_ENCRYPT:
!             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;
      }

*************** calc_key_id(PGP_PubKey *pk)
*** 92,100 ****
      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);
              break;
      }

--- 125,145 ----
      switch (pk->algo)
      {
          case PGP_PUB_ELG_ENCRYPT:
!             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;
      }

*************** calc_key_id(PGP_PubKey *pk)
*** 107,153 ****
      return 0;
  }

! int _pgp_read_public_key(PullFilter *pkt, PGP_PubKey *pk)
  {
      int res;

      /* get version */
      GETBYTE(pkt, pk->ver);
      if (pk->ver != 4) {
!         px_debug("\tunsupported version: %d", pk->ver);
!         return PXE_PGP_NOT_V4_KEYPKT;
      }

      /* read time */
      res = pullf_read_fixed(pkt, 4, pk->time);
      if (res < 0)
!         return res;

      /* 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);
              break;
          case PGP_PUB_ELG_ENCRYPT:
!             res = pgp_mpi_read(pkt, &pk->elg_p);
              if (res < 0) break;
!             res = pgp_mpi_read(pkt, &pk->elg_g);
              if (res < 0) break;
!             res = pgp_mpi_read(pkt, &pk->elg_y);
              if (res < 0) break;

              res = calc_key_id(pk);
              break;
          default:
              px_debug("unknown public algo: %d", pk->algo);
              res = PXE_PGP_UNKNOWN_PUBALGO;
      }

      return res;
  }

--- 152,233 ----
      return 0;
  }

! 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) {
!         res = PXE_PGP_NOT_V4_KEYPKT;
!         goto out;
      }

      /* read time */
      res = pullf_read_fixed(pkt, 4, pk->time);
      if (res < 0)
!         goto out;

      /* pubkey algorithm */
      GETBYTE(pkt, pk->algo);

      switch (pk->algo) {
          case PGP_PUB_DSA_SIGN:
!             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->pub.elg.p);
              if (res < 0) break;
!             res = pgp_mpi_read(pkt, &pk->pub.elg.g);
              if (res < 0) break;
!             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;
  }

*************** check_key_sha1(PullFilter *src, PGP_PubK
*** 173,179 ****
      switch (pk->algo)
      {
          case PGP_PUB_ELG_ENCRYPT:
!             pgp_mpi_hash(md, pk->elg_x);
              break;
      }
      px_md_finish(md, my_sha1);
--- 253,270 ----
      switch (pk->algo)
      {
          case PGP_PUB_ELG_ENCRYPT:
!             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);
*************** check_key_cksum(PullFilter *src, PGP_Pub
*** 205,211 ****
      switch (pk->algo)
      {
          case PGP_PUB_ELG_ENCRYPT:
!             my_cksum = pgp_mpi_cksum(0, pk->elg_x);
              break;
      }
      if (my_cksum != got_cksum)
--- 296,313 ----
      switch (pk->algo)
      {
          case PGP_PUB_ELG_ENCRYPT:
!             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)
*************** check_key_cksum(PullFilter *src, PGP_Pub
*** 216,222 ****
      return 0;
  }

! static int process_secret_key(PullFilter *pkt, PGP_PubKey *pk,
          const uint8 *key, int key_len)
  {
      int res;
--- 318,324 ----
      return 0;
  }

! static int process_secret_key(PullFilter *pkt, PGP_PubKey **pk_p,
          const uint8 *key, int key_len)
  {
      int res;
*************** static int process_secret_key(PullFilter
*** 227,242 ****
      PullFilter *pf_decrypt = NULL, *pf_key;
      PGP_CFB *cfb = NULL;
      PGP_S2K s2k;

      /* first read public key part */
!     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?
       */
--- 329,341 ----
      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);
      if (res < 0)
          return res;

      /*
       * is secret key encrypted?
       */
*************** static int process_secret_key(PullFilter
*** 280,294 ****

      /* 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;
              break;
          case PGP_PUB_ELG_ENCRYPT:
!             res = pgp_mpi_read(pf_key, &pk->elg_x);
              break;
          default:
              px_debug("unknown public algo: %d", pk->algo);
--- 379,401 ----

      /* read secret key */
      switch (pk->algo) {
          case PGP_PUB_RSA_SIGN:
!         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->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);
*************** static int process_secret_key(PullFilter
*** 310,340 ****
      if (cfb)
          pgp_cfb_free(cfb);

      return res;
  }

  static int
  internal_read_key(PullFilter *src, PGP_PubKey **pk_p,
!                     const uint8 *key, int key_len, int pubtype)
  {
      PullFilter *pkt = NULL;
      int res;
      uint8 tag;
      int len;
      PGP_PubKey *pk = NULL;
!     int got_key = 0;
!     int n_subkey = 0;
!
!     res = pgp_key_alloc(&pk);
!     if (res < 0)
!         return res;

      /*
!      * Search for Elgamal 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)
--- 417,447 ----
      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 *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_main_key = 0;

      /*
!      * Search for encryption key.
       *
       * Error out on anything fancy.
       */
      while (1) {
          res = pgp_parse_pkt_hdr(src, &tag, &len, 0);
          if (res <= 0)
*************** internal_read_key(PullFilter *src, PGP_P
*** 344,389 ****
              break;

          switch (tag) {
              case PGP_PKT_SECRET_KEY:
!                 if (got_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++;

!                 if (n_subkey > 1)
!                     res = PXE_PGP_MULTIPLE_SUBKEYS;
!                 else if (pubtype == 1)
!                     res = process_secret_key(pkt, pk, key, key_len);
                  else
!                     res = PXE_PGP_EXPECT_PUBLIC_KEY;
                  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);
                  else
!                     res = PXE_PGP_EXPECT_SECRET_KEY;
                  break;
              case PGP_PKT_SIGNATURE:
              case PGP_PKT_MARKER:
              case PGP_PKT_TRUST:
--- 451,481 ----
              break;

          switch (tag) {
+             case PGP_PKT_PUBLIC_KEY:
              case PGP_PKT_SECRET_KEY:
!                 if (got_main_key)
                  {
                      res = PXE_PGP_MULTIPLE_KEYS;
                      break;
                  }
!                 got_main_key = 1;
!                 res = pgp_skip_packet(pkt);
!                 break;

!             case PGP_PKT_PUBLIC_SUBKEY:
!                 if (pubtype != 0)
!                     res = PXE_PGP_EXPECT_SECRET_KEY;
                  else
!                     res = _pgp_read_public_key(pkt, &pk);
                  break;

!             case PGP_PKT_SECRET_SUBKEY:
!                 if (pubtype != 1)
!                     res = PXE_PGP_EXPECT_PUBLIC_KEY;
                  else
!                     res = process_secret_key(pkt, &pk, psw, psw_len);
                  break;
+
              case PGP_PKT_SIGNATURE:
              case PGP_PKT_MARKER:
              case PGP_PKT_TRUST:
*************** internal_read_key(PullFilter *src, PGP_P
*** 399,408 ****
          pullf_free(pkt);
             pkt = NULL;

!         if (res < 0)
!             break;

!         if (pk->algo == PGP_PUB_ELG_ENCRYPT)
              break;
      }

--- 491,515 ----
          pullf_free(pkt);
             pkt = NULL;

!         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 (res < 0)
              break;
      }

*************** internal_read_key(PullFilter *src, PGP_P
*** 410,426 ****
          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;
!         }
      }
!     return res < 0 ? res : 0;
  }

  int
--- 517,533 ----
          pullf_free(pkt);

      if (res < 0)
!     {
!         if (enc_key)
!             pgp_key_free(enc_key);
!         return res;
      }
!
!     if (!enc_key)
!         res = PXE_PGP_NO_USABLE_KEY;
!     else
!         *pk_p = enc_key;
!     return res;
  }

  int
Index: pgsql/contrib/pgcrypto/pgp.h
===================================================================
*** pgsql.orig/contrib/pgcrypto/pgp.h
--- pgsql/contrib/pgcrypto/pgp.h
*************** struct PGP_PubKey {
*** 173,186 ****
      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;

      uint8 key_id[8];
  };

  int            pgp_init(PGP_Context ** ctx);
--- 173,216 ----
      uint8 ver;
      uint8 time[4];
      uint8 algo;
!
!     /* 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);
*************** int pgp_decompress_filter(PullFilter **r
*** 240,246 ****

  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_parse_pubenc_sesskey(PGP_Context *ctx, PullFilter *pkt);
  int pgp_create_pkt_reader(PullFilter **pf_p, PullFilter *src, int len,
--- 270,276 ----

  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_p);

  int pgp_parse_pubenc_sesskey(PGP_Context *ctx, PullFilter *pkt);
  int pgp_create_pkt_reader(PullFilter **pf_p, PullFilter *src, int len,
*************** int pgp_elgamal_encrypt(PGP_PubKey *pk,
*** 266,271 ****
--- 296,303 ----
                          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;

Index: pgsql/contrib/pgcrypto/pgp-mpi-internal.c
===================================================================
*** pgsql.orig/contrib/pgcrypto/pgp-mpi-internal.c
--- pgsql/contrib/pgcrypto/pgp-mpi-internal.c
*************** pgp_elgamal_decrypt(PGP_PubKey *pk, PGP_
*** 48,50 ****
--- 48,61 ----
      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;
+ }
+
+
Index: pgsql/contrib/pgcrypto/pgp-info.c
===================================================================
*** pgsql.orig/contrib/pgcrypto/pgp-info.c
--- pgsql/contrib/pgcrypto/pgp-info.c
***************
*** 36,61 ****

  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;

!     res = _pgp_read_public_key(pkt, pk);
      if (res < 0)
          goto err;
      res = pgp_skip_packet(pkt);
      if (res < 0)
          goto err;

!     res = 0;
!     if (pk->algo == PGP_PUB_ELG_ENCRYPT)
      {
!         memcpy(keyid_buf, pk->key_id, 8);
!         res = 1;
      }
  err:
      pgp_key_free(pk);
      return res;
--- 36,66 ----

  static int read_pubkey_keyid(PullFilter *pkt, uint8 *keyid_buf)
  {
!     int res;
!     PGP_PubKey *pk = NULL;

!     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;

!     /* is it encryption key */
!     switch (pk->algo)
      {
!         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;
*************** pgp_get_keyid(MBuf *pgp_data, char *dst)
*** 110,115 ****
--- 115,121 ----
      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);
*************** pgp_get_keyid(MBuf *pgp_data, char *dst)
*** 128,133 ****
--- 134,148 ----
          {
              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);
*************** pgp_get_keyid(MBuf *pgp_data, char *dst)
*** 142,147 ****
--- 157,163 ----
                  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:
*************** pgp_get_keyid(MBuf *pgp_data, char *dst)
*** 179,188 ****
          res = PXE_PGP_CORRUPT_DATA;

      if (got_pub_key > 1)
!         res = -1;

      if (got_pubenc_key > 1)
!         res = -1;

      /*
       * if still ok, look what we got
--- 195,204 ----
          res = PXE_PGP_CORRUPT_DATA;

      if (got_pub_key > 1)
!         res = PXE_PGP_MULTIPLE_KEYS;

      if (got_pubenc_key > 1)
!         res = PXE_PGP_MULTIPLE_KEYS;

      /*
       * if still ok, look what we got
Index: pgsql/contrib/pgcrypto/sql/pgp-pubkey-decrypt.sql
===================================================================
*** pgsql.orig/contrib/pgcrypto/sql/pgp-pubkey-decrypt.sql
--- pgsql/contrib/pgcrypto/sql/pgp-pubkey-decrypt.sql
*************** saCh6QCfR1O48O8nYN93SPSfIFZK5rEmdv8=
*** 334,339 ****
--- 334,431 ----
  -----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, '
*************** DYKcOy60/OHMWVvpw6trAoA+iP+cVWPtrbRvLglT
*** 405,410 ****
--- 497,519 ----
  -----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;
*************** from keytbl, encdata where keytbl.id=2 a
*** 415,420 ****
--- 524,532 ----
  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;
Index: pgsql/contrib/pgcrypto/sql/pgp-pubkey-encrypt.sql
===================================================================
*** pgsql.orig/contrib/pgcrypto/sql/pgp-pubkey-encrypt.sql
--- pgsql/contrib/pgcrypto/sql/pgp-pubkey-encrypt.sql
*************** select pgp_pub_decrypt(
*** 18,23 ****
--- 18,28 ----
          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)),
Index: pgsql/contrib/pgcrypto/sql/pgp-info.sql
===================================================================
*** pgsql.orig/contrib/pgcrypto/sql/pgp-info.sql
--- pgsql/contrib/pgcrypto/sql/pgp-info.sql
*************** select pgp_key_id(dearmor(pubkey)) from
*** 9,20 ****
--- 9,22 ----
  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;
Index: pgsql/contrib/pgcrypto/expected/pgp-info.out
===================================================================
*** pgsql.orig/contrib/pgcrypto/expected/pgp-info.out
--- pgsql/contrib/pgcrypto/expected/pgp-info.out
*************** select pgp_key_id(dearmor(pubkey)) from
*** 28,33 ****
--- 28,39 ----
   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
  ------------------
*************** select pgp_key_id(dearmor(seckey)) from
*** 54,59 ****
--- 60,71 ----
   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
*************** from encdata order by id;
*** 61,65 ****
   D936CF64BB73F466
   2C226E1FFE5CC7D4
   B68504FD128E1FF9
! (3 rows)

--- 73,78 ----
   D936CF64BB73F466
   2C226E1FFE5CC7D4
   B68504FD128E1FF9
!  FD0206C409B74875
! (4 rows)

Index: pgsql/contrib/pgcrypto/expected/pgp-pubkey-decrypt.out
===================================================================
*** pgsql.orig/contrib/pgcrypto/expected/pgp-pubkey-decrypt.out
--- pgsql/contrib/pgcrypto/expected/pgp-pubkey-decrypt.out
*************** saCh6QCfR1O48O8nYN93SPSfIFZK5rEmdv8=
*** 326,331 ****
--- 326,422 ----
  =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-----
*************** DYKcOy60/OHMWVvpw6trAoA+iP+cVWPtrbRvLglT
*** 393,398 ****
--- 484,505 ----
  =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;
*************** from keytbl, encdata where keytbl.id=3 a
*** 415,420 ****
--- 522,534 ----
   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;
Index: pgsql/contrib/pgcrypto/expected/pgp-pubkey-encrypt.out
===================================================================
*** pgsql.orig/contrib/pgcrypto/expected/pgp-pubkey-encrypt.out
--- pgsql/contrib/pgcrypto/expected/pgp-pubkey-encrypt.out
*************** from keytbl where keytbl.id=3;
*** 29,34 ****
--- 29,43 ----
   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)),

--