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