1 /* crypto/engine/hw_ibmca.c */
\r
2 /* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL
\r
5 /* ====================================================================
\r
6 * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
\r
8 * Redistribution and use in source and binary forms, with or without
\r
9 * modification, are permitted provided that the following conditions
\r
12 * 1. Redistributions of source code must retain the above copyright
\r
13 * notice, this list of conditions and the following disclaimer.
\r
15 * 2. Redistributions in binary form must reproduce the above copyright
\r
16 * notice, this list of conditions and the following disclaimer in
\r
17 * the documentation and/or other materials provided with the
\r
20 * 3. All advertising materials mentioning features or use of this
\r
21 * software must display the following acknowledgment:
\r
22 * "This product includes software developed by the OpenSSL Project
\r
23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
\r
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
\r
26 * endorse or promote products derived from this software without
\r
27 * prior written permission. For written permission, please contact
\r
28 * licensing@OpenSSL.org.
\r
30 * 5. Products derived from this software may not be called "OpenSSL"
\r
31 * nor may "OpenSSL" appear in their names without prior written
\r
32 * permission of the OpenSSL Project.
\r
34 * 6. Redistributions of any form whatsoever must retain the following
\r
36 * "This product includes software developed by the OpenSSL Project
\r
37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
\r
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
\r
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
\r
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
\r
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
\r
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
\r
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
\r
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
\r
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
\r
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
\r
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
\r
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
\r
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
\r
51 * ====================================================================
\r
53 * This product includes cryptographic software written by Eric Young
\r
54 * (eay@cryptsoft.com). This product includes software written by Tim
\r
55 * Hudson (tjh@cryptsoft.com).
\r
59 /* (C) COPYRIGHT International Business Machines Corp. 2001 */
\r
62 #include <openssl/crypto.h>
\r
63 #include <openssl/dso.h>
\r
64 #include <openssl/engine.h>
\r
66 #ifndef OPENSSL_NO_HW
\r
67 #ifndef OPENSSL_NO_HW_IBMCA
\r
70 #include "ica_openssl_api.h"
\r
72 #include "vendor_defns/ica_openssl_api.h"
\r
75 #define IBMCA_LIB_NAME "ibmca engine"
\r
76 #include "hw_ibmca_err.c"
\r
78 static int ibmca_destroy(ENGINE *e);
\r
79 static int ibmca_init(ENGINE *e);
\r
80 static int ibmca_finish(ENGINE *e);
\r
81 static int ibmca_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)());
\r
83 static const char *IBMCA_F1 = "icaOpenAdapter";
\r
84 static const char *IBMCA_F2 = "icaCloseAdapter";
\r
85 static const char *IBMCA_F3 = "icaRsaModExpo";
\r
86 static const char *IBMCA_F4 = "icaRandomNumberGenerate";
\r
87 static const char *IBMCA_F5 = "icaRsaCrt";
\r
89 ICA_ADAPTER_HANDLE handle=0;
\r
92 static int ibmca_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
\r
93 const BIGNUM *m, BN_CTX *ctx);
\r
95 static int ibmca_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
\r
96 const BIGNUM *q, const BIGNUM *dmp1, const BIGNUM *dmq1,
\r
97 const BIGNUM *iqmp, BN_CTX *ctx);
\r
99 #ifndef OPENSSL_NO_RSA
\r
101 static int ibmca_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa);
\r
104 /* This function is aliased to mod_exp (with the mont stuff dropped). */
\r
105 static int ibmca_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
\r
106 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
\r
108 #ifndef OPENSSL_NO_DSA
\r
110 static int ibmca_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1,
\r
111 BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m,
\r
112 BN_CTX *ctx, BN_MONT_CTX *in_mont);
\r
113 static int ibmca_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a,
\r
114 const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
\r
115 BN_MONT_CTX *m_ctx);
\r
118 #ifndef OPENSSL_NO_DH
\r
120 /* This function is alised to mod_exp (with the DH and mont dropped). */
\r
121 static int ibmca_mod_exp_dh(const DH *dh, BIGNUM *r,
\r
122 const BIGNUM *a, const BIGNUM *p,
\r
123 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
\r
127 static int ibmca_rand_bytes(unsigned char *buf, int num);
\r
128 static int ibmca_rand_status(void);
\r
131 /* WJH - check for more commands, like in nuron */
\r
133 /* The definitions for control commands specific to this engine */
\r
134 #define IBMCA_CMD_SO_PATH ENGINE_CMD_BASE
\r
135 static const ENGINE_CMD_DEFN ibmca_cmd_defns[] = {
\r
136 {IBMCA_CMD_SO_PATH,
\r
138 "Specifies the path to the 'atasi' shared library",
\r
139 ENGINE_CMD_FLAG_STRING},
\r
143 #ifndef OPENSSL_NO_RSA
\r
144 /* Our internal RSA_METHOD that we provide pointers to */
\r
145 static RSA_METHOD ibmca_rsa =
\r
147 "Ibmca RSA method",
\r
153 ibmca_mod_exp_mont,
\r
163 #ifndef OPENSSL_NO_DSA
\r
164 /* Our internal DSA_METHOD that we provide pointers to */
\r
165 static DSA_METHOD ibmca_dsa =
\r
167 "Ibmca DSA method",
\r
168 NULL, /* dsa_do_sign */
\r
169 NULL, /* dsa_sign_setup */
\r
170 NULL, /* dsa_do_verify */
\r
171 ibmca_dsa_mod_exp, /* dsa_mod_exp */
\r
172 ibmca_mod_exp_dsa, /* bn_mod_exp */
\r
176 NULL /* app_data */
\r
180 #ifndef OPENSSL_NO_DH
\r
181 /* Our internal DH_METHOD that we provide pointers to */
\r
182 static DH_METHOD ibmca_dh =
\r
195 static RAND_METHOD ibmca_rand =
\r
197 /* "IBMCA RAND method", */
\r
206 /* Constants used when creating the ENGINE */
\r
207 static const char *engine_ibmca_id = "ibmca";
\r
208 static const char *engine_ibmca_name = "Ibmca hardware engine support";
\r
210 /* This internal function is used by ENGINE_ibmca() and possibly by the
\r
211 * "dynamic" ENGINE support too */
\r
212 static int bind_helper(ENGINE *e)
\r
214 #ifndef OPENSSL_NO_RSA
\r
215 const RSA_METHOD *meth1;
\r
217 #ifndef OPENSSL_NO_DSA
\r
218 const DSA_METHOD *meth2;
\r
220 #ifndef OPENSSL_NO_DH
\r
221 const DH_METHOD *meth3;
\r
223 if(!ENGINE_set_id(e, engine_ibmca_id) ||
\r
224 !ENGINE_set_name(e, engine_ibmca_name) ||
\r
225 #ifndef OPENSSL_NO_RSA
\r
226 !ENGINE_set_RSA(e, &ibmca_rsa) ||
\r
228 #ifndef OPENSSL_NO_DSA
\r
229 !ENGINE_set_DSA(e, &ibmca_dsa) ||
\r
231 #ifndef OPENSSL_NO_DH
\r
232 !ENGINE_set_DH(e, &ibmca_dh) ||
\r
234 !ENGINE_set_RAND(e, &ibmca_rand) ||
\r
235 !ENGINE_set_destroy_function(e, ibmca_destroy) ||
\r
236 !ENGINE_set_init_function(e, ibmca_init) ||
\r
237 !ENGINE_set_finish_function(e, ibmca_finish) ||
\r
238 !ENGINE_set_ctrl_function(e, ibmca_ctrl) ||
\r
239 !ENGINE_set_cmd_defns(e, ibmca_cmd_defns))
\r
242 #ifndef OPENSSL_NO_RSA
\r
243 /* We know that the "PKCS1_SSLeay()" functions hook properly
\r
244 * to the ibmca-specific mod_exp and mod_exp_crt so we use
\r
245 * those functions. NB: We don't use ENGINE_openssl() or
\r
246 * anything "more generic" because something like the RSAref
\r
247 * code may not hook properly, and if you own one of these
\r
248 * cards then you have the right to do RSA operations on it
\r
250 meth1 = RSA_PKCS1_SSLeay();
\r
251 ibmca_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
\r
252 ibmca_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
\r
253 ibmca_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
\r
254 ibmca_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
\r
257 #ifndef OPENSSL_NO_DSA
\r
258 /* Use the DSA_OpenSSL() method and just hook the mod_exp-ish
\r
260 meth2 = DSA_OpenSSL();
\r
261 ibmca_dsa.dsa_do_sign = meth2->dsa_do_sign;
\r
262 ibmca_dsa.dsa_sign_setup = meth2->dsa_sign_setup;
\r
263 ibmca_dsa.dsa_do_verify = meth2->dsa_do_verify;
\r
266 #ifndef OPENSSL_NO_DH
\r
267 /* Much the same for Diffie-Hellman */
\r
268 meth3 = DH_OpenSSL();
\r
269 ibmca_dh.generate_key = meth3->generate_key;
\r
270 ibmca_dh.compute_key = meth3->compute_key;
\r
273 /* Ensure the ibmca error handling is set up */
\r
274 ERR_load_IBMCA_strings();
\r
278 static ENGINE *engine_ibmca(void)
\r
280 ENGINE *ret = ENGINE_new();
\r
283 if(!bind_helper(ret))
\r
291 #ifdef ENGINE_DYNAMIC_SUPPORT
\r
294 void ENGINE_load_ibmca(void)
\r
296 /* Copied from eng_[openssl|dyn].c */
\r
297 ENGINE *toadd = engine_ibmca();
\r
300 ENGINE_free(toadd);
\r
304 /* Destructor (complements the "ENGINE_ibmca()" constructor) */
\r
305 static int ibmca_destroy(ENGINE *e)
\r
307 /* Unload the ibmca error strings so any error state including our
\r
308 * functs or reasons won't lead to a segfault (they simply get displayed
\r
309 * without corresponding string data because none will be found). */
\r
310 ERR_unload_IBMCA_strings();
\r
315 /* This is a process-global DSO handle used for loading and unloading
\r
316 * the Ibmca library. NB: This is only set (or unset) during an
\r
317 * init() or finish() call (reference counts permitting) and they're
\r
318 * operating with global locks, so this should be thread-safe
\r
321 static DSO *ibmca_dso = NULL;
\r
323 /* These are the function pointers that are (un)set when the library has
\r
324 * successfully (un)loaded. */
\r
326 static unsigned int (ICA_CALL *p_icaOpenAdapter)();
\r
327 static unsigned int (ICA_CALL *p_icaCloseAdapter)();
\r
328 static unsigned int (ICA_CALL *p_icaRsaModExpo)();
\r
329 static unsigned int (ICA_CALL *p_icaRandomNumberGenerate)();
\r
330 static unsigned int (ICA_CALL *p_icaRsaCrt)();
\r
332 /* utility function to obtain a context */
\r
333 static int get_context(ICA_ADAPTER_HANDLE *p_handle)
\r
335 unsigned int status=0;
\r
337 status = p_icaOpenAdapter(0, p_handle);
\r
343 /* similarly to release one. */
\r
344 static void release_context(ICA_ADAPTER_HANDLE handle)
\r
346 p_icaCloseAdapter(handle);
\r
349 /* (de)initialisation functions. */
\r
350 static int ibmca_init(ENGINE *e)
\r
359 if(ibmca_dso != NULL)
\r
361 IBMCAerr(IBMCA_F_IBMCA_INIT,IBMCA_R_ALREADY_LOADED);
\r
364 /* Attempt to load libatasi.so/atasi.dll/whatever. Needs to be
\r
365 * changed unfortunately because the Ibmca drivers don't have
\r
366 * standard library names that can be platform-translated well. */
\r
367 /* TODO: Work out how to actually map to the names the Ibmca
\r
368 * drivers really use - for now a symbollic link needs to be
\r
369 * created on the host system from libatasi.so to atasi.so on
\r
370 * unix variants. */
\r
372 /* WJH XXX check name translation */
\r
374 ibmca_dso = DSO_load(NULL, IBMCA_LIBNAME, NULL,
\r
375 /* DSO_FLAG_NAME_TRANSLATION */ 0);
\r
376 if(ibmca_dso == NULL)
\r
378 IBMCAerr(IBMCA_F_IBMCA_INIT,IBMCA_R_DSO_FAILURE);
\r
382 if(!(p1 = DSO_bind_func(
\r
383 ibmca_dso, IBMCA_F1)) ||
\r
384 !(p2 = DSO_bind_func(
\r
385 ibmca_dso, IBMCA_F2)) ||
\r
386 !(p3 = DSO_bind_func(
\r
387 ibmca_dso, IBMCA_F3)) ||
\r
388 !(p4 = DSO_bind_func(
\r
389 ibmca_dso, IBMCA_F4)) ||
\r
390 !(p5 = DSO_bind_func(
\r
391 ibmca_dso, IBMCA_F5)))
\r
393 IBMCAerr(IBMCA_F_IBMCA_INIT,IBMCA_R_DSO_FAILURE);
\r
397 /* Copy the pointers */
\r
399 p_icaOpenAdapter = (unsigned int (ICA_CALL *)())p1;
\r
400 p_icaCloseAdapter = (unsigned int (ICA_CALL *)())p2;
\r
401 p_icaRsaModExpo = (unsigned int (ICA_CALL *)())p3;
\r
402 p_icaRandomNumberGenerate = (unsigned int (ICA_CALL *)())p4;
\r
403 p_icaRsaCrt = (unsigned int (ICA_CALL *)())p5;
\r
405 if(!get_context(&handle))
\r
407 IBMCAerr(IBMCA_F_IBMCA_INIT,IBMCA_R_UNIT_FAILURE);
\r
414 DSO_free(ibmca_dso);
\r
416 p_icaOpenAdapter = NULL;
\r
417 p_icaCloseAdapter = NULL;
\r
418 p_icaRsaModExpo = NULL;
\r
419 p_icaRandomNumberGenerate = NULL;
\r
424 static int ibmca_finish(ENGINE *e)
\r
426 if(ibmca_dso == NULL)
\r
428 IBMCAerr(IBMCA_F_IBMCA_FINISH,IBMCA_R_NOT_LOADED);
\r
431 release_context(handle);
\r
432 if(!DSO_free(ibmca_dso))
\r
434 IBMCAerr(IBMCA_F_IBMCA_FINISH,IBMCA_R_DSO_FAILURE);
\r
442 static int ibmca_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
\r
444 int initialised = ((ibmca_dso == NULL) ? 0 : 1);
\r
447 case IBMCA_CMD_SO_PATH:
\r
450 IBMCAerr(IBMCA_F_IBMCA_CTRL,ERR_R_PASSED_NULL_PARAMETER);
\r
455 IBMCAerr(IBMCA_F_IBMCA_CTRL,IBMCA_R_ALREADY_LOADED);
\r
458 IBMCA_LIBNAME = (const char *)p;
\r
463 IBMCAerr(IBMCA_F_IBMCA_CTRL,IBMCA_R_CTRL_COMMAND_NOT_IMPLEMENTED);
\r
468 static int ibmca_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
\r
469 const BIGNUM *m, BN_CTX *ctx)
\r
471 /* I need somewhere to store temporary serialised values for
\r
472 * use with the Ibmca API calls. A neat cheat - I'll use
\r
473 * BIGNUMs from the BN_CTX but access their arrays directly as
\r
474 * byte arrays <grin>. This way I don't have to clean anything
\r
477 BIGNUM *argument=NULL;
\r
478 BIGNUM *result=NULL;
\r
481 int inLen, outLen, tmpLen;
\r
484 ICA_KEY_RSA_MODEXPO *publKey=NULL;
\r
487 to_return = 0; /* expect failure */
\r
491 IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_NOT_LOADED);
\r
494 /* Prepare the params */
\r
496 argument = BN_CTX_get(ctx);
\r
497 result = BN_CTX_get(ctx);
\r
498 key = BN_CTX_get(ctx);
\r
500 if( !argument || !result || !key)
\r
502 IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_BN_CTX_FULL);
\r
507 if(!bn_wexpand(argument, m->top) || !bn_wexpand(result, m->top) ||
\r
508 !bn_wexpand(key, sizeof(*publKey)/BN_BYTES))
\r
511 IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_BN_EXPAND_FAIL);
\r
515 publKey = (ICA_KEY_RSA_MODEXPO *)key->d;
\r
517 if (publKey == NULL)
\r
521 memset(publKey, 0, sizeof(ICA_KEY_RSA_MODEXPO));
\r
523 publKey->keyType = CORRECT_ENDIANNESS(ME_KEY_TYPE);
\r
524 publKey->keyLength = CORRECT_ENDIANNESS(sizeof(ICA_KEY_RSA_MODEXPO));
\r
525 publKey->expOffset = (char *) publKey->keyRecord - (char *) publKey;
\r
527 /* A quirk of the card: the exponent length has to be the same
\r
528 as the modulus (key) length */
\r
530 outLen = BN_num_bytes(m);
\r
532 /* check for modulus length SAB*/
\r
533 if (outLen > 256 ) {
\r
534 IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_MEXP_LENGTH_TO_LARGE);
\r
537 /* check for modulus length SAB*/
\r
540 publKey->expLength = publKey->nLength = outLen;
\r
541 /* SAB Check for underflow condition
\r
542 the size of the exponent is less than the size of the parameter
\r
543 then we have a big problem and will underflow the keyRecord
\r
544 buffer. Bad stuff could happen then
\r
546 if (outLen < BN_num_bytes(p)){
\r
547 IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_UNDERFLOW_KEYRECORD);
\r
550 /* SAB End check for underflow */
\r
553 BN_bn2bin(p, &publKey->keyRecord[publKey->expLength -
\r
555 BN_bn2bin(m, &publKey->keyRecord[publKey->expLength]);
\r
559 publKey->modulusBitLength = CORRECT_ENDIANNESS(publKey->nLength * 8);
\r
560 publKey->nOffset = CORRECT_ENDIANNESS(publKey->expOffset +
\r
561 publKey->expLength);
\r
563 publKey->expOffset = CORRECT_ENDIANNESS((char *) publKey->keyRecord -
\r
567 publKey->expLength = publKey->nLength = CORRECT_ENDIANNESS(tmpLen);
\r
569 /* Prepare the argument */
\r
571 memset(argument->d, 0, outLen);
\r
572 BN_bn2bin(a, (unsigned char *)argument->d + outLen -
\r
577 /* Perform the operation */
\r
579 if( (rc = p_icaRsaModExpo(handle, inLen,(unsigned char *)argument->d,
\r
580 publKey, &outLen, (unsigned char *)result->d))
\r
584 printf("rc = %d\n", rc);
\r
585 IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_REQUEST_FAILED);
\r
590 /* Convert the response */
\r
591 BN_bin2bn((unsigned char *)result->d, outLen, r);
\r
598 #ifndef OPENSSL_NO_RSA
\r
599 static int ibmca_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa)
\r
604 if((ctx = BN_CTX_new()) == NULL)
\r
606 if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
\r
608 if(!rsa->d || !rsa->n)
\r
610 IBMCAerr(IBMCA_F_IBMCA_RSA_MOD_EXP,
\r
611 IBMCA_R_MISSING_KEY_COMPONENTS);
\r
614 to_return = ibmca_mod_exp(r0, I, rsa->d, rsa->n, ctx);
\r
618 to_return = ibmca_mod_exp_crt(r0, I, rsa->p, rsa->q, rsa->dmp1,
\r
619 rsa->dmq1, rsa->iqmp, ctx);
\r
628 /* Ein kleines chinesisches "Restessen" */
\r
629 static int ibmca_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
\r
630 const BIGNUM *q, const BIGNUM *dmp1,
\r
631 const BIGNUM *dmq1, const BIGNUM *iqmp, BN_CTX *ctx)
\r
634 BIGNUM *argument = NULL;
\r
635 BIGNUM *result = NULL;
\r
636 BIGNUM *key = NULL;
\r
638 int to_return = 0; /* expect failure */
\r
641 ICA_KEY_RSA_CRT *privKey=NULL;
\r
645 unsigned int offset, pSize, qSize;
\r
646 /* SAB New variables */
\r
647 unsigned int keyRecordSize;
\r
648 unsigned int pbytes = BN_num_bytes(p);
\r
649 unsigned int qbytes = BN_num_bytes(q);
\r
650 unsigned int dmp1bytes = BN_num_bytes(dmp1);
\r
651 unsigned int dmq1bytes = BN_num_bytes(dmq1);
\r
652 unsigned int iqmpbytes = BN_num_bytes(iqmp);
\r
654 /* Prepare the params */
\r
657 argument = BN_CTX_get(ctx);
\r
658 result = BN_CTX_get(ctx);
\r
659 key = BN_CTX_get(ctx);
\r
661 if(!argument || !result || !key)
\r
663 IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_BN_CTX_FULL);
\r
667 if(!bn_wexpand(argument, p->top + q->top) ||
\r
668 !bn_wexpand(result, p->top + q->top) ||
\r
669 !bn_wexpand(key, sizeof(*privKey)/BN_BYTES ))
\r
671 IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_BN_EXPAND_FAIL);
\r
676 privKey = (ICA_KEY_RSA_CRT *)key->d;
\r
677 /* SAB Add check for total size in bytes of the parms does not exceed
\r
678 the buffer space we have
\r
681 keyRecordSize = pbytes+qbytes+dmp1bytes+dmq1bytes+iqmpbytes;
\r
682 if ( keyRecordSize > sizeof(privKey->keyRecord )) {
\r
683 IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_OPERANDS_TO_LARGE);
\r
687 if ( (qbytes + dmq1bytes) > 256 ){
\r
688 IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_OPERANDS_TO_LARGE);
\r
692 if ( pbytes + dmp1bytes > 256 ) {
\r
693 IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_OPERANDS_TO_LARGE);
\r
697 /* end SAB additions */
\r
699 memset(privKey, 0, sizeof(ICA_KEY_RSA_CRT));
\r
700 privKey->keyType = CORRECT_ENDIANNESS(CRT_KEY_TYPE);
\r
701 privKey->keyLength = CORRECT_ENDIANNESS(sizeof(ICA_KEY_RSA_CRT));
\r
702 privKey->modulusBitLength =
\r
703 CORRECT_ENDIANNESS(BN_num_bytes(q) * 2 * 8);
\r
706 * p,dp & qInv are 1 QWORD Larger
\r
708 privKey->pLength = CORRECT_ENDIANNESS(BN_num_bytes(p)+8);
\r
709 privKey->qLength = CORRECT_ENDIANNESS(BN_num_bytes(q));
\r
710 privKey->dpLength = CORRECT_ENDIANNESS(BN_num_bytes(dmp1)+8);
\r
711 privKey->dqLength = CORRECT_ENDIANNESS(BN_num_bytes(dmq1));
\r
712 privKey->qInvLength = CORRECT_ENDIANNESS(BN_num_bytes(iqmp)+8);
\r
714 offset = (char *) privKey->keyRecord
\r
715 - (char *) privKey;
\r
717 qSize = BN_num_bytes(q);
\r
718 pSize = qSize + 8; /* 1 QWORD larger */
\r
721 /* SAB probably aittle redundant, but we'll verify that each of the
\r
722 components which make up a key record sent ot the card does not exceed
\r
723 the space that is allocated for it. this handles the case where even if
\r
724 the total length does not exceed keyrecord zied, if the operands are funny sized
\r
725 they could cause potential side affects on either the card or the result */
\r
727 if ( (pbytes > pSize) || (dmp1bytes > pSize) ||
\r
728 (iqmpbytes > pSize) || ( qbytes >qSize) ||
\r
729 (dmq1bytes > qSize) ) {
\r
730 IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT, IBMCA_R_OPERANDS_TO_LARGE);
\r
736 privKey->dpOffset = CORRECT_ENDIANNESS(offset);
\r
739 privKey->dqOffset = CORRECT_ENDIANNESS(offset);
\r
742 privKey->pOffset = CORRECT_ENDIANNESS(offset);
\r
745 privKey->qOffset = CORRECT_ENDIANNESS(offset);
\r
748 privKey->qInvOffset = CORRECT_ENDIANNESS(offset);
\r
750 pkey = (char *) privKey->keyRecord;
\r
753 /* SAB first check that we don;t under flow the buffer */
\r
754 if ( pSize < pbytes ) {
\r
755 IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT, IBMCA_R_UNDERFLOW_CONDITION);
\r
759 /* pkey += pSize - BN_num_bytes(p); WROING this should be dmp1) */
\r
760 pkey += pSize - BN_num_bytes(dmp1);
\r
761 BN_bn2bin(dmp1, pkey);
\r
762 pkey += BN_num_bytes(dmp1); /* move the pointer */
\r
764 BN_bn2bin(dmq1, pkey); /* Copy over dmq1 */
\r
766 pkey += qSize; /* move pointer */
\r
767 pkey += pSize - BN_num_bytes(p); /* set up for zero padding of next field */
\r
769 BN_bn2bin(p, pkey);
\r
770 pkey += BN_num_bytes(p); /* increment pointer by number of bytes moved */
\r
772 BN_bn2bin(q, pkey);
\r
773 pkey += qSize ; /* move the pointer */
\r
774 pkey += pSize - BN_num_bytes(iqmp); /* Adjust for padding */
\r
775 BN_bn2bin(iqmp, pkey);
\r
777 /* Prepare the argument and response */
\r
779 outLen = CORRECT_ENDIANNESS(privKey->qLength) * 2; /* Correct endianess is used
\r
780 because the fields were converted above */
\r
782 if (outLen > 256) {
\r
783 IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_OUTLEN_TO_LARGE);
\r
787 /* SAB check for underflow here on the argeument */
\r
788 if ( outLen < BN_num_bytes(a)) {
\r
789 IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_UNDERFLOW_CONDITION);
\r
793 BN_bn2bin(a, (unsigned char *)argument->d + outLen -
\r
797 memset(result->d, 0, outLen);
\r
799 /* Perform the operation */
\r
801 if ( (rc = p_icaRsaCrt(handle, inLen, (unsigned char *)argument->d,
\r
802 privKey, &outLen, (unsigned char *)result->d)) != 0)
\r
804 printf("rc = %d\n", rc);
\r
805 IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_REQUEST_FAILED);
\r
809 /* Convert the response */
\r
811 BN_bin2bn((unsigned char *)result->d, outLen, r);
\r
820 #ifndef OPENSSL_NO_DSA
\r
821 /* This code was liberated and adapted from the commented-out code in
\r
822 * dsa_ossl.c. Because of the unoptimised form of the Ibmca acceleration
\r
823 * (it doesn't have a CRT form for RSA), this function means that an
\r
824 * Ibmca system running with a DSA server certificate can handshake
\r
825 * around 5 or 6 times faster/more than an equivalent system running with
\r
826 * RSA. Just check out the "signs" statistics from the RSA and DSA parts
\r
827 * of "openssl speed -engine ibmca dsa1024 rsa1024". */
\r
828 static int ibmca_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1,
\r
829 BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m,
\r
830 BN_CTX *ctx, BN_MONT_CTX *in_mont)
\r
836 /* let rr = a1 ^ p1 mod m */
\r
837 if (!ibmca_mod_exp(rr,a1,p1,m,ctx)) goto end;
\r
838 /* let t = a2 ^ p2 mod m */
\r
839 if (!ibmca_mod_exp(&t,a2,p2,m,ctx)) goto end;
\r
840 /* let rr = rr * t mod m */
\r
841 if (!BN_mod_mul(rr,rr,&t,m,ctx)) goto end;
\r
849 static int ibmca_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a,
\r
850 const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
\r
851 BN_MONT_CTX *m_ctx)
\r
853 return ibmca_mod_exp(r, a, p, m, ctx);
\r
857 /* This function is aliased to mod_exp (with the mont stuff dropped). */
\r
858 static int ibmca_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
\r
859 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
\r
861 return ibmca_mod_exp(r, a, p, m, ctx);
\r
864 #ifndef OPENSSL_NO_DH
\r
865 /* This function is aliased to mod_exp (with the dh and mont dropped). */
\r
866 static int ibmca_mod_exp_dh(DH const *dh, BIGNUM *r,
\r
867 const BIGNUM *a, const BIGNUM *p,
\r
868 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
\r
870 return ibmca_mod_exp(r, a, p, m, ctx);
\r
874 /* Random bytes are good */
\r
875 static int ibmca_rand_bytes(unsigned char *buf, int num)
\r
877 int to_return = 0; /* assume failure */
\r
883 IBMCAerr(IBMCA_F_IBMCA_RAND_BYTES,IBMCA_R_NOT_INITIALISED);
\r
887 ret = p_icaRandomNumberGenerate(handle, num, buf);
\r
890 IBMCAerr(IBMCA_F_IBMCA_RAND_BYTES,IBMCA_R_REQUEST_FAILED);
\r
898 static int ibmca_rand_status(void)
\r
903 /* This stuff is needed if this ENGINE is being compiled into a self-contained
\r
904 * shared-library. */
\r
905 #ifdef ENGINE_DYNAMIC_SUPPORT
\r
906 static int bind_fn(ENGINE *e, const char *id)
\r
908 if(id && (strcmp(id, engine_ibmca_id) != 0)) /* WJH XXX */
\r
910 if(!bind_helper(e))
\r
914 IMPLEMENT_DYNAMIC_CHECK_FN()
\r
915 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
\r
916 #endif /* ENGINE_DYNAMIC_SUPPORT */
\r
919 #endif /* !OPENSSL_NO_HW_IBMCA */
\r
920 #endif /* !OPENSSL_NO_HW */
\r