summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--engines/e_devcrypto.c72
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)