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