mirror of
https://github.com/openssl/openssl.git
synced 2024-11-30 21:44:16 +08:00
Support session information on FreeBSD.
FreeBSD's /dev/crypto does not provide a CIOCGSESSINFO ioctl, but it does provide other ioctls that can be used to provide similar functionality. First, FreeBSD's /dev/crypto defines a CIOCGESSION2 ioctl which accepts a 'struct session2_op'. This structure extends 'struct session_op' with a 'crid' member which can be used to either request an individual driver by id, or a class of drivers via flags. To determine if the available drivers for a given algorithm are accelerated or not, use CIOCGESSION2 to first attempt to create an accelerated (hardware) session. If that fails, fall back to attempting a software session. In addition, when requesting a new cipher session, use the current setting of the 'use_softdrivers' flag to determine the value assigned to 'crid' when invoking CIOCGSESSION2. Finally, use the returned 'crid' value from CIOCGSESSION2 to look up the name of the associated driver via the CIOCFINDDEV ioctl. Reviewed-by: Matt Caswell <matt@openssl.org> Reviewed-by: Ben Kaduk <kaduk@mit.edu> (Merged from https://github.com/openssl/openssl/pull/13468)
This commit is contained in:
parent
b39c215dec
commit
7fd1ca723a
@ -34,6 +34,16 @@
|
||||
|
||||
#define engine_devcrypto_id "devcrypto"
|
||||
|
||||
/*
|
||||
* Use session2_op on FreeBSD which permits requesting specific
|
||||
* drivers or classes of drivers at session creation time.
|
||||
*/
|
||||
#ifdef CIOCGSESSION2
|
||||
typedef struct session2_op session_op_t;
|
||||
#else
|
||||
typedef struct session_op session_op_t;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ONE global file descriptor for all sessions. This allows operations
|
||||
* such as digest session data copying (see digest_copy()), but is also
|
||||
@ -73,12 +83,12 @@ struct driver_info_st {
|
||||
void engine_load_devcrypto_int(void);
|
||||
#endif
|
||||
|
||||
static int clean_devcrypto_session(struct session_op *sess) {
|
||||
static int clean_devcrypto_session(session_op_t *sess) {
|
||||
if (ioctl(cfd, CIOCFSESSION, &sess->ses) < 0) {
|
||||
ERR_raise_data(ERR_LIB_SYS, errno, "calling ioctl()");
|
||||
return 0;
|
||||
}
|
||||
memset(sess, 0, sizeof(struct session_op));
|
||||
memset(sess, 0, sizeof(*sess));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -93,7 +103,7 @@ static int clean_devcrypto_session(struct session_op *sess) {
|
||||
*****/
|
||||
|
||||
struct cipher_ctx {
|
||||
struct session_op sess;
|
||||
session_op_t sess;
|
||||
int op; /* COP_ENCRYPT or COP_DECRYPT */
|
||||
unsigned long mode; /* EVP_CIPH_*_MODE */
|
||||
|
||||
@ -198,6 +208,7 @@ static int cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
|
||||
(struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
|
||||
const struct cipher_data_st *cipher_d =
|
||||
get_cipher_data(EVP_CIPHER_CTX_nid(ctx));
|
||||
int ret;
|
||||
|
||||
/* cleanup a previous session */
|
||||
if (cipher_ctx->sess.ses != 0 &&
|
||||
@ -210,7 +221,15 @@ static int cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
|
||||
cipher_ctx->op = enc ? COP_ENCRYPT : COP_DECRYPT;
|
||||
cipher_ctx->mode = cipher_d->flags & EVP_CIPH_MODE;
|
||||
cipher_ctx->blocksize = cipher_d->blocksize;
|
||||
if (ioctl(cfd, CIOCGSESSION, &cipher_ctx->sess) < 0) {
|
||||
#ifdef CIOCGSESSION2
|
||||
cipher_ctx->sess.crid = (use_softdrivers == DEVCRYPTO_USE_SOFTWARE) ?
|
||||
CRYPTO_FLAG_SOFTWARE | CRYPTO_FLAG_HARDWARE :
|
||||
CRYPTO_FLAG_HARDWARE;
|
||||
ret = ioctl(cfd, CIOCGSESSION2, &cipher_ctx->sess);
|
||||
#else
|
||||
ret = ioctl(cfd, CIOCGSESSION, &cipher_ctx->sess);
|
||||
#endif
|
||||
if (ret < 0) {
|
||||
ERR_raise_data(ERR_LIB_SYS, errno, "calling ioctl()");
|
||||
return 0;
|
||||
}
|
||||
@ -406,9 +425,12 @@ static int devcrypto_test_cipher(size_t cipher_data_index)
|
||||
static void prepare_cipher_methods(void)
|
||||
{
|
||||
size_t i;
|
||||
struct session_op sess;
|
||||
session_op_t sess;
|
||||
unsigned long cipher_mode;
|
||||
#ifdef CIOCGSESSINFO
|
||||
#ifdef CIOCGSESSION2
|
||||
struct crypt_find_op fop;
|
||||
enum devcrypto_accelerated_t accelerated;
|
||||
#elif defined(CIOCGSESSINFO)
|
||||
struct session_info_op siop;
|
||||
#endif
|
||||
|
||||
@ -426,10 +448,29 @@ static void prepare_cipher_methods(void)
|
||||
*/
|
||||
sess.cipher = cipher_data[i].devcryptoid;
|
||||
sess.keylen = cipher_data[i].keylen;
|
||||
#ifdef CIOCGSESSION2
|
||||
/*
|
||||
* When using CIOCGSESSION2, first try to allocate a hardware
|
||||
* ("accelerated") session. If that fails, fall back to
|
||||
* allocating a software session.
|
||||
*/
|
||||
sess.crid = CRYPTO_FLAG_HARDWARE;
|
||||
if (ioctl(cfd, CIOCGSESSION2, &sess) == 0) {
|
||||
accelerated = DEVCRYPTO_ACCELERATED;
|
||||
} else {
|
||||
sess.crid = CRYPTO_FLAG_SOFTWARE;
|
||||
if (ioctl(cfd, CIOCGSESSION2, &sess) < 0) {
|
||||
cipher_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION;
|
||||
continue;
|
||||
}
|
||||
accelerated = DEVCRYPTO_NOT_ACCELERATED;
|
||||
}
|
||||
#else
|
||||
if (ioctl(cfd, CIOCGSESSION, &sess) < 0) {
|
||||
cipher_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
cipher_mode = cipher_data[i].flags & EVP_CIPH_MODE;
|
||||
|
||||
@ -460,7 +501,14 @@ static void prepare_cipher_methods(void)
|
||||
known_cipher_methods[i] = NULL;
|
||||
} else {
|
||||
cipher_driver_info[i].status = DEVCRYPTO_STATUS_USABLE;
|
||||
#ifdef CIOCGSESSINFO
|
||||
#ifdef CIOCGSESSION2
|
||||
cipher_driver_info[i].accelerated = accelerated;
|
||||
fop.crid = sess.crid;
|
||||
if (ioctl(cfd, CIOCFINDDEV, &fop) == 0) {
|
||||
cipher_driver_info[i].driver_name =
|
||||
OPENSSL_strndup(fop.name, sizeof(fop.name));
|
||||
}
|
||||
#elif defined(CIOCGSESSINFO)
|
||||
siop.ses = sess.ses;
|
||||
if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) {
|
||||
cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN;
|
||||
@ -624,7 +672,7 @@ static void dump_cipher_info(void)
|
||||
*****/
|
||||
|
||||
struct digest_ctx {
|
||||
struct session_op sess;
|
||||
session_op_t sess;
|
||||
/* This signals that the init function was called, not that it succeeded. */
|
||||
int init_called;
|
||||
unsigned char digest_res[HASH_MAX_LEN];
|
||||
@ -843,7 +891,7 @@ static void rebuild_known_digest_nids(ENGINE *e)
|
||||
static void prepare_digest_methods(void)
|
||||
{
|
||||
size_t i;
|
||||
struct session_op sess1, sess2;
|
||||
session_op_t sess1, sess2;
|
||||
#ifdef CIOCGSESSINFO
|
||||
struct session_info_op siop;
|
||||
#endif
|
||||
@ -1051,7 +1099,7 @@ static void dump_digest_info(void)
|
||||
#define DEVCRYPTO_CMD_DUMP_INFO (ENGINE_CMD_BASE + 3)
|
||||
|
||||
static const ENGINE_CMD_DEFN devcrypto_cmds[] = {
|
||||
#ifdef CIOCGSESSINFO
|
||||
#if defined(CIOCGSESSINFO) || defined(CIOCGSESSION2)
|
||||
{DEVCRYPTO_CMD_USE_SOFTDRIVERS,
|
||||
"USE_SOFTDRIVERS",
|
||||
"specifies whether to use software (not accelerated) drivers ("
|
||||
@ -1087,7 +1135,7 @@ static int devcrypto_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
|
||||
{
|
||||
int *new_list;
|
||||
switch (cmd) {
|
||||
#ifdef CIOCGSESSINFO
|
||||
#if defined(CIOCGSESSINFO) || defined(CIOCGSESSION2)
|
||||
case DEVCRYPTO_CMD_USE_SOFTDRIVERS:
|
||||
switch (i) {
|
||||
case DEVCRYPTO_REQUIRE_ACCELERATED:
|
||||
@ -1106,7 +1154,7 @@ static int devcrypto_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
|
||||
#endif
|
||||
rebuild_known_cipher_nids(e);
|
||||
return 1;
|
||||
#endif /* CIOCGSESSINFO */
|
||||
#endif /* CIOCGSESSINFO || CIOCGSESSION2 */
|
||||
|
||||
case DEVCRYPTO_CMD_CIPHERS:
|
||||
if (p == NULL)
|
||||
|
Loading…
Reference in New Issue
Block a user