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