Commit 2bafe6cf authored by Eneas U de Queiroz's avatar Eneas U de Queiroz Committed by Richard Levitte
Browse files

eng_devcrypto: add command to dump driver info



This is useful to determine the kernel driver running each algorithm.

Signed-off-by: default avatarEneas U de Queiroz <cote2004-github@yahoo.com>

Reviewed-by: default avatarMatthias St. Pierre <Matthias.St.Pierre@ncp-e.com>
Reviewed-by: default avatarRichard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/7585)
parent 166261a5
Loading
Loading
Loading
Loading
+127 −24
Original line number Diff line number Diff line
@@ -48,7 +48,9 @@ static int use_softdrivers = DEVCRYPTO_DEFAULT_USE_SOFDTRIVERS;
 */
struct driver_info_st {
    enum devcrypto_status_t {
        DEVCRYPTO_STATUS_UNUSABLE       = -1, /* session open failed */
        DEVCRYPTO_STATUS_FAILURE         = -3, /* unusable for other reason */
        DEVCRYPTO_STATUS_NO_CIOCCPHASH   = -2, /* hash state copy not supported */
        DEVCRYPTO_STATUS_NO_CIOCGSESSION = -1, /* session open failed */
        DEVCRYPTO_STATUS_UNKNOWN         =  0, /* not tested yet */
        DEVCRYPTO_STATUS_USABLE          =  1  /* algo can be used */
    } status;
@@ -58,6 +60,8 @@ struct driver_info_st {
        DEVCRYPTO_ACCELERATION_UNKNOWN   =  0, /* acceleration support unkown */
        DEVCRYPTO_ACCELERATED            =  1  /* hardware accelerated */
    } accelerated;

    char *driver_name;
};

/******************************************************************************
@@ -392,7 +396,7 @@ static void prepare_cipher_methods(void)
        sess.cipher = cipher_data[i].devcryptoid;
        sess.keylen = cipher_data[i].keylen;
        if (ioctl(cfd, CIOCGSESSION, &sess) < 0) {
            cipher_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE;
            cipher_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION;
            continue;
        }

@@ -419,19 +423,24 @@ static void prepare_cipher_methods(void)
                                            cipher_cleanup)
            || !EVP_CIPHER_meth_set_impl_ctx_size(known_cipher_methods[i],
                                                  sizeof(struct cipher_ctx))) {
            cipher_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE;
            cipher_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
            EVP_CIPHER_meth_free(known_cipher_methods[i]);
            known_cipher_methods[i] = NULL;
        } else {
            cipher_driver_info[i].status = DEVCRYPTO_STATUS_USABLE;
#ifdef CIOCGSESSINFO
            siop.ses = sess.ses;
            if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0)
            if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) {
                cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN;
            else if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY))
            } else {
                cipher_driver_info[i].driver_name =
                    OPENSSL_strndup(siop.cipher_info.cra_driver_name,
                                    CRYPTODEV_MAX_ALG_NAME);
                if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY))
                    cipher_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED;
                else
                    cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED;
            }
#endif /* CIOCGSESSINFO */
        }
        ioctl(cfd, CIOCFSESSION, &sess.ses);
@@ -481,8 +490,11 @@ static void destroy_all_cipher_methods(void)
{
    size_t i;

    for (i = 0; i < OSSL_NELEM(cipher_data); i++)
    for (i = 0; i < OSSL_NELEM(cipher_data); i++) {
        destroy_cipher_method(cipher_data[i].nid);
        OPENSSL_free(cipher_driver_info[i].driver_name);
        cipher_driver_info[i].driver_name = NULL;
    }
}

static int devcrypto_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
@@ -526,6 +538,40 @@ static int cryptodev_select_cipher_cb(const char *str, int len, void *usr)
    return 1;
}

static void dump_cipher_info(void)
{
    size_t i;
    const char *name;

    fprintf (stderr, "Information about ciphers supported by the /dev/crypto"
             " engine:\n");
#ifndef CIOCGSESSINFO
    fprintf(stderr, "CIOCGSESSINFO (session info call) unavailable\n");
#endif
    for (i = 0; i < OSSL_NELEM(cipher_data); i++) {
        name = OBJ_nid2sn(cipher_data[i].nid);
        fprintf (stderr, "Cipher %s, NID=%d, /dev/crypto info: id=%d, ",
                 name ? name : "unknown", cipher_data[i].nid,
                 cipher_data[i].devcryptoid);
        if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCGSESSION ) {
            fprintf (stderr, "CIOCGSESSION (session open call) failed\n");
            continue;
        }
        fprintf (stderr, "driver=%s ", cipher_driver_info[i].driver_name ?
                 cipher_driver_info[i].driver_name : "unknown");
        if (cipher_driver_info[i].accelerated == DEVCRYPTO_ACCELERATED)
            fprintf(stderr, "(hw accelerated)");
        else if (cipher_driver_info[i].accelerated == DEVCRYPTO_NOT_ACCELERATED)
            fprintf(stderr, "(software)");
        else
            fprintf(stderr, "(acceleration status unknown)");
        if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_FAILURE)
            fprintf (stderr, ". Cipher setup failed");
        fprintf(stderr, "\n");
    }
    fprintf(stderr, "\n");
}

/*
 * We only support digests if the cryptodev implementation supports multiple
 * data updates and session copying.  Otherwise, we would be forced to maintain
@@ -790,31 +836,36 @@ static void prepare_digest_methods(void)
        sess1.mac = digest_data[i].devcryptoid;
        sess2.ses = 0;
        if (ioctl(cfd, CIOCGSESSION, &sess1) < 0) {
            digest_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE;
            digest_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION;
            goto finish;
        }

#ifdef CIOCGSESSINFO
        /* gather hardware acceleration info from the driver */
        siop.ses = sess1.ses;
        if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0)
        if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) {
            digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN;
        else if (siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)
        } else {
            digest_driver_info[i].driver_name =
                OPENSSL_strndup(siop.hash_info.cra_driver_name,
                                CRYPTODEV_MAX_ALG_NAME);
            if (siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)
                digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED;
            else
                digest_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED;
        }
#endif

        /* digest must be capable of hash state copy */
        sess2.mac = sess1.mac;
        if (ioctl(cfd, CIOCGSESSION, &sess2) < 0) {
            digest_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE;
            digest_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
            goto finish;
        }
        cphash.src_ses = sess1.ses;
        cphash.dst_ses = sess2.ses;
        if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) {
            digest_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE;
            digest_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCCPHASH;
            goto finish;
        }
        if ((known_digest_methods[i] = EVP_MD_meth_new(digest_data[i].nid,
@@ -828,7 +879,7 @@ static void prepare_digest_methods(void)
            || !EVP_MD_meth_set_cleanup(known_digest_methods[i], digest_cleanup)
            || !EVP_MD_meth_set_app_datasize(known_digest_methods[i],
                                             sizeof(struct digest_ctx))) {
            digest_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE;
            digest_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
            EVP_MD_meth_free(known_digest_methods[i]);
            known_digest_methods[i] = NULL;
            goto finish;
@@ -870,8 +921,11 @@ static void destroy_all_digest_methods(void)
{
    size_t i;

    for (i = 0; i < OSSL_NELEM(digest_data); i++)
    for (i = 0; i < OSSL_NELEM(digest_data); i++) {
        destroy_digest_method(digest_data[i].nid);
        OPENSSL_free(digest_driver_info[i].driver_name);
        digest_driver_info[i].driver_name = NULL;
    }
}

static int devcrypto_digests(ENGINE *e, const EVP_MD **digest,
@@ -915,6 +969,43 @@ static int cryptodev_select_digest_cb(const char *str, int len, void *usr)
    return 1;
}

static void dump_digest_info(void)
{
    size_t i;
    const char *name;

    fprintf (stderr, "Information about digests supported by the /dev/crypto"
             " engine:\n");
#ifndef CIOCGSESSINFO
    fprintf(stderr, "CIOCGSESSINFO (session info call) unavailable\n");
#endif

    for (i = 0; i < OSSL_NELEM(digest_data); i++) {
        name = OBJ_nid2sn(digest_data[i].nid);
        fprintf (stderr, "Digest %s, NID=%d, /dev/crypto info: id=%d, driver=%s",
                 name ? name : "unknown", digest_data[i].nid,
                 digest_data[i].devcryptoid,
                 digest_driver_info[i].driver_name ? digest_driver_info[i].driver_name : "unknown");
        if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCGSESSION) {
            fprintf (stderr, ". CIOCGSESSION (session open) failed\n");
            continue;
        }
        if (digest_driver_info[i].accelerated == DEVCRYPTO_ACCELERATED)
            fprintf(stderr, " (hw accelerated)");
        else if (digest_driver_info[i].accelerated == DEVCRYPTO_NOT_ACCELERATED)
            fprintf(stderr, " (software)");
        else
            fprintf(stderr, " (acceleration status unknown)");
        if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_FAILURE)
            fprintf (stderr, ". Cipher setup failed\n");
        else if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCCPHASH)
            fprintf(stderr, ", CIOCCPHASH failed\n");
        else
            fprintf(stderr, ", CIOCCPHASH capable\n");
    }
    fprintf(stderr, "\n");
}

#endif

/******************************************************************************
@@ -953,6 +1044,11 @@ static const ENGINE_CMD_DEFN devcrypto_cmds[] = {
    ENGINE_CMD_FLAG_STRING},
#endif

   {DEVCRYPTO_CMD_DUMP_INFO,
    "DUMP_INFO",
    "dump info about each algorithm to stderr; use 'openssl engine -pre DUMP_INFO devcrypto'",
    ENGINE_CMD_FLAG_NO_INPUT},

   {0, NULL, NULL, 0}
};

@@ -1021,6 +1117,13 @@ static int devcrypto_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
        return 1;
#endif /* IMPLEMENT_DIGEST */

    case DEVCRYPTO_CMD_DUMP_INFO:
        dump_cipher_info();
#ifdef IMPLEMENT_DIGEST
        dump_digest_info();
#endif
        return 1;

    default:
        break;
    }