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 10296465Sdelphij * 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 55296465Sdelphij/* 56296465Sdelphij * This stuff should now all be supported through 57296465Sdelphij * crypto/engine/hw_openbsd_dev_crypto.c unless I botched it up 58296465Sdelphij */ 59296465Sdelphijstatic void *dummy = &dummy; 60109998Smarkm 61109998Smarkm#if 0 62109998Smarkm 63109998Smarkm/* check flag after OpenSSL headers to ensure make depend works */ 64296465Sdelphij# ifdef OPENSSL_OPENBSD_DEV_CRYPTO 65109998Smarkm 66296465Sdelphij# include <fcntl.h> 67296465Sdelphij# include <stdio.h> 68296465Sdelphij# include <errno.h> 69296465Sdelphij# include <sys/ioctl.h> 70296465Sdelphij# include <crypto/cryptodev.h> 71296465Sdelphij# include <unistd.h> 72296465Sdelphij# include <assert.h> 73109998Smarkm 74109998Smarkm/* longest key supported in hardware */ 75296465Sdelphij# define MAX_HW_KEY 24 76296465Sdelphij# define MAX_HW_IV 8 77109998Smarkm 78296465Sdelphij# define MD5_DIGEST_LENGTH 16 79296465Sdelphij# define MD5_CBLOCK 64 80109998Smarkm 81109998Smarkmstatic int fd; 82109998Smarkmstatic int dev_failed; 83109998Smarkm 84109998Smarkmtypedef struct session_op session_op; 85109998Smarkm 86296465Sdelphij# define CDATA(ctx) EVP_C_DATA(session_op,ctx) 87109998Smarkm 88109998Smarkmstatic void err(const char *str) 89296465Sdelphij{ 90296465Sdelphij fprintf(stderr, "%s: errno %d\n", str, errno); 91296465Sdelphij} 92109998Smarkm 93109998Smarkmstatic int dev_crypto_init(session_op *ses) 94296465Sdelphij{ 95296465Sdelphij if (dev_failed) 96296465Sdelphij return 0; 97296465Sdelphij if (!fd) { 98296465Sdelphij int cryptodev_fd; 99109998Smarkm 100296465Sdelphij if ((cryptodev_fd = open("/dev/crypto", O_RDWR, 0)) < 0) { 101296465Sdelphij err("/dev/crypto"); 102296465Sdelphij dev_failed = 1; 103296465Sdelphij return 0; 104296465Sdelphij } 105296465Sdelphij if (ioctl(cryptodev_fd, CRIOGET, &fd) == -1) { 106296465Sdelphij err("CRIOGET failed"); 107296465Sdelphij close(cryptodev_fd); 108296465Sdelphij dev_failed = 1; 109296465Sdelphij return 0; 110296465Sdelphij } 111296465Sdelphij close(cryptodev_fd); 112296465Sdelphij } 113109998Smarkm assert(ses); 114296465Sdelphij memset(ses, '\0', sizeof *ses); 115109998Smarkm 116109998Smarkm return 1; 117296465Sdelphij} 118109998Smarkm 119109998Smarkmstatic int dev_crypto_cleanup(EVP_CIPHER_CTX *ctx) 120296465Sdelphij{ 121296465Sdelphij if (ioctl(fd, CIOCFSESSION, &CDATA(ctx)->ses) == -1) 122296465Sdelphij err("CIOCFSESSION failed"); 123109998Smarkm 124109998Smarkm OPENSSL_free(CDATA(ctx)->key); 125109998Smarkm 126109998Smarkm return 1; 127296465Sdelphij} 128109998Smarkm 129296465Sdelphijstatic int dev_crypto_init_key(EVP_CIPHER_CTX *ctx, int cipher, 130296465Sdelphij const unsigned char *key, int klen) 131296465Sdelphij{ 132296465Sdelphij if (!dev_crypto_init(CDATA(ctx))) 133296465Sdelphij return 0; 134109998Smarkm 135296465Sdelphij CDATA(ctx)->key = OPENSSL_malloc(MAX_HW_KEY); 136109998Smarkm 137109998Smarkm assert(ctx->cipher->iv_len <= MAX_HW_IV); 138109998Smarkm 139296465Sdelphij memcpy(CDATA(ctx)->key, key, klen); 140109998Smarkm 141296465Sdelphij CDATA(ctx)->cipher = cipher; 142296465Sdelphij CDATA(ctx)->keylen = klen; 143296465Sdelphij 144296465Sdelphij if (ioctl(fd, CIOCGSESSION, CDATA(ctx)) == -1) { 145296465Sdelphij err("CIOCGSESSION failed"); 146296465Sdelphij return 0; 147296465Sdelphij } 148109998Smarkm return 1; 149296465Sdelphij} 150109998Smarkm 151296465Sdelphijstatic int dev_crypto_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, 152296465Sdelphij const unsigned char *in, unsigned int inl) 153296465Sdelphij{ 154109998Smarkm struct crypt_op cryp; 155109998Smarkm unsigned char lb[MAX_HW_IV]; 156109998Smarkm 157296465Sdelphij if (!inl) 158296465Sdelphij return 1; 159109998Smarkm 160109998Smarkm assert(CDATA(ctx)); 161109998Smarkm assert(!dev_failed); 162109998Smarkm 163296465Sdelphij memset(&cryp, '\0', sizeof cryp); 164296465Sdelphij cryp.ses = CDATA(ctx)->ses; 165296465Sdelphij cryp.op = ctx->encrypt ? COP_ENCRYPT : COP_DECRYPT; 166296465Sdelphij cryp.flags = 0; 167296465Sdelphij cryp.len = inl; 168296465Sdelphij assert((inl & (ctx->cipher->block_size - 1)) == 0); 169296465Sdelphij cryp.src = (caddr_t) in; 170296465Sdelphij cryp.dst = (caddr_t) out; 171296465Sdelphij cryp.mac = 0; 172296465Sdelphij if (ctx->cipher->iv_len) 173296465Sdelphij cryp.iv = (caddr_t) ctx->iv; 174109998Smarkm 175296465Sdelphij if (!ctx->encrypt) 176296465Sdelphij memcpy(lb, &in[cryp.len - ctx->cipher->iv_len], ctx->cipher->iv_len); 177109998Smarkm 178296465Sdelphij if (ioctl(fd, CIOCCRYPT, &cryp) == -1) { 179296465Sdelphij if (errno == EINVAL) { /* buffers are misaligned */ 180296465Sdelphij unsigned int cinl = 0; 181296465Sdelphij char *cin = NULL; 182296465Sdelphij char *cout = NULL; 183109998Smarkm 184296465Sdelphij /* NB: this can only make cinl != inl with stream ciphers */ 185296465Sdelphij cinl = (inl + 3) / 4 * 4; 186109998Smarkm 187296465Sdelphij if (((unsigned long)in & 3) || cinl != inl) { 188296465Sdelphij cin = OPENSSL_malloc(cinl); 189296465Sdelphij memcpy(cin, in, inl); 190296465Sdelphij cryp.src = cin; 191296465Sdelphij } 192109998Smarkm 193296465Sdelphij if (((unsigned long)out & 3) || cinl != inl) { 194296465Sdelphij cout = OPENSSL_malloc(cinl); 195296465Sdelphij cryp.dst = cout; 196296465Sdelphij } 197109998Smarkm 198296465Sdelphij cryp.len = cinl; 199109998Smarkm 200296465Sdelphij if (ioctl(fd, CIOCCRYPT, &cryp) == -1) { 201296465Sdelphij err("CIOCCRYPT(2) failed"); 202296465Sdelphij printf("src=%p dst=%p\n", cryp.src, cryp.dst); 203296465Sdelphij abort(); 204296465Sdelphij return 0; 205296465Sdelphij } 206109998Smarkm 207296465Sdelphij if (cout) { 208296465Sdelphij memcpy(out, cout, inl); 209296465Sdelphij OPENSSL_free(cout); 210296465Sdelphij } 211296465Sdelphij if (cin) 212296465Sdelphij OPENSSL_free(cin); 213296465Sdelphij } else { 214296465Sdelphij err("CIOCCRYPT failed"); 215296465Sdelphij abort(); 216296465Sdelphij return 0; 217296465Sdelphij } 218296465Sdelphij } 219296465Sdelphij 220296465Sdelphij if (ctx->encrypt) 221296465Sdelphij memcpy(ctx->iv, &out[cryp.len - ctx->cipher->iv_len], 222296465Sdelphij ctx->cipher->iv_len); 223109998Smarkm else 224296465Sdelphij memcpy(ctx->iv, lb, ctx->cipher->iv_len); 225109998Smarkm 226109998Smarkm return 1; 227296465Sdelphij} 228109998Smarkm 229109998Smarkmstatic int dev_crypto_des_ede3_init_key(EVP_CIPHER_CTX *ctx, 230296465Sdelphij const unsigned char *key, 231296465Sdelphij const unsigned char *iv, int enc) 232296465Sdelphij{ 233296465Sdelphij return dev_crypto_init_key(ctx, CRYPTO_3DES_CBC, key, 24); 234296465Sdelphij} 235109998Smarkm 236296465Sdelphij# define dev_crypto_des_ede3_cbc_cipher dev_crypto_cipher 237109998Smarkm 238109998SmarkmBLOCK_CIPHER_def_cbc(dev_crypto_des_ede3, session_op, NID_des_ede3, 8, 24, 8, 239296465Sdelphij 0, dev_crypto_des_ede3_init_key, 240296465Sdelphij dev_crypto_cleanup, 241296465Sdelphij EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL) 242109998Smarkm 243109998Smarkmstatic int dev_crypto_rc4_init_key(EVP_CIPHER_CTX *ctx, 244296465Sdelphij const unsigned char *key, 245296465Sdelphij const unsigned char *iv, int enc) 246296465Sdelphij{ 247296465Sdelphij return dev_crypto_init_key(ctx, CRYPTO_ARC4, key, 16); 248296465Sdelphij} 249109998Smarkm 250296465Sdelphijstatic const EVP_CIPHER r4_cipher = { 251109998Smarkm NID_rc4, 252296465Sdelphij 1, 16, 0, /* FIXME: key should be up to 256 bytes */ 253109998Smarkm EVP_CIPH_VARIABLE_LENGTH, 254109998Smarkm dev_crypto_rc4_init_key, 255109998Smarkm dev_crypto_cipher, 256109998Smarkm dev_crypto_cleanup, 257109998Smarkm sizeof(session_op), 258109998Smarkm NULL, 259109998Smarkm NULL, 260109998Smarkm NULL 261296465Sdelphij}; 262109998Smarkm 263109998Smarkmconst EVP_CIPHER *EVP_dev_crypto_rc4(void) 264296465Sdelphij{ 265296465Sdelphij return &r4_cipher; 266296465Sdelphij} 267109998Smarkm 268296465Sdelphijtypedef struct { 269109998Smarkm session_op sess; 270109998Smarkm char *data; 271109998Smarkm int len; 272109998Smarkm unsigned char md[EVP_MAX_MD_SIZE]; 273296465Sdelphij} MD_DATA; 274109998Smarkm 275296465Sdelphijstatic int dev_crypto_init_digest(MD_DATA *md_data, int mac) 276296465Sdelphij{ 277296465Sdelphij if (!dev_crypto_init(&md_data->sess)) 278296465Sdelphij return 0; 279109998Smarkm 280296465Sdelphij md_data->len = 0; 281296465Sdelphij md_data->data = NULL; 282109998Smarkm 283296465Sdelphij md_data->sess.mac = mac; 284109998Smarkm 285296465Sdelphij if (ioctl(fd, CIOCGSESSION, &md_data->sess) == -1) { 286296465Sdelphij err("CIOCGSESSION failed"); 287296465Sdelphij return 0; 288296465Sdelphij } 289109998Smarkm return 1; 290296465Sdelphij} 291109998Smarkm 292109998Smarkmstatic int dev_crypto_cleanup_digest(MD_DATA *md_data) 293296465Sdelphij{ 294296465Sdelphij if (ioctl(fd, CIOCFSESSION, &md_data->sess.ses) == -1) { 295296465Sdelphij err("CIOCFSESSION failed"); 296296465Sdelphij return 0; 297296465Sdelphij } 298109998Smarkm 299109998Smarkm return 1; 300296465Sdelphij} 301109998Smarkm 302109998Smarkm/* FIXME: if device can do chained MACs, then don't accumulate */ 303109998Smarkm/* FIXME: move accumulation to the framework */ 304109998Smarkmstatic int dev_crypto_md5_init(EVP_MD_CTX *ctx) 305296465Sdelphij{ 306296465Sdelphij return dev_crypto_init_digest(ctx->md_data, CRYPTO_MD5); 307296465Sdelphij} 308109998Smarkm 309296465Sdelphijstatic int do_digest(int ses, unsigned char *md, const void *data, int len) 310296465Sdelphij{ 311109998Smarkm struct crypt_op cryp; 312296465Sdelphij static unsigned char md5zero[16] = { 313296465Sdelphij 0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04, 314296465Sdelphij 0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e 315296465Sdelphij }; 316109998Smarkm 317109998Smarkm /* some cards can't do zero length */ 318296465Sdelphij if (!len) { 319296465Sdelphij memcpy(md, md5zero, 16); 320296465Sdelphij return 1; 321296465Sdelphij } 322109998Smarkm 323296465Sdelphij memset(&cryp, '\0', sizeof cryp); 324296465Sdelphij cryp.ses = ses; 325296465Sdelphij cryp.op = COP_ENCRYPT; /* required to do the MAC rather than check 326296465Sdelphij * it */ 327296465Sdelphij cryp.len = len; 328296465Sdelphij cryp.src = (caddr_t) data; 329296465Sdelphij cryp.dst = (caddr_t) data; // FIXME!!! 330296465Sdelphij cryp.mac = (caddr_t) md; 331109998Smarkm 332296465Sdelphij if (ioctl(fd, CIOCCRYPT, &cryp) == -1) { 333296465Sdelphij if (errno == EINVAL) { /* buffer is misaligned */ 334296465Sdelphij char *dcopy; 335109998Smarkm 336296465Sdelphij dcopy = OPENSSL_malloc(len); 337296465Sdelphij memcpy(dcopy, data, len); 338296465Sdelphij cryp.src = dcopy; 339296465Sdelphij cryp.dst = cryp.src; // FIXME!!! 340109998Smarkm 341296465Sdelphij if (ioctl(fd, CIOCCRYPT, &cryp) == -1) { 342296465Sdelphij err("CIOCCRYPT(MAC2) failed"); 343296465Sdelphij abort(); 344296465Sdelphij return 0; 345296465Sdelphij } 346296465Sdelphij OPENSSL_free(dcopy); 347296465Sdelphij } else { 348296465Sdelphij err("CIOCCRYPT(MAC) failed"); 349296465Sdelphij abort(); 350296465Sdelphij return 0; 351296465Sdelphij } 352296465Sdelphij } 353296465Sdelphij // printf("done\n"); 354109998Smarkm 355109998Smarkm return 1; 356296465Sdelphij} 357109998Smarkm 358296465Sdelphijstatic int dev_crypto_md5_update(EVP_MD_CTX *ctx, const void *data, 359296465Sdelphij unsigned long len) 360296465Sdelphij{ 361296465Sdelphij MD_DATA *md_data = ctx->md_data; 362109998Smarkm 363296465Sdelphij if (ctx->flags & EVP_MD_CTX_FLAG_ONESHOT) 364296465Sdelphij return do_digest(md_data->sess.ses, md_data->md, data, len); 365109998Smarkm 366296465Sdelphij md_data->data = OPENSSL_realloc(md_data->data, md_data->len + len); 367296465Sdelphij memcpy(md_data->data + md_data->len, data, len); 368296465Sdelphij md_data->len += len; 369109998Smarkm 370109998Smarkm return 1; 371296465Sdelphij} 372109998Smarkm 373296465Sdelphijstatic int dev_crypto_md5_final(EVP_MD_CTX *ctx, unsigned char *md) 374296465Sdelphij{ 375109998Smarkm int ret; 376296465Sdelphij MD_DATA *md_data = ctx->md_data; 377109998Smarkm 378296465Sdelphij if (ctx->flags & EVP_MD_CTX_FLAG_ONESHOT) { 379296465Sdelphij memcpy(md, md_data->md, MD5_DIGEST_LENGTH); 380296465Sdelphij ret = 1; 381296465Sdelphij } else { 382296465Sdelphij ret = do_digest(md_data->sess.ses, md, md_data->data, md_data->len); 383296465Sdelphij OPENSSL_free(md_data->data); 384296465Sdelphij md_data->data = NULL; 385296465Sdelphij md_data->len = 0; 386296465Sdelphij } 387109998Smarkm 388109998Smarkm return ret; 389296465Sdelphij} 390109998Smarkm 391296465Sdelphijstatic int dev_crypto_md5_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from) 392296465Sdelphij{ 393296465Sdelphij const MD_DATA *from_md = from->md_data; 394296465Sdelphij MD_DATA *to_md = to->md_data; 395109998Smarkm 396109998Smarkm // How do we copy sessions? 397296465Sdelphij assert(from->digest->flags & EVP_MD_FLAG_ONESHOT); 398109998Smarkm 399296465Sdelphij to_md->data = OPENSSL_malloc(from_md->len); 400296465Sdelphij memcpy(to_md->data, from_md->data, from_md->len); 401109998Smarkm 402109998Smarkm return 1; 403296465Sdelphij} 404109998Smarkm 405109998Smarkmstatic int dev_crypto_md5_cleanup(EVP_MD_CTX *ctx) 406296465Sdelphij{ 407109998Smarkm return dev_crypto_cleanup_digest(ctx->md_data); 408296465Sdelphij} 409109998Smarkm 410296465Sdelphijstatic const EVP_MD md5_md = { 411109998Smarkm NID_md5, 412109998Smarkm NID_md5WithRSAEncryption, 413109998Smarkm MD5_DIGEST_LENGTH, 414296465Sdelphij EVP_MD_FLAG_ONESHOT, // XXX: set according to device info... 415109998Smarkm dev_crypto_md5_init, 416109998Smarkm dev_crypto_md5_update, 417109998Smarkm dev_crypto_md5_final, 418109998Smarkm dev_crypto_md5_copy, 419109998Smarkm dev_crypto_md5_cleanup, 420109998Smarkm EVP_PKEY_RSA_method, 421109998Smarkm MD5_CBLOCK, 422109998Smarkm sizeof(MD_DATA), 423296465Sdelphij}; 424109998Smarkm 425109998Smarkmconst EVP_MD *EVP_dev_crypto_md5(void) 426296465Sdelphij{ 427296465Sdelphij return &md5_md; 428296465Sdelphij} 429109998Smarkm 430296465Sdelphij# endif 431109998Smarkm#endif 432