1
2 /*
3 * Licensed Materials - Property of IBM
4 *
5 * trousers - An open source TCG Software Stack
6 *
7 * (C) Copyright International Business Machines Corp. 2006
8 *
9 */
10
11 #include <stdlib.h>
12 #include <string.h>
13 #include <errno.h>
14
15 #include "daa_structs.h"
16 #include "trousers/tss.h"
17 #include "trousers/trousers.h"
18 #include "spi_internal_types.h"
19 #include "spi_utils.h"
20 #include "obj.h"
21 #include "tsplog.h"
22 #include "daa_parameter.h"
23 #include "verifier.h"
24 #include "platform.h"
25
26 // for RSA Key
27 #include <openssl/rsa.h>
28
29 #define DEFAULT_FILENAME "issuer.txt"
30 #define DEFAULT_CREDENTIAL_FILENAME "credential.txt"
31 #define DEFAULT_DAACOUNTER 0x01020304
32 #define DEFAULT_OWN_PASSWD "OWN_PWD"
33
34 // from IssuerFactory
35 static const int DEFAULT_KEY_CHAIN_LENGTH = 3;
36
37 typedef struct tdIssuer {
38 // use on Tspi calls
39 TSS_DAA_PK *pk_extern;
40 TSS_DAA_KEY_PAIR *key_pair_extern;
41
42 // used internally
43 int length_key_chain;
44 RSA **key_chain;
45 TSS_DAA_PK_internal *pk;
46 DAA_PRIVATE_KEY_internal *private_key;
47 TSS_DAA_PK_PROOF_internal *pk_proof;
48 //RSA **auth_key_pairs;
49 BYTE **pk_signatures;
50 bi_ptr zeta;
51 } Issuer;
52
alloc(UINT32 length,TCS_CONTEXT_HANDLE tcsContext)53 void *alloc( UINT32 length, TCS_CONTEXT_HANDLE tcsContext) {
54 void *result = calloc_tspi( tcsContext, length);
55 LogDebug("allocate tspi memory:%d", (int)result);
56 return result;
57 }
58
59 /**
60 Used by RSA_generate_key
61 From RSA_generate_key documentation:
62 -> callback(2, n, cb_arg) is called when n-th randomly generated prime is rejected
63 -> callback(3, 0, cb_arg) is called when p is found with p-1 more or less prime to e
64 -> callback(3, 1, cb_arg) repeatedly called for prime q
65 */
callback(int step,int number,void * arg)66 void callback(int step, int number, void *arg) {
67 #ifdef DAA_DEBUG
68 putc( '.', stdout); fflush( stdout);
69 #endif
70 }
71
sign(BYTE * buffer_2_sign,int len_buffer_2_sign,RSA * rsa,BYTE * signature,int * len_signature)72 int sign( BYTE *buffer_2_sign,
73 int len_buffer_2_sign,
74 RSA *rsa,
75 BYTE *signature,
76 int *len_signature
77 ) {
78 EVP_MD_CTX *ctx;
79 int len_message = EVP_MD_size( EVP_sha1()), current_len_message;
80 BYTE *message = (BYTE *)malloc( len_message);
81 int ret;
82
83 ctx = EVP_MD_CTX_create();
84 EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
85 EVP_DigestUpdate(ctx, buffer_2_sign, len_buffer_2_sign);
86 EVP_DigestFinal_ex(ctx, message, ¤t_len_message);
87 LogDebug("Sign rsa-> with message (length=%d)", current_len_message);
88 // int RSA_sign(int type, unsigned char *m, unsigned int m_len,
89 // unsigned char *sigret, unsigned int *siglen, RSA *rsa);
90 ret = RSA_sign( NID_sha1, message, current_len_message, signature, len_signature, rsa);
91 if( ret == 0) {
92 LogError("Error in RSA_sign: %s", ERR_error_string( ERR_get_error(), NULL));
93 }
94 LogDebug("Sign rsa-> signature (length=%d)", *len_signature );
95 EVP_MD_CTX_destroy(ctx);
96 free( message);
97 return ret;
98 }
99
100 /* Compute key chain. */
init_key_chain(int length_key_chain,Issuer * issuer)101 static int init_key_chain(int length_key_chain, Issuer *issuer) {
102 BYTE *signature;
103 int i, len_sign, ret;
104 BYTE *modulus;
105 BYTE *message;
106 // generate RSA key of length DAA_PARAM_KEY_SIZE with exponent
107 // 65537 (java.security.spec.RSAKeyGenParameterSpec.F4)
108 unsigned long e = 65537;
109 RSA *rsa;
110 bi_ptr bi;
111 EVP_MD_CTX *ctx;
112 int len_message = EVP_MD_size( EVP_sha1());
113 int current_len_message;
114
115 EVP_MD_CTX_create(ctx);
116 message = (BYTE *)malloc(len_message);
117 if( length_key_chain < 1) {
118 free( message);
119 return -1;
120 }
121 issuer->length_key_chain = length_key_chain;
122 issuer->key_chain = (RSA **)malloc(sizeof(RSA *) * length_key_chain);
123 issuer->pk_signatures = (BYTE **)malloc(sizeof(BYTE *) * length_key_chain);
124 for(i = 0; i<length_key_chain; i++) {
125 rsa = RSA_generate_key( DAA_PARAM_KEY_SIZE, e, &callback, NULL);
126 if( (BN_num_bits(rsa->n) + 7) / 8 != (DAA_PARAM_KEY_SIZE + 7) / 8) {
127 LogError("BN_num_bits(rsa->n) + 7) / 8 != (DAA_PARAM_KEY_SIZE + 7) / 8)");
128 return -1;
129 }
130 issuer->key_chain[i] = rsa;
131 if( i > 0) {
132 signature = (BYTE *)malloc( RSA_size(rsa));
133 modulus = (BYTE *)malloc( DAA_PARAM_KEY_SIZE / 8);
134 // signature algorithm from Issuer.java - "SHA1withRSA"
135 // sign the modulus (n) of the RSA key with the previous RSA key (chain)
136 // sign rsa(i)->n with auth_key_pairs[i-1]
137 LogDebug("modulus=%s\n", dump_byte_array(256, modulus));
138 LogDebug("signature=%s\n", dump_byte_array(256, signature));
139 bi = bi_new_ptr();
140 bi_set_as_hex( bi, BN_bn2hex( rsa->n));
141 bi_2_byte_array( modulus, DAA_PARAM_KEY_SIZE / 8, bi);
142 LogDebug("bi=%s", bi_2_hex_char( bi));
143 bi_free_ptr( bi);
144 EVP_DigestInit_ex(ctx, EVP_sha1(), NULL);
145 EVP_DigestUpdate(ctx, modulus, DAA_PARAM_KEY_SIZE / 8);
146 EVP_DigestFinal_ex(ctx, message, ¤t_len_message);
147 ret = RSA_sign( NID_sha1, message, current_len_message,
148 signature, &len_sign, issuer->key_chain[i-1]);
149 if( ret == 0) {
150 LogError("Error in RSA_sign: %s",
151 ERR_error_string( ERR_get_error(), NULL));
152 }
153 LogDebug("Sign rsa->n (length=%d) with signature (length=%d,\
154 truelength=%d message_len=%d) ret = %d ERROR?=%s",
155 RSA_size(rsa),
156 DAA_PARAM_KEY_SIZE / 8,
157 len_sign,
158 current_len_message,
159 ret,
160 ERR_error_string( ERR_get_error(),
161 NULL) );
162 LogDebug("message=%s\n", dump_byte_array(256, message));
163 LogDebug("signature=%s\n",dump_byte_array(256, signature));
164 issuer->pk_signatures[i-1] = signature;
165 }
166 }
167 free( message);
168 EVP_MD_CTX_destroy(ctx);
169 return 0;
170 }
171
initIssuer(int length_key_chain,char * filename,char * exec,TSS_HCONTEXT hContext)172 Issuer* initIssuer(int length_key_chain, char *filename, char *exec, TSS_HCONTEXT hContext) {
173 FILE *file;
174 EVP_MD_CTX *mdctx;
175 Issuer *issuer = (Issuer *)malloc(sizeof( Issuer));
176 TPM_DAA_ISSUER *tpm_daa_issuer;
177 bi_ptr modulus_N0;
178 int len_issuer_settings, len_signature;
179 BYTE *modulus_N0_bytes;
180 BYTE *digest_n0;
181 BYTE *issuer_settings_byte_array;
182 BYTE *sign_data;
183 BYTE *signature;
184 RSA *private_nn;
185 KEY_PAIR_WITH_PROOF_internal *key_pair_with_proof;
186
187 LogDebug("Loading issuer info (keypair & proof) -> \'%s\'", filename);
188 file = fopen( filename, "r");
189 if( file == NULL) {
190 fprintf( stderr, "%s: Error when opening \'%s\': %s\n",
191 exec,
192 filename,
193 strerror( errno));
194 free( issuer);
195 return NULL;
196 }
197 key_pair_with_proof = load_KEY_PAIR_WITH_PROOF( file);
198 if( key_pair_with_proof == NULL) {
199 LogError( "Error when reading \'%s\': %s\n", filename, strerror( errno));
200 free( issuer);
201 return NULL;
202 }
203 fclose( file);
204 issuer->pk = key_pair_with_proof->pk;
205 issuer->pk_extern = i_2_e_TSS_DAA_PK( issuer->pk, &alloc, hContext);
206 issuer->key_pair_extern = (TSS_DAA_KEY_PAIR *)malloc( sizeof(TSS_DAA_KEY_PAIR));
207 init_tss_version( issuer->key_pair_extern);
208 issuer->key_pair_extern->public_key = issuer->pk_extern;
209 issuer->key_pair_extern->private_key = i_2_e_TSS_DAA_PRIVATE_KEY(
210 key_pair_with_proof->private_key,
211 &alloc, hContext);
212 issuer->pk_proof = key_pair_with_proof->proof;
213 issuer->private_key = key_pair_with_proof->private_key;
214 init_key_chain( length_key_chain, issuer);
215 issuer->zeta = compute_zeta( issuer->pk->issuerBaseNameLength,
216 issuer->pk->issuerBaseName, issuer->pk);
217 // sign "issuer settings"
218 modulus_N0 = bi_new_ptr();
219 bi_set_as_hex( modulus_N0, BN_bn2hex( issuer->key_chain[0]->n));
220 // in TPM, N0 is hashed by hashing the scratch (256 bytes) so it must
221 // be formatted according to the scratch size (TPM_DAA_SIZE_issuerModulus)
222 modulus_N0_bytes = (BYTE *)malloc( TPM_DAA_SIZE_issuerModulus);
223 bi_2_byte_array( modulus_N0_bytes, TPM_DAA_SIZE_issuerModulus, modulus_N0);
224 bi_free_ptr( modulus_N0);
225
226 if( TPM_DAA_SIZE_issuerModulus * 8 != DAA_PARAM_KEY_SIZE) {
227 LogError("TPM_DAA_SIZE_issuerModulus * 8 (%d) != DAA_PARAM_KEY_SIZE(%d)",
228 TPM_DAA_SIZE_issuerModulus*8,
229 DAA_PARAM_KEY_SIZE);
230 free( issuer);
231 return NULL;
232 }
233
234 EVP_MD_CTX_create(mdctx);
235 EVP_DigestInit_ex(mdctx, DAA_PARAM_get_message_digest(), NULL);
236 // digestN0 = hash( modulus_N0)
237 EVP_DigestUpdate(mdctx, modulus_N0_bytes, TPM_DAA_SIZE_issuerModulus);
238 digest_n0 = (BYTE *)EVP_MD_CTX_create();
239 EVP_DigestFinal_ex(mdctx, digest_n0, NULL);
240 tpm_daa_issuer = convert2issuer_settings( issuer->pk);
241 issuer_settings_byte_array = issuer_2_byte_array( tpm_daa_issuer, &len_issuer_settings);
242 // data to sign: concatenation of digest_n0 and issuer_settings_byte_array
243 sign_data = (BYTE *)malloc( EVP_MD_CTX_size(mdctx) + len_issuer_settings);
244 memcpy( sign_data, digest_n0, EVP_MD_CTX_size(mdctx));
245 memcpy( &sign_data[EVP_MD_CTX_size(mdctx)],
246 issuer_settings_byte_array,
247 len_issuer_settings);
248 free( issuer_settings_byte_array);
249 // sign digest of TPM compatible Issuer key (sign_data)
250 private_nn = issuer->key_chain[issuer->length_key_chain - 1];
251 signature = (BYTE *)malloc( RSA_size(private_nn));
252 if ( sign( sign_data, EVP_MD_CTX_size(mdctx) + len_issuer_settings,
253 private_nn,
254 signature,
255 &len_signature) ==0) {
256 LogError("Can not sign digest of TPM compatible Issuer key");
257 goto close;
258 }
259 issuer->pk_signatures[ issuer->length_key_chain - 1] = signature;
260 LogDebug("Set last signature sign[%d] = %s",
261 issuer->length_key_chain - 1,
262 dump_byte_array(EVP_MD_size( EVP_sha1()),
263 signature));
264 // TODO sign the complete public key of TPM compatible Issuer key
265 /* EVP_DigestInit_ex(mdctx, DAA_PARAM_get_message_digest(), NULL);
266 EVP_DigestUpdate(mdctx, digest_n0, EVP_MD_CTX_size(mdctx));
267 pk_encoded = encoded_DAA_PK_internal( &pk_encodedLength, issuer->pk);
268 EVP_DigestUpdate(mdctx, pk_encoded, pk_encodedLength);
269 EVP_DigestFinal(mdctx, , NULL);
270 signature = (BYTE *)malloc( EVP_MD_size( EVP_sha1()));
271 if (sign( sign_data, EVP_MD_CTX_size(mdctx) + len_issuer_settings,
272 private_nn, signature, &len_signature) !=0) goto close;
273 */
274 close:
275 EVP_MD_CTX_destroy(mdctx);
276 free( digest_n0);
277 free( sign_data);
278 return issuer;
279 }
280
print_usage(char * exec)281 int print_usage(char *exec) {
282 fprintf(stderr, "usage: %s\n", exec);
283 fprintf(stderr, "\t-if,\t--issuer_file\n\t\tthe file that will contain all key\
284 pair and proof to be used by the issuer\n\t\t (default: %s)\n",
285 DEFAULT_FILENAME);
286 fprintf(stderr, "\t-dc,\t--daa_counter\n\t\tdaa counter (default: %d)\n",
287 DEFAULT_DAACOUNTER);
288 fprintf(stderr,
289 "\t-pw,\t--passwd\n\t\ttpm owner password (default: %s)\n",
290 DEFAULT_OWN_PASSWD);
291 return -1;
292 }
293
main(int argc,char * argv[])294 int main(int argc, char *argv[]) {
295 TSS_HCONTEXT hContext;
296 TSS_RESULT result;
297 TSS_HTPM hTPM;
298 TSS_HPOLICY hPolicy;
299 int i, length;
300 char *param, *filename = DEFAULT_FILENAME;
301 char *credential_filename = DEFAULT_CREDENTIAL_FILENAME;
302 UINT32 daaCounter = DEFAULT_DAACOUNTER;
303 UINT32 capital_UPrimeLength;
304 BYTE *capitalUPrime;
305 TSS_DAA_IDENTITY_PROOF identityProof;
306 TSS_DAA_JOIN_SESSION joinSession;
307 TSS_DAA_JOIN_ISSUER_SESSION join_issuer_session;
308 TSS_DAA_CREDENTIAL_REQUEST credentialRequest;
309 TSS_DAA_CRED_ISSUER credIssuer;
310 TSS_HDAA hDAA;
311 Issuer* issuer;
312 char *szTpmPasswd = DEFAULT_OWN_PASSWD;
313 UINT32 endorsementKeyLength;
314 BYTE *endorsementKey;
315 UINT32 nonceIssuerLength;
316 BYTE *nonceIssuer;
317 UINT32 authenticationChallengeLength;
318 BYTE *authenticationChallenge;
319 bi_array_ptr capital_receiver;
320 BYTE **attributesPlatform;
321 UINT32 attributesPlatformLength;
322 BYTE **attributesIssuer;
323 UINT32 attributesIssuerLength;
324 bi_t random;
325 FILE *file;
326
327 init_tss_version( &identityProof);
328 init_tss_version( &joinSession);
329 init_tss_version( &join_issuer_session);
330 init_tss_version( &credentialRequest);
331 init_tss_version( &credIssuer);
332 i = 1;
333 while( i < argc) {
334 param = argv[ i];
335 if ( strcmp( param, "-if") == 0 || strcmp( param, "--issuer_file") == 0) {
336 i++;
337 if( i == argc) return print_usage( argv[0]);
338 filename = argv[i];
339 } else if( strcmp( param, "-dc") == 0 || strcmp( param, "--daa_counter") == 0){
340 i++;
341 if( i == argc) return print_usage( argv[0]);
342 daaCounter = atoi(argv[i]);
343 } else if( strcmp( param, "-pw") == 0 || strcmp( param, "--passwd") == 0){
344 i++;
345 if( i == argc) return print_usage( argv[0]);
346 szTpmPasswd = argv[i];
347 } else {
348 fprintf(stderr, "\n%s:unrecognized option <%s>\n", argv[0], param);
349 return print_usage( argv[0]);
350 }
351 i++;
352 }
353 bi_init( NULL);
354
355 // Create Context
356 LogDebug("Create Context");
357 result = Tspi_Context_Create( &hContext );
358 if ( result != TSS_SUCCESS )
359 {
360 LogError( "Tspi_Context_Create %d\n", result );
361 goto out;
362 }
363 // Connect to Context
364 result = Tspi_Context_Connect( hContext, NULL );
365 if ( result != TSS_SUCCESS) goto out_close;
366 printf("\nConnect to the context: %X\n", hContext);
367
368 if( (result = Tspi_Context_GetTpmObject( hContext, &hTPM)) != TSS_SUCCESS)
369 goto out_close;
370 // Get the correct policy using the TPM ownership PASSWD
371 if( (result = Tspi_GetPolicyObject( hTPM,
372 TSS_POLICY_USAGE,
373 &hPolicy)) != TSS_SUCCESS)
374 goto out_close;
375 if( (result = Tspi_Policy_SetSecret( hPolicy,
376 TSS_SECRET_MODE_PLAIN,
377 strlen( szTpmPasswd),
378 szTpmPasswd)) != TSS_SUCCESS)
379 goto out_close;
380 LogDebug("Tspi_Policy_SetSecret hPolicy received;%d\n", hPolicy);
381
382 //Create Object
383 result = obj_daa_add( hContext, &hDAA);
384 if (result != TSS_SUCCESS) {
385 LogError("Tspi_Context_CreateObject:%d\n", result);
386 Tspi_Context_Close(hContext);
387 LogError("%s: %s\n", argv[0], err_string(result));
388 exit(result);
389 }
390 LogDebug("created DAA object:%X", hDAA);
391 issuer = initIssuer( DEFAULT_KEY_CHAIN_LENGTH, filename, argv[0], hContext);
392 if( issuer == NULL) goto out_close;
393
394 // generate receiver attributes and issuer attributes (random)
395 attributesPlatformLength = issuer->pk->capitalRReceiver->length;
396 attributesPlatform = (BYTE **)malloc( attributesPlatformLength * sizeof(BYTE *));
397 bi_new( random);
398 for( i=0; i<(int)attributesPlatformLength; i++) {
399 bi_urandom( random, DAA_PARAM_SIZE_F_I);
400 attributesPlatform[i] = bi_2_nbin( &length, random);
401 if( attributesPlatform[i] == NULL) {
402 LogError("malloc of %d bytes failed", length);
403 result = TSPERR(TSS_E_OUTOFMEMORY);
404 goto out_close;
405 }
406 }
407 attributesIssuerLength = issuer->pk->capitalRIssuer->length;
408 attributesIssuer = (BYTE **)malloc( attributesIssuerLength * sizeof(BYTE *));
409 for( i=0; i<(int)attributesIssuerLength; i++) {
410 bi_urandom( random, DAA_PARAM_SIZE_F_I);
411 attributesIssuer[i] = bi_2_nbin( &length, random);
412 if( attributesIssuer[i] == NULL) {
413 LogError("malloc of %d bytes failed", length);
414 result = TSPERR(TSS_E_OUTOFMEMORY);
415 goto out_close;
416 }
417 }
418 bi_free(random);
419 LogDebug("Generated attributes (Platform=%d,Issuer=%d)",
420 attributesPlatformLength, attributesIssuerLength);
421
422 result = Tspi_TPM_DAA_JoinInit(
423 hDAA, // in
424 hTPM, // in
425 daaCounter, // in
426 (TSS_HKEY)issuer->pk_extern, // in
427 issuer->length_key_chain, // in
428 (TSS_HKEY *)issuer->key_chain, // in
429 issuer->length_key_chain, // in
430 issuer->pk_signatures, // in
431 &capital_UPrimeLength, // out
432 &capitalUPrime, // out
433 &identityProof, // out
434 &joinSession // out
435 );
436 if( result != TSS_SUCCESS) goto out_close;
437
438 result = Tspi_DAA_IssueInit(
439 hDAA, // in
440 (TSS_HKEY)issuer->key_chain[0], // in
441 (TSS_HKEY)issuer->key_pair_extern, // in
442 identityProof, // in
443 capital_UPrimeLength, // in
444 capitalUPrime, // in
445 daaCounter, // in
446 &nonceIssuerLength, // out
447 &nonceIssuer, // out
448 &authenticationChallengeLength, // out
449 &authenticationChallenge, // out
450 &join_issuer_session // out
451 );
452 if( result != TSS_SUCCESS) goto out_close;
453
454 result = Tspi_TPM_DAA_JoinCreateDaaPubKey(
455 hDAA, // in
456 hTPM, // in
457 authenticationChallengeLength, // in
458 authenticationChallenge, // in
459 nonceIssuerLength, // in
460 nonceIssuer, // in
461 attributesPlatformLength, // in
462 attributesPlatform, // in
463 &joinSession, // in & out
464 &credentialRequest // out
465 );
466 if( result != TSS_SUCCESS) goto out_close;
467
468 result = Tspi_DAA_IssueCredential(
469 hDAA, // in
470 attributesIssuerLength, // in
471 attributesIssuer, // in
472 credentialRequest, // in
473 join_issuer_session, // in
474 &credIssuer // out
475 );
476
477 result = Tspi_TPM_DAA_JoinStoreCredential(
478 hDAA, // in
479 hTPM, // in
480 credIssuer, // in
481 joinSession, // in
482 (TSS_HKEY*)&credentialRequest // out
483 );
484 if( result != TSS_SUCCESS) goto out_close;
485
486 printf("Saving credential: %s ", credential_filename);
487 file = fopen( credential_filename, "w");
488 if( save_TSS_DAA_CREDENTIAL( file, &credentialRequest) != 0) {
489 LogError( "[test_join]: Error when saving \'%s\': %s",
490 credential_filename,
491 strerror( errno));
492 result = TSS_E_FAIL;
493 goto out_close;
494 }
495 fclose( file);
496 printf("Done\n");
497
498 out_close:
499 Tspi_Context_FreeMemory( hContext, NULL );
500 Tspi_Context_Close( hContext );
501 out:
502 bi_release();
503 LogDebug("THE END result=%d:%s",result, err_string( result) );;
504 return result;
505 }
506