d01a037835d85e24ad505048364b37629085612f
[openssl.git] / engines / e_4758_cca.c
1 /* Author: Maurice Gittens <maurice@gittens.nl>                       */
2 /* ====================================================================
3  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer. 
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in
14  *    the documentation and/or other materials provided with the
15  *    distribution.
16  *
17  * 3. All advertising materials mentioning features or use of this
18  *    software must display the following acknowledgment:
19  *    "This product includes software developed by the OpenSSL Project
20  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
21  *
22  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23  *    endorse or promote products derived from this software without
24  *    prior written permission. For written permission, please contact
25  *    licensing@OpenSSL.org.
26  *
27  * 5. Products derived from this software may not be called "OpenSSL"
28  *    nor may "OpenSSL" appear in their names without prior written
29  *    permission of the OpenSSL Project.
30  *
31  * 6. Redistributions of any form whatsoever must retain the following
32  *    acknowledgment:
33  *    "This product includes software developed by the OpenSSL Project
34  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
35  *
36  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47  * OF THE POSSIBILITY OF SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This product includes cryptographic software written by Eric Young
51  * (eay@cryptsoft.com).  This product includes software written by Tim
52  * Hudson (tjh@cryptsoft.com).
53  *
54  */
55
56 #include <stdio.h>
57 #include <string.h>
58 #include <openssl/crypto.h>
59 #include <openssl/dso.h>
60 #include <openssl/x509.h>
61 #include <openssl/objects.h>
62 #include <openssl/engine.h>
63 #include <openssl/rand.h>
64 #include <openssl/rsa.h>
65 #include <openssl/bn.h>
66
67 #ifndef OPENSSL_NO_HW
68 #ifndef OPENSSL_NO_HW_4758_CCA
69
70 #ifdef FLAT_INC
71 #include "hw_4758_cca.h"
72 #else
73 #include "vendor_defns/hw_4758_cca.h"
74 #endif
75
76 #include "e_4758_cca_err.c"
77
78 static int ibm_4758_cca_destroy(ENGINE *e);
79 static int ibm_4758_cca_init(ENGINE *e);
80 static int ibm_4758_cca_finish(ENGINE *e);
81 static int ibm_4758_cca_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void));
82
83 /* rsa functions */
84 /*---------------*/
85 #ifndef OPENSSL_NO_RSA
86 static int cca_rsa_pub_enc(int flen, const unsigned char *from,
87                 unsigned char *to, RSA *rsa,int padding);
88 static int cca_rsa_priv_dec(int flen, const unsigned char *from,
89                 unsigned char *to, RSA *rsa,int padding);
90 static int cca_rsa_sign(int type, const unsigned char *m, unsigned int m_len,
91                 unsigned char *sigret, unsigned int *siglen, const RSA *rsa);
92 static int cca_rsa_verify(int dtype, const unsigned char *m, unsigned int m_len,
93                 unsigned char *sigbuf, unsigned int siglen, const RSA *rsa);
94
95 /* utility functions */
96 /*-----------------------*/
97 static EVP_PKEY *ibm_4758_load_privkey(ENGINE*, const char*,
98                 UI_METHOD *ui_method, void *callback_data);
99 static EVP_PKEY *ibm_4758_load_pubkey(ENGINE*, const char*,
100                 UI_METHOD *ui_method, void *callback_data);
101
102 static int getModulusAndExponent(const unsigned char *token, long *exponentLength,
103                 unsigned char *exponent, long *modulusLength,
104                 long *modulusFieldLength, unsigned char *modulus);
105 #endif
106
107 /* RAND number functions */
108 /*-----------------------*/
109 static int cca_get_random_bytes(unsigned char*, int );
110 static int cca_random_status(void);
111
112 static void cca_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
113                 int idx,long argl, void *argp);
114
115 /* Function pointers for CCA verbs */
116 /*---------------------------------*/
117 #ifndef OPENSSL_NO_RSA
118 static F_KEYRECORDREAD keyRecordRead;
119 static F_DIGITALSIGNATUREGENERATE digitalSignatureGenerate;
120 static F_DIGITALSIGNATUREVERIFY digitalSignatureVerify;
121 static F_PUBLICKEYEXTRACT publicKeyExtract;
122 static F_PKAENCRYPT pkaEncrypt;
123 static F_PKADECRYPT pkaDecrypt;
124 #endif
125 static F_RANDOMNUMBERGENERATE randomNumberGenerate;
126
127 /* static variables */
128 /*------------------*/
129 static const char *CCA4758_LIB_NAME = NULL;
130 static const char *get_CCA4758_LIB_NAME(void)
131         {
132         if(CCA4758_LIB_NAME)
133                 return CCA4758_LIB_NAME;
134         return CCA_LIB_NAME;
135         }
136 static void free_CCA4758_LIB_NAME(void)
137         {
138         if(CCA4758_LIB_NAME)
139                 OPENSSL_free((void*)CCA4758_LIB_NAME);
140         CCA4758_LIB_NAME = NULL;
141         }
142 static long set_CCA4758_LIB_NAME(const char *name)
143         {
144         free_CCA4758_LIB_NAME();
145         return (((CCA4758_LIB_NAME = BUF_strdup(name)) != NULL) ? 1 : 0);
146         }
147 #ifndef OPENSSL_NO_RSA
148 static const char* n_keyRecordRead = CSNDKRR;
149 static const char* n_digitalSignatureGenerate = CSNDDSG;
150 static const char* n_digitalSignatureVerify = CSNDDSV;
151 static const char* n_publicKeyExtract = CSNDPKX;
152 static const char* n_pkaEncrypt = CSNDPKE;
153 static const char* n_pkaDecrypt = CSNDPKD;
154 #endif
155 static const char* n_randomNumberGenerate = CSNBRNG;
156
157 static int hndidx = -1;
158 static DSO *dso = NULL;
159
160 /* openssl engine initialization structures */
161 /*------------------------------------------*/
162
163 #define CCA4758_CMD_SO_PATH             ENGINE_CMD_BASE
164 static const ENGINE_CMD_DEFN    cca4758_cmd_defns[] = {
165         {CCA4758_CMD_SO_PATH,
166                 "SO_PATH",
167                 "Specifies the path to the '4758cca' shared library",
168                 ENGINE_CMD_FLAG_STRING},
169         {0, NULL, NULL, 0}
170         };
171
172 #ifndef OPENSSL_NO_RSA
173 static RSA_METHOD ibm_4758_cca_rsa =
174         {
175         "IBM 4758 CCA RSA method",
176         cca_rsa_pub_enc,
177         NULL,
178         NULL,
179         cca_rsa_priv_dec,
180         NULL, /*rsa_mod_exp,*/
181         NULL, /*mod_exp_mont,*/
182         NULL, /* init */
183         NULL, /* finish */
184         RSA_FLAG_SIGN_VER,        /* flags */
185         NULL, /* app_data */
186         cca_rsa_sign, /* rsa_sign */
187         cca_rsa_verify, /* rsa_verify */
188         NULL /* rsa_keygen */
189         };
190 #endif
191
192 static RAND_METHOD ibm_4758_cca_rand =
193         {
194         /* "IBM 4758 RAND method", */
195         NULL, /* seed */
196         cca_get_random_bytes, /* get random bytes from the card */
197         NULL, /* cleanup */
198         NULL, /* add */
199         cca_get_random_bytes, /* pseudo rand */
200         cca_random_status, /* status */
201         };
202
203 static const char *engine_4758_cca_id = "4758cca";
204 static const char *engine_4758_cca_name = "IBM 4758 CCA hardware engine support";
205 /* Compatibility hack, the dynamic library uses this form in the path */
206 static const char *engine_4758_cca_id_alt = "4758_cca";
207
208 /* engine implementation */
209 /*-----------------------*/
210 static int bind_helper(ENGINE *e)
211         {
212         if(!ENGINE_set_id(e, engine_4758_cca_id) ||
213                         !ENGINE_set_name(e, engine_4758_cca_name) ||
214 #ifndef OPENSSL_NO_RSA
215                         !ENGINE_set_RSA(e, &ibm_4758_cca_rsa) ||
216 #endif
217                         !ENGINE_set_RAND(e, &ibm_4758_cca_rand) ||
218                         !ENGINE_set_destroy_function(e, ibm_4758_cca_destroy) ||
219                         !ENGINE_set_init_function(e, ibm_4758_cca_init) ||
220                         !ENGINE_set_finish_function(e, ibm_4758_cca_finish) ||
221                         !ENGINE_set_ctrl_function(e, ibm_4758_cca_ctrl) ||
222                         !ENGINE_set_load_privkey_function(e, ibm_4758_load_privkey) ||
223                         !ENGINE_set_load_pubkey_function(e, ibm_4758_load_pubkey) ||
224                         !ENGINE_set_cmd_defns(e, cca4758_cmd_defns))
225                 return 0;
226         /* Ensure the error handling is set up */
227         ERR_load_CCA4758_strings();
228         return 1;
229         }
230
231 #ifdef OPENSSL_NO_DYNAMIC_ENGINE
232 static ENGINE *engine_4758_cca(void)
233         {
234         ENGINE *ret = ENGINE_new();
235         if(!ret)
236                 return NULL;
237         if(!bind_helper(ret))
238                 {
239                 ENGINE_free(ret);
240                 return NULL;
241                 }
242         return ret;
243         }
244
245 void ENGINE_load_4758cca(void)
246         {
247         ENGINE *e_4758 = engine_4758_cca();
248         if (!e_4758) return;
249         ENGINE_add(e_4758);
250         ENGINE_free(e_4758);
251         ERR_clear_error();   
252         }
253 #endif
254
255 static int ibm_4758_cca_destroy(ENGINE *e)
256         {
257         ERR_unload_CCA4758_strings();
258         free_CCA4758_LIB_NAME();
259         return 1;
260         }
261
262 static int ibm_4758_cca_init(ENGINE *e)
263         {
264         if(dso)
265                 {
266                 CCA4758err(CCA4758_F_IBM_4758_CCA_INIT,CCA4758_R_ALREADY_LOADED);
267                 goto err;
268                 }
269
270         dso = DSO_load(NULL, get_CCA4758_LIB_NAME(), NULL, 0);
271         if(!dso)
272                 {
273                 CCA4758err(CCA4758_F_IBM_4758_CCA_INIT,CCA4758_R_DSO_FAILURE);
274                 goto err;
275                 }
276
277 #ifndef OPENSSL_NO_RSA
278         if(!(keyRecordRead = (F_KEYRECORDREAD)
279                                 DSO_bind_func(dso, n_keyRecordRead)) ||
280                         !(randomNumberGenerate = (F_RANDOMNUMBERGENERATE)
281                                 DSO_bind_func(dso, n_randomNumberGenerate)) ||
282                         !(digitalSignatureGenerate = (F_DIGITALSIGNATUREGENERATE)
283                                 DSO_bind_func(dso, n_digitalSignatureGenerate)) ||
284                         !(digitalSignatureVerify = (F_DIGITALSIGNATUREVERIFY)
285                                 DSO_bind_func(dso, n_digitalSignatureVerify)) ||
286                         !(publicKeyExtract = (F_PUBLICKEYEXTRACT)
287                                 DSO_bind_func(dso, n_publicKeyExtract)) ||
288                         !(pkaEncrypt = (F_PKAENCRYPT)
289                                 DSO_bind_func(dso, n_pkaEncrypt)) ||
290                         !(pkaDecrypt = (F_PKADECRYPT)
291                                 DSO_bind_func(dso, n_pkaDecrypt)))
292                 {
293                 CCA4758err(CCA4758_F_IBM_4758_CCA_INIT,CCA4758_R_DSO_FAILURE);
294                 goto err;
295                 }
296 #else
297         if(!(randomNumberGenerate = (F_RANDOMNUMBERGENERATE)
298                                 DSO_bind_func(dso, n_randomNumberGenerate)))
299                 {
300                 CCA4758err(CCA4758_F_IBM_4758_CCA_INIT,CCA4758_R_DSO_FAILURE);
301                 goto err;
302                 }
303 #endif
304
305         hndidx = RSA_get_ex_new_index(0, "IBM 4758 CCA RSA key handle",
306                 NULL, NULL, cca_ex_free);
307
308         return 1;
309 err:
310         if(dso)
311                 DSO_free(dso);
312         dso = NULL;
313
314         keyRecordRead = (F_KEYRECORDREAD)0;
315         randomNumberGenerate = (F_RANDOMNUMBERGENERATE)0;
316         digitalSignatureGenerate = (F_DIGITALSIGNATUREGENERATE)0;
317         digitalSignatureVerify = (F_DIGITALSIGNATUREVERIFY)0;
318         publicKeyExtract = (F_PUBLICKEYEXTRACT)0;
319         pkaEncrypt = (F_PKAENCRYPT)0;
320         pkaDecrypt = (F_PKADECRYPT)0;
321         return 0;
322         }
323
324 static int ibm_4758_cca_finish(ENGINE *e)
325         {
326         free_CCA4758_LIB_NAME();
327         if(!dso)
328                 {
329                 CCA4758err(CCA4758_F_IBM_4758_CCA_FINISH,
330                                 CCA4758_R_NOT_LOADED);
331                 return 0;
332                 }
333         if(!DSO_free(dso))
334                 {
335                 CCA4758err(CCA4758_F_IBM_4758_CCA_FINISH,
336                                 CCA4758_R_UNIT_FAILURE);
337                 return 0;
338                 }
339         dso = NULL;
340         keyRecordRead = (F_KEYRECORDREAD)0;
341         randomNumberGenerate = (F_RANDOMNUMBERGENERATE)0;
342         digitalSignatureGenerate = (F_DIGITALSIGNATUREGENERATE)0;
343         digitalSignatureVerify = (F_DIGITALSIGNATUREVERIFY)0;
344         publicKeyExtract = (F_PUBLICKEYEXTRACT)0;
345         pkaEncrypt = (F_PKAENCRYPT)0;
346         pkaDecrypt = (F_PKADECRYPT)0;
347         return 1;
348         }
349
350 static int ibm_4758_cca_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
351         {
352         int initialised = ((dso == NULL) ? 0 : 1);
353         switch(cmd)
354                 {
355         case CCA4758_CMD_SO_PATH:
356                 if(p == NULL)
357                         {
358                         CCA4758err(CCA4758_F_IBM_4758_CCA_CTRL,
359                                         ERR_R_PASSED_NULL_PARAMETER);
360                         return 0;
361                         }
362                 if(initialised)
363                         {
364                         CCA4758err(CCA4758_F_IBM_4758_CCA_CTRL,
365                                         CCA4758_R_ALREADY_LOADED);
366                         return 0;
367                         }
368                 return set_CCA4758_LIB_NAME((const char *)p);
369         default:
370                 break;
371                 }
372         CCA4758err(CCA4758_F_IBM_4758_CCA_CTRL,
373                         CCA4758_R_COMMAND_NOT_IMPLEMENTED);
374         return 0;
375         }
376
377 #ifndef OPENSSL_NO_RSA
378
379 #define MAX_CCA_PKA_TOKEN_SIZE 2500
380
381 static EVP_PKEY *ibm_4758_load_privkey(ENGINE* e, const char* key_id,
382                         UI_METHOD *ui_method, void *callback_data)
383         {
384         RSA *rtmp = NULL;
385         EVP_PKEY *res = NULL;
386         unsigned char* keyToken = NULL;
387         unsigned char pubKeyToken[MAX_CCA_PKA_TOKEN_SIZE];
388         long pubKeyTokenLength = MAX_CCA_PKA_TOKEN_SIZE;
389         long keyTokenLength = MAX_CCA_PKA_TOKEN_SIZE;
390         long returnCode;
391         long reasonCode;
392         long exitDataLength = 0;
393         long ruleArrayLength = 0;
394         unsigned char exitData[8];
395         unsigned char ruleArray[8];
396         unsigned char keyLabel[64];
397         unsigned long keyLabelLength = strlen(key_id);
398         unsigned char modulus[256];
399         long modulusFieldLength = sizeof(modulus);
400         long modulusLength = 0;
401         unsigned char exponent[256];
402         long exponentLength = sizeof(exponent);
403
404         if (keyLabelLength > sizeof(keyLabel))
405                 {
406                 CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY,
407                 CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
408                 return NULL;
409                 }
410
411         memset(keyLabel,' ', sizeof(keyLabel));
412         memcpy(keyLabel, key_id, keyLabelLength);
413
414         keyToken = OPENSSL_malloc(MAX_CCA_PKA_TOKEN_SIZE + sizeof(long));
415         if (!keyToken)
416                 {
417                 CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY,
418                                 ERR_R_MALLOC_FAILURE);
419                 goto err;
420                 }
421
422         keyRecordRead(&returnCode, &reasonCode, &exitDataLength,
423                 exitData, &ruleArrayLength, ruleArray, keyLabel,
424                 &keyTokenLength, keyToken+sizeof(long));
425
426         if (returnCode)
427                 {
428                 CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY,
429                         CCA4758_R_FAILED_LOADING_PRIVATE_KEY);
430                 goto err;
431                 }
432
433         publicKeyExtract(&returnCode, &reasonCode, &exitDataLength,
434                 exitData, &ruleArrayLength, ruleArray, &keyTokenLength,
435                 keyToken+sizeof(long), &pubKeyTokenLength, pubKeyToken);
436
437         if (returnCode)
438                 {
439                 CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY,
440                         CCA4758_R_FAILED_LOADING_PRIVATE_KEY);
441                 goto err;
442                 }
443
444         if (!getModulusAndExponent(pubKeyToken, &exponentLength,
445                         exponent, &modulusLength, &modulusFieldLength,
446                         modulus))
447                 {
448                 CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY,
449                         CCA4758_R_FAILED_LOADING_PRIVATE_KEY);
450                 goto err;
451                 }
452
453         (*(long*)keyToken) = keyTokenLength;
454         rtmp = RSA_new_method(e);
455         RSA_set_ex_data(rtmp, hndidx, (char *)keyToken);
456
457         rtmp->e = BN_bin2bn(exponent, exponentLength, NULL);
458         rtmp->n = BN_bin2bn(modulus, modulusFieldLength, NULL);
459         rtmp->flags |= RSA_FLAG_EXT_PKEY;
460
461         res = EVP_PKEY_new();
462         EVP_PKEY_assign_RSA(res, rtmp);
463
464         return res;
465 err:
466         if (keyToken)
467                 OPENSSL_free(keyToken);
468         if (res)
469                 EVP_PKEY_free(res);
470         if (rtmp)
471                 RSA_free(rtmp);
472         return NULL;
473         }
474
475 static EVP_PKEY *ibm_4758_load_pubkey(ENGINE* e, const char* key_id,
476                         UI_METHOD *ui_method, void *callback_data)
477         {
478         RSA *rtmp = NULL;
479         EVP_PKEY *res = NULL;
480         unsigned char* keyToken = NULL;
481         long keyTokenLength = MAX_CCA_PKA_TOKEN_SIZE;
482         long returnCode;
483         long reasonCode;
484         long exitDataLength = 0;
485         long ruleArrayLength = 0;
486         unsigned char exitData[8];
487         unsigned char ruleArray[8];
488         unsigned char keyLabel[64];
489         unsigned long keyLabelLength = strlen(key_id);
490         unsigned char modulus[512];
491         long modulusFieldLength = sizeof(modulus);
492         long modulusLength = 0;
493         unsigned char exponent[512];
494         long exponentLength = sizeof(exponent);
495
496         if (keyLabelLength > sizeof(keyLabel))
497                 {
498                 CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY,
499                         CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
500                 return NULL;
501                 }
502
503         memset(keyLabel,' ', sizeof(keyLabel));
504         memcpy(keyLabel, key_id, keyLabelLength);
505
506         keyToken = OPENSSL_malloc(MAX_CCA_PKA_TOKEN_SIZE + sizeof(long));
507         if (!keyToken)
508                 {
509                 CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY,
510                                 ERR_R_MALLOC_FAILURE);
511                 goto err;
512                 }
513
514         keyRecordRead(&returnCode, &reasonCode, &exitDataLength, exitData,
515                 &ruleArrayLength, ruleArray, keyLabel, &keyTokenLength,
516                 keyToken+sizeof(long));
517
518         if (returnCode)
519                 {
520                 CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY,
521                                 ERR_R_MALLOC_FAILURE);
522                 goto err;
523                 }
524
525         if (!getModulusAndExponent(keyToken+sizeof(long), &exponentLength,
526                         exponent, &modulusLength, &modulusFieldLength, modulus))
527                 {
528                 CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY,
529                         CCA4758_R_FAILED_LOADING_PUBLIC_KEY);
530                 goto err;
531                 }
532
533         (*(long*)keyToken) = keyTokenLength;
534         rtmp = RSA_new_method(e);
535         RSA_set_ex_data(rtmp, hndidx, (char *)keyToken);
536         rtmp->e = BN_bin2bn(exponent, exponentLength, NULL);
537         rtmp->n = BN_bin2bn(modulus, modulusFieldLength, NULL);
538         rtmp->flags |= RSA_FLAG_EXT_PKEY;
539         res = EVP_PKEY_new();
540         EVP_PKEY_assign_RSA(res, rtmp);
541
542         return res;
543 err:
544         if (keyToken)
545                 OPENSSL_free(keyToken);
546         if (res)
547                 EVP_PKEY_free(res);
548         if (rtmp)
549                 RSA_free(rtmp);
550         return NULL;
551         }
552
553 static int cca_rsa_pub_enc(int flen, const unsigned char *from,
554                         unsigned char *to, RSA *rsa,int padding)
555         {
556         long returnCode;
557         long reasonCode;
558         long lflen = flen;
559         long exitDataLength = 0;
560         unsigned char exitData[8];
561         long ruleArrayLength = 1;
562         unsigned char ruleArray[8] = "PKCS-1.2";
563         long dataStructureLength = 0;
564         unsigned char dataStructure[8];
565         long outputLength = RSA_size(rsa);
566         long keyTokenLength;
567         unsigned char* keyToken = (unsigned char*)RSA_get_ex_data(rsa, hndidx);
568
569         keyTokenLength = *(long*)keyToken;
570         keyToken+=sizeof(long);
571
572         pkaEncrypt(&returnCode, &reasonCode, &exitDataLength, exitData,
573                 &ruleArrayLength, ruleArray, &lflen, (unsigned char*)from,
574                 &dataStructureLength, dataStructure, &keyTokenLength,
575                 keyToken, &outputLength, to);
576
577         if (returnCode || reasonCode)
578                 return -(returnCode << 16 | reasonCode);
579         return outputLength;
580         }
581
582 static int cca_rsa_priv_dec(int flen, const unsigned char *from,
583                         unsigned char *to, RSA *rsa,int padding)
584         {
585         long returnCode;
586         long reasonCode;
587         long lflen = flen;
588         long exitDataLength = 0;
589         unsigned char exitData[8];
590         long ruleArrayLength = 1;
591         unsigned char ruleArray[8] = "PKCS-1.2";
592         long dataStructureLength = 0;
593         unsigned char dataStructure[8];
594         long outputLength = RSA_size(rsa);
595         long keyTokenLength;
596         unsigned char* keyToken = (unsigned char*)RSA_get_ex_data(rsa, hndidx);
597
598         keyTokenLength = *(long*)keyToken;
599         keyToken+=sizeof(long);
600
601         pkaDecrypt(&returnCode, &reasonCode, &exitDataLength, exitData,
602                 &ruleArrayLength, ruleArray, &lflen, (unsigned char*)from,
603                 &dataStructureLength, dataStructure, &keyTokenLength,
604                 keyToken, &outputLength, to);
605
606         return (returnCode | reasonCode) ? 0 : 1;
607         }
608
609 #define SSL_SIG_LEN 36
610
611 static int cca_rsa_verify(int type, const unsigned char *m, unsigned int m_len,
612                 unsigned char *sigbuf, unsigned int siglen, const RSA *rsa)
613         {
614         long returnCode;
615         long reasonCode;
616         long lsiglen = siglen;
617         long exitDataLength = 0;
618         unsigned char exitData[8];
619         long ruleArrayLength = 1;
620         unsigned char ruleArray[8] = "PKCS-1.1";
621         long keyTokenLength;
622         unsigned char* keyToken = (unsigned char*)RSA_get_ex_data(rsa, hndidx);
623         long length = SSL_SIG_LEN;
624         long keyLength ;
625         unsigned char *hashBuffer = NULL;
626         X509_SIG sig;
627         ASN1_TYPE parameter;
628         X509_ALGOR algorithm;
629         ASN1_OCTET_STRING digest;
630
631         keyTokenLength = *(long*)keyToken;
632         keyToken+=sizeof(long);
633
634         if (type == NID_md5 || type == NID_sha1)
635                 {
636                 sig.algor = &algorithm;
637                 algorithm.algorithm = OBJ_nid2obj(type);
638
639                 if (!algorithm.algorithm)
640                         {
641                         CCA4758err(CCA4758_F_CCA_RSA_VERIFY,
642                                 CCA4758_R_UNKNOWN_ALGORITHM_TYPE);
643                         return 0;
644                         }
645
646                 if (!algorithm.algorithm->length)
647                         {
648                         CCA4758err(CCA4758_F_CCA_RSA_VERIFY,
649                                 CCA4758_R_ASN1_OID_UNKNOWN_FOR_MD);
650                         return 0;
651                         }
652
653                 parameter.type = V_ASN1_NULL;
654                 parameter.value.ptr = NULL;
655                 algorithm.parameter = &parameter;
656
657                 sig.digest = &digest;
658                 sig.digest->data = (unsigned char*)m;
659                 sig.digest->length = m_len;
660
661                 length = i2d_X509_SIG(&sig, NULL);
662                 }
663
664         keyLength = RSA_size(rsa);
665
666         if (length - RSA_PKCS1_PADDING > keyLength)
667                 {
668                 CCA4758err(CCA4758_F_CCA_RSA_VERIFY,
669                         CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
670                 return 0;
671                 }
672
673         switch (type)
674                 {
675                 case NID_md5_sha1 :
676                         if (m_len != SSL_SIG_LEN)
677                                 {
678                                 CCA4758err(CCA4758_F_CCA_RSA_VERIFY,
679                                 CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
680                                 return 0;
681                                 }
682
683                         hashBuffer = (unsigned char *)m;
684                         length = m_len;
685                         break;
686                 case NID_md5 :
687                         {
688                         unsigned char *ptr;
689                         ptr = hashBuffer = OPENSSL_malloc(
690                                         (unsigned int)keyLength+1);
691                         if (!hashBuffer)
692                                 {
693                                 CCA4758err(CCA4758_F_CCA_RSA_VERIFY,
694                                                 ERR_R_MALLOC_FAILURE);
695                                 return 0;
696                                 }
697
698                         i2d_X509_SIG(&sig, &ptr);
699                         }
700                         break;
701                 case NID_sha1 :
702                         {
703                         unsigned char *ptr;
704                         ptr = hashBuffer = OPENSSL_malloc(
705                                         (unsigned int)keyLength+1);
706                         if (!hashBuffer)
707                                 {
708                                 CCA4758err(CCA4758_F_CCA_RSA_VERIFY,
709                                                 ERR_R_MALLOC_FAILURE);
710                                 return 0;
711                                 }
712                         i2d_X509_SIG(&sig, &ptr);
713                         }
714                         break;
715                 default:
716                         return 0;
717                 }
718
719         digitalSignatureVerify(&returnCode, &reasonCode, &exitDataLength,
720                 exitData, &ruleArrayLength, ruleArray, &keyTokenLength,
721                 keyToken, &length, hashBuffer, &lsiglen, sigbuf);
722
723         if (type == NID_sha1 || type == NID_md5)
724                 {
725                 OPENSSL_cleanse(hashBuffer, keyLength+1);
726                 OPENSSL_free(hashBuffer);
727                 }
728
729         return ((returnCode || reasonCode) ? 0 : 1);
730         }
731
732 #define SSL_SIG_LEN 36
733
734 static int cca_rsa_sign(int type, const unsigned char *m, unsigned int m_len,
735                 unsigned char *sigret, unsigned int *siglen, const RSA *rsa)
736         {
737         long returnCode;
738         long reasonCode;
739         long exitDataLength = 0;
740         unsigned char exitData[8];
741         long ruleArrayLength = 1;
742         unsigned char ruleArray[8] = "PKCS-1.1";
743         long outputLength=256;
744         long outputBitLength;
745         long keyTokenLength;
746         unsigned char *hashBuffer = NULL;
747         unsigned char* keyToken = (unsigned char*)RSA_get_ex_data(rsa, hndidx);
748         long length = SSL_SIG_LEN;
749         long keyLength ;
750         X509_SIG sig;
751         ASN1_TYPE parameter;
752         X509_ALGOR algorithm;
753         ASN1_OCTET_STRING digest;
754
755         keyTokenLength = *(long*)keyToken;
756         keyToken+=sizeof(long);
757
758         if (type == NID_md5 || type == NID_sha1)
759                 {
760                 sig.algor = &algorithm;
761                 algorithm.algorithm = OBJ_nid2obj(type);
762
763                 if (!algorithm.algorithm)
764                         {
765                         CCA4758err(CCA4758_F_CCA_RSA_SIGN,
766                                 CCA4758_R_UNKNOWN_ALGORITHM_TYPE);
767                         return 0;
768                         }
769
770                 if (!algorithm.algorithm->length)
771                         {
772                         CCA4758err(CCA4758_F_CCA_RSA_SIGN,
773                                 CCA4758_R_ASN1_OID_UNKNOWN_FOR_MD);
774                         return 0;
775                         }
776
777                 parameter.type = V_ASN1_NULL;
778                 parameter.value.ptr = NULL;
779                 algorithm.parameter = &parameter;
780
781                 sig.digest = &digest;
782                 sig.digest->data = (unsigned char*)m;
783                 sig.digest->length = m_len;
784
785                 length = i2d_X509_SIG(&sig, NULL);
786                 }
787
788         keyLength = RSA_size(rsa);
789
790         if (length - RSA_PKCS1_PADDING > keyLength)
791                 {
792                 CCA4758err(CCA4758_F_CCA_RSA_SIGN,
793                         CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
794                 return 0;
795                 }
796
797         switch (type)
798                 {
799                 case NID_md5_sha1 :
800                         if (m_len != SSL_SIG_LEN)
801                                 {
802                                 CCA4758err(CCA4758_F_CCA_RSA_SIGN,
803                                 CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
804                                 return 0;
805                                 }
806                         hashBuffer = (unsigned char*)m;
807                         length = m_len;
808                         break;
809                 case NID_md5 :
810                         {
811                         unsigned char *ptr;
812                         ptr = hashBuffer = OPENSSL_malloc(
813                                         (unsigned int)keyLength+1);
814                         if (!hashBuffer)
815                                 {
816                                 CCA4758err(CCA4758_F_CCA_RSA_SIGN,
817                                                 ERR_R_MALLOC_FAILURE);
818                                 return 0;
819                                 }
820                         i2d_X509_SIG(&sig, &ptr);
821                         }
822                         break;
823                 case NID_sha1 :
824                         {
825                         unsigned char *ptr;
826                         ptr = hashBuffer = OPENSSL_malloc(
827                                         (unsigned int)keyLength+1);
828                         if (!hashBuffer)
829                                 {
830                                 CCA4758err(CCA4758_F_CCA_RSA_SIGN,
831                                                 ERR_R_MALLOC_FAILURE);
832                                 return 0;
833                                 }
834                         i2d_X509_SIG(&sig, &ptr);
835                         }
836                         break;
837                 default:
838                         return 0;
839                 }
840
841         digitalSignatureGenerate(&returnCode, &reasonCode, &exitDataLength,
842                 exitData, &ruleArrayLength, ruleArray, &keyTokenLength,
843                 keyToken, &length, hashBuffer, &outputLength, &outputBitLength,
844                 sigret);
845
846         if (type == NID_sha1 || type == NID_md5)
847                 {
848                 OPENSSL_cleanse(hashBuffer, keyLength+1);
849                 OPENSSL_free(hashBuffer);
850                 }
851
852         *siglen = outputLength;
853
854         return ((returnCode || reasonCode) ? 0 : 1);
855         }
856
857 static int getModulusAndExponent(const unsigned char*token, long *exponentLength,
858                 unsigned char *exponent, long *modulusLength, long *modulusFieldLength,
859                 unsigned char *modulus)
860         {
861         unsigned long len;
862
863         if (*token++ != (char)0x1E) /* internal PKA token? */
864                 return 0;
865
866         if (*token++) /* token version must be zero */
867                 return 0;
868
869         len = *token++;
870         len = len << 8;
871         len |= (unsigned char)*token++;
872
873         token += 4; /* skip reserved bytes */
874
875         if (*token++ == (char)0x04)
876                 {
877                 if (*token++) /* token version must be zero */
878                         return 0;
879
880                 len = *token++;
881                 len = len << 8;
882                 len |= (unsigned char)*token++;
883
884                 token+=2; /* skip reserved section */
885
886                 len = *token++;
887                 len = len << 8;
888                 len |= (unsigned char)*token++;
889
890                 *exponentLength = len;
891
892                 len = *token++;
893                 len = len << 8;
894                 len |= (unsigned char)*token++;
895
896                 *modulusLength = len;
897
898                 len = *token++;
899                 len = len << 8;
900                 len |= (unsigned char)*token++;
901
902                 *modulusFieldLength = len;
903
904                 memcpy(exponent, token, *exponentLength);
905                 token+= *exponentLength;
906
907                 memcpy(modulus, token, *modulusFieldLength);
908                 return 1;
909                 }
910         return 0;
911         }
912
913 #endif /* OPENSSL_NO_RSA */
914
915 static int cca_random_status(void)
916         {
917         return 1;
918         }
919
920 static int cca_get_random_bytes(unsigned char* buf, int num)
921         {
922         long ret_code;
923         long reason_code;
924         long exit_data_length;
925         unsigned char exit_data[4];
926         unsigned char form[] = "RANDOM  ";
927         unsigned char rand_buf[8];
928
929         while(num >= (int)sizeof(rand_buf))
930                 {
931                 randomNumberGenerate(&ret_code, &reason_code, &exit_data_length,
932                         exit_data, form, rand_buf);
933                 if (ret_code)
934                         return 0;
935                 num -= sizeof(rand_buf);
936                 memcpy(buf, rand_buf, sizeof(rand_buf));
937                 buf += sizeof(rand_buf);
938                 }
939
940         if (num)
941                 {
942                 randomNumberGenerate(&ret_code, &reason_code, NULL, NULL,
943                         form, rand_buf);
944                 if (ret_code)
945                         return 0;
946                 memcpy(buf, rand_buf, num);
947                 }
948
949         return 1;
950         }
951
952 static void cca_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad, int idx,
953                 long argl, void *argp)
954         {
955         if (item)
956                 OPENSSL_free(item);
957         }
958
959 /* Goo to handle building as a dynamic engine */
960 #ifndef OPENSSL_NO_DYNAMIC_ENGINE 
961 static int bind_fn(ENGINE *e, const char *id)
962         {
963         if(id && (strcmp(id, engine_4758_cca_id) != 0) &&
964                         (strcmp(id, engine_4758_cca_id_alt) != 0))
965                 return 0;
966         if(!bind_helper(e))
967                 return 0;
968         return 1;
969         }       
970 IMPLEMENT_DYNAMIC_CHECK_FN()
971 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
972 #endif /* OPENSSL_NO_DYNAMIC_ENGINE */
973
974 #endif /* !OPENSSL_NO_HW_4758_CCA */
975 #endif /* !OPENSSL_NO_HW */