1 /* 2 * Copyright 2019-2023 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 chacha20 cipher */ 11 12 #include <openssl/proverr.h> 13 #include "cipher_chacha20.h" 14 #include "prov/implementations.h" 15 #include "prov/providercommon.h" 16 17 #define CHACHA20_KEYLEN (CHACHA_KEY_SIZE) 18 #define CHACHA20_BLKLEN (1) 19 #define CHACHA20_IVLEN (CHACHA_CTR_SIZE) 20 #define CHACHA20_FLAGS (PROV_CIPHER_FLAG_CUSTOM_IV) 21 22 static OSSL_FUNC_cipher_newctx_fn chacha20_newctx; 23 static OSSL_FUNC_cipher_freectx_fn chacha20_freectx; 24 static OSSL_FUNC_cipher_dupctx_fn chacha20_dupctx; 25 static OSSL_FUNC_cipher_get_params_fn chacha20_get_params; 26 static OSSL_FUNC_cipher_get_ctx_params_fn chacha20_get_ctx_params; 27 static OSSL_FUNC_cipher_set_ctx_params_fn chacha20_set_ctx_params; 28 static OSSL_FUNC_cipher_gettable_ctx_params_fn chacha20_gettable_ctx_params; 29 static OSSL_FUNC_cipher_settable_ctx_params_fn chacha20_settable_ctx_params; 30 #define chacha20_cipher ossl_cipher_generic_cipher 31 #define chacha20_update ossl_cipher_generic_stream_update 32 #define chacha20_final ossl_cipher_generic_stream_final 33 #define chacha20_gettable_params ossl_cipher_generic_gettable_params 34 35 void ossl_chacha20_initctx(PROV_CHACHA20_CTX *ctx) 36 { 37 ossl_cipher_generic_initkey(ctx, CHACHA20_KEYLEN * 8, 38 CHACHA20_BLKLEN * 8, 39 CHACHA20_IVLEN * 8, 40 0, CHACHA20_FLAGS, 41 ossl_prov_cipher_hw_chacha20(CHACHA20_KEYLEN * 8), 42 NULL); 43 } 44 45 static void *chacha20_newctx(void *provctx) 46 { 47 PROV_CHACHA20_CTX *ctx; 48 49 if (!ossl_prov_is_running()) 50 return NULL; 51 52 ctx = OPENSSL_zalloc(sizeof(*ctx)); 53 if (ctx != NULL) 54 ossl_chacha20_initctx(ctx); 55 return ctx; 56 } 57 58 static void chacha20_freectx(void *vctx) 59 { 60 PROV_CHACHA20_CTX *ctx = (PROV_CHACHA20_CTX *)vctx; 61 62 if (ctx != NULL) { 63 ossl_cipher_generic_reset_ctx((PROV_CIPHER_CTX *)vctx); 64 OPENSSL_clear_free(ctx, sizeof(*ctx)); 65 } 66 } 67 68 static void *chacha20_dupctx(void *vctx) 69 { 70 PROV_CHACHA20_CTX *ctx = (PROV_CHACHA20_CTX *)vctx; 71 PROV_CHACHA20_CTX *dupctx = NULL; 72 73 if (ctx != NULL) { 74 dupctx = OPENSSL_memdup(ctx, sizeof(*dupctx)); 75 if (dupctx != NULL && dupctx->base.tlsmac != NULL && dupctx->base.alloced) { 76 dupctx->base.tlsmac = OPENSSL_memdup(dupctx->base.tlsmac, 77 dupctx->base.tlsmacsize); 78 if (dupctx->base.tlsmac == NULL) { 79 OPENSSL_free(dupctx); 80 dupctx = NULL; 81 } 82 } 83 } 84 return dupctx; 85 } 86 87 static int chacha20_get_params(OSSL_PARAM params[]) 88 { 89 return ossl_cipher_generic_get_params(params, 0, CHACHA20_FLAGS, 90 CHACHA20_KEYLEN * 8, 91 CHACHA20_BLKLEN * 8, 92 CHACHA20_IVLEN * 8); 93 } 94 95 static int chacha20_get_ctx_params(void *vctx, OSSL_PARAM params[]) 96 { 97 OSSL_PARAM *p; 98 99 p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN); 100 if (p != NULL && !OSSL_PARAM_set_size_t(p, CHACHA20_IVLEN)) { 101 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); 102 return 0; 103 } 104 p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN); 105 if (p != NULL && !OSSL_PARAM_set_size_t(p, CHACHA20_KEYLEN)) { 106 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); 107 return 0; 108 } 109 110 return 1; 111 } 112 113 static const OSSL_PARAM chacha20_known_gettable_ctx_params[] = { 114 OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), 115 OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL), 116 OSSL_PARAM_END 117 }; 118 const OSSL_PARAM *chacha20_gettable_ctx_params(ossl_unused void *cctx, 119 ossl_unused void *provctx) 120 { 121 return chacha20_known_gettable_ctx_params; 122 } 123 124 static int chacha20_set_ctx_params(void *vctx, const OSSL_PARAM params[]) 125 { 126 const OSSL_PARAM *p; 127 size_t len; 128 129 if (params == NULL) 130 return 1; 131 132 p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN); 133 if (p != NULL) { 134 if (!OSSL_PARAM_get_size_t(p, &len)) { 135 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); 136 return 0; 137 } 138 if (len != CHACHA20_KEYLEN) { 139 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); 140 return 0; 141 } 142 } 143 p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_IVLEN); 144 if (p != NULL) { 145 if (!OSSL_PARAM_get_size_t(p, &len)) { 146 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); 147 return 0; 148 } 149 if (len != CHACHA20_IVLEN) { 150 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH); 151 return 0; 152 } 153 } 154 return 1; 155 } 156 157 static const OSSL_PARAM chacha20_known_settable_ctx_params[] = { 158 OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_KEYLEN, NULL), 159 OSSL_PARAM_size_t(OSSL_CIPHER_PARAM_IVLEN, NULL), 160 OSSL_PARAM_END 161 }; 162 const OSSL_PARAM *chacha20_settable_ctx_params(ossl_unused void *cctx, 163 ossl_unused void *provctx) 164 { 165 return chacha20_known_settable_ctx_params; 166 } 167 168 int ossl_chacha20_einit(void *vctx, const unsigned char *key, size_t keylen, 169 const unsigned char *iv, size_t ivlen, 170 const OSSL_PARAM params[]) 171 { 172 int ret; 173 174 /* The generic function checks for ossl_prov_is_running() */ 175 ret = ossl_cipher_generic_einit(vctx, key, keylen, iv, ivlen, NULL); 176 if (ret && iv != NULL) { 177 PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; 178 PROV_CIPHER_HW_CHACHA20 *hw = (PROV_CIPHER_HW_CHACHA20 *)ctx->hw; 179 180 hw->initiv(ctx); 181 } 182 if (ret && !chacha20_set_ctx_params(vctx, params)) 183 ret = 0; 184 return ret; 185 } 186 187 int ossl_chacha20_dinit(void *vctx, const unsigned char *key, size_t keylen, 188 const unsigned char *iv, size_t ivlen, 189 const OSSL_PARAM params[]) 190 { 191 int ret; 192 193 /* The generic function checks for ossl_prov_is_running() */ 194 ret = ossl_cipher_generic_dinit(vctx, key, keylen, iv, ivlen, NULL); 195 if (ret && iv != NULL) { 196 PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; 197 PROV_CIPHER_HW_CHACHA20 *hw = (PROV_CIPHER_HW_CHACHA20 *)ctx->hw; 198 199 hw->initiv(ctx); 200 } 201 if (ret && !chacha20_set_ctx_params(vctx, params)) 202 ret = 0; 203 return ret; 204 } 205 206 /* ossl_chacha20_functions */ 207 const OSSL_DISPATCH ossl_chacha20_functions[] = { 208 { OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))chacha20_newctx }, 209 { OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))chacha20_freectx }, 210 { OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))chacha20_dupctx }, 211 { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))ossl_chacha20_einit }, 212 { OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))ossl_chacha20_dinit }, 213 { OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))chacha20_update }, 214 { OSSL_FUNC_CIPHER_FINAL, (void (*)(void))chacha20_final }, 215 { OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))chacha20_cipher}, 216 { OSSL_FUNC_CIPHER_GET_PARAMS, (void (*)(void))chacha20_get_params }, 217 { OSSL_FUNC_CIPHER_GETTABLE_PARAMS,(void (*)(void))chacha20_gettable_params }, 218 { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, (void (*)(void))chacha20_get_ctx_params }, 219 { OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS, 220 (void (*)(void))chacha20_gettable_ctx_params }, 221 { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, (void (*)(void))chacha20_set_ctx_params }, 222 { OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS, 223 (void (*)(void))chacha20_settable_ctx_params }, 224 { 0, NULL } 225 }; 226 227