16d49e1aeSJan Lentfer /*
26d49e1aeSJan Lentfer * Big number math
36d49e1aeSJan Lentfer * Copyright (c) 2006, Jouni Malinen <j@w1.fi>
46d49e1aeSJan Lentfer *
53ff40c12SJohn Marino * This software may be distributed under the terms of the BSD license.
63ff40c12SJohn Marino * See README for more details.
76d49e1aeSJan Lentfer */
86d49e1aeSJan Lentfer
96d49e1aeSJan Lentfer #include "includes.h"
106d49e1aeSJan Lentfer
116d49e1aeSJan Lentfer #include "common.h"
126d49e1aeSJan Lentfer #include "bignum.h"
136d49e1aeSJan Lentfer
146d49e1aeSJan Lentfer #ifdef CONFIG_INTERNAL_LIBTOMMATH
156d49e1aeSJan Lentfer #include "libtommath.c"
166d49e1aeSJan Lentfer #else /* CONFIG_INTERNAL_LIBTOMMATH */
176d49e1aeSJan Lentfer #include <tommath.h>
186d49e1aeSJan Lentfer #endif /* CONFIG_INTERNAL_LIBTOMMATH */
196d49e1aeSJan Lentfer
206d49e1aeSJan Lentfer
216d49e1aeSJan Lentfer /*
226d49e1aeSJan Lentfer * The current version is just a wrapper for LibTomMath library, so
236d49e1aeSJan Lentfer * struct bignum is just typecast to mp_int.
246d49e1aeSJan Lentfer */
256d49e1aeSJan Lentfer
266d49e1aeSJan Lentfer /**
276d49e1aeSJan Lentfer * bignum_init - Allocate memory for bignum
286d49e1aeSJan Lentfer * Returns: Pointer to allocated bignum or %NULL on failure
296d49e1aeSJan Lentfer */
bignum_init(void)306d49e1aeSJan Lentfer struct bignum * bignum_init(void)
316d49e1aeSJan Lentfer {
326d49e1aeSJan Lentfer struct bignum *n = os_zalloc(sizeof(mp_int));
336d49e1aeSJan Lentfer if (n == NULL)
346d49e1aeSJan Lentfer return NULL;
356d49e1aeSJan Lentfer if (mp_init((mp_int *) n) != MP_OKAY) {
366d49e1aeSJan Lentfer os_free(n);
376d49e1aeSJan Lentfer n = NULL;
386d49e1aeSJan Lentfer }
396d49e1aeSJan Lentfer return n;
406d49e1aeSJan Lentfer }
416d49e1aeSJan Lentfer
426d49e1aeSJan Lentfer
436d49e1aeSJan Lentfer /**
446d49e1aeSJan Lentfer * bignum_deinit - Free bignum
456d49e1aeSJan Lentfer * @n: Bignum from bignum_init()
466d49e1aeSJan Lentfer */
bignum_deinit(struct bignum * n)476d49e1aeSJan Lentfer void bignum_deinit(struct bignum *n)
486d49e1aeSJan Lentfer {
496d49e1aeSJan Lentfer if (n) {
506d49e1aeSJan Lentfer mp_clear((mp_int *) n);
516d49e1aeSJan Lentfer os_free(n);
526d49e1aeSJan Lentfer }
536d49e1aeSJan Lentfer }
546d49e1aeSJan Lentfer
556d49e1aeSJan Lentfer
566d49e1aeSJan Lentfer /**
576d49e1aeSJan Lentfer * bignum_get_unsigned_bin - Get length of bignum as an unsigned binary buffer
586d49e1aeSJan Lentfer * @n: Bignum from bignum_init()
596d49e1aeSJan Lentfer * Returns: Length of n if written to a binary buffer
606d49e1aeSJan Lentfer */
bignum_get_unsigned_bin_len(struct bignum * n)616d49e1aeSJan Lentfer size_t bignum_get_unsigned_bin_len(struct bignum *n)
626d49e1aeSJan Lentfer {
636d49e1aeSJan Lentfer return mp_unsigned_bin_size((mp_int *) n);
646d49e1aeSJan Lentfer }
656d49e1aeSJan Lentfer
666d49e1aeSJan Lentfer
676d49e1aeSJan Lentfer /**
686d49e1aeSJan Lentfer * bignum_get_unsigned_bin - Set binary buffer to unsigned bignum
696d49e1aeSJan Lentfer * @n: Bignum from bignum_init()
706d49e1aeSJan Lentfer * @buf: Buffer for the binary number
716d49e1aeSJan Lentfer * @len: Length of the buffer, can be %NULL if buffer is known to be long
726d49e1aeSJan Lentfer * enough. Set to used buffer length on success if not %NULL.
736d49e1aeSJan Lentfer * Returns: 0 on success, -1 on failure
746d49e1aeSJan Lentfer */
bignum_get_unsigned_bin(const struct bignum * n,u8 * buf,size_t * len)756d49e1aeSJan Lentfer int bignum_get_unsigned_bin(const struct bignum *n, u8 *buf, size_t *len)
766d49e1aeSJan Lentfer {
776d49e1aeSJan Lentfer size_t need = mp_unsigned_bin_size((mp_int *) n);
786d49e1aeSJan Lentfer if (len && need > *len) {
796d49e1aeSJan Lentfer *len = need;
806d49e1aeSJan Lentfer return -1;
816d49e1aeSJan Lentfer }
826d49e1aeSJan Lentfer if (mp_to_unsigned_bin((mp_int *) n, buf) != MP_OKAY) {
836d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__);
846d49e1aeSJan Lentfer return -1;
856d49e1aeSJan Lentfer }
866d49e1aeSJan Lentfer if (len)
876d49e1aeSJan Lentfer *len = need;
886d49e1aeSJan Lentfer return 0;
896d49e1aeSJan Lentfer }
906d49e1aeSJan Lentfer
916d49e1aeSJan Lentfer
926d49e1aeSJan Lentfer /**
936d49e1aeSJan Lentfer * bignum_set_unsigned_bin - Set bignum based on unsigned binary buffer
946d49e1aeSJan Lentfer * @n: Bignum from bignum_init(); to be set to the given value
956d49e1aeSJan Lentfer * @buf: Buffer with unsigned binary value
966d49e1aeSJan Lentfer * @len: Length of buf in octets
976d49e1aeSJan Lentfer * Returns: 0 on success, -1 on failure
986d49e1aeSJan Lentfer */
bignum_set_unsigned_bin(struct bignum * n,const u8 * buf,size_t len)996d49e1aeSJan Lentfer int bignum_set_unsigned_bin(struct bignum *n, const u8 *buf, size_t len)
1006d49e1aeSJan Lentfer {
1016d49e1aeSJan Lentfer if (mp_read_unsigned_bin((mp_int *) n, (u8 *) buf, len) != MP_OKAY) {
1026d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__);
1036d49e1aeSJan Lentfer return -1;
1046d49e1aeSJan Lentfer }
1056d49e1aeSJan Lentfer return 0;
1066d49e1aeSJan Lentfer }
1076d49e1aeSJan Lentfer
1086d49e1aeSJan Lentfer
1096d49e1aeSJan Lentfer /**
1106d49e1aeSJan Lentfer * bignum_cmp - Signed comparison
1116d49e1aeSJan Lentfer * @a: Bignum from bignum_init()
1126d49e1aeSJan Lentfer * @b: Bignum from bignum_init()
1136d49e1aeSJan Lentfer * Returns: 0 on success, -1 on failure
1146d49e1aeSJan Lentfer */
bignum_cmp(const struct bignum * a,const struct bignum * b)1156d49e1aeSJan Lentfer int bignum_cmp(const struct bignum *a, const struct bignum *b)
1166d49e1aeSJan Lentfer {
1176d49e1aeSJan Lentfer return mp_cmp((mp_int *) a, (mp_int *) b);
1186d49e1aeSJan Lentfer }
1196d49e1aeSJan Lentfer
1206d49e1aeSJan Lentfer
1216d49e1aeSJan Lentfer /**
122*a1157835SDaniel Fojt * bignum_cmp_d - Compare bignum to standard integer
1236d49e1aeSJan Lentfer * @a: Bignum from bignum_init()
1246d49e1aeSJan Lentfer * @b: Small integer
125*a1157835SDaniel Fojt * Returns: -1 if a < b, 0 if a == b, 1 if a > b
1266d49e1aeSJan Lentfer */
bignum_cmp_d(const struct bignum * a,unsigned long b)1276d49e1aeSJan Lentfer int bignum_cmp_d(const struct bignum *a, unsigned long b)
1286d49e1aeSJan Lentfer {
1296d49e1aeSJan Lentfer return mp_cmp_d((mp_int *) a, b);
1306d49e1aeSJan Lentfer }
1316d49e1aeSJan Lentfer
1326d49e1aeSJan Lentfer
1336d49e1aeSJan Lentfer /**
1346d49e1aeSJan Lentfer * bignum_add - c = a + b
1356d49e1aeSJan Lentfer * @a: Bignum from bignum_init()
1366d49e1aeSJan Lentfer * @b: Bignum from bignum_init()
1376d49e1aeSJan Lentfer * @c: Bignum from bignum_init(); used to store the result of a + b
1386d49e1aeSJan Lentfer * Returns: 0 on success, -1 on failure
1396d49e1aeSJan Lentfer */
bignum_add(const struct bignum * a,const struct bignum * b,struct bignum * c)1406d49e1aeSJan Lentfer int bignum_add(const struct bignum *a, const struct bignum *b,
1416d49e1aeSJan Lentfer struct bignum *c)
1426d49e1aeSJan Lentfer {
1436d49e1aeSJan Lentfer if (mp_add((mp_int *) a, (mp_int *) b, (mp_int *) c) != MP_OKAY) {
1446d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__);
1456d49e1aeSJan Lentfer return -1;
1466d49e1aeSJan Lentfer }
1476d49e1aeSJan Lentfer return 0;
1486d49e1aeSJan Lentfer }
1496d49e1aeSJan Lentfer
1506d49e1aeSJan Lentfer
1516d49e1aeSJan Lentfer /**
1526d49e1aeSJan Lentfer * bignum_sub - c = a - b
1536d49e1aeSJan Lentfer * @a: Bignum from bignum_init()
1546d49e1aeSJan Lentfer * @b: Bignum from bignum_init()
1556d49e1aeSJan Lentfer * @c: Bignum from bignum_init(); used to store the result of a - b
1566d49e1aeSJan Lentfer * Returns: 0 on success, -1 on failure
1576d49e1aeSJan Lentfer */
bignum_sub(const struct bignum * a,const struct bignum * b,struct bignum * c)1586d49e1aeSJan Lentfer int bignum_sub(const struct bignum *a, const struct bignum *b,
1596d49e1aeSJan Lentfer struct bignum *c)
1606d49e1aeSJan Lentfer {
1616d49e1aeSJan Lentfer if (mp_sub((mp_int *) a, (mp_int *) b, (mp_int *) c) != MP_OKAY) {
1626d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__);
1636d49e1aeSJan Lentfer return -1;
1646d49e1aeSJan Lentfer }
1656d49e1aeSJan Lentfer return 0;
1666d49e1aeSJan Lentfer }
1676d49e1aeSJan Lentfer
1686d49e1aeSJan Lentfer
1696d49e1aeSJan Lentfer /**
1706d49e1aeSJan Lentfer * bignum_mul - c = a * b
1716d49e1aeSJan Lentfer * @a: Bignum from bignum_init()
1726d49e1aeSJan Lentfer * @b: Bignum from bignum_init()
1736d49e1aeSJan Lentfer * @c: Bignum from bignum_init(); used to store the result of a * b
1746d49e1aeSJan Lentfer * Returns: 0 on success, -1 on failure
1756d49e1aeSJan Lentfer */
bignum_mul(const struct bignum * a,const struct bignum * b,struct bignum * c)1766d49e1aeSJan Lentfer int bignum_mul(const struct bignum *a, const struct bignum *b,
1776d49e1aeSJan Lentfer struct bignum *c)
1786d49e1aeSJan Lentfer {
1796d49e1aeSJan Lentfer if (mp_mul((mp_int *) a, (mp_int *) b, (mp_int *) c) != MP_OKAY) {
1806d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__);
1816d49e1aeSJan Lentfer return -1;
1826d49e1aeSJan Lentfer }
1836d49e1aeSJan Lentfer return 0;
1846d49e1aeSJan Lentfer }
1856d49e1aeSJan Lentfer
1866d49e1aeSJan Lentfer
1876d49e1aeSJan Lentfer /**
1886d49e1aeSJan Lentfer * bignum_mulmod - d = a * b (mod c)
1896d49e1aeSJan Lentfer * @a: Bignum from bignum_init()
1906d49e1aeSJan Lentfer * @b: Bignum from bignum_init()
1916d49e1aeSJan Lentfer * @c: Bignum from bignum_init(); modulus
1926d49e1aeSJan Lentfer * @d: Bignum from bignum_init(); used to store the result of a * b (mod c)
1936d49e1aeSJan Lentfer * Returns: 0 on success, -1 on failure
1946d49e1aeSJan Lentfer */
bignum_mulmod(const struct bignum * a,const struct bignum * b,const struct bignum * c,struct bignum * d)1956d49e1aeSJan Lentfer int bignum_mulmod(const struct bignum *a, const struct bignum *b,
1966d49e1aeSJan Lentfer const struct bignum *c, struct bignum *d)
1976d49e1aeSJan Lentfer {
1986d49e1aeSJan Lentfer if (mp_mulmod((mp_int *) a, (mp_int *) b, (mp_int *) c, (mp_int *) d)
1996d49e1aeSJan Lentfer != MP_OKAY) {
2006d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__);
2016d49e1aeSJan Lentfer return -1;
2026d49e1aeSJan Lentfer }
2036d49e1aeSJan Lentfer return 0;
2046d49e1aeSJan Lentfer }
2056d49e1aeSJan Lentfer
2066d49e1aeSJan Lentfer
2076d49e1aeSJan Lentfer /**
2086d49e1aeSJan Lentfer * bignum_exptmod - Modular exponentiation: d = a^b (mod c)
2096d49e1aeSJan Lentfer * @a: Bignum from bignum_init(); base
2106d49e1aeSJan Lentfer * @b: Bignum from bignum_init(); exponent
2116d49e1aeSJan Lentfer * @c: Bignum from bignum_init(); modulus
2126d49e1aeSJan Lentfer * @d: Bignum from bignum_init(); used to store the result of a^b (mod c)
2136d49e1aeSJan Lentfer * Returns: 0 on success, -1 on failure
2146d49e1aeSJan Lentfer */
bignum_exptmod(const struct bignum * a,const struct bignum * b,const struct bignum * c,struct bignum * d)2156d49e1aeSJan Lentfer int bignum_exptmod(const struct bignum *a, const struct bignum *b,
2166d49e1aeSJan Lentfer const struct bignum *c, struct bignum *d)
2176d49e1aeSJan Lentfer {
2186d49e1aeSJan Lentfer if (mp_exptmod((mp_int *) a, (mp_int *) b, (mp_int *) c, (mp_int *) d)
2196d49e1aeSJan Lentfer != MP_OKAY) {
2206d49e1aeSJan Lentfer wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__);
2216d49e1aeSJan Lentfer return -1;
2226d49e1aeSJan Lentfer }
2236d49e1aeSJan Lentfer return 0;
2246d49e1aeSJan Lentfer }
225