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

Generated by: LCOV version 1.13