e_nuron.c revision 160815
1/* crypto/engine/hw_nuron.c */ 2/* Written by Ben Laurie for the OpenSSL Project, leaning heavily on Geoff 3 * Thorpe's Atalla implementation. 4 */ 5/* ==================================================================== 6 * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * 20 * 3. All advertising materials mentioning features or use of this 21 * software must display the following acknowledgment: 22 * "This product includes software developed by the OpenSSL Project 23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24 * 25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26 * endorse or promote products derived from this software without 27 * prior written permission. For written permission, please contact 28 * licensing@OpenSSL.org. 29 * 30 * 5. Products derived from this software may not be called "OpenSSL" 31 * nor may "OpenSSL" appear in their names without prior written 32 * permission of the OpenSSL Project. 33 * 34 * 6. Redistributions of any form whatsoever must retain the following 35 * acknowledgment: 36 * "This product includes software developed by the OpenSSL Project 37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38 * 39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50 * OF THE POSSIBILITY OF SUCH DAMAGE. 51 * ==================================================================== 52 * 53 * This product includes cryptographic software written by Eric Young 54 * (eay@cryptsoft.com). This product includes software written by Tim 55 * Hudson (tjh@cryptsoft.com). 56 * 57 */ 58 59#include <stdio.h> 60#include <string.h> 61#include <openssl/crypto.h> 62#include <openssl/buffer.h> 63#include <openssl/dso.h> 64#include <openssl/engine.h> 65#ifndef OPENSSL_NO_RSA 66#include <openssl/rsa.h> 67#endif 68#ifndef OPENSSL_NO_DSA 69#include <openssl/dsa.h> 70#endif 71#ifndef OPENSSL_NO_DH 72#include <openssl/dh.h> 73#endif 74#include <openssl/bn.h> 75 76#ifndef OPENSSL_NO_HW 77#ifndef OPENSSL_NO_HW_NURON 78 79#define NURON_LIB_NAME "nuron engine" 80#include "e_nuron_err.c" 81 82static const char *NURON_LIBNAME = NULL; 83static const char *get_NURON_LIBNAME(void) 84 { 85 if(NURON_LIBNAME) 86 return NURON_LIBNAME; 87 return "nuronssl"; 88 } 89static void free_NURON_LIBNAME(void) 90 { 91 if(NURON_LIBNAME) 92 OPENSSL_free((void*)NURON_LIBNAME); 93 NURON_LIBNAME = NULL; 94 } 95static long set_NURON_LIBNAME(const char *name) 96 { 97 free_NURON_LIBNAME(); 98 return (((NURON_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0); 99 } 100static const char *NURON_F1 = "nuron_mod_exp"; 101 102/* The definitions for control commands specific to this engine */ 103#define NURON_CMD_SO_PATH ENGINE_CMD_BASE 104static const ENGINE_CMD_DEFN nuron_cmd_defns[] = { 105 {NURON_CMD_SO_PATH, 106 "SO_PATH", 107 "Specifies the path to the 'nuronssl' shared library", 108 ENGINE_CMD_FLAG_STRING}, 109 {0, NULL, NULL, 0} 110 }; 111 112typedef int tfnModExp(BIGNUM *r,const BIGNUM *a,const BIGNUM *p,const BIGNUM *m); 113static tfnModExp *pfnModExp = NULL; 114 115static DSO *pvDSOHandle = NULL; 116 117static int nuron_destroy(ENGINE *e) 118 { 119 free_NURON_LIBNAME(); 120 ERR_unload_NURON_strings(); 121 return 1; 122 } 123 124static int nuron_init(ENGINE *e) 125 { 126 if(pvDSOHandle != NULL) 127 { 128 NURONerr(NURON_F_NURON_INIT,NURON_R_ALREADY_LOADED); 129 return 0; 130 } 131 132 pvDSOHandle = DSO_load(NULL, get_NURON_LIBNAME(), NULL, 133 DSO_FLAG_NAME_TRANSLATION_EXT_ONLY); 134 if(!pvDSOHandle) 135 { 136 NURONerr(NURON_F_NURON_INIT,NURON_R_DSO_NOT_FOUND); 137 return 0; 138 } 139 140 pfnModExp = (tfnModExp *)DSO_bind_func(pvDSOHandle, NURON_F1); 141 if(!pfnModExp) 142 { 143 NURONerr(NURON_F_NURON_INIT,NURON_R_DSO_FUNCTION_NOT_FOUND); 144 return 0; 145 } 146 147 return 1; 148 } 149 150static int nuron_finish(ENGINE *e) 151 { 152 free_NURON_LIBNAME(); 153 if(pvDSOHandle == NULL) 154 { 155 NURONerr(NURON_F_NURON_FINISH,NURON_R_NOT_LOADED); 156 return 0; 157 } 158 if(!DSO_free(pvDSOHandle)) 159 { 160 NURONerr(NURON_F_NURON_FINISH,NURON_R_DSO_FAILURE); 161 return 0; 162 } 163 pvDSOHandle=NULL; 164 pfnModExp=NULL; 165 return 1; 166 } 167 168static int nuron_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)) 169 { 170 int initialised = ((pvDSOHandle == NULL) ? 0 : 1); 171 switch(cmd) 172 { 173 case NURON_CMD_SO_PATH: 174 if(p == NULL) 175 { 176 NURONerr(NURON_F_NURON_CTRL,ERR_R_PASSED_NULL_PARAMETER); 177 return 0; 178 } 179 if(initialised) 180 { 181 NURONerr(NURON_F_NURON_CTRL,NURON_R_ALREADY_LOADED); 182 return 0; 183 } 184 return set_NURON_LIBNAME((const char *)p); 185 default: 186 break; 187 } 188 NURONerr(NURON_F_NURON_CTRL,NURON_R_CTRL_COMMAND_NOT_IMPLEMENTED); 189 return 0; 190} 191 192static int nuron_mod_exp(BIGNUM *r,const BIGNUM *a,const BIGNUM *p, 193 const BIGNUM *m,BN_CTX *ctx) 194 { 195 if(!pvDSOHandle) 196 { 197 NURONerr(NURON_F_NURON_MOD_EXP,NURON_R_NOT_LOADED); 198 return 0; 199 } 200 return pfnModExp(r,a,p,m); 201 } 202 203#ifndef OPENSSL_NO_RSA 204static int nuron_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) 205 { 206 return nuron_mod_exp(r0,I,rsa->d,rsa->n,ctx); 207 } 208#endif 209 210#ifndef OPENSSL_NO_DSA 211/* This code was liberated and adapted from the commented-out code in 212 * dsa_ossl.c. Because of the unoptimised form of the Atalla acceleration 213 * (it doesn't have a CRT form for RSA), this function means that an 214 * Atalla system running with a DSA server certificate can handshake 215 * around 5 or 6 times faster/more than an equivalent system running with 216 * RSA. Just check out the "signs" statistics from the RSA and DSA parts 217 * of "openssl speed -engine atalla dsa1024 rsa1024". */ 218static int nuron_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1, 219 BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m, 220 BN_CTX *ctx, BN_MONT_CTX *in_mont) 221 { 222 BIGNUM t; 223 int to_return = 0; 224 225 BN_init(&t); 226 /* let rr = a1 ^ p1 mod m */ 227 if (!nuron_mod_exp(rr,a1,p1,m,ctx)) 228 goto end; 229 /* let t = a2 ^ p2 mod m */ 230 if (!nuron_mod_exp(&t,a2,p2,m,ctx)) 231 goto end; 232 /* let rr = rr * t mod m */ 233 if (!BN_mod_mul(rr,rr,&t,m,ctx)) 234 goto end; 235 to_return = 1; 236end: 237 BN_free(&t); 238 return to_return; 239 } 240 241 242static int nuron_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a, 243 const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, 244 BN_MONT_CTX *m_ctx) 245 { 246 return nuron_mod_exp(r, a, p, m, ctx); 247 } 248#endif 249 250/* This function is aliased to mod_exp (with the mont stuff dropped). */ 251#ifndef OPENSSL_NO_RSA 252static int nuron_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, 253 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) 254 { 255 return nuron_mod_exp(r, a, p, m, ctx); 256 } 257#endif 258 259#ifndef OPENSSL_NO_DH 260/* This function is aliased to mod_exp (with the dh and mont dropped). */ 261static int nuron_mod_exp_dh(const DH *dh, BIGNUM *r, 262 const BIGNUM *a, const BIGNUM *p, 263 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) 264 { 265 return nuron_mod_exp(r, a, p, m, ctx); 266 } 267#endif 268 269#ifndef OPENSSL_NO_RSA 270static RSA_METHOD nuron_rsa = 271 { 272 "Nuron RSA method", 273 NULL, 274 NULL, 275 NULL, 276 NULL, 277 nuron_rsa_mod_exp, 278 nuron_mod_exp_mont, 279 NULL, 280 NULL, 281 0, 282 NULL, 283 NULL, 284 NULL, 285 NULL 286 }; 287#endif 288 289#ifndef OPENSSL_NO_DSA 290static DSA_METHOD nuron_dsa = 291 { 292 "Nuron DSA method", 293 NULL, /* dsa_do_sign */ 294 NULL, /* dsa_sign_setup */ 295 NULL, /* dsa_do_verify */ 296 nuron_dsa_mod_exp, /* dsa_mod_exp */ 297 nuron_mod_exp_dsa, /* bn_mod_exp */ 298 NULL, /* init */ 299 NULL, /* finish */ 300 0, /* flags */ 301 NULL, /* app_data */ 302 NULL, /* dsa_paramgen */ 303 NULL /* dsa_keygen */ 304 }; 305#endif 306 307#ifndef OPENSSL_NO_DH 308static DH_METHOD nuron_dh = 309 { 310 "Nuron DH method", 311 NULL, 312 NULL, 313 nuron_mod_exp_dh, 314 NULL, 315 NULL, 316 0, 317 NULL, 318 NULL 319 }; 320#endif 321 322/* Constants used when creating the ENGINE */ 323static const char *engine_nuron_id = "nuron"; 324static const char *engine_nuron_name = "Nuron hardware engine support"; 325 326/* This internal function is used by ENGINE_nuron() and possibly by the 327 * "dynamic" ENGINE support too */ 328static int bind_helper(ENGINE *e) 329 { 330#ifndef OPENSSL_NO_RSA 331 const RSA_METHOD *meth1; 332#endif 333#ifndef OPENSSL_NO_DSA 334 const DSA_METHOD *meth2; 335#endif 336#ifndef OPENSSL_NO_DH 337 const DH_METHOD *meth3; 338#endif 339 if(!ENGINE_set_id(e, engine_nuron_id) || 340 !ENGINE_set_name(e, engine_nuron_name) || 341#ifndef OPENSSL_NO_RSA 342 !ENGINE_set_RSA(e, &nuron_rsa) || 343#endif 344#ifndef OPENSSL_NO_DSA 345 !ENGINE_set_DSA(e, &nuron_dsa) || 346#endif 347#ifndef OPENSSL_NO_DH 348 !ENGINE_set_DH(e, &nuron_dh) || 349#endif 350 !ENGINE_set_destroy_function(e, nuron_destroy) || 351 !ENGINE_set_init_function(e, nuron_init) || 352 !ENGINE_set_finish_function(e, nuron_finish) || 353 !ENGINE_set_ctrl_function(e, nuron_ctrl) || 354 !ENGINE_set_cmd_defns(e, nuron_cmd_defns)) 355 return 0; 356 357#ifndef OPENSSL_NO_RSA 358 /* We know that the "PKCS1_SSLeay()" functions hook properly 359 * to the nuron-specific mod_exp and mod_exp_crt so we use 360 * those functions. NB: We don't use ENGINE_openssl() or 361 * anything "more generic" because something like the RSAref 362 * code may not hook properly, and if you own one of these 363 * cards then you have the right to do RSA operations on it 364 * anyway! */ 365 meth1=RSA_PKCS1_SSLeay(); 366 nuron_rsa.rsa_pub_enc=meth1->rsa_pub_enc; 367 nuron_rsa.rsa_pub_dec=meth1->rsa_pub_dec; 368 nuron_rsa.rsa_priv_enc=meth1->rsa_priv_enc; 369 nuron_rsa.rsa_priv_dec=meth1->rsa_priv_dec; 370#endif 371 372#ifndef OPENSSL_NO_DSA 373 /* Use the DSA_OpenSSL() method and just hook the mod_exp-ish 374 * bits. */ 375 meth2=DSA_OpenSSL(); 376 nuron_dsa.dsa_do_sign=meth2->dsa_do_sign; 377 nuron_dsa.dsa_sign_setup=meth2->dsa_sign_setup; 378 nuron_dsa.dsa_do_verify=meth2->dsa_do_verify; 379#endif 380 381#ifndef OPENSSL_NO_DH 382 /* Much the same for Diffie-Hellman */ 383 meth3=DH_OpenSSL(); 384 nuron_dh.generate_key=meth3->generate_key; 385 nuron_dh.compute_key=meth3->compute_key; 386#endif 387 388 /* Ensure the nuron error handling is set up */ 389 ERR_load_NURON_strings(); 390 return 1; 391 } 392 393#ifdef OPENSSL_NO_DYNAMIC_ENGINE 394static ENGINE *engine_nuron(void) 395 { 396 ENGINE *ret = ENGINE_new(); 397 if(!ret) 398 return NULL; 399 if(!bind_helper(ret)) 400 { 401 ENGINE_free(ret); 402 return NULL; 403 } 404 return ret; 405 } 406 407void ENGINE_load_nuron(void) 408 { 409 /* Copied from eng_[openssl|dyn].c */ 410 ENGINE *toadd = engine_nuron(); 411 if(!toadd) return; 412 ENGINE_add(toadd); 413 ENGINE_free(toadd); 414 ERR_clear_error(); 415 } 416#endif 417 418/* This stuff is needed if this ENGINE is being compiled into a self-contained 419 * shared-library. */ 420#ifndef OPENSSL_NO_DYNAMIC_ENGINE 421static int bind_fn(ENGINE *e, const char *id) 422 { 423 if(id && (strcmp(id, engine_nuron_id) != 0)) 424 return 0; 425 if(!bind_helper(e)) 426 return 0; 427 return 1; 428 } 429IMPLEMENT_DYNAMIC_CHECK_FN() 430IMPLEMENT_DYNAMIC_BIND_FN(bind_fn) 431#endif /* OPENSSL_NO_DYNAMIC_ENGINE */ 432 433#endif /* !OPENSSL_NO_HW_NURON */ 434#endif /* !OPENSSL_NO_HW */ 435