From 9cea7b85baecb1a02a3ea617de73d9693a9792eb Mon Sep 17 00:00:00 2001 From: markus <> Date: Sun, 11 May 2003 21:36:59 +0000 Subject: import 0.9.7b (without idea and rc5) --- src/lib/libcrypto/engine/hw_cryptodev.c | 540 ++++++++++++++++++++++---------- 1 file changed, 373 insertions(+), 167 deletions(-) (limited to 'src/lib/libcrypto/engine/hw_cryptodev.c') diff --git a/src/lib/libcrypto/engine/hw_cryptodev.c b/src/lib/libcrypto/engine/hw_cryptodev.c index 7c3728f395..40af97ac24 100644 --- a/src/lib/libcrypto/engine/hw_cryptodev.c +++ b/src/lib/libcrypto/engine/hw_cryptodev.c @@ -1,6 +1,7 @@ /* * Copyright (c) 2002 Bob Beck * 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 @@ -28,33 +29,85 @@ * */ -#include +#include +#include +#include + +#if (defined(__unix__) || defined(unix)) && !defined(USG) #include +# 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 #include #include #include #include #include #include -#include #include -#include -#include -#include +#include +#include +#include -static int cryptodev_fd = -1; -static int cryptodev_sessions = 0; -static u_int32_t cryptodev_symfeat = 0; +struct dev_crypto_state { + struct session_op d_sess; + int d_fd; +}; +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 cryptodev_max_iv(int cipher); +static int cryptodev_key_length_valid(int cipher, int len); +static int cipher_nid_to_cryptodev(int nid); +static int get_cryptodev_ciphers(const int **cnids); +static int get_cryptodev_digests(const int **cnids); +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, unsigned int 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_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa); 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); +static int cryptodev_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa); 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, @@ -64,6 +117,9 @@ static int cryptodev_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a, 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 ENGINE_load_cryptodev(void); static const ENGINE_CMD_DEFN cryptodev_defns[] = { { 0, NULL, NULL, 0 } @@ -77,11 +133,10 @@ static struct { } ciphers[] = { { CRYPTO_DES_CBC, NID_des_cbc, 8, 8, }, { CRYPTO_3DES_CBC, NID_des_ede3_cbc, 8, 24, }, - { CRYPTO_AES_CBC, NID_undef, 8, 24, }, + { CRYPTO_AES_CBC, NID_aes_128_cbc, 16, 16, }, { CRYPTO_BLF_CBC, NID_bf_cbc, 8, 16, }, - { CRYPTO_CAST_CBC, NID_cast5_cbc, 8, 8, }, + { CRYPTO_CAST_CBC, NID_cast5_cbc, 8, 16, }, { CRYPTO_SKIPJACK_CBC, NID_undef, 0, 0, }, - { CRYPTO_ARC4, NID_rc4, 8, 16, }, { 0, NID_undef, 0, 0, }, }; @@ -99,33 +154,53 @@ static struct { }; /* - * Return 1 if /dev/crypto seems usable, 0 otherwise , also - * does most of the work of initting the device, if not already - * done.. This should leave is with global fd initialized with CRIOGET. + * Return a fd if /dev/crypto seems usable, 0 otherwise. */ static int -check_dev_crypto() +open_dev_crypto(void) { - int fd; + static int fd = -1; - if (cryptodev_fd == -1) { + if (fd == -1) { if ((fd = open("/dev/crypto", O_RDWR, 0)) == -1) - return (0); - if (ioctl(fd, CRIOGET, &cryptodev_fd) == -1) { - close(fd); - return (0); - } - close(fd); + return (-1); /* close on exec */ - if (fcntl(cryptodev_fd, F_SETFD, 1) == -1) { - close(cryptodev_fd); - cryptodev_fd = -1; - return (0); + if (fcntl(fd, F_SETFD, 1) == -1) { + close(fd); + fd = -1; + return (-1); } } - ioctl(cryptodev_fd, CIOCSYMFEAT, &cryptodev_symfeat); + return (fd); +} - return (1); +static int +get_dev_crypto(void) +{ + int fd, retfd; + + if ((fd = open_dev_crypto()) == -1) + return (-1); + if (ioctl(fd, CRIOGET, &retfd) == -1) + return (-1); + + /* close on exec */ + if (fcntl(retfd, F_SETFD, 1) == -1) { + close(retfd); + return (-1); + } + return (retfd); +} + +/* 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; } /* @@ -183,8 +258,12 @@ get_cryptodev_ciphers(const int **cnids) { static int nids[CRYPTO_ALGORITHM_MAX]; struct session_op sess; - int i, count = 0; + int fd, i, count = 0; + if ((fd = get_dev_crypto()) < 0) { + *nids = NULL; + return (0); + } memset(&sess, 0, sizeof(sess)); sess.key = (caddr_t)"123456781234567812345678"; @@ -194,10 +273,12 @@ get_cryptodev_ciphers(const int **cnids) sess.cipher = ciphers[i].id; sess.keylen = ciphers[i].keylen; sess.mac = 0; - if (ioctl(cryptodev_fd, CIOCGSESSION, &sess) != -1 && - ioctl(cryptodev_fd, CIOCFSESSION, &sess.ses) != -1) + if (ioctl(fd, CIOCGSESSION, &sess) != -1 && + ioctl(fd, CIOCFSESSION, &sess.ses) != -1) nids[count++] = ciphers[i].nid; } + close(fd); + if (count > 0) *cnids = nids; else @@ -216,18 +297,24 @@ get_cryptodev_digests(const int **cnids) { static int nids[CRYPTO_ALGORITHM_MAX]; struct session_op sess; - int i, count = 0; + int fd, i, count = 0; + if ((fd = get_dev_crypto()) < 0) { + *nids = NULL; + return (0); + } memset(&sess, 0, sizeof(sess)); for (i = 0; digests[i].id && count < CRYPTO_ALGORITHM_MAX; i++) { if (digests[i].nid == NID_undef) continue; sess.mac = digests[i].id; sess.cipher = 0; - if (ioctl(cryptodev_fd, CIOCGSESSION, &sess) != -1 && - ioctl(cryptodev_fd, CIOCFSESSION, &sess.ses) != -1) + if (ioctl(fd, CIOCGSESSION, &sess) != -1 && + ioctl(fd, CIOCFSESSION, &sess.ses) != -1) nids[count++] = digests[i].nid; } + close(fd); + if (count > 0) *cnids = nids; else @@ -256,25 +343,15 @@ get_cryptodev_digests(const int **cnids) * want most of the decisions made about what we actually want * to use from /dev/crypto. */ -int +static int cryptodev_usable_ciphers(const int **nids) { - if (!check_dev_crypto()) { - *nids = NULL; - return (0); - } - - /* find what the device can do. Unfortunately, we don't - * necessarily want all of these yet, because we aren't - * yet set up to do them - */ return (get_cryptodev_ciphers(nids)); } -int +static int cryptodev_usable_digests(const int **nids) { -#if 1 /* * XXXX just disable all digests for now, because it sucks. * we need a better way to decide this - i.e. I may not @@ -289,29 +366,19 @@ cryptodev_usable_digests(const int **nids) */ *nids = NULL; return (0); -#endif - - if (!check_dev_crypto()) { - *nids = NULL; - return (0); - } - return (get_cryptodev_digests(nids)); } - -int +static int cryptodev_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl) { struct crypt_op cryp; - struct session_op *sess = ctx->cipher_data; + struct dev_crypto_state *state = ctx->cipher_data; + struct session_op *sess = &state->d_sess; void *iiv; unsigned char save_iv[EVP_MAX_IV_LENGTH]; - struct syslog_data sd = SYSLOG_DATA_INIT; - if (cryptodev_fd == -1) - return (0); - if (sess == NULL) + if (state->d_fd < 0) return (0); if (!inl) return (1); @@ -338,11 +405,10 @@ cryptodev_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, } else cryp.iv = NULL; - if (ioctl(cryptodev_fd, CIOCCRYPT, &cryp) == -1) { + if (ioctl(state->d_fd, CIOCCRYPT, &cryp) == -1) { /* XXX need better errror handling * this can fail for a number of different reasons. */ - syslog_r(LOG_ERR, &sd, "CIOCCRYPT failed (%m)"); return (0); } @@ -356,20 +422,17 @@ cryptodev_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, return (1); } -int +static int cryptodev_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { - struct session_op *sess = ctx->cipher_data; - struct syslog_data sd = SYSLOG_DATA_INIT; + struct dev_crypto_state *state = ctx->cipher_data; + struct session_op *sess = &state->d_sess; int cipher; if ((cipher = cipher_nid_to_cryptodev(ctx->cipher->nid)) == NID_undef) return (0); - if (!check_dev_crypto()) - return (0); - if (ctx->cipher->iv_len > cryptodev_max_iv(cipher)) return (0); @@ -378,15 +441,18 @@ cryptodev_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, memset(sess, 0, sizeof(struct session_op)); + if ((state->d_fd = get_dev_crypto()) < 0) + return (0); + sess->key = (unsigned char *)key; sess->keylen = ctx->key_len; sess->cipher = cipher; - if (ioctl(cryptodev_fd, CIOCGSESSION, sess) == -1) { - syslog_r(LOG_ERR, &sd, "CIOCGSESSION failed (%m)"); + if (ioctl(state->d_fd, CIOCGSESSION, sess) == -1) { + close(state->d_fd); + state->d_fd = -1; return (0); } - cryptodev_sessions++; return (1); } @@ -394,14 +460,14 @@ cryptodev_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, * free anything we allocated earlier when initting a * session, and close the session. */ -int +static int cryptodev_cleanup(EVP_CIPHER_CTX *ctx) { int ret = 0; - struct session_op *sess = ctx->cipher_data; - struct syslog_data sd = SYSLOG_DATA_INIT; + struct dev_crypto_state *state = ctx->cipher_data; + struct session_op *sess = &state->d_sess; - if (sess == NULL) + if (state->d_fd < 0) return (0); /* XXX if this ioctl fails, someting's wrong. the invoker @@ -415,17 +481,14 @@ cryptodev_cleanup(EVP_CIPHER_CTX *ctx) * print messages to users of the library. hmm.. */ - if (ioctl(cryptodev_fd, CIOCFSESSION, &sess->ses) == -1) { - syslog_r(LOG_ERR, &sd, "CIOCFSESSION failed (%m)"); + if (ioctl(state->d_fd, CIOCFSESSION, &sess->ses) == -1) { ret = 0; } else { - cryptodev_sessions--; ret = 1; } - if (cryptodev_sessions == 0 && cryptodev_fd != -1 ) { - close(cryptodev_fd); /* XXX should this be closed? */ - cryptodev_fd = -1; - } + close(state->d_fd); + state->d_fd = -1; + return (ret); } @@ -434,20 +497,6 @@ cryptodev_cleanup(EVP_CIPHER_CTX *ctx) * gets called when libcrypto requests a cipher NID. */ -/* ARC4 (16 byte key) */ -const EVP_CIPHER cryptodev_arc4_cipher = { - NID_rc4, - 1, 16, 0, - EVP_CIPH_VARIABLE_LENGTH, - cryptodev_init_key, - cryptodev_cipher, - cryptodev_cleanup, - sizeof(struct session_op), - NULL, - NULL, - NULL -}; - /* DES CBC EVP */ const EVP_CIPHER cryptodev_des_cbc = { NID_des_cbc, @@ -456,7 +505,7 @@ const EVP_CIPHER cryptodev_des_cbc = { cryptodev_init_key, cryptodev_cipher, cryptodev_cleanup, - sizeof(struct session_op), + sizeof(struct dev_crypto_state), EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL @@ -470,19 +519,57 @@ const EVP_CIPHER cryptodev_3des_cbc = { cryptodev_init_key, cryptodev_cipher, cryptodev_cleanup, - sizeof(struct session_op), + 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 +}; /* * 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 */ -int +static int cryptodev_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid) { @@ -490,15 +577,21 @@ cryptodev_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, return (cryptodev_usable_ciphers(nids)); switch (nid) { - case NID_rc4: - *cipher = &cryptodev_arc4_cipher; - 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; default: *cipher = NULL; break; @@ -506,7 +599,7 @@ cryptodev_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, return (*cipher != NULL); } -int +static int cryptodev_engine_digests(ENGINE *e, const EVP_MD **digest, const int **nids, int nid) { @@ -524,7 +617,6 @@ cryptodev_engine_digests(ENGINE *e, const EVP_MD **digest, return (*digest != NULL); } - /* * Convert a BIGNUM to the representation that /dev/crypto needs. * Upon completion of use, the caller is responsible for freeing @@ -533,7 +625,7 @@ cryptodev_engine_digests(ENGINE *e, const EVP_MD **digest, static int bn2crparam(const BIGNUM *a, struct crparam *crp) { - int i, j, n; + int i, j, k; ssize_t words, bytes, bits; u_char *b; @@ -550,17 +642,13 @@ bn2crparam(const BIGNUM *a, struct crparam *crp) crp->crp_p = b; crp->crp_nbits = bits; - words = (bits + BN_BITS2 - 1) / BN_BITS2; - - n = 0; - for (i = 0; i < words && n < bytes; i++) { - BN_ULONG word; - - word = a->d[i]; - for (j = 0 ; j < BN_BYTES && n < bytes; j++, n++) { - *b++ = (word & 0xff); - word >>= 8; + 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); } @@ -569,15 +657,22 @@ bn2crparam(const BIGNUM *a, struct crparam *crp) static int crparam2bn(struct crparam *crp, BIGNUM *a) { + u_int8_t *pd; int i, bytes; - bytes = (crp->crp_nbits + 7)/8; + bytes = (crp->crp_nbits + 7) / 8; - BN_zero(a); - for (i = bytes - 1; i >= 0; i--) { - BN_lshift(a, a, 8); - BN_add_word(a, (u_char)crp->crp_p[i]); - } + 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); } @@ -596,25 +691,32 @@ zapparams(struct crypt_kop *kop) } static int -cryptodev_sym(struct crypt_kop *kop, BIGNUM *r, BIGNUM *s) +cryptodev_asym(struct crypt_kop *kop, int rlen, BIGNUM *r, int slen, BIGNUM *s) { - int ret = -1; + int fd, ret = -1; + + if ((fd = get_asym_dev_crypto()) < 0) + return (ret); if (r) { - kop->crk_param[kop->crk_iparams].crp_p = malloc(256); - kop->crk_param[kop->crk_iparams].crp_nbits = 256 * 8; + 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 = malloc(256); - kop->crk_param[kop->crk_iparams+1].crp_nbits = 256 * 8; + 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(cryptodev_fd, CIOCKEY, &kop) == 0) { - crparam2bn(&kop->crk_param[3], r); + 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); } @@ -623,38 +725,58 @@ 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 = 0; + 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 m p */ + /* inputs: a^p % m */ if (bn2crparam(a, &kop.crk_param[0])) goto err; - if (bn2crparam(m, &kop.crk_param[1])) + if (bn2crparam(p, &kop.crk_param[1])) goto err; - if (bn2crparam(p, &kop.crk_param[2])) + if (bn2crparam(m, &kop.crk_param[2])) goto err; kop.crk_iparams = 3; - if (cryptodev_sym(&kop, r, NULL) == -1) { - ret = BN_mod_exp(r, a, p, m, ctx); + if (cryptodev_asym(&kop, BN_num_bytes(m), r, 0, NULL) == -1) { + const RSA_METHOD *meth = RSA_PKCS1_SSLeay(); + ret = meth->bn_mod_exp(r, a, p, m, ctx, in_mont); } err: zapparams(&kop); return (ret); } +static int +cryptodev_rsa_nocrt_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa) +{ + int r; + BN_CTX *ctx; + + 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) { struct crypt_kop kop; - int ret = 0; + int ret = 1; if (!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp) { /* XXX 0 means failure?? */ - goto err; + return (0); } memset(&kop, 0, sizeof kop); @@ -674,9 +796,8 @@ cryptodev_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa) goto err; kop.crk_iparams = 6; - if (cryptodev_sym(&kop, r0, NULL) == -1) { + if (cryptodev_asym(&kop, BN_num_bytes(rsa->n), r0, 0, NULL) == -1) { const RSA_METHOD *meth = RSA_PKCS1_SSLeay(); - ret = (*meth->rsa_mod_exp)(r0, I, rsa); } err: @@ -690,8 +811,8 @@ static RSA_METHOD cryptodev_rsa = { NULL, /* rsa_pub_dec */ NULL, /* rsa_priv_enc */ NULL, /* rsa_priv_dec */ - cryptodev_rsa_mod_exp, /* rsa_mod_exp */ - cryptodev_bn_mod_exp, /* bn_mod_exp */ + NULL, + NULL, NULL, /* init */ NULL, /* finish */ 0, /* flags */ @@ -707,6 +828,38 @@ cryptodev_dsa_bn_mod_exp(DSA *dsa, BIGNUM *r, BIGNUM *a, const BIGNUM *p, 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) { @@ -721,6 +874,7 @@ cryptodev_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) goto err; } + printf("bar\n"); memset(&kop, 0, sizeof kop); kop.crk_op = CRK_DSA_SIGN; @@ -737,13 +891,13 @@ cryptodev_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) goto err; kop.crk_iparams = 5; - if (cryptodev_sym(&kop, r, s) == 0) { + 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); @@ -759,7 +913,7 @@ cryptodev_dsa_verify(const unsigned char *dgst, int dlen, DSA_SIG *sig, DSA *dsa) { struct crypt_kop kop; - int dsaret = 0; + int dsaret = 1; memset(&kop, 0, sizeof kop); kop.crk_op = CRK_DSA_VERIFY; @@ -781,7 +935,7 @@ cryptodev_dsa_verify(const unsigned char *dgst, int dlen, goto err; kop.crk_iparams = 7; - if (cryptodev_sym(&kop, NULL, NULL) == 0) { + if (cryptodev_asym(&kop, 0, NULL, 0, NULL) == 0) { dsaret = kop.crk_status; } else { const DSA_METHOD *meth = DSA_OpenSSL(); @@ -796,11 +950,11 @@ err: static DSA_METHOD cryptodev_dsa = { "cryptodev DSA method", - cryptodev_dsa_do_sign, + NULL, NULL, /* dsa_sign_setup */ - cryptodev_dsa_verify, + NULL, NULL, /* dsa_mod_exp */ - cryptodev_dsa_bn_mod_exp, /* bn_mod_exp */ + NULL, NULL, /* init */ NULL, /* finish */ 0, /* flags */ @@ -819,8 +973,14 @@ static int cryptodev_dh_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh) { struct crypt_kop kop; - int dhret = 0; - int keylen; + 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); @@ -840,7 +1000,7 @@ cryptodev_dh_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh) kop.crk_param[3].crp_nbits = keylen * 8; kop.crk_oparams = 1; - if (ioctl(cryptodev_fd, CIOCKEY, &kop) == -1) { + if (ioctl(fd, CIOCKEY, &kop) == -1) { const DH_METHOD *meth = DH_OpenSSL(); dhret = (meth->compute_key)(key, pub_key, dh); @@ -854,8 +1014,8 @@ err: static DH_METHOD cryptodev_dh = { "cryptodev DH method", NULL, /* cryptodev_dh_generate_key */ - cryptodev_dh_compute_key, - cryptodev_mod_exp_dh, + NULL, + NULL, NULL, NULL, 0, /* flags */ @@ -869,12 +1029,18 @@ static DH_METHOD cryptodev_dh = { static int cryptodev_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)()) { +#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); @@ -884,14 +1050,24 @@ void ENGINE_load_cryptodev(void) { ENGINE *engine = ENGINE_new(); - const RSA_METHOD *rsa_meth; - const DH_METHOD *dh_meth; + int fd; if (engine == NULL) return; + if ((fd = get_dev_crypto()) < 0) + return; + + /* + * find out what asymmetric crypto algorithms we support + */ + if (ioctl(fd, CIOCASYMFEAT, &cryptodev_asymfeat) == -1) { + close(fd); + return; + } + close(fd); if (!ENGINE_set_id(engine, "cryptodev") || - !ENGINE_set_name(engine, "OpenBSD cryptodev engine") || + !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) || @@ -900,27 +1076,57 @@ ENGINE_load_cryptodev(void) return; } - if ((cryptodev_symfeat & CRSFEAT_RSA) && - ENGINE_set_RSA(engine, &cryptodev_rsa)) { - rsa_meth = RSA_PKCS1_SSLeay(); + 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_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 ((cryptodev_symfeat & CRSFEAT_DSA) && - ENGINE_set_DSA(engine, &cryptodev_dsa)) { + 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 ((cryptodev_symfeat & CRSFEAT_DH) && - ENGINE_set_DH(engine, &cryptodev_dh)) { - dh_meth = DH_OpenSSL(); + 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 */ -- cgit v1.2.3-55-g6feb