]> de.git.xonotic.org Git - xonotic/d0_blind_id.git/blob - d0_bignum-openssl.c
implement OpenSSL variant
[xonotic/d0_blind_id.git] / d0_bignum-openssl.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 <openssl/bn.h>
23
24 struct d0_bignum_s
25 {
26         BIGNUM z;
27 };
28
29 static d0_bignum_t temp;
30 static BN_CTX ctx;
31
32 #include <time.h>
33 #include <stdio.h>
34
35 WARN_UNUSED_RESULT BOOL d0_bignum_INITIALIZE(void)
36 {
37         BN_CTX_init(&ctx);
38         d0_bignum_init(&temp);
39         return 1;
40 }
41
42 void d0_bignum_SHUTDOWN(void)
43 {
44         d0_bignum_clear(&temp);
45         BN_CTX_free(&ctx);
46 }
47
48 BOOL d0_iobuf_write_bignum(d0_iobuf_t *buf, const d0_bignum_t *bignum)
49 {
50         static unsigned char numbuf[65536];
51         size_t count = 0;
52         numbuf[0] = BN_is_zero(&bignum->z) ? 0 : BN_is_negative(&bignum->z) ? 3 : 1;
53         if((numbuf[0] & 3) != 0) // nonzero
54         {
55                 count = BN_num_bytes(&bignum->z);
56                 if(count > sizeof(numbuf) - 1)
57                         return 0;
58                 BN_bn2bin(numbuf+1, &bignum->z);
59         }
60         return d0_iobuf_write_packet(buf, numbuf, count + 1);
61 }
62
63 d0_bignum_t *d0_iobuf_read_bignum(d0_iobuf_t *buf, d0_bignum_t *bignum)
64 {
65         static unsigned char numbuf[65536];
66         size_t count = sizeof(numbuf);
67         if(!d0_iobuf_read_packet(buf, numbuf, &count))
68                 return NULL;
69         if(count < 1)
70                 return NULL;
71         if(!bignum) bignum = d0_bignum_new(); if(!bignum) return NULL;
72         if(numbuf[0] & 3) // nonzero
73         {
74                 BN_bin2bn(numbuf+1, count-1, &bignum->z);
75                 if(numbuf[0] & 2) // negative
76                         BN_set_negative(&bignum->z, 1);
77         }
78         else // zero
79         {
80                 BN_zero(&bignum->z);
81         }
82         return bignum;
83 }
84
85 ssize_t d0_bignum_export_unsigned(const d0_bignum_t *bignum, void *buf, size_t bufsize)
86 {
87         size_t count;
88         count = BN_num_bytes(&bignum->z);
89         if(count > bufsize)
90                 return -1;
91         if(bufsize > count)
92         {
93                 // pad from left (big endian numbers!)
94                 memset(buf, 0, bufsize - count);
95                 buf += bufsize - count;
96         }
97         BN_bn2bin(&bignum->z, buf);
98         return bufsize;
99 }
100
101 d0_bignum_t *d0_bignum_import_unsigned(d0_bignum_t *bignum, const void *buf, size_t bufsize)
102 {
103         size_t count;
104         if(!bignum) bignum = d0_bignum_new(); if(!bignum) return NULL;
105         BN_bin2bn(buf, bufsize, &bignum->z);
106         return bignum;
107 }
108
109 d0_bignum_t *d0_bignum_new(void)
110 {
111         d0_bignum_t *b = d0_malloc(sizeof(d0_bignum_t));
112         BN_init(&b->z);
113         return b;
114 }
115
116 void d0_bignum_free(d0_bignum_t *a)
117 {
118         BN_free(&a->z);
119         d0_free(a);
120 }
121
122 void d0_bignum_init(d0_bignum_t *b)
123 {
124         BN_init(&b->z);
125 }
126
127 void d0_bignum_clear(d0_bignum_t *a)
128 {
129         BN_free(&a->z);
130 }
131
132 size_t d0_bignum_size(const d0_bignum_t *r)
133 {
134         return BN_num_bits(&r->z);
135 }
136
137 int d0_bignum_cmp(const d0_bignum_t *a, const d0_bignum_t *b)
138 {
139         return BN_cmp(&a->z, &b->z);
140 }
141
142 d0_bignum_t *d0_bignum_rand_range(d0_bignum_t *r, const d0_bignum_t *min, const d0_bignum_t *max)
143 {
144         if(!r) r = d0_bignum_new(); if(!r) return NULL;
145         BN_sub(&temp.z, &max->z, &min->z);
146         BN_rand_range(&r->z, &temp.z);
147         BN_add(&r->z, &r->z, &min->z);
148         return r;
149 }
150
151 d0_bignum_t *d0_bignum_rand_bit_atmost(d0_bignum_t *r, size_t n)
152 {
153         if(!r) r = d0_bignum_new(); if(!r) return NULL;
154         BN_rand(&r->z, n, -1, 0);
155         return r;
156 }
157
158 d0_bignum_t *d0_bignum_rand_bit_exact(d0_bignum_t *r, size_t n)
159 {
160         if(!r) r = d0_bignum_new(); if(!r) return NULL;
161         BN_rand(&r->z, n, 0, 0);
162         return r;
163 }
164
165 d0_bignum_t *d0_bignum_zero(d0_bignum_t *r)
166 {
167         if(!r) r = d0_bignum_new(); if(!r) return NULL;
168         BN_zero(&r->z);
169         return r;
170 }
171
172 d0_bignum_t *d0_bignum_one(d0_bignum_t *r)
173 {
174         if(!r) r = d0_bignum_new(); if(!r) return NULL;
175         BN_one(&r->z);
176         return r;
177 }
178
179 d0_bignum_t *d0_bignum_int(d0_bignum_t *r, int n)
180 {
181         if(!r) r = d0_bignum_new(); if(!r) return NULL;
182         BN_set_word(&r->z, n);
183         return r;
184 }
185
186 d0_bignum_t *d0_bignum_mov(d0_bignum_t *r, const d0_bignum_t *a)
187 {
188         if(r == a)
189                 return r; // trivial
190         if(!r) r = d0_bignum_new(); if(!r) return NULL;
191         BN_copy(&r->z, &a->z);
192         return r;
193 }
194
195 d0_bignum_t *d0_bignum_neg(d0_bignum_t *r, const d0_bignum_t *a)
196 {
197         if(!r) r = d0_bignum_new(); if(!r) return NULL;
198         if(r != a)
199                 BN_copy(&r->z, &a->z);
200         BN_set_negative(&r->z, !BN_is_negative(&r->z));
201         return r;
202 }
203
204 d0_bignum_t *d0_bignum_shl(d0_bignum_t *r, const d0_bignum_t *a, ssize_t n)
205 {
206         if(!r) r = d0_bignum_new(); if(!r) return NULL;
207         if(n > 0)
208                 BN_lshift(&r->z, &a->z, n);
209         else if(n < 0)
210                 BN_rshift(&r->z, &a->z, n);
211         else if(r != a)
212                 BN_copy(&r->z, &a->z);
213         return r;
214 }
215
216 d0_bignum_t *d0_bignum_add(d0_bignum_t *r, const d0_bignum_t *a, const d0_bignum_t *b)
217 {
218         if(!r) r = d0_bignum_new(); if(!r) return NULL;
219         BN_add(&r->z, &a->z, &b->z);
220         return r;
221 }
222
223 d0_bignum_t *d0_bignum_sub(d0_bignum_t *r, const d0_bignum_t *a, const d0_bignum_t *b)
224 {
225         if(!r) r = d0_bignum_new(); if(!r) return NULL;
226         BN_sub(&r->z, &a->z, &b->z);
227         return r;
228 }
229
230 d0_bignum_t *d0_bignum_mul(d0_bignum_t *r, const d0_bignum_t *a, const d0_bignum_t *b)
231 {
232         if(!r) r = d0_bignum_new(); if(!r) return NULL;
233         BN_mul(&r->z, &a->z, &b->z);
234         return r;
235 }
236
237 d0_bignum_t *d0_bignum_divmod(d0_bignum_t *q, d0_bignum_t *m, const d0_bignum_t *a, const d0_bignum_t *b)
238 {
239         if(!q && !m)
240                 m = d0_bignum_new();
241         if(q)
242         {
243                 if(m)
244                         BN_div(&q->z, &m->z, &a->z, &b->z, &ctx);
245                 else
246                         BN_div(&q->z, NULL, &a->z, &b->z, &ctx);
247                 assert(!"I know this code is broken (rounds towards zero), need handle negative correctly");
248         }
249         else
250                 BN_nnmod(&q->z, NULL, &a->z, &b->z, &ctx);
251         if(m)
252                 return m;
253         else
254                 return q;
255 }
256
257 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)
258 {
259         if(!r) r = d0_bignum_new(); if(!r) return NULL;
260         BN_mod_add(&r->z, &a->z, &b->z, &m->z, &ctx);
261         return r;
262 }
263
264 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)
265 {
266         if(!r) r = d0_bignum_new(); if(!r) return NULL;
267         BN_mod_mul(&r->z, &a->z, &b->z, &m->z, &ctx);
268         return r;
269 }
270
271 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)
272 {
273         if(!r) r = d0_bignum_new(); if(!r) return NULL;
274         BN_mod_exp(&r->z, &a->z, &b->z, &m->z, &ctx);
275         return r;
276 }
277
278 BOOL d0_bignum_mod_inv(d0_bignum_t *r, const d0_bignum_t *a, const d0_bignum_t *m)
279 {
280         // here, r MUST be set, as otherwise we cannot return error state!
281         return !!BN_mod_inverse(&r->z, &a->z, &m->z, &ctx);
282 }
283
284 int d0_bignum_isprime(d0_bignum_t *r, int param)
285 {
286         return BN_is_prime(&r->z, param, NULL, &ctx, NULL);
287 }
288
289 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)
290 {
291         if(!r) r = d0_bignum_new(); if(!r) return NULL;
292         if(s)
293                 assert(!"Extended gcd not implemented");
294         else if(t)
295                 assert(!"Extended gcd not implemented");
296         else
297                 BN_gcd(&r->z, &a->z, &b->z, &ctx);
298         return r;
299 }
300
301 char *d0_bignum_tostring(const d0_bignum_t *x, unsigned int base)
302 {
303         if(base == 10)
304                 return BN_bn2dec(&x->z);
305         else if(base == 16)
306                 return BN_bn2hex(&x->z);
307         else
308                 assert(!"Other bases not implemented");
309 }