e_4758cca.c revision 296341
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
80static int ibm_4758_cca_destroy(ENGINE *e);
81static int ibm_4758_cca_init(ENGINE *e);
82static int ibm_4758_cca_finish(ENGINE *e);
83static 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
89static int cca_rsa_pub_enc(int flen, const unsigned char *from,
90                           unsigned char *to, RSA *rsa, int padding);
91static int cca_rsa_priv_dec(int flen, const unsigned char *from,
92                            unsigned char *to, RSA *rsa, int padding);
93static 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);
96static 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/* ---------------------*/
102static EVP_PKEY *ibm_4758_load_privkey(ENGINE *, const char *,
103                                       UI_METHOD *ui_method,
104                                       void *callback_data);
105static EVP_PKEY *ibm_4758_load_pubkey(ENGINE *, const char *,
106                                      UI_METHOD *ui_method,
107                                      void *callback_data);
108
109static 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/* ---------------------*/
118static int cca_get_random_bytes(unsigned char *, int);
119static int cca_random_status(void);
120
121#  ifndef OPENSSL_NO_RSA
122static 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
129static F_KEYRECORDREAD keyRecordRead;
130static F_DIGITALSIGNATUREGENERATE digitalSignatureGenerate;
131static F_DIGITALSIGNATUREVERIFY digitalSignatureVerify;
132static F_PUBLICKEYEXTRACT publicKeyExtract;
133static F_PKAENCRYPT pkaEncrypt;
134static F_PKADECRYPT pkaDecrypt;
135#  endif
136static F_RANDOMNUMBERGENERATE randomNumberGenerate;
137
138/* static variables */
139/* ----------------*/
140static const char *CCA4758_LIB_NAME = NULL;
141static 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
148static 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
155static 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
162static const char *n_keyRecordRead = CSNDKRR;
163static const char *n_digitalSignatureGenerate = CSNDDSG;
164static const char *n_digitalSignatureVerify = CSNDDSV;
165static const char *n_publicKeyExtract = CSNDPKX;
166static const char *n_pkaEncrypt = CSNDPKE;
167static const char *n_pkaDecrypt = CSNDPKD;
168#  endif
169static const char *n_randomNumberGenerate = CSNBRNG;
170
171#  ifndef OPENSSL_NO_RSA
172static int hndidx = -1;
173#  endif
174static DSO *dso = NULL;
175
176/* openssl engine initialization structures */
177/* ----------------------------------------*/
178
179#  define CCA4758_CMD_SO_PATH             ENGINE_CMD_BASE
180static 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
189static 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
207static 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
217static const char *engine_4758_cca_id = "4758cca";
218static 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 */
222static const char *engine_4758_cca_id_alt = "4758_cca";
223#  endif
224
225/* engine implementation */
226/* ---------------------*/
227static 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
251static 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
263void 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
274static int ibm_4758_cca_destroy(ENGINE *e)
275{
276    ERR_unload_CCA4758_strings();
277    free_CCA4758_LIB_NAME();
278    return 1;
279}
280
281static 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    if (dso)
328        DSO_free(dso);
329    dso = NULL;
330
331#  ifndef OPENSSL_NO_RSA
332    keyRecordRead = (F_KEYRECORDREAD) 0;
333    digitalSignatureGenerate = (F_DIGITALSIGNATUREGENERATE) 0;
334    digitalSignatureVerify = (F_DIGITALSIGNATUREVERIFY)0;
335    publicKeyExtract = (F_PUBLICKEYEXTRACT)0;
336    pkaEncrypt = (F_PKAENCRYPT) 0;
337    pkaDecrypt = (F_PKADECRYPT) 0;
338#  endif
339    randomNumberGenerate = (F_RANDOMNUMBERGENERATE) 0;
340    return 0;
341}
342
343static int ibm_4758_cca_finish(ENGINE *e)
344{
345    free_CCA4758_LIB_NAME();
346    if (!dso) {
347        CCA4758err(CCA4758_F_IBM_4758_CCA_FINISH, CCA4758_R_NOT_LOADED);
348        return 0;
349    }
350    if (!DSO_free(dso)) {
351        CCA4758err(CCA4758_F_IBM_4758_CCA_FINISH, CCA4758_R_UNIT_FAILURE);
352        return 0;
353    }
354    dso = NULL;
355#  ifndef OPENSSL_NO_RSA
356    keyRecordRead = (F_KEYRECORDREAD) 0;
357    randomNumberGenerate = (F_RANDOMNUMBERGENERATE) 0;
358    digitalSignatureGenerate = (F_DIGITALSIGNATUREGENERATE) 0;
359    digitalSignatureVerify = (F_DIGITALSIGNATUREVERIFY)0;
360    publicKeyExtract = (F_PUBLICKEYEXTRACT)0;
361    pkaEncrypt = (F_PKAENCRYPT) 0;
362    pkaDecrypt = (F_PKADECRYPT) 0;
363#  endif
364    randomNumberGenerate = (F_RANDOMNUMBERGENERATE) 0;
365    return 1;
366}
367
368static int ibm_4758_cca_ctrl(ENGINE *e, int cmd, long i, void *p,
369                             void (*f) (void))
370{
371    int initialised = ((dso == NULL) ? 0 : 1);
372    switch (cmd) {
373    case CCA4758_CMD_SO_PATH:
374        if (p == NULL) {
375            CCA4758err(CCA4758_F_IBM_4758_CCA_CTRL,
376                       ERR_R_PASSED_NULL_PARAMETER);
377            return 0;
378        }
379        if (initialised) {
380            CCA4758err(CCA4758_F_IBM_4758_CCA_CTRL, CCA4758_R_ALREADY_LOADED);
381            return 0;
382        }
383        return set_CCA4758_LIB_NAME((const char *)p);
384    default:
385        break;
386    }
387    CCA4758err(CCA4758_F_IBM_4758_CCA_CTRL,
388               CCA4758_R_COMMAND_NOT_IMPLEMENTED);
389    return 0;
390}
391
392#  ifndef OPENSSL_NO_RSA
393
394#   define MAX_CCA_PKA_TOKEN_SIZE 2500
395
396static EVP_PKEY *ibm_4758_load_privkey(ENGINE *e, const char *key_id,
397                                       UI_METHOD *ui_method,
398                                       void *callback_data)
399{
400    RSA *rtmp = NULL;
401    EVP_PKEY *res = NULL;
402    unsigned char *keyToken = NULL;
403    unsigned char pubKeyToken[MAX_CCA_PKA_TOKEN_SIZE];
404    long pubKeyTokenLength = MAX_CCA_PKA_TOKEN_SIZE;
405    long keyTokenLength = MAX_CCA_PKA_TOKEN_SIZE;
406    long returnCode;
407    long reasonCode;
408    long exitDataLength = 0;
409    long ruleArrayLength = 0;
410    unsigned char exitData[8];
411    unsigned char ruleArray[8];
412    unsigned char keyLabel[64];
413    unsigned long keyLabelLength = strlen(key_id);
414    unsigned char modulus[256];
415    long modulusFieldLength = sizeof(modulus);
416    long modulusLength = 0;
417    unsigned char exponent[256];
418    long exponentLength = sizeof(exponent);
419
420    if (keyLabelLength > sizeof(keyLabel)) {
421        CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY,
422                   CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
423        return NULL;
424    }
425
426    memset(keyLabel, ' ', sizeof(keyLabel));
427    memcpy(keyLabel, key_id, keyLabelLength);
428
429    keyToken = OPENSSL_malloc(MAX_CCA_PKA_TOKEN_SIZE + sizeof(long));
430    if (!keyToken) {
431        CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY, ERR_R_MALLOC_FAILURE);
432        goto err;
433    }
434
435    keyRecordRead(&returnCode, &reasonCode, &exitDataLength,
436                  exitData, &ruleArrayLength, ruleArray, keyLabel,
437                  &keyTokenLength, keyToken + sizeof(long));
438
439    if (returnCode) {
440        CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY,
441                   CCA4758_R_FAILED_LOADING_PRIVATE_KEY);
442        goto err;
443    }
444
445    publicKeyExtract(&returnCode, &reasonCode, &exitDataLength,
446                     exitData, &ruleArrayLength, ruleArray, &keyTokenLength,
447                     keyToken + sizeof(long), &pubKeyTokenLength,
448                     pubKeyToken);
449
450    if (returnCode) {
451        CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY,
452                   CCA4758_R_FAILED_LOADING_PRIVATE_KEY);
453        goto err;
454    }
455
456    if (!getModulusAndExponent(pubKeyToken, &exponentLength,
457                               exponent, &modulusLength, &modulusFieldLength,
458                               modulus)) {
459        CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY,
460                   CCA4758_R_FAILED_LOADING_PRIVATE_KEY);
461        goto err;
462    }
463
464    (*(long *)keyToken) = keyTokenLength;
465    rtmp = RSA_new_method(e);
466    RSA_set_ex_data(rtmp, hndidx, (char *)keyToken);
467
468    rtmp->e = BN_bin2bn(exponent, exponentLength, NULL);
469    rtmp->n = BN_bin2bn(modulus, modulusFieldLength, NULL);
470    rtmp->flags |= RSA_FLAG_EXT_PKEY;
471
472    res = EVP_PKEY_new();
473    EVP_PKEY_assign_RSA(res, rtmp);
474
475    return res;
476 err:
477    if (keyToken)
478        OPENSSL_free(keyToken);
479    return NULL;
480}
481
482static EVP_PKEY *ibm_4758_load_pubkey(ENGINE *e, const char *key_id,
483                                      UI_METHOD *ui_method,
484                                      void *callback_data)
485{
486    RSA *rtmp = NULL;
487    EVP_PKEY *res = NULL;
488    unsigned char *keyToken = NULL;
489    long keyTokenLength = MAX_CCA_PKA_TOKEN_SIZE;
490    long returnCode;
491    long reasonCode;
492    long exitDataLength = 0;
493    long ruleArrayLength = 0;
494    unsigned char exitData[8];
495    unsigned char ruleArray[8];
496    unsigned char keyLabel[64];
497    unsigned long keyLabelLength = strlen(key_id);
498    unsigned char modulus[512];
499    long modulusFieldLength = sizeof(modulus);
500    long modulusLength = 0;
501    unsigned char exponent[512];
502    long exponentLength = sizeof(exponent);
503
504    if (keyLabelLength > sizeof(keyLabel)) {
505        CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY,
506                   CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
507        return NULL;
508    }
509
510    memset(keyLabel, ' ', sizeof(keyLabel));
511    memcpy(keyLabel, key_id, keyLabelLength);
512
513    keyToken = OPENSSL_malloc(MAX_CCA_PKA_TOKEN_SIZE + sizeof(long));
514    if (!keyToken) {
515        CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY, ERR_R_MALLOC_FAILURE);
516        goto err;
517    }
518
519    keyRecordRead(&returnCode, &reasonCode, &exitDataLength, exitData,
520                  &ruleArrayLength, ruleArray, keyLabel, &keyTokenLength,
521                  keyToken + sizeof(long));
522
523    if (returnCode) {
524        CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY, ERR_R_MALLOC_FAILURE);
525        goto err;
526    }
527
528    if (!getModulusAndExponent(keyToken + sizeof(long), &exponentLength,
529                               exponent, &modulusLength, &modulusFieldLength,
530                               modulus)) {
531        CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY,
532                   CCA4758_R_FAILED_LOADING_PUBLIC_KEY);
533        goto err;
534    }
535
536    (*(long *)keyToken) = keyTokenLength;
537    rtmp = RSA_new_method(e);
538    RSA_set_ex_data(rtmp, hndidx, (char *)keyToken);
539    rtmp->e = BN_bin2bn(exponent, exponentLength, NULL);
540    rtmp->n = BN_bin2bn(modulus, modulusFieldLength, NULL);
541    rtmp->flags |= RSA_FLAG_EXT_PKEY;
542    res = EVP_PKEY_new();
543    EVP_PKEY_assign_RSA(res, rtmp);
544
545    return res;
546 err:
547    if (keyToken)
548        OPENSSL_free(keyToken);
549    return NULL;
550}
551
552static int cca_rsa_pub_enc(int flen, const unsigned char *from,
553                           unsigned char *to, RSA *rsa, int padding)
554{
555    long returnCode;
556    long reasonCode;
557    long lflen = flen;
558    long exitDataLength = 0;
559    unsigned char exitData[8];
560    long ruleArrayLength = 1;
561    unsigned char ruleArray[8] = "PKCS-1.2";
562    long dataStructureLength = 0;
563    unsigned char dataStructure[8];
564    long outputLength = RSA_size(rsa);
565    long keyTokenLength;
566    unsigned char *keyToken = (unsigned char *)RSA_get_ex_data(rsa, hndidx);
567
568    keyTokenLength = *(long *)keyToken;
569    keyToken += sizeof(long);
570
571    pkaEncrypt(&returnCode, &reasonCode, &exitDataLength, exitData,
572               &ruleArrayLength, ruleArray, &lflen, (unsigned char *)from,
573               &dataStructureLength, dataStructure, &keyTokenLength,
574               keyToken, &outputLength, to);
575
576    if (returnCode || reasonCode)
577        return -(returnCode << 16 | reasonCode);
578    return outputLength;
579}
580
581static int cca_rsa_priv_dec(int flen, const unsigned char *from,
582                            unsigned char *to, RSA *rsa, int padding)
583{
584    long returnCode;
585    long reasonCode;
586    long lflen = flen;
587    long exitDataLength = 0;
588    unsigned char exitData[8];
589    long ruleArrayLength = 1;
590    unsigned char ruleArray[8] = "PKCS-1.2";
591    long dataStructureLength = 0;
592    unsigned char dataStructure[8];
593    long outputLength = RSA_size(rsa);
594    long keyTokenLength;
595    unsigned char *keyToken = (unsigned char *)RSA_get_ex_data(rsa, hndidx);
596
597    keyTokenLength = *(long *)keyToken;
598    keyToken += sizeof(long);
599
600    pkaDecrypt(&returnCode, &reasonCode, &exitDataLength, exitData,
601               &ruleArrayLength, ruleArray, &lflen, (unsigned char *)from,
602               &dataStructureLength, dataStructure, &keyTokenLength,
603               keyToken, &outputLength, to);
604
605    return (returnCode | reasonCode) ? 0 : 1;
606}
607
608#   define SSL_SIG_LEN 36
609
610static int cca_rsa_verify(int type, const unsigned char *m,
611                          unsigned int m_len, const unsigned char *sigbuf,
612                          unsigned int siglen, const RSA *rsa)
613{
614    long returnCode;
615    long reasonCode;
616    long lsiglen = siglen;
617    long exitDataLength = 0;
618    unsigned char exitData[8];
619    long ruleArrayLength = 1;
620    unsigned char ruleArray[8] = "PKCS-1.1";
621    long keyTokenLength;
622    unsigned char *keyToken = (unsigned char *)RSA_get_ex_data(rsa, hndidx);
623    long length = SSL_SIG_LEN;
624    long keyLength;
625    unsigned char *hashBuffer = NULL;
626    X509_SIG sig;
627    ASN1_TYPE parameter;
628    X509_ALGOR algorithm;
629    ASN1_OCTET_STRING digest;
630
631    keyTokenLength = *(long *)keyToken;
632    keyToken += sizeof(long);
633
634    if (type == NID_md5 || type == NID_sha1) {
635        sig.algor = &algorithm;
636        algorithm.algorithm = OBJ_nid2obj(type);
637
638        if (!algorithm.algorithm) {
639            CCA4758err(CCA4758_F_CCA_RSA_VERIFY,
640                       CCA4758_R_UNKNOWN_ALGORITHM_TYPE);
641            return 0;
642        }
643
644        if (!algorithm.algorithm->length) {
645            CCA4758err(CCA4758_F_CCA_RSA_VERIFY,
646                       CCA4758_R_ASN1_OID_UNKNOWN_FOR_MD);
647            return 0;
648        }
649
650        parameter.type = V_ASN1_NULL;
651        parameter.value.ptr = NULL;
652        algorithm.parameter = &parameter;
653
654        sig.digest = &digest;
655        sig.digest->data = (unsigned char *)m;
656        sig.digest->length = m_len;
657
658        length = i2d_X509_SIG(&sig, NULL);
659    }
660
661    keyLength = RSA_size(rsa);
662
663    if (length - RSA_PKCS1_PADDING > keyLength) {
664        CCA4758err(CCA4758_F_CCA_RSA_VERIFY,
665                   CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
666        return 0;
667    }
668
669    switch (type) {
670    case NID_md5_sha1:
671        if (m_len != SSL_SIG_LEN) {
672            CCA4758err(CCA4758_F_CCA_RSA_VERIFY,
673                       CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
674            return 0;
675        }
676
677        hashBuffer = (unsigned char *)m;
678        length = m_len;
679        break;
680    case NID_md5:
681        {
682            unsigned char *ptr;
683            ptr = hashBuffer = OPENSSL_malloc((unsigned int)keyLength + 1);
684            if (!hashBuffer) {
685                CCA4758err(CCA4758_F_CCA_RSA_VERIFY, ERR_R_MALLOC_FAILURE);
686                return 0;
687            }
688
689            i2d_X509_SIG(&sig, &ptr);
690        }
691        break;
692    case NID_sha1:
693        {
694            unsigned char *ptr;
695            ptr = hashBuffer = OPENSSL_malloc((unsigned int)keyLength + 1);
696            if (!hashBuffer) {
697                CCA4758err(CCA4758_F_CCA_RSA_VERIFY, ERR_R_MALLOC_FAILURE);
698                return 0;
699            }
700            i2d_X509_SIG(&sig, &ptr);
701        }
702        break;
703    default:
704        return 0;
705    }
706
707    digitalSignatureVerify(&returnCode, &reasonCode, &exitDataLength,
708                           exitData, &ruleArrayLength, ruleArray,
709                           &keyTokenLength, keyToken, &length, hashBuffer,
710                           &lsiglen, (unsigned char *)sigbuf);
711
712    if (type == NID_sha1 || type == NID_md5) {
713        OPENSSL_cleanse(hashBuffer, keyLength + 1);
714        OPENSSL_free(hashBuffer);
715    }
716
717    return ((returnCode || reasonCode) ? 0 : 1);
718}
719
720#   define SSL_SIG_LEN 36
721
722static int cca_rsa_sign(int type, const unsigned char *m, unsigned int m_len,
723                        unsigned char *sigret, unsigned int *siglen,
724                        const RSA *rsa)
725{
726    long returnCode;
727    long reasonCode;
728    long exitDataLength = 0;
729    unsigned char exitData[8];
730    long ruleArrayLength = 1;
731    unsigned char ruleArray[8] = "PKCS-1.1";
732    long outputLength = 256;
733    long outputBitLength;
734    long keyTokenLength;
735    unsigned char *hashBuffer = NULL;
736    unsigned char *keyToken = (unsigned char *)RSA_get_ex_data(rsa, hndidx);
737    long length = SSL_SIG_LEN;
738    long keyLength;
739    X509_SIG sig;
740    ASN1_TYPE parameter;
741    X509_ALGOR algorithm;
742    ASN1_OCTET_STRING digest;
743
744    keyTokenLength = *(long *)keyToken;
745    keyToken += sizeof(long);
746
747    if (type == NID_md5 || type == NID_sha1) {
748        sig.algor = &algorithm;
749        algorithm.algorithm = OBJ_nid2obj(type);
750
751        if (!algorithm.algorithm) {
752            CCA4758err(CCA4758_F_CCA_RSA_SIGN,
753                       CCA4758_R_UNKNOWN_ALGORITHM_TYPE);
754            return 0;
755        }
756
757        if (!algorithm.algorithm->length) {
758            CCA4758err(CCA4758_F_CCA_RSA_SIGN,
759                       CCA4758_R_ASN1_OID_UNKNOWN_FOR_MD);
760            return 0;
761        }
762
763        parameter.type = V_ASN1_NULL;
764        parameter.value.ptr = NULL;
765        algorithm.parameter = &parameter;
766
767        sig.digest = &digest;
768        sig.digest->data = (unsigned char *)m;
769        sig.digest->length = m_len;
770
771        length = i2d_X509_SIG(&sig, NULL);
772    }
773
774    keyLength = RSA_size(rsa);
775
776    if (length - RSA_PKCS1_PADDING > keyLength) {
777        CCA4758err(CCA4758_F_CCA_RSA_SIGN,
778                   CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
779        return 0;
780    }
781
782    switch (type) {
783    case NID_md5_sha1:
784        if (m_len != SSL_SIG_LEN) {
785            CCA4758err(CCA4758_F_CCA_RSA_SIGN,
786                       CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
787            return 0;
788        }
789        hashBuffer = (unsigned char *)m;
790        length = m_len;
791        break;
792    case NID_md5:
793        {
794            unsigned char *ptr;
795            ptr = hashBuffer = OPENSSL_malloc((unsigned int)keyLength + 1);
796            if (!hashBuffer) {
797                CCA4758err(CCA4758_F_CCA_RSA_SIGN, ERR_R_MALLOC_FAILURE);
798                return 0;
799            }
800            i2d_X509_SIG(&sig, &ptr);
801        }
802        break;
803    case NID_sha1:
804        {
805            unsigned char *ptr;
806            ptr = hashBuffer = OPENSSL_malloc((unsigned int)keyLength + 1);
807            if (!hashBuffer) {
808                CCA4758err(CCA4758_F_CCA_RSA_SIGN, ERR_R_MALLOC_FAILURE);
809                return 0;
810            }
811            i2d_X509_SIG(&sig, &ptr);
812        }
813        break;
814    default:
815        return 0;
816    }
817
818    digitalSignatureGenerate(&returnCode, &reasonCode, &exitDataLength,
819                             exitData, &ruleArrayLength, ruleArray,
820                             &keyTokenLength, keyToken, &length, hashBuffer,
821                             &outputLength, &outputBitLength, sigret);
822
823    if (type == NID_sha1 || type == NID_md5) {
824        OPENSSL_cleanse(hashBuffer, keyLength + 1);
825        OPENSSL_free(hashBuffer);
826    }
827
828    *siglen = outputLength;
829
830    return ((returnCode || reasonCode) ? 0 : 1);
831}
832
833static int getModulusAndExponent(const unsigned char *token,
834                                 long *exponentLength,
835                                 unsigned char *exponent, long *modulusLength,
836                                 long *modulusFieldLength,
837                                 unsigned char *modulus)
838{
839    unsigned long len;
840
841    if (*token++ != (char)0x1E) /* internal PKA token? */
842        return 0;
843
844    if (*token++)               /* token version must be zero */
845        return 0;
846
847    len = *token++;
848    len = len << 8;
849    len |= (unsigned char)*token++;
850
851    token += 4;                 /* skip reserved bytes */
852
853    if (*token++ == (char)0x04) {
854        if (*token++)           /* token version must be zero */
855            return 0;
856
857        len = *token++;
858        len = len << 8;
859        len |= (unsigned char)*token++;
860
861        token += 2;             /* skip reserved section */
862
863        len = *token++;
864        len = len << 8;
865        len |= (unsigned char)*token++;
866
867        *exponentLength = len;
868
869        len = *token++;
870        len = len << 8;
871        len |= (unsigned char)*token++;
872
873        *modulusLength = len;
874
875        len = *token++;
876        len = len << 8;
877        len |= (unsigned char)*token++;
878
879        *modulusFieldLength = len;
880
881        memcpy(exponent, token, *exponentLength);
882        token += *exponentLength;
883
884        memcpy(modulus, token, *modulusFieldLength);
885        return 1;
886    }
887    return 0;
888}
889
890#  endif                        /* OPENSSL_NO_RSA */
891
892static int cca_random_status(void)
893{
894    return 1;
895}
896
897static int cca_get_random_bytes(unsigned char *buf, int num)
898{
899    long ret_code;
900    long reason_code;
901    long exit_data_length;
902    unsigned char exit_data[4];
903    unsigned char form[] = "RANDOM  ";
904    unsigned char rand_buf[8];
905
906    while (num >= (int)sizeof(rand_buf)) {
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        randomNumberGenerate(&ret_code, &reason_code, NULL, NULL,
918                             form, rand_buf);
919        if (ret_code)
920            return 0;
921        memcpy(buf, rand_buf, num);
922    }
923
924    return 1;
925}
926
927#  ifndef OPENSSL_NO_RSA
928static 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#  endif
935
936/* Goo to handle building as a dynamic engine */
937#  ifndef OPENSSL_NO_DYNAMIC_ENGINE
938static int bind_fn(ENGINE *e, const char *id)
939{
940    if (id && (strcmp(id, engine_4758_cca_id) != 0) &&
941        (strcmp(id, engine_4758_cca_id_alt) != 0))
942        return 0;
943    if (!bind_helper(e))
944        return 0;
945    return 1;
946}
947
948IMPLEMENT_DYNAMIC_CHECK_FN()
949    IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
950#  endif                        /* OPENSSL_NO_DYNAMIC_ENGINE */
951# endif                         /* !OPENSSL_NO_HW_4758_CCA */
952#endif                          /* !OPENSSL_NO_HW */
953