|
1 /* Written by Ben Laurie, 2001 */ |
|
2 /* |
|
3 * Copyright (c) 2001 The OpenSSL Project. All rights reserved. |
|
4 * |
|
5 * Redistribution and use in source and binary forms, with or without |
|
6 * modification, are permitted provided that the following conditions |
|
7 * are met: |
|
8 * |
|
9 * 1. Redistributions of source code must retain the above copyright |
|
10 * notice, this list of conditions and the following disclaimer. |
|
11 * |
|
12 * 2. Redistributions in binary form must reproduce the above copyright |
|
13 * notice, this list of conditions and the following disclaimer in |
|
14 * the documentation and/or other materials provided with the |
|
15 * distribution. |
|
16 * |
|
17 * 3. All advertising materials mentioning features or use of this |
|
18 * software must display the following acknowledgment: |
|
19 * "This product includes software developed by the OpenSSL Project |
|
20 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" |
|
21 * |
|
22 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to |
|
23 * endorse or promote products derived from this software without |
|
24 * prior written permission. For written permission, please contact |
|
25 * openssl-core@openssl.org. |
|
26 * |
|
27 * 5. Products derived from this software may not be called "OpenSSL" |
|
28 * nor may "OpenSSL" appear in their names without prior written |
|
29 * permission of the OpenSSL Project. |
|
30 * |
|
31 * 6. Redistributions of any form whatsoever must retain the following |
|
32 * acknowledgment: |
|
33 * "This product includes software developed by the OpenSSL Project |
|
34 * for use in the OpenSSL Toolkit (http://www.openssl.org/)" |
|
35 * |
|
36 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY |
|
37 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
39 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR |
|
40 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
|
42 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
|
43 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|
44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
|
45 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
46 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
|
47 * OF THE POSSIBILITY OF SUCH DAMAGE. |
|
48 */ |
|
49 |
|
50 #include <openssl/evp.h> |
|
51 #include <openssl/objects.h> |
|
52 #include <openssl/rsa.h> |
|
53 #include "evp_locl.h" |
|
54 |
|
55 /* This stuff should now all be supported through |
|
56 * crypto/engine/hw_openbsd_dev_crypto.c unless I botched it up */ |
|
57 static void *dummy=&dummy; |
|
58 |
|
59 #if 0 |
|
60 |
|
61 /* check flag after OpenSSL headers to ensure make depend works */ |
|
62 #ifdef OPENSSL_OPENBSD_DEV_CRYPTO |
|
63 |
|
64 #include <fcntl.h> |
|
65 #include <stdio.h> |
|
66 #include <errno.h> |
|
67 #include <sys/ioctl.h> |
|
68 #include <crypto/cryptodev.h> |
|
69 #include <unistd.h> |
|
70 #include <assert.h> |
|
71 |
|
72 /* longest key supported in hardware */ |
|
73 #define MAX_HW_KEY 24 |
|
74 #define MAX_HW_IV 8 |
|
75 |
|
76 #define MD5_DIGEST_LENGTH 16 |
|
77 #define MD5_CBLOCK 64 |
|
78 |
|
79 static int fd; |
|
80 static int dev_failed; |
|
81 |
|
82 typedef struct session_op session_op; |
|
83 |
|
84 #define CDATA(ctx) EVP_C_DATA(session_op,ctx) |
|
85 |
|
86 static void err(const char *str) |
|
87 { |
|
88 fprintf(stderr,"%s: errno %d\n",str,errno); |
|
89 } |
|
90 |
|
91 static int dev_crypto_init(session_op *ses) |
|
92 { |
|
93 if(dev_failed) |
|
94 return 0; |
|
95 if(!fd) |
|
96 { |
|
97 int cryptodev_fd; |
|
98 |
|
99 if ((cryptodev_fd=open("/dev/crypto",O_RDWR,0)) < 0) |
|
100 { |
|
101 err("/dev/crypto"); |
|
102 dev_failed=1; |
|
103 return 0; |
|
104 } |
|
105 if (ioctl(cryptodev_fd,CRIOGET,&fd) == -1) |
|
106 { |
|
107 err("CRIOGET failed"); |
|
108 close(cryptodev_fd); |
|
109 dev_failed=1; |
|
110 return 0; |
|
111 } |
|
112 close(cryptodev_fd); |
|
113 } |
|
114 assert(ses); |
|
115 memset(ses,'\0',sizeof *ses); |
|
116 |
|
117 return 1; |
|
118 } |
|
119 |
|
120 static int dev_crypto_cleanup(EVP_CIPHER_CTX *ctx) |
|
121 { |
|
122 if(ioctl(fd,CIOCFSESSION,&CDATA(ctx)->ses) == -1) |
|
123 err("CIOCFSESSION failed"); |
|
124 |
|
125 OPENSSL_free(CDATA(ctx)->key); |
|
126 |
|
127 return 1; |
|
128 } |
|
129 |
|
130 static int dev_crypto_init_key(EVP_CIPHER_CTX *ctx,int cipher, |
|
131 const unsigned char *key,int klen) |
|
132 { |
|
133 if(!dev_crypto_init(CDATA(ctx))) |
|
134 return 0; |
|
135 |
|
136 CDATA(ctx)->key=OPENSSL_malloc(MAX_HW_KEY); |
|
137 |
|
138 assert(ctx->cipher->iv_len <= MAX_HW_IV); |
|
139 |
|
140 memcpy(CDATA(ctx)->key,key,klen); |
|
141 |
|
142 CDATA(ctx)->cipher=cipher; |
|
143 CDATA(ctx)->keylen=klen; |
|
144 |
|
145 if (ioctl(fd,CIOCGSESSION,CDATA(ctx)) == -1) |
|
146 { |
|
147 err("CIOCGSESSION failed"); |
|
148 return 0; |
|
149 } |
|
150 return 1; |
|
151 } |
|
152 |
|
153 static int dev_crypto_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out, |
|
154 const unsigned char *in,unsigned int inl) |
|
155 { |
|
156 struct crypt_op cryp; |
|
157 unsigned char lb[MAX_HW_IV]; |
|
158 |
|
159 if(!inl) |
|
160 return 1; |
|
161 |
|
162 assert(CDATA(ctx)); |
|
163 assert(!dev_failed); |
|
164 |
|
165 memset(&cryp,'\0',sizeof cryp); |
|
166 cryp.ses=CDATA(ctx)->ses; |
|
167 cryp.op=ctx->encrypt ? COP_ENCRYPT : COP_DECRYPT; |
|
168 cryp.flags=0; |
|
169 cryp.len=inl; |
|
170 assert((inl&(ctx->cipher->block_size-1)) == 0); |
|
171 cryp.src=(caddr_t)in; |
|
172 cryp.dst=(caddr_t)out; |
|
173 cryp.mac=0; |
|
174 if(ctx->cipher->iv_len) |
|
175 cryp.iv=(caddr_t)ctx->iv; |
|
176 |
|
177 if(!ctx->encrypt) |
|
178 memcpy(lb,&in[cryp.len-ctx->cipher->iv_len],ctx->cipher->iv_len); |
|
179 |
|
180 if(ioctl(fd, CIOCCRYPT, &cryp) == -1) |
|
181 { |
|
182 if(errno == EINVAL) /* buffers are misaligned */ |
|
183 { |
|
184 unsigned int cinl=0; |
|
185 char *cin=NULL; |
|
186 char *cout=NULL; |
|
187 |
|
188 /* NB: this can only make cinl != inl with stream ciphers */ |
|
189 cinl=(inl+3)/4*4; |
|
190 |
|
191 if(((unsigned long)in&3) || cinl != inl) |
|
192 { |
|
193 cin=OPENSSL_malloc(cinl); |
|
194 memcpy(cin,in,inl); |
|
195 cryp.src=cin; |
|
196 } |
|
197 |
|
198 if(((unsigned long)out&3) || cinl != inl) |
|
199 { |
|
200 cout=OPENSSL_malloc(cinl); |
|
201 cryp.dst=cout; |
|
202 } |
|
203 |
|
204 cryp.len=cinl; |
|
205 |
|
206 if(ioctl(fd, CIOCCRYPT, &cryp) == -1) |
|
207 { |
|
208 err("CIOCCRYPT(2) failed"); |
|
209 printf("src=%p dst=%p\n",cryp.src,cryp.dst); |
|
210 abort(); |
|
211 return 0; |
|
212 } |
|
213 |
|
214 if(cout) |
|
215 { |
|
216 memcpy(out,cout,inl); |
|
217 OPENSSL_free(cout); |
|
218 } |
|
219 if(cin) |
|
220 OPENSSL_free(cin); |
|
221 } |
|
222 else |
|
223 { |
|
224 err("CIOCCRYPT failed"); |
|
225 abort(); |
|
226 return 0; |
|
227 } |
|
228 } |
|
229 |
|
230 if(ctx->encrypt) |
|
231 memcpy(ctx->iv,&out[cryp.len-ctx->cipher->iv_len],ctx->cipher->iv_len); |
|
232 else |
|
233 memcpy(ctx->iv,lb,ctx->cipher->iv_len); |
|
234 |
|
235 return 1; |
|
236 } |
|
237 |
|
238 static int dev_crypto_des_ede3_init_key(EVP_CIPHER_CTX *ctx, |
|
239 const unsigned char *key, |
|
240 const unsigned char *iv, int enc) |
|
241 { return dev_crypto_init_key(ctx,CRYPTO_3DES_CBC,key,24); } |
|
242 |
|
243 #define dev_crypto_des_ede3_cbc_cipher dev_crypto_cipher |
|
244 |
|
245 BLOCK_CIPHER_def_cbc(dev_crypto_des_ede3, session_op, NID_des_ede3, 8, 24, 8, |
|
246 0, dev_crypto_des_ede3_init_key, |
|
247 dev_crypto_cleanup, |
|
248 EVP_CIPHER_set_asn1_iv, |
|
249 EVP_CIPHER_get_asn1_iv, |
|
250 NULL) |
|
251 |
|
252 static int dev_crypto_rc4_init_key(EVP_CIPHER_CTX *ctx, |
|
253 const unsigned char *key, |
|
254 const unsigned char *iv, int enc) |
|
255 { return dev_crypto_init_key(ctx,CRYPTO_ARC4,key,16); } |
|
256 |
|
257 static const EVP_CIPHER r4_cipher= |
|
258 { |
|
259 NID_rc4, |
|
260 1,16,0, /* FIXME: key should be up to 256 bytes */ |
|
261 EVP_CIPH_VARIABLE_LENGTH, |
|
262 dev_crypto_rc4_init_key, |
|
263 dev_crypto_cipher, |
|
264 dev_crypto_cleanup, |
|
265 sizeof(session_op), |
|
266 NULL, |
|
267 NULL, |
|
268 NULL |
|
269 }; |
|
270 |
|
271 const EVP_CIPHER *EVP_dev_crypto_rc4(void) |
|
272 { return &r4_cipher; } |
|
273 |
|
274 typedef struct |
|
275 { |
|
276 session_op sess; |
|
277 char *data; |
|
278 int len; |
|
279 unsigned char md[EVP_MAX_MD_SIZE]; |
|
280 } MD_DATA; |
|
281 |
|
282 static int dev_crypto_init_digest(MD_DATA *md_data,int mac) |
|
283 { |
|
284 if(!dev_crypto_init(&md_data->sess)) |
|
285 return 0; |
|
286 |
|
287 md_data->len=0; |
|
288 md_data->data=NULL; |
|
289 |
|
290 md_data->sess.mac=mac; |
|
291 |
|
292 if (ioctl(fd,CIOCGSESSION,&md_data->sess) == -1) |
|
293 { |
|
294 err("CIOCGSESSION failed"); |
|
295 return 0; |
|
296 } |
|
297 return 1; |
|
298 } |
|
299 |
|
300 static int dev_crypto_cleanup_digest(MD_DATA *md_data) |
|
301 { |
|
302 if (ioctl(fd,CIOCFSESSION,&md_data->sess.ses) == -1) |
|
303 { |
|
304 err("CIOCFSESSION failed"); |
|
305 return 0; |
|
306 } |
|
307 |
|
308 return 1; |
|
309 } |
|
310 |
|
311 /* FIXME: if device can do chained MACs, then don't accumulate */ |
|
312 /* FIXME: move accumulation to the framework */ |
|
313 static int dev_crypto_md5_init(EVP_MD_CTX *ctx) |
|
314 { return dev_crypto_init_digest(ctx->md_data,CRYPTO_MD5); } |
|
315 |
|
316 static int do_digest(int ses,unsigned char *md,const void *data,int len) |
|
317 { |
|
318 struct crypt_op cryp; |
|
319 static unsigned char md5zero[16]= |
|
320 { |
|
321 0xd4,0x1d,0x8c,0xd9,0x8f,0x00,0xb2,0x04, |
|
322 0xe9,0x80,0x09,0x98,0xec,0xf8,0x42,0x7e |
|
323 }; |
|
324 |
|
325 /* some cards can't do zero length */ |
|
326 if(!len) |
|
327 { |
|
328 memcpy(md,md5zero,16); |
|
329 return 1; |
|
330 } |
|
331 |
|
332 memset(&cryp,'\0',sizeof cryp); |
|
333 cryp.ses=ses; |
|
334 cryp.op=COP_ENCRYPT;/* required to do the MAC rather than check it */ |
|
335 cryp.len=len; |
|
336 cryp.src=(caddr_t)data; |
|
337 cryp.dst=(caddr_t)data; // FIXME!!! |
|
338 cryp.mac=(caddr_t)md; |
|
339 |
|
340 if(ioctl(fd, CIOCCRYPT, &cryp) == -1) |
|
341 { |
|
342 if(errno == EINVAL) /* buffer is misaligned */ |
|
343 { |
|
344 char *dcopy; |
|
345 |
|
346 dcopy=OPENSSL_malloc(len); |
|
347 memcpy(dcopy,data,len); |
|
348 cryp.src=dcopy; |
|
349 cryp.dst=cryp.src; // FIXME!!! |
|
350 |
|
351 if(ioctl(fd, CIOCCRYPT, &cryp) == -1) |
|
352 { |
|
353 err("CIOCCRYPT(MAC2) failed"); |
|
354 abort(); |
|
355 return 0; |
|
356 } |
|
357 OPENSSL_free(dcopy); |
|
358 } |
|
359 else |
|
360 { |
|
361 err("CIOCCRYPT(MAC) failed"); |
|
362 abort(); |
|
363 return 0; |
|
364 } |
|
365 } |
|
366 // printf("done\n"); |
|
367 |
|
368 return 1; |
|
369 } |
|
370 |
|
371 static int dev_crypto_md5_update(EVP_MD_CTX *ctx,const void *data, |
|
372 unsigned long len) |
|
373 { |
|
374 MD_DATA *md_data=ctx->md_data; |
|
375 |
|
376 if(ctx->flags&EVP_MD_CTX_FLAG_ONESHOT) |
|
377 return do_digest(md_data->sess.ses,md_data->md,data,len); |
|
378 |
|
379 md_data->data=OPENSSL_realloc(md_data->data,md_data->len+len); |
|
380 memcpy(md_data->data+md_data->len,data,len); |
|
381 md_data->len+=len; |
|
382 |
|
383 return 1; |
|
384 } |
|
385 |
|
386 static int dev_crypto_md5_final(EVP_MD_CTX *ctx,unsigned char *md) |
|
387 { |
|
388 int ret; |
|
389 MD_DATA *md_data=ctx->md_data; |
|
390 |
|
391 if(ctx->flags&EVP_MD_CTX_FLAG_ONESHOT) |
|
392 { |
|
393 memcpy(md,md_data->md,MD5_DIGEST_LENGTH); |
|
394 ret=1; |
|
395 } |
|
396 else |
|
397 { |
|
398 ret=do_digest(md_data->sess.ses,md,md_data->data,md_data->len); |
|
399 OPENSSL_free(md_data->data); |
|
400 md_data->data=NULL; |
|
401 md_data->len=0; |
|
402 } |
|
403 |
|
404 return ret; |
|
405 } |
|
406 |
|
407 static int dev_crypto_md5_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from) |
|
408 { |
|
409 const MD_DATA *from_md=from->md_data; |
|
410 MD_DATA *to_md=to->md_data; |
|
411 |
|
412 // How do we copy sessions? |
|
413 assert(from->digest->flags&EVP_MD_FLAG_ONESHOT); |
|
414 |
|
415 to_md->data=OPENSSL_malloc(from_md->len); |
|
416 memcpy(to_md->data,from_md->data,from_md->len); |
|
417 |
|
418 return 1; |
|
419 } |
|
420 |
|
421 static int dev_crypto_md5_cleanup(EVP_MD_CTX *ctx) |
|
422 { |
|
423 return dev_crypto_cleanup_digest(ctx->md_data); |
|
424 } |
|
425 |
|
426 static const EVP_MD md5_md= |
|
427 { |
|
428 NID_md5, |
|
429 NID_md5WithRSAEncryption, |
|
430 MD5_DIGEST_LENGTH, |
|
431 EVP_MD_FLAG_ONESHOT, // XXX: set according to device info... |
|
432 dev_crypto_md5_init, |
|
433 dev_crypto_md5_update, |
|
434 dev_crypto_md5_final, |
|
435 dev_crypto_md5_copy, |
|
436 dev_crypto_md5_cleanup, |
|
437 EVP_PKEY_RSA_method, |
|
438 MD5_CBLOCK, |
|
439 sizeof(MD_DATA), |
|
440 }; |
|
441 |
|
442 const EVP_MD *EVP_dev_crypto_md5(void) |
|
443 { return &md5_md; } |
|
444 |
|
445 #endif |
|
446 #endif |