summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--stubdom/vtpmmgr/marshal.h15
-rw-r--r--stubdom/vtpmmgr/vtpm_cmd_handler.c61
2 files changed, 75 insertions, 1 deletions
diff --git a/stubdom/vtpmmgr/marshal.h b/stubdom/vtpmmgr/marshal.h
index dce19c6439..f1037a7976 100644
--- a/stubdom/vtpmmgr/marshal.h
+++ b/stubdom/vtpmmgr/marshal.h
@@ -891,6 +891,15 @@ inline int sizeof_TPM_AUTH_SESSION(const TPM_AUTH_SESSION* auth) {
}
static
+inline int sizeof_TPM_RQU_HEADER(BYTE* ptr) {
+ int rv = 0;
+ rv += sizeof_UINT16(ptr);
+ rv += sizeof_UINT32(ptr);
+ rv += sizeof_UINT32(ptr);
+ return rv;
+}
+
+static
inline BYTE* pack_TPM_RQU_HEADER(BYTE* ptr,
TPM_TAG tag,
UINT32 size,
@@ -920,8 +929,14 @@ inline int unpack3_TPM_RQU_HEADER(BYTE* ptr, UINT32* pos, UINT32 max,
unpack3_UINT32(ptr, pos, max, ord);
}
+static
+inline int sizeof_TPM_RQU_GetRandom(BYTE* ptr) {
+ return sizeof_TPM_RQU_HEADER(ptr) + sizeof_UINT32(ptr);
+}
+
#define pack_TPM_RSP_HEADER(p, t, s, r) pack_TPM_RQU_HEADER(p, t, s, r)
#define unpack_TPM_RSP_HEADER(p, t, s, r) unpack_TPM_RQU_HEADER(p, t, s, r)
#define unpack3_TPM_RSP_HEADER(p, l, m, t, s, r) unpack3_TPM_RQU_HEADER(p, l, m, t, s, r)
+#define sizeof_TPM_RSP_HEADER(p) sizeof_TPM_RQU_HEADER(p)
#endif
diff --git a/stubdom/vtpmmgr/vtpm_cmd_handler.c b/stubdom/vtpmmgr/vtpm_cmd_handler.c
index 2ac14fae77..c879b24c13 100644
--- a/stubdom/vtpmmgr/vtpm_cmd_handler.c
+++ b/stubdom/vtpmmgr/vtpm_cmd_handler.c
@@ -47,6 +47,7 @@
#include "vtpm_disk.h"
#include "vtpmmgr.h"
#include "tpm.h"
+#include "tpm2.h"
#include "tpmrsa.h"
#include "tcg.h"
#include "mgmt_authority.h"
@@ -772,6 +773,64 @@ static int vtpmmgr_permcheck(struct tpm_opaque *opq)
return 1;
}
+TPM_RESULT vtpmmgr_handle_getrandom(struct tpm_opaque *opaque,
+ tpmcmd_t* tpmcmd)
+{
+ TPM_RESULT status = TPM_SUCCESS;
+ TPM_TAG tag;
+ UINT32 size;
+ const int max_rand_size = TCPA_MAX_BUFFER_LENGTH -
+ sizeof_TPM_RQU_GetRandom(tpmcmd->req);
+ UINT32 rand_offset;
+ UINT32 rand_size;
+ TPM_COMMAND_CODE ord;
+ BYTE *p;
+
+ if (tpmcmd->req_len != sizeof_TPM_RQU_GetRandom(tpmcmd->req)) {
+ status = TPM_BAD_PARAMETER;
+ tag = TPM_TAG_RQU_COMMAND;
+ goto abort_egress;
+ }
+
+ p = unpack_TPM_RQU_HEADER(tpmcmd->req, &tag, &size, &ord);
+
+ if (!hw_is_tpm2()) {
+ size = TCPA_MAX_BUFFER_LENGTH;
+ TPMTRYRETURN(TPM_TransmitData(tpmcmd->req, tpmcmd->req_len,
+ tpmcmd->resp, &size));
+ tpmcmd->resp_len = size;
+
+ return TPM_SUCCESS;
+ }
+
+ /* TPM_GetRandom req: <header><uint32 num bytes> */
+ unpack_UINT32(p, &rand_size);
+
+ /* Returning fewer bytes is acceptable per the spec. */
+ if (rand_size > max_rand_size)
+ rand_size = max_rand_size;
+
+ /* Call TPM2_GetRandom but return a TPM_GetRandom response. */
+ /* TPM_GetRandom resp: <header><uint32 num bytes><num random bytes> */
+ rand_offset = sizeof_TPM_RSP_HEADER(tpmcmd->resp) +
+ sizeof_UINT32(tpmcmd->resp);
+
+ TPMTRYRETURN(TPM2_GetRandom(&rand_size, tpmcmd->resp + rand_offset));
+
+ p = pack_TPM_RSP_HEADER(tpmcmd->resp, TPM_TAG_RSP_COMMAND,
+ rand_offset + rand_size, status);
+ p = pack_UINT32(p, rand_size);
+ tpmcmd->resp_len = rand_offset + rand_size;
+
+ return status;
+
+abort_egress:
+ tpmcmd->resp_len = VTPM_COMMAND_HEADER_SIZE;
+ pack_TPM_RSP_HEADER(tpmcmd->resp, tag + 3, tpmcmd->resp_len, status);
+
+ return status;
+}
+
TPM_RESULT vtpmmgr_handle_cmd(
struct tpm_opaque *opaque,
tpmcmd_t* tpmcmd)
@@ -842,7 +901,7 @@ TPM_RESULT vtpmmgr_handle_cmd(
switch(ord) {
case TPM_ORD_GetRandom:
vtpmloginfo(VTPM_LOG_VTPM, "Passthrough: TPM_GetRandom\n");
- break;
+ return vtpmmgr_handle_getrandom(opaque, tpmcmd);
case TPM_ORD_PcrRead:
vtpmloginfo(VTPM_LOG_VTPM, "Passthrough: TPM_PcrRead\n");
// Quotes also need to be restricted to hide PCR values