1160814Ssimon/* Author: Maurice Gittens <maurice@gittens.nl>                       */
2160814Ssimon/* ====================================================================
3160814Ssimon * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
4160814Ssimon *
5160814Ssimon * Redistribution and use in source and binary forms, with or without
6160814Ssimon * modification, are permitted provided that the following conditions
7160814Ssimon * are met:
8160814Ssimon *
9160814Ssimon * 1. Redistributions of source code must retain the above copyright
10280297Sjkim *    notice, this list of conditions and the following disclaimer.
11160814Ssimon *
12160814Ssimon * 2. Redistributions in binary form must reproduce the above copyright
13160814Ssimon *    notice, this list of conditions and the following disclaimer in
14160814Ssimon *    the documentation and/or other materials provided with the
15160814Ssimon *    distribution.
16160814Ssimon *
17160814Ssimon * 3. All advertising materials mentioning features or use of this
18160814Ssimon *    software must display the following acknowledgment:
19160814Ssimon *    "This product includes software developed by the OpenSSL Project
20160814Ssimon *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
21160814Ssimon *
22160814Ssimon * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23160814Ssimon *    endorse or promote products derived from this software without
24160814Ssimon *    prior written permission. For written permission, please contact
25160814Ssimon *    licensing@OpenSSL.org.
26160814Ssimon *
27160814Ssimon * 5. Products derived from this software may not be called "OpenSSL"
28160814Ssimon *    nor may "OpenSSL" appear in their names without prior written
29160814Ssimon *    permission of the OpenSSL Project.
30160814Ssimon *
31160814Ssimon * 6. Redistributions of any form whatsoever must retain the following
32160814Ssimon *    acknowledgment:
33160814Ssimon *    "This product includes software developed by the OpenSSL Project
34160814Ssimon *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
35160814Ssimon *
36160814Ssimon * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37160814Ssimon * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38160814Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39160814Ssimon * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
40160814Ssimon * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41160814Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42160814Ssimon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43160814Ssimon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44160814Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45160814Ssimon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46160814Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47160814Ssimon * OF THE POSSIBILITY OF SUCH DAMAGE.
48160814Ssimon * ====================================================================
49160814Ssimon *
50160814Ssimon * This product includes cryptographic software written by Eric Young
51160814Ssimon * (eay@cryptsoft.com).  This product includes software written by Tim
52160814Ssimon * Hudson (tjh@cryptsoft.com).
53160814Ssimon *
54160814Ssimon */
55160814Ssimon
56160814Ssimon#include <stdio.h>
57160814Ssimon#include <string.h>
58160814Ssimon#include <openssl/crypto.h>
59160814Ssimon#include <openssl/dso.h>
60160814Ssimon#include <openssl/x509.h>
61160814Ssimon#include <openssl/objects.h>
62160814Ssimon#include <openssl/engine.h>
63160814Ssimon#include <openssl/rand.h>
64160814Ssimon#ifndef OPENSSL_NO_RSA
65280297Sjkim# include <openssl/rsa.h>
66160814Ssimon#endif
67160814Ssimon#include <openssl/bn.h>
68160814Ssimon
69160814Ssimon#ifndef OPENSSL_NO_HW
70280297Sjkim# ifndef OPENSSL_NO_HW_4758_CCA
71160814Ssimon
72280297Sjkim#  ifdef FLAT_INC
73280297Sjkim#   include "hw_4758_cca.h"
74280297Sjkim#  else
75280297Sjkim#   include "vendor_defns/hw_4758_cca.h"
76280297Sjkim#  endif
77160814Ssimon
78280297Sjkim#  include "e_4758cca_err.c"
79160814Ssimon
80160814Ssimonstatic int ibm_4758_cca_destroy(ENGINE *e);
81160814Ssimonstatic int ibm_4758_cca_init(ENGINE *e);
82160814Ssimonstatic int ibm_4758_cca_finish(ENGINE *e);
83280297Sjkimstatic int ibm_4758_cca_ctrl(ENGINE *e, int cmd, long i, void *p,
84280297Sjkim                             void (*f) (void));
85160814Ssimon
86160814Ssimon/* rsa functions */
87280297Sjkim/* -------------*/
88280297Sjkim#  ifndef OPENSSL_NO_RSA
89160814Ssimonstatic int cca_rsa_pub_enc(int flen, const unsigned char *from,
90280297Sjkim                           unsigned char *to, RSA *rsa, int padding);
91160814Ssimonstatic int cca_rsa_priv_dec(int flen, const unsigned char *from,
92280297Sjkim                            unsigned char *to, RSA *rsa, int padding);
93160814Ssimonstatic int cca_rsa_sign(int type, const unsigned char *m, unsigned int m_len,
94280297Sjkim                        unsigned char *sigret, unsigned int *siglen,
95280297Sjkim                        const RSA *rsa);
96280297Sjkimstatic int cca_rsa_verify(int dtype, const unsigned char *m,
97280297Sjkim                          unsigned int m_len, const unsigned char *sigbuf,
98280297Sjkim                          unsigned int siglen, const RSA *rsa);
99160814Ssimon
100160814Ssimon/* utility functions */
101280297Sjkim/* ---------------------*/
102280297Sjkimstatic EVP_PKEY *ibm_4758_load_privkey(ENGINE *, const char *,
103280297Sjkim                                       UI_METHOD *ui_method,
104280297Sjkim                                       void *callback_data);
105280297Sjkimstatic EVP_PKEY *ibm_4758_load_pubkey(ENGINE *, const char *,
106280297Sjkim                                      UI_METHOD *ui_method,
107280297Sjkim                                      void *callback_data);
108160814Ssimon
109280297Sjkimstatic int getModulusAndExponent(const unsigned char *token,
110280297Sjkim                                 long *exponentLength,
111280297Sjkim                                 unsigned char *exponent, long *modulusLength,
112280297Sjkim                                 long *modulusFieldLength,
113280297Sjkim                                 unsigned char *modulus);
114280297Sjkim#  endif
115160814Ssimon
116160814Ssimon/* RAND number functions */
117280297Sjkim/* ---------------------*/
118280297Sjkimstatic int cca_get_random_bytes(unsigned char *, int);
119160814Ssimonstatic int cca_random_status(void);
120160814Ssimon
121280297Sjkim#  ifndef OPENSSL_NO_RSA
122160814Ssimonstatic void cca_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
123280297Sjkim                        int idx, long argl, void *argp);
124280297Sjkim#  endif
125160814Ssimon
126160814Ssimon/* Function pointers for CCA verbs */
127280297Sjkim/* -------------------------------*/
128280297Sjkim#  ifndef OPENSSL_NO_RSA
129160814Ssimonstatic F_KEYRECORDREAD keyRecordRead;
130160814Ssimonstatic F_DIGITALSIGNATUREGENERATE digitalSignatureGenerate;
131160814Ssimonstatic F_DIGITALSIGNATUREVERIFY digitalSignatureVerify;
132160814Ssimonstatic F_PUBLICKEYEXTRACT publicKeyExtract;
133160814Ssimonstatic F_PKAENCRYPT pkaEncrypt;
134160814Ssimonstatic F_PKADECRYPT pkaDecrypt;
135280297Sjkim#  endif
136160814Ssimonstatic F_RANDOMNUMBERGENERATE randomNumberGenerate;
137160814Ssimon
138160814Ssimon/* static variables */
139280297Sjkim/* ----------------*/
140160814Ssimonstatic const char *CCA4758_LIB_NAME = NULL;
141160814Ssimonstatic const char *get_CCA4758_LIB_NAME(void)
142280297Sjkim{
143280297Sjkim    if (CCA4758_LIB_NAME)
144280297Sjkim        return CCA4758_LIB_NAME;
145280297Sjkim    return CCA_LIB_NAME;
146280297Sjkim}
147280297Sjkim
148160814Ssimonstatic void free_CCA4758_LIB_NAME(void)
149280297Sjkim{
150280297Sjkim    if (CCA4758_LIB_NAME)
151280297Sjkim        OPENSSL_free((void *)CCA4758_LIB_NAME);
152280297Sjkim    CCA4758_LIB_NAME = NULL;
153280297Sjkim}
154280297Sjkim
155160814Ssimonstatic long set_CCA4758_LIB_NAME(const char *name)
156280297Sjkim{
157280297Sjkim    free_CCA4758_LIB_NAME();
158280297Sjkim    return (((CCA4758_LIB_NAME = BUF_strdup(name)) != NULL) ? 1 : 0);
159280297Sjkim}
160160814Ssimon
161280297Sjkim#  ifndef OPENSSL_NO_RSA
162280297Sjkimstatic const char *n_keyRecordRead = CSNDKRR;
163280297Sjkimstatic const char *n_digitalSignatureGenerate = CSNDDSG;
164280297Sjkimstatic const char *n_digitalSignatureVerify = CSNDDSV;
165280297Sjkimstatic const char *n_publicKeyExtract = CSNDPKX;
166280297Sjkimstatic const char *n_pkaEncrypt = CSNDPKE;
167280297Sjkimstatic const char *n_pkaDecrypt = CSNDPKD;
168280297Sjkim#  endif
169280297Sjkimstatic const char *n_randomNumberGenerate = CSNBRNG;
170280297Sjkim
171280297Sjkim#  ifndef OPENSSL_NO_RSA
172160814Ssimonstatic int hndidx = -1;
173280297Sjkim#  endif
174160814Ssimonstatic DSO *dso = NULL;
175160814Ssimon
176160814Ssimon/* openssl engine initialization structures */
177280297Sjkim/* ----------------------------------------*/
178160814Ssimon
179280297Sjkim#  define CCA4758_CMD_SO_PATH             ENGINE_CMD_BASE
180280297Sjkimstatic const ENGINE_CMD_DEFN cca4758_cmd_defns[] = {
181280297Sjkim    {CCA4758_CMD_SO_PATH,
182280297Sjkim     "SO_PATH",
183280297Sjkim     "Specifies the path to the '4758cca' shared library",
184280297Sjkim     ENGINE_CMD_FLAG_STRING},
185280297Sjkim    {0, NULL, NULL, 0}
186280297Sjkim};
187160814Ssimon
188280297Sjkim#  ifndef OPENSSL_NO_RSA
189280297Sjkimstatic RSA_METHOD ibm_4758_cca_rsa = {
190280297Sjkim    "IBM 4758 CCA RSA method",
191280297Sjkim    cca_rsa_pub_enc,
192280297Sjkim    NULL,
193280297Sjkim    NULL,
194280297Sjkim    cca_rsa_priv_dec,
195280297Sjkim    NULL,                       /* rsa_mod_exp, */
196280297Sjkim    NULL,                       /* mod_exp_mont, */
197280297Sjkim    NULL,                       /* init */
198280297Sjkim    NULL,                       /* finish */
199280297Sjkim    RSA_FLAG_SIGN_VER,          /* flags */
200280297Sjkim    NULL,                       /* app_data */
201280297Sjkim    cca_rsa_sign,               /* rsa_sign */
202280297Sjkim    cca_rsa_verify,             /* rsa_verify */
203280297Sjkim    NULL                        /* rsa_keygen */
204280297Sjkim};
205280297Sjkim#  endif
206160814Ssimon
207280297Sjkimstatic RAND_METHOD ibm_4758_cca_rand = {
208280297Sjkim    /* "IBM 4758 RAND method", */
209280297Sjkim    NULL,                       /* seed */
210280297Sjkim    cca_get_random_bytes,       /* get random bytes from the card */
211280297Sjkim    NULL,                       /* cleanup */
212280297Sjkim    NULL,                       /* add */
213280297Sjkim    cca_get_random_bytes,       /* pseudo rand */
214280297Sjkim    cca_random_status,          /* status */
215280297Sjkim};
216160814Ssimon
217160814Ssimonstatic const char *engine_4758_cca_id = "4758cca";
218280297Sjkimstatic const char *engine_4758_cca_name =
219280297Sjkim    "IBM 4758 CCA hardware engine support";
220280297Sjkim#  ifndef OPENSSL_NO_DYNAMIC_ENGINE
221160814Ssimon/* Compatibility hack, the dynamic library uses this form in the path */
222160814Ssimonstatic const char *engine_4758_cca_id_alt = "4758_cca";
223280297Sjkim#  endif
224160814Ssimon
225160814Ssimon/* engine implementation */
226280297Sjkim/* ---------------------*/
227160814Ssimonstatic int bind_helper(ENGINE *e)
228280297Sjkim{
229280297Sjkim    if (!ENGINE_set_id(e, engine_4758_cca_id) ||
230280297Sjkim        !ENGINE_set_name(e, engine_4758_cca_name) ||
231280297Sjkim#  ifndef OPENSSL_NO_RSA
232280297Sjkim        !ENGINE_set_RSA(e, &ibm_4758_cca_rsa) ||
233280297Sjkim#  endif
234280297Sjkim        !ENGINE_set_RAND(e, &ibm_4758_cca_rand) ||
235280297Sjkim        !ENGINE_set_destroy_function(e, ibm_4758_cca_destroy) ||
236280297Sjkim        !ENGINE_set_init_function(e, ibm_4758_cca_init) ||
237280297Sjkim        !ENGINE_set_finish_function(e, ibm_4758_cca_finish) ||
238280297Sjkim        !ENGINE_set_ctrl_function(e, ibm_4758_cca_ctrl) ||
239280297Sjkim#  ifndef OPENSSL_NO_RSA
240280297Sjkim        !ENGINE_set_load_privkey_function(e, ibm_4758_load_privkey) ||
241280297Sjkim        !ENGINE_set_load_pubkey_function(e, ibm_4758_load_pubkey) ||
242280297Sjkim#  endif
243280297Sjkim        !ENGINE_set_cmd_defns(e, cca4758_cmd_defns))
244280297Sjkim        return 0;
245280297Sjkim    /* Ensure the error handling is set up */
246280297Sjkim    ERR_load_CCA4758_strings();
247280297Sjkim    return 1;
248280297Sjkim}
249160814Ssimon
250280297Sjkim#  ifdef OPENSSL_NO_DYNAMIC_ENGINE
251160814Ssimonstatic ENGINE *engine_4758_cca(void)
252280297Sjkim{
253280297Sjkim    ENGINE *ret = ENGINE_new();
254280297Sjkim    if (!ret)
255280297Sjkim        return NULL;
256280297Sjkim    if (!bind_helper(ret)) {
257280297Sjkim        ENGINE_free(ret);
258280297Sjkim        return NULL;
259280297Sjkim    }
260280297Sjkim    return ret;
261280297Sjkim}
262160814Ssimon
263160814Ssimonvoid ENGINE_load_4758cca(void)
264280297Sjkim{
265280297Sjkim    ENGINE *e_4758 = engine_4758_cca();
266280297Sjkim    if (!e_4758)
267280297Sjkim        return;
268280297Sjkim    ENGINE_add(e_4758);
269280297Sjkim    ENGINE_free(e_4758);
270280297Sjkim    ERR_clear_error();
271280297Sjkim}
272280297Sjkim#  endif
273160814Ssimon
274160814Ssimonstatic int ibm_4758_cca_destroy(ENGINE *e)
275280297Sjkim{
276280297Sjkim    ERR_unload_CCA4758_strings();
277280297Sjkim    free_CCA4758_LIB_NAME();
278280297Sjkim    return 1;
279280297Sjkim}
280160814Ssimon
281160814Ssimonstatic int ibm_4758_cca_init(ENGINE *e)
282280297Sjkim{
283280297Sjkim    if (dso) {
284280297Sjkim        CCA4758err(CCA4758_F_IBM_4758_CCA_INIT, CCA4758_R_ALREADY_LOADED);
285280297Sjkim        goto err;
286280297Sjkim    }
287160814Ssimon
288280297Sjkim    dso = DSO_load(NULL, get_CCA4758_LIB_NAME(), NULL, 0);
289280297Sjkim    if (!dso) {
290280297Sjkim        CCA4758err(CCA4758_F_IBM_4758_CCA_INIT, CCA4758_R_DSO_FAILURE);
291280297Sjkim        goto err;
292280297Sjkim    }
293280297Sjkim#  ifndef OPENSSL_NO_RSA
294280297Sjkim    if (!(keyRecordRead = (F_KEYRECORDREAD)
295280297Sjkim          DSO_bind_func(dso, n_keyRecordRead)) ||
296280297Sjkim        !(randomNumberGenerate = (F_RANDOMNUMBERGENERATE)
297280297Sjkim          DSO_bind_func(dso, n_randomNumberGenerate)) ||
298280297Sjkim        !(digitalSignatureGenerate = (F_DIGITALSIGNATUREGENERATE)
299280297Sjkim          DSO_bind_func(dso, n_digitalSignatureGenerate)) ||
300280297Sjkim        !(digitalSignatureVerify = (F_DIGITALSIGNATUREVERIFY)
301280297Sjkim          DSO_bind_func(dso, n_digitalSignatureVerify)) ||
302280297Sjkim        !(publicKeyExtract = (F_PUBLICKEYEXTRACT)
303280297Sjkim          DSO_bind_func(dso, n_publicKeyExtract)) ||
304280297Sjkim        !(pkaEncrypt = (F_PKAENCRYPT)
305280297Sjkim          DSO_bind_func(dso, n_pkaEncrypt)) || !(pkaDecrypt = (F_PKADECRYPT)
306280297Sjkim                                                 DSO_bind_func(dso,
307280297Sjkim                                                               n_pkaDecrypt)))
308280297Sjkim    {
309280297Sjkim        CCA4758err(CCA4758_F_IBM_4758_CCA_INIT, CCA4758_R_DSO_FAILURE);
310280297Sjkim        goto err;
311280297Sjkim    }
312280297Sjkim#  else
313280297Sjkim    if (!(randomNumberGenerate = (F_RANDOMNUMBERGENERATE)
314280297Sjkim          DSO_bind_func(dso, n_randomNumberGenerate))) {
315280297Sjkim        CCA4758err(CCA4758_F_IBM_4758_CCA_INIT, CCA4758_R_DSO_FAILURE);
316280297Sjkim        goto err;
317280297Sjkim    }
318280297Sjkim#  endif
319160814Ssimon
320280297Sjkim#  ifndef OPENSSL_NO_RSA
321280297Sjkim    hndidx = RSA_get_ex_new_index(0, "IBM 4758 CCA RSA key handle",
322280297Sjkim                                  NULL, NULL, cca_ex_free);
323280297Sjkim#  endif
324160814Ssimon
325280297Sjkim    return 1;
326280297Sjkim err:
327280297Sjkim    if (dso)
328280297Sjkim        DSO_free(dso);
329280297Sjkim    dso = NULL;
330160814Ssimon
331280297Sjkim#  ifndef OPENSSL_NO_RSA
332280297Sjkim    keyRecordRead = (F_KEYRECORDREAD) 0;
333280297Sjkim    digitalSignatureGenerate = (F_DIGITALSIGNATUREGENERATE) 0;
334280297Sjkim    digitalSignatureVerify = (F_DIGITALSIGNATUREVERIFY)0;
335280297Sjkim    publicKeyExtract = (F_PUBLICKEYEXTRACT)0;
336280297Sjkim    pkaEncrypt = (F_PKAENCRYPT) 0;
337280297Sjkim    pkaDecrypt = (F_PKADECRYPT) 0;
338280297Sjkim#  endif
339280297Sjkim    randomNumberGenerate = (F_RANDOMNUMBERGENERATE) 0;
340280297Sjkim    return 0;
341280297Sjkim}
342160814Ssimon
343160814Ssimonstatic int ibm_4758_cca_finish(ENGINE *e)
344280297Sjkim{
345280297Sjkim    free_CCA4758_LIB_NAME();
346280297Sjkim    if (!dso) {
347280297Sjkim        CCA4758err(CCA4758_F_IBM_4758_CCA_FINISH, CCA4758_R_NOT_LOADED);
348280297Sjkim        return 0;
349280297Sjkim    }
350280297Sjkim    if (!DSO_free(dso)) {
351280297Sjkim        CCA4758err(CCA4758_F_IBM_4758_CCA_FINISH, CCA4758_R_UNIT_FAILURE);
352280297Sjkim        return 0;
353280297Sjkim    }
354280297Sjkim    dso = NULL;
355280297Sjkim#  ifndef OPENSSL_NO_RSA
356280297Sjkim    keyRecordRead = (F_KEYRECORDREAD) 0;
357280297Sjkim    randomNumberGenerate = (F_RANDOMNUMBERGENERATE) 0;
358280297Sjkim    digitalSignatureGenerate = (F_DIGITALSIGNATUREGENERATE) 0;
359280297Sjkim    digitalSignatureVerify = (F_DIGITALSIGNATUREVERIFY)0;
360280297Sjkim    publicKeyExtract = (F_PUBLICKEYEXTRACT)0;
361280297Sjkim    pkaEncrypt = (F_PKAENCRYPT) 0;
362280297Sjkim    pkaDecrypt = (F_PKADECRYPT) 0;
363280297Sjkim#  endif
364280297Sjkim    randomNumberGenerate = (F_RANDOMNUMBERGENERATE) 0;
365280297Sjkim    return 1;
366280297Sjkim}
367160814Ssimon
368280297Sjkimstatic int ibm_4758_cca_ctrl(ENGINE *e, int cmd, long i, void *p,
369280297Sjkim                             void (*f) (void))
370280297Sjkim{
371280297Sjkim    int initialised = ((dso == NULL) ? 0 : 1);
372280297Sjkim    switch (cmd) {
373280297Sjkim    case CCA4758_CMD_SO_PATH:
374280297Sjkim        if (p == NULL) {
375280297Sjkim            CCA4758err(CCA4758_F_IBM_4758_CCA_CTRL,
376280297Sjkim                       ERR_R_PASSED_NULL_PARAMETER);
377280297Sjkim            return 0;
378280297Sjkim        }
379280297Sjkim        if (initialised) {
380280297Sjkim            CCA4758err(CCA4758_F_IBM_4758_CCA_CTRL, CCA4758_R_ALREADY_LOADED);
381280297Sjkim            return 0;
382280297Sjkim        }
383280297Sjkim        return set_CCA4758_LIB_NAME((const char *)p);
384280297Sjkim    default:
385280297Sjkim        break;
386280297Sjkim    }
387280297Sjkim    CCA4758err(CCA4758_F_IBM_4758_CCA_CTRL,
388280297Sjkim               CCA4758_R_COMMAND_NOT_IMPLEMENTED);
389280297Sjkim    return 0;
390280297Sjkim}
391160814Ssimon
392280297Sjkim#  ifndef OPENSSL_NO_RSA
393160814Ssimon
394280297Sjkim#   define MAX_CCA_PKA_TOKEN_SIZE 2500
395160814Ssimon
396280297Sjkimstatic EVP_PKEY *ibm_4758_load_privkey(ENGINE *e, const char *key_id,
397280297Sjkim                                       UI_METHOD *ui_method,
398280297Sjkim                                       void *callback_data)
399280297Sjkim{
400280297Sjkim    RSA *rtmp = NULL;
401280297Sjkim    EVP_PKEY *res = NULL;
402280297Sjkim    unsigned char *keyToken = NULL;
403280297Sjkim    unsigned char pubKeyToken[MAX_CCA_PKA_TOKEN_SIZE];
404280297Sjkim    long pubKeyTokenLength = MAX_CCA_PKA_TOKEN_SIZE;
405280297Sjkim    long keyTokenLength = MAX_CCA_PKA_TOKEN_SIZE;
406280297Sjkim    long returnCode;
407280297Sjkim    long reasonCode;
408280297Sjkim    long exitDataLength = 0;
409280297Sjkim    long ruleArrayLength = 0;
410280297Sjkim    unsigned char exitData[8];
411280297Sjkim    unsigned char ruleArray[8];
412280297Sjkim    unsigned char keyLabel[64];
413280297Sjkim    unsigned long keyLabelLength = strlen(key_id);
414280297Sjkim    unsigned char modulus[256];
415280297Sjkim    long modulusFieldLength = sizeof(modulus);
416280297Sjkim    long modulusLength = 0;
417280297Sjkim    unsigned char exponent[256];
418280297Sjkim    long exponentLength = sizeof(exponent);
419160814Ssimon
420280297Sjkim    if (keyLabelLength > sizeof(keyLabel)) {
421280297Sjkim        CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY,
422280297Sjkim                   CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
423280297Sjkim        return NULL;
424280297Sjkim    }
425160814Ssimon
426280297Sjkim    memset(keyLabel, ' ', sizeof(keyLabel));
427280297Sjkim    memcpy(keyLabel, key_id, keyLabelLength);
428160814Ssimon
429280297Sjkim    keyToken = OPENSSL_malloc(MAX_CCA_PKA_TOKEN_SIZE + sizeof(long));
430280297Sjkim    if (!keyToken) {
431280297Sjkim        CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY, ERR_R_MALLOC_FAILURE);
432280297Sjkim        goto err;
433280297Sjkim    }
434160814Ssimon
435280297Sjkim    keyRecordRead(&returnCode, &reasonCode, &exitDataLength,
436280297Sjkim                  exitData, &ruleArrayLength, ruleArray, keyLabel,
437280297Sjkim                  &keyTokenLength, keyToken + sizeof(long));
438160814Ssimon
439280297Sjkim    if (returnCode) {
440280297Sjkim        CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY,
441280297Sjkim                   CCA4758_R_FAILED_LOADING_PRIVATE_KEY);
442280297Sjkim        goto err;
443280297Sjkim    }
444160814Ssimon
445280297Sjkim    publicKeyExtract(&returnCode, &reasonCode, &exitDataLength,
446280297Sjkim                     exitData, &ruleArrayLength, ruleArray, &keyTokenLength,
447280297Sjkim                     keyToken + sizeof(long), &pubKeyTokenLength,
448280297Sjkim                     pubKeyToken);
449160814Ssimon
450280297Sjkim    if (returnCode) {
451280297Sjkim        CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY,
452280297Sjkim                   CCA4758_R_FAILED_LOADING_PRIVATE_KEY);
453280297Sjkim        goto err;
454280297Sjkim    }
455160814Ssimon
456280297Sjkim    if (!getModulusAndExponent(pubKeyToken, &exponentLength,
457280297Sjkim                               exponent, &modulusLength, &modulusFieldLength,
458280297Sjkim                               modulus)) {
459280297Sjkim        CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY,
460280297Sjkim                   CCA4758_R_FAILED_LOADING_PRIVATE_KEY);
461280297Sjkim        goto err;
462280297Sjkim    }
463160814Ssimon
464280297Sjkim    (*(long *)keyToken) = keyTokenLength;
465280297Sjkim    rtmp = RSA_new_method(e);
466306195Sjkim    if (rtmp == NULL) {
467306195Sjkim        CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY, ERR_R_MALLOC_FAILURE);
468306195Sjkim        goto err;
469306195Sjkim    }
470280297Sjkim    RSA_set_ex_data(rtmp, hndidx, (char *)keyToken);
471160814Ssimon
472280297Sjkim    rtmp->e = BN_bin2bn(exponent, exponentLength, NULL);
473280297Sjkim    rtmp->n = BN_bin2bn(modulus, modulusFieldLength, NULL);
474280297Sjkim    rtmp->flags |= RSA_FLAG_EXT_PKEY;
475160814Ssimon
476280297Sjkim    res = EVP_PKEY_new();
477280297Sjkim    EVP_PKEY_assign_RSA(res, rtmp);
478160814Ssimon
479280297Sjkim    return res;
480280297Sjkim err:
481280297Sjkim    if (keyToken)
482280297Sjkim        OPENSSL_free(keyToken);
483280297Sjkim    return NULL;
484280297Sjkim}
485160814Ssimon
486280297Sjkimstatic EVP_PKEY *ibm_4758_load_pubkey(ENGINE *e, const char *key_id,
487280297Sjkim                                      UI_METHOD *ui_method,
488280297Sjkim                                      void *callback_data)
489280297Sjkim{
490280297Sjkim    RSA *rtmp = NULL;
491280297Sjkim    EVP_PKEY *res = NULL;
492280297Sjkim    unsigned char *keyToken = NULL;
493280297Sjkim    long keyTokenLength = MAX_CCA_PKA_TOKEN_SIZE;
494280297Sjkim    long returnCode;
495280297Sjkim    long reasonCode;
496280297Sjkim    long exitDataLength = 0;
497280297Sjkim    long ruleArrayLength = 0;
498280297Sjkim    unsigned char exitData[8];
499280297Sjkim    unsigned char ruleArray[8];
500280297Sjkim    unsigned char keyLabel[64];
501280297Sjkim    unsigned long keyLabelLength = strlen(key_id);
502280297Sjkim    unsigned char modulus[512];
503280297Sjkim    long modulusFieldLength = sizeof(modulus);
504280297Sjkim    long modulusLength = 0;
505280297Sjkim    unsigned char exponent[512];
506280297Sjkim    long exponentLength = sizeof(exponent);
507160814Ssimon
508280297Sjkim    if (keyLabelLength > sizeof(keyLabel)) {
509280297Sjkim        CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY,
510280297Sjkim                   CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
511280297Sjkim        return NULL;
512280297Sjkim    }
513160814Ssimon
514280297Sjkim    memset(keyLabel, ' ', sizeof(keyLabel));
515280297Sjkim    memcpy(keyLabel, key_id, keyLabelLength);
516160814Ssimon
517280297Sjkim    keyToken = OPENSSL_malloc(MAX_CCA_PKA_TOKEN_SIZE + sizeof(long));
518280297Sjkim    if (!keyToken) {
519280297Sjkim        CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY, ERR_R_MALLOC_FAILURE);
520280297Sjkim        goto err;
521280297Sjkim    }
522160814Ssimon
523280297Sjkim    keyRecordRead(&returnCode, &reasonCode, &exitDataLength, exitData,
524280297Sjkim                  &ruleArrayLength, ruleArray, keyLabel, &keyTokenLength,
525280297Sjkim                  keyToken + sizeof(long));
526160814Ssimon
527280297Sjkim    if (returnCode) {
528280297Sjkim        CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY, ERR_R_MALLOC_FAILURE);
529280297Sjkim        goto err;
530280297Sjkim    }
531160814Ssimon
532280297Sjkim    if (!getModulusAndExponent(keyToken + sizeof(long), &exponentLength,
533280297Sjkim                               exponent, &modulusLength, &modulusFieldLength,
534280297Sjkim                               modulus)) {
535280297Sjkim        CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY,
536280297Sjkim                   CCA4758_R_FAILED_LOADING_PUBLIC_KEY);
537280297Sjkim        goto err;
538280297Sjkim    }
539160814Ssimon
540280297Sjkim    (*(long *)keyToken) = keyTokenLength;
541280297Sjkim    rtmp = RSA_new_method(e);
542306195Sjkim    if (rtmp == NULL) {
543306195Sjkim        CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY, ERR_R_MALLOC_FAILURE);
544306195Sjkim        goto err;
545306195Sjkim    }
546280297Sjkim    RSA_set_ex_data(rtmp, hndidx, (char *)keyToken);
547280297Sjkim    rtmp->e = BN_bin2bn(exponent, exponentLength, NULL);
548280297Sjkim    rtmp->n = BN_bin2bn(modulus, modulusFieldLength, NULL);
549280297Sjkim    rtmp->flags |= RSA_FLAG_EXT_PKEY;
550280297Sjkim    res = EVP_PKEY_new();
551280297Sjkim    EVP_PKEY_assign_RSA(res, rtmp);
552160814Ssimon
553280297Sjkim    return res;
554280297Sjkim err:
555280297Sjkim    if (keyToken)
556280297Sjkim        OPENSSL_free(keyToken);
557280297Sjkim    return NULL;
558280297Sjkim}
559160814Ssimon
560160814Ssimonstatic int cca_rsa_pub_enc(int flen, const unsigned char *from,
561280297Sjkim                           unsigned char *to, RSA *rsa, int padding)
562280297Sjkim{
563280297Sjkim    long returnCode;
564280297Sjkim    long reasonCode;
565280297Sjkim    long lflen = flen;
566280297Sjkim    long exitDataLength = 0;
567280297Sjkim    unsigned char exitData[8];
568280297Sjkim    long ruleArrayLength = 1;
569280297Sjkim    unsigned char ruleArray[8] = "PKCS-1.2";
570280297Sjkim    long dataStructureLength = 0;
571280297Sjkim    unsigned char dataStructure[8];
572280297Sjkim    long outputLength = RSA_size(rsa);
573280297Sjkim    long keyTokenLength;
574280297Sjkim    unsigned char *keyToken = (unsigned char *)RSA_get_ex_data(rsa, hndidx);
575160814Ssimon
576280297Sjkim    keyTokenLength = *(long *)keyToken;
577280297Sjkim    keyToken += sizeof(long);
578160814Ssimon
579280297Sjkim    pkaEncrypt(&returnCode, &reasonCode, &exitDataLength, exitData,
580280297Sjkim               &ruleArrayLength, ruleArray, &lflen, (unsigned char *)from,
581280297Sjkim               &dataStructureLength, dataStructure, &keyTokenLength,
582280297Sjkim               keyToken, &outputLength, to);
583160814Ssimon
584280297Sjkim    if (returnCode || reasonCode)
585280297Sjkim        return -(returnCode << 16 | reasonCode);
586280297Sjkim    return outputLength;
587280297Sjkim}
588160814Ssimon
589160814Ssimonstatic int cca_rsa_priv_dec(int flen, const unsigned char *from,
590280297Sjkim                            unsigned char *to, RSA *rsa, int padding)
591280297Sjkim{
592280297Sjkim    long returnCode;
593280297Sjkim    long reasonCode;
594280297Sjkim    long lflen = flen;
595280297Sjkim    long exitDataLength = 0;
596280297Sjkim    unsigned char exitData[8];
597280297Sjkim    long ruleArrayLength = 1;
598280297Sjkim    unsigned char ruleArray[8] = "PKCS-1.2";
599280297Sjkim    long dataStructureLength = 0;
600280297Sjkim    unsigned char dataStructure[8];
601280297Sjkim    long outputLength = RSA_size(rsa);
602280297Sjkim    long keyTokenLength;
603280297Sjkim    unsigned char *keyToken = (unsigned char *)RSA_get_ex_data(rsa, hndidx);
604160814Ssimon
605280297Sjkim    keyTokenLength = *(long *)keyToken;
606280297Sjkim    keyToken += sizeof(long);
607160814Ssimon
608280297Sjkim    pkaDecrypt(&returnCode, &reasonCode, &exitDataLength, exitData,
609280297Sjkim               &ruleArrayLength, ruleArray, &lflen, (unsigned char *)from,
610280297Sjkim               &dataStructureLength, dataStructure, &keyTokenLength,
611280297Sjkim               keyToken, &outputLength, to);
612160814Ssimon
613280297Sjkim    return (returnCode | reasonCode) ? 0 : 1;
614280297Sjkim}
615160814Ssimon
616280297Sjkim#   define SSL_SIG_LEN 36
617160814Ssimon
618280297Sjkimstatic int cca_rsa_verify(int type, const unsigned char *m,
619280297Sjkim                          unsigned int m_len, const unsigned char *sigbuf,
620280297Sjkim                          unsigned int siglen, const RSA *rsa)
621280297Sjkim{
622280297Sjkim    long returnCode;
623280297Sjkim    long reasonCode;
624280297Sjkim    long lsiglen = siglen;
625280297Sjkim    long exitDataLength = 0;
626280297Sjkim    unsigned char exitData[8];
627280297Sjkim    long ruleArrayLength = 1;
628280297Sjkim    unsigned char ruleArray[8] = "PKCS-1.1";
629280297Sjkim    long keyTokenLength;
630280297Sjkim    unsigned char *keyToken = (unsigned char *)RSA_get_ex_data(rsa, hndidx);
631280297Sjkim    long length = SSL_SIG_LEN;
632280297Sjkim    long keyLength;
633280297Sjkim    unsigned char *hashBuffer = NULL;
634280297Sjkim    X509_SIG sig;
635280297Sjkim    ASN1_TYPE parameter;
636280297Sjkim    X509_ALGOR algorithm;
637280297Sjkim    ASN1_OCTET_STRING digest;
638160814Ssimon
639280297Sjkim    keyTokenLength = *(long *)keyToken;
640280297Sjkim    keyToken += sizeof(long);
641160814Ssimon
642280297Sjkim    if (type == NID_md5 || type == NID_sha1) {
643280297Sjkim        sig.algor = &algorithm;
644280297Sjkim        algorithm.algorithm = OBJ_nid2obj(type);
645160814Ssimon
646280297Sjkim        if (!algorithm.algorithm) {
647280297Sjkim            CCA4758err(CCA4758_F_CCA_RSA_VERIFY,
648280297Sjkim                       CCA4758_R_UNKNOWN_ALGORITHM_TYPE);
649280297Sjkim            return 0;
650280297Sjkim        }
651160814Ssimon
652280297Sjkim        if (!algorithm.algorithm->length) {
653280297Sjkim            CCA4758err(CCA4758_F_CCA_RSA_VERIFY,
654280297Sjkim                       CCA4758_R_ASN1_OID_UNKNOWN_FOR_MD);
655280297Sjkim            return 0;
656280297Sjkim        }
657160814Ssimon
658280297Sjkim        parameter.type = V_ASN1_NULL;
659280297Sjkim        parameter.value.ptr = NULL;
660280297Sjkim        algorithm.parameter = &parameter;
661160814Ssimon
662280297Sjkim        sig.digest = &digest;
663280297Sjkim        sig.digest->data = (unsigned char *)m;
664280297Sjkim        sig.digest->length = m_len;
665160814Ssimon
666280297Sjkim        length = i2d_X509_SIG(&sig, NULL);
667280297Sjkim    }
668160814Ssimon
669280297Sjkim    keyLength = RSA_size(rsa);
670160814Ssimon
671280297Sjkim    if (length - RSA_PKCS1_PADDING > keyLength) {
672280297Sjkim        CCA4758err(CCA4758_F_CCA_RSA_VERIFY,
673280297Sjkim                   CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
674280297Sjkim        return 0;
675280297Sjkim    }
676160814Ssimon
677280297Sjkim    switch (type) {
678280297Sjkim    case NID_md5_sha1:
679280297Sjkim        if (m_len != SSL_SIG_LEN) {
680280297Sjkim            CCA4758err(CCA4758_F_CCA_RSA_VERIFY,
681280297Sjkim                       CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
682280297Sjkim            return 0;
683280297Sjkim        }
684160814Ssimon
685280297Sjkim        hashBuffer = (unsigned char *)m;
686280297Sjkim        length = m_len;
687280297Sjkim        break;
688280297Sjkim    case NID_md5:
689280297Sjkim        {
690280297Sjkim            unsigned char *ptr;
691280297Sjkim            ptr = hashBuffer = OPENSSL_malloc((unsigned int)keyLength + 1);
692280297Sjkim            if (!hashBuffer) {
693280297Sjkim                CCA4758err(CCA4758_F_CCA_RSA_VERIFY, ERR_R_MALLOC_FAILURE);
694280297Sjkim                return 0;
695280297Sjkim            }
696160814Ssimon
697280297Sjkim            i2d_X509_SIG(&sig, &ptr);
698280297Sjkim        }
699280297Sjkim        break;
700280297Sjkim    case NID_sha1:
701280297Sjkim        {
702280297Sjkim            unsigned char *ptr;
703280297Sjkim            ptr = hashBuffer = OPENSSL_malloc((unsigned int)keyLength + 1);
704280297Sjkim            if (!hashBuffer) {
705280297Sjkim                CCA4758err(CCA4758_F_CCA_RSA_VERIFY, ERR_R_MALLOC_FAILURE);
706280297Sjkim                return 0;
707280297Sjkim            }
708280297Sjkim            i2d_X509_SIG(&sig, &ptr);
709280297Sjkim        }
710280297Sjkim        break;
711280297Sjkim    default:
712280297Sjkim        return 0;
713280297Sjkim    }
714160814Ssimon
715280297Sjkim    digitalSignatureVerify(&returnCode, &reasonCode, &exitDataLength,
716280297Sjkim                           exitData, &ruleArrayLength, ruleArray,
717280297Sjkim                           &keyTokenLength, keyToken, &length, hashBuffer,
718280297Sjkim                           &lsiglen, (unsigned char *)sigbuf);
719160814Ssimon
720280297Sjkim    if (type == NID_sha1 || type == NID_md5) {
721280297Sjkim        OPENSSL_cleanse(hashBuffer, keyLength + 1);
722280297Sjkim        OPENSSL_free(hashBuffer);
723280297Sjkim    }
724160814Ssimon
725280297Sjkim    return ((returnCode || reasonCode) ? 0 : 1);
726280297Sjkim}
727160814Ssimon
728280297Sjkim#   define SSL_SIG_LEN 36
729160814Ssimon
730160814Ssimonstatic int cca_rsa_sign(int type, const unsigned char *m, unsigned int m_len,
731280297Sjkim                        unsigned char *sigret, unsigned int *siglen,
732280297Sjkim                        const RSA *rsa)
733280297Sjkim{
734280297Sjkim    long returnCode;
735280297Sjkim    long reasonCode;
736280297Sjkim    long exitDataLength = 0;
737280297Sjkim    unsigned char exitData[8];
738280297Sjkim    long ruleArrayLength = 1;
739280297Sjkim    unsigned char ruleArray[8] = "PKCS-1.1";
740280297Sjkim    long outputLength = 256;
741280297Sjkim    long outputBitLength;
742280297Sjkim    long keyTokenLength;
743280297Sjkim    unsigned char *hashBuffer = NULL;
744280297Sjkim    unsigned char *keyToken = (unsigned char *)RSA_get_ex_data(rsa, hndidx);
745280297Sjkim    long length = SSL_SIG_LEN;
746280297Sjkim    long keyLength;
747280297Sjkim    X509_SIG sig;
748280297Sjkim    ASN1_TYPE parameter;
749280297Sjkim    X509_ALGOR algorithm;
750280297Sjkim    ASN1_OCTET_STRING digest;
751160814Ssimon
752280297Sjkim    keyTokenLength = *(long *)keyToken;
753280297Sjkim    keyToken += sizeof(long);
754160814Ssimon
755280297Sjkim    if (type == NID_md5 || type == NID_sha1) {
756280297Sjkim        sig.algor = &algorithm;
757280297Sjkim        algorithm.algorithm = OBJ_nid2obj(type);
758160814Ssimon
759280297Sjkim        if (!algorithm.algorithm) {
760280297Sjkim            CCA4758err(CCA4758_F_CCA_RSA_SIGN,
761280297Sjkim                       CCA4758_R_UNKNOWN_ALGORITHM_TYPE);
762280297Sjkim            return 0;
763280297Sjkim        }
764160814Ssimon
765280297Sjkim        if (!algorithm.algorithm->length) {
766280297Sjkim            CCA4758err(CCA4758_F_CCA_RSA_SIGN,
767280297Sjkim                       CCA4758_R_ASN1_OID_UNKNOWN_FOR_MD);
768280297Sjkim            return 0;
769280297Sjkim        }
770160814Ssimon
771280297Sjkim        parameter.type = V_ASN1_NULL;
772280297Sjkim        parameter.value.ptr = NULL;
773280297Sjkim        algorithm.parameter = &parameter;
774160814Ssimon
775280297Sjkim        sig.digest = &digest;
776280297Sjkim        sig.digest->data = (unsigned char *)m;
777280297Sjkim        sig.digest->length = m_len;
778160814Ssimon
779280297Sjkim        length = i2d_X509_SIG(&sig, NULL);
780280297Sjkim    }
781160814Ssimon
782280297Sjkim    keyLength = RSA_size(rsa);
783160814Ssimon
784280297Sjkim    if (length - RSA_PKCS1_PADDING > keyLength) {
785280297Sjkim        CCA4758err(CCA4758_F_CCA_RSA_SIGN,
786280297Sjkim                   CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
787280297Sjkim        return 0;
788280297Sjkim    }
789160814Ssimon
790280297Sjkim    switch (type) {
791280297Sjkim    case NID_md5_sha1:
792280297Sjkim        if (m_len != SSL_SIG_LEN) {
793280297Sjkim            CCA4758err(CCA4758_F_CCA_RSA_SIGN,
794280297Sjkim                       CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
795280297Sjkim            return 0;
796280297Sjkim        }
797280297Sjkim        hashBuffer = (unsigned char *)m;
798280297Sjkim        length = m_len;
799280297Sjkim        break;
800280297Sjkim    case NID_md5:
801280297Sjkim        {
802280297Sjkim            unsigned char *ptr;
803280297Sjkim            ptr = hashBuffer = OPENSSL_malloc((unsigned int)keyLength + 1);
804280297Sjkim            if (!hashBuffer) {
805280297Sjkim                CCA4758err(CCA4758_F_CCA_RSA_SIGN, ERR_R_MALLOC_FAILURE);
806280297Sjkim                return 0;
807280297Sjkim            }
808280297Sjkim            i2d_X509_SIG(&sig, &ptr);
809280297Sjkim        }
810280297Sjkim        break;
811280297Sjkim    case NID_sha1:
812280297Sjkim        {
813280297Sjkim            unsigned char *ptr;
814280297Sjkim            ptr = hashBuffer = OPENSSL_malloc((unsigned int)keyLength + 1);
815280297Sjkim            if (!hashBuffer) {
816280297Sjkim                CCA4758err(CCA4758_F_CCA_RSA_SIGN, ERR_R_MALLOC_FAILURE);
817280297Sjkim                return 0;
818280297Sjkim            }
819280297Sjkim            i2d_X509_SIG(&sig, &ptr);
820280297Sjkim        }
821280297Sjkim        break;
822280297Sjkim    default:
823280297Sjkim        return 0;
824280297Sjkim    }
825160814Ssimon
826280297Sjkim    digitalSignatureGenerate(&returnCode, &reasonCode, &exitDataLength,
827280297Sjkim                             exitData, &ruleArrayLength, ruleArray,
828280297Sjkim                             &keyTokenLength, keyToken, &length, hashBuffer,
829280297Sjkim                             &outputLength, &outputBitLength, sigret);
830160814Ssimon
831280297Sjkim    if (type == NID_sha1 || type == NID_md5) {
832280297Sjkim        OPENSSL_cleanse(hashBuffer, keyLength + 1);
833280297Sjkim        OPENSSL_free(hashBuffer);
834280297Sjkim    }
835160814Ssimon
836280297Sjkim    *siglen = outputLength;
837160814Ssimon
838280297Sjkim    return ((returnCode || reasonCode) ? 0 : 1);
839280297Sjkim}
840160814Ssimon
841280297Sjkimstatic int getModulusAndExponent(const unsigned char *token,
842280297Sjkim                                 long *exponentLength,
843280297Sjkim                                 unsigned char *exponent, long *modulusLength,
844280297Sjkim                                 long *modulusFieldLength,
845280297Sjkim                                 unsigned char *modulus)
846280297Sjkim{
847280297Sjkim    unsigned long len;
848160814Ssimon
849280297Sjkim    if (*token++ != (char)0x1E) /* internal PKA token? */
850280297Sjkim        return 0;
851160814Ssimon
852280297Sjkim    if (*token++)               /* token version must be zero */
853280297Sjkim        return 0;
854160814Ssimon
855280297Sjkim    len = *token++;
856280297Sjkim    len = len << 8;
857280297Sjkim    len |= (unsigned char)*token++;
858160814Ssimon
859280297Sjkim    token += 4;                 /* skip reserved bytes */
860160814Ssimon
861280297Sjkim    if (*token++ == (char)0x04) {
862280297Sjkim        if (*token++)           /* token version must be zero */
863280297Sjkim            return 0;
864160814Ssimon
865280297Sjkim        len = *token++;
866280297Sjkim        len = len << 8;
867280297Sjkim        len |= (unsigned char)*token++;
868160814Ssimon
869280297Sjkim        token += 2;             /* skip reserved section */
870160814Ssimon
871280297Sjkim        len = *token++;
872280297Sjkim        len = len << 8;
873280297Sjkim        len |= (unsigned char)*token++;
874160814Ssimon
875280297Sjkim        *exponentLength = len;
876160814Ssimon
877280297Sjkim        len = *token++;
878280297Sjkim        len = len << 8;
879280297Sjkim        len |= (unsigned char)*token++;
880160814Ssimon
881280297Sjkim        *modulusLength = len;
882160814Ssimon
883280297Sjkim        len = *token++;
884280297Sjkim        len = len << 8;
885280297Sjkim        len |= (unsigned char)*token++;
886160814Ssimon
887280297Sjkim        *modulusFieldLength = len;
888160814Ssimon
889280297Sjkim        memcpy(exponent, token, *exponentLength);
890280297Sjkim        token += *exponentLength;
891160814Ssimon
892280297Sjkim        memcpy(modulus, token, *modulusFieldLength);
893280297Sjkim        return 1;
894280297Sjkim    }
895280297Sjkim    return 0;
896280297Sjkim}
897160814Ssimon
898280297Sjkim#  endif                        /* OPENSSL_NO_RSA */
899160814Ssimon
900160814Ssimonstatic int cca_random_status(void)
901280297Sjkim{
902280297Sjkim    return 1;
903280297Sjkim}
904160814Ssimon
905280297Sjkimstatic int cca_get_random_bytes(unsigned char *buf, int num)
906280297Sjkim{
907280297Sjkim    long ret_code;
908280297Sjkim    long reason_code;
909280297Sjkim    long exit_data_length;
910280297Sjkim    unsigned char exit_data[4];
911280297Sjkim    unsigned char form[] = "RANDOM  ";
912280297Sjkim    unsigned char rand_buf[8];
913160814Ssimon
914280297Sjkim    while (num >= (int)sizeof(rand_buf)) {
915280297Sjkim        randomNumberGenerate(&ret_code, &reason_code, &exit_data_length,
916280297Sjkim                             exit_data, form, rand_buf);
917280297Sjkim        if (ret_code)
918280297Sjkim            return 0;
919280297Sjkim        num -= sizeof(rand_buf);
920280297Sjkim        memcpy(buf, rand_buf, sizeof(rand_buf));
921280297Sjkim        buf += sizeof(rand_buf);
922280297Sjkim    }
923160814Ssimon
924280297Sjkim    if (num) {
925280297Sjkim        randomNumberGenerate(&ret_code, &reason_code, NULL, NULL,
926280297Sjkim                             form, rand_buf);
927280297Sjkim        if (ret_code)
928280297Sjkim            return 0;
929280297Sjkim        memcpy(buf, rand_buf, num);
930280297Sjkim    }
931160814Ssimon
932280297Sjkim    return 1;
933280297Sjkim}
934160814Ssimon
935280297Sjkim#  ifndef OPENSSL_NO_RSA
936160814Ssimonstatic void cca_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad, int idx,
937280297Sjkim                        long argl, void *argp)
938280297Sjkim{
939280297Sjkim    if (item)
940280297Sjkim        OPENSSL_free(item);
941280297Sjkim}
942280297Sjkim#  endif
943160814Ssimon
944160814Ssimon/* Goo to handle building as a dynamic engine */
945280297Sjkim#  ifndef OPENSSL_NO_DYNAMIC_ENGINE
946160814Ssimonstatic int bind_fn(ENGINE *e, const char *id)
947280297Sjkim{
948280297Sjkim    if (id && (strcmp(id, engine_4758_cca_id) != 0) &&
949280297Sjkim        (strcmp(id, engine_4758_cca_id_alt) != 0))
950280297Sjkim        return 0;
951280297Sjkim    if (!bind_helper(e))
952280297Sjkim        return 0;
953280297Sjkim    return 1;
954280297Sjkim}
955280297Sjkim
956160814SsimonIMPLEMENT_DYNAMIC_CHECK_FN()
957280297Sjkim    IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
958280297Sjkim#  endif                        /* OPENSSL_NO_DYNAMIC_ENGINE */
959280297Sjkim# endif                         /* !OPENSSL_NO_HW_4758_CCA */
960280297Sjkim#endif                          /* !OPENSSL_NO_HW */
961