summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/engine/hw_cryptodev.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/engine/hw_cryptodev.c')
-rw-r--r--src/lib/libcrypto/engine/hw_cryptodev.c926
1 files changed, 926 insertions, 0 deletions
diff --git a/src/lib/libcrypto/engine/hw_cryptodev.c b/src/lib/libcrypto/engine/hw_cryptodev.c
new file mode 100644
index 0000000000..7c3728f395
--- /dev/null
+++ b/src/lib/libcrypto/engine/hw_cryptodev.c
@@ -0,0 +1,926 @@
1/*
2 * Copyright (c) 2002 Bob Beck <beck@openbsd.org>
3 * Copyright (c) 2002 Theo de Raadt
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the author nor the names of contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 */
30
31#include <sys/types.h>
32#include <sys/param.h>
33#include <crypto/cryptodev.h>
34#include <sys/ioctl.h>
35#include <errno.h>
36#include <stdio.h>
37#include <unistd.h>
38#include <fcntl.h>
39#include <syslog.h>
40#include <stdarg.h>
41#include <ssl/objects.h>
42#include <ssl/engine.h>
43#include <ssl/evp.h>
44
45static int cryptodev_fd = -1;
46static int cryptodev_sessions = 0;
47static u_int32_t cryptodev_symfeat = 0;
48
49static int bn2crparam(const BIGNUM *a, struct crparam *crp);
50static int crparam2bn(struct crparam *crp, BIGNUM *a);
51static void zapparams(struct crypt_kop *kop);
52
53static int cryptodev_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa);
54static int cryptodev_bn_mod_exp(BIGNUM *r, const BIGNUM *a,
55 const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
56static int cryptodev_dsa_bn_mod_exp(DSA *dsa, BIGNUM *r, BIGNUM *a,
57 const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
58static DSA_SIG *cryptodev_dsa_do_sign(const unsigned char *dgst,
59 int dlen, DSA *dsa);
60static int cryptodev_dsa_verify(const unsigned char *dgst, int dgst_len,
61 DSA_SIG *sig, DSA *dsa);
62static int cryptodev_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a,
63 const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
64 BN_MONT_CTX *m_ctx);
65static int cryptodev_dh_compute_key(unsigned char *key,
66 const BIGNUM *pub_key, DH *dh);
67
68static const ENGINE_CMD_DEFN cryptodev_defns[] = {
69 { 0, NULL, NULL, 0 }
70};
71
72static struct {
73 int id;
74 int nid;
75 int ivmax;
76 int keylen;
77} ciphers[] = {
78 { CRYPTO_DES_CBC, NID_des_cbc, 8, 8, },
79 { CRYPTO_3DES_CBC, NID_des_ede3_cbc, 8, 24, },
80 { CRYPTO_AES_CBC, NID_undef, 8, 24, },
81 { CRYPTO_BLF_CBC, NID_bf_cbc, 8, 16, },
82 { CRYPTO_CAST_CBC, NID_cast5_cbc, 8, 8, },
83 { CRYPTO_SKIPJACK_CBC, NID_undef, 0, 0, },
84 { CRYPTO_ARC4, NID_rc4, 8, 16, },
85 { 0, NID_undef, 0, 0, },
86};
87
88static struct {
89 int id;
90 int nid;
91} digests[] = {
92 { CRYPTO_SHA1_HMAC, NID_hmacWithSHA1, },
93 { CRYPTO_RIPEMD160_HMAC, NID_ripemd160, },
94 { CRYPTO_MD5_KPDK, NID_undef, },
95 { CRYPTO_SHA1_KPDK, NID_undef, },
96 { CRYPTO_MD5, NID_md5, },
97 { CRYPTO_SHA1, NID_undef, },
98 { 0, NID_undef, },
99};
100
101/*
102 * Return 1 if /dev/crypto seems usable, 0 otherwise , also
103 * does most of the work of initting the device, if not already
104 * done.. This should leave is with global fd initialized with CRIOGET.
105 */
106static int
107check_dev_crypto()
108{
109 int fd;
110
111 if (cryptodev_fd == -1) {
112 if ((fd = open("/dev/crypto", O_RDWR, 0)) == -1)
113 return (0);
114 if (ioctl(fd, CRIOGET, &cryptodev_fd) == -1) {
115 close(fd);
116 return (0);
117 }
118 close(fd);
119 /* close on exec */
120 if (fcntl(cryptodev_fd, F_SETFD, 1) == -1) {
121 close(cryptodev_fd);
122 cryptodev_fd = -1;
123 return (0);
124 }
125 }
126 ioctl(cryptodev_fd, CIOCSYMFEAT, &cryptodev_symfeat);
127
128 return (1);
129}
130
131/*
132 * XXXX this needs to be set for each alg - and determined from
133 * a running card.
134 */
135static int
136cryptodev_max_iv(int cipher)
137{
138 int i;
139
140 for (i = 0; ciphers[i].id; i++)
141 if (ciphers[i].id == cipher)
142 return (ciphers[i].ivmax);
143 return (0);
144}
145
146/*
147 * XXXX this needs to be set for each alg - and determined from
148 * a running card. For now, fake it out - but most of these
149 * for real devices should return 1 for the supported key
150 * sizes the device can handle.
151 */
152static int
153cryptodev_key_length_valid(int cipher, int len)
154{
155 int i;
156
157 for (i = 0; ciphers[i].id; i++)
158 if (ciphers[i].id == cipher)
159 return (ciphers[i].keylen == len);
160 return (0);
161}
162
163/* convert libcrypto nids to cryptodev */
164static int
165cipher_nid_to_cryptodev(int nid)
166{
167 int i;
168
169 for (i = 0; ciphers[i].id; i++)
170 if (ciphers[i].nid == nid)
171 return (ciphers[i].id);
172 return (0);
173}
174
175/*
176 * Find out what ciphers /dev/crypto will let us have a session for.
177 * XXX note, that some of these openssl doesn't deal with yet!
178 * returning them here is harmless, as long as we return NULL
179 * when asked for a handler in the cryptodev_engine_ciphers routine
180 */
181static int
182get_cryptodev_ciphers(const int **cnids)
183{
184 static int nids[CRYPTO_ALGORITHM_MAX];
185 struct session_op sess;
186 int i, count = 0;
187
188 memset(&sess, 0, sizeof(sess));
189 sess.key = (caddr_t)"123456781234567812345678";
190
191 for (i = 0; ciphers[i].id && count < CRYPTO_ALGORITHM_MAX; i++) {
192 if (ciphers[i].nid == NID_undef)
193 continue;
194 sess.cipher = ciphers[i].id;
195 sess.keylen = ciphers[i].keylen;
196 sess.mac = 0;
197 if (ioctl(cryptodev_fd, CIOCGSESSION, &sess) != -1 &&
198 ioctl(cryptodev_fd, CIOCFSESSION, &sess.ses) != -1)
199 nids[count++] = ciphers[i].nid;
200 }
201 if (count > 0)
202 *cnids = nids;
203 else
204 *cnids = NULL;
205 return (count);
206}
207
208/*
209 * Find out what digests /dev/crypto will let us have a session for.
210 * XXX note, that some of these openssl doesn't deal with yet!
211 * returning them here is harmless, as long as we return NULL
212 * when asked for a handler in the cryptodev_engine_digests routine
213 */
214static int
215get_cryptodev_digests(const int **cnids)
216{
217 static int nids[CRYPTO_ALGORITHM_MAX];
218 struct session_op sess;
219 int i, count = 0;
220
221 memset(&sess, 0, sizeof(sess));
222 for (i = 0; digests[i].id && count < CRYPTO_ALGORITHM_MAX; i++) {
223 if (digests[i].nid == NID_undef)
224 continue;
225 sess.mac = digests[i].id;
226 sess.cipher = 0;
227 if (ioctl(cryptodev_fd, CIOCGSESSION, &sess) != -1 &&
228 ioctl(cryptodev_fd, CIOCFSESSION, &sess.ses) != -1)
229 nids[count++] = digests[i].nid;
230 }
231 if (count > 0)
232 *cnids = nids;
233 else
234 *cnids = NULL;
235 return (count);
236}
237
238/*
239 * Find the useable ciphers|digests from dev/crypto - this is the first
240 * thing called by the engine init crud which determines what it
241 * can use for ciphers from this engine. We want to return
242 * only what we can do, anythine else is handled by software.
243 *
244 * If we can't initialize the device to do anything useful for
245 * any reason, we want to return a NULL array, and 0 length,
246 * which forces everything to be done is software. By putting
247 * the initalization of the device in here, we ensure we can
248 * use this engine as the default, and if for whatever reason
249 * /dev/crypto won't do what we want it will just be done in
250 * software
251 *
252 * This can (should) be greatly expanded to perhaps take into
253 * account speed of the device, and what we want to do.
254 * (although the disabling of particular alg's could be controlled
255 * by the device driver with sysctl's.) - this is where we
256 * want most of the decisions made about what we actually want
257 * to use from /dev/crypto.
258 */
259int
260cryptodev_usable_ciphers(const int **nids)
261{
262 if (!check_dev_crypto()) {
263 *nids = NULL;
264 return (0);
265 }
266
267 /* find what the device can do. Unfortunately, we don't
268 * necessarily want all of these yet, because we aren't
269 * yet set up to do them
270 */
271 return (get_cryptodev_ciphers(nids));
272}
273
274int
275cryptodev_usable_digests(const int **nids)
276{
277#if 1
278 /*
279 * XXXX just disable all digests for now, because it sucks.
280 * we need a better way to decide this - i.e. I may not
281 * want digests on slow cards like hifn on fast machines,
282 * but might want them on slow or loaded machines, etc.
283 * will also want them when using crypto cards that don't
284 * suck moose gonads - would be nice to be able to decide something
285 * as reasonable default without having hackery that's card dependent.
286 * of course, the default should probably be just do everything,
287 * with perhaps a sysctl to turn algoritms off (or have them off
288 * by default) on cards that generally suck like the hifn.
289 */
290 *nids = NULL;
291 return (0);
292#endif
293
294 if (!check_dev_crypto()) {
295 *nids = NULL;
296 return (0);
297 }
298 return (get_cryptodev_digests(nids));
299}
300
301
302int
303cryptodev_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
304 const unsigned char *in, unsigned int inl)
305{
306 struct crypt_op cryp;
307 struct session_op *sess = ctx->cipher_data;
308 void *iiv;
309 unsigned char save_iv[EVP_MAX_IV_LENGTH];
310 struct syslog_data sd = SYSLOG_DATA_INIT;
311
312 if (cryptodev_fd == -1)
313 return (0);
314 if (sess == NULL)
315 return (0);
316 if (!inl)
317 return (1);
318 if ((inl % ctx->cipher->block_size) != 0)
319 return (0);
320
321 memset(&cryp, 0, sizeof(cryp));
322
323 cryp.ses = sess->ses;
324 cryp.flags = 0;
325 cryp.len = inl;
326 cryp.src = (caddr_t) in;
327 cryp.dst = (caddr_t) out;
328 cryp.mac = 0;
329
330 cryp.op = ctx->encrypt ? COP_ENCRYPT : COP_DECRYPT;
331
332 if (ctx->cipher->iv_len) {
333 cryp.iv = (caddr_t) ctx->iv;
334 if (!ctx->encrypt) {
335 iiv = (void *) in + inl - ctx->cipher->iv_len;
336 memcpy(save_iv, iiv, ctx->cipher->iv_len);
337 }
338 } else
339 cryp.iv = NULL;
340
341 if (ioctl(cryptodev_fd, CIOCCRYPT, &cryp) == -1) {
342 /* XXX need better errror handling
343 * this can fail for a number of different reasons.
344 */
345 syslog_r(LOG_ERR, &sd, "CIOCCRYPT failed (%m)");
346 return (0);
347 }
348
349 if (ctx->cipher->iv_len) {
350 if (ctx->encrypt)
351 iiv = (void *) out + inl - ctx->cipher->iv_len;
352 else
353 iiv = save_iv;
354 memcpy(ctx->iv, iiv, ctx->cipher->iv_len);
355 }
356 return (1);
357}
358
359int
360cryptodev_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
361 const unsigned char *iv, int enc)
362{
363 struct session_op *sess = ctx->cipher_data;
364 struct syslog_data sd = SYSLOG_DATA_INIT;
365 int cipher;
366
367 if ((cipher = cipher_nid_to_cryptodev(ctx->cipher->nid)) == NID_undef)
368 return (0);
369
370 if (!check_dev_crypto())
371 return (0);
372
373 if (ctx->cipher->iv_len > cryptodev_max_iv(cipher))
374 return (0);
375
376 if (!cryptodev_key_length_valid(cipher, ctx->key_len))
377 return (0);
378
379 memset(sess, 0, sizeof(struct session_op));
380
381 sess->key = (unsigned char *)key;
382 sess->keylen = ctx->key_len;
383 sess->cipher = cipher;
384
385 if (ioctl(cryptodev_fd, CIOCGSESSION, sess) == -1) {
386 syslog_r(LOG_ERR, &sd, "CIOCGSESSION failed (%m)");
387 return (0);
388 }
389 cryptodev_sessions++;
390 return (1);
391}
392
393/*
394 * free anything we allocated earlier when initting a
395 * session, and close the session.
396 */
397int
398cryptodev_cleanup(EVP_CIPHER_CTX *ctx)
399{
400 int ret = 0;
401 struct session_op *sess = ctx->cipher_data;
402 struct syslog_data sd = SYSLOG_DATA_INIT;
403
404 if (sess == NULL)
405 return (0);
406
407 /* XXX if this ioctl fails, someting's wrong. the invoker
408 * may have called us with a bogus ctx, or we could
409 * have a device that for whatever reason just doesn't
410 * want to play ball - it's not clear what's right
411 * here - should this be an error? should it just
412 * increase a counter, hmm. For right now, we return
413 * 0 - I don't believe that to be "right". we could
414 * call the gorpy openssl lib error handlers that
415 * print messages to users of the library. hmm..
416 */
417
418 if (ioctl(cryptodev_fd, CIOCFSESSION, &sess->ses) == -1) {
419 syslog_r(LOG_ERR, &sd, "CIOCFSESSION failed (%m)");
420 ret = 0;
421 } else {
422 cryptodev_sessions--;
423 ret = 1;
424 }
425 if (cryptodev_sessions == 0 && cryptodev_fd != -1 ) {
426 close(cryptodev_fd); /* XXX should this be closed? */
427 cryptodev_fd = -1;
428 }
429 return (ret);
430}
431
432/*
433 * libcrypto EVP stuff - this is how we get wired to EVP so the engine
434 * gets called when libcrypto requests a cipher NID.
435 */
436
437/* ARC4 (16 byte key) */
438const EVP_CIPHER cryptodev_arc4_cipher = {
439 NID_rc4,
440 1, 16, 0,
441 EVP_CIPH_VARIABLE_LENGTH,
442 cryptodev_init_key,
443 cryptodev_cipher,
444 cryptodev_cleanup,
445 sizeof(struct session_op),
446 NULL,
447 NULL,
448 NULL
449};
450
451/* DES CBC EVP */
452const EVP_CIPHER cryptodev_des_cbc = {
453 NID_des_cbc,
454 8, 8, 8,
455 EVP_CIPH_CBC_MODE,
456 cryptodev_init_key,
457 cryptodev_cipher,
458 cryptodev_cleanup,
459 sizeof(struct session_op),
460 EVP_CIPHER_set_asn1_iv,
461 EVP_CIPHER_get_asn1_iv,
462 NULL
463};
464
465/* 3DES CBC EVP */
466const EVP_CIPHER cryptodev_3des_cbc = {
467 NID_des_ede3_cbc,
468 8, 24, 8,
469 EVP_CIPH_CBC_MODE,
470 cryptodev_init_key,
471 cryptodev_cipher,
472 cryptodev_cleanup,
473 sizeof(struct session_op),
474 EVP_CIPHER_set_asn1_iv,
475 EVP_CIPHER_get_asn1_iv,
476 NULL
477};
478
479
480/*
481 * Registered by the ENGINE when used to find out how to deal with
482 * a particular NID in the ENGINE. this says what we'll do at the
483 * top level - note, that list is restricted by what we answer with
484 */
485int
486cryptodev_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
487 const int **nids, int nid)
488{
489 if (!cipher)
490 return (cryptodev_usable_ciphers(nids));
491
492 switch (nid) {
493 case NID_rc4:
494 *cipher = &cryptodev_arc4_cipher;
495 break;
496 case NID_des_ede3_cbc:
497 *cipher = &cryptodev_3des_cbc;
498 break;
499 case NID_des_cbc:
500 *cipher = &cryptodev_des_cbc;
501 break;
502 default:
503 *cipher = NULL;
504 break;
505 }
506 return (*cipher != NULL);
507}
508
509int
510cryptodev_engine_digests(ENGINE *e, const EVP_MD **digest,
511 const int **nids, int nid)
512{
513 if (!digest)
514 return (cryptodev_usable_digests(nids));
515
516 switch (nid) {
517 case NID_md5:
518 *digest = NULL; /* need to make a clean md5 critter */
519 break;
520 default:
521 *digest = NULL;
522 break;
523 }
524 return (*digest != NULL);
525}
526
527
528/*
529 * Convert a BIGNUM to the representation that /dev/crypto needs.
530 * Upon completion of use, the caller is responsible for freeing
531 * crp->crp_p.
532 */
533static int
534bn2crparam(const BIGNUM *a, struct crparam *crp)
535{
536 int i, j, n;
537 ssize_t words, bytes, bits;
538 u_char *b;
539
540 crp->crp_p = NULL;
541 crp->crp_nbits = 0;
542
543 bits = BN_num_bits(a);
544 bytes = (bits + 7) / 8;
545
546 b = malloc(bytes);
547 if (b == NULL)
548 return (1);
549
550 crp->crp_p = b;
551 crp->crp_nbits = bits;
552
553 words = (bits + BN_BITS2 - 1) / BN_BITS2;
554
555 n = 0;
556 for (i = 0; i < words && n < bytes; i++) {
557 BN_ULONG word;
558
559 word = a->d[i];
560 for (j = 0 ; j < BN_BYTES && n < bytes; j++, n++) {
561 *b++ = (word & 0xff);
562 word >>= 8;
563 }
564 }
565 return (0);
566}
567
568/* Convert a /dev/crypto parameter to a BIGNUM */
569static int
570crparam2bn(struct crparam *crp, BIGNUM *a)
571{
572 int i, bytes;
573
574 bytes = (crp->crp_nbits + 7)/8;
575
576 BN_zero(a);
577 for (i = bytes - 1; i >= 0; i--) {
578 BN_lshift(a, a, 8);
579 BN_add_word(a, (u_char)crp->crp_p[i]);
580 }
581
582 return (0);
583}
584
585static void
586zapparams(struct crypt_kop *kop)
587{
588 int i;
589
590 for (i = 0; i <= kop->crk_iparams + kop->crk_oparams; i++) {
591 if (kop->crk_param[i].crp_p)
592 free(kop->crk_param[i].crp_p);
593 kop->crk_param[i].crp_p = NULL;
594 kop->crk_param[i].crp_nbits = 0;
595 }
596}
597
598static int
599cryptodev_sym(struct crypt_kop *kop, BIGNUM *r, BIGNUM *s)
600{
601 int ret = -1;
602
603 if (r) {
604 kop->crk_param[kop->crk_iparams].crp_p = malloc(256);
605 kop->crk_param[kop->crk_iparams].crp_nbits = 256 * 8;
606 kop->crk_oparams++;
607 }
608 if (s) {
609 kop->crk_param[kop->crk_iparams+1].crp_p = malloc(256);
610 kop->crk_param[kop->crk_iparams+1].crp_nbits = 256 * 8;
611 kop->crk_oparams++;
612 }
613
614 if (ioctl(cryptodev_fd, CIOCKEY, &kop) == 0) {
615 crparam2bn(&kop->crk_param[3], r);
616 ret = 0;
617 }
618 return (ret);
619}
620
621static int
622cryptodev_bn_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
623 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont)
624{
625 struct crypt_kop kop;
626 int ret = 0;
627
628 memset(&kop, 0, sizeof kop);
629 kop.crk_op = CRK_MOD_EXP;
630
631 /* inputs: a m p */
632 if (bn2crparam(a, &kop.crk_param[0]))
633 goto err;
634 if (bn2crparam(m, &kop.crk_param[1]))
635 goto err;
636 if (bn2crparam(p, &kop.crk_param[2]))
637 goto err;
638 kop.crk_iparams = 3;
639
640 if (cryptodev_sym(&kop, r, NULL) == -1) {
641 ret = BN_mod_exp(r, a, p, m, ctx);
642 }
643err:
644 zapparams(&kop);
645 return (ret);
646}
647
648
649static int
650cryptodev_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa)
651{
652 struct crypt_kop kop;
653 int ret = 0;
654
655 if (!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp) {
656 /* XXX 0 means failure?? */
657 goto err;
658 }
659
660 memset(&kop, 0, sizeof kop);
661 kop.crk_op = CRK_MOD_EXP_CRT;
662 /* inputs: rsa->p rsa->q I rsa->dmp1 rsa->dmq1 rsa->iqmp */
663 if (bn2crparam(rsa->p, &kop.crk_param[0]))
664 goto err;
665 if (bn2crparam(rsa->q, &kop.crk_param[1]))
666 goto err;
667 if (bn2crparam(I, &kop.crk_param[2]))
668 goto err;
669 if (bn2crparam(rsa->dmp1, &kop.crk_param[3]))
670 goto err;
671 if (bn2crparam(rsa->dmq1, &kop.crk_param[4]))
672 goto err;
673 if (bn2crparam(rsa->iqmp, &kop.crk_param[5]))
674 goto err;
675 kop.crk_iparams = 6;
676
677 if (cryptodev_sym(&kop, r0, NULL) == -1) {
678 const RSA_METHOD *meth = RSA_PKCS1_SSLeay();
679
680 ret = (*meth->rsa_mod_exp)(r0, I, rsa);
681 }
682err:
683 zapparams(&kop);
684 return (ret);
685}
686
687static RSA_METHOD cryptodev_rsa = {
688 "cryptodev RSA method",
689 NULL, /* rsa_pub_enc */
690 NULL, /* rsa_pub_dec */
691 NULL, /* rsa_priv_enc */
692 NULL, /* rsa_priv_dec */
693 cryptodev_rsa_mod_exp, /* rsa_mod_exp */
694 cryptodev_bn_mod_exp, /* bn_mod_exp */
695 NULL, /* init */
696 NULL, /* finish */
697 0, /* flags */
698 NULL, /* app_data */
699 NULL, /* rsa_sign */
700 NULL /* rsa_verify */
701};
702
703static int
704cryptodev_dsa_bn_mod_exp(DSA *dsa, BIGNUM *r, BIGNUM *a, const BIGNUM *p,
705 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
706{
707 return (cryptodev_bn_mod_exp(r, a, p, m, ctx, m_ctx));
708}
709
710static DSA_SIG *
711cryptodev_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
712{
713 struct crypt_kop kop;
714 BIGNUM *r = NULL, *s = NULL;
715 DSA_SIG *dsaret = NULL;
716
717 if ((r = BN_new()) == NULL)
718 goto err;
719 if ((s = BN_new()) == NULL) {
720 BN_free(r);
721 goto err;
722 }
723
724 memset(&kop, 0, sizeof kop);
725 kop.crk_op = CRK_DSA_SIGN;
726
727 /* inputs: dgst dsa->p dsa->q dsa->g dsa->priv_key */
728 kop.crk_param[0].crp_p = (caddr_t)dgst;
729 kop.crk_param[0].crp_nbits = dlen * 8;
730 if (bn2crparam(dsa->p, &kop.crk_param[1]))
731 goto err;
732 if (bn2crparam(dsa->q, &kop.crk_param[2]))
733 goto err;
734 if (bn2crparam(dsa->g, &kop.crk_param[3]))
735 goto err;
736 if (bn2crparam(dsa->priv_key, &kop.crk_param[4]))
737 goto err;
738 kop.crk_iparams = 5;
739
740 if (cryptodev_sym(&kop, r, s) == 0) {
741 dsaret = DSA_SIG_new();
742 dsaret->r = r;
743 dsaret->s = s;
744 } else {
745 const DSA_METHOD *meth = DSA_OpenSSL();
746
747 BN_free(r);
748 BN_free(s);
749 dsaret = (meth->dsa_do_sign)(dgst, dlen, dsa);
750 }
751err:
752 kop.crk_param[0].crp_p = NULL;
753 zapparams(&kop);
754 return (dsaret);
755}
756
757static int
758cryptodev_dsa_verify(const unsigned char *dgst, int dlen,
759 DSA_SIG *sig, DSA *dsa)
760{
761 struct crypt_kop kop;
762 int dsaret = 0;
763
764 memset(&kop, 0, sizeof kop);
765 kop.crk_op = CRK_DSA_VERIFY;
766
767 /* inputs: dgst dsa->p dsa->q dsa->g dsa->pub_key sig->r sig->s */
768 kop.crk_param[0].crp_p = (caddr_t)dgst;
769 kop.crk_param[0].crp_nbits = dlen * 8;
770 if (bn2crparam(dsa->p, &kop.crk_param[1]))
771 goto err;
772 if (bn2crparam(dsa->q, &kop.crk_param[2]))
773 goto err;
774 if (bn2crparam(dsa->g, &kop.crk_param[3]))
775 goto err;
776 if (bn2crparam(dsa->pub_key, &kop.crk_param[4]))
777 goto err;
778 if (bn2crparam(sig->r, &kop.crk_param[5]))
779 goto err;
780 if (bn2crparam(sig->s, &kop.crk_param[6]))
781 goto err;
782 kop.crk_iparams = 7;
783
784 if (cryptodev_sym(&kop, NULL, NULL) == 0) {
785 dsaret = kop.crk_status;
786 } else {
787 const DSA_METHOD *meth = DSA_OpenSSL();
788
789 dsaret = (meth->dsa_do_verify)(dgst, dlen, sig, dsa);
790 }
791err:
792 kop.crk_param[0].crp_p = NULL;
793 zapparams(&kop);
794 return (dsaret);
795}
796
797static DSA_METHOD cryptodev_dsa = {
798 "cryptodev DSA method",
799 cryptodev_dsa_do_sign,
800 NULL, /* dsa_sign_setup */
801 cryptodev_dsa_verify,
802 NULL, /* dsa_mod_exp */
803 cryptodev_dsa_bn_mod_exp, /* bn_mod_exp */
804 NULL, /* init */
805 NULL, /* finish */
806 0, /* flags */
807 NULL /* app_data */
808};
809
810static int
811cryptodev_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a,
812 const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
813 BN_MONT_CTX *m_ctx)
814{
815 return (cryptodev_bn_mod_exp(r, a, p, m, ctx, m_ctx));
816}
817
818static int
819cryptodev_dh_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
820{
821 struct crypt_kop kop;
822 int dhret = 0;
823 int keylen;
824
825 keylen = BN_num_bits(dh->p);
826
827 memset(&kop, 0, sizeof kop);
828 kop.crk_op = CRK_DH_COMPUTE_KEY;
829
830 /* inputs: dh->priv_key pub_key dh->p key */
831 if (bn2crparam(dh->priv_key, &kop.crk_param[0]))
832 goto err;
833 if (bn2crparam(pub_key, &kop.crk_param[1]))
834 goto err;
835 if (bn2crparam(dh->p, &kop.crk_param[2]))
836 goto err;
837 kop.crk_iparams = 3;
838
839 kop.crk_param[3].crp_p = key;
840 kop.crk_param[3].crp_nbits = keylen * 8;
841 kop.crk_oparams = 1;
842
843 if (ioctl(cryptodev_fd, CIOCKEY, &kop) == -1) {
844 const DH_METHOD *meth = DH_OpenSSL();
845
846 dhret = (meth->compute_key)(key, pub_key, dh);
847 }
848err:
849 kop.crk_param[3].crp_p = NULL;
850 zapparams(&kop);
851 return (dhret);
852}
853
854static DH_METHOD cryptodev_dh = {
855 "cryptodev DH method",
856 NULL, /* cryptodev_dh_generate_key */
857 cryptodev_dh_compute_key,
858 cryptodev_mod_exp_dh,
859 NULL,
860 NULL,
861 0, /* flags */
862 NULL /* app_data */
863};
864
865/*
866 * ctrl right now is just a wrapper that doesn't do much
867 * but I expect we'll want some options soon.
868 */
869static int
870cryptodev_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
871{
872 struct syslog_data sd = SYSLOG_DATA_INIT;
873
874 switch (cmd) {
875 default:
876 syslog_r(LOG_ERR, &sd,
877 "cryptodev_ctrl: unknown command %d", cmd);
878 break;
879 }
880 return (1);
881}
882
883void
884ENGINE_load_cryptodev(void)
885{
886 ENGINE *engine = ENGINE_new();
887 const RSA_METHOD *rsa_meth;
888 const DH_METHOD *dh_meth;
889
890 if (engine == NULL)
891 return;
892
893 if (!ENGINE_set_id(engine, "cryptodev") ||
894 !ENGINE_set_name(engine, "OpenBSD cryptodev engine") ||
895 !ENGINE_set_ciphers(engine, cryptodev_engine_ciphers) ||
896 !ENGINE_set_digests(engine, cryptodev_engine_digests) ||
897 !ENGINE_set_ctrl_function(engine, cryptodev_ctrl) ||
898 !ENGINE_set_cmd_defns(engine, cryptodev_defns)) {
899 ENGINE_free(engine);
900 return;
901 }
902
903 if ((cryptodev_symfeat & CRSFEAT_RSA) &&
904 ENGINE_set_RSA(engine, &cryptodev_rsa)) {
905 rsa_meth = RSA_PKCS1_SSLeay();
906 cryptodev_rsa.rsa_pub_enc = rsa_meth->rsa_pub_enc;
907 cryptodev_rsa.rsa_pub_dec = rsa_meth->rsa_pub_dec;
908 cryptodev_rsa.rsa_priv_enc = rsa_meth->rsa_priv_dec;
909 cryptodev_rsa.rsa_priv_dec = rsa_meth->rsa_priv_dec;
910 }
911
912 if ((cryptodev_symfeat & CRSFEAT_DSA) &&
913 ENGINE_set_DSA(engine, &cryptodev_dsa)) {
914 }
915
916 if ((cryptodev_symfeat & CRSFEAT_DH) &&
917 ENGINE_set_DH(engine, &cryptodev_dh)) {
918 dh_meth = DH_OpenSSL();
919 cryptodev_dh.generate_key = dh_meth->generate_key;
920 cryptodev_dh.compute_key = dh_meth->compute_key;
921 }
922
923 ENGINE_add(engine);
924 ENGINE_free(engine);
925 ERR_clear_error();
926}