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