]> git.ipfire.org Git - thirdparty/openssl.git/blob - demos/engines/ibmca/hw_ibmca.c
indent has problems with comments that are on the right hand side of a line.
[thirdparty/openssl.git] / demos / engines / ibmca / hw_ibmca.c
1 /* crypto/engine/hw_ibmca.c */
2 /* Written by Geoff Thorpe (geoff@geoffthorpe.net) 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
28 * licensing@OpenSSL.org.
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 * (eay@cryptsoft.com). This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
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
89 ICA_ADAPTER_HANDLE handle=0;
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[] = {
136 {IBMCA_CMD_SO_PATH,
137 "SO_PATH",
138 "Specifies the path to the 'atasi' shared library",
139 ENGINE_CMD_FLAG_STRING},
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
294 void ENGINE_load_ibmca(void)
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 {
361 IBMCAerr(IBMCA_F_IBMCA_INIT,IBMCA_R_ALREADY_LOADED);
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 {
378 IBMCAerr(IBMCA_F_IBMCA_INIT,IBMCA_R_DSO_FAILURE);
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 {
393 IBMCAerr(IBMCA_F_IBMCA_INIT,IBMCA_R_DSO_FAILURE);
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 {
407 IBMCAerr(IBMCA_F_IBMCA_INIT,IBMCA_R_UNIT_FAILURE);
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 {
428 IBMCAerr(IBMCA_F_IBMCA_FINISH,IBMCA_R_NOT_LOADED);
429 return 0;
430 }
431 release_context(handle);
432 if(!DSO_free(ibmca_dso))
433 {
434 IBMCAerr(IBMCA_F_IBMCA_FINISH,IBMCA_R_DSO_FAILURE);
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 {
450 IBMCAerr(IBMCA_F_IBMCA_CTRL,ERR_R_PASSED_NULL_PARAMETER);
451 return 0;
452 }
453 if(initialised)
454 {
455 IBMCAerr(IBMCA_F_IBMCA_CTRL,IBMCA_R_ALREADY_LOADED);
456 return 0;
457 }
458 IBMCA_LIBNAME = (const char *)p;
459 return 1;
460 default:
461 break;
462 }
463 IBMCAerr(IBMCA_F_IBMCA_CTRL,IBMCA_R_CTRL_COMMAND_NOT_IMPLEMENTED);
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 {
491 IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_NOT_LOADED);
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 {
502 IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_BN_CTX_FULL);
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 {
511 IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_BN_EXPAND_FAIL);
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
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;
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 ) {
534 IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_MEXP_LENGTH_TO_LARGE);
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)){
547 IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_UNDERFLOW_KEYRECORD);
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);
585 IBMCAerr(IBMCA_F_IBMCA_MOD_EXP,IBMCA_R_REQUEST_FAILED);
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 {
610 IBMCAerr(IBMCA_F_IBMCA_RSA_MOD_EXP,
611 IBMCA_R_MISSING_KEY_COMPONENTS);
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 {
663 IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_BN_CTX_FULL);
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 {
671 IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_BN_EXPAND_FAIL);
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 )) {
683 IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_OPERANDS_TO_LARGE);
684 goto err;
685 }
686
687 if ( (qbytes + dmq1bytes) > 256 ){
688 IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_OPERANDS_TO_LARGE);
689 goto err;
690 }
691
692 if ( pbytes + dmp1bytes > 256 ) {
693 IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_OPERANDS_TO_LARGE);
694 goto err;
695 }
696
697 /* end SAB additions */
698
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);
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) ) {
730 IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT, IBMCA_R_OPERANDS_TO_LARGE);
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 ) {
755 IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT, IBMCA_R_UNDERFLOW_CONDITION);
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 /* Correct endianess is used because the fields were converted above */
780 outLen = CORRECT_ENDIANNESS(privKey->qLength) * 2;
781
782 if (outLen > 256) {
783 IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_OUTLEN_TO_LARGE);
784 goto err;
785 }
786
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);
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);
805 IBMCAerr(IBMCA_F_IBMCA_MOD_EXP_CRT,IBMCA_R_REQUEST_FAILED);
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 {
883 IBMCAerr(IBMCA_F_IBMCA_RAND_BYTES,IBMCA_R_NOT_INITIALISED);
884 goto err;
885 }
886
887 ret = p_icaRandomNumberGenerate(handle, num, buf);
888 if (ret < 0)
889 {
890 IBMCAerr(IBMCA_F_IBMCA_RAND_BYTES,IBMCA_R_REQUEST_FAILED);
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 }
914 IMPLEMENT_DYNAMIC_CHECK_FN()
915 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
916 #endif /* ENGINE_DYNAMIC_SUPPORT */
917
918
919 #endif /* !OPENSSL_NO_HW_IBMCA */
920 #endif /* !OPENSSL_NO_HW */