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