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