e_4758cca.c revision 296465
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, 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    if (res)
480        EVP_PKEY_free(res);
481    if (rtmp)
482        RSA_free(rtmp);
483    return NULL;
484}
485
486static EVP_PKEY *ibm_4758_load_pubkey(ENGINE *e, const char *key_id,
487                                      UI_METHOD *ui_method,
488                                      void *callback_data)
489{
490    RSA *rtmp = NULL;
491    EVP_PKEY *res = NULL;
492    unsigned char *keyToken = NULL;
493    long keyTokenLength = MAX_CCA_PKA_TOKEN_SIZE;
494    long returnCode;
495    long reasonCode;
496    long exitDataLength = 0;
497    long ruleArrayLength = 0;
498    unsigned char exitData[8];
499    unsigned char ruleArray[8];
500    unsigned char keyLabel[64];
501    unsigned long keyLabelLength = strlen(key_id);
502    unsigned char modulus[512];
503    long modulusFieldLength = sizeof(modulus);
504    long modulusLength = 0;
505    unsigned char exponent[512];
506    long exponentLength = sizeof(exponent);
507
508    if (keyLabelLength > sizeof(keyLabel)) {
509        CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY,
510                   CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
511        return NULL;
512    }
513
514    memset(keyLabel, ' ', sizeof(keyLabel));
515    memcpy(keyLabel, key_id, keyLabelLength);
516
517    keyToken = OPENSSL_malloc(MAX_CCA_PKA_TOKEN_SIZE + sizeof(long));
518    if (!keyToken) {
519        CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY, ERR_R_MALLOC_FAILURE);
520        goto err;
521    }
522
523    keyRecordRead(&returnCode, &reasonCode, &exitDataLength, exitData,
524                  &ruleArrayLength, ruleArray, keyLabel, &keyTokenLength,
525                  keyToken + sizeof(long));
526
527    if (returnCode) {
528        CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY, ERR_R_MALLOC_FAILURE);
529        goto err;
530    }
531
532    if (!getModulusAndExponent(keyToken + sizeof(long), &exponentLength,
533                               exponent, &modulusLength, &modulusFieldLength,
534                               modulus)) {
535        CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY,
536                   CCA4758_R_FAILED_LOADING_PUBLIC_KEY);
537        goto err;
538    }
539
540    (*(long *)keyToken) = keyTokenLength;
541    rtmp = RSA_new_method(e);
542    RSA_set_ex_data(rtmp, hndidx, (char *)keyToken);
543    rtmp->e = BN_bin2bn(exponent, exponentLength, NULL);
544    rtmp->n = BN_bin2bn(modulus, modulusFieldLength, NULL);
545    rtmp->flags |= RSA_FLAG_EXT_PKEY;
546    res = EVP_PKEY_new();
547    EVP_PKEY_assign_RSA(res, rtmp);
548
549    return res;
550 err:
551    if (keyToken)
552        OPENSSL_free(keyToken);
553    if (res)
554        EVP_PKEY_free(res);
555    if (rtmp)
556        RSA_free(rtmp);
557    return NULL;
558}
559
560static int cca_rsa_pub_enc(int flen, const unsigned char *from,
561                           unsigned char *to, RSA *rsa, int padding)
562{
563    long returnCode;
564    long reasonCode;
565    long lflen = flen;
566    long exitDataLength = 0;
567    unsigned char exitData[8];
568    long ruleArrayLength = 1;
569    unsigned char ruleArray[8] = "PKCS-1.2";
570    long dataStructureLength = 0;
571    unsigned char dataStructure[8];
572    long outputLength = RSA_size(rsa);
573    long keyTokenLength;
574    unsigned char *keyToken = (unsigned char *)RSA_get_ex_data(rsa, hndidx);
575
576    keyTokenLength = *(long *)keyToken;
577    keyToken += sizeof(long);
578
579    pkaEncrypt(&returnCode, &reasonCode, &exitDataLength, exitData,
580               &ruleArrayLength, ruleArray, &lflen, (unsigned char *)from,
581               &dataStructureLength, dataStructure, &keyTokenLength,
582               keyToken, &outputLength, to);
583
584    if (returnCode || reasonCode)
585        return -(returnCode << 16 | reasonCode);
586    return outputLength;
587}
588
589static int cca_rsa_priv_dec(int flen, const unsigned char *from,
590                            unsigned char *to, RSA *rsa, int padding)
591{
592    long returnCode;
593    long reasonCode;
594    long lflen = flen;
595    long exitDataLength = 0;
596    unsigned char exitData[8];
597    long ruleArrayLength = 1;
598    unsigned char ruleArray[8] = "PKCS-1.2";
599    long dataStructureLength = 0;
600    unsigned char dataStructure[8];
601    long outputLength = RSA_size(rsa);
602    long keyTokenLength;
603    unsigned char *keyToken = (unsigned char *)RSA_get_ex_data(rsa, hndidx);
604
605    keyTokenLength = *(long *)keyToken;
606    keyToken += sizeof(long);
607
608    pkaDecrypt(&returnCode, &reasonCode, &exitDataLength, exitData,
609               &ruleArrayLength, ruleArray, &lflen, (unsigned char *)from,
610               &dataStructureLength, dataStructure, &keyTokenLength,
611               keyToken, &outputLength, to);
612
613    return (returnCode | reasonCode) ? 0 : 1;
614}
615
616#   define SSL_SIG_LEN 36
617
618static int cca_rsa_verify(int type, const unsigned char *m,
619                          unsigned int m_len, unsigned char *sigbuf,
620                          unsigned int siglen, const RSA *rsa)
621{
622    long returnCode;
623    long reasonCode;
624    long lsiglen = siglen;
625    long exitDataLength = 0;
626    unsigned char exitData[8];
627    long ruleArrayLength = 1;
628    unsigned char ruleArray[8] = "PKCS-1.1";
629    long keyTokenLength;
630    unsigned char *keyToken = (unsigned char *)RSA_get_ex_data(rsa, hndidx);
631    long length = SSL_SIG_LEN;
632    long keyLength;
633    unsigned char *hashBuffer = NULL;
634    X509_SIG sig;
635    ASN1_TYPE parameter;
636    X509_ALGOR algorithm;
637    ASN1_OCTET_STRING digest;
638
639    keyTokenLength = *(long *)keyToken;
640    keyToken += sizeof(long);
641
642    if (type == NID_md5 || type == NID_sha1) {
643        sig.algor = &algorithm;
644        algorithm.algorithm = OBJ_nid2obj(type);
645
646        if (!algorithm.algorithm) {
647            CCA4758err(CCA4758_F_CCA_RSA_VERIFY,
648                       CCA4758_R_UNKNOWN_ALGORITHM_TYPE);
649            return 0;
650        }
651
652        if (!algorithm.algorithm->length) {
653            CCA4758err(CCA4758_F_CCA_RSA_VERIFY,
654                       CCA4758_R_ASN1_OID_UNKNOWN_FOR_MD);
655            return 0;
656        }
657
658        parameter.type = V_ASN1_NULL;
659        parameter.value.ptr = NULL;
660        algorithm.parameter = &parameter;
661
662        sig.digest = &digest;
663        sig.digest->data = (unsigned char *)m;
664        sig.digest->length = m_len;
665
666        length = i2d_X509_SIG(&sig, NULL);
667    }
668
669    keyLength = RSA_size(rsa);
670
671    if (length - RSA_PKCS1_PADDING > keyLength) {
672        CCA4758err(CCA4758_F_CCA_RSA_VERIFY,
673                   CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
674        return 0;
675    }
676
677    switch (type) {
678    case NID_md5_sha1:
679        if (m_len != SSL_SIG_LEN) {
680            CCA4758err(CCA4758_F_CCA_RSA_VERIFY,
681                       CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
682            return 0;
683        }
684
685        hashBuffer = (unsigned char *)m;
686        length = m_len;
687        break;
688    case NID_md5:
689        {
690            unsigned char *ptr;
691            ptr = hashBuffer = OPENSSL_malloc((unsigned int)keyLength + 1);
692            if (!hashBuffer) {
693                CCA4758err(CCA4758_F_CCA_RSA_VERIFY, ERR_R_MALLOC_FAILURE);
694                return 0;
695            }
696
697            i2d_X509_SIG(&sig, &ptr);
698        }
699        break;
700    case NID_sha1:
701        {
702            unsigned char *ptr;
703            ptr = hashBuffer = OPENSSL_malloc((unsigned int)keyLength + 1);
704            if (!hashBuffer) {
705                CCA4758err(CCA4758_F_CCA_RSA_VERIFY, ERR_R_MALLOC_FAILURE);
706                return 0;
707            }
708            i2d_X509_SIG(&sig, &ptr);
709        }
710        break;
711    default:
712        return 0;
713    }
714
715    digitalSignatureVerify(&returnCode, &reasonCode, &exitDataLength,
716                           exitData, &ruleArrayLength, ruleArray,
717                           &keyTokenLength, keyToken, &length, hashBuffer,
718                           &lsiglen, sigbuf);
719
720    if (type == NID_sha1 || type == NID_md5) {
721        OPENSSL_cleanse(hashBuffer, keyLength + 1);
722        OPENSSL_free(hashBuffer);
723    }
724
725    return ((returnCode || reasonCode) ? 0 : 1);
726}
727
728#   define SSL_SIG_LEN 36
729
730static int cca_rsa_sign(int type, const unsigned char *m, unsigned int m_len,
731                        unsigned char *sigret, unsigned int *siglen,
732                        const RSA *rsa)
733{
734    long returnCode;
735    long reasonCode;
736    long exitDataLength = 0;
737    unsigned char exitData[8];
738    long ruleArrayLength = 1;
739    unsigned char ruleArray[8] = "PKCS-1.1";
740    long outputLength = 256;
741    long outputBitLength;
742    long keyTokenLength;
743    unsigned char *hashBuffer = NULL;
744    unsigned char *keyToken = (unsigned char *)RSA_get_ex_data(rsa, hndidx);
745    long length = SSL_SIG_LEN;
746    long keyLength;
747    X509_SIG sig;
748    ASN1_TYPE parameter;
749    X509_ALGOR algorithm;
750    ASN1_OCTET_STRING digest;
751
752    keyTokenLength = *(long *)keyToken;
753    keyToken += sizeof(long);
754
755    if (type == NID_md5 || type == NID_sha1) {
756        sig.algor = &algorithm;
757        algorithm.algorithm = OBJ_nid2obj(type);
758
759        if (!algorithm.algorithm) {
760            CCA4758err(CCA4758_F_CCA_RSA_SIGN,
761                       CCA4758_R_UNKNOWN_ALGORITHM_TYPE);
762            return 0;
763        }
764
765        if (!algorithm.algorithm->length) {
766            CCA4758err(CCA4758_F_CCA_RSA_SIGN,
767                       CCA4758_R_ASN1_OID_UNKNOWN_FOR_MD);
768            return 0;
769        }
770
771        parameter.type = V_ASN1_NULL;
772        parameter.value.ptr = NULL;
773        algorithm.parameter = &parameter;
774
775        sig.digest = &digest;
776        sig.digest->data = (unsigned char *)m;
777        sig.digest->length = m_len;
778
779        length = i2d_X509_SIG(&sig, NULL);
780    }
781
782    keyLength = RSA_size(rsa);
783
784    if (length - RSA_PKCS1_PADDING > keyLength) {
785        CCA4758err(CCA4758_F_CCA_RSA_SIGN,
786                   CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
787        return 0;
788    }
789
790    switch (type) {
791    case NID_md5_sha1:
792        if (m_len != SSL_SIG_LEN) {
793            CCA4758err(CCA4758_F_CCA_RSA_SIGN,
794                       CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
795            return 0;
796        }
797        hashBuffer = (unsigned char *)m;
798        length = m_len;
799        break;
800    case NID_md5:
801        {
802            unsigned char *ptr;
803            ptr = hashBuffer = OPENSSL_malloc((unsigned int)keyLength + 1);
804            if (!hashBuffer) {
805                CCA4758err(CCA4758_F_CCA_RSA_SIGN, ERR_R_MALLOC_FAILURE);
806                return 0;
807            }
808            i2d_X509_SIG(&sig, &ptr);
809        }
810        break;
811    case NID_sha1:
812        {
813            unsigned char *ptr;
814            ptr = hashBuffer = OPENSSL_malloc((unsigned int)keyLength + 1);
815            if (!hashBuffer) {
816                CCA4758err(CCA4758_F_CCA_RSA_SIGN, ERR_R_MALLOC_FAILURE);
817                return 0;
818            }
819            i2d_X509_SIG(&sig, &ptr);
820        }
821        break;
822    default:
823        return 0;
824    }
825
826    digitalSignatureGenerate(&returnCode, &reasonCode, &exitDataLength,
827                             exitData, &ruleArrayLength, ruleArray,
828                             &keyTokenLength, keyToken, &length, hashBuffer,
829                             &outputLength, &outputBitLength, sigret);
830
831    if (type == NID_sha1 || type == NID_md5) {
832        OPENSSL_cleanse(hashBuffer, keyLength + 1);
833        OPENSSL_free(hashBuffer);
834    }
835
836    *siglen = outputLength;
837
838    return ((returnCode || reasonCode) ? 0 : 1);
839}
840
841static int getModulusAndExponent(const unsigned char *token,
842                                 long *exponentLength,
843                                 unsigned char *exponent, long *modulusLength,
844                                 long *modulusFieldLength,
845                                 unsigned char *modulus)
846{
847    unsigned long len;
848
849    if (*token++ != (char)0x1E) /* internal PKA token? */
850        return 0;
851
852    if (*token++)               /* token version must be zero */
853        return 0;
854
855    len = *token++;
856    len = len << 8;
857    len |= (unsigned char)*token++;
858
859    token += 4;                 /* skip reserved bytes */
860
861    if (*token++ == (char)0x04) {
862        if (*token++)           /* token version must be zero */
863            return 0;
864
865        len = *token++;
866        len = len << 8;
867        len |= (unsigned char)*token++;
868
869        token += 2;             /* skip reserved section */
870
871        len = *token++;
872        len = len << 8;
873        len |= (unsigned char)*token++;
874
875        *exponentLength = len;
876
877        len = *token++;
878        len = len << 8;
879        len |= (unsigned char)*token++;
880
881        *modulusLength = len;
882
883        len = *token++;
884        len = len << 8;
885        len |= (unsigned char)*token++;
886
887        *modulusFieldLength = len;
888
889        memcpy(exponent, token, *exponentLength);
890        token += *exponentLength;
891
892        memcpy(modulus, token, *modulusFieldLength);
893        return 1;
894    }
895    return 0;
896}
897
898#  endif                        /* OPENSSL_NO_RSA */
899
900static int cca_random_status(void)
901{
902    return 1;
903}
904
905static int cca_get_random_bytes(unsigned char *buf, int num)
906{
907    long ret_code;
908    long reason_code;
909    long exit_data_length;
910    unsigned char exit_data[4];
911    unsigned char form[] = "RANDOM  ";
912    unsigned char rand_buf[8];
913
914    while (num >= (int)sizeof(rand_buf)) {
915        randomNumberGenerate(&ret_code, &reason_code, &exit_data_length,
916                             exit_data, form, rand_buf);
917        if (ret_code)
918            return 0;
919        num -= sizeof(rand_buf);
920        memcpy(buf, rand_buf, sizeof(rand_buf));
921        buf += sizeof(rand_buf);
922    }
923
924    if (num) {
925        randomNumberGenerate(&ret_code, &reason_code, NULL, NULL,
926                             form, rand_buf);
927        if (ret_code)
928            return 0;
929        memcpy(buf, rand_buf, num);
930    }
931
932    return 1;
933}
934
935#  ifndef OPENSSL_NO_RSA
936static void cca_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad, int idx,
937                        long argl, void *argp)
938{
939    if (item)
940        OPENSSL_free(item);
941}
942#  endif
943
944/* Goo to handle building as a dynamic engine */
945#  ifndef OPENSSL_NO_DYNAMIC_ENGINE
946static int bind_fn(ENGINE *e, const char *id)
947{
948    if (id && (strcmp(id, engine_4758_cca_id) != 0) &&
949        (strcmp(id, engine_4758_cca_id_alt) != 0))
950        return 0;
951    if (!bind_helper(e))
952        return 0;
953    return 1;
954}
955
956IMPLEMENT_DYNAMIC_CHECK_FN()
957    IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
958#  endif                        /* OPENSSL_NO_DYNAMIC_ENGINE */
959# endif                         /* !OPENSSL_NO_HW_4758_CCA */
960#endif                          /* !OPENSSL_NO_HW */
961