1 /*
2 * Copyright 2017-2023 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10 /* We need to use some deprecated APIs */
11 #define OPENSSL_SUPPRESS_DEPRECATED
12
13 #include "internal/e_os.h"
14 #include <string.h>
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <fcntl.h>
18 #include <sys/ioctl.h>
19 #include <unistd.h>
20 #include <assert.h>
21
22 #include <openssl/conf.h>
23 #include <openssl/evp.h>
24 #include <openssl/err.h>
25 #include <openssl/engine.h>
26 #include <openssl/objects.h>
27 #include "crypto/cryptodev.h"
28 #include "internal/nelem.h"
29
30 /* #define ENGINE_DEVCRYPTO_DEBUG */
31
32 #if CRYPTO_ALGORITHM_MIN < CRYPTO_ALGORITHM_MAX
33 #define CHECK_BSD_STYLE_MACROS
34 #endif
35
36 #define engine_devcrypto_id "devcrypto"
37
38 /*
39 * Use session2_op on FreeBSD which permits requesting specific
40 * drivers or classes of drivers at session creation time.
41 */
42 #ifdef CIOCGSESSION2
43 typedef struct session2_op session_op_t;
44 #else
45 typedef struct session_op session_op_t;
46 #endif
47
48 /*
49 * ONE global file descriptor for all sessions. This allows operations
50 * such as digest session data copying (see digest_copy()), but is also
51 * saner... why re-open /dev/crypto for every session?
52 */
53 static int cfd = -1;
54 #define DEVCRYPTO_REQUIRE_ACCELERATED 0 /* require confirmation of acceleration */
55 #define DEVCRYPTO_USE_SOFTWARE 1 /* allow software drivers */
56 #define DEVCRYPTO_REJECT_SOFTWARE 2 /* only disallow confirmed software drivers */
57
58 #define DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS DEVCRYPTO_REJECT_SOFTWARE
59 static int use_softdrivers = DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS;
60
61 /*
62 * cipher/digest status & acceleration definitions
63 * Make sure the defaults are set to 0
64 */
65 struct driver_info_st {
66 enum devcrypto_status_t {
67 DEVCRYPTO_STATUS_FAILURE = -3, /* unusable for other reason */
68 DEVCRYPTO_STATUS_NO_CIOCCPHASH = -2, /* hash state copy not supported */
69 DEVCRYPTO_STATUS_NO_CIOCGSESSION = -1, /* session open failed */
70 DEVCRYPTO_STATUS_UNKNOWN = 0, /* not tested yet */
71 DEVCRYPTO_STATUS_USABLE = 1 /* algo can be used */
72 } status;
73
74 enum devcrypto_accelerated_t {
75 DEVCRYPTO_NOT_ACCELERATED = -1, /* software implemented */
76 DEVCRYPTO_ACCELERATION_UNKNOWN = 0, /* acceleration support unknown */
77 DEVCRYPTO_ACCELERATED = 1 /* hardware accelerated */
78 } accelerated;
79
80 char *driver_name;
81 };
82
83 #ifdef OPENSSL_NO_DYNAMIC_ENGINE
84 void engine_load_devcrypto_int(void);
85 #endif
86
clean_devcrypto_session(session_op_t * sess)87 static int clean_devcrypto_session(session_op_t *sess)
88 {
89 if (ioctl(cfd, CIOCFSESSION, &sess->ses) < 0) {
90 ERR_raise_data(ERR_LIB_SYS, errno, "calling ioctl()");
91 return 0;
92 }
93 memset(sess, 0, sizeof(*sess));
94 return 1;
95 }
96
97 /******************************************************************************
98 *
99 * Ciphers
100 *
101 * Because they all do the same basic operation, we have only one set of
102 * method functions for them all to share, and a mapping table between
103 * NIDs and cryptodev IDs, with all the necessary size data.
104 *
105 *****/
106
107 struct cipher_ctx {
108 session_op_t sess;
109 int op; /* COP_ENCRYPT or COP_DECRYPT */
110 unsigned long mode; /* EVP_CIPH_*_MODE */
111
112 /* to handle ctr mode being a stream cipher */
113 unsigned char partial[EVP_MAX_BLOCK_LENGTH];
114 unsigned int blocksize, num;
115 };
116
117 static const struct cipher_data_st {
118 int nid;
119 int blocksize;
120 int keylen;
121 int ivlen;
122 int flags;
123 int devcryptoid;
124 } cipher_data[] = {
125 #ifndef OPENSSL_NO_DES
126 { NID_des_cbc, 8, 8, 8, EVP_CIPH_CBC_MODE, CRYPTO_DES_CBC },
127 { NID_des_ede3_cbc, 8, 24, 8, EVP_CIPH_CBC_MODE, CRYPTO_3DES_CBC },
128 #endif
129 #ifndef OPENSSL_NO_BF
130 { NID_bf_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_BLF_CBC },
131 #endif
132 #ifndef OPENSSL_NO_CAST
133 { NID_cast5_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_CAST_CBC },
134 #endif
135 { NID_aes_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
136 { NID_aes_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
137 { NID_aes_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
138 #ifndef OPENSSL_NO_RC4
139 { NID_rc4, 1, 16, 0, EVP_CIPH_STREAM_CIPHER, CRYPTO_ARC4 },
140 #endif
141 #if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_CTR)
142 { NID_aes_128_ctr, 16, 128 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
143 { NID_aes_192_ctr, 16, 192 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
144 { NID_aes_256_ctr, 16, 256 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
145 #endif
146 #if 0 /* Not yet supported */
147 { NID_aes_128_xts, 16, 128 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS },
148 { NID_aes_256_xts, 16, 256 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS },
149 #endif
150 #if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_ECB)
151 { NID_aes_128_ecb, 16, 128 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
152 { NID_aes_192_ecb, 16, 192 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
153 { NID_aes_256_ecb, 16, 256 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
154 #endif
155 #if 0 /* Not yet supported */
156 { NID_aes_128_gcm, 16, 128 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
157 { NID_aes_192_gcm, 16, 192 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
158 { NID_aes_256_gcm, 16, 256 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
159 #endif
160 #ifndef OPENSSL_NO_CAMELLIA
161 { NID_camellia_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE,
162 CRYPTO_CAMELLIA_CBC },
163 { NID_camellia_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE,
164 CRYPTO_CAMELLIA_CBC },
165 { NID_camellia_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE,
166 CRYPTO_CAMELLIA_CBC },
167 #endif
168 };
169
find_cipher_data_index(int nid)170 static size_t find_cipher_data_index(int nid)
171 {
172 size_t i;
173
174 for (i = 0; i < OSSL_NELEM(cipher_data); i++)
175 if (nid == cipher_data[i].nid)
176 return i;
177 return (size_t)-1;
178 }
179
get_cipher_data_index(int nid)180 static size_t get_cipher_data_index(int nid)
181 {
182 size_t i = find_cipher_data_index(nid);
183
184 if (i != (size_t)-1)
185 return i;
186
187 /*
188 * Code further down must make sure that only NIDs in the table above
189 * are used. If any other NID reaches this function, there's a grave
190 * coding error further down.
191 */
192 assert("Code that never should be reached" == NULL);
193 return -1;
194 }
195
get_cipher_data(int nid)196 static const struct cipher_data_st *get_cipher_data(int nid)
197 {
198 return &cipher_data[get_cipher_data_index(nid)];
199 }
200
201 /*
202 * Following are the three necessary functions to map OpenSSL functionality
203 * with cryptodev.
204 */
205
cipher_init(EVP_CIPHER_CTX * ctx,const unsigned char * key,const unsigned char * iv,int enc)206 static int cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
207 const unsigned char *iv, int enc)
208 {
209 struct cipher_ctx *cipher_ctx = (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
210 const struct cipher_data_st *cipher_d = get_cipher_data(EVP_CIPHER_CTX_get_nid(ctx));
211 int ret;
212
213 /* cleanup a previous session */
214 if (cipher_ctx->sess.ses != 0 && clean_devcrypto_session(&cipher_ctx->sess) == 0)
215 return 0;
216
217 cipher_ctx->sess.cipher = cipher_d->devcryptoid;
218 cipher_ctx->sess.keylen = cipher_d->keylen;
219 cipher_ctx->sess.key = (void *)key;
220 cipher_ctx->op = enc ? COP_ENCRYPT : COP_DECRYPT;
221 cipher_ctx->mode = cipher_d->flags & EVP_CIPH_MODE;
222 cipher_ctx->blocksize = cipher_d->blocksize;
223 #ifdef CIOCGSESSION2
224 cipher_ctx->sess.crid = (use_softdrivers == DEVCRYPTO_USE_SOFTWARE) ? CRYPTO_FLAG_SOFTWARE | CRYPTO_FLAG_HARDWARE : CRYPTO_FLAG_HARDWARE;
225 ret = ioctl(cfd, CIOCGSESSION2, &cipher_ctx->sess);
226 #else
227 ret = ioctl(cfd, CIOCGSESSION, &cipher_ctx->sess);
228 #endif
229 if (ret < 0) {
230 ERR_raise_data(ERR_LIB_SYS, errno, "calling ioctl()");
231 return 0;
232 }
233
234 return 1;
235 }
236
cipher_do_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t inl)237 static int cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
238 const unsigned char *in, size_t inl)
239 {
240 struct cipher_ctx *cipher_ctx = (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
241 struct crypt_op cryp;
242 unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
243 #if !defined(COP_FLAG_WRITE_IV)
244 unsigned char saved_iv[EVP_MAX_IV_LENGTH];
245 const unsigned char *ivptr;
246 size_t nblocks, ivlen;
247 #endif
248
249 memset(&cryp, 0, sizeof(cryp));
250 cryp.ses = cipher_ctx->sess.ses;
251 cryp.len = inl;
252 cryp.src = (void *)in;
253 cryp.dst = (void *)out;
254 cryp.iv = (void *)iv;
255 cryp.op = cipher_ctx->op;
256 #if !defined(COP_FLAG_WRITE_IV)
257 cryp.flags = 0;
258
259 ivlen = EVP_CIPHER_CTX_get_iv_length(ctx);
260 if (ivlen > 0)
261 switch (cipher_ctx->mode) {
262 case EVP_CIPH_CBC_MODE:
263 assert(inl >= ivlen);
264 if (!EVP_CIPHER_CTX_is_encrypting(ctx)) {
265 ivptr = in + inl - ivlen;
266 memcpy(saved_iv, ivptr, ivlen);
267 }
268 break;
269
270 case EVP_CIPH_CTR_MODE:
271 break;
272
273 default: /* should not happen */
274 return 0;
275 }
276 #else
277 cryp.flags = COP_FLAG_WRITE_IV;
278 #endif
279
280 if (ioctl(cfd, CIOCCRYPT, &cryp) < 0) {
281 ERR_raise_data(ERR_LIB_SYS, errno, "calling ioctl()");
282 return 0;
283 }
284
285 #if !defined(COP_FLAG_WRITE_IV)
286 if (ivlen > 0)
287 switch (cipher_ctx->mode) {
288 case EVP_CIPH_CBC_MODE:
289 assert(inl >= ivlen);
290 if (EVP_CIPHER_CTX_is_encrypting(ctx))
291 ivptr = out + inl - ivlen;
292 else
293 ivptr = saved_iv;
294
295 memcpy(iv, ivptr, ivlen);
296 break;
297
298 case EVP_CIPH_CTR_MODE:
299 nblocks = (inl + cipher_ctx->blocksize - 1)
300 / cipher_ctx->blocksize;
301 do {
302 ivlen--;
303 nblocks += iv[ivlen];
304 iv[ivlen] = (uint8_t)nblocks;
305 nblocks >>= 8;
306 } while (ivlen);
307 break;
308
309 default: /* should not happen */
310 return 0;
311 }
312 #endif
313
314 return 1;
315 }
316
ctr_do_cipher(EVP_CIPHER_CTX * ctx,unsigned char * out,const unsigned char * in,size_t inl)317 static int ctr_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
318 const unsigned char *in, size_t inl)
319 {
320 struct cipher_ctx *cipher_ctx = (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
321 size_t nblocks, len;
322
323 /* initial partial block */
324 while (cipher_ctx->num && inl) {
325 (*out++) = *(in++) ^ cipher_ctx->partial[cipher_ctx->num];
326 --inl;
327 cipher_ctx->num = (cipher_ctx->num + 1) % cipher_ctx->blocksize;
328 }
329
330 /* full blocks */
331 if (inl > cipher_ctx->blocksize) {
332 nblocks = inl / cipher_ctx->blocksize;
333 len = nblocks * cipher_ctx->blocksize;
334 if (cipher_do_cipher(ctx, out, in, len) < 1)
335 return 0;
336 inl -= len;
337 out += len;
338 in += len;
339 }
340
341 /* final partial block */
342 if (inl) {
343 memset(cipher_ctx->partial, 0, cipher_ctx->blocksize);
344 if (cipher_do_cipher(ctx, cipher_ctx->partial, cipher_ctx->partial,
345 cipher_ctx->blocksize)
346 < 1)
347 return 0;
348 while (inl--) {
349 out[cipher_ctx->num] = in[cipher_ctx->num]
350 ^ cipher_ctx->partial[cipher_ctx->num];
351 cipher_ctx->num++;
352 }
353 }
354
355 return 1;
356 }
357
cipher_ctrl(EVP_CIPHER_CTX * ctx,int type,int p1,void * p2)358 static int cipher_ctrl(EVP_CIPHER_CTX *ctx, int type, int p1, void *p2)
359 {
360 struct cipher_ctx *cipher_ctx = (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
361 EVP_CIPHER_CTX *to_ctx = (EVP_CIPHER_CTX *)p2;
362 struct cipher_ctx *to_cipher_ctx;
363
364 switch (type) {
365
366 case EVP_CTRL_COPY:
367 if (cipher_ctx == NULL)
368 return 1;
369 /* when copying the context, a new session needs to be initialized */
370 to_cipher_ctx = (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(to_ctx);
371 memset(&to_cipher_ctx->sess, 0, sizeof(to_cipher_ctx->sess));
372 return cipher_init(to_ctx, (void *)cipher_ctx->sess.key, EVP_CIPHER_CTX_iv(ctx),
373 (cipher_ctx->op == COP_ENCRYPT));
374
375 case EVP_CTRL_INIT:
376 memset(&cipher_ctx->sess, 0, sizeof(cipher_ctx->sess));
377 return 1;
378
379 default:
380 break;
381 }
382
383 return -1;
384 }
385
cipher_cleanup(EVP_CIPHER_CTX * ctx)386 static int cipher_cleanup(EVP_CIPHER_CTX *ctx)
387 {
388 struct cipher_ctx *cipher_ctx = (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
389
390 return clean_devcrypto_session(&cipher_ctx->sess);
391 }
392
393 /*
394 * Keep tables of known nids, associated methods, selected ciphers, and driver
395 * info.
396 * Note that known_cipher_nids[] isn't necessarily indexed the same way as
397 * cipher_data[] above, which the other tables are.
398 */
399 static int known_cipher_nids[OSSL_NELEM(cipher_data)];
400 static int known_cipher_nids_amount = -1; /* -1 indicates not yet initialised */
401 static EVP_CIPHER *known_cipher_methods[OSSL_NELEM(cipher_data)] = {
402 NULL,
403 };
404 static int selected_ciphers[OSSL_NELEM(cipher_data)];
405 static struct driver_info_st cipher_driver_info[OSSL_NELEM(cipher_data)];
406
devcrypto_test_cipher(size_t cipher_data_index)407 static int devcrypto_test_cipher(size_t cipher_data_index)
408 {
409 return (cipher_driver_info[cipher_data_index].status == DEVCRYPTO_STATUS_USABLE
410 && selected_ciphers[cipher_data_index] == 1
411 && (cipher_driver_info[cipher_data_index].accelerated
412 == DEVCRYPTO_ACCELERATED
413 || use_softdrivers == DEVCRYPTO_USE_SOFTWARE
414 || (cipher_driver_info[cipher_data_index].accelerated
415 != DEVCRYPTO_NOT_ACCELERATED
416 && use_softdrivers == DEVCRYPTO_REJECT_SOFTWARE)));
417 }
418
prepare_cipher_methods(void)419 static void prepare_cipher_methods(void)
420 {
421 size_t i;
422 session_op_t sess;
423 unsigned long cipher_mode;
424 #ifdef CIOCGSESSION2
425 struct crypt_find_op fop;
426 enum devcrypto_accelerated_t accelerated;
427 #elif defined(CIOCGSESSINFO)
428 struct session_info_op siop;
429 #endif
430
431 memset(&cipher_driver_info, 0, sizeof(cipher_driver_info));
432
433 memset(&sess, 0, sizeof(sess));
434 sess.key = (void *)"01234567890123456789012345678901234567890123456789";
435
436 for (i = 0, known_cipher_nids_amount = 0;
437 i < OSSL_NELEM(cipher_data); i++) {
438
439 selected_ciphers[i] = 1;
440 /*
441 * Check that the cipher is usable
442 */
443 sess.cipher = cipher_data[i].devcryptoid;
444 sess.keylen = cipher_data[i].keylen;
445 #ifdef CIOCGSESSION2
446 /*
447 * When using CIOCGSESSION2, first try to allocate a hardware
448 * ("accelerated") session. If that fails, fall back to
449 * allocating a software session.
450 */
451 sess.crid = CRYPTO_FLAG_HARDWARE;
452 if (ioctl(cfd, CIOCGSESSION2, &sess) == 0) {
453 accelerated = DEVCRYPTO_ACCELERATED;
454 } else {
455 sess.crid = CRYPTO_FLAG_SOFTWARE;
456 if (ioctl(cfd, CIOCGSESSION2, &sess) < 0) {
457 cipher_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION;
458 continue;
459 }
460 accelerated = DEVCRYPTO_NOT_ACCELERATED;
461 }
462 #else
463 if (ioctl(cfd, CIOCGSESSION, &sess) < 0) {
464 cipher_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION;
465 continue;
466 }
467 #endif
468
469 cipher_mode = cipher_data[i].flags & EVP_CIPH_MODE;
470
471 if ((known_cipher_methods[i] = EVP_CIPHER_meth_new(cipher_data[i].nid,
472 cipher_mode == EVP_CIPH_CTR_MODE ? 1 : cipher_data[i].blocksize,
473 cipher_data[i].keylen))
474 == NULL
475 || !EVP_CIPHER_meth_set_iv_length(known_cipher_methods[i],
476 cipher_data[i].ivlen)
477 || !EVP_CIPHER_meth_set_flags(known_cipher_methods[i],
478 cipher_data[i].flags
479 | EVP_CIPH_CUSTOM_COPY
480 | EVP_CIPH_CTRL_INIT
481 | EVP_CIPH_FLAG_DEFAULT_ASN1)
482 || !EVP_CIPHER_meth_set_init(known_cipher_methods[i], cipher_init)
483 || !EVP_CIPHER_meth_set_do_cipher(known_cipher_methods[i],
484 cipher_mode == EVP_CIPH_CTR_MODE ? ctr_do_cipher : cipher_do_cipher)
485 || !EVP_CIPHER_meth_set_ctrl(known_cipher_methods[i], cipher_ctrl)
486 || !EVP_CIPHER_meth_set_cleanup(known_cipher_methods[i],
487 cipher_cleanup)
488 || !EVP_CIPHER_meth_set_impl_ctx_size(known_cipher_methods[i],
489 sizeof(struct cipher_ctx))) {
490 cipher_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
491 EVP_CIPHER_meth_free(known_cipher_methods[i]);
492 known_cipher_methods[i] = NULL;
493 } else {
494 cipher_driver_info[i].status = DEVCRYPTO_STATUS_USABLE;
495 #ifdef CIOCGSESSION2
496 cipher_driver_info[i].accelerated = accelerated;
497 fop.crid = sess.crid;
498 if (ioctl(cfd, CIOCFINDDEV, &fop) == 0) {
499 cipher_driver_info[i].driver_name = OPENSSL_strndup(fop.name, sizeof(fop.name));
500 }
501 #elif defined(CIOCGSESSINFO)
502 siop.ses = sess.ses;
503 if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) {
504 cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN;
505 } else {
506 cipher_driver_info[i].driver_name = OPENSSL_strndup(siop.cipher_info.cra_driver_name,
507 CRYPTODEV_MAX_ALG_NAME);
508 if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY))
509 cipher_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED;
510 else
511 cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED;
512 }
513 #endif /* CIOCGSESSINFO */
514 }
515 ioctl(cfd, CIOCFSESSION, &sess.ses);
516 if (devcrypto_test_cipher(i)) {
517 known_cipher_nids[known_cipher_nids_amount++] = cipher_data[i].nid;
518 }
519 }
520 }
521
rebuild_known_cipher_nids(ENGINE * e)522 static void rebuild_known_cipher_nids(ENGINE *e)
523 {
524 size_t i;
525
526 for (i = 0, known_cipher_nids_amount = 0; i < OSSL_NELEM(cipher_data); i++) {
527 if (devcrypto_test_cipher(i))
528 known_cipher_nids[known_cipher_nids_amount++] = cipher_data[i].nid;
529 }
530 ENGINE_unregister_ciphers(e);
531 ENGINE_register_ciphers(e);
532 }
533
get_cipher_method(int nid)534 static const EVP_CIPHER *get_cipher_method(int nid)
535 {
536 size_t i = get_cipher_data_index(nid);
537
538 if (i == (size_t)-1)
539 return NULL;
540 return known_cipher_methods[i];
541 }
542
get_cipher_nids(const int ** nids)543 static int get_cipher_nids(const int **nids)
544 {
545 *nids = known_cipher_nids;
546 return known_cipher_nids_amount;
547 }
548
destroy_cipher_method(int nid)549 static void destroy_cipher_method(int nid)
550 {
551 size_t i = get_cipher_data_index(nid);
552
553 EVP_CIPHER_meth_free(known_cipher_methods[i]);
554 known_cipher_methods[i] = NULL;
555 }
556
destroy_all_cipher_methods(void)557 static void destroy_all_cipher_methods(void)
558 {
559 size_t i;
560
561 for (i = 0; i < OSSL_NELEM(cipher_data); i++) {
562 destroy_cipher_method(cipher_data[i].nid);
563 OPENSSL_free(cipher_driver_info[i].driver_name);
564 cipher_driver_info[i].driver_name = NULL;
565 }
566 }
567
devcrypto_ciphers(ENGINE * e,const EVP_CIPHER ** cipher,const int ** nids,int nid)568 static int devcrypto_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
569 const int **nids, int nid)
570 {
571 if (cipher == NULL)
572 return get_cipher_nids(nids);
573
574 *cipher = get_cipher_method(nid);
575
576 return *cipher != NULL;
577 }
578
devcrypto_select_all_ciphers(int * cipher_list)579 static void devcrypto_select_all_ciphers(int *cipher_list)
580 {
581 size_t i;
582
583 for (i = 0; i < OSSL_NELEM(cipher_data); i++)
584 cipher_list[i] = 1;
585 }
586
cryptodev_select_cipher_cb(const char * str,int len,void * usr)587 static int cryptodev_select_cipher_cb(const char *str, int len, void *usr)
588 {
589 int *cipher_list = (int *)usr;
590 char *name;
591 const EVP_CIPHER *EVP;
592 size_t i;
593
594 if (len == 0)
595 return 1;
596 if (usr == NULL || (name = OPENSSL_strndup(str, len)) == NULL)
597 return 0;
598 EVP = EVP_get_cipherbyname(name);
599 if (EVP == NULL)
600 fprintf(stderr, "devcrypto: unknown cipher %s\n", name);
601 else if ((i = find_cipher_data_index(EVP_CIPHER_get_nid(EVP))) != (size_t)-1)
602 cipher_list[i] = 1;
603 else
604 fprintf(stderr, "devcrypto: cipher %s not available\n", name);
605 OPENSSL_free(name);
606 return 1;
607 }
608
dump_cipher_info(void)609 static void dump_cipher_info(void)
610 {
611 size_t i;
612 const char *name;
613
614 fprintf(stderr, "Information about ciphers supported by the /dev/crypto"
615 " engine:\n");
616 #ifndef CIOCGSESSINFO
617 fprintf(stderr, "CIOCGSESSINFO (session info call) unavailable\n");
618 #endif
619 for (i = 0; i < OSSL_NELEM(cipher_data); i++) {
620 name = OBJ_nid2sn(cipher_data[i].nid);
621 fprintf(stderr, "Cipher %s, NID=%d, /dev/crypto info: id=%d, ",
622 name ? name : "unknown", cipher_data[i].nid,
623 cipher_data[i].devcryptoid);
624 if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCGSESSION) {
625 fprintf(stderr, "CIOCGSESSION (session open call) failed\n");
626 continue;
627 }
628 fprintf(stderr, "driver=%s ", cipher_driver_info[i].driver_name ? cipher_driver_info[i].driver_name : "unknown");
629 if (cipher_driver_info[i].accelerated == DEVCRYPTO_ACCELERATED)
630 fprintf(stderr, "(hw accelerated)");
631 else if (cipher_driver_info[i].accelerated == DEVCRYPTO_NOT_ACCELERATED)
632 fprintf(stderr, "(software)");
633 else
634 fprintf(stderr, "(acceleration status unknown)");
635 if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_FAILURE)
636 fprintf(stderr, ". Cipher setup failed");
637 fprintf(stderr, "\n");
638 }
639 fprintf(stderr, "\n");
640 }
641
642 /*
643 * We only support digests if the cryptodev implementation supports multiple
644 * data updates and session copying. Otherwise, we would be forced to maintain
645 * a cache, which is perilous if there's a lot of data coming in (if someone
646 * wants to checksum an OpenSSL tarball, for example).
647 */
648 #if defined(CIOCCPHASH) && defined(COP_FLAG_UPDATE) && defined(COP_FLAG_FINAL)
649 #define IMPLEMENT_DIGEST
650
651 /******************************************************************************
652 *
653 * Digests
654 *
655 * Because they all do the same basic operation, we have only one set of
656 * method functions for them all to share, and a mapping table between
657 * NIDs and cryptodev IDs, with all the necessary size data.
658 *
659 *****/
660
661 struct digest_ctx {
662 session_op_t sess;
663 /* This signals that the init function was called, not that it succeeded. */
664 int init_called;
665 unsigned char digest_res[HASH_MAX_LEN];
666 };
667
668 static const struct digest_data_st {
669 int nid;
670 int blocksize;
671 int digestlen;
672 int devcryptoid;
673 } digest_data[] = {
674 #ifndef OPENSSL_NO_MD5
675 { NID_md5, /* MD5_CBLOCK */ 64, 16, CRYPTO_MD5 },
676 #endif
677 { NID_sha1, SHA_CBLOCK, 20, CRYPTO_SHA1 },
678 #ifndef OPENSSL_NO_RMD160
679 #if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_RIPEMD160)
680 { NID_ripemd160, /* RIPEMD160_CBLOCK */ 64, 20, CRYPTO_RIPEMD160 },
681 #endif
682 #endif
683 #if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_224)
684 { NID_sha224, SHA256_CBLOCK, 224 / 8, CRYPTO_SHA2_224 },
685 #endif
686 #if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_256)
687 { NID_sha256, SHA256_CBLOCK, 256 / 8, CRYPTO_SHA2_256 },
688 #endif
689 #if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_384)
690 { NID_sha384, SHA512_CBLOCK, 384 / 8, CRYPTO_SHA2_384 },
691 #endif
692 #if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_512)
693 { NID_sha512, SHA512_CBLOCK, 512 / 8, CRYPTO_SHA2_512 },
694 #endif
695 };
696
find_digest_data_index(int nid)697 static size_t find_digest_data_index(int nid)
698 {
699 size_t i;
700
701 for (i = 0; i < OSSL_NELEM(digest_data); i++)
702 if (nid == digest_data[i].nid)
703 return i;
704 return (size_t)-1;
705 }
706
get_digest_data_index(int nid)707 static size_t get_digest_data_index(int nid)
708 {
709 size_t i = find_digest_data_index(nid);
710
711 if (i != (size_t)-1)
712 return i;
713
714 /*
715 * Code further down must make sure that only NIDs in the table above
716 * are used. If any other NID reaches this function, there's a grave
717 * coding error further down.
718 */
719 assert("Code that never should be reached" == NULL);
720 return -1;
721 }
722
get_digest_data(int nid)723 static const struct digest_data_st *get_digest_data(int nid)
724 {
725 return &digest_data[get_digest_data_index(nid)];
726 }
727
728 /*
729 * Following are the five necessary functions to map OpenSSL functionality
730 * with cryptodev: init, update, final, cleanup, and copy.
731 */
732
digest_init(EVP_MD_CTX * ctx)733 static int digest_init(EVP_MD_CTX *ctx)
734 {
735 struct digest_ctx *digest_ctx = (struct digest_ctx *)EVP_MD_CTX_get0_md_data(ctx);
736 const struct digest_data_st *digest_d = get_digest_data(EVP_MD_CTX_get_type(ctx));
737
738 digest_ctx->init_called = 1;
739
740 memset(&digest_ctx->sess, 0, sizeof(digest_ctx->sess));
741 digest_ctx->sess.mac = digest_d->devcryptoid;
742 if (ioctl(cfd, CIOCGSESSION, &digest_ctx->sess) < 0) {
743 ERR_raise_data(ERR_LIB_SYS, errno, "calling ioctl()");
744 return 0;
745 }
746 return 1;
747 }
748
digest_op(struct digest_ctx * ctx,const void * src,size_t srclen,void * res,unsigned int flags)749 static int digest_op(struct digest_ctx *ctx, const void *src, size_t srclen,
750 void *res, unsigned int flags)
751 {
752 struct crypt_op cryp;
753
754 memset(&cryp, 0, sizeof(cryp));
755 cryp.ses = ctx->sess.ses;
756 cryp.len = srclen;
757 cryp.src = (void *)src;
758 cryp.dst = NULL;
759 cryp.mac = res;
760 cryp.flags = flags;
761 return ioctl(cfd, CIOCCRYPT, &cryp);
762 }
763
digest_update(EVP_MD_CTX * ctx,const void * data,size_t count)764 static int digest_update(EVP_MD_CTX *ctx, const void *data, size_t count)
765 {
766 struct digest_ctx *digest_ctx = (struct digest_ctx *)EVP_MD_CTX_get0_md_data(ctx);
767
768 if (count == 0)
769 return 1;
770
771 if (digest_ctx == NULL)
772 return 0;
773
774 if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) {
775 if (digest_op(digest_ctx, data, count, digest_ctx->digest_res, 0) >= 0)
776 return 1;
777 } else if (digest_op(digest_ctx, data, count, NULL, COP_FLAG_UPDATE) >= 0) {
778 return 1;
779 }
780
781 ERR_raise_data(ERR_LIB_SYS, errno, "calling ioctl()");
782 return 0;
783 }
784
digest_final(EVP_MD_CTX * ctx,unsigned char * md)785 static int digest_final(EVP_MD_CTX *ctx, unsigned char *md)
786 {
787 struct digest_ctx *digest_ctx = (struct digest_ctx *)EVP_MD_CTX_get0_md_data(ctx);
788
789 if (md == NULL || digest_ctx == NULL)
790 return 0;
791
792 if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) {
793 memcpy(md, digest_ctx->digest_res, EVP_MD_CTX_get_size(ctx));
794 } else if (digest_op(digest_ctx, NULL, 0, md, COP_FLAG_FINAL) < 0) {
795 ERR_raise_data(ERR_LIB_SYS, errno, "calling ioctl()");
796 return 0;
797 }
798
799 return 1;
800 }
801
digest_copy(EVP_MD_CTX * to,const EVP_MD_CTX * from)802 static int digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
803 {
804 struct digest_ctx *digest_from = (struct digest_ctx *)EVP_MD_CTX_get0_md_data(from);
805 struct digest_ctx *digest_to = (struct digest_ctx *)EVP_MD_CTX_get0_md_data(to);
806 struct cphash_op cphash;
807
808 if (digest_from == NULL || digest_from->init_called != 1)
809 return 1;
810
811 if (!digest_init(to)) {
812 ERR_raise_data(ERR_LIB_SYS, errno, "calling ioctl()");
813 return 0;
814 }
815
816 cphash.src_ses = digest_from->sess.ses;
817 cphash.dst_ses = digest_to->sess.ses;
818 if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) {
819 ERR_raise_data(ERR_LIB_SYS, errno, "calling ioctl()");
820 return 0;
821 }
822 return 1;
823 }
824
digest_cleanup(EVP_MD_CTX * ctx)825 static int digest_cleanup(EVP_MD_CTX *ctx)
826 {
827 struct digest_ctx *digest_ctx = (struct digest_ctx *)EVP_MD_CTX_get0_md_data(ctx);
828
829 if (digest_ctx == NULL)
830 return 1;
831
832 return clean_devcrypto_session(&digest_ctx->sess);
833 }
834
835 /*
836 * Keep tables of known nids, associated methods, selected digests, and
837 * driver info.
838 * Note that known_digest_nids[] isn't necessarily indexed the same way as
839 * digest_data[] above, which the other tables are.
840 */
841 static int known_digest_nids[OSSL_NELEM(digest_data)];
842 static int known_digest_nids_amount = -1; /* -1 indicates not yet initialised */
843 static EVP_MD *known_digest_methods[OSSL_NELEM(digest_data)] = {
844 NULL,
845 };
846 static int selected_digests[OSSL_NELEM(digest_data)];
847 static struct driver_info_st digest_driver_info[OSSL_NELEM(digest_data)];
848
devcrypto_test_digest(size_t digest_data_index)849 static int devcrypto_test_digest(size_t digest_data_index)
850 {
851 return (digest_driver_info[digest_data_index].status == DEVCRYPTO_STATUS_USABLE
852 && selected_digests[digest_data_index] == 1
853 && (digest_driver_info[digest_data_index].accelerated
854 == DEVCRYPTO_ACCELERATED
855 || use_softdrivers == DEVCRYPTO_USE_SOFTWARE
856 || (digest_driver_info[digest_data_index].accelerated
857 != DEVCRYPTO_NOT_ACCELERATED
858 && use_softdrivers == DEVCRYPTO_REJECT_SOFTWARE)));
859 }
860
rebuild_known_digest_nids(ENGINE * e)861 static void rebuild_known_digest_nids(ENGINE *e)
862 {
863 size_t i;
864
865 for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data); i++) {
866 if (devcrypto_test_digest(i))
867 known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid;
868 }
869 ENGINE_unregister_digests(e);
870 ENGINE_register_digests(e);
871 }
872
prepare_digest_methods(void)873 static void prepare_digest_methods(void)
874 {
875 size_t i;
876 session_op_t sess1, sess2;
877 #ifdef CIOCGSESSINFO
878 struct session_info_op siop;
879 #endif
880 struct cphash_op cphash;
881
882 memset(&digest_driver_info, 0, sizeof(digest_driver_info));
883
884 memset(&sess1, 0, sizeof(sess1));
885 memset(&sess2, 0, sizeof(sess2));
886
887 for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data);
888 i++) {
889
890 selected_digests[i] = 1;
891
892 /*
893 * Check that the digest is usable
894 */
895 sess1.mac = digest_data[i].devcryptoid;
896 sess2.ses = 0;
897 if (ioctl(cfd, CIOCGSESSION, &sess1) < 0) {
898 digest_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION;
899 goto finish;
900 }
901
902 #ifdef CIOCGSESSINFO
903 /* gather hardware acceleration info from the driver */
904 siop.ses = sess1.ses;
905 if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) {
906 digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN;
907 } else {
908 digest_driver_info[i].driver_name = OPENSSL_strndup(siop.hash_info.cra_driver_name,
909 CRYPTODEV_MAX_ALG_NAME);
910 if (siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)
911 digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED;
912 else
913 digest_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED;
914 }
915 #endif
916
917 /* digest must be capable of hash state copy */
918 sess2.mac = sess1.mac;
919 if (ioctl(cfd, CIOCGSESSION, &sess2) < 0) {
920 digest_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
921 goto finish;
922 }
923 cphash.src_ses = sess1.ses;
924 cphash.dst_ses = sess2.ses;
925 if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) {
926 digest_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCCPHASH;
927 goto finish;
928 }
929 if ((known_digest_methods[i] = EVP_MD_meth_new(digest_data[i].nid,
930 NID_undef))
931 == NULL
932 || !EVP_MD_meth_set_input_blocksize(known_digest_methods[i],
933 digest_data[i].blocksize)
934 || !EVP_MD_meth_set_result_size(known_digest_methods[i],
935 digest_data[i].digestlen)
936 || !EVP_MD_meth_set_init(known_digest_methods[i], digest_init)
937 || !EVP_MD_meth_set_update(known_digest_methods[i], digest_update)
938 || !EVP_MD_meth_set_final(known_digest_methods[i], digest_final)
939 || !EVP_MD_meth_set_copy(known_digest_methods[i], digest_copy)
940 || !EVP_MD_meth_set_cleanup(known_digest_methods[i], digest_cleanup)
941 || !EVP_MD_meth_set_app_datasize(known_digest_methods[i],
942 sizeof(struct digest_ctx))) {
943 digest_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
944 EVP_MD_meth_free(known_digest_methods[i]);
945 known_digest_methods[i] = NULL;
946 goto finish;
947 }
948 digest_driver_info[i].status = DEVCRYPTO_STATUS_USABLE;
949 finish:
950 ioctl(cfd, CIOCFSESSION, &sess1.ses);
951 if (sess2.ses != 0)
952 ioctl(cfd, CIOCFSESSION, &sess2.ses);
953 if (devcrypto_test_digest(i))
954 known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid;
955 }
956 }
957
get_digest_method(int nid)958 static const EVP_MD *get_digest_method(int nid)
959 {
960 size_t i = get_digest_data_index(nid);
961
962 if (i == (size_t)-1)
963 return NULL;
964 return known_digest_methods[i];
965 }
966
get_digest_nids(const int ** nids)967 static int get_digest_nids(const int **nids)
968 {
969 *nids = known_digest_nids;
970 return known_digest_nids_amount;
971 }
972
destroy_digest_method(int nid)973 static void destroy_digest_method(int nid)
974 {
975 size_t i = get_digest_data_index(nid);
976
977 EVP_MD_meth_free(known_digest_methods[i]);
978 known_digest_methods[i] = NULL;
979 }
980
destroy_all_digest_methods(void)981 static void destroy_all_digest_methods(void)
982 {
983 size_t i;
984
985 for (i = 0; i < OSSL_NELEM(digest_data); i++) {
986 destroy_digest_method(digest_data[i].nid);
987 OPENSSL_free(digest_driver_info[i].driver_name);
988 digest_driver_info[i].driver_name = NULL;
989 }
990 }
991
devcrypto_digests(ENGINE * e,const EVP_MD ** digest,const int ** nids,int nid)992 static int devcrypto_digests(ENGINE *e, const EVP_MD **digest,
993 const int **nids, int nid)
994 {
995 if (digest == NULL)
996 return get_digest_nids(nids);
997
998 *digest = get_digest_method(nid);
999
1000 return *digest != NULL;
1001 }
1002
devcrypto_select_all_digests(int * digest_list)1003 static void devcrypto_select_all_digests(int *digest_list)
1004 {
1005 size_t i;
1006
1007 for (i = 0; i < OSSL_NELEM(digest_data); i++)
1008 digest_list[i] = 1;
1009 }
1010
cryptodev_select_digest_cb(const char * str,int len,void * usr)1011 static int cryptodev_select_digest_cb(const char *str, int len, void *usr)
1012 {
1013 int *digest_list = (int *)usr;
1014 char *name;
1015 const EVP_MD *EVP;
1016 size_t i;
1017
1018 if (len == 0)
1019 return 1;
1020 if (usr == NULL || (name = OPENSSL_strndup(str, len)) == NULL)
1021 return 0;
1022 EVP = EVP_get_digestbyname(name);
1023 if (EVP == NULL)
1024 fprintf(stderr, "devcrypto: unknown digest %s\n", name);
1025 else if ((i = find_digest_data_index(EVP_MD_get_type(EVP))) != (size_t)-1)
1026 digest_list[i] = 1;
1027 else
1028 fprintf(stderr, "devcrypto: digest %s not available\n", name);
1029 OPENSSL_free(name);
1030 return 1;
1031 }
1032
dump_digest_info(void)1033 static void dump_digest_info(void)
1034 {
1035 size_t i;
1036 const char *name;
1037
1038 fprintf(stderr, "Information about digests supported by the /dev/crypto"
1039 " engine:\n");
1040 #ifndef CIOCGSESSINFO
1041 fprintf(stderr, "CIOCGSESSINFO (session info call) unavailable\n");
1042 #endif
1043
1044 for (i = 0; i < OSSL_NELEM(digest_data); i++) {
1045 name = OBJ_nid2sn(digest_data[i].nid);
1046 fprintf(stderr, "Digest %s, NID=%d, /dev/crypto info: id=%d, driver=%s",
1047 name ? name : "unknown", digest_data[i].nid,
1048 digest_data[i].devcryptoid,
1049 digest_driver_info[i].driver_name ? digest_driver_info[i].driver_name : "unknown");
1050 if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCGSESSION) {
1051 fprintf(stderr, ". CIOCGSESSION (session open) failed\n");
1052 continue;
1053 }
1054 if (digest_driver_info[i].accelerated == DEVCRYPTO_ACCELERATED)
1055 fprintf(stderr, " (hw accelerated)");
1056 else if (digest_driver_info[i].accelerated == DEVCRYPTO_NOT_ACCELERATED)
1057 fprintf(stderr, " (software)");
1058 else
1059 fprintf(stderr, " (acceleration status unknown)");
1060 if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_FAILURE)
1061 fprintf(stderr, ". Cipher setup failed\n");
1062 else if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCCPHASH)
1063 fprintf(stderr, ", CIOCCPHASH failed\n");
1064 else
1065 fprintf(stderr, ", CIOCCPHASH capable\n");
1066 }
1067 fprintf(stderr, "\n");
1068 }
1069
1070 #endif
1071
1072 /******************************************************************************
1073 *
1074 * CONTROL COMMANDS
1075 *
1076 *****/
1077
1078 #define DEVCRYPTO_CMD_USE_SOFTDRIVERS ENGINE_CMD_BASE
1079 #define DEVCRYPTO_CMD_CIPHERS (ENGINE_CMD_BASE + 1)
1080 #define DEVCRYPTO_CMD_DIGESTS (ENGINE_CMD_BASE + 2)
1081 #define DEVCRYPTO_CMD_DUMP_INFO (ENGINE_CMD_BASE + 3)
1082
1083 static const ENGINE_CMD_DEFN devcrypto_cmds[] = {
1084 #if defined(CIOCGSESSINFO) || defined(CIOCGSESSION2)
1085 { DEVCRYPTO_CMD_USE_SOFTDRIVERS,
1086 "USE_SOFTDRIVERS",
1087 "specifies whether to use software (not accelerated) drivers (" OPENSSL_MSTR(DEVCRYPTO_REQUIRE_ACCELERATED) "=use only accelerated drivers, " OPENSSL_MSTR(DEVCRYPTO_USE_SOFTWARE) "=allow all drivers, " OPENSSL_MSTR(DEVCRYPTO_REJECT_SOFTWARE) "=use if acceleration can't be determined) [default=" OPENSSL_MSTR(DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS) "]",
1088 ENGINE_CMD_FLAG_NUMERIC },
1089 #endif
1090
1091 { DEVCRYPTO_CMD_CIPHERS,
1092 "CIPHERS",
1093 "either ALL, NONE, or a comma-separated list of ciphers to enable [default=ALL]",
1094 ENGINE_CMD_FLAG_STRING },
1095
1096 #ifdef IMPLEMENT_DIGEST
1097 { DEVCRYPTO_CMD_DIGESTS,
1098 "DIGESTS",
1099 "either ALL, NONE, or a comma-separated list of digests to enable [default=ALL]",
1100 ENGINE_CMD_FLAG_STRING },
1101 #endif
1102
1103 { DEVCRYPTO_CMD_DUMP_INFO,
1104 "DUMP_INFO",
1105 "dump info about each algorithm to stderr; use 'openssl engine -pre DUMP_INFO devcrypto'",
1106 ENGINE_CMD_FLAG_NO_INPUT },
1107
1108 { 0, NULL, NULL, 0 }
1109 };
1110
devcrypto_ctrl(ENGINE * e,int cmd,long i,void * p,void (* f)(void))1111 static int devcrypto_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
1112 {
1113 int *new_list;
1114 switch (cmd) {
1115 #if defined(CIOCGSESSINFO) || defined(CIOCGSESSION2)
1116 case DEVCRYPTO_CMD_USE_SOFTDRIVERS:
1117 switch (i) {
1118 case DEVCRYPTO_REQUIRE_ACCELERATED:
1119 case DEVCRYPTO_USE_SOFTWARE:
1120 case DEVCRYPTO_REJECT_SOFTWARE:
1121 break;
1122 default:
1123 fprintf(stderr, "devcrypto: invalid value (%ld) for USE_SOFTDRIVERS\n", i);
1124 return 0;
1125 }
1126 if (use_softdrivers == i)
1127 return 1;
1128 use_softdrivers = i;
1129 #ifdef IMPLEMENT_DIGEST
1130 rebuild_known_digest_nids(e);
1131 #endif
1132 rebuild_known_cipher_nids(e);
1133 return 1;
1134 #endif /* CIOCGSESSINFO || CIOCGSESSION2 */
1135
1136 case DEVCRYPTO_CMD_CIPHERS:
1137 if (p == NULL)
1138 return 1;
1139 if (OPENSSL_strcasecmp((const char *)p, "ALL") == 0) {
1140 devcrypto_select_all_ciphers(selected_ciphers);
1141 } else if (OPENSSL_strcasecmp((const char *)p, "NONE") == 0) {
1142 memset(selected_ciphers, 0, sizeof(selected_ciphers));
1143 } else {
1144 new_list = OPENSSL_zalloc(sizeof(selected_ciphers));
1145 if (!CONF_parse_list(p, ',', 1, cryptodev_select_cipher_cb, new_list)) {
1146 OPENSSL_free(new_list);
1147 return 0;
1148 }
1149 memcpy(selected_ciphers, new_list, sizeof(selected_ciphers));
1150 OPENSSL_free(new_list);
1151 }
1152 rebuild_known_cipher_nids(e);
1153 return 1;
1154
1155 #ifdef IMPLEMENT_DIGEST
1156 case DEVCRYPTO_CMD_DIGESTS:
1157 if (p == NULL)
1158 return 1;
1159 if (OPENSSL_strcasecmp((const char *)p, "ALL") == 0) {
1160 devcrypto_select_all_digests(selected_digests);
1161 } else if (OPENSSL_strcasecmp((const char *)p, "NONE") == 0) {
1162 memset(selected_digests, 0, sizeof(selected_digests));
1163 } else {
1164 new_list = OPENSSL_zalloc(sizeof(selected_digests));
1165 if (!CONF_parse_list(p, ',', 1, cryptodev_select_digest_cb, new_list)) {
1166 OPENSSL_free(new_list);
1167 return 0;
1168 }
1169 memcpy(selected_digests, new_list, sizeof(selected_digests));
1170 OPENSSL_free(new_list);
1171 }
1172 rebuild_known_digest_nids(e);
1173 return 1;
1174 #endif /* IMPLEMENT_DIGEST */
1175
1176 case DEVCRYPTO_CMD_DUMP_INFO:
1177 dump_cipher_info();
1178 #ifdef IMPLEMENT_DIGEST
1179 dump_digest_info();
1180 #endif
1181 return 1;
1182
1183 default:
1184 break;
1185 }
1186 return 0;
1187 }
1188
1189 /******************************************************************************
1190 *
1191 * LOAD / UNLOAD
1192 *
1193 *****/
1194
1195 /*
1196 * Opens /dev/crypto
1197 */
open_devcrypto(void)1198 static int open_devcrypto(void)
1199 {
1200 int fd;
1201
1202 if (cfd >= 0)
1203 return 1;
1204
1205 if ((fd = open("/dev/crypto", O_RDWR, 0)) < 0) {
1206 #ifndef ENGINE_DEVCRYPTO_DEBUG
1207 if (errno != ENOENT && errno != ENXIO)
1208 #endif
1209 fprintf(stderr, "Could not open /dev/crypto: %s\n", strerror(errno));
1210 return 0;
1211 }
1212
1213 #ifdef CRIOGET
1214 if (ioctl(fd, CRIOGET, &cfd) < 0) {
1215 fprintf(stderr, "Could not create crypto fd: %s\n", strerror(errno));
1216 close(fd);
1217 cfd = -1;
1218 return 0;
1219 }
1220 close(fd);
1221 #else
1222 cfd = fd;
1223 #endif
1224
1225 return 1;
1226 }
1227
close_devcrypto(void)1228 static int close_devcrypto(void)
1229 {
1230 int ret;
1231
1232 if (cfd < 0)
1233 return 1;
1234 ret = close(cfd);
1235 cfd = -1;
1236 if (ret != 0) {
1237 fprintf(stderr, "Error closing /dev/crypto: %s\n", strerror(errno));
1238 return 0;
1239 }
1240 return 1;
1241 }
1242
devcrypto_unload(ENGINE * e)1243 static int devcrypto_unload(ENGINE *e)
1244 {
1245 destroy_all_cipher_methods();
1246 #ifdef IMPLEMENT_DIGEST
1247 destroy_all_digest_methods();
1248 #endif
1249
1250 close_devcrypto();
1251
1252 return 1;
1253 }
1254
bind_devcrypto(ENGINE * e)1255 static int bind_devcrypto(ENGINE *e)
1256 {
1257
1258 if (!ENGINE_set_id(e, engine_devcrypto_id)
1259 || !ENGINE_set_name(e, "/dev/crypto engine")
1260 || !ENGINE_set_destroy_function(e, devcrypto_unload)
1261 || !ENGINE_set_cmd_defns(e, devcrypto_cmds)
1262 || !ENGINE_set_ctrl_function(e, devcrypto_ctrl))
1263 return 0;
1264
1265 prepare_cipher_methods();
1266 #ifdef IMPLEMENT_DIGEST
1267 prepare_digest_methods();
1268 #endif
1269
1270 return (ENGINE_set_ciphers(e, devcrypto_ciphers)
1271 #ifdef IMPLEMENT_DIGEST
1272 && ENGINE_set_digests(e, devcrypto_digests)
1273 #endif
1274 /*
1275 * Asymmetric ciphers aren't well supported with /dev/crypto. Among the BSD
1276 * implementations, it seems to only exist in FreeBSD, and regarding the
1277 * parameters in its crypt_kop, the manual crypto(4) has this to say:
1278 *
1279 * The semantics of these arguments are currently undocumented.
1280 *
1281 * Reading through the FreeBSD source code doesn't give much more than
1282 * their CRK_MOD_EXP implementation for ubsec.
1283 *
1284 * It doesn't look much better with cryptodev-linux. They have the crypt_kop
1285 * structure as well as the command (CRK_*) in cryptodev.h, but no support
1286 * seems to be implemented at all for the moment.
1287 *
1288 * At the time of writing, it seems impossible to write proper support for
1289 * FreeBSD's asym features without some very deep knowledge and access to
1290 * specific kernel modules.
1291 *
1292 * /Richard Levitte, 2017-05-11
1293 */
1294 #if 0
1295 && ENGINE_set_RSA(e, devcrypto_rsa)
1296 #ifndef OPENSSL_NO_DSA
1297 && ENGINE_set_DSA(e, devcrypto_dsa)
1298 #endif
1299 #ifndef OPENSSL_NO_DH
1300 && ENGINE_set_DH(e, devcrypto_dh)
1301 #endif
1302 #ifndef OPENSSL_NO_EC
1303 && ENGINE_set_EC(e, devcrypto_ec)
1304 #endif
1305 #endif
1306 );
1307 }
1308
1309 #ifdef OPENSSL_NO_DYNAMIC_ENGINE
1310 /*
1311 * In case this engine is built into libcrypto, then it doesn't offer any
1312 * ability to be dynamically loadable.
1313 */
engine_load_devcrypto_int(void)1314 void engine_load_devcrypto_int(void)
1315 {
1316 ENGINE *e = NULL;
1317
1318 if (!open_devcrypto())
1319 return;
1320
1321 if ((e = ENGINE_new()) == NULL
1322 || !bind_devcrypto(e)) {
1323 close_devcrypto();
1324 ENGINE_free(e);
1325 return;
1326 }
1327
1328 ERR_set_mark();
1329 ENGINE_add(e);
1330 /*
1331 * If the "add" worked, it gets a structural reference. So either way, we
1332 * release our just-created reference.
1333 */
1334 ENGINE_free(e); /* Loose our local reference */
1335 /*
1336 * If the "add" didn't work, it was probably a conflict because it was
1337 * already added (eg. someone calling ENGINE_load_blah then calling
1338 * ENGINE_load_builtin_engines() perhaps).
1339 */
1340 ERR_pop_to_mark();
1341 }
1342
1343 #else
1344
bind_helper(ENGINE * e,const char * id)1345 static int bind_helper(ENGINE *e, const char *id)
1346 {
1347 if ((id && (strcmp(id, engine_devcrypto_id) != 0))
1348 || !open_devcrypto())
1349 return 0;
1350 if (!bind_devcrypto(e)) {
1351 close_devcrypto();
1352 return 0;
1353 }
1354 return 1;
1355 }
1356
1357 IMPLEMENT_DYNAMIC_CHECK_FN()
1358 IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
1359
1360 #endif
1361