/contrib/pgcrypto:

* 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
This commit is contained in:
Bruce Momjian 2001-08-21 00:42:41 +00:00
parent 5950a984a7
commit 2518e27334
12 changed files with 1821 additions and 287 deletions

View 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

View File

@ -1,56 +1,184 @@
DESCRIPTION
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'.
decode(data, type)
decodes the data processed by encode()
digest(data::text, hash_name::text)
which returns cryptographic checksum over data by
specified algorithm. eg
> select encode(digest('blah', 'sha1'), 'hex');
5bf1fd927dfb8679496a2e6cf00cbe50c1c87145
digest_exists(hash_name::text)::bool
which reports if particular hash type exists.
If any of arguments are NULL they return NULL.
HASHES
For choosing library you must edit Makefile.
standalone (default):
MD5, SHA1
(the code is from KAME project. Actually I hate code
duplication, but I also want to quarantee that MD5 and
SHA1 exist)
mhash (0.8.1):
MD5, SHA1, CRC32, CRC32B, GOST, TIGER, RIPEMD160,
HAVAL(256,224,192,160,128)
openssl:
MD5, SHA1, RIPEMD160, MD2
kerberos5 (heimdal):
MD5, SHA1
ENCRYPTION
There is experimental version out with encryption, HMAC
and UN*X crypt() support in
http://www.l-t.ee/marko/pgsql/
Current latest release is pgcrypto-0.3.tar.gz.
pgcrypto 0.4 - cryptographic functions for PostgreSQL.
======================================================
by Marko Kreen <marko@l-t.ee>
INSTALLATION
============
Edit makefile, if you want to use any external library.
make
make install
SQL FUNCTIONS
=============
If any of arguments are NULL they return NULL.
digest(data::bytea, type::text)::bytea
Type is here the algorithm to use. E.g. 'md5', 'sha1', ...
Returns binary hash.
digest_exists(type::text)::bool
Returns BOOL whether given hash exists.
hmac(data::bytea, key::bytea, type::text)::bytea
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. ]
hmac_exists(type::text)::bool
Returns BOOL. It is separate function because all hashes
cannot be used in HMAC.
crypt(password::text, salt::text)::text
Calculates UN*X crypt(3) style hash. Useful for storing
passwords. For generating salt you should use the
gen_salt() function. Usage:
New password:
UPDATE .. SET pswhash = crypt(new_psw, gen_salt('md5'));
Authentication:
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...
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.

View 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
@ -26,15 +26,18 @@
* 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 <postgres.h>
#include "px.h"
#include "md5.h"
#include "sha1.h"
#include "blf.h"
#include "rijndael.h"
#ifndef MD5_DIGEST_LENGTH
#define MD5_DIGEST_LENGTH 16
@ -48,67 +51,496 @@
#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 void init_md5(PX_MD * h);
static void init_sha1(PX_MD * h);
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 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)
{
MD5_CTX ctx;
MD5Init(&ctx);
MD5Update(&ctx, src, len);
MD5Final(buf, &ctx);
return buf;
return MD5_BLOCK_SIZE;
}
static void
int_md5_update(PX_MD * h, const uint8 * data, uint dlen)
{
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);
}
static void
int_md5_free(PX_MD * h)
{
MD5_CTX *ctx = (MD5_CTX *) h->p.ptr;
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)
{
SHA1_CTX ctx;
SHA1Init(&ctx);
SHA1Update(&ctx, src, len);
SHA1Final(buf, &ctx);
return buf;
return SHA1_BLOCK_SIZE;
}
pg_digest *
pg_find_digest(pg_digest * h, char *name)
static void
int_sha1_update(PX_MD * h, const uint8 * data, uint dlen)
{
pg_digest *p;
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()
{
return rj_load(MODE_CBC);
}
static PX_Cipher * bf_ecb_load()
{
return bf_load(MODE_ECB);
}
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 }
};
/* PUBLIC FUNCTIONS */
int
px_find_digest(const char *name, PX_MD ** res)
{
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;
}

View 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 */

View 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_ */

View 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
@ -26,48 +26,177 @@
* 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 <postgres.h>
#include "pgcrypto.h"
#include "px.h"
#include <mhash.h>
#include <mcrypt.h>
#define MAX_KEY_LENGTH 512
#define MAX_IV_LENGTH 128
#define DEF_KEY_LEN 16
/* DIGEST */
static uint
pg_mhash_len(pg_digest * hash);
static uint8 *pg_mhash_digest(pg_digest * hash, uint8 *src,
uint len, uint8 *buf);
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);
return dst;
mh = mhash_init(id);
h->p.ptr = mh;
}
pg_digest *
pg_find_digest(pg_digest * h, char *name)
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;
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);
}
/* 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;
}

View 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
@ -26,60 +26,388 @@
* 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 <postgres.h>
#include "pgcrypto.h"
#include "px.h"
#include <evp.h>
#include <openssl/evp.h>
#include <openssl/blowfish.h>
/*#include <openssl/crypto.h>*/
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 uint8 *
pg_ossl_digest(pg_digest * h, uint8 *src, uint len, uint8 *buf)
{
EVP_MD *md = (EVP_MD *) h->misc.ptr;
EVP_MD_CTX ctx;
EVP_DigestInit(&ctx, md);
EVP_DigestUpdate(&ctx, src, len);
EVP_DigestFinal(&ctx, buf, NULL);
return buf;
}
static int pg_openssl_initialized = 0;
pg_digest *
pg_find_digest(pg_digest * h, char *name)
static void
digest_reset(PX_MD * h)
{
EVP_MD_CTX *ctx = (EVP_MD_CTX *) h->p.ptr;
const EVP_MD *md;
if (!pg_openssl_initialized)
md = EVP_MD_CTX_md(ctx);
EVP_DigestInit(ctx, md);
}
static void
digest_update(PX_MD * h, const uint8 * data, uint dlen)
{
EVP_MD_CTX *ctx = (EVP_MD_CTX *) h->p.ptr;
EVP_DigestUpdate(ctx, data, dlen);
}
static void
digest_finish(PX_MD * h, uint8 * dst)
{
EVP_MD_CTX *ctx = (EVP_MD_CTX *) h->p.ptr;
EVP_DigestFinal(ctx, dst, NULL);
}
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;
}
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 (!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;
}

View 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
@ -26,113 +26,487 @@
* 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 <postgres.h>
#include <fmgr.h>
#include <ctype.h>
#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)
{
pg_digest *p;
char buf[NAMEDATALEN];
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)
{
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 (p == NULL && !silent)
elog(ERROR, "Hash type does not exist: '%s'", buf);
return p;
if (err && !silent)
elog(ERROR, "%s type does not exist: '%s'", desc, buf);
return err ? NULL : res;
}

View File

@ -26,27 +26,24 @@
* 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

View 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 encode(text, text) RETURNS text
CREATE FUNCTION hmac(bytea, bytea, text) RETURNS bytea
AS '@MODULE_FILENAME@',
'encode' LANGUAGE 'C';
'pg_hmac' LANGUAGE 'C';
CREATE FUNCTION decode(text, text) RETURNS text
CREATE FUNCTION hmac_exists(text) RETURNS bool
AS '@MODULE_FILENAME@',
'decode' LANGUAGE 'C';
'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 decrypt_iv(bytea, bytea, bytea, text) RETURNS bytea
AS '@MODULE_FILENAME@',
'pg_decrypt_iv' LANGUAGE 'C';
CREATE FUNCTION cipher_exists(text) RETURNS bool
AS '@MODULE_FILENAME@',
'pg_cipher_exists' LANGUAGE 'C';

View 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 */

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