-
Notifications
You must be signed in to change notification settings - Fork 192
Expand file tree
/
Copy pathgost_prov_digest.c
More file actions
198 lines (163 loc) · 6.49 KB
/
gost_prov_digest.c
File metadata and controls
198 lines (163 loc) · 6.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
/**********************************************************************
* gost_prov_digest.c - Initialize all digests *
* *
* Copyright (c) 2021 Richard Levitte <richard@levitte.org> *
* This file is distributed under the same license as OpenSSL *
* *
* OpenSSL provider interface to GOST digest functions *
* Requires OpenSSL 3.0 for compilation *
**********************************************************************/
#include <openssl/core.h>
#include <openssl/core_dispatch.h>
#include "gost_prov.h"
#include "gost_prov_digest.h"
#include "gost_lcl.h"
/*
* Forward declarations of all OSSL_DISPATCH functions, to make sure they
* are correctly defined further down.
*/
static OSSL_FUNC_digest_dupctx_fn digest_dupctx;
static OSSL_FUNC_digest_freectx_fn digest_freectx;
static OSSL_FUNC_digest_init_fn digest_init;
static OSSL_FUNC_digest_update_fn digest_update;
static OSSL_FUNC_digest_final_fn digest_final;
struct gost_prov_crypt_ctx_st {
PROV_CTX *provctx;
const GOST_digest *descriptor;
GOST_digest_ctx *dctx;
};
typedef struct gost_prov_crypt_ctx_st GOST_CTX;
static void digest_freectx(void *vgctx)
{
GOST_CTX *gctx = vgctx;
if (!gctx)
return;
GOST_digest_ctx_free(gctx->dctx);
OPENSSL_free(gctx);
}
static GOST_CTX *digest_newctx(void *provctx, const GOST_digest *descriptor)
{
GOST_CTX *gctx = NULL;
if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
gctx->provctx = provctx;
gctx->descriptor = descriptor;
gctx->dctx = GOST_digest_ctx_new();
if (gctx->dctx == NULL) {
digest_freectx(gctx);
gctx = NULL;
}
}
return gctx;
}
static void *digest_dupctx(void *vsrc)
{
GOST_CTX *src = vsrc;
GOST_CTX *dst = digest_newctx(src->provctx, src->descriptor);
if (dst != NULL)
GOST_digest_ctx_copy(dst->dctx, src->dctx);
return dst;
}
static int digest_get_params(const GOST_digest *descriptor, OSSL_PARAM params[])
{
OSSL_PARAM *p;
if (((p = OSSL_PARAM_locate(params, "blocksize")) != NULL
&& !OSSL_PARAM_set_size_t(p, GOST_digest_block_size(descriptor)))
|| ((p = OSSL_PARAM_locate(params, "size")) != NULL
&& !OSSL_PARAM_set_size_t(p, GOST_digest_size(descriptor)))
|| ((p = OSSL_PARAM_locate(params, "xof")) != NULL
&& !OSSL_PARAM_set_size_t(p, GOST_digest_flags(descriptor) & EVP_MD_FLAG_XOF)))
return 0;
return 1;
}
static int digest_init(void *vgctx, const OSSL_PARAM unused_params[])
{
GOST_CTX *gctx = vgctx;
return GOST_digest_ctx_init(gctx->dctx, gctx->descriptor) > 0;
}
static int digest_update(void *vgctx, const unsigned char *in, size_t inl)
{
GOST_CTX *gctx = vgctx;
return GOST_digest_ctx_update(gctx->dctx, in, inl) > 0;
}
static int digest_final(void *vgctx,
unsigned char *out, size_t *outl, size_t outsize)
{
GOST_CTX *gctx = vgctx;
if (outl == NULL) {
return 0;
}
if (out == NULL) {
*outl = GOST_digest_size(gctx->descriptor);
return 1;
}
if (outsize < GOST_digest_size(gctx->descriptor))
return 0;
int res = GOST_digest_ctx_final(gctx->dctx, out);
GOST_digest_ctx_cleanup(gctx->dctx);
if (res > 0)
*outl = GOST_digest_size(gctx->descriptor);
return res > 0;
}
/*
* These are named like the EVP_MD templates in gost_md.c etc, with the
* added suffix "_functions". Hopefully, that makes it easy to find the
* actual implementation.
*/
typedef void (*fptr_t)(void);
#define MAKE_FUNCTIONS(name) \
static OSSL_FUNC_digest_get_params_fn name##_get_params; \
static int name##_get_params(OSSL_PARAM *params) \
{ \
return digest_get_params(&name, params); \
} \
static OSSL_FUNC_digest_newctx_fn name##_newctx; \
static void *name##_newctx(void *provctx) \
{ \
return digest_newctx(provctx, &name); \
} \
static const OSSL_DISPATCH name##_functions[] = { \
{ OSSL_FUNC_DIGEST_GET_PARAMS, (fptr_t)name##_get_params }, \
{ OSSL_FUNC_DIGEST_NEWCTX, (fptr_t)name##_newctx }, \
{ OSSL_FUNC_DIGEST_DUPCTX, (fptr_t)digest_dupctx }, \
{ OSSL_FUNC_DIGEST_FREECTX, (fptr_t)digest_freectx }, \
{ OSSL_FUNC_DIGEST_INIT, (fptr_t)digest_init }, \
{ OSSL_FUNC_DIGEST_UPDATE, (fptr_t)digest_update }, \
{ OSSL_FUNC_DIGEST_FINAL, (fptr_t)digest_final }, \
}
MAKE_FUNCTIONS(GostR3411_94_digest);
MAKE_FUNCTIONS(GostR3411_2012_256_digest);
MAKE_FUNCTIONS(GostR3411_2012_512_digest);
/* The OSSL_ALGORITHM for the provider's operation query function */
const OSSL_ALGORITHM GOST_prov_digests[] = {
/*
* Described in RFC 6986, first name from
* https://www.ietf.org/archive/id/draft-deremin-rfc4491-bis-06.txt
* (is there not an RFC namming these?)
*/
{ SN_id_GostR3411_2012_256":id-tc26-gost3411-12-256:1.2.643.7.1.1.2.2", NULL,
GostR3411_2012_256_digest_functions,
"GOST R 34.11-2012 with 256 bit hash" },
{ SN_id_GostR3411_2012_512":id-tc26-gost3411-12-512:1.2.643.7.1.1.2.3", NULL,
GostR3411_2012_512_digest_functions,
"GOST R 34.11-2012 with 512 bit hash" },
/* Described in RFC 5831, first name from RFC 4357, section 10.4 */
{ SN_id_GostR3411_94":id-GostR3411-94:1.2.643.2.2.9", NULL,
GostR3411_94_digest_functions, "GOST R 34.11-94" },
{ NULL , NULL, NULL }
};
static GOST_digest *digests[] = {
&GostR3411_94_digest,
&GostR3411_2012_256_digest,
&GostR3411_2012_512_digest,
};
#define arraysize(l) (sizeof(l) / sizeof(l[0]))
void GOST_prov_init_digests(void) {
size_t i;
for (i = 0; i < arraysize(digests); i++)
GOST_digest_init(digests[i]);
}
void GOST_prov_deinit_digests(void) {
size_t i;
for (i = 0; i < arraysize(digests); i++)
GOST_digest_deinit(digests[i]);
}