Xuyi Wang / wolfcrypt

Dependents:   OS

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers wolfmath.c Source File

wolfmath.c

00001 /* wolfmath.c
00002  *
00003  * Copyright (C) 2006-2017 wolfSSL Inc.
00004  *
00005  * This file is part of wolfSSL.
00006  *
00007  * wolfSSL is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * wolfSSL is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
00020  */
00021 
00022 
00023 /* common functions for either math library */
00024 
00025 #ifdef HAVE_CONFIG_H
00026     #include <config.h>
00027 #endif
00028 
00029 /* in case user set USE_FAST_MATH there */
00030 #include <wolfcrypt/settings.h>
00031 
00032 #ifdef USE_FAST_MATH
00033     #include <wolfcrypt/tfm.h>
00034 #else
00035     #include <wolfcrypt/integer.h>
00036 #endif
00037 
00038 #include <wolfcrypt/error-crypt.h>
00039 #include <wolfcrypt/logging.h>
00040 
00041 #if defined(USE_FAST_MATH) || !defined(NO_BIG_INT)
00042 
00043 #ifdef WOLFSSL_ASYNC_CRYPT
00044     #include <wolfcrypt/async.h>
00045 #endif
00046 
00047 #ifdef NO_INLINE
00048     #include <wolfcrypt/misc.h>
00049 #else
00050     #define WOLFSSL_MISC_INCLUDED
00051     #include <wolfcrypt/src/misc.c>
00052 #endif
00053 
00054 
00055 #if !defined(WC_NO_CACHE_RESISTANT) && \
00056     ((defined(HAVE_ECC) && defined(ECC_TIMING_RESISTANT)) || \
00057      (defined(USE_FAST_MATH) && defined(TFM_TIMING_RESISTANT)))
00058 
00059     /* all off / all on pointer addresses for constant calculations */
00060     /* ecc.c uses same table */
00061     const wolfssl_word wc_off_on_addr[2] =
00062     {
00063     #if defined(WC_64BIT_CPU)
00064         W64LIT(0x0000000000000000),
00065         W64LIT(0xffffffffffffffff)
00066     #elif defined(WC_16BIT_CPU)
00067         0x0000U,
00068         0xffffU
00069     #else
00070         /* 32 bit */
00071         0x00000000U,
00072         0xffffffffU
00073     #endif
00074     };
00075 #endif
00076 
00077 
00078 int get_digit_count(mp_int* a)
00079 {
00080     if (a == NULL)
00081         return 0;
00082 
00083     return a->used;
00084 }
00085 
00086 mp_digit get_digit(mp_int* a, int n)
00087 {
00088     if (a == NULL)
00089         return 0;
00090 
00091     return (n >= a->used || n < 0) ? 0 : a->dp[n];
00092 }
00093 
00094 int get_rand_digit(WC_RNG* rng, mp_digit* d)
00095 {
00096     return wc_RNG_GenerateBlock(rng, (byte*)d, sizeof(mp_digit));
00097 }
00098 
00099 #ifdef WC_RSA_BLINDING
00100 int mp_rand(mp_int* a, int digits, WC_RNG* rng)
00101 {
00102     int ret = 0;
00103     DECLARE_VAR(d, mp_digit, 1, rng->heap);
00104 
00105     if (rng == NULL) {
00106         ret = MISSING_RNG_E; goto exit;
00107     }
00108 
00109     if (a == NULL
00110     #ifdef WOLFSSL_ASYNC_CRYPT
00111         || d == NULL
00112     #endif
00113     ) {
00114         ret = BAD_FUNC_ARG; goto exit;
00115     }
00116 
00117     mp_zero(a);
00118     if (digits <= 0) {
00119         ret = MP_OKAY; goto exit;
00120     }
00121 
00122     /* first place a random non-zero digit */
00123     do {
00124         ret = get_rand_digit(rng, d);
00125         if (ret != 0) {
00126             goto exit;
00127         }
00128     } while (*d == 0);
00129 
00130     if ((ret = mp_add_d(a, *d, a)) != MP_OKAY) {
00131         goto exit;
00132     }
00133 
00134     while (--digits > 0) {
00135         if ((ret = mp_lshd(a, 1)) != MP_OKAY) {
00136             goto exit;
00137         }
00138         if ((ret = get_rand_digit(rng, d)) != 0) {
00139             goto exit;
00140         }
00141         if ((ret = mp_add_d(a, *d, a)) != MP_OKAY) {
00142             goto exit;
00143         }
00144     }
00145 
00146 exit:
00147     FREE_VAR(d, rng->heap);
00148 
00149     return ret;
00150 }
00151 #endif /* WC_RSA_BLINDING */
00152 
00153 
00154 #ifdef HAVE_WOLF_BIGINT
00155 void wc_bigint_init(WC_BIGINT* a)
00156 {
00157     if (a != NULL) {
00158         a->buf = NULL;
00159         a->len = 0;
00160         a->heap = NULL;
00161     }
00162 }
00163 
00164 int wc_bigint_alloc(WC_BIGINT* a, word32 sz)
00165 {
00166     int err = MP_OKAY;
00167 
00168     if (a == NULL)
00169         return BAD_FUNC_ARG;
00170 
00171     if (sz > 0) {
00172         if (a->buf && sz > a->len) {
00173             wc_bigint_free(a);
00174         }
00175         if (a->buf == NULL) {
00176             a->buf = (byte*)XMALLOC(sz, a->heap, DYNAMIC_TYPE_WOLF_BIGINT);
00177         }
00178         if (a->buf == NULL) {
00179             err = MP_MEM;
00180         }
00181         else {
00182             XMEMSET(a->buf, 0, sz);
00183         }
00184     }
00185     a->len = sz;
00186 
00187     return err;
00188 }
00189 
00190 /* assumes input is big endian format */
00191 int wc_bigint_from_unsigned_bin(WC_BIGINT* a, const byte* in, word32 inlen)
00192 {
00193     int err;
00194 
00195     if (a == NULL || in == NULL || inlen == 0)
00196         return BAD_FUNC_ARG;
00197 
00198     err = wc_bigint_alloc(a, inlen);
00199     if (err == 0) {
00200         XMEMCPY(a->buf, in, inlen);
00201     }
00202 
00203     return err;
00204 }
00205 
00206 int wc_bigint_to_unsigned_bin(WC_BIGINT* a, byte* out, word32* outlen)
00207 {
00208     word32 sz;
00209 
00210     if (a == NULL || out == NULL || outlen == NULL || *outlen == 0)
00211         return BAD_FUNC_ARG;
00212 
00213     /* trim to fit into output buffer */
00214     sz = a->len;
00215     if (a->len > *outlen) {
00216         WOLFSSL_MSG("wc_bigint_export: Truncating output");
00217         sz = *outlen;
00218     }
00219 
00220     if (a->buf) {
00221         XMEMCPY(out, a->buf, sz);
00222     }
00223 
00224     *outlen = sz;
00225 
00226     return MP_OKAY;
00227 }
00228 
00229 void wc_bigint_zero(WC_BIGINT* a)
00230 {
00231     if (a && a->buf) {
00232         ForceZero(a->buf, a->len);
00233     }
00234 }
00235 
00236 void wc_bigint_free(WC_BIGINT* a)
00237 {
00238     if (a) {
00239         if (a->buf) {
00240           XFREE(a->buf, a->heap, DYNAMIC_TYPE_WOLF_BIGINT);
00241         }
00242         a->buf = NULL;
00243         a->len = 0;
00244     }
00245 }
00246 
00247 /* sz: make sure the buffer is at least that size and zero padded.
00248  *     A `sz == 0` will use the size of `src`.
00249  *     The calulcates sz is stored into dst->len in `wc_bigint_alloc`.
00250  */
00251 int wc_mp_to_bigint_sz(mp_int* src, WC_BIGINT* dst, word32 sz)
00252 {
00253     int err;
00254     word32 x, y;
00255 
00256     if (src == NULL || dst == NULL)
00257         return BAD_FUNC_ARG;
00258 
00259     /* get size of source */
00260     x = mp_unsigned_bin_size(src);
00261     if (sz < x)
00262         sz = x;
00263 
00264     /* make sure destination is allocated and large enough */
00265     err = wc_bigint_alloc(dst, sz);
00266     if (err == MP_OKAY) {
00267 
00268         /* leading zero pad */
00269         y = sz - x;
00270         XMEMSET(dst->buf, 0, y);
00271 
00272         /* export src as unsigned bin to destination buf */
00273         err = mp_to_unsigned_bin(src, dst->buf + y);
00274     }
00275 
00276     return err;
00277 }
00278 
00279 int wc_mp_to_bigint(mp_int* src, WC_BIGINT* dst)
00280 {
00281     if (src == NULL || dst == NULL)
00282         return BAD_FUNC_ARG;
00283 
00284     return wc_mp_to_bigint_sz(src, dst, 0);
00285 }
00286 
00287 int wc_bigint_to_mp(WC_BIGINT* src, mp_int* dst)
00288 {
00289     int err;
00290 
00291     if (src == NULL || dst == NULL)
00292         return BAD_FUNC_ARG;
00293 
00294     if (src->buf == NULL)
00295         return BAD_FUNC_ARG;
00296 
00297     err = mp_read_unsigned_bin(dst, src->buf, src->len);
00298     wc_bigint_free(src);
00299 
00300     return err;
00301 }
00302 
00303 #endif /* HAVE_WOLF_BIGINT */
00304 
00305 #endif /* USE_FAST_MATH || !NO_BIG_INT */
00306