3 * Wrapper for OpenSSL library.
5 * Copyright (c) 2001 Marko Kreen
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * contrib/pgcrypto/openssl.c
34#include <openssl/crypto.h>
35#include <openssl/evp.h>
36#include <openssl/err.h>
37#include <openssl/rand.h>
44 * Max lengths we might want to handle.
46 #define MAX_KEY (512/8)
47 #define MAX_IV (128/8)
54 * To make sure we don't leak OpenSSL handles, we use the ResourceOwner
55 * mechanism to free them on abort.
65/* ResourceOwner callbacks to hold OpenSSL digest handles */
70 .
name =
"pgcrypto OpenSSL digest handle",
74 .DebugPrint = NULL,
/* default message is fine */
77/* Convenience wrappers over ResourceOwnerRemember/Forget */
92 EVP_MD_CTX_destroy(digest->
ctx);
93 if (digest->
owner != NULL)
102 int result = EVP_MD_CTX_size(digest->
ctx);
114 int result = EVP_MD_CTX_block_size(digest->
ctx);
117 elog(
ERROR,
"EVP_MD_CTX_block_size() failed");
127 if (!EVP_DigestInit_ex(digest->
ctx, digest->
algo, NULL))
128 elog(
ERROR,
"EVP_DigestInit_ex() failed");
136 if (!EVP_DigestUpdate(digest->
ctx,
data, dlen))
137 elog(
ERROR,
"EVP_DigestUpdate() failed");
145 if (!EVP_DigestFinal_ex(digest->
ctx, dst, NULL))
146 elog(
ERROR,
"EVP_DigestFinal_ex() failed");
158/* PUBLIC functions */
168 md = EVP_get_digestbyname(
name);
175 * Create an OSSLDigest object, an OpenSSL MD object, and a PX_MD object.
176 * The order is crucial, to make sure we don't leak anything on
177 * out-of-memory or other error.
181 ctx = EVP_MD_CTX_create();
187 if (EVP_DigestInit_ex(ctx, md, NULL) == 0)
189 EVP_MD_CTX_destroy(ctx);
199 /* The PX_MD object is allocated in the current memory context. */
213/* ResourceOwner callbacks for OSSLDigest */
220 digest->
owner = NULL;
227 * We use OpenSSL's EVP* family of functions for these.
231 * prototype for the EVP functions that return an algorithm, e.g.
234 typedef const EVP_CIPHER *(*ossl_EVP_cipher_func) (void);
237 * ossl_cipher contains the static information about each cipher.
248 * OSSLCipher contains the state for using a cipher. A separate OSSLCipher
249 * object is allocated in each px_find_cipher() call.
251 * To make sure we don't leak OpenSSL handles, we use the ResourceOwner
252 * mechanism to free them on abort.
267/* ResourceOwner callbacks to hold OpenSSL cipher state */
272 .
name =
"pgcrypto OpenSSL cipher handle",
276 .DebugPrint = NULL,
/* default message is fine */
279/* Convenience wrappers over ResourceOwnerRemember/Forget */
294 EVP_CIPHER_CTX_free(od->
evp_ctx);
295 if (od->
owner != NULL)
300/* Common routines for all algorithms */
339 uint8 *res,
unsigned *rlen)
349 if (!EVP_CIPHER_CTX_set_padding(od->
evp_ctx, padding))
351 if (!EVP_CIPHER_CTX_set_key_length(od->
evp_ctx, od->
klen))
353 if (!EVP_DecryptInit_ex(od->
evp_ctx, NULL, NULL, od->
key, od->
iv))
358 if (!EVP_DecryptUpdate(od->
evp_ctx, res, &outlen,
data, dlen))
360 if (!EVP_DecryptFinal_ex(od->
evp_ctx, res + outlen, &outlen2))
362 *rlen = outlen + outlen2;
369 uint8 *res,
unsigned *rlen)
379 if (!EVP_CIPHER_CTX_set_padding(od->
evp_ctx, padding))
381 if (!EVP_CIPHER_CTX_set_key_length(od->
evp_ctx, od->
klen))
383 if (!EVP_EncryptInit_ex(od->
evp_ctx, NULL, NULL, od->
key, od->
iv))
388 if (!EVP_EncryptUpdate(od->
evp_ctx, res, &outlen,
data, dlen))
390 if (!EVP_EncryptFinal_ex(od->
evp_ctx, res + outlen, &outlen2))
392 *rlen = outlen + outlen2;
400 * Check if strong crypto is supported. Some OpenSSL installations
401 * support only short keys and unfortunately BF_set_key does not return any
402 * error value. This function tests if is possible to use strong key.
408 0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87, 0x78, 0x69,
409 0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f, 0x00, 0x11, 0x22, 0x33,
410 0x44, 0x55, 0x66, 0x77, 0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd,
411 0x3b, 0x2f, 0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76,
412 0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e, 0xff, 0xff,
413 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
416 static const uint8 data[8] = {0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10};
417 static const uint8 res[8] = {0xc0, 0x45, 0x04, 0x01, 0x2e, 0x4e, 0x1f, 0x53};
419 EVP_CIPHER_CTX *evp_ctx;
423 /* encrypt with 448bits key and verify output */
424 evp_ctx = EVP_CIPHER_CTX_new();
427 if (!EVP_EncryptInit_ex(evp_ctx, EVP_bf_ecb(), NULL, NULL, NULL))
429 if (!EVP_CIPHER_CTX_set_key_length(evp_ctx, 56))
431 if (!EVP_EncryptInit_ex(evp_ctx, NULL, NULL,
key, NULL))
434 if (!EVP_EncryptUpdate(evp_ctx, out, &outlen,
data, 8))
437 if (memcmp(out, res, 8) != 0)
438 goto leave;
/* Output does not match -> strong cipher is
443 EVP_CIPHER_CTX_free(evp_ctx);
452 static int bf_is_strong = -1;
455 * Test if key len is supported. BF_set_key silently cut large keys and it
456 * could be a problem when user transfer encrypted data from one server to
460 if (bf_is_strong == -1)
463 if (!bf_is_strong && klen > 16)
466 /* Key len is supported. We can use it. */
468 memcpy(od->
key,
key, klen);
471 memcpy(od->
iv, iv, bs);
473 memset(od->
iv, 0, bs);
486 memset(od->
key, 0, 8);
487 memcpy(od->
key,
key, klen > 8 ? 8 : klen);
490 memcpy(od->
iv, iv, bs);
492 memset(od->
iv, 0, bs);
505 memset(od->
key, 0, 24);
506 memcpy(od->
key,
key, klen > 24 ? 24 : klen);
509 memcpy(od->
iv, iv, bs);
511 memset(od->
iv, 0, bs);
524 memcpy(od->
key,
key, klen);
527 memcpy(od->
iv, iv, bs);
529 memset(od->
iv, 0, bs);
543 else if (klen <= 192 / 8)
545 else if (klen <= 256 / 8)
550 memcpy(od->
key,
key, klen);
553 memcpy(od->
iv, iv, bs);
555 memset(od->
iv, 0, bs);
582 /* shouldn't happen */
612 /* shouldn't happen */
642 /* shouldn't happen */
656 {
"blowfish",
"bf-cbc"},
657 {
"blowfish-cbc",
"bf-cbc"},
658 {
"blowfish-ecb",
"bf-ecb"},
659 {
"blowfish-cfb",
"bf-cfb"},
661 {
"3des",
"des3-cbc"},
662 {
"3des-ecb",
"des3-ecb"},
663 {
"3des-cbc",
"des3-cbc"},
664 {
"cast5",
"cast5-cbc"},
666 {
"rijndael",
"aes-cbc"},
667 {
"rijndael-cbc",
"aes-cbc"},
668 {
"rijndael-ecb",
"aes-ecb"},
669 {
"rijndael-cfb",
"aes-cfb"},
729 NULL,
/* EVP_aes_XXX_ecb(), determined in init
736 NULL,
/* EVP_aes_XXX_cbc(), determined in init
743 NULL,
/* EVP_aes_XXX_cfb(), determined in init
773/* PUBLIC functions */
785 if (strcmp(
i->name,
name) == 0)
793 * Create an OSSLCipher object, an EVP_CIPHER_CTX object and a PX_Cipher.
794 * The order is crucial, to make sure we don't leak anything on
795 * out-of-memory or other error.
800 /* Allocate an EVP_CIPHER_CTX object. */
801 ctx = EVP_CIPHER_CTX_new();
812 if (
i->ciph->cipher_func)
815 /* The PX_Cipher is allocated in current memory context */
830/* ResourceOwner callbacks for OSSLCipher */
841 * Returns the FIPS mode of the underlying OpenSSL installation.
846 int fips_enabled = 0;
849 * EVP_default_properties_is_fips_enabled was added in OpenSSL 3.0, before
850 * that FIPS_mode() was used to test for FIPS being enabled. The last
851 * upstream OpenSSL version before 3.0 which supported FIPS was 1.0.2, but
852 * there are forks of 1.1.1 which are FIPS validated so we still need to
853 * test with FIPS_mode() even though we don't support 1.0.2.
856#if OPENSSL_VERSION_NUMBER >= 0x30000000L
857 EVP_default_properties_is_fips_enabled(NULL);
862 return (fips_enabled == 1);
866 * CheckBuiltinCryptoMode
868 * Function for erroring out in case built-in crypto is executed when the user
869 * has disabled it. If builtin_crypto_enabled is set to BC_OFF or BC_FIPS and
870 * OpenSSL is operating in FIPS mode the function will error out, else the
871 * query executing built-in crypto can proceed.
881 errmsg(
"use of built-in crypto functions is disabled"));
887 errmsg(
"use of non-FIPS validated crypto not allowed when OpenSSL is in FIPS mode"));
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
void err(int eval, const char *fmt,...)
Assert(PointerIsAligned(start, uint64))
if(TABLE==NULL||TABLE_index==NULL)
void * MemoryContextAlloc(MemoryContext context, Size size)
void * MemoryContextAllocZero(MemoryContext context, Size size)
void pfree(void *pointer)
MemoryContext TopMemoryContext
static unsigned gen_ossl_block_size(PX_Cipher *c)
int px_find_digest(const char *name, PX_MD **res)
void CheckBuiltinCryptoMode(void)
static const struct ossl_cipher ossl_des_ecb
static const struct ossl_cipher ossl_des3_cbc
static void digest_update(PX_MD *h, const uint8 *data, unsigned dlen)
static int bf_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
static int bf_check_supported_key_len(void)
static void ResourceOwnerForgetOSSLDigest(ResourceOwner owner, OSSLDigest *digest)
static unsigned digest_result_size(PX_MD *h)
static const struct ossl_cipher ossl_aes_ecb
static void ResourceOwnerRememberOSSLDigest(ResourceOwner owner, OSSLDigest *digest)
static void digest_finish(PX_MD *h, uint8 *dst)
struct OSSLCipher OSSLCipher
static const struct ossl_cipher ossl_aes_cfb
static const ResourceOwnerDesc ossldigest_resowner_desc
static void free_openssl_cipher(OSSLCipher *od)
const EVP_CIPHER *(* ossl_EVP_cipher_func)(void)
static void ResourceOwnerForgetOSSLCipher(ResourceOwner owner, OSSLCipher *od)
static unsigned gen_ossl_key_size(PX_Cipher *c)
static int ossl_aes_ecb_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
static const struct ossl_cipher ossl_des3_ecb
static void ResOwnerReleaseOSSLCipher(Datum res)
static const struct ossl_cipher ossl_bf_cfb
struct OSSLDigest OSSLDigest
static int gen_ossl_encrypt(PX_Cipher *c, int padding, const uint8 *data, unsigned dlen, uint8 *res, unsigned *rlen)
static const struct ossl_cipher ossl_cast_cbc
static const ResourceOwnerDesc osslcipher_resowner_desc
static int gen_ossl_decrypt(PX_Cipher *c, int padding, const uint8 *data, unsigned dlen, uint8 *res, unsigned *rlen)
static void gen_ossl_free(PX_Cipher *c)
static const struct ossl_cipher ossl_des_cbc
static void digest_reset(PX_MD *h)
static void ResOwnerReleaseOSSLDigest(Datum res)
static int ossl_cast_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
static unsigned gen_ossl_iv_size(PX_Cipher *c)
int px_find_cipher(const char *name, PX_Cipher **res)
static const struct ossl_cipher ossl_bf_ecb
static PX_Alias ossl_aliases[]
static const struct ossl_cipher ossl_bf_cbc
static const struct ossl_cipher_lookup ossl_cipher_types[]
static void free_openssl_digest(OSSLDigest *digest)
static const struct ossl_cipher ossl_cast_ecb
static int ossl_aes_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
static int ossl_aes_cfb_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
static unsigned digest_block_size(PX_MD *h)
static const struct ossl_cipher ossl_aes_cbc
static int ossl_aes_cbc_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
static void digest_free(PX_MD *h)
static int ossl_des3_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
static void ResourceOwnerRememberOSSLCipher(ResourceOwner owner, OSSLCipher *od)
static int ossl_des_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
int builtin_crypto_enabled
static Datum PointerGetDatum(const void *X)
static Pointer DatumGetPointer(Datum X)
const char * px_resolve_alias(const PX_Alias *list, const char *name)
#define PXE_DECRYPT_FAILED
#define PXE_ENCRYPT_FAILED
ResourceOwner CurrentResourceOwner
void ResourceOwnerForget(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
void ResourceOwnerRemember(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
void ResourceOwnerEnlarge(ResourceOwner owner)
@ RESOURCE_RELEASE_BEFORE_LOCKS
#define RELEASE_PRIO_FIRST
const struct ossl_cipher * ciph
const EVP_CIPHER * evp_ciph
const struct ossl_cipher * ciph
int(* init)(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
ossl_EVP_cipher_func cipher_func
void(* update)(PX_MD *h, const uint8 *data, unsigned dlen)
unsigned(* result_size)(PX_MD *h)
unsigned(* block_size)(PX_MD *h)
void(* finish)(PX_MD *h, uint8 *dst)