Re: pgcrypto update - Mailing list pgsql-patches
From | Bruce Momjian |
---|---|
Subject | Re: pgcrypto update |
Date | |
Msg-id | 200109230414.f8N4EBr05021@candle.pha.pa.us Whole thread Raw |
In response to | pgcrypto update (Marko Kreen <marko@l-t.ee>) |
List | pgsql-patches |
Patch applied. Thanks. Your name has been added to the bottom of the TODO list. > > Big thanks to Solar Designer who pointed out a bug in bcrypt > salt generation code. He also urged using better random source > and making possible to choose using bcrypt and xdes rounds more > easily. So, here's patch: > > * For all salt generation, use Solar Designer's own code. This > is mostly due fact that his code is more fit for get_random_bytes() > style interface. > * New function: gen_salt(type, rounds). This lets specify iteration > count for algorithm. > * random.c: px_get_random_bytes() function. > Supported randomness soure: /dev/urandom, OpenSSL PRNG, libc random() > Default: /dev/urandom. > * Draft description of C API for pgcrypto functions. > > New files: API, crypt-gensalt.c, random.c > > > -- > marko > > > diff -urNX /home/marko/misc/diff-exclude contrib/pgcrypto.orig/API contrib/pgcrypto/API > --- contrib/pgcrypto.orig/API Thu Jan 1 03:00:00 1970 > +++ contrib/pgcrypto/API Sat Sep 22 01:57:41 2001 > @@ -0,0 +1,163 @@ > + > +C API for pgcrypto > +================== > + > + > +UN*X crypt() > +============ > + > +#include <px-crypt.h> > + > +char * > +px_crypt(const char *psw, const char *salt, char *buf, unsigned buflen); > + > + returns buf or NULL for error. > + > +unsigned px_gen_salt(const char *salt_type, char *dst, int rounds); > + > + returns salt size. dst should be PX_MAX_SALT_LEN bytes. > + 'rounds' is algorithm specific. 0 means default for > + that algorithm. > + > +Random > +====== > + > +int px_rand_get_bytes(uint8 *dst, int num) > + > + > +Crypto "objects" > +================ > + > +PX_MD - Message digest > +PX_HMAC - HMAC (Hash MAC) > +PX_Cipher - cipher+mode: provided by libs > +PX_Combo - higher-level encryption -> padding, [MD] > + > +Objects are activated with following functions: > + > +int px_find_digest(const char *name, PX_MD **res); > +int px_find_hmac(const char *name, PX_HMAC **res); > +int px_find_cipher(const char *name, PX_Cipher **res); > +int px_find_combo(const char *name, PX_Combo **res); > + > + returns 0 on success, < 0 on error. If successful, > + *res contains pointer to new object. > + > +Message Digest > +============== > + > +uint px_md_result_size(PX_MD *md) > + > + returns final result size in bytes > + > +void px_md_reset(PX_MD *md) > + > + resets md to clean state > + > +uint px_md_block_size(PX_MD *md) > + > + return algorithm block size in bytes > + > +void px_md_update(PX_MD *md, const uint8 *data, uint dlen) > + > + updates hash state with new data > + > +void px_md_finish(PX_MD *md, uint8 *buf) > + > + puts final hash state into buf. buf should have room > + for px_md_result_size() bytes. > + > +void px_md_free(PX_MD *md) > + > + frees resources. > + > +HMAC (Hash Message Authentication Code) > +======================================= > + > +int px_hmac_init(PX_HMAC *hmac, const uint8 *key, uint klen) > + > + initalized hmac state with key. > + > +uint px_hmac_result_size(PX_HMAC *md) > + > + returns final result size in bytes > + > +void px_hmac_reset(PX_HMAC *md) > + > + resets md to state after _init() > + > +uint px_hmac_block_size(PX_HMAC *md) > + > + return algorithm block size in bytes > + > +void px_hmac_update(PX_HMAC *md, const uint8 *data, uint dlen) > + > + updates hash state with new data > + > +void px_hmac_finish(PX_HMAC *md, uint8 *buf) > + > + puts final hash state into buf. buf should have room > + for px_hmac_result_size() bytes. > + > +void px_hmac_free(PX_HMAC *md) > + > + frees resources. > + > + > +Cipher > +====== > + > +uint px_cipher_key_size(PX_Cipher *c) > + > + returns max key size in bytes > + > +uint px_cipher_block_size(PX_Cipher *c) > + > + returns cipher+mode block size in bytes. So blowfish > + in CFB mode should return 1. > + > +uint px_cipher_iv_size(PX_Cipher *c) > + > + returns IV size in bytes. > + > +int px_cipher_init(PX_Cipher *c, uint8 *key, uint klen, uint8 *iv) > + > + initializes cipher with supplied key and iv. > + > +int px_cipher_encrypt(PX_Cipher *c, uint8 *data, uint dlen, uint8 *res) > + > + encrypts data. res must have room for dlen bytes. > + data must be multiple of px_cipher_block_size(). > + > +int px_cipher_decrypt(PX_Cipher *c, uint8 *data, uint dlen, uint8 *res) > + > + decrypts data. res must have room for dlen bytes. > + > +void px_cipher_free(PX_Cipher *c) > + > + frees resources assiocated. > + > +PX_Combo > +======== > + > +uint px_combo_encrypt_len(PX_Combo *c, uint dlen) > + > + calculates max result length for dlen of data. > + > +uint px_combo_decrypt_len(PX_Combo *c, uint dlen) > + > + calculates result length for dlen of data. > + > +int px_combo_init(PX_Combo *c, uint8 *key, uint klen, uint8 *iv, uint ivlen) > + > + initializes c with key and iv. If cipher uses fixed length keys, > + key will be padded with zeroes to needed length. > + > +int px_combo_encrypt(PX_Combo *c, uint8 *data, uint dlen, uint8 *res, uint rlen) > + > +int px_combo_decrypt(PX_Combo *c, uint8 *data, uint dlen, uint8 *res, uint rlen) > + > +void px_combo_free(PX_Combo *c) > + > + frees resources assiocated. > + > diff -urNX /home/marko/misc/diff-exclude contrib/pgcrypto.orig/Makefile contrib/pgcrypto/Makefile > --- contrib/pgcrypto.orig/Makefile Sun Sep 16 18:11:09 2001 > +++ contrib/pgcrypto/Makefile Sat Sep 22 02:30:09 2001 > @@ -12,6 +12,18 @@ > # either 'builtin', 'system' > cryptsrc = builtin > > +# Random source, preferred order: > +# 'dev' - read from random device > +# > +# 'openssl' - use openssl PRNG. > +# Note that currently pgcrypto does not do any > +# entropy feeding to it > +# This works ofcouse only with cryptolib = openssl > +# > +# 'silly' - use libc random() - very weak > +random = dev > +random_dev = \"/dev/urandom\" > + > ########################## > > ifeq ($(cryptolib), builtin) > @@ -38,8 +50,19 @@ > CRYPTO_CFLAGS += -DPX_SYSTEM_CRYPT > endif > > +ifeq ($(random), dev) > +CRYPTO_CFLAGS += -DRAND_DEV=$(random_dev) > +endif > +ifeq ($(random), openssl) > +CRYPTO_CFLAGS += -DRAND_OPENSSL > +endif > +ifeq ($(random), silly) > +CRYPTO_CFLAGS += -DRAND_SILLY > +endif > + > NAME := pgcrypto > -SRCS += pgcrypto.c px.c px-hmac.c px-crypt.c misc.c > +SRCS += pgcrypto.c px.c px-hmac.c px-crypt.c misc.c \ > + crypt-gensalt.c random.c > OBJS := $(SRCS:.c=.o) > SHLIB_LINK := $(CRYPTO_LDFLAGS) > SO_MAJOR_VERSION = 0 > diff -urNX /home/marko/misc/diff-exclude contrib/pgcrypto.orig/README.pgcrypto contrib/pgcrypto/README.pgcrypto > --- contrib/pgcrypto.orig/README.pgcrypto Tue Aug 21 02:42:41 2001 > +++ contrib/pgcrypto/README.pgcrypto Sat Sep 22 02:39:52 2001 > @@ -9,6 +9,13 @@ > > Edit makefile, if you want to use any external library. > > +NB! Default randomness source is /dev/urandom device. If you > +do not have it, you also need to edit Makefile to let pgcrypto > +use either OpenSSL PRNG or libc random() PRNG. Using libc random() > +is discouraged. > + > +After editing Makefile: > + > make > make install > > @@ -72,6 +79,27 @@ > > When you use --enable-system-crypt then note that system > libcrypt may not support them all. > + > +gen_salt(type::text, rounds::int4)::text > + > + same as above, but lets user specify iteration count > + for algorithm. Number is algotithm specific: > + > + type default min max > + --------------------------------- > + xdes 725 1 16777215 > + bf 6 4 31 > + > + In case of xdes there is a additional limitation that the > + count must be a odd number. > + > + The higher the count, the more time it takes to calculate > + crypt and therefore the more time to break it. But beware! > + With too high count it takes a _very_long_ time to > + calculate it. > + > + For maximum security, you should choose the 'bf' crypt > + and use maximum number of rounds you can still tolerate. > > encrypt(data::bytea, key::bytea, type::text)::bytea > decrypt(data::bytea, key::bytea, type::text)::bytea > diff -urNX /home/marko/misc/diff-exclude contrib/pgcrypto.orig/crypt-blowfish.c contrib/pgcrypto/crypt-blowfish.c > --- contrib/pgcrypto.orig/crypt-blowfish.c Tue Aug 21 03:32:01 2001 > +++ contrib/pgcrypto/crypt-blowfish.c Thu Sep 20 11:18:37 2001 > @@ -705,28 +705,3 @@ > return output; > } > > -char *_crypt_gensalt_blowfish_rn(unsigned long count, > - __CONST char *input, int size, char *output, int output_size) > -{ > - if (size < 16 || output_size < 7 + 22 + 1 || > - (count && (count < 4 || count > 31))) { > - if (output_size > 0) output[0] = '\0'; > - __set_errno((output_size < 7 + 22 + 1) ? ERANGE : EINVAL); > - return NULL; > - } > - > - if (!count) count = 5; > - > - output[0] = '$'; > - output[1] = '2'; > - output[2] = 'a'; > - output[3] = '$'; > - output[4] = '0' + count / 10; > - output[5] = '0' + count % 10; > - output[6] = '$'; > - > - BF_encode(&output[7], (BF_word *)input, 16); > - output[7 + 22] = '\0'; > - > - return output; > -} > diff -urNX /home/marko/misc/diff-exclude contrib/pgcrypto.orig/crypt-gensalt.c contrib/pgcrypto/crypt-gensalt.c > --- contrib/pgcrypto.orig/crypt-gensalt.c Thu Jan 1 03:00:00 1970 > +++ contrib/pgcrypto/crypt-gensalt.c Wed Sep 19 12:01:51 2001 > @@ -0,0 +1,181 @@ > +/* > + * Written by Solar Designer and placed in the public domain. > + * See crypt_blowfish.c for more information. > + * > + * This file contains salt generation functions for the traditional and > + * other common crypt(3) algorithms, except for bcrypt which is defined > + * entirely in crypt_blowfish.c. > + * > + * Put bcrypt generator also here as crypt-blowfish.c > + * may not be compiled always. -- marko > + */ > + > +#include <postgres.h> > +#include "px-crypt.h" > + > +#include <errno.h> > +#ifndef __set_errno > +#define __set_errno(val) errno = (val) > +#endif > + > +#undef __CONST > +#ifdef __GNUC__ > +#define __CONST __const > +#else > +#define __CONST > +#endif > + > +typedef unsigned int BF_word; > + > +unsigned char _crypt_itoa64[64 + 1] = > + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; > + > +char *_crypt_gensalt_traditional_rn(unsigned long count, > + __CONST char *input, int size, char *output, int output_size) > +{ > + if (size < 2 || output_size < 2 + 1 || (count && count != 25)) { > + if (output_size > 0) output[0] = '\0'; > + __set_errno((output_size < 2 + 1) ? ERANGE : EINVAL); > + return NULL; > + } > + > + output[0] = _crypt_itoa64[(unsigned int)input[0] & 0x3f]; > + output[1] = _crypt_itoa64[(unsigned int)input[1] & 0x3f]; > + output[2] = '\0'; > + > + return output; > +} > + > +char *_crypt_gensalt_extended_rn(unsigned long count, > + __CONST char *input, int size, char *output, int output_size) > +{ > + unsigned long value; > + > +/* Even iteration counts make it easier to detect weak DES keys from a look > + * at the hash, so they should be avoided */ > + if (size < 3 || output_size < 1 + 4 + 4 + 1 || > + (count && (count > 0xffffff || !(count & 1)))) { > + if (output_size > 0) output[0] = '\0'; > + __set_errno((output_size < 1 + 4 + 4 + 1) ? ERANGE : EINVAL); > + return NULL; > + } > + > + if (!count) count = 725; > + > + output[0] = '_'; > + output[1] = _crypt_itoa64[count & 0x3f]; > + output[2] = _crypt_itoa64[(count >> 6) & 0x3f]; > + output[3] = _crypt_itoa64[(count >> 12) & 0x3f]; > + output[4] = _crypt_itoa64[(count >> 18) & 0x3f]; > + value = (unsigned long)input[0] | > + ((unsigned long)input[1] << 8) | > + ((unsigned long)input[2] << 16); > + output[5] = _crypt_itoa64[value & 0x3f]; > + output[6] = _crypt_itoa64[(value >> 6) & 0x3f]; > + output[7] = _crypt_itoa64[(value >> 12) & 0x3f]; > + output[8] = _crypt_itoa64[(value >> 18) & 0x3f]; > + output[9] = '\0'; > + > + return output; > +} > + > +char *_crypt_gensalt_md5_rn(unsigned long count, > + __CONST char *input, int size, char *output, int output_size) > +{ > + unsigned long value; > + > + if (size < 3 || output_size < 3 + 4 + 1 || (count && count != 1000)) { > + if (output_size > 0) output[0] = '\0'; > + __set_errno((output_size < 3 + 4 + 1) ? ERANGE : EINVAL); > + return NULL; > + } > + > + output[0] = '$'; > + output[1] = '1'; > + output[2] = '$'; > + value = (unsigned long)input[0] | > + ((unsigned long)input[1] << 8) | > + ((unsigned long)input[2] << 16); > + output[3] = _crypt_itoa64[value & 0x3f]; > + output[4] = _crypt_itoa64[(value >> 6) & 0x3f]; > + output[5] = _crypt_itoa64[(value >> 12) & 0x3f]; > + output[6] = _crypt_itoa64[(value >> 18) & 0x3f]; > + output[7] = '\0'; > + > + if (size >= 6 && output_size >= 3 + 4 + 4 + 1) { > + value = (unsigned long)input[3] | > + ((unsigned long)input[4] << 8) | > + ((unsigned long)input[5] << 16); > + output[7] = _crypt_itoa64[value & 0x3f]; > + output[8] = _crypt_itoa64[(value >> 6) & 0x3f]; > + output[9] = _crypt_itoa64[(value >> 12) & 0x3f]; > + output[10] = _crypt_itoa64[(value >> 18) & 0x3f]; > + output[11] = '\0'; > + } > + > + return output; > +} > + > + > + > +static unsigned char BF_itoa64[64 + 1] = > + "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; > + > +static void BF_encode(char *dst, __CONST BF_word *src, int size) > +{ > + unsigned char *sptr = (unsigned char *)src; > + unsigned char *end = sptr + size; > + unsigned char *dptr = (unsigned char *)dst; > + unsigned int c1, c2; > + > + do { > + c1 = *sptr++; > + *dptr++ = BF_itoa64[c1 >> 2]; > + c1 = (c1 & 0x03) << 4; > + if (sptr >= end) { > + *dptr++ = BF_itoa64[c1]; > + break; > + } > + > + c2 = *sptr++; > + c1 |= c2 >> 4; > + *dptr++ = BF_itoa64[c1]; > + c1 = (c2 & 0x0f) << 2; > + if (sptr >= end) { > + *dptr++ = BF_itoa64[c1]; > + break; > + } > + > + c2 = *sptr++; > + c1 |= c2 >> 6; > + *dptr++ = BF_itoa64[c1]; > + *dptr++ = BF_itoa64[c2 & 0x3f]; > + } while (sptr < end); > +} > + > +char *_crypt_gensalt_blowfish_rn(unsigned long count, > + __CONST char *input, int size, char *output, int output_size) > +{ > + if (size < 16 || output_size < 7 + 22 + 1 || > + (count && (count < 4 || count > 31))) { > + if (output_size > 0) output[0] = '\0'; > + __set_errno((output_size < 7 + 22 + 1) ? ERANGE : EINVAL); > + return NULL; > + } > + > + if (!count) count = 5; > + > + output[0] = '$'; > + output[1] = '2'; > + output[2] = 'a'; > + output[3] = '$'; > + output[4] = '0' + count / 10; > + output[5] = '0' + count % 10; > + output[6] = '$'; > + > + BF_encode(&output[7], (BF_word *)input, 16); > + output[7 + 22] = '\0'; > + > + return output; > +} > + > Binary files contrib/pgcrypto.orig/libpgcrypto.so.0 and contrib/pgcrypto/libpgcrypto.so.0 differ > diff -urNX /home/marko/misc/diff-exclude contrib/pgcrypto.orig/openssl.c contrib/pgcrypto/openssl.c > --- contrib/pgcrypto.orig/openssl.c Tue Aug 21 02:42:41 2001 > +++ contrib/pgcrypto/openssl.c Thu Sep 20 11:40:12 2001 > @@ -35,7 +35,6 @@ > > #include <openssl/evp.h> > #include <openssl/blowfish.h> > -/*#include <openssl/crypto.h>*/ > > static uint > digest_result_size(PX_MD * h) > diff -urNX /home/marko/misc/diff-exclude contrib/pgcrypto.orig/pgcrypto.c contrib/pgcrypto/pgcrypto.c > --- contrib/pgcrypto.orig/pgcrypto.c Tue Aug 21 02:42:41 2001 > +++ contrib/pgcrypto/pgcrypto.c Wed Sep 19 10:22:27 2001 > @@ -200,9 +200,44 @@ > 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); > + len = px_gen_salt(buf, buf, 0); > 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_gen_salt(text, int4) returns text */ > +PG_FUNCTION_INFO_V1(pg_gen_salt_rounds); > + > +Datum > +pg_gen_salt_rounds(PG_FUNCTION_ARGS) > +{ > + text *arg0; > + int rounds; > + uint len; > + text *res; > + char buf[PX_MAX_SALT_LEN + 1]; > + > + if (PG_ARGISNULL(0) || PG_ARGISNULL(1)) > + PG_RETURN_NULL(); > + > + arg0 = PG_GETARG_TEXT_P(0); > + rounds = PG_GETARG_INT32(1); > + > + 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, rounds); > + if (len == 0) > + elog(ERROR, "No such crypt algorithm or bad number of rounds"); > > res = (text *) palloc(len + VARHDRSZ); > VARATT_SIZEP(res) = len + VARHDRSZ; > diff -urNX /home/marko/misc/diff-exclude contrib/pgcrypto.orig/pgcrypto.h contrib/pgcrypto/pgcrypto.h > --- contrib/pgcrypto.orig/pgcrypto.h Tue Aug 21 02:42:41 2001 > +++ contrib/pgcrypto/pgcrypto.h Mon Sep 17 20:21:39 2001 > @@ -38,6 +38,7 @@ > Datum pg_hmac(PG_FUNCTION_ARGS); > Datum pg_hmac_exists(PG_FUNCTION_ARGS); > Datum pg_gen_salt(PG_FUNCTION_ARGS); > +Datum pg_gen_salt_rounds(PG_FUNCTION_ARGS); > Datum pg_crypt(PG_FUNCTION_ARGS); > Datum pg_encrypt(PG_FUNCTION_ARGS); > Datum pg_decrypt(PG_FUNCTION_ARGS); > diff -urNX /home/marko/misc/diff-exclude contrib/pgcrypto.orig/pgcrypto.sql contrib/pgcrypto/pgcrypto.sql > --- contrib/pgcrypto.orig/pgcrypto.sql Thu Jan 1 03:00:00 1970 > +++ contrib/pgcrypto/pgcrypto.sql Sat Sep 22 02:36:53 2001 > @@ -0,0 +1,65 @@ > + > +-- drop function digest(bytea, text); > +-- drop function digest_exists(text); > +-- drop function hmac(bytea, bytea, text); > +-- drop function hmac_exists(text); > +-- drop function crypt(text, text); > +-- drop function gen_salt(text); > +-- drop function gen_salt(text, int4); > +-- 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); > +-- drop function cipher_exists(text); > + > + > + > +CREATE FUNCTION digest(bytea, text) RETURNS bytea > + AS '$libdir/pgcrypto', > + 'pg_digest' LANGUAGE 'C'; > + > +CREATE FUNCTION digest_exists(text) RETURNS bool > + AS '$libdir/pgcrypto', > + 'pg_digest_exists' LANGUAGE 'C'; > + > +CREATE FUNCTION hmac(bytea, bytea, text) RETURNS bytea > + AS '$libdir/pgcrypto', > + 'pg_hmac' LANGUAGE 'C'; > + > +CREATE FUNCTION hmac_exists(text) RETURNS bool > + AS '$libdir/pgcrypto', > + 'pg_hmac_exists' LANGUAGE 'C'; > + > +CREATE FUNCTION crypt(text, text) RETURNS text > + AS '$libdir/pgcrypto', > + 'pg_crypt' LANGUAGE 'C'; > + > +CREATE FUNCTION gen_salt(text) RETURNS text > + AS '$libdir/pgcrypto', > + 'pg_gen_salt' LANGUAGE 'C'; > + > +CREATE FUNCTION gen_salt(text, int4) RETURNS text > + AS '$libdir/pgcrypto', > + 'pg_gen_salt_rounds' LANGUAGE 'C'; > + > +CREATE FUNCTION encrypt(bytea, bytea, text) RETURNS bytea > + AS '$libdir/pgcrypto', > + 'pg_encrypt' LANGUAGE 'C'; > + > +CREATE FUNCTION decrypt(bytea, bytea, text) RETURNS bytea > + AS '$libdir/pgcrypto', > + 'pg_decrypt' LANGUAGE 'C'; > + > +CREATE FUNCTION encrypt_iv(bytea, bytea, bytea, text) RETURNS bytea > + AS '$libdir/pgcrypto', > + 'pg_encrypt_iv' LANGUAGE 'C'; > + > +CREATE FUNCTION decrypt_iv(bytea, bytea, bytea, text) RETURNS bytea > + AS '$libdir/pgcrypto', > + 'pg_decrypt_iv' LANGUAGE 'C'; > + > +CREATE FUNCTION cipher_exists(text) RETURNS bool > + AS '$libdir/pgcrypto', > + 'pg_cipher_exists' LANGUAGE 'C'; > + > + > diff -urNX /home/marko/misc/diff-exclude contrib/pgcrypto.orig/pgcrypto.sql.in contrib/pgcrypto/pgcrypto.sql.in > --- contrib/pgcrypto.orig/pgcrypto.sql.in Tue Aug 21 02:42:41 2001 > +++ contrib/pgcrypto/pgcrypto.sql.in Mon Sep 17 20:23:56 2001 > @@ -5,10 +5,12 @@ > -- drop function hmac_exists(text); > -- drop function crypt(text, text); > -- drop function gen_salt(text); > +-- drop function gen_salt(text, int4); > -- 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); > +-- drop function cipher_exists(text); > > > > @@ -35,6 +37,10 @@ > CREATE FUNCTION gen_salt(text) RETURNS text > AS '@MODULE_FILENAME@', > 'pg_gen_salt' LANGUAGE 'C'; > + > +CREATE FUNCTION gen_salt(text, int4) RETURNS text > + AS '@MODULE_FILENAME@', > + 'pg_gen_salt_rounds' LANGUAGE 'C'; > > CREATE FUNCTION encrypt(bytea, bytea, text) RETURNS bytea > AS '@MODULE_FILENAME@', > diff -urNX /home/marko/misc/diff-exclude contrib/pgcrypto.orig/px-crypt.c contrib/pgcrypto/px-crypt.c > --- contrib/pgcrypto.orig/px-crypt.c Tue Aug 21 03:32:01 2001 > +++ contrib/pgcrypto/px-crypt.c Wed Sep 19 11:34:43 2001 > @@ -30,6 +30,7 @@ > */ > > #include <postgres.h> > +#include "px.h" > #include "px-crypt.h" > > > @@ -62,12 +63,8 @@ > char *buf, unsigned len) > { > char *res; > - > res = _crypt_blowfish_rn(psw, salt, buf, len); > - if (!res) > - return NULL; > - strcpy(buf, res); > - return buf; > + return res; > } > > static struct > @@ -128,106 +125,53 @@ > * salt generators > */ > > -static int my_rand64() > -{ > - return random() % 64; > -} > - > -static uint > -gen_des_salt(char *buf) > -{ > - buf[0] = px_crypt_a64[my_rand64()]; > - buf[1] = px_crypt_a64[my_rand64()]; > - buf[2] = 0; > - > - return 2; > -} > - > -static uint > -gen_xdes_salt(char *buf) > -{ > - strcpy(buf, "_12345678"); > - > - px_crypt_to64(buf+1, (long)PX_XDES_ROUNDS, 4); > - px_crypt_to64(buf+5, random(), 4); > - > - return 9; > -} > - > -static uint > -gen_md5_salt(char *buf) > -{ > - int i; > - strcpy(buf, "$1$12345678$"); > - > - for (i = 0; i < 8; i++) > - buf[3 + i] = px_crypt_a64[my_rand64()]; > - > - return 12; > -} > - > -static uint > -gen_bf_salt(char *buf) > -{ > - int i, count; > - char *s; > - char saltbuf[16+3]; > - unsigned slen = 16; > - uint32 *v; > - > - for (i = 0; i < slen; i++) > - saltbuf[i] = random() & 255; > - saltbuf[16] = 0; > - saltbuf[17] = 0; > - saltbuf[18] = 0; > - > - strcpy(buf, "$2a$00$0123456789012345678901"); > - > - count = PX_BF_ROUNDS; > - buf[4] = '0' + count / 10; > - buf[5] = '0' + count % 10; > - > - s = buf + 7; > - for (i = 0; i < slen; ) > - { > - v = (uint32 *)&saltbuf[i]; > - if (i + 3 <= slen) > - px_crypt_to64(s, *v, 4); > - else > - /* slen-i could be 1,2 make it 2,3 */ > - px_crypt_to64(s, *v, slen-i+1); > - s += 4; > - i += 3; > - } > - > - s = buf; > - /*s = _crypt_gensalt_blowfish_rn(count, saltbuf, 16, buf, PX_MAX_CRYPT);*/ > - > - return s ? strlen(s) : 0; > -} > - > struct generator { > char *name; > - uint (*gen)(char *buf); > + char *(*gen)(unsigned long count, const char *input, int size, > + char *output, int output_size); > + int input_len; > + int def_rounds; > + int min_rounds; > + int max_rounds; > }; > > static struct generator gen_list [] = { > - { "des", gen_des_salt }, > - { "md5", gen_md5_salt }, > - { "xdes", gen_xdes_salt }, > - { "bf", gen_bf_salt }, > - { NULL, NULL } > + { "des", _crypt_gensalt_traditional_rn, 2, 0, 0, 0 }, > + { "md5", _crypt_gensalt_md5_rn, 6, 0, 0, 0 }, > + { "xdes", _crypt_gensalt_extended_rn, 3, PX_XDES_ROUNDS, 1, 0xFFFFFF }, > + { "bf", _crypt_gensalt_blowfish_rn, 16, PX_BF_ROUNDS, 4, 31 }, > + { NULL, NULL, 0, 0, 0 } > }; > > uint > -px_gen_salt(const char *salt_type, char *buf) > +px_gen_salt(const char *salt_type, char *buf, int rounds) > { > - int i; > + int i, res; > struct generator *g; > + char *p; > + char rbuf[16]; > + > for (i = 0; gen_list[i].name; i++) { > g = &gen_list[i]; > - if (!strcasecmp(g->name, salt_type)) > - return g->gen(buf); > + if (strcasecmp(g->name, salt_type) != 0) > + continue; > + > + if (g->def_rounds) { > + if (rounds == 0) > + rounds = g->def_rounds; > + > + if (rounds < g->min_rounds || rounds > g->max_rounds) > + return 0; > + } > + > + res = px_get_random_bytes(rbuf, g->input_len); > + if (res != g->input_len) > + return 0; > + > + p = g->gen(rounds, rbuf, g->input_len, buf, PX_MAX_SALT_LEN); > + memset(rbuf, 0, sizeof(rbuf)); > + > + return p != NULL ? strlen(p) : 0; > } > > return 0; > diff -urNX /home/marko/misc/diff-exclude contrib/pgcrypto.orig/px-crypt.h contrib/pgcrypto/px-crypt.h > --- contrib/pgcrypto.orig/px-crypt.h Tue Aug 21 03:32:01 2001 > +++ contrib/pgcrypto/px-crypt.h Wed Sep 19 10:03:03 2001 > @@ -38,19 +38,22 @@ > /* max salt returned by gen_salt() */ > #define PX_MAX_SALT_LEN 128 > > -/* rounds for xdes salt */ > +/* default rounds for xdes salt */ > /* NetBSD bin/passwd/local_passwd.c has (29 * 25)*/ > #define PX_XDES_ROUNDS (29 * 25) > > -/* rounds for blowfish salt */ > +/* default for blowfish salt */ > #define PX_BF_ROUNDS 6 > > /* > * main interface > */ > char *px_crypt(const char *psw, const char *salt, char *buf, unsigned buflen); > -unsigned px_gen_salt(const char *salt_type, char *dst); > +unsigned px_gen_salt(const char *salt_type, char *dst, int rounds); > > +/* > + * internal functions > + */ > > /* misc.c */ > extern void px_crypt_to64(char *s, unsigned long v, int n); > @@ -59,6 +62,15 @@ > #define _crypt_to64 px_crypt_to64 > #define _crypt_a64 px_crypt_a64 > > +/* crypt-gensalt.c */ > +char *_crypt_gensalt_traditional_rn(unsigned long count, > + const char *input, int size, char *output, int output_size); > +char *_crypt_gensalt_extended_rn(unsigned long count, > + const char *input, int size, char *output, int output_size); > +char *_crypt_gensalt_md5_rn(unsigned long count, > + const char *input, int size, char *output, int output_size); > +char *_crypt_gensalt_blowfish_rn(unsigned long count, > + const char *input, int size, char *output, int output_size); > > #ifndef PX_SYSTEM_CRYPT > > @@ -66,9 +78,6 @@ > /* #define DISABLE_XDES */ > > /* crypt-blowfish.c */ > -char *_crypt_gensalt_blowfish_rn(unsigned long count, > - const char *input, int size, > - char *output, int output_size); > char *_crypt_blowfish_rn(const char *key, const char *setting, > char *output, int size); > > diff -urNX /home/marko/misc/diff-exclude contrib/pgcrypto.orig/px.h contrib/pgcrypto/px.h > --- contrib/pgcrypto.orig/px.h Tue Aug 21 03:32:01 2001 > +++ contrib/pgcrypto/px.h Wed Sep 19 13:38:42 2001 > @@ -133,6 +133,8 @@ > int px_find_cipher(const char *name, PX_Cipher **res); > int px_find_combo(const char *name, PX_Combo **res); > > +int px_get_random_bytes(uint8 *dst, unsigned count); > + > const char *px_resolve_alias(const PX_Alias *aliases, const char *name); > > #define px_md_result_size(md) (md)->result_size(md) > diff -urNX /home/marko/misc/diff-exclude contrib/pgcrypto.orig/random.c contrib/pgcrypto/random.c > --- contrib/pgcrypto.orig/random.c Thu Jan 1 03:00:00 1970 > +++ contrib/pgcrypto/random.c Thu Sep 20 11:39:49 2001 > @@ -0,0 +1,127 @@ > +/* > + * random.c > + * Random functions. > + * > + * Copyright (c) 2001 Marko Kreen > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * > + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND > + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE > + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE > + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE > + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL > + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS > + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) > + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT > + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY > + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > + * SUCH DAMAGE. > + * > + * $Id$ > + */ > + > + > +#include <postgres.h> > + > +#include "px.h" > + > + > +#ifdef RAND_DEV > + > +#include <errno.h> > +#include <fcntl.h> > +#include <unistd.h> > + > +static int > +safe_read(int fd, void *buf, size_t count) > +{ > + int done = 0; > + char *p = buf; > + int res; > + > + while (count) { > + res = read(fd, p, count); > + if (res <= 0) { > + if (errno == EINTR) > + continue; > + return -1; > + } > + p += res; > + done += res; > + count -= res; > + } > + return done; > +} > + > +int > +px_get_random_bytes(uint8 *dst, unsigned count) > +{ > + int fd; > + int res; > + > + fd = open(RAND_DEV, O_RDONLY); > + if (fd == -1) > + return -1; > + res = safe_read(fd, dst, count); > + close(fd); > + return res; > +} > + > +#endif /* RAND_DEV */ > + > +#ifdef RAND_SILLY > + > +int px_get_random_bytes(char *dst, unsigned count) > +{ > + int i; > + for (i = 0; i < count; i++) { > + *dst++ = random(); > + } > + return i; > +} > + > +#endif /* RAND_SILLY */ > + > +#ifdef RAND_OPENSSL > + > +#include <openssl/evp.h> > +#include <openssl/blowfish.h> > +#include <openssl/rand.h> > +#include <openssl/err.h> > + > +static int openssl_random_init = 0; > + > +int px_get_random_bytes(uint8 *dst, unsigned count) > +{ > + int res; > + > + if (!openssl_random_init) { > + if (RAND_get_rand_method() == NULL) { > + RAND_set_rand_method(RAND_SSLeay()); > + } > + openssl_random_init = 1; > + } > + > + /* > + * OpenSSL random should re-feeded occasionally. > + * From /dev/urandom preferrably. > + */ > + > + res = RAND_bytes(dst, count); > + if (res > 0) > + return count; > + > + return -1; > +} > + > +#endif /* RAND_OPENSSL */ > + > > ---------------------------(end of broadcast)--------------------------- > TIP 4: Don't 'kill -9' the postmaster > -- Bruce Momjian | http://candle.pha.pa.us pgman@candle.pha.pa.us | (610) 853-3000 + If your life is a hard drive, | 830 Blythe Avenue + Christ can be your backup. | Drexel Hill, Pennsylvania 19026
pgsql-patches by date: