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
10160814Ssimon *    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
65160814Ssimon#include <openssl/rsa.h>
66160814Ssimon#endif
67160814Ssimon#include <openssl/bn.h>
68160814Ssimon
69160814Ssimon#ifndef OPENSSL_NO_HW
70160814Ssimon#ifndef OPENSSL_NO_HW_4758_CCA
71160814Ssimon
72160814Ssimon#ifdef FLAT_INC
73160814Ssimon#include "hw_4758_cca.h"
74160814Ssimon#else
75160814Ssimon#include "vendor_defns/hw_4758_cca.h"
76160814Ssimon#endif
77160814Ssimon
78160814Ssimon#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);
83160814Ssimonstatic int ibm_4758_cca_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void));
84160814Ssimon
85160814Ssimon/* rsa functions */
86160814Ssimon/*---------------*/
87160814Ssimon#ifndef OPENSSL_NO_RSA
88160814Ssimonstatic int cca_rsa_pub_enc(int flen, const unsigned char *from,
89160814Ssimon		unsigned char *to, RSA *rsa,int padding);
90160814Ssimonstatic int cca_rsa_priv_dec(int flen, const unsigned char *from,
91160814Ssimon		unsigned char *to, RSA *rsa,int padding);
92160814Ssimonstatic int cca_rsa_sign(int type, const unsigned char *m, unsigned int m_len,
93160814Ssimon		unsigned char *sigret, unsigned int *siglen, const RSA *rsa);
94160814Ssimonstatic int cca_rsa_verify(int dtype, const unsigned char *m, unsigned int m_len,
95238405Sjkim	const unsigned char *sigbuf, unsigned int siglen, const RSA *rsa);
96160814Ssimon
97160814Ssimon/* utility functions */
98160814Ssimon/*-----------------------*/
99160814Ssimonstatic EVP_PKEY *ibm_4758_load_privkey(ENGINE*, const char*,
100160814Ssimon		UI_METHOD *ui_method, void *callback_data);
101160814Ssimonstatic EVP_PKEY *ibm_4758_load_pubkey(ENGINE*, const char*,
102160814Ssimon		UI_METHOD *ui_method, void *callback_data);
103160814Ssimon
104160814Ssimonstatic int getModulusAndExponent(const unsigned char *token, long *exponentLength,
105160814Ssimon		unsigned char *exponent, long *modulusLength,
106160814Ssimon		long *modulusFieldLength, unsigned char *modulus);
107160814Ssimon#endif
108160814Ssimon
109160814Ssimon/* RAND number functions */
110160814Ssimon/*-----------------------*/
111238405Sjkimstatic int cca_get_random_bytes(unsigned char*, int);
112160814Ssimonstatic int cca_random_status(void);
113160814Ssimon
114160814Ssimon#ifndef OPENSSL_NO_RSA
115160814Ssimonstatic void cca_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
116160814Ssimon		int idx,long argl, void *argp);
117160814Ssimon#endif
118160814Ssimon
119160814Ssimon/* Function pointers for CCA verbs */
120160814Ssimon/*---------------------------------*/
121160814Ssimon#ifndef OPENSSL_NO_RSA
122160814Ssimonstatic F_KEYRECORDREAD keyRecordRead;
123160814Ssimonstatic F_DIGITALSIGNATUREGENERATE digitalSignatureGenerate;
124160814Ssimonstatic F_DIGITALSIGNATUREVERIFY digitalSignatureVerify;
125160814Ssimonstatic F_PUBLICKEYEXTRACT publicKeyExtract;
126160814Ssimonstatic F_PKAENCRYPT pkaEncrypt;
127160814Ssimonstatic F_PKADECRYPT pkaDecrypt;
128160814Ssimon#endif
129160814Ssimonstatic F_RANDOMNUMBERGENERATE randomNumberGenerate;
130160814Ssimon
131160814Ssimon/* static variables */
132160814Ssimon/*------------------*/
133160814Ssimonstatic const char *CCA4758_LIB_NAME = NULL;
134160814Ssimonstatic const char *get_CCA4758_LIB_NAME(void)
135160814Ssimon	{
136160814Ssimon	if(CCA4758_LIB_NAME)
137160814Ssimon		return CCA4758_LIB_NAME;
138160814Ssimon	return CCA_LIB_NAME;
139160814Ssimon	}
140160814Ssimonstatic void free_CCA4758_LIB_NAME(void)
141160814Ssimon	{
142160814Ssimon	if(CCA4758_LIB_NAME)
143160814Ssimon		OPENSSL_free((void*)CCA4758_LIB_NAME);
144160814Ssimon	CCA4758_LIB_NAME = NULL;
145160814Ssimon	}
146160814Ssimonstatic long set_CCA4758_LIB_NAME(const char *name)
147160814Ssimon	{
148160814Ssimon	free_CCA4758_LIB_NAME();
149160814Ssimon	return (((CCA4758_LIB_NAME = BUF_strdup(name)) != NULL) ? 1 : 0);
150160814Ssimon	}
151160814Ssimon#ifndef OPENSSL_NO_RSA
152160814Ssimonstatic const char* n_keyRecordRead = CSNDKRR;
153160814Ssimonstatic const char* n_digitalSignatureGenerate = CSNDDSG;
154160814Ssimonstatic const char* n_digitalSignatureVerify = CSNDDSV;
155160814Ssimonstatic const char* n_publicKeyExtract = CSNDPKX;
156160814Ssimonstatic const char* n_pkaEncrypt = CSNDPKE;
157160814Ssimonstatic const char* n_pkaDecrypt = CSNDPKD;
158160814Ssimon#endif
159160814Ssimonstatic const char* n_randomNumberGenerate = CSNBRNG;
160160814Ssimon
161160814Ssimon#ifndef OPENSSL_NO_RSA
162160814Ssimonstatic int hndidx = -1;
163160814Ssimon#endif
164160814Ssimonstatic DSO *dso = NULL;
165160814Ssimon
166160814Ssimon/* openssl engine initialization structures */
167160814Ssimon/*------------------------------------------*/
168160814Ssimon
169160814Ssimon#define CCA4758_CMD_SO_PATH		ENGINE_CMD_BASE
170160814Ssimonstatic const ENGINE_CMD_DEFN	cca4758_cmd_defns[] = {
171160814Ssimon	{CCA4758_CMD_SO_PATH,
172160814Ssimon		"SO_PATH",
173160814Ssimon		"Specifies the path to the '4758cca' shared library",
174160814Ssimon		ENGINE_CMD_FLAG_STRING},
175160814Ssimon	{0, NULL, NULL, 0}
176160814Ssimon	};
177160814Ssimon
178160814Ssimon#ifndef OPENSSL_NO_RSA
179160814Ssimonstatic RSA_METHOD ibm_4758_cca_rsa =
180160814Ssimon	{
181160814Ssimon	"IBM 4758 CCA RSA method",
182160814Ssimon	cca_rsa_pub_enc,
183160814Ssimon	NULL,
184160814Ssimon	NULL,
185160814Ssimon	cca_rsa_priv_dec,
186160814Ssimon	NULL, /*rsa_mod_exp,*/
187160814Ssimon	NULL, /*mod_exp_mont,*/
188160814Ssimon	NULL, /* init */
189160814Ssimon	NULL, /* finish */
190160814Ssimon	RSA_FLAG_SIGN_VER,	  /* flags */
191160814Ssimon	NULL, /* app_data */
192160814Ssimon	cca_rsa_sign, /* rsa_sign */
193160814Ssimon	cca_rsa_verify, /* rsa_verify */
194160814Ssimon	NULL /* rsa_keygen */
195160814Ssimon	};
196160814Ssimon#endif
197160814Ssimon
198160814Ssimonstatic RAND_METHOD ibm_4758_cca_rand =
199160814Ssimon	{
200160814Ssimon	/* "IBM 4758 RAND method", */
201160814Ssimon	NULL, /* seed */
202160814Ssimon	cca_get_random_bytes, /* get random bytes from the card */
203160814Ssimon	NULL, /* cleanup */
204160814Ssimon	NULL, /* add */
205160814Ssimon	cca_get_random_bytes, /* pseudo rand */
206160814Ssimon	cca_random_status, /* status */
207160814Ssimon	};
208160814Ssimon
209160814Ssimonstatic const char *engine_4758_cca_id = "4758cca";
210160814Ssimonstatic const char *engine_4758_cca_name = "IBM 4758 CCA hardware engine support";
211160814Ssimon#ifndef OPENSSL_NO_DYNAMIC_ENGINE
212160814Ssimon/* Compatibility hack, the dynamic library uses this form in the path */
213160814Ssimonstatic const char *engine_4758_cca_id_alt = "4758_cca";
214160814Ssimon#endif
215160814Ssimon
216160814Ssimon/* engine implementation */
217160814Ssimon/*-----------------------*/
218160814Ssimonstatic int bind_helper(ENGINE *e)
219160814Ssimon	{
220160814Ssimon	if(!ENGINE_set_id(e, engine_4758_cca_id) ||
221160814Ssimon			!ENGINE_set_name(e, engine_4758_cca_name) ||
222160814Ssimon#ifndef OPENSSL_NO_RSA
223160814Ssimon			!ENGINE_set_RSA(e, &ibm_4758_cca_rsa) ||
224160814Ssimon#endif
225160814Ssimon			!ENGINE_set_RAND(e, &ibm_4758_cca_rand) ||
226160814Ssimon			!ENGINE_set_destroy_function(e, ibm_4758_cca_destroy) ||
227160814Ssimon			!ENGINE_set_init_function(e, ibm_4758_cca_init) ||
228160814Ssimon			!ENGINE_set_finish_function(e, ibm_4758_cca_finish) ||
229160814Ssimon			!ENGINE_set_ctrl_function(e, ibm_4758_cca_ctrl) ||
230160814Ssimon#ifndef OPENSSL_NO_RSA
231160814Ssimon			!ENGINE_set_load_privkey_function(e, ibm_4758_load_privkey) ||
232160814Ssimon			!ENGINE_set_load_pubkey_function(e, ibm_4758_load_pubkey) ||
233160814Ssimon#endif
234160814Ssimon			!ENGINE_set_cmd_defns(e, cca4758_cmd_defns))
235160814Ssimon		return 0;
236160814Ssimon	/* Ensure the error handling is set up */
237160814Ssimon	ERR_load_CCA4758_strings();
238160814Ssimon	return 1;
239160814Ssimon	}
240160814Ssimon
241160814Ssimon#ifdef OPENSSL_NO_DYNAMIC_ENGINE
242160814Ssimonstatic ENGINE *engine_4758_cca(void)
243160814Ssimon	{
244160814Ssimon	ENGINE *ret = ENGINE_new();
245160814Ssimon	if(!ret)
246160814Ssimon		return NULL;
247160814Ssimon	if(!bind_helper(ret))
248160814Ssimon		{
249160814Ssimon		ENGINE_free(ret);
250160814Ssimon		return NULL;
251160814Ssimon		}
252160814Ssimon	return ret;
253160814Ssimon	}
254160814Ssimon
255160814Ssimonvoid ENGINE_load_4758cca(void)
256160814Ssimon	{
257160814Ssimon	ENGINE *e_4758 = engine_4758_cca();
258160814Ssimon	if (!e_4758) return;
259160814Ssimon	ENGINE_add(e_4758);
260160814Ssimon	ENGINE_free(e_4758);
261160814Ssimon	ERR_clear_error();
262160814Ssimon	}
263160814Ssimon#endif
264160814Ssimon
265160814Ssimonstatic int ibm_4758_cca_destroy(ENGINE *e)
266160814Ssimon	{
267160814Ssimon	ERR_unload_CCA4758_strings();
268160814Ssimon	free_CCA4758_LIB_NAME();
269160814Ssimon	return 1;
270160814Ssimon	}
271160814Ssimon
272160814Ssimonstatic int ibm_4758_cca_init(ENGINE *e)
273160814Ssimon	{
274160814Ssimon	if(dso)
275160814Ssimon		{
276160814Ssimon		CCA4758err(CCA4758_F_IBM_4758_CCA_INIT,CCA4758_R_ALREADY_LOADED);
277160814Ssimon		goto err;
278160814Ssimon		}
279160814Ssimon
280160814Ssimon	dso = DSO_load(NULL, get_CCA4758_LIB_NAME(), NULL, 0);
281160814Ssimon	if(!dso)
282160814Ssimon		{
283160814Ssimon		CCA4758err(CCA4758_F_IBM_4758_CCA_INIT,CCA4758_R_DSO_FAILURE);
284160814Ssimon		goto err;
285160814Ssimon		}
286160814Ssimon
287160814Ssimon#ifndef OPENSSL_NO_RSA
288160814Ssimon	if(!(keyRecordRead = (F_KEYRECORDREAD)
289160814Ssimon				DSO_bind_func(dso, n_keyRecordRead)) ||
290160814Ssimon			!(randomNumberGenerate = (F_RANDOMNUMBERGENERATE)
291160814Ssimon				DSO_bind_func(dso, n_randomNumberGenerate)) ||
292160814Ssimon			!(digitalSignatureGenerate = (F_DIGITALSIGNATUREGENERATE)
293160814Ssimon				DSO_bind_func(dso, n_digitalSignatureGenerate)) ||
294160814Ssimon			!(digitalSignatureVerify = (F_DIGITALSIGNATUREVERIFY)
295160814Ssimon				DSO_bind_func(dso, n_digitalSignatureVerify)) ||
296160814Ssimon			!(publicKeyExtract = (F_PUBLICKEYEXTRACT)
297160814Ssimon				DSO_bind_func(dso, n_publicKeyExtract)) ||
298160814Ssimon			!(pkaEncrypt = (F_PKAENCRYPT)
299160814Ssimon				DSO_bind_func(dso, n_pkaEncrypt)) ||
300160814Ssimon			!(pkaDecrypt = (F_PKADECRYPT)
301160814Ssimon				DSO_bind_func(dso, n_pkaDecrypt)))
302160814Ssimon		{
303160814Ssimon		CCA4758err(CCA4758_F_IBM_4758_CCA_INIT,CCA4758_R_DSO_FAILURE);
304160814Ssimon		goto err;
305160814Ssimon		}
306160814Ssimon#else
307160814Ssimon	if(!(randomNumberGenerate = (F_RANDOMNUMBERGENERATE)
308160814Ssimon				DSO_bind_func(dso, n_randomNumberGenerate)))
309160814Ssimon		{
310160814Ssimon		CCA4758err(CCA4758_F_IBM_4758_CCA_INIT,CCA4758_R_DSO_FAILURE);
311160814Ssimon		goto err;
312160814Ssimon		}
313160814Ssimon#endif
314160814Ssimon
315160814Ssimon#ifndef OPENSSL_NO_RSA
316160814Ssimon	hndidx = RSA_get_ex_new_index(0, "IBM 4758 CCA RSA key handle",
317160814Ssimon		NULL, NULL, cca_ex_free);
318160814Ssimon#endif
319160814Ssimon
320160814Ssimon	return 1;
321160814Ssimonerr:
322160814Ssimon	if(dso)
323160814Ssimon		DSO_free(dso);
324160814Ssimon	dso = NULL;
325160814Ssimon
326160814Ssimon#ifndef OPENSSL_NO_RSA
327160814Ssimon	keyRecordRead = (F_KEYRECORDREAD)0;
328160814Ssimon	digitalSignatureGenerate = (F_DIGITALSIGNATUREGENERATE)0;
329160814Ssimon	digitalSignatureVerify = (F_DIGITALSIGNATUREVERIFY)0;
330160814Ssimon	publicKeyExtract = (F_PUBLICKEYEXTRACT)0;
331160814Ssimon	pkaEncrypt = (F_PKAENCRYPT)0;
332160814Ssimon	pkaDecrypt = (F_PKADECRYPT)0;
333160814Ssimon#endif
334160814Ssimon	randomNumberGenerate = (F_RANDOMNUMBERGENERATE)0;
335160814Ssimon	return 0;
336160814Ssimon	}
337160814Ssimon
338160814Ssimonstatic int ibm_4758_cca_finish(ENGINE *e)
339160814Ssimon	{
340160814Ssimon	free_CCA4758_LIB_NAME();
341160814Ssimon	if(!dso)
342160814Ssimon		{
343160814Ssimon		CCA4758err(CCA4758_F_IBM_4758_CCA_FINISH,
344160814Ssimon				CCA4758_R_NOT_LOADED);
345160814Ssimon		return 0;
346160814Ssimon		}
347160814Ssimon	if(!DSO_free(dso))
348160814Ssimon		{
349160814Ssimon		CCA4758err(CCA4758_F_IBM_4758_CCA_FINISH,
350160814Ssimon				CCA4758_R_UNIT_FAILURE);
351160814Ssimon		return 0;
352160814Ssimon		}
353160814Ssimon	dso = NULL;
354160814Ssimon#ifndef OPENSSL_NO_RSA
355160814Ssimon	keyRecordRead = (F_KEYRECORDREAD)0;
356160814Ssimon	randomNumberGenerate = (F_RANDOMNUMBERGENERATE)0;
357160814Ssimon	digitalSignatureGenerate = (F_DIGITALSIGNATUREGENERATE)0;
358160814Ssimon	digitalSignatureVerify = (F_DIGITALSIGNATUREVERIFY)0;
359160814Ssimon	publicKeyExtract = (F_PUBLICKEYEXTRACT)0;
360160814Ssimon	pkaEncrypt = (F_PKAENCRYPT)0;
361160814Ssimon	pkaDecrypt = (F_PKADECRYPT)0;
362160814Ssimon#endif
363160814Ssimon	randomNumberGenerate = (F_RANDOMNUMBERGENERATE)0;
364160814Ssimon	return 1;
365160814Ssimon	}
366160814Ssimon
367160814Ssimonstatic int ibm_4758_cca_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
368160814Ssimon	{
369160814Ssimon	int initialised = ((dso == NULL) ? 0 : 1);
370160814Ssimon	switch(cmd)
371160814Ssimon		{
372160814Ssimon	case CCA4758_CMD_SO_PATH:
373160814Ssimon		if(p == NULL)
374160814Ssimon			{
375160814Ssimon			CCA4758err(CCA4758_F_IBM_4758_CCA_CTRL,
376160814Ssimon					ERR_R_PASSED_NULL_PARAMETER);
377160814Ssimon			return 0;
378160814Ssimon			}
379160814Ssimon		if(initialised)
380160814Ssimon			{
381160814Ssimon			CCA4758err(CCA4758_F_IBM_4758_CCA_CTRL,
382160814Ssimon					CCA4758_R_ALREADY_LOADED);
383160814Ssimon			return 0;
384160814Ssimon			}
385160814Ssimon		return set_CCA4758_LIB_NAME((const char *)p);
386160814Ssimon	default:
387160814Ssimon		break;
388160814Ssimon		}
389160814Ssimon	CCA4758err(CCA4758_F_IBM_4758_CCA_CTRL,
390160814Ssimon			CCA4758_R_COMMAND_NOT_IMPLEMENTED);
391160814Ssimon	return 0;
392160814Ssimon	}
393160814Ssimon
394160814Ssimon#ifndef OPENSSL_NO_RSA
395160814Ssimon
396160814Ssimon#define MAX_CCA_PKA_TOKEN_SIZE 2500
397160814Ssimon
398160814Ssimonstatic EVP_PKEY *ibm_4758_load_privkey(ENGINE* e, const char* key_id,
399160814Ssimon			UI_METHOD *ui_method, void *callback_data)
400160814Ssimon	{
401160814Ssimon	RSA *rtmp = NULL;
402160814Ssimon	EVP_PKEY *res = NULL;
403160814Ssimon	unsigned char* keyToken = NULL;
404160814Ssimon	unsigned char pubKeyToken[MAX_CCA_PKA_TOKEN_SIZE];
405160814Ssimon	long pubKeyTokenLength = MAX_CCA_PKA_TOKEN_SIZE;
406160814Ssimon	long keyTokenLength = MAX_CCA_PKA_TOKEN_SIZE;
407160814Ssimon	long returnCode;
408160814Ssimon	long reasonCode;
409160814Ssimon	long exitDataLength = 0;
410160814Ssimon	long ruleArrayLength = 0;
411160814Ssimon	unsigned char exitData[8];
412160814Ssimon	unsigned char ruleArray[8];
413160814Ssimon	unsigned char keyLabel[64];
414160814Ssimon	unsigned long keyLabelLength = strlen(key_id);
415160814Ssimon	unsigned char modulus[256];
416160814Ssimon	long modulusFieldLength = sizeof(modulus);
417160814Ssimon	long modulusLength = 0;
418160814Ssimon	unsigned char exponent[256];
419160814Ssimon	long exponentLength = sizeof(exponent);
420160814Ssimon
421160814Ssimon	if (keyLabelLength > sizeof(keyLabel))
422160814Ssimon		{
423160814Ssimon		CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY,
424160814Ssimon		CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
425160814Ssimon		return NULL;
426160814Ssimon		}
427160814Ssimon
428160814Ssimon	memset(keyLabel,' ', sizeof(keyLabel));
429160814Ssimon	memcpy(keyLabel, key_id, keyLabelLength);
430160814Ssimon
431160814Ssimon	keyToken = OPENSSL_malloc(MAX_CCA_PKA_TOKEN_SIZE + sizeof(long));
432160814Ssimon	if (!keyToken)
433160814Ssimon		{
434160814Ssimon		CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY,
435160814Ssimon				ERR_R_MALLOC_FAILURE);
436160814Ssimon		goto err;
437160814Ssimon		}
438160814Ssimon
439160814Ssimon	keyRecordRead(&returnCode, &reasonCode, &exitDataLength,
440160814Ssimon		exitData, &ruleArrayLength, ruleArray, keyLabel,
441160814Ssimon		&keyTokenLength, keyToken+sizeof(long));
442160814Ssimon
443160814Ssimon	if (returnCode)
444160814Ssimon		{
445160814Ssimon		CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY,
446160814Ssimon			CCA4758_R_FAILED_LOADING_PRIVATE_KEY);
447160814Ssimon		goto err;
448160814Ssimon		}
449160814Ssimon
450160814Ssimon	publicKeyExtract(&returnCode, &reasonCode, &exitDataLength,
451160814Ssimon		exitData, &ruleArrayLength, ruleArray, &keyTokenLength,
452160814Ssimon		keyToken+sizeof(long), &pubKeyTokenLength, pubKeyToken);
453160814Ssimon
454160814Ssimon	if (returnCode)
455160814Ssimon		{
456160814Ssimon		CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY,
457160814Ssimon			CCA4758_R_FAILED_LOADING_PRIVATE_KEY);
458160814Ssimon		goto err;
459160814Ssimon		}
460160814Ssimon
461160814Ssimon	if (!getModulusAndExponent(pubKeyToken, &exponentLength,
462160814Ssimon			exponent, &modulusLength, &modulusFieldLength,
463160814Ssimon			modulus))
464160814Ssimon		{
465160814Ssimon		CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY,
466160814Ssimon			CCA4758_R_FAILED_LOADING_PRIVATE_KEY);
467160814Ssimon		goto err;
468160814Ssimon		}
469160814Ssimon
470160814Ssimon	(*(long*)keyToken) = keyTokenLength;
471160814Ssimon	rtmp = RSA_new_method(e);
472160814Ssimon	RSA_set_ex_data(rtmp, hndidx, (char *)keyToken);
473160814Ssimon
474160814Ssimon	rtmp->e = BN_bin2bn(exponent, exponentLength, NULL);
475160814Ssimon	rtmp->n = BN_bin2bn(modulus, modulusFieldLength, NULL);
476160814Ssimon	rtmp->flags |= RSA_FLAG_EXT_PKEY;
477160814Ssimon
478160814Ssimon	res = EVP_PKEY_new();
479160814Ssimon	EVP_PKEY_assign_RSA(res, rtmp);
480160814Ssimon
481160814Ssimon	return res;
482160814Ssimonerr:
483160814Ssimon	if (keyToken)
484160814Ssimon		OPENSSL_free(keyToken);
485160814Ssimon	return NULL;
486160814Ssimon	}
487160814Ssimon
488160814Ssimonstatic EVP_PKEY *ibm_4758_load_pubkey(ENGINE* e, const char* key_id,
489160814Ssimon			UI_METHOD *ui_method, void *callback_data)
490160814Ssimon	{
491160814Ssimon	RSA *rtmp = NULL;
492160814Ssimon	EVP_PKEY *res = NULL;
493160814Ssimon	unsigned char* keyToken = NULL;
494160814Ssimon	long keyTokenLength = MAX_CCA_PKA_TOKEN_SIZE;
495160814Ssimon	long returnCode;
496160814Ssimon	long reasonCode;
497160814Ssimon	long exitDataLength = 0;
498160814Ssimon	long ruleArrayLength = 0;
499160814Ssimon	unsigned char exitData[8];
500160814Ssimon	unsigned char ruleArray[8];
501160814Ssimon	unsigned char keyLabel[64];
502160814Ssimon	unsigned long keyLabelLength = strlen(key_id);
503160814Ssimon	unsigned char modulus[512];
504160814Ssimon	long modulusFieldLength = sizeof(modulus);
505160814Ssimon	long modulusLength = 0;
506160814Ssimon	unsigned char exponent[512];
507160814Ssimon	long exponentLength = sizeof(exponent);
508160814Ssimon
509160814Ssimon	if (keyLabelLength > sizeof(keyLabel))
510160814Ssimon		{
511160814Ssimon		CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY,
512160814Ssimon			CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
513160814Ssimon		return NULL;
514160814Ssimon		}
515160814Ssimon
516160814Ssimon	memset(keyLabel,' ', sizeof(keyLabel));
517160814Ssimon	memcpy(keyLabel, key_id, keyLabelLength);
518160814Ssimon
519160814Ssimon	keyToken = OPENSSL_malloc(MAX_CCA_PKA_TOKEN_SIZE + sizeof(long));
520160814Ssimon	if (!keyToken)
521160814Ssimon		{
522160814Ssimon		CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY,
523160814Ssimon				ERR_R_MALLOC_FAILURE);
524160814Ssimon		goto err;
525160814Ssimon		}
526160814Ssimon
527160814Ssimon	keyRecordRead(&returnCode, &reasonCode, &exitDataLength, exitData,
528160814Ssimon		&ruleArrayLength, ruleArray, keyLabel, &keyTokenLength,
529160814Ssimon		keyToken+sizeof(long));
530160814Ssimon
531160814Ssimon	if (returnCode)
532160814Ssimon		{
533160814Ssimon		CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY,
534160814Ssimon				ERR_R_MALLOC_FAILURE);
535160814Ssimon		goto err;
536160814Ssimon		}
537160814Ssimon
538160814Ssimon	if (!getModulusAndExponent(keyToken+sizeof(long), &exponentLength,
539160814Ssimon			exponent, &modulusLength, &modulusFieldLength, modulus))
540160814Ssimon		{
541160814Ssimon		CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY,
542160814Ssimon			CCA4758_R_FAILED_LOADING_PUBLIC_KEY);
543160814Ssimon		goto err;
544160814Ssimon		}
545160814Ssimon
546160814Ssimon	(*(long*)keyToken) = keyTokenLength;
547160814Ssimon	rtmp = RSA_new_method(e);
548160814Ssimon	RSA_set_ex_data(rtmp, hndidx, (char *)keyToken);
549160814Ssimon	rtmp->e = BN_bin2bn(exponent, exponentLength, NULL);
550160814Ssimon	rtmp->n = BN_bin2bn(modulus, modulusFieldLength, NULL);
551160814Ssimon	rtmp->flags |= RSA_FLAG_EXT_PKEY;
552160814Ssimon	res = EVP_PKEY_new();
553160814Ssimon	EVP_PKEY_assign_RSA(res, rtmp);
554160814Ssimon
555160814Ssimon	return res;
556160814Ssimonerr:
557160814Ssimon	if (keyToken)
558160814Ssimon		OPENSSL_free(keyToken);
559160814Ssimon	return NULL;
560160814Ssimon	}
561160814Ssimon
562160814Ssimonstatic int cca_rsa_pub_enc(int flen, const unsigned char *from,
563160814Ssimon			unsigned char *to, RSA *rsa,int padding)
564160814Ssimon	{
565160814Ssimon	long returnCode;
566160814Ssimon	long reasonCode;
567160814Ssimon	long lflen = flen;
568160814Ssimon	long exitDataLength = 0;
569160814Ssimon	unsigned char exitData[8];
570160814Ssimon	long ruleArrayLength = 1;
571160814Ssimon	unsigned char ruleArray[8] = "PKCS-1.2";
572160814Ssimon	long dataStructureLength = 0;
573160814Ssimon	unsigned char dataStructure[8];
574160814Ssimon	long outputLength = RSA_size(rsa);
575160814Ssimon	long keyTokenLength;
576160814Ssimon	unsigned char* keyToken = (unsigned char*)RSA_get_ex_data(rsa, hndidx);
577160814Ssimon
578160814Ssimon	keyTokenLength = *(long*)keyToken;
579160814Ssimon	keyToken+=sizeof(long);
580160814Ssimon
581160814Ssimon	pkaEncrypt(&returnCode, &reasonCode, &exitDataLength, exitData,
582160814Ssimon		&ruleArrayLength, ruleArray, &lflen, (unsigned char*)from,
583160814Ssimon		&dataStructureLength, dataStructure, &keyTokenLength,
584160814Ssimon		keyToken, &outputLength, to);
585160814Ssimon
586160814Ssimon	if (returnCode || reasonCode)
587160814Ssimon		return -(returnCode << 16 | reasonCode);
588160814Ssimon	return outputLength;
589160814Ssimon	}
590160814Ssimon
591160814Ssimonstatic int cca_rsa_priv_dec(int flen, const unsigned char *from,
592160814Ssimon			unsigned char *to, RSA *rsa,int padding)
593160814Ssimon	{
594160814Ssimon	long returnCode;
595160814Ssimon	long reasonCode;
596160814Ssimon	long lflen = flen;
597160814Ssimon	long exitDataLength = 0;
598160814Ssimon	unsigned char exitData[8];
599160814Ssimon	long ruleArrayLength = 1;
600160814Ssimon	unsigned char ruleArray[8] = "PKCS-1.2";
601160814Ssimon	long dataStructureLength = 0;
602160814Ssimon	unsigned char dataStructure[8];
603160814Ssimon	long outputLength = RSA_size(rsa);
604160814Ssimon	long keyTokenLength;
605160814Ssimon	unsigned char* keyToken = (unsigned char*)RSA_get_ex_data(rsa, hndidx);
606160814Ssimon
607160814Ssimon	keyTokenLength = *(long*)keyToken;
608160814Ssimon	keyToken+=sizeof(long);
609160814Ssimon
610160814Ssimon	pkaDecrypt(&returnCode, &reasonCode, &exitDataLength, exitData,
611160814Ssimon		&ruleArrayLength, ruleArray, &lflen, (unsigned char*)from,
612160814Ssimon		&dataStructureLength, dataStructure, &keyTokenLength,
613160814Ssimon		keyToken, &outputLength, to);
614160814Ssimon
615160814Ssimon	return (returnCode | reasonCode) ? 0 : 1;
616160814Ssimon	}
617160814Ssimon
618160814Ssimon#define SSL_SIG_LEN 36
619160814Ssimon
620160814Ssimonstatic int cca_rsa_verify(int type, const unsigned char *m, unsigned int m_len,
621238405Sjkim	const unsigned char *sigbuf, unsigned int siglen, const RSA *rsa)
622160814Ssimon	{
623160814Ssimon	long returnCode;
624160814Ssimon	long reasonCode;
625160814Ssimon	long lsiglen = siglen;
626160814Ssimon	long exitDataLength = 0;
627160814Ssimon	unsigned char exitData[8];
628160814Ssimon	long ruleArrayLength = 1;
629160814Ssimon	unsigned char ruleArray[8] = "PKCS-1.1";
630160814Ssimon	long keyTokenLength;
631160814Ssimon	unsigned char* keyToken = (unsigned char*)RSA_get_ex_data(rsa, hndidx);
632160814Ssimon	long length = SSL_SIG_LEN;
633160814Ssimon	long keyLength ;
634160814Ssimon	unsigned char *hashBuffer = NULL;
635160814Ssimon	X509_SIG sig;
636160814Ssimon	ASN1_TYPE parameter;
637160814Ssimon	X509_ALGOR algorithm;
638160814Ssimon	ASN1_OCTET_STRING digest;
639160814Ssimon
640160814Ssimon	keyTokenLength = *(long*)keyToken;
641160814Ssimon	keyToken+=sizeof(long);
642160814Ssimon
643160814Ssimon	if (type == NID_md5 || type == NID_sha1)
644160814Ssimon		{
645160814Ssimon		sig.algor = &algorithm;
646160814Ssimon		algorithm.algorithm = OBJ_nid2obj(type);
647160814Ssimon
648160814Ssimon		if (!algorithm.algorithm)
649160814Ssimon			{
650160814Ssimon			CCA4758err(CCA4758_F_CCA_RSA_VERIFY,
651160814Ssimon				CCA4758_R_UNKNOWN_ALGORITHM_TYPE);
652160814Ssimon			return 0;
653160814Ssimon			}
654160814Ssimon
655160814Ssimon		if (!algorithm.algorithm->length)
656160814Ssimon			{
657160814Ssimon			CCA4758err(CCA4758_F_CCA_RSA_VERIFY,
658160814Ssimon				CCA4758_R_ASN1_OID_UNKNOWN_FOR_MD);
659160814Ssimon			return 0;
660160814Ssimon			}
661160814Ssimon
662160814Ssimon		parameter.type = V_ASN1_NULL;
663160814Ssimon		parameter.value.ptr = NULL;
664160814Ssimon		algorithm.parameter = &parameter;
665160814Ssimon
666160814Ssimon		sig.digest = &digest;
667160814Ssimon		sig.digest->data = (unsigned char*)m;
668160814Ssimon		sig.digest->length = m_len;
669160814Ssimon
670160814Ssimon		length = i2d_X509_SIG(&sig, NULL);
671160814Ssimon		}
672160814Ssimon
673160814Ssimon	keyLength = RSA_size(rsa);
674160814Ssimon
675160814Ssimon	if (length - RSA_PKCS1_PADDING > keyLength)
676160814Ssimon		{
677160814Ssimon		CCA4758err(CCA4758_F_CCA_RSA_VERIFY,
678160814Ssimon			CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
679160814Ssimon		return 0;
680160814Ssimon		}
681160814Ssimon
682160814Ssimon	switch (type)
683160814Ssimon		{
684160814Ssimon		case NID_md5_sha1 :
685160814Ssimon			if (m_len != SSL_SIG_LEN)
686160814Ssimon				{
687160814Ssimon				CCA4758err(CCA4758_F_CCA_RSA_VERIFY,
688160814Ssimon				CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
689160814Ssimon				return 0;
690160814Ssimon				}
691160814Ssimon
692160814Ssimon			hashBuffer = (unsigned char *)m;
693160814Ssimon			length = m_len;
694160814Ssimon			break;
695160814Ssimon		case NID_md5 :
696160814Ssimon			{
697160814Ssimon			unsigned char *ptr;
698160814Ssimon			ptr = hashBuffer = OPENSSL_malloc(
699160814Ssimon					(unsigned int)keyLength+1);
700160814Ssimon			if (!hashBuffer)
701160814Ssimon				{
702160814Ssimon				CCA4758err(CCA4758_F_CCA_RSA_VERIFY,
703160814Ssimon						ERR_R_MALLOC_FAILURE);
704160814Ssimon				return 0;
705160814Ssimon				}
706160814Ssimon
707160814Ssimon			i2d_X509_SIG(&sig, &ptr);
708160814Ssimon			}
709160814Ssimon			break;
710160814Ssimon		case NID_sha1 :
711160814Ssimon			{
712160814Ssimon			unsigned char *ptr;
713160814Ssimon			ptr = hashBuffer = OPENSSL_malloc(
714160814Ssimon					(unsigned int)keyLength+1);
715160814Ssimon			if (!hashBuffer)
716160814Ssimon				{
717160814Ssimon				CCA4758err(CCA4758_F_CCA_RSA_VERIFY,
718160814Ssimon						ERR_R_MALLOC_FAILURE);
719160814Ssimon				return 0;
720160814Ssimon				}
721160814Ssimon			i2d_X509_SIG(&sig, &ptr);
722160814Ssimon			}
723160814Ssimon			break;
724160814Ssimon		default:
725160814Ssimon			return 0;
726160814Ssimon		}
727160814Ssimon
728160814Ssimon	digitalSignatureVerify(&returnCode, &reasonCode, &exitDataLength,
729160814Ssimon		exitData, &ruleArrayLength, ruleArray, &keyTokenLength,
730238405Sjkim		keyToken, &length, hashBuffer, &lsiglen,
731238405Sjkim						(unsigned char *)sigbuf);
732160814Ssimon
733160814Ssimon	if (type == NID_sha1 || type == NID_md5)
734160814Ssimon		{
735160814Ssimon		OPENSSL_cleanse(hashBuffer, keyLength+1);
736160814Ssimon		OPENSSL_free(hashBuffer);
737160814Ssimon		}
738160814Ssimon
739160814Ssimon	return ((returnCode || reasonCode) ? 0 : 1);
740160814Ssimon	}
741160814Ssimon
742160814Ssimon#define SSL_SIG_LEN 36
743160814Ssimon
744160814Ssimonstatic int cca_rsa_sign(int type, const unsigned char *m, unsigned int m_len,
745160814Ssimon		unsigned char *sigret, unsigned int *siglen, const RSA *rsa)
746160814Ssimon	{
747160814Ssimon	long returnCode;
748160814Ssimon	long reasonCode;
749160814Ssimon	long exitDataLength = 0;
750160814Ssimon	unsigned char exitData[8];
751160814Ssimon	long ruleArrayLength = 1;
752160814Ssimon	unsigned char ruleArray[8] = "PKCS-1.1";
753160814Ssimon	long outputLength=256;
754160814Ssimon	long outputBitLength;
755160814Ssimon	long keyTokenLength;
756160814Ssimon	unsigned char *hashBuffer = NULL;
757160814Ssimon	unsigned char* keyToken = (unsigned char*)RSA_get_ex_data(rsa, hndidx);
758160814Ssimon	long length = SSL_SIG_LEN;
759160814Ssimon	long keyLength ;
760160814Ssimon	X509_SIG sig;
761160814Ssimon	ASN1_TYPE parameter;
762160814Ssimon	X509_ALGOR algorithm;
763160814Ssimon	ASN1_OCTET_STRING digest;
764160814Ssimon
765160814Ssimon	keyTokenLength = *(long*)keyToken;
766160814Ssimon	keyToken+=sizeof(long);
767160814Ssimon
768160814Ssimon	if (type == NID_md5 || type == NID_sha1)
769160814Ssimon		{
770160814Ssimon		sig.algor = &algorithm;
771160814Ssimon		algorithm.algorithm = OBJ_nid2obj(type);
772160814Ssimon
773160814Ssimon		if (!algorithm.algorithm)
774160814Ssimon			{
775160814Ssimon			CCA4758err(CCA4758_F_CCA_RSA_SIGN,
776160814Ssimon				CCA4758_R_UNKNOWN_ALGORITHM_TYPE);
777160814Ssimon			return 0;
778160814Ssimon			}
779160814Ssimon
780160814Ssimon		if (!algorithm.algorithm->length)
781160814Ssimon			{
782160814Ssimon			CCA4758err(CCA4758_F_CCA_RSA_SIGN,
783160814Ssimon				CCA4758_R_ASN1_OID_UNKNOWN_FOR_MD);
784160814Ssimon			return 0;
785160814Ssimon			}
786160814Ssimon
787160814Ssimon		parameter.type = V_ASN1_NULL;
788160814Ssimon		parameter.value.ptr = NULL;
789160814Ssimon		algorithm.parameter = &parameter;
790160814Ssimon
791160814Ssimon		sig.digest = &digest;
792160814Ssimon		sig.digest->data = (unsigned char*)m;
793160814Ssimon		sig.digest->length = m_len;
794160814Ssimon
795160814Ssimon		length = i2d_X509_SIG(&sig, NULL);
796160814Ssimon		}
797160814Ssimon
798160814Ssimon	keyLength = RSA_size(rsa);
799160814Ssimon
800160814Ssimon	if (length - RSA_PKCS1_PADDING > keyLength)
801160814Ssimon		{
802160814Ssimon		CCA4758err(CCA4758_F_CCA_RSA_SIGN,
803160814Ssimon			CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
804160814Ssimon		return 0;
805160814Ssimon		}
806160814Ssimon
807160814Ssimon	switch (type)
808160814Ssimon		{
809160814Ssimon		case NID_md5_sha1 :
810160814Ssimon			if (m_len != SSL_SIG_LEN)
811160814Ssimon				{
812160814Ssimon				CCA4758err(CCA4758_F_CCA_RSA_SIGN,
813160814Ssimon				CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
814160814Ssimon				return 0;
815160814Ssimon				}
816160814Ssimon			hashBuffer = (unsigned char*)m;
817160814Ssimon			length = m_len;
818160814Ssimon			break;
819160814Ssimon		case NID_md5 :
820160814Ssimon			{
821160814Ssimon			unsigned char *ptr;
822160814Ssimon			ptr = hashBuffer = OPENSSL_malloc(
823160814Ssimon					(unsigned int)keyLength+1);
824160814Ssimon			if (!hashBuffer)
825160814Ssimon				{
826160814Ssimon				CCA4758err(CCA4758_F_CCA_RSA_SIGN,
827160814Ssimon						ERR_R_MALLOC_FAILURE);
828160814Ssimon				return 0;
829160814Ssimon				}
830160814Ssimon			i2d_X509_SIG(&sig, &ptr);
831160814Ssimon			}
832160814Ssimon			break;
833160814Ssimon		case NID_sha1 :
834160814Ssimon			{
835160814Ssimon			unsigned char *ptr;
836160814Ssimon			ptr = hashBuffer = OPENSSL_malloc(
837160814Ssimon					(unsigned int)keyLength+1);
838160814Ssimon			if (!hashBuffer)
839160814Ssimon				{
840160814Ssimon				CCA4758err(CCA4758_F_CCA_RSA_SIGN,
841160814Ssimon						ERR_R_MALLOC_FAILURE);
842160814Ssimon				return 0;
843160814Ssimon				}
844160814Ssimon			i2d_X509_SIG(&sig, &ptr);
845160814Ssimon			}
846160814Ssimon			break;
847160814Ssimon		default:
848160814Ssimon			return 0;
849160814Ssimon		}
850160814Ssimon
851160814Ssimon	digitalSignatureGenerate(&returnCode, &reasonCode, &exitDataLength,
852160814Ssimon		exitData, &ruleArrayLength, ruleArray, &keyTokenLength,
853160814Ssimon		keyToken, &length, hashBuffer, &outputLength, &outputBitLength,
854160814Ssimon		sigret);
855160814Ssimon
856160814Ssimon	if (type == NID_sha1 || type == NID_md5)
857160814Ssimon		{
858160814Ssimon		OPENSSL_cleanse(hashBuffer, keyLength+1);
859160814Ssimon		OPENSSL_free(hashBuffer);
860160814Ssimon		}
861160814Ssimon
862160814Ssimon	*siglen = outputLength;
863160814Ssimon
864160814Ssimon	return ((returnCode || reasonCode) ? 0 : 1);
865160814Ssimon	}
866160814Ssimon
867160814Ssimonstatic int getModulusAndExponent(const unsigned char*token, long *exponentLength,
868160814Ssimon		unsigned char *exponent, long *modulusLength, long *modulusFieldLength,
869160814Ssimon		unsigned char *modulus)
870160814Ssimon	{
871160814Ssimon	unsigned long len;
872160814Ssimon
873160814Ssimon	if (*token++ != (char)0x1E) /* internal PKA token? */
874160814Ssimon		return 0;
875160814Ssimon
876160814Ssimon	if (*token++) /* token version must be zero */
877160814Ssimon		return 0;
878160814Ssimon
879160814Ssimon	len = *token++;
880160814Ssimon	len = len << 8;
881160814Ssimon	len |= (unsigned char)*token++;
882160814Ssimon
883160814Ssimon	token += 4; /* skip reserved bytes */
884160814Ssimon
885160814Ssimon	if (*token++ == (char)0x04)
886160814Ssimon		{
887160814Ssimon		if (*token++) /* token version must be zero */
888160814Ssimon			return 0;
889160814Ssimon
890160814Ssimon		len = *token++;
891160814Ssimon		len = len << 8;
892160814Ssimon		len |= (unsigned char)*token++;
893160814Ssimon
894160814Ssimon		token+=2; /* skip reserved section */
895160814Ssimon
896160814Ssimon		len = *token++;
897160814Ssimon		len = len << 8;
898160814Ssimon		len |= (unsigned char)*token++;
899160814Ssimon
900160814Ssimon		*exponentLength = len;
901160814Ssimon
902160814Ssimon		len = *token++;
903160814Ssimon		len = len << 8;
904160814Ssimon		len |= (unsigned char)*token++;
905160814Ssimon
906160814Ssimon		*modulusLength = len;
907160814Ssimon
908160814Ssimon		len = *token++;
909160814Ssimon		len = len << 8;
910160814Ssimon		len |= (unsigned char)*token++;
911160814Ssimon
912160814Ssimon		*modulusFieldLength = len;
913160814Ssimon
914160814Ssimon		memcpy(exponent, token, *exponentLength);
915160814Ssimon		token+= *exponentLength;
916160814Ssimon
917160814Ssimon		memcpy(modulus, token, *modulusFieldLength);
918160814Ssimon		return 1;
919160814Ssimon		}
920160814Ssimon	return 0;
921160814Ssimon	}
922160814Ssimon
923160814Ssimon#endif /* OPENSSL_NO_RSA */
924160814Ssimon
925160814Ssimonstatic int cca_random_status(void)
926160814Ssimon	{
927160814Ssimon	return 1;
928160814Ssimon	}
929160814Ssimon
930160814Ssimonstatic int cca_get_random_bytes(unsigned char* buf, int num)
931160814Ssimon	{
932160814Ssimon	long ret_code;
933160814Ssimon	long reason_code;
934160814Ssimon	long exit_data_length;
935160814Ssimon	unsigned char exit_data[4];
936160814Ssimon	unsigned char form[] = "RANDOM  ";
937160814Ssimon	unsigned char rand_buf[8];
938160814Ssimon
939160814Ssimon	while(num >= (int)sizeof(rand_buf))
940160814Ssimon		{
941160814Ssimon		randomNumberGenerate(&ret_code, &reason_code, &exit_data_length,
942160814Ssimon			exit_data, form, rand_buf);
943160814Ssimon		if (ret_code)
944160814Ssimon			return 0;
945160814Ssimon		num -= sizeof(rand_buf);
946160814Ssimon		memcpy(buf, rand_buf, sizeof(rand_buf));
947160814Ssimon		buf += sizeof(rand_buf);
948160814Ssimon		}
949160814Ssimon
950160814Ssimon	if (num)
951160814Ssimon		{
952160814Ssimon		randomNumberGenerate(&ret_code, &reason_code, NULL, NULL,
953160814Ssimon			form, rand_buf);
954160814Ssimon		if (ret_code)
955160814Ssimon			return 0;
956160814Ssimon		memcpy(buf, rand_buf, num);
957160814Ssimon		}
958160814Ssimon
959160814Ssimon	return 1;
960160814Ssimon	}
961160814Ssimon
962160814Ssimon#ifndef OPENSSL_NO_RSA
963160814Ssimonstatic void cca_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad, int idx,
964160814Ssimon		long argl, void *argp)
965160814Ssimon	{
966160814Ssimon	if (item)
967160814Ssimon		OPENSSL_free(item);
968160814Ssimon	}
969160814Ssimon#endif
970160814Ssimon
971160814Ssimon/* Goo to handle building as a dynamic engine */
972160814Ssimon#ifndef OPENSSL_NO_DYNAMIC_ENGINE
973160814Ssimonstatic int bind_fn(ENGINE *e, const char *id)
974160814Ssimon	{
975160814Ssimon	if(id && (strcmp(id, engine_4758_cca_id) != 0) &&
976160814Ssimon			(strcmp(id, engine_4758_cca_id_alt) != 0))
977160814Ssimon		return 0;
978160814Ssimon	if(!bind_helper(e))
979160814Ssimon		return 0;
980160814Ssimon	return 1;
981160814Ssimon	}
982160814SsimonIMPLEMENT_DYNAMIC_CHECK_FN()
983160814SsimonIMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
984160814Ssimon#endif /* OPENSSL_NO_DYNAMIC_ENGINE */
985160814Ssimon
986160814Ssimon#endif /* !OPENSSL_NO_HW_4758_CCA */
987160814Ssimon#endif /* !OPENSSL_NO_HW */
988