LCOV - code coverage report
Current view: top level - contrib/pgcrypto - openssl.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 259 318 81.4 %
Date: 2025-02-18 08:14:55 Functions: 30 33 90.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * openssl.c
       3             :  *      Wrapper for OpenSSL library.
       4             :  *
       5             :  * Copyright (c) 2001 Marko Kreen
       6             :  * All rights reserved.
       7             :  *
       8             :  * Redistribution and use in source and binary forms, with or without
       9             :  * modification, are permitted provided that the following conditions
      10             :  * are met:
      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.
      16             :  *
      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
      27             :  * SUCH DAMAGE.
      28             :  *
      29             :  * contrib/pgcrypto/openssl.c
      30             :  */
      31             : 
      32             : #include "postgres.h"
      33             : 
      34             : #include <openssl/crypto.h>
      35             : #include <openssl/evp.h>
      36             : #include <openssl/err.h>
      37             : #include <openssl/rand.h>
      38             : 
      39             : #include "px.h"
      40             : #include "utils/memutils.h"
      41             : #include "utils/resowner.h"
      42             : 
      43             : /*
      44             :  * Max lengths we might want to handle.
      45             :  */
      46             : #define MAX_KEY     (512/8)
      47             : #define MAX_IV      (128/8)
      48             : 
      49             : /*
      50             :  * Hashes
      51             :  */
      52             : 
      53             : /*
      54             :  * To make sure we don't leak OpenSSL handles, we use the ResourceOwner
      55             :  * mechanism to free them on abort.
      56             :  */
      57             : typedef struct OSSLDigest
      58             : {
      59             :     const EVP_MD *algo;
      60             :     EVP_MD_CTX *ctx;
      61             : 
      62             :     ResourceOwner owner;
      63             : } OSSLDigest;
      64             : 
      65             : /* ResourceOwner callbacks to hold OpenSSL digest handles */
      66             : static void ResOwnerReleaseOSSLDigest(Datum res);
      67             : 
      68             : static const ResourceOwnerDesc ossldigest_resowner_desc =
      69             : {
      70             :     .name = "pgcrypto OpenSSL digest handle",
      71             :     .release_phase = RESOURCE_RELEASE_BEFORE_LOCKS,
      72             :     .release_priority = RELEASE_PRIO_FIRST,
      73             :     .ReleaseResource = ResOwnerReleaseOSSLDigest,
      74             :     .DebugPrint = NULL,         /* default message is fine */
      75             : };
      76             : 
      77             : /* Convenience wrappers over ResourceOwnerRemember/Forget */
      78             : static inline void
      79         596 : ResourceOwnerRememberOSSLDigest(ResourceOwner owner, OSSLDigest *digest)
      80             : {
      81         596 :     ResourceOwnerRemember(owner, PointerGetDatum(digest), &ossldigest_resowner_desc);
      82         596 : }
      83             : static inline void
      84         596 : ResourceOwnerForgetOSSLDigest(ResourceOwner owner, OSSLDigest *digest)
      85             : {
      86         596 :     ResourceOwnerForget(owner, PointerGetDatum(digest), &ossldigest_resowner_desc);
      87         596 : }
      88             : 
      89             : static void
      90         596 : free_openssl_digest(OSSLDigest *digest)
      91             : {
      92         596 :     EVP_MD_CTX_destroy(digest->ctx);
      93         596 :     if (digest->owner != NULL)
      94         596 :         ResourceOwnerForgetOSSLDigest(digest->owner, digest);
      95         596 :     pfree(digest);
      96         596 : }
      97             : 
      98             : static unsigned
      99         328 : digest_result_size(PX_MD *h)
     100             : {
     101         328 :     OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
     102         328 :     int         result = EVP_MD_CTX_size(digest->ctx);
     103             : 
     104         328 :     if (result < 0)
     105           0 :         elog(ERROR, "EVP_MD_CTX_size() failed");
     106             : 
     107         328 :     return result;
     108             : }
     109             : 
     110             : static unsigned
     111         112 : digest_block_size(PX_MD *h)
     112             : {
     113         112 :     OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
     114         112 :     int         result = EVP_MD_CTX_block_size(digest->ctx);
     115             : 
     116         112 :     if (result < 0)
     117           0 :         elog(ERROR, "EVP_MD_CTX_block_size() failed");
     118             : 
     119         112 :     return result;
     120             : }
     121             : 
     122             : static void
     123        8256 : digest_reset(PX_MD *h)
     124             : {
     125        8256 :     OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
     126             : 
     127        8256 :     if (!EVP_DigestInit_ex(digest->ctx, digest->algo, NULL))
     128           0 :         elog(ERROR, "EVP_DigestInit_ex() failed");
     129        8256 : }
     130             : 
     131             : static void
     132    51279584 : digest_update(PX_MD *h, const uint8 *data, unsigned dlen)
     133             : {
     134    51279584 :     OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
     135             : 
     136    51279584 :     if (!EVP_DigestUpdate(digest->ctx, data, dlen))
     137           0 :         elog(ERROR, "EVP_DigestUpdate() failed");
     138    51279584 : }
     139             : 
     140             : static void
     141        8660 : digest_finish(PX_MD *h, uint8 *dst)
     142             : {
     143        8660 :     OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
     144             : 
     145        8660 :     if (!EVP_DigestFinal_ex(digest->ctx, dst, NULL))
     146           0 :         elog(ERROR, "EVP_DigestFinal_ex() failed");
     147        8660 : }
     148             : 
     149             : static void
     150         596 : digest_free(PX_MD *h)
     151             : {
     152         596 :     OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
     153             : 
     154         596 :     free_openssl_digest(digest);
     155         596 :     pfree(h);
     156         596 : }
     157             : 
     158             : /* PUBLIC functions */
     159             : 
     160             : int
     161         600 : px_find_digest(const char *name, PX_MD **res)
     162             : {
     163             :     const EVP_MD *md;
     164             :     EVP_MD_CTX *ctx;
     165             :     PX_MD      *h;
     166             :     OSSLDigest *digest;
     167             : 
     168         600 :     md = EVP_get_digestbyname(name);
     169         600 :     if (md == NULL)
     170           4 :         return PXE_NO_HASH;
     171             : 
     172         596 :     ResourceOwnerEnlarge(CurrentResourceOwner);
     173             : 
     174             :     /*
     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.
     178             :      */
     179         596 :     digest = MemoryContextAlloc(TopMemoryContext, sizeof(*digest));
     180             : 
     181         596 :     ctx = EVP_MD_CTX_create();
     182         596 :     if (!ctx)
     183             :     {
     184           0 :         pfree(digest);
     185           0 :         return PXE_CIPHER_INIT;
     186             :     }
     187         596 :     if (EVP_DigestInit_ex(ctx, md, NULL) == 0)
     188             :     {
     189           0 :         EVP_MD_CTX_destroy(ctx);
     190           0 :         pfree(digest);
     191           0 :         return PXE_CIPHER_INIT;
     192             :     }
     193             : 
     194         596 :     digest->algo = md;
     195         596 :     digest->ctx = ctx;
     196         596 :     digest->owner = CurrentResourceOwner;
     197         596 :     ResourceOwnerRememberOSSLDigest(digest->owner, digest);
     198             : 
     199             :     /* The PX_MD object is allocated in the current memory context. */
     200         596 :     h = palloc(sizeof(*h));
     201         596 :     h->result_size = digest_result_size;
     202         596 :     h->block_size = digest_block_size;
     203         596 :     h->reset = digest_reset;
     204         596 :     h->update = digest_update;
     205         596 :     h->finish = digest_finish;
     206         596 :     h->free = digest_free;
     207         596 :     h->p.ptr = digest;
     208             : 
     209         596 :     *res = h;
     210         596 :     return 0;
     211             : }
     212             : 
     213             : /* ResourceOwner callbacks for OSSLDigest */
     214             : 
     215             : static void
     216           0 : ResOwnerReleaseOSSLDigest(Datum res)
     217             : {
     218           0 :     OSSLDigest *digest = (OSSLDigest *) DatumGetPointer(res);
     219             : 
     220           0 :     digest->owner = NULL;
     221           0 :     free_openssl_digest(digest);
     222           0 : }
     223             : 
     224             : /*
     225             :  * Ciphers
     226             :  *
     227             :  * We use OpenSSL's EVP* family of functions for these.
     228             :  */
     229             : 
     230             : /*
     231             :  * prototype for the EVP functions that return an algorithm, e.g.
     232             :  * EVP_aes_128_cbc().
     233             :  */
     234             : typedef const EVP_CIPHER *(*ossl_EVP_cipher_func) (void);
     235             : 
     236             : /*
     237             :  * ossl_cipher contains the static information about each cipher.
     238             :  */
     239             : struct ossl_cipher
     240             : {
     241             :     int         (*init) (PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv);
     242             :     ossl_EVP_cipher_func cipher_func;
     243             :     int         block_size;
     244             :     int         max_key_size;
     245             : };
     246             : 
     247             : /*
     248             :  * OSSLCipher contains the state for using a cipher. A separate OSSLCipher
     249             :  * object is allocated in each px_find_cipher() call.
     250             :  *
     251             :  * To make sure we don't leak OpenSSL handles, we use the ResourceOwner
     252             :  * mechanism to free them on abort.
     253             :  */
     254             : typedef struct OSSLCipher
     255             : {
     256             :     EVP_CIPHER_CTX *evp_ctx;
     257             :     const EVP_CIPHER *evp_ciph;
     258             :     uint8       key[MAX_KEY];
     259             :     uint8       iv[MAX_IV];
     260             :     unsigned    klen;
     261             :     unsigned    init;
     262             :     const struct ossl_cipher *ciph;
     263             : 
     264             :     ResourceOwner owner;
     265             : } OSSLCipher;
     266             : 
     267             : /* ResourceOwner callbacks to hold OpenSSL cipher state */
     268             : static void ResOwnerReleaseOSSLCipher(Datum res);
     269             : 
     270             : static const ResourceOwnerDesc osslcipher_resowner_desc =
     271             : {
     272             :     .name = "pgcrypto OpenSSL cipher handle",
     273             :     .release_phase = RESOURCE_RELEASE_BEFORE_LOCKS,
     274             :     .release_priority = RELEASE_PRIO_FIRST,
     275             :     .ReleaseResource = ResOwnerReleaseOSSLCipher,
     276             :     .DebugPrint = NULL,         /* default message is fine */
     277             : };
     278             : 
     279             : /* Convenience wrappers over ResourceOwnerRemember/Forget */
     280             : static inline void
     281         428 : ResourceOwnerRememberOSSLCipher(ResourceOwner owner, OSSLCipher *od)
     282             : {
     283         428 :     ResourceOwnerRemember(owner, PointerGetDatum(od), &osslcipher_resowner_desc);
     284         428 : }
     285             : static inline void
     286         428 : ResourceOwnerForgetOSSLCipher(ResourceOwner owner, OSSLCipher *od)
     287             : {
     288         428 :     ResourceOwnerForget(owner, PointerGetDatum(od), &osslcipher_resowner_desc);
     289         428 : }
     290             : 
     291             : static void
     292         428 : free_openssl_cipher(OSSLCipher *od)
     293             : {
     294         428 :     EVP_CIPHER_CTX_free(od->evp_ctx);
     295         428 :     if (od->owner != NULL)
     296         428 :         ResourceOwnerForgetOSSLCipher(od->owner, od);
     297         428 :     pfree(od);
     298         428 : }
     299             : 
     300             : /* Common routines for all algorithms */
     301             : 
     302             : static unsigned
     303         668 : gen_ossl_block_size(PX_Cipher *c)
     304             : {
     305         668 :     OSSLCipher *od = (OSSLCipher *) c->ptr;
     306             : 
     307         668 :     return od->ciph->block_size;
     308             : }
     309             : 
     310             : static unsigned
     311         188 : gen_ossl_key_size(PX_Cipher *c)
     312             : {
     313         188 :     OSSLCipher *od = (OSSLCipher *) c->ptr;
     314             : 
     315         188 :     return od->ciph->max_key_size;
     316             : }
     317             : 
     318             : static unsigned
     319         188 : gen_ossl_iv_size(PX_Cipher *c)
     320             : {
     321             :     unsigned    ivlen;
     322         188 :     OSSLCipher *od = (OSSLCipher *) c->ptr;
     323             : 
     324         188 :     ivlen = od->ciph->block_size;
     325         188 :     return ivlen;
     326             : }
     327             : 
     328             : static void
     329         428 : gen_ossl_free(PX_Cipher *c)
     330             : {
     331         428 :     OSSLCipher *od = (OSSLCipher *) c->ptr;
     332             : 
     333         428 :     free_openssl_cipher(od);
     334         428 :     pfree(c);
     335         428 : }
     336             : 
     337             : static int
     338          44 : gen_ossl_decrypt(PX_Cipher *c, int padding, const uint8 *data, unsigned dlen,
     339             :                  uint8 *res, unsigned *rlen)
     340             : {
     341          44 :     OSSLCipher *od = c->ptr;
     342             :     int         outlen,
     343             :                 outlen2;
     344             : 
     345          44 :     if (!od->init)
     346             :     {
     347          44 :         if (!EVP_DecryptInit_ex(od->evp_ctx, od->evp_ciph, NULL, NULL, NULL))
     348           0 :             return PXE_CIPHER_INIT;
     349          44 :         if (!EVP_CIPHER_CTX_set_padding(od->evp_ctx, padding))
     350           0 :             return PXE_CIPHER_INIT;
     351          44 :         if (!EVP_CIPHER_CTX_set_key_length(od->evp_ctx, od->klen))
     352           0 :             return PXE_CIPHER_INIT;
     353          44 :         if (!EVP_DecryptInit_ex(od->evp_ctx, NULL, NULL, od->key, od->iv))
     354           0 :             return PXE_CIPHER_INIT;
     355          44 :         od->init = true;
     356             :     }
     357             : 
     358          44 :     if (!EVP_DecryptUpdate(od->evp_ctx, res, &outlen, data, dlen))
     359           0 :         return PXE_DECRYPT_FAILED;
     360          44 :     if (!EVP_DecryptFinal_ex(od->evp_ctx, res + outlen, &outlen2))
     361           4 :         return PXE_DECRYPT_FAILED;
     362          40 :     *rlen = outlen + outlen2;
     363             : 
     364          40 :     return 0;
     365             : }
     366             : 
     367             : static int
     368       21792 : gen_ossl_encrypt(PX_Cipher *c, int padding, const uint8 *data, unsigned dlen,
     369             :                  uint8 *res, unsigned *rlen)
     370             : {
     371       21792 :     OSSLCipher *od = c->ptr;
     372             :     int         outlen,
     373             :                 outlen2;
     374             : 
     375       21792 :     if (!od->init)
     376             :     {
     377         384 :         if (!EVP_EncryptInit_ex(od->evp_ctx, od->evp_ciph, NULL, NULL, NULL))
     378           0 :             return PXE_CIPHER_INIT;
     379         384 :         if (!EVP_CIPHER_CTX_set_padding(od->evp_ctx, padding))
     380           0 :             return PXE_CIPHER_INIT;
     381         384 :         if (!EVP_CIPHER_CTX_set_key_length(od->evp_ctx, od->klen))
     382           0 :             return PXE_CIPHER_INIT;
     383         384 :         if (!EVP_EncryptInit_ex(od->evp_ctx, NULL, NULL, od->key, od->iv))
     384           0 :             return PXE_CIPHER_INIT;
     385         384 :         od->init = true;
     386             :     }
     387             : 
     388       21792 :     if (!EVP_EncryptUpdate(od->evp_ctx, res, &outlen, data, dlen))
     389           0 :         return PXE_ENCRYPT_FAILED;
     390       21792 :     if (!EVP_EncryptFinal_ex(od->evp_ctx, res + outlen, &outlen2))
     391           2 :         return PXE_ENCRYPT_FAILED;
     392       21790 :     *rlen = outlen + outlen2;
     393             : 
     394       21790 :     return 0;
     395             : }
     396             : 
     397             : /* Blowfish */
     398             : 
     399             : /*
     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.
     403             :  */
     404             : static int
     405           8 : bf_check_supported_key_len(void)
     406             : {
     407             :     static const uint8 key[56] = {
     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
     414             :     };
     415             : 
     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};
     418             :     uint8       out[8];
     419             :     EVP_CIPHER_CTX *evp_ctx;
     420             :     int         outlen;
     421           8 :     int         status = 0;
     422             : 
     423             :     /* encrypt with 448bits key and verify output */
     424           8 :     evp_ctx = EVP_CIPHER_CTX_new();
     425           8 :     if (!evp_ctx)
     426           0 :         return 0;
     427           8 :     if (!EVP_EncryptInit_ex(evp_ctx, EVP_bf_ecb(), NULL, NULL, NULL))
     428           0 :         goto leave;
     429           8 :     if (!EVP_CIPHER_CTX_set_key_length(evp_ctx, 56))
     430           0 :         goto leave;
     431           8 :     if (!EVP_EncryptInit_ex(evp_ctx, NULL, NULL, key, NULL))
     432           0 :         goto leave;
     433             : 
     434           8 :     if (!EVP_EncryptUpdate(evp_ctx, out, &outlen, data, 8))
     435           0 :         goto leave;
     436             : 
     437           8 :     if (memcmp(out, res, 8) != 0)
     438           0 :         goto leave;             /* Output does not match -> strong cipher is
     439             :                                  * not supported */
     440           8 :     status = 1;
     441             : 
     442           8 : leave:
     443           8 :     EVP_CIPHER_CTX_free(evp_ctx);
     444           8 :     return status;
     445             : }
     446             : 
     447             : static int
     448          60 : bf_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
     449             : {
     450          60 :     OSSLCipher *od = c->ptr;
     451          60 :     unsigned    bs = gen_ossl_block_size(c);
     452             :     static int  bf_is_strong = -1;
     453             : 
     454             :     /*
     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
     457             :      * another.
     458             :      */
     459             : 
     460          60 :     if (bf_is_strong == -1)
     461           8 :         bf_is_strong = bf_check_supported_key_len();
     462             : 
     463          60 :     if (!bf_is_strong && klen > 16)
     464           0 :         return PXE_KEY_TOO_BIG;
     465             : 
     466             :     /* Key len is supported. We can use it. */
     467          60 :     od->klen = klen;
     468          60 :     memcpy(od->key, key, klen);
     469             : 
     470          60 :     if (iv)
     471          44 :         memcpy(od->iv, iv, bs);
     472             :     else
     473          16 :         memset(od->iv, 0, bs);
     474          60 :     return 0;
     475             : }
     476             : 
     477             : /* DES */
     478             : 
     479             : static int
     480          20 : ossl_des_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
     481             : {
     482          20 :     OSSLCipher *od = c->ptr;
     483          20 :     unsigned    bs = gen_ossl_block_size(c);
     484             : 
     485          20 :     od->klen = 8;
     486          20 :     memset(od->key, 0, 8);
     487          20 :     memcpy(od->key, key, klen > 8 ? 8 : klen);
     488             : 
     489          20 :     if (iv)
     490          20 :         memcpy(od->iv, iv, bs);
     491             :     else
     492           0 :         memset(od->iv, 0, bs);
     493          20 :     return 0;
     494             : }
     495             : 
     496             : /* DES3 */
     497             : 
     498             : static int
     499          22 : ossl_des3_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
     500             : {
     501          22 :     OSSLCipher *od = c->ptr;
     502          22 :     unsigned    bs = gen_ossl_block_size(c);
     503             : 
     504          22 :     od->klen = 24;
     505          22 :     memset(od->key, 0, 24);
     506          22 :     memcpy(od->key, key, klen > 24 ? 24 : klen);
     507             : 
     508          22 :     if (iv)
     509          22 :         memcpy(od->iv, iv, bs);
     510             :     else
     511           0 :         memset(od->iv, 0, bs);
     512          22 :     return 0;
     513             : }
     514             : 
     515             : /* CAST5 */
     516             : 
     517             : static int
     518          24 : ossl_cast_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
     519             : {
     520          24 :     OSSLCipher *od = c->ptr;
     521          24 :     unsigned    bs = gen_ossl_block_size(c);
     522             : 
     523          24 :     od->klen = klen;
     524          24 :     memcpy(od->key, key, klen);
     525             : 
     526          24 :     if (iv)
     527          24 :         memcpy(od->iv, iv, bs);
     528             :     else
     529           0 :         memset(od->iv, 0, bs);
     530          24 :     return 0;
     531             : }
     532             : 
     533             : /* AES */
     534             : 
     535             : static int
     536         302 : ossl_aes_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
     537             : {
     538         302 :     OSSLCipher *od = c->ptr;
     539         302 :     unsigned    bs = gen_ossl_block_size(c);
     540             : 
     541         302 :     if (klen <= 128 / 8)
     542         234 :         od->klen = 128 / 8;
     543          68 :     else if (klen <= 192 / 8)
     544          30 :         od->klen = 192 / 8;
     545          38 :     else if (klen <= 256 / 8)
     546          38 :         od->klen = 256 / 8;
     547             :     else
     548           0 :         return PXE_KEY_TOO_BIG;
     549             : 
     550         302 :     memcpy(od->key, key, klen);
     551             : 
     552         302 :     if (iv)
     553          78 :         memcpy(od->iv, iv, bs);
     554             :     else
     555         224 :         memset(od->iv, 0, bs);
     556             : 
     557         302 :     return 0;
     558             : }
     559             : 
     560             : static int
     561         230 : ossl_aes_ecb_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
     562             : {
     563         230 :     OSSLCipher *od = c->ptr;
     564             :     int         err;
     565             : 
     566         230 :     err = ossl_aes_init(c, key, klen, iv);
     567         230 :     if (err)
     568           0 :         return err;
     569             : 
     570         230 :     switch (od->klen)
     571             :     {
     572         182 :         case 128 / 8:
     573         182 :             od->evp_ciph = EVP_aes_128_ecb();
     574         182 :             break;
     575          22 :         case 192 / 8:
     576          22 :             od->evp_ciph = EVP_aes_192_ecb();
     577          22 :             break;
     578          26 :         case 256 / 8:
     579          26 :             od->evp_ciph = EVP_aes_256_ecb();
     580          26 :             break;
     581           0 :         default:
     582             :             /* shouldn't happen */
     583           0 :             err = PXE_CIPHER_INIT;
     584           0 :             break;
     585             :     }
     586             : 
     587         230 :     return err;
     588             : }
     589             : 
     590             : static int
     591          36 : ossl_aes_cbc_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
     592             : {
     593          36 :     OSSLCipher *od = c->ptr;
     594             :     int         err;
     595             : 
     596          36 :     err = ossl_aes_init(c, key, klen, iv);
     597          36 :     if (err)
     598           0 :         return err;
     599             : 
     600          36 :     switch (od->klen)
     601             :     {
     602          26 :         case 128 / 8:
     603          26 :             od->evp_ciph = EVP_aes_128_cbc();
     604          26 :             break;
     605           4 :         case 192 / 8:
     606           4 :             od->evp_ciph = EVP_aes_192_cbc();
     607           4 :             break;
     608           6 :         case 256 / 8:
     609           6 :             od->evp_ciph = EVP_aes_256_cbc();
     610           6 :             break;
     611           0 :         default:
     612             :             /* shouldn't happen */
     613           0 :             err = PXE_CIPHER_INIT;
     614           0 :             break;
     615             :     }
     616             : 
     617          36 :     return err;
     618             : }
     619             : 
     620             : static int
     621          36 : ossl_aes_cfb_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
     622             : {
     623          36 :     OSSLCipher *od = c->ptr;
     624             :     int         err;
     625             : 
     626          36 :     err = ossl_aes_init(c, key, klen, iv);
     627          36 :     if (err)
     628           0 :         return err;
     629             : 
     630          36 :     switch (od->klen)
     631             :     {
     632          26 :         case 128 / 8:
     633          26 :             od->evp_ciph = EVP_aes_128_cfb();
     634          26 :             break;
     635           4 :         case 192 / 8:
     636           4 :             od->evp_ciph = EVP_aes_192_cfb();
     637           4 :             break;
     638           6 :         case 256 / 8:
     639           6 :             od->evp_ciph = EVP_aes_256_cfb();
     640           6 :             break;
     641           0 :         default:
     642             :             /* shouldn't happen */
     643           0 :             err = PXE_CIPHER_INIT;
     644           0 :             break;
     645             :     }
     646             : 
     647          36 :     return err;
     648             : }
     649             : 
     650             : /*
     651             :  * aliases
     652             :  */
     653             : 
     654             : static PX_Alias ossl_aliases[] = {
     655             :     {"bf", "bf-cbc"},
     656             :     {"blowfish", "bf-cbc"},
     657             :     {"blowfish-cbc", "bf-cbc"},
     658             :     {"blowfish-ecb", "bf-ecb"},
     659             :     {"blowfish-cfb", "bf-cfb"},
     660             :     {"des", "des-cbc"},
     661             :     {"3des", "des3-cbc"},
     662             :     {"3des-ecb", "des3-ecb"},
     663             :     {"3des-cbc", "des3-cbc"},
     664             :     {"cast5", "cast5-cbc"},
     665             :     {"aes", "aes-cbc"},
     666             :     {"rijndael", "aes-cbc"},
     667             :     {"rijndael-cbc", "aes-cbc"},
     668             :     {"rijndael-ecb", "aes-ecb"},
     669             :     {"rijndael-cfb", "aes-cfb"},
     670             :     {NULL}
     671             : };
     672             : 
     673             : static const struct ossl_cipher ossl_bf_cbc = {
     674             :     bf_init,
     675             :     EVP_bf_cbc,
     676             :     64 / 8, 448 / 8
     677             : };
     678             : 
     679             : static const struct ossl_cipher ossl_bf_ecb = {
     680             :     bf_init,
     681             :     EVP_bf_ecb,
     682             :     64 / 8, 448 / 8
     683             : };
     684             : 
     685             : static const struct ossl_cipher ossl_bf_cfb = {
     686             :     bf_init,
     687             :     EVP_bf_cfb,
     688             :     64 / 8, 448 / 8
     689             : };
     690             : 
     691             : static const struct ossl_cipher ossl_des_ecb = {
     692             :     ossl_des_init,
     693             :     EVP_des_ecb,
     694             :     64 / 8, 64 / 8
     695             : };
     696             : 
     697             : static const struct ossl_cipher ossl_des_cbc = {
     698             :     ossl_des_init,
     699             :     EVP_des_cbc,
     700             :     64 / 8, 64 / 8
     701             : };
     702             : 
     703             : static const struct ossl_cipher ossl_des3_ecb = {
     704             :     ossl_des3_init,
     705             :     EVP_des_ede3_ecb,
     706             :     64 / 8, 192 / 8
     707             : };
     708             : 
     709             : static const struct ossl_cipher ossl_des3_cbc = {
     710             :     ossl_des3_init,
     711             :     EVP_des_ede3_cbc,
     712             :     64 / 8, 192 / 8
     713             : };
     714             : 
     715             : static const struct ossl_cipher ossl_cast_ecb = {
     716             :     ossl_cast_init,
     717             :     EVP_cast5_ecb,
     718             :     64 / 8, 128 / 8
     719             : };
     720             : 
     721             : static const struct ossl_cipher ossl_cast_cbc = {
     722             :     ossl_cast_init,
     723             :     EVP_cast5_cbc,
     724             :     64 / 8, 128 / 8
     725             : };
     726             : 
     727             : static const struct ossl_cipher ossl_aes_ecb = {
     728             :     ossl_aes_ecb_init,
     729             :     NULL,                       /* EVP_aes_XXX_ecb(), determined in init
     730             :                                  * function */
     731             :     128 / 8, 256 / 8
     732             : };
     733             : 
     734             : static const struct ossl_cipher ossl_aes_cbc = {
     735             :     ossl_aes_cbc_init,
     736             :     NULL,                       /* EVP_aes_XXX_cbc(), determined in init
     737             :                                  * function */
     738             :     128 / 8, 256 / 8
     739             : };
     740             : 
     741             : static const struct ossl_cipher ossl_aes_cfb = {
     742             :     ossl_aes_cfb_init,
     743             :     NULL,                       /* EVP_aes_XXX_cfb(), determined in init
     744             :                                  * function */
     745             :     128 / 8, 256 / 8
     746             : };
     747             : 
     748             : /*
     749             :  * Special handlers
     750             :  */
     751             : struct ossl_cipher_lookup
     752             : {
     753             :     const char *name;
     754             :     const struct ossl_cipher *ciph;
     755             : };
     756             : 
     757             : static const struct ossl_cipher_lookup ossl_cipher_types[] = {
     758             :     {"bf-cbc", &ossl_bf_cbc},
     759             :     {"bf-ecb", &ossl_bf_ecb},
     760             :     {"bf-cfb", &ossl_bf_cfb},
     761             :     {"des-ecb", &ossl_des_ecb},
     762             :     {"des-cbc", &ossl_des_cbc},
     763             :     {"des3-ecb", &ossl_des3_ecb},
     764             :     {"des3-cbc", &ossl_des3_cbc},
     765             :     {"cast5-ecb", &ossl_cast_ecb},
     766             :     {"cast5-cbc", &ossl_cast_cbc},
     767             :     {"aes-ecb", &ossl_aes_ecb},
     768             :     {"aes-cbc", &ossl_aes_cbc},
     769             :     {"aes-cfb", &ossl_aes_cfb},
     770             :     {NULL}
     771             : };
     772             : 
     773             : /* PUBLIC functions */
     774             : 
     775             : int
     776         430 : px_find_cipher(const char *name, PX_Cipher **res)
     777             : {
     778             :     const struct ossl_cipher_lookup *i;
     779         430 :     PX_Cipher  *c = NULL;
     780             :     EVP_CIPHER_CTX *ctx;
     781             :     OSSLCipher *od;
     782             : 
     783         430 :     name = px_resolve_alias(ossl_aliases, name);
     784        3710 :     for (i = ossl_cipher_types; i->name; i++)
     785        3708 :         if (strcmp(i->name, name) == 0)
     786         428 :             break;
     787         430 :     if (i->name == NULL)
     788           2 :         return PXE_NO_CIPHER;
     789             : 
     790         428 :     ResourceOwnerEnlarge(CurrentResourceOwner);
     791             : 
     792             :     /*
     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.
     796             :      */
     797         428 :     od = MemoryContextAllocZero(TopMemoryContext, sizeof(*od));
     798         428 :     od->ciph = i->ciph;
     799             : 
     800             :     /* Allocate an EVP_CIPHER_CTX object. */
     801         428 :     ctx = EVP_CIPHER_CTX_new();
     802         428 :     if (!ctx)
     803             :     {
     804           0 :         pfree(od);
     805           0 :         return PXE_CIPHER_INIT;
     806             :     }
     807             : 
     808         428 :     od->evp_ctx = ctx;
     809         428 :     od->owner = CurrentResourceOwner;
     810         428 :     ResourceOwnerRememberOSSLCipher(od->owner, od);
     811             : 
     812         428 :     if (i->ciph->cipher_func)
     813         126 :         od->evp_ciph = i->ciph->cipher_func();
     814             : 
     815             :     /* The PX_Cipher is allocated in current memory context */
     816         428 :     c = palloc(sizeof(*c));
     817         428 :     c->block_size = gen_ossl_block_size;
     818         428 :     c->key_size = gen_ossl_key_size;
     819         428 :     c->iv_size = gen_ossl_iv_size;
     820         428 :     c->free = gen_ossl_free;
     821         428 :     c->init = od->ciph->init;
     822         428 :     c->encrypt = gen_ossl_encrypt;
     823         428 :     c->decrypt = gen_ossl_decrypt;
     824         428 :     c->ptr = od;
     825             : 
     826         428 :     *res = c;
     827         428 :     return 0;
     828             : }
     829             : 
     830             : /* ResourceOwner callbacks for OSSLCipher */
     831             : 
     832             : static void
     833           0 : ResOwnerReleaseOSSLCipher(Datum res)
     834             : {
     835           0 :     free_openssl_cipher((OSSLCipher *) DatumGetPointer(res));
     836           0 : }
     837             : 
     838             : /*
     839             :  * CheckFIPSMode
     840             :  *
     841             :  * Returns the FIPS mode of the underlying OpenSSL installation.
     842             :  */
     843             : bool
     844           0 : CheckFIPSMode(void)
     845             : {
     846           0 :     int         fips_enabled = 0;
     847             : 
     848             :     /*
     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.
     854             :      */
     855             :     fips_enabled =
     856             : #if OPENSSL_VERSION_NUMBER >= 0x30000000L
     857             :         EVP_default_properties_is_fips_enabled(NULL);
     858             : #else
     859           0 :         FIPS_mode();
     860             : #endif
     861             : 
     862           0 :     return (fips_enabled == 1);
     863             : }
     864             : 
     865             : /*
     866             :  * CheckBuiltinCryptoMode
     867             :  *
     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.
     872             :  */
     873             : void
     874          64 : CheckBuiltinCryptoMode(void)
     875             : {
     876          64 :     if (builtin_crypto_enabled == BC_ON)
     877          60 :         return;
     878             : 
     879           4 :     if (builtin_crypto_enabled == BC_OFF)
     880           4 :         ereport(ERROR,
     881             :                 errmsg("use of built-in crypto functions is disabled"));
     882             : 
     883             :     Assert(builtin_crypto_enabled == BC_FIPS);
     884             : 
     885           0 :     if (CheckFIPSMode() == true)
     886           0 :         ereport(ERROR,
     887             :                 errmsg("use of non-FIPS validated crypto not allowed when OpenSSL is in FIPS mode"));
     888             : }

Generated by: LCOV version 1.14