143efbdeea4e588d9414a964af3089d3e4cd1866
[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(ENGINE *e);
78 static int ubsec_finish(ENGINE *e);
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 /* 
235  * These are the static string constants for the DSO file name and the function
236  * symbol names to bind to. 
237  */
238
239 static const char *UBSEC_LIBNAME = "ubsec";
240 static const char *UBSEC_F1 = "ubsec_bytes_to_bits";
241 static const char *UBSEC_F2 = "ubsec_bits_to_bytes";
242 static const char *UBSEC_F3 = "ubsec_open";
243 static const char *UBSEC_F4 = "ubsec_close";
244 static const char *UBSEC_F5 = "diffie_hellman_generate_ioctl";
245 static const char *UBSEC_F6 = "diffie_hellman_agree_ioctl";
246 static const char *UBSEC_F7 = "rsa_mod_exp_ioctl";
247 static const char *UBSEC_F8 = "rsa_mod_exp_crt_ioctl";
248 static const char *UBSEC_F9 = "dsa_sign_ioctl";
249 static const char *UBSEC_F10 = "dsa_verify_ioctl";
250 static const char *UBSEC_F11 = "math_accelerate_ioctl";
251 static const char *UBSEC_F12 = "rng_ioctl";
252
253 /* (de)initialisation functions. */
254 static int ubsec_init(ENGINE *e)
255         {
256         t_UBSEC_ubsec_bytes_to_bits *p1;
257         t_UBSEC_ubsec_bits_to_bytes *p2;
258         t_UBSEC_ubsec_open *p3;
259         t_UBSEC_ubsec_close *p4;
260         t_UBSEC_diffie_hellman_generate_ioctl *p5;
261         t_UBSEC_diffie_hellman_agree_ioctl *p6;
262         t_UBSEC_rsa_mod_exp_ioctl *p7;
263         t_UBSEC_rsa_mod_exp_crt_ioctl *p8;
264         t_UBSEC_dsa_sign_ioctl *p9;
265         t_UBSEC_dsa_verify_ioctl *p10;
266         t_UBSEC_math_accelerate_ioctl *p11;
267         t_UBSEC_rng_ioctl *p12;
268         int fd = 0;
269
270         if(ubsec_dso != NULL)
271                 {
272                 ENGINEerr(ENGINE_F_UBSEC_INIT, ENGINE_R_ALREADY_LOADED);
273                 goto err;
274                 }
275         /* 
276          * Attempt to load libubsec.so/ubsec.dll/whatever. 
277          */
278         ubsec_dso = DSO_load(NULL, UBSEC_LIBNAME, NULL, 0);
279         if(ubsec_dso == NULL)
280                 {
281                 ENGINEerr(ENGINE_F_UBSEC_INIT, ENGINE_R_DSO_FAILURE);
282                 goto err;
283                 }
284
285         if (
286         !(p1 = (t_UBSEC_ubsec_bytes_to_bits *) DSO_bind_func(ubsec_dso, UBSEC_F1)) ||
287         !(p2 = (t_UBSEC_ubsec_bits_to_bytes *) DSO_bind_func(ubsec_dso, UBSEC_F2)) ||
288         !(p3 = (t_UBSEC_ubsec_open *) DSO_bind_func(ubsec_dso, UBSEC_F3)) ||
289         !(p4 = (t_UBSEC_ubsec_close *) DSO_bind_func(ubsec_dso, UBSEC_F4)) ||
290         !(p5 = (t_UBSEC_diffie_hellman_generate_ioctl *) 
291                                 DSO_bind_func(ubsec_dso, UBSEC_F5)) ||
292         !(p6 = (t_UBSEC_diffie_hellman_agree_ioctl *) 
293                                 DSO_bind_func(ubsec_dso, UBSEC_F6)) ||
294         !(p7 = (t_UBSEC_rsa_mod_exp_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F7)) ||
295         !(p8 = (t_UBSEC_rsa_mod_exp_crt_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F8)) ||
296         !(p9 = (t_UBSEC_dsa_sign_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F9)) ||
297         !(p10 = (t_UBSEC_dsa_verify_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F10)) ||
298         !(p11 = (t_UBSEC_math_accelerate_ioctl *) 
299                                 DSO_bind_func(ubsec_dso, UBSEC_F11)) ||
300         !(p12 = (t_UBSEC_rng_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F12)))
301                 {
302                 ENGINEerr(ENGINE_F_UBSEC_INIT, ENGINE_R_DSO_FAILURE);
303                 goto err;
304                 }
305
306         /* Copy the pointers */
307         p_UBSEC_ubsec_bytes_to_bits = p1;
308         p_UBSEC_ubsec_bits_to_bytes = p2;
309         p_UBSEC_ubsec_open = p3;
310         p_UBSEC_ubsec_close = p4;
311         p_UBSEC_diffie_hellman_generate_ioctl = p5;
312         p_UBSEC_diffie_hellman_agree_ioctl = p6;
313         p_UBSEC_rsa_mod_exp_ioctl = p7;
314         p_UBSEC_rsa_mod_exp_crt_ioctl = p8;
315         p_UBSEC_dsa_sign_ioctl = p9;
316         p_UBSEC_dsa_verify_ioctl = p10;
317         p_UBSEC_math_accelerate_ioctl = p11;
318         p_UBSEC_rng_ioctl = p12;
319
320         /* Perform an open to see if there's actually any unit running. */
321         if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) > 0)
322                 {
323                 p_UBSEC_ubsec_close(fd);
324                 return 1;
325                 }
326         else
327                 {
328                 ENGINEerr(ENGINE_F_UBSEC_INIT, ENGINE_R_UNIT_FAILURE);
329                 }
330
331 err:
332         if(ubsec_dso)
333                 DSO_free(ubsec_dso);
334         p_UBSEC_ubsec_bytes_to_bits = NULL;
335         p_UBSEC_ubsec_bits_to_bytes = NULL;
336         p_UBSEC_ubsec_open = NULL;
337         p_UBSEC_ubsec_close = NULL;
338         p_UBSEC_diffie_hellman_generate_ioctl = NULL;
339         p_UBSEC_diffie_hellman_agree_ioctl = NULL;
340         p_UBSEC_rsa_mod_exp_ioctl = NULL;
341         p_UBSEC_rsa_mod_exp_crt_ioctl = NULL;
342         p_UBSEC_dsa_sign_ioctl = NULL;
343         p_UBSEC_dsa_verify_ioctl = NULL;
344         p_UBSEC_math_accelerate_ioctl = NULL;
345         p_UBSEC_rng_ioctl = NULL;
346
347         return 0;
348         }
349
350 static int ubsec_finish(ENGINE *e)
351         {
352         if(ubsec_dso == NULL)
353                 {
354                 ENGINEerr(ENGINE_F_UBSEC_FINISH, ENGINE_R_NOT_LOADED);
355                 return 0;
356                 }
357         if(!DSO_free(ubsec_dso))
358                 {
359                 ENGINEerr(ENGINE_F_UBSEC_FINISH, ENGINE_R_DSO_FAILURE);
360                 return 0;
361                 }
362         ubsec_dso = NULL;
363         p_UBSEC_ubsec_bytes_to_bits = NULL;
364         p_UBSEC_ubsec_bits_to_bytes = NULL;
365         p_UBSEC_ubsec_open = NULL;
366         p_UBSEC_ubsec_close = NULL;
367         p_UBSEC_diffie_hellman_generate_ioctl = NULL;
368         p_UBSEC_diffie_hellman_agree_ioctl = NULL;
369         p_UBSEC_rsa_mod_exp_ioctl = NULL;
370         p_UBSEC_rsa_mod_exp_crt_ioctl = NULL;
371         p_UBSEC_dsa_sign_ioctl = NULL;
372         p_UBSEC_dsa_verify_ioctl = NULL;
373         p_UBSEC_math_accelerate_ioctl = NULL;
374         p_UBSEC_rng_ioctl = NULL;
375         return 1;
376         }
377
378 static int ubsec_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
379                 const BIGNUM *m, BN_CTX *ctx)
380         {
381         int     y_len = 0;
382         int     fd;
383
384         if(ubsec_dso == NULL)
385         {
386                 ENGINEerr(ENGINE_F_UBSEC_MOD_EXP, ENGINE_R_NOT_LOADED);
387                 return 0;
388         }
389
390         /* Check if hardware can't handle this argument. */
391         y_len = BN_num_bits(m);
392         if (y_len > 1024) {
393                 ENGINEerr(ENGINE_F_UBSEC_MOD_EXP, ENGINE_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
394                 return 0;
395         } 
396
397         if(!bn_wexpand(r, m->top))
398         {
399                 ENGINEerr(ENGINE_F_UBSEC_MOD_EXP, ENGINE_R_BN_EXPAND_FAIL);
400                 return 0;
401         }
402         memset(r->d, 0, BN_num_bytes(m));
403
404         if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) {
405                 fd = 0;
406                 ENGINEerr(ENGINE_F_UBSEC_INIT, ENGINE_R_UNIT_FAILURE);
407                 return 0;
408         }
409
410         if (p_UBSEC_rsa_mod_exp_ioctl(fd, (unsigned char *)a->d, BN_num_bits(a),
411                 (unsigned char *)m->d, BN_num_bits(m), (unsigned char *)p->d, 
412                 BN_num_bits(p), (unsigned char *)r->d, &y_len) != 0)
413         {
414                 ENGINEerr(ENGINE_F_UBSEC_MOD_EXP, ENGINE_R_REQUEST_FAILED);
415                 return 0;
416         }
417
418         p_UBSEC_ubsec_close(fd);
419
420         r->top = (BN_num_bits(m)+BN_BITS2-1)/BN_BITS2;
421         return 1;
422         }
423
424 static int ubsec_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa)
425         {
426         BN_CTX *ctx;
427         int to_return = 0;
428
429         if((ctx = BN_CTX_new()) == NULL)
430                 goto err;
431
432         if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
433                 {
434                 ENGINEerr(ENGINE_F_UBSEC_RSA_MOD_EXP, ENGINE_R_MISSING_KEY_COMPONENTS);
435                 goto err;
436                 }
437
438         /*
439          * Do in software if argument is too large for hardware.
440          */
441         if ((BN_num_bits(rsa->p)+BN_num_bits(rsa->q)) > 1024) {
442                 const RSA_METHOD *meth = RSA_PKCS1_SSLeay();
443                 to_return = (*meth->rsa_mod_exp)(r0, I, rsa);
444         } else {
445                 to_return = ubsec_mod_exp_crt(r0, I, rsa->p, rsa->q, rsa->dmp1,
446                         rsa->dmq1, rsa->iqmp, ctx);
447         }
448 err:
449         if(ctx)
450                 BN_CTX_free(ctx);
451         return to_return;
452         }
453
454 static int ubsec_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
455                         const BIGNUM *q, const BIGNUM *dp,
456                         const BIGNUM *dq, const BIGNUM *qinv, BN_CTX *ctx)
457         {
458         int     y_len,
459                 m_len,
460                 fd;
461
462         m_len = BN_num_bytes(p) + BN_num_bytes(q) + 1;
463         y_len = BN_num_bits(p) + BN_num_bits(q);
464
465         /* Check if hardware can't handle this argument. */
466         if (y_len > 1024) {
467                 ENGINEerr(ENGINE_F_UBSEC_MOD_EXP, ENGINE_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
468                 return 0;
469         } 
470
471         if (!bn_wexpand(r, p->top + q->top + 1)) {
472                 ENGINEerr(ENGINE_F_UBSEC_RSA_MOD_EXP_CRT, ENGINE_R_BN_EXPAND_FAIL);
473                 return 0;
474         }
475
476         if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) {
477                 fd = 0;
478                 ENGINEerr(ENGINE_F_UBSEC_INIT, ENGINE_R_UNIT_FAILURE);
479                 return 0;
480         }
481
482         if (p_UBSEC_rsa_mod_exp_crt_ioctl(fd,
483                 (unsigned char *)a->d, BN_num_bits(a), 
484                 (unsigned char *)qinv->d, BN_num_bits(qinv),
485                 (unsigned char *)dp->d, BN_num_bits(dp),
486                 (unsigned char *)p->d, BN_num_bits(p),
487                 (unsigned char *)dq->d, BN_num_bits(dq),
488                 (unsigned char *)q->d, BN_num_bits(q),
489                 (unsigned char *)r->d,  &y_len) != 0) {
490                 ENGINEerr(ENGINE_F_UBSEC_MOD_EXP, ENGINE_R_REQUEST_FAILED);
491                 return 0;
492         }
493
494         p_UBSEC_ubsec_close(fd);
495
496         r->top = (BN_num_bits(p) + BN_num_bits(q) + BN_BITS2 - 1)/BN_BITS2;
497         return 1;
498 }
499
500 #if NOT_USED
501 static int ubsec_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1,
502                 BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m,
503                 BN_CTX *ctx, BN_MONT_CTX *in_mont)
504         {
505         BIGNUM t;
506         int to_return = 0;
507  
508         BN_init(&t);
509         /* let rr = a1 ^ p1 mod m */
510         if (!ubsec_mod_exp(rr,a1,p1,m,ctx)) goto end;
511         /* let t = a2 ^ p2 mod m */
512         if (!ubsec_mod_exp(&t,a2,p2,m,ctx)) goto end;
513         /* let rr = rr * t mod m */
514         if (!BN_mod_mul(rr,rr,&t,m,ctx)) goto end;
515         to_return = 1;
516 end:
517         BN_free(&t);
518         return to_return;
519         }
520
521 static int ubsec_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a,
522                 const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
523                 BN_MONT_CTX *m_ctx)
524         {
525         return ubsec_mod_exp(r, a, p, m, ctx);
526         }
527 #endif
528
529 /*
530  * This function is aliased to mod_exp (with the mont stuff dropped).
531  */
532 static int ubsec_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
533                 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
534 {
535         int ret = 0;
536
537         /* Do in software if the key is too large for the hardware. */
538         if (BN_num_bits(m) > 1024) {
539                 const RSA_METHOD *meth = RSA_PKCS1_SSLeay();
540                 ret = (*meth->bn_mod_exp)(r, a, p, m, ctx, m_ctx);
541         } else {
542                 ret = ubsec_mod_exp(r, a, p, m, ctx);
543         }
544         
545         return ret;
546 }
547
548 /* This function is aliased to mod_exp (with the dh and mont dropped). */
549 static int ubsec_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a,
550                 const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
551                 BN_MONT_CTX *m_ctx)
552         {
553         return ubsec_mod_exp(r, a, p, m, ctx);
554         }
555
556 static DSA_SIG *ubsec_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
557         {
558         DSA_SIG *to_return = NULL;
559         int s_len = 160, r_len = 160, d_len, fd;
560         BIGNUM m, *r=NULL, *s=NULL;
561
562         BN_init(&m);
563
564         s = BN_new();
565         r = BN_new();
566         if ((s == NULL) || (r==NULL))
567                 goto err;
568
569         d_len = p_UBSEC_ubsec_bytes_to_bits((unsigned char *)dgst, dlen);
570
571         if(!bn_wexpand(r, (160+BN_BITS2-1)/BN_BITS2) ||
572            (!bn_wexpand(s, (160+BN_BITS2-1)/BN_BITS2))) {
573                 ENGINEerr(ENGINE_F_UBSEC_DSA_SIGN, ENGINE_R_BN_EXPAND_FAIL);
574                 goto err;
575         }
576
577         if (BN_bin2bn(dgst,dlen,&m) == NULL) {
578                 ENGINEerr(ENGINE_F_UBSEC_DSA_SIGN, ENGINE_R_BN_EXPAND_FAIL);
579                 goto err;
580         } 
581
582         if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) {
583                 fd = 0;
584                 ENGINEerr(ENGINE_F_UBSEC_INIT, ENGINE_R_UNIT_FAILURE);
585                 return 0;
586         }
587
588         if (p_UBSEC_dsa_sign_ioctl(fd, 0, /* compute hash before signing */
589                 (unsigned char *)dgst, d_len,
590                 NULL, 0,  /* compute random value */
591                 (unsigned char *)dsa->p->d, BN_num_bits(dsa->p), 
592                 (unsigned char *)dsa->q->d, BN_num_bits(dsa->q),
593                 (unsigned char *)dsa->g->d, BN_num_bits(dsa->g),
594                 (unsigned char *)dsa->priv_key->d, BN_num_bits(dsa->priv_key),
595                 (unsigned char *)r->d, &r_len,
596                 (unsigned char *)s->d, &s_len ) != 0) {
597                 ENGINEerr(ENGINE_F_UBSEC_DSA_SIGN, ENGINE_R_REQUEST_FAILED);
598                 goto err;
599         }
600
601         p_UBSEC_ubsec_close(fd);
602
603         r->top = (160+BN_BITS2-1)/BN_BITS2;
604         s->top = (160+BN_BITS2-1)/BN_BITS2;
605
606         to_return = DSA_SIG_new();
607         if(to_return == NULL) {
608                 ENGINEerr(ENGINE_F_UBSEC_DSA_SIGN, ENGINE_R_BN_EXPAND_FAIL);
609                 goto err;
610         }
611
612         to_return->r = r;
613         to_return->s = s;
614
615 err:
616         if (!to_return) {
617                 if (r) BN_free(r);
618                 if (s) BN_free(s);
619         }                                 
620         BN_clear_free(&m);
621         return to_return;
622 }
623
624 static int ubsec_dsa_verify(const unsigned char *dgst, int dgst_len,
625                                 DSA_SIG *sig, DSA *dsa)
626         {
627         int v_len, d_len;
628         int to_return = 0;
629         int fd;
630         BIGNUM v;
631
632         BN_init(&v);
633
634         if(!bn_wexpand(&v, dsa->p->top)) {
635                 ENGINEerr(ENGINE_F_UBSEC_DSA_VERIFY ,ENGINE_R_BN_EXPAND_FAIL);
636                 goto err;
637         }
638
639         v_len = BN_num_bits(dsa->p);
640
641         d_len = p_UBSEC_ubsec_bytes_to_bits((unsigned char *)dgst, dgst_len);
642
643         if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) {
644                 fd = 0;
645                 ENGINEerr(ENGINE_F_UBSEC_INIT, ENGINE_R_UNIT_FAILURE);
646                 return 0;
647         }
648
649         if (p_UBSEC_dsa_verify_ioctl(fd, 0, /* compute hash before signing */
650                 (unsigned char *)dgst, d_len,
651                 (unsigned char *)dsa->p->d, BN_num_bits(dsa->p), 
652                 (unsigned char *)dsa->q->d, BN_num_bits(dsa->q),
653                 (unsigned char *)dsa->g->d, BN_num_bits(dsa->g),
654                 (unsigned char *)dsa->pub_key->d, BN_num_bits(dsa->pub_key),
655                 (unsigned char *)sig->r->d, BN_num_bits(sig->r),
656                 (unsigned char *)sig->s->d, BN_num_bits(sig->s),
657                 (unsigned char *)v.d, &v_len) != 0) {
658                 ENGINEerr(ENGINE_F_UBSEC_DSA_VERIFY , ENGINE_R_REQUEST_FAILED);
659                 goto err;
660         }
661
662         p_UBSEC_ubsec_close(fd);
663
664         to_return = 1;
665 err:
666         BN_clear_free(&v);
667         return to_return;
668         }
669
670 static int ubsec_dh_compute_key (unsigned char *key,const BIGNUM *pub_key,DH *dh)
671         {
672         return 0;
673         }
674
675 static int ubsec_dh_generate_key (DH *dh)
676         {
677         return 0;
678         }
679
680 #ifdef NOT_USED
681 static int ubsec_rand_bytes(unsigned char *buf, int num)
682         {
683         return 0;
684         }
685
686 static int ubsec_rand_status(void)
687         {
688         return 0;
689         }
690 #endif
691
692 #endif /* !OPENSSL_NO_HW_UBSEC */
693 #endif /* !OPENSSL_NO_HW */