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