1160814Ssimon/* 2160814Ssimon * Copyright (c) 2002 Bob Beck <beck@openbsd.org> 3160814Ssimon * Copyright (c) 2002 Theo de Raadt 4160814Ssimon * Copyright (c) 2002 Markus Friedl 5160814Ssimon * All rights reserved. 6160814Ssimon * 7160814Ssimon * Redistribution and use in source and binary forms, with or without 8160814Ssimon * modification, are permitted provided that the following conditions 9160814Ssimon * are met: 10160814Ssimon * 1. Redistributions of source code must retain the above copyright 11160814Ssimon * notice, this list of conditions and the following disclaimer. 12160814Ssimon * 2. Redistributions in binary form must reproduce the above copyright 13160814Ssimon * notice, this list of conditions and the following disclaimer in the 14160814Ssimon * documentation and/or other materials provided with the distribution. 15160814Ssimon * 16160814Ssimon * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY 17160814Ssimon * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18160814Ssimon * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19160814Ssimon * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY 20160814Ssimon * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21160814Ssimon * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22160814Ssimon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23160814Ssimon * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24160814Ssimon * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25160814Ssimon * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26160814Ssimon * 27160814Ssimon */ 28160814Ssimon 29160814Ssimon#include <openssl/objects.h> 30160814Ssimon#include <openssl/engine.h> 31160814Ssimon#include <openssl/evp.h> 32160814Ssimon#include <openssl/bn.h> 33160814Ssimon 34160814Ssimon#if (defined(__unix__) || defined(unix)) && !defined(USG) && \ 35296341Sdelphij (defined(OpenBSD) || defined(__FreeBSD__)) 36296341Sdelphij# include <sys/param.h> 37160814Ssimon# if (OpenBSD >= 200112) || ((__FreeBSD_version >= 470101 && __FreeBSD_version < 500000) || __FreeBSD_version >= 500041) 38160814Ssimon# define HAVE_CRYPTODEV 39160814Ssimon# endif 40160814Ssimon# if (OpenBSD >= 200110) 41160814Ssimon# define HAVE_SYSLOG_R 42160814Ssimon# endif 43160814Ssimon#endif 44160814Ssimon 45160814Ssimon#ifndef HAVE_CRYPTODEV 46160814Ssimon 47296341Sdelphijvoid ENGINE_load_cryptodev(void) 48160814Ssimon{ 49296341Sdelphij /* This is a NOP on platforms without /dev/crypto */ 50296341Sdelphij return; 51160814Ssimon} 52160814Ssimon 53296341Sdelphij#else 54160814Ssimon 55296341Sdelphij# include <sys/types.h> 56296341Sdelphij# include <crypto/cryptodev.h> 57296341Sdelphij# include <crypto/dh/dh.h> 58296341Sdelphij# include <crypto/dsa/dsa.h> 59296341Sdelphij# include <crypto/err/err.h> 60296341Sdelphij# include <crypto/rsa/rsa.h> 61296341Sdelphij# include <sys/ioctl.h> 62296341Sdelphij# include <errno.h> 63296341Sdelphij# include <stdio.h> 64296341Sdelphij# include <unistd.h> 65296341Sdelphij# include <fcntl.h> 66296341Sdelphij# include <stdarg.h> 67296341Sdelphij# include <syslog.h> 68296341Sdelphij# include <errno.h> 69296341Sdelphij# include <string.h> 70296341Sdelphij 71160814Ssimonstruct dev_crypto_state { 72296341Sdelphij struct session_op d_sess; 73296341Sdelphij int d_fd; 74296341Sdelphij# ifdef USE_CRYPTODEV_DIGESTS 75296341Sdelphij char dummy_mac_key[HASH_MAX_LEN]; 76296341Sdelphij unsigned char digest_res[HASH_MAX_LEN]; 77296341Sdelphij char *mac_data; 78296341Sdelphij int mac_len; 79296341Sdelphij# endif 80160814Ssimon}; 81160814Ssimon 82160814Ssimonstatic u_int32_t cryptodev_asymfeat = 0; 83160814Ssimon 84160814Ssimonstatic int get_asym_dev_crypto(void); 85160814Ssimonstatic int open_dev_crypto(void); 86160814Ssimonstatic int get_dev_crypto(void); 87160814Ssimonstatic int get_cryptodev_ciphers(const int **cnids); 88296341Sdelphij# ifdef USE_CRYPTODEV_DIGESTS 89238405Sjkimstatic int get_cryptodev_digests(const int **cnids); 90296341Sdelphij# endif 91160814Ssimonstatic int cryptodev_usable_ciphers(const int **nids); 92160814Ssimonstatic int cryptodev_usable_digests(const int **nids); 93160814Ssimonstatic int cryptodev_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 94296341Sdelphij const unsigned char *in, size_t inl); 95160814Ssimonstatic int cryptodev_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, 96296341Sdelphij const unsigned char *iv, int enc); 97160814Ssimonstatic int cryptodev_cleanup(EVP_CIPHER_CTX *ctx); 98160814Ssimonstatic int cryptodev_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, 99296341Sdelphij const int **nids, int nid); 100160814Ssimonstatic int cryptodev_engine_digests(ENGINE *e, const EVP_MD **digest, 101296341Sdelphij const int **nids, int nid); 102160814Ssimonstatic int bn2crparam(const BIGNUM *a, struct crparam *crp); 103160814Ssimonstatic int crparam2bn(struct crparam *crp, BIGNUM *a); 104160814Ssimonstatic void zapparams(struct crypt_kop *kop); 105160814Ssimonstatic int cryptodev_asym(struct crypt_kop *kop, int rlen, BIGNUM *r, 106296341Sdelphij int slen, BIGNUM *s); 107160814Ssimon 108160814Ssimonstatic int cryptodev_bn_mod_exp(BIGNUM *r, const BIGNUM *a, 109296341Sdelphij const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, 110296341Sdelphij BN_MONT_CTX *m_ctx); 111296341Sdelphijstatic int cryptodev_rsa_nocrt_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, 112296341Sdelphij BN_CTX *ctx); 113296341Sdelphijstatic int cryptodev_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, 114296341Sdelphij BN_CTX *ctx); 115160814Ssimonstatic int cryptodev_dsa_bn_mod_exp(DSA *dsa, BIGNUM *r, BIGNUM *a, 116296341Sdelphij const BIGNUM *p, const BIGNUM *m, 117296341Sdelphij BN_CTX *ctx, BN_MONT_CTX *m_ctx); 118160814Ssimonstatic int cryptodev_dsa_dsa_mod_exp(DSA *dsa, BIGNUM *t1, BIGNUM *g, 119296341Sdelphij BIGNUM *u1, BIGNUM *pub_key, BIGNUM *u2, 120296341Sdelphij BIGNUM *p, BN_CTX *ctx, 121296341Sdelphij BN_MONT_CTX *mont); 122296341Sdelphijstatic DSA_SIG *cryptodev_dsa_do_sign(const unsigned char *dgst, int dlen, 123296341Sdelphij DSA *dsa); 124160814Ssimonstatic int cryptodev_dsa_verify(const unsigned char *dgst, int dgst_len, 125296341Sdelphij DSA_SIG *sig, DSA *dsa); 126160814Ssimonstatic int cryptodev_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a, 127296341Sdelphij const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, 128296341Sdelphij BN_MONT_CTX *m_ctx); 129296341Sdelphijstatic int cryptodev_dh_compute_key(unsigned char *key, const BIGNUM *pub_key, 130296341Sdelphij DH *dh); 131160814Ssimonstatic int cryptodev_ctrl(ENGINE *e, int cmd, long i, void *p, 132296341Sdelphij void (*f) (void)); 133160814Ssimonvoid ENGINE_load_cryptodev(void); 134160814Ssimon 135160814Ssimonstatic const ENGINE_CMD_DEFN cryptodev_defns[] = { 136296341Sdelphij {0, NULL, NULL, 0} 137160814Ssimon}; 138160814Ssimon 139160814Ssimonstatic struct { 140296341Sdelphij int id; 141296341Sdelphij int nid; 142296341Sdelphij int ivmax; 143296341Sdelphij int keylen; 144160814Ssimon} ciphers[] = { 145296341Sdelphij { 146296341Sdelphij CRYPTO_ARC4, NID_rc4, 0, 16, 147296341Sdelphij }, 148296341Sdelphij { 149296341Sdelphij CRYPTO_DES_CBC, NID_des_cbc, 8, 8, 150296341Sdelphij }, 151296341Sdelphij { 152296341Sdelphij CRYPTO_3DES_CBC, NID_des_ede3_cbc, 8, 24, 153296341Sdelphij }, 154296341Sdelphij { 155296341Sdelphij CRYPTO_AES_CBC, NID_aes_128_cbc, 16, 16, 156296341Sdelphij }, 157296341Sdelphij { 158296341Sdelphij CRYPTO_AES_CBC, NID_aes_192_cbc, 16, 24, 159296341Sdelphij }, 160296341Sdelphij { 161296341Sdelphij CRYPTO_AES_CBC, NID_aes_256_cbc, 16, 32, 162296341Sdelphij }, 163296341Sdelphij { 164296341Sdelphij CRYPTO_BLF_CBC, NID_bf_cbc, 8, 16, 165296341Sdelphij }, 166296341Sdelphij { 167296341Sdelphij CRYPTO_CAST_CBC, NID_cast5_cbc, 8, 16, 168296341Sdelphij }, 169296341Sdelphij { 170296341Sdelphij CRYPTO_SKIPJACK_CBC, NID_undef, 0, 0, 171296341Sdelphij }, 172296341Sdelphij { 173296341Sdelphij 0, NID_undef, 0, 0, 174296341Sdelphij }, 175160814Ssimon}; 176160814Ssimon 177296341Sdelphij# ifdef USE_CRYPTODEV_DIGESTS 178160814Ssimonstatic struct { 179296341Sdelphij int id; 180296341Sdelphij int nid; 181296341Sdelphij int keylen; 182160814Ssimon} digests[] = { 183296341Sdelphij { 184296341Sdelphij CRYPTO_MD5_HMAC, NID_hmacWithMD5, 16 185296341Sdelphij }, 186296341Sdelphij { 187296341Sdelphij CRYPTO_SHA1_HMAC, NID_hmacWithSHA1, 20 188296341Sdelphij }, 189296341Sdelphij { 190296341Sdelphij CRYPTO_RIPEMD160_HMAC, NID_ripemd160, 16 191296341Sdelphij /* ? */ 192296341Sdelphij }, 193296341Sdelphij { 194296341Sdelphij CRYPTO_MD5_KPDK, NID_undef, 0 195296341Sdelphij }, 196296341Sdelphij { 197296341Sdelphij CRYPTO_SHA1_KPDK, NID_undef, 0 198296341Sdelphij }, 199296341Sdelphij { 200296341Sdelphij CRYPTO_MD5, NID_md5, 16 201296341Sdelphij }, 202296341Sdelphij { 203296341Sdelphij CRYPTO_SHA1, NID_sha1, 20 204296341Sdelphij }, 205296341Sdelphij { 206296341Sdelphij 0, NID_undef, 0 207296341Sdelphij }, 208160814Ssimon}; 209296341Sdelphij# endif 210160814Ssimon 211160814Ssimon/* 212160814Ssimon * Return a fd if /dev/crypto seems usable, 0 otherwise. 213160814Ssimon */ 214296341Sdelphijstatic int open_dev_crypto(void) 215160814Ssimon{ 216296341Sdelphij static int fd = -1; 217160814Ssimon 218296341Sdelphij if (fd == -1) { 219296341Sdelphij if ((fd = open("/dev/crypto", O_RDWR, 0)) == -1) 220296341Sdelphij return (-1); 221296341Sdelphij /* close on exec */ 222296341Sdelphij if (fcntl(fd, F_SETFD, 1) == -1) { 223296341Sdelphij close(fd); 224296341Sdelphij fd = -1; 225296341Sdelphij return (-1); 226296341Sdelphij } 227296341Sdelphij } 228296341Sdelphij return (fd); 229160814Ssimon} 230160814Ssimon 231296341Sdelphijstatic int get_dev_crypto(void) 232160814Ssimon{ 233296341Sdelphij int fd, retfd; 234160814Ssimon 235296341Sdelphij if ((fd = open_dev_crypto()) == -1) 236296341Sdelphij return (-1); 237296341Sdelphij# ifndef CRIOGET_NOT_NEEDED 238296341Sdelphij if (ioctl(fd, CRIOGET, &retfd) == -1) 239296341Sdelphij return (-1); 240160814Ssimon 241296341Sdelphij /* close on exec */ 242296341Sdelphij if (fcntl(retfd, F_SETFD, 1) == -1) { 243296341Sdelphij close(retfd); 244296341Sdelphij return (-1); 245296341Sdelphij } 246296341Sdelphij# else 247296341Sdelphij retfd = fd; 248296341Sdelphij# endif 249296341Sdelphij return (retfd); 250160814Ssimon} 251160814Ssimon 252238405Sjkimstatic void put_dev_crypto(int fd) 253238405Sjkim{ 254296341Sdelphij# ifndef CRIOGET_NOT_NEEDED 255296341Sdelphij close(fd); 256296341Sdelphij# endif 257238405Sjkim} 258238405Sjkim 259160814Ssimon/* Caching version for asym operations */ 260296341Sdelphijstatic int get_asym_dev_crypto(void) 261160814Ssimon{ 262296341Sdelphij static int fd = -1; 263160814Ssimon 264296341Sdelphij if (fd == -1) 265296341Sdelphij fd = get_dev_crypto(); 266296341Sdelphij return fd; 267160814Ssimon} 268160814Ssimon 269160814Ssimon/* 270160814Ssimon * Find out what ciphers /dev/crypto will let us have a session for. 271160814Ssimon * XXX note, that some of these openssl doesn't deal with yet! 272160814Ssimon * returning them here is harmless, as long as we return NULL 273160814Ssimon * when asked for a handler in the cryptodev_engine_ciphers routine 274160814Ssimon */ 275296341Sdelphijstatic int get_cryptodev_ciphers(const int **cnids) 276160814Ssimon{ 277296341Sdelphij static int nids[CRYPTO_ALGORITHM_MAX]; 278296341Sdelphij struct session_op sess; 279296341Sdelphij int fd, i, count = 0; 280160814Ssimon 281296341Sdelphij if ((fd = get_dev_crypto()) < 0) { 282296341Sdelphij *cnids = NULL; 283296341Sdelphij return (0); 284296341Sdelphij } 285296341Sdelphij memset(&sess, 0, sizeof(sess)); 286296341Sdelphij sess.key = (caddr_t) "123456789abcdefghijklmno"; 287160814Ssimon 288296341Sdelphij for (i = 0; ciphers[i].id && count < CRYPTO_ALGORITHM_MAX; i++) { 289296341Sdelphij if (ciphers[i].nid == NID_undef) 290296341Sdelphij continue; 291296341Sdelphij sess.cipher = ciphers[i].id; 292296341Sdelphij sess.keylen = ciphers[i].keylen; 293296341Sdelphij sess.mac = 0; 294296341Sdelphij if (ioctl(fd, CIOCGSESSION, &sess) != -1 && 295296341Sdelphij ioctl(fd, CIOCFSESSION, &sess.ses) != -1) 296296341Sdelphij nids[count++] = ciphers[i].nid; 297296341Sdelphij } 298296341Sdelphij put_dev_crypto(fd); 299160814Ssimon 300296341Sdelphij if (count > 0) 301296341Sdelphij *cnids = nids; 302296341Sdelphij else 303296341Sdelphij *cnids = NULL; 304296341Sdelphij return (count); 305160814Ssimon} 306160814Ssimon 307296341Sdelphij# ifdef USE_CRYPTODEV_DIGESTS 308160814Ssimon/* 309160814Ssimon * Find out what digests /dev/crypto will let us have a session for. 310160814Ssimon * XXX note, that some of these openssl doesn't deal with yet! 311160814Ssimon * returning them here is harmless, as long as we return NULL 312160814Ssimon * when asked for a handler in the cryptodev_engine_digests routine 313160814Ssimon */ 314296341Sdelphijstatic int get_cryptodev_digests(const int **cnids) 315160814Ssimon{ 316296341Sdelphij static int nids[CRYPTO_ALGORITHM_MAX]; 317296341Sdelphij struct session_op sess; 318296341Sdelphij int fd, i, count = 0; 319160814Ssimon 320296341Sdelphij if ((fd = get_dev_crypto()) < 0) { 321296341Sdelphij *cnids = NULL; 322296341Sdelphij return (0); 323296341Sdelphij } 324296341Sdelphij memset(&sess, 0, sizeof(sess)); 325296341Sdelphij sess.mackey = (caddr_t) "123456789abcdefghijklmno"; 326296341Sdelphij for (i = 0; digests[i].id && count < CRYPTO_ALGORITHM_MAX; i++) { 327296341Sdelphij if (digests[i].nid == NID_undef) 328296341Sdelphij continue; 329296341Sdelphij sess.mac = digests[i].id; 330296341Sdelphij sess.mackeylen = digests[i].keylen; 331296341Sdelphij sess.cipher = 0; 332296341Sdelphij if (ioctl(fd, CIOCGSESSION, &sess) != -1 && 333296341Sdelphij ioctl(fd, CIOCFSESSION, &sess.ses) != -1) 334296341Sdelphij nids[count++] = digests[i].nid; 335296341Sdelphij } 336296341Sdelphij put_dev_crypto(fd); 337160814Ssimon 338296341Sdelphij if (count > 0) 339296341Sdelphij *cnids = nids; 340296341Sdelphij else 341296341Sdelphij *cnids = NULL; 342296341Sdelphij return (count); 343160814Ssimon} 344296341Sdelphij# endif /* 0 */ 345160814Ssimon 346160814Ssimon/* 347160814Ssimon * Find the useable ciphers|digests from dev/crypto - this is the first 348160814Ssimon * thing called by the engine init crud which determines what it 349160814Ssimon * can use for ciphers from this engine. We want to return 350160814Ssimon * only what we can do, anythine else is handled by software. 351160814Ssimon * 352160814Ssimon * If we can't initialize the device to do anything useful for 353160814Ssimon * any reason, we want to return a NULL array, and 0 length, 354160814Ssimon * which forces everything to be done is software. By putting 355160814Ssimon * the initalization of the device in here, we ensure we can 356160814Ssimon * use this engine as the default, and if for whatever reason 357160814Ssimon * /dev/crypto won't do what we want it will just be done in 358160814Ssimon * software 359160814Ssimon * 360160814Ssimon * This can (should) be greatly expanded to perhaps take into 361160814Ssimon * account speed of the device, and what we want to do. 362160814Ssimon * (although the disabling of particular alg's could be controlled 363160814Ssimon * by the device driver with sysctl's.) - this is where we 364160814Ssimon * want most of the decisions made about what we actually want 365160814Ssimon * to use from /dev/crypto. 366160814Ssimon */ 367296341Sdelphijstatic int cryptodev_usable_ciphers(const int **nids) 368160814Ssimon{ 369296341Sdelphij return (get_cryptodev_ciphers(nids)); 370160814Ssimon} 371160814Ssimon 372296341Sdelphijstatic int cryptodev_usable_digests(const int **nids) 373160814Ssimon{ 374296341Sdelphij# ifdef USE_CRYPTODEV_DIGESTS 375296341Sdelphij return (get_cryptodev_digests(nids)); 376296341Sdelphij# else 377296341Sdelphij /* 378296341Sdelphij * XXXX just disable all digests for now, because it sucks. 379296341Sdelphij * we need a better way to decide this - i.e. I may not 380296341Sdelphij * want digests on slow cards like hifn on fast machines, 381296341Sdelphij * but might want them on slow or loaded machines, etc. 382296341Sdelphij * will also want them when using crypto cards that don't 383296341Sdelphij * suck moose gonads - would be nice to be able to decide something 384296341Sdelphij * as reasonable default without having hackery that's card dependent. 385296341Sdelphij * of course, the default should probably be just do everything, 386296341Sdelphij * with perhaps a sysctl to turn algoritms off (or have them off 387296341Sdelphij * by default) on cards that generally suck like the hifn. 388296341Sdelphij */ 389296341Sdelphij *nids = NULL; 390296341Sdelphij return (0); 391296341Sdelphij# endif 392160814Ssimon} 393160814Ssimon 394160814Ssimonstatic int 395160814Ssimoncryptodev_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 396296341Sdelphij const unsigned char *in, size_t inl) 397160814Ssimon{ 398296341Sdelphij struct crypt_op cryp; 399296341Sdelphij struct dev_crypto_state *state = ctx->cipher_data; 400296341Sdelphij struct session_op *sess = &state->d_sess; 401296341Sdelphij const void *iiv; 402296341Sdelphij unsigned char save_iv[EVP_MAX_IV_LENGTH]; 403160814Ssimon 404296341Sdelphij if (state->d_fd < 0) 405296341Sdelphij return (0); 406296341Sdelphij if (!inl) 407296341Sdelphij return (1); 408296341Sdelphij if ((inl % ctx->cipher->block_size) != 0) 409296341Sdelphij return (0); 410160814Ssimon 411296341Sdelphij memset(&cryp, 0, sizeof(cryp)); 412160814Ssimon 413296341Sdelphij cryp.ses = sess->ses; 414296341Sdelphij cryp.flags = 0; 415296341Sdelphij cryp.len = inl; 416296341Sdelphij cryp.src = (caddr_t) in; 417296341Sdelphij cryp.dst = (caddr_t) out; 418296341Sdelphij cryp.mac = 0; 419160814Ssimon 420296341Sdelphij cryp.op = ctx->encrypt ? COP_ENCRYPT : COP_DECRYPT; 421160814Ssimon 422296341Sdelphij if (ctx->cipher->iv_len) { 423296341Sdelphij cryp.iv = (caddr_t) ctx->iv; 424296341Sdelphij if (!ctx->encrypt) { 425296341Sdelphij iiv = in + inl - ctx->cipher->iv_len; 426296341Sdelphij memcpy(save_iv, iiv, ctx->cipher->iv_len); 427296341Sdelphij } 428296341Sdelphij } else 429296341Sdelphij cryp.iv = NULL; 430160814Ssimon 431296341Sdelphij if (ioctl(state->d_fd, CIOCCRYPT, &cryp) == -1) { 432296341Sdelphij /* 433296341Sdelphij * XXX need better errror handling this can fail for a number of 434296341Sdelphij * different reasons. 435296341Sdelphij */ 436296341Sdelphij return (0); 437296341Sdelphij } 438160814Ssimon 439296341Sdelphij if (ctx->cipher->iv_len) { 440296341Sdelphij if (ctx->encrypt) 441296341Sdelphij iiv = out + inl - ctx->cipher->iv_len; 442296341Sdelphij else 443296341Sdelphij iiv = save_iv; 444296341Sdelphij memcpy(ctx->iv, iiv, ctx->cipher->iv_len); 445296341Sdelphij } 446296341Sdelphij return (1); 447160814Ssimon} 448160814Ssimon 449160814Ssimonstatic int 450160814Ssimoncryptodev_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, 451296341Sdelphij const unsigned char *iv, int enc) 452160814Ssimon{ 453296341Sdelphij struct dev_crypto_state *state = ctx->cipher_data; 454296341Sdelphij struct session_op *sess = &state->d_sess; 455296341Sdelphij int cipher = -1, i; 456160814Ssimon 457296341Sdelphij for (i = 0; ciphers[i].id; i++) 458296341Sdelphij if (ctx->cipher->nid == ciphers[i].nid && 459296341Sdelphij ctx->cipher->iv_len <= ciphers[i].ivmax && 460296341Sdelphij ctx->key_len == ciphers[i].keylen) { 461296341Sdelphij cipher = ciphers[i].id; 462296341Sdelphij break; 463296341Sdelphij } 464160814Ssimon 465296341Sdelphij if (!ciphers[i].id) { 466296341Sdelphij state->d_fd = -1; 467296341Sdelphij return (0); 468296341Sdelphij } 469160814Ssimon 470296341Sdelphij memset(sess, 0, sizeof(struct session_op)); 471160814Ssimon 472296341Sdelphij if ((state->d_fd = get_dev_crypto()) < 0) 473296341Sdelphij return (0); 474160814Ssimon 475296341Sdelphij sess->key = (caddr_t) key; 476296341Sdelphij sess->keylen = ctx->key_len; 477296341Sdelphij sess->cipher = cipher; 478160814Ssimon 479296341Sdelphij if (ioctl(state->d_fd, CIOCGSESSION, sess) == -1) { 480296341Sdelphij put_dev_crypto(state->d_fd); 481296341Sdelphij state->d_fd = -1; 482296341Sdelphij return (0); 483296341Sdelphij } 484296341Sdelphij return (1); 485160814Ssimon} 486160814Ssimon 487160814Ssimon/* 488160814Ssimon * free anything we allocated earlier when initting a 489160814Ssimon * session, and close the session. 490160814Ssimon */ 491296341Sdelphijstatic int cryptodev_cleanup(EVP_CIPHER_CTX *ctx) 492160814Ssimon{ 493296341Sdelphij int ret = 0; 494296341Sdelphij struct dev_crypto_state *state = ctx->cipher_data; 495296341Sdelphij struct session_op *sess = &state->d_sess; 496160814Ssimon 497296341Sdelphij if (state->d_fd < 0) 498296341Sdelphij return (0); 499160814Ssimon 500296341Sdelphij /* 501296341Sdelphij * XXX if this ioctl fails, someting's wrong. the invoker may have called 502296341Sdelphij * us with a bogus ctx, or we could have a device that for whatever 503296341Sdelphij * reason just doesn't want to play ball - it's not clear what's right 504296341Sdelphij * here - should this be an error? should it just increase a counter, 505296341Sdelphij * hmm. For right now, we return 0 - I don't believe that to be "right". 506296341Sdelphij * we could call the gorpy openssl lib error handlers that print messages 507296341Sdelphij * to users of the library. hmm.. 508296341Sdelphij */ 509160814Ssimon 510296341Sdelphij if (ioctl(state->d_fd, CIOCFSESSION, &sess->ses) == -1) { 511296341Sdelphij ret = 0; 512296341Sdelphij } else { 513296341Sdelphij ret = 1; 514296341Sdelphij } 515296341Sdelphij put_dev_crypto(state->d_fd); 516296341Sdelphij state->d_fd = -1; 517160814Ssimon 518296341Sdelphij return (ret); 519160814Ssimon} 520160814Ssimon 521160814Ssimon/* 522160814Ssimon * libcrypto EVP stuff - this is how we get wired to EVP so the engine 523160814Ssimon * gets called when libcrypto requests a cipher NID. 524160814Ssimon */ 525160814Ssimon 526238405Sjkim/* RC4 */ 527238405Sjkimconst EVP_CIPHER cryptodev_rc4 = { 528296341Sdelphij NID_rc4, 529296341Sdelphij 1, 16, 0, 530296341Sdelphij EVP_CIPH_VARIABLE_LENGTH, 531296341Sdelphij cryptodev_init_key, 532296341Sdelphij cryptodev_cipher, 533296341Sdelphij cryptodev_cleanup, 534296341Sdelphij sizeof(struct dev_crypto_state), 535296341Sdelphij NULL, 536296341Sdelphij NULL, 537296341Sdelphij NULL 538238405Sjkim}; 539238405Sjkim 540160814Ssimon/* DES CBC EVP */ 541160814Ssimonconst EVP_CIPHER cryptodev_des_cbc = { 542296341Sdelphij NID_des_cbc, 543296341Sdelphij 8, 8, 8, 544296341Sdelphij EVP_CIPH_CBC_MODE, 545296341Sdelphij cryptodev_init_key, 546296341Sdelphij cryptodev_cipher, 547296341Sdelphij cryptodev_cleanup, 548296341Sdelphij sizeof(struct dev_crypto_state), 549296341Sdelphij EVP_CIPHER_set_asn1_iv, 550296341Sdelphij EVP_CIPHER_get_asn1_iv, 551296341Sdelphij NULL 552160814Ssimon}; 553160814Ssimon 554160814Ssimon/* 3DES CBC EVP */ 555160814Ssimonconst EVP_CIPHER cryptodev_3des_cbc = { 556296341Sdelphij NID_des_ede3_cbc, 557296341Sdelphij 8, 24, 8, 558296341Sdelphij EVP_CIPH_CBC_MODE, 559296341Sdelphij cryptodev_init_key, 560296341Sdelphij cryptodev_cipher, 561296341Sdelphij cryptodev_cleanup, 562296341Sdelphij sizeof(struct dev_crypto_state), 563296341Sdelphij EVP_CIPHER_set_asn1_iv, 564296341Sdelphij EVP_CIPHER_get_asn1_iv, 565296341Sdelphij NULL 566160814Ssimon}; 567160814Ssimon 568160814Ssimonconst EVP_CIPHER cryptodev_bf_cbc = { 569296341Sdelphij NID_bf_cbc, 570296341Sdelphij 8, 16, 8, 571296341Sdelphij EVP_CIPH_CBC_MODE, 572296341Sdelphij cryptodev_init_key, 573296341Sdelphij cryptodev_cipher, 574296341Sdelphij cryptodev_cleanup, 575296341Sdelphij sizeof(struct dev_crypto_state), 576296341Sdelphij EVP_CIPHER_set_asn1_iv, 577296341Sdelphij EVP_CIPHER_get_asn1_iv, 578296341Sdelphij NULL 579160814Ssimon}; 580160814Ssimon 581160814Ssimonconst EVP_CIPHER cryptodev_cast_cbc = { 582296341Sdelphij NID_cast5_cbc, 583296341Sdelphij 8, 16, 8, 584296341Sdelphij EVP_CIPH_CBC_MODE, 585296341Sdelphij cryptodev_init_key, 586296341Sdelphij cryptodev_cipher, 587296341Sdelphij cryptodev_cleanup, 588296341Sdelphij sizeof(struct dev_crypto_state), 589296341Sdelphij EVP_CIPHER_set_asn1_iv, 590296341Sdelphij EVP_CIPHER_get_asn1_iv, 591296341Sdelphij NULL 592160814Ssimon}; 593160814Ssimon 594160814Ssimonconst EVP_CIPHER cryptodev_aes_cbc = { 595296341Sdelphij NID_aes_128_cbc, 596296341Sdelphij 16, 16, 16, 597296341Sdelphij EVP_CIPH_CBC_MODE, 598296341Sdelphij cryptodev_init_key, 599296341Sdelphij cryptodev_cipher, 600296341Sdelphij cryptodev_cleanup, 601296341Sdelphij sizeof(struct dev_crypto_state), 602296341Sdelphij EVP_CIPHER_set_asn1_iv, 603296341Sdelphij EVP_CIPHER_get_asn1_iv, 604296341Sdelphij NULL 605160814Ssimon}; 606160814Ssimon 607238405Sjkimconst EVP_CIPHER cryptodev_aes_192_cbc = { 608296341Sdelphij NID_aes_192_cbc, 609296341Sdelphij 16, 24, 16, 610296341Sdelphij EVP_CIPH_CBC_MODE, 611296341Sdelphij cryptodev_init_key, 612296341Sdelphij cryptodev_cipher, 613296341Sdelphij cryptodev_cleanup, 614296341Sdelphij sizeof(struct dev_crypto_state), 615296341Sdelphij EVP_CIPHER_set_asn1_iv, 616296341Sdelphij EVP_CIPHER_get_asn1_iv, 617296341Sdelphij NULL 618238405Sjkim}; 619238405Sjkim 620238405Sjkimconst EVP_CIPHER cryptodev_aes_256_cbc = { 621296341Sdelphij NID_aes_256_cbc, 622296341Sdelphij 16, 32, 16, 623296341Sdelphij EVP_CIPH_CBC_MODE, 624296341Sdelphij cryptodev_init_key, 625296341Sdelphij cryptodev_cipher, 626296341Sdelphij cryptodev_cleanup, 627296341Sdelphij sizeof(struct dev_crypto_state), 628296341Sdelphij EVP_CIPHER_set_asn1_iv, 629296341Sdelphij EVP_CIPHER_get_asn1_iv, 630296341Sdelphij NULL 631238405Sjkim}; 632238405Sjkim 633160814Ssimon/* 634160814Ssimon * Registered by the ENGINE when used to find out how to deal with 635160814Ssimon * a particular NID in the ENGINE. this says what we'll do at the 636160814Ssimon * top level - note, that list is restricted by what we answer with 637160814Ssimon */ 638160814Ssimonstatic int 639160814Ssimoncryptodev_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, 640296341Sdelphij const int **nids, int nid) 641160814Ssimon{ 642296341Sdelphij if (!cipher) 643296341Sdelphij return (cryptodev_usable_ciphers(nids)); 644160814Ssimon 645296341Sdelphij switch (nid) { 646296341Sdelphij case NID_rc4: 647296341Sdelphij *cipher = &cryptodev_rc4; 648296341Sdelphij break; 649296341Sdelphij case NID_des_ede3_cbc: 650296341Sdelphij *cipher = &cryptodev_3des_cbc; 651296341Sdelphij break; 652296341Sdelphij case NID_des_cbc: 653296341Sdelphij *cipher = &cryptodev_des_cbc; 654296341Sdelphij break; 655296341Sdelphij case NID_bf_cbc: 656296341Sdelphij *cipher = &cryptodev_bf_cbc; 657296341Sdelphij break; 658296341Sdelphij case NID_cast5_cbc: 659296341Sdelphij *cipher = &cryptodev_cast_cbc; 660296341Sdelphij break; 661296341Sdelphij case NID_aes_128_cbc: 662296341Sdelphij *cipher = &cryptodev_aes_cbc; 663296341Sdelphij break; 664296341Sdelphij case NID_aes_192_cbc: 665296341Sdelphij *cipher = &cryptodev_aes_192_cbc; 666296341Sdelphij break; 667296341Sdelphij case NID_aes_256_cbc: 668296341Sdelphij *cipher = &cryptodev_aes_256_cbc; 669296341Sdelphij break; 670296341Sdelphij default: 671296341Sdelphij *cipher = NULL; 672296341Sdelphij break; 673296341Sdelphij } 674296341Sdelphij return (*cipher != NULL); 675160814Ssimon} 676160814Ssimon 677296341Sdelphij# ifdef USE_CRYPTODEV_DIGESTS 678238405Sjkim 679238405Sjkim/* convert digest type to cryptodev */ 680296341Sdelphijstatic int digest_nid_to_cryptodev(int nid) 681238405Sjkim{ 682296341Sdelphij int i; 683238405Sjkim 684296341Sdelphij for (i = 0; digests[i].id; i++) 685296341Sdelphij if (digests[i].nid == nid) 686296341Sdelphij return (digests[i].id); 687296341Sdelphij return (0); 688238405Sjkim} 689238405Sjkim 690296341Sdelphijstatic int digest_key_length(int nid) 691238405Sjkim{ 692296341Sdelphij int i; 693238405Sjkim 694296341Sdelphij for (i = 0; digests[i].id; i++) 695296341Sdelphij if (digests[i].nid == nid) 696296341Sdelphij return digests[i].keylen; 697296341Sdelphij return (0); 698238405Sjkim} 699238405Sjkim 700238405Sjkimstatic int cryptodev_digest_init(EVP_MD_CTX *ctx) 701238405Sjkim{ 702296341Sdelphij struct dev_crypto_state *state = ctx->md_data; 703296341Sdelphij struct session_op *sess = &state->d_sess; 704296341Sdelphij int digest; 705238405Sjkim 706296341Sdelphij if ((digest = digest_nid_to_cryptodev(ctx->digest->type)) == NID_undef) { 707296341Sdelphij printf("cryptodev_digest_init: Can't get digest \n"); 708296341Sdelphij return (0); 709296341Sdelphij } 710238405Sjkim 711296341Sdelphij memset(state, 0, sizeof(struct dev_crypto_state)); 712238405Sjkim 713296341Sdelphij if ((state->d_fd = get_dev_crypto()) < 0) { 714296341Sdelphij printf("cryptodev_digest_init: Can't get Dev \n"); 715296341Sdelphij return (0); 716296341Sdelphij } 717238405Sjkim 718296341Sdelphij sess->mackey = state->dummy_mac_key; 719296341Sdelphij sess->mackeylen = digest_key_length(ctx->digest->type); 720296341Sdelphij sess->mac = digest; 721238405Sjkim 722296341Sdelphij if (ioctl(state->d_fd, CIOCGSESSION, sess) < 0) { 723296341Sdelphij put_dev_crypto(state->d_fd); 724296341Sdelphij state->d_fd = -1; 725296341Sdelphij printf("cryptodev_digest_init: Open session failed\n"); 726296341Sdelphij return (0); 727296341Sdelphij } 728238405Sjkim 729296341Sdelphij return (1); 730238405Sjkim} 731238405Sjkim 732238405Sjkimstatic int cryptodev_digest_update(EVP_MD_CTX *ctx, const void *data, 733296341Sdelphij size_t count) 734238405Sjkim{ 735296341Sdelphij struct crypt_op cryp; 736296341Sdelphij struct dev_crypto_state *state = ctx->md_data; 737296341Sdelphij struct session_op *sess = &state->d_sess; 738238405Sjkim 739296341Sdelphij if (!data || state->d_fd < 0) { 740296341Sdelphij printf("cryptodev_digest_update: illegal inputs \n"); 741296341Sdelphij return (0); 742296341Sdelphij } 743238405Sjkim 744296341Sdelphij if (!count) { 745296341Sdelphij return (0); 746296341Sdelphij } 747238405Sjkim 748296341Sdelphij if (!(ctx->flags & EVP_MD_CTX_FLAG_ONESHOT)) { 749296341Sdelphij /* if application doesn't support one buffer */ 750296341Sdelphij state->mac_data = 751296341Sdelphij OPENSSL_realloc(state->mac_data, state->mac_len + count); 752238405Sjkim 753296341Sdelphij if (!state->mac_data) { 754296341Sdelphij printf("cryptodev_digest_update: realloc failed\n"); 755296341Sdelphij return (0); 756296341Sdelphij } 757238405Sjkim 758296341Sdelphij memcpy(state->mac_data + state->mac_len, data, count); 759296341Sdelphij state->mac_len += count; 760238405Sjkim 761296341Sdelphij return (1); 762296341Sdelphij } 763238405Sjkim 764296341Sdelphij memset(&cryp, 0, sizeof(cryp)); 765296341Sdelphij 766296341Sdelphij cryp.ses = sess->ses; 767296341Sdelphij cryp.flags = 0; 768296341Sdelphij cryp.len = count; 769296341Sdelphij cryp.src = (caddr_t) data; 770296341Sdelphij cryp.dst = NULL; 771296341Sdelphij cryp.mac = (caddr_t) state->digest_res; 772296341Sdelphij if (ioctl(state->d_fd, CIOCCRYPT, &cryp) < 0) { 773296341Sdelphij printf("cryptodev_digest_update: digest failed\n"); 774296341Sdelphij return (0); 775296341Sdelphij } 776296341Sdelphij return (1); 777238405Sjkim} 778238405Sjkim 779238405Sjkimstatic int cryptodev_digest_final(EVP_MD_CTX *ctx, unsigned char *md) 780238405Sjkim{ 781296341Sdelphij struct crypt_op cryp; 782296341Sdelphij struct dev_crypto_state *state = ctx->md_data; 783296341Sdelphij struct session_op *sess = &state->d_sess; 784238405Sjkim 785296341Sdelphij int ret = 1; 786238405Sjkim 787296341Sdelphij if (!md || state->d_fd < 0) { 788296341Sdelphij printf("cryptodev_digest_final: illegal input\n"); 789296341Sdelphij return (0); 790296341Sdelphij } 791238405Sjkim 792296341Sdelphij if (!(ctx->flags & EVP_MD_CTX_FLAG_ONESHOT)) { 793296341Sdelphij /* if application doesn't support one buffer */ 794296341Sdelphij memset(&cryp, 0, sizeof(cryp)); 795296341Sdelphij cryp.ses = sess->ses; 796296341Sdelphij cryp.flags = 0; 797296341Sdelphij cryp.len = state->mac_len; 798296341Sdelphij cryp.src = state->mac_data; 799296341Sdelphij cryp.dst = NULL; 800296341Sdelphij cryp.mac = (caddr_t) md; 801296341Sdelphij if (ioctl(state->d_fd, CIOCCRYPT, &cryp) < 0) { 802296341Sdelphij printf("cryptodev_digest_final: digest failed\n"); 803296341Sdelphij return (0); 804296341Sdelphij } 805238405Sjkim 806296341Sdelphij return 1; 807296341Sdelphij } 808238405Sjkim 809296341Sdelphij memcpy(md, state->digest_res, ctx->digest->md_size); 810238405Sjkim 811296341Sdelphij return (ret); 812238405Sjkim} 813238405Sjkim 814238405Sjkimstatic int cryptodev_digest_cleanup(EVP_MD_CTX *ctx) 815238405Sjkim{ 816296341Sdelphij int ret = 1; 817296341Sdelphij struct dev_crypto_state *state = ctx->md_data; 818296341Sdelphij struct session_op *sess = &state->d_sess; 819238405Sjkim 820296341Sdelphij if (state == NULL) 821296341Sdelphij return 0; 822238405Sjkim 823296341Sdelphij if (state->d_fd < 0) { 824296341Sdelphij printf("cryptodev_digest_cleanup: illegal input\n"); 825296341Sdelphij return (0); 826296341Sdelphij } 827238405Sjkim 828296341Sdelphij if (state->mac_data) { 829296341Sdelphij OPENSSL_free(state->mac_data); 830296341Sdelphij state->mac_data = NULL; 831296341Sdelphij state->mac_len = 0; 832296341Sdelphij } 833238405Sjkim 834296341Sdelphij if (ioctl(state->d_fd, CIOCFSESSION, &sess->ses) < 0) { 835296341Sdelphij printf("cryptodev_digest_cleanup: failed to close session\n"); 836296341Sdelphij ret = 0; 837296341Sdelphij } else { 838296341Sdelphij ret = 1; 839296341Sdelphij } 840296341Sdelphij put_dev_crypto(state->d_fd); 841296341Sdelphij state->d_fd = -1; 842238405Sjkim 843296341Sdelphij return (ret); 844238405Sjkim} 845238405Sjkim 846296341Sdelphijstatic int cryptodev_digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from) 847238405Sjkim{ 848296341Sdelphij struct dev_crypto_state *fstate = from->md_data; 849296341Sdelphij struct dev_crypto_state *dstate = to->md_data; 850296341Sdelphij struct session_op *sess; 851296341Sdelphij int digest; 852238405Sjkim 853296341Sdelphij if (dstate == NULL || fstate == NULL) 854296341Sdelphij return 1; 855238405Sjkim 856296341Sdelphij memcpy(dstate, fstate, sizeof(struct dev_crypto_state)); 857238405Sjkim 858296341Sdelphij sess = &dstate->d_sess; 859238405Sjkim 860296341Sdelphij digest = digest_nid_to_cryptodev(to->digest->type); 861238405Sjkim 862296341Sdelphij sess->mackey = dstate->dummy_mac_key; 863296341Sdelphij sess->mackeylen = digest_key_length(to->digest->type); 864296341Sdelphij sess->mac = digest; 865238405Sjkim 866296341Sdelphij dstate->d_fd = get_dev_crypto(); 867238405Sjkim 868296341Sdelphij if (ioctl(dstate->d_fd, CIOCGSESSION, sess) < 0) { 869296341Sdelphij put_dev_crypto(dstate->d_fd); 870296341Sdelphij dstate->d_fd = -1; 871296341Sdelphij printf("cryptodev_digest_init: Open session failed\n"); 872296341Sdelphij return (0); 873296341Sdelphij } 874238405Sjkim 875296341Sdelphij if (fstate->mac_len != 0) { 876296341Sdelphij if (fstate->mac_data != NULL) { 877296341Sdelphij dstate->mac_data = OPENSSL_malloc(fstate->mac_len); 878296341Sdelphij memcpy(dstate->mac_data, fstate->mac_data, fstate->mac_len); 879296341Sdelphij dstate->mac_len = fstate->mac_len; 880296341Sdelphij } 881296341Sdelphij } 882238405Sjkim 883296341Sdelphij return 1; 884238405Sjkim} 885238405Sjkim 886238405Sjkimconst EVP_MD cryptodev_sha1 = { 887296341Sdelphij NID_sha1, 888296341Sdelphij NID_undef, 889296341Sdelphij SHA_DIGEST_LENGTH, 890296341Sdelphij EVP_MD_FLAG_ONESHOT, 891296341Sdelphij cryptodev_digest_init, 892296341Sdelphij cryptodev_digest_update, 893296341Sdelphij cryptodev_digest_final, 894296341Sdelphij cryptodev_digest_copy, 895296341Sdelphij cryptodev_digest_cleanup, 896296341Sdelphij EVP_PKEY_NULL_method, 897296341Sdelphij SHA_CBLOCK, 898296341Sdelphij sizeof(struct dev_crypto_state), 899238405Sjkim}; 900238405Sjkim 901238405Sjkimconst EVP_MD cryptodev_md5 = { 902296341Sdelphij NID_md5, 903296341Sdelphij NID_undef, 904296341Sdelphij 16 /* MD5_DIGEST_LENGTH */ , 905296341Sdelphij EVP_MD_FLAG_ONESHOT, 906296341Sdelphij cryptodev_digest_init, 907296341Sdelphij cryptodev_digest_update, 908296341Sdelphij cryptodev_digest_final, 909296341Sdelphij cryptodev_digest_copy, 910296341Sdelphij cryptodev_digest_cleanup, 911296341Sdelphij EVP_PKEY_NULL_method, 912296341Sdelphij 64 /* MD5_CBLOCK */ , 913296341Sdelphij sizeof(struct dev_crypto_state), 914238405Sjkim}; 915238405Sjkim 916296341Sdelphij# endif /* USE_CRYPTODEV_DIGESTS */ 917238405Sjkim 918238405Sjkimstatic int 919160814Ssimoncryptodev_engine_digests(ENGINE *e, const EVP_MD **digest, 920296341Sdelphij const int **nids, int nid) 921160814Ssimon{ 922296341Sdelphij if (!digest) 923296341Sdelphij return (cryptodev_usable_digests(nids)); 924160814Ssimon 925296341Sdelphij switch (nid) { 926296341Sdelphij# ifdef USE_CRYPTODEV_DIGESTS 927296341Sdelphij case NID_md5: 928296341Sdelphij *digest = &cryptodev_md5; 929296341Sdelphij break; 930296341Sdelphij case NID_sha1: 931296341Sdelphij *digest = &cryptodev_sha1; 932296341Sdelphij break; 933296341Sdelphij default: 934296341Sdelphij# endif /* USE_CRYPTODEV_DIGESTS */ 935296341Sdelphij *digest = NULL; 936296341Sdelphij break; 937296341Sdelphij } 938296341Sdelphij return (*digest != NULL); 939160814Ssimon} 940160814Ssimon 941160814Ssimon/* 942160814Ssimon * Convert a BIGNUM to the representation that /dev/crypto needs. 943160814Ssimon * Upon completion of use, the caller is responsible for freeing 944160814Ssimon * crp->crp_p. 945160814Ssimon */ 946296341Sdelphijstatic int bn2crparam(const BIGNUM *a, struct crparam *crp) 947160814Ssimon{ 948296341Sdelphij int i, j, k; 949296341Sdelphij ssize_t bytes, bits; 950296341Sdelphij u_char *b; 951160814Ssimon 952296341Sdelphij crp->crp_p = NULL; 953296341Sdelphij crp->crp_nbits = 0; 954160814Ssimon 955296341Sdelphij bits = BN_num_bits(a); 956296341Sdelphij bytes = (bits + 7) / 8; 957160814Ssimon 958296341Sdelphij b = malloc(bytes); 959296341Sdelphij if (b == NULL) 960296341Sdelphij return (1); 961296341Sdelphij memset(b, 0, bytes); 962160814Ssimon 963296341Sdelphij crp->crp_p = (caddr_t) b; 964296341Sdelphij crp->crp_nbits = bits; 965160814Ssimon 966296341Sdelphij for (i = 0, j = 0; i < a->top; i++) { 967296341Sdelphij for (k = 0; k < BN_BITS2 / 8; k++) { 968296341Sdelphij if ((j + k) >= bytes) 969296341Sdelphij return (0); 970296341Sdelphij b[j + k] = a->d[i] >> (k * 8); 971296341Sdelphij } 972296341Sdelphij j += BN_BITS2 / 8; 973296341Sdelphij } 974296341Sdelphij return (0); 975160814Ssimon} 976160814Ssimon 977160814Ssimon/* Convert a /dev/crypto parameter to a BIGNUM */ 978296341Sdelphijstatic int crparam2bn(struct crparam *crp, BIGNUM *a) 979160814Ssimon{ 980296341Sdelphij u_int8_t *pd; 981296341Sdelphij int i, bytes; 982160814Ssimon 983296341Sdelphij bytes = (crp->crp_nbits + 7) / 8; 984160814Ssimon 985296341Sdelphij if (bytes == 0) 986296341Sdelphij return (-1); 987160814Ssimon 988296341Sdelphij if ((pd = (u_int8_t *) malloc(bytes)) == NULL) 989296341Sdelphij return (-1); 990160814Ssimon 991296341Sdelphij for (i = 0; i < bytes; i++) 992296341Sdelphij pd[i] = crp->crp_p[bytes - i - 1]; 993160814Ssimon 994296341Sdelphij BN_bin2bn(pd, bytes, a); 995296341Sdelphij free(pd); 996160814Ssimon 997296341Sdelphij return (0); 998160814Ssimon} 999160814Ssimon 1000296341Sdelphijstatic void zapparams(struct crypt_kop *kop) 1001160814Ssimon{ 1002296341Sdelphij int i; 1003160814Ssimon 1004296341Sdelphij for (i = 0; i < kop->crk_iparams + kop->crk_oparams; i++) { 1005296341Sdelphij if (kop->crk_param[i].crp_p) 1006296341Sdelphij free(kop->crk_param[i].crp_p); 1007296341Sdelphij kop->crk_param[i].crp_p = NULL; 1008296341Sdelphij kop->crk_param[i].crp_nbits = 0; 1009296341Sdelphij } 1010160814Ssimon} 1011160814Ssimon 1012160814Ssimonstatic int 1013296341Sdelphijcryptodev_asym(struct crypt_kop *kop, int rlen, BIGNUM *r, int slen, 1014296341Sdelphij BIGNUM *s) 1015160814Ssimon{ 1016296341Sdelphij int fd, ret = -1; 1017160814Ssimon 1018296341Sdelphij if ((fd = get_asym_dev_crypto()) < 0) 1019296341Sdelphij return (ret); 1020160814Ssimon 1021296341Sdelphij if (r) { 1022296341Sdelphij kop->crk_param[kop->crk_iparams].crp_p = calloc(rlen, sizeof(char)); 1023296341Sdelphij kop->crk_param[kop->crk_iparams].crp_nbits = rlen * 8; 1024296341Sdelphij kop->crk_oparams++; 1025296341Sdelphij } 1026296341Sdelphij if (s) { 1027296341Sdelphij kop->crk_param[kop->crk_iparams + 1].crp_p = 1028296341Sdelphij calloc(slen, sizeof(char)); 1029296341Sdelphij kop->crk_param[kop->crk_iparams + 1].crp_nbits = slen * 8; 1030296341Sdelphij kop->crk_oparams++; 1031296341Sdelphij } 1032160814Ssimon 1033296341Sdelphij if (ioctl(fd, CIOCKEY, kop) == 0) { 1034296341Sdelphij if (r) 1035296341Sdelphij crparam2bn(&kop->crk_param[kop->crk_iparams], r); 1036296341Sdelphij if (s) 1037296341Sdelphij crparam2bn(&kop->crk_param[kop->crk_iparams + 1], s); 1038296341Sdelphij ret = 0; 1039296341Sdelphij } 1040160814Ssimon 1041296341Sdelphij return (ret); 1042160814Ssimon} 1043160814Ssimon 1044160814Ssimonstatic int 1045160814Ssimoncryptodev_bn_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, 1046296341Sdelphij const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont) 1047160814Ssimon{ 1048296341Sdelphij struct crypt_kop kop; 1049296341Sdelphij int ret = 1; 1050160814Ssimon 1051296341Sdelphij /* 1052296341Sdelphij * Currently, we know we can do mod exp iff we can do any asymmetric 1053296341Sdelphij * operations at all. 1054296341Sdelphij */ 1055296341Sdelphij if (cryptodev_asymfeat == 0) { 1056296341Sdelphij ret = BN_mod_exp(r, a, p, m, ctx); 1057296341Sdelphij return (ret); 1058296341Sdelphij } 1059160814Ssimon 1060296341Sdelphij memset(&kop, 0, sizeof kop); 1061296341Sdelphij kop.crk_op = CRK_MOD_EXP; 1062160814Ssimon 1063296341Sdelphij /* inputs: a^p % m */ 1064296341Sdelphij if (bn2crparam(a, &kop.crk_param[0])) 1065296341Sdelphij goto err; 1066296341Sdelphij if (bn2crparam(p, &kop.crk_param[1])) 1067296341Sdelphij goto err; 1068296341Sdelphij if (bn2crparam(m, &kop.crk_param[2])) 1069296341Sdelphij goto err; 1070296341Sdelphij kop.crk_iparams = 3; 1071160814Ssimon 1072296341Sdelphij if (cryptodev_asym(&kop, BN_num_bytes(m), r, 0, NULL)) { 1073296341Sdelphij const RSA_METHOD *meth = RSA_PKCS1_SSLeay(); 1074296341Sdelphij printf("OCF asym process failed, Running in software\n"); 1075296341Sdelphij ret = meth->bn_mod_exp(r, a, p, m, ctx, in_mont); 1076206046Ssimon 1077296341Sdelphij } else if (ECANCELED == kop.crk_status) { 1078296341Sdelphij const RSA_METHOD *meth = RSA_PKCS1_SSLeay(); 1079296341Sdelphij printf("OCF hardware operation cancelled. Running in Software\n"); 1080296341Sdelphij ret = meth->bn_mod_exp(r, a, p, m, ctx, in_mont); 1081296341Sdelphij } 1082296341Sdelphij /* else cryptodev operation worked ok ==> ret = 1 */ 1083206046Ssimon 1084296341Sdelphij err: 1085296341Sdelphij zapparams(&kop); 1086296341Sdelphij return (ret); 1087160814Ssimon} 1088160814Ssimon 1089160814Ssimonstatic int 1090296341Sdelphijcryptodev_rsa_nocrt_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, 1091296341Sdelphij BN_CTX *ctx) 1092160814Ssimon{ 1093296341Sdelphij int r; 1094296341Sdelphij ctx = BN_CTX_new(); 1095296341Sdelphij r = cryptodev_bn_mod_exp(r0, I, rsa->d, rsa->n, ctx, NULL); 1096296341Sdelphij BN_CTX_free(ctx); 1097296341Sdelphij return (r); 1098160814Ssimon} 1099160814Ssimon 1100160814Ssimonstatic int 1101160814Ssimoncryptodev_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) 1102160814Ssimon{ 1103296341Sdelphij struct crypt_kop kop; 1104296341Sdelphij int ret = 1; 1105160814Ssimon 1106296341Sdelphij if (!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp) { 1107296341Sdelphij /* XXX 0 means failure?? */ 1108296341Sdelphij return (0); 1109296341Sdelphij } 1110160814Ssimon 1111296341Sdelphij memset(&kop, 0, sizeof kop); 1112296341Sdelphij kop.crk_op = CRK_MOD_EXP_CRT; 1113296341Sdelphij /* inputs: rsa->p rsa->q I rsa->dmp1 rsa->dmq1 rsa->iqmp */ 1114296341Sdelphij if (bn2crparam(rsa->p, &kop.crk_param[0])) 1115296341Sdelphij goto err; 1116296341Sdelphij if (bn2crparam(rsa->q, &kop.crk_param[1])) 1117296341Sdelphij goto err; 1118296341Sdelphij if (bn2crparam(I, &kop.crk_param[2])) 1119296341Sdelphij goto err; 1120296341Sdelphij if (bn2crparam(rsa->dmp1, &kop.crk_param[3])) 1121296341Sdelphij goto err; 1122296341Sdelphij if (bn2crparam(rsa->dmq1, &kop.crk_param[4])) 1123296341Sdelphij goto err; 1124296341Sdelphij if (bn2crparam(rsa->iqmp, &kop.crk_param[5])) 1125296341Sdelphij goto err; 1126296341Sdelphij kop.crk_iparams = 6; 1127160814Ssimon 1128296341Sdelphij if (cryptodev_asym(&kop, BN_num_bytes(rsa->n), r0, 0, NULL)) { 1129296341Sdelphij const RSA_METHOD *meth = RSA_PKCS1_SSLeay(); 1130296341Sdelphij printf("OCF asym process failed, running in Software\n"); 1131296341Sdelphij ret = (*meth->rsa_mod_exp) (r0, I, rsa, ctx); 1132206046Ssimon 1133296341Sdelphij } else if (ECANCELED == kop.crk_status) { 1134296341Sdelphij const RSA_METHOD *meth = RSA_PKCS1_SSLeay(); 1135296341Sdelphij printf("OCF hardware operation cancelled. Running in Software\n"); 1136296341Sdelphij ret = (*meth->rsa_mod_exp) (r0, I, rsa, ctx); 1137296341Sdelphij } 1138296341Sdelphij /* else cryptodev operation worked ok ==> ret = 1 */ 1139206046Ssimon 1140296341Sdelphij err: 1141296341Sdelphij zapparams(&kop); 1142296341Sdelphij return (ret); 1143160814Ssimon} 1144160814Ssimon 1145160814Ssimonstatic RSA_METHOD cryptodev_rsa = { 1146296341Sdelphij "cryptodev RSA method", 1147296341Sdelphij NULL, /* rsa_pub_enc */ 1148296341Sdelphij NULL, /* rsa_pub_dec */ 1149296341Sdelphij NULL, /* rsa_priv_enc */ 1150296341Sdelphij NULL, /* rsa_priv_dec */ 1151296341Sdelphij NULL, 1152296341Sdelphij NULL, 1153296341Sdelphij NULL, /* init */ 1154296341Sdelphij NULL, /* finish */ 1155296341Sdelphij 0, /* flags */ 1156296341Sdelphij NULL, /* app_data */ 1157296341Sdelphij NULL, /* rsa_sign */ 1158296341Sdelphij NULL /* rsa_verify */ 1159160814Ssimon}; 1160160814Ssimon 1161160814Ssimonstatic int 1162160814Ssimoncryptodev_dsa_bn_mod_exp(DSA *dsa, BIGNUM *r, BIGNUM *a, const BIGNUM *p, 1163296341Sdelphij const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) 1164160814Ssimon{ 1165296341Sdelphij return (cryptodev_bn_mod_exp(r, a, p, m, ctx, m_ctx)); 1166160814Ssimon} 1167160814Ssimon 1168160814Ssimonstatic int 1169160814Ssimoncryptodev_dsa_dsa_mod_exp(DSA *dsa, BIGNUM *t1, BIGNUM *g, 1170296341Sdelphij BIGNUM *u1, BIGNUM *pub_key, BIGNUM *u2, BIGNUM *p, 1171296341Sdelphij BN_CTX *ctx, BN_MONT_CTX *mont) 1172160814Ssimon{ 1173296341Sdelphij BIGNUM t2; 1174296341Sdelphij int ret = 0; 1175160814Ssimon 1176296341Sdelphij BN_init(&t2); 1177160814Ssimon 1178296341Sdelphij /* v = ( g^u1 * y^u2 mod p ) mod q */ 1179296341Sdelphij /* let t1 = g ^ u1 mod p */ 1180296341Sdelphij ret = 0; 1181160814Ssimon 1182296341Sdelphij if (!dsa->meth->bn_mod_exp(dsa, t1, dsa->g, u1, dsa->p, ctx, mont)) 1183296341Sdelphij goto err; 1184160814Ssimon 1185296341Sdelphij /* let t2 = y ^ u2 mod p */ 1186296341Sdelphij if (!dsa->meth->bn_mod_exp(dsa, &t2, dsa->pub_key, u2, dsa->p, ctx, mont)) 1187296341Sdelphij goto err; 1188296341Sdelphij /* let u1 = t1 * t2 mod p */ 1189296341Sdelphij if (!BN_mod_mul(u1, t1, &t2, dsa->p, ctx)) 1190296341Sdelphij goto err; 1191160814Ssimon 1192296341Sdelphij BN_copy(t1, u1); 1193160814Ssimon 1194296341Sdelphij ret = 1; 1195296341Sdelphij err: 1196296341Sdelphij BN_free(&t2); 1197296341Sdelphij return (ret); 1198160814Ssimon} 1199160814Ssimon 1200296341Sdelphijstatic DSA_SIG *cryptodev_dsa_do_sign(const unsigned char *dgst, int dlen, 1201296341Sdelphij DSA *dsa) 1202160814Ssimon{ 1203296341Sdelphij struct crypt_kop kop; 1204296341Sdelphij BIGNUM *r = NULL, *s = NULL; 1205296341Sdelphij DSA_SIG *dsaret = NULL; 1206160814Ssimon 1207296341Sdelphij if ((r = BN_new()) == NULL) 1208296341Sdelphij goto err; 1209296341Sdelphij if ((s = BN_new()) == NULL) { 1210296341Sdelphij BN_free(r); 1211296341Sdelphij goto err; 1212296341Sdelphij } 1213160814Ssimon 1214296341Sdelphij memset(&kop, 0, sizeof kop); 1215296341Sdelphij kop.crk_op = CRK_DSA_SIGN; 1216160814Ssimon 1217296341Sdelphij /* inputs: dgst dsa->p dsa->q dsa->g dsa->priv_key */ 1218296341Sdelphij kop.crk_param[0].crp_p = (caddr_t) dgst; 1219296341Sdelphij kop.crk_param[0].crp_nbits = dlen * 8; 1220296341Sdelphij if (bn2crparam(dsa->p, &kop.crk_param[1])) 1221296341Sdelphij goto err; 1222296341Sdelphij if (bn2crparam(dsa->q, &kop.crk_param[2])) 1223296341Sdelphij goto err; 1224296341Sdelphij if (bn2crparam(dsa->g, &kop.crk_param[3])) 1225296341Sdelphij goto err; 1226296341Sdelphij if (bn2crparam(dsa->priv_key, &kop.crk_param[4])) 1227296341Sdelphij goto err; 1228296341Sdelphij kop.crk_iparams = 5; 1229160814Ssimon 1230296341Sdelphij if (cryptodev_asym(&kop, BN_num_bytes(dsa->q), r, 1231296341Sdelphij BN_num_bytes(dsa->q), s) == 0) { 1232296341Sdelphij dsaret = DSA_SIG_new(); 1233296341Sdelphij dsaret->r = r; 1234296341Sdelphij dsaret->s = s; 1235296341Sdelphij } else { 1236296341Sdelphij const DSA_METHOD *meth = DSA_OpenSSL(); 1237296341Sdelphij BN_free(r); 1238296341Sdelphij BN_free(s); 1239296341Sdelphij dsaret = (meth->dsa_do_sign) (dgst, dlen, dsa); 1240296341Sdelphij } 1241296341Sdelphij err: 1242296341Sdelphij kop.crk_param[0].crp_p = NULL; 1243296341Sdelphij zapparams(&kop); 1244296341Sdelphij return (dsaret); 1245160814Ssimon} 1246160814Ssimon 1247160814Ssimonstatic int 1248160814Ssimoncryptodev_dsa_verify(const unsigned char *dgst, int dlen, 1249296341Sdelphij DSA_SIG *sig, DSA *dsa) 1250160814Ssimon{ 1251296341Sdelphij struct crypt_kop kop; 1252296341Sdelphij int dsaret = 1; 1253160814Ssimon 1254296341Sdelphij memset(&kop, 0, sizeof kop); 1255296341Sdelphij kop.crk_op = CRK_DSA_VERIFY; 1256160814Ssimon 1257296341Sdelphij /* inputs: dgst dsa->p dsa->q dsa->g dsa->pub_key sig->r sig->s */ 1258296341Sdelphij kop.crk_param[0].crp_p = (caddr_t) dgst; 1259296341Sdelphij kop.crk_param[0].crp_nbits = dlen * 8; 1260296341Sdelphij if (bn2crparam(dsa->p, &kop.crk_param[1])) 1261296341Sdelphij goto err; 1262296341Sdelphij if (bn2crparam(dsa->q, &kop.crk_param[2])) 1263296341Sdelphij goto err; 1264296341Sdelphij if (bn2crparam(dsa->g, &kop.crk_param[3])) 1265296341Sdelphij goto err; 1266296341Sdelphij if (bn2crparam(dsa->pub_key, &kop.crk_param[4])) 1267296341Sdelphij goto err; 1268296341Sdelphij if (bn2crparam(sig->r, &kop.crk_param[5])) 1269296341Sdelphij goto err; 1270296341Sdelphij if (bn2crparam(sig->s, &kop.crk_param[6])) 1271296341Sdelphij goto err; 1272296341Sdelphij kop.crk_iparams = 7; 1273160814Ssimon 1274296341Sdelphij if (cryptodev_asym(&kop, 0, NULL, 0, NULL) == 0) { 1275296341Sdelphij /* 1276296341Sdelphij * OCF success value is 0, if not zero, change dsaret to fail 1277296341Sdelphij */ 1278296341Sdelphij if (0 != kop.crk_status) 1279296341Sdelphij dsaret = 0; 1280296341Sdelphij } else { 1281296341Sdelphij const DSA_METHOD *meth = DSA_OpenSSL(); 1282160814Ssimon 1283296341Sdelphij dsaret = (meth->dsa_do_verify) (dgst, dlen, sig, dsa); 1284296341Sdelphij } 1285296341Sdelphij err: 1286296341Sdelphij kop.crk_param[0].crp_p = NULL; 1287296341Sdelphij zapparams(&kop); 1288296341Sdelphij return (dsaret); 1289160814Ssimon} 1290160814Ssimon 1291160814Ssimonstatic DSA_METHOD cryptodev_dsa = { 1292296341Sdelphij "cryptodev DSA method", 1293296341Sdelphij NULL, 1294296341Sdelphij NULL, /* dsa_sign_setup */ 1295296341Sdelphij NULL, 1296296341Sdelphij NULL, /* dsa_mod_exp */ 1297296341Sdelphij NULL, 1298296341Sdelphij NULL, /* init */ 1299296341Sdelphij NULL, /* finish */ 1300296341Sdelphij 0, /* flags */ 1301296341Sdelphij NULL /* app_data */ 1302160814Ssimon}; 1303160814Ssimon 1304160814Ssimonstatic int 1305160814Ssimoncryptodev_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a, 1306296341Sdelphij const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, 1307296341Sdelphij BN_MONT_CTX *m_ctx) 1308160814Ssimon{ 1309296341Sdelphij return (cryptodev_bn_mod_exp(r, a, p, m, ctx, m_ctx)); 1310160814Ssimon} 1311160814Ssimon 1312160814Ssimonstatic int 1313160814Ssimoncryptodev_dh_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh) 1314160814Ssimon{ 1315296341Sdelphij struct crypt_kop kop; 1316296341Sdelphij int dhret = 1; 1317296341Sdelphij int fd, keylen; 1318160814Ssimon 1319296341Sdelphij if ((fd = get_asym_dev_crypto()) < 0) { 1320296341Sdelphij const DH_METHOD *meth = DH_OpenSSL(); 1321160814Ssimon 1322296341Sdelphij return ((meth->compute_key) (key, pub_key, dh)); 1323296341Sdelphij } 1324160814Ssimon 1325296341Sdelphij keylen = BN_num_bits(dh->p); 1326160814Ssimon 1327296341Sdelphij memset(&kop, 0, sizeof kop); 1328296341Sdelphij kop.crk_op = CRK_DH_COMPUTE_KEY; 1329160814Ssimon 1330296341Sdelphij /* inputs: dh->priv_key pub_key dh->p key */ 1331296341Sdelphij if (bn2crparam(dh->priv_key, &kop.crk_param[0])) 1332296341Sdelphij goto err; 1333296341Sdelphij if (bn2crparam(pub_key, &kop.crk_param[1])) 1334296341Sdelphij goto err; 1335296341Sdelphij if (bn2crparam(dh->p, &kop.crk_param[2])) 1336296341Sdelphij goto err; 1337296341Sdelphij kop.crk_iparams = 3; 1338160814Ssimon 1339296341Sdelphij kop.crk_param[3].crp_p = (caddr_t) key; 1340296341Sdelphij kop.crk_param[3].crp_nbits = keylen * 8; 1341296341Sdelphij kop.crk_oparams = 1; 1342160814Ssimon 1343296341Sdelphij if (ioctl(fd, CIOCKEY, &kop) == -1) { 1344296341Sdelphij const DH_METHOD *meth = DH_OpenSSL(); 1345160814Ssimon 1346296341Sdelphij dhret = (meth->compute_key) (key, pub_key, dh); 1347296341Sdelphij } 1348296341Sdelphij err: 1349296341Sdelphij kop.crk_param[3].crp_p = NULL; 1350296341Sdelphij zapparams(&kop); 1351296341Sdelphij return (dhret); 1352160814Ssimon} 1353160814Ssimon 1354160814Ssimonstatic DH_METHOD cryptodev_dh = { 1355296341Sdelphij "cryptodev DH method", 1356296341Sdelphij NULL, /* cryptodev_dh_generate_key */ 1357296341Sdelphij NULL, 1358296341Sdelphij NULL, 1359296341Sdelphij NULL, 1360296341Sdelphij NULL, 1361296341Sdelphij 0, /* flags */ 1362296341Sdelphij NULL /* app_data */ 1363160814Ssimon}; 1364160814Ssimon 1365160814Ssimon/* 1366160814Ssimon * ctrl right now is just a wrapper that doesn't do much 1367160814Ssimon * but I expect we'll want some options soon. 1368160814Ssimon */ 1369160814Ssimonstatic int 1370296341Sdelphijcryptodev_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void)) 1371160814Ssimon{ 1372296341Sdelphij# ifdef HAVE_SYSLOG_R 1373296341Sdelphij struct syslog_data sd = SYSLOG_DATA_INIT; 1374296341Sdelphij# endif 1375160814Ssimon 1376296341Sdelphij switch (cmd) { 1377296341Sdelphij default: 1378296341Sdelphij# ifdef HAVE_SYSLOG_R 1379296341Sdelphij syslog_r(LOG_ERR, &sd, "cryptodev_ctrl: unknown command %d", cmd); 1380296341Sdelphij# else 1381296341Sdelphij syslog(LOG_ERR, "cryptodev_ctrl: unknown command %d", cmd); 1382296341Sdelphij# endif 1383296341Sdelphij break; 1384296341Sdelphij } 1385296341Sdelphij return (1); 1386160814Ssimon} 1387160814Ssimon 1388296341Sdelphijvoid ENGINE_load_cryptodev(void) 1389160814Ssimon{ 1390296341Sdelphij ENGINE *engine = ENGINE_new(); 1391296341Sdelphij int fd; 1392160814Ssimon 1393296341Sdelphij if (engine == NULL) 1394296341Sdelphij return; 1395296341Sdelphij if ((fd = get_dev_crypto()) < 0) { 1396296341Sdelphij ENGINE_free(engine); 1397296341Sdelphij return; 1398296341Sdelphij } 1399160814Ssimon 1400296341Sdelphij /* 1401296341Sdelphij * find out what asymmetric crypto algorithms we support 1402296341Sdelphij */ 1403296341Sdelphij if (ioctl(fd, CIOCASYMFEAT, &cryptodev_asymfeat) == -1) { 1404296341Sdelphij put_dev_crypto(fd); 1405296341Sdelphij ENGINE_free(engine); 1406296341Sdelphij return; 1407296341Sdelphij } 1408296341Sdelphij put_dev_crypto(fd); 1409160814Ssimon 1410296341Sdelphij if (!ENGINE_set_id(engine, "cryptodev") || 1411296341Sdelphij !ENGINE_set_name(engine, "BSD cryptodev engine") || 1412296341Sdelphij !ENGINE_set_ciphers(engine, cryptodev_engine_ciphers) || 1413296341Sdelphij !ENGINE_set_digests(engine, cryptodev_engine_digests) || 1414296341Sdelphij !ENGINE_set_ctrl_function(engine, cryptodev_ctrl) || 1415296341Sdelphij !ENGINE_set_cmd_defns(engine, cryptodev_defns)) { 1416296341Sdelphij ENGINE_free(engine); 1417296341Sdelphij return; 1418296341Sdelphij } 1419160814Ssimon 1420296341Sdelphij if (ENGINE_set_RSA(engine, &cryptodev_rsa)) { 1421296341Sdelphij const RSA_METHOD *rsa_meth = RSA_PKCS1_SSLeay(); 1422160814Ssimon 1423296341Sdelphij cryptodev_rsa.bn_mod_exp = rsa_meth->bn_mod_exp; 1424296341Sdelphij cryptodev_rsa.rsa_mod_exp = rsa_meth->rsa_mod_exp; 1425296341Sdelphij cryptodev_rsa.rsa_pub_enc = rsa_meth->rsa_pub_enc; 1426296341Sdelphij cryptodev_rsa.rsa_pub_dec = rsa_meth->rsa_pub_dec; 1427296341Sdelphij cryptodev_rsa.rsa_priv_enc = rsa_meth->rsa_priv_enc; 1428296341Sdelphij cryptodev_rsa.rsa_priv_dec = rsa_meth->rsa_priv_dec; 1429296341Sdelphij if (cryptodev_asymfeat & CRF_MOD_EXP) { 1430296341Sdelphij cryptodev_rsa.bn_mod_exp = cryptodev_bn_mod_exp; 1431296341Sdelphij if (cryptodev_asymfeat & CRF_MOD_EXP_CRT) 1432296341Sdelphij cryptodev_rsa.rsa_mod_exp = cryptodev_rsa_mod_exp; 1433296341Sdelphij else 1434296341Sdelphij cryptodev_rsa.rsa_mod_exp = cryptodev_rsa_nocrt_mod_exp; 1435296341Sdelphij } 1436296341Sdelphij } 1437160814Ssimon 1438296341Sdelphij if (ENGINE_set_DSA(engine, &cryptodev_dsa)) { 1439296341Sdelphij const DSA_METHOD *meth = DSA_OpenSSL(); 1440160814Ssimon 1441296341Sdelphij memcpy(&cryptodev_dsa, meth, sizeof(DSA_METHOD)); 1442296341Sdelphij if (cryptodev_asymfeat & CRF_DSA_SIGN) 1443296341Sdelphij cryptodev_dsa.dsa_do_sign = cryptodev_dsa_do_sign; 1444296341Sdelphij if (cryptodev_asymfeat & CRF_MOD_EXP) { 1445296341Sdelphij cryptodev_dsa.bn_mod_exp = cryptodev_dsa_bn_mod_exp; 1446296341Sdelphij cryptodev_dsa.dsa_mod_exp = cryptodev_dsa_dsa_mod_exp; 1447296341Sdelphij } 1448296341Sdelphij if (cryptodev_asymfeat & CRF_DSA_VERIFY) 1449296341Sdelphij cryptodev_dsa.dsa_do_verify = cryptodev_dsa_verify; 1450296341Sdelphij } 1451160814Ssimon 1452296341Sdelphij if (ENGINE_set_DH(engine, &cryptodev_dh)) { 1453296341Sdelphij const DH_METHOD *dh_meth = DH_OpenSSL(); 1454160814Ssimon 1455296341Sdelphij cryptodev_dh.generate_key = dh_meth->generate_key; 1456296341Sdelphij cryptodev_dh.compute_key = dh_meth->compute_key; 1457296341Sdelphij cryptodev_dh.bn_mod_exp = dh_meth->bn_mod_exp; 1458296341Sdelphij if (cryptodev_asymfeat & CRF_MOD_EXP) { 1459296341Sdelphij cryptodev_dh.bn_mod_exp = cryptodev_mod_exp_dh; 1460296341Sdelphij if (cryptodev_asymfeat & CRF_DH_COMPUTE_KEY) 1461296341Sdelphij cryptodev_dh.compute_key = cryptodev_dh_compute_key; 1462296341Sdelphij } 1463296341Sdelphij } 1464160814Ssimon 1465296341Sdelphij ENGINE_add(engine); 1466296341Sdelphij ENGINE_free(engine); 1467296341Sdelphij ERR_clear_error(); 1468160814Ssimon} 1469160814Ssimon 1470296341Sdelphij#endif /* HAVE_CRYPTODEV */ 1471