Fix Linux crash
[openssl.git] / engines / e_dasync.c
1 /* engines/e_dasync.c */
2 /*
3  * Written by Matt Caswell (matt@openssl.org) for the OpenSSL project.
4  */
5 /* ====================================================================
6  * Copyright (c) 2015 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  */
53
54 #include <stdio.h>
55 #include <string.h>
56
57 #include <openssl/engine.h>
58 #include <openssl/sha.h>
59 #include <openssl/rsa.h>
60 #include <openssl/evp.h>
61 #include <openssl/async.h>
62 #include <openssl/bn.h>
63
64 #define DASYNC_LIB_NAME "DASYNC"
65 #include "e_dasync_err.c"
66
67 /* Engine Id and Name */
68 static const char *engine_dasync_id = "dasync";
69 static const char *engine_dasync_name = "Dummy Async engine support";
70
71
72 /* Engine Lifetime functions */
73 static int dasync_destroy(ENGINE *e);
74 static int dasync_init(ENGINE *e);
75 static int dasync_finish(ENGINE *e);
76 void ENGINE_load_dasync(void);
77
78
79 /* Set up digests. Just SHA1 for now */
80 static int dasync_digests(ENGINE *e, const EVP_MD **digest,
81                           const int **nids, int nid);
82
83 static int dasync_digest_nids[] = { NID_sha1, 0 };
84
85 static void dummy_pause_job(void);
86
87 /* SHA1 */
88 static int digest_sha1_init(EVP_MD_CTX *ctx);
89 static int digest_sha1_update(EVP_MD_CTX *ctx, const void *data,
90                              unsigned long count);
91 static int digest_sha1_final(EVP_MD_CTX *ctx, unsigned char *md);
92
93 static const EVP_MD digest_sha1 = {
94     NID_sha1,
95     NID_sha1WithRSAEncryption,
96     SHA_DIGEST_LENGTH,
97     EVP_MD_FLAG_PKEY_METHOD_SIGNATURE | EVP_MD_FLAG_DIGALGID_ABSENT,
98     digest_sha1_init,
99     digest_sha1_update,
100     digest_sha1_final,
101     NULL,
102     NULL,
103     EVP_PKEY_NULL_method,
104     SHA_CBLOCK,
105     sizeof(EVP_MD *) + sizeof(SHA_CTX),
106 };
107
108 /* RSA */
109
110 static int dasync_pub_enc(int flen, const unsigned char *from,
111                     unsigned char *to, RSA *rsa, int padding);
112 static int dasync_pub_dec(int flen, const unsigned char *from,
113                     unsigned char *to, RSA *rsa, int padding);
114 static int dasync_rsa_priv_enc(int flen, const unsigned char *from,
115                       unsigned char *to, RSA *rsa, int padding);
116 static int dasync_rsa_priv_dec(int flen, const unsigned char *from,
117                       unsigned char *to, RSA *rsa, int padding);
118 static int dasync_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa,
119                               BN_CTX *ctx);
120
121 static int dasync_rsa_init(RSA *rsa);
122 static int dasync_rsa_finish(RSA *rsa);
123
124 static RSA_METHOD dasync_rsa_method = {
125     "Dummy Async RSA method",
126     dasync_pub_enc,             /* pub_enc */
127     dasync_pub_dec,             /* pub_dec */
128     dasync_rsa_priv_enc,        /* priv_enc */
129     dasync_rsa_priv_dec,        /* priv_dec */
130     dasync_rsa_mod_exp,         /* rsa_mod_exp */
131     BN_mod_exp_mont,            /* bn_mod_exp */
132     dasync_rsa_init,            /* init */
133     dasync_rsa_finish,          /* finish */
134     0,                          /* flags */
135     NULL,                       /* app_data */
136     0,                          /* rsa_sign */
137     0,                          /* rsa_verify */
138     NULL                        /* rsa_keygen */
139 };
140
141
142 static int bind_dasync(ENGINE *e)
143 {
144     /* Ensure the dasync error handling is set up */
145     ERR_load_DASYNC_strings();
146
147     if (!ENGINE_set_id(e, engine_dasync_id)
148         || !ENGINE_set_name(e, engine_dasync_name)
149         || !ENGINE_set_RSA(e, &dasync_rsa_method)
150         || !ENGINE_set_digests(e, dasync_digests)
151         || !ENGINE_set_destroy_function(e, dasync_destroy)
152         || !ENGINE_set_init_function(e, dasync_init)
153         || !ENGINE_set_finish_function(e, dasync_finish)) {
154         DASYNCerr(DASYNC_F_BIND_DASYNC, DASYNC_R_INIT_FAILED);
155         return 0;
156     }
157
158     return 1;
159 }
160
161 # ifndef OPENSSL_NO_DYNAMIC_ENGINE
162 static int bind_helper(ENGINE *e, const char *id)
163 {
164     if (id && (strcmp(id, engine_dasync_id) != 0))
165         return 0;
166     if (!bind_dasync(e))
167         return 0;
168     return 1;
169 }
170
171 IMPLEMENT_DYNAMIC_CHECK_FN()
172     IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
173 # endif
174
175 static ENGINE *engine_dasync(void)
176 {
177     ENGINE *ret = ENGINE_new();
178     if (!ret)
179         return NULL;
180     if (!bind_dasync(ret)) {
181         ENGINE_free(ret);
182         return NULL;
183     }
184     return ret;
185 }
186
187 void ENGINE_load_dasync(void)
188 {
189     ENGINE *toadd = engine_dasync();
190     if (!toadd)
191         return;
192     ENGINE_add(toadd);
193     ENGINE_free(toadd);
194     ERR_clear_error();
195 }
196
197 static int dasync_init(ENGINE *e)
198 {
199     return 1;
200 }
201
202
203 static int dasync_finish(ENGINE *e)
204 {
205     return 1;
206 }
207
208
209 static int dasync_destroy(ENGINE *e)
210 {
211     ERR_unload_DASYNC_strings();
212     return 1;
213 }
214
215 static int dasync_digests(ENGINE *e, const EVP_MD **digest,
216                           const int **nids, int nid)
217 {
218     int ok = 1;
219     if (!digest) {
220         /* We are returning a list of supported nids */
221         *nids = dasync_digest_nids;
222         return (sizeof(dasync_digest_nids) -
223                 1) / sizeof(dasync_digest_nids[0]);
224     }
225     /* We are being asked for a specific digest */
226     switch (nid) {
227     case NID_sha1:
228         *digest = &digest_sha1;
229         break;
230     default:
231         ok = 0;
232         *digest = NULL;
233         break;
234     }
235     return ok;
236 }
237
238 static void dummy_pause_job(void) {
239     ASYNC_JOB *job;
240
241     if ((job = ASYNC_get_current_job()) == NULL)
242         return;
243
244     /*
245      * In the Dummy async engine we are cheating. We signal that the job
246      * is complete by waking it before the call to ASYNC_pause_job(). A real
247      * async engine would only wake when the job was actually complete
248      */
249     ASYNC_wake(job);
250
251     /* Ignore errors - we carry on anyway */
252     ASYNC_pause_job();
253
254     ASYNC_clear_wake(job);
255 }
256
257
258 /*
259  * SHA1 implementation. At the moment we just defer to the standard
260  * implementation
261  */
262 #undef data
263 #define data(ctx) ((SHA_CTX *)(ctx)->md_data)
264 static int digest_sha1_init(EVP_MD_CTX *ctx)
265 {
266     dummy_pause_job();
267
268     return SHA1_Init(data(ctx));
269 }
270
271 static int digest_sha1_update(EVP_MD_CTX *ctx, const void *data,
272                              unsigned long count)
273 {
274     dummy_pause_job();
275
276     return SHA1_Update(data(ctx), data, (size_t)count);
277 }
278
279 static int digest_sha1_final(EVP_MD_CTX *ctx, unsigned char *md)
280 {
281     dummy_pause_job();
282
283     return SHA1_Final(md, data(ctx));
284 }
285
286 /*
287  * RSA implementation
288  */
289
290 static int dasync_pub_enc(int flen, const unsigned char *from,
291                     unsigned char *to, RSA *rsa, int padding) {
292     /* Ignore errors - we carry on anyway */
293     dummy_pause_job();
294     return RSA_PKCS1_OpenSSL()->rsa_pub_enc(flen, from, to, rsa, padding);
295 }
296
297 static int dasync_pub_dec(int flen, const unsigned char *from,
298                     unsigned char *to, RSA *rsa, int padding) {
299     /* Ignore errors - we carry on anyway */
300     dummy_pause_job();
301     return RSA_PKCS1_OpenSSL()->rsa_pub_dec(flen, from, to, rsa, padding);
302 }
303
304 static int dasync_rsa_priv_enc(int flen, const unsigned char *from,
305                       unsigned char *to, RSA *rsa, int padding)
306 {
307     /* Ignore errors - we carry on anyway */
308     dummy_pause_job();
309     return RSA_PKCS1_OpenSSL()->rsa_priv_enc(flen, from, to, rsa, padding);
310 }
311
312 static int dasync_rsa_priv_dec(int flen, const unsigned char *from,
313                       unsigned char *to, RSA *rsa, int padding)
314 {
315     /* Ignore errors - we carry on anyway */
316     dummy_pause_job();
317     return RSA_PKCS1_OpenSSL()->rsa_priv_dec(flen, from, to, rsa, padding);
318 }
319
320 static int dasync_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
321 {
322     /* Ignore errors - we carry on anyway */
323     dummy_pause_job();
324     return RSA_PKCS1_OpenSSL()->rsa_mod_exp(r0, I, rsa, ctx);
325 }
326
327 static int dasync_rsa_init(RSA *rsa)
328 {
329     return RSA_PKCS1_OpenSSL()->init(rsa);
330 }
331 static int dasync_rsa_finish(RSA *rsa)
332 {
333     return RSA_PKCS1_OpenSSL()->finish(rsa);
334 }