1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (c) 2013 The Chromium OS Authors.
4 * Coypright (c) 2013 Guntermann & Drunck GmbH
5 */
6
7#define LOG_CATEGORY UCLASS_TPM
8
9#include <dm.h>
10#include <log.h>
11#include <asm/unaligned.h>
12#include <u-boot/sha1.h>
13#include <tpm-common.h>
14#include <tpm-v1.h>
15#include "tpm-utils.h"
16
17#ifdef CONFIG_TPM_AUTH_SESSIONS
18
19#ifndef CONFIG_SHA1
20#error "TPM_AUTH_SESSIONS require SHA1 to be configured, too"
21#endif /* !CONFIG_SHA1 */
22
23struct session_data {
24	int		valid;
25	u32	handle;
26	u8		nonce_even[DIGEST_LENGTH];
27	u8		nonce_odd[DIGEST_LENGTH];
28};
29
30static struct session_data oiap_session = {0, };
31
32#endif /* CONFIG_TPM_AUTH_SESSIONS */
33
34u32 tpm1_startup(struct udevice *dev, enum tpm_startup_type mode)
35{
36	const u8 command[12] = {
37		0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x0, 0x0, 0x0, 0x99, 0x0, 0x0,
38	};
39	const size_t mode_offset = 10;
40	u8 buf[COMMAND_BUFFER_SIZE];
41
42	if (pack_byte_string(buf, sizeof(buf), "sw",
43			     0, command, sizeof(command),
44			     mode_offset, mode))
45		return TPM_LIB_ERROR;
46
47	return tpm_sendrecv_command(dev, buf, NULL, NULL);
48}
49
50u32 tpm1_resume(struct udevice *dev)
51{
52	return tpm1_startup(dev, TPM_ST_STATE);
53}
54
55u32 tpm1_self_test_full(struct udevice *dev)
56{
57	const u8 command[10] = {
58		0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x50,
59	};
60	return tpm_sendrecv_command(dev, command, NULL, NULL);
61}
62
63u32 tpm1_continue_self_test(struct udevice *dev)
64{
65	const u8 command[10] = {
66		0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x53,
67	};
68	return tpm_sendrecv_command(dev, command, NULL, NULL);
69}
70
71u32 tpm1_auto_start(struct udevice *dev)
72{
73	u32 rc;
74
75	rc = tpm1_startup(dev, TPM_ST_CLEAR);
76	/* continue on if the TPM is already inited */
77	if (rc && rc != TPM_INVALID_POSTINIT)
78		return rc;
79
80	rc = tpm1_self_test_full(dev);
81
82	return rc;
83}
84
85u32 tpm1_clear_and_reenable(struct udevice *dev)
86{
87	u32 ret;
88
89	log_info("TPM: Clear and re-enable\n");
90	ret = tpm1_force_clear(dev);
91	if (ret != TPM_SUCCESS) {
92		log_err("Can't initiate a force clear\n");
93		return ret;
94	}
95
96	ret = tpm1_physical_enable(dev);
97	if (ret != TPM_SUCCESS) {
98		log_err("TPM: Can't set enabled state\n");
99		return ret;
100	}
101
102	ret = tpm1_physical_set_deactivated(dev, 0);
103	if (ret != TPM_SUCCESS) {
104		log_err("TPM: Can't set deactivated state\n");
105		return ret;
106	}
107
108	return TPM_SUCCESS;
109}
110
111u32 tpm1_nv_define_space(struct udevice *dev, u32 index, u32 perm, u32 size)
112{
113	const u8 command[101] = {
114		0x0, 0xc1,		/* TPM_TAG */
115		0x0, 0x0, 0x0, 0x65,	/* parameter size */
116		0x0, 0x0, 0x0, 0xcc,	/* TPM_COMMAND_CODE */
117		/* TPM_NV_DATA_PUBLIC->... */
118		0x0, 0x18,		/* ...->TPM_STRUCTURE_TAG */
119		0, 0, 0, 0,		/* ...->TPM_NV_INDEX */
120		/* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
121		0x0, 0x3,
122		0, 0, 0,
123		0x1f,
124		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
125		/* TPM_NV_DATA_PUBLIC->TPM_PCR_INFO_SHORT */
126		0x0, 0x3,
127		0, 0, 0,
128		0x1f,
129		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
130		/* TPM_NV_ATTRIBUTES->... */
131		0x0, 0x17,		/* ...->TPM_STRUCTURE_TAG */
132		0, 0, 0, 0,		/* ...->attributes */
133		/* End of TPM_NV_ATTRIBUTES */
134		0,			/* bReadSTClear */
135		0,			/* bWriteSTClear */
136		0,			/* bWriteDefine */
137		0, 0, 0, 0,		/* size */
138	};
139	const size_t index_offset = 12;
140	const size_t perm_offset = 70;
141	const size_t size_offset = 77;
142	u8 buf[COMMAND_BUFFER_SIZE];
143
144	if (pack_byte_string(buf, sizeof(buf), "sddd",
145			     0, command, sizeof(command),
146			     index_offset, index,
147			     perm_offset, perm,
148			     size_offset, size))
149		return TPM_LIB_ERROR;
150
151	return tpm_sendrecv_command(dev, buf, NULL, NULL);
152}
153
154u32 tpm1_nv_set_locked(struct udevice *dev)
155{
156	return tpm1_nv_define_space(dev, TPM_NV_INDEX_LOCK, 0, 0);
157}
158
159u32 tpm1_nv_read_value(struct udevice *dev, u32 index, void *data, u32 count)
160{
161	const u8 command[22] = {
162		0x0, 0xc1, 0x0, 0x0, 0x0, 0x16, 0x0, 0x0, 0x0, 0xcf,
163	};
164	const size_t index_offset = 10;
165	const size_t length_offset = 18;
166	const size_t data_size_offset = 10;
167	const size_t data_offset = 14;
168	u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
169	size_t response_length = sizeof(response);
170	u32 data_size;
171	u32 err;
172
173	if (pack_byte_string(buf, sizeof(buf), "sdd",
174			     0, command, sizeof(command),
175			     index_offset, index,
176			     length_offset, count))
177		return TPM_LIB_ERROR;
178	err = tpm_sendrecv_command(dev, buf, response, &response_length);
179	if (err)
180		return err;
181	if (unpack_byte_string(response, response_length, "d",
182			       data_size_offset, &data_size))
183		return TPM_LIB_ERROR;
184	if (data_size > count)
185		return TPM_LIB_ERROR;
186	if (unpack_byte_string(response, response_length, "s",
187			       data_offset, data, data_size))
188		return TPM_LIB_ERROR;
189
190	return 0;
191}
192
193u32 tpm1_nv_write_value(struct udevice *dev, u32 index, const void *data,
194			u32 length)
195{
196	const u8 command[256] = {
197		0x0, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xcd,
198	};
199	const size_t command_size_offset = 2;
200	const size_t index_offset = 10;
201	const size_t length_offset = 18;
202	const size_t data_offset = 22;
203	const size_t write_info_size = 12;
204	const u32 total_length =
205		TPM_REQUEST_HEADER_LENGTH + write_info_size + length;
206	u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
207	size_t response_length = sizeof(response);
208	u32 err;
209
210	if (pack_byte_string(buf, sizeof(buf), "sddds",
211			     0, command, sizeof(command),
212			     command_size_offset, total_length,
213			     index_offset, index,
214			     length_offset, length,
215			     data_offset, data, length))
216		return TPM_LIB_ERROR;
217	err = tpm_sendrecv_command(dev, buf, response, &response_length);
218	if (err)
219		return err;
220
221	return 0;
222}
223
224u32 tpm1_extend(struct udevice *dev, u32 index, const void *in_digest,
225		void *out_digest)
226{
227	const u8 command[34] = {
228		0x0, 0xc1, 0x0, 0x0, 0x0, 0x22, 0x0, 0x0, 0x0, 0x14,
229	};
230	const size_t index_offset = 10;
231	const size_t in_digest_offset = 14;
232	const size_t out_digest_offset = 10;
233	u8 buf[COMMAND_BUFFER_SIZE];
234	u8 response[TPM_RESPONSE_HEADER_LENGTH + PCR_DIGEST_LENGTH];
235	size_t response_length = sizeof(response);
236	u32 err;
237
238	if (pack_byte_string(buf, sizeof(buf), "sds",
239			     0, command, sizeof(command),
240			     index_offset, index,
241			     in_digest_offset, in_digest,
242			     PCR_DIGEST_LENGTH))
243		return TPM_LIB_ERROR;
244	err = tpm_sendrecv_command(dev, buf, response, &response_length);
245	if (err)
246		return err;
247
248	if (unpack_byte_string(response, response_length, "s",
249			       out_digest_offset, out_digest,
250			       PCR_DIGEST_LENGTH))
251		return TPM_LIB_ERROR;
252
253	return 0;
254}
255
256u32 tpm1_pcr_read(struct udevice *dev, u32 index, void *data, size_t count)
257{
258	const u8 command[14] = {
259		0x0, 0xc1, 0x0, 0x0, 0x0, 0xe, 0x0, 0x0, 0x0, 0x15,
260	};
261	const size_t index_offset = 10;
262	const size_t out_digest_offset = 10;
263	u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
264	size_t response_length = sizeof(response);
265	u32 err;
266
267	if (count < PCR_DIGEST_LENGTH)
268		return TPM_LIB_ERROR;
269
270	if (pack_byte_string(buf, sizeof(buf), "sd",
271			     0, command, sizeof(command),
272			     index_offset, index))
273		return TPM_LIB_ERROR;
274	err = tpm_sendrecv_command(dev, buf, response, &response_length);
275	if (err)
276		return err;
277	if (unpack_byte_string(response, response_length, "s",
278			       out_digest_offset, data, PCR_DIGEST_LENGTH))
279		return TPM_LIB_ERROR;
280
281	return 0;
282}
283
284u32 tpm1_tsc_physical_presence(struct udevice *dev, u16 presence)
285{
286	const u8 command[12] = {
287		0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x0, 0x0,
288	};
289	const size_t presence_offset = 10;
290	u8 buf[COMMAND_BUFFER_SIZE];
291
292	if (pack_byte_string(buf, sizeof(buf), "sw",
293			     0, command, sizeof(command),
294			     presence_offset, presence))
295		return TPM_LIB_ERROR;
296
297	return tpm_sendrecv_command(dev, buf, NULL, NULL);
298}
299
300u32 tpm1_finalise_physical_presence(struct udevice *dev)
301{
302	const u8 command[12] = {
303		0x0, 0xc1, 0x0, 0x0, 0x0, 0xc, 0x40, 0x0, 0x0, 0xa, 0x2, 0xa0,
304	};
305
306	return tpm_sendrecv_command(dev, command, NULL, NULL);
307}
308
309u32 tpm1_read_pubek(struct udevice *dev, void *data, size_t count)
310{
311	const u8 command[30] = {
312		0x0, 0xc1, 0x0, 0x0, 0x0, 0x1e, 0x0, 0x0, 0x0, 0x7c,
313	};
314	const size_t response_size_offset = 2;
315	const size_t data_offset = 10;
316	const size_t header_and_checksum_size = TPM_RESPONSE_HEADER_LENGTH + 20;
317	u8 response[COMMAND_BUFFER_SIZE + TPM_PUBEK_SIZE];
318	size_t response_length = sizeof(response);
319	u32 data_size;
320	u32 err;
321
322	err = tpm_sendrecv_command(dev, command, response, &response_length);
323	if (err)
324		return err;
325	if (unpack_byte_string(response, response_length, "d",
326			       response_size_offset, &data_size))
327		return TPM_LIB_ERROR;
328	if (data_size < header_and_checksum_size)
329		return TPM_LIB_ERROR;
330	data_size -= header_and_checksum_size;
331	if (data_size > count)
332		return TPM_LIB_ERROR;
333	if (unpack_byte_string(response, response_length, "s",
334			       data_offset, data, data_size))
335		return TPM_LIB_ERROR;
336
337	return 0;
338}
339
340u32 tpm1_force_clear(struct udevice *dev)
341{
342	const u8 command[10] = {
343		0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x5d,
344	};
345
346	return tpm_sendrecv_command(dev, command, NULL, NULL);
347}
348
349u32 tpm1_physical_enable(struct udevice *dev)
350{
351	const u8 command[10] = {
352		0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x6f,
353	};
354
355	return tpm_sendrecv_command(dev, command, NULL, NULL);
356}
357
358u32 tpm1_physical_disable(struct udevice *dev)
359{
360	const u8 command[10] = {
361		0x0, 0xc1, 0x0, 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0x70,
362	};
363
364	return tpm_sendrecv_command(dev, command, NULL, NULL);
365}
366
367u32 tpm1_physical_set_deactivated(struct udevice *dev, u8 state)
368{
369	const u8 command[11] = {
370		0x0, 0xc1, 0x0, 0x0, 0x0, 0xb, 0x0, 0x0, 0x0, 0x72,
371	};
372	const size_t state_offset = 10;
373	u8 buf[COMMAND_BUFFER_SIZE];
374
375	if (pack_byte_string(buf, sizeof(buf), "sb",
376			     0, command, sizeof(command),
377			     state_offset, state))
378		return TPM_LIB_ERROR;
379
380	return tpm_sendrecv_command(dev, buf, NULL, NULL);
381}
382
383u32 tpm1_get_capability(struct udevice *dev, u32 cap_area, u32 sub_cap,
384			void *cap, size_t count)
385{
386	const u8 command[22] = {
387		0x0, 0xc1,		/* TPM_TAG */
388		0x0, 0x0, 0x0, 0x16,	/* parameter size */
389		0x0, 0x0, 0x0, 0x65,	/* TPM_COMMAND_CODE */
390		0x0, 0x0, 0x0, 0x0,	/* TPM_CAPABILITY_AREA */
391		0x0, 0x0, 0x0, 0x4,	/* subcap size */
392		0x0, 0x0, 0x0, 0x0,	/* subcap value */
393	};
394	const size_t cap_area_offset = 10;
395	const size_t sub_cap_offset = 18;
396	const size_t cap_offset = 14;
397	const size_t cap_size_offset = 10;
398	u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
399	size_t response_length = sizeof(response);
400	u32 cap_size;
401	u32 err;
402
403	if (pack_byte_string(buf, sizeof(buf), "sdd",
404			     0, command, sizeof(command),
405			     cap_area_offset, cap_area,
406			     sub_cap_offset, sub_cap))
407		return TPM_LIB_ERROR;
408	err = tpm_sendrecv_command(dev, buf, response, &response_length);
409	if (err)
410		return err;
411	if (unpack_byte_string(response, response_length, "d",
412			       cap_size_offset, &cap_size))
413		return TPM_LIB_ERROR;
414	if (cap_size > response_length || cap_size > count)
415		return TPM_LIB_ERROR;
416	if (unpack_byte_string(response, response_length, "s",
417			       cap_offset, cap, cap_size))
418		return TPM_LIB_ERROR;
419
420	return 0;
421}
422
423u32 tpm1_get_permanent_flags(struct udevice *dev,
424			     struct tpm_permanent_flags *pflags)
425{
426	const u8 command[22] = {
427		0x0, 0xc1,		/* TPM_TAG */
428		0x0, 0x0, 0x0, 0x16,	/* parameter size */
429		0x0, 0x0, 0x0, 0x65,	/* TPM_COMMAND_CODE */
430		0x0, 0x0, 0x0, 0x4,	/* TPM_CAP_FLAG_PERM */
431		0x0, 0x0, 0x0, 0x4,	/* subcap size */
432		0x0, 0x0, 0x1, 0x8,	/* subcap value */
433	};
434	const size_t data_size_offset = TPM_HEADER_SIZE;
435	const size_t data_offset = TPM_HEADER_SIZE + sizeof(u32);
436	u8 response[COMMAND_BUFFER_SIZE];
437	size_t response_length = sizeof(response);
438	u32 err;
439	u32 data_size;
440
441	err = tpm_sendrecv_command(dev, command, response, &response_length);
442	if (err)
443		return err;
444	if (unpack_byte_string(response, response_length, "d",
445			       data_size_offset, &data_size)) {
446		log_err("Cannot unpack data size\n");
447		return TPM_LIB_ERROR;
448	}
449	if (data_size < sizeof(*pflags)) {
450		log_err("Data size too small\n");
451		return TPM_LIB_ERROR;
452	}
453	if (unpack_byte_string(response, response_length, "s",
454			       data_offset, pflags, sizeof(*pflags))) {
455		log_err("Cannot unpack pflags\n");
456		return TPM_LIB_ERROR;
457	}
458
459	return 0;
460}
461
462u32 tpm1_get_permissions(struct udevice *dev, u32 index, u32 *perm)
463{
464	const u8 command[22] = {
465		0x0, 0xc1,		/* TPM_TAG */
466		0x0, 0x0, 0x0, 0x16,	/* parameter size */
467		0x0, 0x0, 0x0, 0x65,	/* TPM_COMMAND_CODE */
468		0x0, 0x0, 0x0, 0x11,
469		0x0, 0x0, 0x0, 0x4,
470	};
471	const size_t index_offset = 18;
472	const size_t perm_offset = 74;
473	u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
474	size_t response_length = sizeof(response);
475	u32 err;
476
477	if (pack_byte_string(buf, sizeof(buf), "sd",
478			     0, command, sizeof(command),
479			     index_offset, index))
480		return TPM_LIB_ERROR;
481	err = tpm_sendrecv_command(dev, buf, response, &response_length);
482	if (err)
483		return err;
484	if (unpack_byte_string(response, response_length, "d",
485			       perm_offset, perm))
486		return TPM_LIB_ERROR;
487
488	return 0;
489}
490
491#ifdef CONFIG_TPM_FLUSH_RESOURCES
492u32 tpm1_flush_specific(struct udevice *dev, u32 key_handle, u32 resource_type)
493{
494	const u8 command[18] = {
495		0x00, 0xc1,             /* TPM_TAG */
496		0x00, 0x00, 0x00, 0x12, /* parameter size */
497		0x00, 0x00, 0x00, 0xba, /* TPM_COMMAND_CODE */
498		0x00, 0x00, 0x00, 0x00, /* key handle */
499		0x00, 0x00, 0x00, 0x00, /* resource type */
500	};
501	const size_t key_handle_offset = 10;
502	const size_t resource_type_offset = 14;
503	u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
504	size_t response_length = sizeof(response);
505	u32 err;
506
507	if (pack_byte_string(buf, sizeof(buf), "sdd",
508			     0, command, sizeof(command),
509			     key_handle_offset, key_handle,
510			     resource_type_offset, resource_type))
511		return TPM_LIB_ERROR;
512
513	err = tpm_sendrecv_command(dev, buf, response, &response_length);
514	if (err)
515		return err;
516	return 0;
517}
518#endif /* CONFIG_TPM_FLUSH_RESOURCES */
519
520#ifdef CONFIG_TPM_AUTH_SESSIONS
521
522/**
523 * Fill an authentication block in a request.
524 * This func can create the first as well as the second auth block (for
525 * double authorized commands).
526 *
527 * @param request	pointer to the request (w/ uninitialised auth data)
528 * @param request_len0	length of the request without auth data
529 * @param handles_len	length of the handles area in request
530 * @param auth_session	pointer to the (valid) auth session to be used
531 * @param request_auth	pointer to the auth block of the request to be filled
532 * @param auth		authentication data (HMAC key)
533 */
534static u32 create_request_auth(const void *request, size_t request_len0,
535			       size_t handles_len,
536			       struct session_data *auth_session,
537			       void *request_auth, const void *auth)
538{
539	u8 hmac_data[DIGEST_LENGTH * 3 + 1];
540	sha1_context hash_ctx;
541	const size_t command_code_offset = 6;
542	const size_t auth_nonce_odd_offset = 4;
543	const size_t auth_continue_offset = 24;
544	const size_t auth_auth_offset = 25;
545
546	if (!auth_session || !auth_session->valid)
547		return TPM_LIB_ERROR;
548
549	sha1_starts(&hash_ctx);
550	sha1_update(&hash_ctx, request + command_code_offset, 4);
551	if (request_len0 > TPM_REQUEST_HEADER_LENGTH + handles_len)
552		sha1_update(&hash_ctx,
553			    request + TPM_REQUEST_HEADER_LENGTH + handles_len,
554			    request_len0 - TPM_REQUEST_HEADER_LENGTH
555			    - handles_len);
556	sha1_finish(&hash_ctx, hmac_data);
557
558	sha1_starts(&hash_ctx);
559	sha1_update(&hash_ctx, auth_session->nonce_odd, DIGEST_LENGTH);
560	sha1_update(&hash_ctx, hmac_data, sizeof(hmac_data));
561	sha1_finish(&hash_ctx, auth_session->nonce_odd);
562
563	if (pack_byte_string(request_auth, TPM_REQUEST_AUTH_LENGTH, "dsb",
564			     0, auth_session->handle,
565			     auth_nonce_odd_offset, auth_session->nonce_odd,
566			     DIGEST_LENGTH,
567			     auth_continue_offset, 1))
568		return TPM_LIB_ERROR;
569	if (pack_byte_string(hmac_data, sizeof(hmac_data), "ss",
570			     DIGEST_LENGTH,
571			     auth_session->nonce_even,
572			     DIGEST_LENGTH,
573			     2 * DIGEST_LENGTH,
574			     request_auth + auth_nonce_odd_offset,
575			     DIGEST_LENGTH + 1))
576		return TPM_LIB_ERROR;
577	sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
578		  request_auth + auth_auth_offset);
579
580	return TPM_SUCCESS;
581}
582
583/**
584 * Verify an authentication block in a response.
585 * Since this func updates the nonce_even in the session data it has to be
586 * called when receiving a succesfull AUTH response.
587 * This func can verify the first as well as the second auth block (for
588 * double authorized commands).
589 *
590 * @param command_code	command code of the request
591 * @param response	pointer to the request (w/ uninitialised auth data)
592 * @param handles_len	length of the handles area in response
593 * @param auth_session	pointer to the (valid) auth session to be used
594 * @param response_auth	pointer to the auth block of the response to be verified
595 * @param auth		authentication data (HMAC key)
596 */
597static u32 verify_response_auth(u32 command_code, const void *response,
598				size_t response_len0, size_t handles_len,
599				struct session_data *auth_session,
600				const void *response_auth, const void *auth)
601{
602	u8 hmac_data[DIGEST_LENGTH * 3 + 1];
603	u8 computed_auth[DIGEST_LENGTH];
604	sha1_context hash_ctx;
605	const size_t return_code_offset = 6;
606	const size_t auth_continue_offset = 20;
607	const size_t auth_auth_offset = 21;
608	u8 auth_continue;
609
610	if (!auth_session || !auth_session->valid)
611		return TPM_AUTHFAIL;
612	if (pack_byte_string(hmac_data, sizeof(hmac_data), "d",
613			     0, command_code))
614		return TPM_LIB_ERROR;
615	if (response_len0 < TPM_RESPONSE_HEADER_LENGTH)
616		return TPM_LIB_ERROR;
617
618	sha1_starts(&hash_ctx);
619	sha1_update(&hash_ctx, response + return_code_offset, 4);
620	sha1_update(&hash_ctx, hmac_data, 4);
621	if (response_len0 > TPM_RESPONSE_HEADER_LENGTH + handles_len)
622		sha1_update(&hash_ctx,
623			    response + TPM_RESPONSE_HEADER_LENGTH + handles_len,
624			    response_len0 - TPM_RESPONSE_HEADER_LENGTH
625			    - handles_len);
626	sha1_finish(&hash_ctx, hmac_data);
627
628	memcpy(auth_session->nonce_even, response_auth, DIGEST_LENGTH);
629	auth_continue = ((u8 *)response_auth)[auth_continue_offset];
630	if (pack_byte_string(hmac_data, sizeof(hmac_data), "ssb",
631			     DIGEST_LENGTH,
632			     response_auth,
633			     DIGEST_LENGTH,
634			     2 * DIGEST_LENGTH,
635			     auth_session->nonce_odd,
636			     DIGEST_LENGTH,
637			     3 * DIGEST_LENGTH,
638			     auth_continue))
639		return TPM_LIB_ERROR;
640
641	sha1_hmac(auth, DIGEST_LENGTH, hmac_data, sizeof(hmac_data),
642		  computed_auth);
643
644	if (memcmp(computed_auth, response_auth + auth_auth_offset,
645		   DIGEST_LENGTH))
646		return TPM_AUTHFAIL;
647
648	return TPM_SUCCESS;
649}
650
651u32 tpm1_terminate_auth_session(struct udevice *dev, u32 auth_handle)
652{
653	const u8 command[18] = {
654		0x00, 0xc1,		/* TPM_TAG */
655		0x00, 0x00, 0x00, 0x00,	/* parameter size */
656		0x00, 0x00, 0x00, 0xba,	/* TPM_COMMAND_CODE */
657		0x00, 0x00, 0x00, 0x00,	/* TPM_HANDLE */
658		0x00, 0x00, 0x00, 0x02,	/* TPM_RESOURCE_TYPE */
659	};
660	const size_t req_handle_offset = TPM_REQUEST_HEADER_LENGTH;
661	u8 request[COMMAND_BUFFER_SIZE];
662
663	if (pack_byte_string(request, sizeof(request), "sd",
664			     0, command, sizeof(command),
665			     req_handle_offset, auth_handle))
666		return TPM_LIB_ERROR;
667	if (oiap_session.valid && oiap_session.handle == auth_handle)
668		oiap_session.valid = 0;
669
670	return tpm_sendrecv_command(dev, request, NULL, NULL);
671}
672
673u32 tpm1_end_oiap(struct udevice *dev)
674{
675	u32 err = TPM_SUCCESS;
676
677	if (oiap_session.valid)
678		err = tpm1_terminate_auth_session(dev, oiap_session.handle);
679	return err;
680}
681
682u32 tpm1_oiap(struct udevice *dev, u32 *auth_handle)
683{
684	const u8 command[10] = {
685		0x00, 0xc1,		/* TPM_TAG */
686		0x00, 0x00, 0x00, 0x0a,	/* parameter size */
687		0x00, 0x00, 0x00, 0x0a,	/* TPM_COMMAND_CODE */
688	};
689	const size_t res_auth_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
690	const size_t res_nonce_even_offset = TPM_RESPONSE_HEADER_LENGTH + 4;
691	u8 response[COMMAND_BUFFER_SIZE];
692	size_t response_length = sizeof(response);
693	u32 err;
694
695	if (oiap_session.valid)
696		tpm1_terminate_auth_session(dev, oiap_session.handle);
697
698	err = tpm_sendrecv_command(dev, command, response, &response_length);
699	if (err)
700		return err;
701	if (unpack_byte_string(response, response_length, "ds",
702			       res_auth_handle_offset, &oiap_session.handle,
703			       res_nonce_even_offset, &oiap_session.nonce_even,
704			       (u32)DIGEST_LENGTH))
705		return TPM_LIB_ERROR;
706	oiap_session.valid = 1;
707	if (auth_handle)
708		*auth_handle = oiap_session.handle;
709	return 0;
710}
711
712u32 tpm1_load_key2_oiap(struct udevice *dev, u32 parent_handle, const void *key,
713			size_t key_length, const void *parent_key_usage_auth,
714			u32 *key_handle)
715{
716	const u8 command[14] = {
717		0x00, 0xc2,		/* TPM_TAG */
718		0x00, 0x00, 0x00, 0x00,	/* parameter size */
719		0x00, 0x00, 0x00, 0x41,	/* TPM_COMMAND_CODE */
720		0x00, 0x00, 0x00, 0x00,	/* parent handle */
721	};
722	const size_t req_size_offset = 2;
723	const size_t req_parent_handle_offset = TPM_REQUEST_HEADER_LENGTH;
724	const size_t req_key_offset = TPM_REQUEST_HEADER_LENGTH + 4;
725	const size_t res_handle_offset = TPM_RESPONSE_HEADER_LENGTH;
726	u8 request[sizeof(command) + TPM_KEY12_MAX_LENGTH +
727		   TPM_REQUEST_AUTH_LENGTH];
728	u8 response[COMMAND_BUFFER_SIZE];
729	size_t response_length = sizeof(response);
730	u32 err;
731
732	if (!oiap_session.valid) {
733		err = tpm1_oiap(dev, NULL);
734		if (err)
735			return err;
736	}
737	if (pack_byte_string(request, sizeof(request), "sdds",
738			     0, command, sizeof(command),
739			     req_size_offset,
740			     sizeof(command) + key_length
741			     + TPM_REQUEST_AUTH_LENGTH,
742			     req_parent_handle_offset, parent_handle,
743			     req_key_offset, key, key_length
744		))
745		return TPM_LIB_ERROR;
746
747	err = create_request_auth(request, sizeof(command) + key_length, 4,
748				  &oiap_session,
749				  request + sizeof(command) + key_length,
750				  parent_key_usage_auth);
751	if (err)
752		return err;
753	err = tpm_sendrecv_command(dev, request, response, &response_length);
754	if (err) {
755		if (err == TPM_AUTHFAIL)
756			oiap_session.valid = 0;
757		return err;
758	}
759
760	err = verify_response_auth(0x00000041, response,
761				   response_length - TPM_RESPONSE_AUTH_LENGTH,
762				   4, &oiap_session,
763				   response + response_length -
764				   TPM_RESPONSE_AUTH_LENGTH,
765				   parent_key_usage_auth);
766	if (err)
767		return err;
768
769	if (key_handle) {
770		if (unpack_byte_string(response, response_length, "d",
771				       res_handle_offset, key_handle))
772			return TPM_LIB_ERROR;
773	}
774
775	return 0;
776}
777
778u32 tpm1_get_pub_key_oiap(struct udevice *dev, u32 key_handle,
779			  const void *usage_auth, void *pubkey,
780			  size_t *pubkey_len)
781{
782	const u8 command[14] = {
783		0x00, 0xc2,		/* TPM_TAG */
784		0x00, 0x00, 0x00, 0x00,	/* parameter size */
785		0x00, 0x00, 0x00, 0x21,	/* TPM_COMMAND_CODE */
786		0x00, 0x00, 0x00, 0x00,	/* key handle */
787	};
788	const size_t req_size_offset = 2;
789	const size_t req_key_handle_offset = TPM_REQUEST_HEADER_LENGTH;
790	const size_t res_pubkey_offset = TPM_RESPONSE_HEADER_LENGTH;
791	u8 request[sizeof(command) + TPM_REQUEST_AUTH_LENGTH];
792	u8 response[TPM_RESPONSE_HEADER_LENGTH + TPM_PUBKEY_MAX_LENGTH +
793		    TPM_RESPONSE_AUTH_LENGTH];
794	size_t response_length = sizeof(response);
795	u32 err;
796
797	if (!oiap_session.valid) {
798		err = tpm1_oiap(dev, NULL);
799		if (err)
800			return err;
801	}
802	if (pack_byte_string(request, sizeof(request), "sdd",
803			     0, command, sizeof(command),
804			     req_size_offset,
805			     (u32)(sizeof(command)
806			     + TPM_REQUEST_AUTH_LENGTH),
807			     req_key_handle_offset, key_handle
808		))
809		return TPM_LIB_ERROR;
810	err = create_request_auth(request, sizeof(command), 4, &oiap_session,
811				  request + sizeof(command), usage_auth);
812	if (err)
813		return err;
814	err = tpm_sendrecv_command(dev, request, response, &response_length);
815	if (err) {
816		if (err == TPM_AUTHFAIL)
817			oiap_session.valid = 0;
818		return err;
819	}
820	err = verify_response_auth(0x00000021, response,
821				   response_length - TPM_RESPONSE_AUTH_LENGTH,
822				   0, &oiap_session,
823				   response + response_length -
824				   TPM_RESPONSE_AUTH_LENGTH,
825				   usage_auth);
826	if (err)
827		return err;
828
829	if (pubkey) {
830		if ((response_length - TPM_RESPONSE_HEADER_LENGTH
831		     - TPM_RESPONSE_AUTH_LENGTH) > *pubkey_len)
832			return TPM_LIB_ERROR;
833		*pubkey_len = response_length - TPM_RESPONSE_HEADER_LENGTH
834			- TPM_RESPONSE_AUTH_LENGTH;
835		memcpy(pubkey, response + res_pubkey_offset,
836		       response_length - TPM_RESPONSE_HEADER_LENGTH
837		       - TPM_RESPONSE_AUTH_LENGTH);
838	}
839
840	return 0;
841}
842
843#ifdef CONFIG_TPM_LOAD_KEY_BY_SHA1
844u32 tpm1_find_key_sha1(struct udevice *dev, const u8 auth[20],
845		       const u8 pubkey_digest[20], u32 *handle)
846{
847	u16 key_count;
848	u32 key_handles[10];
849	u8 buf[288];
850	u8 *ptr;
851	u32 err;
852	u8 digest[20];
853	size_t buf_len;
854	unsigned int i;
855
856	/* fetch list of already loaded keys in the TPM */
857	err = tpm1_get_capability(dev, TPM_CAP_HANDLE, TPM_RT_KEY, buf,
858				 sizeof(buf));
859	if (err)
860		return -1;
861	key_count = get_unaligned_be16(buf);
862	ptr = buf + 2;
863	for (i = 0; i < key_count; ++i, ptr += 4)
864		key_handles[i] = get_unaligned_be32(ptr);
865
866	/* now search a(/ the) key which we can access with the given auth */
867	for (i = 0; i < key_count; ++i) {
868		buf_len = sizeof(buf);
869		err = tpm1_get_pub_key_oiap(dev, key_handles[i], auth, buf, &buf_len);
870		if (err && err != TPM_AUTHFAIL)
871			return -1;
872		if (err)
873			continue;
874		sha1_csum(buf, buf_len, digest);
875		if (!memcmp(digest, pubkey_digest, 20)) {
876			*handle = key_handles[i];
877			return 0;
878		}
879	}
880	return 1;
881}
882#endif /* CONFIG_TPM_LOAD_KEY_BY_SHA1 */
883
884#endif /* CONFIG_TPM_AUTH_SESSIONS */
885
886u32 tpm1_get_random(struct udevice *dev, void *data, u32 count)
887{
888	const u8 command[14] = {
889		0x0, 0xc1,		/* TPM_TAG */
890		0x0, 0x0, 0x0, 0xe,	/* parameter size */
891		0x0, 0x0, 0x0, 0x46,	/* TPM_COMMAND_CODE */
892	};
893	const size_t length_offset = 10;
894	const size_t data_size_offset = 10;
895	const size_t data_offset = 14;
896	u8 buf[COMMAND_BUFFER_SIZE], response[COMMAND_BUFFER_SIZE];
897	size_t response_length = sizeof(response);
898	u32 data_size;
899	u8 *out = data;
900
901	while (count > 0) {
902		u32 this_bytes = min((size_t)count,
903				     sizeof(response) - data_offset);
904		u32 err;
905
906		if (pack_byte_string(buf, sizeof(buf), "sd",
907				     0, command, sizeof(command),
908				     length_offset, this_bytes))
909			return TPM_LIB_ERROR;
910		err = tpm_sendrecv_command(dev, buf, response,
911					   &response_length);
912		if (err)
913			return err;
914		if (unpack_byte_string(response, response_length, "d",
915				       data_size_offset, &data_size))
916			return TPM_LIB_ERROR;
917		if (data_size > count)
918			return TPM_LIB_ERROR;
919		if (unpack_byte_string(response, response_length, "s",
920				       data_offset, out, data_size))
921			return TPM_LIB_ERROR;
922
923		count -= data_size;
924		out += data_size;
925	}
926
927	return 0;
928}
929