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