Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 1 | /******************************************************************************* |
| 2 | * Copyright 2017, Fraunhofer SIT sponsored by Infineon Technologies AG |
| 3 | * All rights reserved. |
| 4 | * |
| 5 | * Redistribution and use in source and binary forms, with or without |
| 6 | * modification, are permitted provided that the following conditions are met: |
| 7 | * |
| 8 | * 1. Redistributions of source code must retain the above copyright notice, |
| 9 | * this list of conditions and the following disclaimer. |
| 10 | * |
| 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, |
| 12 | * this list of conditions and the following disclaimer in the documentation |
| 13 | * and/or other materials provided with the distribution. |
| 14 | * |
| 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
| 25 | * THE POSSIBILITY OF SUCH DAMAGE. |
| 26 | *******************************************************************************/ |
Juergen Repp | 6209718 | 2018-03-19 18:04:42 +0100 | [diff] [blame] | 27 | |
| 28 | #include "tss2_esys.h" |
| 29 | #include "esys_mu.h" |
| 30 | |
| 31 | #include "esys_iutil.h" |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 32 | #define LOGMODULE esys |
Philip Tricca | a7c51ce | 2018-03-10 18:28:25 -0800 | [diff] [blame] | 33 | #include "util/log.h" |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 34 | |
| 35 | /** Serialization of an ESYS_TR into a byte buffer. |
| 36 | * |
| 37 | * Serialize the metadata of an ESYS_TR object into a byte buffer such that it |
| 38 | * can be stored on disk for later use by a different program or context. |
| 39 | * The serialized object can be deserialized suing Esys_TR_Deserialize. |
Juergen Repp | 506c473 | 2018-04-26 11:15:50 +0200 | [diff] [blame] | 40 | * @param esys_context [in,out] The ESYS_CONTEXT. |
| 41 | * @param esys_handle [in] The ESYS_TR object to serialize. |
| 42 | * @param buffer [out] The buffer containing the serialized metadata. |
| 43 | * (caller-callocated) Shall be freed using free(). |
| 44 | * @param buffer_size [out] The size of the buffer parameter. |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 45 | * @retval TSS2_RC_SUCCESS on Success. |
Juergen Repp | 506c473 | 2018-04-26 11:15:50 +0200 | [diff] [blame] | 46 | * @retval TSS2_ESYS_RC_BAD_TR if the ESYS_TR object is unknown to the |
| 47 | * ESYS_CONTEXT. |
| 48 | * @retval TSS2_ESYS_RC_MEMORY if the buffer for marshaling the object can't |
| 49 | * be allocated. |
| 50 | * @retval TSS2_ESYS_RC_BAD_VALUE For invalid ESYS data to be marshaled. |
| 51 | * @retval TSS2_RCs produced by lower layers of the software stack. |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 52 | */ |
| 53 | TSS2_RC |
| 54 | Esys_TR_Serialize(ESYS_CONTEXT * esys_context, |
| 55 | ESYS_TR esys_handle, uint8_t ** buffer, size_t * buffer_size) |
| 56 | { |
| 57 | TSS2_RC r = TSS2_RC_SUCCESS; |
| 58 | RSRC_NODE_T *esys_object; |
| 59 | size_t offset = 0; |
Juergen Repp | 219fda5 | 2018-02-23 11:14:47 +0100 | [diff] [blame] | 60 | *buffer_size = 0; |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 61 | |
| 62 | r = esys_GetResourceObject(esys_context, esys_handle, &esys_object); |
| 63 | return_if_error(r, "Get resource object"); |
Juergen Repp | b832467 | 2018-02-23 11:15:39 +0100 | [diff] [blame] | 64 | |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 65 | r = Tss2_MU_IESYS_RESOURCE_Marshal(&esys_object->rsrc, NULL, SIZE_MAX, |
| 66 | buffer_size); |
| 67 | return_if_error(r, "Marshal resource object"); |
Juergen Repp | b832467 | 2018-02-23 11:15:39 +0100 | [diff] [blame] | 68 | |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 69 | *buffer = malloc(*buffer_size); |
| 70 | return_if_null(*buffer, "Buffer could not be allocated", |
| 71 | TSS2_ESYS_RC_MEMORY); |
Juergen Repp | b832467 | 2018-02-23 11:15:39 +0100 | [diff] [blame] | 72 | |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 73 | r = Tss2_MU_IESYS_RESOURCE_Marshal(&esys_object->rsrc, *buffer, |
| 74 | *buffer_size, &offset); |
| 75 | return_if_error(r, "Marshal resource object"); |
Juergen Repp | b832467 | 2018-02-23 11:15:39 +0100 | [diff] [blame] | 76 | |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 77 | return TSS2_RC_SUCCESS; |
| 78 | }; |
| 79 | |
| 80 | /** Deserialization of an ESYS_TR from a byte buffer. |
| 81 | * |
| 82 | * Deserialize the metadata of an ESYS_TR object from a byte buffer that was |
| 83 | * stored on disk for later use by a different program or context. |
| 84 | * An object can be serialized suing Esys_TR_Serialize. |
Juergen Repp | 506c473 | 2018-04-26 11:15:50 +0200 | [diff] [blame] | 85 | * @param esys_context [in,out] The ESYS_CONTEXT. |
| 86 | * @param esys_handle [in] The ESYS_TR object to serialize. |
| 87 | * @param buffer [out] The buffer containing the serialized metadata. |
| 88 | * (caller-callocated) Shall be freed using free(). |
| 89 | * @param buffer_size [out] The size of the buffer parameter. |
| 90 | * @retval TSS2_RC_SUCCESS on Success. |
| 91 | * @retval TSS2_ESYS_RC_MEMORY if the object can not be allocated. |
| 92 | * @retval TSS2_ESYS_RC_INSUFFICIENT_BUFFER if the buffer for unmarshaling. |
| 93 | * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext is NULL. |
| 94 | * @retval TSS2_RCs produced by lower layers of the software stack. |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 95 | */ |
| 96 | TSS2_RC |
| 97 | Esys_TR_Deserialize(ESYS_CONTEXT * esys_context, |
| 98 | uint8_t const *buffer, |
| 99 | size_t buffer_size, ESYS_TR * esys_handle) |
| 100 | { |
Andreas Fuchs | 8071f1d | 2018-04-26 16:57:38 +0200 | [diff] [blame] | 101 | TSS2_RC r; |
| 102 | |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 103 | RSRC_NODE_T *esys_object; |
| 104 | size_t offset = 0; |
| 105 | |
Andreas Fuchs | 8071f1d | 2018-04-26 16:57:38 +0200 | [diff] [blame] | 106 | _ESYS_ASSERT_NON_NULL(esys_context); |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 107 | r = esys_CreateResourceObject(esys_context, *esys_handle, &esys_object); |
| 108 | return_if_error(r, "Get resource object"); |
Juergen Repp | b832467 | 2018-02-23 11:15:39 +0100 | [diff] [blame] | 109 | |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 110 | r = Tss2_MU_IESYS_RESOURCE_Unmarshal(buffer, buffer_size, &offset, |
| 111 | &esys_object->rsrc); |
| 112 | return_if_error(r, "Unmarshal resource object"); |
Juergen Repp | b832467 | 2018-02-23 11:15:39 +0100 | [diff] [blame] | 113 | |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 114 | return TSS2_RC_SUCCESS; |
| 115 | } |
| 116 | |
dantpm | f6ef247 | 2018-04-06 15:21:59 -0700 | [diff] [blame] | 117 | /** Start synchronous creation of an ESYS_TR object from TPM metadata. |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 118 | * |
| 119 | * This function starts the asynchronous retrieval of metadata from the TPM in |
| 120 | * order to create a new ESYS_TR object. |
Juergen Repp | 506c473 | 2018-04-26 11:15:50 +0200 | [diff] [blame] | 121 | * @param esys_context [in,out] The ESYS_CONTEXT |
| 122 | * @param tpm_handle [in] The handle of the TPM object to represent as ESYS_TR. |
| 123 | * @param shandle1 [in,out] A session for securing the TPM command (optional). |
| 124 | * @param shandle2 [in,out] A session for securing the TPM command (optional). |
| 125 | * @param shandle3 [in,out] A session for securing the TPM command (optional). |
| 126 | * @retval TSS2_RC_SUCCESS on success |
| 127 | * @retval ESYS_RC_SUCCESS if the function call was a success. |
| 128 | * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext is NULL. |
| 129 | * @retval TSS2_ESYS_RC_BAD_CONTEXT: if esysContext corruption is detected. |
| 130 | * @retval TSS2_ESYS_RC_MEMORY: if the ESAPI cannot allocate enough memory for |
| 131 | * internal operations or return parameters. |
| 132 | * @retval TSS2_ESYS_RC_MULTIPLE_DECRYPT_SESSIONS: if more than one session has |
| 133 | * the 'decrypt' attribute bit set. |
| 134 | * @retval TSS2_ESYS_RC_MULTIPLE_ENCRYPT_SESSIONS: if more than one session has |
| 135 | * the 'encrypt' attribute bit set. |
| 136 | * @retval TSS2_ESYS_RC_NO_DECRYPT_PARAM: if one of the sessions has the |
| 137 | * 'decrypt' attribute set and the command does not support encryption |
| 138 | * of the first command parameter. |
| 139 | * @retval TSS2_RCs produced by lower layers of the software stack may be |
| 140 | * returned to the caller unaltered unless handled internally. |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 141 | */ |
| 142 | TSS2_RC |
| 143 | Esys_TR_FromTPMPublic_Async(ESYS_CONTEXT * esys_context, |
| 144 | TPM2_HANDLE tpm_handle, |
| 145 | ESYS_TR shandle1, |
| 146 | ESYS_TR shandle2, ESYS_TR shandle3) |
| 147 | { |
| 148 | TSS2_RC r; |
Andreas Fuchs | 8071f1d | 2018-04-26 16:57:38 +0200 | [diff] [blame] | 149 | _ESYS_ASSERT_NON_NULL(esys_context); |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 150 | ESYS_TR esys_handle = esys_context->esys_handle_cnt++; |
| 151 | RSRC_NODE_T *esysHandleNode = NULL; |
| 152 | r = esys_CreateResourceObject(esys_context, esys_handle, &esysHandleNode); |
| 153 | goto_if_error(r, "Error create resource", error_cleanup); |
Juergen Repp | b832467 | 2018-02-23 11:15:39 +0100 | [diff] [blame] | 154 | |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 155 | esysHandleNode->rsrc.handle = tpm_handle; |
| 156 | esys_context->esys_handle = esys_handle; |
| 157 | |
| 158 | if (tpm_handle >= TPM2_NV_INDEX_FIRST && tpm_handle <= TPM2_NV_INDEX_LAST) { |
| 159 | esys_context->in.NV_ReadPublic.nvIndex = esys_handle; |
Juergen Repp | add438d | 2018-04-09 10:00:19 +0200 | [diff] [blame] | 160 | r = Esys_NV_ReadPublic_Async(esys_context, esys_handle, shandle1, |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 161 | shandle2, shandle3); |
| 162 | goto_if_error(r, "Error NV_ReadPublic", error_cleanup); |
Juergen Repp | b832467 | 2018-02-23 11:15:39 +0100 | [diff] [blame] | 163 | |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 164 | } else { |
| 165 | esys_context->in.ReadPublic.objectHandle = esys_handle; |
Juergen Repp | add438d | 2018-04-09 10:00:19 +0200 | [diff] [blame] | 166 | r = Esys_ReadPublic_Async(esys_context, esys_handle, shandle1, shandle2, |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 167 | shandle3); |
| 168 | goto_if_error(r, "Error ReadPublic", error_cleanup); |
| 169 | } |
| 170 | return r; |
| 171 | error_cleanup: |
| 172 | Esys_TR_Close(esys_context, &esys_handle); |
| 173 | return r; |
| 174 | } |
| 175 | |
dantpm | f6ef247 | 2018-04-06 15:21:59 -0700 | [diff] [blame] | 176 | /** Finish asynchronous creation of an ESYS_TR object from TPM metadata. |
Juergen Repp | 506c473 | 2018-04-26 11:15:50 +0200 | [diff] [blame] | 177 | * |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 178 | * This function finishes the asynchronous retrieval of metadata from the TPM in |
| 179 | * order to create a new ESYS_TR object. |
Juergen Repp | 506c473 | 2018-04-26 11:15:50 +0200 | [diff] [blame] | 180 | * @param esys_context [in,out] The ESYS_CONTEXT |
| 181 | * @param object [out] The newly created ESYS_TR metadata object. |
| 182 | * @retval TSS2_RC_SUCCESS on success |
| 183 | * @retval ESYS_RC_SUCCESS if the function call was a success. |
| 184 | * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext or required input |
| 185 | * pointers or required output handle references are NULL. |
| 186 | * @retval TSS2_ESYS_RC_BAD_CONTEXT: if esysContext corruption is detected. |
| 187 | * @retval TSS2_ESYS_RC_MEMORY: if the ESAPI cannot allocate enough memory for |
| 188 | * internal operations or return parameters. |
| 189 | * @retval TSS2_ESYS_RC_BAD_SEQUENCE: if the context has an asynchronous |
| 190 | * operation already pending. |
| 191 | * @retval TSS2_ESYS_RC_TRY_AGAIN: if the timeout counter expires before the |
| 192 | * TPM response is received. |
| 193 | * @retval TSS2_ESYS_RC_INSUFFICIENT_RESPONSE: if the TPM's response does not |
| 194 | * at least contain the tag, response length, and response code. |
| 195 | * @retval TSS2_ESYS_RC_MALFORMED_RESPONSE: if the TPM's response is corrupted. |
| 196 | * @retval TSS2_RCs produced by lower layers of the software stack may be |
| 197 | * returned to the caller unaltered unless handled internally. |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 198 | */ |
| 199 | TSS2_RC |
Juergen Repp | 506c473 | 2018-04-26 11:15:50 +0200 | [diff] [blame] | 200 | Esys_TR_FromTPMPublic_Finish(ESYS_CONTEXT * esys_context, ESYS_TR * object) |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 201 | { |
| 202 | TSS2_RC r = TSS2_RC_SUCCESS; |
| 203 | ESYS_TR objectHandle = esys_context->esys_handle; |
| 204 | RSRC_NODE_T *objectHandleNode; |
| 205 | |
Andreas Fuchs | 8071f1d | 2018-04-26 16:57:38 +0200 | [diff] [blame] | 206 | _ESYS_ASSERT_NON_NULL(esys_context); |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 207 | r = esys_GetResourceObject(esys_context, objectHandle, &objectHandleNode); |
| 208 | goto_if_error(r, "get resource", error_cleanup); |
Juergen Repp | b832467 | 2018-02-23 11:15:39 +0100 | [diff] [blame] | 209 | |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 210 | if (objectHandleNode->rsrc.handle >= TPM2_NV_INDEX_FIRST |
| 211 | && objectHandleNode->rsrc.handle <= TPM2_NV_INDEX_LAST) { |
| 212 | TPM2B_NV_PUBLIC *nvPublic; |
| 213 | TPM2B_NAME *nvName; |
Juergen Repp | add438d | 2018-04-09 10:00:19 +0200 | [diff] [blame] | 214 | r = Esys_NV_ReadPublic_Finish(esys_context, &nvPublic, &nvName); |
Andreas Fuchs | b82f6da | 2018-04-12 13:43:04 +0200 | [diff] [blame] | 215 | if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN) { |
| 216 | LOG_DEBUG("A layer below returned TRY_AGAIN: %" PRIx32 |
| 217 | " => resubmitting command", r); |
| 218 | return r; |
| 219 | } |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 220 | goto_if_error(r, "Error NV_ReadPublic", error_cleanup); |
Juergen Repp | b832467 | 2018-02-23 11:15:39 +0100 | [diff] [blame] | 221 | |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 222 | objectHandleNode->rsrc.rsrcType = IESYSC_NV_RSRC; |
| 223 | objectHandleNode->rsrc.name = *nvName; |
| 224 | objectHandleNode->rsrc.misc.rsrc_nv_pub = *nvPublic; |
| 225 | SAFE_FREE(nvPublic); |
| 226 | SAFE_FREE(nvName); |
| 227 | } else { |
| 228 | TPM2B_PUBLIC *public; |
| 229 | TPM2B_NAME *name = NULL; |
| 230 | TPM2B_NAME *qualifiedName = NULL; |
Juergen Repp | add438d | 2018-04-09 10:00:19 +0200 | [diff] [blame] | 231 | r = Esys_ReadPublic_Finish(esys_context, &public, &name, |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 232 | &qualifiedName); |
Andreas Fuchs | b82f6da | 2018-04-12 13:43:04 +0200 | [diff] [blame] | 233 | if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN) { |
| 234 | LOG_DEBUG("A layer below returned TRY_AGAIN: %" PRIx32 |
| 235 | " => resubmitting command", r); |
| 236 | return r; |
| 237 | } |
Juergen Repp | b832467 | 2018-02-23 11:15:39 +0100 | [diff] [blame] | 238 | goto_if_error(r, "Error ReadPublic", error_cleanup); |
| 239 | |
| 240 | objectHandleNode->rsrc.rsrcType = IESYSC_KEY_RSRC; |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 241 | objectHandleNode->rsrc.name = *name; |
| 242 | objectHandleNode->rsrc.misc.rsrc_key_pub = *public; |
| 243 | SAFE_FREE(public); |
| 244 | SAFE_FREE(name); |
| 245 | SAFE_FREE(qualifiedName); |
| 246 | } |
Juergen Repp | 506c473 | 2018-04-26 11:15:50 +0200 | [diff] [blame] | 247 | *object = objectHandle; |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 248 | return TSS2_RC_SUCCESS; |
| 249 | |
| 250 | error_cleanup: |
| 251 | Esys_TR_Close(esys_context, &objectHandle); |
| 252 | return r; |
| 253 | } |
| 254 | |
| 255 | /** Creation of an ESYS_TR object from TPM metadata. |
| 256 | * |
dantpm | f6ef247 | 2018-04-06 15:21:59 -0700 | [diff] [blame] | 257 | * This function can be used to create ESYS_TR object for Tpm Resources that are |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 258 | * not created or loaded (e.g. using ESys_CreatePrimary or ESys_Load) but |
| 259 | * pre-exist inside the TPM. Examples are NV-Indices or persistent object. |
| 260 | * |
| 261 | * Note: For PCRs and hierarchies, please use the global ESYS_TR identifiers. |
| 262 | * Note: If a session is provided the TPM is queried for the metadata twice. |
| 263 | * First without a session to retrieve some metadata then with the session where |
| 264 | * this metadata is used in the session HMAC calculation and thereby verified. |
| 265 | * |
| 266 | * Since man in the middle attacks should be prevented as much as possible it is |
| 267 | * recommended to pass a session. |
Juergen Repp | 506c473 | 2018-04-26 11:15:50 +0200 | [diff] [blame] | 268 | * @param esys_context [in,out] The ESYS_CONTEXT |
| 269 | * @param tpm_handle [in] The handle of the TPM object to represent as ESYS_TR. |
| 270 | * @param shandle1 [in,out] A session for securing the TPM command (optional). |
| 271 | * @param shandle2 [in,out] A session for securing the TPM command (optional). |
| 272 | * @param shandle3 [in,out] A session for securing the TPM command (optional). |
| 273 | * @param object [out] The newly created ESYS_TR metadata object. |
| 274 | * @retval TSS2_RC_SUCCESS on success |
| 275 | * @retval ESYS_RC_SUCCESS if the function call was a success. |
| 276 | * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext or required input |
| 277 | * pointers or required output handle references are NULL. |
| 278 | * @retval TSS2_ESYS_RC_BAD_CONTEXT: if esysContext corruption is detected. |
| 279 | * @retval TSS2_ESYS_RC_MEMORY: if the ESAPI cannot allocate enough memory for |
| 280 | * internal operations or return parameters. |
| 281 | * @retval TSS2_ESYS_RC_BAD_SEQUENCE: if the context has an asynchronous |
| 282 | * operation already pending. |
| 283 | * @retval TSS2_ESYS_RC_INSUFFICIENT_RESPONSE: if the TPM's response does not |
| 284 | * at least contain the tag, response length, and response code. |
| 285 | * @retval TSS2_ESYS_RC_MALFORMED_RESPONSE: if the TPM's response is corrupted. |
| 286 | * @retval TSS2_ESYS_RC_MULTIPLE_DECRYPT_SESSIONS: if more than one session has |
| 287 | * the 'decrypt' attribute bit set. |
| 288 | * @retval TSS2_ESYS_RC_MULTIPLE_ENCRYPT_SESSIONS: if more than one session has |
| 289 | * the 'encrypt' attribute bit set. |
| 290 | * @retval TSS2_ESYS_RC_NO_DECRYPT_PARAM: if one of the sessions has the |
| 291 | * 'decrypt' attribute set and the command does not support encryption |
| 292 | * of the first command parameter. |
| 293 | * @retval TSS2_RCs produced by lower layers of the software stack may be |
| 294 | * returned to the caller unaltered unless handled internally. |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 295 | */ |
| 296 | TSS2_RC |
| 297 | Esys_TR_FromTPMPublic(ESYS_CONTEXT * esys_context, |
| 298 | TPM2_HANDLE tpm_handle, |
| 299 | ESYS_TR shandle1, |
| 300 | ESYS_TR shandle2, ESYS_TR shandle3, ESYS_TR * object) |
| 301 | { |
| 302 | TSS2_RC r; |
Andreas Fuchs | 8071f1d | 2018-04-26 16:57:38 +0200 | [diff] [blame] | 303 | |
| 304 | _ESYS_ASSERT_NON_NULL(esys_context); |
Andreas Fuchs | b82f6da | 2018-04-12 13:43:04 +0200 | [diff] [blame] | 305 | r = Esys_TR_FromTPMPublic_Async(esys_context, tpm_handle, |
| 306 | shandle1, shandle2, shandle3); |
| 307 | return_if_error(r, "Error TR FromTPMPublic"); |
Juergen Repp | b832467 | 2018-02-23 11:15:39 +0100 | [diff] [blame] | 308 | |
Andreas Fuchs | b82f6da | 2018-04-12 13:43:04 +0200 | [diff] [blame] | 309 | /* Set the timeout to indefinite for now, since we want _Finish to block */ |
| 310 | int32_t timeouttmp = esys_context->timeout; |
| 311 | esys_context->timeout = -1; |
| 312 | /* |
| 313 | * Now we call the finish function, until return code is not equal to |
| 314 | * from TSS2_BASE_RC_TRY_AGAIN. |
| 315 | * Note that the finish function may return TSS2_RC_TRY_AGAIN, even if we |
| 316 | * have set the timeout to -1. This occurs for example if the TPM requests |
| 317 | * a retransmission of the command via TPM2_RC_YIELDED. |
| 318 | */ |
| 319 | do { |
| 320 | r = Esys_TR_FromTPMPublic_Finish(esys_context, object); |
| 321 | if ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN) |
| 322 | LOG_DEBUG("A layer below returned TRY_AGAIN: %" PRIx32 |
| 323 | " => resubmitting command", r); |
| 324 | } while ((r & ~TSS2_RC_LAYER_MASK) == TSS2_BASE_RC_TRY_AGAIN); |
Juergen Repp | b832467 | 2018-02-23 11:15:39 +0100 | [diff] [blame] | 325 | |
Andreas Fuchs | b82f6da | 2018-04-12 13:43:04 +0200 | [diff] [blame] | 326 | /* Restore the timeout value to the original value */ |
| 327 | esys_context->timeout = timeouttmp; |
| 328 | return_if_error(r, "Error TR FromTPMPublic"); |
| 329 | |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 330 | return r; |
| 331 | } |
| 332 | |
| 333 | /** Close an ESYS_TR without removing it from the TPM. |
| 334 | * |
| 335 | * This function deletes an ESYS_TR object from an ESYS_CONTEXT without deleting |
| 336 | * it from the TPM. This is useful for NV-Indices or persistent keys, after |
| 337 | * Esys_TR_Serialize has been called. Transient objects should be deleted using |
| 338 | * Esys_FlushContext. |
Juergen Repp | 506c473 | 2018-04-26 11:15:50 +0200 | [diff] [blame] | 339 | * @param esys_context [in,out] The ESYS_CONTEXT |
| 340 | * @param object [out] ESYS_TR metadata object to be deleted from ESYS_CONTEXT. |
| 341 | * @retval TSS2_RC_SUCCESS on Success. |
| 342 | * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext is NULL. |
| 343 | * @retval TSS2_ESYS_RC_BAD_TR if the ESYS_TR object is unknown to the |
| 344 | * ESYS_CONTEXT. |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 345 | */ |
| 346 | TSS2_RC |
| 347 | Esys_TR_Close(ESYS_CONTEXT * esys_context, ESYS_TR * object) |
| 348 | { |
Andreas Fuchs | 1c48e2b | 2018-03-08 11:25:12 +0100 | [diff] [blame] | 349 | RSRC_NODE_T *node; |
| 350 | RSRC_NODE_T **update_ptr; |
Andreas Fuchs | 8071f1d | 2018-04-26 16:57:38 +0200 | [diff] [blame] | 351 | |
| 352 | _ESYS_ASSERT_NON_NULL(esys_context); |
Andreas Fuchs | 1c48e2b | 2018-03-08 11:25:12 +0100 | [diff] [blame] | 353 | for (node = esys_context->rsrc_list, |
| 354 | update_ptr = &esys_context->rsrc_list; |
| 355 | node != NULL; |
| 356 | update_ptr = &node->next, node = node->next) { |
| 357 | if (node->esys_handle == *object) { |
| 358 | *update_ptr = node->next; |
| 359 | SAFE_FREE(node); |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 360 | *object = ESYS_TR_NONE; |
| 361 | return TSS2_RC_SUCCESS; |
| 362 | } |
| 363 | } |
| 364 | LOG_ERROR("Error: Esys handle does not exist (%x).", TSS2_ESYS_RC_BAD_TR); |
| 365 | return TSS2_ESYS_RC_BAD_TR; |
| 366 | } |
| 367 | |
| 368 | /** Set the authorization value of an ESYS_TR. |
| 369 | * |
| 370 | * Authorization values are associated with ESYS_TR Tpm Resource object. They |
| 371 | * are then picked up whenever an authorization is needed. |
| 372 | * |
| 373 | * Note: The authorization value is not stored in the metadata during |
| 374 | * Esys_TR_Serialize. Therefor Esys_TR_SetAuth needs to be called again after |
| 375 | * every Esys_TR_Deserialize. |
Juergen Repp | 506c473 | 2018-04-26 11:15:50 +0200 | [diff] [blame] | 376 | * @param esys_context [in,out] The ESYS_CONTEXT. |
| 377 | * @param esys_handle [in,out] The ESYS_TR for which to set the auth value. |
| 378 | * @param authValue [in] The auth value to set for the ESYS_TR. |
| 379 | * @retval TSS2_RC_SUCCESS on Success. |
| 380 | * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext is NULL. |
| 381 | * @retval TSS2_ESYS_RC_BAD_TR if the ESYS_TR object is unknown to the |
| 382 | * ESYS_CONTEXT. |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 383 | */ |
| 384 | TSS2_RC |
| 385 | Esys_TR_SetAuth(ESYS_CONTEXT * esys_context, ESYS_TR esys_handle, |
| 386 | TPM2B_AUTH const *authValue) |
| 387 | { |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 388 | RSRC_NODE_T *esys_object; |
| 389 | TSS2_RC r; |
Andreas Fuchs | 8071f1d | 2018-04-26 16:57:38 +0200 | [diff] [blame] | 390 | _ESYS_ASSERT_NON_NULL(esys_context); |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 391 | r = esys_GetResourceObject(esys_context, esys_handle, &esys_object); |
| 392 | if (r != TPM2_RC_SUCCESS) |
| 393 | return r; |
| 394 | esys_object->auth = *authValue; |
| 395 | return TSS2_RC_SUCCESS; |
| 396 | } |
| 397 | |
| 398 | /** Retrieve the TPM public name of an Esys_TR object. |
| 399 | * |
| 400 | * Some operations (i.e. Esys_PolicyNameHash) require the name of a TPM object |
| 401 | * to be passed. Esys_TR_GetName provides this name to the caller. |
Juergen Repp | 506c473 | 2018-04-26 11:15:50 +0200 | [diff] [blame] | 402 | * @param esys_context [in,out] The ESYS_CONTEXT. |
| 403 | * @param esys_handle [in,out] The ESYS_TR for which to retrieve the name. |
| 404 | * @param name [out] The name of the object (caller-allocated; use free()). |
| 405 | * @retval TSS2_RC_SUCCESS on Success. |
| 406 | * @retval TSS2_ESYS_RC_MEMORY if needed memory can't be allocated. |
| 407 | * @retval TSS2_ESYS_RC_GENERAL_FAILURE for errors of the crypto library. |
| 408 | * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext is NULL. |
| 409 | * @retval TSS2_SYS_RC_* for SAPI errors. |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 410 | */ |
| 411 | TSS2_RC |
| 412 | Esys_TR_GetName(ESYS_CONTEXT * esys_context, ESYS_TR esys_handle, |
| 413 | TPM2B_NAME ** name) |
| 414 | { |
| 415 | RSRC_NODE_T *esys_object; |
Andreas Fuchs | 8071f1d | 2018-04-26 16:57:38 +0200 | [diff] [blame] | 416 | TSS2_RC r; |
| 417 | _ESYS_ASSERT_NON_NULL(esys_context); |
| 418 | |
| 419 | r = esys_GetResourceObject(esys_context, esys_handle, &esys_object); |
Andreas Fuchs | 1c48e2b | 2018-03-08 11:25:12 +0100 | [diff] [blame] | 420 | return_if_error(r, "Object not found"); |
Juergen Repp | b832467 | 2018-02-23 11:15:39 +0100 | [diff] [blame] | 421 | |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 422 | *name = malloc(sizeof(TPM2B_NAME)); |
| 423 | if (*name == NULL) { |
| 424 | LOG_ERROR("Error: out of memory"); |
| 425 | return TSS2_ESYS_RC_MEMORY; |
| 426 | } |
| 427 | if (esys_object->rsrc.rsrcType == IESYSC_KEY_RSRC) { |
| 428 | r = iesys_get_name(&esys_object->rsrc.misc.rsrc_key_pub, *name); |
| 429 | goto_if_error(r, "Error get name", error_cleanup); |
Juergen Repp | b832467 | 2018-02-23 11:15:39 +0100 | [diff] [blame] | 430 | |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 431 | } else { |
| 432 | if (esys_object->rsrc.rsrcType == IESYSC_NV_RSRC) { |
| 433 | r = iesys_nv_get_name(&esys_object->rsrc.misc.rsrc_nv_pub, *name); |
| 434 | goto_if_error(r, "Error get name", error_cleanup); |
Juergen Repp | b832467 | 2018-02-23 11:15:39 +0100 | [diff] [blame] | 435 | |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 436 | } else { |
| 437 | size_t offset = 0; |
Juergen Repp | 2384030 | 2018-04-10 13:44:45 +0200 | [diff] [blame] | 438 | r = Tss2_MU_TPM2_HANDLE_Marshal(esys_object->rsrc.handle, |
| 439 | &(*name)->name[0], sizeof(TPM2_HANDLE), |
| 440 | &offset); |
| 441 | goto_if_error(r, "Error get name", error_cleanup); |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 442 | (*name)->size = offset; |
| 443 | } |
| 444 | } |
| 445 | return r; |
| 446 | error_cleanup: |
| 447 | SAFE_FREE(name); |
| 448 | return r; |
| 449 | } |
| 450 | |
| 451 | |
| 452 | /** Retrieve the Session Attributes of the ESYS_TR session. |
| 453 | * |
| 454 | * Sessions possess attributes, such as whether they shall continue of be |
| 455 | * flushed after the next command, or whether they are used to encrypt |
| 456 | * parameters. |
| 457 | * Note: this function only applies to ESYS_TR objects that represent sessions. |
Juergen Repp | 506c473 | 2018-04-26 11:15:50 +0200 | [diff] [blame] | 458 | * @param esys_context [in,out] The ESYS_CONTEXT. |
| 459 | * @param esys_handle [in,out] The ESYS_TR of the session. |
| 460 | * @param flags [out] The attributes of the session. |
| 461 | * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext is NULL. |
| 462 | * @retval TSS2_ESYS_RC_BAD_TR if the ESYS_TR object is unknown to the |
| 463 | * ESYS_CONTEXT or ESYS_TR object is not a session object. |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 464 | */ |
| 465 | TSS2_RC |
| 466 | Esys_TRSess_GetAttributes(ESYS_CONTEXT * esys_context, ESYS_TR esys_handle, |
| 467 | TPMA_SESSION * flags) |
| 468 | { |
| 469 | RSRC_NODE_T *esys_object; |
Andreas Fuchs | 8071f1d | 2018-04-26 16:57:38 +0200 | [diff] [blame] | 470 | |
| 471 | _ESYS_ASSERT_NON_NULL(esys_context); |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 472 | TSS2_RC r = esys_GetResourceObject(esys_context, esys_handle, &esys_object); |
| 473 | return_if_error(r, "Object not found"); |
Juergen Repp | b832467 | 2018-02-23 11:15:39 +0100 | [diff] [blame] | 474 | |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 475 | if (esys_object->rsrc.rsrcType != IESYSC_SESSION_RSRC) |
| 476 | return_error(TSS2_ESYS_RC_BAD_TR, "Object is not a session object"); |
| 477 | *flags = esys_object->rsrc.misc.rsrc_session.sessionAttributes; |
| 478 | return TSS2_RC_SUCCESS; |
| 479 | } |
| 480 | |
| 481 | /** Set session attributes |
| 482 | * |
dantpm | f6ef247 | 2018-04-06 15:21:59 -0700 | [diff] [blame] | 483 | * Set or unset a session's attributes according to the provided flags and mask. |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 484 | * @verbatim new_attributes = old_attributes & ~mask | flags & mask @endverbatim |
| 485 | * Note: this function only applies to ESYS_TR objects that represent sessions. |
Juergen Repp | 506c473 | 2018-04-26 11:15:50 +0200 | [diff] [blame] | 486 | * @param esys_context [in,out] The ESYS_CONTEXT. |
| 487 | * @param esys_handle [in,out] The ESYS_TR of the session. |
| 488 | * @param flags [in] The flags to be set or unset for the session. |
| 489 | * @param mask [in] The mask for the flags to be set or unset. |
| 490 | * @retval TSS2_RC_SUCCESS on Success. |
| 491 | * @retval TSS2_ESYS_RC_BAD_REFERENCE if the esysContext is NULL. |
| 492 | * @retval TSS2_ESYS_RC_BAD_TR if the ESYS_TR object is unknown to the |
| 493 | * ESYS_CONTEXT or ESYS_TR object is not a session object. |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 494 | */ |
| 495 | TSS2_RC |
| 496 | Esys_TRSess_SetAttributes(ESYS_CONTEXT * esys_context, ESYS_TR esys_handle, |
| 497 | TPMA_SESSION flags, TPMA_SESSION mask) |
| 498 | { |
| 499 | RSRC_NODE_T *esys_object; |
Andreas Fuchs | 8071f1d | 2018-04-26 16:57:38 +0200 | [diff] [blame] | 500 | |
| 501 | _ESYS_ASSERT_NON_NULL(esys_context); |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 502 | TSS2_RC r = esys_GetResourceObject(esys_context, esys_handle, &esys_object); |
| 503 | return_if_error(r, "Object not found"); |
Juergen Repp | b832467 | 2018-02-23 11:15:39 +0100 | [diff] [blame] | 504 | |
Juergen Repp | ff821bd | 2017-12-11 15:21:42 +0100 | [diff] [blame] | 505 | if (esys_object->rsrc.rsrcType != IESYSC_SESSION_RSRC) |
| 506 | return_error(TSS2_ESYS_RC_BAD_TR, "Object is not a session object"); |
| 507 | esys_object->rsrc.misc.rsrc_session.sessionAttributes = |
| 508 | (esys_object->rsrc.misc.rsrc_session. |
| 509 | sessionAttributes & ~mask) | (flags & mask); |
| 510 | return TSS2_RC_SUCCESS; |
| 511 | } |