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