1 /* 2 * The Initial Developer of the Original Code is International 3 * Business Machines Corporation. Portions created by IBM 4 * Corporation are Copyright (C) 2005 International Business 5 * Machines Corporation. All Rights Reserved. 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the Common Public License as published by 9 * IBM Corporation; either version 1 of the License, or (at your option) 10 * any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * Common Public License for more details. 16 * 17 * You should have received a copy of the Common Public License 18 * along with this program; if not, a copy can be viewed at 19 * http://www.opensource.org/licenses/cpl1.0.php. 20 */ 21 22 #include "tpm_tspi.h" 23 #include "tpm_utils.h" 24 25 TSS_HCONTEXT hContext = 0; 26 27 #ifdef TSS_LIB_IS_12 28 #include <limits.h> 29 30 //Controled by input options 31 static char in_filename[PATH_MAX] = "", out_filename[PATH_MAX] = ""; 32 static BOOL isRevocable = FALSE; 33 static BOOL needGenerateSecret = FALSE; 34 static BOOL inFileSet = FALSE; 35 static BOOL outFileSet = FALSE; 36 37 static void help(const char *aCmd) 38 { 39 logCmdHelp(aCmd); 40 logCmdOption("-r, --revocable", 41 _("Creates a revocable EK instead of the default non-revocable one. Requires [-g -o] or [-i]")); 42 logCmdOption("-i, --infile FILE", 43 _("Filename containing the secret data used to revoke the EK.")); 44 logCmdOption("-g, --generate-secret", 45 _("Generates a 20 Bytes secret that is used to revoke the EK. Requires [-o]")); 46 logCmdOption("-o, --outfile FILE", 47 _("Filename to write the secret data generated to revoke the EK.")); 48 49 } 50 51 static int parse(const int aOpt, const char *aArg) 52 { 53 switch (aOpt){ 54 case 'r': 55 isRevocable = TRUE; 56 break; 57 case 'g': 58 needGenerateSecret = TRUE; 59 break; 60 case 'i': 61 inFileSet = TRUE; 62 if (aArg){ 63 strncpy(in_filename, aArg, PATH_MAX); 64 } 65 break; 66 case 'o': 67 outFileSet = TRUE; 68 if (aArg){ 69 strncpy(out_filename, aArg, PATH_MAX); 70 } 71 break; 72 default: 73 return -1; 74 } 75 return 0; 76 77 } 78 79 static TSS_RESULT 80 tpmCreateRevEk(TSS_HTPM a_hTpm, TSS_HKEY a_hKey, 81 TSS_VALIDATION * a_pValData, UINT32 *revDataSz, BYTE **revData) 82 { 83 TSS_RESULT result = Tspi_TPM_CreateRevocableEndorsementKey(a_hTpm, a_hKey, 84 a_pValData, revDataSz, revData); 85 tspiResult("Tspi_TPM_CreateRevocableEndorsementKey", result); 86 return result; 87 } 88 89 static int readData(UINT32 bytesToRead, BYTE **buffer) 90 { 91 FILE *infile = NULL; 92 size_t iBytes; 93 int rc = 0; 94 BYTE eofile; 95 96 memset(*buffer, 0x00, bytesToRead); 97 infile = fopen(in_filename, "r"); 98 if ( !infile ){ 99 logError(_("Unable to open input file: %s\n"), 100 in_filename); 101 return -1; 102 } 103 104 //Read the data 105 iBytes = fread( *buffer, 1, bytesToRead, infile ); 106 if ( iBytes < bytesToRead ) { 107 logError(_("Error: the secret data file %s contains less than %d bytes. Aborting ...\n"), 108 in_filename, bytesToRead); 109 rc = -1; 110 } else if ( (iBytes = fread( &eofile, 1, 1, infile )) ) { 111 //Test if there's more than 20 bytes 112 if ( !feof( infile)) 113 logMsg(_("WARNING: Using only the first %d bytes of file %s for secret data\n"), 114 bytesToRead, in_filename); 115 } else { 116 logDebug(_("Read %d bytes of secret data from file %s.\n"), 117 bytesToRead, in_filename); 118 } 119 120 fclose( infile); 121 return rc; 122 } 123 124 static int writeData(UINT32 bytesToWrite, BYTE *buffer) 125 { 126 FILE *outfile = NULL; 127 size_t iBytes; 128 int rc = 0; 129 130 logDebug(_("bytesToWrite: %d\n"), bytesToWrite); 131 outfile = fopen(out_filename, "w"); 132 if ( !outfile ) { 133 logError(_("Unable to open output file: %s\n"), out_filename); 134 return -1; 135 } 136 137 //Write data in buffer 138 iBytes = fwrite( buffer, 1, bytesToWrite, outfile); 139 if ( iBytes != bytesToWrite ) { 140 logError(_("Error: Unable to write %d bytes on the file %s.\n"), 141 bytesToWrite, out_filename); 142 rc = -1; 143 } 144 145 logDebug(_("%zd bytes written on file %s.\n"), iBytes, out_filename); 146 fclose( outfile ); 147 return rc; 148 149 } 150 #endif 151 152 static TSS_RESULT 153 tpmCreateEk(TSS_HTPM a_hTpm, TSS_HKEY a_hKey, 154 TSS_VALIDATION * a_pValData) 155 { 156 157 TSS_RESULT result = Tspi_TPM_CreateEndorsementKey(a_hTpm, a_hKey, 158 a_pValData); 159 tspiResult("Tspi_TPM_CreateEndorsementKey", result); 160 return result; 161 } 162 163 int main(int argc, char **argv) 164 { 165 TSS_RESULT tResult; 166 TSS_HTPM hTpm; 167 TSS_HKEY hEk; 168 TSS_FLAG fEkAttrs; 169 int iRc = -1; 170 171 #ifdef TSS_LIB_IS_12 172 struct option opts[] = {{"revocable", no_argument, NULL, 'r'}, 173 {"generate-secret", no_argument, NULL, 'g'}, 174 {"infile", required_argument, NULL, 'i'}, 175 {"outfile", required_argument, NULL, 'o'}, 176 }; 177 UINT32 revDataSz; 178 BYTE revokeData[TPM_SHA1BASED_NONCE_LEN]; 179 BYTE *pRevData; 180 #endif 181 182 initIntlSys(); 183 184 #ifdef TSS_LIB_IS_12 185 if (genericOptHandler(argc, argv, "rgi:o:", opts, sizeof(opts) / sizeof(struct option), 186 parse, help) != 0) 187 goto out; 188 189 //Check commands for command hierarchy 190 if (isRevocable) { 191 if (needGenerateSecret) { 192 if (!outFileSet) { 193 logError(_("Please specify an output file\n")); 194 goto out; 195 } 196 if (inFileSet) { 197 logError(_("The option -i, --infile is not valid with -g\n")); 198 goto out; 199 } 200 } else if (!inFileSet) { 201 logError(_("Please specify -i, --infile or -g, --generate-secret\n")); 202 goto out; 203 } else if (outFileSet) { 204 logError(_("The option -o, --outfile is not valid with -i, --infile")); 205 goto out; 206 } 207 } 208 logDebug("Input file name: %s\n", in_filename); 209 logDebug("Output file name: %s\n", out_filename); 210 211 if (inFileSet) { 212 pRevData = revokeData; 213 revDataSz = sizeof(revokeData); 214 if (readData(revDataSz, &pRevData)) 215 goto out; 216 } else if (outFileSet) { 217 FILE *outfile = fopen(out_filename, "w"); 218 if (!outfile) { 219 iRc = -1; 220 logError(_("Unable to open output file: %s\n"), out_filename); 221 goto out; 222 } 223 fclose(outfile); 224 225 //TPM should generate the revoke data 226 revDataSz = 0; 227 pRevData = NULL; 228 } 229 #else 230 if (genericOptHandler(argc, argv, NULL, NULL, 0, NULL, NULL) != 0){ 231 logError(_("See man pages for details.\n")); 232 goto out; 233 } 234 #endif 235 236 if (contextCreate(&hContext) != TSS_SUCCESS) 237 goto out; 238 239 if (contextConnect(hContext) != TSS_SUCCESS) 240 goto out_close; 241 242 if (contextGetTpm(hContext, &hTpm) != TSS_SUCCESS) 243 goto out_close; 244 245 //Initialize EK attributes here 246 fEkAttrs = TSS_KEY_SIZE_2048 | TSS_KEY_TYPE_LEGACY; 247 if (contextCreateObject(hContext, TSS_OBJECT_TYPE_RSAKEY, fEkAttrs, &hEk) != TSS_SUCCESS) 248 goto out_close; 249 250 #ifdef TSS_LIB_IS_12 251 if (isRevocable){ 252 tResult = tpmCreateRevEk(hTpm, hEk, NULL, &revDataSz, &pRevData); 253 if (tResult != TSS_SUCCESS) 254 goto out_close; 255 //Writes the generated secret into the output file 256 if (outFileSet) { 257 if (writeData(revDataSz, pRevData)) { 258 logError(_("Creating revocable EK succeeded, but writing the EK " 259 "revoke authorization to disk failed.\nPrinting the " 260 "revoke authorization instead:\n")); 261 logHex(revDataSz, pRevData); 262 logError(_("You should record this data, as its the authorization " 263 "you'll need to revoke your EK!\n")); 264 goto out_close; 265 } 266 } 267 } else 268 #endif 269 tResult = tpmCreateEk(hTpm, hEk, NULL); 270 if (tResult != TSS_SUCCESS) 271 goto out_close; 272 273 iRc = 0; 274 logSuccess(argv[0]); 275 276 out_close: 277 contextClose(hContext); 278 279 out: 280 return iRc; 281 } 282