xref: /netbsd-src/crypto/external/bsd/openssl/dist/providers/implementations/ciphers/cipher_chacha20.c (revision 4778aede4608a995eaeedca856a7a71a2fa5c675)
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