Coverage Report

Created: 2022-11-30 06:20

/src/openssl/engines/e_chil.c
Line
Count
Source (jump to first uncovered line)
1
/* crypto/engine/e_chil.c */
2
/*
3
 * Written by Richard Levitte (richard@levitte.org), Geoff Thorpe
4
 * (geoff@geoffthorpe.net) and Dr Stephen N Henson (steve@openssl.org) for
5
 * the OpenSSL project 2000.
6
 */
7
/* ====================================================================
8
 * Copyright (c) 1999-2001 The OpenSSL Project.  All rights reserved.
9
 *
10
 * Redistribution and use in source and binary forms, with or without
11
 * modification, are permitted provided that the following conditions
12
 * are met:
13
 *
14
 * 1. Redistributions of source code must retain the above copyright
15
 *    notice, this list of conditions and the following disclaimer.
16
 *
17
 * 2. Redistributions in binary form must reproduce the above copyright
18
 *    notice, this list of conditions and the following disclaimer in
19
 *    the documentation and/or other materials provided with the
20
 *    distribution.
21
 *
22
 * 3. All advertising materials mentioning features or use of this
23
 *    software must display the following acknowledgment:
24
 *    "This product includes software developed by the OpenSSL Project
25
 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
26
 *
27
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
28
 *    endorse or promote products derived from this software without
29
 *    prior written permission. For written permission, please contact
30
 *    licensing@OpenSSL.org.
31
 *
32
 * 5. Products derived from this software may not be called "OpenSSL"
33
 *    nor may "OpenSSL" appear in their names without prior written
34
 *    permission of the OpenSSL Project.
35
 *
36
 * 6. Redistributions of any form whatsoever must retain the following
37
 *    acknowledgment:
38
 *    "This product includes software developed by the OpenSSL Project
39
 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
40
 *
41
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
42
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
44
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
45
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
47
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
48
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
50
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
51
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
52
 * OF THE POSSIBILITY OF SUCH DAMAGE.
53
 * ====================================================================
54
 *
55
 * This product includes cryptographic software written by Eric Young
56
 * (eay@cryptsoft.com).  This product includes software written by Tim
57
 * Hudson (tjh@cryptsoft.com).
58
 *
59
 */
60
61
#include <stdio.h>
62
#include <string.h>
63
#include <openssl/crypto.h>
64
#include <openssl/pem.h>
65
#include <openssl/dso.h>
66
#include <openssl/engine.h>
67
#include <openssl/ui.h>
68
#include <openssl/rand.h>
69
#ifndef OPENSSL_NO_RSA
70
# include <openssl/rsa.h>
71
#endif
72
#ifndef OPENSSL_NO_DH
73
# include <openssl/dh.h>
74
#endif
75
#include <openssl/bn.h>
76
77
#ifndef OPENSSL_NO_HW
78
# ifndef OPENSSL_NO_HW_CHIL
79
80
/*-
81
 * Attribution notice: nCipher have said several times that it's OK for
82
 * us to implement a general interface to their boxes, and recently declared
83
 * their HWCryptoHook to be public, and therefore available for us to use.
84
 * Thanks, nCipher.
85
 *
86
 * The hwcryptohook.h included here is from May 2000.
87
 * [Richard Levitte]
88
 */
89
#  ifdef FLAT_INC
90
#   include "hwcryptohook.h"
91
#  else
92
#   include "vendor_defns/hwcryptohook.h"
93
#  endif
94
95
#  define HWCRHK_LIB_NAME "CHIL engine"
96
#  include "e_chil_err.c"
97
98
static int hwcrhk_destroy(ENGINE *e);
99
static int hwcrhk_init(ENGINE *e);
100
static int hwcrhk_finish(ENGINE *e);
101
static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void));
102
103
/* Functions to handle mutexes */
104
static int hwcrhk_mutex_init(HWCryptoHook_Mutex *,
105
                             HWCryptoHook_CallerContext *);
106
static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *);
107
static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex *);
108
static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *);
109
110
/* BIGNUM stuff */
111
static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
112
                          const BIGNUM *m, BN_CTX *ctx);
113
114
#  ifndef OPENSSL_NO_RSA
115
/* RSA stuff */
116
static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa,
117
                              BN_CTX *ctx);
118
/* This function is aliased to mod_exp (with the mont stuff dropped). */
119
static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
120
                               const BIGNUM *m, BN_CTX *ctx,
121
                               BN_MONT_CTX *m_ctx);
122
static int hwcrhk_rsa_finish(RSA *rsa);
123
#  endif
124
125
#  ifndef OPENSSL_NO_DH
126
/* DH stuff */
127
/* This function is alised to mod_exp (with the DH and mont dropped). */
128
static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
129
                             const BIGNUM *a, const BIGNUM *p,
130
                             const BIGNUM *m, BN_CTX *ctx,
131
                             BN_MONT_CTX *m_ctx);
132
#  endif
133
134
/* RAND stuff */
135
static int hwcrhk_rand_bytes(unsigned char *buf, int num);
136
static int hwcrhk_rand_status(void);
137
138
/* KM stuff */
139
static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
140
                                     UI_METHOD *ui_method,
141
                                     void *callback_data);
142
static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
143
                                    UI_METHOD *ui_method,
144
                                    void *callback_data);
145
146
/* Interaction stuff */
147
static int hwcrhk_insert_card(const char *prompt_info,
148
                              const char *wrong_info,
149
                              HWCryptoHook_PassphraseContext * ppctx,
150
                              HWCryptoHook_CallerContext * cactx);
151
static int hwcrhk_get_pass(const char *prompt_info,
152
                           int *len_io, char *buf,
153
                           HWCryptoHook_PassphraseContext * ppctx,
154
                           HWCryptoHook_CallerContext * cactx);
155
static void hwcrhk_log_message(void *logstr, const char *message);
156
157
/* The definitions for control commands specific to this engine */
158
0
#  define HWCRHK_CMD_SO_PATH              ENGINE_CMD_BASE
159
0
#  define HWCRHK_CMD_FORK_CHECK           (ENGINE_CMD_BASE + 1)
160
0
#  define HWCRHK_CMD_THREAD_LOCKING       (ENGINE_CMD_BASE + 2)
161
0
#  define HWCRHK_CMD_SET_USER_INTERFACE   (ENGINE_CMD_BASE + 3)
162
0
#  define HWCRHK_CMD_SET_CALLBACK_DATA    (ENGINE_CMD_BASE + 4)
163
static const ENGINE_CMD_DEFN hwcrhk_cmd_defns[] = {
164
    {HWCRHK_CMD_SO_PATH,
165
     "SO_PATH",
166
     "Specifies the path to the 'hwcrhk' shared library",
167
     ENGINE_CMD_FLAG_STRING},
168
    {HWCRHK_CMD_FORK_CHECK,
169
     "FORK_CHECK",
170
     "Turns fork() checking on (non-zero) or off (zero)",
171
     ENGINE_CMD_FLAG_NUMERIC},
172
    {HWCRHK_CMD_THREAD_LOCKING,
173
     "THREAD_LOCKING",
174
     "Turns thread-safe locking on (zero) or off (non-zero)",
175
     ENGINE_CMD_FLAG_NUMERIC},
176
    {HWCRHK_CMD_SET_USER_INTERFACE,
177
     "SET_USER_INTERFACE",
178
     "Set the global user interface (internal)",
179
     ENGINE_CMD_FLAG_INTERNAL},
180
    {HWCRHK_CMD_SET_CALLBACK_DATA,
181
     "SET_CALLBACK_DATA",
182
     "Set the global user interface extra data (internal)",
183
     ENGINE_CMD_FLAG_INTERNAL},
184
    {0, NULL, NULL, 0}
185
};
186
187
#  ifndef OPENSSL_NO_RSA
188
/* Our internal RSA_METHOD that we provide pointers to */
189
static RSA_METHOD hwcrhk_rsa = {
190
    "CHIL RSA method",
191
    NULL,
192
    NULL,
193
    NULL,
194
    NULL,
195
    hwcrhk_rsa_mod_exp,
196
    hwcrhk_mod_exp_mont,
197
    NULL,
198
    hwcrhk_rsa_finish,
199
    0,
200
    NULL,
201
    NULL,
202
    NULL,
203
    NULL
204
};
205
#  endif
206
207
#  ifndef OPENSSL_NO_DH
208
/* Our internal DH_METHOD that we provide pointers to */
209
static DH_METHOD hwcrhk_dh = {
210
    "CHIL DH method",
211
    NULL,
212
    NULL,
213
    hwcrhk_mod_exp_dh,
214
    NULL,
215
    NULL,
216
    0,
217
    NULL,
218
    NULL
219
};
220
#  endif
221
222
static RAND_METHOD hwcrhk_rand = {
223
    /* "CHIL RAND method", */
224
    NULL,
225
    hwcrhk_rand_bytes,
226
    NULL,
227
    NULL,
228
    hwcrhk_rand_bytes,
229
    hwcrhk_rand_status,
230
};
231
232
/* Constants used when creating the ENGINE */
233
static const char *engine_hwcrhk_id = "chil";
234
static const char *engine_hwcrhk_name = "CHIL hardware engine support";
235
#  ifndef OPENSSL_NO_DYNAMIC_ENGINE
236
/* Compatibility hack, the dynamic library uses this form in the path */
237
static const char *engine_hwcrhk_id_alt = "ncipher";
238
#  endif
239
240
/* Internal stuff for HWCryptoHook */
241
242
/* Some structures needed for proper use of thread locks */
243
/*
244
 * hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue
245
 * into HWCryptoHook_Mutex
246
 */
247
struct HWCryptoHook_MutexValue {
248
    int lockid;
249
};
250
251
/*
252
 * hwcryptohook.h has some typedefs that turn struct
253
 * HWCryptoHook_PassphraseContextValue into HWCryptoHook_PassphraseContext
254
 */
255
struct HWCryptoHook_PassphraseContextValue {
256
    UI_METHOD *ui_method;
257
    void *callback_data;
258
};
259
260
/*
261
 * hwcryptohook.h has some typedefs that turn struct
262
 * HWCryptoHook_CallerContextValue into HWCryptoHook_CallerContext
263
 */
264
struct HWCryptoHook_CallerContextValue {
265
    pem_password_cb *password_callback; /* Deprecated! Only present for
266
                                         * backward compatibility! */
267
    UI_METHOD *ui_method;
268
    void *callback_data;
269
};
270
271
/*
272
 * The MPI structure in HWCryptoHook is pretty compatible with OpenSSL
273
 * BIGNUM's, so lets define a couple of conversion macros
274
 */
275
#  define BN2MPI(mp, bn) \
276
0
    {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
277
#  define MPI2BN(bn, mp) \
278
0
    {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
279
280
static BIO *logstream = NULL;
281
static int disable_mutex_callbacks = 0;
282
283
/*
284
 * One might wonder why these are needed, since one can pass down at least a
285
 * UI_METHOD and a pointer to callback data to the key-loading functions. The
286
 * thing is that the ModExp and RSAImmed functions can load keys as well, if
287
 * the data they get is in a special, nCipher-defined format (hint: if you
288
 * look at the private exponent of the RSA data as a string, you'll see this
289
 * string: "nCipher KM tool key id", followed by some bytes, followed a key
290
 * identity string, followed by more bytes.  This happens when you use
291
 * "embed" keys instead of "hwcrhk" keys).  Unfortunately, those functions do
292
 * not take any passphrase or caller context, and our functions can't really
293
 * take any callback data either.  Still, the "insert_card" and
294
 * "get_passphrase" callbacks may be called down the line, and will need to
295
 * know what user interface callbacks to call, and having callback data from
296
 * the application may be a nice thing as well, so we need to keep track of
297
 * that globally.
298
 */
299
static HWCryptoHook_CallerContext password_context = { NULL, NULL, NULL };
300
301
/* Stuff to pass to the HWCryptoHook library */
302
static HWCryptoHook_InitInfo hwcrhk_globals = {
303
    HWCryptoHook_InitFlags_SimpleForkCheck, /* Flags */
304
    &logstream,                 /* logstream */
305
    sizeof(BN_ULONG),           /* limbsize */
306
    0,                          /* mslimb first: false for BNs */
307
    -1,                         /* msbyte first: use native */
308
    0,                          /* Max mutexes, 0 = no small limit */
309
    0,                          /* Max simultaneous, 0 = default */
310
311
    /*
312
     * The next few are mutex stuff: we write wrapper functions around the OS
313
     * mutex functions.  We initialise them to 0 here, and change that to
314
     * actual function pointers in hwcrhk_init() if dynamic locks are
315
     * supported (that is, if the application programmer has made sure of
316
     * setting up callbacks bafore starting this engine) *and* if
317
     * disable_mutex_callbacks hasn't been set by a call to
318
     * ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING).
319
     */
320
    sizeof(HWCryptoHook_Mutex),
321
    0,
322
    0,
323
    0,
324
    0,
325
326
    /*
327
     * The next few are condvar stuff: we write wrapper functions round the
328
     * OS functions.  Currently not implemented and not and absolute
329
     * necessity even in threaded programs, therefore 0'ed.  Will hopefully
330
     * be implemented some day, since it enhances the efficiency of
331
     * HWCryptoHook.
332
     */
333
    0,                          /* sizeof(HWCryptoHook_CondVar), */
334
    0,                          /* hwcrhk_cv_init, */
335
    0,                          /* hwcrhk_cv_wait, */
336
    0,                          /* hwcrhk_cv_signal, */
337
    0,                          /* hwcrhk_cv_broadcast, */
338
    0,                          /* hwcrhk_cv_destroy, */
339
340
    hwcrhk_get_pass,            /* pass phrase */
341
    hwcrhk_insert_card,         /* insert a card */
342
    hwcrhk_log_message          /* Log message */
343
};
344
345
/* Now, to our own code */
346
347
/*
348
 * This internal function is used by ENGINE_chil() and possibly by the
349
 * "dynamic" ENGINE support too
350
 */
351
static int bind_helper(ENGINE *e)
352
19
{
353
19
#  ifndef OPENSSL_NO_RSA
354
19
    const RSA_METHOD *meth1;
355
19
#  endif
356
19
#  ifndef OPENSSL_NO_DH
357
19
    const DH_METHOD *meth2;
358
19
#  endif
359
19
    if (!ENGINE_set_id(e, engine_hwcrhk_id) ||
360
19
        !ENGINE_set_name(e, engine_hwcrhk_name) ||
361
19
#  ifndef OPENSSL_NO_RSA
362
19
        !ENGINE_set_RSA(e, &hwcrhk_rsa) ||
363
19
#  endif
364
19
#  ifndef OPENSSL_NO_DH
365
19
        !ENGINE_set_DH(e, &hwcrhk_dh) ||
366
19
#  endif
367
19
        !ENGINE_set_RAND(e, &hwcrhk_rand) ||
368
19
        !ENGINE_set_destroy_function(e, hwcrhk_destroy) ||
369
19
        !ENGINE_set_init_function(e, hwcrhk_init) ||
370
19
        !ENGINE_set_finish_function(e, hwcrhk_finish) ||
371
19
        !ENGINE_set_ctrl_function(e, hwcrhk_ctrl) ||
372
19
        !ENGINE_set_load_privkey_function(e, hwcrhk_load_privkey) ||
373
19
        !ENGINE_set_load_pubkey_function(e, hwcrhk_load_pubkey) ||
374
19
        !ENGINE_set_cmd_defns(e, hwcrhk_cmd_defns))
375
0
        return 0;
376
377
19
#  ifndef OPENSSL_NO_RSA
378
    /*
379
     * We know that the "PKCS1_SSLeay()" functions hook properly to the
380
     * cswift-specific mod_exp and mod_exp_crt so we use those functions. NB:
381
     * We don't use ENGINE_openssl() or anything "more generic" because
382
     * something like the RSAref code may not hook properly, and if you own
383
     * one of these cards then you have the right to do RSA operations on it
384
     * anyway!
385
     */
386
19
    meth1 = RSA_PKCS1_SSLeay();
387
19
    hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
388
19
    hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
389
19
    hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
390
19
    hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
391
19
#  endif
392
393
19
#  ifndef OPENSSL_NO_DH
394
    /* Much the same for Diffie-Hellman */
395
19
    meth2 = DH_OpenSSL();
396
19
    hwcrhk_dh.generate_key = meth2->generate_key;
397
19
    hwcrhk_dh.compute_key = meth2->compute_key;
398
19
#  endif
399
400
    /* Ensure the hwcrhk error handling is set up */
401
19
    ERR_load_HWCRHK_strings();
402
19
    return 1;
403
19
}
404
405
#  ifdef OPENSSL_NO_DYNAMIC_ENGINE
406
static ENGINE *engine_chil(void)
407
19
{
408
19
    ENGINE *ret = ENGINE_new();
409
19
    if (!ret)
410
0
        return NULL;
411
19
    if (!bind_helper(ret)) {
412
0
        ENGINE_free(ret);
413
0
        return NULL;
414
0
    }
415
19
    return ret;
416
19
}
417
418
void ENGINE_load_chil(void)
419
19
{
420
    /* Copied from eng_[openssl|dyn].c */
421
19
    ENGINE *toadd = engine_chil();
422
19
    if (!toadd)
423
0
        return;
424
19
    ENGINE_add(toadd);
425
19
    ENGINE_free(toadd);
426
19
    ERR_clear_error();
427
19
}
428
#  endif
429
430
/*
431
 * This is a process-global DSO handle used for loading and unloading the
432
 * HWCryptoHook library. NB: This is only set (or unset) during an init() or
433
 * finish() call (reference counts permitting) and they're operating with
434
 * global locks, so this should be thread-safe implicitly.
435
 */
436
static DSO *hwcrhk_dso = NULL;
437
static HWCryptoHook_ContextHandle hwcrhk_context = 0;
438
#  ifndef OPENSSL_NO_RSA
439
/* Index for KM handle.  Not really used yet. */
440
static int hndidx_rsa = -1;
441
#  endif
442
443
/*
444
 * These are the function pointers that are (un)set when the library has
445
 * successfully (un)loaded.
446
 */
447
static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL;
448
static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL;
449
static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL;
450
#  ifndef OPENSSL_NO_RSA
451
static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL;
452
#  endif
453
static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL;
454
#  ifndef OPENSSL_NO_RSA
455
static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL;
456
static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL;
457
static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL;
458
#  endif
459
static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL;
460
461
/* Used in the DSO operations. */
462
static const char *HWCRHK_LIBNAME = NULL;
463
static void free_HWCRHK_LIBNAME(void)
464
0
{
465
0
    if (HWCRHK_LIBNAME)
466
0
        OPENSSL_free((void *)HWCRHK_LIBNAME);
467
0
    HWCRHK_LIBNAME = NULL;
468
0
}
469
470
static const char *get_HWCRHK_LIBNAME(void)
471
18
{
472
18
    if (HWCRHK_LIBNAME)
473
0
        return HWCRHK_LIBNAME;
474
18
    return "nfhwcrhk";
475
18
}
476
477
static long set_HWCRHK_LIBNAME(const char *name)
478
0
{
479
0
    free_HWCRHK_LIBNAME();
480
0
    return (((HWCRHK_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0);
481
0
}
482
483
static const char *n_hwcrhk_Init = "HWCryptoHook_Init";
484
static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish";
485
static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp";
486
#  ifndef OPENSSL_NO_RSA
487
static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA";
488
#  endif
489
static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes";
490
#  ifndef OPENSSL_NO_RSA
491
static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey";
492
static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey";
493
static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey";
494
#  endif
495
static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT";
496
497
/*
498
 * HWCryptoHook library functions and mechanics - these are used by the
499
 * higher-level functions further down. NB: As and where there's no error
500
 * checking, take a look lower down where these functions are called, the
501
 * checking and error handling is probably down there.
502
 */
503
504
/* utility function to obtain a context */
505
static int get_context(HWCryptoHook_ContextHandle * hac,
506
                       HWCryptoHook_CallerContext * cac)
507
0
{
508
0
    char tempbuf[1024];
509
0
    HWCryptoHook_ErrMsgBuf rmsg;
510
511
0
    rmsg.buf = tempbuf;
512
0
    rmsg.size = sizeof(tempbuf);
513
514
0
    *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg, cac);
515
0
    if (!*hac)
516
0
        return 0;
517
0
    return 1;
518
0
}
519
520
/* similarly to release one. */
521
static void release_context(HWCryptoHook_ContextHandle hac)
522
0
{
523
0
    p_hwcrhk_Finish(hac);
524
0
}
525
526
/* Destructor (complements the "ENGINE_chil()" constructor) */
527
static int hwcrhk_destroy(ENGINE *e)
528
0
{
529
0
    free_HWCRHK_LIBNAME();
530
0
    ERR_unload_HWCRHK_strings();
531
0
    return 1;
532
0
}
533
534
/* (de)initialisation functions. */
535
static int hwcrhk_init(ENGINE *e)
536
18
{
537
18
    HWCryptoHook_Init_t *p1;
538
18
    HWCryptoHook_Finish_t *p2;
539
18
    HWCryptoHook_ModExp_t *p3;
540
18
#  ifndef OPENSSL_NO_RSA
541
18
    HWCryptoHook_RSA_t *p4;
542
18
    HWCryptoHook_RSALoadKey_t *p5;
543
18
    HWCryptoHook_RSAGetPublicKey_t *p6;
544
18
    HWCryptoHook_RSAUnloadKey_t *p7;
545
18
#  endif
546
18
    HWCryptoHook_RandomBytes_t *p8;
547
18
    HWCryptoHook_ModExpCRT_t *p9;
548
549
18
    if (hwcrhk_dso != NULL) {
550
0
        HWCRHKerr(HWCRHK_F_HWCRHK_INIT, HWCRHK_R_ALREADY_LOADED);
551
0
        goto err;
552
0
    }
553
    /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
554
18
    hwcrhk_dso = DSO_load(NULL, get_HWCRHK_LIBNAME(), NULL, 0);
555
18
    if (hwcrhk_dso == NULL) {
556
18
        HWCRHKerr(HWCRHK_F_HWCRHK_INIT, HWCRHK_R_DSO_FAILURE);
557
18
        goto err;
558
18
    }
559
0
    if (!(p1 = (HWCryptoHook_Init_t *)
560
0
          DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) ||
561
0
        !(p2 = (HWCryptoHook_Finish_t *)
562
0
          DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) ||
563
0
        !(p3 = (HWCryptoHook_ModExp_t *)
564
0
          DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) ||
565
0
#  ifndef OPENSSL_NO_RSA
566
0
        !(p4 = (HWCryptoHook_RSA_t *)
567
0
          DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) ||
568
0
        !(p5 = (HWCryptoHook_RSALoadKey_t *)
569
0
          DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) ||
570
0
        !(p6 = (HWCryptoHook_RSAGetPublicKey_t *)
571
0
          DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) ||
572
0
        !(p7 = (HWCryptoHook_RSAUnloadKey_t *)
573
0
          DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) ||
574
0
#  endif
575
0
        !(p8 = (HWCryptoHook_RandomBytes_t *)
576
0
          DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) ||
577
0
        !(p9 = (HWCryptoHook_ModExpCRT_t *)
578
0
          DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT))) {
579
0
        HWCRHKerr(HWCRHK_F_HWCRHK_INIT, HWCRHK_R_DSO_FAILURE);
580
0
        goto err;
581
0
    }
582
    /* Copy the pointers */
583
0
    p_hwcrhk_Init = p1;
584
0
    p_hwcrhk_Finish = p2;
585
0
    p_hwcrhk_ModExp = p3;
586
0
#  ifndef OPENSSL_NO_RSA
587
0
    p_hwcrhk_RSA = p4;
588
0
    p_hwcrhk_RSALoadKey = p5;
589
0
    p_hwcrhk_RSAGetPublicKey = p6;
590
0
    p_hwcrhk_RSAUnloadKey = p7;
591
0
#  endif
592
0
    p_hwcrhk_RandomBytes = p8;
593
0
    p_hwcrhk_ModExpCRT = p9;
594
595
    /*
596
     * Check if the application decided to support dynamic locks, and if it
597
     * does, use them.
598
     */
599
0
    if (disable_mutex_callbacks == 0) {
600
0
        if (CRYPTO_get_dynlock_create_callback() != NULL &&
601
0
            CRYPTO_get_dynlock_lock_callback() != NULL &&
602
0
            CRYPTO_get_dynlock_destroy_callback() != NULL) {
603
0
            hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
604
0
            hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
605
0
            hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
606
0
            hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
607
0
        }
608
0
    }
609
610
    /*
611
     * Try and get a context - if not, we may have a DSO but no accelerator!
612
     */
613
0
    if (!get_context(&hwcrhk_context, &password_context)) {
614
0
        HWCRHKerr(HWCRHK_F_HWCRHK_INIT, HWCRHK_R_UNIT_FAILURE);
615
0
        goto err;
616
0
    }
617
    /* Everything's fine. */
618
0
#  ifndef OPENSSL_NO_RSA
619
0
    if (hndidx_rsa == -1)
620
0
        hndidx_rsa = RSA_get_ex_new_index(0,
621
0
                                          "nFast HWCryptoHook RSA key handle",
622
0
                                          NULL, NULL, NULL);
623
0
#  endif
624
0
    return 1;
625
18
 err:
626
18
    if (hwcrhk_dso)
627
0
        DSO_free(hwcrhk_dso);
628
18
    hwcrhk_dso = NULL;
629
18
    p_hwcrhk_Init = NULL;
630
18
    p_hwcrhk_Finish = NULL;
631
18
    p_hwcrhk_ModExp = NULL;
632
18
#  ifndef OPENSSL_NO_RSA
633
18
    p_hwcrhk_RSA = NULL;
634
18
    p_hwcrhk_RSALoadKey = NULL;
635
18
    p_hwcrhk_RSAGetPublicKey = NULL;
636
18
    p_hwcrhk_RSAUnloadKey = NULL;
637
18
#  endif
638
18
    p_hwcrhk_ModExpCRT = NULL;
639
18
    p_hwcrhk_RandomBytes = NULL;
640
18
    return 0;
641
0
}
642
643
static int hwcrhk_finish(ENGINE *e)
644
0
{
645
0
    int to_return = 1;
646
0
    free_HWCRHK_LIBNAME();
647
0
    if (hwcrhk_dso == NULL) {
648
0
        HWCRHKerr(HWCRHK_F_HWCRHK_FINISH, HWCRHK_R_NOT_LOADED);
649
0
        to_return = 0;
650
0
        goto err;
651
0
    }
652
0
    release_context(hwcrhk_context);
653
0
    if (!DSO_free(hwcrhk_dso)) {
654
0
        HWCRHKerr(HWCRHK_F_HWCRHK_FINISH, HWCRHK_R_DSO_FAILURE);
655
0
        to_return = 0;
656
0
        goto err;
657
0
    }
658
0
 err:
659
0
    if (logstream)
660
0
        BIO_free(logstream);
661
0
    hwcrhk_dso = NULL;
662
0
    p_hwcrhk_Init = NULL;
663
0
    p_hwcrhk_Finish = NULL;
664
0
    p_hwcrhk_ModExp = NULL;
665
0
#  ifndef OPENSSL_NO_RSA
666
0
    p_hwcrhk_RSA = NULL;
667
0
    p_hwcrhk_RSALoadKey = NULL;
668
0
    p_hwcrhk_RSAGetPublicKey = NULL;
669
0
    p_hwcrhk_RSAUnloadKey = NULL;
670
0
#  endif
671
0
    p_hwcrhk_ModExpCRT = NULL;
672
0
    p_hwcrhk_RandomBytes = NULL;
673
0
    return to_return;
674
0
}
675
676
static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
677
0
{
678
0
    int to_return = 1;
679
680
0
    switch (cmd) {
681
0
    case HWCRHK_CMD_SO_PATH:
682
0
        if (hwcrhk_dso) {
683
0
            HWCRHKerr(HWCRHK_F_HWCRHK_CTRL, HWCRHK_R_ALREADY_LOADED);
684
0
            return 0;
685
0
        }
686
0
        if (p == NULL) {
687
0
            HWCRHKerr(HWCRHK_F_HWCRHK_CTRL, ERR_R_PASSED_NULL_PARAMETER);
688
0
            return 0;
689
0
        }
690
0
        return set_HWCRHK_LIBNAME((const char *)p);
691
0
    case ENGINE_CTRL_SET_LOGSTREAM:
692
0
        {
693
0
            BIO *bio = (BIO *)p;
694
695
0
            CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
696
0
            if (logstream) {
697
0
                BIO_free(logstream);
698
0
                logstream = NULL;
699
0
            }
700
0
            if (CRYPTO_add(&bio->references, 1, CRYPTO_LOCK_BIO) > 1)
701
0
                logstream = bio;
702
0
            else
703
0
                HWCRHKerr(HWCRHK_F_HWCRHK_CTRL, HWCRHK_R_BIO_WAS_FREED);
704
0
        }
705
0
        CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
706
0
        break;
707
0
    case ENGINE_CTRL_SET_PASSWORD_CALLBACK:
708
0
        CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
709
0
        password_context.password_callback = (pem_password_cb *)f;
710
0
        CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
711
0
        break;
712
0
    case ENGINE_CTRL_SET_USER_INTERFACE:
713
0
    case HWCRHK_CMD_SET_USER_INTERFACE:
714
0
        CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
715
0
        password_context.ui_method = (UI_METHOD *)p;
716
0
        CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
717
0
        break;
718
0
    case ENGINE_CTRL_SET_CALLBACK_DATA:
719
0
    case HWCRHK_CMD_SET_CALLBACK_DATA:
720
0
        CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
721
0
        password_context.callback_data = p;
722
0
        CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
723
0
        break;
724
        /*
725
         * this enables or disables the "SimpleForkCheck" flag used in the
726
         * initialisation structure.
727
         */
728
0
    case ENGINE_CTRL_CHIL_SET_FORKCHECK:
729
0
    case HWCRHK_CMD_FORK_CHECK:
730
0
        CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
731
0
        if (i)
732
0
            hwcrhk_globals.flags |= HWCryptoHook_InitFlags_SimpleForkCheck;
733
0
        else
734
0
            hwcrhk_globals.flags &= ~HWCryptoHook_InitFlags_SimpleForkCheck;
735
0
        CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
736
0
        break;
737
        /*
738
         * This will prevent the initialisation function from "installing"
739
         * the mutex-handling callbacks, even if they are available from
740
         * within the library (or were provided to the library from the
741
         * calling application). This is to remove any baggage for
742
         * applications not using multithreading.
743
         */
744
0
    case ENGINE_CTRL_CHIL_NO_LOCKING:
745
0
        CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
746
0
        disable_mutex_callbacks = 1;
747
0
        CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
748
0
        break;
749
0
    case HWCRHK_CMD_THREAD_LOCKING:
750
0
        CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
751
0
        disable_mutex_callbacks = ((i == 0) ? 0 : 1);
752
0
        CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
753
0
        break;
754
755
        /* The command isn't understood by this engine */
756
0
    default:
757
0
        HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,
758
0
                  HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
759
0
        to_return = 0;
760
0
        break;
761
0
    }
762
763
0
    return to_return;
764
0
}
765
766
static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
767
                                     UI_METHOD *ui_method,
768
                                     void *callback_data)
769
0
{
770
0
#  ifndef OPENSSL_NO_RSA
771
0
    RSA *rtmp = NULL;
772
0
#  endif
773
0
    EVP_PKEY *res = NULL;
774
0
#  ifndef OPENSSL_NO_RSA
775
0
    HWCryptoHook_MPI e, n;
776
0
    HWCryptoHook_RSAKeyHandle *hptr;
777
0
#  endif
778
0
#  if !defined(OPENSSL_NO_RSA)
779
0
    char tempbuf[1024];
780
0
    HWCryptoHook_ErrMsgBuf rmsg;
781
0
    HWCryptoHook_PassphraseContext ppctx;
782
0
#  endif
783
784
0
#  if !defined(OPENSSL_NO_RSA)
785
0
    rmsg.buf = tempbuf;
786
0
    rmsg.size = sizeof(tempbuf);
787
0
#  endif
788
789
0
    if (!hwcrhk_context) {
790
0
        HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_NOT_INITIALISED);
791
0
        goto err;
792
0
    }
793
0
#  ifndef OPENSSL_NO_RSA
794
0
    hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle));
795
0
    if (!hptr) {
796
0
        HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, ERR_R_MALLOC_FAILURE);
797
0
        goto err;
798
0
    }
799
0
    ppctx.ui_method = ui_method;
800
0
    ppctx.callback_data = callback_data;
801
0
    if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr, &rmsg, &ppctx)) {
802
0
        HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_CHIL_ERROR);
803
0
        ERR_add_error_data(1, rmsg.buf);
804
0
        goto err;
805
0
    }
806
0
    if (!*hptr) {
807
0
        HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_NO_KEY);
808
0
        goto err;
809
0
    }
810
0
#  endif
811
0
#  ifndef OPENSSL_NO_RSA
812
0
    rtmp = RSA_new_method(eng);
813
0
    if (rtmp == NULL) {
814
0
        HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, ERR_R_MALLOC_FAILURE);
815
0
        goto err;
816
0
    }
817
0
    RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr);
818
0
    rtmp->e = BN_new();
819
0
    rtmp->n = BN_new();
820
0
    if (rtmp->e == NULL || rtmp->n == NULL) {
821
0
        HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, ERR_R_MALLOC_FAILURE);
822
0
        goto err;
823
0
    }
824
0
    rtmp->flags |= RSA_FLAG_EXT_PKEY;
825
0
    MPI2BN(rtmp->e, e);
826
0
    MPI2BN(rtmp->n, n);
827
0
    if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
828
0
        != HWCRYPTOHOOK_ERROR_MPISIZE) {
829
0
        HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_CHIL_ERROR);
830
0
        ERR_add_error_data(1, rmsg.buf);
831
0
        goto err;
832
0
    }
833
834
0
    if (bn_expand2(rtmp->e, e.size / sizeof(BN_ULONG)) == NULL) {
835
0
        HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, ERR_R_MALLOC_FAILURE);
836
0
        goto err;
837
0
    }
838
0
    if (bn_expand2(rtmp->n, n.size / sizeof(BN_ULONG)) == NULL) {
839
0
        HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, ERR_R_MALLOC_FAILURE);
840
0
        goto err;
841
0
    }
842
0
    MPI2BN(rtmp->e, e);
843
0
    MPI2BN(rtmp->n, n);
844
845
0
    if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)) {
846
0
        HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_CHIL_ERROR);
847
0
        ERR_add_error_data(1, rmsg.buf);
848
0
        goto err;
849
0
    }
850
0
    rtmp->e->top = e.size / sizeof(BN_ULONG);
851
0
    bn_fix_top(rtmp->e);
852
0
    rtmp->n->top = n.size / sizeof(BN_ULONG);
853
0
    bn_fix_top(rtmp->n);
854
855
0
    res = EVP_PKEY_new();
856
0
    if (res == NULL) {
857
0
        HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_CHIL_ERROR);
858
0
        goto err;
859
0
    }
860
0
    EVP_PKEY_assign_RSA(res, rtmp);
861
0
#  endif
862
863
0
    if (!res)
864
0
        HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
865
0
                  HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED);
866
867
0
    return res;
868
0
 err:
869
0
#  ifndef OPENSSL_NO_RSA
870
0
    if (rtmp)
871
0
        RSA_free(rtmp);
872
0
#  endif
873
0
    return NULL;
874
0
}
875
876
static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
877
                                    UI_METHOD *ui_method, void *callback_data)
878
0
{
879
0
    EVP_PKEY *res = NULL;
880
881
0
#  ifndef OPENSSL_NO_RSA
882
0
    res = hwcrhk_load_privkey(eng, key_id, ui_method, callback_data);
883
0
#  endif
884
885
0
    if (res)
886
0
        switch (res->type) {
887
0
#  ifndef OPENSSL_NO_RSA
888
0
        case EVP_PKEY_RSA:
889
0
            {
890
0
                RSA *rsa = NULL;
891
892
0
                CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
893
0
                rsa = res->pkey.rsa;
894
0
                res->pkey.rsa = RSA_new();
895
0
                res->pkey.rsa->n = rsa->n;
896
0
                res->pkey.rsa->e = rsa->e;
897
0
                rsa->n = NULL;
898
0
                rsa->e = NULL;
899
0
                CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
900
0
                RSA_free(rsa);
901
0
            }
902
0
            break;
903
0
#  endif
904
0
        default:
905
0
            HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
906
0
                      HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
907
0
            goto err;
908
0
        }
909
910
0
    return res;
911
0
 err:
912
0
    if (res)
913
0
        EVP_PKEY_free(res);
914
0
    return NULL;
915
0
}
916
917
/* A little mod_exp */
918
static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
919
                          const BIGNUM *m, BN_CTX *ctx)
920
0
{
921
0
    char tempbuf[1024];
922
0
    HWCryptoHook_ErrMsgBuf rmsg;
923
    /*
924
     * Since HWCryptoHook_MPI is pretty compatible with BIGNUM's, we use them
925
     * directly, plus a little macro magic.  We only thing we need to make
926
     * sure of is that enough space is allocated.
927
     */
928
0
    HWCryptoHook_MPI m_a, m_p, m_n, m_r;
929
0
    int to_return, ret;
930
931
0
    to_return = 0;              /* expect failure */
932
0
    rmsg.buf = tempbuf;
933
0
    rmsg.size = sizeof(tempbuf);
934
935
0
    if (!hwcrhk_context) {
936
0
        HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP, HWCRHK_R_NOT_INITIALISED);
937
0
        goto err;
938
0
    }
939
    /* Prepare the params */
940
0
    if (bn_expand2(r, m->top) == NULL) {     /* Check for error !! */
941
0
        HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP, ERR_R_MALLOC_FAILURE);
942
0
        goto err;
943
0
    }
944
0
    BN2MPI(m_a, a);
945
0
    BN2MPI(m_p, p);
946
0
    BN2MPI(m_n, m);
947
0
    MPI2BN(r, m_r);
948
949
    /* Perform the operation */
950
0
    ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
951
952
    /* Convert the response */
953
0
    r->top = m_r.size / sizeof(BN_ULONG);
954
0
    bn_fix_top(r);
955
956
0
    if (ret < 0) {
957
        /*
958
         * FIXME: When this error is returned, HWCryptoHook is telling us
959
         * that falling back to software computation might be a good thing.
960
         */
961
0
        if (ret == HWCRYPTOHOOK_ERROR_FALLBACK) {
962
0
            HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP, HWCRHK_R_REQUEST_FALLBACK);
963
0
        } else {
964
0
            HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP, HWCRHK_R_REQUEST_FAILED);
965
0
        }
966
0
        ERR_add_error_data(1, rmsg.buf);
967
0
        goto err;
968
0
    }
969
970
0
    to_return = 1;
971
0
 err:
972
0
    return to_return;
973
0
}
974
975
#  ifndef OPENSSL_NO_RSA
976
static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa,
977
                              BN_CTX *ctx)
978
0
{
979
0
    char tempbuf[1024];
980
0
    HWCryptoHook_ErrMsgBuf rmsg;
981
0
    HWCryptoHook_RSAKeyHandle *hptr;
982
0
    int to_return = 0, ret;
983
984
0
    rmsg.buf = tempbuf;
985
0
    rmsg.size = sizeof(tempbuf);
986
987
0
    if (!hwcrhk_context) {
988
0
        HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, HWCRHK_R_NOT_INITIALISED);
989
0
        goto err;
990
0
    }
991
992
    /*
993
     * This provides support for nForce keys.  Since that's opaque data all
994
     * we do is provide a handle to the proper key and let HWCryptoHook take
995
     * care of the rest.
996
     */
997
0
    if ((hptr =
998
0
         (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa))
999
0
        != NULL) {
1000
0
        HWCryptoHook_MPI m_a, m_r;
1001
1002
0
        if (!rsa->n) {
1003
0
            HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1004
0
                      HWCRHK_R_MISSING_KEY_COMPONENTS);
1005
0
            goto err;
1006
0
        }
1007
1008
        /* Prepare the params */
1009
0
        if (bn_expand2(r, rsa->n->top) == NULL) { /* Check for error !! */
1010
0
            HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, ERR_R_MALLOC_FAILURE);
1011
0
            goto err;
1012
0
        }
1013
0
        BN2MPI(m_a, I);
1014
0
        MPI2BN(r, m_r);
1015
1016
        /* Perform the operation */
1017
0
        ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
1018
1019
        /* Convert the response */
1020
0
        r->top = m_r.size / sizeof(BN_ULONG);
1021
0
        bn_fix_top(r);
1022
1023
0
        if (ret < 0) {
1024
            /*
1025
             * FIXME: When this error is returned, HWCryptoHook is telling us
1026
             * that falling back to software computation might be a good
1027
             * thing.
1028
             */
1029
0
            if (ret == HWCRYPTOHOOK_ERROR_FALLBACK) {
1030
0
                HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1031
0
                          HWCRHK_R_REQUEST_FALLBACK);
1032
0
            } else {
1033
0
                HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1034
0
                          HWCRHK_R_REQUEST_FAILED);
1035
0
            }
1036
0
            ERR_add_error_data(1, rmsg.buf);
1037
0
            goto err;
1038
0
        }
1039
0
    } else {
1040
0
        HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
1041
1042
0
        if (!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp) {
1043
0
            HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1044
0
                      HWCRHK_R_MISSING_KEY_COMPONENTS);
1045
0
            goto err;
1046
0
        }
1047
1048
        /* Prepare the params */
1049
0
        if (bn_expand2(r, rsa->n->top) == NULL) { /* Check for error !! */
1050
0
            HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, ERR_R_MALLOC_FAILURE);
1051
0
            goto err;
1052
0
        }
1053
0
        BN2MPI(m_a, I);
1054
0
        BN2MPI(m_p, rsa->p);
1055
0
        BN2MPI(m_q, rsa->q);
1056
0
        BN2MPI(m_dmp1, rsa->dmp1);
1057
0
        BN2MPI(m_dmq1, rsa->dmq1);
1058
0
        BN2MPI(m_iqmp, rsa->iqmp);
1059
0
        MPI2BN(r, m_r);
1060
1061
        /* Perform the operation */
1062
0
        ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
1063
0
                                 m_dmp1, m_dmq1, m_iqmp, &m_r, &rmsg);
1064
1065
        /* Convert the response */
1066
0
        r->top = m_r.size / sizeof(BN_ULONG);
1067
0
        bn_fix_top(r);
1068
1069
0
        if (ret < 0) {
1070
            /*
1071
             * FIXME: When this error is returned, HWCryptoHook is telling us
1072
             * that falling back to software computation might be a good
1073
             * thing.
1074
             */
1075
0
            if (ret == HWCRYPTOHOOK_ERROR_FALLBACK) {
1076
0
                HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1077
0
                          HWCRHK_R_REQUEST_FALLBACK);
1078
0
            } else {
1079
0
                HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1080
0
                          HWCRHK_R_REQUEST_FAILED);
1081
0
            }
1082
0
            ERR_add_error_data(1, rmsg.buf);
1083
0
            goto err;
1084
0
        }
1085
0
    }
1086
    /*
1087
     * If we're here, we must be here with some semblance of success :-)
1088
     */
1089
0
    to_return = 1;
1090
0
 err:
1091
0
    return to_return;
1092
0
}
1093
#  endif
1094
1095
#  ifndef OPENSSL_NO_RSA
1096
/* This function is aliased to mod_exp (with the mont stuff dropped). */
1097
static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
1098
                               const BIGNUM *m, BN_CTX *ctx,
1099
                               BN_MONT_CTX *m_ctx)
1100
0
{
1101
0
    return hwcrhk_mod_exp(r, a, p, m, ctx);
1102
0
}
1103
1104
static int hwcrhk_rsa_finish(RSA *rsa)
1105
0
{
1106
0
    HWCryptoHook_RSAKeyHandle *hptr;
1107
1108
0
    hptr = RSA_get_ex_data(rsa, hndidx_rsa);
1109
0
    if (hptr) {
1110
0
        p_hwcrhk_RSAUnloadKey(*hptr, NULL);
1111
0
        OPENSSL_free(hptr);
1112
0
        RSA_set_ex_data(rsa, hndidx_rsa, NULL);
1113
0
    }
1114
0
    return 1;
1115
0
}
1116
1117
#  endif
1118
1119
#  ifndef OPENSSL_NO_DH
1120
/* This function is aliased to mod_exp (with the dh and mont dropped). */
1121
static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
1122
                             const BIGNUM *a, const BIGNUM *p,
1123
                             const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1124
0
{
1125
0
    return hwcrhk_mod_exp(r, a, p, m, ctx);
1126
0
}
1127
#  endif
1128
1129
/* Random bytes are good */
1130
static int hwcrhk_rand_bytes(unsigned char *buf, int num)
1131
0
{
1132
0
    char tempbuf[1024];
1133
0
    HWCryptoHook_ErrMsgBuf rmsg;
1134
0
    int to_return = 0;          /* assume failure */
1135
0
    int ret;
1136
1137
0
    rmsg.buf = tempbuf;
1138
0
    rmsg.size = sizeof(tempbuf);
1139
1140
0
    if (!hwcrhk_context) {
1141
0
        HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES, HWCRHK_R_NOT_INITIALISED);
1142
0
        goto err;
1143
0
    }
1144
1145
0
    ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
1146
0
    if (ret < 0) {
1147
        /*
1148
         * FIXME: When this error is returned, HWCryptoHook is telling us
1149
         * that falling back to software computation might be a good thing.
1150
         */
1151
0
        if (ret == HWCRYPTOHOOK_ERROR_FALLBACK) {
1152
0
            HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES, HWCRHK_R_REQUEST_FALLBACK);
1153
0
        } else {
1154
0
            HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES, HWCRHK_R_REQUEST_FAILED);
1155
0
        }
1156
0
        ERR_add_error_data(1, rmsg.buf);
1157
0
        goto err;
1158
0
    }
1159
0
    to_return = 1;
1160
0
 err:
1161
0
    return to_return;
1162
0
}
1163
1164
static int hwcrhk_rand_status(void)
1165
0
{
1166
0
    return 1;
1167
0
}
1168
1169
/*
1170
 * Mutex calls: since the HWCryptoHook model closely follows the POSIX model
1171
 * these just wrap the POSIX functions and add some logging.
1172
 */
1173
1174
static int hwcrhk_mutex_init(HWCryptoHook_Mutex * mt,
1175
                             HWCryptoHook_CallerContext * cactx)
1176
0
{
1177
0
    mt->lockid = CRYPTO_get_new_dynlockid();
1178
0
    if (mt->lockid == 0)
1179
0
        return 1;               /* failure */
1180
0
    return 0;                   /* success */
1181
0
}
1182
1183
static int hwcrhk_mutex_lock(HWCryptoHook_Mutex * mt)
1184
0
{
1185
0
    CRYPTO_w_lock(mt->lockid);
1186
0
    return 0;
1187
0
}
1188
1189
static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
1190
0
{
1191
0
    CRYPTO_w_unlock(mt->lockid);
1192
0
}
1193
1194
static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex * mt)
1195
0
{
1196
0
    CRYPTO_destroy_dynlockid(mt->lockid);
1197
0
}
1198
1199
static int hwcrhk_get_pass(const char *prompt_info,
1200
                           int *len_io, char *buf,
1201
                           HWCryptoHook_PassphraseContext * ppctx,
1202
                           HWCryptoHook_CallerContext * cactx)
1203
0
{
1204
0
    pem_password_cb *callback = NULL;
1205
0
    void *callback_data = NULL;
1206
0
    UI_METHOD *ui_method = NULL;
1207
    /*
1208
     * Despite what the documentation says prompt_info can be an empty
1209
     * string.
1210
     */
1211
0
    if (prompt_info && !*prompt_info)
1212
0
        prompt_info = NULL;
1213
1214
0
    if (cactx) {
1215
0
        if (cactx->ui_method)
1216
0
            ui_method = cactx->ui_method;
1217
0
        if (cactx->password_callback)
1218
0
            callback = cactx->password_callback;
1219
0
        if (cactx->callback_data)
1220
0
            callback_data = cactx->callback_data;
1221
0
    }
1222
0
    if (ppctx) {
1223
0
        if (ppctx->ui_method) {
1224
0
            ui_method = ppctx->ui_method;
1225
0
            callback = NULL;
1226
0
        }
1227
0
        if (ppctx->callback_data)
1228
0
            callback_data = ppctx->callback_data;
1229
0
    }
1230
0
    if (callback == NULL && ui_method == NULL) {
1231
0
        HWCRHKerr(HWCRHK_F_HWCRHK_GET_PASS, HWCRHK_R_NO_CALLBACK);
1232
0
        return -1;
1233
0
    }
1234
1235
0
    if (ui_method) {
1236
0
        UI *ui = UI_new_method(ui_method);
1237
0
        if (ui) {
1238
0
            int ok;
1239
0
            char *prompt = UI_construct_prompt(ui,
1240
0
                                               "pass phrase", prompt_info);
1241
1242
0
            ok = UI_add_input_string(ui, prompt,
1243
0
                                     UI_INPUT_FLAG_DEFAULT_PWD,
1244
0
                                     buf, 0, (*len_io) - 1);
1245
0
            UI_add_user_data(ui, callback_data);
1246
0
            UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
1247
1248
0
            if (ok >= 0)
1249
0
                do {
1250
0
                    ok = UI_process(ui);
1251
0
                }
1252
0
                while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
1253
1254
0
            if (ok >= 0)
1255
0
                *len_io = strlen(buf);
1256
1257
0
            UI_free(ui);
1258
0
            OPENSSL_free(prompt);
1259
0
        }
1260
0
    } else {
1261
0
        *len_io = callback(buf, *len_io, 0, callback_data);
1262
0
    }
1263
0
    if (!*len_io)
1264
0
        return -1;
1265
0
    return 0;
1266
0
}
1267
1268
static int hwcrhk_insert_card(const char *prompt_info,
1269
                              const char *wrong_info,
1270
                              HWCryptoHook_PassphraseContext * ppctx,
1271
                              HWCryptoHook_CallerContext * cactx)
1272
0
{
1273
0
    int ok = -1;
1274
0
    UI *ui;
1275
0
    void *callback_data = NULL;
1276
0
    UI_METHOD *ui_method = NULL;
1277
1278
0
    if (cactx) {
1279
0
        if (cactx->ui_method)
1280
0
            ui_method = cactx->ui_method;
1281
0
        if (cactx->callback_data)
1282
0
            callback_data = cactx->callback_data;
1283
0
    }
1284
0
    if (ppctx) {
1285
0
        if (ppctx->ui_method)
1286
0
            ui_method = ppctx->ui_method;
1287
0
        if (ppctx->callback_data)
1288
0
            callback_data = ppctx->callback_data;
1289
0
    }
1290
0
    if (ui_method == NULL) {
1291
0
        HWCRHKerr(HWCRHK_F_HWCRHK_INSERT_CARD, HWCRHK_R_NO_CALLBACK);
1292
0
        return -1;
1293
0
    }
1294
1295
0
    ui = UI_new_method(ui_method);
1296
1297
0
    if (ui) {
1298
0
        char answer = '\0';
1299
0
        char buf[BUFSIZ];
1300
        /*
1301
         * Despite what the documentation says wrong_info can be an empty
1302
         * string.
1303
         */
1304
0
        if (wrong_info && *wrong_info)
1305
0
            BIO_snprintf(buf, sizeof(buf) - 1,
1306
0
                         "Current card: \"%s\"\n", wrong_info);
1307
0
        else
1308
0
            buf[0] = 0;
1309
0
        ok = UI_dup_info_string(ui, buf);
1310
0
        if (ok >= 0 && prompt_info) {
1311
0
            BIO_snprintf(buf, sizeof(buf) - 1,
1312
0
                         "Insert card \"%s\"", prompt_info);
1313
0
            ok = UI_dup_input_boolean(ui, buf,
1314
0
                                      "\n then hit <enter> or C<enter> to cancel\n",
1315
0
                                      "\r\n", "Cc", UI_INPUT_FLAG_ECHO,
1316
0
                                      &answer);
1317
0
        }
1318
0
        UI_add_user_data(ui, callback_data);
1319
1320
0
        if (ok >= 0)
1321
0
            ok = UI_process(ui);
1322
0
        UI_free(ui);
1323
1324
0
        if (ok == -2 || (ok >= 0 && answer == 'C'))
1325
0
            ok = 1;
1326
0
        else if (ok < 0)
1327
0
            ok = -1;
1328
0
        else
1329
0
            ok = 0;
1330
0
    }
1331
0
    return ok;
1332
0
}
1333
1334
static void hwcrhk_log_message(void *logstr, const char *message)
1335
0
{
1336
0
    BIO *lstream = NULL;
1337
1338
0
    CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1339
0
    if (logstr)
1340
0
        lstream = *(BIO **)logstr;
1341
0
    if (lstream) {
1342
0
        BIO_printf(lstream, "%s\n", message);
1343
0
    }
1344
0
    CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1345
0
}
1346
1347
/*
1348
 * This stuff is needed if this ENGINE is being compiled into a
1349
 * self-contained shared-library.
1350
 */
1351
#  ifndef OPENSSL_NO_DYNAMIC_ENGINE
1352
static int bind_fn(ENGINE *e, const char *id)
1353
{
1354
    if (id && (strcmp(id, engine_hwcrhk_id) != 0) &&
1355
        (strcmp(id, engine_hwcrhk_id_alt) != 0))
1356
        return 0;
1357
    if (!bind_helper(e))
1358
        return 0;
1359
    return 1;
1360
}
1361
1362
IMPLEMENT_DYNAMIC_CHECK_FN()
1363
    IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
1364
#  endif                        /* OPENSSL_NO_DYNAMIC_ENGINE */
1365
# endif                         /* !OPENSSL_NO_HW_CHIL */
1366
#endif                          /* !OPENSSL_NO_HW */