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

Generated by: LCOV version 1.14