mirror of
https://github.com/clearml/dropbear
synced 2025-06-26 18:17:32 +00:00
propagate of 3f8f752126017cbe7d93c4086c27a91550df745f and 747ebf284d40a15b338e5a5c7730ecec6eade3d7 from branch 'au.asn.ucc.matt.ltc-orig' to 'au.asn.ucc.matt.ltc-db'
--HG-- branch : libtomcrypt extra : convert_revision : 6abc32a16c5814f6a46957d95c1cc4c5a3f63191
This commit is contained in:
@@ -15,7 +15,8 @@ VERSION=0.99
|
||||
#ARFLAGS=r
|
||||
|
||||
# Compilation flags. Note the += does not write over the user's CFLAGS!
|
||||
CFLAGS += -c -I./ -Wall -Wsign-compare -W -Wshadow
|
||||
# The rest of the flags come from the parent Dropbear makefile
|
||||
CFLAGS += -c -I$(srcdir)
|
||||
# -Werror
|
||||
|
||||
# optimize for SPEED
|
||||
@@ -25,7 +26,7 @@ CFLAGS += -c -I./ -Wall -Wsign-compare -W -Wshadow
|
||||
#CFLAGS += -fomit-frame-pointer
|
||||
|
||||
# optimize for SIZE
|
||||
CFLAGS += -Os -DSMALL_CODE
|
||||
#CFLAGS += -Os -DSMALL_CODE
|
||||
|
||||
# compile for DEBUGING (required for ccmalloc checking!!!)
|
||||
#CFLAGS += -g3
|
||||
@@ -51,7 +52,9 @@ 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
|
||||
#MPIOBJECT=mpi.o
|
||||
#Dropbear uses libtommath
|
||||
MPIOBJECT=
|
||||
|
||||
OBJECTS=error_to_string.o mpi_to_ltc_error.o base64_encode.o base64_decode.o \
|
||||
\
|
||||
@@ -138,14 +141,14 @@ COMPRESSED=crypt-$(VERSION).tar.bz2 crypt-$(VERSION).zip
|
||||
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
|
||||
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 aes.c -o aes_enc.o
|
||||
$(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
|
||||
@@ -161,6 +164,7 @@ library: $(LIBNAME)
|
||||
|
||||
$(LIBNAME): $(OBJECTS)
|
||||
$(AR) $(ARFLAGS) $@ $(OBJECTS)
|
||||
$(RANLIB) $@
|
||||
|
||||
#This rule makes the hash program included with libtomcrypt
|
||||
hashsum: library $(HASHOBJECTS)
|
||||
@@ -200,19 +204,19 @@ install_lib: library
|
||||
#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 \
|
||||
-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
|
||||
-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)
|
||||
-rm -f doc/crypt.pdf $(LEFTOVERS)
|
||||
echo "hello" > crypt.ind
|
||||
latex crypt > /dev/null
|
||||
latex crypt > /dev/null
|
||||
@@ -220,7 +224,7 @@ docs: crypt.tex
|
||||
latex crypt > /dev/null
|
||||
dvipdf crypt
|
||||
mv -ivf crypt.pdf doc/crypt.pdf
|
||||
rm -f $(LEFTOVERS)
|
||||
-rm -f $(LEFTOVERS)
|
||||
|
||||
docdvi: crypt.tex
|
||||
echo hello > crypt.ind
|
||||
38
PLAN
Normal file
38
PLAN
Normal file
@@ -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???
|
||||
55
ampi.c
Normal file
55
ampi.c
Normal file
@@ -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
|
||||
|
||||
121
base64.c
Normal file
121
base64.c
Normal file
@@ -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, tomstdenis@iahu.ca, http://libtomcrypt.org
|
||||
*/
|
||||
/* compliant base64 code donated by Wayne Scott (wscott@bitmover.com) */
|
||||
#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
|
||||
|
||||
3
crypt.c
3
crypt.c
@@ -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 @@ const char *crypt_build_settings =
|
||||
"\n"
|
||||
"\n\n\n"
|
||||
;
|
||||
*/
|
||||
|
||||
|
||||
BIN
doc/crypt.pdf
BIN
doc/crypt.pdf
Binary file not shown.
305
gf.c
Normal file
305
gf.c
Normal file
@@ -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, tomstdenis@iahu.ca, 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
|
||||
|
||||
|
||||
862
keyring.c
Normal file
862
keyring.c
Normal file
@@ -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, tomstdenis@iahu.ca, 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
|
||||
|
||||
|
||||
@@ -23,7 +23,8 @@ extern "C" {
|
||||
#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 {
|
||||
|
||||
146
mycrypt_custom.h
146
mycrypt_custom.h
@@ -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 */
|
||||
|
||||
/* 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
|
||||
#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
|
||||
#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
|
||||
|
||||
|
||||
32
mycrypt_gf.h
Normal file
32
mycrypt_gf.h
Normal file
@@ -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
|
||||
@@ -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
|
||||
|
||||
273
rsa.c
Normal file
273
rsa.c
Normal file
@@ -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, tomstdenis@iahu.ca, 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 */
|
||||
|
||||
|
||||
274
rsa_sys.c
Normal file
274
rsa_sys.c
Normal file
@@ -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, tomstdenis@iahu.ca, 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;
|
||||
}
|
||||
|
||||
698
serpent.c
Normal file
698
serpent.c
Normal file
@@ -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 gladman@seven77.demon.co.uk
|
||||
*
|
||||
* 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
|
||||
|
||||
|
||||
86
strings.c
Normal file
86
strings.c
Normal file
@@ -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, tomstdenis@iahu.ca, 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
|
||||
|
||||
558
tommath.h
Normal file
558
tommath.h
Normal file
@@ -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, tomstdenis@iahu.ca, 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
|
||||
|
||||
Reference in New Issue
Block a user