My favorites | Sign in
Project Home Downloads Wiki Issues Source
Repository:
Checkout   Browse   Changes   Clones    
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
/*
*
* TRECC/tpm_util.c: - creates a signing key as a child of the SRK, stores in SYSTEM persistent storage (-n)
* - signs imageID SHA1 meta-digest in 40-character ASCII encoding (-s -i#)
* - lists all persistent keys (-l)
* - clears all SYSTEM persistent keys (except the SRK) (-r)
*
* Copyright: 2010 Paul Makowski
* License: GPLv2
* Contact: my.hndl@gmail.com | http://paulmakowski.wordpress.com
*
* Ref: - A Practical Guide to Trusted Computing, pp. 83-84
* - http://www.privacyca.com/code.html
* - http://docs.hp.com/en/5991-7466/apb.html
* - more, as seen inline
*
* Known Issues:
* - nasty error on TPM lock; need to implement fcntl() with file locks to better manage TPM
*
* Usage:
* $ gcc [-Wall -ggdb] -ltspi -luuid -lsqlite3 tpm_util.c -o tpm_util
*
* Notes:
* - allow ~5s for signing operation (-s) (bounded by TPM speed; consistantly ~2.8s on 2.6Ghz Core 2 Duo)
* - allow ~2m for key creation (-n) (bounded primarily by the entropy pool I believe; varies heavily)
* - reset SYSTEM persistent keys and & list operations (-r, -l) take a trivial amount of time
*
*/

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <trousers/tss.h>
#include <trousers/trousers.h>
#include <sqlite3.h>


#define ACTION_CREATE 0
#define ACTION_SIGN 1
#define ACTION_LIST 2
#define ACTION_RESET 3
#define INVALID_FLAG -1

#define TRECC_SRK_SECRET_MODE TSS_SECRET_MODE_PLAIN // DISABLED FOR NOW -- SRK and OWNER passwords will be well-known (NULL) in v0.1
#define TRECC_OWNER_SECRET (BYTE *)"t\0r\0e\0c\0c\0" // 16bit (dual byte) unicode hack
#define TRECC_SRK_SECRET (BYTE *)"t\0r\0e\0c\0c\0" // as seen here: http://blog.gmane.org/gmane.comp.encryption.trousers.devel/month=20090101
#define TRECC_OWNER_SECRET_LEN 10 // strlen("trecc") * 2
#define TRECC_SRK_SECRET_LEN 10 // ^ditto^
#define TRECC_DB_LOCATION "/etc/trecc/trecc.sqlite"

#define SHA1_DIGEST_LENGTH 20 // we're signing SHA1 hashes which /must/ be 20B long


/* globals */
int resultCode, debug = 0, verboseDebug, imageID = INVALID_FLAG;
char debugMsg[1024], query[1024], *errMsg = 0, *digestHex = 0;
sqlite3 *db;
TSS_HCONTEXT hContext;
TSS_RESULT result;
TSS_UUID SRK_UUID = TSS_UUID_SRK; /* from tss_defines.h: #define TSS_UUID_SRK {0, 0, 0, 0, 0, {0, 0, 0, 0, 0, 1}} // Storage root key */
TSS_UUID keyUUID = {'T', 'R', 'E', 'C', 'C', {0, 0, 0, 0, 0, 0}}; // for simplicity's sake, this will be static

void debugLog(char *debugMsg) { if (debug) printf("%s\n", debugMsg); }

void checkErr(TSS_RESULT result, char *funcName)
{
if (verboseDebug || result != TSS_SUCCESS) { printf("[!] %s returned errno: 0x%x, error: %s\n", funcName, result, Trspi_Error_String(result)); }
if (result != TSS_SUCCESS) { Tspi_Context_FreeMemory(hContext, NULL); Tspi_Context_Close(hContext); exit(1); }
}

/* modified from: http://article.gmane.org/gmane.comp.encryption.trousers.scm/2141 */
void print_KM_KEYINFO2(TSS_KM_KEYINFO2 *k)
{
printf("Version : %hhu.%hhu.%hhu.%hhu\n", k->versionInfo.bMajor, k->versionInfo.bMinor,
k->versionInfo.bRevMajor, k->versionInfo.bRevMinor);
printf("UUID : %08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx\n",
k->keyUUID.ulTimeLow, k->keyUUID.usTimeMid, k->keyUUID.usTimeHigh,
k->keyUUID.bClockSeqHigh, k->keyUUID.bClockSeqLow,
k->keyUUID.rgbNode[0] & 0xff, k->keyUUID.rgbNode[1] & 0xff,
k->keyUUID.rgbNode[2] & 0xff, k->keyUUID.rgbNode[3] & 0xff,
k->keyUUID.rgbNode[4] & 0xff, k->keyUUID.rgbNode[5] & 0xff);
printf("parent UUID : %08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx\n",
k->parentKeyUUID.ulTimeLow, k->parentKeyUUID.usTimeMid, k->parentKeyUUID.usTimeHigh,
k->parentKeyUUID.bClockSeqHigh, k->parentKeyUUID.bClockSeqLow,
k->parentKeyUUID.rgbNode[0] & 0xff, k->parentKeyUUID.rgbNode[1] & 0xff,
k->parentKeyUUID.rgbNode[2] & 0xff, k->parentKeyUUID.rgbNode[3] & 0xff,
k->parentKeyUUID.rgbNode[4] & 0xff, k->parentKeyUUID.rgbNode[5] & 0xff);
printf("Auth? : %s\n", k->bAuthDataUsage ? "YES" : "NO");

if (k->persistentStorageType == TSS_PS_TYPE_SYSTEM) printf("Store : System\n");
else if (k->persistentStorageType == TSS_PS_TYPE_USER) printf("Store : User\n");
else printf("Store : Error\n");

if (k->persistentStorageTypeParent == TSS_PS_TYPE_SYSTEM) printf("Parent Store : System\n");
else if (k->persistentStorageTypeParent == TSS_PS_TYPE_USER) printf("Parent Store : User\n");
else printf("Parent Store : Error\n");

if (k->ulVendorDataLength) printf("Vendor Data : \"%s\" (%u bytes)\n", k->rgbVendorData, k->ulVendorDataLength);
else printf("Vendor Data : (0 bytes)\n");

/* custom additions below */
printf("Loaded? : %s\n", k->fIsLoaded ? "YES" : "NO");
printf("\n");
}


/* this will be the callback for the sqlite3_exec() call in main()
* this is disjoint from the actual signHash() function so as to minimize DB locking while the TPM is signing
* this function will return quickly, allowing sqlite3_exec() to release its lock and allow signHash() to create a new one */
static int signHashCallback(void *NotUsed, int argc, char **argv, char **azColName)
{
/* copy argv[0] (the digestHex) to the heap so that it doesn't get destroyed on return from this function */
digestHex = malloc(41); // 40 characters for the 2-character hex encoding, 1 char for the NULL byte
strncpy(digestHex, argv[0], 40); // copy the first 40 characters from argv[0] into the location pointed to by digestHex (there should be only 40)
return 0;
}


void signHash(void)
{
/* locals */
BYTE digestBin[20], *sig;
UINT32 sigLen;
TSS_HHASH hHash;
TSS_HPOLICY srkPolicy, sigKeyPolicy;
TSS_HKEY hSRK, hSigningKey;


/*
* OpenSSL generates a 20B SHA1 digest which measure.c converts into a 40-character hex representation for easy debugging
* this is done to gaurantee the ability to repesent the digest in printable ASCII
* the problem: trousers' TSPI expects a digest in binary format, so we need to the digest hex string back to binary
* the solution: binary OR every pair of characters in the OpenSSL format to achieve binary encoding of the digest
* in MySQL, this is called "UNHEX", Python: "binascii.unhexlify(hexstr)", in C we need to code it ourselves
*/
unsigned char high, low;
int i; for (i=0; i<20; i++)
{
// right now we're viewing the chars as chars...let's convert them to chars holding only the hex value they describe
// this means 'high' will contain XXXX0000 and 'low' will contain 0000XXXX (in binary, where X is either 1 or 0)
high = digestHex[i*2];
low = digestHex[(i*2)+1];

if (48 <= high && high <= 57) high = (high-48) << 4; // high is one of [0-9]; adjust value to the hex nibble it describes; shift left
else if (97 <= high && high <= 102) high = (high-87) << 4; // high is one of [a-f]; adjust value to the hex nibble it describes; shift left
else { snprintf(debugMsg, sizeof(debugMsg), "[!] ERROR: invalid hex value '0x%x' in digest @ offset %d; exiting.", high, i*2); debugLog(debugMsg); exit(1); }

if (48 <= low && low <= 57) low -= 48; // low is one of [0-9]; adjust value to the hex nibble it describes
else if (97 <= low && low <= 102) low -= 87; // low is one of [a-f]; adjust value to the hex nibble it describes
else { snprintf(debugMsg, sizeof(debugMsg), "[!] ERROR: invalid hex value '0x%x' in digest @ offset %d; exiting.", high, i*2+1); debugLog(debugMsg); exit(1); }
digestBin[i] = high | low; // OR the high and low nibbles, store in digestBin
}


/* load SRK (this will be our new key's parent); get SRK's policy; populate policy with SRK password */
result = Tspi_Context_LoadKeyByUUID(hContext, TSS_PS_TYPE_SYSTEM, SRK_UUID, &hSRK); checkErr(result, "Tspi_Context_LoadKeyByUUID()");
result = Tspi_GetPolicyObject(hSRK, TSS_POLICY_USAGE, &srkPolicy); checkErr(result, "Tspi_GetPolicyObject()");

/* TODO: SRK passwords temporarily disabled due to Bash piping to tpm_takeownership -u quirk during .deb installation
result = Tspi_Policy_SetSecret ( srkPolicy, // we're operating on SRK's policy
TRECC_SRK_SECRET_MODE, // this translates to TSS_SECRET_MODE_PLAIN
TRECC_SRK_SECRET_LEN, // specified at the beginning of this file
TRECC_SRK_SECRET ); // ^ditto^
*/
result = Tspi_Policy_SetSecret ( srkPolicy, // we're operating on SRK's policy
TSS_SECRET_MODE_NONE, // this translates to TSS_SECRET_MODE_PLAIN
0, // specified at the beginning of this file
NULL ); // ^ditto^
checkErr(result, "Tspi_Policy_SetSecret()");


/* load signing key by UUID; point to it with hSigningKey -- static for now */
result = Tspi_Context_LoadKeyByUUID ( hContext, // load the key into this context
TSS_PS_TYPE_SYSTEM, // signing key stored in SYSTEM-wide presistent storage
keyUUID, // indexed by its UUID
&hSigningKey ); // point to the key with hSigningKey
checkErr(result, "Tspi_Context_LoadKeyByUUID()");


/* create usage policy object for the key, set NULL secret in policy, assign policy to key object */
result = Tspi_Context_CreateObject ( hContext, // create in the current context
TSS_OBJECT_TYPE_POLICY, // this is a POLICY object
TSS_POLICY_USAGE, // "a usage policy (for authorization to use an object)"
&sigKeyPolicy ); // point to this object with 'sigKeyPolicy'
checkErr(result, "Tspi_Context_CreateObject()");
result = Tspi_Policy_SetSecret ( sigKeyPolicy, // operating on the newly created object
TSS_SECRET_MODE_NONE, // no secret to this object (remember: this is really just a PoC)
0, // the well-known (NULL) secret has 0 length
NULL ); // pointer to the secret (NULL)
checkErr(result, "Tspi_Policy_SetSecret()");
result = Tspi_Policy_AssignToObject ( sigKeyPolicy, // we're assigning this new policy with no secret to...
hSigningKey ); // the signing key pointed to by 'hSigningKey'
checkErr(result, "Tspi_Policy_AssignToObject()");


/* create hash object as type SHA1, populate with the digest to be hashed */
result = Tspi_Context_CreateObject ( hContext, // create in the current context
TSS_OBJECT_TYPE_HASH, // this is a hash objectType; ref: http://linux.die.net/man/3/tspi_context_createobject
TSS_HASH_SHA1, // SHA1 hash; other option is 'TSS_HASH_OTHER', which isn't handled by TPM
// ref: A Praint c, action = -1;ctical Guide to Trusted Computing, p.97
&hHash ); // point to the hash object with hHash
checkErr(result, "Tspi_Context_CreateObject()");
result = Tspi_Hash_SetHashValue ( hHash, // a pointer to the hash data struct that we are populating
SHA1_DIGEST_LENGTH, // SHA1 always produces a 20B output
(BYTE *)digestBin ); // pointer to the digest (data to the signed)
checkErr(result, "Tspi_Hash_SetHashValue()");


/* have TPM sign the hash */
/* TODO: implement locking to minimize time during which the TPM is inactive */
result = Tspi_Hash_Sign ( hHash, // a pointer to the hash struct that contains the digest to be signed
hSigningKey, // a pointer to the key that will be used to sign
&sigLen, // this will hold the length of the signature generated
&sig ); // pointer to the signature generated
checkErr(result, "Tspi_Hash_Sign()");


/* verify TPM's signature */
if (sigLen != 256) { snprintf(debugMsg, sizeof(debugMsg), "[!] ERROR: expected signature length of 256B; got %dB", sigLen); debugLog(debugMsg); }
result = Tspi_Hash_VerifySignature ( hHash, // pointer to the hash object we're verifying
hSigningKey, // pointer to the key object used for signing
sigLen, // length of the signature
sig ); // pointer to the signature itself
checkErr(result, "Tspi_Hash_VerifySignature()");


/* convert signature to hex string */
char sigString[513];
for (i = 0; i < 256; i++) { sprintf(sigString+(i*2), "%02x", sig[i]); }
sigString[512] = '\0'; // terminate the string


/* reconnect to the DB, store signature */
resultCode = sqlite3_open(TRECC_DB_LOCATION, &db);
sqlite3_busy_timeout(db, 5000);
if (resultCode != SQLITE_OK) {
snprintf(debugMsg, sizeof(debugMsg), "can't open database: %s; exiting...", sqlite3_errmsg(db)); debugLog(debugMsg);
sqlite3_close(db); exit(1);
}
snprintf(query, sizeof(query), "UPDATE policy SET sig='%s' WHERE imageID='%d'", sigString, imageID);
snprintf(debugMsg, sizeof(debugMsg), "[+] SIGNED imageID %d's meta-digest (%s)", imageID, digestHex); debugLog(debugMsg);
resultCode = sqlite3_exec ( db, // handle to DB that we're querying
query, // the query we just built
NULL, // callback function
0, // 1st argument to callback (we're not using this)
&errMsg); // point to error message with errMsg
if (resultCode != SQLITE_OK)
{
snprintf(debugMsg, sizeof(debugMsg), "[!] ERROR: storing signature failed. SQL error: '%s'; exiting...", errMsg);
sqlite3_free(errMsg); debugLog(debugMsg); exit(1);
}


/* done */
Tspi_Key_UnloadKey(hSRK); Tspi_Key_UnloadKey(hSigningKey);
free(digestHex);
sqlite3_close(db);
return;
}


int main (int argc, char **argv)
{
/* parse & validate args */
int c, action = INVALID_FLAG;
while ((c = getopt (argc, argv, "dvnslrk:i:")) != -1)
switch (c)
{
case 'd': debug = 1; break; // no output unless this is flagged
case 'v': verboseDebug = 1; break; // print errno and error messages even on success
case 'n': action = ACTION_CREATE; break; // create a new key to be used for signing
case 's': action = ACTION_SIGN; break; // we're going to be signing a hash with a TPM key
case 'l': action = ACTION_LIST; break; // list all the keys in persistent storage (USER, SYSTEM)
case 'r': action = ACTION_RESET; break; // clear all keys (but the root) in SYSTEM persistent storage
case 'i': imageID = strtol(optarg, NULL, 0);break; // imageID (for signing meta-digest)
case '?':
if (isprint (optopt)) { snprintf(debugMsg, sizeof(debugMsg), "unknown option `-%c'.", optopt); debugLog(debugMsg); }
else { snprintf(debugMsg, sizeof(debugMsg), "unknown option character `\\x%x'.", optopt); debugLog(debugMsg); }
return 1;

default: abort();
}
if (action == INVALID_FLAG) { snprintf(debugMsg, sizeof(debugMsg), "[!] FATAL: no action selected; valid actions: [-n, -s, -r, -l]"); debugLog(debugMsg); exit(1); }
if (action == ACTION_SIGN && imageID == INVALID_FLAG) { snprintf(debugMsg, sizeof(debugMsg), "[!] FATAL: no imageID specified"); debugLog(debugMsg); exit(1); }


/* create context, connect it to local TCS */
result = Tspi_Context_Create( &hContext ); // create context struct in memory, point to it with hContext
checkErr(result, "Tspi_Context_Create()");
result = Tspi_Context_Connect ( hContext, // the context pointed to by hContext..
NULL ); // is to be connected to the local TCS
checkErr(result, "Tspi_Context_Connect()");


/* LIST INFO ON KEYS IN USER & SYSTEM PERSISTENT STORAGE */
if (action == ACTION_LIST)
{
TSS_KM_KEYINFO2 *keys;
UINT32 keysLen;

Tspi_Context_GetRegisteredKeysByUUID2 ( hContext, // get info on current context
TSS_PS_TYPE_SYSTEM, // it appears to ignore this and prints both SYSTEM and USER persistent keys
NULL, // NULL in this UUID field means "give me info on all the keys"; otherwise this would provide // data about all the keys in the path leading to the identified key
&keysLen, // will store the number of array entries retrieved
&keys ); // this will point to actual key heirarchy

printf("\nKeys currently stored in persistent storage (USER and SYSTEM stores):\n");
printf("---------------------------------------------------------------------\n");
int i; for (i=0; i<keysLen; i++) { print_KM_KEYINFO2(&keys[i]); }
}


/* CLEAR ALL THE KEYS IN SYSTEM PERSISTENT STORAGE EXCEPT THE SRK */
if (action == ACTION_RESET)
{
/* locals */
int keysRemoved = 0;
UINT32 persistentKeysLen;
TSS_HKEY *hDeletedKey; // TODO: GCC complains about this; come back to this
TSS_KM_KEYINFO2 *persistentKeys;

printf("\nRemoving the all non-root keys from SYSTEM persistent storage:\n");

/* get all persistent keys, point to the array of structs with 'persistentKeys' */
Tspi_Context_GetRegisteredKeysByUUID2 ( hContext, // get info on current context
TSS_PS_TYPE_SYSTEM, // it appears to ignore this and prints both SYSTEM and USER persistent keys
NULL, // NULL in this UUID field means "give me info on all the keys"; otherwise this would // only provide data about all the keys in the path leading to the identified key
&persistentKeysLen, // will store the number of array entries retrieved
&persistentKeys ); // this will point to actual key heirarchy


char keyUUIDString[38], parentUUIDString[38];
int i; for (i=0; i<persistentKeysLen; i++)
{ TSS_KM_KEYINFO2 *k = &persistentKeys[i];

if (k->persistentStorageType != TSS_PS_TYPE_SYSTEM) continue; // we're only concerned with keys in SYSTEM persistent storage


/* get the parent UUID in the same format as displayed in the '-l' option */
snprintf(parentUUIDString, sizeof(parentUUIDString),
"%08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
k->parentKeyUUID.ulTimeLow, k->parentKeyUUID.usTimeMid, k->parentKeyUUID.usTimeHigh,
k->parentKeyUUID.bClockSeqHigh, k->parentKeyUUID.bClockSeqLow,
k->parentKeyUUID.rgbNode[0] & 0xff, k->parentKeyUUID.rgbNode[1] & 0xff,
k->parentKeyUUID.rgbNode[2] & 0xff, k->parentKeyUUID.rgbNode[3] & 0xff,
k->parentKeyUUID.rgbNode[4] & 0xff, k->parentKeyUUID.rgbNode[5] & 0xff);

if (!strcmp(parentUUIDString, "00000000-0000-0000-0000-000000000000")) continue; // skip the root key (whose parent is the NULL UUID)


/* get key's UUID for reporting to user */
snprintf(keyUUIDString, sizeof(keyUUIDString),
"%08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
k->keyUUID.ulTimeLow, k->keyUUID.usTimeMid, k->keyUUID.usTimeHigh,
k->keyUUID.bClockSeqHigh, k->keyUUID.bClockSeqLow,
k->keyUUID.rgbNode[0] & 0xff, k->keyUUID.rgbNode[1] & 0xff,
k->keyUUID.rgbNode[2] & 0xff, k->keyUUID.rgbNode[3] & 0xff,
k->keyUUID.rgbNode[4] & 0xff, k->keyUUID.rgbNode[5] & 0xff);


/* delete key */
Tspi_Context_UnregisterKey ( hContext, // our current context
TSS_PS_TYPE_SYSTEM, // we're deleting from SYSTEM persistent storage
k->keyUUID, // we're deleting the current key's UUID
hDeletedKey ); // not sure why this is required
checkErr(result, "Tspi_Context_UnregisterKey()");


/* report to user */
printf("[-] UUID '%s' removed from SYSTEM persistent storage.\n", keyUUIDString);
keysRemoved++;
}

printf("%d keys removed.\n", keysRemoved);
printf("\n");
}


/* SIGNING HASH WITH EXISTING KEY */
if (action == ACTION_SIGN)
{
/* connect to DB; wait up to 20 seconds for lock */
resultCode = sqlite3_open(TRECC_DB_LOCATION, &db);
sqlite3_busy_timeout(db, 20000);
if (resultCode != SQLITE_OK) {
snprintf(debugMsg, sizeof(debugMsg), "can't open database: %s; exiting...", sqlite3_errmsg(db)); debugLog(debugMsg);
sqlite3_close(db); exit(1);
}


/* query DB for imageID's meta-digest, callback to signHash */
snprintf(query, sizeof(query), "SELECT metaHash FROM policy WHERE imageID='%d'", imageID);
resultCode = sqlite3_exec ( db, // handle to DB that we're querying
query, // the query we just built
signHashCallback, // callback function
0, // 1st argument to signHashCallback (we're not using this)
&errMsg); // point to error message with errMsg
if (resultCode != SQLITE_OK)
{
snprintf(debugMsg, sizeof(debugMsg), "[!] ERROR: metaHash retrieval on imageID %d failed. SQL error: %s; exiting...", imageID, errMsg);
sqlite3_free(errMsg); debugLog(debugMsg); exit(1);
}


/* minimize locking; sign hash, write to DB */
sqlite3_close(db);
signHash();
}


/* CREATING NEW SIGNING KEY */
if (action == ACTION_CREATE)
{
/* locals */
TSS_HKEY hSRK, hNewKey;
TSS_HPOLICY srkPolicy, newKeyPolicy;


/* load SRK (this will be our new key's parent); get SRK's policy; populate policy with SRK password */
result = Tspi_Context_LoadKeyByUUID ( hContext, // we're loading into the current context
TSS_PS_TYPE_SYSTEM, // ...from the SYSTEM persistent storage
SRK_UUID, // SRK's UUID is always the same
&hSRK ); // point to the loaded SRK with hSRK
checkErr(result, "Tspi_Context_LoadKeyByUUID()");
result = Tspi_GetPolicyObject ( hSRK, // we're dealing with SRK
TSS_POLICY_USAGE, // ...and getting its policy
&srkPolicy ); // ...which we'll point to with 'srkPolicy'
checkErr(result, "Tspi_GetPolicyObject()");
/* TODO: SRK passwords temporarily disabled due to Bash piping to tpm_takeownership -u quirk during .deb installation
result = Tspi_Policy_SetSecret ( srkPolicy, // we're operating on SRK's policy
TRECC_SRK_SECRET_MODE, // this translates to TSS_SECRET_MODE_PLAIN
TRECC_SRK_SECRET_LEN, // specified at the beginning of this file
TRECC_SRK_SECRET ); // ^ditto^
*/
result = Tspi_Policy_SetSecret ( srkPolicy, // we're operating on SRK's policy
TSS_SECRET_MODE_NONE, // this translates to TSS_SECRET_MODE_PLAIN
0, // specified at the beginning of this file
NULL ); // ^ditto^
checkErr(result, "Tspi_Policy_SetSecret()");


/* create object for the new key */
result = Tspi_Context_CreateObject ( hContext, // create in the current context...
TSS_OBJECT_TYPE_RSAKEY, // an RSA key
TSS_KEY_SIZE_2048 | // ...of length 2048bits
TSS_KEY_TYPE_SIGNING, // ...that will be used for signing
&hNewKey ); // we'll point to it with hNewKey
checkErr(result, "Tspi_Context_CreateObject() (created key object)");


/* create usage policy object for the key, set NULL secret in policy, assign policy to key object */
result = Tspi_Context_CreateObject ( hContext, // create in the current context...
TSS_OBJECT_TYPE_POLICY, // a policy object (for our new signing key)
TSS_POLICY_USAGE, // again, this is a policy object (this field is somewhat redundant for this operation)
&newKeyPolicy ); // point to the policy with 'newkeyPolicy'
checkErr(result, "Tspi_Context_CreateObject() (created policy object)");
result = Tspi_Policy_SetSecret ( newKeyPolicy, // we're setting the secret in the new policy object
TSS_SECRET_MODE_NONE, // the secret is: there is no secret
0, // no secret has 0 length
NULL ); // and is pointed to by NULL
checkErr(result, "Tspi_Policy_SetSecret()");
result = Tspi_Policy_AssignToObject ( newKeyPolicy, // we're assigning the newly created policy object (with no secret) to...
hNewKey ); // our new key
checkErr(result, "Tspi_Policy_AssignToObject()");


/* call down to the TPM to generate the key -- may take some time */
result = Tspi_Key_CreateKey ( hNewKey, // actually generate a key pair from the hNewKey struct (private portion stays in TPM)
hSRK, // the new key's parent is the SRK
0 ); // bind to PCR values; this is a PoC, so we don't care (in the real world we would)
checkErr(result, "Tspi_Key_CreateKey()");


/* store the key as a child of the SRK in user persistant storage */
result = Tspi_Context_RegisterKey ( hContext, // our current context
hNewKey, // pointer to the key object we are going to store
TSS_PS_TYPE_SYSTEM, // store in SYSTEM-wide persistent storage (was having problems with USER storage)
keyUUID, // our key's UUID
TSS_PS_TYPE_SYSTEM, // our key's parent is the SRK; it can be found in system-wide persistant storage
SRK_UUID ); // the SRK's UUID
checkErr(result, "Tspi_Context_RegisterKey()");

/* unload keys */
Tspi_Key_UnloadKey(hSRK); Tspi_Key_UnloadKey(hNewKey);
}


/* clean up, exit */
Tspi_Context_FreeMemory(hContext, NULL); checkErr(result, "Tspi_Context_FreeMemory()");
result = Tspi_Context_Close(hContext); checkErr(result, "Tspi_Context_Close()");
return 0;
}




Change log

e131b6694d7c by my.hndl on Jun 3, 2010   Diff
initial v0.1 checkin
Go to: 
Project members, sign in to write a code review

Older revisions

All revisions of this file

File info

Size: 24395 bytes, 497 lines
Powered by Google Project Hosting