aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/pgcrypto/Makefile25
-rw-r--r--contrib/pgcrypto/README.pgcrypto163
-rw-r--r--contrib/pgcrypto/pgcrypto.sql.in137
-rw-r--r--contrib/pgcrypto/px.c52
-rw-r--r--contrib/pgcrypto/px.h48
5 files changed, 408 insertions, 17 deletions
diff --git a/contrib/pgcrypto/Makefile b/contrib/pgcrypto/Makefile
index 82f2a8295e6..81ad9b372e2 100644
--- a/contrib/pgcrypto/Makefile
+++ b/contrib/pgcrypto/Makefile
@@ -1,23 +1,35 @@
#
-# $PostgreSQL: pgsql/contrib/pgcrypto/Makefile,v 1.19 2005/07/10 03:55:28 momjian Exp $
+# $PostgreSQL: pgsql/contrib/pgcrypto/Makefile,v 1.20 2005/07/10 03:57:55 momjian Exp $
#
INT_SRCS = md5.c sha1.c sha2.c internal.c blf.c rijndael.c \
- fortuna.c random.c
+ fortuna.c random.c pgp-mpi-internal.c
INT_TESTS = sha2
-OSSL_SRCS = openssl.c
+OSSL_SRCS = openssl.c pgp-mpi-openssl.c
OSSL_TESTS = 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 =
+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))
PG_CPPFLAGS = $(CF_CFLAGS)
SRCS = pgcrypto.c px.c px-hmac.c px-crypt.c misc.c \
crypt-gensalt.c crypt-blowfish.c crypt-des.c \
- crypt-md5.c $(CF_SRCS)
+ crypt-md5.c $(CF_SRCS) \
+ mbuf.c pgp.c pgp-armor.c pgp-cfb.c pgp-compress.c \
+ pgp-decrypt.c pgp-encrypt.c pgp-info.c pgp-mpi.c \
+ pgp-pubdec.c pgp-pubenc.c pgp-pubkey.c pgp-s2k.c \
+ pgp-pgsql.c
MODULE_big = pgcrypto
OBJS = $(SRCS:.c=.o)
@@ -27,7 +39,8 @@ EXTRA_CLEAN = gen-rtab
REGRESS = init md5 sha1 hmac-md5 hmac-sha1 blowfish rijndael \
$(CF_TESTS) \
- crypt-des crypt-md5 crypt-blowfish crypt-xdes
+ crypt-des crypt-md5 crypt-blowfish crypt-xdes \
+ pgp-armor pgp-decrypt pgp-encrypt $(CF_PGP_TESTS)
ifdef USE_PGXS
diff --git a/contrib/pgcrypto/README.pgcrypto b/contrib/pgcrypto/README.pgcrypto
index b828739160c..5446c19a3b5 100644
--- a/contrib/pgcrypto/README.pgcrypto
+++ b/contrib/pgcrypto/README.pgcrypto
@@ -11,10 +11,10 @@ Edit makefile, if you want to use any external library.
NB! Default randomness source is libc random() function. This
is so only to get pgcrypto build everywhere. Randomness is
-needed for gen_salt() function. So if you plan using it, you
-should definitely change that by editing Makefile. You should
-be using urandom device if your OS supports it, otherwise link
-pgcrypto against OpenSSL library and use its PRNG.
+needed for gen_salt() and pgp_encrypt() functions. So if you plan
+using those, you should definitely change that by editing Makefile.
+You can should use urandom device if your OS supports it, otherwise
+link pgcrypto against OpenSSL library and use its PRNG.
After editing Makefile:
@@ -108,6 +108,161 @@ gen_salt(type::text, rounds::int4)::text
For maximum security, you should choose the 'bf' crypt
and use maximum number of rounds you can still tolerate.
+armor(bytea)::text
+dearmor(text)::bytea
+
+ Those wrap/unwrap data into PGP Ascii Armor which
+ is basically Base64 with CRC and additional formatting.
+
+pgp_sym_encrypt(data::text, key::text)::bytea
+pgp_sym_encrypt(data::text, key::text, arg::text)::bytea
+pgp_sym_encrypt_bytea(data::bytea, key::text)::bytea
+pgp_sym_encrypt_bytea(data::bytea, key::text, arg::text)::bytea
+
+pgp_sym_decrypt(data::bytea, key::text)::text
+pgp_sym_decrypt(data::bytea, key::text, arg::text)::text
+pgp_sym_decrypt_bytea(data::text, key::text)::bytea
+pgp_sym_decrypt_bytea(data::text, key::text, arg::text)::bytea
+
+ Encrypt data into OpenPGP Symmetrically Encrypted Data
+ message. And decrypt it from it.
+
+ Note that the pgp_sym_encrypt_bytea functions tag the data
+ as binary, as the pgp_sym_encrypt will tag the data as text.
+ You can not decrypt the binary data as text. But you can
+ decrypt text data as binary. This rule avoids having
+ broken textual data in PostgreSQL.
+
+ Both encrypt and decrypt accept also third argument, which
+ is parameters to the function in following format:
+
+ parm=val[,parm=val]...
+
+ Example:
+
+ select pgp_sym_encrypt('data', 'psw',
+ 'compress-algo=2, unicode-mode=1');
+
+ Accepted parameters are:
+
+ cipher-algo: bf, aes, aes128, aes192, aes256
+ Cipher algorithm to use. OpenSSL gives additional algorithms:
+ 3des, cast5
+ Default: aes128
+
+ compress-algo: 0, 1, 2
+ Which compression algorithm to use.
+ 0 - no compression
+ 1 - ZIP compression
+ 2 - ZLIB compression [=ZIP plus meta-data and block-CRC's]
+ Default: 0
+
+ compress-level: 0, 1-9
+ How much to compress. Bigger level compresses smaller
+ but also slower. 0 disables compression.
+ Default: 6
+
+ convert-crlf: 0, 1
+ Whether to convert \n into \r\n when encrypting and
+ \r\n to \n when decrypting. RFC2440 specifies that
+ text packets should use "\r\n" line-feeds.
+ Use this to get fully RFC-compliant behaviour.
+ Default: 0
+
+ disable-mdc: 0, 1
+ Do not protect data with SHA-1. Note that SHA-1 protected
+ packet is from upcoming update to RFC2440. (Currently at
+ version RFC2440bis-13.) You need to disable it if you need
+ compatibility with ancient PGP products. Recent gnupg.org
+ and pgp.com software supports it fine.
+ Default: 0
+
+ enable-session-key: 0, 1
+ Use separate session key.
+ Default: 0
+
+ s2k-mode: 0, 1, 3
+ Which S2K algorithm to use. 0 is dangerous - without salt.
+ Default: 3
+
+ s2k-digest-algo: md5, sha1
+ Which digest algorithm to use in S2K calculation.
+ Default: SHA-1
+
+ s2k-cipher-algo: bf, aes, aes128, aes192, aes256
+ Which cipher to use for encrypting separate session key.
+ Default: same as cipher-algo.
+
+ unicode-mode: 0, 1
+ Whether to convert textual data from database internal
+ encoding to UTF-8 and back.
+ Default: 0
+
+ Only 'convert-crlf' applies to both encrypt and decrypt,
+ all others apply only to encrypt - decrypt gets the
+ settings from PGP data.
+
+
+pgp_pub_encrypt(data::text, key::bytea)::bytea
+pgp_pub_encrypt(data::text, key::bytea, arg::text)::bytea
+pgp_pub_encrypt_bytea(data::bytea, bytea::text)::bytea
+pgp_pub_encrypt_bytea(data::bytea, bytea::text, arg::text)::bytea
+
+pgp_pub_decrypt(data::bytea, key::bytea)::text
+pgp_pub_decrypt(data::bytea, key::bytea, psw::text)::text
+pgp_pub_decrypt(data::bytea, key::bytea, psw::text, arg::text)::text
+pgp_pub_decrypt_bytea(data::text, key::bytea)::bytea
+pgp_pub_decrypt_bytea(data::text, key::bytea, psw::text)::bytea
+pgp_pub_decrypt_bytea(data::text, key::bytea, psw::text, arg::bytea)::bytea
+
+ Encrypt data into OpenPGP Public-Key Encrypted Data
+ message. And decrypt it from it. The arg parameter is
+ described in pgp_sym_* section.
+
+ The key must be a public-key packet for pgp_pub_encrypt
+ functions and a secret key packet for pgp_pub_decrypt
+ functions. Trying to encrypt with secret key gives a error.
+ While being technically possible, it is probably a sign of
+ user error and leaking secret keys.
+
+ Here is a example how to generate them:
+
+ Generate a new key:
+
+ gpg --gen-key
+
+ You need to pick "DSA and Elgamal" key type, others
+ are sign-only.
+
+ List keys:
+
+ gpg --list-secret-keys
+
+ Export ascii-armored public key:
+
+ gpg -a --export KEYID > public.key
+
+ Export ascii-armored secret key:
+
+ gpg -a --export-secret-keys KEYID > secret.key
+
+ You need to use dearmor() on them before giving giving
+ them to pgp_pub_* functions. Ofcourse, if you can handle
+ binary data, you can drop "-a" from gpg.
+
+
+pgp_key_id(key / data)
+
+ It shows you either key ID if given PGP public or secret
+ key. Or it gives the key ID what was used for encrypting
+ the data, if given encrypted data.
+
+ It can return 2 special key ID's:
+
+ SYMKEY - it got symmetrically encrypted data.
+ ANYKEY - the data packet key ID is clear. That means
+ you should try all you secret keys on it.
+
encrypt(data::bytea, key::bytea, type::text)::bytea
decrypt(data::bytea, key::bytea, type::text)::bytea
encrypt_iv(data::bytea, key::bytea, iv::bytea, type::text)::bytea
diff --git a/contrib/pgcrypto/pgcrypto.sql.in b/contrib/pgcrypto/pgcrypto.sql.in
index 6179f621369..fb3949d56e4 100644
--- a/contrib/pgcrypto/pgcrypto.sql.in
+++ b/contrib/pgcrypto/pgcrypto.sql.in
@@ -71,4 +71,141 @@ RETURNS bool
AS 'MODULE_PATHNAME', 'pg_cipher_exists'
LANGUAGE 'C' IMMUTABLE STRICT;
+--
+-- pgp_sym_encrypt(data, key)
+--
+CREATE OR REPLACE FUNCTION pgp_sym_encrypt(text, text)
+RETURNS bytea
+AS 'MODULE_PATHNAME', 'pgp_sym_encrypt_text'
+LANGUAGE 'C' STRICT;
+
+CREATE OR REPLACE FUNCTION pgp_sym_encrypt_bytea(bytea, text)
+RETURNS bytea
+AS 'MODULE_PATHNAME', 'pgp_sym_encrypt_bytea'
+LANGUAGE 'C' STRICT;
+
+--
+-- pgp_sym_encrypt(data, key, args)
+--
+CREATE OR REPLACE FUNCTION pgp_sym_encrypt(text, text, text)
+RETURNS bytea
+AS 'MODULE_PATHNAME', 'pgp_sym_encrypt_text'
+LANGUAGE 'C' STRICT;
+
+CREATE OR REPLACE FUNCTION pgp_sym_encrypt_bytea(bytea, text, text)
+RETURNS bytea
+AS 'MODULE_PATHNAME', 'pgp_sym_encrypt_bytea'
+LANGUAGE 'C' STRICT;
+
+--
+-- pgp_sym_decrypt(data, key)
+--
+CREATE OR REPLACE FUNCTION pgp_sym_decrypt(bytea, text)
+RETURNS text
+AS 'MODULE_PATHNAME', 'pgp_sym_decrypt_text'
+LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OR REPLACE FUNCTION pgp_sym_decrypt_bytea(bytea, text)
+RETURNS bytea
+AS 'MODULE_PATHNAME', 'pgp_sym_decrypt_bytea'
+LANGUAGE 'C' IMMUTABLE STRICT;
+
+--
+-- pgp_sym_decrypt(data, key, args)
+--
+CREATE OR REPLACE FUNCTION pgp_sym_decrypt(bytea, text, text)
+RETURNS text
+AS 'MODULE_PATHNAME', 'pgp_sym_decrypt_text'
+LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OR REPLACE FUNCTION pgp_sym_decrypt_bytea(bytea, text, text)
+RETURNS bytea
+AS 'MODULE_PATHNAME', 'pgp_sym_decrypt_bytea'
+LANGUAGE 'C' IMMUTABLE STRICT;
+
+--
+-- pgp_pub_encrypt(data, key)
+--
+CREATE OR REPLACE FUNCTION pgp_pub_encrypt(text, bytea)
+RETURNS bytea
+AS 'MODULE_PATHNAME', 'pgp_pub_encrypt_text'
+LANGUAGE 'C' STRICT;
+
+CREATE OR REPLACE FUNCTION pgp_pub_encrypt_bytea(bytea, bytea)
+RETURNS bytea
+AS 'MODULE_PATHNAME', 'pgp_pub_encrypt_bytea'
+LANGUAGE 'C' STRICT;
+
+--
+-- pgp_pub_encrypt(data, key, args)
+--
+CREATE OR REPLACE FUNCTION pgp_pub_encrypt(text, bytea, text)
+RETURNS bytea
+AS 'MODULE_PATHNAME', 'pgp_pub_encrypt_text'
+LANGUAGE 'C' STRICT;
+
+CREATE OR REPLACE FUNCTION pgp_pub_encrypt_bytea(bytea, bytea, text)
+RETURNS bytea
+AS 'MODULE_PATHNAME', 'pgp_pub_encrypt_bytea'
+LANGUAGE 'C' STRICT;
+
+--
+-- pgp_pub_decrypt(data, key)
+--
+CREATE OR REPLACE FUNCTION pgp_pub_decrypt(bytea, bytea)
+RETURNS text
+AS 'MODULE_PATHNAME', 'pgp_pub_decrypt_text'
+LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OR REPLACE FUNCTION pgp_pub_decrypt_bytea(bytea, bytea)
+RETURNS bytea
+AS 'MODULE_PATHNAME', 'pgp_pub_decrypt_bytea'
+LANGUAGE 'C' IMMUTABLE STRICT;
+
+--
+-- pgp_pub_decrypt(data, key, psw)
+--
+CREATE OR REPLACE FUNCTION pgp_pub_decrypt(bytea, bytea, text)
+RETURNS text
+AS 'MODULE_PATHNAME', 'pgp_pub_decrypt_text'
+LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OR REPLACE FUNCTION pgp_pub_decrypt_bytea(bytea, bytea, text)
+RETURNS bytea
+AS 'MODULE_PATHNAME', 'pgp_pub_decrypt_bytea'
+LANGUAGE 'C' IMMUTABLE STRICT;
+
+--
+-- pgp_pub_decrypt(data, key, psw, arg)
+--
+CREATE OR REPLACE FUNCTION pgp_pub_decrypt(bytea, bytea, text, text)
+RETURNS text
+AS 'MODULE_PATHNAME', 'pgp_pub_decrypt_text'
+LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OR REPLACE FUNCTION pgp_pub_decrypt_bytea(bytea, bytea, text, text)
+RETURNS bytea
+AS 'MODULE_PATHNAME', 'pgp_pub_decrypt_bytea'
+LANGUAGE 'C' IMMUTABLE STRICT;
+
+--
+-- PGP key ID
+--
+CREATE OR REPLACE FUNCTION pgp_key_id(bytea)
+RETURNS text
+AS 'MODULE_PATHNAME', 'pgp_key_id_w'
+LANGUAGE 'C' IMMUTABLE STRICT;
+
+--
+-- pgp armor
+--
+CREATE OR REPLACE FUNCTION armor(bytea)
+RETURNS text
+AS 'MODULE_PATHNAME', 'pg_armor'
+LANGUAGE 'C' IMMUTABLE STRICT;
+
+CREATE OR REPLACE FUNCTION dearmor(text)
+RETURNS bytea
+AS 'MODULE_PATHNAME', 'pg_dearmor'
+LANGUAGE 'C' IMMUTABLE STRICT;
diff --git a/contrib/pgcrypto/px.c b/contrib/pgcrypto/px.c
index 51f83069179..ca271e33a82 100644
--- a/contrib/pgcrypto/px.c
+++ b/contrib/pgcrypto/px.c
@@ -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.c,v 1.11 2005/03/21 05:22:14 neilc Exp $
+ * $PostgreSQL: pgsql/contrib/pgcrypto/px.c,v 1.12 2005/07/10 03:57:55 momjian Exp $
*/
#include <postgres.h>
@@ -57,6 +57,37 @@ static const struct error_desc px_err_list[] = {
{PXE_BAD_SALT_ROUNDS, "Incorrect number of rounds"},
{PXE_MCRYPT_INTERNAL, "mcrypt internal error"},
{PXE_NO_RANDOM, "No strong random source"},
+ {PXE_PGP_CORRUPT_DATA, "Wrong key or corrupt data"},
+ {PXE_PGP_CORRUPT_ARMOR, "Corrupt ascii-armor"},
+ {PXE_PGP_UNSUPPORTED_COMPR, "Unsupported compression algorithm"},
+ {PXE_PGP_UNSUPPORTED_CIPHER, "Unsupported cipher algorithm"},
+ {PXE_PGP_UNSUPPORTED_HASH, "Unsupported digest algorithm"},
+ {PXE_PGP_COMPRESSION_ERROR, "Compression error"},
+ {PXE_PGP_NOT_TEXT, "Not text data"},
+ {PXE_PGP_UNEXPECTED_PKT, "Unexpected packet in key data"},
+ {PXE_PGP_NO_BIGNUM,
+ "public-key functions disabled - "
+ "pgcrypto needs OpenSSL for bignums"},
+ {PXE_PGP_MATH_FAILED, "Math operation failed"},
+ {PXE_PGP_SHORT_ELGAMAL_KEY, "Elgamal keys must be at least 1024 bits long"},
+ {PXE_PGP_RSA_UNSUPPORTED, "pgcrypto does not support RSA keys"},
+ {PXE_PGP_UNKNOWN_PUBALGO, "Unknown public-key encryption algorithm"},
+ {PXE_PGP_WRONG_KEYID, "Data is not encrypted with this key"},
+ {PXE_PGP_MULTIPLE_KEYS,
+ "Several keys given - pgcrypto does not handle keyring"},
+ {PXE_PGP_EXPECT_PUBLIC_KEY, "Refusing to encrypt with secret key"},
+ {PXE_PGP_EXPECT_SECRET_KEY, "Cannot decrypt with public key"},
+ {PXE_PGP_NOT_V4_KEYPKT, "Only V4 key packets are supported"},
+ {PXE_PGP_KEYPKT_CORRUPT, "Corrupt key packet"},
+ {PXE_PGP_NO_USABLE_KEY, "No usable key found (expecting Elgamal key)"},
+ {PXE_PGP_NEED_SECRET_PSW, "Need password for secret key"},
+ {PXE_PGP_BAD_S2K_MODE, "Bad S2K mode"},
+ {PXE_PGP_UNSUPPORTED_PUBALGO, "Unsupported public key algorithm"},
+ {PXE_PGP_MULTIPLE_SUBKEYS, "Several subkeys not supported"},
+
+ /* fake this as PXE_PGP_CORRUPT_DATA */
+ {PXE_MBUF_SHORT_READ, "Corrupt data"},
+
{0, NULL},
};
@@ -82,6 +113,25 @@ px_resolve_alias(const PX_Alias * list, const char *name)
return name;
}
+static void (*debug_handler)(const char *) = NULL;
+
+void px_set_debug_handler(void (*handler)(const char *))
+{
+ debug_handler = handler;
+}
+
+void px_debug(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ if (debug_handler) {
+ char buf[512];
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ debug_handler(buf);
+ }
+ va_end(ap);
+}
+
/*
* combo - cipher + padding (+ checksum)
*/
diff --git a/contrib/pgcrypto/px.h b/contrib/pgcrypto/px.h
index b584ae6b347..bf45705c5da 100644
--- a/contrib/pgcrypto/px.h
+++ b/contrib/pgcrypto/px.h
@@ -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.h,v 1.13 2005/07/10 03:55:28 momjian Exp $
+ * $PostgreSQL: pgsql/contrib/pgcrypto/px.h,v 1.14 2005/07/10 03:57:55 momjian Exp $
*/
#ifndef __PX_H
@@ -42,19 +42,20 @@
#error BYTE_ORDER must be defined as LITTLE_ENDIAN or BIG_ENDIAN
#endif
+/* keep debug messages? */
+#define PX_DEBUG
+/* a way to disable palloc
+ * - useful if compiled into standalone
+ */
#ifndef PX_OWN_ALLOC
-
#define px_alloc(s) palloc(s)
#define px_realloc(p, s) repalloc(p, s)
#define px_free(p) pfree(p)
-
#else
-
void *px_alloc(size_t s);
void *px_realloc(void *p, size_t s);
void px_free(void *p);
-
#endif
/* max len of 'type' parms */
@@ -85,6 +86,34 @@ void px_free(void *p);
#define PXE_MCRYPT_INTERNAL -16
#define PXE_NO_RANDOM -17
+#define PXE_MBUF_SHORT_READ -50
+
+#define PXE_PGP_CORRUPT_DATA -100
+#define PXE_PGP_CORRUPT_ARMOR -101
+#define PXE_PGP_UNSUPPORTED_COMPR -102
+#define PXE_PGP_UNSUPPORTED_CIPHER -103
+#define PXE_PGP_UNSUPPORTED_HASH -104
+#define PXE_PGP_COMPRESSION_ERROR -105
+#define PXE_PGP_NOT_TEXT -106
+#define PXE_PGP_UNEXPECTED_PKT -107
+#define PXE_PGP_NO_BIGNUM -108
+#define PXE_PGP_MATH_FAILED -109
+#define PXE_PGP_SHORT_ELGAMAL_KEY -110
+#define PXE_PGP_RSA_UNSUPPORTED -111
+#define PXE_PGP_UNKNOWN_PUBALGO -112
+#define PXE_PGP_WRONG_KEYID -113
+#define PXE_PGP_MULTIPLE_KEYS -114
+#define PXE_PGP_EXPECT_PUBLIC_KEY -115
+#define PXE_PGP_EXPECT_SECRET_KEY -116
+#define PXE_PGP_NOT_V4_KEYPKT -117
+#define PXE_PGP_KEYPKT_CORRUPT -118
+#define PXE_PGP_NO_USABLE_KEY -119
+#define PXE_PGP_NEED_SECRET_PSW -120
+#define PXE_PGP_BAD_S2K_MODE -121
+#define PXE_PGP_UNSUPPORTED_PUBALGO -122
+#define PXE_PGP_MULTIPLE_SUBKEYS -123
+
+
typedef struct px_digest PX_MD;
typedef struct px_alias PX_Alias;
typedef struct px_hmac PX_HMAC;
@@ -103,7 +132,7 @@ struct px_digest
union
{
unsigned code;
- const void *ptr;
+ void *ptr;
} p;
};
@@ -178,6 +207,13 @@ const char *px_strerror(int err);
const char *px_resolve_alias(const PX_Alias * aliases, const char *name);
+void px_set_debug_handler(void (*handler)(const char *));
+#ifdef PX_DEBUG
+void px_debug(const char *fmt, ...);
+#else
+#define px_debug(...)
+#endif
+
#define px_md_result_size(md) (md)->result_size(md)
#define px_md_block_size(md) (md)->block_size(md)
#define px_md_reset(md) (md)->reset(md)