1diff --git a/tpm/tpm_cmd_handler.c b/tpm/tpm_cmd_handler.c
2index 9e1cfb4..0fabf98 100644
3--- a/tpm/tpm_cmd_handler.c
4+++ b/tpm/tpm_cmd_handler.c
5@@ -3312,6 +3312,37 @@ static TPM_RESULT execute_TPM_OwnerReadPubek(TPM_REQUEST *req, TPM_RESPONSE *rsp
6   return res;
7 }
8
9+static TPM_RESULT execute_TPM_ParentSignEK(TPM_REQUEST *req, TPM_RESPONSE *rsp)
10+{
11+	TPM_NONCE nonce;
12+	TPM_RESULT res;
13+	UINT32 sigSize;
14+	BYTE *sig;
15+	BYTE *ptr;
16+	UINT32 len;
17+	TPM_PCR_SELECTION targetPCR;
18+
19+	tpm_compute_in_param_digest(req);
20+
21+	ptr = req->param;
22+	len = req->paramSize;
23+	if (tpm_unmarshal_TPM_NONCE(&ptr, &len, &nonce)
24+		|| tpm_unmarshal_TPM_PCR_SELECTION(&ptr, &len, &targetPCR)
25+		|| len != 0) return TPM_BAD_PARAMETER;
26+
27+	res = TPM_ParentSignEK(&nonce, &targetPCR, &req->auth1, &sigSize, &sig);
28+	if (res != TPM_SUCCESS) return res;
29+	rsp->paramSize = len = sigSize;
30+	rsp->param = ptr = tpm_malloc(len);
31+	if (ptr == NULL || tpm_marshal_BLOB(&ptr, &len, sig, sigSize)) {
32+		tpm_free(rsp->param);
33+		res = TPM_FAIL;
34+	}
35+	tpm_free(sig);
36+
37+	return res;
38+}
39+
40 static void tpm_setup_rsp_auth(TPM_COMMAND_CODE ordinal, TPM_RESPONSE *rsp)
41 {
42   tpm_hmac_ctx_t hmac;
43@@ -4062,6 +4093,11 @@ void tpm_execute_command(TPM_REQUEST *req, TPM_RESPONSE *rsp)
44       res = execute_TPM_OwnerReadPubek(req, rsp);
45     break;
46
47+    case TPM_ORD_ParentSignEK:
48+      debug("[TPM_ORD_ParentSignEK]");
49+      res = execute_TPM_ParentSignEK(req, rsp);
50+    break;
51+
52     default:
53 #ifdef MTM_EMULATOR
54       res = mtm_execute_command(req, rsp);
55diff --git a/tpm/tpm_commands.h b/tpm/tpm_commands.h
56index a7666f6..7fef934 100644
57--- a/tpm/tpm_commands.h
58+++ b/tpm/tpm_commands.h
59@@ -3054,6 +3054,23 @@ TPM_RESULT TPM_OwnerReadPubek(
60   TPM_PUBKEY *pubEndorsementKey
61 );
62
63+/**
64+ * TPM_ParentSignEK - gets a hardware TPM quote of a vTPM's EK
65+ * @externalData: [in] AntiReplay nonce to prevent replay of messages
66+ * @sel: [in] PCR selection for the hardware TPM's quote
67+ * @auth1: [in, out] Authorization protocol parameters
68+ * @sigSize: [out] The length of the returned digital signature
69+ * @sig: [out] The resulting digital signature and PCR values
70+ * Returns: TPM_SUCCESS on success, a TPM error code otherwise.
71+ */
72+TPM_RESULT TPM_ParentSignEK(
73+  TPM_NONCE *externalData,
74+  TPM_PCR_SELECTION *sel,
75+  TPM_AUTH *auth1,
76+  UINT32 *sigSize,
77+  BYTE **sig
78+);
79+
80 /*
81  * Error handling
82  * [tpm_error.c]
83diff --git a/tpm/tpm_credentials.c b/tpm/tpm_credentials.c
84index 9cd64af..01f29e6 100644
85--- a/tpm/tpm_credentials.c
86+++ b/tpm/tpm_credentials.c
87@@ -180,3 +180,34 @@ TPM_RESULT TPM_OwnerReadInternalPub(TPM_KEY_HANDLE keyHandle, TPM_AUTH *auth1,
88     return TPM_BAD_PARAMETER;
89   }
90 }
91+
92+int endorsementKeyFresh = 0;
93+
94+TPM_RESULT VTPM_GetParentQuote(TPM_DIGEST* data, TPM_PCR_SELECTION *sel, UINT32 *sigSize, BYTE **sig);
95+
96+TPM_RESULT TPM_ParentSignEK(TPM_NONCE *externalData, TPM_PCR_SELECTION *sel,
97+                            TPM_AUTH *auth1, UINT32 *sigSize, BYTE **sig)
98+{
99+	TPM_PUBKEY pubKey;
100+	TPM_RESULT res;
101+	TPM_DIGEST hres;
102+
103+	info("TPM_ParentSignEK()");
104+
105+	res = tpm_verify_auth(auth1, tpmData.permanent.data.ownerAuth, TPM_KH_OWNER);
106+	if (res != TPM_SUCCESS) return res;
107+
108+	if (!endorsementKeyFresh) return TPM_DISABLED_CMD;
109+
110+	res = tpm_get_pubek(&pubKey);
111+	if (res != TPM_SUCCESS) return res;
112+
113+	if (tpm_compute_pubkey_checksum(externalData, &pubKey, &hres))
114+		res = TPM_FAIL;
115+
116+	if (res == TPM_SUCCESS)
117+		res = VTPM_GetParentQuote(&hres, sel, sigSize, sig);
118+
119+	free_TPM_PUBKEY(pubKey);
120+	return res;
121+}
122diff --git a/tpm/tpm_data.c b/tpm/tpm_data.c
123index 50c9697..6a0c499 100644
124--- a/tpm/tpm_data.c
125+++ b/tpm/tpm_data.c
126@@ -76,6 +76,8 @@ static void init_timeouts(void)
127   tpmData.permanent.data.cmd_durations[2] = 1000;
128 }
129
130+extern int endorsementKeyFresh;
131+
132 void tpm_init_data(void)
133 {
134   /* endorsement key */
135@@ -157,6 +159,7 @@ void tpm_init_data(void)
136   if (tpmConf & TPM_CONF_GENERATE_EK) {
137     /* generate a new endorsement key */
138     tpm_rsa_generate_key(&tpmData.permanent.data.endorsementKey, 2048);
139+    endorsementKeyFresh = 1;
140   } else {
141     /* setup endorsement key */
142     tpm_rsa_import_key(&tpmData.permanent.data.endorsementKey,
143diff --git a/tpm/tpm_structures.h b/tpm/tpm_structures.h
144index f746c05..b0f4625 100644
145--- a/tpm/tpm_structures.h
146+++ b/tpm/tpm_structures.h
147@@ -658,6 +658,49 @@ typedef struct tdTPM_CMK_MA_APPROVAL {
148 #define TPM_ORD_TickStampBlob                   242
149 #define TPM_ORD_MAX                             256
150
151+/* VTPM-only commands: */
152+/*
153+ * ParentSignEK - Proof of fresh provisioning and EK value
154+ *
155+ * Input:
156+ *   TPM_TAG             tag           TPM_TAG_RQU_AUTH1_COMMAND
157+ *   UINT32              paramSize     Total size of request
158+ *   TPM_COMMAND_CODE    ordinal       TPM_ORD_ParentSignEK
159+ *   TPM_NONCE           externData    20 bytes of external data
160+ *   TPM_PCR_SELECTION   ptSel         PCR selection for physical TPM
161+ *   ---
162+ *   UINT32              authHandle    Owner authorization session (OIAP)
163+ *   TPM_NONCE           nonceOdd      Nonce for authHandle
164+ *   BOOL                continueAuth  Continue flag for authHandle
165+ *   TPM_AUTHDATA        privAuth      Authorization digest for command
166+ *
167+ * Output:
168+ *   TPM_TAG             tag           TPM_TAG_RSP_AUTH1_COMMAND
169+ *   UINT32              paramSize     Total size of response
170+ *   TPM_RESULT          returnCode    Return code of the operation
171+ *   BYTE[]              sig           Signature provided by physical TPM
172+ *   TPM_PCRVALUE[]      pcrValue      Values of hardware PCRs used in the quote
173+ *   ---
174+ *   TPM_NONCE           nonceEven     Nonce for authHandle
175+ *   BOOL                continueAuth  Continue flag for authHandle
176+ *   TPM_AUTHDATA        resAuth       Authorization digest for response
177+ *
178+ * This command is only valid on the first boot of a vTPM; on any subsequent
179+ * boot, the command returns TPM_DISABLED_CMD. It is intended to be used to
180+ * provide evidence of proper platform configuration to the verifier/CA which is
181+ * responsible for the creation of the vTPM's endorsement credential, which will
182+ * be used on subsequent boots to certify AIKs via the usual Privacy CA protocol.
183+ *
184+ * The values of the virtual TPM's PCRs are not included in the response.
185+ * The signature is a standard TPM_Quote response from the physical TPM; its
186+ * externalData is the SHA1 hash of the following structure:
187+ *   TPM_PUBKEY          pubEK         The vTPM's public EK
188+ *   TPM_NONCE           externData    From input to the deep quote
189+ *
190+ * This structure was chosen to match the return of TPM_ReadPubek
191+ */
192+#define TPM_ORD_ParentSignEK                    (TPM_VENDOR_COMMAND | TPM_ORD_ReadPubek)
193+
194 /*
195  * TCS Ordinals ([TPM_Part2], Section 17.1)
196  *
197