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