From: Kent Y. <ky...@us...> - 2008-01-04 16:51:18
|
Update of /cvsroot/trousers/trousers/src/tspi/daa/daa_issuer In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv27095/src/tspi/daa/daa_issuer Added Files: issue_credential.c issuer_init.c issuer_setup.c key_correctness_proof.c keypair_generator.c key_verification.c prime_gen.c Log Message: initial add of daa code --- NEW FILE: prime_gen.c --- /* * 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; } --- NEW FILE: issuer_init.c --- /* * 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; } --- NEW FILE: issue_credential.c --- /* * 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; } --- NEW FILE: key_correctness_proof.c --- /* * 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); } --- NEW FILE: issuer_setup.c --- /* * 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 C... [truncated message content] |