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