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