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
help(const char * aCmd)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
parse(const int aOpt,const char * aArg)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
tpmCreateRevEk(TSS_HTPM a_hTpm,TSS_HKEY a_hKey,TSS_VALIDATION * a_pValData,UINT32 * revDataSz,BYTE ** revData)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
readData(UINT32 bytesToRead,BYTE ** buffer)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
writeData(UINT32 bytesToWrite,BYTE * buffer)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
tpmCreateEk(TSS_HTPM a_hTpm,TSS_HKEY a_hKey,TSS_VALIDATION * a_pValData)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
main(int argc,char ** argv)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