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