Home | History | Annotate | Line # | Download | only in test
fake_pipelineprov.c revision 1.1.1.1.2.1
      1          1.1  christos /*
      2          1.1  christos  * Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved.
      3          1.1  christos  *
      4          1.1  christos  * Licensed under the Apache License 2.0 (the "License").  You may not use
      5          1.1  christos  * this file except in compliance with the License.  You can obtain a copy
      6          1.1  christos  * in the file LICENSE in the source distribution or at
      7          1.1  christos  * https://www.openssl.org/source/license.html
      8          1.1  christos  */
      9          1.1  christos 
     10          1.1  christos /*
     11          1.1  christos  * This file uses the low level AES functions (which are deprecated for
     12          1.1  christos  * non-internal use) in order to implement provider AES ciphers.
     13          1.1  christos  */
     14          1.1  christos #include "internal/deprecated.h"
     15          1.1  christos 
     16          1.1  christos #include <openssl/core.h>
     17          1.1  christos #include <openssl/core_names.h>
     18          1.1  christos #include <openssl/params.h>
     19          1.1  christos #include <openssl/proverr.h>
     20          1.1  christos #include "prov/providercommon.h"
     21          1.1  christos #include "prov/ciphercommon.h"
     22          1.1  christos #include "prov/ciphercommon_aead.h"
     23          1.1  christos #include "testutil.h"
     24          1.1  christos #include "fake_pipelineprov.h"
     25          1.1  christos 
     26          1.1  christos /*
     27          1.1  christos  * This file provides a fake provider that implements a pipeline cipher
     28          1.1  christos  * for AES GCM.
     29          1.1  christos  */
     30          1.1  christos 
     31          1.1  christos typedef struct fake_pipeline_ctx_st {
     32          1.1  christos     size_t keylen;
     33          1.1  christos     size_t ivlen;
     34          1.1  christos     size_t numpipes;
     35          1.1  christos     EVP_CIPHER *cipher;
     36          1.1  christos     EVP_CIPHER_CTX *cipher_ctxs[EVP_MAX_PIPES];
     37          1.1  christos } CIPHER_PIPELINE_CTX;
     38          1.1  christos 
     39          1.1  christos static void *fake_pipeline_newctx(void *provctx, char *ciphername,
     40  1.1.1.1.2.1    martin     size_t kbits, size_t ivbits)
     41          1.1  christos {
     42          1.1  christos     CIPHER_PIPELINE_CTX *ctx;
     43          1.1  christos 
     44          1.1  christos     if (!ossl_prov_is_running())
     45          1.1  christos         return NULL;
     46          1.1  christos 
     47          1.1  christos     ctx = OPENSSL_zalloc(sizeof(*ctx));
     48          1.1  christos     if (ctx == NULL)
     49          1.1  christos         return NULL;
     50          1.1  christos 
     51          1.1  christos     ctx->keylen = kbits / 8;
     52          1.1  christos     ctx->ivlen = ivbits / 8;
     53          1.1  christos     ctx->numpipes = 0;
     54          1.1  christos     ctx->cipher = EVP_CIPHER_fetch(provctx, ciphername, "provider=default");
     55          1.1  christos 
     56          1.1  christos     return ctx;
     57          1.1  christos }
     58          1.1  christos 
     59          1.1  christos static OSSL_FUNC_cipher_freectx_fn fake_pipeline_freectx;
     60          1.1  christos static void fake_pipeline_freectx(void *vctx)
     61          1.1  christos {
     62          1.1  christos     CIPHER_PIPELINE_CTX *ctx = (CIPHER_PIPELINE_CTX *)vctx;
     63          1.1  christos     size_t i;
     64          1.1  christos 
     65          1.1  christos     EVP_CIPHER_free(ctx->cipher);
     66          1.1  christos     for (i = 0; i < ctx->numpipes; i++)
     67          1.1  christos         EVP_CIPHER_CTX_free(ctx->cipher_ctxs[i]);
     68          1.1  christos     OPENSSL_clear_free(ctx, sizeof(*ctx));
     69          1.1  christos }
     70          1.1  christos 
     71          1.1  christos OSSL_FUNC_cipher_pipeline_encrypt_init_fn fake_pipeline_einit;
     72          1.1  christos OSSL_FUNC_cipher_pipeline_decrypt_init_fn fake_pipeline_dinit;
     73          1.1  christos OSSL_FUNC_cipher_pipeline_update_fn fake_pipeline_update;
     74          1.1  christos OSSL_FUNC_cipher_pipeline_final_fn fake_pipeline_final;
     75          1.1  christos OSSL_FUNC_cipher_gettable_ctx_params_fn fake_pipeline_aead_gettable_ctx_params;
     76          1.1  christos OSSL_FUNC_cipher_get_ctx_params_fn fake_pipeline_aead_get_ctx_params;
     77          1.1  christos OSSL_FUNC_cipher_settable_ctx_params_fn fake_pipeline_aead_settable_ctx_params;
     78          1.1  christos OSSL_FUNC_cipher_set_ctx_params_fn fake_pipeline_aead_set_ctx_params;
     79          1.1  christos 
     80          1.1  christos static int fake_pipeline_init(void *vctx,
     81  1.1.1.1.2.1    martin     const unsigned char *key, size_t keylen,
     82  1.1.1.1.2.1    martin     size_t numpipes, const unsigned char **iv,
     83  1.1.1.1.2.1    martin     size_t ivlen, int enc)
     84          1.1  christos {
     85          1.1  christos     CIPHER_PIPELINE_CTX *ctx = (CIPHER_PIPELINE_CTX *)vctx;
     86          1.1  christos     size_t i = 0;
     87          1.1  christos 
     88          1.1  christos     ctx->numpipes = numpipes;
     89          1.1  christos     for (i = 0; i < numpipes; i++) {
     90          1.1  christos         ctx->cipher_ctxs[i] = EVP_CIPHER_CTX_new();
     91          1.1  christos         if (ctx->cipher_ctxs[i] == NULL)
     92          1.1  christos             return 0;
     93          1.1  christos         if (!EVP_CipherInit(ctx->cipher_ctxs[i], ctx->cipher, key, iv[i], enc))
     94          1.1  christos             return 0;
     95          1.1  christos     }
     96          1.1  christos 
     97          1.1  christos     return 1;
     98          1.1  christos }
     99          1.1  christos 
    100          1.1  christos int fake_pipeline_einit(void *vctx,
    101  1.1.1.1.2.1    martin     const unsigned char *key, size_t keylen,
    102  1.1.1.1.2.1    martin     size_t numpipes, const unsigned char **iv,
    103  1.1.1.1.2.1    martin     size_t ivlen, const OSSL_PARAM params[])
    104          1.1  christos {
    105          1.1  christos     return fake_pipeline_init(vctx, key, keylen, numpipes, iv, ivlen, 1);
    106          1.1  christos }
    107          1.1  christos 
    108          1.1  christos int fake_pipeline_dinit(void *vctx,
    109  1.1.1.1.2.1    martin     const unsigned char *key, size_t keylen,
    110  1.1.1.1.2.1    martin     size_t numpipes, const unsigned char **iv,
    111  1.1.1.1.2.1    martin     size_t ivlen, const OSSL_PARAM params[])
    112          1.1  christos {
    113          1.1  christos     return fake_pipeline_init(vctx, key, keylen, numpipes, iv, ivlen, 0);
    114          1.1  christos }
    115          1.1  christos 
    116          1.1  christos int fake_pipeline_update(void *vctx, size_t numpipes,
    117  1.1.1.1.2.1    martin     unsigned char **out, size_t *outl,
    118  1.1.1.1.2.1    martin     const size_t *outsize,
    119  1.1.1.1.2.1    martin     const unsigned char **in, const size_t *inl)
    120          1.1  christos {
    121          1.1  christos     CIPHER_PIPELINE_CTX *ctx = (CIPHER_PIPELINE_CTX *)vctx;
    122          1.1  christos     int ioutl, inl_;
    123          1.1  christos     size_t i = 0;
    124          1.1  christos 
    125          1.1  christos     for (i = 0; i < numpipes; i++) {
    126          1.1  christos         inl_ = (int)inl[i];
    127          1.1  christos         if (!EVP_CipherUpdate(ctx->cipher_ctxs[i],
    128  1.1.1.1.2.1    martin                 (out != NULL) ? out[i] : NULL,
    129  1.1.1.1.2.1    martin                 &ioutl,
    130  1.1.1.1.2.1    martin                 in[i], inl_))
    131          1.1  christos             return 0;
    132          1.1  christos         outl[i] = (size_t)ioutl;
    133          1.1  christos     }
    134          1.1  christos     return 1;
    135          1.1  christos }
    136          1.1  christos 
    137          1.1  christos int fake_pipeline_final(void *vctx, size_t numpipes,
    138  1.1.1.1.2.1    martin     unsigned char **out, size_t *outl,
    139  1.1.1.1.2.1    martin     const size_t *outsize)
    140          1.1  christos {
    141          1.1  christos     CIPHER_PIPELINE_CTX *ctx = (CIPHER_PIPELINE_CTX *)vctx;
    142          1.1  christos     int ioutl;
    143          1.1  christos     size_t i = 0;
    144          1.1  christos 
    145          1.1  christos     for (i = 0; i < numpipes; i++) {
    146          1.1  christos         if (!EVP_CipherFinal(ctx->cipher_ctxs[i], out[i], &ioutl))
    147          1.1  christos             return 0;
    148          1.1  christos         outl[i] = (size_t)ioutl;
    149          1.1  christos     }
    150          1.1  christos     return 1;
    151          1.1  christos }
    152          1.1  christos 
    153          1.1  christos static const OSSL_PARAM fake_pipeline_aead_known_gettable_ctx_params[] = {
    154          1.1  christos     OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
    155          1.1  christos     OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL),
    156          1.1  christos     OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TAGLEN, NULL),
    157          1.1  christos     OSSL_PARAM_octet_ptr(OSSL_CIPHER_PARAM_PIPELINE_AEAD_TAG, NULL, 0),
    158          1.1  christos     OSSL_PARAM_END
    159          1.1  christos };
    160          1.1  christos const OSSL_PARAM *fake_pipeline_aead_gettable_ctx_params(ossl_unused void *cctx,
    161  1.1.1.1.2.1    martin     ossl_unused void *provctx)
    162          1.1  christos {
    163          1.1  christos     return fake_pipeline_aead_known_gettable_ctx_params;
    164          1.1  christos }
    165          1.1  christos 
    166          1.1  christos static const OSSL_PARAM fake_pipeline_aead_known_settable_ctx_params[] = {
    167          1.1  christos     OSSL_PARAM_octet_ptr(OSSL_CIPHER_PARAM_PIPELINE_AEAD_TAG, NULL, 0),
    168          1.1  christos     OSSL_PARAM_END
    169          1.1  christos };
    170          1.1  christos const OSSL_PARAM *fake_pipeline_aead_settable_ctx_params(ossl_unused void *cctx,
    171  1.1.1.1.2.1    martin     ossl_unused void *provctx)
    172          1.1  christos {
    173          1.1  christos     return fake_pipeline_aead_known_settable_ctx_params;
    174          1.1  christos }
    175          1.1  christos 
    176          1.1  christos int fake_pipeline_aead_get_ctx_params(void *vctx, OSSL_PARAM params[])
    177          1.1  christos {
    178          1.1  christos     CIPHER_PIPELINE_CTX *ctx = (CIPHER_PIPELINE_CTX *)vctx;
    179          1.1  christos     OSSL_PARAM *p;
    180          1.1  christos     size_t taglen, i;
    181          1.1  christos     unsigned char **aead_tags = NULL;
    182          1.1  christos     OSSL_PARAM aead_params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
    183          1.1  christos 
    184          1.1  christos     if (ossl_param_is_empty(params))
    185          1.1  christos         return 1;
    186          1.1  christos 
    187          1.1  christos     p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
    188          1.1  christos     if (p != NULL) {
    189          1.1  christos         if (!OSSL_PARAM_set_size_t(p, ctx->ivlen)) {
    190          1.1  christos             ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
    191          1.1  christos             return 0;
    192          1.1  christos         }
    193          1.1  christos     }
    194          1.1  christos 
    195          1.1  christos     p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
    196          1.1  christos     if (p != NULL) {
    197          1.1  christos         if (!OSSL_PARAM_set_size_t(p, ctx->keylen)) {
    198          1.1  christos             ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
    199          1.1  christos             return 0;
    200          1.1  christos         }
    201          1.1  christos     }
    202          1.1  christos 
    203          1.1  christos     p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_PIPELINE_AEAD_TAG);
    204          1.1  christos     if (p != NULL) {
    205          1.1  christos         if (!OSSL_PARAM_get_octet_ptr(p, (const void **)&aead_tags, &taglen)) {
    206          1.1  christos             ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
    207          1.1  christos             return 0;
    208          1.1  christos         }
    209          1.1  christos         for (i = 0; i < ctx->numpipes; i++) {
    210          1.1  christos             aead_params[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG,
    211  1.1.1.1.2.1    martin                 (void *)aead_tags[i],
    212  1.1.1.1.2.1    martin                 taglen);
    213          1.1  christos             if (!EVP_CIPHER_CTX_get_params(ctx->cipher_ctxs[i], aead_params)) {
    214          1.1  christos                 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
    215          1.1  christos                 return 0;
    216          1.1  christos             }
    217          1.1  christos         }
    218          1.1  christos     }
    219          1.1  christos 
    220          1.1  christos     return 1;
    221          1.1  christos }
    222          1.1  christos 
    223          1.1  christos int fake_pipeline_aead_set_ctx_params(void *vctx, const OSSL_PARAM params[])
    224          1.1  christos {
    225          1.1  christos     CIPHER_PIPELINE_CTX *ctx = (CIPHER_PIPELINE_CTX *)vctx;
    226          1.1  christos     const OSSL_PARAM *p;
    227          1.1  christos     size_t taglen, i;
    228          1.1  christos     unsigned char **aead_tags = NULL;
    229          1.1  christos     OSSL_PARAM aead_params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
    230          1.1  christos 
    231          1.1  christos     p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_PIPELINE_AEAD_TAG);
    232          1.1  christos     if (p != NULL) {
    233          1.1  christos         if (!OSSL_PARAM_get_octet_ptr(p, (const void **)&aead_tags, &taglen)) {
    234          1.1  christos             ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
    235          1.1  christos             return 0;
    236          1.1  christos         }
    237          1.1  christos         for (i = 0; i < ctx->numpipes; i++) {
    238          1.1  christos             aead_params[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG,
    239  1.1.1.1.2.1    martin                 (void *)aead_tags[i],
    240  1.1.1.1.2.1    martin                 taglen);
    241          1.1  christos             if (!EVP_CIPHER_CTX_set_params(ctx->cipher_ctxs[i], aead_params)) {
    242          1.1  christos                 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
    243          1.1  christos                 return 0;
    244          1.1  christos             }
    245          1.1  christos         }
    246          1.1  christos     }
    247          1.1  christos 
    248          1.1  christos     /* No other settable ctx param */
    249          1.1  christos     return 1;
    250          1.1  christos }
    251          1.1  christos 
    252  1.1.1.1.2.1    martin #define IMPLEMENT_aead_cipher_pipeline(alg, lc, UCMODE, flags, kbits, blkbits,       \
    253  1.1.1.1.2.1    martin     ivbits, ciphername)                                                              \
    254  1.1.1.1.2.1    martin     static OSSL_FUNC_cipher_get_params_fn alg##_##kbits##_##lc##_get_params;         \
    255  1.1.1.1.2.1    martin     static int alg##_##kbits##_##lc##_get_params(OSSL_PARAM params[])                \
    256  1.1.1.1.2.1    martin     {                                                                                \
    257  1.1.1.1.2.1    martin         return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE,      \
    258  1.1.1.1.2.1    martin             flags, kbits, blkbits, ivbits);                                          \
    259  1.1.1.1.2.1    martin     }                                                                                \
    260  1.1.1.1.2.1    martin     static OSSL_FUNC_cipher_newctx_fn fake_pipeline_##alg##_##kbits##_##lc##_newctx; \
    261  1.1.1.1.2.1    martin     static void *fake_pipeline_##alg##_##kbits##_##lc##_newctx(void *provctx)        \
    262  1.1.1.1.2.1    martin     {                                                                                \
    263  1.1.1.1.2.1    martin         return fake_pipeline_newctx(provctx, ciphername, kbits, ivbits);             \
    264  1.1.1.1.2.1    martin     }                                                                                \
    265  1.1.1.1.2.1    martin     static const OSSL_DISPATCH fake_pipeline_##alg##kbits##lc##_functions[] = {      \
    266  1.1.1.1.2.1    martin         { OSSL_FUNC_CIPHER_NEWCTX,                                                   \
    267  1.1.1.1.2.1    martin             (void (*)(void))fake_pipeline_##alg##_##kbits##_##lc##_newctx },         \
    268  1.1.1.1.2.1    martin         { OSSL_FUNC_CIPHER_FREECTX,                                                  \
    269  1.1.1.1.2.1    martin             (void (*)(void))fake_pipeline_freectx },                                 \
    270  1.1.1.1.2.1    martin         { OSSL_FUNC_CIPHER_PIPELINE_ENCRYPT_INIT,                                    \
    271  1.1.1.1.2.1    martin             (void (*)(void))fake_pipeline_einit },                                   \
    272  1.1.1.1.2.1    martin         { OSSL_FUNC_CIPHER_PIPELINE_DECRYPT_INIT,                                    \
    273  1.1.1.1.2.1    martin             (void (*)(void))fake_pipeline_dinit },                                   \
    274  1.1.1.1.2.1    martin         { OSSL_FUNC_CIPHER_PIPELINE_UPDATE,                                          \
    275  1.1.1.1.2.1    martin             (void (*)(void))fake_pipeline_update },                                  \
    276  1.1.1.1.2.1    martin         { OSSL_FUNC_CIPHER_PIPELINE_FINAL,                                           \
    277  1.1.1.1.2.1    martin             (void (*)(void))fake_pipeline_final },                                   \
    278  1.1.1.1.2.1    martin         { OSSL_FUNC_CIPHER_GET_PARAMS,                                               \
    279  1.1.1.1.2.1    martin             (void (*)(void))alg##_##kbits##_##lc##_get_params },                     \
    280  1.1.1.1.2.1    martin         { OSSL_FUNC_CIPHER_GET_CTX_PARAMS,                                           \
    281  1.1.1.1.2.1    martin             (void (*)(void))fake_pipeline_aead_get_ctx_params },                     \
    282  1.1.1.1.2.1    martin         { OSSL_FUNC_CIPHER_SET_CTX_PARAMS,                                           \
    283  1.1.1.1.2.1    martin             (void (*)(void))fake_pipeline_aead_set_ctx_params },                     \
    284  1.1.1.1.2.1    martin         { OSSL_FUNC_CIPHER_GETTABLE_PARAMS,                                          \
    285  1.1.1.1.2.1    martin             (void (*)(void))ossl_cipher_generic_gettable_params },                   \
    286  1.1.1.1.2.1    martin         { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS,                                      \
    287  1.1.1.1.2.1    martin             (void (*)(void))fake_pipeline_aead_gettable_ctx_params },                \
    288  1.1.1.1.2.1    martin         { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS,                                      \
    289  1.1.1.1.2.1    martin             (void (*)(void))fake_pipeline_aead_settable_ctx_params },                \
    290  1.1.1.1.2.1    martin         OSSL_DISPATCH_END                                                            \
    291          1.1  christos     }
    292          1.1  christos 
    293          1.1  christos IMPLEMENT_aead_cipher_pipeline(aes, gcm, GCM, AEAD_FLAGS, 256, 8, 96, "AES-256-GCM");
    294          1.1  christos 
    295          1.1  christos static const OSSL_ALGORITHM fake_ciphers[] = {
    296  1.1.1.1.2.1    martin     { "AES-256-GCM", "provider=fake-pipeline", fake_pipeline_aes256gcm_functions },
    297  1.1.1.1.2.1    martin     { NULL, NULL, NULL }
    298          1.1  christos };
    299          1.1  christos 
    300          1.1  christos static const OSSL_ALGORITHM *fake_pipeline_query(OSSL_PROVIDER *prov,
    301  1.1.1.1.2.1    martin     int operation_id,
    302  1.1.1.1.2.1    martin     int *no_cache)
    303          1.1  christos {
    304          1.1  christos     *no_cache = 0;
    305          1.1  christos     switch (operation_id) {
    306          1.1  christos     case OSSL_OP_CIPHER:
    307          1.1  christos         return fake_ciphers;
    308          1.1  christos     }
    309          1.1  christos     return NULL;
    310          1.1  christos }
    311          1.1  christos 
    312          1.1  christos /* Functions we provide to the core */
    313          1.1  christos static const OSSL_DISPATCH fake_pipeline_method[] = {
    314          1.1  christos     { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))OSSL_LIB_CTX_free },
    315          1.1  christos     { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))fake_pipeline_query },
    316          1.1  christos     OSSL_DISPATCH_END
    317          1.1  christos };
    318          1.1  christos 
    319          1.1  christos static int fake_pipeline_provider_init(const OSSL_CORE_HANDLE *handle,
    320  1.1.1.1.2.1    martin     const OSSL_DISPATCH *in,
    321  1.1.1.1.2.1    martin     const OSSL_DISPATCH **out, void **provctx)
    322          1.1  christos {
    323          1.1  christos     if (!TEST_ptr(*provctx = OSSL_LIB_CTX_new()))
    324          1.1  christos         return 0;
    325          1.1  christos     *out = fake_pipeline_method;
    326          1.1  christos     return 1;
    327          1.1  christos }
    328          1.1  christos 
    329          1.1  christos OSSL_PROVIDER *fake_pipeline_start(OSSL_LIB_CTX *libctx)
    330          1.1  christos {
    331          1.1  christos     OSSL_PROVIDER *p;
    332          1.1  christos 
    333          1.1  christos     if (!TEST_true(OSSL_PROVIDER_add_builtin(libctx, "fake-pipeline",
    334  1.1.1.1.2.1    martin             fake_pipeline_provider_init))
    335  1.1.1.1.2.1    martin         || !TEST_ptr(p = OSSL_PROVIDER_try_load(libctx, "fake-pipeline", 1)))
    336          1.1  christos         return NULL;
    337          1.1  christos 
    338          1.1  christos     return p;
    339          1.1  christos }
    340          1.1  christos 
    341          1.1  christos void fake_pipeline_finish(OSSL_PROVIDER *p)
    342          1.1  christos {
    343          1.1  christos     OSSL_PROVIDER_unload(p);
    344          1.1  christos }
    345