Some more tweaks to ENGINE code.
[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 <openssl/crypto.h>
62 #include <openssl/pem.h>
63 #include "cryptlib.h"
64 #include <openssl/dso.h>
65 #include "engine_int.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(void);
86 static int hwcrhk_finish(void);
87 static int hwcrhk_ctrl(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 /* RSA stuff */
100 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa);
101 /* This function is aliased to mod_exp (with the mont stuff dropped). */
102 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
103                 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
104
105 /* DH stuff */
106 /* This function is alised to mod_exp (with the DH and mont dropped). */
107 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
108         const BIGNUM *a, const BIGNUM *p,
109         const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
110
111 /* RAND stuff */
112 static int hwcrhk_rand_bytes(unsigned char *buf, int num);
113 static int hwcrhk_rand_status(void);
114
115 /* KM stuff */
116 static EVP_PKEY *hwcrhk_load_privkey(const char *key_id,
117         const char *passphrase);
118 static EVP_PKEY *hwcrhk_load_pubkey(const char *key_id,
119         const char *passphrase);
120 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
121         int ind,long argl, void *argp);
122
123 /* Interaction stuff */
124 static int hwcrhk_get_pass(const char *prompt_info,
125         int *len_io, char *buf,
126         HWCryptoHook_PassphraseContext *ppctx,
127         HWCryptoHook_CallerContext *cactx);
128 static void hwcrhk_log_message(void *logstr, const char *message);
129
130 /* Our internal RSA_METHOD that we provide pointers to */
131 static RSA_METHOD hwcrhk_rsa =
132         {
133         "nCipher RSA method",
134         NULL,
135         NULL,
136         NULL,
137         NULL,
138         hwcrhk_rsa_mod_exp,
139         hwcrhk_mod_exp_mont,
140         NULL,
141         NULL,
142         0,
143         NULL,
144         NULL,
145         NULL
146         };
147
148 /* Our internal DH_METHOD that we provide pointers to */
149 static DH_METHOD hwcrhk_dh =
150         {
151         "nCipher DH method",
152         NULL,
153         NULL,
154         hwcrhk_mod_exp_dh,
155         NULL,
156         NULL,
157         0,
158         NULL
159         };
160
161 static RAND_METHOD hwcrhk_rand =
162         {
163         /* "nCipher RAND method", */
164         NULL,
165         hwcrhk_rand_bytes,
166         NULL,
167         NULL,
168         hwcrhk_rand_bytes,
169         hwcrhk_rand_status,
170         };
171
172 /* Our ENGINE structure. */
173 static ENGINE engine_hwcrhk =
174         {
175         "chil",
176         "nCipher hardware engine support",
177         &hwcrhk_rsa,
178         NULL,
179         &hwcrhk_dh,
180         &hwcrhk_rand,
181         hwcrhk_mod_exp,
182         NULL,
183         hwcrhk_init,
184         hwcrhk_finish,
185         hwcrhk_ctrl,
186         hwcrhk_load_privkey,
187         hwcrhk_load_pubkey,
188         0, /* no flags */
189         0, 0, /* no references */
190         NULL, NULL /* unlinked */
191         };
192
193 /* Internal stuff for HWCryptoHook */
194
195 /* Some structures needed for proper use of thread locks */
196 /* hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue
197    into HWCryptoHook_Mutex */
198 struct HWCryptoHook_MutexValue
199         {
200         int lockid;
201         };
202
203 /* hwcryptohook.h has some typedefs that turn
204    struct HWCryptoHook_PassphraseContextValue
205    into HWCryptoHook_PassphraseContext */
206 struct HWCryptoHook_PassphraseContextValue
207         {
208         void *any;
209         };
210
211 /* hwcryptohook.h has some typedefs that turn
212    struct HWCryptoHook_CallerContextValue
213    into HWCryptoHook_CallerContext */
214 struct HWCryptoHook_CallerContextValue
215         {
216         void *any;
217         };
218
219 /* The MPI structure in HWCryptoHook is pretty compatible with OpenSSL
220    BIGNUM's, so lets define a couple of conversion macros */
221 #define BN2MPI(mp, bn) \
222     {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
223 #define MPI2BN(bn, mp) \
224     {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
225
226 #if 0 /* Card and password management is not yet supported */
227 /* HWCryptoHook callbacks.  insert_card() and get_pass() are not yet
228    defined, because we haven't quite decided on the proper form yet.
229    log_message() just adds an entry in the error stack.  I don't know
230    if that's good or bad...  */
231 static int insert_card(const char *prompt_info,
232         const char *wrong_info,
233         HWCryptoHook_PassphraseContext *ppctx,
234         HWCryptoHook_CallerContext *cactx);
235 static int get_pass(const char *prompt_info,
236         int *len_io, char *buf,
237         HWCryptoHook_PassphraseContext *ppctx,
238         HWCryptoHook_CallerContext *cactx);
239 #endif
240
241 static BIO *logstream = NULL;
242 static pem_password_cb *password_callback = NULL;
243 #if 0
244 static void *password_callback_userdata = NULL;
245 #endif
246 static int disable_mutex_callbacks = 0;
247
248 /* Stuff to pass to the HWCryptoHook library */
249 static HWCryptoHook_InitInfo hwcrhk_globals = {
250         0,                      /* Flags */
251         &logstream,             /* logstream */
252         sizeof(BN_ULONG),       /* limbsize */
253         0,                      /* mslimb first: false for BNs */
254         -1,                     /* msbyte first: use native */
255         0,                      /* Max mutexes, 0 = no small limit */
256         0,                      /* Max simultaneous, 0 = default */
257
258         /* The next few are mutex stuff: we write wrapper functions
259            around the OS mutex functions.  We initialise them to 0
260            here, and change that to actual function pointers in hwcrhk_init()
261            if dynamic locks are supported (that is, if the application
262            programmer has made sure of setting up callbacks bafore starting
263            this engine) *and* if disable_mutex_callbacks hasn't been set by
264            a call to ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING). */
265         sizeof(HWCryptoHook_Mutex),
266         0,
267         0,
268         0,
269         0,
270
271         /* The next few are condvar stuff: we write wrapper functions
272            round the OS functions.  Currently not implemented and not
273            and absolute necessity even in threaded programs, therefore
274            0'ed.  Will hopefully be implemented some day, since it
275            enhances the efficiency of HWCryptoHook.  */
276         0, /* sizeof(HWCryptoHook_CondVar), */
277         0, /* hwcrhk_cv_init, */
278         0, /* hwcrhk_cv_wait, */
279         0, /* hwcrhk_cv_signal, */
280         0, /* hwcrhk_cv_broadcast, */
281         0, /* hwcrhk_cv_destroy, */
282
283         hwcrhk_get_pass,        /* pass phrase */
284         0, /* insert_card, */   /* insert a card */
285         hwcrhk_log_message      /* Log message */
286 };
287
288
289 /* Now, to our own code */
290
291 /* As this is only ever called once, there's no need for locking
292  * (indeed - the lock will already be held by our caller!!!) */
293 ENGINE *ENGINE_ncipher()
294         {
295         const RSA_METHOD *meth1;
296         const DH_METHOD *meth2;
297
298         /* We know that the "PKCS1_SSLeay()" functions hook properly
299          * to the cswift-specific mod_exp and mod_exp_crt so we use
300          * those functions. NB: We don't use ENGINE_openssl() or
301          * anything "more generic" because something like the RSAref
302          * code may not hook properly, and if you own one of these
303          * cards then you have the right to do RSA operations on it
304          * anyway! */ 
305         meth1 = RSA_PKCS1_SSLeay();
306         hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
307         hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
308         hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
309         hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
310
311         /* Much the same for Diffie-Hellman */
312         meth2 = DH_OpenSSL();
313         hwcrhk_dh.generate_key = meth2->generate_key;
314         hwcrhk_dh.compute_key = meth2->compute_key;
315         return &engine_hwcrhk;
316         }
317
318 /* This is a process-global DSO handle used for loading and unloading
319  * the HWCryptoHook library. NB: This is only set (or unset) during an
320  * init() or finish() call (reference counts permitting) and they're
321  * operating with global locks, so this should be thread-safe
322  * implicitly. */
323 static DSO *hwcrhk_dso = NULL;
324 static HWCryptoHook_ContextHandle hwcrhk_context = 0;
325 static int hndidx = -1; /* Index for KM handle.  Not really used yet. */
326
327 /* These are the function pointers that are (un)set when the library has
328  * successfully (un)loaded. */
329 static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL;
330 static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL;
331 static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL;
332 static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL;
333 static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL;
334 static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL;
335 static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL;
336 static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL;
337 static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL;
338
339 /* Used in the DSO operations. */
340 static const char *HWCRHK_LIBNAME = "nfhwcrhk";
341 static const char *n_hwcrhk_Init = "HWCryptoHook_Init";
342 static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish";
343 static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp";
344 static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA";
345 static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes";
346 static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey";
347 static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey";
348 static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey";
349 static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT";
350
351 /* HWCryptoHook library functions and mechanics - these are used by the
352  * higher-level functions further down. NB: As and where there's no
353  * error checking, take a look lower down where these functions are
354  * called, the checking and error handling is probably down there. */
355
356 /* utility function to obtain a context */
357 static int get_context(HWCryptoHook_ContextHandle *hac)
358         {
359         char tempbuf[1024];
360         HWCryptoHook_ErrMsgBuf rmsg;
361
362         rmsg.buf = tempbuf;
363         rmsg.size = 1024;
364
365         *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg,
366                 NULL);
367         if (!*hac)
368                 return 0;
369         return 1;
370         }
371  
372 /* similarly to release one. */
373 static void release_context(HWCryptoHook_ContextHandle hac)
374         {
375         p_hwcrhk_Finish(hac);
376         }
377
378 /* (de)initialisation functions. */
379 static int hwcrhk_init(void)
380         {
381         HWCryptoHook_Init_t *p1;
382         HWCryptoHook_Finish_t *p2;
383         HWCryptoHook_ModExp_t *p3;
384         HWCryptoHook_RSA_t *p4;
385         HWCryptoHook_RSALoadKey_t *p5;
386         HWCryptoHook_RSAGetPublicKey_t *p6;
387         HWCryptoHook_RSAUnloadKey_t *p7;
388         HWCryptoHook_RandomBytes_t *p8;
389         HWCryptoHook_ModExpCRT_t *p9;
390
391         if(hwcrhk_dso != NULL)
392                 {
393                 ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_ALREADY_LOADED);
394                 goto err;
395                 }
396         /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
397         hwcrhk_dso = DSO_load(NULL, HWCRHK_LIBNAME, NULL, 0);
398         if(hwcrhk_dso == NULL)
399                 {
400                 ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_DSO_FAILURE);
401                 goto err;
402                 }
403         if(!(p1 = (HWCryptoHook_Init_t *)
404                         DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) ||
405                 !(p2 = (HWCryptoHook_Finish_t *)
406                         DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) ||
407                 !(p3 = (HWCryptoHook_ModExp_t *)
408                         DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) ||
409                 !(p4 = (HWCryptoHook_RSA_t *)
410                         DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) ||
411                 !(p5 = (HWCryptoHook_RSALoadKey_t *)
412                         DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) ||
413                 !(p6 = (HWCryptoHook_RSAGetPublicKey_t *)
414                         DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) ||
415                 !(p7 = (HWCryptoHook_RSAUnloadKey_t *)
416                         DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) ||
417                 !(p8 = (HWCryptoHook_RandomBytes_t *)
418                         DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) ||
419                 !(p9 = (HWCryptoHook_ModExpCRT_t *)
420                         DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT)))
421                 {
422                 ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_DSO_FAILURE);
423                 goto err;
424                 }
425         /* Copy the pointers */
426         p_hwcrhk_Init = p1;
427         p_hwcrhk_Finish = p2;
428         p_hwcrhk_ModExp = p3;
429         p_hwcrhk_RSA = p4;
430         p_hwcrhk_RSALoadKey = p5;
431         p_hwcrhk_RSAGetPublicKey = p6;
432         p_hwcrhk_RSAUnloadKey = p7;
433         p_hwcrhk_RandomBytes = p8;
434         p_hwcrhk_ModExpCRT = p9;
435
436         /* Check if the application decided to support dynamic locks,
437            and if it does, use them. */
438         if (disable_mutex_callbacks == 0 &&
439                 CRYPTO_get_dynlock_create_callback() != NULL &&
440                 CRYPTO_get_dynlock_lock_callback() != NULL &&
441                 CRYPTO_get_dynlock_destroy_callback() != NULL)
442                 {
443                 hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
444                 hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
445                 hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
446                 hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
447                 }
448
449         /* Try and get a context - if not, we may have a DSO but no
450          * accelerator! */
451         if(!get_context(&hwcrhk_context))
452                 {
453                 ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_UNIT_FAILURE);
454                 goto err;
455                 }
456         /* Everything's fine. */
457         if (hndidx == -1)
458                 hndidx = RSA_get_ex_new_index(0,
459                         "nFast HWCryptoHook RSA key handle",
460                         NULL, NULL, hwcrhk_ex_free);
461         return 1;
462 err:
463         if(hwcrhk_dso)
464                 DSO_free(hwcrhk_dso);
465         hwcrhk_dso = NULL;
466         p_hwcrhk_Init = NULL;
467         p_hwcrhk_Finish = NULL;
468         p_hwcrhk_ModExp = NULL;
469         p_hwcrhk_RSA = NULL;
470         p_hwcrhk_RSALoadKey = NULL;
471         p_hwcrhk_RSAGetPublicKey = NULL;
472         p_hwcrhk_RSAUnloadKey = NULL;
473         p_hwcrhk_ModExpCRT = NULL;
474         p_hwcrhk_RandomBytes = NULL;
475         return 0;
476         }
477
478 static int hwcrhk_finish(void)
479         {
480         int to_return = 1;
481         if(hwcrhk_dso == NULL)
482                 {
483                 ENGINEerr(ENGINE_F_HWCRHK_FINISH,ENGINE_R_NOT_LOADED);
484                 to_return = 0;
485                 goto err;
486                 }
487         release_context(hwcrhk_context);
488         if(!DSO_free(hwcrhk_dso))
489                 {
490                 ENGINEerr(ENGINE_F_HWCRHK_FINISH,ENGINE_R_DSO_FAILURE);
491                 to_return = 0;
492                 goto err;
493                 }
494  err:
495         if (logstream)
496                 BIO_free(logstream);
497         hwcrhk_dso = NULL;
498         p_hwcrhk_Init = NULL;
499         p_hwcrhk_Finish = NULL;
500         p_hwcrhk_ModExp = NULL;
501         p_hwcrhk_RSA = NULL;
502         p_hwcrhk_RSALoadKey = NULL;
503         p_hwcrhk_RSAGetPublicKey = NULL;
504         p_hwcrhk_RSAUnloadKey = NULL;
505         p_hwcrhk_ModExpCRT = NULL;
506         p_hwcrhk_RandomBytes = NULL;
507         return to_return;
508         }
509
510 static int hwcrhk_ctrl(int cmd, long i, void *p, void (*f)())
511         {
512         int to_return = 1;
513
514         switch(cmd)
515                 {
516         case ENGINE_CTRL_SET_LOGSTREAM:
517                 {
518                 BIO *bio = (BIO *)p;
519
520                 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
521                 if (logstream)
522                         {
523                         BIO_free(logstream);
524                         logstream = NULL;
525                         }
526                 if (CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO) > 1)
527                         logstream = bio;
528                 else
529                         ENGINEerr(ENGINE_F_HWCRHK_CTRL,ENGINE_R_BIO_WAS_FREED);
530                 }
531                 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
532                 break;
533         case ENGINE_CTRL_SET_PASSWORD_CALLBACK:
534                 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
535                 password_callback = (pem_password_cb *)f;
536                 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
537                 break;
538         /* this enables or disables the "SimpleForkCheck" flag used in the
539          * initialisation structure. */
540         case ENGINE_CTRL_CHIL_SET_FORKCHECK:
541                 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
542                 if(i)
543                         hwcrhk_globals.flags |=
544                                 HWCryptoHook_InitFlags_SimpleForkCheck;
545                 else
546                         hwcrhk_globals.flags &=
547                                 ~HWCryptoHook_InitFlags_SimpleForkCheck;
548                 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
549                 break;
550         /* This will prevent the initialisation function from "installing"
551          * the mutex-handling callbacks, even if they are available from
552          * within the library (or were provided to the library from the
553          * calling application). This is to remove any baggage for
554          * applications not using multithreading. */
555         case ENGINE_CTRL_CHIL_NO_LOCKING:
556                 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
557                 disable_mutex_callbacks = 1;
558                 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
559                 break;
560
561         /* The command isn't understood by this engine */
562         default:
563                 ENGINEerr(ENGINE_F_HWCRHK_CTRL,
564                         ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED);
565                 to_return = 0;
566                 break;
567                 }
568
569         return to_return;
570         }
571
572 static EVP_PKEY *hwcrhk_load_privkey(const char *key_id,
573         const char *passphrase)
574         {
575         RSA *rtmp = NULL;
576         EVP_PKEY *res = NULL;
577         HWCryptoHook_MPI e, n;
578         HWCryptoHook_RSAKeyHandle *hptr;
579         HWCryptoHook_ErrMsgBuf rmsg;
580
581         if(!hwcrhk_context)
582                 {
583                 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY,
584                         ENGINE_R_NOT_INITIALISED);
585                 goto err;
586                 }
587         hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle));
588         if (!hptr)
589                 {
590                 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY,
591                         ERR_R_MALLOC_FAILURE);
592                 goto err;
593                 }
594         if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr,
595                 &rmsg, NULL))
596                 {
597                 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY,
598                         ENGINE_R_CHIL_ERROR);
599                 ERR_add_error_data(1,rmsg.buf);
600                 goto err;
601                 }
602         if (!*hptr)
603                 {
604                 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY,
605                         ENGINE_R_NO_KEY);
606                 goto err;
607                 }
608         rtmp = RSA_new_method(&engine_hwcrhk);
609         RSA_set_ex_data(rtmp, hndidx, (char *)hptr);
610         rtmp->e = BN_new();
611         rtmp->n = BN_new();
612         rtmp->flags |= RSA_FLAG_EXT_PKEY;
613         MPI2BN(rtmp->e, e);
614         MPI2BN(rtmp->n, n);
615         if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
616                 != HWCRYPTOHOOK_ERROR_MPISIZE)
617                 {
618                 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PUBKEY,ENGINE_R_CHIL_ERROR);
619                 ERR_add_error_data(1,rmsg.buf);
620                 goto err;
621                 }
622                         
623         bn_expand2(rtmp->e, e.size/sizeof(BN_ULONG));
624         bn_expand2(rtmp->n, n.size/sizeof(BN_ULONG));
625         MPI2BN(rtmp->e, e);
626         MPI2BN(rtmp->n, n);
627
628         if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg))
629                 {
630                 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PUBKEY,
631                         ENGINE_R_CHIL_ERROR);
632                 ERR_add_error_data(1,rmsg.buf);
633                 goto err;
634                 }
635         rtmp->e->top = e.size / sizeof(BN_ULONG);
636         bn_fix_top(rtmp->e);
637         rtmp->n->top = n.size / sizeof(BN_ULONG);
638         bn_fix_top(rtmp->n);
639
640         res = EVP_PKEY_new();
641         EVP_PKEY_assign_RSA(res, rtmp);
642
643         return res;
644  err:
645         if (res)
646                 EVP_PKEY_free(res);
647         if (rtmp)
648                 RSA_free(rtmp);
649         return NULL;
650         }
651
652 static EVP_PKEY *hwcrhk_load_pubkey(const char *key_id, const char *passphrase)
653         {
654         EVP_PKEY *res = hwcrhk_load_privkey(key_id, passphrase);
655
656         if (res)
657                 switch(res->type)
658                         {
659                 case EVP_PKEY_RSA:
660                         {
661                         RSA *rsa = NULL;
662
663                         CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
664                         rsa = res->pkey.rsa;
665                         res->pkey.rsa = RSA_new();
666                         res->pkey.rsa->n = rsa->n;
667                         res->pkey.rsa->e = rsa->e;
668                         CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
669                         RSA_free(rsa);
670                         }
671                 default:
672                         ENGINEerr(ENGINE_F_HWCRHK_LOAD_PUBKEY,
673                                 ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED);
674                         goto err;
675                         }
676
677         return res;
678  err:
679         if (res)
680                 EVP_PKEY_free(res);
681         return NULL;
682         }
683
684 /* A little mod_exp */
685 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
686                         const BIGNUM *m, BN_CTX *ctx)
687         {
688         char tempbuf[1024];
689         HWCryptoHook_ErrMsgBuf rmsg;
690         /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's,
691            we use them directly, plus a little macro magic.  We only
692            thing we need to make sure of is that enough space is allocated. */
693         HWCryptoHook_MPI m_a, m_p, m_n, m_r;
694         int to_return, ret;
695  
696         to_return = 0; /* expect failure */
697         rmsg.buf = tempbuf;
698         rmsg.size = 1024;
699
700         if(!hwcrhk_context)
701                 {
702                 ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_NOT_INITIALISED);
703                 goto err;
704                 }
705         /* Prepare the params */
706         bn_expand2(r, m->top);  /* Check for error !! */
707         BN2MPI(m_a, a);
708         BN2MPI(m_p, p);
709         BN2MPI(m_n, m);
710         MPI2BN(r, m_r);
711
712         /* Perform the operation */
713         ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
714
715         /* Convert the response */
716         r->top = m_r.size / sizeof(BN_ULONG);
717         bn_fix_top(r);
718
719         if (ret < 0)
720                 {
721                 /* FIXME: When this error is returned, HWCryptoHook is
722                    telling us that falling back to software computation
723                    might be a good thing. */
724                 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
725                         {
726                         ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_REQUEST_FALLBACK);
727                         }
728                 else
729                         {
730                         ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_REQUEST_FAILED);
731                         }
732                 ERR_add_error_data(1,rmsg.buf);
733                 goto err;
734                 }
735
736         to_return = 1;
737 err:
738         return to_return;
739         }
740  
741 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa)
742         {
743         char tempbuf[1024];
744         HWCryptoHook_ErrMsgBuf rmsg;
745         HWCryptoHook_RSAKeyHandle *hptr;
746         int to_return = 0, ret;
747
748         if(!hwcrhk_context)
749                 {
750                 ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_NOT_INITIALISED);
751                 goto err;
752                 }
753
754         /* This provides support for nForce keys.  Since that's opaque data
755            all we do is provide a handle to the proper key and let HWCryptoHook
756            take care of the rest. */
757         if ((hptr = (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx))
758                 != NULL)
759                 {
760                 HWCryptoHook_MPI m_a, m_r;
761
762                 if(!rsa->n)
763                         {
764                         ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,
765                                 ENGINE_R_MISSING_KEY_COMPONENTS);
766                         goto err;
767                         }
768
769                 rmsg.buf = tempbuf;
770                 rmsg.size = 1024;
771
772                 /* Prepare the params */
773                 bn_expand2(r, rsa->n->top); /* Check for error !! */
774                 BN2MPI(m_a, I);
775                 MPI2BN(r, m_r);
776
777                 /* Perform the operation */
778                 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
779
780                 /* Convert the response */
781                 r->top = m_r.size / sizeof(BN_ULONG);
782                 bn_fix_top(r);
783
784                 if (ret < 0)
785                         {
786                         /* FIXME: When this error is returned, HWCryptoHook is
787                            telling us that falling back to software computation
788                            might be a good thing. */
789                         if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
790                                 {
791                                 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FALLBACK);
792                                 }
793                         else
794                                 {
795                                 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FAILED);
796                                 }
797                         ERR_add_error_data(1,rmsg.buf);
798                         goto err;
799                         }
800                 }
801         else
802                 {
803                 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
804
805                 if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
806                         {
807                         ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,
808                                 ENGINE_R_MISSING_KEY_COMPONENTS);
809                         goto err;
810                         }
811
812                 rmsg.buf = tempbuf;
813                 rmsg.size = 1024;
814
815                 /* Prepare the params */
816                 bn_expand2(r, rsa->n->top); /* Check for error !! */
817                 BN2MPI(m_a, I);
818                 BN2MPI(m_p, rsa->p);
819                 BN2MPI(m_q, rsa->q);
820                 BN2MPI(m_dmp1, rsa->dmp1);
821                 BN2MPI(m_dmq1, rsa->dmq1);
822                 BN2MPI(m_iqmp, rsa->iqmp);
823                 MPI2BN(r, m_r);
824
825                 /* Perform the operation */
826                 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
827                         m_dmp1, m_dmq1, m_iqmp, &m_r, NULL);
828
829                 /* Convert the response */
830                 r->top = m_r.size / sizeof(BN_ULONG);
831                 bn_fix_top(r);
832
833                 if (ret < 0)
834                         {
835                         /* FIXME: When this error is returned, HWCryptoHook is
836                            telling us that falling back to software computation
837                            might be a good thing. */
838                         if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
839                                 {
840                                 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FALLBACK);
841                                 }
842                         else
843                                 {
844                                 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FAILED);
845                                 }
846                         ERR_add_error_data(1,rmsg.buf);
847                         goto err;
848                         }
849                 }
850         /* If we're here, we must be here with some semblance of success :-) */
851         to_return = 1;
852 err:
853         return to_return;
854         }
855
856 /* This function is aliased to mod_exp (with the mont stuff dropped). */
857 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
858                 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
859         {
860         return hwcrhk_mod_exp(r, a, p, m, ctx);
861         }
862
863 /* This function is aliased to mod_exp (with the dh and mont dropped). */
864 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
865                 const BIGNUM *a, const BIGNUM *p,
866                 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
867         {
868         return hwcrhk_mod_exp(r, a, p, m, ctx);
869         }
870
871 /* Random bytes are good */
872 static int hwcrhk_rand_bytes(unsigned char *buf, int num)
873         {
874         char tempbuf[1024];
875         HWCryptoHook_ErrMsgBuf rmsg;
876         int to_return = 0; /* assume failure */
877         int ret;
878
879         rmsg.buf = tempbuf;
880         rmsg.size = 1024;
881
882         if(!hwcrhk_context)
883                 {
884                 ENGINEerr(ENGINE_F_HWCRHK_RAND_BYTES,ENGINE_R_NOT_INITIALISED);
885                 goto err;
886                 }
887
888         ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
889         if (ret < 0)
890                 {
891                 /* FIXME: When this error is returned, HWCryptoHook is
892                    telling us that falling back to software computation
893                    might be a good thing. */
894                 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
895                         {
896                         ENGINEerr(ENGINE_F_HWCRHK_RAND_BYTES,ENGINE_R_REQUEST_FALLBACK);
897                         }
898                 else
899                         {
900                         ENGINEerr(ENGINE_F_HWCRHK_RAND_BYTES,ENGINE_R_REQUEST_FAILED);
901                         }
902                 ERR_add_error_data(1,rmsg.buf);
903                 goto err;
904                 }
905         to_return = 1;
906  err:
907         return to_return;
908         }
909
910 static int hwcrhk_rand_status(void)
911         {
912         return 1;
913         }
914
915 /* This cleans up an RSA KM key, called when ex_data is freed */
916
917 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
918         int ind,long argl, void *argp)
919 {
920         char tempbuf[1024];
921         HWCryptoHook_ErrMsgBuf rmsg;
922         HWCryptoHook_RSAKeyHandle *hptr;
923         int ret;
924
925         rmsg.buf = tempbuf;
926         rmsg.size = 1024;
927
928         hptr = (HWCryptoHook_RSAKeyHandle *) item;
929         if(!hptr) return;
930         ret = p_hwcrhk_RSAUnloadKey(*hptr, NULL);
931         OPENSSL_free(hptr);
932 }
933
934 /* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
935  * these just wrap the POSIX functions and add some logging.
936  */
937
938 static int hwcrhk_mutex_init(HWCryptoHook_Mutex* mt,
939         HWCryptoHook_CallerContext *cactx)
940         {
941         mt->lockid = CRYPTO_get_new_dynlockid();
942         if (mt->lockid == 0)
943                 return 0;
944         return 1;
945         }
946
947 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *mt)
948         {
949         CRYPTO_w_lock(mt->lockid);
950         return 1;
951         }
952
953 void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
954         {
955         CRYPTO_w_unlock(mt->lockid);
956         }
957
958 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *mt)
959         {
960         CRYPTO_destroy_dynlockid(mt->lockid);
961         }
962
963 static int hwcrhk_get_pass(const char *prompt_info,
964         int *len_io, char *buf,
965         HWCryptoHook_PassphraseContext *ppctx,
966         HWCryptoHook_CallerContext *cactx)
967         {
968         int l = 0;
969         char prompt[1024];
970
971         if (password_callback == NULL)
972                 {
973                 ENGINEerr(ENGINE_F_HWCRHK_GET_PASS,ENGINE_R_NO_CALLBACK);
974                 return -1;
975                 }
976         if (prompt_info)
977                 {
978                 strncpy(prompt, "Card: \"", sizeof(prompt));
979                 l += 5;
980                 strncpy(prompt + l, prompt_info, sizeof(prompt) - l);
981                 l += strlen(prompt_info);
982                 if (l + 2 < sizeof(prompt))
983                         {
984                         strncpy(prompt + l, "\"\n", sizeof(prompt) - l);
985                         l += 2;
986                         }
987                 }
988         if (l < sizeof(prompt) - 1)
989                 {
990                 strncpy(prompt, "Enter Passphrase <enter to cancel>:",
991                         sizeof(prompt) - l);
992                 l += 35;
993                 }
994         prompt[l] = '\0';
995
996         /* I know, passing on the prompt instead of the user data *is*
997            a bad thing.  However, that's all we have right now.
998            --  Richard Levitte */
999         *len_io = password_callback(buf, *len_io, 0, prompt);
1000         if(!*len_io)
1001                 return -1;
1002         return 0;
1003         }
1004
1005 static void hwcrhk_log_message(void *logstr, const char *message)
1006         {
1007         BIO *lstream = NULL;
1008
1009         CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1010         if (logstr)
1011                 lstream=*(BIO **)logstr;
1012         if (lstream)
1013                 {
1014                 BIO_write(lstream, message, strlen(message));
1015                 }
1016         CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1017         }
1018
1019 #endif /* !OPENSSL_NO_HW_NCIPHER */
1020 #endif /* !OPENSSL_NO_HW */