hw_ubsec.c 30.1 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
#ifdef 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
#ifdef 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
/* 
 * These are the static string constants for the DSO file name and the function
 * symbol names to bind to. 
 */

307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324
static const char *UBSEC_LIBNAME = NULL;
static const char *get_UBSEC_LIBNAME(void)
	{
	if(UBSEC_LIBNAME)
		return UBSEC_LIBNAME;
	return "ubsec";
	}
static void free_UBSEC_LIBNAME(void)
	{
	if(UBSEC_LIBNAME)
		OPENSSL_free((void*)UBSEC_LIBNAME);
	UBSEC_LIBNAME = NULL;
	}
static long set_UBSEC_LIBNAME(const char *name)
	{
	free_UBSEC_LIBNAME();
	return (((UBSEC_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0);
	}
325 326 327 328
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";
329
#ifndef OPENSSL_NO_DH
330 331
static const char *UBSEC_F5 = "diffie_hellman_generate_ioctl";
static const char *UBSEC_F6 = "diffie_hellman_agree_ioctl";
332 333
#endif
/* #ifndef OPENSSL_NO_RSA */
334 335
static const char *UBSEC_F7 = "rsa_mod_exp_ioctl";
static const char *UBSEC_F8 = "rsa_mod_exp_crt_ioctl";
336 337
/* #endif */
#ifndef OPENSSL_NO_DSA
338 339
static const char *UBSEC_F9 = "dsa_sign_ioctl";
static const char *UBSEC_F10 = "dsa_verify_ioctl";
340
#endif
341 342
static const char *UBSEC_F11 = "math_accelerate_ioctl";
static const char *UBSEC_F12 = "rng_ioctl";
343
static const char *UBSEC_F13 = "ubsec_max_key_len_ioctl";
344

345 346 347
/* Destructor (complements the "ENGINE_ubsec()" constructor) */
static int ubsec_destroy(ENGINE *e)
	{
348
	free_UBSEC_LIBNAME();
349
	ERR_unload_UBSEC_strings();
350 351 352
	return 1;
	}

353
/* (de)initialisation functions. */
G
Geoff Thorpe 已提交
354
static int ubsec_init(ENGINE *e)
355 356 357 358 359
	{
	t_UBSEC_ubsec_bytes_to_bits *p1;
	t_UBSEC_ubsec_bits_to_bytes *p2;
	t_UBSEC_ubsec_open *p3;
	t_UBSEC_ubsec_close *p4;
360
#ifndef OPENSSL_NO_DH
361 362
	t_UBSEC_diffie_hellman_generate_ioctl *p5;
	t_UBSEC_diffie_hellman_agree_ioctl *p6;
363 364
#endif
/* #ifndef OPENSSL_NO_RSA */
365 366
	t_UBSEC_rsa_mod_exp_ioctl *p7;
	t_UBSEC_rsa_mod_exp_crt_ioctl *p8;
367 368
/* #endif */
#ifndef OPENSSL_NO_DSA
369 370
	t_UBSEC_dsa_sign_ioctl *p9;
	t_UBSEC_dsa_verify_ioctl *p10;
371
#endif
372 373
	t_UBSEC_math_accelerate_ioctl *p11;
	t_UBSEC_rng_ioctl *p12;
374
        t_UBSEC_max_key_len_ioctl *p13;
375 376 377 378
	int fd = 0;

	if(ubsec_dso != NULL)
		{
379
		UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_ALREADY_LOADED);
380 381 382 383 384
		goto err;
		}
	/* 
	 * Attempt to load libubsec.so/ubsec.dll/whatever. 
	 */
385
	ubsec_dso = DSO_load(NULL, get_UBSEC_LIBNAME(), NULL, 0);
386 387
	if(ubsec_dso == NULL)
		{
388
		UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_DSO_FAILURE);
389 390 391 392 393 394 395 396
		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)) ||
397
#ifndef OPENSSL_NO_DH
398 399 400 401
	!(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)) ||
402 403
#endif
/* #ifndef OPENSSL_NO_RSA */
404 405
	!(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)) ||
406 407
/* #endif */
#ifndef OPENSSL_NO_DSA
408 409
	!(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)) ||
410
#endif
411 412
	!(p11 = (t_UBSEC_math_accelerate_ioctl *) 
				DSO_bind_func(ubsec_dso, UBSEC_F11)) ||
413 414
	!(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)))
415
		{
416
		UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_DSO_FAILURE);
417 418 419 420 421 422 423 424
		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;
425
#ifndef OPENSSL_NO_DH
426 427
	p_UBSEC_diffie_hellman_generate_ioctl = p5;
	p_UBSEC_diffie_hellman_agree_ioctl = p6;
428 429
#endif
#ifndef OPENSSL_NO_RSA
430 431
	p_UBSEC_rsa_mod_exp_ioctl = p7;
	p_UBSEC_rsa_mod_exp_crt_ioctl = p8;
432 433
#endif
#ifndef OPENSSL_NO_DSA
434 435
	p_UBSEC_dsa_sign_ioctl = p9;
	p_UBSEC_dsa_verify_ioctl = p10;
436
#endif
437 438
	p_UBSEC_math_accelerate_ioctl = p11;
	p_UBSEC_rng_ioctl = p12;
439
        p_UBSEC_max_key_len_ioctl = p13;
440 441

	/* Perform an open to see if there's actually any unit running. */
442 443 444 445 446
	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;
	}
447
	else
448 449 450
	{
	  UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_UNIT_FAILURE);
	}
451 452 453 454 455 456 457 458

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;
459
#ifndef OPENSSL_NO_DH
460 461
	p_UBSEC_diffie_hellman_generate_ioctl = NULL;
	p_UBSEC_diffie_hellman_agree_ioctl = NULL;
462 463
#endif
#ifndef OPENSSL_NO_RSA
464 465
	p_UBSEC_rsa_mod_exp_ioctl = NULL;
	p_UBSEC_rsa_mod_exp_crt_ioctl = NULL;
466 467
#endif
#ifndef OPENSSL_NO_DSA
468 469
	p_UBSEC_dsa_sign_ioctl = NULL;
	p_UBSEC_dsa_verify_ioctl = NULL;
470
#endif
471 472
	p_UBSEC_math_accelerate_ioctl = NULL;
	p_UBSEC_rng_ioctl = NULL;
473
        p_UBSEC_max_key_len_ioctl = NULL;
474 475 476 477

	return 0;
	}

G
Geoff Thorpe 已提交
478
static int ubsec_finish(ENGINE *e)
479
	{
480
	free_UBSEC_LIBNAME();
481 482
	if(ubsec_dso == NULL)
		{
483
		UBSECerr(UBSEC_F_UBSEC_FINISH, UBSEC_R_NOT_LOADED);
484 485 486 487
		return 0;
		}
	if(!DSO_free(ubsec_dso))
		{
488
		UBSECerr(UBSEC_F_UBSEC_FINISH, UBSEC_R_DSO_FAILURE);
489 490 491 492 493 494 495
		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;
496
#ifndef OPENSSL_NO_DH
497 498
	p_UBSEC_diffie_hellman_generate_ioctl = NULL;
	p_UBSEC_diffie_hellman_agree_ioctl = NULL;
499 500
#endif
#ifndef OPENSSL_NO_RSA
501 502
	p_UBSEC_rsa_mod_exp_ioctl = NULL;
	p_UBSEC_rsa_mod_exp_crt_ioctl = NULL;
503 504
#endif
#ifndef OPENSSL_NO_DSA
505 506
	p_UBSEC_dsa_sign_ioctl = NULL;
	p_UBSEC_dsa_verify_ioctl = NULL;
507
#endif
508 509
	p_UBSEC_math_accelerate_ioctl = NULL;
	p_UBSEC_rng_ioctl = NULL;
510
        p_UBSEC_max_key_len_ioctl = NULL;
511 512 513
	return 1;
	}

G
Geoff Thorpe 已提交
514 515 516 517 518 519 520 521
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)
			{
522
			UBSECerr(UBSEC_F_UBSEC_CTRL,ERR_R_PASSED_NULL_PARAMETER);
G
Geoff Thorpe 已提交
523 524 525 526
			return 0;
			}
		if(initialised)
			{
527
			UBSECerr(UBSEC_F_UBSEC_CTRL,UBSEC_R_ALREADY_LOADED);
G
Geoff Thorpe 已提交
528 529
			return 0;
			}
530
		return set_UBSEC_LIBNAME((const char *)p);
G
Geoff Thorpe 已提交
531 532 533
	default:
		break;
		}
534
	UBSECerr(UBSEC_F_UBSEC_CTRL,UBSEC_R_CTRL_COMMAND_NOT_IMPLEMENTED);
G
Geoff Thorpe 已提交
535 536 537
	return 0;
	}

538 539 540 541 542 543 544 545
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)
	{
546
		UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_NOT_LOADED);
547 548 549 550 551
		return 0;
	}

	/* Check if hardware can't handle this argument. */
	y_len = BN_num_bits(m);
552
	if (y_len > max_key_len) {
553
		UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
554
                return BN_mod_exp(r, a, p, m, ctx);
555 556 557 558
	} 

	if(!bn_wexpand(r, m->top))
	{
559
		UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_BN_EXPAND_FAIL);
560 561 562 563 564 565
		return 0;
	}
	memset(r->d, 0, BN_num_bytes(m));

	if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) {
		fd = 0;
566
		UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_UNIT_FAILURE);
567
                return BN_mod_exp(r, a, p, m, ctx);
568 569 570 571 572 573
	}

	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)
	{
574
		UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_REQUEST_FAILED);
575 576 577
                p_UBSEC_ubsec_close(fd);

                return BN_mod_exp(r, a, p, m, ctx);
578 579 580 581 582 583 584 585
	}

	p_UBSEC_ubsec_close(fd);

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

586
#ifndef OPENSSL_NO_RSA
587 588 589 590 591 592 593 594 595 596
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)
		{
597
		UBSECerr(UBSEC_F_UBSEC_RSA_MOD_EXP, UBSEC_R_MISSING_KEY_COMPONENTS);
598 599 600
		goto err;
		}

601 602 603 604 605 606 607 608 609
	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);
610 611 612 613 614 615
	}
err:
	if(ctx)
		BN_CTX_free(ctx);
	return to_return;
	}
616
#endif
617 618 619 620 621 622 623 624 625 626 627 628 629

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. */
630
	if (y_len > max_key_len) {
631
		UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
632
		return FAIL_TO_SOFTWARE;
633 634 635
	} 

	if (!bn_wexpand(r, p->top + q->top + 1)) {
636
		UBSECerr(UBSEC_F_UBSEC_RSA_MOD_EXP_CRT, UBSEC_R_BN_EXPAND_FAIL);
637 638 639 640 641
		return 0;
	}

	if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) {
		fd = 0;
642
		UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_UNIT_FAILURE);
643
		return FAIL_TO_SOFTWARE;
644 645 646 647 648 649 650 651 652 653
	}

	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) {
654
		UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_REQUEST_FAILED);
655 656
                p_UBSEC_ubsec_close(fd);
		return FAIL_TO_SOFTWARE;
657 658 659 660 661 662 663 664
	}

	p_UBSEC_ubsec_close(fd);

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

665
#ifndef OPENSSL_NO_DSA
666
#ifdef NOT_USED
667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692
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);
	}
693
#endif
694
#endif
695 696 697 698 699 700

/*
 * 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)
701
        {
702 703
	int ret = 0;

704
#ifndef OPENSSL_NO_RSA
705
 	/* Do in software if the key is too large for the hardware. */
706
	if (BN_num_bits(m) > max_key_len)
707
                {
708 709
		const RSA_METHOD *meth = RSA_PKCS1_SSLeay();
		ret = (*meth->bn_mod_exp)(r, a, p, m, ctx, m_ctx);
710 711 712 713
                }
        else
#endif
                {
714
		ret = ubsec_mod_exp(r, a, p, m, ctx);
715
                }
716 717
	
	return ret;
718
        }
719

720
#ifndef OPENSSL_NO_DH
721 722 723 724 725 726 727
/* 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);
	}
728
#endif
729

730
#ifndef OPENSSL_NO_DSA
731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747
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))) {
748
		UBSECerr(UBSEC_F_UBSEC_DSA_SIGN, UBSEC_R_BN_EXPAND_FAIL);
749 750 751 752
		goto err;
	}

	if (BN_bin2bn(dgst,dlen,&m) == NULL) {
753
		UBSECerr(UBSEC_F_UBSEC_DSA_SIGN, UBSEC_R_BN_EXPAND_FAIL);
754 755 756 757
		goto err;
	} 

	if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) {
758
                const DSA_METHOD *meth;
759
		fd = 0;
760
		UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_UNIT_FAILURE);
761 762 763
                meth = DSA_OpenSSL();
                to_return =  meth->dsa_do_sign(dgst, dlen, dsa);
		goto err;
764 765 766 767 768 769 770 771 772 773 774
	}

	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) {
775 776
                const DSA_METHOD *meth;

777
		UBSECerr(UBSEC_F_UBSEC_DSA_SIGN, UBSEC_R_REQUEST_FAILED);
778 779 780 781
                p_UBSEC_ubsec_close(fd);
                meth = DSA_OpenSSL();
                to_return = meth->dsa_do_sign(dgst, dlen, dsa);

782 783 784 785 786 787 788 789 790 791
		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) {
792
		UBSECerr(UBSEC_F_UBSEC_DSA_SIGN, UBSEC_R_BN_EXPAND_FAIL);
793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818
		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)) {
819
		UBSECerr(UBSEC_F_UBSEC_DSA_VERIFY ,UBSEC_R_BN_EXPAND_FAIL);
820 821 822 823 824 825 826 827
		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) {
828
                const DSA_METHOD *meth;
829
		fd = 0;
830
		UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_UNIT_FAILURE);
831 832 833
                meth = DSA_OpenSSL();
                to_return = meth->dsa_do_verify(dgst, dgst_len, sig, dsa);
		goto err;
834 835 836 837 838 839 840 841 842 843 844
	}

	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) {
845
                const DSA_METHOD *meth;
846
		UBSECerr(UBSEC_F_UBSEC_DSA_VERIFY , UBSEC_R_REQUEST_FAILED);
847 848 849 850 851
                p_UBSEC_ubsec_close(fd);

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

852 853 854 855 856 857 858 859 860 861
		goto err;
	}

	p_UBSEC_ubsec_close(fd);

	to_return = 1;
err:
	BN_clear_free(&v);
	return to_return;
	}
862
#endif
863

864
#ifndef OPENSSL_NO_DH
865
static int ubsec_dh_compute_key (unsigned char *key,const BIGNUM *pub_key,DH *dh)
866 867 868 869 870 871 872 873 874 875
        {
        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;
876
                ENGINEerr(UBSEC_F_UBSEC_INIT, UBSEC_R_UNIT_FAILURE);
877 878 879 880 881 882 883 884 885 886 887 888 889
                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;
890
                ENGINEerr(UBSEC_F_UBSEC_DH_COMPUTE_KEY, UBSEC_R_REQUEST_FAILED);
891 892 893 894 895 896 897 898 899 900 901 902 903 904
                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;
        }
905 906

static int ubsec_dh_generate_key (DH *dh)
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
        {
        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;
952
                ENGINEerr(UBSEC_F_UBSEC_INIT, UBSEC_R_UNIT_FAILURE);
953 954 955 956 957 958 959 960 961 962 963 964 965 966 967
                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;

968
                ENGINEerr(UBSEC_F_UBSEC_DH_COMPUTE_KEY, UBSEC_R_REQUEST_FAILED);
969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987
                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;
        }
988
#endif
989

990
#ifdef NOT_USED
991 992 993 994 995 996 997 998 999
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;
1000
                ENGINEerr(UBSEC_F_UBSEC_INIT, UBSEC_R_UNIT_FAILURE);
1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017
                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;

1018
                ENGINEerr(UBSEC_F_UBSEC_RNG_BYTES, UBSEC_R_REQUEST_FAILED);
1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035
                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);
        }

1036 1037 1038 1039 1040

static int ubsec_rand_status(void)
	{
	return 0;
	}
1041
#endif
1042

1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057
/* 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 */

1058 1059
#endif /* !OPENSSL_NO_HW_UBSEC */
#endif /* !OPENSSL_NO_HW */