Home | History | Annotate | Line # | Download | only in daa_issuer
      1 /*
      2  * Licensed Materials - Property of IBM
      3  *
      4  * trousers - An open source TCG Software Stack
      5  *
      6  * (C) Copyright International Business Machines Corp. 2006
      7  *
      8  */
      9 
     10 #include <stdlib.h>
     11 #include <stdio.h>
     12 #include <string.h>
     13 
     14 // for little-big endian conversion
     15 #include <arpa/inet.h>
     16 // for message digest
     17 #include <openssl/evp.h>
     18 
     19 #include "bi.h"
     20 
     21 #include "daa_parameter.h"
     22 #include "list.h"
     23 #include "daa_structs.h"
     24 
     25 #include "issuer.h"
     26 
     27 //standard bit length extension to obtain a uniformly distributed number [0,element]
     28 static const int SAFETY_PARAM = 80;
     29 
     30 static bi_array_ptr get_generators( const TSS_DAA_PK_internal *pk) {
     31 	bi_array_ptr result = ALLOC_BI_ARRAY();
     32 	int i;
     33 
     34 	bi_new_array( result, 3 + pk->capitalY->length );
     35 	for(i = 0; i<result->length; i++) {
     36 		result->array[i] = pk->capitalS;
     37 	}
     38 	return result;
     39 }
     40 
     41 static bi_array_ptr get_verifiable_numbers( const TSS_DAA_PK_internal *pk) {
     42 	bi_array_ptr result = ALLOC_BI_ARRAY();
     43 	int i;
     44 
     45 	bi_new_array( result, 3 + pk->capitalY->length);
     46 	result->array[0] = pk->capitalZ;
     47 	result->array[1] = pk->capitalR0;
     48 	result->array[2] = pk->capitalR1;
     49 	// CAPITAL Y ( capitalRReceiver + capitalRIssuer)
     50 	for( i=0; i<pk->capitalY ->length; i++)
     51 		result->array[ 3+i] = pk->capitalY->array[i];
     52 	return result;
     53 }
     54 
     55 /* computes an array of random numbers in the range of [1,element] */
     56 void compute_random_numbers( bi_array_ptr result, int quantity, const bi_ptr element) {
     57 	int i=0;
     58 
     59 	for( i=0; i<quantity; i++) {
     60 		compute_random_number( result->array[i], element);
     61 		bi_inc( result->array[i]);							// array[i]++
     62 	}
     63 }
     64 
     65 int test_bit( int pos, BYTE* array, int length) {
     66 	return (((int)array[ length - (pos / 8) - 1]) & (1 << (pos % 8))) != 0;
     67 }
     68 
     69 void toByteArray( BYTE *result, int length, bi_ptr bi, char *logMsg) {
     70 	LogDebug("-> toByteArray <%d> %s",(int)bi, logMsg);
     71 	LogDebug("lenghts <%d|%d>",length, (int)bi_nbin_size(bi));
     72 	bi_2_byte_array( result, length, bi);
     73 	LogDebug("<- toByteArray result=%s [<%d|%d>] ",
     74 		dump_byte_array( length, result),
     75 		length,
     76 		(int)bi_nbin_size(bi));
     77 }
     78 
     79 /*
     80 Compute the message digest used in the proof. (from DAA_Param, the digest
     81 algorithm is RSA, but this is not available in openssl, the successor of RSA is SHA1
     82 */
     83 TSS_RESULT
     84 generateMessageDigest(BYTE *md_value,
     85 			int *md_len,
     86 			const TSS_DAA_PK_internal *pk,
     87 			bi_array_ptr *commitments,
     88 			const int commitments_size
     89 ) {
     90 	EVP_MD_CTX *mdctx;
     91 	const EVP_MD *md;
     92 	int i, j;
     93 	int length = DAA_PARAM_SIZE_RSA_MODULUS / 8;
     94 	BYTE *array;
     95 
     96 	// 10000 to be sure, and this memory will be released quite quickly
     97 	array = (BYTE *)malloc( 10000);
     98 	if (array == NULL) {
     99 		LogError("malloc of %d bytes failed", 10000);
    100 		return TSPERR(TSS_E_OUTOFMEMORY);
    101 	}
    102 	OpenSSL_add_all_digests();
    103 	md = EVP_get_digestbyname( DAA_PARAM_MESSAGE_DIGEST_ALGORITHM);
    104 	EVP_MD_CTX_create(mdctx);
    105 	EVP_DigestInit_ex(mdctx, md, NULL);
    106 #ifdef DAA_DEBUG
    107 	fprintf(stderr, "modulus=%s\n", bi_2_hex_char( pk->modulus));
    108 #endif
    109 	toByteArray( array, length, pk->modulus,
    110 			"!! [generateMessageDigest modulus] current_size=%d  length=%d\n");
    111 	EVP_DigestUpdate(mdctx, array , length);
    112 	toByteArray( array, length, pk->capitalS,
    113 			"!! [generateMessageDigest capitalS] current_size=%d  length=%d\n");
    114 	EVP_DigestUpdate(mdctx, array , length);
    115 	// add capitalZ, capitalR0, capitalR1, capitalY
    116 	LogDebug("capitalZ capitalR0 capitalY");
    117 	toByteArray( array, length, pk->capitalZ,
    118 			"!! [generateMessageDigest capitalZ] current_size=%d  length=%d\n");
    119 	EVP_DigestUpdate(mdctx, array , length);
    120 	toByteArray( array, length, pk->capitalR0,
    121 			"!! [generateMessageDigest capitalR0] current_size=%d  length=%d\n");
    122 	EVP_DigestUpdate(mdctx, array , length);
    123 	toByteArray( array, length, pk->capitalR1,
    124 			"!! [generateMessageDigest capitalR1] current_size=%d  length=%d\n");
    125 	EVP_DigestUpdate(mdctx, array , length);
    126 	// CAPITAL Y ( capitalRReceiver )
    127 	LogDebug("capitalRReceiver");
    128 	for( i=0; i<pk->capitalRReceiver->length; i++) {
    129 		toByteArray( array, length, pk->capitalRReceiver->array[i],
    130 			"!![generateMessageDigest capitalRReceiver] current_size=%d  length=%d\n");
    131 		EVP_DigestUpdate(mdctx, array , length);
    132 	}
    133 	LogDebug("capitalRIssuer");
    134 	// CAPITAL Y ( capitalRIssuer)
    135 	for( i=0; i<pk->capitalRIssuer->length; i++) {
    136 		toByteArray( array, length, pk->capitalRIssuer->array[i],
    137 			"!![generateMessageDigest capitalRReceiver] current_size=%d  length=%d\n");
    138 		EVP_DigestUpdate(mdctx, array , length);
    139 	}
    140 	LogDebug("commitments");
    141 	for( i=0; i<commitments_size; i++) {
    142 		for( j=0; j<commitments[i]->length; j++) {
    143 			toByteArray( array, length, commitments[i]->array[j],
    144 			"!! [generateMessageDigest commitments] current_size=%d  length=%d\n");
    145 			EVP_DigestUpdate(mdctx, array , length);
    146 		}
    147 	}
    148 	EVP_DigestFinal_ex(mdctx, md_value, md_len);
    149 	EVP_MD_CTX_destroy(mdctx);
    150 	free( array);
    151 	return TSS_SUCCESS;
    152 }
    153 
    154 int is_range_correct( bi_ptr b, bi_ptr range) {
    155 	return bi_cmp( b, range) < 0 && bi_cmp( b, bi_0) >= 0;
    156 }
    157 
    158 /*
    159 Verifies if the parameters Z,R0,R1,RReceiver and RIssuer of the public key
    160 were correctly computed.
    161 pk: the public key, which one wants to verfy.
    162 */
    163 TSS_RESULT
    164 is_pk_correct( TSS_DAA_PK_internal *public_key,
    165 		TSS_DAA_PK_PROOF_internal *proof,
    166 		int *isCorrect
    167 ) {
    168 	int bit_size_message_digest = DAA_PARAM_SIZE_MESSAGE_DIGEST;
    169 	bi_ptr n = public_key->modulus;
    170 	int num_of_variables;
    171 	int i,j;
    172 	TSS_RESULT result = TSS_SUCCESS;
    173 	BYTE verifiable_challenge[EVP_MAX_MD_SIZE];
    174 	int length_challenge;
    175 	bi_array_ptr verifiable_numbers;
    176 	bi_array_ptr *verification_commitments = NULL;
    177 	bi_array_ptr generators = NULL;
    178 	bi_t tmp;
    179 	bi_t tmp1;
    180 #ifdef DAA_DEBUG
    181 	FILE *f;
    182 	bi_array_ptr *commitments;
    183 #endif
    184 
    185 	bi_new( tmp);
    186 	bi_new( tmp1);
    187 	*isCorrect = 0;
    188 #ifdef DAA_DEBUG
    189 	f=fopen("/tmp/commits", "r");
    190 	commitments = (bi_array_ptr *)malloc( sizeof(bi_array_ptr) * num_of_variables);
    191 	if (commitments == NULL) {
    192 		LogError("malloc of %d bytes failed", sizeof(bi_array_ptr) * num_of_variables);
    193 		result = TSPERR(TSS_E_OUTOFMEMORY);
    194 		goto close;
    195 	}
    196 	for( i=0; i<num_of_variables; i++) {
    197 		commitments[i] = ALLOC_BI_ARRAY();
    198 		BI_LOAD_ARRAY( commitments[i], f);
    199 	}
    200 	fclose(f);
    201 	DUMP_BI( n);
    202 #endif
    203 	LogDebug("STEP 1 ( Tspi_DAA_IssuerKeyVerification spec.)");
    204 	if( !bi_is_probable_prime( public_key->capitalGamma)) {
    205 		LogError( "pk->capitalGamma not prime\ncapitalGamma=\n%s",
    206 				bi_2_hex_char( public_key->capitalGamma));
    207 		result = TSS_E_BAD_PARAMETER;
    208 		goto close;
    209 	}
    210 	if( !bi_is_probable_prime( public_key->rho)) {
    211 		LogError( "pk->rho not prime\nrho=\n%s",
    212 				bi_2_hex_char( public_key->rho));
    213 		result = TSS_E_BAD_PARAMETER;
    214 		goto close;
    215 	}
    216 	// (capitalGamma - 1) %  rho should be equal to 0
    217 	if( !bi_equals( bi_mod( tmp1, bi_sub( tmp1, public_key->capitalGamma, bi_1),
    218 				public_key->rho),
    219 			bi_0)) {
    220 		LogError( "(capitalGamma - 1) %%  rho != 0\nActual value:\n%s",
    221 				bi_2_hex_char( tmp1));
    222 		result = TSS_E_BAD_PARAMETER;
    223 	}
    224 	// (gamma ^ rho) % capitalGamma should be equals to 1
    225 	if ( !bi_equals( bi_mod_exp( tmp1, public_key->gamma,
    226 						public_key->rho,
    227 						public_key->capitalGamma),
    228 				bi_1) ) {
    229 		LogError( "(gamma ^ rho) %% capitalGamma != 1\nActual value:\n%s",
    230 				bi_2_hex_char( tmp1));
    231 		result = TSS_E_BAD_PARAMETER;
    232 		goto close;
    233 	}
    234 	// (gamma ^ rho) % capitalGamma should be equal to 1
    235 	if ( !bi_equals( bi_mod_exp( tmp1,
    236 						public_key->gamma,
    237 						public_key->rho,
    238 						public_key->capitalGamma),
    239 				bi_1) ) {
    240 		LogError( "(gamma ^ rho) %% capitalGamma != 1\nActual value:\n%s",
    241 				bi_2_hex_char( tmp1));
    242 		result = TSS_E_BAD_PARAMETER;
    243 		goto close;
    244 	}
    245 	LogDebug("STEP 2 check whether all public key parameters have the required length");
    246 	if( bi_nbin_size( n) != DAA_PARAM_SIZE_RSA_MODULUS / 8) {
    247 		LogError( "size( n)[%ld] != DAA_PARAM_SIZE_RSA_MODULUS[%d]",
    248 			bi_nbin_size( n),
    249 			DAA_PARAM_SIZE_RSA_MODULUS / 8);
    250 		result = TSS_E_BAD_PARAMETER;
    251 		goto close;
    252 	}
    253 	if( bi_cmp( n, bi_shift_left( tmp1, bi_1, DAA_PARAM_SIZE_RSA_MODULUS))
    254 		>= 0) {
    255 		LogError( "n[%ld] != DAA_PARAM_SIZE_RSA_MODULUS[%d]",
    256 			bi_nbin_size( n),
    257 			DAA_PARAM_SIZE_RSA_MODULUS);
    258 		result = TSS_E_BAD_PARAMETER;
    259 		goto close;
    260 	}
    261 	if( bi_cmp( n, bi_shift_left( tmp1, bi_1, DAA_PARAM_SIZE_RSA_MODULUS - 1 ))
    262 		<= 0) {
    263 		LogError( "n[%ld] != DAA_PARAM_SIZE_RSA_MODULUS[%d]",
    264 			bi_nbin_size( n),
    265 			DAA_PARAM_SIZE_RSA_MODULUS);
    266 		result = TSS_E_BAD_PARAMETER;
    267 		goto close;
    268 	}
    269 	// rho
    270 	if( bi_nbin_size( public_key->rho) * 8 != DAA_PARAM_SIZE_RHO) {
    271 		LogError( "size( rho)[%ld] != DAA_PARAM_SIZE_RHO[%d]",
    272 			bi_nbin_size( public_key->rho) * 8,
    273 			DAA_PARAM_SIZE_RHO);
    274 		result = TSS_E_BAD_PARAMETER;
    275 		goto close;
    276 	}
    277 	// Gamma
    278 	if( bi_nbin_size( public_key->capitalGamma) * 8 != DAA_PARAM_SIZE_MODULUS_GAMMA) {
    279 		LogError( "size( rho)[%ld] != DAA_PARAM_SIZE_MODULUS_GAMMA[%d]",
    280 			bi_nbin_size( public_key->capitalGamma) * 8,
    281 			DAA_PARAM_SIZE_MODULUS_GAMMA);
    282 		result = TSS_E_BAD_PARAMETER;
    283 		goto close;
    284 	}
    285 	if( is_range_correct( public_key->capitalS, n) == 0) {
    286 		LogError( "range not correct( pk->capitalS)\ncapitalS=\n%s\nn=\n%s",
    287 			bi_2_hex_char( public_key->capitalS),
    288 			bi_2_hex_char( n));
    289 		result = TSS_E_BAD_PARAMETER;
    290 		goto close;
    291 	}
    292 	if( is_range_correct( public_key->capitalZ, n) == 0) {
    293 		LogError( "range not correct( pk->capitalZ)\ncapitalZ=\n%s\nn=\n%s",
    294 			bi_2_hex_char( public_key->capitalZ),
    295 			bi_2_hex_char( n));
    296 		result = TSS_E_BAD_PARAMETER;
    297 		goto close;
    298 	}
    299 	if( is_range_correct( public_key->capitalR0, n) == 0) {
    300 		LogError( "range not correct( pk->capitalR0)\ncapitalR0=\n%s\nn=\n%s",
    301 			bi_2_hex_char( public_key->capitalR0),
    302 			bi_2_hex_char( n));
    303 		result = TSS_E_BAD_PARAMETER;
    304 		goto close;
    305 	}
    306 	if( is_range_correct( public_key->capitalR1, n) == 0) {
    307 		LogError( "range not correct( pk->capitalR1)\ncapitalR1=\n%s\nn=\n%s",
    308 			bi_2_hex_char( public_key->capitalR1),
    309 			bi_2_hex_char( n));
    310 		result = TSS_E_BAD_PARAMETER;
    311 		goto close;
    312 	}
    313 	for( i=0; i<public_key->capitalY->length; i++) {
    314 		if( is_range_correct( public_key->capitalY->array[i], n) == 0) {
    315 			LogError( "range not correct(pk->capitalY[%d])\ncapitalY[%d]=\n%s\nn=\n%s",
    316 				i, i,
    317 				bi_2_hex_char( public_key->capitalY->array[i]),
    318 				bi_2_hex_char( n));
    319 			result = TSS_E_BAD_PARAMETER;
    320 			goto close;
    321 		}
    322 	}
    323 	LogDebug("STEP 3 - compute verification commitments");
    324 	// only the array is allocated, but all refs are  pointing to public_key numbers
    325 	generators = get_generators( public_key);
    326 	verifiable_numbers = get_verifiable_numbers( public_key);
    327 	num_of_variables = verifiable_numbers->length;
    328 	verification_commitments = (bi_array_ptr *)malloc( sizeof(bi_array_ptr)*num_of_variables);
    329 	if (verification_commitments == NULL) {
    330 		LogError("malloc of %d bytes failed", sizeof(bi_array_ptr)*num_of_variables);
    331 		result = TSPERR(TSS_E_OUTOFMEMORY);
    332 		goto close;
    333 	}
    334 	for( i = 0; i<num_of_variables; i++) {
    335 		verification_commitments[i] = ALLOC_BI_ARRAY();
    336 		bi_new_array( verification_commitments[i], bit_size_message_digest);
    337 		for( j = 0; j<bit_size_message_digest; j++) {
    338 #ifdef DAA_DEBUG
    339 			printf( "[# i=%d j=%d test_bit:%d]",
    340 				i, j, test_bit( j, proof->challenge, proof->length_challenge));
    341 #endif
    342 			bi_mod_exp( verification_commitments[i]->array[j],
    343 				generators->array[i],
    344 				proof->response[i]->array[j], n);
    345 			if( test_bit( j, proof->challenge, proof->length_challenge)) {
    346 				bi_mul( verification_commitments[i]->array[j],
    347 					verification_commitments[i]->array[j],
    348 					verifiable_numbers->array[i]);
    349 #ifdef DAA_DEBUG
    350 				DUMP_BI( verification_commitments[i]->array[j]);
    351 #endif
    352 				bi_mod( verification_commitments[i]->array[j],
    353 					verification_commitments[i]->array[j],
    354 					n);
    355 			}
    356 #ifdef DAA_DEBUG
    357 			if( commitments != NULL &&
    358 				bi_equals( verification_commitments[i]->array[j],
    359 						commitments[i]->array[j]) ==0) {
    360 				LogError( "!! ERROR i=%d j=%d\n", i, j);
    361 				DUMP_BI( commitments[i]->array[j]);
    362 				DUMP_BI( verification_commitments[i]->array[j]);
    363 				DUMP_BI( generators->array[i]);
    364 				DUMP_BI( proof->response[i]->array[j]);
    365 				DUMP_BI( verifiable_numbers->array[i]);
    366 			}
    367 			printf( "o"); fflush( stdout);
    368 #endif
    369 		}
    370 	}
    371 	// STEP 3 - d
    372 	generateMessageDigest( verifiable_challenge,
    373 						&length_challenge,
    374 						public_key,
    375 						verification_commitments,
    376 						num_of_variables);
    377 	LogDebug("verifiable challenge=%s",
    378 			dump_byte_array( length_challenge, verifiable_challenge));
    379 	LogDebug("           challenge=%s",
    380 			dump_byte_array( proof->length_challenge, proof->challenge));
    381 	if( length_challenge != proof->length_challenge) {
    382 		result = TSS_E_BAD_PARAMETER;
    383 		goto close;
    384 	}
    385 	for( i=0; i<length_challenge; i++) {
    386 		if( verifiable_challenge[i] != proof->challenge[i]) {
    387 			result = TSS_E_BAD_PARAMETER;
    388 			goto close;
    389 		}
    390 	}
    391 	*isCorrect = ( memcmp( verifiable_challenge, proof->challenge, length_challenge) == 0);
    392 close:
    393 	if( verification_commitments != NULL) {
    394 		for( i = 0; i<num_of_variables; i++) {
    395 			bi_free_array( verification_commitments[i]);
    396 		}
    397 		free( verification_commitments);
    398 	}
    399 	if( generators != NULL) free( generators);
    400 	bi_free( tmp1);
    401 	bi_free( tmp);
    402 	return result;
    403 }
    404 
    405 
    406 TSS_DAA_PK_PROOF_internal *generate_proof(const bi_ptr product_PQ_prime,
    407 					const TSS_DAA_PK_internal *public_key,
    408 					const bi_ptr xz,
    409 					const bi_ptr x0,
    410 					const bi_ptr x1,
    411 					bi_array_ptr x
    412 ) {
    413 	int i, j;
    414 	bi_array_ptr generators = get_generators( public_key);
    415 	bi_ptr n = public_key->modulus;
    416 	int num_of_variables;
    417 	int bit_size_message_digest = DAA_PARAM_SIZE_MESSAGE_DIGEST;
    418 	bi_array_ptr *xTildes = NULL;
    419 	BYTE *challenge_param;
    420 
    421 	bi_array_ptr exponents = ALLOC_BI_ARRAY();
    422 	bi_new_array2( exponents, 3 + x->length);
    423 	exponents->array[0] = xz; 	exponents->array[1] = x0; exponents->array[2] = x1;
    424 	bi_copy_array( x, 0, exponents, 3, x->length);
    425 	num_of_variables = exponents->length;
    426 	LogDebug("Step a - choose random numbers");
    427 	LogDebug("\nchoose random numbers\n");
    428 	xTildes = (bi_array_ptr *)malloc( sizeof(bi_array_ptr) * num_of_variables);
    429 	if (xTildes == NULL) {
    430 		LogError("malloc of %d bytes failed", sizeof(bi_array_ptr) * num_of_variables);
    431 		return NULL;
    432 	}
    433 	for( i=0; i<num_of_variables; i++) {
    434 #ifdef DAA_DEBUG
    435 		printf("*");
    436 		fflush(stdout);
    437 #endif
    438 		xTildes[i] = ALLOC_BI_ARRAY();
    439 		bi_new_array( xTildes[i], bit_size_message_digest);
    440 		compute_random_numbers( xTildes[i], bit_size_message_digest, product_PQ_prime);
    441 	}
    442 	// Compute commitments
    443 	LogDebug("\ncompute commitments");
    444 	bi_array_ptr *commitments =
    445 		(bi_array_ptr *)malloc( sizeof(bi_array_ptr) * num_of_variables);
    446 	if (commitments == NULL) {
    447 		LogError("malloc of %d bytes failed", sizeof(bi_array_ptr) * num_of_variables);
    448 		return NULL;
    449 	}
    450 	for( i=0; i<num_of_variables; i++) {
    451 		commitments[i] = ALLOC_BI_ARRAY();
    452 		bi_new_array( commitments[i], bit_size_message_digest);
    453 		for( j=0; j<bit_size_message_digest; j++) {
    454 #ifdef DAA_DEBUG
    455 			printf("#");
    456 			fflush(stdout);
    457 #endif
    458 			bi_mod_exp( commitments[i]->array[j],
    459 				generators->array[i],
    460 				xTildes[i]->array[j],
    461 				n);
    462 		}
    463 	}
    464 #ifdef DAA_DEBUG
    465 	FILE *f=fopen("/tmp/commits", "w");
    466 	for( i=0; i<num_of_variables; i++) {
    467 		BI_SAVE_ARRAY( commitments[i], f);
    468 	}
    469 	fclose(f);
    470 #endif
    471 	LogDebug("Step b: compute challenge (message digest)");
    472 	BYTE challenge[EVP_MAX_MD_SIZE];
    473 	int length_challenge;
    474 	generateMessageDigest( challenge,
    475 				&length_challenge,
    476 				public_key,
    477 				commitments,
    478 				num_of_variables);
    479 	//     STEP c - compute response
    480 	LogDebug("Step c: compute response\n");
    481 	bi_array_ptr *response = (bi_array_ptr *)malloc( sizeof(bi_array_ptr) * num_of_variables);
    482 	if (response == NULL) {
    483 		LogError("malloc of %d bytes failed", sizeof(bi_array_ptr) * num_of_variables);
    484 		return NULL;
    485 	}
    486 	for( i=0; i<num_of_variables; i++) {
    487 		response[i] = ALLOC_BI_ARRAY();
    488 		bi_new_array( response[i], bit_size_message_digest);
    489 		for( j=0; j<bit_size_message_digest; j++) {
    490 			if( test_bit( j, challenge, length_challenge)) {
    491 				bi_sub( response[i]->array[j],
    492 					xTildes[i]->array[j],
    493 					exponents->array[i]);
    494 			} else {
    495 				bi_set( response[i]->array[j],
    496 					xTildes[i]->array[j]);
    497 			}
    498 			bi_mod( response[i]->array[j], response[i]->array[j],  product_PQ_prime);
    499 #ifdef DAA_DEBUG
    500 			printf("#");
    501 			fflush(stdout);
    502 #endif
    503 		}
    504 	}
    505 	challenge_param = (BYTE *)malloc( length_challenge);
    506 	if (challenge_param == NULL) {
    507 		LogError("malloc of %d bytes failed", length_challenge);
    508 		return NULL;
    509 	}
    510 	memcpy( challenge_param, challenge, length_challenge);
    511 
    512 	return create_DAA_PK_PROOF( challenge_param,
    513 					length_challenge,
    514 					response,
    515 					num_of_variables);
    516 }
    517