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