]>
Commit | Line | Data |
---|---|---|
76dfca87 RL |
1 | /* |
2 | * Copyright (c) 2002 Bob Beck <beck@openbsd.org> | |
3 | * Copyright (c) 2002 Theo de Raadt | |
4 | * Copyright (c) 2002 Markus Friedl | |
5 | * All rights reserved. | |
6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | |
10 | * 1. Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | |
76dfca87 RL |
15 | * |
16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY | |
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
19 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY | |
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
26 | * | |
27 | */ | |
28 | ||
29 | #include <openssl/objects.h> | |
30 | #include <openssl/engine.h> | |
31 | #include <openssl/evp.h> | |
ac0d0a5e | 32 | #include <openssl/bn.h> |
4de83857 | 33 | #include "../bn/bn_lcl.h" |
76dfca87 | 34 | |
6145b0b1 | 35 | #if (defined(__unix__) || defined(unix)) && !defined(USG) && \ |
0f113f3e MC |
36 | (defined(OpenBSD) || defined(__FreeBSD__)) |
37 | # include <sys/param.h> | |
0c3426da | 38 | # if (OpenBSD >= 200112) || ((__FreeBSD_version >= 470101 && __FreeBSD_version < 500000) || __FreeBSD_version >= 500041) |
c00cee00 RL |
39 | # define HAVE_CRYPTODEV |
40 | # endif | |
41 | # if (OpenBSD >= 200110) | |
42 | # define HAVE_SYSLOG_R | |
43 | # endif | |
44 | #endif | |
b84d5b72 | 45 | |
c00cee00 | 46 | #ifndef HAVE_CRYPTODEV |
b84d5b72 | 47 | |
0f113f3e | 48 | void ENGINE_load_cryptodev(void) |
b84d5b72 | 49 | { |
0f113f3e MC |
50 | /* This is a NOP on platforms without /dev/crypto */ |
51 | return; | |
b84d5b72 RL |
52 | } |
53 | ||
0f113f3e | 54 | #else |
8b968750 | 55 | |
0f113f3e MC |
56 | # include <sys/types.h> |
57 | # include <crypto/cryptodev.h> | |
58 | # include <openssl/dh.h> | |
59 | # include <openssl/dsa.h> | |
60 | # include <openssl/err.h> | |
61 | # include <openssl/rsa.h> | |
62 | # include <sys/ioctl.h> | |
63 | # include <errno.h> | |
64 | # include <stdio.h> | |
65 | # include <unistd.h> | |
66 | # include <fcntl.h> | |
67 | # include <stdarg.h> | |
68 | # include <syslog.h> | |
69 | # include <errno.h> | |
70 | # include <string.h> | |
8b968750 | 71 | |
0f113f3e MC |
72 | struct dev_crypto_state { |
73 | struct session_op d_sess; | |
74 | int d_fd; | |
75 | # ifdef USE_CRYPTODEV_DIGESTS | |
76 | char dummy_mac_key[HASH_MAX_LEN]; | |
77 | unsigned char digest_res[HASH_MAX_LEN]; | |
78 | char *mac_data; | |
79 | int mac_len; | |
80 | # endif | |
76dfca87 RL |
81 | }; |
82 | ||
83 | static u_int32_t cryptodev_asymfeat = 0; | |
84 | ||
85 | static int get_asym_dev_crypto(void); | |
86 | static int open_dev_crypto(void); | |
87 | static int get_dev_crypto(void); | |
76dfca87 | 88 | static int get_cryptodev_ciphers(const int **cnids); |
0f113f3e | 89 | # ifdef USE_CRYPTODEV_DIGESTS |
5e28ccb7 | 90 | static int get_cryptodev_digests(const int **cnids); |
0f113f3e | 91 | # endif |
76dfca87 RL |
92 | static int cryptodev_usable_ciphers(const int **nids); |
93 | static int cryptodev_usable_digests(const int **nids); | |
94 | static int cryptodev_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, | |
0f113f3e | 95 | const unsigned char *in, size_t inl); |
76dfca87 | 96 | static int cryptodev_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, |
0f113f3e | 97 | const unsigned char *iv, int enc); |
76dfca87 RL |
98 | static int cryptodev_cleanup(EVP_CIPHER_CTX *ctx); |
99 | static int cryptodev_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, | |
0f113f3e | 100 | const int **nids, int nid); |
76dfca87 | 101 | static int cryptodev_engine_digests(ENGINE *e, const EVP_MD **digest, |
0f113f3e | 102 | const int **nids, int nid); |
76dfca87 RL |
103 | static int bn2crparam(const BIGNUM *a, struct crparam *crp); |
104 | static int crparam2bn(struct crparam *crp, BIGNUM *a); | |
105 | static void zapparams(struct crypt_kop *kop); | |
106 | static int cryptodev_asym(struct crypt_kop *kop, int rlen, BIGNUM *r, | |
0f113f3e | 107 | int slen, BIGNUM *s); |
76dfca87 RL |
108 | |
109 | static int cryptodev_bn_mod_exp(BIGNUM *r, const BIGNUM *a, | |
0f113f3e MC |
110 | const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, |
111 | BN_MONT_CTX *m_ctx); | |
112 | static int cryptodev_rsa_nocrt_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, | |
113 | BN_CTX *ctx); | |
114 | static int cryptodev_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, | |
115 | BN_CTX *ctx); | |
76dfca87 | 116 | static int cryptodev_dsa_bn_mod_exp(DSA *dsa, BIGNUM *r, BIGNUM *a, |
0f113f3e MC |
117 | const BIGNUM *p, const BIGNUM *m, |
118 | BN_CTX *ctx, BN_MONT_CTX *m_ctx); | |
76dfca87 | 119 | static int cryptodev_dsa_dsa_mod_exp(DSA *dsa, BIGNUM *t1, BIGNUM *g, |
0f113f3e MC |
120 | BIGNUM *u1, BIGNUM *pub_key, BIGNUM *u2, |
121 | BIGNUM *p, BN_CTX *ctx, | |
122 | BN_MONT_CTX *mont); | |
123 | static DSA_SIG *cryptodev_dsa_do_sign(const unsigned char *dgst, int dlen, | |
124 | DSA *dsa); | |
76dfca87 | 125 | static int cryptodev_dsa_verify(const unsigned char *dgst, int dgst_len, |
0f113f3e | 126 | DSA_SIG *sig, DSA *dsa); |
76dfca87 | 127 | static int cryptodev_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a, |
0f113f3e MC |
128 | const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, |
129 | BN_MONT_CTX *m_ctx); | |
130 | static int cryptodev_dh_compute_key(unsigned char *key, const BIGNUM *pub_key, | |
131 | DH *dh); | |
76dfca87 | 132 | static int cryptodev_ctrl(ENGINE *e, int cmd, long i, void *p, |
0f113f3e | 133 | void (*f) (void)); |
76dfca87 RL |
134 | void ENGINE_load_cryptodev(void); |
135 | ||
136 | static const ENGINE_CMD_DEFN cryptodev_defns[] = { | |
0f113f3e | 137 | {0, NULL, NULL, 0} |
76dfca87 RL |
138 | }; |
139 | ||
140 | static struct { | |
0f113f3e MC |
141 | int id; |
142 | int nid; | |
143 | int ivmax; | |
144 | int keylen; | |
76dfca87 | 145 | } ciphers[] = { |
0f113f3e MC |
146 | { |
147 | CRYPTO_ARC4, NID_rc4, 0, 16, | |
148 | }, | |
149 | { | |
150 | CRYPTO_DES_CBC, NID_des_cbc, 8, 8, | |
151 | }, | |
152 | { | |
153 | CRYPTO_3DES_CBC, NID_des_ede3_cbc, 8, 24, | |
154 | }, | |
155 | { | |
156 | CRYPTO_AES_CBC, NID_aes_128_cbc, 16, 16, | |
157 | }, | |
158 | { | |
159 | CRYPTO_AES_CBC, NID_aes_192_cbc, 16, 24, | |
160 | }, | |
161 | { | |
162 | CRYPTO_AES_CBC, NID_aes_256_cbc, 16, 32, | |
163 | }, | |
164 | # ifdef CRYPTO_AES_CTR | |
165 | { | |
166 | CRYPTO_AES_CTR, NID_aes_128_ctr, 14, 16, | |
167 | }, | |
168 | { | |
169 | CRYPTO_AES_CTR, NID_aes_192_ctr, 14, 24, | |
170 | }, | |
171 | { | |
172 | CRYPTO_AES_CTR, NID_aes_256_ctr, 14, 32, | |
173 | }, | |
174 | # endif | |
175 | { | |
176 | CRYPTO_BLF_CBC, NID_bf_cbc, 8, 16, | |
177 | }, | |
178 | { | |
179 | CRYPTO_CAST_CBC, NID_cast5_cbc, 8, 16, | |
180 | }, | |
181 | { | |
182 | CRYPTO_SKIPJACK_CBC, NID_undef, 0, 0, | |
183 | }, | |
184 | { | |
185 | 0, NID_undef, 0, 0, | |
186 | }, | |
76dfca87 RL |
187 | }; |
188 | ||
0f113f3e | 189 | # ifdef USE_CRYPTODEV_DIGESTS |
76dfca87 | 190 | static struct { |
0f113f3e MC |
191 | int id; |
192 | int nid; | |
193 | int keylen; | |
76dfca87 | 194 | } digests[] = { |
0f113f3e MC |
195 | { |
196 | CRYPTO_MD5_HMAC, NID_hmacWithMD5, 16 | |
197 | }, | |
198 | { | |
199 | CRYPTO_SHA1_HMAC, NID_hmacWithSHA1, 20 | |
200 | }, | |
201 | { | |
202 | CRYPTO_RIPEMD160_HMAC, NID_ripemd160, 16 | |
203 | /* ? */ | |
204 | }, | |
205 | { | |
206 | CRYPTO_MD5_KPDK, NID_undef, 0 | |
207 | }, | |
208 | { | |
209 | CRYPTO_SHA1_KPDK, NID_undef, 0 | |
210 | }, | |
211 | { | |
212 | CRYPTO_MD5, NID_md5, 16 | |
213 | }, | |
214 | { | |
215 | CRYPTO_SHA1, NID_sha1, 20 | |
216 | }, | |
217 | { | |
218 | 0, NID_undef, 0 | |
219 | }, | |
76dfca87 | 220 | }; |
0f113f3e | 221 | # endif |
76dfca87 RL |
222 | |
223 | /* | |
224 | * Return a fd if /dev/crypto seems usable, 0 otherwise. | |
225 | */ | |
0f113f3e | 226 | static int open_dev_crypto(void) |
76dfca87 | 227 | { |
0f113f3e MC |
228 | static int fd = -1; |
229 | ||
230 | if (fd == -1) { | |
231 | if ((fd = open("/dev/crypto", O_RDWR, 0)) == -1) | |
232 | return (-1); | |
233 | /* close on exec */ | |
234 | if (fcntl(fd, F_SETFD, 1) == -1) { | |
235 | close(fd); | |
236 | fd = -1; | |
237 | return (-1); | |
238 | } | |
239 | } | |
240 | return (fd); | |
76dfca87 RL |
241 | } |
242 | ||
0f113f3e | 243 | static int get_dev_crypto(void) |
76dfca87 | 244 | { |
0f113f3e MC |
245 | int fd, retfd; |
246 | ||
247 | if ((fd = open_dev_crypto()) == -1) | |
248 | return (-1); | |
249 | # ifndef CRIOGET_NOT_NEEDED | |
250 | if (ioctl(fd, CRIOGET, &retfd) == -1) | |
251 | return (-1); | |
252 | ||
253 | /* close on exec */ | |
254 | if (fcntl(retfd, F_SETFD, 1) == -1) { | |
255 | close(retfd); | |
256 | return (-1); | |
257 | } | |
258 | # else | |
259 | retfd = fd; | |
260 | # endif | |
261 | return (retfd); | |
76dfca87 RL |
262 | } |
263 | ||
d441e6d8 DSH |
264 | static void put_dev_crypto(int fd) |
265 | { | |
0f113f3e MC |
266 | # ifndef CRIOGET_NOT_NEEDED |
267 | close(fd); | |
268 | # endif | |
d441e6d8 DSH |
269 | } |
270 | ||
76dfca87 | 271 | /* Caching version for asym operations */ |
0f113f3e | 272 | static int get_asym_dev_crypto(void) |
76dfca87 | 273 | { |
0f113f3e | 274 | static int fd = -1; |
76dfca87 | 275 | |
0f113f3e MC |
276 | if (fd == -1) |
277 | fd = get_dev_crypto(); | |
278 | return fd; | |
76dfca87 RL |
279 | } |
280 | ||
76dfca87 RL |
281 | /* |
282 | * Find out what ciphers /dev/crypto will let us have a session for. | |
283 | * XXX note, that some of these openssl doesn't deal with yet! | |
284 | * returning them here is harmless, as long as we return NULL | |
285 | * when asked for a handler in the cryptodev_engine_ciphers routine | |
286 | */ | |
0f113f3e | 287 | static int get_cryptodev_ciphers(const int **cnids) |
76dfca87 | 288 | { |
0f113f3e MC |
289 | static int nids[CRYPTO_ALGORITHM_MAX]; |
290 | struct session_op sess; | |
291 | int fd, i, count = 0; | |
292 | ||
293 | if ((fd = get_dev_crypto()) < 0) { | |
294 | *cnids = NULL; | |
295 | return (0); | |
296 | } | |
297 | memset(&sess, 0, sizeof(sess)); | |
298 | sess.key = (caddr_t) "123456789abcdefghijklmno"; | |
299 | ||
300 | for (i = 0; ciphers[i].id && count < CRYPTO_ALGORITHM_MAX; i++) { | |
301 | if (ciphers[i].nid == NID_undef) | |
302 | continue; | |
303 | sess.cipher = ciphers[i].id; | |
304 | sess.keylen = ciphers[i].keylen; | |
305 | sess.mac = 0; | |
306 | if (ioctl(fd, CIOCGSESSION, &sess) != -1 && | |
307 | ioctl(fd, CIOCFSESSION, &sess.ses) != -1) | |
308 | nids[count++] = ciphers[i].nid; | |
309 | } | |
310 | put_dev_crypto(fd); | |
311 | ||
312 | if (count > 0) | |
313 | *cnids = nids; | |
314 | else | |
315 | *cnids = NULL; | |
316 | return (count); | |
76dfca87 RL |
317 | } |
318 | ||
0f113f3e | 319 | # ifdef USE_CRYPTODEV_DIGESTS |
76dfca87 RL |
320 | /* |
321 | * Find out what digests /dev/crypto will let us have a session for. | |
322 | * XXX note, that some of these openssl doesn't deal with yet! | |
323 | * returning them here is harmless, as long as we return NULL | |
324 | * when asked for a handler in the cryptodev_engine_digests routine | |
325 | */ | |
0f113f3e | 326 | static int get_cryptodev_digests(const int **cnids) |
76dfca87 | 327 | { |
0f113f3e MC |
328 | static int nids[CRYPTO_ALGORITHM_MAX]; |
329 | struct session_op sess; | |
330 | int fd, i, count = 0; | |
331 | ||
332 | if ((fd = get_dev_crypto()) < 0) { | |
333 | *cnids = NULL; | |
334 | return (0); | |
335 | } | |
336 | memset(&sess, 0, sizeof(sess)); | |
337 | sess.mackey = (caddr_t) "123456789abcdefghijklmno"; | |
338 | for (i = 0; digests[i].id && count < CRYPTO_ALGORITHM_MAX; i++) { | |
339 | if (digests[i].nid == NID_undef) | |
340 | continue; | |
341 | sess.mac = digests[i].id; | |
342 | sess.mackeylen = digests[i].keylen; | |
343 | sess.cipher = 0; | |
344 | if (ioctl(fd, CIOCGSESSION, &sess) != -1 && | |
345 | ioctl(fd, CIOCFSESSION, &sess.ses) != -1) | |
346 | nids[count++] = digests[i].nid; | |
347 | } | |
348 | put_dev_crypto(fd); | |
349 | ||
350 | if (count > 0) | |
351 | *cnids = nids; | |
352 | else | |
353 | *cnids = NULL; | |
354 | return (count); | |
76dfca87 | 355 | } |
0f113f3e | 356 | # endif /* 0 */ |
76dfca87 RL |
357 | |
358 | /* | |
359 | * Find the useable ciphers|digests from dev/crypto - this is the first | |
360 | * thing called by the engine init crud which determines what it | |
361 | * can use for ciphers from this engine. We want to return | |
362 | * only what we can do, anythine else is handled by software. | |
363 | * | |
364 | * If we can't initialize the device to do anything useful for | |
365 | * any reason, we want to return a NULL array, and 0 length, | |
366 | * which forces everything to be done is software. By putting | |
367 | * the initalization of the device in here, we ensure we can | |
368 | * use this engine as the default, and if for whatever reason | |
369 | * /dev/crypto won't do what we want it will just be done in | |
370 | * software | |
371 | * | |
372 | * This can (should) be greatly expanded to perhaps take into | |
373 | * account speed of the device, and what we want to do. | |
374 | * (although the disabling of particular alg's could be controlled | |
375 | * by the device driver with sysctl's.) - this is where we | |
376 | * want most of the decisions made about what we actually want | |
377 | * to use from /dev/crypto. | |
378 | */ | |
0f113f3e | 379 | static int cryptodev_usable_ciphers(const int **nids) |
76dfca87 | 380 | { |
0f113f3e | 381 | return (get_cryptodev_ciphers(nids)); |
76dfca87 RL |
382 | } |
383 | ||
0f113f3e | 384 | static int cryptodev_usable_digests(const int **nids) |
76dfca87 | 385 | { |
0f113f3e MC |
386 | # ifdef USE_CRYPTODEV_DIGESTS |
387 | return (get_cryptodev_digests(nids)); | |
388 | # else | |
389 | /* | |
390 | * XXXX just disable all digests for now, because it sucks. | |
391 | * we need a better way to decide this - i.e. I may not | |
392 | * want digests on slow cards like hifn on fast machines, | |
393 | * but might want them on slow or loaded machines, etc. | |
394 | * will also want them when using crypto cards that don't | |
395 | * suck moose gonads - would be nice to be able to decide something | |
396 | * as reasonable default without having hackery that's card dependent. | |
397 | * of course, the default should probably be just do everything, | |
398 | * with perhaps a sysctl to turn algoritms off (or have them off | |
399 | * by default) on cards that generally suck like the hifn. | |
400 | */ | |
401 | *nids = NULL; | |
402 | return (0); | |
403 | # endif | |
76dfca87 RL |
404 | } |
405 | ||
406 | static int | |
407 | cryptodev_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, | |
0f113f3e | 408 | const unsigned char *in, size_t inl) |
76dfca87 | 409 | { |
0f113f3e MC |
410 | struct crypt_op cryp; |
411 | struct dev_crypto_state *state = ctx->cipher_data; | |
412 | struct session_op *sess = &state->d_sess; | |
413 | const void *iiv; | |
414 | unsigned char save_iv[EVP_MAX_IV_LENGTH]; | |
415 | ||
416 | if (state->d_fd < 0) | |
417 | return (0); | |
418 | if (!inl) | |
419 | return (1); | |
420 | if ((inl % ctx->cipher->block_size) != 0) | |
421 | return (0); | |
422 | ||
423 | memset(&cryp, 0, sizeof(cryp)); | |
424 | ||
425 | cryp.ses = sess->ses; | |
426 | cryp.flags = 0; | |
427 | cryp.len = inl; | |
428 | cryp.src = (caddr_t) in; | |
429 | cryp.dst = (caddr_t) out; | |
430 | cryp.mac = 0; | |
431 | ||
432 | cryp.op = ctx->encrypt ? COP_ENCRYPT : COP_DECRYPT; | |
433 | ||
434 | if (ctx->cipher->iv_len) { | |
435 | cryp.iv = (caddr_t) ctx->iv; | |
436 | if (!ctx->encrypt) { | |
437 | iiv = in + inl - ctx->cipher->iv_len; | |
438 | memcpy(save_iv, iiv, ctx->cipher->iv_len); | |
439 | } | |
440 | } else | |
441 | cryp.iv = NULL; | |
442 | ||
443 | if (ioctl(state->d_fd, CIOCCRYPT, &cryp) == -1) { | |
444 | /* | |
445 | * XXX need better errror handling this can fail for a number of | |
446 | * different reasons. | |
447 | */ | |
448 | return (0); | |
449 | } | |
450 | ||
451 | if (ctx->cipher->iv_len) { | |
452 | if (ctx->encrypt) | |
453 | iiv = out + inl - ctx->cipher->iv_len; | |
454 | else | |
455 | iiv = save_iv; | |
456 | memcpy(ctx->iv, iiv, ctx->cipher->iv_len); | |
457 | } | |
458 | return (1); | |
76dfca87 RL |
459 | } |
460 | ||
461 | static int | |
462 | cryptodev_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, | |
0f113f3e | 463 | const unsigned char *iv, int enc) |
76dfca87 | 464 | { |
0f113f3e MC |
465 | struct dev_crypto_state *state = ctx->cipher_data; |
466 | struct session_op *sess = &state->d_sess; | |
467 | int cipher = -1, i; | |
468 | ||
469 | for (i = 0; ciphers[i].id; i++) | |
470 | if (ctx->cipher->nid == ciphers[i].nid && | |
471 | ctx->cipher->iv_len <= ciphers[i].ivmax && | |
472 | ctx->key_len == ciphers[i].keylen) { | |
473 | cipher = ciphers[i].id; | |
474 | break; | |
475 | } | |
476 | ||
477 | if (!ciphers[i].id) { | |
478 | state->d_fd = -1; | |
479 | return (0); | |
480 | } | |
481 | ||
482 | memset(sess, 0, sizeof(struct session_op)); | |
483 | ||
484 | if ((state->d_fd = get_dev_crypto()) < 0) | |
485 | return (0); | |
486 | ||
487 | sess->key = (caddr_t) key; | |
488 | sess->keylen = ctx->key_len; | |
489 | sess->cipher = cipher; | |
490 | ||
491 | if (ioctl(state->d_fd, CIOCGSESSION, sess) == -1) { | |
492 | put_dev_crypto(state->d_fd); | |
493 | state->d_fd = -1; | |
494 | return (0); | |
495 | } | |
496 | return (1); | |
76dfca87 RL |
497 | } |
498 | ||
499 | /* | |
500 | * free anything we allocated earlier when initting a | |
501 | * session, and close the session. | |
502 | */ | |
0f113f3e | 503 | static int cryptodev_cleanup(EVP_CIPHER_CTX *ctx) |
76dfca87 | 504 | { |
0f113f3e MC |
505 | int ret = 0; |
506 | struct dev_crypto_state *state = ctx->cipher_data; | |
507 | struct session_op *sess = &state->d_sess; | |
508 | ||
509 | if (state->d_fd < 0) | |
510 | return (0); | |
511 | ||
512 | /* | |
513 | * XXX if this ioctl fails, someting's wrong. the invoker may have called | |
514 | * us with a bogus ctx, or we could have a device that for whatever | |
515 | * reason just doesn't want to play ball - it's not clear what's right | |
516 | * here - should this be an error? should it just increase a counter, | |
517 | * hmm. For right now, we return 0 - I don't believe that to be "right". | |
518 | * we could call the gorpy openssl lib error handlers that print messages | |
519 | * to users of the library. hmm.. | |
520 | */ | |
521 | ||
522 | if (ioctl(state->d_fd, CIOCFSESSION, &sess->ses) == -1) { | |
523 | ret = 0; | |
524 | } else { | |
525 | ret = 1; | |
526 | } | |
527 | put_dev_crypto(state->d_fd); | |
528 | state->d_fd = -1; | |
529 | ||
530 | return (ret); | |
76dfca87 RL |
531 | } |
532 | ||
533 | /* | |
534 | * libcrypto EVP stuff - this is how we get wired to EVP so the engine | |
535 | * gets called when libcrypto requests a cipher NID. | |
536 | */ | |
537 | ||
b53e0769 DSH |
538 | /* RC4 */ |
539 | const EVP_CIPHER cryptodev_rc4 = { | |
0f113f3e MC |
540 | NID_rc4, |
541 | 1, 16, 0, | |
542 | EVP_CIPH_VARIABLE_LENGTH, | |
543 | cryptodev_init_key, | |
544 | cryptodev_cipher, | |
545 | cryptodev_cleanup, | |
546 | sizeof(struct dev_crypto_state), | |
547 | NULL, | |
548 | NULL, | |
549 | NULL | |
b53e0769 DSH |
550 | }; |
551 | ||
76dfca87 RL |
552 | /* DES CBC EVP */ |
553 | const EVP_CIPHER cryptodev_des_cbc = { | |
0f113f3e MC |
554 | NID_des_cbc, |
555 | 8, 8, 8, | |
556 | EVP_CIPH_CBC_MODE, | |
557 | cryptodev_init_key, | |
558 | cryptodev_cipher, | |
559 | cryptodev_cleanup, | |
560 | sizeof(struct dev_crypto_state), | |
561 | EVP_CIPHER_set_asn1_iv, | |
562 | EVP_CIPHER_get_asn1_iv, | |
563 | NULL | |
76dfca87 RL |
564 | }; |
565 | ||
566 | /* 3DES CBC EVP */ | |
567 | const EVP_CIPHER cryptodev_3des_cbc = { | |
0f113f3e MC |
568 | NID_des_ede3_cbc, |
569 | 8, 24, 8, | |
570 | EVP_CIPH_CBC_MODE, | |
571 | cryptodev_init_key, | |
572 | cryptodev_cipher, | |
573 | cryptodev_cleanup, | |
574 | sizeof(struct dev_crypto_state), | |
575 | EVP_CIPHER_set_asn1_iv, | |
576 | EVP_CIPHER_get_asn1_iv, | |
577 | NULL | |
76dfca87 RL |
578 | }; |
579 | ||
580 | const EVP_CIPHER cryptodev_bf_cbc = { | |
0f113f3e MC |
581 | NID_bf_cbc, |
582 | 8, 16, 8, | |
583 | EVP_CIPH_CBC_MODE, | |
584 | cryptodev_init_key, | |
585 | cryptodev_cipher, | |
586 | cryptodev_cleanup, | |
587 | sizeof(struct dev_crypto_state), | |
588 | EVP_CIPHER_set_asn1_iv, | |
589 | EVP_CIPHER_get_asn1_iv, | |
590 | NULL | |
76dfca87 RL |
591 | }; |
592 | ||
593 | const EVP_CIPHER cryptodev_cast_cbc = { | |
0f113f3e MC |
594 | NID_cast5_cbc, |
595 | 8, 16, 8, | |
596 | EVP_CIPH_CBC_MODE, | |
597 | cryptodev_init_key, | |
598 | cryptodev_cipher, | |
599 | cryptodev_cleanup, | |
600 | sizeof(struct dev_crypto_state), | |
601 | EVP_CIPHER_set_asn1_iv, | |
602 | EVP_CIPHER_get_asn1_iv, | |
603 | NULL | |
76dfca87 RL |
604 | }; |
605 | ||
606 | const EVP_CIPHER cryptodev_aes_cbc = { | |
0f113f3e MC |
607 | NID_aes_128_cbc, |
608 | 16, 16, 16, | |
609 | EVP_CIPH_CBC_MODE, | |
610 | cryptodev_init_key, | |
611 | cryptodev_cipher, | |
612 | cryptodev_cleanup, | |
613 | sizeof(struct dev_crypto_state), | |
614 | EVP_CIPHER_set_asn1_iv, | |
615 | EVP_CIPHER_get_asn1_iv, | |
616 | NULL | |
76dfca87 RL |
617 | }; |
618 | ||
b53e0769 | 619 | const EVP_CIPHER cryptodev_aes_192_cbc = { |
0f113f3e MC |
620 | NID_aes_192_cbc, |
621 | 16, 24, 16, | |
622 | EVP_CIPH_CBC_MODE, | |
623 | cryptodev_init_key, | |
624 | cryptodev_cipher, | |
625 | cryptodev_cleanup, | |
626 | sizeof(struct dev_crypto_state), | |
627 | EVP_CIPHER_set_asn1_iv, | |
628 | EVP_CIPHER_get_asn1_iv, | |
629 | NULL | |
b53e0769 DSH |
630 | }; |
631 | ||
632 | const EVP_CIPHER cryptodev_aes_256_cbc = { | |
0f113f3e MC |
633 | NID_aes_256_cbc, |
634 | 16, 32, 16, | |
635 | EVP_CIPH_CBC_MODE, | |
636 | cryptodev_init_key, | |
637 | cryptodev_cipher, | |
638 | cryptodev_cleanup, | |
639 | sizeof(struct dev_crypto_state), | |
640 | EVP_CIPHER_set_asn1_iv, | |
641 | EVP_CIPHER_get_asn1_iv, | |
642 | NULL | |
b53e0769 | 643 | }; |
0f113f3e MC |
644 | |
645 | # ifdef CRYPTO_AES_CTR | |
be2c4d9b | 646 | const EVP_CIPHER cryptodev_aes_ctr = { |
0f113f3e MC |
647 | NID_aes_128_ctr, |
648 | 16, 16, 14, | |
649 | EVP_CIPH_CTR_MODE, | |
650 | cryptodev_init_key, | |
651 | cryptodev_cipher, | |
652 | cryptodev_cleanup, | |
653 | sizeof(struct dev_crypto_state), | |
654 | EVP_CIPHER_set_asn1_iv, | |
655 | EVP_CIPHER_get_asn1_iv, | |
656 | NULL | |
be2c4d9b KPJ |
657 | }; |
658 | ||
659 | const EVP_CIPHER cryptodev_aes_ctr_192 = { | |
0f113f3e MC |
660 | NID_aes_192_ctr, |
661 | 16, 24, 14, | |
662 | EVP_CIPH_CTR_MODE, | |
663 | cryptodev_init_key, | |
664 | cryptodev_cipher, | |
665 | cryptodev_cleanup, | |
666 | sizeof(struct dev_crypto_state), | |
667 | EVP_CIPHER_set_asn1_iv, | |
668 | EVP_CIPHER_get_asn1_iv, | |
669 | NULL | |
be2c4d9b KPJ |
670 | }; |
671 | ||
672 | const EVP_CIPHER cryptodev_aes_ctr_256 = { | |
0f113f3e MC |
673 | NID_aes_256_ctr, |
674 | 16, 32, 14, | |
675 | EVP_CIPH_CTR_MODE, | |
676 | cryptodev_init_key, | |
677 | cryptodev_cipher, | |
678 | cryptodev_cleanup, | |
679 | sizeof(struct dev_crypto_state), | |
680 | EVP_CIPHER_set_asn1_iv, | |
681 | EVP_CIPHER_get_asn1_iv, | |
682 | NULL | |
be2c4d9b | 683 | }; |
0f113f3e | 684 | # endif |
76dfca87 RL |
685 | /* |
686 | * Registered by the ENGINE when used to find out how to deal with | |
687 | * a particular NID in the ENGINE. this says what we'll do at the | |
688 | * top level - note, that list is restricted by what we answer with | |
689 | */ | |
690 | static int | |
691 | cryptodev_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher, | |
0f113f3e | 692 | const int **nids, int nid) |
76dfca87 | 693 | { |
0f113f3e MC |
694 | if (!cipher) |
695 | return (cryptodev_usable_ciphers(nids)); | |
696 | ||
697 | switch (nid) { | |
698 | case NID_rc4: | |
699 | *cipher = &cryptodev_rc4; | |
700 | break; | |
701 | case NID_des_ede3_cbc: | |
702 | *cipher = &cryptodev_3des_cbc; | |
703 | break; | |
704 | case NID_des_cbc: | |
705 | *cipher = &cryptodev_des_cbc; | |
706 | break; | |
707 | case NID_bf_cbc: | |
708 | *cipher = &cryptodev_bf_cbc; | |
709 | break; | |
710 | case NID_cast5_cbc: | |
711 | *cipher = &cryptodev_cast_cbc; | |
712 | break; | |
713 | case NID_aes_128_cbc: | |
714 | *cipher = &cryptodev_aes_cbc; | |
715 | break; | |
716 | case NID_aes_192_cbc: | |
717 | *cipher = &cryptodev_aes_192_cbc; | |
718 | break; | |
719 | case NID_aes_256_cbc: | |
720 | *cipher = &cryptodev_aes_256_cbc; | |
721 | break; | |
722 | # ifdef CRYPTO_AES_CTR | |
723 | case NID_aes_128_ctr: | |
724 | *cipher = &cryptodev_aes_ctr; | |
725 | break; | |
726 | case NID_aes_192_ctr: | |
727 | *cipher = &cryptodev_aes_ctr_192; | |
728 | break; | |
729 | case NID_aes_256_ctr: | |
730 | *cipher = &cryptodev_aes_ctr_256; | |
731 | break; | |
732 | # endif | |
733 | default: | |
734 | *cipher = NULL; | |
735 | break; | |
736 | } | |
737 | return (*cipher != NULL); | |
76dfca87 RL |
738 | } |
739 | ||
0f113f3e | 740 | # ifdef USE_CRYPTODEV_DIGESTS |
8b968750 DSH |
741 | |
742 | /* convert digest type to cryptodev */ | |
0f113f3e | 743 | static int digest_nid_to_cryptodev(int nid) |
8b968750 | 744 | { |
0f113f3e | 745 | int i; |
8b968750 | 746 | |
0f113f3e MC |
747 | for (i = 0; digests[i].id; i++) |
748 | if (digests[i].nid == nid) | |
749 | return (digests[i].id); | |
750 | return (0); | |
8b968750 DSH |
751 | } |
752 | ||
0f113f3e | 753 | static int digest_key_length(int nid) |
8b968750 | 754 | { |
0f113f3e | 755 | int i; |
8b968750 | 756 | |
0f113f3e MC |
757 | for (i = 0; digests[i].id; i++) |
758 | if (digests[i].nid == nid) | |
759 | return digests[i].keylen; | |
760 | return (0); | |
8b968750 DSH |
761 | } |
762 | ||
8b968750 DSH |
763 | static int cryptodev_digest_init(EVP_MD_CTX *ctx) |
764 | { | |
0f113f3e MC |
765 | struct dev_crypto_state *state = ctx->md_data; |
766 | struct session_op *sess = &state->d_sess; | |
767 | int digest; | |
768 | ||
769 | if ((digest = digest_nid_to_cryptodev(ctx->digest->type)) == NID_undef) { | |
770 | printf("cryptodev_digest_init: Can't get digest \n"); | |
771 | return (0); | |
772 | } | |
773 | ||
774 | memset(state, 0, sizeof(struct dev_crypto_state)); | |
775 | ||
776 | if ((state->d_fd = get_dev_crypto()) < 0) { | |
777 | printf("cryptodev_digest_init: Can't get Dev \n"); | |
778 | return (0); | |
779 | } | |
780 | ||
781 | sess->mackey = state->dummy_mac_key; | |
782 | sess->mackeylen = digest_key_length(ctx->digest->type); | |
783 | sess->mac = digest; | |
784 | ||
785 | if (ioctl(state->d_fd, CIOCGSESSION, sess) < 0) { | |
786 | put_dev_crypto(state->d_fd); | |
787 | state->d_fd = -1; | |
788 | printf("cryptodev_digest_init: Open session failed\n"); | |
789 | return (0); | |
790 | } | |
791 | ||
792 | return (1); | |
8b968750 DSH |
793 | } |
794 | ||
795 | static int cryptodev_digest_update(EVP_MD_CTX *ctx, const void *data, | |
0f113f3e | 796 | size_t count) |
8b968750 | 797 | { |
0f113f3e MC |
798 | struct crypt_op cryp; |
799 | struct dev_crypto_state *state = ctx->md_data; | |
800 | struct session_op *sess = &state->d_sess; | |
801 | char *new_mac_data; | |
802 | ||
803 | if (!data || state->d_fd < 0) { | |
804 | printf("cryptodev_digest_update: illegal inputs \n"); | |
805 | return (0); | |
806 | } | |
807 | ||
808 | if (!count) { | |
809 | return (0); | |
810 | } | |
811 | ||
812 | if (!(ctx->flags & EVP_MD_CTX_FLAG_ONESHOT)) { | |
813 | /* if application doesn't support one buffer */ | |
814 | new_mac_data = | |
815 | OPENSSL_realloc(state->mac_data, state->mac_len + count); | |
816 | ||
817 | if (!new_mac_data) { | |
818 | printf("cryptodev_digest_update: realloc failed\n"); | |
819 | return (0); | |
820 | } | |
821 | state->mac_data = new_mac_data; | |
822 | ||
823 | memcpy(state->mac_data + state->mac_len, data, count); | |
824 | state->mac_len += count; | |
825 | ||
826 | return (1); | |
827 | } | |
828 | ||
829 | memset(&cryp, 0, sizeof(cryp)); | |
830 | ||
831 | cryp.ses = sess->ses; | |
832 | cryp.flags = 0; | |
833 | cryp.len = count; | |
834 | cryp.src = (caddr_t) data; | |
835 | cryp.dst = NULL; | |
836 | cryp.mac = (caddr_t) state->digest_res; | |
837 | if (ioctl(state->d_fd, CIOCCRYPT, &cryp) < 0) { | |
838 | printf("cryptodev_digest_update: digest failed\n"); | |
839 | return (0); | |
840 | } | |
841 | return (1); | |
8b968750 DSH |
842 | } |
843 | ||
8b968750 DSH |
844 | static int cryptodev_digest_final(EVP_MD_CTX *ctx, unsigned char *md) |
845 | { | |
0f113f3e MC |
846 | struct crypt_op cryp; |
847 | struct dev_crypto_state *state = ctx->md_data; | |
848 | struct session_op *sess = &state->d_sess; | |
849 | ||
850 | int ret = 1; | |
851 | ||
852 | if (!md || state->d_fd < 0) { | |
853 | printf("cryptodev_digest_final: illegal input\n"); | |
854 | return (0); | |
855 | } | |
856 | ||
857 | if (!(ctx->flags & EVP_MD_CTX_FLAG_ONESHOT)) { | |
858 | /* if application doesn't support one buffer */ | |
859 | memset(&cryp, 0, sizeof(cryp)); | |
860 | cryp.ses = sess->ses; | |
861 | cryp.flags = 0; | |
862 | cryp.len = state->mac_len; | |
863 | cryp.src = state->mac_data; | |
864 | cryp.dst = NULL; | |
865 | cryp.mac = (caddr_t) md; | |
866 | if (ioctl(state->d_fd, CIOCCRYPT, &cryp) < 0) { | |
867 | printf("cryptodev_digest_final: digest failed\n"); | |
868 | return (0); | |
869 | } | |
870 | ||
871 | return 1; | |
872 | } | |
873 | ||
874 | memcpy(md, state->digest_res, ctx->digest->md_size); | |
875 | ||
876 | return (ret); | |
8b968750 DSH |
877 | } |
878 | ||
8b968750 DSH |
879 | static int cryptodev_digest_cleanup(EVP_MD_CTX *ctx) |
880 | { | |
0f113f3e MC |
881 | int ret = 1; |
882 | struct dev_crypto_state *state = ctx->md_data; | |
883 | struct session_op *sess = &state->d_sess; | |
884 | ||
885 | if (state == NULL) | |
886 | return 0; | |
887 | ||
888 | if (state->d_fd < 0) { | |
889 | printf("cryptodev_digest_cleanup: illegal input\n"); | |
890 | return (0); | |
891 | } | |
892 | ||
893 | if (state->mac_data) { | |
894 | OPENSSL_free(state->mac_data); | |
895 | state->mac_data = NULL; | |
896 | state->mac_len = 0; | |
897 | } | |
898 | ||
899 | if (ioctl(state->d_fd, CIOCFSESSION, &sess->ses) < 0) { | |
900 | printf("cryptodev_digest_cleanup: failed to close session\n"); | |
901 | ret = 0; | |
902 | } else { | |
903 | ret = 1; | |
904 | } | |
905 | put_dev_crypto(state->d_fd); | |
906 | state->d_fd = -1; | |
907 | ||
908 | return (ret); | |
8b968750 DSH |
909 | } |
910 | ||
0f113f3e | 911 | static int cryptodev_digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from) |
8b968750 | 912 | { |
0f113f3e MC |
913 | struct dev_crypto_state *fstate = from->md_data; |
914 | struct dev_crypto_state *dstate = to->md_data; | |
915 | struct session_op *sess; | |
916 | int digest; | |
917 | ||
918 | if (dstate == NULL || fstate == NULL) | |
919 | return 1; | |
920 | ||
921 | memcpy(dstate, fstate, sizeof(struct dev_crypto_state)); | |
922 | ||
923 | sess = &dstate->d_sess; | |
924 | ||
925 | digest = digest_nid_to_cryptodev(to->digest->type); | |
926 | ||
927 | sess->mackey = dstate->dummy_mac_key; | |
928 | sess->mackeylen = digest_key_length(to->digest->type); | |
929 | sess->mac = digest; | |
930 | ||
931 | dstate->d_fd = get_dev_crypto(); | |
932 | ||
933 | if (ioctl(dstate->d_fd, CIOCGSESSION, sess) < 0) { | |
934 | put_dev_crypto(dstate->d_fd); | |
935 | dstate->d_fd = -1; | |
936 | printf("cryptodev_digest_copy: Open session failed\n"); | |
937 | return (0); | |
938 | } | |
939 | ||
940 | if (fstate->mac_len != 0) { | |
941 | if (fstate->mac_data != NULL) { | |
942 | dstate->mac_data = OPENSSL_malloc(fstate->mac_len); | |
943 | if (dstate->mac_data == NULL) { | |
944 | printf("cryptodev_digest_copy: mac_data allocation failed\n"); | |
945 | return (0); | |
946 | } | |
947 | memcpy(dstate->mac_data, fstate->mac_data, fstate->mac_len); | |
948 | dstate->mac_len = fstate->mac_len; | |
949 | } | |
950 | } | |
951 | ||
952 | return 1; | |
8b968750 DSH |
953 | } |
954 | ||
8b968750 | 955 | const EVP_MD cryptodev_sha1 = { |
0f113f3e MC |
956 | NID_sha1, |
957 | NID_undef, | |
958 | SHA_DIGEST_LENGTH, | |
959 | EVP_MD_FLAG_ONESHOT, | |
960 | cryptodev_digest_init, | |
961 | cryptodev_digest_update, | |
962 | cryptodev_digest_final, | |
963 | cryptodev_digest_copy, | |
964 | cryptodev_digest_cleanup, | |
965 | EVP_PKEY_NULL_method, | |
966 | SHA_CBLOCK, | |
967 | sizeof(struct dev_crypto_state), | |
8b968750 DSH |
968 | }; |
969 | ||
970 | const EVP_MD cryptodev_md5 = { | |
0f113f3e MC |
971 | NID_md5, |
972 | NID_undef, | |
973 | 16 /* MD5_DIGEST_LENGTH */ , | |
974 | EVP_MD_FLAG_ONESHOT, | |
975 | cryptodev_digest_init, | |
976 | cryptodev_digest_update, | |
977 | cryptodev_digest_final, | |
978 | cryptodev_digest_copy, | |
979 | cryptodev_digest_cleanup, | |
980 | EVP_PKEY_NULL_method, | |
981 | 64 /* MD5_CBLOCK */ , | |
982 | sizeof(struct dev_crypto_state), | |
8b968750 DSH |
983 | }; |
984 | ||
0f113f3e | 985 | # endif /* USE_CRYPTODEV_DIGESTS */ |
8b968750 | 986 | |
76dfca87 RL |
987 | static int |
988 | cryptodev_engine_digests(ENGINE *e, const EVP_MD **digest, | |
0f113f3e | 989 | const int **nids, int nid) |
76dfca87 | 990 | { |
0f113f3e MC |
991 | if (!digest) |
992 | return (cryptodev_usable_digests(nids)); | |
993 | ||
994 | switch (nid) { | |
995 | # ifdef USE_CRYPTODEV_DIGESTS | |
996 | case NID_md5: | |
997 | *digest = &cryptodev_md5; | |
998 | break; | |
999 | case NID_sha1: | |
1000 | *digest = &cryptodev_sha1; | |
1001 | break; | |
1002 | default: | |
1003 | # endif /* USE_CRYPTODEV_DIGESTS */ | |
1004 | *digest = NULL; | |
1005 | break; | |
1006 | } | |
1007 | return (*digest != NULL); | |
76dfca87 RL |
1008 | } |
1009 | ||
1010 | /* | |
1011 | * Convert a BIGNUM to the representation that /dev/crypto needs. | |
1012 | * Upon completion of use, the caller is responsible for freeing | |
1013 | * crp->crp_p. | |
1014 | */ | |
0f113f3e | 1015 | static int bn2crparam(const BIGNUM *a, struct crparam *crp) |
76dfca87 | 1016 | { |
0f113f3e MC |
1017 | int i, j, k; |
1018 | ssize_t bytes, bits; | |
1019 | u_char *b; | |
1020 | ||
1021 | crp->crp_p = NULL; | |
1022 | crp->crp_nbits = 0; | |
1023 | ||
1024 | bits = BN_num_bits(a); | |
1025 | bytes = (bits + 7) / 8; | |
1026 | ||
1027 | b = malloc(bytes); | |
1028 | if (b == NULL) | |
1029 | return (1); | |
1030 | memset(b, 0, bytes); | |
1031 | ||
1032 | crp->crp_p = (caddr_t) b; | |
1033 | crp->crp_nbits = bits; | |
1034 | ||
1035 | for (i = 0, j = 0; i < a->top; i++) { | |
1036 | for (k = 0; k < BN_BITS2 / 8; k++) { | |
1037 | if ((j + k) >= bytes) | |
1038 | return (0); | |
1039 | b[j + k] = a->d[i] >> (k * 8); | |
1040 | } | |
1041 | j += BN_BITS2 / 8; | |
1042 | } | |
1043 | return (0); | |
76dfca87 RL |
1044 | } |
1045 | ||
1046 | /* Convert a /dev/crypto parameter to a BIGNUM */ | |
0f113f3e | 1047 | static int crparam2bn(struct crparam *crp, BIGNUM *a) |
76dfca87 | 1048 | { |
0f113f3e MC |
1049 | u_int8_t *pd; |
1050 | int i, bytes; | |
76dfca87 | 1051 | |
0f113f3e | 1052 | bytes = (crp->crp_nbits + 7) / 8; |
76dfca87 | 1053 | |
0f113f3e MC |
1054 | if (bytes == 0) |
1055 | return (-1); | |
76dfca87 | 1056 | |
0f113f3e MC |
1057 | if ((pd = (u_int8_t *) malloc(bytes)) == NULL) |
1058 | return (-1); | |
76dfca87 | 1059 | |
0f113f3e MC |
1060 | for (i = 0; i < bytes; i++) |
1061 | pd[i] = crp->crp_p[bytes - i - 1]; | |
76dfca87 | 1062 | |
0f113f3e MC |
1063 | BN_bin2bn(pd, bytes, a); |
1064 | free(pd); | |
76dfca87 | 1065 | |
0f113f3e | 1066 | return (0); |
76dfca87 RL |
1067 | } |
1068 | ||
0f113f3e | 1069 | static void zapparams(struct crypt_kop *kop) |
76dfca87 | 1070 | { |
0f113f3e MC |
1071 | int i; |
1072 | ||
1073 | for (i = 0; i < kop->crk_iparams + kop->crk_oparams; i++) { | |
1074 | if (kop->crk_param[i].crp_p) | |
1075 | free(kop->crk_param[i].crp_p); | |
1076 | kop->crk_param[i].crp_p = NULL; | |
1077 | kop->crk_param[i].crp_nbits = 0; | |
1078 | } | |
76dfca87 RL |
1079 | } |
1080 | ||
1081 | static int | |
0f113f3e MC |
1082 | cryptodev_asym(struct crypt_kop *kop, int rlen, BIGNUM *r, int slen, |
1083 | BIGNUM *s) | |
76dfca87 | 1084 | { |
0f113f3e MC |
1085 | int fd, ret = -1; |
1086 | ||
1087 | if ((fd = get_asym_dev_crypto()) < 0) | |
1088 | return (ret); | |
1089 | ||
1090 | if (r) { | |
1091 | kop->crk_param[kop->crk_iparams].crp_p = calloc(rlen, sizeof(char)); | |
1092 | kop->crk_param[kop->crk_iparams].crp_nbits = rlen * 8; | |
1093 | kop->crk_oparams++; | |
1094 | } | |
1095 | if (s) { | |
1096 | kop->crk_param[kop->crk_iparams + 1].crp_p = | |
1097 | calloc(slen, sizeof(char)); | |
1098 | kop->crk_param[kop->crk_iparams + 1].crp_nbits = slen * 8; | |
1099 | kop->crk_oparams++; | |
1100 | } | |
1101 | ||
1102 | if (ioctl(fd, CIOCKEY, kop) == 0) { | |
1103 | if (r) | |
1104 | crparam2bn(&kop->crk_param[kop->crk_iparams], r); | |
1105 | if (s) | |
1106 | crparam2bn(&kop->crk_param[kop->crk_iparams + 1], s); | |
1107 | ret = 0; | |
1108 | } | |
1109 | ||
1110 | return (ret); | |
76dfca87 RL |
1111 | } |
1112 | ||
1113 | static int | |
1114 | cryptodev_bn_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, | |
0f113f3e | 1115 | const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont) |
76dfca87 | 1116 | { |
0f113f3e MC |
1117 | struct crypt_kop kop; |
1118 | int ret = 1; | |
1119 | ||
1120 | /* | |
1121 | * Currently, we know we can do mod exp iff we can do any asymmetric | |
1122 | * operations at all. | |
1123 | */ | |
1124 | if (cryptodev_asymfeat == 0) { | |
1125 | ret = BN_mod_exp(r, a, p, m, ctx); | |
1126 | return (ret); | |
1127 | } | |
1128 | ||
1129 | memset(&kop, 0, sizeof kop); | |
1130 | kop.crk_op = CRK_MOD_EXP; | |
1131 | ||
1132 | /* inputs: a^p % m */ | |
1133 | if (bn2crparam(a, &kop.crk_param[0])) | |
1134 | goto err; | |
1135 | if (bn2crparam(p, &kop.crk_param[1])) | |
1136 | goto err; | |
1137 | if (bn2crparam(m, &kop.crk_param[2])) | |
1138 | goto err; | |
1139 | kop.crk_iparams = 3; | |
1140 | ||
1141 | if (cryptodev_asym(&kop, BN_num_bytes(m), r, 0, NULL)) { | |
1142 | const RSA_METHOD *meth = RSA_PKCS1_SSLeay(); | |
1143 | printf("OCF asym process failed, Running in software\n"); | |
1144 | ret = meth->bn_mod_exp(r, a, p, m, ctx, in_mont); | |
1145 | ||
1146 | } else if (ECANCELED == kop.crk_status) { | |
1147 | const RSA_METHOD *meth = RSA_PKCS1_SSLeay(); | |
1148 | printf("OCF hardware operation cancelled. Running in Software\n"); | |
1149 | ret = meth->bn_mod_exp(r, a, p, m, ctx, in_mont); | |
1150 | } | |
1151 | /* else cryptodev operation worked ok ==> ret = 1 */ | |
1152 | ||
1153 | err: | |
1154 | zapparams(&kop); | |
1155 | return (ret); | |
76dfca87 RL |
1156 | } |
1157 | ||
1158 | static int | |
0f113f3e MC |
1159 | cryptodev_rsa_nocrt_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, |
1160 | BN_CTX *ctx) | |
76dfca87 | 1161 | { |
0f113f3e MC |
1162 | int r; |
1163 | ctx = BN_CTX_new(); | |
1164 | r = cryptodev_bn_mod_exp(r0, I, rsa->d, rsa->n, ctx, NULL); | |
1165 | BN_CTX_free(ctx); | |
1166 | return (r); | |
76dfca87 RL |
1167 | } |
1168 | ||
1169 | static int | |
ea77fc33 | 1170 | cryptodev_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) |
76dfca87 | 1171 | { |
0f113f3e MC |
1172 | struct crypt_kop kop; |
1173 | int ret = 1; | |
1174 | ||
1175 | if (!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp) { | |
1176 | /* XXX 0 means failure?? */ | |
1177 | return (0); | |
1178 | } | |
1179 | ||
1180 | memset(&kop, 0, sizeof kop); | |
1181 | kop.crk_op = CRK_MOD_EXP_CRT; | |
1182 | /* inputs: rsa->p rsa->q I rsa->dmp1 rsa->dmq1 rsa->iqmp */ | |
1183 | if (bn2crparam(rsa->p, &kop.crk_param[0])) | |
1184 | goto err; | |
1185 | if (bn2crparam(rsa->q, &kop.crk_param[1])) | |
1186 | goto err; | |
1187 | if (bn2crparam(I, &kop.crk_param[2])) | |
1188 | goto err; | |
1189 | if (bn2crparam(rsa->dmp1, &kop.crk_param[3])) | |
1190 | goto err; | |
1191 | if (bn2crparam(rsa->dmq1, &kop.crk_param[4])) | |
1192 | goto err; | |
1193 | if (bn2crparam(rsa->iqmp, &kop.crk_param[5])) | |
1194 | goto err; | |
1195 | kop.crk_iparams = 6; | |
1196 | ||
1197 | if (cryptodev_asym(&kop, BN_num_bytes(rsa->n), r0, 0, NULL)) { | |
1198 | const RSA_METHOD *meth = RSA_PKCS1_SSLeay(); | |
1199 | printf("OCF asym process failed, running in Software\n"); | |
1200 | ret = (*meth->rsa_mod_exp) (r0, I, rsa, ctx); | |
1201 | ||
1202 | } else if (ECANCELED == kop.crk_status) { | |
1203 | const RSA_METHOD *meth = RSA_PKCS1_SSLeay(); | |
1204 | printf("OCF hardware operation cancelled. Running in Software\n"); | |
1205 | ret = (*meth->rsa_mod_exp) (r0, I, rsa, ctx); | |
1206 | } | |
1207 | /* else cryptodev operation worked ok ==> ret = 1 */ | |
1208 | ||
1209 | err: | |
1210 | zapparams(&kop); | |
1211 | return (ret); | |
76dfca87 RL |
1212 | } |
1213 | ||
1214 | static RSA_METHOD cryptodev_rsa = { | |
0f113f3e MC |
1215 | "cryptodev RSA method", |
1216 | NULL, /* rsa_pub_enc */ | |
1217 | NULL, /* rsa_pub_dec */ | |
1218 | NULL, /* rsa_priv_enc */ | |
1219 | NULL, /* rsa_priv_dec */ | |
1220 | NULL, | |
1221 | NULL, | |
1222 | NULL, /* init */ | |
1223 | NULL, /* finish */ | |
1224 | 0, /* flags */ | |
1225 | NULL, /* app_data */ | |
1226 | NULL, /* rsa_sign */ | |
1227 | NULL /* rsa_verify */ | |
76dfca87 RL |
1228 | }; |
1229 | ||
1230 | static int | |
1231 | cryptodev_dsa_bn_mod_exp(DSA *dsa, BIGNUM *r, BIGNUM *a, const BIGNUM *p, | |
0f113f3e | 1232 | const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) |
76dfca87 | 1233 | { |
0f113f3e | 1234 | return (cryptodev_bn_mod_exp(r, a, p, m, ctx, m_ctx)); |
76dfca87 RL |
1235 | } |
1236 | ||
1237 | static int | |
1238 | cryptodev_dsa_dsa_mod_exp(DSA *dsa, BIGNUM *t1, BIGNUM *g, | |
0f113f3e MC |
1239 | BIGNUM *u1, BIGNUM *pub_key, BIGNUM *u2, BIGNUM *p, |
1240 | BN_CTX *ctx, BN_MONT_CTX *mont) | |
76dfca87 | 1241 | { |
0f113f3e MC |
1242 | BIGNUM t2; |
1243 | int ret = 0; | |
76dfca87 | 1244 | |
0f113f3e | 1245 | BN_init(&t2); |
76dfca87 | 1246 | |
0f113f3e MC |
1247 | /* v = ( g^u1 * y^u2 mod p ) mod q */ |
1248 | /* let t1 = g ^ u1 mod p */ | |
1249 | ret = 0; | |
76dfca87 | 1250 | |
0f113f3e MC |
1251 | if (!dsa->meth->bn_mod_exp(dsa, t1, dsa->g, u1, dsa->p, ctx, mont)) |
1252 | goto err; | |
76dfca87 | 1253 | |
0f113f3e MC |
1254 | /* let t2 = y ^ u2 mod p */ |
1255 | if (!dsa->meth->bn_mod_exp(dsa, &t2, dsa->pub_key, u2, dsa->p, ctx, mont)) | |
1256 | goto err; | |
1257 | /* let u1 = t1 * t2 mod p */ | |
1258 | if (!BN_mod_mul(u1, t1, &t2, dsa->p, ctx)) | |
1259 | goto err; | |
76dfca87 | 1260 | |
0f113f3e | 1261 | BN_copy(t1, u1); |
76dfca87 | 1262 | |
0f113f3e MC |
1263 | ret = 1; |
1264 | err: | |
1265 | BN_free(&t2); | |
1266 | return (ret); | |
76dfca87 RL |
1267 | } |
1268 | ||
0f113f3e MC |
1269 | static DSA_SIG *cryptodev_dsa_do_sign(const unsigned char *dgst, int dlen, |
1270 | DSA *dsa) | |
76dfca87 | 1271 | { |
0f113f3e MC |
1272 | struct crypt_kop kop; |
1273 | BIGNUM *r = NULL, *s = NULL; | |
1274 | DSA_SIG *dsaret = NULL; | |
1275 | ||
1276 | if ((r = BN_new()) == NULL) | |
1277 | goto err; | |
1278 | if ((s = BN_new()) == NULL) { | |
1279 | BN_free(r); | |
1280 | goto err; | |
1281 | } | |
1282 | ||
1283 | memset(&kop, 0, sizeof kop); | |
1284 | kop.crk_op = CRK_DSA_SIGN; | |
1285 | ||
1286 | /* inputs: dgst dsa->p dsa->q dsa->g dsa->priv_key */ | |
1287 | kop.crk_param[0].crp_p = (caddr_t) dgst; | |
1288 | kop.crk_param[0].crp_nbits = dlen * 8; | |
1289 | if (bn2crparam(dsa->p, &kop.crk_param[1])) | |
1290 | goto err; | |
1291 | if (bn2crparam(dsa->q, &kop.crk_param[2])) | |
1292 | goto err; | |
1293 | if (bn2crparam(dsa->g, &kop.crk_param[3])) | |
1294 | goto err; | |
1295 | if (bn2crparam(dsa->priv_key, &kop.crk_param[4])) | |
1296 | goto err; | |
1297 | kop.crk_iparams = 5; | |
1298 | ||
1299 | if (cryptodev_asym(&kop, BN_num_bytes(dsa->q), r, | |
1300 | BN_num_bytes(dsa->q), s) == 0) { | |
1301 | dsaret = DSA_SIG_new(); | |
1302 | dsaret->r = r; | |
1303 | dsaret->s = s; | |
1304 | } else { | |
1305 | const DSA_METHOD *meth = DSA_OpenSSL(); | |
1306 | BN_free(r); | |
1307 | BN_free(s); | |
1308 | dsaret = (meth->dsa_do_sign) (dgst, dlen, dsa); | |
1309 | } | |
1310 | err: | |
1311 | kop.crk_param[0].crp_p = NULL; | |
1312 | zapparams(&kop); | |
1313 | return (dsaret); | |
76dfca87 RL |
1314 | } |
1315 | ||
1316 | static int | |
1317 | cryptodev_dsa_verify(const unsigned char *dgst, int dlen, | |
0f113f3e | 1318 | DSA_SIG *sig, DSA *dsa) |
76dfca87 | 1319 | { |
0f113f3e MC |
1320 | struct crypt_kop kop; |
1321 | int dsaret = 1; | |
1322 | ||
1323 | memset(&kop, 0, sizeof kop); | |
1324 | kop.crk_op = CRK_DSA_VERIFY; | |
1325 | ||
1326 | /* inputs: dgst dsa->p dsa->q dsa->g dsa->pub_key sig->r sig->s */ | |
1327 | kop.crk_param[0].crp_p = (caddr_t) dgst; | |
1328 | kop.crk_param[0].crp_nbits = dlen * 8; | |
1329 | if (bn2crparam(dsa->p, &kop.crk_param[1])) | |
1330 | goto err; | |
1331 | if (bn2crparam(dsa->q, &kop.crk_param[2])) | |
1332 | goto err; | |
1333 | if (bn2crparam(dsa->g, &kop.crk_param[3])) | |
1334 | goto err; | |
1335 | if (bn2crparam(dsa->pub_key, &kop.crk_param[4])) | |
1336 | goto err; | |
1337 | if (bn2crparam(sig->r, &kop.crk_param[5])) | |
1338 | goto err; | |
1339 | if (bn2crparam(sig->s, &kop.crk_param[6])) | |
1340 | goto err; | |
1341 | kop.crk_iparams = 7; | |
1342 | ||
1343 | if (cryptodev_asym(&kop, 0, NULL, 0, NULL) == 0) { | |
1344 | /* | |
1345 | * OCF success value is 0, if not zero, change dsaret to fail | |
1346 | */ | |
1347 | if (0 != kop.crk_status) | |
1348 | dsaret = 0; | |
1349 | } else { | |
1350 | const DSA_METHOD *meth = DSA_OpenSSL(); | |
1351 | ||
1352 | dsaret = (meth->dsa_do_verify) (dgst, dlen, sig, dsa); | |
1353 | } | |
1354 | err: | |
1355 | kop.crk_param[0].crp_p = NULL; | |
1356 | zapparams(&kop); | |
1357 | return (dsaret); | |
76dfca87 RL |
1358 | } |
1359 | ||
1360 | static DSA_METHOD cryptodev_dsa = { | |
0f113f3e MC |
1361 | "cryptodev DSA method", |
1362 | NULL, | |
1363 | NULL, /* dsa_sign_setup */ | |
1364 | NULL, | |
1365 | NULL, /* dsa_mod_exp */ | |
1366 | NULL, | |
1367 | NULL, /* init */ | |
1368 | NULL, /* finish */ | |
1369 | 0, /* flags */ | |
1370 | NULL /* app_data */ | |
76dfca87 RL |
1371 | }; |
1372 | ||
1373 | static int | |
1374 | cryptodev_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a, | |
0f113f3e MC |
1375 | const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, |
1376 | BN_MONT_CTX *m_ctx) | |
76dfca87 | 1377 | { |
0f113f3e | 1378 | return (cryptodev_bn_mod_exp(r, a, p, m, ctx, m_ctx)); |
76dfca87 RL |
1379 | } |
1380 | ||
1381 | static int | |
1382 | cryptodev_dh_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh) | |
1383 | { | |
0f113f3e MC |
1384 | struct crypt_kop kop; |
1385 | int dhret = 1; | |
1386 | int fd, keylen; | |
1387 | ||
1388 | if ((fd = get_asym_dev_crypto()) < 0) { | |
1389 | const DH_METHOD *meth = DH_OpenSSL(); | |
1390 | ||
1391 | return ((meth->compute_key) (key, pub_key, dh)); | |
1392 | } | |
1393 | ||
1394 | keylen = BN_num_bits(dh->p); | |
1395 | ||
1396 | memset(&kop, 0, sizeof kop); | |
1397 | kop.crk_op = CRK_DH_COMPUTE_KEY; | |
1398 | ||
1399 | /* inputs: dh->priv_key pub_key dh->p key */ | |
1400 | if (bn2crparam(dh->priv_key, &kop.crk_param[0])) | |
1401 | goto err; | |
1402 | if (bn2crparam(pub_key, &kop.crk_param[1])) | |
1403 | goto err; | |
1404 | if (bn2crparam(dh->p, &kop.crk_param[2])) | |
1405 | goto err; | |
1406 | kop.crk_iparams = 3; | |
1407 | ||
1408 | kop.crk_param[3].crp_p = (caddr_t) key; | |
1409 | kop.crk_param[3].crp_nbits = keylen * 8; | |
1410 | kop.crk_oparams = 1; | |
1411 | ||
1412 | if (ioctl(fd, CIOCKEY, &kop) == -1) { | |
1413 | const DH_METHOD *meth = DH_OpenSSL(); | |
1414 | ||
1415 | dhret = (meth->compute_key) (key, pub_key, dh); | |
1416 | } | |
1417 | err: | |
1418 | kop.crk_param[3].crp_p = NULL; | |
1419 | zapparams(&kop); | |
1420 | return (dhret); | |
76dfca87 RL |
1421 | } |
1422 | ||
1423 | static DH_METHOD cryptodev_dh = { | |
0f113f3e MC |
1424 | "cryptodev DH method", |
1425 | NULL, /* cryptodev_dh_generate_key */ | |
1426 | NULL, | |
1427 | NULL, | |
1428 | NULL, | |
1429 | NULL, | |
1430 | 0, /* flags */ | |
1431 | NULL /* app_data */ | |
76dfca87 RL |
1432 | }; |
1433 | ||
1434 | /* | |
1435 | * ctrl right now is just a wrapper that doesn't do much | |
1436 | * but I expect we'll want some options soon. | |
1437 | */ | |
1438 | static int | |
0f113f3e | 1439 | cryptodev_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void)) |
76dfca87 | 1440 | { |
0f113f3e MC |
1441 | # ifdef HAVE_SYSLOG_R |
1442 | struct syslog_data sd = SYSLOG_DATA_INIT; | |
1443 | # endif | |
76dfca87 | 1444 | |
0f113f3e MC |
1445 | switch (cmd) { |
1446 | default: | |
1447 | # ifdef HAVE_SYSLOG_R | |
1448 | syslog_r(LOG_ERR, &sd, "cryptodev_ctrl: unknown command %d", cmd); | |
1449 | # else | |
1450 | syslog(LOG_ERR, "cryptodev_ctrl: unknown command %d", cmd); | |
1451 | # endif | |
1452 | break; | |
1453 | } | |
1454 | return (1); | |
76dfca87 RL |
1455 | } |
1456 | ||
0f113f3e | 1457 | void ENGINE_load_cryptodev(void) |
76dfca87 | 1458 | { |
0f113f3e MC |
1459 | ENGINE *engine = ENGINE_new(); |
1460 | int fd; | |
1461 | ||
1462 | if (engine == NULL) | |
1463 | return; | |
1464 | if ((fd = get_dev_crypto()) < 0) { | |
1465 | ENGINE_free(engine); | |
1466 | return; | |
1467 | } | |
1468 | ||
1469 | /* | |
1470 | * find out what asymmetric crypto algorithms we support | |
1471 | */ | |
1472 | if (ioctl(fd, CIOCASYMFEAT, &cryptodev_asymfeat) == -1) { | |
1473 | put_dev_crypto(fd); | |
1474 | ENGINE_free(engine); | |
1475 | return; | |
1476 | } | |
1477 | put_dev_crypto(fd); | |
1478 | ||
1479 | if (!ENGINE_set_id(engine, "cryptodev") || | |
1480 | !ENGINE_set_name(engine, "BSD cryptodev engine") || | |
1481 | !ENGINE_set_ciphers(engine, cryptodev_engine_ciphers) || | |
1482 | !ENGINE_set_digests(engine, cryptodev_engine_digests) || | |
1483 | !ENGINE_set_ctrl_function(engine, cryptodev_ctrl) || | |
1484 | !ENGINE_set_cmd_defns(engine, cryptodev_defns)) { | |
1485 | ENGINE_free(engine); | |
1486 | return; | |
1487 | } | |
1488 | ||
1489 | if (ENGINE_set_RSA(engine, &cryptodev_rsa)) { | |
1490 | const RSA_METHOD *rsa_meth = RSA_PKCS1_SSLeay(); | |
1491 | ||
1492 | cryptodev_rsa.bn_mod_exp = rsa_meth->bn_mod_exp; | |
1493 | cryptodev_rsa.rsa_mod_exp = rsa_meth->rsa_mod_exp; | |
1494 | cryptodev_rsa.rsa_pub_enc = rsa_meth->rsa_pub_enc; | |
1495 | cryptodev_rsa.rsa_pub_dec = rsa_meth->rsa_pub_dec; | |
1496 | cryptodev_rsa.rsa_priv_enc = rsa_meth->rsa_priv_enc; | |
1497 | cryptodev_rsa.rsa_priv_dec = rsa_meth->rsa_priv_dec; | |
1498 | if (cryptodev_asymfeat & CRF_MOD_EXP) { | |
1499 | cryptodev_rsa.bn_mod_exp = cryptodev_bn_mod_exp; | |
1500 | if (cryptodev_asymfeat & CRF_MOD_EXP_CRT) | |
1501 | cryptodev_rsa.rsa_mod_exp = cryptodev_rsa_mod_exp; | |
1502 | else | |
1503 | cryptodev_rsa.rsa_mod_exp = cryptodev_rsa_nocrt_mod_exp; | |
1504 | } | |
1505 | } | |
1506 | ||
1507 | if (ENGINE_set_DSA(engine, &cryptodev_dsa)) { | |
1508 | const DSA_METHOD *meth = DSA_OpenSSL(); | |
1509 | ||
1510 | memcpy(&cryptodev_dsa, meth, sizeof(DSA_METHOD)); | |
1511 | if (cryptodev_asymfeat & CRF_DSA_SIGN) | |
1512 | cryptodev_dsa.dsa_do_sign = cryptodev_dsa_do_sign; | |
1513 | if (cryptodev_asymfeat & CRF_MOD_EXP) { | |
1514 | cryptodev_dsa.bn_mod_exp = cryptodev_dsa_bn_mod_exp; | |
1515 | cryptodev_dsa.dsa_mod_exp = cryptodev_dsa_dsa_mod_exp; | |
1516 | } | |
1517 | if (cryptodev_asymfeat & CRF_DSA_VERIFY) | |
1518 | cryptodev_dsa.dsa_do_verify = cryptodev_dsa_verify; | |
1519 | } | |
1520 | ||
1521 | if (ENGINE_set_DH(engine, &cryptodev_dh)) { | |
1522 | const DH_METHOD *dh_meth = DH_OpenSSL(); | |
1523 | ||
1524 | cryptodev_dh.generate_key = dh_meth->generate_key; | |
1525 | cryptodev_dh.compute_key = dh_meth->compute_key; | |
1526 | cryptodev_dh.bn_mod_exp = dh_meth->bn_mod_exp; | |
1527 | if (cryptodev_asymfeat & CRF_MOD_EXP) { | |
1528 | cryptodev_dh.bn_mod_exp = cryptodev_mod_exp_dh; | |
1529 | if (cryptodev_asymfeat & CRF_DH_COMPUTE_KEY) | |
1530 | cryptodev_dh.compute_key = cryptodev_dh_compute_key; | |
1531 | } | |
1532 | } | |
1533 | ||
1534 | ENGINE_add(engine); | |
1535 | ENGINE_free(engine); | |
1536 | ERR_clear_error(); | |
76dfca87 RL |
1537 | } |
1538 | ||
0f113f3e | 1539 | #endif /* HAVE_CRYPTODEV */ |