1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*******************************************************************************
3  * Copyright 2017-2018, Fraunhofer SIT sponsored by Infineon Technologies AG
4  * All rights reserved.
5  ******************************************************************************/
6 #ifndef AUX_UTIL_H
7 #define AUX_UTIL_H
8 
9 #include <stdbool.h>
10 #ifdef HAVE_CONFIG_H
11 #include <config.h>
12 #endif
13 #include "tss2_tpm2_types.h"
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17 
18 #define SAFE_FREE(S) if((S) != NULL) {free((void*) (S)); (S)=NULL;}
19 
20 #define TPM2_ERROR_FORMAT "%s%s (0x%08x)"
21 #define TPM2_ERROR_TEXT(r) "Error", "Code", r
22 #define SIZE_OF_ARY(ary) (sizeof(ary) / sizeof(ary[0]))
23 
24 #if defined (__GNUC__)
25 #define COMPILER_ATTR(...) __attribute__((__VA_ARGS__))
26 #else
27 #define COMPILER_ATTR(...)
28 #endif
29 
30 #define UNUSED(x) (void)(x)
31 #if (MAXLOGLEVEL == LOGL_NONE)
32 /* Note:
33  * MAYBE_UNUSED macro should be used to mark variables used only
34  * for assertions i.e. in debug mode, and/or for logging, which
35  * might be compiled out. This shuldn't trigger 'unused variable'
36  * or 'variable assigned, but not used' warnings when debug and
37  * logging is disabled on configure time, but should trigger
38  * warnings for variables that are not used for neither.
39  */
40 #define MAYBE_UNUSED COMPILER_ATTR(unused)
41 #else
42 #define MAYBE_UNUSED
43 #endif
44 
45 #define return_if_error(r,msg) \
46     if (r != TSS2_RC_SUCCESS) { \
47         LOG_ERROR("%s " TPM2_ERROR_FORMAT, msg, TPM2_ERROR_TEXT(r)); \
48         return r;  \
49     }
50 
51 #define return_state_if_error(r,s,msg)      \
52     if (r != TSS2_RC_SUCCESS) { \
53         LOG_ERROR("%s " TPM2_ERROR_FORMAT, msg, TPM2_ERROR_TEXT(r)); \
54         esysContext->state = s; \
55         return r;  \
56     }
57 
58 #define return_error(r,msg) \
59     { \
60         LOG_ERROR("%s " TPM2_ERROR_FORMAT, msg, TPM2_ERROR_TEXT(r)); \
61         return r;  \
62     }
63 
64 #define goto_state_if_error(r,s,msg,label) \
65     if (r != TSS2_RC_SUCCESS) { \
66         LOG_ERROR("%s " TPM2_ERROR_FORMAT, msg, TPM2_ERROR_TEXT(r)); \
67         esysContext->state = s; \
68         goto label;  \
69     }
70 
71 #define goto_if_null(p,msg,ec,label) \
72     if ((p) == NULL) { \
73         LOG_ERROR("%s ", (msg)); \
74         r = (ec); \
75         goto label;  \
76     }
77 
78 #define goto_if_error(r,msg,label) \
79     if (r != TSS2_RC_SUCCESS) { \
80         LOG_ERROR("%s " TPM2_ERROR_FORMAT, msg, TPM2_ERROR_TEXT(r)); \
81         goto label;  \
82     }
83 
84 #define goto_error(r,v,msg,label, ...)              \
85     { r = v;  \
86       LOG_ERROR(TPM2_ERROR_FORMAT " " msg, TPM2_ERROR_TEXT(r), ## __VA_ARGS__); \
87       goto label; \
88     }
89 
90 #define return_if_null(p,msg,ec) \
91     if (p == NULL) { \
92         LOG_ERROR("%s ", msg); \
93         return ec; \
94     }
95 
96 #define return_if_notnull(p,msg,ec) \
97     if (p != NULL) { \
98         LOG_ERROR("%s ", msg); \
99         return ec; \
100     }
101 
102 #define set_return_code(r_max, r, msg) \
103     if (r != TSS2_RC_SUCCESS) { \
104         LOG_ERROR("%s " TPM2_ERROR_FORMAT, msg, TPM2_ERROR_TEXT(r)); \
105         r_max = r; \
106     }
107 
108 #define base_rc(r) (r & ~TSS2_RC_LAYER_MASK)
109 #define number_rc(r) (r & ~TPM2_RC_N_MASK)
110 
111 static inline TSS2_RC
tss2_fmt_p1_error_to_rc(UINT16 err)112 tss2_fmt_p1_error_to_rc(UINT16 err)
113 {
114     return TPM2_RC_1+TPM2_RC_P+err;
115 }
116 
117 static inline bool
tss2_is_expected_error(TSS2_RC rc)118 tss2_is_expected_error(TSS2_RC rc)
119 {
120     /* Success is always expected */
121     if (rc == TSS2_RC_SUCCESS) {
122         return true;
123     }
124 
125     /*
126      * drop the layer, any part of the TSS stack can gripe about this error
127      * if it wants too.
128      */
129     rc &= ~TSS2_RC_LAYER_MASK;
130 
131     /*
132      * Format 1, parameter 1 errors plus the below RC's
133      * contain everything we care about:
134      *   - TPM2_RC_CURVE
135      *   - TPM2_RC_HASH
136      *   - TPM2_RC_ASYMMETRIC
137      *   - TPM2_RC_KEY_SIZE
138      */
139     if (rc == tss2_fmt_p1_error_to_rc(TPM2_RC_CURVE)
140             || rc == tss2_fmt_p1_error_to_rc(TPM2_RC_VALUE)
141             || rc == tss2_fmt_p1_error_to_rc(TPM2_RC_HASH)
142             || rc == tss2_fmt_p1_error_to_rc(TPM2_RC_ASYMMETRIC)
143             || rc == tss2_fmt_p1_error_to_rc(TPM2_RC_KEY_SIZE)) {
144         return true;
145     }
146 
147     return false;
148 }
149 
150 #ifdef __cplusplus
151 } /* extern "C" */
152 #endif
153 
154 #endif /* AUX_UTIL_H */
155