1 /********************************************************************************/
2 /*										*/
3 /*			   EncryptDecrypt					*/
4 /*			     Written by Ken Goldman				*/
5 /*		       IBM Thomas J. Watson Research Center			*/
6 /*										*/
7 /* (c) Copyright IBM Corporation 2015 - 2019.					*/
8 /*										*/
9 /* All rights reserved.								*/
10 /* 										*/
11 /* Redistribution and use in source and binary forms, with or without		*/
12 /* modification, are permitted provided that the following conditions are	*/
13 /* met:										*/
14 /* 										*/
15 /* Redistributions of source code must retain the above copyright notice,	*/
16 /* this list of conditions and the following disclaimer.			*/
17 /* 										*/
18 /* Redistributions in binary form must reproduce the above copyright		*/
19 /* notice, this list of conditions and the following disclaimer in the		*/
20 /* documentation and/or other materials provided with the distribution.		*/
21 /* 										*/
22 /* Neither the names of the IBM Corporation nor the names of its		*/
23 /* contributors may be used to endorse or promote products derived from		*/
24 /* this software without specific prior written permission.			*/
25 /* 										*/
26 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS		*/
27 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT		*/
28 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR	*/
29 /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT		*/
30 /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,	*/
31 /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT		*/
32 /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,	*/
33 /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY	*/
34 /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT		*/
35 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE	*/
36 /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.		*/
37 /********************************************************************************/
38 
39 /*
40 
41 */
42 
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <stdint.h>
47 
48 #include <ibmtss/tss.h>
49 #include <ibmtss/tssutils.h>
50 #include <ibmtss/tssresponsecode.h>
51 #include <ibmtss/tssmarshal.h>
52 
53 
54 static void printDecrypt(EncryptDecrypt_Out *out);
55 static void printUsage(void);
56 
57 extern int tssUtilsVerbose;
58 
main(int argc,char * argv[])59 int main(int argc, char *argv[])
60 {
61     TPM_RC			rc = 0;
62     int				i;    /* argc iterator */
63     TSS_CONTEXT			*tssContext = NULL;
64     EncryptDecrypt_In 		in;
65     EncryptDecrypt_Out 		out;
66     EncryptDecrypt2_In 		in2;
67     TPMI_DH_OBJECT		keyHandle = 0;
68     const char			*inFilename = NULL;
69     const char			*outFilename = NULL;
70     TPMI_YES_NO			decrypt = NO;
71     int				two = FALSE;
72     const char			*keyPassword = NULL;
73     TPMI_SH_AUTH_SESSION    	sessionHandle0 = TPM_RS_PW;
74     unsigned int		sessionAttributes0 = 0;
75     TPMI_SH_AUTH_SESSION    	sessionHandle1 = TPM_RH_NULL;
76     unsigned int		sessionAttributes1 = 0;
77     TPMI_SH_AUTH_SESSION    	sessionHandle2 = TPM_RH_NULL;
78     unsigned int		sessionAttributes2 = 0;
79 
80     uint16_t			written;
81     size_t			length;
82     uint8_t			*buffer = NULL;		/* for the free */
83     uint8_t			*buffer1 = NULL;	/* for marshaling */
84 
85     setvbuf(stdout, 0, _IONBF, 0);      /* output may be going through pipe to log file */
86     TSS_SetProperty(NULL, TPM_TRACE_LEVEL, "1");
87     tssUtilsVerbose = FALSE;
88 
89     /* command line argument defaults */
90 
91     for (i=1 ; (i<argc) && (rc == 0) ; i++) {
92 	if (strcmp(argv[i],"-hk") == 0) {
93 	    i++;
94 	    if (i < argc) {
95 		sscanf(argv[i],"%x",&keyHandle);
96 	    }
97 	    else {
98 		printf("Missing parameter for -hk\n");
99 		printUsage();
100 	    }
101 	}
102 	else if (strcmp(argv[i],"-pwdk") == 0) {
103 	    i++;
104 	    if (i < argc) {
105 		keyPassword = argv[i];
106 	    }
107 	    else {
108 		printf("-pwdk option needs a value\n");
109 		printUsage();
110 	    }
111 	}
112 	else if (strcmp(argv[i],"-if") == 0) {
113 	    i++;
114 	    if (i < argc) {
115 		inFilename = argv[i];
116 	    }
117 	    else {
118 		printf("-if option needs a value\n");
119 		printUsage();
120 	    }
121 	}
122 	else if (strcmp(argv[i],"-of") == 0) {
123 	    i++;
124 	    if (i < argc) {
125 		outFilename = argv[i];
126 	    }
127 	    else {
128 		printf("-of option needs a value\n");
129 		printUsage();
130 	    }
131 	}
132  	else if (strcmp(argv[i],"-d") == 0) {
133 	    decrypt = YES;
134 	}
135  	else if (strcmp(argv[i],"-2") == 0) {
136 	    two = TRUE;
137 	}
138  	else if (strcmp(argv[i],"-se0") == 0) {
139 	    i++;
140 	    if (i < argc) {
141 		sscanf(argv[i],"%x", &sessionHandle0);
142 	    }
143 	    else {
144 		printf("Missing parameter for -se0\n");
145 		printUsage();
146 	    }
147 	    i++;
148 	    if (i < argc) {
149 		sscanf(argv[i],"%x", &sessionAttributes0);
150 		if (sessionAttributes0 > 0xff) {
151 		    printf("Out of range session attributes for -se0\n");
152 		    printUsage();
153 		}
154 	    }
155 	    else {
156 		printf("Missing parameter for -se0\n");
157 		printUsage();
158 	    }
159 	}
160 	else if (strcmp(argv[i],"-se1") == 0) {
161 	    i++;
162 	    if (i < argc) {
163 		sscanf(argv[i],"%x", &sessionHandle1);
164 	    }
165 	    else {
166 		printf("Missing parameter for -se1\n");
167 		printUsage();
168 	    }
169 	    i++;
170 	    if (i < argc) {
171 		sscanf(argv[i],"%x", &sessionAttributes1);
172 		if (sessionAttributes1 > 0xff) {
173 		    printf("Out of range session attributes for -se1\n");
174 		    printUsage();
175 		}
176 	    }
177 	    else {
178 		printf("Missing parameter for -se1\n");
179 		printUsage();
180 	    }
181 	}
182 	else if (strcmp(argv[i],"-se2") == 0) {
183 	    i++;
184 	    if (i < argc) {
185 		sscanf(argv[i],"%x", &sessionHandle2);
186 	    }
187 	    else {
188 		printf("Missing parameter for -se2\n");
189 		printUsage();
190 	    }
191 	    i++;
192 	    if (i < argc) {
193 		sscanf(argv[i],"%x", &sessionAttributes2);
194 		if (sessionAttributes2 > 0xff) {
195 		    printf("Out of range session attributes for -se2\n");
196 		    printUsage();
197 		}
198 	    }
199 	    else {
200 		printf("Missing parameter for -se2\n");
201 		printUsage();
202 	    }
203 	}
204 	else if (strcmp(argv[i],"-h") == 0) {
205 	    printUsage();
206 	}
207 	else if (strcmp(argv[i],"-v") == 0) {
208 	    tssUtilsVerbose = TRUE;
209 	    TSS_SetProperty(NULL, TPM_TRACE_LEVEL, "2");
210 	}
211 	else {
212 	    printf("\n%s is not a valid option\n", argv[i]);
213 	    printUsage();
214 	}
215     }
216     if (keyHandle == 0) {
217 	printf("Missing handle parameter -hk\n");
218 	printUsage();
219     }
220     if (inFilename == NULL) {
221 	printf("Missing encrypted message -if\n");
222 	printUsage();
223     }
224     if (rc == 0) {
225 	rc = TSS_File_ReadBinaryFile(&buffer,     /* freed @1 */
226 				     &length,
227 				     inFilename);
228     }
229     if (rc == 0) {
230 	if (length > sizeof(in.inData.t.buffer)) {
231 	    printf("Input data too long %u\n", (uint32_t)length);
232 	    rc = TSS_RC_INSUFFICIENT_BUFFER;
233 	}
234     }
235     if (rc == 0) {
236 	if (!two) {	/* use TPM_CC_EncryptDecrypt */
237 	    /* the symmetric key used for the operation */
238 	    in.keyHandle = keyHandle;
239 	    /* if YES, then the operation is decryption; if NO, the operation is encryption */
240 	    in.decrypt = decrypt;
241 	    /* symmetric mode */
242 	    in.mode = TPM_ALG_NULL;
243 	    /* an initial value as required by the algorithm */
244 	    in.ivIn.t.size = MAX_SYM_BLOCK_SIZE;
245 	    memset(in.ivIn.t.buffer, 0, MAX_SYM_BLOCK_SIZE);
246 	    /* the data to be encrypted/decrypted */
247 	    in.inData.t.size = (uint16_t)length;
248 	    if (length > 0) {	/* if length is 0, buffer is NULL */
249 		memcpy(in.inData.t.buffer, buffer, length);
250 	    }
251 	}
252 	else {
253 	    /* the symmetric key used for the operation */
254 	    in2.keyHandle = keyHandle;
255 	    /* if YES, then the operation is decryption; if NO, the operation is encryption */
256 	    in2.decrypt = decrypt;
257 	    /* symmetric mode */
258 	    in2.mode = TPM_ALG_NULL;
259 	    /* an initial value as required by the algorithm */
260 	    in2.ivIn.t.size = MAX_SYM_BLOCK_SIZE;
261 	    memset(in2.ivIn.t.buffer, 0, MAX_SYM_BLOCK_SIZE);
262 	    /* the data to be encrypted/decrypted */
263 	    in2.inData.t.size = (uint16_t)length;
264 	    if (length > 0) {	/* if length is 0, buffer is NULL */
265 		memcpy(in2.inData.t.buffer, buffer, length);
266 	    }
267 	}
268     }
269     free (buffer);	/* @1 */
270     buffer = NULL;
271 
272     /* Start a TSS context */
273     if (rc == 0) {
274 	rc = TSS_Create(&tssContext);
275     }
276     /* call TSS to execute the command */
277     if (rc == 0) {
278 	if (!two) {	/* use TPM_CC_EncryptDecrypt */
279 	    rc = TSS_Execute(tssContext,
280 			     (RESPONSE_PARAMETERS *)&out,
281 			     (COMMAND_PARAMETERS *)&in,
282 			     NULL,
283 			     TPM_CC_EncryptDecrypt,
284 			     sessionHandle0, keyPassword, sessionAttributes0,
285 			     sessionHandle1, NULL, sessionAttributes1,
286 			     sessionHandle2, NULL, sessionAttributes2,
287 			     TPM_RH_NULL, NULL, 0);
288 	}
289 	else {	/* use TPM_CC_EncryptDecrypt2 */
290 	    rc = TSS_Execute(tssContext,
291 			     (RESPONSE_PARAMETERS *)&out,
292 			     (COMMAND_PARAMETERS *)&in2,
293 			     NULL,
294 			     TPM_CC_EncryptDecrypt2,
295 			     sessionHandle0, keyPassword, sessionAttributes0,
296 			     sessionHandle1, NULL, sessionAttributes1,
297 			     sessionHandle2, NULL, sessionAttributes2,
298 			     TPM_RH_NULL, NULL, 0);
299 	}
300     }
301     {
302 	TPM_RC rc1 = TSS_Delete(tssContext);
303 	if (rc == 0) {
304 	    rc = rc1;
305 	}
306     }
307     if ((rc == 0) && (outFilename != NULL)) {
308 	written = 0;
309 	rc = TSS_TPM2B_MAX_BUFFER_Marshalu(&out.outData, &written, NULL, NULL);
310     }
311     if ((rc == 0) && (outFilename != NULL)) {
312 	buffer = realloc(buffer, written);	/* freed @2 */
313 	buffer1 = buffer;
314 	written = 0;
315 	rc = TSS_TPM2B_MAX_BUFFER_Marshalu(&out.outData, &written, &buffer1, NULL);
316     }
317     if ((rc == 0) && (outFilename != NULL)) {
318 	rc = TSS_File_WriteBinaryFile(buffer + sizeof(uint16_t),
319 				      written - sizeof(uint16_t),
320 				      outFilename);
321     }
322     free(buffer);	/* @2 */
323     if (rc == 0) {
324 	if (tssUtilsVerbose) printDecrypt(&out);
325 	if (tssUtilsVerbose) printf("encryptdecrypt: success\n");
326     }
327     else {
328 	const char *msg;
329 	const char *submsg;
330 	const char *num;
331 	printf("encryptdecrypt: failed, rc %08x\n", rc);
332 	TSS_ResponseCode_toString(&msg, &submsg, &num, rc);
333 	printf("%s%s%s\n", msg, submsg, num);
334 	rc = EXIT_FAILURE;
335     }
336     return rc;
337 }
338 
printDecrypt(EncryptDecrypt_Out * out)339 static void printDecrypt(EncryptDecrypt_Out *out)
340 {
341     TSS_PrintAll("outData", out->outData.t.buffer, out->outData.t.size);
342 }
343 
printUsage(void)344 static void printUsage(void)
345 {
346     printf("\n");
347     printf("encryptdecrypt\n");
348     printf("\n");
349     printf("Runs TPM2_EncryptDecrypt\n");
350     printf("\n");
351     printf("\t-hk\tkey handle\n");
352     printf("\t-pwdk\tpassword for key (default empty)\n");
353     printf("\t-d\tdecrypt (default encrypt)\n");
354     printf("\t-if\tinput file name\n");
355     printf("\t[-of\toutput file name (default do not save)]\n");
356     printf("\t[-2\tuse TPM2_EncryptDecrypt2]\n");
357     printf("\n");
358     printf("\t-se[0-2] session handle / attributes (default PWAP)\n");
359     printf("\t01\tcontinue\n");
360     printf("\t20\tcommand decrypt\n");
361     printf("\t40\tresponse encrypt\n");
362     exit(1);
363 }
364