diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2012-11-25 14:36:20 +0000 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2012-11-25 14:36:20 +0000 |
commit | c3649a2def02c41d837ae1f79dda729ccb91e677 (patch) | |
tree | bea46dff212fdef977fe9094a70a939e8cc21885 /src/tspi/daa | |
download | trousers-upstream.tar.gz |
Imported Upstream version 0.3.9upstream/0.3.9upstream
Diffstat (limited to 'src/tspi/daa')
27 files changed, 10129 insertions, 0 deletions
diff --git a/src/tspi/daa/Makefile.am b/src/tspi/daa/Makefile.am new file mode 100644 index 0000000..b02bbde --- /dev/null +++ b/src/tspi/daa/Makefile.am @@ -0,0 +1,31 @@ +bin_PROGRAMS=issuer_setup key_verification test test_tpm test_join test_sign +#todel + +test_SOURCES=big_integer/bi_gmp.c big_integer/bi_openssl.c big_integer/bi.c utils/list.c big_integer/test/test.c big_integer/test/multi_exp.c +test_CFLAGS=-I../../include/daa -I../../include -DBI_DEBUG -g -DAPPID=\"BI\" +test_LDFLAGS=-lcrypto + +issuer_setup_SOURCES = daa_issuer/issuer_setup.c +issuer_setup_CFLAGS=-I../../include/daa -I../../include -DBI_DEBUG -DAPPID=\"DAA_ISSUER_SETUP\" +issuer_setup_LDFLAGS=-lcrypto ../libtspi.la ../libdaa.la + +key_verification_SOURCES=daa_issuer/key_verification.c +key_verification_CFLAGS=-I../../include/daa -I../../include -DBI_DEBUG -DAPPID=\"DAA_KEY_VERIFICATION\" +key_verification_LDFLAGS=-lcrypto ../libtspi.la ../libdaa.la + +test_tpm_SOURCES = daa_platform/test.c +test_tpm_CFLAGS=-I../../include/daa -I../../include +test_tpm_LDFLAGS=-lcrypto ../libtspi.la ../libdaa.la + +test_join_SOURCES = daa_platform/test_join.c +test_join_CFLAGS=-I../../include/daa -I../../include -DBI_DEBUG -DAPPID=\"DAA_JOIN\" +test_join_LDFLAGS=-lcrypto ../libtspi.la ../libdaa.la + +test_sign_SOURCES = test_sign.c +test_sign_CFLAGS=-I../../include/daa -I../../include -DBI_DEBUG -DAPPID=\"DAA_JOIN\" +test_sign_LDFLAGS=-lcrypto ../libtspi.la ../libdaa.la + +#todel_SOURCES = todel.c +#todel_CFLAGS=-I../../include/daa -I../../include -DBI_DEBUG -DAPPID=\"DAA_JOIN\" +#todel_LDFLAGS=-lcrypto ../libtspi.la ../libdaa.la + 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; + +} + diff --git a/src/tspi/daa/daa_anonymityrevocation/csencryption_result.c b/src/tspi/daa/daa_anonymityrevocation/csencryption_result.c new file mode 100644 index 0000000..9750e7e --- /dev/null +++ b/src/tspi/daa/daa_anonymityrevocation/csencryption_result.c @@ -0,0 +1,211 @@ + +/* + * Licensed Materials - Property of IBM + * + * trousers - An open source TCG Software Stack + * + * (C) Copyright International Business Machines Corp. 2006 + * + */ + +#include "daa_parameter.h" +#include "daa_structs.h" +#include "anonymity_revocation.h" +#include "verifier.h" +#include "tsplog.h" + +CS_ENCRYPTION_RESULT *create_CS_ENCRYPTION_RESULT( + bi_ptr c1, + bi_ptr c2, + bi_ptr c3, + bi_ptr c4 +) { + CS_ENCRYPTION_RESULT *result = + (CS_ENCRYPTION_RESULT *)malloc( sizeof(CS_ENCRYPTION_RESULT)); + + if (result == NULL) { + LogError("malloc of %d bytes failed", sizeof(CS_ENCRYPTION_RESULT)); + return NULL; + } + result->c1 = c1; + result->c2 = c2; + result->c3 = c3; + result->c4 = c4; + return result; +} + +CS_ENCRYPTION_RESULT_RANDOMNESS *create_CS_ENCRYPTION_RESULT_RANDOMNESS( + CS_ENCRYPTION_RESULT *cs_encryption_result, + bi_ptr randomness +) { + CS_ENCRYPTION_RESULT_RANDOMNESS *result = + (CS_ENCRYPTION_RESULT_RANDOMNESS *) + malloc(sizeof(CS_ENCRYPTION_RESULT_RANDOMNESS)); + + if (result == NULL) { + LogError("malloc of %d bytes failed", + sizeof(CS_ENCRYPTION_RESULT_RANDOMNESS)); + return NULL; + } + result->randomness = randomness; + result->result = cs_encryption_result; + return result; +} + +bi_ptr compute_u( const EVP_MD *digest, + const bi_ptr c1, + const bi_ptr c2, + const bi_ptr c3, + const BYTE *condition, + const int conditionLength +) { + BYTE *buffer, *bytes; + int c1_size = bi_nbin_size( c1); + int c2_size = bi_nbin_size( c2); + int c3_size = bi_nbin_size( c3); + int index = 0; + int length; + bi_ptr value; + int bufferLength = c1_size + c2_size + c3_size + conditionLength; + + buffer = (BYTE *)malloc( bufferLength); + if (buffer == NULL) { + LogError("malloc of %d bytes failed", bufferLength); + return NULL; + } + bi_2_byte_array( &buffer[index], c1_size, c1); + index += c1_size; + bi_2_byte_array( &buffer[index], c2_size, c2); + index += c2_size; + bi_2_byte_array( &buffer[index], c3_size, c3); + index += c3_size; + memcpy( &buffer[index], condition, conditionLength); + index += conditionLength; + length = DAA_PARAM_LENGTH_MFG1_ANONYMITY_REVOCATION / 8; // 25 /8 + bytes = compute_bytes( bufferLength, buffer, length, digest); + if( bytes == NULL) return NULL; + value = bi_set_as_nbin( length, bytes); + free( bytes); + free( buffer); + return value; +} + +CS_ENCRYPTION_RESULT_RANDOMNESS* internal_compute_encryption_proof( + const bi_ptr msg, + const bi_ptr delta1, + const bi_ptr delta2, + const bi_ptr delta3, + const bi_ptr randomness, + const CS_PUBLIC_KEY *key, + const struct tdTSS_DAA_PK_internal *daa_key, + const BYTE *condition, + const int conditionLength, + const EVP_MD *digest +) { + bi_ptr modulus = daa_key->modulus; + bi_ptr gamma = daa_key->gamma; + bi_ptr c1 = bi_new_ptr( ); + bi_ptr c2 = bi_new_ptr( ); + bi_ptr c3 = bi_new_ptr( ); + bi_ptr c4; + bi_ptr exp; + bi_t bi_tmp; + bi_t bi_tmp1; + + bi_new( bi_tmp); + bi_new( bi_tmp1); + if( bi_cmp( msg, modulus) >= 0) { + LogError("IllegalArgument: msg to big for key size"); + bi_free_ptr( c1); + bi_free_ptr( c2); + bi_free_ptr( c3); + bi_free( bi_tmp); + bi_free( bi_tmp1); + return NULL; + } + bi_mod_exp( c1, gamma, randomness, modulus); + bi_mod_exp( c2, key->eta, randomness, modulus); + // c3=msg * (key->lambda3 ^ randomness) % mopdulus) + bi_mul( c3, msg, bi_mod_exp( bi_tmp, key->lambda3, randomness, modulus)); + bi_mod( c3, c3, modulus); // c3 = c3 % modulus + if( delta1 != NULL) { + if( !( delta2!=NULL && delta3!=NULL)) { + LogError("Illegal Arguments: delta2==NULL or delta3==NULL"); + bi_free_ptr( c1); + bi_free_ptr( c2); + bi_free_ptr( c3); + bi_free( bi_tmp); + bi_free( bi_tmp1); + return NULL; + } + exp = compute_u( digest, delta1, delta2, delta3, condition, conditionLength); + } else { + if( !( delta2==NULL && delta3==NULL)) { + LogError("Illegal Arguments: delta2!=NULL or delta3!=NULL"); + bi_free_ptr( c1); + bi_free_ptr( c2); + bi_free_ptr( c3); + bi_free( bi_tmp); + bi_free( bi_tmp1); + return NULL; + } + exp = compute_u( digest, c1, c2, c3, condition, conditionLength); + } + // exp = exp * randomness + bi_mul( exp, exp, randomness); + // exp = exp % daa_key->rho + bi_mod( exp, exp, daa_key->rho); + // bi_tmp = (key->lambda1 ^ randomness) % modulus + bi_mod_exp( bi_tmp, key->lambda1, randomness, modulus); + // bi_tmp1 = (key->lambda2 ^ exp) % modulus + bi_mod_exp( bi_tmp1, key->lambda2, exp, modulus); + c4 = bi_new_ptr(); + // c4 = bi_tmp * bi_tmp1 + bi_mul( c4, bi_tmp, bi_tmp1); + // c4 = c4 % modulus + bi_mod( c4, c4, modulus); + bi_free_ptr( exp); + bi_free( bi_tmp1); + bi_free( bi_tmp); + return create_CS_ENCRYPTION_RESULT_RANDOMNESS( + create_CS_ENCRYPTION_RESULT( c1, c2, c3, c4), + randomness); +} + +/* +Cramer-Shoup EncryptionProof +from com.ibm.zurich.tcg.daa.anonymityrevocation.CSEncryptionProof + */ +CS_ENCRYPTION_RESULT_RANDOMNESS *compute_ecryption_proof( + const bi_ptr msg, + const bi_ptr delta1, + const bi_ptr delta2, + const bi_ptr delta3, + const bi_ptr randomness, + const CS_PUBLIC_KEY *key, + const struct tdTSS_DAA_PK_internal *daa_key, + const BYTE *condition, + const int conditionLength, + const EVP_MD *digest +) { + if( delta1 == NULL || delta2 == NULL || delta3 == NULL) { + LogError("Illegal Argument: deltas (delta1:%ld delta2:%ld delta3:%ld)", + (long)delta1, (long)delta2, (long)delta3); + return NULL; + } + if( bi_cmp( randomness, daa_key->rho) >=0 || bi_cmp_si( randomness, 0) < 0) { + LogError("randomness >= rho || randomness < 0 \n\trandomness:%s\n\trho:%s\n", + bi_2_dec_char( randomness), bi_2_dec_char( daa_key->rho)); + return NULL; + } + return internal_compute_encryption_proof( msg, + delta1, + delta2, + delta3, + randomness, + key, + daa_key, + condition, + conditionLength, + digest); +} diff --git a/src/tspi/daa/daa_debug.c b/src/tspi/daa/daa_debug.c new file mode 100644 index 0000000..d39273b --- /dev/null +++ b/src/tspi/daa/daa_debug.c @@ -0,0 +1,294 @@ + + +/******************************************************************************************** +* KEY PAIR WITH PROOF +********************************************************************************************/ + +int +save_KEY_PAIR_WITH_PROOF(FILE *file, + KEY_PAIR_WITH_PROOF_internal *key_pair_with_proof) +{ + save_DAA_PK_internal( file, key_pair_with_proof->pk); + save_DAA_PRIVATE_KEY( file, key_pair_with_proof->private_key); + save_DAA_PK_PROOF_internal( file, key_pair_with_proof->proof); + + return 0; +} + +KEY_PAIR_WITH_PROOF_internal * +load_KEY_PAIR_WITH_PROOF(FILE *file) +{ + KEY_PAIR_WITH_PROOF_internal *key_pair_with_proof = + (KEY_PAIR_WITH_PROOF_internal *)malloc(sizeof(KEY_PAIR_WITH_PROOF_internal)); + + key_pair_with_proof->pk = load_DAA_PK_internal(file); + key_pair_with_proof->private_key = load_DAA_PRIVATE_KEY(file); + key_pair_with_proof->proof = load_DAA_PK_PROOF_internal(file); + + return key_pair_with_proof; +} + +int +save_DAA_PK_internal(FILE *file, const TSS_DAA_PK_internal *pk_internal) +{ + char *buffer; + + LogDebug("-> save_DAA_PK_internal"); + + BI_SAVE( pk_internal->modulus, file); + BI_SAVE( pk_internal->capitalS, file); + BI_SAVE( pk_internal->capitalZ, file); + BI_SAVE( pk_internal->capitalR0, file); + BI_SAVE( pk_internal->capitalR1, file); + BI_SAVE( pk_internal->gamma, file); + BI_SAVE( pk_internal->capitalGamma, file); + BI_SAVE( pk_internal->rho, file); + BI_SAVE_ARRAY( pk_internal->capitalRReceiver, file); + BI_SAVE_ARRAY( pk_internal->capitalRIssuer, file); + fprintf( file, "%d\n", pk_internal->issuerBaseNameLength); + buffer = (char *)malloc( pk_internal->issuerBaseNameLength + 1); + memcpy( buffer, pk_internal->issuerBaseName, pk_internal->issuerBaseNameLength); + buffer[ pk_internal->issuerBaseNameLength] = 0; + fprintf( file, "%s\n", buffer); + free( buffer); + + LogDebug("<- save_DAA_PK_internal"); + + return 0; +} + +TSS_DAA_PK_internal * +load_DAA_PK_internal(FILE *file) +{ + TSS_DAA_PK_internal *pk_internal = + (TSS_DAA_PK_internal *)malloc(sizeof(TSS_DAA_PK_internal)); + char *read_buffer; + + pk_internal->modulus = bi_new_ptr(); + BI_LOAD( pk_internal->modulus, file); + pk_internal->capitalS = bi_new_ptr(); + BI_LOAD( pk_internal->capitalS, file); + pk_internal->capitalZ = bi_new_ptr(); + BI_LOAD( pk_internal->capitalZ, file); + pk_internal->capitalR0 = bi_new_ptr(); + BI_LOAD( pk_internal->capitalR0, file); + pk_internal->capitalR1 = bi_new_ptr(); + BI_LOAD( pk_internal->capitalR1, file); + pk_internal->gamma = bi_new_ptr(); + BI_LOAD( pk_internal->gamma, file); + pk_internal->capitalGamma = bi_new_ptr(); + BI_LOAD( pk_internal->capitalGamma, file); + pk_internal->rho = bi_new_ptr(); + BI_LOAD( pk_internal->rho, file); + pk_internal->capitalRReceiver = ALLOC_BI_ARRAY(); + BI_LOAD_ARRAY( pk_internal->capitalRReceiver, file); + pk_internal->capitalRIssuer = ALLOC_BI_ARRAY(); + BI_LOAD_ARRAY( pk_internal->capitalRIssuer, file); + pk_internal->capitalY = ALLOC_BI_ARRAY(); + populate_capitalY( pk_internal); + pk_internal->issuerBaseNameLength = read_int( file); + read_buffer = read_str( file); + pk_internal->issuerBaseName = malloc( pk_internal->issuerBaseNameLength); + memcpy( pk_internal->issuerBaseName, read_buffer, pk_internal->issuerBaseNameLength); + compute_capitalSprime( pk_internal); + return pk_internal; +} + +int +save_DAA_PK_PROOF_internal(FILE *file, TSS_DAA_PK_PROOF_internal *proof) +{ + int i; + +#ifdef DAA_DEBUG + printf("save_DAA_PK_PROOF_internal"); +#endif + fprintf(file, "%d # %s.length\n", proof->length_challenge, "challenge"); + fprintf(file, "%s\n", dump_byte_array( proof->length_challenge, + proof->challenge)); + fprintf(file, "%d # %s.length\n", proof->length_response, "response"); + for (i = 0; i < proof->length_response; i++) { + BI_SAVE_ARRAY( proof->response[i], file); + } + + return 0; +} + +/* load <proof> using <filename> */ +/* allocation of: */ +/* proof->challenge (BYTE*) */ +/* response (bi_array_ptr) */ +TSS_DAA_PK_PROOF_internal * +load_DAA_PK_PROOF_internal(FILE *file) +{ + TSS_DAA_PK_PROOF_internal *proof = + (TSS_DAA_PK_PROOF_internal *)malloc(sizeof(TSS_DAA_PK_PROOF_internal)); + char *read_buffer; + int i; + +#ifdef DAA_DEBUG + printf("load_DAA_PK_PROOF_internal"); +#endif + proof->length_challenge = read_int( file); + read_buffer = read_str( file); + proof->challenge = retrieve_byte_array( &(proof->length_challenge),read_buffer); + proof->length_response = read_int( file); + proof->response = (bi_array_ptr *)malloc( sizeof(bi_array_ptr) * proof->length_response); + for (i = 0; i < proof->length_response; i++) { + proof->response[i] = ALLOC_BI_ARRAY(); + BI_LOAD_ARRAY( proof->response[i], file); + } + return proof; +} + +TSS_DAA_CRED_ISSUER * +load_TSS_DAA_CRED_ISSUER(FILE *file) +{ + TSS_DAA_CRED_ISSUER *credential = + (TSS_DAA_CRED_ISSUER *)malloc(sizeof(TSS_DAA_CRED_ISSUER)); + char *read_buffer; + int i, len; + + init_tss_version( credential); + credential->capitalALength = read_int( file); + read_buffer = read_str( file); + credential->capitalA = retrieve_byte_array( &(credential->capitalALength), + read_buffer); + credential->eLength = read_int( file); + read_buffer = read_str( file); + credential->e = retrieve_byte_array( &(credential->eLength),read_buffer); + credential->vPrimePrimeLength = read_int( file); + read_buffer = read_str( file); + credential->vPrimePrime = retrieve_byte_array(&(credential->vPrimePrimeLength), + read_buffer); + // attributes issuer + credential->attributesIssuerLength = read_int( file); + credential->attributesIssuer = malloc(credential->attributesIssuerLength*sizeof(BYTE*)); + for( i=0; i < (int)credential->attributesIssuerLength; i++) { + credential->attributesIssuer[i] = retrieve_byte_array( &len, read_buffer); + } + credential->cPrimeLength = read_int( file); + read_buffer = read_str( file); + credential->cPrime = retrieve_byte_array( &(credential->cPrimeLength),read_buffer); + credential->sELength = read_int( file); + read_buffer = read_str( file); + credential->sE = retrieve_byte_array( &(credential->sELength),read_buffer); + return credential; +} + +int +save_TSS_DAA_CRED_ISSUER(FILE *file, TSS_DAA_CRED_ISSUER *credential) +{ + int i; + + fprintf(file, "%d # %s.length\n", credential->capitalALength, "capitalA"); + fprintf(file, "%s\n", dump_byte_array( credential->capitalALength, + credential->capitalA)); + fprintf(file, "%d # %s.length\n", credential->eLength, "e"); + fprintf(file, "%s\n", dump_byte_array( credential->eLength, + credential->e)); + fprintf(file, "%d # %s.length\n", credential->vPrimePrimeLength, "vPrimePrime"); + fprintf(file, "%s\n", dump_byte_array( credential->vPrimePrimeLength, + credential->vPrimePrime)); + fprintf(file, "%d # %s\n", credential->attributesIssuerLength, "attributesIssuerLength"); + for( i=0; i < (int)credential->attributesIssuerLength; i++) { + fprintf(file, "%s\n", dump_byte_array( DAA_PARAM_SIZE_F_I / 8, + credential->attributesIssuer[i])); + + } + fprintf(file, "%d # %s.length\n", credential->cPrimeLength, "cPrime"); + fprintf(file, "%s\n", dump_byte_array( credential->cPrimeLength, + credential->cPrime)); + fprintf(file, "%d # %s.length\n", credential->sELength, "sE"); + fprintf(file, "%s\n", dump_byte_array( credential->sELength, + credential->sE)); + return 0; +} + +TSS_DAA_CREDENTIAL * +load_TSS_DAA_CREDENTIAL(FILE *file) +{ + TSS_DAA_CREDENTIAL *credential = + (TSS_DAA_CREDENTIAL *)malloc(sizeof(TSS_DAA_CREDENTIAL)); + char *read_buffer; + int i, len; + TSS_DAA_PK_internal *pk_internal; + TSS_DAA_PK *pk; + + init_tss_version( credential); + credential->capitalALength = read_int( file); + read_buffer = read_str( file); + credential->capitalA = retrieve_byte_array( &(credential->capitalALength), + read_buffer); + credential->exponentLength = read_int( file); + read_buffer = read_str( file); + credential->exponent = retrieve_byte_array( &(credential->exponentLength), + read_buffer); + credential->vBar0Length = read_int( file); + read_buffer = read_str( file); + credential->vBar0 = retrieve_byte_array(&(credential->vBar0Length), + read_buffer); + credential->vBar1Length = read_int( file); + read_buffer = read_str( file); + credential->vBar1 = retrieve_byte_array(&(credential->vBar1Length), + read_buffer); + // attributes issuer + credential->attributesLength = read_int( file); + printf("attributesLength=%d\n", credential->attributesLength); + credential->attributes = malloc(credential->attributesLength * sizeof( BYTE *)); + for( i=0; i < (int)credential->attributesLength; i++) { + read_buffer = read_str( file); + credential->attributes[i] = retrieve_byte_array( &len, read_buffer); + if( len != DAA_PARAM_SIZE_F_I / 8) { + LogError("Error when parsing attributes"); + LogError("\tattribute length:%d", len); + LogError("\texpected length:%d", DAA_PARAM_SIZE_F_I / 8); + return NULL; + } + } + pk_internal = load_DAA_PK_internal( file); + pk = i_2_e_TSS_DAA_PK( pk_internal, &normal_malloc, (TSS_HOBJECT)NULL); + memcpy( &(credential->issuerPK), pk, sizeof(TSS_DAA_PK)); + free( pk); + free_TSS_DAA_PK_internal( pk_internal); + credential->tpmSpecificEncLength = read_int( file); + read_buffer = read_str( file); + credential->tpmSpecificEnc = retrieve_byte_array( &(credential->tpmSpecificEncLength), + read_buffer); + credential->daaCounter = read_int( file); + return credential; +} + +int +save_TSS_DAA_CREDENTIAL(FILE *file, + TSS_DAA_CREDENTIAL *credential) +{ + int i; + TSS_DAA_PK_internal *pk_internal; + + fprintf(file, "%d # %s.length\n", credential->capitalALength, "capitalA"); + fprintf(file, "%s\n", dump_byte_array( credential->capitalALength, + credential->capitalA)); + fprintf(file, "%d # %s.length\n", credential->exponentLength, "exponent"); + fprintf(file, "%s\n", dump_byte_array( credential->exponentLength, + credential->exponent)); + fprintf(file, "%d # %s.length\n", credential->vBar0Length, "vBar0"); + fprintf(file, "%s\n", dump_byte_array( credential->vBar0Length, + credential->vBar0)); + fprintf(file, "%d # %s.length\n", credential->vBar1Length, "vBar1"); + fprintf(file, "%s\n", dump_byte_array( credential->vBar1Length, + credential->vBar1)); + fprintf(file, "%d # %s\n", credential->attributesLength, "attributesLength"); + for( i=0; i < (int)credential->attributesLength; i++) { + fprintf(file, "%s\n", dump_byte_array( DAA_PARAM_SIZE_F_I / 8, + credential->attributes[i])); + } + pk_internal = e_2_i_TSS_DAA_PK( &(credential->issuerPK) ); + save_DAA_PK_internal( file, pk_internal); + free_TSS_DAA_PK_internal( pk_internal); + fprintf(file, "%d # %s.length\n", credential->tpmSpecificEncLength, "tpmSpecificEnc"); + fprintf(file, "%s\n", dump_byte_array( credential->tpmSpecificEncLength, + credential->tpmSpecificEnc)); + fprintf(file, "%d # daaCounter\n", credential->daaCounter); + return 0; +} + diff --git a/src/tspi/daa/daa_debug.h b/src/tspi/daa/daa_debug.h new file mode 100644 index 0000000..368dd3d --- /dev/null +++ b/src/tspi/daa/daa_debug.h @@ -0,0 +1,66 @@ + +/******************************************************************************************** + * KEY PAIR WITH PROOF + ********************************************************************************************/ + +typedef struct tdKEY_PAIR_WITH_PROOF_internal { + TSS_DAA_PK_internal *pk; + DAA_PRIVATE_KEY_internal *private_key; + TSS_DAA_PK_PROOF_internal *proof; +} KEY_PAIR_WITH_PROOF_internal; + +int save_KEY_PAIR_WITH_PROOF( + FILE *file, + KEY_PAIR_WITH_PROOF_internal *key_pair_with_proof +); + +KEY_PAIR_WITH_PROOF_internal *load_KEY_PAIR_WITH_PROOF( + FILE *file +); + +TSS_DAA_KEY_PAIR *get_TSS_DAA_KEY_PAIR( + KEY_PAIR_WITH_PROOF_internal *key_pair_with_proof, + void * (*daa_alloc)(size_t size, TSS_HOBJECT object), + TSS_HOBJECT param_alloc +); + + +int save_DAA_PK_internal( + FILE *file, + const TSS_DAA_PK_internal *pk_internal +); + +TSS_DAA_PK_internal *load_DAA_PK_internal( + FILE *file +); + +int save_DAA_PRIVATE_KEY( + FILE *file, + const DAA_PRIVATE_KEY_internal *private_key +); + +DAA_PRIVATE_KEY_internal *load_DAA_PRIVATE_KEY( + FILE *file +); + +int save_DAA_PK_PROOF_internal( + FILE *file, + TSS_DAA_PK_PROOF_internal *pk_internal +); + +TSS_DAA_PK_PROOF_internal *load_DAA_PK_PROOF_internal( + FILE *file +); + +TSS_DAA_CRED_ISSUER *load_TSS_DAA_CRED_ISSUER( FILE *file); + +int save_TSS_DAA_CRED_ISSUER( FILE *file, TSS_DAA_CRED_ISSUER *credential); + +TSS_DAA_CREDENTIAL *load_TSS_DAA_CREDENTIAL( FILE *file); + +int save_TSS_DAA_CREDENTIAL( + FILE *file, + TSS_DAA_CREDENTIAL *credential +); + + diff --git a/src/tspi/daa/daa_issuer/issue_credential.c b/src/tspi/daa/daa_issuer/issue_credential.c new file mode 100644 index 0000000..0602dcb --- /dev/null +++ b/src/tspi/daa/daa_issuer/issue_credential.c @@ -0,0 +1,787 @@ + +/* + * Licensed Materials - Property of IBM + * + * trousers - An open source TCG Software Stack + * + * (C) Copyright International Business Machines Corp. 2006 + * + */ + + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +// for message digest +#include <openssl/evp.h> + +#include <stdlib.h> +#include "daa_structs.h" +#include "daa_parameter.h" +#include "trousers/tss.h" +#include "spi_internal_types.h" +#include "spi_utils.h" +#include <trousers/trousers.h> +#include <spi_utils.h> +#include <obj.h> +#include "tsplog.h" +#include "tss/tcs.h" +#include "platform.h" +// to include compute_zeta +#include "verifier.h" + +// from UBigInteger (computePrime) +// remark: the type bi_t (bi_ptr) can not used a certaintity for probable_prime +// as used in UbigInteger. (certaintity: DAA_PARAM_SAFETY) +void compute_prime( bi_ptr e, int length, int interval) { + do { + bi_urandom( e, interval - 1); + bi_setbit( e, length - 1); + } while( bi_is_probable_prime( e) == 0); +} + +/* + code derived from verifyAuthenticity (IssuerTransaction.java) +*/ +TSS_RESULT verify_authentificity(TSS_DAA_CREDENTIAL_REQUEST *credentialRequest, + TSS_DAA_JOIN_ISSUER_SESSION *joinSession) { + EVP_MD_CTX mdctx; + BYTE *modulus_N0_bytes; + BYTE *digest_n0; + BYTE *contextHash; + BYTE *capitalUPrime_bytes; + BYTE *hash; + UINT32 digest_n0Length, contextHashLength, hashLength, daaCount; + bi_ptr capitalUPrime =NULL; + bi_ptr modulus_N0 = NULL; + TSS_RESULT result = TSS_SUCCESS; + char *buffer; + + modulus_N0 = bi_new_ptr(); + buffer = BN_bn2hex( ((RSA *)joinSession->issuerAuthPK)->n); + if( buffer == NULL) { + LogError("malloc of hexadecimal representation failed"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_set_as_hex( modulus_N0, buffer); + // in TPM, N0 is hashed by hashing the scratch (256 bytes) so it must + // be formatted according to the scratch size (TPM_DAA_SIZE_issuerModulus) + modulus_N0_bytes = (BYTE *)malloc( TPM_DAA_SIZE_issuerModulus); + if (modulus_N0_bytes == NULL) { + LogError("malloc of %d bytes failed", TPM_DAA_SIZE_issuerModulus); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_2_byte_array( modulus_N0_bytes, TPM_DAA_SIZE_issuerModulus, modulus_N0); + bi_free_ptr( modulus_N0); + + if( TPM_DAA_SIZE_issuerModulus * 8 != DAA_PARAM_KEY_SIZE) { + LogError("TPM_DAA_SIZE_issuerModulus * 8 (%d) != DAA_PARAM_KEY_SIZE(%d)", + TPM_DAA_SIZE_issuerModulus*8, DAA_PARAM_KEY_SIZE); + return TSS_E_INTERNAL_ERROR; + } + EVP_DigestInit(&mdctx, DAA_PARAM_get_message_digest()); + // digestN0 = hash( modulus_N0) see Appendix B of spec. and TPM join stage 7 and 8 + EVP_DigestUpdate(&mdctx, modulus_N0_bytes, TPM_DAA_SIZE_issuerModulus); + digest_n0Length = EVP_MD_CTX_size(&mdctx); + digest_n0 = (BYTE *)malloc( digest_n0Length); + if (digest_n0 == NULL) { + LogError("malloc of %d bytes failed", digest_n0Length); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + EVP_DigestFinal(&mdctx, digest_n0, NULL); + + // test if credentialRequest->authenticationProof = + // H( H( U, daaCount, H(n0), joinSession->nonceEncrypted)) + EVP_DigestInit(&mdctx, DAA_PARAM_get_message_digest()); + // enlarge capitalU to 256 (TPM_DAA_SIZE_issuerModulus) + // allocation + capitalUPrime = bi_set_as_nbin( joinSession->capitalUprimeLength, joinSession->capitalUprime); + capitalUPrime_bytes = (BYTE *)malloc( TPM_DAA_SIZE_issuerModulus); + if (capitalUPrime_bytes == NULL) { + LogError("malloc of %d bytes failed", TPM_DAA_SIZE_issuerModulus); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_2_byte_array( capitalUPrime_bytes, TPM_DAA_SIZE_issuerModulus, capitalUPrime); + EVP_DigestUpdate(&mdctx, capitalUPrime_bytes, TPM_DAA_SIZE_issuerModulus); + bi_free_ptr( capitalUPrime); + daaCount = htonl( joinSession->daaCounter); + EVP_DigestUpdate(&mdctx, &daaCount, sizeof(UINT32)); + EVP_DigestUpdate(&mdctx, digest_n0, digest_n0Length); + contextHashLength = EVP_MD_CTX_size(&mdctx); + contextHash = (BYTE *)malloc( contextHashLength); + if (contextHash == NULL) { + LogError("malloc of %d bytes failed", contextHashLength); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + EVP_DigestFinal(&mdctx, contextHash, NULL); + EVP_DigestInit(&mdctx, DAA_PARAM_get_message_digest()); + LogDebug("PK(0).n=%s", dump_byte_array( TPM_DAA_SIZE_issuerModulus, modulus_N0_bytes)); + LogDebug("digestN0h=%s", dump_byte_array( digest_n0Length, digest_n0)); + LogDebug("UPrime=%s", dump_byte_array( TPM_DAA_SIZE_issuerModulus, capitalUPrime_bytes)); + LogDebug("daaCount=%4x", daaCount); + + LogDebug("contextHash[%d]=%s", contextHashLength, dump_byte_array( contextHashLength, contextHash)); + EVP_DigestUpdate(&mdctx, contextHash, contextHashLength); + EVP_DigestUpdate(&mdctx, joinSession->nonceEncrypted, joinSession->nonceEncryptedLength); + hashLength = EVP_MD_CTX_size(&mdctx); + hash = (BYTE *)malloc( hashLength); + if (hash == NULL) { + LogError("malloc of %d bytes failed", hashLength); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + EVP_DigestFinal(&mdctx, hash, NULL); + if( credentialRequest->authenticationProofLength != hashLength || + memcmp( credentialRequest->authenticationProof, hash, hashLength) != 0) { + LogError("Verification of authenticationProof failed - Step 2.b"); + LogError("credentialRequest->authenticationProof[%d]=%s", + credentialRequest->authenticationProofLength, + dump_byte_array( credentialRequest->authenticationProofLength, + credentialRequest->authenticationProof)); + LogError("internal cByte[%d]=%s", + hashLength, + dump_byte_array( hashLength, hash)); + result = TSS_E_DAA_AUTHENTICATION_ERROR; + goto close; + } else + LogDebug("verify_authenticity Done:%s", + dump_byte_array( hashLength, hash)); +close: + free( contextHash); + free( digest_n0); + free( capitalUPrime_bytes); + free( hash); + return result; +} + +TSS_RESULT +compute_join_challenge_issuer( TSS_DAA_PK_internal *pk_intern, + bi_ptr v_prime_prime, + bi_ptr capitalA, + bi_ptr capital_Atilde, + UINT32 nonceReceiverLength, + BYTE *nonceReceiver, + UINT32 *c_primeLength, + BYTE **c_prime) { // out allocation + EVP_MD_CTX mdctx; + BYTE *encoded_pk; + BYTE *byte_array; + UINT32 encoded_pkLength; + + byte_array = (BYTE *)malloc( DAA_PARAM_SIZE_RND_VALUE_CERTIFICATE / 8); // allocation + if (byte_array == NULL) { + LogError("malloc of %d bytes failed", DAA_PARAM_SIZE_RND_VALUE_CERTIFICATE / 8); + return TSPERR(TSS_E_OUTOFMEMORY); + } + EVP_DigestInit(&mdctx, DAA_PARAM_get_message_digest()); + encoded_pk = encoded_DAA_PK_internal( &encoded_pkLength, pk_intern); + EVP_DigestUpdate(&mdctx, encoded_pk, encoded_pkLength); + LogDebug( "issuerPk: %s", dump_byte_array( encoded_pkLength, encoded_pk)); + bi_2_byte_array( byte_array, DAA_PARAM_SIZE_RND_VALUE_CERTIFICATE / 8, v_prime_prime); + EVP_DigestUpdate(&mdctx, byte_array, DAA_PARAM_SIZE_RND_VALUE_CERTIFICATE / 8); + LogDebug( "vPrimePrime: %s", + dump_byte_array( DAA_PARAM_SIZE_RND_VALUE_CERTIFICATE / 8, byte_array)); + free( byte_array); + // allocation + byte_array = (BYTE *)malloc( DAA_PARAM_SIZE_RSA_MODULUS / 8); + if (byte_array == NULL) { + LogError("malloc of %d bytes failed", DAA_PARAM_SIZE_RSA_MODULUS / 8); + return TSPERR(TSS_E_OUTOFMEMORY); + } + bi_2_byte_array( byte_array, DAA_PARAM_SIZE_RSA_MODULUS / 8, capitalA); + EVP_DigestUpdate(&mdctx, byte_array, DAA_PARAM_SIZE_RSA_MODULUS / 8); + LogDebug( "capitalA: %s", dump_byte_array( DAA_PARAM_SIZE_RSA_MODULUS / 8, byte_array)); + bi_2_byte_array( byte_array, DAA_PARAM_SIZE_RSA_MODULUS / 8, capital_Atilde); + EVP_DigestUpdate(&mdctx, byte_array, DAA_PARAM_SIZE_RSA_MODULUS / 8); + LogDebug( "capital_Atilde: %s", + dump_byte_array( DAA_PARAM_SIZE_RSA_MODULUS / 8, byte_array)); + EVP_DigestUpdate(&mdctx, nonceReceiver, nonceReceiverLength); + LogDebug( "nonceReceiver: %s", + dump_byte_array( nonceReceiverLength, nonceReceiver)); + *c_primeLength = EVP_MD_CTX_size(&mdctx); + *c_prime = (BYTE *)malloc( *c_primeLength); + if (*c_prime == NULL) { + LogError("malloc of %d bytes failed", *c_primeLength); + free( byte_array); + return TSPERR(TSS_E_OUTOFMEMORY); + } + LogDebug( "c_prime: %s", dump_byte_array( *c_primeLength, *c_prime)); + EVP_DigestFinal(&mdctx, *c_prime, NULL); + free( byte_array); + return TSS_SUCCESS; +} + +// inspired by computeCredentialProof (IssuerTransaction.java) +TSS_RESULT +compute_credential_proof( TSS_DAA_PK_internal *pk_intern, + bi_ptr capital_A, + bi_ptr fraction_A, + bi_ptr eInverse, + bi_ptr v_prime_prime, + bi_ptr productPQprime, + UINT32 noncePlatformLength, + BYTE *noncePlatform, + bi_ptr *c_prime, // out + bi_ptr *s_e // out +) { + bi_ptr random_E = bi_new_ptr(); + bi_ptr capital_Atilde = bi_new_ptr(); + BYTE *c_prime_bytes; + UINT32 c_primeLength; + + bi_urandom( random_E, bi_length( productPQprime) + DAA_PARAM_SAFETY_MARGIN * 8); + bi_mod( random_E, random_E, productPQprime); + bi_inc( random_E); + bi_mod_exp( capital_Atilde, fraction_A, random_E, pk_intern->modulus); + compute_join_challenge_issuer( pk_intern, + v_prime_prime, + capital_A, + capital_Atilde, + noncePlatformLength, + noncePlatform, + &c_primeLength, + &c_prime_bytes); // allocation + *c_prime = bi_set_as_nbin( c_primeLength, c_prime_bytes); // allocation + *s_e = bi_new_ptr(); + bi_mul( *s_e, *c_prime, eInverse); + bi_mod( *s_e, *s_e, productPQprime); + bi_sub( *s_e, random_E, *s_e); + bi_mod( *s_e, *s_e, productPQprime); + bi_free_ptr( capital_Atilde); + bi_free_ptr( random_E); + free( c_prime_bytes); + return TSS_SUCCESS; +} + +// from IssuerTransaction.java (joinStep2) +// stacks: TCGApplication.java (retrieveDAACredential) -> Issuer.java(issueCredential) +TSPICALL Tspi_DAA_IssueCredential_internal +( + TSS_HDAA hDAA, // in + UINT32 attributesIssuerLength, // in + BYTE** attributesIssuer, // in + TSS_DAA_CREDENTIAL_REQUEST credentialRequest, // in + TSS_DAA_JOIN_ISSUER_SESSION joinSession, // in + TSS_DAA_CRED_ISSUER* credIssuer // out +) { + TSS_RESULT result = TSS_SUCCESS; + TCS_CONTEXT_HANDLE tcsContext; + bi_ptr capitalU_hat_prime = NULL; + bi_ptr tmp1; + bi_ptr tmp2; + bi_ptr sa_i; + bi_ptr capitalU_prime = NULL; + bi_ptr c = NULL; + bi_ptr n = NULL; + bi_ptr sf0 = NULL; + bi_ptr sf1 = NULL; + bi_ptr sv_prime = NULL; + bi_ptr capitalR0 = NULL; + bi_ptr capitalR1 = NULL; + bi_ptr capitalS = NULL; + bi_ptr capitalU = NULL; + bi_ptr capitalU_hat = NULL; + bi_ptr capitalN_hat_i = NULL; + bi_ptr exp = NULL; + bi_ptr product_attr_receiver = NULL; + bi_ptr product_attr_issuer = NULL; + bi_ptr sv_tilde_prime = NULL; + bi_ptr capital_ni = NULL; + bi_ptr v_hat = NULL; + bi_ptr fraction_A = NULL; + bi_ptr capitalA = NULL; + bi_ptr e = NULL; + bi_ptr eInverse = NULL; + bi_ptr v_prime_prime = NULL; + bi_ptr c_prime = NULL; + bi_ptr s_e = NULL; + bi_ptr zeta = NULL; + TSS_DAA_PK *daa_pk_extern; + TSS_DAA_PK_internal *pk_intern; + TSS_DAA_PRIVATE_KEY *private_key; + UINT32 i, chLength, challengeLength, length, interval; + EVP_MD_CTX mdctx; + BYTE *ch = NULL, *challenge = NULL; + + tmp1 = bi_new_ptr(); + tmp2 = bi_new_ptr(); + if( tmp1 == NULL || tmp2 == NULL) { + LogError("malloc of BI <%s> failed", "tmp1, tmp2"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + if( (result = obj_daa_get_tsp_context( hDAA, &tcsContext)) != TSS_SUCCESS) goto close; + // 1 TODO Check the TPM rogue list + + // 2 verify the authentication proof of the TPM + result = verify_authentificity(&credentialRequest, &joinSession); + if( result != TSS_SUCCESS) goto close; + daa_pk_extern = (TSS_DAA_PK *)(((TSS_DAA_KEY_PAIR *)joinSession.issuerKeyPair)->public_key); + pk_intern = e_2_i_TSS_DAA_PK( daa_pk_extern); + n = bi_set_as_nbin( daa_pk_extern->modulusLength, + daa_pk_extern->modulus); // allocation + if( n == NULL) { + LogError("malloc of BI <%s> failed", "n"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + capitalR0 = bi_set_as_nbin( daa_pk_extern->capitalR0Length, + daa_pk_extern->capitalR0); // allocation + if( capitalR0 == NULL) { + LogError("malloc of BI <%s> failed", "capitalR0"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + capitalR1 = bi_set_as_nbin( daa_pk_extern->capitalR1Length, + daa_pk_extern->capitalR1); // allocation + if( capitalR1 == NULL) { + LogError("malloc of BI <%s> failed", "capitalR1"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + capitalS = bi_set_as_nbin( daa_pk_extern->capitalSLength, + daa_pk_extern->capitalS); // allocation + if( capitalS == NULL) { + LogError("malloc of BI <%s> failed", "capitalS"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + capitalU = bi_set_as_nbin( credentialRequest.capitalULength, + credentialRequest.capitalU); // allocation + if( capitalU == NULL) { + LogError("malloc of BI <%s> failed", "capitalU"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + sv_tilde_prime = bi_set_as_nbin( credentialRequest.sVtildePrimeLength, + credentialRequest.sVtildePrime); // allocation + if( sv_tilde_prime == NULL) { + LogError("malloc of BI <%s> failed", "sv_tilde_prime"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + capital_ni = bi_set_as_nbin( credentialRequest.capitalNiLength, + credentialRequest.capitalNi); // allocation + if( capital_ni == NULL) { + LogError("malloc of BI <%s> failed", "capital_ni"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + // 3 Verify the correctness proof of the credential request + // 3.a TODO commitments + + // 3.b + capitalU_prime = bi_set_as_nbin( joinSession.capitalUprimeLength, + joinSession.capitalUprime); // allocation + if( capitalU_prime == NULL) { + LogError("malloc of BI <%s> failed", "capitalU_prime"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + sf0 = bi_set_as_nbin( credentialRequest.sF0Length, + credentialRequest.sF0); // allocation + if( sf0 == NULL) { + LogError("malloc of BI <%s> failed", "sf0"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + sf1 = bi_set_as_nbin( credentialRequest.sF1Length, + credentialRequest.sF1); // allocation + if( sf1 == NULL) { + LogError("malloc of BI <%s> failed", "sf1"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + sv_prime = bi_set_as_nbin( credentialRequest.sVprimeLength, + credentialRequest.sVprime); // allocation + if( sv_prime == NULL) { + LogError("malloc of BI <%s> failed", "sv_prime"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + c = bi_set_as_nbin( credentialRequest.challengeLength, + credentialRequest.challenge); // allocation + if( c == NULL) { + LogError("malloc of BI <%s> failed", "c"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + capitalU_hat_prime = bi_new_ptr();// allocation + if( capitalU_hat_prime == NULL) { + LogError("malloc of BI <%s> failed", "c"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + // capitalU_hat_prime = capitalU_prime ~% n + bi_invert_mod( capitalU_hat_prime, capitalU_prime, n); + // capitalU_hat_prime = ( capitalU_hat_prime ^ c ) % n + bi_mod_exp( capitalU_hat_prime, capitalU_hat_prime, c, n); + // capitalU_hat_prime = ( capitalU_hat_prime * ( capitalR0 ^ sf0)) % n + bi_mod_exp( tmp1, capitalR0, sf0, n); + bi_mul( capitalU_hat_prime, capitalU_hat_prime, tmp1); + bi_mod( capitalU_hat_prime, capitalU_hat_prime, n); + // capitalU_hat_prime = ( capitalU_hat_prime * ( capitalR1 ^ sf1)) % n + bi_mod_exp( tmp1, capitalR1, sf1, n); + bi_mul( capitalU_hat_prime, capitalU_hat_prime, tmp1); + bi_mod( capitalU_hat_prime, capitalU_hat_prime, n); + // capitalU_hat_prime = ( capitalU_hat_prime * ( capitalS ^ sv_prime)) % n + bi_mod_exp( tmp1, capitalS, sv_prime, n); + bi_mul( capitalU_hat_prime, capitalU_hat_prime, tmp1); + bi_mod( capitalU_hat_prime, capitalU_hat_prime, n); + // verify blinded encoded attributes of the Receiver + product_attr_receiver = bi_new_ptr(); + bi_set( product_attr_receiver, bi_1); + length = ( DAA_PARAM_SIZE_RANDOMIZED_ATTRIBUTES + 7) / 8; + for( i=0; i<credentialRequest.sALength; i++) { + sa_i = bi_set_as_nbin( length, credentialRequest.sA[i]); // allocation + if( sa_i == NULL) { + LogError("malloc of BI <%s> failed", "sa_i"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_mod_exp( tmp1, pk_intern->capitalRReceiver->array[i], sa_i, n); + bi_mul( product_attr_receiver, product_attr_receiver, tmp1); + bi_mod( product_attr_receiver, product_attr_receiver, n); + bi_free_ptr( sa_i); + } + // tmp1 = ( 1 / capitalU ) % n + bi_invert_mod( tmp1, capitalU, n); + capitalU_hat = bi_new_ptr(); + if( capitalU_hat == NULL) { + LogError("malloc of BI <%s> failed", "capitalU_hat"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_mul( capitalU_hat, capitalU_prime, tmp1); + // capitalU_hat = capitalU_prime / capitalU + bi_mod( capitalU_hat, capitalU_hat, n); + // capital_Uhat = ( (capital_Uhat ^ c ) % n + bi_mod_exp( capitalU_hat, capitalU_hat, c, n); + // capital_Uhat = ( capital_Uhat * ( capitalS ^ sv_tilde_prime) % n ) % n + bi_mod_exp( tmp1, pk_intern->capitalS, sv_tilde_prime, n); + bi_mul( capitalU_hat, capitalU_hat, tmp1); + bi_mod( capitalU_hat, capitalU_hat, n); + bi_mul( capitalU_hat, capitalU_hat, product_attr_receiver); + bi_mod( capitalU_hat, capitalU_hat, n); + // capital_Nhat_i = (( capital_Ni ~% pk_intern->capitalGamma ) ^ c ) % pk_intern->capitalGamma + capitalN_hat_i = bi_new_ptr(); + bi_invert_mod( capitalN_hat_i, capital_ni, pk_intern->capitalGamma); + bi_mod_exp( capitalN_hat_i, capitalN_hat_i, c, pk_intern->capitalGamma); + // exp = sf1 << (DAA_PARAM_SIZE_F_I) + sf0 + exp = bi_new_ptr(); + if( exp == NULL) { + LogError("malloc of BI <%s> failed", "exp"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_shift_left( exp, sf1, DAA_PARAM_SIZE_F_I); + bi_add( exp, exp, sf0); + zeta = compute_zeta( pk_intern->issuerBaseNameLength, + pk_intern->issuerBaseName, + pk_intern); + // capital_Nhat_i = ( capital_Nhat_i * + // ( ( issuer.zeta ^ exp) % pk->capitalGamma) ) % pk->capitalGamma + bi_mod_exp( tmp1, zeta, exp, pk_intern->capitalGamma); + bi_mul( capitalN_hat_i, capitalN_hat_i, tmp1); + bi_mod( capitalN_hat_i, capitalN_hat_i, pk_intern->capitalGamma); + + LogDebug("calculation Uhat: capitalS:%s\n", bi_2_hex_char( pk_intern->capitalS)); + LogDebug("calculation Uhat: sv_tilde_prime:%s\n", bi_2_hex_char( sv_tilde_prime)); + LogDebug("calculation Uhat: n:%s\n", bi_2_hex_char( n)); + LogDebug("calculation Uhat: product_attributes:%s\n", bi_2_hex_char( product_attr_receiver)); + LogDebug("calculation NhatI: zeta:%s\n", bi_2_hex_char( zeta)); + LogDebug("calculation NhatI: exp:%s\n", bi_2_hex_char( exp)); + LogDebug("calculation NhatI: capitalGamma:%s\n", bi_2_hex_char( pk_intern->capitalGamma)); + // calculate challenge + result = compute_join_challenge_host(hDAA, + pk_intern, + capitalU, + capitalU_prime, + capitalU_hat, + capitalU_hat_prime, + capital_ni, + capitalN_hat_i, + 0, // TODO: commitmentsProofLength + NULL, // TODO: commits + joinSession.nonceIssuerLength, + joinSession.nonceIssuer, + &chLength, // out + &ch); // out allocation + if( result != TSS_SUCCESS) goto close; + LogDebug("JoinChallengeHost: %s", dump_byte_array( chLength, ch)); + EVP_DigestInit(&mdctx, DAA_PARAM_get_message_digest()); + EVP_DigestUpdate(&mdctx, ch, chLength); + challengeLength = EVP_MD_CTX_size( &mdctx); + challenge = (BYTE *)malloc( challengeLength); + if( challenge == NULL) { + LogError("malloc of %d bytes failed", challengeLength); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + EVP_DigestUpdate(&mdctx, credentialRequest.nonceTpm, credentialRequest.nonceTpmLength); + EVP_DigestFinal(&mdctx, challenge, NULL); + // checks + if( credentialRequest.challengeLength != challengeLength || + memcmp( credentialRequest.challenge, challenge, challengeLength)!=0) { + LogError("Verification of c failed - Step 3.f.i"); + LogError("credentialRequest.challenge[%d]=%s", + credentialRequest.challengeLength, + dump_byte_array( credentialRequest.challengeLength, + credentialRequest.challenge)); + LogError("challenge[%d]=%s", + challengeLength, + dump_byte_array( challengeLength, challenge)); + result = TSS_E_DAA_CREDENTIAL_REQUEST_PROOF_ERROR; + goto close; + } + // + 1 because the result of ( rA(43 bits) + c(20 bits) * a(13 bits)) can + // shift 1 bit above the normal size (43 bits) + length = DAA_PARAM_SIZE_RANDOMIZED_ATTRIBUTES + 1; + if( bi_length( sf0) > (long)length) { + LogError( "Verification of sF0 failed - Step 3.f.ii"); + LogError("\tsf0 bits length: %d expected maximum length:%d\n", + (int)bi_length( sf0), (int)length); + result = TSS_E_DAA_CREDENTIAL_REQUEST_PROOF_ERROR; + goto close; + } + if( bi_length( sf1) > (long)length) { + LogError( "Verification of sF1 failed - Step 3.f.ii"); + LogError("\tsf1 length: %d expected maximum length:%d\n", + (int)bi_length( sf1), (int)length); + result = TSS_E_DAA_CREDENTIAL_REQUEST_PROOF_ERROR; + goto close; + } + // blinded attributes + length = DAA_PARAM_SIZE_RANDOMIZED_ATTRIBUTES; + for( i=0; i<credentialRequest.sALength; i++) { + sa_i = bi_set_as_nbin( ( length + 7) / 8, credentialRequest.sA[i]); // allocation + if( sa_i == NULL) { + LogError("malloc of BI <%s> failed", "sa_i"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + if( bi_length( sa_i) > (long)length) { + LogError("Verification of sA[%d] failed - Step 3.f.ii", i); + LogError("sA.length=%d length=%d", (int)bi_length( sa_i), length); + result = TSS_E_DAA_CREDENTIAL_REQUEST_PROOF_ERROR; + goto close; + } + bi_free_ptr( sa_i); + if( result != TSS_SUCCESS) goto close; + } + length = DAA_PARAM_SIZE_RSA_MODULUS + 2 * DAA_PARAM_SAFETY_MARGIN + + DAA_PARAM_SIZE_MESSAGE_DIGEST; + if( bi_length( sv_prime) > (int)length) { + LogError("Verification of sVprime failed - Step 3.f.iii\n"); + LogError("\tsv_prime bits length: %d expected maximum length:%d\n", + (int)bi_length( sv_prime), (int)length); + result = TSS_E_DAA_CREDENTIAL_REQUEST_PROOF_ERROR; + goto close; + } + if( bi_nbin_size( sv_tilde_prime) > (int)length) { + LogError("Verification of sVtildePrime failed - Step 3.f.iii"); + LogError("\tsv_tilde_prime bits length: %d expected maximum length:%d\n", + (int)bi_length( sv_tilde_prime), (int)length); + result = TSS_E_DAA_CREDENTIAL_REQUEST_PROOF_ERROR; + goto close; + } + // compute credential + v_hat = bi_new_ptr(); + if( v_hat == NULL) { + LogError("malloc of BI <%s> failed", "v_hat"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_urandom( v_hat, DAA_PARAM_SIZE_RND_VALUE_CERTIFICATE - 1); + length = DAA_PARAM_SIZE_EXPONENT_CERTIFICATE; + interval = DAA_PARAM_SIZE_INTERVAL_EXPONENT_CERTIFICATE; + e = bi_new_ptr(); + if( e == NULL) { + LogError("malloc of BI <%s> failed", "e"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + compute_prime( e, length, interval); + + // v'' = ( 1 << DAA_PARAM_SIZE_RND_VALUE_CERTIFICATE) + v_hat + v_prime_prime = bi_new_ptr(); + bi_shift_left( tmp1, bi_1, DAA_PARAM_SIZE_RND_VALUE_CERTIFICATE - 1); + bi_add( v_prime_prime, tmp1, v_hat); + + // fraction_A = (( pk->capitalS ^ v``) % n) * capitalU + fraction_A = bi_new_ptr(); + if( fraction_A == NULL) { + LogError("malloc of BI <%s> failed", "fraction_A"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_mod_exp( fraction_A, pk_intern->capitalS, v_prime_prime, n); + bi_mul( fraction_A, fraction_A, capitalU); + bi_mod( fraction_A, fraction_A, n); + + // encode attributes + bi_free_ptr( tmp1); + product_attr_issuer = bi_new_ptr(); + if( product_attr_issuer == NULL) { + LogError("malloc of BI <%s> failed", "product_attr_issuer"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_set( product_attr_issuer, bi_1); + for( i=0; i< attributesIssuerLength; i++) { + tmp1 = bi_set_as_nbin( DAA_PARAM_SIZE_F_I / 8, attributesIssuer[i]); // allocation + bi_mod_exp( tmp2, pk_intern->capitalRIssuer->array[i], tmp1, n); + bi_mul( product_attr_issuer, product_attr_issuer, tmp2); + bi_mod( product_attr_issuer, product_attr_issuer, n); + bi_free_ptr( tmp1); + } + tmp1 = bi_new_ptr(); + if( tmp1 == NULL) { + LogError("malloc of BI <%s> failed", "tmp1"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_mul( fraction_A, fraction_A, product_attr_issuer); + bi_mod( fraction_A, fraction_A, n); + + bi_invert_mod( fraction_A, fraction_A, n); + bi_mul( fraction_A, fraction_A, pk_intern->capitalZ); + bi_mod( fraction_A, fraction_A, n); + + private_key = (TSS_DAA_PRIVATE_KEY *) + (((TSS_DAA_KEY_PAIR *)joinSession.issuerKeyPair)->private_key); + bi_free_ptr( tmp2); + tmp2 = bi_set_as_nbin( private_key->productPQprimeLength, + private_key->productPQprime); // allocation + if( tmp2 == NULL) { + LogError("malloc of BI <%s> failed", "tmp2"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + eInverse = bi_new_ptr(); + if( eInverse == NULL) { + LogError("malloc of BI <%s> failed", "eInverse"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_invert_mod( eInverse, e, tmp2); + capitalA = bi_new_ptr(); + if( capitalA == NULL) { + LogError("malloc of BI <%s> failed", "capitalA"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + LogDebug("fraction_A[%ld]=%s", bi_nbin_size( fraction_A), bi_2_hex_char( fraction_A)); + LogDebug("eInverse[%ld]=%s", bi_nbin_size( eInverse), bi_2_hex_char( eInverse)); + LogDebug("productPQprime[%ld]=%s", bi_nbin_size( tmp2), bi_2_hex_char( tmp2)); + LogDebug("eInverse[%ld]=%s", bi_nbin_size( eInverse), bi_2_hex_char( eInverse)); + LogDebug("e[%ld]=%s", bi_nbin_size( e), bi_2_hex_char( e)); + LogDebug("n[%ld]=%s", bi_nbin_size( n), bi_2_hex_char( n)); + bi_mod_exp( capitalA, fraction_A, eInverse, n); + + compute_credential_proof( pk_intern, + capitalA, + fraction_A, + eInverse, + v_prime_prime, + tmp2, // productPQprime + credentialRequest.noncePlatformLength, + credentialRequest.noncePlatform, + &c_prime, // out: allocation + &s_e); // out: allocation + // populate credIssuer (TSS_DAA_CRED_ISSUER *) + credIssuer->capitalA = calloc_tspi( tcsContext, bi_nbin_size( capitalA)); + if( credIssuer->capitalA == NULL) { + LogError("malloc of %ld bytes failed", bi_nbin_size( capitalA)); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_2_nbin1( &(credIssuer->capitalALength), credIssuer->capitalA, capitalA); + credIssuer->e = calloc_tspi( tcsContext, bi_nbin_size( e)); + if( credIssuer->e == NULL) { + LogError("malloc of %ld bytes failed", bi_nbin_size( e)); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_2_nbin1( &(credIssuer->eLength), credIssuer->e, e); + credIssuer->vPrimePrime = calloc_tspi( tcsContext, bi_nbin_size( v_prime_prime)); + if( credIssuer->vPrimePrime == NULL) { + LogError("malloc of %ld bytes failed", bi_nbin_size( v_prime_prime)); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_2_nbin1( &(credIssuer->vPrimePrimeLength), credIssuer->vPrimePrime, v_prime_prime); + // attributes issuer + credIssuer->attributesIssuerLength = attributesIssuerLength; + credIssuer->attributesIssuer = calloc_tspi( tcsContext, + attributesIssuerLength * sizeof( BYTE *)); + if( credIssuer->attributesIssuer == NULL) { + LogError("malloc of %d bytes failed", attributesIssuerLength * sizeof( BYTE *)); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + for( i=0; i< attributesIssuerLength; i++) { + credIssuer->attributesIssuer[i] = calloc_tspi( tcsContext, DAA_PARAM_SIZE_F_I / 8); + if( credIssuer->attributesIssuer[i] == NULL) { + LogError("malloc of %d bytes failed", DAA_PARAM_SIZE_F_I / 8); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + memcpy( credIssuer->attributesIssuer[i], attributesIssuer[i], DAA_PARAM_SIZE_F_I / 8); + } + credIssuer->cPrime = calloc_tspi( tcsContext, bi_nbin_size( c_prime)); + if( credIssuer->cPrime == NULL) { + LogError("malloc of %ld bytes failed", bi_nbin_size( c_prime)); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_2_nbin1( &(credIssuer->cPrimeLength), credIssuer->cPrime, c_prime); + credIssuer->sE = calloc_tspi( tcsContext, bi_nbin_size( s_e)); + if( credIssuer->sE == NULL) { + LogError("malloc of %ld bytes failed", bi_nbin_size( s_e)); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_2_nbin1( &(credIssuer->sELength), credIssuer->sE, s_e); + +close: + //free_TSS_DAA_PK( daa_pk_extern); + if( ch != NULL) free( ch); + if( challenge != NULL) free( challenge); + FREE_BI( tmp1); + FREE_BI( tmp2); + FREE_BI( s_e); + FREE_BI( c_prime); + FREE_BI( capitalA); + FREE_BI( v_prime_prime); + FREE_BI( eInverse); + FREE_BI( e); + FREE_BI( fraction_A); + FREE_BI( v_hat); + FREE_BI( capital_ni); + FREE_BI( sv_tilde_prime); + FREE_BI( product_attr_receiver); + FREE_BI( product_attr_issuer); + FREE_BI( capitalU_hat_prime); + FREE_BI( capitalU_prime); + FREE_BI( sv_prime); + FREE_BI( exp); + FREE_BI( capitalN_hat_i); + FREE_BI( capitalU_hat); + FREE_BI( capitalU); + FREE_BI( capitalS); + FREE_BI( capitalR1); + FREE_BI( capitalR0); + FREE_BI( sf1); + FREE_BI( sf0); + FREE_BI( n); + FREE_BI( c); + FREE_BI( zeta); + return result; +} diff --git a/src/tspi/daa/daa_issuer/issuer_init.c b/src/tspi/daa/daa_issuer/issuer_init.c new file mode 100644 index 0000000..788bb8d --- /dev/null +++ b/src/tspi/daa/daa_issuer/issuer_init.c @@ -0,0 +1,142 @@ + +/* + * Licensed Materials - Property of IBM + * + * trousers - An open source TCG Software Stack + * + * (C) Copyright International Business Machines Corp. 2006 + * + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +// for message digest +#include <openssl/evp.h> + +#include <stdlib.h> +#include "daa_structs.h" +#include "daa_parameter.h" +#include "trousers/tss.h" +#include "spi_internal_types.h" +#include "spi_utils.h" +#include <trousers/trousers.h> +#include <spi_utils.h> +#include <obj.h> +#include "tsplog.h" +#include "tss/tcs.h" + +/* +Verifies if the key is a valid endorsement key of a TPM. (TPM is good) +return 0 if correct + */ +int verify_ek_and_daaCounter( + UINT32 endorsementLength, + BYTE *endorsementCredential, + UINT32 daaCounter +) { + // TODO + return 0; +} + + +TSS_RESULT Tspi_DAA_IssueInit_internal( + TSS_HDAA hDAA, // in + TSS_HKEY issuerAuthPK, // in + TSS_HKEY issuerKeyPair, // in (TSS_DAA_KEY_PAIR *) + TSS_DAA_IDENTITY_PROOF identityProof, // in + UINT32 capitalUprimeLength, // in + BYTE* capitalUprime, // in + UINT32 daaCounter, // in + UINT32* nonceIssuerLength, // out + BYTE** nonceIssuer, // out + UINT32* authenticationChallengeLength, // out + BYTE** authenticationChallenge, // out + TSS_DAA_JOIN_ISSUER_SESSION* joinSession // out +) { + TCS_CONTEXT_HANDLE tcsContext; + TSS_RESULT result; + BYTE *ne, *buffer; + bi_t random; + int length_ne; + + if( (result = obj_daa_get_tsp_context( hDAA, &tcsContext)) != TSS_SUCCESS) + return result; + // 1 & 2 : verify EK (and associated credentials) of the platform + if( verify_ek_and_daaCounter( identityProof.endorsementLength, + identityProof.endorsementCredential, daaCounter) != 0) { + LogError("EK verification failed"); + return TSS_E_INTERNAL_ERROR; + } + + // 3 : choose a random nonce for the platform (ni) + bi_new( random); + bi_urandom( random, DAA_PARAM_LENGTH_MESSAGE_DIGEST * 8); + buffer = bi_2_nbin( nonceIssuerLength, random); + if( buffer == NULL) { + LogError("malloc of %d bytes failed", *nonceIssuerLength); + return TSPERR(TSS_E_OUTOFMEMORY); + } + *nonceIssuer = convert_alloc( tcsContext, *nonceIssuerLength, buffer); + if (*nonceIssuer == NULL) { + LogError("malloc of %d bytes failed", *nonceIssuerLength); + free( buffer); + return TSPERR(TSS_E_OUTOFMEMORY); + } + + LogDebug("nonce Issuer[%d:%d]:%s", DAA_PARAM_LENGTH_MESSAGE_DIGEST, + *nonceIssuerLength, + dump_byte_array( *nonceIssuerLength , *nonceIssuer)); + + // 4 : choose a random nonce ne and encrypt it under EK + bi_urandom( random, DAA_PARAM_LENGTH_MESSAGE_DIGEST * 8); + ne = convert_alloc( tcsContext, length_ne, bi_2_nbin( &length_ne, random)); + if (ne == NULL) { + LogError("malloc of %d bytes failed", length_ne); + free( buffer); + free( nonceIssuer); + return TSPERR(TSS_E_OUTOFMEMORY); + } + + bi_free( random); + *authenticationChallenge = (BYTE *)calloc_tspi( tcsContext, 256); // 256: RSA size + if (*authenticationChallenge == NULL) { + LogError("malloc of %d bytes failed", 256); + free( buffer); + free( nonceIssuer); + free( ne); + return TSPERR(TSS_E_OUTOFMEMORY); + } + result = Trspi_RSA_Encrypt( + ne, // message to encrypt + length_ne, // length message to encrypt + *authenticationChallenge, // destination + authenticationChallengeLength, // length destination + identityProof.endorsementCredential, // public key + identityProof.endorsementLength); // public key size + if( result != TSS_SUCCESS) { + LogError("Can not encrypt the Authentication Challenge"); + free( buffer); + free( nonceIssuer); + free( ne); + return TSS_E_INTERNAL_ERROR; + } + LogDebug("authenticationChallenge[%d:%d]:%s", DAA_PARAM_LENGTH_MESSAGE_DIGEST, + *authenticationChallengeLength, + dump_byte_array( *authenticationChallengeLength , *authenticationChallenge)); + + // 5 : save PK, PKDAA, (p', q'), U', daaCounter, ni, ne in joinSession + // EK is not a member of joinSession but is already saved in identityProof + joinSession->issuerAuthPK = issuerAuthPK; + joinSession->issuerKeyPair = issuerKeyPair; + memcpy( &(joinSession->identityProof), &identityProof, sizeof(TSS_DAA_IDENTITY_PROOF)); + joinSession->capitalUprimeLength = capitalUprimeLength; + joinSession->capitalUprime = capitalUprime; + joinSession->daaCounter = daaCounter; + joinSession->nonceIssuerLength = *nonceIssuerLength; + joinSession->nonceIssuer = *nonceIssuer; + joinSession->nonceEncryptedLength = length_ne; + joinSession->nonceEncrypted = ne; + return result; +} diff --git a/src/tspi/daa/daa_issuer/issuer_setup.c b/src/tspi/daa/daa_issuer/issuer_setup.c new file mode 100644 index 0000000..44e3679 --- /dev/null +++ b/src/tspi/daa/daa_issuer/issuer_setup.c @@ -0,0 +1,166 @@ +/* + * Licensed Materials - Property of IBM + * + * trousers - An open source TCG Software Stack + * + * (C) Copyright International Business Machines Corp. 2006 + * + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#include "trousers/tss.h" +#include "spi_internal_types.h" +#include "spi_utils.h" +#include "obj.h" +// #include "tcslog.h" +#include "bi.h" +#include "daa_parameter.h" +#include "issuer.h" + +static char *DEFAULT_FILENAME = "issuer.txt"; +static char *DEFAULT_ISSUER = "IBM-Issuer"; + +static const int DEFAULT_ISSUER_ATTRIBUTES = 2; // A1 A2 +static const int DEFAULT_RECEIVER_ATTRIBUTES = 3; // A3 A4 A5 + +int print_usage(char *cmd) { + fprintf(stderr, "usage: %s\n", cmd); + fprintf(stderr, " \t-npa,\t--nb_platform_attr\tnumber of attributes that the\ + Platform can choose and which will not be visible to the Issuer (default: %d)\n", + DEFAULT_ISSUER_ATTRIBUTES); + fprintf(stderr, " \t-nia,\t--nb_issuer_attr\tnumber of attributes that the issuer\ + can choose and which will be visible to both the Platform and the Issuer(default: %d)\n", + DEFAULT_RECEIVER_ATTRIBUTES); + fprintf(stderr, " \t-if,\t--issuer_file\tthe file that will contain all key pair\ + and proof to be used by the issuer (default: %s)\n", + DEFAULT_FILENAME); + fprintf(stderr, " \t-i,\t--issuer\tissuer identity (default: %s)\n", + DEFAULT_ISSUER); + return -1; +} + +int main(int argc, char *argv[]) { + int nb_platform_attr = DEFAULT_ISSUER_ATTRIBUTES; + int nb_issuer_attr = DEFAULT_RECEIVER_ATTRIBUTES; + char *filename = DEFAULT_FILENAME; + char *issuer = DEFAULT_ISSUER; + int i; + char *param; + TSS_HCONTEXT hContext; + TSS_DAA_KEY_PAIR *key_pair; + TSS_DAA_PK_PROOF *public_keyproof; + TSS_RESULT result; + TSS_HDAA hDAA; + TSS_DAA_PK_PROOF_internal *public_keyproof_internal; + TSS_DAA_PK_internal *pk; + TSS_DAA_PRIVATE_KEY *private_key; + DAA_PRIVATE_KEY_internal *private_key_internal; + KEY_PAIR_WITH_PROOF_internal *key_pair_with_proof; + + printf("Issuer Setup (%s:%s,%s)\n", argv[0], __DATE__, __TIME__); + i = 1; + while( i < argc) { + param = argv[ i]; + if ( strcmp( param, "-if") == 0 || strcmp( param, "--issuer_file")) { + i++; + if( i == argc) return print_usage( argv[0]); + filename = argv[i]; + } else if( strcmp( param, "-npa") == 0 || strcmp( param, "--nb_platform_attr")) { + i++; + if( i == argc) return print_usage( argv[0]); + nb_platform_attr = atoi( argv[i]); + } else if( strcmp( param, "-nia") == 0 || strcmp( param, "--nb_issuer_attr")) { + i++; + if( i == argc) return print_usage( argv[0]); + nb_issuer_attr = atoi(argv[i]); + } else if( strcmp( param, "-i") == 0 || strcmp( param, "--issuer")) { + i++; + if( i == argc) return print_usage( argv[0]); + issuer = argv[i]; + } else { + fprintf(stderr, "%s:unrecognized option `%s'\n", argv[0], param); + return print_usage( argv[0]); + } + i++; + } + bi_init( NULL); + // Create Context + printf("Create Context\n"); + result = Tspi_Context_Create( &hContext ); + if ( result != TSS_SUCCESS ) + { + fprintf( stderr, "Tspi_Context_Create %d\n", result ); + exit( result ); + } + + // Connect to Context + printf("Connect to the context\n"); + result = Tspi_Context_Connect( hContext, NULL ); + if ( result != TSS_SUCCESS ) + { + fprintf( stderr, "Tspi_Context_Connect error:%d\n", result ); + Tspi_Context_FreeMemory( hContext, NULL ); + Tspi_Context_Close( hContext ); + exit( result ); + } + //Create Object + result = obj_daa_add( hContext, &hDAA); + if (result != TSS_SUCCESS) { + goto close; + } + result = Tspi_DAA_IssueSetup( + hDAA, // in + strlen( issuer), // in + (BYTE *)issuer, // in + nb_platform_attr, // in + nb_issuer_attr, // in + (TSS_HKEY *)&key_pair, // out + &public_keyproof); // out + if( result != TSS_SUCCESS) goto close; + + // TSS_DAA_KEY_PAIR_internal *key_pair_internal = DAA_KEY_PAIR_2_internal( key_pair); + public_keyproof_internal = e_2_i_TSS_DAA_PK_PROOF( public_keyproof); + pk = e_2_i_TSS_DAA_PK( key_pair->public_key); + private_key = key_pair->private_key; + private_key_internal = e_2_i_TSS_DAA_PRIVATE_KEY( private_key); + key_pair_with_proof = + (KEY_PAIR_WITH_PROOF_internal *)malloc( sizeof(KEY_PAIR_WITH_PROOF_internal)); + if( key_pair_with_proof == NULL) { + fprintf("malloc of %d bytes failed", sizeof(KEY_PAIR_WITH_PROOF_internal)); + goto close; + } + key_pair_with_proof->pk = pk; + key_pair_with_proof->private_key = private_key_internal; + key_pair_with_proof->proof = public_keyproof_internal; + + printf("Saving key pair with proof -> \'%s\'", filename); + FILE *file = fopen( filename, "w"); + if( file == NULL) { + fprintf( stderr, "%s: Error when saving \'%s\': %s\n", + argv[0], + filename, + strerror( errno)); + return -1; + } + if( save_KEY_PAIR_WITH_PROOF( file, key_pair_with_proof) != 0) { + fprintf( stderr, "%s: Error when saving \'%s\': %s\n", + argv[0], + filename, + strerror( errno)); + return -1; + } + fclose( file); + printf("\nDone.\n"); +close: + obj_daa_remove( hDAA, hContext); + printf("Closing the context\n"); + Tspi_Context_FreeMemory( hContext, NULL ); + Tspi_Context_Close( hContext ); + bi_release(); + printf("Result: %d", result); + return result; +} diff --git a/src/tspi/daa/daa_issuer/key_correctness_proof.c b/src/tspi/daa/daa_issuer/key_correctness_proof.c new file mode 100644 index 0000000..505e760 --- /dev/null +++ b/src/tspi/daa/daa_issuer/key_correctness_proof.c @@ -0,0 +1,516 @@ +/* + * Licensed Materials - Property of IBM + * + * trousers - An open source TCG Software Stack + * + * (C) Copyright International Business Machines Corp. 2006 + * + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +// for little-big endian conversion +#include <arpa/inet.h> +// for message digest +#include <openssl/evp.h> + +#include "bi.h" + +#include "daa_parameter.h" +#include "list.h" +#include "daa_structs.h" + +#include "issuer.h" + +//standard bit length extension to obtain a uniformly distributed number [0,element] +static const int SAFETY_PARAM = 80; + +static bi_array_ptr get_generators( const TSS_DAA_PK_internal *pk) { + bi_array_ptr result = ALLOC_BI_ARRAY(); + int i; + + bi_new_array( result, 3 + pk->capitalY->length ); + for(i = 0; i<result->length; i++) { + result->array[i] = pk->capitalS; + } + return result; +} + +static bi_array_ptr get_verifiable_numbers( const TSS_DAA_PK_internal *pk) { + bi_array_ptr result = ALLOC_BI_ARRAY(); + int i; + + bi_new_array( result, 3 + pk->capitalY->length); + result->array[0] = pk->capitalZ; + result->array[1] = pk->capitalR0; + result->array[2] = pk->capitalR1; + // CAPITAL Y ( capitalRReceiver + capitalRIssuer) + for( i=0; i<pk->capitalY ->length; i++) + result->array[ 3+i] = pk->capitalY->array[i]; + return result; +} + +/* computes an array of random numbers in the range of [1,element] */ +void compute_random_numbers( bi_array_ptr result, int quantity, const bi_ptr element) { + int i=0; + + for( i=0; i<quantity; i++) { + compute_random_number( result->array[i], element); + bi_inc( result->array[i]); // array[i]++ + } +} + +int test_bit( int pos, BYTE* array, int length) { + return (((int)array[ length - (pos / 8) - 1]) & (1 << (pos % 8))) != 0; +} + +void toByteArray( BYTE *result, int length, bi_ptr bi, char *logMsg) { + LogDebug("-> toByteArray <%d> %s",(int)bi, logMsg); + LogDebug("lenghts <%d|%d>",length, (int)bi_nbin_size(bi)); + bi_2_byte_array( result, length, bi); + LogDebug("<- toByteArray result=%s [<%d|%d>] ", + dump_byte_array( length, result), + length, + (int)bi_nbin_size(bi)); +} + +/* +Compute the message digest used in the proof. (from DAA_Param, the digest +algorithm is RSA, but this is not available in openssl, the successor of RSA is SHA1 +*/ +TSS_RESULT +generateMessageDigest(BYTE *md_value, + int *md_len, + const TSS_DAA_PK_internal *pk, + bi_array_ptr *commitments, + const int commitments_size +) { + EVP_MD_CTX mdctx; + const EVP_MD *md; + int i, j; + int length = DAA_PARAM_SIZE_RSA_MODULUS / 8; + BYTE *array; + + // 10000 to be sure, and this memory will be released quite quickly + array = (BYTE *)malloc( 10000); + if (array == NULL) { + LogError("malloc of %d bytes failed", 10000); + return TSPERR(TSS_E_OUTOFMEMORY); + } + OpenSSL_add_all_digests(); + md = EVP_get_digestbyname( DAA_PARAM_MESSAGE_DIGEST_ALGORITHM); + EVP_MD_CTX_init(&mdctx); + EVP_DigestInit_ex(&mdctx, md, NULL); +#ifdef DAA_DEBUG + fprintf(stderr, "modulus=%s\n", bi_2_hex_char( pk->modulus)); +#endif + toByteArray( array, length, pk->modulus, + "!! [generateMessageDigest modulus] current_size=%d length=%d\n"); + EVP_DigestUpdate(&mdctx, array , length); + toByteArray( array, length, pk->capitalS, + "!! [generateMessageDigest capitalS] current_size=%d length=%d\n"); + EVP_DigestUpdate(&mdctx, array , length); + // add capitalZ, capitalR0, capitalR1, capitalY + LogDebug("capitalZ capitalR0 capitalY"); + toByteArray( array, length, pk->capitalZ, + "!! [generateMessageDigest capitalZ] current_size=%d length=%d\n"); + EVP_DigestUpdate(&mdctx, array , length); + toByteArray( array, length, pk->capitalR0, + "!! [generateMessageDigest capitalR0] current_size=%d length=%d\n"); + EVP_DigestUpdate(&mdctx, array , length); + toByteArray( array, length, pk->capitalR1, + "!! [generateMessageDigest capitalR1] current_size=%d length=%d\n"); + EVP_DigestUpdate(&mdctx, array , length); + // CAPITAL Y ( capitalRReceiver ) + LogDebug("capitalRReceiver"); + for( i=0; i<pk->capitalRReceiver->length; i++) { + toByteArray( array, length, pk->capitalRReceiver->array[i], + "!![generateMessageDigest capitalRReceiver] current_size=%d length=%d\n"); + EVP_DigestUpdate(&mdctx, array , length); + } + LogDebug("capitalRIssuer"); + // CAPITAL Y ( capitalRIssuer) + for( i=0; i<pk->capitalRIssuer->length; i++) { + toByteArray( array, length, pk->capitalRIssuer->array[i], + "!![generateMessageDigest capitalRReceiver] current_size=%d length=%d\n"); + EVP_DigestUpdate(&mdctx, array , length); + } + LogDebug("commitments"); + for( i=0; i<commitments_size; i++) { + for( j=0; j<commitments[i]->length; j++) { + toByteArray( array, length, commitments[i]->array[j], + "!! [generateMessageDigest commitments] current_size=%d length=%d\n"); + EVP_DigestUpdate(&mdctx, array , length); + } + } + EVP_DigestFinal_ex(&mdctx, md_value, md_len); + EVP_MD_CTX_cleanup(&mdctx); + free( array); + return TSS_SUCCESS; +} + +int is_range_correct( bi_ptr b, bi_ptr range) { + return bi_cmp( b, range) < 0 && bi_cmp( b, bi_0) >= 0; +} + +/* +Verifies if the parameters Z,R0,R1,RReceiver and RIssuer of the public key +were correctly computed. +pk: the public key, which one wants to verfy. +*/ +TSS_RESULT +is_pk_correct( TSS_DAA_PK_internal *public_key, + TSS_DAA_PK_PROOF_internal *proof, + int *isCorrect +) { + int bit_size_message_digest = DAA_PARAM_SIZE_MESSAGE_DIGEST; + bi_ptr n = public_key->modulus; + int num_of_variables; + int i,j; + TSS_RESULT result = TSS_SUCCESS; + BYTE verifiable_challenge[EVP_MAX_MD_SIZE]; + int length_challenge; + bi_array_ptr verifiable_numbers; + bi_array_ptr *verification_commitments = NULL; + bi_array_ptr generators = NULL; + bi_t tmp; + bi_t tmp1; +#ifdef DAA_DEBUG + FILE *f; + bi_array_ptr *commitments; +#endif + + bi_new( tmp); + bi_new( tmp1); + *isCorrect = 0; +#ifdef DAA_DEBUG + f=fopen("/tmp/commits", "r"); + commitments = (bi_array_ptr *)malloc( sizeof(bi_array_ptr) * num_of_variables); + if (commitments == NULL) { + LogError("malloc of %d bytes failed", sizeof(bi_array_ptr) * num_of_variables); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + for( i=0; i<num_of_variables; i++) { + commitments[i] = ALLOC_BI_ARRAY(); + BI_LOAD_ARRAY( commitments[i], f); + } + fclose(f); + DUMP_BI( n); +#endif + LogDebug("STEP 1 ( Tspi_DAA_IssuerKeyVerification spec.)"); + if( !bi_is_probable_prime( public_key->capitalGamma)) { + LogError( "pk->capitalGamma not prime\ncapitalGamma=\n%s", + bi_2_hex_char( public_key->capitalGamma)); + result = TSS_E_BAD_PARAMETER; + goto close; + } + if( !bi_is_probable_prime( public_key->rho)) { + LogError( "pk->rho not prime\nrho=\n%s", + bi_2_hex_char( public_key->rho)); + result = TSS_E_BAD_PARAMETER; + goto close; + } + // (capitalGamma - 1) % rho should be equal to 0 + if( !bi_equals( bi_mod( tmp1, bi_sub( tmp1, public_key->capitalGamma, bi_1), + public_key->rho), + bi_0)) { + LogError( "(capitalGamma - 1) %% rho != 0\nActual value:\n%s", + bi_2_hex_char( tmp1)); + result = TSS_E_BAD_PARAMETER; + } + // (gamma ^ rho) % capitalGamma should be equals to 1 + if ( !bi_equals( bi_mod_exp( tmp1, public_key->gamma, + public_key->rho, + public_key->capitalGamma), + bi_1) ) { + LogError( "(gamma ^ rho) %% capitalGamma != 1\nActual value:\n%s", + bi_2_hex_char( tmp1)); + result = TSS_E_BAD_PARAMETER; + goto close; + } + // (gamma ^ rho) % capitalGamma should be equal to 1 + if ( !bi_equals( bi_mod_exp( tmp1, + public_key->gamma, + public_key->rho, + public_key->capitalGamma), + bi_1) ) { + LogError( "(gamma ^ rho) %% capitalGamma != 1\nActual value:\n%s", + bi_2_hex_char( tmp1)); + result = TSS_E_BAD_PARAMETER; + goto close; + } + LogDebug("STEP 2 check whether all public key parameters have the required length"); + if( bi_nbin_size( n) != DAA_PARAM_SIZE_RSA_MODULUS / 8) { + LogError( "size( n)[%ld] != DAA_PARAM_SIZE_RSA_MODULUS[%d]", + bi_nbin_size( n), + DAA_PARAM_SIZE_RSA_MODULUS / 8); + result = TSS_E_BAD_PARAMETER; + goto close; + } + if( bi_cmp( n, bi_shift_left( tmp1, bi_1, DAA_PARAM_SIZE_RSA_MODULUS)) + >= 0) { + LogError( "n[%ld] != DAA_PARAM_SIZE_RSA_MODULUS[%d]", + bi_nbin_size( n), + DAA_PARAM_SIZE_RSA_MODULUS); + result = TSS_E_BAD_PARAMETER; + goto close; + } + if( bi_cmp( n, bi_shift_left( tmp1, bi_1, DAA_PARAM_SIZE_RSA_MODULUS - 1 )) + <= 0) { + LogError( "n[%ld] != DAA_PARAM_SIZE_RSA_MODULUS[%d]", + bi_nbin_size( n), + DAA_PARAM_SIZE_RSA_MODULUS); + result = TSS_E_BAD_PARAMETER; + goto close; + } + // rho + if( bi_nbin_size( public_key->rho) * 8 != DAA_PARAM_SIZE_RHO) { + LogError( "size( rho)[%ld] != DAA_PARAM_SIZE_RHO[%d]", + bi_nbin_size( public_key->rho) * 8, + DAA_PARAM_SIZE_RHO); + result = TSS_E_BAD_PARAMETER; + goto close; + } + // Gamma + if( bi_nbin_size( public_key->capitalGamma) * 8 != DAA_PARAM_SIZE_MODULUS_GAMMA) { + LogError( "size( rho)[%ld] != DAA_PARAM_SIZE_MODULUS_GAMMA[%d]", + bi_nbin_size( public_key->capitalGamma) * 8, + DAA_PARAM_SIZE_MODULUS_GAMMA); + result = TSS_E_BAD_PARAMETER; + goto close; + } + if( is_range_correct( public_key->capitalS, n) == 0) { + LogError( "range not correct( pk->capitalS)\ncapitalS=\n%s\nn=\n%s", + bi_2_hex_char( public_key->capitalS), + bi_2_hex_char( n)); + result = TSS_E_BAD_PARAMETER; + goto close; + } + if( is_range_correct( public_key->capitalZ, n) == 0) { + LogError( "range not correct( pk->capitalZ)\ncapitalZ=\n%s\nn=\n%s", + bi_2_hex_char( public_key->capitalZ), + bi_2_hex_char( n)); + result = TSS_E_BAD_PARAMETER; + goto close; + } + if( is_range_correct( public_key->capitalR0, n) == 0) { + LogError( "range not correct( pk->capitalR0)\ncapitalR0=\n%s\nn=\n%s", + bi_2_hex_char( public_key->capitalR0), + bi_2_hex_char( n)); + result = TSS_E_BAD_PARAMETER; + goto close; + } + if( is_range_correct( public_key->capitalR1, n) == 0) { + LogError( "range not correct( pk->capitalR1)\ncapitalR1=\n%s\nn=\n%s", + bi_2_hex_char( public_key->capitalR1), + bi_2_hex_char( n)); + result = TSS_E_BAD_PARAMETER; + goto close; + } + for( i=0; i<public_key->capitalY->length; i++) { + if( is_range_correct( public_key->capitalY->array[i], n) == 0) { + LogError( "range not correct(pk->capitalY[%d])\ncapitalY[%d]=\n%s\nn=\n%s", + i, i, + bi_2_hex_char( public_key->capitalY->array[i]), + bi_2_hex_char( n)); + result = TSS_E_BAD_PARAMETER; + goto close; + } + } + LogDebug("STEP 3 - compute verification commitments"); + // only the array is allocated, but all refs are pointing to public_key numbers + generators = get_generators( public_key); + verifiable_numbers = get_verifiable_numbers( public_key); + num_of_variables = verifiable_numbers->length; + verification_commitments = (bi_array_ptr *)malloc( sizeof(bi_array_ptr)*num_of_variables); + if (verification_commitments == NULL) { + LogError("malloc of %d bytes failed", sizeof(bi_array_ptr)*num_of_variables); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + for( i = 0; i<num_of_variables; i++) { + verification_commitments[i] = ALLOC_BI_ARRAY(); + bi_new_array( verification_commitments[i], bit_size_message_digest); + for( j = 0; j<bit_size_message_digest; j++) { +#ifdef DAA_DEBUG + printf( "[# i=%d j=%d test_bit:%d]", + i, j, test_bit( j, proof->challenge, proof->length_challenge)); +#endif + bi_mod_exp( verification_commitments[i]->array[j], + generators->array[i], + proof->response[i]->array[j], n); + if( test_bit( j, proof->challenge, proof->length_challenge)) { + bi_mul( verification_commitments[i]->array[j], + verification_commitments[i]->array[j], + verifiable_numbers->array[i]); +#ifdef DAA_DEBUG + DUMP_BI( verification_commitments[i]->array[j]); +#endif + bi_mod( verification_commitments[i]->array[j], + verification_commitments[i]->array[j], + n); + } +#ifdef DAA_DEBUG + if( commitments != NULL && + bi_equals( verification_commitments[i]->array[j], + commitments[i]->array[j]) ==0) { + LogError( "!! ERROR i=%d j=%d\n", i, j); + DUMP_BI( commitments[i]->array[j]); + DUMP_BI( verification_commitments[i]->array[j]); + DUMP_BI( generators->array[i]); + DUMP_BI( proof->response[i]->array[j]); + DUMP_BI( verifiable_numbers->array[i]); + } + printf( "o"); fflush( stdout); +#endif + } + } + // STEP 3 - d + generateMessageDigest( verifiable_challenge, + &length_challenge, + public_key, + verification_commitments, + num_of_variables); + LogDebug("verifiable challenge=%s", + dump_byte_array( length_challenge, verifiable_challenge)); + LogDebug(" challenge=%s", + dump_byte_array( proof->length_challenge, proof->challenge)); + if( length_challenge != proof->length_challenge) { + result = TSS_E_BAD_PARAMETER; + goto close; + } + for( i=0; i<length_challenge; i++) { + if( verifiable_challenge[i] != proof->challenge[i]) { + result = TSS_E_BAD_PARAMETER; + goto close; + } + } + *isCorrect = ( memcmp( verifiable_challenge, proof->challenge, length_challenge) == 0); +close: + if( verification_commitments != NULL) { + for( i = 0; i<num_of_variables; i++) { + bi_free_array( verification_commitments[i]); + } + free( verification_commitments); + } + if( generators != NULL) free( generators); + bi_free( tmp1); + bi_free( tmp); + return result; +} + + +TSS_DAA_PK_PROOF_internal *generate_proof(const bi_ptr product_PQ_prime, + const TSS_DAA_PK_internal *public_key, + const bi_ptr xz, + const bi_ptr x0, + const bi_ptr x1, + bi_array_ptr x +) { + int i, j; + bi_array_ptr generators = get_generators( public_key); + bi_ptr n = public_key->modulus; + int num_of_variables; + int bit_size_message_digest = DAA_PARAM_SIZE_MESSAGE_DIGEST; + bi_array_ptr *xTildes = NULL; + BYTE *challenge_param; + + bi_array_ptr exponents = ALLOC_BI_ARRAY(); + bi_new_array2( exponents, 3 + x->length); + exponents->array[0] = xz; exponents->array[1] = x0; exponents->array[2] = x1; + bi_copy_array( x, 0, exponents, 3, x->length); + num_of_variables = exponents->length; + LogDebug("Step a - choose random numbers"); + LogDebug("\nchoose random numbers\n"); + xTildes = (bi_array_ptr *)malloc( sizeof(bi_array_ptr) * num_of_variables); + if (xTildes == NULL) { + LogError("malloc of %d bytes failed", sizeof(bi_array_ptr) * num_of_variables); + return NULL; + } + for( i=0; i<num_of_variables; i++) { +#ifdef DAA_DEBUG + printf("*"); + fflush(stdout); +#endif + xTildes[i] = ALLOC_BI_ARRAY(); + bi_new_array( xTildes[i], bit_size_message_digest); + compute_random_numbers( xTildes[i], bit_size_message_digest, product_PQ_prime); + } + // Compute commitments + LogDebug("\ncompute commitments"); + bi_array_ptr *commitments = + (bi_array_ptr *)malloc( sizeof(bi_array_ptr) * num_of_variables); + if (commitments == NULL) { + LogError("malloc of %d bytes failed", sizeof(bi_array_ptr) * num_of_variables); + return NULL; + } + for( i=0; i<num_of_variables; i++) { + commitments[i] = ALLOC_BI_ARRAY(); + bi_new_array( commitments[i], bit_size_message_digest); + for( j=0; j<bit_size_message_digest; j++) { +#ifdef DAA_DEBUG + printf("#"); + fflush(stdout); +#endif + bi_mod_exp( commitments[i]->array[j], + generators->array[i], + xTildes[i]->array[j], + n); + } + } +#ifdef DAA_DEBUG + FILE *f=fopen("/tmp/commits", "w"); + for( i=0; i<num_of_variables; i++) { + BI_SAVE_ARRAY( commitments[i], f); + } + fclose(f); +#endif + LogDebug("Step b: compute challenge (message digest)"); + BYTE challenge[EVP_MAX_MD_SIZE]; + int length_challenge; + generateMessageDigest( challenge, + &length_challenge, + public_key, + commitments, + num_of_variables); + // STEP c - compute response + LogDebug("Step c: compute response\n"); + bi_array_ptr *response = (bi_array_ptr *)malloc( sizeof(bi_array_ptr) * num_of_variables); + if (response == NULL) { + LogError("malloc of %d bytes failed", sizeof(bi_array_ptr) * num_of_variables); + return NULL; + } + for( i=0; i<num_of_variables; i++) { + response[i] = ALLOC_BI_ARRAY(); + bi_new_array( response[i], bit_size_message_digest); + for( j=0; j<bit_size_message_digest; j++) { + if( test_bit( j, challenge, length_challenge)) { + bi_sub( response[i]->array[j], + xTildes[i]->array[j], + exponents->array[i]); + } else { + bi_set( response[i]->array[j], + xTildes[i]->array[j]); + } + bi_mod( response[i]->array[j], response[i]->array[j], product_PQ_prime); +#ifdef DAA_DEBUG + printf("#"); + fflush(stdout); +#endif + } + } + challenge_param = (BYTE *)malloc( length_challenge); + if (challenge_param == NULL) { + LogError("malloc of %d bytes failed", length_challenge); + return NULL; + } + memcpy( challenge_param, challenge, length_challenge); + + return create_DAA_PK_PROOF( challenge_param, + length_challenge, + response, + num_of_variables); +} diff --git a/src/tspi/daa/daa_issuer/key_verification.c b/src/tspi/daa/daa_issuer/key_verification.c new file mode 100644 index 0000000..d7584f0 --- /dev/null +++ b/src/tspi/daa/daa_issuer/key_verification.c @@ -0,0 +1,147 @@ +/* + * Licensed Materials - Property of IBM + * + * trousers - An open source TCG Software Stack + * + * (C) Copyright International Business Machines Corp. 2006 + * + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#include <trousers/tss.h> +#include "spi_internal_types.h" +#include "spi_utils.h" +#include "obj.h" +#include "issuer.h" + +static char *DEFAULT_FILENAME = "issuer.txt"; + +//static TSS_HCONTEXT _hContext; + +static void *intern_alloc( size_t size, TSS_HOBJECT param_alloc) { + // void *ret = calloc_tspi( , size); + void *ret = malloc( size); + LogDebug("[intern_alloc (%d)] -> %d", (int)size, (int)ret); + return ret; +} + +void isCorrect( TSS_HDAA hDAA, + TSS_DAA_PK_internal *pk_internal, + TSS_DAA_PK_PROOF_internal *proof_internal) +{ + TSS_BOOL isCorrect; + TSS_RESULT result; + TSS_DAA_PK *pk; + TSS_DAA_PK_PROOF *pk_proof; + + pk = i_2_e_TSS_DAA_PK( pk_internal, &intern_alloc, (TSS_HOBJECT)NULL); + pk_proof = i_2_e_TSS_DAA_PK_PROOF( proof_internal, + &intern_alloc, + (TSS_HOBJECT)NULL); + result = Tspi_DAA_IssuerKeyVerification( hDAA, + (TSS_HKEY)pk, + pk_proof, + &isCorrect); + if ( result != TSS_SUCCESS ) { + fprintf( stderr, "Tspi_DAA_IssuerKeyVerification error: %d\n", result ); + } + free_TSS_DAA_PK( pk); + printf("isCorrect=%d\n", isCorrect); +} + +int print_usage(char *cmd) { + fprintf(stderr, "usage: %s\n", cmd); + fprintf(stderr, "\t-if,\t--issuer_file\tthe file that will contain\ + all key pair and proof to be used by the issuer (default: %s)\n", DEFAULT_FILENAME); + return -1; +} + +int main(int argc, char *argv[]) { + char *filename = DEFAULT_FILENAME; + int i=1; + char *param; + TSS_RESULT result; + TSS_HCONTEXT hContext; + TSS_HDAA hDAA; + FILE *file; + +// foreground = 1; // for debug + printf("Key Verification (%s:%s,%s)\n", argv[0], __DATE__, __TIME__); + while( i < argc) { + param = argv[ i]; + if( strcmp( param, "-if") == 0 || strcmp( param, "--issuer_file")) { + i++; + if( i == argc) return print_usage( argv[0]); + filename = argv[i]; + } else { + fprintf(stderr, "%s:unrecognized option `%s'\n", argv[0], param); + return print_usage( argv[0]); + } + i++; + } + bi_init( NULL); + printf("Loading issuer info (keypair & proof) -> \'%s\'", filename); + file = fopen( filename, "r"); + if( file == NULL) { + fprintf( stderr, + "%s: Error when opening \'%s\': %s\n", + argv[0], + filename, + strerror( errno)); + return -1; + } + KEY_PAIR_WITH_PROOF_internal *key_pair_with_proof = load_KEY_PAIR_WITH_PROOF( file); + if( key_pair_with_proof == NULL) { + fprintf( stderr, + "%s: Error when reading \'%s\': %s\n", + argv[0], + filename, + strerror( errno)); + return -1; + } + fclose( file); + + // Create Context + printf("\nCreate Context\n"); + result = Tspi_Context_Create( &hContext ); + if ( result != TSS_SUCCESS ) + { + fprintf( stderr, "Tspi_Context_Create %d\n", result ); + exit( result ); + } + + // Connect to Context + printf("\nConnect to the context\n"); + result = Tspi_Context_Connect( hContext, NULL ); + if ( result != TSS_SUCCESS ) + { + fprintf( stderr, "Tspi_Context_Connect error:%d\n", result ); + Tspi_Context_FreeMemory( hContext, NULL ); + Tspi_Context_Close( hContext ); + exit( result ); + } + + //TODO save key in the persistent store + // result = ps_write_key( fd, ) + + //Create Object + result = obj_daa_add( hContext, &hDAA); + if (result != TSS_SUCCESS) { + LogError("Tspi_Context_CreateObject:%d", result); + Tspi_Context_Close(hContext); + LogError("issuer_setup: %s", err_string(result)); + exit(result); + } + + // TSS_HDAA, TSS_HKEY, TSS_DAA_PK_PROOF, TSS_BOOL* + isCorrect( hDAA, key_pair_with_proof->pk, key_pair_with_proof->proof); + obj_daa_remove( hDAA, hContext); + printf("\nClosing the context\n"); + Tspi_Context_FreeMemory( hContext, NULL ); + Tspi_Context_Close( hContext ); + exit( 0 ); +} diff --git a/src/tspi/daa/daa_issuer/keypair_generator.c b/src/tspi/daa/daa_issuer/keypair_generator.c new file mode 100644 index 0000000..9a67254 --- /dev/null +++ b/src/tspi/daa/daa_issuer/keypair_generator.c @@ -0,0 +1,397 @@ +/* + * Licensed Materials - Property of IBM + * + * trousers - An open source TCG Software Stack + * + * (C) Copyright International Business Machines Corp. 2006 + * + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#include "bi.h" +#include "list.h" +#include "daa_structs.h" +#include "daa_parameter.h" +#include "issuer.h" + +static const int ELEMENT = 0; +static const int EXPONENT = 1; + +extern void prime_init(); +extern void compute_safe_prime(bi_ptr result, int bit_length, int prime_certainty); + +bi_ptr +compute_random_number_star( bi_ptr result, const bi_ptr element) +{ + bi_t bi_tmp; + + bi_new(bi_tmp); + do { + compute_random_number(result, element); + } while (!bi_equals_si(bi_gcd(bi_tmp, result, element), 1)); + + bi_free(bi_tmp); + + return result; +} + +/* Compute a generator of the group of quadratic residue modulo n. The + * generator will not be part of the subgroup of size 2. + * n: modulus */ +void +compute_generator_quadratic_residue(bi_t qr, bi_t n) +{ + bi_t bi_tmp, bi_tmp1; + + bi_new(bi_tmp); + bi_new(bi_tmp1); + + do { + compute_random_number(qr, n); + // qr = (qr ^ bi_2) % n + bi_mod_exp(qr, qr, bi_2, n); + } while (bi_cmp_si(qr, 1) == 0 || + bi_cmp_si(bi_gcd(bi_tmp, n, bi_sub_si(bi_tmp1, qr, 1)), 1) != 0); + + bi_free(bi_tmp); + bi_free(bi_tmp1); +} + +void +compute_group_element(bi_ptr result[], + bi_ptr generator, + bi_ptr product_PQprime, + bi_ptr n) +{ + bi_t bi_tmp; + + bi_new(bi_tmp); + compute_random_number(bi_tmp, product_PQprime); + + // bi_tmp++ + bi_inc(bi_tmp); + + // result[ELEMENT] := (generator ^ bi_tmp) mod n + bi_mod_exp(result[ELEMENT], generator, bi_tmp, n); + bi_set(result[EXPONENT], bi_tmp); + bi_free(bi_tmp); +} + + +TSS_RESULT +generate_key_pair(UINT32 num_attributes_issuer, + UINT32 num_attributes_receiver, + UINT32 base_nameLength, + BYTE* base_name, + KEY_PAIR_WITH_PROOF_internal** key_pair_with_proof) +{ + TSS_RESULT result = TSS_SUCCESS; + int length_mod = DAA_PARAM_SIZE_RSA_MODULUS; + int length; + int i; + TSS_DAA_PK_internal *public_key = NULL; + BYTE *buffer = NULL; + bi_ptr pPrime = NULL; + bi_ptr qPrime = NULL; + bi_ptr n = NULL; + bi_ptr p = NULL; + bi_ptr q = NULL; + bi_ptr capital_s = NULL; + bi_ptr capital_z = NULL; + bi_ptr product_PQprime = NULL; + bi_ptr pair[2] = {NULL, NULL}; + bi_ptr xz = NULL; + bi_ptr capital_r0 = NULL; + bi_ptr x0 = NULL; + bi_ptr capital_r1 = NULL; + bi_ptr x1 = NULL; + bi_array_ptr x = NULL; + bi_array_ptr capital_r = NULL; + bi_array_ptr capitalRReceiver = NULL; + bi_array_ptr capitalRIssuer = NULL; + bi_ptr gamma = NULL; + bi_ptr capital_gamma = NULL; + bi_ptr rho = NULL; + bi_ptr r = NULL; + bi_ptr rho_double = NULL; + bi_t bi_tmp, bi_tmp1, bi_tmp2; + + bi_new(bi_tmp); + bi_new(bi_tmp1); + bi_new(bi_tmp2); + *key_pair_with_proof = NULL; + + // STEP 1 + LogDebug("Step 1 of 8 - compute modulus n (please wait: long process)\n"); + + // FUTURE USAGE if( IS_DEBUG==0) + prime_init(); + p = bi_new_ptr(); + q = bi_new_ptr(); + n = bi_new_ptr(); + + do { + // FUTURE USAGE + /* compute_safe_prime( p, length_mod / 2); + do { + compute_safe_prime( q, + length_mod - (length_mod >> 1)); + } while( bi_cmp( p, q) ==0); + } else */ + { + bi_generate_safe_prime(p, length_mod / 2); + bi_generate_safe_prime(q, length_mod - (length_mod / 2)); + LogDebug("."); + } + // n = p*q + bi_mul(n, p, q); + } while(bi_length(n) != length_mod); + + pPrime = bi_new_ptr(); + bi_sub(pPrime, p, bi_1); + + // pPrime = (p - 1) >> 1 + bi_shift_right(pPrime, pPrime, 1); + qPrime = bi_new_ptr(); + bi_sub(qPrime, q, bi_1); + + // qPrime = (q - 1) >> 1 + bi_shift_right( qPrime, qPrime, 1); + if (bi_is_probable_prime(pPrime) == 0) { + LogError("!! pPrime not a prime number: %s", bi_2_hex_char(pPrime)); + result = TSPERR(TSS_E_INTERNAL_ERROR); + goto close; + } + if (bi_is_probable_prime(qPrime) == 0) { + LogError("!! qPrime not a prime number: %s", bi_2_hex_char(qPrime)); + result = TSPERR(TSS_E_INTERNAL_ERROR); + goto close; + } + LogDebug("p=%s", bi_2_hex_char(p)); + LogDebug("q=%s", bi_2_hex_char(q)); + LogDebug("n=%s", bi_2_hex_char(n)); + + // STEP 2 + LogDebug("Step 2 - choose random generator of QR_n"); + capital_s = bi_new_ptr(); + compute_generator_quadratic_residue(capital_s, n); + LogDebug("capital_s=%s", bi_2_hex_char(capital_s)); + + // STEP 3 & 4 + LogDebug("Step 3 & 4 - compute group elements"); + product_PQprime = bi_new_ptr(); + bi_mul( product_PQprime, pPrime, qPrime); + pair[ELEMENT] = bi_new_ptr(); + pair[EXPONENT] = bi_new_ptr(); + + LogDebug("product_PQprime=%s [%ld]", bi_2_hex_char(product_PQprime), + bi_nbin_size(product_PQprime)); + + compute_group_element(pair, capital_s, product_PQprime, n); + capital_z = bi_new_ptr(); + bi_set(capital_z, pair[ELEMENT]); + xz = bi_new_ptr(); + bi_set(xz, pair[EXPONENT]); + + // attributes bases + compute_group_element(pair, capital_s, product_PQprime, n); + capital_r0 = bi_new_ptr(); + bi_set(capital_r0, pair[ELEMENT]); + x0 = bi_new_ptr(); + bi_set(x0, pair[EXPONENT]); + + compute_group_element(pair, capital_s, product_PQprime, n); + capital_r1 = bi_new_ptr(); + bi_set(capital_r1, pair[ELEMENT]); + x1 = bi_new_ptr(); + bi_set(x1, pair[EXPONENT]); + + // additional attribute bases + length = num_attributes_issuer + num_attributes_receiver; + x = ALLOC_BI_ARRAY(); + bi_new_array(x, length); + capital_r = ALLOC_BI_ARRAY(); + bi_new_array(capital_r, length); + + for (i = 0; i < length; i++) { + compute_group_element(pair, capital_s, product_PQprime, n); + bi_set(capital_r->array[i], pair[ELEMENT]); + bi_set(x->array[i], pair[EXPONENT]); + } + + // split capitalR into Receiver and Issuer part + capitalRReceiver = ALLOC_BI_ARRAY(); + bi_new_array2(capitalRReceiver, num_attributes_receiver); + for (i = 0; i < num_attributes_receiver; i++) + capitalRReceiver->array[i] = capital_r->array[i]; + capitalRIssuer = ALLOC_BI_ARRAY(); + bi_new_array2(capitalRIssuer, num_attributes_issuer); + for (i = 0; i < num_attributes_issuer; i++) + capitalRIssuer->array[i] = capital_r->array[i + num_attributes_receiver]; + + // STEP 6a + LogDebug("Step 6"); + gamma = bi_new_ptr(); + capital_gamma = bi_new_ptr(); + rho = bi_new_ptr(); + r = bi_new_ptr(); + rho_double = bi_new_ptr(); + + bi_generate_prime(rho, DAA_PARAM_SIZE_RHO); + if (bi_length(rho) != DAA_PARAM_SIZE_RHO) { + LogError("rho bit length=%ld", bi_length(rho)); + result = TSPERR(TSS_E_INTERNAL_ERROR); + goto close; + } + + do { + length = DAA_PARAM_SIZE_MODULUS_GAMMA - DAA_PARAM_SIZE_RHO; + do { + bi_urandom(r, length); + } while(bi_length(r) != length || bi_equals_si(bi_mod(bi_tmp, r, rho), 0)); + + // rho is not a dividor of r + bi_mul( capital_gamma, rho, r); + // capital_gamma ++ + bi_inc( capital_gamma); +#ifdef DAA_DEBUG + if (bi_length(capital_gamma) != DAA_PARAM_SIZE_MODULUS_GAMMA) { + printf("|"); fflush(stdout); + } else { + printf("."); fflush(stdout); + } +#endif + } while (bi_length(capital_gamma) != DAA_PARAM_SIZE_MODULUS_GAMMA || + bi_is_probable_prime(capital_gamma) == 0 ); + + // STEP 6b + if (bi_equals(bi_sub_si(bi_tmp, capital_gamma, 1), + bi_mod(bi_tmp1, bi_mul(bi_tmp2, rho, r), n)) == 0) { + LogWarn("capital_gamma-1 != (rho * r) mod n tmp=%s tmp1=%s", + bi_2_hex_char(bi_tmp), bi_2_hex_char(bi_tmp1)); + } + + if (bi_equals(bi_div(bi_tmp, bi_sub_si(bi_tmp1, capital_gamma, 1), rho), r ) == 0) { + LogWarn("( capital_gamma - 1)/rho != r"); + } + + LogDebug("capital_gamma=%s\n", bi_2_hex_char(capital_gamma)); + do { + compute_random_number_star(gamma, capital_gamma); + // gamma = (gamma ^ r) mod capital_gamma + bi_mod_exp(gamma, gamma, r, capital_gamma); + } while (bi_equals(gamma, bi_1)); + // STEP 7 + buffer = (BYTE *)malloc(base_nameLength); + if (buffer == NULL) { + LogError("malloc of %u bytes failed", base_nameLength); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + memcpy(buffer, base_name, base_nameLength); + // all fields are linked to the struct with direct reference + public_key = create_DAA_PK(n, capital_s, capital_z, capital_r0, capital_r1, gamma, + capital_gamma, rho, capitalRReceiver, capitalRIssuer, + base_nameLength, buffer); + + // STEP 8 + // TODO dynamically load DAAKeyCorrectnessProof + LogDebug("Step 8: generate proof (please wait: long process)"); + TSS_DAA_PK_PROOF_internal *correctness_proof = generate_proof(product_PQprime, public_key, + xz, x0, x1, x); + if (correctness_proof == NULL) { + LogError("creation of correctness_proof failed"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + + *key_pair_with_proof = (KEY_PAIR_WITH_PROOF_internal *) + malloc(sizeof(KEY_PAIR_WITH_PROOF_internal)); + if (*key_pair_with_proof == NULL) { + LogError("malloc of %zd bytes failed", sizeof(KEY_PAIR_WITH_PROOF_internal)); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + + (*key_pair_with_proof)->pk = public_key; + (*key_pair_with_proof)->proof = correctness_proof; + // all fields are linked to the struct with direct reference + (*key_pair_with_proof)->private_key = create_TSS_DAA_PRIVATE_KEY(pPrime, qPrime); +close: + if (result != TSS_SUCCESS) { + // remove everything, even numbers that should be stored in a struct + FREE_BI(pPrime); // kept if no error + FREE_BI(qPrime); // kept if no error + FREE_BI(n); // kept if no error + // FREE_BI( p); + // FREE_BI( q); + FREE_BI(capital_s); // kept if no error + FREE_BI(capital_z); // kept if no error + // FREE_BI(product_PQprime); + // FREE_BI(pair[ELEMENT]); + // FREE_BI(pair[EXPONENT]); + // FREE_BI(xz); + FREE_BI(capital_r0); // kept if no error + // FREE_BI(x0); + FREE_BI(capital_r1); // kept if no error + // FREE_BI( x1); + // bi_array_ptr x = NULL; + // bi_array_ptr capital_r = NULL; + // bi_array_ptr capitalRReceiver = NULL; + // bi_array_ptr capitalRIssuer = NULL; + FREE_BI( gamma); // kept if no error + FREE_BI( capital_gamma); // kept if no error + FREE_BI( rho); // kept if no error + // FREE_BI( r); + // FREE_BI( rho_double); + if (buffer!=NULL) + free(buffer); + + if (public_key != NULL) + free(public_key); + + if (*key_pair_with_proof != NULL) + free(*key_pair_with_proof); + } + /* + Fields kept by structures + TSS_DAA_PK: n + capital_s + capital_z + capital_r0 + capital_r1 + gamma + capital_gamma + rho + capitalRReceiver + capitalRIssuer + base_nameLength + buffer + TSS_DAA_PRIVATE_KEY: + pPrime + qPrime + */ + bi_free(bi_tmp); + bi_free(bi_tmp1); + bi_free(bi_tmp2); + FREE_BI(p); + FREE_BI(q); + FREE_BI(product_PQprime); + FREE_BI(pair[ELEMENT]); + FREE_BI(pair[EXPONENT]); + FREE_BI(xz); + FREE_BI(x0); + FREE_BI(x0); + // bi_array_ptr x = NULL; + // bi_array_ptr capital_r = NULL; + // bi_array_ptr capitalRReceiver = NULL; + // bi_array_ptr capitalRIssuer = NULL; + FREE_BI(r); + FREE_BI(rho_double); + + return result; +} diff --git a/src/tspi/daa/daa_issuer/prime_gen.c b/src/tspi/daa/daa_issuer/prime_gen.c new file mode 100644 index 0000000..27c4026 --- /dev/null +++ b/src/tspi/daa/daa_issuer/prime_gen.c @@ -0,0 +1,327 @@ +/* + * Licensed Materials - Property of IBM + * + * trousers - An open source TCG Software Stack + * + * (C) Copyright International Business Machines Corp. 2004, 2005 + * + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "bi.h" +#include "list.h" +#include "tsplog.h" + +static unsigned long *primes; +static int primes_length; + +/* Generates a random number of bit_length bit length. The first two bits and the last bit of this + * number are always set, therefore the number is odd and >= (2^(bit_length-1)+2^(bit_length-2)+1) + * + * bit_length: The length of the number to be generated, in bits + * return: a random number of bitLength bit length with first and last bits set + */ +void +random_odd_bi(bi_ptr bi, int bit_length) +{ + if (bit_length > 0) { + bi_urandom(bi, bit_length); + //bi_generate_prime(bi, bit_length); + bi_setbit(bi, 0); + bi_setbit(bi, bit_length - 1); + bi_setbit(bi, bit_length - 2); + } +} + +/* This method generates small prime numbers up to a specified bounds using the Sieve of + * Eratosthenes algorithm. + * + * prime_bound: the upper bound for the primes to be generated + * starting_prime: the first prime in the list of primes that is returned + * return: list of primes up to the specified bound. Each prime is of type bi_ptr + */ +void +generate_small_primes(int prime_bound, int starting_prime) +{ + list_ptr res; + int length; + int *is_primes; + int i; + int k; + int prime; + node_t *current; + + primes_length = 0; + res = list_new(); + if (allocs == NULL) { + LogError("malloc of list failed"); + return; + } + if ((prime_bound <= 1) || (starting_prime > prime_bound)) + return; + + if (starting_prime <= 2) { + starting_prime = 2; + list_add(res, bi_2); + } + length = (prime_bound - 1) >> 1; // length = (prime_bound -1) / 2; + is_primes = (int *)malloc(sizeof(int)*length); + if (is_primes == NULL) { + LogError("malloc of %zd bytes failed", sizeof(int) * length); + return; + } + + for (i = 0; i < length; i++) + is_primes[i] = 1; + + for (i = 0; i < length; i++) { + if (is_primes[i] == 1) { + prime = 2 * i + 3; + for (k = i + prime; k < length; k+= prime) + is_primes[k] = 0; + + if (prime >= starting_prime) { + list_add(res, (void *)prime); + primes_length++; + } + } + } + // converti the list to a table + current = res->head; // go to first node + primes = (unsigned long *)malloc(sizeof(unsigned long) * primes_length); + if (primes == NULL) { + LogError("malloc of %d bytes failed", + sizeof(unsigned long)*primes_length); + return; + } + + i = 0; + while (current != NULL) { + primes[i++] = (unsigned long)current->obj; + current = current->next; // traverse through the list + } + + free(is_primes); + list_freeall(res); +} + +void +prime_init() +{ + generate_small_primes(16384, 3); +} + +/* Test whether the provided pDash or p = 2*pDash + 1 are divisible by any of the small primes + * saved in the listOfSmallPrimes. A limit for the largest prime to be tested against can be + * specified, but it will be ignored if it exeeds the number of precalculated primes. + * + * p_dash: the number to be tested (p_dash) + * prime_bound: the limit for the small primes to be tested against. + */ +static int +test_small_prime_factors(const bi_ptr p_dash, const unsigned long prime_bound) +{ + int sievePassed = 1; + unsigned long r; + unsigned long small_prime; + bi_t temp; bi_new(temp); + + small_prime = 1; + int i = 0; + while (i < primes_length && small_prime < prime_bound ) { + small_prime = primes[i++]; + // r = p_dash % small_prime + bi_mod_si(temp, p_dash, small_prime); + r = bi_get_si(temp); + // test if pDash = 0 (mod smallPrime) + if (r == 0) { + sievePassed = 0; + break; + } + // test if p = 0 (mod smallPrime) (or r == smallPrime - r - 1) + if (r == (small_prime - r - 1)) { + sievePassed = 0; + break; + } + } + bi_free(temp); + + return sievePassed; +} + +/* Tests if a is a Miller-Rabin witness for n + * + * a: number which is supposed to be the witness + * n: number to be tested against + * return: true if a is Miller-Rabin witness for n, false otherwise + */ +int +is_miller_rabin_witness(const bi_ptr a, const bi_ptr n) +{ + bi_t n_1; + bi_t temp; + bi_t _2_power_t; + bi_t u; + bi_t x0; + bi_t x1; + int t = -1; + int i; + + bi_new(n_1); + bi_new(temp); + bi_new(_2_power_t); + bi_new(u); + + // n1 = n - 1 + bi_sub_si(n_1, n, 1); + + // test if n-1 = 2^t*u with t >= 1 && u even + do { + t++; + // _2_power_t = bi_1 << t ( == 2 ^ t) + bi_shift_left(_2_power_t, bi_1, t); + // u = n_1 / (2 ^ t) + bi_div(u, n_1, _2_power_t); + } while (bi_equals_si(bi_mod(temp, u, bi_2), 0)); + + bi_new(x0); + bi_new(x1); + + // x1 = (a ^ u ) % n + bi_mod_exp(x1, a, u, n); + + // finished to use u, _2_power_t and temp + bi_free(u); + bi_free(_2_power_t); + bi_free(temp); + for (i = 0; i < t; i++) { + bi_set(x0, x1); + + // x1 = (x0 ^ 2) % n + bi_mod_exp(x1, x0, bi_2, n); + if (bi_equals_si(x1, 1) && !bi_equals_si(x0, 1) && !bi_equals(x0, n_1) != 0) { + bi_free(x0); + bi_free(x1); + bi_free(n_1); + return 1; + } + } + + bi_free(x0); + bi_free(x1); + bi_free(n_1); + + if (!bi_equals(x1, bi_1)) + return 1; + + return 0; +} + +bi_ptr +compute_trivial_safe_prime(bi_ptr result, int bit_length) +{ + LogDebugFn("Enter"); + do { + bi_generate_prime(result, bit_length-1); + bi_shift_left(result, result, 1); // result := result << 1 + bi_add_si(result, result, 1); // result := result -1 + if (getenv("TSS_DEBUG_OFF") == NULL) { + printf("."); + fflush(stdout); + } + } while (bi_is_probable_prime(result)==0); + + return result; +} + +/* The main method to compute a random safe prime of the specified bit length. + * IMPORTANT: The computer prime will have two first bits and the last bit set to 1 !! + * i.e. > (2^(bitLength-1)+2^(bitLength-2)+1). This is done to be sure that if two primes of + * bitLength n are multiplied, the result will have the bitLenght of 2*n exactly This + * implementation uses the algorithm proposed by Ronald Cramer and Victor Shoup in "Signature + * Schemes Based on the strong RSA Assumption" May 9, 2000. + * + * bitLength: the bit length of the safe prime to be computed. + * return: a number which is considered to be safe prime + */ +bi_ptr +compute_safe_prime(bi_ptr p, int bit_length) +{ + bi_ptr p_dash; + bi_ptr temp_p; + bi_ptr p_minus_1; + int stop; + unsigned long prime_bound; + + LogDebug("compute Safe Prime: length: %d bits\n", bit_length); + + p_dash = bi_new_ptr(); + temp_p = bi_new_ptr(); + p_minus_1 = bi_new_ptr(); + + /* some heuristic checks to limit the number of small primes to check against and the + * number of Miller-Rabin primality tests at the end */ + if (bit_length <= 256) { + prime_bound = 768; + } else if (bit_length <= 512) { + prime_bound = 3072; + } else if (bit_length <= 768) { + prime_bound = 6144; + } else if (bit_length <= 1024) { + prime_bound = 1024; + } else { + prime_bound = 16384; + } + + do { + stop = 0; + /* p_dash = generated random with basic bit settings (odd) */ + random_odd_bi(p_dash, bit_length - 1); + + if (test_small_prime_factors(p_dash, prime_bound) == 0) { + LogDebugFn("1"); + continue; + } + /* test if p_dash or p are divisible by some small primes */ + if (is_miller_rabin_witness(bi_2, p_dash)) { + LogDebugFn("2"); + continue; + } + /* test if 2^(pDash) = +1/-1 (mod p) + * bi can not handle negative operation, we compare to (p-1) instead of -1 + * calculate p = 2*pDash+1 -> (pDash << 1) + 1 + */ + bi_shift_left(p, p_dash, 1); + bi_add(p, p, bi_1); + + // p_minus_1:= p - 1 + bi_sub(p_minus_1, p, bi_1); + + // temp_p := ( 2 ^ p_dash ) mod p + bi_mod_exp(temp_p, bi_2, p_dash, p); + if (!bi_equals_si(temp_p, 1) && !bi_equals(temp_p, p_minus_1) ) { + LogDebugFn("3"); + continue; + } + + // test if pDash or p are divisible by some small primes + if (is_miller_rabin_witness(bi_2, p_dash)) { + LogDebugFn("4"); + continue; + } + // test the library dependent probable_prime + if (bi_is_probable_prime(p_dash)) + stop = 1; + } while (stop == 0); + + bi_free(p_minus_1); + bi_free(temp_p); + bi_free(p_dash); + + LogDebug("found Safe Prime: %s bits", bi_2_hex_char(p)); + + return p; +} diff --git a/src/tspi/daa/daa_parameter.c b/src/tspi/daa/daa_parameter.c new file mode 100644 index 0000000..58f240f --- /dev/null +++ b/src/tspi/daa/daa_parameter.c @@ -0,0 +1,184 @@ + +/* + * Licensed Materials - Property of IBM + * + * trousers - An open source TCG Software Stack + * + * (C) Copyright International Business Machines Corp. 2006 + * + */ + +#include "daa_parameter.h" + +setenv("TCSD_FOREGROUND", "1", 1); + +static EVP_MD *digest = NULL; + +extern EVP_MD *DAA_PARAM_get_message_digest(void) { + if( digest == NULL) { + OpenSSL_add_all_digests(); + digest = EVP_get_digestbyname( DAA_PARAM_MESSAGE_DIGEST_ALGORITHM); + } + return digest; +} + +// from common.c (ltp-tss) +char *err_string(TSS_RESULT r) +{ + /* Check the return code to see if it is common to all layers. + * If so, return it. + */ + switch (TSS_ERROR_CODE(r)) { + case TSS_SUCCESS: return "TSS_SUCCESS"; + default: + break; + } + + /* The return code is either unknown, or specific to a layer */ + if (TSS_ERROR_LAYER(r) == TSS_LAYER_TPM) { + switch (TSS_ERROR_CODE(r)) { + case TCPA_E_AUTHFAIL: return "TCPA_E_AUTHFAIL"; + case TCPA_E_BADINDEX: return "TCPA_E_BADINDEX"; + case TCPA_E_AUDITFAILURE: return "TCPA_E_AUDITFAILURE"; + case TCPA_E_CLEAR_DISABLED: return "TCPA_E_CLEAR_DISABLED"; + case TCPA_E_DEACTIVATED: return "TCPA_E_DEACTIVATED"; + case TCPA_E_DISABLED: return "TCPA_E_DISABLED"; + case TCPA_E_DISABLED_CMD: return "TCPA_E_DISABLED_CMD"; + case TCPA_E_FAIL: return "TCPA_E_FAIL"; + case TCPA_E_INACTIVE: return "TCPA_E_INACTIVE"; + case TCPA_E_INSTALL_DISABLED: return "TCPA_E_INSTALL_DISABLED"; + case TCPA_E_INVALID_KEYHANDLE: return "TCPA_E_INVALID_KEYHANDLE"; + case TCPA_E_KEYNOTFOUND: return "TCPA_E_KEYNOTFOUND"; + case TCPA_E_NEED_SELFTEST: return "TCPA_E_NEED_SELFTEST"; + case TCPA_E_MIGRATEFAIL: return "TCPA_E_MIGRATEFAIL"; + case TCPA_E_NO_PCR_INFO: return "TCPA_E_NO_PCR_INFO"; + case TCPA_E_NOSPACE: return "TCPA_E_NOSPACE"; + case TCPA_E_NOSRK: return "TCPA_E_NOSRK"; + case TCPA_E_NOTSEALED_BLOB: return "TCPA_E_NOTSEALED_BLOB"; + case TCPA_E_OWNER_SET: return "TCPA_E_OWNER_SET"; + case TCPA_E_RESOURCES: return "TCPA_E_RESOURCES"; + case TCPA_E_SHORTRANDOM: return "TCPA_E_SHORTRANDOM"; + case TCPA_E_SIZE: return "TCPA_E_SIZE"; + case TCPA_E_WRONGPCRVAL: return "TCPA_E_WRONGPCRVAL"; + case TCPA_E_BAD_PARAM_SIZE: return "TCPA_E_BAD_PARAM_SIZE"; + case TCPA_E_SHA_THREAD: return "TCPA_E_SHA_THREAD"; + case TCPA_E_SHA_ERROR: return "TCPA_E_SHA_ERROR"; + case TCPA_E_FAILEDSELFTEST: return "TCPA_E_FAILEDSELFTEST"; + case TCPA_E_AUTH2FAIL: return "TCPA_E_AUTH2FAIL"; + case TCPA_E_BADTAG: return "TCPA_E_BADTAG"; + case TCPA_E_IOERROR: return "TCPA_E_IOERROR"; + case TCPA_E_ENCRYPT_ERROR: return "TCPA_E_ENCRYPT_ERROR"; + case TCPA_E_DECRYPT_ERROR: return "TCPA_E_DECRYPT_ERROR"; + case TCPA_E_INVALID_AUTHHANDLE: return "TCPA_E_INVALID_AUTHHANDLE"; + case TCPA_E_NO_ENDORSEMENT: return "TCPA_E_NO_ENDORSEMENT"; + case TCPA_E_INVALID_KEYUSAGE: return "TCPA_E_INVALID_KEYUSAGE"; + case TCPA_E_WRONG_ENTITYTYPE: return "TCPA_E_WRONG_ENTITYTYPE"; + case TCPA_E_INVALID_POSTINIT: return "TCPA_E_INVALID_POSTINIT"; + case TCPA_E_INAPPROPRIATE_SIG: return "TCPA_E_INAPPROPRIATE_SIG"; + case TCPA_E_BAD_KEY_PROPERTY: return "TCPA_E_BAD_KEY_PROPERTY"; + case TCPA_E_BAD_MIGRATION: return "TCPA_E_BAD_MIGRATION"; + case TCPA_E_BAD_SCHEME: return "TCPA_E_BAD_SCHEME"; + case TCPA_E_BAD_DATASIZE: return "TCPA_E_BAD_DATASIZE"; + case TCPA_E_BAD_MODE: return "TCPA_E_BAD_MODE"; + case TCPA_E_BAD_PRESENCE: return "TCPA_E_BAD_PRESENCE"; + case TCPA_E_BAD_VERSION: return "TCPA_E_BAD_VERSION"; + case TCPA_E_RETRY: return "TCPA_E_RETRY"; + default: return "UNKNOWN TPM ERROR"; + } + } else if (TSS_ERROR_LAYER(r) == TSS_LAYER_TDDL) { + switch (TSS_ERROR_CODE(r)) { + case TSS_E_FAIL: return "TSS_E_FAIL"; + case TSS_E_BAD_PARAMETER: return "TSS_E_BAD_PARAMETER"; + case TSS_E_INTERNAL_ERROR: return "TSS_E_INTERNAL_ERROR"; + case TSS_E_NOTIMPL: return "TSS_E_NOTIMPL"; + case TSS_E_PS_KEY_NOTFOUND: return "TSS_E_PS_KEY_NOTFOUND"; + case TSS_E_KEY_ALREADY_REGISTERED: return "TSS_E_KEY_ALREADY_REGISTERED"; + case TSS_E_CANCELED: return "TSS_E_CANCELED"; + case TSS_E_TIMEOUT: return "TSS_E_TIMEOUT"; + case TSS_E_OUTOFMEMORY: return "TSS_E_OUTOFMEMORY"; + case TSS_E_TPM_UNEXPECTED: return "TSS_E_TPM_UNEXPECTED"; + case TSS_E_COMM_FAILURE: return "TSS_E_COMM_FAILURE"; + case TSS_E_TPM_UNSUPPORTED_FEATURE: return "TSS_E_TPM_UNSUPPORTED_FEATURE"; + case TDDL_E_COMPONENT_NOT_FOUND: return "TDDL_E_COMPONENT_NOT_FOUND"; + case TDDL_E_ALREADY_OPENED: return "TDDL_E_ALREADY_OPENED"; + case TDDL_E_BADTAG: return "TDDL_E_BADTAG"; + case TDDL_E_INSUFFICIENT_BUFFER: return "TDDL_E_INSUFFICIENT_BUFFER"; + case TDDL_E_COMMAND_COMPLETED: return "TDDL_E_COMMAND_COMPLETED"; + case TDDL_E_ALREADY_CLOSED: return "TDDL_E_ALREADY_CLOSED"; + case TDDL_E_IOERROR: return "TDDL_E_IOERROR"; + default: return "UNKNOWN TDDL ERROR"; + } + } else if (TSS_ERROR_LAYER(r) == TSS_LAYER_TCS) { + switch (TSS_ERROR_CODE(r)) { + case TSS_E_FAIL: return "TSS_E_FAIL"; + case TSS_E_BAD_PARAMETER: return "TSS_E_BAD_PARAMETER"; + case TSS_E_INTERNAL_ERROR: return "TSS_E_INTERNAL_ERROR"; + case TSS_E_NOTIMPL: return "TSS_E_NOTIMPL"; + case TSS_E_PS_KEY_NOTFOUND: return "TSS_E_PS_KEY_NOTFOUND"; + case TSS_E_KEY_ALREADY_REGISTERED: return "TSS_E_KEY_ALREADY_REGISTERED"; + case TSS_E_CANCELED: return "TSS_E_CANCELED"; + case TSS_E_TIMEOUT: return "TSS_E_TIMEOUT"; + case TSS_E_OUTOFMEMORY: return "TSS_E_OUTOFMEMORY"; + case TSS_E_TPM_UNEXPECTED: return "TSS_E_TPM_UNEXPECTED"; + case TSS_E_COMM_FAILURE: return "TSS_E_COMM_FAILURE"; + case TSS_E_TPM_UNSUPPORTED_FEATURE: return "TSS_E_TPM_UNSUPPORTED_FEATURE"; + case TCS_E_KEY_MISMATCH: return "TCS_E_KEY_MISMATCH"; + case TCS_E_KM_LOADFAILED: return "TCS_E_KM_LOADFAILED"; + case TCS_E_KEY_CONTEXT_RELOAD: return "TCS_E_KEY_CONTEXT_RELOAD"; + case TCS_E_INVALID_CONTEXTHANDLE: return "TCS_E_INVALID_CONTEXTHANDLE"; + case TCS_E_INVALID_KEYHANDLE: return "TCS_E_INVALID_KEYHANDLE"; + case TCS_E_INVALID_AUTHHANDLE: return "TCS_E_INVALID_AUTHHANDLE"; + case TCS_E_INVALID_AUTHSESSION: return "TCS_E_INVALID_AUTHSESSION"; + case TCS_E_INVALID_KEY: return "TCS_E_INVALID_KEY"; + default: return "UNKNOWN TCS ERROR"; + } + } else { + switch (TSS_ERROR_CODE(r)) { + case TSS_E_FAIL: return "TSS_E_FAIL"; + case TSS_E_BAD_PARAMETER: return "TSS_E_BAD_PARAMETER"; + case TSS_E_INTERNAL_ERROR: return "TSS_E_INTERNAL_ERROR"; + case TSS_E_NOTIMPL: return "TSS_E_NOTIMPL"; + case TSS_E_PS_KEY_NOTFOUND: return "TSS_E_PS_KEY_NOTFOUND"; + case TSS_E_KEY_ALREADY_REGISTERED: return "TSS_E_KEY_ALREADY_REGISTERED"; + case TSS_E_CANCELED: return "TSS_E_CANCELED"; + case TSS_E_TIMEOUT: return "TSS_E_TIMEOUT"; + case TSS_E_OUTOFMEMORY: return "TSS_E_OUTOFMEMORY"; + case TSS_E_TPM_UNEXPECTED: return "TSS_E_TPM_UNEXPECTED"; + case TSS_E_COMM_FAILURE: return "TSS_E_COMM_FAILURE"; + case TSS_E_TPM_UNSUPPORTED_FEATURE: return "TSS_E_TPM_UNSUPPORTED_FEATURE"; + case TSS_E_INVALID_OBJECT_TYPE: return "TSS_E_INVALID_OBJECT_TYPE"; + case TSS_E_INVALID_OBJECT_INITFLAG: return "TSS_E_INVALID_OBJECT_INITFLAG"; + case TSS_E_INVALID_HANDLE: return "TSS_E_INVALID_HANDLE"; + case TSS_E_NO_CONNECTION: return "TSS_E_NO_CONNECTION"; + case TSS_E_CONNECTION_FAILED: return "TSS_E_CONNECTION_FAILED"; + case TSS_E_CONNECTION_BROKEN: return "TSS_E_CONNECTION_BROKEN"; + case TSS_E_HASH_INVALID_ALG: return "TSS_E_HASH_INVALID_ALG"; + case TSS_E_HASH_INVALID_LENGTH: return "TSS_E_HASH_INVALID_LENGTH"; + case TSS_E_HASH_NO_DATA: return "TSS_E_HASH_NO_DATA"; + case TSS_E_SILENT_CONTEXT: return "TSS_E_SILENT_CONTEXT"; + case TSS_E_INVALID_ATTRIB_FLAG: return "TSS_E_INVALID_ATTRIB_FLAG"; + case TSS_E_INVALID_ATTRIB_SUBFLAG: return "TSS_E_INVALID_ATTRIB_SUBFLAG"; + case TSS_E_INVALID_ATTRIB_DATA: return "TSS_E_INVALID_ATTRIB_DATA"; + case TSS_E_NO_PCRS_SET: return "TSS_E_NO_PCRS_SET"; + case TSS_E_KEY_NOT_LOADED: return "TSS_E_KEY_NOT_LOADED"; + case TSS_E_KEY_NOT_SET: return "TSS_E_KEY_NOT_SET"; + case TSS_E_VALIDATION_FAILED: return "TSS_E_VALIDATION_FAILED"; + case TSS_E_TSP_AUTHREQUIRED: return "TSS_E_TSP_AUTHREQUIRED"; + case TSS_E_TSP_AUTH2REQUIRED: return "TSS_E_TSP_AUTH2REQUIRED"; + case TSS_E_TSP_AUTHFAIL: return "TSS_E_TSP_AUTHFAIL"; + case TSS_E_TSP_AUTH2FAIL: return "TSS_E_TSP_AUTH2FAIL"; + case TSS_E_KEY_NO_MIGRATION_POLICY: return "TSS_E_KEY_NO_MIGRATION_POLICY"; + case TSS_E_POLICY_NO_SECRET: return "TSS_E_POLICY_NO_SECRET"; + case TSS_E_INVALID_OBJ_ACCESS: return "TSS_E_INVALID_OBJ_ACCESS"; + case TSS_E_INVALID_ENCSCHEME: return "TSS_E_INVALID_ENCSCHEME"; + case TSS_E_INVALID_SIGSCHEME: return "TSS_E_INVALID_SIGSCHEME"; + case TSS_E_ENC_INVALID_LENGTH: return "TSS_E_ENC_INVALID_LENGTH"; + case TSS_E_ENC_NO_DATA: return "TSS_E_ENC_NO_DATA"; + case TSS_E_ENC_INVALID_TYPE: return "TSS_E_ENC_INVALID_TYPE"; + case TSS_E_INVALID_KEYUSAGE: return "TSS_E_INVALID_KEYUSAGE"; + case TSS_E_VERIFICATION_FAILED: return "TSS_E_VERIFICATION_FAILED"; + case TSS_E_HASH_NO_IDENTIFIER: return "TSS_E_HASH_NO_IDENTIFIER"; + default: return "UNKNOWN TSS ERROR"; + } + } +} diff --git a/src/tspi/daa/daa_platform/platform.c b/src/tspi/daa/daa_platform/platform.c new file mode 100644 index 0000000..80180ca --- /dev/null +++ b/src/tspi/daa/daa_platform/platform.c @@ -0,0 +1,2644 @@ + +/* + * Licensed Materials - Property of IBM + * + * trousers - An open source TCG Software Stack + * + * (C) Copyright International Business Machines Corp. 2006 + * + */ + + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +// for message digest +#include <openssl/evp.h> +#include <openssl/hmac.h> +#include <openssl/err.h> +#include <openssl/rsa.h> +#include <openssl/sha.h> + +#include <stdlib.h> + +#include "daa_structs.h" +#include "daa_parameter.h" +#include "trousers/tss.h" +#include "spi_internal_types.h" +#include "spi_utils.h" +#include <trousers/trousers.h> +#include <spi_utils.h> +#include <obj.h> +#include "tsplog.h" +#include "tss/tcs.h" +#include "platform.h" +#include "issuer.h" +#include "verifier.h" + +#define EVP_SUCCESS 1 + +TSS_RESULT +Tcsip_TPM_DAA_Join(TCS_CONTEXT_HANDLE tcsContext, // in + TSS_HDAA hDAA, // in + BYTE stage, // in + UINT32 inputSize0, // in + BYTE* inputData0, // in + UINT32 inputSize1, // in + BYTE* inputData1, // in + TPM_AUTH* ownerAuth, // in/out + UINT32* outputSize, // out + BYTE** outputData // out +) { + TSS_RESULT result; + TSS_HPOLICY hPolicy; + TCPA_DIGEST digest; + UINT16 offset = 0; + BYTE hashblob[10000]; + TPM_HANDLE hTPM; + TPM_HANDLE join_session; + // TPM_HANDLE hTPM; + + if( (result = obj_daa_get_handle_tpm( hDAA, &hTPM)) != TSS_SUCCESS) + return result; + if( (result = obj_daa_get_session_handle( hDAA, &join_session)) != TSS_SUCCESS) + return result; + LogDebug("Tcsip_TPM_DAA_Join(tcsContext=%x,hDAA=%x,join_session=%x, hTPM=%x stage=%d)", + tcsContext, + hDAA, + join_session, + hTPM, + stage); + + LogDebug("obj_tpm_get_policy(hTPM=%X)", hTPM); + if( (result = obj_tpm_get_policy( hTPM, &hPolicy)) != TSS_SUCCESS) + return result; + LogDebug("Trspi_LoadBlob_UINT32(&offset, TPM_ORD_DAA_Join, hashblob)"); + // hash TPM_COMMAND_CODE + Trspi_LoadBlob_UINT32(&offset, TPM_ORD_DAA_Join, hashblob); + LogDebug("Trspi_Hash(TSS_HASH_SHA1, offset, hashblob, digest.digest)"); + // hash stage + Trspi_LoadBlob_BYTE(&offset, stage, hashblob); + LogDebug("Trspi_LoadBlob_UINT32(&offset, 0, hashblob)"); + // hash inputSize0 + Trspi_LoadBlob_UINT32(&offset, inputSize0, hashblob); + LogDebug("Trspi_LoadBlob_UINT32(&offset, inputSize0:%d", inputSize0); + // hash inputData0 + Trspi_LoadBlob( &offset, inputSize0, hashblob, inputData0); + // hash inputSize1 + Trspi_LoadBlob_UINT32(&offset, inputSize1, hashblob); + LogDebug("Trspi_LoadBlob_UINT32(&offset, inputSize1:%d", inputSize1); + // hash inputData1 + Trspi_LoadBlob( &offset, inputSize1, hashblob, inputData1); + Trspi_Hash(TSS_HASH_SHA1, offset, hashblob, digest.digest); + + if ((result = secret_PerformAuth_OIAP(hTPM, TPM_ORD_DAA_Join, + hPolicy, &digest, + ownerAuth)) != TSS_SUCCESS) return result; + LogDebug("secret_PerformAuth_OIAP(hTPM, TPM_ORD_DAA_Join ret=%d", result); + LogDebug("TCSP_DAAJoin(%x,%x,stage=%x,%x,%x,%x,%x,%x)\n", + tcsContext, + hTPM, + stage, + inputSize0, + (int)inputData0, + inputSize1, + (int)inputData1, + (int)&ownerAuth); + /* step of the following call: + TCSP_DAAJoin tcsd_api/calltcsapi.c (define in spi_utils.h) + TCSP_DAAJoin_TP tcsd_api/tcstp.c (define in trctp.h) + */ + result = TCSP_DaaJoin( tcsContext, + join_session, + stage, + inputSize0, inputData0, + inputSize1, inputData1, + ownerAuth, + outputSize, outputData); + if( result != TSS_SUCCESS) return result; + + offset = 0; + Trspi_LoadBlob_UINT32(&offset, result, hashblob); + Trspi_LoadBlob_UINT32(&offset, TPM_ORD_DAA_Join, hashblob); + Trspi_LoadBlob_UINT32(&offset, *outputSize, hashblob); + Trspi_LoadBlob(&offset, *outputSize, hashblob, *outputData); + LogDebug("TCSP_DAAJoin stage=%d outputSize=%d outputData=%x RESULT=%d", + (int)stage, (int)*outputSize, (int)outputData, (int)result); + Trspi_Hash(TSS_HASH_SHA1, offset, hashblob, digest.digest); + if( (result = obj_policy_validate_auth_oiap( hPolicy, &digest, ownerAuth))) { + LogError("obj_policy_validate_auth=%d", result); + } + return result; +} + +TSS_RESULT Tcsip_TPM_DAA_Sign( TCS_CONTEXT_HANDLE hContext, // in + TPM_HANDLE handle, // in + BYTE stage, // in + UINT32 inputSize0, // in + BYTE* inputData0, // in + UINT32 inputSize1, // in + BYTE* inputData1, // in + TPM_AUTH* ownerAuth, // in, out + UINT32* outputSize, // out + BYTE** outputData // out +) { + TSS_RESULT result; + TSS_HPOLICY hPolicy; + TCPA_DIGEST digest; + UINT16 offset = 0; + BYTE hashblob[1000]; + TPM_HANDLE hTPM; + TPM_HANDLE session_handle; + TSS_HDAA hDAA = (TSS_HDAA)handle; + // TPM_HANDLE hTPM; + + if( (result = obj_daa_get_handle_tpm( hDAA, &hTPM)) != TSS_SUCCESS) + return result; + if( (result = obj_daa_get_session_handle( hDAA, &session_handle)) != TSS_SUCCESS) + return result; + LogDebug("Tcsip_TPM_DAA_Sign(tcsContext=%x,hDAA=%x,sign_session=%x, hTPM=%x stage=%d)", + hContext, + hDAA, + session_handle, + hTPM, + stage); + + LogDebug("obj_tpm_get_policy(hTPM=%X)", hTPM); + if( (result = obj_tpm_get_policy( hTPM, &hPolicy)) != TSS_SUCCESS) + return result; + LogDebug("Trspi_LoadBlob_UINT32(&offset, TPM_ORD_DAA_Sign, hashblob)"); + // hash TPM_COMMAND_CODE + Trspi_LoadBlob_UINT32(&offset, TPM_ORD_DAA_Sign, hashblob); + LogDebug("Trspi_Hash(TSS_HASH_SHA1, offset, hashblob, digest.digest)"); + // hash stage + Trspi_LoadBlob_BYTE(&offset, stage, hashblob); + LogDebug("Trspi_LoadBlob_UINT32(&offset, 0, hashblob)"); + // hash inputSize0 + Trspi_LoadBlob_UINT32(&offset, inputSize0, hashblob); + LogDebug("Trspi_LoadBlob_UINT32(&offset, inputSize0:%d", inputSize0); + // hash inputData0 + Trspi_LoadBlob( &offset, inputSize0, hashblob, inputData0); + // hash inputSize1 + Trspi_LoadBlob_UINT32(&offset, inputSize1, hashblob); + LogDebug("Trspi_LoadBlob_UINT32(&offset, inputSize1:%d", inputSize1); + // hash inputData1 + Trspi_LoadBlob( &offset, inputSize1, hashblob, inputData1); + Trspi_Hash(TSS_HASH_SHA1, offset, hashblob, digest.digest); + + if ((result = secret_PerformAuth_OIAP(hTPM, TPM_ORD_DAA_Join, + hPolicy, &digest, + ownerAuth)) != TSS_SUCCESS) return result; + LogDebug("secret_PerformAuth_OIAP(hTPM, TPM_ORD_DAA_Join ret=%d", result); + LogDebug("TCSP_DAASign(%x,%x,stage=%x,%x,%x,%x,%x,%x)", + hContext, + hTPM, + stage, + inputSize0,(int)inputData0, + inputSize1,(int)inputData1, + (int)&ownerAuth); + /* step of the following call: + TCSP_DAASign tcsd_api/calltcsapi.c (define in spi_utils.h) + TCSP_DAASign_TP tcsd_api/tcstp.c (define in trctp.h) + */ + result = TCSP_DaaSign( hContext, + session_handle, + stage, + inputSize0, inputData0, + inputSize1, inputData1, + ownerAuth, + outputSize, outputData); + if( result != TSS_SUCCESS) return result; + + offset = 0; + Trspi_LoadBlob_UINT32(&offset, result, hashblob); + Trspi_LoadBlob_UINT32(&offset, TPM_ORD_DAA_Sign, hashblob); + Trspi_LoadBlob_UINT32(&offset, *outputSize, hashblob); + Trspi_LoadBlob(&offset, *outputSize, hashblob, *outputData); + LogDebug("TCSP_DAASign stage=%d outputSize=%d outputData=%x RESULT=%d", + (int)stage, (int)*outputSize, (int)outputData, (int)result); + Trspi_Hash(TSS_HASH_SHA1, offset, hashblob, digest.digest); + if( (result = obj_policy_validate_auth_oiap( hPolicy, &digest, ownerAuth))) + { + LogError("obj_policy_validate_auth=%d", result); + } + return result; +} + +/** + Only used for the logging +*/ +static TSS_RESULT +Tcsip_TPM_DAA_Join_encapsulate(TCS_CONTEXT_HANDLE tcsContext, // in + TSS_HDAA hDAA, // in + BYTE stage, // in + UINT32 inputSize0, // in + BYTE* inputData0, // in + UINT32 inputSize1, // in + BYTE* inputData1, // in + TPM_AUTH* ownerAuth, // in/out + UINT32* outputSize, // out + BYTE** outputData // out +) { + TSS_RESULT result; + + LogDebug("Tcsip_DAA_Join(TCS_CONTEXT=%X,TSS_HDAA=%X,stage=%d,\ + inputSize0=%u,inputData0=%s\ninputSize1=%u,inputData1=%s,ownerAuth=%X)", + tcsContext, hDAA, stage, + inputSize0, dump_byte_array(inputSize0, inputData0), + inputSize1,dump_byte_array(inputSize1, inputData1), + (int)ownerAuth); + result = Tcsip_TPM_DAA_Join( + tcsContext, // in + hDAA, // in + stage, // in + inputSize0, // in + inputData0, // in + inputSize1, // in + inputData1, // in + ownerAuth, // in/out + outputSize, // out + outputData // out + ); + LogDebug("Tcsip_DAA_Join(stage=%d,outputSize=%u outputData=%s ownerAuth=%X) result=%d", + (int)stage, *outputSize, dump_byte_array( *outputSize, *outputData), (int)ownerAuth, result); + return result; +} + +#if 0 +/* from TSS.java */ +/* openssl RSA (struct rsa_st) could manage RSA Key */ +TSS_RESULT +Tspi_TPM_DAA_JoinInit_internal( TSS_HDAA hDAA, + TSS_HTPM hTPM, + int daa_counter, + TSS_DAA_PK *issuer_pk, + int issuer_authentication_PKLengh, + RSA **issuer_authentication_PK, + int issuer_authentication_PK_signaturesLength, + BYTE **issuer_authentication_PK_signatures, + int *capital_UprimeLength, + BYTE **capital_Uprime, + TSS_DAA_IDENTITY_PROOF *identity_proof, + TSS_DAA_JOIN_SESSION *join_session) +{ + // Optional: verification of the PKDAA and issuer settings (authen. by the RSA Public Key chain) + TSS_RESULT result; + TCS_CONTEXT_HANDLE tcsContext; + TPM_AUTH ownerAuth; + int i, modulus_length, outputSize, length, length1; + UINT32 return_join_session; + BYTE *outputData, *issuer_settings_bytes; + BYTE *buffer_modulus; + TPM_DAA_ISSUER *issuer_settings; + char buffer[1000], buffer1[1000]; + TSS_DAA_PK_internal *pk_internal = e_2_i_TSS_DAA_PK( issuer_pk); + bi_ptr issuer_authentication_PK_i = NULL; + + if( (result = obj_tpm_is_connected( hTPM, &tcsContext)) != TSS_SUCCESS) + return result; + obj_daa_set_handle_tpm( hDAA, hTPM); + + // stages 0-2 explained in the diagram "Keys of DAA Issuer" + // issuer_authentication_PKLengh should be converted to Network Based integer + i = htonl(issuer_authentication_PKLengh); + result = Tcsip_TPM_DAA_Join_encapsulate( tcsContext, hDAA, + 0, + sizeof(int), (BYTE *)(&i), + 0, NULL, + &ownerAuth, &outputSize, &outputData); + if( result != TSS_SUCCESS) { goto close;} + // set the sessionHandle to the returned value + return_join_session = ntohl( *((UINT32 *)outputData)); + free( outputData); + obj_daa_set_session_handle( hDAA, return_join_session); + + LogDebug("done join 0 settings join_session:%x\n", return_join_session); + modulus_length = DAA_PARAM_SIZE_RSA_MODULUS / 8; + buffer_modulus = malloc(modulus_length); + if (buffer_modulus == NULL) { + LogError("malloc of %d bytes failed", modulus_length); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + issuer_authentication_PK_i = bi_new_ptr(); + for(i =0; i< issuer_authentication_PKLengh; i++) { + bi_set_as_BIGNUM( issuer_authentication_PK_i, issuer_authentication_PK[i]->n); + bi_2_byte_array( buffer_modulus, + modulus_length, + issuer_authentication_PK_i); + if ( i==0) { + result = Tcsip_TPM_DAA_Join_encapsulate( + tcsContext, hDAA, + 1, + modulus_length, buffer_modulus, + 0, NULL, + &ownerAuth, &outputSize, &outputData); + if( result != TSS_SUCCESS) { + free( buffer_modulus); + goto close; + } + } else { + result = Tcsip_TPM_DAA_Join_encapsulate( + tcsContext, hDAA, + 1, + modulus_length, buffer_modulus, + DAA_PARAM_KEY_SIZE / 8, issuer_authentication_PK_signatures[i -1], + &ownerAuth, &outputSize, &outputData); + if( result != TSS_SUCCESS) { + free( buffer_modulus); + goto close; + } + } + } + free( buffer_modulus); + LogDebug("done join 1-%d\n", issuer_authentication_PKLengh); + // define issuer_settings + issuer_settings = convert2issuer_settings( pk_internal); + issuer_settings_bytes = issuer_2_byte_array( issuer_settings, &length); + result = Tcsip_TPM_DAA_Join_encapsulate( + tcsContext, hDAA, + 2, + length, issuer_settings_bytes, + modulus_length, + issuer_authentication_PK_signatures[issuer_authentication_PKLengh-1], + &ownerAuth, &outputSize, &outputData); + if( result != TSS_SUCCESS) { goto close;} + LogDebug("done join 2\n"); + i = htonl( daa_counter); + result = Tcsip_TPM_DAA_Join_encapsulate( + tcsContext, hDAA, + 3, + sizeof(UINT32), (BYTE *)(&i), + 0, NULL, + &ownerAuth, &outputSize, &outputData); + if( result != TSS_SUCCESS) { goto close;} + LogDebug("done join 3\n"); + // reserved another buffer for storing Big Integer + bi_2_nbin1( &length, buffer, pk_internal->capitalR0); + bi_2_nbin1( &length1, buffer1, pk_internal->modulus); + result = Tcsip_TPM_DAA_Join_encapsulate( + tcsContext, hDAA, + 4, + length, buffer, + length1, buffer1, + &ownerAuth, &outputSize, &outputData); + if( result != TSS_SUCCESS) { goto close;} + LogDebug("done join 4\n"); + bi_2_nbin1( &length, buffer, pk_internal->capitalR1); + result = Tcsip_TPM_DAA_Join_encapsulate( + tcsContext, hDAA, + 5, + length, buffer, + length1, buffer1, + &ownerAuth, &outputSize, &outputData); + if( result != TSS_SUCCESS) { goto close;} + LogDebug("done join 5\n"); + bi_2_nbin1( &length, buffer, pk_internal->capitalS); + result = Tcsip_TPM_DAA_Join_encapsulate( + tcsContext, hDAA, + 6, + length, buffer, + length1, buffer1, + &ownerAuth, &outputSize, &outputData); + if( result != TSS_SUCCESS) { goto close;} + LogDebug("done join 6\n"); + bi_2_nbin1( &length, buffer, pk_internal->capitalSprime); + // define Uprime + result = Tcsip_TPM_DAA_Join_encapsulate( + tcsContext, hDAA, + 7, + length, buffer, + length1, buffer1, + &ownerAuth, &outputSize, &outputData); + // 5 : save PKDAA, U, daaCount and sessionHandle in joinSession + join_session->issuerPk = (TSS_HKEY)issuer_pk; + if( result == TSS_SUCCESS) { + *capital_UprimeLength = outputSize; + *capital_Uprime = convert_alloc( tcsContext, outputSize, outputData); + if (*capital_Uprime == NULL) { + LogError("malloc of %d bytes failed", outputSize); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + join_session->capitalUPrime = copy_alloc( tcsContext, + *capital_UprimeLength, + *capital_Uprime); + if (join_session->capitalUPrime == NULL) { + LogError("malloc of %d bytes failed", *capital_UprimeLength); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + join_session->capitalUPrimeLength = *capital_UprimeLength; + } + join_session->sessionHandle = return_join_session; + // get the endorsement Key (public part) + result = get_public_EK( + hTPM, // in + &( identity_proof->endorsementLength), + &( identity_proof->endorsementCredential) + ); + +close: + FREE_BI( issuer_authentication_PK_i); + LogDebug("result = %d", result); + LogDebug("outputSize=%d", outputSize); + LogDebug("outputData=%s", dump_byte_array( outputSize, outputData)); + return result; +} +#else +TSS_RESULT +Tspi_TPM_DAA_JoinInit_internal(TSS_HTPM hTPM, + TSS_HDAA_ISSUER_KEY hIssuerKey + UINT32 daa_counter, + UINT32 issuerAuthPKsLength, + TSS_HKEY* issuerAuthPKs, + UINT32 issuerAuthPKSignaturesLength, + UINT32 issuerAuthPKSignaturesLength2, + BYTE** issuerAuthPKSignatures, + UINT32* capitalUprimeLength, + BYTE** capitalUprime, + TSS_DAA_IDENTITY_PROOF** identity_proof, + UINT32* joinSessionLength, + BYTE** joinSession) +{ + // Optional: verification of the PKDAA and issuer settings (authen. by the RSA Public Key chain) + TSS_RESULT result; + TSS_HCONTEXT tspContext; + TPM_AUTH ownerAuth; + int length, length1; + UINT32 i, modulus_length, outputSize, buf_len; + BYTE *outputData, *issuer_settings_bytes; + BYTE *modulus, stage, *buf; + //TPM_DAA_ISSUER *issuer_settings; + //char buffer[1000], buffer1[1000]; + //TSS_DAA_PK_internal *pk_internal = e_2_i_TSS_DAA_PK(issuer_pk); + bi_ptr issuerAuthPK = NULL; + TPM_HANDLE daaHandle; + Trspi_HashCtx hashCtx; + TPM_DIGEST digest; + TSS_DAA_IDENTITY_PROOF daaIdentityProof; + + if ((result = obj_tpm_is_connected(hTPM, &tspContext))) + return result; + + if ((result = obj_daaissuerkey_get_daa_handle(hIssuerKey, &daaHandle))) + return result; + + stage = 0; + inputSize0 = (UINT32)sizeof(UINT32); + inputData0 = issuerAuthPKsLength; + inputSize1 = 0; + inputData1 = NULL; + + result = Trspi_HashInit(&hashCtx, TSS_HASH_SHA1); + result |= Trspi_Hash_UINT32(&hashCtx, TPM_ORD_DAA_Join); + result |= Trspi_Hash_BYTE(&hashCtx, stage); + result |= Trspi_Hash_UINT32(&hashCtx, inputSize0); + result |= Trspi_HashUpdate(&hashCtx, inputSize0, inputData0); + result |= Trspi_Hash_UINT32(&hashCtx, inputSize1); + result |= Trspi_HashUpdate(&hashCtx, inputSize1, inputData1); + if ((result |= Trspi_HashFinal(&hashCtx, digest.digest))) + return result; + + // stages 0-2 explained in the diagram "Keys of DAA Issuer" + if ((result = TCS_API(tspContext)->DaaJoin(tspContext, daaHandle, stage, inputSize1, + inputData0, inputSize1, inputData1, &ownerAuth, + &outputSize, &outputData))) + goto close; + + if (outputSize != sizeof(UINT32)) { + result = TSPERR(TSS_E_INTERNAL_ERROR); + goto close; + } + + // set the sessionHandle to the returned value + Trspi_UnloadBlob_UINT32(&offset, &daaHandle, outputData); + free(outputData); + if ((result = obj_daaissuerkey_set_daa_handle(hIssuerKey, daaHandle))) + goto close; + + LogDebug("done join 0 settings join_session:%x", daaHandle); + + modulus_length = DAA_PARAM_SIZE_RSA_MODULUS / 8; + if ((buffer_modulus = malloc(modulus_length)) == NULL) { + LogError("malloc of %d bytes failed", modulus_length); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + + stage = 1; + for (i = 0; i < issuerAuthPKsLength; i++) { + if ((result = obj_rsakey_get_modulus(issuerAuthPKs[i], &modulus_length, &modulus))) + goto close; + + outputData = NULL; + if (i==0) { + result = Tcsip_TPM_DAA_Join_encapsulate(tspContext, daaHandle, stage, + modulus_length, modulus, 0, NULL, + &ownerAuth, &outputSize, + &outputData); + } else { + result = Tcsip_TPM_DAA_Join_encapsulate(tspContext, daaHandle, stage, + modulus_length, modulus, + issuerAuthPKSignaturesLength2, + issuerAuthPKSignatures[i - 1], + &ownerAuth, &outputSize, + &outputData); + } + + free(outputData); + free_tspi(tspContext, modulus); + if (result != TSS_SUCCESS) { + LogDebugFn("Stage 1 iteration %u failed", i); + goto close; + } + } + + LogDebug("done join 1-%d\n", issuer_authentication_PKLengh); + + stage = 2; + // define issuer_settings +#if 0 + issuer_settings = convert2issuer_settings(pk_internal); + issuer_settings_bytes = issuer_2_byte_array(issuer_settings, &length); +#else + if ((result = obj_daaissuerkey_get_daa_issuer(hIssuerKey, &issuer_length, &issuer))) + goto close; + + if ((result = obj_daaissuerkey_get_modulus(hIssuerKey, &modulus_length, &modulus))) { + free_tspi(tspContext, issuer); + goto close; + } +#endif + if ((result = Tcsip_TPM_DAA_Join_encapsulate(tspContext, daaHandle, stage, issuer_length, + issuer, issuerAuthPKSignaturesLength2, + issuerAuthPKSignatures[i - 1], &ownerAuth, + &outputSize, &outputData))) { + free_tspi(tspContext, issuer); + free_tspi(tspContext, modulus); + goto close; + } + free_tspi(tspContext, issuer); + + LogDebug("done join 2\n"); + + stage = 3; + if ((result = Tcsip_TPM_DAA_Join_encapsulate(tspContext, daaHandle, stage, sizeof(UINT32), + (BYTE *)(&daa_counter), 0, NULL, &ownerAuth, + &outputSize, &outputData))) + goto close; + + LogDebug("done join 3\n"); + + stage = 4; +#if 0 + // reserved another buffer for storing Big Integer + bi_2_nbin1( &length, buffer, pk_internal->capitalR0); + bi_2_nbin1( &length1, buffer1, pk_internal->modulus); +#else + if ((result = obj_daaissuerkey_get_capitalR0(hIssuerKey, &buf_len, &buf))) + return result; +#endif + if ((result = Tcsip_TPM_DAA_Join_encapsulate(tspContext, daaHandle, stage, buf_len, buf, + modulus_length, modulus, &ownerAuth, + &outputSize, &outputData))) { + free_tspi(tspContext, buf); + free_tspi(tspContext, modulus); + goto close; + } + free_tspi(tspContext, buf); + + LogDebug("done join 4\n"); + + stage = 5; +#if 0 + bi_2_nbin1( &length, buffer, pk_internal->capitalR1); +#else + if ((result = obj_daaissuerkey_get_capitalR1(hIssuerKey, &buf_len, &buf))) + return result; +#endif + if ((result = Tcsip_TPM_DAA_Join_encapsulate(tspContext, daaHandle, stage, buf_len, + buf, modulus_length, modulus, &ownerAuth, + &outputSize, &outputData))) { + free_tspi(tspContext, buf); + free_tspi(tspContext, modulus); + goto close; + } + free_tspi(tspContext, buf); + + LogDebug("done join 5\n"); + + stage = 6; +#if 0 + bi_2_nbin1( &length, buffer, pk_internal->capitalS); +#else + if ((result = obj_daaissuerkey_get_capitalS(hIssuerKey, &buf_len, &buf))) + return result; +#endif + if ((result = Tcsip_TPM_DAA_Join_encapsulate(tspContext, daaHandle, stage, buf_len, buf, + modulus_length, modulus, &ownerAuth, + &outputSize, &outputData))) { + free_tspi(tspContext, buf); + free_tspi(tspContext, modulus); + goto close; + } + free_tspi(tspContext, buf); + + LogDebug("done join 6\n"); + + stage = 7; +#if 0 + bi_2_nbin1( &length, buffer, pk_internal->capitalSprime); +#else + if ((result = obj_daaissuerkey_get_capitalSprime(hIssuerKey, &buf_len, &buf))) + return result; +#endif + // define Uprime + if ((result = Tcsip_TPM_DAA_Join_encapsulate(tspContext, daaHandle, stage, buf_len, buf, + modulus_length, modulus, &ownerAuth, + &outputSize, &outputData))) { + free_tspi(tspContext, buf); + free_tspi(tspContext, modulus); + goto close; + } + free_tspi(tspContext, buf); + +#if 0 + // 5 : save PKDAA, U, daaCount and sessionHandle in joinSession + join_session->issuerPk = (TSS_HKEY)issuer_pk; + if( result == TSS_SUCCESS) { + *capital_UprimeLength = outputSize; + *capital_Uprime = convert_alloc( tspContext, outputSize, outputData); + if (*capital_Uprime == NULL) { + LogError("malloc of %d bytes failed", outputSize); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + join_session->capitalUPrime = copy_alloc( tspContext, + *capital_UprimeLength, + *capital_Uprime); + if (join_session->capitalUPrime == NULL) { + LogError("malloc of %d bytes failed", *capital_UprimeLength); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + join_session->capitalUPrimeLength = *capital_UprimeLength; + } + join_session->sessionHandle = return_join_session; + // get the endorsement Key (public part) + result = get_public_EK( + hTPM, // in + &( identity_proof->endorsementLength), + &( identity_proof->endorsementCredential) + ); +#else + /* fill out the identity proof struct */ + if ((result = TCS_API(obj->tspContext)->GetTPMCapability(obj->tspContext, TPM_CAP_VERSION, + 0, NULL, &buf_len, &buf))) + goto close; + + offset = 0; + Trspi_UnloadBlob_VERSION(&offset, buf, &daaIdentityProof.versionInfo); + free_tspi(tspContext, buf); + +#error set all 3 credentials in the daaIdentityProof struct here + + /* set the U data */ + if ((result = __tspi_add_mem_entry(tspContext, outputData))) + goto close; + *capitalUPrime = outputData; + *capitalUPrimeLength = outputSize; + + /* return the TSS specific stuff */ +#endif + +close: + FREE_BI( issuer_authentication_PK_i); + LogDebug("result = %d", result); + LogDebug("outputSize=%d", outputSize); + LogDebug("outputData=%s", dump_byte_array( outputSize, outputData)); + return result; +} +#endif + + +/* allocation: + endorsementKey as BYTE * +*/ +TSS_RESULT +get_public_EK(TSS_HTPM hTPM, + UINT32 *endorsementKeyLength, + BYTE **endorsementKey + +) { + TSS_RESULT result; + TSS_HKEY hEk; + TSS_HPOLICY hTpmPolicy; + UINT32 uiAttrSize; + BYTE *pAttr; + + if( (result = obj_tpm_get_policy( hTPM, &hTpmPolicy)) != TSS_SUCCESS) { + LogError("can not retrieve policy from the TPM handler"); + goto out_close; + } + + if( (result = Tspi_TPM_GetPubEndorsementKey(hTPM, TRUE, NULL, &hEk)) != TSS_SUCCESS) { + LogError("can not retrieve the Public endorsed Key"); + goto out_close; + } + + result = Tspi_GetAttribData( + hEk, + TSS_TSPATTRIB_KEY_INFO, + TSS_TSPATTRIB_KEYINFO_VERSION, + &uiAttrSize, + &pAttr); + + if (result != TSS_SUCCESS) goto out_close; + LogDebug("keyinfo:%s", dump_byte_array( uiAttrSize, pAttr)); + + result = Tspi_GetAttribData( + hEk, + TSS_TSPATTRIB_KEY_BLOB, + TSS_TSPATTRIB_KEYBLOB_PUBLIC_KEY, + endorsementKeyLength, + endorsementKey); + + LogDebug("Public Endorsement Key:%s", + dump_byte_array( *endorsementKeyLength, *endorsementKey)); +out_close: + return result; +} + +// from TSS.java (479) +TSS_RESULT +compute_join_challenge_host(TSS_HDAA hDAA, + TSS_DAA_PK_internal *pk_internal, + bi_ptr capitalU, + bi_ptr capital_Uprime, + bi_ptr capital_utilde, + bi_ptr capital_utilde_prime, + bi_ptr capital_ni, + bi_ptr capital_ni_tilde, + UINT32 commitments_proofLength, + TSS_DAA_ATTRIB_COMMIT_internal * + commitments_proof, + UINT32 nonceIssuerLength, + BYTE* nonceIssuer, + UINT32 *resultLength, + BYTE **result) { + EVP_MD_CTX mdctx; + BYTE *encoded_pk = NULL, *buffer; + UINT32 encoded_pkLength; + int rv, length; + + buffer = (BYTE *)malloc( 10000); // to be sure, and it will be free quickly + if (buffer == NULL) { + LogError("malloc of %d bytes failed", 10000); + return TSPERR(TSS_E_OUTOFMEMORY); + } + // EVP_MD_CTX_init(&mdctx); + rv = EVP_DigestInit(&mdctx, DAA_PARAM_get_message_digest()); + if (rv != EVP_SUCCESS) goto err; + // allocation + encoded_pk = encoded_DAA_PK_internal( &encoded_pkLength, pk_internal); + LogDebug("encoded issuerPk[%d]: %s", + encoded_pkLength, + dump_byte_array( encoded_pkLength, encoded_pk)); + rv = EVP_DigestUpdate(&mdctx, encoded_pk, encoded_pkLength); + if (rv != EVP_SUCCESS) goto err; + // capitalU + length = DAA_PARAM_SIZE_RSA_MODULUS / 8; + bi_2_byte_array( buffer, length, capitalU); + LogDebug("capitalU[%ld]: %s", + bi_nbin_size(capitalU) , + dump_byte_array( length, buffer)); + rv = EVP_DigestUpdate(&mdctx, buffer, length); + if (rv != EVP_SUCCESS) goto err; + // capital UPrime + bi_2_byte_array( buffer, length, capital_Uprime); + LogDebug("capitalUPrime[%d]: %s", + length, + dump_byte_array( length, buffer)); + rv = EVP_DigestUpdate(&mdctx, buffer, length); + if (rv != EVP_SUCCESS) goto err; + // capital Utilde + bi_2_byte_array( buffer, length, capital_utilde); + LogDebug("capitalUTilde[%d]: %s", + length, + dump_byte_array( length, buffer)); + rv = EVP_DigestUpdate(&mdctx, buffer, length); + if (rv != EVP_SUCCESS) goto err; + // capital UtildePrime + bi_2_byte_array( buffer, length, capital_utilde_prime); + LogDebug("capital_utilde_prime[%d]: %s", + length, + dump_byte_array( length, buffer)); + rv = EVP_DigestUpdate(&mdctx, buffer, length); + if (rv != EVP_SUCCESS) goto err; + //capital_ni + length = DAA_PARAM_SIZE_MODULUS_GAMMA / 8; + bi_2_byte_array( buffer, length, capital_ni); + LogDebug("capital_ni[%d]: %s", + length, + dump_byte_array( length, buffer)); + rv = EVP_DigestUpdate(&mdctx, buffer, length); + if (rv != EVP_SUCCESS) goto err; + //capital_ni_tilde + bi_2_byte_array( buffer, length, capital_ni_tilde); + LogDebug("capital_ni_tilde[%d]: %s", + length, + dump_byte_array( length, buffer)); + rv = EVP_DigestUpdate(&mdctx, buffer, length); + if (rv != EVP_SUCCESS) goto err; + // TODO: commitments + LogDebug("nonceIssuer[%d]: %s", + nonceIssuerLength, + dump_byte_array( nonceIssuerLength, nonceIssuer)); + rv = EVP_DigestUpdate(&mdctx, nonceIssuer, nonceIssuerLength); + if (rv != EVP_SUCCESS) goto err; + *resultLength = EVP_MD_CTX_size(&mdctx); + *result = (BYTE *)malloc( *resultLength); + if (*result == NULL) { + LogError("malloc of %d bytes failed", *resultLength); + free( buffer); + free( encoded_pk); + return TSPERR(TSS_E_OUTOFMEMORY); + } + rv = EVP_DigestFinal(&mdctx, *result, NULL); + if (rv != EVP_SUCCESS) goto err; + free( buffer); + free( encoded_pk); + return TSS_SUCCESS; +err: + free( buffer); + free( encoded_pk); + DEBUG_print_openssl_errors(); + return TSPERR(TSS_E_INTERNAL_ERROR); +} + +/* +This is the second out of 3 functions to execute in order to receive a DAA Credential. It +computes the credential request for the DAA Issuer, which also includes the Platforms & DAA +public key and the attributes that were chosen by the Platform, and which are not visible to \ +the DAA Issuer. The Platform can commit to the attribute values it has chosen. +Code influenced by TSS.java (TssDaaCredentialRequest) +*/ +TSPICALL +Tspi_TPM_DAA_JoinCreateDaaPubKey_internal( + TSS_HDAA hDAA, // in + TSS_HTPM hTPM, // in + UINT32 authenticationChallengeLength, // in + BYTE* authenticationChallenge, // in + UINT32 nonceIssuerLength, // in + BYTE* nonceIssuer, // in + UINT32 attributesPlatformLength, // in + BYTE** attributesPlatform, // in + TSS_DAA_JOIN_SESSION* joinSession, // in, out + TSS_DAA_CREDENTIAL_REQUEST* credentialRequest // out +) { + TSS_RESULT result; + TCS_CONTEXT_HANDLE tcsContext; + TPM_AUTH ownerAuth; + bi_ptr tmp1 = bi_new_ptr(); + bi_ptr tmp2 = bi_new_ptr(); + bi_ptr capital_utilde = bi_new_ptr(); + bi_ptr v_tilde_prime = bi_new_ptr(); + bi_ptr rv_tilde_prime = bi_new_ptr(); + bi_ptr capitalU = bi_new_ptr(); + bi_ptr product_attributes = bi_new_ptr(); + bi_ptr capital_ni = NULL; + bi_ptr capital_utilde_prime = NULL; + bi_ptr capital_ni_tilde = NULL; + bi_ptr n = NULL; + bi_ptr attributePlatform = NULL; + bi_ptr c = NULL; + bi_ptr zeta = NULL; + bi_ptr capital_Uprime = NULL; + bi_ptr sv_tilde_prime = NULL; + bi_ptr s_f0 = NULL; + bi_ptr s_f1 = NULL; + bi_ptr sv_prime = NULL; + bi_ptr sv_prime1 = NULL; + bi_ptr sv_prime2 = NULL; + bi_array_ptr ra = NULL; + bi_array_ptr sa = NULL; + TSS_DAA_PK* pk_extern = (TSS_DAA_PK *)joinSession->issuerPk; + TSS_DAA_PK_internal* pk_internal = e_2_i_TSS_DAA_PK( pk_extern); + UINT32 i, outputSize, authentication_proofLength, nonce_tpmLength; + UINT32 capitalSprime_byte_arrayLength, size_bits, length, chLength, c_byteLength; + UINT32 internal_cbyteLength, noncePlatformLength; + BYTE *outputData, *authentication_proof, *capitalSprime_byte_array = NULL, *buffer; + BYTE *ch = NULL; + BYTE *c_byte, *noncePlatform, *nonce_tpm; + BYTE *internal_cbyte = NULL; + EVP_MD_CTX mdctx; + + if( tmp1 == NULL || tmp2 == NULL || capital_utilde == NULL || + v_tilde_prime == NULL || rv_tilde_prime == NULL || + capitalU == NULL || product_attributes == NULL) { + LogError("malloc of bi(s) failed"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + if( pk_internal == NULL) { + LogError("malloc of pk_internal failed"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + if( (result = obj_tpm_is_connected( hTPM, &tcsContext)) != TSS_SUCCESS) { + goto close; + } + obj_daa_set_handle_tpm( hDAA, hTPM); + // allocation + n = bi_set_as_nbin( pk_extern->modulusLength, pk_extern->modulus); + if( n == NULL) { + LogError("malloc of %d bytes failed", pk_extern->modulusLength); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + // allocation + capitalSprime_byte_array = bi_2_nbin( &capitalSprime_byte_arrayLength, + pk_internal->capitalSprime); + if( capitalSprime_byte_array == NULL) { + LogError("malloc of %d bytes failed", capitalSprime_byte_arrayLength); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + // compute second part of the credential request + // encode plateform attributes (the one visible only by the receiver) + bi_set( product_attributes, bi_1); + for( i=0; i<attributesPlatformLength; i++) { + attributePlatform = bi_set_as_nbin( DAA_PARAM_SIZE_F_I / 8, + attributesPlatform[i]); // allocation + if( attributePlatform == NULL) { + LogError("malloc of bi <%s> failed", "attributePlatform"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + // bi_tmp1 = ( capitalRReceiver[i] ^ attributesPlatform ) % n + bi_mod_exp( tmp1, pk_internal->capitalRReceiver->array[i], attributePlatform, n); + // bi_tmp1 = bi_tmp1 * product_attributes + bi_mul( tmp1, tmp1, product_attributes); + // product_attributes = bi_tmp1 % n + bi_mod( product_attributes, tmp1, n); + bi_free_ptr( attributePlatform); + } + bi_urandom( v_tilde_prime, DAA_PARAM_SIZE_RSA_MODULUS + + DAA_PARAM_SAFETY_MARGIN); + // tmp1 = capitalUPrime * capitalS + bi_free_ptr( tmp1); + tmp1 = bi_set_as_nbin( joinSession->capitalUPrimeLength, + joinSession->capitalUPrime); // allocation + if( tmp1 == NULL) { + LogError("malloc of %d bytes failed", joinSession->capitalUPrimeLength); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + // U = ( U' * ( ( pk->S ^ v~' ) % n) ) % n + // tmp2 = ( pk->S ^ v~') % n + bi_mod_exp( tmp2, pk_internal->capitalS, v_tilde_prime, n); + // U = tmp1( U') * tmp2 + bi_mul( capitalU, tmp1, tmp2); + bi_mod( capitalU, capitalU, n); + // U = ( U * product_attributes ) % n + bi_mul( capitalU, capitalU, product_attributes); + bi_mod( capitalU, capitalU, n); + // 2 : call the TPM to compute authentication proof with U' + result = Tcsip_TPM_DAA_Join_encapsulate( tcsContext, hDAA, + 8, + authenticationChallengeLength, authenticationChallenge, + 0, NULL, + &ownerAuth, &outputSize, &outputData); + if( result != TSS_SUCCESS) goto close; + LogDebug("Done Join 8"); + authentication_proof = calloc_tspi( tcsContext, outputSize); + if( authentication_proof == NULL) { + LogError("malloc of %d bytes failed", outputSize); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + memcpy( authentication_proof, outputData, outputSize); + free( outputData); + authentication_proofLength = outputSize; + + // 3 : call the TPM to compute U' (first part of correctness proof of the credential + // request + result = Tcsip_TPM_DAA_Join_encapsulate( tcsContext, hDAA, + 9, + pk_extern->capitalR0Length, pk_extern->capitalR0, + pk_extern->modulusLength, pk_extern->modulus, + &ownerAuth, &outputSize, &outputData); + if( result != TSS_SUCCESS) goto close; + LogDebug("Done Join 9: capitalR0"); + free( outputData); + + result = Tcsip_TPM_DAA_Join_encapsulate( tcsContext, hDAA, + 10, + pk_extern->capitalR1Length, pk_extern->capitalR1, + pk_extern->modulusLength, pk_extern->modulus, + &ownerAuth, &outputSize, &outputData); + if( result != TSS_SUCCESS) goto close; + LogDebug("Done Join 10: capitalR1"); + free( outputData); + + result = Tcsip_TPM_DAA_Join_encapsulate( tcsContext, hDAA, + 11, + pk_extern->capitalSLength, pk_extern->capitalS, + pk_extern->modulusLength, pk_extern->modulus, + &ownerAuth, &outputSize, &outputData); + if( result != TSS_SUCCESS) goto close; + LogDebug("Done Join 11: capitalS"); + free( outputData); + + result = Tcsip_TPM_DAA_Join_encapsulate( tcsContext, hDAA, + 12, + capitalSprime_byte_arrayLength, capitalSprime_byte_array, + pk_extern->modulusLength, pk_extern->modulus, + &ownerAuth, &outputSize, &outputData); + if( result != TSS_SUCCESS) goto close; + LogDebug("Done Join 12: capitalUTildePrime"); + capital_utilde_prime = bi_set_as_nbin( outputSize, outputData); // allocation + if( capital_utilde_prime == NULL) { + LogError("malloc of %d bytes failed", outputSize); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + free( outputData); + // 4 compute pseudonym with respect to the DAA Issuer + // allocation + zeta = compute_zeta( pk_internal->issuerBaseNameLength, + pk_internal->issuerBaseName, + pk_internal); + if( zeta == NULL) { + LogError("malloc of bi <%s> failed", "zeta"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + buffer = (BYTE *)malloc( TPM_DAA_SIZE_w); + if( buffer == NULL) { + LogError("malloc of %d bytes failed", TPM_DAA_SIZE_w); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + LogDebug("zeta[%ld] = %s", bi_nbin_size( zeta), bi_2_hex_char( zeta)); + bi_2_byte_array( buffer, TPM_DAA_SIZE_w, zeta); + LogDebug("zeta[%d] = %s", TPM_DAA_SIZE_w, dump_byte_array( TPM_DAA_SIZE_w, buffer)); + + result = Tcsip_TPM_DAA_Join_encapsulate( tcsContext, hDAA, + 13, + pk_extern->capitalGammaLength, pk_extern->capitalGamma, + TPM_DAA_SIZE_w, buffer, // zeta + &ownerAuth, &outputSize, &outputData); + free( buffer); + if( result != TSS_SUCCESS) goto close; + LogDebug("Done Join 13: capitalGamma / zeta"); + free( outputData); + + result = Tcsip_TPM_DAA_Join_encapsulate( tcsContext, hDAA, + 14, + pk_extern->capitalGammaLength, pk_extern->capitalGamma, + 0, NULL, + &ownerAuth, &outputSize, &outputData); + if( result != TSS_SUCCESS) goto close; + LogDebug("Done Join 14: capitalGamma"); + capital_ni = bi_set_as_nbin( outputSize, outputData); // allocation + if( capital_ni == NULL) { + LogError("malloc of bi <%s> failed", "capital_ni"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + free( outputData); + + result = Tcsip_TPM_DAA_Join_encapsulate( tcsContext, hDAA, + 15, + pk_extern->capitalGammaLength, pk_extern->capitalGamma, + 0, NULL, + &ownerAuth, &outputSize, &outputData); + if( result != TSS_SUCCESS) goto close; + LogDebug("Done Join 15: capitalGamma"); + capital_ni_tilde = bi_set_as_nbin( outputSize, outputData); // allocation + if( capital_ni_tilde == NULL) { + LogError("malloc of bi <%s> failed", "capital_ni_tilde"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + free( outputData); + + // 5 : compute the second part of the correctness proof of the credential request + // (with attributes not visible to issuer) + // randomize/blind attributesReceiver + size_bits = DAA_PARAM_SIZE_RANDOMIZED_ATTRIBUTES; + bi_set( product_attributes, bi_1); + ra = (bi_array_ptr)malloc( sizeof( struct _bi_array)); + if( ra == NULL) { + LogError("malloc of %d bytes failed", sizeof( struct _bi_array)); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_new_array( ra, attributesPlatformLength); + if( ra->array == NULL) { + LogError("malloc of bi_array <%s> failed", "ra"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + for( i=0; i < attributesPlatformLength; i++) { + bi_urandom( ra->array[i], size_bits); + LogDebug("ra[i]=%s size=%d", bi_2_hex_char( ra->array[i]), size_bits); + // product_attributes=(((capitalYplatform ^ ra[i]) % n)*<product_attributes-1>)%n + bi_mod_exp( tmp1, pk_internal->capitalRReceiver->array[i], ra->array[i], n); + bi_mul( tmp1, tmp1, product_attributes); + bi_mod( product_attributes, tmp1, n); + } + size_bits = DAA_PARAM_SIZE_F_I+2*DAA_PARAM_SAFETY_MARGIN+DAA_PARAM_SIZE_MESSAGE_DIGEST; + bi_urandom( rv_tilde_prime, size_bits); + // capital_utilde = ( capitalS ^ rv_tilde_prime) % n + bi_mod_exp( capital_utilde, pk_internal->capitalS, rv_tilde_prime, n); + // capital_utilde = capital_utilde * product_attributes + bi_mul( capital_utilde, capital_utilde, product_attributes); + // capital_utilde = capital_utilde % n + bi_mod( capital_utilde, capital_utilde, n); + // 5e + capital_Uprime = bi_set_as_nbin( joinSession->capitalUPrimeLength, + joinSession->capitalUPrime); // allocation + if( capital_Uprime == NULL) { + LogError("malloc of bi <%s> failed", "capital_Uprime"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + LogDebug("calculation UTilde: capitalS:%s\n", bi_2_hex_char( pk_internal->capitalS)); + LogDebug("calculation UTilde: rv_tilde_prime:%s\n", bi_2_hex_char( rv_tilde_prime)); + LogDebug("calculation UTilde: n:%s\n", bi_2_hex_char( n)); + LogDebug("calculation UTilde: product_attributes:%s\n", bi_2_hex_char( product_attributes)); + LogDebug("calculation NItilde: ntilde:%s\n", bi_2_hex_char( capital_ni_tilde)); + + result = compute_join_challenge_host( + hDAA, + pk_internal, + capitalU, + capital_Uprime, + capital_utilde, + capital_utilde_prime, + capital_ni, + capital_ni_tilde, + 0, // TODO commitmentProofLength + NULL, // TODO commitment + nonceIssuerLength, + nonceIssuer, + &chLength, // out + &ch // out allocation + ); + if( result != TSS_SUCCESS) goto close; + + result = Tcsip_TPM_DAA_Join_encapsulate( tcsContext, hDAA, + 16, + chLength, ch, + 0, NULL, + &ownerAuth, &outputSize, &outputData); + if( result != TSS_SUCCESS) goto close; + nonce_tpm = outputData; + nonce_tpmLength = outputSize; + LogDebug("Done Join 16: compute_join_challenge_host return nonce_tpm:%s", + dump_byte_array(nonce_tpmLength, nonce_tpm)); + + result = Tcsip_TPM_DAA_Join_encapsulate( tcsContext, hDAA, + 17, + 0, NULL, + 0, NULL, + &ownerAuth, &outputSize, &outputData); + if( result != TSS_SUCCESS) goto close; + s_f0 = bi_set_as_nbin( outputSize, outputData); // allocation + if( s_f0 == NULL) { + LogError("malloc of <bi> %s failed", "s_f0"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + LogDebug("Done Join 17: return sF0:%s", dump_byte_array(outputSize, outputData) ); + free( outputData); + + result = Tcsip_TPM_DAA_Join_encapsulate( tcsContext, hDAA, + 18, + 0, NULL, + 0, NULL, + &ownerAuth, &outputSize, &outputData); + if( result != TSS_SUCCESS) goto close; + s_f1 = bi_set_as_nbin( outputSize, outputData); // allocation + if( s_f1 == NULL) { + LogError("malloc of <bi> %s failed", "s_f1"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + LogDebug("Done Join 18: return sF1:%s", dump_byte_array(outputSize, outputData) ); + free( outputData); + + result = Tcsip_TPM_DAA_Join_encapsulate( tcsContext, hDAA, + 19, + 0, NULL, + 0, NULL, + &ownerAuth, &outputSize, &outputData); + if( result != TSS_SUCCESS) goto close; + LogDebug("Done Join 19: return sv_prime1"); + sv_prime1 = bi_set_as_nbin( outputSize, outputData); // allocation + if( sv_prime1 == NULL) { + LogError("malloc of <bi> %s failed", "sv_prime1"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + free( outputData); + + result = Tcsip_TPM_DAA_Join_encapsulate( tcsContext, hDAA, + 20, + 0, NULL, + 0, NULL, + &ownerAuth, &outputSize, &outputData); + if( result != TSS_SUCCESS) goto close; + LogDebug("Done Join 20: return cByte"); + c_byte = (BYTE *)calloc_tspi( tcsContext, outputSize); + if( c_byte == NULL) { + LogError("malloc of %d bytes failed", outputSize); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + memcpy( c_byte, outputData, outputSize); + free( outputData); + c_byteLength = outputSize; + c = bi_set_as_nbin( c_byteLength, c_byte); // allocation + if( c == NULL) { + LogError("malloc of <bi> %s failed", "c"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + + // verify computation of c by TPM + EVP_DigestInit(&mdctx, DAA_PARAM_get_message_digest()); + EVP_DigestUpdate(&mdctx, ch, chLength); + EVP_DigestUpdate(&mdctx, nonce_tpm, nonce_tpmLength); + nonce_tpm = convert_alloc( tcsContext, nonce_tpmLength, nonce_tpm); // allocation + if( nonce_tpm == NULL) { + LogError("malloc of %d bytes failed", nonce_tpmLength); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + internal_cbyteLength = EVP_MD_CTX_size(&mdctx); + internal_cbyte = (BYTE *)malloc( internal_cbyteLength); + if( internal_cbyte == NULL) { + LogError("malloc of %d bytes failed", internal_cbyteLength); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + EVP_DigestFinal(&mdctx, internal_cbyte, NULL); + if( c_byteLength != internal_cbyteLength || + memcmp( c_byte, internal_cbyte, c_byteLength) != 0) { + LogError( "Computation of c in TPM DAA Join command is incorrect. Affected stages: 16,20\n"); + LogError( "\t c_byte[%d] %s", + c_byteLength, + dump_byte_array( c_byteLength, c_byte)); + LogError( "\tc_internal_byte[%d] %s", + internal_cbyteLength, + dump_byte_array( internal_cbyteLength, internal_cbyte)); + result = TSS_E_INTERNAL_ERROR; + goto close; + } + + // 5m) blind attributesReceiver + sa = (bi_array_ptr)malloc( sizeof( struct _bi_array)); + if( sa == NULL) { + LogError("malloc of %d bytes failed", sizeof( struct _bi_array)); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_new_array( sa, attributesPlatformLength); + for( i=0; i < attributesPlatformLength; i++) { + attributePlatform = bi_set_as_nbin( DAA_PARAM_SIZE_F_I / 8, + attributesPlatform[i]); // allocation + if( attributePlatform == NULL) { + LogError("malloc of <bi> %s failed", "attributePlatform"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + LogDebug("calculating sa[%d]: raLength=%ld cLength=%ld attributesPlatformLength=%ld\n", + i, bi_nbin_size( ra->array[i]), bi_nbin_size( c), bi_nbin_size( attributePlatform)); + bi_add( sa->array[i], ra->array[i], bi_mul( tmp1, c, attributePlatform)); + bi_free_ptr( attributePlatform); + } + attributePlatform = NULL; + // 5o) Commitments + // TODO + + result = Tcsip_TPM_DAA_Join_encapsulate( tcsContext, hDAA, + 21, + 0, NULL, + 0, NULL, + &ownerAuth, &outputSize, &outputData); + if( result != TSS_SUCCESS) goto close; + LogDebug("Done Join 21: return sv_prime2"); + sv_prime2 = bi_set_as_nbin( outputSize, outputData); // allocation + if( sv_prime2 == NULL) { + LogError("malloc of <bi> %s failed", "sv_prime2"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + free( outputData); + sv_prime = bi_new_ptr(); + if( sv_prime == NULL) { + LogError("malloc of <bi> %s failed", "sv_prime"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + // sv_prime = sv_prime2 << DAA_PARAM_SIZE_SPLIT_EXPONENT + bi_shift_left( sv_prime, sv_prime2, DAA_PARAM_SIZE_SPLIT_EXPONENT); + // sv_prime = sv_prime + sv_prime1 + bi_add( sv_prime, sv_prime, sv_prime1); + + sv_tilde_prime = bi_new_ptr(); + // tmp1 = c * v_tilde_prime + bi_mul( tmp1, c, v_tilde_prime); + // sv_tilde_prime = rv_tilde_prime + tmp1 + bi_add( sv_tilde_prime, rv_tilde_prime, tmp1); + + // step 6) - choose nonce + bi_urandom( tmp1, DAA_PARAM_SAFETY_MARGIN * 8); + noncePlatform = (BYTE *)calloc_tspi( tcsContext, DAA_PARAM_SAFETY_MARGIN); + if( noncePlatform == NULL) { + LogError("malloc of <bi> %s failed", "noncePlatform"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_2_nbin1( &noncePlatformLength, noncePlatform, tmp1); + + LogDebug("challenge:%s", dump_byte_array( c_byteLength, c_byte)); + LogDebug("sF0 [%ld]:%s", bi_length( s_f0), bi_2_hex_char( s_f0)); + LogDebug("sF1 [%ld]:%s", bi_length( s_f1), bi_2_hex_char( s_f1)); + LogDebug("sv_prime [%ld]:%s", bi_length( sv_prime), bi_2_hex_char( sv_prime)); + LogDebug("sv_tilde_prime [%ld]:%s", bi_length( sv_tilde_prime), bi_2_hex_char( sv_tilde_prime)); + // update joinSession + joinSession->capitalU = calloc_tspi( tcsContext, bi_nbin_size( capitalU)); + if( joinSession->capitalU == NULL) { + LogError("malloc of %ld bytes failed", bi_nbin_size( capitalU)); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_2_nbin1( &(joinSession->capitalULength), + joinSession->capitalU, + capitalU); + joinSession->attributesPlatformLength = attributesPlatformLength; + joinSession->attributesPlatform = calloc_tspi( tcsContext, sizeof(BYTE *)); + for( i=0; i<joinSession->attributesPlatformLength; i++) { + joinSession->attributesPlatform[i] = + calloc_tspi( tcsContext,DAA_PARAM_SIZE_F_I / 8); + memcpy( joinSession->attributesPlatform[i], + attributesPlatform[i], + DAA_PARAM_SIZE_F_I / 8); + } + joinSession->noncePlatform = noncePlatform; + joinSession->noncePlatformLength = noncePlatformLength; + joinSession->vTildePrime = calloc_tspi( tcsContext, bi_nbin_size( v_tilde_prime)); + if( joinSession->vTildePrime == NULL) { + LogError("malloc of %ld bytes failed", bi_nbin_size( v_tilde_prime)); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_2_nbin1( &(joinSession->vTildePrimeLength), + joinSession->vTildePrime, + v_tilde_prime); + // update credentialRequest + credentialRequest->capitalU = calloc_tspi( tcsContext, bi_nbin_size( capitalU)); + if( credentialRequest->capitalU == NULL) { + LogError("malloc of %ld bytes failed", bi_nbin_size( capitalU)); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_2_nbin1( &(credentialRequest->capitalULength), + credentialRequest->capitalU, + capitalU); + credentialRequest->capitalNi = calloc_tspi( tcsContext, bi_nbin_size( capital_ni)); + if( credentialRequest->capitalNi == NULL) { + LogError("malloc of %ld bytes failed", bi_nbin_size( capital_ni)); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_2_nbin1( &(credentialRequest->capitalNiLength), + credentialRequest->capitalNi, + capital_ni); + credentialRequest->authenticationProofLength = authentication_proofLength; + credentialRequest->authenticationProof = authentication_proof; + credentialRequest->challenge = c_byte; + credentialRequest->challengeLength = c_byteLength; + credentialRequest->nonceTpm = nonce_tpm; + credentialRequest->nonceTpmLength = nonce_tpmLength; + credentialRequest->noncePlatform = noncePlatform; + credentialRequest->noncePlatformLength = DAA_PARAM_SAFETY_MARGIN; + credentialRequest->sF0 = calloc_tspi( tcsContext, bi_nbin_size( s_f0)); + if( credentialRequest->sF0 == NULL) { + LogError("malloc of %ld bytes failed", bi_nbin_size( s_f0)); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_2_nbin1( &(credentialRequest->sF0Length), credentialRequest->sF0, s_f0); + credentialRequest->sF1 = calloc_tspi( tcsContext, bi_nbin_size( s_f1)); + if( credentialRequest->sF1 == NULL) { + LogError("malloc of %ld bytes failed", bi_nbin_size( s_f1)); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_2_nbin1( &(credentialRequest->sF1Length), credentialRequest->sF1, s_f1); + credentialRequest->sVprime = calloc_tspi( tcsContext, bi_nbin_size( sv_prime)); + if( credentialRequest->sVprime == NULL) { + LogError("malloc of %ld bytes failed", bi_nbin_size( sv_prime)); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_2_nbin1( &(credentialRequest->sVprimeLength), + credentialRequest->sVprime, + sv_prime); + credentialRequest->sVtildePrime = calloc_tspi( tcsContext, bi_nbin_size( sv_tilde_prime)); + if( credentialRequest->sVtildePrime == NULL) { + LogError("malloc of %ld bytes failed", bi_nbin_size( sv_tilde_prime)); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_2_nbin1( &(credentialRequest->sVtildePrimeLength), + credentialRequest->sVtildePrime, + sv_tilde_prime); + length = (DAA_PARAM_SIZE_RANDOMIZED_ATTRIBUTES + 7) / 8; + LogDebug("SA length=%d", sa->length); + credentialRequest->sA = calloc_tspi( tcsContext, sizeof( BYTE *) * sa->length); + if( credentialRequest->sA == NULL) { + LogError("malloc of %d bytes failed", sizeof( BYTE *) * sa->length); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + + for( i=0; i<(UINT32)sa->length; i++) { + LogDebug("sa[%d].size=%d", i, (int)bi_nbin_size( sa->array[i])); + credentialRequest->sA[i] = calloc_tspi( tcsContext, length); + if( credentialRequest->sA[i] == NULL) { + LogError("malloc of %d bytes failed", length); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + // size used only as repository + bi_2_byte_array( credentialRequest->sA[i], length, sa->array[i]); + } + credentialRequest->sALength = sa->length; +close: + if( capitalSprime_byte_array!=NULL) free( capitalSprime_byte_array); + if( ch!=NULL) free( ch); + if( internal_cbyte != NULL) free( internal_cbyte); + bi_free_ptr( rv_tilde_prime); + bi_free_ptr( v_tilde_prime); + bi_free_ptr( capital_utilde); + bi_free_ptr( tmp1); + bi_free_ptr( tmp2); + bi_free_ptr( capitalU); + if( ra != NULL) { + bi_free_array( ra); + free( ra); + } + if( sa != NULL) { + bi_free_array( sa); + free( sa); + } + FREE_BI( capital_ni); + FREE_BI( capital_utilde_prime); + FREE_BI( capital_ni_tilde); + FREE_BI( n); + FREE_BI( attributePlatform); + FREE_BI( c); + FREE_BI( zeta); + FREE_BI( capital_Uprime); + FREE_BI( sv_tilde_prime); + FREE_BI( s_f0); + FREE_BI( s_f1); + FREE_BI( sv_prime); + FREE_BI( sv_prime1); + FREE_BI( sv_prime2); + FREE_BI( product_attributes); + free_TSS_DAA_PK_internal( pk_internal); + return result; +} + +/* +Code influenced by TSS.java (joinStoreCredential) +*/ +TSPICALL Tspi_TPM_DAA_JoinStoreCredential_internal +( + TSS_HDAA hDAA, // in + TSS_HTPM hTPM, // in + TSS_DAA_CRED_ISSUER credIssuer, // in + TSS_DAA_JOIN_SESSION joinSession, // in + TSS_HKEY* hDaaCredential // out +) { + TCS_CONTEXT_HANDLE tcsContext; + TPM_AUTH ownerAuth; + bi_ptr tmp1 = bi_new_ptr(); + bi_ptr tmp2 = bi_new_ptr(); + bi_ptr n = NULL; + bi_ptr e = NULL; + bi_ptr fraction_A = NULL; + bi_ptr v_prime_prime = NULL; + bi_ptr capital_U = NULL; + bi_ptr product_attributes = NULL; + bi_ptr capital_Atilde = NULL; + bi_ptr s_e = NULL; + bi_ptr c_prime = NULL; + bi_ptr capital_A = NULL; + bi_ptr product = NULL; + bi_ptr v_tilde_prime = NULL; + bi_ptr v_prime_prime0 = NULL; + bi_ptr v_prime_prime1 = NULL; + TSS_DAA_PK *daa_pk_extern; + TSS_DAA_PK_internal *pk_intern = NULL; + TSS_DAA_CREDENTIAL *daaCredential; + bi_array_ptr attributes_issuer; + TSS_RESULT result = TSS_SUCCESS; + UINT32 i; + UINT32 c_byteLength, v0Length, v1Length, tpm_specificLength; + BYTE *c_byte = NULL; + BYTE *v0 = NULL; + BYTE *v1 = NULL; + BYTE *tpm_specific = NULL; + + if( tmp1 == NULL || tmp2 == NULL) { + LogError("malloc of bi(s) failed"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + if( (result = obj_tpm_is_connected( hTPM, &tcsContext)) != TSS_SUCCESS) return result; + obj_daa_set_handle_tpm( hDAA, hTPM); + + LogDebug("Converting issuer public"); + daa_pk_extern = (TSS_DAA_PK *)joinSession.issuerPk; + pk_intern = e_2_i_TSS_DAA_PK( daa_pk_extern); + if( pk_intern == NULL) { + LogError("malloc of pk_intern failed"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + n = bi_new_ptr(); + if( n == NULL) { + LogError("malloc of bi <%s> failed", "n"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_set( n, pk_intern->modulus); + attributes_issuer = (bi_array_ptr)malloc( sizeof( struct _bi_array)); + if( attributes_issuer == NULL) { + LogError("malloc of %d bytes failed", sizeof( struct _bi_array)); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_new_array( attributes_issuer, credIssuer.attributesIssuerLength); + if( attributes_issuer->array == NULL) { + LogError("malloc of bi_array <%s> failed", "attributes_issuer->array"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + for( i=0; i < credIssuer.attributesIssuerLength; i++) { + // allocation + attributes_issuer->array[i] = bi_set_as_nbin( DAA_PARAM_SIZE_F_I / 8, + credIssuer.attributesIssuer[i]); + if( attributes_issuer->array[i] == NULL) { + LogError("malloc of bi <attributes_issuer->array[%d]> failed", i); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + } + LogDebug("verify credential of issuer ( part 1)"); + e = bi_set_as_nbin( credIssuer.eLength, credIssuer.e); // allocation + if( e == NULL) { + LogError("malloc of bi <%s> failed", "e"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_set( tmp1, bi_0); + bi_setbit( tmp1, DAA_PARAM_SIZE_EXPONENT_CERTIFICATE - 1); + bi_set( tmp2, bi_0); + bi_setbit( tmp1, DAA_PARAM_SIZE_INTERVAL_EXPONENT_CERTIFICATE - 1); + bi_add( tmp1, tmp1, tmp2); + if( bi_is_probable_prime( e) == 0 || + bi_length(e) < DAA_PARAM_SIZE_EXPONENT_CERTIFICATE || + bi_cmp( e, tmp1) > 0) { + LogError("Verification e failed - Step 1.a"); + LogError("\tPrime(e):%d", bi_is_probable_prime( e)); + LogError("\tbit_length(e):%ld", bi_length(e)); + LogError("\te > (2^(l_e) + 2^(l_prime_e)):%d", bi_cmp( e, tmp1)); + result = TSS_E_DAA_CREDENTIAL_PROOF_ERROR; + goto close; + } + LogDebug("verify credential of issuer (part 2) with proof"); + fraction_A = bi_new_ptr(); + if( fraction_A == NULL) { + LogError("malloc of bi <%s> failed", "fraction_A"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + v_prime_prime = bi_set_as_nbin( credIssuer.vPrimePrimeLength, + credIssuer.vPrimePrime); // allocation + if( v_prime_prime == NULL) { + LogError("malloc of bi <%s> failed", "v_prime_prime"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + capital_U = bi_set_as_nbin( joinSession.capitalULength, + joinSession.capitalU); // allocation + if( capital_U == NULL) { + LogError("malloc of bi <%s> failed", "capital_U"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_mod_exp( fraction_A, pk_intern->capitalS, v_prime_prime, n); + bi_mul( fraction_A, fraction_A, capital_U); + bi_mod( fraction_A, fraction_A, n); + LogDebug("encode attributes"); + product_attributes = bi_new_ptr(); + bi_set( product_attributes, bi_1); + for( i=0; i<(UINT32)attributes_issuer->length; i++) { + bi_mod_exp( tmp1, pk_intern->capitalRIssuer->array[i], + attributes_issuer->array[i], n); + bi_mul( product_attributes, tmp1, product_attributes); + bi_mod( product_attributes, product_attributes, n); + } + bi_mul( fraction_A, fraction_A, product_attributes); + bi_mod( fraction_A, fraction_A, n); + capital_Atilde = bi_new_ptr(); + if( capital_Atilde == NULL) { + LogError("malloc of bi <%s> failed", "capital_Atilde"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_invert_mod( capital_Atilde, fraction_A, n); + bi_mul( capital_Atilde, capital_Atilde, pk_intern->capitalZ); + bi_mod( capital_Atilde, capital_Atilde, n); + s_e = bi_set_as_nbin( credIssuer.sELength, credIssuer.sE); // allocation + if( s_e == NULL) { + LogError("malloc of bi <%s> failed", "s_e"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_mod_exp( capital_Atilde, capital_Atilde, s_e, n); + c_prime = bi_set_as_nbin( credIssuer.cPrimeLength, credIssuer.cPrime); // allocation + if( c_prime == NULL) { + LogError("malloc of bi <%s> failed", "c_prime"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + capital_A = bi_set_as_nbin( credIssuer.capitalALength, credIssuer.capitalA); // allocation + if( capital_A == NULL) { + LogError("malloc of bi <%s> failed", "capital_A"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_mod_exp( tmp1, capital_A, c_prime, n); + bi_mul( capital_Atilde, capital_Atilde, tmp1); + bi_mod( capital_Atilde, capital_Atilde, n); + + result = compute_join_challenge_issuer( pk_intern, + v_prime_prime, + capital_A, + capital_Atilde, + joinSession.noncePlatformLength, + joinSession.noncePlatform, + &c_byteLength, + &c_byte); // out allocation + if( result != TSS_SUCCESS) goto close; + if( credIssuer.cPrimeLength != c_byteLength || + memcmp( credIssuer.cPrime, c_byte, c_byteLength)!=0) { + LogError("Verification of c failed - Step 1.c.i"); + LogError("credentialRequest.cPrime[%d]=%s", + credIssuer.cPrimeLength, + dump_byte_array( credIssuer.cPrimeLength, credIssuer.cPrime) ); + LogError("challenge[%d]=%s", + c_byteLength, + dump_byte_array( c_byteLength, c_byte) ); + result = TSS_E_DAA_CREDENTIAL_PROOF_ERROR; + goto close; + } + product = bi_new_ptr(); + if( product == NULL) { + LogError("malloc of bi <%s> failed", "product"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_mod_exp( product, capital_A, e, n); + bi_mul( product, product, fraction_A); + bi_mod( product, product, n); + if( bi_equals( pk_intern->capitalZ, product) == 0) { + LogError("Verification of A failed - Step 1.c.ii"); + LogError("\tcapitalZ=%s", bi_2_hex_char( pk_intern->capitalZ)); + LogError("\tproduct=%s", bi_2_hex_char( product)); + result = TSS_E_DAA_CREDENTIAL_PROOF_ERROR; + goto close; + } + v_tilde_prime = bi_set_as_nbin( joinSession.vTildePrimeLength, + joinSession.vTildePrime); // allocation + bi_add( v_prime_prime, v_prime_prime, v_tilde_prime); + bi_shift_left( tmp1, bi_1, DAA_PARAM_SIZE_SPLIT_EXPONENT); + v_prime_prime0 = bi_new_ptr(); + if( v_prime_prime0 == NULL) { + LogError("malloc of bi <%s> failed", "v_prime_prime0"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_mod( v_prime_prime0, v_prime_prime, tmp1); + v_prime_prime1 = bi_new_ptr(); + if( v_prime_prime1 == NULL) { + LogError("malloc of bi <%s> failed", "v_prime_prime1"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_shift_right( v_prime_prime1, v_prime_prime, DAA_PARAM_SIZE_SPLIT_EXPONENT); + free( c_byte); + c_byte = (BYTE *)malloc( TPM_DAA_SIZE_v0); + if( c_byte == NULL) { + LogError("malloc of %d bytes failed", TPM_DAA_SIZE_v0); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_2_byte_array( c_byte, TPM_DAA_SIZE_v0, v_prime_prime0); + result = Tcsip_TPM_DAA_Join_encapsulate( tcsContext, hDAA, + 22, + TPM_DAA_SIZE_v0, c_byte, + 0, NULL, + &ownerAuth, &v0Length, &v0); + if( result != TSS_SUCCESS) goto close; + LogDebug("Done Join 22: return v0"); + free( c_byte); + c_byte = (BYTE *)malloc( TPM_DAA_SIZE_v1); + if( c_byte == NULL) { + LogError("malloc of %d bytes failed", TPM_DAA_SIZE_v1); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_2_byte_array( c_byte, TPM_DAA_SIZE_v1, v_prime_prime1); + result = Tcsip_TPM_DAA_Join_encapsulate( tcsContext, hDAA, + 23, + TPM_DAA_SIZE_v1, c_byte, + 0, NULL, + &ownerAuth, &v1Length, &v1); + if( result != TSS_SUCCESS) goto close; + LogDebug("Done Join 23: return v1"); + result = Tcsip_TPM_DAA_Join_encapsulate( tcsContext, hDAA, + 24, + 0, NULL, + 0, NULL, + &ownerAuth, &tpm_specificLength, &tpm_specific); + if( result != TSS_SUCCESS) goto close; + + daaCredential = (TSS_DAA_CREDENTIAL *)hDaaCredential; + daaCredential->capitalA = calloc_tspi( tcsContext, bi_nbin_size( capital_A)); + if( daaCredential->capitalA == NULL) { + LogError("malloc of %ld bytes failed", bi_nbin_size( capital_A)); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_2_nbin1( &(daaCredential->capitalALength), daaCredential->capitalA, capital_A); + daaCredential->exponent = calloc_tspi( tcsContext, bi_nbin_size( e)); + if( daaCredential->exponent == NULL) { + LogError("malloc of %ld bytes failed", bi_nbin_size( e)); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_2_nbin1( &(daaCredential->exponentLength), daaCredential->exponent, e); + daaCredential->vBar0 = calloc_tspi( tcsContext, v0Length); + if( daaCredential->vBar0 == NULL) { + LogError("malloc of %d bytes failed", v0Length); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + daaCredential->vBar0Length = v0Length; + memcpy( daaCredential->vBar0, v0, v0Length); + LogDebug("vBar0[%d]=%s", + daaCredential->vBar0Length, + dump_byte_array( daaCredential->vBar0Length, daaCredential->vBar0)); + daaCredential->vBar1 = calloc_tspi( tcsContext, v1Length); + if( daaCredential->vBar1 == NULL) { + LogError("malloc of %d bytes failed", v1Length); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + daaCredential->vBar1Length = v1Length; + memcpy( daaCredential->vBar1, v1, v1Length); + LogDebug("vBar1[%d]=%s", + daaCredential->vBar1Length, + dump_byte_array( daaCredential->vBar1Length, daaCredential->vBar1)); + //TODO remove + LogDebug("[BUSS] joinSession.attributesPlatformLength=%d", + joinSession.attributesPlatformLength); + LogDebug("[BUSS] credIssuer.attributesIssuerLength=%d", + credIssuer.attributesIssuerLength); + daaCredential->attributesLength = joinSession.attributesPlatformLength + + credIssuer.attributesIssuerLength; + daaCredential->attributes = (BYTE **)calloc_tspi( tcsContext, + sizeof(BYTE *) * daaCredential->attributesLength); + if( daaCredential->attributes == NULL) { + LogError("malloc of %d bytes failed", + sizeof(BYTE *) * daaCredential->attributesLength); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + for( i=0; i < joinSession.attributesPlatformLength; i++) { + daaCredential->attributes[i] = calloc_tspi( tcsContext, DAA_PARAM_SIZE_F_I / 8); + if( daaCredential->attributes[i] == NULL) { + LogError("malloc of %d bytes failed", DAA_PARAM_SIZE_F_I / 8); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + LogDebug("allocation attributes[%d]=%lx", i, (long)daaCredential->attributes[i]); + memcpy( daaCredential->attributes[i], + joinSession.attributesPlatform[i], + DAA_PARAM_SIZE_F_I / 8); + } + for( i=0; i < credIssuer.attributesIssuerLength; i++) { + daaCredential->attributes[i+joinSession.attributesPlatformLength] = + calloc_tspi( tcsContext, DAA_PARAM_SIZE_F_I / 8); + if( daaCredential->attributes[i+joinSession.attributesPlatformLength] == NULL) { + LogError("malloc of %d bytes failed", DAA_PARAM_SIZE_F_I / 8); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + memcpy( daaCredential->attributes[i+joinSession.attributesPlatformLength], + credIssuer.attributesIssuer[i], DAA_PARAM_SIZE_F_I / 8); + } + memcpy( &(daaCredential->issuerPK), daa_pk_extern, sizeof( TSS_DAA_PK)); + daaCredential->tpmSpecificEnc = calloc_tspi( tcsContext, tpm_specificLength); + if( daaCredential->tpmSpecificEnc == NULL) { + LogError("malloc of %d bytes failed", tpm_specificLength); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + daaCredential->tpmSpecificEncLength = tpm_specificLength; + memcpy( daaCredential->tpmSpecificEnc, tpm_specific, tpm_specificLength); + // TODO store in TSS this TSS_DAA_CREDENTIAL_REQUEST + *hDaaCredential = (TSS_HKEY)daaCredential; +close: + if( v0 != NULL) free( v0); + if( v1 != NULL) free( v1); + if( tpm_specific != NULL) free( tpm_specific); + if( c_byte != NULL) free( c_byte); + bi_free_ptr( tmp2); + bi_free_ptr( tmp1); + if( attributes_issuer != NULL) { + bi_free_array( attributes_issuer); + free( attributes_issuer); + } + FREE_BI( v_prime_prime1); + FREE_BI( v_prime_prime0); + FREE_BI( v_tilde_prime); + FREE_BI( product); + FREE_BI( capital_A); + FREE_BI( c_prime); + FREE_BI( s_e); + FREE_BI( capital_Atilde); + FREE_BI( product_attributes); + FREE_BI( capital_U); + FREE_BI( v_prime_prime); + FREE_BI( fraction_A); + FREE_BI( e); + FREE_BI( n); + if( pk_intern!=NULL) free_TSS_DAA_PK_internal( pk_intern); + return result; +} + +static void add_splitet( bi_ptr result, bi_ptr a, bi_ptr b) { + bi_shift_left( result, bi_1, DAA_PARAM_SIZE_SPLIT_EXPONENT); + bi_mul( result, result, b); + bi_add( result, result, a); +} + +/* code influenced by TSS.java (signStep) */ +TSS_RESULT Tspi_TPM_DAA_Sign_internal +( + TSS_HDAA hDAA, // in + TSS_HTPM hTPM, // in + TSS_HKEY hDaaCredential, // in + TSS_DAA_SELECTED_ATTRIB revealAttributes, // in + UINT32 verifierBaseNameLength, // in + BYTE* verifierBaseName, // in + UINT32 verifierNonceLength, // in + BYTE* verifierNonce, // in + TSS_DAA_SIGN_DATA signData, // in + TSS_DAA_SIGNATURE* daaSignature // out +) +{ + TCS_CONTEXT_HANDLE tcsContext; + TSS_DAA_CREDENTIAL *daaCredential; + TPM_DAA_ISSUER *tpm_daa_issuer; + TPM_AUTH ownerAuth; + TSS_RESULT result = TSS_SUCCESS; + TSS_DAA_PK *pk; + TSS_DAA_PK_internal *pk_intern; + int i; + bi_ptr tmp1 = bi_new_ptr(), tmp2; + bi_ptr n = NULL; + bi_ptr capital_gamma = NULL; + bi_ptr gamma = NULL; + bi_ptr zeta = NULL; + bi_ptr r = NULL; + bi_ptr t_tilde_T = NULL; + bi_ptr capital_Nv = NULL; + bi_ptr capital_N_tilde_v = NULL; + bi_ptr w = NULL; + bi_ptr capital_T = NULL; + bi_ptr r_E = NULL; + bi_ptr r_V = NULL; + bi_ptr capital_T_tilde = NULL; + bi_ptr capital_A = NULL; + bi_array_ptr capital_R; + bi_ptr product_R = NULL; + bi_array_ptr r_A = NULL; + bi_array_ptr s_A = NULL; + bi_ptr c = NULL; + bi_ptr sF0 = NULL; + bi_ptr sF1 = NULL; + bi_ptr sV1 = NULL; + bi_ptr sV2 = NULL; + bi_ptr e = NULL; + bi_ptr s_E = NULL; + bi_ptr s_V = NULL; + CS_ENCRYPTION_RESULT_RANDOMNESS *encryption_result_rand = NULL; + BYTE *issuer_settings = NULL, *outputData, byte; + BYTE *buffer = NULL, *ch = NULL, *nonce_tpm = NULL, *c_bytes = NULL; + UINT32 issuer_settingsLength, outputSize, length, size_bits, chLength; + UINT32 nonce_tpmLength; + UINT32 c_bytesLength, return_sign_session; + // for anonymity revocation + CS_ENCRYPTION_RESULT *encryption_result = NULL; + CS_ENCRYPTION_RESULT *encryption_result_tilde = NULL; + TSS_DAA_PSEUDONYM *signature_pseudonym; + TSS_DAA_PSEUDONYM_PLAIN *pseudonym_plain = NULL; + TSS_DAA_PSEUDONYM_PLAIN *pseudonym_plain_tilde = NULL; + TSS_DAA_ATTRIB_COMMIT *signed_commitments; + + if( (result = obj_tpm_is_connected( hTPM, &tcsContext)) != TSS_SUCCESS) + return result; + if( tmp1 == NULL) { + LogError("malloc of bi <%s> failed", "tmp1"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + obj_daa_set_handle_tpm( hDAA, hTPM); + // TODO retrieve the daaCredential from the persistence storage + daaCredential = (TSS_DAA_CREDENTIAL *)hDaaCredential; + pk = (TSS_DAA_PK *)&(daaCredential->issuerPK); + pk_intern = e_2_i_TSS_DAA_PK( pk); + if( pk_intern == NULL) { + LogError("malloc of <%s> failed", "pk_intern"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + tpm_daa_issuer = convert2issuer_settings( pk_intern); + if( daaCredential->attributesLength == 0 || + daaCredential->attributesLength != revealAttributes.indicesListLength) { + LogDebug("Problem with the reveal attribs: attributes length:%d reveal length:%d", + daaCredential->attributesLength, revealAttributes.indicesListLength); + result = TSS_E_BAD_PARAMETER; + goto close; + } + if( verifierNonce == NULL || + verifierNonceLength != DAA_PARAM_LENGTH_MESSAGE_DIGEST) { + LogDebug("Problem with the nonce verifier: nonce verifier length:%d", + verifierNonceLength); + result = TSS_E_BAD_PARAMETER; + goto close; + } + n = bi_new_ptr(); + if( n == NULL) { + LogError("malloc of bi <%s> failed", "n"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_set( n, pk_intern->modulus); + capital_gamma = bi_new_ptr(); + if( capital_gamma == NULL) { + LogError("malloc of bi <%s> failed", "capital_gamma"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_set( capital_gamma, pk_intern->capitalGamma); + gamma = bi_new_ptr(); + if( gamma == NULL) { + LogError("malloc of bi <%s> failed", "gamma"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_set( gamma, pk_intern->gamma); + if( verifierBaseNameLength == 0 || verifierBaseName == NULL) { + r = bi_new_ptr(); + compute_random_number( r, capital_gamma); + zeta = project_into_group_gamma( r, pk_intern); // allocation + if( zeta == NULL) { + LogError("malloc of bi <%s> failed", "zeta"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + } else { + zeta = compute_zeta( verifierBaseNameLength, verifierBaseName, pk_intern); + if( zeta == NULL) { + LogError("malloc of bi <%s> failed", "zeta"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + } + issuer_settings = issuer_2_byte_array( tpm_daa_issuer, + &issuer_settingsLength); // allocation + if( issuer_settings == NULL) { + LogError("malloc of %d bytes failed", issuer_settingsLength); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + LogDebug( "Issuer Settings:[%s]", + dump_byte_array(issuer_settingsLength, issuer_settings) ); + result = Tcsip_TPM_DAA_Sign( + tcsContext, hDAA, + 0, + issuer_settingsLength, issuer_settings, + 0, NULL, + &ownerAuth, &outputSize, &outputData); + if( result != TSS_SUCCESS) goto close; + // set the sessionHandle to the returned value + return_sign_session = ntohl( *((UINT32 *)outputData)); + obj_daa_set_session_handle( hDAA, return_sign_session); + free( outputData); + result = Tcsip_TPM_DAA_Sign( + tcsContext, hDAA, + 1, + daaCredential->tpmSpecificEncLength, daaCredential->tpmSpecificEnc, + 0, NULL, + &ownerAuth, &outputSize, &outputData); + if( result != TSS_SUCCESS) goto close; + free( outputData); + LogDebug( "done Sign 1 - TPM specific"); + result = Tcsip_TPM_DAA_Sign( + tcsContext, hDAA, + 2, + pk->capitalR0Length, pk->capitalR0, + pk->modulusLength, pk->modulus, + &ownerAuth, &outputSize, &outputData); + if( result != TSS_SUCCESS) goto close; + free( outputData); + LogDebug( "done Sign 2 - capitalR0"); + result = Tcsip_TPM_DAA_Sign( + tcsContext, hDAA, + 3, + pk->capitalR1Length, pk->capitalR1, + pk->modulusLength, pk->modulus, + &ownerAuth, &outputSize, &outputData); + if( result != TSS_SUCCESS) goto close; + free( outputData); + LogDebug( "done Sign 3 - capitalR1"); + result = Tcsip_TPM_DAA_Sign( + tcsContext, hDAA, + 4, + pk->capitalSLength, pk->capitalS, + pk->modulusLength, pk->modulus, + &ownerAuth, &outputSize, &outputData); + if( outputSize > 0 && outputData != NULL) free( outputData); + if( result != TSS_SUCCESS) goto close; + LogDebug( "done Sign 4 - capitalS"); + buffer = bi_2_nbin( &length, pk_intern->capitalSprime); // allocation + if( buffer == NULL) { + LogError("malloc of %d bytes failed", length); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + result = Tcsip_TPM_DAA_Sign( + tcsContext, hDAA, + 5, + length, buffer, + pk->modulusLength, pk->modulus, + &ownerAuth, &outputSize, &outputData); + free( buffer); + if( result != TSS_SUCCESS) goto close; + LogDebug( "done Sign 5 - capitalSPrime. Return t_tilde_T"); + t_tilde_T = bi_set_as_nbin( outputSize, outputData); // allocation + if( t_tilde_T == NULL) { + LogError("malloc of bi <%s> failed", "t_tilde_T"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + free( outputData); + // first precomputation until here possible (verifier independent) + length = TPM_DAA_SIZE_w; + buffer = (BYTE *)malloc( length); + if( buffer == NULL) { + LogError("malloc of %d bytes failed", length); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_2_byte_array( buffer, length, zeta); + result = Tcsip_TPM_DAA_Sign( + tcsContext, hDAA, + 6, + pk->capitalGammaLength, pk->capitalGamma, + length, buffer, + &ownerAuth, &outputSize, &outputData); + free( buffer); + if( result != TSS_SUCCESS) goto close; + LogDebug( "done Sign 6 - capitalGamma & zeta"); + result = Tcsip_TPM_DAA_Sign( + tcsContext, hDAA, + 7, + pk->capitalGammaLength, pk->capitalGamma, + 0, NULL, + &ownerAuth, &outputSize, &outputData); + if( result != TSS_SUCCESS) goto close; + LogDebug( "done Sign 7 - capitalGamma. Return capital_Nv"); + capital_Nv = bi_set_as_nbin( outputSize, outputData); // allocation + if( capital_Nv == NULL) { + LogError("malloc of bi <%s> failed", "capital_Nv"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + free( outputData); + // TODO Step 6 a.b - anonymity revocation + + result = Tcsip_TPM_DAA_Sign( + tcsContext, hDAA, + 8, + pk->capitalGammaLength, pk->capitalGamma, + 0, NULL, + &ownerAuth, &outputSize, &outputData); + if( result != TSS_SUCCESS) goto close; + LogDebug( "done Sign 8 - capitalGamma. Return capital_N_tilde_v"); + capital_N_tilde_v = bi_set_as_nbin( outputSize, outputData); // allocation + if( capital_N_tilde_v == NULL) { + LogError("malloc of bi <%s> failed", "capital_N_tilde_v"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + free( outputData); + // TODO Step 6 c,d - anonymity revocation + + // Second precomputation until here possible (verifier dependent) + size_bits = DAA_PARAM_SIZE_RSA_MODULUS + DAA_PARAM_SAFETY_MARGIN; + w = bi_new_ptr(); + if( w == NULL) { + LogError("malloc of bi <%s> failed", "w"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_urandom( w, size_bits); + capital_A = bi_set_as_nbin( daaCredential->capitalALength, + daaCredential->capitalA); // allocation + if( capital_A == NULL) { + LogError("malloc of bi <%s> failed", "capital_A"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + capital_T = bi_new_ptr(); + if( capital_T == NULL) { + LogError("malloc of bi <%s> failed", "capital_T"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_mod_exp( tmp1, pk_intern->capitalS, w, n); + bi_mul( capital_T, capital_A, tmp1); + bi_mod( capital_T, capital_T, n); + size_bits = DAA_PARAM_SIZE_INTERVAL_EXPONENT_CERTIFICATE + + DAA_PARAM_SAFETY_MARGIN + DAA_PARAM_SIZE_MESSAGE_DIGEST; + r_E = bi_new_ptr(); + if( r_E == NULL) { + LogError("malloc of bi <%s> failed", "r_E"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_urandom( r_E, size_bits); + size_bits = DAA_PARAM_SIZE_EXPONENT_CERTIFICATE + DAA_PARAM_SIZE_RSA_MODULUS + + 2 * DAA_PARAM_SAFETY_MARGIN + DAA_PARAM_SIZE_MESSAGE_DIGEST + 1; + r_V = bi_new_ptr(); + if( r_V == NULL) { + LogError("malloc of bi <%s> failed", "r_V"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_urandom( r_V, size_bits); + capital_T_tilde = bi_new_ptr(); + if( capital_T_tilde == NULL) { + LogError("malloc of bi <%s> failed", "capital_T_tilde"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_mod_exp( tmp1, capital_T, r_E, n); + bi_mul( capital_T_tilde, t_tilde_T, tmp1); + bi_mod( capital_T_tilde, capital_T_tilde, n); + + bi_mod_exp( tmp1, pk_intern->capitalS, r_V, n); + bi_mul( capital_T_tilde, capital_T_tilde, tmp1); + bi_mod( capital_T_tilde, capital_T_tilde, n); + + // attributes extension + size_bits = DAA_PARAM_SIZE_F_I + + DAA_PARAM_SAFETY_MARGIN + + DAA_PARAM_SIZE_MESSAGE_DIGEST; + capital_R = pk_intern->capitalY; + r_A = (bi_array_ptr)malloc( sizeof( struct _bi_array)); + if( r_A == NULL) { + LogError("malloc of %d bytes failed", sizeof( struct _bi_array)); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_new_array2( r_A, revealAttributes.indicesListLength); + product_R = bi_new_ptr(); + if( product_R == NULL) { + LogError("malloc of bi <%s> failed", "product_R"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_set( product_R, bi_1); + for( i=0; i<(int)revealAttributes.indicesListLength; i++) { + if( revealAttributes.indicesList[i] == 0) { + // only non selected + r_A->array[i] = bi_new_ptr(); + if( r_A->array[i] == NULL) { + LogError("malloc of bi <%s> failed", "r_A->array[i]"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_urandom( r_A->array[i] , size_bits); + bi_mod_exp( tmp1, capital_R->array[i], r_A->array[i], n); + bi_mul( product_R, product_R, tmp1); + bi_mod( product_R, product_R, n); + } else r_A->array[i] = NULL; + } + bi_mul( capital_T_tilde, capital_T_tilde, product_R); + bi_mod( capital_T_tilde, capital_T_tilde, n); + //TODO Step 8 - Commitments + // compute commitment to attributes not revealed to the verifier + + //TODO Step 9 - callback functions + + // only when revocation not enabled + pseudonym_plain = (TSS_DAA_PSEUDONYM_PLAIN *)calloc_tspi( tcsContext, + sizeof(TSS_DAA_PSEUDONYM_PLAIN)); + if( pseudonym_plain == NULL) { + LogError("malloc of %d bytes failed", sizeof(TSS_DAA_PSEUDONYM_PLAIN)); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + init_tss_version( pseudonym_plain); + pseudonym_plain->capitalNv = calloc_tspi( tcsContext, + bi_nbin_size( capital_Nv)); + if( pseudonym_plain->capitalNv == NULL) { + LogError("malloc of bi <%s> failed", "pseudonym_plain->capitalNv"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_2_nbin1( &(pseudonym_plain->capitalNvLength), + pseudonym_plain->capitalNv, + capital_Nv); + pseudonym_plain_tilde = (TSS_DAA_PSEUDONYM_PLAIN *) + calloc_tspi( tcsContext,sizeof(TSS_DAA_PSEUDONYM_PLAIN)); + if( pseudonym_plain_tilde == NULL) { + LogError("malloc of %d bytes failed", sizeof(TSS_DAA_PSEUDONYM_PLAIN)); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + init_tss_version( pseudonym_plain_tilde); + pseudonym_plain_tilde->capitalNv = calloc_tspi( tcsContext, + bi_nbin_size( capital_N_tilde_v)); + if( pseudonym_plain_tilde->capitalNv == NULL) { + LogError("malloc of bi <%s> failed", "pseudonym_plain_tilde->capitalNv"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_2_nbin1( &(pseudonym_plain_tilde->capitalNvLength), + pseudonym_plain_tilde->capitalNv, + capital_N_tilde_v); + + // Step 10 - compute challenge + ch = compute_sign_challenge_host( + &chLength, + DAA_PARAM_get_message_digest(), + pk_intern, + verifierNonceLength, + verifierNonce, + 0, // int selected_attributes2commitLength, + NULL, // TSS_DAA_SELECTED_ATTRIB **selected_attributes2commit, + 0, // int is_anonymity_revocation_enabled, + zeta, + capital_T, + capital_T_tilde, + 0, // int attribute_commitmentsLength, + NULL, // TSS_DAA_ATTRIB_COMMIT_internal **attribute_commitments, + NULL, // TSS_DAA_ATTRIB_COMMIT_internal **attribute_commitment_proofs, + capital_Nv, + capital_N_tilde_v, + NULL, // CS_PUBLIC_KEY *anonymity_revocator_pk, + NULL, // CS_ENCRYPTION_RESULT *encryption_result_rand, + NULL //CS_ENCRYPTION_RESULT *encryption_result_proof) + ); + if( ch == NULL) { + LogError("malloc in compute_sign_challenge_host failed"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + result = Tcsip_TPM_DAA_Sign( tcsContext, hDAA, + 9, + chLength, ch, + 0, NULL, + &ownerAuth, &nonce_tpmLength, &nonce_tpm); + if( result != TSS_SUCCESS) goto close; + LogDebug( "done Sign 9 - compute sign challenge host. Return nonce_tpm"); + byte = (BYTE)signData.payloadFlag; // 0 -> payload contains a handle to an AIK + // 1 -> payload contains a hashed message + result = Tcsip_TPM_DAA_Sign( tcsContext, hDAA, + 10, + sizeof(BYTE), &byte, + signData.payloadLength, signData.payload, + &ownerAuth, &c_bytesLength, &c_bytes); + LogDebug("calculation of c: ch[%d]%s", chLength, dump_byte_array( chLength, ch)); + LogDebug("calculation of c: nonce_tpm[%d]%s", + nonce_tpmLength, + dump_byte_array( nonce_tpmLength, nonce_tpm)); + LogDebug("calculation of c: sign_data.payloadFlag[%d]%x", + 1, + (int)signData.payloadFlag); + LogDebug("calculation of c: signdata.payload[%d]%s", + signData.payloadLength, + dump_byte_array( signData.payloadLength, signData.payload)); + + if( result != TSS_SUCCESS) goto close; + LogDebug( "done Sign 10 - compute signData.payload."); + LogDebug(" Return c_bytes[%d]%s", + c_bytesLength, + dump_byte_array( c_bytesLength, c_bytes)); + c = bi_set_as_nbin( c_bytesLength, c_bytes); // allocation + if( c == NULL) { + LogError("malloc of bi <%s> failed", "c"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + result = Tcsip_TPM_DAA_Sign( + tcsContext, hDAA, + 11, + 0, NULL, + 0, NULL, + &ownerAuth, &outputSize, &outputData); + if( result != TSS_SUCCESS)goto close; + LogDebug( "done Sign 11. Return sF0"); + sF0 = bi_set_as_nbin( outputSize, outputData); // allocation + if( sF0 == NULL) { + LogError("malloc of bi <%s> failed", "sF0"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + free( outputData); + result = Tcsip_TPM_DAA_Sign( + tcsContext, hDAA, + 12, + 0, NULL, + 0, NULL, + &ownerAuth, &outputSize, &outputData); + if( result != TSS_SUCCESS) goto close; + LogDebug( "done Sign 12. Return sF1"); + sF1 = bi_set_as_nbin( outputSize, outputData); // allocation + if( sF1 == NULL) { + LogError("malloc of bi <%s> failed", "sF1"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + free( outputData); + result = Tcsip_TPM_DAA_Sign( + tcsContext, hDAA, + 13, + daaCredential->vBar0Length, daaCredential->vBar0, + 0, NULL, + &ownerAuth, &outputSize, &outputData); + if( result != TSS_SUCCESS) goto close; + LogDebug( "done Sign 13. Return sV1"); + sV1 = bi_set_as_nbin( outputSize, outputData); // allocation + if( sV1 == NULL) { + LogError("malloc of bi <%s> failed", "sV1"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + free( outputData); + result = Tcsip_TPM_DAA_Sign( + tcsContext, hDAA, + 14, + daaCredential->vBar0Length, daaCredential->vBar0, + 0, NULL, + &ownerAuth, &outputSize, &outputData); + if( result != TSS_SUCCESS) goto close; + free( outputData); + LogDebug( "done Sign 14."); + result = Tcsip_TPM_DAA_Sign( + tcsContext, hDAA, + 15, + daaCredential->vBar1Length, daaCredential->vBar1, + 0, NULL, + &ownerAuth, &outputSize, &outputData); + if( result != TSS_SUCCESS) goto close; + LogDebug( "done Sign 15. Return sV2"); + sV2 = bi_set_as_nbin( outputSize, outputData); // allocation + if( sV2 == NULL) { + LogError("malloc of bi <%s> failed", "sV2"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + free( outputData); + // allocation + e = bi_set_as_nbin( daaCredential->exponentLength, daaCredential->exponent); + if( e == NULL) { + LogError("malloc of bi <%s> failed", "e"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + // s_e = r_E + ( c * ( e - ( 1 << (sizeExponentCertificate -1)))) + s_E = bi_new_ptr(); + if( s_E == NULL) { + LogError("malloc of bi <%s> failed", "s_E"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_shift_left( tmp1, bi_1, DAA_PARAM_SIZE_EXPONENT_CERTIFICATE - 1); + bi_sub( tmp1, e, tmp1); + bi_mul( tmp1, c, tmp1); + bi_add( s_E, r_E, tmp1); + s_V = bi_new_ptr(); + if( s_V == NULL) { + LogError("malloc of bi <%s> failed", "s_V"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + add_splitet( s_V, sV1, sV2); + bi_add( s_V, s_V, r_V); + bi_mul( tmp1, c, w); + bi_mul( tmp1, tmp1, e); + bi_sub( s_V, s_V, tmp1); + // attributes extension + // TODO verify the size of each selected attributes + s_A = (bi_array_ptr)malloc( sizeof( struct _bi_array)); + if( s_A == NULL) { + LogError("malloc of bi_array <%s> failed", "s_A"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_new_array2( s_A, revealAttributes.indicesListLength); + if( s_A->array == NULL) { + LogError("malloc of bi_array <%s> failed", "s_A"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + for( i=0; i<(int)revealAttributes.indicesListLength; i++) { + if( revealAttributes.indicesList[i] == 0) { + s_A->array[i] = bi_new_ptr(); + if( s_A->array[i] == NULL) { + LogError("malloc of bi <%s> failed", "s_A->array[i]"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + tmp2 = bi_set_as_nbin( DAA_PARAM_SIZE_F_I / 8, + daaCredential->attributes[i]); // allocation + if( tmp2 == NULL) { + LogError("malloc of %d bytes failed", DAA_PARAM_SIZE_F_I / 8); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_mul( tmp1, c, tmp2); + // TODEL + LogDebug("daaCredential->attributes[i]=%ld", bi_nbin_size( tmp2)); + LogDebug("r_A:%ld", bi_nbin_size( r_A->array[i])); + LogDebug("c:%ld", bi_nbin_size( c)); + LogDebug("c*daaCredential->attributes[i]=%ld", bi_nbin_size( tmp1)); + // END TODEL + bi_add( s_A->array[i], r_A->array[i], tmp1); + bi_free_ptr( tmp2); + } else s_A->array[i] = NULL; + } + + // Compose result structure + + // DAASignaturePseudonym TODO: implement anonymity revocation + // if ( !revocation_enabled) + signature_pseudonym = pseudonym_plain; + + // populate the signature (TSS_DAA_SIGNATURE) + daaSignature->zeta = (BYTE *)calloc_tspi( tcsContext, bi_nbin_size( zeta)); + if (daaSignature->zeta == NULL) { + LogError("malloc of %ld bytes failed", bi_nbin_size( zeta)); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_2_nbin1( &(daaSignature->zetaLength), daaSignature->zeta, zeta); + daaSignature->capitalT = (BYTE *)calloc_tspi( tcsContext, bi_nbin_size( capital_T)); + if (daaSignature->capitalT == NULL) { + LogError("malloc of %ld bytes failed", bi_nbin_size( capital_T)); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_2_nbin1( &(daaSignature->capitalTLength), daaSignature->capitalT, capital_T); + daaSignature->challenge = (BYTE *)calloc_tspi( tcsContext, c_bytesLength); + if (daaSignature->challenge == NULL) { + LogError("malloc of %d bytes failed", c_bytesLength); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + daaSignature->challengeLength = c_bytesLength; + memcpy( daaSignature->challenge, c_bytes, c_bytesLength); + daaSignature->nonceTpm = (BYTE *)calloc_tspi( tcsContext, nonce_tpmLength); + if (daaSignature->nonceTpm == NULL) { + LogError("malloc of %d bytes failed", nonce_tpmLength); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + daaSignature->nonceTpmLength = nonce_tpmLength; + memcpy( daaSignature->nonceTpm, nonce_tpm, nonce_tpmLength); + daaSignature->sV = (BYTE *)calloc_tspi( tcsContext, bi_nbin_size( s_V)); + if (daaSignature->sV == NULL) { + LogError("malloc of %ld bytes failed", bi_nbin_size( s_V)); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_2_nbin1( &(daaSignature->sVLength), daaSignature->sV, s_V); + daaSignature->sF0 = (BYTE *)calloc_tspi( tcsContext, bi_nbin_size( sF0)); + if (daaSignature->sF0 == NULL) { + LogError("malloc of %ld bytes failed", bi_nbin_size( sF0)); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_2_nbin1( &(daaSignature->sF0Length), daaSignature->sF0, sF0); + daaSignature->sF1 = (BYTE *)calloc_tspi( tcsContext, bi_nbin_size( sF1)); + if (daaSignature->sF1 == NULL) { + LogError("malloc of %ld bytes failed", bi_nbin_size( sF1)); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_2_nbin1( &(daaSignature->sF1Length), daaSignature->sF1, sF1); + daaSignature->sE = (BYTE *)calloc_tspi( tcsContext, bi_nbin_size( s_E)); + if (daaSignature->sE == NULL) { + LogError("malloc of %ld bytes failed", bi_nbin_size( s_E)); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_2_nbin1( &(daaSignature->sELength), daaSignature->sE, s_E); + daaSignature->sALength = revealAttributes.indicesListLength; + daaSignature->sA = (BYTE **)calloc_tspi( + tcsContext, + sizeof(BYTE *)*revealAttributes.indicesListLength); + if (daaSignature->sA == NULL) { + LogError("malloc of %d bytes failed", + sizeof(BYTE *)*revealAttributes.indicesListLength); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + length = (DAA_PARAM_SIZE_RANDOMIZED_ATTRIBUTES + 7) / 8; + for( i=0; i<(int)revealAttributes.indicesListLength; i++) { + daaSignature->sA[i] = calloc_tspi( tcsContext, length); + if (daaSignature->sA[i] == NULL) { + LogError("malloc of %d bytes failed", length); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + if( s_A->array[i] == NULL) + bi_2_byte_array( daaSignature->sA[i], length, bi_0); + else { + bi_2_byte_array( daaSignature->sA[i], length, s_A->array[i]); + LogDebug("size big_integer s_A[i] = %ld size daaSignature->sA[i]=%d", + bi_nbin_size( s_A->array[i]), length); + } + } + daaSignature->attributeCommitmentsLength = 0; + daaSignature->signedPseudonym = signature_pseudonym; +close: + bi_free_ptr( tmp1); + if( c_bytes != NULL) free( c_bytes); + if( ch != NULL) free( ch); + if( nonce_tpm != NULL) free( nonce_tpm); + if( encryption_result !=NULL) free( encryption_result); + if( encryption_result_tilde !=NULL) free( encryption_result_tilde); + if( issuer_settings != NULL) free( issuer_settings); + if( r_A != NULL) { + for( i=0; i<(int)revealAttributes.indicesListLength; i++) + if( r_A->array[i] != NULL) bi_free_ptr( r_A->array[i]); + free( r_A); + } + FREE_BI( s_V); + FREE_BI( s_E); + FREE_BI( e); + FREE_BI( sV2); + FREE_BI( sV1); + FREE_BI( sF1); + FREE_BI( sF0); + FREE_BI( c); + FREE_BI( product_R); + FREE_BI( capital_A); + FREE_BI( capital_T_tilde); + FREE_BI( r_V); + FREE_BI( r_E); + FREE_BI( capital_T); + FREE_BI( w); + FREE_BI( capital_N_tilde_v); + FREE_BI( capital_Nv); + FREE_BI( t_tilde_T); + FREE_BI( n); + FREE_BI( capital_gamma); + FREE_BI( gamma); + FREE_BI( zeta); + FREE_BI( r); + free_TSS_DAA_PK_internal( pk_intern); + free_TPM_DAA_ISSUER( tpm_daa_issuer); + return result; +} diff --git a/src/tspi/daa/daa_platform/test.c b/src/tspi/daa/daa_platform/test.c new file mode 100644 index 0000000..04fdd38 --- /dev/null +++ b/src/tspi/daa/daa_platform/test.c @@ -0,0 +1,142 @@ + +#include <stdlib.h> +#include <string.h> +#include <trousers/tss.h> +#include <trousers/trousers.h> +#include "spi_internal_types.h" +#include <spi_utils.h> +#include <obj.h> +#include "tsplog.h" +#include "daa_parameter.h" + +setenv("TCSD_FOREGROUND", "1", 1); + +// simulating Tspi_TPM_DAA_JoinInit (spi_daa.c) +TSS_RESULT Tspi_DAA_Join(TSS_HTPM hTPM, int stage, UINT32 inputSize0, BYTE *inputData0, UINT32 inputSize1, BYTE *inputData1, UINT32 *outputSize, BYTE **outputData) { + TSS_RESULT result; + TCS_CONTEXT_HANDLE tcsContext; + TSS_HCONTEXT tspContext; + TSS_HPOLICY hPolicy; + TCPA_DIGEST digest; + TPM_AUTH ownerAuth; + UINT16 offset = 0; + BYTE hashblob[1000]; + + printf("[%s:%d] obj_tpm_is_connected(hTPM)\n", __FILE__, __LINE__); + if( (result = obj_tpm_is_connected( hTPM, &tcsContext)) != TSS_SUCCESS) return result; + printf("[%s:%d] obj_tpm_get_tsp_context(hTPM)\n", __FILE__, __LINE__); + if( (result = obj_tpm_get_tsp_context( hTPM, &tspContext)) != TSS_SUCCESS) return result; + printf("[%s:%d] obj_tpm_get_policy(hTPM)\n", __FILE__, __LINE__); + if( (result = obj_tpm_get_policy( hTPM, &hPolicy)) != TSS_SUCCESS) return result; + + printf("[%s:%d] Trspi_LoadBlob_UINT32(&offset, TPM_ORD_DAA_Join, hashblob)\n", __FILE__, __LINE__); + Trspi_LoadBlob_UINT32(&offset, TPM_ORD_DAA_Join, hashblob); // hash TPM_COMMAND_CODE + printf("[%s:%d] Trspi_Hash(TSS_HASH_SHA1, offset, hashblob, digest.digest)\n",__FILE__, __LINE__); + Trspi_LoadBlob_BYTE(&offset, stage, hashblob); // hash stage + printf("[%s:%d] Trspi_LoadBlob_UINT32(&offset, 0, hashblob)\n",__FILE__, __LINE__); + //TODO old 4 + Trspi_LoadBlob_UINT32(&offset, inputSize0, hashblob); // hash inputSize0 + printf("[%s:%d] Trspi_LoadBlob_UINT32(&offset, 0, hashblob)\n",__FILE__, __LINE__); + Trspi_LoadBlob( &offset, inputSize0, hashblob, inputData0); // hash inputData0 + //TODO old 1 + Trspi_LoadBlob_UINT32(&offset, inputSize1, hashblob); // hash inputSize1 + printf("[%s:%d] Trspi_LoadBlob_UINT32(&offset, 0, hashblob)\n",__FILE__, __LINE__); + Trspi_LoadBlob( &offset, inputSize1, hashblob, inputData1); // hash inputData1 + Trspi_Hash(TSS_HASH_SHA1, offset, hashblob, digest.digest); + + if ((result = secret_PerformAuth_OIAP(hTPM, TPM_ORD_DAA_Join, + hPolicy, &digest, + &ownerAuth)) != TSS_SUCCESS) return result; + printf("[%s:%d] secret_PerformAuth_OIAP(hTPM, TPM_ORD_DAA_Join ret=%d\n",__FILE__, __LINE__, result); + // out + + /* step of the following call: + TCSP_DAAJoin tcsd_api/calltcsapi.c (define in spi_utils.h) + TCSP_DAAJoin_TP tcsd_api/tcstp.c (define in trctp.h) + */ + + printf("[%s:%d] TCSP_DAAJoin(%x,%x,%x,%x,%x,%x,%x)\n",__FILE__, __LINE__, + (int)hTPM, 0, inputSize0,(int)inputData0,inputSize1,(int)inputData1,(int)&ownerAuth); + if ( (result = TCSP_DaaJoin( tcsContext, hTPM, 0, inputSize0, inputData0, inputSize1, inputData1, &ownerAuth, outputSize, outputData)) != TSS_SUCCESS) + return result; + + offset = 0; + Trspi_LoadBlob_UINT32(&offset, result, hashblob); + Trspi_LoadBlob_UINT32(&offset, TPM_ORD_DAA_Join, hashblob); + Trspi_LoadBlob_UINT32(&offset, *outputSize, hashblob); + Trspi_LoadBlob(&offset, *outputSize, hashblob, *outputData); + Trspi_Hash(TSS_HASH_SHA1, offset, hashblob, digest.digest); + if( (result = obj_policy_validate_auth_oiap( hPolicy, &digest, &ownerAuth))) + { + printf("[%s:%d] obj_policy_validate_auth=%d\n",__FILE__, __LINE__, result); + } + return result; +} + + +int main(int argc, char *argv[]) +{ + TSS_HCONTEXT hContext; + TSS_RESULT result; + TSS_HTPM hTPM; + TSS_HPOLICY hPolicy; + + // Create Context + printf("Create Context\n"); + result = Tspi_Context_Create( &hContext ); + if ( result != TSS_SUCCESS ) + { + fprintf( stderr, "Tspi_Context_Create %d\n", result ); + exit( result ); + } + + // Connect to Context + printf("\nConnect to the context\n"); + result = Tspi_Context_Connect( hContext, NULL ); + if ( result != TSS_SUCCESS ) goto out_close; + + if( (result = Tspi_Context_GetTpmObject( hContext, &hTPM)) != TSS_SUCCESS) + goto out_close; + + // Get the correct policy using the TPM ownership PASSWD + char *szTpmPasswd = "OWN_PWD"; + if( (result = Tspi_GetPolicyObject( hTPM, TSS_POLICY_USAGE, &hPolicy)) != TSS_SUCCESS) + goto out_close; + //BUSS + if( (result = Tspi_Policy_SetSecret( hPolicy, TSS_SECRET_MODE_PLAIN, strlen( szTpmPasswd), szTpmPasswd)) != TSS_SUCCESS) + goto out_close; + printf("Tspi_Policy_SetSecret hPolicy received;%d\n", hPolicy); + + //BUSS + // in + //int modulus_length = DAA_PARAM_SIZE_MODULUS_GAMMA / 8; + UINT32 inputSize0 = sizeof(int); + UINT32 inputSize1 = 0; + UINT32 outputSize = 0; + int ia_length = 7; + BYTE *inputData0 = (BYTE *)(&ia_length);//= (BYTE *)malloc( inputSize0) + BYTE *inputData1 = NULL; + BYTE *outputData = NULL; + + if( (result = Tspi_DAA_Join(hTPM, 0, inputSize0, inputData0, inputSize1, inputData1, &outputSize, &outputData)) != TSS_SUCCESS) goto out_close; + + goto out; +out_close: + printf( "Tspi Error:%d - %s\n", result, err_string( result) ); + +out: + printf("ouputSize=%d\n", outputSize); + if( outputData != NULL) { + int i; + printf("outputData(hex )=[\n"); + for( i=0; i<(int)outputSize; i++) printf("%x ", outputData[i]); + printf("\n]"); + printf("outputData(ascii)=[\n"); + for( i=0; i<(int)outputSize; i++) printf("%c ", outputData[i]); + printf("\n]"); + } + Tspi_Context_FreeMemory( hContext, NULL ); + Tspi_Context_Close( hContext ); + printf("[%s:%d] THE END\n",__FILE__, __LINE__); + return result; +} diff --git a/src/tspi/daa/daa_platform/test_join.c b/src/tspi/daa/daa_platform/test_join.c new file mode 100644 index 0000000..a244d85 --- /dev/null +++ b/src/tspi/daa/daa_platform/test_join.c @@ -0,0 +1,504 @@ + +/* + * Licensed Materials - Property of IBM + * + * trousers - An open source TCG Software Stack + * + * (C) Copyright International Business Machines Corp. 2006 + * + */ + +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include "daa_structs.h" +#include "trousers/tss.h" +#include "trousers/trousers.h" +#include "spi_internal_types.h" +#include "spi_utils.h" +#include "obj.h" +#include "tsplog.h" +#include "daa_parameter.h" +#include "verifier.h" +#include "platform.h" + +// for RSA Key +#include <openssl/rsa.h> + +#define DEFAULT_FILENAME "issuer.txt" +#define DEFAULT_CREDENTIAL_FILENAME "credential.txt" +#define DEFAULT_DAACOUNTER 0x01020304 +#define DEFAULT_OWN_PASSWD "OWN_PWD" + +// from IssuerFactory +static const int DEFAULT_KEY_CHAIN_LENGTH = 3; + +typedef struct tdIssuer { + // use on Tspi calls + TSS_DAA_PK *pk_extern; + TSS_DAA_KEY_PAIR *key_pair_extern; + + // used internally + int length_key_chain; + RSA **key_chain; + TSS_DAA_PK_internal *pk; + DAA_PRIVATE_KEY_internal *private_key; + TSS_DAA_PK_PROOF_internal *pk_proof; + //RSA **auth_key_pairs; + BYTE **pk_signatures; + bi_ptr zeta; +} Issuer; + +void *alloc( UINT32 length, TCS_CONTEXT_HANDLE tcsContext) { + void *result = calloc_tspi( tcsContext, length); + LogDebug("allocate tspi memory:%d", (int)result); + return result; +} + +/** +Used by RSA_generate_key +From RSA_generate_key documentation: +-> callback(2, n, cb_arg) is called when n-th randomly generated prime is rejected +-> callback(3, 0, cb_arg) is called when p is found with p-1 more or less prime to e +-> callback(3, 1, cb_arg) repeatedly called for prime q +*/ +void callback(int step, int number, void *arg) { +#ifdef DAA_DEBUG + putc( '.', stdout); fflush( stdout); +#endif +} + +int sign( BYTE *buffer_2_sign, + int len_buffer_2_sign, + RSA *rsa, + BYTE *signature, + int *len_signature +) { + EVP_MD_CTX ctx; + int len_message = EVP_MD_size( EVP_sha1()), current_len_message; + BYTE *message = (BYTE *)malloc( len_message); + int ret; + + EVP_MD_CTX_init(&ctx); + EVP_DigestInit_ex(&ctx, EVP_sha1(), NULL); + EVP_DigestUpdate(&ctx, buffer_2_sign, len_buffer_2_sign); + EVP_DigestFinal_ex(&ctx, message, ¤t_len_message); + LogDebug("Sign rsa-> with message (length=%d)", current_len_message); +// int RSA_sign(int type, unsigned char *m, unsigned int m_len, +// unsigned char *sigret, unsigned int *siglen, RSA *rsa); + ret = RSA_sign( NID_sha1, message, current_len_message, signature, len_signature, rsa); + if( ret == 0) { + LogError("Error in RSA_sign: %s", ERR_error_string( ERR_get_error(), NULL)); + } + LogDebug("Sign rsa-> signature (length=%d)", *len_signature ); + EVP_MD_CTX_cleanup(&ctx); + free( message); + return ret; +} + +/* Compute key chain. */ +static int init_key_chain(int length_key_chain, Issuer *issuer) { + BYTE *signature; + int i, len_sign, ret; + BYTE *modulus; + BYTE *message; + // generate RSA key of length DAA_PARAM_KEY_SIZE with exponent + // 65537 (java.security.spec.RSAKeyGenParameterSpec.F4) + unsigned long e = 65537; + RSA *rsa; + bi_ptr bi; + EVP_MD_CTX ctx; + int len_message = EVP_MD_size( EVP_sha1()); + int current_len_message; + + EVP_MD_CTX_init(&ctx); + message = (BYTE *)malloc(len_message); + if( length_key_chain < 1) { + free( message); + return -1; + } + issuer->length_key_chain = length_key_chain; + issuer->key_chain = (RSA **)malloc(sizeof(RSA *) * length_key_chain); + issuer->pk_signatures = (BYTE **)malloc(sizeof(BYTE *) * length_key_chain); + for(i = 0; i<length_key_chain; i++) { + rsa = RSA_generate_key( DAA_PARAM_KEY_SIZE, e, &callback, NULL); + if( (BN_num_bits(rsa->n) + 7) / 8 != (DAA_PARAM_KEY_SIZE + 7) / 8) { + LogError("BN_num_bits(rsa->n) + 7) / 8 != (DAA_PARAM_KEY_SIZE + 7) / 8)"); + return -1; + } + issuer->key_chain[i] = rsa; + if( i > 0) { + signature = (BYTE *)malloc( RSA_size(rsa)); + modulus = (BYTE *)malloc( DAA_PARAM_KEY_SIZE / 8); + // signature algorithm from Issuer.java - "SHA1withRSA" + // sign the modulus (n) of the RSA key with the previous RSA key (chain) + // sign rsa(i)->n with auth_key_pairs[i-1] + LogDebug("modulus=%s\n", dump_byte_array(256, modulus)); + LogDebug("signature=%s\n", dump_byte_array(256, signature)); + bi = bi_new_ptr(); + bi_set_as_hex( bi, BN_bn2hex( rsa->n)); + bi_2_byte_array( modulus, DAA_PARAM_KEY_SIZE / 8, bi); + LogDebug("bi=%s", bi_2_hex_char( bi)); + bi_free_ptr( bi); + EVP_DigestInit_ex(&ctx, EVP_sha1(), NULL); + EVP_DigestUpdate(&ctx, modulus, DAA_PARAM_KEY_SIZE / 8); + EVP_DigestFinal_ex(&ctx, message, ¤t_len_message); + ret = RSA_sign( NID_sha1, message, current_len_message, + signature, &len_sign, issuer->key_chain[i-1]); + if( ret == 0) { + LogError("Error in RSA_sign: %s", + ERR_error_string( ERR_get_error(), NULL)); + } + LogDebug("Sign rsa->n (length=%d) with signature (length=%d,\ + truelength=%d message_len=%d) ret = %d ERROR?=%s", + RSA_size(rsa), + DAA_PARAM_KEY_SIZE / 8, + len_sign, + current_len_message, + ret, + ERR_error_string( ERR_get_error(), + NULL) ); + LogDebug("message=%s\n", dump_byte_array(256, message)); + LogDebug("signature=%s\n",dump_byte_array(256, signature)); + issuer->pk_signatures[i-1] = signature; + } + } + free( message); + EVP_MD_CTX_cleanup(&ctx); + return 0; +} + +Issuer* initIssuer(int length_key_chain, char *filename, char *exec, TSS_HCONTEXT hContext) { + FILE *file; + EVP_MD_CTX mdctx; + Issuer *issuer = (Issuer *)malloc(sizeof( Issuer)); + TPM_DAA_ISSUER *tpm_daa_issuer; + bi_ptr modulus_N0; + int len_issuer_settings, len_signature; + BYTE *modulus_N0_bytes; + BYTE *digest_n0; + BYTE *issuer_settings_byte_array; + BYTE *sign_data; + BYTE *signature; + RSA *private_nn; + KEY_PAIR_WITH_PROOF_internal *key_pair_with_proof; + + LogDebug("Loading issuer info (keypair & proof) -> \'%s\'", filename); + file = fopen( filename, "r"); + if( file == NULL) { + fprintf( stderr, "%s: Error when opening \'%s\': %s\n", + exec, + filename, + strerror( errno)); + free( issuer); + return NULL; + } + key_pair_with_proof = load_KEY_PAIR_WITH_PROOF( file); + if( key_pair_with_proof == NULL) { + LogError( "Error when reading \'%s\': %s\n", filename, strerror( errno)); + free( issuer); + return NULL; + } + fclose( file); + issuer->pk = key_pair_with_proof->pk; + issuer->pk_extern = i_2_e_TSS_DAA_PK( issuer->pk, &alloc, hContext); + issuer->key_pair_extern = (TSS_DAA_KEY_PAIR *)malloc( sizeof(TSS_DAA_KEY_PAIR)); + init_tss_version( issuer->key_pair_extern); + issuer->key_pair_extern->public_key = issuer->pk_extern; + issuer->key_pair_extern->private_key = i_2_e_TSS_DAA_PRIVATE_KEY( + key_pair_with_proof->private_key, + &alloc, hContext); + issuer->pk_proof = key_pair_with_proof->proof; + issuer->private_key = key_pair_with_proof->private_key; + init_key_chain( length_key_chain, issuer); + issuer->zeta = compute_zeta( issuer->pk->issuerBaseNameLength, + issuer->pk->issuerBaseName, issuer->pk); + // sign "issuer settings" + modulus_N0 = bi_new_ptr(); + bi_set_as_hex( modulus_N0, BN_bn2hex( issuer->key_chain[0]->n)); + // in TPM, N0 is hashed by hashing the scratch (256 bytes) so it must + // be formatted according to the scratch size (TPM_DAA_SIZE_issuerModulus) + modulus_N0_bytes = (BYTE *)malloc( TPM_DAA_SIZE_issuerModulus); + bi_2_byte_array( modulus_N0_bytes, TPM_DAA_SIZE_issuerModulus, modulus_N0); + bi_free_ptr( modulus_N0); + + if( TPM_DAA_SIZE_issuerModulus * 8 != DAA_PARAM_KEY_SIZE) { + LogError("TPM_DAA_SIZE_issuerModulus * 8 (%d) != DAA_PARAM_KEY_SIZE(%d)", + TPM_DAA_SIZE_issuerModulus*8, + DAA_PARAM_KEY_SIZE); + free( issuer); + return NULL; + } + + EVP_MD_CTX_init(&mdctx); + EVP_DigestInit_ex(&mdctx, DAA_PARAM_get_message_digest(), NULL); + // digestN0 = hash( modulus_N0) + EVP_DigestUpdate(&mdctx, modulus_N0_bytes, TPM_DAA_SIZE_issuerModulus); + digest_n0 = (BYTE *)malloc( EVP_MD_CTX_size(&mdctx)); + EVP_DigestFinal_ex(&mdctx, digest_n0, NULL); + tpm_daa_issuer = convert2issuer_settings( issuer->pk); + issuer_settings_byte_array = issuer_2_byte_array( tpm_daa_issuer, &len_issuer_settings); + // data to sign: concatenation of digest_n0 and issuer_settings_byte_array + sign_data = (BYTE *)malloc( EVP_MD_CTX_size(&mdctx) + len_issuer_settings); + memcpy( sign_data, digest_n0, EVP_MD_CTX_size(&mdctx)); + memcpy( &sign_data[EVP_MD_CTX_size(&mdctx)], + issuer_settings_byte_array, + len_issuer_settings); + free( issuer_settings_byte_array); + // sign digest of TPM compatible Issuer key (sign_data) + private_nn = issuer->key_chain[issuer->length_key_chain - 1]; + signature = (BYTE *)malloc( RSA_size(private_nn)); + if ( sign( sign_data, EVP_MD_CTX_size(&mdctx) + len_issuer_settings, + private_nn, + signature, + &len_signature) ==0) { + LogError("Can not sign digest of TPM compatible Issuer key"); + goto close; + } + issuer->pk_signatures[ issuer->length_key_chain - 1] = signature; + LogDebug("Set last signature sign[%d] = %s", + issuer->length_key_chain - 1, + dump_byte_array(EVP_MD_size( EVP_sha1()), + signature)); + // TODO sign the complete public key of TPM compatible Issuer key +/* EVP_DigestInit_ex(&mdctx, DAA_PARAM_get_message_digest(), NULL); + EVP_DigestUpdate(&mdctx, digest_n0, EVP_MD_CTX_size(&mdctx)); + pk_encoded = encoded_DAA_PK_internal( &pk_encodedLength, issuer->pk); + EVP_DigestUpdate(&mdctx, pk_encoded, pk_encodedLength); + EVP_DigestFinal(&mdctx, , NULL); + signature = (BYTE *)malloc( EVP_MD_size( EVP_sha1())); + if (sign( sign_data, EVP_MD_CTX_size(&mdctx) + len_issuer_settings, + private_nn, signature, &len_signature) !=0) goto close; +*/ +close: + free( digest_n0); + free( sign_data); + return issuer; +} + +int print_usage(char *exec) { + fprintf(stderr, "usage: %s\n", exec); + fprintf(stderr, "\t-if,\t--issuer_file\n\t\tthe file that will contain all key\ +pair and proof to be used by the issuer\n\t\t (default: %s)\n", + DEFAULT_FILENAME); + fprintf(stderr, "\t-dc,\t--daa_counter\n\t\tdaa counter (default: %d)\n", + DEFAULT_DAACOUNTER); + fprintf(stderr, + "\t-pw,\t--passwd\n\t\ttpm owner password (default: %s)\n", + DEFAULT_OWN_PASSWD); + return -1; +} + +int main(int argc, char *argv[]) { + TSS_HCONTEXT hContext; + TSS_RESULT result; + TSS_HTPM hTPM; + TSS_HPOLICY hPolicy; + int i, length; + char *param, *filename = DEFAULT_FILENAME; + char *credential_filename = DEFAULT_CREDENTIAL_FILENAME; + UINT32 daaCounter = DEFAULT_DAACOUNTER; + UINT32 capital_UPrimeLength; + BYTE *capitalUPrime; + TSS_DAA_IDENTITY_PROOF identityProof; + TSS_DAA_JOIN_SESSION joinSession; + TSS_DAA_JOIN_ISSUER_SESSION join_issuer_session; + TSS_DAA_CREDENTIAL_REQUEST credentialRequest; + TSS_DAA_CRED_ISSUER credIssuer; + TSS_HDAA hDAA; + Issuer* issuer; + char *szTpmPasswd = DEFAULT_OWN_PASSWD; + UINT32 endorsementKeyLength; + BYTE *endorsementKey; + UINT32 nonceIssuerLength; + BYTE *nonceIssuer; + UINT32 authenticationChallengeLength; + BYTE *authenticationChallenge; + bi_array_ptr capital_receiver; + BYTE **attributesPlatform; + UINT32 attributesPlatformLength; + BYTE **attributesIssuer; + UINT32 attributesIssuerLength; + bi_t random; + FILE *file; + + init_tss_version( &identityProof); + init_tss_version( &joinSession); + init_tss_version( &join_issuer_session); + init_tss_version( &credentialRequest); + init_tss_version( &credIssuer); + i = 1; + while( i < argc) { + param = argv[ i]; + if ( strcmp( param, "-if") == 0 || strcmp( param, "--issuer_file") == 0) { + i++; + if( i == argc) return print_usage( argv[0]); + filename = argv[i]; + } else if( strcmp( param, "-dc") == 0 || strcmp( param, "--daa_counter") == 0){ + i++; + if( i == argc) return print_usage( argv[0]); + daaCounter = atoi(argv[i]); + } else if( strcmp( param, "-pw") == 0 || strcmp( param, "--passwd") == 0){ + i++; + if( i == argc) return print_usage( argv[0]); + szTpmPasswd = argv[i]; + } else { + fprintf(stderr, "\n%s:unrecognized option <%s>\n", argv[0], param); + return print_usage( argv[0]); + } + i++; + } + bi_init( NULL); + + // Create Context + LogDebug("Create Context"); + result = Tspi_Context_Create( &hContext ); + if ( result != TSS_SUCCESS ) + { + LogError( "Tspi_Context_Create %d\n", result ); + goto out; + } + // Connect to Context + result = Tspi_Context_Connect( hContext, NULL ); + if ( result != TSS_SUCCESS) goto out_close; + printf("\nConnect to the context: %X\n", hContext); + + if( (result = Tspi_Context_GetTpmObject( hContext, &hTPM)) != TSS_SUCCESS) + goto out_close; + // Get the correct policy using the TPM ownership PASSWD + if( (result = Tspi_GetPolicyObject( hTPM, + TSS_POLICY_USAGE, + &hPolicy)) != TSS_SUCCESS) + goto out_close; + if( (result = Tspi_Policy_SetSecret( hPolicy, + TSS_SECRET_MODE_PLAIN, + strlen( szTpmPasswd), + szTpmPasswd)) != TSS_SUCCESS) + goto out_close; + LogDebug("Tspi_Policy_SetSecret hPolicy received;%d\n", hPolicy); + + //Create Object + result = obj_daa_add( hContext, &hDAA); + if (result != TSS_SUCCESS) { + LogError("Tspi_Context_CreateObject:%d\n", result); + Tspi_Context_Close(hContext); + LogError("%s: %s\n", argv[0], err_string(result)); + exit(result); + } + LogDebug("created DAA object:%X", hDAA); + issuer = initIssuer( DEFAULT_KEY_CHAIN_LENGTH, filename, argv[0], hContext); + if( issuer == NULL) goto out_close; + + // generate receiver attributes and issuer attributes (random) + attributesPlatformLength = issuer->pk->capitalRReceiver->length; + attributesPlatform = (BYTE **)malloc( attributesPlatformLength * sizeof(BYTE *)); + bi_new( random); + for( i=0; i<(int)attributesPlatformLength; i++) { + bi_urandom( random, DAA_PARAM_SIZE_F_I); + attributesPlatform[i] = bi_2_nbin( &length, random); + if( attributesPlatform[i] == NULL) { + LogError("malloc of %d bytes failed", length); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto out_close; + } + } + attributesIssuerLength = issuer->pk->capitalRIssuer->length; + attributesIssuer = (BYTE **)malloc( attributesIssuerLength * sizeof(BYTE *)); + for( i=0; i<(int)attributesIssuerLength; i++) { + bi_urandom( random, DAA_PARAM_SIZE_F_I); + attributesIssuer[i] = bi_2_nbin( &length, random); + if( attributesIssuer[i] == NULL) { + LogError("malloc of %d bytes failed", length); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto out_close; + } + } + bi_free(random); + LogDebug("Generated attributes (Platform=%d,Issuer=%d)", + attributesPlatformLength, attributesIssuerLength); + + result = Tspi_TPM_DAA_JoinInit( + hDAA, // in + hTPM, // in + daaCounter, // in + (TSS_HKEY)issuer->pk_extern, // in + issuer->length_key_chain, // in + (TSS_HKEY *)issuer->key_chain, // in + issuer->length_key_chain, // in + issuer->pk_signatures, // in + &capital_UPrimeLength, // out + &capitalUPrime, // out + &identityProof, // out + &joinSession // out + ); + if( result != TSS_SUCCESS) goto out_close; + + result = Tspi_DAA_IssueInit( + hDAA, // in + (TSS_HKEY)issuer->key_chain[0], // in + (TSS_HKEY)issuer->key_pair_extern, // in + identityProof, // in + capital_UPrimeLength, // in + capitalUPrime, // in + daaCounter, // in + &nonceIssuerLength, // out + &nonceIssuer, // out + &authenticationChallengeLength, // out + &authenticationChallenge, // out + &join_issuer_session // out + ); + if( result != TSS_SUCCESS) goto out_close; + + result = Tspi_TPM_DAA_JoinCreateDaaPubKey( + hDAA, // in + hTPM, // in + authenticationChallengeLength, // in + authenticationChallenge, // in + nonceIssuerLength, // in + nonceIssuer, // in + attributesPlatformLength, // in + attributesPlatform, // in + &joinSession, // in & out + &credentialRequest // out + ); + if( result != TSS_SUCCESS) goto out_close; + + result = Tspi_DAA_IssueCredential( + hDAA, // in + attributesIssuerLength, // in + attributesIssuer, // in + credentialRequest, // in + join_issuer_session, // in + &credIssuer // out + ); + + result = Tspi_TPM_DAA_JoinStoreCredential( + hDAA, // in + hTPM, // in + credIssuer, // in + joinSession, // in + (TSS_HKEY*)&credentialRequest // out + ); + if( result != TSS_SUCCESS) goto out_close; + + printf("Saving credential: %s ", credential_filename); + file = fopen( credential_filename, "w"); + if( save_TSS_DAA_CREDENTIAL( file, &credentialRequest) != 0) { + LogError( "[test_join]: Error when saving \'%s\': %s", + credential_filename, + strerror( errno)); + result = TSS_E_FAIL; + goto out_close; + } + fclose( file); + printf("Done\n"); + +out_close: + Tspi_Context_FreeMemory( hContext, NULL ); + Tspi_Context_Close( hContext ); +out: + bi_release(); + LogDebug("THE END result=%d:%s",result, err_string( result) );; + return result; +} diff --git a/src/tspi/daa/daa_structs.c b/src/tspi/daa/daa_structs.c new file mode 100644 index 0000000..787d5d0 --- /dev/null +++ b/src/tspi/daa/daa_structs.c @@ -0,0 +1,1317 @@ + +/* +* Licensed Materials - Property of IBM +* +* trousers - An open source TCG Software Stack +* +* (C) Copyright International Business Machines Corp. 2006 +* +*/ + +/* +This file implements Helper functions for converting / creating and freeing +internal representation of TSS_DAA structures. +An external representation is the one define in tss_structs.h. +An internal representation is using bi_t or bi_ptr for representing big numbers. +Naming convention: for each structures we can have: +init_(<STRUCT>, struct *) : initialize the version field +create_<STRUCT> : init all fields +free_<STRUCT> : free all fields +e_2_i_<STRUCT> : convertor from External representation to internal +i_2_e_<STRUCT> : convertor from Internal to External. This call use a given memory +allocation function, to allow +for example to use calloc_tspi, or a "normal" malloc. +*/ +#include <stdio.h> +#include <strings.h> +#include <errno.h> +#include <strings.h> + +#include "daa_parameter.h" +#include "daa_structs.h" +#include "tcslog.h" + +#define DUMP_DAA_PK_FIELD( field) \ +do { \ + printf("%s=", #field); \ + dump_field( pk->field##Length, pk->field); \ + puts(""); \ +} while(0); + +#if 0 +#define STORE_DAA_PK_BI1( field, bi) \ +do { \ + store_bi( &pk->field##Length, &pk->field, bi); \ +} while(0); + +#define STORE_DAA_PK_BI( field, daa_alloc, param_alloc) \ +do { \ + store_bi( &pk->field##Length,\ + &pk->field,\ + pk_internal->field,\ + daa_alloc,\ + param_alloc); \ +} while(0); + +// used only to read a structure from a file, so only as helping function +// for TCG application +static char buffer[1000]; +#endif +BYTE *convert_alloc( TCS_CONTEXT_HANDLE tcsContext, UINT32 length, BYTE *source) { + BYTE *result = calloc_tspi( tcsContext, length); + + if( result == NULL) return NULL; + memcpy( result, source, length); + free( source); + return result; +} + +BYTE *copy_alloc( TCS_CONTEXT_HANDLE tcsContext, UINT32 length, BYTE *source) { + BYTE *result = calloc_tspi( tcsContext, length); + + if( result == NULL) return NULL; + memcpy( result, source, length); + return result; +} + +static void *normal_malloc( size_t size, TSS_HOBJECT object) { + void *ret = malloc( size); + return ret; +} + +/* store a bi to a buffer and update the length in big endian format */ +void store_bi( UINT32 *length, + BYTE **buffer, + const bi_ptr i, + void * (*daa_alloc)(size_t size, TSS_HOBJECT object), + TSS_HOBJECT object +) { + int size; + + *buffer = (BYTE *)daa_alloc( bi_length( i), object); + bi_2_nbin1( &size, *buffer, i); + *length = size; + LogDebug( "[store_bi] host_length:%d network_length:%d[address:%d]\n", + size, + (int)*length, + (int)*buffer); +} + +bi_ptr get_bi( const unsigned long n_length, const BYTE *buffer) { + unsigned long length; + + length = n_length; + LogDebug( "[get_bi] %d [address:%d -> |%2x|%2x| ]\n", + (int)length, + (int)buffer, + (int)(buffer[0] &0xFF), + (int)(buffer[1]&0xFF)); + return bi_set_as_nbin( length, buffer); +} + +/* length is in network format: big indian */ +void dump_field( int length, BYTE *buffer) { + int i; + + for( i=0; i< length; i++) { + BYTE byte = (BYTE)(buffer[i] & 0xFF); + printf("%02X", byte); + } +} + +#if 0 +/* !: do not keep the return buffer */ +char *read_str(FILE *file) { + int i; + char c; + + fgets( buffer, 1000, file); + i=0; + while( buffer[i] =='\n' || buffer[i]=='\r' || buffer[i]==' ') i++; + do { + c = buffer[ i++]; + } while( c != 0 && c != ' ' && c!='\n' && c!='\r' && c!='#'); + buffer[ i -1] = 0; + return buffer; +} + +/** + * + * @param file + * @return + */ +int read_int( FILE *file) { + int i, ret; + char c; + + fgets( buffer, 1000, file); + i=0; + while( buffer[i] =='\n' || buffer[i]=='\r' || buffer[i]==' ') i++; + do { + c = buffer[ i++]; + } while( c != 0 && c != ' ' && c!='\n' && c!='\r' && c!='#'); + buffer[ i -1] = 0; + sscanf( buffer, "%d", &ret); + return ret; +} +#endif +/******************************************************************************************** +* TSS_DAA_SELECTED_ATTRIB +* this struct is used internally and externally, only a call to +internal_2_DAA_SELECTED_ATTRIB +* and DAA_SELECTED_ATTRIB_2_internal will change the struct to be internal or +external +********************************************************************************************/ + +void i_2_e_TSS_DAA_SELECTED_ATTRIB( + TSS_DAA_SELECTED_ATTRIB *selected_attrib +) { +} + +void e_2_i_TSS_DAA_SELECTED_ATTRIB( + TSS_DAA_SELECTED_ATTRIB *selected_attrib +) { +} + +/* work ONLY with internal format +important: TSS_BOOL is of type int_8_t, so a char, if the size is bigger, we +will maybe need +to transform each part to big indian ? or maybe each part is false if equal to +0, true otherwise. +*/ +BYTE *to_bytes_TSS_DAA_SELECTED_ATTRIB_internal( + int *result_length, + TSS_DAA_SELECTED_ATTRIB *selected_attrib +) { + BYTE *result; + int index = 0; + unsigned int length = selected_attrib->indicesListLength; + + *result_length = sizeof(unsigned int) + + (selected_attrib->indicesListLength * sizeof(TSS_BOOL)); + result = (BYTE *)malloc( *result_length); + memcpy( &result[index], &length, sizeof(UINT32)); + index+=sizeof(UINT32); + memcpy( &result[index], selected_attrib->indicesList, + sizeof(TSS_BOOL) * selected_attrib->indicesListLength); + return result; +} + +/* +create a TSS_DAA_SELECTED_ATTRIB of length <length> with given selected attributes. +example of selections of the second and third attributes upon 5: +create_TSS_DAA_SELECTED_ATTRIB( &selected_attrib, 5, 0, 1, 1, 0, 0); +*/ +void create_TSS_DAA_SELECTED_ATTRIB( TSS_DAA_SELECTED_ATTRIB *attrib, int length, ...) { + va_list ap; + int i, select; + + attrib->indicesListLength = length; + attrib->indicesList = (TSS_BOOL *)malloc( length * sizeof( TSS_BOOL)); + va_start (ap, length); + for( i=0; i<length; i++) { + select = va_arg( ap, int) != 0; + attrib->indicesList[i] = select; + } + va_end (ap); +} + + +/****************************************************************************************** +* TSS_DAA_SIGN_DATA +* this struct is used internally and externally, only a call to internal_2_DAA_SIGN_DATA +* DAA_SIGN_DATA_2_internal will change the struct to be internal or external +*******************************************************************************************/ + +void i_2_e_TSS_DAA_SIGN_DATA( TSS_DAA_SIGN_DATA *sign_data) { +} + +void e_2_i_TSS_DAA_SIGN( TSS_DAA_SIGN_DATA *sign_data) { +} + +/******************************************************************************************** +* TSS_DAA_ATTRIB_COMMIT +********************************************************************************************/ + +TSS_DAA_ATTRIB_COMMIT_internal *create_TSS_DAA_ATTRIB_COMMIT( bi_ptr beta, bi_ptr sMu) { + TSS_DAA_ATTRIB_COMMIT_internal *result = + (TSS_DAA_ATTRIB_COMMIT_internal *)malloc( sizeof(TSS_DAA_ATTRIB_COMMIT_internal)); + + result->beta = beta; + result->sMu = sMu; + return result; +} + + +/******************************************************************************************** +* TSS_DAA_PSEUDONYM_PLAIN +********************************************************************************************/ + +TSS_DAA_PSEUDONYM_PLAIN_internal * +create_TSS_DAA_PSEUDONYM_PLAIN(bi_ptr nV) +{ + TSS_DAA_PSEUDONYM_PLAIN_internal *result = (TSS_DAA_PSEUDONYM_PLAIN_internal *) + malloc(sizeof(TSS_DAA_PSEUDONYM_PLAIN_internal)); + + result->nV = nV; + return result; +} + +/******************************************************************************************** +* DAA PRIVATE KEY +********************************************************************************************/ +/* +* allocate: ret->p_prime +* ret->q_prime +* ret->productPQprime +*/ +DAA_PRIVATE_KEY_internal * +create_TSS_DAA_PRIVATE_KEY(bi_ptr pPrime, bi_ptr qPrime) +{ + DAA_PRIVATE_KEY_internal *private_key = + (DAA_PRIVATE_KEY_internal *)malloc( sizeof( DAA_PRIVATE_KEY_internal)); + + private_key->p_prime = bi_new_ptr(); bi_set( private_key->p_prime, pPrime); + private_key->q_prime = bi_new_ptr(); bi_set( private_key->q_prime, qPrime); + private_key->productPQprime = bi_new_ptr(); + bi_mul( private_key->productPQprime, pPrime, qPrime); + return private_key; +} + +#if 0 +int +save_DAA_PRIVATE_KEY(FILE *file, const DAA_PRIVATE_KEY_internal *private_key) +{ + BI_SAVE( private_key->p_prime , file); + BI_SAVE( private_key->q_prime , file); + BI_SAVE( private_key->productPQprime, file); + return 0; +} + +DAA_PRIVATE_KEY_internal * +load_DAA_PRIVATE_KEY(FILE *file) +{ + DAA_PRIVATE_KEY_internal *private_key = + (DAA_PRIVATE_KEY_internal *)malloc( sizeof(DAA_PRIVATE_KEY_internal)); + + private_key->p_prime = bi_new_ptr(); + BI_LOAD( private_key->p_prime, file); + private_key->q_prime = bi_new_ptr(); + BI_LOAD( private_key->q_prime, file); + private_key->productPQprime = bi_new_ptr(); + BI_LOAD( private_key->productPQprime, file); + return private_key; +} +#endif +DAA_PRIVATE_KEY_internal *e_2_i_TSS_DAA_PRIVATE_KEY(TSS_DAA_PRIVATE_KEY *private_key) { + DAA_PRIVATE_KEY_internal *private_key_internal; + + LogDebug("-> e_2_i_TSS_DAA_PRIVATE_KEY"); + private_key_internal = + (DAA_PRIVATE_KEY_internal *)malloc( sizeof(DAA_PRIVATE_KEY_internal)); + private_key_internal->p_prime = get_bi( private_key->p_primeLength, private_key->p_prime); + private_key_internal->q_prime = get_bi( private_key->q_primeLength, private_key->q_prime); + private_key_internal->productPQprime = + get_bi( private_key->productPQprimeLength, private_key->productPQprime); + LogDebug("<- e_2_i_TSS_DAA_PRIVATE_KEY"); + return private_key_internal; +} + +TSS_DAA_PRIVATE_KEY * +i_2_e_TSS_DAA_PRIVATE_KEY(DAA_PRIVATE_KEY_internal *private_key_internal, + void * (*daa_alloc)(size_t size, TSS_HOBJECT object), + TSS_HOBJECT param_alloc) +{ + TSS_DAA_PRIVATE_KEY *result; + + LogDebug("-> i_2_e_TSS_DAA_PRIVATE_KEY"); + result = (TSS_DAA_PRIVATE_KEY *)daa_alloc( sizeof(TSS_DAA_PRIVATE_KEY), param_alloc); + init_tss_version( result); + store_bi( &(result->p_primeLength), + &(result->p_prime), + private_key_internal->p_prime, + daa_alloc, + param_alloc); + store_bi( &(result->q_primeLength), + &(result->q_prime), + private_key_internal->q_prime, + daa_alloc, + param_alloc); + store_bi( &(result->productPQprimeLength), + &(result->productPQprime), + private_key_internal->productPQprime, + daa_alloc, + param_alloc); + LogDebug("<- i_2_e_TSS_DAA_PRIVATE_KEY"); + return result; +} + +/******************************************************************************************** +* KEY PAIR WITH PROOF +********************************************************************************************/ + +#if 0 + +/* moved to daa_debug.c */ + +int +save_KEY_PAIR_WITH_PROOF(FILE *file, + KEY_PAIR_WITH_PROOF_internal *key_pair_with_proof) +{ + save_DAA_PK_internal( file, key_pair_with_proof->pk); + save_DAA_PRIVATE_KEY( file, key_pair_with_proof->private_key); + save_DAA_PK_PROOF_internal( file, key_pair_with_proof->proof); + + return 0; +} + +KEY_PAIR_WITH_PROOF_internal * +load_KEY_PAIR_WITH_PROOF(FILE *file) +{ + KEY_PAIR_WITH_PROOF_internal *key_pair_with_proof = + (KEY_PAIR_WITH_PROOF_internal *)malloc(sizeof(KEY_PAIR_WITH_PROOF_internal)); + + key_pair_with_proof->pk = load_DAA_PK_internal(file); + key_pair_with_proof->private_key = load_DAA_PRIVATE_KEY(file); + key_pair_with_proof->proof = load_DAA_PK_PROOF_internal(file); + + return key_pair_with_proof; +} + +#endif +/* allocated using instrumented daa_alloc */ +TSS_DAA_KEY_PAIR *get_TSS_DAA_KEY_PAIR(KEY_PAIR_WITH_PROOF_internal *key_pair_with_proof, + void * (*daa_alloc)(size_t size, TSS_HOBJECT object), + TSS_HOBJECT param_alloc) +{ + TSS_DAA_KEY_PAIR *result; + + LogDebug("-> i_2_e_KEY_PAIR_WITH_PROOF"); + + result = (TSS_DAA_KEY_PAIR *)daa_alloc(sizeof(TSS_DAA_KEY_PAIR), param_alloc); + init_tss_version(result); + result->private_key = i_2_e_TSS_DAA_PRIVATE_KEY(key_pair_with_proof->private_key, + daa_alloc, param_alloc); + result->public_key = i_2_e_TSS_DAA_PK( key_pair_with_proof->pk, daa_alloc, param_alloc); + + LogDebug("<- i_2_e_KEY_PAIR_WITH_PROOF"); + + return result; +} + + +/******************************************************************************************** +* TSS_DAA_PK +********************************************************************************************/ + +/* pk_internal->capitalY must be alocated using ALLOC_BI_ARRAY() */ +void +populate_capitalY(TSS_DAA_PK_internal *pk_internal) +{ + int i; + + bi_new_array(pk_internal->capitalY, + pk_internal->capitalRReceiver->length + pk_internal->capitalRIssuer->length); + + // CAPITAL Y ( capitalRReceiver ) + for (i = 0; i < pk_internal->capitalRReceiver->length; i++) + pk_internal->capitalY->array[i] = pk_internal->capitalRReceiver->array[i]; + // CAPITAL Y ( capitalRIssuer) + for (i = 0; i < pk_internal->capitalRIssuer->length; i++) + pk_internal->capitalY->array[pk_internal->capitalRReceiver->length+i] = + pk_internal->capitalRIssuer->array[i]; +} + +void +compute_capitalSprime(TSS_DAA_PK_internal *pk_internal) +{ + bi_t bi_tmp; + + bi_new(bi_tmp); + pk_internal->capitalSprime = bi_new_ptr(); + bi_shift_left( bi_tmp, bi_1, DAA_PARAM_SIZE_SPLIT_EXPONENT); + bi_mod_exp(pk_internal->capitalSprime, pk_internal->capitalS, bi_tmp, pk_internal->modulus); + bi_free( bi_tmp); +} + +/* +* create anf feel a TSS_DAA_PK_internal structures +* ! this function keep pointer on all parameters +*/ +TSS_DAA_PK_internal * +create_DAA_PK(const bi_ptr modulus, + const bi_ptr capitalS, + const bi_ptr capitalZ, + const bi_ptr capitalR0, + const bi_ptr capitalR1, + const bi_ptr gamma, + const bi_ptr capitalGamma, + const bi_ptr rho, + const bi_array_ptr capitalRReceiver, + const bi_array_ptr capitalRIssuer, + const int issuerBaseNameLength, + BYTE * const issuerBaseName) +{ + TSS_DAA_PK_internal *pk_internal; + + LogDebug("-> create_DAA_PK"); + pk_internal = (TSS_DAA_PK_internal *)malloc(sizeof(TSS_DAA_PK_internal)); + pk_internal->modulus = modulus; + pk_internal->capitalS = capitalS; + pk_internal->capitalZ = capitalZ; + pk_internal->capitalR0 = capitalR0; + pk_internal->capitalR1 = capitalR1; + pk_internal->gamma = gamma; + pk_internal->capitalGamma = capitalGamma; + pk_internal->rho = rho; + pk_internal->capitalRReceiver = capitalRReceiver; + pk_internal->capitalRIssuer = capitalRIssuer; + pk_internal->capitalY = ALLOC_BI_ARRAY(); + populate_capitalY( pk_internal); + pk_internal->issuerBaseNameLength = issuerBaseNameLength; + pk_internal->issuerBaseName = issuerBaseName; + compute_capitalSprime( pk_internal); + + LogDebug("<- create_DAA_PK"); + + return pk_internal; +} + +#if 0 + +/* moved to daa_debug.c */ + +int +save_DAA_PK_internal(FILE *file, const TSS_DAA_PK_internal *pk_internal) +{ + char *buffer; + + LogDebug("-> save_DAA_PK_internal"); + + BI_SAVE( pk_internal->modulus, file); + BI_SAVE( pk_internal->capitalS, file); + BI_SAVE( pk_internal->capitalZ, file); + BI_SAVE( pk_internal->capitalR0, file); + BI_SAVE( pk_internal->capitalR1, file); + BI_SAVE( pk_internal->gamma, file); + BI_SAVE( pk_internal->capitalGamma, file); + BI_SAVE( pk_internal->rho, file); + BI_SAVE_ARRAY( pk_internal->capitalRReceiver, file); + BI_SAVE_ARRAY( pk_internal->capitalRIssuer, file); + fprintf( file, "%d\n", pk_internal->issuerBaseNameLength); + buffer = (char *)malloc( pk_internal->issuerBaseNameLength + 1); + memcpy( buffer, pk_internal->issuerBaseName, pk_internal->issuerBaseNameLength); + buffer[ pk_internal->issuerBaseNameLength] = 0; + fprintf( file, "%s\n", buffer); + free( buffer); + + LogDebug("<- save_DAA_PK_internal"); + + return 0; +} + +TSS_DAA_PK_internal * +load_DAA_PK_internal(FILE *file) +{ + TSS_DAA_PK_internal *pk_internal = + (TSS_DAA_PK_internal *)malloc(sizeof(TSS_DAA_PK_internal)); + char *read_buffer; + + pk_internal->modulus = bi_new_ptr(); + BI_LOAD( pk_internal->modulus, file); + pk_internal->capitalS = bi_new_ptr(); + BI_LOAD( pk_internal->capitalS, file); + pk_internal->capitalZ = bi_new_ptr(); + BI_LOAD( pk_internal->capitalZ, file); + pk_internal->capitalR0 = bi_new_ptr(); + BI_LOAD( pk_internal->capitalR0, file); + pk_internal->capitalR1 = bi_new_ptr(); + BI_LOAD( pk_internal->capitalR1, file); + pk_internal->gamma = bi_new_ptr(); + BI_LOAD( pk_internal->gamma, file); + pk_internal->capitalGamma = bi_new_ptr(); + BI_LOAD( pk_internal->capitalGamma, file); + pk_internal->rho = bi_new_ptr(); + BI_LOAD( pk_internal->rho, file); + pk_internal->capitalRReceiver = ALLOC_BI_ARRAY(); + BI_LOAD_ARRAY( pk_internal->capitalRReceiver, file); + pk_internal->capitalRIssuer = ALLOC_BI_ARRAY(); + BI_LOAD_ARRAY( pk_internal->capitalRIssuer, file); + pk_internal->capitalY = ALLOC_BI_ARRAY(); + populate_capitalY( pk_internal); + pk_internal->issuerBaseNameLength = read_int( file); + read_buffer = read_str( file); + pk_internal->issuerBaseName = malloc( pk_internal->issuerBaseNameLength); + memcpy( pk_internal->issuerBaseName, read_buffer, pk_internal->issuerBaseNameLength); + compute_capitalSprime( pk_internal); + return pk_internal; +} + +#endif +void +dump_DAA_PK_internal(char *name, TSS_DAA_PK_internal *pk_internal) +{ + LogDebug("Dump TSS_DAA_PK_internal:%s\n", name); + + DUMP_BI( pk_internal->modulus); + DUMP_BI( pk_internal->capitalS); + DUMP_BI( pk_internal->capitalZ); + DUMP_BI( pk_internal->capitalR0); + DUMP_BI( pk_internal->capitalR1); + DUMP_BI( pk_internal->gamma); + DUMP_BI( pk_internal->capitalGamma); + DUMP_BI( pk_internal->rho); + DUMP_BI_ARRAY( pk_internal->capitalRReceiver); + DUMP_BI_ARRAY( pk_internal->capitalRIssuer); + + LogDebug("issuerBaseName = %s\n", pk_internal->issuerBaseName); + LogDebug("End Dump TSS_DAA_PK_internal:%s\n", name); +} + +/* +* Encode the DAA_PK like java.security.Key#getEncoded +*/ +BYTE * +encoded_DAA_PK_internal(int *result_length, const TSS_DAA_PK_internal *pk) +{ + int length_issuer_base_name = pk->issuerBaseNameLength; + int total_length = DAA_PARAM_TSS_VERSION_LENGTH + + 5 * ((DAA_PARAM_SIZE_RSA_MODULUS / 8)+ sizeof(int)) + + 2 * ((DAA_PARAM_SIZE_MODULUS_GAMMA / 8)+sizeof(int)) + + 1 * ((DAA_PARAM_SIZE_RHO / 8)+sizeof(int)) + + pk->capitalY->length*(((DAA_PARAM_SIZE_RSA_MODULUS / 8)+sizeof(int))) + + length_issuer_base_name; + BYTE *result = (BYTE *)malloc(total_length); + int i, index = 0, length, big_indian_length; + + if (result == NULL) + return NULL; + + LogDebug("total_length=%d", total_length); + for (index = 0; index < DAA_PARAM_TSS_VERSION_LENGTH; index++) + result[index] = DAA_PARAM_TSS_VERSION[index]; + // n, capitalS, capitalZ, capitalR0, capitalR1 + length = DAA_PARAM_SIZE_RSA_MODULUS / 8; + big_indian_length = length; + memcpy(&result[index], &big_indian_length, sizeof(int)); + index += sizeof(int); + bi_2_byte_array( &result[index], length, pk->modulus); + index += length; + memcpy(&result[index], &big_indian_length, sizeof(int)); + index += sizeof(int); + bi_2_byte_array( &result[index], length, pk->capitalS); + index += length; + memcpy(&result[index], &big_indian_length, sizeof(int)); + index += sizeof(int); + bi_2_byte_array( &result[index], length, pk->capitalZ); + index += length; + memcpy(&result[index], &big_indian_length, sizeof(int)); + index += sizeof(int); + bi_2_byte_array( &result[index], length, pk->capitalR0); + index += length; + memcpy(&result[index], &big_indian_length, sizeof(int)); + index += sizeof(int); + bi_2_byte_array( &result[index], length, pk->capitalR1); + index += length; + // gamma, capitalGamma + length = DAA_PARAM_SIZE_MODULUS_GAMMA / 8; + big_indian_length = length; + memcpy(&result[index], &big_indian_length, sizeof(int)); + index += sizeof(int); + bi_2_byte_array( &result[index], length, pk->gamma); + index += length; + memcpy(&result[index], &big_indian_length, sizeof(int)); + index += sizeof(int); + bi_2_byte_array( &result[index], length, pk->capitalGamma); + index += length; + // rho + length = DAA_PARAM_SIZE_RHO / 8; + big_indian_length = length; + memcpy(&result[index], &big_indian_length, sizeof(int)); + index += sizeof(int); + bi_2_byte_array( &result[index], length, pk->rho); + index += length; + // capitalY + length = DAA_PARAM_SIZE_RSA_MODULUS / 8; + big_indian_length = length; + + for( i=0; i<pk->capitalY->length; i++) { + memcpy( &result[index], &big_indian_length, sizeof(int)); + index+=sizeof(int); + bi_2_byte_array( &result[index], length, pk->capitalY->array[i]); + index+=length; + } + // basename + memcpy( &result[index], pk->issuerBaseName, length_issuer_base_name); + index+=length_issuer_base_name; + *result_length = index; + + LogDebug("return length=%d", index); + + return result; +} + +/* create anf feel a TSS_DAA_PK structures */ +TSS_DAA_PK * +i_2_e_TSS_DAA_PK(TSS_DAA_PK_internal *pk_internal, + void *(*daa_alloc)(size_t size, TSS_HOBJECT param_alloc), + TSS_HOBJECT param_alloc) +{ + int i; + int capitalYLength; + int capitalYLength2; + TSS_DAA_PK *pk; + + LogDebug("-> i_2_e_TSS_DAA_PK"); + pk = (TSS_DAA_PK *)daa_alloc( sizeof(TSS_DAA_PK), param_alloc); + init_tss_version( pk); + if (pk == NULL) { + LogError("Can not allocate the TSS_DAA_PK structure"); + return NULL; + } + STORE_DAA_PK_BI( modulus, daa_alloc, param_alloc); + STORE_DAA_PK_BI( capitalS, daa_alloc, param_alloc); + STORE_DAA_PK_BI( capitalZ, daa_alloc, param_alloc); + STORE_DAA_PK_BI( capitalR0, daa_alloc, param_alloc); + STORE_DAA_PK_BI( capitalR1, daa_alloc, param_alloc); + STORE_DAA_PK_BI( gamma, daa_alloc, param_alloc); + STORE_DAA_PK_BI( capitalGamma, daa_alloc, param_alloc); + STORE_DAA_PK_BI( rho, daa_alloc, param_alloc); + capitalYLength = pk_internal->capitalY->length; + capitalYLength2 = bi_nbin_size( pk_internal->capitalY->array[0]); + LogDebug("[capitalYLength=%d capitalYLength2=%d total size=%d]\n", + capitalYLength, capitalYLength2, sizeof(BYTE) * capitalYLength * + capitalYLength2); + pk->capitalY = (BYTE **) daa_alloc( sizeof(BYTE *) * capitalYLength, param_alloc ); + for (i = 0; i < capitalYLength; i++) { + if( bi_nbin_size( pk_internal->capitalY->array[i]) != capitalYLength2) { + // LOG ERROR + LogError("Error during feel operation of capitalY (index=%d capitalYLength" + "2=%d, currentSize=%d)\n", i, capitalYLength2, + (int)bi_nbin_size(pk_internal->capitalY->array[i])); + } + BYTE *buffer = (BYTE*) daa_alloc( sizeof(BYTE) * capitalYLength2, param_alloc); + bi_2_byte_array( buffer, capitalYLength2, pk_internal->capitalY->array[i]); + // bi_2_nbin1( &checkSize, buffer, pk_internal->capitalY->array[i]); + pk->capitalY[i] = buffer; + LogDebug( "[i=%d currentsize=%d buffer[%d]=[%2x|%2x]\n", + i, + (int)bi_nbin_size( pk_internal->capitalY->array[i]), + (int)pk->capitalY[i], + (int)pk->capitalY[i][0], + (int)pk->capitalY[i][1]); + } + pk->capitalYLength = capitalYLength; + pk->capitalYLength2 = capitalYLength2; + pk->capitalYPlatformLength = pk_internal->capitalRReceiver->length; + LogDebug("issuer= len=%d", pk_internal->issuerBaseNameLength); + pk->issuerBaseNameLength = pk_internal->issuerBaseNameLength; + pk->issuerBaseName = (BYTE *)daa_alloc(pk_internal->issuerBaseNameLength, param_alloc); + memcpy( pk->issuerBaseName, + pk_internal->issuerBaseName, + pk_internal->issuerBaseNameLength); + LogDebug("i_2_e_TSS_DAA_PK extern_issuer=%s intern_issuer=%s\n", + pk->issuerBaseName, + pk_internal->issuerBaseName); + LogDebug("<- i_2_e_TSS_DAA_PK"); + return pk; +} + +/**/ +TSS_DAA_PK_internal * +e_2_i_TSS_DAA_PK( TSS_DAA_PK *pk) +{ + TSS_DAA_PK_internal *pk_internal = + (TSS_DAA_PK_internal *)malloc(sizeof(TSS_DAA_PK_internal)); + unsigned long capitalYLength, capitalYLength2, capitalYPlatformLength; + UINT32 i; + int issuer_length; + + // pk_internal->modulus = GET_DAA_PK_BI( modulus); + pk_internal->modulus = get_bi(pk->modulusLength, pk->modulus); + pk_internal->capitalS = get_bi(pk->capitalSLength, pk->capitalS); + pk_internal->capitalZ = get_bi(pk->capitalZLength, pk->capitalZ); + pk_internal->capitalR0 = get_bi(pk->capitalR0Length, pk->capitalR0); + pk_internal->capitalR1 = get_bi(pk->capitalR1Length, pk->capitalR1); + pk_internal->gamma = get_bi(pk->gammaLength, pk->gamma); + pk_internal->capitalGamma = get_bi(pk->capitalGammaLength, pk->capitalGamma); + pk_internal->rho = get_bi(pk->rhoLength, pk->rho); + capitalYLength = pk->capitalYLength; + capitalYLength2= pk->capitalYLength2; + capitalYPlatformLength = pk->capitalYPlatformLength; + LogDebug( "capitalYLength:%ld capitalYLength2:%ld capitalYPlatformLength:%ld\n", + capitalYLength, capitalYLength2, capitalYPlatformLength); + + pk_internal->capitalRReceiver = ALLOC_BI_ARRAY(); + bi_new_array2(pk_internal->capitalRReceiver, capitalYPlatformLength); + for (i = 0; i < capitalYPlatformLength; i++) { + LogDebug( "i=%d\n", i); + pk_internal->capitalRReceiver->array[i] = + get_bi(pk->capitalYLength2, pk->capitalY[i]); + } + pk_internal->capitalRIssuer = ALLOC_BI_ARRAY(); + bi_new_array2( pk_internal->capitalRIssuer, capitalYLength - + capitalYPlatformLength); + for( ; i<capitalYLength; i++) { + pk_internal->capitalRIssuer->array[ i - capitalYPlatformLength] = + get_bi( pk->capitalYLength2, pk->capitalY[i]); + } + pk_internal->capitalY = ALLOC_BI_ARRAY(); + populate_capitalY( pk_internal); + issuer_length = pk->issuerBaseNameLength; + pk_internal->issuerBaseNameLength = issuer_length; + LogDebug( "issuer_length=%d\n", issuer_length); + pk_internal->issuerBaseName = (BYTE *)malloc( issuer_length); + memcpy( pk_internal->issuerBaseName, pk->issuerBaseName, issuer_length); + LogDebug("e_2_i_TSS_DAA_PK extern_issuer=%s intern_issuer=%s\n", + pk->issuerBaseName, + pk_internal->issuerBaseName); + compute_capitalSprime( pk_internal); // allocation + return pk_internal; +} + +void +free_TSS_DAA_PK_internal(TSS_DAA_PK_internal *pk_internal) +{ + bi_free_ptr( pk_internal->capitalSprime); + free( pk_internal->issuerBaseName); + free( pk_internal->capitalY); + bi_free_array( pk_internal->capitalRIssuer); + bi_free_array( pk_internal->capitalRReceiver); + bi_free_ptr( pk_internal->rho); + bi_free_ptr( pk_internal->capitalGamma); + bi_free_ptr( pk_internal->gamma); + bi_free_ptr( pk_internal->capitalR1); + bi_free_ptr( pk_internal->capitalR0); + bi_free_ptr( pk_internal->capitalZ); + bi_free_ptr( pk_internal->capitalS); + bi_free_ptr( pk_internal->modulus); + free( pk_internal); +} + +/* free a TSS_DAA_PK structures */ +void +free_TSS_DAA_PK(TSS_DAA_PK *pk) +{ + int i; + + LogDebug("-> free_TSS_DAA_PK"); + free( pk->modulus); + free( pk->capitalS); + free( pk->capitalZ); + free( pk->capitalR0); + free( pk->capitalR1); + free( pk->gamma); + free( pk->capitalGamma); + free( pk->rho); + for( i=0; i<(int)pk->capitalYLength; i++) { + free( pk->capitalY[i]); + } + free( pk->capitalY); + free( pk->issuerBaseName); + free( pk); + LogDebug("<- free_TSS_DAA_PK"); + +} + +TPM_DAA_ISSUER * +convert2issuer_settings(TSS_DAA_PK_internal *pk_internal) +{ + TPM_DAA_ISSUER *result = (TPM_DAA_ISSUER *)malloc(sizeof(TPM_DAA_ISSUER)); + EVP_MD_CTX mdctx; + UINT32 length; + BYTE *array = (BYTE*)malloc((DAA_PARAM_SIZE_RSA_MODULUS+7)/8); + + LogDebug("convert2issuer_settings"); + EVP_MD_CTX_init(&mdctx); + // TAG + result->tag = htons( TPM_TAG_DAA_ISSUER); + // capitalR0 + EVP_DigestInit(&mdctx, DAA_PARAM_get_message_digest()); + + EVP_DigestInit_ex(&mdctx, DAA_PARAM_get_message_digest(), NULL); + bi_2_byte_array( array, + length = (bi_length( pk_internal->capitalR0)+7)/8, + pk_internal->capitalR0); + LogDebug("capitalR0 length=%d", length); + EVP_DigestUpdate(&mdctx, array, length); + EVP_DigestFinal_ex(&mdctx, (BYTE *)&(result->DAA_digest_R0), NULL); + // capitalR1 + EVP_DigestInit_ex(&mdctx, DAA_PARAM_get_message_digest(), NULL); + bi_2_byte_array( array, + length = (bi_length( pk_internal->capitalR1)+7)/8, + pk_internal->capitalR1); + LogDebug("capitalR1 length=%d", length); + EVP_DigestUpdate(&mdctx, array, length); + EVP_DigestFinal_ex(&mdctx, (BYTE *)&(result->DAA_digest_R1), NULL); + // capitalS (S0) + EVP_DigestInit_ex(&mdctx, DAA_PARAM_get_message_digest(), NULL); + bi_2_byte_array( array, + length = (bi_length( pk_internal->capitalS)+7)/8, + pk_internal->capitalS); + LogDebug("capitalS length=%d", length); + EVP_DigestUpdate(&mdctx, array, length); + EVP_DigestFinal_ex(&mdctx, (BYTE *)&(result->DAA_digest_S0), NULL); + // capitalSprime (S1) + EVP_DigestInit_ex(&mdctx, DAA_PARAM_get_message_digest(), NULL); + bi_2_byte_array( array, + length = (bi_length( pk_internal->capitalSprime)+7)/8, + pk_internal->capitalSprime); + LogDebug("capitalSprime length=%d", length); + EVP_DigestUpdate(&mdctx, array, length); + EVP_DigestFinal_ex(&mdctx, (BYTE *)&(result->DAA_digest_S1), NULL); + // modulus (n) + EVP_DigestInit_ex(&mdctx, DAA_PARAM_get_message_digest(), NULL); + bi_2_byte_array( array, + length = (bi_length( pk_internal->modulus)+7)/8, + pk_internal->modulus); + LogDebug("modulus length=%d", length); + EVP_DigestUpdate(&mdctx, array, length); + EVP_DigestFinal_ex(&mdctx, (BYTE *)&(result->DAA_digest_n), NULL); + // modulus (n) + EVP_DigestInit_ex(&mdctx, DAA_PARAM_get_message_digest(), NULL); + bi_2_byte_array( array, + length = (bi_length( pk_internal->capitalGamma)+7)/8, + pk_internal->capitalGamma); + LogDebug("capitalGamma length=%d", length); + EVP_DigestUpdate(&mdctx, array, length); + free(array); + EVP_DigestFinal_ex(&mdctx, (BYTE *)&(result->DAA_digest_gamma), NULL); + EVP_MD_CTX_cleanup(&mdctx); + // rho + bi_2_byte_array( (BYTE *)&(result->DAA_generic_q), 26, pk_internal->rho); + return result; +} + +BYTE * +issuer_2_byte_array(TPM_DAA_ISSUER *tpm_daa_issuer, int *length) +{ + UINT32 size = sizeof(UINT16) + ( 6 * TPM_SHA1_160_HASH_LEN) + 26; + BYTE * result = (BYTE *)malloc( sizeof(BYTE)*size); + UINT32 i = 0; + + memcpy( &result[i], &(tpm_daa_issuer->tag), sizeof(UINT16)); + i+=sizeof(UINT16); + memcpy( &result[i], &(tpm_daa_issuer->DAA_digest_R0), TPM_SHA1_160_HASH_LEN); + i+=TPM_SHA1_160_HASH_LEN; + memcpy( &result[i], &(tpm_daa_issuer->DAA_digest_R1), TPM_SHA1_160_HASH_LEN); + i+=TPM_SHA1_160_HASH_LEN; + memcpy( &result[i], &(tpm_daa_issuer->DAA_digest_S0), TPM_SHA1_160_HASH_LEN); + i+=TPM_SHA1_160_HASH_LEN; + memcpy( &result[i], &(tpm_daa_issuer->DAA_digest_S1), TPM_SHA1_160_HASH_LEN); + i+=TPM_SHA1_160_HASH_LEN; + memcpy( &result[i], &(tpm_daa_issuer->DAA_digest_n), TPM_SHA1_160_HASH_LEN); + i+=TPM_SHA1_160_HASH_LEN; + memcpy( &result[i], &(tpm_daa_issuer->DAA_digest_gamma), TPM_SHA1_160_HASH_LEN); + i+=TPM_SHA1_160_HASH_LEN; + memcpy( &result[i], &(tpm_daa_issuer->DAA_generic_q), 26); + *length = size; + return result; +} + +/******************************************************************************************** +* TSS_DAA_PK_PROOF +********************************************************************************************/ + +/* +* this function keep references on: +* - challenge (BYTE *) +* - response (bi_array_ptr *) +*/ +TSS_DAA_PK_PROOF_internal * +create_DAA_PK_PROOF(BYTE* const challenge, + const int length_challenge, + bi_array_ptr *response, + const int length_response) +{ + TSS_DAA_PK_PROOF_internal *pk_proof; + +#ifdef DAA_DEBUG + printf("create_DAA_PK_PROOF_internal\n"); +#endif + pk_proof = (TSS_DAA_PK_PROOF_internal *)malloc( sizeof(TSS_DAA_PK_PROOF_internal)); + pk_proof->challenge = challenge; + pk_proof->length_challenge = length_challenge; + pk_proof->response = response; + pk_proof->length_response = length_response; + return pk_proof; +} + +#if 0 +int +save_DAA_PK_PROOF_internal(FILE *file, TSS_DAA_PK_PROOF_internal *proof) +{ + int i; + +#ifdef DAA_DEBUG + printf("save_DAA_PK_PROOF_internal"); +#endif + fprintf(file, "%d # %s.length\n", proof->length_challenge, "challenge"); + fprintf(file, "%s\n", dump_byte_array( proof->length_challenge, + proof->challenge)); + fprintf(file, "%d # %s.length\n", proof->length_response, "response"); + for (i = 0; i < proof->length_response; i++) { + BI_SAVE_ARRAY( proof->response[i], file); + } + + return 0; +} + +/* load <proof> using <filename> */ +/* allocation of: */ +/* proof->challenge (BYTE*) */ +/* response (bi_array_ptr) */ +TSS_DAA_PK_PROOF_internal * +load_DAA_PK_PROOF_internal(FILE *file) +{ + TSS_DAA_PK_PROOF_internal *proof = + (TSS_DAA_PK_PROOF_internal *)malloc(sizeof(TSS_DAA_PK_PROOF_internal)); + char *read_buffer; + int i; + +#ifdef DAA_DEBUG + printf("load_DAA_PK_PROOF_internal"); +#endif + proof->length_challenge = read_int( file); + read_buffer = read_str( file); + proof->challenge = retrieve_byte_array( &(proof->length_challenge),read_buffer); + proof->length_response = read_int( file); + proof->response = (bi_array_ptr *)malloc( sizeof(bi_array_ptr) * proof->length_response); + for (i = 0; i < proof->length_response; i++) { + proof->response[i] = ALLOC_BI_ARRAY(); + BI_LOAD_ARRAY( proof->response[i], file); + } + return proof; +} +#endif + +TSS_DAA_PK_PROOF * +i_2_e_TSS_DAA_PK_PROOF(TSS_DAA_PK_PROOF_internal*pk_internal_proof, + void * (*daa_alloc)(size_t size, TSS_HOBJECT param), + TSS_HOBJECT param_alloc) +{ + TSS_DAA_PK_PROOF *pk_proof = + (TSS_DAA_PK_PROOF *)daa_alloc( sizeof(TSS_DAA_PK_PROOF), param_alloc); + int i, j; + int length_response2; + int length_response3; + + init_tss_version( pk_proof); + // CHALLENGE + pk_proof->challengeLength = pk_internal_proof->length_challenge; + pk_proof->challenge = (BYTE *)daa_alloc( pk_internal_proof->length_challenge, + param_alloc); + memcpy( pk_proof->challenge, pk_internal_proof->challenge, + pk_internal_proof->length_challenge); + // RESPONSES + pk_proof->responseLength = pk_internal_proof->length_response; + length_response2 = pk_internal_proof->response[0]->length; + pk_proof->responseLength2 = length_response2; + length_response3 = bi_nbin_size( + pk_internal_proof->response[0]->array[0]); + if( length_response3 & 1) length_response3++; // length_response3 should be paire + pk_proof->responseLength3 = length_response3; + pk_proof->response = (BYTE ***)daa_alloc( sizeof(BYTE **) * + pk_internal_proof->length_response, param_alloc); + for(i = 0; i < pk_internal_proof->length_response; i++) { + pk_proof->response[i] = (BYTE **)daa_alloc( sizeof(BYTE *) * length_response2, + param_alloc); + for( j = 0; j < length_response2; j++) { + (pk_proof->response[i])[j] = (BYTE *)malloc( + sizeof(BYTE) * length_response3); + bi_2_byte_array( pk_proof->response[i][j], + length_response3, + pk_internal_proof->response[i]->array[j]); + } + } + return pk_proof; +} + +TSS_DAA_PK_PROOF_internal * +e_2_i_TSS_DAA_PK_PROOF(TSS_DAA_PK_PROOF *pk_proof) +{ + int i, j, response_length2; + TSS_DAA_PK_PROOF_internal *pk_proof_internal = + (TSS_DAA_PK_PROOF_internal *)malloc( sizeof( TSS_DAA_PK_PROOF_internal)); + + // CHALLENGE + pk_proof_internal->length_challenge = pk_proof->challengeLength; +#ifdef DAA_DEBUG + fprintf(stderr, "issuer_length=%d\n", pk_proof_internal->length_challenge); +#endif + pk_proof_internal->challenge = (BYTE *)malloc( pk_proof_internal->length_challenge); + memcpy( pk_proof_internal->challenge, + pk_proof->challenge, + pk_proof_internal->length_challenge); + // RESPONSES + pk_proof_internal->length_response = pk_proof->responseLength; + response_length2 = pk_proof->responseLength2; + pk_proof_internal->response = + (bi_array_ptr *)malloc( sizeof(bi_array_ptr) * + pk_proof_internal->length_response); + for(i = 0; i<pk_proof_internal->length_response; i++) { + pk_proof_internal->response[i] = ALLOC_BI_ARRAY(); + bi_new_array2( pk_proof_internal->response[i], response_length2); + for( j = 0; j < response_length2; j++) { + pk_proof_internal->response[i]->array[j] = + get_bi( pk_proof->responseLength3, pk_proof->response[i][j]); + } + } + return pk_proof_internal; +} + + +/******************************************************************************************** +* TSS_DAA_JOIN_ISSUER_SESSION +********************************************************************************************/ + +TSS_DAA_JOIN_ISSUER_SESSION_internal * +create(TSS_DAA_PK_PROOF_internal *issuerKeyPair, + TPM_DAA_ISSUER *issuerAuthKey, + TSS_DAA_IDENTITY_PROOF *identityProof, + bi_ptr capitalUprime, + int daaCounter, + int nonceIssuerLength, + BYTE *nonceIssuer, + int nonceEncryptedLength, + BYTE *nonceEncrypted) +{ + TSS_DAA_JOIN_ISSUER_SESSION_internal *result = + (TSS_DAA_JOIN_ISSUER_SESSION_internal *)malloc( + sizeof(TSS_DAA_JOIN_ISSUER_SESSION_internal)); + + result->issuerAuthKey = issuerAuthKey; + result->issuerKeyPair = issuerKeyPair; + result->identityProof = identityProof; + result->capitalUprime = capitalUprime; + result->daaCounter = daaCounter; + result->nonceIssuerLength = nonceIssuerLength; + result->nonceIssuer = nonceIssuer; + result->nonceEncryptedLength = nonceEncryptedLength; + result->nonceEncrypted = nonceEncrypted; + return result; +} + + +/******************************************************************************************** + * TSS_DAA_SIGNATURE + ********************************************************************************************/ + +TSS_DAA_SIGNATURE_internal* +e_2_i_TSS_DAA_SIGNATURE(TSS_DAA_SIGNATURE* signature) +{ + TSS_DAA_SIGNATURE_internal *signature_intern = + (TSS_DAA_SIGNATURE_internal *)malloc( sizeof( TSS_DAA_SIGNATURE_internal)); + int i, length; + + signature_intern->zeta = bi_set_as_nbin( signature->zetaLength, signature->zeta); + signature_intern->capitalT = bi_set_as_nbin( signature->capitalTLength, + signature->capitalT); + signature_intern->challenge_length = signature->challengeLength; + signature_intern->challenge = (BYTE *)malloc( signature->challengeLength); + memcpy( signature_intern->challenge, + signature->challenge, + signature->challengeLength); + signature_intern->nonce_tpm_length = signature->nonceTpmLength; + signature_intern->nonce_tpm = (BYTE *)malloc( signature->nonceTpmLength); + memcpy( signature_intern->nonce_tpm, signature->nonceTpm, signature->nonceTpmLength); + signature_intern->sV = bi_set_as_nbin( signature->sVLength, signature->sV); + signature_intern->sF0 = bi_set_as_nbin( signature->sF0Length, signature->sF0); + signature_intern->sF1 = bi_set_as_nbin( signature->sF1Length, signature->sF1); + signature_intern->sE = bi_set_as_nbin( signature->sELength, signature->sE); + signature_intern->sA = (bi_array_ptr)malloc( sizeof( bi_array)); + bi_new_array2( signature_intern->sA, signature->sALength); + length = ( DAA_PARAM_SIZE_RANDOMIZED_ATTRIBUTES + 7) / 8; + for (i = 0; i < (int)signature->sALength; i++) { + signature_intern->sA->array[i] = bi_set_as_nbin( length, signature->sA[i]); + } + + return signature_intern; +} + +void +free_TSS_DAA_SIGNATURE_internal(TSS_DAA_SIGNATURE_internal *signature) +{ + bi_free_array( signature->sA); + bi_free_ptr( signature->sE); + bi_free_ptr( signature->sF1); + bi_free_ptr( signature->sF0); + bi_free_ptr( signature->sV); + free( signature->nonce_tpm); + free( signature->challenge); + bi_free_ptr( signature->capitalT); + bi_free_ptr( signature->zeta); + free( signature); +} + +#if 0 +/******************************************************************************************** + TSS_DAA_CRED_ISSUER +********************************************************************************************/ + +TSS_DAA_CRED_ISSUER * +load_TSS_DAA_CRED_ISSUER(FILE *file) +{ + TSS_DAA_CRED_ISSUER *credential = + (TSS_DAA_CRED_ISSUER *)malloc(sizeof(TSS_DAA_CRED_ISSUER)); + char *read_buffer; + int i, len; + + init_tss_version( credential); + credential->capitalALength = read_int( file); + read_buffer = read_str( file); + credential->capitalA = retrieve_byte_array( &(credential->capitalALength), + read_buffer); + credential->eLength = read_int( file); + read_buffer = read_str( file); + credential->e = retrieve_byte_array( &(credential->eLength),read_buffer); + credential->vPrimePrimeLength = read_int( file); + read_buffer = read_str( file); + credential->vPrimePrime = retrieve_byte_array(&(credential->vPrimePrimeLength), + read_buffer); + // attributes issuer + credential->attributesIssuerLength = read_int( file); + credential->attributesIssuer = malloc(credential->attributesIssuerLength*sizeof(BYTE*)); + for( i=0; i < (int)credential->attributesIssuerLength; i++) { + credential->attributesIssuer[i] = retrieve_byte_array( &len, read_buffer); + } + credential->cPrimeLength = read_int( file); + read_buffer = read_str( file); + credential->cPrime = retrieve_byte_array( &(credential->cPrimeLength),read_buffer); + credential->sELength = read_int( file); + read_buffer = read_str( file); + credential->sE = retrieve_byte_array( &(credential->sELength),read_buffer); + return credential; +} + +int +save_TSS_DAA_CRED_ISSUER(FILE *file, TSS_DAA_CRED_ISSUER *credential) +{ + int i; + + fprintf(file, "%d # %s.length\n", credential->capitalALength, "capitalA"); + fprintf(file, "%s\n", dump_byte_array( credential->capitalALength, + credential->capitalA)); + fprintf(file, "%d # %s.length\n", credential->eLength, "e"); + fprintf(file, "%s\n", dump_byte_array( credential->eLength, + credential->e)); + fprintf(file, "%d # %s.length\n", credential->vPrimePrimeLength, "vPrimePrime"); + fprintf(file, "%s\n", dump_byte_array( credential->vPrimePrimeLength, + credential->vPrimePrime)); + fprintf(file, "%d # %s\n", credential->attributesIssuerLength, "attributesIssuerLength"); + for( i=0; i < (int)credential->attributesIssuerLength; i++) { + fprintf(file, "%s\n", dump_byte_array( DAA_PARAM_SIZE_F_I / 8, + credential->attributesIssuer[i])); + + } + fprintf(file, "%d # %s.length\n", credential->cPrimeLength, "cPrime"); + fprintf(file, "%s\n", dump_byte_array( credential->cPrimeLength, + credential->cPrime)); + fprintf(file, "%d # %s.length\n", credential->sELength, "sE"); + fprintf(file, "%s\n", dump_byte_array( credential->sELength, + credential->sE)); + return 0; +} + + +/******************************************************************************************** + TSS_DAA_CREDENTIAL +********************************************************************************************/ + +TSS_DAA_CREDENTIAL * +load_TSS_DAA_CREDENTIAL(FILE *file) +{ + TSS_DAA_CREDENTIAL *credential = + (TSS_DAA_CREDENTIAL *)malloc(sizeof(TSS_DAA_CREDENTIAL)); + char *read_buffer; + int i, len; + TSS_DAA_PK_internal *pk_internal; + TSS_DAA_PK *pk; + + init_tss_version( credential); + credential->capitalALength = read_int( file); + read_buffer = read_str( file); + credential->capitalA = retrieve_byte_array( &(credential->capitalALength), + read_buffer); + credential->exponentLength = read_int( file); + read_buffer = read_str( file); + credential->exponent = retrieve_byte_array( &(credential->exponentLength), + read_buffer); + credential->vBar0Length = read_int( file); + read_buffer = read_str( file); + credential->vBar0 = retrieve_byte_array(&(credential->vBar0Length), + read_buffer); + credential->vBar1Length = read_int( file); + read_buffer = read_str( file); + credential->vBar1 = retrieve_byte_array(&(credential->vBar1Length), + read_buffer); + // attributes issuer + credential->attributesLength = read_int( file); + printf("attributesLength=%d\n", credential->attributesLength); + credential->attributes = malloc(credential->attributesLength * sizeof( BYTE *)); + for( i=0; i < (int)credential->attributesLength; i++) { + read_buffer = read_str( file); + credential->attributes[i] = retrieve_byte_array( &len, read_buffer); + if( len != DAA_PARAM_SIZE_F_I / 8) { + LogError("Error when parsing attributes"); + LogError("\tattribute length:%d", len); + LogError("\texpected length:%d", DAA_PARAM_SIZE_F_I / 8); + return NULL; + } + } + pk_internal = load_DAA_PK_internal( file); + pk = i_2_e_TSS_DAA_PK( pk_internal, &normal_malloc, (TSS_HOBJECT)NULL); + memcpy( &(credential->issuerPK), pk, sizeof(TSS_DAA_PK)); + free( pk); + free_TSS_DAA_PK_internal( pk_internal); + credential->tpmSpecificEncLength = read_int( file); + read_buffer = read_str( file); + credential->tpmSpecificEnc = retrieve_byte_array( &(credential->tpmSpecificEncLength), + read_buffer); + credential->daaCounter = read_int( file); + return credential; +} + +int +save_TSS_DAA_CREDENTIAL(FILE *file, + TSS_DAA_CREDENTIAL *credential) +{ + int i; + TSS_DAA_PK_internal *pk_internal; + + fprintf(file, "%d # %s.length\n", credential->capitalALength, "capitalA"); + fprintf(file, "%s\n", dump_byte_array( credential->capitalALength, + credential->capitalA)); + fprintf(file, "%d # %s.length\n", credential->exponentLength, "exponent"); + fprintf(file, "%s\n", dump_byte_array( credential->exponentLength, + credential->exponent)); + fprintf(file, "%d # %s.length\n", credential->vBar0Length, "vBar0"); + fprintf(file, "%s\n", dump_byte_array( credential->vBar0Length, + credential->vBar0)); + fprintf(file, "%d # %s.length\n", credential->vBar1Length, "vBar1"); + fprintf(file, "%s\n", dump_byte_array( credential->vBar1Length, + credential->vBar1)); + fprintf(file, "%d # %s\n", credential->attributesLength, "attributesLength"); + for( i=0; i < (int)credential->attributesLength; i++) { + fprintf(file, "%s\n", dump_byte_array( DAA_PARAM_SIZE_F_I / 8, + credential->attributes[i])); + } + pk_internal = e_2_i_TSS_DAA_PK( &(credential->issuerPK) ); + save_DAA_PK_internal( file, pk_internal); + free_TSS_DAA_PK_internal( pk_internal); + fprintf(file, "%d # %s.length\n", credential->tpmSpecificEncLength, "tpmSpecificEnc"); + fprintf(file, "%s\n", dump_byte_array( credential->tpmSpecificEncLength, + credential->tpmSpecificEnc)); + fprintf(file, "%d # daaCounter\n", credential->daaCounter); + return 0; +} +#endif +/******************************************************************************************** + TPM_DAA_ISSUER +********************************************************************************************/ + +void +free_TPM_DAA_ISSUER(TPM_DAA_ISSUER *tpm_daa_issuer) +{ + free(tpm_daa_issuer); +} diff --git a/src/tspi/daa/daa_verifier/test/Makefile.am b/src/tspi/daa/daa_verifier/test/Makefile.am new file mode 100644 index 0000000..aa02721 --- /dev/null +++ b/src/tspi/daa/daa_verifier/test/Makefile.am @@ -0,0 +1,7 @@ +bin_PROGRAMS = verifier_transaction + +verifier_transaction_SOURCES = ../verifier_transaction.c ../../daa_structs.c \ + ../../big_integer/bi_gmp.c ../../big_integer/bi_openssl.c ../../big_integer/bi.c \ + ../../../include/bi.h ../../../include/bi_openssl.h ../../../include/bi_gmp.h \ + ../../../include/list_.h ../../utils/list.c ../../../include/tss/tss.h ../../../include/daa_parameter.h \ + ../../../include/daa_structs.h diff --git a/src/tspi/daa/daa_verifier/verifier.c b/src/tspi/daa/daa_verifier/verifier.c new file mode 100644 index 0000000..ad7cef1 --- /dev/null +++ b/src/tspi/daa/daa_verifier/verifier.c @@ -0,0 +1,57 @@ + +/* + * Licensed Materials - Property of IBM + * + * trousers - An open source TCG Software Stack + * + * (C) Copyright International Business Machines Corp. 2006 + * + */ + + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "bi.h" +#include "daa_parameter.h" +#include "trousers/tss.h" +#include "spi_internal_types.h" +#include "spi_utils.h" +#include <trousers/trousers.h> +#include <obj.h> +#include "tsplog.h" +#include "tss/tcs.h" +#include "platform.h" + +#include "verifier.h" + +TSPICALL Tspi_DAA_VerifyInit_internal +( + TSS_HDAA hDAA, // in + UINT32* nonceVerifierLength, // out + BYTE** nonceVerifier, // out + UINT32 baseNameLength, // out + BYTE ** baseName // out +) { + TSS_RESULT result = TSS_SUCCESS; + TCS_CONTEXT_HANDLE tcsContext; + bi_ptr nounce = NULL; + + //TODO how to setup the baseName & baseNameLength + if( (result = obj_daa_get_tsp_context( hDAA, &tcsContext)) != TSS_SUCCESS) + goto close; + *nonceVerifierLength = DAA_PARAM_LENGTH_MESSAGE_DIGEST; + *nonceVerifier = calloc_tspi( tcsContext, DAA_PARAM_LENGTH_MESSAGE_DIGEST); + if (*nonceVerifier == NULL) { + LogError("malloc of %d bytes failed", DAA_PARAM_LENGTH_MESSAGE_DIGEST); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + nounce = bi_new_ptr(); + bi_urandom( nounce, DAA_PARAM_LENGTH_MESSAGE_DIGEST * 8); + bi_2_byte_array( *nonceVerifier, DAA_PARAM_LENGTH_MESSAGE_DIGEST, nounce); +close: + FREE_BI( nounce); + return result; +} diff --git a/src/tspi/daa/daa_verifier/verifier_transaction.c b/src/tspi/daa/daa_verifier/verifier_transaction.c new file mode 100644 index 0000000..1eecd43 --- /dev/null +++ b/src/tspi/daa/daa_verifier/verifier_transaction.c @@ -0,0 +1,873 @@ + +/* + * Licensed Materials - Property of IBM + * + * trousers - An open source TCG Software Stack + * + * (C) Copyright International Business Machines Corp. 2006 + * + */ + + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +// for message digest +#include <openssl/evp.h> + +#include "daa_structs.h" +#include "daa_parameter.h" +#include "trousers/tss.h" +#include "spi_internal_types.h" +#include "spi_utils.h" +#include <trousers/trousers.h> +#include <spi_utils.h> +#include <obj.h> +#include "tsplog.h" +#include "tss/tcs.h" +#include "verifier.h" + +#include "trousers/tss.h" +#include "spi_internal_types.h" +#include "spi_utils.h" + +#include "anonymity_revocation.h" + +DAA_VERIFIER_TRANSACTION *create_verifier_transaction( int length, char *base_name) { + DAA_VERIFIER_TRANSACTION *verifier_transaction = + malloc(sizeof(DAA_VERIFIER_TRANSACTION)); + + if (verifier_transaction == NULL) { + LogError("malloc of %d bytes failed", sizeof(DAA_VERIFIER_TRANSACTION)); + return NULL; + } + verifier_transaction->baseName = base_name; + verifier_transaction->baseName_length = length; + OpenSSL_add_all_digests(); + verifier_transaction->digest = DAA_PARAM_get_message_digest(); + return verifier_transaction; +} + +static int verifyNonce( BYTE *nonce_verifier, int length) { + //TODO check nonce_verifier with the current transaction nonce + return 1; +} + +BYTE *compute_bytes( int seedLength, BYTE *seed, int length, const EVP_MD *digest) { + EVP_MD_CTX mdctx; + int N; + BYTE *hash; + BYTE *result; + int i, big_indian_i, len_hash; + + result = (BYTE *)malloc( length); + if (result == NULL) { + LogError("malloc of %d bytes failed", length); + return NULL; + } + EVP_MD_CTX_init(&mdctx); + EVP_DigestInit_ex(&mdctx, digest, NULL); + len_hash = EVP_MD_size(digest); + N = length / len_hash; + hash = (BYTE *)malloc( len_hash); + if (hash == NULL) { + LogError("malloc of %d bytes failed", len_hash); + return NULL; + } + for( i=0; i<N; i++) { + EVP_DigestUpdate(&mdctx, seed, seedLength); + big_indian_i = htonl( i); + EVP_DigestUpdate(&mdctx, &big_indian_i, sizeof( int)); + EVP_DigestFinal_ex(&mdctx, &result[ i * len_hash], NULL); + EVP_DigestInit_ex(&mdctx, digest, NULL); + } + // fill up the rest of the array (i=N) + EVP_DigestUpdate(&mdctx, seed, seedLength); + big_indian_i = htonl( i); + EVP_DigestUpdate(&mdctx, &big_indian_i, sizeof( int)); + EVP_DigestFinal(&mdctx, hash, NULL); + // copy the rest: base_nameLength % len_hash bytes + memcpy( &result[ i * len_hash], hash, length - N * len_hash); + free( hash); + return result; +} + +/* from DAAUtil */ +bi_ptr project_into_group_gamma( bi_ptr base, TSS_DAA_PK_internal *issuer_pk) { + bi_t exponent; bi_new( exponent); + bi_ptr capital_gamma = issuer_pk->capitalGamma; + bi_ptr rho = issuer_pk->rho; + bi_ptr zeta = bi_new_ptr(); + + if( capital_gamma == NULL || + rho == NULL || + zeta == NULL) return NULL; + // exponent = capital_gamma - 1 + bi_sub( exponent, capital_gamma, bi_1); + // exponent = exponent / rho + bi_div( exponent, exponent, rho); + // zeta = ( base ^ exponent) % capital_gamma + LogDebug("project_into_group_gamma: rho [%ld]:%s", + bi_nbin_size( rho), bi_2_hex_char( rho)); + LogDebug("project_into_group_gamma: base[%ld]:%s", + bi_nbin_size( base), bi_2_hex_char( base)); + LogDebug("project_into_group_gamma: exponent [%ld]:%s", + bi_nbin_size( exponent), bi_2_hex_char( exponent)); + LogDebug("project_into_group_gamma: capitalGamma[%ld]:%s", + bi_nbin_size( capital_gamma), + bi_2_hex_char( capital_gamma)); + bi_mod_exp( zeta, base, exponent, capital_gamma); + LogDebug("project_into_group_gamma: result:%s", bi_2_hex_char( zeta)); + bi_free( exponent); + return zeta; +} + +bi_ptr compute_zeta( int nameLength, unsigned char *name, TSS_DAA_PK_internal *issuer_pk) { + BYTE *bytes; + bi_ptr base; + bi_ptr result; + + LogDebug("compute_zeta: %d [%s] pk:%x", nameLength, name, (int)issuer_pk); + bytes = compute_bytes( nameLength, + name, + DAA_PARAM_LENGTH_MFG1_GAMMA, + DAA_PARAM_get_message_digest()); + if( bytes == NULL) return NULL; + base = bi_set_as_nbin( DAA_PARAM_LENGTH_MFG1_GAMMA, bytes); + if( base == NULL) return NULL; + LogDebug("base: %ld [%s]", bi_nbin_size( base), bi_2_hex_char( base)); + result = project_into_group_gamma( base, issuer_pk); + if( result == NULL) return NULL; + bi_free_ptr( base); + free( bytes); + LogDebug("return zeta:%s\n", bi_2_hex_char( result)); + return result; +} + +bi_ptr compute_parameterized_gamma(int k, TSS_DAA_PK_internal *issuer_pk) { + int length; + int hashLength = bi_nbin_size( issuer_pk->gamma) + sizeof(int); + BYTE *hash; + int big_indian_k = htonl( k); + BYTE *bytes; + bi_ptr value, result; + + hash = (BYTE *)malloc( hashLength); + if (hash == NULL) { + LogError("malloc of %d bytes failed", hashLength); + return NULL; + } + // hash[0-3] = big_indian(k) + memcpy( hash, &big_indian_k, sizeof(int)); + // hash[4-end] = issuer_pk->gamma + bi_2_nbin1( &length, &hash[sizeof(int)], issuer_pk->gamma); + // allocation + bytes = compute_bytes( hashLength, hash, + DAA_PARAM_LENGTH_MFG1_GAMMA, + DAA_PARAM_get_message_digest()); + if( bytes == NULL) return NULL; + // allocation + value = bi_set_as_nbin( DAA_PARAM_LENGTH_MFG1_GAMMA, bytes); + if( value == NULL) return NULL; + result = project_into_group_gamma( value, issuer_pk); // allocation + if (result == NULL) { + LogError("malloc of %d bytes failed", hashLength); + return NULL; + } + bi_free_ptr( value); + free( bytes); + return result; +} + +inline bi_ptr apply_challenge( bi_ptr value, bi_ptr delta, bi_ptr c, bi_ptr capital_gamma) { + bi_ptr delta_tilde = bi_new_ptr(); + bi_t c_negate; + + if( delta_tilde == NULL) return NULL; + bi_new( c_negate); + bi_set( c_negate, c); + bi_negate( c_negate); + // delta_tilde = ( delta ^ (-c)) % capital_gamma + bi_mod_exp( delta_tilde, delta, c_negate, capital_gamma); + bi_free( c_negate); + // delta_tilde = (delta_tilde * value) % capital_gamma + return bi_mod( delta_tilde, bi_mul( delta_tilde, delta_tilde, value), capital_gamma); +} + +DAA_VERIFIER_TRANSACTION *createTransaction(int baseName_length, BYTE* baseName) { + DAA_VERIFIER_TRANSACTION *result = + (DAA_VERIFIER_TRANSACTION *)malloc( sizeof(DAA_VERIFIER_TRANSACTION)); + + if (result == NULL) { + LogError("malloc of %d bytes failed", sizeof(DAA_VERIFIER_TRANSACTION)); + return NULL; + } + result->baseName = baseName; + result->baseName_length = baseName_length; + return result; +} + +void update( EVP_MD_CTX *mdctx, char *name, bi_ptr integer, int bitLength) { + int length = bitLength / 8; + BYTE buffer[length]; + + bi_2_byte_array( buffer, length, integer); + LogDebug("[update] %s:%s", name, dump_byte_array( length, buffer)); + EVP_DigestUpdate(mdctx, buffer, length); +} + +BYTE *compute_sign_challenge_host( + int *result_length, + EVP_MD *digest, + TSS_DAA_PK_internal *issuer_pk, + int nonce_verifierLength, + BYTE *nonce_verifier, + int selected_attributes2commitLength, + TSS_DAA_SELECTED_ATTRIB **selected_attributes2commit, + int is_anonymity_revocation_enabled, + bi_ptr zeta, + bi_ptr capital_t, + bi_ptr capital_tilde, + int attribute_commitmentsLength, + TSS_DAA_ATTRIB_COMMIT_internal **attribute_commitments, + TSS_DAA_ATTRIB_COMMIT_internal **attribute_commitment_proofs, + bi_ptr capital_nv, + bi_ptr capital_tilde_v, + CS_PUBLIC_KEY *anonymity_revocator_pk, + CS_ENCRYPTION_RESULT *encryption_result_rand, + CS_ENCRYPTION_RESULT *encryption_result_proof +) { + EVP_MD_CTX mdctx; + int i, length; + unsigned int big_indian; + BYTE *buffer; + int length_gamma_modulus; + BYTE *buffer1; + + LogDebug("issuer_pk basename[%d]:%s", + issuer_pk->issuerBaseNameLength, + dump_byte_array( issuer_pk->issuerBaseNameLength, + issuer_pk->issuerBaseName)); + LogDebug("nonce_verifier[%d]:%s", + nonce_verifierLength, + dump_byte_array( nonce_verifierLength, nonce_verifier)); + LogDebug("selected_attributes2commitLength:%d", selected_attributes2commitLength); + LogDebug("is_anonymity_revocation_enabled:%d", is_anonymity_revocation_enabled); + LogDebug("zeta[%ld]:%s", bi_nbin_size( zeta), bi_2_hex_char( zeta)); + LogDebug("capital_t[%ld]:%s", bi_nbin_size( capital_t), bi_2_hex_char( capital_t)); + LogDebug("capital_tilde[%ld]:%s", + bi_nbin_size( capital_tilde), + bi_2_hex_char( capital_tilde)); + LogDebug("attribute_commitmentsLength:%d", attribute_commitmentsLength); + LogDebug("attribute_commitments:%d", (int)attribute_commitments); + LogDebug("attribute_commitment_proofs:%d", (int)attribute_commitment_proofs); + LogDebug("capital_nv[%ld]:%s", bi_nbin_size( capital_nv), bi_2_hex_char( capital_nv)); + LogDebug("capital_tilde_v[%ld]:%s", + bi_nbin_size( capital_tilde_v), + bi_2_hex_char( capital_tilde_v)); + LogDebug("anonymity_revocator_pk:%d", (int)anonymity_revocator_pk); + LogDebug("encryption_result_rand:%d", (int)encryption_result_rand); + LogDebug("encryption_result_proof:%d", (int)encryption_result_proof); + + EVP_MD_CTX_init(&mdctx); + EVP_DigestInit_ex(&mdctx, digest, NULL); + // update with encoded PK + buffer = encoded_DAA_PK_internal( &length, issuer_pk); + if( buffer == NULL) return NULL; + LogDebug("encoded issuer_pk[%d]:%s", length, dump_byte_array( length, buffer)); + EVP_DigestUpdate(&mdctx, buffer , length); + free( buffer); + // nonce verifier + EVP_DigestUpdate(&mdctx, nonce_verifier , nonce_verifierLength); + // length Commitments + big_indian = attribute_commitmentsLength; + EVP_DigestUpdate(&mdctx, &big_indian, sizeof(int)); + // Anonymity enabled + big_indian = is_anonymity_revocation_enabled; + EVP_DigestUpdate(&mdctx, &big_indian, sizeof(int)); + + update( &mdctx, "zeta", zeta, DAA_PARAM_SIZE_MODULUS_GAMMA); + update( &mdctx, "capitalT", capital_t, DAA_PARAM_SIZE_RSA_MODULUS); + update( &mdctx, "capitalTTilde", capital_tilde, DAA_PARAM_SIZE_RSA_MODULUS); + + length_gamma_modulus = DAA_PARAM_SIZE_MODULUS_GAMMA / 8; + buffer = (BYTE *)malloc( length_gamma_modulus);// allocation + if (buffer == NULL) { + LogError("malloc of %d bytes failed", length_gamma_modulus); + return NULL; + } + if( selected_attributes2commitLength > 0) { + for( i=0; i<selected_attributes2commitLength; i++) { + buffer1 = to_bytes_TSS_DAA_SELECTED_ATTRIB_internal( + &length, + selected_attributes2commit[i]); + EVP_DigestUpdate(&mdctx, buffer1, length); + free( buffer1); + bi_2_byte_array( buffer, + length_gamma_modulus, + attribute_commitments[i]->beta); + EVP_DigestUpdate(&mdctx, + buffer, + length_gamma_modulus); + bi_2_byte_array( buffer, + length_gamma_modulus, + attribute_commitment_proofs[i]->beta); + EVP_DigestUpdate(&mdctx, + buffer, + length_gamma_modulus); + } + } + if( !is_anonymity_revocation_enabled) { + // Nv, N~v + bi_2_byte_array( buffer, length_gamma_modulus, capital_nv); + EVP_DigestUpdate(&mdctx, buffer, length_gamma_modulus); + bi_2_byte_array( buffer, length_gamma_modulus, capital_tilde_v); + EVP_DigestUpdate(&mdctx, buffer, length_gamma_modulus); + } else { + bi_2_byte_array( buffer, length_gamma_modulus, anonymity_revocator_pk->eta); + EVP_DigestUpdate(&mdctx, buffer, length_gamma_modulus); + bi_2_byte_array( buffer, length_gamma_modulus, anonymity_revocator_pk->lambda1); + EVP_DigestUpdate(&mdctx, buffer, length_gamma_modulus); + bi_2_byte_array( buffer, length_gamma_modulus, anonymity_revocator_pk->lambda2); + EVP_DigestUpdate(&mdctx, buffer, length_gamma_modulus); + bi_2_byte_array( buffer, length_gamma_modulus, anonymity_revocator_pk->lambda3); + EVP_DigestUpdate(&mdctx, buffer, length_gamma_modulus); + bi_2_byte_array( buffer, length_gamma_modulus, encryption_result_rand->c1); + EVP_DigestUpdate(&mdctx, buffer, length_gamma_modulus); + bi_2_byte_array( buffer, length_gamma_modulus, encryption_result_rand->c2); + EVP_DigestUpdate(&mdctx, buffer, length_gamma_modulus); + bi_2_byte_array( buffer, length_gamma_modulus, encryption_result_rand->c3); + EVP_DigestUpdate(&mdctx, buffer, length_gamma_modulus); + bi_2_byte_array( buffer, length_gamma_modulus, encryption_result_rand->c4); + EVP_DigestUpdate(&mdctx, buffer, length_gamma_modulus); + bi_2_byte_array( buffer, length_gamma_modulus, encryption_result_proof->c1); + EVP_DigestUpdate(&mdctx, buffer, length_gamma_modulus); + bi_2_byte_array( buffer, length_gamma_modulus, encryption_result_proof->c2); + EVP_DigestUpdate(&mdctx, buffer, length_gamma_modulus); + bi_2_byte_array( buffer, length_gamma_modulus, encryption_result_proof->c3); + EVP_DigestUpdate(&mdctx, buffer, length_gamma_modulus); + bi_2_byte_array( buffer, length_gamma_modulus, encryption_result_proof->c4); + EVP_DigestUpdate(&mdctx, buffer, length_gamma_modulus); + } + free(buffer); + buffer = (BYTE *)malloc(EVP_MD_size(digest)); // allocation + if (buffer == NULL) { + LogError("malloc of %d bytes failed", EVP_MD_size(digest)); + return NULL; + } + EVP_DigestFinal_ex(&mdctx, buffer, result_length); + EVP_MD_CTX_cleanup(&mdctx); + LogDebug("compute_sign_challenge_host[%d]:%s", + *result_length, + dump_byte_array( *result_length, buffer)); + return buffer; +} + +inline int is_element_gamma( bi_ptr capital_nv, TSS_DAA_PK_internal *issuer_pk) { + bi_ptr tmp1 = bi_new_ptr(); + int result; + + // ( ( capital_nv ^ issuer_pk->rho ) % issuer_pk->capitalGamma ) == 1 + result = bi_equals( bi_mod_exp( tmp1, + capital_nv, + issuer_pk->rho, + issuer_pk->capitalGamma), + bi_1); + bi_free_ptr( tmp1); + return result; +} + +/* implementation derived from isValid (VerifierTransaction.java) */ +TSPICALL Tspi_DAA_VerifySignature_internal +( TSS_HDAA hDAA, // in + TSS_DAA_SIGNATURE signature_ext, // in + TSS_HKEY hPubKeyIssuer, // in + TSS_DAA_SIGN_DATA sign_data, // in + UINT32 attributesLength, // in + BYTE **attributes, // in + UINT32 nonce_verifierLength, // out + BYTE *nonce_verifier, // out + UINT32 base_nameLength, // out + BYTE *base_name, // out + TSS_BOOL *isCorrect // out +) { + int i, j; + DAA_VERIFIER_TRANSACTION *verifier_transaction = NULL; + TSS_DAA_ATTRIB_COMMIT *commitments; + TSS_DAA_PK_internal *issuer_pk; + TSS_DAA_SIGNATURE_internal *signature = NULL; + bi_ptr tmp1; + bi_array_ptr sA; + bi_ptr n = NULL; + bi_ptr c = NULL; + bi_ptr capital_gamma = NULL; + bi_ptr zeta_2_verify = NULL; + bi_ptr capital_z = NULL; + bi_array_ptr capital_R = NULL; + bi_ptr product_r = NULL; + bi_ptr exp = NULL; + bi_ptr capital_THat = NULL; + bi_ptr beta_tilde = NULL; + bi_ptr gamma_i = NULL; + bi_ptr capital_nv = NULL; + bi_ptr capital_ntilde_v = NULL; + bi_ptr pseudonym_projected = NULL; + bi_ptr s_tau = NULL; + bi_ptr delta_tilde1 = NULL; + bi_ptr delta_tilde2 = NULL; + bi_ptr delta_tilde3 = NULL; + bi_ptr delta_tilde4 = NULL; + bi_ptr attribute_i; + TSS_DAA_PSEUDONYM_PLAIN *pseudonym_plain; + CS_ENCRYPTION_RESULT *pseudonym_enc = NULL; + CS_ENCRYPTION_RESULT *pseudonym_encryption_proof = NULL; + TSS_DAA_PSEUDONYM_ENCRYPTED_internal *sig_pseudonym_encrypted = NULL; + CS_ENCRYPTION_RESULT_RANDOMNESS *result_random = NULL; + CS_ENCRYPTION_RESULT *encryption_result = NULL; + TSS_DAA_ATTRIB_COMMIT_internal **commitment_proofs = NULL; + TCS_CONTEXT_HANDLE tcsContext; + TSS_RESULT result = TSS_SUCCESS; + EVP_MD_CTX mdctx; + int length_ch, len_hash, bits; + BYTE *ch = NULL, *hash = NULL; + TSS_BOOL *indices; + + tmp1 = bi_new_ptr(); + if( tmp1 == NULL) { + LogError("malloc of BI <%s> failed", "tmp1"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + *isCorrect = FALSE; + if( (result = obj_daa_get_tsp_context( hDAA, &tcsContext)) != TSS_SUCCESS) + goto close; + // allocation of issuer_pk + issuer_pk = e_2_i_TSS_DAA_PK( (TSS_DAA_PK *)hPubKeyIssuer); + if( issuer_pk == NULL) { + LogError("malloc of TSS_DAA_PK_internal failed"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + // allocation of signature + signature = e_2_i_TSS_DAA_SIGNATURE( &signature_ext); + if( signature == NULL) { + LogError("malloc of TSS_DAA_SIGNATURE_internal failed"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + commitments = signature_ext.attributeCommitments; + // TODO verify consistency of sig.getSA() with selectedAttributes,.. + sA = signature->sA; + if( sA->length != (int)attributesLength) { + LogError("Verifier Error: lengths of attributes and sA must be equal"); + result = TSS_E_BAD_PARAMETER; + goto close; + } + for ( i = 0; i < (int)attributesLength; i++) { + if ( (attributes[i] == NULL && bi_equals( sA->array[i], bi_0)) || + (attributes[i] != NULL && !bi_equals( sA->array[i], bi_0))) { + LogError( "Verifier Error: illegal argument content in attributes\ + and sA[%d]", i); + result = TSS_E_BAD_PARAMETER; + goto close; + } + } + // TODO: implement verify nonce + if ( verifyNonce(nonce_verifier, nonce_verifierLength) == 0) { + LogError("Verifier Error: nonce invalid"); + result = TSS_E_INTERNAL_ERROR; + goto close; + } + n = issuer_pk->modulus; + c = bi_set_as_nbin( signature->challenge_length, signature->challenge); + capital_gamma = issuer_pk->capitalGamma; + if( base_name != NULL) { // isRandomBaseName + zeta_2_verify = compute_zeta( base_nameLength, base_name, issuer_pk); + if( bi_equals( signature->zeta, zeta_2_verify) == 0) { + LogError("Verifier Error: Verification of zeta failed - Step 1"); + result = TSS_E_INTERNAL_ERROR; + goto close; + } + } + LogDebug( "step 2"); + capital_z = issuer_pk->capitalZ; + capital_R = issuer_pk->capitalY; + product_r = bi_new_ptr(); + if( product_r == NULL) { + LogError("malloc of BI <%s> failed", "product_r"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_set( product_r, bi_1); // product_r = 1 + for( i=0; i<(int)attributesLength; i++) { + if( attributes[i] != NULL) { + // allocation + attribute_i = bi_set_as_nbin( DAA_PARAM_SIZE_F_I / 8, attributes[i]); + if( attribute_i == NULL) { + LogError("malloc of %d bytes failed", DAA_PARAM_SIZE_F_I / 8); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + // tmp1 = (capital_R[i] ^ attributes[i]) mod n + bi_mod_exp( tmp1, capital_R->array[i], attribute_i, n); + // product_r = product_r * tmp1 + bi_mul( product_r, product_r, tmp1); + // product_r = product_r mod n + bi_mod( product_r, product_r, n); + bi_free_ptr( attribute_i); + } + } + exp = bi_new_ptr(); + if( exp == NULL) { + LogError("malloc of BI <%s> failed", "product_r"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + capital_THat = bi_new_ptr(); + // tmp1 = product_r invmod n + bi_invert_mod( tmp1, product_r, n); + // capital_THat = capital_z * tmp1 + bi_mul( capital_THat, capital_z, tmp1); + // capital_THat = capital_THat % n + bi_mod( capital_THat, capital_THat, n); + // capital_THat = (capital_THat ^ (-c)) mod n = ( 1 / (capital_That ^ c) ) % n + bi_mod_exp( capital_THat, capital_THat, c, n); + bi_invert_mod( capital_THat, capital_THat, n); + // tmp1 = c << (SizeExponentCertificate - 1) + bi_shift_left( tmp1, c, DAA_PARAM_SIZE_EXPONENT_CERTIFICATE - 1); + // exp = signature->sE + tmp1 + bi_add( exp, signature->sE, tmp1); + // tmp1 = (signature->capitalT ^ exp) mod n + bi_mod_exp( tmp1, signature->capitalT, exp, n); + // capital_THat = ( capital_THat * tmp1 ) % n + bi_mul( capital_THat, capital_THat, tmp1); + bi_mod( capital_THat, capital_THat, n); + // tmp1=( issuer_pk->capitalR0 ^ signature->sF0) % n + bi_mod_exp( tmp1, issuer_pk->capitalR0, signature->sF0, n); + // capital_THat = ( capital_THat * tmp1 ) % n + bi_mul( capital_THat, capital_THat, tmp1); + bi_mod( capital_THat, capital_THat, n); + // tmp1=( issuer_pk->capitalR1 ^ signature->sF1) % n + bi_mod_exp( tmp1, issuer_pk->capitalR1, signature->sF1, n); + // capital_THat = ( capital_THat * tmp1 ) % n + bi_mul( capital_THat, capital_THat, tmp1); + bi_mod( capital_THat, capital_THat, n); + // tmp1=( issuer_pk->capitalS ^ signature->sV) % n + bi_mod_exp( tmp1, issuer_pk->capitalS, signature->sV, n); + // capital_THat = ( capital_THat * tmp1 ) % n + bi_mul( capital_THat, capital_THat, tmp1); + bi_mod( capital_THat, capital_THat, n); + + bi_set( product_r, bi_1); // product_r = 1 + for( i=0; i<(int)attributesLength; i++) { + if( attributes[i] == NULL) { + // tmp1=(capital_R->array[i] ^ sA->array[i]) % n + bi_mod_exp( tmp1, capital_R->array[i], sA->array[i], n); + // product_r = ( product_r * tmp1 ) % n + bi_mul( product_r, product_r, tmp1); + bi_mod( product_r, product_r, n); + } + } + // capital_THat = (capital_THat * product_r) % n + bi_mod( capital_THat, bi_mul( tmp1, capital_THat, product_r), n); + LogDebug("Step 3 - Commitments"); + + //TODO when enabling the commitment feature, verifier_transaction should be set + #ifdef ANONYMITY_REVOCATION + if( verifier_transaction != NULL && + verifier_transaction->selected_attributes2commitLength > 0) { + commitment_proofs = (TSS_DAA_ATTRIB_COMMIT_internal **) + malloc(verifier_transaction->selected_attributes2commitLength * + sizeof(TSS_DAA_ATTRIB_COMMIT_internal*)); + if (commitment_proofs == NULL) { + LogError("malloc of %d bytes failed", + verifier_transaction->selected_attributes2commitLength * + sizeof(TSS_DAA_ATTRIB_COMMIT_internal*)); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + for( j=0; j<verifier_transaction->selected_attributes2commitLength; j++) { + if( bi_cmp( commitments[j].sMu, issuer_pk->rho) >= 0 || + bi_cmp_si( commitments[j].sMu, 0) < 0) { + LogError("sMu >= rho || sMu < 0"); + result = TSS_E_INTERNAL_ERROR; + goto close; + } + beta_tilde = bi_new_ptr(); + if( beta_tilde == NULL) { + LogError("malloc of BI <%s> failed", "beta_tilde"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_set( tmp1, c); + bi_negate( tmp1); + // beta_tilde=(commitments[j]->beta ^ (-c)) % capitalGamma + bi_mod_exp( beta_tilde, commitments[j]->beta, tmp1, capital_gamma); + // tmp1=(issuer_pk->gamma ^ commitments[j]->sMu) % capital_gamma + bi_mod_exp( tmp1, issuer_pk->gamma, commitments[j]->sMu, capital_gamma); + // beta_tilde=beta_tilde * tmp1 + bi_mul( beta_tilde, beta_tilde, tmp1); + // beta_tilde=beta_tilde % capital_gamma + bi_mod( beta_tilde, beta_tilde, capital_gamma); + indices = (verifier_transaction->selected_attributes2commit[j])-> + indicesList; + if( verifier_transaction->selected_attributes2commit[j]-> + indicesListLength != (UINT32)(issuer_pk->capitalY->length) ) { + LogError("indicesList of selected_attribs[%d] (%d) \ +and issuer_pk are not consistent (%d)\n", + j, + verifier_transaction->selected_attributes2commit[j]-> + indicesListLength, + issuer_pk->capitalY->length); + result = TSS_E_INTERNAL_ERROR; + goto close; + } + for( i=0; i<issuer_pk->capitalY->length; i++) { + if( indices[i]) { + gamma_i = compute_parameterized_gamma( i, issuer_pk); + if( gamma_i == NULL) { + LogError("malloc of BI <%s> failed", "gamma_i"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + // tmp1=(gamma_i ^ sA[j]) % capital_gamma + bi_mod_exp( tmp1, gamma_i, sA->array[i], capital_gamma); + // beta_tilde=beta_tilde * tmp1 + bi_mul( beta_tilde, beta_tilde, tmp1); + // beta_tilde=beta_tilde % capital_gamma + bi_mod( beta_tilde, beta_tilde, capital_gamma); + } + } + commitment_proofs[j] = create_TSS_DAA_ATTRIB_COMMIT( beta_tilde, NULL); + } + } + #endif + LogDebug("Step 4 - Pseudonym"); + capital_nv = bi_new_ptr(); + if( capital_nv == NULL) { + LogError("malloc of BI <%s> failed", "capital_nv"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + capital_ntilde_v = bi_new_ptr(); + if( capital_ntilde_v == NULL) { + LogError("malloc of BI <%s> failed", "capital_ntilde_v"); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + bi_shift_left( tmp1, signature->sF1, DAA_PARAM_SIZE_F_I); + bi_add( exp, signature->sF0, tmp1); + pseudonym_projected = bi_new_ptr(); + // pseudonym_projected = (signature->zeta ^ exp) % capital_gamma + bi_mod_exp( pseudonym_projected, signature->zeta, exp, capital_gamma); + pseudonym_enc = NULL; + pseudonym_encryption_proof = NULL; + //TODO when enabling the commitment feature, verifier_transaction should be set + if( verifier_transaction == NULL || + verifier_transaction->is_anonymity_revocation_enabled ==0) { + // anonymity revocation not enabled + pseudonym_plain = (TSS_DAA_PSEUDONYM_PLAIN *)signature_ext.signedPseudonym; + capital_nv = bi_set_as_nbin( pseudonym_plain->capitalNvLength, + pseudonym_plain->capitalNv); +//TODO + // capital_ntilde_v = ( capital_nv ^ ( - c) ) % capital_gamma + // = ( 1 / (capital_nv ^ c) % capital_gamma) % capital_gamma + bi_mod_exp( tmp1, capital_nv, c, capital_gamma); + bi_invert_mod( capital_ntilde_v, tmp1, capital_gamma); + // capital_ntilde_v = ( capital_ntilde_v * pseudonym_projected ) % capital_gamma + bi_mul(capital_ntilde_v, capital_ntilde_v, pseudonym_projected); + bi_mod( capital_ntilde_v, capital_ntilde_v, capital_gamma); + } else { +#ifdef ANONYMITY_REVOCATION + // anonymity revocation enabled + sig_pseudonym_encrypted = (TSS_DAA_PSEUDONYM_ENCRYPTED_internal *)pseudonym; + s_tau = sig_pseudonym_encrypted->sTau; + pseudonym_enc = sig_pseudonym_encrypted->cs_enc_result; + // Note: It verifies if s_tau <= rho + result_random = compute_ecryption_proof( + pseudonym_projected, + pseudonym_enc->c1, + pseudonym_enc->c2, + pseudonym_enc->c3, + s_tau, + verifier_transaction->anonymity_revocator_pk, issuer_pk, + verifier_transaction->anonymity_revocation_condition, + verifier_transaction->anonymity_revocation_condition_length, + DAA_PARAM_get_message_digest() ); + encryption_result = result_random->result; + delta_tilde1 = apply_challenge( encryption_result->c1, + pseudonym_enc->c1, + c, + capital_gamma); + delta_tilde2 = apply_challenge( encryption_result->c2, + pseudonym_enc->c2, + c, + capital_gamma); + delta_tilde3 = apply_challenge( encryption_result->c3, + pseudonym_enc->c3, + c, + capital_gamma); + delta_tilde4 = apply_challenge( encryption_result->c4, + pseudonym_enc->c4, + c, + capital_gamma); + pseudonym_encryption_proof = create_CS_ENCRYPTION_RESULT( delta_tilde1, + delta_tilde2, + delta_tilde3, + delta_tilde4); +#endif + } + + // TODO: Step 5 - Callback + LogDebug("Step 5 - Callback"); + + LogDebug("Step 6 - Hash"); + ch = compute_sign_challenge_host( + &length_ch, + DAA_PARAM_get_message_digest(), + issuer_pk, + nonce_verifierLength, + nonce_verifier, + 0, // verifier_transaction->selected_attributes2commitLength, + NULL, //verifier_transaction->selected_attributes2commit, + 0, // verifier_transaction->is_anonymity_revocation_enabled, + signature->zeta, + signature->capitalT, + capital_THat, + 0, //signature_ext.attributeCommitmentsLength, + NULL, // signature_ext.attributeCommitments, + commitment_proofs, + capital_nv, + capital_ntilde_v, + NULL, // verifier_transaction->anonymity_revocator_pk, + pseudonym_enc, + pseudonym_encryption_proof); + LogDebug("calculation of c: ch[%d]%s", length_ch, dump_byte_array( length_ch, ch)); + LogDebug("calculation of c: nonce_tpm[%d]%s", + signature->nonce_tpm_length, + dump_byte_array( signature->nonce_tpm_length, signature->nonce_tpm)); + LogDebug("calculation of c: sign_data.payloadFlag[%d]%x", 1, sign_data.payloadFlag); + LogDebug("calculation of c: signdata.payload[%d]%s", + sign_data.payloadLength, + dump_byte_array( sign_data.payloadLength, sign_data.payload)); + EVP_MD_CTX_init(&mdctx); + EVP_DigestInit_ex(&mdctx, DAA_PARAM_get_message_digest(), NULL); + EVP_DigestUpdate(&mdctx, ch, length_ch); + EVP_DigestUpdate(&mdctx, signature->nonce_tpm, signature->nonce_tpm_length); + len_hash = EVP_MD_size( DAA_PARAM_get_message_digest()); + hash = (BYTE *)malloc( len_hash);// allocation + if (hash == NULL) { + LogError("malloc of %d bytes failed", len_hash); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + EVP_DigestFinal_ex(&mdctx, hash, NULL); + EVP_DigestInit_ex(&mdctx, DAA_PARAM_get_message_digest(), NULL); + EVP_DigestUpdate(&mdctx, hash, EVP_MD_size( DAA_PARAM_get_message_digest())); + EVP_DigestUpdate(&mdctx, &sign_data.payloadFlag, 1); + EVP_DigestUpdate(&mdctx, sign_data.payload, sign_data.payloadLength); + len_hash = EVP_MD_size( DAA_PARAM_get_message_digest()); + free( hash); + hash = (BYTE *)malloc( len_hash);// allocation + if (hash == NULL) { + LogError("malloc of %d bytes failed", len_hash); + result = TSPERR(TSS_E_OUTOFMEMORY); + goto close; + } + EVP_DigestFinal(&mdctx, hash, NULL); + + if( signature->challenge_length != len_hash || + memcmp( signature->challenge, hash, len_hash) != 0) { + LogError( "Verification of c failed - Step 6.c.i"); + LogError(" - challenge[%d] : %s", + signature->challenge_length, + dump_byte_array( signature->challenge_length, signature->challenge)); + LogError(" - hash[%d] : %s", + len_hash, + dump_byte_array( len_hash, hash)); + result = TSS_E_INTERNAL_ERROR; + goto close; + } + if( verifier_transaction == NULL || + !verifier_transaction->is_anonymity_revocation_enabled) { + // Nv element <gamma> ? + if( !is_element_gamma( capital_nv, issuer_pk) ) { + LogError( "Verification of Nv failed - Step 4.b.i"); + result = TSS_E_INTERNAL_ERROR; + goto close; + } + } else { + // are delta1-4 element <gamma> ? + if( !( is_element_gamma( pseudonym_enc->c1, issuer_pk) && + is_element_gamma( pseudonym_enc->c2, issuer_pk) && + is_element_gamma( pseudonym_enc->c3, issuer_pk) && + is_element_gamma( pseudonym_enc->c4, issuer_pk))) { + LogError( "Verification of delta1-4 failed - Step 4.c.i"); + result = TSS_E_INTERNAL_ERROR; + goto close; + } + } + // zeta element <gamma> + if( !is_element_gamma( signature->zeta, issuer_pk)) { + LogError( "Verification of zeta failed - Step 4.b/c.i"); + result = TSS_E_INTERNAL_ERROR; + goto close; + } + bits = DAA_PARAM_SIZE_F_I + DAA_PARAM_SAFETY_MARGIN + + DAA_PARAM_SIZE_MESSAGE_DIGEST + 1; + if( bi_length( signature->sF0) > bits) { + LogError("Verification of sF0 failed - Step 6.c.ii"); + result = TSS_E_INTERNAL_ERROR; + goto close; + } + if( bi_length( signature->sF1) > bits) { + LogError("Verification of sF1 failed - Step 6.c.ii"); + result = TSS_E_INTERNAL_ERROR; + goto close; + } + // attributes extension + for( i=0; i<sA->length; i++) { + if( sA->array[i] != NULL && bi_length(sA->array[i]) > bits) { + LogError( "Verification of sA[%d] failed - Step 6.c.ii", i); + result = TSS_E_INTERNAL_ERROR; + goto close; + } + } + bits = DAA_PARAM_SIZE_INTERVAL_EXPONENT_CERTIFICATE + + DAA_PARAM_SAFETY_MARGIN + DAA_PARAM_SIZE_MESSAGE_DIGEST + 1; + if( bi_length( signature->sE) > bits) { + LogError("Verification of sE failed - Step 6.c.iii"); + result = TSS_E_INTERNAL_ERROR; + goto close; + } + // step 4 + // TODO: implement revocation list + *isCorrect = TRUE; +close: + bi_free_ptr( tmp1); + if( ch != NULL) free( ch); + if( hash != NULL) free( hash); + free_TSS_DAA_PK_internal( issuer_pk); + free_TSS_DAA_SIGNATURE_internal( signature); + // n not allocated, refere to issuer_pk->modulus + FREE_BI( c); + // capital_gamma not allocated, refere to issuer_pk->capitalGamma + FREE_BI( zeta_2_verify); + // capital_z not allocated, refere to issuer_pk->capitalZ + // capital_R not allocated, refere to issuer_pk->capitalY + FREE_BI( product_r); + FREE_BI( exp); + FREE_BI( capital_THat); + // beta_tilde kept on TSS_DAA_ATTRIB_COMMIT + FREE_BI( gamma_i); + FREE_BI( capital_nv); + FREE_BI( capital_ntilde_v); + FREE_BI( pseudonym_projected); + FREE_BI( s_tau); + // delta_tilde1 kept on CS_ENCRYPTION_RESULT + // delta_tilde2 kept on CS_ENCRYPTION_RESULT + // delta_tilde3 kept on CS_ENCRYPTION_RESULT + // delta_tilde4 kept on CS_ENCRYPTION_RESULT + return result; +} diff --git a/src/tspi/daa/test_sign.c b/src/tspi/daa/test_sign.c new file mode 100644 index 0000000..2b13791 --- /dev/null +++ b/src/tspi/daa/test_sign.c @@ -0,0 +1,238 @@ + +/* + * Licensed Materials - Property of IBM + * + * trousers - An open source TCG Software Stack + * + * (C) Copyright International Business Machines Corp. 2006 + * + */ + +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#include "daa_structs.h" +#include "trousers/tss.h" +#include "trousers/trousers.h" +#include "spi_internal_types.h" +#include "spi_utils.h" +#include "obj.h" +#include "tsplog.h" +#include "daa_parameter.h" +#include "verifier.h" +#include "platform.h" + +// for RSA Key +#include <openssl/rsa.h> + +#define DEFAULT_CREDENTIAL_FILENAME "credential.txt" +#define DEFAULT_OWN_PASSWD "OWN_PWD" + +int print_usage(char *exec) { + fprintf(stderr, "usage: %s\n", exec); + fprintf(stderr, + "\t-m,\t--message\n\t\tif define, the data is signed using this message\n\ +\t\totherwise an AIK will be generated and used\n"); + fprintf(stderr, + "\t-pw,\t--passwd\n\t\ttpm owner password (default: %s)\n", + DEFAULT_OWN_PASSWD); + fprintf(stderr, + "\t-cr,\t--credential\n\t\tcredential filename (default: %s)\n", + DEFAULT_CREDENTIAL_FILENAME); + return -1; +} + +int main(int argc, char *argv[]) { + TSS_HCONTEXT hContext; + TSS_RESULT result; + TSS_HTPM hTPM; + TSS_HPOLICY hPolicy; + char *credential_filename = DEFAULT_CREDENTIAL_FILENAME; + UINT32 nonceVerifierLength; + BYTE *nonceVerifier; + TSS_HDAA hDAA; + TSS_DAA_CREDENTIAL *hDaaCredential; + TSS_DAA_SIGN_DATA signData; + TSS_DAA_SIGNATURE daaSignature; + TSS_DAA_SELECTED_ATTRIB revealAttributes; + char *szTpmPasswd = DEFAULT_OWN_PASSWD; + char *message = NULL; + BYTE **attributes = NULL; + FILE *file; + char *param; + int i, length, rv; + bi_ptr random = NULL; + TSS_BOOL isCorrect; + EVP_MD_CTX mdctx; + TSS_HKEY hKEY; + + init_tss_version( &signData); + init_tss_version( &daaSignature); + init_tss_version( &revealAttributes); + i = 1; + while( i < argc) { + param = argv[ i]; + if ( strcmp( param, "-m") == 0 || strcmp( param, "--message") == 0) { + i++; + if( i == argc) return print_usage( argv[0]); + message = argv[i]; + } else if( strcmp( param, "-cr") == 0 || strcmp( param, "--credential") == 0){ + i++; + if( i == argc) return print_usage( argv[0]); + credential_filename = argv[i]; + } else if( strcmp( param, "-pw") == 0 || strcmp( param, "--passwd") == 0){ + i++; + if( i == argc) return print_usage( argv[0]); + szTpmPasswd = argv[i]; + } else { + fprintf(stderr, "%s:unrecognized option `%s'\n", argv[0], param); + return print_usage( argv[0]); + } + i++; + } + bi_init( NULL); + printf("Loading credential: %s ", credential_filename); + file = fopen( credential_filename, "r"); + if( (hDaaCredential = load_TSS_DAA_CREDENTIAL( file)) == 0) { + LogError( "[test_join]: Error when loading \'%s\': %s\n", + credential_filename, + strerror( errno)); + result = TSS_E_FAIL; + goto out_close; + } + fclose( file); + printf("Done\n"); + + // Create Context + LogDebug("Create Context"); + result = Tspi_Context_Create( &hContext ); + if ( result != TSS_SUCCESS ) + { + LogError( "Tspi_Context_Create %d\n", result ); + goto out; + } + // Connect to Context + result = Tspi_Context_Connect( hContext, NULL ); + if ( result != TSS_SUCCESS) goto out_close; + printf("\nConnect to the context: %X\n", hContext); + + if( (result = Tspi_Context_GetTpmObject( hContext, &hTPM)) != TSS_SUCCESS) + goto out_close; + // Get the correct policy using the TPM ownership PASSWD + if( (result = Tspi_GetPolicyObject( hTPM, TSS_POLICY_USAGE, &hPolicy)) != TSS_SUCCESS) + goto out_close; + if( (result = Tspi_Policy_SetSecret( hPolicy, + TSS_SECRET_MODE_PLAIN, + strlen( szTpmPasswd), + szTpmPasswd)) != TSS_SUCCESS) + goto out_close; + LogDebug("Tspi_Policy_SetSecret hPolicy received;%d", hPolicy); + + //Create Object + result = obj_daa_add( hContext, &hDAA); + if (result != TSS_SUCCESS) { + LogError("Tspi_Context_CreateObject:%d", result); + Tspi_Context_Close(hContext); + LogError("%s: %s", argv[0], err_string(result)); + exit(result); + } + LogDebug("created DAA object:%X", hDAA); + + // TODO: verifier base name ?? + result = Tspi_DAA_VerifyInit( + hDAA, // in + &nonceVerifierLength, // out + &nonceVerifier, // out + 0, //baseNameLength, // out + NULL //baseName // out + ); + if (result != TSS_SUCCESS) goto out_close; + LogDebug("Verify Init return nonceVerifier [%s]", + dump_byte_array( nonceVerifierLength, nonceVerifier)); + + create_TSS_DAA_SELECTED_ATTRIB( &revealAttributes, 5, 0, 1, 1, 0, 0); + + // create the TSS_DAA_SIGN_DATA struct + // .selector: 0 -> payload contains a handle to an AIK + // 1 -> payload contains a hashed message + if( message != NULL) { + signData.selector = TSS_FLAG_DAA_SIGN_MESSAGE_HASH; + signData.payloadFlag = TSS_FLAG_DAA_SIGN_MESSAGE_HASH; + EVP_DigestInit(&mdctx, DAA_PARAM_get_message_digest()); + EVP_DigestUpdate(&mdctx, (BYTE *)message, strlen( message)); + signData.payloadLength = EVP_MD_CTX_size(&mdctx); + signData.payload = (BYTE *)malloc( EVP_MD_CTX_size(&mdctx)); + EVP_DigestFinal(&mdctx, signData.payload, NULL); + } else { + signData.selector = TSS_FLAG_DAA_SIGN_IDENTITY_KEY; + result = Tspi_Context_CreateObject( + hContext, // in + TSS_OBJECT_TYPE_RSAKEY, // in + TSS_KEY_SIZE_2048, // in + &hKEY // out + ); + if( result != TSS_SUCCESS) goto out_close; + + } + + result = Tspi_TPM_DAA_Sign( + hDAA, // in + hTPM, // in + (TSS_HKEY)hDaaCredential, // in + revealAttributes, // in + 0, // verifierBaseNameLength, // in + NULL, // verifierBaseName, // in + nonceVerifierLength, // in + nonceVerifier, // in + signData, // in + &daaSignature // out + ); + if (result != TSS_SUCCESS) goto out_close; + LogDebug("TPM_DAA_Sign return daaSignature [%s]", + dump_byte_array( nonceVerifierLength, nonceVerifier)); + + // generate attributes list but without copying the not revealed ones + attributes = malloc( sizeof(BYTE *) * hDaaCredential->attributesLength); + for( i=0; i < (int)(hDaaCredential->attributesLength); i++) { + if( revealAttributes.indicesList[i]) { + attributes[i] = (BYTE *)malloc( DAA_PARAM_SIZE_F_I / 8); + memcpy( attributes[i], + hDaaCredential->attributes[i], + DAA_PARAM_SIZE_F_I / 8); + } else { + attributes[i] = NULL; + } + } + + result = Tspi_DAA_VerifySignature( + hDAA, // in + daaSignature, // in + (TSS_HKEY)&(hDaaCredential->issuerPK), // in + signData, // in + hDaaCredential->attributesLength, // in + attributes, // in + nonceVerifierLength, // in + nonceVerifier, // in + 0, //baseNameLength, //in + NULL, // in + &isCorrect // out + ); + printf("Signature correct:%s\n", ( isCorrect ? "yes" : "no")); + +out_close: + if( attributes != NULL) { + for( i=0; i<(int)hDaaCredential->attributesLength; i++) { + if( attributes[i] != NULL) free( attributes[i]); + } + free( attributes); + } + if( random != NULL) bi_free_ptr( random); + Tspi_Context_FreeMemory( hContext, NULL ); + Tspi_Context_Close( hContext ); +out: + bi_release(); + LogDebug("THE END result=%d:%s",result, err_string( result) );; + return result; +} + diff --git a/src/tspi/daa/utils/list.c b/src/tspi/daa/utils/list.c new file mode 100644 index 0000000..634129b --- /dev/null +++ b/src/tspi/daa/utils/list.c @@ -0,0 +1,66 @@ + +/* +* Licensed Materials - Property of IBM +* +* trousers - An open source TCG Software Stack +* +* (C) Copyright International Business Machines Corp. 2006 +* +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <list.h> + +#include "tsplog.h" + +list_ptr list_new( void) { + list_ptr list = (list_ptr)malloc( sizeof( list_struct)); + + if( list == NULL) return NULL; + list->head = NULL; + return list; +} + +void list_add(list_ptr list, void *obj) { + list->current = (node_t *) malloc (sizeof(struct _list_t)); + if (list->current == NULL) { + LogError("[list_add] malloc of %d bytes failed", sizeof(struct _list_t)); + return; + } + if( list->head == NULL) { + list->head = list->current; + } else + list->previous->next = list->current; + list->current->obj = obj; + list->current->next = NULL; + list->previous = list->current; +} + +void list_dump(list_ptr list) { + node_t *current; + + if( list->head == NULL) // if head has not been altered + puts("no data"); // list is empty + else { + current = list->head; // go to first node + do { + printf("%d\n", (int)current->obj); // print value at current node + current = current->next; // traverse through the list + } while(current != NULL); // until current node is NULL + } +} + +void list_freeall(list_ptr list) { + node_t *current = list->head; // go to first node + node_t *next; + + if( list->head != NULL) { + current = list->head; // go to first node + do { + next = current->next; + free(current); + current = next; + } while(current != NULL); // until current node is NULL + } +} |