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