diff options
-rw-r--r-- | engines/e_devcrypto.c | 72 |
1 files changed, 60 insertions, 12 deletions
diff --git a/engines/e_devcrypto.c b/engines/e_devcrypto.c index 6715ef408e..7f3768d36c 100644 --- a/engines/e_devcrypto.c +++ b/engines/e_devcrypto.c @@ -35,6 +35,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 * saner... why re-open /dev/crypto for every session? @@ -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) |