OpenSSL  1.0.1c
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
hw_ibmca.c
Go to the documentation of this file.
1 /* crypto/engine/hw_ibmca.c */
2 /* Written by Geoff Thorpe ([email protected]) for the OpenSSL
3  * project 2000.
4  */
5 /* ====================================================================
6  * Copyright (c) 1999 The OpenSSL Project. All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
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
18  * distribution.
19  *
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/)"
24  *
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
29  *
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.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  * acknowledgment:
36  * "This product includes software developed by the OpenSSL Project
37  * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
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  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * ([email protected]). This product includes software written by Tim
55  * Hudson ([email protected]).
56  *
57  */
58 
59 /* (C) COPYRIGHT International Business Machines Corp. 2001 */
60 
61 #include <stdio.h>
62 #include <openssl/crypto.h>
63 #include <openssl/dso.h>
64 #include <openssl/engine.h>
65 
66 #ifndef OPENSSL_NO_HW
67 #ifndef OPENSSL_NO_HW_IBMCA
68 
69 #ifdef FLAT_INC
70 #include "ica_openssl_api.h"
71 #else
72 #include "vendor_defns/ica_openssl_api.h"
73 #endif
74 
75 #define IBMCA_LIB_NAME "ibmca engine"
76 #include "hw_ibmca_err.c"
77 
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)());
82 
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";
88 
90 
91 /* BIGNUM stuff */
92 static int ibmca_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
93  const BIGNUM *m, BN_CTX *ctx);
94 
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);
98 
99 #ifndef OPENSSL_NO_RSA
100 /* RSA stuff */
101 static int ibmca_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa);
102 #endif
103 
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);
107 
108 #ifndef OPENSSL_NO_DSA
109 /* DSA stuff */
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,
115  BN_MONT_CTX *m_ctx);
116 #endif
117 
118 #ifndef OPENSSL_NO_DH
119 /* DH stuff */
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);
124 #endif
125 
126 /* RAND stuff */
127 static int ibmca_rand_bytes(unsigned char *buf, int num);
128 static int ibmca_rand_status(void);
129 
130 
131 /* WJH - check for more commands, like in nuron */
132 
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[] = {
137  "SO_PATH",
138  "Specifies the path to the 'atasi' shared library",
140  {0, NULL, NULL, 0}
141  };
142 
143 #ifndef OPENSSL_NO_RSA
144 /* Our internal RSA_METHOD that we provide pointers to */
145 static RSA_METHOD ibmca_rsa =
146  {
147  "Ibmca RSA method",
148  NULL,
149  NULL,
150  NULL,
151  NULL,
152  ibmca_rsa_mod_exp,
153  ibmca_mod_exp_mont,
154  NULL,
155  NULL,
156  0,
157  NULL,
158  NULL,
159  NULL
160  };
161 #endif
162 
163 #ifndef OPENSSL_NO_DSA
164 /* Our internal DSA_METHOD that we provide pointers to */
165 static DSA_METHOD ibmca_dsa =
166  {
167  "Ibmca DSA method",
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 */
173  NULL, /* init */
174  NULL, /* finish */
175  0, /* flags */
176  NULL /* app_data */
177  };
178 #endif
179 
180 #ifndef OPENSSL_NO_DH
181 /* Our internal DH_METHOD that we provide pointers to */
182 static DH_METHOD ibmca_dh =
183  {
184  "Ibmca DH method",
185  NULL,
186  NULL,
187  ibmca_mod_exp_dh,
188  NULL,
189  NULL,
190  0,
191  NULL
192  };
193 #endif
194 
195 static RAND_METHOD ibmca_rand =
196  {
197  /* "IBMCA RAND method", */
198  NULL,
199  ibmca_rand_bytes,
200  NULL,
201  NULL,
202  ibmca_rand_bytes,
203  ibmca_rand_status,
204  };
205 
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";
209 
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)
213  {
214 #ifndef OPENSSL_NO_RSA
215  const RSA_METHOD *meth1;
216 #endif
217 #ifndef OPENSSL_NO_DSA
218  const DSA_METHOD *meth2;
219 #endif
220 #ifndef OPENSSL_NO_DH
221  const DH_METHOD *meth3;
222 #endif
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) ||
227 #endif
228 #ifndef OPENSSL_NO_DSA
229  !ENGINE_set_DSA(e, &ibmca_dsa) ||
230 #endif
231 #ifndef OPENSSL_NO_DH
232  !ENGINE_set_DH(e, &ibmca_dh) ||
233 #endif
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))
240  return 0;
241 
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
249  * anyway! */
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;
255 #endif
256 
257 #ifndef OPENSSL_NO_DSA
258  /* Use the DSA_OpenSSL() method and just hook the mod_exp-ish
259  * bits. */
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;
264 #endif
265 
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;
271 #endif
272 
273  /* Ensure the ibmca error handling is set up */
274  ERR_load_IBMCA_strings();
275  return 1;
276  }
277 
278 static ENGINE *engine_ibmca(void)
279  {
280  ENGINE *ret = ENGINE_new();
281  if(!ret)
282  return NULL;
283  if(!bind_helper(ret))
284  {
285  ENGINE_free(ret);
286  return NULL;
287  }
288  return ret;
289  }
290 
291 #ifdef ENGINE_DYNAMIC_SUPPORT
292 static
293 #endif
295  {
296  /* Copied from eng_[openssl|dyn].c */
297  ENGINE *toadd = engine_ibmca();
298  if(!toadd) return;
299  ENGINE_add(toadd);
300  ENGINE_free(toadd);
301  ERR_clear_error();
302  }
303 
304 /* Destructor (complements the "ENGINE_ibmca()" constructor) */
305 static int ibmca_destroy(ENGINE *e)
306  {
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();
311  return 1;
312  }
313 
314 
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
319  * implicitly. */
320 
321 static DSO *ibmca_dso = NULL;
322 
323 /* These are the function pointers that are (un)set when the library has
324  * successfully (un)loaded. */
325 
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)();
331 
332 /* utility function to obtain a context */
333 static int get_context(ICA_ADAPTER_HANDLE *p_handle)
334  {
335  unsigned int status=0;
336 
337  status = p_icaOpenAdapter(0, p_handle);
338  if(status != 0)
339  return 0;
340  return 1;
341  }
342 
343 /* similarly to release one. */
344 static void release_context(ICA_ADAPTER_HANDLE handle)
345  {
346  p_icaCloseAdapter(handle);
347  }
348 
349 /* (de)initialisation functions. */
350 static int ibmca_init(ENGINE *e)
351  {
352 
353  void (*p1)();
354  void (*p2)();
355  void (*p3)();
356  void (*p4)();
357  void (*p5)();
358 
359  if(ibmca_dso != NULL)
360  {
362  goto err;
363  }
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
370  * unix variants. */
371 
372  /* WJH XXX check name translation */
373 
374  ibmca_dso = DSO_load(NULL, IBMCA_LIBNAME, NULL,
375  /* DSO_FLAG_NAME_TRANSLATION */ 0);
376  if(ibmca_dso == NULL)
377  {
379  goto err;
380  }
381 
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)))
392  {
394  goto err;
395  }
396 
397  /* Copy the pointers */
398 
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;
404 
405  if(!get_context(&handle))
406  {
408  goto err;
409  }
410 
411  return 1;
412  err:
413  if(ibmca_dso)
414  DSO_free(ibmca_dso);
415 
416  p_icaOpenAdapter = NULL;
417  p_icaCloseAdapter = NULL;
418  p_icaRsaModExpo = NULL;
419  p_icaRandomNumberGenerate = NULL;
420 
421  return 0;
422  }
423 
424 static int ibmca_finish(ENGINE *e)
425  {
426  if(ibmca_dso == NULL)
427  {
429  return 0;
430  }
431  release_context(handle);
432  if(!DSO_free(ibmca_dso))
433  {
435  return 0;
436  }
437  ibmca_dso = NULL;
438 
439  return 1;
440  }
441 
442 static int ibmca_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
443  {
444  int initialised = ((ibmca_dso == NULL) ? 0 : 1);
445  switch(cmd)
446  {
447  case IBMCA_CMD_SO_PATH:
448  if(p == NULL)
449  {
451  return 0;
452  }
453  if(initialised)
454  {
456  return 0;
457  }
458  IBMCA_LIBNAME = (const char *)p;
459  return 1;
460  default:
461  break;
462  }
464  return 0;
465  }
466 
467 
468 static int ibmca_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
469  const BIGNUM *m, BN_CTX *ctx)
470  {
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
475  * up. */
476 
477  BIGNUM *argument=NULL;
478  BIGNUM *result=NULL;
479  BIGNUM *key=NULL;
480  int to_return;
481  int inLen, outLen, tmpLen;
482 
483 
484  ICA_KEY_RSA_MODEXPO *publKey=NULL;
485  unsigned int rc;
486 
487  to_return = 0; /* expect failure */
488 
489  if(!ibmca_dso)
490  {
492  goto err;
493  }
494  /* Prepare the params */
495  BN_CTX_start(ctx);
496  argument = BN_CTX_get(ctx);
497  result = BN_CTX_get(ctx);
498  key = BN_CTX_get(ctx);
499 
500  if( !argument || !result || !key)
501  {
503  goto err;
504  }
505 
506 
507  if(!bn_wexpand(argument, m->top) || !bn_wexpand(result, m->top) ||
508  !bn_wexpand(key, sizeof(*publKey)/BN_BYTES))
509 
510  {
512  goto err;
513  }
514 
515  publKey = (ICA_KEY_RSA_MODEXPO *)key->d;
516 
517  if (publKey == NULL)
518  {
519  goto err;
520  }
521  memset(publKey, 0, sizeof(ICA_KEY_RSA_MODEXPO));
522 
525  publKey->expOffset = (char *) publKey->keyRecord - (char *) publKey;
526 
527  /* A quirk of the card: the exponent length has to be the same
528  as the modulus (key) length */
529 
530  outLen = BN_num_bytes(m);
531 
532 /* check for modulus length SAB*/
533  if (outLen > 256 ) {
535  goto err;
536  }
537 /* check for modulus length SAB*/
538 
539 
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
545 */
546 if (outLen < BN_num_bytes(p)){
548  goto err;
549 }
550 /* SAB End check for underflow */
551 
552 
553  BN_bn2bin(p, &publKey->keyRecord[publKey->expLength -
554  BN_num_bytes(p)]);
555  BN_bn2bin(m, &publKey->keyRecord[publKey->expLength]);
556 
557 
558 
559  publKey->modulusBitLength = CORRECT_ENDIANNESS(publKey->nLength * 8);
560  publKey->nOffset = CORRECT_ENDIANNESS(publKey->expOffset +
561  publKey->expLength);
562 
563  publKey->expOffset = CORRECT_ENDIANNESS((char *) publKey->keyRecord -
564  (char *) publKey);
565 
566  tmpLen = outLen;
567  publKey->expLength = publKey->nLength = CORRECT_ENDIANNESS(tmpLen);
568 
569  /* Prepare the argument */
570 
571  memset(argument->d, 0, outLen);
572  BN_bn2bin(a, (unsigned char *)argument->d + outLen -
573  BN_num_bytes(a));
574 
575  inLen = outLen;
576 
577  /* Perform the operation */
578 
579  if( (rc = p_icaRsaModExpo(handle, inLen,(unsigned char *)argument->d,
580  publKey, &outLen, (unsigned char *)result->d))
581  !=0 )
582 
583  {
584  printf("rc = %d\n", rc);
586  goto err;
587  }
588 
589 
590  /* Convert the response */
591  BN_bin2bn((unsigned char *)result->d, outLen, r);
592  to_return = 1;
593  err:
594  BN_CTX_end(ctx);
595  return to_return;
596  }
597 
598 #ifndef OPENSSL_NO_RSA
599 static int ibmca_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa)
600  {
601  BN_CTX *ctx;
602  int to_return = 0;
603 
604  if((ctx = BN_CTX_new()) == NULL)
605  goto err;
606  if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
607  {
608  if(!rsa->d || !rsa->n)
609  {
612  goto err;
613  }
614  to_return = ibmca_mod_exp(r0, I, rsa->d, rsa->n, ctx);
615  }
616  else
617  {
618  to_return = ibmca_mod_exp_crt(r0, I, rsa->p, rsa->q, rsa->dmp1,
619  rsa->dmq1, rsa->iqmp, ctx);
620  }
621  err:
622  if(ctx)
623  BN_CTX_free(ctx);
624  return to_return;
625  }
626 #endif
627 
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)
632  {
633 
634  BIGNUM *argument = NULL;
635  BIGNUM *result = NULL;
636  BIGNUM *key = NULL;
637 
638  int to_return = 0; /* expect failure */
639 
640  char *pkey=NULL;
641  ICA_KEY_RSA_CRT *privKey=NULL;
642  int inLen, outLen;
643 
644  int rc;
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);
653 
654  /* Prepare the params */
655 
656  BN_CTX_start(ctx);
657  argument = BN_CTX_get(ctx);
658  result = BN_CTX_get(ctx);
659  key = BN_CTX_get(ctx);
660 
661  if(!argument || !result || !key)
662  {
664  goto err;
665  }
666 
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 ))
670  {
672  goto err;
673  }
674 
675 
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
679  do this first
680 */
681  keyRecordSize = pbytes+qbytes+dmp1bytes+dmq1bytes+iqmpbytes;
682  if ( keyRecordSize > sizeof(privKey->keyRecord )) {
684  goto err;
685  }
686 
687  if ( (qbytes + dmq1bytes) > 256 ){
689  goto err;
690  }
691 
692  if ( pbytes + dmp1bytes > 256 ) {
694  goto err;
695  }
696 
697 /* end SAB additions */
698 
699  memset(privKey, 0, sizeof(ICA_KEY_RSA_CRT));
701  privKey->keyLength = CORRECT_ENDIANNESS(sizeof(ICA_KEY_RSA_CRT));
702  privKey->modulusBitLength =
703  CORRECT_ENDIANNESS(BN_num_bytes(q) * 2 * 8);
704 
705  /*
706  * p,dp & qInv are 1 QWORD Larger
707  */
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);
713 
714  offset = (char *) privKey->keyRecord
715  - (char *) privKey;
716 
717  qSize = BN_num_bytes(q);
718  pSize = qSize + 8; /* 1 QWORD larger */
719 
720 
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 */
726 
727  if ( (pbytes > pSize) || (dmp1bytes > pSize) ||
728  (iqmpbytes > pSize) || ( qbytes >qSize) ||
729  (dmq1bytes > qSize) ) {
731  goto err;
732 
733  }
734 
735 
736  privKey->dpOffset = CORRECT_ENDIANNESS(offset);
737 
738  offset += pSize;
739  privKey->dqOffset = CORRECT_ENDIANNESS(offset);
740 
741  offset += qSize;
742  privKey->pOffset = CORRECT_ENDIANNESS(offset);
743 
744  offset += pSize;
745  privKey->qOffset = CORRECT_ENDIANNESS(offset);
746 
747  offset += qSize;
748  privKey->qInvOffset = CORRECT_ENDIANNESS(offset);
749 
750  pkey = (char *) privKey->keyRecord;
751 
752 
753 /* SAB first check that we don;t under flow the buffer */
754  if ( pSize < pbytes ) {
756  goto err;
757  }
758 
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 */
763 
764  BN_bn2bin(dmq1, pkey); /* Copy over dmq1 */
765 
766  pkey += qSize; /* move pointer */
767  pkey += pSize - BN_num_bytes(p); /* set up for zero padding of next field */
768 
769  BN_bn2bin(p, pkey);
770  pkey += BN_num_bytes(p); /* increment pointer by number of bytes moved */
771 
772  BN_bn2bin(q, pkey);
773  pkey += qSize ; /* move the pointer */
774  pkey += pSize - BN_num_bytes(iqmp); /* Adjust for padding */
775  BN_bn2bin(iqmp, pkey);
776 
777  /* Prepare the argument and response */
778 
779  outLen = CORRECT_ENDIANNESS(privKey->qLength) * 2; /* Correct endianess is used
780  because the fields were converted above */
781 
782  if (outLen > 256) {
784  goto err;
785  }
786 
787  /* SAB check for underflow here on the argeument */
788  if ( outLen < BN_num_bytes(a)) {
790  goto err;
791  }
792 
793  BN_bn2bin(a, (unsigned char *)argument->d + outLen -
794  BN_num_bytes(a));
795  inLen = outLen;
796 
797  memset(result->d, 0, outLen);
798 
799  /* Perform the operation */
800 
801  if ( (rc = p_icaRsaCrt(handle, inLen, (unsigned char *)argument->d,
802  privKey, &outLen, (unsigned char *)result->d)) != 0)
803  {
804  printf("rc = %d\n", rc);
806  goto err;
807  }
808 
809  /* Convert the response */
810 
811  BN_bin2bn((unsigned char *)result->d, outLen, r);
812  to_return = 1;
813 
814  err:
815  BN_CTX_end(ctx);
816  return to_return;
817 
818  }
819 
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)
831  {
832  BIGNUM t;
833  int to_return = 0;
834 
835  BN_init(&t);
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;
842  to_return = 1;
843  end:
844  BN_free(&t);
845  return to_return;
846  }
847 
848 
849 static int ibmca_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a,
850  const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
851  BN_MONT_CTX *m_ctx)
852  {
853  return ibmca_mod_exp(r, a, p, m, ctx);
854  }
855 #endif
856 
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)
860  {
861  return ibmca_mod_exp(r, a, p, m, ctx);
862  }
863 
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)
869  {
870  return ibmca_mod_exp(r, a, p, m, ctx);
871  }
872 #endif
873 
874 /* Random bytes are good */
875 static int ibmca_rand_bytes(unsigned char *buf, int num)
876  {
877  int to_return = 0; /* assume failure */
878  unsigned int ret;
879 
880 
881  if(handle == 0)
882  {
884  goto err;
885  }
886 
887  ret = p_icaRandomNumberGenerate(handle, num, buf);
888  if (ret < 0)
889  {
891  goto err;
892  }
893  to_return = 1;
894  err:
895  return to_return;
896  }
897 
898 static int ibmca_rand_status(void)
899  {
900  return 1;
901  }
902 
903 /* This stuff is needed if this ENGINE is being compiled into a self-contained
904  * shared-library. */
905 #ifdef ENGINE_DYNAMIC_SUPPORT
906 static int bind_fn(ENGINE *e, const char *id)
907  {
908  if(id && (strcmp(id, engine_ibmca_id) != 0)) /* WJH XXX */
909  return 0;
910  if(!bind_helper(e))
911  return 0;
912  return 1;
913  }
916 #endif /* ENGINE_DYNAMIC_SUPPORT */
917 
918 
919 #endif /* !OPENSSL_NO_HW_IBMCA */
920 #endif /* !OPENSSL_NO_HW */