os/ossrv/ssl/libcrypto/src/crypto/evp/openbsd_hw.c
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
/* Written by Ben Laurie, 2001 */
sl@0
     2
/*
sl@0
     3
 * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
sl@0
     4
 *
sl@0
     5
 * Redistribution and use in source and binary forms, with or without
sl@0
     6
 * modification, are permitted provided that the following conditions
sl@0
     7
 * are met:
sl@0
     8
 *
sl@0
     9
 * 1. Redistributions of source code must retain the above copyright
sl@0
    10
 *    notice, this list of conditions and the following disclaimer. 
sl@0
    11
 *
sl@0
    12
 * 2. Redistributions in binary form must reproduce the above copyright
sl@0
    13
 *    notice, this list of conditions and the following disclaimer in
sl@0
    14
 *    the documentation and/or other materials provided with the
sl@0
    15
 *    distribution.
sl@0
    16
 *
sl@0
    17
 * 3. All advertising materials mentioning features or use of this
sl@0
    18
 *    software must display the following acknowledgment:
sl@0
    19
 *    "This product includes software developed by the OpenSSL Project
sl@0
    20
 *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
sl@0
    21
 *
sl@0
    22
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
sl@0
    23
 *    endorse or promote products derived from this software without
sl@0
    24
 *    prior written permission. For written permission, please contact
sl@0
    25
 *    openssl-core@openssl.org.
sl@0
    26
 *
sl@0
    27
 * 5. Products derived from this software may not be called "OpenSSL"
sl@0
    28
 *    nor may "OpenSSL" appear in their names without prior written
sl@0
    29
 *    permission of the OpenSSL Project.
sl@0
    30
 *
sl@0
    31
 * 6. Redistributions of any form whatsoever must retain the following
sl@0
    32
 *    acknowledgment:
sl@0
    33
 *    "This product includes software developed by the OpenSSL Project
sl@0
    34
 *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
sl@0
    35
 *
sl@0
    36
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
sl@0
    37
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
sl@0
    38
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
sl@0
    39
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
sl@0
    40
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
sl@0
    41
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
sl@0
    42
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
sl@0
    43
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
sl@0
    44
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
sl@0
    45
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
sl@0
    46
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
sl@0
    47
 * OF THE POSSIBILITY OF SUCH DAMAGE.
sl@0
    48
 */
sl@0
    49
sl@0
    50
#include <openssl/evp.h>
sl@0
    51
#include <openssl/objects.h>
sl@0
    52
#include <openssl/rsa.h>
sl@0
    53
#include "evp_locl.h"
sl@0
    54
sl@0
    55
/* This stuff should now all be supported through
sl@0
    56
 * crypto/engine/hw_openbsd_dev_crypto.c unless I botched it up */
sl@0
    57
static void *dummy=&dummy;
sl@0
    58
sl@0
    59
#if 0
sl@0
    60
sl@0
    61
/* check flag after OpenSSL headers to ensure make depend works */
sl@0
    62
#ifdef OPENSSL_OPENBSD_DEV_CRYPTO
sl@0
    63
sl@0
    64
#include <fcntl.h>
sl@0
    65
#include <stdio.h>
sl@0
    66
#include <errno.h>
sl@0
    67
#include <sys/ioctl.h>
sl@0
    68
#include <crypto/cryptodev.h>
sl@0
    69
#include <unistd.h>
sl@0
    70
#include <assert.h>
sl@0
    71
sl@0
    72
/* longest key supported in hardware */
sl@0
    73
#define MAX_HW_KEY	24
sl@0
    74
#define MAX_HW_IV	8
sl@0
    75
sl@0
    76
#define MD5_DIGEST_LENGTH	16
sl@0
    77
#define MD5_CBLOCK		64
sl@0
    78
sl@0
    79
static int fd;
sl@0
    80
static int dev_failed;
sl@0
    81
sl@0
    82
typedef struct session_op session_op;
sl@0
    83
sl@0
    84
#define CDATA(ctx) EVP_C_DATA(session_op,ctx)
sl@0
    85
sl@0
    86
static void err(const char *str)
sl@0
    87
    {
sl@0
    88
    fprintf(stderr,"%s: errno %d\n",str,errno);
sl@0
    89
    }
sl@0
    90
sl@0
    91
static int dev_crypto_init(session_op *ses)
sl@0
    92
    {
sl@0
    93
    if(dev_failed)
sl@0
    94
	return 0;
sl@0
    95
    if(!fd)
sl@0
    96
	{
sl@0
    97
	int cryptodev_fd;
sl@0
    98
sl@0
    99
        if ((cryptodev_fd=open("/dev/crypto",O_RDWR,0)) < 0)
sl@0
   100
	    {
sl@0
   101
	    err("/dev/crypto");
sl@0
   102
	    dev_failed=1;
sl@0
   103
	    return 0;
sl@0
   104
	    }
sl@0
   105
        if (ioctl(cryptodev_fd,CRIOGET,&fd) == -1)
sl@0
   106
	    {
sl@0
   107
	    err("CRIOGET failed");
sl@0
   108
	    close(cryptodev_fd);
sl@0
   109
	    dev_failed=1;
sl@0
   110
	    return 0;
sl@0
   111
	    }
sl@0
   112
	close(cryptodev_fd);
sl@0
   113
	}
sl@0
   114
    assert(ses);
sl@0
   115
    memset(ses,'\0',sizeof *ses);
sl@0
   116
sl@0
   117
    return 1;
sl@0
   118
    }
sl@0
   119
sl@0
   120
static int dev_crypto_cleanup(EVP_CIPHER_CTX *ctx)
sl@0
   121
    {
sl@0
   122
    if(ioctl(fd,CIOCFSESSION,&CDATA(ctx)->ses) == -1)
sl@0
   123
	err("CIOCFSESSION failed");
sl@0
   124
sl@0
   125
    OPENSSL_free(CDATA(ctx)->key);
sl@0
   126
sl@0
   127
    return 1;
sl@0
   128
    }
sl@0
   129
sl@0
   130
static int dev_crypto_init_key(EVP_CIPHER_CTX *ctx,int cipher,
sl@0
   131
			       const unsigned char *key,int klen)
sl@0
   132
    {
sl@0
   133
    if(!dev_crypto_init(CDATA(ctx)))
sl@0
   134
	return 0;
sl@0
   135
sl@0
   136
    CDATA(ctx)->key=OPENSSL_malloc(MAX_HW_KEY);
sl@0
   137
sl@0
   138
    assert(ctx->cipher->iv_len <= MAX_HW_IV);
sl@0
   139
sl@0
   140
    memcpy(CDATA(ctx)->key,key,klen);
sl@0
   141
    
sl@0
   142
    CDATA(ctx)->cipher=cipher;
sl@0
   143
    CDATA(ctx)->keylen=klen;
sl@0
   144
sl@0
   145
    if (ioctl(fd,CIOCGSESSION,CDATA(ctx)) == -1)
sl@0
   146
	{
sl@0
   147
	err("CIOCGSESSION failed");
sl@0
   148
	return 0;
sl@0
   149
	}
sl@0
   150
    return 1;
sl@0
   151
    }
sl@0
   152
sl@0
   153
static int dev_crypto_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out,
sl@0
   154
			     const unsigned char *in,unsigned int inl)
sl@0
   155
    {
sl@0
   156
    struct crypt_op cryp;
sl@0
   157
    unsigned char lb[MAX_HW_IV];
sl@0
   158
sl@0
   159
    if(!inl)
sl@0
   160
	return 1;
sl@0
   161
sl@0
   162
    assert(CDATA(ctx));
sl@0
   163
    assert(!dev_failed);
sl@0
   164
sl@0
   165
    memset(&cryp,'\0',sizeof cryp);
sl@0
   166
    cryp.ses=CDATA(ctx)->ses;
sl@0
   167
    cryp.op=ctx->encrypt ? COP_ENCRYPT : COP_DECRYPT;
sl@0
   168
    cryp.flags=0;
sl@0
   169
    cryp.len=inl;
sl@0
   170
    assert((inl&(ctx->cipher->block_size-1)) == 0);
sl@0
   171
    cryp.src=(caddr_t)in;
sl@0
   172
    cryp.dst=(caddr_t)out;
sl@0
   173
    cryp.mac=0;
sl@0
   174
    if(ctx->cipher->iv_len)
sl@0
   175
	cryp.iv=(caddr_t)ctx->iv;
sl@0
   176
sl@0
   177
    if(!ctx->encrypt)
sl@0
   178
	memcpy(lb,&in[cryp.len-ctx->cipher->iv_len],ctx->cipher->iv_len);
sl@0
   179
sl@0
   180
    if(ioctl(fd, CIOCCRYPT, &cryp) == -1)
sl@0
   181
	{
sl@0
   182
	if(errno == EINVAL) /* buffers are misaligned */
sl@0
   183
	    {
sl@0
   184
	    unsigned int cinl=0;
sl@0
   185
	    char *cin=NULL;
sl@0
   186
	    char *cout=NULL;
sl@0
   187
sl@0
   188
	    /* NB: this can only make cinl != inl with stream ciphers */
sl@0
   189
	    cinl=(inl+3)/4*4;
sl@0
   190
sl@0
   191
	    if(((unsigned long)in&3) || cinl != inl)
sl@0
   192
		{
sl@0
   193
		cin=OPENSSL_malloc(cinl);
sl@0
   194
		memcpy(cin,in,inl);
sl@0
   195
		cryp.src=cin;
sl@0
   196
		}
sl@0
   197
sl@0
   198
	    if(((unsigned long)out&3) || cinl != inl)
sl@0
   199
		{
sl@0
   200
		cout=OPENSSL_malloc(cinl);
sl@0
   201
		cryp.dst=cout;
sl@0
   202
		}
sl@0
   203
sl@0
   204
	    cryp.len=cinl;
sl@0
   205
sl@0
   206
	    if(ioctl(fd, CIOCCRYPT, &cryp) == -1)
sl@0
   207
		{
sl@0
   208
		err("CIOCCRYPT(2) failed");
sl@0
   209
		printf("src=%p dst=%p\n",cryp.src,cryp.dst);
sl@0
   210
		abort();
sl@0
   211
		return 0;
sl@0
   212
		}
sl@0
   213
		
sl@0
   214
	    if(cout)
sl@0
   215
		{
sl@0
   216
		memcpy(out,cout,inl);
sl@0
   217
		OPENSSL_free(cout);
sl@0
   218
		}
sl@0
   219
	    if(cin)
sl@0
   220
		OPENSSL_free(cin);
sl@0
   221
	    }
sl@0
   222
	else 
sl@0
   223
	    {	    
sl@0
   224
	    err("CIOCCRYPT failed");
sl@0
   225
	    abort();
sl@0
   226
	    return 0;
sl@0
   227
	    }
sl@0
   228
	}
sl@0
   229
sl@0
   230
    if(ctx->encrypt)
sl@0
   231
	memcpy(ctx->iv,&out[cryp.len-ctx->cipher->iv_len],ctx->cipher->iv_len);
sl@0
   232
    else
sl@0
   233
	memcpy(ctx->iv,lb,ctx->cipher->iv_len);
sl@0
   234
sl@0
   235
    return 1;
sl@0
   236
    }
sl@0
   237
sl@0
   238
static int dev_crypto_des_ede3_init_key(EVP_CIPHER_CTX *ctx,
sl@0
   239
					const unsigned char *key,
sl@0
   240
					const unsigned char *iv, int enc)
sl@0
   241
    { return dev_crypto_init_key(ctx,CRYPTO_3DES_CBC,key,24); }
sl@0
   242
sl@0
   243
#define dev_crypto_des_ede3_cbc_cipher dev_crypto_cipher
sl@0
   244
sl@0
   245
BLOCK_CIPHER_def_cbc(dev_crypto_des_ede3, session_op, NID_des_ede3, 8, 24, 8,
sl@0
   246
		     0, dev_crypto_des_ede3_init_key,
sl@0
   247
		     dev_crypto_cleanup, 
sl@0
   248
		     EVP_CIPHER_set_asn1_iv,
sl@0
   249
		     EVP_CIPHER_get_asn1_iv,
sl@0
   250
		     NULL)
sl@0
   251
sl@0
   252
static int dev_crypto_rc4_init_key(EVP_CIPHER_CTX *ctx,
sl@0
   253
					const unsigned char *key,
sl@0
   254
					const unsigned char *iv, int enc)
sl@0
   255
    { return dev_crypto_init_key(ctx,CRYPTO_ARC4,key,16); }
sl@0
   256
sl@0
   257
static const EVP_CIPHER r4_cipher=
sl@0
   258
    {
sl@0
   259
    NID_rc4,
sl@0
   260
    1,16,0,	/* FIXME: key should be up to 256 bytes */
sl@0
   261
    EVP_CIPH_VARIABLE_LENGTH,
sl@0
   262
    dev_crypto_rc4_init_key,
sl@0
   263
    dev_crypto_cipher,
sl@0
   264
    dev_crypto_cleanup,
sl@0
   265
    sizeof(session_op),
sl@0
   266
    NULL,
sl@0
   267
    NULL,
sl@0
   268
    NULL
sl@0
   269
    };
sl@0
   270
sl@0
   271
const EVP_CIPHER *EVP_dev_crypto_rc4(void)
sl@0
   272
    { return &r4_cipher; }
sl@0
   273
sl@0
   274
typedef struct
sl@0
   275
    {
sl@0
   276
    session_op sess;
sl@0
   277
    char *data;
sl@0
   278
    int len;
sl@0
   279
    unsigned char md[EVP_MAX_MD_SIZE];
sl@0
   280
    } MD_DATA;
sl@0
   281
sl@0
   282
static int dev_crypto_init_digest(MD_DATA *md_data,int mac)
sl@0
   283
    {
sl@0
   284
    if(!dev_crypto_init(&md_data->sess))
sl@0
   285
	return 0;
sl@0
   286
sl@0
   287
    md_data->len=0;
sl@0
   288
    md_data->data=NULL;
sl@0
   289
sl@0
   290
    md_data->sess.mac=mac;
sl@0
   291
sl@0
   292
    if (ioctl(fd,CIOCGSESSION,&md_data->sess) == -1)
sl@0
   293
	{
sl@0
   294
	err("CIOCGSESSION failed");
sl@0
   295
	return 0;
sl@0
   296
	}
sl@0
   297
    return 1;
sl@0
   298
    }
sl@0
   299
sl@0
   300
static int dev_crypto_cleanup_digest(MD_DATA *md_data)
sl@0
   301
    {
sl@0
   302
    if (ioctl(fd,CIOCFSESSION,&md_data->sess.ses) == -1)
sl@0
   303
	{
sl@0
   304
	err("CIOCFSESSION failed");
sl@0
   305
	return 0;
sl@0
   306
	}
sl@0
   307
sl@0
   308
    return 1;
sl@0
   309
    }
sl@0
   310
sl@0
   311
/* FIXME: if device can do chained MACs, then don't accumulate */
sl@0
   312
/* FIXME: move accumulation to the framework */
sl@0
   313
static int dev_crypto_md5_init(EVP_MD_CTX *ctx)
sl@0
   314
    { return dev_crypto_init_digest(ctx->md_data,CRYPTO_MD5); }
sl@0
   315
sl@0
   316
static int do_digest(int ses,unsigned char *md,const void *data,int len)
sl@0
   317
    {
sl@0
   318
    struct crypt_op cryp;
sl@0
   319
    static unsigned char md5zero[16]=
sl@0
   320
	{
sl@0
   321
	0xd4,0x1d,0x8c,0xd9,0x8f,0x00,0xb2,0x04,
sl@0
   322
	0xe9,0x80,0x09,0x98,0xec,0xf8,0x42,0x7e
sl@0
   323
	};
sl@0
   324
sl@0
   325
    /* some cards can't do zero length */
sl@0
   326
    if(!len)
sl@0
   327
	{
sl@0
   328
	memcpy(md,md5zero,16);
sl@0
   329
	return 1;
sl@0
   330
	}
sl@0
   331
sl@0
   332
    memset(&cryp,'\0',sizeof cryp);
sl@0
   333
    cryp.ses=ses;
sl@0
   334
    cryp.op=COP_ENCRYPT;/* required to do the MAC rather than check it */
sl@0
   335
    cryp.len=len;
sl@0
   336
    cryp.src=(caddr_t)data;
sl@0
   337
    cryp.dst=(caddr_t)data; // FIXME!!!
sl@0
   338
    cryp.mac=(caddr_t)md;
sl@0
   339
sl@0
   340
    if(ioctl(fd, CIOCCRYPT, &cryp) == -1)
sl@0
   341
	{
sl@0
   342
	if(errno == EINVAL) /* buffer is misaligned */
sl@0
   343
	    {
sl@0
   344
	    char *dcopy;
sl@0
   345
sl@0
   346
	    dcopy=OPENSSL_malloc(len);
sl@0
   347
	    memcpy(dcopy,data,len);
sl@0
   348
	    cryp.src=dcopy;
sl@0
   349
	    cryp.dst=cryp.src; // FIXME!!!
sl@0
   350
sl@0
   351
	    if(ioctl(fd, CIOCCRYPT, &cryp) == -1)
sl@0
   352
		{
sl@0
   353
		err("CIOCCRYPT(MAC2) failed");
sl@0
   354
		abort();
sl@0
   355
		return 0;
sl@0
   356
		}
sl@0
   357
	    OPENSSL_free(dcopy);
sl@0
   358
	    }
sl@0
   359
	else
sl@0
   360
	    {
sl@0
   361
	    err("CIOCCRYPT(MAC) failed");
sl@0
   362
	    abort();
sl@0
   363
	    return 0;
sl@0
   364
	    }
sl@0
   365
	}
sl@0
   366
    //    printf("done\n");
sl@0
   367
sl@0
   368
    return 1;
sl@0
   369
    }
sl@0
   370
sl@0
   371
static int dev_crypto_md5_update(EVP_MD_CTX *ctx,const void *data,
sl@0
   372
				 unsigned long len)
sl@0
   373
    {
sl@0
   374
    MD_DATA *md_data=ctx->md_data;
sl@0
   375
sl@0
   376
    if(ctx->flags&EVP_MD_CTX_FLAG_ONESHOT)
sl@0
   377
	return do_digest(md_data->sess.ses,md_data->md,data,len);
sl@0
   378
sl@0
   379
    md_data->data=OPENSSL_realloc(md_data->data,md_data->len+len);
sl@0
   380
    memcpy(md_data->data+md_data->len,data,len);
sl@0
   381
    md_data->len+=len;
sl@0
   382
sl@0
   383
    return 1;
sl@0
   384
    }	
sl@0
   385
sl@0
   386
static int dev_crypto_md5_final(EVP_MD_CTX *ctx,unsigned char *md)
sl@0
   387
    {
sl@0
   388
    int ret;
sl@0
   389
    MD_DATA *md_data=ctx->md_data;
sl@0
   390
sl@0
   391
    if(ctx->flags&EVP_MD_CTX_FLAG_ONESHOT)
sl@0
   392
	{
sl@0
   393
	memcpy(md,md_data->md,MD5_DIGEST_LENGTH);
sl@0
   394
	ret=1;
sl@0
   395
	}
sl@0
   396
    else
sl@0
   397
	{
sl@0
   398
	ret=do_digest(md_data->sess.ses,md,md_data->data,md_data->len);
sl@0
   399
	OPENSSL_free(md_data->data);
sl@0
   400
	md_data->data=NULL;
sl@0
   401
	md_data->len=0;
sl@0
   402
	}
sl@0
   403
sl@0
   404
    return ret;
sl@0
   405
    }
sl@0
   406
sl@0
   407
static int dev_crypto_md5_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from)
sl@0
   408
    {
sl@0
   409
    const MD_DATA *from_md=from->md_data;
sl@0
   410
    MD_DATA *to_md=to->md_data;
sl@0
   411
sl@0
   412
    // How do we copy sessions?
sl@0
   413
    assert(from->digest->flags&EVP_MD_FLAG_ONESHOT);
sl@0
   414
sl@0
   415
    to_md->data=OPENSSL_malloc(from_md->len);
sl@0
   416
    memcpy(to_md->data,from_md->data,from_md->len);
sl@0
   417
sl@0
   418
    return 1;
sl@0
   419
    }
sl@0
   420
sl@0
   421
static int dev_crypto_md5_cleanup(EVP_MD_CTX *ctx)
sl@0
   422
    {
sl@0
   423
    return dev_crypto_cleanup_digest(ctx->md_data);
sl@0
   424
    }
sl@0
   425
sl@0
   426
static const EVP_MD md5_md=
sl@0
   427
    {
sl@0
   428
    NID_md5,
sl@0
   429
    NID_md5WithRSAEncryption,
sl@0
   430
    MD5_DIGEST_LENGTH,
sl@0
   431
    EVP_MD_FLAG_ONESHOT,	// XXX: set according to device info...
sl@0
   432
    dev_crypto_md5_init,
sl@0
   433
    dev_crypto_md5_update,
sl@0
   434
    dev_crypto_md5_final,
sl@0
   435
    dev_crypto_md5_copy,
sl@0
   436
    dev_crypto_md5_cleanup,
sl@0
   437
    EVP_PKEY_RSA_method,
sl@0
   438
    MD5_CBLOCK,
sl@0
   439
    sizeof(MD_DATA),
sl@0
   440
    };
sl@0
   441
sl@0
   442
const EVP_MD *EVP_dev_crypto_md5(void)
sl@0
   443
    { return &md5_md; }
sl@0
   444
sl@0
   445
#endif
sl@0
   446
#endif