From 73701c27b3cb9aacead88c0a3f933a269e2c7113 Mon Sep 17 00:00:00 2001 From: Ben Laurie Date: Sat, 7 Oct 2000 11:04:05 +0000 Subject: [PATCH] First cut at Nuron mod-exp card support (untested, awaiting new libraries from Nuron). --- crypto/engine/Makefile.ssl | 4 +- crypto/engine/engine.h | 5 + crypto/engine/engine_err.c | 7 +- crypto/engine/engine_int.h | 4 + crypto/engine/engine_list.c | 4 + crypto/engine/hw_nuron.c | 284 ++++++++++++++++++++++++++++++++++++ 6 files changed, 305 insertions(+), 3 deletions(-) create mode 100644 crypto/engine/hw_nuron.c diff --git a/crypto/engine/Makefile.ssl b/crypto/engine/Makefile.ssl index 7a0ffe755d..e9933d122e 100644 --- a/crypto/engine/Makefile.ssl +++ b/crypto/engine/Makefile.ssl @@ -23,9 +23,9 @@ APPS= LIB=$(TOP)/libcrypto.a LIBSRC= engine_err.c engine_lib.c engine_list.c engine_openssl.c \ - hw_atalla.c hw_cswift.c hw_ncipher.c + hw_atalla.c hw_cswift.c hw_ncipher.c hw_nuron.c LIBOBJ= engine_err.o engine_lib.o engine_list.o engine_openssl.o \ - hw_atalla.o hw_cswift.o hw_ncipher.o + hw_atalla.o hw_cswift.o hw_ncipher.o hw_nuron.o SRC= $(LIBSRC) diff --git a/crypto/engine/engine.h b/crypto/engine/engine.h index 2983f47034..78cf41c378 100644 --- a/crypto/engine/engine.h +++ b/crypto/engine/engine.h @@ -357,6 +357,9 @@ void ERR_load_ENGINE_strings(void); #define ENGINE_F_HWCRHK_RAND_BYTES 139 #define ENGINE_F_HWCRHK_RSA_MOD_EXP 140 #define ENGINE_F_LOG_MESSAGE 141 +#define ENGINE_F_NURON_FINISH 157 +#define ENGINE_F_NURON_INIT 156 +#define ENGINE_F_NURON_MOD_EXP 158 /* Reason codes. */ #define ENGINE_R_ALREADY_LOADED 100 @@ -367,6 +370,8 @@ void ERR_load_ENGINE_strings(void); #define ENGINE_R_CONFLICTING_ENGINE_ID 103 #define ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED 119 #define ENGINE_R_DSO_FAILURE 104 +#define ENGINE_R_DSO_FUNCTION_NOT_FOUND 131 +#define ENGINE_R_DSO_NOT_FOUND 132 #define ENGINE_R_ENGINE_IS_NOT_IN_LIST 105 #define ENGINE_R_FAILED_LOADING_PRIVATE_KEY 128 #define ENGINE_R_FAILED_LOADING_PUBLIC_KEY 129 diff --git a/crypto/engine/engine_err.c b/crypto/engine/engine_err.c index 0d7a31f6d5..44c4fb9dde 100644 --- a/crypto/engine/engine_err.c +++ b/crypto/engine/engine_err.c @@ -126,6 +126,9 @@ static ERR_STRING_DATA ENGINE_str_functs[]= {ERR_PACK(0,ENGINE_F_HWCRHK_RAND_BYTES,0), "HWCRHK_RAND_BYTES"}, {ERR_PACK(0,ENGINE_F_HWCRHK_RSA_MOD_EXP,0), "HWCRHK_RSA_MOD_EXP"}, {ERR_PACK(0,ENGINE_F_LOG_MESSAGE,0), "LOG_MESSAGE"}, +{ERR_PACK(0,ENGINE_F_NURON_FINISH,0), "NURON_FINISH"}, +{ERR_PACK(0,ENGINE_F_NURON_INIT,0), "NURON_INIT"}, +{ERR_PACK(0,ENGINE_F_NURON_MOD_EXP,0), "NURON_MOD_EXP"}, {0,NULL} }; @@ -139,6 +142,8 @@ static ERR_STRING_DATA ENGINE_str_reasons[]= {ENGINE_R_CONFLICTING_ENGINE_ID ,"conflicting engine id"}, {ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED ,"ctrl command not implemented"}, {ENGINE_R_DSO_FAILURE ,"DSO failure"}, +{ENGINE_R_DSO_FUNCTION_NOT_FOUND ,"dso function not found"}, +{ENGINE_R_DSO_NOT_FOUND ,"dso not found"}, {ENGINE_R_ENGINE_IS_NOT_IN_LIST ,"engine is not in the list"}, {ENGINE_R_FAILED_LOADING_PRIVATE_KEY ,"failed loading private key"}, {ENGINE_R_FAILED_LOADING_PUBLIC_KEY ,"failed loading public key"}, @@ -154,7 +159,7 @@ static ERR_STRING_DATA ENGINE_str_reasons[]= {ENGINE_R_NO_CONTROL_FUNCTION ,"no control function"}, {ENGINE_R_NO_KEY ,"no key"}, {ENGINE_R_NO_LOAD_FUNCTION ,"no load function"}, -{ENGINE_R_NO_REFERENCE ,"no reference"}, +{ENGINE_R_NO_REFERENCE ,"no reference"}, {ENGINE_R_NO_SUCH_ENGINE ,"no such engine"}, {ENGINE_R_NO_UNLOAD_FUNCTION ,"no unload function"}, {ENGINE_R_PROVIDE_PARAMETERS ,"provide parameters"}, diff --git a/crypto/engine/engine_int.h b/crypto/engine/engine_int.h index 447fa2a320..d4aa8faca2 100644 --- a/crypto/engine/engine_int.h +++ b/crypto/engine/engine_int.h @@ -151,6 +151,10 @@ ENGINE *ENGINE_ncipher(); ENGINE *ENGINE_atalla(); #endif /* !NO_HW_ATALLA */ +#ifndef NO_HW_NURON +ENGINE *ENGINE_nuron(); +#endif /* !NO_HW_NURON */ + #endif /* !NO_HW */ #ifdef __cplusplus diff --git a/crypto/engine/engine_list.c b/crypto/engine/engine_list.c index d764c60661..8fe4f305b4 100644 --- a/crypto/engine/engine_list.c +++ b/crypto/engine/engine_list.c @@ -198,6 +198,10 @@ static int engine_internal_check(void) if(!engine_list_add(ENGINE_atalla())) return 0; #endif /* !NO_HW_ATALLA */ +#ifndef NO_HW_NURON + if(!engine_list_add(ENGINE_nuron())) + return 0; +#endif /* !NO_HW_NURON */ #endif /* !NO_HW */ engine_list_flag = 1; return 1; diff --git a/crypto/engine/hw_nuron.c b/crypto/engine/hw_nuron.c new file mode 100644 index 0000000000..8e7e3cf18c --- /dev/null +++ b/crypto/engine/hw_nuron.c @@ -0,0 +1,284 @@ +/* crypto/engine/hw_nuron.c */ +/* Written by Ben Laurie for the OpenSSL Project, leaning heavily on Geoff + * Thorpe's Atalla implementation. + */ +/* ==================================================================== + * Copyright (c) 2000 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). + * + */ + +#include +#include +#include "cryptlib.h" +#include +#include "engine_int.h" +#include +#include + + +#ifndef NO_HW +#ifndef NO_HW_NURON + +static int (*pfnModExp)(BIGNUM *r,BIGNUM *a,const BIGNUM *p,const BIGNUM *m); +void *pvDSOHandle; + +static int nuron_init() + { + if(pvDSOHandle != NULL) + { + ENGINEerr(ENGINE_F_NURON_INIT,ENGINE_R_ALREADY_LOADED); + return 0; + } + + pvDSOHandle=dlopen("nuronssl.so",RTLD_NOW); + if(!pvDSOHandle) + { + ENGINEerr(ENGINE_F_NURON_INIT,ENGINE_R_DSO_NOT_FOUND); + return 0; + } + + pfnModExp=(int (*)(BIGNUM *r,BIGNUM *a,const BIGNUM *p, + const BIGNUM *m))dlsym(pvDSOHandle,"nuron_mod_exp"); + if(!pfnModExp) + { + ENGINEerr(ENGINE_F_NURON_INIT,ENGINE_R_DSO_FUNCTION_NOT_FOUND); + return 0; + } + + return 1; + } + +static int nuron_finish() + { + if(pvDSOHandle == NULL) + { + ENGINEerr(ENGINE_F_NURON_FINISH,ENGINE_R_NOT_LOADED); + return 0; + } + if(!DSO_free(pvDSOHandle)) + { + ENGINEerr(ENGINE_F_NURON_FINISH,ENGINE_R_DSO_FAILURE); + return 0; + } + pvDSOHandle=NULL; + pfnModExp=NULL; + return 1; + } + +static int nuron_mod_exp(BIGNUM *r,BIGNUM *a,const BIGNUM *p, + const BIGNUM *m,BN_CTX *ctx) + { + if(!pvDSOHandle) + { + ENGINEerr(ENGINE_F_NURON_MOD_EXP,ENGINE_R_NOT_LOADED); + return 0; + } + return pfnModExp(r,a,p,m); + } + +static int nuron_rsa_mod_exp(BIGNUM *r0, BIGNUM *I, RSA *rsa) + { + return nuron_mod_exp(r0,I,rsa->d,rsa->n,NULL); + } + +/* This code was liberated and adapted from the commented-out code in + * dsa_ossl.c. Because of the unoptimised form of the Atalla acceleration + * (it doesn't have a CRT form for RSA), this function means that an + * Atalla system running with a DSA server certificate can handshake + * around 5 or 6 times faster/more than an equivalent system running with + * RSA. Just check out the "signs" statistics from the RSA and DSA parts + * of "openssl speed -engine atalla dsa1024 rsa1024". */ +static int nuron_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1, + BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m, + BN_CTX *ctx, BN_MONT_CTX *in_mont) + { + BIGNUM t; + int to_return = 0; + + BN_init(&t); + /* let rr = a1 ^ p1 mod m */ + if (!nuron_mod_exp(rr,a1,p1,m,ctx)) + goto end; + /* let t = a2 ^ p2 mod m */ + if (!nuron_mod_exp(&t,a2,p2,m,ctx)) + goto end; + /* let rr = rr * t mod m */ + if (!BN_mod_mul(rr,rr,&t,m,ctx)) + goto end; + to_return = 1; +end: + BN_free(&t); + return to_return; + } + + +static int nuron_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a, + const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *m_ctx) + { + return nuron_mod_exp(r, a, p, m, ctx); + } + +/* This function is aliased to mod_exp (with the mont stuff dropped). */ +static int nuron_mod_exp_mont(BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) + { + return nuron_mod_exp(r, a, p, m, ctx); + } + +/* This function is aliased to mod_exp (with the dh and mont dropped). */ +static int nuron_mod_exp_dh(DH *dh, BIGNUM *r, BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) + { + return nuron_mod_exp(r, a, p, m, ctx); + } + +static RSA_METHOD nuron_rsa = + { + "Nuron RSA method", + NULL, + NULL, + NULL, + NULL, + nuron_rsa_mod_exp, + nuron_mod_exp_mont, + NULL, + NULL, + 0, + NULL, + NULL, + NULL + }; + +static DSA_METHOD nuron_dsa = + { + "Nuron DSA method", + NULL, /* dsa_do_sign */ + NULL, /* dsa_sign_setup */ + NULL, /* dsa_do_verify */ + nuron_dsa_mod_exp, /* dsa_mod_exp */ + nuron_mod_exp_dsa, /* bn_mod_exp */ + NULL, /* init */ + NULL, /* finish */ + 0, /* flags */ + NULL /* app_data */ + }; + +static DH_METHOD nuron_dh = + { + "Nuron DH method", + NULL, + NULL, + nuron_mod_exp_dh, + NULL, + NULL, + 0, + NULL + }; + +static ENGINE engine_nuron = + { + "nuron", + "Nuron hardware engine support", + &nuron_rsa, + &nuron_dsa, + &nuron_dh, + NULL, + nuron_mod_exp, + NULL, + nuron_init, + nuron_finish, + NULL, /* no ctrl() */ + NULL, /* no load_privkey() */ + NULL, /* no load_pubkey() */ + 0, /* no flags */ + 0, 0, /* no references */ + NULL, NULL /* unlinked */ + }; + +/* 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_nuron() + { + RSA_METHOD *meth1; + DSA_METHOD *meth2; + DH_METHOD *meth3; + + /* We know that the "PKCS1_SSLeay()" functions hook properly + * to the nuron-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! */ + meth1=RSA_PKCS1_SSLeay(); + nuron_rsa.rsa_pub_enc=meth1->rsa_pub_enc; + nuron_rsa.rsa_pub_dec=meth1->rsa_pub_dec; + nuron_rsa.rsa_priv_enc=meth1->rsa_priv_enc; + nuron_rsa.rsa_priv_dec=meth1->rsa_priv_dec; + + /* Use the DSA_OpenSSL() method and just hook the mod_exp-ish + * bits. */ + meth2=DSA_OpenSSL(); + nuron_dsa.dsa_do_sign=meth2->dsa_do_sign; + nuron_dsa.dsa_sign_setup=meth2->dsa_sign_setup; + nuron_dsa.dsa_do_verify=meth2->dsa_do_verify; + + /* Much the same for Diffie-Hellman */ + meth3=DH_OpenSSL(); + nuron_dh.generate_key=meth3->generate_key; + nuron_dh.compute_key=meth3->compute_key; + return &engine_nuron; + } + +#endif /* !NO_HW_NURON */ +#endif /* !NO_HW */ -- 2.25.1