Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: MiniTLS-HTTPS-Example
tfm.h
00001 /* TomsFastMath, a fast ISO C bignum library. 00002 * 00003 * This project is meant to fill in where LibTomMath 00004 * falls short. That is speed ;-) 00005 * 00006 * This project is public domain and free for all purposes. 00007 * 00008 * Tom St Denis, tomstdenis@gmail.com 00009 */ 00010 #ifndef TFM_H_ 00011 #define TFM_H_ 00012 00013 #include <stdio.h> 00014 #include <string.h> 00015 #include <stdint.h> 00016 #include <stdlib.h> 00017 #include <ctype.h> 00018 #include <limits.h> 00019 00020 /* Specific Config */ 00021 #include "inc/minitls_config.h" 00022 #define TFM_ECC192 CRYPTO_ECC192 //Enable stuff needed for ECC 192 computations 00023 #define TFM_NO_ASM 1 00024 #define TFM_TIMING_RESISTANT //Slower but fixed computation times and lower stack usage 00025 #define FP_MAX_SIZE 2*(DIGIT_BIT+CRYPTO_MAX_KEY_SIZE)//ECC192 max 00026 00027 /* */ 00028 00029 #ifndef MIN 00030 #define MIN(x,y) ((x)<(y)?(x):(y)) 00031 #endif 00032 00033 #ifndef MAX 00034 #define MAX(x,y) ((x)>(y)?(x):(y)) 00035 #endif 00036 00037 /* externally define this symbol to ignore the default settings, useful for changing the build from the make process */ 00038 #ifndef TFM_ALREADY_SET 00039 00040 /* do we want the large set of small multiplications ? 00041 Enable these if you are going to be doing a lot of small (<= 16 digit) multiplications say in ECC 00042 Or if you're on a 64-bit machine doing RSA as a 1024-bit integer == 16 digits ;-) 00043 */ 00044 //#define TFM_SMALL_SET 00045 00046 /* do we want huge code 00047 Enable these if you are doing 20, 24, 28, 32, 48, 64 digit multiplications (useful for RSA) 00048 Less important on 64-bit machines as 32 digits == 2048 bits 00049 */ 00050 #if 0 //DG 00051 #if 0 00052 #define TFM_MUL3 00053 #define TFM_MUL4 00054 #define TFM_MUL6 00055 #define TFM_MUL7 00056 #define TFM_MUL8 00057 #define TFM_MUL9 00058 #define TFM_MUL12 00059 #define TFM_MUL17 00060 #endif 00061 #define TFM_MUL20 00062 #define TFM_MUL24 00063 #define TFM_MUL28 00064 #define TFM_MUL32 00065 #define TFM_MUL48 00066 #define TFM_MUL64 00067 #if 0 00068 #define TFM_SQR3 00069 #define TFM_SQR4 00070 #define TFM_SQR6 00071 #define TFM_SQR7 00072 #define TFM_SQR8 00073 #define TFM_SQR9 00074 #define TFM_SQR12 00075 #define TFM_SQR17 00076 #endif 00077 #define TFM_SQR20 00078 #define TFM_SQR24 00079 #define TFM_SQR28 00080 #define TFM_SQR32 00081 #define TFM_SQR48 00082 #define TFM_SQR64 00083 #endif 00084 00085 /* do we want some overflow checks 00086 Not required if you make sure your numbers are within range (e.g. by default a modulus for fp_exptmod() can only be upto 2048 bits long) 00087 */ 00088 /* #define TFM_CHECK */ 00089 00090 /* Is the target a P4 Prescott 00091 */ 00092 /* #define TFM_PRESCOTT */ 00093 00094 /* Do we want timing resistant fp_exptmod() ? 00095 * This makes it slower but also timing invariant with respect to the exponent 00096 */ 00097 //#define TFM_TIMING_RESISTANT 00098 00099 #endif 00100 00101 /* Max size of any number in bits. Basically the largest size you will be multiplying 00102 * should be half [or smaller] of FP_MAX_SIZE-four_digit 00103 * 00104 * You can externally define this or it defaults to 4096-bits [allowing multiplications upto 2048x2048 bits ] 00105 */ 00106 #ifndef FP_MAX_SIZE 00107 #define FP_MAX_SIZE (4096+(8*DIGIT_BIT)) 00108 #endif 00109 00110 /* will this lib work? */ 00111 #if (CHAR_BIT & 7) 00112 #error CHAR_BIT must be a multiple of eight. 00113 #endif 00114 #if FP_MAX_SIZE % CHAR_BIT 00115 #error FP_MAX_SIZE must be a multiple of CHAR_BIT 00116 #endif 00117 00118 /* autodetect x86-64 and make sure we are using 64-bit digits with x86-64 asm */ 00119 #if defined(__x86_64__) 00120 #if defined(TFM_X86) || defined(TFM_SSE2) || defined(TFM_ARM) 00121 #error x86-64 detected, x86-32/SSE2/ARM optimizations are not valid! 00122 #endif 00123 #if !defined(TFM_X86_64) && !defined(TFM_NO_ASM) 00124 #define TFM_X86_64 00125 #endif 00126 #endif 00127 #if defined(TFM_X86_64) 00128 #if !defined(FP_64BIT) 00129 #define FP_64BIT 00130 #endif 00131 #endif 00132 00133 /* try to detect x86-32 */ 00134 #if defined(__i386__) && !defined(TFM_SSE2) 00135 #if defined(TFM_X86_64) || defined(TFM_ARM) 00136 #error x86-32 detected, x86-64/ARM optimizations are not valid! 00137 #endif 00138 #if !defined(TFM_X86) && !defined(TFM_NO_ASM) 00139 #define TFM_X86 00140 #endif 00141 #endif 00142 00143 /* make sure we're 32-bit for x86-32/sse/arm/ppc32 */ 00144 #if (defined(TFM_X86) || defined(TFM_SSE2) || defined(TFM_ARM) || defined(TFM_PPC32)) && defined(FP_64BIT) 00145 #warning x86-32, SSE2 and ARM, PPC32 optimizations require 32-bit digits (undefining) 00146 #undef FP_64BIT 00147 #endif 00148 00149 /* multi asms? */ 00150 #ifdef TFM_X86 00151 #define TFM_ASM 00152 #endif 00153 #ifdef TFM_X86_64 00154 #ifdef TFM_ASM 00155 #error TFM_ASM already defined! 00156 #endif 00157 #define TFM_ASM 00158 #endif 00159 #ifdef TFM_SSE2 00160 #ifdef TFM_ASM 00161 #error TFM_ASM already defined! 00162 #endif 00163 #define TFM_ASM 00164 #endif 00165 #ifdef TFM_ARM 00166 #ifdef TFM_ASM 00167 #error TFM_ASM already defined! 00168 #endif 00169 #define TFM_ASM 00170 #endif 00171 #ifdef TFM_PPC32 00172 #ifdef TFM_ASM 00173 #error TFM_ASM already defined! 00174 #endif 00175 #define TFM_ASM 00176 #endif 00177 #ifdef TFM_PPC64 00178 #ifdef TFM_ASM 00179 #error TFM_ASM already defined! 00180 #endif 00181 #define TFM_ASM 00182 #endif 00183 #ifdef TFM_AVR32 00184 #ifdef TFM_ASM 00185 #error TFM_ASM already defined! 00186 #endif 00187 #define TFM_ASM 00188 #endif 00189 00190 /* we want no asm? */ 00191 #ifdef TFM_NO_ASM 00192 #undef TFM_X86 00193 #undef TFM_X86_64 00194 #undef TFM_SSE2 00195 #undef TFM_ARM 00196 #undef TFM_PPC32 00197 #undef TFM_PPC64 00198 #undef TFM_AVR32 00199 #undef TFM_ASM 00200 #endif 00201 00202 /* ECC helpers */ 00203 #ifdef TFM_ECC192 00204 #ifdef FP_64BIT 00205 #define TFM_MUL3 00206 #define TFM_SQR3 00207 #else 00208 #define TFM_MUL6 00209 #define TFM_SQR6 00210 #endif 00211 #endif 00212 00213 #ifdef TFM_ECC224 00214 #ifdef FP_64BIT 00215 #define TFM_MUL4 00216 #define TFM_SQR4 00217 #else 00218 #define TFM_MUL7 00219 #define TFM_SQR7 00220 #endif 00221 #endif 00222 00223 #ifdef TFM_ECC256 00224 #ifdef FP_64BIT 00225 #define TFM_MUL4 00226 #define TFM_SQR4 00227 #else 00228 #define TFM_MUL8 00229 #define TFM_SQR8 00230 #endif 00231 #endif 00232 00233 #ifdef TFM_ECC384 00234 #ifdef FP_64BIT 00235 #define TFM_MUL6 00236 #define TFM_SQR6 00237 #else 00238 #define TFM_MUL12 00239 #define TFM_SQR12 00240 #endif 00241 #endif 00242 00243 #ifdef TFM_ECC521 00244 #ifdef FP_64BIT 00245 #define TFM_MUL9 00246 #define TFM_SQR9 00247 #else 00248 #define TFM_MUL17 00249 #define TFM_SQR17 00250 #endif 00251 #endif 00252 00253 00254 /* some default configurations. 00255 */ 00256 #if 0 00257 #if defined(FP_64BIT) 00258 /* for GCC only on supported platforms */ 00259 #ifndef CRYPT 00260 typedef unsigned long ulong64; 00261 #endif 00262 typedef ulong64 fp_digit; 00263 typedef unsigned long fp_word __attribute__ ((mode(TI))); 00264 #else 00265 /* this is to make porting into LibTomCrypt easier :-) */ 00266 #ifndef CRYPT 00267 #if defined(_MSC_VER) || defined(__BORLANDC__) 00268 typedef unsigned __int64 ulong64; 00269 typedef signed __int64 long64; 00270 #else 00271 typedef unsigned long long ulong64; 00272 typedef signed long long long64; 00273 #endif 00274 #endif 00275 typedef unsigned long fp_digit; 00276 typedef ulong64 fp_word; 00277 #endif 00278 #endif 00279 00280 typedef uint32_t fp_digit; 00281 typedef uint64_t fp_word; 00282 00283 /* # of digits this is */ 00284 #define DIGIT_BIT (int)((CHAR_BIT) * sizeof(fp_digit)) 00285 #define FP_MASK (fp_digit)(-1) 00286 #define FP_SIZE (FP_MAX_SIZE/DIGIT_BIT) 00287 00288 /* signs */ 00289 #define FP_ZPOS 0 00290 #define FP_NEG 1 00291 00292 /* return codes */ 00293 #include "inc/minitls_errors.h" 00294 #define FP_OKAY MINITLS_OK 00295 #define FP_VAL MINITLS_ERR_PARAMETERS 00296 #define FP_MEM MINITLS_ERR_MEMORY 00297 00298 /* equalities */ 00299 #define FP_LT -1 /* less than */ 00300 #define FP_EQ 0 /* equal to */ 00301 #define FP_GT 1 /* greater than */ 00302 00303 /* replies */ 00304 #define FP_YES 1 /* yes response */ 00305 #define FP_NO 0 /* no response */ 00306 00307 /* a FP type */ 00308 typedef struct { 00309 fp_digit dp[FP_SIZE]; 00310 int used, 00311 sign; 00312 } fp_int; 00313 00314 /* functions */ 00315 00316 /* returns a TFM ident string useful for debugging... */ 00317 const char *fp_ident(void); 00318 00319 /* initialize [or zero] an fp int */ 00320 #define fp_init(a) (void)memset((a), 0, sizeof(fp_int)) 00321 #define fp_zero(a) fp_init(a) 00322 00323 /* zero/even/odd ? */ 00324 #define fp_iszero(a) (((a)->used == 0) ? FP_YES : FP_NO) 00325 #define fp_iseven(a) (((a)->used >= 0 && (((a)->dp[0] & 1) == 0)) ? FP_YES : FP_NO) 00326 #define fp_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? FP_YES : FP_NO) 00327 00328 /* set to a small digit */ 00329 void fp_set(fp_int *a, fp_digit b); 00330 00331 /* copy from a to b */ 00332 #define fp_copy(a, b) (void)(((a) != (b)) && memcpy((b), (a), sizeof(fp_int))) 00333 #define fp_init_copy(a, b) fp_copy(b, a) 00334 00335 /* clamp digits */ 00336 #define fp_clamp(a) { while ((a)->used && (a)->dp[(a)->used-1] == 0) --((a)->used); (a)->sign = (a)->used ? (a)->sign : FP_ZPOS; } 00337 00338 /* negate and absolute */ 00339 #define fp_neg(a, b) { fp_copy(a, b); (b)->sign ^= 1; fp_clamp(b); } 00340 #define fp_abs(a, b) { fp_copy(a, b); (b)->sign = 0; } 00341 00342 /* right shift x digits */ 00343 void fp_rshd(fp_int *a, int x); 00344 00345 /* left shift x digits */ 00346 void fp_lshd(fp_int *a, int x); 00347 00348 /* signed comparison */ 00349 int fp_cmp(fp_int *a, fp_int *b); 00350 00351 /* unsigned comparison */ 00352 int fp_cmp_mag(fp_int *a, fp_int *b); 00353 00354 /* power of 2 operations */ 00355 void fp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d); 00356 void fp_mod_2d(fp_int *a, int b, fp_int *c); 00357 void fp_mul_2d(fp_int *a, int b, fp_int *c); 00358 void fp_2expt (fp_int *a, int b); 00359 void fp_mul_2(fp_int *a, fp_int *c); 00360 void fp_div_2(fp_int *a, fp_int *c); 00361 00362 /* Counts the number of lsbs which are zero before the first zero bit */ 00363 int fp_cnt_lsb(fp_int *a); 00364 00365 /* c = a + b */ 00366 void fp_add(fp_int *a, fp_int *b, fp_int *c); 00367 00368 /* c = a - b */ 00369 void fp_sub(fp_int *a, fp_int *b, fp_int *c); 00370 00371 /* c = a * b */ 00372 void fp_mul(fp_int *a, fp_int *b, fp_int *c); 00373 00374 /* b = a*a */ 00375 void fp_sqr(fp_int *a, fp_int *b); 00376 00377 /* a/b => cb + d == a */ 00378 int fp_div(fp_int *a, fp_int *b, fp_int *c, fp_int *d); 00379 00380 /* c = a mod b, 0 <= c < b */ 00381 int fp_mod(fp_int *a, fp_int *b, fp_int *c); 00382 00383 /* compare against a single digit */ 00384 int fp_cmp_d(fp_int *a, fp_digit b); 00385 00386 /* c = a + b */ 00387 void fp_add_d(fp_int *a, fp_digit b, fp_int *c); 00388 00389 /* c = a - b */ 00390 void fp_sub_d(fp_int *a, fp_digit b, fp_int *c); 00391 00392 /* c = a * b */ 00393 void fp_mul_d(fp_int *a, fp_digit b, fp_int *c); 00394 00395 /* a/b => cb + d == a */ 00396 int fp_div_d(fp_int *a, fp_digit b, fp_int *c, fp_digit *d); 00397 00398 /* c = a mod b, 0 <= c < b */ 00399 int fp_mod_d(fp_int *a, fp_digit b, fp_digit *c); 00400 00401 /* ---> number theory <--- */ 00402 /* d = a + b (mod c) */ 00403 int fp_addmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d); 00404 00405 /* d = a - b (mod c) */ 00406 int fp_submod(fp_int *a, fp_int *b, fp_int *c, fp_int *d); 00407 00408 /* d = a * b (mod c) */ 00409 int fp_mulmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d); 00410 00411 /* c = a * a (mod b) */ 00412 int fp_sqrmod(fp_int *a, fp_int *b, fp_int *c); 00413 00414 /* c = 1/a (mod b) */ 00415 int fp_invmod(fp_int *a, fp_int *b, fp_int *c); 00416 00417 /* c = (a, b) */ 00418 void fp_gcd(fp_int *a, fp_int *b, fp_int *c); 00419 00420 /* c = [a, b] */ 00421 void fp_lcm(fp_int *a, fp_int *b, fp_int *c); 00422 00423 /* setups the montgomery reduction */ 00424 int fp_montgomery_setup(fp_int *a, fp_digit *mp); 00425 00426 /* computes a = B**n mod b without division or multiplication useful for 00427 * normalizing numbers in a Montgomery system. 00428 */ 00429 void fp_montgomery_calc_normalization(fp_int *a, fp_int *b); 00430 00431 /* computes x/R == x (mod N) via Montgomery Reduction */ 00432 void fp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp); 00433 00434 /* d = a**b (mod c) */ 00435 int fp_exptmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d); 00436 00437 /* primality stuff */ 00438 00439 /* perform a Miller-Rabin test of a to the base b and store result in "result" */ 00440 void fp_prime_miller_rabin (fp_int * a, fp_int * b, int *result); 00441 00442 /* 256 trial divisions + 8 Miller-Rabins, returns FP_YES if probable prime */ 00443 int fp_isprime(fp_int *a); 00444 00445 /* Primality generation flags */ 00446 #define TFM_PRIME_BBS 0x0001 /* BBS style prime */ 00447 #define TFM_PRIME_SAFE 0x0002 /* Safe prime (p-1)/2 == prime */ 00448 #define TFM_PRIME_2MSB_OFF 0x0004 /* force 2nd MSB to 0 */ 00449 #define TFM_PRIME_2MSB_ON 0x0008 /* force 2nd MSB to 1 */ 00450 00451 /* callback for fp_prime_random, should fill dst with random bytes and return how many read [upto len] */ 00452 typedef int tfm_prime_callback(unsigned char *dst, int len, void *dat); 00453 00454 #define fp_prime_random(a, t, size, bbs, cb, dat) fp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?TFM_PRIME_BBS:0, cb, dat) 00455 00456 int fp_prime_random_ex(fp_int *a, int t, int size, int flags, tfm_prime_callback cb, void *dat); 00457 00458 /* radix conersions */ 00459 int fp_count_bits(fp_int *a); 00460 00461 int fp_unsigned_bin_size(fp_int *a); 00462 void fp_read_unsigned_bin(fp_int *a, unsigned char *b, int c); 00463 void fp_to_unsigned_bin(fp_int *a, unsigned char *b); 00464 00465 int fp_signed_bin_size(fp_int *a); 00466 void fp_read_signed_bin(fp_int *a, unsigned char *b, int c); 00467 void fp_to_signed_bin(fp_int *a, unsigned char *b); 00468 00469 int fp_read_radix(fp_int *a, char *str, int radix); 00470 int fp_toradix(fp_int *a, char *str, int radix); 00471 int fp_toradix_n(fp_int * a, char *str, int radix, int maxlen); 00472 00473 00474 /* VARIOUS LOW LEVEL STUFFS */ 00475 void s_fp_add(fp_int *a, fp_int *b, fp_int *c); 00476 void s_fp_sub(fp_int *a, fp_int *b, fp_int *c); 00477 void fp_reverse(unsigned char *s, int len); 00478 00479 void fp_mul_comba(fp_int *A, fp_int *B, fp_int *C); 00480 00481 #ifdef TFM_SMALL_SET 00482 void fp_mul_comba_small(fp_int *A, fp_int *B, fp_int *C); 00483 #endif 00484 00485 #ifdef TFM_MUL3 00486 void fp_mul_comba3(fp_int *A, fp_int *B, fp_int *C); 00487 #endif 00488 #ifdef TFM_MUL4 00489 void fp_mul_comba4(fp_int *A, fp_int *B, fp_int *C); 00490 #endif 00491 #ifdef TFM_MUL6 00492 void fp_mul_comba6(fp_int *A, fp_int *B, fp_int *C); 00493 #endif 00494 #ifdef TFM_MUL7 00495 void fp_mul_comba7(fp_int *A, fp_int *B, fp_int *C); 00496 #endif 00497 #ifdef TFM_MUL8 00498 void fp_mul_comba8(fp_int *A, fp_int *B, fp_int *C); 00499 #endif 00500 #ifdef TFM_MUL9 00501 void fp_mul_comba9(fp_int *A, fp_int *B, fp_int *C); 00502 #endif 00503 #ifdef TFM_MUL12 00504 void fp_mul_comba12(fp_int *A, fp_int *B, fp_int *C); 00505 #endif 00506 #ifdef TFM_MUL17 00507 void fp_mul_comba17(fp_int *A, fp_int *B, fp_int *C); 00508 #endif 00509 00510 #ifdef TFM_MUL20 00511 void fp_mul_comba20(fp_int *A, fp_int *B, fp_int *C); 00512 #endif 00513 #ifdef TFM_MUL24 00514 void fp_mul_comba24(fp_int *A, fp_int *B, fp_int *C); 00515 #endif 00516 #ifdef TFM_MUL28 00517 void fp_mul_comba28(fp_int *A, fp_int *B, fp_int *C); 00518 #endif 00519 #ifdef TFM_MUL32 00520 void fp_mul_comba32(fp_int *A, fp_int *B, fp_int *C); 00521 #endif 00522 #ifdef TFM_MUL48 00523 void fp_mul_comba48(fp_int *A, fp_int *B, fp_int *C); 00524 #endif 00525 #ifdef TFM_MUL64 00526 void fp_mul_comba64(fp_int *A, fp_int *B, fp_int *C); 00527 #endif 00528 00529 void fp_sqr_comba(fp_int *A, fp_int *B); 00530 00531 #ifdef TFM_SMALL_SET 00532 void fp_sqr_comba_small(fp_int *A, fp_int *B); 00533 #endif 00534 00535 #ifdef TFM_SQR3 00536 void fp_sqr_comba3(fp_int *A, fp_int *B); 00537 #endif 00538 #ifdef TFM_SQR4 00539 void fp_sqr_comba4(fp_int *A, fp_int *B); 00540 #endif 00541 #ifdef TFM_SQR6 00542 void fp_sqr_comba6(fp_int *A, fp_int *B); 00543 #endif 00544 #ifdef TFM_SQR7 00545 void fp_sqr_comba7(fp_int *A, fp_int *B); 00546 #endif 00547 #ifdef TFM_SQR8 00548 void fp_sqr_comba8(fp_int *A, fp_int *B); 00549 #endif 00550 #ifdef TFM_SQR9 00551 void fp_sqr_comba9(fp_int *A, fp_int *B); 00552 #endif 00553 #ifdef TFM_SQR12 00554 void fp_sqr_comba12(fp_int *A, fp_int *B); 00555 #endif 00556 #ifdef TFM_SQR17 00557 void fp_sqr_comba17(fp_int *A, fp_int *B); 00558 #endif 00559 00560 #ifdef TFM_SQR20 00561 void fp_sqr_comba20(fp_int *A, fp_int *B); 00562 #endif 00563 #ifdef TFM_SQR24 00564 void fp_sqr_comba24(fp_int *A, fp_int *B); 00565 #endif 00566 #ifdef TFM_SQR28 00567 void fp_sqr_comba28(fp_int *A, fp_int *B); 00568 #endif 00569 #ifdef TFM_SQR32 00570 void fp_sqr_comba32(fp_int *A, fp_int *B); 00571 #endif 00572 #ifdef TFM_SQR48 00573 void fp_sqr_comba48(fp_int *A, fp_int *B); 00574 #endif 00575 #ifdef TFM_SQR64 00576 void fp_sqr_comba64(fp_int *A, fp_int *B); 00577 #endif 00578 extern const char *fp_s_rmap; 00579 00580 #endif 00581 00582 00583 /* $Source: /cvs/libtom/tomsfastmath/src/headers/tfm.h,v $ */ 00584 /* $Revision: 1.3 $ */ 00585 /* $Date: 2007/02/27 02:38:44 $ */
Generated on Wed Jul 13 2022 00:22:54 by
1.7.2