1 // 2 // Copyright (C) 2014 The Android Open Source Project 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #include "trunks/error_codes.h" 18 19 #include <sstream> 20 #include <string> 21 22 #include <base/logging.h> 23 24 namespace { 25 26 // Masks out the P and N bits (see TPM 2.0 Part 2 Table 14). 27 const trunks::TPM_RC kFormatOneErrorMask = 0x0BF; 28 // Selects just the N bits that identify the subject index. 29 const trunks::TPM_RC kFormatOneSubjectMask = 0x700; 30 const trunks::TPM_RC kLayerMask = 0xFFFFF000; 31 32 // Returns a known error code or the empty string if unknown. 33 std::string GetErrorStringInternal(trunks::TPM_RC error) { 34 switch (error) { 35 case trunks::TPM_RC_SUCCESS: return "TPM_RC_SUCCESS"; 36 case trunks::TPM_RC_BAD_TAG: return "TPM_RC_BAD_TAG"; 37 case trunks::TPM_RC_INITIALIZE: return "TPM_RC_INITIALIZE"; 38 case trunks::TPM_RC_FAILURE: return "TPM_RC_FAILURE"; 39 case trunks::TPM_RC_SEQUENCE: return "TPM_RC_SEQUENCE"; 40 case trunks::TPM_RC_PRIVATE: return "TPM_RC_PRIVATE"; 41 case trunks::TPM_RC_HMAC: return "TPM_RC_HMAC"; 42 case trunks::TPM_RC_DISABLED: return "TPM_RC_DISABLED"; 43 case trunks::TPM_RC_EXCLUSIVE: return "TPM_RC_EXCLUSIVE"; 44 case trunks::TPM_RC_AUTH_TYPE: return "TPM_RC_AUTH_TYPE"; 45 case trunks::TPM_RC_AUTH_MISSING: return "TPM_RC_AUTH_MISSING"; 46 case trunks::TPM_RC_POLICY: return "TPM_RC_POLICY"; 47 case trunks::TPM_RC_PCR: return "TPM_RC_PCR"; 48 case trunks::TPM_RC_PCR_CHANGED: return "TPM_RC_PCR_CHANGED"; 49 case trunks::TPM_RC_UPGRADE: return "TPM_RC_UPGRADE"; 50 case trunks::TPM_RC_TOO_MANY_CONTEXTS: return "TPM_RC_TOO_MANY_CONTEXTS"; 51 case trunks::TPM_RC_AUTH_UNAVAILABLE: return "TPM_RC_AUTH_UNAVAILABLE"; 52 case trunks::TPM_RC_REBOOT: return "TPM_RC_REBOOT"; 53 case trunks::TPM_RC_UNBALANCED: return "TPM_RC_UNBALANCED"; 54 case trunks::TPM_RC_COMMAND_SIZE: return "TPM_RC_COMMAND_SIZE"; 55 case trunks::TPM_RC_COMMAND_CODE: return "TPM_RC_COMMAND_CODE"; 56 case trunks::TPM_RC_AUTHSIZE: return "TPM_RC_AUTHSIZE"; 57 case trunks::TPM_RC_AUTH_CONTEXT: return "TPM_RC_AUTH_CONTEXT"; 58 case trunks::TPM_RC_NV_RANGE: return "TPM_RC_NV_RANGE"; 59 case trunks::TPM_RC_NV_SIZE: return "TPM_RC_NV_SIZE"; 60 case trunks::TPM_RC_NV_LOCKED: return "TPM_RC_NV_LOCKED"; 61 case trunks::TPM_RC_NV_AUTHORIZATION: return "TPM_RC_NV_AUTHORIZATION"; 62 case trunks::TPM_RC_NV_UNINITIALIZED: return "TPM_RC_NV_UNINITIALIZED"; 63 case trunks::TPM_RC_NV_SPACE: return "TPM_RC_NV_SPACE"; 64 case trunks::TPM_RC_NV_DEFINED: return "TPM_RC_NV_DEFINED"; 65 case trunks::TPM_RC_BAD_CONTEXT: return "TPM_RC_BAD_CONTEXT"; 66 case trunks::TPM_RC_CPHASH: return "TPM_RC_CPHASH"; 67 case trunks::TPM_RC_PARENT: return "TPM_RC_PARENT"; 68 case trunks::TPM_RC_NEEDS_TEST: return "TPM_RC_NEEDS_TEST"; 69 case trunks::TPM_RC_NO_RESULT: return "TPM_RC_NO_RESULT"; 70 case trunks::TPM_RC_SENSITIVE: return "TPM_RC_SENSITIVE"; 71 case trunks::TPM_RC_ASYMMETRIC: return "TPM_RC_ASYMMETRIC"; 72 case trunks::TPM_RC_ATTRIBUTES: return "TPM_RC_ATTRIBUTES"; 73 case trunks::TPM_RC_HASH: return "TPM_RC_HASH"; 74 case trunks::TPM_RC_VALUE: return "TPM_RC_VALUE"; 75 case trunks::TPM_RC_HIERARCHY: return "TPM_RC_HIERARCHY"; 76 case trunks::TPM_RC_KEY_SIZE: return "TPM_RC_KEY_SIZE"; 77 case trunks::TPM_RC_MGF: return "TPM_RC_MGF"; 78 case trunks::TPM_RC_MODE: return "TPM_RC_MODE"; 79 case trunks::TPM_RC_TYPE: return "TPM_RC_TYPE"; 80 case trunks::TPM_RC_HANDLE: return "TPM_RC_HANDLE"; 81 case trunks::TPM_RC_KDF: return "TPM_RC_KDF"; 82 case trunks::TPM_RC_RANGE: return "TPM_RC_RANGE"; 83 case trunks::TPM_RC_AUTH_FAIL: return "TPM_RC_AUTH_FAIL"; 84 case trunks::TPM_RC_NONCE: return "TPM_RC_NONCE"; 85 case trunks::TPM_RC_PP: return "TPM_RC_PP"; 86 case trunks::TPM_RC_SCHEME: return "TPM_RC_SCHEME"; 87 case trunks::TPM_RC_SIZE: return "TPM_RC_SIZE"; 88 case trunks::TPM_RC_SYMMETRIC: return "TPM_RC_SYMMETRIC"; 89 case trunks::TPM_RC_TAG: return "TPM_RC_TAG"; 90 case trunks::TPM_RC_SELECTOR: return "TPM_RC_SELECTOR"; 91 case trunks::TPM_RC_INSUFFICIENT: return "TPM_RC_INSUFFICIENT"; 92 case trunks::TPM_RC_SIGNATURE: return "TPM_RC_SIGNATURE"; 93 case trunks::TPM_RC_KEY: return "TPM_RC_KEY"; 94 case trunks::TPM_RC_POLICY_FAIL: return "TPM_RC_POLICY_FAIL"; 95 case trunks::TPM_RC_INTEGRITY: return "TPM_RC_INTEGRITY"; 96 case trunks::TPM_RC_TICKET: return "TPM_RC_TICKET"; 97 case trunks::TPM_RC_RESERVED_BITS: return "TPM_RC_RESERVED_BITS"; 98 case trunks::TPM_RC_BAD_AUTH: return "TPM_RC_BAD_AUTH"; 99 case trunks::TPM_RC_EXPIRED: return "TPM_RC_EXPIRED"; 100 case trunks::TPM_RC_POLICY_CC: return "TPM_RC_POLICY_CC"; 101 case trunks::TPM_RC_BINDING: return "TPM_RC_BINDING"; 102 case trunks::TPM_RC_CURVE: return "TPM_RC_CURVE"; 103 case trunks::TPM_RC_ECC_POINT: return "TPM_RC_ECC_POINT"; 104 case trunks::TPM_RC_CONTEXT_GAP: return "TPM_RC_CONTEXT_GAP"; 105 case trunks::TPM_RC_OBJECT_MEMORY: return "TPM_RC_OBJECT_MEMORY"; 106 case trunks::TPM_RC_SESSION_MEMORY: return "TPM_RC_SESSION_MEMORY"; 107 case trunks::TPM_RC_MEMORY: return "TPM_RC_MEMORY"; 108 case trunks::TPM_RC_SESSION_HANDLES: return "TPM_RC_SESSION_HANDLES"; 109 case trunks::TPM_RC_OBJECT_HANDLES: return "TPM_RC_OBJECT_HANDLES"; 110 case trunks::TPM_RC_LOCALITY: return "TPM_RC_LOCALITY"; 111 case trunks::TPM_RC_YIELDED: return "TPM_RC_YIELDED"; 112 case trunks::TPM_RC_CANCELED: return "TPM_RC_CANCELED"; 113 case trunks::TPM_RC_TESTING: return "TPM_RC_TESTING"; 114 case trunks::TPM_RC_REFERENCE_H0: return "TPM_RC_REFERENCE_H0"; 115 case trunks::TPM_RC_REFERENCE_H1: return "TPM_RC_REFERENCE_H1"; 116 case trunks::TPM_RC_REFERENCE_H2: return "TPM_RC_REFERENCE_H2"; 117 case trunks::TPM_RC_REFERENCE_H3: return "TPM_RC_REFERENCE_H3"; 118 case trunks::TPM_RC_REFERENCE_H4: return "TPM_RC_REFERENCE_H4"; 119 case trunks::TPM_RC_REFERENCE_H5: return "TPM_RC_REFERENCE_H5"; 120 case trunks::TPM_RC_REFERENCE_H6: return "TPM_RC_REFERENCE_H6"; 121 case trunks::TPM_RC_REFERENCE_S0: return "TPM_RC_REFERENCE_S0"; 122 case trunks::TPM_RC_REFERENCE_S1: return "TPM_RC_REFERENCE_S1"; 123 case trunks::TPM_RC_REFERENCE_S2: return "TPM_RC_REFERENCE_S2"; 124 case trunks::TPM_RC_REFERENCE_S3: return "TPM_RC_REFERENCE_S3"; 125 case trunks::TPM_RC_REFERENCE_S4: return "TPM_RC_REFERENCE_S4"; 126 case trunks::TPM_RC_REFERENCE_S5: return "TPM_RC_REFERENCE_S5"; 127 case trunks::TPM_RC_REFERENCE_S6: return "TPM_RC_REFERENCE_S6"; 128 case trunks::TPM_RC_NV_RATE: return "TPM_RC_NV_RATE"; 129 case trunks::TPM_RC_LOCKOUT: return "TPM_RC_LOCKOUT"; 130 case trunks::TPM_RC_RETRY: return "TPM_RC_RETRY"; 131 case trunks::TPM_RC_NV_UNAVAILABLE: return "TPM_RC_NV_UNAVAILABLE"; 132 case trunks::TPM_RC_NOT_USED: return "TPM_RC_NOT_USED"; 133 case trunks::TRUNKS_RC_AUTHORIZATION_FAILED: 134 return "TRUNKS_RC_AUTHORIZATION_FAILED"; 135 case trunks::TRUNKS_RC_ENCRYPTION_FAILED: 136 return "TRUNKS_RC_ENCRYPTION_FAILED"; 137 case trunks::TRUNKS_RC_READ_ERROR: return "TRUNKS_RC_READ_ERROR"; 138 case trunks::TRUNKS_RC_WRITE_ERROR: return "TRUNKS_RC_WRITE_ERROR"; 139 case trunks::TRUNKS_RC_IPC_ERROR: return "TRUNKS_RC_IPC_ERROR"; 140 case trunks::TCTI_RC_TRY_AGAIN: return "TCTI_RC_TRY_AGAIN"; 141 case trunks::TCTI_RC_GENERAL_FAILURE: return "TCTI_RC_GENERAL_FAILURE"; 142 case trunks::TCTI_RC_BAD_CONTEXT: return "TCTI_RC_BAD_CONTEXT"; 143 case trunks::TCTI_RC_WRONG_ABI_VERSION: return "TCTI_RC_WRONG_ABI_VERSION"; 144 case trunks::TCTI_RC_NOT_IMPLEMENTED: return "TCTI_RC_NOT_IMPLEMENTED"; 145 case trunks::TCTI_RC_BAD_PARAMETER: return "TCTI_RC_BAD_PARAMETER"; 146 case trunks::TCTI_RC_INSUFFICIENT_BUFFER: 147 return "TCTI_RC_INSUFFICIENT_BUFFER"; 148 case trunks::TCTI_RC_NO_CONNECTION: return "TCTI_RC_NO_CONNECTION"; 149 case trunks::TCTI_RC_DRIVER_NOT_FOUND: return "TCTI_RC_DRIVER_NOT_FOUND"; 150 case trunks::TCTI_RC_DRIVERINFO_NOT_FOUND: 151 return "TCTI_RC_DRIVERINFO_NOT_FOUND"; 152 case trunks::TCTI_RC_NO_RESPONSE: return "TCTI_RC_NO_RESPONSE"; 153 case trunks::TCTI_RC_BAD_VALUE: return "TCTI_RC_BAD_VALUE"; 154 case trunks::SAPI_RC_INVALID_SESSIONS: return "SAPI_RC_INVALID_SESSIONS"; 155 case trunks::SAPI_RC_ABI_MISMATCH: return "SAPI_RC_ABI_MISMATCH"; 156 case trunks::SAPI_RC_INSUFFICIENT_BUFFER: 157 return "SAPI_RC_INSUFFICIENT_BUFFER"; 158 case trunks::SAPI_RC_BAD_PARAMETER: return "SAPI_RC_BAD_PARAMETER"; 159 case trunks::SAPI_RC_BAD_SEQUENCE: return "SAPI_RC_BAD_SEQUENCE"; 160 case trunks::SAPI_RC_NO_DECRYPT_PARAM: return "SAPI_RC_NO_DECRYPT_PARAM"; 161 case trunks::SAPI_RC_NO_ENCRYPT_PARAM: return "SAPI_RC_NO_ENCRYPT_PARAM"; 162 case trunks::SAPI_RC_NO_RESPONSE_RECEIVED: 163 return "SAPI_RC_NO_RESPONSE_RECEIVED"; 164 case trunks::SAPI_RC_BAD_SIZE: return "SAPI_RC_BAD_SIZE"; 165 case trunks::SAPI_RC_CORRUPTED_DATA: return "SAPI_RC_CORRUPTED_DATA"; 166 case trunks::SAPI_RC_INSUFFICIENT_CONTEXT: 167 return "SAPI_RC_INSUFFICIENT_CONTEXT"; 168 case trunks::SAPI_RC_INSUFFICIENT_RESPONSE: 169 return "SAPI_RC_INSUFFICIENT_RESPONSE"; 170 case trunks::SAPI_RC_INCOMPATIBLE_TCTI: return "SAPI_RC_INCOMPATIBLE_TCTI"; 171 case trunks::SAPI_RC_MALFORMED_RESPONSE: 172 return "SAPI_RC_MALFORMED_RESPONSE"; 173 case trunks::SAPI_RC_BAD_TCTI_STRUCTURE: 174 return "SAPI_RC_BAD_TCTI_STRUCTURE"; 175 default: return std::string(); 176 } 177 NOTREACHED(); 178 return std::string(); 179 } 180 181 bool IsFormatOne(trunks::TPM_RC error) { 182 return (error & kLayerMask) == 0 && (error & trunks::RC_FMT1) != 0; 183 } 184 185 } // namespace 186 187 namespace trunks { 188 189 std::string GetErrorString(TPM_RC error) { 190 std::string error_string = GetErrorStringInternal(error); 191 if (!error_string.empty()) { 192 return error_string; 193 } 194 std::stringstream ss; 195 if ((error & kLayerMask) == kResourceManagerTpmErrorBase) { 196 error &= ~kLayerMask; 197 error_string = GetErrorStringInternal(error); 198 ss << "Resource Manager: "; 199 } 200 // Check if we have a TPM 'Format-One' response code. 201 if (IsFormatOne(error)) { 202 if (error & TPM_RC_P) { 203 ss << "Parameter "; 204 } else if (error & TPM_RC_S) { 205 ss << "Session "; 206 } else { 207 ss << "Handle "; 208 } 209 // Bits 8-10 specify which handle / parameter / session. 210 ss << ((error & kFormatOneSubjectMask) >> 8) << ": "; 211 // Mask out everything but the format bit and error number. 212 error_string = GetErrorStringInternal(error & kFormatOneErrorMask); 213 if (!error_string.empty()) { 214 ss << error_string; 215 } 216 } 217 if (error_string.empty()) { 218 ss << "Unknown error: " << error << " (0x" << std::hex << error << ")"; 219 } 220 return ss.str(); 221 } 222 223 TPM_RC GetFormatOneError(TPM_RC error) { 224 if (IsFormatOne(error)) { 225 return (error & kFormatOneErrorMask); 226 } 227 return error; 228 } 229 230 std::string CreateErrorResponse(TPM_RC error_code) { 231 const uint32_t kErrorResponseSize = 10; 232 std::string response; 233 CHECK_EQ(Serialize_TPM_ST(TPM_ST_NO_SESSIONS, &response), TPM_RC_SUCCESS); 234 CHECK_EQ(Serialize_UINT32(kErrorResponseSize, &response), TPM_RC_SUCCESS); 235 CHECK_EQ(Serialize_TPM_RC(error_code, &response), TPM_RC_SUCCESS); 236 return response; 237 } 238 239 } // namespace trunks 240