5c5595b8c96fcde323aeb134301cc0107aab59a2
[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(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 /* 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(ENGINE *eng, const char *key_id,
117         const char *passphrase);
118 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, 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(ENGINE *e)
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(ENGINE *e)
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(ENGINE *e, 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(ENGINE *eng, 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(ENGINE *eng, const char *key_id,
653         const char *passphrase)
654         {
655         EVP_PKEY *res = hwcrhk_load_privkey(eng, key_id, passphrase);
656
657         if (res)
658                 switch(res->type)
659                         {
660                 case EVP_PKEY_RSA:
661                         {
662                         RSA *rsa = NULL;
663
664                         CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
665                         rsa = res->pkey.rsa;
666                         res->pkey.rsa = RSA_new();
667                         res->pkey.rsa->n = rsa->n;
668                         res->pkey.rsa->e = rsa->e;
669                         CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
670                         RSA_free(rsa);
671                         }
672                 default:
673                         ENGINEerr(ENGINE_F_HWCRHK_LOAD_PUBKEY,
674                                 ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED);
675                         goto err;
676                         }
677
678         return res;
679  err:
680         if (res)
681                 EVP_PKEY_free(res);
682         return NULL;
683         }
684
685 /* A little mod_exp */
686 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
687                         const BIGNUM *m, BN_CTX *ctx)
688         {
689         char tempbuf[1024];
690         HWCryptoHook_ErrMsgBuf rmsg;
691         /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's,
692            we use them directly, plus a little macro magic.  We only
693            thing we need to make sure of is that enough space is allocated. */
694         HWCryptoHook_MPI m_a, m_p, m_n, m_r;
695         int to_return, ret;
696  
697         to_return = 0; /* expect failure */
698         rmsg.buf = tempbuf;
699         rmsg.size = 1024;
700
701         if(!hwcrhk_context)
702                 {
703                 ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_NOT_INITIALISED);
704                 goto err;
705                 }
706         /* Prepare the params */
707         bn_expand2(r, m->top);  /* Check for error !! */
708         BN2MPI(m_a, a);
709         BN2MPI(m_p, p);
710         BN2MPI(m_n, m);
711         MPI2BN(r, m_r);
712
713         /* Perform the operation */
714         ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
715
716         /* Convert the response */
717         r->top = m_r.size / sizeof(BN_ULONG);
718         bn_fix_top(r);
719
720         if (ret < 0)
721                 {
722                 /* FIXME: When this error is returned, HWCryptoHook is
723                    telling us that falling back to software computation
724                    might be a good thing. */
725                 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
726                         {
727                         ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_REQUEST_FALLBACK);
728                         }
729                 else
730                         {
731                         ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_REQUEST_FAILED);
732                         }
733                 ERR_add_error_data(1,rmsg.buf);
734                 goto err;
735                 }
736
737         to_return = 1;
738 err:
739         return to_return;
740         }
741  
742 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa)
743         {
744         char tempbuf[1024];
745         HWCryptoHook_ErrMsgBuf rmsg;
746         HWCryptoHook_RSAKeyHandle *hptr;
747         int to_return = 0, ret;
748
749         if(!hwcrhk_context)
750                 {
751                 ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_NOT_INITIALISED);
752                 goto err;
753                 }
754
755         /* This provides support for nForce keys.  Since that's opaque data
756            all we do is provide a handle to the proper key and let HWCryptoHook
757            take care of the rest. */
758         if ((hptr = (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx))
759                 != NULL)
760                 {
761                 HWCryptoHook_MPI m_a, m_r;
762
763                 if(!rsa->n)
764                         {
765                         ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,
766                                 ENGINE_R_MISSING_KEY_COMPONENTS);
767                         goto err;
768                         }
769
770                 rmsg.buf = tempbuf;
771                 rmsg.size = 1024;
772
773                 /* Prepare the params */
774                 bn_expand2(r, rsa->n->top); /* Check for error !! */
775                 BN2MPI(m_a, I);
776                 MPI2BN(r, m_r);
777
778                 /* Perform the operation */
779                 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
780
781                 /* Convert the response */
782                 r->top = m_r.size / sizeof(BN_ULONG);
783                 bn_fix_top(r);
784
785                 if (ret < 0)
786                         {
787                         /* FIXME: When this error is returned, HWCryptoHook is
788                            telling us that falling back to software computation
789                            might be a good thing. */
790                         if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
791                                 {
792                                 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FALLBACK);
793                                 }
794                         else
795                                 {
796                                 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FAILED);
797                                 }
798                         ERR_add_error_data(1,rmsg.buf);
799                         goto err;
800                         }
801                 }
802         else
803                 {
804                 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
805
806                 if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
807                         {
808                         ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,
809                                 ENGINE_R_MISSING_KEY_COMPONENTS);
810                         goto err;
811                         }
812
813                 rmsg.buf = tempbuf;
814                 rmsg.size = 1024;
815
816                 /* Prepare the params */
817                 bn_expand2(r, rsa->n->top); /* Check for error !! */
818                 BN2MPI(m_a, I);
819                 BN2MPI(m_p, rsa->p);
820                 BN2MPI(m_q, rsa->q);
821                 BN2MPI(m_dmp1, rsa->dmp1);
822                 BN2MPI(m_dmq1, rsa->dmq1);
823                 BN2MPI(m_iqmp, rsa->iqmp);
824                 MPI2BN(r, m_r);
825
826                 /* Perform the operation */
827                 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
828                         m_dmp1, m_dmq1, m_iqmp, &m_r, NULL);
829
830                 /* Convert the response */
831                 r->top = m_r.size / sizeof(BN_ULONG);
832                 bn_fix_top(r);
833
834                 if (ret < 0)
835                         {
836                         /* FIXME: When this error is returned, HWCryptoHook is
837                            telling us that falling back to software computation
838                            might be a good thing. */
839                         if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
840                                 {
841                                 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FALLBACK);
842                                 }
843                         else
844                                 {
845                                 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FAILED);
846                                 }
847                         ERR_add_error_data(1,rmsg.buf);
848                         goto err;
849                         }
850                 }
851         /* If we're here, we must be here with some semblance of success :-) */
852         to_return = 1;
853 err:
854         return to_return;
855         }
856
857 /* This function is aliased to mod_exp (with the mont stuff dropped). */
858 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
859                 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
860         {
861         return hwcrhk_mod_exp(r, a, p, m, ctx);
862         }
863
864 /* This function is aliased to mod_exp (with the dh and mont dropped). */
865 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
866                 const BIGNUM *a, const BIGNUM *p,
867                 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
868         {
869         return hwcrhk_mod_exp(r, a, p, m, ctx);
870         }
871
872 /* Random bytes are good */
873 static int hwcrhk_rand_bytes(unsigned char *buf, int num)
874         {
875         char tempbuf[1024];
876         HWCryptoHook_ErrMsgBuf rmsg;
877         int to_return = 0; /* assume failure */
878         int ret;
879
880         rmsg.buf = tempbuf;
881         rmsg.size = 1024;
882
883         if(!hwcrhk_context)
884                 {
885                 ENGINEerr(ENGINE_F_HWCRHK_RAND_BYTES,ENGINE_R_NOT_INITIALISED);
886                 goto err;
887                 }
888
889         ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
890         if (ret < 0)
891                 {
892                 /* FIXME: When this error is returned, HWCryptoHook is
893                    telling us that falling back to software computation
894                    might be a good thing. */
895                 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
896                         {
897                         ENGINEerr(ENGINE_F_HWCRHK_RAND_BYTES,ENGINE_R_REQUEST_FALLBACK);
898                         }
899                 else
900                         {
901                         ENGINEerr(ENGINE_F_HWCRHK_RAND_BYTES,ENGINE_R_REQUEST_FAILED);
902                         }
903                 ERR_add_error_data(1,rmsg.buf);
904                 goto err;
905                 }
906         to_return = 1;
907  err:
908         return to_return;
909         }
910
911 static int hwcrhk_rand_status(void)
912         {
913         return 1;
914         }
915
916 /* This cleans up an RSA KM key, called when ex_data is freed */
917
918 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
919         int ind,long argl, void *argp)
920 {
921         char tempbuf[1024];
922         HWCryptoHook_ErrMsgBuf rmsg;
923         HWCryptoHook_RSAKeyHandle *hptr;
924         int ret;
925
926         rmsg.buf = tempbuf;
927         rmsg.size = 1024;
928
929         hptr = (HWCryptoHook_RSAKeyHandle *) item;
930         if(!hptr) return;
931         ret = p_hwcrhk_RSAUnloadKey(*hptr, NULL);
932         OPENSSL_free(hptr);
933 }
934
935 /* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
936  * these just wrap the POSIX functions and add some logging.
937  */
938
939 static int hwcrhk_mutex_init(HWCryptoHook_Mutex* mt,
940         HWCryptoHook_CallerContext *cactx)
941         {
942         mt->lockid = CRYPTO_get_new_dynlockid();
943         if (mt->lockid == 0)
944                 return 0;
945         return 1;
946         }
947
948 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *mt)
949         {
950         CRYPTO_w_lock(mt->lockid);
951         return 1;
952         }
953
954 void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
955         {
956         CRYPTO_w_unlock(mt->lockid);
957         }
958
959 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *mt)
960         {
961         CRYPTO_destroy_dynlockid(mt->lockid);
962         }
963
964 static int hwcrhk_get_pass(const char *prompt_info,
965         int *len_io, char *buf,
966         HWCryptoHook_PassphraseContext *ppctx,
967         HWCryptoHook_CallerContext *cactx)
968         {
969         int l = 0;
970         char prompt[1024];
971
972         if (password_callback == NULL)
973                 {
974                 ENGINEerr(ENGINE_F_HWCRHK_GET_PASS,ENGINE_R_NO_CALLBACK);
975                 return -1;
976                 }
977         if (prompt_info)
978                 {
979                 strncpy(prompt, "Card: \"", sizeof(prompt));
980                 l += 5;
981                 strncpy(prompt + l, prompt_info, sizeof(prompt) - l);
982                 l += strlen(prompt_info);
983                 if (l + 2 < sizeof(prompt))
984                         {
985                         strncpy(prompt + l, "\"\n", sizeof(prompt) - l);
986                         l += 2;
987                         }
988                 }
989         if (l < sizeof(prompt) - 1)
990                 {
991                 strncpy(prompt, "Enter Passphrase <enter to cancel>:",
992                         sizeof(prompt) - l);
993                 l += 35;
994                 }
995         prompt[l] = '\0';
996
997         /* I know, passing on the prompt instead of the user data *is*
998            a bad thing.  However, that's all we have right now.
999            --  Richard Levitte */
1000         *len_io = password_callback(buf, *len_io, 0, prompt);
1001         if(!*len_io)
1002                 return -1;
1003         return 0;
1004         }
1005
1006 static void hwcrhk_log_message(void *logstr, const char *message)
1007         {
1008         BIO *lstream = NULL;
1009
1010         CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1011         if (logstr)
1012                 lstream=*(BIO **)logstr;
1013         if (lstream)
1014                 {
1015                 BIO_write(lstream, message, strlen(message));
1016                 }
1017         CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1018         }
1019
1020 #endif /* !OPENSSL_NO_HW_NCIPHER */
1021 #endif /* !OPENSSL_NO_HW */