summaryrefslogtreecommitdiff
path: root/src/tspi/daa/big_integer
diff options
context:
space:
mode:
Diffstat (limited to 'src/tspi/daa/big_integer')
-rw-r--r--src/tspi/daa/big_integer/bi.c237
-rw-r--r--src/tspi/daa/big_integer/bi_gmp.c261
-rw-r--r--src/tspi/daa/big_integer/bi_openssl.c181
-rw-r--r--src/tspi/daa/big_integer/test/Makefile.am9
-rw-r--r--src/tspi/daa/big_integer/test/multi_exp.c29
-rw-r--r--src/tspi/daa/big_integer/test/test.c296
6 files changed, 1013 insertions, 0 deletions
diff --git a/src/tspi/daa/big_integer/bi.c b/src/tspi/daa/big_integer/bi.c
new file mode 100644
index 0000000..b86b2c1
--- /dev/null
+++ b/src/tspi/daa/big_integer/bi.c
@@ -0,0 +1,237 @@
+
+/*
+ * Licensed Materials - Property of IBM
+ *
+ * trousers - An open source TCG Software Stack
+ *
+ * (C) Copyright International Business Machines Corp. 2006
+ *
+ */
+
+#include <bi.h>
+
+#include "tcslog.h"
+
+#undef INLINE_DECL
+#define INLINE_DECL
+
+/***********************************************************************************
+ CONSTANT
+*************************************************************************************/
+
+bi_t bi_0;
+bi_t bi_1;
+bi_t bi_2;
+
+/***********************************************************************************
+ WORK VARIABLE
+*************************************************************************************/
+
+// Buffer to load bi from a file . A static field is used, this should not be
+// refere in any SPI calls.
+#define BUFFER_SIZE 10000
+static char buffer[BUFFER_SIZE]; // used for loading bi
+
+#define SAFETY_PARAM 80
+
+// keep the list of allocated memory, usually used for the format functions
+list_ptr allocs = NULL;
+
+/***********************************************************************************
+ DUMP LIB
+*************************************************************************************/
+
+// !! to use only for debugging
+// do not used it in the same call, as a static buffer is used
+char *dump_byte_array(int len, unsigned char *array) {
+ int i, j=0;
+ char c, str[3];
+
+ for( i=0; i<len; i++) {
+ c = array[i];
+ sprintf( str, "%02X", (int)(c & 0xFF));
+ buffer[j] = str[0];
+ buffer[j+1] = str[1];
+ j+=2;
+ }
+ buffer[j] = 0;
+ return buffer;
+}
+
+/* convert <strings> and return it into a byte array <result> of length <length> */
+unsigned char *retrieve_byte_array( int *len, const char *strings) {
+ int index_str = 0, index_result = 0;
+ int str_len = strlen( strings);
+ char read_buffer[3];
+ int c;
+ unsigned char *result;
+
+ read_buffer[2]=0;
+ *len = ( str_len >> 1);
+ #ifdef BI_DEBUG
+ printf("[%s]\n", strings);
+ printf("[retrieve_byte_array] strlen=%d len=%d\n", str_len, *len);
+ #endif
+ result = (unsigned char *)malloc( *len+1);
+ if( result == NULL) {
+ LogError("malloc of %d bytes failed", *len+1);
+ return NULL;
+ }
+ if( (str_len & 1) ==1) {
+ // impair => 1 12 23 -> 01 12 23
+ read_buffer[0]='0';
+ read_buffer[1]=strings[index_str++];
+ sscanf( read_buffer, "%2X", &c);
+ #ifdef BI_DEBUG
+ printf("[c'=%2X|%s]", (int)(c & 0xFF), read_buffer);
+ #endif
+ result[index_result++] = c&0xFF;
+ (*len)++;
+ }
+ while( index_str < str_len) {
+ read_buffer[0] = strings[ index_str++];
+ read_buffer[1] = strings[ index_str++];
+ sscanf( read_buffer, "%02X", &c);
+ #ifdef BI_DEBUG
+ printf("[c'=%2X|%s]", (int)(c & 0xFF), read_buffer);
+ #endif
+ result[index_result++] = c&0xFF;
+ }
+ return result;
+}
+
+/* create a <big integer> array */
+INLINE_DECL void bi_new_array( bi_array array, const int length) {
+ int i=0;
+
+ bi_new_array2( array, length);
+ if( array->array == NULL) return;
+ for( i = 0; i< length; i++) {
+ array->array[i] = bi_new_ptr();
+ }
+}
+
+/* create a <big integer> array */
+INLINE_DECL void bi_new_array2( bi_array array, const int length) {
+ array->length = length;
+ array->array = (bi_ptr *)malloc( sizeof(bi_ptr) * length);
+ if( array->array == NULL) {
+ LogError("malloc of %d bytes failed", sizeof(bi_ptr)*length);
+ return;
+ }
+}
+
+/* free resources allocated to the big integer <i> */
+INLINE_DECL void bi_free_array(bi_array array) {
+ int length = array->length;
+ int i=0;
+
+ for( i = 0; i< length; i++) {
+ bi_free_ptr( array->array[i]);
+ }
+ free( array->array);
+}
+
+/* copy length pointers from the array <src, offset_src> to array <dest, offset_dest> */
+INLINE_DECL void bi_copy_array(bi_array_ptr src,
+ int offset_src,
+ bi_array_ptr dest,
+ int offset_dest,
+ int length) {
+ int i=0;
+
+ for( i = 0; i< length; i++) {
+ dest->array[ offset_dest + i] = src->array[ offset_src + i];
+ }
+}
+
+/* debug function -> dump a field of type bi_array */
+void dump_bi_array( char *field, const bi_array_ptr array) {
+ int i;
+
+ for( i=0; i<array->length; i++) {
+ printf("%s->array[%d] = %s\n", field, i, bi_2_hex_char(array->array[i]));
+ }
+}
+
+/***********************************************************************************
+ SAFE RANDOM
+*************************************************************************************/
+
+/* Returns a random number in the range of [0,element-1] */
+bi_ptr compute_random_number( bi_ptr result, const bi_ptr element) {
+ bi_urandom( result, bi_length( element) + SAFETY_PARAM);
+ bi_mod( result, result, element);
+ return result;
+}
+
+/***********************************************************************************
+ SAVE / LOAD
+*************************************************************************************/
+
+/* load an big integer from an open file handler */
+void bi_load( bi_ptr bi, FILE *file) {
+ int i=0;
+ char c;
+
+ fgets( buffer, BUFFER_SIZE, file);
+ do {
+ c = buffer[i];
+ i++;
+ } while( c != 0 && c != ' ');
+ buffer[i-1] = 0;
+ bi_set_as_hex( bi, buffer);
+}
+
+/* load an big integer array from an open file handler */
+void bi_load_array( bi_array_ptr array, FILE *file) {
+ int i, j = 0, length;
+ char c;
+
+ fgets( buffer, BUFFER_SIZE, file);
+ do {
+ c = buffer[ j];
+ j++;
+ } while( c != 0 && c != ' ');
+ buffer[ j -1] = 0;
+ sscanf( buffer, "%d", &length);
+ bi_new_array( array, length);
+ for( i=0; i<array->length; i++) {
+ bi_load( array->array[i], file);
+ }
+}
+
+/* save an big integer to an open file handler */
+void bi_save( const bi_ptr bi, const char *name, FILE *file) {
+ fprintf( file, "%s # %s [%ld]\n", bi_2_hex_char( bi), name, bi_nbin_size( bi));
+}
+
+/* save an big integer array to an open file handler */
+void bi_save_array( const bi_array_ptr array, const char *name, FILE *file) {
+ int i;
+ char new_name[100];
+
+ fprintf(file, "%d # %s.length\n", array->length, name);
+ for( i=0; i<array->length; i++) {
+ sprintf( new_name, "%s[%d]", name, i);
+ bi_save( array->array[i], new_name, file);
+ }
+}
+
+/* convert <bi> to a byte array of length result, the beginning of */
+/* this buffer is feel with '0' if needed */
+void bi_2_byte_array( unsigned char *result, int length, bi_ptr bi) {
+ int i, result_length;
+
+ bi_2_nbin1( &result_length, buffer, bi);
+ int delta = length - result_length;
+ #ifdef BI_DEBUG
+ fprintf( stderr, "[bi_2_byte_array] result_length=%d length=%d\n", result_length, length);
+ #endif
+ if( delta < 0) {
+ LogError( "[bi_2_byte_array] asked length:%d found:%d\n", length, result_length);
+ return;
+ }
+ for( i=0; i<delta; i++) result[i] = 0;
+ for( ; i<length; i++) result[ i] = buffer[ i - delta];
+}
diff --git a/src/tspi/daa/big_integer/bi_gmp.c b/src/tspi/daa/big_integer/bi_gmp.c
new file mode 100644
index 0000000..f03bf4c
--- /dev/null
+++ b/src/tspi/daa/big_integer/bi_gmp.c
@@ -0,0 +1,261 @@
+
+/*
+ * Licensed Materials - Property of IBM
+ *
+ * trousers - An open source TCG Software Stack
+ *
+ * (C) Copyright International Business Machines Corp. 2006
+ *
+ */
+
+#ifdef BI_GMP
+
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <bi.h>
+
+#undef INLINE_DECL
+#define INLINE_DECL
+
+gmp_randstate_t state;
+
+/*
+ reps controls how many tests should be done in mpz_probable_prime_p:
+ 5 to 10 are reasonable number
+*/
+static int reps = 20;
+
+static int initialized = 0;
+void * (*bi_alloc)(size_t size);
+
+/***********************************************************************************
+ BITS OPERATION
+*************************************************************************************/
+
+// for conversion from and to byte[] see mpz_export and mpz_import
+
+/* return the size of a network byte order representation of <i> */
+long bi_nbin_size(const bi_ptr i) {
+ int word_size = 1; // 1 byte per word
+ int numb = 8 * word_size - 0;
+ int count = (mpz_sizeinbase ( i, 2) + numb-1) / numb;
+
+ return count * word_size;
+}
+
+/* return a BYTE * - in network byte order - and update the length <length> */
+unsigned char *bi_2_nbin( int *length, const bi_ptr i) {
+ unsigned char *buffer = (unsigned char *)bi_alloc( bi_nbin_size( i));
+
+ if( buffer == NULL) return NULL;
+ mpz_export(buffer, length, 1, 1, 1, 0, i);
+ return buffer;
+}
+
+/* return a BYTE * - in network byte order - and update the length <length> */
+/* different from bi_2_nbin: you should reserve enough memory for the storage */
+void bi_2_nbin1( int *length, unsigned char *buffer, const bi_ptr i) {
+ mpz_export(buffer, length, 1, 1, 1, 0, i);
+}
+
+/* return a bi_ptr that correspond to the big endian encoded BYTE array of length <n_length> */
+INLINE_DECL bi_ptr bi_set_as_nbin( const unsigned long length, const unsigned char *buffer) {
+ bi_ptr ret = bi_new_ptr();
+
+ if( ret == NULL) return NULL;
+ mpz_import( ret, length, 1, 1, 1, 0, buffer);
+ return ret;
+}
+
+
+/***********************************************************************************
+ BASIC MATH OPERATION
+*************************************************************************************/
+
+/* multiple-exponentiation */
+/* <result> := mod( Multi( <g>i, <e>i), number of byte <m>) with 0 <= i <= <n> */
+bi_ptr bi_multi_mod_exp( bi_ptr result,
+ const int n,
+ const bi_t g[],
+ const long e[],
+ const int m) {
+ mpz_t temp, bi_m;
+ int i;
+
+ mpz_init( temp);
+ mpz_init( bi_m);
+ mpz_set_si( bi_m, m);
+ // result := (g[0] ^ e[0]) mod m
+ mpz_powm_ui( result, g[0], e[0], bi_m);
+ for( i=1; i<n; i++) {
+ // temp := (g[i] ^ e[i]) mod bi_m
+ mpz_powm_ui( temp, g[i], e[i], bi_m);
+ // result := result * temp
+ mpz_mul( result, result, temp);
+ }
+ mpz_mod_ui( result, result, m);
+ mpz_clear( bi_m);
+ mpz_clear( temp);
+ return result;
+}
+
+/***********************************************************************************
+ NUMBER THEORIE OPERATION
+*************************************************************************************/
+/* generate prime number of <length> bits */
+INLINE_DECL bi_ptr bi_generate_prime( bi_ptr result, const long length) {
+ do {
+ mpz_urandomb( result, state, length); // i := random( length)
+ bi_setbit( result, 0);
+ bi_setbit( result, length - 1);
+ bi_setbit( result, length - 2);
+ mpz_nextprime( result, result); // i := nextPrime( i)
+ } while( mpz_sizeinbase( result, 2) != (unsigned long)length &&
+ bi_is_probable_prime( result) );
+ return result;
+}
+
+/* generate a safe prime number of <length> bits */
+/* by safe we mean a prime p so that (p-1)/2 is also prime */
+INLINE_DECL bi_ptr bi_generate_safe_prime( bi_ptr result, long length) {
+ mpz_t temp;
+
+ mpz_init(temp);
+ do {
+ bi_generate_prime( result, length);
+ mpz_sub_ui( temp, result, 1); // temp := result - 1
+ mpz_div_2exp( temp, temp, 1); // temp := temp / 2
+ } while( mpz_probab_prime_p( temp, 10) == 0);
+#ifdef BI_DEBUG
+ printf("GENERATE SAFE PRIME DONE");fflush(stdout);
+#endif
+ mpz_clear( temp);
+ return result;
+}
+
+/* return true if <i> is a probably prime */
+INLINE_DECL int bi_is_probable_prime( bi_ptr i) {
+ /*
+ This function does some trial divisions and after some Miller-Rabin probabilistic
+ primality tests. The second parameter controls how many tests should be done,
+ 5 to 10 are reasonable number
+ */
+ return mpz_probab_prime_p( i, reps)>=1 ? 1 : 0;
+}
+
+/* return in <result> the greatest common divisor of <a> and <b> */
+/* <result> := gcd( <a>, <b>) */
+INLINE_DECL bi_ptr bi_gcd( bi_ptr result, bi_ptr a, bi_ptr b) {
+ // result := gcd( a, b)
+ mpz_gcd( result, a, b);
+ return result;
+}
+
+
+/***********************************************************************************
+ INIT/RELEASE LIBRARY
+*************************************************************************************/
+
+/* bi_alloc_p allocation function used only for exporting a bi struct, so for bi_2_nbin
+if define as NULL, a stdlib malloc() will be used */
+void bi_init( void * (*bi_alloc_p)(size_t size)) {
+ time_t start;
+ unsigned long seed;
+ FILE *f;
+#ifdef INTERACTIVE
+ int c, i;
+#endif
+
+ if( initialized == 1) return;
+ if( bi_alloc_p == NULL) bi_alloc = &malloc;
+ else bi_alloc = bi_alloc_p;
+ mpz_init( bi_0);
+ mpz_set_ui( bi_0, 0);
+ mpz_init( bi_1);
+ mpz_set_ui( bi_1, 1);
+ mpz_init( bi_2);
+ mpz_set_ui( bi_2, 2);
+ allocs = list_new();
+ if( allocs == NULL) {
+ LogError("malloc of list failed");
+ return;
+ }
+#ifdef BI_DEBUG
+ printf("bi_init() -> gmp lib\n");
+#endif
+ time( &start);
+ // first try /dev/random, the most secure random generator
+ f = fopen("/dev/random", "r");
+ // in case of failure, but les secure :(
+ if( f== NULL) f = fopen("/dev/urandom", "r");
+ if( f != NULL) {
+ fread( &seed, sizeof(unsigned long int), 1, f);
+ fclose(f);
+ }
+#ifdef INTERACTIVE
+ else {
+ printf("! devices /dev/random and /dev/urandom not found\n");
+ printf("type some characters to generate a random seed (follow by enter)\n");
+ fflush(stdout);
+ i=0;
+ while( (c = fgetc(stdin)) != 10) {
+ time_t temps;
+ time( &temps);
+ seed += temps +( c << i);
+ i++;
+ }
+ time_t temps;
+ time( &temps);
+ seed += temps;
+#ifdef BI_DEBUG
+ printf("temps=%lx\n", temps - start);
+#endif // BI_DEBUG
+ seed = (long)( temps * start);
+ }
+#endif // INTERACTIVE
+#ifdef BI_DEBUG
+ printf("seed=%lx\n", seed);
+#endif
+ gmp_randinit_default( state);
+ gmp_randseed_ui( state, seed);
+ initialized = 1;
+}
+
+void bi_release(void) {
+ if( initialized) {
+ bi_flush_memory();
+ bi_free( bi_0);
+ bi_free( bi_1);
+ bi_free( bi_2);
+ initialized = 0;
+ }
+}
+void bi_flush_memory(void) {
+ node_t *current;
+ list_ptr list = allocs;
+
+ if( list->head == NULL) return; // list is empty
+ else {
+ current = list->head; // go to first node
+ do {
+ LogDebug("[flush memory] free %lx\n", current->obj);
+ free( current->obj);
+ current = current->next; // traverse through the list
+ } while(current != NULL); // until current node is NULL
+ }
+ list_freeall( allocs);
+ allocs = list_new();
+ if( allocs == NULL) {
+ LogError("malloc of list failed");
+ return;
+ }
+}
+
+
+int bi_is_initialized(void) {
+ return initialized;
+}
+
+#endif
diff --git a/src/tspi/daa/big_integer/bi_openssl.c b/src/tspi/daa/big_integer/bi_openssl.c
new file mode 100644
index 0000000..50ef030
--- /dev/null
+++ b/src/tspi/daa/big_integer/bi_openssl.c
@@ -0,0 +1,181 @@
+
+/*
+ * Licensed Materials - Property of IBM
+ *
+ * trousers - An open source TCG Software Stack
+ *
+ * (C) Copyright International Business Machines Corp. 2006
+ *
+ */
+
+#ifdef BI_OPENSSL
+
+#define INSIDE_LIB
+
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <bi.h>
+
+#include "tcslog.h"
+
+#undef INLINE_DECL
+#define INLINE_DECL
+
+#include <string.h>
+#include <openssl/rand.h>
+
+BN_CTX *context;
+static int initialized = 0;
+
+void * (*bi_alloc)(size_t size);
+
+/* return true if <i> is a probably prime */
+INLINE_DECL int bi_is_probable_prime( const bi_ptr i) {
+ /*
+ * start tests using some small prime numbers. Continue by performing a Miller-Rabin
+ * probabilistic primality test with checks iterations, and with some iterations that
+ * yields a false positive rate of at most 2^-80 for random input.
+ * return:
+ * 0 if the number is composite
+ * 1 if it is prime with an error probability of less than 0.25^checks, and on error.
+ */
+ return BN_is_prime_fasttest( i, BN_prime_checks, NULL, context, NULL, 1);
+}
+
+/* <result> := ( <g> ^ <e> ) mod <m> */
+INLINE_DECL bi_ptr bi_mod_exp_si( bi_ptr result, const bi_ptr g, const bi_ptr e, const long m) {
+ bi_t bi_tmp;
+
+ bi_new( bi_tmp);
+ BN_set_word( bi_tmp, m);
+#ifdef BI_DEBUG
+ printf("[bi_mod_exp] (g=%s ^ e=%s) mod=%s\n",
+ BN_bn2dec( g),
+ BN_bn2dec( e),
+ BN_bn2dec( bi_tmp));
+#endif
+ BN_mod_exp( result, g, e, bi_tmp, context); // result := (g ^ e) mod bi_tmp9
+#ifdef BI_DEBUG
+ printf("[bi_mod_exp] res=%s\n", BN_bn2dec( result));
+#endif
+ bi_free( bi_tmp);
+ return result;
+}
+
+/* multiple-exponentiation */
+/* <result> := mod( Multi( <g>i, <e>i), number of byte <m>) with 0 <= i <= <n> */
+bi_ptr bi_multi_mod_exp( bi_ptr result,
+ const int n,
+ const bi_t g[],
+ const long e[],
+ const int m
+) {
+ BIGNUM *temp = BN_new();
+ BIGNUM *bi_m = BN_new();
+ BIGNUM *bi_e = BN_new();
+ int i;
+
+ BN_set_word( bi_m, m);
+ BN_set_word( bi_e, e[0]);
+ // result := (g[0] ^ e[0]) mod bi_m
+ BN_mod_exp( result, g[0], bi_e, bi_m, context);
+ for( i=1; i<n; i++) {
+ BN_set_word( bi_e, e[i]);
+ // temp := (g[i] ^ e[i]) mod bi_m
+ BN_mod_exp( temp, g[i], bi_e, bi_m, context);
+ // result := result * temp
+ BN_mul( result, result, temp, context);
+ }
+ BN_mod( result, result, bi_m, context);
+ BN_free(bi_e);
+ BN_free(bi_m);
+ BN_free(temp);
+ return result;
+}
+
+
+/***********************************************************************************
+ INIT/RELEASE LIBRARY
+************************************************************************************/
+
+/* bi_alloc_p allocation function used only for exporting a bi struct,
+so for bi_2_nbin? for example. if define as NULL, a stdlib malloc() will be used
+*/
+void bi_init( void * (*bi_alloc_p)(size_t size)) {
+ if( initialized == 1) return;
+ if( bi_alloc_p == NULL) bi_alloc = &malloc;
+ else bi_alloc = bi_alloc_p;
+ bi_new( bi_0);
+ bi_set_as_si( bi_1, 0);
+ bi_new( bi_1);
+ bi_set_as_si( bi_1, 1);
+ bi_new( bi_2);
+ bi_set_as_si( bi_2, 2);
+ allocs = list_new();
+ if( allocs == NULL) {
+ LogError("malloc of list failed");
+ return;
+ }
+ LogDebug("bi_init() -> openssl lib\n");
+ LogDebug("bi_init() -> seed status = %d\n", RAND_status());
+ context = BN_CTX_new();
+ if( RAND_status() != 1) {
+ LogError("! PRNG has not been seeded with enough data\n");
+#ifdef INTERACTIVE
+ printf("type some characters to regenerate a random seed\n");
+ fflush(stdout);
+ int c, i=0, seed;
+ char str[2] = "a";
+ while( RAND_status() !=1 ) {
+ c = fgetc(stdin);
+ time_t temps;
+ time( &temps);
+ seed += temps +( c << i);
+ i++;
+ str[0]=c;
+ RAND_seed( str, 1);
+ }
+#endif
+ }
+ initialized = 1;
+}
+
+void bi_release(void) {
+ if( initialized) {
+ bi_flush_memory();
+ bi_free( bi_0);
+ bi_free( bi_1);
+ bi_free( bi_2);
+ BN_CTX_free( context);
+ initialized = 0;
+ }
+}
+
+void bi_flush_memory(void) {
+ node_t *current;
+ list_ptr list = allocs;
+
+ if( list->head == NULL) return; // list is empty
+ else {
+ current = list->head; // go to first node
+ do {
+ LogDebug("[flush memory] free %lx\n", (long)current->obj);
+ free( current->obj);
+ current = current->next; // traverse through the list
+ } while(current != NULL); // until current node is NULL
+ }
+ list_freeall( allocs);
+ allocs = list_new();
+ if( allocs == NULL) {
+ LogError("malloc of list failed");
+ return;
+ }
+}
+
+int bi_is_initialized(void) {
+ return initialized;
+}
+
+#endif
diff --git a/src/tspi/daa/big_integer/test/Makefile.am b/src/tspi/daa/big_integer/test/Makefile.am
new file mode 100644
index 0000000..d631c2a
--- /dev/null
+++ b/src/tspi/daa/big_integer/test/Makefile.am
@@ -0,0 +1,9 @@
+bin_PROGRAMS = test
+
+
+test_SOURCES=test.c multi_exp.c ../bi_gmp.c ../bi_openssl.c ../bi.c \
+ ../../../include/bi.h ../../../include/bi_openssl.h ../../../include/bi_gmp.h
+test_CFLAGS=-G
+
+# test_CFLAGS=-I../../../include -DBI_OPENSSL
+
diff --git a/src/tspi/daa/big_integer/test/multi_exp.c b/src/tspi/daa/big_integer/test/multi_exp.c
new file mode 100644
index 0000000..2ff80fc
--- /dev/null
+++ b/src/tspi/daa/big_integer/test/multi_exp.c
@@ -0,0 +1,29 @@
+#include <stdio.h>
+
+#include <bi.h>
+
+// use standard C definition to avoid .h
+int test_exp_multi(void) {
+ bi_t result;
+ bi_t g[3];
+ unsigned long e[3];
+
+ bi_new( result);
+ bi_new( g[0]);
+ bi_new( g[1]);
+ bi_new( g[2]);
+ // result = (2^2 * 5^4 * 7^7) mod 56 -> should give 28
+ bi_set_as_dec( g[0], "2");
+ bi_set_as_dec( g[1], "5");
+ bi_set_as_dec( g[2], "7");
+ e[0] = 2L;
+ e[1] = 4L;
+ e[2] = 7L;
+ bi_multi_mod_exp( result, 3, g, e, 56);
+ printf("multi-exponentiation <result>=%s\n", bi_2_dec_char(result));
+ bi_free( g[0]);
+ bi_free( g[1]);
+ bi_free( g[2]);
+ bi_free( result);
+ return 0;
+}
diff --git a/src/tspi/daa/big_integer/test/test.c b/src/tspi/daa/big_integer/test/test.c
new file mode 100644
index 0000000..4cc3a7f
--- /dev/null
+++ b/src/tspi/daa/big_integer/test/test.c
@@ -0,0 +1,296 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <bi.h>
+
+/* for the logging system used by TSS */
+setenv("TCSD_FOREGROUND", "1", 1);
+
+ /*
+ * standard bit length extension to obtain a uniformly distributed number
+ * [0,element]
+ */
+int test_exp_multi(void);
+
+void foo (bi_t result, const bi_ptr param, unsigned long n) {
+ unsigned long i;
+
+ bi_set( result, param);
+ bi_mul_si( result, result, n);
+ for (i = 1; i < n; i++) bi_add_si( result, result, i*7);
+}
+
+void *my_malloc(size_t size) {
+ void *ret = malloc( size);
+
+ printf("my_malloc() -> %ld\n", (long)ret);
+ return ret;
+}
+
+ /**
+ * Returns a random number in the range of [0,element-1].
+ *
+ * @param element
+ * the upper limit
+ * @param random
+ * the secure random source
+ * @return the random number
+ */
+void computeRandomNumber(bi_t res, const bi_ptr element) {
+ int length = 80 + bi_length( res); // give the length
+ bi_urandom( res, length); // res = random( of length);
+ int element_length = bi_length( element);
+ bi_mod_si( res, res, element_length); // res = res mod <number byte of element>
+}
+
+int main (int argc, char **argv) {
+ bi_t bi_tmp, bi_tmp1, bi_tmp2, bi_tmp3, bi_tmp4, bi_tmp5, bi_tmp6;
+ bi_t r;
+ bi_t n;
+ int i;
+ unsigned char result1[5];
+ int len;
+ char *byte_array;
+ FILE *file;
+ unsigned char ret[] = { (unsigned char)1, 0, (unsigned char)254 };
+ int length;
+ unsigned char *buffer;
+ unsigned char byte;
+ bi_ptr nn;
+
+ bi_init( &my_malloc);
+ printf("test(%s,%s)\n", __DATE__, __TIME__);
+ #ifdef BI_GMP
+ printf("using BMP\n");
+ #endif
+ #ifdef BI_OPENSSL
+ printf("using OPENSSL\n");
+ #endif
+
+ bi_new( bi_tmp);
+ bi_new( bi_tmp1);
+ bi_new( bi_tmp2);
+ bi_new( bi_tmp3);
+ bi_new( bi_tmp4);
+ bi_new( bi_tmp5);
+ bi_new( bi_tmp6);
+ bi_new( n);
+ bi_new( r);
+ bi_set_as_hex( n, "75E8F38669C531EB78C7ACD62CCDEFFB5E5BE15E2AA55B3AD28B1A35F6E937097CE09A49C689AC335FBA669205CEF209275CFF273F8F81C5B864E5029EECDFA0743BC15D6E4D2C2CB0DED2DC7119A7E0D61669D417BB3B12BA1D10FD40326A49CA6C9E77F8585F25D8C897D9C73284152E103582C018C964F02ADDBA56CB1161A949AAE2847ADE8BC1152716C8B4AF37A87011C2569F646FD3EDA83099048B9525A6401C47A372F3EA43C91066AD5851AE11DEF1EAC7108FFB06AD94D0B849C339A5E8793C4C054456D3D22D30ACCCF7EF33EF7A7D65799E7908D95B0538A9EFC91BF104CE5008D79625394DB1E5883B2F202B95320BBD868BF65C996FC0DFC5");
+ bi_set_as_hex( r, "35A624E6607CFD37162C6052547450B2267ECC749F10CDAEB5C294491321EEB47CA0229F423ADCEF3FA7806F5C4DB3C3445D8E7039EBC457149A1343BECF3B1078385C06EE74351A476BE0D5203633C81F7B8D68548DB763F0C096B20615B6016C180291EF32CC064A173BB22F6B46B3240ACC0B50D8338757FA28D5B0313BC4201CD2B35472842E71994C8FCA557B08004B2495304D13A93D796134BB8078E2EE371707DE5809D72474A7CCE1F865ECD8876105D3DB9AFA9426052D0120C755C60F56A0C0F30FAED2053CEB3129FAB6F57F6E209A8E7B2A559D734B339E19E1F2A147BC94DB2FF491CB5ACCEEEED7F2EA75AFF7CAD33E1E420A09135D9C5C1F");
+ DUMP_BI( n);
+ DUMP_BI( r);
+ printf("big number n=n*r\n");
+ bi_mul( n, n, r);
+ DUMP_BI( n);
+ bi_set_as_hex( r, "D7E7028DA181DADAC29C95143C865702453465115AFA7576AADF1E57DD84DA7FF4C8F66530D1E9D1AB69BC12342B89FA0A9755F9F4EE1DA445D50016CEF50622ED905CC9B987FCC7910CAA841641814C1994BC442A15CB05FE5C145626F1454E90435FBC6A529856EF29BDBCBFCB62FB69EDBD11DC33357667867278E1679EABCDBEEA02E9A6911804DF47ACA6B2D63A31E258AD542D71A8178A5E072F5E221EADBB10E16D5533AE427101FF94C5967575FABCD18305C5F15C103CEA1A8ACD01898E88426EDA7C0DF58AA48435808A840F6EEE1D7205D33F356E20FE0D4136B401BF386F11869C3CE4A808B96435694748EF3706F58756548A71E4CF4D2BE157");
+ bi_mod( n, n, r);
+ printf("mod big number n=n mod r\n");
+ DUMP_BI( n);
+ if( bi_get_si( bi_set_as_si( n, 13)) != 13) {
+ printf("!!! bi_set_as_si 13(%s) = 13\n", bi_2_dec_char( n ));
+ exit(-1);
+ }
+ if( bi_get_si( bi_set_as_si( n, -13)) != -13) {
+ printf("!!! bi_set_as_si -13(%s) = -13\n", bi_2_dec_char( n ));
+ exit(-1);
+ }
+ if( bi_get_si( bi_inc(bi_set_as_si( n, 13))) != 14) {
+ puts("!!! bi_inc 13++ = 14\n");
+ exit(-1);
+ }
+ if( bi_get_si( bi_dec(bi_set_as_si( n, 13))) != 12) {
+ puts("!!! bi_dec 13-- = 12\n");
+ exit(-1);
+ }
+ if( bi_get_si( bi_setbit(bi_set_as_si( n, 0), 10)) != 1024) {
+ puts("!!! bi_setbit set[10] = 1024\n");
+ exit(-1);
+ }
+ if( bi_get_si( bi_mod_si(bi_tmp, bi_set_as_si( n, 12), 10)) != 2) {
+ puts("!!! bi_mod_si 12 mod 10 = 2\n");
+ exit(-1);
+ }
+ if( bi_get_si( bi_mul_si(bi_tmp, bi_set_as_si( n, 12), 10)) != 120) {
+ puts("!!! bi_mul_si 12 * 10 = 120\n");
+ exit(-1);
+ }
+ if( bi_get_si( bi_mul(bi_tmp, bi_set_as_si( n, 12), bi_set_as_si( bi_tmp1, 10))) != 120) {
+ puts("!!! bi_mul_si 12 * 10 = 120\n");
+ exit(-1);
+ }
+ if( bi_get_si( bi_mod_exp_si(bi_tmp, bi_set_as_si( bi_tmp1, 4), bi_2, 10)) != 6) {
+ puts("!!! bi_mod_exp_si 4 ^ 2 mod 10 = 6\n");
+ exit(-1);
+ }
+ if( bi_get_si( bi_mod_exp(bi_tmp, bi_set_as_si( bi_tmp1, 4), bi_2, bi_set_as_si( bi_tmp2, 10))) != 6) {
+ puts("!!! bi_mod_exp 4 ^ 2 mod 10 = 6\n");
+ exit(-1);
+ }
+ if( bi_get_si( bi_mod(bi_tmp, bi_set_as_si( n, 12), bi_set_as_si(bi_tmp1, 10))) != 2) { printf("!!! bi_mod 12 mod 10 = 2 [%s]\n",bi_2_dec_char( bi_tmp)); exit(-1); }
+ if( bi_get_si( bi_mod(bi_tmp, bi_set_as_si( n, -12), bi_set_as_si(bi_tmp1, 10))) != 8) { printf("!!! bi_mod -12 mod 10 = 8 [%s]\n",bi_2_dec_char( bi_tmp)); exit(-1); }
+ if( bi_get_si( bi_mod(bi_tmp, bi_set_as_si( n, -27), bi_set_as_si(bi_tmp1, 10))) != 3) { printf("!!! bi_mod -27 mod 10 = 3 [%s]\n",bi_2_dec_char( bi_tmp)); exit(-1); }
+ bi_set_as_si(n, 0x12345678);
+ bi_2_byte_array( result1, 5, n);
+ if( result1[0] != 0x00 || result1[1] != 0x12 || result1[2] != 0x34 || result1[3] != 0x56 || result1[4] != 0x78 ) {
+ printf("!!! bi_2_byte_array[0x123456578] [0]=%x [1]=%x [2]=%x [3]=%x [4]=%x \n", result1[0], result1[1], result1[2], result1[3], result1[4]);
+ exit( -1);
+ }
+ byte_array = retrieve_byte_array( &len, "12345");
+ printf("test dump_byte_array len=%d \n", len);
+ printf("test dump_byte_array(\"12345\")=%s\n", dump_byte_array( len, byte_array));
+ free( byte_array);
+ byte_array = retrieve_byte_array( &len, "12345678");
+ printf("test dump_byte_array len=%d \n", len);
+ printf("test dump_byte_array(\"12345678\")=%s\n", dump_byte_array( len, byte_array));
+
+ // test save end load of bi_t and bi_array
+ /////////////////////////////////////////////////////////////////////////////////////
+ bi_array result;
+ bi_new_array( result, 2);
+ bi_set_as_si( bi_tmp, 6);
+ bi_set_as_si( result->array[0], 314159);
+ bi_set_as_si( result->array[1], 123456789);
+ file = fopen("/tmp/test.todel", "w");
+ bi_save_array( result, "result", file);
+ bi_save( bi_tmp, "bi_tmp", file);
+ fclose( file);
+ bi_set_as_si( result->array[0], 0);
+ bi_set_as_si( result->array[1], 0);
+ bi_set_as_si( bi_tmp, 0);
+ file = fopen("/tmp/test.todel", "r");
+ bi_load_array( result, file);
+ bi_load( bi_tmp, file);
+ fclose( file);
+ if( bi_get_si( result->array[0]) != 314159) { puts("!!! save/load array[0] = 314159\n"); exit(-1); }
+ if( bi_get_si( result->array[1]) != 123456789) { puts("!!! save/load array[1] = 123456789\n"); exit(-1); }
+ if( bi_get_si( bi_tmp) != 6) { puts("!!! save/load bi_tmp = 6\n"); exit(-1); }
+
+ // conversion from bi_t 2 big endian BYTE*
+ /////////////////////////////////////////////////////////////////////////////////////
+ bi_set_as_si( n, 254+(1 << 16));
+ buffer = bi_2_nbin( &length, n);
+ printf("value 2 convert=%s length=%ld\n", bi_2_hex_char( n), bi_nbin_size( n));
+ for( i=0; i<length; i++) {
+ byte = (unsigned char)(buffer[i] & 0xFF);
+ if( byte != ret[i]) { printf("\n!!! bi_2_nbin[%d] %x = %x\n", i, byte, ret[i]); exit(-1); }
+ printf("[buffer[%d]=%x]", i, (int)(byte));
+ }
+ printf("\n");
+ nn = bi_set_as_nbin( length, buffer);
+ if( bi_equals_si( nn, 254+(1 << 16) ) == 0) {
+ printf("\n!!! bi_set_as_nbin %s = %x\n", bi_2_hex_char( nn), 254+(1 << 16));
+ exit(-1);
+ }
+ if( !bi_equals( bi_sub_si( bi_tmp, bi_set_as_si( bi_tmp1, 9), 1),
+ bi_mod( bi_tmp2,
+ bi_mul( bi_tmp3, bi_set_as_si(bi_tmp4, 6),
+ bi_set_as_si( bi_tmp5, 3)),
+ bi_set_as_si( bi_tmp6, 10)))) {
+ puts("!!! 9-1 == (6*3) mod 10\n");
+ printf("!!! tmp(8) = %s tmp1(9)=%s tmp2(8)=%s tmp3(6*3)=%s tmp4(6)=%s\
+ tmp5(3)=%s tmp6(10)=%s\n",
+ bi_2_dec_char(bi_tmp),
+ bi_2_dec_char(bi_tmp1),
+ bi_2_dec_char(bi_tmp2),
+ bi_2_dec_char(bi_tmp3),
+ bi_2_dec_char(bi_tmp4),
+ bi_2_dec_char(bi_tmp5),
+ bi_2_dec_char(bi_tmp6));
+ exit(-1);
+ puts("!!! 9-1 == (6*3) mod 10\n"); exit(-1);
+ }
+ bi_set_as_si(n, 1);
+ bi_shift_left(n, n, 10);
+ printf("1 << 10 = %s\n", bi_2_dec_char( n));
+ bi_set_as_si(n, 1);
+ printf("(1 << 10) >> 5 = %s\n", bi_2_dec_char( bi_shift_right(bi_tmp, bi_shift_left(bi_tmp1, n, 10), 5)));
+ bi_set_as_si(n, 1);
+ printf("[* (1 << 10) >> 5 *] = (2^10) / (2^5) -> %s\n", bi_2_dec_char( bi_shift_right( bi_tmp, ( bi_shift_left( bi_tmp1, n, 10)), 5)));
+ bi_set_as_si( n, 10);
+ printf(" (2^10) = %s\n", bi_2_dec_char( bi_mod_exp_si( bi_tmp, bi_2, n, 2000)));
+ printf(" (1<<5) = %s\n", bi_2_dec_char( bi_shift_left( bi_tmp, bi_set_as_si( bi_tmp1, 1), 5)));
+ printf(" 1024 / 500 = %s\n", bi_2_dec_char( bi_div( bi_tmp, bi_set_as_si( bi_tmp1, 1024), bi_set_as_si( bi_tmp2, 500))));
+ printf(" 1024 / 500 = %s\n", bi_2_dec_char( bi_div_si( bi_tmp, bi_set_as_si( bi_tmp1, 1024), 500)));
+ printf(" (1 << 10) >> 5 = [* (2^10) / (2^5) *] -> %s\n", bi_2_dec_char( bi_div( bi_tmp1,
+ bi_mod_exp_si( bi_tmp2, bi_2, bi_set_as_si( bi_tmp3, 10), 2000),
+ bi_mod_exp_si( bi_tmp4, bi_2, bi_set_as_si( bi_tmp5, 5), 2000) )));
+
+ printf("(1 << 10) >> 5 = (2^10) / (1<<5) -> %d\n", bi_equals( bi_shift_right( bi_tmp, ( bi_shift_left( bi_tmp1, bi_1, 10)), 5),
+ bi_div( bi_tmp2,
+ bi_mod_exp_si( bi_tmp3, bi_2, bi_set_as_si( bi_tmp4, 10), 2000),
+ bi_mod_exp_si( bi_tmp5, bi_2, bi_set_as_si( bi_tmp6, 5), 2000))));
+ printf("( 45 ^ -5 ) %% 10 == ( 1 / ( (45 ^ 5) %% 10) ) %% 10\n");
+ bi_set_as_si( bi_tmp, 45);
+ bi_set_as_si( bi_tmp1, 5);
+ // bi_negate( bi_tmp1);
+ bi_set_as_si( bi_tmp2, 10);
+ bi_mod_exp( bi_tmp3, bi_tmp, bi_tmp1, bi_tmp2);
+ bi_set_as_si( bi_tmp1, 5);
+ bi_mod_exp( bi_tmp4, bi_tmp, bi_tmp1, bi_tmp2);
+ printf("\t( 45 ^ -5 ) %% 10 = %s\n", bi_2_dec_char( bi_tmp3));
+ printf("\t( 1 / ( (45 ^ 5) %% 10) ) %% 10 = %s\n", bi_2_dec_char( bi_tmp4));
+ if( bi_equals( bi_tmp3, bi_tmp4) == 0) {
+ printf("!!! error !\n");
+ exit( -1);
+ }
+ for( i=0; i<5; i++) {
+ bi_generate_prime( bi_tmp, 1024);
+ printf("bi=%s\n", bi_2_hex_char( bi_tmp));
+ printf("bi.length=%ld \n", bi_length( bi_tmp));
+ if( bi_length( bi_tmp) != 1024) { puts("!!! length(random(1024)) != 1024\n"); exit(-1); }
+ }
+ bi_set_as_si(n, 0);
+ bi_setbit( n, 10);
+ printf("setbit(10) = %s\n", bi_2_dec_char( n));
+ bi_set_as_dec(n, "123456");
+ foo( r, n, 20L);
+ printf("TEST:%s\n", bi_2_dec_char( r));
+ bi_urandom( n, 1024);
+ bi_urandom( r, 1024);
+ computeRandomNumber( r, n);
+ printf("r:%s n:%s\n", bi_2_hex_char( r), bi_2_hex_char( n));
+ bi_generate_prime( r, 1024);
+ printf("prime:%s\nIs probable prime:%d\n", bi_2_hex_char( r), bi_is_probable_prime( r));
+ int error = bi_invert_mod( r, r, n);
+ printf("Invert mod return:%d\nInvert(r):%s\n", error, bi_2_hex_char( r));
+ bi_negate( r);
+ printf("negate(r):%s\n", bi_2_hex_char( r));
+ bi_generate_safe_prime( r, 128);
+ bi_sub_si( n, r, 1); // n= r - 1
+ bi_shift_right( n, n, 1); // n = n / 2
+ printf("safe prime(r):%s probable_prime:%d\n", bi_2_hex_char( r), bi_is_probable_prime( r));
+ printf("safe prime( (r-1)/2):%s probable_prime:%d\n", bi_2_hex_char( n), bi_is_probable_prime( n));
+ test_exp_multi();
+ bi_free( r);
+ bi_free( n);
+
+ bi_set_as_si( result->array[0], 1);
+ printf("result-> 1<<20:%s\n", bi_2_dec_char( bi_shift_left( result->array[0], result->array[0], 20)));
+ bi_set_as_si( result->array[1], 1);
+ printf("result1-> 1<<10:%s\n", bi_2_dec_char( bi_shift_right( result->array[1], result->array[0], 10)));
+ // copy arrays
+ bi_array new_result; bi_new_array2( new_result, 4);
+ bi_new_array2( new_result, 4);
+ bi_copy_array( result, 0, new_result, 0, 2);
+ bi_copy_array( result, 0, new_result, 2, 2);
+ for( i = 0; i<4; i++) {
+ printf("new_result[%d]-> [even-> 1<<20] [odd-> 1<<10] :%s\n", i, bi_2_dec_char( new_result->array[i]));
+ }
+
+ bi_free( bi_tmp);
+ bi_free( bi_tmp1);
+ bi_free( bi_tmp2);
+ bi_free( bi_tmp3);
+ bi_free( bi_tmp4);
+ bi_free( bi_tmp5);
+ bi_free( bi_tmp6);
+ bi_release();
+ printf("THE END [%s,%s]\n", __DATE__, __TIME__);
+ fflush(stdout);
+ return 0;
+
+}
+