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/* 56 * This stuff should now all be supported through 57 * crypto/engine/hw_openbsd_dev_crypto.c unless I botched it up 58 */ 59static void *dummy = &dummy; 60 61#if 0 62 63/* check flag after OpenSSL headers to ensure make depend works */ 64# ifdef OPENSSL_OPENBSD_DEV_CRYPTO 65 66# include <fcntl.h> 67# include <stdio.h> 68# include <errno.h> 69# include <sys/ioctl.h> 70# include <crypto/cryptodev.h> 71# include <unistd.h> 72# include <assert.h> 73 74/* longest key supported in hardware */ 75# define MAX_HW_KEY 24 76# define MAX_HW_IV 8 77 78# define MD5_DIGEST_LENGTH 16 79# define MD5_CBLOCK 64 80 81static int fd; 82static int dev_failed; 83 84typedef struct session_op session_op; 85 86# define CDATA(ctx) EVP_C_DATA(session_op,ctx) 87 88static void err(const char *str) 89{ 90 fprintf(stderr, "%s: errno %d\n", str, errno); 91} 92 93static int dev_crypto_init(session_op *ses) 94{ 95 if (dev_failed) 96 return 0; 97 if (!fd) { 98 int cryptodev_fd; 99 100 if ((cryptodev_fd = open("/dev/crypto", O_RDWR, 0)) < 0) { 101 err("/dev/crypto"); 102 dev_failed = 1; 103 return 0; 104 } 105 if (ioctl(cryptodev_fd, CRIOGET, &fd) == -1) { 106 err("CRIOGET failed"); 107 close(cryptodev_fd); 108 dev_failed = 1; 109 return 0; 110 } 111 close(cryptodev_fd); 112 } 113 assert(ses); 114 memset(ses, '\0', sizeof *ses); 115 116 return 1; 117} 118 119static int dev_crypto_cleanup(EVP_CIPHER_CTX *ctx) 120{ 121 if (ioctl(fd, CIOCFSESSION, &CDATA(ctx)->ses) == -1) 122 err("CIOCFSESSION failed"); 123 124 OPENSSL_free(CDATA(ctx)->key); 125 126 return 1; 127} 128 129static int dev_crypto_init_key(EVP_CIPHER_CTX *ctx, int cipher, 130 const unsigned char *key, int klen) 131{ 132 if (!dev_crypto_init(CDATA(ctx))) 133 return 0; 134 135 CDATA(ctx)->key = OPENSSL_malloc(MAX_HW_KEY); 136 137 assert(ctx->cipher->iv_len <= MAX_HW_IV); 138 139 memcpy(CDATA(ctx)->key, key, klen); 140 141 CDATA(ctx)->cipher = cipher; 142 CDATA(ctx)->keylen = klen; 143 144 if (ioctl(fd, CIOCGSESSION, CDATA(ctx)) == -1) { 145 err("CIOCGSESSION failed"); 146 return 0; 147 } 148 return 1; 149} 150 151static int dev_crypto_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 152 const unsigned char *in, unsigned int inl) 153{ 154 struct crypt_op cryp; 155 unsigned char lb[MAX_HW_IV]; 156 157 if (!inl) 158 return 1; 159 160 assert(CDATA(ctx)); 161 assert(!dev_failed); 162 163 memset(&cryp, '\0', sizeof cryp); 164 cryp.ses = CDATA(ctx)->ses; 165 cryp.op = ctx->encrypt ? COP_ENCRYPT : COP_DECRYPT; 166 cryp.flags = 0; 167 cryp.len = inl; 168 assert((inl & (ctx->cipher->block_size - 1)) == 0); 169 cryp.src = (caddr_t) in; 170 cryp.dst = (caddr_t) out; 171 cryp.mac = 0; 172 if (ctx->cipher->iv_len) 173 cryp.iv = (caddr_t) ctx->iv; 174 175 if (!ctx->encrypt) 176 memcpy(lb, &in[cryp.len - ctx->cipher->iv_len], ctx->cipher->iv_len); 177 178 if (ioctl(fd, CIOCCRYPT, &cryp) == -1) { 179 if (errno == EINVAL) { /* buffers are misaligned */ 180 unsigned int cinl = 0; 181 char *cin = NULL; 182 char *cout = NULL; 183 184 /* NB: this can only make cinl != inl with stream ciphers */ 185 cinl = (inl + 3) / 4 * 4; 186 187 if (((unsigned long)in & 3) || cinl != inl) { 188 cin = OPENSSL_malloc(cinl); 189 memcpy(cin, in, inl); 190 cryp.src = cin; 191 } 192 193 if (((unsigned long)out & 3) || cinl != inl) { 194 cout = OPENSSL_malloc(cinl); 195 cryp.dst = cout; 196 } 197 198 cryp.len = cinl; 199 200 if (ioctl(fd, CIOCCRYPT, &cryp) == -1) { 201 err("CIOCCRYPT(2) failed"); 202 printf("src=%p dst=%p\n", cryp.src, cryp.dst); 203 abort(); 204 return 0; 205 } 206 207 if (cout) { 208 memcpy(out, cout, inl); 209 OPENSSL_free(cout); 210 } 211 if (cin) 212 OPENSSL_free(cin); 213 } else { 214 err("CIOCCRYPT failed"); 215 abort(); 216 return 0; 217 } 218 } 219 220 if (ctx->encrypt) 221 memcpy(ctx->iv, &out[cryp.len - ctx->cipher->iv_len], 222 ctx->cipher->iv_len); 223 else 224 memcpy(ctx->iv, lb, ctx->cipher->iv_len); 225 226 return 1; 227} 228 229static int dev_crypto_des_ede3_init_key(EVP_CIPHER_CTX *ctx, 230 const unsigned char *key, 231 const unsigned char *iv, int enc) 232{ 233 return dev_crypto_init_key(ctx, CRYPTO_3DES_CBC, key, 24); 234} 235 236# define dev_crypto_des_ede3_cbc_cipher dev_crypto_cipher 237 238BLOCK_CIPHER_def_cbc(dev_crypto_des_ede3, session_op, NID_des_ede3, 8, 24, 8, 239 0, dev_crypto_des_ede3_init_key, 240 dev_crypto_cleanup, 241 EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL) 242 243static int dev_crypto_rc4_init_key(EVP_CIPHER_CTX *ctx, 244 const unsigned char *key, 245 const unsigned char *iv, int enc) 246{ 247 return dev_crypto_init_key(ctx, CRYPTO_ARC4, key, 16); 248} 249 250static const EVP_CIPHER r4_cipher = { 251 NID_rc4, 252 1, 16, 0, /* FIXME: key should be up to 256 bytes */ 253 EVP_CIPH_VARIABLE_LENGTH, 254 dev_crypto_rc4_init_key, 255 dev_crypto_cipher, 256 dev_crypto_cleanup, 257 sizeof(session_op), 258 NULL, 259 NULL, 260 NULL 261}; 262 263const EVP_CIPHER *EVP_dev_crypto_rc4(void) 264{ 265 return &r4_cipher; 266} 267 268typedef struct { 269 session_op sess; 270 char *data; 271 int len; 272 unsigned char md[EVP_MAX_MD_SIZE]; 273} MD_DATA; 274 275static int dev_crypto_init_digest(MD_DATA *md_data, int mac) 276{ 277 if (!dev_crypto_init(&md_data->sess)) 278 return 0; 279 280 md_data->len = 0; 281 md_data->data = NULL; 282 283 md_data->sess.mac = mac; 284 285 if (ioctl(fd, CIOCGSESSION, &md_data->sess) == -1) { 286 err("CIOCGSESSION failed"); 287 return 0; 288 } 289 return 1; 290} 291 292static int dev_crypto_cleanup_digest(MD_DATA *md_data) 293{ 294 if (ioctl(fd, CIOCFSESSION, &md_data->sess.ses) == -1) { 295 err("CIOCFSESSION failed"); 296 return 0; 297 } 298 299 return 1; 300} 301 302/* FIXME: if device can do chained MACs, then don't accumulate */ 303/* FIXME: move accumulation to the framework */ 304static int dev_crypto_md5_init(EVP_MD_CTX *ctx) 305{ 306 return dev_crypto_init_digest(ctx->md_data, CRYPTO_MD5); 307} 308 309static int do_digest(int ses, unsigned char *md, const void *data, int len) 310{ 311 struct crypt_op cryp; 312 static unsigned char md5zero[16] = { 313 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 314 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e 315 }; 316 317 /* some cards can't do zero length */ 318 if (!len) { 319 memcpy(md, md5zero, 16); 320 return 1; 321 } 322 323 memset(&cryp, '\0', sizeof cryp); 324 cryp.ses = ses; 325 cryp.op = COP_ENCRYPT; /* required to do the MAC rather than check 326 * it */ 327 cryp.len = len; 328 cryp.src = (caddr_t) data; 329 cryp.dst = (caddr_t) data; // FIXME!!! 330 cryp.mac = (caddr_t) md; 331 332 if (ioctl(fd, CIOCCRYPT, &cryp) == -1) { 333 if (errno == EINVAL) { /* buffer is misaligned */ 334 char *dcopy; 335 336 dcopy = OPENSSL_malloc(len); 337 memcpy(dcopy, data, len); 338 cryp.src = dcopy; 339 cryp.dst = cryp.src; // FIXME!!! 340 341 if (ioctl(fd, CIOCCRYPT, &cryp) == -1) { 342 err("CIOCCRYPT(MAC2) failed"); 343 abort(); 344 return 0; 345 } 346 OPENSSL_free(dcopy); 347 } else { 348 err("CIOCCRYPT(MAC) failed"); 349 abort(); 350 return 0; 351 } 352 } 353 // printf("done\n"); 354 355 return 1; 356} 357 358static int dev_crypto_md5_update(EVP_MD_CTX *ctx, const void *data, 359 unsigned long len) 360{ 361 MD_DATA *md_data = ctx->md_data; 362 363 if (ctx->flags & EVP_MD_CTX_FLAG_ONESHOT) 364 return do_digest(md_data->sess.ses, md_data->md, data, len); 365 366 md_data->data = OPENSSL_realloc(md_data->data, md_data->len + len); 367 memcpy(md_data->data + md_data->len, data, len); 368 md_data->len += len; 369 370 return 1; 371} 372 373static int dev_crypto_md5_final(EVP_MD_CTX *ctx, unsigned char *md) 374{ 375 int ret; 376 MD_DATA *md_data = ctx->md_data; 377 378 if (ctx->flags & EVP_MD_CTX_FLAG_ONESHOT) { 379 memcpy(md, md_data->md, MD5_DIGEST_LENGTH); 380 ret = 1; 381 } else { 382 ret = do_digest(md_data->sess.ses, md, md_data->data, md_data->len); 383 OPENSSL_free(md_data->data); 384 md_data->data = NULL; 385 md_data->len = 0; 386 } 387 388 return ret; 389} 390 391static int dev_crypto_md5_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from) 392{ 393 const MD_DATA *from_md = from->md_data; 394 MD_DATA *to_md = to->md_data; 395 396 // How do we copy sessions? 397 assert(from->digest->flags & EVP_MD_FLAG_ONESHOT); 398 399 to_md->data = OPENSSL_malloc(from_md->len); 400 memcpy(to_md->data, from_md->data, from_md->len); 401 402 return 1; 403} 404 405static int dev_crypto_md5_cleanup(EVP_MD_CTX *ctx) 406{ 407 return dev_crypto_cleanup_digest(ctx->md_data); 408} 409 410static const EVP_MD md5_md = { 411 NID_md5, 412 NID_md5WithRSAEncryption, 413 MD5_DIGEST_LENGTH, 414 EVP_MD_FLAG_ONESHOT, // XXX: set according to device info... 415 dev_crypto_md5_init, 416 dev_crypto_md5_update, 417 dev_crypto_md5_final, 418 dev_crypto_md5_copy, 419 dev_crypto_md5_cleanup, 420 EVP_PKEY_RSA_method, 421 MD5_CBLOCK, 422 sizeof(MD_DATA), 423}; 424 425const EVP_MD *EVP_dev_crypto_md5(void) 426{ 427 return &md5_md; 428} 429 430# endif 431#endif 432