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