static int cryptodev_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { struct dev_crypto_state *state = ctx->cipher_data; struct session_op *sess = &state->d_sess; struct dev_crypto_cipher *cipher; if ((cipher = cipher_nid_to_cryptodev(ctx->cipher->nid)) == NULL) return (0); if (ctx->cipher->iv_len > cipher->c_ivmax) return (0); if (ctx->key_len != cipher->c_keylen) return (0); memset(sess, 0, sizeof(struct session_op)); if ((state->d_fd = get_dev_crypto()) < 0) return (0); sess->key = (unsigned char *)key; sess->keylen = ctx->key_len; sess->cipher = cipher->c_id; if (ioctl(state->d_fd, CIOCGSESSION, sess) == -1) { close(state->d_fd); state->d_fd = -1; return (0); } return (1); }
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(*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) { put_dev_crypto(state->d_fd); state->d_fd = -1; printf("cryptodev_digest_init: Open session failed\n"); return (0); } return (1); }
/* * Find out what digests /dev/crypto will let us have a session for. * XXX note, that some of these openssl doesn't deal with yet! * returning them here is harmless, as long as we return NULL * when asked for a handler in the cryptodev_engine_digests routine */ #if 0 /* UNUSED */ static int get_cryptodev_digests(const int **cnids) { static int nids[CRYPTO_ALGORITHM_MAX]; struct session_op sess; int fd, i, count = 0; if ((fd = get_dev_crypto()) < 0) { *cnids = NULL; return (0); } memset(&sess, 0, sizeof(sess)); for (i = 0; digests[i].id && count < CRYPTO_ALGORITHM_MAX; i++) { if (digests[i].nid == NID_undef) continue; sess.mac = digests[i].id; sess.cipher = 0; if (ioctl(fd, CIOCGSESSION, &sess) != -1 && ioctl(fd, CIOCFSESSION, &sess.ses) != -1) nids[count++] = digests[i].nid; } close(fd); if (count > 0) *cnids = nids; else *cnids = NULL; return (count); }
/* * Find out what ciphers /dev/crypto will let us have a session for. * XXX note, that some of these openssl doesn't deal with yet! * returning them here is harmless, as long as we return NULL * when asked for a handler in the cryptodev_engine_ciphers routine */ static int get_cryptodev_ciphers(const int **cnids) { static int nids[CRYPTO_ALGORITHM_MAX]; struct session_op sess; int fd, i, count = 0; if ((fd = get_dev_crypto()) < 0) { *cnids = NULL; return (0); } memset(&sess, 0, sizeof(sess)); sess.key = (caddr_t) "123456789abcdefghijklmno"; for (i = 0; ciphers[i].id && count < CRYPTO_ALGORITHM_MAX; i++) { if (ciphers[i].nid == NID_undef) continue; sess.cipher = ciphers[i].id; sess.keylen = ciphers[i].keylen; sess.mac = 0; if (ioctl(fd, CIOCGSESSION, &sess) != -1 && ioctl(fd, CIOCFSESSION, &sess.ses) != -1) nids[count++] = ciphers[i].nid; } put_dev_crypto(fd); if (count > 0) *cnids = nids; else *cnids = NULL; return (count); }
/* * Find out what ciphers /dev/crypto will let us have a session for. * XXX note, that some of these openssl doesn't deal with yet! * returning them here is harmless, as long as we return NULL * when asked for a handler in the cryptodev_engine_ciphers routine */ static int get_cryptodev_ciphers(const int **cnids) { static int nids[CRYPTO_ALGORITHM_MAX]; struct session_op sess; int fd, i, count = 0; if ((fd = get_dev_crypto()) < 0) { *cnids = NULL; return (0); } memset(&sess, 0, sizeof(sess)); sess.key = (caddr_t)"123456781234567812345678"; for (i = 0; ciphers[i].c_id && count < CRYPTO_ALGORITHM_MAX; i++) { if (ciphers[i].c_nid == NID_undef) continue; sess.cipher = ciphers[i].c_id; sess.keylen = ciphers[i].c_keylen; sess.mac = 0; if (ioctl(fd, CIOCGSESSION, &sess) != -1 && ioctl(fd, CIOCFSESSION, &sess.ses) != -1) nids[count++] = ciphers[i].c_nid; } close(fd); #if defined(__i386__) /* * On i386, always check for the VIA C3 AES instructions; * even if /dev/crypto is disabled. */ if (check_viac3aes() >= 1) { int have_NID_aes_128_cbc = 0; int have_NID_aes_192_cbc = 0; int have_NID_aes_256_cbc = 0; for (i = 0; i < count; i++) { if (nids[i] == NID_aes_128_cbc) have_NID_aes_128_cbc = 1; if (nids[i] == NID_aes_192_cbc) have_NID_aes_192_cbc = 1; if (nids[i] == NID_aes_256_cbc) have_NID_aes_256_cbc = 1; } if (!have_NID_aes_128_cbc) nids[count++] = NID_aes_128_cbc; if (!have_NID_aes_192_cbc) nids[count++] = NID_aes_192_cbc; if (!have_NID_aes_256_cbc) nids[count++] = NID_aes_256_cbc; } #endif if (count > 0) *cnids = nids; else *cnids = NULL; return (count); }
/* Caching version for asym operations */ static int get_asym_dev_crypto(void) { static int fd = -1; if (fd == -1) fd = get_dev_crypto(); return fd; }
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; 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(to->digest->type); sess->mackey = dstate->dummy_mac_key; sess->mackeylen = digest_key_length(to->digest->type); 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 int cryptodev_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { struct dev_crypto_state *state = ctx->cipher_data; struct session_op *sess = &state->d_sess; int cipher = -1, i; for (i = 0; ciphers[i].id; i++) if (ctx->cipher->nid == ciphers[i].nid && ctx->cipher->iv_len <= ciphers[i].ivmax && ctx->key_len == ciphers[i].keylen) { cipher = ciphers[i].id; break; } if (!ciphers[i].id) { state->d_fd = -1; return (0); } memset(sess, 0, sizeof(*sess)); if ((state->d_fd = get_dev_crypto()) < 0) return (0); sess->key = (caddr_t) key; sess->keylen = ctx->key_len; sess->cipher = cipher; if (ioctl(state->d_fd, CIOCGSESSION, sess) == -1) { put_dev_crypto(state->d_fd); state->d_fd = -1; return (0); } return (1); }
void ENGINE_load_cryptodev(void) { ENGINE *engine = ENGINE_new(); int fd; if (engine == NULL) return; if ((fd = get_dev_crypto()) < 0) { ENGINE_free(engine); return; } /* * find out what asymmetric crypto algorithms we support */ if (ioctl(fd, CIOCASYMFEAT, &cryptodev_asymfeat) == -1) { close(fd); ENGINE_free(engine); return; } close(fd); if (!ENGINE_set_id(engine, "cryptodev") || !ENGINE_set_name(engine, "BSD cryptodev engine") || !ENGINE_set_ciphers(engine, cryptodev_engine_ciphers) || !ENGINE_set_digests(engine, cryptodev_engine_digests) || !ENGINE_set_ctrl_function(engine, cryptodev_ctrl) || !ENGINE_set_cmd_defns(engine, cryptodev_defns)) { ENGINE_free(engine); return; } if (ENGINE_set_RSA(engine, &cryptodev_rsa)) { const RSA_METHOD *rsa_meth = RSA_PKCS1_SSLeay(); cryptodev_rsa.bn_mod_exp = rsa_meth->bn_mod_exp; cryptodev_rsa.rsa_mod_exp = rsa_meth->rsa_mod_exp; cryptodev_rsa.rsa_pub_enc = rsa_meth->rsa_pub_enc; cryptodev_rsa.rsa_pub_dec = rsa_meth->rsa_pub_dec; cryptodev_rsa.rsa_priv_enc = rsa_meth->rsa_priv_enc; cryptodev_rsa.rsa_priv_dec = rsa_meth->rsa_priv_dec; if (cryptodev_asymfeat & CRF_MOD_EXP) { cryptodev_rsa.bn_mod_exp = cryptodev_bn_mod_exp; if (cryptodev_asymfeat & CRF_MOD_EXP_CRT) cryptodev_rsa.rsa_mod_exp = cryptodev_rsa_mod_exp; else cryptodev_rsa.rsa_mod_exp = cryptodev_rsa_nocrt_mod_exp; } } if (ENGINE_set_DSA(engine, &cryptodev_dsa)) { const DSA_METHOD *meth = DSA_OpenSSL(); memcpy(&cryptodev_dsa, meth, sizeof(DSA_METHOD)); if (cryptodev_asymfeat & CRF_DSA_SIGN) cryptodev_dsa.dsa_do_sign = cryptodev_dsa_do_sign; if (cryptodev_asymfeat & CRF_MOD_EXP) { cryptodev_dsa.bn_mod_exp = cryptodev_dsa_bn_mod_exp; cryptodev_dsa.dsa_mod_exp = cryptodev_dsa_dsa_mod_exp; } if (cryptodev_asymfeat & CRF_DSA_VERIFY) cryptodev_dsa.dsa_do_verify = cryptodev_dsa_verify; } if (ENGINE_set_DH(engine, &cryptodev_dh)){ const DH_METHOD *dh_meth = DH_OpenSSL(); cryptodev_dh.generate_key = dh_meth->generate_key; cryptodev_dh.compute_key = dh_meth->compute_key; cryptodev_dh.bn_mod_exp = dh_meth->bn_mod_exp; if (cryptodev_asymfeat & CRF_MOD_EXP) { cryptodev_dh.bn_mod_exp = cryptodev_mod_exp_dh; if (cryptodev_asymfeat & CRF_DH_COMPUTE_KEY) cryptodev_dh.compute_key = cryptodev_dh_compute_key; } } ENGINE_add(engine); ENGINE_free(engine); ERR_clear_error(); }
/* * Find out what we can support and use it. */ void load_cryptodev(void) { struct session_op ses; int assisted = 0; u_int32_t feat; struct lswcrypto_meth old_meth = lswcrypto; if ((cryptodev_fd = get_dev_crypto()) == -1) { libreswan_log( "OCF assist for IKE disabled: is the cryptodev module loaded ?"); return; } /* find out what asymmetric crypto algorithms we support */ if (ioctl(cryptodev_fd, CIOCASYMFEAT, &feat) != -1) { if (feat & CRF_MOD_EXP) { /* Use modular exponentiation */ lswcrypto.mod_exp = cryptodev_mod_exp; libreswan_log( "OCF assist for IKE for modular exponentiation enabled"); assisted++; } if (feat & CRF_MOD_EXP_CRT) { lswcrypto.rsa_mod_exp_crt = cryptodev_rsa_mod_exp_crt; libreswan_log( "OCF assist for IKE for modular exponentiation (CRT) enabled"); assisted++; } } /* test we can do AES */ memset(&ses, 0, sizeof(ses)); ses.key = (caddr_t)"12345678901234567890123456789012"; ses.cipher = CRYPTO_AES_CBC; ses.keylen = 16; if (ioctl(cryptodev_fd, CIOCGSESSION, &ses) != -1 && ioctl(cryptodev_fd, CIOCFSESSION, &ses.ses) != -1) { libreswan_log("OCF assist for IKE for AES crypto enabled"); lswcrypto.aes_set_key = cryptodev_aes_set_key; lswcrypto.aes_cbc_encrypt = cryptodev_aes_cbc_encrypt; assisted++; } /* test we can do DES */ memset(&ses, 0, sizeof(ses)); ses.key = (caddr_t)"123456789012345678901234"; ses.cipher = CRYPTO_DES_CBC; ses.keylen = 8; if (ioctl(cryptodev_fd, CIOCGSESSION, &ses) != -1 && ioctl(cryptodev_fd, CIOCFSESSION, &ses.ses) != -1) { libreswan_log("OCF assist for IKE for DES crypto enabled"); lswcrypto.des_set_key = cryptodev_des_set_key; lswcrypto.des_cbc_encrypt = cryptodev_des_cbc_encrypt; lswcrypto.des_encrypt = cryptodev_des_encrypt; lswcrypto.des_ncbc_encrypt = cryptodev_des_ncbc_encrypt; lswcrypto.des_ecb_encrypt = cryptodev_des_ecb_encrypt; assisted++; /* test we can do 3DES */ ses.cipher = CRYPTO_3DES_CBC; ses.keylen = 24; if (ioctl(cryptodev_fd, CIOCGSESSION, &ses) != -1 && ioctl(cryptodev_fd, CIOCFSESSION, &ses.ses) != -1) { libreswan_log( "OCF assist for IKE for 3DES crypto enabled"); lswcrypto.des_ede3_cbc_encrypt = cryptodev_des_ede3_cbc_encrypt; //DAVIDM 3des setkey is technically needed if HW can only do DES assisted++; } } if (assisted == 0) { close(cryptodev_fd); cryptodev_fd = -1; } else if (!soft_meth_loaded) { soft_meth_loaded = 1; soft_meth = old_meth; } }