1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83: #include <stdio.h>
84: #include <string.h>
85: #include <openssl/crypto.h>
86: #include <openssl/buffer.h>
87: #include <openssl/engine.h>
88:
89: #ifndef OPENSSL_NO_HW
90: #if defined(OPENSSL_USE_GMP) && !defined(OPENSSL_NO_HW_GMP)
91:
92: #include <gmp.h>
93:
94: #define E_GMP_LIB_NAME "gmp engine"
95: #include "e_gmp_err.c"
96:
97: static int e_gmp_destroy(ENGINE *e);
98: static int e_gmp_init(ENGINE *e);
99: static int e_gmp_finish(ENGINE *e);
100: static int e_gmp_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void));
101:
102: #ifndef OPENSSL_NO_RSA
103:
104: static int e_gmp_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa, BN_CTX *ctx);
105: static int e_gmp_rsa_finish(RSA *r);
106: #endif
107:
108:
109:
110: static const ENGINE_CMD_DEFN e_gmp_cmd_defns[] = {
111: #if 0
112: {E_GMP_CMD_SO_PATH,
113: "SO_PATH",
114: "Specifies the path to the 'e_gmp' shared library",
115: ENGINE_CMD_FLAG_STRING},
116: #endif
117: {0, NULL, NULL, 0}
118: };
119:
120: #ifndef OPENSSL_NO_RSA
121:
122: static RSA_METHOD e_gmp_rsa =
123: {
124: "GMP RSA method",
125: NULL,
126: NULL,
127: NULL,
128: NULL,
129: e_gmp_rsa_mod_exp,
130: NULL,
131: NULL,
132: e_gmp_rsa_finish,
133:
134:
135:
136: RSA_FLAG_CACHE_PUBLIC|RSA_FLAG_CACHE_PRIVATE,
137: NULL,
138: NULL,
139: NULL
140: };
141: #endif
142:
143:
144: static const char *engine_e_gmp_id = "gmp";
145: static const char *engine_e_gmp_name = "GMP engine support";
146:
147:
148:
149: static int bind_helper(ENGINE *e)
150: {
151: #ifndef OPENSSL_NO_RSA
152: const RSA_METHOD *meth1;
153: #endif
154: if(!ENGINE_set_id(e, engine_e_gmp_id) ||
155: !ENGINE_set_name(e, engine_e_gmp_name) ||
156: #ifndef OPENSSL_NO_RSA
157: !ENGINE_set_RSA(e, &e_gmp_rsa) ||
158: #endif
159: !ENGINE_set_destroy_function(e, e_gmp_destroy) ||
160: !ENGINE_set_init_function(e, e_gmp_init) ||
161: !ENGINE_set_finish_function(e, e_gmp_finish) ||
162: !ENGINE_set_ctrl_function(e, e_gmp_ctrl) ||
163: !ENGINE_set_cmd_defns(e, e_gmp_cmd_defns))
164: return 0;
165:
166: #ifndef OPENSSL_NO_RSA
167: meth1 = RSA_PKCS1_SSLeay();
168: e_gmp_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
169: e_gmp_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
170: e_gmp_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
171: e_gmp_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
172: e_gmp_rsa.bn_mod_exp = meth1->bn_mod_exp;
173: #endif
174:
175:
176: ERR_load_GMP_strings();
177: return 1;
178: }
179:
180: static ENGINE *engine_gmp(void)
181: {
182: ENGINE *ret = ENGINE_new();
183: if(!ret)
184: return NULL;
185: if(!bind_helper(ret))
186: {
187: ENGINE_free(ret);
188: return NULL;
189: }
190: return ret;
191: }
192:
193: void ENGINE_load_gmp(void)
194: {
195:
196: ENGINE *toadd = engine_gmp();
197: if(!toadd) return;
198: ENGINE_add(toadd);
199: ENGINE_free(toadd);
200: ERR_clear_error();
201: }
202:
203: #ifndef OPENSSL_NO_RSA
204:
205: static int hndidx_rsa = -1;
206: #endif
207:
208: static int e_gmp_destroy(ENGINE *e)
209: {
210: ERR_unload_GMP_strings();
211: return 1;
212: }
213:
214:
215: static int e_gmp_init(ENGINE *e)
216: {
217: #ifndef OPENSSL_NO_RSA
218: if (hndidx_rsa == -1)
219: hndidx_rsa = RSA_get_ex_new_index(0,
220: "GMP-based RSA key handle",
221: NULL, NULL, NULL);
222: #endif
223: if (hndidx_rsa == -1)
224: return 0;
225: return 1;
226: }
227:
228: static int e_gmp_finish(ENGINE *e)
229: {
230: return 1;
231: }
232:
233: static int e_gmp_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
234: {
235: int to_return = 1;
236:
237: switch(cmd)
238: {
239: #if 0
240: case E_GMP_CMD_SO_PATH:
241:
242: #endif
243:
244: default:
245: GMPerr(GMP_F_E_GMP_CTRL,
246: GMP_R_CTRL_COMMAND_NOT_IMPLEMENTED);
247: to_return = 0;
248: break;
249: }
250:
251: return to_return;
252: }
253:
254:
255:
256: static int bn2gmp(const BIGNUM *bn, mpz_t g)
257: {
258: int toret;
259: char *tmpchar = BN_bn2hex(bn);
260: if(!tmpchar) return 0;
261: toret = (mpz_set_str(g, tmpchar, 16) == 0 ? 1 : 0);
262: OPENSSL_free(tmpchar);
263: return toret;
264: }
265:
266: static int gmp2bn(mpz_t g, BIGNUM *bn)
267: {
268: int toret;
269: char *tmpchar = OPENSSL_malloc(mpz_sizeinbase(g, 16) + 10);
270: if(!tmpchar) return 0;
271: mpz_get_str(tmpchar, 16, g);
272: toret = BN_hex2bn(&bn, tmpchar);
273: OPENSSL_free(tmpchar);
274: return toret;
275: }
276:
277: #ifndef OPENSSL_NO_RSA
278: typedef struct st_e_gmp_rsa_ctx
279: {
280: int public_only;
281: mpz_t n;
282: mpz_t d;
283: mpz_t e;
284: mpz_t p;
285: mpz_t q;
286: mpz_t dmp1;
287: mpz_t dmq1;
288: mpz_t iqmp;
289: mpz_t r0, r1, I0, m1;
290: } E_GMP_RSA_CTX;
291:
292: static E_GMP_RSA_CTX *e_gmp_get_rsa(RSA *rsa)
293: {
294: E_GMP_RSA_CTX *hptr = RSA_get_ex_data(rsa, hndidx_rsa);
295: if(hptr) return hptr;
296: hptr = OPENSSL_malloc(sizeof(E_GMP_RSA_CTX));
297: if(!hptr) return NULL;
298:
299:
300: mpz_init(hptr->n);
301: mpz_init(hptr->d);
302: mpz_init(hptr->e);
303: mpz_init(hptr->p);
304: mpz_init(hptr->q);
305: mpz_init(hptr->dmp1);
306: mpz_init(hptr->dmq1);
307: mpz_init(hptr->iqmp);
308: mpz_init(hptr->r0);
309: mpz_init(hptr->r1);
310: mpz_init(hptr->I0);
311: mpz_init(hptr->m1);
312: if(!bn2gmp(rsa->n, hptr->n) || !bn2gmp(rsa->e, hptr->e))
313: goto err;
314: if(!rsa->p || !rsa->q || !rsa->d || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
315: {
316: hptr->public_only = 1;
317: return hptr;
318: }
319: if(!bn2gmp(rsa->d, hptr->d) || !bn2gmp(rsa->p, hptr->p) ||
320: !bn2gmp(rsa->q, hptr->q) || !bn2gmp(rsa->dmp1, hptr->dmp1) ||
321: !bn2gmp(rsa->dmq1, hptr->dmq1) || !bn2gmp(rsa->iqmp, hptr->iqmp))
322: goto err;
323: hptr->public_only = 0;
324: RSA_set_ex_data(rsa, hndidx_rsa, hptr);
325: return hptr;
326: err:
327: mpz_clear(hptr->n);
328: mpz_clear(hptr->d);
329: mpz_clear(hptr->e);
330: mpz_clear(hptr->p);
331: mpz_clear(hptr->q);
332: mpz_clear(hptr->dmp1);
333: mpz_clear(hptr->dmq1);
334: mpz_clear(hptr->iqmp);
335: mpz_clear(hptr->r0);
336: mpz_clear(hptr->r1);
337: mpz_clear(hptr->I0);
338: mpz_clear(hptr->m1);
339: OPENSSL_free(hptr);
340: return NULL;
341: }
342:
343: static int e_gmp_rsa_finish(RSA *rsa)
344: {
345: E_GMP_RSA_CTX *hptr = RSA_get_ex_data(rsa, hndidx_rsa);
346: if(!hptr) return 0;
347: mpz_clear(hptr->n);
348: mpz_clear(hptr->d);
349: mpz_clear(hptr->e);
350: mpz_clear(hptr->p);
351: mpz_clear(hptr->q);
352: mpz_clear(hptr->dmp1);
353: mpz_clear(hptr->dmq1);
354: mpz_clear(hptr->iqmp);
355: mpz_clear(hptr->r0);
356: mpz_clear(hptr->r1);
357: mpz_clear(hptr->I0);
358: mpz_clear(hptr->m1);
359: OPENSSL_free(hptr);
360: RSA_set_ex_data(rsa, hndidx_rsa, NULL);
361: return 1;
362: }
363:
364: static int e_gmp_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
365: {
366: E_GMP_RSA_CTX *hptr;
367: int to_return = 0;
368:
369: hptr = e_gmp_get_rsa(rsa);
370: if(!hptr)
371: {
372: GMPerr(GMP_F_E_GMP_RSA_MOD_EXP,
373: GMP_R_KEY_CONTEXT_ERROR);
374: return 0;
375: }
376: if(hptr->public_only)
377: {
378: GMPerr(GMP_F_E_GMP_RSA_MOD_EXP,
379: GMP_R_MISSING_KEY_COMPONENTS);
380: return 0;
381: }
382:
383:
384: if(!bn2gmp(I, hptr->I0))
385: return 0;
386:
387:
388:
389:
390:
391:
392: mpz_mod(hptr->r1, hptr->I0, hptr->q);
393: mpz_powm(hptr->m1, hptr->r1, hptr->dmq1, hptr->q);
394:
395: mpz_mod(hptr->r1, hptr->I0, hptr->p);
396: mpz_powm(hptr->r0, hptr->r1, hptr->dmp1, hptr->p);
397:
398: mpz_sub(hptr->r0, hptr->r0, hptr->m1);
399:
400: if(mpz_sgn(hptr->r0) < 0)
401: mpz_add(hptr->r0, hptr->r0, hptr->p);
402: mpz_mul(hptr->r1, hptr->r0, hptr->iqmp);
403: mpz_mod(hptr->r0, hptr->r1, hptr->p);
404:
405: if(mpz_sgn(hptr->r0) < 0)
406: mpz_add(hptr->r0, hptr->r0, hptr->p);
407: mpz_mul(hptr->r1, hptr->r0, hptr->q);
408: mpz_add(hptr->r0, hptr->r1, hptr->m1);
409:
410:
411: if(gmp2bn(hptr->r0, r))
412: to_return = 1;
413:
414: return 1;
415: }
416: #endif
417:
418:
419:
420: #ifdef ENGINE_DYNAMIC_SUPPORT
421: static int bind_fn(ENGINE *e, const char *id)
422: {
423: if(id && (strcmp(id, engine_e_gmp_id) != 0))
424: return 0;
425: if(!bind_helper(e))
426: return 0;
427: return 1;
428: }
429: IMPLEMENT_DYNAMIC_CHECK_FN()
430: IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
431: #endif
432:
433: #endif
434: #endif
435: