Home | History | Annotate | Line # | Download | only in ciphers
      1 /*
      2  * Copyright 2019-2025 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 /* Dispatch functions for AES SIV mode */
     11 
     12 /*
     13  * This file uses the low level AES functions (which are deprecated for
     14  * non-internal use) in order to implement provider AES ciphers.
     15  */
     16 #include "internal/deprecated.h"
     17 
     18 #include <openssl/proverr.h>
     19 #include "prov/implementations.h"
     20 #include "prov/providercommon.h"
     21 #include "prov/ciphercommon_aead.h"
     22 #include "prov/provider_ctx.h"
     23 #include "cipher_aes_gcm_siv.h"
     24 
     25 static int ossl_aes_gcm_siv_set_ctx_params(void *vctx, const OSSL_PARAM params[]);
     26 
     27 static void *ossl_aes_gcm_siv_newctx(void *provctx, size_t keybits)
     28 {
     29     PROV_AES_GCM_SIV_CTX *ctx;
     30 
     31     if (!ossl_prov_is_running())
     32         return NULL;
     33 
     34     ctx = OPENSSL_zalloc(sizeof(*ctx));
     35     if (ctx != NULL) {
     36         ctx->key_len = keybits / 8;
     37         ctx->hw = ossl_prov_cipher_hw_aes_gcm_siv(keybits);
     38         ctx->libctx = PROV_LIBCTX_OF(provctx);
     39         ctx->provctx = provctx;
     40     }
     41     return ctx;
     42 }
     43 
     44 static void ossl_aes_gcm_siv_freectx(void *vctx)
     45 {
     46     PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx;
     47 
     48     if (ctx == NULL)
     49         return;
     50 
     51     OPENSSL_clear_free(ctx->aad, ctx->aad_len);
     52     ctx->hw->clean_ctx(ctx);
     53     OPENSSL_clear_free(ctx, sizeof(*ctx));
     54 }
     55 
     56 static void *ossl_aes_gcm_siv_dupctx(void *vctx)
     57 {
     58     PROV_AES_GCM_SIV_CTX *in = (PROV_AES_GCM_SIV_CTX *)vctx;
     59     PROV_AES_GCM_SIV_CTX *ret;
     60 
     61     if (!ossl_prov_is_running())
     62         return NULL;
     63 
     64     if (in->hw == NULL)
     65         return NULL;
     66 
     67     ret = OPENSSL_memdup(in, sizeof(*in));
     68     if (ret == NULL)
     69         return NULL;
     70     /* NULL-out these things we create later */
     71     ret->aad = NULL;
     72     ret->ecb_ctx = NULL;
     73 
     74     if (in->aad != NULL) {
     75         if ((ret->aad = OPENSSL_memdup(in->aad, UP16(ret->aad_len))) == NULL)
     76             goto err;
     77     }
     78 
     79     if (!in->hw->dup_ctx(ret, in))
     80         goto err;
     81 
     82     return ret;
     83 err:
     84     if (ret != NULL) {
     85         OPENSSL_clear_free(ret->aad, ret->aad_len);
     86         OPENSSL_free(ret);
     87     }
     88     return NULL;
     89 }
     90 
     91 static int ossl_aes_gcm_siv_init(void *vctx, const unsigned char *key, size_t keylen,
     92     const unsigned char *iv, size_t ivlen,
     93     const OSSL_PARAM params[], int enc)
     94 {
     95     PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx;
     96 
     97     if (!ossl_prov_is_running())
     98         return 0;
     99 
    100     ctx->enc = enc;
    101 
    102     if (key != NULL) {
    103         if (keylen != ctx->key_len) {
    104             ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
    105             return 0;
    106         }
    107         memcpy(ctx->key_gen_key, key, ctx->key_len);
    108     }
    109     if (iv != NULL) {
    110         if (ivlen != sizeof(ctx->nonce)) {
    111             ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
    112             return 0;
    113         }
    114         memcpy(ctx->nonce, iv, sizeof(ctx->nonce));
    115     }
    116 
    117     if (!ctx->hw->initkey(ctx))
    118         return 0;
    119 
    120     return ossl_aes_gcm_siv_set_ctx_params(ctx, params);
    121 }
    122 
    123 static int ossl_aes_gcm_siv_einit(void *vctx, const unsigned char *key, size_t keylen,
    124     const unsigned char *iv, size_t ivlen,
    125     const OSSL_PARAM params[])
    126 {
    127     return ossl_aes_gcm_siv_init(vctx, key, keylen, iv, ivlen, params, 1);
    128 }
    129 
    130 static int ossl_aes_gcm_siv_dinit(void *vctx, const unsigned char *key, size_t keylen,
    131     const unsigned char *iv, size_t ivlen,
    132     const OSSL_PARAM params[])
    133 {
    134     return ossl_aes_gcm_siv_init(vctx, key, keylen, iv, ivlen, params, 0);
    135 }
    136 
    137 #define ossl_aes_gcm_siv_stream_update ossl_aes_gcm_siv_cipher
    138 static int ossl_aes_gcm_siv_cipher(void *vctx, unsigned char *out, size_t *outl,
    139     size_t outsize, const unsigned char *in, size_t inl)
    140 {
    141     PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx;
    142     int error = 0;
    143 
    144     if (!ossl_prov_is_running())
    145         return 0;
    146 
    147     if (outsize < inl) {
    148         ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
    149         return 0;
    150     }
    151 
    152     error |= !ctx->hw->cipher(ctx, out, in, inl);
    153 
    154     if (outl != NULL && !error)
    155         *outl = inl;
    156     return !error;
    157 }
    158 
    159 static int ossl_aes_gcm_siv_stream_final(void *vctx, unsigned char *out, size_t *outl,
    160     size_t outsize)
    161 {
    162     PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx;
    163     int error = 0;
    164 
    165     if (!ossl_prov_is_running())
    166         return 0;
    167 
    168     error |= !ctx->hw->cipher(vctx, out, NULL, 0);
    169 
    170     if (outl != NULL && !error)
    171         *outl = 0;
    172     return !error;
    173 }
    174 
    175 static int ossl_aes_gcm_siv_get_ctx_params(void *vctx, OSSL_PARAM params[])
    176 {
    177     PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx;
    178     OSSL_PARAM *p;
    179 
    180     p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG);
    181     if (p != NULL && p->data_type == OSSL_PARAM_OCTET_STRING) {
    182         if (!ctx->enc || !ctx->generated_tag
    183             || p->data_size != sizeof(ctx->tag)
    184             || !OSSL_PARAM_set_octet_string(p, ctx->tag, sizeof(ctx->tag))) {
    185             ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
    186             return 0;
    187         }
    188     }
    189     p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAGLEN);
    190     if (p != NULL && !OSSL_PARAM_set_size_t(p, sizeof(ctx->tag))) {
    191         ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
    192         return 0;
    193     }
    194     p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
    195     if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->key_len)) {
    196         ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
    197         return 0;
    198     }
    199     return 1;
    200 }
    201 
    202 static const OSSL_PARAM aes_gcm_siv_known_gettable_ctx_params[] = {
    203     OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
    204     OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_AEAD_TAGLEN, NULL),
    205     OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
    206     OSSL_PARAM_END
    207 };
    208 
    209 static const OSSL_PARAM *ossl_aes_gcm_siv_gettable_ctx_params(ossl_unused void *cctx,
    210     ossl_unused void *provctx)
    211 {
    212     return aes_gcm_siv_known_gettable_ctx_params;
    213 }
    214 
    215 static int ossl_aes_gcm_siv_set_ctx_params(void *vctx, const OSSL_PARAM params[])
    216 {
    217     PROV_AES_GCM_SIV_CTX *ctx = (PROV_AES_GCM_SIV_CTX *)vctx;
    218     const OSSL_PARAM *p;
    219     unsigned int speed = 0;
    220 
    221     if (ossl_param_is_empty(params))
    222         return 1;
    223 
    224     p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG);
    225     if (p != NULL) {
    226         if (p->data_type != OSSL_PARAM_OCTET_STRING
    227             || p->data_size != sizeof(ctx->user_tag)) {
    228             ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
    229             return 0;
    230         }
    231         if (!ctx->enc) {
    232             memcpy(ctx->user_tag, p->data, sizeof(ctx->tag));
    233             ctx->have_user_tag = 1;
    234         }
    235     }
    236     p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_SPEED);
    237     if (p != NULL) {
    238         if (!OSSL_PARAM_get_uint(p, &speed)) {
    239             ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
    240             return 0;
    241         }
    242         ctx->speed = !!speed;
    243     }
    244     p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN);
    245     if (p != NULL) {
    246         size_t key_len;
    247 
    248         if (!OSSL_PARAM_get_size_t(p, &key_len)) {
    249             ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
    250             return 0;
    251         }
    252         /* The key length can not be modified */
    253         if (key_len != ctx->key_len) {
    254             ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
    255             return 0;
    256         }
    257     }
    258     return 1;
    259 }
    260 
    261 static const OSSL_PARAM aes_gcm_siv_known_settable_ctx_params[] = {
    262     OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL),
    263     OSSL_PARAM_uint(OSSL_CIPHER_PARAM_SPEED, NULL),
    264     OSSL_PARAM_octet_string(OSSL_CIPHER_PARAM_AEAD_TAG, NULL, 0),
    265     OSSL_PARAM_END
    266 };
    267 static const OSSL_PARAM *ossl_aes_gcm_siv_settable_ctx_params(ossl_unused void *cctx,
    268     ossl_unused void *provctx)
    269 {
    270     return aes_gcm_siv_known_settable_ctx_params;
    271 }
    272 
    273 #define IMPLEMENT_cipher(alg, lc, UCMODE, flags, kbits, blkbits, ivbits)                                   \
    274     static OSSL_FUNC_cipher_newctx_fn ossl_##alg##kbits##_##lc##_newctx;                                   \
    275     static OSSL_FUNC_cipher_freectx_fn ossl_##alg##_##lc##_freectx;                                        \
    276     static OSSL_FUNC_cipher_dupctx_fn ossl_##alg##_##lc##_dupctx;                                          \
    277     static OSSL_FUNC_cipher_encrypt_init_fn ossl_##alg##_##lc##_einit;                                     \
    278     static OSSL_FUNC_cipher_decrypt_init_fn ossl_##alg##_##lc##_dinit;                                     \
    279     static OSSL_FUNC_cipher_update_fn ossl_##alg##_##lc##_stream_update;                                   \
    280     static OSSL_FUNC_cipher_final_fn ossl_##alg##_##lc##_stream_final;                                     \
    281     static OSSL_FUNC_cipher_cipher_fn ossl_##alg##_##lc##_cipher;                                          \
    282     static OSSL_FUNC_cipher_get_params_fn ossl_##alg##_##kbits##_##lc##_get_params;                        \
    283     static OSSL_FUNC_cipher_get_ctx_params_fn ossl_##alg##_##lc##_get_ctx_params;                          \
    284     static OSSL_FUNC_cipher_gettable_ctx_params_fn ossl_##alg##_##lc##_gettable_ctx_params;                \
    285     static OSSL_FUNC_cipher_set_ctx_params_fn ossl_##alg##_##lc##_set_ctx_params;                          \
    286     static OSSL_FUNC_cipher_settable_ctx_params_fn ossl_##alg##_##lc##_settable_ctx_params;                \
    287     static int ossl_##alg##_##kbits##_##lc##_get_params(OSSL_PARAM params[])                               \
    288     {                                                                                                      \
    289         return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE,                            \
    290             flags, kbits, blkbits, ivbits);                                                                \
    291     }                                                                                                      \
    292     static void *ossl_##alg##kbits##_##lc##_newctx(void *provctx)                                          \
    293     {                                                                                                      \
    294         return ossl_##alg##_##lc##_newctx(provctx, kbits);                                                 \
    295     }                                                                                                      \
    296     const OSSL_DISPATCH ossl_##alg##kbits##lc##_functions[] = {                                            \
    297         { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))ossl_##alg##kbits##_##lc##_newctx },                    \
    298         { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))ossl_##alg##_##lc##_freectx },                         \
    299         { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))ossl_##alg##_##lc##_dupctx },                           \
    300         { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))ossl_##alg##_##lc##_einit },                      \
    301         { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))ossl_##alg##_##lc##_dinit },                      \
    302         { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))ossl_##alg##_##lc##_stream_update },                    \
    303         { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))ossl_##alg##_##lc##_stream_final },                      \
    304         { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))ossl_##alg##_##lc##_cipher },                           \
    305         { OSSL_FUNC_CIPHER_GET_PARAMS, (void (*)(void))ossl_##alg##_##kbits##_##lc##_get_params },         \
    306         { OSSL_FUNC_CIPHER_GETTABLE_PARAMS, (void (*)(void))ossl_cipher_generic_gettable_params },         \
    307         { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, (void (*)(void))ossl_##alg##_##lc##_get_ctx_params },           \
    308         { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, (void (*)(void))ossl_##alg##_##lc##_gettable_ctx_params }, \
    309         { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, (void (*)(void))ossl_##alg##_##lc##_set_ctx_params },           \
    310         { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, (void (*)(void))ossl_##alg##_##lc##_settable_ctx_params }, \
    311         OSSL_DISPATCH_END                                                                                  \
    312     }
    313 
    314 IMPLEMENT_cipher(aes, gcm_siv, GCM_SIV, AEAD_FLAGS, 128, 8, 96);
    315 IMPLEMENT_cipher(aes, gcm_siv, GCM_SIV, AEAD_FLAGS, 192, 8, 96);
    316 IMPLEMENT_cipher(aes, gcm_siv, GCM_SIV, AEAD_FLAGS, 256, 8, 96);
    317