/*
* The Initial Developer of the Original Code is International
* Business Machines Corporation. Portions created by IBM
* Corporation are Copyright (C) 2005 International Business
* Machines Corporation. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the Common Public License as published by
* IBM Corporation; either version 1 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Common Public License for more details.
*
* You should have received a copy of the Common Public License
* along with this program; if not, a copy can be viewed at
* http://www.opensource.org/licenses/cpl1.0.php.
*/
#include "tpm_tspi.h"
#include "tpm_utils.h"
TSS_HCONTEXT hContext = 0;
#ifdef TSS_LIB_IS_12
#include <limits.h>
//Controled by input options
static char in_filename[PATH_MAX] = "", out_filename[PATH_MAX] = "";
static BOOL isRevocable = FALSE;
static BOOL needGenerateSecret = FALSE;
static BOOL inFileSet = FALSE;
static BOOL outFileSet = FALSE;
static void help(const char *aCmd)
{
logCmdHelp(aCmd);
logCmdOption("-r, --revocable",
_("Creates a revocable EK instead of the default non-revocable one. Requires [-g -o] or [-i]"));
logCmdOption("-i, --infile FILE",
_("Filename containing the secret data used to revoke the EK."));
logCmdOption("-g, --generate-secret",
_("Generates a 20 Bytes secret that is used to revoke the EK. Requires [-o]"));
logCmdOption("-o, --outfile FILE",
_("Filename to write the secret data generated to revoke the EK."));
}
static int parse(const int aOpt, const char *aArg)
{
switch (aOpt){
case 'r':
isRevocable = TRUE;
break;
case 'g':
needGenerateSecret = TRUE;
break;
case 'i':
inFileSet = TRUE;
if (aArg){
strncpy(in_filename, aArg, PATH_MAX);
}
break;
case 'o':
outFileSet = TRUE;
if (aArg){
strncpy(out_filename, aArg, PATH_MAX);
}
break;
default:
return -1;
}
return 0;
}
static TSS_RESULT
tpmCreateRevEk(TSS_HTPM a_hTpm, TSS_HKEY a_hKey,
TSS_VALIDATION * a_pValData, UINT32 *revDataSz, BYTE **revData)
{
TSS_RESULT result = Tspi_TPM_CreateRevocableEndorsementKey(a_hTpm, a_hKey,
a_pValData, revDataSz, revData);
tspiResult("Tspi_TPM_CreateRevocableEndorsementKey", result);
return result;
}
static int readData(UINT32 bytesToRead, BYTE **buffer)
{
FILE *infile = NULL;
size_t iBytes;
int rc = 0;
BYTE eofile;
__memset(*buffer, 0x00, bytesToRead);
infile = fopen(in_filename, "r");
if ( !infile ){
logError(_("Unable to open input file: %s\n"),
in_filename);
return -1;
}
//Read the data
iBytes = fread( *buffer, 1, bytesToRead, infile );
if ( iBytes < bytesToRead ) {
logError(_("Error: the secret data file %s contains less than %d bytes. Aborting ...\n"),
in_filename, bytesToRead);
rc = -1;
} else if ( (iBytes = fread( &eofile, 1, 1, infile )) ) {
//Test if there's more than 20 bytes
if ( !feof( infile))
logMsg(_("WARNING: Using only the first %d bytes of file %s for secret data\n"),
bytesToRead, in_filename);
} else {
logDebug(_("Read %d bytes of secret data from file %s.\n"),
bytesToRead, in_filename);
}
fclose( infile);
return rc;
}
static int writeData(UINT32 bytesToWrite, BYTE *buffer)
{
FILE *outfile = NULL;
size_t iBytes;
int rc = 0;
logDebug(_("bytesToWrite: %d\n"), bytesToWrite);
outfile = fopen(out_filename, "w");
if ( !outfile ) {
logError(_("Unable to open output file: %s\n"), out_filename);
return -1;
}
//Write data in buffer
iBytes = fwrite( buffer, 1, bytesToWrite, outfile);
if ( iBytes != bytesToWrite ) {
logError(_("Error: Unable to write %d bytes on the file %s.\n"),
bytesToWrite, out_filename);
rc = -1;
}
logDebug(_("%zd bytes written on file %s.\n"), iBytes, out_filename);
fclose( outfile );
return rc;
}
#endif
static TSS_RESULT
tpmCreateEk(TSS_HTPM a_hTpm, TSS_HKEY a_hKey,
TSS_VALIDATION * a_pValData)
{
TSS_RESULT result = Tspi_TPM_CreateEndorsementKey(a_hTpm, a_hKey,
a_pValData);
tspiResult("Tspi_TPM_CreateEndorsementKey", result);
return result;
}
int main(int argc, char **argv)
{
TSS_RESULT tResult;
TSS_HTPM hTpm;
TSS_HKEY hEk;
TSS_FLAG fEkAttrs;
int iRc = -1;
#ifdef TSS_LIB_IS_12
struct option opts[] = {{"revocable", no_argument, NULL, 'r'},
{"generate-secret", no_argument, NULL, 'g'},
{"infile", required_argument, NULL, 'i'},
{"outfile", required_argument, NULL, 'o'},
};
UINT32 revDataSz;
BYTE revokeData[TPM_SHA1BASED_NONCE_LEN];
BYTE *pRevData;
#endif
initIntlSys();
#ifdef TSS_LIB_IS_12
if (genericOptHandler(argc, argv, "rgi:o:", opts, sizeof(opts) / sizeof(struct option),
parse, help) != 0)
goto out;
//Check commands for command hierarchy
if (isRevocable) {
if (needGenerateSecret) {
if (!outFileSet) {
logError(_("Please specify an output file\n"));
goto out;
}
if (inFileSet) {
logError(_("The option -i, --infile is not valid with -g\n"));
goto out;
}
} else if (!inFileSet) {
logError(_("Please specify -i, --infile or -g, --generate-secret\n"));
goto out;
} else if (outFileSet) {
logError(_("The option -o, --outfile is not valid with -i, --infile"));
goto out;
}
}
logDebug("Input file name: %s\n", in_filename);
logDebug("Output file name: %s\n", out_filename);
if (inFileSet) {
pRevData = revokeData;
revDataSz = sizeof(revokeData);
if (readData(revDataSz, &pRevData))
goto out;
} else if (outFileSet) {
FILE *outfile = fopen(out_filename, "w");
if (!outfile) {
iRc = -1;
logError(_("Unable to open output file: %s\n"), out_filename);
goto out;
}
fclose(outfile);
//TPM should generate the revoke data
revDataSz = 0;
pRevData = NULL;
}
#else
if (genericOptHandler(argc, argv, NULL, NULL, 0, NULL, NULL) != 0){
logError(_("See man pages for details.\n"));
goto out;
}
#endif
if (contextCreate(&hContext) != TSS_SUCCESS)
goto out;
if (contextConnect(hContext) != TSS_SUCCESS)
goto out_close;
if (contextGetTpm(hContext, &hTpm) != TSS_SUCCESS)
goto out_close;
//Initialize EK attributes here
fEkAttrs = TSS_KEY_SIZE_2048 | TSS_KEY_TYPE_LEGACY;
if (contextCreateObject(hContext, TSS_OBJECT_TYPE_RSAKEY, fEkAttrs, &hEk) != TSS_SUCCESS)
goto out_close;
#ifdef TSS_LIB_IS_12
if (isRevocable){
tResult = tpmCreateRevEk(hTpm, hEk, NULL, &revDataSz, &pRevData);
if (tResult != TSS_SUCCESS)
goto out_close;
//Writes the generated secret into the output file
if (outFileSet) {
if (writeData(revDataSz, pRevData)) {
logError(_("Creating revocable EK succeeded, but writing the EK "
"revoke authorization to disk failed.\nPrinting the "
"revoke authorization instead:\n"));
logHex(revDataSz, pRevData);
logError(_("You should record this data, as its the authorization "
"you'll need to revoke your EK!\n"));
goto out_close;
}
}
} else
#endif
tResult = tpmCreateEk(hTpm, hEk, NULL);
if (tResult != TSS_SUCCESS)
goto out_close;
iRc = 0;
logSuccess(argv[0]);
out_close:
contextClose(hContext);
out:
return iRc;
}