1  /*
2   * Big number math
3   * Copyright (c) 2006, Jouni Malinen <j@w1.fi>
4   *
5   * This software may be distributed under the terms of the BSD license.
6   * See README for more details.
7   */
8  
9  #include "includes.h"
10  
11  #include "common.h"
12  #include "bignum.h"
13  
14  #ifdef CONFIG_INTERNAL_LIBTOMMATH
15  #include "libtommath.c"
16  #else /* CONFIG_INTERNAL_LIBTOMMATH */
17  #include <tommath.h>
18  #endif /* CONFIG_INTERNAL_LIBTOMMATH */
19  
20  
21  /*
22   * The current version is just a wrapper for LibTomMath library, so
23   * struct bignum is just typecast to mp_int.
24   */
25  
26  /**
27   * bignum_init - Allocate memory for bignum
28   * Returns: Pointer to allocated bignum or %NULL on failure
29   */
bignum_init(void)30  struct bignum * bignum_init(void)
31  {
32  	struct bignum *n = os_zalloc(sizeof(mp_int));
33  	if (n == NULL)
34  		return NULL;
35  	if (mp_init((mp_int *) n) != MP_OKAY) {
36  		os_free(n);
37  		n = NULL;
38  	}
39  	return n;
40  }
41  
42  
43  /**
44   * bignum_deinit - Free bignum
45   * @n: Bignum from bignum_init()
46   */
bignum_deinit(struct bignum * n)47  void bignum_deinit(struct bignum *n)
48  {
49  	if (n) {
50  		mp_clear((mp_int *) n);
51  		os_free(n);
52  	}
53  }
54  
55  
56  /**
57   * bignum_get_unsigned_bin - Get length of bignum as an unsigned binary buffer
58   * @n: Bignum from bignum_init()
59   * Returns: Length of n if written to a binary buffer
60   */
bignum_get_unsigned_bin_len(struct bignum * n)61  size_t bignum_get_unsigned_bin_len(struct bignum *n)
62  {
63  	return mp_unsigned_bin_size((mp_int *) n);
64  }
65  
66  
67  /**
68   * bignum_get_unsigned_bin - Set binary buffer to unsigned bignum
69   * @n: Bignum from bignum_init()
70   * @buf: Buffer for the binary number
71   * @len: Length of the buffer, can be %NULL if buffer is known to be long
72   * enough. Set to used buffer length on success if not %NULL.
73   * Returns: 0 on success, -1 on failure
74   */
bignum_get_unsigned_bin(const struct bignum * n,u8 * buf,size_t * len)75  int bignum_get_unsigned_bin(const struct bignum *n, u8 *buf, size_t *len)
76  {
77  	size_t need = mp_unsigned_bin_size((mp_int *) n);
78  	if (len && need > *len) {
79  		*len = need;
80  		return -1;
81  	}
82  	if (mp_to_unsigned_bin((mp_int *) n, buf) != MP_OKAY) {
83  		wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__);
84  		return -1;
85  	}
86  	if (len)
87  		*len = need;
88  	return 0;
89  }
90  
91  
92  /**
93   * bignum_set_unsigned_bin - Set bignum based on unsigned binary buffer
94   * @n: Bignum from bignum_init(); to be set to the given value
95   * @buf: Buffer with unsigned binary value
96   * @len: Length of buf in octets
97   * Returns: 0 on success, -1 on failure
98   */
bignum_set_unsigned_bin(struct bignum * n,const u8 * buf,size_t len)99  int bignum_set_unsigned_bin(struct bignum *n, const u8 *buf, size_t len)
100  {
101  	if (mp_read_unsigned_bin((mp_int *) n, (u8 *) buf, len) != MP_OKAY) {
102  		wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__);
103  		return -1;
104  	}
105  	return 0;
106  }
107  
108  
109  /**
110   * bignum_cmp - Signed comparison
111   * @a: Bignum from bignum_init()
112   * @b: Bignum from bignum_init()
113   * Returns: 0 on success, -1 on failure
114   */
bignum_cmp(const struct bignum * a,const struct bignum * b)115  int bignum_cmp(const struct bignum *a, const struct bignum *b)
116  {
117  	return mp_cmp((mp_int *) a, (mp_int *) b);
118  }
119  
120  
121  /**
122   * bignum_cmp_d - Compare bignum to standard integer
123   * @a: Bignum from bignum_init()
124   * @b: Small integer
125   * Returns: -1 if a < b, 0 if a == b, 1 if a > b
126   */
bignum_cmp_d(const struct bignum * a,unsigned long b)127  int bignum_cmp_d(const struct bignum *a, unsigned long b)
128  {
129  	return mp_cmp_d((mp_int *) a, b);
130  }
131  
132  
133  /**
134   * bignum_add - c = a + b
135   * @a: Bignum from bignum_init()
136   * @b: Bignum from bignum_init()
137   * @c: Bignum from bignum_init(); used to store the result of a + b
138   * Returns: 0 on success, -1 on failure
139   */
bignum_add(const struct bignum * a,const struct bignum * b,struct bignum * c)140  int bignum_add(const struct bignum *a, const struct bignum *b,
141  	       struct bignum *c)
142  {
143  	if (mp_add((mp_int *) a, (mp_int *) b, (mp_int *) c) != MP_OKAY) {
144  		wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__);
145  		return -1;
146  	}
147  	return 0;
148  }
149  
150  
151  /**
152   * bignum_sub - c = a - b
153   * @a: Bignum from bignum_init()
154   * @b: Bignum from bignum_init()
155   * @c: Bignum from bignum_init(); used to store the result of a - b
156   * Returns: 0 on success, -1 on failure
157   */
bignum_sub(const struct bignum * a,const struct bignum * b,struct bignum * c)158  int bignum_sub(const struct bignum *a, const struct bignum *b,
159  	       struct bignum *c)
160  {
161  	if (mp_sub((mp_int *) a, (mp_int *) b, (mp_int *) c) != MP_OKAY) {
162  		wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__);
163  		return -1;
164  	}
165  	return 0;
166  }
167  
168  
169  /**
170   * bignum_mul - c = a * b
171   * @a: Bignum from bignum_init()
172   * @b: Bignum from bignum_init()
173   * @c: Bignum from bignum_init(); used to store the result of a * b
174   * Returns: 0 on success, -1 on failure
175   */
bignum_mul(const struct bignum * a,const struct bignum * b,struct bignum * c)176  int bignum_mul(const struct bignum *a, const struct bignum *b,
177  	       struct bignum *c)
178  {
179  	if (mp_mul((mp_int *) a, (mp_int *) b, (mp_int *) c) != MP_OKAY) {
180  		wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__);
181  		return -1;
182  	}
183  	return 0;
184  }
185  
186  
187  /**
188   * bignum_mulmod - d = a * b (mod c)
189   * @a: Bignum from bignum_init()
190   * @b: Bignum from bignum_init()
191   * @c: Bignum from bignum_init(); modulus
192   * @d: Bignum from bignum_init(); used to store the result of a * b (mod c)
193   * Returns: 0 on success, -1 on failure
194   */
bignum_mulmod(const struct bignum * a,const struct bignum * b,const struct bignum * c,struct bignum * d)195  int bignum_mulmod(const struct bignum *a, const struct bignum *b,
196  		  const struct bignum *c, struct bignum *d)
197  {
198  	if (mp_mulmod((mp_int *) a, (mp_int *) b, (mp_int *) c, (mp_int *) d)
199  	    != MP_OKAY) {
200  		wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__);
201  		return -1;
202  	}
203  	return 0;
204  }
205  
206  
207  /**
208   * bignum_exptmod - Modular exponentiation: d = a^b (mod c)
209   * @a: Bignum from bignum_init(); base
210   * @b: Bignum from bignum_init(); exponent
211   * @c: Bignum from bignum_init(); modulus
212   * @d: Bignum from bignum_init(); used to store the result of a^b (mod c)
213   * Returns: 0 on success, -1 on failure
214   */
bignum_exptmod(const struct bignum * a,const struct bignum * b,const struct bignum * c,struct bignum * d)215  int bignum_exptmod(const struct bignum *a, const struct bignum *b,
216  		   const struct bignum *c, struct bignum *d)
217  {
218  	if (mp_exptmod((mp_int *) a, (mp_int *) b, (mp_int *) c, (mp_int *) d)
219  	    != MP_OKAY) {
220  		wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__);
221  		return -1;
222  	}
223  	return 0;
224  }
225