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