1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved. 3e1051a39Sopenharmony_ci * 4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 5e1051a39Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at 7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html 8e1051a39Sopenharmony_ci */ 9e1051a39Sopenharmony_ci 10e1051a39Sopenharmony_ci/* Dispatch functions for chacha20 cipher */ 11e1051a39Sopenharmony_ci 12e1051a39Sopenharmony_ci#include <openssl/proverr.h> 13e1051a39Sopenharmony_ci#include "cipher_chacha20.h" 14e1051a39Sopenharmony_ci#include "prov/implementations.h" 15e1051a39Sopenharmony_ci#include "prov/providercommon.h" 16e1051a39Sopenharmony_ci 17e1051a39Sopenharmony_ci#define CHACHA20_KEYLEN (CHACHA_KEY_SIZE) 18e1051a39Sopenharmony_ci#define CHACHA20_BLKLEN (1) 19e1051a39Sopenharmony_ci#define CHACHA20_IVLEN (CHACHA_CTR_SIZE) 20e1051a39Sopenharmony_ci#define CHACHA20_FLAGS (PROV_CIPHER_FLAG_CUSTOM_IV) 21e1051a39Sopenharmony_ci 22e1051a39Sopenharmony_cistatic OSSL_FUNC_cipher_newctx_fn chacha20_newctx; 23e1051a39Sopenharmony_cistatic OSSL_FUNC_cipher_freectx_fn chacha20_freectx; 24e1051a39Sopenharmony_cistatic OSSL_FUNC_cipher_get_params_fn chacha20_get_params; 25e1051a39Sopenharmony_cistatic OSSL_FUNC_cipher_get_ctx_params_fn chacha20_get_ctx_params; 26e1051a39Sopenharmony_cistatic OSSL_FUNC_cipher_set_ctx_params_fn chacha20_set_ctx_params; 27e1051a39Sopenharmony_cistatic OSSL_FUNC_cipher_gettable_ctx_params_fn chacha20_gettable_ctx_params; 28e1051a39Sopenharmony_cistatic OSSL_FUNC_cipher_settable_ctx_params_fn chacha20_settable_ctx_params; 29e1051a39Sopenharmony_ci#define chacha20_cipher ossl_cipher_generic_cipher 30e1051a39Sopenharmony_ci#define chacha20_update ossl_cipher_generic_stream_update 31e1051a39Sopenharmony_ci#define chacha20_final ossl_cipher_generic_stream_final 32e1051a39Sopenharmony_ci#define chacha20_gettable_params ossl_cipher_generic_gettable_params 33e1051a39Sopenharmony_ci 34e1051a39Sopenharmony_civoid ossl_chacha20_initctx(PROV_CHACHA20_CTX *ctx) 35e1051a39Sopenharmony_ci{ 36e1051a39Sopenharmony_ci ossl_cipher_generic_initkey(ctx, CHACHA20_KEYLEN * 8, 37e1051a39Sopenharmony_ci CHACHA20_BLKLEN * 8, 38e1051a39Sopenharmony_ci CHACHA20_IVLEN * 8, 39e1051a39Sopenharmony_ci 0, CHACHA20_FLAGS, 40e1051a39Sopenharmony_ci ossl_prov_cipher_hw_chacha20(CHACHA20_KEYLEN * 8), 41e1051a39Sopenharmony_ci NULL); 42e1051a39Sopenharmony_ci} 43e1051a39Sopenharmony_ci 44e1051a39Sopenharmony_cistatic void *chacha20_newctx(void *provctx) 45e1051a39Sopenharmony_ci{ 46e1051a39Sopenharmony_ci PROV_CHACHA20_CTX *ctx; 47e1051a39Sopenharmony_ci 48e1051a39Sopenharmony_ci if (!ossl_prov_is_running()) 49e1051a39Sopenharmony_ci return NULL; 50e1051a39Sopenharmony_ci 51e1051a39Sopenharmony_ci ctx = OPENSSL_zalloc(sizeof(*ctx)); 52e1051a39Sopenharmony_ci if (ctx != NULL) 53e1051a39Sopenharmony_ci ossl_chacha20_initctx(ctx); 54e1051a39Sopenharmony_ci return ctx; 55e1051a39Sopenharmony_ci} 56e1051a39Sopenharmony_ci 57e1051a39Sopenharmony_cistatic void chacha20_freectx(void *vctx) 58e1051a39Sopenharmony_ci{ 59e1051a39Sopenharmony_ci PROV_CHACHA20_CTX *ctx = (PROV_CHACHA20_CTX *)vctx; 60e1051a39Sopenharmony_ci 61e1051a39Sopenharmony_ci if (ctx != NULL) { 62e1051a39Sopenharmony_ci ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx); 63e1051a39Sopenharmony_ci OPENSSL_clear_free(ctx, sizeof(*ctx)); 64e1051a39Sopenharmony_ci } 65e1051a39Sopenharmony_ci} 66e1051a39Sopenharmony_ci 67e1051a39Sopenharmony_cistatic int chacha20_get_params(OSSL_PARAM params[]) 68e1051a39Sopenharmony_ci{ 69e1051a39Sopenharmony_ci return ossl_cipher_generic_get_params(params, 0, CHACHA20_FLAGS, 70e1051a39Sopenharmony_ci CHACHA20_KEYLEN * 8, 71e1051a39Sopenharmony_ci CHACHA20_BLKLEN * 8, 72e1051a39Sopenharmony_ci CHACHA20_IVLEN * 8); 73e1051a39Sopenharmony_ci} 74e1051a39Sopenharmony_ci 75e1051a39Sopenharmony_cistatic int chacha20_get_ctx_params(void *vctx, OSSL_PARAM params[]) 76e1051a39Sopenharmony_ci{ 77e1051a39Sopenharmony_ci OSSL_PARAM *p; 78e1051a39Sopenharmony_ci 79e1051a39Sopenharmony_ci p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN); 80e1051a39Sopenharmony_ci if (p != NULL && !OSSL_PARAM_set_size_t(p, CHACHA20_IVLEN)) { 81e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); 82e1051a39Sopenharmony_ci return 0; 83e1051a39Sopenharmony_ci } 84e1051a39Sopenharmony_ci p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN); 85e1051a39Sopenharmony_ci if (p != NULL && !OSSL_PARAM_set_size_t(p, CHACHA20_KEYLEN)) { 86e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); 87e1051a39Sopenharmony_ci return 0; 88e1051a39Sopenharmony_ci } 89e1051a39Sopenharmony_ci 90e1051a39Sopenharmony_ci return 1; 91e1051a39Sopenharmony_ci} 92e1051a39Sopenharmony_ci 93e1051a39Sopenharmony_cistatic const OSSL_PARAM chacha20_known_gettable_ctx_params[] = { 94e1051a39Sopenharmony_ci OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), 95e1051a39Sopenharmony_ci OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL), 96e1051a39Sopenharmony_ci OSSL_PARAM_END 97e1051a39Sopenharmony_ci}; 98e1051a39Sopenharmony_ciconst OSSL_PARAM *chacha20_gettable_ctx_params(ossl_unused void *cctx, 99e1051a39Sopenharmony_ci ossl_unused void *provctx) 100e1051a39Sopenharmony_ci{ 101e1051a39Sopenharmony_ci return chacha20_known_gettable_ctx_params; 102e1051a39Sopenharmony_ci} 103e1051a39Sopenharmony_ci 104e1051a39Sopenharmony_cistatic int chacha20_set_ctx_params(void *vctx, const OSSL_PARAM params[]) 105e1051a39Sopenharmony_ci{ 106e1051a39Sopenharmony_ci const OSSL_PARAM *p; 107e1051a39Sopenharmony_ci size_t len; 108e1051a39Sopenharmony_ci 109e1051a39Sopenharmony_ci if (params == NULL) 110e1051a39Sopenharmony_ci return 1; 111e1051a39Sopenharmony_ci 112e1051a39Sopenharmony_ci p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN); 113e1051a39Sopenharmony_ci if (p != NULL) { 114e1051a39Sopenharmony_ci if (!OSSL_PARAM_get_size_t(p, &len)) { 115e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); 116e1051a39Sopenharmony_ci return 0; 117e1051a39Sopenharmony_ci } 118e1051a39Sopenharmony_ci if (len != CHACHA20_KEYLEN) { 119e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); 120e1051a39Sopenharmony_ci return 0; 121e1051a39Sopenharmony_ci } 122e1051a39Sopenharmony_ci } 123e1051a39Sopenharmony_ci p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_IVLEN); 124e1051a39Sopenharmony_ci if (p != NULL) { 125e1051a39Sopenharmony_ci if (!OSSL_PARAM_get_size_t(p, &len)) { 126e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); 127e1051a39Sopenharmony_ci return 0; 128e1051a39Sopenharmony_ci } 129e1051a39Sopenharmony_ci if (len != CHACHA20_IVLEN) { 130e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH); 131e1051a39Sopenharmony_ci return 0; 132e1051a39Sopenharmony_ci } 133e1051a39Sopenharmony_ci } 134e1051a39Sopenharmony_ci return 1; 135e1051a39Sopenharmony_ci} 136e1051a39Sopenharmony_ci 137e1051a39Sopenharmony_cistatic const OSSL_PARAM chacha20_known_settable_ctx_params[] = { 138e1051a39Sopenharmony_ci OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), 139e1051a39Sopenharmony_ci OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL), 140e1051a39Sopenharmony_ci OSSL_PARAM_END 141e1051a39Sopenharmony_ci}; 142e1051a39Sopenharmony_ciconst OSSL_PARAM *chacha20_settable_ctx_params(ossl_unused void *cctx, 143e1051a39Sopenharmony_ci ossl_unused void *provctx) 144e1051a39Sopenharmony_ci{ 145e1051a39Sopenharmony_ci return chacha20_known_settable_ctx_params; 146e1051a39Sopenharmony_ci} 147e1051a39Sopenharmony_ci 148e1051a39Sopenharmony_ciint ossl_chacha20_einit(void *vctx, const unsigned char *key, size_t keylen, 149e1051a39Sopenharmony_ci const unsigned char *iv, size_t ivlen, 150e1051a39Sopenharmony_ci const OSSL_PARAM params[]) 151e1051a39Sopenharmony_ci{ 152e1051a39Sopenharmony_ci int ret; 153e1051a39Sopenharmony_ci 154e1051a39Sopenharmony_ci /* The generic function checks for ossl_prov_is_running() */ 155e1051a39Sopenharmony_ci ret = ossl_cipher_generic_einit(vctx, key, keylen, iv, ivlen, NULL); 156e1051a39Sopenharmony_ci if (ret && iv != NULL) { 157e1051a39Sopenharmony_ci PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; 158e1051a39Sopenharmony_ci PROV_CIPHER_HW_CHACHA20 *hw = (PROV_CIPHER_HW_CHACHA20 *)ctx->hw; 159e1051a39Sopenharmony_ci 160e1051a39Sopenharmony_ci hw->initiv(ctx); 161e1051a39Sopenharmony_ci } 162e1051a39Sopenharmony_ci if (ret && !chacha20_set_ctx_params(vctx, params)) 163e1051a39Sopenharmony_ci ret = 0; 164e1051a39Sopenharmony_ci return ret; 165e1051a39Sopenharmony_ci} 166e1051a39Sopenharmony_ci 167e1051a39Sopenharmony_ciint ossl_chacha20_dinit(void *vctx, const unsigned char *key, size_t keylen, 168e1051a39Sopenharmony_ci const unsigned char *iv, size_t ivlen, 169e1051a39Sopenharmony_ci const OSSL_PARAM params[]) 170e1051a39Sopenharmony_ci{ 171e1051a39Sopenharmony_ci int ret; 172e1051a39Sopenharmony_ci 173e1051a39Sopenharmony_ci /* The generic function checks for ossl_prov_is_running() */ 174e1051a39Sopenharmony_ci ret = ossl_cipher_generic_dinit(vctx, key, keylen, iv, ivlen, NULL); 175e1051a39Sopenharmony_ci if (ret && iv != NULL) { 176e1051a39Sopenharmony_ci PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; 177e1051a39Sopenharmony_ci PROV_CIPHER_HW_CHACHA20 *hw = (PROV_CIPHER_HW_CHACHA20 *)ctx->hw; 178e1051a39Sopenharmony_ci 179e1051a39Sopenharmony_ci hw->initiv(ctx); 180e1051a39Sopenharmony_ci } 181e1051a39Sopenharmony_ci if (ret && !chacha20_set_ctx_params(vctx, params)) 182e1051a39Sopenharmony_ci ret = 0; 183e1051a39Sopenharmony_ci return ret; 184e1051a39Sopenharmony_ci} 185e1051a39Sopenharmony_ci 186e1051a39Sopenharmony_ci/* ossl_chacha20_functions */ 187e1051a39Sopenharmony_ciconst OSSL_DISPATCH ossl_chacha20_functions[] = { 188e1051a39Sopenharmony_ci { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))chacha20_newctx }, 189e1051a39Sopenharmony_ci { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))chacha20_freectx }, 190e1051a39Sopenharmony_ci { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))ossl_chacha20_einit }, 191e1051a39Sopenharmony_ci { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))ossl_chacha20_dinit }, 192e1051a39Sopenharmony_ci { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))chacha20_update }, 193e1051a39Sopenharmony_ci { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))chacha20_final }, 194e1051a39Sopenharmony_ci { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))chacha20_cipher}, 195e1051a39Sopenharmony_ci { OSSL_FUNC_CIPHER_GET_PARAMS, (void (*)(void))chacha20_get_params }, 196e1051a39Sopenharmony_ci { OSSL_FUNC_CIPHER_GETTABLE_PARAMS,(void (*)(void))chacha20_gettable_params }, 197e1051a39Sopenharmony_ci { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, (void (*)(void))chacha20_get_ctx_params }, 198e1051a39Sopenharmony_ci { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, 199e1051a39Sopenharmony_ci (void (*)(void))chacha20_gettable_ctx_params }, 200e1051a39Sopenharmony_ci { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, (void (*)(void))chacha20_set_ctx_params }, 201e1051a39Sopenharmony_ci { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, 202e1051a39Sopenharmony_ci (void (*)(void))chacha20_settable_ctx_params }, 203e1051a39Sopenharmony_ci { 0, NULL } 204e1051a39Sopenharmony_ci}; 205e1051a39Sopenharmony_ci 206