1 // SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
2 /* Copyright 2020 IBM Corp. */
3 
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <skiboot.h>
8 #include <opal-api.h>
9 #include <tssskiboot.h>
10 #include <tpm_chip.h>
11 #include <ibmtss/tssfile.h>
12 #include <ibmtss/TPM_Types.h>
13 #include <ibmtss/tssmarshal.h>
14 #include <ibmtss/tssresponsecode.h>
15 
16 #define TSS_MAX_NV_BUFFER_SIZE 1024
17 
18 /*
19  * Helper to string-fy TSS error response codes.
20  */
tss_error_trace(const char * function,TPM_RC rc)21 static void tss_error_trace(const char *function, TPM_RC rc)
22 {
23 	const char *msg;
24 	const char *submsg;
25 	const char *num;
26 	prlog(PR_ERR, "%s: failed, rc %08x\n", function, rc);
27 	TSS_ResponseCode_toString(&msg, &submsg, &num, rc);
28 	prlog(PR_ERR, "%s%s%s\n", msg, submsg, num);
29 }
30 
31 /*
32  * @brief Reads the public and name area of a NV Index.
33  * @param nv_index 		The target NV index to read public info from.
34  * @param nv_public		buffer to save public are read from nv index
35  * @param nv_name		buffer to save nv index name.
36  */
tss_nv_read_public(TPMI_RH_NV_INDEX nv_index,TPMS_NV_PUBLIC * nv_public,TPM2B_NAME * nv_name)37 int tss_nv_read_public(TPMI_RH_NV_INDEX nv_index, TPMS_NV_PUBLIC *nv_public,
38 		       TPM2B_NAME *nv_name)
39 {
40 	NV_ReadPublic_Out *out = NULL;
41 	NV_ReadPublic_In *in = NULL;
42 	TSS_CONTEXT *context = NULL;
43 	TPM_RC rc = OPAL_SUCCESS;
44 
45 	if (!nv_public || !nv_name) {
46 		rc = OPAL_PARAMETER;
47 		goto cleanup;
48 	}
49 
50 	in = zalloc(sizeof(NV_ReadPublic_In));
51 	if (!in) {
52 		rc = OPAL_NO_MEM;
53 		goto cleanup;
54 	}
55 
56 	out = zalloc(sizeof(NV_ReadPublic_Out));
57 	if (!out) {
58 		rc = OPAL_NO_MEM;
59 		goto cleanup;
60 	}
61 
62 	rc = TSS_Create(&context);
63 	if (rc) {
64 		tss_error_trace("tss_nv_read_public", rc);
65 		rc = OPAL_NO_MEM;
66 		goto cleanup;
67 	}
68 
69 	in->nvIndex = nv_index;
70 	rc = TSS_Execute(context,
71 			 (RESPONSE_PARAMETERS *) out,
72 			 (COMMAND_PARAMETERS *) in,
73 			 NULL,
74 			 TPM_CC_NV_ReadPublic,
75 			 TPM_RH_NULL, NULL, 0);
76 	if (!rc) {
77 		memcpy(nv_public, &out->nvPublic, sizeof(TPMS_NV_PUBLIC));
78 		memcpy(nv_name, &out->nvName, sizeof(TPM2B_NAME));
79 	}
80 	else
81 		tss_error_trace("tss_nv_read_public", rc);
82 cleanup:
83 	free(in);
84 	free(out);
85 	TSS_Delete(context);
86 	return rc;
87 }
88 
89 /* @brief This command reads a value from an area previously defined using
90  * nv_define_space
91  * @param nv_index 		The target NV index to read from.
92  * @param buffer		buffer to save the data read.
93  * @param buffer_size		size of the buffer, to avoid overflow.
94  * @param offset		position where to start the nv read operation.
95  */
tss_nv_read(TPMI_RH_NV_INDEX nv_index,void * buffer,size_t buffer_size,uint16_t offset)96 int tss_nv_read(TPMI_RH_NV_INDEX nv_index, void *buffer,
97 		size_t buffer_size, uint16_t offset)
98 {
99 	TSS_CONTEXT *context = NULL;
100 	NV_Read_Out *out = NULL;
101 	NV_Read_In *in = NULL;
102 	TPM_RC rc = OPAL_SUCCESS;
103 	int64_t buffer_remaining;
104 
105 	if (!buffer) {
106 		rc = OPAL_PARAMETER;
107 		goto cleanup;
108 	}
109 
110 	in = zalloc(sizeof(NV_Read_In));
111 	if (!in) {
112 		rc = OPAL_NO_MEM;
113 		goto cleanup;
114 	}
115 
116 	out = zalloc(sizeof(NV_Read_Out));
117 	if (!out) {
118 		rc = OPAL_NO_MEM;
119 		goto cleanup;
120 	}
121 
122 	rc = TSS_Create(&context);
123 	if (rc) {
124 		tss_error_trace("tss_nv_read", rc);
125 		rc = OPAL_NO_MEM;
126 		goto cleanup;
127 	}
128 
129 	in->nvIndex = nv_index;
130 	in->authHandle = nv_index;
131 
132 	buffer_remaining = buffer_size;
133 	while (buffer_remaining > 0) {
134 		in->offset = offset;
135 		in->size = MIN(TSS_MAX_NV_BUFFER_SIZE, buffer_remaining);
136 
137 		rc = TSS_Execute(context,
138 				 (RESPONSE_PARAMETERS *) out,
139 				 (COMMAND_PARAMETERS *) in,
140 				 NULL,
141 				 TPM_CC_NV_Read,
142 				 TPM_RS_PW, NULL, 0,
143 				 TPM_RH_NULL, NULL, 0);
144 
145 		if (rc) {
146 			tss_error_trace("tss_nv_read", rc);
147 			goto cleanup;
148 		}
149 
150 		memcpy(buffer, out->data.b.buffer, in->size);
151 		buffer += TSS_MAX_NV_BUFFER_SIZE;
152 		buffer_remaining -= TSS_MAX_NV_BUFFER_SIZE;
153 		offset += TSS_MAX_NV_BUFFER_SIZE;
154 	}
155 
156 cleanup:
157 	TSS_Delete(context);
158 	free(in);
159 	free(out);
160 	return rc;
161 }
162 
163 /* @brief This command writes a value in an area previously defined using
164  * nv_define_space
165  * @param nv_index 		The target NV index to write to.
166  * @param buffer		buffer containing the data write.
167  * @param buffer_size		size of the buffer to write.
168  * @param offset		position where to start the nv write operation.
169  */
tss_nv_write(TPMI_RH_NV_INDEX nv_index,void * buffer,size_t buffer_size,uint16_t offset)170 int tss_nv_write(TPMI_RH_NV_INDEX nv_index, void *buffer,
171 		 size_t buffer_size, uint16_t offset)
172 {
173 	TSS_CONTEXT *context = NULL;
174 	NV_Write_In *in = NULL;
175 	TPM_RC rc = OPAL_SUCCESS;
176 	int64_t buffer_remaining;
177 
178 	if (!buffer) {
179 		rc = OPAL_PARAMETER;
180 		goto cleanup;
181 	}
182 
183 	in = zalloc(sizeof(NV_Write_In));
184 	if (!in) {
185 		rc = OPAL_NO_MEM;
186 		goto cleanup;
187 	}
188 
189 	rc = TSS_Create(&context);
190 	if (rc) {
191 		tss_error_trace("tss_nv_write", rc);
192 		rc = OPAL_NO_MEM;
193 		goto cleanup;
194 	}
195 
196 	in->nvIndex = nv_index;
197 	in->authHandle = TPM_RH_PLATFORM;
198 
199 	buffer_remaining = buffer_size;
200 	while (buffer_remaining > 0) {
201 		in->offset = offset;
202 		rc = TSS_TPM2B_Create(&in->data.b, buffer,
203 				      MIN(TSS_MAX_NV_BUFFER_SIZE, buffer_remaining),
204 				      sizeof(in->data.t.buffer));
205 
206 		if (rc) {
207 			tss_error_trace("tss_nv_write", rc);
208 			goto cleanup;
209 		}
210 
211 		rc = TSS_Execute(context,
212 				 NULL,
213 				 (COMMAND_PARAMETERS *) in,
214 				 NULL,
215 				 TPM_CC_NV_Write,
216 				 TPM_RS_PW, NULL, 0,
217 				 TPM_RH_NULL, NULL, 0);
218 		if (rc) {
219 			tss_error_trace("tss_nv_write", rc);
220 			goto cleanup;
221 		}
222 
223 		buffer += TSS_MAX_NV_BUFFER_SIZE;
224 		buffer_remaining -= TSS_MAX_NV_BUFFER_SIZE;
225 		offset += TSS_MAX_NV_BUFFER_SIZE;
226 	}
227 
228 cleanup:
229 	TSS_Delete(context);
230 	free(in);
231 	return rc;
232 }
233 
234 /*
235  * @brief This command locks an area, pointed by the index and previously
236  * defined using nv_define_space, preventing further writing operations on it.
237  * @param nv_index 		The target NV index to lock.
238  */
tss_nv_write_lock(TPMI_RH_NV_INDEX nv_index)239 int tss_nv_write_lock(TPMI_RH_NV_INDEX nv_index)
240 {
241 	TSS_CONTEXT *context = NULL;
242 	NV_WriteLock_In *in = NULL;
243 	TPM_RC rc = OPAL_SUCCESS;
244 
245 	in = zalloc(sizeof(NV_WriteLock_In));
246 	if (!in) {
247 		rc = OPAL_NO_MEM;
248 		goto cleanup;
249 	}
250 
251 	rc = TSS_Create(&context);
252 	if (rc) {
253 		rc = OPAL_NO_MEM;
254 		goto cleanup;
255 	}
256 
257 	in->authHandle = TPM_RH_PLATFORM;
258 	in->nvIndex = nv_index;
259 	rc = TSS_Execute(context,
260 			 NULL,
261 			 (COMMAND_PARAMETERS *) in,
262 			 NULL,
263 			 TPM_CC_NV_WriteLock,
264 			 TPM_RS_PW, NULL, 0,
265 			 TPM_RH_NULL, NULL, 0);
266 	if (rc)
267 		tss_error_trace("tss_nv_write_lock", rc);
268 cleanup:
269 	TSS_Delete(context);
270 	free(in);
271 	return rc;
272 }
273 
274  /*
275  * @brief This command defines the area pointed by nv index and its attributes.
276  * @param nv_index 		The target NV index to define.
277  * @param data_size		size of the area to be defined.
278  */
tss_nv_define_space(TPMI_RH_NV_INDEX nv_index,uint16_t data_size)279 int tss_nv_define_space(TPMI_RH_NV_INDEX nv_index, uint16_t data_size)
280 {
281 	NV_DefineSpace_In *in = NULL;
282 	TSS_CONTEXT *context = NULL;
283 	TPM_RC rc = OPAL_SUCCESS;
284 
285 	in = zalloc(sizeof(NV_DefineSpace_In));
286 	if (!in) {
287 		rc = OPAL_NO_MEM;
288 		goto cleanup;
289 	}
290 
291 	rc = TSS_Create(&context);
292 	if (rc) {
293 		rc = OPAL_NO_MEM;
294 		goto cleanup;
295 	}
296 
297 	in->authHandle = TPM_RH_PLATFORM;
298 
299 	in->publicInfo.nvPublic.nvIndex = nv_index;
300 	in->publicInfo.nvPublic.dataSize = data_size;
301 	/* password is NULL so b.size is 0 */
302 	in->auth.b.size = 0;
303 	/* Empty policy, so size is 0 */
304 	in->publicInfo.nvPublic.authPolicy.t.size = 0;
305 	/* Used algorithm is SHA256 */
306 	in->publicInfo.nvPublic.nameAlg = TPM_ALG_SHA256;
307 	/*
308 	 * This carries the flags set according to default settings, excepting
309 	 * for what is set by this function parameters. Further customization
310 	 * will require a different setup for nvAttribute flags as is done in
311 	 * TSS's code.
312 	 */
313 	in->publicInfo.nvPublic.attributes.val = (TPMA_NVA_PPWRITE |
314 						  TPMA_NVA_ORDINARY |
315 						  TPMA_NVA_WRITE_STCLEAR |
316 						  TPMA_NVA_AUTHREAD |
317 						  TPMA_NVA_PLATFORMCREATE |
318 						  TPMA_NVA_NO_DA);
319 
320 	rc = TSS_Execute(context,
321 			 NULL,
322 			 (COMMAND_PARAMETERS *)in,
323 			 NULL,
324 			 TPM_CC_NV_DefineSpace,
325 			 TPM_RS_PW, NULL, 0,
326 			 TPM_RH_NULL, NULL, 0);
327 	if (rc) {
328 		tss_error_trace("tss_nv_define_space", rc);
329 		switch(rc) {
330 			case TPM_RC_NV_DEFINED:
331 				rc = OPAL_WRONG_STATE;
332 				break;
333 			default:
334 				break;
335 		}
336 	}
337 cleanup:
338 	TSS_Delete(context);
339 	free(in);
340 	return rc;
341 }
342 
343 /*
344  * @brief Extends a PCR using the given hashes and digest
345  * @param pcr_handle		The PCR to be extended
346  * @param alg_hashes		A pointer to an array of hash algorithms, each
347  * 				one used to extend its respective PCR bank.
348  * @param alg_hash_count	The number of elements in alg_hashes array
349  * @param digests		The digest data.
350  */
tss_pcr_extend(TPMI_DH_PCR pcr_handle,TPMI_ALG_HASH * alg_hashes,uint8_t alg_hash_count,const uint8_t ** digests)351 int tss_pcr_extend(TPMI_DH_PCR pcr_handle, TPMI_ALG_HASH *alg_hashes,
352 		   uint8_t alg_hash_count, const uint8_t **digests)
353 {
354 	TSS_CONTEXT *context = NULL;
355 	uint32_t rc = OPAL_SUCCESS;
356 	PCR_Extend_In *in = NULL;
357 	uint16_t digest_size;
358 
359 	if (!alg_hashes || !digests || pcr_handle >= IMPLEMENTATION_PCR) {
360 		rc = OPAL_PARAMETER;
361 		goto cleanup;
362 	}
363 
364 	in = zalloc(sizeof(PCR_Extend_In));
365 	if (!in) {
366 		rc = OPAL_NO_MEM;
367 		goto cleanup;
368 	}
369 
370 	rc = TSS_Create(&context);
371 	if (rc) {
372 		tss_error_trace("tss_pcr_extend", rc);
373 		rc = OPAL_NO_MEM;
374 		goto cleanup;
375 	}
376 
377 	if (alg_hash_count >= HASH_COUNT) {
378 		rc = OPAL_PARAMETER;
379 		goto cleanup;
380 	}
381 
382 	in->digests.count = alg_hash_count;
383 	in->pcrHandle = pcr_handle;
384 	for (uint8_t i=0; i < alg_hash_count; i++) {
385 		in->digests.digests[i].hashAlg = alg_hashes[i];
386 		/* memset zeroes first to assure the digest data is zero
387 		 * padded.*/
388 		memset((uint8_t*) &in->digests.digests[i].digest, 0,
389 		       sizeof(TPMU_HA));
390 
391 		digest_size = 0;
392 		/* Marshal the digest in order to obtain its size. This is a
393 		 * commonly used pattern in TSS.
394 		 */
395 		rc = TSS_TPMU_HA_Marshalu((const TPMU_HA *)digests[i],
396 					  &digest_size, NULL, NULL ,
397 					  alg_hashes[i]);
398 		if (rc)
399 			goto cleanup;
400 		memcpy((uint8_t*) &in->digests.digests[i].digest, digests[i],
401 		       digest_size);
402 	}
403 	rc = TSS_Execute(context,
404 			 NULL,
405 			 (COMMAND_PARAMETERS *) in,
406 			 NULL,
407 			 TPM_CC_PCR_Extend,
408 			 TPM_RS_PW, NULL, 0,
409 			 TPM_RH_NULL, NULL, 0);
410 	if (rc)
411 		tss_error_trace("tss_pcr_extend", rc);
412 cleanup:
413 	TSS_Delete(context);
414 	free(in);
415 	return rc;
416 }
417 
418 /*
419  * @brief reads pcr values of a given pcr handle.
420  * @param pcr_handle		The PCR to be extended
421  * @param alg_hashes		A pointer to an array of hash algorithms, each
422  * 				one used to extend its respective PCR bank.
423  * @param alg_hash_count	The length of alg hashes array
424  */
tss_pcr_read(TPMI_DH_PCR pcr_handle,TPMI_ALG_HASH * alg_hashes,uint8_t alg_hash_count)425 int tss_pcr_read(TPMI_DH_PCR pcr_handle, TPMI_ALG_HASH *alg_hashes,
426 		 uint8_t alg_hash_count)
427 {
428 	TSS_CONTEXT *context = NULL;
429 	PCR_Read_Out *out = NULL;
430 	PCR_Read_In *in = NULL;
431 	uint32_t rc = OPAL_SUCCESS;
432 
433 	if (!alg_hashes) {
434 		rc = OPAL_PARAMETER;
435 		goto cleanup;
436 	}
437 
438 	in = zalloc(sizeof(PCR_Read_In));
439 	if (!in) {
440 		rc = OPAL_NO_MEM;
441 		goto cleanup;
442 	}
443 
444 	out = zalloc(sizeof(PCR_Read_Out));
445 	if (!out) {
446 		rc = OPAL_NO_MEM;
447 		goto cleanup;
448 	}
449 
450 	rc = TSS_Create(&context);
451 	if (!rc) {
452 		tss_error_trace("tss_pcr_read", rc);
453 		rc = OPAL_NO_MEM;
454 		goto cleanup;
455 	}
456 
457 	in->pcrSelectionIn.count = alg_hash_count;
458 	for (int i=0; i < alg_hash_count; i++) {
459 		in->pcrSelectionIn.pcrSelections[i].hash = alg_hashes[i];
460 		in->pcrSelectionIn.pcrSelections[i].sizeofSelect = 3;
461 		in->pcrSelectionIn.pcrSelections[i].pcrSelect[0] = 0;
462 		in->pcrSelectionIn.pcrSelections[i].pcrSelect[1] = 0;
463 		in->pcrSelectionIn.pcrSelections[i].pcrSelect[2] = 0;
464 		in->pcrSelectionIn.pcrSelections[i].pcrSelect[pcr_handle/8] = 1 << (pcr_handle % 8);
465 	}
466 
467 	rc = TSS_Execute(context,
468 			 (RESPONSE_PARAMETERS *) out,
469 			 (COMMAND_PARAMETERS *) in,
470 			 NULL,
471 			 TPM_CC_PCR_Read,
472 			 TPM_RH_NULL, NULL, 0);
473 	if (rc)
474 		tss_error_trace("tss_pcr_read", rc);
475 cleanup:
476 	TSS_Delete(context);
477 	free(in);
478 	free(out);
479 	return rc;
480 }
481 
482 /*
483  * @brief returns next bytes_requested bytes from the TPM RNG
484  * @param buffer		Buffer to save the generated numbers.
485  * @param bytes_requested	How many random bytes are requested.
486  */
tss_get_random_number(void * buffer,uint16_t bytes_requested)487 int tss_get_random_number(void *buffer, uint16_t bytes_requested)
488 {
489 	TSS_CONTEXT *context = NULL;
490 	GetRandom_Out *out = NULL;
491 	TPM_RC rc = OPAL_SUCCESS;
492 	GetRandom_In *in = NULL;
493 	void *p_buffer = buffer;
494 
495 	if (!buffer) {
496 		rc = OPAL_PARAMETER;
497 		goto cleanup;
498 	}
499 
500 	in = zalloc(sizeof(GetRandom_In));
501 	if (!in) {
502 		rc = OPAL_NO_MEM;
503 		goto cleanup;
504 	}
505 
506 	out = zalloc(sizeof(GetRandom_Out));
507 	if (!out) {
508 		rc = OPAL_NO_MEM;
509 		goto cleanup;
510 	}
511 
512 	rc = TSS_Create(&context);
513 	if (rc) {
514 		tss_error_trace("tss_get_random_number", rc);
515 		rc = OPAL_NO_MEM;
516 		goto cleanup;
517 	}
518 
519 	/*
520 	 * Even though we request a specific number of bytes, there is no
521 	 * guarantee that TPM will return that number of bytes, so we ask again
522 	 * until we reach the desired total of bytes or rng function fails
523 	 */
524 	for (uint16_t bytes_copied = 0; bytes_copied < bytes_requested; ) {
525 		in->bytesRequested = bytes_requested - bytes_copied;
526 		rc = TSS_Execute(context,
527 				 (RESPONSE_PARAMETERS *)out,
528 				 (COMMAND_PARAMETERS *)in,
529 				 NULL, TPM_CC_GetRandom,
530 				 TPM_RH_NULL, NULL, 0);
531 		if (!rc){
532 			memcpy(p_buffer, out->randomBytes.t.buffer,
533 			       out->randomBytes.t.size);
534 			bytes_copied += out->randomBytes.t.size;
535 			p_buffer += bytes_copied;
536 			/* explicitly clean up output's buffer from memory on
537 			 * every iteration, since the size will vary, to avoid
538 			 * some kind of exploitation.
539 			 */
540 			memset(out->randomBytes.t.buffer, 0,
541 			       out->randomBytes.t.size);
542 
543 		}
544 		else {
545 			tss_error_trace("tss_get_random_number", rc);
546 			break;
547 		}
548 	}
549 
550 cleanup:
551 	TSS_Delete(context);
552 	free(in);
553 	free(out);
554 	return rc;
555 }
556 
557 /* local helper to generate random password without zeroes */
generate_random_passwd(char * passwd,uint16_t passwd_len)558 static int generate_random_passwd(char *passwd, uint16_t passwd_len)
559 {
560 	TPM_RC rc = OPAL_SUCCESS;
561 	char *buffer = NULL;
562 	int bytes_copied;
563 	int i;
564 
565 	buffer = zalloc(passwd_len);
566 	if (!buffer) {
567 		rc = OPAL_NO_MEM;
568 		goto cleanup;
569 	}
570 
571 	bytes_copied = 0;
572 	while ((rc == 0) && (bytes_copied < passwd_len)) {
573 		rc = tss_get_random_number(buffer, passwd_len);
574 		if (rc)
575 			goto cleanup;
576 
577 		/* Copy as many bytes as were received or until bytes requested */
578 		for (i = 0; (i < passwd_len) &&
579 			    (bytes_copied < passwd_len); i++) {
580 
581 			/* Skip zero bytes */
582 			if (buffer[i] == 0)
583 				continue;
584 			passwd[bytes_copied] = buffer[i];
585 			bytes_copied++;
586 		}
587 	}
588 cleanup:
589 	free(buffer);
590 	return rc;
591 }
592 
593 /*
594  * @brief This command allows the authorization secret for a hierarchy to be
595  * changed.
596  */
tss_set_platform_auth(void)597 int tss_set_platform_auth(void)
598 {
599 	HierarchyChangeAuth_In *in =  NULL;
600 	TSS_CONTEXT *context = NULL;
601 	TPM_RC rc = OPAL_SUCCESS;
602 	char *key_passwd = NULL;
603 
604 	in = zalloc(sizeof(HierarchyChangeAuth_In));
605 	if (!in) {
606 		rc = OPAL_NO_MEM;
607 		goto cleanup;
608 	}
609 
610 	key_passwd = zalloc(TSS_AUTH_PASSWD_LEN + 1);
611 	if (!key_passwd) {
612 		rc = OPAL_NO_MEM;
613 		goto cleanup;
614 	}
615 
616 	rc = TSS_Create(&context);
617 	if (rc) {
618 		tss_error_trace("tss_set_platform_auth", rc);
619 		rc = OPAL_NO_MEM;
620 		goto cleanup;
621 	}
622 
623 	rc = generate_random_passwd(key_passwd,	TSS_AUTH_PASSWD_LEN);
624 	if (rc) {
625 		tss_error_trace("Failed to generate the auth password", rc);
626 		goto cleanup;
627 	}
628 	key_passwd[TSS_AUTH_PASSWD_LEN] = 0;
629 
630 	in->authHandle = TPM_RH_PLATFORM;
631 	rc = TSS_TPM2B_StringCopy(&in->newAuth.b, key_passwd,
632 				  sizeof(in->newAuth.t.buffer));
633 	if (rc) {
634 		tss_error_trace("tss_set_platform_auth", rc);
635 		goto cleanup;
636 	}
637 
638 	rc = TSS_Execute(context,
639 			 NULL,
640 			 (COMMAND_PARAMETERS *)in,
641 			 NULL,
642 			 TPM_CC_HierarchyChangeAuth,
643 			 TPM_RS_PW, NULL, 0,
644 			 TPM_RH_NULL, NULL, 0);
645 	if (rc)
646 		tss_error_trace("tss_set_platform_auth", rc);
647 
648 cleanup:
649 	TSS_Delete(context);
650 	free(in);
651 	/* explicitly clean up password from memory to avoid some kind of
652 	* exploitation.
653 	*/
654 	memset(key_passwd, 0, TSS_AUTH_PASSWD_LEN + 1);
655 	free(key_passwd);
656 	return rc;
657 }
658 
659 /*
660  * @brief returns a list of defined NV indices
661  * @param pcr_handle		The PCR to be extended
662  * @param alg_hashes		A pointer to an array of hash algorithms, each
663  * 				one used to extend its respective PCR bank.
664  * @param alg_hash_count	The length of alg hashes array
665  */
tss_get_defined_nv_indices(TPMI_RH_NV_INDEX ** indices,size_t * count)666 int tss_get_defined_nv_indices(TPMI_RH_NV_INDEX **indices, size_t *count)
667 {
668 	TSS_CONTEXT *context = NULL;
669 	GetCapability_In *in = NULL;
670 	GetCapability_Out *out = NULL;
671 	uint32_t rc = OPAL_SUCCESS;
672 	TPML_HANDLE *handles;
673 
674 	in = zalloc(sizeof(GetCapability_In));
675 	if (!in) {
676 	        rc = OPAL_NO_MEM;
677 		goto cleanup;
678 	}
679 
680 	out = zalloc(sizeof(GetCapability_Out));
681 	if (!out) {
682 		rc = OPAL_NO_MEM;
683 		goto cleanup;
684 	}
685 
686 	rc = TSS_Create(&context);
687 	if (rc) {
688 		tss_error_trace("tss_check_nv_index", rc);
689 		rc = OPAL_NO_MEM;
690 		goto cleanup;
691 	}
692 
693 	in->capability = 1;
694 	in->property = 0x01000000;
695 	in->propertyCount = 64;
696 
697 	rc = TSS_Execute(context,
698 			 (RESPONSE_PARAMETERS *) out,
699 			 (COMMAND_PARAMETERS *) in,
700 			 NULL,
701 			 TPM_CC_GetCapability,
702 			 TPM_RH_NULL, NULL, 0);
703 	if (rc) {
704 		tss_error_trace("tss_check_nv_index", rc);
705 		goto cleanup;
706 	}
707 
708 	handles = (TPML_HANDLE *) &out->capabilityData.data;
709 	*count = handles->count;
710 	*indices = malloc(*count * sizeof(TPMI_RH_NV_INDEX));
711 	if (!indices) {
712 		rc = OPAL_NO_MEM;
713 		goto cleanup;
714 	}
715 
716 	memcpy(*indices, handles->handle, *count * sizeof(TPMI_RH_NV_INDEX));
717 
718 cleanup:
719 	TSS_Delete(context);
720 	free(in);
721 	free(out);
722 	return rc;
723 }
724 
725 
tss_nv_undefine_space(TPMI_RH_NV_INDEX nv_index)726 int tss_nv_undefine_space(TPMI_RH_NV_INDEX nv_index)
727 {
728 	int rc;
729 	TSS_CONTEXT *context = NULL;
730 	NV_UndefineSpace_In in;
731 
732 	rc = TSS_Create(&context);
733 	if (rc) {
734 		tss_error_trace("tss_check_nv_undefine_index", rc);
735 		rc = OPAL_NO_MEM;
736 		return rc;
737 	}
738 
739 	in.authHandle = TPM_RH_PLATFORM;
740 	in.nvIndex = nv_index;
741 
742 	rc = TSS_Execute(context, NULL,
743 			 (COMMAND_PARAMETERS *) &in,
744 			 NULL,
745 			 TPM_CC_NV_UndefineSpace,
746 			 TPM_RS_PW, NULL, 0,
747 			 TPM_RH_NULL, NULL, 0);
748 	if (rc)
749 		tss_error_trace("tss_check_nv_index", rc);
750 
751 	TSS_Delete(context);
752 	return rc;
753 }
754