LCOV - code coverage report
Current view: top level - contrib/pgcrypto - openssl.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 239 288 83.0 %
Date: 2024-11-21 08:14:44 Functions: 28 30 93.3 %
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/evp.h>
      35             : #include <openssl/err.h>
      36             : #include <openssl/rand.h>
      37             : 
      38             : #include "px.h"
      39             : #include "utils/memutils.h"
      40             : #include "utils/resowner.h"
      41             : 
      42             : /*
      43             :  * Max lengths we might want to handle.
      44             :  */
      45             : #define MAX_KEY     (512/8)
      46             : #define MAX_IV      (128/8)
      47             : 
      48             : /*
      49             :  * Hashes
      50             :  */
      51             : 
      52             : /*
      53             :  * To make sure we don't leak OpenSSL handles, we use the ResourceOwner
      54             :  * mechanism to free them on abort.
      55             :  */
      56             : typedef struct OSSLDigest
      57             : {
      58             :     const EVP_MD *algo;
      59             :     EVP_MD_CTX *ctx;
      60             : 
      61             :     ResourceOwner owner;
      62             : } OSSLDigest;
      63             : 
      64             : /* ResourceOwner callbacks to hold OpenSSL digest handles */
      65             : static void ResOwnerReleaseOSSLDigest(Datum res);
      66             : 
      67             : static const ResourceOwnerDesc ossldigest_resowner_desc =
      68             : {
      69             :     .name = "pgcrypto OpenSSL digest handle",
      70             :     .release_phase = RESOURCE_RELEASE_BEFORE_LOCKS,
      71             :     .release_priority = RELEASE_PRIO_FIRST,
      72             :     .ReleaseResource = ResOwnerReleaseOSSLDigest,
      73             :     .DebugPrint = NULL,         /* default message is fine */
      74             : };
      75             : 
      76             : /* Convenience wrappers over ResourceOwnerRemember/Forget */
      77             : static inline void
      78         596 : ResourceOwnerRememberOSSLDigest(ResourceOwner owner, OSSLDigest *digest)
      79             : {
      80         596 :     ResourceOwnerRemember(owner, PointerGetDatum(digest), &ossldigest_resowner_desc);
      81         596 : }
      82             : static inline void
      83         596 : ResourceOwnerForgetOSSLDigest(ResourceOwner owner, OSSLDigest *digest)
      84             : {
      85         596 :     ResourceOwnerForget(owner, PointerGetDatum(digest), &ossldigest_resowner_desc);
      86         596 : }
      87             : 
      88             : static void
      89         596 : free_openssl_digest(OSSLDigest *digest)
      90             : {
      91         596 :     EVP_MD_CTX_destroy(digest->ctx);
      92         596 :     if (digest->owner != NULL)
      93         596 :         ResourceOwnerForgetOSSLDigest(digest->owner, digest);
      94         596 :     pfree(digest);
      95         596 : }
      96             : 
      97             : static unsigned
      98         328 : digest_result_size(PX_MD *h)
      99             : {
     100         328 :     OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
     101         328 :     int         result = EVP_MD_CTX_size(digest->ctx);
     102             : 
     103         328 :     if (result < 0)
     104           0 :         elog(ERROR, "EVP_MD_CTX_size() failed");
     105             : 
     106         328 :     return result;
     107             : }
     108             : 
     109             : static unsigned
     110         112 : digest_block_size(PX_MD *h)
     111             : {
     112         112 :     OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
     113         112 :     int         result = EVP_MD_CTX_block_size(digest->ctx);
     114             : 
     115         112 :     if (result < 0)
     116           0 :         elog(ERROR, "EVP_MD_CTX_block_size() failed");
     117             : 
     118         112 :     return result;
     119             : }
     120             : 
     121             : static void
     122        8256 : digest_reset(PX_MD *h)
     123             : {
     124        8256 :     OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
     125             : 
     126        8256 :     if (!EVP_DigestInit_ex(digest->ctx, digest->algo, NULL))
     127           0 :         elog(ERROR, "EVP_DigestInit_ex() failed");
     128        8256 : }
     129             : 
     130             : static void
     131    51133948 : digest_update(PX_MD *h, const uint8 *data, unsigned dlen)
     132             : {
     133    51133948 :     OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
     134             : 
     135    51133948 :     if (!EVP_DigestUpdate(digest->ctx, data, dlen))
     136           0 :         elog(ERROR, "EVP_DigestUpdate() failed");
     137    51133948 : }
     138             : 
     139             : static void
     140        8660 : digest_finish(PX_MD *h, uint8 *dst)
     141             : {
     142        8660 :     OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
     143             : 
     144        8660 :     if (!EVP_DigestFinal_ex(digest->ctx, dst, NULL))
     145           0 :         elog(ERROR, "EVP_DigestFinal_ex() failed");
     146        8660 : }
     147             : 
     148             : static void
     149         596 : digest_free(PX_MD *h)
     150             : {
     151         596 :     OSSLDigest *digest = (OSSLDigest *) h->p.ptr;
     152             : 
     153         596 :     free_openssl_digest(digest);
     154         596 :     pfree(h);
     155         596 : }
     156             : 
     157             : /* PUBLIC functions */
     158             : 
     159             : int
     160         600 : px_find_digest(const char *name, PX_MD **res)
     161             : {
     162             :     const EVP_MD *md;
     163             :     EVP_MD_CTX *ctx;
     164             :     PX_MD      *h;
     165             :     OSSLDigest *digest;
     166             : 
     167         600 :     md = EVP_get_digestbyname(name);
     168         600 :     if (md == NULL)
     169           4 :         return PXE_NO_HASH;
     170             : 
     171         596 :     ResourceOwnerEnlarge(CurrentResourceOwner);
     172             : 
     173             :     /*
     174             :      * Create an OSSLDigest object, an OpenSSL MD object, and a PX_MD object.
     175             :      * The order is crucial, to make sure we don't leak anything on
     176             :      * out-of-memory or other error.
     177             :      */
     178         596 :     digest = MemoryContextAlloc(TopMemoryContext, sizeof(*digest));
     179             : 
     180         596 :     ctx = EVP_MD_CTX_create();
     181         596 :     if (!ctx)
     182             :     {
     183           0 :         pfree(digest);
     184           0 :         return PXE_CIPHER_INIT;
     185             :     }
     186         596 :     if (EVP_DigestInit_ex(ctx, md, NULL) == 0)
     187             :     {
     188           0 :         EVP_MD_CTX_destroy(ctx);
     189           0 :         pfree(digest);
     190           0 :         return PXE_CIPHER_INIT;
     191             :     }
     192             : 
     193         596 :     digest->algo = md;
     194         596 :     digest->ctx = ctx;
     195         596 :     digest->owner = CurrentResourceOwner;
     196         596 :     ResourceOwnerRememberOSSLDigest(digest->owner, digest);
     197             : 
     198             :     /* The PX_MD object is allocated in the current memory context. */
     199         596 :     h = palloc(sizeof(*h));
     200         596 :     h->result_size = digest_result_size;
     201         596 :     h->block_size = digest_block_size;
     202         596 :     h->reset = digest_reset;
     203         596 :     h->update = digest_update;
     204         596 :     h->finish = digest_finish;
     205         596 :     h->free = digest_free;
     206         596 :     h->p.ptr = (void *) digest;
     207             : 
     208         596 :     *res = h;
     209         596 :     return 0;
     210             : }
     211             : 
     212             : /* ResourceOwner callbacks for OSSLDigest */
     213             : 
     214             : static void
     215           0 : ResOwnerReleaseOSSLDigest(Datum res)
     216             : {
     217           0 :     OSSLDigest *digest = (OSSLDigest *) DatumGetPointer(res);
     218             : 
     219           0 :     digest->owner = NULL;
     220           0 :     free_openssl_digest(digest);
     221           0 : }
     222             : 
     223             : /*
     224             :  * Ciphers
     225             :  *
     226             :  * We use OpenSSL's EVP* family of functions for these.
     227             :  */
     228             : 
     229             : /*
     230             :  * prototype for the EVP functions that return an algorithm, e.g.
     231             :  * EVP_aes_128_cbc().
     232             :  */
     233             : typedef const EVP_CIPHER *(*ossl_EVP_cipher_func) (void);
     234             : 
     235             : /*
     236             :  * ossl_cipher contains the static information about each cipher.
     237             :  */
     238             : struct ossl_cipher
     239             : {
     240             :     int         (*init) (PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv);
     241             :     ossl_EVP_cipher_func cipher_func;
     242             :     int         block_size;
     243             :     int         max_key_size;
     244             : };
     245             : 
     246             : /*
     247             :  * OSSLCipher contains the state for using a cipher. A separate OSSLCipher
     248             :  * object is allocated in each px_find_cipher() call.
     249             :  *
     250             :  * To make sure we don't leak OpenSSL handles, we use the ResourceOwner
     251             :  * mechanism to free them on abort.
     252             :  */
     253             : typedef struct OSSLCipher
     254             : {
     255             :     EVP_CIPHER_CTX *evp_ctx;
     256             :     const EVP_CIPHER *evp_ciph;
     257             :     uint8       key[MAX_KEY];
     258             :     uint8       iv[MAX_IV];
     259             :     unsigned    klen;
     260             :     unsigned    init;
     261             :     const struct ossl_cipher *ciph;
     262             : 
     263             :     ResourceOwner owner;
     264             : } OSSLCipher;
     265             : 
     266             : /* ResourceOwner callbacks to hold OpenSSL cipher state */
     267             : static void ResOwnerReleaseOSSLCipher(Datum res);
     268             : 
     269             : static const ResourceOwnerDesc osslcipher_resowner_desc =
     270             : {
     271             :     .name = "pgcrypto OpenSSL cipher handle",
     272             :     .release_phase = RESOURCE_RELEASE_BEFORE_LOCKS,
     273             :     .release_priority = RELEASE_PRIO_FIRST,
     274             :     .ReleaseResource = ResOwnerReleaseOSSLCipher,
     275             :     .DebugPrint = NULL,         /* default message is fine */
     276             : };
     277             : 
     278             : /* Convenience wrappers over ResourceOwnerRemember/Forget */
     279             : static inline void
     280         392 : ResourceOwnerRememberOSSLCipher(ResourceOwner owner, OSSLCipher *od)
     281             : {
     282         392 :     ResourceOwnerRemember(owner, PointerGetDatum(od), &osslcipher_resowner_desc);
     283         392 : }
     284             : static inline void
     285         392 : ResourceOwnerForgetOSSLCipher(ResourceOwner owner, OSSLCipher *od)
     286             : {
     287         392 :     ResourceOwnerForget(owner, PointerGetDatum(od), &osslcipher_resowner_desc);
     288         392 : }
     289             : 
     290             : static void
     291         392 : free_openssl_cipher(OSSLCipher *od)
     292             : {
     293         392 :     EVP_CIPHER_CTX_free(od->evp_ctx);
     294         392 :     if (od->owner != NULL)
     295         392 :         ResourceOwnerForgetOSSLCipher(od->owner, od);
     296         392 :     pfree(od);
     297         392 : }
     298             : 
     299             : /* Common routines for all algorithms */
     300             : 
     301             : static unsigned
     302         632 : gen_ossl_block_size(PX_Cipher *c)
     303             : {
     304         632 :     OSSLCipher *od = (OSSLCipher *) c->ptr;
     305             : 
     306         632 :     return od->ciph->block_size;
     307             : }
     308             : 
     309             : static unsigned
     310         152 : gen_ossl_key_size(PX_Cipher *c)
     311             : {
     312         152 :     OSSLCipher *od = (OSSLCipher *) c->ptr;
     313             : 
     314         152 :     return od->ciph->max_key_size;
     315             : }
     316             : 
     317             : static unsigned
     318         152 : gen_ossl_iv_size(PX_Cipher *c)
     319             : {
     320             :     unsigned    ivlen;
     321         152 :     OSSLCipher *od = (OSSLCipher *) c->ptr;
     322             : 
     323         152 :     ivlen = od->ciph->block_size;
     324         152 :     return ivlen;
     325             : }
     326             : 
     327             : static void
     328         392 : gen_ossl_free(PX_Cipher *c)
     329             : {
     330         392 :     OSSLCipher *od = (OSSLCipher *) c->ptr;
     331             : 
     332         392 :     free_openssl_cipher(od);
     333         392 :     pfree(c);
     334         392 : }
     335             : 
     336             : static int
     337          34 : gen_ossl_decrypt(PX_Cipher *c, int padding, const uint8 *data, unsigned dlen,
     338             :                  uint8 *res, unsigned *rlen)
     339             : {
     340          34 :     OSSLCipher *od = c->ptr;
     341             :     int         outlen,
     342             :                 outlen2;
     343             : 
     344          34 :     if (!od->init)
     345             :     {
     346          34 :         if (!EVP_DecryptInit_ex(od->evp_ctx, od->evp_ciph, NULL, NULL, NULL))
     347           0 :             return PXE_CIPHER_INIT;
     348          34 :         if (!EVP_CIPHER_CTX_set_padding(od->evp_ctx, padding))
     349           0 :             return PXE_CIPHER_INIT;
     350          34 :         if (!EVP_CIPHER_CTX_set_key_length(od->evp_ctx, od->klen))
     351           0 :             return PXE_CIPHER_INIT;
     352          34 :         if (!EVP_DecryptInit_ex(od->evp_ctx, NULL, NULL, od->key, od->iv))
     353           0 :             return PXE_CIPHER_INIT;
     354          34 :         od->init = true;
     355             :     }
     356             : 
     357          34 :     if (!EVP_DecryptUpdate(od->evp_ctx, res, &outlen, data, dlen))
     358           0 :         return PXE_DECRYPT_FAILED;
     359          34 :     if (!EVP_DecryptFinal_ex(od->evp_ctx, res + outlen, &outlen2))
     360           4 :         return PXE_DECRYPT_FAILED;
     361          30 :     *rlen = outlen + outlen2;
     362             : 
     363          30 :     return 0;
     364             : }
     365             : 
     366             : static int
     367       21766 : gen_ossl_encrypt(PX_Cipher *c, int padding, const uint8 *data, unsigned dlen,
     368             :                  uint8 *res, unsigned *rlen)
     369             : {
     370       21766 :     OSSLCipher *od = c->ptr;
     371             :     int         outlen,
     372             :                 outlen2;
     373             : 
     374       21766 :     if (!od->init)
     375             :     {
     376         358 :         if (!EVP_EncryptInit_ex(od->evp_ctx, od->evp_ciph, NULL, NULL, NULL))
     377           0 :             return PXE_CIPHER_INIT;
     378         358 :         if (!EVP_CIPHER_CTX_set_padding(od->evp_ctx, padding))
     379           0 :             return PXE_CIPHER_INIT;
     380         358 :         if (!EVP_CIPHER_CTX_set_key_length(od->evp_ctx, od->klen))
     381           0 :             return PXE_CIPHER_INIT;
     382         358 :         if (!EVP_EncryptInit_ex(od->evp_ctx, NULL, NULL, od->key, od->iv))
     383           0 :             return PXE_CIPHER_INIT;
     384         358 :         od->init = true;
     385             :     }
     386             : 
     387       21766 :     if (!EVP_EncryptUpdate(od->evp_ctx, res, &outlen, data, dlen))
     388           0 :         return PXE_ENCRYPT_FAILED;
     389       21766 :     if (!EVP_EncryptFinal_ex(od->evp_ctx, res + outlen, &outlen2))
     390           2 :         return PXE_ENCRYPT_FAILED;
     391       21764 :     *rlen = outlen + outlen2;
     392             : 
     393       21764 :     return 0;
     394             : }
     395             : 
     396             : /* Blowfish */
     397             : 
     398             : /*
     399             :  * Check if strong crypto is supported. Some OpenSSL installations
     400             :  * support only short keys and unfortunately BF_set_key does not return any
     401             :  * error value. This function tests if is possible to use strong key.
     402             :  */
     403             : static int
     404           8 : bf_check_supported_key_len(void)
     405             : {
     406             :     static const uint8 key[56] = {
     407             :         0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87, 0x78, 0x69,
     408             :         0x5a, 0x4b, 0x3c, 0x2d, 0x1e, 0x0f, 0x00, 0x11, 0x22, 0x33,
     409             :         0x44, 0x55, 0x66, 0x77, 0x04, 0x68, 0x91, 0x04, 0xc2, 0xfd,
     410             :         0x3b, 0x2f, 0x58, 0x40, 0x23, 0x64, 0x1a, 0xba, 0x61, 0x76,
     411             :         0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e, 0xff, 0xff,
     412             :         0xff, 0xff, 0xff, 0xff, 0xff, 0xff
     413             :     };
     414             : 
     415             :     static const uint8 data[8] = {0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10};
     416             :     static const uint8 res[8] = {0xc0, 0x45, 0x04, 0x01, 0x2e, 0x4e, 0x1f, 0x53};
     417             :     uint8       out[8];
     418             :     EVP_CIPHER_CTX *evp_ctx;
     419             :     int         outlen;
     420           8 :     int         status = 0;
     421             : 
     422             :     /* encrypt with 448bits key and verify output */
     423           8 :     evp_ctx = EVP_CIPHER_CTX_new();
     424           8 :     if (!evp_ctx)
     425           0 :         return 0;
     426           8 :     if (!EVP_EncryptInit_ex(evp_ctx, EVP_bf_ecb(), NULL, NULL, NULL))
     427           0 :         goto leave;
     428           8 :     if (!EVP_CIPHER_CTX_set_key_length(evp_ctx, 56))
     429           0 :         goto leave;
     430           8 :     if (!EVP_EncryptInit_ex(evp_ctx, NULL, NULL, key, NULL))
     431           0 :         goto leave;
     432             : 
     433           8 :     if (!EVP_EncryptUpdate(evp_ctx, out, &outlen, data, 8))
     434           0 :         goto leave;
     435             : 
     436           8 :     if (memcmp(out, res, 8) != 0)
     437           0 :         goto leave;             /* Output does not match -> strong cipher is
     438             :                                  * not supported */
     439           8 :     status = 1;
     440             : 
     441           8 : leave:
     442           8 :     EVP_CIPHER_CTX_free(evp_ctx);
     443           8 :     return status;
     444             : }
     445             : 
     446             : static int
     447          60 : bf_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
     448             : {
     449          60 :     OSSLCipher *od = c->ptr;
     450          60 :     unsigned    bs = gen_ossl_block_size(c);
     451             :     static int  bf_is_strong = -1;
     452             : 
     453             :     /*
     454             :      * Test if key len is supported. BF_set_key silently cut large keys and it
     455             :      * could be a problem when user transfer encrypted data from one server to
     456             :      * another.
     457             :      */
     458             : 
     459          60 :     if (bf_is_strong == -1)
     460           8 :         bf_is_strong = bf_check_supported_key_len();
     461             : 
     462          60 :     if (!bf_is_strong && klen > 16)
     463           0 :         return PXE_KEY_TOO_BIG;
     464             : 
     465             :     /* Key len is supported. We can use it. */
     466          60 :     od->klen = klen;
     467          60 :     memcpy(od->key, key, klen);
     468             : 
     469          60 :     if (iv)
     470          44 :         memcpy(od->iv, iv, bs);
     471             :     else
     472          16 :         memset(od->iv, 0, bs);
     473          60 :     return 0;
     474             : }
     475             : 
     476             : /* DES */
     477             : 
     478             : static int
     479          20 : ossl_des_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
     480             : {
     481          20 :     OSSLCipher *od = c->ptr;
     482          20 :     unsigned    bs = gen_ossl_block_size(c);
     483             : 
     484          20 :     od->klen = 8;
     485          20 :     memset(od->key, 0, 8);
     486          20 :     memcpy(od->key, key, klen > 8 ? 8 : klen);
     487             : 
     488          20 :     if (iv)
     489          20 :         memcpy(od->iv, iv, bs);
     490             :     else
     491           0 :         memset(od->iv, 0, bs);
     492          20 :     return 0;
     493             : }
     494             : 
     495             : /* DES3 */
     496             : 
     497             : static int
     498          22 : ossl_des3_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
     499             : {
     500          22 :     OSSLCipher *od = c->ptr;
     501          22 :     unsigned    bs = gen_ossl_block_size(c);
     502             : 
     503          22 :     od->klen = 24;
     504          22 :     memset(od->key, 0, 24);
     505          22 :     memcpy(od->key, key, klen > 24 ? 24 : klen);
     506             : 
     507          22 :     if (iv)
     508          22 :         memcpy(od->iv, iv, bs);
     509             :     else
     510           0 :         memset(od->iv, 0, bs);
     511          22 :     return 0;
     512             : }
     513             : 
     514             : /* CAST5 */
     515             : 
     516             : static int
     517          24 : ossl_cast_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
     518             : {
     519          24 :     OSSLCipher *od = c->ptr;
     520          24 :     unsigned    bs = gen_ossl_block_size(c);
     521             : 
     522          24 :     od->klen = klen;
     523          24 :     memcpy(od->key, key, klen);
     524             : 
     525          24 :     if (iv)
     526          24 :         memcpy(od->iv, iv, bs);
     527             :     else
     528           0 :         memset(od->iv, 0, bs);
     529          24 :     return 0;
     530             : }
     531             : 
     532             : /* AES */
     533             : 
     534             : static int
     535         266 : ossl_aes_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
     536             : {
     537         266 :     OSSLCipher *od = c->ptr;
     538         266 :     unsigned    bs = gen_ossl_block_size(c);
     539             : 
     540         266 :     if (klen <= 128 / 8)
     541         208 :         od->klen = 128 / 8;
     542          58 :     else if (klen <= 192 / 8)
     543          26 :         od->klen = 192 / 8;
     544          32 :     else if (klen <= 256 / 8)
     545          32 :         od->klen = 256 / 8;
     546             :     else
     547           0 :         return PXE_KEY_TOO_BIG;
     548             : 
     549         266 :     memcpy(od->key, key, klen);
     550             : 
     551         266 :     if (iv)
     552          42 :         memcpy(od->iv, iv, bs);
     553             :     else
     554         224 :         memset(od->iv, 0, bs);
     555             : 
     556         266 :     return 0;
     557             : }
     558             : 
     559             : static int
     560         230 : ossl_aes_ecb_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
     561             : {
     562         230 :     OSSLCipher *od = c->ptr;
     563             :     int         err;
     564             : 
     565         230 :     err = ossl_aes_init(c, key, klen, iv);
     566         230 :     if (err)
     567           0 :         return err;
     568             : 
     569         230 :     switch (od->klen)
     570             :     {
     571         182 :         case 128 / 8:
     572         182 :             od->evp_ciph = EVP_aes_128_ecb();
     573         182 :             break;
     574          22 :         case 192 / 8:
     575          22 :             od->evp_ciph = EVP_aes_192_ecb();
     576          22 :             break;
     577          26 :         case 256 / 8:
     578          26 :             od->evp_ciph = EVP_aes_256_ecb();
     579          26 :             break;
     580           0 :         default:
     581             :             /* shouldn't happen */
     582           0 :             err = PXE_CIPHER_INIT;
     583           0 :             break;
     584             :     }
     585             : 
     586         230 :     return err;
     587             : }
     588             : 
     589             : static int
     590          36 : ossl_aes_cbc_init(PX_Cipher *c, const uint8 *key, unsigned klen, const uint8 *iv)
     591             : {
     592          36 :     OSSLCipher *od = c->ptr;
     593             :     int         err;
     594             : 
     595          36 :     err = ossl_aes_init(c, key, klen, iv);
     596          36 :     if (err)
     597           0 :         return err;
     598             : 
     599          36 :     switch (od->klen)
     600             :     {
     601          26 :         case 128 / 8:
     602          26 :             od->evp_ciph = EVP_aes_128_cbc();
     603          26 :             break;
     604           4 :         case 192 / 8:
     605           4 :             od->evp_ciph = EVP_aes_192_cbc();
     606           4 :             break;
     607           6 :         case 256 / 8:
     608           6 :             od->evp_ciph = EVP_aes_256_cbc();
     609           6 :             break;
     610           0 :         default:
     611             :             /* shouldn't happen */
     612           0 :             err = PXE_CIPHER_INIT;
     613           0 :             break;
     614             :     }
     615             : 
     616          36 :     return err;
     617             : }
     618             : 
     619             : /*
     620             :  * aliases
     621             :  */
     622             : 
     623             : static PX_Alias ossl_aliases[] = {
     624             :     {"bf", "bf-cbc"},
     625             :     {"blowfish", "bf-cbc"},
     626             :     {"blowfish-cbc", "bf-cbc"},
     627             :     {"blowfish-ecb", "bf-ecb"},
     628             :     {"blowfish-cfb", "bf-cfb"},
     629             :     {"des", "des-cbc"},
     630             :     {"3des", "des3-cbc"},
     631             :     {"3des-ecb", "des3-ecb"},
     632             :     {"3des-cbc", "des3-cbc"},
     633             :     {"cast5", "cast5-cbc"},
     634             :     {"aes", "aes-cbc"},
     635             :     {"rijndael", "aes-cbc"},
     636             :     {"rijndael-cbc", "aes-cbc"},
     637             :     {"rijndael-ecb", "aes-ecb"},
     638             :     {NULL}
     639             : };
     640             : 
     641             : static const struct ossl_cipher ossl_bf_cbc = {
     642             :     bf_init,
     643             :     EVP_bf_cbc,
     644             :     64 / 8, 448 / 8
     645             : };
     646             : 
     647             : static const struct ossl_cipher ossl_bf_ecb = {
     648             :     bf_init,
     649             :     EVP_bf_ecb,
     650             :     64 / 8, 448 / 8
     651             : };
     652             : 
     653             : static const struct ossl_cipher ossl_bf_cfb = {
     654             :     bf_init,
     655             :     EVP_bf_cfb,
     656             :     64 / 8, 448 / 8
     657             : };
     658             : 
     659             : static const struct ossl_cipher ossl_des_ecb = {
     660             :     ossl_des_init,
     661             :     EVP_des_ecb,
     662             :     64 / 8, 64 / 8
     663             : };
     664             : 
     665             : static const struct ossl_cipher ossl_des_cbc = {
     666             :     ossl_des_init,
     667             :     EVP_des_cbc,
     668             :     64 / 8, 64 / 8
     669             : };
     670             : 
     671             : static const struct ossl_cipher ossl_des3_ecb = {
     672             :     ossl_des3_init,
     673             :     EVP_des_ede3_ecb,
     674             :     64 / 8, 192 / 8
     675             : };
     676             : 
     677             : static const struct ossl_cipher ossl_des3_cbc = {
     678             :     ossl_des3_init,
     679             :     EVP_des_ede3_cbc,
     680             :     64 / 8, 192 / 8
     681             : };
     682             : 
     683             : static const struct ossl_cipher ossl_cast_ecb = {
     684             :     ossl_cast_init,
     685             :     EVP_cast5_ecb,
     686             :     64 / 8, 128 / 8
     687             : };
     688             : 
     689             : static const struct ossl_cipher ossl_cast_cbc = {
     690             :     ossl_cast_init,
     691             :     EVP_cast5_cbc,
     692             :     64 / 8, 128 / 8
     693             : };
     694             : 
     695             : static const struct ossl_cipher ossl_aes_ecb = {
     696             :     ossl_aes_ecb_init,
     697             :     NULL,                       /* EVP_aes_XXX_ecb(), determined in init
     698             :                                  * function */
     699             :     128 / 8, 256 / 8
     700             : };
     701             : 
     702             : static const struct ossl_cipher ossl_aes_cbc = {
     703             :     ossl_aes_cbc_init,
     704             :     NULL,                       /* EVP_aes_XXX_cbc(), determined in init
     705             :                                  * function */
     706             :     128 / 8, 256 / 8
     707             : };
     708             : 
     709             : /*
     710             :  * Special handlers
     711             :  */
     712             : struct ossl_cipher_lookup
     713             : {
     714             :     const char *name;
     715             :     const struct ossl_cipher *ciph;
     716             : };
     717             : 
     718             : static const struct ossl_cipher_lookup ossl_cipher_types[] = {
     719             :     {"bf-cbc", &ossl_bf_cbc},
     720             :     {"bf-ecb", &ossl_bf_ecb},
     721             :     {"bf-cfb", &ossl_bf_cfb},
     722             :     {"des-ecb", &ossl_des_ecb},
     723             :     {"des-cbc", &ossl_des_cbc},
     724             :     {"des3-ecb", &ossl_des3_ecb},
     725             :     {"des3-cbc", &ossl_des3_cbc},
     726             :     {"cast5-ecb", &ossl_cast_ecb},
     727             :     {"cast5-cbc", &ossl_cast_cbc},
     728             :     {"aes-ecb", &ossl_aes_ecb},
     729             :     {"aes-cbc", &ossl_aes_cbc},
     730             :     {NULL}
     731             : };
     732             : 
     733             : /* PUBLIC functions */
     734             : 
     735             : int
     736         394 : px_find_cipher(const char *name, PX_Cipher **res)
     737             : {
     738             :     const struct ossl_cipher_lookup *i;
     739         394 :     PX_Cipher  *c = NULL;
     740             :     EVP_CIPHER_CTX *ctx;
     741             :     OSSLCipher *od;
     742             : 
     743         394 :     name = px_resolve_alias(ossl_aliases, name);
     744        3276 :     for (i = ossl_cipher_types; i->name; i++)
     745        3274 :         if (strcmp(i->name, name) == 0)
     746         392 :             break;
     747         394 :     if (i->name == NULL)
     748           2 :         return PXE_NO_CIPHER;
     749             : 
     750         392 :     ResourceOwnerEnlarge(CurrentResourceOwner);
     751             : 
     752             :     /*
     753             :      * Create an OSSLCipher object, an EVP_CIPHER_CTX object and a PX_Cipher.
     754             :      * The order is crucial, to make sure we don't leak anything on
     755             :      * out-of-memory or other error.
     756             :      */
     757         392 :     od = MemoryContextAllocZero(TopMemoryContext, sizeof(*od));
     758         392 :     od->ciph = i->ciph;
     759             : 
     760             :     /* Allocate an EVP_CIPHER_CTX object. */
     761         392 :     ctx = EVP_CIPHER_CTX_new();
     762         392 :     if (!ctx)
     763             :     {
     764           0 :         pfree(od);
     765           0 :         return PXE_CIPHER_INIT;
     766             :     }
     767             : 
     768         392 :     od->evp_ctx = ctx;
     769         392 :     od->owner = CurrentResourceOwner;
     770         392 :     ResourceOwnerRememberOSSLCipher(od->owner, od);
     771             : 
     772         392 :     if (i->ciph->cipher_func)
     773         126 :         od->evp_ciph = i->ciph->cipher_func();
     774             : 
     775             :     /* The PX_Cipher is allocated in current memory context */
     776         392 :     c = palloc(sizeof(*c));
     777         392 :     c->block_size = gen_ossl_block_size;
     778         392 :     c->key_size = gen_ossl_key_size;
     779         392 :     c->iv_size = gen_ossl_iv_size;
     780         392 :     c->free = gen_ossl_free;
     781         392 :     c->init = od->ciph->init;
     782         392 :     c->encrypt = gen_ossl_encrypt;
     783         392 :     c->decrypt = gen_ossl_decrypt;
     784         392 :     c->ptr = od;
     785             : 
     786         392 :     *res = c;
     787         392 :     return 0;
     788             : }
     789             : 
     790             : /* ResourceOwner callbacks for OSSLCipher */
     791             : 
     792             : static void
     793           0 : ResOwnerReleaseOSSLCipher(Datum res)
     794             : {
     795           0 :     free_openssl_cipher((OSSLCipher *) DatumGetPointer(res));
     796           0 : }

Generated by: LCOV version 1.14