libtommath support: compiles, does not work yet
authorRudolf Polzer <divverent@xonotic.org>
Fri, 29 Apr 2011 10:59:41 +0000 (12:59 +0200)
committerRudolf Polzer <divverent@xonotic.org>
Fri, 29 Apr 2011 10:59:41 +0000 (12:59 +0200)
Makefile.am
configure.ac
d0_bignum-gmp.c
d0_bignum-tommath.c [new file with mode: 0644]

index 2419e71..2912c1b 100644 (file)
@@ -13,11 +13,16 @@ lib_LTLIBRARIES = libd0_blind_id.la
 libd0_blind_id_la_SOURCES = d0_blind_id.c d0.c d0_iobuf.c sha2.c \
                             d0_blind_id.h d0.h d0_iobuf.h sha2.h \
                            d0_bignum.h
+
+if WITH_TOMMATH
+libd0_blind_id_la_SOURCES += d0_bignum-tommath.c
+else
 if WITH_OPENSSL
 libd0_blind_id_la_SOURCES += d0_bignum-openssl.c
 else
 libd0_blind_id_la_SOURCES += d0_bignum-gmp.c
 endif
+endif
 libd0_blind_id_la_LDFLAGS = -versioninfo 4:0:4
 libd0_blind_id_la_CFLAGS = -fvisibility=hidden -Wold-style-definition -Wstrict-prototypes -Wsign-compare -Wdeclaration-after-statement
 library_includedir = $(includedir)/d0_blind_id
index 268cc4c..46853a1 100644 (file)
@@ -5,13 +5,18 @@ AC_PROG_CC
 AC_PROG_LIBTOOL
 
 AC_ARG_WITH(openssl, AS_HELP_STRING([--with-openssl], [Use OpenSSL instead of GMP (beware of the OpenSSL license)]), [with_openssl=$withval], [with_openssl=no])
+AC_ARG_WITH(tommath, AS_HELP_STRING([--with-tommath], [Use libtommath instead of GMP (slow, but WTFPL)]), [with_tommath=$withval], [with_tommath=no])
 AM_CONDITIONAL(WITH_OPENSSL, [test x"$with_openssl" != xno])
+AM_CONDITIONAL(WITH_TOMMATH, [test x"$with_tommath" != xno])
 
-AS_IF([test x"$with_openssl" != xno],
-       [AC_SEARCH_LIBS(BN_init, crypto, ,
-               [AC_MSG_ERROR([OpenSSL not found, see http://www.openssl.org/, or try --without-openssl])])],
-       [AC_SEARCH_LIBS(__gmpz_init, gmp, ,
-               [AC_MSG_ERROR([GNU MP not found, see http://gmplib.org/, or try --with-openssl])])])
+AS_IF([test x"$with_tommath" != xno],
+       [AC_SEARCH_LIBS(mp_init, tommath, ,
+               [AC_MSG_ERROR([libtommath not found, see http://www.libtom.org/, or try --without-tommath])])],
+       [AS_IF([test x"$with_openssl" != xno],
+               [AC_SEARCH_LIBS(BN_init, crypto, ,
+                       [AC_MSG_ERROR([OpenSSL not found, see http://www.openssl.org/, or try --without-openssl])])],
+               [AC_SEARCH_LIBS(__gmpz_init, gmp, ,
+                       [AC_MSG_ERROR([GNU MP not found, see http://gmplib.org/, or try --with-openssl])])])])
 
 AC_ARG_ENABLE(rijndael, AS_HELP_STRING([--disable-rijndael], [Disable build of the d0_rijndael library]), [enable_aes=$enableval], [enable_aes=yes])
 
index 3b36b7d..484de57 100644 (file)
@@ -195,7 +195,7 @@ ssize_t d0_bignum_export_unsigned(const d0_bignum_t *bignum, void *buf, size_t b
                // BAD
                // mpz_sizeinbase lied to us
                // move the number
-               if(bufsize == 0)
+               if(count == 0)
                {
                        memset(buf, 0, count);
                }
diff --git a/d0_bignum-tommath.c b/d0_bignum-tommath.c
new file mode 100644 (file)
index 0000000..d38a260
--- /dev/null
@@ -0,0 +1,426 @@
+/*
+ * FILE:       d0_bignum-gmp.c
+ * AUTHOR:     Rudolf Polzer - divVerent@xonotic.org
+ * 
+ * Copyright (c) 2010, Rudolf Polzer
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Format:commit %H$
+ * $Id$
+ */
+
+/* NOTE: this file links against libgmp (http://gmplib.org), which is under the
+ * Lesser General Public License 2.1 or later. You may have to abide to its
+ * terms too if you use this file.
+ * To alternatively link to OpenSSL, provide the option --with-openssl to
+ * ./configure.
+ */
+
+#ifdef WIN32
+#include <windows.h>
+#include <wincrypt.h>
+#endif
+
+#include "d0_bignum.h"
+
+#include <tommath.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+struct d0_bignum_s
+{
+       mp_int z;
+};
+
+static d0_bignum_t temp;
+
+#include <stdio.h>
+
+#ifdef WIN32
+HCRYPTPROV hCryptProv;
+#else
+static FILE *randf;
+#endif
+
+void rand_bytes(unsigned char *buf, size_t n)
+{
+#ifdef WIN32
+       CryptGenRandom(hCryptProv, n, (PBYTE) buf);
+#else
+       if(!randf)
+               return;
+       fread(buf, 1, n, randf);
+#endif
+}
+
+D0_WARN_UNUSED_RESULT D0_BOOL d0_bignum_INITIALIZE(void)
+{
+       D0_BOOL ret = 1;
+       unsigned char buf[256];
+       d0_bignum_init(&temp);
+#ifdef WIN32
+       {
+               if(CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
+               {
+               }
+               else if(CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_NEWKEYSET))
+               {
+               }
+               else
+               {
+                       fprintf(stderr, "WARNING: could not initialize random number generator (CryptAcquireContext failed)\n");
+                       ret = 0;
+                       hCryptProv = NULL;
+               }
+       }
+#else
+       randf = fopen("/dev/urandom", "rb");
+       if(!randf)
+               randf = fopen("/dev/random", "rb");
+       if(randf)
+       {
+               setbuf(randf, NULL);
+       }
+       else
+       {
+               fprintf(stderr, "WARNING: could not initialize random number generator (no random device found)\n");
+               ret = 0;
+       }
+#endif
+
+       return ret;
+}
+
+void d0_bignum_SHUTDOWN(void)
+{
+       d0_bignum_clear(&temp);
+#ifdef WIN32
+       if(hCryptProv)
+       {
+               CryptReleaseContext(hCryptProv, 0);
+               hCryptProv = NULL;
+       }
+#endif
+}
+
+D0_BOOL d0_iobuf_write_bignum(d0_iobuf_t *buf, const d0_bignum_t *bignum)
+{
+       static unsigned char numbuf[65536];
+       size_t count = 0;
+       numbuf[0] = (mp_iszero(&bignum->z) ? 0 : (bignum->z.sign == MP_ZPOS) ? 1 : 3);
+       if((numbuf[0] & 3) != 0) // nonzero
+       {
+               count = mp_unsigned_bin_size(&bignum->z);
+               if(count > sizeof(numbuf) - 1)
+                       return 0;
+               mp_to_unsigned_bin(&bignum->z, numbuf+1);
+       }
+       return d0_iobuf_write_packet(buf, numbuf, count + 1);
+}
+
+d0_bignum_t *d0_iobuf_read_bignum(d0_iobuf_t *buf, d0_bignum_t *bignum)
+{
+       static unsigned char numbuf[65536];
+       size_t count = sizeof(numbuf);
+       if(!d0_iobuf_read_packet(buf, numbuf, &count))
+               return NULL;
+       if(count < 1)
+               return NULL;
+       if(!bignum) bignum = d0_bignum_new(); if(!bignum) return NULL;
+       if(numbuf[0] & 3) // nonzero
+       {
+               mp_read_unsigned_bin(&bignum->z, numbuf+1, count-1);
+               if(numbuf[0] & 2) // negative
+                       bignum->z.sign = MP_NEG;
+       }
+       else // zero
+       {
+               mp_zero(&bignum->z);
+       }
+       return bignum;
+}
+
+ssize_t d0_bignum_export_unsigned(const d0_bignum_t *bignum, void *buf, size_t bufsize)
+{
+       unsigned long count;
+       count = mp_unsigned_bin_size(&bignum->z);
+       if(count > bufsize)
+               return -1;
+       if(bufsize > count)
+       {
+               // pad from left (big endian numbers!)
+               memset(buf, 0, bufsize - count);
+               buf += bufsize - count;
+       }
+       mp_to_unsigned_bin_n(&bignum->z, buf, &count);
+       if(bufsize > count)
+       {
+               // REALLY BAD
+               // mpz_sizeinbase lied to us
+               // buffer overflow
+               // there is no sane way whatsoever to handle this
+               abort();
+       }
+       if(bufsize < count)
+       {
+               // BAD
+               // mpz_sizeinbase lied to us
+               // move the number
+               if(count == 0)
+               {
+                       memset(buf, 0, count);
+               }
+               else
+               {
+                       memmove(buf + count - bufsize, buf, bufsize);
+                       memset(buf, 0, count - bufsize);
+               }
+       }
+       return bufsize;
+}
+
+d0_bignum_t *d0_bignum_import_unsigned(d0_bignum_t *bignum, const void *buf, size_t bufsize)
+{
+       size_t count;
+       if(!bignum) bignum = d0_bignum_new(); if(!bignum) return NULL;
+       mp_read_unsigned_bin(&bignum->z, buf, bufsize);
+       return bignum;
+}
+
+d0_bignum_t *d0_bignum_new(void)
+{
+       d0_bignum_t *b = d0_malloc(sizeof(d0_bignum_t));
+       mp_init(&b->z);
+       return b;
+}
+
+void d0_bignum_free(d0_bignum_t *a)
+{
+       mp_clear(&a->z);
+       d0_free(a);
+}
+
+void d0_bignum_init(d0_bignum_t *b)
+{
+       mp_init(&b->z);
+}
+
+void d0_bignum_clear(d0_bignum_t *a)
+{
+       mp_clear(&a->z);
+}
+
+size_t d0_bignum_size(const d0_bignum_t *r)
+{
+       return mp_count_bits(&r->z);
+}
+
+int d0_bignum_cmp(const d0_bignum_t *a, const d0_bignum_t *b)
+{
+       return mp_cmp(&a->z, &b->z);
+}
+
+static d0_bignum_t *d0_bignum_rand_0_to_limit(d0_bignum_t *r, const d0_bignum_t *limit)
+{
+       size_t n = d0_bignum_size(limit);
+       size_t b = (n + 7) / 8;
+       unsigned char mask = "\xFF\x7F\x3F\x1F\x0F\x07\x03\x01"[8*b - n];
+       unsigned char numbuf[65536];
+       assert(b <= sizeof(numbuf));
+       for(;;)
+       {
+               rand_bytes(&numbuf, b);
+               numbuf[0] &= mask;
+               r = d0_bignum_import_unsigned(r, numbuf, b);
+               if(d0_bignum_cmp(r, limit) < 0)
+                       return r;
+       }
+}
+
+d0_bignum_t *d0_bignum_rand_range(d0_bignum_t *r, const d0_bignum_t *min, const d0_bignum_t *max)
+{
+       mp_sub(&max->z, &min->z, &temp.z);
+       r = d0_bignum_rand_0_to_limit(r, &temp);
+       mp_add(&r->z, &min->z, &r->z);
+       return r;
+}
+
+d0_bignum_t *d0_bignum_rand_bit_atmost(d0_bignum_t *r, size_t n)
+{
+       d0_bignum_one(&temp);
+       d0_bignum_shl(&temp, &temp, n);
+       r = d0_bignum_rand_0_to_limit(r, &temp);
+       return r;
+}
+
+d0_bignum_t *d0_bignum_rand_bit_exact(d0_bignum_t *r, size_t n)
+{
+       d0_bignum_one(&temp);
+       d0_bignum_shl(&temp, &temp, n-1);
+       r = d0_bignum_rand_0_to_limit(r, &temp);
+       d0_bignum_add(r, r, &temp);
+       return r;
+}
+
+d0_bignum_t *d0_bignum_zero(d0_bignum_t *r)
+{
+       if(!r) r = d0_bignum_new(); if(!r) return NULL;
+       mp_zero(&r->z);
+       return r;
+}
+
+d0_bignum_t *d0_bignum_one(d0_bignum_t *r)
+{
+       return d0_bignum_int(r, 1);
+}
+
+d0_bignum_t *d0_bignum_int(d0_bignum_t *r, int n)
+{
+       if(!r) r = d0_bignum_new(); if(!r) return NULL;
+       mp_set_int(&r->z, n);
+       return r;
+}
+
+d0_bignum_t *d0_bignum_mov(d0_bignum_t *r, const d0_bignum_t *a)
+{
+       if(r == a)
+               return r; // trivial
+       if(!r) r = d0_bignum_new(); if(!r) return NULL;
+       mp_copy(&r->z, &a->z);
+       return r;
+}
+
+d0_bignum_t *d0_bignum_neg(d0_bignum_t *r, const d0_bignum_t *a)
+{
+       if(!r) r = d0_bignum_new(); if(!r) return NULL;
+       mp_neg(&a->z, &r->z);
+       return r;
+}
+
+d0_bignum_t *d0_bignum_shl(d0_bignum_t *r, const d0_bignum_t *a, ssize_t n)
+{
+       r = d0_bignum_mov(r, a);
+       if(n > 0)
+               mp_mul_2d(&r->z,  n, &r->z);
+       else if(n < 0)
+               mp_div_2d(&r->z, -n, &r->z, NULL);
+       return r;
+}
+
+d0_bignum_t *d0_bignum_add(d0_bignum_t *r, const d0_bignum_t *a, const d0_bignum_t *b)
+{
+       if(!r) r = d0_bignum_new(); if(!r) return NULL;
+       mp_add(&a->z, &b->z, &r->z);
+       return r;
+}
+
+d0_bignum_t *d0_bignum_sub(d0_bignum_t *r, const d0_bignum_t *a, const d0_bignum_t *b)
+{
+       if(!r) r = d0_bignum_new(); if(!r) return NULL;
+       mp_sub(&a->z, &b->z, &r->z);
+       return r;
+}
+
+d0_bignum_t *d0_bignum_mul(d0_bignum_t *r, const d0_bignum_t *a, const d0_bignum_t *b)
+{
+       if(!r) r = d0_bignum_new(); if(!r) return NULL;
+       mp_mul(&a->z, &b->z, &r->z);
+       return r;
+}
+
+d0_bignum_t *d0_bignum_divmod(d0_bignum_t *q, d0_bignum_t *m, const d0_bignum_t *a, const d0_bignum_t *b)
+{
+       if(!q && !m)
+               m = d0_bignum_new();
+       if(q)
+               mp_div(&a->z, &b->z, &q->z, m ? &m->z : NULL);
+       else
+               mp_mod(&a->z, &b->z, &m->z);
+       if(m)
+               return m;
+       else
+               return q;
+}
+
+d0_bignum_t *d0_bignum_mod_add(d0_bignum_t *r, const d0_bignum_t *a, const d0_bignum_t *b, const d0_bignum_t *m)
+{
+       if(!r) r = d0_bignum_new(); if(!r) return NULL;
+       mp_addmod(&a->z, &b->z, &m->z, &r->z);
+       return r;
+}
+
+d0_bignum_t *d0_bignum_mod_sub(d0_bignum_t *r, const d0_bignum_t *a, const d0_bignum_t *b, const d0_bignum_t *m)
+{
+       if(!r) r = d0_bignum_new(); if(!r) return NULL;
+       mp_submod(&a->z, &b->z, &m->z, &r->z);
+       return r;
+}
+
+d0_bignum_t *d0_bignum_mod_mul(d0_bignum_t *r, const d0_bignum_t *a, const d0_bignum_t *b, const d0_bignum_t *m)
+{
+       if(!r) r = d0_bignum_new(); if(!r) return NULL;
+       mp_mulmod(&a->z, &b->z, &m->z, &r->z);
+       return r;
+}
+
+d0_bignum_t *d0_bignum_mod_pow(d0_bignum_t *r, const d0_bignum_t *a, const d0_bignum_t *b, const d0_bignum_t *m)
+{
+       if(!r) r = d0_bignum_new(); if(!r) return NULL;
+       mp_exptmod(&a->z, &b->z, &m->z, &r->z);
+       return r;
+}
+
+D0_BOOL d0_bignum_mod_inv(d0_bignum_t *r, const d0_bignum_t *a, const d0_bignum_t *m)
+{
+       // here, r MUST be set, as otherwise we cannot return error state!
+       return mp_invmod(&a->z, &m->z, &r->z);
+}
+
+int d0_bignum_isprime(d0_bignum_t *r, int param)
+{
+       int ret = 0;
+       mp_prime_is_prime(&r->z, param, &ret);
+       return ret;
+}
+
+d0_bignum_t *d0_bignum_gcd(d0_bignum_t *r, d0_bignum_t *s, d0_bignum_t *t, const d0_bignum_t *a, const d0_bignum_t *b)
+{
+       if(!r) r = d0_bignum_new(); if(!r) return NULL;
+       if(s || t)
+               mp_exteuclid(&a->z, &b->z, s ? &s->z : NULL, t ? &t->z : NULL, &r->z);
+       else
+               mp_gcd(&a->z, &b->z, &r->z);
+       return r;
+}
+
+char *d0_bignum_tostring(const d0_bignum_t *x, unsigned int base)
+{
+       static char str[65536];
+       mp_toradix_n(&x->z, str, base, sizeof(str));
+       return str;
+}