]>
Commit | Line | Data |
---|---|---|
a14e9ff7 | 1 | /* |
48e5119a | 2 | * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. |
a14e9ff7 | 3 | * |
ab3fa1c0 | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
440e5d80 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 | |
a14e9ff7 MC |
8 | */ |
9 | ||
85d843c8 P |
10 | /* |
11 | * SHA-1 low level APIs are deprecated for public use, but still ok for | |
12 | * internal use. Note, that due to symbols not being exported, only the | |
13 | * #defines and strucures can be accessed, in this case SHA_CBLOCK and | |
14 | * sizeof(SHA_CTX). | |
15 | */ | |
16 | #include "internal/deprecated.h" | |
17 | ||
f1f5ee17 AP |
18 | #if defined(_WIN32) |
19 | # include <windows.h> | |
20 | #endif | |
21 | ||
a14e9ff7 MC |
22 | #include <stdio.h> |
23 | #include <string.h> | |
24 | ||
25 | #include <openssl/engine.h> | |
26 | #include <openssl/sha.h> | |
2f2c9caa | 27 | #include <openssl/aes.h> |
a14e9ff7 MC |
28 | #include <openssl/rsa.h> |
29 | #include <openssl/evp.h> | |
30 | #include <openssl/async.h> | |
31 | #include <openssl/bn.h> | |
7b9f8f7f | 32 | #include <openssl/crypto.h> |
98ee7543 MC |
33 | #include <openssl/ssl.h> |
34 | #include <openssl/modes.h> | |
a14e9ff7 | 35 | |
6ce66ce0 | 36 | #if defined(OPENSSL_SYS_UNIX) && defined(OPENSSL_THREADS) |
ff75a257 MC |
37 | # undef ASYNC_POSIX |
38 | # define ASYNC_POSIX | |
39 | # include <unistd.h> | |
40 | #elif defined(_WIN32) | |
41 | # undef ASYNC_WIN | |
42 | # define ASYNC_WIN | |
ff75a257 MC |
43 | #endif |
44 | ||
a14e9ff7 MC |
45 | #include "e_dasync_err.c" |
46 | ||
47 | /* Engine Id and Name */ | |
48 | static const char *engine_dasync_id = "dasync"; | |
49 | static const char *engine_dasync_name = "Dummy Async engine support"; | |
50 | ||
51 | ||
52 | /* Engine Lifetime functions */ | |
53 | static int dasync_destroy(ENGINE *e); | |
54 | static int dasync_init(ENGINE *e); | |
55 | static int dasync_finish(ENGINE *e); | |
b3599dbb | 56 | void engine_load_dasync_int(void); |
a14e9ff7 MC |
57 | |
58 | ||
59 | /* Set up digests. Just SHA1 for now */ | |
60 | static int dasync_digests(ENGINE *e, const EVP_MD **digest, | |
61 | const int **nids, int nid); | |
62 | ||
f4da39d2 | 63 | static void dummy_pause_job(void); |
a14e9ff7 MC |
64 | |
65 | /* SHA1 */ | |
46a283c0 MC |
66 | static int dasync_sha1_init(EVP_MD_CTX *ctx); |
67 | static int dasync_sha1_update(EVP_MD_CTX *ctx, const void *data, | |
652d4a8c | 68 | size_t count); |
46a283c0 | 69 | static int dasync_sha1_final(EVP_MD_CTX *ctx, unsigned char *md); |
a14e9ff7 | 70 | |
11780ac3 MC |
71 | /* |
72 | * Holds the EVP_MD object for sha1 in this engine. Set up once only during | |
73 | * engine bind and can then be reused many times. | |
74 | */ | |
cddcea8c RL |
75 | static EVP_MD *_hidden_sha1_md = NULL; |
76 | static const EVP_MD *dasync_sha1(void) | |
77 | { | |
cddcea8c RL |
78 | return _hidden_sha1_md; |
79 | } | |
80 | static void destroy_digests(void) | |
81 | { | |
82 | EVP_MD_meth_free(_hidden_sha1_md); | |
83 | _hidden_sha1_md = NULL; | |
84 | } | |
11780ac3 | 85 | |
cddcea8c RL |
86 | static int dasync_digest_nids(const int **nids) |
87 | { | |
88 | static int digest_nids[2] = { 0, 0 }; | |
89 | static int pos = 0; | |
90 | static int init = 0; | |
91 | ||
92 | if (!init) { | |
93 | const EVP_MD *md; | |
94 | if ((md = dasync_sha1()) != NULL) | |
95 | digest_nids[pos++] = EVP_MD_type(md); | |
96 | digest_nids[pos] = 0; | |
97 | init = 1; | |
98 | } | |
99 | *nids = digest_nids; | |
100 | return pos; | |
101 | } | |
a14e9ff7 MC |
102 | |
103 | /* RSA */ | |
104 | ||
105 | static int dasync_pub_enc(int flen, const unsigned char *from, | |
106 | unsigned char *to, RSA *rsa, int padding); | |
107 | static int dasync_pub_dec(int flen, const unsigned char *from, | |
108 | unsigned char *to, RSA *rsa, int padding); | |
109 | static int dasync_rsa_priv_enc(int flen, const unsigned char *from, | |
110 | unsigned char *to, RSA *rsa, int padding); | |
111 | static int dasync_rsa_priv_dec(int flen, const unsigned char *from, | |
112 | unsigned char *to, RSA *rsa, int padding); | |
113 | static int dasync_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, | |
114 | BN_CTX *ctx); | |
115 | ||
116 | static int dasync_rsa_init(RSA *rsa); | |
117 | static int dasync_rsa_finish(RSA *rsa); | |
118 | ||
b72c9121 | 119 | static RSA_METHOD *dasync_rsa_method = NULL; |
a14e9ff7 | 120 | |
98ee7543 MC |
121 | /* AES */ |
122 | ||
123 | static int dasync_aes128_cbc_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, | |
124 | void *ptr); | |
98ee7543 MC |
125 | static int dasync_aes128_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, |
126 | const unsigned char *iv, int enc); | |
98ee7543 MC |
127 | static int dasync_aes128_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, |
128 | const unsigned char *in, size_t inl); | |
98ee7543 MC |
129 | static int dasync_aes128_cbc_cleanup(EVP_CIPHER_CTX *ctx); |
130 | ||
2f2c9caa MC |
131 | static int dasync_aes128_cbc_hmac_sha1_ctrl(EVP_CIPHER_CTX *ctx, int type, |
132 | int arg, void *ptr); | |
133 | static int dasync_aes128_cbc_hmac_sha1_init_key(EVP_CIPHER_CTX *ctx, | |
134 | const unsigned char *key, | |
135 | const unsigned char *iv, | |
136 | int enc); | |
137 | static int dasync_aes128_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, | |
138 | unsigned char *out, | |
139 | const unsigned char *in, | |
140 | size_t inl); | |
141 | static int dasync_aes128_cbc_hmac_sha1_cleanup(EVP_CIPHER_CTX *ctx); | |
142 | ||
e38c2e85 | 143 | struct dasync_pipeline_ctx { |
98ee7543 | 144 | void *inner_cipher_data; |
98ee7543 MC |
145 | unsigned int numpipes; |
146 | unsigned char **inbufs; | |
147 | unsigned char **outbufs; | |
148 | size_t *lens; | |
2f2c9caa MC |
149 | unsigned char tlsaad[SSL_MAX_PIPELINES][EVP_AEAD_TLS1_AAD_LEN]; |
150 | unsigned int aadctr; | |
98ee7543 MC |
151 | }; |
152 | ||
11780ac3 MC |
153 | /* |
154 | * Holds the EVP_CIPHER object for aes_128_cbc in this engine. Set up once only | |
155 | * during engine bind and can then be reused many times. | |
156 | */ | |
98ee7543 MC |
157 | static EVP_CIPHER *_hidden_aes_128_cbc = NULL; |
158 | static const EVP_CIPHER *dasync_aes_128_cbc(void) | |
159 | { | |
11780ac3 MC |
160 | return _hidden_aes_128_cbc; |
161 | } | |
162 | ||
163 | /* | |
164 | * Holds the EVP_CIPHER object for aes_128_cbc_hmac_sha1 in this engine. Set up | |
165 | * once only during engine bind and can then be reused many times. | |
a4a0a1eb DMSP |
166 | * |
167 | * This 'stitched' cipher depends on the EVP_aes_128_cbc_hmac_sha1() cipher, | |
168 | * which is implemented only if the AES-NI instruction set extension is available | |
169 | * (see OPENSSL_IA32CAP(3)). If that's not the case, then this cipher will not | |
170 | * be available either. | |
171 | * | |
172 | * Note: Since it is a legacy mac-then-encrypt cipher, modern TLS peers (which | |
173 | * negotiate the encrypt-then-mac extension) won't negotiate it anyway. | |
11780ac3 MC |
174 | */ |
175 | static EVP_CIPHER *_hidden_aes_128_cbc_hmac_sha1 = NULL; | |
176 | static const EVP_CIPHER *dasync_aes_128_cbc_hmac_sha1(void) | |
177 | { | |
178 | return _hidden_aes_128_cbc_hmac_sha1; | |
179 | } | |
180 | ||
181 | static void destroy_ciphers(void) | |
182 | { | |
183 | EVP_CIPHER_meth_free(_hidden_aes_128_cbc); | |
184 | EVP_CIPHER_meth_free(_hidden_aes_128_cbc_hmac_sha1); | |
185 | _hidden_aes_128_cbc = NULL; | |
186 | _hidden_aes_128_cbc_hmac_sha1 = NULL; | |
187 | } | |
188 | ||
189 | static int dasync_ciphers(ENGINE *e, const EVP_CIPHER **cipher, | |
190 | const int **nids, int nid); | |
191 | ||
192 | static int dasync_cipher_nids[] = { | |
193 | NID_aes_128_cbc, | |
194 | NID_aes_128_cbc_hmac_sha1, | |
195 | 0 | |
196 | }; | |
197 | ||
198 | static int bind_dasync(ENGINE *e) | |
199 | { | |
b72c9121 RL |
200 | /* Setup RSA_METHOD */ |
201 | if ((dasync_rsa_method = RSA_meth_new("Dummy Async RSA method", 0)) == NULL | |
202 | || RSA_meth_set_pub_enc(dasync_rsa_method, dasync_pub_enc) == 0 | |
203 | || RSA_meth_set_pub_dec(dasync_rsa_method, dasync_pub_dec) == 0 | |
204 | || RSA_meth_set_priv_enc(dasync_rsa_method, dasync_rsa_priv_enc) == 0 | |
8aac5d2e | 205 | || RSA_meth_set_priv_dec(dasync_rsa_method, dasync_rsa_priv_dec) == 0 |
b72c9121 RL |
206 | || RSA_meth_set_mod_exp(dasync_rsa_method, dasync_rsa_mod_exp) == 0 |
207 | || RSA_meth_set_bn_mod_exp(dasync_rsa_method, BN_mod_exp_mont) == 0 | |
208 | || RSA_meth_set_init(dasync_rsa_method, dasync_rsa_init) == 0 | |
209 | || RSA_meth_set_finish(dasync_rsa_method, dasync_rsa_finish) == 0) { | |
210 | DASYNCerr(DASYNC_F_BIND_DASYNC, DASYNC_R_INIT_FAILED); | |
211 | return 0; | |
212 | } | |
213 | ||
11780ac3 MC |
214 | /* Ensure the dasync error handling is set up */ |
215 | ERR_load_DASYNC_strings(); | |
216 | ||
217 | if (!ENGINE_set_id(e, engine_dasync_id) | |
218 | || !ENGINE_set_name(e, engine_dasync_name) | |
b72c9121 | 219 | || !ENGINE_set_RSA(e, dasync_rsa_method) |
11780ac3 MC |
220 | || !ENGINE_set_digests(e, dasync_digests) |
221 | || !ENGINE_set_ciphers(e, dasync_ciphers) | |
222 | || !ENGINE_set_destroy_function(e, dasync_destroy) | |
223 | || !ENGINE_set_init_function(e, dasync_init) | |
224 | || !ENGINE_set_finish_function(e, dasync_finish)) { | |
225 | DASYNCerr(DASYNC_F_BIND_DASYNC, DASYNC_R_INIT_FAILED); | |
226 | return 0; | |
227 | } | |
228 | ||
229 | /* | |
230 | * Set up the EVP_CIPHER and EVP_MD objects for the ciphers/digests | |
231 | * supplied by this engine | |
232 | */ | |
233 | _hidden_sha1_md = EVP_MD_meth_new(NID_sha1, NID_sha1WithRSAEncryption); | |
234 | if (_hidden_sha1_md == NULL | |
235 | || !EVP_MD_meth_set_result_size(_hidden_sha1_md, SHA_DIGEST_LENGTH) | |
236 | || !EVP_MD_meth_set_input_blocksize(_hidden_sha1_md, SHA_CBLOCK) | |
237 | || !EVP_MD_meth_set_app_datasize(_hidden_sha1_md, | |
238 | sizeof(EVP_MD *) + sizeof(SHA_CTX)) | |
239 | || !EVP_MD_meth_set_flags(_hidden_sha1_md, EVP_MD_FLAG_DIGALGID_ABSENT) | |
240 | || !EVP_MD_meth_set_init(_hidden_sha1_md, dasync_sha1_init) | |
241 | || !EVP_MD_meth_set_update(_hidden_sha1_md, dasync_sha1_update) | |
242 | || !EVP_MD_meth_set_final(_hidden_sha1_md, dasync_sha1_final)) { | |
243 | EVP_MD_meth_free(_hidden_sha1_md); | |
244 | _hidden_sha1_md = NULL; | |
245 | } | |
246 | ||
247 | _hidden_aes_128_cbc = EVP_CIPHER_meth_new(NID_aes_128_cbc, | |
248 | 16 /* block size */, | |
249 | 16 /* key len */); | |
98ee7543 MC |
250 | if (_hidden_aes_128_cbc == NULL |
251 | || !EVP_CIPHER_meth_set_iv_length(_hidden_aes_128_cbc,16) | |
252 | || !EVP_CIPHER_meth_set_flags(_hidden_aes_128_cbc, | |
253 | EVP_CIPH_FLAG_DEFAULT_ASN1 | |
254 | | EVP_CIPH_CBC_MODE | |
255 | | EVP_CIPH_FLAG_PIPELINE) | |
256 | || !EVP_CIPHER_meth_set_init(_hidden_aes_128_cbc, | |
257 | dasync_aes128_init_key) | |
258 | || !EVP_CIPHER_meth_set_do_cipher(_hidden_aes_128_cbc, | |
259 | dasync_aes128_cbc_cipher) | |
260 | || !EVP_CIPHER_meth_set_cleanup(_hidden_aes_128_cbc, | |
261 | dasync_aes128_cbc_cleanup) | |
262 | || !EVP_CIPHER_meth_set_ctrl(_hidden_aes_128_cbc, | |
263 | dasync_aes128_cbc_ctrl) | |
264 | || !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_aes_128_cbc, | |
e38c2e85 | 265 | sizeof(struct dasync_pipeline_ctx))) { |
98ee7543 MC |
266 | EVP_CIPHER_meth_free(_hidden_aes_128_cbc); |
267 | _hidden_aes_128_cbc = NULL; | |
268 | } | |
98ee7543 | 269 | |
11780ac3 MC |
270 | _hidden_aes_128_cbc_hmac_sha1 = EVP_CIPHER_meth_new( |
271 | NID_aes_128_cbc_hmac_sha1, | |
272 | 16 /* block size */, | |
273 | 16 /* key len */); | |
2f2c9caa MC |
274 | if (_hidden_aes_128_cbc_hmac_sha1 == NULL |
275 | || !EVP_CIPHER_meth_set_iv_length(_hidden_aes_128_cbc_hmac_sha1,16) | |
276 | || !EVP_CIPHER_meth_set_flags(_hidden_aes_128_cbc_hmac_sha1, | |
277 | EVP_CIPH_CBC_MODE | |
278 | | EVP_CIPH_FLAG_DEFAULT_ASN1 | |
279 | | EVP_CIPH_FLAG_AEAD_CIPHER | |
280 | | EVP_CIPH_FLAG_PIPELINE) | |
281 | || !EVP_CIPHER_meth_set_init(_hidden_aes_128_cbc_hmac_sha1, | |
282 | dasync_aes128_cbc_hmac_sha1_init_key) | |
283 | || !EVP_CIPHER_meth_set_do_cipher(_hidden_aes_128_cbc_hmac_sha1, | |
284 | dasync_aes128_cbc_hmac_sha1_cipher) | |
285 | || !EVP_CIPHER_meth_set_cleanup(_hidden_aes_128_cbc_hmac_sha1, | |
286 | dasync_aes128_cbc_hmac_sha1_cleanup) | |
287 | || !EVP_CIPHER_meth_set_ctrl(_hidden_aes_128_cbc_hmac_sha1, | |
288 | dasync_aes128_cbc_hmac_sha1_ctrl) | |
289 | || !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_aes_128_cbc_hmac_sha1, | |
e38c2e85 | 290 | sizeof(struct dasync_pipeline_ctx))) { |
2f2c9caa MC |
291 | EVP_CIPHER_meth_free(_hidden_aes_128_cbc_hmac_sha1); |
292 | _hidden_aes_128_cbc_hmac_sha1 = NULL; | |
293 | } | |
a14e9ff7 MC |
294 | |
295 | return 1; | |
296 | } | |
297 | ||
298 | # ifndef OPENSSL_NO_DYNAMIC_ENGINE | |
299 | static int bind_helper(ENGINE *e, const char *id) | |
300 | { | |
301 | if (id && (strcmp(id, engine_dasync_id) != 0)) | |
302 | return 0; | |
303 | if (!bind_dasync(e)) | |
304 | return 0; | |
305 | return 1; | |
306 | } | |
307 | ||
308 | IMPLEMENT_DYNAMIC_CHECK_FN() | |
309 | IMPLEMENT_DYNAMIC_BIND_FN(bind_helper) | |
310 | # endif | |
311 | ||
312 | static ENGINE *engine_dasync(void) | |
313 | { | |
314 | ENGINE *ret = ENGINE_new(); | |
315 | if (!ret) | |
316 | return NULL; | |
317 | if (!bind_dasync(ret)) { | |
318 | ENGINE_free(ret); | |
319 | return NULL; | |
320 | } | |
321 | return ret; | |
322 | } | |
323 | ||
b3599dbb | 324 | void engine_load_dasync_int(void) |
a14e9ff7 MC |
325 | { |
326 | ENGINE *toadd = engine_dasync(); | |
327 | if (!toadd) | |
328 | return; | |
329 | ENGINE_add(toadd); | |
330 | ENGINE_free(toadd); | |
331 | ERR_clear_error(); | |
332 | } | |
333 | ||
334 | static int dasync_init(ENGINE *e) | |
335 | { | |
336 | return 1; | |
337 | } | |
338 | ||
339 | ||
340 | static int dasync_finish(ENGINE *e) | |
341 | { | |
342 | return 1; | |
343 | } | |
344 | ||
345 | ||
346 | static int dasync_destroy(ENGINE *e) | |
347 | { | |
cddcea8c | 348 | destroy_digests(); |
11780ac3 | 349 | destroy_ciphers(); |
b72c9121 | 350 | RSA_meth_free(dasync_rsa_method); |
a14e9ff7 MC |
351 | ERR_unload_DASYNC_strings(); |
352 | return 1; | |
353 | } | |
354 | ||
355 | static int dasync_digests(ENGINE *e, const EVP_MD **digest, | |
356 | const int **nids, int nid) | |
357 | { | |
358 | int ok = 1; | |
359 | if (!digest) { | |
360 | /* We are returning a list of supported nids */ | |
cddcea8c | 361 | return dasync_digest_nids(nids); |
a14e9ff7 MC |
362 | } |
363 | /* We are being asked for a specific digest */ | |
364 | switch (nid) { | |
365 | case NID_sha1: | |
cddcea8c | 366 | *digest = dasync_sha1(); |
a14e9ff7 MC |
367 | break; |
368 | default: | |
369 | ok = 0; | |
370 | *digest = NULL; | |
371 | break; | |
372 | } | |
373 | return ok; | |
374 | } | |
375 | ||
98ee7543 MC |
376 | static int dasync_ciphers(ENGINE *e, const EVP_CIPHER **cipher, |
377 | const int **nids, int nid) | |
378 | { | |
379 | int ok = 1; | |
11780ac3 | 380 | if (cipher == NULL) { |
98ee7543 MC |
381 | /* We are returning a list of supported nids */ |
382 | *nids = dasync_cipher_nids; | |
383 | return (sizeof(dasync_cipher_nids) - | |
384 | 1) / sizeof(dasync_cipher_nids[0]); | |
385 | } | |
386 | /* We are being asked for a specific cipher */ | |
387 | switch (nid) { | |
388 | case NID_aes_128_cbc: | |
389 | *cipher = dasync_aes_128_cbc(); | |
390 | break; | |
2f2c9caa MC |
391 | case NID_aes_128_cbc_hmac_sha1: |
392 | *cipher = dasync_aes_128_cbc_hmac_sha1(); | |
393 | break; | |
98ee7543 MC |
394 | default: |
395 | ok = 0; | |
396 | *cipher = NULL; | |
397 | break; | |
398 | } | |
399 | return ok; | |
400 | } | |
401 | ||
ff75a257 MC |
402 | static void wait_cleanup(ASYNC_WAIT_CTX *ctx, const void *key, |
403 | OSSL_ASYNC_FD readfd, void *pvwritefd) | |
404 | { | |
405 | OSSL_ASYNC_FD *pwritefd = (OSSL_ASYNC_FD *)pvwritefd; | |
406 | #if defined(ASYNC_WIN) | |
407 | CloseHandle(readfd); | |
408 | CloseHandle(*pwritefd); | |
409 | #elif defined(ASYNC_POSIX) | |
410 | close(readfd); | |
411 | close(*pwritefd); | |
412 | #endif | |
413 | OPENSSL_free(pwritefd); | |
414 | } | |
415 | ||
416 | #define DUMMY_CHAR 'X' | |
417 | ||
f4da39d2 MC |
418 | static void dummy_pause_job(void) { |
419 | ASYNC_JOB *job; | |
ff75a257 | 420 | ASYNC_WAIT_CTX *waitctx; |
9f5a87fd PY |
421 | ASYNC_callback_fn callback; |
422 | void * callback_arg; | |
ff75a257 MC |
423 | OSSL_ASYNC_FD pipefds[2] = {0, 0}; |
424 | OSSL_ASYNC_FD *writefd; | |
425 | #if defined(ASYNC_WIN) | |
426 | DWORD numwritten, numread; | |
427 | char buf = DUMMY_CHAR; | |
428 | #elif defined(ASYNC_POSIX) | |
429 | char buf = DUMMY_CHAR; | |
430 | #endif | |
f4da39d2 MC |
431 | |
432 | if ((job = ASYNC_get_current_job()) == NULL) | |
433 | return; | |
434 | ||
ff75a257 MC |
435 | waitctx = ASYNC_get_wait_ctx(job); |
436 | ||
9f5a87fd PY |
437 | if (ASYNC_WAIT_CTX_get_callback(waitctx, &callback, &callback_arg) && callback != NULL) { |
438 | /* | |
439 | * In the Dummy async engine we are cheating. We call the callback that the job | |
440 | * is complete before the call to ASYNC_pause_job(). A real | |
441 | * async engine would only call the callback when the job was actually complete | |
442 | */ | |
443 | (*callback)(callback_arg); | |
444 | ASYNC_pause_job(); | |
445 | return; | |
446 | } | |
447 | ||
448 | ||
ff75a257 MC |
449 | if (ASYNC_WAIT_CTX_get_fd(waitctx, engine_dasync_id, &pipefds[0], |
450 | (void **)&writefd)) { | |
451 | pipefds[1] = *writefd; | |
452 | } else { | |
453 | writefd = OPENSSL_malloc(sizeof(*writefd)); | |
454 | if (writefd == NULL) | |
455 | return; | |
456 | #if defined(ASYNC_WIN) | |
457 | if (CreatePipe(&pipefds[0], &pipefds[1], NULL, 256) == 0) { | |
458 | OPENSSL_free(writefd); | |
459 | return; | |
460 | } | |
461 | #elif defined(ASYNC_POSIX) | |
462 | if (pipe(pipefds) != 0) { | |
463 | OPENSSL_free(writefd); | |
464 | return; | |
465 | } | |
466 | #endif | |
467 | *writefd = pipefds[1]; | |
468 | ||
f479eab2 F |
469 | if (!ASYNC_WAIT_CTX_set_wait_fd(waitctx, engine_dasync_id, pipefds[0], |
470 | writefd, wait_cleanup)) { | |
ff75a257 MC |
471 | wait_cleanup(waitctx, engine_dasync_id, pipefds[0], writefd); |
472 | return; | |
473 | } | |
474 | } | |
f4da39d2 MC |
475 | /* |
476 | * In the Dummy async engine we are cheating. We signal that the job | |
477 | * is complete by waking it before the call to ASYNC_pause_job(). A real | |
478 | * async engine would only wake when the job was actually complete | |
479 | */ | |
ff75a257 MC |
480 | #if defined(ASYNC_WIN) |
481 | WriteFile(pipefds[1], &buf, 1, &numwritten, NULL); | |
482 | #elif defined(ASYNC_POSIX) | |
b8972eda AG |
483 | if (write(pipefds[1], &buf, 1) < 0) |
484 | return; | |
ff75a257 | 485 | #endif |
f4da39d2 MC |
486 | |
487 | /* Ignore errors - we carry on anyway */ | |
488 | ASYNC_pause_job(); | |
489 | ||
ff75a257 MC |
490 | /* Clear the wake signal */ |
491 | #if defined(ASYNC_WIN) | |
492 | ReadFile(pipefds[0], &buf, 1, &numread, NULL); | |
493 | #elif defined(ASYNC_POSIX) | |
b8972eda AG |
494 | if (read(pipefds[0], &buf, 1) < 0) |
495 | return; | |
ff75a257 | 496 | #endif |
f4da39d2 MC |
497 | } |
498 | ||
a14e9ff7 MC |
499 | /* |
500 | * SHA1 implementation. At the moment we just defer to the standard | |
501 | * implementation | |
502 | */ | |
46a283c0 | 503 | static int dasync_sha1_init(EVP_MD_CTX *ctx) |
a14e9ff7 | 504 | { |
f4da39d2 | 505 | dummy_pause_job(); |
a14e9ff7 | 506 | |
85d843c8 | 507 | return EVP_MD_meth_get_init(EVP_sha1())(ctx); |
a14e9ff7 MC |
508 | } |
509 | ||
46a283c0 | 510 | static int dasync_sha1_update(EVP_MD_CTX *ctx, const void *data, |
652d4a8c | 511 | size_t count) |
a14e9ff7 | 512 | { |
f4da39d2 | 513 | dummy_pause_job(); |
a14e9ff7 | 514 | |
85d843c8 | 515 | return EVP_MD_meth_get_update(EVP_sha1())(ctx, data, count); |
a14e9ff7 MC |
516 | } |
517 | ||
46a283c0 | 518 | static int dasync_sha1_final(EVP_MD_CTX *ctx, unsigned char *md) |
a14e9ff7 | 519 | { |
f4da39d2 | 520 | dummy_pause_job(); |
a14e9ff7 | 521 | |
85d843c8 | 522 | return EVP_MD_meth_get_final(EVP_sha1())(ctx, md); |
a14e9ff7 MC |
523 | } |
524 | ||
525 | /* | |
526 | * RSA implementation | |
527 | */ | |
528 | ||
529 | static int dasync_pub_enc(int flen, const unsigned char *from, | |
530 | unsigned char *to, RSA *rsa, int padding) { | |
531 | /* Ignore errors - we carry on anyway */ | |
f4da39d2 | 532 | dummy_pause_job(); |
b72c9121 RL |
533 | return RSA_meth_get_pub_enc(RSA_PKCS1_OpenSSL()) |
534 | (flen, from, to, rsa, padding); | |
a14e9ff7 MC |
535 | } |
536 | ||
537 | static int dasync_pub_dec(int flen, const unsigned char *from, | |
538 | unsigned char *to, RSA *rsa, int padding) { | |
539 | /* Ignore errors - we carry on anyway */ | |
f4da39d2 | 540 | dummy_pause_job(); |
b72c9121 RL |
541 | return RSA_meth_get_pub_dec(RSA_PKCS1_OpenSSL()) |
542 | (flen, from, to, rsa, padding); | |
a14e9ff7 MC |
543 | } |
544 | ||
545 | static int dasync_rsa_priv_enc(int flen, const unsigned char *from, | |
546 | unsigned char *to, RSA *rsa, int padding) | |
547 | { | |
548 | /* Ignore errors - we carry on anyway */ | |
f4da39d2 | 549 | dummy_pause_job(); |
b72c9121 RL |
550 | return RSA_meth_get_priv_enc(RSA_PKCS1_OpenSSL()) |
551 | (flen, from, to, rsa, padding); | |
a14e9ff7 MC |
552 | } |
553 | ||
554 | static int dasync_rsa_priv_dec(int flen, const unsigned char *from, | |
555 | unsigned char *to, RSA *rsa, int padding) | |
556 | { | |
557 | /* Ignore errors - we carry on anyway */ | |
f4da39d2 | 558 | dummy_pause_job(); |
b72c9121 RL |
559 | return RSA_meth_get_priv_dec(RSA_PKCS1_OpenSSL()) |
560 | (flen, from, to, rsa, padding); | |
a14e9ff7 MC |
561 | } |
562 | ||
563 | static int dasync_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) | |
564 | { | |
565 | /* Ignore errors - we carry on anyway */ | |
f4da39d2 | 566 | dummy_pause_job(); |
b72c9121 | 567 | return RSA_meth_get_mod_exp(RSA_PKCS1_OpenSSL())(r0, I, rsa, ctx); |
a14e9ff7 MC |
568 | } |
569 | ||
570 | static int dasync_rsa_init(RSA *rsa) | |
571 | { | |
b72c9121 | 572 | return RSA_meth_get_init(RSA_PKCS1_OpenSSL())(rsa); |
a14e9ff7 MC |
573 | } |
574 | static int dasync_rsa_finish(RSA *rsa) | |
575 | { | |
b72c9121 | 576 | return RSA_meth_get_finish(RSA_PKCS1_OpenSSL())(rsa); |
a14e9ff7 | 577 | } |
98ee7543 | 578 | |
e38c2e85 | 579 | /* Cipher helper functions */ |
98ee7543 | 580 | |
e38c2e85 MC |
581 | static int dasync_cipher_ctrl_helper(EVP_CIPHER_CTX *ctx, int type, int arg, |
582 | void *ptr, int aeadcapable) | |
98ee7543 MC |
583 | { |
584 | int ret; | |
e38c2e85 MC |
585 | struct dasync_pipeline_ctx *pipe_ctx = |
586 | (struct dasync_pipeline_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); | |
2f2c9caa MC |
587 | |
588 | if (pipe_ctx == NULL) | |
589 | return 0; | |
590 | ||
591 | switch (type) { | |
592 | case EVP_CTRL_SET_PIPELINE_OUTPUT_BUFS: | |
593 | pipe_ctx->numpipes = arg; | |
594 | pipe_ctx->outbufs = (unsigned char **)ptr; | |
595 | break; | |
596 | ||
597 | case EVP_CTRL_SET_PIPELINE_INPUT_BUFS: | |
598 | pipe_ctx->numpipes = arg; | |
599 | pipe_ctx->inbufs = (unsigned char **)ptr; | |
600 | break; | |
601 | ||
602 | case EVP_CTRL_SET_PIPELINE_INPUT_LENS: | |
603 | pipe_ctx->numpipes = arg; | |
604 | pipe_ctx->lens = (size_t *)ptr; | |
605 | break; | |
606 | ||
607 | case EVP_CTRL_AEAD_SET_MAC_KEY: | |
e38c2e85 MC |
608 | if (!aeadcapable) |
609 | return -1; | |
2f2c9caa MC |
610 | EVP_CIPHER_CTX_set_cipher_data(ctx, pipe_ctx->inner_cipher_data); |
611 | ret = EVP_CIPHER_meth_get_ctrl(EVP_aes_128_cbc_hmac_sha1()) | |
612 | (ctx, type, arg, ptr); | |
613 | EVP_CIPHER_CTX_set_cipher_data(ctx, pipe_ctx); | |
614 | return ret; | |
615 | ||
616 | case EVP_CTRL_AEAD_TLS1_AAD: | |
617 | { | |
618 | unsigned char *p = ptr; | |
619 | unsigned int len; | |
620 | ||
e38c2e85 | 621 | if (!aeadcapable || arg != EVP_AEAD_TLS1_AAD_LEN) |
2f2c9caa MC |
622 | return -1; |
623 | ||
624 | if (pipe_ctx->aadctr >= SSL_MAX_PIPELINES) | |
625 | return -1; | |
626 | ||
627 | memcpy(pipe_ctx->tlsaad[pipe_ctx->aadctr], ptr, | |
628 | EVP_AEAD_TLS1_AAD_LEN); | |
629 | pipe_ctx->aadctr++; | |
630 | ||
631 | len = p[arg - 2] << 8 | p[arg - 1]; | |
632 | ||
695dd3a3 | 633 | if (EVP_CIPHER_CTX_encrypting(ctx)) { |
2f2c9caa | 634 | if ((p[arg - 4] << 8 | p[arg - 3]) >= TLS1_1_VERSION) { |
a68d3505 RS |
635 | if (len < AES_BLOCK_SIZE) |
636 | return 0; | |
2f2c9caa MC |
637 | len -= AES_BLOCK_SIZE; |
638 | } | |
639 | ||
640 | return ((len + SHA_DIGEST_LENGTH + AES_BLOCK_SIZE) | |
641 | & -AES_BLOCK_SIZE) - len; | |
642 | } else { | |
643 | return SHA_DIGEST_LENGTH; | |
644 | } | |
645 | } | |
646 | ||
2f2c9caa MC |
647 | default: |
648 | return 0; | |
649 | } | |
650 | ||
651 | return 1; | |
652 | } | |
653 | ||
e38c2e85 MC |
654 | static int dasync_cipher_init_key_helper(EVP_CIPHER_CTX *ctx, |
655 | const unsigned char *key, | |
656 | const unsigned char *iv, int enc, | |
657 | const EVP_CIPHER *cipher) | |
2f2c9caa MC |
658 | { |
659 | int ret; | |
e38c2e85 MC |
660 | struct dasync_pipeline_ctx *pipe_ctx = |
661 | (struct dasync_pipeline_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); | |
2f2c9caa MC |
662 | |
663 | if (pipe_ctx->inner_cipher_data == NULL | |
e38c2e85 MC |
664 | && EVP_CIPHER_impl_ctx_size(cipher) != 0) { |
665 | pipe_ctx->inner_cipher_data = OPENSSL_zalloc( | |
666 | EVP_CIPHER_impl_ctx_size(cipher)); | |
2f2c9caa | 667 | if (pipe_ctx->inner_cipher_data == NULL) { |
2f781956 | 668 | DASYNCerr(DASYNC_F_DASYNC_CIPHER_INIT_KEY_HELPER, |
2f2c9caa MC |
669 | ERR_R_MALLOC_FAILURE); |
670 | return 0; | |
671 | } | |
672 | } | |
673 | ||
674 | pipe_ctx->numpipes = 0; | |
e38c2e85 | 675 | pipe_ctx->aadctr = 0; |
2f2c9caa MC |
676 | |
677 | EVP_CIPHER_CTX_set_cipher_data(ctx, pipe_ctx->inner_cipher_data); | |
e38c2e85 | 678 | ret = EVP_CIPHER_meth_get_init(cipher)(ctx, key, iv, enc); |
2f2c9caa MC |
679 | EVP_CIPHER_CTX_set_cipher_data(ctx, pipe_ctx); |
680 | ||
681 | return ret; | |
682 | } | |
683 | ||
e38c2e85 MC |
684 | static int dasync_cipher_helper(EVP_CIPHER_CTX *ctx, unsigned char *out, |
685 | const unsigned char *in, size_t inl, | |
686 | const EVP_CIPHER *cipher) | |
2f2c9caa MC |
687 | { |
688 | int ret = 1; | |
689 | unsigned int i, pipes; | |
e38c2e85 MC |
690 | struct dasync_pipeline_ctx *pipe_ctx = |
691 | (struct dasync_pipeline_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); | |
2f2c9caa MC |
692 | |
693 | pipes = pipe_ctx->numpipes; | |
694 | EVP_CIPHER_CTX_set_cipher_data(ctx, pipe_ctx->inner_cipher_data); | |
695 | if (pipes == 0) { | |
696 | if (pipe_ctx->aadctr != 0) { | |
697 | if (pipe_ctx->aadctr != 1) | |
698 | return -1; | |
e38c2e85 | 699 | EVP_CIPHER_meth_get_ctrl(cipher) |
2f2c9caa MC |
700 | (ctx, EVP_CTRL_AEAD_TLS1_AAD, |
701 | EVP_AEAD_TLS1_AAD_LEN, | |
702 | pipe_ctx->tlsaad[0]); | |
703 | } | |
e38c2e85 | 704 | ret = EVP_CIPHER_meth_get_do_cipher(cipher) |
2f2c9caa MC |
705 | (ctx, out, in, inl); |
706 | } else { | |
707 | if (pipe_ctx->aadctr > 0 && pipe_ctx->aadctr != pipes) | |
708 | return -1; | |
709 | for (i = 0; i < pipes; i++) { | |
710 | if (pipe_ctx->aadctr > 0) { | |
e38c2e85 | 711 | EVP_CIPHER_meth_get_ctrl(cipher) |
2f2c9caa MC |
712 | (ctx, EVP_CTRL_AEAD_TLS1_AAD, |
713 | EVP_AEAD_TLS1_AAD_LEN, | |
714 | pipe_ctx->tlsaad[i]); | |
715 | } | |
e38c2e85 | 716 | ret = ret && EVP_CIPHER_meth_get_do_cipher(cipher) |
2f2c9caa MC |
717 | (ctx, pipe_ctx->outbufs[i], pipe_ctx->inbufs[i], |
718 | pipe_ctx->lens[i]); | |
719 | } | |
720 | pipe_ctx->numpipes = 0; | |
721 | } | |
722 | pipe_ctx->aadctr = 0; | |
723 | EVP_CIPHER_CTX_set_cipher_data(ctx, pipe_ctx); | |
724 | return ret; | |
725 | } | |
726 | ||
e38c2e85 MC |
727 | static int dasync_cipher_cleanup_helper(EVP_CIPHER_CTX *ctx, |
728 | const EVP_CIPHER *cipher) | |
2f2c9caa | 729 | { |
e38c2e85 MC |
730 | struct dasync_pipeline_ctx *pipe_ctx = |
731 | (struct dasync_pipeline_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx); | |
2f2c9caa MC |
732 | |
733 | OPENSSL_clear_free(pipe_ctx->inner_cipher_data, | |
e38c2e85 | 734 | EVP_CIPHER_impl_ctx_size(cipher)); |
2f2c9caa MC |
735 | |
736 | return 1; | |
737 | } | |
e38c2e85 MC |
738 | |
739 | /* | |
740 | * AES128 CBC Implementation | |
741 | */ | |
742 | ||
743 | static int dasync_aes128_cbc_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, | |
744 | void *ptr) | |
745 | { | |
746 | return dasync_cipher_ctrl_helper(ctx, type, arg, ptr, 0); | |
747 | } | |
748 | ||
749 | static int dasync_aes128_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, | |
750 | const unsigned char *iv, int enc) | |
751 | { | |
752 | return dasync_cipher_init_key_helper(ctx, key, iv, enc, EVP_aes_128_cbc()); | |
753 | } | |
754 | ||
755 | static int dasync_aes128_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, | |
756 | const unsigned char *in, size_t inl) | |
757 | { | |
758 | return dasync_cipher_helper(ctx, out, in, inl, EVP_aes_128_cbc()); | |
759 | } | |
760 | ||
761 | static int dasync_aes128_cbc_cleanup(EVP_CIPHER_CTX *ctx) | |
762 | { | |
763 | return dasync_cipher_cleanup_helper(ctx, EVP_aes_128_cbc()); | |
764 | } | |
765 | ||
766 | ||
767 | /* | |
768 | * AES128 CBC HMAC SHA1 Implementation | |
769 | */ | |
770 | ||
771 | static int dasync_aes128_cbc_hmac_sha1_ctrl(EVP_CIPHER_CTX *ctx, int type, | |
772 | int arg, void *ptr) | |
773 | { | |
774 | return dasync_cipher_ctrl_helper(ctx, type, arg, ptr, 1); | |
775 | } | |
776 | ||
777 | static int dasync_aes128_cbc_hmac_sha1_init_key(EVP_CIPHER_CTX *ctx, | |
778 | const unsigned char *key, | |
779 | const unsigned char *iv, | |
780 | int enc) | |
781 | { | |
a4a0a1eb DMSP |
782 | /* |
783 | * We can safely assume that EVP_aes_128_cbc_hmac_sha1() != NULL, | |
784 | * see comment before the definition of dasync_aes_128_cbc_hmac_sha1(). | |
785 | */ | |
e38c2e85 MC |
786 | return dasync_cipher_init_key_helper(ctx, key, iv, enc, |
787 | EVP_aes_128_cbc_hmac_sha1()); | |
788 | } | |
789 | ||
790 | static int dasync_aes128_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, | |
791 | unsigned char *out, | |
792 | const unsigned char *in, | |
793 | size_t inl) | |
794 | { | |
795 | return dasync_cipher_helper(ctx, out, in, inl, EVP_aes_128_cbc_hmac_sha1()); | |
796 | } | |
797 | ||
798 | static int dasync_aes128_cbc_hmac_sha1_cleanup(EVP_CIPHER_CTX *ctx) | |
799 | { | |
a4a0a1eb DMSP |
800 | /* |
801 | * We can safely assume that EVP_aes_128_cbc_hmac_sha1() != NULL, | |
802 | * see comment before the definition of dasync_aes_128_cbc_hmac_sha1(). | |
803 | */ | |
e38c2e85 MC |
804 | return dasync_cipher_cleanup_helper(ctx, EVP_aes_128_cbc_hmac_sha1()); |
805 | } |