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