diff options
Diffstat (limited to 'src/lib/libcrypto/engine/hw_atalla.c')
-rw-r--r-- | src/lib/libcrypto/engine/hw_atalla.c | 444 |
1 files changed, 444 insertions, 0 deletions
diff --git a/src/lib/libcrypto/engine/hw_atalla.c b/src/lib/libcrypto/engine/hw_atalla.c new file mode 100644 index 0000000000..3bb992a193 --- /dev/null +++ b/src/lib/libcrypto/engine/hw_atalla.c | |||
@@ -0,0 +1,444 @@ | |||
1 | /* crypto/engine/hw_atalla.c */ | ||
2 | /* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL | ||
3 | * project 2000. | ||
4 | */ | ||
5 | /* ==================================================================== | ||
6 | * Copyright (c) 1999 The OpenSSL Project. All rights reserved. | ||
7 | * | ||
8 | * Redistribution and use in source and binary forms, with or without | ||
9 | * modification, are permitted provided that the following conditions | ||
10 | * are met: | ||
11 | * | ||
12 | * 1. Redistributions of source code must retain the above copyright | ||
13 | * notice, this list of conditions and the following disclaimer. | ||
14 | * | ||
15 | * 2. Redistributions in binary form must reproduce the above copyright | ||
16 | * notice, this list of conditions and the following disclaimer in | ||
17 | * the documentation and/or other materials provided with the | ||
18 | * distribution. | ||
19 | * | ||
20 | * 3. All advertising materials mentioning features or use of this | ||
21 | * software must display the following acknowledgment: | ||
22 | * "This product includes software developed by the OpenSSL Project | ||
23 | * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" | ||
24 | * | ||
25 | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | ||
26 | * endorse or promote products derived from this software without | ||
27 | * prior written permission. For written permission, please contact | ||
28 | * licensing@OpenSSL.org. | ||
29 | * | ||
30 | * 5. Products derived from this software may not be called "OpenSSL" | ||
31 | * nor may "OpenSSL" appear in their names without prior written | ||
32 | * permission of the OpenSSL Project. | ||
33 | * | ||
34 | * 6. Redistributions of any form whatsoever must retain the following | ||
35 | * acknowledgment: | ||
36 | * "This product includes software developed by the OpenSSL Project | ||
37 | * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" | ||
38 | * | ||
39 | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | ||
40 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
41 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
42 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | ||
43 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
44 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
45 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
46 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
47 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
48 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
49 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | ||
50 | * OF THE POSSIBILITY OF SUCH DAMAGE. | ||
51 | * ==================================================================== | ||
52 | * | ||
53 | * This product includes cryptographic software written by Eric Young | ||
54 | * (eay@cryptsoft.com). This product includes software written by Tim | ||
55 | * Hudson (tjh@cryptsoft.com). | ||
56 | * | ||
57 | */ | ||
58 | |||
59 | #include <stdio.h> | ||
60 | #include <openssl/crypto.h> | ||
61 | #include "cryptlib.h" | ||
62 | #include <openssl/dso.h> | ||
63 | #include "engine_int.h" | ||
64 | #include <openssl/engine.h> | ||
65 | |||
66 | #ifndef NO_HW | ||
67 | #ifndef NO_HW_ATALLA | ||
68 | |||
69 | #ifdef FLAT_INC | ||
70 | #include "atalla.h" | ||
71 | #else | ||
72 | #include "vendor_defns/atalla.h" | ||
73 | #endif | ||
74 | |||
75 | static int atalla_init(void); | ||
76 | static int atalla_finish(void); | ||
77 | |||
78 | /* BIGNUM stuff */ | ||
79 | static int atalla_mod_exp(BIGNUM *r, BIGNUM *a, const BIGNUM *p, | ||
80 | const BIGNUM *m, BN_CTX *ctx); | ||
81 | |||
82 | /* RSA stuff */ | ||
83 | static int atalla_rsa_mod_exp(BIGNUM *r0, BIGNUM *I, RSA *rsa); | ||
84 | /* This function is aliased to mod_exp (with the mont stuff dropped). */ | ||
85 | static int atalla_mod_exp_mont(BIGNUM *r, BIGNUM *a, const BIGNUM *p, | ||
86 | const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); | ||
87 | |||
88 | /* DSA stuff */ | ||
89 | static int atalla_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1, | ||
90 | BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m, | ||
91 | BN_CTX *ctx, BN_MONT_CTX *in_mont); | ||
92 | static int atalla_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a, | ||
93 | const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, | ||
94 | BN_MONT_CTX *m_ctx); | ||
95 | |||
96 | /* DH stuff */ | ||
97 | /* This function is alised to mod_exp (with the DH and mont dropped). */ | ||
98 | static int atalla_mod_exp_dh(DH *dh, BIGNUM *r, BIGNUM *a, const BIGNUM *p, | ||
99 | const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); | ||
100 | |||
101 | |||
102 | /* Our internal RSA_METHOD that we provide pointers to */ | ||
103 | static RSA_METHOD atalla_rsa = | ||
104 | { | ||
105 | "Atalla RSA method", | ||
106 | NULL, | ||
107 | NULL, | ||
108 | NULL, | ||
109 | NULL, | ||
110 | atalla_rsa_mod_exp, | ||
111 | atalla_mod_exp_mont, | ||
112 | NULL, | ||
113 | NULL, | ||
114 | 0, | ||
115 | NULL, | ||
116 | NULL, | ||
117 | NULL | ||
118 | }; | ||
119 | |||
120 | /* Our internal DSA_METHOD that we provide pointers to */ | ||
121 | static DSA_METHOD atalla_dsa = | ||
122 | { | ||
123 | "Atalla DSA method", | ||
124 | NULL, /* dsa_do_sign */ | ||
125 | NULL, /* dsa_sign_setup */ | ||
126 | NULL, /* dsa_do_verify */ | ||
127 | atalla_dsa_mod_exp, /* dsa_mod_exp */ | ||
128 | atalla_mod_exp_dsa, /* bn_mod_exp */ | ||
129 | NULL, /* init */ | ||
130 | NULL, /* finish */ | ||
131 | 0, /* flags */ | ||
132 | NULL /* app_data */ | ||
133 | }; | ||
134 | |||
135 | /* Our internal DH_METHOD that we provide pointers to */ | ||
136 | static DH_METHOD atalla_dh = | ||
137 | { | ||
138 | "Atalla DH method", | ||
139 | NULL, | ||
140 | NULL, | ||
141 | atalla_mod_exp_dh, | ||
142 | NULL, | ||
143 | NULL, | ||
144 | 0, | ||
145 | NULL | ||
146 | }; | ||
147 | |||
148 | /* Our ENGINE structure. */ | ||
149 | static ENGINE engine_atalla = | ||
150 | { | ||
151 | "atalla", | ||
152 | "Atalla hardware engine support", | ||
153 | &atalla_rsa, | ||
154 | &atalla_dsa, | ||
155 | &atalla_dh, | ||
156 | NULL, | ||
157 | atalla_mod_exp, | ||
158 | NULL, | ||
159 | atalla_init, | ||
160 | atalla_finish, | ||
161 | NULL, /* no ctrl() */ | ||
162 | NULL, /* no load_privkey() */ | ||
163 | NULL, /* no load_pubkey() */ | ||
164 | 0, /* no flags */ | ||
165 | 0, 0, /* no references */ | ||
166 | NULL, NULL /* unlinked */ | ||
167 | }; | ||
168 | |||
169 | /* As this is only ever called once, there's no need for locking | ||
170 | * (indeed - the lock will already be held by our caller!!!) */ | ||
171 | ENGINE *ENGINE_atalla() | ||
172 | { | ||
173 | RSA_METHOD *meth1; | ||
174 | DSA_METHOD *meth2; | ||
175 | DH_METHOD *meth3; | ||
176 | |||
177 | /* We know that the "PKCS1_SSLeay()" functions hook properly | ||
178 | * to the atalla-specific mod_exp and mod_exp_crt so we use | ||
179 | * those functions. NB: We don't use ENGINE_openssl() or | ||
180 | * anything "more generic" because something like the RSAref | ||
181 | * code may not hook properly, and if you own one of these | ||
182 | * cards then you have the right to do RSA operations on it | ||
183 | * anyway! */ | ||
184 | meth1 = RSA_PKCS1_SSLeay(); | ||
185 | atalla_rsa.rsa_pub_enc = meth1->rsa_pub_enc; | ||
186 | atalla_rsa.rsa_pub_dec = meth1->rsa_pub_dec; | ||
187 | atalla_rsa.rsa_priv_enc = meth1->rsa_priv_enc; | ||
188 | atalla_rsa.rsa_priv_dec = meth1->rsa_priv_dec; | ||
189 | |||
190 | /* Use the DSA_OpenSSL() method and just hook the mod_exp-ish | ||
191 | * bits. */ | ||
192 | meth2 = DSA_OpenSSL(); | ||
193 | atalla_dsa.dsa_do_sign = meth2->dsa_do_sign; | ||
194 | atalla_dsa.dsa_sign_setup = meth2->dsa_sign_setup; | ||
195 | atalla_dsa.dsa_do_verify = meth2->dsa_do_verify; | ||
196 | |||
197 | /* Much the same for Diffie-Hellman */ | ||
198 | meth3 = DH_OpenSSL(); | ||
199 | atalla_dh.generate_key = meth3->generate_key; | ||
200 | atalla_dh.compute_key = meth3->compute_key; | ||
201 | return &engine_atalla; | ||
202 | } | ||
203 | |||
204 | /* This is a process-global DSO handle used for loading and unloading | ||
205 | * the Atalla library. NB: This is only set (or unset) during an | ||
206 | * init() or finish() call (reference counts permitting) and they're | ||
207 | * operating with global locks, so this should be thread-safe | ||
208 | * implicitly. */ | ||
209 | static DSO *atalla_dso = NULL; | ||
210 | |||
211 | /* These are the function pointers that are (un)set when the library has | ||
212 | * successfully (un)loaded. */ | ||
213 | static tfnASI_GetHardwareConfig *p_Atalla_GetHardwareConfig = NULL; | ||
214 | static tfnASI_RSAPrivateKeyOpFn *p_Atalla_RSAPrivateKeyOpFn = NULL; | ||
215 | static tfnASI_GetPerformanceStatistics *p_Atalla_GetPerformanceStatistics = NULL; | ||
216 | |||
217 | /* (de)initialisation functions. */ | ||
218 | static int atalla_init() | ||
219 | { | ||
220 | tfnASI_GetHardwareConfig *p1; | ||
221 | tfnASI_RSAPrivateKeyOpFn *p2; | ||
222 | tfnASI_GetPerformanceStatistics *p3; | ||
223 | /* Not sure of the origin of this magic value, but Ben's code had it | ||
224 | * and it seemed to have been working for a few people. :-) */ | ||
225 | unsigned int config_buf[1024]; | ||
226 | |||
227 | if(atalla_dso != NULL) | ||
228 | { | ||
229 | ENGINEerr(ENGINE_F_ATALLA_INIT,ENGINE_R_ALREADY_LOADED); | ||
230 | goto err; | ||
231 | } | ||
232 | /* Attempt to load libatasi.so/atasi.dll/whatever. Needs to be | ||
233 | * changed unfortunately because the Atalla drivers don't have | ||
234 | * standard library names that can be platform-translated well. */ | ||
235 | /* TODO: Work out how to actually map to the names the Atalla | ||
236 | * drivers really use - for now a symbollic link needs to be | ||
237 | * created on the host system from libatasi.so to atasi.so on | ||
238 | * unix variants. */ | ||
239 | atalla_dso = DSO_load(NULL, ATALLA_LIBNAME, NULL, | ||
240 | DSO_FLAG_NAME_TRANSLATION); | ||
241 | if(atalla_dso == NULL) | ||
242 | { | ||
243 | ENGINEerr(ENGINE_F_ATALLA_INIT,ENGINE_R_DSO_FAILURE); | ||
244 | goto err; | ||
245 | } | ||
246 | if(!(p1 = (tfnASI_GetHardwareConfig *)DSO_bind_func( | ||
247 | atalla_dso, ATALLA_F1)) || | ||
248 | !(p2 = (tfnASI_RSAPrivateKeyOpFn *)DSO_bind_func( | ||
249 | atalla_dso, ATALLA_F2)) || | ||
250 | !(p3 = (tfnASI_GetPerformanceStatistics *)DSO_bind_func( | ||
251 | atalla_dso, ATALLA_F3))) | ||
252 | { | ||
253 | ENGINEerr(ENGINE_F_ATALLA_INIT,ENGINE_R_DSO_FAILURE); | ||
254 | goto err; | ||
255 | } | ||
256 | /* Copy the pointers */ | ||
257 | p_Atalla_GetHardwareConfig = p1; | ||
258 | p_Atalla_RSAPrivateKeyOpFn = p2; | ||
259 | p_Atalla_GetPerformanceStatistics = p3; | ||
260 | /* Perform a basic test to see if there's actually any unit | ||
261 | * running. */ | ||
262 | if(p1(0L, config_buf) != 0) | ||
263 | { | ||
264 | ENGINEerr(ENGINE_F_ATALLA_INIT,ENGINE_R_UNIT_FAILURE); | ||
265 | goto err; | ||
266 | } | ||
267 | /* Everything's fine. */ | ||
268 | return 1; | ||
269 | err: | ||
270 | if(atalla_dso) | ||
271 | DSO_free(atalla_dso); | ||
272 | p_Atalla_GetHardwareConfig = NULL; | ||
273 | p_Atalla_RSAPrivateKeyOpFn = NULL; | ||
274 | p_Atalla_GetPerformanceStatistics = NULL; | ||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | static int atalla_finish() | ||
279 | { | ||
280 | if(atalla_dso == NULL) | ||
281 | { | ||
282 | ENGINEerr(ENGINE_F_ATALLA_FINISH,ENGINE_R_NOT_LOADED); | ||
283 | return 0; | ||
284 | } | ||
285 | if(!DSO_free(atalla_dso)) | ||
286 | { | ||
287 | ENGINEerr(ENGINE_F_ATALLA_FINISH,ENGINE_R_DSO_FAILURE); | ||
288 | return 0; | ||
289 | } | ||
290 | atalla_dso = NULL; | ||
291 | p_Atalla_GetHardwareConfig = NULL; | ||
292 | p_Atalla_RSAPrivateKeyOpFn = NULL; | ||
293 | p_Atalla_GetPerformanceStatistics = NULL; | ||
294 | return 1; | ||
295 | } | ||
296 | |||
297 | static int atalla_mod_exp(BIGNUM *r, BIGNUM *a, const BIGNUM *p, | ||
298 | const BIGNUM *m, BN_CTX *ctx) | ||
299 | { | ||
300 | /* I need somewhere to store temporary serialised values for | ||
301 | * use with the Atalla API calls. A neat cheat - I'll use | ||
302 | * BIGNUMs from the BN_CTX but access their arrays directly as | ||
303 | * byte arrays <grin>. This way I don't have to clean anything | ||
304 | * up. */ | ||
305 | BIGNUM *modulus; | ||
306 | BIGNUM *exponent; | ||
307 | BIGNUM *argument; | ||
308 | BIGNUM *result; | ||
309 | RSAPrivateKey keydata; | ||
310 | int to_return, numbytes; | ||
311 | |||
312 | modulus = exponent = argument = result = NULL; | ||
313 | to_return = 0; /* expect failure */ | ||
314 | |||
315 | if(!atalla_dso) | ||
316 | { | ||
317 | ENGINEerr(ENGINE_F_ATALLA_MOD_EXP,ENGINE_R_NOT_LOADED); | ||
318 | goto err; | ||
319 | } | ||
320 | /* Prepare the params */ | ||
321 | modulus = BN_CTX_get(ctx); | ||
322 | exponent = BN_CTX_get(ctx); | ||
323 | argument = BN_CTX_get(ctx); | ||
324 | result = BN_CTX_get(ctx); | ||
325 | if(!modulus || !exponent || !argument || !result) | ||
326 | { | ||
327 | ENGINEerr(ENGINE_F_ATALLA_MOD_EXP,ENGINE_R_BN_CTX_FULL); | ||
328 | goto err; | ||
329 | } | ||
330 | if(!bn_wexpand(modulus, m->top) || !bn_wexpand(exponent, m->top) || | ||
331 | !bn_wexpand(argument, m->top) || !bn_wexpand(result, m->top)) | ||
332 | { | ||
333 | ENGINEerr(ENGINE_F_ATALLA_MOD_EXP,ENGINE_R_BN_EXPAND_FAIL); | ||
334 | goto err; | ||
335 | } | ||
336 | /* Prepare the key-data */ | ||
337 | memset(&keydata, 0,sizeof keydata); | ||
338 | numbytes = BN_num_bytes(m); | ||
339 | memset(exponent->d, 0, numbytes); | ||
340 | memset(modulus->d, 0, numbytes); | ||
341 | BN_bn2bin(p, (unsigned char *)exponent->d + numbytes - BN_num_bytes(p)); | ||
342 | BN_bn2bin(m, (unsigned char *)modulus->d + numbytes - BN_num_bytes(m)); | ||
343 | keydata.privateExponent.data = (unsigned char *)exponent->d; | ||
344 | keydata.privateExponent.len = numbytes; | ||
345 | keydata.modulus.data = (unsigned char *)modulus->d; | ||
346 | keydata.modulus.len = numbytes; | ||
347 | /* Prepare the argument */ | ||
348 | memset(argument->d, 0, numbytes); | ||
349 | memset(result->d, 0, numbytes); | ||
350 | BN_bn2bin(a, (unsigned char *)argument->d + numbytes - BN_num_bytes(a)); | ||
351 | /* Perform the operation */ | ||
352 | if(p_Atalla_RSAPrivateKeyOpFn(&keydata, (unsigned char *)result->d, | ||
353 | (unsigned char *)argument->d, | ||
354 | keydata.modulus.len) != 0) | ||
355 | { | ||
356 | ENGINEerr(ENGINE_F_ATALLA_MOD_EXP,ENGINE_R_REQUEST_FAILED); | ||
357 | goto err; | ||
358 | } | ||
359 | /* Convert the response */ | ||
360 | BN_bin2bn((unsigned char *)result->d, numbytes, r); | ||
361 | to_return = 1; | ||
362 | err: | ||
363 | if(modulus) ctx->tos--; | ||
364 | if(exponent) ctx->tos--; | ||
365 | if(argument) ctx->tos--; | ||
366 | if(result) ctx->tos--; | ||
367 | return to_return; | ||
368 | } | ||
369 | |||
370 | static int atalla_rsa_mod_exp(BIGNUM *r0, BIGNUM *I, RSA *rsa) | ||
371 | { | ||
372 | BN_CTX *ctx = NULL; | ||
373 | int to_return = 0; | ||
374 | |||
375 | if(!atalla_dso) | ||
376 | { | ||
377 | ENGINEerr(ENGINE_F_ATALLA_RSA_MOD_EXP,ENGINE_R_NOT_LOADED); | ||
378 | goto err; | ||
379 | } | ||
380 | if((ctx = BN_CTX_new()) == NULL) | ||
381 | goto err; | ||
382 | if(!rsa->d || !rsa->n) | ||
383 | { | ||
384 | ENGINEerr(ENGINE_F_ATALLA_RSA_MOD_EXP,ENGINE_R_MISSING_KEY_COMPONENTS); | ||
385 | goto err; | ||
386 | } | ||
387 | to_return = atalla_mod_exp(r0, I, rsa->d, rsa->n, ctx); | ||
388 | err: | ||
389 | if(ctx) | ||
390 | BN_CTX_free(ctx); | ||
391 | return to_return; | ||
392 | } | ||
393 | |||
394 | /* This code was liberated and adapted from the commented-out code in | ||
395 | * dsa_ossl.c. Because of the unoptimised form of the Atalla acceleration | ||
396 | * (it doesn't have a CRT form for RSA), this function means that an | ||
397 | * Atalla system running with a DSA server certificate can handshake | ||
398 | * around 5 or 6 times faster/more than an equivalent system running with | ||
399 | * RSA. Just check out the "signs" statistics from the RSA and DSA parts | ||
400 | * of "openssl speed -engine atalla dsa1024 rsa1024". */ | ||
401 | static int atalla_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1, | ||
402 | BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m, | ||
403 | BN_CTX *ctx, BN_MONT_CTX *in_mont) | ||
404 | { | ||
405 | BIGNUM t; | ||
406 | int to_return = 0; | ||
407 | |||
408 | BN_init(&t); | ||
409 | /* let rr = a1 ^ p1 mod m */ | ||
410 | if (!atalla_mod_exp(rr,a1,p1,m,ctx)) goto end; | ||
411 | /* let t = a2 ^ p2 mod m */ | ||
412 | if (!atalla_mod_exp(&t,a2,p2,m,ctx)) goto end; | ||
413 | /* let rr = rr * t mod m */ | ||
414 | if (!BN_mod_mul(rr,rr,&t,m,ctx)) goto end; | ||
415 | to_return = 1; | ||
416 | end: | ||
417 | BN_free(&t); | ||
418 | return to_return; | ||
419 | } | ||
420 | |||
421 | |||
422 | static int atalla_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a, | ||
423 | const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, | ||
424 | BN_MONT_CTX *m_ctx) | ||
425 | { | ||
426 | return atalla_mod_exp(r, a, p, m, ctx); | ||
427 | } | ||
428 | |||
429 | /* This function is aliased to mod_exp (with the mont stuff dropped). */ | ||
430 | static int atalla_mod_exp_mont(BIGNUM *r, BIGNUM *a, const BIGNUM *p, | ||
431 | const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) | ||
432 | { | ||
433 | return atalla_mod_exp(r, a, p, m, ctx); | ||
434 | } | ||
435 | |||
436 | /* This function is aliased to mod_exp (with the dh and mont dropped). */ | ||
437 | static int atalla_mod_exp_dh(DH *dh, BIGNUM *r, BIGNUM *a, const BIGNUM *p, | ||
438 | const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) | ||
439 | { | ||
440 | return atalla_mod_exp(r, a, p, m, ctx); | ||
441 | } | ||
442 | |||
443 | #endif /* !NO_HW_ATALLA */ | ||
444 | #endif /* !NO_HW */ | ||