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