123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470 |
- /*
- * Copyright (c) 2002 Bob Beck <beck@openbsd.org>
- * Copyright (c) 2002 Theo de Raadt
- * Copyright (c) 2002 Markus Friedl
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
- #include <openssl/objects.h>
- #include <openssl/engine.h>
- #include <openssl/evp.h>
- #include <openssl/bn.h>
- #if (defined(__unix__) || defined(unix)) && !defined(USG) && \
- (defined(OpenBSD) || defined(__FreeBSD__))
- # include <sys/param.h>
- # if (OpenBSD >= 200112) || ((__FreeBSD_version >= 470101 && __FreeBSD_version < 500000) || __FreeBSD_version >= 500041)
- # define HAVE_CRYPTODEV
- # endif
- # if (OpenBSD >= 200110)
- # define HAVE_SYSLOG_R
- # endif
- #endif
- #ifndef HAVE_CRYPTODEV
- void ENGINE_load_cryptodev(void)
- {
- /* This is a NOP on platforms without /dev/crypto */
- return;
- }
- #else
- # include <sys/types.h>
- # include <crypto/cryptodev.h>
- # include <crypto/dh/dh.h>
- # include <crypto/dsa/dsa.h>
- # include <crypto/err/err.h>
- # include <crypto/rsa/rsa.h>
- # include <sys/ioctl.h>
- # include <errno.h>
- # include <stdio.h>
- # include <unistd.h>
- # include <fcntl.h>
- # include <stdarg.h>
- # include <syslog.h>
- # include <errno.h>
- # include <string.h>
- struct dev_crypto_state {
- struct session_op d_sess;
- int d_fd;
- # ifdef USE_CRYPTODEV_DIGESTS
- char dummy_mac_key[HASH_MAX_LEN];
- unsigned char digest_res[HASH_MAX_LEN];
- char *mac_data;
- int mac_len;
- # endif
- };
- static u_int32_t cryptodev_asymfeat = 0;
- static int get_asym_dev_crypto(void);
- static int open_dev_crypto(void);
- static int get_dev_crypto(void);
- static int get_cryptodev_ciphers(const int **cnids);
- # ifdef USE_CRYPTODEV_DIGESTS
- static int get_cryptodev_digests(const int **cnids);
- # endif
- static int cryptodev_usable_ciphers(const int **nids);
- static int cryptodev_usable_digests(const int **nids);
- static int cryptodev_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
- const unsigned char *in, size_t inl);
- static int cryptodev_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
- const unsigned char *iv, int enc);
- static int cryptodev_cleanup(EVP_CIPHER_CTX *ctx);
- static int cryptodev_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
- const int **nids, int nid);
- static int cryptodev_engine_digests(ENGINE *e, const EVP_MD **digest,
- const int **nids, int nid);
- static int bn2crparam(const BIGNUM *a, struct crparam *crp);
- static int crparam2bn(struct crparam *crp, BIGNUM *a);
- static void zapparams(struct crypt_kop *kop);
- static int cryptodev_asym(struct crypt_kop *kop, int rlen, BIGNUM *r,
- int slen, BIGNUM *s);
- static int cryptodev_bn_mod_exp(BIGNUM *r, const BIGNUM *a,
- const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
- BN_MONT_CTX *m_ctx);
- static int cryptodev_rsa_nocrt_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa,
- BN_CTX *ctx);
- static int cryptodev_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa,
- BN_CTX *ctx);
- static int cryptodev_dsa_bn_mod_exp(DSA *dsa, BIGNUM *r, BIGNUM *a,
- const BIGNUM *p, const BIGNUM *m,
- BN_CTX *ctx, BN_MONT_CTX *m_ctx);
- static int cryptodev_dsa_dsa_mod_exp(DSA *dsa, BIGNUM *t1, BIGNUM *g,
- BIGNUM *u1, BIGNUM *pub_key, BIGNUM *u2,
- BIGNUM *p, BN_CTX *ctx,
- BN_MONT_CTX *mont);
- static DSA_SIG *cryptodev_dsa_do_sign(const unsigned char *dgst, int dlen,
- DSA *dsa);
- static int cryptodev_dsa_verify(const unsigned char *dgst, int dgst_len,
- DSA_SIG *sig, DSA *dsa);
- static int cryptodev_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a,
- const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
- BN_MONT_CTX *m_ctx);
- static int cryptodev_dh_compute_key(unsigned char *key, const BIGNUM *pub_key,
- DH *dh);
- static int cryptodev_ctrl(ENGINE *e, int cmd, long i, void *p,
- void (*f) (void));
- void ENGINE_load_cryptodev(void);
- static const ENGINE_CMD_DEFN cryptodev_defns[] = {
- {0, NULL, NULL, 0}
- };
- static struct {
- int id;
- int nid;
- int ivmax;
- int keylen;
- } ciphers[] = {
- {
- CRYPTO_ARC4, NID_rc4, 0, 16,
- },
- {
- CRYPTO_DES_CBC, NID_des_cbc, 8, 8,
- },
- {
- CRYPTO_3DES_CBC, NID_des_ede3_cbc, 8, 24,
- },
- {
- CRYPTO_AES_CBC, NID_aes_128_cbc, 16, 16,
- },
- {
- CRYPTO_AES_CBC, NID_aes_192_cbc, 16, 24,
- },
- {
- CRYPTO_AES_CBC, NID_aes_256_cbc, 16, 32,
- },
- {
- CRYPTO_BLF_CBC, NID_bf_cbc, 8, 16,
- },
- {
- CRYPTO_CAST_CBC, NID_cast5_cbc, 8, 16,
- },
- {
- CRYPTO_SKIPJACK_CBC, NID_undef, 0, 0,
- },
- {
- 0, NID_undef, 0, 0,
- },
- };
- # ifdef USE_CRYPTODEV_DIGESTS
- static struct {
- int id;
- int nid;
- int keylen;
- } digests[] = {
- {
- CRYPTO_MD5_HMAC, NID_hmacWithMD5, 16
- },
- {
- CRYPTO_SHA1_HMAC, NID_hmacWithSHA1, 20
- },
- {
- CRYPTO_RIPEMD160_HMAC, NID_ripemd160, 16
- /* ? */
- },
- {
- CRYPTO_MD5_KPDK, NID_undef, 0
- },
- {
- CRYPTO_SHA1_KPDK, NID_undef, 0
- },
- {
- CRYPTO_MD5, NID_md5, 16
- },
- {
- CRYPTO_SHA1, NID_sha1, 20
- },
- {
- 0, NID_undef, 0
- },
- };
- # endif
- /*
- * Return a fd if /dev/crypto seems usable, 0 otherwise.
- */
- static int open_dev_crypto(void)
- {
- static int fd = -1;
- if (fd == -1) {
- if ((fd = open("/dev/crypto", O_RDWR, 0)) == -1)
- return (-1);
- /* close on exec */
- if (fcntl(fd, F_SETFD, 1) == -1) {
- close(fd);
- fd = -1;
- return (-1);
- }
- }
- return (fd);
- }
- static int get_dev_crypto(void)
- {
- int fd, retfd;
- if ((fd = open_dev_crypto()) == -1)
- return (-1);
- # ifndef CRIOGET_NOT_NEEDED
- if (ioctl(fd, CRIOGET, &retfd) == -1)
- return (-1);
- /* close on exec */
- if (fcntl(retfd, F_SETFD, 1) == -1) {
- close(retfd);
- return (-1);
- }
- # else
- retfd = fd;
- # endif
- return (retfd);
- }
- static void put_dev_crypto(int fd)
- {
- # ifndef CRIOGET_NOT_NEEDED
- close(fd);
- # endif
- }
- /* 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;
- }
- /*
- * 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);
- }
- # ifdef USE_CRYPTODEV_DIGESTS
- /*
- * 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
- */
- 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));
- sess.mackey = (caddr_t) "123456789abcdefghijklmno";
- for (i = 0; digests[i].id && count < CRYPTO_ALGORITHM_MAX; i++) {
- if (digests[i].nid == NID_undef)
- continue;
- sess.mac = digests[i].id;
- sess.mackeylen = digests[i].keylen;
- sess.cipher = 0;
- if (ioctl(fd, CIOCGSESSION, &sess) != -1 &&
- ioctl(fd, CIOCFSESSION, &sess.ses) != -1)
- nids[count++] = digests[i].nid;
- }
- put_dev_crypto(fd);
- if (count > 0)
- *cnids = nids;
- else
- *cnids = NULL;
- return (count);
- }
- # endif /* 0 */
- /*
- * Find the useable ciphers|digests from dev/crypto - this is the first
- * thing called by the engine init crud which determines what it
- * can use for ciphers from this engine. We want to return
- * only what we can do, anythine else is handled by software.
- *
- * If we can't initialize the device to do anything useful for
- * any reason, we want to return a NULL array, and 0 length,
- * which forces everything to be done is software. By putting
- * the initalization of the device in here, we ensure we can
- * use this engine as the default, and if for whatever reason
- * /dev/crypto won't do what we want it will just be done in
- * software
- *
- * This can (should) be greatly expanded to perhaps take into
- * account speed of the device, and what we want to do.
- * (although the disabling of particular alg's could be controlled
- * by the device driver with sysctl's.) - this is where we
- * want most of the decisions made about what we actually want
- * to use from /dev/crypto.
- */
- static int cryptodev_usable_ciphers(const int **nids)
- {
- return (get_cryptodev_ciphers(nids));
- }
- static int cryptodev_usable_digests(const int **nids)
- {
- # ifdef USE_CRYPTODEV_DIGESTS
- return (get_cryptodev_digests(nids));
- # else
- /*
- * XXXX just disable all digests for now, because it sucks.
- * we need a better way to decide this - i.e. I may not
- * want digests on slow cards like hifn on fast machines,
- * but might want them on slow or loaded machines, etc.
- * will also want them when using crypto cards that don't
- * suck moose gonads - would be nice to be able to decide something
- * as reasonable default without having hackery that's card dependent.
- * of course, the default should probably be just do everything,
- * with perhaps a sysctl to turn algoritms off (or have them off
- * by default) on cards that generally suck like the hifn.
- */
- *nids = NULL;
- return (0);
- # endif
- }
- static int
- cryptodev_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
- const unsigned char *in, size_t inl)
- {
- struct crypt_op cryp;
- struct dev_crypto_state *state = ctx->cipher_data;
- struct session_op *sess = &state->d_sess;
- const void *iiv;
- unsigned char save_iv[EVP_MAX_IV_LENGTH];
- if (state->d_fd < 0)
- return (0);
- if (!inl)
- return (1);
- if ((inl % ctx->cipher->block_size) != 0)
- return (0);
- memset(&cryp, 0, sizeof(cryp));
- cryp.ses = sess->ses;
- cryp.flags = 0;
- cryp.len = inl;
- cryp.src = (caddr_t) in;
- cryp.dst = (caddr_t) out;
- cryp.mac = 0;
- cryp.op = ctx->encrypt ? COP_ENCRYPT : COP_DECRYPT;
- if (ctx->cipher->iv_len) {
- cryp.iv = (caddr_t) ctx->iv;
- if (!ctx->encrypt) {
- iiv = in + inl - ctx->cipher->iv_len;
- memcpy(save_iv, iiv, ctx->cipher->iv_len);
- }
- } else
- cryp.iv = NULL;
- if (ioctl(state->d_fd, CIOCCRYPT, &cryp) == -1) {
- /*
- * XXX need better errror handling this can fail for a number of
- * different reasons.
- */
- return (0);
- }
- if (ctx->cipher->iv_len) {
- if (ctx->encrypt)
- iiv = out + inl - ctx->cipher->iv_len;
- else
- iiv = save_iv;
- memcpy(ctx->iv, iiv, ctx->cipher->iv_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(struct session_op));
- 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);
- }
- /*
- * free anything we allocated earlier when initting a
- * session, and close the session.
- */
- static int cryptodev_cleanup(EVP_CIPHER_CTX *ctx)
- {
- int ret = 0;
- struct dev_crypto_state *state = ctx->cipher_data;
- struct session_op *sess = &state->d_sess;
- if (state->d_fd < 0)
- return (0);
- /*
- * XXX if this ioctl fails, someting's wrong. the invoker may have called
- * us with a bogus ctx, or we could have a device that for whatever
- * reason just doesn't want to play ball - it's not clear what's right
- * here - should this be an error? should it just increase a counter,
- * hmm. For right now, we return 0 - I don't believe that to be "right".
- * we could call the gorpy openssl lib error handlers that print messages
- * to users of the library. hmm..
- */
- if (ioctl(state->d_fd, CIOCFSESSION, &sess->ses) == -1) {
- ret = 0;
- } else {
- ret = 1;
- }
- put_dev_crypto(state->d_fd);
- state->d_fd = -1;
- return (ret);
- }
- /*
- * libcrypto EVP stuff - this is how we get wired to EVP so the engine
- * gets called when libcrypto requests a cipher NID.
- */
- /* RC4 */
- const EVP_CIPHER cryptodev_rc4 = {
- NID_rc4,
- 1, 16, 0,
- EVP_CIPH_VARIABLE_LENGTH,
- cryptodev_init_key,
- cryptodev_cipher,
- cryptodev_cleanup,
- sizeof(struct dev_crypto_state),
- NULL,
- NULL,
- NULL
- };
- /* DES CBC EVP */
- const EVP_CIPHER cryptodev_des_cbc = {
- NID_des_cbc,
- 8, 8, 8,
- EVP_CIPH_CBC_MODE,
- cryptodev_init_key,
- cryptodev_cipher,
- cryptodev_cleanup,
- sizeof(struct dev_crypto_state),
- EVP_CIPHER_set_asn1_iv,
- EVP_CIPHER_get_asn1_iv,
- NULL
- };
- /* 3DES CBC EVP */
- const EVP_CIPHER cryptodev_3des_cbc = {
- NID_des_ede3_cbc,
- 8, 24, 8,
- EVP_CIPH_CBC_MODE,
- cryptodev_init_key,
- cryptodev_cipher,
- cryptodev_cleanup,
- sizeof(struct dev_crypto_state),
- EVP_CIPHER_set_asn1_iv,
- EVP_CIPHER_get_asn1_iv,
- NULL
- };
- const EVP_CIPHER cryptodev_bf_cbc = {
- NID_bf_cbc,
- 8, 16, 8,
- EVP_CIPH_CBC_MODE,
- cryptodev_init_key,
- cryptodev_cipher,
- cryptodev_cleanup,
- sizeof(struct dev_crypto_state),
- EVP_CIPHER_set_asn1_iv,
- EVP_CIPHER_get_asn1_iv,
- NULL
- };
- const EVP_CIPHER cryptodev_cast_cbc = {
- NID_cast5_cbc,
- 8, 16, 8,
- EVP_CIPH_CBC_MODE,
- cryptodev_init_key,
- cryptodev_cipher,
- cryptodev_cleanup,
- sizeof(struct dev_crypto_state),
- EVP_CIPHER_set_asn1_iv,
- EVP_CIPHER_get_asn1_iv,
- NULL
- };
- const EVP_CIPHER cryptodev_aes_cbc = {
- NID_aes_128_cbc,
- 16, 16, 16,
- EVP_CIPH_CBC_MODE,
- cryptodev_init_key,
- cryptodev_cipher,
- cryptodev_cleanup,
- sizeof(struct dev_crypto_state),
- EVP_CIPHER_set_asn1_iv,
- EVP_CIPHER_get_asn1_iv,
- NULL
- };
- const EVP_CIPHER cryptodev_aes_192_cbc = {
- NID_aes_192_cbc,
- 16, 24, 16,
- EVP_CIPH_CBC_MODE,
- cryptodev_init_key,
- cryptodev_cipher,
- cryptodev_cleanup,
- sizeof(struct dev_crypto_state),
- EVP_CIPHER_set_asn1_iv,
- EVP_CIPHER_get_asn1_iv,
- NULL
- };
- const EVP_CIPHER cryptodev_aes_256_cbc = {
- NID_aes_256_cbc,
- 16, 32, 16,
- EVP_CIPH_CBC_MODE,
- cryptodev_init_key,
- cryptodev_cipher,
- cryptodev_cleanup,
- sizeof(struct dev_crypto_state),
- EVP_CIPHER_set_asn1_iv,
- EVP_CIPHER_get_asn1_iv,
- NULL
- };
- /*
- * Registered by the ENGINE when used to find out how to deal with
- * a particular NID in the ENGINE. this says what we'll do at the
- * top level - note, that list is restricted by what we answer with
- */
- static int
- cryptodev_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
- 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;
- 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 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) {
- 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 = 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 == NULL)
- return 0;
- 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 (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 = 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_init: Open session failed\n");
- return (0);
- }
- if (fstate->mac_len != 0) {
- if (fstate->mac_data != NULL) {
- dstate->mac_data = OPENSSL_malloc(fstate->mac_len);
- memcpy(dstate->mac_data, fstate->mac_data, fstate->mac_len);
- dstate->mac_len = fstate->mac_len;
- }
- }
- 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 */
- static int
- cryptodev_engine_digests(ENGINE *e, const EVP_MD **digest,
- const int **nids, int nid)
- {
- if (!digest)
- return (cryptodev_usable_digests(nids));
- switch (nid) {
- # ifdef USE_CRYPTODEV_DIGESTS
- case NID_md5:
- *digest = &cryptodev_md5;
- break;
- case NID_sha1:
- *digest = &cryptodev_sha1;
- break;
- default:
- # endif /* USE_CRYPTODEV_DIGESTS */
- *digest = NULL;
- break;
- }
- return (*digest != NULL);
- }
- /*
- * Convert a BIGNUM to the representation that /dev/crypto needs.
- * Upon completion of use, the caller is responsible for freeing
- * crp->crp_p.
- */
- static int bn2crparam(const BIGNUM *a, struct crparam *crp)
- {
- int i, j, k;
- ssize_t bytes, bits;
- u_char *b;
- crp->crp_p = NULL;
- crp->crp_nbits = 0;
- bits = BN_num_bits(a);
- bytes = (bits + 7) / 8;
- b = malloc(bytes);
- if (b == NULL)
- return (1);
- memset(b, 0, bytes);
- crp->crp_p = (caddr_t) b;
- crp->crp_nbits = bits;
- for (i = 0, j = 0; i < a->top; i++) {
- for (k = 0; k < BN_BITS2 / 8; k++) {
- if ((j + k) >= bytes)
- return (0);
- b[j + k] = a->d[i] >> (k * 8);
- }
- j += BN_BITS2 / 8;
- }
- return (0);
- }
- /* Convert a /dev/crypto parameter to a BIGNUM */
- static int crparam2bn(struct crparam *crp, BIGNUM *a)
- {
- u_int8_t *pd;
- int i, bytes;
- bytes = (crp->crp_nbits + 7) / 8;
- if (bytes == 0)
- return (-1);
- if ((pd = (u_int8_t *) malloc(bytes)) == NULL)
- return (-1);
- for (i = 0; i < bytes; i++)
- pd[i] = crp->crp_p[bytes - i - 1];
- BN_bin2bn(pd, bytes, a);
- free(pd);
- return (0);
- }
- static void zapparams(struct crypt_kop *kop)
- {
- int i;
- for (i = 0; i < kop->crk_iparams + kop->crk_oparams; i++) {
- if (kop->crk_param[i].crp_p)
- free(kop->crk_param[i].crp_p);
- kop->crk_param[i].crp_p = NULL;
- kop->crk_param[i].crp_nbits = 0;
- }
- }
- static int
- cryptodev_asym(struct crypt_kop *kop, int rlen, BIGNUM *r, int slen,
- BIGNUM *s)
- {
- int fd, ret = -1;
- if ((fd = get_asym_dev_crypto()) < 0)
- return (ret);
- if (r) {
- kop->crk_param[kop->crk_iparams].crp_p = calloc(rlen, sizeof(char));
- kop->crk_param[kop->crk_iparams].crp_nbits = rlen * 8;
- kop->crk_oparams++;
- }
- if (s) {
- kop->crk_param[kop->crk_iparams + 1].crp_p =
- calloc(slen, sizeof(char));
- kop->crk_param[kop->crk_iparams + 1].crp_nbits = slen * 8;
- kop->crk_oparams++;
- }
- if (ioctl(fd, CIOCKEY, kop) == 0) {
- if (r)
- crparam2bn(&kop->crk_param[kop->crk_iparams], r);
- if (s)
- crparam2bn(&kop->crk_param[kop->crk_iparams + 1], s);
- ret = 0;
- }
- return (ret);
- }
- static int
- cryptodev_bn_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
- const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont)
- {
- struct crypt_kop kop;
- int ret = 1;
- /*
- * Currently, we know we can do mod exp iff we can do any asymmetric
- * operations at all.
- */
- if (cryptodev_asymfeat == 0) {
- ret = BN_mod_exp(r, a, p, m, ctx);
- return (ret);
- }
- memset(&kop, 0, sizeof kop);
- kop.crk_op = CRK_MOD_EXP;
- /* inputs: a^p % m */
- if (bn2crparam(a, &kop.crk_param[0]))
- goto err;
- if (bn2crparam(p, &kop.crk_param[1]))
- goto err;
- if (bn2crparam(m, &kop.crk_param[2]))
- goto err;
- kop.crk_iparams = 3;
- if (cryptodev_asym(&kop, BN_num_bytes(m), r, 0, NULL)) {
- const RSA_METHOD *meth = RSA_PKCS1_SSLeay();
- printf("OCF asym process failed, Running in software\n");
- ret = meth->bn_mod_exp(r, a, p, m, ctx, in_mont);
- } else if (ECANCELED == kop.crk_status) {
- const RSA_METHOD *meth = RSA_PKCS1_SSLeay();
- printf("OCF hardware operation cancelled. Running in Software\n");
- ret = meth->bn_mod_exp(r, a, p, m, ctx, in_mont);
- }
- /* else cryptodev operation worked ok ==> ret = 1 */
- err:
- zapparams(&kop);
- return (ret);
- }
- static int
- cryptodev_rsa_nocrt_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa,
- BN_CTX *ctx)
- {
- int r;
- ctx = BN_CTX_new();
- r = cryptodev_bn_mod_exp(r0, I, rsa->d, rsa->n, ctx, NULL);
- BN_CTX_free(ctx);
- return (r);
- }
- static int
- cryptodev_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
- {
- struct crypt_kop kop;
- int ret = 1;
- if (!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp) {
- /* XXX 0 means failure?? */
- return (0);
- }
- memset(&kop, 0, sizeof kop);
- kop.crk_op = CRK_MOD_EXP_CRT;
- /* inputs: rsa->p rsa->q I rsa->dmp1 rsa->dmq1 rsa->iqmp */
- if (bn2crparam(rsa->p, &kop.crk_param[0]))
- goto err;
- if (bn2crparam(rsa->q, &kop.crk_param[1]))
- goto err;
- if (bn2crparam(I, &kop.crk_param[2]))
- goto err;
- if (bn2crparam(rsa->dmp1, &kop.crk_param[3]))
- goto err;
- if (bn2crparam(rsa->dmq1, &kop.crk_param[4]))
- goto err;
- if (bn2crparam(rsa->iqmp, &kop.crk_param[5]))
- goto err;
- kop.crk_iparams = 6;
- if (cryptodev_asym(&kop, BN_num_bytes(rsa->n), r0, 0, NULL)) {
- const RSA_METHOD *meth = RSA_PKCS1_SSLeay();
- printf("OCF asym process failed, running in Software\n");
- ret = (*meth->rsa_mod_exp) (r0, I, rsa, ctx);
- } else if (ECANCELED == kop.crk_status) {
- const RSA_METHOD *meth = RSA_PKCS1_SSLeay();
- printf("OCF hardware operation cancelled. Running in Software\n");
- ret = (*meth->rsa_mod_exp) (r0, I, rsa, ctx);
- }
- /* else cryptodev operation worked ok ==> ret = 1 */
- err:
- zapparams(&kop);
- return (ret);
- }
- static RSA_METHOD cryptodev_rsa = {
- "cryptodev RSA method",
- NULL, /* rsa_pub_enc */
- NULL, /* rsa_pub_dec */
- NULL, /* rsa_priv_enc */
- NULL, /* rsa_priv_dec */
- NULL,
- NULL,
- NULL, /* init */
- NULL, /* finish */
- 0, /* flags */
- NULL, /* app_data */
- NULL, /* rsa_sign */
- NULL /* rsa_verify */
- };
- static int
- cryptodev_dsa_bn_mod_exp(DSA *dsa, BIGNUM *r, BIGNUM *a, const BIGNUM *p,
- const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
- {
- return (cryptodev_bn_mod_exp(r, a, p, m, ctx, m_ctx));
- }
- static int
- cryptodev_dsa_dsa_mod_exp(DSA *dsa, BIGNUM *t1, BIGNUM *g,
- BIGNUM *u1, BIGNUM *pub_key, BIGNUM *u2, BIGNUM *p,
- BN_CTX *ctx, BN_MONT_CTX *mont)
- {
- BIGNUM t2;
- int ret = 0;
- BN_init(&t2);
- /* v = ( g^u1 * y^u2 mod p ) mod q */
- /* let t1 = g ^ u1 mod p */
- ret = 0;
- if (!dsa->meth->bn_mod_exp(dsa, t1, dsa->g, u1, dsa->p, ctx, mont))
- goto err;
- /* let t2 = y ^ u2 mod p */
- if (!dsa->meth->bn_mod_exp(dsa, &t2, dsa->pub_key, u2, dsa->p, ctx, mont))
- goto err;
- /* let u1 = t1 * t2 mod p */
- if (!BN_mod_mul(u1, t1, &t2, dsa->p, ctx))
- goto err;
- BN_copy(t1, u1);
- ret = 1;
- err:
- BN_free(&t2);
- return (ret);
- }
- static DSA_SIG *cryptodev_dsa_do_sign(const unsigned char *dgst, int dlen,
- DSA *dsa)
- {
- struct crypt_kop kop;
- BIGNUM *r = NULL, *s = NULL;
- DSA_SIG *dsaret = NULL;
- if ((r = BN_new()) == NULL)
- goto err;
- if ((s = BN_new()) == NULL) {
- BN_free(r);
- goto err;
- }
- memset(&kop, 0, sizeof kop);
- kop.crk_op = CRK_DSA_SIGN;
- /* inputs: dgst dsa->p dsa->q dsa->g dsa->priv_key */
- kop.crk_param[0].crp_p = (caddr_t) dgst;
- kop.crk_param[0].crp_nbits = dlen * 8;
- if (bn2crparam(dsa->p, &kop.crk_param[1]))
- goto err;
- if (bn2crparam(dsa->q, &kop.crk_param[2]))
- goto err;
- if (bn2crparam(dsa->g, &kop.crk_param[3]))
- goto err;
- if (bn2crparam(dsa->priv_key, &kop.crk_param[4]))
- goto err;
- kop.crk_iparams = 5;
- if (cryptodev_asym(&kop, BN_num_bytes(dsa->q), r,
- BN_num_bytes(dsa->q), s) == 0) {
- dsaret = DSA_SIG_new();
- dsaret->r = r;
- dsaret->s = s;
- } else {
- const DSA_METHOD *meth = DSA_OpenSSL();
- BN_free(r);
- BN_free(s);
- dsaret = (meth->dsa_do_sign) (dgst, dlen, dsa);
- }
- err:
- kop.crk_param[0].crp_p = NULL;
- zapparams(&kop);
- return (dsaret);
- }
- static int
- cryptodev_dsa_verify(const unsigned char *dgst, int dlen,
- DSA_SIG *sig, DSA *dsa)
- {
- struct crypt_kop kop;
- int dsaret = 1;
- memset(&kop, 0, sizeof kop);
- kop.crk_op = CRK_DSA_VERIFY;
- /* inputs: dgst dsa->p dsa->q dsa->g dsa->pub_key sig->r sig->s */
- kop.crk_param[0].crp_p = (caddr_t) dgst;
- kop.crk_param[0].crp_nbits = dlen * 8;
- if (bn2crparam(dsa->p, &kop.crk_param[1]))
- goto err;
- if (bn2crparam(dsa->q, &kop.crk_param[2]))
- goto err;
- if (bn2crparam(dsa->g, &kop.crk_param[3]))
- goto err;
- if (bn2crparam(dsa->pub_key, &kop.crk_param[4]))
- goto err;
- if (bn2crparam(sig->r, &kop.crk_param[5]))
- goto err;
- if (bn2crparam(sig->s, &kop.crk_param[6]))
- goto err;
- kop.crk_iparams = 7;
- if (cryptodev_asym(&kop, 0, NULL, 0, NULL) == 0) {
- /*
- * OCF success value is 0, if not zero, change dsaret to fail
- */
- if (0 != kop.crk_status)
- dsaret = 0;
- } else {
- const DSA_METHOD *meth = DSA_OpenSSL();
- dsaret = (meth->dsa_do_verify) (dgst, dlen, sig, dsa);
- }
- err:
- kop.crk_param[0].crp_p = NULL;
- zapparams(&kop);
- return (dsaret);
- }
- static DSA_METHOD cryptodev_dsa = {
- "cryptodev DSA method",
- NULL,
- NULL, /* dsa_sign_setup */
- NULL,
- NULL, /* dsa_mod_exp */
- NULL,
- NULL, /* init */
- NULL, /* finish */
- 0, /* flags */
- NULL /* app_data */
- };
- static int
- cryptodev_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a,
- const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
- BN_MONT_CTX *m_ctx)
- {
- return (cryptodev_bn_mod_exp(r, a, p, m, ctx, m_ctx));
- }
- static int
- cryptodev_dh_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
- {
- struct crypt_kop kop;
- int dhret = 1;
- int fd, keylen;
- if ((fd = get_asym_dev_crypto()) < 0) {
- const DH_METHOD *meth = DH_OpenSSL();
- return ((meth->compute_key) (key, pub_key, dh));
- }
- keylen = BN_num_bits(dh->p);
- memset(&kop, 0, sizeof kop);
- kop.crk_op = CRK_DH_COMPUTE_KEY;
- /* inputs: dh->priv_key pub_key dh->p key */
- if (bn2crparam(dh->priv_key, &kop.crk_param[0]))
- goto err;
- if (bn2crparam(pub_key, &kop.crk_param[1]))
- goto err;
- if (bn2crparam(dh->p, &kop.crk_param[2]))
- goto err;
- kop.crk_iparams = 3;
- kop.crk_param[3].crp_p = (caddr_t) key;
- kop.crk_param[3].crp_nbits = keylen * 8;
- kop.crk_oparams = 1;
- if (ioctl(fd, CIOCKEY, &kop) == -1) {
- const DH_METHOD *meth = DH_OpenSSL();
- dhret = (meth->compute_key) (key, pub_key, dh);
- }
- err:
- kop.crk_param[3].crp_p = NULL;
- zapparams(&kop);
- return (dhret);
- }
- static DH_METHOD cryptodev_dh = {
- "cryptodev DH method",
- NULL, /* cryptodev_dh_generate_key */
- NULL,
- NULL,
- NULL,
- NULL,
- 0, /* flags */
- NULL /* app_data */
- };
- /*
- * ctrl right now is just a wrapper that doesn't do much
- * but I expect we'll want some options soon.
- */
- static int
- cryptodev_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
- {
- # ifdef HAVE_SYSLOG_R
- struct syslog_data sd = SYSLOG_DATA_INIT;
- # endif
- switch (cmd) {
- default:
- # ifdef HAVE_SYSLOG_R
- syslog_r(LOG_ERR, &sd, "cryptodev_ctrl: unknown command %d", cmd);
- # else
- syslog(LOG_ERR, "cryptodev_ctrl: unknown command %d", cmd);
- # endif
- break;
- }
- 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) {
- put_dev_crypto(fd);
- ENGINE_free(engine);
- return;
- }
- put_dev_crypto(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();
- }
- #endif /* HAVE_CRYPTODEV */
|