openssl/demos/engines/zencod/hw_zencod.c
Richard Levitte 04ed3994e2 OK, I've amused myself with making sure the engines that have been
contributed TO WORK WITH 0.9.7 can be built as dynamically loadable
libraries.

For now, they're not included in crypto/engine/ since 0.9.7 is in
feature freeze.  Further discussion might change that, but don't hold
your breath.
2002-08-13 12:26:41 +00:00

1736 lines
46 KiB
C

/* crypto/engine/hw_zencod.c */
/* Written by Fred Donnat (frederic.donnat@zencod.com) for "zencod"
* engine integration in order to redirect crypto computing on a crypto
* hardware accelerator zenssl32 ;-)
*
* Date : 25 jun 2002
* Revision : 17 Ju7 2002
* Version : zencod_engine-0.9.7
*/
/* ====================================================================
* Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* licensing@OpenSSL.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
/* ENGINE general include */
#include <stdio.h>
#include <openssl/crypto.h>
#include <openssl/dso.h>
#include <openssl/engine.h>
#ifndef OPENSSL_NO_HW
#ifndef OPENSSL_NO_HW_ZENCOD
#ifdef FLAT_INC
# include "hw_zencod.h"
#else
# include "vendor_defns/hw_zencod.h"
#endif
#define ZENCOD_LIB_NAME "zencod engine"
#include "hw_zencod_err.c"
#define FAIL_TO_SOFTWARE -15
#define ZEN_LIBRARY "zenbridge"
#if 0
# define PERROR(s) perror(s)
# define CHEESE() fputs("## [ZenEngine] ## " __FUNCTION__ "\n", stderr)
#else
# define PERROR(s)
# define CHEESE()
#endif
/* Sorry ;) */
#ifndef WIN32
static inline void esrever ( unsigned char *d, int l )
{
for(;--l>0;--l,d++){*d^=*(d+l);*(d+l)^=*d;*d^=*(d+l);}
}
static inline void ypcmem ( unsigned char *d, const unsigned char *s, int l )
{
for(d+=l;l--;)*--d=*s++;
}
#else
static __inline void esrever ( unsigned char *d, int l )
{
for(;--l>0;--l,d++){*d^=*(d+l);*(d+l)^=*d;*d^=*(d+l);}
}
static __inline void ypcmem ( unsigned char *d, const unsigned char *s, int l )
{
for(d+=l;l--;)*--d=*s++;
}
#endif
#define BIGNUM2ZEN(n, bn) (ptr_zencod_init_number((n), \
(unsigned long) ((bn)->top * BN_BITS2), \
(unsigned char *) ((bn)->d)))
#define ZEN_BITS(n, bytes) (ptr_zencod_bytes2bits((unsigned char *) (n), (unsigned long) (bytes)))
#define ZEN_BYTES(bits) (ptr_zencod_bits2bytes((unsigned long) (bits)))
/* Function for ENGINE detection and control */
static int zencod_destroy ( ENGINE *e ) ;
static int zencod_init ( ENGINE *e ) ;
static int zencod_finish ( ENGINE *e ) ;
static int zencod_ctrl ( ENGINE *e, int cmd, long i, void *p, void (*f) () ) ;
/* BIGNUM stuff */
static int zencod_bn_mod_exp ( BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx ) ;
/* RSA stuff */
#ifndef OPENSSL_NO_RSA
static int RSA_zencod_rsa_mod_exp ( BIGNUM *r0, const BIGNUM *I, RSA *rsa ) ;
static int RSA_zencod_bn_mod_exp ( BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx ) ;
#endif
/* DSA stuff */
#ifndef OPENSSL_NO_DSA
static int DSA_zencod_bn_mod_exp ( DSA *dsa, BIGNUM *r, BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
BN_MONT_CTX *m_ctx ) ;
static DSA_SIG *DSA_zencod_do_sign ( const unsigned char *dgst, int dlen, DSA *dsa ) ;
static int DSA_zencod_do_verify ( const unsigned char *dgst, int dgst_len, DSA_SIG *sig,
DSA *dsa ) ;
#endif
/* DH stuff */
#ifndef OPENSSL_NO_DH
static int DH_zencod_bn_mod_exp ( const DH *dh, BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
BN_MONT_CTX *m_ctx ) ;
static int DH_zencod_generate_key ( DH *dh ) ;
static int DH_zencod_compute_key ( unsigned char *key, const BIGNUM *pub_key, DH *dh ) ;
#endif
/* Rand stuff */
static void RAND_zencod_seed ( const void *buf, int num ) ;
static int RAND_zencod_rand_bytes ( unsigned char *buf, int num ) ;
static int RAND_zencod_rand_status ( void ) ;
/* Digest Stuff */
static int engine_digests ( ENGINE *e, const EVP_MD **digest, const int **nids, int nid ) ;
/* Cipher Stuff */
static int engine_ciphers ( ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid ) ;
#define ZENCOD_CMD_SO_PATH ENGINE_CMD_BASE
static const ENGINE_CMD_DEFN zencod_cmd_defns [ ] =
{
{ ZENCOD_CMD_SO_PATH,
"SO_PATH",
"Specifies the path to the 'zenbridge' shared library",
ENGINE_CMD_FLAG_STRING},
{ 0, NULL, NULL, 0 }
} ;
#ifndef OPENSSL_NO_RSA
/* Our internal RSA_METHOD specific to zencod ENGINE providing pointers to our function */
static RSA_METHOD zencod_rsa =
{
"ZENCOD RSA method",
NULL,
NULL,
NULL,
NULL,
RSA_zencod_rsa_mod_exp,
RSA_zencod_bn_mod_exp,
NULL,
NULL,
0,
NULL,
NULL,
NULL
} ;
#endif
#ifndef OPENSSL_NO_DSA
/* Our internal DSA_METHOD specific to zencod ENGINE providing pointers to our function */
static DSA_METHOD zencod_dsa =
{
"ZENCOD DSA method",
DSA_zencod_do_sign,
NULL,
DSA_zencod_do_verify,
NULL,
DSA_zencod_bn_mod_exp,
NULL,
NULL,
0,
NULL
} ;
#endif
#ifndef OPENSSL_NO_DH
/* Our internal DH_METHOD specific to zencod ENGINE providing pointers to our function */
static DH_METHOD zencod_dh =
{
"ZENCOD DH method",
DH_zencod_generate_key,
DH_zencod_compute_key,
DH_zencod_bn_mod_exp,
NULL,
NULL,
0,
NULL
} ;
#endif
/* Our internal RAND_meth specific to zencod ZNGINE providing pointers to our function */
static RAND_METHOD zencod_rand =
{
RAND_zencod_seed,
RAND_zencod_rand_bytes,
NULL,
NULL,
RAND_zencod_rand_bytes,
RAND_zencod_rand_status
} ;
/* Constants used when creating the ENGINE */
static const char *engine_zencod_id = "zencod";
static const char *engine_zencod_name = "ZENCOD hardware engine support";
/* This internal function is used by ENGINE_zencod () and possibly by the
* "dynamic" ENGINE support too ;-)
*/
static int bind_helper ( ENGINE *e )
{
#ifndef OPENSSL_NO_RSA
const RSA_METHOD *meth_rsa ;
#endif
#ifndef OPENSSL_NO_DSA
const DSA_METHOD *meth_dsa ;
#endif
#ifndef OPENSSL_NO_DH
const DH_METHOD *meth_dh ;
#endif
const RAND_METHOD *meth_rand ;
if ( !ENGINE_set_id ( e, engine_zencod_id ) ||
!ENGINE_set_name ( e, engine_zencod_name ) ||
#ifndef OPENSSL_NO_RSA
!ENGINE_set_RSA ( e, &zencod_rsa ) ||
#endif
#ifndef OPENSSL_NO_DSA
!ENGINE_set_DSA ( e, &zencod_dsa ) ||
#endif
#ifndef OPENSSL_NO_DH
!ENGINE_set_DH ( e, &zencod_dh ) ||
#endif
!ENGINE_set_RAND ( e, &zencod_rand ) ||
!ENGINE_set_destroy_function ( e, zencod_destroy ) ||
!ENGINE_set_init_function ( e, zencod_init ) ||
!ENGINE_set_finish_function ( e, zencod_finish ) ||
!ENGINE_set_ctrl_function ( e, zencod_ctrl ) ||
!ENGINE_set_cmd_defns ( e, zencod_cmd_defns ) ||
!ENGINE_set_digests ( e, engine_digests ) ||
!ENGINE_set_ciphers ( e, engine_ciphers ) ) {
return 0 ;
}
#ifndef OPENSSL_NO_RSA
/* We know that the "PKCS1_SSLeay()" functions hook properly
* to the Zencod-specific mod_exp and mod_exp_crt so we use
* those functions. NB: We don't use ENGINE_openssl() or
* anything "more generic" because something like the RSAref
* code may not hook properly, and if you own one of these
* cards then you have the right to do RSA operations on it
* anyway!
*/
meth_rsa = RSA_PKCS1_SSLeay () ;
zencod_rsa.rsa_pub_enc = meth_rsa->rsa_pub_enc ;
zencod_rsa.rsa_pub_dec = meth_rsa->rsa_pub_dec ;
zencod_rsa.rsa_priv_enc = meth_rsa->rsa_priv_enc ;
zencod_rsa.rsa_priv_dec = meth_rsa->rsa_priv_dec ;
/* meth_rsa->rsa_mod_exp */
/* meth_rsa->bn_mod_exp */
zencod_rsa.init = meth_rsa->init ;
zencod_rsa.finish = meth_rsa->finish ;
#endif
#ifndef OPENSSL_NO_DSA
/* We use OpenSSL meth to supply what we don't provide ;-*)
*/
meth_dsa = DSA_OpenSSL () ;
/* meth_dsa->dsa_do_sign */
zencod_dsa.dsa_sign_setup = meth_dsa->dsa_sign_setup ;
/* meth_dsa->dsa_do_verify */
zencod_dsa.dsa_mod_exp = meth_dsa->dsa_mod_exp ;
/* zencod_dsa.bn_mod_exp = meth_dsa->bn_mod_exp ; */
zencod_dsa.init = meth_dsa->init ;
zencod_dsa.finish = meth_dsa->finish ;
#endif
#ifndef OPENSSL_NO_DH
/* We use OpenSSL meth to supply what we don't provide ;-*)
*/
meth_dh = DH_OpenSSL () ;
/* zencod_dh.generate_key = meth_dh->generate_key ; */
/* zencod_dh.compute_key = meth_dh->compute_key ; */
/* zencod_dh.bn_mod_exp = meth_dh->bn_mod_exp ; */
zencod_dh.init = meth_dh->init ;
zencod_dh.finish = meth_dh->finish ;
#endif
/* We use OpenSSL (SSLeay) meth to supply what we don't provide ;-*)
*/
meth_rand = RAND_SSLeay () ;
/* meth_rand->seed ; */
/* zencod_rand.seed = meth_rand->seed ; */
/* meth_rand->bytes ; */
/* zencod_rand.bytes = meth_rand->bytes ; */
zencod_rand.cleanup = meth_rand->cleanup ;
zencod_rand.add = meth_rand->add ;
/* meth_rand->pseudorand ; */
/* zencod_rand.pseudorand = meth_rand->pseudorand ; */
/* zencod_rand.status = meth_rand->status ; */
/* meth_rand->status ; */
/* Ensure the zencod error handling is set up */
ERR_load_ZENCOD_strings () ;
return 1 ;
}
/* As this is only ever called once, there's no need for locking
* (indeed - the lock will already be held by our caller!!!)
*/
ENGINE *ENGINE_zencod ( void )
{
ENGINE *eng = ENGINE_new () ;
if ( !eng ) {
return NULL ;
}
if ( !bind_helper ( eng ) ) {
ENGINE_free ( eng ) ;
return NULL ;
}
return eng ;
}
void ENGINE_load_zencod ( void )
{
/* Copied from eng_[openssl|dyn].c */
ENGINE *toadd = ENGINE_zencod ( ) ;
if ( !toadd ) return ;
ENGINE_add ( toadd ) ;
ENGINE_free ( toadd ) ;
ERR_clear_error ( ) ;
}
/* This is a process-global DSO handle used for loading and unloading
* the ZENBRIDGE library.
* NB: This is only set (or unset) during an * init () or finish () call
* (reference counts permitting) and they're * operating with global locks,
* so this should be thread-safe * implicitly.
*/
static DSO *zencod_dso = NULL ;
static t_zencod_test *ptr_zencod_test = NULL ;
static t_zencod_bytes2bits *ptr_zencod_bytes2bits = NULL ;
static t_zencod_bits2bytes *ptr_zencod_bits2bytes = NULL ;
static t_zencod_new_number *ptr_zencod_new_number = NULL ;
static t_zencod_init_number *ptr_zencod_init_number = NULL ;
static t_zencod_rsa_mod_exp *ptr_zencod_rsa_mod_exp = NULL ;
static t_zencod_rsa_mod_exp_crt *ptr_zencod_rsa_mod_exp_crt = NULL ;
static t_zencod_dsa_do_sign *ptr_zencod_dsa_do_sign = NULL ;
static t_zencod_dsa_do_verify *ptr_zencod_dsa_do_verify = NULL ;
static t_zencod_dh_generate_key *ptr_zencod_dh_generate_key = NULL ;
static t_zencod_dh_compute_key *ptr_zencod_dh_compute_key = NULL ;
static t_zencod_rand_bytes *ptr_zencod_rand_bytes = NULL ;
static t_zencod_math_mod_exp *ptr_zencod_math_mod_exp = NULL ;
static t_zencod_md5_init *ptr_zencod_md5_init = NULL ;
static t_zencod_md5_update *ptr_zencod_md5_update = NULL ;
static t_zencod_md5_do_final *ptr_zencod_md5_do_final = NULL ;
static t_zencod_sha1_init *ptr_zencod_sha1_init = NULL ;
static t_zencod_sha1_update *ptr_zencod_sha1_update = NULL ;
static t_zencod_sha1_do_final *ptr_zencod_sha1_do_final = NULL ;
static t_zencod_xdes_cipher *ptr_zencod_xdes_cipher = NULL ;
static t_zencod_rc4_cipher *ptr_zencod_rc4_cipher = NULL ;
/* These are the static string constants for the DSO file name and the function
* symbol names to bind to.
*/
static const char *ZENCOD_LIBNAME = ZEN_LIBRARY ;
static const char *ZENCOD_Fct_0 = "test_device" ;
static const char *ZENCOD_Fct_1 = "zenbridge_bytes2bits" ;
static const char *ZENCOD_Fct_2 = "zenbridge_bits2bytes" ;
static const char *ZENCOD_Fct_3 = "zenbridge_new_number" ;
static const char *ZENCOD_Fct_4 = "zenbridge_init_number" ;
static const char *ZENCOD_Fct_exp_1 = "zenbridge_rsa_mod_exp" ;
static const char *ZENCOD_Fct_exp_2 = "zenbridge_rsa_mod_exp_crt" ;
static const char *ZENCOD_Fct_dsa_1 = "zenbridge_dsa_do_sign" ;
static const char *ZENCOD_Fct_dsa_2 = "zenbridge_dsa_do_verify" ;
static const char *ZENCOD_Fct_dh_1 = "zenbridge_dh_generate_key" ;
static const char *ZENCOD_Fct_dh_2 = "zenbridge_dh_compute_key" ;
static const char *ZENCOD_Fct_rand_1 = "zenbridge_rand_bytes" ;
static const char *ZENCOD_Fct_math_1 = "zenbridge_math_mod_exp" ;
static const char *ZENCOD_Fct_md5_1 = "zenbridge_md5_init" ;
static const char *ZENCOD_Fct_md5_2 = "zenbridge_md5_update" ;
static const char *ZENCOD_Fct_md5_3 = "zenbridge_md5_do_final" ;
static const char *ZENCOD_Fct_sha1_1 = "zenbridge_sha1_init" ;
static const char *ZENCOD_Fct_sha1_2 = "zenbridge_sha1_update" ;
static const char *ZENCOD_Fct_sha1_3 = "zenbridge_sha1_do_final" ;
static const char *ZENCOD_Fct_xdes_1 = "zenbridge_xdes_cipher" ;
static const char *ZENCOD_Fct_rc4_1 = "zenbridge_rc4_cipher" ;
/* Destructor (complements the "ENGINE_zencod ()" constructor)
*/
static int zencod_destroy (ENGINE *e )
{
ERR_unload_ZENCOD_strings () ;
return 1 ;
}
/* (de)initialisation functions. Control Function
*/
static int zencod_init ( ENGINE *e )
{
t_zencod_test *ptr_0 ;
t_zencod_bytes2bits *ptr_1 ;
t_zencod_bits2bytes *ptr_2 ;
t_zencod_new_number *ptr_3 ;
t_zencod_init_number *ptr_4 ;
t_zencod_rsa_mod_exp *ptr_exp_1 ;
t_zencod_rsa_mod_exp_crt *ptr_exp_2 ;
t_zencod_dsa_do_sign *ptr_dsa_1 ;
t_zencod_dsa_do_verify *ptr_dsa_2 ;
t_zencod_dh_generate_key *ptr_dh_1 ;
t_zencod_dh_compute_key *ptr_dh_2 ;
t_zencod_rand_bytes *ptr_rand_1 ;
t_zencod_math_mod_exp *ptr_math_1 ;
t_zencod_md5_init *ptr_md5_1 ;
t_zencod_md5_update *ptr_md5_2 ;
t_zencod_md5_do_final *ptr_md5_3 ;
t_zencod_sha1_init *ptr_sha1_1 ;
t_zencod_sha1_update *ptr_sha1_2 ;
t_zencod_sha1_do_final *ptr_sha1_3 ;
t_zencod_xdes_cipher *ptr_xdes_1 ;
t_zencod_rc4_cipher *ptr_rc4_1 ;
CHEESE () ;
/*
* We Should add some tests for non NULL parameters or bad value !!
* Stuff to be done ...
*/
if ( zencod_dso != NULL ) {
ZENCODerr ( ZENCOD_F_ZENCOD_INIT, ZENCOD_R_ALREADY_LOADED ) ;
goto err ;
}
/* Trying to load the Library "cryptozen"
*/
zencod_dso = DSO_load ( NULL, ZENCOD_LIBNAME, NULL, 0 ) ;
if ( zencod_dso == NULL ) {
ZENCODerr ( ZENCOD_F_ZENCOD_INIT, ZENCOD_R_DSO_FAILURE ) ;
goto err ;
}
/* Trying to load Function from the Library
*/
if ( ! ( ptr_1 = (t_zencod_bytes2bits*) DSO_bind_func ( zencod_dso, ZENCOD_Fct_1 ) ) ||
! ( ptr_2 = (t_zencod_bits2bytes*) DSO_bind_func ( zencod_dso, ZENCOD_Fct_2 ) ) ||
! ( ptr_3 = (t_zencod_new_number*) DSO_bind_func ( zencod_dso, ZENCOD_Fct_3 ) ) ||
! ( ptr_4 = (t_zencod_init_number*) DSO_bind_func ( zencod_dso, ZENCOD_Fct_4 ) ) ||
! ( ptr_exp_1 = (t_zencod_rsa_mod_exp*) DSO_bind_func ( zencod_dso, ZENCOD_Fct_exp_1 ) ) ||
! ( ptr_exp_2 = (t_zencod_rsa_mod_exp_crt*) DSO_bind_func ( zencod_dso, ZENCOD_Fct_exp_2 ) ) ||
! ( ptr_dsa_1 = (t_zencod_dsa_do_sign*) DSO_bind_func ( zencod_dso, ZENCOD_Fct_dsa_1 ) ) ||
! ( ptr_dsa_2 = (t_zencod_dsa_do_verify*) DSO_bind_func ( zencod_dso, ZENCOD_Fct_dsa_2 ) ) ||
! ( ptr_dh_1 = (t_zencod_dh_generate_key*) DSO_bind_func ( zencod_dso, ZENCOD_Fct_dh_1 ) ) ||
! ( ptr_dh_2 = (t_zencod_dh_compute_key*) DSO_bind_func ( zencod_dso, ZENCOD_Fct_dh_2 ) ) ||
! ( ptr_rand_1 = (t_zencod_rand_bytes*) DSO_bind_func ( zencod_dso, ZENCOD_Fct_rand_1 ) ) ||
! ( ptr_math_1 = (t_zencod_math_mod_exp*) DSO_bind_func ( zencod_dso, ZENCOD_Fct_math_1 ) ) ||
! ( ptr_0 = (t_zencod_test *) DSO_bind_func ( zencod_dso, ZENCOD_Fct_0 ) ) ||
! ( ptr_md5_1 = (t_zencod_md5_init *) DSO_bind_func ( zencod_dso, ZENCOD_Fct_md5_1 ) ) ||
! ( ptr_md5_2 = (t_zencod_md5_update *) DSO_bind_func ( zencod_dso, ZENCOD_Fct_md5_2 ) ) ||
! ( ptr_md5_3 = (t_zencod_md5_do_final *) DSO_bind_func ( zencod_dso, ZENCOD_Fct_md5_3 ) ) ||
! ( ptr_sha1_1 = (t_zencod_sha1_init *) DSO_bind_func ( zencod_dso, ZENCOD_Fct_sha1_1 ) ) ||
! ( ptr_sha1_2 = (t_zencod_sha1_update *) DSO_bind_func ( zencod_dso, ZENCOD_Fct_sha1_2 ) ) ||
! ( ptr_sha1_3 = (t_zencod_sha1_do_final *) DSO_bind_func ( zencod_dso, ZENCOD_Fct_sha1_3 ) ) ||
! ( ptr_xdes_1 = (t_zencod_xdes_cipher *) DSO_bind_func ( zencod_dso, ZENCOD_Fct_xdes_1 ) ) ||
! ( ptr_rc4_1 = (t_zencod_rc4_cipher *) DSO_bind_func ( zencod_dso, ZENCOD_Fct_rc4_1 ) ) ) {
ZENCODerr ( ZENCOD_F_ZENCOD_INIT, ZENCOD_R_DSO_FAILURE ) ;
goto err ;
}
/* The function from "cryptozen" Library have been correctly loaded so copy them
*/
ptr_zencod_test = ptr_0 ;
ptr_zencod_bytes2bits = ptr_1 ;
ptr_zencod_bits2bytes = ptr_2 ;
ptr_zencod_new_number = ptr_3 ;
ptr_zencod_init_number = ptr_4 ;
ptr_zencod_rsa_mod_exp = ptr_exp_1 ;
ptr_zencod_rsa_mod_exp_crt = ptr_exp_2 ;
ptr_zencod_dsa_do_sign = ptr_dsa_1 ;
ptr_zencod_dsa_do_verify = ptr_dsa_2 ;
ptr_zencod_dh_generate_key = ptr_dh_1 ;
ptr_zencod_dh_compute_key = ptr_dh_2 ;
ptr_zencod_rand_bytes = ptr_rand_1 ;
ptr_zencod_math_mod_exp = ptr_math_1 ;
ptr_zencod_test = ptr_0 ;
ptr_zencod_md5_init = ptr_md5_1 ;
ptr_zencod_md5_update = ptr_md5_2 ;
ptr_zencod_md5_do_final = ptr_md5_3 ;
ptr_zencod_sha1_init = ptr_sha1_1 ;
ptr_zencod_sha1_update = ptr_sha1_2 ;
ptr_zencod_sha1_do_final = ptr_sha1_3 ;
ptr_zencod_xdes_cipher = ptr_xdes_1 ;
ptr_zencod_rc4_cipher = ptr_rc4_1 ;
/* We should peform a test to see if there is actually any unit runnig on the system ...
* Even if the cryptozen library is loaded the module coul not be loaded on the system ...
* For now we may just open and close the device !!
*/
if ( ptr_zencod_test () != 0 ) {
ZENCODerr ( ZENCOD_F_ZENCOD_INIT, ZENCOD_R_UNIT_FAILURE ) ;
goto err ;
}
return 1 ;
err :
if ( zencod_dso ) {
DSO_free ( zencod_dso ) ;
}
zencod_dso = NULL ;
ptr_zencod_bytes2bits = NULL ;
ptr_zencod_bits2bytes = NULL ;
ptr_zencod_new_number = NULL ;
ptr_zencod_init_number = NULL ;
ptr_zencod_rsa_mod_exp = NULL ;
ptr_zencod_rsa_mod_exp_crt = NULL ;
ptr_zencod_dsa_do_sign = NULL ;
ptr_zencod_dsa_do_verify = NULL ;
ptr_zencod_dh_generate_key = NULL ;
ptr_zencod_dh_compute_key = NULL ;
ptr_zencod_rand_bytes = NULL ;
ptr_zencod_math_mod_exp = NULL ;
ptr_zencod_test = NULL ;
ptr_zencod_md5_init = NULL ;
ptr_zencod_md5_update = NULL ;
ptr_zencod_md5_do_final = NULL ;
ptr_zencod_sha1_init = NULL ;
ptr_zencod_sha1_update = NULL ;
ptr_zencod_sha1_do_final = NULL ;
ptr_zencod_xdes_cipher = NULL ;
ptr_zencod_rc4_cipher = NULL ;
return 0 ;
}
static int zencod_finish ( ENGINE *e )
{
CHEESE () ;
/*
* We Should add some tests for non NULL parameters or bad value !!
* Stuff to be done ...
*/
if ( zencod_dso == NULL ) {
ZENCODerr ( ZENCOD_F_ZENCOD_FINISH, ZENCOD_R_NOT_LOADED ) ;
return 0 ;
}
if ( !DSO_free ( zencod_dso ) ) {
ZENCODerr ( ZENCOD_F_ZENCOD_FINISH, ZENCOD_R_DSO_FAILURE ) ;
return 0 ;
}
zencod_dso = NULL ;
ptr_zencod_bytes2bits = NULL ;
ptr_zencod_bits2bytes = NULL ;
ptr_zencod_new_number = NULL ;
ptr_zencod_init_number = NULL ;
ptr_zencod_rsa_mod_exp = NULL ;
ptr_zencod_rsa_mod_exp_crt = NULL ;
ptr_zencod_dsa_do_sign = NULL ;
ptr_zencod_dsa_do_verify = NULL ;
ptr_zencod_dh_generate_key = NULL ;
ptr_zencod_dh_compute_key = NULL ;
ptr_zencod_rand_bytes = NULL ;
ptr_zencod_math_mod_exp = NULL ;
ptr_zencod_test = NULL ;
ptr_zencod_md5_init = NULL ;
ptr_zencod_md5_update = NULL ;
ptr_zencod_md5_do_final = NULL ;
ptr_zencod_sha1_init = NULL ;
ptr_zencod_sha1_update = NULL ;
ptr_zencod_sha1_do_final = NULL ;
ptr_zencod_xdes_cipher = NULL ;
ptr_zencod_rc4_cipher = NULL ;
return 1 ;
}
static int zencod_ctrl ( ENGINE *e, int cmd, long i, void *p, void (*f) () )
{
int initialised = ( ( zencod_dso == NULL ) ? 0 : 1 ) ;
CHEESE () ;
/*
* We Should add some tests for non NULL parameters or bad value !!
* Stuff to be done ...
*/
switch ( cmd ) {
case ZENCOD_CMD_SO_PATH :
if ( p == NULL ) {
ZENCODerr ( ZENCOD_F_ZENCOD_CTRL, ERR_R_PASSED_NULL_PARAMETER ) ;
return 0 ;
}
if ( initialised ) {
ZENCODerr ( ZENCOD_F_ZENCOD_CTRL, ZENCOD_R_ALREADY_LOADED ) ;
return 0 ;
}
ZENCOD_LIBNAME = (const char *) p ;
return 1 ;
default :
break ;
}
ZENCODerr ( ZENCOD_F_ZENCOD_CTRL, ZENCOD_R_CTRL_COMMAND_NOT_IMPLEMENTED ) ;
return 0 ;
}
/* BIGNUM stuff Functions
*/
static int zencod_bn_mod_exp ( BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx )
{
zen_nb_t y, x, e, n;
int ret;
CHEESE () ;
if ( !zencod_dso ) {
ENGINEerr(ZENCOD_F_ZENCOD_BN_MOD_EXP, ZENCOD_R_NOT_LOADED);
return 0;
}
if ( !bn_wexpand(r, m->top + 1) ) {
ENGINEerr(ZENCOD_F_ZENCOD_BN_MOD_EXP, ZENCOD_R_BN_EXPAND_FAIL);
return 0;
}
memset(r->d, 0, BN_num_bytes(m));
ptr_zencod_init_number ( &y, (r->dmax - 1) * sizeof (BN_ULONG) * 8, (unsigned char *) r->d ) ;
BIGNUM2ZEN ( &x, a ) ;
BIGNUM2ZEN ( &e, p ) ;
BIGNUM2ZEN ( &n, m ) ;
/* Must invert x and e parameter due to BN mod exp prototype ... */
ret = ptr_zencod_math_mod_exp ( &y, &e, &x, &n ) ;
if ( ret ) {
PERROR("zenbridge_math_mod_exp");
ENGINEerr(ZENCOD_F_ZENCOD_BN_MOD_EXP, ZENCOD_R_REQUEST_FAILED);
return 0;
}
r->top = (BN_num_bits(m) + BN_BITS2 - 1) / BN_BITS2;
return 1;
}
/* RSA stuff Functions
*/
#ifndef OPENSSL_NO_RSA
static int RSA_zencod_rsa_mod_exp ( BIGNUM *r0, const BIGNUM *i, RSA *rsa )
{
CHEESE () ;
if ( !zencod_dso ) {
ENGINEerr(ZENCOD_F_ZENCOD_RSA_MOD_EXP_CRT, ZENCOD_R_NOT_LOADED);
return 0;
}
if ( !rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp ) {
ENGINEerr(ZENCOD_F_ZENCOD_RSA_MOD_EXP_CRT, ZENCOD_R_BAD_KEY_COMPONENTS);
return 0;
}
/* Do in software if argument is too large for hardware */
if ( RSA_size(rsa) * 8 > ZENBRIDGE_MAX_KEYSIZE_RSA_CRT ) {
const RSA_METHOD *meth;
meth = RSA_PKCS1_SSLeay();
return meth->rsa_mod_exp(r0, i, rsa);
} else {
zen_nb_t y, x, p, q, dmp1, dmq1, iqmp;
if ( !bn_expand(r0, RSA_size(rsa) * 8) ) {
ENGINEerr(ZENCOD_F_ZENCOD_RSA_MOD_EXP_CRT, ZENCOD_R_BN_EXPAND_FAIL);
return 0;
}
r0->top = (RSA_size(rsa) * 8 + BN_BITS2 - 1) / BN_BITS2;
BIGNUM2ZEN ( &x, i ) ;
BIGNUM2ZEN ( &y, r0 ) ;
BIGNUM2ZEN ( &p, rsa->p ) ;
BIGNUM2ZEN ( &q, rsa->q ) ;
BIGNUM2ZEN ( &dmp1, rsa->dmp1 ) ;
BIGNUM2ZEN ( &dmq1, rsa->dmq1 ) ;
BIGNUM2ZEN ( &iqmp, rsa->iqmp ) ;
if ( ptr_zencod_rsa_mod_exp_crt ( &y, &x, &p, &q, &dmp1, &dmq1, &iqmp ) < 0 ) {
PERROR("zenbridge_rsa_mod_exp_crt");
ENGINEerr(ZENCOD_F_ZENCOD_RSA_MOD_EXP_CRT, ZENCOD_R_REQUEST_FAILED);
return 0;
}
return 1;
}
}
/* This function is aliased to RSA_mod_exp (with the mont stuff dropped).
*/
static int RSA_zencod_bn_mod_exp ( BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx )
{
CHEESE () ;
if ( !zencod_dso ) {
ENGINEerr(ZENCOD_F_ZENCOD_RSA_MOD_EXP, ZENCOD_R_NOT_LOADED);
return 0;
}
/* Do in software if argument is too large for hardware */
if ( BN_num_bits(m) > ZENBRIDGE_MAX_KEYSIZE_RSA ) {
const RSA_METHOD *meth;
meth = RSA_PKCS1_SSLeay();
return meth->bn_mod_exp(r, a, p, m, ctx, m_ctx);
} else {
zen_nb_t y, x, e, n;
if ( !bn_expand(r, BN_num_bits(m)) ) {
ENGINEerr(ZENCOD_F_ZENCOD_RSA_MOD_EXP, ZENCOD_R_BN_EXPAND_FAIL);
return 0;
}
r->top = (BN_num_bits(m) + BN_BITS2 - 1) / BN_BITS2;
BIGNUM2ZEN ( &x, a ) ;
BIGNUM2ZEN ( &y, r ) ;
BIGNUM2ZEN ( &e, p ) ;
BIGNUM2ZEN ( &n, m ) ;
if ( ptr_zencod_rsa_mod_exp ( &y, &x, &n, &e ) < 0 ) {
PERROR("zenbridge_rsa_mod_exp");
ENGINEerr(ZENCOD_F_ZENCOD_RSA_MOD_EXP, ZENCOD_R_REQUEST_FAILED);
return 0;
}
return 1;
}
}
#endif /* !OPENSSL_NO_RSA */
#ifndef OPENSSL_NO_DSA
/* DSA stuff Functions
*/
static DSA_SIG *DSA_zencod_do_sign ( const unsigned char *dgst, int dlen, DSA *dsa )
{
zen_nb_t p, q, g, x, y, r, s, data;
DSA_SIG *sig;
BIGNUM *bn_r = NULL;
BIGNUM *bn_s = NULL;
char msg[20];
CHEESE();
if ( !zencod_dso ) {
ENGINEerr(ZENCOD_F_ZENCOD_DSA_DO_SIGN, ZENCOD_R_NOT_LOADED);
goto FAILED;
}
if ( dlen > 160 ) {
ENGINEerr(ZENCOD_F_ZENCOD_DSA_DO_SIGN, ZENCOD_R_REQUEST_FAILED);
goto FAILED;
}
/* Do in software if argument is too large for hardware */
if ( BN_num_bits(dsa->p) > ZENBRIDGE_MAX_KEYSIZE_DSA_SIGN ||
BN_num_bits(dsa->g) > ZENBRIDGE_MAX_KEYSIZE_DSA_SIGN ) {
const DSA_METHOD *meth;
ENGINEerr(ZENCOD_F_ZENCOD_DSA_DO_SIGN, ZENCOD_R_BAD_KEY_COMPONENTS);
meth = DSA_OpenSSL();
return meth->dsa_do_sign(dgst, dlen, dsa);
}
if ( !(bn_s = BN_new()) || !(bn_r = BN_new()) ) {
ENGINEerr(ZENCOD_F_ZENCOD_DSA_DO_SIGN, ZENCOD_R_BAD_KEY_COMPONENTS);
goto FAILED;
}
if ( !bn_expand(bn_r, 160) || !bn_expand(bn_s, 160) ) {
ENGINEerr(ZENCOD_F_ZENCOD_DSA_DO_SIGN, ZENCOD_R_BN_EXPAND_FAIL);
goto FAILED;
}
bn_r->top = bn_s->top = (160 + BN_BITS2 - 1) / BN_BITS2;
BIGNUM2ZEN ( &p, dsa->p ) ;
BIGNUM2ZEN ( &q, dsa->q ) ;
BIGNUM2ZEN ( &g, dsa->g ) ;
BIGNUM2ZEN ( &x, dsa->priv_key ) ;
BIGNUM2ZEN ( &y, dsa->pub_key ) ;
BIGNUM2ZEN ( &r, bn_r ) ;
BIGNUM2ZEN ( &s, bn_s ) ;
q.len = x.len = 160;
ypcmem(msg, dgst, 20);
ptr_zencod_init_number ( &data, 160, msg ) ;
if ( ptr_zencod_dsa_do_sign ( 0, &data, &y, &p, &q, &g, &x, &r, &s ) < 0 ) {
PERROR("zenbridge_dsa_do_sign");
ENGINEerr(ZENCOD_F_ZENCOD_DSA_DO_SIGN, ZENCOD_R_REQUEST_FAILED);
goto FAILED;
}
if ( !( sig = DSA_SIG_new () ) ) {
ENGINEerr(ZENCOD_F_ZENCOD_DSA_DO_SIGN, ZENCOD_R_REQUEST_FAILED);
goto FAILED;
}
sig->r = bn_r;
sig->s = bn_s;
return sig;
FAILED:
if (bn_r)
BN_free(bn_r);
if (bn_s)
BN_free(bn_s);
return NULL;
}
static int DSA_zencod_do_verify ( const unsigned char *dgst, int dlen, DSA_SIG *sig, DSA *dsa )
{
zen_nb_t data, p, q, g, y, r, s, v;
char msg[20];
char v_data[20];
int ret;
CHEESE();
if ( !zencod_dso ) {
ENGINEerr(ZENCOD_F_ZENCOD_DSA_DO_VERIFY, ZENCOD_R_NOT_LOADED);
return 0;
}
if ( dlen > 160 ) {
ENGINEerr(ZENCOD_F_ZENCOD_DSA_DO_SIGN, ZENCOD_R_REQUEST_FAILED);
return 0;
}
/* Do in software if argument is too large for hardware */
if ( BN_num_bits(dsa->p) > ZENBRIDGE_MAX_KEYSIZE_DSA_SIGN ||
BN_num_bits(dsa->g) > ZENBRIDGE_MAX_KEYSIZE_DSA_SIGN ) {
const DSA_METHOD *meth;
ENGINEerr(ZENCOD_F_ZENCOD_DSA_DO_SIGN, ZENCOD_R_BAD_KEY_COMPONENTS);
meth = DSA_OpenSSL();
return meth->dsa_do_verify(dgst, dlen, sig, dsa);
}
BIGNUM2ZEN ( &p, dsa->p ) ;
BIGNUM2ZEN ( &q, dsa->q ) ;
BIGNUM2ZEN ( &g, dsa->g ) ;
BIGNUM2ZEN ( &y, dsa->pub_key ) ;
BIGNUM2ZEN ( &r, sig->r ) ;
BIGNUM2ZEN ( &s, sig->s ) ;
ptr_zencod_init_number ( &v, 160, v_data ) ;
ypcmem(msg, dgst, 20);
ptr_zencod_init_number ( &data, 160, msg ) ;
if ( ( ret = ptr_zencod_dsa_do_verify ( 0, &data, &p, &q, &g, &y, &r, &s, &v ) ) < 0 ) {
PERROR("zenbridge_dsa_do_verify");
ENGINEerr(ZENCOD_F_ZENCOD_DSA_DO_VERIFY, ZENCOD_R_REQUEST_FAILED);
return 0;
}
return ( ( ret == 0 ) ? 1 : ret ) ;
}
static int DSA_zencod_bn_mod_exp ( DSA *dsa, BIGNUM *r, BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
BN_CTX *ctx, BN_MONT_CTX *m_ctx )
{
CHEESE () ;
return zencod_bn_mod_exp ( r, a, p, m, ctx ) ;
}
#endif /* !OPENSSL_NO_DSA */
#ifndef OPENSSl_NO_DH
/* DH stuff Functions
*/
static int DH_zencod_generate_key ( DH *dh )
{
BIGNUM *bn_prv = NULL;
BIGNUM *bn_pub = NULL;
zen_nb_t y, x, g, p;
int generate_x;
CHEESE();
if ( !zencod_dso ) {
ENGINEerr(ZENCOD_F_ZENCOD_DH_GENERATE, ZENCOD_R_NOT_LOADED);
return 0;
}
/* Private key */
if ( dh->priv_key ) {
bn_prv = dh->priv_key;
generate_x = 0;
} else {
if (!(bn_prv = BN_new())) {
ENGINEerr(ZENCOD_F_ZENCOD_DH_GENERATE, ZENCOD_R_BN_EXPAND_FAIL);
goto FAILED;
}
generate_x = 1;
}
/* Public key */
if ( dh->pub_key )
bn_pub = dh->pub_key;
else
if ( !( bn_pub = BN_new () ) ) {
ENGINEerr(ZENCOD_F_ZENCOD_DH_GENERATE, ZENCOD_R_BN_EXPAND_FAIL);
goto FAILED;
}
/* Expand */
if ( !bn_wexpand ( bn_prv, dh->p->dmax ) ||
!bn_wexpand ( bn_pub, dh->p->dmax ) ) {
ENGINEerr(ZENCOD_F_ZENCOD_DH_GENERATE, ZENCOD_R_BN_EXPAND_FAIL);
goto FAILED;
}
bn_prv->top = dh->p->top;
bn_pub->top = dh->p->top;
/* Convert all keys */
BIGNUM2ZEN ( &p, dh->p ) ;
BIGNUM2ZEN ( &g, dh->g ) ;
BIGNUM2ZEN ( &y, bn_pub ) ;
BIGNUM2ZEN ( &x, bn_prv ) ;
x.len = DH_size(dh) * 8;
/* Adjust the lengths of P and G */
p.len = ptr_zencod_bytes2bits ( p.data, ZEN_BYTES ( p.len ) ) ;
g.len = ptr_zencod_bytes2bits ( g.data, ZEN_BYTES ( g.len ) ) ;
/* Send the request to the driver */
if ( ptr_zencod_dh_generate_key ( &y, &x, &g, &p, generate_x ) < 0 ) {
perror("zenbridge_dh_generate_key");
ENGINEerr(ZENCOD_F_ZENCOD_DH_GENERATE, ZENCOD_R_REQUEST_FAILED);
goto FAILED;
}
dh->priv_key = bn_prv;
dh->pub_key = bn_pub;
return 1;
FAILED:
if (!dh->priv_key && bn_prv)
BN_free(bn_prv);
if (!dh->pub_key && bn_pub)
BN_free(bn_pub);
return 0;
}
static int DH_zencod_compute_key ( unsigned char *key, const BIGNUM *pub_key, DH *dh )
{
zen_nb_t y, x, p, k;
CHEESE();
if ( !zencod_dso ) {
ENGINEerr(ZENCOD_F_ZENCOD_DH_COMPUTE, ZENCOD_R_NOT_LOADED);
return 0;
}
if ( !dh->priv_key ) {
ENGINEerr(ZENCOD_F_ZENCOD_DH_COMPUTE, ZENCOD_R_BAD_KEY_COMPONENTS);
return 0;
}
/* Convert all keys */
BIGNUM2ZEN ( &y, pub_key ) ;
BIGNUM2ZEN ( &x, dh->priv_key ) ;
BIGNUM2ZEN ( &p, dh->p ) ;
ptr_zencod_init_number ( &k, p.len, key ) ;
/* Adjust the lengths */
p.len = ptr_zencod_bytes2bits ( p.data, ZEN_BYTES ( p.len ) ) ;
y.len = ptr_zencod_bytes2bits ( y.data, ZEN_BYTES ( y.len ) ) ;
x.len = ptr_zencod_bytes2bits ( x.data, ZEN_BYTES ( x.len ) ) ;
/* Call the hardware */
if ( ptr_zencod_dh_compute_key ( &k, &y, &x, &p ) < 0 ) {
ENGINEerr(ZENCOD_F_ZENCOD_DH_COMPUTE, ZENCOD_R_REQUEST_FAILED);
return 0;
}
/* The key must be written MSB -> LSB */
k.len = ptr_zencod_bytes2bits ( k.data, ZEN_BYTES ( k.len ) ) ;
esrever ( key, ZEN_BYTES ( k.len ) ) ;
return ZEN_BYTES ( k.len ) ;
}
static int DH_zencod_bn_mod_exp ( const DH *dh, BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
BN_MONT_CTX *m_ctx )
{
CHEESE () ;
return zencod_bn_mod_exp ( r, a, p, m, ctx ) ;
}
#endif /* !OPENSSL_NO_DH */
/* RAND stuff Functions
*/
static void RAND_zencod_seed ( const void *buf, int num )
{
/* Nothing to do cause our crypto accelerator provide a true random generator */
}
static int RAND_zencod_rand_bytes ( unsigned char *buf, int num )
{
zen_nb_t r;
CHEESE();
if ( !zencod_dso ) {
ENGINEerr(ZENCOD_F_ZENCOD_RAND, ZENCOD_R_NOT_LOADED);
return 0;
}
ptr_zencod_init_number ( &r, num * 8, buf ) ;
if ( ptr_zencod_rand_bytes ( &r, ZENBRIDGE_RNG_DIRECT ) < 0 ) {
PERROR("zenbridge_rand_bytes");
ENGINEerr(ZENCOD_F_ZENCOD_RAND, ZENCOD_R_REQUEST_FAILED);
return 0;
}
return 1;
}
static int RAND_zencod_rand_status ( void )
{
CHEESE () ;
return 1;
}
/* This stuff is needed if this ENGINE is being compiled into a self-contained
* shared-library.
*/
#ifdef ENGINE_DYNAMIC_SUPPORT
static int bind_fn ( ENGINE *e, const char *id )
{
if ( id && ( strcmp ( id, engine_zencod_id ) != 0 ) ) {
return 0 ;
}
if ( !bind_helper ( e ) ) {
return 0 ;
}
return 1 ;
}
IMPLEMENT_DYNAMIC_CHECK_FN ()
IMPLEMENT_DYNAMIC_BIND_FN ( bind_fn )
#endif /* ENGINE_DYNAMIC_SUPPORT */
/*
* Adding "Digest" and "Cipher" tools ...
* This is in development ... ;-)
* In orfer to code this, i refer to hw_openbsd_dev_crypto and openssl engine made by Geoff Thorpe (if i'm rigth),
* and evp, sha md5 definitions etc ...
*/
/* First add some include ... */
#include <openssl/evp.h>
#include <openssl/sha.h>
#include <openssl/md5.h>
#include <openssl/rc4.h>
#include <openssl/des.h>
/* Some variables declaration ... */
/* DONS:
* Disable symetric computation except DES and 3DES, but let part of the code
*/
/* static int engine_digest_nids [ ] = { NID_sha1, NID_md5 } ; */
static int engine_digest_nids [ ] = { } ;
static int engine_digest_nids_num = 0 ;
/* static int engine_cipher_nids [ ] = { NID_rc4, NID_rc4_40, NID_des_cbc, NID_des_ede3_cbc } ; */
static int engine_cipher_nids [ ] = { NID_des_cbc, NID_des_ede3_cbc } ;
static int engine_cipher_nids_num = 2 ;
/* Function prototype ... */
/* SHA stuff */
static int engine_sha1_init ( EVP_MD_CTX *ctx ) ;
static int engine_sha1_update ( EVP_MD_CTX *ctx, const void *data, unsigned long count ) ;
static int engine_sha1_final ( EVP_MD_CTX *ctx, unsigned char *md ) ;
/* MD5 stuff */
static int engine_md5_init ( EVP_MD_CTX *ctx ) ;
static int engine_md5_update ( EVP_MD_CTX *ctx, const void *data, unsigned long count ) ;
static int engine_md5_final ( EVP_MD_CTX *ctx, unsigned char *md ) ;
static int engine_md_cleanup ( EVP_MD_CTX *ctx ) ;
static int engine_md_copy ( EVP_MD_CTX *to, const EVP_MD_CTX *from ) ;
/* RC4 Stuff */
static int engine_rc4_init_key ( EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc ) ;
static int engine_rc4_cipher ( EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl ) ;
/* DES Stuff */
static int engine_des_init_key ( EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc ) ;
static int engine_des_cbc_cipher ( EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl ) ;
/* 3DES Stuff */
static int engine_des_ede3_init_key ( EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc ) ;
static int engine_des_ede3_cbc_cipher ( EVP_CIPHER_CTX *ctx, unsigned char *out,const unsigned char *in, unsigned int inl ) ;
static int engine_cipher_cleanup ( EVP_CIPHER_CTX *ctx ) ; /* cleanup ctx */
/* The one for SHA ... */
static const EVP_MD engine_sha1_md =
{
NID_sha1,
NID_sha1WithRSAEncryption,
SHA_DIGEST_LENGTH,
EVP_MD_FLAG_ONESHOT,
/* 0, */ /* EVP_MD_FLAG_ONESHOT = x0001 digest can only handle a single block
* XXX: set according to device info ... */
engine_sha1_init,
engine_sha1_update,
engine_sha1_final,
engine_md_copy, /* dev_crypto_sha_copy */
engine_md_cleanup, /* dev_crypto_sha_cleanup */
EVP_PKEY_RSA_method,
SHA_CBLOCK,
/* sizeof ( EVP_MD * ) + sizeof ( SHA_CTX ) */
sizeof ( ZEN_MD_DATA )
/* sizeof ( MD_CTX_DATA ) The message digest data stucture ... */
} ;
/* The one for MD5 ... */
static const EVP_MD engine_md5_md =
{
NID_md5,
NID_md5WithRSAEncryption,
MD5_DIGEST_LENGTH,
EVP_MD_FLAG_ONESHOT,
/* 0, */ /* EVP_MD_FLAG_ONESHOT = x0001 digest can only handle a single block
* XXX: set according to device info ... */
engine_md5_init,
engine_md5_update,
engine_md5_final,
engine_md_copy, /* dev_crypto_md5_copy */
engine_md_cleanup, /* dev_crypto_md5_cleanup */
EVP_PKEY_RSA_method,
MD5_CBLOCK,
/* sizeof ( EVP_MD * ) + sizeof ( MD5_CTX ) */
sizeof ( ZEN_MD_DATA )
/* sizeof ( MD_CTX_DATA ) The message digest data stucture ... */
} ;
/* The one for RC4 ... */
#define EVP_RC4_KEY_SIZE 16
/* Try something static ... */
typedef struct
{
unsigned int len ;
unsigned int first ;
unsigned char rc4_state [ 260 ] ;
} NEW_ZEN_RC4_KEY ;
#define rc4_data(ctx) ( (EVP_RC4_KEY *) ( ctx )->cipher_data )
static const EVP_CIPHER engine_rc4 =
{
NID_rc4,
1,
16, /* EVP_RC4_KEY_SIZE should be 128 bits */
0, /* FIXME: key should be up to 256 bytes */
EVP_CIPH_VARIABLE_LENGTH,
engine_rc4_init_key,
engine_rc4_cipher,
engine_cipher_cleanup,
sizeof ( NEW_ZEN_RC4_KEY ),
NULL,
NULL,
NULL
} ;
/* The one for RC4_40 ... */
static const EVP_CIPHER engine_rc4_40 =
{
NID_rc4_40,
1,
5, /* 40 bits */
0,
EVP_CIPH_VARIABLE_LENGTH,
engine_rc4_init_key,
engine_rc4_cipher,
engine_cipher_cleanup,
sizeof ( NEW_ZEN_RC4_KEY ),
NULL,
NULL,
NULL
} ;
/* The one for DES ... */
/* Try something static ... */
typedef struct
{
unsigned char des_key [ 24 ] ;
unsigned char des_iv [ 8 ] ;
} ZEN_DES_KEY ;
static const EVP_CIPHER engine_des_cbc =
{
NID_des_cbc,
8, 8, 8,
0 | EVP_CIPH_CBC_MODE,
engine_des_init_key,
engine_des_cbc_cipher,
engine_cipher_cleanup,
sizeof(ZEN_DES_KEY),
EVP_CIPHER_set_asn1_iv,
EVP_CIPHER_get_asn1_iv,
NULL,
NULL
};
/* The one for 3DES ... */
/* Try something static ... */
typedef struct
{
unsigned char des3_key [ 24 ] ;
unsigned char des3_iv [ 8 ] ;
} ZEN_3DES_KEY ;
#define des_data(ctx) ( (DES_EDE_KEY *) ( ctx )->cipher_data )
static const EVP_CIPHER engine_des_ede3_cbc =
{
NID_des_ede3_cbc,
8, 8, 8,
0 | EVP_CIPH_CBC_MODE,
engine_des_ede3_init_key,
engine_des_ede3_cbc_cipher,
engine_cipher_cleanup,
sizeof(ZEN_3DES_KEY),
EVP_CIPHER_set_asn1_iv,
EVP_CIPHER_get_asn1_iv,
NULL,
NULL
};
/* General function cloned on hw_openbsd_dev_crypto one ... */
static int engine_digests ( ENGINE *e, const EVP_MD **digest, const int **nids, int nid )
{
#ifdef DEBUG_ZENCOD_MD
fprintf ( stderr, "\t=>Function : static int engine_digests () called !\n" ) ;
#endif
if ( !digest ) {
/* We are returning a list of supported nids */
*nids = engine_digest_nids ;
return engine_digest_nids_num ;
}
/* We are being asked for a specific digest */
if ( nid == NID_md5 ) {
*digest = &engine_md5_md ;
}
else if ( nid == NID_sha1 ) {
*digest = &engine_sha1_md ;
}
else {
*digest = NULL ;
return 0 ;
}
return 1 ;
}
/* SHA stuff Functions
*/
static int engine_sha1_init ( EVP_MD_CTX *ctx )
{
int to_return = 0 ;
/* Test with zenbridge library ... */
to_return = ptr_zencod_sha1_init ( (ZEN_MD_DATA *) ctx->md_data ) ;
to_return = !to_return ;
return to_return ;
}
static int engine_sha1_update ( EVP_MD_CTX *ctx, const void *data, unsigned long count )
{
zen_nb_t input ;
int to_return = 0 ;
/* Convert parameters ... */
input.len = count ;
input.data = (unsigned char *) data ;
/* Test with zenbridge library ... */
to_return = ptr_zencod_sha1_update ( (ZEN_MD_DATA *) ctx->md_data, (const zen_nb_t *) &input ) ;
to_return = !to_return ;
return to_return ;
}
static int engine_sha1_final ( EVP_MD_CTX *ctx, unsigned char *md )
{
zen_nb_t output ;
int to_return = 0 ;
/* Convert parameters ... */
output.len = SHA_DIGEST_LENGTH ;
output.data = md ;
/* Test with zenbridge library ... */
to_return = ptr_zencod_sha1_do_final ( (ZEN_MD_DATA *) ctx->md_data, (zen_nb_t *) &output ) ;
to_return = !to_return ;
return to_return ;
}
/* MD5 stuff Functions
*/
static int engine_md5_init ( EVP_MD_CTX *ctx )
{
int to_return = 0 ;
/* Test with zenbridge library ... */
to_return = ptr_zencod_md5_init ( (ZEN_MD_DATA *) ctx->md_data ) ;
to_return = !to_return ;
return to_return ;
}
static int engine_md5_update ( EVP_MD_CTX *ctx, const void *data, unsigned long count )
{
zen_nb_t input ;
int to_return = 0 ;
/* Convert parameters ... */
input.len = count ;
input.data = (unsigned char *) data ;
/* Test with zenbridge library ... */
to_return = ptr_zencod_md5_update ( (ZEN_MD_DATA *) ctx->md_data, (const zen_nb_t *) &input ) ;
to_return = !to_return ;
return to_return ;
}
static int engine_md5_final ( EVP_MD_CTX *ctx, unsigned char *md )
{
zen_nb_t output ;
int to_return = 0 ;
/* Convert parameters ... */
output.len = MD5_DIGEST_LENGTH ;
output.data = md ;
/* Test with zenbridge library ... */
to_return = ptr_zencod_md5_do_final ( (ZEN_MD_DATA *) ctx->md_data, (zen_nb_t *) &output ) ;
to_return = !to_return ;
return to_return ;
}
static int engine_md_cleanup ( EVP_MD_CTX *ctx )
{
ZEN_MD_DATA *zen_md_data = (ZEN_MD_DATA *) ctx->md_data ;
if ( zen_md_data->HashBuffer != NULL ) {
OPENSSL_free ( zen_md_data->HashBuffer ) ;
zen_md_data->HashBufferSize = 0 ;
ctx->md_data = NULL ;
}
return 1 ;
}
static int engine_md_copy ( EVP_MD_CTX *to, const EVP_MD_CTX *from )
{
const ZEN_MD_DATA *from_md = (ZEN_MD_DATA *) from->md_data ;
ZEN_MD_DATA *to_md = (ZEN_MD_DATA *) to->md_data ;
to_md->HashBuffer = OPENSSL_malloc ( from_md->HashBufferSize ) ;
memcpy ( to_md->HashBuffer, from_md->HashBuffer, from_md->HashBufferSize ) ;
return 1;
}
/* General function cloned on hw_openbsd_dev_crypto one ... */
static int engine_ciphers ( ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid )
{
if ( !cipher ) {
/* We are returning a list of supported nids */
*nids = engine_cipher_nids ;
return engine_cipher_nids_num ;
}
/* We are being asked for a specific cipher */
if ( nid == NID_rc4 ) {
*cipher = &engine_rc4 ;
}
else if ( nid == NID_rc4_40 ) {
*cipher = &engine_rc4_40 ;
}
else if ( nid == NID_des_cbc ) {
*cipher = &engine_des_cbc ;
}
else if ( nid == NID_des_ede3_cbc ) {
*cipher = &engine_des_ede3_cbc ;
}
else {
*cipher = NULL ;
return 0 ;
}
return 1 ;
}
static int engine_rc4_init_key ( EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc )
{
int to_return = 0 ;
int i = 0 ;
int nb = 0 ;
NEW_ZEN_RC4_KEY *tmp_rc4_key = NULL ;
tmp_rc4_key = (NEW_ZEN_RC4_KEY *) ( ctx->cipher_data ) ;
tmp_rc4_key->first = 0 ;
tmp_rc4_key->len = ctx->key_len ;
tmp_rc4_key->rc4_state [ 0 ] = 0x00 ;
tmp_rc4_key->rc4_state [ 2 ] = 0x00 ;
nb = 256 / ctx->key_len ;
for ( i = 0; i < nb ; i++ ) {
memcpy ( &( tmp_rc4_key->rc4_state [ 4 + i*ctx->key_len ] ), key, ctx->key_len ) ;
}
to_return = 1 ;
return to_return ;
}
static int engine_rc4_cipher ( EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int in_len )
{
zen_nb_t output, input ;
zen_nb_t rc4key ;
int to_return = 0 ;
NEW_ZEN_RC4_KEY *tmp_rc4_key = NULL ;
/* Convert parameters ... */
input.len = in_len ;
input.data = (unsigned char *) in ;
output.len = in_len ;
output.data = (unsigned char *) out ;
tmp_rc4_key = ( (NEW_ZEN_RC4_KEY *) ( ctx->cipher_data ) ) ;
rc4key.len = 260 ;
rc4key.data = &( tmp_rc4_key->rc4_state [ 0 ] ) ;
/* Test with zenbridge library ... */
to_return = ptr_zencod_rc4_cipher ( &output, &input, (const zen_nb_t *) &rc4key, &( tmp_rc4_key->rc4_state [0] ), &( tmp_rc4_key->rc4_state [3] ), !tmp_rc4_key->first ) ;
to_return = !to_return ;
/* Update encryption state ... */
tmp_rc4_key->first = 1 ;
tmp_rc4_key = NULL ;
return to_return ;
}
static int engine_des_init_key ( EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc )
{
ZEN_DES_KEY *tmp_des_key = NULL ;
int to_return = 0 ;
tmp_des_key = (ZEN_DES_KEY *) ( ctx->cipher_data ) ;
memcpy ( &( tmp_des_key->des_key [ 0 ] ), key, 8 ) ;
memcpy ( &( tmp_des_key->des_key [ 8 ] ), key, 8 ) ;
memcpy ( &( tmp_des_key->des_key [ 16 ] ), key, 8 ) ;
memcpy ( &( tmp_des_key->des_iv [ 0 ] ), iv, 8 ) ;
to_return = 1 ;
return to_return ;
}
static int engine_des_cbc_cipher ( EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl )
{
zen_nb_t output, input ;
zen_nb_t deskey_1, deskey_2, deskey_3, iv ;
int to_return = 0 ;
/* Convert parameters ... */
input.len = inl ;
input.data = (unsigned char *) in ;
output.len = inl ;
output.data = out ;
/* Set key parameters ... */
deskey_1.len = 8 ;
deskey_2.len = 8 ;
deskey_3.len = 8 ;
deskey_1.data = (unsigned char *) ( (ZEN_DES_KEY *) ( ctx->cipher_data ) )->des_key ;
deskey_2.data = (unsigned char *) &( (ZEN_DES_KEY *) ( ctx->cipher_data ) )->des_key [ 8 ] ;
deskey_3.data = (unsigned char *) &( (ZEN_DES_KEY *) ( ctx->cipher_data ) )->des_key [ 16 ] ;
/* Key correct iv ... */
memcpy ( ( (ZEN_DES_KEY *) ( ctx->cipher_data ) )->des_iv, ctx->iv, 8 ) ;
iv.len = 8 ;
iv.data = (unsigned char *) ( (ZEN_DES_KEY *) ( ctx->cipher_data ) )->des_iv ;
if ( ctx->encrypt == 0 ) {
memcpy ( ctx->iv, &( input.data [ input.len - 8 ] ), 8 ) ;
}
/* Test with zenbridge library ... */
to_return = ptr_zencod_xdes_cipher ( &output, &input,
(zen_nb_t *) &deskey_1, (zen_nb_t *) &deskey_2, (zen_nb_t *) &deskey_3, &iv, ctx->encrypt ) ;
to_return = !to_return ;
/* But we need to set up the rigth iv ...
* Test ENCRYPT or DECRYPT mode to set iv ... */
if ( ctx->encrypt == 1 ) {
memcpy ( ctx->iv, &( output.data [ output.len - 8 ] ), 8 ) ;
}
return to_return ;
}
static int engine_des_ede3_init_key ( EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc )
{
ZEN_3DES_KEY *tmp_3des_key = NULL ;
int to_return = 0 ;
tmp_3des_key = (ZEN_3DES_KEY *) ( ctx->cipher_data ) ;
memcpy ( &( tmp_3des_key->des3_key [ 0 ] ), key, 24 ) ;
memcpy ( &( tmp_3des_key->des3_iv [ 0 ] ), iv, 8 ) ;
to_return = 1;
return to_return ;
}
static int engine_des_ede3_cbc_cipher ( EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in,
unsigned int in_len )
{
zen_nb_t output, input ;
zen_nb_t deskey_1, deskey_2, deskey_3, iv ;
int to_return = 0 ;
/* Convert parameters ... */
input.len = in_len ;
input.data = (unsigned char *) in ;
output.len = in_len ;
output.data = out ;
/* Set key ... */
deskey_1.len = 8 ;
deskey_2.len = 8 ;
deskey_3.len = 8 ;
deskey_1.data = (unsigned char *) ( (ZEN_3DES_KEY *) ( ctx->cipher_data ) )->des3_key ;
deskey_2.data = (unsigned char *) &( (ZEN_3DES_KEY *) ( ctx->cipher_data ) )->des3_key [ 8 ] ;
deskey_3.data = (unsigned char *) &( (ZEN_3DES_KEY *) ( ctx->cipher_data ) )->des3_key [ 16 ] ;
/* Key correct iv ... */
memcpy ( ( (ZEN_3DES_KEY *) ( ctx->cipher_data ) )->des3_iv, ctx->iv, 8 ) ;
iv.len = 8 ;
iv.data = (unsigned char *) ( (ZEN_3DES_KEY *) ( ctx->cipher_data ) )->des3_iv ;
if ( ctx->encrypt == 0 ) {
memcpy ( ctx->iv, &( input.data [ input.len - 8 ] ), 8 ) ;
}
/* Test with zenbridge library ... */
to_return = ptr_zencod_xdes_cipher ( &output, &input,
(zen_nb_t *) &deskey_1, (zen_nb_t *) &deskey_2, (zen_nb_t *) &deskey_3, &iv, ctx->encrypt ) ;
to_return = !to_return ;
if ( ctx->encrypt == 1 ) {
memcpy ( ctx->iv, &( output.data [ output.len - 8 ] ), 8 ) ;
}
return to_return ;
}
static int engine_cipher_cleanup ( EVP_CIPHER_CTX *ctx )
{
/* Set the key pointer ... */
if ( ctx->cipher->nid == NID_rc4 || ctx->cipher->nid == NID_rc4_40 ) {
}
else if ( ctx->cipher->nid == NID_des_cbc ) {
}
else if ( ctx->cipher->nid == NID_des_ede3_cbc ) {
}
return 1 ;
}
#endif /* !OPENSSL_NO_HW_ZENCOD */
#endif /* !OPENSSL_NO_HW */