xref: /aosp_15_r20/external/tpm2-tss/src/tss2-fapi/api/Fapi_GetPlatformCertificates.c (revision 758e9fba6fc9adbf15340f70c73baee7b168b1c9)
1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*******************************************************************************
3  * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
4  * All rights reserved.
5  ******************************************************************************/
6 
7 #ifdef HAVE_CONFIG_H
8 #include <config.h>
9 #endif
10 
11 #include <stdlib.h>
12 #include <errno.h>
13 #include <unistd.h>
14 #include <errno.h>
15 #include <string.h>
16 
17 #include "tss2_fapi.h"
18 #include "fapi_int.h"
19 #include "fapi_util.h"
20 #include "tss2_esys.h"
21 #define LOGMODULE fapi
22 #include "util/log.h"
23 #include "util/aux_util.h"
24 
25 /** One-Call function for Fapi_GetPlatformCertificates
26  *
27  * Platform certificates for TPM 2.0 can consist not only of a single certificate
28  * but a series of so-called delta certificates.
29  * This function returns the set of Platform certificates concatenated in
30  * a continuous buffer.
31  *
32  * @param[in,out] context The FAPI_CONTEXT
33  * @param[out] certificates The platform certificates
34  * @param[out] certificatesSize The size of the buffer with the certificates.
35  *             May be NULL
36  *
37  * @retval TSS2_RC_SUCCESS: if the function call was a success.
38  * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or certificates is NULL.
39  * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
40  * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
41  *         operation already pending.
42  * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
43  * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for internal
44  *         operations or return parameters.
45  * @retval TSS2_FAPI_RC_NO_TPM if FAPI was initialized in no-TPM-mode via its
46  *         config file.
47  * @retval TSS2_FAPI_RC_NO_CERT if an error did occur during certificate downloading.
48  * @retval TSS2_FAPI_RC_TRY_AGAIN if an I/O operation is not finished yet and
49  *         this function needs to be called again.
50  * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback
51  *         is not set.
52  * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
53  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
54  * @retval TSS2_FAPI_RC_POLICY_UNKNOWN if policy search for a certain policy digest
55  *         was not successful.
56  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
57  */
58 TSS2_RC
Fapi_GetPlatformCertificates(FAPI_CONTEXT * context,uint8_t ** certificates,size_t * certificatesSize)59 Fapi_GetPlatformCertificates(
60     FAPI_CONTEXT *context,
61     uint8_t **certificates,
62     size_t *certificatesSize)
63 {
64     LOG_TRACE("called for context:%p", context);
65 
66     TSS2_RC r, r2;
67 
68     /* Check for NULL parameters */
69     check_not_null(context);
70     check_not_null(certificates);
71 
72     /* Check whether TCTI and ESYS are initialized */
73     return_if_null(context->esys, "Command can't be executed in none TPM mode.",
74                    TSS2_FAPI_RC_NO_TPM);
75 
76     /* If the async state automata of FAPI shall be tested, then we must not set
77        the timeouts of ESYS to blocking mode.
78        During testing, the mssim tcti will ensure multiple re-invocations.
79        Usually however the synchronous invocations of FAPI shall instruct ESYS
80        to block until a result is available. */
81 #ifndef TEST_FAPI_ASYNC
82     r = Esys_SetTimeout(context->esys, TSS2_TCTI_TIMEOUT_BLOCK);
83     return_if_error_reset_state(r, "Set Timeout to blocking");
84 #endif /* TEST_FAPI_ASYNC */
85 
86     r = Fapi_GetPlatformCertificates_Async(context);
87     return_if_error_reset_state(r, "Path_PlatformGetCertificate");
88 
89     do {
90         /* We wait for file I/O to be ready if the FAPI state automata
91            are in a file I/O state. */
92         r = ifapi_io_poll(&context->io);
93         return_if_error(r, "Something went wrong with IO polling");
94 
95         /* Repeatedly call the finish function, until FAPI has transitioned
96            through all execution stages / states of this invocation. */
97         r = Fapi_GetPlatformCertificates_Finish(context, certificates,
98                 certificatesSize);
99     } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN);
100 
101     /* Reset the ESYS timeout to non-blocking, immediate response. */
102     r2 = Esys_SetTimeout(context->esys, 0);
103     return_if_error(r2, "Set Timeout to non-blocking");
104 
105     return_if_error_reset_state(r, "Path_PlatformGetCertificate");
106 
107     LOG_TRACE("finished");
108     return TSS2_RC_SUCCESS;
109 }
110 
111 /** Asynchronous function for Fapi_GetPlatformCertificates
112  *
113  * Platform certificates for TPM 2.0 can consist not only of a single certificate
114  * but a series of so-called delta certificates.
115  * This function returns the set of Platform certificates concatenated in
116  * a continuous buffer.
117  *
118  * Call Fapi_GetPlatformCertificates_Finish to finish the execution of this
119  * command.
120  *
121  * @param[in,out] context The FAPI_CONTEXT
122  *
123  * @retval TSS2_RC_SUCCESS: if the function call was a success.
124  * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context is NULL.
125  * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
126  * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
127  *         operation already pending.
128  * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
129  * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for internal
130  *         operations or return parameters.
131  * @retval TSS2_FAPI_RC_NO_TPM if FAPI was initialized in no-TPM-mode via its
132  *         config file.
133  */
134 TSS2_RC
Fapi_GetPlatformCertificates_Async(FAPI_CONTEXT * context)135 Fapi_GetPlatformCertificates_Async(
136     FAPI_CONTEXT *context)
137 {
138     LOG_TRACE("called for context:%p", context);
139 
140     TSS2_RC r;
141 
142     /* Check for NULL parameters */
143     check_not_null(context);
144 
145     /* Reset all context-internal session state information. */
146     r = ifapi_session_init(context);
147     return_if_error(r, "Initialize Fapi_GetPlatformCertificates");
148 
149     /* Initialize the context state for this operation. */
150     context->state = GET_PLATFORM_CERTIFICATE;
151 
152     LOG_TRACE("finished");
153     return TSS2_RC_SUCCESS;
154 }
155 
156 /** Asynchronous finish function for Fapi_GetPlatformCertificates
157  *
158  * This function should be called after a previous
159  * Fapi_GetPlatformCertificates_Async.
160  *
161  * @param[in,out] context The FAPI_CONTEXT
162  * @param[out] certificates The platform certificates
163  * @param[out] certificatesSize The size of the buffer with the certificates.
164  *             May be NULL
165  *
166  * @retval TSS2_RC_SUCCESS: if the function call was a success.
167  * @retval TSS2_FAPI_RC_BAD_REFERENCE: if context or certificates is NULL.
168  * @retval TSS2_FAPI_RC_BAD_CONTEXT: if context corruption is detected.
169  * @retval TSS2_FAPI_RC_BAD_SEQUENCE: if the context has an asynchronous
170  *         operation already pending.
171  * @retval TSS2_FAPI_RC_IO_ERROR: if the data cannot be saved.
172  * @retval TSS2_FAPI_RC_MEMORY: if the FAPI cannot allocate enough memory for
173  *         internal operations or return parameters.
174  * @retval TSS2_FAPI_RC_TRY_AGAIN: if the asynchronous operation is not yet
175  *         complete. Call this function again later.
176  * @retval TSS2_FAPI_RC_NO_CERT if an error did occur during certificate downloading.
177  * @retval TSS2_FAPI_RC_AUTHORIZATION_UNKNOWN if a required authorization callback
178  *         is not set.
179  * @retval TSS2_FAPI_RC_AUTHORIZATION_FAILED if the authorization attempt fails.
180  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
181  * @retval TSS2_FAPI_RC_POLICY_UNKNOWN if policy search for a certain policy digest
182  *         was not successful.
183  * @retval TSS2_ESYS_RC_* possible error codes of ESAPI.
184  */
185 TSS2_RC
Fapi_GetPlatformCertificates_Finish(FAPI_CONTEXT * context,uint8_t ** certificates,size_t * certificatesSize)186 Fapi_GetPlatformCertificates_Finish(
187     FAPI_CONTEXT *context,
188     uint8_t **certificates,
189     size_t *certificatesSize)
190 {
191     LOG_TRACE("called for context:%p", context);
192 
193     NODE_OBJECT_T *cert_list = NULL;
194     TSS2_RC r;
195 
196     /* Check for NULL parameters */
197     check_not_null(context);
198     check_not_null(certificates);
199     *certificates = NULL;
200 
201     switch (context->state) {
202         statecase(context->state, GET_PLATFORM_CERTIFICATE);
203             /* Retrieve the certificates from the TPM's NV space. */
204             r = ifapi_get_certificates(context, MIN_PLATFORM_CERT_HANDLE,
205                                        MAX_PLATFORM_CERT_HANDLE,
206                                        &cert_list);
207             return_try_again(r);
208             goto_if_error(r, "Get certificates.", error);
209 
210             if (cert_list) {
211                 /* Concatenate the found certificates */
212                 size_t size;
213                 NODE_OBJECT_T *cert = cert_list;
214                 size = 0;
215                 while (cert) {
216                     size += cert->size;
217                     cert = cert->next;
218                 }
219                 if (certificatesSize)
220                     *certificatesSize = size;
221                 *certificates = malloc(size);
222                 goto_if_null2(*certificates, "Out of memory.",
223                         r, TSS2_FAPI_RC_MEMORY, error);
224 
225                 cert = cert_list;
226                 size = 0;
227                 while (cert) {
228                     memcpy(&cert[size], cert->object, cert->size);
229                     size += cert->size;
230                     cert = cert->next;
231                 }
232             } else {
233                 if (certificatesSize)
234                     *certificatesSize = 0;
235                 goto_error(r, TSS2_FAPI_RC_NO_CERT,
236                         "No platform certificates available.", error);
237             }
238             break;
239         statecasedefault(context->state);
240     }
241 
242     /* Cleanup any intermediate results and state stored in the context. */
243     ifapi_free_object_list(cert_list);
244     SAFE_FREE(context->cmd.Provision.capabilityData);
245     context->state =  _FAPI_STATE_INIT;
246     LOG_TRACE("finished");
247     return TSS2_RC_SUCCESS;
248 
249 error:
250     /* Cleanup any intermediate results and state stored in the context. */
251     context->state =  _FAPI_STATE_INIT;
252     ifapi_free_object_list(cert_list);
253     SAFE_FREE(context->cmd.Provision.capabilityData);
254     SAFE_FREE(*certificates);
255     return r;
256 }
257