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