http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/801100ed/contrib/pgcrypto/pgp-mpi.c
----------------------------------------------------------------------
diff --git a/contrib/pgcrypto/pgp-mpi.c b/contrib/pgcrypto/pgp-mpi.c
new file mode 100644
index 0000000..c8765b6
--- /dev/null
+++ b/contrib/pgcrypto/pgp-mpi.c
@@ -0,0 +1,143 @@
+/*
+ * pgp-mpi.c
+ *       OpenPGP MPI helper functions.
+ *
+ * Copyright (c) 2005 Marko Kreen
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.     IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * contrib/pgcrypto/pgp-mpi.c
+ */
+#include "postgres.h"
+
+#include "px.h"
+#include "mbuf.h"
+#include "pgp.h"
+
+int
+pgp_mpi_alloc(int bits, PGP_MPI **mpi)
+{
+       PGP_MPI    *n;
+       int                     len = (bits + 7) / 8;
+
+       if (bits < 0 || bits > 0xFFFF)
+       {
+               px_debug("pgp_mpi_alloc: unreasonable request: bits=%d", bits);
+               return PXE_PGP_CORRUPT_DATA;
+       }
+       n = px_alloc(sizeof(*n) + len);
+       n->bits = bits;
+       n->bytes = len;
+       n->data = (uint8 *) (n) + sizeof(*n);
+       *mpi = n;
+       return 0;
+}
+
+int
+pgp_mpi_create(uint8 *data, int bits, PGP_MPI **mpi)
+{
+       int                     res;
+       PGP_MPI    *n;
+
+       res = pgp_mpi_alloc(bits, &n);
+       if (res < 0)
+               return res;
+       memcpy(n->data, data, n->bytes);
+       *mpi = n;
+       return 0;
+}
+
+int
+pgp_mpi_free(PGP_MPI *mpi)
+{
+       if (mpi == NULL)
+               return 0;
+       memset(mpi, 0, sizeof(*mpi) + mpi->bytes);
+       px_free(mpi);
+       return 0;
+}
+
+int
+pgp_mpi_read(PullFilter *src, PGP_MPI **mpi)
+{
+       int                     res;
+       uint8           hdr[2];
+       int                     bits;
+       PGP_MPI    *n;
+
+       res = pullf_read_fixed(src, 2, hdr);
+       if (res < 0)
+               return res;
+       bits = ((unsigned) hdr[0] << 8) + hdr[1];
+
+       res = pgp_mpi_alloc(bits, &n);
+       if (res < 0)
+               return res;
+
+       res = pullf_read_fixed(src, n->bytes, n->data);
+       if (res < 0)
+               pgp_mpi_free(n);
+       else
+               *mpi = n;
+       return res;
+}
+
+int
+pgp_mpi_write(PushFilter *dst, PGP_MPI *n)
+{
+       int                     res;
+       uint8           buf[2];
+
+       buf[0] = n->bits >> 8;
+       buf[1] = n->bits & 0xFF;
+       res = pushf_write(dst, buf, 2);
+       if (res >= 0)
+               res = pushf_write(dst, n->data, n->bytes);
+       return res;
+}
+
+int
+pgp_mpi_hash(PX_MD *md, PGP_MPI *n)
+{
+       uint8           buf[2];
+
+       buf[0] = n->bits >> 8;
+       buf[1] = n->bits & 0xFF;
+       px_md_update(md, buf, 2);
+       px_md_update(md, n->data, n->bytes);
+
+       return 0;
+}
+
+unsigned
+pgp_mpi_cksum(unsigned cksum, PGP_MPI *n)
+{
+       int                     i;
+
+       cksum += n->bits >> 8;
+       cksum += n->bits & 0xFF;
+       for (i = 0; i < n->bytes; i++)
+               cksum += n->data[i];
+
+       return cksum & 0xFFFF;
+}

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/801100ed/contrib/pgcrypto/pgp-pgsql.c
----------------------------------------------------------------------
diff --git a/contrib/pgcrypto/pgp-pgsql.c b/contrib/pgcrypto/pgp-pgsql.c
new file mode 100644
index 0000000..d4eec03
--- /dev/null
+++ b/contrib/pgcrypto/pgp-pgsql.c
@@ -0,0 +1,919 @@
+/*
+ * pgp-pgsql.c
+ *             PostgreSQL wrappers for pgp.
+ *
+ * Copyright (c) 2005 Marko Kreen
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.     IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * contrib/pgcrypto/pgp-pgsql.c
+ */
+
+#include "postgres.h"
+
+#include "mb/pg_wchar.h"
+#include "utils/builtins.h"
+
+#include "mbuf.h"
+#include "px.h"
+#include "pgp.h"
+
+/*
+ * public functions
+ */
+Datum          pgp_sym_encrypt_text(PG_FUNCTION_ARGS);
+Datum          pgp_sym_encrypt_bytea(PG_FUNCTION_ARGS);
+Datum          pgp_sym_decrypt_text(PG_FUNCTION_ARGS);
+Datum          pgp_sym_decrypt_bytea(PG_FUNCTION_ARGS);
+
+Datum          pgp_pub_encrypt_text(PG_FUNCTION_ARGS);
+Datum          pgp_pub_encrypt_bytea(PG_FUNCTION_ARGS);
+Datum          pgp_pub_decrypt_text(PG_FUNCTION_ARGS);
+Datum          pgp_pub_decrypt_bytea(PG_FUNCTION_ARGS);
+
+Datum          pgp_key_id_w(PG_FUNCTION_ARGS);
+
+Datum          pg_armor(PG_FUNCTION_ARGS);
+Datum          pg_dearmor(PG_FUNCTION_ARGS);
+
+/* function headers */
+
+PG_FUNCTION_INFO_V1(pgp_sym_encrypt_bytea);
+PG_FUNCTION_INFO_V1(pgp_sym_encrypt_text);
+PG_FUNCTION_INFO_V1(pgp_sym_decrypt_bytea);
+PG_FUNCTION_INFO_V1(pgp_sym_decrypt_text);
+
+PG_FUNCTION_INFO_V1(pgp_pub_encrypt_bytea);
+PG_FUNCTION_INFO_V1(pgp_pub_encrypt_text);
+PG_FUNCTION_INFO_V1(pgp_pub_decrypt_bytea);
+PG_FUNCTION_INFO_V1(pgp_pub_decrypt_text);
+
+PG_FUNCTION_INFO_V1(pgp_key_id_w);
+
+PG_FUNCTION_INFO_V1(pg_armor);
+PG_FUNCTION_INFO_V1(pg_dearmor);
+
+/*
+ * Mix a block of data into RNG.
+ */
+static void
+add_block_entropy(PX_MD *md, text *data)
+{
+       uint8           sha1[20];
+
+       px_md_reset(md);
+       px_md_update(md, (uint8 *) VARDATA(data), VARSIZE(data) - VARHDRSZ);
+       px_md_finish(md, sha1);
+
+       px_add_entropy(sha1, 20);
+
+       memset(sha1, 0, 20);
+}
+
+/*
+ * Mix user data into RNG.     It is for user own interests to have
+ * RNG state shuffled.
+ */
+static void
+add_entropy(text *data1, text *data2, text *data3)
+{
+       PX_MD      *md;
+       uint8           rnd[3];
+
+       if (!data1 && !data2 && !data3)
+               return;
+
+       if (px_get_random_bytes(rnd, 3) < 0)
+               return;
+
+       if (px_find_digest("sha1", &md) < 0)
+               return;
+
+       /*
+        * Try to make the feeding unpredictable.
+        *
+        * Prefer data over keys, as it's rather likely that key is same in
+        * several calls.
+        */
+
+       /* chance: 7/8 */
+       if (data1 && rnd[0] >= 32)
+               add_block_entropy(md, data1);
+
+       /* chance: 5/8 */
+       if (data2 && rnd[1] >= 160)
+               add_block_entropy(md, data2);
+
+       /* chance: 5/8 */
+       if (data3 && rnd[2] >= 160)
+               add_block_entropy(md, data3);
+
+       px_md_free(md);
+       memset(rnd, 0, sizeof(rnd));
+}
+
+/*
+ * returns src in case of no conversion or error
+ */
+static text *
+convert_charset(text *src, int cset_from, int cset_to)
+{
+       int                     src_len = VARSIZE(src) - VARHDRSZ;
+       unsigned char *dst;
+       unsigned char *csrc = (unsigned char *) VARDATA(src);
+       text       *res;
+
+       dst = pg_do_encoding_conversion(csrc, src_len, cset_from, cset_to);
+       if (dst == csrc)
+               return src;
+
+       res = cstring_to_text((char *) dst);
+       pfree(dst);
+       return res;
+}
+
+static text *
+convert_from_utf8(text *src)
+{
+       return convert_charset(src, PG_UTF8, GetDatabaseEncoding());
+}
+
+static text *
+convert_to_utf8(text *src)
+{
+       return convert_charset(src, GetDatabaseEncoding(), PG_UTF8);
+}
+
+static void
+clear_and_pfree(text *p)
+{
+       memset(p, 0, VARSIZE(p));
+       pfree(p);
+}
+
+/*
+ * expect-* arguments storage
+ */
+struct debug_expect
+{
+       int                     debug;
+       int                     expect;
+       int                     cipher_algo;
+       int                     s2k_mode;
+       int                     s2k_cipher_algo;
+       int                     s2k_digest_algo;
+       int                     compress_algo;
+       int                     use_sess_key;
+       int                     disable_mdc;
+       int                     unicode_mode;
+};
+
+static void
+fill_expect(struct debug_expect * ex, int text_mode)
+{
+       ex->debug = 0;
+       ex->expect = 0;
+       ex->cipher_algo = -1;
+       ex->s2k_mode = -1;
+       ex->s2k_cipher_algo = -1;
+       ex->s2k_digest_algo = -1;
+       ex->compress_algo = -1;
+       ex->use_sess_key = -1;
+       ex->disable_mdc = -1;
+       ex->unicode_mode = -1;
+}
+
+#define EX_MSG(arg) \
+       ereport(NOTICE, (errmsg( \
+               "pgp_decrypt: unexpected %s: expected %d got %d", \
+               CppAsString(arg), ex->arg, ctx->arg)))
+
+#define EX_CHECK(arg) do { \
+               if (ex->arg >= 0 && ex->arg != ctx->arg) EX_MSG(arg); \
+       } while (0)
+
+static void
+check_expect(PGP_Context *ctx, struct debug_expect * ex)
+{
+       EX_CHECK(cipher_algo);
+       EX_CHECK(s2k_mode);
+       EX_CHECK(s2k_digest_algo);
+       EX_CHECK(use_sess_key);
+       if (ctx->use_sess_key)
+               EX_CHECK(s2k_cipher_algo);
+       EX_CHECK(disable_mdc);
+       EX_CHECK(compress_algo);
+       EX_CHECK(unicode_mode);
+}
+
+static void
+show_debug(const char *msg)
+{
+       ereport(NOTICE, (errmsg("dbg: %s", msg)));
+}
+
+static int
+set_arg(PGP_Context *ctx, char *key, char *val,
+               struct debug_expect * ex)
+{
+       int                     res = 0;
+
+       if (strcmp(key, "cipher-algo") == 0)
+               res = pgp_set_cipher_algo(ctx, val);
+       else if (strcmp(key, "disable-mdc") == 0)
+               res = pgp_disable_mdc(ctx, atoi(val));
+       else if (strcmp(key, "sess-key") == 0)
+               res = pgp_set_sess_key(ctx, atoi(val));
+       else if (strcmp(key, "s2k-mode") == 0)
+               res = pgp_set_s2k_mode(ctx, atoi(val));
+       else if (strcmp(key, "s2k-digest-algo") == 0)
+               res = pgp_set_s2k_digest_algo(ctx, val);
+       else if (strcmp(key, "s2k-cipher-algo") == 0)
+               res = pgp_set_s2k_cipher_algo(ctx, val);
+       else if (strcmp(key, "compress-algo") == 0)
+               res = pgp_set_compress_algo(ctx, atoi(val));
+       else if (strcmp(key, "compress-level") == 0)
+               res = pgp_set_compress_level(ctx, atoi(val));
+       else if (strcmp(key, "convert-crlf") == 0)
+               res = pgp_set_convert_crlf(ctx, atoi(val));
+       else if (strcmp(key, "unicode-mode") == 0)
+               res = pgp_set_unicode_mode(ctx, atoi(val));
+       /* decrypt debug */
+       else if (ex != NULL && strcmp(key, "debug") == 0)
+               ex->debug = atoi(val);
+       else if (ex != NULL && strcmp(key, "expect-cipher-algo") == 0)
+       {
+               ex->expect = 1;
+               ex->cipher_algo = pgp_get_cipher_code(val);
+       }
+       else if (ex != NULL && strcmp(key, "expect-disable-mdc") == 0)
+       {
+               ex->expect = 1;
+               ex->disable_mdc = atoi(val);
+       }
+       else if (ex != NULL && strcmp(key, "expect-sess-key") == 0)
+       {
+               ex->expect = 1;
+               ex->use_sess_key = atoi(val);
+       }
+       else if (ex != NULL && strcmp(key, "expect-s2k-mode") == 0)
+       {
+               ex->expect = 1;
+               ex->s2k_mode = atoi(val);
+       }
+       else if (ex != NULL && strcmp(key, "expect-s2k-digest-algo") == 0)
+       {
+               ex->expect = 1;
+               ex->s2k_digest_algo = pgp_get_digest_code(val);
+       }
+       else if (ex != NULL && strcmp(key, "expect-s2k-cipher-algo") == 0)
+       {
+               ex->expect = 1;
+               ex->s2k_cipher_algo = pgp_get_cipher_code(val);
+       }
+       else if (ex != NULL && strcmp(key, "expect-compress-algo") == 0)
+       {
+               ex->expect = 1;
+               ex->compress_algo = atoi(val);
+       }
+       else if (ex != NULL && strcmp(key, "expect-unicode-mode") == 0)
+       {
+               ex->expect = 1;
+               ex->unicode_mode = atoi(val);
+       }
+       else
+               res = PXE_ARGUMENT_ERROR;
+
+       return res;
+}
+
+/*
+ * Find next word.     Handle ',' and '=' as words.  Skip whitespace.
+ * Put word info into res_p, res_len.
+ * Returns ptr to next word.
+ */
+static char *
+getword(char *p, char **res_p, int *res_len)
+{
+       /* whitespace at start */
+       while (*p && (*p == ' ' || *p == '\t' || *p == '\n'))
+               p++;
+
+       /* word data */
+       *res_p = p;
+       if (*p == '=' || *p == ',')
+               p++;
+       else
+               while (*p && !(*p == ' ' || *p == '\t' || *p == '\n'
+                                          || *p == '=' || *p == ','))
+                       p++;
+
+       /* word end */
+       *res_len = p - *res_p;
+
+       /* whitespace at end */
+       while (*p && (*p == ' ' || *p == '\t' || *p == '\n'))
+               p++;
+
+       return p;
+}
+
+/*
+ * Convert to lowercase asciiz string.
+ */
+static char *
+downcase_convert(const uint8 *s, int len)
+{
+       int                     c,
+                               i;
+       char       *res = palloc(len + 1);
+
+       for (i = 0; i < len; i++)
+       {
+               c = s[i];
+               if (c >= 'A' && c <= 'Z')
+                       c += 'a' - 'A';
+               res[i] = c;
+       }
+       res[len] = 0;
+       return res;
+}
+
+static int
+parse_args(PGP_Context *ctx, uint8 *args, int arg_len,
+                  struct debug_expect * ex)
+{
+       char       *str = downcase_convert(args, arg_len);
+       char       *key,
+                          *val;
+       int                     key_len,
+                               val_len;
+       int                     res = 0;
+       char       *p = str;
+
+       while (*p)
+       {
+               res = PXE_ARGUMENT_ERROR;
+               p = getword(p, &key, &key_len);
+               if (*p++ != '=')
+                       break;
+               p = getword(p, &val, &val_len);
+               if (*p == '\0')
+                       ;
+               else if (*p++ != ',')
+                       break;
+
+               if (*key == 0 || *val == 0 || val_len == 0)
+                       break;
+
+               key[key_len] = 0;
+               val[val_len] = 0;
+
+               res = set_arg(ctx, key, val, ex);
+               if (res < 0)
+                       break;
+       }
+       pfree(str);
+       return res;
+}
+
+static MBuf *
+create_mbuf_from_vardata(text *data)
+{
+       return mbuf_create_from_data((uint8 *) VARDATA(data),
+                                                                VARSIZE(data) 
- VARHDRSZ);
+}
+
+static void
+init_work(PGP_Context **ctx_p, int is_text,
+                 text *args, struct debug_expect * ex)
+{
+       int                     err = pgp_init(ctx_p);
+
+       fill_expect(ex, is_text);
+
+       if (err == 0 && args != NULL)
+               err = parse_args(*ctx_p, (uint8 *) VARDATA(args),
+                                                VARSIZE(args) - VARHDRSZ, ex);
+
+       if (err)
+       {
+               ereport(ERROR,
+                               
(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
+                                errmsg("%s", px_strerror(err))));
+       }
+
+       if (ex->debug)
+               px_set_debug_handler(show_debug);
+
+       pgp_set_text_mode(*ctx_p, is_text);
+}
+
+static bytea *
+encrypt_internal(int is_pubenc, int is_text,
+                                text *data, text *key, text *args)
+{
+       MBuf       *src,
+                          *dst;
+       uint8           tmp[VARHDRSZ];
+       uint8      *restmp;
+       bytea      *res;
+       int                     res_len;
+       PGP_Context *ctx;
+       int                     err;
+       struct debug_expect ex;
+       text       *tmp_data = NULL;
+
+       /*
+        * Add data and key info RNG.
+        */
+       add_entropy(data, key, NULL);
+
+       init_work(&ctx, is_text, args, &ex);
+
+       if (is_text && pgp_get_unicode_mode(ctx))
+       {
+               tmp_data = convert_to_utf8(data);
+               if (tmp_data == data)
+                       tmp_data = NULL;
+               else
+                       data = tmp_data;
+       }
+
+       src = create_mbuf_from_vardata(data);
+       dst = mbuf_create(VARSIZE(data) + 128);
+
+       /*
+        * reserve room for header
+        */
+       mbuf_append(dst, tmp, VARHDRSZ);
+
+       /*
+        * set key
+        */
+       if (is_pubenc)
+       {
+               MBuf       *kbuf = create_mbuf_from_vardata(key);
+
+               err = pgp_set_pubkey(ctx, kbuf,
+                                                        NULL, 0, 0);
+               mbuf_free(kbuf);
+       }
+       else
+               err = pgp_set_symkey(ctx, (uint8 *) VARDATA(key),
+                                                        VARSIZE(key) - 
VARHDRSZ);
+
+       /*
+        * encrypt
+        */
+       if (err >= 0)
+               err = pgp_encrypt(ctx, src, dst);
+
+       /*
+        * check for error
+        */
+       if (err)
+       {
+               if (ex.debug)
+                       px_set_debug_handler(NULL);
+               if (tmp_data)
+                       clear_and_pfree(tmp_data);
+               pgp_free(ctx);
+               mbuf_free(src);
+               mbuf_free(dst);
+               ereport(ERROR,
+                               
(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
+                                errmsg("%s", px_strerror(err))));
+       }
+
+       /* res_len includes VARHDRSZ */
+       res_len = mbuf_steal_data(dst, &restmp);
+       res = (bytea *) restmp;
+       SET_VARSIZE(res, res_len);
+
+       if (tmp_data)
+               clear_and_pfree(tmp_data);
+       pgp_free(ctx);
+       mbuf_free(src);
+       mbuf_free(dst);
+
+       px_set_debug_handler(NULL);
+
+       return res;
+}
+
+static bytea *
+decrypt_internal(int is_pubenc, int need_text, text *data,
+                                text *key, text *keypsw, text *args)
+{
+       int                     err;
+       MBuf       *src = NULL,
+                          *dst = NULL;
+       uint8           tmp[VARHDRSZ];
+       uint8      *restmp;
+       bytea      *res;
+       int                     res_len;
+       PGP_Context *ctx = NULL;
+       struct debug_expect ex;
+       int                     got_unicode = 0;
+
+
+       init_work(&ctx, need_text, args, &ex);
+
+       src = mbuf_create_from_data((uint8 *) VARDATA(data),
+                                                               VARSIZE(data) - 
VARHDRSZ);
+       dst = mbuf_create(VARSIZE(data) + 2048);
+
+       /*
+        * reserve room for header
+        */
+       mbuf_append(dst, tmp, VARHDRSZ);
+
+       /*
+        * set key
+        */
+       if (is_pubenc)
+       {
+               uint8      *psw = NULL;
+               int                     psw_len = 0;
+               MBuf       *kbuf;
+
+               if (keypsw)
+               {
+                       psw = (uint8 *) VARDATA(keypsw);
+                       psw_len = VARSIZE(keypsw) - VARHDRSZ;
+               }
+               kbuf = create_mbuf_from_vardata(key);
+               err = pgp_set_pubkey(ctx, kbuf, psw, psw_len, 1);
+               mbuf_free(kbuf);
+       }
+       else
+               err = pgp_set_symkey(ctx, (uint8 *) VARDATA(key),
+                                                        VARSIZE(key) - 
VARHDRSZ);
+
+       /*
+        * decrypt
+        */
+       if (err >= 0)
+               err = pgp_decrypt(ctx, src, dst);
+
+       /*
+        * failed?
+        */
+       if (err < 0)
+               goto out;
+
+       if (ex.expect)
+               check_expect(ctx, &ex);
+
+       /* remember the setting */
+       got_unicode = pgp_get_unicode_mode(ctx);
+
+out:
+       if (src)
+               mbuf_free(src);
+       if (ctx)
+               pgp_free(ctx);
+
+       if (err)
+       {
+               px_set_debug_handler(NULL);
+               if (dst)
+                       mbuf_free(dst);
+               ereport(ERROR,
+                               
(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
+                                errmsg("%s", px_strerror(err))));
+       }
+
+       res_len = mbuf_steal_data(dst, &restmp);
+       mbuf_free(dst);
+
+       /* res_len includes VARHDRSZ */
+       res = (bytea *) restmp;
+       SET_VARSIZE(res, res_len);
+
+       if (need_text && got_unicode)
+       {
+               text       *utf = convert_from_utf8(res);
+
+               if (utf != res)
+               {
+                       clear_and_pfree(res);
+                       res = utf;
+               }
+       }
+       px_set_debug_handler(NULL);
+
+       /*
+        * add successful decryptions also into RNG
+        */
+       add_entropy(res, key, keypsw);
+
+       return res;
+}
+
+/*
+ * Wrappers for symmetric-key functions
+ */
+Datum
+pgp_sym_encrypt_bytea(PG_FUNCTION_ARGS)
+{
+       bytea      *data,
+                          *key;
+       text       *arg = NULL;
+       text       *res;
+
+       data = PG_GETARG_BYTEA_P(0);
+       key = PG_GETARG_BYTEA_P(1);
+       if (PG_NARGS() > 2)
+               arg = PG_GETARG_BYTEA_P(2);
+
+       res = encrypt_internal(0, 0, data, key, arg);
+
+       PG_FREE_IF_COPY(data, 0);
+       PG_FREE_IF_COPY(key, 1);
+       if (PG_NARGS() > 2)
+               PG_FREE_IF_COPY(arg, 2);
+       PG_RETURN_TEXT_P(res);
+}
+
+Datum
+pgp_sym_encrypt_text(PG_FUNCTION_ARGS)
+{
+       bytea      *data,
+                          *key;
+       text       *arg = NULL;
+       text       *res;
+
+       data = PG_GETARG_BYTEA_P(0);
+       key = PG_GETARG_BYTEA_P(1);
+       if (PG_NARGS() > 2)
+               arg = PG_GETARG_BYTEA_P(2);
+
+       res = encrypt_internal(0, 1, data, key, arg);
+
+       PG_FREE_IF_COPY(data, 0);
+       PG_FREE_IF_COPY(key, 1);
+       if (PG_NARGS() > 2)
+               PG_FREE_IF_COPY(arg, 2);
+       PG_RETURN_TEXT_P(res);
+}
+
+
+Datum
+pgp_sym_decrypt_bytea(PG_FUNCTION_ARGS)
+{
+       bytea      *data,
+                          *key;
+       text       *arg = NULL;
+       text       *res;
+
+       data = PG_GETARG_BYTEA_P(0);
+       key = PG_GETARG_BYTEA_P(1);
+       if (PG_NARGS() > 2)
+               arg = PG_GETARG_BYTEA_P(2);
+
+       res = decrypt_internal(0, 0, data, key, NULL, arg);
+
+       PG_FREE_IF_COPY(data, 0);
+       PG_FREE_IF_COPY(key, 1);
+       if (PG_NARGS() > 2)
+               PG_FREE_IF_COPY(arg, 2);
+       PG_RETURN_TEXT_P(res);
+}
+
+Datum
+pgp_sym_decrypt_text(PG_FUNCTION_ARGS)
+{
+       bytea      *data,
+                          *key;
+       text       *arg = NULL;
+       text       *res;
+
+       data = PG_GETARG_BYTEA_P(0);
+       key = PG_GETARG_BYTEA_P(1);
+       if (PG_NARGS() > 2)
+               arg = PG_GETARG_BYTEA_P(2);
+
+       res = decrypt_internal(0, 1, data, key, NULL, arg);
+
+       PG_FREE_IF_COPY(data, 0);
+       PG_FREE_IF_COPY(key, 1);
+       if (PG_NARGS() > 2)
+               PG_FREE_IF_COPY(arg, 2);
+       PG_RETURN_TEXT_P(res);
+}
+
+/*
+ * Wrappers for public-key functions
+ */
+
+Datum
+pgp_pub_encrypt_bytea(PG_FUNCTION_ARGS)
+{
+       bytea      *data,
+                          *key;
+       text       *arg = NULL;
+       text       *res;
+
+       data = PG_GETARG_BYTEA_P(0);
+       key = PG_GETARG_BYTEA_P(1);
+       if (PG_NARGS() > 2)
+               arg = PG_GETARG_BYTEA_P(2);
+
+       res = encrypt_internal(1, 0, data, key, arg);
+
+       PG_FREE_IF_COPY(data, 0);
+       PG_FREE_IF_COPY(key, 1);
+       if (PG_NARGS() > 2)
+               PG_FREE_IF_COPY(arg, 2);
+       PG_RETURN_TEXT_P(res);
+}
+
+Datum
+pgp_pub_encrypt_text(PG_FUNCTION_ARGS)
+{
+       bytea      *data,
+                          *key;
+       text       *arg = NULL;
+       text       *res;
+
+       data = PG_GETARG_BYTEA_P(0);
+       key = PG_GETARG_BYTEA_P(1);
+       if (PG_NARGS() > 2)
+               arg = PG_GETARG_BYTEA_P(2);
+
+       res = encrypt_internal(1, 1, data, key, arg);
+
+       PG_FREE_IF_COPY(data, 0);
+       PG_FREE_IF_COPY(key, 1);
+       if (PG_NARGS() > 2)
+               PG_FREE_IF_COPY(arg, 2);
+       PG_RETURN_TEXT_P(res);
+}
+
+
+Datum
+pgp_pub_decrypt_bytea(PG_FUNCTION_ARGS)
+{
+       bytea      *data,
+                          *key;
+       text       *psw = NULL,
+                          *arg = NULL;
+       text       *res;
+
+       data = PG_GETARG_BYTEA_P(0);
+       key = PG_GETARG_BYTEA_P(1);
+       if (PG_NARGS() > 2)
+               psw = PG_GETARG_BYTEA_P(2);
+       if (PG_NARGS() > 3)
+               arg = PG_GETARG_BYTEA_P(3);
+
+       res = decrypt_internal(1, 0, data, key, psw, arg);
+
+       PG_FREE_IF_COPY(data, 0);
+       PG_FREE_IF_COPY(key, 1);
+       if (PG_NARGS() > 2)
+               PG_FREE_IF_COPY(psw, 2);
+       if (PG_NARGS() > 3)
+               PG_FREE_IF_COPY(arg, 3);
+       PG_RETURN_TEXT_P(res);
+}
+
+Datum
+pgp_pub_decrypt_text(PG_FUNCTION_ARGS)
+{
+       bytea      *data,
+                          *key;
+       text       *psw = NULL,
+                          *arg = NULL;
+       text       *res;
+
+       data = PG_GETARG_BYTEA_P(0);
+       key = PG_GETARG_BYTEA_P(1);
+       if (PG_NARGS() > 2)
+               psw = PG_GETARG_BYTEA_P(2);
+       if (PG_NARGS() > 3)
+               arg = PG_GETARG_BYTEA_P(3);
+
+       res = decrypt_internal(1, 1, data, key, psw, arg);
+
+       PG_FREE_IF_COPY(data, 0);
+       PG_FREE_IF_COPY(key, 1);
+       if (PG_NARGS() > 2)
+               PG_FREE_IF_COPY(psw, 2);
+       if (PG_NARGS() > 3)
+               PG_FREE_IF_COPY(arg, 3);
+       PG_RETURN_TEXT_P(res);
+}
+
+
+/*
+ * Wrappers for PGP ascii armor
+ */
+
+Datum
+pg_armor(PG_FUNCTION_ARGS)
+{
+       bytea      *data;
+       text       *res;
+       int                     data_len,
+                               res_len,
+                               guess_len;
+
+       data = PG_GETARG_BYTEA_P(0);
+       data_len = VARSIZE(data) - VARHDRSZ;
+
+       guess_len = pgp_armor_enc_len(data_len);
+       res = palloc(VARHDRSZ + guess_len);
+
+       res_len = pgp_armor_encode((uint8 *) VARDATA(data), data_len,
+                                                          (uint8 *) 
VARDATA(res));
+       if (res_len > guess_len)
+               ereport(ERROR,
+                               
(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
+                                errmsg("Overflow - encode estimate too 
small")));
+       SET_VARSIZE(res, VARHDRSZ + res_len);
+
+       PG_FREE_IF_COPY(data, 0);
+       PG_RETURN_TEXT_P(res);
+}
+
+Datum
+pg_dearmor(PG_FUNCTION_ARGS)
+{
+       text       *data;
+       bytea      *res;
+       int                     data_len,
+                               res_len,
+                               guess_len;
+
+       data = PG_GETARG_TEXT_P(0);
+       data_len = VARSIZE(data) - VARHDRSZ;
+
+       guess_len = pgp_armor_dec_len(data_len);
+       res = palloc(VARHDRSZ + guess_len);
+
+       res_len = pgp_armor_decode((uint8 *) VARDATA(data), data_len,
+                                                          (uint8 *) 
VARDATA(res));
+       if (res_len < 0)
+               ereport(ERROR,
+                               
(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
+                                errmsg("%s", px_strerror(res_len))));
+       if (res_len > guess_len)
+               ereport(ERROR,
+                               
(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
+                                errmsg("Overflow - decode estimate too 
small")));
+       SET_VARSIZE(res, VARHDRSZ + res_len);
+
+       PG_FREE_IF_COPY(data, 0);
+       PG_RETURN_TEXT_P(res);
+}
+
+/*
+ * Wrappers for PGP key id
+ */
+
+Datum
+pgp_key_id_w(PG_FUNCTION_ARGS)
+{
+       bytea      *data;
+       text       *res;
+       int                     res_len;
+       MBuf       *buf;
+
+       data = PG_GETARG_BYTEA_P(0);
+       buf = create_mbuf_from_vardata(data);
+       res = palloc(VARHDRSZ + 17);
+
+       res_len = pgp_get_keyid(buf, VARDATA(res));
+       mbuf_free(buf);
+       if (res_len < 0)
+               ereport(ERROR,
+                               
(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
+                                errmsg("%s", px_strerror(res_len))));
+       SET_VARSIZE(res, VARHDRSZ + res_len);
+
+       PG_FREE_IF_COPY(data, 0);
+       PG_RETURN_TEXT_P(res);
+}

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/801100ed/contrib/pgcrypto/pgp-pubdec.c
----------------------------------------------------------------------
diff --git a/contrib/pgcrypto/pgp-pubdec.c b/contrib/pgcrypto/pgp-pubdec.c
new file mode 100644
index 0000000..fe5fae0
--- /dev/null
+++ b/contrib/pgcrypto/pgp-pubdec.c
@@ -0,0 +1,236 @@
+/*
+ * pgp-pubdec.c
+ *       Decrypt public-key encrypted session key.
+ *
+ * Copyright (c) 2005 Marko Kreen
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.     IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * contrib/pgcrypto/pgp-pubdec.c
+ */
+#include "postgres.h"
+
+#include "px.h"
+#include "mbuf.h"
+#include "pgp.h"
+
+/*
+ * padded msg = 02 || PS || 00 || M
+ * PS - pad bytes
+ * M - msg
+ */
+static uint8 *
+check_eme_pkcs1_v15(uint8 *data, int len)
+{
+       uint8      *data_end = data + len;
+       uint8      *p = data;
+       int                     rnd = 0;
+
+       if (len < 1 + 8 + 1)
+               return NULL;
+
+       if (*p++ != 2)
+               return NULL;
+
+       while (p < data_end && *p)
+       {
+               p++;
+               rnd++;
+       }
+
+       if (p == data_end)
+               return NULL;
+       if (*p != 0)
+               return NULL;
+       if (rnd < 8)
+               return NULL;
+       return p + 1;
+}
+
+/*
+ * secret message: 1 byte algo, sesskey, 2 byte cksum
+ * ignore algo in cksum
+ */
+static int
+control_cksum(uint8 *msg, int msglen)
+{
+       int                     i;
+       unsigned        my_cksum,
+                               got_cksum;
+
+       if (msglen < 3)
+               return PXE_PGP_WRONG_KEY;
+
+       my_cksum = 0;
+       for (i = 1; i < msglen - 2; i++)
+               my_cksum += msg[i];
+       my_cksum &= 0xFFFF;
+       got_cksum = ((unsigned) (msg[msglen - 2]) << 8) + msg[msglen - 1];
+       if (my_cksum != got_cksum)
+       {
+               px_debug("pubenc cksum failed");
+               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};
+
+int
+pgp_parse_pubenc_sesskey(PGP_Context *ctx, PullFilter *pkt)
+{
+       int                     ver;
+       int                     algo;
+       int                     res;
+       uint8           key_id[8];
+       PGP_PubKey *pk;
+       uint8      *msg;
+       int                     msglen;
+       PGP_MPI    *m;
+
+       pk = ctx->pub_key;
+       if (pk == NULL)
+       {
+               px_debug("no pubkey?");
+               return PXE_BUG;
+       }
+
+       GETBYTE(pkt, ver);
+       if (ver != 3)
+       {
+               px_debug("unknown pubenc_sesskey pkt ver=%d", ver);
+               return PXE_PGP_CORRUPT_DATA;
+       }
+
+       /*
+        * check if keyid's match - user-friendly msg
+        */
+       res = pullf_read_fixed(pkt, 8, key_id);
+       if (res < 0)
+               return res;
+       if (memcmp(key_id, any_key, 8) != 0
+               && memcmp(key_id, pk->key_id, 8) != 0)
+       {
+               px_debug("key_id's does not match");
+               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;
+
+       /*
+        * extract message
+        */
+       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
+        */
+       ctx->cipher_algo = *msg;
+       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);
+}

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/801100ed/contrib/pgcrypto/pgp-pubenc.c
----------------------------------------------------------------------
diff --git a/contrib/pgcrypto/pgp-pubenc.c b/contrib/pgcrypto/pgp-pubenc.c
new file mode 100644
index 0000000..943d2e4
--- /dev/null
+++ b/contrib/pgcrypto/pgp-pubenc.c
@@ -0,0 +1,250 @@
+/*
+ * pgp-pubenc.c
+ *       Encrypt session key with public key.
+ *
+ * Copyright (c) 2005 Marko Kreen
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.     IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * contrib/pgcrypto/pgp-pubenc.c
+ */
+#include "postgres.h"
+
+#include "px.h"
+#include "mbuf.h"
+#include "pgp.h"
+
+/*
+ * padded msg: 02 || non-zero pad bytes || 00 || msg
+ */
+static int
+pad_eme_pkcs1_v15(uint8 *data, int data_len, int res_len, uint8 **res_p)
+{
+       int                     res;
+       uint8      *buf,
+                          *p;
+       int                     pad_len = res_len - 2 - data_len;
+
+       if (pad_len < 8)
+               return PXE_BUG;
+
+       buf = px_alloc(res_len);
+       buf[0] = 0x02;
+       res = px_get_random_bytes(buf + 1, pad_len);
+       if (res < 0)
+       {
+               px_free(buf);
+               return res;
+       }
+
+       /* pad must not contain zero bytes */
+       p = buf + 1;
+       while (p < buf + 1 + pad_len)
+       {
+               if (*p == 0)
+               {
+                       res = px_get_random_bytes(p, 1);
+                       if (res < 0)
+                               break;
+               }
+               if (*p != 0)
+                       p++;
+       }
+
+       if (res < 0)
+       {
+               memset(buf, 0, res_len);
+               px_free(buf);
+               return res;
+       }
+
+       buf[pad_len + 1] = 0;
+       memcpy(buf + pad_len + 2, data, data_len);
+       *res_p = buf;
+
+       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 "secret message"
+        */
+       secmsg = px_alloc(klen + 3);
+       secmsg[0] = ctx->cipher_algo;
+       memcpy(secmsg + 1, ctx->sess_key, klen);
+       secmsg[klen + 1] = (cksum >> 8) & 0xFF;
+       secmsg[klen + 2] = cksum & 0xFF;
+
+       /*
+        * now create a large integer of it
+        */
+       res = pad_eme_pkcs1_v15(secmsg, klen + 3, full_bytes, &padded);
+       if (res >= 0)
+       {
+               /* first byte will be 0x02 */
+               int                     full_bits = full_bytes * 8 - 6;
+
+               res = pgp_mpi_create(padded, full_bits, &m);
+       }
+
+       if (padded)
+       {
+               memset(padded, 0, full_bytes);
+               px_free(padded);
+       }
+       memset(secmsg, 0, klen + 3);
+       px_free(secmsg);
+
+       if (res >= 0)
+               *msg_p = m;
+
+       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;
+
+       if (pk == NULL)
+       {
+               px_debug("no pubkey?\n");
+               return PXE_BUG;
+       }
+
+       algo = pk->algo;
+
+       /*
+        * now write packet
+        */
+       res = pgp_create_pkt_writer(dst, PGP_PKT_PUBENCRYPTED_SESSKEY, &pkt);
+       if (res < 0)
+               goto err;
+       res = pushf_write(pkt, &ver, 1);
+       if (res < 0)
+               goto err;
+       res = pushf_write(pkt, pk->key_id, 8);
+       if (res < 0)
+               goto err;
+       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;
+
+       /*
+        * done, signal packet end
+        */
+       res = pushf_flush(pkt);
+err:
+       if (pkt)
+               pushf_free(pkt);
+
+       return res;
+}

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/801100ed/contrib/pgcrypto/pgp-pubkey.c
----------------------------------------------------------------------
diff --git a/contrib/pgcrypto/pgp-pubkey.c b/contrib/pgcrypto/pgp-pubkey.c
new file mode 100644
index 0000000..283e0ec
--- /dev/null
+++ b/contrib/pgcrypto/pgp-pubkey.c
@@ -0,0 +1,584 @@
+/*
+ * pgp-pubkey.c
+ *       Read public or secret key.
+ *
+ * Copyright (c) 2005 Marko Kreen
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.     IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * contrib/pgcrypto/pgp-pubkey.c
+ */
+#include "postgres.h"
+
+#include "px.h"
+#include "mbuf.h"
+#include "pgp.h"
+
+int
+pgp_key_alloc(PGP_PubKey **pk_p)
+{
+       PGP_PubKey *pk;
+
+       pk = px_alloc(sizeof(*pk));
+       memset(pk, 0, sizeof(*pk));
+       *pk_p = pk;
+       return 0;
+}
+
+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);
+}
+
+static int
+calc_key_id(PGP_PubKey *pk)
+{
+       int                     res;
+       PX_MD      *md;
+       int                     len;
+       uint8           hdr[3];
+       uint8           hash[20];
+
+       res = pgp_load_digest(PGP_DIGEST_SHA1, &md);
+       if (res < 0)
+               return res;
+
+       len = 1 + 4 + 1;
+       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;
+       }
+
+       hdr[0] = 0x99;
+       hdr[1] = len >> 8;
+       hdr[2] = len & 0xFF;
+       px_md_update(md, hdr, 3);
+
+       px_md_update(md, &pk->ver, 1);
+       px_md_update(md, pk->time, 4);
+       px_md_update(md, &pk->algo, 1);
+
+       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;
+       }
+
+       px_md_finish(md, hash);
+       px_md_free(md);
+
+       memcpy(pk->key_id, hash + 12, 8);
+       memset(hash, 0, 20);
+
+       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;
+}
+
+#define HIDE_CLEAR 0
+#define HIDE_CKSUM 255
+#define HIDE_SHA1 254
+
+static int
+check_key_sha1(PullFilter *src, PGP_PubKey *pk)
+{
+       int                     res;
+       uint8           got_sha1[20];
+       uint8           my_sha1[20];
+       PX_MD      *md;
+
+       res = pullf_read_fixed(src, 20, got_sha1);
+       if (res < 0)
+               return res;
+
+       res = pgp_load_digest(PGP_DIGEST_SHA1, &md);
+       if (res < 0)
+               goto err;
+       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);
+       px_md_free(md);
+
+       if (memcmp(my_sha1, got_sha1, 20) != 0)
+       {
+               px_debug("key sha1 check failed");
+               res = PXE_PGP_KEYPKT_CORRUPT;
+       }
+err:
+       memset(got_sha1, 0, 20);
+       memset(my_sha1, 0, 20);
+       return res;
+}
+
+static int
+check_key_cksum(PullFilter *src, PGP_PubKey *pk)
+{
+       int                     res;
+       unsigned        got_cksum,
+                               my_cksum = 0;
+       uint8           buf[2];
+
+       res = pullf_read_fixed(src, 2, buf);
+       if (res < 0)
+               return res;
+
+       got_cksum = ((unsigned) buf[0] << 8) + buf[1];
+       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)
+       {
+               px_debug("key cksum check failed");
+               return PXE_PGP_KEYPKT_CORRUPT;
+       }
+       return 0;
+}
+
+static int
+process_secret_key(PullFilter *pkt, PGP_PubKey **pk_p,
+                                  const uint8 *key, int key_len)
+{
+       int                     res;
+       int                     hide_type;
+       int                     cipher_algo;
+       int                     bs;
+       uint8           iv[512];
+       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?
+        */
+       GETBYTE(pkt, hide_type);
+       if (hide_type == HIDE_SHA1 || hide_type == HIDE_CKSUM)
+       {
+               if (key == NULL)
+                       return PXE_PGP_NEED_SECRET_PSW;
+               GETBYTE(pkt, cipher_algo);
+               res = pgp_s2k_read(pkt, &s2k);
+               if (res < 0)
+                       return res;
+
+               res = pgp_s2k_process(&s2k, cipher_algo, key, key_len);
+               if (res < 0)
+                       return res;
+
+               bs = pgp_get_cipher_block_size(cipher_algo);
+               if (bs == 0)
+               {
+                       px_debug("unknown cipher algo=%d", cipher_algo);
+                       return PXE_PGP_UNSUPPORTED_CIPHER;
+               }
+               res = pullf_read_fixed(pkt, bs, iv);
+               if (res < 0)
+                       return res;
+
+               /*
+                * create decrypt filter
+                */
+               res = pgp_cfb_create(&cfb, cipher_algo, s2k.key, s2k.key_len, 
0, iv);
+               if (res < 0)
+                       return res;
+               res = pullf_create(&pf_decrypt, &pgp_decrypt_filter, cfb, pkt);
+               if (res < 0)
+                       return res;
+               pf_key = pf_decrypt;
+       }
+       else if (hide_type == HIDE_CLEAR)
+       {
+               pf_key = pkt;
+       }
+       else
+       {
+               px_debug("unknown hide type");
+               return PXE_PGP_KEYPKT_CORRUPT;
+       }
+
+       /* 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);
+                       res = PXE_PGP_KEYPKT_CORRUPT;
+       }
+       /* read checksum / sha1 */
+       if (res >= 0)
+       {
+               if (hide_type == HIDE_SHA1)
+                       res = check_key_sha1(pf_key, pk);
+               else
+                       res = check_key_cksum(pf_key, pk);
+       }
+       if (res >= 0)
+               res = pgp_expect_packet_end(pf_key);
+
+       if (pf_decrypt)
+               pullf_free(pf_decrypt);
+       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)
+                       break;
+               res = pgp_create_pkt_reader(&pkt, src, len, res, NULL);
+               if (res < 0)
+                       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:
+                       case PGP_PKT_USER_ID:
+                       case PGP_PKT_USER_ATTR:
+                       case PGP_PKT_PRIV_61:
+                               res = pgp_skip_packet(pkt);
+                               break;
+                       default:
+                               px_debug("unknown/unexpected packet: %d", tag);
+                               res = PXE_PGP_UNEXPECTED_PKT;
+               }
+               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;
+       }
+
+       if (pkt)
+               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
+pgp_set_pubkey(PGP_Context *ctx, MBuf *keypkt,
+                          const uint8 *key, int key_len, int pubtype)
+{
+       int                     res;
+       PullFilter *src;
+       PGP_PubKey *pk = NULL;
+
+       res = pullf_create_mbuf_reader(&src, keypkt);
+       if (res < 0)
+               return res;
+
+       res = internal_read_key(src, &pk, key, key_len, pubtype);
+       pullf_free(src);
+
+       if (res >= 0)
+               ctx->pub_key = pk;
+
+       return res < 0 ? res : 0;
+}

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/801100ed/contrib/pgcrypto/pgp-s2k.c
----------------------------------------------------------------------
diff --git a/contrib/pgcrypto/pgp-s2k.c b/contrib/pgcrypto/pgp-s2k.c
new file mode 100644
index 0000000..349234e
--- /dev/null
+++ b/contrib/pgcrypto/pgp-s2k.c
@@ -0,0 +1,296 @@
+/*
+ * pgp-s2k.c
+ *       OpenPGP string2key functions.
+ *
+ * Copyright (c) 2005 Marko Kreen
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.     IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * contrib/pgcrypto/pgp-s2k.c
+ */
+
+#include "postgres.h"
+
+#include "px.h"
+#include "mbuf.h"
+#include "pgp.h"
+
+static int
+calc_s2k_simple(PGP_S2K *s2k, PX_MD *md, const uint8 *key,
+                               unsigned key_len)
+{
+       unsigned        md_rlen;
+       uint8           buf[PGP_MAX_DIGEST];
+       unsigned        preload;
+       unsigned        remain;
+       uint8      *dst = s2k->key;
+
+       md_rlen = px_md_result_size(md);
+
+       remain = s2k->key_len;
+       preload = 0;
+       while (remain > 0)
+       {
+               px_md_reset(md);
+
+               if (preload)
+               {
+                       memset(buf, 0, preload);
+                       px_md_update(md, buf, preload);
+               }
+               preload++;
+
+               px_md_update(md, key, key_len);
+               px_md_finish(md, buf);
+
+               if (remain > md_rlen)
+               {
+                       memcpy(dst, buf, md_rlen);
+                       dst += md_rlen;
+                       remain -= md_rlen;
+               }
+               else
+               {
+                       memcpy(dst, buf, remain);
+                       remain = 0;
+               }
+       }
+       return 0;
+}
+
+static int
+calc_s2k_salted(PGP_S2K *s2k, PX_MD *md, const uint8 *key, unsigned key_len)
+{
+       unsigned        md_rlen;
+       uint8           buf[PGP_MAX_DIGEST];
+       unsigned        preload = 0;
+       uint8      *dst;
+       unsigned        remain;
+
+       md_rlen = px_md_result_size(md);
+
+       dst = s2k->key;
+       remain = s2k->key_len;
+       while (remain > 0)
+       {
+               px_md_reset(md);
+
+               if (preload > 0)
+               {
+                       memset(buf, 0, preload);
+                       px_md_update(md, buf, preload);
+               }
+               preload++;
+
+               px_md_update(md, s2k->salt, PGP_S2K_SALT);
+               px_md_update(md, key, key_len);
+               px_md_finish(md, buf);
+
+               if (remain > md_rlen)
+               {
+                       memcpy(dst, buf, md_rlen);
+                       remain -= md_rlen;
+                       dst += md_rlen;
+               }
+               else
+               {
+                       memcpy(dst, buf, remain);
+                       remain = 0;
+               }
+       }
+       return 0;
+}
+
+static int
+calc_s2k_iter_salted(PGP_S2K *s2k, PX_MD *md, const uint8 *key,
+                                        unsigned key_len)
+{
+       unsigned        md_rlen;
+       uint8           buf[PGP_MAX_DIGEST];
+       uint8      *dst;
+       unsigned        preload = 0;
+       unsigned        remain,
+                               c,
+                               cval,
+                               curcnt,
+                               count;
+
+       cval = s2k->iter;
+       count = ((unsigned) 16 + (cval & 15)) << ((cval >> 4) + 6);
+
+       md_rlen = px_md_result_size(md);
+
+       remain = s2k->key_len;
+       dst = s2k->key;
+       while (remain > 0)
+       {
+               px_md_reset(md);
+
+               if (preload)
+               {
+                       memset(buf, 0, preload);
+                       px_md_update(md, buf, preload);
+               }
+               preload++;
+
+               px_md_update(md, s2k->salt, PGP_S2K_SALT);
+               px_md_update(md, key, key_len);
+               curcnt = PGP_S2K_SALT + key_len;
+
+               while (curcnt < count)
+               {
+                       if (curcnt + PGP_S2K_SALT < count)
+                               c = PGP_S2K_SALT;
+                       else
+                               c = count - curcnt;
+                       px_md_update(md, s2k->salt, c);
+                       curcnt += c;
+
+                       if (curcnt + key_len < count)
+                               c = key_len;
+                       else if (curcnt < count)
+                               c = count - curcnt;
+                       else
+                               break;
+                       px_md_update(md, key, c);
+                       curcnt += c;
+               }
+               px_md_finish(md, buf);
+
+               if (remain > md_rlen)
+               {
+                       memcpy(dst, buf, md_rlen);
+                       remain -= md_rlen;
+                       dst += md_rlen;
+               }
+               else
+               {
+                       memcpy(dst, buf, remain);
+                       remain = 0;
+               }
+       }
+       return 0;
+}
+
+/*
+ * Decide S2K_ISALTED iteration count
+ *
+ * Too small: weak
+ * Too big: slow
+ * gpg defaults to 96 => 65536 iters
+ * let it float a bit: 96 + 32 => 262144 iters
+ */
+static int
+decide_count(unsigned rand_byte)
+{
+       return 96 + (rand_byte & 0x1F);
+}
+
+int
+pgp_s2k_fill(PGP_S2K *s2k, int mode, int digest_algo)
+{
+       int                     res = 0;
+       uint8           tmp;
+
+       s2k->mode = mode;
+       s2k->digest_algo = digest_algo;
+
+       switch (s2k->mode)
+       {
+               case 0:
+                       break;
+               case 1:
+                       res = px_get_pseudo_random_bytes(s2k->salt, 
PGP_S2K_SALT);
+                       break;
+               case 3:
+                       res = px_get_pseudo_random_bytes(s2k->salt, 
PGP_S2K_SALT);
+                       if (res < 0)
+                               break;
+                       res = px_get_pseudo_random_bytes(&tmp, 1);
+                       if (res < 0)
+                               break;
+                       s2k->iter = decide_count(tmp);
+                       break;
+               default:
+                       res = PXE_PGP_BAD_S2K_MODE;
+       }
+       return res;
+}
+
+int
+pgp_s2k_read(PullFilter *src, PGP_S2K *s2k)
+{
+       int                     res = 0;
+
+       GETBYTE(src, s2k->mode);
+       GETBYTE(src, s2k->digest_algo);
+       switch (s2k->mode)
+       {
+               case 0:
+                       break;
+               case 1:
+                       res = pullf_read_fixed(src, 8, s2k->salt);
+                       break;
+               case 3:
+                       res = pullf_read_fixed(src, 8, s2k->salt);
+                       if (res < 0)
+                               break;
+                       GETBYTE(src, s2k->iter);
+                       break;
+               default:
+                       res = PXE_PGP_BAD_S2K_MODE;
+       }
+       return res;
+}
+
+int
+pgp_s2k_process(PGP_S2K *s2k, int cipher, const uint8 *key, int key_len)
+{
+       int                     res;
+       PX_MD      *md;
+
+       s2k->key_len = pgp_get_cipher_key_size(cipher);
+       if (s2k->key_len <= 0)
+               return PXE_PGP_UNSUPPORTED_CIPHER;
+
+       res = pgp_load_digest(s2k->digest_algo, &md);
+       if (res < 0)
+               return res;
+
+       switch (s2k->mode)
+       {
+               case 0:
+                       res = calc_s2k_simple(s2k, md, key, key_len);
+                       break;
+               case 1:
+                       res = calc_s2k_salted(s2k, md, key, key_len);
+                       break;
+               case 3:
+                       res = calc_s2k_iter_salted(s2k, md, key, key_len);
+                       break;
+               default:
+                       res = PXE_PGP_BAD_S2K_MODE;
+       }
+       px_md_free(md);
+       return res;
+}

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/801100ed/contrib/pgcrypto/pgp.c
----------------------------------------------------------------------
diff --git a/contrib/pgcrypto/pgp.c b/contrib/pgcrypto/pgp.c
new file mode 100644
index 0000000..b8a6bc4
--- /dev/null
+++ b/contrib/pgcrypto/pgp.c
@@ -0,0 +1,360 @@
+/*
+ * pgp.c
+ *       Various utility stuff.
+ *
+ * Copyright (c) 2005 Marko Kreen
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.     IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * contrib/pgcrypto/pgp.c
+ */
+
+#include "postgres.h"
+
+#include "px.h"
+#include "mbuf.h"
+#include "pgp.h"
+
+/*
+ * Defaults.
+ */
+static int     def_cipher_algo = PGP_SYM_AES_128;
+static int     def_s2k_cipher_algo = -1;
+static int     def_s2k_mode = PGP_S2K_ISALTED;
+static int     def_s2k_digest_algo = PGP_DIGEST_SHA1;
+static int     def_compress_algo = PGP_COMPR_NONE;
+static int     def_compress_level = 6;
+static int     def_disable_mdc = 0;
+static int     def_use_sess_key = 0;
+static int     def_text_mode = 0;
+static int     def_unicode_mode = 0;
+static int     def_convert_crlf = 0;
+
+struct digest_info
+{
+       const char *name;
+       int                     code;
+       const char *int_name;
+};
+
+struct cipher_info
+{
+       const char *name;
+       int                     code;
+       const char *int_name;
+       int                     key_len;
+       int                     block_len;
+};
+
+static const struct digest_info digest_list[] = {
+       {"md5", PGP_DIGEST_MD5},
+       {"sha1", PGP_DIGEST_SHA1},
+       {"sha-1", PGP_DIGEST_SHA1},
+       {"ripemd160", PGP_DIGEST_RIPEMD160},
+       {"sha256", PGP_DIGEST_SHA256},
+       {"sha384", PGP_DIGEST_SHA384},
+       {"sha512", PGP_DIGEST_SHA512},
+       {NULL, 0}
+};
+
+static const struct cipher_info cipher_list[] = {
+       {"3des", PGP_SYM_DES3, "3des-ecb", 192 / 8, 64 / 8},
+       {"cast5", PGP_SYM_CAST5, "cast5-ecb", 128 / 8, 64 / 8},
+       {"bf", PGP_SYM_BLOWFISH, "bf-ecb", 128 / 8, 64 / 8},
+       {"blowfish", PGP_SYM_BLOWFISH, "bf-ecb", 128 / 8, 64 / 8},
+       {"aes", PGP_SYM_AES_128, "aes-ecb", 128 / 8, 128 / 8},
+       {"aes128", PGP_SYM_AES_128, "aes-ecb", 128 / 8, 128 / 8},
+       {"aes192", PGP_SYM_AES_192, "aes-ecb", 192 / 8, 128 / 8},
+       {"aes256", PGP_SYM_AES_256, "aes-ecb", 256 / 8, 128 / 8},
+       {"twofish", PGP_SYM_TWOFISH, "twofish-ecb", 256 / 8, 128 / 8},
+       {NULL, 0, NULL}
+};
+
+static const struct cipher_info *
+get_cipher_info(int code)
+{
+       const struct cipher_info *i;
+
+       for (i = cipher_list; i->name; i++)
+               if (i->code == code)
+                       return i;
+       return NULL;
+}
+
+int
+pgp_get_digest_code(const char *name)
+{
+       const struct digest_info *i;
+
+       for (i = digest_list; i->name; i++)
+               if (pg_strcasecmp(i->name, name) == 0)
+                       return i->code;
+       return PXE_PGP_UNSUPPORTED_HASH;
+}
+
+int
+pgp_get_cipher_code(const char *name)
+{
+       const struct cipher_info *i;
+
+       for (i = cipher_list; i->name; i++)
+               if (pg_strcasecmp(i->name, name) == 0)
+                       return i->code;
+       return PXE_PGP_UNSUPPORTED_CIPHER;
+}
+
+const char *
+pgp_get_digest_name(int code)
+{
+       const struct digest_info *i;
+
+       for (i = digest_list; i->name; i++)
+               if (i->code == code)
+                       return i->name;
+       return NULL;
+}
+
+const char *
+pgp_get_cipher_name(int code)
+{
+       const struct cipher_info *i = get_cipher_info(code);
+
+       if (i != NULL)
+               return i->name;
+       return NULL;
+}
+
+int
+pgp_get_cipher_key_size(int code)
+{
+       const struct cipher_info *i = get_cipher_info(code);
+
+       if (i != NULL)
+               return i->key_len;
+       return 0;
+}
+
+int
+pgp_get_cipher_block_size(int code)
+{
+       const struct cipher_info *i = get_cipher_info(code);
+
+       if (i != NULL)
+               return i->block_len;
+       return 0;
+}
+
+int
+pgp_load_cipher(int code, PX_Cipher **res)
+{
+       int                     err;
+       const struct cipher_info *i = get_cipher_info(code);
+
+       if (i == NULL)
+               return PXE_PGP_CORRUPT_DATA;
+
+       err = px_find_cipher(i->int_name, res);
+       if (err == 0)
+               return 0;
+
+       return PXE_PGP_UNSUPPORTED_CIPHER;
+}
+
+int
+pgp_load_digest(int code, PX_MD **res)
+{
+       int                     err;
+       const char *name = pgp_get_digest_name(code);
+
+       if (name == NULL)
+               return PXE_PGP_CORRUPT_DATA;
+
+       err = px_find_digest(name, res);
+       if (err == 0)
+               return 0;
+
+       return PXE_PGP_UNSUPPORTED_HASH;
+}
+
+int
+pgp_init(PGP_Context **ctx_p)
+{
+       PGP_Context *ctx;
+
+       ctx = px_alloc(sizeof *ctx);
+       memset(ctx, 0, sizeof *ctx);
+
+       ctx->cipher_algo = def_cipher_algo;
+       ctx->s2k_cipher_algo = def_s2k_cipher_algo;
+       ctx->s2k_mode = def_s2k_mode;
+       ctx->s2k_digest_algo = def_s2k_digest_algo;
+       ctx->compress_algo = def_compress_algo;
+       ctx->compress_level = def_compress_level;
+       ctx->disable_mdc = def_disable_mdc;
+       ctx->use_sess_key = def_use_sess_key;
+       ctx->unicode_mode = def_unicode_mode;
+       ctx->convert_crlf = def_convert_crlf;
+       ctx->text_mode = def_text_mode;
+
+       *ctx_p = ctx;
+       return 0;
+}
+
+int
+pgp_free(PGP_Context *ctx)
+{
+       if (ctx->pub_key)
+               pgp_key_free(ctx->pub_key);
+       memset(ctx, 0, sizeof *ctx);
+       px_free(ctx);
+       return 0;
+}
+
+int
+pgp_disable_mdc(PGP_Context *ctx, int disable)
+{
+       ctx->disable_mdc = disable ? 1 : 0;
+       return 0;
+}
+
+int
+pgp_set_sess_key(PGP_Context *ctx, int use)
+{
+       ctx->use_sess_key = use ? 1 : 0;
+       return 0;
+}
+
+int
+pgp_set_convert_crlf(PGP_Context *ctx, int doit)
+{
+       ctx->convert_crlf = doit ? 1 : 0;
+       return 0;
+}
+
+int
+pgp_set_s2k_mode(PGP_Context *ctx, int mode)
+{
+       int                     err = PXE_OK;
+
+       switch (mode)
+       {
+               case PGP_S2K_SIMPLE:
+               case PGP_S2K_SALTED:
+               case PGP_S2K_ISALTED:
+                       ctx->s2k_mode = mode;
+                       break;
+               default:
+                       err = PXE_ARGUMENT_ERROR;
+                       break;
+       }
+       return err;
+}
+
+int
+pgp_set_compress_algo(PGP_Context *ctx, int algo)
+{
+       switch (algo)
+       {
+               case PGP_COMPR_NONE:
+               case PGP_COMPR_ZIP:
+               case PGP_COMPR_ZLIB:
+               case PGP_COMPR_BZIP2:
+                       ctx->compress_algo = algo;
+                       return 0;
+       }
+       return PXE_ARGUMENT_ERROR;
+}
+
+int
+pgp_set_compress_level(PGP_Context *ctx, int level)
+{
+       if (level >= 0 && level <= 9)
+       {
+               ctx->compress_level = level;
+               return 0;
+       }
+       return PXE_ARGUMENT_ERROR;
+}
+
+int
+pgp_set_text_mode(PGP_Context *ctx, int mode)
+{
+       ctx->text_mode = mode;
+       return 0;
+}
+
+int
+pgp_set_cipher_algo(PGP_Context *ctx, const char *name)
+{
+       int                     code = pgp_get_cipher_code(name);
+
+       if (code < 0)
+               return code;
+       ctx->cipher_algo = code;
+       return 0;
+}
+
+int
+pgp_set_s2k_cipher_algo(PGP_Context *ctx, const char *name)
+{
+       int                     code = pgp_get_cipher_code(name);
+
+       if (code < 0)
+               return code;
+       ctx->s2k_cipher_algo = code;
+       return 0;
+}
+
+int
+pgp_set_s2k_digest_algo(PGP_Context *ctx, const char *name)
+{
+       int                     code = pgp_get_digest_code(name);
+
+       if (code < 0)
+               return code;
+       ctx->s2k_digest_algo = code;
+       return 0;
+}
+
+int
+pgp_get_unicode_mode(PGP_Context *ctx)
+{
+       return ctx->unicode_mode;
+}
+
+int
+pgp_set_unicode_mode(PGP_Context *ctx, int mode)
+{
+       ctx->unicode_mode = mode ? 1 : 0;
+       return 0;
+}
+
+int
+pgp_set_symkey(PGP_Context *ctx, const uint8 *key, int len)
+{
+       if (key == NULL || len < 1)
+               return PXE_ARGUMENT_ERROR;
+       ctx->sym_key = key;
+       ctx->sym_key_len = len;
+       return 0;
+}

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/801100ed/contrib/pgcrypto/pgp.h
----------------------------------------------------------------------
diff --git a/contrib/pgcrypto/pgp.h b/contrib/pgcrypto/pgp.h
new file mode 100644
index 0000000..7ae01cc
--- /dev/null
+++ b/contrib/pgcrypto/pgp.h
@@ -0,0 +1,314 @@
+/*
+ * pgp.h
+ *       OpenPGP implementation.
+ *
+ * Copyright (c) 2005 Marko Kreen
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.     IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * contrib/pgcrypto/pgp.h
+ */
+
+enum PGP_S2K_TYPE
+{
+       PGP_S2K_SIMPLE = 0,
+       PGP_S2K_SALTED = 1,
+       PGP_S2K_ISALTED = 3
+};
+
+enum PGP_PKT_TYPE
+{
+       PGP_PKT_RESERVED = 0,
+       PGP_PKT_PUBENCRYPTED_SESSKEY = 1,
+       PGP_PKT_SIGNATURE = 2,
+       PGP_PKT_SYMENCRYPTED_SESSKEY = 3,
+       PGP_PKT_SECRET_KEY = 5,
+       PGP_PKT_PUBLIC_KEY = 6,
+       PGP_PKT_SECRET_SUBKEY = 7,
+       PGP_PKT_COMPRESSED_DATA = 8,
+       PGP_PKT_SYMENCRYPTED_DATA = 9,
+       PGP_PKT_MARKER = 10,
+       PGP_PKT_LITERAL_DATA = 11,
+       PGP_PKT_TRUST = 12,
+       PGP_PKT_USER_ID = 13,
+       PGP_PKT_PUBLIC_SUBKEY = 14,
+       PGP_PKT_USER_ATTR = 17,
+       PGP_PKT_SYMENCRYPTED_DATA_MDC = 18,
+       PGP_PKT_MDC = 19,
+       PGP_PKT_PRIV_61 = 61            /* occurs in gpg secring */
+};
+
+enum PGP_PUB_ALGO_TYPE
+{
+       PGP_PUB_RSA_ENCRYPT_SIGN = 1,
+       PGP_PUB_RSA_ENCRYPT = 2,
+       PGP_PUB_RSA_SIGN = 3,
+       PGP_PUB_ELG_ENCRYPT = 16,
+       PGP_PUB_DSA_SIGN = 17
+};
+
+enum PGP_SYMENC_TYPE
+{
+       PGP_SYM_PLAIN = 0,                      /* ?? */
+       PGP_SYM_IDEA = 1,                       /* obsolete, PGP 2.6 compat */
+       PGP_SYM_DES3 = 2,                       /* must */
+       PGP_SYM_CAST5 = 3,                      /* should */
+       PGP_SYM_BLOWFISH = 4,
+       PGP_SYM_SAFER_SK128 = 5,        /* obsolete */
+       PGP_SYM_DES_SK = 6,                     /* obsolete */
+       PGP_SYM_AES_128 = 7,            /* should */
+       PGP_SYM_AES_192 = 8,
+       PGP_SYM_AES_256 = 9,
+       PGP_SYM_TWOFISH = 10
+};
+
+enum PGP_COMPR_TYPE
+{
+       PGP_COMPR_NONE = 0,                     /* must */
+       PGP_COMPR_ZIP = 1,                      /* should */
+       PGP_COMPR_ZLIB = 2,
+       PGP_COMPR_BZIP2 = 3
+};
+
+enum PGP_DIGEST_TYPE
+{
+       PGP_DIGEST_MD5 = 1,                     /* should, deprecated  */
+       PGP_DIGEST_SHA1 = 2,            /* must */
+       PGP_DIGEST_RIPEMD160 = 3,
+       PGP_DIGEST_XSHA = 4,            /* obsolete */
+       PGP_DIGEST_MD2 = 5,                     /* obsolete */
+       PGP_DIGEST_TIGER192 = 6,        /* obsolete */
+       PGP_DIGEST_HAVAL5_160 = 7,      /* obsolete */
+       PGP_DIGEST_SHA256 = 8,
+       PGP_DIGEST_SHA384 = 9,
+       PGP_DIGEST_SHA512 = 10
+};
+
+#define PGP_MAX_KEY    (256/8)
+#define PGP_MAX_BLOCK  (256/8)
+#define PGP_MAX_DIGEST (512/8)
+#define PGP_S2K_SALT   8
+
+typedef struct PGP_MPI PGP_MPI;
+typedef struct PGP_PubKey PGP_PubKey;
+typedef struct PGP_Context PGP_Context;
+typedef struct PGP_S2K PGP_S2K;
+
+struct PGP_S2K
+{
+       uint8           mode;
+       uint8           digest_algo;
+       uint8           salt[8];
+       uint8           iter;
+       /* calculated: */
+       uint8           key[PGP_MAX_KEY];
+       uint8           key_len;
+};
+
+
+struct PGP_Context
+{
+       /*
+        * parameters
+        */
+       PGP_S2K         s2k;
+       int                     s2k_mode;
+       int                     s2k_digest_algo;
+       int                     s2k_cipher_algo;
+       int                     cipher_algo;
+       int                     compress_algo;
+       int                     compress_level;
+       int                     disable_mdc;
+       int                     use_sess_key;
+       int                     text_mode;
+       int                     convert_crlf;
+       int                     unicode_mode;
+
+       /*
+        * internal variables
+        */
+       int                     mdc_checked;
+       int                     corrupt_prefix;
+       int                     in_mdc_pkt;
+       int                     use_mdcbuf_filter;
+       PX_MD      *mdc_ctx;
+
+       PGP_PubKey *pub_key;            /* ctx owns it */
+       const uint8 *sym_key;           /* ctx does not own it */
+       int                     sym_key_len;
+
+       /*
+        * read or generated data
+        */
+       uint8           sess_key[PGP_MAX_KEY];
+       unsigned        sess_key_len;
+};
+
+struct PGP_MPI
+{
+       uint8      *data;
+       int                     bits;
+       int                     bytes;
+};
+
+struct PGP_PubKey
+{
+       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_encrypt(PGP_Context *ctx, MBuf *src, MBuf *dst);
+int                    pgp_decrypt(PGP_Context *ctx, MBuf *src, MBuf *dst);
+int                    pgp_free(PGP_Context *ctx);
+
+int                    pgp_get_digest_code(const char *name);
+int                    pgp_get_cipher_code(const char *name);
+const char *pgp_get_digest_name(int code);
+const char *pgp_get_cipher_name(int code);
+
+int                    pgp_set_cipher_algo(PGP_Context *ctx, const char *name);
+int                    pgp_set_s2k_mode(PGP_Context *ctx, int type);
+int                    pgp_set_s2k_cipher_algo(PGP_Context *ctx, const char 
*name);
+int                    pgp_set_s2k_digest_algo(PGP_Context *ctx, const char 
*name);
+int                    pgp_set_convert_crlf(PGP_Context *ctx, int doit);
+int                    pgp_disable_mdc(PGP_Context *ctx, int disable);
+int                    pgp_set_sess_key(PGP_Context *ctx, int use);
+int                    pgp_set_compress_algo(PGP_Context *ctx, int algo);
+int                    pgp_set_compress_level(PGP_Context *ctx, int level);
+int                    pgp_set_text_mode(PGP_Context *ctx, int mode);
+int                    pgp_set_unicode_mode(PGP_Context *ctx, int mode);
+int                    pgp_get_unicode_mode(PGP_Context *ctx);
+
+int                    pgp_set_symkey(PGP_Context *ctx, const uint8 *key, int 
klen);
+int pgp_set_pubkey(PGP_Context *ctx, MBuf *keypkt,
+                          const uint8 *key, int klen, int pubtype);
+
+int                    pgp_get_keyid(MBuf *pgp_data, char *dst);
+
+/* internal functions */
+
+int                    pgp_load_digest(int c, PX_MD **res);
+int                    pgp_load_cipher(int c, PX_Cipher **res);
+int                    pgp_get_cipher_key_size(int c);
+int                    pgp_get_cipher_block_size(int c);
+
+int                    pgp_s2k_fill(PGP_S2K *s2k, int mode, int digest_algo);
+int                    pgp_s2k_read(PullFilter *src, PGP_S2K *s2k);
+int                    pgp_s2k_process(PGP_S2K *s2k, int cipher, const uint8 
*key, int klen);
+
+typedef struct PGP_CFB PGP_CFB;
+int
+pgp_cfb_create(PGP_CFB **ctx_p, int algo,
+                          const uint8 *key, int key_len, int recync, uint8 
*iv);
+void           pgp_cfb_free(PGP_CFB *ctx);
+int                    pgp_cfb_encrypt(PGP_CFB *ctx, const uint8 *data, int 
len, uint8 *dst);
+int                    pgp_cfb_decrypt(PGP_CFB *ctx, const uint8 *data, int 
len, uint8 *dst);
+
+int                    pgp_armor_encode(const uint8 *src, unsigned len, uint8 
*dst);
+int                    pgp_armor_decode(const uint8 *src, unsigned len, uint8 
*dst);
+unsigned       pgp_armor_enc_len(unsigned len);
+unsigned       pgp_armor_dec_len(unsigned len);
+
+int                    pgp_compress_filter(PushFilter **res, PGP_Context *ctx, 
PushFilter *dst);
+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_p);
+
+int                    pgp_parse_pubenc_sesskey(PGP_Context *ctx, PullFilter 
*pkt);
+int pgp_create_pkt_reader(PullFilter **pf_p, PullFilter *src, int len,
+                                         int pkttype, PGP_Context *ctx);
+int pgp_parse_pkt_hdr(PullFilter *src, uint8 *tag, int *len_p,
+                                 int allow_ctx);
+
+int                    pgp_skip_packet(PullFilter *pkt);
+int                    pgp_expect_packet_end(PullFilter *pkt);
+
+int                    pgp_write_pubenc_sesskey(PGP_Context *ctx, PushFilter 
*dst);
+int                    pgp_create_pkt_writer(PushFilter *dst, int tag, 
PushFilter **res_p);
+
+int                    pgp_mpi_alloc(int bits, PGP_MPI **mpi);
+int                    pgp_mpi_create(uint8 *data, int bits, PGP_MPI **mpi);
+int                    pgp_mpi_free(PGP_MPI *mpi);
+int                    pgp_mpi_read(PullFilter *src, PGP_MPI **mpi);
+int                    pgp_mpi_write(PushFilter *dst, PGP_MPI *n);
+int                    pgp_mpi_hash(PX_MD *md, PGP_MPI *n);
+unsigned       pgp_mpi_cksum(unsigned cksum, PGP_MPI *n);
+
+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;

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/801100ed/contrib/pgcrypto/px-crypt.c
----------------------------------------------------------------------
diff --git a/contrib/pgcrypto/px-crypt.c b/contrib/pgcrypto/px-crypt.c
new file mode 100644
index 0000000..63ec038
--- /dev/null
+++ b/contrib/pgcrypto/px-crypt.c
@@ -0,0 +1,167 @@
+/*
+ * px-crypt.c
+ *             Wrapper for various crypt algorithms.
+ *
+ * Copyright (c) 2001 Marko Kreen
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.     IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * contrib/pgcrypto/px-crypt.c
+ */
+
+#include "postgres.h"
+
+#include "px.h"
+#include "px-crypt.h"
+
+
+static char *
+run_crypt_des(const char *psw, const char *salt,
+                         char *buf, unsigned len)
+{
+       char       *res;
+
+       res = px_crypt_des(psw, salt);
+       if (strlen(res) > len - 1)
+               return NULL;
+       strcpy(buf, res);
+       return buf;
+}
+
+static char *
+run_crypt_md5(const char *psw, const char *salt,
+                         char *buf, unsigned len)
+{
+       char       *res;
+
+       res = px_crypt_md5(psw, salt, buf, len);
+       return res;
+}
+
+static char *
+run_crypt_bf(const char *psw, const char *salt,
+                        char *buf, unsigned len)
+{
+       char       *res;
+
+       res = _crypt_blowfish_rn(psw, salt, buf, len);
+       return res;
+}
+
+struct px_crypt_algo
+{
+       char       *id;
+       unsigned        id_len;
+       char       *(*crypt) (const char *psw, const char *salt,
+                                                                         char 
*buf, unsigned len);
+};
+
+static const struct px_crypt_algo
+                       px_crypt_list[] = {
+       {"$2a$", 4, run_crypt_bf},
+       {"$2x$", 4, run_crypt_bf},
+       {"$2$", 3, NULL},                       /* N/A */
+       {"$1$", 3, run_crypt_md5},
+       {"_", 1, run_crypt_des},
+       {"", 0, run_crypt_des},
+       {NULL, 0, NULL}
+};
+
+char *
+px_crypt(const char *psw, const char *salt, char *buf, unsigned len)
+{
+       const struct px_crypt_algo *c;
+
+       for (c = px_crypt_list; c->id; c++)
+       {
+               if (!c->id_len)
+                       break;
+               if (strncmp(salt, c->id, c->id_len) == 0)
+                       break;
+       }
+
+       if (c->crypt == NULL)
+               return NULL;
+
+       return c->crypt(psw, salt, buf, len);
+}
+
+/*
+ * salt generators
+ */
+
+struct generator
+{
+       char       *name;
+       char       *(*gen) (unsigned long count, const char *input, int size,
+                                                                       char 
*output, int output_size);
+       int                     input_len;
+       int                     def_rounds;
+       int                     min_rounds;
+       int                     max_rounds;
+};
+
+static struct generator gen_list[] = {
+       {"des", _crypt_gensalt_traditional_rn, 2, 0, 0, 0},
+       {"md5", _crypt_gensalt_md5_rn, 6, 0, 0, 0},
+       {"xdes", _crypt_gensalt_extended_rn, 3, PX_XDES_ROUNDS, 1, 0xFFFFFF},
+       {"bf", _crypt_gensalt_blowfish_rn, 16, PX_BF_ROUNDS, 4, 31},
+       {NULL, NULL, 0, 0, 0, 0}
+};
+
+int
+px_gen_salt(const char *salt_type, char *buf, int rounds)
+{
+       int                     res;
+       struct generator *g;
+       char       *p;
+       char            rbuf[16];
+
+       for (g = gen_list; g->name; g++)
+               if (pg_strcasecmp(g->name, salt_type) == 0)
+                       break;
+
+       if (g->name == NULL)
+               return PXE_UNKNOWN_SALT_ALGO;
+
+       if (g->def_rounds)
+       {
+               if (rounds == 0)
+                       rounds = g->def_rounds;
+
+               if (rounds < g->min_rounds || rounds > g->max_rounds)
+                       return PXE_BAD_SALT_ROUNDS;
+       }
+
+       res = px_get_pseudo_random_bytes((uint8 *) rbuf, g->input_len);
+       if (res < 0)
+               return res;
+
+       p = g->gen(rounds, rbuf, g->input_len, buf, PX_MAX_SALT_LEN);
+       memset(rbuf, 0, sizeof(rbuf));
+
+       if (p == NULL)
+               return PXE_BAD_SALT_ROUNDS;
+
+       return strlen(p);
+}

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/801100ed/contrib/pgcrypto/px-crypt.h
----------------------------------------------------------------------
diff --git a/contrib/pgcrypto/px-crypt.h b/contrib/pgcrypto/px-crypt.h
new file mode 100644
index 0000000..7dde9ab
--- /dev/null
+++ b/contrib/pgcrypto/px-crypt.h
@@ -0,0 +1,82 @@
+/*
+ * px-crypt.h
+ *             Header file for px_crypt().
+ *
+ * Copyright (c) 2001 Marko Kreen
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.     IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * contrib/pgcrypto/px-crypt.h
+ */
+
+#ifndef _PX_CRYPT_H
+#define _PX_CRYPT_H
+
+/* max room for result */
+#define PX_MAX_CRYPT  128
+
+/* max salt returned by gen_salt() */
+#define PX_MAX_SALT_LEN                128
+
+/* default rounds for xdes salt */
+/* NetBSD bin/passwd/local_passwd.c has (29 * 25)*/
+#define PX_XDES_ROUNDS         (29 * 25)
+
+/* default for blowfish salt */
+#define PX_BF_ROUNDS           6
+
+/*
+ * main interface
+ */
+char      *px_crypt(const char *psw, const char *salt, char *buf, unsigned 
buflen);
+int                    px_gen_salt(const char *salt_type, char *dst, int 
rounds);
+
+/*
+ * internal functions
+ */
+
+/* crypt-gensalt.c */
+char *_crypt_gensalt_traditional_rn(unsigned long count,
+                                const char *input, int size, char *output, int 
output_size);
+char *_crypt_gensalt_extended_rn(unsigned long count,
+                                const char *input, int size, char *output, int 
output_size);
+char *_crypt_gensalt_md5_rn(unsigned long count,
+                                const char *input, int size, char *output, int 
output_size);
+char *_crypt_gensalt_blowfish_rn(unsigned long count,
+                                const char *input, int size, char *output, int 
output_size);
+
+/* disable 'extended DES crypt' */
+/* #define DISABLE_XDES */
+
+/* crypt-blowfish.c */
+char *_crypt_blowfish_rn(const char *key, const char *setting,
+                                  char *output, int size);
+
+/* crypt-des.c */
+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_CRYPT_H */

http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/801100ed/contrib/pgcrypto/px-hmac.c
----------------------------------------------------------------------
diff --git a/contrib/pgcrypto/px-hmac.c b/contrib/pgcrypto/px-hmac.c
new file mode 100644
index 0000000..36efabd
--- /dev/null
+++ b/contrib/pgcrypto/px-hmac.c
@@ -0,0 +1,177 @@
+/*
+ * px-hmac.c
+ *             HMAC implementation.
+ *
+ * Copyright (c) 2001 Marko Kreen
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.     IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * contrib/pgcrypto/px-hmac.c
+ */
+
+#include "postgres.h"
+
+#include "px.h"
+
+#define HMAC_IPAD 0x36
+#define HMAC_OPAD 0x5C
+
+static unsigned
+hmac_result_size(PX_HMAC *h)
+{
+       return px_md_result_size(h->md);
+}
+
+static unsigned
+hmac_block_size(PX_HMAC *h)
+{
+       return px_md_block_size(h->md);
+}
+
+static void
+hmac_init(PX_HMAC *h, const uint8 *key, unsigned klen)
+{
+       unsigned        bs,
+                               i;
+       uint8      *keybuf;
+       PX_MD      *md = h->md;
+
+       bs = px_md_block_size(md);
+       keybuf = px_alloc(bs);
+       memset(keybuf, 0, bs);
+
+       if (klen > bs)
+       {
+               px_md_update(md, key, klen);
+               px_md_finish(md, keybuf);
+               px_md_reset(md);
+       }
+       else
+               memcpy(keybuf, key, klen);
+
+       for (i = 0; i < bs; i++)
+       {
+               h->p.ipad[i] = keybuf[i] ^ HMAC_IPAD;
+               h->p.opad[i] = keybuf[i] ^ HMAC_OPAD;
+       }
+
+       memset(keybuf, 0, bs);
+       px_free(keybuf);
+
+       px_md_update(md, h->p.ipad, bs);
+}
+
+static void
+hmac_reset(PX_HMAC *h)
+{
+       PX_MD      *md = h->md;
+       unsigned        bs = px_md_block_size(md);
+
+       px_md_reset(md);
+       px_md_update(md, h->p.ipad, bs);
+}
+
+static void
+hmac_update(PX_HMAC *h, const uint8 *data, unsigned dlen)
+{
+       px_md_update(h->md, data, dlen);
+}
+
+static void
+hmac_finish(PX_HMAC *h, uint8 *dst)
+{
+       PX_MD      *md = h->md;
+       unsigned        bs,
+                               hlen;
+       uint8      *buf;
+
+       bs = px_md_block_size(md);
+       hlen = px_md_result_size(md);
+
+       buf = px_alloc(hlen);
+
+       px_md_finish(md, buf);
+
+       px_md_reset(md);
+       px_md_update(md, h->p.opad, bs);
+       px_md_update(md, buf, hlen);
+       px_md_finish(md, dst);
+
+       memset(buf, 0, hlen);
+       px_free(buf);
+}
+
+static void
+hmac_free(PX_HMAC *h)
+{
+       unsigned        bs;
+
+       bs = px_md_block_size(h->md);
+       px_md_free(h->md);
+
+       memset(h->p.ipad, 0, bs);
+       memset(h->p.opad, 0, bs);
+       px_free(h->p.ipad);
+       px_free(h->p.opad);
+       px_free(h);
+}
+
+
+/* PUBLIC FUNCTIONS */
+
+int
+px_find_hmac(const char *name, PX_HMAC **res)
+{
+       int                     err;
+       PX_MD      *md;
+       PX_HMAC    *h;
+       unsigned        bs;
+
+       err = px_find_digest(name, &md);
+       if (err)
+               return err;
+
+       bs = px_md_block_size(md);
+       if (bs < 2)
+       {
+               px_md_free(md);
+               return PXE_HASH_UNUSABLE_FOR_HMAC;
+       }
+
+       h = px_alloc(sizeof(*h));
+       h->p.ipad = px_alloc(bs);
+       h->p.opad = px_alloc(bs);
+       h->md = md;
+
+       h->result_size = hmac_result_size;
+       h->block_size = hmac_block_size;
+       h->reset = hmac_reset;
+       h->update = hmac_update;
+       h->finish = hmac_finish;
+       h->free = hmac_free;
+       h->init = hmac_init;
+
+       *res = h;
+
+       return 0;
+}

Reply via email to