mirror of
https://github.com/postgres/postgres.git
synced 2025-07-30 11:03:19 +03:00
/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:
@ -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
|
subdir = contrib/pgcrypto
|
||||||
top_builddir = ../..
|
top_builddir = ../..
|
||||||
include $(top_builddir)/src/Makefile.global
|
include $(top_builddir)/src/Makefile.global
|
||||||
|
|
||||||
# either 'builtin', 'mhash', 'openssl', 'krb5'
|
# either 'builtin', 'mhash', 'openssl'
|
||||||
cryptolib = builtin
|
cryptolib = builtin
|
||||||
|
|
||||||
|
# either 'builtin', 'system'
|
||||||
|
cryptsrc = builtin
|
||||||
|
|
||||||
##########################
|
##########################
|
||||||
|
|
||||||
ifeq ($(cryptolib), builtin)
|
ifeq ($(cryptolib), builtin)
|
||||||
CRYPTO_CFLAGS =
|
CRYPTO_CFLAGS =
|
||||||
CRYPTO_LDFLAGS =
|
CRYPTO_LDFLAGS =
|
||||||
SRCS = md5.c sha1.c internal.c
|
SRCS = md5.c sha1.c internal.c blf.c rijndael.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(cryptolib), openssl)
|
ifeq ($(cryptolib), openssl)
|
||||||
@ -25,18 +28,18 @@ endif
|
|||||||
|
|
||||||
ifeq ($(cryptolib), mhash)
|
ifeq ($(cryptolib), mhash)
|
||||||
CRYPTO_CFLAGS = -I/usr/local/include
|
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
|
SRCS = mhash.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(cryptolib), krb5)
|
ifeq ($(cryptsrc), builtin)
|
||||||
CRYPTO_CFLAGS = -I/usr/include
|
SRCS += crypt-blowfish.c crypt-des.c crypt-md5.c
|
||||||
CRYPTO_LDFLAGS = -ldes
|
else
|
||||||
SRCS = krb.c
|
CRYPTO_CFLAGS += -DPX_SYSTEM_CRYPT
|
||||||
endif
|
endif
|
||||||
|
|
||||||
NAME := pgcrypto
|
NAME := pgcrypto
|
||||||
SRCS += pgcrypto.c encode.c
|
SRCS += pgcrypto.c px.c px-hmac.c px-crypt.c misc.c
|
||||||
OBJS := $(SRCS:.c=.o)
|
OBJS := $(SRCS:.c=.o)
|
||||||
SHLIB_LINK := $(CRYPTO_LDFLAGS)
|
SHLIB_LINK := $(CRYPTO_LDFLAGS)
|
||||||
SO_MAJOR_VERSION = 0
|
SO_MAJOR_VERSION = 0
|
||||||
@ -52,6 +55,12 @@ include $(top_srcdir)/src/Makefile.shlib
|
|||||||
$(NAME).sql: $(NAME).sql.in
|
$(NAME).sql: $(NAME).sql.in
|
||||||
sed 's,@MODULE_FILENAME@,$(libdir)/contrib/pgcrypto$(DLSUFFIX),g' $< >$@
|
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: all installdirs
|
||||||
$(INSTALL_SHLIB) $(shlib) $(DESTDIR)$(libdir)/contrib/pgcrypto$(DLSUFFIX)
|
$(INSTALL_SHLIB) $(shlib) $(DESTDIR)$(libdir)/contrib/pgcrypto$(DLSUFFIX)
|
||||||
$(INSTALL_DATA) $(NAME).sql $(DESTDIR)$(datadir)/contrib/$(NAME).sql
|
$(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)
|
rm -f $(DESTDIR)$(libdir)/contrib/pgcrypto$(DLSUFFIX) $(datadir)/contrib/$(NAME).sql $(docdir)/contrib/README.$(NAME)
|
||||||
|
|
||||||
clean distclean maintainer-clean: clean-lib
|
clean distclean maintainer-clean: clean-lib
|
||||||
rm -f $(OBJS) $(NAME).sql
|
rm -f $(OBJS) $(NAME).sql gen-rtab
|
||||||
|
@ -1,56 +1,184 @@
|
|||||||
|
|
||||||
DESCRIPTION
|
pgcrypto 0.4 - cryptographic functions for PostgreSQL.
|
||||||
|
======================================================
|
||||||
Here are various cryptographic and otherwise useful
|
by Marko Kreen <marko@l-t.ee>
|
||||||
functions for PostgreSQL.
|
|
||||||
|
|
||||||
encode(data, type)
|
INSTALLATION
|
||||||
encodes binary data into ASCII-only representation.
|
============
|
||||||
Types supported are 'hex' and 'base64'.
|
|
||||||
|
Edit makefile, if you want to use any external library.
|
||||||
decode(data, type)
|
|
||||||
decodes the data processed by encode()
|
make
|
||||||
|
make install
|
||||||
digest(data::text, hash_name::text)
|
|
||||||
which returns cryptographic checksum over data by
|
SQL FUNCTIONS
|
||||||
specified algorithm. eg
|
=============
|
||||||
|
|
||||||
> select encode(digest('blah', 'sha1'), 'hex');
|
If any of arguments are NULL they return NULL.
|
||||||
5bf1fd927dfb8679496a2e6cf00cbe50c1c87145
|
|
||||||
|
digest(data::bytea, type::text)::bytea
|
||||||
digest_exists(hash_name::text)::bool
|
|
||||||
which reports if particular hash type exists.
|
Type is here the algorithm to use. E.g. 'md5', 'sha1', ...
|
||||||
|
Returns binary hash.
|
||||||
If any of arguments are NULL they return NULL.
|
|
||||||
|
digest_exists(type::text)::bool
|
||||||
HASHES
|
|
||||||
|
Returns BOOL whether given hash exists.
|
||||||
For choosing library you must edit Makefile.
|
|
||||||
|
hmac(data::bytea, key::bytea, type::text)::bytea
|
||||||
standalone (default):
|
|
||||||
MD5, SHA1
|
Calculates Hashed MAC over data. type is the same as
|
||||||
|
in digest(). Returns binary hash. Similar to digest()
|
||||||
(the code is from KAME project. Actually I hate code
|
but noone can alter data and re-calculate hash without
|
||||||
duplication, but I also want to quarantee that MD5 and
|
knowing key. If the key is larger than hash blocksize
|
||||||
SHA1 exist)
|
it will first hashed and the hash will be used as key.
|
||||||
|
|
||||||
mhash (0.8.1):
|
[ HMAC is described in RFC2104. ]
|
||||||
MD5, SHA1, CRC32, CRC32B, GOST, TIGER, RIPEMD160,
|
|
||||||
HAVAL(256,224,192,160,128)
|
hmac_exists(type::text)::bool
|
||||||
|
Returns BOOL. It is separate function because all hashes
|
||||||
openssl:
|
cannot be used in HMAC.
|
||||||
MD5, SHA1, RIPEMD160, MD2
|
|
||||||
|
crypt(password::text, salt::text)::text
|
||||||
kerberos5 (heimdal):
|
|
||||||
MD5, SHA1
|
Calculates UN*X crypt(3) style hash. Useful for storing
|
||||||
|
passwords. For generating salt you should use the
|
||||||
ENCRYPTION
|
gen_salt() function. Usage:
|
||||||
|
|
||||||
There is experimental version out with encryption, HMAC
|
New password:
|
||||||
and UN*X crypt() support in
|
|
||||||
|
UPDATE .. SET pswhash = crypt(new_psw, gen_salt('md5'));
|
||||||
http://www.l-t.ee/marko/pgsql/
|
|
||||||
|
Authentication:
|
||||||
Current latest release is pgcrypto-0.3.tar.gz.
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* internal.c
|
* internal.c
|
||||||
* Wrapper for builtin functions
|
* Wrapper for builtin functions
|
||||||
*
|
*
|
||||||
* Copyright (c) 2000 Marko Kreen
|
* Copyright (c) 2001 Marko Kreen
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* 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
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* 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 "md5.h"
|
||||||
#include "sha1.h"
|
#include "sha1.h"
|
||||||
|
#include "blf.h"
|
||||||
|
#include "rijndael.h"
|
||||||
|
|
||||||
#ifndef MD5_DIGEST_LENGTH
|
#ifndef MD5_DIGEST_LENGTH
|
||||||
#define MD5_DIGEST_LENGTH 16
|
#define MD5_DIGEST_LENGTH 16
|
||||||
@ -48,67 +51,496 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static uint
|
#define SHA1_BLOCK_SIZE 64
|
||||||
pg_md5_len(pg_digest * h);
|
#define MD5_BLOCK_SIZE 64
|
||||||
static uint8 *
|
|
||||||
pg_md5_digest(pg_digest * h, uint8 *src, uint len, uint8 *buf);
|
|
||||||
|
|
||||||
static uint
|
static void init_md5(PX_MD * h);
|
||||||
pg_sha1_len(pg_digest * h);
|
static void init_sha1(PX_MD * h);
|
||||||
static uint8 *
|
|
||||||
pg_sha1_digest(pg_digest * h, uint8 *src, uint len, uint8 *buf);
|
|
||||||
|
|
||||||
static pg_digest
|
static struct int_digest
|
||||||
int_digest_list[] = {
|
{
|
||||||
{"md5", pg_md5_len, pg_md5_digest, {0}},
|
char *name;
|
||||||
{"sha1", pg_sha1_len, pg_sha1_digest, {0}},
|
void (*init) (PX_MD * h);
|
||||||
{NULL, NULL, NULL, {0}}
|
} int_digest_list[] =
|
||||||
|
{
|
||||||
|
{ "md5", init_md5 },
|
||||||
|
{ "sha1", init_sha1 },
|
||||||
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* MD5 */
|
||||||
|
|
||||||
static uint
|
static uint
|
||||||
pg_md5_len(pg_digest * h)
|
int_md5_len(PX_MD * h)
|
||||||
{
|
{
|
||||||
return MD5_DIGEST_LENGTH;
|
return MD5_DIGEST_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8 *
|
static uint
|
||||||
pg_md5_digest(pg_digest * h, uint8 *src, uint len, uint8 *buf)
|
int_md5_block_len(PX_MD * h)
|
||||||
{
|
{
|
||||||
MD5_CTX ctx;
|
return MD5_BLOCK_SIZE;
|
||||||
|
|
||||||
MD5Init(&ctx);
|
|
||||||
MD5Update(&ctx, src, len);
|
|
||||||
MD5Final(buf, &ctx);
|
|
||||||
|
|
||||||
return buf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
static uint
|
||||||
pg_sha1_len(pg_digest * h)
|
int_sha1_len(PX_MD * h)
|
||||||
{
|
{
|
||||||
return SHA1_DIGEST_LENGTH;
|
return SHA1_DIGEST_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8 *
|
static uint
|
||||||
pg_sha1_digest(pg_digest * h, uint8 *src, uint len, uint8 *buf)
|
int_sha1_block_len(PX_MD * h)
|
||||||
{
|
{
|
||||||
SHA1_CTX ctx;
|
return SHA1_BLOCK_SIZE;
|
||||||
|
|
||||||
SHA1Init(&ctx);
|
|
||||||
SHA1Update(&ctx, src, len);
|
|
||||||
SHA1Final(buf, &ctx);
|
|
||||||
|
|
||||||
return buf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
pg_digest *
|
int_sha1_update(PX_MD * h, const uint8 * data, uint dlen)
|
||||||
pg_find_digest(pg_digest * h, char *name)
|
|
||||||
{
|
{
|
||||||
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++)
|
for (p = int_digest_list; p->name; p++)
|
||||||
if (!strcasecmp(p->name, name))
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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 $ */
|
/* $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 *);
|
static void md5_calc(uint8 *, md5_ctxt *);
|
||||||
|
|
||||||
void
|
void
|
||||||
md5_init(ctxt)
|
md5_init(md5_ctxt *ctxt)
|
||||||
md5_ctxt *ctxt;
|
|
||||||
{
|
{
|
||||||
ctxt->md5_n = 0;
|
ctxt->md5_n = 0;
|
||||||
ctxt->md5_i = 0;
|
ctxt->md5_i = 0;
|
||||||
@ -141,10 +140,7 @@ md5_ctxt *ctxt;
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
md5_loop(ctxt, input, len)
|
md5_loop(md5_ctxt *ctxt, const uint8 *input, unsigned len)
|
||||||
md5_ctxt *ctxt;
|
|
||||||
uint8 *input;
|
|
||||||
unsigned int len; /* number of bytes */
|
|
||||||
{
|
{
|
||||||
unsigned int gap,
|
unsigned int gap,
|
||||||
i;
|
i;
|
||||||
@ -173,8 +169,7 @@ unsigned int len; /* number of bytes */
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
md5_pad(ctxt)
|
md5_pad(md5_ctxt *ctxt)
|
||||||
md5_ctxt *ctxt;
|
|
||||||
{
|
{
|
||||||
unsigned int gap;
|
unsigned int gap;
|
||||||
|
|
||||||
@ -216,9 +211,7 @@ md5_ctxt *ctxt;
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
md5_result(digest, ctxt)
|
md5_result(uint8 *digest, md5_ctxt *ctxt)
|
||||||
uint8 *digest;
|
|
||||||
md5_ctxt *ctxt;
|
|
||||||
{
|
{
|
||||||
/* 4 byte words */
|
/* 4 byte words */
|
||||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||||
@ -245,14 +238,11 @@ md5_ctxt *ctxt;
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if BYTE_ORDER == BIG_ENDIAN
|
#if BYTE_ORDER == BIG_ENDIAN
|
||||||
uint32 X[16];
|
static uint32 X[16];
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
md5_calc(b64, ctxt)
|
md5_calc(uint8 *b64, md5_ctxt *ctxt)
|
||||||
uint8 *b64;
|
|
||||||
md5_ctxt *ctxt;
|
|
||||||
{
|
{
|
||||||
uint32 A = ctxt->md5_sta;
|
uint32 A = ctxt->md5_sta;
|
||||||
uint32 B = ctxt->md5_stb;
|
uint32 B = ctxt->md5_stb;
|
||||||
@ -261,7 +251,6 @@ md5_ctxt *ctxt;
|
|||||||
|
|
||||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||||
uint32 *X = (uint32 *) b64;
|
uint32 *X = (uint32 *) b64;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#if BYTE_ORDER == BIG_ENDIAN
|
#if BYTE_ORDER == BIG_ENDIAN
|
||||||
/* 4 byte words */
|
/* 4 byte words */
|
||||||
|
@ -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 $ */
|
/* $KAME: md5.h,v 1.3 2000/02/22 14:01:18 itojun Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -62,7 +62,7 @@ typedef struct
|
|||||||
} md5_ctxt;
|
} md5_ctxt;
|
||||||
|
|
||||||
extern void md5_init(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_pad(md5_ctxt *);
|
||||||
extern void md5_result(uint8 *, md5_ctxt *);
|
extern void md5_result(uint8 *, md5_ctxt *);
|
||||||
|
|
||||||
@ -75,5 +75,4 @@ do { \
|
|||||||
md5_pad((y)); \
|
md5_pad((y)); \
|
||||||
md5_result((x), (y)); \
|
md5_result((x), (y)); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#endif /* ! _NETINET6_MD5_H_ */
|
#endif /* ! _NETINET6_MD5_H_ */
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* mhash.c
|
* 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.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* 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
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* 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 <mhash.h>
|
||||||
|
#include <mcrypt.h>
|
||||||
|
|
||||||
|
#define MAX_KEY_LENGTH 512
|
||||||
|
#define MAX_IV_LENGTH 128
|
||||||
|
|
||||||
|
#define DEF_KEY_LEN 16
|
||||||
|
|
||||||
|
|
||||||
|
/* DIGEST */
|
||||||
|
|
||||||
static uint
|
static uint
|
||||||
pg_mhash_len(pg_digest * hash);
|
digest_result_size(PX_MD * h)
|
||||||
static uint8 *pg_mhash_digest(pg_digest * hash, uint8 *src,
|
|
||||||
uint len, uint8 *buf);
|
|
||||||
|
|
||||||
static uint
|
|
||||||
pg_mhash_len(pg_digest * 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 *
|
static uint
|
||||||
pg_mhash_digest(pg_digest * h, uint8 *src, uint len, uint8 *dst)
|
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);
|
static void
|
||||||
res = mhash_end(mh);
|
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);
|
mhash_free(res);
|
||||||
|
mh = mhash_init(id);
|
||||||
return dst;
|
h->p.ptr = mh;
|
||||||
}
|
}
|
||||||
|
|
||||||
pg_digest *
|
static void
|
||||||
pg_find_digest(pg_digest * h, char *name)
|
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,
|
size_t hnum,
|
||||||
i,
|
b,
|
||||||
b;
|
i;
|
||||||
char *mname;
|
char *mname;
|
||||||
|
|
||||||
hnum = mhash_count();
|
hnum = mhash_count();
|
||||||
@ -80,12 +209,134 @@ pg_find_digest(pg_digest * h, char *name)
|
|||||||
free(mname);
|
free(mname);
|
||||||
if (!b)
|
if (!b)
|
||||||
{
|
{
|
||||||
h->name = mhash_get_hash_name(i);
|
res = i;
|
||||||
h->length = pg_mhash_len;
|
break;
|
||||||
h->digest = pg_mhash_digest;
|
|
||||||
h->misc.code = i;
|
|
||||||
return h;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* openssl.c
|
* openssl.c
|
||||||
* Wrapper for OpenSSL library.
|
* Wrapper for OpenSSL library.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2000 Marko Kreen
|
* Copyright (c) 2001 Marko Kreen
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* 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
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* 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
|
static uint
|
||||||
pg_ossl_len(pg_digest * h);
|
digest_result_size(PX_MD * h)
|
||||||
static uint8 *
|
{
|
||||||
pg_ossl_digest(pg_digest * h, uint8 *src, uint len, uint8 *buf);
|
return EVP_MD_CTX_size((EVP_MD_CTX *) h->p.ptr);
|
||||||
|
}
|
||||||
|
|
||||||
static uint
|
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 *
|
static void
|
||||||
pg_ossl_digest(pg_digest * h, uint8 *src, uint len, uint8 *buf)
|
digest_reset(PX_MD * h)
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
|
EVP_MD_CTX *ctx = (EVP_MD_CTX *) h->p.ptr;
|
||||||
const EVP_MD *md;
|
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();
|
px_openssl_initialized = 1;
|
||||||
pg_openssl_initialized = 1;
|
/*CRYPTO_set_mem_functions(o_alloc, o_realloc, o_free);*/
|
||||||
|
OpenSSL_add_all_algorithms();
|
||||||
}
|
}
|
||||||
|
|
||||||
md = EVP_get_digestbyname(name);
|
md = EVP_get_digestbyname(name);
|
||||||
if (md == NULL)
|
if (md == NULL)
|
||||||
return NULL;
|
return -1;
|
||||||
|
|
||||||
h->name = name;
|
ctx = px_alloc(sizeof(*ctx));
|
||||||
h->length = pg_ossl_len;
|
EVP_DigestInit(ctx, md);
|
||||||
h->digest = pg_ossl_digest;
|
|
||||||
h->misc.ptr = (void *) 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* pgcrypto.c
|
* pgcrypto.c
|
||||||
* Cryptographic digests for PostgreSQL.
|
* Various cryptographic stuff for PostgreSQL.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2000 Marko Kreen
|
* Copyright (c) 2001 Marko Kreen
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* 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
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* 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 <postgres.h>
|
||||||
|
#include <fmgr.h>
|
||||||
#include "utils/builtins.h"
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "px.h"
|
||||||
|
#include "px-crypt.h"
|
||||||
#include "pgcrypto.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 */
|
/* 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 */
|
/* SQL function: hash(text, text) returns text */
|
||||||
PG_FUNCTION_INFO_V1(digest);
|
PG_FUNCTION_INFO_V1(pg_digest);
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
digest(PG_FUNCTION_ARGS)
|
pg_digest(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
text *arg;
|
bytea *arg;
|
||||||
text *name;
|
text *name;
|
||||||
uint len,
|
uint len,
|
||||||
hlen;
|
hlen;
|
||||||
pg_digest *h,
|
PX_MD *md;
|
||||||
_hbuf;
|
bytea *res;
|
||||||
text *res;
|
|
||||||
|
|
||||||
if (PG_ARGISNULL(0) || PG_ARGISNULL(1))
|
if (PG_ARGISNULL(0) || PG_ARGISNULL(1))
|
||||||
PG_RETURN_NULL();
|
PG_RETURN_NULL();
|
||||||
|
|
||||||
name = PG_GETARG_TEXT_P(1);
|
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);
|
res = (text *) palloc(hlen + VARHDRSZ);
|
||||||
VARATT_SIZEP(res) = hlen + VARHDRSZ;
|
VARATT_SIZEP(res) = hlen + VARHDRSZ;
|
||||||
|
|
||||||
arg = PG_GETARG_TEXT_P(0);
|
arg = PG_GETARG_BYTEA_P(0);
|
||||||
len = VARSIZE(arg) - VARHDRSZ;
|
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(arg, 0);
|
||||||
PG_FREE_IF_COPY(name, 1);
|
PG_FREE_IF_COPY(name, 1);
|
||||||
|
|
||||||
PG_RETURN_TEXT_P(res);
|
PG_RETURN_BYTEA_P(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check if given hash exists */
|
/* check if given hash exists */
|
||||||
PG_FUNCTION_INFO_V1(digest_exists);
|
PG_FUNCTION_INFO_V1(pg_digest_exists);
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
digest_exists(PG_FUNCTION_ARGS)
|
pg_digest_exists(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
text *name;
|
text *name;
|
||||||
pg_digest _hbuf,
|
PX_MD *res;
|
||||||
*res;
|
|
||||||
|
|
||||||
if (PG_ARGISNULL(0))
|
if (PG_ARGISNULL(0))
|
||||||
PG_RETURN_NULL();
|
PG_RETURN_NULL();
|
||||||
|
|
||||||
name = PG_GETARG_TEXT_P(0);
|
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);
|
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(true);
|
||||||
|
}
|
||||||
PG_RETURN_BOOL(false);
|
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;
|
text *arg0;
|
||||||
char buf[NAMEDATALEN];
|
|
||||||
uint len;
|
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;
|
len = VARSIZE(name) - VARHDRSZ;
|
||||||
if (len >= NAMEDATALEN)
|
if (len > PX_MAX_NAMELEN)
|
||||||
{
|
{
|
||||||
if (silent)
|
if (silent)
|
||||||
return NULL;
|
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;
|
buf[len] = 0;
|
||||||
|
|
||||||
p = pg_find_digest(hbuf, buf);
|
err = provider_lookup(buf, &res);
|
||||||
|
|
||||||
if (p == NULL && !silent)
|
if (err && !silent)
|
||||||
elog(ERROR, "Hash type does not exist: '%s'", buf);
|
elog(ERROR, "%s type does not exist: '%s'", desc, buf);
|
||||||
return p;
|
|
||||||
|
return err ? NULL : res;
|
||||||
}
|
}
|
||||||
|
@ -26,27 +26,24 @@
|
|||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
* SUCH DAMAGE.
|
* 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
|
#ifndef _PG_CRYPTO_H
|
||||||
#define _PG_CRYPTO_H
|
#define _PG_CRYPTO_H
|
||||||
|
|
||||||
typedef struct _pg_digest pg_digest;
|
/* exported functions */
|
||||||
struct _pg_digest
|
Datum pg_digest(PG_FUNCTION_ARGS);
|
||||||
{
|
Datum pg_digest_exists(PG_FUNCTION_ARGS);
|
||||||
char *name;
|
Datum pg_hmac(PG_FUNCTION_ARGS);
|
||||||
uint (*length) (pg_digest * h);
|
Datum pg_hmac_exists(PG_FUNCTION_ARGS);
|
||||||
uint8 *(*digest) (pg_digest * h, uint8 *data,
|
Datum pg_gen_salt(PG_FUNCTION_ARGS);
|
||||||
uint dlen, uint8 *buf);
|
Datum pg_crypt(PG_FUNCTION_ARGS);
|
||||||
/* private */
|
Datum pg_encrypt(PG_FUNCTION_ARGS);
|
||||||
union
|
Datum pg_decrypt(PG_FUNCTION_ARGS);
|
||||||
{
|
Datum pg_encrypt_iv(PG_FUNCTION_ARGS);
|
||||||
uint code;
|
Datum pg_decrypt_iv(PG_FUNCTION_ARGS);
|
||||||
const void *ptr;
|
Datum pg_cipher_exists(PG_FUNCTION_ARGS);
|
||||||
} misc;
|
|
||||||
};
|
|
||||||
|
|
||||||
extern pg_digest *pg_find_digest(pg_digest * hbuf, char *name);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1,23 +1,59 @@
|
|||||||
|
|
||||||
-- drop function digest(text, text);
|
-- drop function digest(bytea, text);
|
||||||
-- drop function digest_exists(text);
|
-- drop function digest_exists(text);
|
||||||
-- drop function encode(text, text);
|
-- drop function hmac(bytea, bytea, text);
|
||||||
-- drop function decode(text, 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@',
|
AS '@MODULE_FILENAME@',
|
||||||
'digest' LANGUAGE 'C';
|
'pg_digest' LANGUAGE 'C';
|
||||||
|
|
||||||
CREATE FUNCTION digest_exists(text) RETURNS bool
|
CREATE FUNCTION digest_exists(text) RETURNS bool
|
||||||
AS '@MODULE_FILENAME@',
|
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@',
|
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@',
|
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';
|
||||||
|
|
||||||
|
|
||||||
|
@ -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 $ */
|
/* $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(struct sha1_ctxt *);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sha1_step(ctxt)
|
sha1_step(struct sha1_ctxt *ctxt)
|
||||||
struct sha1_ctxt *ctxt;
|
|
||||||
{
|
{
|
||||||
uint32 a,
|
uint32 a,
|
||||||
b,
|
b,
|
||||||
@ -231,8 +230,7 @@ struct sha1_ctxt *ctxt;
|
|||||||
/*------------------------------------------------------------*/
|
/*------------------------------------------------------------*/
|
||||||
|
|
||||||
void
|
void
|
||||||
sha1_init(ctxt)
|
sha1_init(struct sha1_ctxt *ctxt)
|
||||||
struct sha1_ctxt *ctxt;
|
|
||||||
{
|
{
|
||||||
bzero(ctxt, sizeof(struct sha1_ctxt));
|
bzero(ctxt, sizeof(struct sha1_ctxt));
|
||||||
H(0) = 0x67452301;
|
H(0) = 0x67452301;
|
||||||
@ -243,8 +241,7 @@ struct sha1_ctxt *ctxt;
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sha1_pad(ctxt)
|
sha1_pad(struct sha1_ctxt *ctxt)
|
||||||
struct sha1_ctxt *ctxt;
|
|
||||||
{
|
{
|
||||||
size_t padlen; /* pad length in bytes */
|
size_t padlen; /* pad length in bytes */
|
||||||
size_t padstart;
|
size_t padstart;
|
||||||
@ -287,10 +284,7 @@ struct sha1_ctxt *ctxt;
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sha1_loop(ctxt, input0, len)
|
sha1_loop(struct sha1_ctxt *ctxt, const uint8 *input0, size_t len)
|
||||||
struct sha1_ctxt *ctxt;
|
|
||||||
const caddr_t input0;
|
|
||||||
size_t len;
|
|
||||||
{
|
{
|
||||||
const uint8 *input;
|
const uint8 *input;
|
||||||
size_t gaplen;
|
size_t gaplen;
|
||||||
@ -318,9 +312,7 @@ size_t len;
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
sha1_result(ctxt, digest0)
|
sha1_result(struct sha1_ctxt *ctxt, uint8 *digest0)
|
||||||
struct sha1_ctxt *ctxt;
|
|
||||||
caddr_t digest0;
|
|
||||||
{
|
{
|
||||||
uint8 *digest;
|
uint8 *digest;
|
||||||
|
|
||||||
@ -351,5 +343,4 @@ caddr_t digest0;
|
|||||||
digest[19] = ctxt->h.b8[16];
|
digest[19] = ctxt->h.b8[16];
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* unsupported */
|
#endif /* unsupported */
|
||||||
|
@ -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 $ */
|
/* $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_init(struct sha1_ctxt *);
|
||||||
extern void sha1_pad(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_loop(struct sha1_ctxt *, const uint8 *, size_t);
|
||||||
extern void sha1_result(struct sha1_ctxt *, caddr_t);
|
extern void sha1_result(struct sha1_ctxt *, uint8 *);
|
||||||
|
|
||||||
/* compatibilty with other SHA1 source codes */
|
/* compatibilty with other SHA1 source codes */
|
||||||
typedef struct sha1_ctxt SHA1_CTX;
|
typedef struct sha1_ctxt SHA1_CTX;
|
||||||
|
Reference in New Issue
Block a user