1 /* Written by Dr Stephen N Henson ([email protected]) for the OpenSSL
2 * project 2006.
3 */
4 /* ====================================================================
5 * Copyright (c) 2006,2007 The OpenSSL Project. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 *
19 * 3. All advertising materials mentioning features or use of this
20 * software must display the following acknowledgment:
21 * "This product includes software developed by the OpenSSL Project
22 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
23 *
24 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
25 * endorse or promote products derived from this software without
26 * prior written permission. For written permission, please contact
27 * [email protected].
28 *
29 * 5. Products derived from this software may not be called "OpenSSL"
30 * nor may "OpenSSL" appear in their names without prior written
31 * permission of the OpenSSL Project.
32 *
33 * 6. Redistributions of any form whatsoever must retain the following
34 * acknowledgment:
35 * "This product includes software developed by the OpenSSL Project
36 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
37 *
38 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
39 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
41 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
42 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
47 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
49 * OF THE POSSIBILITY OF SUCH DAMAGE.
50 * ====================================================================
51 *
52 * This product includes cryptographic software written by Eric Young
53 * ([email protected]). This product includes software written by Tim
54 * Hudson ([email protected]). */
55
56 #include <openssl/evp.h>
57
58 #include <openssl/err.h>
59
60 #include "../../evp/internal.h"
61 #include "../delocate.h"
62 #include "../digest/internal.h"
63 #include "../service_indicator/internal.h"
64
65
66 enum evp_sign_verify_t {
67 evp_sign,
68 evp_verify,
69 };
70
DEFINE_LOCAL_DATA(struct evp_md_pctx_ops,md_pctx_ops)71 DEFINE_LOCAL_DATA(struct evp_md_pctx_ops, md_pctx_ops) {
72 out->free = EVP_PKEY_CTX_free;
73 out->dup = EVP_PKEY_CTX_dup;
74 };
75
uses_prehash(EVP_MD_CTX * ctx,enum evp_sign_verify_t op)76 static int uses_prehash(EVP_MD_CTX *ctx, enum evp_sign_verify_t op) {
77 return (op == evp_sign) ? (ctx->pctx->pmeth->sign != NULL)
78 : (ctx->pctx->pmeth->verify != NULL);
79 }
80
do_sigver_init(EVP_MD_CTX * ctx,EVP_PKEY_CTX ** pctx,const EVP_MD * type,ENGINE * e,EVP_PKEY * pkey,enum evp_sign_verify_t op)81 static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
82 const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey,
83 enum evp_sign_verify_t op) {
84 if (ctx->pctx == NULL) {
85 ctx->pctx = EVP_PKEY_CTX_new(pkey, e);
86 }
87 if (ctx->pctx == NULL) {
88 return 0;
89 }
90 ctx->pctx_ops = md_pctx_ops();
91
92 if (op == evp_verify) {
93 if (!EVP_PKEY_verify_init(ctx->pctx)) {
94 return 0;
95 }
96 } else {
97 if (!EVP_PKEY_sign_init(ctx->pctx)) {
98 return 0;
99 }
100 }
101
102 if (type != NULL &&
103 !EVP_PKEY_CTX_set_signature_md(ctx->pctx, type)) {
104 return 0;
105 }
106
107 if (uses_prehash(ctx, op)) {
108 if (type == NULL) {
109 OPENSSL_PUT_ERROR(EVP, EVP_R_NO_DEFAULT_DIGEST);
110 return 0;
111 }
112 if (!EVP_DigestInit_ex(ctx, type, e)) {
113 return 0;
114 }
115 }
116
117 if (pctx) {
118 *pctx = ctx->pctx;
119 }
120 return 1;
121 }
122
EVP_DigestSignInit(EVP_MD_CTX * ctx,EVP_PKEY_CTX ** pctx,const EVP_MD * type,ENGINE * e,EVP_PKEY * pkey)123 int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, const EVP_MD *type,
124 ENGINE *e, EVP_PKEY *pkey) {
125 return do_sigver_init(ctx, pctx, type, e, pkey, evp_sign);
126 }
127
EVP_DigestVerifyInit(EVP_MD_CTX * ctx,EVP_PKEY_CTX ** pctx,const EVP_MD * type,ENGINE * e,EVP_PKEY * pkey)128 int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
129 const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey) {
130 return do_sigver_init(ctx, pctx, type, e, pkey, evp_verify);
131 }
132
EVP_DigestSignUpdate(EVP_MD_CTX * ctx,const void * data,size_t len)133 int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *data, size_t len) {
134 if (!uses_prehash(ctx, evp_sign)) {
135 OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
136 return 0;
137 }
138
139 return EVP_DigestUpdate(ctx, data, len);
140 }
141
EVP_DigestVerifyUpdate(EVP_MD_CTX * ctx,const void * data,size_t len)142 int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data, size_t len) {
143 if (!uses_prehash(ctx, evp_verify)) {
144 OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
145 return 0;
146 }
147
148 return EVP_DigestUpdate(ctx, data, len);
149 }
150
EVP_DigestSignFinal(EVP_MD_CTX * ctx,uint8_t * out_sig,size_t * out_sig_len)151 int EVP_DigestSignFinal(EVP_MD_CTX *ctx, uint8_t *out_sig,
152 size_t *out_sig_len) {
153 if (!uses_prehash(ctx, evp_sign)) {
154 OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
155 return 0;
156 }
157
158 if (out_sig) {
159 EVP_MD_CTX tmp_ctx;
160 int ret;
161 uint8_t md[EVP_MAX_MD_SIZE];
162 unsigned int mdlen;
163
164 FIPS_service_indicator_lock_state();
165 EVP_MD_CTX_init(&tmp_ctx);
166 ret = EVP_MD_CTX_copy_ex(&tmp_ctx, ctx) &&
167 EVP_DigestFinal_ex(&tmp_ctx, md, &mdlen) &&
168 EVP_PKEY_sign(ctx->pctx, out_sig, out_sig_len, md, mdlen);
169 EVP_MD_CTX_cleanup(&tmp_ctx);
170 FIPS_service_indicator_unlock_state();
171
172 if (ret) {
173 EVP_DigestSign_verify_service_indicator(ctx);
174 }
175
176 return ret;
177 } else {
178 size_t s = EVP_MD_size(ctx->digest);
179 return EVP_PKEY_sign(ctx->pctx, out_sig, out_sig_len, NULL, s);
180 }
181 }
182
EVP_DigestVerifyFinal(EVP_MD_CTX * ctx,const uint8_t * sig,size_t sig_len)183 int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const uint8_t *sig,
184 size_t sig_len) {
185 if (!uses_prehash(ctx, evp_verify)) {
186 OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
187 return 0;
188 }
189
190 EVP_MD_CTX tmp_ctx;
191 int ret;
192 uint8_t md[EVP_MAX_MD_SIZE];
193 unsigned int mdlen;
194
195 FIPS_service_indicator_lock_state();
196 EVP_MD_CTX_init(&tmp_ctx);
197 ret = EVP_MD_CTX_copy_ex(&tmp_ctx, ctx) &&
198 EVP_DigestFinal_ex(&tmp_ctx, md, &mdlen) &&
199 EVP_PKEY_verify(ctx->pctx, sig, sig_len, md, mdlen);
200 FIPS_service_indicator_unlock_state();
201 EVP_MD_CTX_cleanup(&tmp_ctx);
202
203 if (ret) {
204 EVP_DigestVerify_verify_service_indicator(ctx);
205 }
206
207 return ret;
208 }
209
EVP_DigestSign(EVP_MD_CTX * ctx,uint8_t * out_sig,size_t * out_sig_len,const uint8_t * data,size_t data_len)210 int EVP_DigestSign(EVP_MD_CTX *ctx, uint8_t *out_sig, size_t *out_sig_len,
211 const uint8_t *data, size_t data_len) {
212 FIPS_service_indicator_lock_state();
213 int ret = 0;
214
215 if (uses_prehash(ctx, evp_sign)) {
216 // If |out_sig| is NULL, the caller is only querying the maximum output
217 // length. |data| should only be incorporated in the final call.
218 if (out_sig != NULL &&
219 !EVP_DigestSignUpdate(ctx, data, data_len)) {
220 goto end;
221 }
222
223 ret = EVP_DigestSignFinal(ctx, out_sig, out_sig_len);
224 goto end;
225 }
226
227 if (ctx->pctx->pmeth->sign_message == NULL) {
228 OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
229 goto end;
230 }
231
232 ret = ctx->pctx->pmeth->sign_message(ctx->pctx, out_sig, out_sig_len, data,
233 data_len);
234
235 end:
236 FIPS_service_indicator_unlock_state();
237 if (ret) {
238 EVP_DigestSign_verify_service_indicator(ctx);
239 }
240 return ret;
241 }
242
EVP_DigestVerify(EVP_MD_CTX * ctx,const uint8_t * sig,size_t sig_len,const uint8_t * data,size_t len)243 int EVP_DigestVerify(EVP_MD_CTX *ctx, const uint8_t *sig, size_t sig_len,
244 const uint8_t *data, size_t len) {
245 FIPS_service_indicator_lock_state();
246 int ret = 0;
247
248 if (uses_prehash(ctx, evp_verify)) {
249 ret = EVP_DigestVerifyUpdate(ctx, data, len) &&
250 EVP_DigestVerifyFinal(ctx, sig, sig_len);
251 goto end;
252 }
253
254 if (ctx->pctx->pmeth->verify_message == NULL) {
255 OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
256 goto end;
257 }
258
259 ret = ctx->pctx->pmeth->verify_message(ctx->pctx, sig, sig_len, data, len);
260
261 end:
262 FIPS_service_indicator_unlock_state();
263 if (ret) {
264 EVP_DigestVerify_verify_service_indicator(ctx);
265 }
266 return ret;
267 }
268