diff --git a/contrib/pgcrypto/openssl.c b/contrib/pgcrypto/openssl.c index a4840227ad1c0fb0cfd28d329f87de5c8c4919b3..8fc60eba420b5ff3459f3a72ec25f19a88f0f040 100644 --- a/contrib/pgcrypto/openssl.c +++ b/contrib/pgcrypto/openssl.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/openssl.c,v 1.26 2005/10/15 02:49:06 momjian Exp $ + * $PostgreSQL: pgsql/contrib/pgcrypto/openssl.c,v 1.27 2006/02/18 20:48:51 neilc Exp $ */ #include "postgres.h" @@ -47,17 +47,24 @@ #define MAX_IV (128/8) /* - * Does OpenSSL support AES? + * Compatibility with OpenSSL 0.9.6 + * + * It needs AES and newer DES and digest API. */ #if OPENSSL_VERSION_NUMBER >= 0x00907000L -/* Yes, it does. */ +/* + * Nothing needed for OpenSSL 0.9.7+ + */ + #include <openssl/aes.h> + #else /* old OPENSSL */ /* - * No, it does not. So use included rijndael code to emulate it. + * Emulate OpenSSL AES. */ + #include "rijndael.c" #define AES_ENCRYPT 1 @@ -90,12 +97,11 @@ memcpy(iv, (src) + (len) - 16, 16); \ } \ } while (0) -#endif /* old OPENSSL */ /* - * Compatibility with older OpenSSL API for DES. + * Emulate DES_* API */ -#if OPENSSL_VERSION_NUMBER < 0x00907000L + #define DES_key_schedule des_key_schedule #define DES_cblock des_cblock #define DES_set_key(k, ks) \ @@ -110,63 +116,91 @@ #define DES_ede3_cbc_encrypt(i, o, l, k1, k2, k3, iv, e) \ des_ede3_cbc_encrypt((i), (o), \ (l), *(k1), *(k2), *(k3), (iv), (e)) -#endif + +/* + * Emulate newer digest API. + */ + +static void EVP_MD_CTX_init(EVP_MD_CTX *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); +} + +static int EVP_MD_CTX_cleanup(EVP_MD_CTX *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); + return 1; +} + +static int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *md, void *engine) +{ + EVP_DigestInit(ctx, md); + return 1; +} + +static int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *res, unsigned int *len) +{ + EVP_DigestFinal(ctx, res, len); + return 1; +} + +#endif /* old OpenSSL */ /* * Hashes */ + +typedef struct OSSLDigest { + const EVP_MD *algo; + EVP_MD_CTX ctx; +} OSSLDigest; + static unsigned digest_result_size(PX_MD * h) { - return EVP_MD_CTX_size((EVP_MD_CTX *) h->p.ptr); + OSSLDigest *digest = (OSSLDigest *)h->p.ptr; + return EVP_MD_CTX_size(&digest->ctx); } static unsigned digest_block_size(PX_MD * h) { - return EVP_MD_CTX_block_size((EVP_MD_CTX *) h->p.ptr); + OSSLDigest *digest = (OSSLDigest *)h->p.ptr; + return EVP_MD_CTX_block_size(&digest->ctx); } static void digest_reset(PX_MD * h) { - EVP_MD_CTX *ctx = (EVP_MD_CTX *) h->p.ptr; - const EVP_MD *md; + OSSLDigest *digest = (OSSLDigest *)h->p.ptr; - md = EVP_MD_CTX_md(ctx); - - EVP_DigestInit(ctx, md); + EVP_DigestInit_ex(&digest->ctx, digest->algo, NULL); } static void digest_update(PX_MD * h, const uint8 *data, unsigned dlen) { - EVP_MD_CTX *ctx = (EVP_MD_CTX *) h->p.ptr; + OSSLDigest *digest = (OSSLDigest *)h->p.ptr; - EVP_DigestUpdate(ctx, data, dlen); + EVP_DigestUpdate(&digest->ctx, data, dlen); } static void digest_finish(PX_MD * h, uint8 *dst) { - EVP_MD_CTX *ctx = (EVP_MD_CTX *) h->p.ptr; - const EVP_MD *md = EVP_MD_CTX_md(ctx); - - EVP_DigestFinal(ctx, dst, NULL); + OSSLDigest *digest = (OSSLDigest *)h->p.ptr; - /* - * Some builds of 0.9.7x clear all of ctx in EVP_DigestFinal. Fix it by - * reinitializing ctx. - */ - EVP_DigestInit(ctx, md); + EVP_DigestFinal_ex(&digest->ctx, dst, NULL); } static void digest_free(PX_MD * h) { - EVP_MD_CTX *ctx = (EVP_MD_CTX *) h->p.ptr; + OSSLDigest *digest = (OSSLDigest *)h->p.ptr; + + EVP_MD_CTX_cleanup(&digest->ctx); - px_free(ctx); + px_free(digest); px_free(h); } @@ -178,8 +212,8 @@ int px_find_digest(const char *name, PX_MD ** res) { const EVP_MD *md; - EVP_MD_CTX *ctx; PX_MD *h; + OSSLDigest *digest; if (!px_openssl_initialized) { @@ -191,8 +225,12 @@ px_find_digest(const char *name, PX_MD ** res) if (md == NULL) return PXE_NO_HASH; - ctx = px_alloc(sizeof(*ctx)); - EVP_DigestInit(ctx, md); + digest = px_alloc(sizeof(*digest)); + digest->algo = md; + + EVP_MD_CTX_init(&digest->ctx); + if (EVP_DigestInit_ex(&digest->ctx, digest->algo, NULL) == 0) + return -1; h = px_alloc(sizeof(*h)); h->result_size = digest_result_size; @@ -201,7 +239,7 @@ px_find_digest(const char *name, PX_MD ** res) h->update = digest_update; h->finish = digest_finish; h->free = digest_free; - h->p.ptr = (void *) ctx; + h->p.ptr = (void *) digest; *res = h; return 0;