xref: /freebsd/crypto/openssl/engines/e_devcrypto.c (revision f25b8c9fb4f58cf61adb47d7570abe7caa6d385d)
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