1109998Smarkm/* Written by Ben Laurie, 2001 */ 2109998Smarkm/* 3109998Smarkm * Copyright (c) 2001 The OpenSSL Project. All rights reserved. 4109998Smarkm * 5109998Smarkm * Redistribution and use in source and binary forms, with or without 6109998Smarkm * modification, are permitted provided that the following conditions 7109998Smarkm * are met: 8109998Smarkm * 9109998Smarkm * 1. Redistributions of source code must retain the above copyright 10280297Sjkim * notice, this list of conditions and the following disclaimer. 11109998Smarkm * 12109998Smarkm * 2. Redistributions in binary form must reproduce the above copyright 13109998Smarkm * notice, this list of conditions and the following disclaimer in 14109998Smarkm * the documentation and/or other materials provided with the 15109998Smarkm * distribution. 16109998Smarkm * 17109998Smarkm * 3. All advertising materials mentioning features or use of this 18109998Smarkm * software must display the following acknowledgment: 19109998Smarkm * "This product includes software developed by the OpenSSL Project 20109998Smarkm * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 21109998Smarkm * 22109998Smarkm * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 23109998Smarkm * endorse or promote products derived from this software without 24109998Smarkm * prior written permission. For written permission, please contact 25109998Smarkm * openssl-core@openssl.org. 26109998Smarkm * 27109998Smarkm * 5. Products derived from this software may not be called "OpenSSL" 28109998Smarkm * nor may "OpenSSL" appear in their names without prior written 29109998Smarkm * permission of the OpenSSL Project. 30109998Smarkm * 31109998Smarkm * 6. Redistributions of any form whatsoever must retain the following 32109998Smarkm * acknowledgment: 33109998Smarkm * "This product includes software developed by the OpenSSL Project 34109998Smarkm * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 35109998Smarkm * 36109998Smarkm * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 37109998Smarkm * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 38109998Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 39109998Smarkm * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 40109998Smarkm * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 41109998Smarkm * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 42109998Smarkm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 43109998Smarkm * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 44109998Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 45109998Smarkm * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 46109998Smarkm * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 47109998Smarkm * OF THE POSSIBILITY OF SUCH DAMAGE. 48109998Smarkm */ 49109998Smarkm 50109998Smarkm#include <openssl/evp.h> 51109998Smarkm#include <openssl/objects.h> 52109998Smarkm#include <openssl/rsa.h> 53109998Smarkm#include "evp_locl.h" 54109998Smarkm 55280297Sjkim/* 56280297Sjkim * This stuff should now all be supported through 57280297Sjkim * crypto/engine/hw_openbsd_dev_crypto.c unless I botched it up 58280297Sjkim */ 59280297Sjkimstatic void *dummy = &dummy; 60109998Smarkm 61109998Smarkm#if 0 62109998Smarkm 63109998Smarkm/* check flag after OpenSSL headers to ensure make depend works */ 64280297Sjkim# ifdef OPENSSL_OPENBSD_DEV_CRYPTO 65109998Smarkm 66280297Sjkim# include <fcntl.h> 67280297Sjkim# include <stdio.h> 68280297Sjkim# include <errno.h> 69280297Sjkim# include <sys/ioctl.h> 70280297Sjkim# include <crypto/cryptodev.h> 71280297Sjkim# include <unistd.h> 72280297Sjkim# include <assert.h> 73109998Smarkm 74109998Smarkm/* longest key supported in hardware */ 75280297Sjkim# define MAX_HW_KEY 24 76280297Sjkim# define MAX_HW_IV 8 77109998Smarkm 78280297Sjkim# define MD5_DIGEST_LENGTH 16 79280297Sjkim# define MD5_CBLOCK 64 80109998Smarkm 81109998Smarkmstatic int fd; 82109998Smarkmstatic int dev_failed; 83109998Smarkm 84109998Smarkmtypedef struct session_op session_op; 85109998Smarkm 86280297Sjkim# define CDATA(ctx) EVP_C_DATA(session_op,ctx) 87109998Smarkm 88109998Smarkmstatic void err(const char *str) 89280297Sjkim{ 90280297Sjkim fprintf(stderr, "%s: errno %d\n", str, errno); 91280297Sjkim} 92109998Smarkm 93109998Smarkmstatic int dev_crypto_init(session_op *ses) 94280297Sjkim{ 95280297Sjkim if (dev_failed) 96280297Sjkim return 0; 97280297Sjkim if (!fd) { 98280297Sjkim int cryptodev_fd; 99109998Smarkm 100280297Sjkim if ((cryptodev_fd = open("/dev/crypto", O_RDWR, 0)) < 0) { 101280297Sjkim err("/dev/crypto"); 102280297Sjkim dev_failed = 1; 103280297Sjkim return 0; 104280297Sjkim } 105280297Sjkim if (ioctl(cryptodev_fd, CRIOGET, &fd) == -1) { 106280297Sjkim err("CRIOGET failed"); 107280297Sjkim close(cryptodev_fd); 108280297Sjkim dev_failed = 1; 109280297Sjkim return 0; 110280297Sjkim } 111280297Sjkim close(cryptodev_fd); 112280297Sjkim } 113109998Smarkm assert(ses); 114331638Sjkim memset(ses, '\0', sizeof(*ses)); 115109998Smarkm 116109998Smarkm return 1; 117280297Sjkim} 118109998Smarkm 119109998Smarkmstatic int dev_crypto_cleanup(EVP_CIPHER_CTX *ctx) 120280297Sjkim{ 121280297Sjkim if (ioctl(fd, CIOCFSESSION, &CDATA(ctx)->ses) == -1) 122280297Sjkim err("CIOCFSESSION failed"); 123109998Smarkm 124109998Smarkm OPENSSL_free(CDATA(ctx)->key); 125109998Smarkm 126109998Smarkm return 1; 127280297Sjkim} 128109998Smarkm 129280297Sjkimstatic int dev_crypto_init_key(EVP_CIPHER_CTX *ctx, int cipher, 130280297Sjkim const unsigned char *key, int klen) 131280297Sjkim{ 132280297Sjkim if (!dev_crypto_init(CDATA(ctx))) 133280297Sjkim return 0; 134109998Smarkm 135280297Sjkim CDATA(ctx)->key = OPENSSL_malloc(MAX_HW_KEY); 136306195Sjkim if (CDATA(ctx)->key == NULL { 137306195Sjkim err("CDATA(ctx)->key memory allocation failed"); 138306195Sjkim return 0; 139306195Sjkim } 140109998Smarkm 141109998Smarkm assert(ctx->cipher->iv_len <= MAX_HW_IV); 142109998Smarkm 143280297Sjkim memcpy(CDATA(ctx)->key, key, klen); 144109998Smarkm 145280297Sjkim CDATA(ctx)->cipher = cipher; 146280297Sjkim CDATA(ctx)->keylen = klen; 147280297Sjkim 148280297Sjkim if (ioctl(fd, CIOCGSESSION, CDATA(ctx)) == -1) { 149280297Sjkim err("CIOCGSESSION failed"); 150280297Sjkim return 0; 151280297Sjkim } 152109998Smarkm return 1; 153280297Sjkim} 154109998Smarkm 155280297Sjkimstatic int dev_crypto_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 156280297Sjkim const unsigned char *in, unsigned int inl) 157280297Sjkim{ 158109998Smarkm struct crypt_op cryp; 159109998Smarkm unsigned char lb[MAX_HW_IV]; 160109998Smarkm 161280297Sjkim if (!inl) 162280297Sjkim return 1; 163109998Smarkm 164109998Smarkm assert(CDATA(ctx)); 165109998Smarkm assert(!dev_failed); 166109998Smarkm 167331638Sjkim memset(&cryp, '\0', sizeof(cryp)); 168280297Sjkim cryp.ses = CDATA(ctx)->ses; 169280297Sjkim cryp.op = ctx->encrypt ? COP_ENCRYPT : COP_DECRYPT; 170280297Sjkim cryp.flags = 0; 171280297Sjkim cryp.len = inl; 172280297Sjkim assert((inl & (ctx->cipher->block_size - 1)) == 0); 173280297Sjkim cryp.src = (caddr_t) in; 174280297Sjkim cryp.dst = (caddr_t) out; 175280297Sjkim cryp.mac = 0; 176280297Sjkim if (ctx->cipher->iv_len) 177280297Sjkim cryp.iv = (caddr_t) ctx->iv; 178109998Smarkm 179280297Sjkim if (!ctx->encrypt) 180280297Sjkim memcpy(lb, &in[cryp.len - ctx->cipher->iv_len], ctx->cipher->iv_len); 181109998Smarkm 182280297Sjkim if (ioctl(fd, CIOCCRYPT, &cryp) == -1) { 183280297Sjkim if (errno == EINVAL) { /* buffers are misaligned */ 184280297Sjkim unsigned int cinl = 0; 185280297Sjkim char *cin = NULL; 186280297Sjkim char *cout = NULL; 187109998Smarkm 188280297Sjkim /* NB: this can only make cinl != inl with stream ciphers */ 189280297Sjkim cinl = (inl + 3) / 4 * 4; 190109998Smarkm 191280297Sjkim if (((unsigned long)in & 3) || cinl != inl) { 192280297Sjkim cin = OPENSSL_malloc(cinl); 193306195Sjkim if (cin == NULL) { 194306195Sjkim err("cin - memory allocation failed"); 195306195Sjkim abort(); 196306195Sjkim return 0; 197306195Sjkim } 198280297Sjkim memcpy(cin, in, inl); 199280297Sjkim cryp.src = cin; 200280297Sjkim } 201109998Smarkm 202280297Sjkim if (((unsigned long)out & 3) || cinl != inl) { 203280297Sjkim cout = OPENSSL_malloc(cinl); 204280297Sjkim cryp.dst = cout; 205280297Sjkim } 206109998Smarkm 207280297Sjkim cryp.len = cinl; 208109998Smarkm 209280297Sjkim if (ioctl(fd, CIOCCRYPT, &cryp) == -1) { 210280297Sjkim err("CIOCCRYPT(2) failed"); 211280297Sjkim printf("src=%p dst=%p\n", cryp.src, cryp.dst); 212280297Sjkim abort(); 213280297Sjkim return 0; 214280297Sjkim } 215109998Smarkm 216280297Sjkim if (cout) { 217280297Sjkim memcpy(out, cout, inl); 218280297Sjkim OPENSSL_free(cout); 219280297Sjkim } 220280297Sjkim if (cin) 221280297Sjkim OPENSSL_free(cin); 222280297Sjkim } else { 223280297Sjkim err("CIOCCRYPT failed"); 224280297Sjkim abort(); 225280297Sjkim return 0; 226280297Sjkim } 227280297Sjkim } 228280297Sjkim 229280297Sjkim if (ctx->encrypt) 230280297Sjkim memcpy(ctx->iv, &out[cryp.len - ctx->cipher->iv_len], 231280297Sjkim ctx->cipher->iv_len); 232109998Smarkm else 233280297Sjkim memcpy(ctx->iv, lb, ctx->cipher->iv_len); 234109998Smarkm 235109998Smarkm return 1; 236280297Sjkim} 237109998Smarkm 238109998Smarkmstatic int dev_crypto_des_ede3_init_key(EVP_CIPHER_CTX *ctx, 239280297Sjkim const unsigned char *key, 240280297Sjkim const unsigned char *iv, int enc) 241280297Sjkim{ 242280297Sjkim return dev_crypto_init_key(ctx, CRYPTO_3DES_CBC, key, 24); 243280297Sjkim} 244109998Smarkm 245280297Sjkim# define dev_crypto_des_ede3_cbc_cipher dev_crypto_cipher 246109998Smarkm 247109998SmarkmBLOCK_CIPHER_def_cbc(dev_crypto_des_ede3, session_op, NID_des_ede3, 8, 24, 8, 248280297Sjkim 0, dev_crypto_des_ede3_init_key, 249280297Sjkim dev_crypto_cleanup, 250280297Sjkim EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL) 251109998Smarkm 252109998Smarkmstatic int dev_crypto_rc4_init_key(EVP_CIPHER_CTX *ctx, 253280297Sjkim const unsigned char *key, 254280297Sjkim const unsigned char *iv, int enc) 255280297Sjkim{ 256280297Sjkim return dev_crypto_init_key(ctx, CRYPTO_ARC4, key, 16); 257280297Sjkim} 258109998Smarkm 259280297Sjkimstatic const EVP_CIPHER r4_cipher = { 260109998Smarkm NID_rc4, 261280297Sjkim 1, 16, 0, /* FIXME: key should be up to 256 bytes */ 262109998Smarkm EVP_CIPH_VARIABLE_LENGTH, 263109998Smarkm dev_crypto_rc4_init_key, 264109998Smarkm dev_crypto_cipher, 265109998Smarkm dev_crypto_cleanup, 266109998Smarkm sizeof(session_op), 267109998Smarkm NULL, 268109998Smarkm NULL, 269109998Smarkm NULL 270280297Sjkim}; 271109998Smarkm 272109998Smarkmconst EVP_CIPHER *EVP_dev_crypto_rc4(void) 273280297Sjkim{ 274280297Sjkim return &r4_cipher; 275280297Sjkim} 276109998Smarkm 277280297Sjkimtypedef struct { 278109998Smarkm session_op sess; 279109998Smarkm char *data; 280109998Smarkm int len; 281109998Smarkm unsigned char md[EVP_MAX_MD_SIZE]; 282280297Sjkim} MD_DATA; 283109998Smarkm 284280297Sjkimstatic int dev_crypto_init_digest(MD_DATA *md_data, int mac) 285280297Sjkim{ 286280297Sjkim if (!dev_crypto_init(&md_data->sess)) 287280297Sjkim return 0; 288109998Smarkm 289280297Sjkim md_data->len = 0; 290280297Sjkim md_data->data = NULL; 291109998Smarkm 292280297Sjkim md_data->sess.mac = mac; 293109998Smarkm 294280297Sjkim if (ioctl(fd, CIOCGSESSION, &md_data->sess) == -1) { 295280297Sjkim err("CIOCGSESSION failed"); 296280297Sjkim return 0; 297280297Sjkim } 298109998Smarkm return 1; 299280297Sjkim} 300109998Smarkm 301109998Smarkmstatic int dev_crypto_cleanup_digest(MD_DATA *md_data) 302280297Sjkim{ 303280297Sjkim if (ioctl(fd, CIOCFSESSION, &md_data->sess.ses) == -1) { 304280297Sjkim err("CIOCFSESSION failed"); 305280297Sjkim return 0; 306280297Sjkim } 307109998Smarkm 308109998Smarkm return 1; 309280297Sjkim} 310109998Smarkm 311109998Smarkm/* FIXME: if device can do chained MACs, then don't accumulate */ 312109998Smarkm/* FIXME: move accumulation to the framework */ 313109998Smarkmstatic int dev_crypto_md5_init(EVP_MD_CTX *ctx) 314280297Sjkim{ 315280297Sjkim return dev_crypto_init_digest(ctx->md_data, CRYPTO_MD5); 316280297Sjkim} 317109998Smarkm 318280297Sjkimstatic int do_digest(int ses, unsigned char *md, const void *data, int len) 319280297Sjkim{ 320109998Smarkm struct crypt_op cryp; 321280297Sjkim static unsigned char md5zero[16] = { 322280297Sjkim 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 323280297Sjkim 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e 324280297Sjkim }; 325109998Smarkm 326109998Smarkm /* some cards can't do zero length */ 327280297Sjkim if (!len) { 328280297Sjkim memcpy(md, md5zero, 16); 329280297Sjkim return 1; 330280297Sjkim } 331109998Smarkm 332331638Sjkim memset(&cryp, '\0', sizeof(cryp)); 333280297Sjkim cryp.ses = ses; 334280297Sjkim cryp.op = COP_ENCRYPT; /* required to do the MAC rather than check 335280297Sjkim * it */ 336280297Sjkim cryp.len = len; 337280297Sjkim cryp.src = (caddr_t) data; 338280297Sjkim cryp.dst = (caddr_t) data; // FIXME!!! 339280297Sjkim cryp.mac = (caddr_t) md; 340109998Smarkm 341280297Sjkim if (ioctl(fd, CIOCCRYPT, &cryp) == -1) { 342280297Sjkim if (errno == EINVAL) { /* buffer is misaligned */ 343280297Sjkim char *dcopy; 344109998Smarkm 345280297Sjkim dcopy = OPENSSL_malloc(len); 346306195Sjkim if (dcopy == NULL) { 347306195Sjkim err("dcopy - memory allocation failed"); 348306195Sjkim abort(); 349306195Sjkim return 0; 350306195Sjkim } 351280297Sjkim memcpy(dcopy, data, len); 352280297Sjkim cryp.src = dcopy; 353280297Sjkim cryp.dst = cryp.src; // FIXME!!! 354109998Smarkm 355280297Sjkim if (ioctl(fd, CIOCCRYPT, &cryp) == -1) { 356280297Sjkim err("CIOCCRYPT(MAC2) failed"); 357280297Sjkim abort(); 358280297Sjkim return 0; 359280297Sjkim } 360280297Sjkim OPENSSL_free(dcopy); 361280297Sjkim } else { 362280297Sjkim err("CIOCCRYPT(MAC) failed"); 363280297Sjkim abort(); 364280297Sjkim return 0; 365280297Sjkim } 366280297Sjkim } 367280297Sjkim // printf("done\n"); 368109998Smarkm 369109998Smarkm return 1; 370280297Sjkim} 371109998Smarkm 372280297Sjkimstatic int dev_crypto_md5_update(EVP_MD_CTX *ctx, const void *data, 373280297Sjkim unsigned long len) 374280297Sjkim{ 375280297Sjkim MD_DATA *md_data = ctx->md_data; 376109998Smarkm 377280297Sjkim if (ctx->flags & EVP_MD_CTX_FLAG_ONESHOT) 378280297Sjkim return do_digest(md_data->sess.ses, md_data->md, data, len); 379109998Smarkm 380280297Sjkim md_data->data = OPENSSL_realloc(md_data->data, md_data->len + len); 381306195Sjkim if (md_data->data == NULL) { 382306195Sjkim err("DEV_CRYPTO_MD5_UPDATE: unable to allocate memory"); 383306195Sjkim abort(); 384306195Sjkim } 385280297Sjkim memcpy(md_data->data + md_data->len, data, len); 386280297Sjkim md_data->len += len; 387109998Smarkm 388109998Smarkm return 1; 389280297Sjkim} 390109998Smarkm 391280297Sjkimstatic int dev_crypto_md5_final(EVP_MD_CTX *ctx, unsigned char *md) 392280297Sjkim{ 393109998Smarkm int ret; 394280297Sjkim MD_DATA *md_data = ctx->md_data; 395109998Smarkm 396280297Sjkim if (ctx->flags & EVP_MD_CTX_FLAG_ONESHOT) { 397280297Sjkim memcpy(md, md_data->md, MD5_DIGEST_LENGTH); 398280297Sjkim ret = 1; 399280297Sjkim } else { 400280297Sjkim ret = do_digest(md_data->sess.ses, md, md_data->data, md_data->len); 401280297Sjkim OPENSSL_free(md_data->data); 402280297Sjkim md_data->data = NULL; 403280297Sjkim md_data->len = 0; 404280297Sjkim } 405109998Smarkm 406109998Smarkm return ret; 407280297Sjkim} 408109998Smarkm 409280297Sjkimstatic int dev_crypto_md5_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from) 410280297Sjkim{ 411280297Sjkim const MD_DATA *from_md = from->md_data; 412280297Sjkim MD_DATA *to_md = to->md_data; 413109998Smarkm 414109998Smarkm // How do we copy sessions? 415280297Sjkim assert(from->digest->flags & EVP_MD_FLAG_ONESHOT); 416109998Smarkm 417280297Sjkim to_md->data = OPENSSL_malloc(from_md->len); 418306195Sjkim if (to_md->data == NULL) { 419306195Sjkim err("DEV_CRYPTO_MD5_COPY: unable to allocate memory"); 420306195Sjkim abort(); 421306195Sjkim } 422280297Sjkim memcpy(to_md->data, from_md->data, from_md->len); 423109998Smarkm 424109998Smarkm return 1; 425280297Sjkim} 426109998Smarkm 427109998Smarkmstatic int dev_crypto_md5_cleanup(EVP_MD_CTX *ctx) 428280297Sjkim{ 429109998Smarkm return dev_crypto_cleanup_digest(ctx->md_data); 430280297Sjkim} 431109998Smarkm 432280297Sjkimstatic const EVP_MD md5_md = { 433109998Smarkm NID_md5, 434109998Smarkm NID_md5WithRSAEncryption, 435109998Smarkm MD5_DIGEST_LENGTH, 436280297Sjkim EVP_MD_FLAG_ONESHOT, // XXX: set according to device info... 437109998Smarkm dev_crypto_md5_init, 438109998Smarkm dev_crypto_md5_update, 439109998Smarkm dev_crypto_md5_final, 440109998Smarkm dev_crypto_md5_copy, 441109998Smarkm dev_crypto_md5_cleanup, 442109998Smarkm EVP_PKEY_RSA_method, 443109998Smarkm MD5_CBLOCK, 444109998Smarkm sizeof(MD_DATA), 445280297Sjkim}; 446109998Smarkm 447109998Smarkmconst EVP_MD *EVP_dev_crypto_md5(void) 448280297Sjkim{ 449280297Sjkim return &md5_md; 450280297Sjkim} 451109998Smarkm 452280297Sjkim# endif 453109998Smarkm#endif 454