]>
Commit | Line | Data |
---|---|---|
0f113f3e | 1 | /* |
4803717f | 2 | * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. |
91c9e621 | 3 | * |
4a8b0c55 | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
62867571 RS |
5 | * this file except in compliance with the License. You can obtain a copy |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
91c9e621 DSH |
8 | */ |
9 | ||
10 | #include <stdio.h> | |
b39fc560 | 11 | #include "internal/cryptlib.h" |
91c9e621 DSH |
12 | #include <openssl/evp.h> |
13 | #include <openssl/objects.h> | |
14 | #include <openssl/x509.h> | |
25f2138b | 15 | #include "crypto/evp.h" |
d8c98d79 | 16 | #include "internal/provider.h" |
706457b7 | 17 | #include "evp_local.h" |
91c9e621 | 18 | |
72df8f88 MC |
19 | #ifndef FIPS_MODE |
20 | ||
f723c98e DSH |
21 | static int update(EVP_MD_CTX *ctx, const void *data, size_t datalen) |
22 | { | |
23 | EVPerr(EVP_F_UPDATE, EVP_R_ONLY_ONESHOT_SUPPORTED); | |
24 | return 0; | |
25 | } | |
26 | ||
777c47ac | 27 | static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, |
d8c98d79 MC |
28 | const EVP_MD *type, const char *mdname, |
29 | const char *props, ENGINE *e, EVP_PKEY *pkey, | |
0e521004 | 30 | int ver) |
0f113f3e | 31 | { |
d8c98d79 | 32 | EVP_PKEY_CTX *locpctx = NULL; |
0e521004 | 33 | EVP_SIGNATURE *signature = NULL; |
f6aa5774 RL |
34 | EVP_KEYMGMT *tmp_keymgmt = NULL; |
35 | const char *supported_sig = NULL; | |
ead0d234 | 36 | char locmdname[80] = ""; /* 80 chars should be enough */ |
d8c98d79 MC |
37 | void *provkey = NULL; |
38 | int ret; | |
39 | ||
15de965f MC |
40 | if (ctx->provctx != NULL) { |
41 | if (!ossl_assert(ctx->digest != NULL)) { | |
42 | ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); | |
43 | return 0; | |
44 | } | |
45 | if (ctx->digest->freectx != NULL) | |
46 | ctx->digest->freectx(ctx->provctx); | |
47 | ctx->provctx = NULL; | |
48 | } | |
49 | ||
0e521004 | 50 | if (ctx->pctx == NULL) |
0f113f3e | 51 | ctx->pctx = EVP_PKEY_CTX_new(pkey, e); |
0e521004 RL |
52 | if (ctx->pctx == NULL) |
53 | return 0; | |
54 | ||
d8c98d79 MC |
55 | locpctx = ctx->pctx; |
56 | evp_pkey_ctx_free_old_ops(locpctx); | |
d8c98d79 | 57 | |
0b9dd384 RL |
58 | /* |
59 | * TODO when we stop falling back to legacy, this and the ERR_pop_to_mark() | |
60 | * calls can be removed. | |
61 | */ | |
62 | ERR_set_mark(); | |
63 | ||
f23bc0b7 | 64 | if (locpctx->keytype == NULL) |
d8c98d79 MC |
65 | goto legacy; |
66 | ||
f6aa5774 RL |
67 | /* Ensure that the key is provided. If not, go legacy */ |
68 | tmp_keymgmt = locpctx->keymgmt; | |
69 | provkey = evp_pkey_make_provided(locpctx->pkey, locpctx->libctx, | |
b305452f | 70 | &tmp_keymgmt, locpctx->propquery); |
f6aa5774 RL |
71 | if (provkey == NULL) |
72 | goto legacy; | |
73 | if (!EVP_KEYMGMT_up_ref(tmp_keymgmt)) { | |
0b9dd384 | 74 | ERR_clear_last_mark(); |
f6aa5774 RL |
75 | ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); |
76 | goto err; | |
d8c98d79 | 77 | } |
f6aa5774 RL |
78 | EVP_KEYMGMT_free(locpctx->keymgmt); |
79 | locpctx->keymgmt = tmp_keymgmt; | |
80 | ||
81 | if (locpctx->keymgmt->query_operation_name != NULL) | |
82 | supported_sig = | |
83 | locpctx->keymgmt->query_operation_name(OSSL_OP_SIGNATURE); | |
84 | ||
85 | /* | |
86 | * If we didn't get a supported sig, assume there is one with the | |
87 | * same name as the key type. | |
88 | */ | |
89 | if (supported_sig == NULL) | |
90 | supported_sig = locpctx->keytype; | |
91 | ||
92 | /* | |
93 | * Because we cleared out old ops, we shouldn't need to worry about | |
94 | * checking if signature is already there. | |
95 | */ | |
96 | signature = EVP_SIGNATURE_fetch(locpctx->libctx, supported_sig, | |
97 | locpctx->propquery); | |
98 | ||
99 | if (signature == NULL | |
0e521004 RL |
100 | || (EVP_KEYMGMT_provider(locpctx->keymgmt) |
101 | != EVP_SIGNATURE_provider(signature))) { | |
102 | /* | |
0b9dd384 RL |
103 | * We don't need to free ctx->keymgmt here, as it's not necessarily |
104 | * tied to this operation. It will be freed by EVP_PKEY_CTX_free(). | |
0e521004 RL |
105 | */ |
106 | EVP_SIGNATURE_free(signature); | |
107 | goto legacy; | |
108 | } | |
109 | ||
0b9dd384 RL |
110 | /* |
111 | * TODO remove this when legacy is gone | |
112 | * If we don't have the full support we need with provided methods, | |
113 | * let's go see if legacy does. | |
114 | */ | |
115 | ERR_pop_to_mark(); | |
116 | ||
0e521004 | 117 | /* No more legacy from here down to legacy: */ |
d8c98d79 | 118 | |
ead0d234 RL |
119 | if (pctx != NULL) |
120 | *pctx = locpctx; | |
121 | ||
d8c98d79 | 122 | locpctx->op.sig.signature = signature; |
0e521004 RL |
123 | locpctx->operation = ver ? EVP_PKEY_OP_VERIFYCTX |
124 | : EVP_PKEY_OP_SIGNCTX; | |
d8c98d79 MC |
125 | locpctx->op.sig.sigprovctx |
126 | = signature->newctx(ossl_provider_ctx(signature->prov)); | |
127 | if (locpctx->op.sig.sigprovctx == NULL) { | |
128 | ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); | |
129 | goto err; | |
130 | } | |
0e521004 | 131 | if (type != NULL) { |
d8c98d79 | 132 | ctx->reqdigest = type; |
ead0d234 RL |
133 | if (mdname == NULL) |
134 | mdname = EVP_MD_name(type); | |
d8c98d79 | 135 | } else { |
ead0d234 RL |
136 | if (mdname == NULL |
137 | && EVP_PKEY_get_default_digest_name(locpctx->pkey, locmdname, | |
138 | sizeof(locmdname))) | |
139 | mdname = locmdname; | |
140 | ||
141 | if (mdname != NULL) { | |
142 | /* | |
143 | * This might be requested by a later call to EVP_MD_CTX_md(). | |
144 | * In that case the "explicit fetch" rules apply for that | |
145 | * function (as per man pages), i.e. the ref count is not updated | |
146 | * so the EVP_MD should not be used beyound the lifetime of the | |
147 | * EVP_MD_CTX. | |
148 | */ | |
149 | ctx->reqdigest = ctx->fetched_digest = | |
150 | EVP_MD_fetch(locpctx->libctx, mdname, props); | |
151 | } | |
d8c98d79 MC |
152 | } |
153 | ||
154 | if (ver) { | |
155 | if (signature->digest_verify_init == NULL) { | |
156 | ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); | |
157 | goto err; | |
158 | } | |
0e521004 RL |
159 | ret = signature->digest_verify_init(locpctx->op.sig.sigprovctx, |
160 | mdname, props, provkey); | |
d8c98d79 MC |
161 | } else { |
162 | if (signature->digest_sign_init == NULL) { | |
163 | ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); | |
164 | goto err; | |
165 | } | |
0e521004 RL |
166 | ret = signature->digest_sign_init(locpctx->op.sig.sigprovctx, |
167 | mdname, props, provkey); | |
d8c98d79 MC |
168 | } |
169 | ||
170 | return ret ? 1 : 0; | |
171 | err: | |
172 | evp_pkey_ctx_free_old_ops(locpctx); | |
173 | locpctx->operation = EVP_PKEY_OP_UNDEFINED; | |
174 | return 0; | |
e69adea5 | 175 | |
d8c98d79 | 176 | legacy: |
0b9dd384 RL |
177 | /* |
178 | * TODO remove this when legacy is gone | |
179 | * If we don't have the full support we need with provided methods, | |
180 | * let's go see if legacy does. | |
181 | */ | |
182 | ERR_pop_to_mark(); | |
183 | ||
e0d8523e RL |
184 | if (ctx->pctx->pmeth == NULL) { |
185 | EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); | |
76123661 | 186 | return 0; |
e0d8523e RL |
187 | } |
188 | ||
0f113f3e | 189 | if (!(ctx->pctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM)) { |
e69adea5 | 190 | |
0f113f3e MC |
191 | if (type == NULL) { |
192 | int def_nid; | |
193 | if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) > 0) | |
194 | type = EVP_get_digestbynid(def_nid); | |
195 | } | |
c8ef656d | 196 | |
0f113f3e MC |
197 | if (type == NULL) { |
198 | EVPerr(EVP_F_DO_SIGVER_INIT, EVP_R_NO_DEFAULT_DIGEST); | |
199 | return 0; | |
200 | } | |
201 | } | |
e69adea5 | 202 | |
0f113f3e MC |
203 | if (ver) { |
204 | if (ctx->pctx->pmeth->verifyctx_init) { | |
205 | if (ctx->pctx->pmeth->verifyctx_init(ctx->pctx, ctx) <= 0) | |
206 | return 0; | |
207 | ctx->pctx->operation = EVP_PKEY_OP_VERIFYCTX; | |
f723c98e DSH |
208 | } else if (ctx->pctx->pmeth->digestverify != 0) { |
209 | ctx->pctx->operation = EVP_PKEY_OP_VERIFY; | |
210 | ctx->update = update; | |
211 | } else if (EVP_PKEY_verify_init(ctx->pctx) <= 0) { | |
0f113f3e | 212 | return 0; |
f723c98e | 213 | } |
0f113f3e MC |
214 | } else { |
215 | if (ctx->pctx->pmeth->signctx_init) { | |
216 | if (ctx->pctx->pmeth->signctx_init(ctx->pctx, ctx) <= 0) | |
217 | return 0; | |
218 | ctx->pctx->operation = EVP_PKEY_OP_SIGNCTX; | |
f723c98e DSH |
219 | } else if (ctx->pctx->pmeth->digestsign != 0) { |
220 | ctx->pctx->operation = EVP_PKEY_OP_SIGN; | |
221 | ctx->update = update; | |
222 | } else if (EVP_PKEY_sign_init(ctx->pctx) <= 0) { | |
0f113f3e | 223 | return 0; |
f723c98e | 224 | } |
0f113f3e MC |
225 | } |
226 | if (EVP_PKEY_CTX_set_signature_md(ctx->pctx, type) <= 0) | |
227 | return 0; | |
228 | if (pctx) | |
229 | *pctx = ctx->pctx; | |
230 | if (ctx->pctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM) | |
231 | return 1; | |
232 | if (!EVP_DigestInit_ex(ctx, type, e)) | |
233 | return 0; | |
4803717f PY |
234 | /* |
235 | * This indicates the current algorithm requires | |
236 | * special treatment before hashing the tbs-message. | |
237 | */ | |
675f4cee | 238 | if (ctx->pctx->pmeth->digest_custom != NULL) |
4803717f PY |
239 | return ctx->pctx->pmeth->digest_custom(ctx->pctx, ctx); |
240 | ||
0f113f3e MC |
241 | return 1; |
242 | } | |
91c9e621 | 243 | |
d8c98d79 | 244 | int EVP_DigestSignInit_ex(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, |
0e521004 | 245 | const char *mdname, const char *props, EVP_PKEY *pkey) |
d8c98d79 | 246 | { |
0e521004 | 247 | return do_sigver_init(ctx, pctx, NULL, mdname, props, NULL, pkey, 0); |
d8c98d79 MC |
248 | } |
249 | ||
91c9e621 | 250 | int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, |
0f113f3e MC |
251 | const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey) |
252 | { | |
0e521004 | 253 | return do_sigver_init(ctx, pctx, type, NULL, NULL, e, pkey, 0); |
d8c98d79 MC |
254 | } |
255 | ||
256 | int EVP_DigestVerifyInit_ex(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, | |
257 | const char *mdname, const char *props, | |
0e521004 | 258 | EVP_PKEY *pkey) |
d8c98d79 | 259 | { |
0e521004 | 260 | return do_sigver_init(ctx, pctx, NULL, mdname, props, NULL, pkey, 1); |
0f113f3e | 261 | } |
91c9e621 DSH |
262 | |
263 | int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, | |
0f113f3e MC |
264 | const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey) |
265 | { | |
0e521004 | 266 | return do_sigver_init(ctx, pctx, type, NULL, NULL, e, pkey, 1); |
d8c98d79 | 267 | } |
72df8f88 | 268 | #endif /* FIPS_MDOE */ |
d8c98d79 MC |
269 | |
270 | int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize) | |
271 | { | |
272 | EVP_PKEY_CTX *pctx = ctx->pctx; | |
273 | ||
274 | if (pctx == NULL | |
275 | || pctx->operation != EVP_PKEY_OP_SIGNCTX | |
276 | || pctx->op.sig.sigprovctx == NULL | |
277 | || pctx->op.sig.signature == NULL) | |
278 | goto legacy; | |
279 | ||
280 | return pctx->op.sig.signature->digest_sign_update(pctx->op.sig.sigprovctx, | |
281 | data, dsize); | |
282 | ||
283 | legacy: | |
284 | return EVP_DigestUpdate(ctx, data, dsize); | |
0f113f3e | 285 | } |
91c9e621 | 286 | |
d8c98d79 MC |
287 | int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data, size_t dsize) |
288 | { | |
289 | EVP_PKEY_CTX *pctx = ctx->pctx; | |
290 | ||
291 | if (pctx == NULL | |
292 | || pctx->operation != EVP_PKEY_OP_VERIFYCTX | |
293 | || pctx->op.sig.sigprovctx == NULL | |
294 | || pctx->op.sig.signature == NULL) | |
295 | goto legacy; | |
296 | ||
297 | return pctx->op.sig.signature->digest_verify_update(pctx->op.sig.sigprovctx, | |
298 | data, dsize); | |
299 | ||
300 | legacy: | |
301 | return EVP_DigestUpdate(ctx, data, dsize); | |
302 | } | |
303 | ||
72df8f88 | 304 | #ifndef FIPS_MODE |
0f113f3e MC |
305 | int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, |
306 | size_t *siglen) | |
307 | { | |
4c9b0a03 | 308 | int sctx = 0, r = 0; |
0f113f3e | 309 | EVP_PKEY_CTX *pctx = ctx->pctx; |
d8c98d79 MC |
310 | |
311 | if (pctx == NULL | |
312 | || pctx->operation != EVP_PKEY_OP_SIGNCTX | |
313 | || pctx->op.sig.sigprovctx == NULL | |
314 | || pctx->op.sig.signature == NULL) | |
315 | goto legacy; | |
316 | ||
317 | return pctx->op.sig.signature->digest_sign_final(pctx->op.sig.sigprovctx, | |
318 | sigret, siglen, SIZE_MAX); | |
319 | ||
320 | legacy: | |
8f020c3d RL |
321 | if (pctx == NULL || pctx->pmeth == NULL) { |
322 | ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); | |
323 | return 0; | |
324 | } | |
325 | ||
0f113f3e | 326 | if (pctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM) { |
8f020c3d | 327 | if (sigret == NULL) |
0f113f3e MC |
328 | return pctx->pmeth->signctx(pctx, sigret, siglen, ctx); |
329 | if (ctx->flags & EVP_MD_CTX_FLAG_FINALISE) | |
330 | r = pctx->pmeth->signctx(pctx, sigret, siglen, ctx); | |
331 | else { | |
8f020c3d RL |
332 | EVP_PKEY_CTX *dctx = EVP_PKEY_CTX_dup(pctx); |
333 | ||
334 | if (dctx == NULL) | |
0f113f3e MC |
335 | return 0; |
336 | r = dctx->pmeth->signctx(dctx, sigret, siglen, ctx); | |
337 | EVP_PKEY_CTX_free(dctx); | |
338 | } | |
339 | return r; | |
340 | } | |
8f020c3d | 341 | if (pctx->pmeth->signctx != NULL) |
0f113f3e MC |
342 | sctx = 1; |
343 | else | |
344 | sctx = 0; | |
8f020c3d | 345 | if (sigret != NULL) { |
0f113f3e | 346 | unsigned char md[EVP_MAX_MD_SIZE]; |
4c9b0a03 | 347 | unsigned int mdlen = 0; |
8f020c3d | 348 | |
0f113f3e MC |
349 | if (ctx->flags & EVP_MD_CTX_FLAG_FINALISE) { |
350 | if (sctx) | |
8f020c3d | 351 | r = pctx->pmeth->signctx(pctx, sigret, siglen, ctx); |
0f113f3e MC |
352 | else |
353 | r = EVP_DigestFinal_ex(ctx, md, &mdlen); | |
354 | } else { | |
bfb0641f | 355 | EVP_MD_CTX *tmp_ctx = EVP_MD_CTX_new(); |
8f020c3d | 356 | |
19546246 | 357 | if (tmp_ctx == NULL) |
0f113f3e | 358 | return 0; |
19546246 BE |
359 | if (!EVP_MD_CTX_copy_ex(tmp_ctx, ctx)) { |
360 | EVP_MD_CTX_free(tmp_ctx); | |
361 | return 0; | |
362 | } | |
0f113f3e | 363 | if (sctx) |
77a01145 RL |
364 | r = tmp_ctx->pctx->pmeth->signctx(tmp_ctx->pctx, |
365 | sigret, siglen, tmp_ctx); | |
0f113f3e | 366 | else |
77a01145 | 367 | r = EVP_DigestFinal_ex(tmp_ctx, md, &mdlen); |
bfb0641f | 368 | EVP_MD_CTX_free(tmp_ctx); |
0f113f3e MC |
369 | } |
370 | if (sctx || !r) | |
371 | return r; | |
8f020c3d | 372 | if (EVP_PKEY_sign(pctx, sigret, siglen, md, mdlen) <= 0) |
0f113f3e MC |
373 | return 0; |
374 | } else { | |
375 | if (sctx) { | |
376 | if (pctx->pmeth->signctx(pctx, sigret, siglen, ctx) <= 0) | |
377 | return 0; | |
378 | } else { | |
379 | int s = EVP_MD_size(ctx->digest); | |
8f020c3d | 380 | |
0f113f3e MC |
381 | if (s < 0 || EVP_PKEY_sign(pctx, sigret, siglen, NULL, s) <= 0) |
382 | return 0; | |
383 | } | |
384 | } | |
385 | return 1; | |
386 | } | |
91c9e621 | 387 | |
75394189 DSH |
388 | int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret, size_t *siglen, |
389 | const unsigned char *tbs, size_t tbslen) | |
390 | { | |
8f020c3d | 391 | if (ctx->pctx->pmeth != NULL && ctx->pctx->pmeth->digestsign != NULL) |
f723c98e | 392 | return ctx->pctx->pmeth->digestsign(ctx, sigret, siglen, tbs, tbslen); |
75394189 DSH |
393 | if (sigret != NULL && EVP_DigestSignUpdate(ctx, tbs, tbslen) <= 0) |
394 | return 0; | |
395 | return EVP_DigestSignFinal(ctx, sigret, siglen); | |
396 | } | |
397 | ||
0f7fa1b1 | 398 | int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig, |
0f113f3e MC |
399 | size_t siglen) |
400 | { | |
401 | unsigned char md[EVP_MAX_MD_SIZE]; | |
4c9b0a03 GK |
402 | int r = 0; |
403 | unsigned int mdlen = 0; | |
404 | int vctx = 0; | |
d8c98d79 MC |
405 | EVP_PKEY_CTX *pctx = ctx->pctx; |
406 | ||
407 | if (pctx == NULL | |
408 | || pctx->operation != EVP_PKEY_OP_VERIFYCTX | |
409 | || pctx->op.sig.sigprovctx == NULL | |
410 | || pctx->op.sig.signature == NULL) | |
411 | goto legacy; | |
412 | ||
413 | return pctx->op.sig.signature->digest_verify_final(pctx->op.sig.sigprovctx, | |
414 | sig, siglen); | |
0eab41fb | 415 | |
d8c98d79 | 416 | legacy: |
8f020c3d RL |
417 | if (pctx == NULL || pctx->pmeth == NULL) { |
418 | ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); | |
419 | return 0; | |
420 | } | |
421 | ||
422 | if (pctx->pmeth->verifyctx != NULL) | |
0f113f3e MC |
423 | vctx = 1; |
424 | else | |
425 | vctx = 0; | |
426 | if (ctx->flags & EVP_MD_CTX_FLAG_FINALISE) { | |
4803717f | 427 | if (vctx) |
8f020c3d | 428 | r = pctx->pmeth->verifyctx(pctx, sig, siglen, ctx); |
4803717f | 429 | else |
0f113f3e MC |
430 | r = EVP_DigestFinal_ex(ctx, md, &mdlen); |
431 | } else { | |
bfb0641f | 432 | EVP_MD_CTX *tmp_ctx = EVP_MD_CTX_new(); |
19546246 BE |
433 | if (tmp_ctx == NULL) |
434 | return -1; | |
435 | if (!EVP_MD_CTX_copy_ex(tmp_ctx, ctx)) { | |
436 | EVP_MD_CTX_free(tmp_ctx); | |
0f113f3e | 437 | return -1; |
19546246 | 438 | } |
4803717f | 439 | if (vctx) |
77a01145 RL |
440 | r = tmp_ctx->pctx->pmeth->verifyctx(tmp_ctx->pctx, |
441 | sig, siglen, tmp_ctx); | |
4803717f | 442 | else |
77a01145 | 443 | r = EVP_DigestFinal_ex(tmp_ctx, md, &mdlen); |
bfb0641f | 444 | EVP_MD_CTX_free(tmp_ctx); |
0f113f3e MC |
445 | } |
446 | if (vctx || !r) | |
447 | return r; | |
8f020c3d | 448 | return EVP_PKEY_verify(pctx, sig, siglen, md, mdlen); |
0f113f3e | 449 | } |
75394189 DSH |
450 | |
451 | int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret, | |
452 | size_t siglen, const unsigned char *tbs, size_t tbslen) | |
453 | { | |
8f020c3d | 454 | if (ctx->pctx->pmeth != NULL && ctx->pctx->pmeth->digestverify != NULL) |
f723c98e | 455 | return ctx->pctx->pmeth->digestverify(ctx, sigret, siglen, tbs, tbslen); |
75394189 DSH |
456 | if (EVP_DigestVerifyUpdate(ctx, tbs, tbslen) <= 0) |
457 | return -1; | |
458 | return EVP_DigestVerifyFinal(ctx, sigret, siglen); | |
459 | } | |
72df8f88 | 460 | #endif /* FIPS_MODE */ |