Mercurial > dropbear
changeset 144:7ed585a2c53b libtomcrypt
propagate of 3f8f752126017cbe7d93c4086c27a91550df745f and 747ebf284d40a15b338e5a5c7730ecec6eade3d7 from branch 'au.asn.ucc.matt.ltc-orig' to 'au.asn.ucc.matt.ltc-db'
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Sun, 19 Dec 2004 11:47:33 +0000 |
parents | 5d99163f7e32 (current diff) b1edc9158f6c (diff) |
children | c2b93763dac9 |
files | Makefile.in crypt.c crypt_cipher_descriptor.c crypt_hash_descriptor.c crypt_prng_descriptor.c demos/test.c doc/crypt.pdf examples/ch1-01.c examples/ch1-02.c examples/ch1-03.c examples/ch2-01.c makefile makefile.msvc modes_test.c mycrypt.h mycrypt_argchk.h mycrypt_custom.h mycrypt_kr.h mycrypt_macros.h mycrypt_misc.h sha224.c sha256.c sha384.c sha512.c tiger.c whirl.c yarrow.c |
diffstat | 18 files changed, 3597 insertions(+), 364 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile.in Sun Dec 19 11:47:33 2004 +0000 @@ -0,0 +1,253 @@ +# MAKEFILE for linux GCC +# +# Tom St Denis +# Modified by Clay Culver + +# The version +VERSION=0.99 + +# Compiler and Linker Names +#CC=gcc +#LD=ld + +# Archiver [makes .a files] +#AR=ar +#ARFLAGS=r + +# Compilation flags. Note the += does not write over the user's CFLAGS! +# The rest of the flags come from the parent Dropbear makefile +CFLAGS += -c -I$(srcdir) +# -Werror + +# optimize for SPEED +#CFLAGS += -O3 -funroll-all-loops + +#add -fomit-frame-pointer. hinders debugging! +#CFLAGS += -fomit-frame-pointer + +# optimize for SIZE +#CFLAGS += -Os -DSMALL_CODE + +# compile for DEBUGING (required for ccmalloc checking!!!) +#CFLAGS += -g3 + +#These flags control how the library gets built. + +#Output filenames for various targets. +LIBNAME=libtomcrypt.a +HASH=hashsum +CRYPT=encrypt +SMALL=small +PROF=x86_prof +TV=tv_gen + +#LIBPATH-The directory for libtomcrypt to be installed to. +#INCPATH-The directory to install the header files for libtomcrypt. +#DATAPATH-The directory to install the pdf docs. +DESTDIR= +LIBPATH=/usr/lib +INCPATH=/usr/include +DATAPATH=/usr/share/doc/libtomcrypt/pdf + +#List of objects to compile. + +#Leave MPI built-in or force developer to link against libtommath? +#MPIOBJECT=mpi.o +#Dropbear uses libtommath +MPIOBJECT= + +OBJECTS=error_to_string.o mpi_to_ltc_error.o base64_encode.o base64_decode.o \ +\ +crypt.o crypt_find_cipher.o crypt_find_hash_any.o \ +crypt_hash_is_valid.o crypt_register_hash.o crypt_unregister_prng.o \ +crypt_argchk.o crypt_find_cipher_any.o crypt_find_hash_id.o \ +crypt_prng_descriptor.o crypt_register_prng.o crypt_cipher_descriptor.o \ +crypt_find_cipher_id.o crypt_find_prng.o crypt_prng_is_valid.o \ +crypt_unregister_cipher.o crypt_cipher_is_valid.o crypt_find_hash.o \ +crypt_hash_descriptor.o crypt_register_cipher.o crypt_unregister_hash.o \ +\ +sober128.o fortuna.o sprng.o yarrow.o rc4.o rng_get_bytes.o rng_make_prng.o \ +\ +rand_prime.o is_prime.o \ +\ +ecc.o dh.o \ +\ +rsa_decrypt_key.o rsa_encrypt_key.o rsa_exptmod.o rsa_free.o rsa_make_key.o \ +rsa_sign_hash.o rsa_verify_hash.o rsa_export.o rsa_import.o tim_exptmod.o \ +rsa_v15_encrypt_key.o rsa_v15_decrypt_key.o rsa_v15_sign_hash.o rsa_v15_verify_hash.o \ +\ +dsa_export.o dsa_free.o dsa_import.o dsa_make_key.o dsa_sign_hash.o \ +dsa_verify_hash.o dsa_verify_key.o \ +\ +aes.o aes_enc.o \ +\ +blowfish.o des.o safer_tab.o safer.o saferp.o rc2.o xtea.o \ +rc6.o rc5.o cast5.o noekeon.o twofish.o skipjack.o \ +\ +md2.o md4.o md5.o sha1.o sha256.o sha512.o tiger.o whirl.o \ +rmd128.o rmd160.o chc.o \ +\ +packet_store_header.o packet_valid_header.o \ +\ +eax_addheader.o eax_decrypt.o eax_decrypt_verify_memory.o eax_done.o eax_encrypt.o \ +eax_encrypt_authenticate_memory.o eax_init.o eax_test.o \ +\ +ocb_decrypt.o ocb_decrypt_verify_memory.o ocb_done_decrypt.o ocb_done_encrypt.o \ +ocb_encrypt.o ocb_encrypt_authenticate_memory.o ocb_init.o ocb_ntz.o \ +ocb_shift_xor.o ocb_test.o s_ocb_done.o \ +\ +omac_done.o omac_file.o omac_init.o omac_memory.o omac_process.o omac_test.o \ +\ +pmac_done.o pmac_file.o pmac_init.o pmac_memory.o pmac_ntz.o pmac_process.o \ +pmac_shift_xor.o pmac_test.o \ +\ +cbc_start.o cbc_encrypt.o cbc_decrypt.o cbc_getiv.o cbc_setiv.o \ +cfb_start.o cfb_encrypt.o cfb_decrypt.o cfb_getiv.o cfb_setiv.o \ +ofb_start.o ofb_encrypt.o ofb_decrypt.o ofb_getiv.o ofb_setiv.o \ +ctr_start.o ctr_encrypt.o ctr_decrypt.o ctr_getiv.o ctr_setiv.o \ +ecb_start.o ecb_encrypt.o ecb_decrypt.o \ +\ +hash_file.o hash_filehandle.o hash_memory.o \ +\ +hmac_done.o hmac_file.o hmac_init.o hmac_memory.o hmac_process.o hmac_test.o \ +\ +pkcs_1_mgf1.o pkcs_1_oaep_encode.o pkcs_1_oaep_decode.o \ +pkcs_1_pss_encode.o pkcs_1_pss_decode.o pkcs_1_i2osp.o pkcs_1_os2ip.o \ +pkcs_1_v15_es_encode.o pkcs_1_v15_es_decode.o pkcs_1_v15_sa_encode.o pkcs_1_v15_sa_decode.o \ +\ +pkcs_5_1.o pkcs_5_2.o \ +\ +der_encode_integer.o der_decode_integer.o der_length_integer.o \ +der_put_multi_integer.o der_get_multi_integer.o \ +\ +burn_stack.o zeromem.o \ +\ +$(MPIOBJECT) + +TESTOBJECTS=demos/test.o +HASHOBJECTS=demos/hashsum.o +CRYPTOBJECTS=demos/encrypt.o +SMALLOBJECTS=demos/small.o +PROFS=demos/x86_prof.o +TVS=demos/tv_gen.o + +#Files left over from making the crypt.pdf. +LEFTOVERS=*.dvi *.log *.aux *.toc *.idx *.ilg *.ind *.out + +#Compressed filenames +COMPRESSED=crypt-$(VERSION).tar.bz2 crypt-$(VERSION).zip + +#Header files used by libtomcrypt. +HEADERS=ltc_tommath.h mycrypt_cfg.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 mycrypt_pkcs.h + +#The default rule for make builds the libtomcrypt library. +default:library + +#ciphers come in two flavours... enc+dec and enc +aes_enc.o: aes.c aes_tab.c + $(CC) $(CFLAGS) -DENCRYPT_ONLY -c $(srcdir)/aes.c -o aes_enc.o + +#These are the rules to make certain object files. +aes.o: aes.c aes_tab.c +twofish.o: twofish.c twofish_tab.c +whirl.o: whirl.c whirltab.c +ecc.o: ecc.c ecc_sys.c +dh.o: dh.c dh_sys.c +sha512.o: sha512.c sha384.c +sha256.o: sha256.c sha224.c + +#This rule makes the libtomcrypt library. +library: $(LIBNAME) + +$(LIBNAME): $(OBJECTS) + $(AR) $(ARFLAGS) $@ $(OBJECTS) + $(RANLIB) $@ + +#This rule makes the hash program included with libtomcrypt +hashsum: library $(HASHOBJECTS) + $(CC) $(HASHOBJECTS) $(LIBNAME) -o $(HASH) $(WARN) + +#makes the crypt program +crypt: library $(CRYPTOBJECTS) + $(CC) $(CRYPTOBJECTS) $(LIBNAME) -o $(CRYPT) $(WARN) + +#makes the small program +small: library $(SMALLOBJECTS) + $(CC) $(SMALLOBJECTS) $(LIBNAME) -o $(SMALL) $(WARN) + +x86_prof: library $(PROFS) + $(CC) $(PROFS) $(LIBNAME) $(EXTRALIBS) -o $(PROF) + +tv_gen: library $(TVS) + $(CC) $(TVS) $(LIBNAME) $(EXTRALIBS) -o $(TV) + +#This rule installs the library and the header files. This must be run +#as root in order to have a high enough permission to write to the correct +#directories and to set the owner and group to root. +install: library docs + install -d -g root -o root $(DESTDIR)$(LIBPATH) + install -d -g root -o root $(DESTDIR)$(INCPATH) + install -d -g root -o root $(DESTDIR)$(DATAPATH) + install -g root -o root $(LIBNAME) $(DESTDIR)$(LIBPATH) + install -g root -o root $(HEADERS) $(DESTDIR)$(INCPATH) + install -g root -o root doc/crypt.pdf $(DESTDIR)$(DATAPATH) + +install_lib: library + install -d -g root -o root $(DESTDIR)$(LIBPATH) + install -d -g root -o root $(DESTDIR)$(INCPATH) + install -g root -o root $(LIBNAME) $(DESTDIR)$(LIBPATH) + install -g root -o root $(HEADERS) $(DESTDIR)$(INCPATH) + +#This rule cleans the source tree of all compiled code, not including the pdf +#documentation. +clean: + -rm -f $(OBJECTS) $(TESTOBJECTS) $(HASHOBJECTS) $(CRYPTOBJECTS) $(SMALLOBJECTS) $(LEFTOVERS) $(LIBNAME) + -rm -f $(TEST) $(HASH) $(COMPRESSED) $(PROFS) $(PROF) $(TVS) $(TV) + -rm -f *.la *.lo *.o *.a *.dll *stackdump *.lib *.exe *.obj demos/*.obj demos/*.o *.bat *.txt *.il *.da demos/*.il demos/*.da *.dyn *.dpi \ + *.gcda *.gcno demos/*.gcno demos/*.gcda *~ doc/* + -cd demos/test && make clean + -rm -rf .libs demos/.libs demos/test/.libs + +#This builds the crypt.pdf file. Note that the rm -f *.pdf has been removed +#from the clean command! This is because most people would like to keep the +#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 doc/crypt.pdf $(LEFTOVERS) + echo "hello" > crypt.ind + latex crypt > /dev/null + latex crypt > /dev/null + makeindex crypt.idx > /dev/null + latex crypt > /dev/null + dvipdf crypt + mv -ivf crypt.pdf doc/crypt.pdf + -rm -f $(LEFTOVERS) + +docdvi: crypt.tex + echo hello > crypt.ind + latex crypt > /dev/null + latex crypt > /dev/null + makeindex crypt.idx + latex crypt > /dev/null + +#pretty build +pretty: + perl pretty.build + +#for GCC 3.4+ +profiled: + make clean + make CFLAGS="$(CFLAGS) -fprofile-generate" EXTRALIBS=-lgcov x86_prof + ./x86_prof + rm *.o *.a x86_prof + make CFLAGS="$(CFLAGS) -fprofile-use" EXTRALIBS=-lgcov x86_prof + +#zipup the project (take that!) +zipup: clean docs + cd .. ; rm -rf crypt* libtomcrypt-$(VERSION) ; mkdir libtomcrypt-$(VERSION) ; \ + cp -R ./libtomcrypt/* ./libtomcrypt-$(VERSION)/ ; tar -c libtomcrypt-$(VERSION)/* > crypt-$(VERSION).tar ; \ + bzip2 -9vv crypt-$(VERSION).tar ; zip -9 -r crypt-$(VERSION).zip libtomcrypt-$(VERSION)/* ; \ + gpg -b -a crypt-$(VERSION).tar.bz2 ; gpg -b -a crypt-$(VERSION).zip
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PLAN Sun Dec 19 11:47:33 2004 +0000 @@ -0,0 +1,38 @@ +The following functions are marked for removal and/or behavioural change by v1.00 of LibTomCrypt + +1. RSA Support + + rsa_pad, rsa_signpad, rsa_depad, rsa_signdepad, rsa_import, rsa_export + +They will be replaced with PKCS #1 compliant OAEP/PSS padding function as early as v0.96 + +2. DSA Support + + dsa_import, dsa_export + +Will be replaced with suitable DSS [what is the standard?] compliant formats. Planned for v0.96 + +3. Key Ring Support + + (all) + +The entire API will be dropped as early as v0.96. It was just an experiment and nobody uses it anyways. + +4. Test Harness + + demos/test.c + +The test harness is well overdue for a makeover. Planned for as early as v0.97 + + +Put things in order... + +v0.96 -- removed keyring.c and gf.c + -- removed LTC RSA padding + -- DSS support [whatever this entails] + -- Bug fixes/updates to the PKCS/DSS support, should be stable in this release + +v0.97 -- Re-written test harness + -- More demos in the manual and demos/ directory + +... future???
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ampi.c Sun Dec 19 11:47:33 2004 +0000 @@ -0,0 +1,55 @@ +/* Code submitted by Svante Seleborg, cleaned up by Tom St Denis */ + +#include "mycrypt.h" +#include <stdarg.h> + +#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 +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/base64.c Sun Dec 19 11:47:33 2004 +0000 @@ -0,0 +1,121 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, [email protected], http://libtomcrypt.org + */ +/* compliant base64 code donated by Wayne Scott ([email protected]) */ +#include "mycrypt.h" + +#ifdef BASE64 + +static const char *codes = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static const unsigned char map[256] = { +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, +255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, +255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, +255, 255, 255, 255 }; + +int base64_encode(const unsigned char *in, unsigned long len, + unsigned char *out, unsigned long *outlen) +{ + unsigned long i, len2, leven; + unsigned char *p; + + _ARGCHK(in != NULL); + _ARGCHK(out != NULL); + _ARGCHK(outlen != NULL); + + /* valid output size ? */ + len2 = 4 * ((len + 2) / 3); + if (*outlen < len2 + 1) { + return CRYPT_BUFFER_OVERFLOW; + } + p = out; + leven = 3*(len / 3); + for (i = 0; i < leven; i += 3) { + *p++ = codes[(in[0] >> 2) & 0x3F]; + *p++ = codes[(((in[0] & 3) << 4) + (in[1] >> 4)) & 0x3F]; + *p++ = codes[(((in[1] & 0xf) << 2) + (in[2] >> 6)) & 0x3F]; + *p++ = codes[in[2] & 0x3F]; + in += 3; + } + /* Pad it if necessary... */ + if (i < len) { + unsigned a = in[0]; + unsigned b = (i+1 < len) ? in[1] : 0; + + *p++ = codes[(a >> 2) & 0x3F]; + *p++ = codes[(((a & 3) << 4) + (b >> 4)) & 0x3F]; + *p++ = (i+1 < len) ? codes[(((b & 0xf) << 2)) & 0x3F] : '='; + *p++ = '='; + } + + /* append a NULL byte */ + *p = '\0'; + + /* return ok */ + *outlen = p - out; + return CRYPT_OK; +} + +int base64_decode(const unsigned char *in, unsigned long len, + unsigned char *out, unsigned long *outlen) +{ + unsigned long t, x, y, z; + unsigned char c; + int g; + + _ARGCHK(in != NULL); + _ARGCHK(out != NULL); + _ARGCHK(outlen != NULL); + + g = 3; + for (x = y = z = t = 0; x < len; x++) { + c = map[in[x]&0xFF]; + if (c == 255) continue; + if (c == 254) { c = 0; g--; } + t = (t<<6)|c; + if (++y == 4) { + if (z + g > *outlen) { + return CRYPT_BUFFER_OVERFLOW; + } + out[z++] = (unsigned char)((t>>16)&255); + if (g > 1) out[z++] = (unsigned char)((t>>8)&255); + if (g > 2) out[z++] = (unsigned char)(t&255); + y = t = 0; + } + } + if (y != 0) { + return CRYPT_INVALID_PACKET; + } + *outlen = z; + return CRYPT_OK; +} + +#endif +
--- a/crypt.c Sun Dec 19 11:34:45 2004 +0000 +++ b/crypt.c Sun Dec 19 11:47:33 2004 +0000 @@ -10,6 +10,8 @@ */ #include "mycrypt.h" +/* Dropbear doesn't need these + const char *crypt_build_settings = "LibTomCrypt " SCRYPT "\n\n" "Endianess: " @@ -250,4 +252,5 @@ "\n" "\n\n\n" ; + */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gf.c Sun Dec 19 11:47:33 2004 +0000 @@ -0,0 +1,305 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, [email protected], http://libtomcrypt.org + */ +/* polynomial basis GF(2^w) routines */ +#include "mycrypt.h" + +#ifdef GF + +#define FORLOOP for (i = 0; i < LSIZE; i++) + +/* c = a + b */ +void gf_add(gf_intp a, gf_intp b, gf_intp c) +{ + int i; + FORLOOP c[i] = a[i]^b[i]; +} + +/* b = a */ +void gf_copy(gf_intp a, gf_intp b) +{ + int i; + FORLOOP b[i] = a[i]; +} + +/* a = 0 */ +void gf_zero(gf_intp a) +{ + int i; + FORLOOP a[i] = 0; +} + +/* is a zero? */ +int gf_iszero(gf_intp a) +{ + int i; + FORLOOP if (a[i]) { + return 0; + } + return 1; +} + +/* is a one? */ +int gf_isone(gf_intp a) +{ + int i; + for (i = 1; i < LSIZE; i++) { + if (a[i]) { + return 0; + } + } + return a[0] == 1; +} + +/* b = a << 1*/ +void gf_shl(gf_intp a, gf_intp b) +{ + int i; + gf_int tmp; + + gf_copy(a, tmp); + for (i = LSIZE-1; i > 0; i--) + b[i] = ((tmp[i]<<1)|((tmp[i-1]&0xFFFFFFFFUL)>>31))&0xFFFFFFFFUL; + b[0] = (tmp[0] << 1)&0xFFFFFFFFUL; + gf_zero(tmp); +} + +/* b = a >> 1 */ +void gf_shr(gf_intp a, gf_intp b) +{ + int i; + gf_int tmp; + + gf_copy(a, tmp); + for (i = 0; i < LSIZE-1; i++) + b[i] = (((tmp[i]&0xFFFFFFFFUL)>>1)|(tmp[i+1]<<31))&0xFFFFFFFFUL; + b[LSIZE-1] = (tmp[LSIZE-1]&0xFFFFFFFFUL)>>1; + gf_zero(tmp); +} + +/* returns -1 if its zero, otherwise degree of a */ +int gf_deg(gf_intp a) +{ + int i, ii; + unsigned long t; + + ii = -1; + for (i = LSIZE-1; i >= 0; i--) + if (a[i]) { + for (t = a[i], ii = 0; t; t >>= 1, ++ii); + break; + } + if (i == -1) i = 0; + return (i<<5)+ii; +} + +/* c = ab */ +void gf_mul(gf_intp a, gf_intp b, gf_intp c) +{ + gf_int ta, tb; + int i, n; + + gf_copy(a, ta); + gf_copy(b, tb); + gf_zero(c); + n = gf_deg(ta)+1; + for (i = 0; i < n; i++) { + if (ta[i>>5]&(1<<(i&31))) + gf_add(c, tb, c); + gf_shl(tb, tb); + } + gf_zero(ta); + gf_zero(tb); +} + +/* q = a/b, r = a%b */ +void gf_div(gf_intp a, gf_intp b, gf_intp q, gf_intp r) +{ + gf_int ta, tb, shifts[LSIZE*32]; + int i, magb, mag; + + mag = gf_deg(a); + magb = gf_deg(b); + + /* special cases */ + if (magb > mag) { + gf_copy(a, r); + gf_zero(q); + return; + } + if (magb == -1) { + return; + } + + /* copy locally */ + gf_copy(a, ta); + gf_copy(b, tb); + gf_zero(q); + + /* make shifted versions of "b" */ + gf_copy(tb, shifts[0]); + for (i = 1; i <= (mag-magb); i++) + gf_shl(shifts[i-1], shifts[i]); + + while (mag >= magb) { + i = (mag - magb); + q[i>>5] |= (1<<(i&31)); + gf_add(ta, shifts[i], ta); + mag = gf_deg(ta); + } + gf_copy(ta, r); + gf_zero(ta); + gf_zero(tb); + zeromem(shifts, sizeof(shifts)); +} + +/* b = a mod m */ +void gf_mod(gf_intp a, gf_intp m, gf_intp b) +{ + gf_int tmp; + gf_div(a,m,tmp,b); + gf_zero(tmp); +} + +/* c = ab (mod m) */ +void gf_mulmod(gf_intp a, gf_intp b, gf_intp m, gf_intp c) +{ + gf_int tmp; + gf_mul(a, b, tmp); + gf_mod(tmp, m, c); + gf_zero(tmp); +} + +/* B = 1/A mod M */ +void gf_invmod(gf_intp A, gf_intp M, gf_intp B) +{ + gf_int m, n, p0, p1, p2, r, q, tmp; + + /* put all variables in known setup state */ + gf_zero(p0); + gf_zero(p2); + gf_copy(M, m); + gf_copy(A, n); + p0[0] = 1; + gf_div(m, n, p1, r); + gf_copy(p1, q); + + /* loop until r == 0 */ + while (!gf_iszero(r)) { + gf_copy(n, m); + gf_copy(r, n); + gf_div(m, n, q, r); + gf_mul(q, p1, tmp); + gf_add(tmp, p0, p2); + gf_copy(p1, p0); + gf_copy(p2, p1); + } + gf_copy(p0, B); + gf_zero(p0); +} + +/* find a square root modulo a prime. Note the number of + * elements is 2^k - 1, so we must square k-2 times to get the + * square root.. + */ +void gf_sqrt(gf_intp a, gf_intp M, gf_intp b) +{ + int k; + k = gf_deg(M)-2; + gf_copy(a, b); + while (k--) + gf_mulmod(b, b, M, b); +} + +/* c = gcd(A,B) */ +void gf_gcd(gf_intp A, gf_intp B, gf_intp c) +{ + gf_int a, b, r; + int n; + + gf_add(A, B, r); + n = gf_deg(r); + if (gf_deg(A) > n) { + gf_copy(A, a); + gf_copy(B, b); + } else { + gf_copy(A, b); + gf_copy(B, a); + } + + do { + gf_mod(a, b, r); + gf_copy(b, a); + gf_copy(r, b); + } while (!gf_iszero(r)); + gf_copy(a, c); + gf_zero(a); + gf_zero(b); +} + +/* returns non-zero if 'a' is irreducible */ +int gf_is_prime(gf_intp a) +{ + gf_int u, tmp; + int m, n; + + gf_zero(u); + u[0] = 2; /* u(x) = x */ + m = gf_deg(a); + for (n = 0; n < (m/2); n++) { + gf_mulmod(u, u, a, u); /* u(x) = u(x)^2 mod a(x) */ + gf_copy(u, tmp); + tmp[0] ^= 2; /* tmp(x) = u(x) - x */ + gf_gcd(tmp, a, tmp); /* tmp(x) = gcd(a(x), u(x) - x) */ + if (!gf_isone(tmp)) { + return 0; + } + } + return 1; +} + +/* returns bytes required to store a gf_int */ +int gf_size(gf_intp a) +{ + int n; + + n = gf_deg(a); + if (n == -1) { + return 4; + } + n = n + (32 - (n&31)); + return n/8; +} + +/* store a gf_int */ +void gf_toraw(gf_intp a, unsigned char *dst) +{ + int x, n; + n = gf_size(a)/4; + for (x = 0; x < n; x++) { + STORE32L(a[x], dst); + dst += 4; + } +} + +/* read a gf_int (len == in bytes) */ +void gf_readraw(gf_intp a, unsigned char *str, int len) +{ + int x; + gf_zero(a); + for (x = 0; x < len/4; x++) { + LOAD32L(a[x], str); + str += 4; + } +} + +#endif + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/keyring.c Sun Dec 19 11:47:33 2004 +0000 @@ -0,0 +1,862 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, [email protected], http://libtomcrypt.org + */ +/* Provides keyring functionality for libtomcrypt, Tom St Denis */ +#include <mycrypt.h> + +#ifdef KR + +static const unsigned char key_magic[4] = { 0x12, 0x34, 0x56, 0x78 }; +static const unsigned char file_magic[4] = { 0x9A, 0xBC, 0xDE, 0xF0 }; +static const unsigned char sign_magic[4] = { 0x87, 0x56, 0x43, 0x21 }; +static const unsigned char enc_magic[4] = { 0x0F, 0xED, 0xCB, 0xA9 }; + +static const unsigned long crc_table[256] = { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +}; + +#define DO1(buf) crc = crc_table[(crc ^ (*buf++)) & 0xff] ^ (crc >> 8); +#define DO2(buf) DO1(buf); DO1(buf); +#define DO4(buf) DO2(buf); DO2(buf); +#define DO8(buf) DO4(buf); DO4(buf); + +static unsigned long crc32 (unsigned long crc, const unsigned char *buf, unsigned long len) +{ + //_ARGCHK(buf != NULL && len == 0); + crc = crc ^ 0xffffffffL; + while (len >= 8) { + DO8 (buf); + len -= 8; + } + + if (len > 0) { + do { + DO1 (buf); + } while (--len > 0); + } + return crc ^ 0xffffffffUL; +} + +int kr_init(pk_key **pk) +{ + _ARGCHK(pk != NULL); + + *pk = XCALLOC(1, sizeof(pk_key)); + if (*pk == NULL) { + return CRYPT_MEM; + } + (*pk)->system = NON_KEY; + return CRYPT_OK; +} + +unsigned long kr_crc(const unsigned char *name, const unsigned char *email, const unsigned char *description) +{ + unsigned long crc; + _ARGCHK(name != NULL); + _ARGCHK(email != NULL); + _ARGCHK(description != NULL); + crc = crc32(0UL, NULL, 0UL); + crc = crc32(crc, name, (unsigned long)MIN(MAXLEN, strlen((char *)name))); + crc = crc32(crc, email, (unsigned long)MIN(MAXLEN, strlen((char *)email))); + return crc32(crc, description, (unsigned long)MIN(MAXLEN, strlen((char *)description))); +} + +pk_key *kr_find(pk_key *pk, unsigned long ID) +{ + _ARGCHK(pk != NULL); + + while (pk != NULL) { + if (pk->system != NON_KEY && pk->ID == ID) { + return pk; + } + pk = pk->next; + } + return NULL; +} + +pk_key *kr_find_name(pk_key *pk, const char *name) +{ + _ARGCHK(pk != NULL); + _ARGCHK(name != NULL); + + while (pk != NULL) { + if (pk->system != NON_KEY && strncmp((char *)pk->name, (char *)name, sizeof(pk->name)-1) == 0) { + return pk; + } + pk = pk->next; + } + return NULL; +} + + +int kr_add(pk_key *pk, int key_type, int sys, const unsigned char *name, + const unsigned char *email, const unsigned char *description, const _pk_key *key) +{ + _ARGCHK(pk != NULL); + _ARGCHK(name != NULL); + _ARGCHK(email != NULL); + _ARGCHK(description != NULL); + _ARGCHK(key != NULL); + + /* check parameters */ + if (key_type != PK_PRIVATE && key_type != PK_PRIVATE_OPTIMIZED && key_type != PK_PUBLIC) { + return CRYPT_PK_INVALID_TYPE; + } + + if (sys != RSA_KEY && sys != DH_KEY && sys != ECC_KEY) { + return CRYPT_PK_INVALID_SYSTEM; + } + + /* see if its a dupe */ + if (kr_find(pk, kr_crc(name, email, description)) != NULL) { + return CRYPT_PK_DUP; + } + + /* find spot in key ring */ + while (pk->system != NON_KEY) { + if (pk->next == NULL) { + return CRYPT_ERROR; + } + pk = pk->next; + } + + /* now we have a spot make a next spot */ + pk->next = XCALLOC(1, sizeof(pk_key)); + if (pk->next == NULL) { + return CRYPT_MEM; + } + pk->next->system = NON_KEY; + + /* now add this new data to this ring spot */ + pk->key_type = key_type; + pk->system = sys; + strncpy((char *)pk->name, (char *)name, sizeof(pk->name)-1); + strncpy((char *)pk->email, (char *)email, sizeof(pk->email)-1); + strncpy((char *)pk->description, (char *)description, sizeof(pk->description)-1); + pk->ID = kr_crc(pk->name, pk->email, pk->description); + + /* clear the memory area */ + zeromem(&(pk->key), sizeof(pk->key)); + + /* copy the key */ + switch (sys) { + case RSA_KEY: + memcpy(&(pk->key.rsa), &(key->rsa), sizeof(key->rsa)); + break; + case DH_KEY: + memcpy(&(pk->key.dh), &(key->dh), sizeof(key->dh)); + break; + case ECC_KEY: + memcpy(&(pk->key.ecc), &(key->ecc), sizeof(key->ecc)); + break; + } + return CRYPT_OK; +} + +int kr_del(pk_key **_pk, unsigned long ID) +{ + pk_key *ppk, *pk; + + _ARGCHK(_pk != NULL); + + pk = *_pk; + ppk = NULL; + while (pk->system != NON_KEY && pk->ID != ID) { + ppk = pk; + pk = pk->next; + if (pk == NULL) { + return CRYPT_PK_NOT_FOUND; + } + } + + switch (pk->system) { + case RSA_KEY: + rsa_free(&(pk->key.rsa)); + break; + case DH_KEY: + dh_free(&(pk->key.dh)); + break; + case ECC_KEY: + ecc_free(&(pk->key.ecc)); + break; + } + + if (ppk == NULL) { /* the first element matches the ID */ + ppk = pk->next; /* get the 2nd element */ + XFREE(pk); /* free the first */ + *_pk = ppk; /* make the first element the second */ + } else { /* (not) first element matches the ID */ + ppk->next = pk->next; /* make the previous'es next point to the current next */ + XFREE(pk); /* free the element */ + } + return CRYPT_OK; +} + +int kr_clear(pk_key **pk) +{ + int err; + _ARGCHK(pk != NULL); + + while ((*pk)->system != NON_KEY) { + if ((err = kr_del(pk, (*pk)->ID)) != CRYPT_OK) { + return err; + } + } + XFREE(*pk); + *pk = NULL; + return CRYPT_OK; +} + +static unsigned long _write(unsigned char *buf, unsigned long len, FILE *f, symmetric_CTR *ctr) +{ +#ifdef NO_FILE + return 0; +#else + _ARGCHK(buf != NULL); + _ARGCHK(f != NULL); + if (ctr != NULL) { + if (ctr_encrypt(buf, buf, len, ctr) != CRYPT_OK) { + return 0; + } + } + return (unsigned long)fwrite(buf, 1, (size_t)len, f); +#endif +} + +static unsigned long _read(unsigned char *buf, unsigned long len, FILE *f, symmetric_CTR *ctr) +{ +#ifdef NO_FILE + return 0; +#else + unsigned long y; + _ARGCHK(buf != NULL); + _ARGCHK(f != NULL); + y = (unsigned long)fread(buf, 1, (size_t)len, f); + if (ctr != NULL) { + if (ctr_decrypt(buf, buf, y, ctr) != CRYPT_OK) { + return 0; + } + } + return y; +#endif +} + +int kr_export(pk_key *pk, unsigned long ID, int key_type, unsigned char *out, unsigned long *outlen) +{ + unsigned char buf[8192], *obuf; + pk_key *ppk; + unsigned long len; + int err; + + _ARGCHK(pk != NULL); + _ARGCHK(out != NULL); + _ARGCHK(outlen != NULL); + + /* find the desired key */ + ppk = kr_find(pk, ID); + if (ppk == NULL) { + return CRYPT_PK_NOT_FOUND; + } + + if (ppk->key_type == PK_PUBLIC && key_type != PK_PUBLIC) { + return CRYPT_PK_NOT_PRIVATE; + } + + /* this makes PK_PRIVATE an alias for PK_PRIVATE_OPTIMIZED type */ + if (ppk->key_type == PK_PRIVATE_OPTIMIZED && key_type == PK_PRIVATE) { + key_type = PK_PRIVATE_OPTIMIZED; + } + + /* now copy the header and various other details */ + memcpy(buf, key_magic, 4); /* magic info */ + buf[4] = key_type; /* key type */ + buf[5] = ppk->system; /* system */ + STORE32L(ppk->ID, buf+6); /* key ID */ + memcpy(buf+10, ppk->name, MAXLEN); /* the name */ + memcpy(buf+10+MAXLEN, ppk->email, MAXLEN); /* the email */ + memcpy(buf+10+MAXLEN+MAXLEN, ppk->description, MAXLEN); /* the description */ + + /* export key */ + len = sizeof(buf) - (6 + 4 + MAXLEN*3); + obuf = buf+6+4+MAXLEN*3; + switch (ppk->system) { + case RSA_KEY: + if ((err = rsa_export(obuf, &len, key_type, &(ppk->key.rsa))) != CRYPT_OK) { + return err; + } + break; + case DH_KEY: + if ((err = dh_export(obuf, &len, key_type, &(ppk->key.dh))) != CRYPT_OK) { + return err; + } + break; + case ECC_KEY: + if ((err = ecc_export(obuf, &len, key_type, &(ppk->key.ecc))) != CRYPT_OK) { + return err; + } + break; + } + + /* get the entire length of the packet */ + len += 6 + 4 + 3*MAXLEN; + + if (*outlen < len) { + #ifdef CLEAN_STACK + zeromem(buf, sizeof(buf)); + #endif + return CRYPT_BUFFER_OVERFLOW; + } else { + *outlen = len; + memcpy(out, buf, len); + #ifdef CLEAN_STACK + zeromem(buf, sizeof(buf)); + #endif + return CRYPT_OK; + } +} + +int kr_import(pk_key *pk, const unsigned char *in, unsigned long inlen) +{ + _pk_key key; + int sys, key_type, err; + unsigned long ID; + + _ARGCHK(pk != NULL); + _ARGCHK(in != NULL); + + if (inlen < 10) { + return CRYPT_INVALID_PACKET; + } + + if (memcmp(in, key_magic, 4) != 0) { + return CRYPT_INVALID_PACKET; + } + key_type = in[4]; /* get type */ + sys = in[5]; /* get system */ + LOAD32L(ID,in+6); /* the ID */ + + if (ID != kr_crc(in+10, in+10+MAXLEN, in+10+MAXLEN+MAXLEN)) { + return CRYPT_INVALID_PACKET; + } + + zeromem(&key, sizeof(key)); + + /* size of remaining packet */ + inlen -= 10 + 3*MAXLEN; + + switch (sys) { + case RSA_KEY: + if ((err = rsa_import(in+10+3*MAXLEN, inlen, &(key.rsa))) != CRYPT_OK) { + return err; + } + break; + case DH_KEY: + if ((err = dh_import(in+10+3*MAXLEN, inlen, &(key.dh))) != CRYPT_OK) { + return err; + } + break; + case ECC_KEY: + if ((err = ecc_import(in+10+3*MAXLEN, inlen, &(key.ecc))) != CRYPT_OK) { + return err; + } + break; + } + return kr_add(pk, key_type, sys, + in+10, /* the name */ + in+10+MAXLEN, /* email address */ + in+10+MAXLEN+MAXLEN, /* description */ + &key); +} + + +int kr_load(pk_key **pk, FILE *in, symmetric_CTR *ctr) +{ + unsigned char buf[8192], blen[4]; + unsigned long len; + int res, err; + + _ARGCHK(pk != NULL); + _ARGCHK(in != NULL); + + /* init keyring */ + if ((err = kr_init(pk)) != CRYPT_OK) { + return err; + } + + /* read in magic bytes */ + if (_read(buf, 6, in, ctr) != 6) { goto done2; } + + if (memcmp(buf, file_magic, 4) != 0) { + return CRYPT_INVALID_PACKET; + } + + len = (unsigned long)buf[4] | ((unsigned long)buf[5] << 8); + if (len > CRYPT) { + return CRYPT_INVALID_PACKET; + } + + /* while there are lengths to read... */ + while (_read(blen, 4, in, ctr) == 4) { + /* get length */ + LOAD32L(len, blen); + + if (len > (unsigned long)sizeof(buf)) { + return CRYPT_INVALID_PACKET; + } + + if (_read(buf, len, in, ctr) != len) { goto done2; } + if ((err = kr_import(*pk, buf, len)) != CRYPT_OK) { + return err; + } + } + + res = CRYPT_OK; + goto done; +done2: + res = CRYPT_ERROR; +done: +#ifdef CLEAN_STACK + zeromem(buf, sizeof(buf)); +#endif + return res; +} + +int kr_save(pk_key *pk, FILE *out, symmetric_CTR *ctr) +{ + unsigned char buf[8192], blen[4]; + unsigned long len; + int res, err; + + _ARGCHK(pk != NULL); + _ARGCHK(out != NULL); + + /* write out magic bytes */ + memcpy(buf, file_magic, 4); + buf[4] = (unsigned char)(CRYPT&255); + buf[5] = (unsigned char)((CRYPT>>8)&255); + if (_write(buf, 6, out, ctr) != 6) { goto done2; } + + while (pk->system != NON_KEY) { + len = sizeof(buf); + if ((err = kr_export(pk, pk->ID, pk->key_type, buf, &len)) != CRYPT_OK) { + return err; + } + + STORE32L(len, blen); + if (_write(blen, 4, out, ctr) != 4) { goto done2; } + if (_write(buf, len, out, ctr) != len) { goto done2; } + + pk = pk->next; + } + + res = CRYPT_OK; + goto done; +done2: + res = CRYPT_ERROR; +done: +#ifdef CLEAN_STACK + zeromem(buf, sizeof(buf)); +#endif + return res; +} + +int kr_make_key(pk_key *pk, prng_state *prng, int wprng, + int sys, int keysize, const unsigned char *name, + const unsigned char *email, const unsigned char *description) +{ + _pk_key key; + int key_type, err; + + _ARGCHK(pk != NULL); + _ARGCHK(name != NULL); + _ARGCHK(email != NULL); + _ARGCHK(description != NULL); + + /* valid PRNG? */ + if ((err = prng_is_valid(wprng)) != CRYPT_OK) { + return err; + } + + /* make the key first */ + zeromem(&key, sizeof(key)); + switch (sys) { + case RSA_KEY: + if ((err = rsa_make_key(prng, wprng, keysize, 65537, &(key.rsa))) != CRYPT_OK) { + return err; + } + key_type = key.rsa.type; + break; + case DH_KEY: + if ((err = dh_make_key(prng, wprng, keysize, &(key.dh))) != CRYPT_OK) { + return err; + } + key_type = key.dh.type; + break; + case ECC_KEY: + if ((err = ecc_make_key(prng, wprng, keysize, &(key.ecc))) != CRYPT_OK) { + return err; + } + key_type = key.ecc.type; + break; + default: + return CRYPT_PK_INVALID_SYSTEM; + } + + /* now add the key */ + if ((err = kr_add(pk, key_type, sys, name, email, description, &key)) != CRYPT_OK) { + return err; + } + +#ifdef CLEAN_STACK + zeromem(&key, sizeof(key)); +#endif + return CRYPT_OK; +} + +int kr_encrypt_key(pk_key *pk, unsigned long ID, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, int hash) +{ + unsigned char buf[8192]; + unsigned long len; + pk_key *kr; + int err; + + _ARGCHK(pk != NULL); + _ARGCHK(in != NULL); + _ARGCHK(out != NULL); + _ARGCHK(outlen != NULL); + + /* find the key */ + kr = kr_find(pk, ID); + if (kr == NULL) { + return CRYPT_PK_NOT_FOUND; + } + + /* store the header */ + memcpy(buf, enc_magic, 4); + + /* now store the ID */ + STORE32L(kr->ID,buf+4); + + /* now encrypt it */ + len = sizeof(buf)-12; + switch (kr->system) { + case RSA_KEY: + if ((err = rsa_encrypt_key(in, inlen, buf+12, &len, prng, wprng, &(kr->key.rsa))) != CRYPT_OK) { + return err; + } + break; + case DH_KEY: + if ((err = dh_encrypt_key(in, inlen, buf+12, &len, prng, wprng, hash, &(kr->key.dh))) != CRYPT_OK) { + return err; + } + break; + case ECC_KEY: + if ((err = ecc_encrypt_key(in, inlen, buf+12, &len, prng, wprng, hash, &(kr->key.ecc))) != CRYPT_OK) { + return err; + } + break; + } + STORE32L(len,buf+8); + len += 12; + + if (len > *outlen) { + #ifdef CLEAN_STACK + zeromem(buf, sizeof(buf)); + #endif + return CRYPT_BUFFER_OVERFLOW; + } else { + memcpy(out, buf, len); + #ifdef CLEAN_STACK + zeromem(buf, sizeof(buf)); + #endif + *outlen = len; + return CRYPT_OK; + } +} + +int kr_decrypt_key(pk_key *pk, const unsigned char *in, + unsigned char *out, unsigned long *outlen) +{ + unsigned char buf[8192]; + unsigned long pklen, len, ID; + pk_key *kr; + int err; + + _ARGCHK(pk != NULL); + _ARGCHK(in != NULL); + _ARGCHK(out != NULL); + _ARGCHK(outlen != NULL); + + /* check magic header */ + if (memcmp(in, enc_magic, 4)) { + return CRYPT_INVALID_PACKET; + } + + /* now try to find key */ + LOAD32L(ID,in+4); + kr = kr_find(pk, ID); + if (kr == NULL) { + return CRYPT_PK_NOT_FOUND; + } + + /* is it public? */ + if (kr->key_type == PK_PUBLIC) { + return CRYPT_PK_NOT_PRIVATE; + } + + /* now try and decrypt it */ + LOAD32L(pklen,in+8); + len = sizeof(buf); + switch (kr->system) { + case RSA_KEY: + if ((err = rsa_decrypt_key(in+12, pklen, buf, &len, &(kr->key.rsa))) != CRYPT_OK) { + return err; + } + break; + case DH_KEY: + if ((err = dh_decrypt_key(in+12, pklen, buf, &len, &(kr->key.dh))) != CRYPT_OK) { + return err; + } + break; + case ECC_KEY: + if ((err = ecc_decrypt_key(in+12, pklen, buf, &len, &(kr->key.ecc))) != CRYPT_OK) { + return err; + } + break; + } + + if (len > *outlen) { + #ifdef CLEAN_STACK + zeromem(buf, sizeof(buf)); + #endif + return CRYPT_BUFFER_OVERFLOW; + } else { + memcpy(out, buf, len); + #ifdef CLEAN_STACK + zeromem(buf, sizeof(buf)); + #endif + *outlen = len; + return CRYPT_OK; + } +} + +int kr_sign_hash(pk_key *pk, unsigned long ID, + const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng) +{ + unsigned char buf[8192]; + unsigned long len; + pk_key *kr; + int err; + + _ARGCHK(pk != NULL); + _ARGCHK(in != NULL); + _ARGCHK(out != NULL); + _ARGCHK(outlen != NULL); + + /* find the key */ + kr = kr_find(pk, ID); + if (kr == NULL) { + return CRYPT_PK_NOT_FOUND; + } + + /* is it public? */ + if (kr->key_type == PK_PUBLIC) { + return CRYPT_PK_NOT_PRIVATE; + } + + /* store the header */ + memcpy(buf, sign_magic, 4); + + /* now store the ID */ + STORE32L(kr->ID,buf+4); + + /* now sign it */ + len = sizeof(buf)-16; + switch (kr->system) { + case RSA_KEY: + if ((err = rsa_sign_hash(in, inlen, buf+16, &len, &(kr->key.rsa))) != CRYPT_OK) { + return err; + } + break; + case DH_KEY: + if ((err = dh_sign_hash(in, inlen, buf+16, &len, prng, wprng, &(kr->key.dh))) != CRYPT_OK) { + return err; + } + break; + case ECC_KEY: + if ((err = ecc_sign_hash(in, inlen, buf+16, &len, prng, wprng, &(kr->key.ecc))) != CRYPT_OK) { + return err; + } + break; + } + STORE32L(inlen,buf+8); + STORE32L(len,buf+12); + len += 16; + + if (len > *outlen) { + #ifdef CLEAN_STACK + zeromem(buf, sizeof(buf)); + #endif + return CRYPT_BUFFER_OVERFLOW; + } else { + memcpy(out, buf, len); + #ifdef CLEAN_STACK + zeromem(buf, sizeof(buf)); + #endif + *outlen = len; + return CRYPT_OK; + } +} + +int kr_verify_hash(pk_key *pk, const unsigned char *in, const unsigned char *hash, + unsigned long hashlen, int *stat) +{ + unsigned long inlen, pklen, ID; + pk_key *kr; + int err; + + _ARGCHK(pk != NULL); + _ARGCHK(in != NULL); + _ARGCHK(hash != NULL); + _ARGCHK(stat != NULL); + + /* default to not match */ + *stat = 0; + + /* check magic header */ + if (memcmp(in, sign_magic, 4)) { + return CRYPT_INVALID_PACKET; + } + + /* now try to find key */ + LOAD32L(ID,in+4); + kr = kr_find(pk, ID); + if (kr == NULL) { + return CRYPT_PK_NOT_FOUND; + } + + /* now try and verify it */ + LOAD32L(inlen,in+8); /* this is the length of the original inlen */ + LOAD32L(pklen,in+12); /* size of the PK packet */ + if (inlen != hashlen) { /* size doesn't match means the signature is invalid */ + return CRYPT_OK; + } + + switch (kr->system) { + case RSA_KEY: + if ((err = rsa_verify_hash(in+16, pklen, hash, stat, &(kr->key.rsa))) != CRYPT_OK) { + return err; + } + break; + case DH_KEY: + if ((err = dh_verify_hash(in+16, pklen, hash, inlen, stat, &(kr->key.dh))) != CRYPT_OK) { + return err; + } + break; + case ECC_KEY: + if ((err = ecc_verify_hash(in+16, pklen, hash, inlen, stat, &(kr->key.ecc))) != CRYPT_OK) { + return err; + } + break; + } + return CRYPT_OK; +} + +int kr_fingerprint(pk_key *pk, unsigned long ID, int hash, + unsigned char *out, unsigned long *outlen) +{ + unsigned char buf[8192]; + unsigned long len; + int err; + + _ARGCHK(pk != NULL); + _ARGCHK(out != NULL); + _ARGCHK(outlen != NULL); + + /* valid hash? */ + if ((err = hash_is_valid(hash)) != CRYPT_OK) { + return err; + } + + len = (unsigned long)sizeof(buf); + if ((err = kr_export(pk, ID, PK_PUBLIC, buf, &len)) != CRYPT_OK) { + return err; + } + + /* now hash it */ + if ((err = hash_memory(hash, buf, len, out, outlen)) != CRYPT_OK) { + return err; + } + +#ifdef CLEAN_STACK + zeromem(buf, sizeof(buf)); +#endif + return CRYPT_OK; +} + +#endif + +
--- a/makefile Sun Dec 19 11:34:45 2004 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,249 +0,0 @@ -# MAKEFILE for linux GCC -# -# Tom St Denis -# Modified by Clay Culver - -# The version -VERSION=0.99 - -# Compiler and Linker Names -#CC=gcc -#LD=ld - -# Archiver [makes .a files] -#AR=ar -#ARFLAGS=r - -# Compilation flags. Note the += does not write over the user's CFLAGS! -CFLAGS += -c -I./ -Wall -Wsign-compare -W -Wshadow -# -Werror - -# optimize for SPEED -#CFLAGS += -O3 -funroll-all-loops - -#add -fomit-frame-pointer. hinders debugging! -#CFLAGS += -fomit-frame-pointer - -# optimize for SIZE -CFLAGS += -Os -DSMALL_CODE - -# compile for DEBUGING (required for ccmalloc checking!!!) -#CFLAGS += -g3 - -#These flags control how the library gets built. - -#Output filenames for various targets. -LIBNAME=libtomcrypt.a -HASH=hashsum -CRYPT=encrypt -SMALL=small -PROF=x86_prof -TV=tv_gen - -#LIBPATH-The directory for libtomcrypt to be installed to. -#INCPATH-The directory to install the header files for libtomcrypt. -#DATAPATH-The directory to install the pdf docs. -DESTDIR= -LIBPATH=/usr/lib -INCPATH=/usr/include -DATAPATH=/usr/share/doc/libtomcrypt/pdf - -#List of objects to compile. - -#Leave MPI built-in or force developer to link against libtommath? -MPIOBJECT=mpi.o - -OBJECTS=error_to_string.o mpi_to_ltc_error.o base64_encode.o base64_decode.o \ -\ -crypt.o crypt_find_cipher.o crypt_find_hash_any.o \ -crypt_hash_is_valid.o crypt_register_hash.o crypt_unregister_prng.o \ -crypt_argchk.o crypt_find_cipher_any.o crypt_find_hash_id.o \ -crypt_prng_descriptor.o crypt_register_prng.o crypt_cipher_descriptor.o \ -crypt_find_cipher_id.o crypt_find_prng.o crypt_prng_is_valid.o \ -crypt_unregister_cipher.o crypt_cipher_is_valid.o crypt_find_hash.o \ -crypt_hash_descriptor.o crypt_register_cipher.o crypt_unregister_hash.o \ -\ -sober128.o fortuna.o sprng.o yarrow.o rc4.o rng_get_bytes.o rng_make_prng.o \ -\ -rand_prime.o is_prime.o \ -\ -ecc.o dh.o \ -\ -rsa_decrypt_key.o rsa_encrypt_key.o rsa_exptmod.o rsa_free.o rsa_make_key.o \ -rsa_sign_hash.o rsa_verify_hash.o rsa_export.o rsa_import.o tim_exptmod.o \ -rsa_v15_encrypt_key.o rsa_v15_decrypt_key.o rsa_v15_sign_hash.o rsa_v15_verify_hash.o \ -\ -dsa_export.o dsa_free.o dsa_import.o dsa_make_key.o dsa_sign_hash.o \ -dsa_verify_hash.o dsa_verify_key.o \ -\ -aes.o aes_enc.o \ -\ -blowfish.o des.o safer_tab.o safer.o saferp.o rc2.o xtea.o \ -rc6.o rc5.o cast5.o noekeon.o twofish.o skipjack.o \ -\ -md2.o md4.o md5.o sha1.o sha256.o sha512.o tiger.o whirl.o \ -rmd128.o rmd160.o chc.o \ -\ -packet_store_header.o packet_valid_header.o \ -\ -eax_addheader.o eax_decrypt.o eax_decrypt_verify_memory.o eax_done.o eax_encrypt.o \ -eax_encrypt_authenticate_memory.o eax_init.o eax_test.o \ -\ -ocb_decrypt.o ocb_decrypt_verify_memory.o ocb_done_decrypt.o ocb_done_encrypt.o \ -ocb_encrypt.o ocb_encrypt_authenticate_memory.o ocb_init.o ocb_ntz.o \ -ocb_shift_xor.o ocb_test.o s_ocb_done.o \ -\ -omac_done.o omac_file.o omac_init.o omac_memory.o omac_process.o omac_test.o \ -\ -pmac_done.o pmac_file.o pmac_init.o pmac_memory.o pmac_ntz.o pmac_process.o \ -pmac_shift_xor.o pmac_test.o \ -\ -cbc_start.o cbc_encrypt.o cbc_decrypt.o cbc_getiv.o cbc_setiv.o \ -cfb_start.o cfb_encrypt.o cfb_decrypt.o cfb_getiv.o cfb_setiv.o \ -ofb_start.o ofb_encrypt.o ofb_decrypt.o ofb_getiv.o ofb_setiv.o \ -ctr_start.o ctr_encrypt.o ctr_decrypt.o ctr_getiv.o ctr_setiv.o \ -ecb_start.o ecb_encrypt.o ecb_decrypt.o \ -\ -hash_file.o hash_filehandle.o hash_memory.o \ -\ -hmac_done.o hmac_file.o hmac_init.o hmac_memory.o hmac_process.o hmac_test.o \ -\ -pkcs_1_mgf1.o pkcs_1_oaep_encode.o pkcs_1_oaep_decode.o \ -pkcs_1_pss_encode.o pkcs_1_pss_decode.o pkcs_1_i2osp.o pkcs_1_os2ip.o \ -pkcs_1_v15_es_encode.o pkcs_1_v15_es_decode.o pkcs_1_v15_sa_encode.o pkcs_1_v15_sa_decode.o \ -\ -pkcs_5_1.o pkcs_5_2.o \ -\ -der_encode_integer.o der_decode_integer.o der_length_integer.o \ -der_put_multi_integer.o der_get_multi_integer.o \ -\ -burn_stack.o zeromem.o \ -\ -$(MPIOBJECT) - -TESTOBJECTS=demos/test.o -HASHOBJECTS=demos/hashsum.o -CRYPTOBJECTS=demos/encrypt.o -SMALLOBJECTS=demos/small.o -PROFS=demos/x86_prof.o -TVS=demos/tv_gen.o - -#Files left over from making the crypt.pdf. -LEFTOVERS=*.dvi *.log *.aux *.toc *.idx *.ilg *.ind *.out - -#Compressed filenames -COMPRESSED=crypt-$(VERSION).tar.bz2 crypt-$(VERSION).zip - -#Header files used by libtomcrypt. -HEADERS=ltc_tommath.h mycrypt_cfg.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 mycrypt_pkcs.h tommath_class.h tommath_superclass.h - -#The default rule for make builds the libtomcrypt library. -default:library - -#ciphers come in two flavours... enc+dec and enc -aes_enc.o: aes.c aes_tab.c - $(CC) $(CFLAGS) -DENCRYPT_ONLY -c aes.c -o aes_enc.o - -#These are the rules to make certain object files. -aes.o: aes.c aes_tab.c -twofish.o: twofish.c twofish_tab.c -whirl.o: whirl.c whirltab.c -ecc.o: ecc.c ecc_sys.c -dh.o: dh.c dh_sys.c -sha512.o: sha512.c sha384.c -sha256.o: sha256.c sha224.c - -#This rule makes the libtomcrypt library. -library: $(LIBNAME) - -$(LIBNAME): $(OBJECTS) - $(AR) $(ARFLAGS) $@ $(OBJECTS) - -#This rule makes the hash program included with libtomcrypt -hashsum: library $(HASHOBJECTS) - $(CC) $(HASHOBJECTS) $(LIBNAME) -o $(HASH) $(WARN) - -#makes the crypt program -crypt: library $(CRYPTOBJECTS) - $(CC) $(CRYPTOBJECTS) $(LIBNAME) -o $(CRYPT) $(WARN) - -#makes the small program -small: library $(SMALLOBJECTS) - $(CC) $(SMALLOBJECTS) $(LIBNAME) -o $(SMALL) $(WARN) - -x86_prof: library $(PROFS) - $(CC) $(PROFS) $(LIBNAME) $(EXTRALIBS) -o $(PROF) - -tv_gen: library $(TVS) - $(CC) $(TVS) $(LIBNAME) $(EXTRALIBS) -o $(TV) - -#This rule installs the library and the header files. This must be run -#as root in order to have a high enough permission to write to the correct -#directories and to set the owner and group to root. -install: library docs - install -d -g root -o root $(DESTDIR)$(LIBPATH) - install -d -g root -o root $(DESTDIR)$(INCPATH) - install -d -g root -o root $(DESTDIR)$(DATAPATH) - install -g root -o root $(LIBNAME) $(DESTDIR)$(LIBPATH) - install -g root -o root $(HEADERS) $(DESTDIR)$(INCPATH) - install -g root -o root doc/crypt.pdf $(DESTDIR)$(DATAPATH) - -install_lib: library - install -d -g root -o root $(DESTDIR)$(LIBPATH) - install -d -g root -o root $(DESTDIR)$(INCPATH) - install -g root -o root $(LIBNAME) $(DESTDIR)$(LIBPATH) - install -g root -o root $(HEADERS) $(DESTDIR)$(INCPATH) - -#This rule cleans the source tree of all compiled code, not including the pdf -#documentation. -clean: - rm -f $(OBJECTS) $(TESTOBJECTS) $(HASHOBJECTS) $(CRYPTOBJECTS) $(SMALLOBJECTS) $(LEFTOVERS) $(LIBNAME) - rm -f $(TEST) $(HASH) $(COMPRESSED) $(PROFS) $(PROF) $(TVS) $(TV) - rm -f *.la *.lo *.o *.a *.dll *stackdump *.lib *.exe *.obj demos/*.obj demos/*.o *.bat *.txt *.il *.da demos/*.il demos/*.da *.dyn *.dpi \ - *.gcda *.gcno demos/*.gcno demos/*.gcda *~ doc/* - cd demos/test ; make clean - rm -rf .libs demos/.libs demos/test/.libs - -#This builds the crypt.pdf file. Note that the rm -f *.pdf has been removed -#from the clean command! This is because most people would like to keep the -#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 doc/crypt.pdf $(LEFTOVERS) - echo "hello" > crypt.ind - latex crypt > /dev/null - latex crypt > /dev/null - makeindex crypt.idx > /dev/null - latex crypt > /dev/null - dvipdf crypt - mv -ivf crypt.pdf doc/crypt.pdf - rm -f $(LEFTOVERS) - -docdvi: crypt.tex - echo hello > crypt.ind - latex crypt > /dev/null - latex crypt > /dev/null - makeindex crypt.idx - latex crypt > /dev/null - -#pretty build -pretty: - perl pretty.build - -#for GCC 3.4+ -profiled: - make clean - make CFLAGS="$(CFLAGS) -fprofile-generate" EXTRALIBS=-lgcov x86_prof - ./x86_prof - rm *.o *.a x86_prof - make CFLAGS="$(CFLAGS) -fprofile-use" EXTRALIBS=-lgcov x86_prof - -#zipup the project (take that!) -zipup: clean docs - cd .. ; rm -rf crypt* libtomcrypt-$(VERSION) ; mkdir libtomcrypt-$(VERSION) ; \ - cp -R ./libtomcrypt/* ./libtomcrypt-$(VERSION)/ ; tar -c libtomcrypt-$(VERSION)/* > crypt-$(VERSION).tar ; \ - bzip2 -9vv crypt-$(VERSION).tar ; zip -9 -r crypt-$(VERSION).zip libtomcrypt-$(VERSION)/* ; \ - gpg -b -a crypt-$(VERSION).tar.bz2 ; gpg -b -a crypt-$(VERSION).zip
--- a/mycrypt.h Sun Dec 19 11:34:45 2004 +0000 +++ b/mycrypt.h Sun Dec 19 11:47:33 2004 +0000 @@ -23,7 +23,8 @@ #define MAXBLOCKSIZE 64 /* descriptor table size */ -#define TAB_SIZE 32 +/* Dropbear change - this should be smaller, saves some size */ +#define TAB_SIZE 4 /* error codes [will be expanded in future releases] */ enum {
--- a/mycrypt_custom.h Sun Dec 19 11:34:45 2004 +0000 +++ b/mycrypt_custom.h Sun Dec 19 11:47:33 2004 +0000 @@ -5,6 +5,9 @@ #ifndef MYCRYPT_CUSTOM_H_ #define MYCRYPT_CUSTOM_H_ +/* this will sort out which stuff based on the user-config in options.h */ +#include "../options.h" + /* macros for various libc functions you can change for embedded targets */ #define XMALLOC malloc #define XREALLOC realloc @@ -17,11 +20,13 @@ #define XCLOCK clock #define XCLOCKS_PER_SEC CLOCKS_PER_SEC -/* Use small code where possible */ -// #define SMALL_CODE +#ifdef DROPBEAR_SMALL_CODE +#define SMALL_CODE +#endif /* Enable self-test test vector checking */ -#define LTC_TEST +/* Not for dropbear */ +//#define LTC_TEST /* clean the stack of functions which put private information on stack */ // #define CLEAN_STACK @@ -29,131 +34,46 @@ /* disable all file related functions */ // #define NO_FILE -/* various ciphers */ +#define CLEAN_STACK + +#ifdef DROPBEAR_BLOWFISH_CBC #define BLOWFISH -#define RC2 -#define RC5 -#define RC6 -#define SAFERP +#endif + +#ifdef DROPBEAR_AES128_CBC #define RIJNDAEL -#define XTEA -/* _TABLES tells it to use tables during setup, _SMALL means to use the smaller scheduled key format - * (saves 4KB of ram), _ALL_TABLES enables all tables during setup */ +#endif + +#ifdef DROPBEAR_TWOFISH128_CBC #define TWOFISH -#define TWOFISH_TABLES -// #define TWOFISH_ALL_TABLES -// #define TWOFISH_SMALL -/* DES includes EDE triple-DES */ -#define DES -#define CAST5 -#define NOEKEON -#define SKIPJACK -/* SAFER code isn't public domain. It appears to be free to use - * but has been disabled by default to avoid any such problems - */ -//#define SAFER -/* block cipher modes of operation */ -#define CFB -#define OFB -#define ECB +/* enabling just TWOFISH_SMALL will make the binary ~1kB smaller, turning on + * TWOFISH_TABLES will make it a few kB bigger, but perhaps reduces runtime + * memory usage? */ +#define TWOFISH_SMALL +/*#define TWOFISH_TABLES*/ +#endif + +#ifdef DROPBEAR_3DES_CBC +#define DES +#endif #define CBC -#define CTR -/* hash functions */ -#define CHC_HASH -#define WHIRLPOOL +#if defined(DROPBEAR_DSS) && defined(DSS_PROTOK) #define SHA512 -#define SHA384 -#define SHA256 -#define SHA224 -#define TIGER +#endif + #define SHA1 + +#ifdef DROPBEAR_MD5_HMAC #define MD5 -#define MD4 -#define MD2 -#define RIPEMD128 -#define RIPEMD160 +#endif -/* MAC functions */ #define HMAC -#define OMAC -#define PMAC - -/* Encrypt + Authenticate Modes */ -#define EAX_MODE -#define OCB_MODE /* Various tidbits of modern neatoness */ #define BASE64 -/* Yarrow */ -#define YARROW -// which descriptor of AES to use? -// 0 = rijndael_enc 1 = aes_enc, 2 = rijndael [full], 3 = aes [full] -#define YARROW_AES 0 - -#if defined(YARROW) && !defined(CTR) - #error YARROW requires CTR chaining mode to be defined! -#endif - -#define SPRNG -#define RC4 - -/* Fortuna PRNG */ -#define FORTUNA -/* reseed every N calls to the read function */ -#define FORTUNA_WD 10 -/* number of pools (4..32) can save a bit of ram by lowering the count */ -#define FORTUNA_POOLS 32 - -/* Greg's SOBER128 PRNG ;-0 */ -#define SOBER128 - -#define DEVRANDOM -#define TRY_URANDOM_FIRST - -/* Public Key Neatoness */ -#define MRSA -/* enable RSA side channel timing prevention */ -#define RSA_TIMING - -/* Digital Signature Algorithm */ -#define MDSA -/* Max diff between group and modulus size in bytes */ -#define MDSA_DELTA 512 -/* Max DSA group size in bytes (default allows 4k-bit groups) */ -#define MDSA_MAX_GROUP 512 - -/* Diffie-Hellman */ -#define MDH -/* Supported Key Sizes */ -#define DH768 -#define DH1024 -#define DH1280 -#define DH1536 -#define DH1792 -#define DH2048 -#define DH2560 -#define DH3072 -#define DH4096 - -/* ECC */ -#define MECC -/* Supported Key Sizes */ -#define ECC160 -#define ECC192 -#define ECC224 -#define ECC256 -#define ECC384 -#define ECC521 - -/* Include the MPI functionality? (required by the PK algorithms) */ -#define MPI - -/* PKCS #1 (RSA) and #5 (Password Handling) stuff */ -#define PKCS_1 -#define PKCS_5 #endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mycrypt_gf.h Sun Dec 19 11:47:33 2004 +0000 @@ -0,0 +1,32 @@ + +/* ---- GF(2^w) polynomial basis ---- */ +#ifdef GF +#define LSIZE 32 /* handle upto 1024-bit GF numbers */ + +typedef unsigned long gf_int[LSIZE]; +typedef unsigned long *gf_intp; + +extern void gf_copy(gf_intp a, gf_intp b); +extern void gf_zero(gf_intp a); +extern int gf_iszero(gf_intp a); +extern int gf_isone(gf_intp a); +extern int gf_deg(gf_intp a); + +extern void gf_shl(gf_intp a, gf_intp b); +extern void gf_shr(gf_intp a, gf_intp b); +extern void gf_add(gf_intp a, gf_intp b, gf_intp c); +extern void gf_mul(gf_intp a, gf_intp b, gf_intp c); +extern void gf_div(gf_intp a, gf_intp b, gf_intp q, gf_intp r); + +extern void gf_mod(gf_intp a, gf_intp m, gf_intp b); +extern void gf_mulmod(gf_intp a, gf_intp b, gf_intp m, gf_intp c); +extern void gf_invmod(gf_intp A, gf_intp M, gf_intp B); +extern void gf_sqrt(gf_intp a, gf_intp M, gf_intp b); +extern void gf_gcd(gf_intp A, gf_intp B, gf_intp c); +extern int gf_is_prime(gf_intp a); + +extern int gf_size(gf_intp a); +extern void gf_toraw(gf_intp a, unsigned char *dst); +extern void gf_readraw(gf_intp a, unsigned char *str, int len); + +#endif
--- a/mycrypt_misc.h Sun Dec 19 11:34:45 2004 +0000 +++ b/mycrypt_misc.h Sun Dec 19 11:47:33 2004 +0000 @@ -14,4 +14,7 @@ const char *error_to_string(int err); int mpi_to_ltc_error(int err); - extern const char *crypt_build_settings; +#if 0 +/* Takes up space we don\'t need for Dropbear */ +extern const char *crypt_build_settings; +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rsa.c Sun Dec 19 11:47:33 2004 +0000 @@ -0,0 +1,273 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, [email protected], http://libtomcrypt.org + */ + +/* RSA Code by Tom St Denis */ +#include "mycrypt.h" + +#ifdef MRSA + +int rsa_signpad(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x, y; + + _ARGCHK(in != NULL); + _ARGCHK(out != NULL); + _ARGCHK(outlen != NULL); + + if (*outlen < (3 * inlen)) { + return CRYPT_BUFFER_OVERFLOW; + } + + /* check inlen */ + if (inlen > MAX_RSA_SIZE/8) { + return CRYPT_PK_INVALID_SIZE; + } + + for (y = x = 0; x < inlen; x++) + out[y++] = (unsigned char)0xFF; + for (x = 0; x < inlen; x++) + out[y++] = in[x]; + for (x = 0; x < inlen; x++) + out[y++] = (unsigned char)0xFF; + *outlen = 3 * inlen; + return CRYPT_OK; +} + +int rsa_pad(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + int wprng, prng_state *prng) +{ + unsigned char buf[3*(MAX_RSA_SIZE/8)]; + unsigned long x; + int err; + + _ARGCHK(in != NULL); + _ARGCHK(out != NULL); + _ARGCHK(outlen != NULL); + + /* is output big enough? */ + if (*outlen < (3 * inlen)) { + return CRYPT_BUFFER_OVERFLOW; + } + + /* get random padding required */ + if ((err = prng_is_valid(wprng)) != CRYPT_OK) { + return err; + } + + /* check inlen */ + if (inlen > (MAX_RSA_SIZE/8)) { + return CRYPT_PK_INVALID_SIZE; + } + + if (prng_descriptor[wprng].read(buf, inlen*2-2, prng) != (inlen*2 - 2)) { + return CRYPT_ERROR_READPRNG; + } + + /* 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. + */ + for (x = 0; x < inlen-1; x++) { + out[x+1] = buf[x]; + } + + for (x = 0; x < inlen; x++) { + out[x+inlen] = in[x]; + } + + for (x = 0; x < inlen-1; x++) { + out[x+inlen+inlen] = buf[x+inlen-1]; + } + + /* last and first bytes are 0xFF */ + out[0] = out[inlen+inlen+inlen-1] = (unsigned char)0xFF; + + /* clear up and return */ +#ifdef CLEAN_STACK + zeromem(buf, sizeof(buf)); +#endif + *outlen = inlen*3; + return CRYPT_OK; +} + +int rsa_signdepad(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x; + + _ARGCHK(in != NULL); + _ARGCHK(out != NULL); + _ARGCHK(outlen != NULL); + + if (*outlen < inlen/3) { + return CRYPT_BUFFER_OVERFLOW; + } + + /* check padding bytes */ + for (x = 0; x < inlen/3; x++) { + if (in[x] != (unsigned char)0xFF || in[x+(inlen/3)+(inlen/3)] != (unsigned char)0xFF) { + return CRYPT_INVALID_PACKET; + } + } + 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, + unsigned char *out, unsigned long *outlen) +{ + unsigned long x; + + _ARGCHK(in != NULL); + _ARGCHK(out != NULL); + _ARGCHK(outlen != NULL); + + if (*outlen < inlen/3) { + return CRYPT_BUFFER_OVERFLOW; + } + for (x = 0; x < inlen/3; x++) { + out[x] = in[x+(inlen/3)]; + } + *outlen = inlen/3; + return CRYPT_OK; +} + +int rsa_export(unsigned char *out, unsigned long *outlen, int type, rsa_key *key) +{ + unsigned long y, z; + int err; + + _ARGCHK(out != NULL); + _ARGCHK(outlen != NULL); + _ARGCHK(key != NULL); + + /* can we store the static header? */ + if (*outlen < (PACKET_SIZE + 1)) { + return CRYPT_BUFFER_OVERFLOW; + } + + /* type valid? */ + if (!(key->type == PK_PRIVATE || key->type == PK_PRIVATE_OPTIMIZED) && + (type == PK_PRIVATE || type == PK_PRIVATE_OPTIMIZED)) { + return CRYPT_PK_INVALID_TYPE; + } + + /* start at offset y=PACKET_SIZE */ + y = PACKET_SIZE; + + /* output key type */ + out[y++] = type; + + /* output modulus */ + OUTPUT_BIGNUM(&key->N, out, y, z); + + /* output public key */ + OUTPUT_BIGNUM(&key->e, out, y, z); + + if (type == PK_PRIVATE || type == PK_PRIVATE_OPTIMIZED) { + OUTPUT_BIGNUM(&key->d, out, y, z); + } + + if (type == PK_PRIVATE_OPTIMIZED) { + OUTPUT_BIGNUM(&key->dQ, out, y, z); + OUTPUT_BIGNUM(&key->dP, out, y, z); + OUTPUT_BIGNUM(&key->pQ, out, y, z); + OUTPUT_BIGNUM(&key->qP, out, y, z); + OUTPUT_BIGNUM(&key->p, out, y, z); + OUTPUT_BIGNUM(&key->q, out, y, z); + } + + /* store packet header */ + packet_store_header(out, PACKET_SECT_RSA, PACKET_SUB_KEY); + + /* copy to the user buffer */ + *outlen = y; + + /* clear stack and return */ + return CRYPT_OK; +} + +int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key) +{ + unsigned long x, y; + int err; + + _ARGCHK(in != NULL); + _ARGCHK(key != NULL); + + /* 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 ((err = 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 mpi_to_ltc_error(err); + } + + /* get key type */ + y = PACKET_SIZE; + key->type = (int)in[y++]; + + /* load the modulus */ + INPUT_BIGNUM(&key->N, in, x, y, inlen); + + /* load public exponent */ + INPUT_BIGNUM(&key->e, in, x, y, inlen); + + /* get private exponent */ + if (key->type == PK_PRIVATE || key->type == PK_PRIVATE_OPTIMIZED) { + INPUT_BIGNUM(&key->d, in, x, y, inlen); + } + + /* get CRT private data if required */ + if (key->type == PK_PRIVATE_OPTIMIZED) { + INPUT_BIGNUM(&key->dQ, in, x, y, inlen); + INPUT_BIGNUM(&key->dP, in, x, y, inlen); + INPUT_BIGNUM(&key->pQ, in, x, y, inlen); + INPUT_BIGNUM(&key->qP, in, x, y, inlen); + INPUT_BIGNUM(&key->p, in, x, y, inlen); + INPUT_BIGNUM(&key->q, in, x, y, inlen); + } + + /* 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); + } + if (key->type != PK_PRIVATE && key->type != PK_PRIVATE_OPTIMIZED) { + mp_clear(&key->d); + } + + return CRYPT_OK; +error: + mp_clear_multi(&key->d, &key->e, &key->N, &key->dQ, &key->dP, + &key->pQ, &key->qP, &key->p, &key->q, NULL); + return err; +} + +#include "rsa_sys.c" + +#endif /* RSA */ + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rsa_sys.c Sun Dec 19 11:47:33 2004 +0000 @@ -0,0 +1,274 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, [email protected], http://libtomcrypt.org + */ + +/* these are smaller routines written by Clay Culver. They do the same function as the rsa_encrypt/decrypt + * except that they are used to RSA encrypt/decrypt a single value and not a packet. + */ +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) +{ + unsigned char rsa_in[RSA_STACK], rsa_out[RSA_STACK]; + unsigned long x, y, rsa_size; + int err; + + _ARGCHK(inkey != NULL); + _ARGCHK(outkey != NULL); + _ARGCHK(outlen != NULL); + _ARGCHK(key != NULL); + + /* only allow keys from 64 to 256 bits */ + if (inlen < 8 || inlen > 32) { + return CRYPT_INVALID_ARG; + } + + /* are the parameters valid? */ + if ((err = prng_is_valid(wprng)) != CRYPT_OK) { + return err; + } + + /* rsa_pad the symmetric key */ + y = (unsigned long)sizeof(rsa_in); + if ((err = rsa_pad(inkey, inlen, rsa_in, &y, wprng, prng)) != CRYPT_OK) { + return CRYPT_ERROR; + } + + /* rsa encrypt it */ + rsa_size = (unsigned long)sizeof(rsa_out); + if ((err = rsa_exptmod(rsa_in, y, rsa_out, &rsa_size, PK_PUBLIC, key)) != CRYPT_OK) { + return CRYPT_ERROR; + } + + /* check size */ + if (*outlen < (PACKET_SIZE+4+rsa_size)) { + return CRYPT_BUFFER_OVERFLOW; + } + + /* store header */ + packet_store_header(outkey, PACKET_SECT_RSA, PACKET_SUB_ENC_KEY); + + /* now lets make the header */ + y = PACKET_SIZE; + + /* store the size of the RSA value */ + STORE32L(rsa_size, (outkey+y)); + y += 4; + + /* store the rsa value */ + for (x = 0; x < rsa_size; x++, y++) { + outkey[y] = rsa_out[x]; + } + + *outlen = y; +#ifdef CLEAN_STACK + /* clean up */ + zeromem(rsa_in, sizeof(rsa_in)); + zeromem(rsa_out, sizeof(rsa_out)); +#endif + + return CRYPT_OK; +} + +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_out[RSA_STACK]; + unsigned long x, y, z, i, rsa_size; + int err; + + _ARGCHK(in != NULL); + _ARGCHK(outkey != NULL); + _ARGCHK(keylen != NULL); + _ARGCHK(key != NULL); + + /* right key type? */ + if (key->type != PK_PRIVATE && key->type != PK_PRIVATE_OPTIMIZED) { + return CRYPT_PK_NOT_PRIVATE; + } + + if (inlen < PACKET_SIZE+4) { + return CRYPT_INVALID_PACKET; + } else { + inlen -= PACKET_SIZE+4; + } + + /* check the header */ + if ((err = packet_valid_header((unsigned char *)in, PACKET_SECT_RSA, PACKET_SUB_ENC_KEY)) != CRYPT_OK) { + return err; + } + + /* grab length of the rsa key */ + y = PACKET_SIZE; + LOAD32L(rsa_size, (in+y)); + if (inlen < rsa_size) { + return CRYPT_INVALID_PACKET; + } else { + inlen -= rsa_size; + } + y += 4; + + /* decrypt it */ + x = (unsigned long)sizeof(rsa_out); + if ((err = rsa_exptmod(in+y, rsa_size, rsa_out, &x, PK_PRIVATE, key)) != CRYPT_OK) { + return err; + } + y += rsa_size; + + /* depad it */ + z = (unsigned long)sizeof(sym_key); + if ((err = rsa_depad(rsa_out, x, sym_key, &z)) != CRYPT_OK) { + return err; + } + + /* check size */ + if (*keylen < z) { + return CRYPT_BUFFER_OVERFLOW; + } + + for (i = 0; i < z; i++) { + outkey[i] = sym_key[i]; + } + +#ifdef CLEAN_STACK + /* clean up */ + zeromem(sym_key, sizeof(sym_key)); + zeromem(rsa_out, sizeof(rsa_out)); +#endif + *keylen = z; + return CRYPT_OK; +} + +int rsa_sign_hash(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + rsa_key *key) +{ + unsigned long rsa_size, x, y; + unsigned char rsa_in[RSA_STACK], rsa_out[RSA_STACK]; + int err; + + _ARGCHK(in != NULL); + _ARGCHK(out != NULL); + _ARGCHK(outlen != NULL); + _ARGCHK(key != NULL); + + /* reject nonsense sizes */ + if (inlen > (512/3) || inlen < 16) { + return CRYPT_INVALID_ARG; + } + + /* type of key? */ + if (key->type != PK_PRIVATE && key->type != PK_PRIVATE_OPTIMIZED) { + return CRYPT_PK_NOT_PRIVATE; + } + + /* pad it */ + x = (unsigned long)sizeof(rsa_out); + if ((err = rsa_signpad(in, inlen, rsa_out, &x)) != CRYPT_OK) { + return err; + } + + /* sign it */ + rsa_size = (unsigned long)sizeof(rsa_in); + if ((err = rsa_exptmod(rsa_out, x, rsa_in, &rsa_size, PK_PRIVATE, key)) != CRYPT_OK) { + return err; + } + + /* check size */ + if (*outlen < (PACKET_SIZE+4+rsa_size)) { + return CRYPT_BUFFER_OVERFLOW; + } + + /* now lets output the message */ + y = PACKET_SIZE; + + /* output the len */ + STORE32L(rsa_size, (out+y)); + y += 4; + + /* store the signature */ + for (x = 0; x < rsa_size; x++, y++) { + out[y] = rsa_in[x]; + } + + /* store header */ + packet_store_header(out, PACKET_SECT_RSA, PACKET_SUB_SIGNED); + +#ifdef CLEAN_STACK + /* clean up */ + zeromem(rsa_in, sizeof(rsa_in)); + zeromem(rsa_out, sizeof(rsa_out)); +#endif + *outlen = y; + return CRYPT_OK; +} + +int rsa_verify_hash(const unsigned char *sig, unsigned long siglen, + const unsigned char *md, int *stat, rsa_key *key) +{ + unsigned long rsa_size, x, y, z; + unsigned char rsa_in[RSA_STACK], rsa_out[RSA_STACK]; + int err; + + _ARGCHK(sig != NULL); + _ARGCHK(md != NULL); + _ARGCHK(stat != NULL); + _ARGCHK(key != NULL); + + /* always be incorrect by default */ + *stat = 0; + + if (siglen < PACKET_SIZE+4) { + return CRYPT_INVALID_PACKET; + } else { + siglen -= PACKET_SIZE+4; + } + + /* verify header */ + if ((err = packet_valid_header((unsigned char *)sig, PACKET_SECT_RSA, PACKET_SUB_SIGNED)) != CRYPT_OK) { + return err; + } + + /* get the len */ + y = PACKET_SIZE; + LOAD32L(rsa_size, (sig+y)); + if (siglen < rsa_size) { + return CRYPT_INVALID_PACKET; + } else { + siglen -= rsa_size; + } + y += 4; + + /* exptmod it */ + x = (unsigned long)sizeof(rsa_out); + if ((err = rsa_exptmod(sig+y, rsa_size, rsa_out, &x, PK_PUBLIC, key)) != CRYPT_OK) { + return err; + } + y += rsa_size; + + /* depad it */ + z = (unsigned long)sizeof(rsa_in); + if ((err = rsa_signdepad(rsa_out, x, rsa_in, &z)) != CRYPT_OK) { + return err; + } + + /* check? */ + if (memcmp(rsa_in, md, (size_t)z) == 0) { + *stat = 1; + } + +#ifdef CLEAN_STACK + zeromem(rsa_in, sizeof(rsa_in)); + zeromem(rsa_out, sizeof(rsa_out)); +#endif + return CRYPT_OK; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/serpent.c Sun Dec 19 11:47:33 2004 +0000 @@ -0,0 +1,698 @@ +#include "mycrypt.h" + +#ifdef SERPENT + +const struct _cipher_descriptor serpent_desc = +{ + "serpent", + 5, + 16, 32, 16, 32, + &serpent_setup, + &serpent_ecb_encrypt, + &serpent_ecb_decrypt, + &serpent_test, + &serpent_keysize +}; + +/* These defines are derived from Brian Gladman's work. Contact him at [email protected] + * + * Available on the web at http://fp.gladman.plus.com/cryptography_technology/aes/index.htm + */ +#define sb0(a,b,c,d,e,f,g,h) \ + t1 = a ^ d; \ + t2 = a & d; \ + t3 = c ^ t1; \ + t6 = b & t1; \ + t4 = b ^ t3; \ + t10 = ~t3; \ + h = t2 ^ t4; \ + t7 = a ^ t6; \ + t14 = ~t7; \ + t8 = c | t7; \ + t11 = t3 ^ t7; \ + g = t4 ^ t8; \ + t12 = h & t11; \ + f = t10 ^ t12; \ + e = t12 ^ t14 + +/* 15 terms */ + +#define ib0(a,b,c,d,e,f,g,h) \ + t1 = ~a; \ + t2 = a ^ b; \ + t3 = t1 | t2; \ + t4 = d ^ t3; \ + t7 = d & t2; \ + t5 = c ^ t4; \ + t8 = t1 ^ t7; \ + g = t2 ^ t5; \ + t11 = a & t4; \ + t9 = g & t8; \ + t14 = t5 ^ t8; \ + f = t4 ^ t9; \ + t12 = t5 | f; \ + h = t11 ^ t12; \ + e = h ^ t14 + +/* 14 terms! */ + +#define sb1(a,b,c,d,e,f,g,h) \ + t1 = ~a; \ + t2 = b ^ t1; \ + t3 = a | t2; \ + t4 = d | t2; \ + t5 = c ^ t3; \ + g = d ^ t5; \ + t7 = b ^ t4; \ + t8 = t2 ^ g; \ + t9 = t5 & t7; \ + h = t8 ^ t9; \ + t11 = t5 ^ t7; \ + f = h ^ t11; \ + t13 = t8 & t11; \ + e = t5 ^ t13 + +/* 17 terms */ + +#define ib1(a,b,c,d,e,f,g,h) \ + t1 = a ^ d; \ + t2 = a & b; \ + t3 = b ^ c; \ + t4 = a ^ t3; \ + t5 = b | d; \ + t7 = c | t1; \ + h = t4 ^ t5; \ + t8 = b ^ t7; \ + t11 = ~t2; \ + t9 = t4 & t8; \ + f = t1 ^ t9; \ + t13 = t9 ^ t11; \ + t12 = h & f; \ + g = t12 ^ t13; \ + t15 = a & d; \ + t16 = c ^ t13; \ + e = t15 ^ t16 + +/* 16 terms */ + +#define sb2(a,b,c,d,e,f,g,h) \ + t1 = ~a; \ + t2 = b ^ d; \ + t3 = c & t1; \ + t13 = d | t1; \ + e = t2 ^ t3; \ + t5 = c ^ t1; \ + t6 = c ^ e; \ + t7 = b & t6; \ + t10 = e | t5; \ + h = t5 ^ t7; \ + t9 = d | t7; \ + t11 = t9 & t10; \ + t14 = t2 ^ h; \ + g = a ^ t11; \ + t15 = g ^ t13; \ + f = t14 ^ t15 + +/* 16 terms */ + +#define ib2(a,b,c,d,e,f,g,h) \ + t1 = b ^ d; \ + t2 = ~t1; \ + t3 = a ^ c; \ + t4 = c ^ t1; \ + t7 = a | t2; \ + t5 = b & t4; \ + t8 = d ^ t7; \ + t11 = ~t4; \ + e = t3 ^ t5; \ + t9 = t3 | t8; \ + t14 = d & t11; \ + h = t1 ^ t9; \ + t12 = e | h; \ + f = t11 ^ t12; \ + t15 = t3 ^ t12; \ + g = t14 ^ t15 + +/* 17 terms */ + +#define sb3(a,b,c,d,e,f,g,h) \ + t1 = a ^ c; \ + t2 = d ^ t1; \ + t3 = a & t2; \ + t4 = d ^ t3; \ + t5 = b & t4; \ + g = t2 ^ t5; \ + t7 = a | g; \ + t8 = b | d; \ + t11 = a | d; \ + t9 = t4 & t7; \ + f = t8 ^ t9; \ + t12 = b ^ t11; \ + t13 = g ^ t9; \ + t15 = t3 ^ t8; \ + h = t12 ^ t13; \ + t16 = c & t15; \ + e = t12 ^ t16 + +/* 16 term solution that performs less well than 17 term one + in my environment (PPro/PII) + +#define sb3(a,b,c,d,e,f,g,h) \ + t1 = a ^ b; \ + t2 = a & c; \ + t3 = a | d; \ + t4 = c ^ d; \ + t5 = t1 & t3; \ + t6 = t2 | t5; \ + g = t4 ^ t6; \ + t8 = b ^ t3; \ + t9 = t6 ^ t8; \ + t10 = t4 & t9; \ + e = t1 ^ t10; \ + t12 = g & e; \ + f = t9 ^ t12; \ + t14 = b | d; \ + t15 = t4 ^ t12; \ + h = t14 ^ t15 +*/ + +/* 17 terms */ + +#define ib3(a,b,c,d,e,f,g,h) \ + t1 = b ^ c; \ + t2 = b | c; \ + t3 = a ^ c; \ + t7 = a ^ d; \ + t4 = t2 ^ t3; \ + t5 = d | t4; \ + t9 = t2 ^ t7; \ + e = t1 ^ t5; \ + t8 = t1 | t5; \ + t11 = a & t4; \ + g = t8 ^ t9; \ + t12 = e | t9; \ + f = t11 ^ t12; \ + t14 = a & g; \ + t15 = t2 ^ t14; \ + t16 = e & t15; \ + h = t4 ^ t16 + +/* 15 terms */ + +#define sb4(a,b,c,d,e,f,g,h) \ + t1 = a ^ d; \ + t2 = d & t1; \ + t3 = c ^ t2; \ + t4 = b | t3; \ + h = t1 ^ t4; \ + t6 = ~b; \ + t7 = t1 | t6; \ + e = t3 ^ t7; \ + t9 = a & e; \ + t10 = t1 ^ t6; \ + t11 = t4 & t10; \ + g = t9 ^ t11; \ + t13 = a ^ t3; \ + t14 = t10 & g; \ + f = t13 ^ t14 + +/* 17 terms */ + +#define ib4(a,b,c,d,e,f,g,h) \ + t1 = c ^ d; \ + t2 = c | d; \ + t3 = b ^ t2; \ + t4 = a & t3; \ + f = t1 ^ t4; \ + t6 = a ^ d; \ + t7 = b | d; \ + t8 = t6 & t7; \ + h = t3 ^ t8; \ + t10 = ~a; \ + t11 = c ^ h; \ + t12 = t10 | t11;\ + e = t3 ^ t12; \ + t14 = c | t4; \ + t15 = t7 ^ t14; \ + t16 = h | t10; \ + g = t15 ^ t16 + +/* 16 terms */ + +#define sb5(a,b,c,d,e,f,g,h) \ + t1 = ~a; \ + t2 = a ^ b; \ + t3 = a ^ d; \ + t4 = c ^ t1; \ + t5 = t2 | t3; \ + e = t4 ^ t5; \ + t7 = d & e; \ + t8 = t2 ^ e; \ + t10 = t1 | e; \ + f = t7 ^ t8; \ + t11 = t2 | t7; \ + t12 = t3 ^ t10; \ + t14 = b ^ t7; \ + g = t11 ^ t12; \ + t15 = f & t12; \ + h = t14 ^ t15 + +/* 16 terms */ + +#define ib5(a,b,c,d,e,f,g,h) \ + t1 = ~c; \ + t2 = b & t1; \ + t3 = d ^ t2; \ + t4 = a & t3; \ + t5 = b ^ t1; \ + h = t4 ^ t5; \ + t7 = b | h; \ + t8 = a & t7; \ + f = t3 ^ t8; \ + t10 = a | d; \ + t11 = t1 ^ t7; \ + e = t10 ^ t11; \ + t13 = a ^ c; \ + t14 = b & t10; \ + t15 = t4 | t13; \ + g = t14 ^ t15 + +/* 15 terms */ + +#define sb6(a,b,c,d,e,f,g,h) \ + t1 = ~a; \ + t2 = a ^ d; \ + t3 = b ^ t2; \ + t4 = t1 | t2; \ + t5 = c ^ t4; \ + f = b ^ t5; \ + t13 = ~t5; \ + t7 = t2 | f; \ + t8 = d ^ t7; \ + t9 = t5 & t8; \ + g = t3 ^ t9; \ + t11 = t5 ^ t8; \ + e = g ^ t11; \ + t14 = t3 & t11; \ + h = t13 ^ t14 + +/* 15 terms */ + +#define ib6(a,b,c,d,e,f,g,h) \ + t1 = ~a; \ + t2 = a ^ b; \ + t3 = c ^ t2; \ + t4 = c | t1; \ + t5 = d ^ t4; \ + t13 = d & t1; \ + f = t3 ^ t5; \ + t7 = t3 & t5; \ + t8 = t2 ^ t7; \ + t9 = b | t8; \ + h = t5 ^ t9; \ + t11 = b | h; \ + e = t8 ^ t11; \ + t14 = t3 ^ t11; \ + g = t13 ^ t14 + +/* 17 terms */ + +#define sb7(a,b,c,d,e,f,g,h) \ + t1 = ~c; \ + t2 = b ^ c; \ + t3 = b | t1; \ + t4 = d ^ t3; \ + t5 = a & t4; \ + t7 = a ^ d; \ + h = t2 ^ t5; \ + t8 = b ^ t5; \ + t9 = t2 | t8; \ + t11 = d & t3; \ + f = t7 ^ t9; \ + t12 = t5 ^ f; \ + t15 = t1 | t4; \ + t13 = h & t12; \ + g = t11 ^ t13; \ + t16 = t12 ^ g; \ + e = t15 ^ t16 + +/* 17 terms */ + +#define ib7(a,b,c,d,e,f,g,h) \ + t1 = a & b; \ + t2 = a | b; \ + t3 = c | t1; \ + t4 = d & t2; \ + h = t3 ^ t4; \ + t6 = ~d; \ + t7 = b ^ t4; \ + t8 = h ^ t6; \ + t11 = c ^ t7; \ + t9 = t7 | t8; \ + f = a ^ t9; \ + t12 = d | f; \ + e = t11 ^ t12; \ + t14 = a & h; \ + t15 = t3 ^ f; \ + t16 = e ^ t14; \ + g = t15 ^ t16 + +#define k_xor(r,a,b,c,d) \ + a ^= skey->serpent.K[4 * (r) + 0]; \ + b ^= skey->serpent.K[4 * (r) + 1]; \ + c ^= skey->serpent.K[4 * (r) + 2]; \ + d ^= skey->serpent.K[4 * (r) + 3] + +#define k_set(r,a,b,c,d) \ + a = lkey[4 * (r) + 8]; \ + b = lkey[4 * (r) + 9]; \ + c = lkey[4 * (r) + 10]; \ + d = lkey[4 * (r) + 11] + +#define k_get(r,a,b,c,d) \ + skey->serpent.K[4 * (r) + 0] = a; \ + skey->serpent.K[4 * (r) + 1] = b; \ + skey->serpent.K[4 * (r) + 2] = c; \ + skey->serpent.K[4 * (r) + 3] = d + +/* the linear transformation and its inverse */ + +#define rot(a,b,c,d) \ + a = ROL(a, 13); \ + c = ROL(c, 3); \ + d ^= c ^ (a << 3); \ + b ^= a ^ c; \ + d = ROL(d, 7); \ + b = ROL(b, 1); \ + a ^= b ^ d; \ + c ^= d ^ (b << 7); \ + a = ROL(a, 5); \ + c = ROL(c, 22) + +#define irot(a,b,c,d) \ + c = ROR(c, 22); \ + a = ROR(a, 5); \ + c ^= d ^ (b << 7); \ + a ^= b ^ d; \ + d = ROR(d, 7); \ + b = ROR(b, 1); \ + d ^= c ^ (a << 3); \ + b ^= a ^ c; \ + c = ROR(c, 3); \ + a = ROR(a, 13) + +#ifdef CLEAN_STACK +static int _serpent_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +#else +int serpent_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +#endif +{ + unsigned long lkey[140], t, a, b, c, d, e, f, g, h, x; + unsigned long t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16; + unsigned char buf[32]; + + _ARGCHK(key != NULL); + _ARGCHK(skey != NULL); + + /* check rounds */ + if (num_rounds != 0 && num_rounds != 32) { + return CRYPT_INVALID_ROUNDS; + } + + /* check keylen */ + if (keylen < 16 || keylen > 32) { + return CRYPT_INVALID_KEYSIZE; + } + + /* copy key and expand to 32bytes as required */ + for (x = 0; x < (unsigned long)keylen; x++) { + buf[x] = key[x]; + } + + if (x < 32) { + buf[x++] = (unsigned char)0x01; + while (x < 32) { + buf[x++] = (unsigned char)0; + } + } + + /* copy key into 32-bit words */ + for (x = 0; x < 8; x++) { + LOAD32L(lkey[x], &buf[x*4]); + } + + /* expand using the LFSR to 140 words */ + for (x = 0; x < 132; x++) { + t = lkey[x] ^ lkey[x+3] ^ lkey[x+5] ^ lkey[x+7] ^ x ^ 0x9E3779B9UL; + lkey[x + 8] = ROL(t, 11); + } + + /* perform the substituions */ + for (x = 0; x < 32; ) { + k_set( x,a,b,c,d);sb3(a,b,c,d,e,f,g,h);k_get( x,e,f,g,h); ++x; + k_set( x,a,b,c,d);sb2(a,b,c,d,e,f,g,h);k_get( x,e,f,g,h); ++x; + k_set( x,a,b,c,d);sb1(a,b,c,d,e,f,g,h);k_get( x,e,f,g,h); ++x; + k_set( x,a,b,c,d);sb0(a,b,c,d,e,f,g,h);k_get( x,e,f,g,h); ++x; + k_set( x,a,b,c,d);sb7(a,b,c,d,e,f,g,h);k_get( x,e,f,g,h); ++x; + k_set( x,a,b,c,d);sb6(a,b,c,d,e,f,g,h);k_get( x,e,f,g,h); ++x; + k_set( x,a,b,c,d);sb5(a,b,c,d,e,f,g,h);k_get( x,e,f,g,h); ++x; + k_set( x,a,b,c,d);sb4(a,b,c,d,e,f,g,h);k_get( x,e,f,g,h); ++x; + } + k_set(32,a,b,c,d);sb3(a,b,c,d,e,f,g,h);k_get(32,e,f,g,h); + return CRYPT_OK; +} + +#ifdef CLEAN_STACK +int serpent_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey) +{ + int x; + x = _serpent_setup(key, keylen, num_rounds, skey); + burn_stack(sizeof(unsigned long)*166 + sizeof(unsigned char)*32); + return x; +} +#endif + +#ifdef CLEAN_STACK +static void _serpent_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey) +#else +void serpent_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey) +#endif +{ + unsigned long a,b,c,d,e,f,g,h; + unsigned long t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16; + + _ARGCHK(pt != NULL); + _ARGCHK(ct != NULL); + _ARGCHK(skey != NULL); + + LOAD32L(a, &pt[0]);LOAD32L(b, &pt[4]);LOAD32L(c, &pt[8]);LOAD32L(d, &pt[12]); + k_xor( 0,a,b,c,d); sb0(a,b,c,d,e,f,g,h); rot(e,f,g,h); + k_xor( 1,e,f,g,h); sb1(e,f,g,h,a,b,c,d); rot(a,b,c,d); + k_xor( 2,a,b,c,d); sb2(a,b,c,d,e,f,g,h); rot(e,f,g,h); + k_xor( 3,e,f,g,h); sb3(e,f,g,h,a,b,c,d); rot(a,b,c,d); + k_xor( 4,a,b,c,d); sb4(a,b,c,d,e,f,g,h); rot(e,f,g,h); + k_xor( 5,e,f,g,h); sb5(e,f,g,h,a,b,c,d); rot(a,b,c,d); + k_xor( 6,a,b,c,d); sb6(a,b,c,d,e,f,g,h); rot(e,f,g,h); + k_xor( 7,e,f,g,h); sb7(e,f,g,h,a,b,c,d); rot(a,b,c,d); + k_xor( 8,a,b,c,d); sb0(a,b,c,d,e,f,g,h); rot(e,f,g,h); + k_xor( 9,e,f,g,h); sb1(e,f,g,h,a,b,c,d); rot(a,b,c,d); + k_xor(10,a,b,c,d); sb2(a,b,c,d,e,f,g,h); rot(e,f,g,h); + k_xor(11,e,f,g,h); sb3(e,f,g,h,a,b,c,d); rot(a,b,c,d); + k_xor(12,a,b,c,d); sb4(a,b,c,d,e,f,g,h); rot(e,f,g,h); + k_xor(13,e,f,g,h); sb5(e,f,g,h,a,b,c,d); rot(a,b,c,d); + k_xor(14,a,b,c,d); sb6(a,b,c,d,e,f,g,h); rot(e,f,g,h); + k_xor(15,e,f,g,h); sb7(e,f,g,h,a,b,c,d); rot(a,b,c,d); + k_xor(16,a,b,c,d); sb0(a,b,c,d,e,f,g,h); rot(e,f,g,h); + k_xor(17,e,f,g,h); sb1(e,f,g,h,a,b,c,d); rot(a,b,c,d); + k_xor(18,a,b,c,d); sb2(a,b,c,d,e,f,g,h); rot(e,f,g,h); + k_xor(19,e,f,g,h); sb3(e,f,g,h,a,b,c,d); rot(a,b,c,d); + k_xor(20,a,b,c,d); sb4(a,b,c,d,e,f,g,h); rot(e,f,g,h); + k_xor(21,e,f,g,h); sb5(e,f,g,h,a,b,c,d); rot(a,b,c,d); + k_xor(22,a,b,c,d); sb6(a,b,c,d,e,f,g,h); rot(e,f,g,h); + k_xor(23,e,f,g,h); sb7(e,f,g,h,a,b,c,d); rot(a,b,c,d); + k_xor(24,a,b,c,d); sb0(a,b,c,d,e,f,g,h); rot(e,f,g,h); + k_xor(25,e,f,g,h); sb1(e,f,g,h,a,b,c,d); rot(a,b,c,d); + k_xor(26,a,b,c,d); sb2(a,b,c,d,e,f,g,h); rot(e,f,g,h); + k_xor(27,e,f,g,h); sb3(e,f,g,h,a,b,c,d); rot(a,b,c,d); + k_xor(28,a,b,c,d); sb4(a,b,c,d,e,f,g,h); rot(e,f,g,h); + k_xor(29,e,f,g,h); sb5(e,f,g,h,a,b,c,d); rot(a,b,c,d); + k_xor(30,a,b,c,d); sb6(a,b,c,d,e,f,g,h); rot(e,f,g,h); + k_xor(31,e,f,g,h); sb7(e,f,g,h,a,b,c,d); k_xor(32,a,b,c,d); + STORE32L(a, &ct[0]);STORE32L(b, &ct[4]);STORE32L(c, &ct[8]);STORE32L(d, &ct[12]); +} + +#ifdef CLEAN_STACK +void serpent_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey) +{ + _serpent_ecb_encrypt(pt, ct, skey); + burn_stack(sizeof(unsigned long)*24); +} +#endif + +#ifdef CLEAN_STACK +static void _serpent_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey) +#else +void serpent_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey) +#endif +{ + unsigned long a,b,c,d,e,f,g,h; + unsigned long t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11,t12,t13,t14,t15,t16; + + _ARGCHK(pt != NULL); + _ARGCHK(ct != NULL); + _ARGCHK(skey != NULL); + + LOAD32L(a, &ct[0]);LOAD32L(b, &ct[4]);LOAD32L(c, &ct[8]);LOAD32L(d, &ct[12]); + k_xor(32,a,b,c,d); ib7(a,b,c,d,e,f,g,h); k_xor(31,e,f,g,h); + irot(e,f,g,h); ib6(e,f,g,h,a,b,c,d); k_xor(30,a,b,c,d); + irot(a,b,c,d); ib5(a,b,c,d,e,f,g,h); k_xor(29,e,f,g,h); + irot(e,f,g,h); ib4(e,f,g,h,a,b,c,d); k_xor(28,a,b,c,d); + irot(a,b,c,d); ib3(a,b,c,d,e,f,g,h); k_xor(27,e,f,g,h); + irot(e,f,g,h); ib2(e,f,g,h,a,b,c,d); k_xor(26,a,b,c,d); + irot(a,b,c,d); ib1(a,b,c,d,e,f,g,h); k_xor(25,e,f,g,h); + irot(e,f,g,h); ib0(e,f,g,h,a,b,c,d); k_xor(24,a,b,c,d); + irot(a,b,c,d); ib7(a,b,c,d,e,f,g,h); k_xor(23,e,f,g,h); + irot(e,f,g,h); ib6(e,f,g,h,a,b,c,d); k_xor(22,a,b,c,d); + irot(a,b,c,d); ib5(a,b,c,d,e,f,g,h); k_xor(21,e,f,g,h); + irot(e,f,g,h); ib4(e,f,g,h,a,b,c,d); k_xor(20,a,b,c,d); + irot(a,b,c,d); ib3(a,b,c,d,e,f,g,h); k_xor(19,e,f,g,h); + irot(e,f,g,h); ib2(e,f,g,h,a,b,c,d); k_xor(18,a,b,c,d); + irot(a,b,c,d); ib1(a,b,c,d,e,f,g,h); k_xor(17,e,f,g,h); + irot(e,f,g,h); ib0(e,f,g,h,a,b,c,d); k_xor(16,a,b,c,d); + irot(a,b,c,d); ib7(a,b,c,d,e,f,g,h); k_xor(15,e,f,g,h); + irot(e,f,g,h); ib6(e,f,g,h,a,b,c,d); k_xor(14,a,b,c,d); + irot(a,b,c,d); ib5(a,b,c,d,e,f,g,h); k_xor(13,e,f,g,h); + irot(e,f,g,h); ib4(e,f,g,h,a,b,c,d); k_xor(12,a,b,c,d); + irot(a,b,c,d); ib3(a,b,c,d,e,f,g,h); k_xor(11,e,f,g,h); + irot(e,f,g,h); ib2(e,f,g,h,a,b,c,d); k_xor(10,a,b,c,d); + irot(a,b,c,d); ib1(a,b,c,d,e,f,g,h); k_xor( 9,e,f,g,h); + irot(e,f,g,h); ib0(e,f,g,h,a,b,c,d); k_xor( 8,a,b,c,d); + irot(a,b,c,d); ib7(a,b,c,d,e,f,g,h); k_xor( 7,e,f,g,h); + irot(e,f,g,h); ib6(e,f,g,h,a,b,c,d); k_xor( 6,a,b,c,d); + irot(a,b,c,d); ib5(a,b,c,d,e,f,g,h); k_xor( 5,e,f,g,h); + irot(e,f,g,h); ib4(e,f,g,h,a,b,c,d); k_xor( 4,a,b,c,d); + irot(a,b,c,d); ib3(a,b,c,d,e,f,g,h); k_xor( 3,e,f,g,h); + irot(e,f,g,h); ib2(e,f,g,h,a,b,c,d); k_xor( 2,a,b,c,d); + irot(a,b,c,d); ib1(a,b,c,d,e,f,g,h); k_xor( 1,e,f,g,h); + irot(e,f,g,h); ib0(e,f,g,h,a,b,c,d); k_xor( 0,a,b,c,d); + STORE32L(a, &pt[0]);STORE32L(b, &pt[4]);STORE32L(c, &pt[8]);STORE32L(d, &pt[12]); +} + +#ifdef CLEAN_STACK +void serpent_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey) +{ + _serpent_ecb_decrypt(ct, pt, skey); + burn_stack(sizeof(unsigned long)*24); +} +#endif + +int serpent_test(void) +{ + static const struct { + int keylen; + unsigned char key[32], pt[16], ct[16]; + } tests[] = { + { + 16, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xdd, 0xd2, 0x6b, 0x98, 0xa5, 0xff, 0xd8, 0x2c, + 0x05, 0x34, 0x5a, 0x9d, 0xad, 0xbf, 0xaf, 0x49 } + }, + { + 16, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80 }, + { 0x4a, 0xe9, 0xa2, 0x0b, 0x2b, 0x14, 0xa1, 0x02, + 0x90, 0xcb, 0xb8, 0x20, 0xb7, 0xff, 0xb5, 0x10 } + }, + { + 24, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08 }, + { 0xe1, 0x1b, 0x01, 0x52, 0x4e, 0xa1, 0xf4, 0x65, + 0xa2, 0xa2, 0x00, 0x43, 0xeb, 0x9f, 0x7e, 0x8a } + }, + { + 32, + { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xe0, 0x88, 0x5d, 0x44, 0x60, 0x37, 0x34, 0x69, + 0xd1, 0xfa, 0x6c, 0x36, 0xa6, 0xe1, 0xc5, 0x2f } + }, + { + 32, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x17, 0xc6, 0x25, 0x8e, 0x60, 0x09, 0xe2, 0x82, + 0x66, 0x18, 0x69, 0xd5, 0x25, 0xf7, 0xd2, 0x04 } + }, + { + 32, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x9f, 0xe1, 0x43, 0x25, 0x0d, 0x00, 0xe2, 0x56, + 0x96, 0xb0, 0x1e, 0x0a, 0x2e, 0xd0, 0x5d, 0xb3 } + } + }; + + unsigned char buf[2][16]; + int x, err; + symmetric_key key; + + for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) { + /* setup key */ + if ((err = serpent_setup(tests[x].key, tests[x].keylen, 0, &key))!= CRYPT_OK) { + return err; + } + + /* encrypt and decrypt */ + serpent_ecb_encrypt(tests[x].pt, buf[0], &key); + serpent_ecb_decrypt(buf[0], buf[1], &key); + + /* compare */ + if (memcmp(buf[0], tests[x].ct, 16) != 0 || memcmp(buf[1], tests[x].pt, 16) != 0) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +} + +int serpent_keysize(int *desired_keysize) +{ + _ARGCHK(desired_keysize != NULL); + + if (*desired_keysize < 16) + return CRYPT_INVALID_KEYSIZE; + if (*desired_keysize > 32) + *desired_keysize = 32; + return CRYPT_OK; +} + +#endif + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/strings.c Sun Dec 19 11:47:33 2004 +0000 @@ -0,0 +1,86 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis + * + * LibTomCrypt is a library that provides various cryptographic + * algorithms in a highly modular and flexible manner. + * + * The library is free for all purposes without any express + * guarantee it works. + * + * Tom St Denis, [email protected], http://libtomcrypt.org + */ + +/* Future releases will make use of this */ +#include "mycrypt.h" + +static const char *err_2_str[] = +{ + "CRYPT_OK", + "CRYPT_ERROR", + "Non-fatal 'no-operation' requested.", + + "Invalid keysize for block cipher.", + "Invalid number of rounds for block cipher.", + "Algorithm failed test vectors.", + + "Buffer overflow.", + "Invalid input packet.", + + "Invalid number of bits for a PRNG.", + "Error reading the PRNG.", + + "Invalid cipher specified.", + "Invalid hash specified.", + "Invalid PRNG specified.", + + "Out of memory.", + + "Invalid PK key or key type specified for function.", + "A private PK key is required.", + + "Invalid argument provided.", + "File Not Found", + + "Invalid PK type.", + "Invalid PK system.", + "Duplicate PK key found on keyring.", + "Key not found in keyring.", + "Invalid sized parameter.", + + "Invalid size for prime.", + +}; + +#ifdef MPI +static const struct { + int mpi_code, ltc_code; +} mpi_to_ltc_codes[] = { + { MP_OKAY , CRYPT_OK}, + { MP_MEM , CRYPT_MEM}, + { MP_VAL , CRYPT_INVALID_ARG}, +}; +#endif + +const char *error_to_string(int err) +{ + if (err < 0 || err >= (int)(sizeof(err_2_str)/sizeof(err_2_str[0]))) { + return "Invalid error code."; + } else { + return err_2_str[err]; + } +} + +#ifdef MPI +/* convert a MPI error to a LTC error (Possibly the most powerful function ever! Oh wait... no) */ +int mpi_to_ltc_error(int err) +{ + int x; + + for (x = 0; x < (int)(sizeof(mpi_to_ltc_codes)/sizeof(mpi_to_ltc_codes[0])); x++) { + if (err == mpi_to_ltc_codes[x].mpi_code) { + return mpi_to_ltc_codes[x].ltc_code; + } + } + return CRYPT_ERROR; +} +#endif +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tommath.h Sun Dec 19 11:47:33 2004 +0000 @@ -0,0 +1,558 @@ +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is a library that provides multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library was 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, [email protected], http://math.libtomcrypt.org + */ +#ifndef BN_H_ +#define BN_H_ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <ctype.h> +#include <limits.h> + +#define NO_LTM_TOOM 1 + +#undef MIN +#define MIN(x,y) ((x)<(y)?(x):(y)) +#undef MAX +#define MAX(x,y) ((x)>(y)?(x):(y)) + +#ifdef __cplusplus +extern "C" { + +/* C++ compilers don't like assigning void * to mp_digit * */ +#define OPT_CAST(x) (x *) + +#else + +/* C on the other hand doesn't care */ +#define OPT_CAST(x) + +#endif + +/* 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 + * + * 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; + typedef unsigned short mp_word; +#elif defined(MP_16BIT) + typedef unsigned short mp_digit; + typedef unsigned long mp_word; +#elif defined(MP_64BIT) + /* for GCC only on supported platforms */ +#ifndef CRYPT + 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 + + typedef unsigned long mp_digit; + typedef ulong64 mp_word; + +#ifdef MP_31BIT + /* this is an extension that uses 31-bit digits */ + #define DIGIT_BIT 31 +#else + /* default case is 28-bit digits, defines MP_28BIT as a handy macro to test */ + #define DIGIT_BIT 28 + #define MP_28BIT +#endif +#endif + +/* define heap macros */ +#ifndef CRYPT + /* default to libc stuff */ + #ifndef XMALLOC + #define XMALLOC malloc + #define XFREE free + #define XREALLOC realloc + #define XCALLOC calloc + #else + /* prototypes for our heap functions */ + extern void *XMALLOC(size_t n); + extern void *REALLOC(void *p, size_t n); + extern void *XCALLOC(size_t n, size_t s); + extern void XFREE(void *p); + #endif +#endif + + +/* otherwise the bits per digit is calculated automatically from the size of a mp_digit */ +#ifndef DIGIT_BIT + #define DIGIT_BIT ((int)((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 + +/* equalities */ +#define MP_LT -1 /* less than */ +#define MP_EQ 0 /* equal to */ +#define MP_GT 1 /* greater than */ + +#define MP_ZPOS 0 /* positive integer */ +#define MP_NEG 1 /* negative */ + +#define MP_OKAY 0 /* ok result */ +#define MP_MEM -2 /* out of mem */ +#define MP_VAL -3 /* invalid input */ +#define MP_RANGE MP_VAL + +#define MP_YES 1 /* yes response */ +#define MP_NO 0 /* no response */ + +/* Primality generation flags */ +#define LTM_PRIME_BBS 0x0001 /* BBS style prime */ +#define LTM_PRIME_SAFE 0x0002 /* Safe prime (p-1)/2 == prime */ +#define LTM_PRIME_2MSB_OFF 0x0004 /* force 2nd MSB to 0 */ +#define LTM_PRIME_2MSB_ON 0x0008 /* force 2nd MSB to 1 */ + +typedef int mp_err; + +/* you'll have to tune these... */ +extern int KARATSUBA_MUL_CUTOFF, + KARATSUBA_SQR_CUTOFF, + TOOM_MUL_CUTOFF, + TOOM_SQR_CUTOFF; + +/* define this to use lower memory usage routines (exptmods mostly) */ +/* #define MP_LOW_MEM */ + +/* default precision */ +#ifndef MP_PREC + #ifdef MP_LOW_MEM + #define MP_PREC 64 /* default digits of precision */ + #else + #define MP_PREC 8 /* default digits of precision */ + #endif +#endif + +/* 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)) + +/* the infamous mp_int structure */ +typedef struct { + int used, alloc, sign; + mp_digit *dp; +} mp_int; + +/* callback for mp_prime_random, should fill dst with random bytes and return how many read [upto len] */ +typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat); + + +#define USED(m) ((m)->used) +#define DIGIT(m,k) ((m)->dp[(k)]) +#define SIGN(m) ((m)->sign) + +/* error code to char* string */ +char *mp_error_to_string(int code); + +/* ---> init and deinit bignum functions <--- */ +/* init a bignum */ +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); + +/* shrink ram required for a bignum */ +int mp_shrink(mp_int *a); + +/* grow an int to a given size */ +int mp_grow(mp_int *a, int size); + +/* init to a given number of digits */ +int mp_init_size(mp_int *a, int size); + +/* ---> Basic Manipulations <--- */ +#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO) +#define mp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO) +#define mp_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO) + +/* set to zero */ +void mp_zero(mp_int *a); + +/* set to a digit */ +void mp_set(mp_int *a, mp_digit b); + +/* set a 32-bit const */ +int mp_set_int(mp_int *a, unsigned long b); + +/* get a 32-bit value */ +unsigned long mp_get_int(mp_int * a); + +/* initialize and set a digit */ +int mp_init_set (mp_int * a, mp_digit b); + +/* initialize and set 32-bit value */ +int mp_init_set_int (mp_int * a, unsigned long b); + +/* copy, b = a */ +int mp_copy(mp_int *a, mp_int *b); + +/* inits and copies, a = b */ +int mp_init_copy(mp_int *a, mp_int *b); + +/* trim unused digits */ +void mp_clamp(mp_int *a); + +/* ---> digit manipulation <--- */ + +/* right shift by "b" digits */ +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 */ +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 */ +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 */ +int mp_mod_2d(mp_int *a, int b, mp_int *c); + +/* computes a = 2**b */ +int mp_2expt(mp_int *a, int b); + +/* Counts the number of lsbs which are zero before the first zero bit */ +int mp_cnt_lsb(mp_int *a); + +/* I Love Earth! */ + +/* makes a pseudo-random int of a given size */ +int mp_rand(mp_int *a, int digits); + +/* ---> binary operations <--- */ +/* c = a XOR b */ +int mp_xor(mp_int *a, mp_int *b, mp_int *c); + +/* c = a OR b */ +int mp_or(mp_int *a, mp_int *b, mp_int *c); + +/* c = a AND b */ +int mp_and(mp_int *a, mp_int *b, mp_int *c); + +/* ---> Basic arithmetic <--- */ + +/* b = -a */ +int mp_neg(mp_int *a, mp_int *b); + +/* b = |a| */ +int mp_abs(mp_int *a, mp_int *b); + +/* compare a to b */ +int mp_cmp(mp_int *a, mp_int *b); + +/* compare |a| to |b| */ +int mp_cmp_mag(mp_int *a, mp_int *b); + +/* c = a + b */ +int mp_add(mp_int *a, mp_int *b, mp_int *c); + +/* c = a - b */ +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*a */ +int mp_sqr(mp_int *a, mp_int *b); + +/* a/b => cb + d == a */ +int mp_div(mp_int *a, mp_int *b, mp_int *c, mp_int *d); + +/* c = a mod b, 0 <= c < b */ +int mp_mod(mp_int *a, mp_int *b, mp_int *c); + +/* ---> single digit functions <--- */ + +/* compare against a single digit */ +int mp_cmp_d(mp_int *a, mp_digit b); + +/* c = a + b */ +int mp_add_d(mp_int *a, mp_digit b, mp_int *c); + +/* c = a - b */ +int mp_sub_d(mp_int *a, mp_digit b, mp_int *c); + +/* c = a * b */ +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); + +/* 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 */ +int mp_mod_d(mp_int *a, mp_digit b, mp_digit *c); + +/* ---> number theory <--- */ + +/* d = a + b (mod c) */ +int mp_addmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d); + +/* d = a - b (mod c) */ +int mp_submod(mp_int *a, mp_int *b, mp_int *c, mp_int *d); + +/* d = a * b (mod c) */ +int mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d); + +/* c = a * a (mod b) */ +int mp_sqrmod(mp_int *a, mp_int *b, mp_int *c); + +/* c = 1/a (mod b) */ +int mp_invmod(mp_int *a, mp_int *b, mp_int *c); + +/* c = (a, b) */ +int mp_gcd(mp_int *a, mp_int *b, mp_int *c); + +/* produces value such that U1*a + U2*b = U3 */ +int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3); + +/* 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| + * + * returns error if a < 0 and b is even + */ +int mp_n_root(mp_int *a, mp_digit b, mp_int *c); + +/* special sqrt algo */ +int mp_sqrt(mp_int *arg, mp_int *ret); + +/* is number a square? */ +int mp_is_square(mp_int *arg, int *ret); + +/* computes the jacobi c = (a | n) (or Legendre if b is prime) */ +int mp_jacobi(mp_int *a, mp_int *n, int *c); + +/* used to setup the Barrett reduction for a given modulus b */ +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*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); + +/* 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 + * normalizing numbers in a Montgomery system. + */ +int mp_montgomery_calc_normalization(mp_int *a, mp_int *b); + +/* 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 */ +int mp_dr_is_modulus(mp_int *a); + +/* sets the value of "d" required for mp_dr_reduce */ +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); + +/* 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 d); + +/* d = a**b (mod c) */ +int mp_exptmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d); + +/* ---> 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 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 + */ +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 + */ +int mp_prime_miller_rabin(mp_int *a, mp_int *b, int *result); + +/* This gives [for a given bit size] the number of trials required + * such that Miller-Rabin gives a prob of failure lower than 2^-96 + */ +int mp_prime_rabin_miller_trials(int size); + +/* 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. + * + * Sets result to 1 if probably prime, 0 otherwise + */ +int mp_prime_is_prime(mp_int *a, int t, int *result); + +/* finds the next prime after the number "a" using "t" trials + * of Miller-Rabin. + * + * bbs_style = 1 means the prime must be congruent to 3 mod 4 + */ +int mp_prime_next_prime(mp_int *a, int t, int bbs_style); + +/* makes a truly random prime of a given size (bytes), + * call with bbs = 1 if you want it to be congruent to 3 mod 4 + * + * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can + * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself + * so it can be NULL + * + * The prime generated will be larger than 2^(8*size). + */ +#define mp_prime_random(a, t, size, bbs, cb, dat) mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?LTM_PRIME_BBS:0, cb, dat) + +/* makes a truly random prime of a given size (bits), + * + * Flags are as follows: + * + * LTM_PRIME_BBS - make prime congruent to 3 mod 4 + * LTM_PRIME_SAFE - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS) + * LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero + * LTM_PRIME_2MSB_ON - make the 2nd highest bit one + * + * You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can + * have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself + * so it can be NULL + * + */ +int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat); + +/* ---> radix conversion <--- */ +int mp_count_bits(mp_int *a); + +int mp_unsigned_bin_size(mp_int *a); +int mp_read_unsigned_bin(mp_int *a, unsigned char *b, int c); +int mp_to_unsigned_bin(mp_int *a, unsigned char *b); + +int mp_signed_bin_size(mp_int *a); +int mp_read_signed_bin(mp_int *a, unsigned char *b, int c); +int mp_to_signed_bin(mp_int *a, unsigned char *b); + +int mp_read_radix(mp_int *a, char *str, int radix); +int mp_toradix(mp_int *a, char *str, int radix); +int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen); +int mp_radix_size(mp_int *a, int radix, int *size); + +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)) +#define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len)) +#define mp_mag_size(mp) mp_unsigned_bin_size(mp) +#define mp_tomag(mp, str) mp_to_unsigned_bin((mp), (str)) + +#define mp_tobinary(M, S) mp_toradix((M), (S), 2) +#define mp_tooctal(M, S) mp_toradix((M), (S), 8) +#define mp_todecimal(M, S) mp_toradix((M), (S), 10) +#define mp_tohex(M, S) mp_toradix((M), (S), 16) + +/* lowlevel functions, do not call! */ +int s_mp_add(mp_int *a, mp_int *b, mp_int *c); +int s_mp_sub(mp_int *a, mp_int *b, mp_int *c); +#define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1) +int fast_s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs); +int s_mp_mul_digs(mp_int *a, mp_int *b, mp_int *c, int digs); +int fast_s_mp_mul_high_digs(mp_int *a, mp_int *b, mp_int *c, int digs); +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); + +extern const char *mp_s_rmap; + +#ifdef __cplusplus + } +#endif + +#endif +