+
+#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
+digest_key_length(int nid)
+{
+ int i;
+
+ for (i = 0; digests[i].id; i++)
+ if (digests[i].nid == nid)
+ return digests[i].keylen;
+ return (0);
+}
+
+
+static int cryptodev_digest_init(EVP_MD_CTX *ctx)
+{
+ struct dev_crypto_state *state = ctx->md_data;
+ struct session_op *sess = &state->d_sess;
+ int digest;
+
+ if ((digest = digest_nid_to_cryptodev(ctx->digest->type)) == NID_undef){
+ printf("cryptodev_digest_init: Can't get digest \n");
+ return (0);
+ }
+
+ memset(state, 0, sizeof(struct dev_crypto_state));
+
+ if ((state->d_fd = get_dev_crypto()) < 0) {
+ printf("cryptodev_digest_init: Can't get Dev \n");
+ return (0);
+ }
+
+ sess->mackey = state->dummy_mac_key;
+ sess->mackeylen = digest_key_length(ctx->digest->type);
+ sess->mac = digest;
+
+ if (ioctl(state->d_fd, CIOCGSESSION, sess) < 0) {
+ close(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 = ctx->md_data;
+ struct session_op *sess = &state->d_sess;
+
+ if (!data || state->d_fd < 0) {
+ printf("cryptodev_digest_update: illegal inputs \n");
+ return (0);
+ }
+
+ if (!count) {
+ return (0);
+ }
+
+ if (!(ctx->flags & EVP_MD_CTX_FLAG_ONESHOT)) {
+ /* if application doesn't support one buffer */
+ state->mac_data = OPENSSL_realloc(state->mac_data, state->mac_len + count);
+
+ if (!state->mac_data) {
+ printf("cryptodev_digest_update: realloc failed\n");
+ return (0);
+ }
+
+ 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 = (caddr_t) data;
+ cryp.dst = NULL;
+ cryp.mac = (caddr_t) 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 = ctx->md_data;
+ 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 (! (ctx->flags & 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 = (caddr_t)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, ctx->digest->md_size);
+
+ return (ret);
+}
+
+
+static int cryptodev_digest_cleanup(EVP_MD_CTX *ctx)
+{
+ int ret = 1;
+ struct dev_crypto_state *state = ctx->md_data;
+ struct session_op *sess = &state->d_sess;
+
+ if (state->d_fd < 0) {
+ printf("cryptodev_digest_cleanup: illegal input\n");
+ return (0);
+ }
+
+ if (state->mac_data) {
+ OPENSSL_free(state->mac_data);
+ state->mac_data = NULL;
+ state->mac_len = 0;
+ }
+
+ if (state->copy)
+ return 1;
+
+ if (ioctl(state->d_fd, CIOCFSESSION, &sess->ses) < 0) {
+ printf("cryptodev_digest_cleanup: failed to close session\n");
+ ret = 0;
+ } else {
+ ret = 1;
+ }
+ close(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 = from->md_data;
+ struct dev_crypto_state *dstate = to->md_data;
+
+ memcpy(dstate, fstate, sizeof(struct dev_crypto_state));
+
+ if (fstate->mac_len != 0) {
+ dstate->mac_data = OPENSSL_malloc(fstate->mac_len);
+ memcpy(dstate->mac_data, fstate->mac_data, fstate->mac_len);
+ }
+
+ dstate->copy = 1;
+
+ return 1;
+}
+
+
+const EVP_MD cryptodev_sha1 = {
+ NID_sha1,
+ NID_undef,
+ SHA_DIGEST_LENGTH,
+ EVP_MD_FLAG_ONESHOT,
+ cryptodev_digest_init,
+ cryptodev_digest_update,
+ cryptodev_digest_final,
+ cryptodev_digest_copy,
+ cryptodev_digest_cleanup,
+ EVP_PKEY_NULL_method,
+ SHA_CBLOCK,
+ sizeof(struct dev_crypto_state),
+};
+
+const EVP_MD cryptodev_md5 = {
+ NID_md5,
+ NID_undef,
+ 16 /* MD5_DIGEST_LENGTH */,
+ EVP_MD_FLAG_ONESHOT,
+ cryptodev_digest_init,
+ cryptodev_digest_update,
+ cryptodev_digest_final,
+ cryptodev_digest_copy,
+ cryptodev_digest_cleanup,
+ EVP_PKEY_NULL_method,
+ 64 /* MD5_CBLOCK */,
+ sizeof(struct dev_crypto_state),
+};
+
+#endif /* USE_CRYPTODEV_DIGESTS */
+
+