hw_ubsec.c 29.7 KB
Newer Older
1 2 3 4 5 6 7
/* crypto/engine/hw_ubsec.c */
/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL
 * project 2000.
 *
 * Cloned shamelessly by Joe Tardo. 
 */
/* ====================================================================
8
 * Copyright (c) 1999-2001 The OpenSSL Project.  All rights reserved.
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
 *
 * 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 <stdio.h>
#include <openssl/crypto.h>
#include "cryptlib.h"
#include <openssl/dso.h>
#include <openssl/engine.h>

67 68
#ifndef OPENSSL_NO_HW
#ifndef OPENSSL_NO_HW_UBSEC
69 70 71 72 73 74 75

#ifdef FLAT_INC
#include "hw_ubsec.h"
#else
#include "vendor_defns/hw_ubsec.h"
#endif

76 77 78
#define UBSEC_LIB_NAME "ubsec engine"
#include "hw_ubsec_err.c"

79 80
#define FAIL_TO_SOFTWARE -15

81
static int ubsec_destroy(ENGINE *e);
G
Geoff Thorpe 已提交
82 83
static int ubsec_init(ENGINE *e);
static int ubsec_finish(ENGINE *e);
G
Geoff Thorpe 已提交
84
static int ubsec_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)());
85 86 87 88 89
static int ubsec_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
		const BIGNUM *m, BN_CTX *ctx);
static int ubsec_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
			const BIGNUM *q, const BIGNUM *dp,
			const BIGNUM *dq, const BIGNUM *qinv, BN_CTX *ctx);
90
#ifndef OPENSSL_NO_RSA
91
static int ubsec_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa);
92
#endif
93 94
static int ubsec_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
		const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
95
#ifndef OPENSSL_NO_DSA
96
#if NOT_USED
97 98 99 100 101 102
static int ubsec_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);
static int ubsec_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a,
		const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
		BN_MONT_CTX *m_ctx);
103
#endif
104 105 106
static DSA_SIG *ubsec_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa);
static int ubsec_dsa_verify(const unsigned char *dgst, int dgst_len,
                                DSA_SIG *sig, DSA *dsa);
107 108
#endif
#ifndef OPENSSL_NO_DH
109 110 111 112 113
static int ubsec_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a,
		const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
		BN_MONT_CTX *m_ctx);
static int ubsec_dh_compute_key(unsigned char *key,const BIGNUM *pub_key,DH *dh);
static int ubsec_dh_generate_key(DH *dh);
114
#endif
115 116

#if NOT_USED
117 118
static int ubsec_rand_bytes(unsigned char *buf, int num);
static int ubsec_rand_status(void);
119
#endif
G
Geoff Thorpe 已提交
120 121 122 123 124 125 126 127 128 129

#define UBSEC_CMD_SO_PATH		ENGINE_CMD_BASE
static const ENGINE_CMD_DEFN ubsec_cmd_defns[] = {
	{UBSEC_CMD_SO_PATH,
		"SO_PATH",
		"Specifies the path to the 'ubsec' shared library",
		ENGINE_CMD_FLAG_STRING},
	{0, NULL, NULL, 0}
	};

130
#ifndef OPENSSL_NO_RSA
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
/* Our internal RSA_METHOD that we provide pointers to */
static RSA_METHOD ubsec_rsa =
	{
	"UBSEC RSA method",
	NULL,
	NULL,
	NULL,
	NULL,
	ubsec_rsa_mod_exp,
	ubsec_mod_exp_mont,
	NULL,
	NULL,
	0,
	NULL,
	NULL,
	NULL
	};
148
#endif
149

150
#ifndef OPENSSL_NO_DSA
151 152 153 154 155 156 157 158 159 160 161 162 163 164
/* Our internal DSA_METHOD that we provide pointers to */
static DSA_METHOD ubsec_dsa =
	{
	"UBSEC DSA method",
	ubsec_dsa_do_sign, /* dsa_do_sign */
	NULL, /* dsa_sign_setup */
	ubsec_dsa_verify, /* dsa_do_verify */
	NULL, /* ubsec_dsa_mod_exp */ /* dsa_mod_exp */
	NULL, /* ubsec_mod_exp_dsa */ /* bn_mod_exp */
	NULL, /* init */
	NULL, /* finish */
	0, /* flags */
	NULL /* app_data */
	};
165
#endif
166

167
#ifndef OPENSSL_NO_DH
168 169 170 171 172 173 174 175 176 177 178 179
/* Our internal DH_METHOD that we provide pointers to */
static DH_METHOD ubsec_dh =
	{
	"UBSEC DH method",
	ubsec_dh_generate_key,
	ubsec_dh_compute_key,
	ubsec_mod_exp_dh,
	NULL,
	NULL,
	0,
	NULL
	};
180
#endif
181

G
Geoff Thorpe 已提交
182 183 184
/* Constants used when creating the ENGINE */
static const char *engine_ubsec_id = "ubsec";
static const char *engine_ubsec_name = "UBSEC hardware engine support";
185

186 187 188
/* This internal function is used by ENGINE_ubsec() and possibly by the
 * "dynamic" ENGINE support too */
static int bind_helper(ENGINE *e)
189
	{
190
#ifndef OPENSSL_NO_RSA
191
	const RSA_METHOD *meth1;
192 193
#endif
#ifndef OPENSSL_NO_DH
194 195 196
#ifndef HAVE_UBSEC_DH
	const DH_METHOD *meth3;
#endif /* HAVE_UBSEC_DH */
197
#endif
198 199
	if(!ENGINE_set_id(e, engine_ubsec_id) ||
			!ENGINE_set_name(e, engine_ubsec_name) ||
200
#ifndef OPENSSL_NO_RSA
201
			!ENGINE_set_RSA(e, &ubsec_rsa) ||
202 203
#endif
#ifndef OPENSSL_NO_DSA
204
			!ENGINE_set_DSA(e, &ubsec_dsa) ||
205 206
#endif
#ifndef OPENSSL_NO_DH
207 208
			!ENGINE_set_DH(e, &ubsec_dh) ||
#endif
209
			!ENGINE_set_destroy_function(e, ubsec_destroy) ||
210 211 212 213 214
			!ENGINE_set_init_function(e, ubsec_init) ||
			!ENGINE_set_finish_function(e, ubsec_finish) ||
			!ENGINE_set_ctrl_function(e, ubsec_ctrl) ||
			!ENGINE_set_cmd_defns(e, ubsec_cmd_defns))
		return 0;
215

216
#ifndef OPENSSL_NO_RSA
217 218 219 220 221 222 223 224 225 226 227 228
	/* We know that the "PKCS1_SSLeay()" functions hook properly
	 * to the Broadcom-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();
	ubsec_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
	ubsec_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
	ubsec_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
	ubsec_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
229
#endif
230

231
#ifndef OPENSSL_NO_DH
232 233 234 235 236 237
#ifndef HAVE_UBSEC_DH
	/* Much the same for Diffie-Hellman */
	meth3 = DH_OpenSSL();
	ubsec_dh.generate_key = meth3->generate_key;
	ubsec_dh.compute_key = meth3->compute_key;
#endif /* HAVE_UBSEC_DH */
238
#endif
239

240
	/* Ensure the ubsec error handling is set up */
241
	ERR_load_UBSEC_strings();
242 243 244
	return 1;
	}

245
static ENGINE *engine_ubsec(void)
246 247 248 249 250 251 252 253 254
	{
	ENGINE *ret = ENGINE_new();
	if(!ret)
		return NULL;
	if(!bind_helper(ret))
		{
		ENGINE_free(ret);
		return NULL;
		}
G
Geoff Thorpe 已提交
255
	return ret;
256 257
	}

258 259 260 261 262 263 264 265 266 267
void ENGINE_load_ubsec(void)
	{
	/* Copied from eng_[openssl|dyn].c */
	ENGINE *toadd = engine_ubsec();
	if(!toadd) return;
	ENGINE_add(toadd);
	ENGINE_free(toadd);
	ERR_clear_error();
	}

268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
/* This is a process-global DSO handle used for loading and unloading
 * the UBSEC 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 *ubsec_dso = NULL;

/* These are the function pointers that are (un)set when the library has
 * successfully (un)loaded. */

static t_UBSEC_ubsec_bytes_to_bits *p_UBSEC_ubsec_bytes_to_bits = NULL;
static t_UBSEC_ubsec_bits_to_bytes *p_UBSEC_ubsec_bits_to_bytes = NULL;
static t_UBSEC_ubsec_open *p_UBSEC_ubsec_open = NULL;
static t_UBSEC_ubsec_close *p_UBSEC_ubsec_close = NULL;
283
#ifndef OPENSSL_NO_DH
284 285 286
static t_UBSEC_diffie_hellman_generate_ioctl 
	*p_UBSEC_diffie_hellman_generate_ioctl = NULL;
static t_UBSEC_diffie_hellman_agree_ioctl *p_UBSEC_diffie_hellman_agree_ioctl = NULL;
287 288
#endif
/* #ifndef OPENSSL_NO_RSA */
289 290
static t_UBSEC_rsa_mod_exp_ioctl *p_UBSEC_rsa_mod_exp_ioctl = NULL;
static t_UBSEC_rsa_mod_exp_crt_ioctl *p_UBSEC_rsa_mod_exp_crt_ioctl = NULL;
291 292
/* #endif */
#ifndef OPENSSL_NO_DSA
293 294
static t_UBSEC_dsa_sign_ioctl *p_UBSEC_dsa_sign_ioctl = NULL;
static t_UBSEC_dsa_verify_ioctl *p_UBSEC_dsa_verify_ioctl = NULL;
295
#endif
296 297
static t_UBSEC_math_accelerate_ioctl *p_UBSEC_math_accelerate_ioctl = NULL;
static t_UBSEC_rng_ioctl *p_UBSEC_rng_ioctl = NULL;
298 299 300
static t_UBSEC_max_key_len_ioctl *p_UBSEC_max_key_len_ioctl = NULL;

static int max_key_len = 1024;  /* ??? */
301

302 303 304 305 306 307 308 309 310 311
/* 
 * These are the static string constants for the DSO file name and the function
 * symbol names to bind to. 
 */

static const char *UBSEC_LIBNAME = "ubsec";
static const char *UBSEC_F1 = "ubsec_bytes_to_bits";
static const char *UBSEC_F2 = "ubsec_bits_to_bytes";
static const char *UBSEC_F3 = "ubsec_open";
static const char *UBSEC_F4 = "ubsec_close";
312
#ifndef OPENSSL_NO_DH
313 314
static const char *UBSEC_F5 = "diffie_hellman_generate_ioctl";
static const char *UBSEC_F6 = "diffie_hellman_agree_ioctl";
315 316
#endif
/* #ifndef OPENSSL_NO_RSA */
317 318
static const char *UBSEC_F7 = "rsa_mod_exp_ioctl";
static const char *UBSEC_F8 = "rsa_mod_exp_crt_ioctl";
319 320
/* #endif */
#ifndef OPENSSL_NO_DSA
321 322
static const char *UBSEC_F9 = "dsa_sign_ioctl";
static const char *UBSEC_F10 = "dsa_verify_ioctl";
323
#endif
324 325
static const char *UBSEC_F11 = "math_accelerate_ioctl";
static const char *UBSEC_F12 = "rng_ioctl";
326
static const char *UBSEC_F13 = "ubsec_max_key_len_ioctl";
327

328 329 330
/* Destructor (complements the "ENGINE_ubsec()" constructor) */
static int ubsec_destroy(ENGINE *e)
	{
331
	ERR_unload_UBSEC_strings();
332 333 334
	return 1;
	}

335
/* (de)initialisation functions. */
G
Geoff Thorpe 已提交
336
static int ubsec_init(ENGINE *e)
337 338 339 340 341
	{
	t_UBSEC_ubsec_bytes_to_bits *p1;
	t_UBSEC_ubsec_bits_to_bytes *p2;
	t_UBSEC_ubsec_open *p3;
	t_UBSEC_ubsec_close *p4;
342
#ifndef OPENSSL_NO_DH
343 344
	t_UBSEC_diffie_hellman_generate_ioctl *p5;
	t_UBSEC_diffie_hellman_agree_ioctl *p6;
345 346
#endif
/* #ifndef OPENSSL_NO_RSA */
347 348
	t_UBSEC_rsa_mod_exp_ioctl *p7;
	t_UBSEC_rsa_mod_exp_crt_ioctl *p8;
349 350
/* #endif */
#ifndef OPENSSL_NO_DSA
351 352
	t_UBSEC_dsa_sign_ioctl *p9;
	t_UBSEC_dsa_verify_ioctl *p10;
353
#endif
354 355
	t_UBSEC_math_accelerate_ioctl *p11;
	t_UBSEC_rng_ioctl *p12;
356
        t_UBSEC_max_key_len_ioctl *p13;
357 358 359 360
	int fd = 0;

	if(ubsec_dso != NULL)
		{
361
		UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_ALREADY_LOADED);
362 363 364 365 366 367 368 369
		goto err;
		}
	/* 
	 * Attempt to load libubsec.so/ubsec.dll/whatever. 
	 */
	ubsec_dso = DSO_load(NULL, UBSEC_LIBNAME, NULL, 0);
	if(ubsec_dso == NULL)
		{
370
		UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_DSO_FAILURE);
371 372 373 374 375 376 377 378
		goto err;
		}

	if (
	!(p1 = (t_UBSEC_ubsec_bytes_to_bits *) DSO_bind_func(ubsec_dso, UBSEC_F1)) ||
	!(p2 = (t_UBSEC_ubsec_bits_to_bytes *) DSO_bind_func(ubsec_dso, UBSEC_F2)) ||
	!(p3 = (t_UBSEC_ubsec_open *) DSO_bind_func(ubsec_dso, UBSEC_F3)) ||
	!(p4 = (t_UBSEC_ubsec_close *) DSO_bind_func(ubsec_dso, UBSEC_F4)) ||
379
#ifndef OPENSSL_NO_DH
380 381 382 383
	!(p5 = (t_UBSEC_diffie_hellman_generate_ioctl *) 
				DSO_bind_func(ubsec_dso, UBSEC_F5)) ||
	!(p6 = (t_UBSEC_diffie_hellman_agree_ioctl *) 
				DSO_bind_func(ubsec_dso, UBSEC_F6)) ||
384 385
#endif
/* #ifndef OPENSSL_NO_RSA */
386 387
	!(p7 = (t_UBSEC_rsa_mod_exp_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F7)) ||
	!(p8 = (t_UBSEC_rsa_mod_exp_crt_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F8)) ||
388 389
/* #endif */
#ifndef OPENSSL_NO_DSA
390 391
	!(p9 = (t_UBSEC_dsa_sign_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F9)) ||
	!(p10 = (t_UBSEC_dsa_verify_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F10)) ||
392
#endif
393 394
	!(p11 = (t_UBSEC_math_accelerate_ioctl *) 
				DSO_bind_func(ubsec_dso, UBSEC_F11)) ||
395 396
	!(p12 = (t_UBSEC_rng_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F12)) ||
        !(p13 = (t_UBSEC_max_key_len_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F13)))
397
		{
398
		UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_DSO_FAILURE);
399 400 401 402 403 404 405 406
		goto err;
		}

	/* Copy the pointers */
	p_UBSEC_ubsec_bytes_to_bits = p1;
	p_UBSEC_ubsec_bits_to_bytes = p2;
	p_UBSEC_ubsec_open = p3;
	p_UBSEC_ubsec_close = p4;
407
#ifndef OPENSSL_NO_DH
408 409
	p_UBSEC_diffie_hellman_generate_ioctl = p5;
	p_UBSEC_diffie_hellman_agree_ioctl = p6;
410 411
#endif
#ifndef OPENSSL_NO_RSA
412 413
	p_UBSEC_rsa_mod_exp_ioctl = p7;
	p_UBSEC_rsa_mod_exp_crt_ioctl = p8;
414 415
#endif
#ifndef OPENSSL_NO_DSA
416 417
	p_UBSEC_dsa_sign_ioctl = p9;
	p_UBSEC_dsa_verify_ioctl = p10;
418
#endif
419 420
	p_UBSEC_math_accelerate_ioctl = p11;
	p_UBSEC_rng_ioctl = p12;
421
        p_UBSEC_max_key_len_ioctl = p13;
422 423

	/* Perform an open to see if there's actually any unit running. */
424 425 426 427 428
	if (((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) > 0) && (p_UBSEC_max_key_len_ioctl(fd, &max_key_len) == 0))
	{
	   p_UBSEC_ubsec_close(fd);
	   return 1;
	}
429
	else
430 431 432
	{
	  UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_UNIT_FAILURE);
	}
433 434 435 436 437 438 439 440

err:
	if(ubsec_dso)
		DSO_free(ubsec_dso);
	p_UBSEC_ubsec_bytes_to_bits = NULL;
	p_UBSEC_ubsec_bits_to_bytes = NULL;
	p_UBSEC_ubsec_open = NULL;
	p_UBSEC_ubsec_close = NULL;
441
#ifndef OPENSSL_NO_DH
442 443
	p_UBSEC_diffie_hellman_generate_ioctl = NULL;
	p_UBSEC_diffie_hellman_agree_ioctl = NULL;
444 445
#endif
#ifndef OPENSSL_NO_RSA
446 447
	p_UBSEC_rsa_mod_exp_ioctl = NULL;
	p_UBSEC_rsa_mod_exp_crt_ioctl = NULL;
448 449
#endif
#ifndef OPENSSL_NO_DSA
450 451
	p_UBSEC_dsa_sign_ioctl = NULL;
	p_UBSEC_dsa_verify_ioctl = NULL;
452
#endif
453 454
	p_UBSEC_math_accelerate_ioctl = NULL;
	p_UBSEC_rng_ioctl = NULL;
455
        p_UBSEC_max_key_len_ioctl = NULL;
456 457 458 459

	return 0;
	}

G
Geoff Thorpe 已提交
460
static int ubsec_finish(ENGINE *e)
461 462 463
	{
	if(ubsec_dso == NULL)
		{
464
		UBSECerr(UBSEC_F_UBSEC_FINISH, UBSEC_R_NOT_LOADED);
465 466 467 468
		return 0;
		}
	if(!DSO_free(ubsec_dso))
		{
469
		UBSECerr(UBSEC_F_UBSEC_FINISH, UBSEC_R_DSO_FAILURE);
470 471 472 473 474 475 476
		return 0;
		}
	ubsec_dso = NULL;
	p_UBSEC_ubsec_bytes_to_bits = NULL;
	p_UBSEC_ubsec_bits_to_bytes = NULL;
	p_UBSEC_ubsec_open = NULL;
	p_UBSEC_ubsec_close = NULL;
477
#ifndef OPENSSL_NO_DH
478 479
	p_UBSEC_diffie_hellman_generate_ioctl = NULL;
	p_UBSEC_diffie_hellman_agree_ioctl = NULL;
480 481
#endif
#ifndef OPENSSL_NO_RSA
482 483
	p_UBSEC_rsa_mod_exp_ioctl = NULL;
	p_UBSEC_rsa_mod_exp_crt_ioctl = NULL;
484 485
#endif
#ifndef OPENSSL_NO_DSA
486 487
	p_UBSEC_dsa_sign_ioctl = NULL;
	p_UBSEC_dsa_verify_ioctl = NULL;
488
#endif
489 490
	p_UBSEC_math_accelerate_ioctl = NULL;
	p_UBSEC_rng_ioctl = NULL;
491
        p_UBSEC_max_key_len_ioctl = NULL;
492 493 494
	return 1;
	}

G
Geoff Thorpe 已提交
495 496 497 498 499 500 501 502
static int ubsec_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
	{
	int initialised = ((ubsec_dso == NULL) ? 0 : 1);
	switch(cmd)
		{
	case UBSEC_CMD_SO_PATH:
		if(p == NULL)
			{
503
			UBSECerr(UBSEC_F_UBSEC_CTRL,ERR_R_PASSED_NULL_PARAMETER);
G
Geoff Thorpe 已提交
504 505 506 507
			return 0;
			}
		if(initialised)
			{
508
			UBSECerr(UBSEC_F_UBSEC_CTRL,UBSEC_R_ALREADY_LOADED);
G
Geoff Thorpe 已提交
509 510 511 512 513 514 515
			return 0;
			}
		UBSEC_LIBNAME = (const char *)p;
		return 1;
	default:
		break;
		}
516
	UBSECerr(UBSEC_F_UBSEC_CTRL,UBSEC_R_CTRL_COMMAND_NOT_IMPLEMENTED);
G
Geoff Thorpe 已提交
517 518 519
	return 0;
	}

520 521 522 523 524 525 526 527
static int ubsec_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
		const BIGNUM *m, BN_CTX *ctx)
	{
	int 	y_len = 0;
	int 	fd;

	if(ubsec_dso == NULL)
	{
528
		UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_NOT_LOADED);
529 530 531 532 533
		return 0;
	}

	/* Check if hardware can't handle this argument. */
	y_len = BN_num_bits(m);
534
	if (y_len > max_key_len) {
535
		UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
536
                return BN_mod_exp(r, a, p, m, ctx);
537 538 539 540
	} 

	if(!bn_wexpand(r, m->top))
	{
541
		UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_BN_EXPAND_FAIL);
542 543 544 545 546 547
		return 0;
	}
	memset(r->d, 0, BN_num_bytes(m));

	if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) {
		fd = 0;
548
		UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_UNIT_FAILURE);
549
                return BN_mod_exp(r, a, p, m, ctx);
550 551 552 553 554 555
	}

	if (p_UBSEC_rsa_mod_exp_ioctl(fd, (unsigned char *)a->d, BN_num_bits(a),
		(unsigned char *)m->d, BN_num_bits(m), (unsigned char *)p->d, 
		BN_num_bits(p), (unsigned char *)r->d, &y_len) != 0)
	{
556
		UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_REQUEST_FAILED);
557 558 559
                p_UBSEC_ubsec_close(fd);

                return BN_mod_exp(r, a, p, m, ctx);
560 561 562 563 564 565 566 567
	}

	p_UBSEC_ubsec_close(fd);

	r->top = (BN_num_bits(m)+BN_BITS2-1)/BN_BITS2;
	return 1;
	}

568
#ifndef OPENSSL_NO_RSA
569 570 571 572 573 574 575 576 577 578
static int ubsec_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa)
	{
	BN_CTX *ctx;
	int to_return = 0;

	if((ctx = BN_CTX_new()) == NULL)
		goto err;

	if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
		{
579
		UBSECerr(UBSEC_F_UBSEC_RSA_MOD_EXP, UBSEC_R_MISSING_KEY_COMPONENTS);
580 581 582
		goto err;
		}

583 584 585 586 587 588 589 590 591
	to_return = ubsec_mod_exp_crt(r0, I, rsa->p, rsa->q, rsa->dmp1,
		    rsa->dmq1, rsa->iqmp, ctx);
	if (to_return == FAIL_TO_SOFTWARE)
	{
	  /*
	   * Do in software as hardware failed.
	   */
	   const RSA_METHOD *meth = RSA_PKCS1_SSLeay();
	   to_return = (*meth->rsa_mod_exp)(r0, I, rsa);
592 593 594 595 596 597
	}
err:
	if(ctx)
		BN_CTX_free(ctx);
	return to_return;
	}
598
#endif
599 600 601 602 603 604 605 606 607 608 609 610 611

static int ubsec_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
			const BIGNUM *q, const BIGNUM *dp,
			const BIGNUM *dq, const BIGNUM *qinv, BN_CTX *ctx)
	{
	int	y_len,
		m_len,
		fd;

	m_len = BN_num_bytes(p) + BN_num_bytes(q) + 1;
	y_len = BN_num_bits(p) + BN_num_bits(q);

	/* Check if hardware can't handle this argument. */
612
	if (y_len > max_key_len) {
613
		UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
614
		return FAIL_TO_SOFTWARE;
615 616 617
	} 

	if (!bn_wexpand(r, p->top + q->top + 1)) {
618
		UBSECerr(UBSEC_F_UBSEC_RSA_MOD_EXP_CRT, UBSEC_R_BN_EXPAND_FAIL);
619 620 621 622 623
		return 0;
	}

	if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) {
		fd = 0;
624
		UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_UNIT_FAILURE);
625
		return FAIL_TO_SOFTWARE;
626 627 628 629 630 631 632 633 634 635
	}

	if (p_UBSEC_rsa_mod_exp_crt_ioctl(fd,
		(unsigned char *)a->d, BN_num_bits(a), 
		(unsigned char *)qinv->d, BN_num_bits(qinv),
		(unsigned char *)dp->d, BN_num_bits(dp),
		(unsigned char *)p->d, BN_num_bits(p),
		(unsigned char *)dq->d, BN_num_bits(dq),
		(unsigned char *)q->d, BN_num_bits(q),
		(unsigned char *)r->d,  &y_len) != 0) {
636
		UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_REQUEST_FAILED);
637 638
                p_UBSEC_ubsec_close(fd);
		return FAIL_TO_SOFTWARE;
639 640 641 642 643 644 645 646
	}

	p_UBSEC_ubsec_close(fd);

	r->top = (BN_num_bits(p) + BN_num_bits(q) + BN_BITS2 - 1)/BN_BITS2;
	return 1;
}

647
#ifndef OPENSSL_NO_DSA
648
#if NOT_USED
649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674
static int ubsec_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 (!ubsec_mod_exp(rr,a1,p1,m,ctx)) goto end;
	/* let t = a2 ^ p2 mod m */
	if (!ubsec_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 ubsec_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a,
		const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
		BN_MONT_CTX *m_ctx)
	{
	return ubsec_mod_exp(r, a, p, m, ctx);
	}
675
#endif
676
#endif
677 678 679 680 681 682

/*
 * This function is aliased to mod_exp (with the mont stuff dropped).
 */
static int ubsec_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
		const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
683
        {
684 685
	int ret = 0;

686
#ifndef OPENSSL_NO_RSA
687
 	/* Do in software if the key is too large for the hardware. */
688
	if (BN_num_bits(m) > max_key_len)
689
                {
690 691
		const RSA_METHOD *meth = RSA_PKCS1_SSLeay();
		ret = (*meth->bn_mod_exp)(r, a, p, m, ctx, m_ctx);
692 693 694 695
                }
        else
#endif
                {
696
		ret = ubsec_mod_exp(r, a, p, m, ctx);
697
                }
698 699
	
	return ret;
700
        }
701

702
#ifndef OPENSSL_NO_DH
703 704 705 706 707 708 709
/* This function is aliased to mod_exp (with the dh and mont dropped). */
static int ubsec_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a,
		const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
		BN_MONT_CTX *m_ctx)
	{
	return ubsec_mod_exp(r, a, p, m, ctx);
	}
710
#endif
711

712
#ifndef OPENSSL_NO_DSA
713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729
static DSA_SIG *ubsec_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
	{
	DSA_SIG *to_return = NULL;
	int s_len = 160, r_len = 160, d_len, fd;
	BIGNUM m, *r=NULL, *s=NULL;

	BN_init(&m);

	s = BN_new();
	r = BN_new();
	if ((s == NULL) || (r==NULL))
		goto err;

	d_len = p_UBSEC_ubsec_bytes_to_bits((unsigned char *)dgst, dlen);

        if(!bn_wexpand(r, (160+BN_BITS2-1)/BN_BITS2) ||
       	   (!bn_wexpand(s, (160+BN_BITS2-1)/BN_BITS2))) {
730
		UBSECerr(UBSEC_F_UBSEC_DSA_SIGN, UBSEC_R_BN_EXPAND_FAIL);
731 732 733 734
		goto err;
	}

	if (BN_bin2bn(dgst,dlen,&m) == NULL) {
735
		UBSECerr(UBSEC_F_UBSEC_DSA_SIGN, UBSEC_R_BN_EXPAND_FAIL);
736 737 738 739
		goto err;
	} 

	if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) {
740
                const DSA_METHOD *meth;
741
		fd = 0;
742
		UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_UNIT_FAILURE);
743 744 745
                meth = DSA_OpenSSL();
                to_return =  meth->dsa_do_sign(dgst, dlen, dsa);
		goto err;
746 747 748 749 750 751 752 753 754 755 756
	}

	if (p_UBSEC_dsa_sign_ioctl(fd, 0, /* compute hash before signing */
		(unsigned char *)dgst, d_len,
		NULL, 0,  /* compute random value */
		(unsigned char *)dsa->p->d, BN_num_bits(dsa->p), 
		(unsigned char *)dsa->q->d, BN_num_bits(dsa->q),
		(unsigned char *)dsa->g->d, BN_num_bits(dsa->g),
		(unsigned char *)dsa->priv_key->d, BN_num_bits(dsa->priv_key),
		(unsigned char *)r->d, &r_len,
		(unsigned char *)s->d, &s_len ) != 0) {
757 758
                const DSA_METHOD *meth;

759
		UBSECerr(UBSEC_F_UBSEC_DSA_SIGN, UBSEC_R_REQUEST_FAILED);
760 761 762 763
                p_UBSEC_ubsec_close(fd);
                meth = DSA_OpenSSL();
                to_return = meth->dsa_do_sign(dgst, dlen, dsa);

764 765 766 767 768 769 770 771 772 773
		goto err;
	}

	p_UBSEC_ubsec_close(fd);

	r->top = (160+BN_BITS2-1)/BN_BITS2;
	s->top = (160+BN_BITS2-1)/BN_BITS2;

	to_return = DSA_SIG_new();
	if(to_return == NULL) {
774
		UBSECerr(UBSEC_F_UBSEC_DSA_SIGN, UBSEC_R_BN_EXPAND_FAIL);
775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800
		goto err;
	}

	to_return->r = r;
	to_return->s = s;

err:
	if (!to_return) {
		if (r) BN_free(r);
		if (s) BN_free(s);
	}                                 
	BN_clear_free(&m);
	return to_return;
}

static int ubsec_dsa_verify(const unsigned char *dgst, int dgst_len,
                                DSA_SIG *sig, DSA *dsa)
	{
	int v_len, d_len;
	int to_return = 0;
	int fd;
	BIGNUM v;

	BN_init(&v);

	if(!bn_wexpand(&v, dsa->p->top)) {
801
		UBSECerr(UBSEC_F_UBSEC_DSA_VERIFY ,UBSEC_R_BN_EXPAND_FAIL);
802 803 804 805 806 807 808 809
		goto err;
	}

	v_len = BN_num_bits(dsa->p);

	d_len = p_UBSEC_ubsec_bytes_to_bits((unsigned char *)dgst, dgst_len);

	if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) {
810
                const DSA_METHOD *meth;
811
		fd = 0;
812
		UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_UNIT_FAILURE);
813 814 815
                meth = DSA_OpenSSL();
                to_return = meth->dsa_do_verify(dgst, dgst_len, sig, dsa);
		goto err;
816 817 818 819 820 821 822 823 824 825 826
	}

	if (p_UBSEC_dsa_verify_ioctl(fd, 0, /* compute hash before signing */
		(unsigned char *)dgst, d_len,
		(unsigned char *)dsa->p->d, BN_num_bits(dsa->p), 
		(unsigned char *)dsa->q->d, BN_num_bits(dsa->q),
		(unsigned char *)dsa->g->d, BN_num_bits(dsa->g),
		(unsigned char *)dsa->pub_key->d, BN_num_bits(dsa->pub_key),
		(unsigned char *)sig->r->d, BN_num_bits(sig->r),
		(unsigned char *)sig->s->d, BN_num_bits(sig->s),
		(unsigned char *)v.d, &v_len) != 0) {
827
                const DSA_METHOD *meth;
828
		UBSECerr(UBSEC_F_UBSEC_DSA_VERIFY , UBSEC_R_REQUEST_FAILED);
829 830 831 832 833
                p_UBSEC_ubsec_close(fd);

                meth = DSA_OpenSSL();
                to_return = meth->dsa_do_verify(dgst, dgst_len, sig, dsa);

834 835 836 837 838 839 840 841 842 843
		goto err;
	}

	p_UBSEC_ubsec_close(fd);

	to_return = 1;
err:
	BN_clear_free(&v);
	return to_return;
	}
844
#endif
845

846
#ifndef OPENSSL_NO_DH
847
static int ubsec_dh_compute_key (unsigned char *key,const BIGNUM *pub_key,DH *dh)
848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886
        {
        int      ret      = -1,
                 k_len,
                 fd;

        k_len = BN_num_bits(dh->p);

        if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0)
                {
                const DH_METHOD *meth;
                ENGINEerr(UBSEC_F_UBSEC_INIT, ENGINE_R_UNIT_FAILURE);
                meth = DH_OpenSSL();
                ret = meth->compute_key(key, pub_key, dh);
                goto err;
                }

        if (p_UBSEC_diffie_hellman_agree_ioctl(fd,
                                               (unsigned char *)dh->priv_key->d, BN_num_bits(dh->priv_key),
                                               (unsigned char *)pub_key->d, BN_num_bits(pub_key),
                                               (unsigned char *)dh->p->d, BN_num_bits(dh->p),
                                               key, &k_len) != 0)
                {
                /* Hardware's a no go, failover to software */
                const DH_METHOD *meth;
                ENGINEerr(UBSEC_F_UBSEC_DH_COMPUTE_KEY, ENGINE_R_REQUEST_FAILED);
                p_UBSEC_ubsec_close(fd);

                meth = DH_OpenSSL();
                ret = meth->compute_key(key, pub_key, dh);

                goto err;
                }

        p_UBSEC_ubsec_close(fd);

        ret = p_UBSEC_ubsec_bits_to_bytes(k_len);
err:
        return ret;
        }
887 888

static int ubsec_dh_generate_key (DH *dh)
889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969
        {
        int      ret               = 0,
                 random_bits       = 0,
                 pub_key_len       = 0,
                 priv_key_len      = 0,
                 fd;
        BIGNUM   *pub_key          = NULL;
        BIGNUM   *priv_key         = NULL;

        /* 
         *  How many bits should Random x be? dh_key.c
         *  sets the range from 0 to num_bits(modulus) ???
         */

        if (dh->priv_key == NULL)
                {
                priv_key = BN_new();
                if (priv_key == NULL) goto err;
                priv_key_len = BN_num_bits(dh->p);
                bn_wexpand(priv_key, dh->p->top);
                do
                        if (!BN_rand_range(priv_key, dh->p)) goto err;
                while (BN_is_zero(priv_key));
                random_bits = BN_num_bits(priv_key);
                }
        else
                {
                priv_key = dh->priv_key;
                }

        if (dh->pub_key == NULL)
                {
                pub_key = BN_new();
                pub_key_len = BN_num_bits(dh->p);
                bn_wexpand(pub_key, dh->p->top);
                if(pub_key == NULL) goto err;
                }
        else
                {
                pub_key = dh->pub_key;
                }

        if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0)
                {
                const DH_METHOD *meth;
                ENGINEerr(UBSEC_F_UBSEC_INIT, ENGINE_R_UNIT_FAILURE);
                meth = DH_OpenSSL();
                ret = meth->generate_key(dh);
                goto err;
                }

        if (p_UBSEC_diffie_hellman_generate_ioctl(fd,
                                                  (unsigned char *)priv_key->d, &priv_key_len,
                                                  (unsigned char *)pub_key->d,  &pub_key_len,
                                                  (unsigned char *)dh->g->d, BN_num_bits(dh->g),
                                                  (unsigned char *)dh->p->d, BN_num_bits(dh->p),
                                                  0, 0, random_bits) != 0)
                {
                /* Hardware's a no go, failover to software */
                const DH_METHOD *meth;

                ENGINEerr(UBSEC_F_UBSEC_DH_COMPUTE_KEY, ENGINE_R_REQUEST_FAILED);
                p_UBSEC_ubsec_close(fd);

                meth = DH_OpenSSL();
                ret = meth->generate_key(dh);

                goto err;
                }

        p_UBSEC_ubsec_close(fd);

        dh->pub_key = pub_key;
        dh->pub_key->top = (pub_key_len + BN_BITS2-1) / BN_BITS2;
        dh->priv_key = priv_key;
        dh->priv_key->top = (priv_key_len + BN_BITS2-1) / BN_BITS2;

        ret = 1;
err:
        return ret;
        }
970
#endif
971

972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017
#if NOT_USED
static int ubsec_rand_bytes(unsigned char * buf,
                            int num)
        {
        int      ret      = 0,
                 fd;

        if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0)
                {
                const RAND_METHOD *meth;
                ENGINEerr(UBSEC_F_UBSEC_INIT, ENGINE_R_UNIT_FAILURE);
                num = p_UBSEC_ubsec_bits_to_bytes(num);
                meth = RAND_SSLeay();
                meth->seed(buf, num);
                ret = meth->bytes(buf, num);
                goto err;
                }

        num *= 8; /* bytes to bits */

        if (p_UBSEC_rng_ioctl(fd,
                              UBSEC_RNG_DIRECT,
                              buf,
                              &num) != 0)
                {
                /* Hardware's a no go, failover to software */
                const RAND_METHOD *meth;

                ENGINEerr(UBSEC_F_UBSEC_RNG_BYTES, ENGINE_R_REQUEST_FAILED);
                p_UBSEC_ubsec_close(fd);

                num = p_UBSEC_ubsec_bits_to_bytes(num);
                meth = RAND_SSLeay();
                meth->seed(buf, num);
                ret = meth->bytes(buf, num);

                goto err;
                }

        p_UBSEC_ubsec_close(fd);

        ret = 1;
err:
        return(ret);
        }

1018 1019 1020 1021 1022

static int ubsec_rand_status(void)
	{
	return 0;
	}
1023
#endif
1024

1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039
/* 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_ubsec_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 */

1040 1041
#endif /* !OPENSSL_NO_HW_UBSEC */
#endif /* !OPENSSL_NO_HW */