]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_prov_digest.c
tcl_tests: ca.try: Ignore openssl crl exit status for 'corrupted CRL' test
[openssl-gost/engine.git] / gost_prov_digest.c
1 /**********************************************************************
2  *             gost_prov_digest.c - Initialize all digests            *
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 digest 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 OSSL_DISPATCH functions, to make sure they
18  * are correctly defined further down.
19  */
20 static OSSL_FUNC_digest_dupctx_fn digest_dupctx;
21 static OSSL_FUNC_digest_freectx_fn digest_freectx;
22 static OSSL_FUNC_digest_init_fn digest_init;
23 static OSSL_FUNC_digest_update_fn digest_update;
24 static OSSL_FUNC_digest_final_fn digest_final;
25
26
27 struct gost_prov_crypt_ctx_st {
28     /* Provider context */
29     PROV_CTX *provctx;
30     /* OSSL_PARAM descriptors */
31     const OSSL_PARAM *known_params;
32     /* GOST_digest descriptor */
33     GOST_digest *descriptor;
34
35     /*
36      * Since existing functionality is designed for ENGINEs, the functions
37      * in this file are accomodated and are simply wrappers that use a local
38      * EVP_MD and EVP_MD_CTX.
39      * Future development should take a more direct approach and have the
40      * appropriate digest functions and digest data directly in this context.
41      */
42
43     /* The EVP_MD created from |descriptor| */
44     EVP_MD *digest;
45     /* The context for the EVP_MD functions */
46     EVP_MD_CTX *dctx;
47 };
48 typedef struct gost_prov_crypt_ctx_st GOST_CTX;
49
50 static void digest_freectx(void *vgctx)
51 {
52     GOST_CTX *gctx = vgctx;
53
54     /*
55      * We don't free gctx->digest here.
56      * That will be done by the provider teardown, via
57      * GOST_prov_deinit_digests() (defined at the bottom of this file).
58      */
59     EVP_MD_CTX_free(gctx->dctx);
60     OPENSSL_free(gctx);
61 }
62
63 static GOST_CTX *digest_newctx(void *provctx, GOST_digest *descriptor,
64                                const OSSL_PARAM *known_params)
65 {
66     GOST_CTX *gctx = NULL;
67
68     if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
69         gctx->provctx = provctx;
70         gctx->known_params = known_params;
71         gctx->descriptor = descriptor;
72         gctx->digest = GOST_init_digest(descriptor);
73         gctx->dctx = EVP_MD_CTX_new();
74
75         if (gctx->digest == NULL || gctx->dctx == NULL) {
76             digest_freectx(gctx);
77             gctx = NULL;
78         }
79     }
80     return gctx;
81 }
82
83 static void *digest_dupctx(void *vsrc)
84 {
85     GOST_CTX *src = vsrc;
86     GOST_CTX *dst =
87         digest_newctx(src->provctx, src->descriptor, src->known_params);
88
89     if (dst != NULL)
90         EVP_MD_CTX_copy(dst->dctx, src->dctx);
91     return dst;
92 }
93
94 static int digest_get_params(EVP_MD *d, OSSL_PARAM params[])
95 {
96     OSSL_PARAM *p;
97
98     if (((p = OSSL_PARAM_locate(params, "blocksize")) != NULL
99          && !OSSL_PARAM_set_size_t(p, EVP_MD_block_size(d)))
100         || ((p = OSSL_PARAM_locate(params, "size")) != NULL
101             && !OSSL_PARAM_set_size_t(p, EVP_MD_size(d)))
102         || ((p = OSSL_PARAM_locate(params, "xof")) != NULL
103             && !OSSL_PARAM_set_size_t(p, EVP_MD_flags(d) & EVP_MD_FLAG_XOF)))
104         return 0;
105     return 1;
106 }
107
108 static int digest_init(void *vgctx, const OSSL_PARAM unused_params[])
109 {
110     GOST_CTX *gctx = vgctx;
111
112     return EVP_DigestInit_ex(gctx->dctx, gctx->digest, gctx->provctx->e) > 0;
113 }
114
115 static int digest_update(void *vgctx, const unsigned char *in, size_t inl)
116 {
117     GOST_CTX *gctx = vgctx;
118
119     return EVP_DigestUpdate(gctx->dctx, in, (int)inl) > 0;
120 }
121
122 static int digest_final(void *vgctx,
123                         unsigned char *out, size_t *outl, size_t outsize)
124 {
125     GOST_CTX *gctx = vgctx;
126     unsigned int int_outl = outl != NULL ? *outl : 0;
127     int res = EVP_DigestFinal(gctx->dctx, out, &int_outl);
128
129     if (res > 0 && outl != NULL)
130         *outl = (size_t)int_outl;
131     return res > 0;
132 }
133
134 static const OSSL_PARAM *known_GostR3411_94_digest_params;
135 static const OSSL_PARAM *known_GostR3411_2012_256_digest_params;
136 static const OSSL_PARAM *known_GostR3411_2012_512_digest_params;
137
138 /*
139  * These are named like the EVP_MD templates in gost_md.c etc, with the
140  * added suffix "_functions".  Hopefully, that makes it easy to find the
141  * actual implementation.
142  */
143 typedef void (*fptr_t)(void);
144 #define MAKE_FUNCTIONS(name)                                            \
145     static OSSL_FUNC_digest_get_params_fn name##_get_params;            \
146     static int name##_get_params(OSSL_PARAM *params)                    \
147     {                                                                   \
148         return digest_get_params(GOST_init_digest(&name), params);      \
149     }                                                                   \
150     static OSSL_FUNC_digest_newctx_fn name##_newctx;                    \
151     static void *name##_newctx(void *provctx)                           \
152     {                                                                   \
153         return digest_newctx(provctx, &name, known_##name##_params);    \
154     }                                                                   \
155     static const OSSL_DISPATCH name##_functions[] = {                   \
156         { OSSL_FUNC_DIGEST_GET_PARAMS, (fptr_t)name##_get_params },     \
157         { OSSL_FUNC_DIGEST_NEWCTX, (fptr_t)name##_newctx },             \
158         { OSSL_FUNC_DIGEST_DUPCTX, (fptr_t)digest_dupctx },             \
159         { OSSL_FUNC_DIGEST_FREECTX, (fptr_t)digest_freectx },           \
160         { OSSL_FUNC_DIGEST_INIT, (fptr_t)digest_init },                 \
161         { OSSL_FUNC_DIGEST_UPDATE, (fptr_t)digest_update },             \
162         { OSSL_FUNC_DIGEST_FINAL, (fptr_t)digest_final },               \
163     }
164
165 MAKE_FUNCTIONS(GostR3411_94_digest);
166 MAKE_FUNCTIONS(GostR3411_2012_256_digest);
167 MAKE_FUNCTIONS(GostR3411_2012_512_digest);
168
169 /* The OSSL_ALGORITHM for the provider's operation query function */
170 const OSSL_ALGORITHM GOST_prov_digests[] = {
171     /*
172      * Described in RFC 6986, first name from
173      * https://www.ietf.org/archive/id/draft-deremin-rfc4491-bis-06.txt
174      * (is there not an RFC namming these?)
175      */
176     { "id-tc26-gost3411-12-256:md_gost12_256:1.2.643.7.1.1.2.2", NULL,
177       GostR3411_2012_256_digest_functions,
178       "GOST R 34.11-2012 with 256 bit hash" },
179     { "id-tc26-gost3411-12-512:md_gost12_512:1.2.643.7.1.1.2.3", NULL,
180       GostR3411_2012_512_digest_functions,
181       "GOST R 34.11-2012 with 512 bit hash" },
182
183     /* Described in RFC 5831, first name from RFC 4357, section 10.4 */
184     { "id-GostR3411-94:md_gost94:1.2.643.2.2.9", NULL,
185       GostR3411_94_digest_functions, "GOST R 34.11-94" },
186     { NULL , NULL, NULL }
187 };
188
189 void GOST_prov_deinit_digests(void) {
190     static GOST_digest *list[] = {
191         &GostR3411_94_digest,
192         &GostR3411_2012_256_digest,
193         &GostR3411_2012_512_digest,
194     };
195     size_t i;
196 #define elems(l) (sizeof(l) / sizeof(l[0]))
197
198     for (i = 0; i < elems(list); i++)
199         GOST_deinit_digest(list[i]);
200 }