]> de.git.xonotic.org Git - xonotic/d0_blind_id.git/blob - d0_bignum-gmp.c
initial autoconf stuff
[xonotic/d0_blind_id.git] / d0_bignum-gmp.c
1 /*
2 Blind-ID library for user identification using RSA blind signatures
3 Copyright (C) 2010  Rudolf Polzer
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18 */
19
20 #include "d0_bignum.h"
21
22 #include <gmp.h>
23
24 struct d0_bignum_s
25 {
26         mpz_t z;
27 };
28
29 static gmp_randstate_t RANDSTATE;
30
31 #include <time.h>
32 void d0_bignum_INITIALIZE()
33 {
34         gmp_randinit_default(RANDSTATE);
35         gmp_randseed_ui(RANDSTATE, time(NULL)); // TODO seed
36 }
37
38 void d0_bignum_SHUTDOWN()
39 {
40         // free RANDSTATE
41 }
42
43 BOOL d0_iobuf_write_bignum(d0_iobuf_t *buf, const d0_bignum_t *bignum)
44 {
45         static unsigned char numbuf[65536];
46         size_t count = 0;
47         numbuf[0] = mpz_sgn(bignum->z) & 3;
48         if((numbuf[0] & 3) != 0) // nonzero
49         {
50                 count = (mpz_sizeinbase(bignum->z, 2) + 7) / 8;
51                 if(count > sizeof(numbuf) - 1)
52                         return 0;
53                 mpz_export(numbuf+1, &count, 1, 1, 0, 0, bignum->z);
54         }
55         return d0_iobuf_write_packet(buf, numbuf, count + 1);
56 }
57
58 d0_bignum_t *d0_iobuf_read_bignum(d0_iobuf_t *buf, d0_bignum_t *bignum)
59 {
60         static unsigned char numbuf[65536];
61         size_t count = sizeof(numbuf);
62         if(!d0_iobuf_read_packet(buf, numbuf, &count))
63                 return NULL;
64         if(count < 1)
65                 return NULL;
66         if(!bignum) bignum = d0_bignum_new(); if(!bignum) return NULL;
67         if(numbuf[0] & 3) // nonzero
68         {
69                 mpz_import(bignum->z, count-1, 1, 1, 0, 0, numbuf+1);
70                 if(numbuf[0] & 2) // negative
71                         mpz_neg(bignum->z, bignum->z);
72         }
73         else // zero
74         {
75                 mpz_set_ui(bignum->z, 0);
76         }
77         return bignum;
78 }
79
80 d0_bignum_t *d0_bignum_new()
81 {
82         d0_bignum_t *b = d0_malloc(sizeof(d0_bignum_t));
83         mpz_init(b->z);
84         return b;
85 }
86
87 void d0_bignum_free(d0_bignum_t *a)
88 {
89         mpz_clear(a->z);
90         d0_free(a);
91 }
92
93 void d0_bignum_init(d0_bignum_t *b)
94 {
95         mpz_init(b->z);
96 }
97
98 void d0_bignum_clear(d0_bignum_t *a)
99 {
100         mpz_clear(a->z);
101 }
102
103 size_t d0_bignum_size(const d0_bignum_t *r)
104 {
105         return mpz_sizeinbase(r->z, 2);
106 }
107
108 int d0_bignum_cmp(const d0_bignum_t *a, const d0_bignum_t *b)
109 {
110         return mpz_cmp(a->z, b->z);
111 }
112
113 d0_bignum_t *d0_bignum_rand_range(d0_bignum_t *r, const d0_bignum_t *min, const d0_bignum_t *max)
114 {
115         static d0_bignum_t *temp = NULL; if(!temp) temp = d0_bignum_new();
116         if(!r) r = d0_bignum_new(); if(!r) return NULL;
117         mpz_sub(temp->z, max->z, min->z);
118         mpz_urandomm(r->z, RANDSTATE, temp->z);
119         mpz_add(r->z, r->z, min->z);
120         return r;
121 }
122
123 d0_bignum_t *d0_bignum_rand_bit_atmost(d0_bignum_t *r, size_t n)
124 {
125         if(!r) r = d0_bignum_new(); if(!r) return NULL;
126         mpz_urandomb(r->z, RANDSTATE, n);
127         return r;
128 }
129
130 d0_bignum_t *d0_bignum_rand_bit_exact(d0_bignum_t *r, size_t n)
131 {
132         if(!r) r = d0_bignum_new(); if(!r) return NULL;
133         mpz_urandomb(r->z, RANDSTATE, n-1);
134         mpz_setbit(r->z, n-1);
135         return r;
136 }
137
138 d0_bignum_t *d0_bignum_zero(d0_bignum_t *r)
139 {
140         return d0_bignum_int(r, 0);
141 }
142
143 d0_bignum_t *d0_bignum_one(d0_bignum_t *r)
144 {
145         return d0_bignum_int(r, 1);
146 }
147
148 d0_bignum_t *d0_bignum_int(d0_bignum_t *r, int n)
149 {
150         if(!r) r = d0_bignum_new(); if(!r) return NULL;
151         mpz_set_si(r->z, n);
152         return r;
153 }
154
155 d0_bignum_t *d0_bignum_mov(d0_bignum_t *r, const d0_bignum_t *a)
156 {
157         if(r == a)
158                 return r; // trivial
159         if(!r) r = d0_bignum_new(); if(!r) return NULL;
160         mpz_set(r->z, a->z);
161         return r;
162 }
163
164 d0_bignum_t *d0_bignum_neg(d0_bignum_t *r, const d0_bignum_t *a)
165 {
166         if(!r) r = d0_bignum_new(); if(!r) return NULL;
167         mpz_neg(r->z, a->z);
168         return r;
169 }
170
171 d0_bignum_t *d0_bignum_shl(d0_bignum_t *r, const d0_bignum_t *a, ssize_t n)
172 {
173         if(!r) r = d0_bignum_new(); if(!r) return NULL;
174         if(n > 0)
175                 mpz_mul_2exp(r->z, a->z, n);
176         else if(n < 0)
177                 mpz_fdiv_q_2exp(r->z, a->z, -n);
178         else
179                 mpz_set(r->z, a->z);
180         return r;
181 }
182
183 d0_bignum_t *d0_bignum_add(d0_bignum_t *r, const d0_bignum_t *a, const d0_bignum_t *b)
184 {
185         if(!r) r = d0_bignum_new(); if(!r) return NULL;
186         mpz_add(r->z, a->z, b->z);
187         return r;
188 }
189
190 d0_bignum_t *d0_bignum_sub(d0_bignum_t *r, const d0_bignum_t *a, const d0_bignum_t *b)
191 {
192         if(!r) r = d0_bignum_new(); if(!r) return NULL;
193         mpz_sub(r->z, a->z, b->z);
194         return r;
195 }
196
197 d0_bignum_t *d0_bignum_mul(d0_bignum_t *r, const d0_bignum_t *a, const d0_bignum_t *b)
198 {
199         if(!r) r = d0_bignum_new(); if(!r) return NULL;
200         mpz_mul(r->z, a->z, b->z);
201         return r;
202 }
203
204 d0_bignum_t *d0_bignum_divmod(d0_bignum_t *q, d0_bignum_t *m, const d0_bignum_t *a, const d0_bignum_t *b)
205 {
206         if(!q && !m)
207                 m = d0_bignum_new();
208         if(q)
209                 if(m)
210                         mpz_fdiv_qr(q->z, m->z, a->z, b->z);
211                 else
212                         mpz_fdiv_q(q->z, a->z, b->z);
213         else
214                 mpz_fdiv_r(m->z, a->z, b->z);
215         if(m)
216                 return m;
217         else
218                 return q;
219 }
220
221 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)
222 {
223         r = d0_bignum_add(r, a, b);
224         mpz_fdiv_r(r->z, r->z, m->z);
225         return r;
226 }
227
228 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)
229 {
230         r = d0_bignum_mul(r, a, b);
231         mpz_fdiv_r(r->z, r->z, m->z);
232         return r;
233 }
234
235 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)
236 {
237         if(!r) r = d0_bignum_new(); if(!r) return NULL;
238         mpz_powm(r->z, a->z, b->z, m->z);
239         return r;
240 }
241
242 BOOL d0_bignum_mod_inv(d0_bignum_t *r, const d0_bignum_t *a, const d0_bignum_t *m)
243 {
244         // here, r MUST be set, as otherwise we cannot return error state!
245         return mpz_invert(r->z, a->z, m->z);
246 }
247
248 int d0_bignum_isprime(d0_bignum_t *r, int param)
249 {
250         return mpz_probab_prime_p(r->z, param);
251 }
252
253 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)
254 {
255         if(!r) r = d0_bignum_new(); if(!r) return NULL;
256         if(s)
257                 mpz_gcdext(r->z, s->z, t ? t->z : NULL, a->z, b->z);
258         else if(t)
259                 mpz_gcdext(r->z, t->z, NULL, b->z, a->z);
260         else
261                 mpz_gcd(r->z, a->z, b->z);
262         return r;
263 }
264
265 char *d0_bignum_tostring(const d0_bignum_t *x, unsigned int base)
266 {
267         return mpz_get_str(NULL, base, x->z);
268 }