1/* LibTomCrypt, modular cryptographic library -- Tom St Denis
2 *
3 * LibTomCrypt is a library that provides various cryptographic
4 * algorithms in a highly modular and flexible manner.
5 *
6 * The library is free for all purposes without any express
7 * guarantee it works.
8 *
9 * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
10 */
11
12#define DESC_DEF_ONLY
13#include "tomcrypt.h"
14
15#ifdef LTM_DESC
16
17#include <tommath.h>
18
19static const struct {
20    int mpi_code, ltc_code;
21} mpi_to_ltc_codes[] = {
22   { MP_OKAY ,  CRYPT_OK},
23   { MP_MEM  ,  CRYPT_MEM},
24   { MP_VAL  ,  CRYPT_INVALID_ARG},
25};
26
27/**
28   Convert a MPI error to a LTC error (Possibly the most powerful function ever!  Oh wait... no)
29   @param err    The error to convert
30   @return The equivalent LTC error code or CRYPT_ERROR if none found
31*/
32static int mpi_to_ltc_error(int err)
33{
34   int x;
35
36   for (x = 0; x < (int)(sizeof(mpi_to_ltc_codes)/sizeof(mpi_to_ltc_codes[0])); x++) {
37       if (err == mpi_to_ltc_codes[x].mpi_code) {
38          return mpi_to_ltc_codes[x].ltc_code;
39       }
40   }
41   return CRYPT_ERROR;
42}
43
44static int init(void **a)
45{
46   int err;
47
48   LTC_ARGCHK(a != NULL);
49
50   *a = XCALLOC(1, sizeof(mp_int));
51   if (*a == NULL) {
52      return CRYPT_MEM;
53   }
54
55   if ((err = mpi_to_ltc_error(mp_init(*a))) != CRYPT_OK) {
56      XFREE(*a);
57   }
58   return err;
59}
60
61static void deinit(void *a)
62{
63   LTC_ARGCHKVD(a != NULL);
64   mp_clear(a);
65   XFREE(a);
66}
67
68static int neg(void *a, void *b)
69{
70   LTC_ARGCHK(a != NULL);
71   LTC_ARGCHK(b != NULL);
72   return mpi_to_ltc_error(mp_neg(a, b));
73}
74
75static int copy(void *a, void *b)
76{
77   LTC_ARGCHK(a != NULL);
78   LTC_ARGCHK(b != NULL);
79   return mpi_to_ltc_error(mp_copy(a, b));
80}
81
82static int init_copy(void **a, void *b)
83{
84   if (init(a) != CRYPT_OK) {
85      return CRYPT_MEM;
86   }
87   return copy(b, *a);
88}
89
90/* ---- trivial ---- */
91static int set_int(void *a, unsigned long b)
92{
93   LTC_ARGCHK(a != NULL);
94   return mpi_to_ltc_error(mp_set_int(a, b));
95}
96
97static unsigned long get_int(void *a)
98{
99   LTC_ARGCHK(a != NULL);
100   return mp_get_int(a);
101}
102
103static unsigned long get_digit(void *a, int n)
104{
105   mp_int *A;
106   LTC_ARGCHK(a != NULL);
107   A = a;
108   return (n >= A->used || n < 0) ? 0 : A->dp[n];
109}
110
111static int get_digit_count(void *a)
112{
113   mp_int *A;
114   LTC_ARGCHK(a != NULL);
115   A = a;
116   return A->used;
117}
118
119static int compare(void *a, void *b)
120{
121   int ret;
122   LTC_ARGCHK(a != NULL);
123   LTC_ARGCHK(b != NULL);
124   ret = mp_cmp(a, b);
125   switch (ret) {
126      case MP_LT: return LTC_MP_LT;
127      case MP_EQ: return LTC_MP_EQ;
128      case MP_GT: return LTC_MP_GT;
129   }
130   return 0;
131}
132
133static int compare_d(void *a, unsigned long b)
134{
135   int ret;
136   LTC_ARGCHK(a != NULL);
137   ret = mp_cmp_d(a, b);
138   switch (ret) {
139      case MP_LT: return LTC_MP_LT;
140      case MP_EQ: return LTC_MP_EQ;
141      case MP_GT: return LTC_MP_GT;
142   }
143   return 0;
144}
145
146static int count_bits(void *a)
147{
148   LTC_ARGCHK(a != NULL);
149   return mp_count_bits(a);
150}
151
152static int count_lsb_bits(void *a)
153{
154   LTC_ARGCHK(a != NULL);
155   return mp_cnt_lsb(a);
156}
157
158
159static int twoexpt(void *a, int n)
160{
161   LTC_ARGCHK(a != NULL);
162   return mpi_to_ltc_error(mp_2expt(a, n));
163}
164
165/* ---- conversions ---- */
166
167/* read ascii string */
168static int read_radix(void *a, const char *b, int radix)
169{
170   LTC_ARGCHK(a != NULL);
171   LTC_ARGCHK(b != NULL);
172   return mpi_to_ltc_error(mp_read_radix(a, b, radix));
173}
174
175/* write one */
176static int write_radix(void *a, char *b, int radix)
177{
178   LTC_ARGCHK(a != NULL);
179   LTC_ARGCHK(b != NULL);
180   return mpi_to_ltc_error(mp_toradix(a, b, radix));
181}
182
183/* get size as unsigned char string */
184static unsigned long unsigned_size(void *a)
185{
186   LTC_ARGCHK(a != NULL);
187   return mp_unsigned_bin_size(a);
188}
189
190/* store */
191static int unsigned_write(void *a, unsigned char *b)
192{
193   LTC_ARGCHK(a != NULL);
194   LTC_ARGCHK(b != NULL);
195   return mpi_to_ltc_error(mp_to_unsigned_bin(a, b));
196}
197
198/* read */
199static int unsigned_read(void *a, unsigned char *b, unsigned long len)
200{
201   LTC_ARGCHK(a != NULL);
202   LTC_ARGCHK(b != NULL);
203   return mpi_to_ltc_error(mp_read_unsigned_bin(a, b, len));
204}
205
206/* add */
207static int add(void *a, void *b, void *c)
208{
209   LTC_ARGCHK(a != NULL);
210   LTC_ARGCHK(b != NULL);
211   LTC_ARGCHK(c != NULL);
212   return mpi_to_ltc_error(mp_add(a, b, c));
213}
214
215static int addi(void *a, unsigned long b, void *c)
216{
217   LTC_ARGCHK(a != NULL);
218   LTC_ARGCHK(c != NULL);
219   return mpi_to_ltc_error(mp_add_d(a, b, c));
220}
221
222/* sub */
223static int sub(void *a, void *b, void *c)
224{
225   LTC_ARGCHK(a != NULL);
226   LTC_ARGCHK(b != NULL);
227   LTC_ARGCHK(c != NULL);
228   return mpi_to_ltc_error(mp_sub(a, b, c));
229}
230
231static int subi(void *a, unsigned long b, void *c)
232{
233   LTC_ARGCHK(a != NULL);
234   LTC_ARGCHK(c != NULL);
235   return mpi_to_ltc_error(mp_sub_d(a, b, c));
236}
237
238/* mul */
239static int mul(void *a, void *b, void *c)
240{
241   LTC_ARGCHK(a != NULL);
242   LTC_ARGCHK(b != NULL);
243   LTC_ARGCHK(c != NULL);
244   return mpi_to_ltc_error(mp_mul(a, b, c));
245}
246
247static int muli(void *a, unsigned long b, void *c)
248{
249   LTC_ARGCHK(a != NULL);
250   LTC_ARGCHK(c != NULL);
251   return mpi_to_ltc_error(mp_mul_d(a, b, c));
252}
253
254/* sqr */
255static int sqr(void *a, void *b)
256{
257   LTC_ARGCHK(a != NULL);
258   LTC_ARGCHK(b != NULL);
259   return mpi_to_ltc_error(mp_sqr(a, b));
260}
261
262/* div */
263static int divide(void *a, void *b, void *c, void *d)
264{
265   LTC_ARGCHK(a != NULL);
266   LTC_ARGCHK(b != NULL);
267   return mpi_to_ltc_error(mp_div(a, b, c, d));
268}
269
270static int div_2(void *a, void *b)
271{
272   LTC_ARGCHK(a != NULL);
273   LTC_ARGCHK(b != NULL);
274   return mpi_to_ltc_error(mp_div_2(a, b));
275}
276
277/* modi */
278static int modi(void *a, unsigned long b, unsigned long *c)
279{
280   mp_digit tmp;
281   int      err;
282
283   LTC_ARGCHK(a != NULL);
284   LTC_ARGCHK(c != NULL);
285
286   if ((err = mpi_to_ltc_error(mp_mod_d(a, b, &tmp))) != CRYPT_OK) {
287      return err;
288   }
289   *c = tmp;
290   return CRYPT_OK;
291}
292
293/* gcd */
294static int gcd(void *a, void *b, void *c)
295{
296   LTC_ARGCHK(a != NULL);
297   LTC_ARGCHK(b != NULL);
298   LTC_ARGCHK(c != NULL);
299   return mpi_to_ltc_error(mp_gcd(a, b, c));
300}
301
302/* lcm */
303static int lcm(void *a, void *b, void *c)
304{
305   LTC_ARGCHK(a != NULL);
306   LTC_ARGCHK(b != NULL);
307   LTC_ARGCHK(c != NULL);
308   return mpi_to_ltc_error(mp_lcm(a, b, c));
309}
310
311static int mulmod(void *a, void *b, void *c, void *d)
312{
313   LTC_ARGCHK(a != NULL);
314   LTC_ARGCHK(b != NULL);
315   LTC_ARGCHK(c != NULL);
316   LTC_ARGCHK(d != NULL);
317   return mpi_to_ltc_error(mp_mulmod(a,b,c,d));
318}
319
320static int sqrmod(void *a, void *b, void *c)
321{
322   LTC_ARGCHK(a != NULL);
323   LTC_ARGCHK(b != NULL);
324   LTC_ARGCHK(c != NULL);
325   return mpi_to_ltc_error(mp_sqrmod(a,b,c));
326}
327
328/* invmod */
329static int invmod(void *a, void *b, void *c)
330{
331   LTC_ARGCHK(a != NULL);
332   LTC_ARGCHK(b != NULL);
333   LTC_ARGCHK(c != NULL);
334   return mpi_to_ltc_error(mp_invmod(a, b, c));
335}
336
337/* setup */
338static int montgomery_setup(void *a, void **b)
339{
340   int err;
341   LTC_ARGCHK(a != NULL);
342   LTC_ARGCHK(b != NULL);
343   *b = XCALLOC(1, sizeof(mp_digit));
344   if (*b == NULL) {
345      return CRYPT_MEM;
346   }
347   if ((err = mpi_to_ltc_error(mp_montgomery_setup(a, (mp_digit *)*b))) != CRYPT_OK) {
348      XFREE(*b);
349   }
350   return err;
351}
352
353/* get normalization value */
354static int montgomery_normalization(void *a, void *b)
355{
356   LTC_ARGCHK(a != NULL);
357   LTC_ARGCHK(b != NULL);
358   return mpi_to_ltc_error(mp_montgomery_calc_normalization(a, b));
359}
360
361/* reduce */
362static int montgomery_reduce(void *a, void *b, void *c)
363{
364   LTC_ARGCHK(a != NULL);
365   LTC_ARGCHK(b != NULL);
366   LTC_ARGCHK(c != NULL);
367   return mpi_to_ltc_error(mp_montgomery_reduce(a, b, *((mp_digit *)c)));
368}
369
370/* clean up */
371static void montgomery_deinit(void *a)
372{
373   XFREE(a);
374}
375
376static int exptmod(void *a, void *b, void *c, void *d)
377{
378   LTC_ARGCHK(a != NULL);
379   LTC_ARGCHK(b != NULL);
380   LTC_ARGCHK(c != NULL);
381   LTC_ARGCHK(d != NULL);
382   return mpi_to_ltc_error(mp_exptmod(a,b,c,d));
383}
384
385static int isprime(void *a, int *b)
386{
387   int err;
388   LTC_ARGCHK(a != NULL);
389   LTC_ARGCHK(b != NULL);
390   err = mpi_to_ltc_error(mp_prime_is_prime(a, 8, b));
391   *b = (*b == MP_YES) ? LTC_MP_YES : LTC_MP_NO;
392   return err;
393}
394
395const ltc_math_descriptor ltm_desc = {
396
397   "LibTomMath",
398   (int)DIGIT_BIT,
399
400   &init,
401   &init_copy,
402   &deinit,
403
404   &neg,
405   &copy,
406
407   &set_int,
408   &get_int,
409   &get_digit,
410   &get_digit_count,
411   &compare,
412   &compare_d,
413   &count_bits,
414   &count_lsb_bits,
415   &twoexpt,
416
417   &read_radix,
418   &write_radix,
419   &unsigned_size,
420   &unsigned_write,
421   &unsigned_read,
422
423   &add,
424   &addi,
425   &sub,
426   &subi,
427   &mul,
428   &muli,
429   &sqr,
430   &divide,
431   &div_2,
432   &modi,
433   &gcd,
434   &lcm,
435
436   &mulmod,
437   &sqrmod,
438   &invmod,
439
440   &montgomery_setup,
441   &montgomery_normalization,
442   &montgomery_reduce,
443   &montgomery_deinit,
444
445   &exptmod,
446   &isprime,
447
448#ifdef MECC
449#ifdef MECC_FP
450   &ltc_ecc_fp_mulmod,
451#else
452   &ltc_ecc_mulmod,
453#endif
454   &ltc_ecc_projective_add_point,
455   &ltc_ecc_projective_dbl_point,
456   &ltc_ecc_map,
457#ifdef LTC_ECC_SHAMIR
458#ifdef MECC_FP
459   &ltc_ecc_fp_mul2add,
460#else
461   &ltc_ecc_mul2add,
462#endif /* MECC_FP */
463#else
464   NULL,
465#endif /* LTC_ECC_SHAMIR */
466#else
467   NULL, NULL, NULL, NULL, NULL,
468#endif /* MECC */
469
470#ifdef MRSA
471   &rsa_make_key,
472   &rsa_exptmod,
473#else
474   NULL, NULL
475#endif
476};
477
478
479#endif
480
481/* $Source: /cvs/libtom/libtomcrypt/src/math/ltm_desc.c,v $ */
482/* $Revision: 1.29 $ */
483/* $Date: 2006/12/03 00:39:56 $ */
484