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