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