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