e_ubsec.c revision 215697
1/* crypto/engine/hw_ubsec.c */
2/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL
3 * project 2000.
4 *
5 * Cloned shamelessly by Joe Tardo.
6 */
7/* ====================================================================
8 * Copyright (c) 1999-2001 The OpenSSL Project.  All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 *
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 *
17 * 2. Redistributions in binary form must reproduce the above copyright
18 *    notice, this list of conditions and the following disclaimer in
19 *    the documentation and/or other materials provided with the
20 *    distribution.
21 *
22 * 3. All advertising materials mentioning features or use of this
23 *    software must display the following acknowledgment:
24 *    "This product includes software developed by the OpenSSL Project
25 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
26 *
27 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
28 *    endorse or promote products derived from this software without
29 *    prior written permission. For written permission, please contact
30 *    licensing@OpenSSL.org.
31 *
32 * 5. Products derived from this software may not be called "OpenSSL"
33 *    nor may "OpenSSL" appear in their names without prior written
34 *    permission of the OpenSSL Project.
35 *
36 * 6. Redistributions of any form whatsoever must retain the following
37 *    acknowledgment:
38 *    "This product includes software developed by the OpenSSL Project
39 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
40 *
41 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
42 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
44 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
45 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
47 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
48 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
50 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
51 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
52 * OF THE POSSIBILITY OF SUCH DAMAGE.
53 * ====================================================================
54 *
55 * This product includes cryptographic software written by Eric Young
56 * (eay@cryptsoft.com).  This product includes software written by Tim
57 * Hudson (tjh@cryptsoft.com).
58 *
59 */
60
61#include <stdio.h>
62#include <string.h>
63#include <openssl/crypto.h>
64#include <openssl/buffer.h>
65#include <openssl/dso.h>
66#include <openssl/engine.h>
67#ifndef OPENSSL_NO_RSA
68#include <openssl/rsa.h>
69#endif
70#ifndef OPENSSL_NO_DSA
71#include <openssl/dsa.h>
72#endif
73#ifndef OPENSSL_NO_DH
74#include <openssl/dh.h>
75#endif
76#include <openssl/bn.h>
77
78#ifndef OPENSSL_NO_HW
79#ifndef OPENSSL_NO_HW_UBSEC
80
81#ifdef FLAT_INC
82#include "hw_ubsec.h"
83#else
84#include "vendor_defns/hw_ubsec.h"
85#endif
86
87#define UBSEC_LIB_NAME "ubsec engine"
88#include "e_ubsec_err.c"
89
90#define FAIL_TO_SOFTWARE -15
91
92static int ubsec_destroy(ENGINE *e);
93static int ubsec_init(ENGINE *e);
94static int ubsec_finish(ENGINE *e);
95static int ubsec_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void));
96static int ubsec_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
97		const BIGNUM *m, BN_CTX *ctx);
98static int ubsec_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
99			const BIGNUM *q, const BIGNUM *dp,
100			const BIGNUM *dq, const BIGNUM *qinv, BN_CTX *ctx);
101#ifndef OPENSSL_NO_RSA
102static int ubsec_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx);
103#endif
104static int ubsec_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
105		const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
106#ifndef OPENSSL_NO_DSA
107#ifdef NOT_USED
108static int ubsec_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1,
109		BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m,
110		BN_CTX *ctx, BN_MONT_CTX *in_mont);
111static int ubsec_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a,
112		const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
113		BN_MONT_CTX *m_ctx);
114#endif
115static DSA_SIG *ubsec_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa);
116static int ubsec_dsa_verify(const unsigned char *dgst, int dgst_len,
117                                DSA_SIG *sig, DSA *dsa);
118#endif
119#ifndef OPENSSL_NO_DH
120static int ubsec_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a,
121		const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
122		BN_MONT_CTX *m_ctx);
123static int ubsec_dh_compute_key(unsigned char *key,const BIGNUM *pub_key,DH *dh);
124static int ubsec_dh_generate_key(DH *dh);
125#endif
126
127#ifdef NOT_USED
128static int ubsec_rand_bytes(unsigned char *buf, int num);
129static int ubsec_rand_status(void);
130#endif
131
132#define UBSEC_CMD_SO_PATH		ENGINE_CMD_BASE
133static const ENGINE_CMD_DEFN ubsec_cmd_defns[] = {
134	{UBSEC_CMD_SO_PATH,
135		"SO_PATH",
136		"Specifies the path to the 'ubsec' shared library",
137		ENGINE_CMD_FLAG_STRING},
138	{0, NULL, NULL, 0}
139	};
140
141#ifndef OPENSSL_NO_RSA
142/* Our internal RSA_METHOD that we provide pointers to */
143static RSA_METHOD ubsec_rsa =
144	{
145	"UBSEC RSA method",
146	NULL,
147	NULL,
148	NULL,
149	NULL,
150	ubsec_rsa_mod_exp,
151	ubsec_mod_exp_mont,
152	NULL,
153	NULL,
154	0,
155	NULL,
156	NULL,
157	NULL,
158	NULL
159	};
160#endif
161
162#ifndef OPENSSL_NO_DSA
163/* Our internal DSA_METHOD that we provide pointers to */
164static DSA_METHOD ubsec_dsa =
165	{
166	"UBSEC DSA method",
167	ubsec_dsa_do_sign, /* dsa_do_sign */
168	NULL, /* dsa_sign_setup */
169	ubsec_dsa_verify, /* dsa_do_verify */
170	NULL, /* ubsec_dsa_mod_exp */ /* dsa_mod_exp */
171	NULL, /* ubsec_mod_exp_dsa */ /* bn_mod_exp */
172	NULL, /* init */
173	NULL, /* finish */
174	0, /* flags */
175	NULL, /* app_data */
176	NULL, /* dsa_paramgen */
177	NULL /* dsa_keygen */
178	};
179#endif
180
181#ifndef OPENSSL_NO_DH
182/* Our internal DH_METHOD that we provide pointers to */
183static DH_METHOD ubsec_dh =
184	{
185	"UBSEC DH method",
186	ubsec_dh_generate_key,
187	ubsec_dh_compute_key,
188	ubsec_mod_exp_dh,
189	NULL,
190	NULL,
191	0,
192	NULL,
193	NULL
194	};
195#endif
196
197/* Constants used when creating the ENGINE */
198static const char *engine_ubsec_id = "ubsec";
199static const char *engine_ubsec_name = "UBSEC hardware engine support";
200
201/* This internal function is used by ENGINE_ubsec() and possibly by the
202 * "dynamic" ENGINE support too */
203static int bind_helper(ENGINE *e)
204	{
205#ifndef OPENSSL_NO_RSA
206	const RSA_METHOD *meth1;
207#endif
208#ifndef OPENSSL_NO_DH
209#ifndef HAVE_UBSEC_DH
210	const DH_METHOD *meth3;
211#endif /* HAVE_UBSEC_DH */
212#endif
213	if(!ENGINE_set_id(e, engine_ubsec_id) ||
214			!ENGINE_set_name(e, engine_ubsec_name) ||
215#ifndef OPENSSL_NO_RSA
216			!ENGINE_set_RSA(e, &ubsec_rsa) ||
217#endif
218#ifndef OPENSSL_NO_DSA
219			!ENGINE_set_DSA(e, &ubsec_dsa) ||
220#endif
221#ifndef OPENSSL_NO_DH
222			!ENGINE_set_DH(e, &ubsec_dh) ||
223#endif
224			!ENGINE_set_destroy_function(e, ubsec_destroy) ||
225			!ENGINE_set_init_function(e, ubsec_init) ||
226			!ENGINE_set_finish_function(e, ubsec_finish) ||
227			!ENGINE_set_ctrl_function(e, ubsec_ctrl) ||
228			!ENGINE_set_cmd_defns(e, ubsec_cmd_defns))
229		return 0;
230
231#ifndef OPENSSL_NO_RSA
232	/* We know that the "PKCS1_SSLeay()" functions hook properly
233	 * to the Broadcom-specific mod_exp and mod_exp_crt so we use
234	 * those functions. NB: We don't use ENGINE_openssl() or
235	 * anything "more generic" because something like the RSAref
236	 * code may not hook properly, and if you own one of these
237	 * cards then you have the right to do RSA operations on it
238	 * anyway! */
239	meth1 = RSA_PKCS1_SSLeay();
240	ubsec_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
241	ubsec_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
242	ubsec_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
243	ubsec_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
244#endif
245
246#ifndef OPENSSL_NO_DH
247#ifndef HAVE_UBSEC_DH
248	/* Much the same for Diffie-Hellman */
249	meth3 = DH_OpenSSL();
250	ubsec_dh.generate_key = meth3->generate_key;
251	ubsec_dh.compute_key = meth3->compute_key;
252#endif /* HAVE_UBSEC_DH */
253#endif
254
255	/* Ensure the ubsec error handling is set up */
256	ERR_load_UBSEC_strings();
257	return 1;
258	}
259
260#ifdef OPENSSL_NO_DYNAMIC_ENGINE
261static ENGINE *engine_ubsec(void)
262	{
263	ENGINE *ret = ENGINE_new();
264	if(!ret)
265		return NULL;
266	if(!bind_helper(ret))
267		{
268		ENGINE_free(ret);
269		return NULL;
270		}
271	return ret;
272	}
273
274void ENGINE_load_ubsec(void)
275	{
276	/* Copied from eng_[openssl|dyn].c */
277	ENGINE *toadd = engine_ubsec();
278	if(!toadd) return;
279	ENGINE_add(toadd);
280	ENGINE_free(toadd);
281	ERR_clear_error();
282	}
283#endif
284
285/* This is a process-global DSO handle used for loading and unloading
286 * the UBSEC library. NB: This is only set (or unset) during an
287 * init() or finish() call (reference counts permitting) and they're
288 * operating with global locks, so this should be thread-safe
289 * implicitly. */
290
291static DSO *ubsec_dso = NULL;
292
293/* These are the function pointers that are (un)set when the library has
294 * successfully (un)loaded. */
295
296static t_UBSEC_ubsec_bytes_to_bits *p_UBSEC_ubsec_bytes_to_bits = NULL;
297static t_UBSEC_ubsec_bits_to_bytes *p_UBSEC_ubsec_bits_to_bytes = NULL;
298static t_UBSEC_ubsec_open *p_UBSEC_ubsec_open = NULL;
299static t_UBSEC_ubsec_close *p_UBSEC_ubsec_close = NULL;
300#ifndef OPENSSL_NO_DH
301static t_UBSEC_diffie_hellman_generate_ioctl
302	*p_UBSEC_diffie_hellman_generate_ioctl = NULL;
303static t_UBSEC_diffie_hellman_agree_ioctl *p_UBSEC_diffie_hellman_agree_ioctl = NULL;
304#endif
305/* #ifndef OPENSSL_NO_RSA */
306static t_UBSEC_rsa_mod_exp_ioctl *p_UBSEC_rsa_mod_exp_ioctl = NULL;
307static t_UBSEC_rsa_mod_exp_crt_ioctl *p_UBSEC_rsa_mod_exp_crt_ioctl = NULL;
308/* #endif */
309#ifndef OPENSSL_NO_DSA
310static t_UBSEC_dsa_sign_ioctl *p_UBSEC_dsa_sign_ioctl = NULL;
311static t_UBSEC_dsa_verify_ioctl *p_UBSEC_dsa_verify_ioctl = NULL;
312#endif
313static t_UBSEC_math_accelerate_ioctl *p_UBSEC_math_accelerate_ioctl = NULL;
314static t_UBSEC_rng_ioctl *p_UBSEC_rng_ioctl = NULL;
315static t_UBSEC_max_key_len_ioctl *p_UBSEC_max_key_len_ioctl = NULL;
316
317static int max_key_len = 1024;  /* ??? */
318
319/*
320 * These are the static string constants for the DSO file name and the function
321 * symbol names to bind to.
322 */
323
324static const char *UBSEC_LIBNAME = NULL;
325static const char *get_UBSEC_LIBNAME(void)
326	{
327	if(UBSEC_LIBNAME)
328		return UBSEC_LIBNAME;
329	return "ubsec";
330	}
331static void free_UBSEC_LIBNAME(void)
332	{
333	if(UBSEC_LIBNAME)
334		OPENSSL_free((void*)UBSEC_LIBNAME);
335	UBSEC_LIBNAME = NULL;
336	}
337static long set_UBSEC_LIBNAME(const char *name)
338	{
339	free_UBSEC_LIBNAME();
340	return (((UBSEC_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0);
341	}
342static const char *UBSEC_F1 = "ubsec_bytes_to_bits";
343static const char *UBSEC_F2 = "ubsec_bits_to_bytes";
344static const char *UBSEC_F3 = "ubsec_open";
345static const char *UBSEC_F4 = "ubsec_close";
346#ifndef OPENSSL_NO_DH
347static const char *UBSEC_F5 = "diffie_hellman_generate_ioctl";
348static const char *UBSEC_F6 = "diffie_hellman_agree_ioctl";
349#endif
350/* #ifndef OPENSSL_NO_RSA */
351static const char *UBSEC_F7 = "rsa_mod_exp_ioctl";
352static const char *UBSEC_F8 = "rsa_mod_exp_crt_ioctl";
353/* #endif */
354#ifndef OPENSSL_NO_DSA
355static const char *UBSEC_F9 = "dsa_sign_ioctl";
356static const char *UBSEC_F10 = "dsa_verify_ioctl";
357#endif
358static const char *UBSEC_F11 = "math_accelerate_ioctl";
359static const char *UBSEC_F12 = "rng_ioctl";
360static const char *UBSEC_F13 = "ubsec_max_key_len_ioctl";
361
362/* Destructor (complements the "ENGINE_ubsec()" constructor) */
363static int ubsec_destroy(ENGINE *e)
364	{
365	free_UBSEC_LIBNAME();
366	ERR_unload_UBSEC_strings();
367	return 1;
368	}
369
370/* (de)initialisation functions. */
371static int ubsec_init(ENGINE *e)
372	{
373	t_UBSEC_ubsec_bytes_to_bits *p1;
374	t_UBSEC_ubsec_bits_to_bytes *p2;
375	t_UBSEC_ubsec_open *p3;
376	t_UBSEC_ubsec_close *p4;
377#ifndef OPENSSL_NO_DH
378	t_UBSEC_diffie_hellman_generate_ioctl *p5;
379	t_UBSEC_diffie_hellman_agree_ioctl *p6;
380#endif
381/* #ifndef OPENSSL_NO_RSA */
382	t_UBSEC_rsa_mod_exp_ioctl *p7;
383	t_UBSEC_rsa_mod_exp_crt_ioctl *p8;
384/* #endif */
385#ifndef OPENSSL_NO_DSA
386	t_UBSEC_dsa_sign_ioctl *p9;
387	t_UBSEC_dsa_verify_ioctl *p10;
388#endif
389	t_UBSEC_math_accelerate_ioctl *p11;
390	t_UBSEC_rng_ioctl *p12;
391        t_UBSEC_max_key_len_ioctl *p13;
392	int fd = 0;
393
394	if(ubsec_dso != NULL)
395		{
396		UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_ALREADY_LOADED);
397		goto err;
398		}
399	/*
400	 * Attempt to load libubsec.so/ubsec.dll/whatever.
401	 */
402	ubsec_dso = DSO_load(NULL, get_UBSEC_LIBNAME(), NULL, 0);
403	if(ubsec_dso == NULL)
404		{
405		UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_DSO_FAILURE);
406		goto err;
407		}
408
409	if (
410	!(p1 = (t_UBSEC_ubsec_bytes_to_bits *) DSO_bind_func(ubsec_dso, UBSEC_F1)) ||
411	!(p2 = (t_UBSEC_ubsec_bits_to_bytes *) DSO_bind_func(ubsec_dso, UBSEC_F2)) ||
412	!(p3 = (t_UBSEC_ubsec_open *) DSO_bind_func(ubsec_dso, UBSEC_F3)) ||
413	!(p4 = (t_UBSEC_ubsec_close *) DSO_bind_func(ubsec_dso, UBSEC_F4)) ||
414#ifndef OPENSSL_NO_DH
415	!(p5 = (t_UBSEC_diffie_hellman_generate_ioctl *)
416				DSO_bind_func(ubsec_dso, UBSEC_F5)) ||
417	!(p6 = (t_UBSEC_diffie_hellman_agree_ioctl *)
418				DSO_bind_func(ubsec_dso, UBSEC_F6)) ||
419#endif
420/* #ifndef OPENSSL_NO_RSA */
421	!(p7 = (t_UBSEC_rsa_mod_exp_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F7)) ||
422	!(p8 = (t_UBSEC_rsa_mod_exp_crt_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F8)) ||
423/* #endif */
424#ifndef OPENSSL_NO_DSA
425	!(p9 = (t_UBSEC_dsa_sign_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F9)) ||
426	!(p10 = (t_UBSEC_dsa_verify_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F10)) ||
427#endif
428	!(p11 = (t_UBSEC_math_accelerate_ioctl *)
429				DSO_bind_func(ubsec_dso, UBSEC_F11)) ||
430	!(p12 = (t_UBSEC_rng_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F12)) ||
431        !(p13 = (t_UBSEC_max_key_len_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F13)))
432		{
433		UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_DSO_FAILURE);
434		goto err;
435		}
436
437	/* Copy the pointers */
438	p_UBSEC_ubsec_bytes_to_bits = p1;
439	p_UBSEC_ubsec_bits_to_bytes = p2;
440	p_UBSEC_ubsec_open = p3;
441	p_UBSEC_ubsec_close = p4;
442#ifndef OPENSSL_NO_DH
443	p_UBSEC_diffie_hellman_generate_ioctl = p5;
444	p_UBSEC_diffie_hellman_agree_ioctl = p6;
445#endif
446#ifndef OPENSSL_NO_RSA
447	p_UBSEC_rsa_mod_exp_ioctl = p7;
448	p_UBSEC_rsa_mod_exp_crt_ioctl = p8;
449#endif
450#ifndef OPENSSL_NO_DSA
451	p_UBSEC_dsa_sign_ioctl = p9;
452	p_UBSEC_dsa_verify_ioctl = p10;
453#endif
454	p_UBSEC_math_accelerate_ioctl = p11;
455	p_UBSEC_rng_ioctl = p12;
456        p_UBSEC_max_key_len_ioctl = p13;
457
458	/* Perform an open to see if there's actually any unit running. */
459	if (((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) > 0) && (p_UBSEC_max_key_len_ioctl(fd, &max_key_len) == 0))
460	{
461	   p_UBSEC_ubsec_close(fd);
462	   return 1;
463	}
464	else
465	{
466	  UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_UNIT_FAILURE);
467	}
468
469err:
470	if(ubsec_dso)
471		DSO_free(ubsec_dso);
472	ubsec_dso = NULL;
473	p_UBSEC_ubsec_bytes_to_bits = NULL;
474	p_UBSEC_ubsec_bits_to_bytes = NULL;
475	p_UBSEC_ubsec_open = NULL;
476	p_UBSEC_ubsec_close = NULL;
477#ifndef OPENSSL_NO_DH
478	p_UBSEC_diffie_hellman_generate_ioctl = NULL;
479	p_UBSEC_diffie_hellman_agree_ioctl = NULL;
480#endif
481#ifndef OPENSSL_NO_RSA
482	p_UBSEC_rsa_mod_exp_ioctl = NULL;
483	p_UBSEC_rsa_mod_exp_crt_ioctl = NULL;
484#endif
485#ifndef OPENSSL_NO_DSA
486	p_UBSEC_dsa_sign_ioctl = NULL;
487	p_UBSEC_dsa_verify_ioctl = NULL;
488#endif
489	p_UBSEC_math_accelerate_ioctl = NULL;
490	p_UBSEC_rng_ioctl = NULL;
491        p_UBSEC_max_key_len_ioctl = NULL;
492
493	return 0;
494	}
495
496static int ubsec_finish(ENGINE *e)
497	{
498	free_UBSEC_LIBNAME();
499	if(ubsec_dso == NULL)
500		{
501		UBSECerr(UBSEC_F_UBSEC_FINISH, UBSEC_R_NOT_LOADED);
502		return 0;
503		}
504	if(!DSO_free(ubsec_dso))
505		{
506		UBSECerr(UBSEC_F_UBSEC_FINISH, UBSEC_R_DSO_FAILURE);
507		return 0;
508		}
509	ubsec_dso = NULL;
510	p_UBSEC_ubsec_bytes_to_bits = NULL;
511	p_UBSEC_ubsec_bits_to_bytes = NULL;
512	p_UBSEC_ubsec_open = NULL;
513	p_UBSEC_ubsec_close = NULL;
514#ifndef OPENSSL_NO_DH
515	p_UBSEC_diffie_hellman_generate_ioctl = NULL;
516	p_UBSEC_diffie_hellman_agree_ioctl = NULL;
517#endif
518#ifndef OPENSSL_NO_RSA
519	p_UBSEC_rsa_mod_exp_ioctl = NULL;
520	p_UBSEC_rsa_mod_exp_crt_ioctl = NULL;
521#endif
522#ifndef OPENSSL_NO_DSA
523	p_UBSEC_dsa_sign_ioctl = NULL;
524	p_UBSEC_dsa_verify_ioctl = NULL;
525#endif
526	p_UBSEC_math_accelerate_ioctl = NULL;
527	p_UBSEC_rng_ioctl = NULL;
528        p_UBSEC_max_key_len_ioctl = NULL;
529	return 1;
530	}
531
532static int ubsec_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
533	{
534	int initialised = ((ubsec_dso == NULL) ? 0 : 1);
535	switch(cmd)
536		{
537	case UBSEC_CMD_SO_PATH:
538		if(p == NULL)
539			{
540			UBSECerr(UBSEC_F_UBSEC_CTRL,ERR_R_PASSED_NULL_PARAMETER);
541			return 0;
542			}
543		if(initialised)
544			{
545			UBSECerr(UBSEC_F_UBSEC_CTRL,UBSEC_R_ALREADY_LOADED);
546			return 0;
547			}
548		return set_UBSEC_LIBNAME((const char *)p);
549	default:
550		break;
551		}
552	UBSECerr(UBSEC_F_UBSEC_CTRL,UBSEC_R_CTRL_COMMAND_NOT_IMPLEMENTED);
553	return 0;
554	}
555
556static int ubsec_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
557		const BIGNUM *m, BN_CTX *ctx)
558	{
559	int 	y_len = 0;
560	int 	fd;
561
562	if(ubsec_dso == NULL)
563	{
564		UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_NOT_LOADED);
565		return 0;
566	}
567
568	/* Check if hardware can't handle this argument. */
569	y_len = BN_num_bits(m);
570	if (y_len > max_key_len) {
571		UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
572                return BN_mod_exp(r, a, p, m, ctx);
573	}
574
575	if(!bn_wexpand(r, m->top))
576	{
577		UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_BN_EXPAND_FAIL);
578		return 0;
579	}
580
581	if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) {
582		fd = 0;
583		UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_UNIT_FAILURE);
584                return BN_mod_exp(r, a, p, m, ctx);
585	}
586
587	if (p_UBSEC_rsa_mod_exp_ioctl(fd, (unsigned char *)a->d, BN_num_bits(a),
588		(unsigned char *)m->d, BN_num_bits(m), (unsigned char *)p->d,
589		BN_num_bits(p), (unsigned char *)r->d, &y_len) != 0)
590	{
591		UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_REQUEST_FAILED);
592                p_UBSEC_ubsec_close(fd);
593
594                return BN_mod_exp(r, a, p, m, ctx);
595	}
596
597	p_UBSEC_ubsec_close(fd);
598
599	r->top = (BN_num_bits(m)+BN_BITS2-1)/BN_BITS2;
600	return 1;
601	}
602
603#ifndef OPENSSL_NO_RSA
604static int ubsec_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
605	{
606	int to_return = 0;
607
608	if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
609		{
610		UBSECerr(UBSEC_F_UBSEC_RSA_MOD_EXP, UBSEC_R_MISSING_KEY_COMPONENTS);
611		goto err;
612		}
613
614	to_return = ubsec_mod_exp_crt(r0, I, rsa->p, rsa->q, rsa->dmp1,
615		    rsa->dmq1, rsa->iqmp, ctx);
616	if (to_return == FAIL_TO_SOFTWARE)
617	{
618	  /*
619	   * Do in software as hardware failed.
620	   */
621	   const RSA_METHOD *meth = RSA_PKCS1_SSLeay();
622	   to_return = (*meth->rsa_mod_exp)(r0, I, rsa, ctx);
623	}
624err:
625	return to_return;
626	}
627#endif
628
629static int ubsec_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
630			const BIGNUM *q, const BIGNUM *dp,
631			const BIGNUM *dq, const BIGNUM *qinv, BN_CTX *ctx)
632	{
633	int	y_len,
634		fd;
635
636	y_len = BN_num_bits(p) + BN_num_bits(q);
637
638	/* Check if hardware can't handle this argument. */
639	if (y_len > max_key_len) {
640		UBSECerr(UBSEC_F_UBSEC_MOD_EXP_CRT, UBSEC_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
641		return FAIL_TO_SOFTWARE;
642	}
643
644	if (!bn_wexpand(r, p->top + q->top + 1)) {
645		UBSECerr(UBSEC_F_UBSEC_MOD_EXP_CRT, UBSEC_R_BN_EXPAND_FAIL);
646		return 0;
647	}
648
649	if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) {
650		fd = 0;
651		UBSECerr(UBSEC_F_UBSEC_MOD_EXP_CRT, UBSEC_R_UNIT_FAILURE);
652		return FAIL_TO_SOFTWARE;
653	}
654
655	if (p_UBSEC_rsa_mod_exp_crt_ioctl(fd,
656		(unsigned char *)a->d, BN_num_bits(a),
657		(unsigned char *)qinv->d, BN_num_bits(qinv),
658		(unsigned char *)dp->d, BN_num_bits(dp),
659		(unsigned char *)p->d, BN_num_bits(p),
660		(unsigned char *)dq->d, BN_num_bits(dq),
661		(unsigned char *)q->d, BN_num_bits(q),
662		(unsigned char *)r->d,  &y_len) != 0) {
663		UBSECerr(UBSEC_F_UBSEC_MOD_EXP_CRT, UBSEC_R_REQUEST_FAILED);
664                p_UBSEC_ubsec_close(fd);
665		return FAIL_TO_SOFTWARE;
666	}
667
668	p_UBSEC_ubsec_close(fd);
669
670	r->top = (BN_num_bits(p) + BN_num_bits(q) + BN_BITS2 - 1)/BN_BITS2;
671	return 1;
672}
673
674#ifndef OPENSSL_NO_DSA
675#ifdef NOT_USED
676static int ubsec_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1,
677		BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m,
678		BN_CTX *ctx, BN_MONT_CTX *in_mont)
679	{
680	BIGNUM t;
681	int to_return = 0;
682
683	BN_init(&t);
684	/* let rr = a1 ^ p1 mod m */
685	if (!ubsec_mod_exp(rr,a1,p1,m,ctx)) goto end;
686	/* let t = a2 ^ p2 mod m */
687	if (!ubsec_mod_exp(&t,a2,p2,m,ctx)) goto end;
688	/* let rr = rr * t mod m */
689	if (!BN_mod_mul(rr,rr,&t,m,ctx)) goto end;
690	to_return = 1;
691end:
692	BN_free(&t);
693	return to_return;
694	}
695
696static int ubsec_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a,
697		const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
698		BN_MONT_CTX *m_ctx)
699	{
700	return ubsec_mod_exp(r, a, p, m, ctx);
701	}
702#endif
703#endif
704
705/*
706 * This function is aliased to mod_exp (with the mont stuff dropped).
707 */
708static int ubsec_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
709		const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
710        {
711	int ret = 0;
712
713#ifndef OPENSSL_NO_RSA
714 	/* Do in software if the key is too large for the hardware. */
715	if (BN_num_bits(m) > max_key_len)
716                {
717		const RSA_METHOD *meth = RSA_PKCS1_SSLeay();
718		ret = (*meth->bn_mod_exp)(r, a, p, m, ctx, m_ctx);
719                }
720        else
721#endif
722                {
723		ret = ubsec_mod_exp(r, a, p, m, ctx);
724                }
725
726	return ret;
727        }
728
729#ifndef OPENSSL_NO_DH
730/* This function is aliased to mod_exp (with the dh and mont dropped). */
731static int ubsec_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a,
732		const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
733		BN_MONT_CTX *m_ctx)
734	{
735	return ubsec_mod_exp(r, a, p, m, ctx);
736	}
737#endif
738
739#ifndef OPENSSL_NO_DSA
740static DSA_SIG *ubsec_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
741	{
742	DSA_SIG *to_return = NULL;
743	int s_len = 160, r_len = 160, d_len, fd;
744	BIGNUM m, *r=NULL, *s=NULL;
745
746	BN_init(&m);
747
748	s = BN_new();
749	r = BN_new();
750	if ((s == NULL) || (r==NULL))
751		goto err;
752
753	d_len = p_UBSEC_ubsec_bytes_to_bits((unsigned char *)dgst, dlen);
754
755        if(!bn_wexpand(r, (160+BN_BITS2-1)/BN_BITS2) ||
756       	   (!bn_wexpand(s, (160+BN_BITS2-1)/BN_BITS2))) {
757		UBSECerr(UBSEC_F_UBSEC_DSA_DO_SIGN, UBSEC_R_BN_EXPAND_FAIL);
758		goto err;
759	}
760
761	if (BN_bin2bn(dgst,dlen,&m) == NULL) {
762		UBSECerr(UBSEC_F_UBSEC_DSA_DO_SIGN, UBSEC_R_BN_EXPAND_FAIL);
763		goto err;
764	}
765
766	if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) {
767                const DSA_METHOD *meth;
768		fd = 0;
769		UBSECerr(UBSEC_F_UBSEC_DSA_DO_SIGN, UBSEC_R_UNIT_FAILURE);
770                meth = DSA_OpenSSL();
771                to_return =  meth->dsa_do_sign(dgst, dlen, dsa);
772		goto err;
773	}
774
775	if (p_UBSEC_dsa_sign_ioctl(fd, 0, /* compute hash before signing */
776		(unsigned char *)dgst, d_len,
777		NULL, 0,  /* compute random value */
778		(unsigned char *)dsa->p->d, BN_num_bits(dsa->p),
779		(unsigned char *)dsa->q->d, BN_num_bits(dsa->q),
780		(unsigned char *)dsa->g->d, BN_num_bits(dsa->g),
781		(unsigned char *)dsa->priv_key->d, BN_num_bits(dsa->priv_key),
782		(unsigned char *)r->d, &r_len,
783		(unsigned char *)s->d, &s_len ) != 0) {
784                const DSA_METHOD *meth;
785
786		UBSECerr(UBSEC_F_UBSEC_DSA_DO_SIGN, UBSEC_R_REQUEST_FAILED);
787                p_UBSEC_ubsec_close(fd);
788                meth = DSA_OpenSSL();
789                to_return = meth->dsa_do_sign(dgst, dlen, dsa);
790
791		goto err;
792	}
793
794	p_UBSEC_ubsec_close(fd);
795
796	r->top = (160+BN_BITS2-1)/BN_BITS2;
797	s->top = (160+BN_BITS2-1)/BN_BITS2;
798
799	to_return = DSA_SIG_new();
800	if(to_return == NULL) {
801		UBSECerr(UBSEC_F_UBSEC_DSA_DO_SIGN, UBSEC_R_BN_EXPAND_FAIL);
802		goto err;
803	}
804
805	to_return->r = r;
806	to_return->s = s;
807
808err:
809	if (!to_return) {
810		if (r) BN_free(r);
811		if (s) BN_free(s);
812	}
813	BN_clear_free(&m);
814	return to_return;
815}
816
817static int ubsec_dsa_verify(const unsigned char *dgst, int dgst_len,
818                                DSA_SIG *sig, DSA *dsa)
819	{
820	int v_len, d_len;
821	int to_return = 0;
822	int fd;
823	BIGNUM v, *pv = &v;
824
825	BN_init(&v);
826
827	if(!bn_wexpand(pv, dsa->p->top)) {
828		UBSECerr(UBSEC_F_UBSEC_DSA_VERIFY, UBSEC_R_BN_EXPAND_FAIL);
829		goto err;
830	}
831
832	v_len = BN_num_bits(dsa->p);
833
834	d_len = p_UBSEC_ubsec_bytes_to_bits((unsigned char *)dgst, dgst_len);
835
836	if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) {
837                const DSA_METHOD *meth;
838		fd = 0;
839		UBSECerr(UBSEC_F_UBSEC_DSA_VERIFY, UBSEC_R_UNIT_FAILURE);
840                meth = DSA_OpenSSL();
841                to_return = meth->dsa_do_verify(dgst, dgst_len, sig, dsa);
842		goto err;
843	}
844
845	if (p_UBSEC_dsa_verify_ioctl(fd, 0, /* compute hash before signing */
846		(unsigned char *)dgst, d_len,
847		(unsigned char *)dsa->p->d, BN_num_bits(dsa->p),
848		(unsigned char *)dsa->q->d, BN_num_bits(dsa->q),
849		(unsigned char *)dsa->g->d, BN_num_bits(dsa->g),
850		(unsigned char *)dsa->pub_key->d, BN_num_bits(dsa->pub_key),
851		(unsigned char *)sig->r->d, BN_num_bits(sig->r),
852		(unsigned char *)sig->s->d, BN_num_bits(sig->s),
853		(unsigned char *)v.d, &v_len) != 0) {
854                const DSA_METHOD *meth;
855		UBSECerr(UBSEC_F_UBSEC_DSA_VERIFY, UBSEC_R_REQUEST_FAILED);
856                p_UBSEC_ubsec_close(fd);
857
858                meth = DSA_OpenSSL();
859                to_return = meth->dsa_do_verify(dgst, dgst_len, sig, dsa);
860
861		goto err;
862	}
863
864	p_UBSEC_ubsec_close(fd);
865
866	to_return = 1;
867err:
868	BN_clear_free(&v);
869	return to_return;
870	}
871#endif
872
873#ifndef OPENSSL_NO_DH
874static int ubsec_dh_compute_key(unsigned char *key,const BIGNUM *pub_key,DH *dh)
875        {
876        int      ret      = -1,
877                 k_len,
878                 fd;
879
880        k_len = BN_num_bits(dh->p);
881
882        if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0)
883                {
884                const DH_METHOD *meth;
885                UBSECerr(UBSEC_F_UBSEC_DH_COMPUTE_KEY, UBSEC_R_UNIT_FAILURE);
886                meth = DH_OpenSSL();
887                ret = meth->compute_key(key, pub_key, dh);
888                goto err;
889                }
890
891        if (p_UBSEC_diffie_hellman_agree_ioctl(fd,
892                                               (unsigned char *)dh->priv_key->d, BN_num_bits(dh->priv_key),
893                                               (unsigned char *)pub_key->d, BN_num_bits(pub_key),
894                                               (unsigned char *)dh->p->d, BN_num_bits(dh->p),
895                                               key, &k_len) != 0)
896                {
897                /* Hardware's a no go, failover to software */
898                const DH_METHOD *meth;
899                UBSECerr(UBSEC_F_UBSEC_DH_COMPUTE_KEY, UBSEC_R_REQUEST_FAILED);
900                p_UBSEC_ubsec_close(fd);
901
902                meth = DH_OpenSSL();
903                ret = meth->compute_key(key, pub_key, dh);
904
905                goto err;
906                }
907
908        p_UBSEC_ubsec_close(fd);
909
910        ret = p_UBSEC_ubsec_bits_to_bytes(k_len);
911err:
912        return ret;
913        }
914
915static int ubsec_dh_generate_key(DH *dh)
916        {
917        int      ret               = 0,
918                 random_bits       = 0,
919                 pub_key_len       = 0,
920                 priv_key_len      = 0,
921                 fd;
922        BIGNUM   *pub_key          = NULL;
923        BIGNUM   *priv_key         = NULL;
924
925        /*
926         *  How many bits should Random x be? dh_key.c
927         *  sets the range from 0 to num_bits(modulus) ???
928         */
929
930        if (dh->priv_key == NULL)
931                {
932                priv_key = BN_new();
933                if (priv_key == NULL) goto err;
934                priv_key_len = BN_num_bits(dh->p);
935                if(bn_wexpand(priv_key, dh->p->top) == NULL) goto err;
936                do
937                        if (!BN_rand_range(priv_key, dh->p)) goto err;
938                while (BN_is_zero(priv_key));
939                random_bits = BN_num_bits(priv_key);
940                }
941        else
942                {
943                priv_key = dh->priv_key;
944                }
945
946        if (dh->pub_key == NULL)
947                {
948                pub_key = BN_new();
949                pub_key_len = BN_num_bits(dh->p);
950                if(bn_wexpand(pub_key, dh->p->top) == NULL) goto err;
951                if(pub_key == NULL) goto err;
952                }
953        else
954                {
955                pub_key = dh->pub_key;
956                }
957
958        if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0)
959                {
960                const DH_METHOD *meth;
961                UBSECerr(UBSEC_F_UBSEC_DH_GENERATE_KEY, UBSEC_R_UNIT_FAILURE);
962                meth = DH_OpenSSL();
963                ret = meth->generate_key(dh);
964                goto err;
965                }
966
967        if (p_UBSEC_diffie_hellman_generate_ioctl(fd,
968                                                  (unsigned char *)priv_key->d, &priv_key_len,
969                                                  (unsigned char *)pub_key->d,  &pub_key_len,
970                                                  (unsigned char *)dh->g->d, BN_num_bits(dh->g),
971                                                  (unsigned char *)dh->p->d, BN_num_bits(dh->p),
972                                                  0, 0, random_bits) != 0)
973                {
974                /* Hardware's a no go, failover to software */
975                const DH_METHOD *meth;
976
977                UBSECerr(UBSEC_F_UBSEC_DH_GENERATE_KEY, UBSEC_R_REQUEST_FAILED);
978                p_UBSEC_ubsec_close(fd);
979
980                meth = DH_OpenSSL();
981                ret = meth->generate_key(dh);
982
983                goto err;
984                }
985
986        p_UBSEC_ubsec_close(fd);
987
988        dh->pub_key = pub_key;
989        dh->pub_key->top = (pub_key_len + BN_BITS2-1) / BN_BITS2;
990        dh->priv_key = priv_key;
991        dh->priv_key->top = (priv_key_len + BN_BITS2-1) / BN_BITS2;
992
993        ret = 1;
994err:
995        return ret;
996        }
997#endif
998
999#ifdef NOT_USED
1000static int ubsec_rand_bytes(unsigned char * buf,
1001                            int num)
1002        {
1003        int      ret      = 0,
1004                 fd;
1005
1006        if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0)
1007                {
1008                const RAND_METHOD *meth;
1009                UBSECerr(UBSEC_F_UBSEC_RAND_BYTES, UBSEC_R_UNIT_FAILURE);
1010                num = p_UBSEC_ubsec_bits_to_bytes(num);
1011                meth = RAND_SSLeay();
1012                meth->seed(buf, num);
1013                ret = meth->bytes(buf, num);
1014                goto err;
1015                }
1016
1017        num *= 8; /* bytes to bits */
1018
1019        if (p_UBSEC_rng_ioctl(fd,
1020                              UBSEC_RNG_DIRECT,
1021                              buf,
1022                              &num) != 0)
1023                {
1024                /* Hardware's a no go, failover to software */
1025                const RAND_METHOD *meth;
1026
1027                UBSECerr(UBSEC_F_UBSEC_RAND_BYTES, UBSEC_R_REQUEST_FAILED);
1028                p_UBSEC_ubsec_close(fd);
1029
1030                num = p_UBSEC_ubsec_bits_to_bytes(num);
1031                meth = RAND_SSLeay();
1032                meth->seed(buf, num);
1033                ret = meth->bytes(buf, num);
1034
1035                goto err;
1036                }
1037
1038        p_UBSEC_ubsec_close(fd);
1039
1040        ret = 1;
1041err:
1042        return(ret);
1043        }
1044
1045
1046static int ubsec_rand_status(void)
1047	{
1048	return 0;
1049	}
1050#endif
1051
1052/* This stuff is needed if this ENGINE is being compiled into a self-contained
1053 * shared-library. */
1054#ifndef OPENSSL_NO_DYNAMIC_ENGINE
1055static int bind_fn(ENGINE *e, const char *id)
1056	{
1057	if(id && (strcmp(id, engine_ubsec_id) != 0))
1058		return 0;
1059	if(!bind_helper(e))
1060		return 0;
1061	return 1;
1062	}
1063IMPLEMENT_DYNAMIC_CHECK_FN()
1064IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
1065#endif /* OPENSSL_NO_DYNAMIC_ENGINE */
1066
1067#endif /* !OPENSSL_NO_HW_UBSEC */
1068#endif /* !OPENSSL_NO_HW */
1069