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