~brian-sidebotham/openssl-cmake/1.0.1e

« back to all changes in this revision

Viewing changes to demos/engines/ibmca/hw_ibmca.c

  • Committer: Brian Sidebotham
  • Date: 2013-10-19 21:50:27 UTC
  • Revision ID: brian.sidebotham@gmail.com-20131019215027-yzoyh4svqj87uepu
ImportĀ OpenSSLĀ 1.0.1e

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
        outLen = CORRECT_ENDIANNESS(privKey->qLength) * 2;  /* Correct endianess is used 
 
780
                                                because the fields were converted above */
 
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 */