summaryrefslogtreecommitdiffstats
path: root/3rd_party/libsrp6a-sha512/t_math.c
diff options
context:
space:
mode:
Diffstat (limited to '3rd_party/libsrp6a-sha512/t_math.c')
-rw-r--r--3rd_party/libsrp6a-sha512/t_math.c1008
1 files changed, 1008 insertions, 0 deletions
diff --git a/3rd_party/libsrp6a-sha512/t_math.c b/3rd_party/libsrp6a-sha512/t_math.c
new file mode 100644
index 0000000..88ae12f
--- /dev/null
+++ b/3rd_party/libsrp6a-sha512/t_math.c
@@ -0,0 +1,1008 @@
1/*
2 * Copyright (c) 1997-2007 The Stanford SRP Authentication Project
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
18 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
19 *
20 * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
21 * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
22 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
23 * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
24 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 *
26 * Redistributions in source or binary form must retain an intact copy
27 * of this copyright notice.
28 */
29
30#include <stdio.h>
31#include <sys/types.h>
32
33#include "config.h"
34
35#ifdef OPENSSL
36# include "openssl/opensslv.h"
37# include "openssl/bn.h"
38typedef BIGNUM * BigInteger;
39typedef BN_CTX * BigIntegerCtx;
40typedef BN_MONT_CTX * BigIntegerModAccel;
41#include <limits.h>
42# ifdef OPENSSL_ENGINE
43# include "openssl/engine.h"
44static ENGINE * default_engine = NULL;
45# endif /* OPENSSL_ENGINE */
46typedef int (*modexp_meth)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
47 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *mctx);
48static modexp_meth default_modexp = NULL;
49#elif defined(CRYPTOLIB)
50# include "libcrypt.h"
51typedef BigInt BigInteger;
52typedef void * BigIntegerCtx;
53typedef void * BigIntegerModAccel;
54#elif defined(GNU_MP)
55# include "gmp.h"
56typedef MP_INT * BigInteger;
57typedef void * BigIntegerCtx;
58typedef void * BigIntegerModAccel;
59# if __GNU_MP_VERSION >= 4 || (__GNU_MP_VERSION == 4 && __GNU_MP_VERSION_MINOR >= 1)
60/* GMP 4.1 and up has fast import/export routines for integer conversion */
61# define GMP_IMPEXP 1
62# endif
63#elif defined(TOMMATH)
64# ifdef TOMCRYPT
65 /* as of v0.96 */
66# include "ltc_tommath.h"
67# else
68# include "tommath.h"
69# endif
70typedef mp_int * BigInteger;
71typedef void * BigIntegerCtx;
72typedef void * BigIntegerModAccel;
73#elif defined(GCRYPT)
74# include "gcrypt.h"
75typedef gcry_mpi_t BigInteger;
76typedef void * BigIntegerCtx;
77typedef void * BigIntegerModAccel;
78#elif defined(MPI)
79# include "mpi.h"
80typedef mp_int * BigInteger;
81typedef void * BigIntegerCtx;
82typedef void * BigIntegerModAccel;
83#elif defined(MBEDTLS)
84#include <mbedtls/bignum.h>
85#include <mbedtls/error.h>
86typedef mbedtls_mpi* BigInteger;
87typedef void * BigIntegerCtx;
88typedef void * BigIntegerModAccel;
89#else
90# error "no math library specified"
91#endif
92#define MATH_PRIV
93
94#include "t_defines.h"
95#include "t_pwd.h"
96#include "srp_aux.h"
97
98/* Math library interface stubs */
99
100BigInteger
101BigIntegerFromInt(n)
102 unsigned int n;
103{
104#ifdef OPENSSL
105 BIGNUM * a = BN_new();
106 if(a)
107 BN_set_word(a, n);
108 return a;
109#elif defined(CRYPTOLIB)
110 return bigInit(n);
111#elif defined(GNU_MP)
112 BigInteger rv = (BigInteger) malloc(sizeof(MP_INT));
113 if(rv)
114 mpz_init_set_ui(rv, n);
115 return rv;
116#elif defined(GCRYPT)
117 BigInteger rv = gcry_mpi_new(32);
118 gcry_mpi_set_ui(rv, n);
119 return rv;
120#elif defined(MPI) || defined(TOMMATH)
121 BigInteger rv = (BigInteger) malloc(sizeof(mp_int));
122 if(rv) {
123 mp_init(rv);
124 mp_set_int(rv, n);
125 }
126 return rv;
127#elif defined(MBEDTLS)
128 mbedtls_mpi* a = (mbedtls_mpi*)malloc(sizeof(mbedtls_mpi));
129 if (a) {
130 mbedtls_mpi_init(a);
131 mbedtls_mpi_lset(a, n);
132 }
133 return a;
134#endif
135}
136
137BigInteger
138BigIntegerFromBytes(bytes, length)
139 const unsigned char * bytes;
140 int length;
141{
142#ifdef OPENSSL
143 BIGNUM * a = BN_new();
144 BN_bin2bn(bytes, length, a);
145 return a;
146#elif defined(CRYPTOLIB)
147 BigInteger rv, t;
148 int i, n;
149
150 rv = bigInit(0);
151 if(rv == NULL)
152 return rv;
153 if(length % 4 == 0)
154 RSA_bufToBig(bytes, length, rv);
155 else { /* Wouldn't need this if cryptolib behaved better */
156 i = length & 0x3;
157 if(length > i)
158 RSA_bufToBig(bytes + i, length - i, rv);
159 for(n = 0; i > 0; --i)
160 n = (n << 8) | *bytes++;
161 t = bigInit(n);
162 bigLeftShift(t, (length & ~0x3) << 3, t);
163 bigAdd(rv, t, rv);
164 freeBignum(t);
165 }
166 return rv;
167#elif defined(GNU_MP)
168 BigInteger rv = (BigInteger) malloc(sizeof(MP_INT));
169
170# ifdef GMP_IMPEXP
171 if(rv) {
172 mpz_init(rv);
173 mpz_import(rv, length, 1, 1, 1, 0, bytes);
174 }
175# else
176 cstr * hexbuf = cstr_new();
177
178 if(hexbuf) {
179 if(rv)
180 mpz_init_set_str(rv, t_tohexcstr(hexbuf, bytes, length), 16);
181 cstr_clear_free(hexbuf);
182 }
183# endif /* GMP_IMPEXP */
184
185 return rv;
186#elif defined(GCRYPT)
187 BigInteger rv;
188 gcry_mpi_scan(&rv, GCRYMPI_FMT_USG, bytes, length, NULL);
189 return rv;
190#elif defined(MPI) || defined(TOMMATH)
191 BigInteger rv = (BigInteger) malloc(sizeof(mp_int));
192 if(rv) {
193 mp_init(rv);
194 mp_read_unsigned_bin(rv, (unsigned char *)bytes, length);
195 }
196 return rv;
197#elif defined(MBEDTLS)
198 mbedtls_mpi* a = (mbedtls_mpi*)malloc(sizeof(mbedtls_mpi));
199 if (a) {
200 mbedtls_mpi_init(a);
201 mbedtls_mpi_read_binary(a, bytes, length);
202 }
203 return a;
204#endif
205}
206
207int
208BigIntegerToBytes(src, dest, destlen)
209 BigInteger src;
210 unsigned char * dest;
211 int destlen;
212{
213#ifdef OPENSSL
214 return BN_bn2bin(src, dest);
215#elif defined(CRYPTOLIB)
216 int i, j;
217 cstr * rawbuf;
218
219 trim(src);
220 i = bigBytes(src);
221 j = (bigBits(src) + 7) / 8;
222 if(i == j)
223 RSA_bigToBuf(src, i, dest);
224 else { /* Wouldn't need this if cryptolib behaved better */
225 rawbuf = cstr_new();
226 cstr_set_length(rawbuf, i);
227 RSA_bigToBuf(src, i, rawbuf->data);
228 memcpy(dest, rawbuf->data + (i-j), j);
229 cstr_clear_free(rawbuf);
230 }
231 return j;
232#elif defined(GNU_MP)
233 size_t r = 0;
234# ifdef GMP_IMPEXP
235 mpz_export(dest, &r, 1, 1, 1, 0, src);
236# else
237 cstr * hexbuf = cstr_new();
238
239 if(hexbuf) {
240 cstr_set_length(hexbuf, mpz_sizeinbase(src, 16) + 1);
241 mpz_get_str(hexbuf->data, 16, src);
242 r = t_fromhex(dest, hexbuf->data);
243 cstr_clear_free(hexbuf);
244 }
245# endif
246 return r;
247#elif defined(GCRYPT)
248 size_t r = 0;
249 gcry_mpi_print(GCRYMPI_FMT_USG, dest, destlen, &r, src);
250 return r;
251#elif defined(MPI) || defined(TOMMATH)
252 mp_to_unsigned_bin(src, dest);
253 return mp_unsigned_bin_size(src);
254#elif defined(MBEDTLS)
255 size_t r = mbedtls_mpi_size(src);
256 mbedtls_mpi_write_binary(src, dest, r);
257 return r;
258#endif
259}
260
261BigIntegerResult
262BigIntegerToCstr(BigInteger x, cstr * out)
263{
264 int n = BigIntegerByteLen(x);
265 if(cstr_set_length(out, n) < 0)
266 return BIG_INTEGER_ERROR;
267 if(cstr_set_length(out, BigIntegerToBytes(x, (unsigned char*)out->data, n)) < 0)
268 return BIG_INTEGER_ERROR;
269 return BIG_INTEGER_SUCCESS;
270}
271
272BigIntegerResult
273BigIntegerToCstrEx(BigInteger x, cstr * out, int len)
274{
275 int n;
276 if(cstr_set_length(out, len) < 0)
277 return BIG_INTEGER_ERROR;
278#if defined(MBEDTLS)
279 /* mbedtls will prefix the output with zeros if the buffer is larger */
280 mbedtls_mpi_write_binary(x, (unsigned char*)out->data, len);
281#else
282 n = BigIntegerToBytes(x, (unsigned char*)out->data, len);
283 if(n < len) {
284 memmove(out->data + (len - n), out->data, n);
285 memset(out->data, 0, len - n);
286 }
287#endif
288 return BIG_INTEGER_SUCCESS;
289}
290
291BigIntegerResult
292BigIntegerToHex(src, dest, destlen)
293 BigInteger src;
294 char * dest;
295 int destlen;
296{
297#ifdef OPENSSL
298 strncpy(dest, BN_bn2hex(src), destlen);
299#elif defined(CRYPTOLIB)
300 trim(src);
301 bigsprint(src, dest);
302#elif defined(GNU_MP)
303 mpz_get_str(dest, 16, src);
304#elif defined(GCRYPT)
305 gcry_mpi_print(GCRYMPI_FMT_HEX, dest, destlen, NULL, src);
306#elif defined(MPI) || defined(TOMMATH)
307 mp_toradix(src, dest, 16);
308#elif defined(MBEDTLS)
309 size_t olen = 0;
310 mbedtls_mpi_write_string(src, 16, dest, destlen, &olen);
311#endif
312 return BIG_INTEGER_SUCCESS;
313}
314
315static char b64table[] =
316 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./";
317
318BigIntegerResult
319BigIntegerToString(src, dest, destlen, radix)
320 BigInteger src;
321 char * dest;
322 int destlen;
323 unsigned int radix;
324{
325 BigInteger t = BigIntegerFromInt(0);
326 char * p = dest;
327 char c;
328
329 *p++ = b64table[BigIntegerModInt(src, radix, NULL)];
330 BigIntegerDivInt(t, src, radix, NULL);
331 while(BigIntegerCmpInt(t, 0) > 0) {
332 *p++ = b64table[BigIntegerModInt(t, radix, NULL)];
333 BigIntegerDivInt(t, t, radix, NULL);
334 }
335 BigIntegerFree(t);
336 *p-- = '\0';
337 /* reverse the string */
338 while(p > dest) {
339 c = *p;
340 *p-- = *dest;
341 *dest++ = c;
342 }
343 return BIG_INTEGER_SUCCESS;
344}
345
346int
347BigIntegerBitLen(b)
348 BigInteger b;
349{
350#ifdef OPENSSL
351 return BN_num_bits(b);
352#elif defined(CRYPTOLIB)
353 return bigBits(b);
354#elif defined(GNU_MP)
355 return mpz_sizeinbase(b, 2);
356#elif defined(GCRYPT)
357 return gcry_mpi_get_nbits(b);
358#elif defined(MPI) || defined(TOMMATH)
359 return mp_count_bits(b);
360#elif defined(MBEDTLS)
361 return (int)mbedtls_mpi_bitlen(b);
362#endif
363}
364
365int
366BigIntegerCmp(c1, c2)
367 BigInteger c1, c2;
368{
369#ifdef OPENSSL
370 return BN_cmp(c1, c2);
371#elif defined(CRYPTOLIB)
372 return bigCompare(c1, c2);
373#elif defined(GNU_MP)
374 return mpz_cmp(c1, c2);
375#elif defined(GCRYPT)
376 return gcry_mpi_cmp(c1, c2);
377#elif defined(MPI) || defined(TOMMATH)
378 return mp_cmp(c1, c2);
379#elif defined(MBEDTLS)
380 return mbedtls_mpi_cmp_mpi(c1, c2);
381#endif
382}
383
384int
385BigIntegerCmpInt(c1, c2)
386 BigInteger c1;
387 unsigned int c2;
388{
389#ifdef OPENSSL
390 BigInteger bc2 = BigIntegerFromInt(c2);
391 int rv = BigIntegerCmp(c1, bc2);
392 BigIntegerFree(bc2);
393 return rv;
394#elif defined(CRYPTOLIB)
395 BigInteger t;
396 int rv;
397
398 t = bigInit(c2);
399 rv = bigCompare(c1, t);
400 freeBignum(t);
401 return rv;
402#elif defined(GNU_MP)
403 return mpz_cmp_ui(c1, c2);
404#elif defined(TOMMATH)
405 return mp_cmp_d(c1, c2);
406#elif defined(GCRYPT)
407 return gcry_mpi_cmp_ui(c1, c2);
408#elif defined(MPI)
409 return mp_cmp_int(c1, c2);
410#elif defined(MBEDTLS)
411 return mbedtls_mpi_cmp_int(c1, c2);
412#endif
413}
414
415BigIntegerResult
416BigIntegerLShift(result, x, bits)
417 BigInteger result, x;
418 unsigned int bits;
419{
420#ifdef OPENSSL
421 BN_lshift(result, x, bits);
422#elif defined(CRYPTOLIB)
423 bigLeftShift(x, bits, result);
424#elif defined(GNU_MP)
425 mpz_mul_2exp(result, x, bits);
426#elif defined(GCRYPT)
427 gcry_mpi_mul_2exp(result, x, bits);
428#elif defined(MPI) || defined(TOMMATH)
429 mp_mul_2d(x, bits, result);
430#elif defined(MBEDTLS)
431 mbedtls_mpi_copy(result, x);
432 mbedtls_mpi_shift_l(result, bits);
433#endif
434 return BIG_INTEGER_SUCCESS;
435}
436
437BigIntegerResult
438BigIntegerAdd(result, a1, a2)
439 BigInteger result, a1, a2;
440{
441#ifdef OPENSSL
442 BN_add(result, a1, a2);
443#elif defined(CRYPTOLIB)
444 bigAdd(a1, a2, result);
445#elif defined(GNU_MP)
446 mpz_add(result, a1, a2);
447#elif defined(GCRYPT)
448 gcry_mpi_add(result, a1, a2);
449#elif defined(MPI) || defined(TOMMATH)
450 mp_add(a1, a2, result);
451#elif defined(MBEDTLS)
452 mbedtls_mpi_add_mpi(result, a1, a2);
453#endif
454 return BIG_INTEGER_SUCCESS;
455}
456
457BigIntegerResult
458BigIntegerAddInt(result, a1, a2)
459 BigInteger result, a1;
460 unsigned int a2;
461{
462#ifdef OPENSSL
463 if(result != a1)
464 BN_copy(result, a1);
465 BN_add_word(result, a2);
466#elif defined(CRYPTOLIB)
467 BigInteger t;
468
469 t = bigInit(a2);
470 bigAdd(a1, t, result);
471 freeBignum(t);
472#elif defined(GNU_MP)
473 mpz_add_ui(result, a1, a2);
474#elif defined(GCRYPT)
475 gcry_mpi_add_ui(result, a1, a2);
476#elif defined(MPI) || defined(TOMMATH)
477 mp_add_d(a1, a2, result);
478#elif defined(MBEDTLS)
479 mbedtls_mpi_add_int(result, a1, a2);
480#endif
481 return BIG_INTEGER_SUCCESS;
482}
483
484BigIntegerResult
485BigIntegerSub(result, s1, s2)
486 BigInteger result, s1, s2;
487{
488#ifdef OPENSSL
489 BN_sub(result, s1, s2);
490#elif defined(CRYPTOLIB)
491 bigSubtract(s1, s2, result);
492#elif defined(GNU_MP)
493 mpz_sub(result, s1, s2);
494#elif defined(GCRYPT)
495 gcry_mpi_sub(result, s1, s2);
496#elif defined(MPI) || defined(TOMMATH)
497 mp_sub(s1, s2, result);
498#elif defined(MBEDTLS)
499 mbedtls_mpi_sub_mpi(result, s1, s2);
500#endif
501 return BIG_INTEGER_SUCCESS;
502}
503
504BigIntegerResult
505BigIntegerSubInt(result, s1, s2)
506 BigInteger result, s1;
507 unsigned int s2;
508{
509#ifdef OPENSSL
510 if(result != s1)
511 BN_copy(result, s1);
512 BN_sub_word(result, s2);
513#elif defined(CRYPTOLIB)
514 BigInteger t;
515
516 t = bigInit(s2);
517 bigSubtract(s1, t, result);
518 freeBignum(t);
519#elif defined(GNU_MP)
520 mpz_sub_ui(result, s1, s2);
521#elif defined(GCRYPT)
522 gcry_mpi_sub_ui(result, s1, s2);
523#elif defined(MPI) || defined(TOMMATH)
524 mp_sub_d(s1, s2, result);
525#elif defined(MBEDTLS)
526 mbedtls_mpi_sub_int(result, s1, s2);
527#endif
528 return BIG_INTEGER_SUCCESS;
529}
530
531BigIntegerResult
532BigIntegerMul(result, m1, m2, c)
533 BigInteger result, m1, m2;
534 BigIntegerCtx c;
535{
536#ifdef OPENSSL
537 BN_CTX * ctx = NULL;
538 if(c == NULL)
539 c = ctx = BN_CTX_new();
540 BN_mul(result, m1, m2, c);
541 if(ctx)
542 BN_CTX_free(ctx);
543#elif defined(CRYPTOLIB)
544 bigMultiply(m1, m2, result);
545#elif defined(GNU_MP)
546 mpz_mul(result, m1, m2);
547#elif defined(GCRYPT)
548 gcry_mpi_mul(result, m1, m2);
549#elif defined(MPI) || defined(TOMMATH)
550 mp_mul(m1, m2, result);
551#elif defined(MBEDTLS)
552 mbedtls_mpi_mul_mpi(result, m1, m2);
553#endif
554 return BIG_INTEGER_SUCCESS;
555}
556
557BigIntegerResult
558BigIntegerMulInt(result, m1, m2, c)
559 BigInteger result, m1;
560 unsigned int m2;
561 BigIntegerCtx c;
562{
563#ifdef OPENSSL
564 if(result != m1)
565 BN_copy(result, m1);
566 BN_mul_word(result, m2);
567#elif defined(CRYPTOLIB)
568 BigInteger t;
569
570 t = bigInit(m2);
571 bigMultiply(m1, t, result);
572 freeBignum(t);
573#elif defined(GNU_MP)
574 mpz_mul_ui(result, m1, m2);
575#elif defined(GCRYPT)
576 gcry_mpi_mul_ui(result, m1, m2);
577#elif defined(MPI) || defined(TOMMATH)
578 mp_mul_d(m1, m2, result);
579#elif defined(MBEDTLS)
580 mbedtls_mpi_mul_int(result, m1, m2);
581#endif
582 return BIG_INTEGER_SUCCESS;
583}
584
585BigIntegerResult
586BigIntegerDivInt(result, d, m, c)
587 BigInteger result, d;
588 unsigned int m;
589 BigIntegerCtx c;
590{
591#ifdef OPENSSL
592 if(result != d)
593 BN_copy(result, d);
594 BN_div_word(result, m);
595#elif defined(CRYPTOLIB)
596 BigInteger t, u, q;
597
598 t = bigInit(m);
599 u = bigInit(0);
600 /* We use a separate variable q because cryptolib breaks if result == d */
601 q = bigInit(0);
602 bigDivide(d, t, q, u);
603 freeBignum(t);
604 freeBignum(u);
605 bigCopy(q, result);
606 freeBignum(q);
607#elif defined(GNU_MP)
608# ifdef GMP2
609 mpz_fdiv_q_ui(result, d, m);
610# else
611 mpz_div_ui(result, d, m);
612# endif
613#elif defined(GCRYPT)
614 BigInteger t = BigIntegerFromInt(m);
615 gcry_mpi_div(result, NULL, d, t, -1);
616 BigIntegerFree(t);
617#elif defined(MPI) || defined(TOMMATH)
618 mp_div_d(d, m, result, NULL);
619#elif defined(MBEDTLS)
620 mbedtls_mpi_div_int(result, NULL, d, m);
621#endif
622 return BIG_INTEGER_SUCCESS;
623}
624
625BigIntegerResult
626BigIntegerMod(result, d, m, c)
627 BigInteger result, d, m;
628 BigIntegerCtx c;
629{
630#ifdef OPENSSL
631 BN_CTX * ctx = NULL;
632 if(c == NULL)
633 c = ctx = BN_CTX_new();
634 BN_mod(result, d, m, c);
635 if(ctx)
636 BN_CTX_free(ctx);
637#elif defined(CRYPTOLIB)
638 bigMod(d, m, result);
639#elif defined(GNU_MP)
640 mpz_mod(result, d, m);
641#elif defined(GCRYPT)
642 gcry_mpi_mod(result, d, m);
643#elif defined(MPI) || defined(TOMMATH)
644 mp_mod(d, m, result);
645#elif defined(MBEDTLS)
646 mbedtls_mpi_mod_mpi(result, d, m);
647#endif
648 return BIG_INTEGER_SUCCESS;
649}
650
651unsigned int
652BigIntegerModInt(d, m, c)
653 BigInteger d;
654 unsigned int m;
655 BigIntegerCtx c;
656{
657#ifdef OPENSSL
658 return BN_mod_word(d, m);
659#elif defined(CRYPTOLIB)
660 BigInteger t, u;
661 unsigned char r[4];
662
663 t = bigInit(m);
664 u = bigInit(0);
665 bigMod(d, t, u);
666 bigToBuf(u, sizeof(r), r);
667 freeBignum(t);
668 freeBignum(u);
669 return r[0] | (r[1] << 8) | (r[2] << 16) | (r[3] << 24);
670#elif defined(GNU_MP)
671 MP_INT result;
672 unsigned int i;
673
674 mpz_init(&result);
675
676/* Define GMP2 if you're using an old gmp.h but want to link against a
677 * newer libgmp.a (e.g. 2.0 or later). */
678
679# ifdef GMP2
680 mpz_fdiv_r_ui(&result, d, m);
681# else
682 mpz_mod_ui(&result, d, m);
683# endif
684 i = mpz_get_ui(&result);
685 mpz_clear(&result);
686 return i;
687#elif defined(GCRYPT)
688 /* TODO: any way to clean this up??? */
689 unsigned char r[4];
690 size_t len, i;
691 unsigned int ret = 0;
692 BigInteger t = BigIntegerFromInt(m);
693 BigInteger a = BigIntegerFromInt(0);
694 gcry_mpi_mod(a, d, t);
695 gcry_mpi_print(GCRYMPI_FMT_USG, r, 4, &len, a);
696 for(i = 0; i < len; ++i)
697 ret = (ret << 8) | r[i];
698 BigIntegerFree(t);
699 BigIntegerFree(a);
700 return ret;
701#elif defined(MPI) || defined(TOMMATH)
702 mp_digit r;
703 mp_mod_d(d, m, &r);
704 return r;
705#elif defined(MBEDTLS)
706 mbedtls_mpi_uint r = 0;
707 mbedtls_mpi_mod_int(&r, d, m);
708 return r;
709#endif
710}
711
712BigIntegerResult
713BigIntegerModMul(r, m1, m2, modulus, c)
714 BigInteger r, m1, m2, modulus;
715 BigIntegerCtx c;
716{
717#ifdef OPENSSL
718 BN_CTX * ctx = NULL;
719 if(c == NULL)
720 c = ctx = BN_CTX_new();
721 BN_mod_mul(r, m1, m2, modulus, c);
722 if(ctx)
723 BN_CTX_free(ctx);
724#elif defined(CRYPTOLIB)
725 bigMultiply(m1, m2, r);
726 bigMod(r, modulus, r);
727#elif defined(GNU_MP)
728 mpz_mul(r, m1, m2);
729 mpz_mod(r, r, modulus);
730#elif defined(GCRYPT)
731 gcry_mpi_mulm(r, m1, m2, modulus);
732#elif defined(MPI) || defined(TOMMATH)
733 mp_mulmod(m1, m2, modulus, r);
734#elif defined(MBEDTLS)
735 mbedtls_mpi d;
736 mbedtls_mpi_init(&d);
737 mbedtls_mpi_mul_mpi(&d, m1, m2);
738 mbedtls_mpi_mod_mpi(r, &d, modulus);
739 mbedtls_mpi_free(&d);
740#endif
741 return BIG_INTEGER_SUCCESS;
742}
743
744BigIntegerResult
745BigIntegerModExp(r, b, e, m, c, a)
746 BigInteger r, b, e, m;
747 BigIntegerCtx c;
748 BigIntegerModAccel a;
749{
750#ifdef OPENSSL
751#if OPENSSL_VERSION_NUMBER >= 0x00906000
752 BN_ULONG B = BN_get_word(b);
753#endif
754 BN_CTX * ctx = NULL;
755 if(c == NULL)
756 c = ctx = BN_CTX_new();
757 if(default_modexp) {
758 (*default_modexp)(r, b, e, m, c, a);
759 }
760 else if(a == NULL) {
761 BN_mod_exp(r, b, e, m, c);
762 }
763#if OPENSSL_VERSION_NUMBER >= 0x00906000
764 else if(B > 0 && B < ULONG_MAX) { /* 0.9.6 and above has mont_word optimization */
765 BN_mod_exp_mont_word(r, B, e, m, c, a);
766 }
767#endif
768 else
769 BN_mod_exp_mont(r, b, e, m, c, a);
770 if(ctx)
771 BN_CTX_free(ctx);
772#elif defined(CRYPTOLIB)
773 bigPow(b, e, m, r);
774#elif defined(GNU_MP)
775 mpz_powm(r, b, e, m);
776#elif defined(GCRYPT)
777 gcry_mpi_powm(r, b, e, m);
778#elif defined(MPI) || defined(TOMMATH)
779 mp_exptmod(b, e, m, r);
780#elif defined(MBEDTLS)
781 mbedtls_mpi_exp_mod(r, b, e, m, NULL);
782#endif
783 return BIG_INTEGER_SUCCESS;
784}
785
786#if defined(MBEDTLS)
787int _mbedtls_f_rng(void* unused, unsigned char *buf, size_t size)
788{
789 t_random(buf, size);
790 return 0;
791}
792#endif
793
794int
795BigIntegerCheckPrime(n, c)
796 BigInteger n;
797 BigIntegerCtx c;
798{
799#ifdef OPENSSL
800 int rv;
801 BN_CTX * ctx = NULL;
802 if(c == NULL)
803 c = ctx = BN_CTX_new();
804#if OPENSSL_VERSION_NUMBER >= 0x00908000
805 rv = BN_is_prime_ex(n, 25, c, NULL);
806#else
807 rv = BN_is_prime(n, 25, NULL, c, NULL);
808#endif
809 if(ctx)
810 BN_CTX_free(ctx);
811 return rv;
812#elif defined(CRYPTOLIB)
813#if 0
814 /*
815 * Ugh. Not only is cryptolib's bigDivide sensitive to inputs
816 * and outputs being the same, but now the primeTest needs random
817 * numbers, which it gets by calling cryptolib's broken truerand
818 * implementation(!) We have to fake it out by doing our own
819 * seeding explicitly.
820 */
821 static int seeded = 0;
822 static unsigned char seedbuf[64];
823 if(!seeded) {
824 t_random(seedbuf, sizeof(seedbuf));
825 seedDesRandom(seedbuf, sizeof(seedbuf));
826 memset(seedbuf, 0, sizeof(seedbuf));
827 seeded = 1;
828 }
829#endif /* 0 */
830 t_random(NULL, 0);
831 return primeTest(n);
832#elif defined(GNU_MP)
833 return mpz_probab_prime_p(n, 25);
834#elif defined(GCRYPT)
835 return (gcry_prime_check(n, 0) == GPG_ERR_NO_ERROR);
836#elif defined(TOMMATH)
837 int rv;
838 mp_prime_is_prime(n, 25, &rv);
839 return rv;
840#elif defined(MPI)
841 return (mpp_pprime(n, 25) == MP_YES);
842#elif defined(MBEDTLS)
843 return mbedtls_mpi_is_prime_ext(n, 25, _mbedtls_f_rng, NULL);
844#endif
845}
846
847BigIntegerResult
848BigIntegerFree(b)
849 BigInteger b;
850{
851#ifdef OPENSSL
852 BN_free(b);
853#elif defined(CRYPTOLIB)
854 freeBignum(b);
855#elif defined(GNU_MP)
856 mpz_clear(b);
857 free(b);
858#elif defined(GCRYPT)
859 gcry_mpi_release(b);
860#elif defined(MPI) || defined(TOMMATH)
861 mp_clear(b);
862 free(b);
863#elif defined(MBEDTLS)
864 mbedtls_mpi_free(b);
865 free(b);
866#endif
867 return BIG_INTEGER_SUCCESS;
868}
869
870BigIntegerResult
871BigIntegerClearFree(b)
872 BigInteger b;
873{
874#ifdef OPENSSL
875 BN_clear_free(b);
876#elif defined(CRYPTOLIB)
877 /* TODO */
878 freeBignum(b);
879#elif defined(GNU_MP)
880 /* TODO */
881 mpz_clear(b);
882 free(b);
883#elif defined(GCRYPT)
884 /* TODO */
885 gcry_mpi_release(b);
886#elif defined(MPI) || defined(TOMMATH)
887 /* TODO */
888 mp_clear(b);
889 free(b);
890#elif defined(MBEDTLS)
891 mbedtls_mpi_free(b);
892 free(b);
893#endif
894 return BIG_INTEGER_SUCCESS;
895}
896
897BigIntegerCtx
898BigIntegerCtxNew()
899{
900#ifdef OPENSSL
901 return BN_CTX_new();
902#else
903 return NULL;
904#endif
905}
906
907BigIntegerResult
908BigIntegerCtxFree(ctx)
909 BigIntegerCtx ctx;
910{
911#ifdef OPENSSL
912 if(ctx)
913 BN_CTX_free(ctx);
914#endif
915 return BIG_INTEGER_SUCCESS;
916}
917
918BigIntegerModAccel
919BigIntegerModAccelNew(m, c)
920 BigInteger m;
921 BigIntegerCtx c;
922{
923#ifdef OPENSSL
924 BN_CTX * ctx = NULL;
925 BN_MONT_CTX * mctx;
926 if(default_modexp)
927 return NULL;
928 if(c == NULL)
929 c = ctx = BN_CTX_new();
930 mctx = BN_MONT_CTX_new();
931 BN_MONT_CTX_set(mctx, m, c);
932 if(ctx)
933 BN_CTX_free(ctx);
934 return mctx;
935#else
936 return NULL;
937#endif
938}
939
940BigIntegerResult
941BigIntegerModAccelFree(accel)
942 BigIntegerModAccel accel;
943{
944#ifdef OPENSSL
945 if(accel)
946 BN_MONT_CTX_free(accel);
947#endif
948 return BIG_INTEGER_SUCCESS;
949}
950
951BigIntegerResult
952BigIntegerInitialize()
953{
954#if OPENSSL_VERSION_NUMBER >= 0x00907000
955 ENGINE_load_builtin_engines();
956#endif
957 return BIG_INTEGER_SUCCESS;
958}
959
960BigIntegerResult
961BigIntegerFinalize()
962{
963 return BigIntegerReleaseEngine();
964}
965
966BigIntegerResult
967BigIntegerUseEngine(const char * engine)
968{
969#if defined(OPENSSL) && defined(OPENSSL_ENGINE)
970 ENGINE * e = ENGINE_by_id(engine);
971 if(e) {
972 if(ENGINE_init(e) > 0) {
973#if OPENSSL_VERSION_NUMBER >= 0x00907000
974 /* 0.9.7 loses the BN_mod_exp method. Pity. */
975 const RSA_METHOD * rsa = ENGINE_get_RSA(e);
976 if(rsa)
977#if (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER >= 0x3000000fL) || (!defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100005L)
978 default_modexp = (modexp_meth)RSA_meth_get_bn_mod_exp(rsa);
979#else
980 default_modexp = (modexp_meth)rsa->bn_mod_exp;
981#endif
982#else
983 default_modexp = (modexp_meth)ENGINE_get_BN_mod_exp(e);
984#endif
985 BigIntegerReleaseEngine();
986 default_engine = e;
987 return BIG_INTEGER_SUCCESS;
988 }
989 else
990 ENGINE_free(e);
991 }
992#endif
993 return BIG_INTEGER_ERROR;
994}
995
996BigIntegerResult
997BigIntegerReleaseEngine()
998{
999#if defined(OPENSSL) && defined(OPENSSL_ENGINE)
1000 if(default_engine) {
1001 ENGINE_finish(default_engine);
1002 ENGINE_free(default_engine);
1003 default_engine = NULL;
1004 default_modexp = NULL;
1005 }
1006#endif
1007 return BIG_INTEGER_SUCCESS;
1008}