| b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame] | 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_cmp_d - Compare bignum to standard integer | 
|  | 123 | * @a: Bignum from bignum_init() | 
|  | 124 | * @b: Small integer | 
|  | 125 | * Returns: -1 if a < b, 0 if a == b, 1 if a > b | 
|  | 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 | } |