| OLD | NEW |
| (Empty) |
| 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 | |
| OLD | NEW |