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