/contrib/pgcrypto:
authorBruce Momjian
Tue, 21 Aug 2001 00:42:41 +0000 (00:42 +0000)
committerBruce Momjian
Tue, 21 Aug 2001 00:42:41 +0000 (00:42 +0000)
* remove support for encode() as it is in main tree now
* remove krb5.c
* new 'PX library' architecture
* remove BSD license from my code to let the general
  PostgreSQL one to apply
* md5, sha1: ANSIfy, use const where appropriate
* various other formatting and clarity changes
* hmac()
* UN*X-like crypt() - system or internal crypt
* Internal crypt: DES, Extended DES, MD5, Blowfish
  crypt-des.c, crypt-md5.c from FreeBSD
  crypt-blowfish.c from Solar Designer
* gen_salt() for crypt() -  Blowfish, MD5, DES, Extended DES
* encrypt(), decrypt(), encrypt_iv(), decrypt_iv()
* Cipher support in mhash.c, openssl.c
* internal: Blowfish, Rijndael-128 ciphers
* blf.[ch], rijndael.[ch] from OpenBSD
* there will be generated file rijndael-tbl.inc.

Marko Kreen

12 files changed:
contrib/pgcrypto/Makefile
contrib/pgcrypto/README.pgcrypto
contrib/pgcrypto/internal.c
contrib/pgcrypto/md5.c
contrib/pgcrypto/md5.h
contrib/pgcrypto/mhash.c
contrib/pgcrypto/openssl.c
contrib/pgcrypto/pgcrypto.c
contrib/pgcrypto/pgcrypto.h
contrib/pgcrypto/pgcrypto.sql.in
contrib/pgcrypto/sha1.c
contrib/pgcrypto/sha1.h

index 408e1c85f60c28e1534794415dc0182fa60323a2..ef9a30eb63f48422e4ba5abc54a5c07cac62ccef 100644 (file)
@@ -1,20 +1,23 @@
 #
-# $Header: /cvsroot/pgsql/contrib/pgcrypto/Makefile,v 1.4 2001/06/18 21:38:02 momjian Exp $
+# $Header: /cvsroot/pgsql/contrib/pgcrypto/Makefile,v 1.5 2001/08/21 00:42:41 momjian Exp $
 #
 
 subdir = contrib/pgcrypto
 top_builddir = ../..
 include $(top_builddir)/src/Makefile.global
 
-# either 'builtin', 'mhash', 'openssl', 'krb5'
+# either 'builtin', 'mhash', 'openssl'
 cryptolib = builtin
 
+# either 'builtin', 'system'
+cryptsrc = builtin
+
 ##########################
 
 ifeq ($(cryptolib), builtin)
 CRYPTO_CFLAGS =
 CRYPTO_LDFLAGS =
-SRCS = md5.c sha1.c internal.c
+SRCS = md5.c sha1.c internal.c blf.c rijndael.c
 endif
 
 ifeq ($(cryptolib), openssl)
@@ -25,18 +28,18 @@ endif
 
 ifeq ($(cryptolib), mhash)
 CRYPTO_CFLAGS = -I/usr/local/include
-CRYPTO_LDFLAGS = -L/usr/local/lib -lmhash
+CRYPTO_LDFLAGS = -L/usr/local/lib -lmcrypt -lmhash -lltdl
 SRCS = mhash.c
 endif
 
-ifeq ($(cryptolib), krb5)
-CRYPTO_CFLAGS = -I/usr/include
-CRYPTO_LDFLAGS = -ldes
-SRCS = krb.c
+ifeq ($(cryptsrc), builtin)
+SRCS += crypt-blowfish.c crypt-des.c crypt-md5.c 
+else
+CRYPTO_CFLAGS += -DPX_SYSTEM_CRYPT
 endif
 
 NAME   := pgcrypto
-SRCS   += pgcrypto.c encode.c
+SRCS   += pgcrypto.c px.c px-hmac.c px-crypt.c misc.c
 OBJS   := $(SRCS:.c=.o)
 SHLIB_LINK := $(CRYPTO_LDFLAGS)
 SO_MAJOR_VERSION = 0
@@ -52,6 +55,12 @@ include $(top_srcdir)/src/Makefile.shlib
 $(NAME).sql: $(NAME).sql.in
    sed 's,@MODULE_FILENAME@,$(libdir)/contrib/pgcrypto$(DLSUFFIX),g' $< >$@
 
+rijndael.o: rijndael.tbl
+
+rijndael.tbl:
+   $(CC) $(CPPFLAGS) $(CFLAGS) -DPRINT_TABS rijndael.c -o gen-rtab
+   ./gen-rtab > rijndael.tbl
+
 install: all installdirs
    $(INSTALL_SHLIB) $(shlib)   $(DESTDIR)$(libdir)/contrib/pgcrypto$(DLSUFFIX)
    $(INSTALL_DATA) $(NAME).sql $(DESTDIR)$(datadir)/contrib/$(NAME).sql
@@ -64,4 +73,4 @@ uninstall: uninstall-lib
    rm -f $(DESTDIR)$(libdir)/contrib/pgcrypto$(DLSUFFIX) $(datadir)/contrib/$(NAME).sql $(docdir)/contrib/README.$(NAME)
 
 clean distclean maintainer-clean: clean-lib
-   rm -f $(OBJS) $(NAME).sql
+   rm -f $(OBJS) $(NAME).sql gen-rtab
index 1a4c90d0b5b394b1582cd06e8f8869a093beb2a1..7173710bc3fdb138fbac4a26c1a13a3989270252 100644 (file)
 
-DESCRIPTION
+pgcrypto 0.4 - cryptographic functions for PostgreSQL.
+======================================================
+by Marko Kreen 
 
-  Here are various cryptographic and otherwise useful
-  functions for PostgreSQL.
 
-    encode(data, type)
-        encodes binary data into ASCII-only representation.
-   Types supported are 'hex' and 'base64'.
+INSTALLATION
+============
 
-    decode(data, type)
-       decodes the data processed by encode()
+Edit makefile, if you want to use any external library.
 
-    digest(data::text, hash_name::text)
-   which returns cryptographic checksum over data by
-   specified algorithm. eg
+make
+make install
 
-   > select encode(digest('blah', 'sha1'), 'hex');
-   5bf1fd927dfb8679496a2e6cf00cbe50c1c87145
+SQL FUNCTIONS
+=============
 
-    digest_exists(hash_name::text)::bool
-   which reports if particular hash type exists.
+   If any of arguments are NULL they return NULL.
 
-  If any of arguments are NULL they return NULL.
+digest(data::bytea, type::text)::bytea
 
-HASHES
+   Type is here the algorithm to use. E.g. 'md5', 'sha1', ...
+   Returns binary hash.
 
-  For choosing library you must edit Makefile.
+digest_exists(type::text)::bool
 
-  standalone (default):
-   MD5, SHA1
+   Returns BOOL whether given hash exists.
 
-   (the code is from KAME project.  Actually I hate code
-   duplication, but I also want to quarantee that MD5 and
-   SHA1 exist)
+hmac(data::bytea, key::bytea, type::text)::bytea
 
-  mhash (0.8.1):
-   MD5, SHA1, CRC32, CRC32B, GOST, TIGER, RIPEMD160,
-   HAVAL(256,224,192,160,128)
+   Calculates Hashed MAC over data.  type is the same as
+   in digest().  Returns binary hash.  Similar to digest()
+   but noone can alter data and re-calculate hash without
+   knowing key.  If the key is larger than hash blocksize
+   it will first hashed and the hash will be used as key.
+   
+   [ HMAC is described in RFC2104. ]
 
-  openssl:
-   MD5, SHA1, RIPEMD160, MD2
+hmac_exists(type::text)::bool
+   Returns BOOL.  It is separate function because all hashes
+   cannot be used in HMAC.
 
-  kerberos5 (heimdal):
-   MD5, SHA1
+crypt(password::text, salt::text)::text
 
-ENCRYPTION
+   Calculates UN*X crypt(3) style hash.  Useful for storing
+   passwords.  For generating salt you should use the
+   gen_salt() function.  Usage:
 
-  There is experimental version out with encryption, HMAC
-  and UN*X crypt() support in
+   New password:
+   
+     UPDATE .. SET pswhash = crypt(new_psw, gen_salt('md5'));
+   
+   Authentication:
 
-    http://www.l-t.ee/marko/pgsql/
+     SELECT pswhash = crypt(given_psw, pswhash) WHERE .. ;
+   
+   returns BOOL whether the given_psw is correct.  DES crypt
+   has max key of 8 bytes, MD5 has max key at least 2^32-1
+   bytes but may be larger on some platforms...
 
-  Current latest release is pgcrypto-0.3.tar.gz.
+   Builtin crypt() supports DES, Extended DES, MD5 and Blowfish
+   (variant 2a) algorithms.
+
+gen_salt(type::text)::text
+
+   Generates a new random salt for usage in crypt().  Type
+   
+   'des'   - Old UNIX, not recommended
+   'md5'   - md5-based crypt()
+   'xdes'  - 'Extended DES'
+   'bf'    - Blowfish-based, variant 2a
+
+   When you use --enable-system-crypt then note that system
+   libcrypt may not support them all.
+
+encrypt(data::bytea, key::bytea, type::text)::bytea
+decrypt(data::bytea, key::bytea, type::text)::bytea
+encrypt_iv(data::bytea, key::bytea, iv::bytea, type::text)::bytea
+decrypt_iv(data::bytea, key::bytea, iv::bytea, type::text)::bytea
+
+   Encrypt/decrypt data with cipher, padding data if needed.
+
+   Pseudo-noteup:
+
+   algo ['-' mode] ['/pad:' padding]
+
+   Supported algorithms:
+   
+       bf      - Blowfish
+       aes, rijndael   - Rijndael-128
+
+   Others depend on library and are not tested enough, so
+   play on your own risk.
+
+   Modes: 'cbc' (default), 'ecb'.  Again, library may support
+   more.
+
+   Padding is 'pkcs' (default), 'none'.  'none' is mostly for
+   testing ciphers, you should not need it.
+
+   So, example:
+
+       encrypt(data, 'fooz', 'bf')
+   
+   is equal to
+
+       encrypt(data, 'fooz', 'bf-cbc/pad:pkcs')
+
+   IV is initial value for mode, defaults to all zeroes.
+   It is ignored for ECB.  It is clipped or padded with zeroes
+   if not exactly block size.
+
+
+ALGORITHMS
+==========
+
+The standard functionality at the moment consist of
+
+Hashes: md5, sha1
+Ciphers: bf, aes
+Modes: cbc, ecb
+
+TODO: write stardard names for optional ciphers too.
+
+LIBRARIES
+=========
+
+* crypt()
+
+    internal: des, xdes, md5, bf
+
+    -lcrypt: ??? (whatever you have)
+
+* other:
+
+[ This only list of stuff libraries claim to support.  So
+  pgcrypto may work with all of them.  But ATM tested aree only the
+  standard ciphers.  On others pgcrypto and library may mess something
+  up. You have been warned.  ]
+
+internal (default):
+    Hashes: MD5, SHA1
+    Ciphers: Blowfish, Rijndael-128
+
+
+OpenSSL (0.9.6):
+    Hashes:    MD5, SHA1, RIPEMD160, MD2   
+    Ciphers:   DES, DESX, DES3, RC5, RC4, RC2, IDEA,
+       Blowfish, CAST5
+    License:   BSD-like with strong advertisement
+    Url:   http://www.openssl.org/
+
+
+mhash (0.8.9) + mcrypt (2.4.11):
+    Hashes:    MD5, SHA1, CRC32, CRC32B, GOST, TIGER, RIPEMD160,
+       HAVAL(256,224,192,160,128)
+    Ciphers:   DES, DES3, CAST-128(CAST5), CAST-256, xTEA, 3-way,
+           SKIPJACK, Blowfish, Twofish, LOKI97, RC2, RC4, RC6,
+       Rijndael-128/192/256, MARS, PANAMA, WAKE, Serpent, IDEA, GOST,
+       SAFER, SAFER+, Enigma
+    License:   LGPL
+    Url:   http://mcrypt.sourceforge.org/
+    Url:   http://mhash.sourceforge.org/
+
+CREDITS
+=======
+
+I have used code from following sources:
+
+DES crypt() by David Burren and others FreeBSD libcrypt
+MD5 crypt() by Poul-Henning Kamp   FreeBSD libcrypt
+Blowfish crypt() by Solar Designer www.openwall.com
+Blowfish cipher by Niels Provos        OpenBSD sys/crypto
+Rijndael cipher by Brian Gladman   OpenBSD sys/crypto
+MD5 and SHA1 by WIDE Project       KAME kame/sys/crypto
+
+LEGALESE
+========
+
+* I owe a beer to Poul-Henning.
+
+* This product includes software developed by Niels Provos.
 
 
index 2d4a52717e0228237d20654191cc8adc8efee603..1debd2b3884fa3d08db18ed74834a674a26551cf 100644 (file)
@@ -2,7 +2,7 @@
  * internal.c
  *     Wrapper for builtin functions
  *
- * Copyright (c) 2000 Marko Kreen
+ * Copyright (c) 2001 Marko Kreen
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: internal.c,v 1.3 2001/03/22 03:59:10 momjian Exp $
+ * $Id: internal.c,v 1.4 2001/08/21 00:42:41 momjian Exp $
  */
 
-#include "postgres.h"
 
-#include "pgcrypto.h"
+#include 
+
+#include "px.h"
 
 #include "md5.h"
 #include "sha1.h"
+#include "blf.h"
+#include "rijndael.h"
 
 #ifndef MD5_DIGEST_LENGTH
 #define MD5_DIGEST_LENGTH 16
 #endif
 #endif
 
-static uint
-           pg_md5_len(pg_digest * h);
-static uint8 *
-           pg_md5_digest(pg_digest * h, uint8 *src, uint len, uint8 *buf);
+#define SHA1_BLOCK_SIZE 64
+#define MD5_BLOCK_SIZE 64
 
-static uint
-           pg_sha1_len(pg_digest * h);
-static uint8 *
-           pg_sha1_digest(pg_digest * h, uint8 *src, uint len, uint8 *buf);
-
-static pg_digest
-           int_digest_list[] = {
-   {"md5", pg_md5_len, pg_md5_digest, {0}},
-   {"sha1", pg_sha1_len, pg_sha1_digest, {0}},
-   {NULL, NULL, NULL, {0}}
+static void init_md5(PX_MD * h);
+static void init_sha1(PX_MD * h);
+
+static struct int_digest
+{
+   char       *name;
+   void        (*init) (PX_MD * h);
+} int_digest_list[] =
+{
+   { "md5", init_md5 },
+   { "sha1", init_sha1 },
+   { NULL, NULL }
 };
 
+/* MD5 */
+
 static uint
-pg_md5_len(pg_digest * h)
+int_md5_len(PX_MD * h)
 {
    return MD5_DIGEST_LENGTH;
 }
 
-static uint8 *
-pg_md5_digest(pg_digest * h, uint8 *src, uint len, uint8 *buf)
+static uint
+int_md5_block_len(PX_MD * h)
+{
+   return MD5_BLOCK_SIZE;
+}
+
+static void
+int_md5_update(PX_MD * h, const uint8 * data, uint dlen)
 {
-   MD5_CTX     ctx;
+   MD5_CTX    *ctx = (MD5_CTX *) h->p.ptr;
+
+   MD5Update(ctx, data, dlen);
+}
+
+static void
+int_md5_reset(PX_MD * h)
+{
+   MD5_CTX    *ctx = (MD5_CTX *) h->p.ptr;
+
+   MD5Init(ctx);
+}
+
+static void
+int_md5_finish(PX_MD * h, uint8 * dst)
+{
+   MD5_CTX    *ctx = (MD5_CTX *) h->p.ptr;
+
+   MD5Final(dst, ctx);
+}
 
-   MD5Init(&ctx);
-   MD5Update(&ctx, src, len);
-   MD5Final(buf, &ctx);
+static void
+int_md5_free(PX_MD * h)
+{
+   MD5_CTX    *ctx = (MD5_CTX *) h->p.ptr;
 
-   return buf;
+   px_free(ctx);
+   px_free(h);
 }
 
+/* SHA1 */
+
 static uint
-pg_sha1_len(pg_digest * h)
+int_sha1_len(PX_MD * h)
 {
    return SHA1_DIGEST_LENGTH;
 }
 
-static uint8 *
-pg_sha1_digest(pg_digest * h, uint8 *src, uint len, uint8 *buf)
+static uint
+int_sha1_block_len(PX_MD * h)
+{
+   return SHA1_BLOCK_SIZE;
+}
+
+static void
+int_sha1_update(PX_MD * h, const uint8 * data, uint dlen)
+{
+   SHA1_CTX   *ctx = (SHA1_CTX *) h->p.ptr;
+
+   SHA1Update(ctx, (const char *)data, dlen);
+}
+
+static void
+int_sha1_reset(PX_MD * h)
+{
+   SHA1_CTX   *ctx = (SHA1_CTX *) h->p.ptr;
+
+   SHA1Init(ctx);
+}
+
+static void
+int_sha1_finish(PX_MD * h, uint8 * dst)
+{
+   SHA1_CTX   *ctx = (SHA1_CTX *) h->p.ptr;
+
+   SHA1Final(dst, ctx);
+}
+
+static void
+int_sha1_free(PX_MD * h)
+{
+   SHA1_CTX   *ctx = (SHA1_CTX *) h->p.ptr;
+
+   px_free(ctx);
+   px_free(h);
+}
+
+/* init functions */
+
+static void
+init_md5(PX_MD * md)
+{
+   MD5_CTX    *ctx;
+
+   ctx = px_alloc(sizeof(*ctx));
+
+   md->p.ptr = ctx;
+
+   md->result_size = int_md5_len;
+   md->block_size = int_md5_block_len;
+   md->reset = int_md5_reset;
+   md->update = int_md5_update;
+   md->finish = int_md5_finish;
+   md->free = int_md5_free;
+
+   md->reset(md);
+}
+
+static void
+init_sha1(PX_MD * md)
+{
+   SHA1_CTX   *ctx;
+
+   ctx = px_alloc(sizeof(*ctx));
+
+   md->p.ptr = ctx;
+
+   md->result_size = int_sha1_len;
+   md->block_size = int_sha1_block_len;
+   md->reset = int_sha1_reset;
+   md->update = int_sha1_update;
+   md->finish = int_sha1_finish;
+   md->free = int_sha1_free;
+
+   md->reset(md);
+}
+
+/*
+ * ciphers generally
+ */
+
+#define INT_MAX_KEY        (512/8)
+#define INT_MAX_IV     (128/8)
+
+struct int_ctx {
+   uint8 keybuf[INT_MAX_KEY];
+   uint8 iv[INT_MAX_IV];
+   union {
+       blf_ctx bf;
+       rijndael_ctx rj;
+   } ctx;
+   uint keylen;
+   int is_init;
+   int mode;
+};
+
+static void intctx_free(PX_Cipher *c)
+{
+   struct int_ctx *cx = (struct int_ctx *)c->ptr;
+   if (cx) {
+       memset(cx, 0, sizeof *cx);
+       px_free(cx);
+   }
+   px_free(c);
+}
+
+/*
+ * AES/rijndael
+ */
+
+#define MODE_ECB 0
+#define MODE_CBC 1
+
+static uint rj_block_size(PX_Cipher *c)
+{
+   return 128/8;
+}
+
+static uint rj_key_size(PX_Cipher *c)
+{
+   return 256/8;
+}
+
+static uint rj_iv_size(PX_Cipher *c)
+{
+   return 128/8;
+}
+
+static int rj_init(PX_Cipher *c, const uint8 *key, uint klen, const uint8 *iv)
+{
+   struct int_ctx *cx = (struct int_ctx *)c->ptr;
+
+   if (klen <= 128/8)
+       cx->keylen = 128/8;
+   else if (klen <= 192/8)
+       cx->keylen = 192/8;
+   else if (klen <= 256/8)
+       cx->keylen = 256/8;
+   else
+       return -1;
+
+   memcpy(&cx->keybuf, key, klen);
+
+   if (iv)
+       memcpy(cx->iv, iv, 128/8);
+
+   return 0;
+}
+
+static int rj_real_init(struct int_ctx *cx, int dir)
+{
+   aes_set_key(&cx->ctx.rj, cx->keybuf, cx->keylen*8, dir);
+   return 0;
+}
+
+static int rj_encrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res)
+{
+   struct int_ctx *cx = (struct int_ctx *)c->ptr;
+   
+   if (!cx->is_init) {
+       if (rj_real_init(cx, 1))
+           return -1;
+   }
+   
+   if (dlen == 0)
+       return 0;
+
+   if ((dlen & 15) || (((unsigned)res) & 3))
+       return -1;
+
+   memcpy(res, data, dlen);
+
+   if (cx->mode == MODE_CBC) {
+       aes_cbc_encrypt(&cx->ctx.rj, cx->iv, res, dlen);
+       memcpy(cx->iv, res + dlen - 16, 16);
+   } else
+       aes_ecb_encrypt(&cx->ctx.rj, res, dlen);
+   
+   return 0;
+}
+
+static int rj_decrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res)
+{
+   struct int_ctx *cx = (struct int_ctx *)c->ptr;
+   
+   if (!cx->is_init)
+       if (rj_real_init(cx, 0))
+           return -1;
+
+   if (dlen == 0)
+       return 0;
+
+   if ((dlen & 15) || (((unsigned)res) & 3))
+       return -1;
+
+   memcpy(res, data, dlen);
+
+   if (cx->mode == MODE_CBC) {
+       aes_cbc_decrypt(&cx->ctx.rj, cx->iv, res, dlen);
+       memcpy(cx->iv, data + dlen - 16, 16);
+   } else
+       aes_ecb_decrypt(&cx->ctx.rj, res, dlen);
+   
+   return 0;
+}
+
+/*
+ * initializers
+ */
+
+static PX_Cipher * rj_load(int mode)
+{
+   PX_Cipher *c;
+   struct int_ctx *cx;
+   
+   c = px_alloc(sizeof *c);
+   memset(c, 0, sizeof *c);
+
+   c->block_size = rj_block_size;
+   c->key_size = rj_key_size;
+   c->iv_size = rj_iv_size;
+   c->init = rj_init;
+   c->encrypt = rj_encrypt;
+   c->decrypt = rj_decrypt;
+   c->free = intctx_free;
+
+   cx = px_alloc(sizeof *cx);
+   memset(cx, 0, sizeof *cx);
+   cx->mode = mode;
+
+   c->ptr = cx;
+   return c;
+}
+
+/*
+ * blowfish
+ */
+
+static uint bf_block_size(PX_Cipher *c)
+{
+   return 8;
+}
+
+static uint bf_key_size(PX_Cipher *c)
+{
+   return BLF_MAXKEYLEN;
+}
+
+static uint bf_iv_size(PX_Cipher *c)
+{
+   return 8;
+}
+
+static int bf_init(PX_Cipher *c, const uint8 *key, uint klen, const uint8 *iv)
+{
+   struct int_ctx *cx = (struct int_ctx *)c->ptr;
+
+   blf_key(&cx->ctx.bf, key, klen);
+   if (iv)
+       memcpy(cx->iv, iv, 8);
+
+   return 0;
+}
+
+static int bf_encrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res)
+{
+   struct int_ctx *cx = (struct int_ctx *)c->ptr;
+
+   if (dlen == 0)
+       return 0;
+   
+   if ((dlen & 7) || (((unsigned)res) & 3))
+       return -1;
+
+   memcpy(res, data, dlen);
+   switch (cx->mode) {
+   case MODE_ECB:
+       blf_ecb_encrypt(&cx->ctx.bf, res, dlen);
+       break;
+   case MODE_CBC:
+       blf_cbc_encrypt(&cx->ctx.bf, cx->iv, res, dlen);
+       memcpy(cx->iv, res + dlen - 8, 8);
+   }
+   return 0;
+}
+
+static int bf_decrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res)
+{
+   struct int_ctx *cx = (struct int_ctx *)c->ptr;
+
+   if (dlen == 0)
+       return 0;
+
+   if ((dlen & 7) || (((unsigned)res) & 3))
+       return -1;
+
+   memcpy(res, data, dlen);
+   switch (cx->mode) {
+   case MODE_ECB:
+       blf_ecb_decrypt(&cx->ctx.bf, res, dlen);
+       break;
+   case MODE_CBC:
+       blf_cbc_decrypt(&cx->ctx.bf, cx->iv, res, dlen);
+       memcpy(cx->iv, data + dlen - 8, 8);
+   }
+   return 0;
+}
+
+static PX_Cipher * bf_load(int mode)
+{
+   PX_Cipher *c;
+   struct int_ctx *cx;
+   
+   c = px_alloc(sizeof *c);
+   memset(c, 0, sizeof *c);
+
+   c->block_size = bf_block_size;
+   c->key_size = bf_key_size;
+   c->iv_size = bf_iv_size;
+   c->init = bf_init;
+   c->encrypt = bf_encrypt;
+   c->decrypt = bf_decrypt;
+   c->free = intctx_free;
+
+   cx = px_alloc(sizeof *cx);
+   memset(cx, 0, sizeof *cx);
+   cx->mode = mode;
+   c->ptr = cx;
+   return c;
+}
+
+/* ciphers */
+
+static PX_Cipher * rj_128_ecb()
+{
+   return rj_load(MODE_ECB);
+}
+
+static PX_Cipher * rj_128_cbc()
 {
-   SHA1_CTX    ctx;
+   return rj_load(MODE_CBC);
+}
 
-   SHA1Init(&ctx);
-   SHA1Update(&ctx, src, len);
-   SHA1Final(buf, &ctx);
+static PX_Cipher * bf_ecb_load()
+{
+   return bf_load(MODE_ECB);
+}
 
-   return buf;
+static PX_Cipher * bf_cbc_load()
+{
+   return bf_load(MODE_CBC);
 }
 
+static struct {
+   char *name;
+   PX_Cipher *(*load)(void);
+} int_ciphers [] = {
+   { "bf-cbc", bf_cbc_load },
+   { "bf-ecb", bf_ecb_load },
+   { "aes-128-cbc", rj_128_cbc },
+   { "aes-128-ecb", rj_128_ecb },
+   { NULL, NULL }
+};
+
+static PX_Alias int_aliases [] = {
+   { "bf", "bf-cbc" },
+   { "blowfish", "bf-cbc" },
+   { "aes", "aes-128-cbc" },
+   { "aes-ecb", "aes-128-ecb" },
+   { "aes-cbc", "aes-128-cbc" },
+   { "aes-128", "aes-128-cbc" },
+   { "rijndael", "aes-128-cbc" },
+   { "rijndael-128", "aes-128-cbc" },
+   { NULL, NULL }
+};
 
-pg_digest  *
-pg_find_digest(pg_digest * h, char *name)
+/* PUBLIC FUNCTIONS */
+
+int
+px_find_digest(const char *name, PX_MD ** res)
 {
-   pg_digest  *p;
+   struct int_digest *p;
+   PX_MD      *h;
 
    for (p = int_digest_list; p->name; p++)
        if (!strcasecmp(p->name, name))
-           return p;
-   return NULL;
+       {
+           h = px_alloc(sizeof(*h));
+           p->init(h);
+
+           *res = h;
+
+           return 0;
+       }
+   return -1;
+}
+
+int
+px_find_cipher(const char *name, PX_Cipher **res)
+{
+   int i;
+   PX_Cipher *c = NULL;
+
+   name = px_resolve_alias(int_aliases, name);
+
+   for (i = 0; int_ciphers[i].name; i++)
+       if (!strcmp(int_ciphers[i].name, name)) {
+           c = int_ciphers[i].load();
+           break;
+       }
+
+   if (c == NULL)
+       return -1;
+
+   *res = c;
+   return 0;
 }
+
+
index a5cfae34970332707f431100a5228159d73236a0..3ae9d099824839fcfb4281441befac379a745b20 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: md5.c,v 1.5 2001/03/22 03:59:10 momjian Exp $  */
+/* $Id: md5.c,v 1.6 2001/08/21 00:42:41 momjian Exp $  */
 /*    $KAME: md5.c,v 1.3 2000/02/22 14:01:17 itojun Exp $     */
 
 /*
@@ -128,8 +128,7 @@ static const uint8 md5_paddat[MD5_BUFLEN] = {
 static void md5_calc(uint8 *, md5_ctxt *);
 
 void
-md5_init(ctxt)
-md5_ctxt   *ctxt;
+md5_init(md5_ctxt *ctxt)
 {
    ctxt->md5_n = 0;
    ctxt->md5_i = 0;
@@ -141,10 +140,7 @@ md5_ctxt   *ctxt;
 }
 
 void
-md5_loop(ctxt, input, len)
-md5_ctxt   *ctxt;
-uint8     *input;
-unsigned int len;              /* number of bytes */
+md5_loop(md5_ctxt *ctxt, const uint8 *input, unsigned len)
 {
    unsigned int gap,
                i;
@@ -173,8 +169,7 @@ unsigned int len;               /* number of bytes */
 }
 
 void
-md5_pad(ctxt)
-md5_ctxt   *ctxt;
+md5_pad(md5_ctxt *ctxt)
 {
    unsigned int gap;
 
@@ -216,9 +211,7 @@ md5_ctxt   *ctxt;
 }
 
 void
-md5_result(digest, ctxt)
-uint8     *digest;
-md5_ctxt   *ctxt;
+md5_result(uint8 *digest, md5_ctxt *ctxt)
 {
    /* 4 byte words */
 #if BYTE_ORDER == LITTLE_ENDIAN
@@ -245,14 +238,11 @@ md5_ctxt   *ctxt;
 }
 
 #if BYTE_ORDER == BIG_ENDIAN
-uint32     X[16];
-
+static uint32      X[16];
 #endif
 
 static void
-md5_calc(b64, ctxt)
-uint8     *b64;
-md5_ctxt   *ctxt;
+md5_calc(uint8 *b64, md5_ctxt *ctxt)
 {
    uint32      A = ctxt->md5_sta;
    uint32      B = ctxt->md5_stb;
@@ -261,7 +251,6 @@ md5_ctxt   *ctxt;
 
 #if BYTE_ORDER == LITTLE_ENDIAN
    uint32     *X = (uint32 *) b64;
-
 #endif
 #if BYTE_ORDER == BIG_ENDIAN
    /* 4 byte words */
index 54ca2558dff0f2e803ff7f2e813008676b502221..868f8a233a0961e06ca82ec063bd49ac4c6bdcff 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: md5.h,v 1.4 2001/03/22 03:59:10 momjian Exp $  */
+/* $Id: md5.h,v 1.5 2001/08/21 00:42:41 momjian Exp $  */
 /*    $KAME: md5.h,v 1.3 2000/02/22 14:01:18 itojun Exp $     */
 
 /*
@@ -62,7 +62,7 @@ typedef struct
 }          md5_ctxt;
 
 extern void md5_init(md5_ctxt *);
-extern void md5_loop(md5_ctxt *, uint8 *, unsigned int);
+extern void md5_loop(md5_ctxt *, const uint8 *, unsigned int);
 extern void md5_pad(md5_ctxt *);
 extern void md5_result(uint8 *, md5_ctxt *);
 
@@ -75,5 +75,4 @@ do {              \
    md5_pad((y));       \
    md5_result((x), (y));   \
 } while (0)
-
 #endif  /* ! _NETINET6_MD5_H_ */
index d6ada96d149eca11499bb42a87770de021f88062..36d70471a99db2408ed9d030554a65a5b609ea5b 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * mhash.c
- *     Wrapper for mhash library.
+ *     Wrapper for mhash and mcrypt libraries.
  *
- * Copyright (c) 2000 Marko Kreen
+ * Copyright (c) 2001 Marko Kreen
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: mhash.c,v 1.3 2001/03/22 03:59:10 momjian Exp $
+ * $Id: mhash.c,v 1.4 2001/08/21 00:42:41 momjian Exp $
  */
 
-#include "postgres.h"
+#include 
 
-#include "pgcrypto.h"
+#include "px.h"
 
 #include 
+#include 
+
+#define MAX_KEY_LENGTH 512
+#define MAX_IV_LENGTH 128
+
+#define DEF_KEY_LEN 16
 
-static uint
-           pg_mhash_len(pg_digest * hash);
-static uint8 *pg_mhash_digest(pg_digest * hash, uint8 *src,
-               uint len, uint8 *buf);
+
+/* DIGEST */
 
 static uint
-pg_mhash_len(pg_digest * h)
+digest_result_size(PX_MD * h)
 {
-   return mhash_get_block_size(h->misc.code);
+   MHASH       mh = (MHASH) h->p.ptr;
+   hashid      id = mhash_get_mhash_algo(mh);
+
+   return mhash_get_block_size(id);
 }
 
-static uint8 *
-pg_mhash_digest(pg_digest * h, uint8 *src, uint len, uint8 *dst)
+static uint
+digest_block_size(PX_MD * h)
 {
-   uint8      *res;
+   MHASH       mh = (MHASH) h->p.ptr;
+   hashid      id = mhash_get_mhash_algo(mh);
 
-   MHASH       mh = mhash_init(h->misc.code);
+   return mhash_get_hash_pblock(id);
+}
 
-   mhash(mh, src, len);
-   res = mhash_end(mh);
+static void
+digest_reset(PX_MD * h)
+{
+   MHASH       mh = (MHASH) h->p.ptr;
+   hashid      id = mhash_get_mhash_algo(mh);
+   uint8      *res = mhash_end(mh);
 
-   memcpy(dst, res, mhash_get_block_size(h->misc.code));
    mhash_free(res);
+   mh = mhash_init(id);
+   h->p.ptr = mh;
+}
+
+static void
+digest_update(PX_MD * h, const uint8 * data, uint dlen)
+{
+   MHASH       mh = (MHASH) h->p.ptr;
+
+   mhash(mh, data, dlen);
+}
+
+static void
+digest_finish(PX_MD * h, uint8 * dst)
+{
+   MHASH       mh = (MHASH) h->p.ptr;
+   uint        hlen = digest_result_size(h);
+   hashid      id = mhash_get_mhash_algo(mh);
+   uint8      *buf = mhash_end(mh);
+
+   memcpy(dst, buf, hlen);
+   mhash_free(buf);
+
+   mh = mhash_init(id);
+   h->p.ptr = mh;
+}
+
+static void
+digest_free(PX_MD * h)
+{
+   MHASH       mh = (MHASH) h->p.ptr;
+   uint8      *buf = mhash_end(mh);
+
+   mhash_free(buf);
+
+   px_free(h);
+}
+
+/* ENCRYPT / DECRYPT */
+
+static uint
+cipher_block_size(PX_Cipher *c)
+{
+   MCRYPT ctx = (MCRYPT)c->ptr;
+   return mcrypt_enc_get_block_size(ctx);
+}
+
+static uint
+cipher_key_size(PX_Cipher *c)
+{
+   MCRYPT ctx = (MCRYPT)c->ptr;
+   return mcrypt_enc_get_key_size(ctx);
+}
+
+static uint
+cipher_iv_size(PX_Cipher *c)
+{
+   MCRYPT ctx = (MCRYPT)c->ptr;
+   return mcrypt_enc_mode_has_iv(ctx)
+       ? mcrypt_enc_get_iv_size(ctx) : 0;
+}
+
+static int
+cipher_init(PX_Cipher *c, const uint8 *key, uint klen, const uint8 *iv)
+{
+   int err;
+   MCRYPT ctx = (MCRYPT)c->ptr;
+
+   err = mcrypt_generic_init(ctx, (char *)key, klen, (char*)iv);
+   if (err < 0)
+       elog(ERROR, "mcrypt_generic_init error: %s", mcrypt_strerror(err));
+
+   c->pstat = 1;
+   return 0;
+}
+
+static int
+cipher_encrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res)
+{
+   int err;
+   MCRYPT ctx = (MCRYPT)c->ptr;
 
-   return dst;
+   memcpy(res, data, dlen);
+
+   err = mcrypt_generic(ctx, res, dlen);
+   if (err < 0)
+       elog(ERROR, "mcrypt_generic error: %s", mcrypt_strerror(err));
+   return 0;
+}
+
+static int
+cipher_decrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res)
+{
+   int err;
+   MCRYPT ctx = (MCRYPT)c->ptr;
+
+   memcpy(res, data, dlen);
+
+   err = mdecrypt_generic(ctx, res, dlen);
+   if (err < 0)
+       elog(ERROR, "mdecrypt_generic error: %s", mcrypt_strerror(err));
+   return 0;
+}
+
+
+static void
+cipher_free(PX_Cipher *c)
+{
+   MCRYPT ctx = (MCRYPT)c->ptr;
+
+   if (c->pstat)
+       mcrypt_generic_end(ctx);
+   else
+       mcrypt_module_close(ctx);
+   
+   px_free(c);
 }
 
-pg_digest  *
-pg_find_digest(pg_digest * h, char *name)
+/* Helper functions */
+
+static int
+find_hashid(const char *name)
 {
+   int         res = -1;
    size_t      hnum,
-               i,
-               b;
+               b,
+               i;
    char       *mname;
 
    hnum = mhash_count();
@@ -80,12 +209,134 @@ pg_find_digest(pg_digest * h, char *name)
        free(mname);
        if (!b)
        {
-           h->name = mhash_get_hash_name(i);
-           h->length = pg_mhash_len;
-           h->digest = pg_mhash_digest;
-           h->misc.code = i;
-           return h;
+           res = i;
+           break;
        }
    }
-   return NULL;
+
+   return res;
 }
+
+static char *modes[] = {
+   "ecb", "cbc", "cfb", "ofb", "nofb", "stream",
+   "ofb64", "cfb64", NULL
+};
+
+static PX_Alias aliases[] = {
+   {"bf", "blowfish" },
+   {"3des", "tripledes" },
+   {"des3", "tripledes" },
+   {"aes", "rijndael-128" },
+   {"rijndael", "rijndael-128" },
+   {"aes-128", "rijndael-128" },
+   {"aes-192", "rijndael-192" },
+   {"aes-256", "rijndael-256" },
+   { NULL, NULL }
+};
+
+static PX_Alias mode_aliases[] = {
+#if 0 /* N/A */
+   { "cfb", "ncfb" },
+   { "ofb", "nofb" },
+   { "cfb64", "ncfb" },
+#endif
+   /* { "ofb64", "nofb" }, not sure it works */
+   { "cfb8", "cfb" },
+   { "ofb8", "ofb" },
+   { NULL, NULL }
+};
+
+static int is_mode(char *s)
+{
+   char **p;
+   
+   if (*s >= '0' && *s <= '9')
+       return 0;
+
+   for (p = modes; *p; p++)
+       if (!strcmp(s, *p))
+           return 1;
+
+   return 0;
+}
+
+/* PUBLIC FUNCTIONS */
+
+int
+px_find_digest(const char *name, PX_MD **res)
+{
+   PX_MD      *h;
+   MHASH       mh;
+   int         i;
+
+   i = find_hashid(name);
+   if (i < 0)
+       return -1;
+
+   mh = mhash_init(i);
+   h = px_alloc(sizeof(*h));
+   h->p.ptr = (void *) mh;
+
+   h->result_size = digest_result_size;
+   h->block_size = digest_block_size;
+   h->reset = digest_reset;
+   h->update = digest_update;
+   h->finish = digest_finish;
+   h->free = digest_free;
+
+   *res = h;
+   return 0;
+}
+
+
+int
+px_find_cipher(const char *name, PX_Cipher **res)
+{
+   char nbuf[PX_MAX_NAMELEN + 1];
+   const char *mode = NULL;
+   char *p;
+   MCRYPT ctx;
+
+   PX_Cipher *c;
+
+   strcpy(nbuf, name);
+   
+   if ((p = strrchr(nbuf, '-')) != NULL) {
+       if (is_mode(p + 1)) {
+           mode = p + 1;
+           *p = 0;
+       }
+   }
+
+   name = px_resolve_alias(aliases, nbuf);
+
+   if (!mode) {
+       mode = "cbc";
+       /*
+       if (mcrypt_module_is_block_algorithm(name, NULL))
+           mode = "cbc";
+       else
+           mode = "stream";
+       */
+   }
+   mode = px_resolve_alias(mode_aliases, mode);
+   
+   ctx = mcrypt_module_open((char*)name, NULL, (char*)mode, NULL);
+   if (ctx == (void*)MCRYPT_FAILED)
+       return -1;
+
+   c = palloc(sizeof *c);
+   c->iv_size = cipher_iv_size;
+   c->key_size = cipher_key_size;
+   c->block_size = cipher_block_size;
+   c->init = cipher_init;
+   c->encrypt = cipher_encrypt;
+   c->decrypt = cipher_decrypt;
+   c->free = cipher_free;
+   c->ptr = ctx;
+   c->pstat = 0;
+
+   *res = c;
+   return 0;
+}
+
index 866d26f0ffcf04453c8759ee62ba66ea0fc40508..b4d1a0a5e9badb8993b893731bf3a779d3b2c240 100644 (file)
@@ -2,7 +2,7 @@
  * openssl.c
  *     Wrapper for OpenSSL library.
  *
- * Copyright (c) 2000 Marko Kreen
+ * Copyright (c) 2001 Marko Kreen
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: openssl.c,v 1.3 2001/03/22 03:59:10 momjian Exp $
+ * $Id: openssl.c,v 1.4 2001/08/21 00:42:41 momjian Exp $
  */
 
-#include "postgres.h"
+#include 
 
-#include "pgcrypto.h"
+#include "px.h"
 
-#include 
+#include 
+#include 
+/*#include */
 
 static uint
-           pg_ossl_len(pg_digest * h);
-static uint8 *
-           pg_ossl_digest(pg_digest * h, uint8 *src, uint len, uint8 *buf);
+digest_result_size(PX_MD * h)
+{
+   return EVP_MD_CTX_size((EVP_MD_CTX *) h->p.ptr);
+}
 
 static uint
-pg_ossl_len(pg_digest * h)
+digest_block_size(PX_MD * h)
 {
-   return EVP_MD_size((EVP_MD *) h->misc.ptr);
+   return EVP_MD_CTX_block_size((EVP_MD_CTX *) h->p.ptr);
+}
+
+static void
+digest_reset(PX_MD * h)
+{
+   EVP_MD_CTX *ctx = (EVP_MD_CTX *) h->p.ptr;
+   const EVP_MD *md;
+
+   md = EVP_MD_CTX_md(ctx);
+
+   EVP_DigestInit(ctx, md);
 }
 
-static uint8 *
-pg_ossl_digest(pg_digest * h, uint8 *src, uint len, uint8 *buf)
+static void
+digest_update(PX_MD * h, const uint8 * data, uint dlen)
 {
-   EVP_MD     *md = (EVP_MD *) h->misc.ptr;
-   EVP_MD_CTX  ctx;
+   EVP_MD_CTX *ctx = (EVP_MD_CTX *) h->p.ptr;
+
+   EVP_DigestUpdate(ctx, data, dlen);
+}
 
-   EVP_DigestInit(&ctx, md);
-   EVP_DigestUpdate(&ctx, src, len);
-   EVP_DigestFinal(&ctx, buf, NULL);
+static void
+digest_finish(PX_MD * h, uint8 * dst)
+{
+   EVP_MD_CTX *ctx = (EVP_MD_CTX *) h->p.ptr;
 
-   return buf;
+   EVP_DigestFinal(ctx, dst, NULL);
 }
 
-static int pg_openssl_initialized = 0;
+static void
+digest_free(PX_MD * h)
+{
+   EVP_MD_CTX *ctx = (EVP_MD_CTX *) h->p.ptr;
+
+   px_free(ctx);
+   px_free(h);
+}
+
+/* CIPHERS */
+
+/*
+ * The problem with OpenSSL is that the EVP* family
+ * of functions does not allow enough flexibility
+ * and forces some of the parameters (keylen,
+ * padding) to SSL defaults.
+ */
+
+
+typedef struct {
+   union {
+       struct {
+           BF_KEY key;
+           int num;
+       } bf;
+       EVP_CIPHER_CTX evp_ctx;
+   } u;
+   const EVP_CIPHER *evp_ciph;
+   uint8 key[EVP_MAX_KEY_LENGTH];
+   uint8 iv[EVP_MAX_IV_LENGTH];
+   uint klen;
+   uint init;
+} ossldata;
+
+/* generic EVP */
+
+static uint
+gen_evp_block_size(PX_Cipher *c)
+{
+   ossldata *od = (ossldata *)c->ptr;
+   return EVP_CIPHER_block_size(od->evp_ciph);
+}
+
+static uint
+gen_evp_key_size(PX_Cipher *c)
+{
+   ossldata *od = (ossldata *)c->ptr;
+   return EVP_CIPHER_key_length(od->evp_ciph);
+}
+
+static uint
+gen_evp_iv_size(PX_Cipher *c)
+{
+   uint ivlen;
+   ossldata *od = (ossldata *)c->ptr;
+   ivlen = EVP_CIPHER_iv_length(od->evp_ciph);
+   return ivlen;
+}
+
+static void
+gen_evp_free(PX_Cipher *c)
+{
+   ossldata *od = (ossldata*)c->ptr;
+   memset(od, 0, sizeof(*od));
+   pfree(od);
+   pfree(c);
+}
+
+/* fun */
+
+static int
+gen_evp_init(PX_Cipher *c, const uint8 *key, uint klen, const uint8 *iv)
+{
+   ossldata *od = (ossldata*)c->ptr;
+   uint bs = gen_evp_block_size(c);
+   if (iv) {
+       memcpy(od->iv, iv, bs);
+   } else
+       memset(od->iv, 0, bs);
+   memcpy(od->key, key, klen);
+   od->klen = klen;
+   od->init = 0;
+   return 0;
+}
+
+static void
+_gen_init(PX_Cipher *c, int enc)
+{
+   ossldata *od = c->ptr;
+   
+   od->evp_ciph->init(&od->u.evp_ctx, od->key, od->iv, enc);
+   od->init = 1;
+   od->u.evp_ctx.encrypt = enc;
+}
+
+static int
+gen_evp_encrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res)
+{
+   ossldata *od = c->ptr;
+   if (!od->init)
+       _gen_init(c, 1);
+   od->evp_ciph->do_cipher(&od->u.evp_ctx, res, data, dlen);
+   return 0;
+}
+
+static int
+gen_evp_decrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res)
+{
+   ossldata *od = c->ptr;
+   if (!od->init)
+       _gen_init(c, 0);
+   od->evp_ciph->do_cipher(&od->u.evp_ctx, res, data, dlen);
+   return 0;
+}
+
+/* Blowfish */
+
+static int
+bf_init(PX_Cipher *c, const uint8 *key, uint klen, const uint8 *iv)
+{
+   ossldata *od = c->ptr;
+   BF_set_key(&od->u.bf.key, klen, key);
+   if (iv) {
+       memcpy(od->iv, iv, BF_BLOCK);
+   } else
+       memset(od->iv, 0, BF_BLOCK);
+   od->u.bf.num = 0;
+   return 0;
+}
 
-pg_digest  *
-pg_find_digest(pg_digest * h, char *name)
+static int
+bf_ecb_encrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res)
+{
+   uint bs = gen_evp_block_size(c), i;
+   ossldata *od = c->ptr;
+   for (i = 0; i < dlen / bs; i++)
+       BF_ecb_encrypt(data+i*bs, res+i*bs, &od->u.bf.key, BF_ENCRYPT);
+   return 0;
+}
+
+static int
+bf_ecb_decrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res)
+{
+   uint bs = gen_evp_block_size(c), i;
+   ossldata *od = c->ptr;
+   for (i = 0; i < dlen / bs; i++)
+       BF_ecb_encrypt(data+i*bs, res+i*bs, &od->u.bf.key, BF_DECRYPT);
+   return 0;
+}
+
+static int
+bf_cbc_encrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res)
+{
+   ossldata *od = c->ptr;
+   BF_cbc_encrypt(data, res, dlen, &od->u.bf.key, od->iv, BF_ENCRYPT);
+   return 0;
+}
+
+static int
+bf_cbc_decrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res)
+{
+   ossldata *od = c->ptr;
+   BF_cbc_encrypt(data, res, dlen, &od->u.bf.key, od->iv, BF_DECRYPT);
+   return 0;
+}
+
+static int
+bf_cfb64_encrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res)
+{
+   ossldata *od = c->ptr;
+   BF_cfb64_encrypt(data, res, dlen, &od->u.bf.key, od->iv,
+           &od->u.bf.num, BF_ENCRYPT);
+   return 0;
+}
+
+static int
+bf_cfb64_decrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res)
+{
+   ossldata *od = c->ptr;
+   BF_cfb64_encrypt(data, res, dlen, &od->u.bf.key, od->iv,
+           &od->u.bf.num, BF_DECRYPT);
+   return 0;
+}
+
+static int
+bf_ofb64_encrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res)
+{
+   ossldata *od = c->ptr;
+   BF_ofb64_encrypt(data, res, dlen, &od->u.bf.key, od->iv, &od->u.bf.num);
+   return 0;
+}
+
+static int
+bf_ofb64_decrypt(PX_Cipher *c, const uint8 *data, uint dlen, uint8 *res)
+{
+   ossldata *od = c->ptr;
+   BF_ofb64_encrypt(data, res, dlen, &od->u.bf.key, od->iv, &od->u.bf.num);
+   return 0;
+}
+
+/*
+ * aliases
+ */
+
+static PX_Alias ossl_aliases [] = {
+   { "bf", "bf-cbc" },
+   { "blowfish", "bf-cbc" },
+   { "blowfish-cbc", "bf-cbc" },
+   { "blowfish-ecb", "bf-ecb" },
+   { "blowfish-cfb", "bf-cfb" },
+   { "blowfish-ofb", "bf-ofb" },
+   { NULL }
+};
+
+/*
+static PX_Alias ossl_mode_aliases [] = {
+   { "cfb64", "cfb" },
+   { "ofb64", "ofb" },
+   { NULL }
+};*/
+
+/*
+ * Special handlers
+ */
+struct {
+   char *name;
+   PX_Cipher cf;
+} spec_types [] = {
+  { "bf-cbc", { gen_evp_block_size, gen_evp_key_size, gen_evp_iv_size,
+       bf_init, bf_cbc_encrypt, bf_cbc_decrypt, gen_evp_free}},
+  { "bf-ecb", { gen_evp_block_size, gen_evp_key_size, gen_evp_iv_size,
+           bf_init, bf_ecb_encrypt, bf_ecb_decrypt, gen_evp_free}},
+  { "bf-cfb", { gen_evp_block_size, gen_evp_key_size, gen_evp_iv_size,
+         bf_init, bf_cfb64_encrypt, bf_cfb64_decrypt, gen_evp_free}},
+  { "bf-ofb", { gen_evp_block_size, gen_evp_key_size, gen_evp_iv_size,
+         bf_init, bf_ofb64_encrypt, bf_ofb64_decrypt, gen_evp_free}},
+  { NULL }
+};
+
+/*
+ * Generic EVP_* functions handler
+ */
+static PX_Cipher gen_evp_handler = {
+   gen_evp_block_size, gen_evp_key_size, gen_evp_iv_size,
+   gen_evp_init, gen_evp_encrypt, gen_evp_decrypt, gen_evp_free
+};
+
+static int px_openssl_initialized = 0;
+
+/* ATM not needed
+static void *o_alloc(uint s) { return px_alloc(s); }
+static void *o_realloc(void *p) { return px_realloc(p); }
+static void o_free(void *p) { px_free(p); }
+*/
+
+/* PUBLIC functions */
+
+int
+px_find_digest(const char *name, PX_MD **res)
 {
    const EVP_MD *md;
+   EVP_MD_CTX *ctx;
+   PX_MD      *h;
 
-   if (!pg_openssl_initialized)
+   if (!px_openssl_initialized)
    {
-       OpenSSL_add_all_digests();
-       pg_openssl_initialized = 1;
+       px_openssl_initialized = 1;
+       /*CRYPTO_set_mem_functions(o_alloc, o_realloc, o_free);*/
+       OpenSSL_add_all_algorithms();
    }
 
    md = EVP_get_digestbyname(name);
    if (md == NULL)
-       return NULL;
+       return -1;
 
-   h->name = name;
-   h->length = pg_ossl_len;
-   h->digest = pg_ossl_digest;
-   h->misc.ptr = (void *) md;
+   ctx = px_alloc(sizeof(*ctx));
+   EVP_DigestInit(ctx, md);
 
-   return h;
+   h = px_alloc(sizeof(*h));
+   h->result_size = digest_result_size;
+   h->block_size = digest_block_size;
+   h->reset = digest_reset;
+   h->update = digest_update;
+   h->finish = digest_finish;
+   h->free = digest_free;
+   h->p.ptr = (void *) ctx;
+
+   *res = h;
+   return 0;
 }
+
+
+int
+px_find_cipher(const char *name, PX_Cipher **res)
+{
+   uint i;
+   PX_Cipher *c = NULL, *csrc;
+   ossldata *od;
+
+   const EVP_CIPHER *evp_c;
+
+   if (!px_openssl_initialized) {
+       px_openssl_initialized = 1;
+       /*CRYPTO_set_mem_functions(o_alloc, o_realloc, o_free);*/
+       OpenSSL_add_all_algorithms();
+   }
+
+   name = px_resolve_alias(ossl_aliases, name);
+   evp_c = EVP_get_cipherbyname(name);
+   if (evp_c == NULL)
+       return -1;
+
+   od = px_alloc(sizeof(*od));
+   memset(od, 0, sizeof(*od));
+   od->evp_ciph = evp_c;
+   
+   csrc = NULL;
+
+   for (i = 0; spec_types[i].name; i++)
+       if (!strcmp(name, spec_types[i].name)) {
+           csrc = &spec_types[i].cf;
+           break;
+       }
+   
+   if (csrc == NULL)
+       csrc = &gen_evp_handler;
+
+   c = px_alloc(sizeof(*c));
+   memcpy(c, csrc, sizeof(*c));
+   c->ptr = od;
+   
+   *res = c;
+   return 0;
+}
+
index 31e5a845bd6686baf4ed77d26653e35f48c950e1..4a2f37d95bef1798c12abb4f55e62ee8765ad7a5 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * pgcrypto.c
- *     Cryptographic digests for PostgreSQL.
+ *     Various cryptographic stuff for PostgreSQL.
  *
- * Copyright (c) 2000 Marko Kreen
+ * Copyright (c) 2001 Marko Kreen
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: pgcrypto.c,v 1.7 2001/03/22 03:59:10 momjian Exp $
+ * $Id: pgcrypto.c,v 1.8 2001/08/21 00:42:41 momjian Exp $
  */
 
-#include "postgres.h"
-
-#include "utils/builtins.h"
+#include 
+#include 
+#include 
 
+#include "px.h"
+#include "px-crypt.h"
 #include "pgcrypto.h"
 
-/*
- * NAMEDATALEN is used for hash names
- */
-#if NAMEDATALEN < 16
-#error "NAMEDATALEN < 16: too small"
-#endif
-
-
-/* exported functions */
-Datum      digest(PG_FUNCTION_ARGS);
-Datum      digest_exists(PG_FUNCTION_ARGS);
-
 /* private stuff */
-static pg_digest *
-           find_digest(pg_digest * hbuf, text *name, int silent);
 
+typedef int (*PFN) (const char *name, void **res);
+static void *
+           find_provider(text * name, PFN pf, char *desc, int silent);
 
 /* SQL function: hash(text, text) returns text */
-PG_FUNCTION_INFO_V1(digest);
+PG_FUNCTION_INFO_V1(pg_digest);
 
 Datum
-digest(PG_FUNCTION_ARGS)
+pg_digest(PG_FUNCTION_ARGS)
 {
-   text       *arg;
+   bytea      *arg;
    text       *name;
    uint        len,
                hlen;
-   pg_digest  *h,
-               _hbuf;
-   text       *res;
+   PX_MD      *md;
+   bytea      *res;
 
    if (PG_ARGISNULL(0) || PG_ARGISNULL(1))
        PG_RETURN_NULL();
 
    name = PG_GETARG_TEXT_P(1);
-   h = find_digest(&_hbuf, name, 0);   /* will give error if fails */
 
-   hlen = h->length(h);
+   /* will give error if fails */
+   md = find_provider(name, (PFN) px_find_digest, "Digest", 0);
+
+   hlen = px_md_result_size(md);
 
    res = (text *) palloc(hlen + VARHDRSZ);
    VARATT_SIZEP(res) = hlen + VARHDRSZ;
 
-   arg = PG_GETARG_TEXT_P(0);
+   arg = PG_GETARG_BYTEA_P(0);
    len = VARSIZE(arg) - VARHDRSZ;
 
-   h->digest(h, VARDATA(arg), len, VARDATA(res));
+   px_md_update(md, VARDATA(arg), len);
+   px_md_finish(md, VARDATA(res));
+   px_md_free(md);
 
    PG_FREE_IF_COPY(arg, 0);
    PG_FREE_IF_COPY(name, 1);
 
-   PG_RETURN_TEXT_P(res);
+   PG_RETURN_BYTEA_P(res);
 }
 
 /* check if given hash exists */
-PG_FUNCTION_INFO_V1(digest_exists);
+PG_FUNCTION_INFO_V1(pg_digest_exists);
 
 Datum
-digest_exists(PG_FUNCTION_ARGS)
+pg_digest_exists(PG_FUNCTION_ARGS)
 {
    text       *name;
-   pg_digest   _hbuf,
-              *res;
+   PX_MD      *res;
 
    if (PG_ARGISNULL(0))
        PG_RETURN_NULL();
 
    name = PG_GETARG_TEXT_P(0);
 
-   res = find_digest(&_hbuf, name, 1);
+   res = find_provider(name, (PFN) px_find_digest, "Digest", 1);
 
    PG_FREE_IF_COPY(name, 0);
 
-   if (res != NULL)
+   if (res == NULL)
+       PG_RETURN_BOOL(false);
+
+   res->free(res);
+
+   PG_RETURN_BOOL(true);
+}
+
+/* SQL function: hmac(data:text, key:text, type:text) */
+PG_FUNCTION_INFO_V1(pg_hmac);
+
+Datum
+pg_hmac(PG_FUNCTION_ARGS)
+{
+   bytea      *arg;
+   bytea      *key;
+   text       *name;
+   uint        len,
+               hlen,
+               klen;
+   PX_HMAC    *h;
+   bytea      *res;
+
+   if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2))
+       PG_RETURN_NULL();
+
+   name = PG_GETARG_TEXT_P(2);
+
+   /* will give error if fails */
+   h = find_provider(name, (PFN) px_find_hmac, "HMAC", 0);
+
+   hlen = px_hmac_result_size(h);
+
+   res = (text *) palloc(hlen + VARHDRSZ);
+   VARATT_SIZEP(res) = hlen + VARHDRSZ;
+
+   arg = PG_GETARG_BYTEA_P(0);
+   key = PG_GETARG_BYTEA_P(1);
+   len = VARSIZE(arg) - VARHDRSZ;
+   klen = VARSIZE(key) - VARHDRSZ;
+
+   px_hmac_init(h, VARDATA(key), klen);
+   px_hmac_update(h, VARDATA(arg), len);
+   px_hmac_finish(h, VARDATA(res));
+   px_hmac_free(h);
+
+   PG_FREE_IF_COPY(arg, 0);
+   PG_FREE_IF_COPY(key, 1);
+   PG_FREE_IF_COPY(name, 2);
+
+   PG_RETURN_BYTEA_P(res);
+}
+
+/* check if given hmac type exists */
+PG_FUNCTION_INFO_V1(pg_hmac_exists);
+
+Datum
+pg_hmac_exists(PG_FUNCTION_ARGS)
+{
+   text       *name;
+   PX_HMAC    *h;
+
+   if (PG_ARGISNULL(0))
+       PG_RETURN_NULL();
+
+   name = PG_GETARG_TEXT_P(0);
+
+   h = find_provider(name, (PFN) px_find_hmac, "HMAC", 1);
+
+   PG_FREE_IF_COPY(name, 0);
+
+   if (h != NULL)
+   {
+       px_hmac_free(h);
        PG_RETURN_BOOL(true);
+   }
    PG_RETURN_BOOL(false);
 }
 
-static pg_digest *
-find_digest(pg_digest * hbuf, text *name, int silent)
+
+/* SQL function: pg_gen_salt(text) returns text */
+PG_FUNCTION_INFO_V1(pg_gen_salt);
+
+Datum
+pg_gen_salt(PG_FUNCTION_ARGS)
+{
+   text       *arg0;
+   uint        len;
+   text       *res;
+   char        buf[PX_MAX_SALT_LEN + 1];
+
+   if (PG_ARGISNULL(0))
+       PG_RETURN_NULL();
+
+   arg0 = PG_GETARG_TEXT_P(0);
+
+   len = VARSIZE(arg0) - VARHDRSZ;
+   len = len > PX_MAX_SALT_LEN ? PX_MAX_SALT_LEN : len;
+   memcpy(buf, VARDATA(arg0), len);
+   buf[len] = 0;
+   len = px_gen_salt(buf, buf);
+   if (len == 0)
+       elog(ERROR, "No such crypt algorithm");
+
+   res = (text *) palloc(len + VARHDRSZ);
+   VARATT_SIZEP(res) = len + VARHDRSZ;
+   memcpy(VARDATA(res), buf, len);
+
+   PG_FREE_IF_COPY(arg0, 0);
+
+   PG_RETURN_TEXT_P(res);
+}
+
+/* SQL function: pg_crypt(psw:text, salt:text) returns text */
+PG_FUNCTION_INFO_V1(pg_crypt);
+
+Datum
+pg_crypt(PG_FUNCTION_ARGS)
+{
+   text       *arg0;
+   text       *arg1;
+   uint        len0,
+               len1,
+               clen;
+   char       *buf0,
+              *buf1,
+              *cres,
+              *resbuf;
+   text       *res;
+
+   if (PG_ARGISNULL(0) || PG_ARGISNULL(1))
+       PG_RETURN_NULL();
+
+   arg0 = PG_GETARG_TEXT_P(0);
+   arg1 = PG_GETARG_TEXT_P(1);
+   len0 = VARSIZE(arg0) - VARHDRSZ;
+   len1 = VARSIZE(arg1) - VARHDRSZ;
+
+   buf0 = palloc(len0 + 1);
+   buf1 = palloc(len1 + 1);
+
+   memcpy(buf0, VARDATA(arg0), len0);
+   memcpy(buf1, VARDATA(arg1), len1);
+
+   buf0[len0] = '\0';
+   buf1[len1] = '\0';
+
+   resbuf = palloc(PX_MAX_CRYPT);
+
+   memset(resbuf, 0, PX_MAX_CRYPT);
+
+   cres = px_crypt(buf0, buf1, resbuf, PX_MAX_CRYPT);
+
+   pfree(buf0);
+   pfree(buf1);
+
+   if (cres == NULL)
+       elog(ERROR, "crypt(3) returned NULL");
+
+   clen = strlen(cres);
+
+   res = (text *) palloc(clen + VARHDRSZ);
+   VARATT_SIZEP(res) = clen + VARHDRSZ;
+   memcpy(VARDATA(res), cres, clen);
+   pfree(resbuf);
+
+   PG_FREE_IF_COPY(arg0, 0);
+   PG_FREE_IF_COPY(arg1, 1);
+
+   PG_RETURN_TEXT_P(res);
+}
+
+/* SQL function: pg_encrypt(text, text, text) returns text */
+PG_FUNCTION_INFO_V1(pg_encrypt);
+
+Datum
+pg_encrypt(PG_FUNCTION_ARGS)
+{
+   int err;
+   bytea *data, *key, *res;
+   text *type;
+   PX_Combo *c;
+   uint dlen, klen, rlen;
+   
+   if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2))
+       PG_RETURN_NULL();
+   
+   type = PG_GETARG_TEXT_P(2);
+   c = find_provider(type, (PFN)px_find_combo, "Cipher", 0);
+
+   data = PG_GETARG_BYTEA_P(0);
+   key = PG_GETARG_BYTEA_P(1);
+   dlen = VARSIZE(data) - VARHDRSZ;
+   klen = VARSIZE(key) - VARHDRSZ;
+
+   rlen = px_combo_encrypt_len(c, dlen);
+   res = palloc(VARHDRSZ + rlen);
+
+   err = px_combo_init(c, VARDATA(key), klen, NULL, 0);
+   if (!err)
+       err = px_combo_encrypt(c, VARDATA(data), dlen, VARDATA(res), &rlen);
+   px_combo_free(c);
+
+   PG_FREE_IF_COPY(data, 0);
+   PG_FREE_IF_COPY(key, 1);
+   PG_FREE_IF_COPY(type, 2);
+   
+   if (err) {
+       pfree(res);
+       elog(ERROR, "encrypt error: %d", err);
+   }
+
+   VARATT_SIZEP(res) = VARHDRSZ + rlen;
+   PG_RETURN_BYTEA_P(res);
+}
+
+/* SQL function: pg_decrypt(text, text, text) returns text */
+PG_FUNCTION_INFO_V1(pg_decrypt);
+
+Datum
+pg_decrypt(PG_FUNCTION_ARGS)
+{
+   int err;
+   bytea *data, *key, *res;
+   text *type;
+   PX_Combo *c;
+   uint dlen, klen, rlen;
+   
+   if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2))
+       PG_RETURN_NULL();
+   
+   type = PG_GETARG_TEXT_P(2);
+   c = find_provider(type, (PFN)px_find_combo, "Cipher", 0);
+
+   data = PG_GETARG_BYTEA_P(0);
+   key = PG_GETARG_BYTEA_P(1);
+   dlen = VARSIZE(data) - VARHDRSZ;
+   klen = VARSIZE(key) - VARHDRSZ;
+
+   rlen = px_combo_decrypt_len(c, dlen);
+   res = palloc(VARHDRSZ + rlen);
+
+   err = px_combo_init(c, VARDATA(key), klen, NULL, 0);
+   if (!err)
+       err = px_combo_decrypt(c, VARDATA(data), dlen, VARDATA(res), &rlen);
+
+   px_combo_free(c);
+
+   if (err)
+       elog(ERROR, "decrypt error: %d", err);
+
+   VARATT_SIZEP(res) = VARHDRSZ + rlen;
+
+   PG_FREE_IF_COPY(data, 0);
+   PG_FREE_IF_COPY(key, 1);
+   PG_FREE_IF_COPY(type, 2);
+
+   PG_RETURN_BYTEA_P(res);
+}
+
+/* SQL function: pg_encrypt(text, text, text) returns text */
+PG_FUNCTION_INFO_V1(pg_encrypt_iv);
+
+Datum
+pg_encrypt_iv(PG_FUNCTION_ARGS)
 {
-   pg_digest  *p;
-   char        buf[NAMEDATALEN];
+   int err;
+   bytea *data, *key, *iv, *res;
+   text *type;
+   PX_Combo *c;
+   uint dlen, klen, ivlen, rlen;
+   
+   if (PG_ARGISNULL(0) || PG_ARGISNULL(1)
+           || PG_ARGISNULL(2) || PG_ARGISNULL(3))
+       PG_RETURN_NULL();
+   
+   type = PG_GETARG_TEXT_P(3);
+   c = find_provider(type, (PFN)px_find_combo, "Cipher", 0);
+
+   data = PG_GETARG_BYTEA_P(0);
+   key = PG_GETARG_BYTEA_P(1);
+   iv = PG_GETARG_BYTEA_P(2);
+   dlen = VARSIZE(data) - VARHDRSZ;
+   klen = VARSIZE(key) - VARHDRSZ;
+   ivlen = VARSIZE(iv) - VARHDRSZ;
+
+   rlen = px_combo_encrypt_len(c, dlen);
+   res = palloc(VARHDRSZ + rlen);
+
+   err = px_combo_init(c, VARDATA(key), klen, VARDATA(iv), ivlen);
+   if (!err)
+       px_combo_encrypt(c, VARDATA(data), dlen, VARDATA(res), &rlen);
+
+   px_combo_free(c);
+
+   if (err)
+       elog(ERROR, "encrypt_iv error: %d", err);
+
+   VARATT_SIZEP(res) = VARHDRSZ + rlen;
+
+   PG_FREE_IF_COPY(data, 0);
+   PG_FREE_IF_COPY(key, 1);
+   PG_FREE_IF_COPY(iv, 2);
+   PG_FREE_IF_COPY(type, 3);
+
+   PG_RETURN_BYTEA_P(res);
+}
+
+/* SQL function: pg_decrypt_iv(text, text, text) returns text */
+PG_FUNCTION_INFO_V1(pg_decrypt_iv);
+
+Datum
+pg_decrypt_iv(PG_FUNCTION_ARGS)
+{
+   int err;
+   bytea *data, *key, *iv, *res;
+   text *type;
+   PX_Combo *c;
+   uint dlen, klen, rlen, ivlen;
+   
+   if (PG_ARGISNULL(0) || PG_ARGISNULL(1)
+           || PG_ARGISNULL(2) || PG_ARGISNULL(3))
+       PG_RETURN_NULL();
+   
+   type = PG_GETARG_TEXT_P(3);
+   c = find_provider(type, (PFN)px_find_combo, "Cipher", 0);
+
+   data = PG_GETARG_BYTEA_P(0);
+   key = PG_GETARG_BYTEA_P(1);
+   iv = PG_GETARG_BYTEA_P(2);
+   dlen = VARSIZE(data) - VARHDRSZ;
+   klen = VARSIZE(key) - VARHDRSZ;
+   ivlen = VARSIZE(iv) - VARHDRSZ;
+
+   rlen = px_combo_decrypt_len(c, dlen);
+   res = palloc(VARHDRSZ + rlen);
+
+   err = px_combo_init(c, VARDATA(key), klen, VARDATA(iv), ivlen);
+   if (!err)
+       px_combo_decrypt(c, VARDATA(data), dlen, VARDATA(res), &rlen);
+
+   px_combo_free(c);
+
+   if (err)
+       elog(ERROR, "decrypt_iv error: %d", err);
+   
+   VARATT_SIZEP(res) = VARHDRSZ + rlen;
+
+   PG_FREE_IF_COPY(data, 0);
+   PG_FREE_IF_COPY(key, 1);
+   PG_FREE_IF_COPY(iv, 2);
+   PG_FREE_IF_COPY(type, 3);
+
+   PG_RETURN_BYTEA_P(res);
+}
+
+/* SQL function: pg_decrypt(text, text, text) returns text */
+PG_FUNCTION_INFO_V1(pg_cipher_exists);
+
+Datum
+pg_cipher_exists(PG_FUNCTION_ARGS)
+{
+   text *arg;
+   PX_Combo *c;
+
+   if (PG_ARGISNULL(0))
+       PG_RETURN_NULL();
+
+   arg = PG_GETARG_TEXT_P(0);
+
+   c = find_provider(arg, (PFN)px_find_combo, "Cipher", 1);
+   if (c != NULL)
+       px_combo_free(c);
+
+   PG_RETURN_BOOL((c != NULL) ? true : false);
+}
+
+
+static void *
+find_provider(text * name,
+             PFN provider_lookup,
+             char *desc, int silent)
+{
+   void       *res;
+   char        buf[PX_MAX_NAMELEN + 1],
+              *p;
    uint        len;
+   uint        i;
+   int         err;
 
    len = VARSIZE(name) - VARHDRSZ;
-   if (len >= NAMEDATALEN)
+   if (len > PX_MAX_NAMELEN)
    {
        if (silent)
            return NULL;
-       elog(ERROR, "Hash type does not exist (name too long)");
+       elog(ERROR, "%s type does not exist (name too long)", desc);
    }
 
-   memcpy(buf, VARDATA(name), len);
+   p = VARDATA(name);
+   for (i = 0; i < len; i++)
+       buf[i] = tolower(p[i]);
    buf[len] = 0;
 
-   p = pg_find_digest(hbuf, buf);
+   err = provider_lookup(buf, &res);
+
+   if (err && !silent)
+       elog(ERROR, "%s type does not exist: '%s'", desc, buf);
 
-   if (p == NULL && !silent)
-       elog(ERROR, "Hash type does not exist: '%s'", buf);
-   return p;
+   return err ? NULL : res;
 }
index 1700b89b15840bd839ef136e3a61eeea8ebe0a46..4c400243042b2e373b4e180228c77ae031df3099 100644 (file)
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: pgcrypto.h,v 1.3 2001/03/22 03:59:10 momjian Exp $
+ * $Id: pgcrypto.h,v 1.4 2001/08/21 00:42:41 momjian Exp $
  */
 
 #ifndef _PG_CRYPTO_H
 #define _PG_CRYPTO_H
 
-typedef struct _pg_digest pg_digest;
-struct _pg_digest
-{
-   char       *name;
-   uint        (*length) (pg_digest * h);
-   uint8      *(*digest) (pg_digest * h, uint8 *data,
-                                      uint dlen, uint8 *buf);
-   /* private */
-   union
-   {
-       uint        code;
-       const void *ptr;
-   }           misc;
-};
-
-extern pg_digest *pg_find_digest(pg_digest * hbuf, char *name);
+/* exported functions */
+Datum      pg_digest(PG_FUNCTION_ARGS);
+Datum      pg_digest_exists(PG_FUNCTION_ARGS);
+Datum      pg_hmac(PG_FUNCTION_ARGS);
+Datum      pg_hmac_exists(PG_FUNCTION_ARGS);
+Datum      pg_gen_salt(PG_FUNCTION_ARGS);
+Datum      pg_crypt(PG_FUNCTION_ARGS);
+Datum      pg_encrypt(PG_FUNCTION_ARGS);
+Datum      pg_decrypt(PG_FUNCTION_ARGS);
+Datum      pg_encrypt_iv(PG_FUNCTION_ARGS);
+Datum      pg_decrypt_iv(PG_FUNCTION_ARGS);
+Datum      pg_cipher_exists(PG_FUNCTION_ARGS);
 
 #endif
+
index 222b2769fa11e91e821db4b2ca9bada7b2686253..bed50c6946e13853ae4a04470f05d929a723c5a8 100644 (file)
@@ -1,23 +1,59 @@
 
--- drop function digest(text, text);
+-- drop function digest(bytea, text);
 -- drop function digest_exists(text);
--- drop function encode(text, text);
--- drop function decode(text, text);
+-- drop function hmac(bytea, bytea, text);
+-- drop function hmac_exists(text);
+-- drop function crypt(text, text);
+-- drop function gen_salt(text);
+-- drop function encrypt(bytea, bytea, text);
+-- drop function decrypt(bytea, bytea, text);
+-- drop function encrypt_iv(bytea, bytea, bytea, text);
+-- drop function decrypt_iv(bytea, bytea, bytea, text);
 
 
-CREATE FUNCTION digest(text, text) RETURNS text
+
+CREATE FUNCTION digest(bytea, text) RETURNS bytea
   AS '@MODULE_FILENAME@',
-  'digest' LANGUAGE 'C';
+  'pg_digest' LANGUAGE 'C';
 
 CREATE FUNCTION digest_exists(text) RETURNS bool
   AS '@MODULE_FILENAME@',
-  'digest_exists' LANGUAGE 'C';
+  'pg_digest_exists' LANGUAGE 'C';
+
+CREATE FUNCTION hmac(bytea, bytea, text) RETURNS bytea
+  AS '@MODULE_FILENAME@',
+  'pg_hmac' LANGUAGE 'C';
+
+CREATE FUNCTION hmac_exists(text) RETURNS bool
+  AS '@MODULE_FILENAME@',
+  'pg_hmac_exists' LANGUAGE 'C';
+
+CREATE FUNCTION crypt(text, text) RETURNS text
+  AS '@MODULE_FILENAME@',
+  'pg_crypt' LANGUAGE 'C';
+
+CREATE FUNCTION gen_salt(text) RETURNS text
+  AS '@MODULE_FILENAME@',
+  'pg_gen_salt' LANGUAGE 'C';
+
+CREATE FUNCTION encrypt(bytea, bytea, text) RETURNS bytea
+  AS '@MODULE_FILENAME@',
+  'pg_encrypt' LANGUAGE 'C';
+
+CREATE FUNCTION decrypt(bytea, bytea, text) RETURNS bytea
+  AS '@MODULE_FILENAME@',
+  'pg_decrypt' LANGUAGE 'C';
+
+CREATE FUNCTION encrypt_iv(bytea, bytea, bytea, text) RETURNS bytea
+  AS '@MODULE_FILENAME@',
+  'pg_encrypt_iv' LANGUAGE 'C';
 
-CREATE FUNCTION encode(text, text) RETURNS text
+CREATE FUNCTION decrypt_iv(bytea, bytea, bytea, text) RETURNS bytea
   AS '@MODULE_FILENAME@',
-  'encode' LANGUAGE 'C';
+  'pg_decrypt_iv' LANGUAGE 'C';
 
-CREATE FUNCTION decode(text, text) RETURNS text
+CREATE FUNCTION cipher_exists(text) RETURNS bool
   AS '@MODULE_FILENAME@',
-  'decode' LANGUAGE 'C';
+  'pg_cipher_exists' LANGUAGE 'C';
+
 
index db9f1a17c60b89bad0ee743954b6feba98a08f47..98ad552182f29ebfb1457b12d37da3cc2ce6f848 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sha1.c,v 1.5 2001/03/22 03:59:10 momjian Exp $ */
+/* $Id: sha1.c,v 1.6 2001/08/21 00:42:41 momjian Exp $ */
 /*    $KAME: sha1.c,v 1.3 2000/02/22 14:01:18 itojun Exp $    */
 
 /*
@@ -85,8 +85,7 @@ static uint32 _K[] = {0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6};
 static void sha1_step(struct sha1_ctxt *);
 
 static void
-sha1_step(ctxt)
-struct sha1_ctxt *ctxt;
+sha1_step(struct sha1_ctxt *ctxt)
 {
    uint32      a,
                b,
@@ -231,8 +230,7 @@ struct sha1_ctxt *ctxt;
 /*------------------------------------------------------------*/
 
 void
-sha1_init(ctxt)
-struct sha1_ctxt *ctxt;
+sha1_init(struct sha1_ctxt *ctxt)
 {
    bzero(ctxt, sizeof(struct sha1_ctxt));
    H(0) = 0x67452301;
@@ -243,8 +241,7 @@ struct sha1_ctxt *ctxt;
 }
 
 void
-sha1_pad(ctxt)
-struct sha1_ctxt *ctxt;
+sha1_pad(struct sha1_ctxt *ctxt)
 {
    size_t      padlen;         /* pad length in bytes */
    size_t      padstart;
@@ -287,10 +284,7 @@ struct sha1_ctxt *ctxt;
 }
 
 void
-sha1_loop(ctxt, input0, len)
-struct sha1_ctxt *ctxt;
-const caddr_t input0;
-size_t     len;
+sha1_loop(struct sha1_ctxt *ctxt, const uint8 *input0, size_t len)
 {
    const uint8 *input;
    size_t      gaplen;
@@ -318,9 +312,7 @@ size_t      len;
 }
 
 void
-sha1_result(ctxt, digest0)
-struct sha1_ctxt *ctxt;
-caddr_t        digest0;
+sha1_result(struct sha1_ctxt *ctxt, uint8 *digest0)
 {
    uint8      *digest;
 
@@ -351,5 +343,4 @@ caddr_t     digest0;
    digest[19] = ctxt->h.b8[16];
 #endif
 }
-
 #endif  /* unsupported */
index cddc8651e4fa12d53370d942b81a1568a558e345..c83bd7191a586bf9ef8ce783cc3a0977068430cd 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: sha1.h,v 1.4 2001/03/22 03:59:10 momjian Exp $ */
+/* $Id: sha1.h,v 1.5 2001/08/21 00:42:41 momjian Exp $ */
 /*    $KAME: sha1.h,v 1.4 2000/02/22 14:01:18 itojun Exp $    */
 
 /*
@@ -60,8 +60,8 @@ struct sha1_ctxt
 
 extern void sha1_init(struct sha1_ctxt *);
 extern void sha1_pad(struct sha1_ctxt *);
-extern void sha1_loop(struct sha1_ctxt *, const caddr_t, size_t);
-extern void sha1_result(struct sha1_ctxt *, caddr_t);
+extern void sha1_loop(struct sha1_ctxt *, const uint8 *, size_t);
+extern void sha1_result(struct sha1_ctxt *, uint8 *);
 
 /* compatibilty with other SHA1 source codes */
 typedef struct sha1_ctxt SHA1_CTX;