1723e4046Schristos 
2723e4046Schristos /*
3723e4046Schristos  * Licensed Materials - Property of IBM
4723e4046Schristos  *
5723e4046Schristos  * trousers - An open source TCG Software Stack
6723e4046Schristos  *
7723e4046Schristos  * (C) Copyright International Business Machines Corp. 2006
8723e4046Schristos  *
9723e4046Schristos  */
10723e4046Schristos 
11723e4046Schristos 
12723e4046Schristos #include <stdlib.h>
13723e4046Schristos #include <stdio.h>
14723e4046Schristos #include <string.h>
15723e4046Schristos 
16723e4046Schristos // for message digest
17723e4046Schristos #include <openssl/evp.h>
18723e4046Schristos 
19723e4046Schristos #include <stdlib.h>
20723e4046Schristos #include "daa_structs.h"
21723e4046Schristos #include "daa_parameter.h"
22723e4046Schristos #include "trousers/tss.h"
23723e4046Schristos #include "spi_internal_types.h"
24723e4046Schristos #include "spi_utils.h"
25723e4046Schristos #include <trousers/trousers.h>
26723e4046Schristos #include <spi_utils.h>
27723e4046Schristos #include <obj.h>
28723e4046Schristos #include "tsplog.h"
29723e4046Schristos #include "tss/tcs.h"
30723e4046Schristos #include "platform.h"
31723e4046Schristos // to include compute_zeta
32723e4046Schristos #include "verifier.h"
33723e4046Schristos 
34723e4046Schristos // from UBigInteger (computePrime)
35723e4046Schristos // remark: the type bi_t (bi_ptr) can not used a certaintity for probable_prime
36723e4046Schristos // as used in UbigInteger. (certaintity: DAA_PARAM_SAFETY)
compute_prime(bi_ptr e,int length,int interval)37723e4046Schristos void compute_prime( bi_ptr e, int length, int interval) {
38723e4046Schristos 	do {
39723e4046Schristos 		bi_urandom( e, interval - 1);
40723e4046Schristos 		bi_setbit( e, length - 1);
41723e4046Schristos 	} while( bi_is_probable_prime( e) == 0);
42723e4046Schristos }
43723e4046Schristos 
44723e4046Schristos /*
45723e4046Schristos  code derived from verifyAuthenticity (IssuerTransaction.java)
46723e4046Schristos */
verify_authentificity(TSS_DAA_CREDENTIAL_REQUEST * credentialRequest,TSS_DAA_JOIN_ISSUER_SESSION * joinSession)47723e4046Schristos TSS_RESULT verify_authentificity(TSS_DAA_CREDENTIAL_REQUEST *credentialRequest,
48723e4046Schristos 						TSS_DAA_JOIN_ISSUER_SESSION *joinSession) {
49*0861b331Schristos 	EVP_MD_CTX *mdctx;
50723e4046Schristos 	BYTE *modulus_N0_bytes;
51723e4046Schristos 	BYTE *digest_n0;
52723e4046Schristos 	BYTE *contextHash;
53723e4046Schristos 	BYTE *capitalUPrime_bytes;
54723e4046Schristos 	BYTE *hash;
55723e4046Schristos 	UINT32 digest_n0Length, contextHashLength, hashLength, daaCount;
56723e4046Schristos 	bi_ptr capitalUPrime  =NULL;
57723e4046Schristos 	bi_ptr modulus_N0 = NULL;
58723e4046Schristos 	TSS_RESULT result = TSS_SUCCESS;
59723e4046Schristos 	char *buffer;
60723e4046Schristos 
61723e4046Schristos 	modulus_N0 = bi_new_ptr();
62723e4046Schristos 	buffer = BN_bn2hex( ((RSA *)joinSession->issuerAuthPK)->n);
63723e4046Schristos 	if( buffer == NULL) {
64723e4046Schristos 		LogError("malloc of hexadecimal representation failed");
65723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
66723e4046Schristos 		goto close;
67723e4046Schristos 	}
68723e4046Schristos 	bi_set_as_hex( modulus_N0, buffer);
69723e4046Schristos 	// in TPM, N0 is hashed by hashing the scratch (256 bytes) so it must
70723e4046Schristos 	// be formatted according to the scratch size (TPM_DAA_SIZE_issuerModulus)
71723e4046Schristos 	modulus_N0_bytes = (BYTE *)malloc( TPM_DAA_SIZE_issuerModulus);
72723e4046Schristos 	if (modulus_N0_bytes == NULL) {
73723e4046Schristos 		LogError("malloc of %d bytes failed", TPM_DAA_SIZE_issuerModulus);
74723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
75723e4046Schristos 		goto close;
76723e4046Schristos 	}
77723e4046Schristos 	bi_2_byte_array( modulus_N0_bytes, TPM_DAA_SIZE_issuerModulus, modulus_N0);
78723e4046Schristos 	bi_free_ptr( modulus_N0);
79723e4046Schristos 
80723e4046Schristos 	if( TPM_DAA_SIZE_issuerModulus * 8 != DAA_PARAM_KEY_SIZE) {
81723e4046Schristos 		LogError("TPM_DAA_SIZE_issuerModulus * 8 (%d) != DAA_PARAM_KEY_SIZE(%d)",
82723e4046Schristos 			 TPM_DAA_SIZE_issuerModulus*8, DAA_PARAM_KEY_SIZE);
83723e4046Schristos 		return TSS_E_INTERNAL_ERROR;
84723e4046Schristos 	}
85*0861b331Schristos 	mdctx = EVP_MD_CTX_create();
86*0861b331Schristos 	EVP_DigestInit(mdctx, DAA_PARAM_get_message_digest());
87723e4046Schristos 	// digestN0 = hash( modulus_N0) see Appendix B of spec. and TPM join stage 7 and 8
88*0861b331Schristos 	EVP_DigestUpdate(mdctx,  modulus_N0_bytes, TPM_DAA_SIZE_issuerModulus);
89*0861b331Schristos 	digest_n0Length = EVP_MD_CTX_size(mdctx);
90723e4046Schristos 	digest_n0 = (BYTE *)malloc( digest_n0Length);
91723e4046Schristos 	if (digest_n0 == NULL) {
92723e4046Schristos 		LogError("malloc of %d bytes failed", digest_n0Length);
93723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
94723e4046Schristos 		goto close;
95723e4046Schristos 	}
96*0861b331Schristos 	EVP_DigestFinal(mdctx, digest_n0, NULL);
97723e4046Schristos 
98723e4046Schristos 	// test if credentialRequest->authenticationProof =
99723e4046Schristos 	//				H( H( U, daaCount, H(n0), joinSession->nonceEncrypted))
100*0861b331Schristos 	EVP_DigestInit(mdctx, DAA_PARAM_get_message_digest());
101723e4046Schristos 	// enlarge capitalU to 256 (TPM_DAA_SIZE_issuerModulus)
102723e4046Schristos 	 // allocation
103723e4046Schristos 	capitalUPrime = bi_set_as_nbin( joinSession->capitalUprimeLength, joinSession->capitalUprime);
104723e4046Schristos 	capitalUPrime_bytes = (BYTE *)malloc( TPM_DAA_SIZE_issuerModulus);
105723e4046Schristos 	if (capitalUPrime_bytes == NULL) {
106723e4046Schristos 		LogError("malloc of %d bytes failed", TPM_DAA_SIZE_issuerModulus);
107723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
108723e4046Schristos 		goto close;
109723e4046Schristos 	}
110723e4046Schristos 	bi_2_byte_array( capitalUPrime_bytes, TPM_DAA_SIZE_issuerModulus, capitalUPrime);
111*0861b331Schristos 	EVP_DigestUpdate(mdctx,  capitalUPrime_bytes, TPM_DAA_SIZE_issuerModulus);
112723e4046Schristos 	bi_free_ptr( capitalUPrime);
113723e4046Schristos 	daaCount = htonl( joinSession->daaCounter);
114*0861b331Schristos 	EVP_DigestUpdate(mdctx,  &daaCount, sizeof(UINT32));
115*0861b331Schristos 	EVP_DigestUpdate(mdctx,  digest_n0, digest_n0Length);
116*0861b331Schristos 	contextHashLength = EVP_MD_CTX_size(mdctx);
117723e4046Schristos 	contextHash = (BYTE *)malloc( contextHashLength);
118723e4046Schristos 	if (contextHash == NULL) {
119723e4046Schristos 		LogError("malloc of %d bytes failed", contextHashLength);
120723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
121723e4046Schristos 		goto close;
122723e4046Schristos 	}
123*0861b331Schristos 	EVP_DigestFinal(mdctx, contextHash, NULL);
124*0861b331Schristos 	EVP_DigestInit(mdctx, DAA_PARAM_get_message_digest());
125723e4046Schristos 	LogDebug("PK(0).n=%s", dump_byte_array( TPM_DAA_SIZE_issuerModulus, modulus_N0_bytes));
126723e4046Schristos 	LogDebug("digestN0h=%s", dump_byte_array( digest_n0Length, digest_n0));
127723e4046Schristos 	LogDebug("UPrime=%s", dump_byte_array( TPM_DAA_SIZE_issuerModulus, capitalUPrime_bytes));
128723e4046Schristos 	LogDebug("daaCount=%4x", daaCount);
129723e4046Schristos 
130723e4046Schristos 	LogDebug("contextHash[%d]=%s", contextHashLength, dump_byte_array( contextHashLength, contextHash));
131*0861b331Schristos 	EVP_DigestUpdate(mdctx,  contextHash, contextHashLength);
132*0861b331Schristos 	EVP_DigestUpdate(mdctx,  joinSession->nonceEncrypted, joinSession->nonceEncryptedLength);
133*0861b331Schristos 	hashLength = EVP_MD_CTX_size(mdctx);
134723e4046Schristos 	hash = (BYTE *)malloc( hashLength);
135723e4046Schristos 	if (hash == NULL) {
136723e4046Schristos 		LogError("malloc of %d bytes failed", hashLength);
137723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
138723e4046Schristos 		goto close;
139723e4046Schristos 	}
140*0861b331Schristos 	EVP_DigestFinal(mdctx, hash, NULL);
141723e4046Schristos 	if( credentialRequest->authenticationProofLength != hashLength ||
142723e4046Schristos 		memcmp( credentialRequest->authenticationProof, hash, hashLength) != 0) {
143723e4046Schristos 		LogError("Verification of authenticationProof failed - Step 2.b");
144723e4046Schristos 		LogError("credentialRequest->authenticationProof[%d]=%s",
145723e4046Schristos 			credentialRequest->authenticationProofLength,
146723e4046Schristos 			dump_byte_array( credentialRequest->authenticationProofLength,
147723e4046Schristos 				credentialRequest->authenticationProof));
148723e4046Schristos 		LogError("internal cByte[%d]=%s",
149723e4046Schristos 			hashLength,
150723e4046Schristos 			dump_byte_array( hashLength, hash));
151723e4046Schristos 		result = TSS_E_DAA_AUTHENTICATION_ERROR;
152723e4046Schristos 		goto close;
153723e4046Schristos 	} else
154723e4046Schristos 		LogDebug("verify_authenticity Done:%s",
155723e4046Schristos 			dump_byte_array( hashLength, hash));
156723e4046Schristos close:
157*0861b331Schristos 	EVP_MD_CTX_destroy(mdctx);
158723e4046Schristos 	free( contextHash);
159723e4046Schristos 	free( digest_n0);
160723e4046Schristos 	free( capitalUPrime_bytes);
161723e4046Schristos 	free( hash);
162723e4046Schristos 	return result;
163723e4046Schristos }
164723e4046Schristos 
165723e4046Schristos 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)166723e4046Schristos compute_join_challenge_issuer( TSS_DAA_PK_internal *pk_intern,
167723e4046Schristos 							bi_ptr v_prime_prime,
168723e4046Schristos 							bi_ptr capitalA,
169723e4046Schristos 							bi_ptr capital_Atilde,
170723e4046Schristos 							UINT32 nonceReceiverLength,
171723e4046Schristos 							BYTE *nonceReceiver,
172723e4046Schristos 							UINT32 *c_primeLength,
173723e4046Schristos 							BYTE **c_prime) { // out allocation
174*0861b331Schristos 	EVP_MD_CTX *mdctx;
175723e4046Schristos 	BYTE *encoded_pk;
176723e4046Schristos 	BYTE *byte_array;
177723e4046Schristos 	UINT32 encoded_pkLength;
178723e4046Schristos 
179723e4046Schristos 	byte_array = (BYTE *)malloc( DAA_PARAM_SIZE_RND_VALUE_CERTIFICATE / 8); // allocation
180723e4046Schristos 	if (byte_array == NULL) {
181723e4046Schristos 		LogError("malloc of %d bytes failed", DAA_PARAM_SIZE_RND_VALUE_CERTIFICATE / 8);
182723e4046Schristos 		return TSPERR(TSS_E_OUTOFMEMORY);
183723e4046Schristos 	}
184*0861b331Schristos 	mdctx = EVP_MD_CTX_create();
185*0861b331Schristos 	EVP_DigestInit(mdctx, DAA_PARAM_get_message_digest());
186723e4046Schristos 	encoded_pk = encoded_DAA_PK_internal( &encoded_pkLength, pk_intern);
187*0861b331Schristos 	EVP_DigestUpdate(mdctx,  encoded_pk, encoded_pkLength);
188723e4046Schristos 	LogDebug( "issuerPk: %s", dump_byte_array( encoded_pkLength, encoded_pk));
189723e4046Schristos 	bi_2_byte_array( byte_array, DAA_PARAM_SIZE_RND_VALUE_CERTIFICATE / 8, v_prime_prime);
190*0861b331Schristos 	EVP_DigestUpdate(mdctx, byte_array, DAA_PARAM_SIZE_RND_VALUE_CERTIFICATE / 8);
191723e4046Schristos 	LogDebug( "vPrimePrime: %s",
192723e4046Schristos 			dump_byte_array( DAA_PARAM_SIZE_RND_VALUE_CERTIFICATE / 8, byte_array));
193723e4046Schristos 	free( byte_array);
194723e4046Schristos  	// allocation
195723e4046Schristos 	byte_array = (BYTE *)malloc( DAA_PARAM_SIZE_RSA_MODULUS / 8);
196723e4046Schristos 	if (byte_array == NULL) {
197723e4046Schristos 		LogError("malloc of %d bytes failed", DAA_PARAM_SIZE_RSA_MODULUS / 8);
198723e4046Schristos 		return TSPERR(TSS_E_OUTOFMEMORY);
199723e4046Schristos 	}
200723e4046Schristos 	bi_2_byte_array( byte_array, DAA_PARAM_SIZE_RSA_MODULUS / 8, capitalA);
201*0861b331Schristos 	EVP_DigestUpdate(mdctx, byte_array, DAA_PARAM_SIZE_RSA_MODULUS / 8);
202723e4046Schristos 	LogDebug( "capitalA: %s", dump_byte_array( DAA_PARAM_SIZE_RSA_MODULUS / 8, byte_array));
203723e4046Schristos 	bi_2_byte_array( byte_array, DAA_PARAM_SIZE_RSA_MODULUS / 8, capital_Atilde);
204*0861b331Schristos 	EVP_DigestUpdate(mdctx, byte_array, DAA_PARAM_SIZE_RSA_MODULUS / 8);
205723e4046Schristos 	LogDebug( "capital_Atilde: %s",
206723e4046Schristos 			dump_byte_array( DAA_PARAM_SIZE_RSA_MODULUS / 8, byte_array));
207*0861b331Schristos 	EVP_DigestUpdate(mdctx, nonceReceiver, nonceReceiverLength);
208723e4046Schristos 	LogDebug( "nonceReceiver: %s",
209723e4046Schristos 			dump_byte_array( nonceReceiverLength, nonceReceiver));
210*0861b331Schristos 	*c_primeLength = EVP_MD_CTX_size(mdctx);
211723e4046Schristos 	*c_prime = (BYTE *)malloc( *c_primeLength);
212723e4046Schristos 	if (*c_prime == NULL) {
213723e4046Schristos 		LogError("malloc of %d bytes failed", *c_primeLength);
214723e4046Schristos 		free( byte_array);
215723e4046Schristos 		return TSPERR(TSS_E_OUTOFMEMORY);
216723e4046Schristos 	}
217723e4046Schristos 	LogDebug( "c_prime: %s", dump_byte_array( *c_primeLength, *c_prime));
218*0861b331Schristos 	EVP_DigestFinal(mdctx, *c_prime, NULL);
219*0861b331Schristos 	EVP_MD_CTX_destroy(mdctx);
220723e4046Schristos 	free( byte_array);
221723e4046Schristos 	return TSS_SUCCESS;
222723e4046Schristos }
223723e4046Schristos 
224723e4046Schristos // inspired by computeCredentialProof (IssuerTransaction.java)
225723e4046Schristos 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,bi_ptr * s_e)226723e4046Schristos compute_credential_proof( TSS_DAA_PK_internal *pk_intern,
227723e4046Schristos 						bi_ptr capital_A,
228723e4046Schristos 						bi_ptr fraction_A,
229723e4046Schristos 						bi_ptr eInverse,
230723e4046Schristos 						bi_ptr v_prime_prime,
231723e4046Schristos 						bi_ptr productPQprime,
232723e4046Schristos 						UINT32 noncePlatformLength,
233723e4046Schristos 						BYTE *noncePlatform,
234723e4046Schristos 						bi_ptr *c_prime,	// out
235723e4046Schristos 						bi_ptr *s_e	// out
236723e4046Schristos ) {
237723e4046Schristos 	bi_ptr random_E = bi_new_ptr();
238723e4046Schristos 	bi_ptr capital_Atilde = bi_new_ptr();
239723e4046Schristos 	BYTE *c_prime_bytes;
240723e4046Schristos 	UINT32 c_primeLength;
241723e4046Schristos 
242723e4046Schristos 	bi_urandom( random_E, bi_length( productPQprime) + DAA_PARAM_SAFETY_MARGIN * 8);
243723e4046Schristos 	bi_mod( random_E, random_E, productPQprime);
244723e4046Schristos 	bi_inc( random_E);
245723e4046Schristos 	bi_mod_exp( capital_Atilde, fraction_A, random_E, pk_intern->modulus);
246723e4046Schristos 	compute_join_challenge_issuer( pk_intern,
247723e4046Schristos 								v_prime_prime,
248723e4046Schristos 								capital_A,
249723e4046Schristos 								capital_Atilde,
250723e4046Schristos 								noncePlatformLength,
251723e4046Schristos 								noncePlatform,
252723e4046Schristos 								&c_primeLength,
253723e4046Schristos 								&c_prime_bytes); // allocation
254723e4046Schristos 	*c_prime = bi_set_as_nbin( c_primeLength, c_prime_bytes); // allocation
255723e4046Schristos 	*s_e = bi_new_ptr();
256723e4046Schristos 	bi_mul( *s_e, *c_prime, eInverse);
257723e4046Schristos 	bi_mod( *s_e, *s_e, productPQprime);
258723e4046Schristos 	bi_sub( *s_e, random_E, *s_e);
259723e4046Schristos 	bi_mod( *s_e, *s_e, productPQprime);
260723e4046Schristos 	bi_free_ptr( capital_Atilde);
261723e4046Schristos 	bi_free_ptr( random_E);
262723e4046Schristos 	free( c_prime_bytes);
263723e4046Schristos 	return TSS_SUCCESS;
264723e4046Schristos }
265723e4046Schristos 
266723e4046Schristos // from IssuerTransaction.java (joinStep2)
267723e4046Schristos // stacks: TCGApplication.java (retrieveDAACredential) -> Issuer.java(issueCredential)
Tspi_DAA_IssueCredential_internal(TSS_HDAA hDAA,UINT32 attributesIssuerLength,BYTE ** attributesIssuer,TSS_DAA_CREDENTIAL_REQUEST credentialRequest,TSS_DAA_JOIN_ISSUER_SESSION joinSession,TSS_DAA_CRED_ISSUER * credIssuer)268723e4046Schristos TSPICALL Tspi_DAA_IssueCredential_internal
269723e4046Schristos (
270723e4046Schristos 	TSS_HDAA	hDAA,	// in
271723e4046Schristos 	UINT32	attributesIssuerLength,	// in
272723e4046Schristos 	BYTE**	attributesIssuer,	// in
273723e4046Schristos 	TSS_DAA_CREDENTIAL_REQUEST	credentialRequest,	// in
274723e4046Schristos 	TSS_DAA_JOIN_ISSUER_SESSION	joinSession,	// in
275723e4046Schristos 	TSS_DAA_CRED_ISSUER*	credIssuer	// out
276723e4046Schristos ) {
277723e4046Schristos 	TSS_RESULT result = TSS_SUCCESS;
278723e4046Schristos 	TCS_CONTEXT_HANDLE tcsContext;
279723e4046Schristos 	bi_ptr capitalU_hat_prime = NULL;
280723e4046Schristos 	bi_ptr tmp1;
281723e4046Schristos 	bi_ptr tmp2;
282723e4046Schristos 	bi_ptr sa_i;
283723e4046Schristos 	bi_ptr capitalU_prime = NULL;
284723e4046Schristos 	bi_ptr c = NULL;
285723e4046Schristos 	bi_ptr n = NULL;
286723e4046Schristos 	bi_ptr sf0 = NULL;
287723e4046Schristos 	bi_ptr sf1 = NULL;
288723e4046Schristos 	bi_ptr sv_prime = NULL;
289723e4046Schristos 	bi_ptr capitalR0 = NULL;
290723e4046Schristos 	bi_ptr capitalR1 = NULL;
291723e4046Schristos 	bi_ptr capitalS = NULL;
292723e4046Schristos 	bi_ptr capitalU = NULL;
293723e4046Schristos 	bi_ptr capitalU_hat = NULL;
294723e4046Schristos 	bi_ptr capitalN_hat_i = NULL;
295723e4046Schristos 	bi_ptr exp = NULL;
296723e4046Schristos 	bi_ptr product_attr_receiver = NULL;
297723e4046Schristos 	bi_ptr product_attr_issuer = NULL;
298723e4046Schristos 	bi_ptr sv_tilde_prime = NULL;
299723e4046Schristos 	bi_ptr capital_ni = NULL;
300723e4046Schristos 	bi_ptr v_hat = NULL;
301723e4046Schristos 	bi_ptr fraction_A = NULL;
302723e4046Schristos 	bi_ptr capitalA = NULL;
303723e4046Schristos 	bi_ptr e = NULL;
304723e4046Schristos 	bi_ptr eInverse = NULL;
305723e4046Schristos 	bi_ptr v_prime_prime = NULL;
306723e4046Schristos 	bi_ptr c_prime = NULL;
307723e4046Schristos 	bi_ptr s_e = NULL;
308723e4046Schristos 	bi_ptr zeta = NULL;
309723e4046Schristos 	TSS_DAA_PK *daa_pk_extern;
310723e4046Schristos 	TSS_DAA_PK_internal *pk_intern;
311723e4046Schristos 	TSS_DAA_PRIVATE_KEY *private_key;
312723e4046Schristos 	UINT32 i, chLength, challengeLength, length, interval;
313*0861b331Schristos 	EVP_MD_CTX *mdctx;
314723e4046Schristos 	BYTE *ch = NULL, *challenge = NULL;
315723e4046Schristos 
316723e4046Schristos 	tmp1 = bi_new_ptr();
317723e4046Schristos 	tmp2 = bi_new_ptr();
318723e4046Schristos 	if( tmp1 == NULL || tmp2 == NULL) {
319723e4046Schristos 		LogError("malloc of BI <%s> failed", "tmp1, tmp2");
320723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
321723e4046Schristos 		goto close;
322723e4046Schristos 	}
323723e4046Schristos 	if( (result = obj_daa_get_tsp_context( hDAA, &tcsContext)) != TSS_SUCCESS) goto close;
324723e4046Schristos 	// 1 TODO Check the TPM rogue list
325723e4046Schristos 
326723e4046Schristos 	// 2 verify the authentication proof of the TPM
327723e4046Schristos 	result = verify_authentificity(&credentialRequest, &joinSession);
328723e4046Schristos 	if( result != TSS_SUCCESS) goto close;
329723e4046Schristos 	daa_pk_extern = (TSS_DAA_PK *)(((TSS_DAA_KEY_PAIR *)joinSession.issuerKeyPair)->public_key);
330723e4046Schristos 	pk_intern = e_2_i_TSS_DAA_PK( daa_pk_extern);
331723e4046Schristos 	n = bi_set_as_nbin( daa_pk_extern->modulusLength,
332723e4046Schristos 		daa_pk_extern->modulus); // allocation
333723e4046Schristos 	if( n == NULL) {
334723e4046Schristos 		LogError("malloc of BI <%s> failed", "n");
335723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
336723e4046Schristos 		goto close;
337723e4046Schristos 	}
338723e4046Schristos 	capitalR0 = bi_set_as_nbin( daa_pk_extern->capitalR0Length,
339723e4046Schristos 		daa_pk_extern->capitalR0); // allocation
340723e4046Schristos 	if( capitalR0 == NULL) {
341723e4046Schristos 		LogError("malloc of BI <%s> failed", "capitalR0");
342723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
343723e4046Schristos 		goto close;
344723e4046Schristos 	}
345723e4046Schristos 	capitalR1 = bi_set_as_nbin( daa_pk_extern->capitalR1Length,
346723e4046Schristos 		daa_pk_extern->capitalR1); // allocation
347723e4046Schristos 	if( capitalR1 == NULL) {
348723e4046Schristos 		LogError("malloc of BI <%s> failed", "capitalR1");
349723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
350723e4046Schristos 		goto close;
351723e4046Schristos 	}
352723e4046Schristos 	capitalS = bi_set_as_nbin( daa_pk_extern->capitalSLength,
353723e4046Schristos 		daa_pk_extern->capitalS); // allocation
354723e4046Schristos 	if( capitalS == NULL) {
355723e4046Schristos 		LogError("malloc of BI <%s> failed", "capitalS");
356723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
357723e4046Schristos 		goto close;
358723e4046Schristos 	}
359723e4046Schristos 	capitalU = bi_set_as_nbin( credentialRequest.capitalULength,
360723e4046Schristos 		credentialRequest.capitalU); // allocation
361723e4046Schristos 	if( capitalU == NULL) {
362723e4046Schristos 		LogError("malloc of BI <%s> failed", "capitalU");
363723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
364723e4046Schristos 		goto close;
365723e4046Schristos 	}
366723e4046Schristos 	sv_tilde_prime = bi_set_as_nbin( credentialRequest.sVtildePrimeLength,
367723e4046Schristos 		credentialRequest.sVtildePrime); // allocation
368723e4046Schristos 	if( sv_tilde_prime == NULL) {
369723e4046Schristos 		LogError("malloc of BI <%s> failed", "sv_tilde_prime");
370723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
371723e4046Schristos 		goto close;
372723e4046Schristos 	}
373723e4046Schristos 	capital_ni = bi_set_as_nbin( credentialRequest.capitalNiLength,
374723e4046Schristos 		credentialRequest.capitalNi); // allocation
375723e4046Schristos 	if( capital_ni == NULL) {
376723e4046Schristos 		LogError("malloc of BI <%s> failed", "capital_ni");
377723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
378723e4046Schristos 		goto close;
379723e4046Schristos 	}
380723e4046Schristos 	// 3 Verify the correctness proof of the credential request
381723e4046Schristos 	// 3.a TODO commitments
382723e4046Schristos 
383723e4046Schristos 	// 3.b
384723e4046Schristos 	capitalU_prime = bi_set_as_nbin( joinSession.capitalUprimeLength,
385723e4046Schristos 		joinSession.capitalUprime); // allocation
386723e4046Schristos 	if( capitalU_prime == NULL) {
387723e4046Schristos 		LogError("malloc of BI <%s> failed", "capitalU_prime");
388723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
389723e4046Schristos 		goto close;
390723e4046Schristos 	}
391723e4046Schristos 	sf0 = bi_set_as_nbin( credentialRequest.sF0Length,
392723e4046Schristos 		credentialRequest.sF0); // allocation
393723e4046Schristos 	if( sf0 == NULL) {
394723e4046Schristos 		LogError("malloc of BI <%s> failed", "sf0");
395723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
396723e4046Schristos 		goto close;
397723e4046Schristos 	}
398723e4046Schristos 	sf1 = bi_set_as_nbin( credentialRequest.sF1Length,
399723e4046Schristos 		credentialRequest.sF1); // allocation
400723e4046Schristos 	if( sf1 == NULL) {
401723e4046Schristos 		LogError("malloc of BI <%s> failed", "sf1");
402723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
403723e4046Schristos 		goto close;
404723e4046Schristos 	}
405723e4046Schristos 	sv_prime = bi_set_as_nbin( credentialRequest.sVprimeLength,
406723e4046Schristos 		credentialRequest.sVprime); // allocation
407723e4046Schristos 	if( sv_prime == NULL) {
408723e4046Schristos 		LogError("malloc of BI <%s> failed", "sv_prime");
409723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
410723e4046Schristos 		goto close;
411723e4046Schristos 	}
412723e4046Schristos 	c = bi_set_as_nbin( credentialRequest.challengeLength,
413723e4046Schristos 		credentialRequest.challenge); // allocation
414723e4046Schristos 	if( c == NULL) {
415723e4046Schristos 		LogError("malloc of BI <%s> failed", "c");
416723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
417723e4046Schristos 		goto close;
418723e4046Schristos 	}
419723e4046Schristos 	capitalU_hat_prime = bi_new_ptr();// allocation
420723e4046Schristos 	if( capitalU_hat_prime == NULL) {
421723e4046Schristos 		LogError("malloc of BI <%s> failed", "c");
422723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
423723e4046Schristos 		goto close;
424723e4046Schristos 	}
425723e4046Schristos 	// capitalU_hat_prime = capitalU_prime ~% n
426723e4046Schristos 	bi_invert_mod( capitalU_hat_prime, capitalU_prime, n);
427723e4046Schristos 	// capitalU_hat_prime = ( capitalU_hat_prime ^ c ) % n
428723e4046Schristos 	bi_mod_exp( capitalU_hat_prime, capitalU_hat_prime, c, n);
429723e4046Schristos 	// capitalU_hat_prime = ( capitalU_hat_prime * ( capitalR0 ^ sf0)) % n
430723e4046Schristos 	bi_mod_exp( tmp1, capitalR0, sf0, n);
431723e4046Schristos 	bi_mul( capitalU_hat_prime, capitalU_hat_prime, tmp1);
432723e4046Schristos 	bi_mod( capitalU_hat_prime, capitalU_hat_prime, n);
433723e4046Schristos 	// capitalU_hat_prime = ( capitalU_hat_prime * ( capitalR1 ^ sf1)) % n
434723e4046Schristos 	bi_mod_exp( tmp1, capitalR1, sf1, n);
435723e4046Schristos 	bi_mul( capitalU_hat_prime, capitalU_hat_prime, tmp1);
436723e4046Schristos 	bi_mod( capitalU_hat_prime, capitalU_hat_prime, n);
437723e4046Schristos 	// capitalU_hat_prime = ( capitalU_hat_prime * ( capitalS ^ sv_prime)) % n
438723e4046Schristos 	bi_mod_exp( tmp1, capitalS, sv_prime, n);
439723e4046Schristos 	bi_mul( capitalU_hat_prime, capitalU_hat_prime, tmp1);
440723e4046Schristos 	bi_mod( capitalU_hat_prime, capitalU_hat_prime, n);
441723e4046Schristos 	// verify blinded encoded attributes of the Receiver
442723e4046Schristos 	product_attr_receiver = bi_new_ptr();
443723e4046Schristos 	bi_set( product_attr_receiver, bi_1);
444723e4046Schristos 	length = ( DAA_PARAM_SIZE_RANDOMIZED_ATTRIBUTES + 7) / 8;
445723e4046Schristos 	for( i=0; i<credentialRequest.sALength; i++) {
446723e4046Schristos 		sa_i = bi_set_as_nbin( length, credentialRequest.sA[i]); // allocation
447723e4046Schristos 		if( sa_i == NULL) {
448723e4046Schristos 			LogError("malloc of BI <%s> failed", "sa_i");
449723e4046Schristos 			result = TSPERR(TSS_E_OUTOFMEMORY);
450723e4046Schristos 			goto close;
451723e4046Schristos 		}
452723e4046Schristos 		bi_mod_exp( tmp1, pk_intern->capitalRReceiver->array[i], sa_i, n);
453723e4046Schristos 		bi_mul( product_attr_receiver, product_attr_receiver, tmp1);
454723e4046Schristos 		bi_mod( product_attr_receiver, product_attr_receiver, n);
455723e4046Schristos 		bi_free_ptr( sa_i);
456723e4046Schristos 	}
457723e4046Schristos 	// tmp1 = ( 1 / capitalU ) % n
458723e4046Schristos 	bi_invert_mod( tmp1, capitalU, n);
459723e4046Schristos 	capitalU_hat = bi_new_ptr();
460723e4046Schristos 	if( capitalU_hat == NULL) {
461723e4046Schristos 		LogError("malloc of BI <%s> failed", "capitalU_hat");
462723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
463723e4046Schristos 		goto close;
464723e4046Schristos 	}
465723e4046Schristos 	bi_mul( capitalU_hat, capitalU_prime, tmp1);
466723e4046Schristos 	// capitalU_hat = capitalU_prime / capitalU
467723e4046Schristos 	bi_mod( capitalU_hat, capitalU_hat, n);
468723e4046Schristos 	// capital_Uhat = ( (capital_Uhat ^ c ) % n
469723e4046Schristos 	bi_mod_exp( capitalU_hat, capitalU_hat, c, n);
470723e4046Schristos 	// capital_Uhat = ( capital_Uhat * ( capitalS ^ sv_tilde_prime) % n ) % n
471723e4046Schristos 	bi_mod_exp( tmp1, pk_intern->capitalS, sv_tilde_prime, n);
472723e4046Schristos 	bi_mul( capitalU_hat, capitalU_hat, tmp1);
473723e4046Schristos 	bi_mod( capitalU_hat, capitalU_hat, n);
474723e4046Schristos 	bi_mul( capitalU_hat, capitalU_hat, product_attr_receiver);
475723e4046Schristos 	bi_mod( capitalU_hat, capitalU_hat, n);
476723e4046Schristos 	// capital_Nhat_i = (( capital_Ni ~% pk_intern->capitalGamma ) ^ c ) % pk_intern->capitalGamma
477723e4046Schristos 	capitalN_hat_i = bi_new_ptr();
478723e4046Schristos 	bi_invert_mod( capitalN_hat_i, capital_ni, pk_intern->capitalGamma);
479723e4046Schristos 	bi_mod_exp( capitalN_hat_i, capitalN_hat_i, c, pk_intern->capitalGamma);
480723e4046Schristos 	// exp = sf1 << (DAA_PARAM_SIZE_F_I) + sf0
481723e4046Schristos 	exp = bi_new_ptr();
482723e4046Schristos 	if( exp == NULL) {
483723e4046Schristos 		LogError("malloc of BI <%s> failed", "exp");
484723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
485723e4046Schristos 		goto close;
486723e4046Schristos 	}
487723e4046Schristos 	bi_shift_left( exp, sf1, DAA_PARAM_SIZE_F_I);
488723e4046Schristos 	bi_add( exp, exp, sf0);
489723e4046Schristos 	zeta = compute_zeta( pk_intern->issuerBaseNameLength,
490723e4046Schristos 					pk_intern->issuerBaseName,
491723e4046Schristos 					pk_intern);
492723e4046Schristos 	// capital_Nhat_i = ( capital_Nhat_i *
493723e4046Schristos 	//			( ( issuer.zeta ^ exp) % pk->capitalGamma) ) % pk->capitalGamma
494723e4046Schristos 	bi_mod_exp( tmp1, zeta, exp, pk_intern->capitalGamma);
495723e4046Schristos 	bi_mul( capitalN_hat_i, capitalN_hat_i, tmp1);
496723e4046Schristos 	bi_mod( capitalN_hat_i, capitalN_hat_i, pk_intern->capitalGamma);
497723e4046Schristos 
498723e4046Schristos 	LogDebug("calculation Uhat:                capitalS:%s\n", bi_2_hex_char( pk_intern->capitalS));
499723e4046Schristos 	LogDebug("calculation Uhat:       sv_tilde_prime:%s\n", bi_2_hex_char( sv_tilde_prime));
500723e4046Schristos 	LogDebug("calculation Uhat:                          n:%s\n", bi_2_hex_char( n));
501723e4046Schristos 	LogDebug("calculation Uhat: product_attributes:%s\n", bi_2_hex_char( product_attr_receiver));
502723e4046Schristos 	LogDebug("calculation NhatI:                     zeta:%s\n", bi_2_hex_char( zeta));
503723e4046Schristos 	LogDebug("calculation NhatI:                      exp:%s\n", bi_2_hex_char( exp));
504723e4046Schristos 	LogDebug("calculation NhatI:      capitalGamma:%s\n", bi_2_hex_char( pk_intern->capitalGamma));
505723e4046Schristos 	// calculate challenge
506723e4046Schristos 	result = compute_join_challenge_host(hDAA,
507723e4046Schristos 							pk_intern,
508723e4046Schristos 							capitalU,
509723e4046Schristos 							capitalU_prime,
510723e4046Schristos 							capitalU_hat,
511723e4046Schristos 							capitalU_hat_prime,
512723e4046Schristos 							capital_ni,
513723e4046Schristos 							capitalN_hat_i,
514723e4046Schristos 							0, // TODO: commitmentsProofLength
515723e4046Schristos 							NULL, // TODO: commits
516723e4046Schristos 							joinSession.nonceIssuerLength,
517723e4046Schristos 							joinSession.nonceIssuer,
518723e4046Schristos 							&chLength,	// out
519723e4046Schristos 							&ch);		// out allocation
520723e4046Schristos 	if( result != TSS_SUCCESS) goto close;
521723e4046Schristos 	LogDebug("JoinChallengeHost: %s", dump_byte_array( chLength, ch));
522*0861b331Schristos 	mdctx = EVP_MD_CTX_create();
523*0861b331Schristos 	EVP_DigestInit(mdctx, DAA_PARAM_get_message_digest());
524*0861b331Schristos 	EVP_DigestUpdate(mdctx,  ch, chLength);
525*0861b331Schristos 	challengeLength = EVP_MD_CTX_size(mdctx);
526723e4046Schristos 	challenge = (BYTE *)malloc( challengeLength);
527723e4046Schristos 	if( challenge == NULL) {
528723e4046Schristos 		LogError("malloc of %d bytes failed", challengeLength);
529723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
530723e4046Schristos 		goto close;
531723e4046Schristos 	}
532*0861b331Schristos 	EVP_DigestUpdate(mdctx,  credentialRequest.nonceTpm, credentialRequest.nonceTpmLength);
533*0861b331Schristos 	EVP_DigestFinal(mdctx, challenge, NULL);
534723e4046Schristos 	// checks
535723e4046Schristos 	if( credentialRequest.challengeLength != challengeLength ||
536723e4046Schristos 		memcmp( credentialRequest.challenge, challenge, challengeLength)!=0) {
537723e4046Schristos 		LogError("Verification of c failed - Step 3.f.i");
538723e4046Schristos 		LogError("credentialRequest.challenge[%d]=%s",
539723e4046Schristos 			credentialRequest.challengeLength,
540723e4046Schristos 			dump_byte_array( credentialRequest.challengeLength,
541723e4046Schristos 				credentialRequest.challenge));
542723e4046Schristos 		LogError("challenge[%d]=%s",
543723e4046Schristos 			challengeLength,
544723e4046Schristos 			dump_byte_array( challengeLength, challenge));
545723e4046Schristos 		result = TSS_E_DAA_CREDENTIAL_REQUEST_PROOF_ERROR;
546723e4046Schristos 		goto close;
547723e4046Schristos 	}
548723e4046Schristos 	// + 1 because the result of ( rA(43 bits)  + c(20 bits) * a(13 bits)) can
549723e4046Schristos 	// shift 1 bit above the normal size (43 bits)
550723e4046Schristos 	length = DAA_PARAM_SIZE_RANDOMIZED_ATTRIBUTES + 1;
551723e4046Schristos 	if( bi_length( sf0) > (long)length) {
552723e4046Schristos 		LogError( "Verification of sF0 failed - Step 3.f.ii");
553723e4046Schristos 		LogError("\tsf0 bits length: %d  expected maximum length:%d\n",
554723e4046Schristos 				(int)bi_length( sf0), (int)length);
555723e4046Schristos 		result = TSS_E_DAA_CREDENTIAL_REQUEST_PROOF_ERROR;
556723e4046Schristos 		goto close;
557723e4046Schristos 	}
558723e4046Schristos 	if( bi_length( sf1) > (long)length) {
559723e4046Schristos 		LogError( "Verification of sF1 failed - Step 3.f.ii");
560723e4046Schristos 		LogError("\tsf1 length: %d  expected maximum length:%d\n",
561723e4046Schristos 				(int)bi_length( sf1), (int)length);
562723e4046Schristos 		result = TSS_E_DAA_CREDENTIAL_REQUEST_PROOF_ERROR;
563723e4046Schristos 		goto close;
564723e4046Schristos 	}
565723e4046Schristos 	// blinded attributes
566723e4046Schristos 	length = DAA_PARAM_SIZE_RANDOMIZED_ATTRIBUTES;
567723e4046Schristos 	for( i=0; i<credentialRequest.sALength; i++) {
568723e4046Schristos 		sa_i = bi_set_as_nbin( ( length + 7) / 8, credentialRequest.sA[i]); // allocation
569723e4046Schristos 		if( sa_i == NULL) {
570723e4046Schristos 			LogError("malloc of BI <%s> failed", "sa_i");
571723e4046Schristos 			result = TSPERR(TSS_E_OUTOFMEMORY);
572723e4046Schristos 			goto close;
573723e4046Schristos 		}
574723e4046Schristos 		if( bi_length( sa_i) > (long)length) {
575723e4046Schristos 			LogError("Verification of sA[%d] failed - Step 3.f.ii", i);
576723e4046Schristos 			LogError("sA.length=%d length=%d", (int)bi_length( sa_i), length);
577723e4046Schristos 			result = TSS_E_DAA_CREDENTIAL_REQUEST_PROOF_ERROR;
578723e4046Schristos 			goto close;
579723e4046Schristos 		}
580723e4046Schristos 		bi_free_ptr( sa_i);
581723e4046Schristos 		if( result != TSS_SUCCESS) goto close;
582723e4046Schristos 	}
583723e4046Schristos 	length = DAA_PARAM_SIZE_RSA_MODULUS + 2 * DAA_PARAM_SAFETY_MARGIN +
584723e4046Schristos 			DAA_PARAM_SIZE_MESSAGE_DIGEST;
585723e4046Schristos 	if( bi_length( sv_prime) > (int)length) {
586723e4046Schristos 		LogError("Verification of sVprime failed - Step 3.f.iii\n");
587723e4046Schristos 		LogError("\tsv_prime bits length: %d  expected maximum length:%d\n",
588723e4046Schristos 				(int)bi_length( sv_prime), (int)length);
589723e4046Schristos 		result = TSS_E_DAA_CREDENTIAL_REQUEST_PROOF_ERROR;
590723e4046Schristos 		goto close;
591723e4046Schristos 	}
592723e4046Schristos 	if( bi_nbin_size( sv_tilde_prime) > (int)length) {
593723e4046Schristos 		LogError("Verification of sVtildePrime failed - Step 3.f.iii");
594723e4046Schristos 		LogError("\tsv_tilde_prime bits length: %d  expected maximum length:%d\n",
595723e4046Schristos 				(int)bi_length( sv_tilde_prime), (int)length);
596723e4046Schristos 		result = TSS_E_DAA_CREDENTIAL_REQUEST_PROOF_ERROR;
597723e4046Schristos 		goto close;
598723e4046Schristos 	}
599723e4046Schristos 	// compute credential
600723e4046Schristos 	v_hat = bi_new_ptr();
601723e4046Schristos 	if( v_hat == NULL) {
602723e4046Schristos 		LogError("malloc of BI <%s> failed", "v_hat");
603723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
604723e4046Schristos 		goto close;
605723e4046Schristos 	}
606723e4046Schristos 	bi_urandom( v_hat, DAA_PARAM_SIZE_RND_VALUE_CERTIFICATE - 1);
607723e4046Schristos 	length = DAA_PARAM_SIZE_EXPONENT_CERTIFICATE;
608723e4046Schristos 	interval = DAA_PARAM_SIZE_INTERVAL_EXPONENT_CERTIFICATE;
609723e4046Schristos 	e = bi_new_ptr();
610723e4046Schristos 	if( e == NULL) {
611723e4046Schristos 		LogError("malloc of BI <%s> failed", "e");
612723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
613723e4046Schristos 		goto close;
614723e4046Schristos 	}
615723e4046Schristos 	compute_prime( e, length, interval);
616723e4046Schristos 
617723e4046Schristos 	// v'' = ( 1 << DAA_PARAM_SIZE_RND_VALUE_CERTIFICATE) + v_hat
618723e4046Schristos 	v_prime_prime = bi_new_ptr();
619723e4046Schristos 	bi_shift_left( tmp1, bi_1, DAA_PARAM_SIZE_RND_VALUE_CERTIFICATE - 1);
620723e4046Schristos 	bi_add( v_prime_prime, tmp1, v_hat);
621723e4046Schristos 
622723e4046Schristos 	// fraction_A = (( pk->capitalS ^ v``) % n) * capitalU
623723e4046Schristos 	fraction_A = bi_new_ptr();
624723e4046Schristos 	if( fraction_A == NULL) {
625723e4046Schristos 		LogError("malloc of BI <%s> failed", "fraction_A");
626723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
627723e4046Schristos 		goto close;
628723e4046Schristos 	}
629723e4046Schristos 	bi_mod_exp( fraction_A, pk_intern->capitalS, v_prime_prime, n);
630723e4046Schristos 	bi_mul( fraction_A, fraction_A, capitalU);
631723e4046Schristos 	bi_mod( fraction_A, fraction_A, n);
632723e4046Schristos 
633723e4046Schristos 	// encode attributes
634723e4046Schristos 	bi_free_ptr( tmp1);
635723e4046Schristos 	product_attr_issuer = bi_new_ptr();
636723e4046Schristos 	if( product_attr_issuer == NULL) {
637723e4046Schristos 		LogError("malloc of BI <%s> failed", "product_attr_issuer");
638723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
639723e4046Schristos 		goto close;
640723e4046Schristos 	}
641723e4046Schristos 	bi_set( product_attr_issuer, bi_1);
642723e4046Schristos 	for( i=0; i< attributesIssuerLength; i++) {
643723e4046Schristos 		tmp1 = bi_set_as_nbin( DAA_PARAM_SIZE_F_I / 8, attributesIssuer[i]); // allocation
644723e4046Schristos 		bi_mod_exp( tmp2, pk_intern->capitalRIssuer->array[i], tmp1, n);
645723e4046Schristos 		bi_mul( product_attr_issuer, product_attr_issuer, tmp2);
646723e4046Schristos 		bi_mod( product_attr_issuer, product_attr_issuer, n);
647723e4046Schristos 		bi_free_ptr( tmp1);
648723e4046Schristos 	}
649723e4046Schristos 	tmp1 = bi_new_ptr();
650723e4046Schristos 	if( tmp1 == NULL) {
651723e4046Schristos 		LogError("malloc of BI <%s> failed", "tmp1");
652723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
653723e4046Schristos 		goto close;
654723e4046Schristos 	}
655723e4046Schristos 	bi_mul( fraction_A, fraction_A, product_attr_issuer);
656723e4046Schristos 	bi_mod( fraction_A, fraction_A, n);
657723e4046Schristos 
658723e4046Schristos 	bi_invert_mod( fraction_A, fraction_A, n);
659723e4046Schristos 	bi_mul( fraction_A, fraction_A, pk_intern->capitalZ);
660723e4046Schristos 	bi_mod( fraction_A, fraction_A, n);
661723e4046Schristos 
662723e4046Schristos 	private_key = (TSS_DAA_PRIVATE_KEY *)
663723e4046Schristos 				(((TSS_DAA_KEY_PAIR *)joinSession.issuerKeyPair)->private_key);
664723e4046Schristos 	bi_free_ptr( tmp2);
665723e4046Schristos 	tmp2 = bi_set_as_nbin( private_key->productPQprimeLength,
666723e4046Schristos 		private_key->productPQprime); // allocation
667723e4046Schristos 	if( tmp2 == NULL) {
668723e4046Schristos 		LogError("malloc of BI <%s> failed", "tmp2");
669723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
670723e4046Schristos 		goto close;
671723e4046Schristos 	}
672723e4046Schristos 	eInverse = bi_new_ptr();
673723e4046Schristos 	if( eInverse == NULL) {
674723e4046Schristos 		LogError("malloc of BI <%s> failed", "eInverse");
675723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
676723e4046Schristos 		goto close;
677723e4046Schristos 	}
678723e4046Schristos 	bi_invert_mod( eInverse, e, tmp2);
679723e4046Schristos 	capitalA = bi_new_ptr();
680723e4046Schristos 	if( capitalA == NULL) {
681723e4046Schristos 		LogError("malloc of BI <%s> failed", "capitalA");
682723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
683723e4046Schristos 		goto close;
684723e4046Schristos 	}
685723e4046Schristos 	LogDebug("fraction_A[%ld]=%s", bi_nbin_size( fraction_A), bi_2_hex_char( fraction_A));
686723e4046Schristos 	LogDebug("eInverse[%ld]=%s", bi_nbin_size( eInverse), bi_2_hex_char( eInverse));
687723e4046Schristos 	LogDebug("productPQprime[%ld]=%s", bi_nbin_size( tmp2), bi_2_hex_char( tmp2));
688723e4046Schristos 	LogDebug("eInverse[%ld]=%s", bi_nbin_size( eInverse), bi_2_hex_char( eInverse));
689723e4046Schristos 	LogDebug("e[%ld]=%s", bi_nbin_size( e), bi_2_hex_char( e));
690723e4046Schristos 	LogDebug("n[%ld]=%s", bi_nbin_size( n), bi_2_hex_char( n));
691723e4046Schristos 	bi_mod_exp( capitalA, fraction_A, eInverse, n);
692723e4046Schristos 
693723e4046Schristos 	compute_credential_proof( pk_intern,
694723e4046Schristos 				capitalA,
695723e4046Schristos 				fraction_A,
696723e4046Schristos 				eInverse,
697723e4046Schristos 				v_prime_prime,
698723e4046Schristos 				tmp2, // productPQprime
699723e4046Schristos 				credentialRequest.noncePlatformLength,
700723e4046Schristos 				credentialRequest.noncePlatform,
701723e4046Schristos 				&c_prime,	// out: allocation
702723e4046Schristos 				&s_e);	// out: allocation
703723e4046Schristos 	// populate credIssuer (TSS_DAA_CRED_ISSUER *)
704723e4046Schristos 	credIssuer->capitalA = calloc_tspi( tcsContext, bi_nbin_size( capitalA));
705723e4046Schristos 	if( credIssuer->capitalA == NULL) {
706723e4046Schristos 		LogError("malloc of %ld bytes failed", bi_nbin_size( capitalA));
707723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
708723e4046Schristos 		goto close;
709723e4046Schristos 	}
710723e4046Schristos 	bi_2_nbin1( &(credIssuer->capitalALength), credIssuer->capitalA, capitalA);
711723e4046Schristos 	credIssuer->e = calloc_tspi( tcsContext, bi_nbin_size( e));
712723e4046Schristos 	if( credIssuer->e == NULL) {
713723e4046Schristos 		LogError("malloc of %ld bytes failed", bi_nbin_size( e));
714723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
715723e4046Schristos 		goto close;
716723e4046Schristos 	}
717723e4046Schristos 	bi_2_nbin1( &(credIssuer->eLength), credIssuer->e, e);
718723e4046Schristos 	credIssuer->vPrimePrime = calloc_tspi( tcsContext, bi_nbin_size( v_prime_prime));
719723e4046Schristos 	if( credIssuer->vPrimePrime == NULL) {
720723e4046Schristos 		LogError("malloc of %ld bytes failed", bi_nbin_size( v_prime_prime));
721723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
722723e4046Schristos 		goto close;
723723e4046Schristos 	}
724723e4046Schristos 	bi_2_nbin1( &(credIssuer->vPrimePrimeLength), credIssuer->vPrimePrime, v_prime_prime);
725723e4046Schristos 	// attributes issuer
726723e4046Schristos 	credIssuer->attributesIssuerLength = attributesIssuerLength;
727723e4046Schristos 	credIssuer->attributesIssuer = calloc_tspi( tcsContext,
728723e4046Schristos 						attributesIssuerLength * sizeof( BYTE *));
729723e4046Schristos 	if( credIssuer->attributesIssuer == NULL) {
730723e4046Schristos 		LogError("malloc of %d bytes failed", attributesIssuerLength * sizeof( BYTE *));
731723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
732723e4046Schristos 		goto close;
733723e4046Schristos 	}
734723e4046Schristos 	for( i=0; i< attributesIssuerLength; i++) {
735723e4046Schristos 		credIssuer->attributesIssuer[i] = calloc_tspi( tcsContext, DAA_PARAM_SIZE_F_I / 8);
736723e4046Schristos 		if( credIssuer->attributesIssuer[i] == NULL) {
737723e4046Schristos 			LogError("malloc of %d bytes failed", DAA_PARAM_SIZE_F_I / 8);
738723e4046Schristos 			result = TSPERR(TSS_E_OUTOFMEMORY);
739723e4046Schristos 			goto close;
740723e4046Schristos 		}
741723e4046Schristos 		memcpy( credIssuer->attributesIssuer[i], attributesIssuer[i], DAA_PARAM_SIZE_F_I / 8);
742723e4046Schristos 	}
743723e4046Schristos 	credIssuer->cPrime = calloc_tspi( tcsContext, bi_nbin_size( c_prime));
744723e4046Schristos 	if( credIssuer->cPrime == NULL) {
745723e4046Schristos 		LogError("malloc of %ld bytes failed", bi_nbin_size( c_prime));
746723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
747723e4046Schristos 		goto close;
748723e4046Schristos 	}
749723e4046Schristos 	bi_2_nbin1( &(credIssuer->cPrimeLength), credIssuer->cPrime, c_prime);
750723e4046Schristos 	credIssuer->sE = calloc_tspi( tcsContext, bi_nbin_size( s_e));
751723e4046Schristos 	if( credIssuer->sE == NULL) {
752723e4046Schristos 		LogError("malloc of %ld bytes failed", bi_nbin_size( s_e));
753723e4046Schristos 		result = TSPERR(TSS_E_OUTOFMEMORY);
754723e4046Schristos 		goto close;
755723e4046Schristos 	}
756723e4046Schristos 	bi_2_nbin1( &(credIssuer->sELength), credIssuer->sE, s_e);
757723e4046Schristos 
758723e4046Schristos close:
759*0861b331Schristos 	EVP_MD_CTX_destroy(mdctx);
760723e4046Schristos 	//free_TSS_DAA_PK( daa_pk_extern);
761723e4046Schristos 	if( ch != NULL) free( ch);
762723e4046Schristos 	if( challenge != NULL) free( challenge);
763723e4046Schristos 	FREE_BI( tmp1);
764723e4046Schristos 	FREE_BI( tmp2);
765723e4046Schristos 	FREE_BI( s_e);
766723e4046Schristos 	FREE_BI( c_prime);
767723e4046Schristos 	FREE_BI( capitalA);
768723e4046Schristos 	FREE_BI( v_prime_prime);
769723e4046Schristos 	FREE_BI( eInverse);
770723e4046Schristos 	FREE_BI( e);
771723e4046Schristos 	FREE_BI( fraction_A);
772723e4046Schristos 	FREE_BI( v_hat);
773723e4046Schristos 	FREE_BI( capital_ni);
774723e4046Schristos 	FREE_BI( sv_tilde_prime);
775723e4046Schristos 	FREE_BI( product_attr_receiver);
776723e4046Schristos 	FREE_BI( product_attr_issuer);
777723e4046Schristos 	FREE_BI( capitalU_hat_prime);
778723e4046Schristos 	FREE_BI( capitalU_prime);
779723e4046Schristos 	FREE_BI( sv_prime);
780723e4046Schristos 	FREE_BI( exp);
781723e4046Schristos 	FREE_BI( capitalN_hat_i);
782723e4046Schristos 	FREE_BI( capitalU_hat);
783723e4046Schristos 	FREE_BI( capitalU);
784723e4046Schristos 	FREE_BI( capitalS);
785723e4046Schristos 	FREE_BI( capitalR1);
786723e4046Schristos 	FREE_BI( capitalR0);
787723e4046Schristos 	FREE_BI( sf1);
788723e4046Schristos 	FREE_BI( sf0);
789723e4046Schristos 	FREE_BI( n);
790723e4046Schristos 	FREE_BI( c);
791723e4046Schristos 	FREE_BI( zeta);
792723e4046Schristos 	return result;
793723e4046Schristos }
794