f8f1d4127c299052aa35243f7ae181da47d74072
[openssl.git] / crypto / engine / hw_ubsec.c
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 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 <openssl/crypto.h>
63 #include "cryptlib.h"
64 #include <openssl/dso.h>
65 #include <openssl/engine.h>
66
67 #ifndef OPENSSL_NO_HW
68 #ifndef OPENSSL_NO_HW_UBSEC
69
70 #ifdef FLAT_INC
71 #include "hw_ubsec.h"
72 #else
73 #include "vendor_defns/hw_ubsec.h"
74 #endif
75
76 static int ubsec_init(ENGINE *e);
77 static int ubsec_finish(ENGINE *e);
78 static int ubsec_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)());
79 static int ubsec_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
80                 const BIGNUM *m, BN_CTX *ctx);
81 static int ubsec_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
82                         const BIGNUM *q, const BIGNUM *dp,
83                         const BIGNUM *dq, const BIGNUM *qinv, BN_CTX *ctx);
84 #ifndef OPENSSL_NO_RSA
85 static int ubsec_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa);
86 #endif
87 static int ubsec_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
88                 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
89 #ifndef OPENSSL_NO_DSA
90 #if NOT_USED
91 static int ubsec_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1,
92                 BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m,
93                 BN_CTX *ctx, BN_MONT_CTX *in_mont);
94 static int ubsec_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a,
95                 const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
96                 BN_MONT_CTX *m_ctx);
97 #endif
98 static DSA_SIG *ubsec_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa);
99 static int ubsec_dsa_verify(const unsigned char *dgst, int dgst_len,
100                                 DSA_SIG *sig, DSA *dsa);
101 #endif
102 #ifndef OPENSSL_NO_DH
103 static int ubsec_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a,
104                 const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
105                 BN_MONT_CTX *m_ctx);
106 static int ubsec_dh_compute_key(unsigned char *key,const BIGNUM *pub_key,DH *dh);
107 static int ubsec_dh_generate_key(DH *dh);
108 #endif
109
110 #if NOT_USED
111 static int ubsec_rand_bytes(unsigned char *buf, int num);
112 static int ubsec_rand_status(void);
113 #endif
114
115 #define UBSEC_CMD_SO_PATH               ENGINE_CMD_BASE
116 static const ENGINE_CMD_DEFN ubsec_cmd_defns[] = {
117         {UBSEC_CMD_SO_PATH,
118                 "SO_PATH",
119                 "Specifies the path to the 'ubsec' shared library",
120                 ENGINE_CMD_FLAG_STRING},
121         {0, NULL, NULL, 0}
122         };
123
124 #ifndef OPENSSL_NO_RSA
125 /* Our internal RSA_METHOD that we provide pointers to */
126 static RSA_METHOD ubsec_rsa =
127         {
128         "UBSEC RSA method",
129         NULL,
130         NULL,
131         NULL,
132         NULL,
133         ubsec_rsa_mod_exp,
134         ubsec_mod_exp_mont,
135         NULL,
136         NULL,
137         0,
138         NULL,
139         NULL,
140         NULL
141         };
142 #endif
143
144 #ifndef OPENSSL_NO_DSA
145 /* Our internal DSA_METHOD that we provide pointers to */
146 static DSA_METHOD ubsec_dsa =
147         {
148         "UBSEC DSA method",
149         ubsec_dsa_do_sign, /* dsa_do_sign */
150         NULL, /* dsa_sign_setup */
151         ubsec_dsa_verify, /* dsa_do_verify */
152         NULL, /* ubsec_dsa_mod_exp */ /* dsa_mod_exp */
153         NULL, /* ubsec_mod_exp_dsa */ /* bn_mod_exp */
154         NULL, /* init */
155         NULL, /* finish */
156         0, /* flags */
157         NULL /* app_data */
158         };
159 #endif
160
161 #ifndef OPENSSL_NO_DH
162 /* Our internal DH_METHOD that we provide pointers to */
163 static DH_METHOD ubsec_dh =
164         {
165         "UBSEC DH method",
166         ubsec_dh_generate_key,
167         ubsec_dh_compute_key,
168         ubsec_mod_exp_dh,
169         NULL,
170         NULL,
171         0,
172         NULL
173         };
174 #endif
175
176 /* Constants used when creating the ENGINE */
177 static const char *engine_ubsec_id = "ubsec";
178 static const char *engine_ubsec_name = "UBSEC hardware engine support";
179
180 /* As this is only ever called once, there's no need for locking
181  * (indeed - the lock will already be held by our caller!!!) */
182 ENGINE *ENGINE_ubsec()
183         {
184 #ifndef OPENSSL_NO_RSA
185         const RSA_METHOD *meth1;
186 #endif
187 #ifndef OPENSSL_NO_DH
188 #ifndef HAVE_UBSEC_DH
189         const DH_METHOD *meth3;
190 #endif /* HAVE_UBSEC_DH */
191 #endif
192         ENGINE *ret = ENGINE_new();
193         if(!ret)
194                 return NULL;
195         if(!ENGINE_set_id(ret, engine_ubsec_id) ||
196                         !ENGINE_set_name(ret, engine_ubsec_name) ||
197 #ifndef OPENSSL_NO_RSA
198                         !ENGINE_set_RSA(ret, &ubsec_rsa) ||
199 #endif
200 #ifndef OPENSSL_NO_DSA
201                         !ENGINE_set_DSA(ret, &ubsec_dsa) ||
202 #endif
203 #ifndef OPENSSL_NO_DH
204                         !ENGINE_set_DH(ret, &ubsec_dh) ||
205 #endif
206                         !ENGINE_set_BN_mod_exp(ret, ubsec_mod_exp) ||
207                         !ENGINE_set_BN_mod_exp_crt(ret, ubsec_mod_exp_crt) ||
208                         !ENGINE_set_init_function(ret, ubsec_init) ||
209                         !ENGINE_set_finish_function(ret, ubsec_finish) ||
210                         !ENGINE_set_ctrl_function(ret, ubsec_ctrl) ||
211                         !ENGINE_set_cmd_defns(ret, ubsec_cmd_defns))
212                 {
213                 ENGINE_free(ret);
214                 return NULL;
215                 }
216
217 #ifndef OPENSSL_NO_RSA
218         /* We know that the "PKCS1_SSLeay()" functions hook properly
219          * to the Broadcom-specific mod_exp and mod_exp_crt so we use
220          * those functions. NB: We don't use ENGINE_openssl() or
221          * anything "more generic" because something like the RSAref
222          * code may not hook properly, and if you own one of these
223          * cards then you have the right to do RSA operations on it
224          * anyway! */ 
225         meth1 = RSA_PKCS1_SSLeay();
226         ubsec_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
227         ubsec_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
228         ubsec_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
229         ubsec_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
230 #endif
231
232 #ifndef OPENSSL_NO_DH
233 #ifndef HAVE_UBSEC_DH
234         /* Much the same for Diffie-Hellman */
235         meth3 = DH_OpenSSL();
236         ubsec_dh.generate_key = meth3->generate_key;
237         ubsec_dh.compute_key = meth3->compute_key;
238 #endif /* HAVE_UBSEC_DH */
239 #endif
240
241         return ret;
242         }
243
244 /* This is a process-global DSO handle used for loading and unloading
245  * the UBSEC library. NB: This is only set (or unset) during an
246  * init() or finish() call (reference counts permitting) and they're
247  * operating with global locks, so this should be thread-safe
248  * implicitly. */
249
250 static DSO *ubsec_dso = NULL;
251
252 /* These are the function pointers that are (un)set when the library has
253  * successfully (un)loaded. */
254
255 static t_UBSEC_ubsec_bytes_to_bits *p_UBSEC_ubsec_bytes_to_bits = NULL;
256 static t_UBSEC_ubsec_bits_to_bytes *p_UBSEC_ubsec_bits_to_bytes = NULL;
257 static t_UBSEC_ubsec_open *p_UBSEC_ubsec_open = NULL;
258 static t_UBSEC_ubsec_close *p_UBSEC_ubsec_close = NULL;
259 #ifndef OPENSSL_NO_DH
260 static t_UBSEC_diffie_hellman_generate_ioctl 
261         *p_UBSEC_diffie_hellman_generate_ioctl = NULL;
262 static t_UBSEC_diffie_hellman_agree_ioctl *p_UBSEC_diffie_hellman_agree_ioctl = NULL;
263 #endif
264 /* #ifndef OPENSSL_NO_RSA */
265 static t_UBSEC_rsa_mod_exp_ioctl *p_UBSEC_rsa_mod_exp_ioctl = NULL;
266 static t_UBSEC_rsa_mod_exp_crt_ioctl *p_UBSEC_rsa_mod_exp_crt_ioctl = NULL;
267 /* #endif */
268 #ifndef OPENSSL_NO_DSA
269 static t_UBSEC_dsa_sign_ioctl *p_UBSEC_dsa_sign_ioctl = NULL;
270 static t_UBSEC_dsa_verify_ioctl *p_UBSEC_dsa_verify_ioctl = NULL;
271 #endif
272 static t_UBSEC_math_accelerate_ioctl *p_UBSEC_math_accelerate_ioctl = NULL;
273 static t_UBSEC_rng_ioctl *p_UBSEC_rng_ioctl = NULL;
274
275 /* 
276  * These are the static string constants for the DSO file name and the function
277  * symbol names to bind to. 
278  */
279
280 static const char *UBSEC_LIBNAME = "ubsec";
281 static const char *UBSEC_F1 = "ubsec_bytes_to_bits";
282 static const char *UBSEC_F2 = "ubsec_bits_to_bytes";
283 static const char *UBSEC_F3 = "ubsec_open";
284 static const char *UBSEC_F4 = "ubsec_close";
285 #ifndef OPENSSL_NO_DH
286 static const char *UBSEC_F5 = "diffie_hellman_generate_ioctl";
287 static const char *UBSEC_F6 = "diffie_hellman_agree_ioctl";
288 #endif
289 /* #ifndef OPENSSL_NO_RSA */
290 static const char *UBSEC_F7 = "rsa_mod_exp_ioctl";
291 static const char *UBSEC_F8 = "rsa_mod_exp_crt_ioctl";
292 /* #endif */
293 #ifndef OPENSSL_NO_DSA
294 static const char *UBSEC_F9 = "dsa_sign_ioctl";
295 static const char *UBSEC_F10 = "dsa_verify_ioctl";
296 #endif
297 static const char *UBSEC_F11 = "math_accelerate_ioctl";
298 static const char *UBSEC_F12 = "rng_ioctl";
299
300 /* (de)initialisation functions. */
301 static int ubsec_init(ENGINE *e)
302         {
303         t_UBSEC_ubsec_bytes_to_bits *p1;
304         t_UBSEC_ubsec_bits_to_bytes *p2;
305         t_UBSEC_ubsec_open *p3;
306         t_UBSEC_ubsec_close *p4;
307 #ifndef OPENSSL_NO_DH
308         t_UBSEC_diffie_hellman_generate_ioctl *p5;
309         t_UBSEC_diffie_hellman_agree_ioctl *p6;
310 #endif
311 /* #ifndef OPENSSL_NO_RSA */
312         t_UBSEC_rsa_mod_exp_ioctl *p7;
313         t_UBSEC_rsa_mod_exp_crt_ioctl *p8;
314 /* #endif */
315 #ifndef OPENSSL_NO_DSA
316         t_UBSEC_dsa_sign_ioctl *p9;
317         t_UBSEC_dsa_verify_ioctl *p10;
318 #endif
319         t_UBSEC_math_accelerate_ioctl *p11;
320         t_UBSEC_rng_ioctl *p12;
321         int fd = 0;
322
323         if(ubsec_dso != NULL)
324                 {
325                 ENGINEerr(ENGINE_F_UBSEC_INIT, ENGINE_R_ALREADY_LOADED);
326                 goto err;
327                 }
328         /* 
329          * Attempt to load libubsec.so/ubsec.dll/whatever. 
330          */
331         ubsec_dso = DSO_load(NULL, UBSEC_LIBNAME, NULL, 0);
332         if(ubsec_dso == NULL)
333                 {
334                 ENGINEerr(ENGINE_F_UBSEC_INIT, ENGINE_R_DSO_FAILURE);
335                 goto err;
336                 }
337
338         if (
339         !(p1 = (t_UBSEC_ubsec_bytes_to_bits *) DSO_bind_func(ubsec_dso, UBSEC_F1)) ||
340         !(p2 = (t_UBSEC_ubsec_bits_to_bytes *) DSO_bind_func(ubsec_dso, UBSEC_F2)) ||
341         !(p3 = (t_UBSEC_ubsec_open *) DSO_bind_func(ubsec_dso, UBSEC_F3)) ||
342         !(p4 = (t_UBSEC_ubsec_close *) DSO_bind_func(ubsec_dso, UBSEC_F4)) ||
343 #ifndef OPENSSL_NO_DH
344         !(p5 = (t_UBSEC_diffie_hellman_generate_ioctl *) 
345                                 DSO_bind_func(ubsec_dso, UBSEC_F5)) ||
346         !(p6 = (t_UBSEC_diffie_hellman_agree_ioctl *) 
347                                 DSO_bind_func(ubsec_dso, UBSEC_F6)) ||
348 #endif
349 /* #ifndef OPENSSL_NO_RSA */
350         !(p7 = (t_UBSEC_rsa_mod_exp_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F7)) ||
351         !(p8 = (t_UBSEC_rsa_mod_exp_crt_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F8)) ||
352 /* #endif */
353 #ifndef OPENSSL_NO_DSA
354         !(p9 = (t_UBSEC_dsa_sign_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F9)) ||
355         !(p10 = (t_UBSEC_dsa_verify_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F10)) ||
356 #endif
357         !(p11 = (t_UBSEC_math_accelerate_ioctl *) 
358                                 DSO_bind_func(ubsec_dso, UBSEC_F11)) ||
359         !(p12 = (t_UBSEC_rng_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F12)))
360                 {
361                 ENGINEerr(ENGINE_F_UBSEC_INIT, ENGINE_R_DSO_FAILURE);
362                 goto err;
363                 }
364
365         /* Copy the pointers */
366         p_UBSEC_ubsec_bytes_to_bits = p1;
367         p_UBSEC_ubsec_bits_to_bytes = p2;
368         p_UBSEC_ubsec_open = p3;
369         p_UBSEC_ubsec_close = p4;
370 #ifndef OPENSSL_NO_DH
371         p_UBSEC_diffie_hellman_generate_ioctl = p5;
372         p_UBSEC_diffie_hellman_agree_ioctl = p6;
373 #endif
374 #ifndef OPENSSL_NO_RSA
375         p_UBSEC_rsa_mod_exp_ioctl = p7;
376         p_UBSEC_rsa_mod_exp_crt_ioctl = p8;
377 #endif
378 #ifndef OPENSSL_NO_DSA
379         p_UBSEC_dsa_sign_ioctl = p9;
380         p_UBSEC_dsa_verify_ioctl = p10;
381 #endif
382         p_UBSEC_math_accelerate_ioctl = p11;
383         p_UBSEC_rng_ioctl = p12;
384
385         /* Perform an open to see if there's actually any unit running. */
386         if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) > 0)
387                 {
388                 p_UBSEC_ubsec_close(fd);
389                 return 1;
390                 }
391         else
392                 {
393                 ENGINEerr(ENGINE_F_UBSEC_INIT, ENGINE_R_UNIT_FAILURE);
394                 }
395
396 err:
397         if(ubsec_dso)
398                 DSO_free(ubsec_dso);
399         p_UBSEC_ubsec_bytes_to_bits = NULL;
400         p_UBSEC_ubsec_bits_to_bytes = NULL;
401         p_UBSEC_ubsec_open = NULL;
402         p_UBSEC_ubsec_close = NULL;
403 #ifndef OPENSSL_NO_DH
404         p_UBSEC_diffie_hellman_generate_ioctl = NULL;
405         p_UBSEC_diffie_hellman_agree_ioctl = NULL;
406 #endif
407 #ifndef OPENSSL_NO_RSA
408         p_UBSEC_rsa_mod_exp_ioctl = NULL;
409         p_UBSEC_rsa_mod_exp_crt_ioctl = NULL;
410 #endif
411 #ifndef OPENSSL_NO_DSA
412         p_UBSEC_dsa_sign_ioctl = NULL;
413         p_UBSEC_dsa_verify_ioctl = NULL;
414 #endif
415         p_UBSEC_math_accelerate_ioctl = NULL;
416         p_UBSEC_rng_ioctl = NULL;
417
418         return 0;
419         }
420
421 static int ubsec_finish(ENGINE *e)
422         {
423         if(ubsec_dso == NULL)
424                 {
425                 ENGINEerr(ENGINE_F_UBSEC_FINISH, ENGINE_R_NOT_LOADED);
426                 return 0;
427                 }
428         if(!DSO_free(ubsec_dso))
429                 {
430                 ENGINEerr(ENGINE_F_UBSEC_FINISH, ENGINE_R_DSO_FAILURE);
431                 return 0;
432                 }
433         ubsec_dso = NULL;
434         p_UBSEC_ubsec_bytes_to_bits = NULL;
435         p_UBSEC_ubsec_bits_to_bytes = NULL;
436         p_UBSEC_ubsec_open = NULL;
437         p_UBSEC_ubsec_close = NULL;
438 #ifndef OPENSSL_NO_DH
439         p_UBSEC_diffie_hellman_generate_ioctl = NULL;
440         p_UBSEC_diffie_hellman_agree_ioctl = NULL;
441 #endif
442 #ifndef OPENSSL_NO_RSA
443         p_UBSEC_rsa_mod_exp_ioctl = NULL;
444         p_UBSEC_rsa_mod_exp_crt_ioctl = NULL;
445 #endif
446 #ifndef OPENSSL_NO_DSA
447         p_UBSEC_dsa_sign_ioctl = NULL;
448         p_UBSEC_dsa_verify_ioctl = NULL;
449 #endif
450         p_UBSEC_math_accelerate_ioctl = NULL;
451         p_UBSEC_rng_ioctl = NULL;
452         return 1;
453         }
454
455 static int ubsec_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
456         {
457         int initialised = ((ubsec_dso == NULL) ? 0 : 1);
458         switch(cmd)
459                 {
460         case UBSEC_CMD_SO_PATH:
461                 if(p == NULL)
462                         {
463                         ENGINEerr(ENGINE_F_UBSEC_CTRL,ERR_R_PASSED_NULL_PARAMETER);
464                         return 0;
465                         }
466                 if(initialised)
467                         {
468                         ENGINEerr(ENGINE_F_UBSEC_CTRL,ENGINE_R_ALREADY_LOADED);
469                         return 0;
470                         }
471                 UBSEC_LIBNAME = (const char *)p;
472                 return 1;
473         default:
474                 break;
475                 }
476         ENGINEerr(ENGINE_F_UBSEC_CTRL,ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED);
477         return 0;
478         }
479
480 static int ubsec_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
481                 const BIGNUM *m, BN_CTX *ctx)
482         {
483         int     y_len = 0;
484         int     fd;
485
486         if(ubsec_dso == NULL)
487         {
488                 ENGINEerr(ENGINE_F_UBSEC_MOD_EXP, ENGINE_R_NOT_LOADED);
489                 return 0;
490         }
491
492         /* Check if hardware can't handle this argument. */
493         y_len = BN_num_bits(m);
494         if (y_len > 1024) {
495                 ENGINEerr(ENGINE_F_UBSEC_MOD_EXP, ENGINE_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
496                 return 0;
497         } 
498
499         if(!bn_wexpand(r, m->top))
500         {
501                 ENGINEerr(ENGINE_F_UBSEC_MOD_EXP, ENGINE_R_BN_EXPAND_FAIL);
502                 return 0;
503         }
504         memset(r->d, 0, BN_num_bytes(m));
505
506         if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) {
507                 fd = 0;
508                 ENGINEerr(ENGINE_F_UBSEC_INIT, ENGINE_R_UNIT_FAILURE);
509                 return 0;
510         }
511
512         if (p_UBSEC_rsa_mod_exp_ioctl(fd, (unsigned char *)a->d, BN_num_bits(a),
513                 (unsigned char *)m->d, BN_num_bits(m), (unsigned char *)p->d, 
514                 BN_num_bits(p), (unsigned char *)r->d, &y_len) != 0)
515         {
516                 ENGINEerr(ENGINE_F_UBSEC_MOD_EXP, ENGINE_R_REQUEST_FAILED);
517                 return 0;
518         }
519
520         p_UBSEC_ubsec_close(fd);
521
522         r->top = (BN_num_bits(m)+BN_BITS2-1)/BN_BITS2;
523         return 1;
524         }
525
526 #ifndef OPENSSL_NO_RSA
527 static int ubsec_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa)
528         {
529         BN_CTX *ctx;
530         int to_return = 0;
531
532         if((ctx = BN_CTX_new()) == NULL)
533                 goto err;
534
535         if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
536                 {
537                 ENGINEerr(ENGINE_F_UBSEC_RSA_MOD_EXP, ENGINE_R_MISSING_KEY_COMPONENTS);
538                 goto err;
539                 }
540
541         /*
542          * Do in software if argument is too large for hardware.
543          */
544         if ((BN_num_bits(rsa->p)+BN_num_bits(rsa->q)) > 1024) {
545                 const RSA_METHOD *meth = RSA_PKCS1_SSLeay();
546                 to_return = (*meth->rsa_mod_exp)(r0, I, rsa);
547         } else {
548                 to_return = ubsec_mod_exp_crt(r0, I, rsa->p, rsa->q, rsa->dmp1,
549                         rsa->dmq1, rsa->iqmp, ctx);
550         }
551 err:
552         if(ctx)
553                 BN_CTX_free(ctx);
554         return to_return;
555         }
556 #endif
557
558 static int ubsec_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
559                         const BIGNUM *q, const BIGNUM *dp,
560                         const BIGNUM *dq, const BIGNUM *qinv, BN_CTX *ctx)
561         {
562         int     y_len,
563                 m_len,
564                 fd;
565
566         m_len = BN_num_bytes(p) + BN_num_bytes(q) + 1;
567         y_len = BN_num_bits(p) + BN_num_bits(q);
568
569         /* Check if hardware can't handle this argument. */
570         if (y_len > 1024) {
571                 ENGINEerr(ENGINE_F_UBSEC_MOD_EXP, ENGINE_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
572                 return 0;
573         } 
574
575         if (!bn_wexpand(r, p->top + q->top + 1)) {
576                 ENGINEerr(ENGINE_F_UBSEC_RSA_MOD_EXP_CRT, ENGINE_R_BN_EXPAND_FAIL);
577                 return 0;
578         }
579
580         if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) {
581                 fd = 0;
582                 ENGINEerr(ENGINE_F_UBSEC_INIT, ENGINE_R_UNIT_FAILURE);
583                 return 0;
584         }
585
586         if (p_UBSEC_rsa_mod_exp_crt_ioctl(fd,
587                 (unsigned char *)a->d, BN_num_bits(a), 
588                 (unsigned char *)qinv->d, BN_num_bits(qinv),
589                 (unsigned char *)dp->d, BN_num_bits(dp),
590                 (unsigned char *)p->d, BN_num_bits(p),
591                 (unsigned char *)dq->d, BN_num_bits(dq),
592                 (unsigned char *)q->d, BN_num_bits(q),
593                 (unsigned char *)r->d,  &y_len) != 0) {
594                 ENGINEerr(ENGINE_F_UBSEC_MOD_EXP, ENGINE_R_REQUEST_FAILED);
595                 return 0;
596         }
597
598         p_UBSEC_ubsec_close(fd);
599
600         r->top = (BN_num_bits(p) + BN_num_bits(q) + BN_BITS2 - 1)/BN_BITS2;
601         return 1;
602 }
603
604 #ifndef OPENSSL_NO_DSA
605 #if NOT_USED
606 static int ubsec_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1,
607                 BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m,
608                 BN_CTX *ctx, BN_MONT_CTX *in_mont)
609         {
610         BIGNUM t;
611         int to_return = 0;
612  
613         BN_init(&t);
614         /* let rr = a1 ^ p1 mod m */
615         if (!ubsec_mod_exp(rr,a1,p1,m,ctx)) goto end;
616         /* let t = a2 ^ p2 mod m */
617         if (!ubsec_mod_exp(&t,a2,p2,m,ctx)) goto end;
618         /* let rr = rr * t mod m */
619         if (!BN_mod_mul(rr,rr,&t,m,ctx)) goto end;
620         to_return = 1;
621 end:
622         BN_free(&t);
623         return to_return;
624         }
625
626 static int ubsec_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a,
627                 const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
628                 BN_MONT_CTX *m_ctx)
629         {
630         return ubsec_mod_exp(r, a, p, m, ctx);
631         }
632 #endif
633 #endif
634
635 /*
636  * This function is aliased to mod_exp (with the mont stuff dropped).
637  */
638 static int ubsec_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
639                 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
640         {
641         int ret = 0;
642
643 #ifndef OPENSSL_NO_RSA
644         /* Do in software if the key is too large for the hardware. */
645         if (BN_num_bits(m) > 1024)
646                 {
647                 const RSA_METHOD *meth = RSA_PKCS1_SSLeay();
648                 ret = (*meth->bn_mod_exp)(r, a, p, m, ctx, m_ctx);
649                 }
650         else
651 #endif
652                 {
653                 ret = ubsec_mod_exp(r, a, p, m, ctx);
654                 }
655         
656         return ret;
657         }
658
659 #ifndef OPENSSL_NO_DH
660 /* This function is aliased to mod_exp (with the dh and mont dropped). */
661 static int ubsec_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a,
662                 const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
663                 BN_MONT_CTX *m_ctx)
664         {
665         return ubsec_mod_exp(r, a, p, m, ctx);
666         }
667 #endif
668
669 #ifndef OPENSSL_NO_DSA
670 static DSA_SIG *ubsec_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
671         {
672         DSA_SIG *to_return = NULL;
673         int s_len = 160, r_len = 160, d_len, fd;
674         BIGNUM m, *r=NULL, *s=NULL;
675
676         BN_init(&m);
677
678         s = BN_new();
679         r = BN_new();
680         if ((s == NULL) || (r==NULL))
681                 goto err;
682
683         d_len = p_UBSEC_ubsec_bytes_to_bits((unsigned char *)dgst, dlen);
684
685         if(!bn_wexpand(r, (160+BN_BITS2-1)/BN_BITS2) ||
686            (!bn_wexpand(s, (160+BN_BITS2-1)/BN_BITS2))) {
687                 ENGINEerr(ENGINE_F_UBSEC_DSA_SIGN, ENGINE_R_BN_EXPAND_FAIL);
688                 goto err;
689         }
690
691         if (BN_bin2bn(dgst,dlen,&m) == NULL) {
692                 ENGINEerr(ENGINE_F_UBSEC_DSA_SIGN, ENGINE_R_BN_EXPAND_FAIL);
693                 goto err;
694         } 
695
696         if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) {
697                 fd = 0;
698                 ENGINEerr(ENGINE_F_UBSEC_INIT, ENGINE_R_UNIT_FAILURE);
699                 return 0;
700         }
701
702         if (p_UBSEC_dsa_sign_ioctl(fd, 0, /* compute hash before signing */
703                 (unsigned char *)dgst, d_len,
704                 NULL, 0,  /* compute random value */
705                 (unsigned char *)dsa->p->d, BN_num_bits(dsa->p), 
706                 (unsigned char *)dsa->q->d, BN_num_bits(dsa->q),
707                 (unsigned char *)dsa->g->d, BN_num_bits(dsa->g),
708                 (unsigned char *)dsa->priv_key->d, BN_num_bits(dsa->priv_key),
709                 (unsigned char *)r->d, &r_len,
710                 (unsigned char *)s->d, &s_len ) != 0) {
711                 ENGINEerr(ENGINE_F_UBSEC_DSA_SIGN, ENGINE_R_REQUEST_FAILED);
712                 goto err;
713         }
714
715         p_UBSEC_ubsec_close(fd);
716
717         r->top = (160+BN_BITS2-1)/BN_BITS2;
718         s->top = (160+BN_BITS2-1)/BN_BITS2;
719
720         to_return = DSA_SIG_new();
721         if(to_return == NULL) {
722                 ENGINEerr(ENGINE_F_UBSEC_DSA_SIGN, ENGINE_R_BN_EXPAND_FAIL);
723                 goto err;
724         }
725
726         to_return->r = r;
727         to_return->s = s;
728
729 err:
730         if (!to_return) {
731                 if (r) BN_free(r);
732                 if (s) BN_free(s);
733         }                                 
734         BN_clear_free(&m);
735         return to_return;
736 }
737
738 static int ubsec_dsa_verify(const unsigned char *dgst, int dgst_len,
739                                 DSA_SIG *sig, DSA *dsa)
740         {
741         int v_len, d_len;
742         int to_return = 0;
743         int fd;
744         BIGNUM v;
745
746         BN_init(&v);
747
748         if(!bn_wexpand(&v, dsa->p->top)) {
749                 ENGINEerr(ENGINE_F_UBSEC_DSA_VERIFY ,ENGINE_R_BN_EXPAND_FAIL);
750                 goto err;
751         }
752
753         v_len = BN_num_bits(dsa->p);
754
755         d_len = p_UBSEC_ubsec_bytes_to_bits((unsigned char *)dgst, dgst_len);
756
757         if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) {
758                 fd = 0;
759                 ENGINEerr(ENGINE_F_UBSEC_INIT, ENGINE_R_UNIT_FAILURE);
760                 return 0;
761         }
762
763         if (p_UBSEC_dsa_verify_ioctl(fd, 0, /* compute hash before signing */
764                 (unsigned char *)dgst, d_len,
765                 (unsigned char *)dsa->p->d, BN_num_bits(dsa->p), 
766                 (unsigned char *)dsa->q->d, BN_num_bits(dsa->q),
767                 (unsigned char *)dsa->g->d, BN_num_bits(dsa->g),
768                 (unsigned char *)dsa->pub_key->d, BN_num_bits(dsa->pub_key),
769                 (unsigned char *)sig->r->d, BN_num_bits(sig->r),
770                 (unsigned char *)sig->s->d, BN_num_bits(sig->s),
771                 (unsigned char *)v.d, &v_len) != 0) {
772                 ENGINEerr(ENGINE_F_UBSEC_DSA_VERIFY , ENGINE_R_REQUEST_FAILED);
773                 goto err;
774         }
775
776         p_UBSEC_ubsec_close(fd);
777
778         to_return = 1;
779 err:
780         BN_clear_free(&v);
781         return to_return;
782         }
783 #endif
784
785 #ifndef OPENSSL_NO_DH
786 static int ubsec_dh_compute_key (unsigned char *key,const BIGNUM *pub_key,DH *dh)
787         {
788         return 0;
789         }
790
791 static int ubsec_dh_generate_key (DH *dh)
792         {
793         return 0;
794         }
795 #endif
796
797 #ifdef NOT_USED
798 static int ubsec_rand_bytes(unsigned char *buf, int num)
799         {
800         return 0;
801         }
802
803 static int ubsec_rand_status(void)
804         {
805         return 0;
806         }
807 #endif
808
809 #endif /* !OPENSSL_NO_HW_UBSEC */
810 #endif /* !OPENSSL_NO_HW */