tools/squashfskit4: drop unused tool
[openwrt/openwrt.git] / package / libs / openssl / patches / 430-e_devcrypto-make-the-dev-crypto-engine-dynamic.patch
1 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2 From: Eneas U de Queiroz <cote2004-github@yahoo.com>
3 Date: Tue, 6 Nov 2018 10:57:03 -0200
4 Subject: e_devcrypto: make the /dev/crypto engine dynamic
5
6 Engine has been moved from crypto/engine/eng_devcrypto.c to
7 engines/e_devcrypto.c.
8
9 Signed-off-by: Eneas U de Queiroz <cote2004-github@yahoo.com>
10
11 --- a/crypto/engine/build.info
12 +++ b/crypto/engine/build.info
13 @@ -6,6 +6,3 @@ SOURCE[../../libcrypto]=\
14 tb_cipher.c tb_digest.c tb_pkmeth.c tb_asnmth.c tb_eckey.c \
15 eng_openssl.c eng_cnf.c eng_dyn.c \
16 eng_rdrand.c
17 -IF[{- !$disabled{devcryptoeng} -}]
18 - SOURCE[../../libcrypto]=eng_devcrypto.c
19 -ENDIF
20 --- a/crypto/init.c
21 +++ b/crypto/init.c
22 @@ -328,18 +328,6 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_engine_
23 engine_load_openssl_int();
24 return 1;
25 }
26 -# ifndef OPENSSL_NO_DEVCRYPTOENG
27 -static CRYPTO_ONCE engine_devcrypto = CRYPTO_ONCE_STATIC_INIT;
28 -DEFINE_RUN_ONCE_STATIC(ossl_init_engine_devcrypto)
29 -{
30 -# ifdef OPENSSL_INIT_DEBUG
31 - fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_devcrypto: "
32 - "engine_load_devcrypto_int()\n");
33 -# endif
34 - engine_load_devcrypto_int();
35 - return 1;
36 -}
37 -# endif
38
39 # ifndef OPENSSL_NO_RDRAND
40 static CRYPTO_ONCE engine_rdrand = CRYPTO_ONCE_STATIC_INIT;
41 @@ -364,6 +352,18 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_engine_
42 return 1;
43 }
44 # ifndef OPENSSL_NO_STATIC_ENGINE
45 +# ifndef OPENSSL_NO_DEVCRYPTOENG
46 +static CRYPTO_ONCE engine_devcrypto = CRYPTO_ONCE_STATIC_INIT;
47 +DEFINE_RUN_ONCE_STATIC(ossl_init_engine_devcrypto)
48 +{
49 +# ifdef OPENSSL_INIT_DEBUG
50 + fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_devcrypto: "
51 + "engine_load_devcrypto_int()\n");
52 +# endif
53 + engine_load_devcrypto_int();
54 + return 1;
55 +}
56 +# endif
57 # if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK)
58 static CRYPTO_ONCE engine_padlock = CRYPTO_ONCE_STATIC_INIT;
59 DEFINE_RUN_ONCE_STATIC(ossl_init_engine_padlock)
60 @@ -704,11 +704,6 @@ int OPENSSL_init_crypto(uint64_t opts, c
61 if ((opts & OPENSSL_INIT_ENGINE_OPENSSL)
62 && !RUN_ONCE(&engine_openssl, ossl_init_engine_openssl))
63 return 0;
64 -# if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_DEVCRYPTOENG)
65 - if ((opts & OPENSSL_INIT_ENGINE_CRYPTODEV)
66 - && !RUN_ONCE(&engine_devcrypto, ossl_init_engine_devcrypto))
67 - return 0;
68 -# endif
69 # ifndef OPENSSL_NO_RDRAND
70 if ((opts & OPENSSL_INIT_ENGINE_RDRAND)
71 && !RUN_ONCE(&engine_rdrand, ossl_init_engine_rdrand))
72 @@ -718,6 +713,11 @@ int OPENSSL_init_crypto(uint64_t opts, c
73 && !RUN_ONCE(&engine_dynamic, ossl_init_engine_dynamic))
74 return 0;
75 # ifndef OPENSSL_NO_STATIC_ENGINE
76 +# ifndef OPENSSL_NO_DEVCRYPTOENG
77 + if ((opts & OPENSSL_INIT_ENGINE_CRYPTODEV)
78 + && !RUN_ONCE(&engine_devcrypto, ossl_init_engine_devcrypto))
79 + return 0;
80 +# endif
81 # if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK)
82 if ((opts & OPENSSL_INIT_ENGINE_PADLOCK)
83 && !RUN_ONCE(&engine_padlock, ossl_init_engine_padlock))
84 --- a/engines/build.info
85 +++ b/engines/build.info
86 @@ -11,6 +11,9 @@ IF[{- !$disabled{"engine"} -}]
87 IF[{- !$disabled{afalgeng} -}]
88 SOURCE[../libcrypto]=e_afalg.c
89 ENDIF
90 + IF[{- !$disabled{"devcryptoeng"} -}]
91 + SOURCE[../libcrypto]=e_devcrypto.c
92 + ENDIF
93 ELSE
94 IF[{- !$disabled{hw} && !$disabled{'hw-padlock'} -}]
95 ENGINES=padlock
96 @@ -30,6 +33,12 @@ IF[{- !$disabled{"engine"} -}]
97 DEPEND[afalg]=../libcrypto
98 INCLUDE[afalg]= ../include
99 ENDIF
100 + IF[{- !$disabled{"devcryptoeng"} -}]
101 + ENGINES=devcrypto
102 + SOURCE[devcrypto]=e_devcrypto.c
103 + DEPEND[devcrypto]=../libcrypto
104 + INCLUDE[devcrypto]=../include
105 + ENDIF
106
107 ENGINES_NO_INST=ossltest dasync
108 SOURCE[dasync]=e_dasync.c
109 --- a/crypto/engine/eng_devcrypto.c
110 +++ /dev/null
111 @@ -1,1277 +0,0 @@
112 -/*
113 - * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
114 - *
115 - * Licensed under the OpenSSL license (the "License"). You may not use
116 - * this file except in compliance with the License. You can obtain a copy
117 - * in the file LICENSE in the source distribution or at
118 - * https://www.openssl.org/source/license.html
119 - */
120 -
121 -#include "e_os.h"
122 -#include <string.h>
123 -#include <sys/types.h>
124 -#include <sys/stat.h>
125 -#include <fcntl.h>
126 -#include <sys/ioctl.h>
127 -#include <unistd.h>
128 -#include <assert.h>
129 -
130 -#include <openssl/conf.h>
131 -#include <openssl/evp.h>
132 -#include <openssl/err.h>
133 -#include <openssl/engine.h>
134 -#include <openssl/objects.h>
135 -#include <crypto/cryptodev.h>
136 -
137 -#include "crypto/engine.h"
138 -
139 -/* #define ENGINE_DEVCRYPTO_DEBUG */
140 -
141 -#if CRYPTO_ALGORITHM_MIN < CRYPTO_ALGORITHM_MAX
142 -# define CHECK_BSD_STYLE_MACROS
143 -#endif
144 -
145 -/*
146 - * ONE global file descriptor for all sessions. This allows operations
147 - * such as digest session data copying (see digest_copy()), but is also
148 - * saner... why re-open /dev/crypto for every session?
149 - */
150 -static int cfd;
151 -#define DEVCRYPTO_REQUIRE_ACCELERATED 0 /* require confirmation of acceleration */
152 -#define DEVCRYPTO_USE_SOFTWARE 1 /* allow software drivers */
153 -#define DEVCRYPTO_REJECT_SOFTWARE 2 /* only disallow confirmed software drivers */
154 -
155 -#define DEVCRYPTO_DEFAULT_USE_SOFDTRIVERS DEVCRYPTO_REJECT_SOFTWARE
156 -static int use_softdrivers = DEVCRYPTO_DEFAULT_USE_SOFDTRIVERS;
157 -
158 -/*
159 - * cipher/digest status & acceleration definitions
160 - * Make sure the defaults are set to 0
161 - */
162 -struct driver_info_st {
163 - enum devcrypto_status_t {
164 - DEVCRYPTO_STATUS_FAILURE = -3, /* unusable for other reason */
165 - DEVCRYPTO_STATUS_NO_CIOCCPHASH = -2, /* hash state copy not supported */
166 - DEVCRYPTO_STATUS_NO_CIOCGSESSION = -1, /* session open failed */
167 - DEVCRYPTO_STATUS_UNKNOWN = 0, /* not tested yet */
168 - DEVCRYPTO_STATUS_USABLE = 1 /* algo can be used */
169 - } status;
170 -
171 - enum devcrypto_accelerated_t {
172 - DEVCRYPTO_NOT_ACCELERATED = -1, /* software implemented */
173 - DEVCRYPTO_ACCELERATION_UNKNOWN = 0, /* acceleration support unkown */
174 - DEVCRYPTO_ACCELERATED = 1 /* hardware accelerated */
175 - } accelerated;
176 -
177 - char *driver_name;
178 -};
179 -
180 -static int clean_devcrypto_session(struct session_op *sess) {
181 - if (ioctl(cfd, CIOCFSESSION, &sess->ses) < 0) {
182 - SYSerr(SYS_F_IOCTL, errno);
183 - return 0;
184 - }
185 - memset(sess, 0, sizeof(struct session_op));
186 - return 1;
187 -}
188 -
189 -/******************************************************************************
190 - *
191 - * Ciphers
192 - *
193 - * Because they all do the same basic operation, we have only one set of
194 - * method functions for them all to share, and a mapping table between
195 - * NIDs and cryptodev IDs, with all the necessary size data.
196 - *
197 - *****/
198 -
199 -struct cipher_ctx {
200 - struct session_op sess;
201 - int op; /* COP_ENCRYPT or COP_DECRYPT */
202 - unsigned long mode; /* EVP_CIPH_*_MODE */
203 -
204 - /* to handle ctr mode being a stream cipher */
205 - unsigned char partial[EVP_MAX_BLOCK_LENGTH];
206 - unsigned int blocksize, num;
207 -};
208 -
209 -static const struct cipher_data_st {
210 - int nid;
211 - int blocksize;
212 - int keylen;
213 - int ivlen;
214 - int flags;
215 - int devcryptoid;
216 -} cipher_data[] = {
217 -#ifndef OPENSSL_NO_DES
218 - { NID_des_cbc, 8, 8, 8, EVP_CIPH_CBC_MODE, CRYPTO_DES_CBC },
219 - { NID_des_ede3_cbc, 8, 24, 8, EVP_CIPH_CBC_MODE, CRYPTO_3DES_CBC },
220 -#endif
221 -#ifndef OPENSSL_NO_BF
222 - { NID_bf_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_BLF_CBC },
223 -#endif
224 -#ifndef OPENSSL_NO_CAST
225 - { NID_cast5_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_CAST_CBC },
226 -#endif
227 - { NID_aes_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
228 - { NID_aes_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
229 - { NID_aes_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
230 -#ifndef OPENSSL_NO_RC4
231 - { NID_rc4, 1, 16, 0, EVP_CIPH_STREAM_CIPHER, CRYPTO_ARC4 },
232 -#endif
233 -#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_CTR)
234 - { NID_aes_128_ctr, 16, 128 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
235 - { NID_aes_192_ctr, 16, 192 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
236 - { NID_aes_256_ctr, 16, 256 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
237 -#endif
238 -#if 0 /* Not yet supported */
239 - { NID_aes_128_xts, 16, 128 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS },
240 - { NID_aes_256_xts, 16, 256 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS },
241 -#endif
242 -#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_ECB)
243 - { NID_aes_128_ecb, 16, 128 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
244 - { NID_aes_192_ecb, 16, 192 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
245 - { NID_aes_256_ecb, 16, 256 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
246 -#endif
247 -#if 0 /* Not yet supported */
248 - { NID_aes_128_gcm, 16, 128 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
249 - { NID_aes_192_gcm, 16, 192 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
250 - { NID_aes_256_gcm, 16, 256 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
251 -#endif
252 -#ifndef OPENSSL_NO_CAMELLIA
253 - { NID_camellia_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE,
254 - CRYPTO_CAMELLIA_CBC },
255 - { NID_camellia_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE,
256 - CRYPTO_CAMELLIA_CBC },
257 - { NID_camellia_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE,
258 - CRYPTO_CAMELLIA_CBC },
259 -#endif
260 -};
261 -
262 -static size_t find_cipher_data_index(int nid)
263 -{
264 - size_t i;
265 -
266 - for (i = 0; i < OSSL_NELEM(cipher_data); i++)
267 - if (nid == cipher_data[i].nid)
268 - return i;
269 - return (size_t)-1;
270 -}
271 -
272 -static size_t get_cipher_data_index(int nid)
273 -{
274 - size_t i = find_cipher_data_index(nid);
275 -
276 - if (i != (size_t)-1)
277 - return i;
278 -
279 - /*
280 - * Code further down must make sure that only NIDs in the table above
281 - * are used. If any other NID reaches this function, there's a grave
282 - * coding error further down.
283 - */
284 - assert("Code that never should be reached" == NULL);
285 - return -1;
286 -}
287 -
288 -static const struct cipher_data_st *get_cipher_data(int nid)
289 -{
290 - return &cipher_data[get_cipher_data_index(nid)];
291 -}
292 -
293 -/*
294 - * Following are the three necessary functions to map OpenSSL functionality
295 - * with cryptodev.
296 - */
297 -
298 -static int cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
299 - const unsigned char *iv, int enc)
300 -{
301 - struct cipher_ctx *cipher_ctx =
302 - (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
303 - const struct cipher_data_st *cipher_d =
304 - get_cipher_data(EVP_CIPHER_CTX_nid(ctx));
305 -
306 - /* cleanup a previous session */
307 - if (cipher_ctx->sess.ses != 0 &&
308 - clean_devcrypto_session(&cipher_ctx->sess) == 0)
309 - return 0;
310 -
311 - cipher_ctx->sess.cipher = cipher_d->devcryptoid;
312 - cipher_ctx->sess.keylen = cipher_d->keylen;
313 - cipher_ctx->sess.key = (void *)key;
314 - cipher_ctx->op = enc ? COP_ENCRYPT : COP_DECRYPT;
315 - cipher_ctx->mode = cipher_d->flags & EVP_CIPH_MODE;
316 - cipher_ctx->blocksize = cipher_d->blocksize;
317 - if (ioctl(cfd, CIOCGSESSION, &cipher_ctx->sess) < 0) {
318 - SYSerr(SYS_F_IOCTL, errno);
319 - return 0;
320 - }
321 -
322 - return 1;
323 -}
324 -
325 -static int cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
326 - const unsigned char *in, size_t inl)
327 -{
328 - struct cipher_ctx *cipher_ctx =
329 - (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
330 - struct crypt_op cryp;
331 - unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
332 -#if !defined(COP_FLAG_WRITE_IV)
333 - unsigned char saved_iv[EVP_MAX_IV_LENGTH];
334 - const unsigned char *ivptr;
335 - size_t nblocks, ivlen;
336 -#endif
337 -
338 - memset(&cryp, 0, sizeof(cryp));
339 - cryp.ses = cipher_ctx->sess.ses;
340 - cryp.len = inl;
341 - cryp.src = (void *)in;
342 - cryp.dst = (void *)out;
343 - cryp.iv = (void *)iv;
344 - cryp.op = cipher_ctx->op;
345 -#if !defined(COP_FLAG_WRITE_IV)
346 - cryp.flags = 0;
347 -
348 - ivlen = EVP_CIPHER_CTX_iv_length(ctx);
349 - if (ivlen > 0)
350 - switch (cipher_ctx->mode) {
351 - case EVP_CIPH_CBC_MODE:
352 - assert(inl >= ivlen);
353 - if (!EVP_CIPHER_CTX_encrypting(ctx)) {
354 - ivptr = in + inl - ivlen;
355 - memcpy(saved_iv, ivptr, ivlen);
356 - }
357 - break;
358 -
359 - case EVP_CIPH_CTR_MODE:
360 - break;
361 -
362 - default: /* should not happen */
363 - return 0;
364 - }
365 -#else
366 - cryp.flags = COP_FLAG_WRITE_IV;
367 -#endif
368 -
369 - if (ioctl(cfd, CIOCCRYPT, &cryp) < 0) {
370 - SYSerr(SYS_F_IOCTL, errno);
371 - return 0;
372 - }
373 -
374 -#if !defined(COP_FLAG_WRITE_IV)
375 - if (ivlen > 0)
376 - switch (cipher_ctx->mode) {
377 - case EVP_CIPH_CBC_MODE:
378 - assert(inl >= ivlen);
379 - if (EVP_CIPHER_CTX_encrypting(ctx))
380 - ivptr = out + inl - ivlen;
381 - else
382 - ivptr = saved_iv;
383 -
384 - memcpy(iv, ivptr, ivlen);
385 - break;
386 -
387 - case EVP_CIPH_CTR_MODE:
388 - nblocks = (inl + cipher_ctx->blocksize - 1)
389 - / cipher_ctx->blocksize;
390 - do {
391 - ivlen--;
392 - nblocks += iv[ivlen];
393 - iv[ivlen] = (uint8_t) nblocks;
394 - nblocks >>= 8;
395 - } while (ivlen);
396 - break;
397 -
398 - default: /* should not happen */
399 - return 0;
400 - }
401 -#endif
402 -
403 - return 1;
404 -}
405 -
406 -static int ctr_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
407 - const unsigned char *in, size_t inl)
408 -{
409 - struct cipher_ctx *cipher_ctx =
410 - (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
411 - size_t nblocks, len;
412 -
413 - /* initial partial block */
414 - while (cipher_ctx->num && inl) {
415 - (*out++) = *(in++) ^ cipher_ctx->partial[cipher_ctx->num];
416 - --inl;
417 - cipher_ctx->num = (cipher_ctx->num + 1) % cipher_ctx->blocksize;
418 - }
419 -
420 - /* full blocks */
421 - if (inl > (unsigned int) cipher_ctx->blocksize) {
422 - nblocks = inl/cipher_ctx->blocksize;
423 - len = nblocks * cipher_ctx->blocksize;
424 - if (cipher_do_cipher(ctx, out, in, len) < 1)
425 - return 0;
426 - inl -= len;
427 - out += len;
428 - in += len;
429 - }
430 -
431 - /* final partial block */
432 - if (inl) {
433 - memset(cipher_ctx->partial, 0, cipher_ctx->blocksize);
434 - if (cipher_do_cipher(ctx, cipher_ctx->partial, cipher_ctx->partial,
435 - cipher_ctx->blocksize) < 1)
436 - return 0;
437 - while (inl--) {
438 - out[cipher_ctx->num] = in[cipher_ctx->num]
439 - ^ cipher_ctx->partial[cipher_ctx->num];
440 - cipher_ctx->num++;
441 - }
442 - }
443 -
444 - return 1;
445 -}
446 -
447 -static int cipher_ctrl(EVP_CIPHER_CTX *ctx, int type, int p1, void* p2)
448 -{
449 - struct cipher_ctx *cipher_ctx =
450 - (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
451 - EVP_CIPHER_CTX *to_ctx = (EVP_CIPHER_CTX *)p2;
452 - struct cipher_ctx *to_cipher_ctx;
453 -
454 - switch (type) {
455 - case EVP_CTRL_COPY:
456 - if (cipher_ctx == NULL)
457 - return 1;
458 - /* when copying the context, a new session needs to be initialized */
459 - to_cipher_ctx =
460 - (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(to_ctx);
461 - memset(&to_cipher_ctx->sess, 0, sizeof(to_cipher_ctx->sess));
462 - return cipher_init(to_ctx, cipher_ctx->sess.key, EVP_CIPHER_CTX_iv(ctx),
463 - (cipher_ctx->op == COP_ENCRYPT));
464 -
465 - case EVP_CTRL_INIT:
466 - memset(&cipher_ctx->sess, 0, sizeof(cipher_ctx->sess));
467 - return 1;
468 -
469 - default:
470 - break;
471 - }
472 -
473 - return -1;
474 -}
475 -
476 -static int cipher_cleanup(EVP_CIPHER_CTX *ctx)
477 -{
478 - struct cipher_ctx *cipher_ctx =
479 - (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
480 -
481 - return clean_devcrypto_session(&cipher_ctx->sess);
482 -}
483 -
484 -/*
485 - * Keep tables of known nids, associated methods, selected ciphers, and driver
486 - * info.
487 - * Note that known_cipher_nids[] isn't necessarily indexed the same way as
488 - * cipher_data[] above, which the other tables are.
489 - */
490 -static int known_cipher_nids[OSSL_NELEM(cipher_data)];
491 -static int known_cipher_nids_amount = -1; /* -1 indicates not yet initialised */
492 -static EVP_CIPHER *known_cipher_methods[OSSL_NELEM(cipher_data)] = { NULL, };
493 -static int selected_ciphers[OSSL_NELEM(cipher_data)];
494 -static struct driver_info_st cipher_driver_info[OSSL_NELEM(cipher_data)];
495 -
496 -
497 -static int devcrypto_test_cipher(size_t cipher_data_index)
498 -{
499 - return (cipher_driver_info[cipher_data_index].status == DEVCRYPTO_STATUS_USABLE
500 - && selected_ciphers[cipher_data_index] == 1
501 - && (cipher_driver_info[cipher_data_index].accelerated
502 - == DEVCRYPTO_ACCELERATED
503 - || use_softdrivers == DEVCRYPTO_USE_SOFTWARE
504 - || (cipher_driver_info[cipher_data_index].accelerated
505 - != DEVCRYPTO_NOT_ACCELERATED
506 - && use_softdrivers == DEVCRYPTO_REJECT_SOFTWARE)));
507 -}
508 -
509 -static void prepare_cipher_methods(void)
510 -{
511 - size_t i;
512 - struct session_op sess;
513 - unsigned long cipher_mode;
514 -#ifdef CIOCGSESSINFO
515 - struct session_info_op siop;
516 -#endif
517 -
518 - memset(&cipher_driver_info, 0, sizeof(cipher_driver_info));
519 -
520 - memset(&sess, 0, sizeof(sess));
521 - sess.key = (void *)"01234567890123456789012345678901234567890123456789";
522 -
523 - for (i = 0, known_cipher_nids_amount = 0;
524 - i < OSSL_NELEM(cipher_data); i++) {
525 -
526 - selected_ciphers[i] = 1;
527 - /*
528 - * Check that the cipher is usable
529 - */
530 - sess.cipher = cipher_data[i].devcryptoid;
531 - sess.keylen = cipher_data[i].keylen;
532 - if (ioctl(cfd, CIOCGSESSION, &sess) < 0) {
533 - cipher_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION;
534 - continue;
535 - }
536 -
537 - cipher_mode = cipher_data[i].flags & EVP_CIPH_MODE;
538 -
539 - if ((known_cipher_methods[i] =
540 - EVP_CIPHER_meth_new(cipher_data[i].nid,
541 - cipher_mode == EVP_CIPH_CTR_MODE ? 1 :
542 - cipher_data[i].blocksize,
543 - cipher_data[i].keylen)) == NULL
544 - || !EVP_CIPHER_meth_set_iv_length(known_cipher_methods[i],
545 - cipher_data[i].ivlen)
546 - || !EVP_CIPHER_meth_set_flags(known_cipher_methods[i],
547 - cipher_data[i].flags
548 - | EVP_CIPH_CUSTOM_COPY
549 - | EVP_CIPH_CTRL_INIT
550 - | EVP_CIPH_FLAG_DEFAULT_ASN1)
551 - || !EVP_CIPHER_meth_set_init(known_cipher_methods[i], cipher_init)
552 - || !EVP_CIPHER_meth_set_do_cipher(known_cipher_methods[i],
553 - cipher_mode == EVP_CIPH_CTR_MODE ?
554 - ctr_do_cipher :
555 - cipher_do_cipher)
556 - || !EVP_CIPHER_meth_set_ctrl(known_cipher_methods[i], cipher_ctrl)
557 - || !EVP_CIPHER_meth_set_cleanup(known_cipher_methods[i],
558 - cipher_cleanup)
559 - || !EVP_CIPHER_meth_set_impl_ctx_size(known_cipher_methods[i],
560 - sizeof(struct cipher_ctx))) {
561 - cipher_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
562 - EVP_CIPHER_meth_free(known_cipher_methods[i]);
563 - known_cipher_methods[i] = NULL;
564 - } else {
565 - cipher_driver_info[i].status = DEVCRYPTO_STATUS_USABLE;
566 -#ifdef CIOCGSESSINFO
567 - siop.ses = sess.ses;
568 - if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) {
569 - cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN;
570 - } else {
571 - cipher_driver_info[i].driver_name =
572 - OPENSSL_strndup(siop.cipher_info.cra_driver_name,
573 - CRYPTODEV_MAX_ALG_NAME);
574 - if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY))
575 - cipher_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED;
576 - else
577 - cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED;
578 - }
579 -#endif /* CIOCGSESSINFO */
580 - }
581 - ioctl(cfd, CIOCFSESSION, &sess.ses);
582 - if (devcrypto_test_cipher(i)) {
583 - known_cipher_nids[known_cipher_nids_amount++] =
584 - cipher_data[i].nid;
585 - }
586 - }
587 -}
588 -
589 -static void rebuild_known_cipher_nids(ENGINE *e)
590 -{
591 - size_t i;
592 -
593 - for (i = 0, known_cipher_nids_amount = 0; i < OSSL_NELEM(cipher_data); i++) {
594 - if (devcrypto_test_cipher(i))
595 - known_cipher_nids[known_cipher_nids_amount++] = cipher_data[i].nid;
596 - }
597 - ENGINE_unregister_ciphers(e);
598 - ENGINE_register_ciphers(e);
599 -}
600 -
601 -static const EVP_CIPHER *get_cipher_method(int nid)
602 -{
603 - size_t i = get_cipher_data_index(nid);
604 -
605 - if (i == (size_t)-1)
606 - return NULL;
607 - return known_cipher_methods[i];
608 -}
609 -
610 -static int get_cipher_nids(const int **nids)
611 -{
612 - *nids = known_cipher_nids;
613 - return known_cipher_nids_amount;
614 -}
615 -
616 -static void destroy_cipher_method(int nid)
617 -{
618 - size_t i = get_cipher_data_index(nid);
619 -
620 - EVP_CIPHER_meth_free(known_cipher_methods[i]);
621 - known_cipher_methods[i] = NULL;
622 -}
623 -
624 -static void destroy_all_cipher_methods(void)
625 -{
626 - size_t i;
627 -
628 - for (i = 0; i < OSSL_NELEM(cipher_data); i++) {
629 - destroy_cipher_method(cipher_data[i].nid);
630 - OPENSSL_free(cipher_driver_info[i].driver_name);
631 - cipher_driver_info[i].driver_name = NULL;
632 - }
633 -}
634 -
635 -static int devcrypto_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
636 - const int **nids, int nid)
637 -{
638 - if (cipher == NULL)
639 - return get_cipher_nids(nids);
640 -
641 - *cipher = get_cipher_method(nid);
642 -
643 - return *cipher != NULL;
644 -}
645 -
646 -static void devcrypto_select_all_ciphers(int *cipher_list)
647 -{
648 - size_t i;
649 -
650 - for (i = 0; i < OSSL_NELEM(cipher_data); i++)
651 - cipher_list[i] = 1;
652 -}
653 -
654 -static int cryptodev_select_cipher_cb(const char *str, int len, void *usr)
655 -{
656 - int *cipher_list = (int *)usr;
657 - char *name;
658 - const EVP_CIPHER *EVP;
659 - size_t i;
660 -
661 - if (len == 0)
662 - return 1;
663 - if (usr == NULL || (name = OPENSSL_strndup(str, len)) == NULL)
664 - return 0;
665 - EVP = EVP_get_cipherbyname(name);
666 - if (EVP == NULL)
667 - fprintf(stderr, "devcrypto: unknown cipher %s\n", name);
668 - else if ((i = find_cipher_data_index(EVP_CIPHER_nid(EVP))) != (size_t)-1)
669 - cipher_list[i] = 1;
670 - else
671 - fprintf(stderr, "devcrypto: cipher %s not available\n", name);
672 - OPENSSL_free(name);
673 - return 1;
674 -}
675 -
676 -static void dump_cipher_info(void)
677 -{
678 - size_t i;
679 - const char *name;
680 -
681 - fprintf (stderr, "Information about ciphers supported by the /dev/crypto"
682 - " engine:\n");
683 -#ifndef CIOCGSESSINFO
684 - fprintf(stderr, "CIOCGSESSINFO (session info call) unavailable\n");
685 -#endif
686 - for (i = 0; i < OSSL_NELEM(cipher_data); i++) {
687 - name = OBJ_nid2sn(cipher_data[i].nid);
688 - fprintf (stderr, "Cipher %s, NID=%d, /dev/crypto info: id=%d, ",
689 - name ? name : "unknown", cipher_data[i].nid,
690 - cipher_data[i].devcryptoid);
691 - if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCGSESSION ) {
692 - fprintf (stderr, "CIOCGSESSION (session open call) failed\n");
693 - continue;
694 - }
695 - fprintf (stderr, "driver=%s ", cipher_driver_info[i].driver_name ?
696 - cipher_driver_info[i].driver_name : "unknown");
697 - if (cipher_driver_info[i].accelerated == DEVCRYPTO_ACCELERATED)
698 - fprintf(stderr, "(hw accelerated)");
699 - else if (cipher_driver_info[i].accelerated == DEVCRYPTO_NOT_ACCELERATED)
700 - fprintf(stderr, "(software)");
701 - else
702 - fprintf(stderr, "(acceleration status unknown)");
703 - if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_FAILURE)
704 - fprintf (stderr, ". Cipher setup failed");
705 - fprintf(stderr, "\n");
706 - }
707 - fprintf(stderr, "\n");
708 -}
709 -
710 -/*
711 - * We only support digests if the cryptodev implementation supports multiple
712 - * data updates and session copying. Otherwise, we would be forced to maintain
713 - * a cache, which is perilous if there's a lot of data coming in (if someone
714 - * wants to checksum an OpenSSL tarball, for example).
715 - */
716 -#if defined(CIOCCPHASH) && defined(COP_FLAG_UPDATE) && defined(COP_FLAG_FINAL)
717 -#define IMPLEMENT_DIGEST
718 -
719 -/******************************************************************************
720 - *
721 - * Digests
722 - *
723 - * Because they all do the same basic operation, we have only one set of
724 - * method functions for them all to share, and a mapping table between
725 - * NIDs and cryptodev IDs, with all the necessary size data.
726 - *
727 - *****/
728 -
729 -struct digest_ctx {
730 - struct session_op sess;
731 - /* This signals that the init function was called, not that it succeeded. */
732 - int init_called;
733 - unsigned char digest_res[HASH_MAX_LEN];
734 -};
735 -
736 -static const struct digest_data_st {
737 - int nid;
738 - int blocksize;
739 - int digestlen;
740 - int devcryptoid;
741 -} digest_data[] = {
742 -#ifndef OPENSSL_NO_MD5
743 - { NID_md5, /* MD5_CBLOCK */ 64, 16, CRYPTO_MD5 },
744 -#endif
745 - { NID_sha1, SHA_CBLOCK, 20, CRYPTO_SHA1 },
746 -#ifndef OPENSSL_NO_RMD160
747 -# if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_RIPEMD160)
748 - { NID_ripemd160, /* RIPEMD160_CBLOCK */ 64, 20, CRYPTO_RIPEMD160 },
749 -# endif
750 -#endif
751 -#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_224)
752 - { NID_sha224, SHA256_CBLOCK, 224 / 8, CRYPTO_SHA2_224 },
753 -#endif
754 -#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_256)
755 - { NID_sha256, SHA256_CBLOCK, 256 / 8, CRYPTO_SHA2_256 },
756 -#endif
757 -#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_384)
758 - { NID_sha384, SHA512_CBLOCK, 384 / 8, CRYPTO_SHA2_384 },
759 -#endif
760 -#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_512)
761 - { NID_sha512, SHA512_CBLOCK, 512 / 8, CRYPTO_SHA2_512 },
762 -#endif
763 -};
764 -
765 -static size_t find_digest_data_index(int nid)
766 -{
767 - size_t i;
768 -
769 - for (i = 0; i < OSSL_NELEM(digest_data); i++)
770 - if (nid == digest_data[i].nid)
771 - return i;
772 - return (size_t)-1;
773 -}
774 -
775 -static size_t get_digest_data_index(int nid)
776 -{
777 - size_t i = find_digest_data_index(nid);
778 -
779 - if (i != (size_t)-1)
780 - return i;
781 -
782 - /*
783 - * Code further down must make sure that only NIDs in the table above
784 - * are used. If any other NID reaches this function, there's a grave
785 - * coding error further down.
786 - */
787 - assert("Code that never should be reached" == NULL);
788 - return -1;
789 -}
790 -
791 -static const struct digest_data_st *get_digest_data(int nid)
792 -{
793 - return &digest_data[get_digest_data_index(nid)];
794 -}
795 -
796 -/*
797 - * Following are the five necessary functions to map OpenSSL functionality
798 - * with cryptodev: init, update, final, cleanup, and copy.
799 - */
800 -
801 -static int digest_init(EVP_MD_CTX *ctx)
802 -{
803 - struct digest_ctx *digest_ctx =
804 - (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
805 - const struct digest_data_st *digest_d =
806 - get_digest_data(EVP_MD_CTX_type(ctx));
807 -
808 - digest_ctx->init_called = 1;
809 -
810 - memset(&digest_ctx->sess, 0, sizeof(digest_ctx->sess));
811 - digest_ctx->sess.mac = digest_d->devcryptoid;
812 - if (ioctl(cfd, CIOCGSESSION, &digest_ctx->sess) < 0) {
813 - SYSerr(SYS_F_IOCTL, errno);
814 - return 0;
815 - }
816 -
817 - return 1;
818 -}
819 -
820 -static int digest_op(struct digest_ctx *ctx, const void *src, size_t srclen,
821 - void *res, unsigned int flags)
822 -{
823 - struct crypt_op cryp;
824 -
825 - memset(&cryp, 0, sizeof(cryp));
826 - cryp.ses = ctx->sess.ses;
827 - cryp.len = srclen;
828 - cryp.src = (void *)src;
829 - cryp.dst = NULL;
830 - cryp.mac = res;
831 - cryp.flags = flags;
832 - return ioctl(cfd, CIOCCRYPT, &cryp);
833 -}
834 -
835 -static int digest_update(EVP_MD_CTX *ctx, const void *data, size_t count)
836 -{
837 - struct digest_ctx *digest_ctx =
838 - (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
839 -
840 - if (count == 0)
841 - return 1;
842 -
843 - if (digest_ctx == NULL)
844 - return 0;
845 -
846 - if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) {
847 - if (digest_op(digest_ctx, data, count, digest_ctx->digest_res, 0) >= 0)
848 - return 1;
849 - } else if (digest_op(digest_ctx, data, count, NULL, COP_FLAG_UPDATE) >= 0) {
850 - return 1;
851 - }
852 -
853 - SYSerr(SYS_F_IOCTL, errno);
854 - return 0;
855 -}
856 -
857 -static int digest_final(EVP_MD_CTX *ctx, unsigned char *md)
858 -{
859 - struct digest_ctx *digest_ctx =
860 - (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
861 -
862 - if (md == NULL || digest_ctx == NULL)
863 - return 0;
864 -
865 - if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) {
866 - memcpy(md, digest_ctx->digest_res, EVP_MD_CTX_size(ctx));
867 - } else if (digest_op(digest_ctx, NULL, 0, md, COP_FLAG_FINAL) < 0) {
868 - SYSerr(SYS_F_IOCTL, errno);
869 - return 0;
870 - }
871 -
872 - return 1;
873 -}
874 -
875 -static int digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
876 -{
877 - struct digest_ctx *digest_from =
878 - (struct digest_ctx *)EVP_MD_CTX_md_data(from);
879 - struct digest_ctx *digest_to =
880 - (struct digest_ctx *)EVP_MD_CTX_md_data(to);
881 - struct cphash_op cphash;
882 -
883 - if (digest_from == NULL || digest_from->init_called != 1)
884 - return 1;
885 -
886 - if (!digest_init(to)) {
887 - SYSerr(SYS_F_IOCTL, errno);
888 - return 0;
889 - }
890 -
891 - cphash.src_ses = digest_from->sess.ses;
892 - cphash.dst_ses = digest_to->sess.ses;
893 - if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) {
894 - SYSerr(SYS_F_IOCTL, errno);
895 - return 0;
896 - }
897 - return 1;
898 -}
899 -
900 -static int digest_cleanup(EVP_MD_CTX *ctx)
901 -{
902 - struct digest_ctx *digest_ctx =
903 - (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
904 -
905 - if (digest_ctx == NULL)
906 - return 1;
907 -
908 - return clean_devcrypto_session(&digest_ctx->sess);
909 -}
910 -
911 -/*
912 - * Keep tables of known nids, associated methods, selected digests, and
913 - * driver info.
914 - * Note that known_digest_nids[] isn't necessarily indexed the same way as
915 - * digest_data[] above, which the other tables are.
916 - */
917 -static int known_digest_nids[OSSL_NELEM(digest_data)];
918 -static int known_digest_nids_amount = -1; /* -1 indicates not yet initialised */
919 -static EVP_MD *known_digest_methods[OSSL_NELEM(digest_data)] = { NULL, };
920 -static int selected_digests[OSSL_NELEM(digest_data)];
921 -static struct driver_info_st digest_driver_info[OSSL_NELEM(digest_data)];
922 -
923 -static int devcrypto_test_digest(size_t digest_data_index)
924 -{
925 - return (digest_driver_info[digest_data_index].status == DEVCRYPTO_STATUS_USABLE
926 - && selected_digests[digest_data_index] == 1
927 - && (digest_driver_info[digest_data_index].accelerated
928 - == DEVCRYPTO_ACCELERATED
929 - || use_softdrivers == DEVCRYPTO_USE_SOFTWARE
930 - || (digest_driver_info[digest_data_index].accelerated
931 - != DEVCRYPTO_NOT_ACCELERATED
932 - && use_softdrivers == DEVCRYPTO_REJECT_SOFTWARE)));
933 -}
934 -
935 -static void rebuild_known_digest_nids(ENGINE *e)
936 -{
937 - size_t i;
938 -
939 - for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data); i++) {
940 - if (devcrypto_test_digest(i))
941 - known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid;
942 - }
943 - ENGINE_unregister_digests(e);
944 - ENGINE_register_digests(e);
945 -}
946 -
947 -static void prepare_digest_methods(void)
948 -{
949 - size_t i;
950 - struct session_op sess1, sess2;
951 -#ifdef CIOCGSESSINFO
952 - struct session_info_op siop;
953 -#endif
954 - struct cphash_op cphash;
955 -
956 - memset(&digest_driver_info, 0, sizeof(digest_driver_info));
957 -
958 - memset(&sess1, 0, sizeof(sess1));
959 - memset(&sess2, 0, sizeof(sess2));
960 -
961 - for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data);
962 - i++) {
963 -
964 - selected_digests[i] = 1;
965 -
966 - /*
967 - * Check that the digest is usable
968 - */
969 - sess1.mac = digest_data[i].devcryptoid;
970 - sess2.ses = 0;
971 - if (ioctl(cfd, CIOCGSESSION, &sess1) < 0) {
972 - digest_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION;
973 - goto finish;
974 - }
975 -
976 -#ifdef CIOCGSESSINFO
977 - /* gather hardware acceleration info from the driver */
978 - siop.ses = sess1.ses;
979 - if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) {
980 - digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN;
981 - } else {
982 - digest_driver_info[i].driver_name =
983 - OPENSSL_strndup(siop.hash_info.cra_driver_name,
984 - CRYPTODEV_MAX_ALG_NAME);
985 - if (siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)
986 - digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED;
987 - else
988 - digest_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED;
989 - }
990 -#endif
991 -
992 - /* digest must be capable of hash state copy */
993 - sess2.mac = sess1.mac;
994 - if (ioctl(cfd, CIOCGSESSION, &sess2) < 0) {
995 - digest_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
996 - goto finish;
997 - }
998 - cphash.src_ses = sess1.ses;
999 - cphash.dst_ses = sess2.ses;
1000 - if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) {
1001 - digest_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCCPHASH;
1002 - goto finish;
1003 - }
1004 - if ((known_digest_methods[i] = EVP_MD_meth_new(digest_data[i].nid,
1005 - NID_undef)) == NULL
1006 - || !EVP_MD_meth_set_input_blocksize(known_digest_methods[i],
1007 - digest_data[i].blocksize)
1008 - || !EVP_MD_meth_set_result_size(known_digest_methods[i],
1009 - digest_data[i].digestlen)
1010 - || !EVP_MD_meth_set_init(known_digest_methods[i], digest_init)
1011 - || !EVP_MD_meth_set_update(known_digest_methods[i], digest_update)
1012 - || !EVP_MD_meth_set_final(known_digest_methods[i], digest_final)
1013 - || !EVP_MD_meth_set_copy(known_digest_methods[i], digest_copy)
1014 - || !EVP_MD_meth_set_cleanup(known_digest_methods[i], digest_cleanup)
1015 - || !EVP_MD_meth_set_app_datasize(known_digest_methods[i],
1016 - sizeof(struct digest_ctx))) {
1017 - digest_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
1018 - EVP_MD_meth_free(known_digest_methods[i]);
1019 - known_digest_methods[i] = NULL;
1020 - goto finish;
1021 - }
1022 - digest_driver_info[i].status = DEVCRYPTO_STATUS_USABLE;
1023 -finish:
1024 - ioctl(cfd, CIOCFSESSION, &sess1.ses);
1025 - if (sess2.ses != 0)
1026 - ioctl(cfd, CIOCFSESSION, &sess2.ses);
1027 - if (devcrypto_test_digest(i))
1028 - known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid;
1029 - }
1030 -}
1031 -
1032 -static const EVP_MD *get_digest_method(int nid)
1033 -{
1034 - size_t i = get_digest_data_index(nid);
1035 -
1036 - if (i == (size_t)-1)
1037 - return NULL;
1038 - return known_digest_methods[i];
1039 -}
1040 -
1041 -static int get_digest_nids(const int **nids)
1042 -{
1043 - *nids = known_digest_nids;
1044 - return known_digest_nids_amount;
1045 -}
1046 -
1047 -static void destroy_digest_method(int nid)
1048 -{
1049 - size_t i = get_digest_data_index(nid);
1050 -
1051 - EVP_MD_meth_free(known_digest_methods[i]);
1052 - known_digest_methods[i] = NULL;
1053 -}
1054 -
1055 -static void destroy_all_digest_methods(void)
1056 -{
1057 - size_t i;
1058 -
1059 - for (i = 0; i < OSSL_NELEM(digest_data); i++) {
1060 - destroy_digest_method(digest_data[i].nid);
1061 - OPENSSL_free(digest_driver_info[i].driver_name);
1062 - digest_driver_info[i].driver_name = NULL;
1063 - }
1064 -}
1065 -
1066 -static int devcrypto_digests(ENGINE *e, const EVP_MD **digest,
1067 - const int **nids, int nid)
1068 -{
1069 - if (digest == NULL)
1070 - return get_digest_nids(nids);
1071 -
1072 - *digest = get_digest_method(nid);
1073 -
1074 - return *digest != NULL;
1075 -}
1076 -
1077 -static void devcrypto_select_all_digests(int *digest_list)
1078 -{
1079 - size_t i;
1080 -
1081 - for (i = 0; i < OSSL_NELEM(digest_data); i++)
1082 - digest_list[i] = 1;
1083 -}
1084 -
1085 -static int cryptodev_select_digest_cb(const char *str, int len, void *usr)
1086 -{
1087 - int *digest_list = (int *)usr;
1088 - char *name;
1089 - const EVP_MD *EVP;
1090 - size_t i;
1091 -
1092 - if (len == 0)
1093 - return 1;
1094 - if (usr == NULL || (name = OPENSSL_strndup(str, len)) == NULL)
1095 - return 0;
1096 - EVP = EVP_get_digestbyname(name);
1097 - if (EVP == NULL)
1098 - fprintf(stderr, "devcrypto: unknown digest %s\n", name);
1099 - else if ((i = find_digest_data_index(EVP_MD_type(EVP))) != (size_t)-1)
1100 - digest_list[i] = 1;
1101 - else
1102 - fprintf(stderr, "devcrypto: digest %s not available\n", name);
1103 - OPENSSL_free(name);
1104 - return 1;
1105 -}
1106 -
1107 -static void dump_digest_info(void)
1108 -{
1109 - size_t i;
1110 - const char *name;
1111 -
1112 - fprintf (stderr, "Information about digests supported by the /dev/crypto"
1113 - " engine:\n");
1114 -#ifndef CIOCGSESSINFO
1115 - fprintf(stderr, "CIOCGSESSINFO (session info call) unavailable\n");
1116 -#endif
1117 -
1118 - for (i = 0; i < OSSL_NELEM(digest_data); i++) {
1119 - name = OBJ_nid2sn(digest_data[i].nid);
1120 - fprintf (stderr, "Digest %s, NID=%d, /dev/crypto info: id=%d, driver=%s",
1121 - name ? name : "unknown", digest_data[i].nid,
1122 - digest_data[i].devcryptoid,
1123 - digest_driver_info[i].driver_name ? digest_driver_info[i].driver_name : "unknown");
1124 - if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCGSESSION) {
1125 - fprintf (stderr, ". CIOCGSESSION (session open) failed\n");
1126 - continue;
1127 - }
1128 - if (digest_driver_info[i].accelerated == DEVCRYPTO_ACCELERATED)
1129 - fprintf(stderr, " (hw accelerated)");
1130 - else if (digest_driver_info[i].accelerated == DEVCRYPTO_NOT_ACCELERATED)
1131 - fprintf(stderr, " (software)");
1132 - else
1133 - fprintf(stderr, " (acceleration status unknown)");
1134 - if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_FAILURE)
1135 - fprintf (stderr, ". Cipher setup failed\n");
1136 - else if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCCPHASH)
1137 - fprintf(stderr, ", CIOCCPHASH failed\n");
1138 - else
1139 - fprintf(stderr, ", CIOCCPHASH capable\n");
1140 - }
1141 - fprintf(stderr, "\n");
1142 -}
1143 -
1144 -#endif
1145 -
1146 -/******************************************************************************
1147 - *
1148 - * CONTROL COMMANDS
1149 - *
1150 - *****/
1151 -
1152 -#define DEVCRYPTO_CMD_USE_SOFTDRIVERS ENGINE_CMD_BASE
1153 -#define DEVCRYPTO_CMD_CIPHERS (ENGINE_CMD_BASE + 1)
1154 -#define DEVCRYPTO_CMD_DIGESTS (ENGINE_CMD_BASE + 2)
1155 -#define DEVCRYPTO_CMD_DUMP_INFO (ENGINE_CMD_BASE + 3)
1156 -
1157 -/* Helper macros for CPP string composition */
1158 -#ifndef OPENSSL_MSTR
1159 -# define OPENSSL_MSTR_HELPER(x) #x
1160 -# define OPENSSL_MSTR(x) OPENSSL_MSTR_HELPER(x)
1161 -#endif
1162 -
1163 -static const ENGINE_CMD_DEFN devcrypto_cmds[] = {
1164 -#ifdef CIOCGSESSINFO
1165 - {DEVCRYPTO_CMD_USE_SOFTDRIVERS,
1166 - "USE_SOFTDRIVERS",
1167 - "specifies whether to use software (not accelerated) drivers ("
1168 - OPENSSL_MSTR(DEVCRYPTO_REQUIRE_ACCELERATED) "=use only accelerated drivers, "
1169 - OPENSSL_MSTR(DEVCRYPTO_USE_SOFTWARE) "=allow all drivers, "
1170 - OPENSSL_MSTR(DEVCRYPTO_REJECT_SOFTWARE)
1171 - "=use if acceleration can't be determined) [default="
1172 - OPENSSL_MSTR(DEVCRYPTO_DEFAULT_USE_SOFDTRIVERS) "]",
1173 - ENGINE_CMD_FLAG_NUMERIC},
1174 -#endif
1175 -
1176 - {DEVCRYPTO_CMD_CIPHERS,
1177 - "CIPHERS",
1178 - "either ALL, NONE, or a comma-separated list of ciphers to enable [default=ALL]",
1179 - ENGINE_CMD_FLAG_STRING},
1180 -
1181 -#ifdef IMPLEMENT_DIGEST
1182 - {DEVCRYPTO_CMD_DIGESTS,
1183 - "DIGESTS",
1184 - "either ALL, NONE, or a comma-separated list of digests to enable [default=ALL]",
1185 - ENGINE_CMD_FLAG_STRING},
1186 -#endif
1187 -
1188 - {DEVCRYPTO_CMD_DUMP_INFO,
1189 - "DUMP_INFO",
1190 - "dump info about each algorithm to stderr; use 'openssl engine -pre DUMP_INFO devcrypto'",
1191 - ENGINE_CMD_FLAG_NO_INPUT},
1192 -
1193 - {0, NULL, NULL, 0}
1194 -};
1195 -
1196 -static int devcrypto_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
1197 -{
1198 - int *new_list;
1199 - switch (cmd) {
1200 -#ifdef CIOCGSESSINFO
1201 - case DEVCRYPTO_CMD_USE_SOFTDRIVERS:
1202 - switch (i) {
1203 - case DEVCRYPTO_REQUIRE_ACCELERATED:
1204 - case DEVCRYPTO_USE_SOFTWARE:
1205 - case DEVCRYPTO_REJECT_SOFTWARE:
1206 - break;
1207 - default:
1208 - fprintf(stderr, "devcrypto: invalid value (%ld) for USE_SOFTDRIVERS\n", i);
1209 - return 0;
1210 - }
1211 - if (use_softdrivers == i)
1212 - return 1;
1213 - use_softdrivers = i;
1214 -#ifdef IMPLEMENT_DIGEST
1215 - rebuild_known_digest_nids(e);
1216 -#endif
1217 - rebuild_known_cipher_nids(e);
1218 - return 1;
1219 -#endif /* CIOCGSESSINFO */
1220 -
1221 - case DEVCRYPTO_CMD_CIPHERS:
1222 - if (p == NULL)
1223 - return 1;
1224 - if (strcasecmp((const char *)p, "ALL") == 0) {
1225 - devcrypto_select_all_ciphers(selected_ciphers);
1226 - } else if (strcasecmp((const char*)p, "NONE") == 0) {
1227 - memset(selected_ciphers, 0, sizeof(selected_ciphers));
1228 - } else {
1229 - new_list=OPENSSL_zalloc(sizeof(selected_ciphers));
1230 - if (!CONF_parse_list(p, ',', 1, cryptodev_select_cipher_cb, new_list)) {
1231 - OPENSSL_free(new_list);
1232 - return 0;
1233 - }
1234 - memcpy(selected_ciphers, new_list, sizeof(selected_ciphers));
1235 - OPENSSL_free(new_list);
1236 - }
1237 - rebuild_known_cipher_nids(e);
1238 - return 1;
1239 -
1240 -#ifdef IMPLEMENT_DIGEST
1241 - case DEVCRYPTO_CMD_DIGESTS:
1242 - if (p == NULL)
1243 - return 1;
1244 - if (strcasecmp((const char *)p, "ALL") == 0) {
1245 - devcrypto_select_all_digests(selected_digests);
1246 - } else if (strcasecmp((const char*)p, "NONE") == 0) {
1247 - memset(selected_digests, 0, sizeof(selected_digests));
1248 - } else {
1249 - new_list=OPENSSL_zalloc(sizeof(selected_digests));
1250 - if (!CONF_parse_list(p, ',', 1, cryptodev_select_digest_cb, new_list)) {
1251 - OPENSSL_free(new_list);
1252 - return 0;
1253 - }
1254 - memcpy(selected_digests, new_list, sizeof(selected_digests));
1255 - OPENSSL_free(new_list);
1256 - }
1257 - rebuild_known_digest_nids(e);
1258 - return 1;
1259 -#endif /* IMPLEMENT_DIGEST */
1260 -
1261 - case DEVCRYPTO_CMD_DUMP_INFO:
1262 - dump_cipher_info();
1263 -#ifdef IMPLEMENT_DIGEST
1264 - dump_digest_info();
1265 -#endif
1266 - return 1;
1267 -
1268 - default:
1269 - break;
1270 - }
1271 - return 0;
1272 -}
1273 -
1274 -/******************************************************************************
1275 - *
1276 - * LOAD / UNLOAD
1277 - *
1278 - *****/
1279 -
1280 -static int devcrypto_unload(ENGINE *e)
1281 -{
1282 - destroy_all_cipher_methods();
1283 -#ifdef IMPLEMENT_DIGEST
1284 - destroy_all_digest_methods();
1285 -#endif
1286 -
1287 - close(cfd);
1288 -
1289 - return 1;
1290 -}
1291 -/*
1292 - * This engine is always built into libcrypto, so it doesn't offer any
1293 - * ability to be dynamically loadable.
1294 - */
1295 -void engine_load_devcrypto_int()
1296 -{
1297 - ENGINE *e = NULL;
1298 - int fd;
1299 -
1300 - if ((fd = open("/dev/crypto", O_RDWR, 0)) < 0) {
1301 -#ifndef ENGINE_DEVCRYPTO_DEBUG
1302 - if (errno != ENOENT)
1303 -#endif
1304 - fprintf(stderr, "Could not open /dev/crypto: %s\n", strerror(errno));
1305 - return;
1306 - }
1307 -
1308 -#ifdef CRIOGET
1309 - if (ioctl(fd, CRIOGET, &cfd) < 0) {
1310 - fprintf(stderr, "Could not create crypto fd: %s\n", strerror(errno));
1311 - close(fd);
1312 - cfd = -1;
1313 - return;
1314 - }
1315 - close(fd);
1316 -#else
1317 - cfd = fd;
1318 -#endif
1319 -
1320 - if ((e = ENGINE_new()) == NULL
1321 - || !ENGINE_set_destroy_function(e, devcrypto_unload)) {
1322 - ENGINE_free(e);
1323 - /*
1324 - * We know that devcrypto_unload() won't be called when one of the
1325 - * above two calls have failed, so we close cfd explicitly here to
1326 - * avoid leaking resources.
1327 - */
1328 - close(cfd);
1329 - return;
1330 - }
1331 -
1332 - prepare_cipher_methods();
1333 -#ifdef IMPLEMENT_DIGEST
1334 - prepare_digest_methods();
1335 -#endif
1336 -
1337 - if (!ENGINE_set_id(e, "devcrypto")
1338 - || !ENGINE_set_name(e, "/dev/crypto engine")
1339 - || !ENGINE_set_cmd_defns(e, devcrypto_cmds)
1340 - || !ENGINE_set_ctrl_function(e, devcrypto_ctrl)
1341 -
1342 -/*
1343 - * Asymmetric ciphers aren't well supported with /dev/crypto. Among the BSD
1344 - * implementations, it seems to only exist in FreeBSD, and regarding the
1345 - * parameters in its crypt_kop, the manual crypto(4) has this to say:
1346 - *
1347 - * The semantics of these arguments are currently undocumented.
1348 - *
1349 - * Reading through the FreeBSD source code doesn't give much more than
1350 - * their CRK_MOD_EXP implementation for ubsec.
1351 - *
1352 - * It doesn't look much better with cryptodev-linux. They have the crypt_kop
1353 - * structure as well as the command (CRK_*) in cryptodev.h, but no support
1354 - * seems to be implemented at all for the moment.
1355 - *
1356 - * At the time of writing, it seems impossible to write proper support for
1357 - * FreeBSD's asym features without some very deep knowledge and access to
1358 - * specific kernel modules.
1359 - *
1360 - * /Richard Levitte, 2017-05-11
1361 - */
1362 -#if 0
1363 -# ifndef OPENSSL_NO_RSA
1364 - || !ENGINE_set_RSA(e, devcrypto_rsa)
1365 -# endif
1366 -# ifndef OPENSSL_NO_DSA
1367 - || !ENGINE_set_DSA(e, devcrypto_dsa)
1368 -# endif
1369 -# ifndef OPENSSL_NO_DH
1370 - || !ENGINE_set_DH(e, devcrypto_dh)
1371 -# endif
1372 -# ifndef OPENSSL_NO_EC
1373 - || !ENGINE_set_EC(e, devcrypto_ec)
1374 -# endif
1375 -#endif
1376 - || !ENGINE_set_ciphers(e, devcrypto_ciphers)
1377 -#ifdef IMPLEMENT_DIGEST
1378 - || !ENGINE_set_digests(e, devcrypto_digests)
1379 -#endif
1380 - ) {
1381 - ENGINE_free(e);
1382 - return;
1383 - }
1384 -
1385 - ENGINE_add(e);
1386 - ENGINE_free(e); /* Loose our local reference */
1387 - ERR_clear_error();
1388 -}
1389 --- /dev/null
1390 +++ b/engines/e_devcrypto.c
1391 @@ -0,0 +1,1327 @@
1392 +/*
1393 + * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
1394 + *
1395 + * Licensed under the OpenSSL license (the "License"). You may not use
1396 + * this file except in compliance with the License. You can obtain a copy
1397 + * in the file LICENSE in the source distribution or at
1398 + * https://www.openssl.org/source/license.html
1399 + */
1400 +
1401 +#include "../e_os.h"
1402 +#include <string.h>
1403 +#include <sys/types.h>
1404 +#include <sys/stat.h>
1405 +#include <fcntl.h>
1406 +#include <sys/ioctl.h>
1407 +#include <unistd.h>
1408 +#include <assert.h>
1409 +
1410 +#include <openssl/conf.h>
1411 +#include <openssl/evp.h>
1412 +#include <openssl/err.h>
1413 +#include <openssl/engine.h>
1414 +#include <openssl/objects.h>
1415 +#include <crypto/cryptodev.h>
1416 +
1417 +#include "crypto/engine.h"
1418 +
1419 +/* #define ENGINE_DEVCRYPTO_DEBUG */
1420 +
1421 +#if CRYPTO_ALGORITHM_MIN < CRYPTO_ALGORITHM_MAX
1422 +# define CHECK_BSD_STYLE_MACROS
1423 +#endif
1424 +
1425 +#define engine_devcrypto_id "devcrypto"
1426 +
1427 +/*
1428 + * ONE global file descriptor for all sessions. This allows operations
1429 + * such as digest session data copying (see digest_copy()), but is also
1430 + * saner... why re-open /dev/crypto for every session?
1431 + */
1432 +static int cfd = -1;
1433 +#define DEVCRYPTO_REQUIRE_ACCELERATED 0 /* require confirmation of acceleration */
1434 +#define DEVCRYPTO_USE_SOFTWARE 1 /* allow software drivers */
1435 +#define DEVCRYPTO_REJECT_SOFTWARE 2 /* only disallow confirmed software drivers */
1436 +
1437 +#define DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS DEVCRYPTO_REJECT_SOFTWARE
1438 +static int use_softdrivers = DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS;
1439 +
1440 +/*
1441 + * cipher/digest status & acceleration definitions
1442 + * Make sure the defaults are set to 0
1443 + */
1444 +struct driver_info_st {
1445 + enum devcrypto_status_t {
1446 + DEVCRYPTO_STATUS_FAILURE = -3, /* unusable for other reason */
1447 + DEVCRYPTO_STATUS_NO_CIOCCPHASH = -2, /* hash state copy not supported */
1448 + DEVCRYPTO_STATUS_NO_CIOCGSESSION = -1, /* session open failed */
1449 + DEVCRYPTO_STATUS_UNKNOWN = 0, /* not tested yet */
1450 + DEVCRYPTO_STATUS_USABLE = 1 /* algo can be used */
1451 + } status;
1452 +
1453 + enum devcrypto_accelerated_t {
1454 + DEVCRYPTO_NOT_ACCELERATED = -1, /* software implemented */
1455 + DEVCRYPTO_ACCELERATION_UNKNOWN = 0, /* acceleration support unkown */
1456 + DEVCRYPTO_ACCELERATED = 1 /* hardware accelerated */
1457 + } accelerated;
1458 +
1459 + char *driver_name;
1460 +};
1461 +
1462 +static int clean_devcrypto_session(struct session_op *sess) {
1463 + if (ioctl(cfd, CIOCFSESSION, &sess->ses) < 0) {
1464 + SYSerr(SYS_F_IOCTL, errno);
1465 + return 0;
1466 + }
1467 + memset(sess, 0, sizeof(struct session_op));
1468 + return 1;
1469 +}
1470 +
1471 +/******************************************************************************
1472 + *
1473 + * Ciphers
1474 + *
1475 + * Because they all do the same basic operation, we have only one set of
1476 + * method functions for them all to share, and a mapping table between
1477 + * NIDs and cryptodev IDs, with all the necessary size data.
1478 + *
1479 + *****/
1480 +
1481 +struct cipher_ctx {
1482 + struct session_op sess;
1483 + int op; /* COP_ENCRYPT or COP_DECRYPT */
1484 + unsigned long mode; /* EVP_CIPH_*_MODE */
1485 +
1486 + /* to handle ctr mode being a stream cipher */
1487 + unsigned char partial[EVP_MAX_BLOCK_LENGTH];
1488 + unsigned int blocksize, num;
1489 +};
1490 +
1491 +static const struct cipher_data_st {
1492 + int nid;
1493 + int blocksize;
1494 + int keylen;
1495 + int ivlen;
1496 + int flags;
1497 + int devcryptoid;
1498 +} cipher_data[] = {
1499 +#ifndef OPENSSL_NO_DES
1500 + { NID_des_cbc, 8, 8, 8, EVP_CIPH_CBC_MODE, CRYPTO_DES_CBC },
1501 + { NID_des_ede3_cbc, 8, 24, 8, EVP_CIPH_CBC_MODE, CRYPTO_3DES_CBC },
1502 +#endif
1503 +#ifndef OPENSSL_NO_BF
1504 + { NID_bf_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_BLF_CBC },
1505 +#endif
1506 +#ifndef OPENSSL_NO_CAST
1507 + { NID_cast5_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_CAST_CBC },
1508 +#endif
1509 + { NID_aes_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
1510 + { NID_aes_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
1511 + { NID_aes_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
1512 +#ifndef OPENSSL_NO_RC4
1513 + { NID_rc4, 1, 16, 0, EVP_CIPH_STREAM_CIPHER, CRYPTO_ARC4 },
1514 +#endif
1515 +#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_CTR)
1516 + { NID_aes_128_ctr, 16, 128 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
1517 + { NID_aes_192_ctr, 16, 192 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
1518 + { NID_aes_256_ctr, 16, 256 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
1519 +#endif
1520 +#if 0 /* Not yet supported */
1521 + { NID_aes_128_xts, 16, 128 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS },
1522 + { NID_aes_256_xts, 16, 256 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS },
1523 +#endif
1524 +#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_ECB)
1525 + { NID_aes_128_ecb, 16, 128 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
1526 + { NID_aes_192_ecb, 16, 192 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
1527 + { NID_aes_256_ecb, 16, 256 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
1528 +#endif
1529 +#if 0 /* Not yet supported */
1530 + { NID_aes_128_gcm, 16, 128 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
1531 + { NID_aes_192_gcm, 16, 192 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
1532 + { NID_aes_256_gcm, 16, 256 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
1533 +#endif
1534 +#ifndef OPENSSL_NO_CAMELLIA
1535 + { NID_camellia_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE,
1536 + CRYPTO_CAMELLIA_CBC },
1537 + { NID_camellia_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE,
1538 + CRYPTO_CAMELLIA_CBC },
1539 + { NID_camellia_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE,
1540 + CRYPTO_CAMELLIA_CBC },
1541 +#endif
1542 +};
1543 +
1544 +static size_t find_cipher_data_index(int nid)
1545 +{
1546 + size_t i;
1547 +
1548 + for (i = 0; i < OSSL_NELEM(cipher_data); i++)
1549 + if (nid == cipher_data[i].nid)
1550 + return i;
1551 + return (size_t)-1;
1552 +}
1553 +
1554 +static size_t get_cipher_data_index(int nid)
1555 +{
1556 + size_t i = find_cipher_data_index(nid);
1557 +
1558 + if (i != (size_t)-1)
1559 + return i;
1560 +
1561 + /*
1562 + * Code further down must make sure that only NIDs in the table above
1563 + * are used. If any other NID reaches this function, there's a grave
1564 + * coding error further down.
1565 + */
1566 + assert("Code that never should be reached" == NULL);
1567 + return -1;
1568 +}
1569 +
1570 +static const struct cipher_data_st *get_cipher_data(int nid)
1571 +{
1572 + return &cipher_data[get_cipher_data_index(nid)];
1573 +}
1574 +
1575 +/*
1576 + * Following are the three necessary functions to map OpenSSL functionality
1577 + * with cryptodev.
1578 + */
1579 +
1580 +static int cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
1581 + const unsigned char *iv, int enc)
1582 +{
1583 + struct cipher_ctx *cipher_ctx =
1584 + (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
1585 + const struct cipher_data_st *cipher_d =
1586 + get_cipher_data(EVP_CIPHER_CTX_nid(ctx));
1587 +
1588 + /* cleanup a previous session */
1589 + if (cipher_ctx->sess.ses != 0 &&
1590 + clean_devcrypto_session(&cipher_ctx->sess) == 0)
1591 + return 0;
1592 +
1593 + cipher_ctx->sess.cipher = cipher_d->devcryptoid;
1594 + cipher_ctx->sess.keylen = cipher_d->keylen;
1595 + cipher_ctx->sess.key = (void *)key;
1596 + cipher_ctx->op = enc ? COP_ENCRYPT : COP_DECRYPT;
1597 + cipher_ctx->mode = cipher_d->flags & EVP_CIPH_MODE;
1598 + cipher_ctx->blocksize = cipher_d->blocksize;
1599 + if (ioctl(cfd, CIOCGSESSION, &cipher_ctx->sess) < 0) {
1600 + SYSerr(SYS_F_IOCTL, errno);
1601 + return 0;
1602 + }
1603 +
1604 + return 1;
1605 +}
1606 +
1607 +static int cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
1608 + const unsigned char *in, size_t inl)
1609 +{
1610 + struct cipher_ctx *cipher_ctx =
1611 + (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
1612 + struct crypt_op cryp;
1613 + unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
1614 +#if !defined(COP_FLAG_WRITE_IV)
1615 + unsigned char saved_iv[EVP_MAX_IV_LENGTH];
1616 + const unsigned char *ivptr;
1617 + size_t nblocks, ivlen;
1618 +#endif
1619 +
1620 + memset(&cryp, 0, sizeof(cryp));
1621 + cryp.ses = cipher_ctx->sess.ses;
1622 + cryp.len = inl;
1623 + cryp.src = (void *)in;
1624 + cryp.dst = (void *)out;
1625 + cryp.iv = (void *)iv;
1626 + cryp.op = cipher_ctx->op;
1627 +#if !defined(COP_FLAG_WRITE_IV)
1628 + cryp.flags = 0;
1629 +
1630 + ivlen = EVP_CIPHER_CTX_iv_length(ctx);
1631 + if (ivlen > 0)
1632 + switch (cipher_ctx->mode) {
1633 + case EVP_CIPH_CBC_MODE:
1634 + assert(inl >= ivlen);
1635 + if (!EVP_CIPHER_CTX_encrypting(ctx)) {
1636 + ivptr = in + inl - ivlen;
1637 + memcpy(saved_iv, ivptr, ivlen);
1638 + }
1639 + break;
1640 +
1641 + case EVP_CIPH_CTR_MODE:
1642 + break;
1643 +
1644 + default: /* should not happen */
1645 + return 0;
1646 + }
1647 +#else
1648 + cryp.flags = COP_FLAG_WRITE_IV;
1649 +#endif
1650 +
1651 + if (ioctl(cfd, CIOCCRYPT, &cryp) < 0) {
1652 + SYSerr(SYS_F_IOCTL, errno);
1653 + return 0;
1654 + }
1655 +
1656 +#if !defined(COP_FLAG_WRITE_IV)
1657 + if (ivlen > 0)
1658 + switch (cipher_ctx->mode) {
1659 + case EVP_CIPH_CBC_MODE:
1660 + assert(inl >= ivlen);
1661 + if (EVP_CIPHER_CTX_encrypting(ctx))
1662 + ivptr = out + inl - ivlen;
1663 + else
1664 + ivptr = saved_iv;
1665 +
1666 + memcpy(iv, ivptr, ivlen);
1667 + break;
1668 +
1669 + case EVP_CIPH_CTR_MODE:
1670 + nblocks = (inl + cipher_ctx->blocksize - 1)
1671 + / cipher_ctx->blocksize;
1672 + do {
1673 + ivlen--;
1674 + nblocks += iv[ivlen];
1675 + iv[ivlen] = (uint8_t) nblocks;
1676 + nblocks >>= 8;
1677 + } while (ivlen);
1678 + break;
1679 +
1680 + default: /* should not happen */
1681 + return 0;
1682 + }
1683 +#endif
1684 +
1685 + return 1;
1686 +}
1687 +
1688 +static int ctr_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
1689 + const unsigned char *in, size_t inl)
1690 +{
1691 + struct cipher_ctx *cipher_ctx =
1692 + (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
1693 + size_t nblocks, len;
1694 +
1695 + /* initial partial block */
1696 + while (cipher_ctx->num && inl) {
1697 + (*out++) = *(in++) ^ cipher_ctx->partial[cipher_ctx->num];
1698 + --inl;
1699 + cipher_ctx->num = (cipher_ctx->num + 1) % cipher_ctx->blocksize;
1700 + }
1701 +
1702 + /* full blocks */
1703 + if (inl > (unsigned int) cipher_ctx->blocksize) {
1704 + nblocks = inl/cipher_ctx->blocksize;
1705 + len = nblocks * cipher_ctx->blocksize;
1706 + if (cipher_do_cipher(ctx, out, in, len) < 1)
1707 + return 0;
1708 + inl -= len;
1709 + out += len;
1710 + in += len;
1711 + }
1712 +
1713 + /* final partial block */
1714 + if (inl) {
1715 + memset(cipher_ctx->partial, 0, cipher_ctx->blocksize);
1716 + if (cipher_do_cipher(ctx, cipher_ctx->partial, cipher_ctx->partial,
1717 + cipher_ctx->blocksize) < 1)
1718 + return 0;
1719 + while (inl--) {
1720 + out[cipher_ctx->num] = in[cipher_ctx->num]
1721 + ^ cipher_ctx->partial[cipher_ctx->num];
1722 + cipher_ctx->num++;
1723 + }
1724 + }
1725 +
1726 + return 1;
1727 +}
1728 +
1729 +static int cipher_ctrl(EVP_CIPHER_CTX *ctx, int type, int p1, void* p2)
1730 +{
1731 + struct cipher_ctx *cipher_ctx =
1732 + (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
1733 + EVP_CIPHER_CTX *to_ctx = (EVP_CIPHER_CTX *)p2;
1734 + struct cipher_ctx *to_cipher_ctx;
1735 +
1736 + switch (type) {
1737 + case EVP_CTRL_COPY:
1738 + if (cipher_ctx == NULL)
1739 + return 1;
1740 + /* when copying the context, a new session needs to be initialized */
1741 + to_cipher_ctx =
1742 + (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(to_ctx);
1743 + memset(&to_cipher_ctx->sess, 0, sizeof(to_cipher_ctx->sess));
1744 + return cipher_init(to_ctx, cipher_ctx->sess.key, EVP_CIPHER_CTX_iv(ctx),
1745 + (cipher_ctx->op == COP_ENCRYPT));
1746 +
1747 + case EVP_CTRL_INIT:
1748 + memset(&cipher_ctx->sess, 0, sizeof(cipher_ctx->sess));
1749 + return 1;
1750 +
1751 + default:
1752 + break;
1753 + }
1754 +
1755 + return -1;
1756 +}
1757 +
1758 +static int cipher_cleanup(EVP_CIPHER_CTX *ctx)
1759 +{
1760 + struct cipher_ctx *cipher_ctx =
1761 + (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
1762 +
1763 + return clean_devcrypto_session(&cipher_ctx->sess);
1764 +}
1765 +
1766 +/*
1767 + * Keep tables of known nids, associated methods, selected ciphers, and driver
1768 + * info.
1769 + * Note that known_cipher_nids[] isn't necessarily indexed the same way as
1770 + * cipher_data[] above, which the other tables are.
1771 + */
1772 +static int known_cipher_nids[OSSL_NELEM(cipher_data)];
1773 +static int known_cipher_nids_amount = -1; /* -1 indicates not yet initialised */
1774 +static EVP_CIPHER *known_cipher_methods[OSSL_NELEM(cipher_data)] = { NULL, };
1775 +static int selected_ciphers[OSSL_NELEM(cipher_data)];
1776 +static struct driver_info_st cipher_driver_info[OSSL_NELEM(cipher_data)];
1777 +
1778 +
1779 +static int devcrypto_test_cipher(size_t cipher_data_index)
1780 +{
1781 + return (cipher_driver_info[cipher_data_index].status == DEVCRYPTO_STATUS_USABLE
1782 + && selected_ciphers[cipher_data_index] == 1
1783 + && (cipher_driver_info[cipher_data_index].accelerated
1784 + == DEVCRYPTO_ACCELERATED
1785 + || use_softdrivers == DEVCRYPTO_USE_SOFTWARE
1786 + || (cipher_driver_info[cipher_data_index].accelerated
1787 + != DEVCRYPTO_NOT_ACCELERATED
1788 + && use_softdrivers == DEVCRYPTO_REJECT_SOFTWARE)));
1789 +}
1790 +
1791 +static void prepare_cipher_methods(void)
1792 +{
1793 + size_t i;
1794 + struct session_op sess;
1795 + unsigned long cipher_mode;
1796 +#ifdef CIOCGSESSINFO
1797 + struct session_info_op siop;
1798 +#endif
1799 +
1800 + memset(&cipher_driver_info, 0, sizeof(cipher_driver_info));
1801 +
1802 + memset(&sess, 0, sizeof(sess));
1803 + sess.key = (void *)"01234567890123456789012345678901234567890123456789";
1804 +
1805 + for (i = 0, known_cipher_nids_amount = 0;
1806 + i < OSSL_NELEM(cipher_data); i++) {
1807 +
1808 + selected_ciphers[i] = 1;
1809 + /*
1810 + * Check that the cipher is usable
1811 + */
1812 + sess.cipher = cipher_data[i].devcryptoid;
1813 + sess.keylen = cipher_data[i].keylen;
1814 + if (ioctl(cfd, CIOCGSESSION, &sess) < 0) {
1815 + cipher_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION;
1816 + continue;
1817 + }
1818 +
1819 + cipher_mode = cipher_data[i].flags & EVP_CIPH_MODE;
1820 +
1821 + if ((known_cipher_methods[i] =
1822 + EVP_CIPHER_meth_new(cipher_data[i].nid,
1823 + cipher_mode == EVP_CIPH_CTR_MODE ? 1 :
1824 + cipher_data[i].blocksize,
1825 + cipher_data[i].keylen)) == NULL
1826 + || !EVP_CIPHER_meth_set_iv_length(known_cipher_methods[i],
1827 + cipher_data[i].ivlen)
1828 + || !EVP_CIPHER_meth_set_flags(known_cipher_methods[i],
1829 + cipher_data[i].flags
1830 + | EVP_CIPH_CUSTOM_COPY
1831 + | EVP_CIPH_CTRL_INIT
1832 + | EVP_CIPH_FLAG_DEFAULT_ASN1)
1833 + || !EVP_CIPHER_meth_set_init(known_cipher_methods[i], cipher_init)
1834 + || !EVP_CIPHER_meth_set_do_cipher(known_cipher_methods[i],
1835 + cipher_mode == EVP_CIPH_CTR_MODE ?
1836 + ctr_do_cipher :
1837 + cipher_do_cipher)
1838 + || !EVP_CIPHER_meth_set_ctrl(known_cipher_methods[i], cipher_ctrl)
1839 + || !EVP_CIPHER_meth_set_cleanup(known_cipher_methods[i],
1840 + cipher_cleanup)
1841 + || !EVP_CIPHER_meth_set_impl_ctx_size(known_cipher_methods[i],
1842 + sizeof(struct cipher_ctx))) {
1843 + cipher_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
1844 + EVP_CIPHER_meth_free(known_cipher_methods[i]);
1845 + known_cipher_methods[i] = NULL;
1846 + } else {
1847 + cipher_driver_info[i].status = DEVCRYPTO_STATUS_USABLE;
1848 +#ifdef CIOCGSESSINFO
1849 + siop.ses = sess.ses;
1850 + if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) {
1851 + cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN;
1852 + } else {
1853 + cipher_driver_info[i].driver_name =
1854 + OPENSSL_strndup(siop.cipher_info.cra_driver_name,
1855 + CRYPTODEV_MAX_ALG_NAME);
1856 + if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY))
1857 + cipher_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED;
1858 + else
1859 + cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED;
1860 + }
1861 +#endif /* CIOCGSESSINFO */
1862 + }
1863 + ioctl(cfd, CIOCFSESSION, &sess.ses);
1864 + if (devcrypto_test_cipher(i)) {
1865 + known_cipher_nids[known_cipher_nids_amount++] =
1866 + cipher_data[i].nid;
1867 + }
1868 + }
1869 +}
1870 +
1871 +static void rebuild_known_cipher_nids(ENGINE *e)
1872 +{
1873 + size_t i;
1874 +
1875 + for (i = 0, known_cipher_nids_amount = 0; i < OSSL_NELEM(cipher_data); i++) {
1876 + if (devcrypto_test_cipher(i))
1877 + known_cipher_nids[known_cipher_nids_amount++] = cipher_data[i].nid;
1878 + }
1879 + ENGINE_unregister_ciphers(e);
1880 + ENGINE_register_ciphers(e);
1881 +}
1882 +
1883 +static const EVP_CIPHER *get_cipher_method(int nid)
1884 +{
1885 + size_t i = get_cipher_data_index(nid);
1886 +
1887 + if (i == (size_t)-1)
1888 + return NULL;
1889 + return known_cipher_methods[i];
1890 +}
1891 +
1892 +static int get_cipher_nids(const int **nids)
1893 +{
1894 + *nids = known_cipher_nids;
1895 + return known_cipher_nids_amount;
1896 +}
1897 +
1898 +static void destroy_cipher_method(int nid)
1899 +{
1900 + size_t i = get_cipher_data_index(nid);
1901 +
1902 + EVP_CIPHER_meth_free(known_cipher_methods[i]);
1903 + known_cipher_methods[i] = NULL;
1904 +}
1905 +
1906 +static void destroy_all_cipher_methods(void)
1907 +{
1908 + size_t i;
1909 +
1910 + for (i = 0; i < OSSL_NELEM(cipher_data); i++) {
1911 + destroy_cipher_method(cipher_data[i].nid);
1912 + OPENSSL_free(cipher_driver_info[i].driver_name);
1913 + cipher_driver_info[i].driver_name = NULL;
1914 + }
1915 +}
1916 +
1917 +static int devcrypto_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
1918 + const int **nids, int nid)
1919 +{
1920 + if (cipher == NULL)
1921 + return get_cipher_nids(nids);
1922 +
1923 + *cipher = get_cipher_method(nid);
1924 +
1925 + return *cipher != NULL;
1926 +}
1927 +
1928 +static void devcrypto_select_all_ciphers(int *cipher_list)
1929 +{
1930 + size_t i;
1931 +
1932 + for (i = 0; i < OSSL_NELEM(cipher_data); i++)
1933 + cipher_list[i] = 1;
1934 +}
1935 +
1936 +static int cryptodev_select_cipher_cb(const char *str, int len, void *usr)
1937 +{
1938 + int *cipher_list = (int *)usr;
1939 + char *name;
1940 + const EVP_CIPHER *EVP;
1941 + size_t i;
1942 +
1943 + if (len == 0)
1944 + return 1;
1945 + if (usr == NULL || (name = OPENSSL_strndup(str, len)) == NULL)
1946 + return 0;
1947 + EVP = EVP_get_cipherbyname(name);
1948 + if (EVP == NULL)
1949 + fprintf(stderr, "devcrypto: unknown cipher %s\n", name);
1950 + else if ((i = find_cipher_data_index(EVP_CIPHER_nid(EVP))) != (size_t)-1)
1951 + cipher_list[i] = 1;
1952 + else
1953 + fprintf(stderr, "devcrypto: cipher %s not available\n", name);
1954 + OPENSSL_free(name);
1955 + return 1;
1956 +}
1957 +
1958 +static void dump_cipher_info(void)
1959 +{
1960 + size_t i;
1961 + const char *name;
1962 +
1963 + fprintf (stderr, "Information about ciphers supported by the /dev/crypto"
1964 + " engine:\n");
1965 +#ifndef CIOCGSESSINFO
1966 + fprintf(stderr, "CIOCGSESSINFO (session info call) unavailable\n");
1967 +#endif
1968 + for (i = 0; i < OSSL_NELEM(cipher_data); i++) {
1969 + name = OBJ_nid2sn(cipher_data[i].nid);
1970 + fprintf (stderr, "Cipher %s, NID=%d, /dev/crypto info: id=%d, ",
1971 + name ? name : "unknown", cipher_data[i].nid,
1972 + cipher_data[i].devcryptoid);
1973 + if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCGSESSION ) {
1974 + fprintf (stderr, "CIOCGSESSION (session open call) failed\n");
1975 + continue;
1976 + }
1977 + fprintf (stderr, "driver=%s ", cipher_driver_info[i].driver_name ?
1978 + cipher_driver_info[i].driver_name : "unknown");
1979 + if (cipher_driver_info[i].accelerated == DEVCRYPTO_ACCELERATED)
1980 + fprintf(stderr, "(hw accelerated)");
1981 + else if (cipher_driver_info[i].accelerated == DEVCRYPTO_NOT_ACCELERATED)
1982 + fprintf(stderr, "(software)");
1983 + else
1984 + fprintf(stderr, "(acceleration status unknown)");
1985 + if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_FAILURE)
1986 + fprintf (stderr, ". Cipher setup failed");
1987 + fprintf(stderr, "\n");
1988 + }
1989 + fprintf(stderr, "\n");
1990 +}
1991 +
1992 +/*
1993 + * We only support digests if the cryptodev implementation supports multiple
1994 + * data updates and session copying. Otherwise, we would be forced to maintain
1995 + * a cache, which is perilous if there's a lot of data coming in (if someone
1996 + * wants to checksum an OpenSSL tarball, for example).
1997 + */
1998 +#if defined(CIOCCPHASH) && defined(COP_FLAG_UPDATE) && defined(COP_FLAG_FINAL)
1999 +#define IMPLEMENT_DIGEST
2000 +
2001 +/******************************************************************************
2002 + *
2003 + * Digests
2004 + *
2005 + * Because they all do the same basic operation, we have only one set of
2006 + * method functions for them all to share, and a mapping table between
2007 + * NIDs and cryptodev IDs, with all the necessary size data.
2008 + *
2009 + *****/
2010 +
2011 +struct digest_ctx {
2012 + struct session_op sess;
2013 + /* This signals that the init function was called, not that it succeeded. */
2014 + int init_called;
2015 + unsigned char digest_res[HASH_MAX_LEN];
2016 +};
2017 +
2018 +static const struct digest_data_st {
2019 + int nid;
2020 + int blocksize;
2021 + int digestlen;
2022 + int devcryptoid;
2023 +} digest_data[] = {
2024 +#ifndef OPENSSL_NO_MD5
2025 + { NID_md5, /* MD5_CBLOCK */ 64, 16, CRYPTO_MD5 },
2026 +#endif
2027 + { NID_sha1, SHA_CBLOCK, 20, CRYPTO_SHA1 },
2028 +#ifndef OPENSSL_NO_RMD160
2029 +# if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_RIPEMD160)
2030 + { NID_ripemd160, /* RIPEMD160_CBLOCK */ 64, 20, CRYPTO_RIPEMD160 },
2031 +# endif
2032 +#endif
2033 +#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_224)
2034 + { NID_sha224, SHA256_CBLOCK, 224 / 8, CRYPTO_SHA2_224 },
2035 +#endif
2036 +#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_256)
2037 + { NID_sha256, SHA256_CBLOCK, 256 / 8, CRYPTO_SHA2_256 },
2038 +#endif
2039 +#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_384)
2040 + { NID_sha384, SHA512_CBLOCK, 384 / 8, CRYPTO_SHA2_384 },
2041 +#endif
2042 +#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_512)
2043 + { NID_sha512, SHA512_CBLOCK, 512 / 8, CRYPTO_SHA2_512 },
2044 +#endif
2045 +};
2046 +
2047 +static size_t find_digest_data_index(int nid)
2048 +{
2049 + size_t i;
2050 +
2051 + for (i = 0; i < OSSL_NELEM(digest_data); i++)
2052 + if (nid == digest_data[i].nid)
2053 + return i;
2054 + return (size_t)-1;
2055 +}
2056 +
2057 +static size_t get_digest_data_index(int nid)
2058 +{
2059 + size_t i = find_digest_data_index(nid);
2060 +
2061 + if (i != (size_t)-1)
2062 + return i;
2063 +
2064 + /*
2065 + * Code further down must make sure that only NIDs in the table above
2066 + * are used. If any other NID reaches this function, there's a grave
2067 + * coding error further down.
2068 + */
2069 + assert("Code that never should be reached" == NULL);
2070 + return -1;
2071 +}
2072 +
2073 +static const struct digest_data_st *get_digest_data(int nid)
2074 +{
2075 + return &digest_data[get_digest_data_index(nid)];
2076 +}
2077 +
2078 +/*
2079 + * Following are the five necessary functions to map OpenSSL functionality
2080 + * with cryptodev: init, update, final, cleanup, and copy.
2081 + */
2082 +
2083 +static int digest_init(EVP_MD_CTX *ctx)
2084 +{
2085 + struct digest_ctx *digest_ctx =
2086 + (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
2087 + const struct digest_data_st *digest_d =
2088 + get_digest_data(EVP_MD_CTX_type(ctx));
2089 +
2090 + digest_ctx->init_called = 1;
2091 +
2092 + memset(&digest_ctx->sess, 0, sizeof(digest_ctx->sess));
2093 + digest_ctx->sess.mac = digest_d->devcryptoid;
2094 + if (ioctl(cfd, CIOCGSESSION, &digest_ctx->sess) < 0) {
2095 + SYSerr(SYS_F_IOCTL, errno);
2096 + return 0;
2097 + }
2098 +
2099 + return 1;
2100 +}
2101 +
2102 +static int digest_op(struct digest_ctx *ctx, const void *src, size_t srclen,
2103 + void *res, unsigned int flags)
2104 +{
2105 + struct crypt_op cryp;
2106 +
2107 + memset(&cryp, 0, sizeof(cryp));
2108 + cryp.ses = ctx->sess.ses;
2109 + cryp.len = srclen;
2110 + cryp.src = (void *)src;
2111 + cryp.dst = NULL;
2112 + cryp.mac = res;
2113 + cryp.flags = flags;
2114 + return ioctl(cfd, CIOCCRYPT, &cryp);
2115 +}
2116 +
2117 +static int digest_update(EVP_MD_CTX *ctx, const void *data, size_t count)
2118 +{
2119 + struct digest_ctx *digest_ctx =
2120 + (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
2121 +
2122 + if (count == 0)
2123 + return 1;
2124 +
2125 + if (digest_ctx == NULL)
2126 + return 0;
2127 +
2128 + if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) {
2129 + if (digest_op(digest_ctx, data, count, digest_ctx->digest_res, 0) >= 0)
2130 + return 1;
2131 + } else if (digest_op(digest_ctx, data, count, NULL, COP_FLAG_UPDATE) >= 0) {
2132 + return 1;
2133 + }
2134 +
2135 + SYSerr(SYS_F_IOCTL, errno);
2136 + return 0;
2137 +}
2138 +
2139 +static int digest_final(EVP_MD_CTX *ctx, unsigned char *md)
2140 +{
2141 + struct digest_ctx *digest_ctx =
2142 + (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
2143 +
2144 + if (md == NULL || digest_ctx == NULL)
2145 + return 0;
2146 +
2147 + if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) {
2148 + memcpy(md, digest_ctx->digest_res, EVP_MD_CTX_size(ctx));
2149 + } else if (digest_op(digest_ctx, NULL, 0, md, COP_FLAG_FINAL) < 0) {
2150 + SYSerr(SYS_F_IOCTL, errno);
2151 + return 0;
2152 + }
2153 +
2154 + return 1;
2155 +}
2156 +
2157 +static int digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
2158 +{
2159 + struct digest_ctx *digest_from =
2160 + (struct digest_ctx *)EVP_MD_CTX_md_data(from);
2161 + struct digest_ctx *digest_to =
2162 + (struct digest_ctx *)EVP_MD_CTX_md_data(to);
2163 + struct cphash_op cphash;
2164 +
2165 + if (digest_from == NULL || digest_from->init_called != 1)
2166 + return 1;
2167 +
2168 + if (!digest_init(to)) {
2169 + SYSerr(SYS_F_IOCTL, errno);
2170 + return 0;
2171 + }
2172 +
2173 + cphash.src_ses = digest_from->sess.ses;
2174 + cphash.dst_ses = digest_to->sess.ses;
2175 + if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) {
2176 + SYSerr(SYS_F_IOCTL, errno);
2177 + return 0;
2178 + }
2179 + return 1;
2180 +}
2181 +
2182 +static int digest_cleanup(EVP_MD_CTX *ctx)
2183 +{
2184 + struct digest_ctx *digest_ctx =
2185 + (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
2186 +
2187 + if (digest_ctx == NULL)
2188 + return 1;
2189 +
2190 + return clean_devcrypto_session(&digest_ctx->sess);
2191 +}
2192 +
2193 +/*
2194 + * Keep tables of known nids, associated methods, selected digests, and
2195 + * driver info.
2196 + * Note that known_digest_nids[] isn't necessarily indexed the same way as
2197 + * digest_data[] above, which the other tables are.
2198 + */
2199 +static int known_digest_nids[OSSL_NELEM(digest_data)];
2200 +static int known_digest_nids_amount = -1; /* -1 indicates not yet initialised */
2201 +static EVP_MD *known_digest_methods[OSSL_NELEM(digest_data)] = { NULL, };
2202 +static int selected_digests[OSSL_NELEM(digest_data)];
2203 +static struct driver_info_st digest_driver_info[OSSL_NELEM(digest_data)];
2204 +
2205 +static int devcrypto_test_digest(size_t digest_data_index)
2206 +{
2207 + return (digest_driver_info[digest_data_index].status == DEVCRYPTO_STATUS_USABLE
2208 + && selected_digests[digest_data_index] == 1
2209 + && (digest_driver_info[digest_data_index].accelerated
2210 + == DEVCRYPTO_ACCELERATED
2211 + || use_softdrivers == DEVCRYPTO_USE_SOFTWARE
2212 + || (digest_driver_info[digest_data_index].accelerated
2213 + != DEVCRYPTO_NOT_ACCELERATED
2214 + && use_softdrivers == DEVCRYPTO_REJECT_SOFTWARE)));
2215 +}
2216 +
2217 +static void rebuild_known_digest_nids(ENGINE *e)
2218 +{
2219 + size_t i;
2220 +
2221 + for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data); i++) {
2222 + if (devcrypto_test_digest(i))
2223 + known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid;
2224 + }
2225 + ENGINE_unregister_digests(e);
2226 + ENGINE_register_digests(e);
2227 +}
2228 +
2229 +static void prepare_digest_methods(void)
2230 +{
2231 + size_t i;
2232 + struct session_op sess1, sess2;
2233 +#ifdef CIOCGSESSINFO
2234 + struct session_info_op siop;
2235 +#endif
2236 + struct cphash_op cphash;
2237 +
2238 + memset(&digest_driver_info, 0, sizeof(digest_driver_info));
2239 +
2240 + memset(&sess1, 0, sizeof(sess1));
2241 + memset(&sess2, 0, sizeof(sess2));
2242 +
2243 + for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data);
2244 + i++) {
2245 +
2246 + selected_digests[i] = 1;
2247 +
2248 + /*
2249 + * Check that the digest is usable
2250 + */
2251 + sess1.mac = digest_data[i].devcryptoid;
2252 + sess2.ses = 0;
2253 + if (ioctl(cfd, CIOCGSESSION, &sess1) < 0) {
2254 + digest_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION;
2255 + goto finish;
2256 + }
2257 +
2258 +#ifdef CIOCGSESSINFO
2259 + /* gather hardware acceleration info from the driver */
2260 + siop.ses = sess1.ses;
2261 + if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) {
2262 + digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN;
2263 + } else {
2264 + digest_driver_info[i].driver_name =
2265 + OPENSSL_strndup(siop.hash_info.cra_driver_name,
2266 + CRYPTODEV_MAX_ALG_NAME);
2267 + if (siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)
2268 + digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED;
2269 + else
2270 + digest_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED;
2271 + }
2272 +#endif
2273 +
2274 + /* digest must be capable of hash state copy */
2275 + sess2.mac = sess1.mac;
2276 + if (ioctl(cfd, CIOCGSESSION, &sess2) < 0) {
2277 + digest_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
2278 + goto finish;
2279 + }
2280 + cphash.src_ses = sess1.ses;
2281 + cphash.dst_ses = sess2.ses;
2282 + if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) {
2283 + digest_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCCPHASH;
2284 + goto finish;
2285 + }
2286 + if ((known_digest_methods[i] = EVP_MD_meth_new(digest_data[i].nid,
2287 + NID_undef)) == NULL
2288 + || !EVP_MD_meth_set_input_blocksize(known_digest_methods[i],
2289 + digest_data[i].blocksize)
2290 + || !EVP_MD_meth_set_result_size(known_digest_methods[i],
2291 + digest_data[i].digestlen)
2292 + || !EVP_MD_meth_set_init(known_digest_methods[i], digest_init)
2293 + || !EVP_MD_meth_set_update(known_digest_methods[i], digest_update)
2294 + || !EVP_MD_meth_set_final(known_digest_methods[i], digest_final)
2295 + || !EVP_MD_meth_set_copy(known_digest_methods[i], digest_copy)
2296 + || !EVP_MD_meth_set_cleanup(known_digest_methods[i], digest_cleanup)
2297 + || !EVP_MD_meth_set_app_datasize(known_digest_methods[i],
2298 + sizeof(struct digest_ctx))) {
2299 + digest_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
2300 + EVP_MD_meth_free(known_digest_methods[i]);
2301 + known_digest_methods[i] = NULL;
2302 + goto finish;
2303 + }
2304 + digest_driver_info[i].status = DEVCRYPTO_STATUS_USABLE;
2305 +finish:
2306 + ioctl(cfd, CIOCFSESSION, &sess1.ses);
2307 + if (sess2.ses != 0)
2308 + ioctl(cfd, CIOCFSESSION, &sess2.ses);
2309 + if (devcrypto_test_digest(i))
2310 + known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid;
2311 + }
2312 +}
2313 +
2314 +static const EVP_MD *get_digest_method(int nid)
2315 +{
2316 + size_t i = get_digest_data_index(nid);
2317 +
2318 + if (i == (size_t)-1)
2319 + return NULL;
2320 + return known_digest_methods[i];
2321 +}
2322 +
2323 +static int get_digest_nids(const int **nids)
2324 +{
2325 + *nids = known_digest_nids;
2326 + return known_digest_nids_amount;
2327 +}
2328 +
2329 +static void destroy_digest_method(int nid)
2330 +{
2331 + size_t i = get_digest_data_index(nid);
2332 +
2333 + EVP_MD_meth_free(known_digest_methods[i]);
2334 + known_digest_methods[i] = NULL;
2335 +}
2336 +
2337 +static void destroy_all_digest_methods(void)
2338 +{
2339 + size_t i;
2340 +
2341 + for (i = 0; i < OSSL_NELEM(digest_data); i++) {
2342 + destroy_digest_method(digest_data[i].nid);
2343 + OPENSSL_free(digest_driver_info[i].driver_name);
2344 + digest_driver_info[i].driver_name = NULL;
2345 + }
2346 +}
2347 +
2348 +static int devcrypto_digests(ENGINE *e, const EVP_MD **digest,
2349 + const int **nids, int nid)
2350 +{
2351 + if (digest == NULL)
2352 + return get_digest_nids(nids);
2353 +
2354 + *digest = get_digest_method(nid);
2355 +
2356 + return *digest != NULL;
2357 +}
2358 +
2359 +static void devcrypto_select_all_digests(int *digest_list)
2360 +{
2361 + size_t i;
2362 +
2363 + for (i = 0; i < OSSL_NELEM(digest_data); i++)
2364 + digest_list[i] = 1;
2365 +}
2366 +
2367 +static int cryptodev_select_digest_cb(const char *str, int len, void *usr)
2368 +{
2369 + int *digest_list = (int *)usr;
2370 + char *name;
2371 + const EVP_MD *EVP;
2372 + size_t i;
2373 +
2374 + if (len == 0)
2375 + return 1;
2376 + if (usr == NULL || (name = OPENSSL_strndup(str, len)) == NULL)
2377 + return 0;
2378 + EVP = EVP_get_digestbyname(name);
2379 + if (EVP == NULL)
2380 + fprintf(stderr, "devcrypto: unknown digest %s\n", name);
2381 + else if ((i = find_digest_data_index(EVP_MD_type(EVP))) != (size_t)-1)
2382 + digest_list[i] = 1;
2383 + else
2384 + fprintf(stderr, "devcrypto: digest %s not available\n", name);
2385 + OPENSSL_free(name);
2386 + return 1;
2387 +}
2388 +
2389 +static void dump_digest_info(void)
2390 +{
2391 + size_t i;
2392 + const char *name;
2393 +
2394 + fprintf (stderr, "Information about digests supported by the /dev/crypto"
2395 + " engine:\n");
2396 +#ifndef CIOCGSESSINFO
2397 + fprintf(stderr, "CIOCGSESSINFO (session info call) unavailable\n");
2398 +#endif
2399 +
2400 + for (i = 0; i < OSSL_NELEM(digest_data); i++) {
2401 + name = OBJ_nid2sn(digest_data[i].nid);
2402 + fprintf (stderr, "Digest %s, NID=%d, /dev/crypto info: id=%d, driver=%s",
2403 + name ? name : "unknown", digest_data[i].nid,
2404 + digest_data[i].devcryptoid,
2405 + digest_driver_info[i].driver_name ? digest_driver_info[i].driver_name : "unknown");
2406 + if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCGSESSION) {
2407 + fprintf (stderr, ". CIOCGSESSION (session open) failed\n");
2408 + continue;
2409 + }
2410 + if (digest_driver_info[i].accelerated == DEVCRYPTO_ACCELERATED)
2411 + fprintf(stderr, " (hw accelerated)");
2412 + else if (digest_driver_info[i].accelerated == DEVCRYPTO_NOT_ACCELERATED)
2413 + fprintf(stderr, " (software)");
2414 + else
2415 + fprintf(stderr, " (acceleration status unknown)");
2416 + if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_FAILURE)
2417 + fprintf (stderr, ". Cipher setup failed\n");
2418 + else if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCCPHASH)
2419 + fprintf(stderr, ", CIOCCPHASH failed\n");
2420 + else
2421 + fprintf(stderr, ", CIOCCPHASH capable\n");
2422 + }
2423 + fprintf(stderr, "\n");
2424 +}
2425 +
2426 +#endif
2427 +
2428 +/******************************************************************************
2429 + *
2430 + * CONTROL COMMANDS
2431 + *
2432 + *****/
2433 +
2434 +#define DEVCRYPTO_CMD_USE_SOFTDRIVERS ENGINE_CMD_BASE
2435 +#define DEVCRYPTO_CMD_CIPHERS (ENGINE_CMD_BASE + 1)
2436 +#define DEVCRYPTO_CMD_DIGESTS (ENGINE_CMD_BASE + 2)
2437 +#define DEVCRYPTO_CMD_DUMP_INFO (ENGINE_CMD_BASE + 3)
2438 +
2439 +/* Helper macros for CPP string composition */
2440 +#ifndef OPENSSL_MSTR
2441 +# define OPENSSL_MSTR_HELPER(x) #x
2442 +# define OPENSSL_MSTR(x) OPENSSL_MSTR_HELPER(x)
2443 +#endif
2444 +
2445 +static const ENGINE_CMD_DEFN devcrypto_cmds[] = {
2446 +#ifdef CIOCGSESSINFO
2447 + {DEVCRYPTO_CMD_USE_SOFTDRIVERS,
2448 + "USE_SOFTDRIVERS",
2449 + "specifies whether to use software (not accelerated) drivers ("
2450 + OPENSSL_MSTR(DEVCRYPTO_REQUIRE_ACCELERATED) "=use only accelerated drivers, "
2451 + OPENSSL_MSTR(DEVCRYPTO_USE_SOFTWARE) "=allow all drivers, "
2452 + OPENSSL_MSTR(DEVCRYPTO_REJECT_SOFTWARE)
2453 + "=use if acceleration can't be determined) [default="
2454 + OPENSSL_MSTR(DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS) "]",
2455 + ENGINE_CMD_FLAG_NUMERIC},
2456 +#endif
2457 +
2458 + {DEVCRYPTO_CMD_CIPHERS,
2459 + "CIPHERS",
2460 + "either ALL, NONE, or a comma-separated list of ciphers to enable [default=ALL]",
2461 + ENGINE_CMD_FLAG_STRING},
2462 +
2463 +#ifdef IMPLEMENT_DIGEST
2464 + {DEVCRYPTO_CMD_DIGESTS,
2465 + "DIGESTS",
2466 + "either ALL, NONE, or a comma-separated list of digests to enable [default=ALL]",
2467 + ENGINE_CMD_FLAG_STRING},
2468 +#endif
2469 +
2470 + {DEVCRYPTO_CMD_DUMP_INFO,
2471 + "DUMP_INFO",
2472 + "dump info about each algorithm to stderr; use 'openssl engine -pre DUMP_INFO devcrypto'",
2473 + ENGINE_CMD_FLAG_NO_INPUT},
2474 +
2475 + {0, NULL, NULL, 0}
2476 +};
2477 +
2478 +static int devcrypto_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
2479 +{
2480 + int *new_list;
2481 + switch (cmd) {
2482 +#ifdef CIOCGSESSINFO
2483 + case DEVCRYPTO_CMD_USE_SOFTDRIVERS:
2484 + switch (i) {
2485 + case DEVCRYPTO_REQUIRE_ACCELERATED:
2486 + case DEVCRYPTO_USE_SOFTWARE:
2487 + case DEVCRYPTO_REJECT_SOFTWARE:
2488 + break;
2489 + default:
2490 + fprintf(stderr, "devcrypto: invalid value (%ld) for USE_SOFTDRIVERS\n", i);
2491 + return 0;
2492 + }
2493 + if (use_softdrivers == i)
2494 + return 1;
2495 + use_softdrivers = i;
2496 +#ifdef IMPLEMENT_DIGEST
2497 + rebuild_known_digest_nids(e);
2498 +#endif
2499 + rebuild_known_cipher_nids(e);
2500 + return 1;
2501 +#endif /* CIOCGSESSINFO */
2502 +
2503 + case DEVCRYPTO_CMD_CIPHERS:
2504 + if (p == NULL)
2505 + return 1;
2506 + if (strcasecmp((const char *)p, "ALL") == 0) {
2507 + devcrypto_select_all_ciphers(selected_ciphers);
2508 + } else if (strcasecmp((const char*)p, "NONE") == 0) {
2509 + memset(selected_ciphers, 0, sizeof(selected_ciphers));
2510 + } else {
2511 + new_list=OPENSSL_zalloc(sizeof(selected_ciphers));
2512 + if (!CONF_parse_list(p, ',', 1, cryptodev_select_cipher_cb, new_list)) {
2513 + OPENSSL_free(new_list);
2514 + return 0;
2515 + }
2516 + memcpy(selected_ciphers, new_list, sizeof(selected_ciphers));
2517 + OPENSSL_free(new_list);
2518 + }
2519 + rebuild_known_cipher_nids(e);
2520 + return 1;
2521 +
2522 +#ifdef IMPLEMENT_DIGEST
2523 + case DEVCRYPTO_CMD_DIGESTS:
2524 + if (p == NULL)
2525 + return 1;
2526 + if (strcasecmp((const char *)p, "ALL") == 0) {
2527 + devcrypto_select_all_digests(selected_digests);
2528 + } else if (strcasecmp((const char*)p, "NONE") == 0) {
2529 + memset(selected_digests, 0, sizeof(selected_digests));
2530 + } else {
2531 + new_list=OPENSSL_zalloc(sizeof(selected_digests));
2532 + if (!CONF_parse_list(p, ',', 1, cryptodev_select_digest_cb, new_list)) {
2533 + OPENSSL_free(new_list);
2534 + return 0;
2535 + }
2536 + memcpy(selected_digests, new_list, sizeof(selected_digests));
2537 + OPENSSL_free(new_list);
2538 + }
2539 + rebuild_known_digest_nids(e);
2540 + return 1;
2541 +#endif /* IMPLEMENT_DIGEST */
2542 +
2543 + case DEVCRYPTO_CMD_DUMP_INFO:
2544 + dump_cipher_info();
2545 +#ifdef IMPLEMENT_DIGEST
2546 + dump_digest_info();
2547 +#endif
2548 + return 1;
2549 +
2550 + default:
2551 + break;
2552 + }
2553 + return 0;
2554 +}
2555 +
2556 +/******************************************************************************
2557 + *
2558 + * LOAD / UNLOAD
2559 + *
2560 + *****/
2561 +
2562 +/*
2563 + * Opens /dev/crypto
2564 + */
2565 +static int open_devcrypto(void)
2566 +{
2567 + int fd;
2568 +
2569 + if (cfd >= 0)
2570 + return 1;
2571 +
2572 + if ((fd = open("/dev/crypto", O_RDWR, 0)) < 0) {
2573 +#ifndef ENGINE_DEVCRYPTO_DEBUG
2574 + if (errno != ENOENT)
2575 +#endif
2576 + fprintf(stderr, "Could not open /dev/crypto: %s\n", strerror(errno));
2577 + return 0;
2578 + }
2579 +
2580 +#ifdef CRIOGET
2581 + if (ioctl(fd, CRIOGET, &cfd) < 0) {
2582 + fprintf(stderr, "Could not create crypto fd: %s\n", strerror(errno));
2583 + close(fd);
2584 + cfd = -1;
2585 + return 0;
2586 + }
2587 + close(fd);
2588 +#else
2589 + cfd = fd;
2590 +#endif
2591 +
2592 + return 1;
2593 +}
2594 +
2595 +static int close_devcrypto(void)
2596 +{
2597 + int ret;
2598 +
2599 + if (cfd < 0)
2600 + return 1;
2601 + ret = close(cfd);
2602 + cfd = -1;
2603 + if (ret != 0) {
2604 + fprintf(stderr, "Error closing /dev/crypto: %s\n", strerror(errno));
2605 + return 0;
2606 + }
2607 + return 1;
2608 +}
2609 +
2610 +static int devcrypto_unload(ENGINE *e)
2611 +{
2612 + destroy_all_cipher_methods();
2613 +#ifdef IMPLEMENT_DIGEST
2614 + destroy_all_digest_methods();
2615 +#endif
2616 +
2617 + close_devcrypto();
2618 +
2619 + return 1;
2620 +}
2621 +
2622 +static int bind_devcrypto(ENGINE *e) {
2623 +
2624 + if (!ENGINE_set_id(e, engine_devcrypto_id)
2625 + || !ENGINE_set_name(e, "/dev/crypto engine")
2626 + || !ENGINE_set_destroy_function(e, devcrypto_unload)
2627 + || !ENGINE_set_cmd_defns(e, devcrypto_cmds)
2628 + || !ENGINE_set_ctrl_function(e, devcrypto_ctrl))
2629 + return 0;
2630 +
2631 + prepare_cipher_methods();
2632 +#ifdef IMPLEMENT_DIGEST
2633 + prepare_digest_methods();
2634 +#endif
2635 +
2636 + return (ENGINE_set_ciphers(e, devcrypto_ciphers)
2637 +#ifdef IMPLEMENT_DIGEST
2638 + && ENGINE_set_digests(e, devcrypto_digests)
2639 +#endif
2640 +/*
2641 + * Asymmetric ciphers aren't well supported with /dev/crypto. Among the BSD
2642 + * implementations, it seems to only exist in FreeBSD, and regarding the
2643 + * parameters in its crypt_kop, the manual crypto(4) has this to say:
2644 + *
2645 + * The semantics of these arguments are currently undocumented.
2646 + *
2647 + * Reading through the FreeBSD source code doesn't give much more than
2648 + * their CRK_MOD_EXP implementation for ubsec.
2649 + *
2650 + * It doesn't look much better with cryptodev-linux. They have the crypt_kop
2651 + * structure as well as the command (CRK_*) in cryptodev.h, but no support
2652 + * seems to be implemented at all for the moment.
2653 + *
2654 + * At the time of writing, it seems impossible to write proper support for
2655 + * FreeBSD's asym features without some very deep knowledge and access to
2656 + * specific kernel modules.
2657 + *
2658 + * /Richard Levitte, 2017-05-11
2659 + */
2660 +#if 0
2661 +# ifndef OPENSSL_NO_RSA
2662 + && ENGINE_set_RSA(e, devcrypto_rsa)
2663 +# endif
2664 +# ifndef OPENSSL_NO_DSA
2665 + && ENGINE_set_DSA(e, devcrypto_dsa)
2666 +# endif
2667 +# ifndef OPENSSL_NO_DH
2668 + && ENGINE_set_DH(e, devcrypto_dh)
2669 +# endif
2670 +# ifndef OPENSSL_NO_EC
2671 + && ENGINE_set_EC(e, devcrypto_ec)
2672 +# endif
2673 +#endif
2674 + );
2675 +}
2676 +
2677 +#ifdef OPENSSL_NO_DYNAMIC_ENGINE
2678 +/*
2679 + * In case this engine is built into libcrypto, then it doesn't offer any
2680 + * ability to be dynamically loadable.
2681 + */
2682 +void engine_load_devcrypto_int(void)
2683 +{
2684 + ENGINE *e = NULL;
2685 +
2686 + if (!open_devcrypto())
2687 + return;
2688 +
2689 + if ((e = ENGINE_new()) == NULL
2690 + || !bind_devcrypto(e)) {
2691 + close_devcrypto();
2692 + ENGINE_free(e);
2693 + return;
2694 + }
2695 +
2696 + ENGINE_add(e);
2697 + ENGINE_free(e); /* Loose our local reference */
2698 + ERR_clear_error();
2699 +}
2700 +
2701 +#else
2702 +
2703 +static int bind_helper(ENGINE *e, const char *id)
2704 +{
2705 + if ((id && (strcmp(id, engine_devcrypto_id) != 0))
2706 + || !open_devcrypto())
2707 + return 0;
2708 + if (!bind_devcrypto(e)) {
2709 + close_devcrypto();
2710 + return 0;
2711 + }
2712 + return 1;
2713 +}
2714 +
2715 +IMPLEMENT_DYNAMIC_CHECK_FN()
2716 +IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
2717 +
2718 +#endif