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  */
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  */
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  */
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  */
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  */
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  */
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_cmd_d - Compare bignum to standard integer
123  * @a: Bignum from bignum_init()
124  * @b: Small integer
125  * Returns: 0 on success, -1 on failure
126  */
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  */
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  */
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  */
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  */
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  */
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