diff --git a/aes.c b/aes.c index c1bf568..4d63992 100644 --- a/aes.c +++ b/aes.c @@ -327,6 +327,9 @@ void rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_ int rijndael_test(void) { + #ifndef LTC_TEST + return CRYPT_NOP; + #else int errno; static const struct { int keylen; @@ -377,6 +380,7 @@ int rijndael_test(void) } } return CRYPT_OK; + #endif } int rijndael_keysize(int *desired_keysize) diff --git a/ampi.c b/ampi.c deleted file mode 100644 index 2d015ca..0000000 --- a/ampi.c +++ /dev/null @@ -1,55 +0,0 @@ -/* Code submitted by Svante Seleborg, cleaned up by Tom St Denis */ - -#include "mycrypt.h" -#include - -#ifdef MPI - -mp_err mp_init_multi(mp_int *mp, ...) -{ - mp_err res = MP_OKAY; /* Assume ok until proven otherwise */ - int n = 0; /* Number of ok inits */ - mp_int* cur_arg = mp; - va_list args; - - va_start(args, mp); /* init args to next argument from caller */ - while (cur_arg != NULL) { - if (mp_init(cur_arg) != MP_OKAY) { - /* Oops - error! Back-track and mp_clear what we already - succeeded in init-ing, then return error. - */ - va_list clean_args; - cur_arg = mp; - va_start(clean_args, mp); - while (n--) { - mp_clear(cur_arg); - cur_arg = va_arg(clean_args, mp_int*); - } - va_end(clean_args); - res = MP_MEM; - break; - } - n++; - cur_arg = va_arg(args, mp_int*); - } - va_end(args); - return res; /* Assumed ok, if error flagged above. */ -} - -/* - Clear all arguments given, ended by a NULL marker. -*/ -void mp_clear_multi(mp_int *mp, ...) -{ - mp_int* next_mp = mp; - va_list args; - va_start(args, mp); - while (next_mp != NULL) { - mp_clear(next_mp); - next_mp = va_arg(args, mp_int*); - } - va_end(args); -} - -#endif - diff --git a/blowfish.c b/blowfish.c index db8fc1a..3b27e39 100644 --- a/blowfish.c +++ b/blowfish.c @@ -436,6 +436,9 @@ void blowfish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_ int blowfish_test(void) { + #ifndef LTC_TEST + return CRYPT_NOP; + #else int err; symmetric_key key; static const struct { @@ -476,6 +479,7 @@ int blowfish_test(void) } } return CRYPT_OK; + #endif } int blowfish_keysize(int *desired_keysize) diff --git a/cast5.c b/cast5.c index 77b6262..0969aaf 100644 --- a/cast5.c +++ b/cast5.c @@ -552,6 +552,9 @@ void cast5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key int cast5_test(void) { + #ifndef LTC_TEST + return CRYPT_NOP; + #else static const struct { int keylen; unsigned char key[16]; @@ -590,6 +593,7 @@ int cast5_test(void) } return CRYPT_OK; + #endif } int cast5_keysize(int *desired_keysize) diff --git a/changes b/changes index 4c7cdef..e2cf92d 100644 --- a/changes +++ b/changes @@ -1,3 +1,14 @@ +Jun 1st, 2003 +v0.84 -- Removed a 4KB buffer from rsa_decrypt_key that wasn't being used no more + -- Fixed another potential buffer problem. Not an overflow but could cause the + PK import routines to read past the end of the buffer. + -- Optimized the ECC mulmod more by removing a if condition that will always be false + -- Optimized prime.c to not include a 2nd prime table, removed code from is_prime calls prime + test from LibTomMath now + -- Added LTC_TEST define which when defined will enable the test vector routines [see mycrypt_custom.h] + -- Removed ampi.o from the depends cuz it ain't no not working in *nix with it [routines are in mpi.c now]. + + Mar 29th, 2003 v0.83 -- Optimized the ecc_mulmod, it's faster and takes less heap/stack space -- Fixed a free memory error in ecc_mulmod and del_point which would try to free NULL diff --git a/config.pl b/config.pl index 4f68282..cee3453 100644 --- a/config.pl +++ b/config.pl @@ -24,6 +24,7 @@ "SMALL_CODE,Use small code where possible (slower code),y", "NO_FILE,Avoid file I/O calls,n", "CLEAN_STACK,Clean the stack within functions,n", + "LTC_TEST,Include Test Vector Routines,y", "BLOWFISH,Include Blowfish block cipher,y", "RC2,Include RC2 block cipher,y", @@ -144,7 +145,7 @@ for (@settings) { # output objects print OUT "\ndefault: library\n\n"; -print OUT "OBJECTS = keyring.o gf.o mem.o sprng.o ecc.o base64.o dh.o rsa.o bits.o yarrow.o cfb.o ofb.o ecb.o ctr.o cbc.o hash.o tiger.o sha1.o md5.o md4.o md2.o sha256.o sha512.o xtea.o aes.o serpent.o des.o safer_tab.o safer.o safer+.o rc4.o rc2.o rc6.o rc5.o cast5.o noekeon.o blowfish.o crypt.o ampi.o mpi.o prime.o twofish.o packet.o hmac.o strings.o\n\n"; +print OUT "OBJECTS = keyring.o gf.o mem.o sprng.o ecc.o base64.o dh.o rsa.o bits.o yarrow.o cfb.o ofb.o ecb.o ctr.o cbc.o hash.o tiger.o sha1.o md5.o md4.o md2.o sha256.o sha512.o xtea.o aes.o serpent.o des.o safer_tab.o safer.o safer+.o rc4.o rc2.o rc6.o rc5.o cast5.o noekeon.o blowfish.o crypt.o mpi.o prime.o twofish.o packet.o hmac.o strings.o\n\n"; # some depends print OUT "rsa.o: rsa_sys.c\ndh.o: dh_sys.c\necc.o: ecc_sys.c\n\n"; diff --git a/crypt.pdf b/crypt.pdf index a132eb0..0fe991a 100644 Binary files a/crypt.pdf and b/crypt.pdf differ diff --git a/crypt.tex b/crypt.tex index e3b23ef..3b64457 100644 --- a/crypt.tex +++ b/crypt.tex @@ -48,7 +48,7 @@ \def\gap{\vspace{0.5ex}} \makeindex \begin{document} -\title{A Tiny Crypto Library, \\ LibTomCrypt \\ Version 0.83} +\title{A Tiny Crypto Library, \\ LibTomCrypt \\ Version 0.84} \author{Tom St Denis \\ Algonquin College \\ \\ @@ -64,8 +64,8 @@ Canada \newpage \tableofcontents \chapter{Introduction} -\section{What is the Libtomcrypt?} -Libtomcrypt is a portable ANSI C cryptographic library that supports symmetric ciphers, one-way hashes, +\section{What is the LibTomCrypt?} +LibTomCrypt is a portable ANSI C cryptographic library that supports symmetric ciphers, one-way hashes, pseudo-random number generators, public key cryptography (via RSA,DH or ECC/DH) and a plethora of support routines. It is designed to compile out of the box with the GNU C Compiler (GCC) version 2.95.3 (and higher) and with MSVC version 6 in win32. @@ -932,12 +932,12 @@ int hash_filehandle(int hash, FILE *in, unsigned char *dst, unsigned long *outlen); \end{verbatim} -All three functions return {\bf CRYPT\_OK} on success, otherwise they return an error code. The ``hash'' parameter is -the location in the descriptor table of the hash. The ``*outlen'' variable is used to keep track of the output size. You +The ``hash'' parameter is the location in the descriptor table of the hash (\textit{e.g. the return of find\_hash()}). +The ``*outlen'' variable is used to keep track of the output size. You must set it to the size of your output buffer before calling the functions. When they complete succesfully they store the length of the message digest back in it. The functions are otherwise straightforward. The ``hash\_filehandle'' -function assumes that ``in'' is an file handle opened in binary mode. It will not reset the file position after -hashing the content. +function assumes that ``in'' is an file handle opened in binary mode. It will hash to the end of file and not reset +the file position when finished. To perform the above hash with md5 the following code could be used: \begin{small} @@ -993,7 +993,7 @@ int unregister_hash(const struct _hash_descriptor *hash); \end{verbatim} \subsection{Notice} -It is highly recommended that you not use the MD4 or MD5 hashes for the purposes of digital signatures or authentication codes. +It is highly recommended that you \textbf{not} use the MD4 or MD5 hashes for the purposes of digital signatures or authentication codes. These hashes are provided for completeness and they still can be used for the purposes of password hashing or one-way accumulators (e.g. Yarrow). @@ -1039,16 +1039,16 @@ int hmac_memory(int hash, const unsigned char *key, unsigned long keylen, unsigned char *dst, unsigned long *dstlen); \end{verbatim} This will produce an HMAC code for the array of octets in ``data'' of length ``len''. The index into the hash descriptor -table must be provided in ``hash'' it uses the key from ``key'' with a key length of ``keylen''. -The result is stored in the array of octets ``dst'' and the length in ``dstlen''. Similarly for files there is the -following function: +table must be provided in ``hash''. It uses the key from ``key'' with a key length of ``keylen''. +The result is stored in the array of octets ``dst'' and the length in ``dstlen''. The value of ``dstlen'' must be set +to the size of the destination buffer before calling this function. Similarly for files there is the following function: \begin{verbatim} int hmac_file(int hash, const char *fname, const unsigned char *key, unsigned long keylen, unsigned char *dst, unsigned long *dstlen); \end{verbatim} -``hash'' is the index into the hash descriptor table of the hash you want to use. ``fname'' is the filename to process. ``key'' -is the array of octets to use as the key. ``keylen'' is the length of the key. ``dst'' is the array of octets where the +``hash'' is the index into the hash descriptor table of the hash you want to use. ``fname'' is the filename to process. +``key'' is the array of octets to use as the key of length ``keylen''. ``dst'' is the array of octets where the result should be stored. To test if the HMAC code is working there is the following function: @@ -1378,7 +1378,7 @@ int rsa_make_key(prng_state *prng, Where ``wprng'' is the index into the PRNG descriptor array. ``size'' is the size in bytes of the RSA modulus desired. ``e'' is the encryption exponent desired, typical values are 3, 17, 257 and 65537. I suggest you stick with 65537 since its big enough to prevent trivial math attacks and not super slow. ``key'' is where the key is placed. All keys must be at -least 128 bytes and no more than 512 bytes in size (that is from 1024 to 4096 bits). +least 128 bytes and no more than 512 bytes in size (\textit{that is from 1024 to 4096 bits}). Note that the ``rsa\_make\_key()'' function allocates memory at runtime when you make the key. Make sure to call ``rsa\_free()'' (see below) when you are finished with the key. If ``rsa\_make\_key()'' fails it will automatically @@ -1408,22 +1408,21 @@ recipient who can RSA decrypt it and symmetrically decrypt the message. int rsa_encrypt_key(const unsigned char *inkey, unsigned long inlen, unsigned char *outkey, unsigned long *outlen, prng_state *prng, int wprng, rsa_key *key); +\end{verbatim} +This function is used to RSA encrypt a symmetric to share with another user. The symmetric key and its length are +passed as ``inkey'' and ``inlen'' respectively. The symmetric key is limited to a range of 8 to 32 bytes +(\textit{64 to 256 bits}). The RSA encrypted packet is stored in ``outkey'' and will be of length ``outlen'' bytes. The +value of ``outlen'' must be originally set to the size of the output buffer. +\begin{verbatim} int rsa_decrypt_key(const unsigned char *in, unsigned long inlen, unsigned char *outkey, unsigned long *keylen, rsa_key *key); \end{verbatim} -The ``rsa\_encrypt\_key()'' function accepts a symmetric key (limited to 32 bytes) as input in ``inkey''. ``inlen'' -is the size of the input key in bytes. The function will then ``rsa\_pad()'' the key and encrypt it using the RSA -algorithm. It will store the result in ``outkey'' along with the length in ``outlen''. - -The ``rsa\_decrypt\_key()'' function performs the opposite. The ``in'' variable is where the RSA packet of length -``inlen'' goes and it will store the original symmetric key in the ``outkey'' variable along with its length in -``keylen''. - -Similarly to sign or verify a hash of a message the following two messages are provided. The idea is to hash your -message then use these functions to RSA sign the hash. +This function will decrypt an RSA packet to retrieve the original symmetric key encrypted with rsa\_encrypt\_key(). +Similarly to sign or verify a hash of a message the following two messages are provided. The idea is to hash your message +then use these functions to RSA sign the hash. \begin{verbatim} int rsa_sign_hash(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, diff --git a/demos/test.c b/demos/test.c index d60051f..dcdceaf 100644 --- a/demos/test.c +++ b/demos/test.c @@ -14,21 +14,21 @@ int errnum; int null_setup (const unsigned char *key, int keylen, int num_rounds, - symmetric_key * skey) + symmetric_key * skey) { return CRYPT_OK; } void null_ecb_encrypt (const unsigned char *pt, unsigned char *ct, - symmetric_key * key) + symmetric_key * key) { memcpy (ct, pt, 8); } void null_ecb_decrypt (const unsigned char *ct, unsigned char *pt, - symmetric_key * key) + symmetric_key * key) { memcpy (pt, ct, 8); } @@ -156,7 +156,7 @@ cbc_tests (void) /* now lets start a cbc session */ if ((errnum = cbc_start (find_cipher ("blowfish"), IV, key, 16, 0, - &cbc)) != CRYPT_OK) { + &cbc)) != CRYPT_OK) { printf ("CBC Setup: %s\n", error_to_string (errnum)); exit (-1); } @@ -179,7 +179,7 @@ cbc_tests (void) /* now lets start a cbc session */ if ((errnum = cbc_start (find_cipher ("blowfish"), IV, key, 16, 0, - &cbc)) != CRYPT_OK) { + &cbc)) != CRYPT_OK) { printf ("CBC Setup: %s\n", error_to_string (errnum)); exit (-1); } @@ -201,12 +201,12 @@ cbc_tests (void) /* lets actually check the bytes */ memset (IV, 0, 8); - IV[0] = 0xFF; /* IV = FF 00 00 00 00 00 00 00 */ + IV[0] = 0xFF; /* IV = FF 00 00 00 00 00 00 00 */ memset (blk, 0, 32); - blk[8] = 0xFF; /* BLK = 00 00 00 00 00 00 00 00 FF 00 00 00 00 00 00 00 */ + blk[8] = 0xFF; /* BLK = 00 00 00 00 00 00 00 00 FF 00 00 00 00 00 00 00 */ cbc_start (find_cipher ("memcpy()"), IV, key, 8, 0, &cbc); - cbc_encrypt (blk, ct, &cbc); /* expect: FF 00 00 00 00 00 00 00 */ - cbc_encrypt (blk + 8, ct + 8, &cbc); /* expect: 00 00 00 00 00 00 00 00 */ + cbc_encrypt (blk, ct, &cbc); /* expect: FF 00 00 00 00 00 00 00 */ + cbc_encrypt (blk + 8, ct + 8, &cbc); /* expect: 00 00 00 00 00 00 00 00 */ if (memcmp (ct, test, 16)) { printf ("CBC failed logical testing.\n"); for (x = 0; x < 16; x++) @@ -309,7 +309,7 @@ cfb_tests (void) /* now lets start a cfb session */ if ((errnum = cfb_start (find_cipher ("blowfish"), IV, key, 16, 0, - &cfb)) != CRYPT_OK) { + &cfb)) != CRYPT_OK) { printf ("CFB setup: %s\n", error_to_string (errnum)); exit (-1); } @@ -332,7 +332,7 @@ cfb_tests (void) /* now lets start a cfb session */ if ((errnum = cfb_start (find_cipher ("blowfish"), IV, key, 16, 0, - &cfb)) != CRYPT_OK) { + &cfb)) != CRYPT_OK) { printf ("CFB Setup: %s\n", error_to_string (errnum)); exit (-1); } @@ -380,7 +380,7 @@ ctr_tests (void) /* now lets start a ctr session */ if ((errnum = ctr_start (find_cipher ("xtea"), count, key, 16, 0, - &ctr)) != CRYPT_OK) { + &ctr)) != CRYPT_OK) { printf ("CTR Setup: %s\n", error_to_string (errnum)); exit (-1); } @@ -403,7 +403,7 @@ ctr_tests (void) /* now lets start a cbc session */ if ((errnum = ctr_start (find_cipher ("xtea"), count, key, 16, 0, - &ctr)) != CRYPT_OK) { + &ctr)) != CRYPT_OK) { printf ("CTR Setup: %s\n", error_to_string (errnum)); exit (-1); } @@ -426,12 +426,12 @@ ctr_tests (void) /* lets actually check the bytes */ memset (count, 0, 8); - count[0] = 0xFF; /* IV = FF 00 00 00 00 00 00 00 */ + count[0] = 0xFF; /* IV = FF 00 00 00 00 00 00 00 */ memset (blk, 0, 32); - blk[9] = 2; /* BLK = 00 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 */ + blk[9] = 2; /* BLK = 00 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 */ ctr_start (find_cipher ("memcpy()"), count, key, 8, 0, &ctr); - ctr_encrypt (blk, ct, 8, &ctr); /* expect: FF 00 00 00 00 00 00 00 */ - ctr_encrypt (blk + 8, ct + 8, 8, &ctr); /* expect: 00 03 00 00 00 00 00 00 */ + ctr_encrypt (blk, ct, 8, &ctr); /* expect: FF 00 00 00 00 00 00 00 */ + ctr_encrypt (blk + 8, ct + 8, 8, &ctr); /* expect: 00 03 00 00 00 00 00 00 */ if (memcmp (ct, test, 16)) { printf ("CTR failed logical testing.\n"); for (x = 0; x < 16; x++) @@ -520,7 +520,7 @@ rsa_test (void) /* encrypt a short 8 byte string */ if ((errnum = rsa_make_key (&prng, find_prng ("yarrow"), 1024 / 8, 65537, - &key)) != CRYPT_OK) { + &key)) != CRYPT_OK) { printf ("Error: %s\n", error_to_string (errnum)); exit (-1); } @@ -555,7 +555,7 @@ rsa_test (void) y = sizeof (out); if ((errnum = rsa_encrypt_key (in, 16, out, &y, &prng, find_prng ("yarrow"), - &key)) != CRYPT_OK) { + &key)) != CRYPT_OK) { printf ("Error: %s\n", error_to_string (errnum)); exit (-1); } @@ -614,47 +614,47 @@ rsa_test (void) for (z = 1024; z <= limit; z += 512) { t = XCLOCK (); for (tt = 0; tt < 3; tt++) { - if ((errnum = - rsa_make_key (&prng, find_prng ("yarrow"), z / 8, 65537, - &key)) != CRYPT_OK) { - printf ("Error: %s\n", error_to_string (errnum)); - exit (-1); - } - if (tt < 2) - rsa_free (&key); + if ((errnum = + rsa_make_key (&prng, find_prng ("yarrow"), z / 8, 65537, + &key)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + if (tt < 2) + rsa_free (&key); } t = XCLOCK () - t; printf ("Took %.0f ms to make a %ld-bit RSA key.\n", - 1000.0 * (((double) t / 3.0) / (double) XCLOCKS_PER_SEC), z); + 1000.0 * (((double) t / 3.0) / (double) XCLOCKS_PER_SEC), z); /* time encryption */ t = XCLOCK (); - for (tt = 0; tt < 100; tt++) { - y = sizeof (in); - if ((errnum = - rsa_exptmod (in, 8, out, &y, PK_PUBLIC, &key)) != CRYPT_OK) { - printf ("Error: %s\n", error_to_string (errnum)); - exit (-1); - } + for (tt = 0; tt < 20; tt++) { + y = sizeof (in); + if ((errnum = + rsa_exptmod (in, 8, out, &y, PK_PUBLIC, &key)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } } t = XCLOCK () - t; printf ("Took %.0f ms to encrypt with a %ld-bit RSA key.\n", - 1000.0 * (((double) t / 100.0) / (double) XCLOCKS_PER_SEC), z); + 1000.0 * (((double) t / 20.0) / (double) XCLOCKS_PER_SEC), z); /* time decryption */ t = XCLOCK (); - for (tt = 0; tt < 100; tt++) { - x = sizeof (out); - if ((errnum = - rsa_exptmod (out, y, in, &x, PK_PRIVATE, &key)) != CRYPT_OK) { - printf ("Error: %s\n", error_to_string (errnum)); - exit (-1); - } + for (tt = 0; tt < 20; tt++) { + x = sizeof (out); + if ((errnum = + rsa_exptmod (out, y, in, &x, PK_PRIVATE, &key)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } } t = XCLOCK () - t; printf ("Took %.0f ms to decrypt with a %ld-bit RSA key.\n", - 1000.0 * (((double) t / 100.0) / (double) XCLOCKS_PER_SEC), z); + 1000.0 * (((double) t / 20.0) / (double) XCLOCKS_PER_SEC), z); rsa_free (&key); } } @@ -765,9 +765,9 @@ time_hash (void) } t1 = XCLOCK () - t1; printf ("%-20s: Hash at %5.2f Mbit/sec\n", hash_descriptor[x].name, - ((8.0 * 4096.0) * - ((double) y / ((double) t1 / (double) XCLOCKS_PER_SEC))) / - 1000000.0); + ((8.0 * 4096.0) * + ((double) y / ((double) t1 / (double) XCLOCKS_PER_SEC))) / + 1000000.0); } } @@ -783,7 +783,7 @@ time_ecb (void) printf ("ECB Time Trials for the Symmetric Ciphers:\n"); for (x = 0; cipher_descriptor[x].name != NULL; x++) { cipher_descriptor[x].setup (key, cipher_descriptor[x].min_key_length, 0, - &skey); + &skey); #define DO1 func(pt,pt,&skey); #define DO2 DO1 DO1 @@ -816,9 +816,9 @@ time_ecb (void) ("%-20s: Encrypt at %5.2f Mbit/sec and Decrypt at %5.2f Mbit/sec\n", cipher_descriptor[x].name, ((8.0 * (double) cipher_descriptor[x].block_length) * - ((double) y1 / ((double) t1 / (double) XCLOCKS_PER_SEC))) / 1000000.0, + ((double) y1 / ((double) t1 / (double) XCLOCKS_PER_SEC))) / 1000000.0, ((8.0 * (double) cipher_descriptor[x].block_length) * - ((double) y2 / ((double) t2 / (double) XCLOCKS_PER_SEC))) / + ((double) y2 / ((double) t2 / (double) XCLOCKS_PER_SEC))) / 1000000.0); #undef DO256 @@ -843,7 +843,7 @@ dh_tests (void) dh_key usera, userb; clock_t t1; -/* if ((errnum = dh_test()) != CRYPT_OK) printf("DH Error: %s\n", error_to_string(errnum)); */ +/* if ((errnum = dh_test()) != CRYPT_OK) printf("DH Error: %s\n", error_to_string(errnum)); */ dh_sizes (&low, &high); printf ("DH Keys from %d to %d supported.\n", low * 8, high * 8); @@ -921,12 +921,12 @@ dh_tests (void) for (ii = 0; ii < (int) (sizeof (sizes) / sizeof (sizes[0])); ii++) { t1 = XCLOCK (); for (tt = 0; tt < 5; tt++) { - dh_make_key (&prng, find_prng ("yarrow"), sizes[ii], &usera); - dh_free (&usera); + dh_make_key (&prng, find_prng ("yarrow"), sizes[ii], &usera); + dh_free (&usera); } t1 = XCLOCK () - t1; printf ("Make dh-%d key took %f msec\n", sizes[ii] * 8, - 1000.0 * (((double) t1 / 5.0) / (double) XCLOCKS_PER_SEC)); + 1000.0 * (((double) t1 / 5.0) / (double) XCLOCKS_PER_SEC)); } } @@ -937,7 +937,7 @@ dh_tests (void) y = sizeof (buf[1]); if ((errnum = dh_encrypt_key (buf[0], 16, buf[1], &y, &prng, find_prng ("yarrow"), - find_hash ("md5"), &usera)) != CRYPT_OK) { + find_hash ("md5"), &usera)) != CRYPT_OK) { printf ("Error: %s\n", error_to_string (errnum)); exit (-1); } @@ -965,7 +965,7 @@ dh_tests (void) x = sizeof (buf[1]); if ((errnum = dh_sign_hash (buf[0], 16, buf[1], &x, &prng, find_prng ("yarrow"), - &usera)) != CRYPT_OK) { + &usera)) != CRYPT_OK) { printf ("Error: %s\n", error_to_string (errnum)); exit (-1); } @@ -979,8 +979,8 @@ dh_tests (void) exit (-1); } printf ("dh_sign/verify_hash: %s (%d,%d), %lu\n", - ((stat == 1) - && (stat2 == 0)) ? "passed" : "failed", stat, stat2, x); + ((stat == 1) + && (stat2 == 0)) ? "passed" : "failed", stat, stat2, x); dh_free (&usera); } #else @@ -1013,7 +1013,7 @@ rng_tests (void) x = rng_get_bytes (buf, sizeof (buf), &callback); t1 = XCLOCK () - t1; printf (" %f bytes per second...", - (double) x / ((double) t1 / (double) XCLOCKS_PER_SEC)); + (double) x / ((double) t1 / (double) XCLOCKS_PER_SEC)); printf ("read %d bytes.\n ", x); for (y = 0; y < x; y++) printf ("%02x ", buf[y]); @@ -1022,7 +1022,7 @@ rng_tests (void) #ifdef YARROW if ((errnum = rng_make_prng (128, find_prng ("yarrow"), &prng, - &callback)) != CRYPT_OK) { + &callback)) != CRYPT_OK) { printf (" starting yarrow error: %s\n", error_to_string (errnum)); exit (-1); } @@ -1123,18 +1123,18 @@ ecc_tests (void) for (ii = 0; ii < (int) (sizeof (sizes) / sizeof (sizes[0])); ii++) { t1 = XCLOCK (); - for (tt = 0; tt < 25; tt++) { - if ((errnum = - ecc_make_key (&prng, find_prng ("yarrow"), sizes[ii], - &usera)) != CRYPT_OK) { - printf ("Error: %s\n", error_to_string (errnum)); - exit (-1); - } - ecc_free (&usera); + for (tt = 0; tt < 10; tt++) { + if ((errnum = + ecc_make_key (&prng, find_prng ("yarrow"), sizes[ii], + &usera)) != CRYPT_OK) { + printf ("Error: %s\n", error_to_string (errnum)); + exit (-1); + } + ecc_free (&usera); } t1 = XCLOCK () - t1; printf ("Make ECC-%d key took %f msec\n", sizes[ii] * 8, - 1000.0 * (((double) t1 / 25.0) / (double) XCLOCKS_PER_SEC)); + 1000.0 * (((double) t1 / 10.0) / (double) XCLOCKS_PER_SEC)); } } @@ -1145,7 +1145,7 @@ ecc_tests (void) y = sizeof (buf[1]); if ((errnum = ecc_encrypt_key (buf[0], 32, buf[1], &y, &prng, find_prng ("yarrow"), - find_hash ("sha256"), &usera)) != CRYPT_OK) { + find_hash ("sha256"), &usera)) != CRYPT_OK) { printf ("Error: %s\n", error_to_string (errnum)); exit (-1); } @@ -1172,7 +1172,7 @@ ecc_tests (void) x = sizeof (buf[1]); if ((errnum = ecc_sign_hash (buf[0], 16, buf[1], &x, &prng, find_prng ("yarrow"), - &usera)) != CRYPT_OK) { + &usera)) != CRYPT_OK) { printf ("Error: %s\n", error_to_string (errnum)); exit (-1); } @@ -1187,7 +1187,7 @@ ecc_tests (void) exit (-1); } printf ("ecc_sign/verify_hash: %s (%d,%d)\n", - ((stat == 1) && (stat2 == 0)) ? "passed" : "failed", stat, stat2); + ((stat == 1) && (stat2 == 0)) ? "passed" : "failed", stat, stat2); ecc_free (&usera); } #else @@ -1342,15 +1342,15 @@ register_all_algs (void) register_cipher (&null_desc); +#ifdef SHA1 + register_hash (&sha1_desc); +#endif #ifdef SHA256 register_hash (&sha256_desc); #endif #ifdef TIGER register_hash (&tiger_desc); #endif -#ifdef SHA1 - register_hash (&sha1_desc); -#endif #ifdef MD5 register_hash (&md5_desc); #endif @@ -1383,8 +1383,8 @@ kr_display (pk_key * kr) while (kr->system != NON_KEY) { printf ("CRC [%08lx], System [%10s], Type [%20s], %s, %s, %s\n", kr->ID, - sys[kr->system], type[kr->key_type], kr->name, kr->email, - kr->description); + sys[kr->system], type[kr->key_type], kr->name, kr->email, + kr->description); kr = kr->next; } printf ("\n"); @@ -1402,7 +1402,7 @@ kr_test_makekeys (pk_key ** kr) printf ("KR: Making DH key...\n"); if ((errnum = kr_make_key (*kr, &prng, find_prng ("yarrow"), DH_KEY, 128, "dhkey", - "dh@dh.dh", "dhkey one")) != CRYPT_OK) { + "dh@dh.dh", "dhkey one")) != CRYPT_OK) { printf ("Make key error: %s\n", error_to_string (errnum)); exit (-1); } @@ -1411,7 +1411,7 @@ kr_test_makekeys (pk_key ** kr) printf ("KR: Making ECC key...\n"); if ((errnum = kr_make_key (*kr, &prng, find_prng ("yarrow"), ECC_KEY, 20, "ecckey", - "ecc@ecc.ecc", "ecckey one")) != CRYPT_OK) { + "ecc@ecc.ecc", "ecckey one")) != CRYPT_OK) { printf ("Make key error: %s\n", error_to_string (errnum)); exit (-1); } @@ -1420,7 +1420,7 @@ kr_test_makekeys (pk_key ** kr) printf ("KR: Making RSA key...\n"); if ((errnum = kr_make_key (*kr, &prng, find_prng ("yarrow"), RSA_KEY, 128, "rsakey", - "rsa@rsa.rsa", "rsakey one")) != CRYPT_OK) { + "rsa@rsa.rsa", "rsakey one")) != CRYPT_OK) { printf ("Make key error: %s\n", error_to_string (errnum)); exit (-1); } @@ -1533,12 +1533,12 @@ kr_test (void) _kr = kr; for (i = 0; i < 3; i++) { printf ("Testing a key with system %d, type %d:\t", _kr->system, - _kr->key_type); + _kr->key_type); len = sizeof (buf2); if ((errnum = - kr_encrypt_key (kr, _kr->ID, buf, 16, buf2, &len, &prng, - find_prng ("yarrow"), - find_hash ("md5"))) != CRYPT_OK) { + kr_encrypt_key (kr, _kr->ID, buf, 16, buf2, &len, &prng, + find_prng ("yarrow"), + find_hash ("md5"))) != CRYPT_OK) { printf ("Encrypt error, %d, %s\n", i, error_to_string (errnum)); exit (-1); } @@ -1555,8 +1555,8 @@ kr_test (void) len = sizeof (buf2); if ((errnum = - kr_sign_hash (kr, _kr->ID, buf, 32, buf2, &len, &prng, - find_prng ("yarrow"))) != CRYPT_OK) { + kr_sign_hash (kr, _kr->ID, buf, 32, buf2, &len, &prng, + find_prng ("yarrow"))) != CRYPT_OK) { printf ("kr_sign_hash failed, %i, %s\n", i, error_to_string (errnum)); exit (-1); } @@ -1576,8 +1576,8 @@ kr_test (void) len = sizeof (buf); if ((errnum = - kr_fingerprint (kr, _kr->ID, find_hash ("sha1"), buf, - &len)) != CRYPT_OK) { + kr_fingerprint (kr, _kr->ID, find_hash ("sha1"), buf, + &len)) != CRYPT_OK) { printf ("kr_fingerprint failed, %i, %lu\n", i, len); exit (-1); } @@ -1585,7 +1585,7 @@ kr_test (void) for (j = 0; j < 20; j++) { printf ("%02x", buf[j]); if (j < 19) - printf (":"); + printf (":"); } printf ("\n\n"); @@ -1633,8 +1633,8 @@ kr_test (void) len = sizeof (buf3); if ((errnum = kr_encrypt_key (kr, kr->ID, buf, 16, buf3, &len, &prng, - find_prng ("yarrow"), - find_hash ("md5"))) != CRYPT_OK) { + find_prng ("yarrow"), + find_hash ("md5"))) != CRYPT_OK) { printf ("Encrypt error, %d, %s\n", i, error_to_string (errnum)); exit (-1); } diff --git a/des.c b/des.c index 42b11d9..21b4198 100644 --- a/des.c +++ b/des.c @@ -519,6 +519,9 @@ void des3_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key int des_test(void) { + #ifndef LTC_TEST + return CRYPT_NOP; + #else int err; static const struct des_test_case { int num, mode; // mode 1 = encrypt @@ -648,10 +651,14 @@ int des_test(void) } return CRYPT_OK; + #endif } int des3_test(void) { + #ifndef LTC_TEST + return CRYPT_NOP; + #else unsigned char key[24], pt[8], ct[8], tmp[8]; symmetric_key skey; int x, err; @@ -680,6 +687,7 @@ int des3_test(void) } return CRYPT_OK; + #endif } int des_keysize(int *desired_keysize) diff --git a/dh.c b/dh.c index 0e4ac43..7540292 100644 --- a/dh.c +++ b/dh.c @@ -109,7 +109,7 @@ static const struct { #ifdef DH4096 { 512, - "DH-4096", + "DH-4096", "3", "Id8ukxZdao3hS0NGTKAXdt3c8PpiyigIyBY8lwOHjM2cqkaZgwvr1pA6OowS" "32kJkeOqKB8gNTZZZVqOFkPXgvC4WveUgA5a7rhTj28pDidNROmMO70CCcSw" @@ -125,7 +125,7 @@ static const struct { "PT0+ZAUyLSAVHbsul++cawh" }, #endif -{ +{ 0, NULL, NULL, @@ -160,7 +160,7 @@ int dh_test(void) /* ensure p is prime */ if ((res = is_prime(&p, &primality)) != CRYPT_OK) { goto done; } - if (primality == 0) { + if (primality == 0) { res = CRYPT_FAIL_TESTVECTOR; goto done; } @@ -213,7 +213,7 @@ int dh_get_size(dh_key *key) return INT_MAX; /* large value that would cause dh_make_key() to fail */ } } - + int dh_make_key(prng_state *prng, int wprng, int keysize, dh_key *key) { unsigned char buf[512]; @@ -232,7 +232,7 @@ int dh_make_key(prng_state *prng, int wprng, int keysize, dh_key *key) for (x = 0; (keysize > sets[x].size) && (sets[x].size != 0); x++); #ifdef FAST_PK keysize = MIN(sets[x].size, 32); -#else +#else keysize = sets[x].size; #endif @@ -257,7 +257,7 @@ int dh_make_key(prng_state *prng, int wprng, int keysize, dh_key *key) if (mp_read_unsigned_bin(&key->x, buf, keysize) != MP_OKAY) { goto error; } if (mp_exptmod(&g, &key->x, &p, &key->y) != MP_OKAY) { goto error; } key->type = PK_PRIVATE; - + if (mp_shrink(&key->x) != MP_OKAY) { goto error; } if (mp_shrink(&key->y) != MP_OKAY) { goto error; } @@ -341,11 +341,11 @@ int dh_export(unsigned char *out, unsigned long *outlen, int type, dh_key *key) /* export y */ OUTPUT_BIGNUM(&key->y, buf2, y, z); - if (type == PK_PRIVATE) { + if (type == PK_PRIVATE) { /* export x */ OUTPUT_BIGNUM(&key->x, buf2, y, z); } - + /* check for overflow */ if (*outlen < y) { #ifdef CLEAN_STACK @@ -362,9 +362,9 @@ int dh_export(unsigned char *out, unsigned long *outlen, int type, dh_key *key) memcpy(out, buf2, (size_t)y); /* clear mem */ -#ifdef CLEAN_STACK +#ifdef CLEAN_STACK zeromem(buf2, sizeof(buf2)); -#endif +#endif return CRYPT_OK; } @@ -376,24 +376,30 @@ int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key) _ARGCHK(in != NULL); _ARGCHK(key != NULL); - /* check type byte */ - if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_DH, PACKET_SUB_KEY)) != CRYPT_OK) { - return err; - } - + /* make sure valid length */ if (2+PACKET_SIZE > inlen) { return CRYPT_INVALID_PACKET; } + /* check type byte */ + if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_DH, PACKET_SUB_KEY)) != CRYPT_OK) { + return err; + } + /* init */ - if (mp_init_multi(&key->x, &key->y, NULL) != MP_OKAY) { + if (mp_init_multi(&key->x, &key->y, NULL) != MP_OKAY) { return CRYPT_MEM; } + /* advance past packet header */ y = PACKET_SIZE; + + /* key type, e.g. private, public */ key->type = (int)in[y++]; + + /* key size in bytes */ s = (unsigned long)in[y++] * 8; - + for (x = 0; (s > (unsigned long)sets[x].size) && (sets[x].size != 0); x++); if (sets[x].size == 0) { err = CRYPT_INVALID_KEYSIZE; @@ -423,7 +429,7 @@ int dh_import(const unsigned char *in, unsigned long inlen, dh_key *key) /* eliminate private key if public */ if (key->type == PK_PUBLIC) { mp_clear(&key->x); - } + } return CRYPT_OK; error: @@ -431,7 +437,7 @@ error: return err; } -int dh_shared_secret(dh_key *private_key, dh_key *public_key, +int dh_shared_secret(dh_key *private_key, dh_key *public_key, unsigned char *out, unsigned long *outlen) { mp_int tmp, p; @@ -454,7 +460,7 @@ int dh_shared_secret(dh_key *private_key, dh_key *public_key, } /* compute y^x mod p */ - if (mp_init_multi(&tmp, &p, NULL) != MP_OKAY) { + if (mp_init_multi(&tmp, &p, NULL) != MP_OKAY) { return CRYPT_MEM; } @@ -467,7 +473,7 @@ int dh_shared_secret(dh_key *private_key, dh_key *public_key, res = CRYPT_BUFFER_OVERFLOW; goto done; } - (void)mp_to_unsigned_bin(&tmp, out); + if (mp_to_unsigned_bin(&tmp, out) != MP_OKAY) { goto error; } *outlen = x; res = CRYPT_OK; goto done; diff --git a/dh_sys.c b/dh_sys.c index fc39c5c..ade0da5 100644 --- a/dh_sys.c +++ b/dh_sys.c @@ -194,7 +194,24 @@ done: return res; } - +/* perform an ElGamal Signature of a hash + * + * The math works as follows. x is the private key, M is the message to sign + + 1. pick a random k + 2. compute a = g^k mod p + 3. compute b = (M - xa)/k mod p + 4. Send (a,b) + + Now to verify with y=g^x mod p, a and b + + 1. compute y^a * a^b = g^(xa) * g^(k*(M-xa)/k) + = g^(xa + (M - xa)) + = g^M [all mod p] + + 2. Compare against g^M mod p [based on input hash]. + 3. If result of #2 == result of #1 then signature valid +*/ int dh_sign_hash(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, prng_state *prng, int wprng, dh_key *key) diff --git a/ecc.c b/ecc.c index bdd9488..21b59af 100644 --- a/ecc.c +++ b/ecc.c @@ -30,7 +30,7 @@ static const struct { }, #endif #ifdef ECC192 -{ +{ 24, "ECC-192", /* prime */ @@ -65,7 +65,7 @@ static const struct { /* Gx */ "jpqOf1BHus6Yd/pyhyVpP", - + /* Gy */ "3FCtyo2yHA5SFjkCGbYxbOvNeChwS+j6wSIwck", }, @@ -88,7 +88,7 @@ static const struct { /* Gy */ "4/ZGkB+6d+RZkVhIdmFdXOhpZDNQp5UpiksG6Wtlr7r" -}, +}, #endif #ifdef ECC384 { @@ -97,11 +97,11 @@ static const struct { /* prime */ "//////////////////////////////////////////x/////00000000003/" "////", - + /* B */ "ip4lf+8+v+IOZWLhu/Wj6HWTd6x+WK4I0nG8Zr0JXrh6LZcDYYxHdIg5oEtJ" "x2hl", - + /* Order */ "////////////////////////////////nsDDWVGtBTzO6WsoIB2dUkpi6MhC" "nIbp", @@ -109,7 +109,7 @@ static const struct { /* Gx and Gy */ "geVA8hwB1JUEiSSUyo2jT6uTEsABfvkOMVT1u89KAZXL0l9TlrKfR3fKNZXo" "TWgt", - + "DXVUIfOcB6zTdfY/afBSAVZq7RqecXHywTen4xNmkC0AOB7E7Nw1dNf37NoG" "wWvV" }, @@ -118,22 +118,22 @@ static const struct { { 65, "ECC-521", - /* prime */ + /* prime */ "V///////////////////////////////////////////////////////////" "///////////////////////////", - + /* B */ "56LFhbXZXoQ7vAQ8Q2sXK3kejfoMvcp5VEuj8cHZl49uLOPEL7iVfDx5bB0l" "JknlmSrSz+8FImqyUz57zHhK3y0", - - /* Order */ + + /* Order */ "V//////////////////////////////////////////+b66XuE/BvPhVym1I" "FS9fT0xjScuYPn7hhjljnwHE6G9", /* Gx and Gy */ "CQ5ZWQt10JfpPu+osOZbRH2d6I1EGK/jI7uAAzWQqqzkg5BNdVlvrae/Xt19" "wB/gDupIBF1XMf2c/b+VZ72vRrc", - + "HWvAMfucZl015oANxGiVHlPcFL4ILURH6WNhxqN9pvcB9VkSfbUz2P0nL2v0" "J+j1s4rF726edB2G8Y+b7QVqMPG", }, @@ -189,7 +189,7 @@ void ecc_find_base(void) mp_sqrmod(&tmp2, &p, &tmp2); /* tmp2 should equal tmp1 */ - } while (mp_cmp(&tmp1, &tmp2)); + } while (mp_cmp(&tmp1, &tmp2)); /* now output values in way that libtomcrypt wants */ mp_todecimal(&p, buf); @@ -249,8 +249,8 @@ static int dbl_point(ecc_point *P, ecc_point *R, mp_int *modulus, mp_int *mu) { mp_int s, tmp, tmpx; int res; - - if (mp_init_multi(&s, &tmp, &tmpx, NULL) != MP_OKAY) { + + if (mp_init_multi(&s, &tmp, &tmpx, NULL) != MP_OKAY) { return CRYPT_MEM; } @@ -293,8 +293,8 @@ static int add_point(ecc_point *P, ecc_point *Q, ecc_point *R, mp_int *modulus, { mp_int s, tmp, tmpx; int res; - - if (mp_init(&tmp) != MP_OKAY) { + + if (mp_init(&tmp) != MP_OKAY) { return CRYPT_MEM; } @@ -303,14 +303,14 @@ static int add_point(ecc_point *P, ecc_point *Q, ecc_point *R, mp_int *modulus, mp_clear(&tmp); return CRYPT_MEM; } - + if (mp_cmp(&P->x, &Q->x) == MP_EQ) if (mp_cmp(&P->y, &Q->y) == MP_EQ || mp_cmp(&P->y, &tmp) == MP_EQ) { mp_clear(&tmp); return dbl_point(P, R, modulus, mu); } - if (mp_init_multi(&tmpx, &s, NULL) != MP_OKAY) { + if (mp_init_multi(&tmpx, &s, NULL) != MP_OKAY) { mp_clear(&tmp); return CRYPT_MEM; } @@ -360,7 +360,7 @@ static int ecc_mulmod(mp_int *k, ecc_point *G, ecc_point *R, mp_int *modulus) mp_int mu; mp_digit buf; int first, bitbuf, bitcpy, bitcnt, mode, digidx; - + /* init barrett reduction */ if (mp_init(&mu) != MP_OKAY) { return CRYPT_MEM; @@ -369,7 +369,7 @@ static int ecc_mulmod(mp_int *k, ecc_point *G, ecc_point *R, mp_int *modulus) mp_clear(&mu); return CRYPT_MEM; } - + /* alloc ram for window temps */ for (i = 0; i < 8; i++) { M[i] = new_point(); @@ -381,7 +381,7 @@ static int ecc_mulmod(mp_int *k, ecc_point *G, ecc_point *R, mp_int *modulus) return CRYPT_MEM; } } - + /* make a copy of G incase R==G */ tG = new_point(); if (tG == NULL) { goto error; } @@ -391,12 +391,12 @@ static int ecc_mulmod(mp_int *k, ecc_point *G, ecc_point *R, mp_int *modulus) if (dbl_point(G, M[0], modulus, &mu) != CRYPT_OK) { goto error; } if (dbl_point(M[0], M[0], modulus, &mu) != CRYPT_OK) { goto error; } if (dbl_point(M[0], M[0], modulus, &mu) != CRYPT_OK) { goto error; } - + /* now find (8+k)G for k=1..7 */ for (j = 9; j < 16; j++) { if (add_point(M[j-9], G, M[j-8], modulus, &mu) != CRYPT_OK) { goto error; } } - + /* tG = G */ if (mp_copy(&G->x, &tG->x) != MP_OKAY) { goto error; } if (mp_copy(&G->y, &tG->y) != MP_OKAY) { goto error; } @@ -408,13 +408,13 @@ static int ecc_mulmod(mp_int *k, ecc_point *G, ecc_point *R, mp_int *modulus) digidx = k->used - 1; bitcpy = bitbuf = 0; first = 1; - + /* perform ops */ for (;;) { /* grab next digit as required */ if (--bitcnt == 0) { if (digidx == -1) { - break; + break; } buf = k->dp[digidx--]; bitcnt = (int) DIGIT_BIT; @@ -423,17 +423,18 @@ static int ecc_mulmod(mp_int *k, ecc_point *G, ecc_point *R, mp_int *modulus) /* grab the next msb from the multiplicand */ i = (buf >> (DIGIT_BIT - 1)) & 1; buf <<= 1; - + /* skip leading zero bits */ - if (mode == 0 && i == 0) - continue; - - /* if the bit is zero and mode == 1 then we double */ - if (mode == 1 && i == 0) { - if (dbl_point(R, R, modulus, &mu) != CRYPT_OK) { goto error; } + if (mode == 0 && i == 0) { continue; } - + + /* if the bit is zero and mode == 1 then we double */ + if (mode == 1 && i == 0) { + if (dbl_point(R, R, modulus, &mu) != CRYPT_OK) { goto error; } + continue; + } + /* else we add it to the window */ bitbuf |= (i << (WINSIZE - ++bitcpy)); mode = 2; @@ -442,39 +443,35 @@ static int ecc_mulmod(mp_int *k, ecc_point *G, ecc_point *R, mp_int *modulus) /* if this is the first window we do a simple copy */ if (first == 1) { /* R = kG [k = first window] */ - if (mp_copy(&M[bitbuf-8]->x, &R->x) != MP_OKAY) { goto error; } - if (mp_copy(&M[bitbuf-8]->y, &R->y) != MP_OKAY) { goto error; } + if (mp_copy(&M[bitbuf-8]->x, &R->x) != MP_OKAY) { goto error; } + if (mp_copy(&M[bitbuf-8]->y, &R->y) != MP_OKAY) { goto error; } first = 0; } else { /* normal window */ /* ok window is filled so double as required and add */ /* double first */ for (j = 0; j < WINSIZE; j++) { - if (dbl_point(R, R, modulus, &mu) != CRYPT_OK) { goto error; } + if (dbl_point(R, R, modulus, &mu) != CRYPT_OK) { goto error; } } - /* then add, bitbuf will be 1..15 [1..2^WINSIZE] guaranteed */ - if (bitbuf == 1) { - if (add_point(R, tG, R, modulus, &mu) != CRYPT_OK) { goto error; } - } else { - if (add_point(R, M[bitbuf-8], R, modulus, &mu) != CRYPT_OK) { goto error; } - } + /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */ + if (add_point(R, M[bitbuf-8], R, modulus, &mu) != CRYPT_OK) { goto error; } } /* empty window and reset */ bitcpy = bitbuf = 0; mode = 1; } } - + /* if bits remain then double/add */ if (mode == 2 && bitcpy > 0) { /* double then add */ for (j = 0; j < bitcpy; j++) { /* only double if we have had at least one add first */ if (first == 0) { - if (dbl_point(R, R, modulus, &mu) != CRYPT_OK) { goto error; } + if (dbl_point(R, R, modulus, &mu) != CRYPT_OK) { goto error; } } - + bitbuf <<= 1; if ((bitbuf & (1 << WINSIZE)) != 0) { if (first == 1){ @@ -489,7 +486,7 @@ static int ecc_mulmod(mp_int *k, ecc_point *G, ecc_point *R, mp_int *modulus) } } } - res = CRYPT_OK; + res = CRYPT_OK; goto done; error: res = CRYPT_MEM; @@ -510,18 +507,18 @@ int ecc_test(void) ecc_point *G, *GG; int i, res, primality; - if (mp_init_multi(&modulus, &order, NULL) != MP_OKAY) { + if (mp_init_multi(&modulus, &order, NULL) != MP_OKAY) { return CRYPT_MEM; } G = new_point(); - if (G == NULL) { + if (G == NULL) { mp_clear_multi(&modulus, &order, NULL); return CRYPT_MEM; } GG = new_point(); - if (GG == NULL) { + if (GG == NULL) { mp_clear_multi(&modulus, &order, NULL); del_point(G); return CRYPT_MEM; @@ -540,7 +537,7 @@ int ecc_test(void) res = CRYPT_FAIL_TESTVECTOR; goto done1; } - + /* is order prime ? */ if (is_prime(&order, &primality) != CRYPT_OK) { goto error; } if (primality == 0) { @@ -579,11 +576,11 @@ void ecc_sizes(int *low, int *high) *low = INT_MAX; *high = 0; for (i = 0; sets[i].size != 0; i++) { - if (sets[i].size < *low) { - *low = sets[i].size; + if (sets[i].size < *low) { + *low = sets[i].size; } - if (sets[i].size > *high) { - *high = sets[i].size; + if (sets[i].size > *high) { + *high = sets[i].size; } } } @@ -606,7 +603,7 @@ int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key) for (x = 0; (keysize > sets[x].size) && (sets[x].size != 0); x++); keysize = sets[x].size; - if (sets[x].size == 0) { + if (sets[x].size == 0) { return CRYPT_INVALID_KEYSIZE; } key->idx = x; @@ -617,7 +614,7 @@ int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key) } /* setup the key variables */ - if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->k, &prime, NULL) != MP_OKAY) { + if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->k, &prime, NULL) != MP_OKAY) { return CRYPT_MEM; } base = new_point(); @@ -635,7 +632,7 @@ int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key) /* make the public key */ if (ecc_mulmod(&key->k, base, &key->pubkey, &prime) != CRYPT_OK) { goto error; } key->type = PK_PRIVATE; - + /* shrink key */ if (mp_shrink(&key->k) != MP_OKAY) { goto error; } if (mp_shrink(&key->pubkey.x) != MP_OKAY) { goto error; } @@ -689,12 +686,12 @@ static int compress_y_point(ecc_point *pt, int idx, int *result) if (mp_exptmod(&tmp, &tmp2, &p, &tmp) != MP_OKAY) { goto error; } /* tmp = (x^3 - 3x + b)^((p+1)/4) mod p */ /* if tmp equals the y point give a 0, otherwise 1 */ - if (mp_cmp(&tmp, &pt->y) == 0) { + if (mp_cmp(&tmp, &pt->y) == 0) { *result = 0; } else { *result = 1; } - + res = CRYPT_OK; goto done; error: @@ -710,7 +707,7 @@ static int expand_y_point(ecc_point *pt, int idx, int result) int res; _ARGCHK(pt != NULL); - + if (mp_init_multi(&tmp, &tmp2, &p, NULL) != MP_OKAY) { return CRYPT_MEM; } @@ -736,7 +733,7 @@ static int expand_y_point(ecc_point *pt, int idx, int result) } else { if (mp_sub(&p, &tmp, &pt->y) != MP_OKAY) { goto error; } } - + res = CRYPT_OK; goto done; error: @@ -795,8 +792,8 @@ int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key _ARGCHK(key != NULL); /* type valid? */ - if (key->type != PK_PRIVATE && type == PK_PRIVATE) { - return CRYPT_PK_TYPE_MISMATCH; + if (key->type != PK_PRIVATE && type == PK_PRIVATE) { + return CRYPT_PK_TYPE_MISMATCH; } /* output type and magic byte */ @@ -818,7 +815,7 @@ int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key } /* check size */ - if (*outlen < y) { + if (*outlen < y) { return CRYPT_BUFFER_OVERFLOW; } @@ -842,15 +839,16 @@ int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key) _ARGCHK(in != NULL); _ARGCHK(key != NULL); - /* check type */ - if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_ECC, PACKET_SUB_KEY)) != CRYPT_OK) { - return err; - } - + /* check length */ if (2+PACKET_SIZE > inlen) { return CRYPT_INVALID_PACKET; } + /* check type */ + if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_ECC, PACKET_SUB_KEY)) != CRYPT_OK) { + return err; + } + /* init key */ if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->k, NULL) != MP_OKAY) { return CRYPT_MEM; @@ -859,9 +857,9 @@ int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key) y = PACKET_SIZE; key->type = (int)in[y++]; s = (unsigned long)in[y++]; - + for (x = 0; (s > (unsigned long)sets[x].size) && (sets[x].size != 0); x++); - if (sets[x].size == 0) { + if (sets[x].size == 0) { err = CRYPT_INVALID_KEYSIZE; goto error; } @@ -881,30 +879,30 @@ int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key) /* load x coordinate */ INPUT_BIGNUM(&key->pubkey.x, in, x, y); - + /* load y */ x = (unsigned long)in[y++]; - if ((err = expand_y_point(&key->pubkey, key->idx, (int)x)) != CRYPT_OK) { - goto error; + if ((err = expand_y_point(&key->pubkey, key->idx, (int)x)) != CRYPT_OK) { + goto error; } if (key->type == PK_PRIVATE) { /* load private key */ INPUT_BIGNUM(&key->k, in, x, y); } - + /* eliminate private key if public */ if (key->type == PK_PUBLIC) { mp_clear(&key->k); - } - + } + return CRYPT_OK; error: mp_clear_multi(&key->pubkey.x, &key->pubkey.y, &key->k, NULL); return err; } -int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key, +int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key, unsigned char *out, unsigned long *outlen) { unsigned long x, y; @@ -928,17 +926,17 @@ int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key, /* make new point */ result = new_point(); - if (result == NULL) { + if (result == NULL) { return CRYPT_MEM; } - if (mp_init(&prime) != MP_OKAY) { + if (mp_init(&prime) != MP_OKAY) { del_point(result); return CRYPT_MEM; } - if (mp_read_radix(&prime, (unsigned char *)sets[private_key->idx].prime, 64) != MP_OKAY) { goto error; } - if ((err = ecc_mulmod(&private_key->k, &public_key->pubkey, result, &prime)) != CRYPT_OK) { res = err; goto done1; } + if (mp_read_radix(&prime, (unsigned char *)sets[private_key->idx].prime, 64) != MP_OKAY) { goto error; } + if ((res = ecc_mulmod(&private_key->k, &public_key->pubkey, result, &prime)) != CRYPT_OK) { goto done1; } x = (unsigned long)mp_unsigned_bin_size(&result->x); y = (unsigned long)mp_unsigned_bin_size(&result->y); @@ -948,8 +946,8 @@ int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key, goto done1; } *outlen = x+y; - (void)mp_to_unsigned_bin(&result->x, out); - (void)mp_to_unsigned_bin(&result->y, out+x); + if (mp_to_unsigned_bin(&result->x, out) != MP_OKAY) { goto error; } + if (mp_to_unsigned_bin(&result->y, out+x) != MP_OKAY) { goto error; } res = CRYPT_OK; goto done1; diff --git a/ecc_sys.c b/ecc_sys.c index 6a3eb9e..e15e473 100644 --- a/ecc_sys.c +++ b/ecc_sys.c @@ -299,7 +299,19 @@ done1: return res; } -/* verify that mG = (bA + Y) */ +/* verify that mG = (bA + Y) + * + * The signatures work by making up a fresh key "a" with a public key "A". Now we want to sign so the + * public key Y = xG can verify it. + * + * b = (m - x)/k, A is the public key embedded and Y is the users public key [who signed it] + * A = kG therefore bA == ((m-x)/k)kG == (m-x)G + * + * Adding Y = xG to the bA gives us (m-x)G + xG == mG + * + * The user given only xG, kG and b cannot determine k or x which means they can't find the private key. + * + */ int ecc_verify_hash(const unsigned char *sig, unsigned long siglen, const unsigned char *hash, unsigned long inlen, int *stat, ecc_key *key) diff --git a/hmac.c b/hmac.c index 60fc6ec..833f749 100644 --- a/hmac.c +++ b/hmac.c @@ -37,7 +37,7 @@ int hmac_init(hmac_state *hmac, int hash, const unsigned char *key, unsigned lon return err; } - if(key == NULL || keylen == 0) { + if (keylen == 0) { return CRYPT_INVALID_KEYSIZE; } @@ -231,6 +231,9 @@ Category: Informational R. Glenn int hmac_test(void) { + #ifndef LTC_TEST + return CRYPT_NOP; + #else unsigned char digest[MAXBLOCKSIZE]; int i; @@ -497,6 +500,7 @@ Key First" } else { return CRYPT_OK; } + #endif } #endif diff --git a/makefile b/makefile index faf011b..f2255a9 100644 --- a/makefile +++ b/makefile @@ -9,7 +9,7 @@ # a build. This is easy to remedy though, for those that have problems. # The version -VERSION=0.83 +VERSION=0.84 #ch1-01-1 # Compiler and Linker Names @@ -31,7 +31,7 @@ CFLAGS += -c -I./ -Wall -Wsign-compare -W -Wno-unused -Wshadow -Werror # optimize for SIZE CFLAGS += -Os -# compile for DEBUGGING +# compile for DEBUGING #CFLAGS += -g3 #ch1-01-3 @@ -57,7 +57,7 @@ OBJECTS=keyring.o gf.o mem.o sprng.o ecc.o base64.o dh.o rsa.o \ bits.o yarrow.o cfb.o ofb.o ecb.o ctr.o cbc.o hash.o tiger.o sha1.o \ md5.o md4.o md2.o sha256.o sha512.o xtea.o aes.o serpent.o des.o \ safer_tab.o safer.o safer+.o rc4.o rc2.o rc6.o rc5.o cast5.o noekeon.o blowfish.o crypt.o \ -ampi.o mpi.o prime.o twofish.o packet.o hmac.o strings.o +mpi.o prime.o twofish.o packet.o hmac.o strings.o TESTOBJECTS=demos/test.o HASHOBJECTS=demos/hashsum.o @@ -71,7 +71,7 @@ LEFTOVERS=*.dvi *.log *.aux *.toc *.idx *.ilg *.ind COMPRESSED=crypt.tar.bz2 crypt.zip crypt.tar.gz #Header files used by libtomcrypt. -HEADERS=mpi.h mycrypt_cfg.h mycrypt_gf.h mycrypt_kr.h \ +HEADERS=tommath.h mycrypt_cfg.h mycrypt_gf.h mycrypt_kr.h \ mycrypt_misc.h mycrypt_prng.h mycrypt_cipher.h mycrypt_hash.h \ mycrypt_macros.h mycrypt_pk.h mycrypt.h mycrypt_argchk.h mycrypt_custom.h @@ -129,8 +129,7 @@ clean: #nice pre-compiled crypt.pdf that comes with libtomcrypt! We only need to #delete it if we are rebuilding it. docs: crypt.tex - rm -f crypt.pdf - rm -f $(LEFTOVERS) + rm -f crypt.pdf $(LEFTOVERS) latex crypt > /dev/null makeindex crypt > /dev/null pdflatex crypt > /dev/null diff --git a/makefile.msvc b/makefile.msvc index bbf9059..381ebb8 100644 --- a/makefile.msvc +++ b/makefile.msvc @@ -2,7 +2,7 @@ # #Tom St Denis -CFLAGS = /I. /Ogiyb2t /Gs /DWIN32 /W3 +CFLAGS = /I. /Ogiyb1s /Gs /DWIN32 /W3 default: library @@ -11,7 +11,7 @@ OBJECTS=keyring.obj gf.obj mem.obj sprng.obj ecc.obj base64.obj dh.obj rsa.obj \ bits.obj yarrow.obj cfb.obj ofb.obj ecb.obj ctr.obj cbc.obj hash.obj tiger.obj sha1.obj \ md5.obj md4.obj md2.obj sha256.obj sha512.obj xtea.obj aes.obj serpent.obj des.obj \ safer_tab.obj safer.obj safer+.obj rc4.obj rc2.obj rc6.obj rc5.obj cast5.obj noekeon.obj \ -blowfish.obj crypt.obj ampi.obj mpi.obj prime.obj twofish.obj packet.obj hmac.obj strings.obj +blowfish.obj crypt.obj mpi.obj prime.obj twofish.obj packet.obj hmac.obj strings.obj library: $(OBJECTS) lib /out:tomcrypt.lib $(OBJECTS) diff --git a/md2.c b/md2.c index 82bd4a3..249f53a 100644 --- a/md2.c +++ b/md2.c @@ -136,6 +136,9 @@ void md2_done(hash_state * md, unsigned char *hash) int md2_test(void) { + #ifndef LTC_TEST + return CRYPT_NOP; + #else static const struct { char *msg; unsigned char md[16]; @@ -184,6 +187,7 @@ int md2_test(void) } } return CRYPT_OK; + #endif } #endif diff --git a/md4.c b/md4.c index cff1442..6c6003f 100644 --- a/md4.c +++ b/md4.c @@ -221,6 +221,9 @@ void md4_done(hash_state * md, unsigned char *hash) int md4_test(void) { + #ifndef LTC_TEST + return CRYPT_NOP; + #else static const struct md4_test_case { char *input; unsigned char digest[16]; @@ -261,6 +264,7 @@ int md4_test(void) } return CRYPT_OK; + #endif } #endif diff --git a/md5.c b/md5.c index ae9a1dd..ef999c2 100644 --- a/md5.c +++ b/md5.c @@ -208,6 +208,9 @@ void md5_done(hash_state * md, unsigned char *hash) int md5_test(void) { + #ifndef LTC_TEST + return CRYPT_NOP; + #else static const struct { char *msg; unsigned char hash[16]; @@ -249,6 +252,7 @@ int md5_test(void) } } return CRYPT_OK; + #endif } #endif diff --git a/mpi.c b/mpi.c index 10288b1..383d198 100644 --- a/mpi.c +++ b/mpi.c @@ -1,6051 +1,7149 @@ -/* File Generated Automatically by gen.pl */ - -/* Start: bncore.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* configured for a AMD Duron Morgan core with etc/tune.c */ -int KARATSUBA_MUL_CUTOFF = 73, /* Min. number of digits before Karatsuba multiplication is used. */ - KARATSUBA_SQR_CUTOFF = 121, /* Min. number of digits before Karatsuba squaring is used. */ - MONTGOMERY_EXPT_CUTOFF = 128; /* max. number of digits that montgomery reductions will help for */ - -/* End: bncore.c */ - -/* Start: bn_fast_mp_invmod.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* computes the modular inverse via binary extended euclidean algorithm, - * that is c = 1/a mod b - * - * Based on mp_invmod except this is optimized for the case where b is - * odd as per HAC Note 14.64 on pp. 610 - */ -int -fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c) -{ - mp_int x, y, u, v, B, D; - int res, neg; - - /* init all our temps */ - if ((res = mp_init (&x)) != MP_OKAY) { - goto __ERR; - } - - if ((res = mp_init (&y)) != MP_OKAY) { - goto __X; - } - - if ((res = mp_init (&u)) != MP_OKAY) { - goto __Y; - } - - if ((res = mp_init (&v)) != MP_OKAY) { - goto __U; - } - - if ((res = mp_init (&B)) != MP_OKAY) { - goto __V; - } - - if ((res = mp_init (&D)) != MP_OKAY) { - goto __B; - } - - /* x == modulus, y == value to invert */ - if ((res = mp_copy (b, &x)) != MP_OKAY) { - goto __D; - } - if ((res = mp_copy (a, &y)) != MP_OKAY) { - goto __D; - } - - /* we need |y| */ - if ((res = mp_abs (&y, &y)) != MP_OKAY) { - goto __D; - } - - /* 2. [modified] if x,y are both even then return an error! - * - * That is if gcd(x,y) = 2 * k then obviously there is no inverse. - */ - if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) { - res = MP_VAL; - goto __D; - } - - /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ - if ((res = mp_copy (&x, &u)) != MP_OKAY) { - goto __D; - } - if ((res = mp_copy (&y, &v)) != MP_OKAY) { - goto __D; - } - mp_set (&D, 1); - -top: - /* 4. while u is even do */ - while (mp_iseven (&u) == 1) { - /* 4.1 u = u/2 */ - if ((res = mp_div_2 (&u, &u)) != MP_OKAY) { - goto __D; - } - /* 4.2 if A or B is odd then */ - if (mp_iseven (&B) == 0) { - if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) { - goto __D; - } - } - /* B = B/2 */ - if ((res = mp_div_2 (&B, &B)) != MP_OKAY) { - goto __D; - } - } - - /* 5. while v is even do */ - while (mp_iseven (&v) == 1) { - /* 5.1 v = v/2 */ - if ((res = mp_div_2 (&v, &v)) != MP_OKAY) { - goto __D; - } - /* 5.2 if C,D are even then */ - if (mp_iseven (&D) == 0) { - /* D = (D-x)/2 */ - if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) { - goto __D; - } - } - /* D = D/2 */ - if ((res = mp_div_2 (&D, &D)) != MP_OKAY) { - goto __D; - } - } - - /* 6. if u >= v then */ - if (mp_cmp (&u, &v) != MP_LT) { - /* u = u - v, B = B - D */ - if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) { - goto __D; - } - - if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) { - goto __D; - } - } else { - /* v - v - u, D = D - B */ - if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) { - goto __D; - } - - if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) { - goto __D; - } - } - - /* if not zero goto step 4 */ - if (mp_iszero (&u) == 0) { - goto top; - } - - /* now a = C, b = D, gcd == g*v */ - - /* if v != 1 then there is no inverse */ - if (mp_cmp_d (&v, 1) != MP_EQ) { - res = MP_VAL; - goto __D; - } - - /* b is now the inverse */ - neg = a->sign; - while (D.sign == MP_NEG) { - if ((res = mp_add (&D, b, &D)) != MP_OKAY) { - goto __D; - } - } - mp_exch (&D, c); - c->sign = neg; - res = MP_OKAY; - -__D:mp_clear (&D); -__B:mp_clear (&B); -__V:mp_clear (&v); -__U:mp_clear (&u); -__Y:mp_clear (&y); -__X:mp_clear (&x); -__ERR: - return res; -} - -/* End: bn_fast_mp_invmod.c */ - -/* Start: bn_fast_mp_montgomery_reduce.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* computes xR^-1 == x (mod N) via Montgomery Reduction - * - * This is an optimized implementation of mp_montgomery_reduce - * which uses the comba method to quickly calculate the columns of the - * reduction. - * - * Based on Algorithm 14.32 on pp.601 of HAC. -*/ -int -fast_mp_montgomery_reduce (mp_int * a, mp_int * m, mp_digit mp) -{ - int ix, res, olduse; - mp_word W[512]; - - /* get old used count */ - olduse = a->used; - - /* grow a as required */ - if (a->alloc < m->used + 1) { - if ((res = mp_grow (a, m->used + 1)) != MP_OKAY) { - return res; - } - } - - { - register mp_word *_W; - register mp_digit *tmpa; - - _W = W; - tmpa = a->dp; - - /* copy the digits of a into W[0..a->used-1] */ - for (ix = 0; ix < a->used; ix++) { - *_W++ = *tmpa++; - } - - /* zero the high words of W[a->used..m->used*2] */ - for (; ix < m->used * 2 + 1; ix++) { - *_W++ = 0; - } - } - - for (ix = 0; ix < m->used; ix++) { - /* ui = ai * m' mod b - * - * We avoid a double precision multiplication (which isn't required) - * by casting the value down to a mp_digit. Note this requires that W[ix-1] have - * the carry cleared (see after the inner loop) - */ - register mp_digit ui; - ui = (((mp_digit) (W[ix] & MP_MASK)) * mp) & MP_MASK; - - /* a = a + ui * m * b^i - * - * This is computed in place and on the fly. The multiplication - * by b^i is handled by offseting which columns the results - * are added to. - * - * Note the comba method normally doesn't handle carries in the inner loop - * In this case we fix the carry from the previous column since the Montgomery - * reduction requires digits of the result (so far) [see above] to work. This is - * handled by fixing up one carry after the inner loop. The carry fixups are done - * in order so after these loops the first m->used words of W[] have the carries - * fixed - */ - { - register int iy; - register mp_digit *tmpx; - register mp_word *_W; - - /* alias for the digits of the modulus */ - tmpx = m->dp; - - /* Alias for the columns set by an offset of ix */ - _W = W + ix; - - /* inner loop */ - for (iy = 0; iy < m->used; iy++) { - *_W++ += ((mp_word) ui) * ((mp_word) * tmpx++); - } - } - - /* now fix carry for next digit, W[ix+1] */ - W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT); - } - - - { - register mp_digit *tmpa; - register mp_word *_W, *_W1; - - /* nox fix rest of carries */ - _W1 = W + ix; - _W = W + ++ix; - - for (; ix <= m->used * 2 + 1; ix++) { - *_W++ += *_W1++ >> ((mp_word) DIGIT_BIT); - } - - /* copy out, A = A/b^n - * - * The result is A/b^n but instead of converting from an array of mp_word - * to mp_digit than calling mp_rshd we just copy them in the right - * order - */ - tmpa = a->dp; - _W = W + m->used; - - for (ix = 0; ix < m->used + 1; ix++) { - *tmpa++ = *_W++ & ((mp_word) MP_MASK); - } - - /* zero oldused digits, if the input a was larger than - * m->used+1 we'll have to clear the digits */ - for (; ix < olduse; ix++) { - *tmpa++ = 0; - } - } - - /* set the max used and clamp */ - a->used = m->used + 1; - mp_clamp (a); - - /* if A >= m then A = A - m */ - if (mp_cmp_mag (a, m) != MP_LT) { - return s_mp_sub (a, m, a); - } - return MP_OKAY; -} - -/* End: bn_fast_mp_montgomery_reduce.c */ - -/* Start: bn_fast_s_mp_mul_digs.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* Fast (comba) multiplier - * - * This is the fast column-array [comba] multiplier. It is designed to compute - * the columns of the product first then handle the carries afterwards. This - * has the effect of making the nested loops that compute the columns very - * simple and schedulable on super-scalar processors. - * - * This has been modified to produce a variable number of digits of output so - * if say only a half-product is required you don't have to compute the upper half - * (a feature required for fast Barrett reduction). - * - * Based on Algorithm 14.12 on pp.595 of HAC. - * - */ -int -fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) -{ - int olduse, res, pa, ix; - mp_word W[512]; - - /* grow the destination as required */ - if (c->alloc < digs) { - if ((res = mp_grow (c, digs)) != MP_OKAY) { - return res; - } - } - - /* clear temp buf (the columns) */ - memset (W, 0, sizeof (mp_word) * digs); - - /* calculate the columns */ - pa = a->used; - for (ix = 0; ix < pa; ix++) { - - /* this multiplier has been modified to allow you to control how many digits - * of output are produced. So at most we want to make upto "digs" digits - * of output. - * - * this adds products to distinct columns (at ix+iy) of W - * note that each step through the loop is not dependent on - * the previous which means the compiler can easily unroll - * the loop without scheduling problems - */ - { - register mp_digit tmpx, *tmpy; - register mp_word *_W; - register int iy, pb; - - /* alias for the the word on the left e.g. A[ix] * A[iy] */ - tmpx = a->dp[ix]; - - /* alias for the right side */ - tmpy = b->dp; - - /* alias for the columns, each step through the loop adds a new - term to each column - */ - _W = W + ix; - - /* the number of digits is limited by their placement. E.g. - we avoid multiplying digits that will end up above the # of - digits of precision requested - */ - pb = MIN (b->used, digs - ix); - - for (iy = 0; iy < pb; iy++) { - *_W++ += ((mp_word) tmpx) * ((mp_word) * tmpy++); - } - } - - } - - /* setup dest */ - olduse = c->used; - c->used = digs; - - { - register mp_digit *tmpc; - - /* At this point W[] contains the sums of each column. To get the - * correct result we must take the extra bits from each column and - * carry them down - * - * Note that while this adds extra code to the multiplier it saves time - * since the carry propagation is removed from the above nested loop. - * This has the effect of reducing the work from N*(N+N*c)==N^2 + c*N^2 to - * N^2 + N*c where c is the cost of the shifting. On very small numbers - * this is slower but on most cryptographic size numbers it is faster. - */ - tmpc = c->dp; - for (ix = 1; ix < digs; ix++) { - W[ix] += (W[ix - 1] >> ((mp_word) DIGIT_BIT)); - *tmpc++ = (mp_digit) (W[ix - 1] & ((mp_word) MP_MASK)); - } - *tmpc++ = (mp_digit) (W[digs - 1] & ((mp_word) MP_MASK)); - - /* clear unused */ - for (; ix < olduse; ix++) { - *tmpc++ = 0; - } - } - - mp_clamp (c); - return MP_OKAY; -} - -/* End: bn_fast_s_mp_mul_digs.c */ - -/* Start: bn_fast_s_mp_mul_high_digs.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* this is a modified version of fast_s_mp_mul_digs that only produces - * output digits *above* digs. See the comments for fast_s_mp_mul_digs - * to see how it works. - * - * This is used in the Barrett reduction since for one of the multiplications - * only the higher digits were needed. This essentially halves the work. - * - * Based on Algorithm 14.12 on pp.595 of HAC. - */ -int -fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) -{ - int oldused, newused, res, pa, pb, ix; - mp_word W[512]; - - /* calculate size of product and allocate more space if required */ - newused = a->used + b->used + 1; - if (c->alloc < newused) { - if ((res = mp_grow (c, newused)) != MP_OKAY) { - return res; - } - } - - /* like the other comba method we compute the columns first */ - pa = a->used; - pb = b->used; - memset (W + digs, 0, (pa + pb + 1 - digs) * sizeof (mp_word)); - for (ix = 0; ix < pa; ix++) { - { - register mp_digit tmpx, *tmpy; - register int iy; - register mp_word *_W; - - /* work todo, that is we only calculate digits that are at "digs" or above */ - iy = digs - ix; - - /* copy of word on the left of A[ix] * B[iy] */ - tmpx = a->dp[ix]; - - /* alias for right side */ - tmpy = b->dp + iy; - - /* alias for the columns of output. Offset to be equal to or above the - * smallest digit place requested - */ - _W = &(W[digs]); - - /* compute column products for digits above the minimum */ - for (; iy < pb; iy++) { - *_W++ += ((mp_word) tmpx) * ((mp_word) * tmpy++); - } - } - } - - /* setup dest */ - oldused = c->used; - c->used = newused; - - /* now convert the array W downto what we need */ - for (ix = digs + 1; ix < newused; ix++) { - W[ix] += (W[ix - 1] >> ((mp_word) DIGIT_BIT)); - c->dp[ix - 1] = (mp_digit) (W[ix - 1] & ((mp_word) MP_MASK)); - } - c->dp[(pa + pb + 1) - 1] = (mp_digit) (W[(pa + pb + 1) - 1] & ((mp_word) MP_MASK)); - - for (; ix < oldused; ix++) { - c->dp[ix] = 0; - } - mp_clamp (c); - return MP_OKAY; -} - -/* End: bn_fast_s_mp_mul_high_digs.c */ - -/* Start: bn_fast_s_mp_sqr.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* fast squaring - * - * This is the comba method where the columns of the product are computed first - * then the carries are computed. This has the effect of making a very simple - * inner loop that is executed the most - * - * W2 represents the outer products and W the inner. - * - * A further optimizations is made because the inner products are of the form - * "A * B * 2". The *2 part does not need to be computed until the end which is - * good because 64-bit shifts are slow! - * - * Based on Algorithm 14.16 on pp.597 of HAC. - * - */ -int -fast_s_mp_sqr (mp_int * a, mp_int * b) -{ - int olduse, newused, res, ix, pa; - mp_word W2[512], W[512]; - - /* calculate size of product and allocate as required */ - pa = a->used; - newused = pa + pa + 1; - if (b->alloc < newused) { - if ((res = mp_grow (b, newused)) != MP_OKAY) { - return res; - } - } - - /* zero temp buffer (columns) - * Note that there are two buffers. Since squaring requires - * a outter and inner product and the inner product requires - * computing a product and doubling it (a relatively expensive - * op to perform n^2 times if you don't have to) the inner and - * outer products are computed in different buffers. This way - * the inner product can be doubled using n doublings instead of - * n^2 - */ - memset (W, 0, newused * sizeof (mp_word)); - memset (W2, 0, newused * sizeof (mp_word)); - -/* note optimization - * values in W2 are only written in even locations which means - * we can collapse the array to 256 words [and fixup the memset above] - * provided we also fix up the summations below. Ideally - * the fixup loop should be unrolled twice to handle the even/odd - * cases, and then a final step to handle odd cases [e.g. newused == odd] - * - * This will not only save ~8*256 = 2KB of stack but lower the number of - * operations required to finally fix up the columns - */ - - /* This computes the inner product. To simplify the inner N^2 loop - * the multiplication by two is done afterwards in the N loop. - */ - for (ix = 0; ix < pa; ix++) { - /* compute the outer product - * - * Note that every outer product is computed - * for a particular column only once which means that - * there is no need todo a double precision addition - */ - W2[ix + ix] = ((mp_word) a->dp[ix]) * ((mp_word) a->dp[ix]); - - { - register mp_digit tmpx, *tmpy; - register mp_word *_W; - register int iy; - - /* copy of left side */ - tmpx = a->dp[ix]; - - /* alias for right side */ - tmpy = a->dp + (ix + 1); - - /* the column to store the result in */ - _W = W + (ix + ix + 1); - - /* inner products */ - for (iy = ix + 1; iy < pa; iy++) { - *_W++ += ((mp_word) tmpx) * ((mp_word) * tmpy++); - } - } - } - - /* setup dest */ - olduse = b->used; - b->used = newused; - - /* double first value, since the inner products are half of what they should be */ - W[0] += W[0] + W2[0]; - - /* now compute digits */ - { - register mp_digit *tmpb; - - tmpb = b->dp; - - for (ix = 1; ix < newused; ix++) { - /* double/add next digit */ - W[ix] += W[ix] + W2[ix]; - - W[ix] = W[ix] + (W[ix - 1] >> ((mp_word) DIGIT_BIT)); - *tmpb++ = (mp_digit) (W[ix - 1] & ((mp_word) MP_MASK)); - } - *tmpb++ = (mp_digit) (W[(newused) - 1] & ((mp_word) MP_MASK)); - - /* clear high */ - for (; ix < olduse; ix++) { - *tmpb++ = 0; - } - } - - mp_clamp (b); - return MP_OKAY; -} - -/* End: bn_fast_s_mp_sqr.c */ - -/* Start: bn_mp_2expt.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* computes a = 2^b - * - * Simple algorithm which zeroes the int, grows it then just sets one bit - * as required. - */ -int -mp_2expt (mp_int * a, int b) -{ - int res; - - mp_zero (a); - if ((res = mp_grow (a, b / DIGIT_BIT + 1)) != MP_OKAY) { - return res; - } - a->used = b / DIGIT_BIT + 1; - a->dp[b / DIGIT_BIT] = 1 << (b % DIGIT_BIT); - - return MP_OKAY; -} - -/* End: bn_mp_2expt.c */ - -/* Start: bn_mp_abs.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* b = |a| - * - * Simple function copies the input and fixes the sign to positive - */ -int -mp_abs (mp_int * a, mp_int * b) -{ - int res; - if ((res = mp_copy (a, b)) != MP_OKAY) { - return res; - } - b->sign = MP_ZPOS; - return MP_OKAY; -} - -/* End: bn_mp_abs.c */ - -/* Start: bn_mp_add.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* high level addition (handles signs) */ -int -mp_add (mp_int * a, mp_int * b, mp_int * c) -{ - int sa, sb, res; - - /* get sign of both inputs */ - sa = a->sign; - sb = b->sign; - - /* handle four cases */ - if (sa == MP_ZPOS && sb == MP_ZPOS) { - /* both positive */ - res = s_mp_add (a, b, c); - c->sign = MP_ZPOS; - } else if (sa == MP_ZPOS && sb == MP_NEG) { - /* a + -b == a - b, but if b>a then we do it as -(b-a) */ - if (mp_cmp_mag (a, b) == MP_LT) { - res = s_mp_sub (b, a, c); - c->sign = MP_NEG; - } else { - res = s_mp_sub (a, b, c); - c->sign = MP_ZPOS; - } - } else if (sa == MP_NEG && sb == MP_ZPOS) { - /* -a + b == b - a, but if a>b then we do it as -(a-b) */ - if (mp_cmp_mag (a, b) == MP_GT) { - res = s_mp_sub (a, b, c); - c->sign = MP_NEG; - } else { - res = s_mp_sub (b, a, c); - c->sign = MP_ZPOS; - } - } else { - /* -a + -b == -(a + b) */ - res = s_mp_add (a, b, c); - c->sign = MP_NEG; - } - return res; -} - -/* End: bn_mp_add.c */ - -/* Start: bn_mp_addmod.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* d = a + b (mod c) */ -int -mp_addmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) -{ - int res; - mp_int t; - - if ((res = mp_init (&t)) != MP_OKAY) { - return res; - } - - if ((res = mp_add (a, b, &t)) != MP_OKAY) { - mp_clear (&t); - return res; - } - res = mp_mod (&t, c, d); - mp_clear (&t); - return res; -} - -/* End: bn_mp_addmod.c */ - -/* Start: bn_mp_add_d.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* single digit addition */ -int -mp_add_d (mp_int * a, mp_digit b, mp_int * c) -{ - mp_int t; - int res; - - if ((res = mp_init_size(&t, 1)) != MP_OKAY) { - return res; - } - mp_set (&t, b); - res = mp_add (a, &t, c); - - mp_clear (&t); - return res; -} - -/* End: bn_mp_add_d.c */ - -/* Start: bn_mp_and.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* AND two ints together */ -int -mp_and (mp_int * a, mp_int * b, mp_int * c) -{ - int res, ix, px; - mp_int t, *x; - - if (a->used > b->used) { - if ((res = mp_init_copy (&t, a)) != MP_OKAY) { - return res; - } - px = b->used; - x = b; - } else { - if ((res = mp_init_copy (&t, b)) != MP_OKAY) { - return res; - } - px = a->used; - x = a; - } - - for (ix = 0; ix < px; ix++) { - t.dp[ix] &= x->dp[ix]; - } - - /* zero digits above the last from the smallest mp_int */ - for (; ix < t.used; ix++) { - t.dp[ix] = 0; - } - - mp_clamp (&t); - mp_exch (c, &t); - mp_clear (&t); - return MP_OKAY; -} - -/* End: bn_mp_and.c */ - -/* Start: bn_mp_clamp.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* trim unused digits - * - * This is used to ensure that leading zero digits are - * trimed and the leading "used" digit will be non-zero - * Typically very fast. Also fixes the sign if there - * are no more leading digits - */ -void -mp_clamp (mp_int * a) -{ - while (a->used > 0 && a->dp[a->used - 1] == 0) { - --(a->used); - } - if (a->used == 0) { - a->sign = MP_ZPOS; - } -} - -/* End: bn_mp_clamp.c */ - -/* Start: bn_mp_clear.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* clear one (frees) */ -void -mp_clear (mp_int * a) -{ - if (a->dp != NULL) { - - /* first zero the digits */ - memset (a->dp, 0, sizeof (mp_digit) * a->used); - - /* free ram */ - XFREE (a->dp); - - /* reset members to make debugging easier */ - a->dp = NULL; - a->alloc = a->used = 0; - } -} - -/* End: bn_mp_clear.c */ - -/* Start: bn_mp_cmp.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* compare two ints (signed)*/ -int -mp_cmp (mp_int * a, mp_int * b) -{ - /* compare based on sign */ - if (a->sign == MP_NEG && b->sign == MP_ZPOS) { - return MP_LT; - } else if (a->sign == MP_ZPOS && b->sign == MP_NEG) { - return MP_GT; - } - return mp_cmp_mag (a, b); -} - -/* End: bn_mp_cmp.c */ - -/* Start: bn_mp_cmp_d.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* compare a digit */ -int -mp_cmp_d (mp_int * a, mp_digit b) -{ - - if (a->sign == MP_NEG) { - return MP_LT; - } - - if (a->used > 1) { - return MP_GT; - } - - if (a->dp[0] > b) { - return MP_GT; - } else if (a->dp[0] < b) { - return MP_LT; - } else { - return MP_EQ; - } -} - -/* End: bn_mp_cmp_d.c */ - -/* Start: bn_mp_cmp_mag.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* compare maginitude of two ints (unsigned) */ -int -mp_cmp_mag (mp_int * a, mp_int * b) -{ - int n; - - /* compare based on # of non-zero digits */ - if (a->used > b->used) { - return MP_GT; - } else if (a->used < b->used) { - return MP_LT; - } - - /* compare based on digits */ - for (n = a->used - 1; n >= 0; n--) { - if (a->dp[n] > b->dp[n]) { - return MP_GT; - } else if (a->dp[n] < b->dp[n]) { - return MP_LT; - } - } - return MP_EQ; -} - -/* End: bn_mp_cmp_mag.c */ - -/* Start: bn_mp_copy.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* copy, b = a */ -int -mp_copy (mp_int * a, mp_int * b) -{ - int res, n; - - /* if dst == src do nothing */ - if (a == b || a->dp == b->dp) { - return MP_OKAY; - } - - /* grow dest */ - if ((res = mp_grow (b, a->used)) != MP_OKAY) { - return res; - } - - /* zero b and copy the parameters over */ - b->used = a->used; - b->sign = a->sign; - - { - register mp_digit *tmpa, *tmpb; - - /* point aliases */ - tmpa = a->dp; - tmpb = b->dp; - - /* copy all the digits */ - for (n = 0; n < a->used; n++) { - *tmpb++ = *tmpa++; - } - - /* clear high digits */ - for (; n < b->alloc; n++) { - *tmpb++ = 0; - } - } - return MP_OKAY; -} - -/* End: bn_mp_copy.c */ - -/* Start: bn_mp_count_bits.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* returns the number of bits in an int */ -int -mp_count_bits (mp_int * a) -{ - int r; - mp_digit q; - - if (a->used == 0) { - return 0; - } - - r = (a->used - 1) * DIGIT_BIT; - q = a->dp[a->used - 1]; - while (q > ((mp_digit) 0)) { - ++r; - q >>= ((mp_digit) 1); - } - return r; -} - -/* End: bn_mp_count_bits.c */ - -/* Start: bn_mp_div.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* integer signed division. c*b + d == a [e.g. a/b, c=quotient, d=remainder] - * HAC pp.598 Algorithm 14.20 - * - * Note that the description in HAC is horribly incomplete. For example, - * it doesn't consider the case where digits are removed from 'x' in the inner - * loop. It also doesn't consider the case that y has fewer than three digits, etc.. - * - * The overall algorithm is as described as 14.20 from HAC but fixed to treat these cases. -*/ -int -mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d) -{ - mp_int q, x, y, t1, t2; - int res, n, t, i, norm, neg; - - - /* is divisor zero ? */ - if (mp_iszero (b) == 1) { - return MP_VAL; - } - - /* if a < b then q=0, r = a */ - if (mp_cmp_mag (a, b) == MP_LT) { - if (d != NULL) { - res = mp_copy (a, d); - } else { - res = MP_OKAY; - } - if (c != NULL) { - mp_zero (c); - } - return res; - } - - if ((res = mp_init_size (&q, a->used + 2)) != MP_OKAY) { - return res; - } - q.used = a->used + 2; - - if ((res = mp_init (&t1)) != MP_OKAY) { - goto __Q; - } - - if ((res = mp_init (&t2)) != MP_OKAY) { - goto __T1; - } - - if ((res = mp_init_copy (&x, a)) != MP_OKAY) { - goto __T2; - } - - if ((res = mp_init_copy (&y, b)) != MP_OKAY) { - goto __X; - } - - /* fix the sign */ - neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; - x.sign = y.sign = MP_ZPOS; - - /* normalize both x and y, ensure that y >= b/2, [b == 2^DIGIT_BIT] */ - norm = mp_count_bits(&y) % DIGIT_BIT; - if (norm < (DIGIT_BIT-1)) { - norm = (DIGIT_BIT-1) - norm; - if ((res = mp_mul_2d (&x, norm, &x)) != MP_OKAY) { - goto __Y; - } - if ((res = mp_mul_2d (&y, norm, &y)) != MP_OKAY) { - goto __Y; - } - } else { - norm = 0; - } - - /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */ - n = x.used - 1; - t = y.used - 1; - - /* step 2. while (x >= y*b^n-t) do { q[n-t] += 1; x -= y*b^{n-t} } */ - if ((res = mp_lshd (&y, n - t)) != MP_OKAY) { /* y = y*b^{n-t} */ - goto __Y; - } - - while (mp_cmp (&x, &y) != MP_LT) { - ++(q.dp[n - t]); - if ((res = mp_sub (&x, &y, &x)) != MP_OKAY) { - goto __Y; - } - } - - /* reset y by shifting it back down */ - mp_rshd (&y, n - t); - - /* step 3. for i from n down to (t + 1) */ - for (i = n; i >= (t + 1); i--) { - if (i > x.used) - continue; - - /* step 3.1 if xi == yt then set q{i-t-1} to b-1, otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */ - if (x.dp[i] == y.dp[t]) { - q.dp[i - t - 1] = ((1UL << DIGIT_BIT) - 1UL); - } else { - mp_word tmp; - tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT); - tmp |= ((mp_word) x.dp[i - 1]); - tmp /= ((mp_word) y.dp[t]); - if (tmp > (mp_word) MP_MASK) - tmp = MP_MASK; - q.dp[i - t - 1] = (mp_digit) (tmp & (mp_word) (MP_MASK)); - } - - /* step 3.2 while (q{i-t-1} * (yt * b + y{t-1})) > xi * b^2 + xi-1 * b + xi-2 do q{i-t-1} -= 1; */ - q.dp[i - t - 1] = (q.dp[i - t - 1] + 1) & MP_MASK; - do { - q.dp[i - t - 1] = (q.dp[i - t - 1] - 1) & MP_MASK; - - /* find left hand */ - mp_zero (&t1); - t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1]; - t1.dp[1] = y.dp[t]; - t1.used = 2; - if ((res = mp_mul_d (&t1, q.dp[i - t - 1], &t1)) != MP_OKAY) { - goto __Y; - } - - /* find right hand */ - t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2]; - t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1]; - t2.dp[2] = x.dp[i]; - t2.used = 3; - } while (mp_cmp (&t1, &t2) == MP_GT); - - /* step 3.3 x = x - q{i-t-1} * y * b^{i-t-1} */ - if ((res = mp_mul_d (&y, q.dp[i - t - 1], &t1)) != MP_OKAY) { - goto __Y; - } - - if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) { - goto __Y; - } - - if ((res = mp_sub (&x, &t1, &x)) != MP_OKAY) { - goto __Y; - } - - /* step 3.4 if x < 0 then { x = x + y*b^{i-t-1}; q{i-t-1} -= 1; } */ - if (x.sign == MP_NEG) { - if ((res = mp_copy (&y, &t1)) != MP_OKAY) { - goto __Y; - } - if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) { - goto __Y; - } - if ((res = mp_add (&x, &t1, &x)) != MP_OKAY) { - goto __Y; - } - - q.dp[i - t - 1] = (q.dp[i - t - 1] - 1UL) & MP_MASK; - } - } - - /* now q is the quotient and x is the remainder [which we have to normalize] */ - /* get sign before writing to c */ - x.sign = a->sign; - - if (c != NULL) { - mp_clamp (&q); - mp_exch (&q, c); - c->sign = neg; - } - - if (d != NULL) { - mp_div_2d (&x, norm, &x, NULL); - mp_exch (&x, d); - } - - res = MP_OKAY; - -__Y:mp_clear (&y); -__X:mp_clear (&x); -__T2:mp_clear (&t2); -__T1:mp_clear (&t1); -__Q:mp_clear (&q); - return res; -} - -/* End: bn_mp_div.c */ - -/* Start: bn_mp_div_2.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* b = a/2 */ -int -mp_div_2 (mp_int * a, mp_int * b) -{ - int x, res, oldused; - - /* copy */ - if (b->alloc < a->used) { - if ((res = mp_grow (b, a->used)) != MP_OKAY) { - return res; - } - } - - oldused = b->used; - b->used = a->used; - { - register mp_digit r, rr, *tmpa, *tmpb; - - /* source alias */ - tmpa = a->dp + b->used - 1; - - /* dest alias */ - tmpb = b->dp + b->used - 1; - - /* carry */ - r = 0; - for (x = b->used - 1; x >= 0; x--) { - /* get the carry for the next iteration */ - rr = *tmpa & 1; - - /* shift the current digit, add in carry and store */ - *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1)); - - /* forward carry to next iteration */ - r = rr; - } - - /* zero excess digits */ - tmpb = b->dp + b->used; - for (x = b->used; x < oldused; x++) { - *tmpb++ = 0; - } - } - b->sign = a->sign; - mp_clamp (b); - return MP_OKAY; -} - -/* End: bn_mp_div_2.c */ - -/* Start: bn_mp_div_2d.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* shift right by a certain bit count (store quotient in c, remainder in d) */ -int -mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d) -{ - mp_digit D, r, rr; - int x, res; - mp_int t; - - - /* if the shift count is <= 0 then we do no work */ - if (b <= 0) { - res = mp_copy (a, c); - if (d != NULL) { - mp_zero (d); - } - return res; - } - - if ((res = mp_init (&t)) != MP_OKAY) { - return res; - } - - /* get the remainder */ - if (d != NULL) { - if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) { - mp_clear (&t); - return res; - } - } - - /* copy */ - if ((res = mp_copy (a, c)) != MP_OKAY) { - mp_clear (&t); - return res; - } - - /* shift by as many digits in the bit count */ - if (b >= DIGIT_BIT) { - mp_rshd (c, b / DIGIT_BIT); - } - - /* shift any bit count < DIGIT_BIT */ - D = (mp_digit) (b % DIGIT_BIT); - if (D != 0) { - register mp_digit *tmpc, mask; - - /* mask */ - mask = (1U << D) - 1U; - - /* alias */ - tmpc = c->dp + (c->used - 1); - - /* carry */ - r = 0; - for (x = c->used - 1; x >= 0; x--) { - /* get the lower bits of this word in a temp */ - rr = *tmpc & mask; - - /* shift the current word and mix in the carry bits from the previous word */ - *tmpc = (*tmpc >> D) | (r << (DIGIT_BIT - D)); - --tmpc; - - /* set the carry to the carry bits of the current word found above */ - r = rr; - } - } - mp_clamp (c); - res = MP_OKAY; - if (d != NULL) { - mp_exch (&t, d); - } - mp_clear (&t); - return MP_OKAY; -} - -/* End: bn_mp_div_2d.c */ - -/* Start: bn_mp_div_d.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* single digit division */ -int -mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d) -{ - mp_int t, t2; - int res; - - if ((res = mp_init (&t)) != MP_OKAY) { - return res; - } - - if ((res = mp_init (&t2)) != MP_OKAY) { - mp_clear (&t); - return res; - } - - mp_set (&t, b); - res = mp_div (a, &t, c, &t2); - - /* set remainder if not null */ - if (d != NULL) { - *d = t2.dp[0]; - } - - mp_clear (&t); - mp_clear (&t2); - return res; -} - -/* End: bn_mp_div_d.c */ - -/* Start: bn_mp_dr_reduce.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* reduce "a" in place modulo "b" using the Diminished Radix algorithm. - * - * Based on algorithm from the paper - * - * "Generating Efficient Primes for Discrete Log Cryptosystems" - * Chae Hoon Lim, Pil Loong Lee, - * POSTECH Information Research Laboratories - * - * The modulus must be of a special format [see manual] - */ -int -mp_dr_reduce (mp_int * a, mp_int * b, mp_digit mp) -{ - int err, i, j, k; - mp_word r; - mp_digit mu, *tmpj, *tmpi; - - /* k = digits in modulus */ - k = b->used; - - /* ensure that "a" has at least 2k digits */ - if (a->alloc < k + k) { - if ((err = mp_grow (a, k + k)) != MP_OKAY) { - return err; - } - } - - /* alias for a->dp[i] */ - tmpi = a->dp + k + k - 1; - - /* for (i = 2k - 1; i >= k; i = i - 1) - * - * This is the main loop of the reduction. Note that at the end - * the words above position k are not zeroed as expected. The end - * result is that the digits from 0 to k-1 are the residue. So - * we have to clear those afterwards. - */ - for (i = k + k - 1; i >= k; i = i - 1) { - /* x[i - 1 : i - k] += x[i]*mp */ - - /* x[i] * mp */ - r = ((mp_word) *tmpi--) * ((mp_word) mp); - - /* now add r to x[i-1:i-k] - * - * First add it to the first digit x[i-k] then form the carry - * then enter the main loop - */ - j = i - k; - - /* alias for a->dp[j] */ - tmpj = a->dp + j; - - /* add digit */ - *tmpj += (mp_digit)(r & MP_MASK); - - /* this is the carry */ - mu = (r >> ((mp_word) DIGIT_BIT)) + (*tmpj >> DIGIT_BIT); - - /* clear carry from a->dp[j] */ - *tmpj++ &= MP_MASK; - - /* now add rest of the digits - * - * Note this is basically a simple single digit addition to - * a larger multiple digit number. This is optimized somewhat - * because the propagation of carries is not likely to move - * more than a few digits. - * - */ - for (++j; mu != 0 && j <= (i - 1); ++j) { - *tmpj += mu; - mu = *tmpj >> DIGIT_BIT; - *tmpj++ &= MP_MASK; - } - - /* if final carry */ - if (mu != 0) { - /* add mp to this to correct */ - j = i - k; - tmpj = a->dp + j; - - *tmpj += mp; - mu = *tmpj >> DIGIT_BIT; - *tmpj++ &= MP_MASK; - - /* now handle carries */ - for (++j; mu != 0 && j <= (i - 1); j++) { - *tmpj += mu; - mu = *tmpj >> DIGIT_BIT; - *tmpj++ &= MP_MASK; - } - } - } - - /* zero words above k */ - tmpi = a->dp + k; - for (i = k; i < a->used; i++) { - *tmpi++ = 0; - } - - /* clamp, sub and return */ - mp_clamp (a); - - if (mp_cmp_mag (a, b) != MP_LT) { - return s_mp_sub (a, b, a); - } - return MP_OKAY; -} - -/* determines if a number is a valid DR modulus */ -int mp_dr_is_modulus(mp_int *a) -{ - int ix; - - /* must be at least two digits */ - if (a->used < 2) { - return 0; - } - - for (ix = 1; ix < a->used; ix++) { - if (a->dp[ix] != MP_MASK) { - return 0; - } - } - return 1; -} - -/* determines the setup value */ -void mp_dr_setup(mp_int *a, mp_digit *d) -{ - *d = (1 << DIGIT_BIT) - a->dp[0]; -} - - -/* End: bn_mp_dr_reduce.c */ - -/* Start: bn_mp_exch.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* swap the elements of two integers, for cases where you can't simply swap the - * mp_int pointers around - */ -void -mp_exch (mp_int * a, mp_int * b) -{ - mp_int t; - - t = *a; - *a = *b; - *b = t; -} - -/* End: bn_mp_exch.c */ - -/* Start: bn_mp_exptmod.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -static int f_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y); - -/* this is a shell function that calls either the normal or Montgomery - * exptmod functions. Originally the call to the montgomery code was - * embedded in the normal function but that wasted alot of stack space - * for nothing (since 99% of the time the Montgomery code would be called) - */ -int -mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) -{ - int dr; - - dr = mp_dr_is_modulus(P); - /* if the modulus is odd use the fast method */ - if (((mp_isodd (P) == 1 && P->used < MONTGOMERY_EXPT_CUTOFF) || dr == 1) && P->used > 4) { - return mp_exptmod_fast (G, X, P, Y, dr); - } else { - return f_mp_exptmod (G, X, P, Y); - } -} - -static int -f_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) -{ - mp_int M[256], res, mu; - mp_digit buf; - int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; - - /* find window size */ - x = mp_count_bits (X); - if (x <= 7) { - winsize = 2; - } else if (x <= 36) { - winsize = 3; - } else if (x <= 140) { - winsize = 4; - } else if (x <= 450) { - winsize = 5; - } else if (x <= 1303) { - winsize = 6; - } else if (x <= 3529) { - winsize = 7; - } else { - winsize = 8; - } - - /* init G array */ - for (x = 0; x < (1 << winsize); x++) { - if ((err = mp_init_size (&M[x], 1)) != MP_OKAY) { - for (y = 0; y < x; y++) { - mp_clear (&M[y]); - } - return err; - } - } - - /* create mu, used for Barrett reduction */ - if ((err = mp_init (&mu)) != MP_OKAY) { - goto __M; - } - if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) { - goto __MU; - } - - /* create M table - * - * The M table contains powers of the input base, e.g. M[x] = G^x mod P - * - * The first half of the table is not computed though accept for M[0] and M[1] - */ - if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) { - goto __MU; - } - - /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */ - if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) { - goto __MU; - } - - for (x = 0; x < (winsize - 1); x++) { - if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) { - goto __MU; - } - if ((err = mp_reduce (&M[1 << (winsize - 1)], P, &mu)) != MP_OKAY) { - goto __MU; - } - } - - /* create upper table */ - for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { - if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) { - goto __MU; - } - if ((err = mp_reduce (&M[x], P, &mu)) != MP_OKAY) { - goto __MU; - } - } - - /* setup result */ - if ((err = mp_init (&res)) != MP_OKAY) { - goto __MU; - } - mp_set (&res, 1); - - /* set initial mode and bit cnt */ - mode = 0; - bitcnt = 0; - buf = 0; - digidx = X->used - 1; - bitcpy = bitbuf = 0; - - bitcnt = 1; - for (;;) { - /* grab next digit as required */ - if (--bitcnt == 0) { - if (digidx == -1) { - break; - } - buf = X->dp[digidx--]; - bitcnt = (int) DIGIT_BIT; - } - - /* grab the next msb from the exponent */ - y = (buf >> (DIGIT_BIT - 1)) & 1; - buf <<= 1; - - /* if the bit is zero and mode == 0 then we ignore it - * These represent the leading zero bits before the first 1 bit - * in the exponent. Technically this opt is not required but it - * does lower the # of trivial squaring/reductions used - */ - if (mode == 0 && y == 0) - continue; - - /* if the bit is zero and mode == 1 then we square */ - if (mode == 1 && y == 0) { - if ((err = mp_sqr (&res, &res)) != MP_OKAY) { - goto __RES; - } - if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) { - goto __RES; - } - continue; - } - - /* else we add it to the window */ - bitbuf |= (y << (winsize - ++bitcpy)); - mode = 2; - - if (bitcpy == winsize) { - /* ok window is filled so square as required and multiply */ - /* square first */ - for (x = 0; x < winsize; x++) { - if ((err = mp_sqr (&res, &res)) != MP_OKAY) { - goto __RES; - } - if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) { - goto __RES; - } - } - - /* then multiply */ - if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) { - goto __MU; - } - if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) { - goto __MU; - } - - /* empty window and reset */ - bitcpy = bitbuf = 0; - mode = 1; - } - } - - /* if bits remain then square/multiply */ - if (mode == 2 && bitcpy > 0) { - /* square then multiply if the bit is set */ - for (x = 0; x < bitcpy; x++) { - if ((err = mp_sqr (&res, &res)) != MP_OKAY) { - goto __RES; - } - if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) { - goto __RES; - } - - bitbuf <<= 1; - if ((bitbuf & (1 << winsize)) != 0) { - /* then multiply */ - if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) { - goto __RES; - } - if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) { - goto __RES; - } - } - } - } - - mp_exch (&res, Y); - err = MP_OKAY; -__RES:mp_clear (&res); -__MU:mp_clear (&mu); -__M: - for (x = 0; x < (1 << winsize); x++) { - mp_clear (&M[x]); - } - return err; -} - -/* End: bn_mp_exptmod.c */ - -/* Start: bn_mp_exptmod_fast.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* computes Y == G^X mod P, HAC pp.616, Algorithm 14.85 - * - * Uses a left-to-right k-ary sliding window to compute the modular exponentiation. - * The value of k changes based on the size of the exponent. - * - * Uses Montgomery or Diminished Radix reduction [whichever appropriate] - */ -int -mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) -{ - mp_int M[256], res; - mp_digit buf, mp; - int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; - int (*redux)(mp_int*,mp_int*,mp_digit); - - /* find window size */ - x = mp_count_bits (X); - if (x <= 7) { - winsize = 2; - } else if (x <= 36) { - winsize = 3; - } else if (x <= 140) { - winsize = 4; - } else if (x <= 450) { - winsize = 5; - } else if (x <= 1303) { - winsize = 6; - } else if (x <= 3529) { - winsize = 7; - } else { - winsize = 8; - } - - /* init G array */ - for (x = 0; x < (1 << winsize); x++) { - if ((err = mp_init (&M[x])) != MP_OKAY) { - for (y = 0; y < x; y++) { - mp_clear (&M[y]); - } - return err; - } - } - - if (redmode == 0) { - /* now setup montgomery */ - if ((err = mp_montgomery_setup (P, &mp)) != MP_OKAY) { - goto __M; - } - redux = mp_montgomery_reduce; - } else { - /* setup DR reduction */ - mp_dr_setup(P, &mp); - redux = mp_dr_reduce; - } - - /* setup result */ - if ((err = mp_init (&res)) != MP_OKAY) { - goto __RES; - } - - /* create M table - * - * The M table contains powers of the input base, e.g. M[x] = G^x mod P - * - * The first half of the table is not computed though accept for M[0] and M[1] - */ - - if (redmode == 0) { - /* now we need R mod m */ - if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) { - goto __RES; - } - - /* now set M[1] to G * R mod m */ - if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) { - goto __RES; - } - } else { - mp_set(&res, 1); - if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) { - goto __RES; - } - } - - /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */ - if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) { - goto __RES; - } - - for (x = 0; x < (winsize - 1); x++) { - if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) { - goto __RES; - } - if ((err = redux (&M[1 << (winsize - 1)], P, mp)) != MP_OKAY) { - goto __RES; - } - } - - /* create upper table */ - for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { - if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) { - goto __RES; - } - if ((err = redux (&M[x], P, mp)) != MP_OKAY) { - goto __RES; - } - } - - /* set initial mode and bit cnt */ - mode = 0; - bitcnt = 0; - buf = 0; - digidx = X->used - 1; - bitcpy = bitbuf = 0; - - bitcnt = 1; - for (;;) { - /* grab next digit as required */ - if (--bitcnt == 0) { - if (digidx == -1) { - break; - } - buf = X->dp[digidx--]; - bitcnt = (int) DIGIT_BIT; - } - - /* grab the next msb from the exponent */ - y = (buf >> (DIGIT_BIT - 1)) & 1; - buf <<= 1; - - /* if the bit is zero and mode == 0 then we ignore it - * These represent the leading zero bits before the first 1 bit - * in the exponent. Technically this opt is not required but it - * does lower the # of trivial squaring/reductions used - */ - if (mode == 0 && y == 0) - continue; - - /* if the bit is zero and mode == 1 then we square */ - if (mode == 1 && y == 0) { - if ((err = mp_sqr (&res, &res)) != MP_OKAY) { - goto __RES; - } - if ((err = redux (&res, P, mp)) != MP_OKAY) { - goto __RES; - } - continue; - } - - /* else we add it to the window */ - bitbuf |= (y << (winsize - ++bitcpy)); - mode = 2; - - if (bitcpy == winsize) { - /* ok window is filled so square as required and multiply */ - /* square first */ - for (x = 0; x < winsize; x++) { - if ((err = mp_sqr (&res, &res)) != MP_OKAY) { - goto __RES; - } - if ((err = redux (&res, P, mp)) != MP_OKAY) { - goto __RES; - } - } - - /* then multiply */ - if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) { - goto __RES; - } - if ((err = redux (&res, P, mp)) != MP_OKAY) { - goto __RES; - } - - /* empty window and reset */ - bitcpy = bitbuf = 0; - mode = 1; - } - } - - /* if bits remain then square/multiply */ - if (mode == 2 && bitcpy > 0) { - /* square then multiply if the bit is set */ - for (x = 0; x < bitcpy; x++) { - if ((err = mp_sqr (&res, &res)) != MP_OKAY) { - goto __RES; - } - if ((err = redux (&res, P, mp)) != MP_OKAY) { - goto __RES; - } - - bitbuf <<= 1; - if ((bitbuf & (1 << winsize)) != 0) { - /* then multiply */ - if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) { - goto __RES; - } - if ((err = redux (&res, P, mp)) != MP_OKAY) { - goto __RES; - } - } - } - } - - if (redmode == 0) { - /* fixup result */ - if ((err = mp_montgomery_reduce (&res, P, mp)) != MP_OKAY) { - goto __RES; - } - } - - mp_exch (&res, Y); - err = MP_OKAY; -__RES:mp_clear (&res); -__M: - for (x = 0; x < (1 << winsize); x++) { - mp_clear (&M[x]); - } - return err; -} - -/* End: bn_mp_exptmod_fast.c */ - -/* Start: bn_mp_expt_d.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* calculate c = a^b using a square-multiply algorithm */ -int -mp_expt_d (mp_int * a, mp_digit b, mp_int * c) -{ - int res, x; - mp_int g; - - if ((res = mp_init_copy (&g, a)) != MP_OKAY) { - return res; - } - - /* set initial result */ - mp_set (c, 1); - - for (x = 0; x < (int) DIGIT_BIT; x++) { - /* square */ - if ((res = mp_sqr (c, c)) != MP_OKAY) { - mp_clear (&g); - return res; - } - - /* if the bit is set multiply */ - if ((b & (mp_digit) (1 << (DIGIT_BIT - 1))) != 0) { - if ((res = mp_mul (c, &g, c)) != MP_OKAY) { - mp_clear (&g); - return res; - } - } - - /* shift to next bit */ - b <<= 1; - } - - mp_clear (&g); - return MP_OKAY; -} - -/* End: bn_mp_expt_d.c */ - -/* Start: bn_mp_gcd.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* Greatest Common Divisor using the binary method [Algorithm B, page 338, vol2 of TAOCP] - */ -int -mp_gcd (mp_int * a, mp_int * b, mp_int * c) -{ - mp_int u, v, t; - int k, res, neg; - - /* either zero than gcd is the largest */ - if (mp_iszero (a) == 1 && mp_iszero (b) == 0) { - return mp_copy (b, c); - } - if (mp_iszero (a) == 0 && mp_iszero (b) == 1) { - return mp_copy (a, c); - } - if (mp_iszero (a) == 1 && mp_iszero (b) == 1) { - mp_set (c, 1); - return MP_OKAY; - } - - /* if both are negative they share (-1) as a common divisor */ - neg = (a->sign == b->sign) ? a->sign : MP_ZPOS; - - if ((res = mp_init_copy (&u, a)) != MP_OKAY) { - return res; - } - - if ((res = mp_init_copy (&v, b)) != MP_OKAY) { - goto __U; - } - - /* must be positive for the remainder of the algorithm */ - u.sign = v.sign = MP_ZPOS; - - if ((res = mp_init (&t)) != MP_OKAY) { - goto __V; - } - - /* B1. Find power of two */ - k = 0; - while (mp_iseven(&u) == 1 && mp_iseven(&v) == 1) { - ++k; - if ((res = mp_div_2 (&u, &u)) != MP_OKAY) { - goto __T; - } - if ((res = mp_div_2 (&v, &v)) != MP_OKAY) { - goto __T; - } - } - - /* B2. Initialize */ - if (mp_isodd(&u) == 1) { - /* t = -v */ - if ((res = mp_copy (&v, &t)) != MP_OKAY) { - goto __T; - } - t.sign = MP_NEG; - } else { - /* t = u */ - if ((res = mp_copy (&u, &t)) != MP_OKAY) { - goto __T; - } - } - - do { - /* B3 (and B4). Halve t, if even */ - while (t.used != 0 && mp_iseven(&t) == 1) { - if ((res = mp_div_2 (&t, &t)) != MP_OKAY) { - goto __T; - } - } - - /* B5. if t>0 then u=t otherwise v=-t */ - if (t.used != 0 && t.sign != MP_NEG) { - if ((res = mp_copy (&t, &u)) != MP_OKAY) { - goto __T; - } - } else { - if ((res = mp_copy (&t, &v)) != MP_OKAY) { - goto __T; - } - v.sign = (v.sign == MP_ZPOS) ? MP_NEG : MP_ZPOS; - } - - /* B6. t = u - v, if t != 0 loop otherwise terminate */ - if ((res = mp_sub (&u, &v, &t)) != MP_OKAY) { - goto __T; - } - } - while (t.used != 0); - - if ((res = mp_mul_2d (&u, k, &u)) != MP_OKAY) { - goto __T; - } - - mp_exch (&u, c); - c->sign = neg; - res = MP_OKAY; -__T:mp_clear (&t); -__V:mp_clear (&u); -__U:mp_clear (&v); - return res; -} - -/* End: bn_mp_gcd.c */ - -/* Start: bn_mp_grow.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* grow as required */ -int -mp_grow (mp_int * a, int size) -{ - int i, n; - - /* if the alloc size is smaller alloc more ram */ - if (a->alloc < size) { - /* ensure there are always at least MP_PREC digits extra on top */ - size += (MP_PREC * 2) - (size & (MP_PREC - 1)); - - a->dp = OPT_CAST XREALLOC (a->dp, sizeof (mp_digit) * size); - if (a->dp == NULL) { - return MP_MEM; - } - - /* zero excess digits */ - n = a->alloc; - a->alloc = size; - for (i = n; i < a->alloc; i++) { - a->dp[i] = 0; - } - } - return MP_OKAY; -} - -/* End: bn_mp_grow.c */ - -/* Start: bn_mp_init.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* init a new bigint */ -int -mp_init (mp_int * a) -{ - - /* allocate ram required and clear it */ - a->dp = OPT_CAST XCALLOC (sizeof (mp_digit), MP_PREC); - if (a->dp == NULL) { - return MP_MEM; - } - - /* set the used to zero, allocated digit to the default precision - * and sign to positive */ - a->used = 0; - a->alloc = MP_PREC; - a->sign = MP_ZPOS; - - return MP_OKAY; -} - -/* End: bn_mp_init.c */ - -/* Start: bn_mp_init_copy.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* creates "a" then copies b into it */ -int -mp_init_copy (mp_int * a, mp_int * b) -{ - int res; - - if ((res = mp_init (a)) != MP_OKAY) { - return res; - } - return mp_copy (b, a); -} - -/* End: bn_mp_init_copy.c */ - -/* Start: bn_mp_init_size.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* init a mp_init and grow it to a given size */ -int -mp_init_size (mp_int * a, int size) -{ - - /* pad size so there are always extra digits */ - size += (MP_PREC * 2) - (size & (MP_PREC - 1)); - - /* alloc mem */ - a->dp = OPT_CAST XCALLOC (sizeof (mp_digit), size); - if (a->dp == NULL) { - return MP_MEM; - } - a->used = 0; - a->alloc = size; - a->sign = MP_ZPOS; - - return MP_OKAY; -} - -/* End: bn_mp_init_size.c */ - -/* Start: bn_mp_invmod.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -int -mp_invmod (mp_int * a, mp_int * b, mp_int * c) -{ - mp_int x, y, u, v, A, B, C, D; - int res; - - /* b cannot be negative */ - if (b->sign == MP_NEG) { - return MP_VAL; - } - - /* if the modulus is odd we can use a faster routine instead */ - if (mp_iseven (b) == 0) { - return fast_mp_invmod (a, b, c); - } - - if ((res = mp_init (&x)) != MP_OKAY) { - goto __ERR; - } - - if ((res = mp_init (&y)) != MP_OKAY) { - goto __X; - } - - if ((res = mp_init (&u)) != MP_OKAY) { - goto __Y; - } - - if ((res = mp_init (&v)) != MP_OKAY) { - goto __U; - } - - if ((res = mp_init (&A)) != MP_OKAY) { - goto __V; - } - - if ((res = mp_init (&B)) != MP_OKAY) { - goto __A; - } - - if ((res = mp_init (&C)) != MP_OKAY) { - goto __B; - } - - if ((res = mp_init (&D)) != MP_OKAY) { - goto __C; - } - - /* x = a, y = b */ - if ((res = mp_copy (a, &x)) != MP_OKAY) { - goto __D; - } - if ((res = mp_copy (b, &y)) != MP_OKAY) { - goto __D; - } - - if ((res = mp_abs (&x, &x)) != MP_OKAY) { - goto __D; - } - - /* 2. [modified] if x,y are both even then return an error! */ - if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) { - res = MP_VAL; - goto __D; - } - - /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ - if ((res = mp_copy (&x, &u)) != MP_OKAY) { - goto __D; - } - if ((res = mp_copy (&y, &v)) != MP_OKAY) { - goto __D; - } - mp_set (&A, 1); - mp_set (&D, 1); - - -top: - /* 4. while u is even do */ - while (mp_iseven (&u) == 1) { - /* 4.1 u = u/2 */ - if ((res = mp_div_2 (&u, &u)) != MP_OKAY) { - goto __D; - } - /* 4.2 if A or B is odd then */ - if (mp_iseven (&A) == 0 || mp_iseven (&B) == 0) { - /* A = (A+y)/2, B = (B-x)/2 */ - if ((res = mp_add (&A, &y, &A)) != MP_OKAY) { - goto __D; - } - if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) { - goto __D; - } - } - /* A = A/2, B = B/2 */ - if ((res = mp_div_2 (&A, &A)) != MP_OKAY) { - goto __D; - } - if ((res = mp_div_2 (&B, &B)) != MP_OKAY) { - goto __D; - } - } - - - /* 5. while v is even do */ - while (mp_iseven (&v) == 1) { - /* 5.1 v = v/2 */ - if ((res = mp_div_2 (&v, &v)) != MP_OKAY) { - goto __D; - } - /* 5.2 if C,D are even then */ - if (mp_iseven (&C) == 0 || mp_iseven (&D) == 0) { - /* C = (C+y)/2, D = (D-x)/2 */ - if ((res = mp_add (&C, &y, &C)) != MP_OKAY) { - goto __D; - } - if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) { - goto __D; - } - } - /* C = C/2, D = D/2 */ - if ((res = mp_div_2 (&C, &C)) != MP_OKAY) { - goto __D; - } - if ((res = mp_div_2 (&D, &D)) != MP_OKAY) { - goto __D; - } - } - - /* 6. if u >= v then */ - if (mp_cmp (&u, &v) != MP_LT) { - /* u = u - v, A = A - C, B = B - D */ - if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) { - goto __D; - } - - if ((res = mp_sub (&A, &C, &A)) != MP_OKAY) { - goto __D; - } - - if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) { - goto __D; - } - } else { - /* v - v - u, C = C - A, D = D - B */ - if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) { - goto __D; - } - - if ((res = mp_sub (&C, &A, &C)) != MP_OKAY) { - goto __D; - } - - if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) { - goto __D; - } - } - - /* if not zero goto step 4 */ - if (mp_iszero (&u) == 0) - goto top; - - /* now a = C, b = D, gcd == g*v */ - - /* if v != 1 then there is no inverse */ - if (mp_cmp_d (&v, 1) != MP_EQ) { - res = MP_VAL; - goto __D; - } - - /* a is now the inverse */ - mp_exch (&C, c); - res = MP_OKAY; - -__D:mp_clear (&D); -__C:mp_clear (&C); -__B:mp_clear (&B); -__A:mp_clear (&A); -__V:mp_clear (&v); -__U:mp_clear (&u); -__Y:mp_clear (&y); -__X:mp_clear (&x); -__ERR: - return res; -} - -/* End: bn_mp_invmod.c */ - -/* Start: bn_mp_jacobi.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* computes the jacobi c = (a | n) (or Legendre if b is prime) - * HAC pp. 73 Algorithm 2.149 - */ -int -mp_jacobi (mp_int * a, mp_int * n, int *c) -{ - mp_int a1, n1, e; - int s, r, res; - mp_digit residue; - - /* step 1. if a == 0, return 0 */ - if (mp_iszero (a) == 1) { - *c = 0; - return MP_OKAY; - } - - /* step 2. if a == 1, return 1 */ - if (mp_cmp_d (a, 1) == MP_EQ) { - *c = 1; - return MP_OKAY; - } - - /* default */ - s = 0; - - /* step 3. write a = a1 * 2^e */ - if ((res = mp_init_copy (&a1, a)) != MP_OKAY) { - return res; - } - - if ((res = mp_init (&n1)) != MP_OKAY) { - goto __A1; - } - - if ((res = mp_init (&e)) != MP_OKAY) { - goto __N1; - } - - while (mp_iseven (&a1) == 1) { - if ((res = mp_add_d (&e, 1, &e)) != MP_OKAY) { - goto __E; - } - - if ((res = mp_div_2 (&a1, &a1)) != MP_OKAY) { - goto __E; - } - } - - /* step 4. if e is even set s=1 */ - if (mp_iseven (&e) == 1) { - s = 1; - } else { - /* else set s=1 if n = 1/7 (mod 8) or s=-1 if n = 3/5 (mod 8) */ - if ((res = mp_mod_d (n, 8, &residue)) != MP_OKAY) { - goto __E; - } - - if (residue == 1 || residue == 7) { - s = 1; - } else if (residue == 3 || residue == 5) { - s = -1; - } - } - - /* step 5. if n == 3 (mod 4) *and* a1 == 3 (mod 4) then s = -s */ - if ((res = mp_mod_d (n, 4, &residue)) != MP_OKAY) { - goto __E; - } - if (residue == 3) { - if ((res = mp_mod_d (&a1, 4, &residue)) != MP_OKAY) { - goto __E; - } - if (residue == 3) { - s = -s; - } - } - - /* if a1 == 1 we're done */ - if (mp_cmp_d (&a1, 1) == MP_EQ) { - *c = s; - } else { - /* n1 = n mod a1 */ - if ((res = mp_mod (n, &a1, &n1)) != MP_OKAY) { - goto __E; - } - if ((res = mp_jacobi (&n1, &a1, &r)) != MP_OKAY) { - goto __E; - } - *c = s * r; - } - - /* done */ - res = MP_OKAY; -__E:mp_clear (&e); -__N1:mp_clear (&n1); -__A1:mp_clear (&a1); - return res; -} - -/* End: bn_mp_jacobi.c */ - -/* Start: bn_mp_karatsuba_mul.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* c = |a| * |b| using Karatsuba Multiplication using three half size multiplications - * - * Let B represent the radix [e.g. 2**DIGIT_BIT] and let n represent half of the number of digits in the min(a,b) - * - * a = a1 * B^n + a0 - * b = b1 * B^n + b0 - * - * Then, a * b => a1b1 * B^2n + ((a1 - b1)(a0 - b0) + a0b0 + a1b1) * B + a0b0 - * - * Note that a1b1 and a0b0 are used twice and only need to be computed once. So in total - * three half size (half # of digit) multiplications are performed, a0b0, a1b1 and (a1-b1)(a0-b0) - * - * Note that a multiplication of half the digits requires 1/4th the number of single precision - * multiplications so in total after one call 25% of the single precision multiplications are saved. - * Note also that the call to mp_mul can end up back in this function if the a0, a1, b0, or b1 are above - * the threshold. This is known as divide-and-conquer and leads to the famous O(N^lg(3)) or O(N^1.584) work which - * is asymptopically lower than the standard O(N^2) that the baseline/comba methods use. Generally though the - * overhead of this method doesn't pay off until a certain size (N ~ 80) is reached. - */ -int -mp_karatsuba_mul (mp_int * a, mp_int * b, mp_int * c) -{ - mp_int x0, x1, y0, y1, t1, t2, x0y0, x1y1; - int B, err; - - err = MP_MEM; - - /* min # of digits */ - B = MIN (a->used, b->used); - - /* now divide in two */ - B = B / 2; - - /* init copy all the temps */ - if (mp_init_size (&x0, B) != MP_OKAY) - goto ERR; - if (mp_init_size (&x1, a->used - B) != MP_OKAY) - goto X0; - if (mp_init_size (&y0, B) != MP_OKAY) - goto X1; - if (mp_init_size (&y1, b->used - B) != MP_OKAY) - goto Y0; - - /* init temps */ - if (mp_init_size (&t1, B * 2) != MP_OKAY) - goto Y1; - if (mp_init_size (&t2, B * 2) != MP_OKAY) - goto T1; - if (mp_init_size (&x0y0, B * 2) != MP_OKAY) - goto T2; - if (mp_init_size (&x1y1, B * 2) != MP_OKAY) - goto X0Y0; - - /* now shift the digits */ - x0.sign = x1.sign = a->sign; - y0.sign = y1.sign = b->sign; - - x0.used = y0.used = B; - x1.used = a->used - B; - y1.used = b->used - B; - - { - register int x; - register mp_digit *tmpa, *tmpb, *tmpx, *tmpy; - - /* we copy the digits directly instead of using higher level functions - * since we also need to shift the digits - */ - tmpa = a->dp; - tmpb = b->dp; - - tmpx = x0.dp; - tmpy = y0.dp; - for (x = 0; x < B; x++) { - *tmpx++ = *tmpa++; - *tmpy++ = *tmpb++; - } - - tmpx = x1.dp; - for (x = B; x < a->used; x++) { - *tmpx++ = *tmpa++; - } - - tmpy = y1.dp; - for (x = B; x < b->used; x++) { - *tmpy++ = *tmpb++; - } - } - - /* only need to clamp the lower words since by definition the upper words x1/y1 must - * have a known number of digits - */ - mp_clamp (&x0); - mp_clamp (&y0); - - /* now calc the products x0y0 and x1y1 */ - if (mp_mul (&x0, &y0, &x0y0) != MP_OKAY) - goto X1Y1; /* x0y0 = x0*y0 */ - if (mp_mul (&x1, &y1, &x1y1) != MP_OKAY) - goto X1Y1; /* x1y1 = x1*y1 */ - - /* now calc x1-x0 and y1-y0 */ - if (mp_sub (&x1, &x0, &t1) != MP_OKAY) - goto X1Y1; /* t1 = x1 - x0 */ - if (mp_sub (&y1, &y0, &t2) != MP_OKAY) - goto X1Y1; /* t2 = y1 - y0 */ - if (mp_mul (&t1, &t2, &t1) != MP_OKAY) - goto X1Y1; /* t1 = (x1 - x0) * (y1 - y0) */ - - /* add x0y0 */ - if (mp_add (&x0y0, &x1y1, &t2) != MP_OKAY) - goto X1Y1; /* t2 = x0y0 + x1y1 */ - if (mp_sub (&t2, &t1, &t1) != MP_OKAY) - goto X1Y1; /* t1 = x0y0 + x1y1 - (x1-x0)*(y1-y0) */ - - /* shift by B */ - if (mp_lshd (&t1, B) != MP_OKAY) - goto X1Y1; /* t1 = (x0y0 + x1y1 - (x1-x0)*(y1-y0))< - -/* Karatsuba squaring, computes b = a*a using three half size squarings - * - * See comments of mp_karatsuba_mul for details. It is essentially the same algorithm - * but merely tuned to perform recursive squarings. - */ -int -mp_karatsuba_sqr (mp_int * a, mp_int * b) -{ - mp_int x0, x1, t1, t2, x0x0, x1x1; - int B, err; - - err = MP_MEM; - - /* min # of digits */ - B = a->used; - - /* now divide in two */ - B = B / 2; - - /* init copy all the temps */ - if (mp_init_size (&x0, B) != MP_OKAY) - goto ERR; - if (mp_init_size (&x1, a->used - B) != MP_OKAY) - goto X0; - - /* init temps */ - if (mp_init_size (&t1, a->used * 2) != MP_OKAY) - goto X1; - if (mp_init_size (&t2, a->used * 2) != MP_OKAY) - goto T1; - if (mp_init_size (&x0x0, B * 2) != MP_OKAY) - goto T2; - if (mp_init_size (&x1x1, (a->used - B) * 2) != MP_OKAY) - goto X0X0; - - { - register int x; - register mp_digit *dst, *src; - - src = a->dp; - - /* now shift the digits */ - dst = x0.dp; - for (x = 0; x < B; x++) { - *dst++ = *src++; - } - - dst = x1.dp; - for (x = B; x < a->used; x++) { - *dst++ = *src++; - } - } - - x0.used = B; - x1.used = a->used - B; - - mp_clamp (&x0); - - /* now calc the products x0*x0 and x1*x1 */ - if (mp_sqr (&x0, &x0x0) != MP_OKAY) - goto X1X1; /* x0x0 = x0*x0 */ - if (mp_sqr (&x1, &x1x1) != MP_OKAY) - goto X1X1; /* x1x1 = x1*x1 */ - - /* now calc x1-x0 and y1-y0 */ - if (mp_sub (&x1, &x0, &t1) != MP_OKAY) - goto X1X1; /* t1 = x1 - x0 */ - if (mp_sqr (&t1, &t1) != MP_OKAY) - goto X1X1; /* t1 = (x1 - x0) * (y1 - y0) */ - - /* add x0y0 */ - if (s_mp_add (&x0x0, &x1x1, &t2) != MP_OKAY) - goto X1X1; /* t2 = x0y0 + x1y1 */ - if (mp_sub (&t2, &t1, &t1) != MP_OKAY) - goto X1X1; /* t1 = x0y0 + x1y1 - (x1-x0)*(y1-y0) */ - - /* shift by B */ - if (mp_lshd (&t1, B) != MP_OKAY) - goto X1X1; /* t1 = (x0y0 + x1y1 - (x1-x0)*(y1-y0))< - -/* computes least common multiple as a*b/(a, b) */ -int -mp_lcm (mp_int * a, mp_int * b, mp_int * c) -{ - int res; - mp_int t; - - - if ((res = mp_init (&t)) != MP_OKAY) { - return res; - } - - if ((res = mp_mul (a, b, &t)) != MP_OKAY) { - mp_clear (&t); - return res; - } - - if ((res = mp_gcd (a, b, c)) != MP_OKAY) { - mp_clear (&t); - return res; - } - - res = mp_div (&t, c, c, NULL); - mp_clear (&t); - return res; -} - -/* End: bn_mp_lcm.c */ - -/* Start: bn_mp_lshd.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* shift left a certain amount of digits */ -int -mp_lshd (mp_int * a, int b) -{ - int x, res; - - - /* if its less than zero return */ - if (b <= 0) { - return MP_OKAY; - } - - /* grow to fit the new digits */ - if ((res = mp_grow (a, a->used + b)) != MP_OKAY) { - return res; - } - - { - register mp_digit *tmpa, *tmpaa; - - /* increment the used by the shift amount than copy upwards */ - a->used += b; - - /* top */ - tmpa = a->dp + a->used - 1; - - /* base */ - tmpaa = a->dp + a->used - 1 - b; - - /* much like mp_rshd this is implemented using a sliding window - * except the window goes the otherway around. Copying from - * the bottom to the top. see bn_mp_rshd.c for more info. - */ - for (x = a->used - 1; x >= b; x--) { - *tmpa-- = *tmpaa--; - } - - /* zero the lower digits */ - tmpa = a->dp; - for (x = 0; x < b; x++) { - *tmpa++ = 0; - } - } - return MP_OKAY; -} - -/* End: bn_mp_lshd.c */ - -/* Start: bn_mp_mod.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* c = a mod b, 0 <= c < b */ -int -mp_mod (mp_int * a, mp_int * b, mp_int * c) -{ - mp_int t; - int res; - - - if ((res = mp_init (&t)) != MP_OKAY) { - return res; - } - - if ((res = mp_div (a, b, NULL, &t)) != MP_OKAY) { - mp_clear (&t); - return res; - } - - if (t.sign == MP_NEG) { - res = mp_add (b, &t, c); - } else { - res = MP_OKAY; - mp_exch (&t, c); - } - - mp_clear (&t); - return res; -} - -/* End: bn_mp_mod.c */ - -/* Start: bn_mp_mod_2d.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* calc a value mod 2^b */ -int -mp_mod_2d (mp_int * a, int b, mp_int * c) -{ - int x, res; - - - /* if b is <= 0 then zero the int */ - if (b <= 0) { - mp_zero (c); - return MP_OKAY; - } - - /* if the modulus is larger than the value than return */ - if (b > (int) (a->used * DIGIT_BIT)) { - res = mp_copy (a, c); - return res; - } - - /* copy */ - if ((res = mp_copy (a, c)) != MP_OKAY) { - return res; - } - - /* zero digits above the last digit of the modulus */ - for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) { - c->dp[x] = 0; - } - /* clear the digit that is not completely outside/inside the modulus */ - c->dp[b / DIGIT_BIT] &= - (mp_digit) ((((mp_digit) 1) << (((mp_digit) b) % DIGIT_BIT)) - ((mp_digit) 1)); - mp_clamp (c); - return MP_OKAY; -} - -/* End: bn_mp_mod_2d.c */ - -/* Start: bn_mp_mod_d.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -int -mp_mod_d (mp_int * a, mp_digit b, mp_digit * c) -{ - mp_int t, t2; - int res; - - - if ((res = mp_init (&t)) != MP_OKAY) { - return res; - } - - if ((res = mp_init (&t2)) != MP_OKAY) { - mp_clear (&t); - return res; - } - - mp_set (&t, b); - mp_div (a, &t, NULL, &t2); - - if (t2.sign == MP_NEG) { - if ((res = mp_add_d (&t2, b, &t2)) != MP_OKAY) { - mp_clear (&t); - mp_clear (&t2); - return res; - } - } - *c = t2.dp[0]; - mp_clear (&t); - mp_clear (&t2); - return MP_OKAY; -} - -/* End: bn_mp_mod_d.c */ - -/* Start: bn_mp_montgomery_calc_normalization.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* calculates a = B^n mod b for Montgomery reduction - * Where B is the base [e.g. 2^DIGIT_BIT]. - * B^n mod b is computed by first computing - * A = B^(n-1) which doesn't require a reduction but a simple OR. - * then C = A * B = B^n is computed by performing upto DIGIT_BIT - * shifts with subtractions when the result is greater than b. - * - * The method is slightly modified to shift B unconditionally upto just under - * the leading bit of b. This saves alot of multiple precision shifting. - */ -int -mp_montgomery_calc_normalization (mp_int * a, mp_int * b) -{ - int x, bits, res; - - /* how many bits of last digit does b use */ - bits = mp_count_bits (b) % DIGIT_BIT; - - /* compute A = B^(n-1) * 2^(bits-1) */ - if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) { - return res; - } - - /* now compute C = A * B mod b */ - for (x = bits - 1; x < DIGIT_BIT; x++) { - if ((res = mp_mul_2 (a, a)) != MP_OKAY) { - return res; - } - if (mp_cmp_mag (a, b) != MP_LT) { - if ((res = s_mp_sub (a, b, a)) != MP_OKAY) { - return res; - } - } - } - - return MP_OKAY; -} - -/* End: bn_mp_montgomery_calc_normalization.c */ - -/* Start: bn_mp_montgomery_reduce.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* computes xR^-1 == x (mod N) via Montgomery Reduction */ -int -mp_montgomery_reduce (mp_int * a, mp_int * m, mp_digit mp) -{ - int ix, res, digs; - mp_digit ui; - - digs = m->used * 2 + 1; - if ((digs < 512) - && digs < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { - return fast_mp_montgomery_reduce (a, m, mp); - } - - if (a->alloc < m->used * 2 + 1) { - if ((res = mp_grow (a, m->used * 2 + 1)) != MP_OKAY) { - return res; - } - } - a->used = m->used * 2 + 1; - - for (ix = 0; ix < m->used; ix++) { - /* ui = ai * m' mod b */ - ui = (a->dp[ix] * mp) & MP_MASK; - - /* a = a + ui * m * b^i */ - { - register int iy; - register mp_digit *tmpx, *tmpy, mu; - register mp_word r; - - /* aliases */ - tmpx = m->dp; - tmpy = a->dp + ix; - - mu = 0; - for (iy = 0; iy < m->used; iy++) { - r = ((mp_word) ui) * ((mp_word) * tmpx++) + ((mp_word) mu) + ((mp_word) * tmpy); - mu = (r >> ((mp_word) DIGIT_BIT)); - *tmpy++ = (r & ((mp_word) MP_MASK)); - } - /* propagate carries */ - while (mu) { - *tmpy += mu; - mu = (*tmpy >> DIGIT_BIT) & 1; - *tmpy++ &= MP_MASK; - } - } - } - - /* A = A/b^n */ - mp_rshd (a, m->used); - - /* if A >= m then A = A - m */ - if (mp_cmp_mag (a, m) != MP_LT) { - return s_mp_sub (a, m, a); - } - - return MP_OKAY; -} - -/* End: bn_mp_montgomery_reduce.c */ - -/* Start: bn_mp_montgomery_setup.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* setups the montgomery reduction stuff */ -int -mp_montgomery_setup (mp_int * a, mp_digit * mp) -{ - unsigned long x, b; - -/* fast inversion mod 2^32 - * - * Based on the fact that - * - * XA = 1 (mod 2^n) => (X(2-XA)) A = 1 (mod 2^2n) - * => 2*X*A - X*X*A*A = 1 - * => 2*(1) - (1) = 1 - */ - b = a->dp[0]; - - if ((b & 1) == 0) { - return MP_VAL; - } - - x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2^4 */ - x *= 2 - b * x; /* here x*a==1 mod 2^8 */ - x *= 2 - b * x; /* here x*a==1 mod 2^16; each step doubles the nb of bits */ - x *= 2 - b * x; /* here x*a==1 mod 2^32 */ - - /* t = -1/m mod b */ - *mp = ((mp_digit) 1 << ((mp_digit) DIGIT_BIT)) - (x & MP_MASK); - - return MP_OKAY; -} - -/* End: bn_mp_montgomery_setup.c */ - -/* Start: bn_mp_mul.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* high level multiplication (handles sign) */ -int -mp_mul (mp_int * a, mp_int * b, mp_int * c) -{ - int res, neg; - neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; - if (MIN (a->used, b->used) > KARATSUBA_MUL_CUTOFF) { - res = mp_karatsuba_mul (a, b, c); - } else { - - /* can we use the fast multiplier? - * - * The fast multiplier can be used if the output will have less than - * 512 digits and the number of digits won't affect carry propagation - */ - int digs = a->used + b->used + 1; - - if ((digs < 512) - && digs < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { - res = fast_s_mp_mul_digs (a, b, c, digs); - } else { - res = s_mp_mul (a, b, c); - } - - } - c->sign = neg; - return res; -} - -/* End: bn_mp_mul.c */ - -/* Start: bn_mp_mulmod.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* d = a * b (mod c) */ -int -mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) -{ - int res; - mp_int t; - - - if ((res = mp_init (&t)) != MP_OKAY) { - return res; - } - - if ((res = mp_mul (a, b, &t)) != MP_OKAY) { - mp_clear (&t); - return res; - } - res = mp_mod (&t, c, d); - mp_clear (&t); - return res; -} - -/* End: bn_mp_mulmod.c */ - -/* Start: bn_mp_mul_2.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* b = a*2 */ -int -mp_mul_2 (mp_int * a, mp_int * b) -{ - int x, res, oldused; - - /* Optimization: should copy and shift at the same time */ - - if (b->alloc < a->used) { - if ((res = mp_grow (b, a->used)) != MP_OKAY) { - return res; - } - } - - oldused = b->used; - b->used = a->used; - - /* shift any bit count < DIGIT_BIT */ - { - register mp_digit r, rr, *tmpa, *tmpb; - - /* alias for source */ - tmpa = a->dp; - - /* alias for dest */ - tmpb = b->dp; - - /* carry */ - r = 0; - for (x = 0; x < b->used; x++) { - - /* get what will be the *next* carry bit from the MSB of the current digit */ - rr = *tmpa >> (DIGIT_BIT - 1); - - /* now shift up this digit, add in the carry [from the previous] */ - *tmpb++ = ((*tmpa++ << 1) | r) & MP_MASK; - - /* copy the carry that would be from the source digit into the next iteration */ - r = rr; - } - - /* new leading digit? */ - if (r != 0) { - /* do we have to grow to accomodate the new digit? */ - if (b->alloc == b->used) { - if ((res = mp_grow (b, b->used + 1)) != MP_OKAY) { - return res; - } - - /* after the grow *tmpb is no longer valid so we have to reset it! - * (this bug took me about 17 minutes to find...!) - */ - tmpb = b->dp + b->used; - } - /* add a MSB which is always 1 at this point */ - *tmpb = 1; - ++b->used; - } - - /* now zero any excess digits on the destination that we didn't write to */ - tmpb = b->dp + b->used; - for (x = b->used; x < oldused; x++) { - *tmpb++ = 0; - } - } - b->sign = a->sign; - return MP_OKAY; -} - -/* End: bn_mp_mul_2.c */ - -/* Start: bn_mp_mul_2d.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* shift left by a certain bit count */ -int -mp_mul_2d (mp_int * a, int b, mp_int * c) -{ - mp_digit d, r, rr; - int x, res; - - /* copy */ - if ((res = mp_copy (a, c)) != MP_OKAY) { - return res; - } - - if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) { - return res; - } - - /* shift by as many digits in the bit count */ - if (b >= DIGIT_BIT) { - if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) { - return res; - } - } - c->used = c->alloc; - - /* shift any bit count < DIGIT_BIT */ - d = (mp_digit) (b % DIGIT_BIT); - if (d != 0) { - register mp_digit *tmpc, mask; - - /* bitmask for carries */ - mask = (1U << d) - 1U; - - /* alias */ - tmpc = c->dp; - - /* carry */ - r = 0; - for (x = 0; x < c->used; x++) { - /* get the higher bits of the current word */ - rr = (*tmpc >> (DIGIT_BIT - d)) & mask; - - /* shift the current word and OR in the carry */ - *tmpc = ((*tmpc << d) | r) & MP_MASK; - ++tmpc; - - /* set the carry to the carry bits of the current word */ - r = rr; - } - } - mp_clamp (c); - return MP_OKAY; -} - -/* End: bn_mp_mul_2d.c */ - -/* Start: bn_mp_mul_d.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* multiply by a digit */ -int -mp_mul_d (mp_int * a, mp_digit b, mp_int * c) -{ - int res, pa, olduse; - - pa = a->used; - if (c->alloc < pa + 1) { - if ((res = mp_grow (c, pa + 1)) != MP_OKAY) { - return res; - } - } - - olduse = c->used; - c->used = pa + 1; - - { - register mp_digit u, *tmpa, *tmpc; - register mp_word r; - register int ix; - - tmpc = c->dp + c->used; - for (ix = c->used; ix < olduse; ix++) { - *tmpc++ = 0; - } - - tmpa = a->dp; - tmpc = c->dp; - - u = 0; - for (ix = 0; ix < pa; ix++) { - r = ((mp_word) u) + ((mp_word) * tmpa++) * ((mp_word) b); - *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK)); - u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); - } - *tmpc = u; - } - - mp_clamp (c); - return MP_OKAY; -} - -/* End: bn_mp_mul_d.c */ - -/* Start: bn_mp_neg.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* b = -a */ -int -mp_neg (mp_int * a, mp_int * b) -{ - int res; - if ((res = mp_copy (a, b)) != MP_OKAY) { - return res; - } - b->sign = (a->sign == MP_ZPOS) ? MP_NEG : MP_ZPOS; - return MP_OKAY; -} - -/* End: bn_mp_neg.c */ - -/* Start: bn_mp_n_root.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* find the n'th root of an integer - * - * Result found such that (c)^b <= a and (c+1)^b > a - * - * This algorithm uses Newton's approximation x[i+1] = x[i] - f(x[i])/f'(x[i]) - * which will find the root in log(N) time where each step involves a fair bit. This - * is not meant to find huge roots [square and cube at most]. - */ -int -mp_n_root (mp_int * a, mp_digit b, mp_int * c) -{ - mp_int t1, t2, t3; - int res, neg; - - /* input must be positive if b is even */ - if ((b & 1) == 0 && a->sign == MP_NEG) { - return MP_VAL; - } - - if ((res = mp_init (&t1)) != MP_OKAY) { - return res; - } - - if ((res = mp_init (&t2)) != MP_OKAY) { - goto __T1; - } - - if ((res = mp_init (&t3)) != MP_OKAY) { - goto __T2; - } - - /* if a is negative fudge the sign but keep track */ - neg = a->sign; - a->sign = MP_ZPOS; - - /* t2 = 2 */ - mp_set (&t2, 2); - - do { - /* t1 = t2 */ - if ((res = mp_copy (&t2, &t1)) != MP_OKAY) { - goto __T3; - } - - /* t2 = t1 - ((t1^b - a) / (b * t1^(b-1))) */ - if ((res = mp_expt_d (&t1, b - 1, &t3)) != MP_OKAY) { /* t3 = t1^(b-1) */ - goto __T3; - } - - /* numerator */ - if ((res = mp_mul (&t3, &t1, &t2)) != MP_OKAY) { /* t2 = t1^b */ - goto __T3; - } - - if ((res = mp_sub (&t2, a, &t2)) != MP_OKAY) { /* t2 = t1^b - a */ - goto __T3; - } - - if ((res = mp_mul_d (&t3, b, &t3)) != MP_OKAY) { /* t3 = t1^(b-1) * b */ - goto __T3; - } - - if ((res = mp_div (&t2, &t3, &t3, NULL)) != MP_OKAY) { /* t3 = (t1^b - a)/(b * t1^(b-1)) */ - goto __T3; - } - - if ((res = mp_sub (&t1, &t3, &t2)) != MP_OKAY) { - goto __T3; - } - } - while (mp_cmp (&t1, &t2) != MP_EQ); - - /* result can be off by a few so check */ - for (;;) { - if ((res = mp_expt_d (&t1, b, &t2)) != MP_OKAY) { - goto __T3; - } - - if (mp_cmp (&t2, a) == MP_GT) { - if ((res = mp_sub_d (&t1, 1, &t1)) != MP_OKAY) { - goto __T3; - } - } else { - break; - } - } - - /* reset the sign of a first */ - a->sign = neg; - - /* set the result */ - mp_exch (&t1, c); - - /* set the sign of the result */ - c->sign = neg; - - res = MP_OKAY; - -__T3:mp_clear (&t3); -__T2:mp_clear (&t2); -__T1:mp_clear (&t1); - return res; -} - -/* End: bn_mp_n_root.c */ - -/* Start: bn_mp_or.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* OR two ints together */ -int -mp_or (mp_int * a, mp_int * b, mp_int * c) -{ - int res, ix, px; - mp_int t, *x; - - if (a->used > b->used) { - if ((res = mp_init_copy (&t, a)) != MP_OKAY) { - return res; - } - px = b->used; - x = b; - } else { - if ((res = mp_init_copy (&t, b)) != MP_OKAY) { - return res; - } - px = a->used; - x = a; - } - - for (ix = 0; ix < px; ix++) { - t.dp[ix] |= x->dp[ix]; - } - mp_clamp (&t); - mp_exch (c, &t); - mp_clear (&t); - return MP_OKAY; -} - -/* End: bn_mp_or.c */ - -/* Start: bn_mp_prime_fermat.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* performs one Fermat test. - * - * If "a" were prime then b^a == b (mod a) since the order of - * the multiplicative sub-group would be phi(a) = a-1. That means - * it would be the same as b^(a mod (a-1)) == b^1 == b (mod a). - * - * Sets result to 1 if the congruence holds, or zero otherwise. - */ -int -mp_prime_fermat (mp_int * a, mp_int * b, int *result) -{ - mp_int t; - int err; - - /* default to fail */ - *result = 0; - - /* init t */ - if ((err = mp_init (&t)) != MP_OKAY) { - return err; - } - - /* compute t = b^a mod a */ - if ((err = mp_exptmod (b, a, a, &t)) != MP_OKAY) { - goto __T; - } - - /* is it equal to b? */ - if (mp_cmp (&t, b) == MP_EQ) { - *result = 1; - } - - err = MP_OKAY; -__T:mp_clear (&t); - return err; -} - -/* End: bn_mp_prime_fermat.c */ - -/* Start: bn_mp_prime_is_divisible.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* determines if an integers is divisible by one of the first 256 primes or not - * - * sets result to 0 if not, 1 if yes - */ -int -mp_prime_is_divisible (mp_int * a, int *result) -{ - int err, ix; - mp_digit res; - - /* default to not */ - *result = 0; - - for (ix = 0; ix < 256; ix++) { - /* is it equal to the prime? */ - if (mp_cmp_d (a, __prime_tab[ix]) == MP_EQ) { - *result = 1; - return MP_OKAY; - } - - /* what is a mod __prime_tab[ix] */ - if ((err = mp_mod_d (a, __prime_tab[ix], &res)) != MP_OKAY) { - return err; - } - - /* is the residue zero? */ - if (res == 0) { - *result = 1; - return MP_OKAY; - } - } - - return MP_OKAY; -} - -/* End: bn_mp_prime_is_divisible.c */ - -/* Start: bn_mp_prime_is_prime.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* performs a variable number of rounds of Miller-Rabin - * - * Probability of error after t rounds is no more than - * (1/4)^t when 1 <= t <= 256 - * - * Sets result to 1 if probably prime, 0 otherwise - */ -int -mp_prime_is_prime (mp_int * a, int t, int *result) -{ - mp_int b; - int ix, err, res; - - /* default to no */ - *result = 0; - - /* valid value of t? */ - if (t < 1 || t > 256) { - return MP_VAL; - } - - /* first perform trial division */ - if ((err = mp_prime_is_divisible (a, &res)) != MP_OKAY) { - return err; - } - if (res == 1) { - return MP_OKAY; - } - - /* now perform the miller-rabin rounds */ - if ((err = mp_init (&b)) != MP_OKAY) { - return err; - } - - for (ix = 0; ix < t; ix++) { - /* set the prime */ - mp_set (&b, __prime_tab[ix]); - - if ((err = mp_prime_miller_rabin (a, &b, &res)) != MP_OKAY) { - goto __B; - } - - if (res == 0) { - goto __B; - } - } - - /* passed the test */ - *result = 1; -__B:mp_clear (&b); - return err; -} - -/* End: bn_mp_prime_is_prime.c */ - -/* Start: bn_mp_prime_miller_rabin.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* Miller-Rabin test of "a" to the base of "b" as described in - * HAC pp. 139 Algorithm 4.24 - * - * Sets result to 0 if definitely composite or 1 if probably prime. - * Randomly the chance of error is no more than 1/4 and often - * very much lower. - */ -int -mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result) -{ - mp_int n1, y, r; - int s, j, err; - - /* default */ - *result = 0; - - /* get n1 = a - 1 */ - if ((err = mp_init_copy (&n1, a)) != MP_OKAY) { - return err; - } - if ((err = mp_sub_d (&n1, 1, &n1)) != MP_OKAY) { - goto __N1; - } - - /* set 2^s * r = n1 */ - if ((err = mp_init_copy (&r, &n1)) != MP_OKAY) { - goto __N1; - } - s = 0; - while (mp_iseven (&r) == 1) { - ++s; - if ((err = mp_div_2 (&r, &r)) != MP_OKAY) { - goto __R; - } - } - - /* compute y = b^r mod a */ - if ((err = mp_init (&y)) != MP_OKAY) { - goto __R; - } - if ((err = mp_exptmod (b, &r, a, &y)) != MP_OKAY) { - goto __Y; - } - - /* if y != 1 and y != n1 do */ - if (mp_cmp_d (&y, 1) != MP_EQ && mp_cmp (&y, &n1) != MP_EQ) { - j = 1; - /* while j <= s-1 and y != n1 */ - while ((j <= (s - 1)) && mp_cmp (&y, &n1) != MP_EQ) { - if ((err = mp_sqrmod (&y, a, &y)) != MP_OKAY) { - goto __Y; - } - - /* if y == 1 then composite */ - if (mp_cmp_d (&y, 1) == MP_EQ) { - goto __Y; - } - - ++j; - } - - /* if y != n1 then composite */ - if (mp_cmp (&y, &n1) != MP_EQ) { - goto __Y; - } - } - - /* probably prime now */ - *result = 1; -__Y:mp_clear (&y); -__R:mp_clear (&r); -__N1:mp_clear (&n1); - return err; -} - -/* End: bn_mp_prime_miller_rabin.c */ - -/* Start: bn_mp_prime_next_prime.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* finds the next prime after the number "a" using "t" trials - * of Miller-Rabin. - */ -int mp_prime_next_prime(mp_int *a, int t) -{ - int err, res; - - if (mp_iseven(a) == 1) { - /* force odd */ - if ((err = mp_add_d(a, 1, a)) != MP_OKAY) { - return err; - } - } else { - /* force to next number */ - if ((err = mp_add_d(a, 2, a)) != MP_OKAY) { - return err; - } - } - - for (;;) { - /* is this prime? */ - if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { - return err; - } - - if (res == 1) { - break; - } - - /* add two, next candidate */ - if ((err = mp_add_d(a, 2, a)) != MP_OKAY) { - return err; - } - } - - return MP_OKAY; -} - - -/* End: bn_mp_prime_next_prime.c */ - -/* Start: bn_mp_rand.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* makes a pseudo-random int of a given size */ -int -mp_rand (mp_int * a, int digits) -{ - int res; - mp_digit d; - - mp_zero (a); - if (digits <= 0) { - return MP_OKAY; - } - - /* first place a random non-zero digit */ - do { - d = ((mp_digit) abs (rand ())); - } while (d == 0); - - if ((res = mp_add_d (a, d, a)) != MP_OKAY) { - return res; - } - - while (digits-- > 0) { - if ((res = mp_lshd (a, 1)) != MP_OKAY) { - return res; - } - - if ((res = mp_add_d (a, ((mp_digit) abs (rand ())), a)) != MP_OKAY) { - return res; - } - } - - return MP_OKAY; -} - -/* End: bn_mp_rand.c */ - -/* Start: bn_mp_read_signed_bin.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* read signed bin, big endian, first byte is 0==positive or 1==negative */ -int -mp_read_signed_bin (mp_int * a, unsigned char *b, int c) -{ - int res; - - if ((res = mp_read_unsigned_bin (a, b + 1, c - 1)) != MP_OKAY) { - return res; - } - a->sign = ((b[0] == (unsigned char) 0) ? MP_ZPOS : MP_NEG); - return MP_OKAY; -} - -/* End: bn_mp_read_signed_bin.c */ - -/* Start: bn_mp_read_unsigned_bin.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* reads a unsigned char array, assumes the msb is stored first [big endian] */ -int -mp_read_unsigned_bin (mp_int * a, unsigned char *b, int c) -{ - int res; - mp_zero (a); - while (c-- > 0) { - if ((res = mp_mul_2d (a, 8, a)) != MP_OKAY) { - return res; - } - - if (DIGIT_BIT != 7) { - a->dp[0] |= *b++; - a->used += 1; - } else { - a->dp[0] = (*b & MP_MASK); - a->dp[1] |= ((*b++ >> 7U) & 1); - a->used += 2; - } - } - mp_clamp (a); - return MP_OKAY; -} - -/* End: bn_mp_read_unsigned_bin.c */ - -/* Start: bn_mp_reduce.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* pre-calculate the value required for Barrett reduction - * For a given modulus "b" it calulates the value required in "a" - */ -int -mp_reduce_setup (mp_int * a, mp_int * b) -{ - int res; - - - if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) { - return res; - } - res = mp_div (a, b, a, NULL); - return res; -} - -/* reduces x mod m, assumes 0 < x < m^2, mu is precomputed via mp_reduce_setup - * From HAC pp.604 Algorithm 14.42 - */ -int -mp_reduce (mp_int * x, mp_int * m, mp_int * mu) -{ - mp_int q; - int res, um = m->used; - - - if ((res = mp_init_copy (&q, x)) != MP_OKAY) { - return res; - } - - mp_rshd (&q, um - 1); /* q1 = x / b^(k-1) */ - - /* according to HAC this is optimization is ok */ - if (((unsigned long) m->used) > (1UL << (unsigned long) (DIGIT_BIT - 1UL))) { - if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) { - goto CLEANUP; - } - } else { - if ((res = s_mp_mul_high_digs (&q, mu, &q, um - 1)) != MP_OKAY) { - goto CLEANUP; - } - } - - mp_rshd (&q, um + 1); /* q3 = q2 / b^(k+1) */ - - /* x = x mod b^(k+1), quick (no division) */ - if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) { - goto CLEANUP; - } - - /* q = q * m mod b^(k+1), quick (no division) */ - if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) { - goto CLEANUP; - } - - /* x = x - q */ - if ((res = mp_sub (x, &q, x)) != MP_OKAY) - goto CLEANUP; - - /* If x < 0, add b^(k+1) to it */ - if (mp_cmp_d (x, 0) == MP_LT) { - mp_set (&q, 1); - if ((res = mp_lshd (&q, um + 1)) != MP_OKAY) - goto CLEANUP; - if ((res = mp_add (x, &q, x)) != MP_OKAY) - goto CLEANUP; - } - - /* Back off if it's too big */ - while (mp_cmp (x, m) != MP_LT) { - if ((res = s_mp_sub (x, m, x)) != MP_OKAY) - break; - } - -CLEANUP: - mp_clear (&q); - - return res; -} - -/* End: bn_mp_reduce.c */ - -/* Start: bn_mp_rshd.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* shift right a certain amount of digits */ -void -mp_rshd (mp_int * a, int b) -{ - int x; - - /* if b <= 0 then ignore it */ - if (b <= 0) { - return; - } - - /* if b > used then simply zero it and return */ - if (a->used < b) { - mp_zero (a); - return; - } - - { - register mp_digit *tmpa, *tmpaa; - - /* shift the digits down */ - - /* base */ - tmpa = a->dp; - - /* offset into digits */ - tmpaa = a->dp + b; - - /* this is implemented as a sliding window where the window is b-digits long - * and digits from the top of the window are copied to the bottom - * - * e.g. - - b-2 | b-1 | b0 | b1 | b2 | ... | bb | ----> - /\ | ----> - \-------------------/ ----> - */ - for (x = 0; x < (a->used - b); x++) { - *tmpa++ = *tmpaa++; - } - - /* zero the top digits */ - for (; x < a->used; x++) { - *tmpa++ = 0; - } - } - mp_clamp (a); -} - -/* End: bn_mp_rshd.c */ - -/* Start: bn_mp_set.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* set to a digit */ -void -mp_set (mp_int * a, mp_digit b) -{ - mp_zero (a); - a->dp[0] = b & MP_MASK; - a->used = (a->dp[0] != 0) ? 1 : 0; -} - -/* End: bn_mp_set.c */ - -/* Start: bn_mp_set_int.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* set a 32-bit const */ -int -mp_set_int (mp_int * a, unsigned long b) -{ - int x, res; - - mp_zero (a); - - /* set four bits at a time, simplest solution to the what if DIGIT_BIT==7 case */ - for (x = 0; x < 8; x++) { - - /* shift the number up four bits */ - if ((res = mp_mul_2d (a, 4, a)) != MP_OKAY) { - return res; - } - - /* OR in the top four bits of the source */ - a->dp[0] |= (b >> 28) & 15; - - /* shift the source up to the next four bits */ - b <<= 4; - - /* ensure that digits are not clamped off */ - a->used += 32 / DIGIT_BIT + 1; - } - - mp_clamp (a); - return MP_OKAY; -} - -/* End: bn_mp_set_int.c */ - -/* Start: bn_mp_shrink.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* shrink a bignum */ -int -mp_shrink (mp_int * a) -{ - if (a->alloc != a->used) { - if ((a->dp = OPT_CAST XREALLOC (a->dp, sizeof (mp_digit) * a->used)) == NULL) { - return MP_MEM; - } - a->alloc = a->used; - } - return MP_OKAY; -} - -/* End: bn_mp_shrink.c */ - -/* Start: bn_mp_signed_bin_size.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* get the size for an signed equivalent */ -int -mp_signed_bin_size (mp_int * a) -{ - return 1 + mp_unsigned_bin_size (a); -} - -/* End: bn_mp_signed_bin_size.c */ - -/* Start: bn_mp_sqr.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* computes b = a*a */ -int -mp_sqr (mp_int * a, mp_int * b) -{ - int res; - if (a->used > KARATSUBA_SQR_CUTOFF) { - res = mp_karatsuba_sqr (a, b); - } else { - - /* can we use the fast multiplier? */ - if (((a->used * 2 + 1) < 512) - && a->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT) - 1))) { - res = fast_s_mp_sqr (a, b); - } else { - res = s_mp_sqr (a, b); - } - } - b->sign = MP_ZPOS; - return res; -} - -/* End: bn_mp_sqr.c */ - -/* Start: bn_mp_sqrmod.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* c = a * a (mod b) */ -int -mp_sqrmod (mp_int * a, mp_int * b, mp_int * c) -{ - int res; - mp_int t; - - - if ((res = mp_init (&t)) != MP_OKAY) { - return res; - } - - if ((res = mp_sqr (a, &t)) != MP_OKAY) { - mp_clear (&t); - return res; - } - res = mp_mod (&t, b, c); - mp_clear (&t); - return res; -} - -/* End: bn_mp_sqrmod.c */ - -/* Start: bn_mp_sub.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* high level subtraction (handles signs) */ -int -mp_sub (mp_int * a, mp_int * b, mp_int * c) -{ - int sa, sb, res; - - - sa = a->sign; - sb = b->sign; - - /* handle four cases */ - if (sa == MP_ZPOS && sb == MP_ZPOS) { - /* both positive, a - b, but if b>a then we do -(b - a) */ - if (mp_cmp_mag (a, b) == MP_LT) { - /* b>a */ - res = s_mp_sub (b, a, c); - c->sign = MP_NEG; - } else { - res = s_mp_sub (a, b, c); - c->sign = MP_ZPOS; - } - } else if (sa == MP_ZPOS && sb == MP_NEG) { - /* a - -b == a + b */ - res = s_mp_add (a, b, c); - c->sign = MP_ZPOS; - } else if (sa == MP_NEG && sb == MP_ZPOS) { - /* -a - b == -(a + b) */ - res = s_mp_add (a, b, c); - c->sign = MP_NEG; - } else { - /* -a - -b == b - a, but if a>b == -(a - b) */ - if (mp_cmp_mag (a, b) == MP_GT) { - res = s_mp_sub (a, b, c); - c->sign = MP_NEG; - } else { - res = s_mp_sub (b, a, c); - c->sign = MP_ZPOS; - } - } - - return res; -} - -/* End: bn_mp_sub.c */ - -/* Start: bn_mp_submod.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* d = a - b (mod c) */ -int -mp_submod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) -{ - int res; - mp_int t; - - - if ((res = mp_init (&t)) != MP_OKAY) { - return res; - } - - if ((res = mp_sub (a, b, &t)) != MP_OKAY) { - mp_clear (&t); - return res; - } - res = mp_mod (&t, c, d); - mp_clear (&t); - return res; -} - -/* End: bn_mp_submod.c */ - -/* Start: bn_mp_sub_d.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* single digit subtraction */ -int -mp_sub_d (mp_int * a, mp_digit b, mp_int * c) -{ - mp_int t; - int res; - - - if ((res = mp_init (&t)) != MP_OKAY) { - return res; - } - mp_set (&t, b); - res = mp_sub (a, &t, c); - - mp_clear (&t); - return res; -} - -/* End: bn_mp_sub_d.c */ - -/* Start: bn_mp_to_signed_bin.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* store in signed [big endian] format */ -int -mp_to_signed_bin (mp_int * a, unsigned char *b) -{ - int res; - - if ((res = mp_to_unsigned_bin (a, b + 1)) != MP_OKAY) { - return res; - } - b[0] = (unsigned char) ((a->sign == MP_ZPOS) ? 0 : 1); - return MP_OKAY; -} - -/* End: bn_mp_to_signed_bin.c */ - -/* Start: bn_mp_to_unsigned_bin.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* store in unsigned [big endian] format */ -int -mp_to_unsigned_bin (mp_int * a, unsigned char *b) -{ - int x, res; - mp_int t; - - if ((res = mp_init_copy (&t, a)) != MP_OKAY) { - return res; - } - - x = 0; - while (mp_iszero (&t) == 0) { - if (DIGIT_BIT != 7) { - b[x++] = (unsigned char) (t.dp[0] & 255); - } else { - b[x++] = (unsigned char) (t.dp[0] | ((t.dp[1] & 0x01) << 7)); - } - if ((res = mp_div_2d (&t, 8, &t, NULL)) != MP_OKAY) { - mp_clear (&t); - return res; - } - } - bn_reverse (b, x); - mp_clear (&t); - return MP_OKAY; -} - -/* End: bn_mp_to_unsigned_bin.c */ - -/* Start: bn_mp_unsigned_bin_size.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* get the size for an unsigned equivalent */ -int -mp_unsigned_bin_size (mp_int * a) -{ - int size = mp_count_bits (a); - return (size / 8 + ((size & 7) != 0 ? 1 : 0)); -} - -/* End: bn_mp_unsigned_bin_size.c */ - -/* Start: bn_mp_xor.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* XOR two ints together */ -int -mp_xor (mp_int * a, mp_int * b, mp_int * c) -{ - int res, ix, px; - mp_int t, *x; - - if (a->used > b->used) { - if ((res = mp_init_copy (&t, a)) != MP_OKAY) { - return res; - } - px = b->used; - x = b; - } else { - if ((res = mp_init_copy (&t, b)) != MP_OKAY) { - return res; - } - px = a->used; - x = a; - } - - for (ix = 0; ix < px; ix++) { - t.dp[ix] ^= x->dp[ix]; - } - mp_clamp (&t); - mp_exch (c, &t); - mp_clear (&t); - return MP_OKAY; -} - -/* End: bn_mp_xor.c */ - -/* Start: bn_mp_zero.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* set to zero */ -void -mp_zero (mp_int * a) -{ - a->sign = MP_ZPOS; - a->used = 0; - memset (a->dp, 0, sizeof (mp_digit) * a->alloc); -} - -/* End: bn_mp_zero.c */ - -/* Start: bn_prime_tab.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include -const mp_digit __prime_tab[] = { - 0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013, - 0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035, - 0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059, - 0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F, 0x0083, - 0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD, - 0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF, - 0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107, - 0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137, - - 0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167, - 0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199, - 0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9, - 0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7, - 0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239, - 0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265, - 0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293, - 0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF, - - 0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301, - 0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B, - 0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371, - 0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD, - 0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5, - 0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419, - 0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449, - 0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B, - - 0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7, - 0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503, - 0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529, - 0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F, - 0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3, - 0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7, - 0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623, - 0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653 -}; - -/* End: bn_prime_tab.c */ - -/* Start: bn_radix.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* chars used in radix conversions */ -static const char *s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; - -/* read a string [ASCII] in a given radix */ -int -mp_read_radix (mp_int * a, char *str, int radix) -{ - int y, res, neg; - char ch; - - if (radix < 2 || radix > 64) { - return MP_VAL; - } - - if (*str == '-') { - ++str; - neg = MP_NEG; - } else { - neg = MP_ZPOS; - } - - mp_zero (a); - while (*str) { - ch = (char) ((radix < 36) ? toupper (*str) : *str); - for (y = 0; y < 64; y++) { - if (ch == s_rmap[y]) { - break; - } - } - - if (y < radix) { - if ((res = mp_mul_d (a, (mp_digit) radix, a)) != MP_OKAY) { - return res; - } - if ((res = mp_add_d (a, (mp_digit) y, a)) != MP_OKAY) { - return res; - } - } else { - break; - } - ++str; - } - a->sign = neg; - return MP_OKAY; -} - -/* stores a bignum as a ASCII string in a given radix (2..64) */ -int -mp_toradix (mp_int * a, char *str, int radix) -{ - int res, digs; - mp_int t; - mp_digit d; - char *_s = str; - - if (radix < 2 || radix > 64) { - return MP_VAL; - } - - if ((res = mp_init_copy (&t, a)) != MP_OKAY) { - return res; - } - - if (t.sign == MP_NEG) { - ++_s; - *str++ = '-'; - t.sign = MP_ZPOS; - } - - digs = 0; - while (mp_iszero (&t) == 0) { - if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { - mp_clear (&t); - return res; - } - *str++ = s_rmap[d]; - ++digs; - } - bn_reverse ((unsigned char *)_s, digs); - *str++ = '\0'; - mp_clear (&t); - return MP_OKAY; -} - -/* returns size of ASCII reprensentation */ -int -mp_radix_size (mp_int * a, int radix) -{ - int res, digs; - mp_int t; - mp_digit d; - - /* special case for binary */ - if (radix == 2) { - return mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1; - } - - if (radix < 2 || radix > 64) { - return 0; - } - - if ((res = mp_init_copy (&t, a)) != MP_OKAY) { - return 0; - } - - digs = 0; - if (t.sign == MP_NEG) { - ++digs; - t.sign = MP_ZPOS; - } - - while (mp_iszero (&t) == 0) { - if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { - mp_clear (&t); - return 0; - } - ++digs; - } - mp_clear (&t); - return digs + 1; -} - -/* End: bn_radix.c */ - -/* Start: bn_reverse.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* reverse an array, used for radix code */ -void -bn_reverse (unsigned char *s, int len) -{ - int ix, iy; - unsigned char t; - - ix = 0; - iy = len - 1; - while (ix < iy) { - t = s[ix]; - s[ix] = s[iy]; - s[iy] = t; - ++ix; - --iy; - } -} - -/* End: bn_reverse.c */ - -/* Start: bn_s_mp_add.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* low level addition, based on HAC pp.594, Algorithm 14.7 */ -int -s_mp_add (mp_int * a, mp_int * b, mp_int * c) -{ - mp_int *x; - int olduse, res, min, max; - - /* find sizes, we let |a| <= |b| which means we have to sort - * them. "x" will point to the input with the most digits - */ - if (a->used > b->used) { - min = b->used; - max = a->used; - x = a; - } else if (a->used < b->used) { - min = a->used; - max = b->used; - x = b; - } else { - min = max = a->used; - x = NULL; - } - - /* init result */ - if (c->alloc < max + 1) { - if ((res = mp_grow (c, max + 1)) != MP_OKAY) { - return res; - } - } - - olduse = c->used; - c->used = max + 1; - - /* add digits from lower part */ - - /* set the carry to zero */ - { - register mp_digit u, *tmpa, *tmpb, *tmpc; - register int i; - - /* alias for digit pointers */ - - /* first input */ - tmpa = a->dp; - - /* second input */ - tmpb = b->dp; - - /* destination */ - tmpc = c->dp; - - u = 0; - for (i = 0; i < min; i++) { - /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */ - *tmpc = *tmpa++ + *tmpb++ + u; - - /* U = carry bit of T[i] */ - u = *tmpc >> DIGIT_BIT; - - /* take away carry bit from T[i] */ - *tmpc++ &= MP_MASK; - } - - /* now copy higher words if any, that is in A+B if A or B has more digits add those in */ - if (min != max) { - for (; i < max; i++) { - /* T[i] = X[i] + U */ - *tmpc = x->dp[i] + u; - - /* U = carry bit of T[i] */ - u = *tmpc >> DIGIT_BIT; - - /* take away carry bit from T[i] */ - *tmpc++ &= MP_MASK; - } - } - - /* add carry */ - *tmpc++ = u; - - /* clear digits above used (since we may not have grown result above) */ - for (i = c->used; i < olduse; i++) { - *tmpc++ = 0; - } - } - - mp_clamp (c); - return MP_OKAY; -} - -/* End: bn_s_mp_add.c */ - -/* Start: bn_s_mp_mul_digs.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* multiplies |a| * |b| and only computes upto digs digits of result - * HAC pp. 595, Algorithm 14.12 Modified so you can control how many digits of - * output are created. - */ -int -s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) -{ - mp_int t; - int res, pa, pb, ix, iy; - mp_digit u; - mp_word r; - mp_digit tmpx, *tmpt, *tmpy; - - if ((res = mp_init_size (&t, digs)) != MP_OKAY) { - return res; - } - t.used = digs; - - /* compute the digits of the product directly */ - pa = a->used; - for (ix = 0; ix < pa; ix++) { - /* set the carry to zero */ - u = 0; - - /* limit ourselves to making digs digits of output */ - pb = MIN (b->used, digs - ix); - - /* setup some aliases */ - tmpx = a->dp[ix]; - tmpt = &(t.dp[ix]); - tmpy = b->dp; - - /* compute the columns of the output and propagate the carry */ - for (iy = 0; iy < pb; iy++) { - /* compute the column as a mp_word */ - r = ((mp_word) * tmpt) + ((mp_word) tmpx) * ((mp_word) * tmpy++) + ((mp_word) u); - - /* the new column is the lower part of the result */ - *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); - - /* get the carry word from the result */ - u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); - } - if (ix + iy < digs) - *tmpt = u; - } - - mp_clamp (&t); - mp_exch (&t, c); - - mp_clear (&t); - return MP_OKAY; -} - -/* End: bn_s_mp_mul_digs.c */ - -/* Start: bn_s_mp_mul_high_digs.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* multiplies |a| * |b| and does not compute the lower digs digits - * [meant to get the higher part of the product] - */ -int -s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) -{ - mp_int t; - int res, pa, pb, ix, iy; - mp_digit u; - mp_word r; - mp_digit tmpx, *tmpt, *tmpy; - - - /* can we use the fast multiplier? */ - if (((a->used + b->used + 1) < 512) - && MAX (a->used, b->used) < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { - return fast_s_mp_mul_high_digs (a, b, c, digs); - } - - if ((res = mp_init_size (&t, a->used + b->used + 1)) != MP_OKAY) { - return res; - } - t.used = a->used + b->used + 1; - - pa = a->used; - pb = b->used; - for (ix = 0; ix < pa; ix++) { - /* clear the carry */ - u = 0; - - /* left hand side of A[ix] * B[iy] */ - tmpx = a->dp[ix]; - - /* alias to the address of where the digits will be stored */ - tmpt = &(t.dp[digs]); - - /* alias for where to read the right hand side from */ - tmpy = b->dp + (digs - ix); - - for (iy = digs - ix; iy < pb; iy++) { - /* calculate the double precision result */ - r = ((mp_word) * tmpt) + ((mp_word) tmpx) * ((mp_word) * tmpy++) + ((mp_word) u); - - /* get the lower part */ - *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); - - /* carry the carry */ - u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); - } - *tmpt = u; - } - mp_clamp (&t); - mp_exch (&t, c); - mp_clear (&t); - return MP_OKAY; -} - -/* End: bn_s_mp_mul_high_digs.c */ - -/* Start: bn_s_mp_sqr.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */ -int -s_mp_sqr (mp_int * a, mp_int * b) -{ - mp_int t; - int res, ix, iy, pa; - mp_word r, u; - mp_digit tmpx, *tmpt; - - pa = a->used; - if ((res = mp_init_size (&t, pa + pa + 1)) != MP_OKAY) { - return res; - } - t.used = pa + pa + 1; - - for (ix = 0; ix < pa; ix++) { - /* first calculate the digit at 2*ix */ - /* calculate double precision result */ - r = ((mp_word) t.dp[ix + ix]) + ((mp_word) a->dp[ix]) * ((mp_word) a->dp[ix]); - - /* store lower part in result */ - t.dp[ix + ix] = (mp_digit) (r & ((mp_word) MP_MASK)); - - /* get the carry */ - u = (r >> ((mp_word) DIGIT_BIT)); - - /* left hand side of A[ix] * A[iy] */ - tmpx = a->dp[ix]; - - /* alias for where to store the results */ - tmpt = &(t.dp[ix + ix + 1]); - for (iy = ix + 1; iy < pa; iy++) { - /* first calculate the product */ - r = ((mp_word) tmpx) * ((mp_word) a->dp[iy]); - - /* now calculate the double precision result, note we use - * addition instead of *2 since its easier to optimize - */ - r = ((mp_word) * tmpt) + r + r + ((mp_word) u); - - /* store lower part */ - *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); - - /* get carry */ - u = (r >> ((mp_word) DIGIT_BIT)); - } - r = ((mp_word) * tmpt) + u; - *tmpt = (mp_digit) (r & ((mp_word) MP_MASK)); - u = (r >> ((mp_word) DIGIT_BIT)); - /* propagate upwards */ - ++tmpt; - while (u != ((mp_word) 0)) { - r = ((mp_word) * tmpt) + ((mp_word) 1); - *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); - u = (r >> ((mp_word) DIGIT_BIT)); - } - } - - mp_clamp (&t); - mp_exch (&t, b); - mp_clear (&t); - return MP_OKAY; -} - -/* End: bn_s_mp_sqr.c */ - -/* Start: bn_s_mp_sub.c */ -/* LibTomMath, multiple-precision integer library -- Tom St Denis - * - * LibTomMath is library that provides for multiple-precision - * integer arithmetic as well as number theoretic functionality. - * - * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. - * - * The library is free for all purposes without any express - * guarantee it works. - * - * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org - */ -#include - -/* low level subtraction (assumes a > b), HAC pp.595 Algorithm 14.9 */ -int -s_mp_sub (mp_int * a, mp_int * b, mp_int * c) -{ - int olduse, res, min, max; - - /* find sizes */ - min = b->used; - max = a->used; - - /* init result */ - if (c->alloc < max) { - if ((res = mp_grow (c, max)) != MP_OKAY) { - return res; - } - } - olduse = c->used; - c->used = max; - - /* sub digits from lower part */ - - { - register mp_digit u, *tmpa, *tmpb, *tmpc; - register int i; - - /* alias for digit pointers */ - tmpa = a->dp; - tmpb = b->dp; - tmpc = c->dp; - - /* set carry to zero */ - u = 0; - for (i = 0; i < min; i++) { - /* T[i] = A[i] - B[i] - U */ - *tmpc = *tmpa++ - *tmpb++ - u; - - /* U = carry bit of T[i] - * Note this saves performing an AND operation since - * if a carry does occur it will propagate all the way to the - * MSB. As a result a single shift is required to get the carry - */ - u = *tmpc >> (CHAR_BIT * sizeof (mp_digit) - 1); - - /* Clear carry from T[i] */ - *tmpc++ &= MP_MASK; - } - - /* now copy higher words if any, e.g. if A has more digits than B */ - for (; i < max; i++) { - /* T[i] = A[i] - U */ - *tmpc = *tmpa++ - u; - - /* U = carry bit of T[i] */ - u = *tmpc >> (CHAR_BIT * sizeof (mp_digit) - 1); - - /* Clear carry from T[i] */ - *tmpc++ &= MP_MASK; - } - - /* clear digits above used (since we may not have grown result above) */ - for (i = c->used; i < olduse; i++) { - *tmpc++ = 0; - } - } - - mp_clamp (c); - return MP_OKAY; -} - -/* End: bn_s_mp_sub.c */ - - -/* EOF */ +/* Start: bn_fast_mp_invmod.c */ +#line 0 "bn_fast_mp_invmod.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include "mycrypt.h" +#include + +/* computes the modular inverse via binary extended euclidean algorithm, + * that is c = 1/a mod b + * + * Based on mp_invmod except this is optimized for the case where b is + * odd as per HAC Note 14.64 on pp. 610 + */ +int +fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c) +{ + mp_int x, y, u, v, B, D; + int res, neg; + + /* init all our temps */ + if ((res = mp_init_multi(&x, &y, &u, &v, &B, &D, NULL)) != MP_OKAY) { + return res; + } + + /* x == modulus, y == value to invert */ + if ((res = mp_copy (b, &x)) != MP_OKAY) { + goto __ERR; + } + + /* we need y = |a| */ + if ((res = mp_abs (a, &y)) != MP_OKAY) { + goto __ERR; + } + + /* 2. [modified] if x,y are both even then return an error! + * + * That is if gcd(x,y) = 2 * k then obviously there is no inverse. + */ + if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) { + res = MP_VAL; + goto __ERR; + } + + /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ + if ((res = mp_copy (&x, &u)) != MP_OKAY) { + goto __ERR; + } + if ((res = mp_copy (&y, &v)) != MP_OKAY) { + goto __ERR; + } + mp_set (&D, 1); + +top: + /* 4. while u is even do */ + while (mp_iseven (&u) == 1) { + /* 4.1 u = u/2 */ + if ((res = mp_div_2 (&u, &u)) != MP_OKAY) { + goto __ERR; + } + /* 4.2 if A or B is odd then */ + if (mp_iseven (&B) == 0) { + if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) { + goto __ERR; + } + } + /* B = B/2 */ + if ((res = mp_div_2 (&B, &B)) != MP_OKAY) { + goto __ERR; + } + } + + /* 5. while v is even do */ + while (mp_iseven (&v) == 1) { + /* 5.1 v = v/2 */ + if ((res = mp_div_2 (&v, &v)) != MP_OKAY) { + goto __ERR; + } + /* 5.2 if C,D are even then */ + if (mp_iseven (&D) == 0) { + /* D = (D-x)/2 */ + if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) { + goto __ERR; + } + } + /* D = D/2 */ + if ((res = mp_div_2 (&D, &D)) != MP_OKAY) { + goto __ERR; + } + } + + /* 6. if u >= v then */ + if (mp_cmp (&u, &v) != MP_LT) { + /* u = u - v, B = B - D */ + if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) { + goto __ERR; + } + + if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) { + goto __ERR; + } + } else { + /* v - v - u, D = D - B */ + if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) { + goto __ERR; + } + + if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) { + goto __ERR; + } + } + + /* if not zero goto step 4 */ + if (mp_iszero (&u) == 0) { + goto top; + } + + /* now a = C, b = D, gcd == g*v */ + + /* if v != 1 then there is no inverse */ + if (mp_cmp_d (&v, 1) != MP_EQ) { + res = MP_VAL; + goto __ERR; + } + + /* b is now the inverse */ + neg = a->sign; + while (D.sign == MP_NEG) { + if ((res = mp_add (&D, b, &D)) != MP_OKAY) { + goto __ERR; + } + } + mp_exch (&D, c); + c->sign = neg; + res = MP_OKAY; + +__ERR:mp_clear_multi (&x, &y, &u, &v, &B, &D, NULL); + return res; +} + +/* End: bn_fast_mp_invmod.c */ + +/* Start: bn_fast_mp_montgomery_reduce.c */ +#line 0 "bn_fast_mp_montgomery_reduce.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* computes xR**-1 == x (mod N) via Montgomery Reduction + * + * This is an optimized implementation of mp_montgomery_reduce + * which uses the comba method to quickly calculate the columns of the + * reduction. + * + * Based on Algorithm 14.32 on pp.601 of HAC. +*/ +int +fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) +{ + int ix, res, olduse; + mp_word W[MP_WARRAY]; + + /* get old used count */ + olduse = x->used; + + /* grow a as required */ + if (x->alloc < n->used + 1) { + if ((res = mp_grow (x, n->used + 1)) != MP_OKAY) { + return res; + } + } + + { + register mp_word *_W; + register mp_digit *tmpx; + + _W = W; + tmpx = x->dp; + + /* copy the digits of a into W[0..a->used-1] */ + for (ix = 0; ix < x->used; ix++) { + *_W++ = *tmpx++; + } + + /* zero the high words of W[a->used..m->used*2] */ + for (; ix < n->used * 2 + 1; ix++) { + *_W++ = 0; + } + } + + for (ix = 0; ix < n->used; ix++) { + /* mu = ai * m' mod b + * + * We avoid a double precision multiplication (which isn't required) + * by casting the value down to a mp_digit. Note this requires + * that W[ix-1] have the carry cleared (see after the inner loop) + */ + register mp_digit mu; + mu = (((mp_digit) (W[ix] & MP_MASK)) * rho) & MP_MASK; + + /* a = a + mu * m * b**i + * + * This is computed in place and on the fly. The multiplication + * by b**i is handled by offseting which columns the results + * are added to. + * + * Note the comba method normally doesn't handle carries in the + * inner loop In this case we fix the carry from the previous + * column since the Montgomery reduction requires digits of the + * result (so far) [see above] to work. This is + * handled by fixing up one carry after the inner loop. The + * carry fixups are done in order so after these loops the + * first m->used words of W[] have the carries fixed + */ + { + register int iy; + register mp_digit *tmpn; + register mp_word *_W; + + /* alias for the digits of the modulus */ + tmpn = n->dp; + + /* Alias for the columns set by an offset of ix */ + _W = W + ix; + + /* inner loop */ + for (iy = 0; iy < n->used; iy++) { + *_W++ += ((mp_word) mu) * ((mp_word) * tmpn++); + } + } + + /* now fix carry for next digit, W[ix+1] */ + W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT); + } + + + { + register mp_digit *tmpx; + register mp_word *_W, *_W1; + + /* nox fix rest of carries */ + _W1 = W + ix; + _W = W + ++ix; + + for (; ix <= n->used * 2 + 1; ix++) { + *_W++ += *_W1++ >> ((mp_word) DIGIT_BIT); + } + + /* copy out, A = A/b**n + * + * The result is A/b**n but instead of converting from an + * array of mp_word to mp_digit than calling mp_rshd + * we just copy them in the right order + */ + tmpx = x->dp; + _W = W + n->used; + + for (ix = 0; ix < n->used + 1; ix++) { + *tmpx++ = *_W++ & ((mp_word) MP_MASK); + } + + /* zero oldused digits, if the input a was larger than + * m->used+1 we'll have to clear the digits */ + for (; ix < olduse; ix++) { + *tmpx++ = 0; + } + } + + /* set the max used and clamp */ + x->used = n->used + 1; + mp_clamp (x); + + /* if A >= m then A = A - m */ + if (mp_cmp_mag (x, n) != MP_LT) { + return s_mp_sub (x, n, x); + } + return MP_OKAY; +} + +/* End: bn_fast_mp_montgomery_reduce.c */ + +/* Start: bn_fast_s_mp_mul_digs.c */ +#line 0 "bn_fast_s_mp_mul_digs.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* Fast (comba) multiplier + * + * This is the fast column-array [comba] multiplier. It is + * designed to compute the columns of the product first + * then handle the carries afterwards. This has the effect + * of making the nested loops that compute the columns very + * simple and schedulable on super-scalar processors. + * + * This has been modified to produce a variable number of + * digits of output so if say only a half-product is required + * you don't have to compute the upper half (a feature + * required for fast Barrett reduction). + * + * Based on Algorithm 14.12 on pp.595 of HAC. + * + */ +int +fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) +{ + int olduse, res, pa, ix; + mp_word W[MP_WARRAY]; + + /* grow the destination as required */ + if (c->alloc < digs) { + if ((res = mp_grow (c, digs)) != MP_OKAY) { + return res; + } + } + + /* clear temp buf (the columns) */ + memset (W, 0, sizeof (mp_word) * digs); + + /* calculate the columns */ + pa = a->used; + for (ix = 0; ix < pa; ix++) { + /* this multiplier has been modified to allow you to + * control how many digits of output are produced. + * So at most we want to make upto "digs" digits of output. + * + * this adds products to distinct columns (at ix+iy) of W + * note that each step through the loop is not dependent on + * the previous which means the compiler can easily unroll + * the loop without scheduling problems + */ + { + register mp_digit tmpx, *tmpy; + register mp_word *_W; + register int iy, pb; + + /* alias for the the word on the left e.g. A[ix] * A[iy] */ + tmpx = a->dp[ix]; + + /* alias for the right side */ + tmpy = b->dp; + + /* alias for the columns, each step through the loop adds a new + term to each column + */ + _W = W + ix; + + /* the number of digits is limited by their placement. E.g. + we avoid multiplying digits that will end up above the # of + digits of precision requested + */ + pb = MIN (b->used, digs - ix); + + for (iy = 0; iy < pb; iy++) { + *_W++ += ((mp_word) tmpx) * ((mp_word) * tmpy++); + } + } + + } + + /* setup dest */ + olduse = c->used; + c->used = digs; + + { + register mp_digit *tmpc; + + /* At this point W[] contains the sums of each column. To get the + * correct result we must take the extra bits from each column and + * carry them down + * + * Note that while this adds extra code to the multiplier it + * saves time since the carry propagation is removed from the + * above nested loop.This has the effect of reducing the work + * from N*(N+N*c)==N**2 + c*N**2 to N**2 + N*c where c is the + * cost of the shifting. On very small numbers this is slower + * but on most cryptographic size numbers it is faster. + */ + tmpc = c->dp; + for (ix = 1; ix < digs; ix++) { + W[ix] += (W[ix - 1] >> ((mp_word) DIGIT_BIT)); + *tmpc++ = (mp_digit) (W[ix - 1] & ((mp_word) MP_MASK)); + } + *tmpc++ = (mp_digit) (W[digs - 1] & ((mp_word) MP_MASK)); + + /* clear unused */ + for (; ix < olduse; ix++) { + *tmpc++ = 0; + } + } + + mp_clamp (c); + return MP_OKAY; +} + +/* End: bn_fast_s_mp_mul_digs.c */ + +/* Start: bn_fast_s_mp_mul_high_digs.c */ +#line 0 "bn_fast_s_mp_mul_high_digs.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* this is a modified version of fast_s_mp_mul_digs that only produces + * output digits *above* digs. See the comments for fast_s_mp_mul_digs + * to see how it works. + * + * This is used in the Barrett reduction since for one of the multiplications + * only the higher digits were needed. This essentially halves the work. + * + * Based on Algorithm 14.12 on pp.595 of HAC. + */ +int +fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) +{ + int oldused, newused, res, pa, pb, ix; + mp_word W[MP_WARRAY]; + + /* calculate size of product and allocate more space if required */ + newused = a->used + b->used + 1; + if (c->alloc < newused) { + if ((res = mp_grow (c, newused)) != MP_OKAY) { + return res; + } + } + + /* like the other comba method we compute the columns first */ + pa = a->used; + pb = b->used; + memset (W + digs, 0, (pa + pb + 1 - digs) * sizeof (mp_word)); + for (ix = 0; ix < pa; ix++) { + { + register mp_digit tmpx, *tmpy; + register int iy; + register mp_word *_W; + + /* work todo, that is we only calculate digits that are at "digs" or above */ + iy = digs - ix; + + /* copy of word on the left of A[ix] * B[iy] */ + tmpx = a->dp[ix]; + + /* alias for right side */ + tmpy = b->dp + iy; + + /* alias for the columns of output. Offset to be equal to or above the + * smallest digit place requested + */ + _W = W + digs; + + /* skip cases below zero where ix > digs */ + if (iy < 0) { + iy = abs(iy); + tmpy += iy; + _W += iy; + iy = 0; + } + + /* compute column products for digits above the minimum */ + for (; iy < pb; iy++) { + *_W++ += ((mp_word) tmpx) * ((mp_word) * tmpy++); + } + } + } + + /* setup dest */ + oldused = c->used; + c->used = newused; + + /* now convert the array W downto what we need */ + for (ix = digs + 1; ix < newused; ix++) { + W[ix] += (W[ix - 1] >> ((mp_word) DIGIT_BIT)); + c->dp[ix - 1] = (mp_digit) (W[ix - 1] & ((mp_word) MP_MASK)); + } + c->dp[(pa + pb + 1) - 1] = (mp_digit) (W[(pa + pb + 1) - 1] & ((mp_word) MP_MASK)); + + for (; ix < oldused; ix++) { + c->dp[ix] = 0; + } + mp_clamp (c); + return MP_OKAY; +} + +/* End: bn_fast_s_mp_mul_high_digs.c */ + +/* Start: bn_fast_s_mp_sqr.c */ +#line 0 "bn_fast_s_mp_sqr.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* fast squaring + * + * This is the comba method where the columns of the product + * are computed first then the carries are computed. This + * has the effect of making a very simple inner loop that + * is executed the most + * + * W2 represents the outer products and W the inner. + * + * A further optimizations is made because the inner + * products are of the form "A * B * 2". The *2 part does + * not need to be computed until the end which is good + * because 64-bit shifts are slow! + * + * Based on Algorithm 14.16 on pp.597 of HAC. + * + */ +int +fast_s_mp_sqr (mp_int * a, mp_int * b) +{ + int olduse, newused, res, ix, pa; + mp_word W2[MP_WARRAY], W[MP_WARRAY]; + + /* calculate size of product and allocate as required */ + pa = a->used; + newused = pa + pa + 1; + if (b->alloc < newused) { + if ((res = mp_grow (b, newused)) != MP_OKAY) { + return res; + } + } + + /* zero temp buffer (columns) + * Note that there are two buffers. Since squaring requires + * a outter and inner product and the inner product requires + * computing a product and doubling it (a relatively expensive + * op to perform n**2 times if you don't have to) the inner and + * outer products are computed in different buffers. This way + * the inner product can be doubled using n doublings instead of + * n**2 + */ + memset (W, 0, newused * sizeof (mp_word)); + memset (W2, 0, newused * sizeof (mp_word)); + + /* This computes the inner product. To simplify the inner N**2 loop + * the multiplication by two is done afterwards in the N loop. + */ + for (ix = 0; ix < pa; ix++) { + /* compute the outer product + * + * Note that every outer product is computed + * for a particular column only once which means that + * there is no need todo a double precision addition + */ + W2[ix + ix] = ((mp_word) a->dp[ix]) * ((mp_word) a->dp[ix]); + + { + register mp_digit tmpx, *tmpy; + register mp_word *_W; + register int iy; + + /* copy of left side */ + tmpx = a->dp[ix]; + + /* alias for right side */ + tmpy = a->dp + (ix + 1); + + /* the column to store the result in */ + _W = W + (ix + ix + 1); + + /* inner products */ + for (iy = ix + 1; iy < pa; iy++) { + *_W++ += ((mp_word) tmpx) * ((mp_word) * tmpy++); + } + } + } + + /* setup dest */ + olduse = b->used; + b->used = newused; + + /* now compute digits */ + { + register mp_digit *tmpb; + + /* double first value, since the inner products are + * half of what they should be + */ + W[0] += W[0] + W2[0]; + + tmpb = b->dp; + for (ix = 1; ix < newused; ix++) { + /* double/add next digit */ + W[ix] += W[ix] + W2[ix]; + + W[ix] = W[ix] + (W[ix - 1] >> ((mp_word) DIGIT_BIT)); + *tmpb++ = (mp_digit) (W[ix - 1] & ((mp_word) MP_MASK)); + } + /* set the last value. Note even if the carry is zero + * this is required since the next step will not zero + * it if b originally had a value at b->dp[2*a.used] + */ + *tmpb++ = (mp_digit) (W[(newused) - 1] & ((mp_word) MP_MASK)); + + /* clear high digits */ + for (; ix < olduse; ix++) { + *tmpb++ = 0; + } + } + + mp_clamp (b); + return MP_OKAY; +} + +/* End: bn_fast_s_mp_sqr.c */ + +/* Start: bn_mp_2expt.c */ +#line 0 "bn_mp_2expt.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* computes a = 2**b + * + * Simple algorithm which zeroes the int, grows it then just sets one bit + * as required. + */ +int +mp_2expt (mp_int * a, int b) +{ + int res; + + mp_zero (a); + if ((res = mp_grow (a, b / DIGIT_BIT + 1)) != MP_OKAY) { + return res; + } + a->used = b / DIGIT_BIT + 1; + a->dp[b / DIGIT_BIT] = 1 << (b % DIGIT_BIT); + + return MP_OKAY; +} + +/* End: bn_mp_2expt.c */ + +/* Start: bn_mp_abs.c */ +#line 0 "bn_mp_abs.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* b = |a| + * + * Simple function copies the input and fixes the sign to positive + */ +int +mp_abs (mp_int * a, mp_int * b) +{ + int res; + if ((res = mp_copy (a, b)) != MP_OKAY) { + return res; + } + b->sign = MP_ZPOS; + return MP_OKAY; +} + +/* End: bn_mp_abs.c */ + +/* Start: bn_mp_add.c */ +#line 0 "bn_mp_add.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* high level addition (handles signs) */ +int +mp_add (mp_int * a, mp_int * b, mp_int * c) +{ + int sa, sb, res; + + /* get sign of both inputs */ + sa = a->sign; + sb = b->sign; + + /* handle two cases, not four */ + if (sa == sb) { + /* both positive or both negative */ + /* add their magnitudes, copy the sign */ + c->sign = sa; + res = s_mp_add (a, b, c); + } else { + /* one positive, the other negative */ + /* subtract the one with the greater magnitude from */ + /* the one of the lesser magnitude. The result gets */ + /* the sign of the one with the greater magnitude. */ + if (mp_cmp_mag (a, b) == MP_LT) { + c->sign = sb; + res = s_mp_sub (b, a, c); + } else { + c->sign = sa; + res = s_mp_sub (a, b, c); + } + } + return res; +} + + +/* End: bn_mp_add.c */ + +/* Start: bn_mp_add_d.c */ +#line 0 "bn_mp_add_d.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* single digit addition */ +int +mp_add_d (mp_int * a, mp_digit b, mp_int * c) +{ + mp_int t; + int res; + + if ((res = mp_init_size(&t, 1)) != MP_OKAY) { + return res; + } + mp_set (&t, b); + res = mp_add (a, &t, c); + + mp_clear (&t); + return res; +} + +/* End: bn_mp_add_d.c */ + +/* Start: bn_mp_addmod.c */ +#line 0 "bn_mp_addmod.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* d = a + b (mod c) */ +int +mp_addmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) +{ + int res; + mp_int t; + + if ((res = mp_init (&t)) != MP_OKAY) { + return res; + } + + if ((res = mp_add (a, b, &t)) != MP_OKAY) { + mp_clear (&t); + return res; + } + res = mp_mod (&t, c, d); + mp_clear (&t); + return res; +} + +/* End: bn_mp_addmod.c */ + +/* Start: bn_mp_and.c */ +#line 0 "bn_mp_and.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* AND two ints together */ +int +mp_and (mp_int * a, mp_int * b, mp_int * c) +{ + int res, ix, px; + mp_int t, *x; + + if (a->used > b->used) { + if ((res = mp_init_copy (&t, a)) != MP_OKAY) { + return res; + } + px = b->used; + x = b; + } else { + if ((res = mp_init_copy (&t, b)) != MP_OKAY) { + return res; + } + px = a->used; + x = a; + } + + for (ix = 0; ix < px; ix++) { + t.dp[ix] &= x->dp[ix]; + } + + /* zero digits above the last from the smallest mp_int */ + for (; ix < t.used; ix++) { + t.dp[ix] = 0; + } + + mp_clamp (&t); + mp_exch (c, &t); + mp_clear (&t); + return MP_OKAY; +} + +/* End: bn_mp_and.c */ + +/* Start: bn_mp_clamp.c */ +#line 0 "bn_mp_clamp.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* trim unused digits + * + * This is used to ensure that leading zero digits are + * trimed and the leading "used" digit will be non-zero + * Typically very fast. Also fixes the sign if there + * are no more leading digits + */ +void +mp_clamp (mp_int * a) +{ + while (a->used > 0 && a->dp[a->used - 1] == 0) { + --(a->used); + } + if (a->used == 0) { + a->sign = MP_ZPOS; + } +} + +/* End: bn_mp_clamp.c */ + +/* Start: bn_mp_clear.c */ +#line 0 "bn_mp_clear.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* clear one (frees) */ +void +mp_clear (mp_int * a) +{ + if (a->dp != NULL) { + + /* first zero the digits */ + memset (a->dp, 0, sizeof (mp_digit) * a->used); + + /* free ram */ + free (a->dp); + + /* reset members to make debugging easier */ + a->dp = NULL; + a->alloc = a->used = 0; + } +} + +/* End: bn_mp_clear.c */ + +/* Start: bn_mp_cmp.c */ +#line 0 "bn_mp_cmp.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* compare two ints (signed)*/ +int +mp_cmp (mp_int * a, mp_int * b) +{ + /* compare based on sign */ + if (a->sign == MP_NEG && b->sign == MP_ZPOS) { + return MP_LT; + } + + if (a->sign == MP_ZPOS && b->sign == MP_NEG) { + return MP_GT; + } + + /* compare digits */ + if (a->sign == MP_NEG) { + /* if negative compare opposite direction */ + return mp_cmp_mag(b, a); + } else { + return mp_cmp_mag(a, b); + } +} + +/* End: bn_mp_cmp.c */ + +/* Start: bn_mp_cmp_d.c */ +#line 0 "bn_mp_cmp_d.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* compare a digit */ +int +mp_cmp_d (mp_int * a, mp_digit b) +{ + + if (a->sign == MP_NEG) { + return MP_LT; + } + + if (a->used > 1) { + return MP_GT; + } + + if (a->dp[0] > b) { + return MP_GT; + } else if (a->dp[0] < b) { + return MP_LT; + } else { + return MP_EQ; + } +} + +/* End: bn_mp_cmp_d.c */ + +/* Start: bn_mp_cmp_mag.c */ +#line 0 "bn_mp_cmp_mag.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* compare maginitude of two ints (unsigned) */ +int +mp_cmp_mag (mp_int * a, mp_int * b) +{ + int n; + + /* compare based on # of non-zero digits */ + if (a->used > b->used) { + return MP_GT; + } + + if (a->used < b->used) { + return MP_LT; + } + + /* compare based on digits */ + for (n = a->used - 1; n >= 0; n--) { + if (a->dp[n] > b->dp[n]) { + return MP_GT; + } + + if (a->dp[n] < b->dp[n]) { + return MP_LT; + } + } + return MP_EQ; +} + +/* End: bn_mp_cmp_mag.c */ + +/* Start: bn_mp_copy.c */ +#line 0 "bn_mp_copy.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* copy, b = a */ +int +mp_copy (mp_int * a, mp_int * b) +{ + int res, n; + + /* if dst == src do nothing */ + if (a == b) { + return MP_OKAY; + } + + /* grow dest */ + if ((res = mp_grow (b, a->used)) != MP_OKAY) { + return res; + } + + /* zero b and copy the parameters over */ + { + register mp_digit *tmpa, *tmpb; + + /* pointer aliases */ + tmpa = a->dp; + tmpb = b->dp; + + /* copy all the digits */ + for (n = 0; n < a->used; n++) { + *tmpb++ = *tmpa++; + } + + /* clear high digits */ + for (; n < b->used; n++) { + *tmpb++ = 0; + } + } + b->used = a->used; + b->sign = a->sign; + return MP_OKAY; +} + +/* End: bn_mp_copy.c */ + +/* Start: bn_mp_count_bits.c */ +#line 0 "bn_mp_count_bits.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* returns the number of bits in an int */ +int +mp_count_bits (mp_int * a) +{ + int r; + mp_digit q; + + /* shortcut */ + if (a->used == 0) { + return 0; + } + + /* get number of digits and add that */ + r = (a->used - 1) * DIGIT_BIT; + + /* take the last digit and count the bits in it */ + q = a->dp[a->used - 1]; + while (q > ((mp_digit) 0)) { + ++r; + q >>= ((mp_digit) 1); + } + return r; +} + +/* End: bn_mp_count_bits.c */ + +/* Start: bn_mp_div.c */ +#line 0 "bn_mp_div.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* integer signed division. c*b + d == a [e.g. a/b, c=quotient, d=remainder] + * HAC pp.598 Algorithm 14.20 + * + * Note that the description in HAC is horribly incomplete. For example, + * it doesn't consider the case where digits are removed from 'x' in the inner + * loop. It also doesn't consider the case that y has fewer than three digits, etc.. + * + * The overall algorithm is as described as 14.20 from HAC but fixed to treat these cases. +*/ +int +mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d) +{ + mp_int q, x, y, t1, t2; + int res, n, t, i, norm, neg; + + + /* is divisor zero ? */ + if (mp_iszero (b) == 1) { + return MP_VAL; + } + + /* if a < b then q=0, r = a */ + if (mp_cmp_mag (a, b) == MP_LT) { + if (d != NULL) { + res = mp_copy (a, d); + } else { + res = MP_OKAY; + } + if (c != NULL) { + mp_zero (c); + } + return res; + } + + if ((res = mp_init_size (&q, a->used + 2)) != MP_OKAY) { + return res; + } + q.used = a->used + 2; + + if ((res = mp_init (&t1)) != MP_OKAY) { + goto __Q; + } + + if ((res = mp_init (&t2)) != MP_OKAY) { + goto __T1; + } + + if ((res = mp_init_copy (&x, a)) != MP_OKAY) { + goto __T2; + } + + if ((res = mp_init_copy (&y, b)) != MP_OKAY) { + goto __X; + } + + /* fix the sign */ + neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; + x.sign = y.sign = MP_ZPOS; + + /* normalize both x and y, ensure that y >= b/2, [b == 2^DIGIT_BIT] */ + norm = mp_count_bits(&y) % DIGIT_BIT; + if (norm < (int)(DIGIT_BIT-1)) { + norm = (DIGIT_BIT-1) - norm; + if ((res = mp_mul_2d (&x, norm, &x)) != MP_OKAY) { + goto __Y; + } + if ((res = mp_mul_2d (&y, norm, &y)) != MP_OKAY) { + goto __Y; + } + } else { + norm = 0; + } + + /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */ + n = x.used - 1; + t = y.used - 1; + + /* step 2. while (x >= y*b^n-t) do { q[n-t] += 1; x -= y*b^{n-t} } */ + if ((res = mp_lshd (&y, n - t)) != MP_OKAY) { /* y = y*b^{n-t} */ + goto __Y; + } + + while (mp_cmp (&x, &y) != MP_LT) { + ++(q.dp[n - t]); + if ((res = mp_sub (&x, &y, &x)) != MP_OKAY) { + goto __Y; + } + } + + /* reset y by shifting it back down */ + mp_rshd (&y, n - t); + + /* step 3. for i from n down to (t + 1) */ + for (i = n; i >= (t + 1); i--) { + if (i > x.used) + continue; + + /* step 3.1 if xi == yt then set q{i-t-1} to b-1, otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */ + if (x.dp[i] == y.dp[t]) { + q.dp[i - t - 1] = ((((mp_digit)1) << DIGIT_BIT) - 1); + } else { + mp_word tmp; + tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT); + tmp |= ((mp_word) x.dp[i - 1]); + tmp /= ((mp_word) y.dp[t]); + if (tmp > (mp_word) MP_MASK) + tmp = MP_MASK; + q.dp[i - t - 1] = (mp_digit) (tmp & (mp_word) (MP_MASK)); + } + + /* step 3.2 while (q{i-t-1} * (yt * b + y{t-1})) > xi * b^2 + xi-1 * b + xi-2 do q{i-t-1} -= 1; */ + q.dp[i - t - 1] = (q.dp[i - t - 1] + 1) & MP_MASK; + do { + q.dp[i - t - 1] = (q.dp[i - t - 1] - 1) & MP_MASK; + + /* find left hand */ + mp_zero (&t1); + t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1]; + t1.dp[1] = y.dp[t]; + t1.used = 2; + if ((res = mp_mul_d (&t1, q.dp[i - t - 1], &t1)) != MP_OKAY) { + goto __Y; + } + + /* find right hand */ + t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2]; + t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1]; + t2.dp[2] = x.dp[i]; + t2.used = 3; + } while (mp_cmp_mag(&t1, &t2) == MP_GT); + + /* step 3.3 x = x - q{i-t-1} * y * b^{i-t-1} */ + if ((res = mp_mul_d (&y, q.dp[i - t - 1], &t1)) != MP_OKAY) { + goto __Y; + } + + if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) { + goto __Y; + } + + if ((res = mp_sub (&x, &t1, &x)) != MP_OKAY) { + goto __Y; + } + + /* step 3.4 if x < 0 then { x = x + y*b^{i-t-1}; q{i-t-1} -= 1; } */ + if (x.sign == MP_NEG) { + if ((res = mp_copy (&y, &t1)) != MP_OKAY) { + goto __Y; + } + if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) { + goto __Y; + } + if ((res = mp_add (&x, &t1, &x)) != MP_OKAY) { + goto __Y; + } + + q.dp[i - t - 1] = (q.dp[i - t - 1] - 1UL) & MP_MASK; + } + } + + /* now q is the quotient and x is the remainder [which we have to normalize] */ + /* get sign before writing to c */ + x.sign = a->sign; + + if (c != NULL) { + mp_clamp (&q); + mp_exch (&q, c); + c->sign = neg; + } + + if (d != NULL) { + mp_div_2d (&x, norm, &x, NULL); + mp_exch (&x, d); + } + + res = MP_OKAY; + +__Y:mp_clear (&y); +__X:mp_clear (&x); +__T2:mp_clear (&t2); +__T1:mp_clear (&t1); +__Q:mp_clear (&q); + return res; +} + +/* End: bn_mp_div.c */ + +/* Start: bn_mp_div_2.c */ +#line 0 "bn_mp_div_2.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* b = a/2 */ +int +mp_div_2 (mp_int * a, mp_int * b) +{ + int x, res, oldused; + + /* copy */ + if (b->alloc < a->used) { + if ((res = mp_grow (b, a->used)) != MP_OKAY) { + return res; + } + } + + oldused = b->used; + b->used = a->used; + { + register mp_digit r, rr, *tmpa, *tmpb; + + /* source alias */ + tmpa = a->dp + b->used - 1; + + /* dest alias */ + tmpb = b->dp + b->used - 1; + + /* carry */ + r = 0; + for (x = b->used - 1; x >= 0; x--) { + /* get the carry for the next iteration */ + rr = *tmpa & 1; + + /* shift the current digit, add in carry and store */ + *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1)); + + /* forward carry to next iteration */ + r = rr; + } + + /* zero excess digits */ + tmpb = b->dp + b->used; + for (x = b->used; x < oldused; x++) { + *tmpb++ = 0; + } + } + b->sign = a->sign; + mp_clamp (b); + return MP_OKAY; +} + +/* End: bn_mp_div_2.c */ + +/* Start: bn_mp_div_2d.c */ +#line 0 "bn_mp_div_2d.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* shift right by a certain bit count (store quotient in c, optional remainder in d) */ +int +mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d) +{ + mp_digit D, r, rr; + int x, res; + mp_int t; + + + /* if the shift count is <= 0 then we do no work */ + if (b <= 0) { + res = mp_copy (a, c); + if (d != NULL) { + mp_zero (d); + } + return res; + } + + if ((res = mp_init (&t)) != MP_OKAY) { + return res; + } + + /* get the remainder */ + if (d != NULL) { + if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) { + mp_clear (&t); + return res; + } + } + + /* copy */ + if ((res = mp_copy (a, c)) != MP_OKAY) { + mp_clear (&t); + return res; + } + + /* shift by as many digits in the bit count */ + if (b >= (int)DIGIT_BIT) { + mp_rshd (c, b / DIGIT_BIT); + } + + /* shift any bit count < DIGIT_BIT */ + D = (mp_digit) (b % DIGIT_BIT); + if (D != 0) { + register mp_digit *tmpc, mask; + + /* mask */ + mask = (((mp_digit)1) << D) - 1; + + /* alias */ + tmpc = c->dp + (c->used - 1); + + /* carry */ + r = 0; + for (x = c->used - 1; x >= 0; x--) { + /* get the lower bits of this word in a temp */ + rr = *tmpc & mask; + + /* shift the current word and mix in the carry bits from the previous word */ + *tmpc = (*tmpc >> D) | (r << (DIGIT_BIT - D)); + --tmpc; + + /* set the carry to the carry bits of the current word found above */ + r = rr; + } + } + mp_clamp (c); + if (d != NULL) { + mp_exch (&t, d); + } + mp_clear (&t); + return MP_OKAY; +} + +/* End: bn_mp_div_2d.c */ + +/* Start: bn_mp_div_3.c */ +#line 0 "bn_mp_div_3.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* divide by three (based on routine from MPI and the GMP manual) */ +int +mp_div_3 (mp_int * a, mp_int *c, mp_digit * d) +{ + mp_int q; + mp_word w, t; + mp_digit b; + int res, ix; + + /* b = 2**DIGIT_BIT / 3 */ + b = (((mp_word)1) << ((mp_word)DIGIT_BIT)) / ((mp_word)3); + + if ((res = mp_init_size(&q, a->used)) != MP_OKAY) { + return res; + } + + q.used = a->used; + q.sign = a->sign; + w = 0; + for (ix = a->used - 1; ix >= 0; ix--) { + w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]); + + if (w >= 3) { + t = (w * ((mp_word)b)) >> ((mp_word)DIGIT_BIT); + w -= (t << ((mp_word)1)) + t; + while (w >= 3) { + t += 1; + w -= 3; + } + } else { + t = 0; + } + q.dp[ix] = t; + } + + if (d != NULL) { + *d = w; + } + + if (c != NULL) { + mp_clamp(&q); + mp_exch(&q, c); + } + mp_clear(&q); + + return res; +} + + +/* End: bn_mp_div_3.c */ + +/* Start: bn_mp_div_d.c */ +#line 0 "bn_mp_div_d.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* single digit division (based on routine from MPI) */ +int +mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d) +{ + mp_int q; + mp_word w, t; + int res, ix; + + if (b == 0) { + return MP_VAL; + } + + if (b == 3) { + return mp_div_3(a, c, d); + } + + if ((res = mp_init_size(&q, a->used)) != MP_OKAY) { + return res; + } + + q.used = a->used; + q.sign = a->sign; + w = 0; + for (ix = a->used - 1; ix >= 0; ix--) { + w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]); + + if (w >= b) { + t = w / b; + w = w % b; + } else { + t = 0; + } + q.dp[ix] = t; + } + + if (d != NULL) { + *d = w; + } + + if (c != NULL) { + mp_clamp(&q); + mp_exch(&q, c); + } + mp_clear(&q); + + return res; +} + + +/* End: bn_mp_div_d.c */ + +/* Start: bn_mp_dr_is_modulus.c */ +#line 0 "bn_mp_dr_is_modulus.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* determines if a number is a valid DR modulus */ +int mp_dr_is_modulus(mp_int *a) +{ + int ix; + + /* must be at least two digits */ + if (a->used < 2) { + return 0; + } + + for (ix = 1; ix < a->used; ix++) { + if (a->dp[ix] != MP_MASK) { + return 0; + } + } + return 1; +} + + +/* End: bn_mp_dr_is_modulus.c */ + +/* Start: bn_mp_dr_reduce.c */ +#line 0 "bn_mp_dr_reduce.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* reduce "x" in place modulo "n" using the Diminished Radix algorithm. + * + * Based on algorithm from the paper + * + * "Generating Efficient Primes for Discrete Log Cryptosystems" + * Chae Hoon Lim, Pil Loong Lee, + * POSTECH Information Research Laboratories + * + * The modulus must be of a special format [see manual] + * + * Has been modified to use algorithm 7.10 from the LTM book instead + */ +int +mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k) +{ + int err, i, m; + mp_word r; + mp_digit mu, *tmpx1, *tmpx2; + + /* m = digits in modulus */ + m = n->used; + + /* ensure that "x" has at least 2m digits */ + if (x->alloc < m + m) { + if ((err = mp_grow (x, m + m)) != MP_OKAY) { + return err; + } + } + +/* top of loop, this is where the code resumes if + * another reduction pass is required. + */ +top: + /* aliases for digits */ + /* alias for lower half of x */ + tmpx1 = x->dp; + + /* alias for upper half of x, or x/B**m */ + tmpx2 = x->dp + m; + + /* set carry to zero */ + mu = 0; + + /* compute (x mod B**m) + mp * [x/B**m] inline and inplace */ + for (i = 0; i < m; i++) { + r = ((mp_word)*tmpx2++) * ((mp_word)k) + *tmpx1 + mu; + *tmpx1++ = r & MP_MASK; + mu = r >> ((mp_word)DIGIT_BIT); + } + + /* set final carry */ + *tmpx1++ = mu; + + /* zero words above m */ + for (i = m + 1; i < x->used; i++) { + *tmpx1++ = 0; + } + + /* clamp, sub and return */ + mp_clamp (x); + + /* if x >= n then subtract and reduce again + * Each successive "recursion" makes the input smaller and smaller. + */ + if (mp_cmp_mag (x, n) != MP_LT) { + s_mp_sub(x, n, x); + goto top; + } + return MP_OKAY; +} + +/* End: bn_mp_dr_reduce.c */ + +/* Start: bn_mp_dr_setup.c */ +#line 0 "bn_mp_dr_setup.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* determines the setup value */ +void mp_dr_setup(mp_int *a, mp_digit *d) +{ + /* the casts are required if DIGIT_BIT is one less than + * the number of bits in a mp_digit [e.g. DIGIT_BIT==31] + */ + *d = (mp_digit)((((mp_word)1) << ((mp_word)DIGIT_BIT)) - + ((mp_word)a->dp[0])); +} + + +/* End: bn_mp_dr_setup.c */ + +/* Start: bn_mp_exch.c */ +#line 0 "bn_mp_exch.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* swap the elements of two integers, for cases where you can't simply swap the + * mp_int pointers around + */ +void +mp_exch (mp_int * a, mp_int * b) +{ + mp_int t; + + t = *a; + *a = *b; + *b = t; +} + +/* End: bn_mp_exch.c */ + +/* Start: bn_mp_expt_d.c */ +#line 0 "bn_mp_expt_d.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* calculate c = a**b using a square-multiply algorithm */ +int +mp_expt_d (mp_int * a, mp_digit b, mp_int * c) +{ + int res, x; + mp_int g; + + if ((res = mp_init_copy (&g, a)) != MP_OKAY) { + return res; + } + + /* set initial result */ + mp_set (c, 1); + + for (x = 0; x < (int) DIGIT_BIT; x++) { + /* square */ + if ((res = mp_sqr (c, c)) != MP_OKAY) { + mp_clear (&g); + return res; + } + + /* if the bit is set multiply */ + if ((b & (mp_digit) (((mp_digit)1) << (DIGIT_BIT - 1))) != 0) { + if ((res = mp_mul (c, &g, c)) != MP_OKAY) { + mp_clear (&g); + return res; + } + } + + /* shift to next bit */ + b <<= 1; + } + + mp_clear (&g); + return MP_OKAY; +} + +/* End: bn_mp_expt_d.c */ + +/* Start: bn_mp_exptmod.c */ +#line 0 "bn_mp_exptmod.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + + +/* this is a shell function that calls either the normal or Montgomery + * exptmod functions. Originally the call to the montgomery code was + * embedded in the normal function but that wasted alot of stack space + * for nothing (since 99% of the time the Montgomery code would be called) + */ +int +mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) +{ + int dr; + + /* modulus P must be positive */ + if (P->sign == MP_NEG) { + return MP_VAL; + } + + /* if exponent X is negative we have to recurse */ + if (X->sign == MP_NEG) { + mp_int tmpG, tmpX; + int err; + + /* first compute 1/G mod P */ + if ((err = mp_init(&tmpG)) != MP_OKAY) { + return err; + } + if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) { + mp_clear(&tmpG); + return err; + } + + /* now get |X| */ + if ((err = mp_init(&tmpX)) != MP_OKAY) { + mp_clear(&tmpG); + return err; + } + if ((err = mp_abs(X, &tmpX)) != MP_OKAY) { + mp_clear_multi(&tmpG, &tmpX, NULL); + return err; + } + + /* and now compute (1/G)**|X| instead of G**X [X < 0] */ + err = mp_exptmod(&tmpG, &tmpX, P, Y); + mp_clear_multi(&tmpG, &tmpX, NULL); + return err; + } + + dr = mp_dr_is_modulus(P); + if (dr == 0) { + dr = mp_reduce_is_2k(P) << 1; + } + + /* if the modulus is odd use the fast method */ + if ((mp_isodd (P) == 1 || dr != 0) && P->used > 4) { + return mp_exptmod_fast (G, X, P, Y, dr); + } else { + return s_mp_exptmod (G, X, P, Y); + } +} + + +/* End: bn_mp_exptmod.c */ + +/* Start: bn_mp_exptmod_fast.c */ +#line 0 "bn_mp_exptmod_fast.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* computes Y == G^X mod P, HAC pp.616, Algorithm 14.85 + * + * Uses a left-to-right k-ary sliding window to compute the modular exponentiation. + * The value of k changes based on the size of the exponent. + * + * Uses Montgomery or Diminished Radix reduction [whichever appropriate] + */ +int +mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) +{ + mp_int M[256], res; + mp_digit buf, mp; + int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; + + /* use a pointer to the reduction algorithm. This allows us to use + * one of many reduction algorithms without modding the guts of + * the code with if statements everywhere. + */ + int (*redux)(mp_int*,mp_int*,mp_digit); + + /* find window size */ + x = mp_count_bits (X); + if (x <= 7) { + winsize = 2; + } else if (x <= 36) { + winsize = 3; + } else if (x <= 140) { + winsize = 4; + } else if (x <= 450) { + winsize = 5; + } else if (x <= 1303) { + winsize = 6; + } else if (x <= 3529) { + winsize = 7; + } else { + winsize = 8; + } + +#ifdef MP_LOW_MEM + if (winsize > 5) { + winsize = 5; + } +#endif + + + /* init G array */ + for (x = 0; x < (1 << winsize); x++) { + if ((err = mp_init (&M[x])) != MP_OKAY) { + for (y = 0; y < x; y++) { + mp_clear (&M[y]); + } + return err; + } + } + + /* determine and setup reduction code */ + if (redmode == 0) { + /* now setup montgomery */ + if ((err = mp_montgomery_setup (P, &mp)) != MP_OKAY) { + goto __M; + } + + /* automatically pick the comba one if available (saves quite a few calls/ifs) */ + if (((P->used * 2 + 1) < MP_WARRAY) && + P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + redux = fast_mp_montgomery_reduce; + } else { + /* use slower baselien method */ + redux = mp_montgomery_reduce; + } + } else if (redmode == 1) { + /* setup DR reduction */ + mp_dr_setup(P, &mp); + redux = mp_dr_reduce; + } else { + /* setup 2k reduction */ + if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) { + goto __M; + } + redux = mp_reduce_2k; + } + + /* setup result */ + if ((err = mp_init (&res)) != MP_OKAY) { + goto __RES; + } + + /* create M table + * + * The M table contains powers of the input base, e.g. M[x] = G^x mod P + * + * The first half of the table is not computed though accept for M[0] and M[1] + */ + + if (redmode == 0) { + /* now we need R mod m */ + if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) { + goto __RES; + } + + /* now set M[1] to G * R mod m */ + if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) { + goto __RES; + } + } else { + mp_set(&res, 1); + if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) { + goto __RES; + } + } + + /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */ + if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) { + goto __RES; + } + + for (x = 0; x < (winsize - 1); x++) { + if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) { + goto __RES; + } + if ((err = redux (&M[1 << (winsize - 1)], P, mp)) != MP_OKAY) { + goto __RES; + } + } + + /* create upper table */ + for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { + if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) { + goto __RES; + } + if ((err = redux (&M[x], P, mp)) != MP_OKAY) { + goto __RES; + } + } + + /* set initial mode and bit cnt */ + mode = 0; + bitcnt = 1; + buf = 0; + digidx = X->used - 1; + bitcpy = 0; + bitbuf = 0; + + for (;;) { + /* grab next digit as required */ + if (--bitcnt == 0) { + if (digidx == -1) { + break; + } + buf = X->dp[digidx--]; + bitcnt = (int) DIGIT_BIT; + } + + /* grab the next msb from the exponent */ + y = (mp_digit)(buf >> (DIGIT_BIT - 1)) & 1; + buf <<= (mp_digit)1; + + /* if the bit is zero and mode == 0 then we ignore it + * These represent the leading zero bits before the first 1 bit + * in the exponent. Technically this opt is not required but it + * does lower the # of trivial squaring/reductions used + */ + if (mode == 0 && y == 0) { + continue; + } + + /* if the bit is zero and mode == 1 then we square */ + if (mode == 1 && y == 0) { + if ((err = mp_sqr (&res, &res)) != MP_OKAY) { + goto __RES; + } + if ((err = redux (&res, P, mp)) != MP_OKAY) { + goto __RES; + } + continue; + } + + /* else we add it to the window */ + bitbuf |= (y << (winsize - ++bitcpy)); + mode = 2; + + if (bitcpy == winsize) { + /* ok window is filled so square as required and multiply */ + /* square first */ + for (x = 0; x < winsize; x++) { + if ((err = mp_sqr (&res, &res)) != MP_OKAY) { + goto __RES; + } + if ((err = redux (&res, P, mp)) != MP_OKAY) { + goto __RES; + } + } + + /* then multiply */ + if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) { + goto __RES; + } + if ((err = redux (&res, P, mp)) != MP_OKAY) { + goto __RES; + } + + /* empty window and reset */ + bitcpy = 0; + bitbuf = 0; + mode = 1; + } + } + + /* if bits remain then square/multiply */ + if (mode == 2 && bitcpy > 0) { + /* square then multiply if the bit is set */ + for (x = 0; x < bitcpy; x++) { + if ((err = mp_sqr (&res, &res)) != MP_OKAY) { + goto __RES; + } + if ((err = redux (&res, P, mp)) != MP_OKAY) { + goto __RES; + } + + bitbuf <<= 1; + if ((bitbuf & (1 << winsize)) != 0) { + /* then multiply */ + if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) { + goto __RES; + } + if ((err = redux (&res, P, mp)) != MP_OKAY) { + goto __RES; + } + } + } + } + + if (redmode == 0) { + /* fixup result if Montgomery reduction is used */ + if ((err = mp_montgomery_reduce (&res, P, mp)) != MP_OKAY) { + goto __RES; + } + } + + mp_exch (&res, Y); + err = MP_OKAY; +__RES:mp_clear (&res); +__M: + for (x = 0; x < (1 << winsize); x++) { + mp_clear (&M[x]); + } + return err; +} + +/* End: bn_mp_exptmod_fast.c */ + +/* Start: bn_mp_gcd.c */ +#line 0 "bn_mp_gcd.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* Greatest Common Divisor using the binary method [Algorithm B, page 338, vol2 of TAOCP] + */ +int +mp_gcd (mp_int * a, mp_int * b, mp_int * c) +{ + mp_int u, v, t; + int k, res, neg; + + /* either zero than gcd is the largest */ + if (mp_iszero (a) == 1 && mp_iszero (b) == 0) { + return mp_copy (b, c); + } + if (mp_iszero (a) == 0 && mp_iszero (b) == 1) { + return mp_copy (a, c); + } + if (mp_iszero (a) == 1 && mp_iszero (b) == 1) { + mp_set (c, 1); + return MP_OKAY; + } + + /* if both are negative they share (-1) as a common divisor */ + neg = (a->sign == b->sign) ? a->sign : MP_ZPOS; + + if ((res = mp_init_copy (&u, a)) != MP_OKAY) { + return res; + } + + if ((res = mp_init_copy (&v, b)) != MP_OKAY) { + goto __U; + } + + /* must be positive for the remainder of the algorithm */ + u.sign = v.sign = MP_ZPOS; + + if ((res = mp_init (&t)) != MP_OKAY) { + goto __V; + } + + /* B1. Find power of two */ + k = 0; + while (mp_iseven(&u) == 1 && mp_iseven(&v) == 1) { + ++k; + if ((res = mp_div_2 (&u, &u)) != MP_OKAY) { + goto __T; + } + if ((res = mp_div_2 (&v, &v)) != MP_OKAY) { + goto __T; + } + } + + /* B2. Initialize */ + if (mp_isodd(&u) == 1) { + /* t = -v */ + if ((res = mp_copy (&v, &t)) != MP_OKAY) { + goto __T; + } + t.sign = MP_NEG; + } else { + /* t = u */ + if ((res = mp_copy (&u, &t)) != MP_OKAY) { + goto __T; + } + } + + do { + /* B3 (and B4). Halve t, if even */ + while (t.used != 0 && mp_iseven(&t) == 1) { + if ((res = mp_div_2 (&t, &t)) != MP_OKAY) { + goto __T; + } + } + + /* B5. if t>0 then u=t otherwise v=-t */ + if (t.used != 0 && t.sign != MP_NEG) { + if ((res = mp_copy (&t, &u)) != MP_OKAY) { + goto __T; + } + } else { + if ((res = mp_copy (&t, &v)) != MP_OKAY) { + goto __T; + } + v.sign = (v.sign == MP_ZPOS) ? MP_NEG : MP_ZPOS; + } + + /* B6. t = u - v, if t != 0 loop otherwise terminate */ + if ((res = mp_sub (&u, &v, &t)) != MP_OKAY) { + goto __T; + } + } while (mp_iszero(&t) == 0); + + /* multiply by 2^k which we divided out at the beginning */ + if ((res = mp_mul_2d (&u, k, &u)) != MP_OKAY) { + goto __T; + } + + mp_exch (&u, c); + c->sign = neg; + res = MP_OKAY; +__T:mp_clear (&t); +__V:mp_clear (&u); +__U:mp_clear (&v); + return res; +} + +/* End: bn_mp_gcd.c */ + +/* Start: bn_mp_grow.c */ +#line 0 "bn_mp_grow.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* grow as required */ +int +mp_grow (mp_int * a, int size) +{ + int i; + + /* if the alloc size is smaller alloc more ram */ + if (a->alloc < size) { + /* ensure there are always at least MP_PREC digits extra on top */ + size += (MP_PREC * 2) - (size & (MP_PREC - 1)); + + a->dp = OPT_CAST realloc (a->dp, sizeof (mp_digit) * size); + if (a->dp == NULL) { + return MP_MEM; + } + + /* zero excess digits */ + i = a->alloc; + a->alloc = size; + for (; i < a->alloc; i++) { + a->dp[i] = 0; + } + } + return MP_OKAY; +} + +/* End: bn_mp_grow.c */ + +/* Start: bn_mp_init.c */ +#line 0 "bn_mp_init.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* init a new bigint */ +int +mp_init (mp_int * a) +{ + /* allocate ram required and clear it */ + a->dp = OPT_CAST calloc (sizeof (mp_digit), MP_PREC); + if (a->dp == NULL) { + return MP_MEM; + } + + /* set the used to zero, allocated digits to the default precision + * and sign to positive */ + a->used = 0; + a->alloc = MP_PREC; + a->sign = MP_ZPOS; + + return MP_OKAY; +} + +/* End: bn_mp_init.c */ + +/* Start: bn_mp_init_copy.c */ +#line 0 "bn_mp_init_copy.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* creates "a" then copies b into it */ +int +mp_init_copy (mp_int * a, mp_int * b) +{ + int res; + + if ((res = mp_init (a)) != MP_OKAY) { + return res; + } + return mp_copy (b, a); +} + +/* End: bn_mp_init_copy.c */ + +/* Start: bn_mp_init_size.c */ +#line 0 "bn_mp_init_size.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* init a mp_init and grow it to a given size */ +int +mp_init_size (mp_int * a, int size) +{ + + /* pad size so there are always extra digits */ + size += (MP_PREC * 2) - (size & (MP_PREC - 1)); + + /* alloc mem */ + a->dp = OPT_CAST calloc (sizeof (mp_digit), size); + if (a->dp == NULL) { + return MP_MEM; + } + a->used = 0; + a->alloc = size; + a->sign = MP_ZPOS; + + return MP_OKAY; +} + +/* End: bn_mp_init_size.c */ + +/* Start: bn_mp_invmod.c */ +#line 0 "bn_mp_invmod.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +int +mp_invmod (mp_int * a, mp_int * b, mp_int * c) +{ + mp_int x, y, u, v, A, B, C, D; + int res; + + /* b cannot be negative */ + if (b->sign == MP_NEG) { + return MP_VAL; + } + + /* if the modulus is odd we can use a faster routine instead */ + if (mp_iseven (b) == 0) { + return fast_mp_invmod (a, b, c); + } + + /* init temps */ + if ((res = mp_init_multi(&x, &y, &u, &v, &A, &B, &C, &D, NULL)) != MP_OKAY) { + return res; + } + + /* x = a, y = b */ + if ((res = mp_copy (a, &x)) != MP_OKAY) { + goto __ERR; + } + if ((res = mp_copy (b, &y)) != MP_OKAY) { + goto __ERR; + } + + if ((res = mp_abs (&x, &x)) != MP_OKAY) { + goto __ERR; + } + + /* 2. [modified] if x,y are both even then return an error! */ + if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) { + res = MP_VAL; + goto __ERR; + } + + /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ + if ((res = mp_copy (&x, &u)) != MP_OKAY) { + goto __ERR; + } + if ((res = mp_copy (&y, &v)) != MP_OKAY) { + goto __ERR; + } + mp_set (&A, 1); + mp_set (&D, 1); + + +top: + /* 4. while u is even do */ + while (mp_iseven (&u) == 1) { + /* 4.1 u = u/2 */ + if ((res = mp_div_2 (&u, &u)) != MP_OKAY) { + goto __ERR; + } + /* 4.2 if A or B is odd then */ + if (mp_iseven (&A) == 0 || mp_iseven (&B) == 0) { + /* A = (A+y)/2, B = (B-x)/2 */ + if ((res = mp_add (&A, &y, &A)) != MP_OKAY) { + goto __ERR; + } + if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) { + goto __ERR; + } + } + /* A = A/2, B = B/2 */ + if ((res = mp_div_2 (&A, &A)) != MP_OKAY) { + goto __ERR; + } + if ((res = mp_div_2 (&B, &B)) != MP_OKAY) { + goto __ERR; + } + } + + + /* 5. while v is even do */ + while (mp_iseven (&v) == 1) { + /* 5.1 v = v/2 */ + if ((res = mp_div_2 (&v, &v)) != MP_OKAY) { + goto __ERR; + } + /* 5.2 if C,D are even then */ + if (mp_iseven (&C) == 0 || mp_iseven (&D) == 0) { + /* C = (C+y)/2, D = (D-x)/2 */ + if ((res = mp_add (&C, &y, &C)) != MP_OKAY) { + goto __ERR; + } + if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) { + goto __ERR; + } + } + /* C = C/2, D = D/2 */ + if ((res = mp_div_2 (&C, &C)) != MP_OKAY) { + goto __ERR; + } + if ((res = mp_div_2 (&D, &D)) != MP_OKAY) { + goto __ERR; + } + } + + /* 6. if u >= v then */ + if (mp_cmp (&u, &v) != MP_LT) { + /* u = u - v, A = A - C, B = B - D */ + if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) { + goto __ERR; + } + + if ((res = mp_sub (&A, &C, &A)) != MP_OKAY) { + goto __ERR; + } + + if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) { + goto __ERR; + } + } else { + /* v - v - u, C = C - A, D = D - B */ + if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) { + goto __ERR; + } + + if ((res = mp_sub (&C, &A, &C)) != MP_OKAY) { + goto __ERR; + } + + if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) { + goto __ERR; + } + } + + /* if not zero goto step 4 */ + if (mp_iszero (&u) == 0) + goto top; + + /* now a = C, b = D, gcd == g*v */ + + /* if v != 1 then there is no inverse */ + if (mp_cmp_d (&v, 1) != MP_EQ) { + res = MP_VAL; + goto __ERR; + } + + /* a is now the inverse */ + mp_exch (&C, c); + res = MP_OKAY; + +__ERR:mp_clear_multi (&x, &y, &u, &v, &A, &B, &C, &D, NULL); + return res; +} + +/* End: bn_mp_invmod.c */ + +/* Start: bn_mp_jacobi.c */ +#line 0 "bn_mp_jacobi.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* computes the jacobi c = (a | n) (or Legendre if n is prime) + * HAC pp. 73 Algorithm 2.149 + */ +int +mp_jacobi (mp_int * a, mp_int * n, int *c) +{ + mp_int a1, n1, e; + int s, r, res; + mp_digit residue; + + /* step 1. if a == 0, return 0 */ + if (mp_iszero (a) == 1) { + *c = 0; + return MP_OKAY; + } + + /* step 2. if a == 1, return 1 */ + if (mp_cmp_d (a, 1) == MP_EQ) { + *c = 1; + return MP_OKAY; + } + + /* default */ + s = 0; + + /* step 3. write a = a1 * 2^e */ + if ((res = mp_init_copy (&a1, a)) != MP_OKAY) { + return res; + } + + if ((res = mp_init (&n1)) != MP_OKAY) { + goto __A1; + } + + if ((res = mp_init (&e)) != MP_OKAY) { + goto __N1; + } + + while (mp_iseven (&a1) == 1) { + if ((res = mp_add_d (&e, 1, &e)) != MP_OKAY) { + goto __E; + } + + if ((res = mp_div_2 (&a1, &a1)) != MP_OKAY) { + goto __E; + } + } + + /* step 4. if e is even set s=1 */ + if (mp_iseven (&e) == 1) { + s = 1; + } else { + /* else set s=1 if n = 1/7 (mod 8) or s=-1 if n = 3/5 (mod 8) */ + if ((res = mp_mod_d (n, 8, &residue)) != MP_OKAY) { + goto __E; + } + + if (residue == 1 || residue == 7) { + s = 1; + } else if (residue == 3 || residue == 5) { + s = -1; + } + } + + /* step 5. if n == 3 (mod 4) *and* a1 == 3 (mod 4) then s = -s */ + if ((res = mp_mod_d (n, 4, &residue)) != MP_OKAY) { + goto __E; + } + if (residue == 3) { + if ((res = mp_mod_d (&a1, 4, &residue)) != MP_OKAY) { + goto __E; + } + if (residue == 3) { + s = -s; + } + } + + /* if a1 == 1 we're done */ + if (mp_cmp_d (&a1, 1) == MP_EQ) { + *c = s; + } else { + /* n1 = n mod a1 */ + if ((res = mp_mod (n, &a1, &n1)) != MP_OKAY) { + goto __E; + } + if ((res = mp_jacobi (&n1, &a1, &r)) != MP_OKAY) { + goto __E; + } + *c = s * r; + } + + /* done */ + res = MP_OKAY; +__E:mp_clear (&e); +__N1:mp_clear (&n1); +__A1:mp_clear (&a1); + return res; +} + +/* End: bn_mp_jacobi.c */ + +/* Start: bn_mp_karatsuba_mul.c */ +#line 0 "bn_mp_karatsuba_mul.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* c = |a| * |b| using Karatsuba Multiplication using + * three half size multiplications + * + * Let B represent the radix [e.g. 2**DIGIT_BIT] and + * let n represent half of the number of digits in + * the min(a,b) + * + * a = a1 * B**n + a0 + * b = b1 * B**n + b0 + * + * Then, a * b => + a1b1 * B**2n + ((a1 - a0)(b1 - b0) + a0b0 + a1b1) * B + a0b0 + * + * Note that a1b1 and a0b0 are used twice and only need to be + * computed once. So in total three half size (half # of + * digit) multiplications are performed, a0b0, a1b1 and + * (a1-b1)(a0-b0) + * + * Note that a multiplication of half the digits requires + * 1/4th the number of single precision multiplications so in + * total after one call 25% of the single precision multiplications + * are saved. Note also that the call to mp_mul can end up back + * in this function if the a0, a1, b0, or b1 are above the threshold. + * This is known as divide-and-conquer and leads to the famous + * O(N**lg(3)) or O(N**1.584) work which is asymptopically lower than + * the standard O(N**2) that the baseline/comba methods use. + * Generally though the overhead of this method doesn't pay off + * until a certain size (N ~ 80) is reached. + */ +int +mp_karatsuba_mul (mp_int * a, mp_int * b, mp_int * c) +{ + mp_int x0, x1, y0, y1, t1, x0y0, x1y1; + int B, err; + + err = MP_MEM; + + /* min # of digits */ + B = MIN (a->used, b->used); + + /* now divide in two */ + B = B / 2; + + /* init copy all the temps */ + if (mp_init_size (&x0, B) != MP_OKAY) + goto ERR; + if (mp_init_size (&x1, a->used - B) != MP_OKAY) + goto X0; + if (mp_init_size (&y0, B) != MP_OKAY) + goto X1; + if (mp_init_size (&y1, b->used - B) != MP_OKAY) + goto Y0; + + /* init temps */ + if (mp_init_size (&t1, B * 2) != MP_OKAY) + goto Y1; + if (mp_init_size (&x0y0, B * 2) != MP_OKAY) + goto T1; + if (mp_init_size (&x1y1, B * 2) != MP_OKAY) + goto X0Y0; + + /* now shift the digits */ + x0.sign = x1.sign = a->sign; + y0.sign = y1.sign = b->sign; + + x0.used = y0.used = B; + x1.used = a->used - B; + y1.used = b->used - B; + + { + register int x; + register mp_digit *tmpa, *tmpb, *tmpx, *tmpy; + + /* we copy the digits directly instead of using higher level functions + * since we also need to shift the digits + */ + tmpa = a->dp; + tmpb = b->dp; + + tmpx = x0.dp; + tmpy = y0.dp; + for (x = 0; x < B; x++) { + *tmpx++ = *tmpa++; + *tmpy++ = *tmpb++; + } + + tmpx = x1.dp; + for (x = B; x < a->used; x++) { + *tmpx++ = *tmpa++; + } + + tmpy = y1.dp; + for (x = B; x < b->used; x++) { + *tmpy++ = *tmpb++; + } + } + + /* only need to clamp the lower words since by definition the + * upper words x1/y1 must have a known number of digits + */ + mp_clamp (&x0); + mp_clamp (&y0); + + /* now calc the products x0y0 and x1y1 */ + /* after this x0 is no longer required, free temp [x0==t2]! */ + if (mp_mul (&x0, &y0, &x0y0) != MP_OKAY) + goto X1Y1; /* x0y0 = x0*y0 */ + if (mp_mul (&x1, &y1, &x1y1) != MP_OKAY) + goto X1Y1; /* x1y1 = x1*y1 */ + + /* now calc x1-x0 and y1-y0 */ + if (mp_sub (&x1, &x0, &t1) != MP_OKAY) + goto X1Y1; /* t1 = x1 - x0 */ + if (mp_sub (&y1, &y0, &x0) != MP_OKAY) + goto X1Y1; /* t2 = y1 - y0 */ + if (mp_mul (&t1, &x0, &t1) != MP_OKAY) + goto X1Y1; /* t1 = (x1 - x0) * (y1 - y0) */ + + /* add x0y0 */ + if (mp_add (&x0y0, &x1y1, &x0) != MP_OKAY) + goto X1Y1; /* t2 = x0y0 + x1y1 */ + if (mp_sub (&x0, &t1, &t1) != MP_OKAY) + goto X1Y1; /* t1 = x0y0 + x1y1 - (x1-x0)*(y1-y0) */ + + /* shift by B */ + if (mp_lshd (&t1, B) != MP_OKAY) + goto X1Y1; /* t1 = (x0y0 + x1y1 - (x1-x0)*(y1-y0))< + +/* Karatsuba squaring, computes b = a*a using three + * half size squarings + * + * See comments of mp_karatsuba_mul for details. It + * is essentially the same algorithm but merely + * tuned to perform recursive squarings. + */ +int +mp_karatsuba_sqr (mp_int * a, mp_int * b) +{ + mp_int x0, x1, t1, t2, x0x0, x1x1; + int B, err; + + err = MP_MEM; + + /* min # of digits */ + B = a->used; + + /* now divide in two */ + B = B / 2; + + /* init copy all the temps */ + if (mp_init_size (&x0, B) != MP_OKAY) + goto ERR; + if (mp_init_size (&x1, a->used - B) != MP_OKAY) + goto X0; + + /* init temps */ + if (mp_init_size (&t1, a->used * 2) != MP_OKAY) + goto X1; + if (mp_init_size (&t2, a->used * 2) != MP_OKAY) + goto T1; + if (mp_init_size (&x0x0, B * 2) != MP_OKAY) + goto T2; + if (mp_init_size (&x1x1, (a->used - B) * 2) != MP_OKAY) + goto X0X0; + + { + register int x; + register mp_digit *dst, *src; + + src = a->dp; + + /* now shift the digits */ + dst = x0.dp; + for (x = 0; x < B; x++) { + *dst++ = *src++; + } + + dst = x1.dp; + for (x = B; x < a->used; x++) { + *dst++ = *src++; + } + } + + x0.used = B; + x1.used = a->used - B; + + mp_clamp (&x0); + + /* now calc the products x0*x0 and x1*x1 */ + if (mp_sqr (&x0, &x0x0) != MP_OKAY) + goto X1X1; /* x0x0 = x0*x0 */ + if (mp_sqr (&x1, &x1x1) != MP_OKAY) + goto X1X1; /* x1x1 = x1*x1 */ + + /* now calc (x1-x0)**2 */ + if (mp_sub (&x1, &x0, &t1) != MP_OKAY) + goto X1X1; /* t1 = x1 - x0 */ + if (mp_sqr (&t1, &t1) != MP_OKAY) + goto X1X1; /* t1 = (x1 - x0) * (x1 - x0) */ + + /* add x0y0 */ + if (s_mp_add (&x0x0, &x1x1, &t2) != MP_OKAY) + goto X1X1; /* t2 = x0x0 + x1x1 */ + if (mp_sub (&t2, &t1, &t1) != MP_OKAY) + goto X1X1; /* t1 = x0x0 + x1x1 - (x1-x0)*(x1-x0) */ + + /* shift by B */ + if (mp_lshd (&t1, B) != MP_OKAY) + goto X1X1; /* t1 = (x0x0 + x1x1 - (x1-x0)*(x1-x0))< + +/* computes least common multiple as a*b/(a, b) */ +int +mp_lcm (mp_int * a, mp_int * b, mp_int * c) +{ + int res; + mp_int t; + + + if ((res = mp_init (&t)) != MP_OKAY) { + return res; + } + + if ((res = mp_mul (a, b, &t)) != MP_OKAY) { + mp_clear (&t); + return res; + } + + if ((res = mp_gcd (a, b, c)) != MP_OKAY) { + mp_clear (&t); + return res; + } + + res = mp_div (&t, c, c, NULL); + mp_clear (&t); + return res; +} + +/* End: bn_mp_lcm.c */ + +/* Start: bn_mp_lshd.c */ +#line 0 "bn_mp_lshd.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* shift left a certain amount of digits */ +int +mp_lshd (mp_int * a, int b) +{ + int x, res; + + /* if its less than zero return */ + if (b <= 0) { + return MP_OKAY; + } + + /* grow to fit the new digits */ + if (a->alloc < a->used + b) { + if ((res = mp_grow (a, a->used + b)) != MP_OKAY) { + return res; + } + } + + { + register mp_digit *top, *bottom; + + /* increment the used by the shift amount then copy upwards */ + a->used += b; + + /* top */ + top = a->dp + a->used - 1; + + /* base */ + bottom = a->dp + a->used - 1 - b; + + /* much like mp_rshd this is implemented using a sliding window + * except the window goes the otherway around. Copying from + * the bottom to the top. see bn_mp_rshd.c for more info. + */ + for (x = a->used - 1; x >= b; x--) { + *top-- = *bottom--; + } + + /* zero the lower digits */ + top = a->dp; + for (x = 0; x < b; x++) { + *top++ = 0; + } + } + return MP_OKAY; +} + +/* End: bn_mp_lshd.c */ + +/* Start: bn_mp_mod.c */ +#line 0 "bn_mp_mod.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* c = a mod b, 0 <= c < b */ +int +mp_mod (mp_int * a, mp_int * b, mp_int * c) +{ + mp_int t; + int res; + + + if ((res = mp_init (&t)) != MP_OKAY) { + return res; + } + + if ((res = mp_div (a, b, NULL, &t)) != MP_OKAY) { + mp_clear (&t); + return res; + } + + if (t.sign == MP_NEG) { + res = mp_add (b, &t, c); + } else { + res = MP_OKAY; + mp_exch (&t, c); + } + + mp_clear (&t); + return res; +} + +/* End: bn_mp_mod.c */ + +/* Start: bn_mp_mod_2d.c */ +#line 0 "bn_mp_mod_2d.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* calc a value mod 2^b */ +int +mp_mod_2d (mp_int * a, int b, mp_int * c) +{ + int x, res; + + + /* if b is <= 0 then zero the int */ + if (b <= 0) { + mp_zero (c); + return MP_OKAY; + } + + /* if the modulus is larger than the value than return */ + if (b > (int) (a->used * DIGIT_BIT)) { + res = mp_copy (a, c); + return res; + } + + /* copy */ + if ((res = mp_copy (a, c)) != MP_OKAY) { + return res; + } + + /* zero digits above the last digit of the modulus */ + for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) { + c->dp[x] = 0; + } + /* clear the digit that is not completely outside/inside the modulus */ + c->dp[b / DIGIT_BIT] &= + (mp_digit) ((((mp_digit) 1) << (((mp_digit) b) % DIGIT_BIT)) - ((mp_digit) 1)); + mp_clamp (c); + return MP_OKAY; +} + +/* End: bn_mp_mod_2d.c */ + +/* Start: bn_mp_mod_d.c */ +#line 0 "bn_mp_mod_d.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +int +mp_mod_d (mp_int * a, mp_digit b, mp_digit * c) +{ + return mp_div_d(a, b, NULL, c); +} + +/* End: bn_mp_mod_d.c */ + +/* Start: bn_mp_montgomery_calc_normalization.c */ +#line 0 "bn_mp_montgomery_calc_normalization.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* calculates a = B^n mod b for Montgomery reduction + * Where B is the base [e.g. 2^DIGIT_BIT]. + * B^n mod b is computed by first computing + * A = B^(n-1) which doesn't require a reduction but a simple OR. + * then C = A * B = B^n is computed by performing upto DIGIT_BIT + * shifts with subtractions when the result is greater than b. + * + * The method is slightly modified to shift B unconditionally upto just under + * the leading bit of b. This saves alot of multiple precision shifting. + */ +int +mp_montgomery_calc_normalization (mp_int * a, mp_int * b) +{ + int x, bits, res; + + /* how many bits of last digit does b use */ + bits = mp_count_bits (b) % DIGIT_BIT; + + /* compute A = B^(n-1) * 2^(bits-1) */ + if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) { + return res; + } + + /* now compute C = A * B mod b */ + for (x = bits - 1; x < (int)DIGIT_BIT; x++) { + if ((res = mp_mul_2 (a, a)) != MP_OKAY) { + return res; + } + if (mp_cmp_mag (a, b) != MP_LT) { + if ((res = s_mp_sub (a, b, a)) != MP_OKAY) { + return res; + } + } + } + + return MP_OKAY; +} + +/* End: bn_mp_montgomery_calc_normalization.c */ + +/* Start: bn_mp_montgomery_reduce.c */ +#line 0 "bn_mp_montgomery_reduce.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* computes xR**-1 == x (mod N) via Montgomery Reduction */ +int +mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) +{ + int ix, res, digs; + mp_digit mu; + + /* can the fast reduction [comba] method be used? + * + * Note that unlike in mp_mul you're safely allowed *less* + * than the available columns [255 per default] since carries + * are fixed up in the inner loop. + */ + digs = n->used * 2 + 1; + if ((digs < MP_WARRAY) && + n->used < + (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + return fast_mp_montgomery_reduce (x, n, rho); + } + + /* grow the input as required */ + if (x->alloc < digs) { + if ((res = mp_grow (x, digs)) != MP_OKAY) { + return res; + } + } + x->used = digs; + + for (ix = 0; ix < n->used; ix++) { + /* mu = ai * m' mod b */ + mu = (x->dp[ix] * rho) & MP_MASK; + + /* a = a + mu * m * b**i */ + { + register int iy; + register mp_digit *tmpn, *tmpx, u; + register mp_word r; + + /* aliases */ + tmpn = n->dp; + tmpx = x->dp + ix; + + /* set the carry to zero */ + u = 0; + + /* Multiply and add in place */ + for (iy = 0; iy < n->used; iy++) { + r = ((mp_word) mu) * ((mp_word) * tmpn++) + + ((mp_word) u) + ((mp_word) * tmpx); + u = (r >> ((mp_word) DIGIT_BIT)); + *tmpx++ = (r & ((mp_word) MP_MASK)); + } + /* propagate carries */ + while (u) { + *tmpx += u; + u = *tmpx >> DIGIT_BIT; + *tmpx++ &= MP_MASK; + } + } + } + + /* x = x/b**n.used */ + mp_rshd (x, n->used); + + /* if A >= m then A = A - m */ + if (mp_cmp_mag (x, n) != MP_LT) { + return s_mp_sub (x, n, x); + } + + return MP_OKAY; +} + +/* End: bn_mp_montgomery_reduce.c */ + +/* Start: bn_mp_montgomery_setup.c */ +#line 0 "bn_mp_montgomery_setup.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* setups the montgomery reduction stuff */ +int +mp_montgomery_setup (mp_int * n, mp_digit * rho) +{ + mp_digit x, b; + +/* fast inversion mod 2**k + * + * Based on the fact that + * + * XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n) + * => 2*X*A - X*X*A*A = 1 + * => 2*(1) - (1) = 1 + */ + b = n->dp[0]; + + if ((b & 1) == 0) { + return MP_VAL; + } + + x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ + x *= 2 - b * x; /* here x*a==1 mod 2**8 */ +#if !defined(MP_8BIT) + x *= 2 - b * x; /* here x*a==1 mod 2**16 */ +#endif +#if defined(MP_64BIT) || !(defined(MP_8BIT) || defined(MP_16BIT)) + x *= 2 - b * x; /* here x*a==1 mod 2**32 */ +#endif +#ifdef MP_64BIT + x *= 2 - b * x; /* here x*a==1 mod 2**64 */ +#endif + + /* rho = -1/m mod b */ + *rho = (((mp_digit) 1 << ((mp_digit) DIGIT_BIT)) - x) & MP_MASK; + + return MP_OKAY; +} + +/* End: bn_mp_montgomery_setup.c */ + +/* Start: bn_mp_mul.c */ +#line 0 "bn_mp_mul.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* high level multiplication (handles sign) */ +int +mp_mul (mp_int * a, mp_int * b, mp_int * c) +{ + int res, neg; + neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; + + if (MIN (a->used, b->used) >= TOOM_MUL_CUTOFF) { + res = mp_toom_mul(a, b, c); + } else if (MIN (a->used, b->used) >= KARATSUBA_MUL_CUTOFF) { + res = mp_karatsuba_mul (a, b, c); + } else { + + /* can we use the fast multiplier? + * + * The fast multiplier can be used if the output will + * have less than MP_WARRAY digits and the number of + * digits won't affect carry propagation + */ + int digs = a->used + b->used + 1; + + if ((digs < MP_WARRAY) && + MIN(a->used, b->used) <= + (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + res = fast_s_mp_mul_digs (a, b, c, digs); + } else { + res = s_mp_mul (a, b, c); + } + + } + c->sign = neg; + return res; +} + +/* End: bn_mp_mul.c */ + +/* Start: bn_mp_mul_2.c */ +#line 0 "bn_mp_mul_2.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* b = a*2 */ +int +mp_mul_2 (mp_int * a, mp_int * b) +{ + int x, res, oldused; + + /* grow to accomodate result */ + if (b->alloc < a->used + 1) { + if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) { + return res; + } + } + + oldused = b->used; + b->used = a->used; + + { + register mp_digit r, rr, *tmpa, *tmpb; + + /* alias for source */ + tmpa = a->dp; + + /* alias for dest */ + tmpb = b->dp; + + /* carry */ + r = 0; + for (x = 0; x < a->used; x++) { + + /* get what will be the *next* carry bit from the + * MSB of the current digit + */ + rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1)); + + /* now shift up this digit, add in the carry [from the previous] */ + *tmpb++ = ((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK; + + /* copy the carry that would be from the source + * digit into the next iteration + */ + r = rr; + } + + /* new leading digit? */ + if (r != 0) { + /* add a MSB which is always 1 at this point */ + *tmpb = 1; + ++b->used; + } + + /* now zero any excess digits on the destination + * that we didn't write to + */ + tmpb = b->dp + b->used; + for (x = b->used; x < oldused; x++) { + *tmpb++ = 0; + } + } + b->sign = a->sign; + return MP_OKAY; +} + +/* End: bn_mp_mul_2.c */ + +/* Start: bn_mp_mul_2d.c */ +#line 0 "bn_mp_mul_2d.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* NOTE: This routine requires updating. For instance the c->used = c->alloc bit + is wrong. We should just shift c->used digits then set the carry as c->dp[c->used] = carry + + To be fixed for LTM 0.18 + */ + +/* shift left by a certain bit count */ +int +mp_mul_2d (mp_int * a, int b, mp_int * c) +{ + mp_digit d; + int res; + + /* copy */ + if (a != c) { + if ((res = mp_copy (a, c)) != MP_OKAY) { + return res; + } + } + + if (c->alloc < (int)(c->used + b/DIGIT_BIT + 2)) { + if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 2)) != MP_OKAY) { + return res; + } + } + + /* shift by as many digits in the bit count */ + if (b >= (int)DIGIT_BIT) { + if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) { + return res; + } + } + c->used = c->alloc; + + /* shift any bit count < DIGIT_BIT */ + d = (mp_digit) (b % DIGIT_BIT); + if (d != 0) { + register mp_digit *tmpc, mask, r, rr; + register int x; + + /* bitmask for carries */ + mask = (((mp_digit)1) << d) - 1; + + /* alias */ + tmpc = c->dp; + + /* carry */ + r = 0; + for (x = 0; x < c->used; x++) { + /* get the higher bits of the current word */ + rr = (*tmpc >> (DIGIT_BIT - d)) & mask; + + /* shift the current word and OR in the carry */ + *tmpc = ((*tmpc << d) | r) & MP_MASK; + ++tmpc; + + /* set the carry to the carry bits of the current word */ + r = rr; + } + } + mp_clamp (c); + return MP_OKAY; +} + +/* End: bn_mp_mul_2d.c */ + +/* Start: bn_mp_mul_d.c */ +#line 0 "bn_mp_mul_d.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* multiply by a digit */ +int +mp_mul_d (mp_int * a, mp_digit b, mp_int * c) +{ + int res, pa, olduse; + + /* make sure c is big enough to hold a*b */ + pa = a->used; + if (c->alloc < pa + 1) { + if ((res = mp_grow (c, pa + 1)) != MP_OKAY) { + return res; + } + } + + /* get the original destinations used count */ + olduse = c->used; + + /* set the new temporary used count */ + c->used = pa + 1; + + { + register mp_digit u, *tmpa, *tmpc; + register mp_word r; + register int ix; + + /* alias for a->dp [source] */ + tmpa = a->dp; + + /* alias for c->dp [dest] */ + tmpc = c->dp; + + /* zero carry */ + u = 0; + for (ix = 0; ix < pa; ix++) { + /* compute product and carry sum for this term */ + r = ((mp_word) u) + ((mp_word) * tmpa++) * ((mp_word) b); + + /* mask off higher bits to get a single digit */ + *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK)); + + /* send carry into next iteration */ + u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); + } + /* store final carry [if any] */ + *tmpc++ = u; + + /* now zero digits above the top */ + for (; pa < olduse; pa++) { + *tmpc++ = 0; + } + } + + mp_clamp (c); + return MP_OKAY; +} + +/* End: bn_mp_mul_d.c */ + +/* Start: bn_mp_mulmod.c */ +#line 0 "bn_mp_mulmod.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* d = a * b (mod c) */ +int +mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) +{ + int res; + mp_int t; + + + if ((res = mp_init (&t)) != MP_OKAY) { + return res; + } + + if ((res = mp_mul (a, b, &t)) != MP_OKAY) { + mp_clear (&t); + return res; + } + res = mp_mod (&t, c, d); + mp_clear (&t); + return res; +} + +/* End: bn_mp_mulmod.c */ + +/* Start: bn_mp_multi.c */ +#line 0 "bn_mp_multi.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include +#include + +int mp_init_multi(mp_int *mp, ...) +{ + mp_err res = MP_OKAY; /* Assume ok until proven otherwise */ + int n = 0; /* Number of ok inits */ + mp_int* cur_arg = mp; + va_list args; + + va_start(args, mp); /* init args to next argument from caller */ + while (cur_arg != NULL) { + if (mp_init(cur_arg) != MP_OKAY) { + /* Oops - error! Back-track and mp_clear what we already + succeeded in init-ing, then return error. + */ + va_list clean_args; + + /* end the current list */ + va_end(args); + + /* now start cleaning up */ + cur_arg = mp; + va_start(clean_args, mp); + while (n--) { + mp_clear(cur_arg); + cur_arg = va_arg(clean_args, mp_int*); + } + va_end(clean_args); + res = MP_MEM; + break; + } + n++; + cur_arg = va_arg(args, mp_int*); + } + va_end(args); + return res; /* Assumed ok, if error flagged above. */ +} + +void mp_clear_multi(mp_int *mp, ...) +{ + mp_int* next_mp = mp; + va_list args; + va_start(args, mp); + while (next_mp != NULL) { + mp_clear(next_mp); + next_mp = va_arg(args, mp_int*); + } + va_end(args); +} + +/* End: bn_mp_multi.c */ + +/* Start: bn_mp_n_root.c */ +#line 0 "bn_mp_n_root.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* find the n'th root of an integer + * + * Result found such that (c)^b <= a and (c+1)^b > a + * + * This algorithm uses Newton's approximation x[i+1] = x[i] - f(x[i])/f'(x[i]) + * which will find the root in log(N) time where each step involves a fair bit. This + * is not meant to find huge roots [square and cube at most]. + */ +int +mp_n_root (mp_int * a, mp_digit b, mp_int * c) +{ + mp_int t1, t2, t3; + int res, neg; + + /* input must be positive if b is even */ + if ((b & 1) == 0 && a->sign == MP_NEG) { + return MP_VAL; + } + + if ((res = mp_init (&t1)) != MP_OKAY) { + return res; + } + + if ((res = mp_init (&t2)) != MP_OKAY) { + goto __T1; + } + + if ((res = mp_init (&t3)) != MP_OKAY) { + goto __T2; + } + + /* if a is negative fudge the sign but keep track */ + neg = a->sign; + a->sign = MP_ZPOS; + + /* t2 = 2 */ + mp_set (&t2, 2); + + do { + /* t1 = t2 */ + if ((res = mp_copy (&t2, &t1)) != MP_OKAY) { + goto __T3; + } + + /* t2 = t1 - ((t1^b - a) / (b * t1^(b-1))) */ + if ((res = mp_expt_d (&t1, b - 1, &t3)) != MP_OKAY) { /* t3 = t1^(b-1) */ + goto __T3; + } + + /* numerator */ + if ((res = mp_mul (&t3, &t1, &t2)) != MP_OKAY) { /* t2 = t1^b */ + goto __T3; + } + + if ((res = mp_sub (&t2, a, &t2)) != MP_OKAY) { /* t2 = t1^b - a */ + goto __T3; + } + + if ((res = mp_mul_d (&t3, b, &t3)) != MP_OKAY) { /* t3 = t1^(b-1) * b */ + goto __T3; + } + + if ((res = mp_div (&t2, &t3, &t3, NULL)) != MP_OKAY) { /* t3 = (t1^b - a)/(b * t1^(b-1)) */ + goto __T3; + } + + if ((res = mp_sub (&t1, &t3, &t2)) != MP_OKAY) { + goto __T3; + } + } + while (mp_cmp (&t1, &t2) != MP_EQ); + + /* result can be off by a few so check */ + for (;;) { + if ((res = mp_expt_d (&t1, b, &t2)) != MP_OKAY) { + goto __T3; + } + + if (mp_cmp (&t2, a) == MP_GT) { + if ((res = mp_sub_d (&t1, 1, &t1)) != MP_OKAY) { + goto __T3; + } + } else { + break; + } + } + + /* reset the sign of a first */ + a->sign = neg; + + /* set the result */ + mp_exch (&t1, c); + + /* set the sign of the result */ + c->sign = neg; + + res = MP_OKAY; + +__T3:mp_clear (&t3); +__T2:mp_clear (&t2); +__T1:mp_clear (&t1); + return res; +} + +/* End: bn_mp_n_root.c */ + +/* Start: bn_mp_neg.c */ +#line 0 "bn_mp_neg.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* b = -a */ +int +mp_neg (mp_int * a, mp_int * b) +{ + int res; + if ((res = mp_copy (a, b)) != MP_OKAY) { + return res; + } + b->sign = (a->sign == MP_ZPOS) ? MP_NEG : MP_ZPOS; + return MP_OKAY; +} + +/* End: bn_mp_neg.c */ + +/* Start: bn_mp_or.c */ +#line 0 "bn_mp_or.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* OR two ints together */ +int +mp_or (mp_int * a, mp_int * b, mp_int * c) +{ + int res, ix, px; + mp_int t, *x; + + if (a->used > b->used) { + if ((res = mp_init_copy (&t, a)) != MP_OKAY) { + return res; + } + px = b->used; + x = b; + } else { + if ((res = mp_init_copy (&t, b)) != MP_OKAY) { + return res; + } + px = a->used; + x = a; + } + + for (ix = 0; ix < px; ix++) { + t.dp[ix] |= x->dp[ix]; + } + mp_clamp (&t); + mp_exch (c, &t); + mp_clear (&t); + return MP_OKAY; +} + +/* End: bn_mp_or.c */ + +/* Start: bn_mp_prime_fermat.c */ +#line 0 "bn_mp_prime_fermat.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* performs one Fermat test. + * + * If "a" were prime then b^a == b (mod a) since the order of + * the multiplicative sub-group would be phi(a) = a-1. That means + * it would be the same as b^(a mod (a-1)) == b^1 == b (mod a). + * + * Sets result to 1 if the congruence holds, or zero otherwise. + */ +int +mp_prime_fermat (mp_int * a, mp_int * b, int *result) +{ + mp_int t; + int err; + + /* default to fail */ + *result = 0; + + /* init t */ + if ((err = mp_init (&t)) != MP_OKAY) { + return err; + } + + /* compute t = b^a mod a */ + if ((err = mp_exptmod (b, a, a, &t)) != MP_OKAY) { + goto __T; + } + + /* is it equal to b? */ + if (mp_cmp (&t, b) == MP_EQ) { + *result = 1; + } + + err = MP_OKAY; +__T:mp_clear (&t); + return err; +} + +/* End: bn_mp_prime_fermat.c */ + +/* Start: bn_mp_prime_is_divisible.c */ +#line 0 "bn_mp_prime_is_divisible.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* determines if an integers is divisible by one of the first 256 primes or not + * + * sets result to 0 if not, 1 if yes + */ +int +mp_prime_is_divisible (mp_int * a, int *result) +{ + int err, ix; + mp_digit res; + + /* default to not */ + *result = 0; + + for (ix = 0; ix < PRIME_SIZE; ix++) { + /* is it equal to the prime? */ + if (mp_cmp_d (a, __prime_tab[ix]) == MP_EQ) { + *result = 1; + return MP_OKAY; + } + + /* what is a mod __prime_tab[ix] */ + if ((err = mp_mod_d (a, __prime_tab[ix], &res)) != MP_OKAY) { + return err; + } + + /* is the residue zero? */ + if (res == 0) { + *result = 1; + return MP_OKAY; + } + } + + return MP_OKAY; +} + +/* End: bn_mp_prime_is_divisible.c */ + +/* Start: bn_mp_prime_is_prime.c */ +#line 0 "bn_mp_prime_is_prime.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* performs a variable number of rounds of Miller-Rabin + * + * Probability of error after t rounds is no more than + * (1/4)^t when 1 <= t <= 256 + * + * Sets result to 1 if probably prime, 0 otherwise + */ +int +mp_prime_is_prime (mp_int * a, int t, int *result) +{ + mp_int b; + int ix, err, res; + + /* default to no */ + *result = 0; + + /* valid value of t? */ + if (t < 1 || t > PRIME_SIZE) { + return MP_VAL; + } + + /* is the input equal to one of the primes in the table? */ + for (ix = 0; ix < PRIME_SIZE; ix++) { + if (mp_cmp_d(a, __prime_tab[ix]) == MP_EQ) { + *result = 1; + return MP_OKAY; + } + } + + /* first perform trial division */ + if ((err = mp_prime_is_divisible (a, &res)) != MP_OKAY) { + return err; + } + if (res == 1) { + return MP_OKAY; + } + + /* now perform the miller-rabin rounds */ + if ((err = mp_init (&b)) != MP_OKAY) { + return err; + } + + for (ix = 0; ix < t; ix++) { + /* set the prime */ + mp_set (&b, __prime_tab[ix]); + + if ((err = mp_prime_miller_rabin (a, &b, &res)) != MP_OKAY) { + goto __B; + } + + if (res == 0) { + goto __B; + } + } + + /* passed the test */ + *result = 1; +__B:mp_clear (&b); + return err; +} + +/* End: bn_mp_prime_is_prime.c */ + +/* Start: bn_mp_prime_miller_rabin.c */ +#line 0 "bn_mp_prime_miller_rabin.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* Miller-Rabin test of "a" to the base of "b" as described in + * HAC pp. 139 Algorithm 4.24 + * + * Sets result to 0 if definitely composite or 1 if probably prime. + * Randomly the chance of error is no more than 1/4 and often + * very much lower. + */ +int +mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result) +{ + mp_int n1, y, r; + int s, j, err; + + /* default */ + *result = 0; + + /* get n1 = a - 1 */ + if ((err = mp_init_copy (&n1, a)) != MP_OKAY) { + return err; + } + if ((err = mp_sub_d (&n1, 1, &n1)) != MP_OKAY) { + goto __N1; + } + + /* set 2^s * r = n1 */ + if ((err = mp_init_copy (&r, &n1)) != MP_OKAY) { + goto __N1; + } + s = 0; + while (mp_iseven (&r) == 1) { + ++s; + if ((err = mp_div_2 (&r, &r)) != MP_OKAY) { + goto __R; + } + } + + /* compute y = b^r mod a */ + if ((err = mp_init (&y)) != MP_OKAY) { + goto __R; + } + if ((err = mp_exptmod (b, &r, a, &y)) != MP_OKAY) { + goto __Y; + } + + /* if y != 1 and y != n1 do */ + if (mp_cmp_d (&y, 1) != MP_EQ && mp_cmp (&y, &n1) != MP_EQ) { + j = 1; + /* while j <= s-1 and y != n1 */ + while ((j <= (s - 1)) && mp_cmp (&y, &n1) != MP_EQ) { + if ((err = mp_sqrmod (&y, a, &y)) != MP_OKAY) { + goto __Y; + } + + /* if y == 1 then composite */ + if (mp_cmp_d (&y, 1) == MP_EQ) { + goto __Y; + } + + ++j; + } + + /* if y != n1 then composite */ + if (mp_cmp (&y, &n1) != MP_EQ) { + goto __Y; + } + } + + /* probably prime now */ + *result = 1; +__Y:mp_clear (&y); +__R:mp_clear (&r); +__N1:mp_clear (&n1); + return err; +} + +/* End: bn_mp_prime_miller_rabin.c */ + +/* Start: bn_mp_prime_next_prime.c */ +#line 0 "bn_mp_prime_next_prime.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* finds the next prime after the number "a" using "t" trials + * of Miller-Rabin. + */ +int mp_prime_next_prime(mp_int *a, int t) +{ + int err, res; + + if (mp_iseven(a) == 1) { + /* force odd */ + if ((err = mp_add_d(a, 1, a)) != MP_OKAY) { + return err; + } + } else { + /* force to next odd number */ + if ((err = mp_add_d(a, 2, a)) != MP_OKAY) { + return err; + } + } + + for (;;) { + /* is this prime? */ + if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { + return err; + } + + if (res == 1) { + break; + } + + /* add two, next candidate */ + if ((err = mp_add_d(a, 2, a)) != MP_OKAY) { + return err; + } + } + + return MP_OKAY; +} + + +/* End: bn_mp_prime_next_prime.c */ + +/* Start: bn_mp_rand.c */ +#line 0 "bn_mp_rand.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* makes a pseudo-random int of a given size */ +int +mp_rand (mp_int * a, int digits) +{ + int res; + mp_digit d; + + mp_zero (a); + if (digits <= 0) { + return MP_OKAY; + } + + /* first place a random non-zero digit */ + do { + d = ((mp_digit) abs (rand ())); + } while (d == 0); + + if ((res = mp_add_d (a, d, a)) != MP_OKAY) { + return res; + } + + while (digits-- > 0) { + if ((res = mp_lshd (a, 1)) != MP_OKAY) { + return res; + } + + if ((res = mp_add_d (a, ((mp_digit) abs (rand ())), a)) != MP_OKAY) { + return res; + } + } + + return MP_OKAY; +} + +/* End: bn_mp_rand.c */ + +/* Start: bn_mp_read_signed_bin.c */ +#line 0 "bn_mp_read_signed_bin.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* read signed bin, big endian, first byte is 0==positive or 1==negative */ +int +mp_read_signed_bin (mp_int * a, unsigned char *b, int c) +{ + int res; + + if ((res = mp_read_unsigned_bin (a, b + 1, c - 1)) != MP_OKAY) { + return res; + } + a->sign = ((b[0] == (unsigned char) 0) ? MP_ZPOS : MP_NEG); + return MP_OKAY; +} + +/* End: bn_mp_read_signed_bin.c */ + +/* Start: bn_mp_read_unsigned_bin.c */ +#line 0 "bn_mp_read_unsigned_bin.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* reads a unsigned char array, assumes the msb is stored first [big endian] */ +int +mp_read_unsigned_bin (mp_int * a, unsigned char *b, int c) +{ + int res; + mp_zero (a); + while (c-- > 0) { + if ((res = mp_mul_2d (a, 8, a)) != MP_OKAY) { + return res; + } + + if (DIGIT_BIT != 7) { + a->dp[0] |= *b++; + a->used += 1; + } else { + a->dp[0] = (*b & MP_MASK); + a->dp[1] |= ((*b++ >> 7U) & 1); + a->used += 2; + } + } + mp_clamp (a); + return MP_OKAY; +} + +/* End: bn_mp_read_unsigned_bin.c */ + +/* Start: bn_mp_reduce.c */ +#line 0 "bn_mp_reduce.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* reduces x mod m, assumes 0 < x < m**2, mu is + * precomputed via mp_reduce_setup. + * From HAC pp.604 Algorithm 14.42 + */ +int +mp_reduce (mp_int * x, mp_int * m, mp_int * mu) +{ + mp_int q; + int res, um = m->used; + + /* q = x */ + if ((res = mp_init_copy (&q, x)) != MP_OKAY) { + return res; + } + + /* q1 = x / b**(k-1) */ + mp_rshd (&q, um - 1); + + /* according to HAC this is optimization is ok */ + if (((unsigned long) m->used) > (((mp_digit)1) << (DIGIT_BIT - 1))) { + if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) { + goto CLEANUP; + } + } else { + if ((res = s_mp_mul_high_digs (&q, mu, &q, um - 1)) != MP_OKAY) { + goto CLEANUP; + } + } + + /* q3 = q2 / b**(k+1) */ + mp_rshd (&q, um + 1); + + /* x = x mod b**(k+1), quick (no division) */ + if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) { + goto CLEANUP; + } + + /* q = q * m mod b**(k+1), quick (no division) */ + if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) { + goto CLEANUP; + } + + /* x = x - q */ + if ((res = mp_sub (x, &q, x)) != MP_OKAY) { + goto CLEANUP; + } + + /* If x < 0, add b**(k+1) to it */ + if (mp_cmp_d (x, 0) == MP_LT) { + mp_set (&q, 1); + if ((res = mp_lshd (&q, um + 1)) != MP_OKAY) + goto CLEANUP; + if ((res = mp_add (x, &q, x)) != MP_OKAY) + goto CLEANUP; + } + + /* Back off if it's too big */ + while (mp_cmp (x, m) != MP_LT) { + if ((res = s_mp_sub (x, m, x)) != MP_OKAY) { + break; + } + } + +CLEANUP: + mp_clear (&q); + + return res; +} + +/* End: bn_mp_reduce.c */ + +/* Start: bn_mp_reduce_2k.c */ +#line 0 "bn_mp_reduce_2k.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* reduces a modulo n where n is of the form 2**p - k */ +int +mp_reduce_2k(mp_int *a, mp_int *n, mp_digit k) +{ + mp_int q; + int p, res; + + if ((res = mp_init(&q)) != MP_OKAY) { + return res; + } + + p = mp_count_bits(n); +top: + /* q = a/2**p, a = a mod 2**p */ + if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) { + goto ERR; + } + + if (k != 1) { + /* q = q * k */ + if ((res = mp_mul_d(&q, k, &q)) != MP_OKAY) { + goto ERR; + } + } + + /* a = a + q */ + if ((res = s_mp_add(a, &q, a)) != MP_OKAY) { + goto ERR; + } + + if (mp_cmp_mag(a, n) != MP_LT) { + s_mp_sub(a, n, a); + goto top; + } + +ERR: + mp_clear(&q); + return res; +} + + +/* End: bn_mp_reduce_2k.c */ + +/* Start: bn_mp_reduce_2k_setup.c */ +#line 0 "bn_mp_reduce_2k_setup.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* determines the setup value */ +int +mp_reduce_2k_setup(mp_int *a, mp_digit *d) +{ + int res, p; + mp_int tmp; + + if ((res = mp_init(&tmp)) != MP_OKAY) { + return res; + } + + p = mp_count_bits(a); + if ((res = mp_2expt(&tmp, p)) != MP_OKAY) { + mp_clear(&tmp); + return res; + } + + if ((res = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) { + mp_clear(&tmp); + return res; + } + + *d = tmp.dp[0]; + mp_clear(&tmp); + return MP_OKAY; +} + +/* End: bn_mp_reduce_2k_setup.c */ + +/* Start: bn_mp_reduce_is_2k.c */ +#line 0 "bn_mp_reduce_is_2k.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* determines if mp_reduce_2k can be used */ +int +mp_reduce_is_2k(mp_int *a) +{ + int ix, iy; + + if (a->used == 0) { + return 0; + } else if (a->used == 1) { + return 1; + } else if (a->used > 1) { + iy = mp_count_bits(a); + for (ix = DIGIT_BIT; ix < iy; ix++) { + if ((a->dp[ix/DIGIT_BIT] & ((mp_digit)1 << (mp_digit)(ix % DIGIT_BIT))) == 0) { + return 0; + } + } + } + return 1; +} + + +/* End: bn_mp_reduce_is_2k.c */ + +/* Start: bn_mp_reduce_setup.c */ +#line 0 "bn_mp_reduce_setup.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* pre-calculate the value required for Barrett reduction + * For a given modulus "b" it calulates the value required in "a" + */ +int +mp_reduce_setup (mp_int * a, mp_int * b) +{ + int res; + + if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) { + return res; + } + return mp_div (a, b, a, NULL); +} + +/* End: bn_mp_reduce_setup.c */ + +/* Start: bn_mp_rshd.c */ +#line 0 "bn_mp_rshd.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* shift right a certain amount of digits */ +void +mp_rshd (mp_int * a, int b) +{ + int x; + + /* if b <= 0 then ignore it */ + if (b <= 0) { + return; + } + + /* if b > used then simply zero it and return */ + if (a->used <= b) { + mp_zero (a); + return; + } + + { + register mp_digit *bottom, *top; + + /* shift the digits down */ + + /* bottom */ + bottom = a->dp; + + /* top [offset into digits] */ + top = a->dp + b; + + /* this is implemented as a sliding window where + * the window is b-digits long and digits from + * the top of the window are copied to the bottom + * + * e.g. + + b-2 | b-1 | b0 | b1 | b2 | ... | bb | ----> + /\ | ----> + \-------------------/ ----> + */ + for (x = 0; x < (a->used - b); x++) { + *bottom++ = *top++; + } + + /* zero the top digits */ + for (; x < a->used; x++) { + *bottom++ = 0; + } + } + + /* remove excess digits */ + a->used -= b; +} + +/* End: bn_mp_rshd.c */ + +/* Start: bn_mp_set.c */ +#line 0 "bn_mp_set.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* set to a digit */ +void +mp_set (mp_int * a, mp_digit b) +{ + mp_zero (a); + a->dp[0] = b & MP_MASK; + a->used = (a->dp[0] != 0) ? 1 : 0; +} + +/* End: bn_mp_set.c */ + +/* Start: bn_mp_set_int.c */ +#line 0 "bn_mp_set_int.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* set a 32-bit const */ +int +mp_set_int (mp_int * a, unsigned int b) +{ + int x, res; + + mp_zero (a); + /* set four bits at a time */ + for (x = 0; x < 8; x++) { + /* shift the number up four bits */ + if ((res = mp_mul_2d (a, 4, a)) != MP_OKAY) { + return res; + } + + /* OR in the top four bits of the source */ + a->dp[0] |= (b >> 28) & 15; + + /* shift the source up to the next four bits */ + b <<= 4; + + /* ensure that digits are not clamped off */ + a->used += 1; + } + mp_clamp (a); + return MP_OKAY; +} + +/* End: bn_mp_set_int.c */ + +/* Start: bn_mp_shrink.c */ +#line 0 "bn_mp_shrink.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* shrink a bignum */ +int +mp_shrink (mp_int * a) +{ + if (a->alloc != a->used) { + if ((a->dp = OPT_CAST realloc (a->dp, sizeof (mp_digit) * a->used)) == NULL) { + return MP_MEM; + } + a->alloc = a->used; + } + return MP_OKAY; +} + +/* End: bn_mp_shrink.c */ + +/* Start: bn_mp_signed_bin_size.c */ +#line 0 "bn_mp_signed_bin_size.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* get the size for an signed equivalent */ +int +mp_signed_bin_size (mp_int * a) +{ + return 1 + mp_unsigned_bin_size (a); +} + +/* End: bn_mp_signed_bin_size.c */ + +/* Start: bn_mp_sqr.c */ +#line 0 "bn_mp_sqr.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* computes b = a*a */ +int +mp_sqr (mp_int * a, mp_int * b) +{ + int res; + if (a->used >= TOOM_SQR_CUTOFF) { + res = mp_toom_sqr(a, b); + } else if (a->used >= KARATSUBA_SQR_CUTOFF) { + res = mp_karatsuba_sqr (a, b); + } else { + + /* can we use the fast multiplier? */ + if ((a->used * 2 + 1) < MP_WARRAY && + a->used < + (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) { + res = fast_s_mp_sqr (a, b); + } else { + res = s_mp_sqr (a, b); + } + } + b->sign = MP_ZPOS; + return res; +} + +/* End: bn_mp_sqr.c */ + +/* Start: bn_mp_sqrmod.c */ +#line 0 "bn_mp_sqrmod.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* c = a * a (mod b) */ +int +mp_sqrmod (mp_int * a, mp_int * b, mp_int * c) +{ + int res; + mp_int t; + + + if ((res = mp_init (&t)) != MP_OKAY) { + return res; + } + + if ((res = mp_sqr (a, &t)) != MP_OKAY) { + mp_clear (&t); + return res; + } + res = mp_mod (&t, b, c); + mp_clear (&t); + return res; +} + +/* End: bn_mp_sqrmod.c */ + +/* Start: bn_mp_sub.c */ +#line 0 "bn_mp_sub.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* high level subtraction (handles signs) */ +int +mp_sub (mp_int * a, mp_int * b, mp_int * c) +{ + int sa, sb, res; + + sa = a->sign; + sb = b->sign; + + if (sa != sb) { + /* subtract a negative from a positive, OR */ + /* subtract a positive from a negative. */ + /* In either case, ADD their magnitudes, */ + /* and use the sign of the first number. */ + c->sign = sa; + res = s_mp_add (a, b, c); + } else { + /* subtract a positive from a positive, OR */ + /* subtract a negative from a negative. */ + /* First, take the difference between their */ + /* magnitudes, then... */ + if (mp_cmp_mag (a, b) != MP_LT) { + /* Copy the sign from the first */ + c->sign = sa; + /* The first has a larger or equal magnitude */ + res = s_mp_sub (a, b, c); + } else { + /* The result has the *opposite* sign from */ + /* the first number. */ + c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS; + /* The second has a larger magnitude */ + res = s_mp_sub (b, a, c); + } + } + return res; +} + + +/* End: bn_mp_sub.c */ + +/* Start: bn_mp_sub_d.c */ +#line 0 "bn_mp_sub_d.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* single digit subtraction */ +int +mp_sub_d (mp_int * a, mp_digit b, mp_int * c) +{ + mp_int t; + int res; + + + if ((res = mp_init (&t)) != MP_OKAY) { + return res; + } + mp_set (&t, b); + res = mp_sub (a, &t, c); + + mp_clear (&t); + return res; +} + +/* End: bn_mp_sub_d.c */ + +/* Start: bn_mp_submod.c */ +#line 0 "bn_mp_submod.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* d = a - b (mod c) */ +int +mp_submod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) +{ + int res; + mp_int t; + + + if ((res = mp_init (&t)) != MP_OKAY) { + return res; + } + + if ((res = mp_sub (a, b, &t)) != MP_OKAY) { + mp_clear (&t); + return res; + } + res = mp_mod (&t, c, d); + mp_clear (&t); + return res; +} + +/* End: bn_mp_submod.c */ + +/* Start: bn_mp_to_signed_bin.c */ +#line 0 "bn_mp_to_signed_bin.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* store in signed [big endian] format */ +int +mp_to_signed_bin (mp_int * a, unsigned char *b) +{ + int res; + + if ((res = mp_to_unsigned_bin (a, b + 1)) != MP_OKAY) { + return res; + } + b[0] = (unsigned char) ((a->sign == MP_ZPOS) ? 0 : 1); + return MP_OKAY; +} + +/* End: bn_mp_to_signed_bin.c */ + +/* Start: bn_mp_to_unsigned_bin.c */ +#line 0 "bn_mp_to_unsigned_bin.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* store in unsigned [big endian] format */ +int +mp_to_unsigned_bin (mp_int * a, unsigned char *b) +{ + int x, res; + mp_int t; + + if ((res = mp_init_copy (&t, a)) != MP_OKAY) { + return res; + } + + x = 0; + while (mp_iszero (&t) == 0) { + if (DIGIT_BIT != 7) { + b[x++] = (unsigned char) (t.dp[0] & 255); + } else { + b[x++] = (unsigned char) (t.dp[0] | ((t.dp[1] & 0x01) << 7)); + } + if ((res = mp_div_2d (&t, 8, &t, NULL)) != MP_OKAY) { + mp_clear (&t); + return res; + } + } + bn_reverse (b, x); + mp_clear (&t); + return MP_OKAY; +} + +/* End: bn_mp_to_unsigned_bin.c */ + +/* Start: bn_mp_toom_mul.c */ +#line 0 "bn_mp_toom_mul.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* multiplication using Toom-Cook 3-way algorithm */ +int +mp_toom_mul(mp_int *a, mp_int *b, mp_int *c) +{ + mp_int w0, w1, w2, w3, w4, tmp1, tmp2, a0, a1, a2, b0, b1, b2; + int res, B; + + /* init temps */ + if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &b0, &b1, &b2, &tmp1, &tmp2, NULL)) != MP_OKAY) { + return res; + } + + /* B */ + B = MIN(a->used, b->used) / 3; + + /* a = a2 * B^2 + a1 * B + a0 */ + if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_copy(a, &a1)) != MP_OKAY) { + goto ERR; + } + mp_rshd(&a1, B); + mp_mod_2d(&a1, DIGIT_BIT * B, &a1); + + if ((res = mp_copy(a, &a2)) != MP_OKAY) { + goto ERR; + } + mp_rshd(&a2, B*2); + + /* b = b2 * B^2 + b1 * B + b0 */ + if ((res = mp_mod_2d(b, DIGIT_BIT * B, &b0)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_copy(b, &b1)) != MP_OKAY) { + goto ERR; + } + mp_rshd(&b1, B); + mp_mod_2d(&b1, DIGIT_BIT * B, &b1); + + if ((res = mp_copy(b, &b2)) != MP_OKAY) { + goto ERR; + } + mp_rshd(&b2, B*2); + + /* w0 = a0*b0 */ + if ((res = mp_mul(&a0, &b0, &w0)) != MP_OKAY) { + goto ERR; + } + + /* w4 = a2 * b2 */ + if ((res = mp_mul(&a2, &b2, &w4)) != MP_OKAY) { + goto ERR; + } + + /* w1 = (a2 + 2(a1 + 2a0))(b2 + 2(b1 + 2b0)) */ + if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_mul_2(&b0, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp2, &b2, &tmp2)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_mul(&tmp1, &tmp2, &w1)) != MP_OKAY) { + goto ERR; + } + + /* w3 = (a0 + 2(a1 + 2a2))(b0 + 2(b1 + 2b2)) */ + if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_mul_2(&b2, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_mul(&tmp1, &tmp2, &w3)) != MP_OKAY) { + goto ERR; + } + + + /* w2 = (a2 + a1 + a0)(b2 + b1 + b0) */ + if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&b2, &b1, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul(&tmp1, &tmp2, &w2)) != MP_OKAY) { + goto ERR; + } + + /* now solve the matrix + + 0 0 0 0 1 + 1 2 4 8 16 + 1 1 1 1 1 + 16 8 4 2 1 + 1 0 0 0 0 + + using 12 subtractions, 4 shifts, 2 small divisions and 1 small multiplication + */ + + /* r1 - r4 */ + if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - r0 */ + if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) { + goto ERR; + } + /* r1/2 */ + if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3/2 */ + if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) { + goto ERR; + } + /* r2 - r0 - r4 */ + if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) { + goto ERR; + } + /* r1 - r2 */ + if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - r2 */ + if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { + goto ERR; + } + /* r1 - 8r0 */ + if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - 8r4 */ + if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) { + goto ERR; + } + /* 3r2 - r1 - r3 */ + if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) { + goto ERR; + } + /* r1 - r2 */ + if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - r2 */ + if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { + goto ERR; + } + /* r1/3 */ + if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) { + goto ERR; + } + /* r3/3 */ + if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) { + goto ERR; + } + + /* at this point shift W[n] by B*n */ + if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_add(&w0, &w1, c)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, c, c)) != MP_OKAY) { + goto ERR; + } + +ERR: + mp_clear_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &b0, &b1, &b2, &tmp1, &tmp2, NULL); + return res; +} + + +/* End: bn_mp_toom_mul.c */ + +/* Start: bn_mp_toom_sqr.c */ +#line 0 "bn_mp_toom_sqr.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* squaring using Toom-Cook 3-way algorithm */ +int +mp_toom_sqr(mp_int *a, mp_int *b) +{ + mp_int w0, w1, w2, w3, w4, tmp1, a0, a1, a2; + int res, B; + + /* init temps */ + if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL)) != MP_OKAY) { + return res; + } + + /* B */ + B = a->used / 3; + + /* a = a2 * B^2 + a1 * B + a0 */ + if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_copy(a, &a1)) != MP_OKAY) { + goto ERR; + } + mp_rshd(&a1, B); + mp_mod_2d(&a1, DIGIT_BIT * B, &a1); + + if ((res = mp_copy(a, &a2)) != MP_OKAY) { + goto ERR; + } + mp_rshd(&a2, B*2); + + /* w0 = a0*a0 */ + if ((res = mp_sqr(&a0, &w0)) != MP_OKAY) { + goto ERR; + } + + /* w4 = a2 * a2 */ + if ((res = mp_sqr(&a2, &w4)) != MP_OKAY) { + goto ERR; + } + + /* w1 = (a2 + 2(a1 + 2a0))**2 */ + if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_sqr(&tmp1, &w1)) != MP_OKAY) { + goto ERR; + } + + /* w3 = (a0 + 2(a1 + 2a2))**2 */ + if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_sqr(&tmp1, &w3)) != MP_OKAY) { + goto ERR; + } + + + /* w2 = (a2 + a1 + a0)**2 */ + if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sqr(&tmp1, &w2)) != MP_OKAY) { + goto ERR; + } + + /* now solve the matrix + + 0 0 0 0 1 + 1 2 4 8 16 + 1 1 1 1 1 + 16 8 4 2 1 + 1 0 0 0 0 + + using 12 subtractions, 4 shifts, 2 small divisions and 1 small multiplication. + */ + + /* r1 - r4 */ + if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - r0 */ + if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) { + goto ERR; + } + /* r1/2 */ + if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3/2 */ + if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) { + goto ERR; + } + /* r2 - r0 - r4 */ + if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) { + goto ERR; + } + /* r1 - r2 */ + if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - r2 */ + if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { + goto ERR; + } + /* r1 - 8r0 */ + if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - 8r4 */ + if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) { + goto ERR; + } + /* 3r2 - r1 - r3 */ + if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) { + goto ERR; + } + /* r1 - r2 */ + if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) { + goto ERR; + } + /* r3 - r2 */ + if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) { + goto ERR; + } + /* r1/3 */ + if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) { + goto ERR; + } + /* r3/3 */ + if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) { + goto ERR; + } + + /* at this point shift W[n] by B*n */ + if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) { + goto ERR; + } + + if ((res = mp_add(&w0, &w1, b)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) { + goto ERR; + } + if ((res = mp_add(&tmp1, b, b)) != MP_OKAY) { + goto ERR; + } + +ERR: + mp_clear_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL); + return res; +} + + +/* End: bn_mp_toom_sqr.c */ + +/* Start: bn_mp_unsigned_bin_size.c */ +#line 0 "bn_mp_unsigned_bin_size.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* get the size for an unsigned equivalent */ +int +mp_unsigned_bin_size (mp_int * a) +{ + int size = mp_count_bits (a); + return (size / 8 + ((size & 7) != 0 ? 1 : 0)); +} + +/* End: bn_mp_unsigned_bin_size.c */ + +/* Start: bn_mp_xor.c */ +#line 0 "bn_mp_xor.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* XOR two ints together */ +int +mp_xor (mp_int * a, mp_int * b, mp_int * c) +{ + int res, ix, px; + mp_int t, *x; + + if (a->used > b->used) { + if ((res = mp_init_copy (&t, a)) != MP_OKAY) { + return res; + } + px = b->used; + x = b; + } else { + if ((res = mp_init_copy (&t, b)) != MP_OKAY) { + return res; + } + px = a->used; + x = a; + } + + for (ix = 0; ix < px; ix++) { + t.dp[ix] ^= x->dp[ix]; + } + mp_clamp (&t); + mp_exch (c, &t); + mp_clear (&t); + return MP_OKAY; +} + +/* End: bn_mp_xor.c */ + +/* Start: bn_mp_zero.c */ +#line 0 "bn_mp_zero.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* set to zero */ +void +mp_zero (mp_int * a) +{ + a->sign = MP_ZPOS; + a->used = 0; + memset (a->dp, 0, sizeof (mp_digit) * a->alloc); +} + +/* End: bn_mp_zero.c */ + +/* Start: bn_prime_tab.c */ +#line 0 "bn_prime_tab.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include +const mp_digit __prime_tab[] = { + 0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013, + 0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035, + 0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059, + 0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F, +#ifndef MP_8BIT + 0x0083, + 0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD, + 0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF, + 0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107, + 0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137, + + 0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167, + 0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199, + 0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9, + 0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7, + 0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239, + 0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265, + 0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293, + 0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF, + + 0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301, + 0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B, + 0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371, + 0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD, + 0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5, + 0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419, + 0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449, + 0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B, + + 0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7, + 0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503, + 0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529, + 0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F, + 0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3, + 0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7, + 0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623, + 0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653 +#endif +}; + +/* End: bn_prime_tab.c */ + +/* Start: bn_radix.c */ +#line 0 "bn_radix.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* chars used in radix conversions */ +static const char *s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; + +/* read a string [ASCII] in a given radix */ +int +mp_read_radix (mp_int * a, char *str, int radix) +{ + int y, res, neg; + char ch; + + if (radix < 2 || radix > 64) { + return MP_VAL; + } + + if (*str == '-') { + ++str; + neg = MP_NEG; + } else { + neg = MP_ZPOS; + } + + mp_zero (a); + while (*str) { + ch = (char) ((radix < 36) ? toupper (*str) : *str); + for (y = 0; y < 64; y++) { + if (ch == s_rmap[y]) { + break; + } + } + + if (y < radix) { + if ((res = mp_mul_d (a, (mp_digit) radix, a)) != MP_OKAY) { + return res; + } + if ((res = mp_add_d (a, (mp_digit) y, a)) != MP_OKAY) { + return res; + } + } else { + break; + } + ++str; + } + a->sign = neg; + return MP_OKAY; +} + +/* stores a bignum as a ASCII string in a given radix (2..64) */ +int +mp_toradix (mp_int * a, char *str, int radix) +{ + int res, digs; + mp_int t; + mp_digit d; + char *_s = str; + + if (radix < 2 || radix > 64) { + return MP_VAL; + } + + if ((res = mp_init_copy (&t, a)) != MP_OKAY) { + return res; + } + + if (t.sign == MP_NEG) { + ++_s; + *str++ = '-'; + t.sign = MP_ZPOS; + } + + digs = 0; + while (mp_iszero (&t) == 0) { + if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { + mp_clear (&t); + return res; + } + *str++ = s_rmap[d]; + ++digs; + } + bn_reverse ((unsigned char *)_s, digs); + *str++ = '\0'; + mp_clear (&t); + return MP_OKAY; +} + +/* returns size of ASCII reprensentation */ +int +mp_radix_size (mp_int * a, int radix) +{ + int res, digs; + mp_int t; + mp_digit d; + + /* special case for binary */ + if (radix == 2) { + return mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1; + } + + if (radix < 2 || radix > 64) { + return 0; + } + + if ((res = mp_init_copy (&t, a)) != MP_OKAY) { + return 0; + } + + digs = 0; + if (t.sign == MP_NEG) { + ++digs; + t.sign = MP_ZPOS; + } + + while (mp_iszero (&t) == 0) { + if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { + mp_clear (&t); + return 0; + } + ++digs; + } + mp_clear (&t); + return digs + 1; +} + +/* read a bigint from a file stream in ASCII */ +int mp_fread(mp_int *a, int radix, FILE *stream) +{ + int err, ch, neg, y; + + /* clear a */ + mp_zero(a); + + /* if first digit is - then set negative */ + ch = fgetc(stream); + if (ch == '-') { + neg = MP_NEG; + ch = fgetc(stream); + } else { + neg = MP_ZPOS; + } + + for (;;) { + /* find y in the radix map */ + for (y = 0; y < radix; y++) { + if (s_rmap[y] == ch) { + break; + } + } + if (y == radix) { + break; + } + + /* shift up and add */ + if ((err = mp_mul_d(a, radix, a)) != MP_OKAY) { + return err; + } + if ((err = mp_add_d(a, y, a)) != MP_OKAY) { + return err; + } + + ch = fgetc(stream); + } + if (mp_cmp_d(a, 0) != MP_EQ) { + a->sign = neg; + } + + return MP_OKAY; +} + +int mp_fwrite(mp_int *a, int radix, FILE *stream) +{ + char *buf; + int err, len, x; + + len = mp_radix_size(a, radix); + if (len == 0) { + return MP_VAL; + } + + buf = malloc(len); + if (buf == NULL) { + return MP_MEM; + } + + if ((err = mp_toradix(a, buf, radix)) != MP_OKAY) { + free(buf); + return err; + } + + for (x = 0; x < len; x++) { + if (fputc(buf[x], stream) == EOF) { + free(buf); + return MP_VAL; + } + } + + free(buf); + return MP_OKAY; +} + + +/* End: bn_radix.c */ + +/* Start: bn_reverse.c */ +#line 0 "bn_reverse.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* reverse an array, used for radix code */ +void +bn_reverse (unsigned char *s, int len) +{ + int ix, iy; + unsigned char t; + + ix = 0; + iy = len - 1; + while (ix < iy) { + t = s[ix]; + s[ix] = s[iy]; + s[iy] = t; + ++ix; + --iy; + } +} + +/* End: bn_reverse.c */ + +/* Start: bn_s_mp_add.c */ +#line 0 "bn_s_mp_add.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* low level addition, based on HAC pp.594, Algorithm 14.7 */ +int +s_mp_add (mp_int * a, mp_int * b, mp_int * c) +{ + mp_int *x; + int olduse, res, min, max; + + /* find sizes, we let |a| <= |b| which means we have to sort + * them. "x" will point to the input with the most digits + */ + if (a->used > b->used) { + min = b->used; + max = a->used; + x = a; + } else { + min = a->used; + max = b->used; + x = b; + } + + /* init result */ + if (c->alloc < max + 1) { + if ((res = mp_grow (c, max + 1)) != MP_OKAY) { + return res; + } + } + + /* get old used digit count and set new one */ + olduse = c->used; + c->used = max + 1; + + { + register mp_digit u, *tmpa, *tmpb, *tmpc; + register int i; + + /* alias for digit pointers */ + + /* first input */ + tmpa = a->dp; + + /* second input */ + tmpb = b->dp; + + /* destination */ + tmpc = c->dp; + + /* zero the carry */ + u = 0; + for (i = 0; i < min; i++) { + /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */ + *tmpc = *tmpa++ + *tmpb++ + u; + + /* U = carry bit of T[i] */ + u = *tmpc >> ((mp_digit)DIGIT_BIT); + + /* take away carry bit from T[i] */ + *tmpc++ &= MP_MASK; + } + + /* now copy higher words if any, that is in A+B + * if A or B has more digits add those in + */ + if (min != max) { + for (; i < max; i++) { + /* T[i] = X[i] + U */ + *tmpc = x->dp[i] + u; + + /* U = carry bit of T[i] */ + u = *tmpc >> ((mp_digit)DIGIT_BIT); + + /* take away carry bit from T[i] */ + *tmpc++ &= MP_MASK; + } + } + + /* add carry */ + *tmpc++ = u; + + /* clear digits above oldused */ + for (i = c->used; i < olduse; i++) { + *tmpc++ = 0; + } + } + + mp_clamp (c); + return MP_OKAY; +} + +/* End: bn_s_mp_add.c */ + +/* Start: bn_s_mp_exptmod.c */ +#line 0 "bn_s_mp_exptmod.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +int +s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) +{ + mp_int M[256], res, mu; + mp_digit buf; + int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; + + /* find window size */ + x = mp_count_bits (X); + if (x <= 7) { + winsize = 2; + } else if (x <= 36) { + winsize = 3; + } else if (x <= 140) { + winsize = 4; + } else if (x <= 450) { + winsize = 5; + } else if (x <= 1303) { + winsize = 6; + } else if (x <= 3529) { + winsize = 7; + } else { + winsize = 8; + } + +#ifdef MP_LOW_MEM + if (winsize > 5) { + winsize = 5; + } +#endif + + /* init M array */ + for (x = 0; x < (1 << winsize); x++) { + if ((err = mp_init_size (&M[x], 1)) != MP_OKAY) { + for (y = 0; y < x; y++) { + mp_clear (&M[y]); + } + return err; + } + } + + /* create mu, used for Barrett reduction */ + if ((err = mp_init (&mu)) != MP_OKAY) { + goto __M; + } + if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) { + goto __MU; + } + + /* create M table + * + * The M table contains powers of the input base, e.g. M[x] = G**x mod P + * + * The first half of the table is not computed though accept for M[0] and M[1] + */ + if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) { + goto __MU; + } + + /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */ + if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) { + goto __MU; + } + + for (x = 0; x < (winsize - 1); x++) { + if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) { + goto __MU; + } + if ((err = mp_reduce (&M[1 << (winsize - 1)], P, &mu)) != MP_OKAY) { + goto __MU; + } + } + + /* create upper table */ + for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { + if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) { + goto __MU; + } + if ((err = mp_reduce (&M[x], P, &mu)) != MP_OKAY) { + goto __MU; + } + } + + /* setup result */ + if ((err = mp_init (&res)) != MP_OKAY) { + goto __MU; + } + mp_set (&res, 1); + + /* set initial mode and bit cnt */ + mode = 0; + bitcnt = 1; + buf = 0; + digidx = X->used - 1; + bitcpy = 0; + bitbuf = 0; + + for (;;) { + /* grab next digit as required */ + if (--bitcnt == 0) { + if (digidx == -1) { + break; + } + buf = X->dp[digidx--]; + bitcnt = (int) DIGIT_BIT; + } + + /* grab the next msb from the exponent */ + y = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1; + buf <<= (mp_digit)1; + + /* if the bit is zero and mode == 0 then we ignore it + * These represent the leading zero bits before the first 1 bit + * in the exponent. Technically this opt is not required but it + * does lower the # of trivial squaring/reductions used + */ + if (mode == 0 && y == 0) + continue; + + /* if the bit is zero and mode == 1 then we square */ + if (mode == 1 && y == 0) { + if ((err = mp_sqr (&res, &res)) != MP_OKAY) { + goto __RES; + } + if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) { + goto __RES; + } + continue; + } + + /* else we add it to the window */ + bitbuf |= (y << (winsize - ++bitcpy)); + mode = 2; + + if (bitcpy == winsize) { + /* ok window is filled so square as required and multiply */ + /* square first */ + for (x = 0; x < winsize; x++) { + if ((err = mp_sqr (&res, &res)) != MP_OKAY) { + goto __RES; + } + if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) { + goto __RES; + } + } + + /* then multiply */ + if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) { + goto __MU; + } + if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) { + goto __MU; + } + + /* empty window and reset */ + bitcpy = 0; + bitbuf = 0; + mode = 1; + } + } + + /* if bits remain then square/multiply */ + if (mode == 2 && bitcpy > 0) { + /* square then multiply if the bit is set */ + for (x = 0; x < bitcpy; x++) { + if ((err = mp_sqr (&res, &res)) != MP_OKAY) { + goto __RES; + } + if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) { + goto __RES; + } + + bitbuf <<= 1; + if ((bitbuf & (1 << winsize)) != 0) { + /* then multiply */ + if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) { + goto __RES; + } + if ((err = mp_reduce (&res, P, &mu)) != MP_OKAY) { + goto __RES; + } + } + } + } + + mp_exch (&res, Y); + err = MP_OKAY; +__RES:mp_clear (&res); +__MU:mp_clear (&mu); +__M: + for (x = 0; x < (1 << winsize); x++) { + mp_clear (&M[x]); + } + return err; +} + +/* End: bn_s_mp_exptmod.c */ + +/* Start: bn_s_mp_mul_digs.c */ +#line 0 "bn_s_mp_mul_digs.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* multiplies |a| * |b| and only computes upto digs digits of result + * HAC pp. 595, Algorithm 14.12 Modified so you can control how + * many digits of output are created. + */ +int +s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) +{ + mp_int t; + int res, pa, pb, ix, iy; + mp_digit u; + mp_word r; + mp_digit tmpx, *tmpt, *tmpy; + + /* can we use the fast multiplier? */ + if (((digs) < MP_WARRAY) && + MIN (a->used, b->used) < + (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + return fast_s_mp_mul_digs (a, b, c, digs); + } + + if ((res = mp_init_size (&t, digs)) != MP_OKAY) { + return res; + } + t.used = digs; + + /* compute the digits of the product directly */ + pa = a->used; + for (ix = 0; ix < pa; ix++) { + /* set the carry to zero */ + u = 0; + + /* limit ourselves to making digs digits of output */ + pb = MIN (b->used, digs - ix); + + /* setup some aliases */ + /* copy of the digit from a used within the nested loop */ + tmpx = a->dp[ix]; + + /* an alias for the destination shifted ix places */ + tmpt = t.dp + ix; + + /* an alias for the digits of b */ + tmpy = b->dp; + + /* compute the columns of the output and propagate the carry */ + for (iy = 0; iy < pb; iy++) { + /* compute the column as a mp_word */ + r = ((mp_word) *tmpt) + + ((mp_word) tmpx) * ((mp_word) * tmpy++) + + ((mp_word) u); + + /* the new column is the lower part of the result */ + *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); + + /* get the carry word from the result */ + u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); + } + /* set carry if it is placed below digs */ + if (ix + iy < digs) { + *tmpt = u; + } + } + + mp_clamp (&t); + mp_exch (&t, c); + + mp_clear (&t); + return MP_OKAY; +} + +/* End: bn_s_mp_mul_digs.c */ + +/* Start: bn_s_mp_mul_high_digs.c */ +#line 0 "bn_s_mp_mul_high_digs.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* multiplies |a| * |b| and does not compute the lower digs digits + * [meant to get the higher part of the product] + */ +int +s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) +{ + mp_int t; + int res, pa, pb, ix, iy; + mp_digit u; + mp_word r; + mp_digit tmpx, *tmpt, *tmpy; + + + /* can we use the fast multiplier? */ + if (((a->used + b->used + 1) < MP_WARRAY) + && MIN (a->used, b->used) < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + return fast_s_mp_mul_high_digs (a, b, c, digs); + } + + if ((res = mp_init_size (&t, a->used + b->used + 1)) != MP_OKAY) { + return res; + } + t.used = a->used + b->used + 1; + + pa = a->used; + pb = b->used; + for (ix = 0; ix < pa; ix++) { + /* clear the carry */ + u = 0; + + /* left hand side of A[ix] * B[iy] */ + tmpx = a->dp[ix]; + + /* alias to the address of where the digits will be stored */ + tmpt = &(t.dp[digs]); + + /* alias for where to read the right hand side from */ + tmpy = b->dp + (digs - ix); + + for (iy = digs - ix; iy < pb; iy++) { + /* calculate the double precision result */ + r = ((mp_word) * tmpt) + ((mp_word) tmpx) * ((mp_word) * tmpy++) + ((mp_word) u); + + /* get the lower part */ + *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); + + /* carry the carry */ + u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); + } + *tmpt = u; + } + mp_clamp (&t); + mp_exch (&t, c); + mp_clear (&t); + return MP_OKAY; +} + +/* End: bn_s_mp_mul_high_digs.c */ + +/* Start: bn_s_mp_sqr.c */ +#line 0 "bn_s_mp_sqr.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */ +int +s_mp_sqr (mp_int * a, mp_int * b) +{ + mp_int t; + int res, ix, iy, pa; + mp_word r; + mp_digit u, tmpx, *tmpt; + + pa = a->used; + if ((res = mp_init_size (&t, pa + pa + 1)) != MP_OKAY) { + return res; + } + t.used = pa + pa + 1; + + for (ix = 0; ix < pa; ix++) { + /* first calculate the digit at 2*ix */ + /* calculate double precision result */ + r = ((mp_word) t.dp[ix + ix]) + + ((mp_word) a->dp[ix]) * ((mp_word) a->dp[ix]); + + /* store lower part in result */ + t.dp[ix + ix] = (mp_digit) (r & ((mp_word) MP_MASK)); + + /* get the carry */ + u = (r >> ((mp_word) DIGIT_BIT)); + + /* left hand side of A[ix] * A[iy] */ + tmpx = a->dp[ix]; + + /* alias for where to store the results */ + tmpt = t.dp + (ix + ix + 1); + + for (iy = ix + 1; iy < pa; iy++) { + /* first calculate the product */ + r = ((mp_word) tmpx) * ((mp_word) a->dp[iy]); + + /* now calculate the double precision result, note we use + * addition instead of *2 since its easier to optimize + */ + r = ((mp_word) * tmpt) + r + r + ((mp_word) u); + + /* store lower part */ + *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); + + /* get carry */ + u = (r >> ((mp_word) DIGIT_BIT)); + } + /* propagate upwards */ + while (u != ((mp_digit) 0)) { + r = ((mp_word) * tmpt) + ((mp_word) u); + *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); + u = (r >> ((mp_word) DIGIT_BIT)); + } + } + + mp_clamp (&t); + mp_exch (&t, b); + mp_clear (&t); + return MP_OKAY; +} + +/* End: bn_s_mp_sqr.c */ + +/* Start: bn_s_mp_sub.c */ +#line 0 "bn_s_mp_sub.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */ +int +s_mp_sub (mp_int * a, mp_int * b, mp_int * c) +{ + int olduse, res, min, max; + + /* find sizes */ + min = b->used; + max = a->used; + + /* init result */ + if (c->alloc < max) { + if ((res = mp_grow (c, max)) != MP_OKAY) { + return res; + } + } + olduse = c->used; + c->used = max; + + { + register mp_digit u, *tmpa, *tmpb, *tmpc; + register int i; + + /* alias for digit pointers */ + tmpa = a->dp; + tmpb = b->dp; + tmpc = c->dp; + + /* set carry to zero */ + u = 0; + for (i = 0; i < min; i++) { + /* T[i] = A[i] - B[i] - U */ + *tmpc = *tmpa++ - *tmpb++ - u; + + /* U = carry bit of T[i] + * Note this saves performing an AND operation since + * if a carry does occur it will propagate all the way to the + * MSB. As a result a single shift is enough to get the carry + */ + u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1)); + + /* Clear carry from T[i] */ + *tmpc++ &= MP_MASK; + } + + /* now copy higher words if any, e.g. if A has more digits than B */ + for (; i < max; i++) { + /* T[i] = A[i] - U */ + *tmpc = *tmpa++ - u; + + /* U = carry bit of T[i] */ + u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1)); + + /* Clear carry from T[i] */ + *tmpc++ &= MP_MASK; + } + + /* clear digits above used (since we may not have grown result above) */ + for (i = c->used; i < olduse; i++) { + *tmpc++ = 0; + } + } + + mp_clamp (c); + return MP_OKAY; +} + + +/* End: bn_s_mp_sub.c */ + +/* Start: bncore.c */ +#line 0 "bncore.c" +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is designed directly after the MPI library by + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org + */ +#include + +/* Known optimal configurations + + CPU /Compiler /MUL CUTOFF/SQR CUTOFF +------------------------------------------------------------- + Intel P4 /GCC v3.2 / 70/ 108 + AMD Athlon XP /GCC v3.2 / 109/ 127 + +*/ + +/* configured for a AMD XP Thoroughbred core with etc/tune.c */ +int KARATSUBA_MUL_CUTOFF = 109, /* Min. number of digits before Karatsuba multiplication is used. */ + KARATSUBA_SQR_CUTOFF = 127, /* Min. number of digits before Karatsuba squaring is used. */ + + TOOM_MUL_CUTOFF = 350, /* no optimal values of these are known yet so set em high */ + TOOM_SQR_CUTOFF = 400; + +/* End: bncore.c */ + + +/* EOF */ diff --git a/mycrypt.h b/mycrypt.h index d72cb03..3a09a73 100644 --- a/mycrypt.h +++ b/mycrypt.h @@ -16,8 +16,8 @@ extern "C" { #endif /* version */ -#define CRYPT 0x0083 -#define SCRYPT "0.83" +#define CRYPT 0x0084 +#define SCRYPT "0.84" /* max size of either a cipher/hash block or symmetric key [largest of the two] */ #define MAXBLOCKSIZE 128 diff --git a/mycrypt_custom.h b/mycrypt_custom.h index 58203c4..ad6081f 100644 --- a/mycrypt_custom.h +++ b/mycrypt_custom.h @@ -1,14 +1,16 @@ /* This header is meant to be included before mycrypt.h in projects where - * you don't want to throw all the defines in a makefile. + * you don't want to throw all the defines in a makefile. */ #ifndef MYCRYPT_CUSTOM_H_ #define MYCRYPT_CUSTOM_H_ #ifdef CRYPT - #error mycrypt_custom.h should be included before mycrypt.h + #error mycrypt_custom.h should be included before mycrypt.h #endif +#define LTC_TEST + #define XMALLOC malloc #define XREALLOC realloc #define XCALLOC calloc diff --git a/noekeon.c b/noekeon.c index 52b5d32..8f4428e 100644 --- a/noekeon.c +++ b/noekeon.c @@ -169,6 +169,9 @@ void noekeon_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_k int noekeon_test(void) { + #ifndef LTC_TEST + return CRYPT_NOP; + #else static const unsigned char key[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, @@ -193,13 +196,14 @@ int noekeon_test(void) } return CRYPT_OK; + #endif } int noekeon_keysize(int *desired_keysize) { _ARGCHK(desired_keysize != NULL); if (*desired_keysize < 16) { - return CRYPT_INVALID_KEYSIZE; + return CRYPT_INVALID_KEYSIZE; } else { *desired_keysize = 16; return CRYPT_OK; diff --git a/prime.c b/prime.c index 64e6e8e..b50baf2 100644 --- a/prime.c +++ b/prime.c @@ -2,144 +2,17 @@ #ifdef MPI -#define UPPER_LIMIT (sizeof(prime_tab) / sizeof(prime_tab[0])) - -static const mp_digit prime_tab[] = { - 0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013, - 0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035, - 0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059, - 0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F, 0x0083, - 0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD, - 0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF, - 0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107, - 0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137, - - 0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167, - 0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199, - 0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9, - 0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7, - 0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239, - 0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265, - 0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293, - 0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF, - - 0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301, - 0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B, - 0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371, - 0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD, - 0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5, - 0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419, - 0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449, - 0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B, - - 0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7, - 0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503, - 0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529, - 0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F, - 0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3, - 0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7, - 0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623, - 0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653 }; - +#define UPPER_LIMIT PRIME_SIZE /* figures out if a number is prime (MR test) */ -#ifdef CLEAN_STACK -static int _is_prime(mp_int *N, int *result) -#else -int is_prime(mp_int *N, int *result) -#endif -{ - long x, s, j; - int res; - mp_int n1, a, y, r; - mp_digit d; - - _ARGCHK(N != NULL); - _ARGCHK(result != NULL); - - /* default to answer of no */ - *result = 0; - - /* divisible by any of the first primes? */ - for (x = 0; x < (long)UPPER_LIMIT; x++) { - /* is N equal to a small prime? */ - if (mp_cmp_d(N, prime_tab[x]) == 0) { - *result = 1; - return CRYPT_OK; - } - - /* is N mod prime_tab[x] == 0, then its divisible by it */ - if (mp_mod_d(N, prime_tab[x], &d) != MP_OKAY) { - return CRYPT_MEM; - } - - if (d == 0) { - return CRYPT_OK; - } - } - - /* init variables */ - if (mp_init_multi(&r, &n1, &a, &y, NULL) != MP_OKAY) { - return CRYPT_MEM; - } - - /* n1 = N - 1 */ - if (mp_sub_d(N, 1, &n1) != MP_OKAY) { goto error; } - - /* r = N - 1 */ - if (mp_copy(&n1, &r) != MP_OKAY) { goto error; } - - /* find s such that N-1 = (2^s)r */ - s = 0; - while (mp_iseven(&r) != 0) { - ++s; - if (mp_div_2(&r, &r) != MP_OKAY) { - goto error; - } - } - - for (x = 0; x < 8; x++) { - /* choose a */ - mp_set(&a, prime_tab[x]); - - /* compute y = a^r mod n */ - if (mp_exptmod(&a, &r, N, &y) != MP_OKAY) { goto error; } - - /* (y != 1) AND (y != N-1) */ - if ((mp_cmp_d(&y, 1) != 0) && (mp_cmp(&y, &n1) != 0)) { - /* while j <= s-1 and y != n-1 */ - for (j = 1; (j <= (s-1)) && (mp_cmp(&y, &n1) != 0); j++) { - /* y = y^2 mod N */ - if (mp_sqrmod(&y, N, &y) != MP_OKAY) { goto error; } - - /* if y == 1 return false */ - if (mp_cmp_d(&y, 1) == 0) { goto ok; } - } - - /* if y != n-1 return false */ - if (mp_cmp(&y, &n1) != 0) { goto ok; } - } - } - *result = 1; -ok: - res = CRYPT_OK; - goto done; -error: - res = CRYPT_MEM; -done: - mp_clear_multi(&a, &y, &n1, &r, NULL); - return res; -} - -#ifdef CLEAN_STACK int is_prime(mp_int *N, int *result) { - int x; - x = _is_prime(N, result); - burn_stack(sizeof(long) * 3 + sizeof(int) + sizeof(mp_int) * 4 + sizeof(mp_digit)); - return x; -} -#endif + int err; + if ((err = mp_prime_is_prime(N, 8, result)) != MP_OKAY) { + return CRYPT_MEM; + } + return CRYPT_OK; +} static int next_prime(mp_int *N, mp_digit step) { @@ -152,7 +25,7 @@ static int next_prime(mp_int *N, mp_digit step) /* first find the residues */ for (x = 0; x < (long)UPPER_LIMIT; x++) { - if (mp_mod_d(N, prime_tab[x], &residues[x]) != MP_OKAY) { + if (mp_mod_d(N, __prime_tab[x], &residues[x]) != MP_OKAY) { return CRYPT_MEM; } } @@ -168,7 +41,7 @@ loop: dist = step; for (x = 0; (dist < (MP_DIGIT_MAX-step-1)) && (x < (long)UPPER_LIMIT); x++) { j = (long)residues[x] + (long)dist + total_dist; - if (j % (long)prime_tab[x] == 0) { + if (j % (long)__prime_tab[x] == 0) { dist += step; x = -1; } } @@ -195,7 +68,7 @@ loop: } for (x = 0; x < 8; x++) { /* choose a */ - mp_set(&a, prime_tab[x]); + mp_set(&a, __prime_tab[x]); /* compute y = a^r mod n */ if (mp_exptmod(&a, &r, N, &y) != MP_OKAY) { goto error; } diff --git a/rc2.c b/rc2.c index 869376f..faaf8ee 100644 --- a/rc2.c +++ b/rc2.c @@ -239,6 +239,9 @@ void rc2_ecb_decrypt( const unsigned char *cipher, int rc2_test(void) { + #ifndef LTC_TEST + return CRYPT_NOP; + #else static const struct { int keylen; unsigned char key[16], pt[8], ct[8]; @@ -276,6 +279,7 @@ int rc2_test(void) } } return CRYPT_OK; + #endif } int rc2_keysize(int *keysize) diff --git a/rc5.c b/rc5.c index ad2777c..dc2e577 100644 --- a/rc5.c +++ b/rc5.c @@ -152,6 +152,9 @@ void rc5_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key * int rc5_test(void) { + #ifndef LTC_TEST + return CRYPT_NOP; + #else static const struct { unsigned char key[16], pt[8], ct[8]; } tests[] = { @@ -194,6 +197,7 @@ int rc5_test(void) } } return CRYPT_OK; + #endif } int rc5_keysize(int *desired_keysize) diff --git a/rc6.c b/rc6.c index fa647ea..7f26c0b 100644 --- a/rc6.c +++ b/rc6.c @@ -156,6 +156,9 @@ void rc6_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key * int rc6_test(void) { + #ifndef LTC_TEST + return CRYPT_NOP; + #else static const struct { int keylen; unsigned char key[32], pt[16], ct[16]; @@ -214,6 +217,7 @@ int rc6_test(void) } } return CRYPT_OK; + #endif } int rc6_keysize(int *desired_keysize) diff --git a/rsa.c b/rsa.c index c811997..c60d22f 100644 --- a/rsa.c +++ b/rsa.c @@ -5,7 +5,7 @@ int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key) { mp_int p, q, tmp1, tmp2, tmp3; - int res, err; + int res, err; _ARGCHK(key != NULL); @@ -16,7 +16,7 @@ int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key) if ((e < 3) || ((e & 1) == 0)) { return CRYPT_INVALID_ARG; } - + if ((err = prng_is_valid(wprng)) != CRYPT_OK) { return err; } @@ -34,7 +34,7 @@ int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key) if (mp_sub_d(&p, 1, &tmp1) != MP_OKAY) { goto error; } /* tmp1 = p-1 */ if (mp_gcd(&tmp1, &tmp3, &tmp2) != MP_OKAY) { goto error; } /* tmp2 = gcd(p-1, e) */ } while (mp_cmp_d(&tmp2, 1) != 0); /* while e divides p-1 */ - + /* make prime "q" */ do { if (rand_prime(&q, size/2, prng, wprng) != CRYPT_OK) { res = CRYPT_ERROR; goto done; } @@ -48,7 +48,7 @@ int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key) if (mp_lcm(&tmp1, &tmp2, &tmp1) != MP_OKAY) { goto error; } /* tmp1 = lcm(p-1, q-1) */ /* make key */ - if (mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, + if (mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->pQ, &key->p, &key->q, NULL) != MP_OKAY) { goto error; } @@ -64,16 +64,16 @@ int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key) if (mp_mod(&key->d, &tmp1, &key->dP) != MP_OKAY) { goto error2; } /* dP = d mod p-1 */ if (mp_mod(&key->d, &tmp2, &key->dQ) != MP_OKAY) { goto error2; } /* dQ = d mod q-1 */ - + if (mp_invmod(&q, &p, &key->qP) != MP_OKAY) { goto error2; } /* qP = 1/q mod p */ if (mp_mulmod(&key->qP, &q, &key->N, &key->qP)) { goto error2; } /* qP = q * (1/q mod p) mod N */ - if (mp_invmod(&p, &q, &key->pQ) != MP_OKAY) { goto error2; } /* pQ = 1/p mod q */ + if (mp_invmod(&p, &q, &key->pQ) != MP_OKAY) { goto error2; } /* pQ = 1/p mod q */ if (mp_mulmod(&key->pQ, &p, &key->N, &key->pQ)) { goto error2; } /* pQ = p * (1/p mod q) mod N */ if (mp_copy(&p, &key->p) != MP_OKAY) { goto error2; } if (mp_copy(&q, &key->q) != MP_OKAY) { goto error2; } - + /* shrink ram required */ if (mp_shrink(&key->e) != MP_OKAY) { goto error2; } if (mp_shrink(&key->d) != MP_OKAY) { goto error2; } @@ -84,12 +84,12 @@ int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key) if (mp_shrink(&key->pQ) != MP_OKAY) { goto error2; } if (mp_shrink(&key->p) != MP_OKAY) { goto error2; } if (mp_shrink(&key->q) != MP_OKAY) { goto error2; } - + res = CRYPT_OK; key->type = PK_PRIVATE_OPTIMIZED; goto done; error2: - mp_clear_multi(&key->d, &key->e, &key->N, &key->dQ, &key->dP, + mp_clear_multi(&key->d, &key->e, &key->N, &key->dQ, &key->dP, &key->qP, &key->pQ, &key->p, &key->q, NULL); error: res = CRYPT_MEM; @@ -101,7 +101,7 @@ done: void rsa_free(rsa_key *key) { _ARGCHK(key != NULL); - mp_clear_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, + mp_clear_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->pQ, &key->p, &key->q, NULL); } @@ -125,7 +125,7 @@ int rsa_exptmod(const unsigned char *in, unsigned long inlen, /* init and copy into tmp */ if (mp_init_multi(&tmp, &tmpa, &tmpb, NULL) != MP_OKAY) { goto error; } if (mp_read_unsigned_bin(&tmp, (unsigned char *)in, (int)inlen) != MP_OKAY) { goto error; } - + /* sanity check on the input */ if (mp_cmp(&key->N, &tmp) == MP_LT) { res = CRYPT_PK_INVALID_SIZE; @@ -158,7 +158,7 @@ int rsa_exptmod(const unsigned char *in, unsigned long inlen, *outlen = x; /* convert it */ - (void)mp_to_unsigned_bin(&tmp, out); + if (mp_to_unsigned_bin(&tmp, out) != MP_OKAY) { goto error; } /* clean up and return */ res = CRYPT_OK; @@ -170,7 +170,7 @@ done: return res; } -int rsa_signpad(const unsigned char *in, unsigned long inlen, +int rsa_signpad(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { unsigned long x, y; @@ -184,10 +184,10 @@ int rsa_signpad(const unsigned char *in, unsigned long inlen, } /* check inlen */ - if ((inlen <= 0) || inlen > 512) { + if (inlen > 512) { return CRYPT_PK_INVALID_SIZE; } - + for (y = x = 0; x < inlen; x++) out[y++] = (unsigned char)0xFF; for (x = 0; x < inlen; x++) @@ -198,8 +198,8 @@ int rsa_signpad(const unsigned char *in, unsigned long inlen, return CRYPT_OK; } -int rsa_pad(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, +int rsa_pad(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, int wprng, prng_state *prng) { unsigned char buf[1536]; @@ -211,17 +211,17 @@ int rsa_pad(const unsigned char *in, unsigned long inlen, _ARGCHK(outlen != NULL); /* is output big enough? */ - if (*outlen < (3 * inlen)) { + if (*outlen < (3 * inlen)) { return CRYPT_BUFFER_OVERFLOW; } /* get random padding required */ if ((err = prng_is_valid(wprng)) != CRYPT_OK) { - return err; + return err; } /* check inlen */ - if ((inlen <= 0) || inlen > 512) { + if (inlen > 512) { return CRYPT_PK_INVALID_SIZE; } @@ -229,14 +229,14 @@ int rsa_pad(const unsigned char *in, unsigned long inlen, return CRYPT_ERROR_READPRNG; } - /* pad it like a sandwitch (sp?) + /* pad it like a sandwhich * * Looks like 0xFF R1 M R2 0xFF - * - * Where R1/R2 are random and exactly equal to the length of M minus one byte. + * + * Where R1/R2 are random and exactly equal to the length of M minus one byte. */ - for (x = 0; x < inlen-1; x++) { - out[x+1] = buf[x]; + for (x = 0; x < inlen-1; x++) { + out[x+1] = buf[x]; } for (x = 0; x < inlen; x++) { @@ -258,7 +258,7 @@ int rsa_pad(const unsigned char *in, unsigned long inlen, return CRYPT_OK; } -int rsa_signdepad(const unsigned char *in, unsigned long inlen, +int rsa_signdepad(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { unsigned long x; @@ -267,7 +267,7 @@ int rsa_signdepad(const unsigned char *in, unsigned long inlen, _ARGCHK(out != NULL); _ARGCHK(outlen != NULL); - if (*outlen < inlen/3) { + if (*outlen < inlen/3) { return CRYPT_BUFFER_OVERFLOW; } @@ -277,13 +277,13 @@ int rsa_signdepad(const unsigned char *in, unsigned long inlen, return CRYPT_INVALID_PACKET; } } - for (x = 0; x < inlen/3; x++) + for (x = 0; x < inlen/3; x++) out[x] = in[x+(inlen/3)]; *outlen = inlen/3; return CRYPT_OK; } -int rsa_depad(const unsigned char *in, unsigned long inlen, +int rsa_depad(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { unsigned long x; @@ -292,10 +292,10 @@ int rsa_depad(const unsigned char *in, unsigned long inlen, _ARGCHK(out != NULL); _ARGCHK(outlen != NULL); - if (*outlen < inlen/3) { + if (*outlen < inlen/3) { return CRYPT_BUFFER_OVERFLOW; } - for (x = 0; x < inlen/3; x++) + for (x = 0; x < inlen/3; x++) out[x] = in[x+(inlen/3)]; *outlen = inlen/3; return CRYPT_OK; @@ -350,8 +350,8 @@ int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key _ARGCHK(key != NULL); /* type valid? */ - if (!(key->type == PK_PRIVATE || key->type == PK_PRIVATE_OPTIMIZED) && - (type == PK_PRIVATE || type == PK_PRIVATE_OPTIMIZED)) { + if (!(key->type == PK_PRIVATE || key->type == PK_PRIVATE_OPTIMIZED) && + (type == PK_PRIVATE || type == PK_PRIVATE_OPTIMIZED)) { return CRYPT_PK_INVALID_TYPE; } @@ -363,7 +363,7 @@ int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key /* output modulus */ OUTPUT_BIGNUM(&key->N, buf2, y, z); - + /* output public key */ OUTPUT_BIGNUM(&key->e, buf2, y, z); @@ -381,7 +381,7 @@ int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key } /* check size */ - if (*outlen < y) { + if (*outlen < y) { return CRYPT_BUFFER_OVERFLOW; } @@ -407,17 +407,18 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key) _ARGCHK(in != NULL); _ARGCHK(key != NULL); - /* test packet header */ - if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_RSA, PACKET_SUB_KEY)) != CRYPT_OK) { - return err; - } - + /* check length */ if (inlen < 1+PACKET_SIZE) { return CRYPT_INVALID_PACKET; } + /* test packet header */ + if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_RSA, PACKET_SUB_KEY)) != CRYPT_OK) { + return err; + } + /* init key */ - if (mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, + if (mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->pQ, &key->p, &key->q, NULL) != MP_OKAY) { return CRYPT_MEM; } @@ -446,7 +447,7 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key) INPUT_BIGNUM(&key->p, in, x, y); INPUT_BIGNUM(&key->q, in, x, y); } - + /* free up ram not required */ if (key->type != PK_PRIVATE_OPTIMIZED) { mp_clear_multi(&key->dQ, &key->dP, &key->pQ, &key->qP, &key->p, &key->q, NULL); @@ -457,7 +458,7 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key) return CRYPT_OK; error2: - mp_clear_multi(&key->d, &key->e, &key->N, &key->dQ, &key->dP, + mp_clear_multi(&key->d, &key->e, &key->N, &key->dQ, &key->dP, &key->pQ, &key->qP, &key->p, &key->q, NULL); return err; } diff --git a/rsa_sys.c b/rsa_sys.c index 06e6584..4c562b8 100644 --- a/rsa_sys.c +++ b/rsa_sys.c @@ -69,7 +69,7 @@ int rsa_decrypt_key(const unsigned char *in, unsigned long inlen, unsigned char *outkey, unsigned long *keylen, rsa_key *key) { - unsigned char sym_key[MAXBLOCKSIZE], rsa_in[4096], rsa_out[4096]; + unsigned char sym_key[MAXBLOCKSIZE], rsa_out[4096]; unsigned long x, y, z, i, rsa_size; int err; @@ -129,7 +129,6 @@ int rsa_decrypt_key(const unsigned char *in, unsigned long inlen, #ifdef CLEAN_STACK /* clean up */ zeromem(sym_key, sizeof(sym_key)); - zeromem(rsa_in, sizeof(rsa_in)); zeromem(rsa_out, sizeof(rsa_out)); #endif *keylen = z; @@ -150,7 +149,7 @@ int rsa_sign_hash(const unsigned char *in, unsigned long inlen, _ARGCHK(key != NULL); /* reject nonsense sizes */ - if (inlen < 16) { + if (inlen > MAXBLOCKSIZE || inlen < 16) { return CRYPT_INVALID_ARG; } diff --git a/safer+.c b/safer+.c index b3bed1f..d42b254 100644 --- a/safer+.c +++ b/safer+.c @@ -407,6 +407,9 @@ void saferp_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_ke int saferp_test(void) { + #ifndef LTC_TEST + return CRYPT_NOP; + #else static const struct { int keylen; unsigned char key[32], pt[16], ct[16]; @@ -459,6 +462,7 @@ int saferp_test(void) } return CRYPT_OK; + #endif } int saferp_keysize(int *desired_keysize) diff --git a/safer.c b/safer.c index 9a06d46..87c7db9 100644 --- a/safer.c +++ b/safer.c @@ -344,6 +344,9 @@ int safer_128_keysize(int *keysize) int safer_k64_test(void) { + #ifndef LTC_TEST + return CRYPT_NOP; + #else static const unsigned char k64_pt[] = { 1, 2, 3, 4, 5, 6, 7, 8 }, k64_key[] = { 8, 7, 6, 5, 4, 3, 2, 1 }, k64_ct[] = { 200, 242, 156, 221, 135, 120, 62, 217 }; @@ -364,11 +367,15 @@ int safer_k64_test(void) } return CRYPT_OK; + #endif } int safer_sk64_test(void) { + #ifndef LTC_TEST + return CRYPT_NOP; + #else static const unsigned char sk64_pt[] = { 1, 2, 3, 4, 5, 6, 7, 8 }, sk64_key[] = { 1, 2, 3, 4, 5, 6, 7, 8 }, sk64_ct[] = { 95, 206, 155, 162, 5, 132, 56, 199 }; @@ -390,10 +397,14 @@ int safer_sk64_test(void) } return CRYPT_OK; + #endif } int safer_sk128_test(void) { + #ifndef LTC_TEST + return CRYPT_NOP; + #else static const unsigned char sk128_pt[] = { 1, 2, 3, 4, 5, 6, 7, 8 }, sk128_key[] = { 1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0 }, @@ -413,9 +424,8 @@ int safer_sk128_test(void) if (memcmp(buf[0], sk128_ct, 8) != 0 || memcmp(buf[1], sk128_pt, 8) != 0) { return CRYPT_FAIL_TESTVECTOR; } - - - return CRYPT_OK; + return CRYPT_OK; + #endif } #endif diff --git a/serpent.c b/serpent.c index 235ea11..8ea4a9c 100644 --- a/serpent.c +++ b/serpent.c @@ -588,6 +588,9 @@ void serpent_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_k int serpent_test(void) { + #ifndef LTC_TEST + return CRYPT_NOP; + #else static const struct { int keylen; unsigned char key[32], pt[16], ct[16]; @@ -680,6 +683,7 @@ int serpent_test(void) } } return CRYPT_OK; + #endif } int serpent_keysize(int *desired_keysize) diff --git a/sha1.c b/sha1.c index 23f88aa..b273165 100644 --- a/sha1.c +++ b/sha1.c @@ -184,6 +184,9 @@ void sha1_done(hash_state * md, unsigned char *hash) int sha1_test(void) { + #ifndef LTC_TEST + return CRYPT_NOP; + #else static const struct { char *msg; unsigned char hash[20]; @@ -213,6 +216,7 @@ int sha1_test(void) } } return CRYPT_OK; + #endif } #endif diff --git a/sha256.c b/sha256.c index 20f161a..33fd96f 100644 --- a/sha256.c +++ b/sha256.c @@ -34,8 +34,8 @@ static const unsigned long K[64] = { /* Various logical functions */ #define Ch(x,y,z) ((x & y) | (~x & z)) #define Maj(x,y,z) (((x | y) & z) | (x & y)) -#define S(x, n) ROR((x),(n)) -#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) +#define S(x, n) ROR((x),(n)) +#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) #define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) #define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) #define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) @@ -180,6 +180,9 @@ void sha256_done(hash_state * md, unsigned char *hash) int sha256_test(void) { + #ifndef LTC_TEST + return CRYPT_NOP; + #else static const struct { char *msg; unsigned char hash[32]; @@ -211,6 +214,7 @@ int sha256_test(void) } } return CRYPT_OK; + #endif } #endif diff --git a/sha384.c b/sha384.c index dcd9bb2..b07f4d6 100644 --- a/sha384.c +++ b/sha384.c @@ -51,6 +51,9 @@ void sha384_done(hash_state * md, unsigned char *hash) int sha384_test(void) { + #ifndef LTC_TEST + return CRYPT_NOP; + #else static const struct { char *msg; unsigned char hash[48]; @@ -86,6 +89,7 @@ int sha384_test(void) } } return CRYPT_OK; + #endif } diff --git a/sha512.c b/sha512.c index 282733f..88317e4 100644 --- a/sha512.c +++ b/sha512.c @@ -209,6 +209,9 @@ void sha512_done(hash_state * md, unsigned char *hash) int sha512_test(void) { + #ifndef LTC_TEST + return CRYPT_NOP; + #else static const struct { char *msg; unsigned char hash[64]; @@ -248,6 +251,7 @@ int sha512_test(void) } } return CRYPT_OK; + #endif } #ifdef SHA384 diff --git a/tiger.c b/tiger.c index 5dcd13b..cd0dd4c 100644 --- a/tiger.c +++ b/tiger.c @@ -687,6 +687,9 @@ void tiger_done(hash_state * md, unsigned char *hash) int tiger_test(void) { + #ifndef LTC_TEST + return CRYPT_NOP; + #else static const struct { char *msg; unsigned char hash[24]; @@ -731,6 +734,7 @@ int tiger_test(void) } } return CRYPT_OK; + #endif } #endif diff --git a/tommath.h b/tommath.h index d71a264..8e43f6c 100644 --- a/tommath.h +++ b/tommath.h @@ -1,19 +1,17 @@ /* LibTomMath, multiple-precision integer library -- Tom St Denis * - * LibTomMath is library that provides for multiple-precision + * LibTomMath is library that provides for multiple-precision * integer arithmetic as well as number theoretic functionality. - * + * * The library is designed directly after the MPI library by - * Michael Fromberger but has been written from scratch with - * additional optimizations in place. + * Michael Fromberger but has been written from scratch with + * additional optimizations in place. * * The library is free for all purposes without any express * guarantee it works. * * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org */ -#include - #ifndef BN_H_ #define BN_H_ @@ -36,18 +34,18 @@ extern "C" { #else -/* C on the other hand dosen't care */ -#define OPT_CAST +/* C on the other hand doesn't care */ +#define OPT_CAST #endif -/* some default configurations. +/* some default configurations. * - * A "mp_digit" must be able to hold DIGIT_BIT + 1 bits - * A "mp_word" must be able to hold 2*DIGIT_BIT + 1 bits + * A "mp_digit" must be able to hold DIGIT_BIT + 1 bits + * A "mp_word" must be able to hold 2*DIGIT_BIT + 1 bits * - * At the very least a mp_digit must be able to hold 7 bits - * [any size beyond that is ok provided it overflow the data type] + * At the very least a mp_digit must be able to hold 7 bits + * [any size beyond that is ok provided it doesn't overflow the data type] */ #ifdef MP_8BIT typedef unsigned char mp_digit; @@ -55,31 +53,50 @@ extern "C" { #elif defined(MP_16BIT) typedef unsigned short mp_digit; typedef unsigned long mp_word; -#else +#elif defined(MP_64BIT) + /* for GCC only on supported platforms */ #ifndef CRYPT - #ifdef _MSC_VER + typedef unsigned long long ulong64; + typedef signed long long long64; +#endif + + typedef ulong64 mp_digit; + typedef unsigned long mp_word __attribute__ ((mode(TI))); + + #define DIGIT_BIT 60 +#else + /* this is the default case, 28-bit digits */ + + /* this is to make porting into LibTomCrypt easier :-) */ +#ifndef CRYPT + #if defined(_MSC_VER) || defined(__BORLANDC__) typedef unsigned __int64 ulong64; typedef signed __int64 long64; #else typedef unsigned long long ulong64; typedef signed long long long64; - #endif -#endif + #endif +#endif - /* default case */ typedef unsigned long mp_digit; typedef ulong64 mp_word; - - #define DIGIT_BIT 28 -#endif +#ifdef MP_31BIT + #define DIGIT_BIT 31 +#else + #define DIGIT_BIT 28 +#endif +#endif + +/* otherwise the bits per digit is calculated automatically from the size of a mp_digit */ #ifndef DIGIT_BIT #define DIGIT_BIT ((CHAR_BIT * sizeof(mp_digit) - 1)) /* bits per digit */ #endif + #define MP_DIGIT_BIT DIGIT_BIT #define MP_MASK ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1)) -#define MP_DIGIT_MAX MP_MASK +#define MP_DIGIT_MAX MP_MASK /* equalities */ #define MP_LT -1 /* less than */ @@ -99,9 +116,17 @@ typedef int mp_err; /* you'll have to tune these... */ extern int KARATSUBA_MUL_CUTOFF, KARATSUBA_SQR_CUTOFF, - MONTGOMERY_EXPT_CUTOFF; + TOOM_MUL_CUTOFF, + TOOM_SQR_CUTOFF; -#define MP_PREC 64 /* default digits of precision */ +/* various build options */ +#define MP_PREC 64 /* default digits of precision (must be power of two) */ + +/* define this to use lower memory usage routines (exptmods mostly) */ +/* #define MP_LOW_MEM */ + +/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */ +#define MP_WARRAY (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1)) typedef struct { int used, alloc, sign; @@ -120,6 +145,12 @@ int mp_init(mp_int *a); /* free a bignum */ void mp_clear(mp_int *a); +/* init a null terminated series of arguments */ +int mp_init_multi(mp_int *mp, ...); + +/* clear a null terminated series of arguments */ +void mp_clear_multi(mp_int *mp, ...); + /* exchange two ints */ void mp_exch(mp_int *a, mp_int *b); @@ -145,7 +176,7 @@ void mp_zero(mp_int *a); void mp_set(mp_int *a, mp_digit b); /* set a 32-bit const */ -int mp_set_int(mp_int *a, unsigned long b); +int mp_set_int(mp_int *a, unsigned int b); /* copy, b = a */ int mp_copy(mp_int *a, mp_int *b); @@ -164,22 +195,22 @@ void mp_rshd(mp_int *a, int b); /* left shift by "b" digits */ int mp_lshd(mp_int *a, int b); -/* c = a / 2^b */ +/* c = a / 2**b */ int mp_div_2d(mp_int *a, int b, mp_int *c, mp_int *d); /* b = a/2 */ int mp_div_2(mp_int *a, mp_int *b); -/* c = a * 2^b */ +/* c = a * 2**b */ int mp_mul_2d(mp_int *a, int b, mp_int *c); /* b = a*2 */ int mp_mul_2(mp_int *a, mp_int *b); -/* c = a mod 2^d */ +/* c = a mod 2**d */ int mp_mod_2d(mp_int *a, int b, mp_int *c); -/* computes a = 2^b */ +/* computes a = 2**b */ int mp_2expt(mp_int *a, int b); /* makes a pseudo-random int of a given size */ @@ -218,7 +249,7 @@ int mp_sub(mp_int *a, mp_int *b, mp_int *c); /* c = a * b */ int mp_mul(mp_int *a, mp_int *b, mp_int *c); -/* b = a^2 */ +/* b = a*a */ int mp_sqr(mp_int *a, mp_int *b); /* a/b => cb + d == a */ @@ -244,7 +275,10 @@ int mp_mul_d(mp_int *a, mp_digit b, mp_int *c); /* a/b => cb + d == a */ int mp_div_d(mp_int *a, mp_digit b, mp_int *c, mp_digit *d); -/* c = a^b */ +/* a/3 => 3c + d == a */ +int mp_div_3(mp_int *a, mp_int *c, mp_digit *d); + +/* c = a**b */ int mp_expt_d(mp_int *a, mp_digit b, mp_int *c); /* c = a mod b, 0 <= c < b */ @@ -273,7 +307,7 @@ int mp_gcd(mp_int *a, mp_int *b, mp_int *c); /* c = [a, b] or (a*b)/(a, b) */ int mp_lcm(mp_int *a, mp_int *b, mp_int *c); -/* finds one of the b'th root of a, such that |c|^b <= |a| +/* finds one of the b'th root of a, such that |c|**b <= |a| * * returns error if a < 0 and b is even */ @@ -290,7 +324,7 @@ int mp_reduce_setup(mp_int *a, mp_int *b); /* Barrett Reduction, computes a (mod b) with a precomputed value c * - * Assumes that 0 < a <= b^2, note if 0 > a > -(b^2) then you can merely + * Assumes that 0 < a <= b*b, note if 0 > a > -(b*b) then you can merely * compute the reduction as -1 * mp_reduce(mp_abs(a)) [pseudo code]. */ int mp_reduce(mp_int *a, mp_int *b, mp_int *c); @@ -298,12 +332,12 @@ int mp_reduce(mp_int *a, mp_int *b, mp_int *c); /* setups the montgomery reduction */ int mp_montgomery_setup(mp_int *a, mp_digit *mp); -/* computes a = B^n mod b without division or multiplication useful for +/* computes a = B**n mod b without division or multiplication useful for * normalizing numbers in a Montgomery system. */ int mp_montgomery_calc_normalization(mp_int *a, mp_int *b); -/* computes xR^-1 == x (mod N) via Montgomery Reduction */ +/* computes x/R == x (mod N) via Montgomery Reduction */ int mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp); /* returns 1 if a is a valid DR modulus */ @@ -315,32 +349,47 @@ void mp_dr_setup(mp_int *a, mp_digit *d); /* reduces a modulo b using the Diminished Radix method */ int mp_dr_reduce(mp_int *a, mp_int *b, mp_digit mp); -/* d = a^b (mod c) */ +/* returns true if a can be reduced with mp_reduce_2k */ +int mp_reduce_is_2k(mp_int *a); + +/* determines k value for 2k reduction */ +int mp_reduce_2k_setup(mp_int *a, mp_digit *d); + +/* reduces a modulo b where b is of the form 2**p - k [0 <= a] */ +int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit k); + +/* d = a**b (mod c) */ int mp_exptmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d); /* ---> Primes <--- */ -#define PRIME_SIZE 256 /* number of primes */ -/* table of first 256 primes */ +/* number of primes */ +#ifdef MP_8BIT + #define PRIME_SIZE 31 +#else + #define PRIME_SIZE 256 +#endif + +/* table of first PRIME_SIZE primes */ extern const mp_digit __prime_tab[]; -/* result=1 if a is divisible by one of the first 256 primes */ +/* result=1 if a is divisible by one of the first PRIME_SIZE primes */ int mp_prime_is_divisible(mp_int *a, int *result); -/* performs one Fermat test of "a" using base "b". - * Sets result to 0 if composite or 1 if probable prime +/* performs one Fermat test of "a" using base "b". + * Sets result to 0 if composite or 1 if probable prime */ int mp_prime_fermat(mp_int *a, mp_int *b, int *result); /* performs one Miller-Rabin test of "a" using base "b". - * Sets result to 0 if composite or 1 if probable prime + * Sets result to 0 if composite or 1 if probable prime */ int mp_prime_miller_rabin(mp_int *a, mp_int *b, int *result); /* performs t rounds of Miller-Rabin on "a" using the first * t prime bases. Also performs an initial sieve of trial * division. Determines if "a" is prime with probability - * of error no more than (1/4)^t. + * of error no more than (1/4)**t. * * Sets result to 1 if probably prime, 0 otherwise */ @@ -367,6 +416,9 @@ int mp_read_radix(mp_int *a, char *str, int radix); int mp_toradix(mp_int *a, char *str, int radix); int mp_radix_size(mp_int *a, int radix); +int mp_fread(mp_int *a, int radix, FILE *stream); +int mp_fwrite(mp_int *a, int radix, FILE *stream); + #define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len)) #define mp_raw_size(mp) mp_signed_bin_size(mp) #define mp_toraw(mp, str) mp_to_signed_bin((mp), (str)) @@ -390,10 +442,13 @@ int s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs); int fast_s_mp_sqr(mp_int *a, mp_int *b); int s_mp_sqr(mp_int *a, mp_int *b); int mp_karatsuba_mul(mp_int *a, mp_int *b, mp_int *c); +int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c); int mp_karatsuba_sqr(mp_int *a, mp_int *b); +int mp_toom_sqr(mp_int *a, mp_int *b); int fast_mp_invmod(mp_int *a, mp_int *b, mp_int *c); int fast_mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp); int mp_exptmod_fast(mp_int *G, mp_int *X, mp_int *P, mp_int *Y, int mode); +int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y); void bn_reverse(unsigned char *s, int len); #ifdef __cplusplus diff --git a/twofish.c b/twofish.c index cfaa0d1..2d09589 100644 --- a/twofish.c +++ b/twofish.c @@ -633,6 +633,9 @@ void twofish_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_k int twofish_test(void) { + #ifndef LTC_TEST + return CRYPT_NOP; + #else static const struct { int keylen; unsigned char key[32], pt[16], ct[16]; @@ -682,6 +685,7 @@ int twofish_test(void) } } return CRYPT_OK; +#endif } int twofish_keysize(int *desired_keysize) diff --git a/xtea.c b/xtea.c index 21b0840..c0e4715 100644 --- a/xtea.c +++ b/xtea.c @@ -107,6 +107,9 @@ void xtea_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key int xtea_test(void) { + #ifndef LTC_TEST + return CRYPT_NOP; + #else static const unsigned char key[16] = { 0x78, 0x56, 0x34, 0x12, 0xf0, 0xcd, 0xcb, 0x9a, 0x48, 0x37, 0x26, 0x15, 0xc0, 0xbf, 0xae, 0x9d }; @@ -129,6 +132,7 @@ int xtea_test(void) } return CRYPT_OK; + #endif } int xtea_keysize(int *desired_keysize)