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