--- /dev/null
+/* Author: Maurice Gittens <maurice@gittens.nl> */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <stdio.h>
+#include <openssl/crypto.h>
+/* #include <openssl/pem.h> */
+#include "cryptlib.h"
+#include <openssl/dso.h>
+#include <openssl/x509.h>
+#include <openssl/objects.h>
+#include <openssl/engine.h>
+
+#ifndef NO_HW
+#ifndef NO_HW_4758_CCA
+
+#ifdef FLAT_INC
+#include "hw_4758_cca.h"
+#else
+#include "vendor_defns/hw_4758_cca.h"
+#endif
+
+#include "hw_4758_cca_err.c"
+
+static int ibm_4758_cca_destroy(ENGINE *e);
+static int ibm_4758_cca_init(ENGINE *e);
+static int ibm_4758_cca_finish(ENGINE *e);
+static int ibm_4758_cca_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)());
+
+/* rsa functions */
+/*---------------*/
+#ifndef OPENSSL_NO_RSA
+static int cca_rsa_pub_enc(int flen, const unsigned char *from,
+ unsigned char *to, RSA *rsa,int padding);
+static int cca_rsa_priv_dec(int flen, const unsigned char *from,
+ unsigned char *to, RSA *rsa,int padding);
+static int cca_rsa_sign(int type, const unsigned char *m, unsigned int m_len,
+ unsigned char *sigret, unsigned int *siglen, const RSA *rsa);
+static int cca_rsa_verify(int dtype, const unsigned char *m, unsigned int m_len,
+ unsigned char *sigbuf, unsigned int siglen, const RSA *rsa);
+
+/* utility functions */
+/*-----------------------*/
+static EVP_PKEY *ibm_4758_load_privkey(ENGINE*, const char*,
+ UI_METHOD *ui_method, void *callback_data);
+static EVP_PKEY *ibm_4758_load_pubkey(ENGINE*, const char*,
+ UI_METHOD *ui_method, void *callback_data);
+
+static int getModulusAndExponent(const char *token, long *exponentLength,
+ char *exponent, long *modulusLength,
+ long *modulusFieldLength, char *modulus);
+#endif
+
+/* RAND number functions */
+/*-----------------------*/
+static int cca_get_random_bytes(unsigned char*, int );
+static int cca_random_status(void);
+
+static void cca_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
+ int index,long argl, void *argp);
+
+/* Function pointers for CCA verbs */
+/*---------------------------------*/
+#ifndef OPENSSL_NO_RSA
+static F_KEYRECORDREAD keyRecordRead;
+static F_DIGITALSIGNATUREGENERATE digitalSignatureGenerate;
+static F_DIGITALSIGNATUREVERIFY digitalSignatureVerify;
+static F_PUBLICKEYEXTRACT publicKeyExtract;
+static F_PKAENCRYPT pkaEncrypt;
+static F_PKADECRYPT pkaDecrypt;
+#endif
+static F_RANDOMNUMBERGENERATE randomNumberGenerate;
+
+/* static variables */
+/*------------------*/
+static const char def_CCA4758_LIB_NAME[] = CCA_LIB_NAME;
+static const char *CCA4758_LIB_NAME = def_CCA4758_LIB_NAME;
+#ifndef OPENSSL_NO_RSA
+static const char* n_keyRecordRead = CSNDKRR;
+static const char* n_digitalSignatureGenerate = CSNDDSG;
+static const char* n_digitalSignatureVerify = CSNDDSV;
+static const char* n_publicKeyExtract = CSNDPKX;
+static const char* n_pkaEncrypt = CSNDPKE;
+static const char* n_pkaDecrypt = CSNDPKD;
+#endif
+static const char* n_randomNumberGenerate = CSNBRNG;
+
+static int hndidx = -1;
+static DSO *dso = NULL;
+
+/* openssl engine initialization structures */
+/*------------------------------------------*/
+
+#define CCA4758_CMD_SO_PATH ENGINE_CMD_BASE
+static const ENGINE_CMD_DEFN cca4758_cmd_defns[] = {
+ {CCA4758_CMD_SO_PATH,
+ "SO_PATH",
+ "Specifies the path to the '4758cca' shared library",
+ ENGINE_CMD_FLAG_STRING},
+ {0, NULL, NULL, 0}
+ };
+
+#ifndef OPENSSL_NO_RSA
+static RSA_METHOD ibm_4758_cca_rsa =
+ {
+ "IBM 4758 CCA RSA method",
+ cca_rsa_pub_enc,
+ NULL,
+ NULL,
+ cca_rsa_priv_dec,
+ NULL, /*rsa_mod_exp,*/
+ NULL, /*mod_exp_mont,*/
+ NULL, /* init */
+ NULL, /* finish */
+ RSA_FLAG_SIGN_VER, /* flags */
+ NULL, /* app_data */
+ cca_rsa_sign, /* rsa_sign */
+ cca_rsa_verify /* rsa_verify */
+ };
+#endif
+
+static RAND_METHOD ibm_4758_cca_rand =
+ {
+ /* "IBM 4758 RAND method", */
+ NULL, /* seed */
+ cca_get_random_bytes, /* get random bytes from the card */
+ NULL, /* cleanup */
+ NULL, /* add */
+ cca_get_random_bytes, /* pseudo rand */
+ cca_random_status, /* status */
+ };
+
+static const char *engine_4758_cca_id = "4758cca";
+static const char *engine_4758_cca_name = "IBM 4758 CCA hardware engine support";
+
+/* engine implementation */
+/*-----------------------*/
+static int bind_helper(ENGINE *e)
+ {
+ if(!ENGINE_set_id(e, engine_4758_cca_id) ||
+ !ENGINE_set_name(e, engine_4758_cca_name) ||
+#ifndef OPENSSL_NO_RSA
+ !ENGINE_set_RSA(e, &ibm_4758_cca_rsa) ||
+#endif
+ !ENGINE_set_RAND(e, &ibm_4758_cca_rand) ||
+ !ENGINE_set_destroy_function(e, ibm_4758_cca_destroy) ||
+ !ENGINE_set_init_function(e, ibm_4758_cca_init) ||
+ !ENGINE_set_finish_function(e, ibm_4758_cca_finish) ||
+ !ENGINE_set_ctrl_function(e, ibm_4758_cca_ctrl) ||
+ !ENGINE_set_load_privkey_function(e, ibm_4758_load_privkey) ||
+ !ENGINE_set_load_pubkey_function(e, ibm_4758_load_pubkey) ||
+ !ENGINE_set_cmd_defns(e, cca4758_cmd_defns))
+ return 0;
+ /* Ensure the error handling is set up */
+ ERR_load_CCA4758_strings();
+ return 1;
+ }
+
+static ENGINE *engine_4758_cca(void)
+ {
+ ENGINE *ret = ENGINE_new();
+ if(!ret)
+ return NULL;
+ if(!bind_helper(ret))
+ {
+ ENGINE_free(ret);
+ return NULL;
+ }
+ return ret;
+ }
+
+void ENGINE_load_4758cca(void)
+ {
+ ENGINE *e_4758 = engine_4758_cca();
+ if (!e_4758) return;
+ ENGINE_add(e_4758);
+ ENGINE_free(e_4758);
+ ERR_clear_error();
+ }
+
+static int ibm_4758_cca_destroy(ENGINE *e)
+ {
+ ERR_unload_CCA4758_strings();
+ return 1;
+ }
+
+static int ibm_4758_cca_init(ENGINE *e)
+ {
+ if(dso)
+ {
+ CCA4758err(CCA4758_F_IBM_4758_CCA_INIT,CCA4758_R_ALREADY_LOADED);
+ goto err;
+ }
+
+ dso = DSO_load(NULL, CCA4758_LIB_NAME , NULL, 0);
+ if(!dso)
+ {
+ CCA4758err(CCA4758_F_IBM_4758_CCA_INIT,CCA4758_R_DSO_FAILURE);
+ goto err;
+ }
+
+#ifndef OPENSSL_NO_RSA
+ if(!(keyRecordRead = (F_KEYRECORDREAD)
+ DSO_bind_func(dso, n_keyRecordRead)) ||
+ !(randomNumberGenerate = (F_RANDOMNUMBERGENERATE)
+ DSO_bind_func(dso, n_randomNumberGenerate)) ||
+ !(digitalSignatureGenerate = (F_DIGITALSIGNATUREGENERATE)
+ DSO_bind_func(dso, n_digitalSignatureGenerate)) ||
+ !(digitalSignatureVerify = (F_DIGITALSIGNATUREVERIFY)
+ DSO_bind_func(dso, n_digitalSignatureVerify)) ||
+ !(publicKeyExtract = (F_PUBLICKEYEXTRACT)
+ DSO_bind_func(dso, n_publicKeyExtract)) ||
+ !(pkaEncrypt = (F_PKAENCRYPT)
+ DSO_bind_func(dso, n_pkaEncrypt)) ||
+ !(pkaDecrypt = (F_PKADECRYPT)
+ DSO_bind_func(dso, n_pkaDecrypt)))
+ {
+ CCA4758err(CCA4758_F_IBM_4758_CCA_INIT,CCA4758_R_DSO_FAILURE);
+ goto err;
+ }
+#else
+ if(!(randomNumberGenerate = (F_RANDOMNUMBERGENERATE)
+ DSO_bind_func(dso, n_randomNumberGenerate)))
+ {
+ CCA4758err(CCA4758_F_IBM_4758_CCA_INIT,CCA4758_R_DSO_FAILURE);
+ goto err;
+ }
+#endif
+
+ hndidx = RSA_get_ex_new_index(0, "IBM 4758 CCA RSA key handle",
+ NULL, NULL, cca_ex_free);
+
+ return 1;
+err:
+ if(dso)
+ DSO_free(dso);
+ dso = NULL;
+
+ keyRecordRead = (F_KEYRECORDREAD)NULL;
+ randomNumberGenerate = (F_RANDOMNUMBERGENERATE)NULL;
+ digitalSignatureGenerate = (F_DIGITALSIGNATUREGENERATE)NULL;
+ digitalSignatureVerify = (F_DIGITALSIGNATUREVERIFY)NULL;
+ publicKeyExtract = (F_PUBLICKEYEXTRACT)NULL;
+ pkaEncrypt = (F_PKAENCRYPT)NULL;
+ pkaDecrypt = (F_PKADECRYPT)NULL;
+ return 0;
+ }
+
+static int ibm_4758_cca_finish(ENGINE *e)
+ {
+ if(dso)
+ {
+ CCA4758err(CCA4758_F_IBM_4758_CCA_FINISH,
+ CCA4758_R_NOT_LOADED);
+ return 0;
+ }
+ if(!DSO_free(dso))
+ {
+ CCA4758err(CCA4758_F_IBM_4758_CCA_FINISH,
+ CCA4758_R_UNIT_FAILURE);
+ return 0;
+ }
+ dso = NULL;
+ keyRecordRead = (F_KEYRECORDREAD)NULL;
+ randomNumberGenerate = (F_RANDOMNUMBERGENERATE)NULL;
+ digitalSignatureGenerate = (F_DIGITALSIGNATUREGENERATE)NULL;
+ digitalSignatureVerify = (F_DIGITALSIGNATUREVERIFY)NULL;
+ publicKeyExtract = (F_PUBLICKEYEXTRACT)NULL;
+ pkaEncrypt = (F_PKAENCRYPT)NULL;
+ pkaDecrypt = (F_PKADECRYPT)NULL;
+ return 1;
+ }
+
+static int ibm_4758_cca_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
+ {
+ int initialised = ((dso == NULL) ? 0 : 1);
+ switch(cmd)
+ {
+ case CCA4758_CMD_SO_PATH:
+ if(p == NULL)
+ {
+ CCA4758err(CCA4758_F_IBM_4758_CCA_CTRL,
+ ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if(initialised)
+ {
+ CCA4758err(CCA4758_F_IBM_4758_CCA_CTRL,
+ CCA4758_R_ALREADY_LOADED);
+ return 0;
+ }
+ CCA4758_LIB_NAME = (const char *)p;
+ return 1;
+ default:
+ break;
+ }
+ CCA4758err(CCA4758_F_IBM_4758_CCA_CTRL,
+ CCA4758_R_COMMAND_NOT_IMPLEMENTED);
+ return 0;
+ }
+
+#ifndef OPENSSL_NO_RSA
+
+#define MAX_CCA_PKA_TOKEN_SIZE 2500
+
+static EVP_PKEY *ibm_4758_load_privkey(ENGINE* e, const char* key_id,
+ UI_METHOD *ui_method, void *callback_data)
+ {
+ RSA *rtmp = NULL;
+ EVP_PKEY *res = NULL;
+ char* keyToken = NULL;
+ char pubKeyToken[MAX_CCA_PKA_TOKEN_SIZE];
+ long pubKeyTokenLength = MAX_CCA_PKA_TOKEN_SIZE;
+ long keyTokenLength = MAX_CCA_PKA_TOKEN_SIZE;
+ long returnCode;
+ long reasonCode;
+ long exitDataLength = 0;
+ long ruleArrayLength = 0;
+ unsigned char exitData[8];
+ unsigned char ruleArray[8];
+ char keyLabel[64];
+ long keyLabelLength = strlen(key_id);
+ char modulus[256];
+ long modulusFieldLength = sizeof(modulus);
+ long modulusLength = 0;
+ char exponent[256];
+ long exponentLength = sizeof(exponent);
+
+ if (keyLabelLength > sizeof(keyLabel))
+ {
+ CCA4758err(CCA4758_F_IBM_4758_CCA_LOAD_PRIVKEY,
+ CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
+ return NULL;
+ }
+
+ memset(keyLabel,' ', sizeof(keyLabel));
+ memcpy(keyLabel, key_id, keyLabelLength);
+
+ keyToken = OPENSSL_malloc(MAX_CCA_PKA_TOKEN_SIZE + sizeof(long));
+ if (!keyToken)
+ {
+ CCA4758err(CCA4758_F_IBM_4758_CCA_LOAD_PRIVKEY,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ keyRecordRead(&returnCode, &reasonCode, &exitDataLength,
+ exitData, &ruleArrayLength, ruleArray, keyLabel,
+ &keyTokenLength, keyToken+sizeof(long));
+
+ if (returnCode)
+ {
+ CCA4758err(CCA4758_F_IBM_4758_CCA_LOAD_PRIVKEY,
+ CCA4758_R_FAILED_LOADING_PRIVATE_KEY);
+ goto err;
+ }
+
+ publicKeyExtract(&returnCode, &reasonCode, &exitDataLength,
+ exitData, &ruleArrayLength, ruleArray, &keyTokenLength,
+ keyToken+sizeof(long), &pubKeyTokenLength, pubKeyToken);
+
+ if (returnCode)
+ {
+ CCA4758err(CCA4758_F_IBM_4758_CCA_LOAD_PRIVKEY,
+ CCA4758_R_FAILED_LOADING_PRIVATE_KEY);
+ goto err;
+ }
+
+ if (!getModulusAndExponent(pubKeyToken, &exponentLength,
+ exponent, &modulusLength, &modulusFieldLength,
+ modulus))
+ {
+ CCA4758err(CCA4758_F_IBM_4758_CCA_LOAD_PRIVKEY,
+ CCA4758_R_FAILED_LOADING_PRIVATE_KEY);
+ goto err;
+ }
+
+ (*(long*)keyToken) = keyTokenLength;
+ rtmp = RSA_new_method(e);
+ RSA_set_ex_data(rtmp, hndidx, (char *)keyToken);
+
+ rtmp->e = BN_bin2bn(exponent, exponentLength, NULL);
+ rtmp->n = BN_bin2bn(modulus, modulusFieldLength, NULL);
+ rtmp->flags |= RSA_FLAG_EXT_PKEY;
+
+ res = EVP_PKEY_new();
+ EVP_PKEY_assign_RSA(res, rtmp);
+
+ return res;
+err:
+ if (keyToken)
+ OPENSSL_free(keyToken);
+ if (res)
+ EVP_PKEY_free(res);
+ if (rtmp)
+ RSA_free(rtmp);
+ return NULL;
+ }
+
+static EVP_PKEY *ibm_4758_load_pubkey(ENGINE* e, const char* key_id,
+ UI_METHOD *ui_method, void *callback_data)
+ {
+ RSA *rtmp = NULL;
+ EVP_PKEY *res = NULL;
+ char* keyToken = NULL;
+ long keyTokenLength = MAX_CCA_PKA_TOKEN_SIZE;
+ long returnCode;
+ long reasonCode;
+ long exitDataLength = 0;
+ long ruleArrayLength = 0;
+ unsigned char exitData[8];
+ unsigned char ruleArray[8];
+ char keyLabel[64];
+ long keyLabelLength = strlen(key_id);
+ char modulus[512];
+ long modulusFieldLength = sizeof(modulus);
+ long modulusLength = 0;
+ char exponent[512];
+ long exponentLength = sizeof(exponent);
+
+ if (keyLabelLength > sizeof(keyLabel))
+ {
+ CCA4758err(CCA4758_F_IBM_4758_CCA_LOAD_PRIVKEY,
+ CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
+ return NULL;
+ }
+
+ memset(keyLabel,' ', sizeof(keyLabel));
+ memcpy(keyLabel, key_id, keyLabelLength);
+
+ keyToken = OPENSSL_malloc(MAX_CCA_PKA_TOKEN_SIZE + sizeof(long));
+ if (!keyToken)
+ {
+ CCA4758err(CCA4758_F_IBM_4758_CCA_LOAD_PUBKEY,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ keyRecordRead(&returnCode, &reasonCode, &exitDataLength, exitData,
+ &ruleArrayLength, ruleArray, keyLabel, &keyTokenLength,
+ keyToken+sizeof(long));
+
+ if (returnCode)
+ {
+ CCA4758err(CCA4758_F_IBM_4758_CCA_LOAD_PRIVKEY,
+ ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!getModulusAndExponent(keyToken+sizeof(long), &exponentLength,
+ exponent, &modulusLength, &modulusFieldLength, modulus))
+ {
+ CCA4758err(CCA4758_F_IBM_4758_CCA_LOAD_PRIVKEY,
+ CCA4758_R_FAILED_LOADING_PUBLIC_KEY);
+ goto err;
+ }
+
+ (*(long*)keyToken) = keyTokenLength;
+ rtmp = RSA_new_method(e);
+ RSA_set_ex_data(rtmp, hndidx, (char *)keyToken);
+ rtmp->e = BN_bin2bn(exponent, exponentLength, NULL);
+ rtmp->n = BN_bin2bn(modulus, modulusFieldLength, NULL);
+ rtmp->flags |= RSA_FLAG_EXT_PKEY;
+ res = EVP_PKEY_new();
+ EVP_PKEY_assign_RSA(res, rtmp);
+
+ return res;
+err:
+ if (keyToken)
+ OPENSSL_free(keyToken);
+ if (res)
+ EVP_PKEY_free(res);
+ if (rtmp)
+ RSA_free(rtmp);
+ return NULL;
+ }
+
+static int cca_rsa_pub_enc(int flen, const unsigned char *from,
+ unsigned char *to, RSA *rsa,int padding)
+ {
+ long returnCode;
+ long reasonCode;
+ long lflen = flen;
+ long exitDataLength = 0;
+ unsigned char exitData[8];
+ long ruleArrayLength = 1;
+ unsigned char ruleArray[8] = "PKCS-1.2";
+ long dataStructureLength = 0;
+ unsigned char dataStructure[8];
+ long outputLength = RSA_size(rsa);
+ long keyTokenLength;
+ unsigned char* keyToken = (unsigned char*)RSA_get_ex_data(rsa, hndidx);
+
+ keyTokenLength = *(long*)keyToken;
+ keyToken+=sizeof(long);
+
+ pkaEncrypt(&returnCode, &reasonCode, &exitDataLength, exitData,
+ &ruleArrayLength, ruleArray, &lflen, (unsigned char*)from,
+ &dataStructureLength, dataStructure, &keyTokenLength,
+ keyToken, &outputLength, to);
+
+ if (returnCode || reasonCode)
+ return -(returnCode << 16 | reasonCode);
+ return outputLength;
+ }
+
+static int cca_rsa_priv_dec(int flen, const unsigned char *from,
+ unsigned char *to, RSA *rsa,int padding)
+ {
+ long returnCode;
+ long reasonCode;
+ long lflen = flen;
+ long exitDataLength = 0;
+ unsigned char exitData[8];
+ long ruleArrayLength = 1;
+ unsigned char ruleArray[8] = "PKCS-1.2";
+ long dataStructureLength = 0;
+ unsigned char dataStructure[8];
+ long outputLength = RSA_size(rsa);
+ long keyTokenLength;
+ unsigned char* keyToken = (unsigned char*)RSA_get_ex_data(rsa, hndidx);
+
+ keyTokenLength = *(long*)keyToken;
+ keyToken+=sizeof(long);
+
+ pkaDecrypt(&returnCode, &reasonCode, &exitDataLength, exitData,
+ &ruleArrayLength, ruleArray, &lflen, (unsigned char*)from,
+ &dataStructureLength, dataStructure, &keyTokenLength,
+ keyToken, &outputLength, to);
+
+ return (returnCode | reasonCode) ? 0 : 1;
+ }
+
+#define SSL_SIG_LEN 36
+
+static int cca_rsa_verify(int type, const unsigned char *m, unsigned int m_len,
+ unsigned char *sigbuf, unsigned int siglen, const RSA *rsa)
+ {
+ long returnCode;
+ long reasonCode;
+ long lsiglen = siglen;
+ long exitDataLength = 0;
+ unsigned char exitData[8];
+ long ruleArrayLength = 1;
+ unsigned char ruleArray[8] = "PKCS-1.1";
+ long keyTokenLength;
+ unsigned char* keyToken = (unsigned char*)RSA_get_ex_data(rsa, hndidx);
+ long length = SSL_SIG_LEN;
+ long keyLength ;
+ char *hashBuffer = NULL;
+ X509_SIG sig;
+ ASN1_TYPE parameter;
+ X509_ALGOR algorithm;
+ ASN1_OCTET_STRING digest;
+
+ keyTokenLength = *(long*)keyToken;
+ keyToken+=sizeof(long);
+
+ if (type == NID_md5 || type == NID_sha1)
+ {
+ sig.algor = &algorithm;
+ algorithm.algorithm = OBJ_nid2obj(type);
+
+ if (!algorithm.algorithm)
+ {
+ CCA4758err(CCA4758_F_IBM_4758_CCA_VERIFY,
+ CCA4758_R_UNKNOWN_ALGORITHM_TYPE);
+ return 0;
+ }
+
+ if (!algorithm.algorithm->length)
+ {
+ CCA4758err(CCA4758_F_IBM_4758_CCA_VERIFY,
+ CCA4758_R_ASN1_OID_UNKNOWN_FOR_MD);
+ return 0;
+ }
+
+ parameter.type = V_ASN1_NULL;
+ parameter.value.ptr = NULL;
+ algorithm.parameter = ¶meter;
+
+ sig.digest = &digest;
+ sig.digest->data = (unsigned char*)m;
+ sig.digest->length = m_len;
+
+ length = i2d_X509_SIG(&sig, NULL);
+ }
+
+ keyLength = RSA_size(rsa);
+
+ if (length - RSA_PKCS1_PADDING > keyLength)
+ {
+ CCA4758err(CCA4758_F_IBM_4758_CCA_VERIFY,
+ CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
+ return 0;
+ }
+
+ switch (type)
+ {
+ case NID_md5_sha1 :
+ if (m_len != SSL_SIG_LEN)
+ {
+ CCA4758err(CCA4758_F_IBM_4758_CCA_VERIFY,
+ CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
+ return 0;
+ }
+
+ hashBuffer = (char*)m;
+ length = m_len;
+ break;
+ case NID_md5 :
+ {
+ unsigned char *ptr;
+ ptr = hashBuffer = OPENSSL_malloc(
+ (unsigned int)keyLength+1);
+ if (!hashBuffer)
+ {
+ CCA4758err(CCA4758_F_IBM_4758_CCA_VERIFY,
+ ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ i2d_X509_SIG(&sig, &ptr);
+ }
+ break;
+ case NID_sha1 :
+ {
+ unsigned char *ptr;
+ ptr = hashBuffer = OPENSSL_malloc(
+ (unsigned int)keyLength+1);
+ if (!hashBuffer)
+ {
+ CCA4758err(CCA4758_F_IBM_4758_CCA_VERIFY,
+ ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ i2d_X509_SIG(&sig, &ptr);
+ }
+ break;
+ default:
+ return 0;
+ }
+
+ digitalSignatureVerify(&returnCode, &reasonCode, &exitDataLength,
+ exitData, &ruleArrayLength, ruleArray, &keyTokenLength,
+ keyToken, &length, hashBuffer, &lsiglen, sigbuf);
+
+ if (type == NID_sha1 || type == NID_md5)
+ {
+ memset(hashBuffer, keyLength+1, 0);
+ OPENSSL_free(hashBuffer);
+ }
+
+ return ((returnCode || reasonCode) ? 0 : 1);
+ }
+
+#define SSL_SIG_LEN 36
+
+static int cca_rsa_sign(int type, const unsigned char *m, unsigned int m_len,
+ unsigned char *sigret, unsigned int *siglen, const RSA *rsa)
+ {
+ long returnCode;
+ long reasonCode;
+ long exitDataLength = 0;
+ unsigned char exitData[8];
+ long ruleArrayLength = 1;
+ unsigned char ruleArray[8] = "PKCS-1.1";
+ long outputLength=256;
+ long outputBitLength;
+ long keyTokenLength;
+ char *hashBuffer = NULL;
+ unsigned char* keyToken = (unsigned char*)RSA_get_ex_data(rsa, hndidx);
+ long length = SSL_SIG_LEN;
+ long keyLength ;
+ X509_SIG sig;
+ ASN1_TYPE parameter;
+ X509_ALGOR algorithm;
+ ASN1_OCTET_STRING digest;
+
+ keyTokenLength = *(long*)keyToken;
+ keyToken+=sizeof(long);
+
+ if (type == NID_md5 || type == NID_sha1)
+ {
+ sig.algor = &algorithm;
+ algorithm.algorithm = OBJ_nid2obj(type);
+
+ if (!algorithm.algorithm)
+ {
+ CCA4758err(CCA4758_F_IBM_4758_CCA_SIGN,
+ CCA4758_R_UNKNOWN_ALGORITHM_TYPE);
+ return 0;
+ }
+
+ if (!algorithm.algorithm->length)
+ {
+ CCA4758err(CCA4758_F_IBM_4758_CCA_SIGN,
+ CCA4758_R_ASN1_OID_UNKNOWN_FOR_MD);
+ return 0;
+ }
+
+ parameter.type = V_ASN1_NULL;
+ parameter.value.ptr = NULL;
+ algorithm.parameter = ¶meter;
+
+ sig.digest = &digest;
+ sig.digest->data = (unsigned char*)m;
+ sig.digest->length = m_len;
+
+ length = i2d_X509_SIG(&sig, NULL);
+ }
+
+ keyLength = RSA_size(rsa);
+
+ if (length - RSA_PKCS1_PADDING > keyLength)
+ {
+ CCA4758err(CCA4758_F_IBM_4758_CCA_SIGN,
+ CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
+ return 0;
+ }
+
+ switch (type)
+ {
+ case NID_md5_sha1 :
+ if (m_len != SSL_SIG_LEN)
+ {
+ CCA4758err(CCA4758_F_IBM_4758_CCA_SIGN,
+ CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
+ return 0;
+ }
+ hashBuffer = (char*)m;
+ length = m_len;
+ break;
+ case NID_md5 :
+ {
+ unsigned char *ptr;
+ ptr = hashBuffer = OPENSSL_malloc(
+ (unsigned int)keyLength+1);
+ if (!hashBuffer)
+ {
+ CCA4758err(CCA4758_F_IBM_4758_CCA_VERIFY,
+ ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ i2d_X509_SIG(&sig, &ptr);
+ }
+ break;
+ case NID_sha1 :
+ {
+ unsigned char *ptr;
+ ptr = hashBuffer = OPENSSL_malloc(
+ (unsigned int)keyLength+1);
+ if (!hashBuffer)
+ {
+ CCA4758err(CCA4758_F_IBM_4758_CCA_VERIFY,
+ ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ i2d_X509_SIG(&sig, &ptr);
+ }
+ break;
+ default:
+ return 0;
+ }
+
+ digitalSignatureGenerate(&returnCode, &reasonCode, &exitDataLength,
+ exitData, &ruleArrayLength, ruleArray, &keyTokenLength,
+ keyToken, &length, hashBuffer, &outputLength, &outputBitLength,
+ sigret);
+
+ if (type == NID_sha1 || type == NID_md5)
+ {
+ memset(hashBuffer, keyLength+1, 0);
+ OPENSSL_free(hashBuffer);
+ }
+
+ *siglen = outputLength;
+
+ return ((returnCode || reasonCode) ? 0 : 1);
+ }
+
+static int getModulusAndExponent(const char*token, long *exponentLength,
+ char *exponent, long *modulusLength, long *modulusFieldLength,
+ char *modulus)
+ {
+ unsigned long len;
+
+ if (*token++ != (char)0x1E) /* internal PKA token? */
+ return 0;
+
+ if (*token++) /* token version must be zero */
+ return 0;
+
+ len = *token++;
+ len = len << 8;
+ len |= (unsigned char)*token++;
+
+ token += 4; /* skip reserved bytes */
+
+ if (*token++ == (char)0x04)
+ {
+ if (*token++) /* token version must be zero */
+ return 0;
+
+ len = *token++;
+ len = len << 8;
+ len |= (unsigned char)*token++;
+
+ token+=2; /* skip reserved section */
+
+ len = *token++;
+ len = len << 8;
+ len |= (unsigned char)*token++;
+
+ *exponentLength = len;
+
+ len = *token++;
+ len = len << 8;
+ len |= (unsigned char)*token++;
+
+ *modulusLength = len;
+
+ len = *token++;
+ len = len << 8;
+ len |= (unsigned char)*token++;
+
+ *modulusFieldLength = len;
+
+ memcpy(exponent, token, *exponentLength);
+ token+= *exponentLength;
+
+ memcpy(modulus, token, *modulusFieldLength);
+ return 1;
+ }
+ return 0;
+ }
+
+#endif /* OPENSSL_NO_RSA */
+
+static int cca_random_status(void)
+ {
+ return 1;
+ }
+
+static int cca_get_random_bytes(unsigned char* buf, int num)
+ {
+ long ret_code;
+ long reason_code;
+ long exit_data_length;
+ char exit_data[4];
+ char form[] = "RANDOM ";
+ char random[8];
+
+ while(num >= sizeof(random))
+ {
+ randomNumberGenerate(&ret_code, &reason_code, &exit_data_length,
+ exit_data, form, random);
+ if (ret_code)
+ return 0;
+ num -= sizeof(random);
+ memcpy(buf, random, sizeof(random));
+ buf += sizeof(random);
+ }
+
+ if (num)
+ {
+ randomNumberGenerate(&ret_code, &reason_code, NULL, NULL,
+ form, random);
+ if (ret_code)
+ return 0;
+ memcpy(buf, random, num);
+ }
+
+ return 1;
+ }
+
+static void cca_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad, int index,
+ long argl, void *argp)
+ {
+ if (item)
+ OPENSSL_free(item);
+ }
+
+/* Goo to handle building as a dynamic engine */
+#ifdef ENGINE_DYNAMIC_SUPPORT
+static int bind_fn(ENGINE *e, const char *id)
+ {
+ if(id && (strcmp(id, engine_cswift_id) != 0))
+ return 0;
+ if(!bind_helper(e))
+ return 0;
+ return 1;
+ }
+IMPLEMENT_DYNAMIC_CHECK_FN()
+IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
+#endif /* ENGINE_DYNAMIC_SUPPORT */
+
+#endif /* !NO_HW_4758_CCA */
+#endif /* !NO_HW */
--- /dev/null
+/* hw_4758_cca_err.c */
+/* ====================================================================
+ * Copyright (c) 1999-2002 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/* NOTE: this file was auto generated by the mkerr.pl script: any changes
+ * made to it will be overwritten when the script next updates this file,
+ * only reason strings will be preserved.
+ */
+
+#include <stdio.h>
+#include <openssl/err.h>
+#include "hw_4758_cca_err.h"
+
+/* BEGIN ERROR CODES */
+#ifndef OPENSSL_NO_ERR
+static ERR_STRING_DATA CCA4758_str_functs[]=
+ {
+{ERR_PACK(0,CCA4758_F_IBM_4758_CCA_CTRL,0), "IBM_4758_CCA_CTRL"},
+{ERR_PACK(0,CCA4758_F_IBM_4758_CCA_FINISH,0), "IBM_4758_CCA_FINISH"},
+{ERR_PACK(0,CCA4758_F_IBM_4758_CCA_INIT,0), "IBM_4758_CCA_INIT"},
+{ERR_PACK(0,CCA4758_F_IBM_4758_CCA_LOAD_PRIVKEY,0), "IBM_4758_CCA_LOAD_PRIVKEY"},
+{ERR_PACK(0,CCA4758_F_IBM_4758_CCA_LOAD_PUBKEY,0), "IBM_4758_CCA_LOAD_PUBKEY"},
+{ERR_PACK(0,CCA4758_F_IBM_4758_CCA_SIGN,0), "IBM_4758_CCA_SIGN"},
+{ERR_PACK(0,CCA4758_F_IBM_4758_CCA_VERIFY,0), "IBM_4758_CCA_VERIFY"},
+{0,NULL}
+ };
+
+static ERR_STRING_DATA CCA4758_str_reasons[]=
+ {
+{CCA4758_R_ALREADY_LOADED ,"already loaded"},
+{CCA4758_R_ASN1_OID_UNKNOWN_FOR_MD ,"asn1 oid unknown for md"},
+{CCA4758_R_COMMAND_NOT_IMPLEMENTED ,"command not implemented"},
+{CCA4758_R_DSO_FAILURE ,"dso failure"},
+{CCA4758_R_FAILED_LOADING_PRIVATE_KEY ,"failed loading private key"},
+{CCA4758_R_FAILED_LOADING_PUBLIC_KEY ,"failed loading public key"},
+{CCA4758_R_NOT_LOADED ,"not loaded"},
+{CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL ,"size too large or too small"},
+{CCA4758_R_UNIT_FAILURE ,"unit failure"},
+{CCA4758_R_UNKNOWN_ALGORITHM_TYPE ,"unknown algorithm type"},
+{0,NULL}
+ };
+
+#endif
+
+#ifdef CCA4758_LIB_NAME
+static ERR_STRING_DATA CCA4758_lib_name[]=
+ {
+{0 ,CCA4758_LIB_NAME},
+{0,NULL}
+ };
+#endif
+
+
+static int CCA4758_lib_error_code=0;
+static int CCA4758_error_init=1;
+
+static void ERR_load_CCA4758_strings(void)
+ {
+ if (CCA4758_lib_error_code == 0)
+ CCA4758_lib_error_code=ERR_get_next_error_library();
+
+ if (CCA4758_error_init)
+ {
+ CCA4758_error_init=0;
+#ifndef OPENSSL_NO_ERR
+ ERR_load_strings(CCA4758_lib_error_code,CCA4758_str_functs);
+ ERR_load_strings(CCA4758_lib_error_code,CCA4758_str_reasons);
+#endif
+
+#ifdef CCA4758_LIB_NAME
+ CCA4758_lib_name->error = ERR_PACK(CCA4758_lib_error_code,0,0);
+ ERR_load_strings(0,CCA4758_lib_name);
+#endif
+ }
+ }
+
+static void ERR_unload_CCA4758_strings(void)
+ {
+ if (CCA4758_error_init == 0)
+ {
+#ifndef OPENSSL_NO_ERR
+ ERR_unload_strings(CCA4758_lib_error_code,CCA4758_str_functs);
+ ERR_unload_strings(CCA4758_lib_error_code,CCA4758_str_reasons);
+#endif
+
+#ifdef CCA4758_LIB_NAME
+ ERR_unload_strings(0,CCA4758_lib_name);
+#endif
+ CCA4758_error_init=1;
+ }
+ }
+
+static void ERR_CCA4758_error(int function, int reason, char *file, int line)
+ {
+ if (CCA4758_lib_error_code == 0)
+ CCA4758_lib_error_code=ERR_get_next_error_library();
+ ERR_PUT_error(CCA4758_lib_error_code,function,reason,file,line);
+ }
--- /dev/null
+/**********************************************************************/
+/* */
+/* Prototypes of the CCA verbs used by the 4758 CCA openssl driver */
+/* */
+/* Maurice Gittens <maurice@gittens.nl> */
+/* */
+/**********************************************************************/
+
+#ifndef __HW_4758_CCA__
+#define __HW_4758_CCA__
+
+/*
+ * Only WIN32 support for now
+ */
+#if defined(WIN32)
+
+ #define CCA_LIB_NAME "CSUNSAPI"
+
+ #define CSNDPKX "CSNDPKX_32"
+ #define CSNDKRR "CSNDKRR_32"
+ #define CSNDPKE "CSNDPKE_32"
+ #define CSNDPKD "CSNDPKD_32"
+ #define CSNDDSV "CSNDDSV_32"
+ #define CSNDDSG "CSNDDSG_32"
+ #define CSNBRNG "CSNBRNG_32"
+
+ #define SECURITYAPI __stdcall
+#else
+ /* Fixme!!
+ Find out the values of these constants for other platforms.
+ */
+ #define CCA_LIB_NAME "CSUNSAPI"
+
+ #define CSNDPKX "CSNDPKX"
+ #define CSNDKRR "CSNDKRR"
+ #define CSNDPKE "CSNDPKE"
+ #define CSNDPKD "CSNDPKD"
+ #define CSNDDSV "CSNDDSV"
+ #define CSNDDSG "CSNDDSG"
+ #define CSNBRNG "CSNBRNG"
+
+ #define SECURITYAPI
+#endif
+
+/*
+ * security API prototypes
+ */
+
+/* PKA Key Record Read */
+typedef void (SECURITYAPI *F_KEYRECORDREAD)
+ (long * return_code,
+ long * reason_code,
+ long * exit_data_length,
+ unsigned char * exit_data,
+ long * rule_array_count,
+ unsigned char * rule_array,
+ unsigned char * key_label,
+ long * key_token_length,
+ unsigned char * key_token);
+
+/* Random Number Generate */
+typedef void (SECURITYAPI *F_RANDOMNUMBERGENERATE)
+ (long * return_code,
+ long * reason_code,
+ long * exit_data_length,
+ unsigned char * exit_data,
+ unsigned char * form,
+ unsigned char * random_number);
+
+/* Digital Signature Generate */
+typedef void (SECURITYAPI *F_DIGITALSIGNATUREGENERATE)
+ (long * return_code,
+ long * reason_code,
+ long * exit_data_length,
+ unsigned char * exit_data,
+ long * rule_array_count,
+ unsigned char * rule_array,
+ long * PKA_private_key_id_length,
+ unsigned char * PKA_private_key_id,
+ long * hash_length,
+ unsigned char * hash,
+ long * signature_field_length,
+ long * signature_bit_length,
+ unsigned char * signature_field);
+
+/* Digital Signature Verify */
+typedef void (SECURITYAPI *F_DIGITALSIGNATUREVERIFY)(
+ long * return_code,
+ long * reason_code,
+ long * exit_data_length,
+ unsigned char * exit_data,
+ long * rule_array_count,
+ unsigned char * rule_array,
+ long * PKA_public_key_id_length,
+ unsigned char * PKA_public_key_id,
+ long * hash_length,
+ unsigned char * hash,
+ long * signature_field_length,
+ unsigned char * signature_field);
+
+/* PKA Public Key Extract */
+typedef void (SECURITYAPI *F_PUBLICKEYEXTRACT)(
+ long * return_code,
+ long * reason_code,
+ long * exit_data_length,
+ unsigned char * exit_data,
+ long * rule_array_count,
+ unsigned char * rule_array,
+ long * source_key_identifier_length,
+ unsigned char * source_key_identifier,
+ long * target_key_token_length,
+ unsigned char * target_key_token);
+
+/* PKA Encrypt */
+typedef void (SECURITYAPI *F_PKAENCRYPT)
+ (long * return_code,
+ long * reason_code,
+ long * exit_data_length,
+ unsigned char * exit_data,
+ long * rule_array_count,
+ unsigned char * rule_array,
+ long * key_value_length,
+ unsigned char * key_value,
+ long * data_struct_length,
+ unsigned char * data_struct,
+ long * RSA_public_key_length,
+ unsigned char * RSA_public_key,
+ long * RSA_encipher_length,
+ unsigned char * RSA_encipher );
+
+/* PKA Decrypt */
+typedef void (SECURITYAPI *F_PKADECRYPT)
+ (long * return_code,
+ long * reason_code,
+ long * exit_data_length,
+ unsigned char * exit_data,
+ long * rule_array_count,
+ unsigned char * rule_array,
+ long * enciphered_key_length,
+ unsigned char * enciphered_key,
+ long * data_struct_length,
+ unsigned char * data_struct,
+ long * RSA_private_key_length,
+ unsigned char * RSA_private_key,
+ long * key_value_length,
+ unsigned char * key_value );
+
+
+#endif