"Annual" pgcrypto update from Marko Kreen:

Few cleanups and couple of new things:

 - add SHA2 algorithm to older OpenSSL
 - add BIGNUM math to have public-key cryptography work on non-OpenSSL
   build.
 - gen_random_bytes() function

The status of SHA2 algoritms and public-key encryption can now be
changed to 'always available.'

That makes pgcrypto functionally complete and unless there will be new
editions of AES, SHA2 or OpenPGP standards, there is no major changes
planned.
This commit is contained in:
Neil Conway 2006-07-13 04:15:25 +00:00
parent 99ac1e69ba
commit 1abf76e82c
22 changed files with 4397 additions and 374 deletions

View File

@ -1,29 +1,26 @@
#
# $PostgreSQL: pgsql/contrib/pgcrypto/Makefile,v 1.23 2005/09/27 17:13:08 tgl Exp $
# $PostgreSQL: pgsql/contrib/pgcrypto/Makefile,v 1.24 2006/07/13 04:15:24 neilc Exp $
#
INT_SRCS = md5.c sha1.c sha2.c internal.c blf.c rijndael.c \
fortuna.c random.c pgp-mpi-internal.c
INT_SRCS = md5.c sha1.c sha2.c internal.c internal-sha2.c blf.c rijndael.c \
fortuna.c random.c pgp-mpi-internal.c imath.c
INT_TESTS = sha2
OSSL_SRCS = openssl.c pgp-mpi-openssl.c
OSSL_TESTS = des 3des cast5
OSSL_TESTS = sha2 des 3des cast5
ZLIB_OFF_CFLAGS = -DDISABLE_ZLIB
ZLIB_TST = pgp-compression
ZLIB_OFF_TST = pgp-zlib-DISABLED
PUBENC_ON = pgp-pubkey-decrypt pgp-pubkey-encrypt pgp-info
PUBENC_OFF = pgp-pubkey-DISABLED
CF_SRCS = $(if $(subst no,,$(with_openssl)), $(OSSL_SRCS), $(INT_SRCS))
CF_TESTS = $(if $(subst no,,$(with_openssl)), $(OSSL_TESTS), $(INT_TESTS))
CF_CFLAGS = $(if $(subst yes,,$(with_zlib)), $(ZLIB_OFF_CFLAGS))
CF_PGP_TESTS = $(if $(subst no,,$(with_zlib)), $(ZLIB_TST), $(ZLIB_OFF_TST)) \
$(if $(subst no,,$(with_openssl)), $(PUBENC_ON), $(PUBENC_OFF))
CF_PGP_TESTS = $(if $(subst no,,$(with_zlib)), $(ZLIB_TST), $(ZLIB_OFF_TST))
PG_CPPFLAGS = $(CF_CFLAGS)
SRCS = pgcrypto.c px.c px-hmac.c px-crypt.c misc.c \
SRCS = pgcrypto.c px.c px-hmac.c px-crypt.c \
crypt-gensalt.c crypt-blowfish.c crypt-des.c \
crypt-md5.c $(CF_SRCS) \
mbuf.c pgp.c pgp-armor.c pgp-cfb.c pgp-compress.c \
@ -35,12 +32,14 @@ MODULE_big = pgcrypto
OBJS = $(SRCS:.c=.o)
DOCS = README.pgcrypto
DATA_built = pgcrypto.sql
DATA = uninstall_pgcrypto.sql
EXTRA_CLEAN = gen-rtab
REGRESS = init md5 sha1 hmac-md5 hmac-sha1 blowfish rijndael \
$(CF_TESTS) \
crypt-des crypt-md5 crypt-blowfish crypt-xdes \
pgp-armor pgp-decrypt pgp-encrypt $(CF_PGP_TESTS)
pgp-armor pgp-decrypt pgp-encrypt $(CF_PGP_TESTS) \
pgp-pubkey-decrypt pgp-pubkey-encrypt pgp-info
ifdef USE_PGXS

View File

@ -49,14 +49,14 @@ There are some other differences with and without OpenSSL:
----------------------------------------------------
MD5 yes yes
SHA1 yes yes
SHA256/384/512 yes since 0.9.8
SHA224/256/384/512 yes yes (3)
Any other digest algo no yes (1)
Blowfish yes yes
AES yes yes (2)
DES/3DES/CAST5 no yes
Raw encryption yes yes
PGP Symmetric encryption yes yes
PGP Public-Key encryption no yes
PGP Public-Key encryption yes yes
----------------------------------------------------
1. Any digest algorithm OpenSSL supports is automatically picked up.
@ -67,6 +67,9 @@ There are some other differences with and without OpenSSL:
compiled against older version, it will use built-in AES code,
so it has AES always available.
3. SHA2 algorithms were added to OpenSSL in version 0.9.8. For
older versions, pgcrypto will use built-in code.
2.2. NULL handling
~~~~~~~~~~~~~~~~~~~~
@ -621,14 +624,24 @@ is equal to
encrypt(data, 'fooz', 'bf-cbc/pad:pkcs')
7. Credits
7. Random bytes
-----------------
gen_random_bytes(count integer)
Returns `count` cryptographically strong random bytes as bytea value.
There can be maximally 1024 bytes extracted at a time. This is to avoid
draining the randomness generator pool.
8. Credits
------------
I have used code from following sources:
`--------------------`-------------------------`----------------------
`--------------------`-------------------------`-------------------------------
Algorithm Author Source origin
----------------------------------------------------------------------
-------------------------------------------------------------------------------
DES crypt() David Burren and others FreeBSD libcrypt
MD5 crypt() Poul-Henning Kamp FreeBSD libcrypt
Blowfish crypt() Solar Designer www.openwall.com
@ -636,21 +649,22 @@ I have used code from following sources:
Rijndael cipher Brian Gladman OpenBSD sys/crypto
MD5 and SHA1 WIDE Project KAME kame/sys/crypto
SHA256/384/512 Aaron D. Gifford OpenBSD sys/crypto
----------------------------------------------------------------------
BIGNUM math Michael J. Fromberger dartmouth.edu/~sting/sw/imath
-------------------------------------------------------------------------------
8. Legalese
9. Legalese
-------------
* I owe a beer to Poul-Henning.
* This product includes software developed by Niels Provos.
9. References/Links
---------------------
10. References/Links
----------------------
9.1. Useful reading
~~~~~~~~~~~~~~~~~~~~~
10.1. Useful reading
~~~~~~~~~~~~~~~~~~~~~~
http://www.gnupg.org/gph/en/manual.html[]::
The GNU Privacy Handbook
@ -668,8 +682,8 @@ http://www.interhack.net/people/cmcurtin/snake-oil-faq.html[]::
Describes good and bad cryptography.
9.2. Technical references
~~~~~~~~~~~~~~~~~~~~~~~~~~~
10.2. Technical references
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
http://www.ietf.org/rfc/rfc2440.txt[]::
OpenPGP message format
@ -699,4 +713,4 @@ http://www.cs.ut.ee/~helger/crypto/[]::
Collection of cryptology pointers.
// $PostgreSQL: pgsql/contrib/pgcrypto/README.pgcrypto,v 1.14 2005/11/03 02:54:07 tgl Exp $
// $PostgreSQL: pgsql/contrib/pgcrypto/README.pgcrypto,v 1.15 2006/07/13 04:15:24 neilc Exp $

View File

@ -1,7 +1,7 @@
/*
* FreeSec: libcrypt for NetBSD
*
* $PostgreSQL: pgsql/contrib/pgcrypto/crypt-des.c,v 1.14 2006/03/11 04:38:30 momjian Exp $
* $PostgreSQL: pgsql/contrib/pgcrypto/crypt-des.c,v 1.15 2006/07/13 04:15:24 neilc Exp $
*
* Copyright (c) 1994 David Burren
* All rights reserved.
@ -71,6 +71,9 @@
#define _PASSWORD_EFMT1 '_'
static const char _crypt_a64[] =
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
static uint8 IP[64] = {
58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4,
62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8,

View File

@ -2,7 +2,7 @@
* Written by Solar Designer and placed in the public domain.
* See crypt_blowfish.c for more information.
*
* $PostgreSQL: pgsql/contrib/pgcrypto/crypt-gensalt.c,v 1.8 2006/03/11 04:38:30 momjian Exp $
* $PostgreSQL: pgsql/contrib/pgcrypto/crypt-gensalt.c,v 1.9 2006/07/13 04:15:24 neilc Exp $
*
* This file contains salt generation functions for the traditional and
* other common crypt(3) algorithms, except for bcrypt which is defined
@ -19,7 +19,7 @@
typedef unsigned int BF_word;
unsigned char _crypt_itoa64[64 + 1] =
static unsigned char _crypt_itoa64[64 + 1] =
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
char *

View File

@ -8,7 +8,7 @@
*
* $FreeBSD: src/lib/libcrypt/crypt-md5.c,v 1.5 1999/12/17 20:21:45 peter Exp $
*
* $PostgreSQL: pgsql/contrib/pgcrypto/crypt-md5.c,v 1.6 2005/10/15 02:49:06 momjian Exp $
* $PostgreSQL: pgsql/contrib/pgcrypto/crypt-md5.c,v 1.7 2006/07/13 04:15:24 neilc Exp $
*/
#include "postgres.h"
@ -17,6 +17,20 @@
#include "px-crypt.h"
#define MD5_SIZE 16
static const char _crypt_a64[] =
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
static void
_crypt_to64(char *s, unsigned long v, int n)
{
while (--n >= 0)
{
*s++ = _crypt_a64[v & 0x3f];
v >>= 6;
}
}
/*
* UNIX password
*/

View File

@ -1,6 +1,37 @@
--
-- SHA2 family
--
-- SHA224
SELECT encode(digest('', 'sha224'), 'hex');
encode
----------------------------------------------------------
d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f
(1 row)
SELECT encode(digest('a', 'sha224'), 'hex');
encode
----------------------------------------------------------
abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5
(1 row)
SELECT encode(digest('abc', 'sha224'), 'hex');
encode
----------------------------------------------------------
23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7
(1 row)
SELECT encode(digest('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq', 'sha224'), 'hex');
encode
----------------------------------------------------------
75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525
(1 row)
SELECT encode(digest('12345678901234567890123456789012345678901234567890123456789012345678901234567890', 'sha224'), 'hex');
encode
----------------------------------------------------------
b50aecbe4e9bb0b57bc5f3ae760a8e01db24f203fb3cdcd13148046e
(1 row)
-- SHA256
SELECT encode(digest('', 'sha256'), 'hex');
encode

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $PostgreSQL: pgsql/contrib/pgcrypto/fortuna.c,v 1.6 2006/05/21 20:22:16 tgl Exp $
* $PostgreSQL: pgsql/contrib/pgcrypto/fortuna.c,v 1.7 2006/07/13 04:15:24 neilc Exp $
*/
#include "postgres.h"
@ -125,7 +125,7 @@ struct fortuna_state
struct timeval last_reseed_time;
unsigned pool0_bytes;
unsigned rnd_pos;
int counter_init;
int tricks_done;
};
typedef struct fortuna_state FState;
@ -332,7 +332,7 @@ add_entropy(FState * st, const uint8 *data, unsigned len)
/*
* Make sure the pool 0 is initialized, then update randomly.
*/
if (st->reseed_count == 0 && st->pool0_bytes < POOL0_FILL)
if (st->reseed_count == 0)
pos = 0;
else
pos = get_rand_pool(st);
@ -357,21 +357,34 @@ rekey(FState * st)
}
/*
* Fortuna relies on AES standing known-plaintext attack.
* In case it does not, slow down the attacker by initialising
* the couter to random value.
* Hide public constants. (counter, pools > 0)
*
* This can also be viewed as spreading the startup
* entropy over all of the components.
*/
static void
init_counter(FState * st)
startup_tricks(FState * st)
{
int i;
uint8 buf[BLOCK];
/* Use next block as counter. */
encrypt_counter(st, st->counter);
/* Now shuffle pools, excluding #0 */
for (i = 1; i < NUM_POOLS; i++)
{
encrypt_counter(st, buf);
encrypt_counter(st, buf + CIPH_BLOCK);
md_update(&st->pool[i], buf, BLOCK);
}
memset(buf, 0, BLOCK);
/* Hide the key. */
rekey(st);
/* The counter can be shuffled only once. */
st->counter_init = 1;
/* This can be done only once. */
st->tricks_done = 1;
}
static void
@ -380,13 +393,14 @@ extract_data(FState * st, unsigned count, uint8 *dst)
unsigned n;
unsigned block_nr = 0;
/* Can we reseed? */
if (st->pool0_bytes >= POOL0_FILL && enough_time_passed(st))
reseed(st);
/* Should we reseed? */
if (st->pool0_bytes >= POOL0_FILL || st->reseed_count == 0)
if (enough_time_passed(st))
reseed(st);
/* Is counter initialized? */
if (!st->counter_init)
init_counter(st);
/* Do some randomization on first call */
if (!st->tricks_done)
startup_tricks(st);
while (count > 0)
{

3261
contrib/pgcrypto/imath.c Normal file

File diff suppressed because it is too large Load Diff

212
contrib/pgcrypto/imath.h Normal file
View File

@ -0,0 +1,212 @@
/*
Name: imath.h
Purpose: Arbitrary precision integer arithmetic routines.
Author: M. J. Fromberger <http://www.dartmouth.edu/~sting/>
Info: $Id: imath.h,v 1.1 2006/07/13 04:15:24 neilc Exp $
Copyright (C) 2002 Michael J. Fromberger, All Rights Reserved.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files
(the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of the Software,
and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef IMATH_H_
#define IMATH_H_
/* use always 32bit digits - should some arch use 16bit digits? */
#define USE_LONG_LONG
#include <limits.h>
typedef unsigned char mp_sign;
typedef unsigned int mp_size;
typedef int mp_result;
#ifdef USE_LONG_LONG
typedef unsigned int mp_digit;
typedef unsigned long long mp_word;
#else
typedef unsigned short mp_digit;
typedef unsigned int mp_word;
#endif
typedef struct mpz {
mp_digit *digits;
mp_size alloc;
mp_size used;
mp_sign sign;
} mpz_t, *mp_int;
#define MP_DIGITS(Z) ((Z)->digits)
#define MP_ALLOC(Z) ((Z)->alloc)
#define MP_USED(Z) ((Z)->used)
#define MP_SIGN(Z) ((Z)->sign)
extern const mp_result MP_OK;
extern const mp_result MP_FALSE;
extern const mp_result MP_TRUE;
extern const mp_result MP_MEMORY;
extern const mp_result MP_RANGE;
extern const mp_result MP_UNDEF;
extern const mp_result MP_TRUNC;
extern const mp_result MP_BADARG;
#define MP_DIGIT_BIT (sizeof(mp_digit) * CHAR_BIT)
#define MP_WORD_BIT (sizeof(mp_word) * CHAR_BIT)
#ifdef USE_LONG_LONG
# ifndef ULONG_LONG_MAX
# ifdef ULLONG_MAX
# define ULONG_LONG_MAX ULLONG_MAX
# else
# error "Maximum value of unsigned long long not defined!"
# endif
# endif
# define MP_DIGIT_MAX (ULONG_MAX * 1ULL)
# define MP_WORD_MAX ULONG_LONG_MAX
#else
# define MP_DIGIT_MAX (USHRT_MAX * 1UL)
# define MP_WORD_MAX (UINT_MAX * 1UL)
#endif
#define MP_MIN_RADIX 2
#define MP_MAX_RADIX 36
extern const mp_sign MP_NEG;
extern const mp_sign MP_ZPOS;
#define mp_int_is_odd(Z) ((Z)->digits[0] & 1)
#define mp_int_is_even(Z) !((Z)->digits[0] & 1)
mp_size mp_get_default_precision(void);
void mp_set_default_precision(mp_size s);
mp_size mp_get_multiply_threshold(void);
void mp_set_multiply_threshold(mp_size s);
mp_result mp_int_init(mp_int z);
mp_int mp_int_alloc(void);
mp_result mp_int_init_size(mp_int z, mp_size prec);
mp_result mp_int_init_copy(mp_int z, mp_int old);
mp_result mp_int_init_value(mp_int z, int value);
mp_result mp_int_set_value(mp_int z, int value);
void mp_int_clear(mp_int z);
void mp_int_free(mp_int z);
mp_result mp_int_copy(mp_int a, mp_int c); /* c = a */
void mp_int_swap(mp_int a, mp_int c); /* swap a, c */
void mp_int_zero(mp_int z); /* z = 0 */
mp_result mp_int_abs(mp_int a, mp_int c); /* c = |a| */
mp_result mp_int_neg(mp_int a, mp_int c); /* c = -a */
mp_result mp_int_add(mp_int a, mp_int b, mp_int c); /* c = a + b */
mp_result mp_int_add_value(mp_int a, int value, mp_int c);
mp_result mp_int_sub(mp_int a, mp_int b, mp_int c); /* c = a - b */
mp_result mp_int_sub_value(mp_int a, int value, mp_int c);
mp_result mp_int_mul(mp_int a, mp_int b, mp_int c); /* c = a * b */
mp_result mp_int_mul_value(mp_int a, int value, mp_int c);
mp_result mp_int_mul_pow2(mp_int a, int p2, mp_int c);
mp_result mp_int_sqr(mp_int a, mp_int c); /* c = a * a */
mp_result mp_int_div(mp_int a, mp_int b, /* q = a / b */
mp_int q, mp_int r); /* r = a % b */
mp_result mp_int_div_value(mp_int a, int value, /* q = a / value */
mp_int q, int *r); /* r = a % value */
mp_result mp_int_div_pow2(mp_int a, int p2, /* q = a / 2^p2 */
mp_int q, mp_int r); /* r = q % 2^p2 */
mp_result mp_int_mod(mp_int a, mp_int m, mp_int c); /* c = a % m */
#define mp_int_mod_value(A, V, R) mp_int_div_value((A), (V), 0, (R))
mp_result mp_int_expt(mp_int a, int b, mp_int c); /* c = a^b */
mp_result mp_int_expt_value(int a, int b, mp_int c); /* c = a^b */
int mp_int_compare(mp_int a, mp_int b); /* a <=> b */
int mp_int_compare_unsigned(mp_int a, mp_int b); /* |a| <=> |b| */
int mp_int_compare_zero(mp_int z); /* a <=> 0 */
int mp_int_compare_value(mp_int z, int value); /* a <=> v */
/* Returns true if v|a, false otherwise (including errors) */
int mp_int_divisible_value(mp_int a, int v);
/* Returns k >= 0 such that z = 2^k, if one exists; otherwise < 0 */
int mp_int_is_pow2(mp_int z);
mp_result mp_int_exptmod(mp_int a, mp_int b, mp_int m,
mp_int c); /* c = a^b (mod m) */
mp_result mp_int_exptmod_evalue(mp_int a, int value,
mp_int m, mp_int c); /* c = a^v (mod m) */
mp_result mp_int_exptmod_bvalue(int value, mp_int b,
mp_int m, mp_int c); /* c = v^b (mod m) */
mp_result mp_int_exptmod_known(mp_int a, mp_int b,
mp_int m, mp_int mu,
mp_int c); /* c = a^b (mod m) */
mp_result mp_int_redux_const(mp_int m, mp_int c);
mp_result mp_int_invmod(mp_int a, mp_int m, mp_int c); /* c = 1/a (mod m) */
mp_result mp_int_gcd(mp_int a, mp_int b, mp_int c); /* c = gcd(a, b) */
mp_result mp_int_egcd(mp_int a, mp_int b, mp_int c, /* c = gcd(a, b) */
mp_int x, mp_int y); /* c = ax + by */
mp_result mp_int_sqrt(mp_int a, mp_int c); /* c = floor(sqrt(q)) */
/* Convert to an int, if representable (returns MP_RANGE if not). */
mp_result mp_int_to_int(mp_int z, int *out);
/* Convert to nul-terminated string with the specified radix, writing at
most limit characters including the nul terminator */
mp_result mp_int_to_string(mp_int z, mp_size radix,
char *str, int limit);
/* Return the number of characters required to represent
z in the given radix. May over-estimate. */
mp_result mp_int_string_len(mp_int z, mp_size radix);
/* Read zero-terminated string into z */
mp_result mp_int_read_string(mp_int z, mp_size radix, const char *str);
mp_result mp_int_read_cstring(mp_int z, mp_size radix, const char *str,
char **end);
/* Return the number of significant bits in z */
mp_result mp_int_count_bits(mp_int z);
/* Convert z to two's complement binary, writing at most limit bytes */
mp_result mp_int_to_binary(mp_int z, unsigned char *buf, int limit);
/* Read a two's complement binary value into z from the given buffer */
mp_result mp_int_read_binary(mp_int z, unsigned char *buf, int len);
/* Return the number of bytes required to represent z in binary. */
mp_result mp_int_binary_len(mp_int z);
/* Convert z to unsigned binary, writing at most limit bytes */
mp_result mp_int_to_unsigned(mp_int z, unsigned char *buf, int limit);
/* Read an unsigned binary value into z from the given buffer */
mp_result mp_int_read_unsigned(mp_int z, unsigned char *buf, int len);
/* Return the number of bytes required to represent z as unsigned output */
mp_result mp_int_unsigned_len(mp_int z);
/* Return a statically allocated string describing error code res */
const char *mp_error_string(mp_result res);
#if 0
void s_print(char *tag, mp_int z);
void s_print_buf(char *tag, mp_digit *buf, mp_size num);
#endif
#endif /* end IMATH_H_ */

View File

@ -0,0 +1,317 @@
/*
* internal.c
* Wrapper for builtin 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.
*
* $PostgreSQL: pgsql/contrib/pgcrypto/internal-sha2.c,v 1.1 2006/07/13 04:15:24 neilc Exp $
*/
#include "postgres.h"
#include <time.h>
#include "px.h"
#include "sha2.h"
void init_sha224(PX_MD * h);
void init_sha256(PX_MD * h);
void init_sha384(PX_MD * h);
void init_sha512(PX_MD * h);
/* SHA224 */
static unsigned
int_sha224_len(PX_MD * h)
{
return SHA224_DIGEST_LENGTH;
}
static unsigned
int_sha224_block_len(PX_MD * h)
{
return SHA224_BLOCK_LENGTH;
}
static void
int_sha224_update(PX_MD * h, const uint8 *data, unsigned dlen)
{
SHA224_CTX *ctx = (SHA224_CTX *) h->p.ptr;
SHA224_Update(ctx, data, dlen);
}
static void
int_sha224_reset(PX_MD * h)
{
SHA224_CTX *ctx = (SHA224_CTX *) h->p.ptr;
SHA224_Init(ctx);
}
static void
int_sha224_finish(PX_MD * h, uint8 *dst)
{
SHA224_CTX *ctx = (SHA224_CTX *) h->p.ptr;
SHA224_Final(dst, ctx);
}
static void
int_sha224_free(PX_MD * h)
{
SHA224_CTX *ctx = (SHA224_CTX *) h->p.ptr;
memset(ctx, 0, sizeof(*ctx));
px_free(ctx);
px_free(h);
}
/* SHA256 */
static unsigned
int_sha256_len(PX_MD * h)
{
return SHA256_DIGEST_LENGTH;
}
static unsigned
int_sha256_block_len(PX_MD * h)
{
return SHA256_BLOCK_LENGTH;
}
static void
int_sha256_update(PX_MD * h, const uint8 *data, unsigned dlen)
{
SHA256_CTX *ctx = (SHA256_CTX *) h->p.ptr;
SHA256_Update(ctx, data, dlen);
}
static void
int_sha256_reset(PX_MD * h)
{
SHA256_CTX *ctx = (SHA256_CTX *) h->p.ptr;
SHA256_Init(ctx);
}
static void
int_sha256_finish(PX_MD * h, uint8 *dst)
{
SHA256_CTX *ctx = (SHA256_CTX *) h->p.ptr;
SHA256_Final(dst, ctx);
}
static void
int_sha256_free(PX_MD * h)
{
SHA256_CTX *ctx = (SHA256_CTX *) h->p.ptr;
memset(ctx, 0, sizeof(*ctx));
px_free(ctx);
px_free(h);
}
/* SHA384 */
static unsigned
int_sha384_len(PX_MD * h)
{
return SHA384_DIGEST_LENGTH;
}
static unsigned
int_sha384_block_len(PX_MD * h)
{
return SHA384_BLOCK_LENGTH;
}
static void
int_sha384_update(PX_MD * h, const uint8 *data, unsigned dlen)
{
SHA384_CTX *ctx = (SHA384_CTX *) h->p.ptr;
SHA384_Update(ctx, data, dlen);
}
static void
int_sha384_reset(PX_MD * h)
{
SHA384_CTX *ctx = (SHA384_CTX *) h->p.ptr;
SHA384_Init(ctx);
}
static void
int_sha384_finish(PX_MD * h, uint8 *dst)
{
SHA384_CTX *ctx = (SHA384_CTX *) h->p.ptr;
SHA384_Final(dst, ctx);
}
static void
int_sha384_free(PX_MD * h)
{
SHA384_CTX *ctx = (SHA384_CTX *) h->p.ptr;
memset(ctx, 0, sizeof(*ctx));
px_free(ctx);
px_free(h);
}
/* SHA512 */
static unsigned
int_sha512_len(PX_MD * h)
{
return SHA512_DIGEST_LENGTH;
}
static unsigned
int_sha512_block_len(PX_MD * h)
{
return SHA512_BLOCK_LENGTH;
}
static void
int_sha512_update(PX_MD * h, const uint8 *data, unsigned dlen)
{
SHA512_CTX *ctx = (SHA512_CTX *) h->p.ptr;
SHA512_Update(ctx, data, dlen);
}
static void
int_sha512_reset(PX_MD * h)
{
SHA512_CTX *ctx = (SHA512_CTX *) h->p.ptr;
SHA512_Init(ctx);
}
static void
int_sha512_finish(PX_MD * h, uint8 *dst)
{
SHA512_CTX *ctx = (SHA512_CTX *) h->p.ptr;
SHA512_Final(dst, ctx);
}
static void
int_sha512_free(PX_MD * h)
{
SHA512_CTX *ctx = (SHA512_CTX *) h->p.ptr;
memset(ctx, 0, sizeof(*ctx));
px_free(ctx);
px_free(h);
}
/* init functions */
void
init_sha224(PX_MD * md)
{
SHA224_CTX *ctx;
ctx = px_alloc(sizeof(*ctx));
memset(ctx, 0, sizeof(*ctx));
md->p.ptr = ctx;
md->result_size = int_sha224_len;
md->block_size = int_sha224_block_len;
md->reset = int_sha224_reset;
md->update = int_sha224_update;
md->finish = int_sha224_finish;
md->free = int_sha224_free;
md->reset(md);
}
void
init_sha256(PX_MD * md)
{
SHA256_CTX *ctx;
ctx = px_alloc(sizeof(*ctx));
memset(ctx, 0, sizeof(*ctx));
md->p.ptr = ctx;
md->result_size = int_sha256_len;
md->block_size = int_sha256_block_len;
md->reset = int_sha256_reset;
md->update = int_sha256_update;
md->finish = int_sha256_finish;
md->free = int_sha256_free;
md->reset(md);
}
void
init_sha384(PX_MD * md)
{
SHA384_CTX *ctx;
ctx = px_alloc(sizeof(*ctx));
memset(ctx, 0, sizeof(*ctx));
md->p.ptr = ctx;
md->result_size = int_sha384_len;
md->block_size = int_sha384_block_len;
md->reset = int_sha384_reset;
md->update = int_sha384_update;
md->finish = int_sha384_finish;
md->free = int_sha384_free;
md->reset(md);
}
void
init_sha512(PX_MD * md)
{
SHA512_CTX *ctx;
ctx = px_alloc(sizeof(*ctx));
memset(ctx, 0, sizeof(*ctx));
md->p.ptr = ctx;
md->result_size = int_sha512_len;
md->block_size = int_sha512_block_len;
md->reset = int_sha512_reset;
md->update = int_sha512_update;
md->finish = int_sha512_finish;
md->free = int_sha512_free;
md->reset(md);
}

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $PostgreSQL: pgsql/contrib/pgcrypto/internal.c,v 1.23 2005/10/15 02:49:06 momjian Exp $
* $PostgreSQL: pgsql/contrib/pgcrypto/internal.c,v 1.24 2006/07/13 04:15:24 neilc Exp $
*/
#include "postgres.h"
@ -77,9 +77,11 @@
static void init_md5(PX_MD * h);
static void init_sha1(PX_MD * h);
static void init_sha256(PX_MD * h);
static void init_sha384(PX_MD * h);
static void init_sha512(PX_MD * h);
void init_sha224(PX_MD * h);
void init_sha256(PX_MD * h);
void init_sha384(PX_MD * h);
void init_sha512(PX_MD * h);
struct int_digest
{
@ -91,6 +93,7 @@ static const struct int_digest
int_digest_list[] = {
{"md5", init_md5},
{"sha1", init_sha1},
{"sha224", init_sha224},
{"sha256", init_sha256},
{"sha384", init_sha384},
{"sha512", init_sha512},
@ -193,150 +196,6 @@ int_sha1_free(PX_MD * h)
px_free(h);
}
/* SHA256 */
static unsigned
int_sha256_len(PX_MD * h)
{
return SHA256_DIGEST_LENGTH;
}
static unsigned
int_sha256_block_len(PX_MD * h)
{
return SHA256_BLOCK_LENGTH;
}
static void
int_sha256_update(PX_MD * h, const uint8 *data, unsigned dlen)
{
SHA256_CTX *ctx = (SHA256_CTX *) h->p.ptr;
SHA256_Update(ctx, data, dlen);
}
static void
int_sha256_reset(PX_MD * h)
{
SHA256_CTX *ctx = (SHA256_CTX *) h->p.ptr;
SHA256_Init(ctx);
}
static void
int_sha256_finish(PX_MD * h, uint8 *dst)
{
SHA256_CTX *ctx = (SHA256_CTX *) h->p.ptr;
SHA256_Final(dst, ctx);
}
static void
int_sha256_free(PX_MD * h)
{
SHA256_CTX *ctx = (SHA256_CTX *) h->p.ptr;
memset(ctx, 0, sizeof(*ctx));
px_free(ctx);
px_free(h);
}
/* SHA384 */
static unsigned
int_sha384_len(PX_MD * h)
{
return SHA384_DIGEST_LENGTH;
}
static unsigned
int_sha384_block_len(PX_MD * h)
{
return SHA384_BLOCK_LENGTH;
}
static void
int_sha384_update(PX_MD * h, const uint8 *data, unsigned dlen)
{
SHA384_CTX *ctx = (SHA384_CTX *) h->p.ptr;
SHA384_Update(ctx, data, dlen);
}
static void
int_sha384_reset(PX_MD * h)
{
SHA384_CTX *ctx = (SHA384_CTX *) h->p.ptr;
SHA384_Init(ctx);
}
static void
int_sha384_finish(PX_MD * h, uint8 *dst)
{
SHA384_CTX *ctx = (SHA384_CTX *) h->p.ptr;
SHA384_Final(dst, ctx);
}
static void
int_sha384_free(PX_MD * h)
{
SHA384_CTX *ctx = (SHA384_CTX *) h->p.ptr;
memset(ctx, 0, sizeof(*ctx));
px_free(ctx);
px_free(h);
}
/* SHA512 */
static unsigned
int_sha512_len(PX_MD * h)
{
return SHA512_DIGEST_LENGTH;
}
static unsigned
int_sha512_block_len(PX_MD * h)
{
return SHA512_BLOCK_LENGTH;
}
static void
int_sha512_update(PX_MD * h, const uint8 *data, unsigned dlen)
{
SHA512_CTX *ctx = (SHA512_CTX *) h->p.ptr;
SHA512_Update(ctx, data, dlen);
}
static void
int_sha512_reset(PX_MD * h)
{
SHA512_CTX *ctx = (SHA512_CTX *) h->p.ptr;
SHA512_Init(ctx);
}
static void
int_sha512_finish(PX_MD * h, uint8 *dst)
{
SHA512_CTX *ctx = (SHA512_CTX *) h->p.ptr;
SHA512_Final(dst, ctx);
}
static void
int_sha512_free(PX_MD * h)
{
SHA512_CTX *ctx = (SHA512_CTX *) h->p.ptr;
memset(ctx, 0, sizeof(*ctx));
px_free(ctx);
px_free(h);
}
/* init functions */
static void
@ -379,66 +238,6 @@ init_sha1(PX_MD * md)
md->reset(md);
}
static void
init_sha256(PX_MD * md)
{
SHA256_CTX *ctx;
ctx = px_alloc(sizeof(*ctx));
memset(ctx, 0, sizeof(*ctx));
md->p.ptr = ctx;
md->result_size = int_sha256_len;
md->block_size = int_sha256_block_len;
md->reset = int_sha256_reset;
md->update = int_sha256_update;
md->finish = int_sha256_finish;
md->free = int_sha256_free;
md->reset(md);
}
static void
init_sha384(PX_MD * md)
{
SHA384_CTX *ctx;
ctx = px_alloc(sizeof(*ctx));
memset(ctx, 0, sizeof(*ctx));
md->p.ptr = ctx;
md->result_size = int_sha384_len;
md->block_size = int_sha384_block_len;
md->reset = int_sha384_reset;
md->update = int_sha384_update;
md->finish = int_sha384_finish;
md->free = int_sha384_free;
md->reset(md);
}
static void
init_sha512(PX_MD * md)
{
SHA512_CTX *ctx;
ctx = px_alloc(sizeof(*ctx));
memset(ctx, 0, sizeof(*ctx));
md->p.ptr = ctx;
md->result_size = int_sha512_len;
md->block_size = int_sha512_block_len;
md->reset = int_sha512_reset;
md->update = int_sha512_update;
md->finish = int_sha512_finish;
md->free = int_sha512_free;
md->reset(md);
}
/*
* ciphers generally
*/
@ -821,19 +620,12 @@ px_find_cipher(const char *name, PX_Cipher ** res)
*/
/*
* Use libc for all 'public' bytes.
*
* That way we don't expose bytes from Fortuna
* to the public, in case it has some bugs.
* Use always strong randomness.
*/
int
px_get_pseudo_random_bytes(uint8 *dst, unsigned count)
{
int i;
for (i = 0; i < count; i++)
*dst++ = random();
return i;
return px_get_random_bytes(dst, count);
}
static time_t seed_time = 0;

View File

@ -1,51 +0,0 @@
/*
* Copyright (c) 1999
* University of California. All rights reserved.
*
* $PostgreSQL: pgsql/contrib/pgcrypto/misc.c,v 1.3 2006/03/11 04:38:30 momjian Exp $
*
* 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.
* 3. Neither the name of the author nor the names of any co-contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY 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 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.
*
* $FreeBSD: src/lib/libcrypt/misc.c,v 1.1 1999/09/20 12:45:49 markm Exp $
*
*/
#include "px-crypt.h"
char px_crypt_a64[] =
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
/* 0000000000111111111122222222223333333333444444444455555555556666 */
/* 0123456789012345678901234567890123456789012345678901234567890123 */
void
px_crypt_to64(char *s, unsigned long v, int n)
{
while (--n >= 0)
{
*s++ = px_crypt_a64[v & 0x3f];
v >>= 6;
}
}

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $PostgreSQL: pgsql/contrib/pgcrypto/openssl.c,v 1.27 2006/02/18 20:48:51 neilc Exp $
* $PostgreSQL: pgsql/contrib/pgcrypto/openssl.c,v 1.28 2006/07/13 04:15:25 neilc Exp $
*/
#include "postgres.h"
@ -146,6 +146,38 @@ static int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *res, unsigned int
#endif /* old OpenSSL */
/*
* Provide SHA2 for older OpenSSL < 0.9.8
*/
#if OPENSSL_VERSION_NUMBER < 0x00908000L
#include "sha2.c"
#include "internal-sha2.c"
typedef int (*init_f)(PX_MD *md);
static int compat_find_digest(const char *name, PX_MD **res)
{
init_f init = NULL;
if (pg_strcasecmp(name, "sha224") == 0)
init = init_sha224;
else if (pg_strcasecmp(name, "sha256") == 0)
init = init_sha256;
else if (pg_strcasecmp(name, "sha384") == 0)
init = init_sha384;
else if (pg_strcasecmp(name, "sha512") == 0)
init = init_sha512;
else
return PXE_NO_HASH;
*res = px_alloc(sizeof(PX_MD));
init(*res);
return 0;
}
#else
#define compat_find_digest(name, res) (PXE_NO_HASH)
#endif
/*
* Hashes
*/
@ -223,7 +255,7 @@ px_find_digest(const char *name, PX_MD ** res)
md = EVP_get_digestbyname(name);
if (md == NULL)
return PXE_NO_HASH;
return compat_find_digest(name, res);
digest = px_alloc(sizeof(*digest));
digest->algo = md;
@ -526,7 +558,7 @@ ossl_des3_ecb_encrypt(PX_Cipher * c, const uint8 *data, unsigned dlen,
ossldata *od = c->ptr;
for (i = 0; i < dlen / bs; i++)
DES_ecb3_encrypt(data + i * bs, res + i * bs,
DES_ecb3_encrypt((void *)(data + i * bs), (void *)(res + i * bs),
&od->u.des3.k1, &od->u.des3.k2, &od->u.des3.k3, 1);
return 0;
}
@ -540,7 +572,7 @@ ossl_des3_ecb_decrypt(PX_Cipher * c, const uint8 *data, unsigned dlen,
ossldata *od = c->ptr;
for (i = 0; i < dlen / bs; i++)
DES_ecb3_encrypt(data + i * bs, res + i * bs,
DES_ecb3_encrypt((void *)(data + i * bs), (void *)(res + i * bs),
&od->u.des3.k1, &od->u.des3.k2, &od->u.des3.k3, 0);
return 0;
}

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $PostgreSQL: pgsql/contrib/pgcrypto/pgcrypto.c,v 1.21 2006/05/30 22:12:13 tgl Exp $
* $PostgreSQL: pgsql/contrib/pgcrypto/pgcrypto.c,v 1.22 2006/07/13 04:15:25 neilc Exp $
*/
#include "postgres.h"
@ -537,6 +537,34 @@ pg_decrypt_iv(PG_FUNCTION_ARGS)
PG_RETURN_BYTEA_P(res);
}
/* SQL function: pg_random_bytes(int4) returns bytea */
PG_FUNCTION_INFO_V1(pg_random_bytes);
Datum
pg_random_bytes(PG_FUNCTION_ARGS)
{
int err;
int len = PG_GETARG_INT32(0);
bytea *res;
if (len < 1 || len > 1024)
ereport(ERROR,
(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
errmsg("Length not in range")));
res = palloc(VARHDRSZ + len);
VARATT_SIZEP(res) = VARHDRSZ + len;
/* generate result */
err = px_get_random_bytes((uint8*)VARDATA(res), len);
if (err < 0)
ereport(ERROR,
(errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
errmsg("Random generator error: %s", px_strerror(err))));
PG_RETURN_BYTEA_P(res);
}
/* SQL function: pg_cipher_exists(text) returns bool */
PG_FUNCTION_INFO_V1(pg_cipher_exists);

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $PostgreSQL: pgsql/contrib/pgcrypto/pgcrypto.h,v 1.9 2006/07/10 22:06:11 momjian Exp $
* $PostgreSQL: pgsql/contrib/pgcrypto/pgcrypto.h,v 1.10 2006/07/13 04:15:25 neilc Exp $
*/
#ifndef _PG_CRYPTO_H
@ -47,5 +47,6 @@ Datum pg_decrypt(PG_FUNCTION_ARGS);
Datum pg_encrypt_iv(PG_FUNCTION_ARGS);
Datum pg_decrypt_iv(PG_FUNCTION_ARGS);
Datum pg_cipher_exists(PG_FUNCTION_ARGS);
Datum pg_random_bytes(PG_FUNCTION_ARGS);
#endif

View File

@ -71,6 +71,11 @@ RETURNS bool
AS 'MODULE_PATHNAME', 'pg_cipher_exists'
LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION gen_random_bytes(int4)
RETURNS bytea
AS 'MODULE_PATHNAME', 'pg_random_bytes'
LANGUAGE 'C' VOLATILE STRICT;
--
-- pgp_sym_encrypt(data, key)
--

View File

@ -26,36 +26,273 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $PostgreSQL: pgsql/contrib/pgcrypto/pgp-mpi-internal.c,v 1.4 2005/10/15 02:49:06 momjian Exp $
* $PostgreSQL: pgsql/contrib/pgcrypto/pgp-mpi-internal.c,v 1.5 2006/07/13 04:15:25 neilc Exp $
*/
#include "postgres.h"
#include "imath.h"
#include "px.h"
#include "mbuf.h"
#include "pgp.h"
static mpz_t *mp_new()
{
mpz_t *mp = mp_int_alloc();
mp_int_init_size(mp, 256);
return mp;
}
static void mp_clear_free(mpz_t *a)
{
if (!a)
return;
// fixme: no clear?
mp_int_free(a);
}
static int mp_px_rand(uint32 bits, mpz_t *res)
{
int err;
unsigned bytes = (bits + 7) / 8;
int last_bits = bits & 7;
uint8 *buf;
buf = px_alloc(bytes);
err = px_get_random_bytes(buf, bytes);
if (err < 0) {
px_free(buf);
return err;
}
/* clear unnecessary bits and set last bit to one */
if (last_bits) {
buf[0] >>= 8 - last_bits;
buf[0] |= 1 << (last_bits - 1);
} else
buf[0] |= 1 << 7;
mp_int_read_unsigned(res, buf, bytes);
px_free(buf);
return 0;
}
static void mp_modmul(mpz_t *a, mpz_t *b, mpz_t *p, mpz_t *res)
{
mpz_t *tmp = mp_new();
mp_int_mul(a, b, tmp);
mp_int_mod(tmp, p, res);
mp_clear_free(tmp);
}
static mpz_t *
mpi_to_bn(PGP_MPI * n)
{
mpz_t *bn = mp_new();
mp_int_read_unsigned(bn, n->data, n->bytes);
if (!bn)
return NULL;
if (mp_int_count_bits(bn) != n->bits)
{
px_debug("mpi_to_bn: bignum conversion failed: mpi=%d, bn=%d",
n->bits, mp_int_count_bits(bn));
mp_clear_free(bn);
return NULL;
}
return bn;
}
static PGP_MPI *
bn_to_mpi(mpz_t *bn)
{
int res;
PGP_MPI *n;
int bytes;
res = pgp_mpi_alloc(mp_int_count_bits(bn), &n);
if (res < 0)
return NULL;
bytes = (mp_int_count_bits(bn) + 7) / 8;
if (bytes != n->bytes)
{
px_debug("bn_to_mpi: bignum conversion failed: bn=%d, mpi=%d",
bytes, n->bytes);
pgp_mpi_free(n);
return NULL;
}
mp_int_to_unsigned(bn, n->data, n->bytes);
return n;
}
/*
* Decide the number of bits in the random componont k
*
* It should be in the same range as p for signing (which
* is deprecated), but can be much smaller for encrypting.
*
* Until I research it further, I just mimic gpg behaviour.
* It has a special mapping table, for values <= 5120,
* above that it uses 'arbitrary high number'. Following
* algorihm hovers 10-70 bits above gpg values. And for
* larger p, it uses gpg's algorihm.
*
* The point is - if k gets large, encryption will be
* really slow. It does not matter for decryption.
*/
static int
decide_k_bits(int p_bits)
{
if (p_bits <= 5120)
return p_bits / 10 + 160;
else
return (p_bits / 8 + 200) * 3 / 2;
}
int
pgp_elgamal_encrypt(PGP_PubKey * pk, PGP_MPI * _m,
PGP_MPI ** c1_p, PGP_MPI ** c2_p)
{
return PXE_PGP_NO_BIGNUM;
int res = PXE_PGP_MATH_FAILED;
int k_bits;
mpz_t *m = mpi_to_bn(_m);
mpz_t *p = mpi_to_bn(pk->pub.elg.p);
mpz_t *g = mpi_to_bn(pk->pub.elg.g);
mpz_t *y = mpi_to_bn(pk->pub.elg.y);
mpz_t *k = mp_new();
mpz_t *yk = mp_new();
mpz_t *c1 = mp_new();
mpz_t *c2 = mp_new();
if (!m || !p || !g || !y || !k || !yk || !c1 || !c2)
goto err;
/*
* generate k
*/
k_bits = decide_k_bits(mp_int_count_bits(p));
res = mp_px_rand(k_bits, k);
if (res < 0)
return res;
/*
* c1 = g^k c2 = m * y^k
*/
mp_int_exptmod(g, k, p, c1);
mp_int_exptmod(y, k, p, yk);
mp_modmul(m, yk, p, c2);
/* result */
*c1_p = bn_to_mpi(c1);
*c2_p = bn_to_mpi(c2);
if (*c1_p && *c2_p)
res = 0;
err:
mp_clear_free(c2);
mp_clear_free(c1);
mp_clear_free(yk);
mp_clear_free(k);
mp_clear_free(y);
mp_clear_free(g);
mp_clear_free(p);
mp_clear_free(m);
return res;
}
int
pgp_elgamal_decrypt(PGP_PubKey * pk, PGP_MPI * _c1, PGP_MPI * _c2,
PGP_MPI ** msg_p)
{
return PXE_PGP_NO_BIGNUM;
int res = PXE_PGP_MATH_FAILED;
mpz_t *c1 = mpi_to_bn(_c1);
mpz_t *c2 = mpi_to_bn(_c2);
mpz_t *p = mpi_to_bn(pk->pub.elg.p);
mpz_t *x = mpi_to_bn(pk->sec.elg.x);
mpz_t *c1x = mp_new();
mpz_t *div = mp_new();
mpz_t *m = mp_new();
if (!c1 || !c2 || !p || !x || !c1x || !div || !m)
goto err;
/*
* m = c2 / (c1^x)
*/
mp_int_exptmod(c1, x, p, c1x);
mp_int_invmod(c1x, p, div);
mp_modmul(c2, div, p, m);
/* result */
*msg_p = bn_to_mpi(m);
if (*msg_p)
res = 0;
err:
mp_clear_free(m);
mp_clear_free(div);
mp_clear_free(c1x);
mp_clear_free(x);
mp_clear_free(p);
mp_clear_free(c2);
mp_clear_free(c1);
return res;
}
int
pgp_rsa_encrypt(PGP_PubKey * pk, PGP_MPI * m, PGP_MPI ** c)
pgp_rsa_encrypt(PGP_PubKey * pk, PGP_MPI * _m, PGP_MPI ** c_p)
{
return PXE_PGP_NO_BIGNUM;
int res = PXE_PGP_MATH_FAILED;
mpz_t *m = mpi_to_bn(_m);
mpz_t *e = mpi_to_bn(pk->pub.rsa.e);
mpz_t *n = mpi_to_bn(pk->pub.rsa.n);
mpz_t *c = mp_new();
if (!m || !e || !n || !c)
goto err;
/*
* c = m ^ e
*/
mp_int_exptmod(m, e, n, c);
*c_p = bn_to_mpi(c);
if (*c_p)
res = 0;
err:
mp_clear_free(c);
mp_clear_free(n);
mp_clear_free(e);
mp_clear_free(m);
return res;
}
int
pgp_rsa_decrypt(PGP_PubKey * pk, PGP_MPI * c, PGP_MPI ** m)
pgp_rsa_decrypt(PGP_PubKey * pk, PGP_MPI * _c, PGP_MPI ** m_p)
{
return PXE_PGP_NO_BIGNUM;
int res = PXE_PGP_MATH_FAILED;
mpz_t *c = mpi_to_bn(_c);
mpz_t *d = mpi_to_bn(pk->sec.rsa.d);
mpz_t *n = mpi_to_bn(pk->pub.rsa.n);
mpz_t *m = mp_new();
if (!m || !d || !n || !c)
goto err;
/*
* m = c ^ d
*/
mp_int_exptmod(c, d, n, m);
*m_p = bn_to_mpi(m);
if (*m_p)
res = 0;
err:
mp_clear_free(m);
mp_clear_free(n);
mp_clear_free(d);
mp_clear_free(c);
return res;
}

View File

@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $PostgreSQL: pgsql/contrib/pgcrypto/px-crypt.h,v 1.9 2005/10/15 02:49:06 momjian Exp $
* $PostgreSQL: pgsql/contrib/pgcrypto/px-crypt.h,v 1.10 2006/07/13 04:15:25 neilc Exp $
*/
#ifndef _PX_CRYPT_H
@ -55,14 +55,6 @@ int 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);
extern char px_crypt_a64[];
/* avoid conflicts with system libs */
#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);

View File

@ -33,7 +33,7 @@
*
* $From: sha2.c,v 1.1 2001/11/08 00:01:51 adg Exp adg $
*
* $PostgreSQL: pgsql/contrib/pgcrypto/sha2.c,v 1.6 2006/05/30 12:56:45 momjian Exp $
* $PostgreSQL: pgsql/contrib/pgcrypto/sha2.c,v 1.7 2006/07/13 04:15:25 neilc Exp $
*/
#include "postgres.h"
@ -189,6 +189,18 @@ static const uint32 K256[64] = {
0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
};
/* Initial hash value H for SHA-224: */
static const uint32 sha224_initial_hash_value[8] = {
0xc1059ed8UL,
0x367cd507UL,
0x3070dd17UL,
0xf70e5939UL,
0xffc00b31UL,
0x68581511UL,
0x64f98fa7UL,
0xbefa4fa4UL
};
/* Initial hash value H for SHA-256: */
static const uint32 sha256_initial_hash_value[8] = {
0x6a09e667UL,
@ -521,55 +533,61 @@ SHA256_Update(SHA256_CTX * context, const uint8 *data, size_t len)
usedspace = freespace = 0;
}
void
SHA256_Final(uint8 digest[], SHA256_CTX * context)
static void
SHA256_Last(SHA256_CTX *context)
{
unsigned int usedspace;
/* If no digest buffer is passed, we don't bother doing this: */
if (digest != NULL)
{
usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;
usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;
#if BYTE_ORDER == LITTLE_ENDIAN
/* Convert FROM host byte order */
REVERSE64(context->bitcount, context->bitcount);
/* Convert FROM host byte order */
REVERSE64(context->bitcount, context->bitcount);
#endif
if (usedspace > 0)
if (usedspace > 0)
{
/* Begin padding with a 1 bit: */
context->buffer[usedspace++] = 0x80;
if (usedspace <= SHA256_SHORT_BLOCK_LENGTH)
{
/* Begin padding with a 1 bit: */
context->buffer[usedspace++] = 0x80;
if (usedspace <= SHA256_SHORT_BLOCK_LENGTH)
{
/* Set-up for the last transform: */
memset(&context->buffer[usedspace], 0, SHA256_SHORT_BLOCK_LENGTH - usedspace);
}
else
{
if (usedspace < SHA256_BLOCK_LENGTH)
{
memset(&context->buffer[usedspace], 0, SHA256_BLOCK_LENGTH - usedspace);
}
/* Do second-to-last transform: */
SHA256_Transform(context, context->buffer);
/* And set-up for the last transform: */
memset(context->buffer, 0, SHA256_SHORT_BLOCK_LENGTH);
}
/* Set-up for the last transform: */
memset(&context->buffer[usedspace], 0, SHA256_SHORT_BLOCK_LENGTH - usedspace);
}
else
{
/* Set-up for the last transform: */
if (usedspace < SHA256_BLOCK_LENGTH)
{
memset(&context->buffer[usedspace], 0, SHA256_BLOCK_LENGTH - usedspace);
}
/* Do second-to-last transform: */
SHA256_Transform(context, context->buffer);
/* And set-up for the last transform: */
memset(context->buffer, 0, SHA256_SHORT_BLOCK_LENGTH);
/* Begin padding with a 1 bit: */
*context->buffer = 0x80;
}
/* Set the bit count: */
*(uint64 *) &context->buffer[SHA256_SHORT_BLOCK_LENGTH] = context->bitcount;
}
else
{
/* Set-up for the last transform: */
memset(context->buffer, 0, SHA256_SHORT_BLOCK_LENGTH);
/* Final transform: */
SHA256_Transform(context, context->buffer);
/* Begin padding with a 1 bit: */
*context->buffer = 0x80;
}
/* Set the bit count: */
*(uint64 *) &context->buffer[SHA256_SHORT_BLOCK_LENGTH] = context->bitcount;
/* Final transform: */
SHA256_Transform(context, context->buffer);
}
void
SHA256_Final(uint8 digest[], SHA256_CTX * context)
{
/* If no digest buffer is passed, we don't bother doing this: */
if (digest != NULL)
{
SHA256_Last(context);
#if BYTE_ORDER == LITTLE_ENDIAN
{
@ -587,7 +605,6 @@ SHA256_Final(uint8 digest[], SHA256_CTX * context)
/* Clean up state data: */
memset(context, 0, sizeof(*context));
usedspace = 0;
}
@ -963,3 +980,47 @@ SHA384_Final(uint8 digest[], SHA384_CTX * context)
/* Zero out state data */
memset(context, 0, sizeof(*context));
}
/*** SHA-224: *********************************************************/
void
SHA224_Init(SHA224_CTX * context)
{
if (context == NULL)
return;
memcpy(context->state, sha224_initial_hash_value, SHA256_DIGEST_LENGTH);
memset(context->buffer, 0, SHA256_BLOCK_LENGTH);
context->bitcount = 0;
}
void
SHA224_Update(SHA224_CTX * context, const uint8 *data, size_t len)
{
SHA256_Update((SHA256_CTX *) context, data, len);
}
void
SHA224_Final(uint8 digest[], SHA224_CTX * context)
{
/* If no digest buffer is passed, we don't bother doing this: */
if (digest != NULL)
{
SHA256_Last(context);
#if BYTE_ORDER == LITTLE_ENDIAN
{
/* Convert TO host byte order */
int j;
for (j = 0; j < 8; j++)
{
REVERSE32(context->state[j], context->state[j]);
}
}
#endif
memcpy(digest, context->state, SHA224_DIGEST_LENGTH);
}
/* Clean up state data: */
memset(context, 0, sizeof(*context));
}

View File

@ -1,4 +1,4 @@
/* $PostgreSQL: pgsql/contrib/pgcrypto/sha2.h,v 1.3 2006/05/30 12:56:45 momjian Exp $ */
/* $PostgreSQL: pgsql/contrib/pgcrypto/sha2.h,v 1.4 2006/07/13 04:15:25 neilc Exp $ */
/* $OpenBSD: sha2.h,v 1.2 2004/04/28 23:11:57 millert Exp $ */
/*
@ -49,7 +49,10 @@
#define SHA512_Update pg_SHA512_Update
#define SHA512_Final pg_SHA512_Final
/*** SHA-256/384/512 Various Length Definitions ***********************/
/*** SHA-224/256/384/512 Various Length Definitions ***********************/
#define SHA224_BLOCK_LENGTH 64
#define SHA224_DIGEST_LENGTH 28
#define SHA224_DIGEST_STRING_LENGTH (SHA224_DIGEST_LENGTH * 2 + 1)
#define SHA256_BLOCK_LENGTH 64
#define SHA256_DIGEST_LENGTH 32
#define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1)
@ -75,8 +78,13 @@ typedef struct _SHA512_CTX
uint8 buffer[SHA512_BLOCK_LENGTH];
} SHA512_CTX;
typedef SHA256_CTX SHA224_CTX;
typedef SHA512_CTX SHA384_CTX;
void SHA224_Init(SHA224_CTX *);
void SHA224_Update(SHA224_CTX *, const uint8 *, size_t);
void SHA224_Final(uint8[SHA224_DIGEST_LENGTH], SHA224_CTX *);
void SHA256_Init(SHA256_CTX *);
void SHA256_Update(SHA256_CTX *, const uint8 *, size_t);
void SHA256_Final(uint8[SHA256_DIGEST_LENGTH], SHA256_CTX *);

View File

@ -2,6 +2,13 @@
-- SHA2 family
--
-- SHA224
SELECT encode(digest('', 'sha224'), 'hex');
SELECT encode(digest('a', 'sha224'), 'hex');
SELECT encode(digest('abc', 'sha224'), 'hex');
SELECT encode(digest('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq', 'sha224'), 'hex');
SELECT encode(digest('12345678901234567890123456789012345678901234567890123456789012345678901234567890', 'sha224'), 'hex');
-- SHA256
SELECT encode(digest('', 'sha256'), 'hex');
SELECT encode(digest('a', 'sha256'), 'hex');

View File

@ -0,0 +1,46 @@
SET search_path = public;
DROP FUNCTION digest(text, text);
DROP FUNCTION digest(bytea, text);
DROP FUNCTION digest_exists(text);
DROP FUNCTION hmac(text, text, text);
DROP FUNCTION hmac(bytea, bytea, text);
DROP FUNCTION hmac_exists(text);
DROP FUNCTION crypt(text, text);
DROP FUNCTION gen_salt(text);
DROP FUNCTION 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);
DROP FUNCTION gen_random_bytes(int4);
DROP FUNCTION pgp_sym_encrypt(text, text);
DROP FUNCTION pgp_sym_encrypt_bytea(bytea, text);
DROP FUNCTION pgp_sym_encrypt(text, text, text);
DROP FUNCTION pgp_sym_encrypt_bytea(bytea, text, text);
DROP FUNCTION pgp_sym_decrypt(bytea, text);
DROP FUNCTION pgp_sym_decrypt_bytea(bytea, text);
DROP FUNCTION pgp_sym_decrypt(bytea, text, text);
DROP FUNCTION pgp_sym_decrypt_bytea(bytea, text, text);
DROP FUNCTION pgp_pub_encrypt(text, bytea);
DROP FUNCTION pgp_pub_encrypt_bytea(bytea, bytea);
DROP FUNCTION pgp_pub_encrypt(text, bytea, text);
DROP FUNCTION pgp_pub_encrypt_bytea(bytea, bytea, text);
DROP FUNCTION pgp_pub_decrypt(bytea, bytea);
DROP FUNCTION pgp_pub_decrypt_bytea(bytea, bytea);
DROP FUNCTION pgp_pub_decrypt(bytea, bytea, text);
DROP FUNCTION pgp_pub_decrypt_bytea(bytea, bytea, text);
DROP FUNCTION pgp_pub_decrypt(bytea, bytea, text, text);
DROP FUNCTION pgp_pub_decrypt_bytea(bytea, bytea, text, text);
DROP FUNCTION pgp_key_id(bytea);
DROP FUNCTION armor(bytea);
DROP FUNCTION dearmor(text);