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