+ const int **nids, int nid)
+{
+ if (!cipher)
+ return (cryptodev_usable_ciphers(nids));
+
+ switch (nid) {
+ case NID_rc4:
+ *cipher = cryptodev_rc4();
+ break;
+ case NID_des_ede3_cbc:
+ *cipher = cryptodev_3des_cbc();
+ break;
+ case NID_des_cbc:
+ *cipher = cryptodev_des_cbc();
+ break;
+ case NID_bf_cbc:
+ *cipher = cryptodev_bf_cbc();
+ break;
+ case NID_cast5_cbc:
+ *cipher = cryptodev_cast_cbc();
+ break;
+ case NID_aes_128_cbc:
+ *cipher = cryptodev_aes_cbc();
+ break;
+ case NID_aes_192_cbc:
+ *cipher = cryptodev_aes_192_cbc();
+ break;
+ case NID_aes_256_cbc:
+ *cipher = cryptodev_aes_256_cbc();
+ break;
+# ifdef CRYPTO_AES_CTR
+ case NID_aes_128_ctr:
+ *cipher = cryptodev_aes_ctr();
+ break;
+ case NID_aes_192_ctr:
+ *cipher = cryptodev_aes_192_ctr();
+ break;
+ case NID_aes_256_ctr:
+ *cipher = cryptodev_aes_256_ctr();
+ break;
+# endif
+ default:
+ *cipher = NULL;
+ break;
+ }
+ return (*cipher != NULL);
+}
+
+# ifdef USE_CRYPTODEV_DIGESTS
+
+/* convert digest type to cryptodev */
+static int digest_nid_to_cryptodev(int nid)
+{
+ int i;
+
+ for (i = 0; digests[i].id; i++)
+ if (digests[i].nid == nid)
+ return (digests[i].id);
+ return (0);
+}
+
+static int cryptodev_digest_init(EVP_MD_CTX *ctx)
+{
+ struct dev_crypto_state *state = EVP_MD_CTX_md_data(ctx);
+ struct session_op *sess = &state->d_sess;
+ int digest;
+
+ if ((digest = digest_nid_to_cryptodev(EVP_MD_CTX_type(ctx))) == NID_undef) {
+ printf("cryptodev_digest_init: Can't get digest \n");
+ return (0);
+ }
+
+ memset(state, 0, sizeof(*state));
+
+ if ((state->d_fd = get_dev_crypto()) < 0) {
+ printf("cryptodev_digest_init: Can't get Dev \n");
+ return (0);
+ }
+
+ sess->mackey = NULL;
+ sess->mackeylen = 0;
+ sess->mac = digest;
+
+ if (ioctl(state->d_fd, CIOCGSESSION, sess) < 0) {
+ put_dev_crypto(state->d_fd);
+ state->d_fd = -1;
+ printf("cryptodev_digest_init: Open session failed\n");
+ return (0);
+ }
+
+ return (1);
+}
+
+static int cryptodev_digest_update(EVP_MD_CTX *ctx, const void *data,
+ size_t count)
+{
+ struct crypt_op cryp;
+ struct dev_crypto_state *state = EVP_MD_CTX_md_data(ctx);
+ struct session_op *sess = &state->d_sess;
+ char *new_mac_data;
+
+ if (!data || state->d_fd < 0) {
+ printf("cryptodev_digest_update: illegal inputs \n");
+ return (0);
+ }
+
+ if (!count) {
+ return (0);
+ }
+
+ if (!EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) {
+ /* if application doesn't support one buffer */
+ new_mac_data =
+ OPENSSL_realloc(state->mac_data, state->mac_len + count);
+
+ if (!new_mac_data) {
+ printf("cryptodev_digest_update: realloc failed\n");
+ return (0);
+ }
+ state->mac_data = new_mac_data;
+
+ memcpy(state->mac_data + state->mac_len, data, count);
+ state->mac_len += count;
+
+ return (1);
+ }
+
+ memset(&cryp, 0, sizeof(cryp));
+
+ cryp.ses = sess->ses;
+ cryp.flags = 0;
+ cryp.len = count;
+ cryp.src = (void *) data;
+ cryp.dst = NULL;
+ cryp.mac = (void *) state->digest_res;
+ if (ioctl(state->d_fd, CIOCCRYPT, &cryp) < 0) {
+ printf("cryptodev_digest_update: digest failed\n");
+ return (0);
+ }
+ return (1);
+}
+
+static int cryptodev_digest_final(EVP_MD_CTX *ctx, unsigned char *md)
+{
+ struct crypt_op cryp;
+ struct dev_crypto_state *state = EVP_MD_CTX_md_data(ctx);
+ struct session_op *sess = &state->d_sess;
+
+ int ret = 1;
+
+ if (!md || state->d_fd < 0) {
+ printf("cryptodev_digest_final: illegal input\n");
+ return (0);
+ }
+
+ if (!EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) {
+ /* if application doesn't support one buffer */
+ memset(&cryp, 0, sizeof(cryp));
+ cryp.ses = sess->ses;
+ cryp.flags = 0;
+ cryp.len = state->mac_len;
+ cryp.src = state->mac_data;
+ cryp.dst = NULL;
+ cryp.mac = (void *) md;
+ if (ioctl(state->d_fd, CIOCCRYPT, &cryp) < 0) {
+ printf("cryptodev_digest_final: digest failed\n");
+ return (0);
+ }
+
+ return 1;
+ }
+
+ memcpy(md, state->digest_res, EVP_MD_CTX_size(ctx));
+
+ return (ret);
+}
+
+static int cryptodev_digest_cleanup(EVP_MD_CTX *ctx)
+{
+ int ret = 1;
+ struct dev_crypto_state *state = EVP_MD_CTX_md_data(ctx);
+ struct session_op *sess = &state->d_sess;
+
+ if (state == NULL)
+ return 0;
+
+ if (state->d_fd < 0) {
+ printf("cryptodev_digest_cleanup: illegal input\n");
+ return (0);
+ }
+
+ OPENSSL_free(state->mac_data);
+ state->mac_data = NULL;
+ state->mac_len = 0;
+
+ if (ioctl(state->d_fd, CIOCFSESSION, &sess->ses) < 0) {
+ printf("cryptodev_digest_cleanup: failed to close session\n");
+ ret = 0;
+ } else {
+ ret = 1;
+ }
+ put_dev_crypto(state->d_fd);
+ state->d_fd = -1;
+
+ return (ret);
+}
+
+static int cryptodev_digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
+{
+ struct dev_crypto_state *fstate = EVP_MD_CTX_md_data(from);
+ struct dev_crypto_state *dstate = EVP_MD_CTX_md_data(to);
+ struct session_op *sess;
+ int digest;
+
+ if (dstate == NULL || fstate == NULL)
+ return 1;
+
+ memcpy(dstate, fstate, sizeof(struct dev_crypto_state));
+
+ sess = &dstate->d_sess;
+
+ digest = digest_nid_to_cryptodev(EVP_MD_CTX_type(to));
+
+ sess->mackey = NULL;
+ sess->mackeylen = 0;
+ sess->mac = digest;
+
+ dstate->d_fd = get_dev_crypto();
+
+ if (ioctl(dstate->d_fd, CIOCGSESSION, sess) < 0) {
+ put_dev_crypto(dstate->d_fd);
+ dstate->d_fd = -1;
+ printf("cryptodev_digest_copy: Open session failed\n");
+ return (0);
+ }
+
+ if (fstate->mac_len != 0) {
+ if (fstate->mac_data != NULL) {
+ dstate->mac_data = OPENSSL_malloc(fstate->mac_len);
+ if (dstate->mac_data == NULL) {
+ printf("cryptodev_digest_copy: mac_data allocation failed\n");
+ return (0);
+ }
+ memcpy(dstate->mac_data, fstate->mac_data, fstate->mac_len);
+ dstate->mac_len = fstate->mac_len;
+ }
+ }
+
+ return 1;
+}
+
+static EVP_MD *sha1_md = NULL;
+static const EVP_MD *cryptodev_sha1(void)
+{
+ if (sha1_md == NULL) {
+ EVP_MD *md;
+
+ if ((md = EVP_MD_meth_new(NID_sha1, NID_undef)) == NULL
+ || !EVP_MD_meth_set_result_size(md, SHA_DIGEST_LENGTH)
+ || !EVP_MD_meth_set_flags(md, EVP_MD_FLAG_ONESHOT)
+ || !EVP_MD_meth_set_input_blocksize(md, SHA_CBLOCK)
+ || !EVP_MD_meth_set_app_datasize(md,
+ sizeof(struct dev_crypto_state))
+ || !EVP_MD_meth_set_init(md, cryptodev_digest_init)
+ || !EVP_MD_meth_set_update(md, cryptodev_digest_update)
+ || !EVP_MD_meth_set_final(md, cryptodev_digest_final)
+ || !EVP_MD_meth_set_copy(md, cryptodev_digest_copy)
+ || !EVP_MD_meth_set_cleanup(md, cryptodev_digest_cleanup)) {
+ EVP_MD_meth_free(md);
+ md = NULL;
+ }
+ sha1_md = md;
+ }
+ return sha1_md;
+}
+
+static EVP_MD *sha256_md = NULL;
+static const EVP_MD *cryptodev_sha256(void)
+{
+ if (sha256_md == NULL) {
+ EVP_MD *md;
+
+ if ((md = EVP_MD_meth_new(NID_sha256, NID_undef)) == NULL
+ || !EVP_MD_meth_set_result_size(md, SHA_DIGEST_LENGTH)
+ || !EVP_MD_meth_set_flags(md, EVP_MD_FLAG_ONESHOT)
+ || !EVP_MD_meth_set_input_blocksize(md, SHA_CBLOCK)
+ || !EVP_MD_meth_set_app_datasize(md,
+ sizeof(struct dev_crypto_state))
+ || !EVP_MD_meth_set_init(md, cryptodev_digest_init)
+ || !EVP_MD_meth_set_update(md, cryptodev_digest_update)
+ || !EVP_MD_meth_set_final(md, cryptodev_digest_final)
+ || !EVP_MD_meth_set_copy(md, cryptodev_digest_copy)
+ || !EVP_MD_meth_set_cleanup(md, cryptodev_digest_cleanup)) {
+ EVP_MD_meth_free(md);
+ md = NULL;
+ }
+ sha256_md = md;
+ }
+ return sha256_md;
+}
+
+static EVP_MD *sha224_md = NULL;
+static const EVP_MD *cryptodev_sha224(void)
+{
+ if (sha224_md == NULL) {
+ EVP_MD *md;
+
+ if ((md = EVP_MD_meth_new(NID_sha224, NID_undef)) == NULL
+ || !EVP_MD_meth_set_result_size(md, SHA_DIGEST_LENGTH)
+ || !EVP_MD_meth_set_flags(md, EVP_MD_FLAG_ONESHOT)
+ || !EVP_MD_meth_set_input_blocksize(md, SHA_CBLOCK)
+ || !EVP_MD_meth_set_app_datasize(md,
+ sizeof(struct dev_crypto_state))
+ || !EVP_MD_meth_set_init(md, cryptodev_digest_init)
+ || !EVP_MD_meth_set_update(md, cryptodev_digest_update)
+ || !EVP_MD_meth_set_final(md, cryptodev_digest_final)
+ || !EVP_MD_meth_set_copy(md, cryptodev_digest_copy)
+ || !EVP_MD_meth_set_cleanup(md, cryptodev_digest_cleanup)) {
+ EVP_MD_meth_free(md);
+ md = NULL;
+ }
+ sha224_md = md;
+ }
+ return sha224_md;
+}
+
+static EVP_MD *sha384_md = NULL;
+static const EVP_MD *cryptodev_sha384(void)
+{
+ if (sha384_md == NULL) {
+ EVP_MD *md;
+
+ if ((md = EVP_MD_meth_new(NID_sha384, NID_undef)) == NULL
+ || !EVP_MD_meth_set_result_size(md, SHA_DIGEST_LENGTH)
+ || !EVP_MD_meth_set_flags(md, EVP_MD_FLAG_ONESHOT)
+ || !EVP_MD_meth_set_input_blocksize(md, SHA_CBLOCK)
+ || !EVP_MD_meth_set_app_datasize(md,
+ sizeof(struct dev_crypto_state))
+ || !EVP_MD_meth_set_init(md, cryptodev_digest_init)
+ || !EVP_MD_meth_set_update(md, cryptodev_digest_update)
+ || !EVP_MD_meth_set_final(md, cryptodev_digest_final)
+ || !EVP_MD_meth_set_copy(md, cryptodev_digest_copy)
+ || !EVP_MD_meth_set_cleanup(md, cryptodev_digest_cleanup)) {
+ EVP_MD_meth_free(md);
+ md = NULL;
+ }
+ sha384_md = md;
+ }
+ return sha384_md;
+}
+
+static EVP_MD *sha512_md = NULL;
+static const EVP_MD *cryptodev_sha512(void)