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