9424ad97e7618a1e7ef605fe29fef1cce4531148
[crypto.git] / lib / silcmath / mp_tfm.c
1 /*
2
3   mp_tfm.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2005 - 2008 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19
20 #include "silccrypto.h"
21 #include "mp_tfm.h"
22
23 static void silc_mp_set_errno(int err)
24 {
25   if (err == TFM_FP_VAL)
26     silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
27   else if (err == TFM_FP_MEM)
28     silc_set_errno(SILC_ERR_OUT_OF_MEMORY);
29 }
30
31 SilcBool silc_mp_init(SilcMPInt *mp)
32 {
33   tfm_fp_init(mp);
34   return TRUE;
35 }
36
37 SilcBool silc_mp_sinit(SilcStack stack, SilcMPInt *mp)
38 {
39   if (stack)
40     stack = silc_stack_alloc(0, stack);
41   tfm_fp_sinit(stack, mp);
42   return TRUE;
43 }
44
45 void silc_mp_uninit(SilcMPInt *mp)
46 {
47   tfm_fp_zero(mp);
48 }
49
50 size_t silc_mp_size(SilcMPInt *mp)
51 {
52   return tfm_fp_unsigned_bin_size(mp);
53 }
54
55 size_t silc_mp_sizeinbase(SilcMPInt *mp, int base)
56 {
57   int size = 0;
58   tfm_fp_radix_size(mp, base, &size);
59   if (size > 1)
60     size--;
61   return size;
62 }
63
64 SilcBool silc_mp_set(SilcMPInt *dst, SilcMPInt *src)
65 {
66   int ret;
67   if ((ret = tfm_fp_copy(src, dst))) {
68     silc_mp_set_errno(ret);
69     return FALSE;
70   }
71   return TRUE;
72 }
73
74 SilcBool silc_mp_set_ui(SilcMPInt *dst, SilcUInt32 ui)
75 {
76   int ret;
77   if ((ret = tfm_fp_set(dst, ui))) {
78     silc_mp_set_errno(ret);
79     return FALSE;
80   }
81   return TRUE;
82 }
83
84 SilcBool silc_mp_set_si(SilcMPInt *dst, SilcInt32 si)
85 {
86   int ret;
87   if ((ret = tfm_fp_set(dst, si))) {
88     silc_mp_set_errno(ret);
89     return FALSE;
90   }
91   return TRUE;
92 }
93
94 SilcBool silc_mp_set_str(SilcMPInt *dst, const char *str, int base)
95 {
96   int ret;
97   if ((ret = tfm_fp_read_radix(dst, (char *)str, base))) {
98     silc_mp_set_errno(ret);
99     return FALSE;
100   }
101   return TRUE;
102 }
103
104 SilcUInt32 silc_mp_get_ui(SilcMPInt *mp)
105 {
106   tfm_fp_int *tmp = mp;
107   return tmp->used > 0 ? tmp->dp[0] : 0;
108 }
109
110 char *silc_mp_get_str(char *str, SilcMPInt *mp, int base)
111 {
112   if (tfm_fp_toradix(mp, str, base) != TFM_FP_OKAY)
113     return NULL;
114   return str;
115 }
116
117 SilcBool silc_mp_add(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *mp2)
118 {
119   int ret;
120   if ((ret = tfm_fp_add(mp1, mp2, dst))) {
121     silc_mp_set_errno(ret);
122     return FALSE;
123   }
124   return TRUE;
125 }
126
127 SilcBool silc_mp_add_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 ui)
128 {
129   int ret;
130   if ((ret = tfm_fp_add_d(mp1, (tfm_fp_digit)ui, dst))) {
131     silc_mp_set_errno(ret);
132     return FALSE;
133   }
134   return TRUE;
135 }
136
137 SilcBool silc_mp_sub(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *mp2)
138 {
139   int ret;
140   if ((ret = tfm_fp_sub(mp1, mp2, dst))) {
141     silc_mp_set_errno(ret);
142     return FALSE;
143   }
144   return TRUE;
145 }
146
147 SilcBool silc_mp_sub_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 ui)
148 {
149   int ret;
150   if ((ret = tfm_fp_sub_d(mp1, (tfm_fp_digit)ui, dst))) {
151     silc_mp_set_errno(ret);
152     return FALSE;
153   }
154   return TRUE;
155 }
156
157 SilcBool silc_mp_mul(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *mp2)
158 {
159   int ret;
160   if ((ret = tfm_fp_mul(mp1, mp2, dst))) {
161     silc_mp_set_errno(ret);
162     return FALSE;
163   }
164   return TRUE;
165 }
166
167 SilcBool silc_mp_mul_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 ui)
168 {
169   int ret;
170   if ((ret = tfm_fp_mul_d(mp1, (tfm_fp_digit)ui, dst))) {
171     silc_mp_set_errno(ret);
172     return FALSE;
173   }
174   return TRUE;
175 }
176
177 SilcBool silc_mp_mul_2exp(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 exp)
178 {
179   int ret;
180   if ((ret = tfm_fp_mul_2d(mp1, exp, dst))) {
181     silc_mp_set_errno(ret);
182     return FALSE;
183   }
184   return TRUE;
185 }
186
187 SilcBool silc_mp_sqrt(SilcMPInt *dst, SilcMPInt *src)
188 {
189   int ret;
190   if ((ret = tfm_fp_sqrt(src, dst))) {
191     silc_mp_set_errno(ret);
192     return FALSE;
193   }
194   return TRUE;
195 }
196
197 SilcBool silc_mp_div(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *mp2)
198 {
199   int ret;
200   if ((ret = tfm_fp_div(mp1, mp2, dst, NULL))) {
201     silc_mp_set_errno(ret);
202     return FALSE;
203   }
204   return TRUE;
205 }
206
207 SilcBool silc_mp_div_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 ui)
208 {
209   int ret;
210   if ((ret = tfm_fp_div_d(mp1, (tfm_fp_digit)ui, dst, NULL))) {
211     silc_mp_set_errno(ret);
212     return FALSE;
213   }
214   return TRUE;
215 }
216
217 SilcBool silc_mp_div_qr(SilcMPInt *q, SilcMPInt *r, SilcMPInt *mp1,
218                     SilcMPInt *mp2)
219 {
220   int ret;
221   if ((ret = tfm_fp_div(mp1, mp2, q, r))) {
222     silc_mp_set_errno(ret);
223     return FALSE;
224   }
225   return TRUE;
226 }
227
228 SilcBool silc_mp_div_2exp(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 exp)
229 {
230   int ret;
231   if ((ret = tfm_fp_div_2d(mp1, exp, dst, NULL))) {
232     silc_mp_set_errno(ret);
233     return FALSE;
234   }
235   return TRUE;
236 }
237
238 SilcBool silc_mp_div_2exp_qr(SilcMPInt *q, SilcMPInt *r, SilcMPInt *mp1,
239                          SilcUInt32 exp)
240 {
241   int ret;
242   if ((ret = tfm_fp_div_2d(mp1, exp, q, r))) {
243     silc_mp_set_errno(ret);
244     return FALSE;
245   }
246   return TRUE;
247 }
248
249 SilcBool silc_mp_mod(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *mp2)
250 {
251   int ret;
252   if ((ret = tfm_fp_mod(mp1, mp2, dst))) {
253     silc_mp_set_errno(ret);
254     return FALSE;
255   }
256   return TRUE;
257 }
258
259 SilcBool silc_mp_mod_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 ui)
260 {
261   tfm_fp_digit d;
262   int ret;
263
264   if ((ret = tfm_fp_mod_d(mp1, ui, &d))) {
265     silc_mp_set_errno(ret);
266     return FALSE;
267   }
268   if ((ret = silc_mp_set_ui(dst, d))) {
269     silc_mp_set_errno(ret);
270     return FALSE;
271   }
272   return TRUE;
273 }
274
275 SilcBool silc_mp_mod_2exp(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 ui)
276 {
277   int ret;
278   if ((ret = tfm_fp_mod_2d(mp1, ui, dst))) {
279     silc_mp_set_errno(ret);
280     return FALSE;
281   }
282   return TRUE;
283 }
284
285 SilcBool silc_mp_pow_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 exp)
286 {
287   int ret;
288   if ((ret = tfm_fp_expt_d(mp1, (tfm_fp_digit)exp, dst))) {
289     silc_mp_set_errno(ret);
290     return FALSE;
291   }
292   return TRUE;
293 }
294
295 SilcBool silc_mp_pow_mod(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *exp,
296                      SilcMPInt *mod)
297 {
298   int ret;
299   if ((ret = tfm_fp_exptmod(mp1, exp, mod, dst))) {
300     silc_mp_set_errno(ret);
301     return FALSE;
302   }
303   return TRUE;
304 }
305
306 SilcBool silc_mp_pow_mod_ui(SilcMPInt *dst, SilcMPInt *mp1, SilcUInt32 exp,
307                             SilcMPInt *mod)
308 {
309   SilcMPInt tmp;
310   int ret;
311
312   if ((ret = silc_mp_init(&tmp))) {
313     silc_mp_set_errno(ret);
314     return FALSE;
315   }
316   if ((ret = silc_mp_set_ui(&tmp, exp))) {
317     silc_mp_set_errno(ret);
318     return FALSE;
319   }
320   if ((ret = silc_mp_pow_mod(dst, mp1, &tmp, mod))) {
321     silc_mp_set_errno(ret);
322     return FALSE;
323   }
324   silc_mp_uninit(&tmp);
325   return TRUE;
326 }
327
328 SilcBool silc_mp_gcd(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *mp2)
329 {
330   int ret;
331   if ((ret = tfm_fp_gcd(mp1, mp2, dst))) {
332     silc_mp_set_errno(ret);
333     return FALSE;
334   }
335   return TRUE;
336 }
337
338 int silc_mp_cmp(SilcMPInt *mp1, SilcMPInt *mp2)
339 {
340   return tfm_fp_cmp(mp1, mp2);
341 }
342
343 int silc_mp_cmp_si(SilcMPInt *mp1, SilcInt32 si)
344 {
345   return tfm_fp_cmp_d(mp1, si);
346 }
347
348 int silc_mp_cmp_ui(SilcMPInt *mp1, SilcUInt32 ui)
349 {
350   return tfm_fp_cmp_d(mp1, ui);
351 }
352
353 SilcBool silc_mp_abs(SilcMPInt *dst, SilcMPInt *src)
354 {
355   tfm_fp_abs(src, dst);
356   return TRUE;
357 }
358
359 SilcBool silc_mp_neg(SilcMPInt *dst, SilcMPInt *src)
360 {
361   tfm_fp_neg(src, dst);
362   return TRUE;
363 }
364
365 SilcBool silc_mp_and(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *mp2)
366 {
367   int ret;
368   if ((ret = tfm_fp_and(mp1, mp2, dst))) {
369     silc_mp_set_errno(ret);
370     return FALSE;
371   }
372   return TRUE;
373 }
374
375 SilcBool silc_mp_or(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *mp2)
376 {
377   int ret;
378   if ((ret = tfm_fp_or(mp1, mp2, dst))) {
379     silc_mp_set_errno(ret);
380     return FALSE;
381   }
382   return TRUE;
383 }
384
385 SilcBool silc_mp_xor(SilcMPInt *dst, SilcMPInt *mp1, SilcMPInt *mp2)
386 {
387   int ret;
388   if ((ret = tfm_fp_xor(mp1, mp2, dst))) {
389     silc_mp_set_errno(ret);
390     return FALSE;
391   }
392   return TRUE;
393 }
394
395 SilcBool silc_mp_modinv(SilcMPInt *inv, SilcMPInt *a, SilcMPInt *n)
396 {
397   int ret;
398   if ((ret = tfm_fp_invmod(a, n, inv))) {
399     silc_mp_set_errno(ret);
400     return FALSE;
401   }
402   return TRUE;
403 }