Make a note of the recent ENGINE developments.
[openssl.git] / crypto / engine / hw_cswift.c
1 /* crypto/engine/hw_cswift.c */
2 /* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL
3  * project 2000.
4  */
5 /* ====================================================================
6  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer. 
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com).
56  *
57  */
58
59 #include <stdio.h>
60 #include <openssl/crypto.h>
61 #include "cryptlib.h"
62 #include <openssl/dso.h>
63 #include "engine_int.h"
64 #include <openssl/engine.h>
65
66 #ifndef OPENSSL_NO_HW
67 #ifndef OPENSSL_NO_HW_CSWIFT
68
69 /* Attribution notice: Rainbow have generously allowed me to reproduce
70  * the necessary definitions here from their API. This means the support
71  * can build independently of whether application builders have the
72  * API or hardware. This will allow developers to easily produce software
73  * that has latent hardware support for any users that have accelerators
74  * installed, without the developers themselves needing anything extra.
75  *
76  * I have only clipped the parts from the CryptoSwift header files that
77  * are (or seem) relevant to the CryptoSwift support code. This is
78  * simply to keep the file sizes reasonable.
79  * [Geoff]
80  */
81 #ifdef FLAT_INC
82 #include "cswift.h"
83 #else
84 #include "vendor_defns/cswift.h"
85 #endif
86
87 static int cswift_init(ENGINE *);
88 static int cswift_finish(ENGINE *);
89
90 /* BIGNUM stuff */
91 static int cswift_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
92                 const BIGNUM *m, BN_CTX *ctx);
93 static int cswift_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
94                 const BIGNUM *q, const BIGNUM *dmp1, const BIGNUM *dmq1,
95                 const BIGNUM *iqmp, BN_CTX *ctx);
96
97 /* RSA stuff */
98 static int cswift_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa);
99 /* This function is aliased to mod_exp (with the mont stuff dropped). */
100 static int cswift_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
101                 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
102
103 /* DSA stuff */
104 static DSA_SIG *cswift_dsa_sign(const unsigned char *dgst, int dlen, DSA *dsa);
105 static int cswift_dsa_verify(const unsigned char *dgst, int dgst_len,
106                                 DSA_SIG *sig, DSA *dsa);
107
108 /* DH stuff */
109 /* This function is alised to mod_exp (with the DH and mont dropped). */
110 static int cswift_mod_exp_dh(const DH *dh, BIGNUM *r,
111                 const BIGNUM *a, const BIGNUM *p,
112                 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
113
114
115 /* Our internal RSA_METHOD that we provide pointers to */
116 static RSA_METHOD cswift_rsa =
117         {
118         "CryptoSwift RSA method",
119         NULL,
120         NULL,
121         NULL,
122         NULL,
123         cswift_rsa_mod_exp,
124         cswift_mod_exp_mont,
125         NULL,
126         NULL,
127         0,
128         NULL,
129         NULL,
130         NULL
131         };
132
133 /* Our internal DSA_METHOD that we provide pointers to */
134 static DSA_METHOD cswift_dsa =
135         {
136         "CryptoSwift DSA method",
137         cswift_dsa_sign,
138         NULL, /* dsa_sign_setup */
139         cswift_dsa_verify,
140         NULL, /* dsa_mod_exp */
141         NULL, /* bn_mod_exp */
142         NULL, /* init */
143         NULL, /* finish */
144         0, /* flags */
145         NULL /* app_data */
146         };
147
148 /* Our internal DH_METHOD that we provide pointers to */
149 static DH_METHOD cswift_dh =
150         {
151         "CryptoSwift DH method",
152         NULL,
153         NULL,
154         cswift_mod_exp_dh,
155         NULL,
156         NULL,
157         0,
158         NULL
159         };
160
161 /* Our ENGINE structure. */
162 static ENGINE engine_cswift =
163         {
164         "cswift",
165         "CryptoSwift hardware engine support",
166         &cswift_rsa,
167         &cswift_dsa,
168         &cswift_dh,
169         NULL,
170         cswift_mod_exp,
171         cswift_mod_exp_crt,
172         cswift_init,
173         cswift_finish,
174         NULL, /* no ctrl() */
175         NULL, /* no load_privkey() */
176         NULL, /* no load_pubkey() */
177         0, /* no flags */
178         0, 0, /* no references */
179         NULL, NULL /* unlinked */
180         };
181
182 /* As this is only ever called once, there's no need for locking
183  * (indeed - the lock will already be held by our caller!!!) */
184 ENGINE *ENGINE_cswift()
185         {
186         const RSA_METHOD *meth1;
187         const DH_METHOD *meth2;
188
189         /* We know that the "PKCS1_SSLeay()" functions hook properly
190          * to the cswift-specific mod_exp and mod_exp_crt so we use
191          * those functions. NB: We don't use ENGINE_openssl() or
192          * anything "more generic" because something like the RSAref
193          * code may not hook properly, and if you own one of these
194          * cards then you have the right to do RSA operations on it
195          * anyway! */ 
196         meth1 = RSA_PKCS1_SSLeay();
197         cswift_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
198         cswift_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
199         cswift_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
200         cswift_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
201
202         /* Much the same for Diffie-Hellman */
203         meth2 = DH_OpenSSL();
204         cswift_dh.generate_key = meth2->generate_key;
205         cswift_dh.compute_key = meth2->compute_key;
206         return &engine_cswift;
207         }
208
209 /* This is a process-global DSO handle used for loading and unloading
210  * the CryptoSwift 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 static DSO *cswift_dso = NULL;
215
216 /* These are the function pointers that are (un)set when the library has
217  * successfully (un)loaded. */
218 t_swAcquireAccContext *p_CSwift_AcquireAccContext = NULL;
219 t_swAttachKeyParam *p_CSwift_AttachKeyParam = NULL;
220 t_swSimpleRequest *p_CSwift_SimpleRequest = NULL;
221 t_swReleaseAccContext *p_CSwift_ReleaseAccContext = NULL;
222
223 /* Used in the DSO operations. */
224 static const char *CSWIFT_LIBNAME = "swift";
225 static const char *CSWIFT_F1 = "swAcquireAccContext";
226 static const char *CSWIFT_F2 = "swAttachKeyParam";
227 static const char *CSWIFT_F3 = "swSimpleRequest";
228 static const char *CSWIFT_F4 = "swReleaseAccContext";
229
230
231 /* CryptoSwift library functions and mechanics - these are used by the
232  * higher-level functions further down. NB: As and where there's no
233  * error checking, take a look lower down where these functions are
234  * called, the checking and error handling is probably down there. */
235
236 /* utility function to obtain a context */
237 static int get_context(SW_CONTEXT_HANDLE *hac)
238         {
239         SW_STATUS status;
240  
241         status = p_CSwift_AcquireAccContext(hac);
242         if(status != SW_OK)
243                 return 0;
244         return 1;
245         }
246  
247 /* similarly to release one. */
248 static void release_context(SW_CONTEXT_HANDLE hac)
249         {
250         p_CSwift_ReleaseAccContext(hac);
251         }
252
253 /* (de)initialisation functions. */
254 static int cswift_init(ENGINE *e)
255         {
256         SW_CONTEXT_HANDLE hac;
257         t_swAcquireAccContext *p1;
258         t_swAttachKeyParam *p2;
259         t_swSimpleRequest *p3;
260         t_swReleaseAccContext *p4;
261
262         if(cswift_dso != NULL)
263                 {
264                 ENGINEerr(ENGINE_F_CSWIFT_INIT,ENGINE_R_ALREADY_LOADED);
265                 goto err;
266                 }
267         /* Attempt to load libswift.so/swift.dll/whatever. */
268         cswift_dso = DSO_load(NULL, CSWIFT_LIBNAME, NULL, 0);
269         if(cswift_dso == NULL)
270                 {
271                 ENGINEerr(ENGINE_F_CSWIFT_INIT,ENGINE_R_DSO_FAILURE);
272                 goto err;
273                 }
274         if(!(p1 = (t_swAcquireAccContext *)
275                                 DSO_bind_func(cswift_dso, CSWIFT_F1)) ||
276                         !(p2 = (t_swAttachKeyParam *)
277                                 DSO_bind_func(cswift_dso, CSWIFT_F2)) ||
278                         !(p3 = (t_swSimpleRequest *)
279                                 DSO_bind_func(cswift_dso, CSWIFT_F3)) ||
280                         !(p4 = (t_swReleaseAccContext *)
281                                 DSO_bind_func(cswift_dso, CSWIFT_F4)))
282                 {
283                 ENGINEerr(ENGINE_F_CSWIFT_INIT,ENGINE_R_DSO_FAILURE);
284                 goto err;
285                 }
286         /* Copy the pointers */
287         p_CSwift_AcquireAccContext = p1;
288         p_CSwift_AttachKeyParam = p2;
289         p_CSwift_SimpleRequest = p3;
290         p_CSwift_ReleaseAccContext = p4;
291         /* Try and get a context - if not, we may have a DSO but no
292          * accelerator! */
293         if(!get_context(&hac))
294                 {
295                 ENGINEerr(ENGINE_F_CSWIFT_INIT,ENGINE_R_UNIT_FAILURE);
296                 goto err;
297                 }
298         release_context(hac);
299         /* Everything's fine. */
300         return 1;
301 err:
302         if(cswift_dso)
303                 DSO_free(cswift_dso);
304         p_CSwift_AcquireAccContext = NULL;
305         p_CSwift_AttachKeyParam = NULL;
306         p_CSwift_SimpleRequest = NULL;
307         p_CSwift_ReleaseAccContext = NULL;
308         return 0;
309         }
310
311 static int cswift_finish(ENGINE *e)
312         {
313         if(cswift_dso == NULL)
314                 {
315                 ENGINEerr(ENGINE_F_CSWIFT_FINISH,ENGINE_R_NOT_LOADED);
316                 return 0;
317                 }
318         if(!DSO_free(cswift_dso))
319                 {
320                 ENGINEerr(ENGINE_F_CSWIFT_FINISH,ENGINE_R_DSO_FAILURE);
321                 return 0;
322                 }
323         cswift_dso = NULL;
324         p_CSwift_AcquireAccContext = NULL;
325         p_CSwift_AttachKeyParam = NULL;
326         p_CSwift_SimpleRequest = NULL;
327         p_CSwift_ReleaseAccContext = NULL;
328         return 1;
329         }
330
331 /* Un petit mod_exp */
332 static int cswift_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
333                         const BIGNUM *m, BN_CTX *ctx)
334         {
335         /* I need somewhere to store temporary serialised values for
336          * use with the CryptoSwift API calls. A neat cheat - I'll use
337          * BIGNUMs from the BN_CTX but access their arrays directly as
338          * byte arrays <grin>. This way I don't have to clean anything
339          * up. */
340         BIGNUM *modulus;
341         BIGNUM *exponent;
342         BIGNUM *argument;
343         BIGNUM *result;
344         SW_STATUS sw_status;
345         SW_LARGENUMBER arg, res;
346         SW_PARAM sw_param;
347         SW_CONTEXT_HANDLE hac;
348         int to_return, acquired;
349  
350         modulus = exponent = argument = result = NULL;
351         to_return = 0; /* expect failure */
352         acquired = 0;
353  
354         if(!get_context(&hac))
355                 {
356                 ENGINEerr(ENGINE_F_CSWIFT_MOD_EXP,ENGINE_R_GET_HANDLE_FAILED);
357                 goto err;
358                 }
359         acquired = 1;
360         /* Prepare the params */
361         BN_CTX_start(ctx);
362         modulus = BN_CTX_get(ctx);
363         exponent = BN_CTX_get(ctx);
364         argument = BN_CTX_get(ctx);
365         result = BN_CTX_get(ctx);
366         if(!result)
367                 {
368                 ENGINEerr(ENGINE_F_CSWIFT_MOD_EXP,ENGINE_R_BN_CTX_FULL);
369                 goto err;
370                 }
371         if(!bn_wexpand(modulus, m->top) || !bn_wexpand(exponent, p->top) ||
372                 !bn_wexpand(argument, a->top) || !bn_wexpand(result, m->top))
373                 {
374                 ENGINEerr(ENGINE_F_CSWIFT_MOD_EXP,ENGINE_R_BN_EXPAND_FAIL);
375                 goto err;
376                 }
377         sw_param.type = SW_ALG_EXP;
378         sw_param.up.exp.modulus.nbytes = BN_bn2bin(m,
379                 (unsigned char *)modulus->d);
380         sw_param.up.exp.modulus.value = (unsigned char *)modulus->d;
381         sw_param.up.exp.exponent.nbytes = BN_bn2bin(p,
382                 (unsigned char *)exponent->d);
383         sw_param.up.exp.exponent.value = (unsigned char *)exponent->d;
384         /* Attach the key params */
385         sw_status = p_CSwift_AttachKeyParam(hac, &sw_param);
386         switch(sw_status)
387                 {
388         case SW_OK:
389                 break;
390         case SW_ERR_INPUT_SIZE:
391                 ENGINEerr(ENGINE_F_CSWIFT_MOD_EXP,
392                         ENGINE_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
393                 goto err;
394         default:
395                 {
396                 char tmpbuf[20];
397                 ENGINEerr(ENGINE_F_CSWIFT_MOD_EXP,ENGINE_R_REQUEST_FAILED);
398                 sprintf(tmpbuf, "%ld", sw_status);
399                 ERR_add_error_data(2, "CryptoSwift error number is ",tmpbuf);
400                 }
401                 goto err;
402                 }
403         /* Prepare the argument and response */
404         arg.nbytes = BN_bn2bin(a, (unsigned char *)argument->d);
405         arg.value = (unsigned char *)argument->d;
406         res.nbytes = BN_num_bytes(m);
407         memset(result->d, 0, res.nbytes);
408         res.value = (unsigned char *)result->d;
409         /* Perform the operation */
410         if((sw_status = p_CSwift_SimpleRequest(hac, SW_CMD_MODEXP, &arg, 1,
411                 &res, 1)) != SW_OK)
412                 {
413                 char tmpbuf[20];
414                 ENGINEerr(ENGINE_F_CSWIFT_MOD_EXP,ENGINE_R_REQUEST_FAILED);
415                 sprintf(tmpbuf, "%ld", sw_status);
416                 ERR_add_error_data(2, "CryptoSwift error number is ",tmpbuf);
417                 goto err;
418                 }
419         /* Convert the response */
420         BN_bin2bn((unsigned char *)result->d, res.nbytes, r);
421         to_return = 1;
422 err:
423         if(acquired)
424                 release_context(hac);
425         BN_CTX_end(ctx);
426         return to_return;
427         }
428
429 /* Un petit mod_exp chinois */
430 static int cswift_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
431                         const BIGNUM *q, const BIGNUM *dmp1,
432                         const BIGNUM *dmq1, const BIGNUM *iqmp, BN_CTX *ctx)
433         {
434         SW_STATUS sw_status;
435         SW_LARGENUMBER arg, res;
436         SW_PARAM sw_param;
437         SW_CONTEXT_HANDLE hac;
438         BIGNUM *rsa_p = NULL;
439         BIGNUM *rsa_q = NULL;
440         BIGNUM *rsa_dmp1 = NULL;
441         BIGNUM *rsa_dmq1 = NULL;
442         BIGNUM *rsa_iqmp = NULL;
443         BIGNUM *argument = NULL;
444         BIGNUM *result = NULL;
445         int to_return = 0; /* expect failure */
446         int acquired = 0;
447  
448         if(!get_context(&hac))
449                 {
450                 ENGINEerr(ENGINE_F_CSWIFT_MOD_EXP_CRT,ENGINE_R_GET_HANDLE_FAILED);
451                 goto err;
452                 }
453         acquired = 1;
454         /* Prepare the params */
455         BN_CTX_start(ctx);
456         rsa_p = BN_CTX_get(ctx);
457         rsa_q = BN_CTX_get(ctx);
458         rsa_dmp1 = BN_CTX_get(ctx);
459         rsa_dmq1 = BN_CTX_get(ctx);
460         rsa_iqmp = BN_CTX_get(ctx);
461         argument = BN_CTX_get(ctx);
462         result = BN_CTX_get(ctx);
463         if(!result)
464                 {
465                 ENGINEerr(ENGINE_F_CSWIFT_MOD_EXP_CRT,ENGINE_R_BN_CTX_FULL);
466                 goto err;
467                 }
468         if(!bn_wexpand(rsa_p, p->top) || !bn_wexpand(rsa_q, q->top) ||
469                         !bn_wexpand(rsa_dmp1, dmp1->top) ||
470                         !bn_wexpand(rsa_dmq1, dmq1->top) ||
471                         !bn_wexpand(rsa_iqmp, iqmp->top) ||
472                         !bn_wexpand(argument, a->top) ||
473                         !bn_wexpand(result, p->top + q->top))
474                 {
475                 ENGINEerr(ENGINE_F_CSWIFT_MOD_EXP_CRT,ENGINE_R_BN_EXPAND_FAIL);
476                 goto err;
477                 }
478         sw_param.type = SW_ALG_CRT;
479         sw_param.up.crt.p.nbytes = BN_bn2bin(p, (unsigned char *)rsa_p->d);
480         sw_param.up.crt.p.value = (unsigned char *)rsa_p->d;
481         sw_param.up.crt.q.nbytes = BN_bn2bin(q, (unsigned char *)rsa_q->d);
482         sw_param.up.crt.q.value = (unsigned char *)rsa_q->d;
483         sw_param.up.crt.dmp1.nbytes = BN_bn2bin(dmp1,
484                 (unsigned char *)rsa_dmp1->d);
485         sw_param.up.crt.dmp1.value = (unsigned char *)rsa_dmp1->d;
486         sw_param.up.crt.dmq1.nbytes = BN_bn2bin(dmq1,
487                 (unsigned char *)rsa_dmq1->d);
488         sw_param.up.crt.dmq1.value = (unsigned char *)rsa_dmq1->d;
489         sw_param.up.crt.iqmp.nbytes = BN_bn2bin(iqmp,
490                 (unsigned char *)rsa_iqmp->d);
491         sw_param.up.crt.iqmp.value = (unsigned char *)rsa_iqmp->d;
492         /* Attach the key params */
493         sw_status = p_CSwift_AttachKeyParam(hac, &sw_param);
494         switch(sw_status)
495                 {
496         case SW_OK:
497                 break;
498         case SW_ERR_INPUT_SIZE:
499                 ENGINEerr(ENGINE_F_CSWIFT_MOD_EXP_CRT,
500                         ENGINE_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
501                 goto err;
502         default:
503                 {
504                 char tmpbuf[20];
505                 ENGINEerr(ENGINE_F_CSWIFT_MOD_EXP_CRT,ENGINE_R_REQUEST_FAILED);
506                 sprintf(tmpbuf, "%ld", sw_status);
507                 ERR_add_error_data(2, "CryptoSwift error number is ",tmpbuf);
508                 }
509                 goto err;
510                 }
511         /* Prepare the argument and response */
512         arg.nbytes = BN_bn2bin(a, (unsigned char *)argument->d);
513         arg.value = (unsigned char *)argument->d;
514         res.nbytes = 2 * BN_num_bytes(p);
515         memset(result->d, 0, res.nbytes);
516         res.value = (unsigned char *)result->d;
517         /* Perform the operation */
518         if((sw_status = p_CSwift_SimpleRequest(hac, SW_CMD_MODEXP_CRT, &arg, 1,
519                 &res, 1)) != SW_OK)
520                 {
521                 char tmpbuf[20];
522                 ENGINEerr(ENGINE_F_CSWIFT_MOD_EXP_CRT,ENGINE_R_REQUEST_FAILED);
523                 sprintf(tmpbuf, "%ld", sw_status);
524                 ERR_add_error_data(2, "CryptoSwift error number is ",tmpbuf);
525                 goto err;
526                 }
527         /* Convert the response */
528         BN_bin2bn((unsigned char *)result->d, res.nbytes, r);
529         to_return = 1;
530 err:
531         if(acquired)
532                 release_context(hac);
533         BN_CTX_end(ctx);
534         return to_return;
535         }
536  
537 static int cswift_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa)
538         {
539         BN_CTX *ctx;
540         int to_return = 0;
541
542         if((ctx = BN_CTX_new()) == NULL)
543                 goto err;
544         if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
545                 {
546                 ENGINEerr(ENGINE_F_CSWIFT_RSA_MOD_EXP,ENGINE_R_MISSING_KEY_COMPONENTS);
547                 goto err;
548                 }
549         to_return = cswift_mod_exp_crt(r0, I, rsa->p, rsa->q, rsa->dmp1,
550                 rsa->dmq1, rsa->iqmp, ctx);
551 err:
552         if(ctx)
553                 BN_CTX_free(ctx);
554         return to_return;
555         }
556
557 /* This function is aliased to mod_exp (with the mont stuff dropped). */
558 static int cswift_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
559                 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
560         {
561         return cswift_mod_exp(r, a, p, m, ctx);
562         }
563
564 static DSA_SIG *cswift_dsa_sign(const unsigned char *dgst, int dlen, DSA *dsa)
565         {
566         SW_CONTEXT_HANDLE hac;
567         SW_PARAM sw_param;
568         SW_STATUS sw_status;
569         SW_LARGENUMBER arg, res;
570         unsigned char *ptr;
571         BN_CTX *ctx;
572         BIGNUM *dsa_p = NULL;
573         BIGNUM *dsa_q = NULL;
574         BIGNUM *dsa_g = NULL;
575         BIGNUM *dsa_key = NULL;
576         BIGNUM *result = NULL;
577         DSA_SIG *to_return = NULL;
578         int acquired = 0;
579
580         if((ctx = BN_CTX_new()) == NULL)
581                 goto err;
582         if(!get_context(&hac))
583                 {
584                 ENGINEerr(ENGINE_F_CSWIFT_DSA_SIGN,ENGINE_R_GET_HANDLE_FAILED);
585                 goto err;
586                 }
587         acquired = 1;
588         /* Prepare the params */
589         BN_CTX_start(ctx);
590         dsa_p = BN_CTX_get(ctx);
591         dsa_q = BN_CTX_get(ctx);
592         dsa_g = BN_CTX_get(ctx);
593         dsa_key = BN_CTX_get(ctx);
594         result = BN_CTX_get(ctx);
595         if(!result)
596                 {
597                 ENGINEerr(ENGINE_F_CSWIFT_DSA_SIGN,ENGINE_R_BN_CTX_FULL);
598                 goto err;
599                 }
600         if(!bn_wexpand(dsa_p, dsa->p->top) ||
601                         !bn_wexpand(dsa_q, dsa->q->top) ||
602                         !bn_wexpand(dsa_g, dsa->g->top) ||
603                         !bn_wexpand(dsa_key, dsa->priv_key->top) ||
604                         !bn_wexpand(result, dsa->p->top))
605                 {
606                 ENGINEerr(ENGINE_F_CSWIFT_DSA_SIGN,ENGINE_R_BN_EXPAND_FAIL);
607                 goto err;
608                 }
609         sw_param.type = SW_ALG_DSA;
610         sw_param.up.dsa.p.nbytes = BN_bn2bin(dsa->p,
611                                 (unsigned char *)dsa_p->d);
612         sw_param.up.dsa.p.value = (unsigned char *)dsa_p->d;
613         sw_param.up.dsa.q.nbytes = BN_bn2bin(dsa->q,
614                                 (unsigned char *)dsa_q->d);
615         sw_param.up.dsa.q.value = (unsigned char *)dsa_q->d;
616         sw_param.up.dsa.g.nbytes = BN_bn2bin(dsa->g,
617                                 (unsigned char *)dsa_g->d);
618         sw_param.up.dsa.g.value = (unsigned char *)dsa_g->d;
619         sw_param.up.dsa.key.nbytes = BN_bn2bin(dsa->priv_key,
620                                 (unsigned char *)dsa_key->d);
621         sw_param.up.dsa.key.value = (unsigned char *)dsa_key->d;
622         /* Attach the key params */
623         sw_status = p_CSwift_AttachKeyParam(hac, &sw_param);
624         switch(sw_status)
625                 {
626         case SW_OK:
627                 break;
628         case SW_ERR_INPUT_SIZE:
629                 ENGINEerr(ENGINE_F_CSWIFT_DSA_SIGN,
630                         ENGINE_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
631                 goto err;
632         default:
633                 {
634                 char tmpbuf[20];
635                 ENGINEerr(ENGINE_F_CSWIFT_DSA_SIGN,ENGINE_R_REQUEST_FAILED);
636                 sprintf(tmpbuf, "%ld", sw_status);
637                 ERR_add_error_data(2, "CryptoSwift error number is ",tmpbuf);
638                 }
639                 goto err;
640                 }
641         /* Prepare the argument and response */
642         arg.nbytes = dlen;
643         arg.value = (unsigned char *)dgst;
644         res.nbytes = BN_num_bytes(dsa->p);
645         memset(result->d, 0, res.nbytes);
646         res.value = (unsigned char *)result->d;
647         /* Perform the operation */
648         sw_status = p_CSwift_SimpleRequest(hac, SW_CMD_DSS_SIGN, &arg, 1,
649                 &res, 1);
650         if(sw_status != SW_OK)
651                 {
652                 char tmpbuf[20];
653                 ENGINEerr(ENGINE_F_CSWIFT_DSA_SIGN,ENGINE_R_REQUEST_FAILED);
654                 sprintf(tmpbuf, "%ld", sw_status);
655                 ERR_add_error_data(2, "CryptoSwift error number is ",tmpbuf);
656                 goto err;
657                 }
658         /* Convert the response */
659         ptr = (unsigned char *)result->d;
660         if((to_return = DSA_SIG_new()) == NULL)
661                 goto err;
662         to_return->r = BN_bin2bn((unsigned char *)result->d, 20, NULL);
663         to_return->s = BN_bin2bn((unsigned char *)result->d + 20, 20, NULL);
664
665 err:
666         if(acquired)
667                 release_context(hac);
668         if(ctx)
669                 {
670                 BN_CTX_end(ctx);
671                 BN_CTX_free(ctx);
672                 }
673         return to_return;
674         }
675
676 static int cswift_dsa_verify(const unsigned char *dgst, int dgst_len,
677                                 DSA_SIG *sig, DSA *dsa)
678         {
679         SW_CONTEXT_HANDLE hac;
680         SW_PARAM sw_param;
681         SW_STATUS sw_status;
682         SW_LARGENUMBER arg[2], res;
683         unsigned long sig_result;
684         BN_CTX *ctx;
685         BIGNUM *dsa_p = NULL;
686         BIGNUM *dsa_q = NULL;
687         BIGNUM *dsa_g = NULL;
688         BIGNUM *dsa_key = NULL;
689         BIGNUM *argument = NULL;
690         int to_return = -1;
691         int acquired = 0;
692
693         if((ctx = BN_CTX_new()) == NULL)
694                 goto err;
695         if(!get_context(&hac))
696                 {
697                 ENGINEerr(ENGINE_F_CSWIFT_DSA_VERIFY,ENGINE_R_GET_HANDLE_FAILED);
698                 goto err;
699                 }
700         acquired = 1;
701         /* Prepare the params */
702         BN_CTX_start(ctx);
703         dsa_p = BN_CTX_get(ctx);
704         dsa_q = BN_CTX_get(ctx);
705         dsa_g = BN_CTX_get(ctx);
706         dsa_key = BN_CTX_get(ctx);
707         argument = BN_CTX_get(ctx);
708         if(!argument)
709                 {
710                 ENGINEerr(ENGINE_F_CSWIFT_DSA_VERIFY,ENGINE_R_BN_CTX_FULL);
711                 goto err;
712                 }
713         if(!bn_wexpand(dsa_p, dsa->p->top) ||
714                         !bn_wexpand(dsa_q, dsa->q->top) ||
715                         !bn_wexpand(dsa_g, dsa->g->top) ||
716                         !bn_wexpand(dsa_key, dsa->pub_key->top) ||
717                         !bn_wexpand(argument, 40))
718                 {
719                 ENGINEerr(ENGINE_F_CSWIFT_DSA_VERIFY,ENGINE_R_BN_EXPAND_FAIL);
720                 goto err;
721                 }
722         sw_param.type = SW_ALG_DSA;
723         sw_param.up.dsa.p.nbytes = BN_bn2bin(dsa->p,
724                                 (unsigned char *)dsa_p->d);
725         sw_param.up.dsa.p.value = (unsigned char *)dsa_p->d;
726         sw_param.up.dsa.q.nbytes = BN_bn2bin(dsa->q,
727                                 (unsigned char *)dsa_q->d);
728         sw_param.up.dsa.q.value = (unsigned char *)dsa_q->d;
729         sw_param.up.dsa.g.nbytes = BN_bn2bin(dsa->g,
730                                 (unsigned char *)dsa_g->d);
731         sw_param.up.dsa.g.value = (unsigned char *)dsa_g->d;
732         sw_param.up.dsa.key.nbytes = BN_bn2bin(dsa->pub_key,
733                                 (unsigned char *)dsa_key->d);
734         sw_param.up.dsa.key.value = (unsigned char *)dsa_key->d;
735         /* Attach the key params */
736         sw_status = p_CSwift_AttachKeyParam(hac, &sw_param);
737         switch(sw_status)
738                 {
739         case SW_OK:
740                 break;
741         case SW_ERR_INPUT_SIZE:
742                 ENGINEerr(ENGINE_F_CSWIFT_DSA_VERIFY,
743                         ENGINE_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
744                 goto err;
745         default:
746                 {
747                 char tmpbuf[20];
748                 ENGINEerr(ENGINE_F_CSWIFT_DSA_VERIFY,ENGINE_R_REQUEST_FAILED);
749                 sprintf(tmpbuf, "%ld", sw_status);
750                 ERR_add_error_data(2, "CryptoSwift error number is ",tmpbuf);
751                 }
752                 goto err;
753                 }
754         /* Prepare the argument and response */
755         arg[0].nbytes = dgst_len;
756         arg[0].value = (unsigned char *)dgst;
757         arg[1].nbytes = 40;
758         arg[1].value = (unsigned char *)argument->d;
759         memset(arg[1].value, 0, 40);
760         BN_bn2bin(sig->r, arg[1].value + 20 - BN_num_bytes(sig->r));
761         BN_bn2bin(sig->s, arg[1].value + 40 - BN_num_bytes(sig->s));
762         res.nbytes = 4; /* unsigned long */
763         res.value = (unsigned char *)(&sig_result);
764         /* Perform the operation */
765         sw_status = p_CSwift_SimpleRequest(hac, SW_CMD_DSS_VERIFY, arg, 2,
766                 &res, 1);
767         if(sw_status != SW_OK)
768                 {
769                 char tmpbuf[20];
770                 ENGINEerr(ENGINE_F_CSWIFT_DSA_VERIFY,ENGINE_R_REQUEST_FAILED);
771                 sprintf(tmpbuf, "%ld", sw_status);
772                 ERR_add_error_data(2, "CryptoSwift error number is ",tmpbuf);
773                 goto err;
774                 }
775         /* Convert the response */
776         to_return = ((sig_result == 0) ? 0 : 1);
777
778 err:
779         if(acquired)
780                 release_context(hac);
781         if(ctx)
782                 {
783                 BN_CTX_end(ctx);
784                 BN_CTX_free(ctx);
785                 }
786         return to_return;
787         }
788
789 /* This function is aliased to mod_exp (with the dh and mont dropped). */
790 static int cswift_mod_exp_dh(const DH *dh, BIGNUM *r,
791                 const BIGNUM *a, const BIGNUM *p,
792                 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
793         {
794         return cswift_mod_exp(r, a, p, m, ctx);
795         }
796
797 #endif /* !OPENSSL_NO_HW_CSWIFT */
798 #endif /* !OPENSSL_NO_HW */