e_nuron.c revision 280304
1292068Ssjg/* crypto/engine/hw_nuron.c */ 2236769Sobrien/* 3236769Sobrien * Written by Ben Laurie for the OpenSSL Project, leaning heavily on Geoff 4236769Sobrien * Thorpe's Atalla implementation. 5236769Sobrien */ 6236769Sobrien/* ==================================================================== 7236769Sobrien * Copyright (c) 2000-2001 The OpenSSL Project. All rights reserved. 8236769Sobrien * 9236769Sobrien * Redistribution and use in source and binary forms, with or without 10236769Sobrien * modification, are permitted provided that the following conditions 11236769Sobrien * are met: 12236769Sobrien * 13236769Sobrien * 1. Redistributions of source code must retain the above copyright 14236769Sobrien * notice, this list of conditions and the following disclaimer. 15236769Sobrien * 16236769Sobrien * 2. Redistributions in binary form must reproduce the above copyright 17236769Sobrien * notice, this list of conditions and the following disclaimer in 18236769Sobrien * the documentation and/or other materials provided with the 19236769Sobrien * distribution. 20236769Sobrien * 21236769Sobrien * 3. All advertising materials mentioning features or use of this 22236769Sobrien * software must display the following acknowledgment: 23236769Sobrien * "This product includes software developed by the OpenSSL Project 24236769Sobrien * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 25236769Sobrien * 26236769Sobrien * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27236769Sobrien * endorse or promote products derived from this software without 28236769Sobrien * prior written permission. For written permission, please contact 29236769Sobrien * licensing@OpenSSL.org. 30236769Sobrien * 31236769Sobrien * 5. Products derived from this software may not be called "OpenSSL" 32236769Sobrien * nor may "OpenSSL" appear in their names without prior written 33236769Sobrien * permission of the OpenSSL Project. 34236769Sobrien * 35236769Sobrien * 6. Redistributions of any form whatsoever must retain the following 36292068Ssjg * acknowledgment: 37236769Sobrien * "This product includes software developed by the OpenSSL Project 38236769Sobrien * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 39236769Sobrien * 40236769Sobrien * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41236769Sobrien * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42236769Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43292068Ssjg * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44236769Sobrien * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45236769Sobrien * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46236769Sobrien * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47236769Sobrien * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48236769Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49236769Sobrien * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50236769Sobrien * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51236769Sobrien * OF THE POSSIBILITY OF SUCH DAMAGE. 52236769Sobrien * ==================================================================== 53236769Sobrien * 54236769Sobrien * This product includes cryptographic software written by Eric Young 55236769Sobrien * (eay@cryptsoft.com). This product includes software written by Tim 56236769Sobrien * Hudson (tjh@cryptsoft.com). 57236769Sobrien * 58236769Sobrien */ 59236769Sobrien 60236769Sobrien#include <stdio.h> 61236769Sobrien#include <string.h> 62236769Sobrien#include <openssl/crypto.h> 63236769Sobrien#include <openssl/buffer.h> 64236769Sobrien#include <openssl/dso.h> 65236769Sobrien#include <openssl/engine.h> 66236769Sobrien#ifndef OPENSSL_NO_RSA 67236769Sobrien# include <openssl/rsa.h> 68236769Sobrien#endif 69236769Sobrien#ifndef OPENSSL_NO_DSA 70236769Sobrien# include <openssl/dsa.h> 71236769Sobrien#endif 72236769Sobrien#ifndef OPENSSL_NO_DH 73236769Sobrien# include <openssl/dh.h> 74236769Sobrien#endif 75236769Sobrien#include <openssl/bn.h> 76236769Sobrien 77236769Sobrien#ifndef OPENSSL_NO_HW 78236769Sobrien# ifndef OPENSSL_NO_HW_NURON 79236769Sobrien 80236769Sobrien# define NURON_LIB_NAME "nuron engine" 81236769Sobrien# include "e_nuron_err.c" 82236769Sobrien 83236769Sobrienstatic const char *NURON_LIBNAME = NULL; 84236769Sobrienstatic const char *get_NURON_LIBNAME(void) 85236769Sobrien{ 86236769Sobrien if (NURON_LIBNAME) 87236769Sobrien return NURON_LIBNAME; 88236769Sobrien return "nuronssl"; 89236769Sobrien} 90236769Sobrien 91236769Sobrienstatic void free_NURON_LIBNAME(void) 92236769Sobrien{ 93236769Sobrien if (NURON_LIBNAME) 94236769Sobrien OPENSSL_free((void *)NURON_LIBNAME); 95236769Sobrien NURON_LIBNAME = NULL; 96236769Sobrien} 97236769Sobrien 98236769Sobrienstatic long set_NURON_LIBNAME(const char *name) 99236769Sobrien{ 100236769Sobrien free_NURON_LIBNAME(); 101236769Sobrien return (((NURON_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0); 102236769Sobrien} 103236769Sobrien 104236769Sobrienstatic const char *NURON_F1 = "nuron_mod_exp"; 105236769Sobrien 106236769Sobrien/* The definitions for control commands specific to this engine */ 107236769Sobrien# define NURON_CMD_SO_PATH ENGINE_CMD_BASE 108236769Sobrienstatic const ENGINE_CMD_DEFN nuron_cmd_defns[] = { 109236769Sobrien {NURON_CMD_SO_PATH, 110236769Sobrien "SO_PATH", 111236769Sobrien "Specifies the path to the 'nuronssl' shared library", 112236769Sobrien ENGINE_CMD_FLAG_STRING}, 113236769Sobrien {0, NULL, NULL, 0} 114236769Sobrien}; 115236769Sobrien 116236769Sobrientypedef int tfnModExp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, 117236769Sobrien const BIGNUM *m); 118236769Sobrienstatic tfnModExp *pfnModExp = NULL; 119236769Sobrien 120236769Sobrienstatic DSO *pvDSOHandle = NULL; 121236769Sobrien 122236769Sobrienstatic int nuron_destroy(ENGINE *e) 123236769Sobrien{ 124236769Sobrien free_NURON_LIBNAME(); 125236769Sobrien ERR_unload_NURON_strings(); 126236769Sobrien return 1; 127236769Sobrien} 128236769Sobrien 129236769Sobrienstatic int nuron_init(ENGINE *e) 130236769Sobrien{ 131236769Sobrien if (pvDSOHandle != NULL) { 132236769Sobrien NURONerr(NURON_F_NURON_INIT, NURON_R_ALREADY_LOADED); 133236769Sobrien return 0; 134236769Sobrien } 135236769Sobrien 136236769Sobrien pvDSOHandle = DSO_load(NULL, get_NURON_LIBNAME(), NULL, 137 DSO_FLAG_NAME_TRANSLATION_EXT_ONLY); 138 if (!pvDSOHandle) { 139 NURONerr(NURON_F_NURON_INIT, NURON_R_DSO_NOT_FOUND); 140 return 0; 141 } 142 143 pfnModExp = (tfnModExp *) DSO_bind_func(pvDSOHandle, NURON_F1); 144 if (!pfnModExp) { 145 NURONerr(NURON_F_NURON_INIT, NURON_R_DSO_FUNCTION_NOT_FOUND); 146 return 0; 147 } 148 149 return 1; 150} 151 152static int nuron_finish(ENGINE *e) 153{ 154 free_NURON_LIBNAME(); 155 if (pvDSOHandle == NULL) { 156 NURONerr(NURON_F_NURON_FINISH, NURON_R_NOT_LOADED); 157 return 0; 158 } 159 if (!DSO_free(pvDSOHandle)) { 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 case NURON_CMD_SO_PATH: 173 if (p == NULL) { 174 NURONerr(NURON_F_NURON_CTRL, ERR_R_PASSED_NULL_PARAMETER); 175 return 0; 176 } 177 if (initialised) { 178 NURONerr(NURON_F_NURON_CTRL, NURON_R_ALREADY_LOADED); 179 return 0; 180 } 181 return set_NURON_LIBNAME((const char *)p); 182 default: 183 break; 184 } 185 NURONerr(NURON_F_NURON_CTRL, NURON_R_CTRL_COMMAND_NOT_IMPLEMENTED); 186 return 0; 187} 188 189static int nuron_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, 190 const BIGNUM *m, BN_CTX *ctx) 191{ 192 if (!pvDSOHandle) { 193 NURONerr(NURON_F_NURON_MOD_EXP, NURON_R_NOT_LOADED); 194 return 0; 195 } 196 return pfnModExp(r, a, p, m); 197} 198 199# ifndef OPENSSL_NO_RSA 200static int nuron_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, 201 BN_CTX *ctx) 202{ 203 return nuron_mod_exp(r0, I, rsa->d, rsa->n, ctx); 204} 205# endif 206 207# ifndef OPENSSL_NO_DSA 208/* 209 * This code was liberated and adapted from the commented-out code in 210 * dsa_ossl.c. Because of the unoptimised form of the Atalla acceleration (it 211 * doesn't have a CRT form for RSA), this function means that an Atalla 212 * system running with a DSA server certificate can handshake around 5 or 6 213 * times faster/more than an equivalent system running with RSA. Just check 214 * out the "signs" statistics from the RSA and DSA parts of "openssl speed 215 * -engine atalla dsa1024 rsa1024". 216 */ 217static int nuron_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1, 218 BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m, 219 BN_CTX *ctx, BN_MONT_CTX *in_mont) 220{ 221 BIGNUM t; 222 int to_return = 0; 223 224 BN_init(&t); 225 /* let rr = a1 ^ p1 mod m */ 226 if (!nuron_mod_exp(rr, a1, p1, m, ctx)) 227 goto end; 228 /* let t = a2 ^ p2 mod m */ 229 if (!nuron_mod_exp(&t, a2, p2, m, ctx)) 230 goto end; 231 /* let rr = rr * t mod m */ 232 if (!BN_mod_mul(rr, rr, &t, m, ctx)) 233 goto end; 234 to_return = 1; 235 end: 236 BN_free(&t); 237 return to_return; 238} 239 240static int nuron_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a, 241 const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, 242 BN_MONT_CTX *m_ctx) 243{ 244 return nuron_mod_exp(r, a, p, m, ctx); 245} 246# endif 247 248/* This function is aliased to mod_exp (with the mont stuff dropped). */ 249# ifndef OPENSSL_NO_RSA 250static int nuron_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, 251 const BIGNUM *m, BN_CTX *ctx, 252 BN_MONT_CTX *m_ctx) 253{ 254 return nuron_mod_exp(r, a, p, m, ctx); 255} 256# endif 257 258# ifndef OPENSSL_NO_DH 259/* This function is aliased to mod_exp (with the dh and mont dropped). */ 260static int nuron_mod_exp_dh(const DH *dh, BIGNUM *r, 261 const BIGNUM *a, const BIGNUM *p, 262 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) 263{ 264 return nuron_mod_exp(r, a, p, m, ctx); 265} 266# endif 267 268# ifndef OPENSSL_NO_RSA 269static RSA_METHOD nuron_rsa = { 270 "Nuron RSA method", 271 NULL, 272 NULL, 273 NULL, 274 NULL, 275 nuron_rsa_mod_exp, 276 nuron_mod_exp_mont, 277 NULL, 278 NULL, 279 0, 280 NULL, 281 NULL, 282 NULL, 283 NULL 284}; 285# endif 286 287# ifndef OPENSSL_NO_DSA 288static DSA_METHOD nuron_dsa = { 289 "Nuron DSA method", 290 NULL, /* dsa_do_sign */ 291 NULL, /* dsa_sign_setup */ 292 NULL, /* dsa_do_verify */ 293 nuron_dsa_mod_exp, /* dsa_mod_exp */ 294 nuron_mod_exp_dsa, /* bn_mod_exp */ 295 NULL, /* init */ 296 NULL, /* finish */ 297 0, /* flags */ 298 NULL, /* app_data */ 299 NULL, /* dsa_paramgen */ 300 NULL /* dsa_keygen */ 301}; 302# endif 303 304# ifndef OPENSSL_NO_DH 305static DH_METHOD nuron_dh = { 306 "Nuron DH method", 307 NULL, 308 NULL, 309 nuron_mod_exp_dh, 310 NULL, 311 NULL, 312 0, 313 NULL, 314 NULL 315}; 316# endif 317 318/* Constants used when creating the ENGINE */ 319static const char *engine_nuron_id = "nuron"; 320static const char *engine_nuron_name = "Nuron hardware engine support"; 321 322/* 323 * This internal function is used by ENGINE_nuron() and possibly by the 324 * "dynamic" ENGINE support too 325 */ 326static int bind_helper(ENGINE *e) 327{ 328# ifndef OPENSSL_NO_RSA 329 const RSA_METHOD *meth1; 330# endif 331# ifndef OPENSSL_NO_DSA 332 const DSA_METHOD *meth2; 333# endif 334# ifndef OPENSSL_NO_DH 335 const DH_METHOD *meth3; 336# endif 337 if (!ENGINE_set_id(e, engine_nuron_id) || 338 !ENGINE_set_name(e, engine_nuron_name) || 339# ifndef OPENSSL_NO_RSA 340 !ENGINE_set_RSA(e, &nuron_rsa) || 341# endif 342# ifndef OPENSSL_NO_DSA 343 !ENGINE_set_DSA(e, &nuron_dsa) || 344# endif 345# ifndef OPENSSL_NO_DH 346 !ENGINE_set_DH(e, &nuron_dh) || 347# endif 348 !ENGINE_set_destroy_function(e, nuron_destroy) || 349 !ENGINE_set_init_function(e, nuron_init) || 350 !ENGINE_set_finish_function(e, nuron_finish) || 351 !ENGINE_set_ctrl_function(e, nuron_ctrl) || 352 !ENGINE_set_cmd_defns(e, nuron_cmd_defns)) 353 return 0; 354 355# ifndef OPENSSL_NO_RSA 356 /* 357 * We know that the "PKCS1_SSLeay()" functions hook properly to the 358 * nuron-specific mod_exp and mod_exp_crt so we use those functions. NB: 359 * We don't use ENGINE_openssl() or anything "more generic" because 360 * something like the RSAref code may not hook properly, and if you own 361 * one of these cards then you have the right to do RSA operations on it 362 * anyway! 363 */ 364 meth1 = RSA_PKCS1_SSLeay(); 365 nuron_rsa.rsa_pub_enc = meth1->rsa_pub_enc; 366 nuron_rsa.rsa_pub_dec = meth1->rsa_pub_dec; 367 nuron_rsa.rsa_priv_enc = meth1->rsa_priv_enc; 368 nuron_rsa.rsa_priv_dec = meth1->rsa_priv_dec; 369# endif 370 371# ifndef OPENSSL_NO_DSA 372 /* 373 * Use the DSA_OpenSSL() method and just hook the mod_exp-ish bits. 374 */ 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 ENGINE_free(ret); 401 return NULL; 402 } 403 return ret; 404} 405 406void ENGINE_load_nuron(void) 407{ 408 /* Copied from eng_[openssl|dyn].c */ 409 ENGINE *toadd = engine_nuron(); 410 if (!toadd) 411 return; 412 ENGINE_add(toadd); 413 ENGINE_free(toadd); 414 ERR_clear_error(); 415} 416# endif 417 418/* 419 * This stuff is needed if this ENGINE is being compiled into a 420 * self-contained shared-library. 421 */ 422# ifndef OPENSSL_NO_DYNAMIC_ENGINE 423static int bind_fn(ENGINE *e, const char *id) 424{ 425 if (id && (strcmp(id, engine_nuron_id) != 0)) 426 return 0; 427 if (!bind_helper(e)) 428 return 0; 429 return 1; 430} 431 432IMPLEMENT_DYNAMIC_CHECK_FN() 433 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn) 434# endif /* OPENSSL_NO_DYNAMIC_ENGINE */ 435# endif /* !OPENSSL_NO_HW_NURON */ 436#endif /* !OPENSSL_NO_HW */ 437