1 /*
2 * Copyright (c) 2014 Intel Corporation.
3 *
4 * Authors:
5 * Quan Xu <quan.xu@intel.com>
6 *
7 * Copyright (c) 2010-2012 United States Government, as represented by
8 * the Secretary of Defense. All rights reserved.
9 *
10 * based off of the original tools/vtpm_manager code base which is:
11 * Copyright (c) 2005/2006, Intel Corp.
12 * All rights reserved.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 *
18 * * Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * * Redistributions in binary form must reproduce the above
21 * copyright notice, this list of conditions and the following
22 * disclaimer in the documentation and/or other materials provided
23 * with the distribution.
24 * * Neither the name of Intel Corporation nor the names of its
25 * contributors may be used to endorse or promote products derived
26 * from this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
31 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
32 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
33 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39 * OF THE POSSIBILITY OF SUCH DAMAGE.
40 */
41
42 #include <stdio.h>
43 #include <string.h>
44 #include <malloc.h>
45 #include <unistd.h>
46 #include <errno.h>
47 #include <polarssl/sha1.h>
48
49 #include "tcg.h"
50 #include "tpm.h"
51 #include "tpm2.h"
52 #include "log.h"
53 #include "marshal.h"
54 #include "tpm2_marshal.h"
55 #include "tpmrsa.h"
56 #include "vtpmmgr.h"
57
58 #define TCPA_MAX_BUFFER_LENGTH 0x2000
59 #define TPM_BEGIN(TAG, ORD) \
60 const TPM_TAG intag = TAG;\
61 TPM_TAG tag = intag;\
62 UINT32 paramSize;\
63 const TPM_COMMAND_CODE ordinal = ORD;\
64 TPM_RESULT status = TPM_SUCCESS;\
65 BYTE in_buf[TCPA_MAX_BUFFER_LENGTH];\
66 BYTE out_buf[TCPA_MAX_BUFFER_LENGTH];\
67 UINT32 out_len = sizeof(out_buf);\
68 BYTE* ptr = in_buf;\
69 /*Print a log message */\
70 vtpmloginfo(VTPM_LOG_TPM, "%s\n", __func__);\
71 /* Pack the header*/\
72 ptr = pack_TPM_TAG(ptr, tag);\
73 ptr += sizeof(UINT32);\
74 ptr = pack_TPM_COMMAND_CODE(ptr, ordinal)\
75
76 #define TPM_AUTH_BEGIN() \
77 sha1_context sha1_ctx;\
78 BYTE* authbase = ptr - sizeof(TPM_COMMAND_CODE);\
79 TPM_DIGEST paramDigest;\
80 sha1_starts(&sha1_ctx)
81
82 #define TPM_AUTH1_GEN(HMACkey, auth) do {\
83 sha1_finish(&sha1_ctx, paramDigest.digest);\
84 generateAuth(¶mDigest, HMACkey, auth);\
85 ptr = pack_TPM_AUTH_SESSION(ptr, auth);\
86 } while(0)
87
88 #define TPM_AUTH2_GEN(HMACkey, auth) do {\
89 generateAuth(¶mDigest, HMACkey, auth);\
90 ptr = pack_TPM_AUTH_SESSION(ptr, auth);\
91 } while(0)
92
93 #define TPM_TRANSMIT() do {\
94 /* Pack the command size */\
95 paramSize = ptr - in_buf;\
96 pack_UINT32(in_buf + sizeof(TPM_TAG), paramSize);\
97 if ((status = TPM_TransmitData(in_buf, paramSize, out_buf, &out_len)) != TPM_SUCCESS) {\
98 goto abort_egress;\
99 }\
100 } while(0)
101
102 #define TPM_AUTH_VERIFY_BEGIN() do {\
103 UINT32 buf[2] = { cpu_to_be32(status), cpu_to_be32(ordinal) };\
104 sha1_starts(&sha1_ctx);\
105 sha1_update(&sha1_ctx, (unsigned char*)buf, sizeof(buf));\
106 authbase = ptr;\
107 } while(0)
108
109 #define TPM_AUTH1_VERIFY(HMACkey, auth) do {\
110 sha1_finish(&sha1_ctx, paramDigest.digest);\
111 ptr = unpack_TPM_AUTH_SESSION(ptr, auth);\
112 if ((status = verifyAuth(¶mDigest, HMACkey, auth)) != TPM_SUCCESS) {\
113 goto abort_egress;\
114 }\
115 } while(0)
116
117 #define TPM_AUTH2_VERIFY(HMACkey, auth) do {\
118 ptr = unpack_TPM_AUTH_SESSION(ptr, auth);\
119 if ((status = verifyAuth(¶mDigest, HMACkey, auth)) != TPM_SUCCESS) {\
120 goto abort_egress;\
121 }\
122 } while(0)
123
124 #define TPM_UNPACK_VERIFY() do { \
125 ptr = out_buf;\
126 ptr = unpack_TPM_RSP_HEADER(ptr, \
127 &(tag), &(paramSize), &(status));\
128 if ((status) != TPM_SUCCESS){ \
129 vtpmlogerror(VTPM_LOG_TPM, "Failed with return code %s\n", tpm_get_error_name(status));\
130 goto abort_egress;\
131 }\
132 } while(0)
133
134 #define TPM_AUTH_HASH() do {\
135 sha1_update(&sha1_ctx, authbase, ptr - authbase);\
136 authbase = ptr;\
137 } while(0)
138
139 #define TPM_AUTH_SKIP() do {\
140 authbase = ptr;\
141 } while(0)
142
TPM2_PCR_Read(TPML_PCR_SELECTION pcrSelectionIn,UINT32 * pcrUpdateCounter,TPML_PCR_SELECTION * pcrSelectionOut,TPML_DIGEST * pcrValues)143 TPM_RC TPM2_PCR_Read(TPML_PCR_SELECTION pcrSelectionIn,
144 UINT32 *pcrUpdateCounter,
145 TPML_PCR_SELECTION *pcrSelectionOut,
146 TPML_DIGEST *pcrValues)
147 {
148 TPM_BEGIN(TPM_ST_NO_SESSIONS,TPM_CC_PCR_Read);
149
150 /*pack in*/
151 ptr = pack_TPML_PCR_SELECTION(ptr, &pcrSelectionIn);
152
153 TPM_TRANSMIT();
154 TPM_UNPACK_VERIFY();
155
156 /*unpack out*/
157 ptr = unpack_UINT32(ptr, pcrUpdateCounter);
158 ptr = unpack_TPML_PCR_SELECTION(ptr, pcrSelectionOut);
159 ptr = unpack_TPML_DIGEST(ptr, pcrValues);
160
161 goto egress;
162 abort_egress:
163 egress:
164 return status;
165 }
166
TPM2_Load(TPMI_DH_OBJECT parentHandle,TPM2B_PRIVATE * inPrivate,TPM2B_PUBLIC * inPublic,TPM2_HANDLE * objectHandle,TPM2B_NAME * name)167 TPM_RC TPM2_Load(TPMI_DH_OBJECT parentHandle,
168 TPM2B_PRIVATE *inPrivate, /* in */
169 TPM2B_PUBLIC *inPublic, /* in */
170 TPM2_HANDLE *objectHandle, /* out */
171 TPM2B_NAME *name /* out */)
172 {
173 TPM_BEGIN(TPM_ST_SESSIONS, TPM_CC_Load);
174
175 /* pack handle of parent for new object */
176 ptr = pack_UINT32(ptr, parentHandle);
177
178 ptr = pack_TPM_AuthArea(ptr, &vtpm_globals.srk_auth_area);
179 ptr = pack_TPM2B_PRIVATE(ptr, inPrivate);
180 ptr = pack_TPM2B_PUBLIC(ptr, inPublic);
181
182 TPM_TRANSMIT();
183 TPM_UNPACK_VERIFY();
184
185 if (objectHandle != NULL) {
186 ptr = unpack_TPM_HANDLE(ptr, objectHandle);
187 } else {
188 TPM2_HANDLE tmp;
189 ptr = unpack_TPM_HANDLE(ptr, &tmp);
190 }
191
192 if (name != NULL)
193 ptr = unpack_TPM2B_NAME(ptr, name);
194 goto egress;
195
196 abort_egress:
197 egress:
198 return status;
199 }
200
TPM2_Create(TPMI_DH_OBJECT parentHandle,TPM2_Create_Params_in * in,TPM2_Create_Params_out * out)201 TPM_RC TPM2_Create(TPMI_DH_OBJECT parentHandle,
202 TPM2_Create_Params_in *in,
203 TPM2_Create_Params_out *out)
204 {
205 UINT32 param_size;
206 TPM_BEGIN(TPM_ST_SESSIONS, TPM_CC_Create);
207
208 /* pack handle of parent for new object */
209 ptr = pack_UINT32(ptr, parentHandle);
210
211 /* pack Auth Area */
212 ptr = pack_TPM_AuthArea(ptr, &vtpm_globals.srk_auth_area);
213
214 /* pack inSensitive */
215 ptr = pack_TPM2B_SENSITIVE_CREATE(ptr, &in->inSensitive);
216
217 /* pack inPublic */
218 ptr = pack_TPM2B_PUBLIC(ptr, &in->inPublic);
219
220 /* pack outside Info */
221 ptr = pack_TPM2B_DATA(ptr, &in->outsideInfo);
222
223 /* pack createPCR */
224 ptr = pack_TPML_PCR_SELECTION(ptr, &in->creationPCR);
225
226 /* Send the command to the tpm */
227 TPM_TRANSMIT();
228
229 /* Unpack and validate the header */
230 TPM_UNPACK_VERIFY();
231
232 ptr = unpack_UINT32(ptr, ¶m_size);
233 if (out != NULL) {
234 ptr = unpack_TPM2B_PRIVATE(ptr, &vtpm_globals.tpm2_storage_key.Private);
235 ptr = unpack_TPM2B_PUBLIC(ptr, &vtpm_globals.tpm2_storage_key.Public);
236 ptr = unpack_TPM2B_CREATION_DATA(ptr, &out->creationData);
237 ptr = unpack_TPM2B_DIGEST(ptr, &out->creationHash);
238 ptr = unpack_TPMT_TK_CREATION(ptr, &out->creationTicket);
239 } else {
240 ptr += param_size;
241 }
242 goto egress;
243
244 abort_egress:
245 egress:
246 return status;
247 }
248
TPM2_CreatePrimary(TPMI_RH_HIERARCHY primaryHandle,TPM2_Create_Params_in * in,TPM2_HANDLE * objHandle,TPM2_Create_Params_out * out)249 TPM_RC TPM2_CreatePrimary(TPMI_RH_HIERARCHY primaryHandle,
250 TPM2_Create_Params_in *in,
251 TPM2_HANDLE *objHandle,
252 TPM2_Create_Params_out *out)
253 {
254 UINT32 param_size;
255 TPM_BEGIN(TPM_ST_SESSIONS, TPM_CC_CreatePrimary);
256
257 /* pack primary handle */
258 ptr = pack_UINT32(ptr, primaryHandle);
259
260 /* pack Auth Area */
261 ptr = pack_TPM_AuthArea(ptr, &vtpm_globals.pw_auth);
262
263 /* pack inSenstive */
264 ptr = pack_TPM2B_SENSITIVE_CREATE(ptr, &in->inSensitive);
265
266 /* pack inPublic */
267 ptr = pack_TPM2B_PUBLIC(ptr, &in->inPublic);
268
269 /* pack outsideInfo */
270 ptr = pack_TPM2B_DATA(ptr, &in->outsideInfo);
271
272 /* pack creationPCR */
273 ptr = pack_TPML_PCR_SELECTION(ptr, &in->creationPCR);
274
275 /* Send the command to the tpm */
276 TPM_TRANSMIT();
277
278 /* Unpack and validate the header */
279 TPM_UNPACK_VERIFY();
280
281 if (objHandle != NULL)
282 ptr = unpack_TPM_HANDLE(ptr, objHandle);
283 else {
284 TPM2_HANDLE handle;
285 ptr = unpack_TPM_HANDLE(ptr, &handle);
286 }
287 ptr = unpack_UINT32(ptr, ¶m_size);
288
289 if (out != NULL) {
290 ptr = unpack_TPM2B_PUBLIC(ptr, &out->outPublic);
291 ptr = unpack_TPM2B_CREATION_DATA(ptr, &out->creationData);
292 ptr = unpack_TPM2B_DIGEST(ptr, &out->creationHash);
293 ptr = unpack_TPMT_TK_CREATION(ptr, &out->creationTicket);
294 } else {
295 ptr += param_size;
296 }
297
298 goto egress;
299
300 abort_egress:
301 egress:
302 return status;
303 }
304
TPM2_HierachyChangeAuth(TPM2I_RH_HIERARCHY_AUTH authHandle,TPM2B_AUTH * newAuth)305 TPM_RC TPM2_HierachyChangeAuth(TPM2I_RH_HIERARCHY_AUTH authHandle, TPM2B_AUTH *newAuth)
306 {
307 TPM_BEGIN(TPM_ST_SESSIONS, TPM_CC_HierarchyChangeAuth);
308 ptr = pack_UINT32(ptr, authHandle);
309 ptr = pack_TPM_AuthArea(ptr, &vtpm_globals.pw_auth);
310 ptr = pack_TPM2B_AUTH(ptr, newAuth);
311 TPM_TRANSMIT();
312 TPM_UNPACK_VERIFY();
313
314 abort_egress:
315 return status;
316 }
317
TPM2_RSA_ENCRYPT(TPMI_DH_OBJECT keyHandle,TPM2B_PUBLIC_KEY_RSA * message,TPMT_RSA_DECRYPT * inScheme,TPM2B_DATA * label,TPM2B_PUBLIC_KEY_RSA * outData)318 TPM_RC TPM2_RSA_ENCRYPT(TPMI_DH_OBJECT keyHandle,
319 TPM2B_PUBLIC_KEY_RSA *message,
320 TPMT_RSA_DECRYPT *inScheme,
321 TPM2B_DATA *label,
322 TPM2B_PUBLIC_KEY_RSA *outData)
323 {
324 TPM_BEGIN(TPM_ST_NO_SESSIONS, TPM_CC_RSA_Encrypt);
325
326 ptr = pack_UINT32(ptr, keyHandle);
327 ptr = pack_TPM2B_PUBLIC_KEY_RSA(ptr, message);
328 ptr = pack_TPMT_RSA_DECRYPT(ptr, inScheme);
329 ptr = pack_TPM2B_DATA(ptr, label);
330
331 TPM_TRANSMIT();
332 TPM_UNPACK_VERIFY();
333
334 if (outData != NULL)
335 unpack_TPM2B_PUBLIC_KEY_RSA(ptr, outData);
336 abort_egress:
337 return status;
338 }
339
TPM2_Bind(TPMI_DH_OBJECT keyHandle,void * buf,UINT32 len,void * out)340 TPM_RC TPM2_Bind(TPMI_DH_OBJECT keyHandle,
341 void *buf,
342 UINT32 len,
343 void *out)
344 {
345 TPM_RC status = TPM_SUCCESS;
346 TPM2B_PUBLIC_KEY_RSA message;
347 TPMT_RSA_DECRYPT inScheme;
348 TPM2B_DATA label;
349 TPM2B_PUBLIC_KEY_RSA outData;
350
351 message.size = len;
352 memcpy(message.buffer, buf, len);
353 inScheme.scheme = TPM2_ALG_NULL;
354 label.size = 0;
355 TPMTRYRETURN(TPM2_RSA_ENCRYPT(keyHandle, &message, &inScheme, &label, &outData));
356 memcpy(out, outData.buffer, outData.size);
357
358 abort_egress:
359 return status;
360 }
361
TPM2_RSA_Decrypt(TPMI_DH_OBJECT keyHandle,TPM2B_PUBLIC_KEY_RSA * cipherText,TPMT_RSA_DECRYPT * inScheme,TPM2B_DATA * label,TPM2B_PUBLIC_KEY_RSA * message)362 TPM_RC TPM2_RSA_Decrypt(TPMI_DH_OBJECT keyHandle,
363 TPM2B_PUBLIC_KEY_RSA *cipherText,
364 TPMT_RSA_DECRYPT *inScheme,
365 TPM2B_DATA *label,
366 TPM2B_PUBLIC_KEY_RSA *message)
367 {
368 UINT32 param_size;
369
370 TPM_BEGIN(TPM_ST_SESSIONS, TPM_CC_RSA_Decrypt);
371 ptr = pack_UINT32(ptr, keyHandle);
372 ptr = pack_TPM_AuthArea(ptr, &vtpm_globals.srk_auth_area);
373 ptr = pack_TPM2B_PUBLIC_KEY_RSA(ptr, cipherText);
374 ptr = pack_TPMT_RSA_DECRYPT(ptr, inScheme);
375 ptr = pack_TPM2B_DATA(ptr, label);
376
377 TPM_TRANSMIT();
378 TPM_UNPACK_VERIFY();
379
380 ptr = unpack_UINT32(ptr, ¶m_size);
381
382 if (message)
383 ptr = unpack_TPM2B_PUBLIC_KEY_RSA(ptr, message);
384
385 abort_egress:
386 return status;
387 }
388
TPM2_UnBind(TPMI_DH_OBJECT keyHandle,UINT32 ilen,void * in,UINT32 * olen,void * out)389 TPM_RC TPM2_UnBind(TPMI_DH_OBJECT keyHandle,
390 UINT32 ilen,
391 void *in,
392 UINT32 *olen,
393 void *out)
394 {
395 UINT32 status;
396 TPM2B_PUBLIC_KEY_RSA cipher, message;
397 TPMT_RSA_DECRYPT inScheme;
398 TPM2B_DATA label;
399
400 cipher.size = ilen;
401 memcpy(cipher.buffer, in, ilen);
402 inScheme.scheme = TPM2_ALG_NULL;
403 label.size = 0;
404
405 TPMTRYRETURN(TPM2_RSA_Decrypt(keyHandle, &cipher, &inScheme, &label, &message));
406
407 *olen = message.size;
408 memcpy(out, message.buffer, *olen);
409
410 abort_egress:
411 return status;
412 }
413
TPM2_CLEAR(void)414 TPM_RC TPM2_CLEAR(void)
415 {
416 TPM_BEGIN(TPM_ST_SESSIONS, TPM_CC_Clear);
417
418 ptr = pack_UINT32(ptr, TPM_RH_PLATFORM);
419 ptr = pack_TPM_AuthArea(ptr, &vtpm_globals.pw_auth);
420
421 TPM_TRANSMIT();
422 TPM_UNPACK_VERIFY();
423
424 abort_egress:
425 return status;
426 }
427
TPM2_GetRandom(UINT32 * bytesRequested,BYTE * randomBytes)428 TPM_RC TPM2_GetRandom(UINT32 * bytesRequested, BYTE * randomBytes)
429 {
430 TPM_BEGIN(TPM_ST_NO_SESSIONS, TPM_CC_GetRandom);
431
432 ptr = pack_UINT16(ptr, (UINT16)*bytesRequested);
433
434 TPM_TRANSMIT();
435 TPM_UNPACK_VERIFY();
436
437 ptr = unpack_UINT16(ptr, (UINT16 *)bytesRequested);
438 ptr = unpack_TPM_BUFFER(ptr, randomBytes, *bytesRequested);
439
440 abort_egress:
441 return status;
442 }
443
TPM2_FlushContext(TPMI_DH_CONTEXT flushHandle)444 TPM_RC TPM2_FlushContext(TPMI_DH_CONTEXT flushHandle)
445 {
446 TPM_BEGIN(TPM_ST_NO_SESSIONS, TPM_CC_FlushContext);
447
448 ptr = pack_UINT32(ptr, flushHandle);
449
450 TPM_TRANSMIT();
451 TPM_UNPACK_VERIFY();
452
453 abort_egress:
454 return status;
455 }
456