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