1 #include <console.h>
2 #include <unistd.h>
3 #include <errno.h>
4 #include <string.h>
5 #include <inttypes.h>
6 #include <stdlib.h>
7 #include <stdbool.h>
8 #include <mini-os/byteorder.h>
9 #include <polarssl/sha1.h>
10
11 #include "vtpm_manager.h"
12 #include "log.h"
13 #include "uuid.h"
14
15 #include "tpm.h"
16 #include "tcg.h"
17 #include "marshal.h"
18 #include "vtpmmgr.h"
19 #include "vtpm_disk.h"
20 #include "disk_tpm.h"
21 #include "disk_io.h"
22 #include "disk_crypto.h"
23 #include "disk_format.h"
24 #include "mgmt_authority.h"
25
do_provision_aik(struct mem_group * group,const struct tpm_authdata * privCADigest)26 static int do_provision_aik(struct mem_group *group,
27 const struct tpm_authdata *privCADigest)
28 {
29 TPM_KEY kinfo = {
30 .ver = TPM_STRUCT_VER_1_1,
31 .keyUsage = TPM_KEY_IDENTITY,
32 .keyFlags = 0,
33 .authDataUsage = TPM_AUTH_ALWAYS,
34 .algorithmParms = {
35 .algorithmID = TPM_ALG_RSA,
36 .encScheme = TPM_ES_NONE,
37 .sigScheme = TPM_SS_RSASSAPKCS1v15_SHA1,
38 .parmSize = 12,
39 .parms.rsa = {
40 .keyLength = RSA_KEY_SIZE,
41 .numPrimes = 2,
42 .exponentSize = 0,
43 .exponent = NULL,
44 },
45 },
46 .PCRInfoSize = 0,
47 .pubKey.keyLength = 0,
48 .encDataSize = 0,
49 };
50
51 TPM_AUTH_SESSION srkAuth = TPM_AUTH_SESSION_INIT;
52 TPM_AUTH_SESSION ownAuth = TPM_AUTH_SESSION_INIT;
53 TPM_SECRET osapMask;
54
55 TPM_KEY key = TPM_KEY_INIT;
56 UINT32 identityBindingSize;
57 BYTE* identityBinding = NULL;
58
59 TPM_RESULT rc;
60
61 rc = TPM_OSAP(TPM_ET_OWNER, 0, (void*)&vtpm_globals.owner_auth, &osapMask, &ownAuth);
62 if (rc)
63 return rc;
64
65 rc = TPM_OIAP(&srkAuth);
66 if (rc)
67 return rc;
68
69 rc = TPM_MakeIdentity((void*)&group->aik_authdata, (void*)privCADigest, &kinfo,
70 (void*)&vtpm_globals.srk_auth, (void*)&osapMask, &srkAuth, &ownAuth,
71 &key, &identityBindingSize, &identityBinding);
72
73 TPM_TerminateHandle(srkAuth.AuthHandle);
74 TPM_TerminateHandle(ownAuth.AuthHandle);
75
76 if (rc) {
77 printk("TPM_MakeIdentity failed: %d\n", rc);
78 return rc;
79 }
80
81 if (key.pubKey.keyLength != 256)
82 rc = TPM_FAIL;
83 if (key.encDataSize != 256)
84 rc = TPM_FAIL;
85 if (identityBindingSize != 256)
86 rc = TPM_FAIL;
87 if (rc) {
88 printk("TPM_MakeIdentity TPM_KEY mismatch: %d %d %d\n",
89 key.pubKey.keyLength, key.encDataSize, identityBindingSize);
90 } else {
91 memcpy(group->id_data.tpm_aik_public, key.pubKey.key, 256);
92 memcpy(group->id_data.tpm_aik_edata, key.encData, 256);
93 memcpy(group->details.recovery_data, identityBinding, 256);
94 }
95
96 free_TPM_KEY(&key);
97 free(identityBinding);
98
99 return rc;
100 }
101
do_load_aik(struct mem_group * group,TPM_HANDLE * handle)102 static int do_load_aik(struct mem_group *group, TPM_HANDLE *handle)
103 {
104 TPM_KEY key = {
105 .ver = TPM_STRUCT_VER_1_1,
106 .keyUsage = TPM_KEY_IDENTITY,
107 .keyFlags = 0,
108 .authDataUsage = TPM_AUTH_ALWAYS,
109 .algorithmParms = {
110 .algorithmID = TPM_ALG_RSA,
111 .encScheme = TPM_ES_NONE,
112 .sigScheme = TPM_SS_RSASSAPKCS1v15_SHA1,
113 .parmSize = 12,
114 .parms.rsa = {
115 .keyLength = RSA_KEY_SIZE,
116 .numPrimes = 2,
117 .exponentSize = 0,
118 .exponent = NULL,
119 },
120 },
121 .PCRInfoSize = 0,
122 .pubKey.keyLength = 256,
123 .pubKey.key = group->id_data.tpm_aik_public,
124 .encDataSize = 256,
125 .encData = group->id_data.tpm_aik_edata,
126 };
127
128 return TPM_LoadKey(TPM_SRK_KEYHANDLE, &key, handle, (void*)&vtpm_globals.srk_auth, &vtpm_globals.oiap);
129 }
130
do_vtpminfo_hash(uint32_t extra_info_flags,struct mem_group * group,const void * uuid,const uint8_t * kern_hash,unsigned char ** calc_hashes)131 static void do_vtpminfo_hash(uint32_t extra_info_flags,struct mem_group *group,
132 const void* uuid, const uint8_t* kern_hash,unsigned char** calc_hashes)
133 {
134 int i;
135 sha1_context ctx;
136 if(extra_info_flags & VTPM_QUOTE_FLAGS_HASH_UUID){
137 printk("hashing for FLAGS_HASH_UUID: ");
138 sha1_starts(&ctx);
139 if(uuid){
140 printk("true");
141 sha1_update(&ctx, (void*)uuid, 16);
142 }
143 sha1_finish(&ctx, *calc_hashes);
144 *calc_hashes = *calc_hashes + 20;
145 printk("\n");
146 }
147 if(extra_info_flags & VTPM_QUOTE_FLAGS_VTPM_MEASUREMENTS){
148 printk("hashing for VTPM_QUOTE_FLAGS_VTPM_MEASUREMENTS: ");
149 sha1_starts(&ctx);
150 if(kern_hash){
151 printk("true");
152 sha1_update(&ctx, (void*)kern_hash, 20);
153 }
154 sha1_finish(&ctx, *calc_hashes);
155 *calc_hashes = *calc_hashes + 20;
156 printk("\n");
157 }
158 if(extra_info_flags & VTPM_QUOTE_FLAGS_GROUP_INFO){
159 printk("hashing for VTPM_QUOTE_FLAGS_GROUP_INFO: true\n");
160 sha1_starts(&ctx);
161 sha1_update(&ctx, (void*)&group->id_data.saa_pubkey, sizeof(group->id_data.saa_pubkey));
162 sha1_update(&ctx, (void*)&group->details.cfg_seq, 8);
163 sha1_update(&ctx, (void*)&group->seal_bits.nr_cfgs, 4);
164 for(i=0; i < group->nr_seals; i++)
165 sha1_update(&ctx, (void*)&group->seals[i].digest_release, 20);
166 sha1_update(&ctx, (void*)&group->seal_bits.nr_kerns, 4);
167 sha1_update(&ctx, (void*)&group->seal_bits.kernels, 20 * be32_native(group->seal_bits.nr_kerns));
168 sha1_finish(&ctx, *calc_hashes);
169 *calc_hashes = *calc_hashes + 20;
170 }
171 if(extra_info_flags & VTPM_QUOTE_FLAGS_GROUP_PUBKEY){
172 printk("hashing for VTPM_QUOTE_FLAGS_GROUP_PUBKEY: true\n");
173 sha1_starts(&ctx);
174 sha1_update(&ctx, (void*)&group->id_data.saa_pubkey, sizeof(group->id_data.saa_pubkey));
175 sha1_finish(&ctx, *calc_hashes);
176 *calc_hashes = *calc_hashes + 20;
177 }
178 }
179
180 /*
181 * Sets up resettable PCRs for a vTPM deep quote request
182 */
do_pcr_setup(struct mem_group * group,const void * uuid,const uint8_t * kern_hash)183 static int do_pcr_setup(struct mem_group *group, const void* uuid, const uint8_t* kern_hash)
184 {
185 uint32_t reset_sel = (1 << 20) | (1 << 21) | (1 << 22) | (1 << 23);
186 sha1_context ctx;
187 TPM_DIGEST extended;
188 TPM_PCR_SELECTION sel = {
189 .sizeOfSelect = 3,
190 .pcrSelect = (void*)&reset_sel,
191 };
192 int rc;
193 int i;
194
195 rc = TPM_Reset(&sel);
196 if (rc)
197 return rc;
198
199 sha1((void*)&group->id_data.saa_pubkey, sizeof(group->id_data.saa_pubkey), extended.digest);
200 rc = TPM_Extend(20, &extended, &extended);
201 if (rc)
202 return rc;
203
204 sha1_starts(&ctx);
205 sha1_update(&ctx, (void*)&group->details.cfg_seq, 8);
206 sha1_update(&ctx, (void*)&group->seal_bits.nr_cfgs, 4);
207 for(i=0; i < group->nr_seals; i++)
208 sha1_update(&ctx, (void*)&group->seals[i].digest_release, 20);
209 sha1_update(&ctx, (void*)&group->seal_bits.nr_kerns, 4);
210 sha1_update(&ctx, (void*)&group->seal_bits.kernels, 20 * be32_native(group->seal_bits.nr_kerns));
211 sha1_finish(&ctx, extended.digest);
212 rc = TPM_Extend(21, &extended, &extended);
213 if (rc)
214 return rc;
215
216 if (kern_hash) {
217 rc = TPM_Extend(22, (void*)kern_hash, &extended);
218 if (rc)
219 return rc;
220 }
221
222 memset(&extended, 0, 20);
223 memcpy(&extended, group->id_data.uuid, 16);
224 rc = TPM_Extend(23, &extended, &extended);
225 if (rc)
226 return rc;
227
228 if (uuid) {
229 memset(&extended, 0, 20);
230 memcpy(&extended, uuid, 16);
231 rc = TPM_Extend(23, &extended, &extended);
232 if (rc)
233 return rc;
234 }
235
236 return rc;
237 }
238
vtpm_new_group(const struct tpm_authdata * privCADigest)239 struct mem_group *vtpm_new_group(const struct tpm_authdata *privCADigest)
240 {
241 static struct mem_group* group0_delayed = NULL;
242 struct mem_group *group;
243
244 if (group0_delayed) {
245 group = group0_delayed;
246 group0_delayed = NULL;
247 } else {
248 group = calloc(1, sizeof(*group));
249
250 group->flags = MEM_GROUP_FLAG_FIRSTBOOT;
251
252 do_random(&group->id_data.uuid, 16);
253 do_random(&group->group_key, 16);
254 do_random(&group->rollback_mac_key, 16);
255 do_random(&group->aik_authdata, 20);
256
257 group->id_data.uuid[6] = 0x40 | (group->id_data.uuid[6] & 0x0F);
258 group->id_data.uuid[8] = 0x80 | (group->id_data.uuid[8] & 0x3F);
259 }
260
261 if (privCADigest) {
262 int rc;
263 rc = do_provision_aik(group, privCADigest);
264 if (rc) {
265 free(group);
266 return NULL;
267 }
268 } else {
269 group0_delayed = group;
270 }
271
272 return group;
273 }
274
group_do_activate(struct mem_group * group,void * blob,int blobSize,void * resp,unsigned int * rlen)275 int group_do_activate(struct mem_group *group, void* blob, int blobSize,
276 void* resp, unsigned int *rlen)
277 {
278 int rc;
279 TPM_HANDLE handle;
280 TPM_AUTH_SESSION aikAuth = TPM_AUTH_SESSION_INIT;
281 TPM_AUTH_SESSION ownAuth = TPM_AUTH_SESSION_INIT;
282 TPM_SYMMETRIC_KEY symKey;
283
284 /* ActivateIdentity with TPM_EK_BLOB_ACTIVATE can check PCRs */
285 rc = do_pcr_setup(group, NULL, NULL);
286 if (rc)
287 return rc;
288
289 rc = do_load_aik(group, &handle);
290 if (rc)
291 return rc;
292
293 rc = TPM_OIAP(&aikAuth);
294 if (rc) {
295 TPM_TerminateHandle(handle);
296 return rc;
297 }
298
299 rc = TPM_OIAP(&ownAuth);
300 if (rc) {
301 TPM_TerminateHandle(aikAuth.AuthHandle);
302 TPM_TerminateHandle(handle);
303 return rc;
304 }
305
306 rc = TPM_ActivateIdentity(handle, blob, blobSize, (void*)&group->aik_authdata,
307 (void*)&vtpm_globals.owner_auth, &aikAuth, &ownAuth, &symKey);
308
309 TPM_TerminateHandle(ownAuth.AuthHandle);
310 TPM_TerminateHandle(aikAuth.AuthHandle);
311 TPM_TerminateHandle(handle);
312
313 if (rc)
314 return rc;
315
316 pack_TPM_SYMMETRIC_KEY(resp + *rlen, &symKey);
317 *rlen += 8 + symKey.size;
318 free(symKey.data);
319
320 return rc;
321 }
322
vtpm_do_quote(struct mem_group * group,const uuid_t uuid,const uint8_t * kern_hash,const struct tpm_authdata * data,TPM_PCR_SELECTION * sel,uint32_t extra_info_flags,void * pcr_out,uint32_t * pcr_size,void * sig_out)323 int vtpm_do_quote(struct mem_group *group, const uuid_t uuid,
324 const uint8_t* kern_hash, const struct tpm_authdata *data, TPM_PCR_SELECTION *sel,
325 uint32_t extra_info_flags, void* pcr_out, uint32_t *pcr_size, void* sig_out)
326 {
327 TPM_HANDLE handle;
328 TPM_AUTH_SESSION oiap = TPM_AUTH_SESSION_INIT;
329 TPM_PCR_COMPOSITE pcrs;
330 BYTE* sig;
331 UINT32 size;
332 sha1_context ctx;
333 TPM_DIGEST externData;
334 const void* data_to_quote = data;
335 unsigned char* ppcr_out = (unsigned char*)pcr_out;
336 unsigned char** pcr_outv = (unsigned char**)&ppcr_out;
337
338 int rc;
339 printk("Extra Info Flags =0x%x\n",extra_info_flags);
340 if((extra_info_flags & ~VTPM_QUOTE_FLAGS_HASH_UUID
341 & ~VTPM_QUOTE_FLAGS_VTPM_MEASUREMENTS
342 & ~VTPM_QUOTE_FLAGS_GROUP_INFO
343 & ~VTPM_QUOTE_FLAGS_GROUP_PUBKEY) != 0)
344 return VTPM_INVALID_REQUEST;
345
346 sha1_starts(&ctx);
347 sha1_update(&ctx, (void*)&extra_info_flags, 4);
348 sha1_update(&ctx, (void*)data, 20);
349 if(pcr_out!=NULL && extra_info_flags!=0)
350 {
351 /*creates hashes and sets them to pcr_out*/
352 do_vtpminfo_hash(extra_info_flags,group, uuid, kern_hash, pcr_outv);
353 *pcr_size = *pcr_outv - (unsigned char*)pcr_out;
354 if(*pcr_size > 0)
355 sha1_update(&ctx, pcr_out, *pcr_size);
356 }
357 sha1_finish(&ctx, externData.digest);
358 data_to_quote = (void*)externData.digest;
359
360 rc = do_load_aik(group, &handle);
361 if (rc)
362 return rc;
363
364 rc = TPM_OIAP(&oiap);
365 if (rc) {
366 TPM_TerminateHandle(handle);
367 return rc;
368 }
369
370 rc = TPM_Quote(handle, data_to_quote, sel, (void*)&group->aik_authdata, &oiap, &pcrs, &sig, &size);
371
372 TPM_TerminateHandle(oiap.AuthHandle);
373 TPM_FlushSpecific(handle, TPM_RT_KEY);
374
375 if (rc)
376 return rc;
377 if (size != 256) {
378 printk("Bad size\n");
379 rc = TPM_FAIL;
380 goto end;
381 }
382
383 if (pcr_out) {
384 /*append TPM_PCRVALUEs after externData hashes*/
385 memcpy(pcr_out+*pcr_size, pcrs.pcrValue, pcrs.valueSize);
386 *pcr_size = *pcr_size + pcrs.valueSize;
387 }
388
389 memcpy(sig_out, sig, size);
390
391 end:
392 free_TPM_PCR_COMPOSITE(&pcrs);
393 free(sig);
394
395 return rc;
396 }
397