/src/openssl/engines/e_atalla.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* crypto/engine/hw_atalla.c */ |
2 | | /* |
3 | | * Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL project |
4 | | * 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/buffer.h> |
64 | | #include <openssl/dso.h> |
65 | | #include <openssl/engine.h> |
66 | | #ifndef OPENSSL_NO_RSA |
67 | | # include <openssl/rsa.h> |
68 | | #endif |
69 | | #ifndef OPENSSL_NO_DSA |
70 | | # include <openssl/dsa.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_ATALLA |
79 | | |
80 | | # ifdef FLAT_INC |
81 | | # include "atalla.h" |
82 | | # else |
83 | | # include "vendor_defns/atalla.h" |
84 | | # endif |
85 | | |
86 | | # define ATALLA_LIB_NAME "atalla engine" |
87 | | # include "e_atalla_err.c" |
88 | | |
89 | | static int atalla_destroy(ENGINE *e); |
90 | | static int atalla_init(ENGINE *e); |
91 | | static int atalla_finish(ENGINE *e); |
92 | | static int atalla_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void)); |
93 | | |
94 | | /* BIGNUM stuff */ |
95 | | static int atalla_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, |
96 | | const BIGNUM *m, BN_CTX *ctx); |
97 | | |
98 | | # ifndef OPENSSL_NO_RSA |
99 | | /* RSA stuff */ |
100 | | static int atalla_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, |
101 | | BN_CTX *ctx); |
102 | | /* This function is aliased to mod_exp (with the mont stuff dropped). */ |
103 | | static int atalla_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, |
104 | | const BIGNUM *m, BN_CTX *ctx, |
105 | | BN_MONT_CTX *m_ctx); |
106 | | # endif |
107 | | |
108 | | # ifndef OPENSSL_NO_DSA |
109 | | /* DSA stuff */ |
110 | | static int atalla_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1, |
111 | | BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m, |
112 | | BN_CTX *ctx, BN_MONT_CTX *in_mont); |
113 | | static int atalla_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a, |
114 | | const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, |
115 | | BN_MONT_CTX *m_ctx); |
116 | | # endif |
117 | | |
118 | | # ifndef OPENSSL_NO_DH |
119 | | /* DH stuff */ |
120 | | /* This function is alised to mod_exp (with the DH and mont dropped). */ |
121 | | static int atalla_mod_exp_dh(const DH *dh, BIGNUM *r, |
122 | | const BIGNUM *a, const BIGNUM *p, |
123 | | const BIGNUM *m, BN_CTX *ctx, |
124 | | BN_MONT_CTX *m_ctx); |
125 | | # endif |
126 | | |
127 | | /* The definitions for control commands specific to this engine */ |
128 | 0 | # define ATALLA_CMD_SO_PATH ENGINE_CMD_BASE |
129 | | static const ENGINE_CMD_DEFN atalla_cmd_defns[] = { |
130 | | {ATALLA_CMD_SO_PATH, |
131 | | "SO_PATH", |
132 | | "Specifies the path to the 'atasi' shared library", |
133 | | ENGINE_CMD_FLAG_STRING}, |
134 | | {0, NULL, NULL, 0} |
135 | | }; |
136 | | |
137 | | # ifndef OPENSSL_NO_RSA |
138 | | /* Our internal RSA_METHOD that we provide pointers to */ |
139 | | static RSA_METHOD atalla_rsa = { |
140 | | "Atalla RSA method", |
141 | | NULL, |
142 | | NULL, |
143 | | NULL, |
144 | | NULL, |
145 | | atalla_rsa_mod_exp, |
146 | | atalla_mod_exp_mont, |
147 | | NULL, |
148 | | NULL, |
149 | | 0, |
150 | | NULL, |
151 | | NULL, |
152 | | NULL, |
153 | | NULL |
154 | | }; |
155 | | # endif |
156 | | |
157 | | # ifndef OPENSSL_NO_DSA |
158 | | /* Our internal DSA_METHOD that we provide pointers to */ |
159 | | static DSA_METHOD atalla_dsa = { |
160 | | "Atalla DSA method", |
161 | | NULL, /* dsa_do_sign */ |
162 | | NULL, /* dsa_sign_setup */ |
163 | | NULL, /* dsa_do_verify */ |
164 | | atalla_dsa_mod_exp, /* dsa_mod_exp */ |
165 | | atalla_mod_exp_dsa, /* bn_mod_exp */ |
166 | | NULL, /* init */ |
167 | | NULL, /* finish */ |
168 | | 0, /* flags */ |
169 | | NULL, /* app_data */ |
170 | | NULL, /* dsa_paramgen */ |
171 | | NULL /* dsa_keygen */ |
172 | | }; |
173 | | # endif |
174 | | |
175 | | # ifndef OPENSSL_NO_DH |
176 | | /* Our internal DH_METHOD that we provide pointers to */ |
177 | | static DH_METHOD atalla_dh = { |
178 | | "Atalla DH method", |
179 | | NULL, |
180 | | NULL, |
181 | | atalla_mod_exp_dh, |
182 | | NULL, |
183 | | NULL, |
184 | | 0, |
185 | | NULL, |
186 | | NULL |
187 | | }; |
188 | | # endif |
189 | | |
190 | | /* Constants used when creating the ENGINE */ |
191 | | static const char *engine_atalla_id = "atalla"; |
192 | | static const char *engine_atalla_name = "Atalla hardware engine support"; |
193 | | |
194 | | /* |
195 | | * This internal function is used by ENGINE_atalla() and possibly by the |
196 | | * "dynamic" ENGINE support too |
197 | | */ |
198 | | static int bind_helper(ENGINE *e) |
199 | 19 | { |
200 | 19 | # ifndef OPENSSL_NO_RSA |
201 | 19 | const RSA_METHOD *meth1; |
202 | 19 | # endif |
203 | 19 | # ifndef OPENSSL_NO_DSA |
204 | 19 | const DSA_METHOD *meth2; |
205 | 19 | # endif |
206 | 19 | # ifndef OPENSSL_NO_DH |
207 | 19 | const DH_METHOD *meth3; |
208 | 19 | # endif |
209 | 19 | if (!ENGINE_set_id(e, engine_atalla_id) || |
210 | 19 | !ENGINE_set_name(e, engine_atalla_name) || |
211 | 19 | # ifndef OPENSSL_NO_RSA |
212 | 19 | !ENGINE_set_RSA(e, &atalla_rsa) || |
213 | 19 | # endif |
214 | 19 | # ifndef OPENSSL_NO_DSA |
215 | 19 | !ENGINE_set_DSA(e, &atalla_dsa) || |
216 | 19 | # endif |
217 | 19 | # ifndef OPENSSL_NO_DH |
218 | 19 | !ENGINE_set_DH(e, &atalla_dh) || |
219 | 19 | # endif |
220 | 19 | !ENGINE_set_destroy_function(e, atalla_destroy) || |
221 | 19 | !ENGINE_set_init_function(e, atalla_init) || |
222 | 19 | !ENGINE_set_finish_function(e, atalla_finish) || |
223 | 19 | !ENGINE_set_ctrl_function(e, atalla_ctrl) || |
224 | 19 | !ENGINE_set_cmd_defns(e, atalla_cmd_defns)) |
225 | 0 | return 0; |
226 | | |
227 | 19 | # ifndef OPENSSL_NO_RSA |
228 | | /* |
229 | | * We know that the "PKCS1_SSLeay()" functions hook properly to the |
230 | | * atalla-specific mod_exp and mod_exp_crt so we use those functions. NB: |
231 | | * We don't use ENGINE_openssl() or anything "more generic" because |
232 | | * something like the RSAref code may not hook properly, and if you own |
233 | | * one of these cards then you have the right to do RSA operations on it |
234 | | * anyway! |
235 | | */ |
236 | 19 | meth1 = RSA_PKCS1_SSLeay(); |
237 | 19 | atalla_rsa.rsa_pub_enc = meth1->rsa_pub_enc; |
238 | 19 | atalla_rsa.rsa_pub_dec = meth1->rsa_pub_dec; |
239 | 19 | atalla_rsa.rsa_priv_enc = meth1->rsa_priv_enc; |
240 | 19 | atalla_rsa.rsa_priv_dec = meth1->rsa_priv_dec; |
241 | 19 | # endif |
242 | | |
243 | 19 | # ifndef OPENSSL_NO_DSA |
244 | | /* |
245 | | * Use the DSA_OpenSSL() method and just hook the mod_exp-ish bits. |
246 | | */ |
247 | 19 | meth2 = DSA_OpenSSL(); |
248 | 19 | atalla_dsa.dsa_do_sign = meth2->dsa_do_sign; |
249 | 19 | atalla_dsa.dsa_sign_setup = meth2->dsa_sign_setup; |
250 | 19 | atalla_dsa.dsa_do_verify = meth2->dsa_do_verify; |
251 | 19 | # endif |
252 | | |
253 | 19 | # ifndef OPENSSL_NO_DH |
254 | | /* Much the same for Diffie-Hellman */ |
255 | 19 | meth3 = DH_OpenSSL(); |
256 | 19 | atalla_dh.generate_key = meth3->generate_key; |
257 | 19 | atalla_dh.compute_key = meth3->compute_key; |
258 | 19 | # endif |
259 | | |
260 | | /* Ensure the atalla error handling is set up */ |
261 | 19 | ERR_load_ATALLA_strings(); |
262 | 19 | return 1; |
263 | 19 | } |
264 | | |
265 | | # ifdef OPENSSL_NO_DYNAMIC_ENGINE |
266 | | static ENGINE *engine_atalla(void) |
267 | 19 | { |
268 | 19 | ENGINE *ret = ENGINE_new(); |
269 | 19 | if (!ret) |
270 | 0 | return NULL; |
271 | 19 | if (!bind_helper(ret)) { |
272 | 0 | ENGINE_free(ret); |
273 | 0 | return NULL; |
274 | 0 | } |
275 | 19 | return ret; |
276 | 19 | } |
277 | | |
278 | | void ENGINE_load_atalla(void) |
279 | 19 | { |
280 | | /* Copied from eng_[openssl|dyn].c */ |
281 | 19 | ENGINE *toadd = engine_atalla(); |
282 | 19 | if (!toadd) |
283 | 0 | return; |
284 | 19 | ENGINE_add(toadd); |
285 | 19 | ENGINE_free(toadd); |
286 | 19 | ERR_clear_error(); |
287 | 19 | } |
288 | | # endif |
289 | | |
290 | | /* |
291 | | * This is a process-global DSO handle used for loading and unloading the |
292 | | * Atalla library. NB: This is only set (or unset) during an init() or |
293 | | * finish() call (reference counts permitting) and they're operating with |
294 | | * global locks, so this should be thread-safe implicitly. |
295 | | */ |
296 | | static DSO *atalla_dso = NULL; |
297 | | |
298 | | /* |
299 | | * These are the function pointers that are (un)set when the library has |
300 | | * successfully (un)loaded. |
301 | | */ |
302 | | static tfnASI_GetHardwareConfig *p_Atalla_GetHardwareConfig = NULL; |
303 | | static tfnASI_RSAPrivateKeyOpFn *p_Atalla_RSAPrivateKeyOpFn = NULL; |
304 | | static tfnASI_GetPerformanceStatistics *p_Atalla_GetPerformanceStatistics = |
305 | | NULL; |
306 | | |
307 | | /* |
308 | | * These are the static string constants for the DSO file name and the |
309 | | * function symbol names to bind to. Regrettably, the DSO name on *nix |
310 | | * appears to be "atasi.so" rather than something more consistent like |
311 | | * "libatasi.so". At the time of writing, I'm not sure what the file name on |
312 | | * win32 is but clearly native name translation is not possible (eg |
313 | | * libatasi.so on *nix, and atasi.dll on win32). For the purposes of testing, |
314 | | * I have created a symbollic link called "libatasi.so" so that we can use |
315 | | * native name-translation - a better solution will be needed. |
316 | | */ |
317 | | static const char *ATALLA_LIBNAME = NULL; |
318 | | static const char *get_ATALLA_LIBNAME(void) |
319 | 0 | { |
320 | 0 | if (ATALLA_LIBNAME) |
321 | 0 | return ATALLA_LIBNAME; |
322 | 0 | return "atasi"; |
323 | 0 | } |
324 | | |
325 | | static void free_ATALLA_LIBNAME(void) |
326 | 0 | { |
327 | 0 | if (ATALLA_LIBNAME) |
328 | 0 | OPENSSL_free((void *)ATALLA_LIBNAME); |
329 | 0 | ATALLA_LIBNAME = NULL; |
330 | 0 | } |
331 | | |
332 | | static long set_ATALLA_LIBNAME(const char *name) |
333 | 0 | { |
334 | 0 | free_ATALLA_LIBNAME(); |
335 | 0 | return (((ATALLA_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0); |
336 | 0 | } |
337 | | |
338 | | static const char *ATALLA_F1 = "ASI_GetHardwareConfig"; |
339 | | static const char *ATALLA_F2 = "ASI_RSAPrivateKeyOpFn"; |
340 | | static const char *ATALLA_F3 = "ASI_GetPerformanceStatistics"; |
341 | | |
342 | | /* Destructor (complements the "ENGINE_atalla()" constructor) */ |
343 | | static int atalla_destroy(ENGINE *e) |
344 | 0 | { |
345 | 0 | free_ATALLA_LIBNAME(); |
346 | | /* |
347 | | * Unload the atalla error strings so any error state including our |
348 | | * functs or reasons won't lead to a segfault (they simply get displayed |
349 | | * without corresponding string data because none will be found). |
350 | | */ |
351 | 0 | ERR_unload_ATALLA_strings(); |
352 | 0 | return 1; |
353 | 0 | } |
354 | | |
355 | | /* (de)initialisation functions. */ |
356 | | static int atalla_init(ENGINE *e) |
357 | 0 | { |
358 | 0 | tfnASI_GetHardwareConfig *p1; |
359 | 0 | tfnASI_RSAPrivateKeyOpFn *p2; |
360 | 0 | tfnASI_GetPerformanceStatistics *p3; |
361 | | /* |
362 | | * Not sure of the origin of this magic value, but Ben's code had it and |
363 | | * it seemed to have been working for a few people. :-) |
364 | | */ |
365 | 0 | unsigned int config_buf[1024]; |
366 | |
|
367 | 0 | if (atalla_dso != NULL) { |
368 | 0 | ATALLAerr(ATALLA_F_ATALLA_INIT, ATALLA_R_ALREADY_LOADED); |
369 | 0 | goto err; |
370 | 0 | } |
371 | | /* |
372 | | * Attempt to load libatasi.so/atasi.dll/whatever. Needs to be changed |
373 | | * unfortunately because the Atalla drivers don't have standard library |
374 | | * names that can be platform-translated well. |
375 | | */ |
376 | | /* |
377 | | * TODO: Work out how to actually map to the names the Atalla drivers |
378 | | * really use - for now a symbollic link needs to be created on the host |
379 | | * system from libatasi.so to atasi.so on unix variants. |
380 | | */ |
381 | 0 | atalla_dso = DSO_load(NULL, get_ATALLA_LIBNAME(), NULL, 0); |
382 | 0 | if (atalla_dso == NULL) { |
383 | 0 | ATALLAerr(ATALLA_F_ATALLA_INIT, ATALLA_R_NOT_LOADED); |
384 | 0 | goto err; |
385 | 0 | } |
386 | 0 | if (! |
387 | 0 | (p1 = |
388 | 0 | (tfnASI_GetHardwareConfig *) DSO_bind_func(atalla_dso, ATALLA_F1)) |
389 | 0 | || !(p2 = (tfnASI_RSAPrivateKeyOpFn *) DSO_bind_func(atalla_dso, ATALLA_F2)) |
390 | 0 | || !(p3 = |
391 | 0 | (tfnASI_GetPerformanceStatistics *) DSO_bind_func(atalla_dso, |
392 | 0 | ATALLA_F3))) { |
393 | 0 | ATALLAerr(ATALLA_F_ATALLA_INIT, ATALLA_R_NOT_LOADED); |
394 | 0 | goto err; |
395 | 0 | } |
396 | | /* Copy the pointers */ |
397 | 0 | p_Atalla_GetHardwareConfig = p1; |
398 | 0 | p_Atalla_RSAPrivateKeyOpFn = p2; |
399 | 0 | p_Atalla_GetPerformanceStatistics = p3; |
400 | | /* |
401 | | * Perform a basic test to see if there's actually any unit running. |
402 | | */ |
403 | 0 | if (p1(0L, config_buf) != 0) { |
404 | 0 | ATALLAerr(ATALLA_F_ATALLA_INIT, ATALLA_R_UNIT_FAILURE); |
405 | 0 | goto err; |
406 | 0 | } |
407 | | /* Everything's fine. */ |
408 | 0 | return 1; |
409 | 0 | err: |
410 | 0 | if (atalla_dso) |
411 | 0 | DSO_free(atalla_dso); |
412 | 0 | atalla_dso = NULL; |
413 | 0 | p_Atalla_GetHardwareConfig = NULL; |
414 | 0 | p_Atalla_RSAPrivateKeyOpFn = NULL; |
415 | 0 | p_Atalla_GetPerformanceStatistics = NULL; |
416 | 0 | return 0; |
417 | 0 | } |
418 | | |
419 | | static int atalla_finish(ENGINE *e) |
420 | 0 | { |
421 | 0 | free_ATALLA_LIBNAME(); |
422 | 0 | if (atalla_dso == NULL) { |
423 | 0 | ATALLAerr(ATALLA_F_ATALLA_FINISH, ATALLA_R_NOT_LOADED); |
424 | 0 | return 0; |
425 | 0 | } |
426 | 0 | if (!DSO_free(atalla_dso)) { |
427 | 0 | ATALLAerr(ATALLA_F_ATALLA_FINISH, ATALLA_R_UNIT_FAILURE); |
428 | 0 | return 0; |
429 | 0 | } |
430 | 0 | atalla_dso = NULL; |
431 | 0 | p_Atalla_GetHardwareConfig = NULL; |
432 | 0 | p_Atalla_RSAPrivateKeyOpFn = NULL; |
433 | 0 | p_Atalla_GetPerformanceStatistics = NULL; |
434 | 0 | return 1; |
435 | 0 | } |
436 | | |
437 | | static int atalla_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void)) |
438 | 0 | { |
439 | 0 | int initialised = ((atalla_dso == NULL) ? 0 : 1); |
440 | 0 | switch (cmd) { |
441 | 0 | case ATALLA_CMD_SO_PATH: |
442 | 0 | if (p == NULL) { |
443 | 0 | ATALLAerr(ATALLA_F_ATALLA_CTRL, ERR_R_PASSED_NULL_PARAMETER); |
444 | 0 | return 0; |
445 | 0 | } |
446 | 0 | if (initialised) { |
447 | 0 | ATALLAerr(ATALLA_F_ATALLA_CTRL, ATALLA_R_ALREADY_LOADED); |
448 | 0 | return 0; |
449 | 0 | } |
450 | 0 | return set_ATALLA_LIBNAME((const char *)p); |
451 | 0 | default: |
452 | 0 | break; |
453 | 0 | } |
454 | 0 | ATALLAerr(ATALLA_F_ATALLA_CTRL, ATALLA_R_CTRL_COMMAND_NOT_IMPLEMENTED); |
455 | 0 | return 0; |
456 | 0 | } |
457 | | |
458 | | static int atalla_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, |
459 | | const BIGNUM *m, BN_CTX *ctx) |
460 | 0 | { |
461 | | /* |
462 | | * I need somewhere to store temporary serialised values for use with the |
463 | | * Atalla API calls. A neat cheat - I'll use BIGNUMs from the BN_CTX but |
464 | | * access their arrays directly as byte arrays <grin>. This way I don't |
465 | | * have to clean anything up. |
466 | | */ |
467 | 0 | BIGNUM *modulus; |
468 | 0 | BIGNUM *exponent; |
469 | 0 | BIGNUM *argument; |
470 | 0 | BIGNUM *result; |
471 | 0 | RSAPrivateKey keydata; |
472 | 0 | int to_return, numbytes; |
473 | |
|
474 | 0 | modulus = exponent = argument = result = NULL; |
475 | 0 | to_return = 0; /* expect failure */ |
476 | |
|
477 | 0 | if (!atalla_dso) { |
478 | 0 | ATALLAerr(ATALLA_F_ATALLA_MOD_EXP, ATALLA_R_NOT_LOADED); |
479 | 0 | goto err; |
480 | 0 | } |
481 | | /* Prepare the params */ |
482 | 0 | BN_CTX_start(ctx); |
483 | 0 | modulus = BN_CTX_get(ctx); |
484 | 0 | exponent = BN_CTX_get(ctx); |
485 | 0 | argument = BN_CTX_get(ctx); |
486 | 0 | result = BN_CTX_get(ctx); |
487 | 0 | if (!result) { |
488 | 0 | ATALLAerr(ATALLA_F_ATALLA_MOD_EXP, ATALLA_R_BN_CTX_FULL); |
489 | 0 | goto err; |
490 | 0 | } |
491 | 0 | if (!bn_wexpand(modulus, m->top) || !bn_wexpand(exponent, m->top) || |
492 | 0 | !bn_wexpand(argument, m->top) || !bn_wexpand(result, m->top)) { |
493 | 0 | ATALLAerr(ATALLA_F_ATALLA_MOD_EXP, ATALLA_R_BN_EXPAND_FAIL); |
494 | 0 | goto err; |
495 | 0 | } |
496 | | /* Prepare the key-data */ |
497 | 0 | memset(&keydata, 0, sizeof keydata); |
498 | 0 | numbytes = BN_num_bytes(m); |
499 | 0 | memset(exponent->d, 0, numbytes); |
500 | 0 | memset(modulus->d, 0, numbytes); |
501 | 0 | BN_bn2bin(p, (unsigned char *)exponent->d + numbytes - BN_num_bytes(p)); |
502 | 0 | BN_bn2bin(m, (unsigned char *)modulus->d + numbytes - BN_num_bytes(m)); |
503 | 0 | keydata.privateExponent.data = (unsigned char *)exponent->d; |
504 | 0 | keydata.privateExponent.len = numbytes; |
505 | 0 | keydata.modulus.data = (unsigned char *)modulus->d; |
506 | 0 | keydata.modulus.len = numbytes; |
507 | | /* Prepare the argument */ |
508 | 0 | memset(argument->d, 0, numbytes); |
509 | 0 | memset(result->d, 0, numbytes); |
510 | 0 | BN_bn2bin(a, (unsigned char *)argument->d + numbytes - BN_num_bytes(a)); |
511 | | /* Perform the operation */ |
512 | 0 | if (p_Atalla_RSAPrivateKeyOpFn(&keydata, (unsigned char *)result->d, |
513 | 0 | (unsigned char *)argument->d, |
514 | 0 | keydata.modulus.len) != 0) { |
515 | 0 | ATALLAerr(ATALLA_F_ATALLA_MOD_EXP, ATALLA_R_REQUEST_FAILED); |
516 | 0 | goto err; |
517 | 0 | } |
518 | | /* Convert the response */ |
519 | 0 | BN_bin2bn((unsigned char *)result->d, numbytes, r); |
520 | 0 | to_return = 1; |
521 | 0 | err: |
522 | 0 | BN_CTX_end(ctx); |
523 | 0 | return to_return; |
524 | 0 | } |
525 | | |
526 | | # ifndef OPENSSL_NO_RSA |
527 | | static int atalla_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, |
528 | | BN_CTX *ctx) |
529 | 0 | { |
530 | 0 | int to_return = 0; |
531 | |
|
532 | 0 | if (!atalla_dso) { |
533 | 0 | ATALLAerr(ATALLA_F_ATALLA_RSA_MOD_EXP, ATALLA_R_NOT_LOADED); |
534 | 0 | goto err; |
535 | 0 | } |
536 | 0 | if (!rsa->d || !rsa->n) { |
537 | 0 | ATALLAerr(ATALLA_F_ATALLA_RSA_MOD_EXP, |
538 | 0 | ATALLA_R_MISSING_KEY_COMPONENTS); |
539 | 0 | goto err; |
540 | 0 | } |
541 | 0 | to_return = atalla_mod_exp(r0, I, rsa->d, rsa->n, ctx); |
542 | 0 | err: |
543 | 0 | return to_return; |
544 | 0 | } |
545 | | # endif |
546 | | |
547 | | # ifndef OPENSSL_NO_DSA |
548 | | /* |
549 | | * This code was liberated and adapted from the commented-out code in |
550 | | * dsa_ossl.c. Because of the unoptimised form of the Atalla acceleration (it |
551 | | * doesn't have a CRT form for RSA), this function means that an Atalla |
552 | | * system running with a DSA server certificate can handshake around 5 or 6 |
553 | | * times faster/more than an equivalent system running with RSA. Just check |
554 | | * out the "signs" statistics from the RSA and DSA parts of "openssl speed |
555 | | * -engine atalla dsa1024 rsa1024". |
556 | | */ |
557 | | static int atalla_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1, |
558 | | BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m, |
559 | | BN_CTX *ctx, BN_MONT_CTX *in_mont) |
560 | 0 | { |
561 | 0 | BIGNUM t; |
562 | 0 | int to_return = 0; |
563 | |
|
564 | 0 | BN_init(&t); |
565 | | /* let rr = a1 ^ p1 mod m */ |
566 | 0 | if (!atalla_mod_exp(rr, a1, p1, m, ctx)) |
567 | 0 | goto end; |
568 | | /* let t = a2 ^ p2 mod m */ |
569 | 0 | if (!atalla_mod_exp(&t, a2, p2, m, ctx)) |
570 | 0 | goto end; |
571 | | /* let rr = rr * t mod m */ |
572 | 0 | if (!BN_mod_mul(rr, rr, &t, m, ctx)) |
573 | 0 | goto end; |
574 | 0 | to_return = 1; |
575 | 0 | end: |
576 | 0 | BN_free(&t); |
577 | 0 | return to_return; |
578 | 0 | } |
579 | | |
580 | | static int atalla_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a, |
581 | | const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, |
582 | | BN_MONT_CTX *m_ctx) |
583 | 0 | { |
584 | 0 | return atalla_mod_exp(r, a, p, m, ctx); |
585 | 0 | } |
586 | | # endif |
587 | | |
588 | | # ifndef OPENSSL_NO_RSA |
589 | | /* This function is aliased to mod_exp (with the mont stuff dropped). */ |
590 | | static int atalla_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, |
591 | | const BIGNUM *m, BN_CTX *ctx, |
592 | | BN_MONT_CTX *m_ctx) |
593 | 0 | { |
594 | 0 | return atalla_mod_exp(r, a, p, m, ctx); |
595 | 0 | } |
596 | | # endif |
597 | | |
598 | | # ifndef OPENSSL_NO_DH |
599 | | /* This function is aliased to mod_exp (with the dh and mont dropped). */ |
600 | | static int atalla_mod_exp_dh(const DH *dh, BIGNUM *r, |
601 | | const BIGNUM *a, const BIGNUM *p, |
602 | | const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) |
603 | 0 | { |
604 | 0 | return atalla_mod_exp(r, a, p, m, ctx); |
605 | 0 | } |
606 | | # endif |
607 | | |
608 | | /* |
609 | | * This stuff is needed if this ENGINE is being compiled into a |
610 | | * self-contained shared-library. |
611 | | */ |
612 | | # ifndef OPENSSL_NO_DYNAMIC_ENGINE |
613 | | static int bind_fn(ENGINE *e, const char *id) |
614 | | { |
615 | | if (id && (strcmp(id, engine_atalla_id) != 0)) |
616 | | return 0; |
617 | | if (!bind_helper(e)) |
618 | | return 0; |
619 | | return 1; |
620 | | } |
621 | | |
622 | | IMPLEMENT_DYNAMIC_CHECK_FN() |
623 | | IMPLEMENT_DYNAMIC_BIND_FN(bind_fn) |
624 | | # endif /* OPENSSL_NO_DYNAMIC_ENGINE */ |
625 | | # endif /* !OPENSSL_NO_HW_ATALLA */ |
626 | | #endif /* !OPENSSL_NO_HW */ |