]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_prov_cipher.c
Making a gost provider - Add the ciphers
[openssl-gost/engine.git] / gost_prov_cipher.c
1 /**********************************************************************
2  *             gost_prov_crypt.c - Initialize all ciphers             *
3  *                                                                    *
4  *      Copyright (c) 2021 Richard Levitte <richard@levitte.org>      *
5  *     This file is distributed under the same license as OpenSSL     *
6  *                                                                    *
7  *         OpenSSL provider interface to GOST cipher functions        *
8  *                Requires OpenSSL 3.0 for compilation                *
9  **********************************************************************/
10
11 #include <openssl/core.h>
12 #include <openssl/core_dispatch.h>
13 #include "gost_prov.h"
14 #include "gost_lcl.h"
15
16 /*
17  * Forward declarations of all generic OSSL_DISPATCH functions, to make sure
18  * they are correctly defined further down.  For the algorithm specific ones
19  * MAKE_FUNCTIONS() does it for us.
20  */
21 static OSSL_FUNC_cipher_dupctx_fn cipher_dupctx;
22 static OSSL_FUNC_cipher_freectx_fn cipher_freectx;
23 static OSSL_FUNC_cipher_get_ctx_params_fn cipher_get_ctx_params;
24 static OSSL_FUNC_cipher_set_ctx_params_fn cipher_set_ctx_params;
25 static OSSL_FUNC_cipher_encrypt_init_fn cipher_encrypt_init;
26 static OSSL_FUNC_cipher_decrypt_init_fn cipher_decrypt_init;
27 static OSSL_FUNC_cipher_update_fn cipher_update;
28 static OSSL_FUNC_cipher_final_fn cipher_final;
29
30 struct gost_prov_crypt_ctx_st {
31     /* Provider context */
32     PROV_CTX *provctx;
33     /* OSSL_PARAM descriptors */
34     const OSSL_PARAM *known_params;
35     /* GOST_cipher descriptor */
36     GOST_cipher *descriptor;
37
38     /*
39      * Since existing functionality is designed for ENGINEs, the functions
40      * in this file are accomodated and are simply wrappers that use a local
41      * EVP_CIPHER and EVP_CIPHER_CTX.
42      * Future development should take a more direct approach and have the
43      * appropriate cipher functions and cipher data directly in this context.
44      */
45
46     /* The EVP_CIPHER created from |descriptor| */
47     EVP_CIPHER *cipher;
48     /* The context for the EVP_CIPHER functions */
49     EVP_CIPHER_CTX *cctx;
50 };
51 typedef struct gost_prov_crypt_ctx_st GOST_CTX;
52
53 static void cipher_freectx(void *vgctx)
54 {
55     GOST_CTX *gctx = vgctx;
56
57     /*
58      * We don't free gctx->cipher here.
59      * That will be done by the provider teardown, via
60      * GOST_prov_deinit_ciphers() (defined at the bottom of this file).
61      */
62     EVP_CIPHER_CTX_free(gctx->cctx);
63     OPENSSL_free(gctx);
64 }
65
66 static GOST_CTX *cipher_newctx(void *provctx, GOST_cipher *descriptor,
67                                 const OSSL_PARAM *known_params)
68 {
69     GOST_CTX *gctx = NULL;
70
71     if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
72         gctx->provctx = provctx;
73         gctx->known_params = known_params;
74         gctx->descriptor = descriptor;
75         gctx->cipher = GOST_init_cipher(descriptor);
76         gctx->cctx = EVP_CIPHER_CTX_new();
77
78         if (gctx->cipher == NULL || gctx->cctx == NULL) {
79             cipher_freectx(gctx);
80             gctx = NULL;
81         }
82     }
83     return gctx;
84 }
85
86 static void *cipher_dupctx(void *vsrc)
87 {
88     GOST_CTX *src = vsrc;
89     GOST_CTX *dst =
90         cipher_newctx(src->provctx, src->descriptor, src->known_params);
91
92     if (dst != NULL)
93         EVP_CIPHER_CTX_copy(dst->cctx, src->cctx);
94     return dst;
95 }
96
97 static int cipher_get_params(EVP_CIPHER *c, OSSL_PARAM params[])
98 {
99     OSSL_PARAM *p;
100
101     if (((p = OSSL_PARAM_locate(params, "blocksize")) != NULL
102          && !OSSL_PARAM_set_size_t(p, EVP_CIPHER_block_size(c)))
103         || ((p = OSSL_PARAM_locate(params, "ivlen")) != NULL
104             && !OSSL_PARAM_set_size_t(p, EVP_CIPHER_iv_length(c)))
105         || ((p = OSSL_PARAM_locate(params, "keylen")) != NULL
106             && !OSSL_PARAM_set_size_t(p, EVP_CIPHER_key_length(c)))
107         || ((p = OSSL_PARAM_locate(params, "mode")) != NULL
108             && !OSSL_PARAM_set_size_t(p, EVP_CIPHER_flags(c))))
109         return 0;
110     return 1;
111 }
112
113 static int cipher_get_ctx_params(void *vgctx, OSSL_PARAM params[])
114 {
115     GOST_CTX *gctx = vgctx;
116     OSSL_PARAM *p;
117
118     if (!cipher_get_params(gctx->cipher, params))
119         return 0;
120     if ((p = OSSL_PARAM_locate(params, "alg_id_param")) != NULL) {
121         ASN1_TYPE *algidparam = NULL;
122         unsigned char *der = NULL;
123         int derlen = 0;
124         int ret;
125
126         ret = (algidparam = ASN1_TYPE_new()) != NULL
127             && EVP_CIPHER_param_to_asn1(gctx->cctx, algidparam) > 0
128             && (derlen = i2d_ASN1_TYPE(algidparam, &der)) >= 0
129             && OSSL_PARAM_set_octet_string(p, &der, (size_t)derlen);
130
131         OPENSSL_free(der);
132         ASN1_TYPE_free(algidparam);
133         return ret;
134     }
135     if ((p = OSSL_PARAM_locate(params, "updated-iv")) != NULL) {
136         const void *iv = EVP_CIPHER_CTX_iv(gctx->cctx);
137         size_t ivlen = EVP_CIPHER_CTX_iv_length(gctx->cctx);
138
139         if (!OSSL_PARAM_set_octet_ptr(p, iv, ivlen)
140             && !OSSL_PARAM_set_octet_string(p, iv, ivlen))
141             return 0;
142     }
143     return 1;
144 }
145
146 static int cipher_set_ctx_params(void *vgctx, const OSSL_PARAM params[])
147 {
148     GOST_CTX *gctx = vgctx;
149     const OSSL_PARAM *p;
150
151     if ((p = OSSL_PARAM_locate_const(params, "alg_id_param")) != NULL) {
152         ASN1_TYPE *algidparam = NULL;
153         const unsigned char *der = NULL;
154         size_t derlen = 0;
155         int ret;
156
157         ret = OSSL_PARAM_get_octet_string_ptr(p, (const void **)&der, &derlen)
158             && (algidparam = d2i_ASN1_TYPE(NULL, &der, (long)derlen)) != NULL
159             && EVP_CIPHER_asn1_to_param(gctx->cctx, algidparam) > 0;
160
161         ASN1_TYPE_free(algidparam);
162         return ret;
163     }
164     if ((p = OSSL_PARAM_locate_const(params, "padding")) != NULL) {
165         unsigned int pad = 0;
166
167         if (!OSSL_PARAM_get_uint(p, &pad)
168             || EVP_CIPHER_CTX_set_padding(gctx->cctx, pad) <= 0)
169             return 0;
170     }
171     if ((p = OSSL_PARAM_locate_const(params, "key-mesh")) != NULL) {
172         size_t key_mesh = 0;
173
174         if (!OSSL_PARAM_get_size_t(p, &key_mesh)
175             || EVP_CIPHER_CTX_ctrl(gctx->cctx, EVP_CTRL_KEY_MESH,
176                                    key_mesh, NULL) <= 0)
177             return 0;
178     }
179     return 1;
180 }
181
182 static int cipher_encrypt_init(void *vgctx,
183                                const unsigned char *key, size_t keylen,
184                                const unsigned char *iv, size_t ivlen,
185                                const OSSL_PARAM params[])
186 {
187     GOST_CTX *gctx = vgctx;
188
189     if (!cipher_set_ctx_params(vgctx, params)
190         || keylen > EVP_CIPHER_key_length(gctx->cipher)
191         || ivlen > EVP_CIPHER_iv_length(gctx->cipher))
192         return 0;
193     return EVP_CipherInit_ex(gctx->cctx, gctx->cipher, gctx->provctx->e,
194                              key, iv, 1);
195 }
196
197 static int cipher_decrypt_init(void *vgctx,
198                                const unsigned char *key, size_t keylen,
199                                const unsigned char *iv, size_t ivlen,
200                                const OSSL_PARAM params[])
201 {
202     GOST_CTX *gctx = vgctx;
203
204     if (!cipher_set_ctx_params(vgctx, params)
205         || keylen > EVP_CIPHER_key_length(gctx->cipher)
206         || ivlen > EVP_CIPHER_iv_length(gctx->cipher))
207         return 0;
208     return EVP_CipherInit_ex(gctx->cctx, gctx->cipher, gctx->provctx->e,
209                              key, iv, 0) > 0;
210 }
211
212 static int cipher_update(void *vgctx,
213                          unsigned char *out, size_t *outl, size_t outsize,
214                          const unsigned char *in, size_t inl)
215 {
216     GOST_CTX *gctx = vgctx;
217     int int_outl = outl != NULL ? *outl : 0;
218     int res = EVP_CipherUpdate(gctx->cctx, out, &int_outl, in, (int)inl);
219
220     if (res > 0 && outl != NULL)
221         *outl = (size_t)int_outl;
222     return res > 0;
223 }
224
225 static int cipher_final(void *vgctx,
226                         unsigned char *out, size_t *outl, size_t outsize)
227 {
228     GOST_CTX *gctx = vgctx;
229     int int_outl = outl != NULL ? *outl : 0;
230     int res = EVP_CipherFinal(gctx->cctx, out, &int_outl);
231
232     if (res > 0 && outl != NULL)
233         *outl = (size_t)int_outl;
234     return res > 0;
235 }
236
237 static const OSSL_PARAM known_Gost28147_89_cipher_params[] = {};
238 static const OSSL_PARAM known_Gost28147_89_cbc_cipher_params[] = {};
239 static const OSSL_PARAM known_Gost28147_89_cnt_cipher_params[] = {};
240 static const OSSL_PARAM known_Gost28147_89_cnt_12_cipher_params[] = {};
241 static const OSSL_PARAM known_grasshopper_ecb_cipher_params[] = {};
242 static const OSSL_PARAM known_grasshopper_cbc_cipher_params[] = {};
243 static const OSSL_PARAM known_grasshopper_cfb_cipher_params[] = {};
244 static const OSSL_PARAM known_grasshopper_ofb_cipher_params[] = {};
245 static const OSSL_PARAM known_grasshopper_ctr_cipher_params[] = {};
246 static const OSSL_PARAM known_magma_ctr_cipher_params[] = {};
247 static const OSSL_PARAM known_magma_ctr_acpkm_cipher_params[] = {};
248 static const OSSL_PARAM known_magma_ctr_acpkm_omac_cipher_params[] = {};
249 static const OSSL_PARAM known_magma_cbc_cipher_params[] = {};
250 static const OSSL_PARAM known_grasshopper_ctr_acpkm_cipher_params[] = {};
251 static const OSSL_PARAM known_grasshopper_ctr_acpkm_omac_cipher_params[] = {};
252 /*
253  * These are named like the EVP_CIPHER templates in gost_crypt.c, with the
254  * added suffix "_functions".  Hopefully, that makes it easy to find the
255  * actual implementation.
256  */
257 typedef void (*fptr_t)(void);
258 #define MAKE_FUNCTIONS(name)                                            \
259     static OSSL_FUNC_cipher_get_params_fn name##_get_params;            \
260     static int name##_get_params(OSSL_PARAM *params)                    \
261     {                                                                   \
262         return cipher_get_params(GOST_init_cipher(&name), params);      \
263     }                                                                   \
264     static OSSL_FUNC_cipher_newctx_fn name##_newctx;                    \
265     static void *name##_newctx(void *provctx)                           \
266     {                                                                   \
267         return cipher_newctx(provctx, &name, known_##name##_params);    \
268     }                                                                   \
269     static const OSSL_DISPATCH name##_functions[] = {                   \
270         { OSSL_FUNC_CIPHER_GET_PARAMS, (fptr_t)name##_get_params },     \
271         { OSSL_FUNC_CIPHER_NEWCTX, (fptr_t)name##_newctx },             \
272         { OSSL_FUNC_CIPHER_DUPCTX, (fptr_t)cipher_dupctx },             \
273         { OSSL_FUNC_CIPHER_FREECTX, (fptr_t)cipher_freectx },           \
274         { OSSL_FUNC_CIPHER_GET_CTX_PARAMS, (fptr_t)cipher_get_ctx_params }, \
275         { OSSL_FUNC_CIPHER_SET_CTX_PARAMS, (fptr_t)cipher_set_ctx_params }, \
276         { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (fptr_t)cipher_encrypt_init }, \
277         { OSSL_FUNC_CIPHER_DECRYPT_INIT, (fptr_t)cipher_decrypt_init }, \
278         { OSSL_FUNC_CIPHER_UPDATE, (fptr_t)cipher_update },             \
279         { OSSL_FUNC_CIPHER_FINAL, (fptr_t)cipher_final },               \
280     }
281
282 MAKE_FUNCTIONS(Gost28147_89_cipher);
283 MAKE_FUNCTIONS(Gost28147_89_cnt_cipher);
284 MAKE_FUNCTIONS(Gost28147_89_cnt_12_cipher);
285 MAKE_FUNCTIONS(Gost28147_89_cbc_cipher);
286 MAKE_FUNCTIONS(grasshopper_ecb_cipher);
287 MAKE_FUNCTIONS(grasshopper_cbc_cipher);
288 MAKE_FUNCTIONS(grasshopper_cfb_cipher);
289 MAKE_FUNCTIONS(grasshopper_ofb_cipher);
290 MAKE_FUNCTIONS(grasshopper_ctr_cipher);
291 MAKE_FUNCTIONS(magma_cbc_cipher);
292 MAKE_FUNCTIONS(magma_ctr_cipher);
293 MAKE_FUNCTIONS(magma_ctr_acpkm_cipher);
294 MAKE_FUNCTIONS(magma_ctr_acpkm_omac_cipher);
295 MAKE_FUNCTIONS(grasshopper_ctr_acpkm_cipher);
296 MAKE_FUNCTIONS(grasshopper_ctr_acpkm_omac_cipher);
297
298 /* The OSSL_ALGORITHM for the provider's operation query function */
299 const OSSL_ALGORITHM GOST_prov_ciphers[] = {
300     { SN_id_Gost28147_89 ":gost89:GOST 28147-89:1.2.643.2.2.21", NULL,
301       Gost28147_89_cipher_functions },
302     { SN_gost89_cnt, NULL, Gost28147_89_cnt_cipher_functions },
303     { SN_gost89_cnt_12, NULL, Gost28147_89_cnt_12_cipher_functions },
304     { SN_gost89_cbc, NULL, Gost28147_89_cbc_cipher_functions },
305     { SN_grasshopper_ecb, NULL, grasshopper_ecb_cipher_functions },
306     { SN_grasshopper_cbc, NULL, grasshopper_cbc_cipher_functions },
307     { SN_grasshopper_cfb, NULL, grasshopper_cfb_cipher_functions },
308     { SN_grasshopper_ofb, NULL, grasshopper_ofb_cipher_functions },
309     { SN_grasshopper_ctr, NULL, grasshopper_ctr_cipher_functions },
310     { SN_magma_cbc, NULL, magma_cbc_cipher_functions },
311     { SN_magma_ctr, NULL, magma_ctr_cipher_functions },
312     { SN_magma_ctr_acpkm ":1.2.643.7.1.1.5.1.1", NULL,
313       magma_ctr_acpkm_cipher_functions },
314     { SN_magma_ctr_acpkm_omac ":1.2.643.7.1.1.5.1.2", NULL,
315       magma_ctr_acpkm_omac_cipher_functions },
316     { SN_kuznyechik_ctr_acpkm ":1.2.643.7.1.1.5.2.1", NULL,
317       grasshopper_ctr_acpkm_cipher_functions },
318     { SN_kuznyechik_ctr_acpkm_omac ":1.2.643.7.1.1.5.2.2", NULL,
319       grasshopper_ctr_acpkm_omac_cipher_functions },
320 #if 0                           /* Not yet implemented */
321     { SN_magma_kexp15 ":1.2.643.7.1.1.7.1.1", NULL,
322       magma_kexp15_cipher_functions },
323     { SN_kuznyechik_kexp15 ":1.2.643.7.1.1.7.2.1", NULL,
324       kuznyechik_kexp15_cipher_functions },
325 #endif
326     { NULL , NULL, NULL }
327 };
328
329 void GOST_prov_deinit_ciphers(void) {
330     static GOST_cipher *list[] = {
331         &Gost28147_89_cipher,
332         &Gost28147_89_cnt_cipher,
333         &Gost28147_89_cnt_12_cipher,
334         &Gost28147_89_cbc_cipher,
335         &grasshopper_ecb_cipher,
336         &grasshopper_cbc_cipher,
337         &grasshopper_cfb_cipher,
338         &grasshopper_ofb_cipher,
339         &grasshopper_ctr_cipher,
340         &magma_cbc_cipher,
341         &magma_ctr_cipher,
342         &magma_ctr_acpkm_cipher,
343         &magma_ctr_acpkm_omac_cipher,
344         &grasshopper_ctr_acpkm_cipher,
345         &grasshopper_ctr_acpkm_omac_cipher,
346     };
347     size_t i;
348 #define elems(l) (sizeof(l) / sizeof(l[0]))
349
350     for (i = 0; i < elems(list); i++)
351         GOST_deinit_cipher(list[i]);
352 }