xref: /aosp_15_r20/external/tpm2-tss/src/tss2-rc/tss2_rc.c (revision 758e9fba6fc9adbf15340f70c73baee7b168b1c9)
1*758e9fbaSOystein Eftevaag /* SPDX-License-Identifier: BSD-2-Clause */
2*758e9fbaSOystein Eftevaag 
3*758e9fbaSOystein Eftevaag #include <stdarg.h>
4*758e9fbaSOystein Eftevaag #include <stdbool.h>
5*758e9fbaSOystein Eftevaag #include <stdio.h>
6*758e9fbaSOystein Eftevaag #include <string.h>
7*758e9fbaSOystein Eftevaag 
8*758e9fbaSOystein Eftevaag #include "tss2_rc.h"
9*758e9fbaSOystein Eftevaag #include "tss2_sys.h"
10*758e9fbaSOystein Eftevaag 
11*758e9fbaSOystein Eftevaag #if defined (__GNUC__)
12*758e9fbaSOystein Eftevaag #define COMPILER_ATTR(...) __attribute__((__VA_ARGS__))
13*758e9fbaSOystein Eftevaag #else
14*758e9fbaSOystein Eftevaag #define COMPILER_ATTR(...)
15*758e9fbaSOystein Eftevaag #endif
16*758e9fbaSOystein Eftevaag 
17*758e9fbaSOystein Eftevaag #define ARRAY_LEN(x) (sizeof(x)/sizeof(x[0]))
18*758e9fbaSOystein Eftevaag 
19*758e9fbaSOystein Eftevaag /**
20*758e9fbaSOystein Eftevaag  * The maximum size of a layer name.
21*758e9fbaSOystein Eftevaag  */
22*758e9fbaSOystein Eftevaag #define TSS2_ERR_LAYER_NAME_MAX  (16 + 1)
23*758e9fbaSOystein Eftevaag 
24*758e9fbaSOystein Eftevaag /**
25*758e9fbaSOystein Eftevaag  * The maximum size for layer specific error strings.
26*758e9fbaSOystein Eftevaag  */
27*758e9fbaSOystein Eftevaag #define TSS2_ERR_LAYER_ERROR_STR_MAX  512
28*758e9fbaSOystein Eftevaag 
29*758e9fbaSOystein Eftevaag /**
30*758e9fbaSOystein Eftevaag  * Concatenates (safely) onto a static buffer given a format and varaidic
31*758e9fbaSOystein Eftevaag  * arguments similar to sprintf.
32*758e9fbaSOystein Eftevaag  * @param b
33*758e9fbaSOystein Eftevaag  *   The static buffer to concatenate onto.
34*758e9fbaSOystein Eftevaag  * @param fmt
35*758e9fbaSOystein Eftevaag  *   The format specifier as understood by printf followed by the variadic
36*758e9fbaSOystein Eftevaag  *   parameters for the specifier.
37*758e9fbaSOystein Eftevaag  */
38*758e9fbaSOystein Eftevaag #define catbuf(b, fmt, ...) _catbuf(b, sizeof(b), fmt, ##__VA_ARGS__)
39*758e9fbaSOystein Eftevaag 
40*758e9fbaSOystein Eftevaag /**
41*758e9fbaSOystein Eftevaag  * Clears out a static buffer by setting index 0 to the null byte.
42*758e9fbaSOystein Eftevaag  * @param buffer
43*758e9fbaSOystein Eftevaag  *  The buffer to clear out.
44*758e9fbaSOystein Eftevaag  */
45*758e9fbaSOystein Eftevaag static void
clearbuf(char * buffer)46*758e9fbaSOystein Eftevaag clearbuf(char *buffer)
47*758e9fbaSOystein Eftevaag {
48*758e9fbaSOystein Eftevaag     buffer[0] = '\0';
49*758e9fbaSOystein Eftevaag }
50*758e9fbaSOystein Eftevaag 
51*758e9fbaSOystein Eftevaag /**
52*758e9fbaSOystein Eftevaag  * Prints to a buffer using snprintf(3) using the supplied fmt
53*758e9fbaSOystein Eftevaag  * and varaiadic arguments.
54*758e9fbaSOystein Eftevaag  * @param buf
55*758e9fbaSOystein Eftevaag  *  The buffer to print into.
56*758e9fbaSOystein Eftevaag  * @param len
57*758e9fbaSOystein Eftevaag  *  The length of that buffer.
58*758e9fbaSOystein Eftevaag  * @param fmt
59*758e9fbaSOystein Eftevaag  *  The format string
60*758e9fbaSOystein Eftevaag  * @warning
61*758e9fbaSOystein Eftevaag  *  DO NOT CALL DIRECTLY, use the catbuf() macro.
62*758e9fbaSOystein Eftevaag  */
63*758e9fbaSOystein Eftevaag static void COMPILER_ATTR(format (printf, 3, 4))
_catbuf(char * buf,size_t len,const char * fmt,...)64*758e9fbaSOystein Eftevaag _catbuf(char *buf, size_t len, const char *fmt, ...)
65*758e9fbaSOystein Eftevaag {
66*758e9fbaSOystein Eftevaag     va_list argptr;
67*758e9fbaSOystein Eftevaag     va_start(argptr, fmt);
68*758e9fbaSOystein Eftevaag     size_t offset = strlen(buf);
69*758e9fbaSOystein Eftevaag     vsnprintf(&buf[offset], len - offset, fmt, argptr);
70*758e9fbaSOystein Eftevaag     va_end(argptr);
71*758e9fbaSOystein Eftevaag }
72*758e9fbaSOystein Eftevaag 
73*758e9fbaSOystein Eftevaag /**
74*758e9fbaSOystein Eftevaag  * Number of error layers
75*758e9fbaSOystein Eftevaag  */
76*758e9fbaSOystein Eftevaag #define TPM2_ERROR_TSS2_RC_LAYER_COUNT (TSS2_RC_LAYER_MASK >> TSS2_RC_LAYER_SHIFT)
77*758e9fbaSOystein Eftevaag 
78*758e9fbaSOystein Eftevaag /**
79*758e9fbaSOystein Eftevaag  * Mask for the error bits of tpm2 compliant return code.
80*758e9fbaSOystein Eftevaag  */
81*758e9fbaSOystein Eftevaag #define TPM2_ERROR_TSS2_RC_ERROR_MASK 0xFFFF
82*758e9fbaSOystein Eftevaag 
83*758e9fbaSOystein Eftevaag /**
84*758e9fbaSOystein Eftevaag  * Retrieves the error bits from a TSS2_RC. The error bits are
85*758e9fbaSOystein Eftevaag  * contained in the first 2 octets.
86*758e9fbaSOystein Eftevaag  * @param rc
87*758e9fbaSOystein Eftevaag  *  The rc to query for the error bits.
88*758e9fbaSOystein Eftevaag  * @return
89*758e9fbaSOystein Eftevaag  *  The error bits.
90*758e9fbaSOystein Eftevaag  */
91*758e9fbaSOystein Eftevaag static inline UINT16
tpm2_error_get(TSS2_RC rc)92*758e9fbaSOystein Eftevaag tpm2_error_get(TSS2_RC rc)
93*758e9fbaSOystein Eftevaag {
94*758e9fbaSOystein Eftevaag     return ((rc & TPM2_ERROR_TSS2_RC_ERROR_MASK));
95*758e9fbaSOystein Eftevaag }
96*758e9fbaSOystein Eftevaag 
97*758e9fbaSOystein Eftevaag /**
98*758e9fbaSOystein Eftevaag  * Retrieves the layer number. The layer number is in the 3rd
99*758e9fbaSOystein Eftevaag  * octet and is thus 1 byte big.
100*758e9fbaSOystein Eftevaag  *
101*758e9fbaSOystein Eftevaag  * @param rc
102*758e9fbaSOystein Eftevaag  *  The rc to query for the layer number.
103*758e9fbaSOystein Eftevaag  * @return
104*758e9fbaSOystein Eftevaag  *  The layer number.
105*758e9fbaSOystein Eftevaag  */
106*758e9fbaSOystein Eftevaag static inline UINT8
tss2_rc_layer_number_get(TSS2_RC rc)107*758e9fbaSOystein Eftevaag tss2_rc_layer_number_get(TSS2_RC rc)
108*758e9fbaSOystein Eftevaag {
109*758e9fbaSOystein Eftevaag     return ((rc & TSS2_RC_LAYER_MASK) >> TSS2_RC_LAYER_SHIFT);
110*758e9fbaSOystein Eftevaag }
111*758e9fbaSOystein Eftevaag 
112*758e9fbaSOystein Eftevaag /**
113*758e9fbaSOystein Eftevaag  * Queries a TPM format 1 error codes N field. The N field
114*758e9fbaSOystein Eftevaag  * is a 4 bit field located at bits 8:12.
115*758e9fbaSOystein Eftevaag  * @param rc
116*758e9fbaSOystein Eftevaag  *  The rc to query the N field for.
117*758e9fbaSOystein Eftevaag  * @return
118*758e9fbaSOystein Eftevaag  *  The N field value.
119*758e9fbaSOystein Eftevaag  */
120*758e9fbaSOystein Eftevaag static inline UINT8
tpm2_rc_fmt1_N_get(TPM2_RC rc)121*758e9fbaSOystein Eftevaag tpm2_rc_fmt1_N_get(TPM2_RC rc)
122*758e9fbaSOystein Eftevaag {
123*758e9fbaSOystein Eftevaag     return ((rc & (0xF << 8)) >> 8);
124*758e9fbaSOystein Eftevaag }
125*758e9fbaSOystein Eftevaag 
126*758e9fbaSOystein Eftevaag /**
127*758e9fbaSOystein Eftevaag  * Queries the index bits out of the N field contained in a TPM format 1
128*758e9fbaSOystein Eftevaag  * error code. The index bits are the low 3 bits of the N field.
129*758e9fbaSOystein Eftevaag  * @param rc
130*758e9fbaSOystein Eftevaag  *  The TPM format 1 error code to query for the index bits.
131*758e9fbaSOystein Eftevaag  * @return
132*758e9fbaSOystein Eftevaag  *  The index bits from the N field.
133*758e9fbaSOystein Eftevaag  */
134*758e9fbaSOystein Eftevaag static inline UINT8
tpm2_rc_fmt1_N_index_get(TPM2_RC rc)135*758e9fbaSOystein Eftevaag tpm2_rc_fmt1_N_index_get(TPM2_RC rc)
136*758e9fbaSOystein Eftevaag {
137*758e9fbaSOystein Eftevaag     return (tpm2_rc_fmt1_N_get(rc) & 0x7);
138*758e9fbaSOystein Eftevaag }
139*758e9fbaSOystein Eftevaag 
140*758e9fbaSOystein Eftevaag /**
141*758e9fbaSOystein Eftevaag  * Determines if the N field in a TPM format 1 error code is
142*758e9fbaSOystein Eftevaag  * a handle or not.
143*758e9fbaSOystein Eftevaag  * @param rc
144*758e9fbaSOystein Eftevaag  *  The TPM format 1 error code to query.
145*758e9fbaSOystein Eftevaag  * @return
146*758e9fbaSOystein Eftevaag  *  True if it is a handle, false otherwise.
147*758e9fbaSOystein Eftevaag  */
148*758e9fbaSOystein Eftevaag static inline bool
tpm2_rc_fmt1_N_is_handle(TPM2_RC rc)149*758e9fbaSOystein Eftevaag tpm2_rc_fmt1_N_is_handle(TPM2_RC rc)
150*758e9fbaSOystein Eftevaag {
151*758e9fbaSOystein Eftevaag     return ((tpm2_rc_fmt1_N_get(rc) & 0x8) == 0);
152*758e9fbaSOystein Eftevaag }
153*758e9fbaSOystein Eftevaag 
154*758e9fbaSOystein Eftevaag static inline UINT8
tpm2_rc_fmt1_P_get(TPM2_RC rc)155*758e9fbaSOystein Eftevaag tpm2_rc_fmt1_P_get(TPM2_RC rc)
156*758e9fbaSOystein Eftevaag {
157*758e9fbaSOystein Eftevaag     return ((rc & (1 << 6)) >> 6);
158*758e9fbaSOystein Eftevaag }
159*758e9fbaSOystein Eftevaag 
160*758e9fbaSOystein Eftevaag static inline UINT8
tpm2_rc_fmt1_error_get(TPM2_RC rc)161*758e9fbaSOystein Eftevaag tpm2_rc_fmt1_error_get(TPM2_RC rc)
162*758e9fbaSOystein Eftevaag {
163*758e9fbaSOystein Eftevaag     return (rc & 0x3F);
164*758e9fbaSOystein Eftevaag }
165*758e9fbaSOystein Eftevaag 
166*758e9fbaSOystein Eftevaag static inline UINT8
tpm2_rc_fmt0_error_get(TPM2_RC rc)167*758e9fbaSOystein Eftevaag tpm2_rc_fmt0_error_get(TPM2_RC rc)
168*758e9fbaSOystein Eftevaag {
169*758e9fbaSOystein Eftevaag     return (rc & 0x7F);
170*758e9fbaSOystein Eftevaag }
171*758e9fbaSOystein Eftevaag 
172*758e9fbaSOystein Eftevaag static inline UINT8
tpm2_rc_tpm_fmt0_V_get(TPM2_RC rc)173*758e9fbaSOystein Eftevaag tpm2_rc_tpm_fmt0_V_get(TPM2_RC rc)
174*758e9fbaSOystein Eftevaag {
175*758e9fbaSOystein Eftevaag     return ((rc & (1 << 8)) >> 8);
176*758e9fbaSOystein Eftevaag }
177*758e9fbaSOystein Eftevaag 
178*758e9fbaSOystein Eftevaag static inline UINT8
tpm2_rc_fmt0_T_get(TPM2_RC rc)179*758e9fbaSOystein Eftevaag tpm2_rc_fmt0_T_get(TPM2_RC rc)
180*758e9fbaSOystein Eftevaag {
181*758e9fbaSOystein Eftevaag     return ((rc & (1 << 10)) >> 8);
182*758e9fbaSOystein Eftevaag }
183*758e9fbaSOystein Eftevaag 
184*758e9fbaSOystein Eftevaag static inline UINT8
tpm2_rc_fmt0_S_get(TSS2_RC rc)185*758e9fbaSOystein Eftevaag tpm2_rc_fmt0_S_get(TSS2_RC rc)
186*758e9fbaSOystein Eftevaag {
187*758e9fbaSOystein Eftevaag     return ((rc & (1 << 11)) >> 8);
188*758e9fbaSOystein Eftevaag }
189*758e9fbaSOystein Eftevaag 
190*758e9fbaSOystein Eftevaag /**
191*758e9fbaSOystein Eftevaag  * Helper macro for adding a layer handler to the layer
192*758e9fbaSOystein Eftevaag  * registration array.
193*758e9fbaSOystein Eftevaag  */
194*758e9fbaSOystein Eftevaag #define ADD_HANDLER(name, handler) \
195*758e9fbaSOystein Eftevaag     { name, handler }
196*758e9fbaSOystein Eftevaag 
197*758e9fbaSOystein Eftevaag /**
198*758e9fbaSOystein Eftevaag  * Same as ADD_HANDLER but sets it to NULL. Used as a placeholder
199*758e9fbaSOystein Eftevaag  * for non-registered indexes into the handler array.
200*758e9fbaSOystein Eftevaag  */
201*758e9fbaSOystein Eftevaag #define ADD_NULL_HANDLER ADD_HANDLER("\0", NULL)
202*758e9fbaSOystein Eftevaag 
203*758e9fbaSOystein Eftevaag static const char *
tpm2_err_handler_fmt1(TPM2_RC rc)204*758e9fbaSOystein Eftevaag tpm2_err_handler_fmt1(TPM2_RC rc)
205*758e9fbaSOystein Eftevaag {
206*758e9fbaSOystein Eftevaag     /*
207*758e9fbaSOystein Eftevaag      * format 1 error codes start at 1, so
208*758e9fbaSOystein Eftevaag      * add a NULL entry to index 0.
209*758e9fbaSOystein Eftevaag      */
210*758e9fbaSOystein Eftevaag     static const char *fmt1_err_strs[] = {
211*758e9fbaSOystein Eftevaag         /* 0x0 - EMPTY */
212*758e9fbaSOystein Eftevaag         NULL,
213*758e9fbaSOystein Eftevaag         /* 0x1 - TPM2_RC_ASYMMETRIC */
214*758e9fbaSOystein Eftevaag         "asymmetric algorithm not supported or not correct",
215*758e9fbaSOystein Eftevaag         /* 0x2 - TPM2_RC_ATTRIBUTES */
216*758e9fbaSOystein Eftevaag         "inconsistent attributes",
217*758e9fbaSOystein Eftevaag         /* 0x3 - TPM2_RC_HASH */
218*758e9fbaSOystein Eftevaag         "hash algorithm not supported or not appropriate",
219*758e9fbaSOystein Eftevaag         /* 0x4 - TPM2_RC_VALUE */
220*758e9fbaSOystein Eftevaag         "value is out of range or is not correct for the context",
221*758e9fbaSOystein Eftevaag         /* 0x5 - TPM2_RC_HIERARCHY */
222*758e9fbaSOystein Eftevaag         "hierarchy is not enabled or is not correct for the use",
223*758e9fbaSOystein Eftevaag         /* 0x6 - EMPTY */
224*758e9fbaSOystein Eftevaag         NULL,
225*758e9fbaSOystein Eftevaag         /* 0x7 - TPM2_RC_KEY_SIZE */
226*758e9fbaSOystein Eftevaag         "key size is not supported",
227*758e9fbaSOystein Eftevaag         /* 0x8 - TPM2_RC_MGF */
228*758e9fbaSOystein Eftevaag         "mask generation function not supported",
229*758e9fbaSOystein Eftevaag         /* 0x9 - TPM2_RC_MODE */
230*758e9fbaSOystein Eftevaag         "mode of operation not supported",
231*758e9fbaSOystein Eftevaag         /* 0xA - TPM2_RC_TYPE */
232*758e9fbaSOystein Eftevaag         "the type of the value is not appropriate for the use",
233*758e9fbaSOystein Eftevaag         /* 0xB - TPM2_RC_HANDLE */
234*758e9fbaSOystein Eftevaag         "the handle is not correct for the use",
235*758e9fbaSOystein Eftevaag         /* 0xC - TPM2_RC_KDF */
236*758e9fbaSOystein Eftevaag         "unsupported key derivation function or function not appropriate for "
237*758e9fbaSOystein Eftevaag         "use",
238*758e9fbaSOystein Eftevaag         /* 0xD - TPM2_RC_RANGE */
239*758e9fbaSOystein Eftevaag         "value was out of allowed range",
240*758e9fbaSOystein Eftevaag         /* 0xE - TPM2_RC_AUTH_FAIL */
241*758e9fbaSOystein Eftevaag         "the authorization HMAC check failed and DA counter incremented",
242*758e9fbaSOystein Eftevaag         /* 0xF - TPM2_RC_NONCE */
243*758e9fbaSOystein Eftevaag         "invalid nonce size or nonce value mismatch",
244*758e9fbaSOystein Eftevaag         /* 0x10 - TPM2_RC_PP */
245*758e9fbaSOystein Eftevaag         "authorization requires assertion of PP",
246*758e9fbaSOystein Eftevaag         /* 0x11 - EMPTY */
247*758e9fbaSOystein Eftevaag         NULL,
248*758e9fbaSOystein Eftevaag         /* 0x12 - TPM2_RC_SCHEME */
249*758e9fbaSOystein Eftevaag         "unsupported or incompatible scheme",
250*758e9fbaSOystein Eftevaag         /* 0x13 - EMPTY */
251*758e9fbaSOystein Eftevaag         NULL,
252*758e9fbaSOystein Eftevaag         /* 0x14 - EMPTY */
253*758e9fbaSOystein Eftevaag         NULL,
254*758e9fbaSOystein Eftevaag         /* 0x15 - TPM2_RC_SIZE */
255*758e9fbaSOystein Eftevaag         "structure is the wrong size",
256*758e9fbaSOystein Eftevaag         /* 0x16 - TPM2_RC_SYMMETRIC */
257*758e9fbaSOystein Eftevaag         "unsupported symmetric algorithm or key size or not appropriate for"
258*758e9fbaSOystein Eftevaag         " instance",
259*758e9fbaSOystein Eftevaag         /* 0x17 - TPM2_RC_TAG */
260*758e9fbaSOystein Eftevaag         "incorrect structure tag",
261*758e9fbaSOystein Eftevaag         /* 0x18 - TPM2_RC_SELECTOR */
262*758e9fbaSOystein Eftevaag         "union selector is incorrect",
263*758e9fbaSOystein Eftevaag         /* 0x19 - EMPTY */
264*758e9fbaSOystein Eftevaag         NULL,
265*758e9fbaSOystein Eftevaag         /* 0x1A - TPM2_RC_INSUFFICIENT */
266*758e9fbaSOystein Eftevaag         "the TPM was unable to unmarshal a value because there were not enough"
267*758e9fbaSOystein Eftevaag         " octets in the input buffer",
268*758e9fbaSOystein Eftevaag         /* 0x1B - TPM2_RC_SIGNATURE */
269*758e9fbaSOystein Eftevaag         "the signature is not valid",
270*758e9fbaSOystein Eftevaag         /* 0x1C - TPM2_RC_KEY */
271*758e9fbaSOystein Eftevaag         "key fields are not compatible with the selected use",
272*758e9fbaSOystein Eftevaag         /* 0x1D - TPM2_RC_POLICY_FAIL */
273*758e9fbaSOystein Eftevaag         "a policy check failed",
274*758e9fbaSOystein Eftevaag         /* 0x1E - EMPTY */
275*758e9fbaSOystein Eftevaag         NULL,
276*758e9fbaSOystein Eftevaag         /* 0x1F - TPM2_RC_INTEGRITY */
277*758e9fbaSOystein Eftevaag         "integrity check failed",
278*758e9fbaSOystein Eftevaag         /* 0x20 - TPM2_RC_TICKET */
279*758e9fbaSOystein Eftevaag         "invalid ticket",
280*758e9fbaSOystein Eftevaag         /* 0x21 - TPM2_RC_RESERVED_BITS */
281*758e9fbaSOystein Eftevaag         "reserved bits not set to zero as required",
282*758e9fbaSOystein Eftevaag         /* 0x22 - TPM2_RC_BAD_AUTH */
283*758e9fbaSOystein Eftevaag         "authorization failure without DA implications",
284*758e9fbaSOystein Eftevaag         /* 0x23 - TPM2_RC_EXPIRED */
285*758e9fbaSOystein Eftevaag         "the policy has expired",
286*758e9fbaSOystein Eftevaag         /* 0x24 - TPM2_RC_POLICY_CC */
287*758e9fbaSOystein Eftevaag         "the commandCode in the policy is not the commandCode of the command"
288*758e9fbaSOystein Eftevaag         " or the command code in a policy command references a command that"
289*758e9fbaSOystein Eftevaag         " is not implemented",
290*758e9fbaSOystein Eftevaag         /* 0x25 - TPM2_RC_BINDING */
291*758e9fbaSOystein Eftevaag         "public and sensitive portions of an object are not cryptographically bound",
292*758e9fbaSOystein Eftevaag         /* 0x26 - TPM2_RC_CURVE */
293*758e9fbaSOystein Eftevaag         "curve not supported",
294*758e9fbaSOystein Eftevaag         /* 0x27 - TPM2_RC_ECC_POINT */
295*758e9fbaSOystein Eftevaag         "point is not on the required curve",
296*758e9fbaSOystein Eftevaag     };
297*758e9fbaSOystein Eftevaag 
298*758e9fbaSOystein Eftevaag     static __thread char buf[TSS2_ERR_LAYER_ERROR_STR_MAX + 1];
299*758e9fbaSOystein Eftevaag 
300*758e9fbaSOystein Eftevaag     clearbuf(buf);
301*758e9fbaSOystein Eftevaag 
302*758e9fbaSOystein Eftevaag     /* Print whether or not the error is caused by a bad
303*758e9fbaSOystein Eftevaag      * handle or parameter. On the case of a Handle (P == 0)
304*758e9fbaSOystein Eftevaag      * then the N field top bit will be set. Un-set this bit
305*758e9fbaSOystein Eftevaag      * to get the handle index by subtracting 8 as N is a 4
306*758e9fbaSOystein Eftevaag      * bit field.
307*758e9fbaSOystein Eftevaag      *
308*758e9fbaSOystein Eftevaag      * the lower 3 bits of N indicate index, and the high bit
309*758e9fbaSOystein Eftevaag      * indicates
310*758e9fbaSOystein Eftevaag      */
311*758e9fbaSOystein Eftevaag     UINT8 index = tpm2_rc_fmt1_N_index_get(rc);
312*758e9fbaSOystein Eftevaag 
313*758e9fbaSOystein Eftevaag     bool is_handle = tpm2_rc_fmt1_N_is_handle(rc);
314*758e9fbaSOystein Eftevaag     const char *m = tpm2_rc_fmt1_P_get(rc) ? "parameter" :
315*758e9fbaSOystein Eftevaag                     is_handle ? "handle" : "session";
316*758e9fbaSOystein Eftevaag     catbuf(buf, "%s", m);
317*758e9fbaSOystein Eftevaag 
318*758e9fbaSOystein Eftevaag     if (index) {
319*758e9fbaSOystein Eftevaag         catbuf(buf, "(%u):", index);
320*758e9fbaSOystein Eftevaag     } else {
321*758e9fbaSOystein Eftevaag         catbuf(buf, "%s", "(unk):");
322*758e9fbaSOystein Eftevaag     }
323*758e9fbaSOystein Eftevaag 
324*758e9fbaSOystein Eftevaag     UINT8 errnum = tpm2_rc_fmt1_error_get(rc);
325*758e9fbaSOystein Eftevaag     if (errnum < ARRAY_LEN(fmt1_err_strs)) {
326*758e9fbaSOystein Eftevaag         m = fmt1_err_strs[errnum];
327*758e9fbaSOystein Eftevaag         catbuf(buf, "%s", m);
328*758e9fbaSOystein Eftevaag     } else {
329*758e9fbaSOystein Eftevaag         catbuf(buf, "unknown error num: 0x%X", errnum);
330*758e9fbaSOystein Eftevaag     }
331*758e9fbaSOystein Eftevaag 
332*758e9fbaSOystein Eftevaag     return buf;
333*758e9fbaSOystein Eftevaag }
334*758e9fbaSOystein Eftevaag 
335*758e9fbaSOystein Eftevaag static const char *
tpm2_err_handler_fmt0(TSS2_RC rc)336*758e9fbaSOystein Eftevaag tpm2_err_handler_fmt0(TSS2_RC rc)
337*758e9fbaSOystein Eftevaag {
338*758e9fbaSOystein Eftevaag     /*
339*758e9fbaSOystein Eftevaag      * format 0 error codes start at 1, so
340*758e9fbaSOystein Eftevaag      * add a NULL entry to index 0.
341*758e9fbaSOystein Eftevaag      * Thus, no need to offset the error bits
342*758e9fbaSOystein Eftevaag      * and fmt0 and fmt1 arrays can be used
343*758e9fbaSOystein Eftevaag      * in-place of each other for lookups.
344*758e9fbaSOystein Eftevaag      */
345*758e9fbaSOystein Eftevaag     static const char *fmt0_warn_strs[] = {
346*758e9fbaSOystein Eftevaag             /* 0x0 - EMPTY */
347*758e9fbaSOystein Eftevaag             NULL,
348*758e9fbaSOystein Eftevaag             /* 0x1 - TPM2_RC_CONTEXT_GAP */
349*758e9fbaSOystein Eftevaag             "gap for context ID is too large",
350*758e9fbaSOystein Eftevaag             /* 0x2 - TPM2_RC_OBJECT_MEMORY */
351*758e9fbaSOystein Eftevaag             "out of memory for object contexts",
352*758e9fbaSOystein Eftevaag             /* 0x3 - TPM2_RC_SESSION_MEMORY */
353*758e9fbaSOystein Eftevaag             "out of memory for session contexts",
354*758e9fbaSOystein Eftevaag             /* 0x4 - TPM2_RC_MEMORY */
355*758e9fbaSOystein Eftevaag             "out of shared objectsession memory or need space for internal"
356*758e9fbaSOystein Eftevaag             " operations",
357*758e9fbaSOystein Eftevaag             /* 0x5 - TPM2_RC_SESSION_HANDLES */
358*758e9fbaSOystein Eftevaag             "out of session handles",
359*758e9fbaSOystein Eftevaag             /* 0x6 - TPM2_RC_OBJECT_HANDLES */
360*758e9fbaSOystein Eftevaag             "out of object handles",
361*758e9fbaSOystein Eftevaag             /* 0x7 - TPM2_RC_LOCALITY */
362*758e9fbaSOystein Eftevaag             "bad locality",
363*758e9fbaSOystein Eftevaag             /* 0x8 - TPM2_RC_YIELDED */
364*758e9fbaSOystein Eftevaag             "the TPM has suspended operation on the command forward progress"
365*758e9fbaSOystein Eftevaag             " was made and the command may be retried",
366*758e9fbaSOystein Eftevaag             /* 0x9 - TPM2_RC_CANCELED */
367*758e9fbaSOystein Eftevaag             "the command was canceled",
368*758e9fbaSOystein Eftevaag             /* 0xA - TPM2_RC_TESTING */
369*758e9fbaSOystein Eftevaag             "TPM is performing selftests",
370*758e9fbaSOystein Eftevaag             /* 0xB - EMPTY */
371*758e9fbaSOystein Eftevaag             NULL,
372*758e9fbaSOystein Eftevaag             /* 0xC - EMPTY */
373*758e9fbaSOystein Eftevaag             NULL,
374*758e9fbaSOystein Eftevaag             /* 0xD - EMPTY */
375*758e9fbaSOystein Eftevaag             NULL,
376*758e9fbaSOystein Eftevaag             /* 0xE - EMPTY */
377*758e9fbaSOystein Eftevaag             NULL,
378*758e9fbaSOystein Eftevaag             /* 0xF - EMPTY */
379*758e9fbaSOystein Eftevaag             NULL,
380*758e9fbaSOystein Eftevaag             /* 0x10 - TPM2_RC_REFERENCE_H0 */
381*758e9fbaSOystein Eftevaag             "the 1st handle in the handle area references a transient object"
382*758e9fbaSOystein Eftevaag             " or session that is not loaded",
383*758e9fbaSOystein Eftevaag             /* 0x11 - TPM2_RC_REFERENCE_H1 */
384*758e9fbaSOystein Eftevaag             "the 2nd handle in the handle area references a transient object"
385*758e9fbaSOystein Eftevaag             " or session that is not loaded",
386*758e9fbaSOystein Eftevaag             /* 0x12 - TPM2_RC_REFERENCE_H2 */
387*758e9fbaSOystein Eftevaag             "the 3rd handle in the handle area references a transient object"
388*758e9fbaSOystein Eftevaag             " or session that is not loaded",
389*758e9fbaSOystein Eftevaag             /* 0x13 - TPM2_RC_REFERENCE_H3 */
390*758e9fbaSOystein Eftevaag             "the 4th handle in the handle area references a transient object"
391*758e9fbaSOystein Eftevaag             " or session that is not loaded",
392*758e9fbaSOystein Eftevaag             /* 0x14 - TPM2_RC_REFERENCE_H4 */
393*758e9fbaSOystein Eftevaag             "the 5th handle in the handle area references a transient object"
394*758e9fbaSOystein Eftevaag             " or session that is not loaded",
395*758e9fbaSOystein Eftevaag             /* 0x15 - TPM2_RC_REFERENCE_H5 */
396*758e9fbaSOystein Eftevaag             "the 6th handle in the handle area references a transient object"
397*758e9fbaSOystein Eftevaag             " or session that is not loaded",
398*758e9fbaSOystein Eftevaag             /* 0x16 - TPM2_RC_REFERENCE_H6 */
399*758e9fbaSOystein Eftevaag             "the 7th handle in the handle area references a transient object"
400*758e9fbaSOystein Eftevaag             " or session that is not loaded",
401*758e9fbaSOystein Eftevaag             /* 0x17 - EMPTY, */
402*758e9fbaSOystein Eftevaag             NULL,
403*758e9fbaSOystein Eftevaag             /* 0x18 - TPM2_RC_REFERENCE_S0 */
404*758e9fbaSOystein Eftevaag             "the 1st authorization session handle references a session that"
405*758e9fbaSOystein Eftevaag             " is not loaded",
406*758e9fbaSOystein Eftevaag             /* 0x19 - TPM2_RC_REFERENCE_S1 */
407*758e9fbaSOystein Eftevaag             "the 2nd authorization session handle references a session that"
408*758e9fbaSOystein Eftevaag             " is not loaded",
409*758e9fbaSOystein Eftevaag             /* 0x1A - TPM2_RC_REFERENCE_S2 */
410*758e9fbaSOystein Eftevaag             "the 3rd authorization session handle references a session that"
411*758e9fbaSOystein Eftevaag             " is not loaded",
412*758e9fbaSOystein Eftevaag             /* 0x1B - TPM2_RC_REFERENCE_S3 */
413*758e9fbaSOystein Eftevaag             "the 4th authorization session handle references a session that"
414*758e9fbaSOystein Eftevaag             " is not loaded",
415*758e9fbaSOystein Eftevaag             /* 0x1C - TPM2_RC_REFERENCE_S4 */
416*758e9fbaSOystein Eftevaag             "the 5th session handle references a session that"
417*758e9fbaSOystein Eftevaag             " is not loaded",
418*758e9fbaSOystein Eftevaag             /* 0x1D - TPM2_RC_REFERENCE_S5 */
419*758e9fbaSOystein Eftevaag             "the 6th session handle references a session that"
420*758e9fbaSOystein Eftevaag             " is not loaded",
421*758e9fbaSOystein Eftevaag             /* 0x1E - TPM2_RC_REFERENCE_S6 */
422*758e9fbaSOystein Eftevaag             "the 7th authorization session handle references a session that"
423*758e9fbaSOystein Eftevaag             " is not loaded",
424*758e9fbaSOystein Eftevaag             /* 0x1F - EMPTY, */
425*758e9fbaSOystein Eftevaag             NULL,
426*758e9fbaSOystein Eftevaag             /* 0x20 -TPM2_RC_NV_RATE */
427*758e9fbaSOystein Eftevaag             "the TPM is rate limiting accesses to prevent wearout of NV",
428*758e9fbaSOystein Eftevaag             /* 0x21 - TPM2_RC_LOCKOUT */
429*758e9fbaSOystein Eftevaag             "authorizations for objects subject to DA protection are not"
430*758e9fbaSOystein Eftevaag             " allowed at this time because the TPM is in DA lockout mode",
431*758e9fbaSOystein Eftevaag             /* 0x22 - TPM2_RC_RETRY */
432*758e9fbaSOystein Eftevaag             "the TPM was not able to start the command",
433*758e9fbaSOystein Eftevaag             /* 0x23 - TPM2_RC_NV_UNAVAILABLE */
434*758e9fbaSOystein Eftevaag             "the command may require writing of NV and NV is not current"
435*758e9fbaSOystein Eftevaag             " accessible",
436*758e9fbaSOystein Eftevaag     };
437*758e9fbaSOystein Eftevaag 
438*758e9fbaSOystein Eftevaag     /*
439*758e9fbaSOystein Eftevaag      * format 1 error codes start at 0, so
440*758e9fbaSOystein Eftevaag      * no need to offset the error bits.
441*758e9fbaSOystein Eftevaag      */
442*758e9fbaSOystein Eftevaag     static const char *fmt0_err_strs[] = {
443*758e9fbaSOystein Eftevaag         /* 0x0 - TPM2_RC_INITIALIZE */
444*758e9fbaSOystein Eftevaag         "TPM not initialized by TPM2_Startup or already initialized",
445*758e9fbaSOystein Eftevaag         /* 0x1 - TPM2_RC_FAILURE */
446*758e9fbaSOystein Eftevaag         "commands not being accepted because of a TPM failure",
447*758e9fbaSOystein Eftevaag         /* 0x2 - EMPTY */
448*758e9fbaSOystein Eftevaag         NULL,
449*758e9fbaSOystein Eftevaag         /* 0x3 - TPM2_RC_SEQUENCE */
450*758e9fbaSOystein Eftevaag         "improper use of a sequence handle",
451*758e9fbaSOystein Eftevaag         /* 0x4 - EMPTY */
452*758e9fbaSOystein Eftevaag         NULL,
453*758e9fbaSOystein Eftevaag         /* 0x5 - EMPTY */
454*758e9fbaSOystein Eftevaag         NULL,
455*758e9fbaSOystein Eftevaag         /* 0x6 - EMPTY */
456*758e9fbaSOystein Eftevaag         NULL,
457*758e9fbaSOystein Eftevaag         /* 0x7 - EMPTY */
458*758e9fbaSOystein Eftevaag         NULL,
459*758e9fbaSOystein Eftevaag         /* 0x8 - EMPTY */
460*758e9fbaSOystein Eftevaag         NULL,
461*758e9fbaSOystein Eftevaag         /* 0x9 - EMPTY */
462*758e9fbaSOystein Eftevaag         NULL,
463*758e9fbaSOystein Eftevaag         /* 0xA - EMPTY */
464*758e9fbaSOystein Eftevaag         NULL,
465*758e9fbaSOystein Eftevaag         /* 0xB - TPM2_RC_PRIVATE */
466*758e9fbaSOystein Eftevaag         "not currently used",
467*758e9fbaSOystein Eftevaag         /* 0xC - EMPTY */
468*758e9fbaSOystein Eftevaag         NULL,
469*758e9fbaSOystein Eftevaag         /* 0xD - EMPTY */
470*758e9fbaSOystein Eftevaag         NULL,
471*758e9fbaSOystein Eftevaag         /* 0xE - EMPTY */
472*758e9fbaSOystein Eftevaag         NULL,
473*758e9fbaSOystein Eftevaag         /* 0xF - EMPTY */
474*758e9fbaSOystein Eftevaag         NULL,
475*758e9fbaSOystein Eftevaag         /* 0x10 - EMPTY */
476*758e9fbaSOystein Eftevaag         NULL,
477*758e9fbaSOystein Eftevaag         /* 0x11 - EMPTY */
478*758e9fbaSOystein Eftevaag         NULL,
479*758e9fbaSOystein Eftevaag         /* 0x12 - EMPTY */
480*758e9fbaSOystein Eftevaag         NULL,
481*758e9fbaSOystein Eftevaag         /* 0x13 - EMPTY */
482*758e9fbaSOystein Eftevaag         NULL,
483*758e9fbaSOystein Eftevaag         /* 0x14 - EMPTY */
484*758e9fbaSOystein Eftevaag         NULL,
485*758e9fbaSOystein Eftevaag         /* 0x15 - EMPTY */
486*758e9fbaSOystein Eftevaag         NULL,
487*758e9fbaSOystein Eftevaag         /* 0x16 - EMPTY */
488*758e9fbaSOystein Eftevaag         NULL,
489*758e9fbaSOystein Eftevaag         /* 0x17 - EMPTY */
490*758e9fbaSOystein Eftevaag         NULL,
491*758e9fbaSOystein Eftevaag         /* 0x18 - EMPTY */
492*758e9fbaSOystein Eftevaag         NULL,
493*758e9fbaSOystein Eftevaag         /* 0x19 - TPM2_RC_HMAC */
494*758e9fbaSOystein Eftevaag         "not currently used",
495*758e9fbaSOystein Eftevaag         /* 0x1A - EMPTY */
496*758e9fbaSOystein Eftevaag         NULL,
497*758e9fbaSOystein Eftevaag         /* 0x1B - EMPTY */
498*758e9fbaSOystein Eftevaag         NULL,
499*758e9fbaSOystein Eftevaag         /* 0x1C - EMPTY */
500*758e9fbaSOystein Eftevaag         NULL,
501*758e9fbaSOystein Eftevaag         /* 0x1D - EMPTY */
502*758e9fbaSOystein Eftevaag         NULL,
503*758e9fbaSOystein Eftevaag         /* 0x1E - EMPTY */
504*758e9fbaSOystein Eftevaag         NULL,
505*758e9fbaSOystein Eftevaag         /* 0x1F - EMPTY */
506*758e9fbaSOystein Eftevaag         NULL,
507*758e9fbaSOystein Eftevaag         /* 0x20 - TPM2_RC_DISABLED */
508*758e9fbaSOystein Eftevaag         "the command is disabled",
509*758e9fbaSOystein Eftevaag         /* 0x21 - TPM2_RC_EXCLUSIVE */
510*758e9fbaSOystein Eftevaag         "command failed because audit sequence required exclusivity",
511*758e9fbaSOystein Eftevaag         /* 0x22 - EMPTY */
512*758e9fbaSOystein Eftevaag         NULL,
513*758e9fbaSOystein Eftevaag         /* 0x23 - EMPTY, */
514*758e9fbaSOystein Eftevaag         NULL,
515*758e9fbaSOystein Eftevaag         /* 0x24 - TPM2_RC_AUTH_TYPE */
516*758e9fbaSOystein Eftevaag         "authorization handle is not correct for command",
517*758e9fbaSOystein Eftevaag         /* 0x25 - TPM2_RC_AUTH_MISSING */
518*758e9fbaSOystein Eftevaag         "command requires an authorization session for handle and it is"
519*758e9fbaSOystein Eftevaag         " not present",
520*758e9fbaSOystein Eftevaag         /* 0x26 - TPM2_RC_POLICY */
521*758e9fbaSOystein Eftevaag         "policy failure in math operation or an invalid authPolicy value",
522*758e9fbaSOystein Eftevaag         /* 0x27 - TPM2_RC_PCR */
523*758e9fbaSOystein Eftevaag         "PCR check fail",
524*758e9fbaSOystein Eftevaag         /* 0x28 - TPM2_RC_PCR_CHANGED */
525*758e9fbaSOystein Eftevaag         "PCR have changed since checked",
526*758e9fbaSOystein Eftevaag         /* 0x29 - EMPTY */
527*758e9fbaSOystein Eftevaag         NULL,
528*758e9fbaSOystein Eftevaag         /* 0x2A - EMPTY */
529*758e9fbaSOystein Eftevaag         NULL,
530*758e9fbaSOystein Eftevaag         /* 0x2B - EMPTY */
531*758e9fbaSOystein Eftevaag         NULL,
532*758e9fbaSOystein Eftevaag         /* 0x2C - EMPTY */
533*758e9fbaSOystein Eftevaag         NULL,
534*758e9fbaSOystein Eftevaag         /* 0x2D - TPM2_RC_UPGRADE */
535*758e9fbaSOystein Eftevaag         "For all commands, other than TPM2_FieldUpgradeData, "
536*758e9fbaSOystein Eftevaag         "this code indicates that the TPM is in field upgrade mode. "
537*758e9fbaSOystein Eftevaag         "For TPM2_FieldUpgradeData, this code indicates that the TPM "
538*758e9fbaSOystein Eftevaag         "is not in field upgrade mode",
539*758e9fbaSOystein Eftevaag         /* 0x2E - TPM2_RC_TOO_MANY_CONTEXTS */
540*758e9fbaSOystein Eftevaag         "context ID counter is at maximum",
541*758e9fbaSOystein Eftevaag         /* 0x2F - TPM2_RC_AUTH_UNAVAILABLE */
542*758e9fbaSOystein Eftevaag         "authValue or authPolicy is not available for selected entity",
543*758e9fbaSOystein Eftevaag         /* 0x30 - TPM2_RC_REBOOT */
544*758e9fbaSOystein Eftevaag         "a _TPM_Init and StartupCLEAR is required before the TPM can"
545*758e9fbaSOystein Eftevaag         " resume operation",
546*758e9fbaSOystein Eftevaag         /* 0x31 - TPM2_RC_UNBALANCED */
547*758e9fbaSOystein Eftevaag         "the protection algorithms hash and symmetric are not reasonably"
548*758e9fbaSOystein Eftevaag         " balanced. The digest size of the hash must be larger than the key"
549*758e9fbaSOystein Eftevaag         " size of the symmetric algorithm.",
550*758e9fbaSOystein Eftevaag         /* 0x32 - EMPTY */
551*758e9fbaSOystein Eftevaag         NULL,
552*758e9fbaSOystein Eftevaag         /* 0x33 - EMPTY */
553*758e9fbaSOystein Eftevaag         NULL,
554*758e9fbaSOystein Eftevaag         /* 0x34 - EMPTY */
555*758e9fbaSOystein Eftevaag         NULL,
556*758e9fbaSOystein Eftevaag         /* 0x35 - EMPTY */
557*758e9fbaSOystein Eftevaag         NULL,
558*758e9fbaSOystein Eftevaag         /* 0x36 - EMPTY */
559*758e9fbaSOystein Eftevaag         NULL,
560*758e9fbaSOystein Eftevaag         /* 0x37 - EMPTY */
561*758e9fbaSOystein Eftevaag         NULL,
562*758e9fbaSOystein Eftevaag         /* 0x38 - EMPTY */
563*758e9fbaSOystein Eftevaag         NULL,
564*758e9fbaSOystein Eftevaag         /* 0x39 - EMPTY */
565*758e9fbaSOystein Eftevaag         NULL,
566*758e9fbaSOystein Eftevaag         /* 0x3A - EMPTY */
567*758e9fbaSOystein Eftevaag         NULL,
568*758e9fbaSOystein Eftevaag         /* 0x3B - EMPTY */
569*758e9fbaSOystein Eftevaag         NULL,
570*758e9fbaSOystein Eftevaag         /* 0x3C - EMPTY */
571*758e9fbaSOystein Eftevaag         NULL,
572*758e9fbaSOystein Eftevaag         /* 0x3D - EMPTY */
573*758e9fbaSOystein Eftevaag         NULL,
574*758e9fbaSOystein Eftevaag         /* 0x3E - EMPTY */
575*758e9fbaSOystein Eftevaag         NULL,
576*758e9fbaSOystein Eftevaag         /* 0x3F - EMPTY */
577*758e9fbaSOystein Eftevaag         NULL,
578*758e9fbaSOystein Eftevaag         /* 0x40 - EMPTY */
579*758e9fbaSOystein Eftevaag         NULL,
580*758e9fbaSOystein Eftevaag         /* 0x41 - EMPTY */
581*758e9fbaSOystein Eftevaag         NULL,
582*758e9fbaSOystein Eftevaag         /* 0x42 - TPM2_RC_COMMAND_SIZE */
583*758e9fbaSOystein Eftevaag         "command commandSize value is inconsistent with contents of the"
584*758e9fbaSOystein Eftevaag         " command buffer. Either the size is not the same as the octets"
585*758e9fbaSOystein Eftevaag         " loaded by the hardware interface layer or the value is not large"
586*758e9fbaSOystein Eftevaag         " enough to hold a command header",
587*758e9fbaSOystein Eftevaag         /* 0x43 - TPM2_RC_COMMAND_CODE */
588*758e9fbaSOystein Eftevaag         "command code not supported",
589*758e9fbaSOystein Eftevaag         /* 0x44 - TPM2_RC_AUTHSIZE */
590*758e9fbaSOystein Eftevaag         "the value of authorizationSize is out of range or the number of"
591*758e9fbaSOystein Eftevaag         " octets in the Authorization Area is greater than required",
592*758e9fbaSOystein Eftevaag         /* 0x45 - TPM2_RC_AUTH_CONTEXT */
593*758e9fbaSOystein Eftevaag         "use of an authorization session with a context command or another"
594*758e9fbaSOystein Eftevaag         " command that cannot have an authorization session",
595*758e9fbaSOystein Eftevaag         /* 0x46 - TPM2_RC_NV_RANGE */
596*758e9fbaSOystein Eftevaag         "NV offset+size is out of range",
597*758e9fbaSOystein Eftevaag         /* 0x47 - TPM2_RC_NV_SIZE */
598*758e9fbaSOystein Eftevaag         "Requested allocation size is larger than allowed",
599*758e9fbaSOystein Eftevaag         /* 0x48 - TPM2_RC_NV_LOCKED */
600*758e9fbaSOystein Eftevaag         "NV access locked",
601*758e9fbaSOystein Eftevaag         /* 0x49 - TPM2_RC_NV_AUTHORIZATION */
602*758e9fbaSOystein Eftevaag         "NV access authorization fails in command actions",
603*758e9fbaSOystein Eftevaag         /* 0x4A - TPM2_RC_NV_UNINITIALIZED */
604*758e9fbaSOystein Eftevaag         "an NV Index is used before being initialized or the state saved"
605*758e9fbaSOystein Eftevaag         " by TPM2_ShutdownSTATE could not be restored",
606*758e9fbaSOystein Eftevaag         /* 0x4B - TPM2_RC_NV_SPACE */
607*758e9fbaSOystein Eftevaag         "insufficient space for NV allocation",
608*758e9fbaSOystein Eftevaag         /* 0x4C - TPM2_RC_NV_DEFINED */
609*758e9fbaSOystein Eftevaag         "NV Index or persistent object already defined",
610*758e9fbaSOystein Eftevaag         /* 0x4D - EMPTY */
611*758e9fbaSOystein Eftevaag         NULL,
612*758e9fbaSOystein Eftevaag         /* 0x4E - EMPTY */
613*758e9fbaSOystein Eftevaag         NULL,
614*758e9fbaSOystein Eftevaag         /* 0x4F - EMPTY */
615*758e9fbaSOystein Eftevaag         NULL,
616*758e9fbaSOystein Eftevaag         /* 0x50 - TPM2_RC_BAD_CONTEXT */
617*758e9fbaSOystein Eftevaag         "context in TPM2_ContextLoad is not valid",
618*758e9fbaSOystein Eftevaag         /* 0x51 - TPM2_RC_CPHASH */
619*758e9fbaSOystein Eftevaag         "cpHash value already set or not correct for use",
620*758e9fbaSOystein Eftevaag         /* 0x52 - TPM2_RC_PARENT */
621*758e9fbaSOystein Eftevaag         "handle for parent is not a valid parent",
622*758e9fbaSOystein Eftevaag         /* 0x53 - TPM2_RC_NEEDS_TEST */
623*758e9fbaSOystein Eftevaag         "some function needs testing",
624*758e9fbaSOystein Eftevaag         /* 0x54 - TPM2_RC_NO_RESULT */
625*758e9fbaSOystein Eftevaag         "returned when an internal function cannot process a request due to"
626*758e9fbaSOystein Eftevaag         " an unspecified problem. This code is usually related to invalid"
627*758e9fbaSOystein Eftevaag         " parameters that are not properly filtered by the input"
628*758e9fbaSOystein Eftevaag         " unmarshaling code",
629*758e9fbaSOystein Eftevaag         /* 0x55 - TPM2_RC_SENSITIVE */
630*758e9fbaSOystein Eftevaag         "the sensitive area did not unmarshal correctly after decryption",
631*758e9fbaSOystein Eftevaag     };
632*758e9fbaSOystein Eftevaag 
633*758e9fbaSOystein Eftevaag     static __thread char buf[TSS2_ERR_LAYER_ERROR_STR_MAX + 1];
634*758e9fbaSOystein Eftevaag 
635*758e9fbaSOystein Eftevaag     clearbuf(buf);
636*758e9fbaSOystein Eftevaag 
637*758e9fbaSOystein Eftevaag     char *e = tpm2_rc_fmt0_S_get(rc) ? "warn" : "error";
638*758e9fbaSOystein Eftevaag     char *v = tpm2_rc_tpm_fmt0_V_get(rc) ? "2.0" : "1.2";
639*758e9fbaSOystein Eftevaag     catbuf(buf, "%s(%s): ", e, v);
640*758e9fbaSOystein Eftevaag 
641*758e9fbaSOystein Eftevaag     UINT8 errnum = tpm2_rc_fmt0_error_get(rc);
642*758e9fbaSOystein Eftevaag     /* We only have version 2.0 spec codes defined */
643*758e9fbaSOystein Eftevaag     if (tpm2_rc_tpm_fmt0_V_get(rc)) {
644*758e9fbaSOystein Eftevaag         /* TCG specific error code */
645*758e9fbaSOystein Eftevaag         if (tpm2_rc_fmt0_T_get(rc)) {
646*758e9fbaSOystein Eftevaag             catbuf(buf, "Vendor specific error: 0x%X", errnum);
647*758e9fbaSOystein Eftevaag             return buf;
648*758e9fbaSOystein Eftevaag         }
649*758e9fbaSOystein Eftevaag 
650*758e9fbaSOystein Eftevaag         /* is it a warning (version 2 error string) or is it a 1.2 error? */
651*758e9fbaSOystein Eftevaag         size_t len =
652*758e9fbaSOystein Eftevaag                 tpm2_rc_fmt0_S_get(rc) ?
653*758e9fbaSOystein Eftevaag                         ARRAY_LEN(fmt0_warn_strs) : ARRAY_LEN(fmt0_err_strs);
654*758e9fbaSOystein Eftevaag         const char **selection =
655*758e9fbaSOystein Eftevaag                 tpm2_rc_fmt0_S_get(rc) ? fmt0_warn_strs : fmt0_err_strs;
656*758e9fbaSOystein Eftevaag         if (errnum >= len) {
657*758e9fbaSOystein Eftevaag             return NULL;
658*758e9fbaSOystein Eftevaag         }
659*758e9fbaSOystein Eftevaag 
660*758e9fbaSOystein Eftevaag         const char *m = selection[errnum];
661*758e9fbaSOystein Eftevaag         if (!m) {
662*758e9fbaSOystein Eftevaag             return NULL;
663*758e9fbaSOystein Eftevaag         }
664*758e9fbaSOystein Eftevaag 
665*758e9fbaSOystein Eftevaag         catbuf(buf, "%s", m);
666*758e9fbaSOystein Eftevaag         return buf;
667*758e9fbaSOystein Eftevaag     }
668*758e9fbaSOystein Eftevaag 
669*758e9fbaSOystein Eftevaag     catbuf(buf, "%s", "unknown version 1.2 error code");
670*758e9fbaSOystein Eftevaag 
671*758e9fbaSOystein Eftevaag     return buf;
672*758e9fbaSOystein Eftevaag }
673*758e9fbaSOystein Eftevaag 
674*758e9fbaSOystein Eftevaag /**
675*758e9fbaSOystein Eftevaag  * Retrieves the layer field from a TSS2_RC code.
676*758e9fbaSOystein Eftevaag  * @param rc
677*758e9fbaSOystein Eftevaag  *  The rc to query the layer index of.
678*758e9fbaSOystein Eftevaag  * @return
679*758e9fbaSOystein Eftevaag  *  The layer index.
680*758e9fbaSOystein Eftevaag  */
681*758e9fbaSOystein Eftevaag static inline UINT8
tss2_rc_layer_format_get(TSS2_RC rc)682*758e9fbaSOystein Eftevaag tss2_rc_layer_format_get(TSS2_RC rc)
683*758e9fbaSOystein Eftevaag {
684*758e9fbaSOystein Eftevaag     return ((rc & (1 << 7)) >> 7);
685*758e9fbaSOystein Eftevaag }
686*758e9fbaSOystein Eftevaag 
687*758e9fbaSOystein Eftevaag /**
688*758e9fbaSOystein Eftevaag  * Handler for tpm2 error codes. ie codes
689*758e9fbaSOystein Eftevaag  * coming from the tpm layer aka layer 0.
690*758e9fbaSOystein Eftevaag  * @param rc
691*758e9fbaSOystein Eftevaag  *  The rc to decode.
692*758e9fbaSOystein Eftevaag  * @return
693*758e9fbaSOystein Eftevaag  *  An error string.
694*758e9fbaSOystein Eftevaag  */
695*758e9fbaSOystein Eftevaag static const char *
tpm2_ehandler(TSS2_RC rc)696*758e9fbaSOystein Eftevaag tpm2_ehandler(TSS2_RC rc)
697*758e9fbaSOystein Eftevaag {
698*758e9fbaSOystein Eftevaag     bool is_fmt_1 = tss2_rc_layer_format_get(rc);
699*758e9fbaSOystein Eftevaag 
700*758e9fbaSOystein Eftevaag     return is_fmt_1 ? tpm2_err_handler_fmt1(rc) : tpm2_err_handler_fmt0(rc);
701*758e9fbaSOystein Eftevaag }
702*758e9fbaSOystein Eftevaag 
703*758e9fbaSOystein Eftevaag /**
704*758e9fbaSOystein Eftevaag  * The default system code handler. This handles codes
705*758e9fbaSOystein Eftevaag  * from the RM (itself and simulated tpm responses), the marshaling
706*758e9fbaSOystein Eftevaag  * library (mu), the tcti layers, sapi, esys and fapi.
707*758e9fbaSOystein Eftevaag  * @param rc
708*758e9fbaSOystein Eftevaag  *  The rc to decode.
709*758e9fbaSOystein Eftevaag  * @return
710*758e9fbaSOystein Eftevaag  *  An error string.
711*758e9fbaSOystein Eftevaag  */
712*758e9fbaSOystein Eftevaag static const char *
tss_err_handler(TSS2_RC rc)713*758e9fbaSOystein Eftevaag tss_err_handler (TSS2_RC rc)
714*758e9fbaSOystein Eftevaag {
715*758e9fbaSOystein Eftevaag     /*
716*758e9fbaSOystein Eftevaag      * subtract 1 from the error number
717*758e9fbaSOystein Eftevaag      * before indexing into this array.
718*758e9fbaSOystein Eftevaag      *
719*758e9fbaSOystein Eftevaag      * Commented offsets are for the corresponding
720*758e9fbaSOystein Eftevaag      * error number *before* subtraction. Ie error
721*758e9fbaSOystein Eftevaag      * number 4 is at array index 3.
722*758e9fbaSOystein Eftevaag      */
723*758e9fbaSOystein Eftevaag     static const char *errors[] =   {
724*758e9fbaSOystein Eftevaag         /* 1 - TSS2_BASE_RC_GENERAL_FAILURE */
725*758e9fbaSOystein Eftevaag         "Catch all for all errors not otherwise specified",
726*758e9fbaSOystein Eftevaag         /* 2 - TSS2_BASE_RC_NOT_IMPLEMENTED */
727*758e9fbaSOystein Eftevaag         "If called functionality isn't implemented",
728*758e9fbaSOystein Eftevaag         /* 3 - TSS2_BASE_RC_BAD_CONTEXT */
729*758e9fbaSOystein Eftevaag         "A context structure is bad",
730*758e9fbaSOystein Eftevaag         /* 4 - TSS2_BASE_RC_ABI_MISMATCH */
731*758e9fbaSOystein Eftevaag         "Passed in ABI version doesn't match called module's ABI version",
732*758e9fbaSOystein Eftevaag         /* 5 - TSS2_BASE_RC_BAD_REFERENCE */
733*758e9fbaSOystein Eftevaag         "A pointer is NULL that isn't allowed to be NULL.",
734*758e9fbaSOystein Eftevaag         /* 6 - TSS2_BASE_RC_INSUFFICIENT_BUFFER */
735*758e9fbaSOystein Eftevaag         "A buffer isn't large enough",
736*758e9fbaSOystein Eftevaag         /* 7 - TSS2_BASE_RC_BAD_SEQUENCE */
737*758e9fbaSOystein Eftevaag         "Function called in the wrong order",
738*758e9fbaSOystein Eftevaag         /* 8 - TSS2_BASE_RC_NO_CONNECTION */
739*758e9fbaSOystein Eftevaag         "Fails to connect to next lower layer",
740*758e9fbaSOystein Eftevaag         /* 9 - TSS2_BASE_RC_TRY_AGAIN */
741*758e9fbaSOystein Eftevaag         "Operation timed out; function must be called again to be completed",
742*758e9fbaSOystein Eftevaag         /* 10 - TSS2_BASE_RC_IO_ERROR */
743*758e9fbaSOystein Eftevaag         "IO failure",
744*758e9fbaSOystein Eftevaag         /* 11 - TSS2_BASE_RC_BAD_VALUE */
745*758e9fbaSOystein Eftevaag         "A parameter has a bad value",
746*758e9fbaSOystein Eftevaag         /* 12 - TSS2_BASE_RC_NOT_PERMITTED */
747*758e9fbaSOystein Eftevaag         "Operation not permitted.",
748*758e9fbaSOystein Eftevaag         /* 13 - TSS2_BASE_RC_INVALID_SESSIONS */
749*758e9fbaSOystein Eftevaag         "Session structures were sent, but command doesn't use them or doesn't"
750*758e9fbaSOystein Eftevaag         " use the specified number of them",
751*758e9fbaSOystein Eftevaag         /* 14 - TSS2_BASE_RC_NO_DECRYPT_PARAM */
752*758e9fbaSOystein Eftevaag         "If function called that uses decrypt parameter, but command doesn't"
753*758e9fbaSOystein Eftevaag         " support decrypt parameter.",
754*758e9fbaSOystein Eftevaag         /* 15 - TSS2_BASE_RC_NO_ENCRYPT_PARAM */
755*758e9fbaSOystein Eftevaag         "If function called that uses encrypt parameter, but command doesn't"
756*758e9fbaSOystein Eftevaag         " support decrypt parameter.",
757*758e9fbaSOystein Eftevaag         /* 16 - TSS2_BASE_RC_BAD_SIZE */
758*758e9fbaSOystein Eftevaag         "If size of a parameter is incorrect",
759*758e9fbaSOystein Eftevaag         /* 17 - TSS2_BASE_RC_MALFORMED_RESPONSE */
760*758e9fbaSOystein Eftevaag         "Response is malformed",
761*758e9fbaSOystein Eftevaag         /* 18 - TSS2_BASE_RC_INSUFFICIENT_CONTEXT */
762*758e9fbaSOystein Eftevaag         "Context not large enough",
763*758e9fbaSOystein Eftevaag         /* 19 - TSS2_BASE_RC_INSUFFICIENT_RESPONSE */
764*758e9fbaSOystein Eftevaag         "Response is not long enough",
765*758e9fbaSOystein Eftevaag         /* 20 - TSS2_BASE_RC_INCOMPATIBLE_TCTI */
766*758e9fbaSOystein Eftevaag         "Unknown or unusable TCTI version",
767*758e9fbaSOystein Eftevaag         /* 21 - TSS2_BASE_RC_NOT_SUPPORTED */
768*758e9fbaSOystein Eftevaag         "Functionality not supported",
769*758e9fbaSOystein Eftevaag         /* 22 - TSS2_BASE_RC_BAD_TCTI_STRUCTURE */
770*758e9fbaSOystein Eftevaag         "TCTI context is bad",
771*758e9fbaSOystein Eftevaag         /* 23 - TSS2_BASE_RC_MEMORY */
772*758e9fbaSOystein Eftevaag         "Failed to allocate memory",
773*758e9fbaSOystein Eftevaag         /* 24 - TSS2_BASE_RC_BAD_TR */
774*758e9fbaSOystein Eftevaag         "The ESYS_TR resource object is bad",
775*758e9fbaSOystein Eftevaag         /* 25 - TSS2_BASE_RC_MULTIPLE_DECRYPT_SESSIONS */
776*758e9fbaSOystein Eftevaag         "Multiple sessions were marked with attribute decrypt",
777*758e9fbaSOystein Eftevaag         /* 26 - TSS2_BASE_RC_MULTIPLE_ENCRYPT_SESSIONS */
778*758e9fbaSOystein Eftevaag         "Multiple sessions were marked with attribute encrypt",
779*758e9fbaSOystein Eftevaag         /* 27 - TSS2_BASE_RC_RSP_AUTH_FAILED */
780*758e9fbaSOystein Eftevaag         "Authorizing the TPM response failed",
781*758e9fbaSOystein Eftevaag         /* 28 - TSS2_BASE_RC_NO_CONFIG */
782*758e9fbaSOystein Eftevaag         "No config is available",
783*758e9fbaSOystein Eftevaag         /* 29 - TSS2_BASE_RC_BAD_PATH */
784*758e9fbaSOystein Eftevaag         "The provided path is bad",
785*758e9fbaSOystein Eftevaag         /* 30 - TSS2_BASE_RC_NOT_DELETABLE */
786*758e9fbaSOystein Eftevaag         "The object is not deletable",
787*758e9fbaSOystein Eftevaag         /* 31 - TSS2_BASE_RC_PATH_ALREADY_EXISTS */
788*758e9fbaSOystein Eftevaag         "The provided path already exists",
789*758e9fbaSOystein Eftevaag         /* 32 - TSS2_BASE_RC_KEY_NOT_FOUND */
790*758e9fbaSOystein Eftevaag         "The key was not found",
791*758e9fbaSOystein Eftevaag         /* 33 - TSS2_BASE_RC_SIGNATURE_VERIFICATION_FAILED */
792*758e9fbaSOystein Eftevaag         "Signature verification failed",
793*758e9fbaSOystein Eftevaag         /* 34 - TSS2_BASE_RC_HASH_MISMATCH */
794*758e9fbaSOystein Eftevaag         "Hashes mismatch",
795*758e9fbaSOystein Eftevaag         /* 35 - TSS2_BASE_RC_KEY_NOT_DUPLICABLE */
796*758e9fbaSOystein Eftevaag         "Key is not duplicatable",
797*758e9fbaSOystein Eftevaag         /* 36 - TSS2_BASE_RC_PATH_NOT_FOUND */
798*758e9fbaSOystein Eftevaag         "The path was not found",
799*758e9fbaSOystein Eftevaag         /* 37 - TSS2_BASE_RC_NO_CERT */
800*758e9fbaSOystein Eftevaag         "No certificate",
801*758e9fbaSOystein Eftevaag         /* 38 - TSS2_BASE_RC_NO_PCR */
802*758e9fbaSOystein Eftevaag         "No PCR",
803*758e9fbaSOystein Eftevaag         /* 39 - TSS2_BASE_RC_PCR_NOT_RESETTABLE */
804*758e9fbaSOystein Eftevaag         "PCR not resettable",
805*758e9fbaSOystein Eftevaag         /* 40 - TSS2_BASE_RC_BAD_TEMPLATE */
806*758e9fbaSOystein Eftevaag         "The template is bad",
807*758e9fbaSOystein Eftevaag         /* 41 - TSS2_BASE_RC_AUTHORIZATION_FAILED */
808*758e9fbaSOystein Eftevaag         "Authorization failed",
809*758e9fbaSOystein Eftevaag         /* 42 - TSS2_BASE_RC_AUTHORIZATION_UNKNOWN */
810*758e9fbaSOystein Eftevaag         "Authorization is unknown",
811*758e9fbaSOystein Eftevaag         /* 43 - TSS2_BASE_RC_NV_NOT_READABLE */
812*758e9fbaSOystein Eftevaag         "NV is not readable",
813*758e9fbaSOystein Eftevaag         /* 44 - TSS2_BASE_RC_NV_TOO_SMALL */
814*758e9fbaSOystein Eftevaag         "NV is too small",
815*758e9fbaSOystein Eftevaag         /* 45 - TSS2_BASE_RC_NV_NOT_WRITEABLE */
816*758e9fbaSOystein Eftevaag         "NV is not writable",
817*758e9fbaSOystein Eftevaag         /* 46 - TSS2_BASE_RC_POLICY_UNKNOWN */
818*758e9fbaSOystein Eftevaag         "The policy is unknown",
819*758e9fbaSOystein Eftevaag         /* 47 - TSS2_BASE_RC_NV_WRONG_TYPE */
820*758e9fbaSOystein Eftevaag         "The NV type is wrong",
821*758e9fbaSOystein Eftevaag         /* 48 - TSS2_BASE_RC_NAME_ALREADY_EXISTS */
822*758e9fbaSOystein Eftevaag         "The name already exists",
823*758e9fbaSOystein Eftevaag         /* 49 - TSS2_BASE_RC_NO_TPM */
824*758e9fbaSOystein Eftevaag         "No TPM available",
825*758e9fbaSOystein Eftevaag         /* 50 - TSS2_BASE_RC_BAD_KEY */
826*758e9fbaSOystein Eftevaag         "The key is bad",
827*758e9fbaSOystein Eftevaag         /* 51 - TSS2_BASE_RC_NO_HANDLE */
828*758e9fbaSOystein Eftevaag         "No handle provided"
829*758e9fbaSOystein Eftevaag   };
830*758e9fbaSOystein Eftevaag 
831*758e9fbaSOystein Eftevaag     return (rc - 1u < ARRAY_LEN(errors)) ? errors[rc - 1u] : NULL;
832*758e9fbaSOystein Eftevaag }
833*758e9fbaSOystein Eftevaag 
834*758e9fbaSOystein Eftevaag 
835*758e9fbaSOystein Eftevaag static struct {
836*758e9fbaSOystein Eftevaag     char name[TSS2_ERR_LAYER_NAME_MAX];
837*758e9fbaSOystein Eftevaag     TSS2_RC_HANDLER handler;
838*758e9fbaSOystein Eftevaag } layer_handler[TPM2_ERROR_TSS2_RC_LAYER_COUNT] = {
839*758e9fbaSOystein Eftevaag     ADD_HANDLER("tpm" , tpm2_ehandler),
840*758e9fbaSOystein Eftevaag     ADD_NULL_HANDLER,                       /* layer 1  is unused */
841*758e9fbaSOystein Eftevaag     ADD_NULL_HANDLER,                       /* layer 2  is unused */
842*758e9fbaSOystein Eftevaag     ADD_NULL_HANDLER,                       /* layer 3  is unused */
843*758e9fbaSOystein Eftevaag     ADD_NULL_HANDLER,                       /* layer 4  is unused */
844*758e9fbaSOystein Eftevaag     ADD_NULL_HANDLER,                       /* layer 5  is unused */
845*758e9fbaSOystein Eftevaag     ADD_HANDLER("fapi", tss_err_handler),   /* layer 6  is the fapi rc */
846*758e9fbaSOystein Eftevaag     ADD_HANDLER("esapi", tss_err_handler),  /* layer 7  is the esapi rc */
847*758e9fbaSOystein Eftevaag     ADD_HANDLER("sys", tss_err_handler),    /* layer 8  is the sys rc */
848*758e9fbaSOystein Eftevaag     ADD_HANDLER("mu",  tss_err_handler),    /* layer 9  is the mu rc */
849*758e9fbaSOystein Eftevaag                                             /* Defaults to the system handler */
850*758e9fbaSOystein Eftevaag     ADD_HANDLER("tcti", tss_err_handler),   /* layer 10 is the tcti rc */
851*758e9fbaSOystein Eftevaag                                             /* Defaults to the system handler */
852*758e9fbaSOystein Eftevaag     ADD_HANDLER("rmt", tpm2_ehandler),      /* layer 11 is the resource manager TPM RC */
853*758e9fbaSOystein Eftevaag                                             /* The RM usually duplicates TPM responses */
854*758e9fbaSOystein Eftevaag                                             /* So just default the handler to tpm2. */
855*758e9fbaSOystein Eftevaag     ADD_HANDLER("rm", NULL),                /* layer 12 is the rm rc */
856*758e9fbaSOystein Eftevaag     ADD_HANDLER("drvr", NULL),              /* layer 13 is the driver rc */
857*758e9fbaSOystein Eftevaag };
858*758e9fbaSOystein Eftevaag 
859*758e9fbaSOystein Eftevaag /**
860*758e9fbaSOystein Eftevaag  * If a layer has no handler registered, default to this
861*758e9fbaSOystein Eftevaag  * handler that prints the error number in hex.
862*758e9fbaSOystein Eftevaag  * @param rc
863*758e9fbaSOystein Eftevaag  *  The rc to print the error number of.
864*758e9fbaSOystein Eftevaag  * @return
865*758e9fbaSOystein Eftevaag  *  The string.
866*758e9fbaSOystein Eftevaag  */
867*758e9fbaSOystein Eftevaag static const char *
unknown_layer_handler(TSS2_RC rc)868*758e9fbaSOystein Eftevaag unknown_layer_handler(TSS2_RC rc)
869*758e9fbaSOystein Eftevaag {
870*758e9fbaSOystein Eftevaag     static __thread char buf[32];
871*758e9fbaSOystein Eftevaag 
872*758e9fbaSOystein Eftevaag     clearbuf(buf);
873*758e9fbaSOystein Eftevaag     catbuf(buf, "0x%X", tpm2_error_get(rc));
874*758e9fbaSOystein Eftevaag 
875*758e9fbaSOystein Eftevaag     return buf;
876*758e9fbaSOystein Eftevaag }
877*758e9fbaSOystein Eftevaag 
878*758e9fbaSOystein Eftevaag /**
879*758e9fbaSOystein Eftevaag  * Register or unregister a custom layer error handler.
880*758e9fbaSOystein Eftevaag  * @param layer
881*758e9fbaSOystein Eftevaag  *  The layer in which to register a handler for.
882*758e9fbaSOystein Eftevaag  * @param name
883*758e9fbaSOystein Eftevaag  *  A friendly layer name. If the name is NULL or a
884*758e9fbaSOystein Eftevaag  *  length 0 string, then the name is output in base
885*758e9fbaSOystein Eftevaag  *  10 string of the layer number. If the length of
886*758e9fbaSOystein Eftevaag  *  name is greater than 16 characters, then the string
887*758e9fbaSOystein Eftevaag  *  is truncated to 16 characters.
888*758e9fbaSOystein Eftevaag  * @param handler
889*758e9fbaSOystein Eftevaag  *  The handler function to register or NULL to unregister.
890*758e9fbaSOystein Eftevaag  * @return
891*758e9fbaSOystein Eftevaag  *  True on success or False on error.
892*758e9fbaSOystein Eftevaag  */
893*758e9fbaSOystein Eftevaag TSS2_RC_HANDLER
Tss2_RC_SetHandler(UINT8 layer,const char * name,TSS2_RC_HANDLER handler)894*758e9fbaSOystein Eftevaag Tss2_RC_SetHandler(UINT8 layer, const char *name,
895*758e9fbaSOystein Eftevaag                         TSS2_RC_HANDLER handler)
896*758e9fbaSOystein Eftevaag {
897*758e9fbaSOystein Eftevaag     TSS2_RC_HANDLER old = layer_handler[layer].handler;
898*758e9fbaSOystein Eftevaag 
899*758e9fbaSOystein Eftevaag     layer_handler[layer].handler = handler;
900*758e9fbaSOystein Eftevaag 
901*758e9fbaSOystein Eftevaag     if (handler && name) {
902*758e9fbaSOystein Eftevaag         snprintf(layer_handler[layer].name, sizeof(layer_handler[layer].name),
903*758e9fbaSOystein Eftevaag              "%s", name);
904*758e9fbaSOystein Eftevaag     } else {
905*758e9fbaSOystein Eftevaag         memset(layer_handler[layer].name, 0, sizeof(layer_handler[layer].name));
906*758e9fbaSOystein Eftevaag     }
907*758e9fbaSOystein Eftevaag 
908*758e9fbaSOystein Eftevaag     return old;
909*758e9fbaSOystein Eftevaag }
910*758e9fbaSOystein Eftevaag 
911*758e9fbaSOystein Eftevaag /**
912*758e9fbaSOystein Eftevaag  * Given a TSS2_RC return code, provides a static error string in the format:
913*758e9fbaSOystein Eftevaag  * <layer-name>:<layer-specific-msg>.
914*758e9fbaSOystein Eftevaag  *
915*758e9fbaSOystein Eftevaag  * The layer-name section will either be the friendly name, or if no layer
916*758e9fbaSOystein Eftevaag  * handler is registered, the base10 layer number.
917*758e9fbaSOystein Eftevaag  *
918*758e9fbaSOystein Eftevaag  * The "layer-specific-msg" is layer specific and will contain details on the
919*758e9fbaSOystein Eftevaag  * error that occurred or the error code if it couldn't look it up.
920*758e9fbaSOystein Eftevaag  *
921*758e9fbaSOystein Eftevaag  * Known layer specific substrings:
922*758e9fbaSOystein Eftevaag  * TPM - The tpm layer produces 2 distinct format codes that align with:
923*758e9fbaSOystein Eftevaag  *   - Section 6.6 of: https://trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-2-Structures-01.38.pdf
924*758e9fbaSOystein Eftevaag  *   - Section 39.4 of: https://trustedcomputinggroup.org/wp-content/uploads/TPM-Rev-2.0-Part-1-Architecture-01.38.pdf
925*758e9fbaSOystein Eftevaag  *
926*758e9fbaSOystein Eftevaag  *   The two formats are format 0 and format 1.
927*758e9fbaSOystein Eftevaag  *   Format 0 string format:
928*758e9fbaSOystein Eftevaag  *     - "<error|warn>(<version>): <description>
929*758e9fbaSOystein Eftevaag  *     - Examples:
930*758e9fbaSOystein Eftevaag  *       - error(1.2): bad tag
931*758e9fbaSOystein Eftevaag  *       - warn(2.0): the 1st handle in the handle area references a transient object or session that is not loaded
932*758e9fbaSOystein Eftevaag  *
933*758e9fbaSOystein Eftevaag  *   Format 1 string format:
934*758e9fbaSOystein Eftevaag  *      - <handle|session|parameter>(<index>):<description>
935*758e9fbaSOystein Eftevaag  *      - Examples:
936*758e9fbaSOystein Eftevaag  *        - handle(unk):value is out of range or is not correct for the context
937*758e9fbaSOystein Eftevaag  *        - tpm:handle(5):value is out of range or is not correct for the context
938*758e9fbaSOystein Eftevaag  *
939*758e9fbaSOystein Eftevaag  *   Note that passing TPM2_RC_SUCCESS results in the layer specific message of "success".
940*758e9fbaSOystein Eftevaag  *
941*758e9fbaSOystein Eftevaag  *   The System, TCTI and Marshaling (MU) layers, all define simple string
942*758e9fbaSOystein Eftevaag  *   returns analogous to strerror(3).
943*758e9fbaSOystein Eftevaag  *
944*758e9fbaSOystein Eftevaag  *   Unknown layers will have the layer number in decimal and then a layer specific string of
945*758e9fbaSOystein Eftevaag  *   a hex value representing the error code. For example: 9:0x3
946*758e9fbaSOystein Eftevaag  *
947*758e9fbaSOystein Eftevaag  * @param rc
948*758e9fbaSOystein Eftevaag  *  The error code to decode.
949*758e9fbaSOystein Eftevaag  * @return
950*758e9fbaSOystein Eftevaag  *  A human understandable error description string.
951*758e9fbaSOystein Eftevaag  */
952*758e9fbaSOystein Eftevaag const char *
Tss2_RC_Decode(TSS2_RC rc)953*758e9fbaSOystein Eftevaag Tss2_RC_Decode(TSS2_RC rc)
954*758e9fbaSOystein Eftevaag {
955*758e9fbaSOystein Eftevaag     static __thread char buf[TSS2_ERR_LAYER_NAME_MAX + TSS2_ERR_LAYER_ERROR_STR_MAX + 1];
956*758e9fbaSOystein Eftevaag 
957*758e9fbaSOystein Eftevaag     clearbuf(buf);
958*758e9fbaSOystein Eftevaag 
959*758e9fbaSOystein Eftevaag     UINT8 layer = tss2_rc_layer_number_get(rc);
960*758e9fbaSOystein Eftevaag 
961*758e9fbaSOystein Eftevaag     TSS2_RC_HANDLER handler = layer_handler[layer].handler;
962*758e9fbaSOystein Eftevaag     const char *lname = layer_handler[layer].name;
963*758e9fbaSOystein Eftevaag 
964*758e9fbaSOystein Eftevaag     if (lname[0]) {
965*758e9fbaSOystein Eftevaag         catbuf(buf, "%s:", lname);
966*758e9fbaSOystein Eftevaag     } else {
967*758e9fbaSOystein Eftevaag         catbuf(buf, "%u:", layer);
968*758e9fbaSOystein Eftevaag     }
969*758e9fbaSOystein Eftevaag 
970*758e9fbaSOystein Eftevaag     handler = !handler ? unknown_layer_handler : handler;
971*758e9fbaSOystein Eftevaag 
972*758e9fbaSOystein Eftevaag     /*
973*758e9fbaSOystein Eftevaag      * Handlers only need the error bits. This way they don't
974*758e9fbaSOystein Eftevaag      * need to concern themselves with masking off the layer
975*758e9fbaSOystein Eftevaag      * bits or anything else.
976*758e9fbaSOystein Eftevaag      */
977*758e9fbaSOystein Eftevaag     UINT16 err_bits = tpm2_error_get(rc);
978*758e9fbaSOystein Eftevaag     const char *e = err_bits ? handler(err_bits) : "success";
979*758e9fbaSOystein Eftevaag     if (e) {
980*758e9fbaSOystein Eftevaag         catbuf(buf, "%s", e);
981*758e9fbaSOystein Eftevaag     } else {
982*758e9fbaSOystein Eftevaag         catbuf(buf, "0x%X", err_bits);
983*758e9fbaSOystein Eftevaag     }
984*758e9fbaSOystein Eftevaag 
985*758e9fbaSOystein Eftevaag     return buf;
986*758e9fbaSOystein Eftevaag }
987