Line data Source code
1 : /*
2 : * Copyright (c) 2006 - 2007, 2010 Kungliga Tekniska Högskolan
3 : * (Royal Institute of Technology, Stockholm, Sweden).
4 : * All rights reserved.
5 : *
6 : * Redistribution and use in source and binary forms, with or without
7 : * modification, are permitted provided that the following conditions
8 : * are met:
9 : *
10 : * 1. Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : *
13 : * 2. Redistributions in binary form must reproduce the above copyright
14 : * notice, this list of conditions and the following disclaimer in the
15 : * documentation and/or other materials provided with the distribution.
16 : *
17 : * 3. Neither the name of the Institute nor the names of its contributors
18 : * may be used to endorse or promote products derived from this software
19 : * without specific prior written permission.
20 : *
21 : * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 : * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 : * SUCH DAMAGE.
32 : */
33 :
34 : #include <config.h>
35 : #include <roken.h>
36 : #include <krb5-types.h>
37 : #include <assert.h>
38 :
39 : #include <rsa.h>
40 :
41 : #include "tommath.h"
42 :
43 : #define CHECK(f) \
44 : do { where = __LINE__ + 1; if (ret == MP_OKAY && ((ret = f)) != MP_OKAY) { goto out; } } while (0)
45 : #define FIRST(e) do { ret = (e); } while (0)
46 : #define FIRST_ALLOC(e) \
47 : do { where = __LINE__; ret = ((e)) ? MP_OKAY : MP_MEM; } while (0)
48 : #define THEN_MP(e) \
49 : do { where = __LINE__ + 1; if (ret == MP_OKAY) ret = (e); } while (0)
50 : #define THEN_IF_MP(cond, e) \
51 : do { where = __LINE__ + 1; if (ret == MP_OKAY && (cond)) ret = (e); } while (0)
52 : #define THEN_IF_VOID(cond, e) \
53 : do { where = __LINE__ + 1; if (ret == MP_OKAY && (cond)) e; } while (0)
54 : #define THEN_VOID(e) \
55 : do { where = __LINE__ + 1; if (ret == MP_OKAY) e; } while (0)
56 : #define THEN_ALLOC(e) \
57 : do { where = __LINE__ + 1; if (ret == MP_OKAY) ret = ((e)) ? MP_OKAY : MP_MEM; } while (0)
58 :
59 : static mp_err
60 139 : random_num(mp_int *num, size_t len)
61 : {
62 8 : unsigned char *p;
63 139 : mp_err ret = MP_MEM;
64 :
65 139 : len = (len + 7) / 8; /* bits to bytes */
66 139 : if ((p = malloc(len)) && RAND_bytes(p, len) != 1)
67 0 : ret = MP_ERR;
68 139 : if (p)
69 139 : ret = mp_from_ubin(num, p, len);
70 139 : free(p);
71 139 : return ret;
72 : }
73 :
74 : static mp_err
75 1613 : BN2mpz(mp_int *s, const BIGNUM *bn)
76 : {
77 72 : size_t len;
78 1613 : mp_err ret = MP_MEM;
79 72 : void *p;
80 :
81 1613 : len = BN_num_bytes(bn);
82 1613 : p = malloc(len);
83 1613 : if (p) {
84 1613 : BN_bn2bin(bn, p);
85 1613 : ret = mp_from_ubin(s, p, len);
86 : }
87 1613 : free(p);
88 1613 : return ret;
89 : }
90 :
91 : static mp_err
92 139 : setup_blind(mp_int *n, mp_int *b, mp_int *bi)
93 : {
94 8 : mp_err ret;
95 :
96 139 : ret = random_num(b, mp_count_bits(n));
97 139 : if (ret == MP_OKAY) ret = mp_mod(b, n, b);
98 139 : if (ret == MP_OKAY) ret = mp_invmod(b, n, bi);
99 139 : return ret;
100 : }
101 :
102 : static mp_err
103 139 : blind(mp_int *in, mp_int *b, mp_int *e, mp_int *n)
104 : {
105 8 : mp_err ret;
106 8 : mp_int t1;
107 :
108 139 : ret = mp_init(&t1);
109 : /* in' = (in * b^e) mod n */
110 139 : if (ret == MP_OKAY) ret = mp_exptmod(b, e, n, &t1);
111 139 : if (ret == MP_OKAY) ret = mp_mul(&t1, in, in);
112 139 : if (ret == MP_OKAY) ret = mp_mod(in, n, in);
113 139 : mp_clear(&t1);
114 139 : return ret;
115 : }
116 :
117 : static mp_err
118 139 : unblind(mp_int *out, mp_int *bi, mp_int *n)
119 : {
120 8 : mp_err ret;
121 :
122 : /* out' = (out * 1/b) mod n */
123 139 : ret = mp_mul(out, bi, out);
124 139 : if (ret == MP_OKAY) ret = mp_mod(out, n, out);
125 139 : return ret;
126 : }
127 :
128 : static mp_err
129 139 : ltm_rsa_private_calculate(mp_int * in, mp_int * p, mp_int * q,
130 : mp_int * dmp1, mp_int * dmq1, mp_int * iqmp,
131 : mp_int * out)
132 : {
133 8 : mp_err ret;
134 8 : mp_int vp, vq, u;
135 139 : int where HEIMDAL_UNUSED_ATTRIBUTE = 0;
136 :
137 139 : FIRST(mp_init_multi(&vp, &vq, &u, NULL));
138 :
139 : /* vq = c ^ (d mod (q - 1)) mod q */
140 : /* vp = c ^ (d mod (p - 1)) mod p */
141 139 : THEN_MP(mp_mod(in, p, &u));
142 139 : THEN_MP(mp_exptmod(&u, dmp1, p, &vp));
143 139 : THEN_MP(mp_mod(in, q, &u));
144 139 : THEN_MP(mp_exptmod(&u, dmq1, q, &vq));
145 :
146 : /* C2 = 1/q mod p (iqmp) */
147 : /* u = (vp - vq)C2 mod p. */
148 139 : THEN_MP(mp_sub(&vp, &vq, &u));
149 139 : THEN_IF_MP(mp_isneg(&u), mp_add(&u, p, &u));
150 139 : THEN_MP(mp_mul(&u, iqmp, &u));
151 139 : THEN_MP(mp_mod(&u, p, &u));
152 :
153 : /* c ^ d mod n = vq + u q */
154 139 : THEN_MP(mp_mul(&u, q, &u));
155 139 : THEN_MP(mp_add(&u, &vq, out));
156 :
157 139 : mp_clear_multi(&vp, &vq, &u, NULL);
158 139 : return ret;
159 : }
160 :
161 : /*
162 : *
163 : */
164 :
165 : static int
166 21 : ltm_rsa_public_encrypt(int flen, const unsigned char* from,
167 : unsigned char* to, RSA* rsa, int padding)
168 : {
169 21 : unsigned char *p = NULL, *p0 = NULL;
170 21 : size_t size, ssize = 0, padlen;
171 0 : mp_int enc, dec, n, e;
172 0 : mp_err ret;
173 21 : int where = __LINE__;
174 :
175 21 : if (padding != RSA_PKCS1_PADDING)
176 0 : return -1;
177 :
178 21 : FIRST(mp_init_multi(&n, &e, &enc, &dec, NULL));
179 :
180 21 : size = RSA_size(rsa);
181 21 : THEN_IF_MP((size < RSA_PKCS1_PADDING_SIZE ||
182 : size - RSA_PKCS1_PADDING_SIZE < flen),
183 : MP_ERR);
184 21 : THEN_MP(BN2mpz(&n, rsa->n));
185 21 : THEN_MP(BN2mpz(&e, rsa->e));
186 21 : THEN_IF_MP((mp_cmp_d(&e, 3) == MP_LT), MP_ERR);
187 21 : THEN_ALLOC((p = p0 = malloc(size - 1)));
188 :
189 21 : if (ret == MP_OKAY) {
190 21 : padlen = size - flen - 3;
191 21 : *p++ = 2;
192 : }
193 21 : THEN_IF_MP((RAND_bytes(p, padlen) != 1), MP_ERR);
194 :
195 21 : if (ret == MP_OKAY) {
196 4694 : while (padlen) {
197 4673 : if (*p == 0)
198 12 : *p = 1;
199 4673 : padlen--;
200 4673 : p++;
201 : }
202 21 : *p++ = 0;
203 21 : memcpy(p, from, flen);
204 21 : p += flen;
205 21 : assert((p - p0) == size - 1);
206 : }
207 :
208 21 : THEN_MP(mp_from_ubin(&dec, p0, size - 1));
209 21 : THEN_MP(mp_exptmod(&dec, &e, &n, &enc));
210 21 : THEN_VOID(ssize = mp_ubin_size(&enc));
211 21 : THEN_VOID(assert(size >= ssize));
212 21 : THEN_MP(mp_to_ubin(&enc, to, SIZE_MAX, NULL));
213 21 : THEN_VOID(size = ssize);
214 :
215 21 : mp_clear_multi(&dec, &e, &n, NULL);
216 21 : mp_clear(&enc);
217 21 : free(p0);
218 21 : return ret == MP_OKAY ? size : -where;
219 : }
220 :
221 : static int
222 299 : ltm_rsa_public_decrypt(int flen, const unsigned char* from,
223 : unsigned char* to, RSA* rsa, int padding)
224 : {
225 299 : unsigned char *p = NULL;
226 8 : mp_err ret;
227 299 : size_t size = 0;
228 8 : mp_int s, us, n, e;
229 299 : int where = __LINE__;
230 :
231 299 : if (padding != RSA_PKCS1_PADDING)
232 0 : return -1;
233 :
234 299 : if (flen > RSA_size(rsa))
235 0 : return -2;
236 :
237 299 : FIRST(mp_init_multi(&e, &n, &s, &us, NULL));
238 299 : THEN_MP(BN2mpz(&n, rsa->n));
239 299 : THEN_MP(BN2mpz(&e, rsa->e));
240 299 : THEN_MP((mp_cmp_d(&e, 3) == MP_LT) ? MP_ERR : MP_OKAY);
241 299 : THEN_MP(mp_from_ubin(&s, rk_UNCONST(from), (size_t)flen));
242 299 : THEN_MP((mp_cmp(&s, &n) >= 0) ? MP_ERR : MP_OKAY);
243 299 : THEN_MP(mp_exptmod(&s, &e, &n, &us));
244 :
245 299 : THEN_VOID(p = to);
246 299 : THEN_VOID(size = mp_ubin_size(&us));
247 299 : THEN_VOID(assert(size <= RSA_size(rsa)));
248 299 : THEN_MP(mp_to_ubin(&us, p, SIZE_MAX, NULL));
249 :
250 299 : mp_clear_multi(&e, &n, &s, NULL);
251 299 : mp_clear(&us);
252 :
253 299 : if (ret != MP_OKAY || size == 0)
254 0 : return -where;
255 :
256 : /* head zero was skipped by mp_to_unsigned_bin */
257 299 : if (*p == 0)
258 0 : return -where;
259 299 : if (*p != 1)
260 0 : return -(where + 1);
261 299 : size--; p++;
262 196347 : while (size && *p == 0xff) {
263 196048 : size--; p++;
264 : }
265 299 : if (size == 0 || *p != 0)
266 0 : return -(where + 2);
267 299 : size--; p++;
268 299 : memmove(to, p, size);
269 299 : return size;
270 : }
271 :
272 : static int
273 139 : ltm_rsa_private_encrypt(int flen, const unsigned char* from,
274 : unsigned char* to, RSA* rsa, int padding)
275 : {
276 139 : unsigned char *ptr = NULL, *ptr0 = NULL;
277 8 : mp_err ret;
278 8 : mp_int in, out, n, e;
279 8 : mp_int bi, b;
280 8 : size_t size;
281 139 : int blinding = (rsa->flags & RSA_FLAG_NO_BLINDING) == 0;
282 139 : int do_unblind = 0;
283 139 : int where = __LINE__;
284 :
285 139 : if (padding != RSA_PKCS1_PADDING)
286 0 : return -1;
287 :
288 139 : FIRST(mp_init_multi(&e, &n, &in, &out, &b, &bi, NULL));
289 :
290 139 : size = RSA_size(rsa);
291 139 : if (size < RSA_PKCS1_PADDING_SIZE || size - RSA_PKCS1_PADDING_SIZE < flen)
292 0 : return -2;
293 :
294 139 : THEN_ALLOC((ptr0 = ptr = malloc(size)));
295 139 : if (ret == MP_OKAY) {
296 139 : *ptr++ = 0;
297 139 : *ptr++ = 1;
298 139 : memset(ptr, 0xff, size - flen - 3);
299 139 : ptr += size - flen - 3;
300 139 : *ptr++ = 0;
301 139 : memcpy(ptr, from, flen);
302 139 : ptr += flen;
303 139 : assert((ptr - ptr0) == size);
304 : }
305 :
306 139 : THEN_MP(BN2mpz(&n, rsa->n));
307 139 : THEN_MP(BN2mpz(&e, rsa->e));
308 139 : THEN_IF_MP((mp_cmp_d(&e, 3) == MP_LT), MP_ERR);
309 139 : THEN_MP(mp_from_ubin(&in, ptr0, size));
310 139 : free(ptr0);
311 :
312 139 : THEN_IF_MP((mp_isneg(&in) || mp_cmp(&in, &n) >= 0), MP_ERR);
313 :
314 139 : if (blinding) {
315 139 : THEN_MP(setup_blind(&n, &b, &bi));
316 139 : THEN_MP(blind(&in, &b, &e, &n));
317 131 : do_unblind = 1;
318 : }
319 :
320 139 : if (ret == MP_OKAY && rsa->p && rsa->q && rsa->dmp1 && rsa->dmq1 &&
321 278 : rsa->iqmp) {
322 8 : mp_int p, q, dmp1, dmq1, iqmp;
323 :
324 139 : FIRST(mp_init_multi(&p, &q, &dmp1, &dmq1, &iqmp, NULL));
325 139 : THEN_MP(BN2mpz(&p, rsa->p));
326 139 : THEN_MP(BN2mpz(&q, rsa->q));
327 139 : THEN_MP(BN2mpz(&dmp1, rsa->dmp1));
328 139 : THEN_MP(BN2mpz(&dmq1, rsa->dmq1));
329 139 : THEN_MP(BN2mpz(&iqmp, rsa->iqmp));
330 139 : THEN_MP(ltm_rsa_private_calculate(&in, &p, &q, &dmp1, &dmq1, &iqmp,
331 : &out));
332 139 : mp_clear_multi(&p, &q, &dmp1, &dmq1, &iqmp, NULL);
333 139 : if (ret != MP_OKAY) goto out;
334 0 : } else if (ret == MP_OKAY) {
335 0 : mp_int d;
336 :
337 0 : THEN_MP(BN2mpz(&d, rsa->d));
338 0 : THEN_MP(mp_exptmod(&in, &d, &n, &out));
339 0 : mp_clear(&d);
340 0 : if (ret != MP_OKAY) goto out;
341 : }
342 :
343 139 : if (do_unblind)
344 139 : THEN_MP(unblind(&out, &bi, &n));
345 :
346 139 : if (ret == MP_OKAY && size > 0) {
347 8 : size_t ssize;
348 :
349 139 : ssize = mp_ubin_size(&out);
350 139 : assert(size >= ssize);
351 139 : THEN_MP(mp_to_ubin(&out, to, SIZE_MAX, NULL));
352 139 : size = ssize;
353 : }
354 :
355 0 : out:
356 139 : mp_clear_multi(&e, &n, &in, &out, &b, &bi, NULL);
357 139 : return ret == MP_OKAY ? size : -where;
358 : }
359 :
360 : static int
361 0 : ltm_rsa_private_decrypt(int flen, const unsigned char* from,
362 : unsigned char* to, RSA* rsa, int padding)
363 : {
364 0 : unsigned char *ptr;
365 0 : size_t size;
366 0 : mp_err ret;
367 0 : mp_int in, out, n, e, b, bi;
368 0 : int blinding = (rsa->flags & RSA_FLAG_NO_BLINDING) == 0;
369 0 : int do_unblind = 0;
370 0 : int where = __LINE__;
371 :
372 0 : if (padding != RSA_PKCS1_PADDING)
373 0 : return -1;
374 :
375 0 : size = RSA_size(rsa);
376 0 : if (flen > size)
377 0 : return -2;
378 :
379 0 : FIRST(mp_init_multi(&in, &n, &e, &out, &b, &bi, NULL));
380 0 : THEN_MP(BN2mpz(&n, rsa->n));
381 0 : THEN_MP(BN2mpz(&e, rsa->e));
382 0 : THEN_IF_MP((mp_cmp_d(&e, 3) == MP_LT), MP_ERR);
383 0 : THEN_MP(mp_from_ubin(&in, rk_UNCONST(from), flen));
384 0 : THEN_IF_MP((mp_isneg(&in) || mp_cmp(&in, &n) >= 0), MP_ERR);
385 :
386 0 : if (blinding) {
387 0 : THEN_MP(setup_blind(&n, &b, &bi));
388 0 : THEN_MP(blind(&in, &b, &e, &n));
389 0 : do_unblind = 1;
390 : }
391 :
392 0 : if (ret == MP_OKAY && rsa->p && rsa->q && rsa->dmp1 && rsa->dmq1 &&
393 0 : rsa->iqmp) {
394 0 : mp_int p, q, dmp1, dmq1, iqmp;
395 :
396 0 : THEN_MP(mp_init_multi(&p, &q, &dmp1, &dmq1, &iqmp, NULL));
397 0 : THEN_MP(BN2mpz(&p, rsa->p));
398 0 : THEN_MP(BN2mpz(&q, rsa->q));
399 0 : THEN_MP(BN2mpz(&dmp1, rsa->dmp1));
400 0 : THEN_MP(BN2mpz(&dmq1, rsa->dmq1));
401 0 : THEN_MP(BN2mpz(&iqmp, rsa->iqmp));
402 0 : THEN_MP(ltm_rsa_private_calculate(&in, &p, &q, &dmp1, &dmq1, &iqmp, &out));
403 0 : mp_clear_multi(&p, &q, &dmp1, &dmq1, &iqmp, NULL);
404 0 : if (ret != MP_OKAY) goto out;
405 0 : } else if (ret == MP_OKAY) {
406 0 : mp_int d;
407 :
408 0 : THEN_IF_MP((mp_isneg(&in) || mp_cmp(&in, &n) >= 0), MP_ERR);
409 0 : THEN_MP(BN2mpz(&d, rsa->d));
410 0 : THEN_MP(mp_exptmod(&in, &d, &n, &out));
411 0 : mp_clear(&d);
412 0 : if (ret != MP_OKAY) goto out;
413 : }
414 :
415 0 : if (do_unblind)
416 0 : THEN_MP(unblind(&out, &bi, &n));
417 :
418 0 : if (ret == MP_OKAY) {
419 0 : size_t ssize;
420 :
421 0 : ptr = to;
422 0 : ssize = mp_ubin_size(&out);
423 0 : assert(size >= ssize);
424 0 : ret = mp_to_ubin(&out, ptr, SIZE_MAX, NULL);
425 0 : if (ret != MP_OKAY) goto out;
426 0 : size = ssize;
427 :
428 : /* head zero was skipped by mp_int_to_unsigned */
429 0 : if (*ptr != 2) {
430 0 : where = __LINE__;
431 0 : goto out;
432 : }
433 0 : size--; ptr++;
434 0 : while (size && *ptr != 0) {
435 0 : size--; ptr++;
436 : }
437 0 : if (size == 0) {
438 0 : where = __LINE__;
439 0 : goto out;
440 : }
441 0 : size--; ptr++;
442 0 : memmove(to, ptr, size);
443 : }
444 :
445 0 : out:
446 0 : mp_clear_multi(&e, &n, &in, &out, &b, &bi, NULL);
447 0 : return (ret == MP_OKAY) ? size : -where;
448 : }
449 :
450 : static BIGNUM *
451 0 : mpz2BN(mp_int *s)
452 : {
453 0 : size_t size;
454 0 : BIGNUM *bn;
455 0 : mp_err ret;
456 0 : void *p;
457 :
458 0 : size = mp_ubin_size(s);
459 0 : if (size == 0)
460 0 : return NULL;
461 :
462 0 : p = malloc(size);
463 0 : if (p == NULL)
464 0 : return NULL;
465 :
466 0 : ret = mp_to_ubin(s, p, SIZE_MAX, NULL);
467 0 : if (ret == MP_OKAY)
468 0 : bn = BN_bin2bn(p, size, NULL);
469 0 : free(p);
470 0 : return (ret == MP_OKAY) ? bn : NULL;
471 : }
472 :
473 : enum gen_pq_type { GEN_P, GEN_Q };
474 :
475 : static int
476 0 : gen_p(int bits, enum gen_pq_type pq_type, uint8_t nibble_pair, mp_int *p, mp_int *e, BN_GENCB *cb)
477 : {
478 0 : unsigned char *buf = NULL;
479 0 : mp_bool res;
480 0 : mp_err ret = MP_MEM;
481 0 : mp_int t1, t2;
482 0 : size_t len = (bits + 7) / 8;
483 0 : int trials = mp_prime_rabin_miller_trials(bits);
484 0 : int counter = 0;
485 0 : int where HEIMDAL_UNUSED_ATTRIBUTE = 0;
486 :
487 :
488 0 : FIRST(mp_init_multi(&t1, &t2, NULL));
489 0 : if (ret == MP_OKAY && (buf = malloc(len))) do {
490 0 : BN_GENCB_call(cb, 2, counter++);
491 : /* random bytes */
492 0 : ret = (RAND_bytes(buf, len) == 1) ? MP_OKAY : MP_ERR;
493 :
494 : /* make it odd */
495 0 : buf[len - 1] |= 1;
496 :
497 : /* ensure the high nibble of the product is at least 128 */
498 0 : if (pq_type == GEN_P)
499 0 : buf[0] = (nibble_pair & 0xf0) | (buf[0] & 0x0f);
500 : else
501 0 : buf[0] = ((nibble_pair & 0x0f) << 4) | (buf[0] & 0x0f);
502 :
503 : /* load number */
504 0 : THEN_MP(mp_from_ubin(p, buf, len));
505 :
506 : /* test primality; repeat if not */
507 0 : THEN_MP(mp_prime_is_prime(p, trials, &res));
508 0 : if (ret == MP_OKAY && res == MP_NO) continue;
509 :
510 : /* check gcd(p - 1, e) == 1 */
511 0 : THEN_MP(mp_sub_d(p, 1, &t1));
512 0 : THEN_MP(mp_gcd(&t1, e, &t2));
513 0 : } while (ret == MP_OKAY && mp_cmp_d(&t2, 1) != MP_EQ);
514 :
515 0 : mp_clear_multi(&t1, &t2, NULL);
516 0 : free(buf);
517 0 : return ret;
518 : }
519 :
520 : static uint8_t pq_high_nibble_pairs[] = {
521 : 0x9f, 0xad, 0xae, 0xaf, 0xbc, 0xbd, 0xbe, 0xbf, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
522 : 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf9,
523 : 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
524 : };
525 :
526 : static int
527 0 : ltm_rsa_generate_key(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb)
528 : {
529 0 : mp_int el, p, q, n, d, dmp1, dmq1, iqmp, t1, t2, t3;
530 0 : mp_err ret;
531 0 : uint8_t high_nibbles = 0;
532 0 : int bitsp;
533 0 : int where = __LINE__;
534 :
535 0 : if (bits < 789)
536 0 : return -1;
537 :
538 0 : bitsp = (bits + 1) / 2;
539 :
540 0 : FIRST(mp_init_multi(&el, &p, &q, &n, &d,
541 : &dmp1, &dmq1, &iqmp,
542 : &t1, &t2, &t3, NULL));
543 0 : THEN_MP(BN2mpz(&el, e));
544 :
545 : /*
546 : * randomly pick a pair of high nibbles for p and q to ensure the product's
547 : * high nibble is at least 128
548 : */
549 0 : if (ret == MP_OKAY)
550 0 : ret = (RAND_bytes(&high_nibbles, 1) == 1) ? MP_OKAY : MP_ERR;
551 0 : high_nibbles %= sizeof(pq_high_nibble_pairs);
552 0 : high_nibbles = pq_high_nibble_pairs[high_nibbles];
553 :
554 : /* generate p and q so that p != q and bits(pq) ~ bits */
555 0 : THEN_MP(gen_p(bitsp, GEN_P, high_nibbles, &p, &el, cb));
556 0 : BN_GENCB_call(cb, 3, 0);
557 0 : THEN_MP(gen_p(bitsp, GEN_Q, high_nibbles, &q, &el, cb));
558 :
559 : /* make p > q */
560 0 : if (mp_cmp(&p, &q) < 0) {
561 0 : mp_int c;
562 0 : c = p;
563 0 : p = q;
564 0 : q = c;
565 : }
566 :
567 0 : BN_GENCB_call(cb, 3, 1);
568 :
569 : /* calculate n, n = p * q */
570 0 : THEN_MP(mp_mul(&p, &q, &n));
571 :
572 : /* calculate d, d = 1/e mod (p - 1)(q - 1) */
573 0 : THEN_MP(mp_sub_d(&p, 1, &t1));
574 0 : THEN_MP(mp_sub_d(&q, 1, &t2));
575 0 : THEN_MP(mp_mul(&t1, &t2, &t3));
576 0 : THEN_MP(mp_invmod(&el, &t3, &d));
577 :
578 : /* calculate dmp1 dmp1 = d mod (p-1) */
579 0 : THEN_MP(mp_mod(&d, &t1, &dmp1));
580 : /* calculate dmq1 dmq1 = d mod (q-1) */
581 0 : THEN_MP(mp_mod(&d, &t2, &dmq1));
582 : /* calculate iqmp iqmp = 1/q mod p */
583 0 : THEN_MP(mp_invmod(&q, &p, &iqmp));
584 :
585 : /* fill in RSA key */
586 :
587 0 : if (ret == MP_OKAY) {
588 0 : rsa->e = mpz2BN(&el);
589 0 : rsa->p = mpz2BN(&p);
590 0 : rsa->q = mpz2BN(&q);
591 0 : rsa->n = mpz2BN(&n);
592 0 : rsa->d = mpz2BN(&d);
593 0 : rsa->dmp1 = mpz2BN(&dmp1);
594 0 : rsa->dmq1 = mpz2BN(&dmq1);
595 0 : rsa->iqmp = mpz2BN(&iqmp);
596 : }
597 :
598 0 : mp_clear_multi(&el, &p, &q, &n, &d,
599 : &dmp1, &dmq1, &iqmp,
600 : &t1, &t2, &t3, NULL);
601 0 : return (ret == MP_OKAY) ? 1 : -where;
602 : }
603 :
604 : static int
605 394 : ltm_rsa_init(RSA *rsa)
606 : {
607 394 : return 1;
608 : }
609 :
610 : static int
611 340 : ltm_rsa_finish(RSA *rsa)
612 : {
613 340 : return 1;
614 : }
615 :
616 : const RSA_METHOD hc_rsa_ltm_method = {
617 : "hcrypto ltm RSA",
618 : ltm_rsa_public_encrypt,
619 : ltm_rsa_public_decrypt,
620 : ltm_rsa_private_encrypt,
621 : ltm_rsa_private_decrypt,
622 : NULL,
623 : NULL,
624 : ltm_rsa_init,
625 : ltm_rsa_finish,
626 : 0,
627 : NULL,
628 : NULL,
629 : NULL,
630 : ltm_rsa_generate_key
631 : };
632 :
633 : const RSA_METHOD *
634 0 : RSA_ltm_method(void)
635 : {
636 0 : return &hc_rsa_ltm_method;
637 : }
|