xref: /aosp_15_r20/external/tpm2-tss/src/tss2-fapi/ifapi_helpers.c (revision 758e9fba6fc9adbf15340f70c73baee7b168b1c9)
1*758e9fbaSOystein Eftevaag /* SPDX-License-Identifier: BSD-2-Clause */
2*758e9fbaSOystein Eftevaag /*******************************************************************************
3*758e9fbaSOystein Eftevaag  * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
4*758e9fbaSOystein Eftevaag  * All rights reserved.
5*758e9fbaSOystein Eftevaag  *******************************************************************************/
6*758e9fbaSOystein Eftevaag 
7*758e9fbaSOystein Eftevaag #ifdef HAVE_CONFIG_H
8*758e9fbaSOystein Eftevaag #include <config.h>
9*758e9fbaSOystein Eftevaag #endif
10*758e9fbaSOystein Eftevaag 
11*758e9fbaSOystein Eftevaag #include <stdio.h>
12*758e9fbaSOystein Eftevaag #include <string.h>
13*758e9fbaSOystein Eftevaag #include <stdarg.h>
14*758e9fbaSOystein Eftevaag #include <sys/types.h>
15*758e9fbaSOystein Eftevaag #include <sys/stat.h>
16*758e9fbaSOystein Eftevaag #include <stdlib.h>
17*758e9fbaSOystein Eftevaag #include <stdio.h>
18*758e9fbaSOystein Eftevaag #include <unistd.h>
19*758e9fbaSOystein Eftevaag #include <ctype.h>
20*758e9fbaSOystein Eftevaag #include <dirent.h>
21*758e9fbaSOystein Eftevaag #include <curl/curl.h>
22*758e9fbaSOystein Eftevaag 
23*758e9fbaSOystein Eftevaag #include "tss2_mu.h"
24*758e9fbaSOystein Eftevaag #include "fapi_util.h"
25*758e9fbaSOystein Eftevaag #include "fapi_policy.h"
26*758e9fbaSOystein Eftevaag #include "fapi_crypto.h"
27*758e9fbaSOystein Eftevaag #include "ifapi_helpers.h"
28*758e9fbaSOystein Eftevaag #include "ifapi_json_serialize.h"
29*758e9fbaSOystein Eftevaag #include "ifapi_json_deserialize.h"
30*758e9fbaSOystein Eftevaag #include "tpm_json_deserialize.h"
31*758e9fbaSOystein Eftevaag #define LOGMODULE fapi
32*758e9fbaSOystein Eftevaag #include "util/log.h"
33*758e9fbaSOystein Eftevaag #include "util/aux_util.h"
34*758e9fbaSOystein Eftevaag 
35*758e9fbaSOystein Eftevaag /** Create template for key creation based on type flags.
36*758e9fbaSOystein Eftevaag  *
37*758e9fbaSOystein Eftevaag  * Based on passed flags the TPM2B_PUBLIC data which is used for key
38*758e9fbaSOystein Eftevaag  * creation will be adapted.
39*758e9fbaSOystein Eftevaag  *
40*758e9fbaSOystein Eftevaag  * @param[in] type The flags describing the key type.
41*758e9fbaSOystein Eftevaag  * @param[in] policy The flag whether a policy is used.
42*758e9fbaSOystein Eftevaag  * @param[out] template The template including the TPM2B_PUBLIC which will
43*758e9fbaSOystein Eftevaag  *             be used for key creation.
44*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS if the template can be generated.
45*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE If an invalid combination of flags was used.
46*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
47*758e9fbaSOystein Eftevaag  */
48*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_set_key_flags(const char * type,bool policy,IFAPI_KEY_TEMPLATE * template)49*758e9fbaSOystein Eftevaag ifapi_set_key_flags(const char *type, bool policy, IFAPI_KEY_TEMPLATE *template)
50*758e9fbaSOystein Eftevaag {
51*758e9fbaSOystein Eftevaag     TSS2_RC r = TSS2_RC_SUCCESS;
52*758e9fbaSOystein Eftevaag     char *type_dup = NULL;
53*758e9fbaSOystein Eftevaag     TPMA_OBJECT attributes = 0;
54*758e9fbaSOystein Eftevaag     UINT32 handle;
55*758e9fbaSOystein Eftevaag     int pos;
56*758e9fbaSOystein Eftevaag     bool exportable = false;
57*758e9fbaSOystein Eftevaag 
58*758e9fbaSOystein Eftevaag     memset(template, 0, sizeof(IFAPI_KEY_TEMPLATE));
59*758e9fbaSOystein Eftevaag     type_dup = strdup(type);
60*758e9fbaSOystein Eftevaag     return_if_null(type_dup, "Out of memory.", TSS2_FAPI_RC_MEMORY);
61*758e9fbaSOystein Eftevaag 
62*758e9fbaSOystein Eftevaag     char *flag = strtok(type_dup, ", ");
63*758e9fbaSOystein Eftevaag 
64*758e9fbaSOystein Eftevaag     /* The default store will be the user directory */
65*758e9fbaSOystein Eftevaag     template->system = TPM2_NO;
66*758e9fbaSOystein Eftevaag 
67*758e9fbaSOystein Eftevaag     /* Loop over all comma or space separated flags */
68*758e9fbaSOystein Eftevaag     while (flag != NULL) {
69*758e9fbaSOystein Eftevaag         if (strcasecmp(flag, "system") == 0) {
70*758e9fbaSOystein Eftevaag             template->system = TPM2_YES;
71*758e9fbaSOystein Eftevaag         } else if (strcasecmp(flag, "sign") == 0) {
72*758e9fbaSOystein Eftevaag             attributes |= TPMA_OBJECT_SIGN_ENCRYPT;
73*758e9fbaSOystein Eftevaag         } else if (strcasecmp(flag, "decrypt") == 0) {
74*758e9fbaSOystein Eftevaag             attributes |= TPMA_OBJECT_DECRYPT;
75*758e9fbaSOystein Eftevaag         } else if (strcasecmp(flag, "restricted") == 0) {
76*758e9fbaSOystein Eftevaag             attributes |= TPMA_OBJECT_RESTRICTED;
77*758e9fbaSOystein Eftevaag         } else if (strcasecmp(flag, "exportable") == 0) {
78*758e9fbaSOystein Eftevaag             /* TPMA_OBJECT_ENCRYPTEDDUPLICATION will not be set because no inner
79*758e9fbaSOystein Eftevaag                symmetric encryption will be used */
80*758e9fbaSOystein Eftevaag             exportable = true;
81*758e9fbaSOystein Eftevaag         } else if (strcasecmp(flag, "noda") == 0) {
82*758e9fbaSOystein Eftevaag             attributes |= TPMA_OBJECT_NODA;
83*758e9fbaSOystein Eftevaag         } else if (strncmp(flag, "0x", 2) == 0) {
84*758e9fbaSOystein Eftevaag             sscanf(&flag[2], "%"SCNx32 "%n", &handle, &pos);
85*758e9fbaSOystein Eftevaag             if ((size_t)pos != strlen(flag) - 2) {
86*758e9fbaSOystein Eftevaag                 goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Invalid flag: %s",
87*758e9fbaSOystein Eftevaag                            error, flag);
88*758e9fbaSOystein Eftevaag             }
89*758e9fbaSOystein Eftevaag             template->persistent_handle = handle;
90*758e9fbaSOystein Eftevaag             template->persistent = TPM2_YES;
91*758e9fbaSOystein Eftevaag         } else {
92*758e9fbaSOystein Eftevaag             goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Invalid flag: %s",
93*758e9fbaSOystein Eftevaag                        error, flag);
94*758e9fbaSOystein Eftevaag         }
95*758e9fbaSOystein Eftevaag         flag = strtok(NULL, " ,");
96*758e9fbaSOystein Eftevaag     }
97*758e9fbaSOystein Eftevaag     if (exportable) {
98*758e9fbaSOystein Eftevaag         /* Clear flags preventing duplication */
99*758e9fbaSOystein Eftevaag         attributes &= ~TPMA_OBJECT_FIXEDTPM;
100*758e9fbaSOystein Eftevaag         attributes &= ~TPMA_OBJECT_FIXEDPARENT;
101*758e9fbaSOystein Eftevaag     } else {
102*758e9fbaSOystein Eftevaag         attributes |= TPMA_OBJECT_FIXEDTPM;
103*758e9fbaSOystein Eftevaag         attributes |= TPMA_OBJECT_FIXEDPARENT;
104*758e9fbaSOystein Eftevaag     }
105*758e9fbaSOystein Eftevaag     /* Set default flags */
106*758e9fbaSOystein Eftevaag     attributes |= TPMA_OBJECT_SENSITIVEDATAORIGIN;
107*758e9fbaSOystein Eftevaag     if (!policy)
108*758e9fbaSOystein Eftevaag         attributes |= TPMA_OBJECT_USERWITHAUTH;
109*758e9fbaSOystein Eftevaag     else
110*758e9fbaSOystein Eftevaag         attributes |= TPMA_OBJECT_ADMINWITHPOLICY;
111*758e9fbaSOystein Eftevaag 
112*758e9fbaSOystein Eftevaag     /* Check whether flags are appropriate */
113*758e9fbaSOystein Eftevaag     if (attributes & TPMA_OBJECT_RESTRICTED &&
114*758e9fbaSOystein Eftevaag             attributes & TPMA_OBJECT_SIGN_ENCRYPT &&
115*758e9fbaSOystein Eftevaag             attributes & TPMA_OBJECT_DECRYPT) {
116*758e9fbaSOystein Eftevaag         goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
117*758e9fbaSOystein Eftevaag                    "Exactly either sign or decrypt must be set.",
118*758e9fbaSOystein Eftevaag                    error);
119*758e9fbaSOystein Eftevaag     }
120*758e9fbaSOystein Eftevaag 
121*758e9fbaSOystein Eftevaag     template->public.publicArea.objectAttributes = attributes;
122*758e9fbaSOystein Eftevaag     SAFE_FREE(type_dup);
123*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
124*758e9fbaSOystein Eftevaag 
125*758e9fbaSOystein Eftevaag error:
126*758e9fbaSOystein Eftevaag     SAFE_FREE(type_dup);
127*758e9fbaSOystein Eftevaag     return r;
128*758e9fbaSOystein Eftevaag }
129*758e9fbaSOystein Eftevaag 
130*758e9fbaSOystein Eftevaag /** Create template for nv object  creation based on type flags.
131*758e9fbaSOystein Eftevaag  *
132*758e9fbaSOystein Eftevaag  * Based on passed flags the TPM2B_NV_PUBLIC data which is used for key
133*758e9fbaSOystein Eftevaag  * creation will be adapted.
134*758e9fbaSOystein Eftevaag  * @param[in] type The flags describing the nv object type.
135*758e9fbaSOystein Eftevaag  * @param[in] policy The flag whether a policy is used.
136*758e9fbaSOystein Eftevaag  * @param[out] template The template including the TPM2B_NV_PUBLIC which will
137*758e9fbaSOystein Eftevaag  *             be used for nv object creation.
138*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS if the template can be generated.
139*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE If an invalid combination of flags was used.
140*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
141*758e9fbaSOystein Eftevaag  */
142*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_set_nv_flags(const char * type,IFAPI_NV_TEMPLATE * template,const char * policy)143*758e9fbaSOystein Eftevaag ifapi_set_nv_flags(const char *type, IFAPI_NV_TEMPLATE *template,
144*758e9fbaSOystein Eftevaag                    const char *policy)
145*758e9fbaSOystein Eftevaag {
146*758e9fbaSOystein Eftevaag     TSS2_RC r = TSS2_RC_SUCCESS;
147*758e9fbaSOystein Eftevaag     char *type_dup = NULL;
148*758e9fbaSOystein Eftevaag     TPMA_NV attributes = 0;
149*758e9fbaSOystein Eftevaag     UINT32 handle;
150*758e9fbaSOystein Eftevaag     int pos;
151*758e9fbaSOystein Eftevaag     UINT32 size = 0;
152*758e9fbaSOystein Eftevaag     size_t type_count = 0;
153*758e9fbaSOystein Eftevaag 
154*758e9fbaSOystein Eftevaag     memset(template, 0, sizeof(IFAPI_NV_TEMPLATE));
155*758e9fbaSOystein Eftevaag     type_dup = strdup(type);
156*758e9fbaSOystein Eftevaag     return_if_null(type_dup, "Out of memory.", TSS2_FAPI_RC_MEMORY);
157*758e9fbaSOystein Eftevaag     /* The default store will be the user directory */
158*758e9fbaSOystein Eftevaag     template->system = TPM2_NO;
159*758e9fbaSOystein Eftevaag 
160*758e9fbaSOystein Eftevaag     char *flag = strtok(type_dup, ", ");
161*758e9fbaSOystein Eftevaag 
162*758e9fbaSOystein Eftevaag     /* Loop over all comma or space separated flags */
163*758e9fbaSOystein Eftevaag     while (flag != NULL) {
164*758e9fbaSOystein Eftevaag         if (strcasecmp(flag, "system") == 0) {
165*758e9fbaSOystein Eftevaag             template->system = TPM2_YES;
166*758e9fbaSOystein Eftevaag         } else if (strcasecmp(flag, "bitfield") == 0) {
167*758e9fbaSOystein Eftevaag             attributes |= TPM2_NT_BITS << TPMA_NV_TPM2_NT_SHIFT;
168*758e9fbaSOystein Eftevaag             type_count += 1;
169*758e9fbaSOystein Eftevaag         } else if (strcasecmp(flag, "counter") == 0) {
170*758e9fbaSOystein Eftevaag             attributes |= TPM2_NT_COUNTER << TPMA_NV_TPM2_NT_SHIFT;
171*758e9fbaSOystein Eftevaag             type_count += 1;
172*758e9fbaSOystein Eftevaag         } else if (strcasecmp(flag, "pcr") == 0) {
173*758e9fbaSOystein Eftevaag             attributes |= TPM2_NT_EXTEND << TPMA_NV_TPM2_NT_SHIFT;
174*758e9fbaSOystein Eftevaag             type_count += 1;
175*758e9fbaSOystein Eftevaag         } else if (strcasecmp(flag, "noda") == 0) {
176*758e9fbaSOystein Eftevaag             attributes |= TPMA_NV_NO_DA;
177*758e9fbaSOystein Eftevaag         } else if (strncmp(flag, "0x", 2) == 0) {
178*758e9fbaSOystein Eftevaag             sscanf(&flag[2], "%"SCNx32 "%n", &handle, &pos);
179*758e9fbaSOystein Eftevaag             if ((size_t)pos != strlen(flag) - 2) {
180*758e9fbaSOystein Eftevaag                 goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Invalid flag: %s",
181*758e9fbaSOystein Eftevaag                            error, flag);
182*758e9fbaSOystein Eftevaag             }
183*758e9fbaSOystein Eftevaag             template->public.nvIndex = handle;
184*758e9fbaSOystein Eftevaag         } else {
185*758e9fbaSOystein Eftevaag             goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Invalid flag: %s",
186*758e9fbaSOystein Eftevaag                        error, flag);
187*758e9fbaSOystein Eftevaag         }
188*758e9fbaSOystein Eftevaag         flag = strtok(NULL, " ,");
189*758e9fbaSOystein Eftevaag     }
190*758e9fbaSOystein Eftevaag     if (type_count > 1) {
191*758e9fbaSOystein Eftevaag         goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
192*758e9fbaSOystein Eftevaag                    "Only one type of NV object can be set.", error);
193*758e9fbaSOystein Eftevaag     }
194*758e9fbaSOystein Eftevaag     if (type_count == 0) {
195*758e9fbaSOystein Eftevaag         /* Normal NV space will be defined */
196*758e9fbaSOystein Eftevaag         attributes |= TPM2_NT_ORDINARY << TPMA_NV_TPM2_NT_SHIFT;
197*758e9fbaSOystein Eftevaag         if (size == 0)
198*758e9fbaSOystein Eftevaag             size = 64;
199*758e9fbaSOystein Eftevaag     }
200*758e9fbaSOystein Eftevaag     /* If type extend is used the size will be set during the merging of the crypto
201*758e9fbaSOystein Eftevaag        profile depending on the nameHashAlg stored in the profile.
202*758e9fbaSOystein Eftevaag        The size of counter and bitfield will be determined by the TPM. */
203*758e9fbaSOystein Eftevaag 
204*758e9fbaSOystein Eftevaag     if (policy && strlen(policy) > 0) {
205*758e9fbaSOystein Eftevaag         attributes |= TPMA_NV_POLICYWRITE;
206*758e9fbaSOystein Eftevaag         attributes |= TPMA_NV_POLICYREAD;
207*758e9fbaSOystein Eftevaag     } else {
208*758e9fbaSOystein Eftevaag         attributes |= TPMA_NV_AUTHREAD;
209*758e9fbaSOystein Eftevaag         attributes |= TPMA_NV_AUTHWRITE;
210*758e9fbaSOystein Eftevaag     }
211*758e9fbaSOystein Eftevaag 
212*758e9fbaSOystein Eftevaag     attributes |= TPMA_NV_READ_STCLEAR;
213*758e9fbaSOystein Eftevaag     attributes |= TPMA_NV_WRITE_STCLEAR;
214*758e9fbaSOystein Eftevaag     template->public.attributes = attributes;
215*758e9fbaSOystein Eftevaag     template->hierarchy = TPM2_RH_OWNER;
216*758e9fbaSOystein Eftevaag     template->public.dataSize = size;
217*758e9fbaSOystein Eftevaag 
218*758e9fbaSOystein Eftevaag     SAFE_FREE(type_dup);
219*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
220*758e9fbaSOystein Eftevaag 
221*758e9fbaSOystein Eftevaag error:
222*758e9fbaSOystein Eftevaag     SAFE_FREE(type_dup);
223*758e9fbaSOystein Eftevaag     return r;
224*758e9fbaSOystein Eftevaag }
225*758e9fbaSOystein Eftevaag 
226*758e9fbaSOystein Eftevaag /**  Determine whether path is of certain type.
227*758e9fbaSOystein Eftevaag  *
228*758e9fbaSOystein Eftevaag  * @param[in] path The path to be checked.
229*758e9fbaSOystein Eftevaag  * @param[in] type sub-string at the beginning of the path to be checked.
230*758e9fbaSOystein Eftevaag  *
231*758e9fbaSOystein Eftevaag  * @retval true if the path name starts with type.
232*758e9fbaSOystein Eftevaag  * @retval false if not.
233*758e9fbaSOystein Eftevaag  */
234*758e9fbaSOystein Eftevaag bool
ifapi_path_type_p(const char * path,const char * type)235*758e9fbaSOystein Eftevaag ifapi_path_type_p(const char *path, const char *type)
236*758e9fbaSOystein Eftevaag {
237*758e9fbaSOystein Eftevaag     size_t pos = 0;
238*758e9fbaSOystein Eftevaag     char *end;
239*758e9fbaSOystein Eftevaag     int end_pos;
240*758e9fbaSOystein Eftevaag 
241*758e9fbaSOystein Eftevaag     if (strncmp("/", path, 1) == 0)
242*758e9fbaSOystein Eftevaag         pos = 1;
243*758e9fbaSOystein Eftevaag     if (strcmp(&path[pos], type) == 0)
244*758e9fbaSOystein Eftevaag         return true;
245*758e9fbaSOystein Eftevaag 
246*758e9fbaSOystein Eftevaag     end = strchr(&path[pos], IFAPI_FILE_DELIM_CHAR);
247*758e9fbaSOystein Eftevaag     if (!end)
248*758e9fbaSOystein Eftevaag         /* No meaningful path */
249*758e9fbaSOystein Eftevaag         return false;
250*758e9fbaSOystein Eftevaag     end_pos = (int)(end - path);
251*758e9fbaSOystein Eftevaag 
252*758e9fbaSOystein Eftevaag     /* Check sub-string and following delimiter. */
253*758e9fbaSOystein Eftevaag     if (strlen(path) - pos > 3 &&
254*758e9fbaSOystein Eftevaag             strncasecmp(type, &path[pos], strlen(type)) == 0 && end &&
255*758e9fbaSOystein Eftevaag             strncmp(IFAPI_FILE_DELIM, &path[end_pos], 1) == 0)
256*758e9fbaSOystein Eftevaag         return true;
257*758e9fbaSOystein Eftevaag     return false;
258*758e9fbaSOystein Eftevaag }
259*758e9fbaSOystein Eftevaag 
260*758e9fbaSOystein Eftevaag /** Get ESYS handle for a hierarchy path.
261*758e9fbaSOystein Eftevaag  *
262*758e9fbaSOystein Eftevaag  * @param[in] path The path to be checked.
263*758e9fbaSOystein Eftevaag  *
264*758e9fbaSOystein Eftevaag  * @retval The ESAPI handle for the hierarchy defined in path.
265*758e9fbaSOystein Eftevaag  * @retval 0 if not handle can be assigned.
266*758e9fbaSOystein Eftevaag  */
267*758e9fbaSOystein Eftevaag ESYS_TR
ifapi_get_hierary_handle(const char * path)268*758e9fbaSOystein Eftevaag ifapi_get_hierary_handle(const char *path)
269*758e9fbaSOystein Eftevaag {
270*758e9fbaSOystein Eftevaag     int pos = 0;
271*758e9fbaSOystein Eftevaag 
272*758e9fbaSOystein Eftevaag     if (strncmp("/", path, 1) == 0)
273*758e9fbaSOystein Eftevaag         pos = 1;
274*758e9fbaSOystein Eftevaag     if (strcmp(&path[pos], "HE") == 0) {
275*758e9fbaSOystein Eftevaag         return ESYS_TR_RH_ENDORSEMENT;
276*758e9fbaSOystein Eftevaag     }
277*758e9fbaSOystein Eftevaag     if (strcmp(&path[pos], "HS") == 0) {
278*758e9fbaSOystein Eftevaag         return ESYS_TR_RH_OWNER;
279*758e9fbaSOystein Eftevaag     }
280*758e9fbaSOystein Eftevaag     if (strcmp(&path[pos], "LOCKOUT") == 0) {
281*758e9fbaSOystein Eftevaag         return ESYS_TR_RH_LOCKOUT;
282*758e9fbaSOystein Eftevaag     }
283*758e9fbaSOystein Eftevaag     return 0;
284*758e9fbaSOystein Eftevaag }
285*758e9fbaSOystein Eftevaag 
286*758e9fbaSOystein Eftevaag /** Determine whether path describes a hierarchy object.
287*758e9fbaSOystein Eftevaag  *
288*758e9fbaSOystein Eftevaag  * It will be checked whether the path describes a hierarch. A key path
289*758e9fbaSOystein Eftevaag  * with a hierarchy will not deliver true.
290*758e9fbaSOystein Eftevaag  *
291*758e9fbaSOystein Eftevaag  * @param[in] path The path to be checked.
292*758e9fbaSOystein Eftevaag  *
293*758e9fbaSOystein Eftevaag  * @retval true if the path describes a hierarchy.
294*758e9fbaSOystein Eftevaag  * @retval false if not.
295*758e9fbaSOystein Eftevaag  */
296*758e9fbaSOystein Eftevaag bool
ifapi_hierarchy_path_p(const char * path)297*758e9fbaSOystein Eftevaag ifapi_hierarchy_path_p(const char *path)
298*758e9fbaSOystein Eftevaag {
299*758e9fbaSOystein Eftevaag     size_t pos1 = 0;
300*758e9fbaSOystein Eftevaag     size_t pos2 = 0;
301*758e9fbaSOystein Eftevaag     char *start;
302*758e9fbaSOystein Eftevaag 
303*758e9fbaSOystein Eftevaag     if (strncmp("/", path, 1) == 0)
304*758e9fbaSOystein Eftevaag         pos1 = 1;
305*758e9fbaSOystein Eftevaag     /* Skip profile if it does exist in path */
306*758e9fbaSOystein Eftevaag     if (strncmp("P_", &path[pos1], 2) == 0) {
307*758e9fbaSOystein Eftevaag         start = strchr(&path[pos1], IFAPI_FILE_DELIM_CHAR);
308*758e9fbaSOystein Eftevaag         if (start) {
309*758e9fbaSOystein Eftevaag             pos2 = (int)(start - &path[pos1]);
310*758e9fbaSOystein Eftevaag             if (strncmp("/", &path[pos2], 1) == 0)
311*758e9fbaSOystein Eftevaag                 pos2 += 1;
312*758e9fbaSOystein Eftevaag             if (strncmp("/", &path[pos2], 1) == 0)
313*758e9fbaSOystein Eftevaag                 pos2 += 1;
314*758e9fbaSOystein Eftevaag         }
315*758e9fbaSOystein Eftevaag     }
316*758e9fbaSOystein Eftevaag     /* Check whether only hierarchy is specified in path */
317*758e9fbaSOystein Eftevaag     if ((strncasecmp(&path[pos1 + pos2], "HS", 2) == 0 ||
318*758e9fbaSOystein Eftevaag          strncasecmp(&path[pos1 + pos2], "HE", 2) == 0 ||
319*758e9fbaSOystein Eftevaag          strncasecmp(&path[pos1 + pos2], "HE", 2) == 0 ||
320*758e9fbaSOystein Eftevaag          strncasecmp(&path[pos1 + pos2], "HP", 2) == 0 ||
321*758e9fbaSOystein Eftevaag          strncasecmp(&path[pos1 + pos2], "HN", 2) == 0 ||
322*758e9fbaSOystein Eftevaag          strncasecmp(&path[pos1 + pos2], "HP", 2) == 0)
323*758e9fbaSOystein Eftevaag         && (strlen(path) == pos1 + pos2 + 2 ||
324*758e9fbaSOystein Eftevaag             (strlen(path) == pos1 + pos2 + 3 &&
325*758e9fbaSOystein Eftevaag              path[pos1 + pos2 + 2] == IFAPI_FILE_DELIM_CHAR))){
326*758e9fbaSOystein Eftevaag         return true;
327*758e9fbaSOystein Eftevaag     } else if (strncasecmp(&path[pos1 + pos2], "LOCKOUT", 7) == 0
328*758e9fbaSOystein Eftevaag                && (strlen(path) == pos1 + pos2 + 7 ||
329*758e9fbaSOystein Eftevaag                    (strlen(path) == pos1 + pos2 + 8 &&
330*758e9fbaSOystein Eftevaag                     path[pos1 + pos2 + 7] == IFAPI_FILE_DELIM_CHAR))) {
331*758e9fbaSOystein Eftevaag         return true;
332*758e9fbaSOystein Eftevaag     }
333*758e9fbaSOystein Eftevaag     return false;
334*758e9fbaSOystein Eftevaag }
335*758e9fbaSOystein Eftevaag 
336*758e9fbaSOystein Eftevaag /** Compare two variables of type TPM2B_ECC_PARAMETER.
337*758e9fbaSOystein Eftevaag  *
338*758e9fbaSOystein Eftevaag  * @param[in] in1 variable to be compared with in2.
339*758e9fbaSOystein Eftevaag  * @param[in] in2 variable to be compared with in1.
340*758e9fbaSOystein Eftevaag  *
341*758e9fbaSOystein Eftevaag  * @retval true if the variables are equal.
342*758e9fbaSOystein Eftevaag  * @retval false if not.
343*758e9fbaSOystein Eftevaag  */
344*758e9fbaSOystein Eftevaag bool
ifapi_TPM2B_ECC_PARAMETER_cmp(TPM2B_ECC_PARAMETER * in1,TPM2B_ECC_PARAMETER * in2)345*758e9fbaSOystein Eftevaag ifapi_TPM2B_ECC_PARAMETER_cmp(TPM2B_ECC_PARAMETER *in1,
346*758e9fbaSOystein Eftevaag                               TPM2B_ECC_PARAMETER *in2)
347*758e9fbaSOystein Eftevaag {
348*758e9fbaSOystein Eftevaag 
349*758e9fbaSOystein Eftevaag     if (in1->size != in2->size)
350*758e9fbaSOystein Eftevaag         return false;
351*758e9fbaSOystein Eftevaag 
352*758e9fbaSOystein Eftevaag     return memcmp(&in1->buffer[0], &in2->buffer[0], in1->size) == 0;
353*758e9fbaSOystein Eftevaag }
354*758e9fbaSOystein Eftevaag 
355*758e9fbaSOystein Eftevaag /** Compare two variables of type TPMS_ECC_POINT.
356*758e9fbaSOystein Eftevaag  *
357*758e9fbaSOystein Eftevaag  * @param[in] in1 variable to be compared with in2.
358*758e9fbaSOystein Eftevaag  * @param[in] in2 variable to be compared with in1.
359*758e9fbaSOystein Eftevaag  *
360*758e9fbaSOystein Eftevaag  * @retval true if the variables are equal.
361*758e9fbaSOystein Eftevaag  * @retval false if not.
362*758e9fbaSOystein Eftevaag  */
363*758e9fbaSOystein Eftevaag bool
ifapi_TPMS_ECC_POINT_cmp(TPMS_ECC_POINT * in1,TPMS_ECC_POINT * in2)364*758e9fbaSOystein Eftevaag ifapi_TPMS_ECC_POINT_cmp(TPMS_ECC_POINT *in1, TPMS_ECC_POINT *in2)
365*758e9fbaSOystein Eftevaag {
366*758e9fbaSOystein Eftevaag     LOG_TRACE("call");
367*758e9fbaSOystein Eftevaag 
368*758e9fbaSOystein Eftevaag     if (!ifapi_TPM2B_ECC_PARAMETER_cmp(&in1->x, &in2->x))
369*758e9fbaSOystein Eftevaag         return false;
370*758e9fbaSOystein Eftevaag 
371*758e9fbaSOystein Eftevaag     if (!ifapi_TPM2B_ECC_PARAMETER_cmp(&in1->y, &in2->y))
372*758e9fbaSOystein Eftevaag         return false;
373*758e9fbaSOystein Eftevaag 
374*758e9fbaSOystein Eftevaag     return true;
375*758e9fbaSOystein Eftevaag }
376*758e9fbaSOystein Eftevaag 
377*758e9fbaSOystein Eftevaag /**  Compare two variables of type TPM2B_DIGEST.
378*758e9fbaSOystein Eftevaag  *
379*758e9fbaSOystein Eftevaag  * @param[in] in1 variable to be compared with in2.
380*758e9fbaSOystein Eftevaag  * @param[in] in2 variable to be compared with in1.
381*758e9fbaSOystein Eftevaag  *
382*758e9fbaSOystein Eftevaag  * @retval true if the variables are equal.
383*758e9fbaSOystein Eftevaag  * @retval false if not.
384*758e9fbaSOystein Eftevaag  */
385*758e9fbaSOystein Eftevaag bool
ifapi_TPM2B_DIGEST_cmp(TPM2B_DIGEST * in1,TPM2B_DIGEST * in2)386*758e9fbaSOystein Eftevaag ifapi_TPM2B_DIGEST_cmp(TPM2B_DIGEST *in1, TPM2B_DIGEST *in2)
387*758e9fbaSOystein Eftevaag {
388*758e9fbaSOystein Eftevaag 
389*758e9fbaSOystein Eftevaag     if (in1->size != in2->size)
390*758e9fbaSOystein Eftevaag         return false;
391*758e9fbaSOystein Eftevaag 
392*758e9fbaSOystein Eftevaag     return memcmp(&in1->buffer[0], &in2->buffer[0], in1->size) == 0;
393*758e9fbaSOystein Eftevaag }
394*758e9fbaSOystein Eftevaag 
395*758e9fbaSOystein Eftevaag /** Compare two variables of type TPM2B_PUBLIC_KEY_RSA.
396*758e9fbaSOystein Eftevaag  *
397*758e9fbaSOystein Eftevaag  * @param[in] in1 variable to be compared with in2
398*758e9fbaSOystein Eftevaag  * @param[in] in2 variable to be compared with in1
399*758e9fbaSOystein Eftevaag  *
400*758e9fbaSOystein Eftevaag  * @retval true if the variables are equal.
401*758e9fbaSOystein Eftevaag  * @retval false if not.
402*758e9fbaSOystein Eftevaag  */
403*758e9fbaSOystein Eftevaag bool
ifapi_TPM2B_PUBLIC_KEY_RSA_cmp(TPM2B_PUBLIC_KEY_RSA * in1,TPM2B_PUBLIC_KEY_RSA * in2)404*758e9fbaSOystein Eftevaag ifapi_TPM2B_PUBLIC_KEY_RSA_cmp(TPM2B_PUBLIC_KEY_RSA *in1,
405*758e9fbaSOystein Eftevaag                                TPM2B_PUBLIC_KEY_RSA *in2)
406*758e9fbaSOystein Eftevaag {
407*758e9fbaSOystein Eftevaag 
408*758e9fbaSOystein Eftevaag     if (in1->size != in2->size)
409*758e9fbaSOystein Eftevaag         return false;
410*758e9fbaSOystein Eftevaag 
411*758e9fbaSOystein Eftevaag     return memcmp(&in1->buffer[0], &in2->buffer[0], in1->size) == 0;
412*758e9fbaSOystein Eftevaag }
413*758e9fbaSOystein Eftevaag 
414*758e9fbaSOystein Eftevaag /**  Compare two variables of type TPMU_PUBLIC_ID.
415*758e9fbaSOystein Eftevaag  *
416*758e9fbaSOystein Eftevaag  * @param[in] in1 variable to be compared with in2.
417*758e9fbaSOystein Eftevaag  * @param[in] selector1 key type of first key.
418*758e9fbaSOystein Eftevaag  * @param[in] in2 variable to be compared with in1.
419*758e9fbaSOystein Eftevaag  * @param[in] selector2 key type of second key.
420*758e9fbaSOystein Eftevaag  *
421*758e9fbaSOystein Eftevaag  * @result true if variables are equal.
422*758e9fbaSOystein Eftevaag  * @result false if not.
423*758e9fbaSOystein Eftevaag  */
424*758e9fbaSOystein Eftevaag bool
ifapi_TPMU_PUBLIC_ID_cmp(TPMU_PUBLIC_ID * in1,UINT32 selector1,TPMU_PUBLIC_ID * in2,UINT32 selector2)425*758e9fbaSOystein Eftevaag ifapi_TPMU_PUBLIC_ID_cmp(TPMU_PUBLIC_ID *in1, UINT32 selector1,
426*758e9fbaSOystein Eftevaag                          TPMU_PUBLIC_ID *in2, UINT32 selector2)
427*758e9fbaSOystein Eftevaag {
428*758e9fbaSOystein Eftevaag 
429*758e9fbaSOystein Eftevaag     if (selector1 != selector2)
430*758e9fbaSOystein Eftevaag         return false;
431*758e9fbaSOystein Eftevaag 
432*758e9fbaSOystein Eftevaag     switch (selector1) {
433*758e9fbaSOystein Eftevaag     case TPM2_ALG_KEYEDHASH:
434*758e9fbaSOystein Eftevaag         if (!ifapi_TPM2B_DIGEST_cmp(&in1->keyedHash, &in2->keyedHash))
435*758e9fbaSOystein Eftevaag             return false;
436*758e9fbaSOystein Eftevaag         break;
437*758e9fbaSOystein Eftevaag     case TPM2_ALG_SYMCIPHER:
438*758e9fbaSOystein Eftevaag         if (!ifapi_TPM2B_DIGEST_cmp(&in1->sym, &in2->sym))
439*758e9fbaSOystein Eftevaag             return false;
440*758e9fbaSOystein Eftevaag         break;
441*758e9fbaSOystein Eftevaag     case TPM2_ALG_RSA:
442*758e9fbaSOystein Eftevaag         if (!ifapi_TPM2B_PUBLIC_KEY_RSA_cmp(&in1->rsa, &in2->rsa))
443*758e9fbaSOystein Eftevaag             return false;
444*758e9fbaSOystein Eftevaag         break;
445*758e9fbaSOystein Eftevaag     case TPM2_ALG_ECC:
446*758e9fbaSOystein Eftevaag         if (!ifapi_TPMS_ECC_POINT_cmp(&in1->ecc, &in2->ecc))
447*758e9fbaSOystein Eftevaag             return false;
448*758e9fbaSOystein Eftevaag         break;
449*758e9fbaSOystein Eftevaag     default:
450*758e9fbaSOystein Eftevaag         return false;
451*758e9fbaSOystein Eftevaag     };
452*758e9fbaSOystein Eftevaag     return true;
453*758e9fbaSOystein Eftevaag }
454*758e9fbaSOystein Eftevaag 
455*758e9fbaSOystein Eftevaag /**
456*758e9fbaSOystein Eftevaag  * Compare the PUBLIC_ID stored in two  TPMT_PUBLIC structures.
457*758e9fbaSOystein Eftevaag  * @param[in] in1 the public data with the unique data to be compared with:
458*758e9fbaSOystein Eftevaag  * @param[in] in2
459*758e9fbaSOystein Eftevaag  *
460*758e9fbaSOystein Eftevaag  * @retval true if the variables are equal.
461*758e9fbaSOystein Eftevaag  * @retval false if not.
462*758e9fbaSOystein Eftevaag  */
463*758e9fbaSOystein Eftevaag bool
ifapi_TPMT_PUBLIC_cmp(TPMT_PUBLIC * in1,TPMT_PUBLIC * in2)464*758e9fbaSOystein Eftevaag ifapi_TPMT_PUBLIC_cmp(TPMT_PUBLIC *in1, TPMT_PUBLIC *in2)
465*758e9fbaSOystein Eftevaag {
466*758e9fbaSOystein Eftevaag 
467*758e9fbaSOystein Eftevaag     if (!ifapi_TPMU_PUBLIC_ID_cmp(&in1->unique, in1->type, &in2->unique, in2->type))
468*758e9fbaSOystein Eftevaag         return false;
469*758e9fbaSOystein Eftevaag 
470*758e9fbaSOystein Eftevaag     return true;
471*758e9fbaSOystein Eftevaag }
472*758e9fbaSOystein Eftevaag 
473*758e9fbaSOystein Eftevaag /** Print to allocated string.
474*758e9fbaSOystein Eftevaag  *
475*758e9fbaSOystein Eftevaag  * A list of parameters will be printed to an allocated string according to the
476*758e9fbaSOystein Eftevaag  * format description in the first parameter.
477*758e9fbaSOystein Eftevaag  *
478*758e9fbaSOystein Eftevaag  * @param[out] str The allocated output string.
479*758e9fbaSOystein Eftevaag  * @param[in] fmt The format string (printf formats can be used.)
480*758e9fbaSOystein Eftevaag  * @param[in] args The list of objects to be printed.
481*758e9fbaSOystein Eftevaag  *
482*758e9fbaSOystein Eftevaag  * @retval int The size of the string ff the printing was successful.
483*758e9fbaSOystein Eftevaag  * @retval -1 if not enough memory can be allocated.
484*758e9fbaSOystein Eftevaag  */
485*758e9fbaSOystein Eftevaag int
vasprintf(char ** str,const char * fmt,va_list args)486*758e9fbaSOystein Eftevaag vasprintf(char **str, const char *fmt, va_list args)
487*758e9fbaSOystein Eftevaag {
488*758e9fbaSOystein Eftevaag     int size = 0;
489*758e9fbaSOystein Eftevaag     va_list tmpa;
490*758e9fbaSOystein Eftevaag     char *dmy = NULL;
491*758e9fbaSOystein Eftevaag     va_copy(tmpa, args);
492*758e9fbaSOystein Eftevaag     size = vsnprintf(dmy, size, fmt, tmpa);
493*758e9fbaSOystein Eftevaag     va_end(tmpa);
494*758e9fbaSOystein Eftevaag     if (size < 0) {
495*758e9fbaSOystein Eftevaag         return -1;
496*758e9fbaSOystein Eftevaag     }
497*758e9fbaSOystein Eftevaag     *str = (char *) malloc(size + 1);
498*758e9fbaSOystein Eftevaag     if (NULL == *str) {
499*758e9fbaSOystein Eftevaag         return -1;
500*758e9fbaSOystein Eftevaag     }
501*758e9fbaSOystein Eftevaag     size = vsprintf(*str, fmt, args);
502*758e9fbaSOystein Eftevaag     return size;
503*758e9fbaSOystein Eftevaag }
504*758e9fbaSOystein Eftevaag 
505*758e9fbaSOystein Eftevaag /** Print to allocated string.
506*758e9fbaSOystein Eftevaag  *
507*758e9fbaSOystein Eftevaag  * A list of parameters will be printed to an allocated string according to the
508*758e9fbaSOystein Eftevaag  * format description in the first parameter.
509*758e9fbaSOystein Eftevaag  *
510*758e9fbaSOystein Eftevaag  * @param[out] str The allocated output string.
511*758e9fbaSOystein Eftevaag  * @param[in] fmt The format string (printf formats can be used.)
512*758e9fbaSOystein Eftevaag  * @param[in] ... The list of objects to be printed.
513*758e9fbaSOystein Eftevaag  *
514*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS If the printing was successful.
515*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
516*758e9fbaSOystein Eftevaag  */
517*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_asprintf(char ** str,const char * fmt,...)518*758e9fbaSOystein Eftevaag ifapi_asprintf(char **str, const char *fmt, ...)
519*758e9fbaSOystein Eftevaag {
520*758e9fbaSOystein Eftevaag     int size = 0;
521*758e9fbaSOystein Eftevaag     va_list args;
522*758e9fbaSOystein Eftevaag     va_start(args, fmt);
523*758e9fbaSOystein Eftevaag     size = vasprintf(str, fmt, args);
524*758e9fbaSOystein Eftevaag     va_end(args);
525*758e9fbaSOystein Eftevaag     if (size == -1)
526*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_MEMORY;
527*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
528*758e9fbaSOystein Eftevaag }
529*758e9fbaSOystein Eftevaag 
530*758e9fbaSOystein Eftevaag /** Divides str into substrings based on a delimiter.
531*758e9fbaSOystein Eftevaag  *
532*758e9fbaSOystein Eftevaag  * @param[in] string the string to split.
533*758e9fbaSOystein Eftevaag  * @param[in] delimiter the delimiter.
534*758e9fbaSOystein Eftevaag  *
535*758e9fbaSOystein Eftevaag  * @retval The linked list of substrings.
536*758e9fbaSOystein Eftevaag  * @retval NULL if the list cannot be created.
537*758e9fbaSOystein Eftevaag  */
538*758e9fbaSOystein Eftevaag NODE_STR_T *
split_string(const char * string,char * delimiter)539*758e9fbaSOystein Eftevaag split_string(const char *string, char *delimiter)
540*758e9fbaSOystein Eftevaag {
541*758e9fbaSOystein Eftevaag     NODE_STR_T *node = NULL;
542*758e9fbaSOystein Eftevaag     NODE_STR_T *start_node = NULL;
543*758e9fbaSOystein Eftevaag     char *strtok_save = NULL;
544*758e9fbaSOystein Eftevaag     char *stringdup = NULL;
545*758e9fbaSOystein Eftevaag     char *substr = NULL;
546*758e9fbaSOystein Eftevaag     if (string == NULL)
547*758e9fbaSOystein Eftevaag         return NULL;
548*758e9fbaSOystein Eftevaag 
549*758e9fbaSOystein Eftevaag     stringdup = strdup(string);
550*758e9fbaSOystein Eftevaag     if (stringdup == NULL) {
551*758e9fbaSOystein Eftevaag         LOG_ERROR("%s", "Out of memory.");
552*758e9fbaSOystein Eftevaag         goto error_cleanup;
553*758e9fbaSOystein Eftevaag     }
554*758e9fbaSOystein Eftevaag     char *stringdup_tokenized = strtok_r(stringdup, delimiter, &strtok_save);
555*758e9fbaSOystein Eftevaag     if (stringdup_tokenized != NULL) {
556*758e9fbaSOystein Eftevaag         substr = strdup(stringdup_tokenized);
557*758e9fbaSOystein Eftevaag     } else {
558*758e9fbaSOystein Eftevaag         substr = strdup(stringdup);
559*758e9fbaSOystein Eftevaag     }
560*758e9fbaSOystein Eftevaag     if (substr == NULL) {
561*758e9fbaSOystein Eftevaag         LOG_ERROR("%s", "Out of memory.");
562*758e9fbaSOystein Eftevaag         goto error_cleanup;
563*758e9fbaSOystein Eftevaag     }
564*758e9fbaSOystein Eftevaag     do {
565*758e9fbaSOystein Eftevaag         if (node == NULL) {
566*758e9fbaSOystein Eftevaag             node = malloc(sizeof(NODE_STR_T));
567*758e9fbaSOystein Eftevaag             if (node == NULL) {
568*758e9fbaSOystein Eftevaag                 LOG_ERROR("%s", "Out of memory.");
569*758e9fbaSOystein Eftevaag                 goto error_cleanup;
570*758e9fbaSOystein Eftevaag             }
571*758e9fbaSOystein Eftevaag             node->next = NULL;
572*758e9fbaSOystein Eftevaag             node->free_string = true;
573*758e9fbaSOystein Eftevaag             start_node = node;
574*758e9fbaSOystein Eftevaag         } else {
575*758e9fbaSOystein Eftevaag             node->next = malloc(sizeof(NODE_STR_T));
576*758e9fbaSOystein Eftevaag             if (node->next == NULL) {
577*758e9fbaSOystein Eftevaag                 LOG_ERROR("%s", "Out of memory.");
578*758e9fbaSOystein Eftevaag                 goto error_cleanup;
579*758e9fbaSOystein Eftevaag             }
580*758e9fbaSOystein Eftevaag             node = node->next;
581*758e9fbaSOystein Eftevaag             node->next = NULL;
582*758e9fbaSOystein Eftevaag             node->free_string = true;
583*758e9fbaSOystein Eftevaag         }
584*758e9fbaSOystein Eftevaag         node->str = substr;
585*758e9fbaSOystein Eftevaag         substr = strtok_r(NULL, delimiter, &strtok_save);
586*758e9fbaSOystein Eftevaag         if (substr) {
587*758e9fbaSOystein Eftevaag             substr = strdup(substr);
588*758e9fbaSOystein Eftevaag             if (substr == NULL) {
589*758e9fbaSOystein Eftevaag                 LOG_ERROR("%s", "Out of memory.");
590*758e9fbaSOystein Eftevaag                 goto error_cleanup;
591*758e9fbaSOystein Eftevaag             }
592*758e9fbaSOystein Eftevaag         }
593*758e9fbaSOystein Eftevaag     } while (substr != NULL);
594*758e9fbaSOystein Eftevaag 
595*758e9fbaSOystein Eftevaag     SAFE_FREE(stringdup);
596*758e9fbaSOystein Eftevaag     return start_node;
597*758e9fbaSOystein Eftevaag error_cleanup:
598*758e9fbaSOystein Eftevaag     SAFE_FREE(start_node);
599*758e9fbaSOystein Eftevaag     SAFE_FREE(substr);
600*758e9fbaSOystein Eftevaag     SAFE_FREE(stringdup);
601*758e9fbaSOystein Eftevaag     return NULL;
602*758e9fbaSOystein Eftevaag }
603*758e9fbaSOystein Eftevaag 
604*758e9fbaSOystein Eftevaag /** Free linked list of strings.
605*758e9fbaSOystein Eftevaag  *
606*758e9fbaSOystein Eftevaag  * @param[in] node the first node of the linked list.
607*758e9fbaSOystein Eftevaag  */
608*758e9fbaSOystein Eftevaag void
free_string_list(NODE_STR_T * node)609*758e9fbaSOystein Eftevaag free_string_list(NODE_STR_T *node)
610*758e9fbaSOystein Eftevaag {
611*758e9fbaSOystein Eftevaag     NODE_STR_T *next;
612*758e9fbaSOystein Eftevaag     if (node == NULL)
613*758e9fbaSOystein Eftevaag         return;
614*758e9fbaSOystein Eftevaag     while (node != NULL) {
615*758e9fbaSOystein Eftevaag         if (node->free_string)
616*758e9fbaSOystein Eftevaag             free(node->str);
617*758e9fbaSOystein Eftevaag         next = node->next;
618*758e9fbaSOystein Eftevaag         free(node);
619*758e9fbaSOystein Eftevaag         node = next;
620*758e9fbaSOystein Eftevaag     }
621*758e9fbaSOystein Eftevaag }
622*758e9fbaSOystein Eftevaag 
623*758e9fbaSOystein Eftevaag /** Free linked list of IFAPI objects.
624*758e9fbaSOystein Eftevaag  *
625*758e9fbaSOystein Eftevaag  * @param[in] node the first node of the linked list.
626*758e9fbaSOystein Eftevaag  */
627*758e9fbaSOystein Eftevaag void
ifapi_free_object_list(NODE_OBJECT_T * node)628*758e9fbaSOystein Eftevaag ifapi_free_object_list(NODE_OBJECT_T *node)
629*758e9fbaSOystein Eftevaag {
630*758e9fbaSOystein Eftevaag     NODE_OBJECT_T *next;
631*758e9fbaSOystein Eftevaag     if (node == NULL)
632*758e9fbaSOystein Eftevaag         return;
633*758e9fbaSOystein Eftevaag     while (node != NULL) {
634*758e9fbaSOystein Eftevaag         ifapi_cleanup_ifapi_object((IFAPI_OBJECT *)node->object);
635*758e9fbaSOystein Eftevaag         SAFE_FREE(node->object);
636*758e9fbaSOystein Eftevaag         next = node->next;
637*758e9fbaSOystein Eftevaag         free(node);
638*758e9fbaSOystein Eftevaag         node = next;
639*758e9fbaSOystein Eftevaag     }
640*758e9fbaSOystein Eftevaag }
641*758e9fbaSOystein Eftevaag 
642*758e9fbaSOystein Eftevaag /** Free linked list of IFAPI objects (link nodes only).
643*758e9fbaSOystein Eftevaag  *
644*758e9fbaSOystein Eftevaag  * @param[in] node the first node of the linked list.
645*758e9fbaSOystein Eftevaag  */
646*758e9fbaSOystein Eftevaag void
ifapi_free_node_list(NODE_OBJECT_T * node)647*758e9fbaSOystein Eftevaag ifapi_free_node_list(NODE_OBJECT_T *node)
648*758e9fbaSOystein Eftevaag {
649*758e9fbaSOystein Eftevaag     NODE_OBJECT_T *next;
650*758e9fbaSOystein Eftevaag     if (node == NULL)
651*758e9fbaSOystein Eftevaag         return;
652*758e9fbaSOystein Eftevaag     while (node != NULL) {
653*758e9fbaSOystein Eftevaag         next = node->next;
654*758e9fbaSOystein Eftevaag         free(node);
655*758e9fbaSOystein Eftevaag         node = next;
656*758e9fbaSOystein Eftevaag     }
657*758e9fbaSOystein Eftevaag }
658*758e9fbaSOystein Eftevaag 
659*758e9fbaSOystein Eftevaag /** Compute the number on nodes in a linked list.
660*758e9fbaSOystein Eftevaag  *
661*758e9fbaSOystein Eftevaag  * @param[in] node the first node of the linked list.
662*758e9fbaSOystein Eftevaag  *
663*758e9fbaSOystein Eftevaag  * @retval the number on nodes.
664*758e9fbaSOystein Eftevaag  */
665*758e9fbaSOystein Eftevaag size_t
ifapi_path_length(NODE_STR_T * node)666*758e9fbaSOystein Eftevaag ifapi_path_length(NODE_STR_T *node)
667*758e9fbaSOystein Eftevaag {
668*758e9fbaSOystein Eftevaag     size_t length = 0;
669*758e9fbaSOystein Eftevaag     if (node == NULL)
670*758e9fbaSOystein Eftevaag         return 0;
671*758e9fbaSOystein Eftevaag     while (node != NULL) {
672*758e9fbaSOystein Eftevaag         length += 1;
673*758e9fbaSOystein Eftevaag         node = node->next;
674*758e9fbaSOystein Eftevaag     }
675*758e9fbaSOystein Eftevaag     return length;
676*758e9fbaSOystein Eftevaag }
677*758e9fbaSOystein Eftevaag 
678*758e9fbaSOystein Eftevaag /** Compute the size of a concatenated string.
679*758e9fbaSOystein Eftevaag  *
680*758e9fbaSOystein Eftevaag  * @param[in] node the first node of the linked string list.
681*758e9fbaSOystein Eftevaag  * @param[in] delim_length the size of the delimiter used for the concatenation.
682*758e9fbaSOystein Eftevaag  *
683*758e9fbaSOystein Eftevaag  * @retval the size of the string.
684*758e9fbaSOystein Eftevaag  */
685*758e9fbaSOystein Eftevaag static size_t
path_str_length(NODE_STR_T * node,int delim_length)686*758e9fbaSOystein Eftevaag path_str_length(NODE_STR_T *node, int delim_length)
687*758e9fbaSOystein Eftevaag {
688*758e9fbaSOystein Eftevaag     size_t size = 0;
689*758e9fbaSOystein Eftevaag     if (node == NULL)
690*758e9fbaSOystein Eftevaag         return 0;
691*758e9fbaSOystein Eftevaag     while (node != NULL) {
692*758e9fbaSOystein Eftevaag         size += strlen(node->str);
693*758e9fbaSOystein Eftevaag         if (node->next != NULL)
694*758e9fbaSOystein Eftevaag             size = size + delim_length;
695*758e9fbaSOystein Eftevaag         node = node->next;
696*758e9fbaSOystein Eftevaag     }
697*758e9fbaSOystein Eftevaag     return size;
698*758e9fbaSOystein Eftevaag }
699*758e9fbaSOystein Eftevaag 
700*758e9fbaSOystein Eftevaag /** Compute a pathname based on a linked list of strings.
701*758e9fbaSOystein Eftevaag  *
702*758e9fbaSOystein Eftevaag  * @param[out] dest The pointer to the generated pathname (callee allocated).
703*758e9fbaSOystein Eftevaag  * @param[in]  supdir A sup directory will be the prefix of the pathname.
704*758e9fbaSOystein Eftevaag  * @param[in]  node The linked list.
705*758e9fbaSOystein Eftevaag  * @param[in]  name A name which is appended to the result if not NULL.
706*758e9fbaSOystein Eftevaag  *
707*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS if the function call was a success.
708*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if the memory for the pathname can't be allocated.
709*758e9fbaSOystein Eftevaag  */
710*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_path_string(char ** dest,const char * supdir,NODE_STR_T * node,char * name)711*758e9fbaSOystein Eftevaag ifapi_path_string(char **dest, const char *supdir, NODE_STR_T *node, char *name)
712*758e9fbaSOystein Eftevaag {
713*758e9fbaSOystein Eftevaag     size_t length = 1 + path_str_length(node,
714*758e9fbaSOystein Eftevaag                                         1) + ((supdir == NULL) ? 0 : strlen(supdir) + 1)
715*758e9fbaSOystein Eftevaag                     + ((name == NULL) ? 0 : strlen(name) + 1);
716*758e9fbaSOystein Eftevaag     *dest = malloc(length);
717*758e9fbaSOystein Eftevaag     if (*dest == NULL) {
718*758e9fbaSOystein Eftevaag         LOG_ERROR("Out of memory");
719*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_MEMORY;
720*758e9fbaSOystein Eftevaag     }
721*758e9fbaSOystein Eftevaag     *dest[0] = '\0';
722*758e9fbaSOystein Eftevaag     if (supdir != NULL) {
723*758e9fbaSOystein Eftevaag         strcat(*dest, supdir);
724*758e9fbaSOystein Eftevaag         strcat(*dest, IFAPI_FILE_DELIM);
725*758e9fbaSOystein Eftevaag     }
726*758e9fbaSOystein Eftevaag     for (; node != NULL; node = node->next) {
727*758e9fbaSOystein Eftevaag         strcat(*dest, node->str);
728*758e9fbaSOystein Eftevaag         if (node->next != NULL) {
729*758e9fbaSOystein Eftevaag             strcat(*dest, IFAPI_FILE_DELIM);
730*758e9fbaSOystein Eftevaag         }
731*758e9fbaSOystein Eftevaag     }
732*758e9fbaSOystein Eftevaag     if (name != NULL) {
733*758e9fbaSOystein Eftevaag         strcat(*dest, IFAPI_FILE_DELIM);
734*758e9fbaSOystein Eftevaag         strcat(*dest, name);
735*758e9fbaSOystein Eftevaag     }
736*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
737*758e9fbaSOystein Eftevaag }
738*758e9fbaSOystein Eftevaag 
739*758e9fbaSOystein Eftevaag 
740*758e9fbaSOystein Eftevaag /** Compute a pathname based on the first n elements of a linked list of strings.
741*758e9fbaSOystein Eftevaag  *
742*758e9fbaSOystein Eftevaag  * @param[out] dest the pointer to the pathname (callee allocated).
743*758e9fbaSOystein Eftevaag  * @param[in]  supdir a sup directory will be the prefix of the pathname.
744*758e9fbaSOystein Eftevaag  *                    (can be NULL).
745*758e9fbaSOystein Eftevaag  * @param[in]  node the linked list.
746*758e9fbaSOystein Eftevaag  * @param[in]  name  the filename (can be NULL).
747*758e9fbaSOystein Eftevaag  * @param[in]  n the number of the first elements which will bes used for concatenation.
748*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS if the function call was a success.
749*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if the memory for the pathname can't be allocated.
750*758e9fbaSOystein Eftevaag  */
751*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_path_string_n(char ** dest,const char * supdir,NODE_STR_T * node,char * name,size_t n)752*758e9fbaSOystein Eftevaag ifapi_path_string_n(char **dest, const char *supdir, NODE_STR_T *node, char *name,
753*758e9fbaSOystein Eftevaag                     size_t n)
754*758e9fbaSOystein Eftevaag {
755*758e9fbaSOystein Eftevaag     size_t length = 1 + path_str_length(node,
756*758e9fbaSOystein Eftevaag                                         1) + ((supdir == NULL) ? 0 : strlen(supdir) + 1)
757*758e9fbaSOystein Eftevaag                     + ((name == NULL) ? 0 : strlen(name) + 1);
758*758e9fbaSOystein Eftevaag     *dest = malloc(length);
759*758e9fbaSOystein Eftevaag     size_t i;
760*758e9fbaSOystein Eftevaag     if (*dest == NULL) {
761*758e9fbaSOystein Eftevaag         LOG_ERROR("Out of memory");
762*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_MEMORY;
763*758e9fbaSOystein Eftevaag     }
764*758e9fbaSOystein Eftevaag     *dest[0] = '\0';
765*758e9fbaSOystein Eftevaag     if (supdir != NULL) {
766*758e9fbaSOystein Eftevaag         strcat(*dest, supdir);
767*758e9fbaSOystein Eftevaag         strcat(*dest, IFAPI_FILE_DELIM);
768*758e9fbaSOystein Eftevaag     }
769*758e9fbaSOystein Eftevaag     for (i = 1; node != NULL && i <= n; i++, node = node->next) {
770*758e9fbaSOystein Eftevaag         strcat(*dest, node->str);
771*758e9fbaSOystein Eftevaag         if (node->next != NULL) {
772*758e9fbaSOystein Eftevaag             strcat(*dest, IFAPI_FILE_DELIM);
773*758e9fbaSOystein Eftevaag         }
774*758e9fbaSOystein Eftevaag     }
775*758e9fbaSOystein Eftevaag     if (name != NULL) {
776*758e9fbaSOystein Eftevaag         strcat(*dest, IFAPI_FILE_DELIM);
777*758e9fbaSOystein Eftevaag         strcat(*dest, name);
778*758e9fbaSOystein Eftevaag     }
779*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
780*758e9fbaSOystein Eftevaag }
781*758e9fbaSOystein Eftevaag 
782*758e9fbaSOystein Eftevaag /** Initialize a linked list of strings.
783*758e9fbaSOystein Eftevaag  *
784*758e9fbaSOystein Eftevaag  * free string in the list object will be set to true.
785*758e9fbaSOystein Eftevaag  * If the list will be extended by sub-string which are part
786*758e9fbaSOystein Eftevaag  * of this strin free_string has to be set to false.
787*758e9fbaSOystein Eftevaag  *
788*758e9fbaSOystein Eftevaag  * @param[in] string The string for the first element.
789*758e9fbaSOystein Eftevaag  *
790*758e9fbaSOystein Eftevaag  * @retval the initial node of the linked list.
791*758e9fbaSOystein Eftevaag  * @retval NULL if the list cannot be created.
792*758e9fbaSOystein Eftevaag  */
793*758e9fbaSOystein Eftevaag NODE_STR_T *
init_string_list(const char * string)794*758e9fbaSOystein Eftevaag init_string_list(const char *string)
795*758e9fbaSOystein Eftevaag {
796*758e9fbaSOystein Eftevaag     NODE_STR_T *result = malloc(sizeof(NODE_STR_T));
797*758e9fbaSOystein Eftevaag     if (result == NULL)
798*758e9fbaSOystein Eftevaag         return NULL;
799*758e9fbaSOystein Eftevaag     result->next = NULL;
800*758e9fbaSOystein Eftevaag     result->str = strdup(string);
801*758e9fbaSOystein Eftevaag     if (result->str == NULL) {
802*758e9fbaSOystein Eftevaag         LOG_ERROR("Out of memory");
803*758e9fbaSOystein Eftevaag         free(result);
804*758e9fbaSOystein Eftevaag         return NULL;
805*758e9fbaSOystein Eftevaag     }
806*758e9fbaSOystein Eftevaag     result->free_string = true;
807*758e9fbaSOystein Eftevaag     return result;
808*758e9fbaSOystein Eftevaag }
809*758e9fbaSOystein Eftevaag 
810*758e9fbaSOystein Eftevaag /** Add string to the last element of a linked list of strings.
811*758e9fbaSOystein Eftevaag  *
812*758e9fbaSOystein Eftevaag  * A duplicate of the passed string will be added.
813*758e9fbaSOystein Eftevaag  *
814*758e9fbaSOystein Eftevaag  * @param[in,out] str_list The linked list.
815*758e9fbaSOystein Eftevaag  * @param[in] string The string to be added.
816*758e9fbaSOystein Eftevaag  *
817*758e9fbaSOystein Eftevaag  * @retval true if the string was added to the list.
818*758e9fbaSOystein Eftevaag  * @retval false if the list could not be extended.
819*758e9fbaSOystein Eftevaag  */
820*758e9fbaSOystein Eftevaag bool
add_string_to_list(NODE_STR_T * str_list,char * string)821*758e9fbaSOystein Eftevaag add_string_to_list(NODE_STR_T *str_list, char *string)
822*758e9fbaSOystein Eftevaag {
823*758e9fbaSOystein Eftevaag     if (str_list == NULL)
824*758e9fbaSOystein Eftevaag         return NULL;
825*758e9fbaSOystein Eftevaag     NODE_STR_T *last = malloc(sizeof(NODE_STR_T));
826*758e9fbaSOystein Eftevaag     if (last == NULL)
827*758e9fbaSOystein Eftevaag         return false;
828*758e9fbaSOystein Eftevaag     while (str_list->next != NULL)
829*758e9fbaSOystein Eftevaag         str_list = str_list->next;
830*758e9fbaSOystein Eftevaag     str_list->next = last;
831*758e9fbaSOystein Eftevaag     last->next = NULL;
832*758e9fbaSOystein Eftevaag     last->str = strdup(string);
833*758e9fbaSOystein Eftevaag     return_if_null(last->str, "Out of memory.", false);
834*758e9fbaSOystein Eftevaag     last->free_string = true;
835*758e9fbaSOystein Eftevaag     return true;
836*758e9fbaSOystein Eftevaag }
837*758e9fbaSOystein Eftevaag 
838*758e9fbaSOystein Eftevaag /** Add a object as first element to a linked list.
839*758e9fbaSOystein Eftevaag  *
840*758e9fbaSOystein Eftevaag  * @param[in] object The object to be added.
841*758e9fbaSOystein Eftevaag  * @param[in,out] object_list The linked list to be extended.
842*758e9fbaSOystein Eftevaag  *
843*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS if the object was added.
844*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY If memory for the list extension cannot
845*758e9fbaSOystein Eftevaag  *         be allocated.
846*758e9fbaSOystein Eftevaag  */
847*758e9fbaSOystein Eftevaag TSS2_RC
push_object_to_list(void * object,NODE_OBJECT_T ** object_list)848*758e9fbaSOystein Eftevaag push_object_to_list(void *object, NODE_OBJECT_T **object_list)
849*758e9fbaSOystein Eftevaag {
850*758e9fbaSOystein Eftevaag     NODE_OBJECT_T *first = calloc(1, sizeof(NODE_OBJECT_T));
851*758e9fbaSOystein Eftevaag     return_if_null(first, "Out of space.", TSS2_FAPI_RC_MEMORY);
852*758e9fbaSOystein Eftevaag     first->object = object;
853*758e9fbaSOystein Eftevaag     if (*object_list)
854*758e9fbaSOystein Eftevaag         first->next = *object_list;
855*758e9fbaSOystein Eftevaag     *object_list = first;
856*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
857*758e9fbaSOystein Eftevaag }
858*758e9fbaSOystein Eftevaag 
859*758e9fbaSOystein Eftevaag /** Add a object as last element to a linked list.
860*758e9fbaSOystein Eftevaag  *
861*758e9fbaSOystein Eftevaag  * @param[in] object The object to be added.
862*758e9fbaSOystein Eftevaag  * @param[in,out] object_list The linked list to be extended.
863*758e9fbaSOystein Eftevaag  *
864*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS if the object was added.
865*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY If memory for the list extension cannot
866*758e9fbaSOystein Eftevaag  *         be allocated.
867*758e9fbaSOystein Eftevaag  */
868*758e9fbaSOystein Eftevaag TSS2_RC
append_object_to_list(void * object,NODE_OBJECT_T ** object_list)869*758e9fbaSOystein Eftevaag append_object_to_list(void *object, NODE_OBJECT_T **object_list)
870*758e9fbaSOystein Eftevaag {
871*758e9fbaSOystein Eftevaag     NODE_OBJECT_T *list, *last = calloc(1, sizeof(NODE_OBJECT_T));
872*758e9fbaSOystein Eftevaag     return_if_null(last, "Out of space.", TSS2_FAPI_RC_MEMORY);
873*758e9fbaSOystein Eftevaag     last->object = object;
874*758e9fbaSOystein Eftevaag     if (!*object_list) {
875*758e9fbaSOystein Eftevaag         *object_list = last;
876*758e9fbaSOystein Eftevaag         return TSS2_RC_SUCCESS;
877*758e9fbaSOystein Eftevaag     }
878*758e9fbaSOystein Eftevaag     list = *object_list;
879*758e9fbaSOystein Eftevaag     while (list->next)
880*758e9fbaSOystein Eftevaag         list = list->next;
881*758e9fbaSOystein Eftevaag     list->next = last;
882*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
883*758e9fbaSOystein Eftevaag }
884*758e9fbaSOystein Eftevaag 
885*758e9fbaSOystein Eftevaag /** Initialize the internal representation of a FAPI hierarchy object.
886*758e9fbaSOystein Eftevaag  *
887*758e9fbaSOystein Eftevaag  * The object will be cleared and the type of the general fapi object will be
888*758e9fbaSOystein Eftevaag  * set to hierarchy.
889*758e9fbaSOystein Eftevaag  *
890*758e9fbaSOystein Eftevaag  * @param[out] hierarchy The caller allocated hierarchy object.
891*758e9fbaSOystein Eftevaag  * @param[in] esys_handle The ESAPI handle of the hierarchy which will be added to
892*758e9fbaSOystein Eftevaag  *            to the object.
893*758e9fbaSOystein Eftevaag  */
894*758e9fbaSOystein Eftevaag void
ifapi_init_hierarchy_object(IFAPI_OBJECT * hierarchy,ESYS_TR esys_handle)895*758e9fbaSOystein Eftevaag ifapi_init_hierarchy_object(
896*758e9fbaSOystein Eftevaag     IFAPI_OBJECT *hierarchy,
897*758e9fbaSOystein Eftevaag     ESYS_TR esys_handle)
898*758e9fbaSOystein Eftevaag {
899*758e9fbaSOystein Eftevaag     memset(hierarchy, 0, sizeof(IFAPI_OBJECT));
900*758e9fbaSOystein Eftevaag     hierarchy->system = TPM2_YES;
901*758e9fbaSOystein Eftevaag     hierarchy->objectType = IFAPI_HIERARCHY_OBJ;
902*758e9fbaSOystein Eftevaag     hierarchy->handle = esys_handle;
903*758e9fbaSOystein Eftevaag }
904*758e9fbaSOystein Eftevaag 
905*758e9fbaSOystein Eftevaag /** Get description of a FAPI object.
906*758e9fbaSOystein Eftevaag  *
907*758e9fbaSOystein Eftevaag  * @param[in] object The object which might have a description.
908*758e9fbaSOystein Eftevaag  *
909*758e9fbaSOystein Eftevaag  * @retval The character description of the object.
910*758e9fbaSOystein Eftevaag  * @retval NULL if no description is available.
911*758e9fbaSOystein Eftevaag  */
912*758e9fbaSOystein Eftevaag char *
get_description(IFAPI_OBJECT * object)913*758e9fbaSOystein Eftevaag get_description(IFAPI_OBJECT *object)
914*758e9fbaSOystein Eftevaag {
915*758e9fbaSOystein Eftevaag     switch (object->objectType) {
916*758e9fbaSOystein Eftevaag     case IFAPI_KEY_OBJ:
917*758e9fbaSOystein Eftevaag         return object->misc.key.description;
918*758e9fbaSOystein Eftevaag     case IFAPI_NV_OBJ:
919*758e9fbaSOystein Eftevaag         return object->misc.nv.description;
920*758e9fbaSOystein Eftevaag     default:
921*758e9fbaSOystein Eftevaag         return NULL;
922*758e9fbaSOystein Eftevaag     }
923*758e9fbaSOystein Eftevaag }
924*758e9fbaSOystein Eftevaag 
925*758e9fbaSOystein Eftevaag /** Create a directory and all sub directories.
926*758e9fbaSOystein Eftevaag  *
927*758e9fbaSOystein Eftevaag  * @param[in] supdir The sup directory were the directories will be created.
928*758e9fbaSOystein Eftevaag  * @param[in] dir_list A linked list with the directory strings.
929*758e9fbaSOystein Eftevaag  * @param[in] mode The creation mode for the directory which will be used
930*758e9fbaSOystein Eftevaag  *            for the mkdir function.
931*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
932*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
933*758e9fbaSOystein Eftevaag  *         the function.
934*758e9fbaSOystein Eftevaag  */
935*758e9fbaSOystein Eftevaag static TSS2_RC
create_dirs(const char * supdir,NODE_STR_T * dir_list,mode_t mode)936*758e9fbaSOystein Eftevaag create_dirs(const char *supdir, NODE_STR_T *dir_list, mode_t mode)
937*758e9fbaSOystein Eftevaag {
938*758e9fbaSOystein Eftevaag     char *new_dir;
939*758e9fbaSOystein Eftevaag     for (size_t i = 1; i <= ifapi_path_length(dir_list); i++) {
940*758e9fbaSOystein Eftevaag         TSS2_RC r = ifapi_path_string_n(&new_dir, supdir, dir_list, NULL, i);
941*758e9fbaSOystein Eftevaag         return_if_error(r, "Create path string");
942*758e9fbaSOystein Eftevaag         LOG_TRACE("Check file: %s", new_dir);
943*758e9fbaSOystein Eftevaag         int rc = mkdir(new_dir, mode);
944*758e9fbaSOystein Eftevaag         if (rc != 0 && errno != EEXIST) {
945*758e9fbaSOystein Eftevaag             LOG_ERROR("mkdir not possible: %i %s", rc, new_dir);
946*758e9fbaSOystein Eftevaag             free(new_dir);
947*758e9fbaSOystein Eftevaag             return TSS2_FAPI_RC_BAD_VALUE;
948*758e9fbaSOystein Eftevaag         }
949*758e9fbaSOystein Eftevaag         free(new_dir);
950*758e9fbaSOystein Eftevaag     }
951*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
952*758e9fbaSOystein Eftevaag }
953*758e9fbaSOystein Eftevaag 
954*758e9fbaSOystein Eftevaag /** Create sub-directories in a certain directory.
955*758e9fbaSOystein Eftevaag  *
956*758e9fbaSOystein Eftevaag  * @param[in] supdir The directory in which the new directories shall be created.
957*758e9fbaSOystein Eftevaag  * @param[in] path The path containing one or more sub-directories.
958*758e9fbaSOystein Eftevaag  *
959*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS: If the directories were created.
960*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY: If the linked list with the sub-directories
961*758e9fbaSOystein Eftevaag  *                              cannot be allocated.
962*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE: If a directory cannot be created.
963*758e9fbaSOystein Eftevaag  */
964*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_create_dirs(const char * supdir,const char * path)965*758e9fbaSOystein Eftevaag ifapi_create_dirs(const char *supdir, const char *path)
966*758e9fbaSOystein Eftevaag {
967*758e9fbaSOystein Eftevaag     TSS2_RC r;
968*758e9fbaSOystein Eftevaag     NODE_STR_T *path_list = split_string(path, IFAPI_FILE_DELIM);
969*758e9fbaSOystein Eftevaag     return_if_null(path_list, "Out of memory.", TSS2_FAPI_RC_MEMORY);
970*758e9fbaSOystein Eftevaag 
971*758e9fbaSOystein Eftevaag     r = create_dirs(supdir, path_list, 0777);
972*758e9fbaSOystein Eftevaag     goto_if_error2(r, "Create directories for %s", error_cleanup, path);
973*758e9fbaSOystein Eftevaag     free_string_list(path_list);
974*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
975*758e9fbaSOystein Eftevaag 
976*758e9fbaSOystein Eftevaag error_cleanup:
977*758e9fbaSOystein Eftevaag     free_string_list(path_list);
978*758e9fbaSOystein Eftevaag     return r;
979*758e9fbaSOystein Eftevaag }
980*758e9fbaSOystein Eftevaag 
981*758e9fbaSOystein Eftevaag /** Determine whether authentication with an auth value is needed ro an object..
982*758e9fbaSOystein Eftevaag  *
983*758e9fbaSOystein Eftevaag  * In the key store the information whether an auth value was provided for an
984*758e9fbaSOystein Eftevaag  * object is saved. Thus the it is possible to decide whether the auth value
985*758e9fbaSOystein Eftevaag  * callback is required for authentication.
986*758e9fbaSOystein Eftevaag  *
987*758e9fbaSOystein Eftevaag  * @param[in] object The object which has to be checked..
988*758e9fbaSOystein Eftevaag  *
989*758e9fbaSOystein Eftevaag  * @retval true: If an auth value was provided.
990*758e9fbaSOystein Eftevaag  * @retval false: If not.
991*758e9fbaSOystein Eftevaag  */
992*758e9fbaSOystein Eftevaag bool
object_with_auth(IFAPI_OBJECT * object)993*758e9fbaSOystein Eftevaag object_with_auth(IFAPI_OBJECT *object)
994*758e9fbaSOystein Eftevaag {
995*758e9fbaSOystein Eftevaag     switch (object->objectType) {
996*758e9fbaSOystein Eftevaag     case IFAPI_KEY_OBJ:
997*758e9fbaSOystein Eftevaag         return (object->misc.key.with_auth == TPM2_YES);
998*758e9fbaSOystein Eftevaag     case IFAPI_NV_OBJ:
999*758e9fbaSOystein Eftevaag         return (object->misc.nv.with_auth == TPM2_YES);
1000*758e9fbaSOystein Eftevaag     case IFAPI_HIERARCHY_OBJ:
1001*758e9fbaSOystein Eftevaag         return (object->misc.hierarchy.with_auth == TPM2_YES);
1002*758e9fbaSOystein Eftevaag     default:
1003*758e9fbaSOystein Eftevaag         return false;
1004*758e9fbaSOystein Eftevaag     }
1005*758e9fbaSOystein Eftevaag }
1006*758e9fbaSOystein Eftevaag 
1007*758e9fbaSOystein Eftevaag /** Free memory allocated during deserialization of a policy element.
1008*758e9fbaSOystein Eftevaag  *
1009*758e9fbaSOystein Eftevaag  * Depending on the element type the fields of a policy element are freed.
1010*758e9fbaSOystein Eftevaag  *
1011*758e9fbaSOystein Eftevaag  * @param[in] policy The policy element.
1012*758e9fbaSOystein Eftevaag  */
1013*758e9fbaSOystein Eftevaag static void
cleanup_policy_element(TPMT_POLICYELEMENT * policy)1014*758e9fbaSOystein Eftevaag cleanup_policy_element(TPMT_POLICYELEMENT *policy)
1015*758e9fbaSOystein Eftevaag {
1016*758e9fbaSOystein Eftevaag         switch (policy->type) {
1017*758e9fbaSOystein Eftevaag         case POLICYSECRET:
1018*758e9fbaSOystein Eftevaag             SAFE_FREE(policy->element.PolicySecret.objectPath);
1019*758e9fbaSOystein Eftevaag             break;
1020*758e9fbaSOystein Eftevaag         case POLICYAUTHORIZE:
1021*758e9fbaSOystein Eftevaag             SAFE_FREE(policy->element.PolicyAuthorize.keyPath);
1022*758e9fbaSOystein Eftevaag             SAFE_FREE(policy->element.PolicyAuthorize.keyPEM);
1023*758e9fbaSOystein Eftevaag             break;
1024*758e9fbaSOystein Eftevaag         case POLICYAUTHORIZENV:
1025*758e9fbaSOystein Eftevaag             SAFE_FREE( policy->element.PolicyAuthorizeNv.nvPath);
1026*758e9fbaSOystein Eftevaag             SAFE_FREE( policy->element.PolicyAuthorizeNv.policy_buffer);
1027*758e9fbaSOystein Eftevaag             break;
1028*758e9fbaSOystein Eftevaag         case POLICYSIGNED:
1029*758e9fbaSOystein Eftevaag             SAFE_FREE(policy->element.PolicySigned.keyPath);
1030*758e9fbaSOystein Eftevaag             SAFE_FREE(policy->element.PolicySigned.keyPEM);
1031*758e9fbaSOystein Eftevaag             SAFE_FREE(policy->element.PolicySigned.publicKeyHint);
1032*758e9fbaSOystein Eftevaag             break;
1033*758e9fbaSOystein Eftevaag         case POLICYPCR:
1034*758e9fbaSOystein Eftevaag             SAFE_FREE(policy->element.PolicyPCR.pcrs);
1035*758e9fbaSOystein Eftevaag             break;
1036*758e9fbaSOystein Eftevaag         case POLICYNV:
1037*758e9fbaSOystein Eftevaag             SAFE_FREE(policy->element.PolicyNV.nvPath);
1038*758e9fbaSOystein Eftevaag             break;
1039*758e9fbaSOystein Eftevaag         case POLICYDUPLICATIONSELECT:
1040*758e9fbaSOystein Eftevaag             SAFE_FREE(policy->element.PolicyDuplicationSelect.newParentPath);
1041*758e9fbaSOystein Eftevaag             break;
1042*758e9fbaSOystein Eftevaag         case POLICYNAMEHASH:
1043*758e9fbaSOystein Eftevaag             for (size_t i = 0; i < 3; i++) {
1044*758e9fbaSOystein Eftevaag                 SAFE_FREE(policy->element.PolicyNameHash.namePaths[i]);
1045*758e9fbaSOystein Eftevaag             }
1046*758e9fbaSOystein Eftevaag             break;
1047*758e9fbaSOystein Eftevaag         case POLICYACTION:
1048*758e9fbaSOystein Eftevaag             SAFE_FREE(policy->element.PolicyAction.action);
1049*758e9fbaSOystein Eftevaag             break;
1050*758e9fbaSOystein Eftevaag         }
1051*758e9fbaSOystein Eftevaag }
1052*758e9fbaSOystein Eftevaag 
1053*758e9fbaSOystein Eftevaag /** Free memory allocated during deserialization of a a policy element list.
1054*758e9fbaSOystein Eftevaag  *
1055*758e9fbaSOystein Eftevaag  * All elements of a policy element list are freed.
1056*758e9fbaSOystein Eftevaag  *
1057*758e9fbaSOystein Eftevaag  * @param[in] policy The policy element list.
1058*758e9fbaSOystein Eftevaag  */
1059*758e9fbaSOystein Eftevaag static void
cleanup_policy_elements(TPML_POLICYELEMENTS * policy)1060*758e9fbaSOystein Eftevaag cleanup_policy_elements(TPML_POLICYELEMENTS *policy)
1061*758e9fbaSOystein Eftevaag {
1062*758e9fbaSOystein Eftevaag     size_t i, j;
1063*758e9fbaSOystein Eftevaag     if (policy != NULL) {
1064*758e9fbaSOystein Eftevaag         for (i = 0; i < policy->count; i++) {
1065*758e9fbaSOystein Eftevaag             if (policy->elements[i].type == POLICYOR) {
1066*758e9fbaSOystein Eftevaag                 /* Policy with sub policies */
1067*758e9fbaSOystein Eftevaag                 TPML_POLICYBRANCHES *branches = policy->elements[i].element.PolicyOr.branches;
1068*758e9fbaSOystein Eftevaag                 for (j = 0; j < branches->count; j++) {
1069*758e9fbaSOystein Eftevaag                     SAFE_FREE(branches->authorizations[j].name);
1070*758e9fbaSOystein Eftevaag                     SAFE_FREE(branches->authorizations[j].description);
1071*758e9fbaSOystein Eftevaag                     cleanup_policy_elements(branches->authorizations[j].policy);
1072*758e9fbaSOystein Eftevaag                 }
1073*758e9fbaSOystein Eftevaag                 SAFE_FREE(branches);
1074*758e9fbaSOystein Eftevaag             } else {
1075*758e9fbaSOystein Eftevaag                 cleanup_policy_element(&policy->elements[i]);
1076*758e9fbaSOystein Eftevaag             }
1077*758e9fbaSOystein Eftevaag         }
1078*758e9fbaSOystein Eftevaag         SAFE_FREE(policy);
1079*758e9fbaSOystein Eftevaag     }
1080*758e9fbaSOystein Eftevaag }
1081*758e9fbaSOystein Eftevaag 
1082*758e9fbaSOystein Eftevaag /** Free memory allocated during deserialization of policy.
1083*758e9fbaSOystein Eftevaag  *
1084*758e9fbaSOystein Eftevaag  * The object will not be freed (might be declared on the stack).
1085*758e9fbaSOystein Eftevaag  *
1086*758e9fbaSOystein Eftevaag  * @param[in] policy The policy to be cleaned up.
1087*758e9fbaSOystein Eftevaag  *
1088*758e9fbaSOystein Eftevaag  */
1089*758e9fbaSOystein Eftevaag void
ifapi_cleanup_policy(TPMS_POLICY * policy)1090*758e9fbaSOystein Eftevaag ifapi_cleanup_policy(TPMS_POLICY *policy)
1091*758e9fbaSOystein Eftevaag {
1092*758e9fbaSOystein Eftevaag     if (policy) {
1093*758e9fbaSOystein Eftevaag         SAFE_FREE(policy->description);
1094*758e9fbaSOystein Eftevaag         if (policy->policyAuthorizations) {
1095*758e9fbaSOystein Eftevaag             for (size_t i = 0; i < policy->policyAuthorizations->count; i++) {
1096*758e9fbaSOystein Eftevaag                 SAFE_FREE(policy->policyAuthorizations->authorizations[i].type);
1097*758e9fbaSOystein Eftevaag             }
1098*758e9fbaSOystein Eftevaag         }
1099*758e9fbaSOystein Eftevaag         SAFE_FREE(policy->policyAuthorizations);
1100*758e9fbaSOystein Eftevaag         cleanup_policy_elements(policy->policy);
1101*758e9fbaSOystein Eftevaag     }
1102*758e9fbaSOystein Eftevaag }
1103*758e9fbaSOystein Eftevaag 
1104*758e9fbaSOystein Eftevaag /** Free memory of a policy object.
1105*758e9fbaSOystein Eftevaag  *
1106*758e9fbaSOystein Eftevaag  * The memory allocated during deserialization of the policy will
1107*758e9fbaSOystein Eftevaag  * also be freed.
1108*758e9fbaSOystein Eftevaag  *
1109*758e9fbaSOystein Eftevaag  * @param[in] object The policy object to be cleaned up.
1110*758e9fbaSOystein Eftevaag  *
1111*758e9fbaSOystein Eftevaag  */
1112*758e9fbaSOystein Eftevaag static void
cleanup_policy_object(POLICY_OBJECT * object)1113*758e9fbaSOystein Eftevaag cleanup_policy_object(POLICY_OBJECT * object) {
1114*758e9fbaSOystein Eftevaag     if (object != NULL) {
1115*758e9fbaSOystein Eftevaag         SAFE_FREE(object->path);
1116*758e9fbaSOystein Eftevaag         ifapi_cleanup_policy(&object->policy);
1117*758e9fbaSOystein Eftevaag         cleanup_policy_object(object->next);
1118*758e9fbaSOystein Eftevaag     }
1119*758e9fbaSOystein Eftevaag }
1120*758e9fbaSOystein Eftevaag 
1121*758e9fbaSOystein Eftevaag static TPML_POLICYELEMENTS *
1122*758e9fbaSOystein Eftevaag copy_policy_elements(const TPML_POLICYELEMENTS *from_policy);
1123*758e9fbaSOystein Eftevaag 
1124*758e9fbaSOystein Eftevaag /** Copy policy structure.
1125*758e9fbaSOystein Eftevaag  *
1126*758e9fbaSOystein Eftevaag  * @param[in] src The policy structure to be copied.
1127*758e9fbaSOystein Eftevaag  * @param[out] dest The destination policy structure.
1128*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
1129*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1130*758e9fbaSOystein Eftevaag  */
1131*758e9fbaSOystein Eftevaag static TSS2_RC
copy_policy(TPMS_POLICY * dest,const TPMS_POLICY * src)1132*758e9fbaSOystein Eftevaag copy_policy(TPMS_POLICY * dest,
1133*758e9fbaSOystein Eftevaag         const TPMS_POLICY * src) {
1134*758e9fbaSOystein Eftevaag     /* Check for NULL references */
1135*758e9fbaSOystein Eftevaag     if (dest == NULL || src == NULL) {
1136*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_MEMORY;
1137*758e9fbaSOystein Eftevaag     }
1138*758e9fbaSOystein Eftevaag 
1139*758e9fbaSOystein Eftevaag     TSS2_RC r = TSS2_RC_SUCCESS;
1140*758e9fbaSOystein Eftevaag     dest->description = NULL;
1141*758e9fbaSOystein Eftevaag     strdup_check(dest->description, src->description, r, error_cleanup);
1142*758e9fbaSOystein Eftevaag     dest->policy = copy_policy_elements(src->policy);
1143*758e9fbaSOystein Eftevaag     goto_if_null2(dest->policy, "Out of memory", r, TSS2_FAPI_RC_MEMORY,
1144*758e9fbaSOystein Eftevaag             error_cleanup);
1145*758e9fbaSOystein Eftevaag 
1146*758e9fbaSOystein Eftevaag     return r;
1147*758e9fbaSOystein Eftevaag error_cleanup:
1148*758e9fbaSOystein Eftevaag     ifapi_cleanup_policy(dest);
1149*758e9fbaSOystein Eftevaag     return r;
1150*758e9fbaSOystein Eftevaag }
1151*758e9fbaSOystein Eftevaag 
1152*758e9fbaSOystein Eftevaag /** Copy policy object.
1153*758e9fbaSOystein Eftevaag  *
1154*758e9fbaSOystein Eftevaag  * @param[in] src The policy object to be copied.
1155*758e9fbaSOystein Eftevaag  * @param[out] dest The destination policy object.
1156*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
1157*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1158*758e9fbaSOystein Eftevaag  */
1159*758e9fbaSOystein Eftevaag static TSS2_RC
copy_policy_object(POLICY_OBJECT * dest,const POLICY_OBJECT * src)1160*758e9fbaSOystein Eftevaag copy_policy_object(POLICY_OBJECT * dest, const POLICY_OBJECT * src) {
1161*758e9fbaSOystein Eftevaag     /* Check for NULL references */
1162*758e9fbaSOystein Eftevaag     if (dest == NULL || src == NULL) {
1163*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_MEMORY;
1164*758e9fbaSOystein Eftevaag     }
1165*758e9fbaSOystein Eftevaag 
1166*758e9fbaSOystein Eftevaag     TSS2_RC r = TSS2_RC_SUCCESS;
1167*758e9fbaSOystein Eftevaag     dest->policy.description = NULL;
1168*758e9fbaSOystein Eftevaag     dest->policy.policyAuthorizations = NULL;
1169*758e9fbaSOystein Eftevaag     dest->policy.policy = NULL;
1170*758e9fbaSOystein Eftevaag     strdup_check(dest->path, src->path, r, error_cleanup);
1171*758e9fbaSOystein Eftevaag     r = copy_policy(&dest->policy, &src->policy);
1172*758e9fbaSOystein Eftevaag     goto_if_error(r, "Could not copy policy", error_cleanup);
1173*758e9fbaSOystein Eftevaag     if (src->next != NULL) {
1174*758e9fbaSOystein Eftevaag         dest->next = malloc(sizeof(POLICY_OBJECT));
1175*758e9fbaSOystein Eftevaag         goto_if_null(dest->next, "Out of memory", r, error_cleanup);
1176*758e9fbaSOystein Eftevaag         dest->next->next = NULL;
1177*758e9fbaSOystein Eftevaag         r = copy_policy_object(dest->next, src->next);
1178*758e9fbaSOystein Eftevaag         goto_if_error(r, "Could not copy next policy object", error_cleanup);
1179*758e9fbaSOystein Eftevaag     }
1180*758e9fbaSOystein Eftevaag 
1181*758e9fbaSOystein Eftevaag     return r;
1182*758e9fbaSOystein Eftevaag error_cleanup:
1183*758e9fbaSOystein Eftevaag     cleanup_policy_object(dest);
1184*758e9fbaSOystein Eftevaag     return r;
1185*758e9fbaSOystein Eftevaag }
1186*758e9fbaSOystein Eftevaag 
1187*758e9fbaSOystein Eftevaag /** Copy policy authorization.
1188*758e9fbaSOystein Eftevaag  *
1189*758e9fbaSOystein Eftevaag  * @param[in] src The policy authorization to be copied.
1190*758e9fbaSOystein Eftevaag  * @param[out] dest The destination policy authorization.
1191*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
1192*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1193*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1194*758e9fbaSOystein Eftevaag  */
1195*758e9fbaSOystein Eftevaag static TSS2_RC
copy_policyauthorization(TPMS_POLICYAUTHORIZATION * dest,const TPMS_POLICYAUTHORIZATION * src)1196*758e9fbaSOystein Eftevaag copy_policyauthorization(TPMS_POLICYAUTHORIZATION * dest,
1197*758e9fbaSOystein Eftevaag         const TPMS_POLICYAUTHORIZATION * src) {
1198*758e9fbaSOystein Eftevaag     if (dest == NULL || src == NULL) {
1199*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_BAD_REFERENCE;
1200*758e9fbaSOystein Eftevaag     }
1201*758e9fbaSOystein Eftevaag     TSS2_RC r = TSS2_RC_SUCCESS;
1202*758e9fbaSOystein Eftevaag     strdup_check(dest->type, src->type, r, error_cleanup);
1203*758e9fbaSOystein Eftevaag 
1204*758e9fbaSOystein Eftevaag     dest->key = src->key;
1205*758e9fbaSOystein Eftevaag     dest->policyRef = src->policyRef;
1206*758e9fbaSOystein Eftevaag     dest->signature = src->signature;
1207*758e9fbaSOystein Eftevaag 
1208*758e9fbaSOystein Eftevaag     return r;
1209*758e9fbaSOystein Eftevaag error_cleanup:
1210*758e9fbaSOystein Eftevaag     SAFE_FREE(dest->type);
1211*758e9fbaSOystein Eftevaag     return r;
1212*758e9fbaSOystein Eftevaag }
1213*758e9fbaSOystein Eftevaag 
1214*758e9fbaSOystein Eftevaag /** Copy policy branches.
1215*758e9fbaSOystein Eftevaag  *
1216*758e9fbaSOystein Eftevaag  * @param[in] src The policy branches to be copied.
1217*758e9fbaSOystein Eftevaag  * @param[out] dest The destination policy branches.
1218*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
1219*758e9fbaSOystein Eftevaag  */
1220*758e9fbaSOystein Eftevaag static TPML_POLICYBRANCHES *
copy_policy_branches(const TPML_POLICYBRANCHES * from_branches)1221*758e9fbaSOystein Eftevaag copy_policy_branches(const TPML_POLICYBRANCHES *from_branches)
1222*758e9fbaSOystein Eftevaag {
1223*758e9fbaSOystein Eftevaag     TPML_POLICYBRANCHES *to_branches;
1224*758e9fbaSOystein Eftevaag     size_t j;
1225*758e9fbaSOystein Eftevaag 
1226*758e9fbaSOystein Eftevaag     to_branches = calloc(1, sizeof(TPML_POLICYBRANCHES) +
1227*758e9fbaSOystein Eftevaag                          from_branches->count * sizeof(TPMS_POLICYBRANCH));
1228*758e9fbaSOystein Eftevaag     if (!to_branches)
1229*758e9fbaSOystein Eftevaag         return NULL;
1230*758e9fbaSOystein Eftevaag     to_branches->count = from_branches->count;
1231*758e9fbaSOystein Eftevaag     for (j = 0; j < from_branches->count; j++) {
1232*758e9fbaSOystein Eftevaag         to_branches->authorizations[j].name = strdup(from_branches->authorizations[j].name);
1233*758e9fbaSOystein Eftevaag         if (!to_branches->authorizations[j].name)
1234*758e9fbaSOystein Eftevaag             goto error;
1235*758e9fbaSOystein Eftevaag         to_branches->authorizations[j].description =
1236*758e9fbaSOystein Eftevaag             strdup(from_branches->authorizations[j].description);
1237*758e9fbaSOystein Eftevaag         if (!to_branches->authorizations[j].description)
1238*758e9fbaSOystein Eftevaag             goto error;
1239*758e9fbaSOystein Eftevaag         to_branches->authorizations[j].policy =
1240*758e9fbaSOystein Eftevaag             copy_policy_elements(from_branches->authorizations[j].policy);
1241*758e9fbaSOystein Eftevaag         if (to_branches->authorizations[j].policy == NULL
1242*758e9fbaSOystein Eftevaag             && from_branches->authorizations[j].policy != NULL) {
1243*758e9fbaSOystein Eftevaag             LOG_ERROR("Out of memory.");
1244*758e9fbaSOystein Eftevaag             goto error;
1245*758e9fbaSOystein Eftevaag         }
1246*758e9fbaSOystein Eftevaag         to_branches->authorizations[j].policyDigests =
1247*758e9fbaSOystein Eftevaag             from_branches->authorizations[j].policyDigests;
1248*758e9fbaSOystein Eftevaag     }
1249*758e9fbaSOystein Eftevaag     return to_branches;
1250*758e9fbaSOystein Eftevaag 
1251*758e9fbaSOystein Eftevaag error:
1252*758e9fbaSOystein Eftevaag     for (j = 0; j < to_branches->count; j++) {
1253*758e9fbaSOystein Eftevaag         SAFE_FREE(to_branches->authorizations[j].name);
1254*758e9fbaSOystein Eftevaag         SAFE_FREE(to_branches->authorizations[j].description);
1255*758e9fbaSOystein Eftevaag         cleanup_policy_elements(to_branches->authorizations[j].policy);
1256*758e9fbaSOystein Eftevaag     }
1257*758e9fbaSOystein Eftevaag     SAFE_FREE(to_branches);
1258*758e9fbaSOystein Eftevaag     return NULL;
1259*758e9fbaSOystein Eftevaag }
1260*758e9fbaSOystein Eftevaag 
1261*758e9fbaSOystein Eftevaag /** Create a copy of a policy element.
1262*758e9fbaSOystein Eftevaag  *
1263*758e9fbaSOystein Eftevaag  * Depending on the type of a poliy element a copy with newly allocated memory will be
1264*758e9fbaSOystein Eftevaag  * created.
1265*758e9fbaSOystein Eftevaag  *
1266*758e9fbaSOystein Eftevaag  * @param[in]  from_policy The policy to be copied.
1267*758e9fbaSOystein Eftevaag  * @param[out] to_policy The new policy element.
1268*758e9fbaSOystein Eftevaag  *
1269*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS: if copying was successful.
1270*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE: If no from policy or no to policy was passed.
1271*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY: If not enough memory can be allocated.
1272*758e9fbaSOystein Eftevaag  */
1273*758e9fbaSOystein Eftevaag static TSS2_RC
copy_policy_element(const TPMT_POLICYELEMENT * from_policy,TPMT_POLICYELEMENT * to_policy)1274*758e9fbaSOystein Eftevaag copy_policy_element(const TPMT_POLICYELEMENT *from_policy, TPMT_POLICYELEMENT *to_policy)
1275*758e9fbaSOystein Eftevaag {
1276*758e9fbaSOystein Eftevaag     if (from_policy == NULL || to_policy == NULL) {
1277*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_BAD_REFERENCE;
1278*758e9fbaSOystein Eftevaag     }
1279*758e9fbaSOystein Eftevaag     TSS2_RC r = TSS2_RC_SUCCESS;
1280*758e9fbaSOystein Eftevaag 
1281*758e9fbaSOystein Eftevaag     *to_policy = *from_policy;
1282*758e9fbaSOystein Eftevaag     size_t i;
1283*758e9fbaSOystein Eftevaag 
1284*758e9fbaSOystein Eftevaag     switch (from_policy->type) {
1285*758e9fbaSOystein Eftevaag     case POLICYSECRET:
1286*758e9fbaSOystein Eftevaag         strdup_check(to_policy->element.PolicySecret.objectPath,
1287*758e9fbaSOystein Eftevaag                      from_policy->element.PolicySecret.objectPath, r, error);
1288*758e9fbaSOystein Eftevaag         break;
1289*758e9fbaSOystein Eftevaag     case POLICYAUTHORIZE:
1290*758e9fbaSOystein Eftevaag         strdup_check(to_policy->element.PolicyAuthorize.keyPath,
1291*758e9fbaSOystein Eftevaag                      from_policy->element.PolicyAuthorize.keyPath, r, error);
1292*758e9fbaSOystein Eftevaag         strdup_check(to_policy->element.PolicyAuthorize.keyPEM,
1293*758e9fbaSOystein Eftevaag                      from_policy->element.PolicyAuthorize.keyPEM, r, error);
1294*758e9fbaSOystein Eftevaag         if (from_policy->element.PolicyAuthorize.policy_list) {
1295*758e9fbaSOystein Eftevaag             to_policy->element.PolicyAuthorize.policy_list =
1296*758e9fbaSOystein Eftevaag                 malloc(sizeof(POLICY_OBJECT));
1297*758e9fbaSOystein Eftevaag             goto_if_null2(to_policy->element.PolicyAuthorize.policy_list,
1298*758e9fbaSOystein Eftevaag                           "Out of memory", r, TSS2_FAPI_RC_MEMORY, error);
1299*758e9fbaSOystein Eftevaag             to_policy->element.PolicyAuthorize.policy_list->next = NULL;
1300*758e9fbaSOystein Eftevaag             r = copy_policy_object(to_policy->element.PolicyAuthorize.policy_list,
1301*758e9fbaSOystein Eftevaag                                    from_policy->element.PolicyAuthorize.policy_list);
1302*758e9fbaSOystein Eftevaag             goto_if_error(r, "Could not copy policy list", error);
1303*758e9fbaSOystein Eftevaag 
1304*758e9fbaSOystein Eftevaag         }
1305*758e9fbaSOystein Eftevaag         if (from_policy->element.PolicyAuthorize.authorization) {
1306*758e9fbaSOystein Eftevaag             to_policy->element.PolicyAuthorize.authorization =
1307*758e9fbaSOystein Eftevaag                 malloc(sizeof(TPMS_POLICYAUTHORIZATION));
1308*758e9fbaSOystein Eftevaag             goto_if_null(to_policy->element.PolicyAuthorize.authorization,
1309*758e9fbaSOystein Eftevaag                          "Out of memory", r, error);
1310*758e9fbaSOystein Eftevaag             r = copy_policyauthorization(to_policy->element.PolicyAuthorize.authorization,
1311*758e9fbaSOystein Eftevaag                                          from_policy->element.PolicyAuthorize.authorization);
1312*758e9fbaSOystein Eftevaag             goto_if_error(r, "Could not copy policy authorization", error);
1313*758e9fbaSOystein Eftevaag         }
1314*758e9fbaSOystein Eftevaag         break;
1315*758e9fbaSOystein Eftevaag     case POLICYAUTHORIZENV:
1316*758e9fbaSOystein Eftevaag         strdup_check(to_policy->element.PolicyAuthorizeNv.nvPath,
1317*758e9fbaSOystein Eftevaag                      from_policy->element.PolicyAuthorizeNv.nvPath, r, error);
1318*758e9fbaSOystein Eftevaag         break;
1319*758e9fbaSOystein Eftevaag     case POLICYSIGNED:
1320*758e9fbaSOystein Eftevaag         strdup_check(to_policy->element.PolicySigned.keyPath,
1321*758e9fbaSOystein Eftevaag                      from_policy->element.PolicySigned.keyPath, r, error);
1322*758e9fbaSOystein Eftevaag         strdup_check(to_policy->element.PolicySigned.keyPEM,
1323*758e9fbaSOystein Eftevaag                      from_policy->element.PolicySigned.keyPEM, r, error);
1324*758e9fbaSOystein Eftevaag         strdup_check(to_policy->element.PolicySigned.publicKeyHint,
1325*758e9fbaSOystein Eftevaag                      from_policy->element.PolicySigned.publicKeyHint, r, error);
1326*758e9fbaSOystein Eftevaag         break;
1327*758e9fbaSOystein Eftevaag     case POLICYPCR:
1328*758e9fbaSOystein Eftevaag         to_policy->element.PolicyPCR.pcrs =
1329*758e9fbaSOystein Eftevaag             calloc(1, sizeof(TPML_PCRVALUES) +
1330*758e9fbaSOystein Eftevaag                    from_policy->element.PolicyPCR.pcrs->count + sizeof(TPMS_PCRVALUE));
1331*758e9fbaSOystein Eftevaag         goto_if_null2(to_policy->element.PolicyPCR.pcrs, "Out of memory.",
1332*758e9fbaSOystein Eftevaag                       r, TSS2_FAPI_RC_MEMORY, error);
1333*758e9fbaSOystein Eftevaag         to_policy->element.PolicyPCR.pcrs->count
1334*758e9fbaSOystein Eftevaag             = from_policy->element.PolicyPCR.pcrs->count;
1335*758e9fbaSOystein Eftevaag         for (i = 0; i < to_policy->element.PolicyPCR.pcrs->count; i++)
1336*758e9fbaSOystein Eftevaag             to_policy->element.PolicyPCR.pcrs->pcrs[i]
1337*758e9fbaSOystein Eftevaag                 = from_policy->element.PolicyPCR.pcrs->pcrs[i];
1338*758e9fbaSOystein Eftevaag         break;
1339*758e9fbaSOystein Eftevaag     case POLICYNV:
1340*758e9fbaSOystein Eftevaag         strdup_check(to_policy->element.PolicyNV.nvPath,
1341*758e9fbaSOystein Eftevaag                      from_policy->element.PolicyNV.nvPath, r, error);
1342*758e9fbaSOystein Eftevaag         break;
1343*758e9fbaSOystein Eftevaag     case POLICYDUPLICATIONSELECT:
1344*758e9fbaSOystein Eftevaag         strdup_check(to_policy->element.PolicyDuplicationSelect.newParentPath,
1345*758e9fbaSOystein Eftevaag                      from_policy->element.PolicyDuplicationSelect.newParentPath,
1346*758e9fbaSOystein Eftevaag                      r, error);
1347*758e9fbaSOystein Eftevaag         break;
1348*758e9fbaSOystein Eftevaag     case POLICYNAMEHASH:
1349*758e9fbaSOystein Eftevaag         for (size_t i = 0; i < from_policy->element.PolicyNameHash.count; i++) {
1350*758e9fbaSOystein Eftevaag             strdup_check(to_policy->element.PolicyNameHash.namePaths[i],
1351*758e9fbaSOystein Eftevaag                     from_policy->element.PolicyNameHash.namePaths[i],
1352*758e9fbaSOystein Eftevaag                     r, error);
1353*758e9fbaSOystein Eftevaag         }
1354*758e9fbaSOystein Eftevaag         break;
1355*758e9fbaSOystein Eftevaag     case POLICYOR:
1356*758e9fbaSOystein Eftevaag         to_policy->element.PolicyOr.branches =
1357*758e9fbaSOystein Eftevaag             copy_policy_branches(from_policy->element.PolicyOr.branches);
1358*758e9fbaSOystein Eftevaag         goto_if_null2(to_policy->element.PolicyOr.branches, "Out of memory",
1359*758e9fbaSOystein Eftevaag                       r, TSS2_FAPI_RC_MEMORY, error);
1360*758e9fbaSOystein Eftevaag         break;
1361*758e9fbaSOystein Eftevaag     }
1362*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
1363*758e9fbaSOystein Eftevaag 
1364*758e9fbaSOystein Eftevaag error:
1365*758e9fbaSOystein Eftevaag     return r;
1366*758e9fbaSOystein Eftevaag }
1367*758e9fbaSOystein Eftevaag 
1368*758e9fbaSOystein Eftevaag /** Copy a list of policy elements
1369*758e9fbaSOystein Eftevaag  *
1370*758e9fbaSOystein Eftevaag  * @param[in] form_policy The policy list to be copied.
1371*758e9fbaSOystein Eftevaag  * @retval NULL If the policy cannot be copied.
1372*758e9fbaSOystein Eftevaag  * @retval TPML_POLICYELEMENTS The copy of the policy list.
1373*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1374*758e9fbaSOystein Eftevaag  */
1375*758e9fbaSOystein Eftevaag static TPML_POLICYELEMENTS *
copy_policy_elements(const TPML_POLICYELEMENTS * from_policy)1376*758e9fbaSOystein Eftevaag copy_policy_elements(const TPML_POLICYELEMENTS *from_policy)
1377*758e9fbaSOystein Eftevaag {
1378*758e9fbaSOystein Eftevaag     if (from_policy == NULL) {
1379*758e9fbaSOystein Eftevaag         return NULL;
1380*758e9fbaSOystein Eftevaag     }
1381*758e9fbaSOystein Eftevaag     TSS2_RC r;
1382*758e9fbaSOystein Eftevaag     size_t i;
1383*758e9fbaSOystein Eftevaag     TPML_POLICYELEMENTS *to_policy = NULL;
1384*758e9fbaSOystein Eftevaag 
1385*758e9fbaSOystein Eftevaag     to_policy = calloc(1, sizeof(TPML_POLICYELEMENTS) +
1386*758e9fbaSOystein Eftevaag                        from_policy->count * sizeof(TPMT_POLICYELEMENT));
1387*758e9fbaSOystein Eftevaag     to_policy->count = from_policy->count;
1388*758e9fbaSOystein Eftevaag     for (i = 0; i < from_policy->count; i++) {
1389*758e9fbaSOystein Eftevaag         if (from_policy->elements[i].type == POLICYOR) {
1390*758e9fbaSOystein Eftevaag             to_policy->elements[i].type = POLICYOR;
1391*758e9fbaSOystein Eftevaag             /* Policy with sub policies */
1392*758e9fbaSOystein Eftevaag             TPML_POLICYBRANCHES *branches = from_policy->elements[i].element.PolicyOr.branches;
1393*758e9fbaSOystein Eftevaag             to_policy->elements[i].element.PolicyOr.branches = copy_policy_branches(branches);
1394*758e9fbaSOystein Eftevaag             if (to_policy->elements[i].element.PolicyOr.branches == NULL) {
1395*758e9fbaSOystein Eftevaag                 LOG_ERROR("Out of memory");
1396*758e9fbaSOystein Eftevaag                 SAFE_FREE(to_policy);
1397*758e9fbaSOystein Eftevaag                 return NULL;
1398*758e9fbaSOystein Eftevaag             }
1399*758e9fbaSOystein Eftevaag         } else {
1400*758e9fbaSOystein Eftevaag             r = copy_policy_element(&from_policy->elements[i], &to_policy->elements[i]);
1401*758e9fbaSOystein Eftevaag             if (r != TSS2_RC_SUCCESS) {
1402*758e9fbaSOystein Eftevaag                 cleanup_policy_elements(to_policy);
1403*758e9fbaSOystein Eftevaag                 return NULL;
1404*758e9fbaSOystein Eftevaag             }
1405*758e9fbaSOystein Eftevaag         }
1406*758e9fbaSOystein Eftevaag     }
1407*758e9fbaSOystein Eftevaag     return to_policy;
1408*758e9fbaSOystein Eftevaag }
1409*758e9fbaSOystein Eftevaag 
1410*758e9fbaSOystein Eftevaag /** Copy policy.
1411*758e9fbaSOystein Eftevaag  *
1412*758e9fbaSOystein Eftevaag  * @param[in] from_policy the policy to be copied.
1413*758e9fbaSOystein Eftevaag  * @retval The new policy or NULL if not enough memory was available.
1414*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1415*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1416*758e9fbaSOystein Eftevaag  */
1417*758e9fbaSOystein Eftevaag TPMS_POLICY *
ifapi_copy_policy(const TPMS_POLICY * from_policy)1418*758e9fbaSOystein Eftevaag ifapi_copy_policy(
1419*758e9fbaSOystein Eftevaag     const TPMS_POLICY *from_policy)
1420*758e9fbaSOystein Eftevaag {
1421*758e9fbaSOystein Eftevaag     if (from_policy == NULL) {
1422*758e9fbaSOystein Eftevaag         return NULL;
1423*758e9fbaSOystein Eftevaag     }
1424*758e9fbaSOystein Eftevaag     TPMS_POLICY *to_policy = calloc(1, sizeof(TPMS_POLICY));
1425*758e9fbaSOystein Eftevaag     if (to_policy == NULL) {
1426*758e9fbaSOystein Eftevaag         return NULL;
1427*758e9fbaSOystein Eftevaag     }
1428*758e9fbaSOystein Eftevaag     to_policy->description = NULL;
1429*758e9fbaSOystein Eftevaag     TSS2_RC r = copy_policy(to_policy, from_policy);
1430*758e9fbaSOystein Eftevaag     if (r != TSS2_RC_SUCCESS) {
1431*758e9fbaSOystein Eftevaag         SAFE_FREE(to_policy);
1432*758e9fbaSOystein Eftevaag         return NULL;
1433*758e9fbaSOystein Eftevaag     } else {
1434*758e9fbaSOystein Eftevaag         return to_policy;
1435*758e9fbaSOystein Eftevaag     }
1436*758e9fbaSOystein Eftevaag }
1437*758e9fbaSOystein Eftevaag 
1438*758e9fbaSOystein Eftevaag /** Compute the name of a TPM transient or persistent object.
1439*758e9fbaSOystein Eftevaag  *
1440*758e9fbaSOystein Eftevaag  * @param[in] publicInfo The public information of the TPM object.
1441*758e9fbaSOystein Eftevaag  * @param[out] name The computed name.
1442*758e9fbaSOystein Eftevaag  * @retval TPM2_RC_SUCCESS  or one of the possible errors TSS2_FAPI_RC_BAD_VALUE,
1443*758e9fbaSOystein Eftevaag  * TSS2_FAPI_RC_MEMORY, TSS2_FAPI_RC_GENERAL_FAILURE.
1444*758e9fbaSOystein Eftevaag  * or return codes of SAPI errors.
1445*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1446*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1447*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
1448*758e9fbaSOystein Eftevaag  *         the function.
1449*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
1450*758e9fbaSOystein Eftevaag  */
1451*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_get_name(TPMT_PUBLIC * publicInfo,TPM2B_NAME * name)1452*758e9fbaSOystein Eftevaag ifapi_get_name(TPMT_PUBLIC *publicInfo, TPM2B_NAME *name)
1453*758e9fbaSOystein Eftevaag {
1454*758e9fbaSOystein Eftevaag     BYTE buffer[sizeof(TPMT_PUBLIC)];
1455*758e9fbaSOystein Eftevaag     size_t offset = 0;
1456*758e9fbaSOystein Eftevaag     size_t len_alg_id = sizeof(TPMI_ALG_HASH);
1457*758e9fbaSOystein Eftevaag     size_t size = sizeof(TPMU_NAME) - sizeof(TPMI_ALG_HASH);
1458*758e9fbaSOystein Eftevaag     IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext;
1459*758e9fbaSOystein Eftevaag 
1460*758e9fbaSOystein Eftevaag     if (publicInfo->nameAlg == TPM2_ALG_NULL) {
1461*758e9fbaSOystein Eftevaag         name->size = 0;
1462*758e9fbaSOystein Eftevaag         return TSS2_RC_SUCCESS;
1463*758e9fbaSOystein Eftevaag     }
1464*758e9fbaSOystein Eftevaag     TSS2_RC r;
1465*758e9fbaSOystein Eftevaag     r = ifapi_crypto_hash_start(&cryptoContext, publicInfo->nameAlg);
1466*758e9fbaSOystein Eftevaag     return_if_error(r, "crypto hash start");
1467*758e9fbaSOystein Eftevaag 
1468*758e9fbaSOystein Eftevaag     r = Tss2_MU_TPMT_PUBLIC_Marshal(publicInfo,
1469*758e9fbaSOystein Eftevaag                                     &buffer[0], sizeof(TPMT_PUBLIC), &offset);
1470*758e9fbaSOystein Eftevaag     if (r) {
1471*758e9fbaSOystein Eftevaag         LOG_ERROR("Marshaling TPMT_PUBLIC");
1472*758e9fbaSOystein Eftevaag         ifapi_crypto_hash_abort(&cryptoContext);
1473*758e9fbaSOystein Eftevaag         return r;
1474*758e9fbaSOystein Eftevaag     }
1475*758e9fbaSOystein Eftevaag 
1476*758e9fbaSOystein Eftevaag     r = ifapi_crypto_hash_update(cryptoContext, &buffer[0], offset);
1477*758e9fbaSOystein Eftevaag     if (r) {
1478*758e9fbaSOystein Eftevaag         LOG_ERROR("crypto hash update");
1479*758e9fbaSOystein Eftevaag         ifapi_crypto_hash_abort(&cryptoContext);
1480*758e9fbaSOystein Eftevaag         return r;
1481*758e9fbaSOystein Eftevaag     }
1482*758e9fbaSOystein Eftevaag 
1483*758e9fbaSOystein Eftevaag     r = ifapi_crypto_hash_finish(&cryptoContext, &name->name[len_alg_id],
1484*758e9fbaSOystein Eftevaag                                  &size);
1485*758e9fbaSOystein Eftevaag     if (r) {
1486*758e9fbaSOystein Eftevaag         LOG_ERROR("crypto hash finish");
1487*758e9fbaSOystein Eftevaag         ifapi_crypto_hash_abort(&cryptoContext);
1488*758e9fbaSOystein Eftevaag         return r;
1489*758e9fbaSOystein Eftevaag     }
1490*758e9fbaSOystein Eftevaag 
1491*758e9fbaSOystein Eftevaag     offset = 0;
1492*758e9fbaSOystein Eftevaag     r = Tss2_MU_TPMI_ALG_HASH_Marshal(publicInfo->nameAlg,
1493*758e9fbaSOystein Eftevaag                                       &name->name[0], sizeof(TPMI_ALG_HASH),
1494*758e9fbaSOystein Eftevaag                                       &offset);
1495*758e9fbaSOystein Eftevaag     return_if_error(r, "Marshaling TPMI_ALG_HASH");
1496*758e9fbaSOystein Eftevaag 
1497*758e9fbaSOystein Eftevaag     name->size = size + len_alg_id;
1498*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
1499*758e9fbaSOystein Eftevaag }
1500*758e9fbaSOystein Eftevaag 
1501*758e9fbaSOystein Eftevaag /** Compute the name from the public data of a NV index.
1502*758e9fbaSOystein Eftevaag  *
1503*758e9fbaSOystein Eftevaag  * The name of a NV index is computed as follows:
1504*758e9fbaSOystein Eftevaag  *   name = nameAlg||Hash(nameAlg,marshal(publicArea))
1505*758e9fbaSOystein Eftevaag  * @param[in] publicInfo The public information of the NV index.
1506*758e9fbaSOystein Eftevaag  * @param[out] name The computed name.
1507*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS on success.
1508*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY Memory can not be allocated.
1509*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE for invalid parameters.
1510*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE for unexpected NULL pointer parameters.
1511*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE for errors of the crypto library.
1512*758e9fbaSOystein Eftevaag  * @retval TSS2_SYS_RC_* for SAPI errors.
1513*758e9fbaSOystein Eftevaag  */
1514*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_nv_get_name(TPM2B_NV_PUBLIC * publicInfo,TPM2B_NAME * name)1515*758e9fbaSOystein Eftevaag ifapi_nv_get_name(TPM2B_NV_PUBLIC *publicInfo, TPM2B_NAME *name)
1516*758e9fbaSOystein Eftevaag {
1517*758e9fbaSOystein Eftevaag     BYTE buffer[sizeof(TPMS_NV_PUBLIC)];
1518*758e9fbaSOystein Eftevaag     size_t offset = 0;
1519*758e9fbaSOystein Eftevaag     size_t size = sizeof(TPMU_NAME) - sizeof(TPMI_ALG_HASH);
1520*758e9fbaSOystein Eftevaag     size_t len_alg_id = sizeof(TPMI_ALG_HASH);
1521*758e9fbaSOystein Eftevaag     IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext;
1522*758e9fbaSOystein Eftevaag 
1523*758e9fbaSOystein Eftevaag     if (publicInfo->nvPublic.nameAlg == TPM2_ALG_NULL) {
1524*758e9fbaSOystein Eftevaag         name->size = 0;
1525*758e9fbaSOystein Eftevaag         return TSS2_RC_SUCCESS;
1526*758e9fbaSOystein Eftevaag     }
1527*758e9fbaSOystein Eftevaag     TSS2_RC r;
1528*758e9fbaSOystein Eftevaag 
1529*758e9fbaSOystein Eftevaag     /* Initialize the hash computation with the nameAlg. */
1530*758e9fbaSOystein Eftevaag     r = ifapi_crypto_hash_start(&cryptoContext, publicInfo->nvPublic.nameAlg);
1531*758e9fbaSOystein Eftevaag     return_if_error(r, "Crypto hash start");
1532*758e9fbaSOystein Eftevaag 
1533*758e9fbaSOystein Eftevaag     /* Get the marshaled data of the public area. */
1534*758e9fbaSOystein Eftevaag     r = Tss2_MU_TPMS_NV_PUBLIC_Marshal(&publicInfo->nvPublic,
1535*758e9fbaSOystein Eftevaag                                        &buffer[0], sizeof(TPMS_NV_PUBLIC),
1536*758e9fbaSOystein Eftevaag                                        &offset);
1537*758e9fbaSOystein Eftevaag     if (r) {
1538*758e9fbaSOystein Eftevaag         LOG_ERROR("Marshaling TPMS_NV_PUBLIC");
1539*758e9fbaSOystein Eftevaag         ifapi_crypto_hash_abort(&cryptoContext);
1540*758e9fbaSOystein Eftevaag         return r;
1541*758e9fbaSOystein Eftevaag     }
1542*758e9fbaSOystein Eftevaag 
1543*758e9fbaSOystein Eftevaag     r = ifapi_crypto_hash_update(cryptoContext, &buffer[0], offset);
1544*758e9fbaSOystein Eftevaag     if (r) {
1545*758e9fbaSOystein Eftevaag         LOG_ERROR("crypto hash update");
1546*758e9fbaSOystein Eftevaag         ifapi_crypto_hash_abort(&cryptoContext);
1547*758e9fbaSOystein Eftevaag         return r;
1548*758e9fbaSOystein Eftevaag     }
1549*758e9fbaSOystein Eftevaag 
1550*758e9fbaSOystein Eftevaag     /* The hash will be stored after the nameAlg.*/
1551*758e9fbaSOystein Eftevaag     r = ifapi_crypto_hash_finish(&cryptoContext, &name->name[len_alg_id],
1552*758e9fbaSOystein Eftevaag                                  &size);
1553*758e9fbaSOystein Eftevaag     if (r) {
1554*758e9fbaSOystein Eftevaag         LOG_ERROR("crypto hash finish");
1555*758e9fbaSOystein Eftevaag         ifapi_crypto_hash_abort(&cryptoContext);
1556*758e9fbaSOystein Eftevaag         return r;
1557*758e9fbaSOystein Eftevaag     }
1558*758e9fbaSOystein Eftevaag 
1559*758e9fbaSOystein Eftevaag     offset = 0;
1560*758e9fbaSOystein Eftevaag     /* Store the nameAlg in the result. */
1561*758e9fbaSOystein Eftevaag     r = Tss2_MU_TPMI_ALG_HASH_Marshal(publicInfo->nvPublic.nameAlg,
1562*758e9fbaSOystein Eftevaag                                       &name->name[0], sizeof(TPMI_ALG_HASH),
1563*758e9fbaSOystein Eftevaag                                       &offset);
1564*758e9fbaSOystein Eftevaag     return_if_error(r, "Marshaling TPMI_ALG_HASH");
1565*758e9fbaSOystein Eftevaag 
1566*758e9fbaSOystein Eftevaag     name->size = size + len_alg_id;
1567*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
1568*758e9fbaSOystein Eftevaag }
1569*758e9fbaSOystein Eftevaag 
1570*758e9fbaSOystein Eftevaag /** Check whether a nv or key object has a certain name.
1571*758e9fbaSOystein Eftevaag  *
1572*758e9fbaSOystein Eftevaag  * @param[in] object The object (has to be checked whether it's a key).
1573*758e9fbaSOystein Eftevaag  * @param[in] name The name to be compared.
1574*758e9fbaSOystein Eftevaag  * @param[out] equal If the two names are equal.
1575*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESSS if name of object can be deserialized.
1576*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1577*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1578*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
1579*758e9fbaSOystein Eftevaag  *         the function.
1580*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
1581*758e9fbaSOystein Eftevaag  */
1582*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_object_cmp_name(IFAPI_OBJECT * object,void * name,bool * equal)1583*758e9fbaSOystein Eftevaag ifapi_object_cmp_name(IFAPI_OBJECT *object, void *name, bool *equal)
1584*758e9fbaSOystein Eftevaag {
1585*758e9fbaSOystein Eftevaag     TSS2_RC r;
1586*758e9fbaSOystein Eftevaag     *equal = false;
1587*758e9fbaSOystein Eftevaag     TPM2B_NAME *obj_name;
1588*758e9fbaSOystein Eftevaag     TPM2B_NAME nv_name;
1589*758e9fbaSOystein Eftevaag 
1590*758e9fbaSOystein Eftevaag     switch (object->objectType) {
1591*758e9fbaSOystein Eftevaag     case IFAPI_KEY_OBJ:
1592*758e9fbaSOystein Eftevaag         obj_name = &object->misc.key.name;
1593*758e9fbaSOystein Eftevaag         break;
1594*758e9fbaSOystein Eftevaag     case IFAPI_NV_OBJ:
1595*758e9fbaSOystein Eftevaag         r = ifapi_nv_get_name(&object->misc.nv.public, &nv_name);
1596*758e9fbaSOystein Eftevaag         return_if_error(r, "Get NV name.");
1597*758e9fbaSOystein Eftevaag 
1598*758e9fbaSOystein Eftevaag         obj_name = &nv_name;
1599*758e9fbaSOystein Eftevaag         break;
1600*758e9fbaSOystein Eftevaag     default:
1601*758e9fbaSOystein Eftevaag         return TSS2_RC_SUCCESS;
1602*758e9fbaSOystein Eftevaag     }
1603*758e9fbaSOystein Eftevaag     if (obj_name->size != ((TPM2B_NAME *)name)->size)
1604*758e9fbaSOystein Eftevaag         return TSS2_RC_SUCCESS;
1605*758e9fbaSOystein Eftevaag     if (memcmp(&obj_name->name[0], &((TPM2B_NAME *)name)->name[0], obj_name->size))
1606*758e9fbaSOystein Eftevaag         /* The names are not equal */
1607*758e9fbaSOystein Eftevaag         return TSS2_RC_SUCCESS;
1608*758e9fbaSOystein Eftevaag     /* The two names are equal */
1609*758e9fbaSOystein Eftevaag     *equal = true;
1610*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
1611*758e9fbaSOystein Eftevaag }
1612*758e9fbaSOystein Eftevaag 
1613*758e9fbaSOystein Eftevaag /** Check whether a nv object has a certain public info.
1614*758e9fbaSOystein Eftevaag  *
1615*758e9fbaSOystein Eftevaag  * @param[in] object The object (has to be checked whether it's a key).
1616*758e9fbaSOystein Eftevaag  * @param[in] nv_public The NV public data with the NV index.
1617*758e9fbaSOystein Eftevaag  * @param[out] equal If the two names are equal.
1618*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESSS if name of object can be deserialized.
1619*758e9fbaSOystein Eftevaag  */
1620*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_object_cmp_nv_public(IFAPI_OBJECT * object,void * nv_public,bool * equal)1621*758e9fbaSOystein Eftevaag ifapi_object_cmp_nv_public(IFAPI_OBJECT *object, void *nv_public, bool *equal)
1622*758e9fbaSOystein Eftevaag {
1623*758e9fbaSOystein Eftevaag     *equal = false;
1624*758e9fbaSOystein Eftevaag 
1625*758e9fbaSOystein Eftevaag     switch (object->objectType) {
1626*758e9fbaSOystein Eftevaag         break;
1627*758e9fbaSOystein Eftevaag     case IFAPI_NV_OBJ:
1628*758e9fbaSOystein Eftevaag         if (object->misc.nv.public.nvPublic.nvIndex
1629*758e9fbaSOystein Eftevaag             == ((TPM2B_NV_PUBLIC *)nv_public)->nvPublic.nvIndex)
1630*758e9fbaSOystein Eftevaag             *equal = true;
1631*758e9fbaSOystein Eftevaag         break;
1632*758e9fbaSOystein Eftevaag     default:
1633*758e9fbaSOystein Eftevaag         return TSS2_RC_SUCCESS;
1634*758e9fbaSOystein Eftevaag     }
1635*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
1636*758e9fbaSOystein Eftevaag }
1637*758e9fbaSOystein Eftevaag 
1638*758e9fbaSOystein Eftevaag /** Compute signature as byte array and signature size in DER format.
1639*758e9fbaSOystein Eftevaag  *
1640*758e9fbaSOystein Eftevaag  * For ECC signatures the conversion to DER is necessary, for RSA the
1641*758e9fbaSOystein Eftevaag  * buffer of the TPM2B has already DER format.
1642*758e9fbaSOystein Eftevaag  * parameters.
1643*758e9fbaSOystein Eftevaag  * @param[in] sig_key_object The signing key.
1644*758e9fbaSOystein Eftevaag  * @param[in] tpm_signature the signature in TPM format.
1645*758e9fbaSOystein Eftevaag  * @param[out] signature The byte array of the signature (callee allocated).
1646*758e9fbaSOystein Eftevaag  * @param[out] signatureSize The size of the byte array.
1647*758e9fbaSOystein Eftevaag  *
1648*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESSS if the conversion was successful.
1649*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY: if not enough memory can be allocated.
1650*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE If an internal error occurs, which is
1651*758e9fbaSOystein Eftevaag  *         not covered by other return codes (e.g. a unexpected openssl
1652*758e9fbaSOystein Eftevaag  *         error).
1653*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
1654*758e9fbaSOystein Eftevaag  *         the function.
1655*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1656*758e9fbaSOystein Eftevaag  */
1657*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_tpm_to_fapi_signature(IFAPI_OBJECT * sig_key_object,TPMT_SIGNATURE * tpm_signature,uint8_t ** signature,size_t * signatureSize)1658*758e9fbaSOystein Eftevaag ifapi_tpm_to_fapi_signature(
1659*758e9fbaSOystein Eftevaag     IFAPI_OBJECT *sig_key_object,
1660*758e9fbaSOystein Eftevaag     TPMT_SIGNATURE *tpm_signature,
1661*758e9fbaSOystein Eftevaag     uint8_t **signature,
1662*758e9fbaSOystein Eftevaag     size_t *signatureSize)
1663*758e9fbaSOystein Eftevaag {
1664*758e9fbaSOystein Eftevaag     TSS2_RC r;
1665*758e9fbaSOystein Eftevaag 
1666*758e9fbaSOystein Eftevaag     *signature = NULL;
1667*758e9fbaSOystein Eftevaag     TPMT_SIG_SCHEME *sig_scheme = &sig_key_object->misc.key.signing_scheme;
1668*758e9fbaSOystein Eftevaag 
1669*758e9fbaSOystein Eftevaag     if (sig_key_object->misc.key.public.publicArea.type == TPM2_ALG_RSA) {
1670*758e9fbaSOystein Eftevaag         /* Signature is already in DER format. */
1671*758e9fbaSOystein Eftevaag 
1672*758e9fbaSOystein Eftevaag         if (sig_scheme->scheme == TPM2_ALG_RSAPSS) {
1673*758e9fbaSOystein Eftevaag             *signatureSize = tpm_signature->signature.rsapss.sig.size;
1674*758e9fbaSOystein Eftevaag             *signature = malloc(*signatureSize);
1675*758e9fbaSOystein Eftevaag             goto_if_null(*signature, "Out of memory.", TSS2_FAPI_RC_MEMORY, error_cleanup);
1676*758e9fbaSOystein Eftevaag 
1677*758e9fbaSOystein Eftevaag             memcpy(*signature,
1678*758e9fbaSOystein Eftevaag                    &tpm_signature->signature.rsapss.sig.buffer[0],
1679*758e9fbaSOystein Eftevaag                    *signatureSize);
1680*758e9fbaSOystein Eftevaag         } else if (sig_scheme->scheme == TPM2_ALG_RSASSA) {
1681*758e9fbaSOystein Eftevaag             *signatureSize = tpm_signature->signature.rsassa.sig.size;
1682*758e9fbaSOystein Eftevaag             *signature = malloc(*signatureSize);
1683*758e9fbaSOystein Eftevaag             goto_if_null(*signature, "Out of memory.", TSS2_FAPI_RC_MEMORY, error_cleanup);
1684*758e9fbaSOystein Eftevaag 
1685*758e9fbaSOystein Eftevaag             memcpy(*signature,
1686*758e9fbaSOystein Eftevaag                    &tpm_signature->signature.rsassa.sig.buffer[0],
1687*758e9fbaSOystein Eftevaag                    *signatureSize);
1688*758e9fbaSOystein Eftevaag         }
1689*758e9fbaSOystein Eftevaag     } else if (sig_key_object->misc.key.public.publicArea.type == TPM2_ALG_ECC &&
1690*758e9fbaSOystein Eftevaag                sig_scheme->scheme == TPM2_ALG_ECDSA) {
1691*758e9fbaSOystein Eftevaag         /* For ECC signatures the TPM signaute has to be converted to DER. */
1692*758e9fbaSOystein Eftevaag         r = ifapi_tpm_ecc_sig_to_der(tpm_signature,
1693*758e9fbaSOystein Eftevaag                                      signature, signatureSize);
1694*758e9fbaSOystein Eftevaag         goto_if_error(r, "Conversion to DER failed", error_cleanup);
1695*758e9fbaSOystein Eftevaag     } else {
1696*758e9fbaSOystein Eftevaag         goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Unknown signature scheme", error_cleanup);
1697*758e9fbaSOystein Eftevaag     }
1698*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
1699*758e9fbaSOystein Eftevaag 
1700*758e9fbaSOystein Eftevaag error_cleanup:
1701*758e9fbaSOystein Eftevaag     SAFE_FREE(*signature);
1702*758e9fbaSOystein Eftevaag     return r;
1703*758e9fbaSOystein Eftevaag }
1704*758e9fbaSOystein Eftevaag 
1705*758e9fbaSOystein Eftevaag /** Compute the JSON representation of quote information.
1706*758e9fbaSOystein Eftevaag  *
1707*758e9fbaSOystein Eftevaag  * The attest generated by a TPM quote will be converted into a
1708*758e9fbaSOystein Eftevaag  * JSON representation together with the signature scheme of the
1709*758e9fbaSOystein Eftevaag  * key used for the quote.
1710*758e9fbaSOystein Eftevaag  *
1711*758e9fbaSOystein Eftevaag  * @param[in]  sig_key_object The key object which was used for the quote.
1712*758e9fbaSOystein Eftevaag  * @param[in]  tpm_quoted: The attest produced by the quote.
1713*758e9fbaSOystein Eftevaag  * @param[out] quoteInfo The character string with the JSON representation of the
1714*758e9fbaSOystein Eftevaag  *             attest together with the signing schemed.
1715*758e9fbaSOystein Eftevaag  *
1716*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS: If the conversion was successful.
1717*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY: if not enough memory can be allocated.
1718*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE: If an invalid value is detected during
1719*758e9fbaSOystein Eftevaag  *         serialisation.
1720*758e9fbaSOystein Eftevaag  * @retval Possible error codes of the unmarshaling function.
1721*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
1722*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1723*758e9fbaSOystein Eftevaag  */
1724*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_compute_quote_info(IFAPI_OBJECT * sig_key_object,TPM2B_ATTEST * tpm_quoted,char ** quoteInfo)1725*758e9fbaSOystein Eftevaag ifapi_compute_quote_info(
1726*758e9fbaSOystein Eftevaag     IFAPI_OBJECT *sig_key_object,
1727*758e9fbaSOystein Eftevaag     TPM2B_ATTEST *tpm_quoted,
1728*758e9fbaSOystein Eftevaag     char **quoteInfo)
1729*758e9fbaSOystein Eftevaag {
1730*758e9fbaSOystein Eftevaag     json_object *jso = NULL;
1731*758e9fbaSOystein Eftevaag     TSS2_RC r;
1732*758e9fbaSOystein Eftevaag     size_t offset = 0;
1733*758e9fbaSOystein Eftevaag     TPMS_ATTEST attest_struct;
1734*758e9fbaSOystein Eftevaag     FAPI_QUOTE_INFO fapi_quote_info;
1735*758e9fbaSOystein Eftevaag 
1736*758e9fbaSOystein Eftevaag     /* The TPM2B_ATTEST contains the marshaled TPMS_ATTEST structure. */
1737*758e9fbaSOystein Eftevaag     r = Tss2_MU_TPMS_ATTEST_Unmarshal((const uint8_t *)
1738*758e9fbaSOystein Eftevaag                                       &tpm_quoted->attestationData[0],
1739*758e9fbaSOystein Eftevaag                                       tpm_quoted->size, &offset, &attest_struct);
1740*758e9fbaSOystein Eftevaag     return_if_error(r, "Unmarshal TPMS_ATTEST.");
1741*758e9fbaSOystein Eftevaag 
1742*758e9fbaSOystein Eftevaag     fapi_quote_info.attest = attest_struct;
1743*758e9fbaSOystein Eftevaag     /* The signate scheme will be taken from the key used for qoting. */
1744*758e9fbaSOystein Eftevaag     fapi_quote_info.sig_scheme = sig_key_object->misc.key.signing_scheme;
1745*758e9fbaSOystein Eftevaag     r = ifapi_json_FAPI_QUOTE_INFO_serialize(&fapi_quote_info, &jso);
1746*758e9fbaSOystein Eftevaag     return_if_error(r, "Conversion to TPM2B_ATTEST to JSON.");
1747*758e9fbaSOystein Eftevaag 
1748*758e9fbaSOystein Eftevaag     /* The intermediate structure of type FAPI_QOTE_INFO will be serialized. */
1749*758e9fbaSOystein Eftevaag     const char *quote_json = json_object_to_json_string_ext(jso,
1750*758e9fbaSOystein Eftevaag                              JSON_C_TO_STRING_PRETTY);
1751*758e9fbaSOystein Eftevaag     goto_if_null(quote_json, "Conversion attest to json.",
1752*758e9fbaSOystein Eftevaag                  TSS2_FAPI_RC_GENERAL_FAILURE, cleanup);
1753*758e9fbaSOystein Eftevaag 
1754*758e9fbaSOystein Eftevaag     *quoteInfo = strdup(quote_json);
1755*758e9fbaSOystein Eftevaag     goto_if_null(*quoteInfo, "Out of memory.", TSS2_FAPI_RC_MEMORY, cleanup);
1756*758e9fbaSOystein Eftevaag 
1757*758e9fbaSOystein Eftevaag cleanup:
1758*758e9fbaSOystein Eftevaag     json_object_put(jso);
1759*758e9fbaSOystein Eftevaag     return r;
1760*758e9fbaSOystein Eftevaag }
1761*758e9fbaSOystein Eftevaag 
1762*758e9fbaSOystein Eftevaag /** Deserialize the JSON representation of FAPI quote information.
1763*758e9fbaSOystein Eftevaag  *
1764*758e9fbaSOystein Eftevaag  * The JSON representation of FAPI quote information will be
1765*758e9fbaSOystein Eftevaag  * deserialized to a FAPI_QUOTE_INFO structure and also the TPM2B
1766*758e9fbaSOystein Eftevaag  * version of the attest will be created.
1767*758e9fbaSOystein Eftevaag  *
1768*758e9fbaSOystein Eftevaag  * @param[in]  quoteInfo The JSON representation if the quote
1769*758e9fbaSOystein Eftevaag  *             information.
1770*758e9fbaSOystein Eftevaag  * @param[out] tpm_quoted: The marhaled version of the attest structure.
1771*758e9fbaSOystein Eftevaag  * @param[out] fapi_quote_info The quote information structure used by
1772*758e9fbaSOystein Eftevaag  *             FAPI.
1773*758e9fbaSOystein Eftevaag  *
1774*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS: If the deserialization was successful.
1775*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE: If an invalid value is detected during
1776*758e9fbaSOystein Eftevaag  *         deserialisation.
1777*758e9fbaSOystein Eftevaag  * @retval Possible error codes of the marshaling function.
1778*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1779*758e9fbaSOystein Eftevaag  */
1780*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_get_quote_info(char const * quoteInfo,TPM2B_ATTEST * tpm_quoted,FAPI_QUOTE_INFO * fapi_quote_info)1781*758e9fbaSOystein Eftevaag ifapi_get_quote_info(
1782*758e9fbaSOystein Eftevaag     char const *quoteInfo,
1783*758e9fbaSOystein Eftevaag     TPM2B_ATTEST *tpm_quoted,
1784*758e9fbaSOystein Eftevaag     FAPI_QUOTE_INFO *fapi_quote_info)
1785*758e9fbaSOystein Eftevaag {
1786*758e9fbaSOystein Eftevaag     json_object *jso = NULL;
1787*758e9fbaSOystein Eftevaag     TSS2_RC r;
1788*758e9fbaSOystein Eftevaag     size_t offset = 0;
1789*758e9fbaSOystein Eftevaag 
1790*758e9fbaSOystein Eftevaag     jso = json_tokener_parse(quoteInfo);
1791*758e9fbaSOystein Eftevaag     return_if_null(jso, "Json error.", TSS2_FAPI_RC_BAD_VALUE);
1792*758e9fbaSOystein Eftevaag 
1793*758e9fbaSOystein Eftevaag     memset(&fapi_quote_info->attest.attested.quote.pcrSelect, 0,
1794*758e9fbaSOystein Eftevaag            sizeof(TPML_PCR_SELECTION));
1795*758e9fbaSOystein Eftevaag 
1796*758e9fbaSOystein Eftevaag     r = ifapi_json_FAPI_QUOTE_INFO_deserialize(jso, fapi_quote_info);
1797*758e9fbaSOystein Eftevaag     goto_if_error(r, "Conversion to JSON of TPM2S_ATTEST.", cleanup);
1798*758e9fbaSOystein Eftevaag 
1799*758e9fbaSOystein Eftevaag     offset = 0;
1800*758e9fbaSOystein Eftevaag     r = Tss2_MU_TPMS_ATTEST_Marshal(&fapi_quote_info->attest,
1801*758e9fbaSOystein Eftevaag                                     (uint8_t *)&tpm_quoted->attestationData[0],
1802*758e9fbaSOystein Eftevaag                                     sizeof(TPMS_ATTEST), &offset);
1803*758e9fbaSOystein Eftevaag     LOGBLOB_TRACE(&tpm_quoted->attestationData[0],
1804*758e9fbaSOystein Eftevaag                   offset,
1805*758e9fbaSOystein Eftevaag                   "Attest");
1806*758e9fbaSOystein Eftevaag     tpm_quoted-> size = offset;
1807*758e9fbaSOystein Eftevaag     goto_if_error(r, "Marshal attest.", cleanup);
1808*758e9fbaSOystein Eftevaag 
1809*758e9fbaSOystein Eftevaag cleanup:
1810*758e9fbaSOystein Eftevaag     if (jso)
1811*758e9fbaSOystein Eftevaag         json_object_put(jso);
1812*758e9fbaSOystein Eftevaag     return r;
1813*758e9fbaSOystein Eftevaag }
1814*758e9fbaSOystein Eftevaag 
1815*758e9fbaSOystein Eftevaag /** Determine start index for NV object depending on type.
1816*758e9fbaSOystein Eftevaag  *
1817*758e9fbaSOystein Eftevaag  * The value will be determined based on e TCG handle registry.
1818*758e9fbaSOystein Eftevaag  *
1819*758e9fbaSOystein Eftevaag  * @param[in]  path The path used for the NV object.
1820*758e9fbaSOystein Eftevaag  * @param[out] start_nv_index The first possible NV index for this type.
1821*758e9fbaSOystein Eftevaag  *
1822*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS If the index for the path can be determined.
1823*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_PATH If no handle can be assigned.
1824*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1825*758e9fbaSOystein Eftevaag  */
1826*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_get_nv_start_index(const char * path,TPM2_HANDLE * start_nv_index)1827*758e9fbaSOystein Eftevaag ifapi_get_nv_start_index(const char *path, TPM2_HANDLE *start_nv_index)
1828*758e9fbaSOystein Eftevaag {
1829*758e9fbaSOystein Eftevaag     NODE_STR_T *dir_list = split_string(path, IFAPI_FILE_DELIM);
1830*758e9fbaSOystein Eftevaag 
1831*758e9fbaSOystein Eftevaag     *start_nv_index = 0;
1832*758e9fbaSOystein Eftevaag 
1833*758e9fbaSOystein Eftevaag     return_if_null(dir_list, "Out of memory.", TSS2_FAPI_RC_MEMORY);
1834*758e9fbaSOystein Eftevaag     if (dir_list->next && strcmp(dir_list->str, "nv") == 0) {
1835*758e9fbaSOystein Eftevaag         if (strcmp(dir_list->next->str, "TPM") == 0)
1836*758e9fbaSOystein Eftevaag             *start_nv_index = 0x01000000;
1837*758e9fbaSOystein Eftevaag         else if (strcmp(dir_list->next->str, "Platform") == 0)
1838*758e9fbaSOystein Eftevaag             *start_nv_index = 0x01400000;
1839*758e9fbaSOystein Eftevaag         else if (strcmp(dir_list->next->str, "Owner") == 0)
1840*758e9fbaSOystein Eftevaag             *start_nv_index = 0x01800000;
1841*758e9fbaSOystein Eftevaag         else if (strcmp(dir_list->next->str, "Endorsement_Certificate") == 0)
1842*758e9fbaSOystein Eftevaag             *start_nv_index = 0x01c00000;
1843*758e9fbaSOystein Eftevaag         else if (strcmp(dir_list->next->str, "Platform_Certificate") == 0)
1844*758e9fbaSOystein Eftevaag             *start_nv_index = 0x01c80000;
1845*758e9fbaSOystein Eftevaag         else if (strcmp(dir_list->next->str, "Component_OEM") == 0)
1846*758e9fbaSOystein Eftevaag             *start_nv_index = 0x01c10000;
1847*758e9fbaSOystein Eftevaag         else if (strcmp(dir_list->next->str, "TPM_OEM") == 0)
1848*758e9fbaSOystein Eftevaag             *start_nv_index = 0x01c20000;
1849*758e9fbaSOystein Eftevaag         else if (strcmp(dir_list->next->str, "Platform_OEM") == 0)
1850*758e9fbaSOystein Eftevaag             *start_nv_index = 0x01c30000;
1851*758e9fbaSOystein Eftevaag         else if (strcmp(dir_list->next->str, "PC-Client") == 0)
1852*758e9fbaSOystein Eftevaag             *start_nv_index = 0x01c40000;
1853*758e9fbaSOystein Eftevaag         else if (strcmp(dir_list->next->str, "Sever") == 0)
1854*758e9fbaSOystein Eftevaag             *start_nv_index = 0x01c50000;
1855*758e9fbaSOystein Eftevaag         else if (strcmp(dir_list->next->str, "Virtualized_Platform") == 0)
1856*758e9fbaSOystein Eftevaag             *start_nv_index = 0x01c60000;
1857*758e9fbaSOystein Eftevaag         else if (strcmp(dir_list->next->str, "MPWG") == 0)
1858*758e9fbaSOystein Eftevaag             *start_nv_index = 0x01c70000;
1859*758e9fbaSOystein Eftevaag         else if (strcmp(dir_list->next->str, "Embedded") == 0)
1860*758e9fbaSOystein Eftevaag             *start_nv_index = 0x01c80000;
1861*758e9fbaSOystein Eftevaag     }
1862*758e9fbaSOystein Eftevaag     free_string_list(dir_list);
1863*758e9fbaSOystein Eftevaag     if (*start_nv_index)
1864*758e9fbaSOystein Eftevaag         return TSS2_RC_SUCCESS;
1865*758e9fbaSOystein Eftevaag 
1866*758e9fbaSOystein Eftevaag     return_error2(TSS2_FAPI_RC_BAD_PATH, "Invalid NV path: %s", path);
1867*758e9fbaSOystein Eftevaag }
1868*758e9fbaSOystein Eftevaag 
1869*758e9fbaSOystein Eftevaag /** Compute new PCR value from a part of an event list.
1870*758e9fbaSOystein Eftevaag  *
1871*758e9fbaSOystein Eftevaag  * @param[in,out] vpcr The old and the new PCR value.
1872*758e9fbaSOystein Eftevaag  * @param[in] bank The bank corresponding to value of the event list
1873*758e9fbaSOystein Eftevaag  *                 which will be used for computation.
1874*758e9fbaSOystein Eftevaag  * @param[in] event The event list with the values which were extended
1875*758e9fbaSOystein Eftevaag  *                  for a certain bank.
1876*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if the bank was not found in the event list.
1877*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
1878*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1879*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1880*758e9fbaSOystein Eftevaag  */
1881*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_extend_vpcr(TPM2B_DIGEST * vpcr,TPMI_ALG_HASH bank,const IFAPI_EVENT * event)1882*758e9fbaSOystein Eftevaag ifapi_extend_vpcr(
1883*758e9fbaSOystein Eftevaag     TPM2B_DIGEST *vpcr,
1884*758e9fbaSOystein Eftevaag     TPMI_ALG_HASH bank,
1885*758e9fbaSOystein Eftevaag     const IFAPI_EVENT *event)
1886*758e9fbaSOystein Eftevaag {
1887*758e9fbaSOystein Eftevaag     TSS2_RC r;
1888*758e9fbaSOystein Eftevaag     size_t i;
1889*758e9fbaSOystein Eftevaag     size_t event_size, size;
1890*758e9fbaSOystein Eftevaag     IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext;
1891*758e9fbaSOystein Eftevaag 
1892*758e9fbaSOystein Eftevaag     LOGBLOB_TRACE(&vpcr->buffer[0], vpcr->size, "Old vpcr value");
1893*758e9fbaSOystein Eftevaag 
1894*758e9fbaSOystein Eftevaag     for (i = 0; i < event->digests.count; i++) {
1895*758e9fbaSOystein Eftevaag         if (event->digests.digests[i].hashAlg == bank) {
1896*758e9fbaSOystein Eftevaag             event_size = ifapi_hash_get_digest_size(event->digests.digests[i].hashAlg);
1897*758e9fbaSOystein Eftevaag 
1898*758e9fbaSOystein Eftevaag             LOGBLOB_TRACE(&event->digests.digests[i].digest.sha512[0], event_size,
1899*758e9fbaSOystein Eftevaag                           "Extending with");
1900*758e9fbaSOystein Eftevaag 
1901*758e9fbaSOystein Eftevaag             r = ifapi_crypto_hash_start(&cryptoContext, bank);
1902*758e9fbaSOystein Eftevaag             return_if_error(r, "crypto hash start");
1903*758e9fbaSOystein Eftevaag 
1904*758e9fbaSOystein Eftevaag             HASH_UPDATE_BUFFER(cryptoContext, &vpcr->buffer[0], vpcr->size, r, error_cleanup);
1905*758e9fbaSOystein Eftevaag             HASH_UPDATE_BUFFER(cryptoContext, &event->digests.digests[i].digest.sha512[0],
1906*758e9fbaSOystein Eftevaag                                event_size, r, error_cleanup);
1907*758e9fbaSOystein Eftevaag             r = ifapi_crypto_hash_finish(&cryptoContext, &vpcr->buffer[0], &size);
1908*758e9fbaSOystein Eftevaag             return_if_error(r, "crypto hash finish");
1909*758e9fbaSOystein Eftevaag             vpcr->size = size;
1910*758e9fbaSOystein Eftevaag             break;
1911*758e9fbaSOystein Eftevaag         }
1912*758e9fbaSOystein Eftevaag     }
1913*758e9fbaSOystein Eftevaag     if (i == event->digests.count) {
1914*758e9fbaSOystein Eftevaag         LOG_ERROR("No digest for bank %"PRIu16" found in event", bank);
1915*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_BAD_VALUE;
1916*758e9fbaSOystein Eftevaag     }
1917*758e9fbaSOystein Eftevaag     LOGBLOB_TRACE(&vpcr->buffer[0], vpcr->size, "New vpcr value");
1918*758e9fbaSOystein Eftevaag 
1919*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
1920*758e9fbaSOystein Eftevaag 
1921*758e9fbaSOystein Eftevaag error_cleanup:
1922*758e9fbaSOystein Eftevaag     ifapi_crypto_hash_abort(&cryptoContext);
1923*758e9fbaSOystein Eftevaag     return r;
1924*758e9fbaSOystein Eftevaag }
1925*758e9fbaSOystein Eftevaag 
1926*758e9fbaSOystein Eftevaag /** Check whether a event list corresponds to a certain quote information.
1927*758e9fbaSOystein Eftevaag  *
1928*758e9fbaSOystein Eftevaag  * The event list is used to compute the PCR values corresponding
1929*758e9fbaSOystein Eftevaag  * to this event list. The PCR digest for these PCRs is computed and compared
1930*758e9fbaSOystein Eftevaag  * with the attest passed with quote_info.
1931*758e9fbaSOystein Eftevaag  *
1932*758e9fbaSOystein Eftevaag  * @param[in]  jso_event_list The event list in JSON representation.
1933*758e9fbaSOystein Eftevaag  * @param[in]  quote_info The information structure with the attest.
1934*758e9fbaSOystein Eftevaag  * @param[out] pcr_digest The computed pcr_digest for the PCRs uses by FAPI.
1935*758e9fbaSOystein Eftevaag  *
1936*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS: If the PCR digest from the event list matches
1937*758e9fbaSOystein Eftevaag  *         the PCR digest passed with the quote_info.
1938*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_SIGNATURE_VERIFICATION_FAILED: If the digest computed
1939*758e9fbaSOystein Eftevaag  *         from event list does not match the attest
1940*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE: If inappropriate values are detected in the
1941*758e9fbaSOystein Eftevaag  *         input data.
1942*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
1943*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1944*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1945*758e9fbaSOystein Eftevaag  */
1946*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_calculate_pcr_digest(json_object * jso_event_list,const FAPI_QUOTE_INFO * quote_info,TPM2B_DIGEST * pcr_digest)1947*758e9fbaSOystein Eftevaag ifapi_calculate_pcr_digest(
1948*758e9fbaSOystein Eftevaag     json_object *jso_event_list,
1949*758e9fbaSOystein Eftevaag     const FAPI_QUOTE_INFO *quote_info,
1950*758e9fbaSOystein Eftevaag     TPM2B_DIGEST *pcr_digest)
1951*758e9fbaSOystein Eftevaag {
1952*758e9fbaSOystein Eftevaag     TSS2_RC r;
1953*758e9fbaSOystein Eftevaag     IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext = NULL;
1954*758e9fbaSOystein Eftevaag 
1955*758e9fbaSOystein Eftevaag     struct {
1956*758e9fbaSOystein Eftevaag         TPMI_ALG_HASH bank;
1957*758e9fbaSOystein Eftevaag         TPM2_HANDLE pcr;
1958*758e9fbaSOystein Eftevaag         TPM2B_DIGEST value;
1959*758e9fbaSOystein Eftevaag     } pcrs[TPM2_MAX_PCRS];
1960*758e9fbaSOystein Eftevaag     size_t i, pcr, i_evt, hash_size, n_pcrs = 0, n_events = 0;
1961*758e9fbaSOystein Eftevaag 
1962*758e9fbaSOystein Eftevaag     json_object *jso;
1963*758e9fbaSOystein Eftevaag     IFAPI_EVENT event;
1964*758e9fbaSOystein Eftevaag 
1965*758e9fbaSOystein Eftevaag     const TPML_PCR_SELECTION *pcr_selection;
1966*758e9fbaSOystein Eftevaag     TPMI_ALG_HASH pcr_digest_hash_alg;
1967*758e9fbaSOystein Eftevaag 
1968*758e9fbaSOystein Eftevaag     /* Get some data from the quote info for easier access */
1969*758e9fbaSOystein Eftevaag     pcr_selection = &quote_info->attest.attested.quote.pcrSelect;
1970*758e9fbaSOystein Eftevaag     pcr_digest->size = quote_info->attest.attested.quote.pcrDigest.size;
1971*758e9fbaSOystein Eftevaag 
1972*758e9fbaSOystein Eftevaag     switch (quote_info->sig_scheme.scheme) {
1973*758e9fbaSOystein Eftevaag     case TPM2_ALG_RSAPSS:
1974*758e9fbaSOystein Eftevaag         pcr_digest_hash_alg = quote_info->sig_scheme.details.rsapss.hashAlg;
1975*758e9fbaSOystein Eftevaag         break;
1976*758e9fbaSOystein Eftevaag     case TPM2_ALG_RSASSA:
1977*758e9fbaSOystein Eftevaag         pcr_digest_hash_alg = quote_info->sig_scheme.details.rsassa.hashAlg;
1978*758e9fbaSOystein Eftevaag         break;
1979*758e9fbaSOystein Eftevaag     case TPM2_ALG_ECDSA:
1980*758e9fbaSOystein Eftevaag         pcr_digest_hash_alg = quote_info->sig_scheme.details.ecdsa.hashAlg;
1981*758e9fbaSOystein Eftevaag         break;
1982*758e9fbaSOystein Eftevaag     default:
1983*758e9fbaSOystein Eftevaag         LOG_ERROR("Unknown sig scheme");
1984*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_BAD_VALUE;
1985*758e9fbaSOystein Eftevaag     }
1986*758e9fbaSOystein Eftevaag 
1987*758e9fbaSOystein Eftevaag     /* Initialize used pcrs */
1988*758e9fbaSOystein Eftevaag     for (i = 0; i < pcr_selection->count; i++) {
1989*758e9fbaSOystein Eftevaag         for (pcr = 0; pcr < TPM2_MAX_PCRS; pcr++) {
1990*758e9fbaSOystein Eftevaag             uint8_t byte_idx = pcr / 8;
1991*758e9fbaSOystein Eftevaag             uint8_t flag = 1 << (pcr % 8);
1992*758e9fbaSOystein Eftevaag             if (flag & pcr_selection->pcrSelections[i].pcrSelect[byte_idx]) {
1993*758e9fbaSOystein Eftevaag                 hash_size = ifapi_hash_get_digest_size(pcr_selection->pcrSelections[i].hash);
1994*758e9fbaSOystein Eftevaag                 pcrs[n_pcrs].pcr = pcr;
1995*758e9fbaSOystein Eftevaag                 pcrs[n_pcrs].bank = pcr_selection->pcrSelections[i].hash;
1996*758e9fbaSOystein Eftevaag                 pcrs[n_pcrs].value.size = hash_size;
1997*758e9fbaSOystein Eftevaag                 memset(&pcrs[n_pcrs].value.buffer[0], 0, hash_size);
1998*758e9fbaSOystein Eftevaag                 n_pcrs += 1;
1999*758e9fbaSOystein Eftevaag             }
2000*758e9fbaSOystein Eftevaag         }
2001*758e9fbaSOystein Eftevaag     }
2002*758e9fbaSOystein Eftevaag 
2003*758e9fbaSOystein Eftevaag     /* Compute pcr values based on event list */
2004*758e9fbaSOystein Eftevaag     if (jso_event_list) {
2005*758e9fbaSOystein Eftevaag         n_events = json_object_array_length(jso_event_list);
2006*758e9fbaSOystein Eftevaag         for (i_evt = 0; i_evt < n_events; i_evt++) {
2007*758e9fbaSOystein Eftevaag             jso = json_object_array_get_idx(jso_event_list, i_evt);
2008*758e9fbaSOystein Eftevaag             r = ifapi_json_IFAPI_EVENT_deserialize(jso, &event);
2009*758e9fbaSOystein Eftevaag             goto_if_error(r, "Error serialize policy", error_cleanup);
2010*758e9fbaSOystein Eftevaag 
2011*758e9fbaSOystein Eftevaag             for (i = 0; i < n_pcrs; i++) {
2012*758e9fbaSOystein Eftevaag                  r = ifapi_extend_vpcr(&pcrs[i].value, pcrs[i].bank, &event);
2013*758e9fbaSOystein Eftevaag                  goto_if_error2(r, "Extending vpcr %"PRIu32, error_cleanup, pcrs[i].pcr);
2014*758e9fbaSOystein Eftevaag             }
2015*758e9fbaSOystein Eftevaag         }
2016*758e9fbaSOystein Eftevaag     }
2017*758e9fbaSOystein Eftevaag 
2018*758e9fbaSOystein Eftevaag     /* Compute digest for the used pcrs */
2019*758e9fbaSOystein Eftevaag     r = ifapi_crypto_hash_start(&cryptoContext, pcr_digest_hash_alg);
2020*758e9fbaSOystein Eftevaag     return_if_error(r, "crypto hash start");
2021*758e9fbaSOystein Eftevaag 
2022*758e9fbaSOystein Eftevaag     for (i = 0; i < n_pcrs; i++) {
2023*758e9fbaSOystein Eftevaag         HASH_UPDATE_BUFFER(cryptoContext, &pcrs[i].value.buffer, pcrs[i].value.size,
2024*758e9fbaSOystein Eftevaag                            r, error_cleanup);
2025*758e9fbaSOystein Eftevaag     }
2026*758e9fbaSOystein Eftevaag     r = ifapi_crypto_hash_finish(&cryptoContext,
2027*758e9fbaSOystein Eftevaag                                  (uint8_t *) &pcr_digest->buffer[0],
2028*758e9fbaSOystein Eftevaag                                  &hash_size);
2029*758e9fbaSOystein Eftevaag     return_if_error(r, "crypto hash finish");
2030*758e9fbaSOystein Eftevaag     pcr_digest->size = hash_size;
2031*758e9fbaSOystein Eftevaag 
2032*758e9fbaSOystein Eftevaag     /* Compare the digest from the event list with the digest from the attest */
2033*758e9fbaSOystein Eftevaag     if (memcmp(&pcr_digest->buffer[0], &quote_info->attest.attested.quote.pcrDigest.buffer[0],
2034*758e9fbaSOystein Eftevaag                pcr_digest->size) != 0) {
2035*758e9fbaSOystein Eftevaag         goto_error(r, TSS2_FAPI_RC_SIGNATURE_VERIFICATION_FAILED,
2036*758e9fbaSOystein Eftevaag                    "The digest computed from event list does not match the attest.",
2037*758e9fbaSOystein Eftevaag                    error_cleanup);
2038*758e9fbaSOystein Eftevaag     }
2039*758e9fbaSOystein Eftevaag 
2040*758e9fbaSOystein Eftevaag error_cleanup:
2041*758e9fbaSOystein Eftevaag     if (cryptoContext)
2042*758e9fbaSOystein Eftevaag         ifapi_crypto_hash_abort(&cryptoContext);
2043*758e9fbaSOystein Eftevaag     ifapi_cleanup_event(&event);
2044*758e9fbaSOystein Eftevaag     return r;
2045*758e9fbaSOystein Eftevaag }
2046*758e9fbaSOystein Eftevaag 
2047*758e9fbaSOystein Eftevaag /** Check whether profile PCR capabilities are a subset of TPM PCR capabilities.
2048*758e9fbaSOystein Eftevaag  *
2049*758e9fbaSOystein Eftevaag  * It has to be checked that every hash alg from the profile is available and
2050*758e9fbaSOystein Eftevaag  * whether the selected PCRs are available.
2051*758e9fbaSOystein Eftevaag  * @param[in] pcr_profile The pcr profile to use as basis for the selection.
2052*758e9fbaSOystein Eftevaag  * @param[in] pcr_capablity The PCR capabilities  available for TPM.
2053*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESSS if the conversion was successful.
2054*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if profile is not subset of capabilities.
2055*758e9fbaSOystein Eftevaag  */
2056*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_check_profile_pcr_selection(const TPML_PCR_SELECTION * pcr_profile,const TPML_PCR_SELECTION * pcr_capablity)2057*758e9fbaSOystein Eftevaag ifapi_check_profile_pcr_selection(
2058*758e9fbaSOystein Eftevaag     const TPML_PCR_SELECTION *pcr_profile,
2059*758e9fbaSOystein Eftevaag     const TPML_PCR_SELECTION *pcr_capablity)
2060*758e9fbaSOystein Eftevaag {
2061*758e9fbaSOystein Eftevaag     size_t i, j, k;
2062*758e9fbaSOystein Eftevaag 
2063*758e9fbaSOystein Eftevaag     for (i = 0; i < pcr_profile->count; i++) {
2064*758e9fbaSOystein Eftevaag         bool hash_found = false;
2065*758e9fbaSOystein Eftevaag         for (j = 0; j < pcr_capablity->count; j++) {
2066*758e9fbaSOystein Eftevaag             if (pcr_capablity->pcrSelections[j].hash ==
2067*758e9fbaSOystein Eftevaag                     pcr_profile->pcrSelections[i].hash) {
2068*758e9fbaSOystein Eftevaag                 /* Hash algorithm found, check PCRs */
2069*758e9fbaSOystein Eftevaag                 hash_found = true;
2070*758e9fbaSOystein Eftevaag                 if (pcr_profile->pcrSelections[i].sizeofSelect >
2071*758e9fbaSOystein Eftevaag                         pcr_capablity->pcrSelections[j].sizeofSelect) {
2072*758e9fbaSOystein Eftevaag                     return_error(TSS2_FAPI_RC_BAD_VALUE, "Invalid size of PCR select.");
2073*758e9fbaSOystein Eftevaag                 }
2074*758e9fbaSOystein Eftevaag 
2075*758e9fbaSOystein Eftevaag                 for (k = 0;
2076*758e9fbaSOystein Eftevaag                         k < pcr_profile->pcrSelections[i].sizeofSelect;
2077*758e9fbaSOystein Eftevaag                         k++) {
2078*758e9fbaSOystein Eftevaag                     /* Check whether all selected PCRs are available */
2079*758e9fbaSOystein Eftevaag                     if ((pcr_profile->pcrSelections[i].pcrSelect[k] &
2080*758e9fbaSOystein Eftevaag                             pcr_capablity->pcrSelections[j].pcrSelect[k])
2081*758e9fbaSOystein Eftevaag                             != pcr_profile->pcrSelections[i].pcrSelect[k]) {
2082*758e9fbaSOystein Eftevaag                         return_error(TSS2_FAPI_RC_BAD_VALUE, "Invalid PCR selection.");
2083*758e9fbaSOystein Eftevaag 
2084*758e9fbaSOystein Eftevaag                     }
2085*758e9fbaSOystein Eftevaag                 }
2086*758e9fbaSOystein Eftevaag             }
2087*758e9fbaSOystein Eftevaag         }
2088*758e9fbaSOystein Eftevaag         if (!hash_found) {
2089*758e9fbaSOystein Eftevaag             return_error(TSS2_FAPI_RC_BAD_VALUE,
2090*758e9fbaSOystein Eftevaag                          "Hash alg for PCR selection not available.");
2091*758e9fbaSOystein Eftevaag         }
2092*758e9fbaSOystein Eftevaag     }
2093*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
2094*758e9fbaSOystein Eftevaag }
2095*758e9fbaSOystein Eftevaag 
2096*758e9fbaSOystein Eftevaag /** Reduce a PCR selection to a single pcr.
2097*758e9fbaSOystein Eftevaag  *
2098*758e9fbaSOystein Eftevaag  * This includes two steps: clearing all bits but the selected and clearing empty hashalg lines.
2099*758e9fbaSOystein Eftevaag  *
2100*758e9fbaSOystein Eftevaag  * @param[in,out] pcr_selection The pcr selection to be filtered.
2101*758e9fbaSOystein Eftevaag  * @param[in] pcr_index The only PCR to remain selected.
2102*758e9fbaSOystein Eftevaag  * @param[in]  pcr_count The size of the pcr list.
2103*758e9fbaSOystein Eftevaag  *
2104*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS if the filtering was successful.
2105*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE if no pcr remain selected or the pcr selection is malformed.
2106*758e9fbaSOystein Eftevaag  */
2107*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_filter_pcr_selection_by_index(TPML_PCR_SELECTION * pcr_selection,const TPM2_HANDLE * pcr_index,size_t pcr_count)2108*758e9fbaSOystein Eftevaag ifapi_filter_pcr_selection_by_index(
2109*758e9fbaSOystein Eftevaag     TPML_PCR_SELECTION *pcr_selection,
2110*758e9fbaSOystein Eftevaag     const TPM2_HANDLE *pcr_index,
2111*758e9fbaSOystein Eftevaag     size_t pcr_count)
2112*758e9fbaSOystein Eftevaag {
2113*758e9fbaSOystein Eftevaag     UINT32 bank, j;
2114*758e9fbaSOystein Eftevaag     UINT16 select;
2115*758e9fbaSOystein Eftevaag     size_t i;
2116*758e9fbaSOystein Eftevaag     UINT8 selection[] = { 0, 0, 0, 0 };
2117*758e9fbaSOystein Eftevaag 
2118*758e9fbaSOystein Eftevaag     for (i = 0; i < pcr_count; i++) {
2119*758e9fbaSOystein Eftevaag         selection[0] |= (1 << pcr_index[i]) % 256;
2120*758e9fbaSOystein Eftevaag         selection[1] |= (1 << (pcr_index[i] - 8)) % 256;
2121*758e9fbaSOystein Eftevaag         selection[2] |= (1 << (pcr_index[i] - 16)) % 256;
2122*758e9fbaSOystein Eftevaag         selection[3] |= (1 << (pcr_index[i] - 24)) % 256;
2123*758e9fbaSOystein Eftevaag     };
2124*758e9fbaSOystein Eftevaag 
2125*758e9fbaSOystein Eftevaag     /* Remove unselected PCRs */
2126*758e9fbaSOystein Eftevaag     for (bank = 0; bank < pcr_selection->count; bank++) {
2127*758e9fbaSOystein Eftevaag         if (pcr_selection->pcrSelections[bank].sizeofSelect > 4) {
2128*758e9fbaSOystein Eftevaag             LOG_ERROR("pcrSelection's sizeofSelect exceeds allowed value of 4, is %"PRIu16,
2129*758e9fbaSOystein Eftevaag                       pcr_selection->pcrSelections[bank].sizeofSelect);
2130*758e9fbaSOystein Eftevaag             return TSS2_FAPI_RC_BAD_VALUE;
2131*758e9fbaSOystein Eftevaag         }
2132*758e9fbaSOystein Eftevaag         for (select = 0; select < pcr_selection->pcrSelections[bank].sizeofSelect; select++) {
2133*758e9fbaSOystein Eftevaag             pcr_selection->pcrSelections[bank].pcrSelect[select] &= selection[select];
2134*758e9fbaSOystein Eftevaag         }
2135*758e9fbaSOystein Eftevaag     }
2136*758e9fbaSOystein Eftevaag 
2137*758e9fbaSOystein Eftevaag     /* Remove empty banks */
2138*758e9fbaSOystein Eftevaag     for (bank = 0; bank < pcr_selection->count; ) {
2139*758e9fbaSOystein Eftevaag         for (select = 0; select < pcr_selection->pcrSelections[bank].sizeofSelect; select++) {
2140*758e9fbaSOystein Eftevaag             if (pcr_selection->pcrSelections[bank].pcrSelect[select])
2141*758e9fbaSOystein Eftevaag                 break;
2142*758e9fbaSOystein Eftevaag         }
2143*758e9fbaSOystein Eftevaag         if (select < pcr_selection->pcrSelections[bank].sizeofSelect) {
2144*758e9fbaSOystein Eftevaag             /* Bank contains selections */
2145*758e9fbaSOystein Eftevaag             bank ++;
2146*758e9fbaSOystein Eftevaag             continue;
2147*758e9fbaSOystein Eftevaag         }
2148*758e9fbaSOystein Eftevaag 
2149*758e9fbaSOystein Eftevaag         /* Bank contains no selections, move all other banks one up */
2150*758e9fbaSOystein Eftevaag         pcr_selection->count -= 1;
2151*758e9fbaSOystein Eftevaag         for (j = bank; j < pcr_selection->count; j++) {
2152*758e9fbaSOystein Eftevaag             pcr_selection->pcrSelections[j] = pcr_selection->pcrSelections[j+1];
2153*758e9fbaSOystein Eftevaag         }
2154*758e9fbaSOystein Eftevaag     }
2155*758e9fbaSOystein Eftevaag 
2156*758e9fbaSOystein Eftevaag     if (pcr_selection->count == 0) {
2157*758e9fbaSOystein Eftevaag         LOGBLOB_WARNING((void*)pcr_index, pcr_count * sizeof(*pcr_index),
2158*758e9fbaSOystein Eftevaag                         "pcr selection is empty after filtering for pcrlist");
2159*758e9fbaSOystein Eftevaag         return TSS2_FAPI_RC_BAD_VALUE;
2160*758e9fbaSOystein Eftevaag     }
2161*758e9fbaSOystein Eftevaag     return TSS2_RC_SUCCESS;
2162*758e9fbaSOystein Eftevaag }
2163*758e9fbaSOystein Eftevaag 
2164*758e9fbaSOystein Eftevaag /** Compute PCR selection and a PCR digest for a PCR value list.
2165*758e9fbaSOystein Eftevaag  *
2166*758e9fbaSOystein Eftevaag  * @param[in]  pcrs The list of PCR values.
2167*758e9fbaSOystein Eftevaag  * @param[out] pcr_selection The selection computed based on the
2168*758e9fbaSOystein Eftevaag  *             list of PCR values.
2169*758e9fbaSOystein Eftevaag  * @param[in]  hash_alg The hash algorithm which is used for the policy computation.
2170*758e9fbaSOystein Eftevaag  * @param[out] pcr_digest The computed PCR digest corresponding to the passed
2171*758e9fbaSOystein Eftevaag  *             PCR value list.
2172*758e9fbaSOystein Eftevaag  *
2173*758e9fbaSOystein Eftevaag  * @retval TSS2_RC_SUCCESS if the PCR selection and the PCR digest could be computed..
2174*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_VALUE: If inappropriate values are detected in the
2175*758e9fbaSOystein Eftevaag  *         input data.
2176*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
2177*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
2178*758e9fbaSOystein Eftevaag  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
2179*758e9fbaSOystein Eftevaag  */
2180*758e9fbaSOystein Eftevaag TSS2_RC
ifapi_compute_policy_digest(TPML_PCRVALUES * pcrs,TPML_PCR_SELECTION * pcr_selection,TPMI_ALG_HASH hash_alg,TPM2B_DIGEST * pcr_digest)2181*758e9fbaSOystein Eftevaag ifapi_compute_policy_digest(
2182*758e9fbaSOystein Eftevaag     TPML_PCRVALUES *pcrs,
2183*758e9fbaSOystein Eftevaag     TPML_PCR_SELECTION *pcr_selection,
2184*758e9fbaSOystein Eftevaag     TPMI_ALG_HASH hash_alg,
2185*758e9fbaSOystein Eftevaag     TPM2B_DIGEST *pcr_digest)
2186*758e9fbaSOystein Eftevaag {
2187*758e9fbaSOystein Eftevaag     TSS2_RC r = TSS2_RC_SUCCESS;
2188*758e9fbaSOystein Eftevaag     size_t i, j;
2189*758e9fbaSOystein Eftevaag     IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext = NULL;
2190*758e9fbaSOystein Eftevaag     size_t hash_size;
2191*758e9fbaSOystein Eftevaag     UINT32 pcr;
2192*758e9fbaSOystein Eftevaag     UINT32 max_pcr = 0;
2193*758e9fbaSOystein Eftevaag 
2194*758e9fbaSOystein Eftevaag     memset(pcr_selection, 0, sizeof(TPML_PCR_SELECTION));
2195*758e9fbaSOystein Eftevaag 
2196*758e9fbaSOystein Eftevaag     /* Compute PCR selection */
2197*758e9fbaSOystein Eftevaag     pcr_selection->count = 0;
2198*758e9fbaSOystein Eftevaag     for (i = 0; i < pcrs->count; i++) {
2199*758e9fbaSOystein Eftevaag         for (j = 0; j < pcr_selection->count; j++) {
2200*758e9fbaSOystein Eftevaag             if (pcrs->pcrs[i].hashAlg ==
2201*758e9fbaSOystein Eftevaag                 pcr_selection->pcrSelections[j].hash) {
2202*758e9fbaSOystein Eftevaag                 break;
2203*758e9fbaSOystein Eftevaag             }
2204*758e9fbaSOystein Eftevaag         }
2205*758e9fbaSOystein Eftevaag         if (j == pcr_selection->count) {
2206*758e9fbaSOystein Eftevaag             /* New hash alg */
2207*758e9fbaSOystein Eftevaag             pcr_selection->count += 1;
2208*758e9fbaSOystein Eftevaag             if (pcr_selection->count > TPM2_NUM_PCR_BANKS) {
2209*758e9fbaSOystein Eftevaag                 return_error(TSS2_FAPI_RC_BAD_VALUE,
2210*758e9fbaSOystein Eftevaag                              "More hash algs than banks.");
2211*758e9fbaSOystein Eftevaag             }
2212*758e9fbaSOystein Eftevaag             pcr_selection->pcrSelections[j].hash =
2213*758e9fbaSOystein Eftevaag                 pcrs->pcrs[i].hashAlg;
2214*758e9fbaSOystein Eftevaag         }
2215*758e9fbaSOystein Eftevaag         UINT32 pcrIndex = pcrs->pcrs[i].pcr;
2216*758e9fbaSOystein Eftevaag         if (pcrIndex + 1 > max_pcr)
2217*758e9fbaSOystein Eftevaag             max_pcr = pcrIndex + 1;
2218*758e9fbaSOystein Eftevaag         pcr_selection->pcrSelections[j].pcrSelect[pcrIndex / 8] |=
2219*758e9fbaSOystein Eftevaag             1 << pcrIndex % 8;
2220*758e9fbaSOystein Eftevaag         if ((pcrIndex / 8) + 1 > pcr_selection->pcrSelections[j].sizeofSelect)
2221*758e9fbaSOystein Eftevaag             pcr_selection->pcrSelections[j].sizeofSelect = (pcrIndex / 8) + 1;
2222*758e9fbaSOystein Eftevaag     }
2223*758e9fbaSOystein Eftevaag     /* Compute digest for current pcr selection */
2224*758e9fbaSOystein Eftevaag     r = ifapi_crypto_hash_start(&cryptoContext, hash_alg);
2225*758e9fbaSOystein Eftevaag     return_if_error(r, "crypto hash start");
2226*758e9fbaSOystein Eftevaag 
2227*758e9fbaSOystein Eftevaag     if (!(pcr_digest->size = ifapi_hash_get_digest_size(hash_alg))) {
2228*758e9fbaSOystein Eftevaag         goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
2229*758e9fbaSOystein Eftevaag                    "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
2230*758e9fbaSOystein Eftevaag                    hash_alg);
2231*758e9fbaSOystein Eftevaag     }
2232*758e9fbaSOystein Eftevaag 
2233*758e9fbaSOystein Eftevaag     for (i = 0; i < pcr_selection->count; i++) {
2234*758e9fbaSOystein Eftevaag         TPMS_PCR_SELECTION selection = pcr_selection->pcrSelections[i];
2235*758e9fbaSOystein Eftevaag         TPMI_ALG_HASH hashAlg = selection.hash;
2236*758e9fbaSOystein Eftevaag         if (!(hash_size = ifapi_hash_get_digest_size(hashAlg))) {
2237*758e9fbaSOystein Eftevaag             goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
2238*758e9fbaSOystein Eftevaag                        "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
2239*758e9fbaSOystein Eftevaag                        hashAlg);
2240*758e9fbaSOystein Eftevaag         }
2241*758e9fbaSOystein Eftevaag         for (pcr = 0; pcr < max_pcr; pcr++) {
2242*758e9fbaSOystein Eftevaag             if ((selection.pcrSelect[pcr / 8]) & (1 << (pcr % 8))) {
2243*758e9fbaSOystein Eftevaag                 /* pcr selected */
2244*758e9fbaSOystein Eftevaag                 for (j = 0; j < pcrs->count; j++) {
2245*758e9fbaSOystein Eftevaag                     if (pcrs->pcrs[j].pcr == pcr) {
2246*758e9fbaSOystein Eftevaag                         r = ifapi_crypto_hash_update(cryptoContext,
2247*758e9fbaSOystein Eftevaag                                                      (const uint8_t *)&pcrs->
2248*758e9fbaSOystein Eftevaag                                                      pcrs[j].digest,
2249*758e9fbaSOystein Eftevaag                                                      hash_size);
2250*758e9fbaSOystein Eftevaag                         goto_if_error(r, "crypto hash update", cleanup);
2251*758e9fbaSOystein Eftevaag                     }
2252*758e9fbaSOystein Eftevaag                 }
2253*758e9fbaSOystein Eftevaag             }
2254*758e9fbaSOystein Eftevaag         }
2255*758e9fbaSOystein Eftevaag     }
2256*758e9fbaSOystein Eftevaag     r = ifapi_crypto_hash_finish(&cryptoContext,
2257*758e9fbaSOystein Eftevaag                                  (uint8_t *) & pcr_digest->buffer[0],
2258*758e9fbaSOystein Eftevaag                                  &hash_size);
2259*758e9fbaSOystein Eftevaag cleanup:
2260*758e9fbaSOystein Eftevaag     if (cryptoContext)
2261*758e9fbaSOystein Eftevaag         ifapi_crypto_hash_abort(&cryptoContext);
2262*758e9fbaSOystein Eftevaag     return r;
2263*758e9fbaSOystein Eftevaag }
2264*758e9fbaSOystein Eftevaag 
2265*758e9fbaSOystein Eftevaag /** Compare two public keys.
2266*758e9fbaSOystein Eftevaag  *
2267*758e9fbaSOystein Eftevaag  * @param[in] key1 The first key.
2268*758e9fbaSOystein Eftevaag  * @param[in] key2 The second key.
2269*758e9fbaSOystein Eftevaag  * @retval true if equal false if not.
2270*758e9fbaSOystein Eftevaag  */
2271*758e9fbaSOystein Eftevaag bool
ifapi_cmp_public_key(TPM2B_PUBLIC * key1,TPM2B_PUBLIC * key2)2272*758e9fbaSOystein Eftevaag ifapi_cmp_public_key(
2273*758e9fbaSOystein Eftevaag     TPM2B_PUBLIC *key1,
2274*758e9fbaSOystein Eftevaag     TPM2B_PUBLIC *key2)
2275*758e9fbaSOystein Eftevaag {
2276*758e9fbaSOystein Eftevaag     if (key1->publicArea.type != key2->publicArea.type)
2277*758e9fbaSOystein Eftevaag         return false;
2278*758e9fbaSOystein Eftevaag     switch (key1->publicArea.type) {
2279*758e9fbaSOystein Eftevaag     case TPM2_ALG_RSA:
2280*758e9fbaSOystein Eftevaag         if (key1->publicArea.unique.rsa.size != key2->publicArea.unique.rsa.size) {
2281*758e9fbaSOystein Eftevaag             return false;
2282*758e9fbaSOystein Eftevaag         }
2283*758e9fbaSOystein Eftevaag         LOGBLOB_TRACE(&key1->publicArea.unique.rsa.buffer[0],
2284*758e9fbaSOystein Eftevaag                       key1->publicArea.unique.rsa.size, "Key 1");
2285*758e9fbaSOystein Eftevaag         LOGBLOB_TRACE(&key2->publicArea.unique.rsa.buffer[0],
2286*758e9fbaSOystein Eftevaag                       key2->publicArea.unique.rsa.size, "Key 2");
2287*758e9fbaSOystein Eftevaag         if (memcmp(&key1->publicArea.unique.rsa.buffer[0],
2288*758e9fbaSOystein Eftevaag                    &key2->publicArea.unique.rsa.buffer[0],
2289*758e9fbaSOystein Eftevaag                    key1->publicArea.unique.rsa.size) == 0)
2290*758e9fbaSOystein Eftevaag             return true;
2291*758e9fbaSOystein Eftevaag         else
2292*758e9fbaSOystein Eftevaag             return false;
2293*758e9fbaSOystein Eftevaag         break;
2294*758e9fbaSOystein Eftevaag     case TPM2_ALG_ECC:
2295*758e9fbaSOystein Eftevaag         if (key1->publicArea.unique.ecc.x.size != key2->publicArea.unique.ecc.x.size) {
2296*758e9fbaSOystein Eftevaag             return false;
2297*758e9fbaSOystein Eftevaag         }
2298*758e9fbaSOystein Eftevaag         LOGBLOB_TRACE(&key1->publicArea.unique.ecc.x.buffer[0],
2299*758e9fbaSOystein Eftevaag                       key1->publicArea.unique.ecc.x.size, "Key 1 x");
2300*758e9fbaSOystein Eftevaag         LOGBLOB_TRACE(&key2->publicArea.unique.ecc.x.buffer[0],
2301*758e9fbaSOystein Eftevaag                       key2->publicArea.unique.ecc.x.size, "Key 2 x");
2302*758e9fbaSOystein Eftevaag         if (memcmp(&key1->publicArea.unique.ecc.x.buffer[0],
2303*758e9fbaSOystein Eftevaag                    &key2->publicArea.unique.ecc.x.buffer[0],
2304*758e9fbaSOystein Eftevaag                    key1->publicArea.unique.ecc.x.size) != 0)
2305*758e9fbaSOystein Eftevaag             return false;
2306*758e9fbaSOystein Eftevaag         if (key1->publicArea.unique.ecc.y.size != key2->publicArea.unique.ecc.y.size) {
2307*758e9fbaSOystein Eftevaag             return false;
2308*758e9fbaSOystein Eftevaag         }
2309*758e9fbaSOystein Eftevaag         LOGBLOB_TRACE(&key1->publicArea.unique.ecc.y.buffer[0],
2310*758e9fbaSOystein Eftevaag                       key1->publicArea.unique.ecc.y.size, "Key 1 x");
2311*758e9fbaSOystein Eftevaag         LOGBLOB_TRACE(&key2->publicArea.unique.ecc.y.buffer[0],
2312*758e9fbaSOystein Eftevaag                       key2->publicArea.unique.ecc.y.size, "Key 2 x");
2313*758e9fbaSOystein Eftevaag         if (memcmp(&key1->publicArea.unique.ecc.y.buffer[0],
2314*758e9fbaSOystein Eftevaag                    &key2->publicArea.unique.ecc.y.buffer[0],
2315*758e9fbaSOystein Eftevaag                    key1->publicArea.unique.ecc.y.size) != 0)
2316*758e9fbaSOystein Eftevaag             return false;
2317*758e9fbaSOystein Eftevaag         else
2318*758e9fbaSOystein Eftevaag             return true;
2319*758e9fbaSOystein Eftevaag         break;
2320*758e9fbaSOystein Eftevaag 
2321*758e9fbaSOystein Eftevaag     default:
2322*758e9fbaSOystein Eftevaag         return false;
2323*758e9fbaSOystein Eftevaag     }
2324*758e9fbaSOystein Eftevaag }
2325*758e9fbaSOystein Eftevaag 
2326*758e9fbaSOystein Eftevaag struct CurlBufferStruct {
2327*758e9fbaSOystein Eftevaag   unsigned char *buffer;
2328*758e9fbaSOystein Eftevaag   size_t size;
2329*758e9fbaSOystein Eftevaag };
2330*758e9fbaSOystein Eftevaag 
2331*758e9fbaSOystein Eftevaag /** Callback for copying received curl data to a buffer.
2332*758e9fbaSOystein Eftevaag  *
2333*758e9fbaSOystein Eftevaag  * The buffer will be reallocated according to the size of retrieved data.
2334*758e9fbaSOystein Eftevaag  *
2335*758e9fbaSOystein Eftevaag  * @param[in]  contents The retrieved content.
2336*758e9fbaSOystein Eftevaag  * @param[in]  size the block size in the content.
2337*758e9fbaSOystein Eftevaag  * @param[in]  nmemb The number of blocks.
2338*758e9fbaSOystein Eftevaag  * @retval realsize The byte size of the data.
2339*758e9fbaSOystein Eftevaag  */
2340*758e9fbaSOystein Eftevaag static size_t
write_curl_buffer_cb(void * contents,size_t size,size_t nmemb,void * userp)2341*758e9fbaSOystein Eftevaag write_curl_buffer_cb(void *contents, size_t size, size_t nmemb, void *userp)
2342*758e9fbaSOystein Eftevaag {
2343*758e9fbaSOystein Eftevaag     size_t realsize = size * nmemb;
2344*758e9fbaSOystein Eftevaag     struct CurlBufferStruct *curl_buf = (struct CurlBufferStruct *)userp;
2345*758e9fbaSOystein Eftevaag 
2346*758e9fbaSOystein Eftevaag     unsigned char *tmp_ptr = realloc(curl_buf->buffer, curl_buf->size + realsize + 1);
2347*758e9fbaSOystein Eftevaag     if (tmp_ptr == NULL) {
2348*758e9fbaSOystein Eftevaag         LOG_ERROR("Can't allocate memory in CURL callback.");
2349*758e9fbaSOystein Eftevaag         return 0;
2350*758e9fbaSOystein Eftevaag     }
2351*758e9fbaSOystein Eftevaag     curl_buf->buffer = tmp_ptr;
2352*758e9fbaSOystein Eftevaag     memcpy(&(curl_buf->buffer[curl_buf->size]), contents, realsize);
2353*758e9fbaSOystein Eftevaag     curl_buf->size += realsize;
2354*758e9fbaSOystein Eftevaag     curl_buf->buffer[curl_buf->size] = 0;
2355*758e9fbaSOystein Eftevaag 
2356*758e9fbaSOystein Eftevaag     return realsize;
2357*758e9fbaSOystein Eftevaag }
2358*758e9fbaSOystein Eftevaag 
2359*758e9fbaSOystein Eftevaag /** Get byte buffer from file system or web via curl.
2360*758e9fbaSOystein Eftevaag  *
2361*758e9fbaSOystein Eftevaag  * @param[in]  url The url of the resource.
2362*758e9fbaSOystein Eftevaag  * @param[out] buffer The buffer retrieved via the url.
2363*758e9fbaSOystein Eftevaag  * @param[out] buffer_size The size of the retrieved object.
2364*758e9fbaSOystein Eftevaag  *
2365*758e9fbaSOystein Eftevaag  * @retval 0 if buffer could be retrieved.
2366*758e9fbaSOystein Eftevaag  * @retval -1 if an error did occur
2367*758e9fbaSOystein Eftevaag  */
2368*758e9fbaSOystein Eftevaag int
ifapi_get_curl_buffer(unsigned char * url,unsigned char ** buffer,size_t * buffer_size)2369*758e9fbaSOystein Eftevaag ifapi_get_curl_buffer(unsigned char * url, unsigned char ** buffer,
2370*758e9fbaSOystein Eftevaag                           size_t *buffer_size) {
2371*758e9fbaSOystein Eftevaag     int ret = -1;
2372*758e9fbaSOystein Eftevaag     struct CurlBufferStruct curl_buffer = { .size = 0, .buffer = NULL };
2373*758e9fbaSOystein Eftevaag 
2374*758e9fbaSOystein Eftevaag     CURLcode rc = curl_global_init(CURL_GLOBAL_DEFAULT);
2375*758e9fbaSOystein Eftevaag     if (rc != CURLE_OK) {
2376*758e9fbaSOystein Eftevaag         LOG_ERROR("curl_global_init failed: %s", curl_easy_strerror(rc));
2377*758e9fbaSOystein Eftevaag         goto out_memory;
2378*758e9fbaSOystein Eftevaag     }
2379*758e9fbaSOystein Eftevaag 
2380*758e9fbaSOystein Eftevaag     CURL *curl = curl_easy_init();
2381*758e9fbaSOystein Eftevaag     if (!curl) {
2382*758e9fbaSOystein Eftevaag         LOG_ERROR("curl_easy_init failed");
2383*758e9fbaSOystein Eftevaag         goto out_global_cleanup;
2384*758e9fbaSOystein Eftevaag     }
2385*758e9fbaSOystein Eftevaag 
2386*758e9fbaSOystein Eftevaag     rc = curl_easy_setopt(curl, CURLOPT_URL, url);
2387*758e9fbaSOystein Eftevaag     if (rc != CURLE_OK) {
2388*758e9fbaSOystein Eftevaag         LOG_ERROR("curl_easy_setopt for CURLOPT_URL failed: %s",
2389*758e9fbaSOystein Eftevaag                 curl_easy_strerror(rc));
2390*758e9fbaSOystein Eftevaag         goto out_easy_cleanup;
2391*758e9fbaSOystein Eftevaag     }
2392*758e9fbaSOystein Eftevaag 
2393*758e9fbaSOystein Eftevaag     rc = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
2394*758e9fbaSOystein Eftevaag                           write_curl_buffer_cb);
2395*758e9fbaSOystein Eftevaag     if (rc != CURLE_OK) {
2396*758e9fbaSOystein Eftevaag         LOG_ERROR("curl_easy_setopt for CURLOPT_URL failed: %s",
2397*758e9fbaSOystein Eftevaag                 curl_easy_strerror(rc));
2398*758e9fbaSOystein Eftevaag         goto out_easy_cleanup;
2399*758e9fbaSOystein Eftevaag     }
2400*758e9fbaSOystein Eftevaag 
2401*758e9fbaSOystein Eftevaag     rc = curl_easy_setopt(curl, CURLOPT_WRITEDATA,
2402*758e9fbaSOystein Eftevaag                           (void *)&curl_buffer);
2403*758e9fbaSOystein Eftevaag     if (rc != CURLE_OK) {
2404*758e9fbaSOystein Eftevaag         LOG_ERROR("curl_easy_setopt for CURLOPT_URL failed: %s",
2405*758e9fbaSOystein Eftevaag                 curl_easy_strerror(rc));
2406*758e9fbaSOystein Eftevaag         goto out_easy_cleanup;
2407*758e9fbaSOystein Eftevaag     }
2408*758e9fbaSOystein Eftevaag 
2409*758e9fbaSOystein Eftevaag     if (LOGMODULE_status == LOGLEVEL_TRACE) {
2410*758e9fbaSOystein Eftevaag         if (CURLE_OK != curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L)) {
2411*758e9fbaSOystein Eftevaag             LOG_WARNING("Curl easy setopt verbose failed");
2412*758e9fbaSOystein Eftevaag         }
2413*758e9fbaSOystein Eftevaag     }
2414*758e9fbaSOystein Eftevaag 
2415*758e9fbaSOystein Eftevaag     rc = curl_easy_perform(curl);
2416*758e9fbaSOystein Eftevaag     if (rc != CURLE_OK) {
2417*758e9fbaSOystein Eftevaag         LOG_ERROR("curl_easy_perform() failed: %s", curl_easy_strerror(rc));
2418*758e9fbaSOystein Eftevaag         goto out_easy_cleanup;
2419*758e9fbaSOystein Eftevaag     }
2420*758e9fbaSOystein Eftevaag 
2421*758e9fbaSOystein Eftevaag     *buffer = curl_buffer.buffer;
2422*758e9fbaSOystein Eftevaag     *buffer_size = curl_buffer.size;
2423*758e9fbaSOystein Eftevaag 
2424*758e9fbaSOystein Eftevaag     ret = 0;
2425*758e9fbaSOystein Eftevaag 
2426*758e9fbaSOystein Eftevaag out_easy_cleanup:
2427*758e9fbaSOystein Eftevaag     if (ret != 0)
2428*758e9fbaSOystein Eftevaag         free(curl_buffer.buffer);
2429*758e9fbaSOystein Eftevaag     curl_easy_cleanup(curl);
2430*758e9fbaSOystein Eftevaag out_global_cleanup:
2431*758e9fbaSOystein Eftevaag     curl_global_cleanup();
2432*758e9fbaSOystein Eftevaag out_memory:
2433*758e9fbaSOystein Eftevaag     return ret;
2434*758e9fbaSOystein Eftevaag }
2435