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