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 447