Home | History | Annotate | Line # | Download | only in test
fake_pipelineprov.c revision 1.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  christos                                   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  christos                               const unsigned char *key, size_t keylen,
     82  1.1  christos                               size_t numpipes, const unsigned char **iv,
     83  1.1  christos                               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  christos                         const unsigned char *key, size_t keylen,
    102  1.1  christos                         size_t numpipes, const unsigned char **iv,
    103  1.1  christos                         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  christos                         const unsigned char *key, size_t keylen,
    110  1.1  christos                         size_t numpipes, const unsigned char **iv,
    111  1.1  christos                         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  christos                          unsigned char **out, size_t *outl,
    118  1.1  christos                          const size_t *outsize,
    119  1.1  christos                          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  christos                               (out != NULL) ? out[i] : NULL,
    129  1.1  christos                               &ioutl,
    130  1.1  christos                               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  christos                         unsigned char **out, size_t *outl,
    139  1.1  christos                         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  christos                                                          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  christos                                                          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  christos                                                                (void *)aead_tags[i],
    212  1.1  christos                                                                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  christos                                                                (void *)aead_tags[i],
    240  1.1  christos                                                                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  christos #define IMPLEMENT_aead_cipher_pipeline(alg, lc, UCMODE, flags, kbits, blkbits,          \
    253  1.1  christos                                        ivbits, ciphername)                              \
    254  1.1  christos     static OSSL_FUNC_cipher_get_params_fn alg##_##kbits##_##lc##_get_params;            \
    255  1.1  christos     static int alg##_##kbits##_##lc##_get_params(OSSL_PARAM params[])                   \
    256  1.1  christos     {                                                                                   \
    257  1.1  christos         return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE,         \
    258  1.1  christos                                               flags, kbits, blkbits, ivbits);           \
    259  1.1  christos     }                                                                                   \
    260  1.1  christos     static OSSL_FUNC_cipher_newctx_fn fake_pipeline_##alg##_##kbits##_##lc##_newctx;    \
    261  1.1  christos     static void * fake_pipeline_##alg##_##kbits##_##lc##_newctx(void *provctx)          \
    262  1.1  christos     {                                                                                   \
    263  1.1  christos         return fake_pipeline_newctx(provctx, ciphername, kbits, ivbits);                \
    264  1.1  christos     }                                                                                   \
    265  1.1  christos     static const OSSL_DISPATCH fake_pipeline_##alg##kbits##lc##_functions[] = {         \
    266  1.1  christos         { OSSL_FUNC_CIPHER_NEWCTX,                                                      \
    267  1.1  christos           (void (*)(void))fake_pipeline_##alg##_##kbits##_##lc##_newctx },              \
    268  1.1  christos         { OSSL_FUNC_CIPHER_FREECTX,                                                     \
    269  1.1  christos           (void (*)(void))fake_pipeline_freectx },                                      \
    270  1.1  christos         { OSSL_FUNC_CIPHER_PIPELINE_ENCRYPT_INIT,                                       \
    271  1.1  christos           (void (*)(void))fake_pipeline_einit },                                        \
    272  1.1  christos         { OSSL_FUNC_CIPHER_PIPELINE_DECRYPT_INIT,                                       \
    273  1.1  christos           (void (*)(void))fake_pipeline_dinit },                                        \
    274  1.1  christos         { OSSL_FUNC_CIPHER_PIPELINE_UPDATE,                                             \
    275  1.1  christos           (void (*)(void))fake_pipeline_update },                                       \
    276  1.1  christos         { OSSL_FUNC_CIPHER_PIPELINE_FINAL,                                              \
    277  1.1  christos           (void (*)(void))fake_pipeline_final },                                        \
    278  1.1  christos         { OSSL_FUNC_CIPHER_GET_PARAMS,                                                  \
    279  1.1  christos           (void (*)(void)) alg##_##kbits##_##lc##_get_params },                         \
    280  1.1  christos         { OSSL_FUNC_CIPHER_GET_CTX_PARAMS,                                              \
    281  1.1  christos           (void (*)(void)) fake_pipeline_aead_get_ctx_params },                         \
    282  1.1  christos         { OSSL_FUNC_CIPHER_SET_CTX_PARAMS,                                              \
    283  1.1  christos           (void (*)(void)) fake_pipeline_aead_set_ctx_params },                         \
    284  1.1  christos         { OSSL_FUNC_CIPHER_GETTABLE_PARAMS,                                             \
    285  1.1  christos           (void (*)(void)) ossl_cipher_generic_gettable_params },                       \
    286  1.1  christos         { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS,                                         \
    287  1.1  christos           (void (*)(void)) fake_pipeline_aead_gettable_ctx_params },                    \
    288  1.1  christos         { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS,                                         \
    289  1.1  christos           (void (*)(void)) fake_pipeline_aead_settable_ctx_params },                    \
    290  1.1  christos         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  christos     {"AES-256-GCM", "provider=fake-pipeline", fake_pipeline_aes256gcm_functions},
    297  1.1  christos     {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  christos                                                  int operation_id,
    302  1.1  christos                                                  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  christos                                        const OSSL_DISPATCH *in,
    321  1.1  christos                                        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  christos                                              fake_pipeline_provider_init))
    335  1.1  christos             || !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