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