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