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