os/ossrv/ssl/libcrypto/src/crypto/evp/openbsd_hw.c
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/ossrv/ssl/libcrypto/src/crypto/evp/openbsd_hw.c	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,446 @@
     1.4 +/* Written by Ben Laurie, 2001 */
     1.5 +/*
     1.6 + * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
     1.7 + *
     1.8 + * Redistribution and use in source and binary forms, with or without
     1.9 + * modification, are permitted provided that the following conditions
    1.10 + * are met:
    1.11 + *
    1.12 + * 1. Redistributions of source code must retain the above copyright
    1.13 + *    notice, this list of conditions and the following disclaimer. 
    1.14 + *
    1.15 + * 2. Redistributions in binary form must reproduce the above copyright
    1.16 + *    notice, this list of conditions and the following disclaimer in
    1.17 + *    the documentation and/or other materials provided with the
    1.18 + *    distribution.
    1.19 + *
    1.20 + * 3. All advertising materials mentioning features or use of this
    1.21 + *    software must display the following acknowledgment:
    1.22 + *    "This product includes software developed by the OpenSSL Project
    1.23 + *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
    1.24 + *
    1.25 + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
    1.26 + *    endorse or promote products derived from this software without
    1.27 + *    prior written permission. For written permission, please contact
    1.28 + *    openssl-core@openssl.org.
    1.29 + *
    1.30 + * 5. Products derived from this software may not be called "OpenSSL"
    1.31 + *    nor may "OpenSSL" appear in their names without prior written
    1.32 + *    permission of the OpenSSL Project.
    1.33 + *
    1.34 + * 6. Redistributions of any form whatsoever must retain the following
    1.35 + *    acknowledgment:
    1.36 + *    "This product includes software developed by the OpenSSL Project
    1.37 + *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
    1.38 + *
    1.39 + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
    1.40 + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    1.41 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    1.42 + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
    1.43 + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    1.44 + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    1.45 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    1.46 + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    1.47 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
    1.48 + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    1.49 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
    1.50 + * OF THE POSSIBILITY OF SUCH DAMAGE.
    1.51 + */
    1.52 +
    1.53 +#include <openssl/evp.h>
    1.54 +#include <openssl/objects.h>
    1.55 +#include <openssl/rsa.h>
    1.56 +#include "evp_locl.h"
    1.57 +
    1.58 +/* This stuff should now all be supported through
    1.59 + * crypto/engine/hw_openbsd_dev_crypto.c unless I botched it up */
    1.60 +static void *dummy=&dummy;
    1.61 +
    1.62 +#if 0
    1.63 +
    1.64 +/* check flag after OpenSSL headers to ensure make depend works */
    1.65 +#ifdef OPENSSL_OPENBSD_DEV_CRYPTO
    1.66 +
    1.67 +#include <fcntl.h>
    1.68 +#include <stdio.h>
    1.69 +#include <errno.h>
    1.70 +#include <sys/ioctl.h>
    1.71 +#include <crypto/cryptodev.h>
    1.72 +#include <unistd.h>
    1.73 +#include <assert.h>
    1.74 +
    1.75 +/* longest key supported in hardware */
    1.76 +#define MAX_HW_KEY	24
    1.77 +#define MAX_HW_IV	8
    1.78 +
    1.79 +#define MD5_DIGEST_LENGTH	16
    1.80 +#define MD5_CBLOCK		64
    1.81 +
    1.82 +static int fd;
    1.83 +static int dev_failed;
    1.84 +
    1.85 +typedef struct session_op session_op;
    1.86 +
    1.87 +#define CDATA(ctx) EVP_C_DATA(session_op,ctx)
    1.88 +
    1.89 +static void err(const char *str)
    1.90 +    {
    1.91 +    fprintf(stderr,"%s: errno %d\n",str,errno);
    1.92 +    }
    1.93 +
    1.94 +static int dev_crypto_init(session_op *ses)
    1.95 +    {
    1.96 +    if(dev_failed)
    1.97 +	return 0;
    1.98 +    if(!fd)
    1.99 +	{
   1.100 +	int cryptodev_fd;
   1.101 +
   1.102 +        if ((cryptodev_fd=open("/dev/crypto",O_RDWR,0)) < 0)
   1.103 +	    {
   1.104 +	    err("/dev/crypto");
   1.105 +	    dev_failed=1;
   1.106 +	    return 0;
   1.107 +	    }
   1.108 +        if (ioctl(cryptodev_fd,CRIOGET,&fd) == -1)
   1.109 +	    {
   1.110 +	    err("CRIOGET failed");
   1.111 +	    close(cryptodev_fd);
   1.112 +	    dev_failed=1;
   1.113 +	    return 0;
   1.114 +	    }
   1.115 +	close(cryptodev_fd);
   1.116 +	}
   1.117 +    assert(ses);
   1.118 +    memset(ses,'\0',sizeof *ses);
   1.119 +
   1.120 +    return 1;
   1.121 +    }
   1.122 +
   1.123 +static int dev_crypto_cleanup(EVP_CIPHER_CTX *ctx)
   1.124 +    {
   1.125 +    if(ioctl(fd,CIOCFSESSION,&CDATA(ctx)->ses) == -1)
   1.126 +	err("CIOCFSESSION failed");
   1.127 +
   1.128 +    OPENSSL_free(CDATA(ctx)->key);
   1.129 +
   1.130 +    return 1;
   1.131 +    }
   1.132 +
   1.133 +static int dev_crypto_init_key(EVP_CIPHER_CTX *ctx,int cipher,
   1.134 +			       const unsigned char *key,int klen)
   1.135 +    {
   1.136 +    if(!dev_crypto_init(CDATA(ctx)))
   1.137 +	return 0;
   1.138 +
   1.139 +    CDATA(ctx)->key=OPENSSL_malloc(MAX_HW_KEY);
   1.140 +
   1.141 +    assert(ctx->cipher->iv_len <= MAX_HW_IV);
   1.142 +
   1.143 +    memcpy(CDATA(ctx)->key,key,klen);
   1.144 +    
   1.145 +    CDATA(ctx)->cipher=cipher;
   1.146 +    CDATA(ctx)->keylen=klen;
   1.147 +
   1.148 +    if (ioctl(fd,CIOCGSESSION,CDATA(ctx)) == -1)
   1.149 +	{
   1.150 +	err("CIOCGSESSION failed");
   1.151 +	return 0;
   1.152 +	}
   1.153 +    return 1;
   1.154 +    }
   1.155 +
   1.156 +static int dev_crypto_cipher(EVP_CIPHER_CTX *ctx,unsigned char *out,
   1.157 +			     const unsigned char *in,unsigned int inl)
   1.158 +    {
   1.159 +    struct crypt_op cryp;
   1.160 +    unsigned char lb[MAX_HW_IV];
   1.161 +
   1.162 +    if(!inl)
   1.163 +	return 1;
   1.164 +
   1.165 +    assert(CDATA(ctx));
   1.166 +    assert(!dev_failed);
   1.167 +
   1.168 +    memset(&cryp,'\0',sizeof cryp);
   1.169 +    cryp.ses=CDATA(ctx)->ses;
   1.170 +    cryp.op=ctx->encrypt ? COP_ENCRYPT : COP_DECRYPT;
   1.171 +    cryp.flags=0;
   1.172 +    cryp.len=inl;
   1.173 +    assert((inl&(ctx->cipher->block_size-1)) == 0);
   1.174 +    cryp.src=(caddr_t)in;
   1.175 +    cryp.dst=(caddr_t)out;
   1.176 +    cryp.mac=0;
   1.177 +    if(ctx->cipher->iv_len)
   1.178 +	cryp.iv=(caddr_t)ctx->iv;
   1.179 +
   1.180 +    if(!ctx->encrypt)
   1.181 +	memcpy(lb,&in[cryp.len-ctx->cipher->iv_len],ctx->cipher->iv_len);
   1.182 +
   1.183 +    if(ioctl(fd, CIOCCRYPT, &cryp) == -1)
   1.184 +	{
   1.185 +	if(errno == EINVAL) /* buffers are misaligned */
   1.186 +	    {
   1.187 +	    unsigned int cinl=0;
   1.188 +	    char *cin=NULL;
   1.189 +	    char *cout=NULL;
   1.190 +
   1.191 +	    /* NB: this can only make cinl != inl with stream ciphers */
   1.192 +	    cinl=(inl+3)/4*4;
   1.193 +
   1.194 +	    if(((unsigned long)in&3) || cinl != inl)
   1.195 +		{
   1.196 +		cin=OPENSSL_malloc(cinl);
   1.197 +		memcpy(cin,in,inl);
   1.198 +		cryp.src=cin;
   1.199 +		}
   1.200 +
   1.201 +	    if(((unsigned long)out&3) || cinl != inl)
   1.202 +		{
   1.203 +		cout=OPENSSL_malloc(cinl);
   1.204 +		cryp.dst=cout;
   1.205 +		}
   1.206 +
   1.207 +	    cryp.len=cinl;
   1.208 +
   1.209 +	    if(ioctl(fd, CIOCCRYPT, &cryp) == -1)
   1.210 +		{
   1.211 +		err("CIOCCRYPT(2) failed");
   1.212 +		printf("src=%p dst=%p\n",cryp.src,cryp.dst);
   1.213 +		abort();
   1.214 +		return 0;
   1.215 +		}
   1.216 +		
   1.217 +	    if(cout)
   1.218 +		{
   1.219 +		memcpy(out,cout,inl);
   1.220 +		OPENSSL_free(cout);
   1.221 +		}
   1.222 +	    if(cin)
   1.223 +		OPENSSL_free(cin);
   1.224 +	    }
   1.225 +	else 
   1.226 +	    {	    
   1.227 +	    err("CIOCCRYPT failed");
   1.228 +	    abort();
   1.229 +	    return 0;
   1.230 +	    }
   1.231 +	}
   1.232 +
   1.233 +    if(ctx->encrypt)
   1.234 +	memcpy(ctx->iv,&out[cryp.len-ctx->cipher->iv_len],ctx->cipher->iv_len);
   1.235 +    else
   1.236 +	memcpy(ctx->iv,lb,ctx->cipher->iv_len);
   1.237 +
   1.238 +    return 1;
   1.239 +    }
   1.240 +
   1.241 +static int dev_crypto_des_ede3_init_key(EVP_CIPHER_CTX *ctx,
   1.242 +					const unsigned char *key,
   1.243 +					const unsigned char *iv, int enc)
   1.244 +    { return dev_crypto_init_key(ctx,CRYPTO_3DES_CBC,key,24); }
   1.245 +
   1.246 +#define dev_crypto_des_ede3_cbc_cipher dev_crypto_cipher
   1.247 +
   1.248 +BLOCK_CIPHER_def_cbc(dev_crypto_des_ede3, session_op, NID_des_ede3, 8, 24, 8,
   1.249 +		     0, dev_crypto_des_ede3_init_key,
   1.250 +		     dev_crypto_cleanup, 
   1.251 +		     EVP_CIPHER_set_asn1_iv,
   1.252 +		     EVP_CIPHER_get_asn1_iv,
   1.253 +		     NULL)
   1.254 +
   1.255 +static int dev_crypto_rc4_init_key(EVP_CIPHER_CTX *ctx,
   1.256 +					const unsigned char *key,
   1.257 +					const unsigned char *iv, int enc)
   1.258 +    { return dev_crypto_init_key(ctx,CRYPTO_ARC4,key,16); }
   1.259 +
   1.260 +static const EVP_CIPHER r4_cipher=
   1.261 +    {
   1.262 +    NID_rc4,
   1.263 +    1,16,0,	/* FIXME: key should be up to 256 bytes */
   1.264 +    EVP_CIPH_VARIABLE_LENGTH,
   1.265 +    dev_crypto_rc4_init_key,
   1.266 +    dev_crypto_cipher,
   1.267 +    dev_crypto_cleanup,
   1.268 +    sizeof(session_op),
   1.269 +    NULL,
   1.270 +    NULL,
   1.271 +    NULL
   1.272 +    };
   1.273 +
   1.274 +const EVP_CIPHER *EVP_dev_crypto_rc4(void)
   1.275 +    { return &r4_cipher; }
   1.276 +
   1.277 +typedef struct
   1.278 +    {
   1.279 +    session_op sess;
   1.280 +    char *data;
   1.281 +    int len;
   1.282 +    unsigned char md[EVP_MAX_MD_SIZE];
   1.283 +    } MD_DATA;
   1.284 +
   1.285 +static int dev_crypto_init_digest(MD_DATA *md_data,int mac)
   1.286 +    {
   1.287 +    if(!dev_crypto_init(&md_data->sess))
   1.288 +	return 0;
   1.289 +
   1.290 +    md_data->len=0;
   1.291 +    md_data->data=NULL;
   1.292 +
   1.293 +    md_data->sess.mac=mac;
   1.294 +
   1.295 +    if (ioctl(fd,CIOCGSESSION,&md_data->sess) == -1)
   1.296 +	{
   1.297 +	err("CIOCGSESSION failed");
   1.298 +	return 0;
   1.299 +	}
   1.300 +    return 1;
   1.301 +    }
   1.302 +
   1.303 +static int dev_crypto_cleanup_digest(MD_DATA *md_data)
   1.304 +    {
   1.305 +    if (ioctl(fd,CIOCFSESSION,&md_data->sess.ses) == -1)
   1.306 +	{
   1.307 +	err("CIOCFSESSION failed");
   1.308 +	return 0;
   1.309 +	}
   1.310 +
   1.311 +    return 1;
   1.312 +    }
   1.313 +
   1.314 +/* FIXME: if device can do chained MACs, then don't accumulate */
   1.315 +/* FIXME: move accumulation to the framework */
   1.316 +static int dev_crypto_md5_init(EVP_MD_CTX *ctx)
   1.317 +    { return dev_crypto_init_digest(ctx->md_data,CRYPTO_MD5); }
   1.318 +
   1.319 +static int do_digest(int ses,unsigned char *md,const void *data,int len)
   1.320 +    {
   1.321 +    struct crypt_op cryp;
   1.322 +    static unsigned char md5zero[16]=
   1.323 +	{
   1.324 +	0xd4,0x1d,0x8c,0xd9,0x8f,0x00,0xb2,0x04,
   1.325 +	0xe9,0x80,0x09,0x98,0xec,0xf8,0x42,0x7e
   1.326 +	};
   1.327 +
   1.328 +    /* some cards can't do zero length */
   1.329 +    if(!len)
   1.330 +	{
   1.331 +	memcpy(md,md5zero,16);
   1.332 +	return 1;
   1.333 +	}
   1.334 +
   1.335 +    memset(&cryp,'\0',sizeof cryp);
   1.336 +    cryp.ses=ses;
   1.337 +    cryp.op=COP_ENCRYPT;/* required to do the MAC rather than check it */
   1.338 +    cryp.len=len;
   1.339 +    cryp.src=(caddr_t)data;
   1.340 +    cryp.dst=(caddr_t)data; // FIXME!!!
   1.341 +    cryp.mac=(caddr_t)md;
   1.342 +
   1.343 +    if(ioctl(fd, CIOCCRYPT, &cryp) == -1)
   1.344 +	{
   1.345 +	if(errno == EINVAL) /* buffer is misaligned */
   1.346 +	    {
   1.347 +	    char *dcopy;
   1.348 +
   1.349 +	    dcopy=OPENSSL_malloc(len);
   1.350 +	    memcpy(dcopy,data,len);
   1.351 +	    cryp.src=dcopy;
   1.352 +	    cryp.dst=cryp.src; // FIXME!!!
   1.353 +
   1.354 +	    if(ioctl(fd, CIOCCRYPT, &cryp) == -1)
   1.355 +		{
   1.356 +		err("CIOCCRYPT(MAC2) failed");
   1.357 +		abort();
   1.358 +		return 0;
   1.359 +		}
   1.360 +	    OPENSSL_free(dcopy);
   1.361 +	    }
   1.362 +	else
   1.363 +	    {
   1.364 +	    err("CIOCCRYPT(MAC) failed");
   1.365 +	    abort();
   1.366 +	    return 0;
   1.367 +	    }
   1.368 +	}
   1.369 +    //    printf("done\n");
   1.370 +
   1.371 +    return 1;
   1.372 +    }
   1.373 +
   1.374 +static int dev_crypto_md5_update(EVP_MD_CTX *ctx,const void *data,
   1.375 +				 unsigned long len)
   1.376 +    {
   1.377 +    MD_DATA *md_data=ctx->md_data;
   1.378 +
   1.379 +    if(ctx->flags&EVP_MD_CTX_FLAG_ONESHOT)
   1.380 +	return do_digest(md_data->sess.ses,md_data->md,data,len);
   1.381 +
   1.382 +    md_data->data=OPENSSL_realloc(md_data->data,md_data->len+len);
   1.383 +    memcpy(md_data->data+md_data->len,data,len);
   1.384 +    md_data->len+=len;
   1.385 +
   1.386 +    return 1;
   1.387 +    }	
   1.388 +
   1.389 +static int dev_crypto_md5_final(EVP_MD_CTX *ctx,unsigned char *md)
   1.390 +    {
   1.391 +    int ret;
   1.392 +    MD_DATA *md_data=ctx->md_data;
   1.393 +
   1.394 +    if(ctx->flags&EVP_MD_CTX_FLAG_ONESHOT)
   1.395 +	{
   1.396 +	memcpy(md,md_data->md,MD5_DIGEST_LENGTH);
   1.397 +	ret=1;
   1.398 +	}
   1.399 +    else
   1.400 +	{
   1.401 +	ret=do_digest(md_data->sess.ses,md,md_data->data,md_data->len);
   1.402 +	OPENSSL_free(md_data->data);
   1.403 +	md_data->data=NULL;
   1.404 +	md_data->len=0;
   1.405 +	}
   1.406 +
   1.407 +    return ret;
   1.408 +    }
   1.409 +
   1.410 +static int dev_crypto_md5_copy(EVP_MD_CTX *to,const EVP_MD_CTX *from)
   1.411 +    {
   1.412 +    const MD_DATA *from_md=from->md_data;
   1.413 +    MD_DATA *to_md=to->md_data;
   1.414 +
   1.415 +    // How do we copy sessions?
   1.416 +    assert(from->digest->flags&EVP_MD_FLAG_ONESHOT);
   1.417 +
   1.418 +    to_md->data=OPENSSL_malloc(from_md->len);
   1.419 +    memcpy(to_md->data,from_md->data,from_md->len);
   1.420 +
   1.421 +    return 1;
   1.422 +    }
   1.423 +
   1.424 +static int dev_crypto_md5_cleanup(EVP_MD_CTX *ctx)
   1.425 +    {
   1.426 +    return dev_crypto_cleanup_digest(ctx->md_data);
   1.427 +    }
   1.428 +
   1.429 +static const EVP_MD md5_md=
   1.430 +    {
   1.431 +    NID_md5,
   1.432 +    NID_md5WithRSAEncryption,
   1.433 +    MD5_DIGEST_LENGTH,
   1.434 +    EVP_MD_FLAG_ONESHOT,	// XXX: set according to device info...
   1.435 +    dev_crypto_md5_init,
   1.436 +    dev_crypto_md5_update,
   1.437 +    dev_crypto_md5_final,
   1.438 +    dev_crypto_md5_copy,
   1.439 +    dev_crypto_md5_cleanup,
   1.440 +    EVP_PKEY_RSA_method,
   1.441 +    MD5_CBLOCK,
   1.442 +    sizeof(MD_DATA),
   1.443 +    };
   1.444 +
   1.445 +const EVP_MD *EVP_dev_crypto_md5(void)
   1.446 +    { return &md5_md; }
   1.447 +
   1.448 +#endif
   1.449 +#endif