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(&paramDigest, HMACkey, auth);\
85     ptr = pack_TPM_AUTH_SESSION(ptr, auth);\
86 } while(0)
87 
88 #define TPM_AUTH2_GEN(HMACkey, auth) do {\
89     generateAuth(&paramDigest, 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(&paramDigest, 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(&paramDigest, 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, &param_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, &param_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, &param_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