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