Re: pgcrypto update

From: Bruce Momjian <pgman(at)candle(dot)pha(dot)pa(dot)us>
To: Marko Kreen <marko(at)l-t(dot)ee>
Cc: pgsql-patches(at)postgresql(dot)org
Subject: Re: pgcrypto update
Date: 2001-09-23 04:14:11
Message-ID: 200109230414.f8N4EBr05021@candle.pha.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: 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(at)candle(dot)pha(dot)pa(dot)us | (610) 853-3000
+ If your life is a hard drive, | 830 Blythe Avenue
+ Christ can be your backup. | Drexel Hill, Pennsylvania 19026

In response to

Browse pgsql-patches by date

  From Date Subject
Next Message Bruce Momjian 2001-09-23 04:14:23 Re: JDBC test suite patch
Previous Message Bruce Momjian 2001-09-23 04:11:11 Re: JDBC test suite patch