| // Copyright 2014 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "trunks/error_codes.h" |
| |
| #include <sstream> |
| #include <string> |
| |
| #include <base/logging.h> |
| |
| namespace { |
| |
| // Masks out the P and N bits (see TPM 2.0 Part 2 Table 14). |
| const trunks::TPM_RC kFormatOneErrorMask = 0x0BF; |
| // Selects just the N bits that identify the subject index. |
| const trunks::TPM_RC kFormatOneSubjectMask = 0x700; |
| const trunks::TPM_RC kLayerMask = 0xFFFFF000; |
| |
| // Returns a known error code or the empty string if unknown. |
| std::string GetErrorStringInternal(trunks::TPM_RC error) { |
| switch (error) { |
| case trunks::TPM_RC_SUCCESS: return "TPM_RC_SUCCESS"; |
| case trunks::TPM_RC_BAD_TAG: return "TPM_RC_BAD_TAG"; |
| case trunks::TPM_RC_INITIALIZE: return "TPM_RC_INITIALIZE"; |
| case trunks::TPM_RC_FAILURE: return "TPM_RC_FAILURE"; |
| case trunks::TPM_RC_SEQUENCE: return "TPM_RC_SEQUENCE"; |
| case trunks::TPM_RC_PRIVATE: return "TPM_RC_PRIVATE"; |
| case trunks::TPM_RC_HMAC: return "TPM_RC_HMAC"; |
| case trunks::TPM_RC_DISABLED: return "TPM_RC_DISABLED"; |
| case trunks::TPM_RC_EXCLUSIVE: return "TPM_RC_EXCLUSIVE"; |
| case trunks::TPM_RC_AUTH_TYPE: return "TPM_RC_AUTH_TYPE"; |
| case trunks::TPM_RC_AUTH_MISSING: return "TPM_RC_AUTH_MISSING"; |
| case trunks::TPM_RC_POLICY: return "TPM_RC_POLICY"; |
| case trunks::TPM_RC_PCR: return "TPM_RC_PCR"; |
| case trunks::TPM_RC_PCR_CHANGED: return "TPM_RC_PCR_CHANGED"; |
| case trunks::TPM_RC_UPGRADE: return "TPM_RC_UPGRADE"; |
| case trunks::TPM_RC_TOO_MANY_CONTEXTS: return "TPM_RC_TOO_MANY_CONTEXTS"; |
| case trunks::TPM_RC_AUTH_UNAVAILABLE: return "TPM_RC_AUTH_UNAVAILABLE"; |
| case trunks::TPM_RC_REBOOT: return "TPM_RC_REBOOT"; |
| case trunks::TPM_RC_UNBALANCED: return "TPM_RC_UNBALANCED"; |
| case trunks::TPM_RC_COMMAND_SIZE: return "TPM_RC_COMMAND_SIZE"; |
| case trunks::TPM_RC_COMMAND_CODE: return "TPM_RC_COMMAND_CODE"; |
| case trunks::TPM_RC_AUTHSIZE: return "TPM_RC_AUTHSIZE"; |
| case trunks::TPM_RC_AUTH_CONTEXT: return "TPM_RC_AUTH_CONTEXT"; |
| case trunks::TPM_RC_NV_RANGE: return "TPM_RC_NV_RANGE"; |
| case trunks::TPM_RC_NV_SIZE: return "TPM_RC_NV_SIZE"; |
| case trunks::TPM_RC_NV_LOCKED: return "TPM_RC_NV_LOCKED"; |
| case trunks::TPM_RC_NV_AUTHORIZATION: return "TPM_RC_NV_AUTHORIZATION"; |
| case trunks::TPM_RC_NV_UNINITIALIZED: return "TPM_RC_NV_UNINITIALIZED"; |
| case trunks::TPM_RC_NV_SPACE: return "TPM_RC_NV_SPACE"; |
| case trunks::TPM_RC_NV_DEFINED: return "TPM_RC_NV_DEFINED"; |
| case trunks::TPM_RC_BAD_CONTEXT: return "TPM_RC_BAD_CONTEXT"; |
| case trunks::TPM_RC_CPHASH: return "TPM_RC_CPHASH"; |
| case trunks::TPM_RC_PARENT: return "TPM_RC_PARENT"; |
| case trunks::TPM_RC_NEEDS_TEST: return "TPM_RC_NEEDS_TEST"; |
| case trunks::TPM_RC_NO_RESULT: return "TPM_RC_NO_RESULT"; |
| case trunks::TPM_RC_SENSITIVE: return "TPM_RC_SENSITIVE"; |
| case trunks::TPM_RC_ASYMMETRIC: return "TPM_RC_ASYMMETRIC"; |
| case trunks::TPM_RC_ATTRIBUTES: return "TPM_RC_ATTRIBUTES"; |
| case trunks::TPM_RC_HASH: return "TPM_RC_HASH"; |
| case trunks::TPM_RC_VALUE: return "TPM_RC_VALUE"; |
| case trunks::TPM_RC_HIERARCHY: return "TPM_RC_HIERARCHY"; |
| case trunks::TPM_RC_KEY_SIZE: return "TPM_RC_KEY_SIZE"; |
| case trunks::TPM_RC_MGF: return "TPM_RC_MGF"; |
| case trunks::TPM_RC_MODE: return "TPM_RC_MODE"; |
| case trunks::TPM_RC_TYPE: return "TPM_RC_TYPE"; |
| case trunks::TPM_RC_HANDLE: return "TPM_RC_HANDLE"; |
| case trunks::TPM_RC_KDF: return "TPM_RC_KDF"; |
| case trunks::TPM_RC_RANGE: return "TPM_RC_RANGE"; |
| case trunks::TPM_RC_AUTH_FAIL: return "TPM_RC_AUTH_FAIL"; |
| case trunks::TPM_RC_NONCE: return "TPM_RC_NONCE"; |
| case trunks::TPM_RC_PP: return "TPM_RC_PP"; |
| case trunks::TPM_RC_SCHEME: return "TPM_RC_SCHEME"; |
| case trunks::TPM_RC_SIZE: return "TPM_RC_SIZE"; |
| case trunks::TPM_RC_SYMMETRIC: return "TPM_RC_SYMMETRIC"; |
| case trunks::TPM_RC_TAG: return "TPM_RC_TAG"; |
| case trunks::TPM_RC_SELECTOR: return "TPM_RC_SELECTOR"; |
| case trunks::TPM_RC_INSUFFICIENT: return "TPM_RC_INSUFFICIENT"; |
| case trunks::TPM_RC_SIGNATURE: return "TPM_RC_SIGNATURE"; |
| case trunks::TPM_RC_KEY: return "TPM_RC_KEY"; |
| case trunks::TPM_RC_POLICY_FAIL: return "TPM_RC_POLICY_FAIL"; |
| case trunks::TPM_RC_INTEGRITY: return "TPM_RC_INTEGRITY"; |
| case trunks::TPM_RC_TICKET: return "TPM_RC_TICKET"; |
| case trunks::TPM_RC_RESERVED_BITS: return "TPM_RC_RESERVED_BITS"; |
| case trunks::TPM_RC_BAD_AUTH: return "TPM_RC_BAD_AUTH"; |
| case trunks::TPM_RC_EXPIRED: return "TPM_RC_EXPIRED"; |
| case trunks::TPM_RC_POLICY_CC: return "TPM_RC_POLICY_CC"; |
| case trunks::TPM_RC_BINDING: return "TPM_RC_BINDING"; |
| case trunks::TPM_RC_CURVE: return "TPM_RC_CURVE"; |
| case trunks::TPM_RC_ECC_POINT: return "TPM_RC_ECC_POINT"; |
| case trunks::TPM_RC_CONTEXT_GAP: return "TPM_RC_CONTEXT_GAP"; |
| case trunks::TPM_RC_OBJECT_MEMORY: return "TPM_RC_OBJECT_MEMORY"; |
| case trunks::TPM_RC_SESSION_MEMORY: return "TPM_RC_SESSION_MEMORY"; |
| case trunks::TPM_RC_MEMORY: return "TPM_RC_MEMORY"; |
| case trunks::TPM_RC_SESSION_HANDLES: return "TPM_RC_SESSION_HANDLES"; |
| case trunks::TPM_RC_OBJECT_HANDLES: return "TPM_RC_OBJECT_HANDLES"; |
| case trunks::TPM_RC_LOCALITY: return "TPM_RC_LOCALITY"; |
| case trunks::TPM_RC_YIELDED: return "TPM_RC_YIELDED"; |
| case trunks::TPM_RC_CANCELED: return "TPM_RC_CANCELED"; |
| case trunks::TPM_RC_TESTING: return "TPM_RC_TESTING"; |
| case trunks::TPM_RC_REFERENCE_H0: return "TPM_RC_REFERENCE_H0"; |
| case trunks::TPM_RC_REFERENCE_H1: return "TPM_RC_REFERENCE_H1"; |
| case trunks::TPM_RC_REFERENCE_H2: return "TPM_RC_REFERENCE_H2"; |
| case trunks::TPM_RC_REFERENCE_H3: return "TPM_RC_REFERENCE_H3"; |
| case trunks::TPM_RC_REFERENCE_H4: return "TPM_RC_REFERENCE_H4"; |
| case trunks::TPM_RC_REFERENCE_H5: return "TPM_RC_REFERENCE_H5"; |
| case trunks::TPM_RC_REFERENCE_H6: return "TPM_RC_REFERENCE_H6"; |
| case trunks::TPM_RC_REFERENCE_S0: return "TPM_RC_REFERENCE_S0"; |
| case trunks::TPM_RC_REFERENCE_S1: return "TPM_RC_REFERENCE_S1"; |
| case trunks::TPM_RC_REFERENCE_S2: return "TPM_RC_REFERENCE_S2"; |
| case trunks::TPM_RC_REFERENCE_S3: return "TPM_RC_REFERENCE_S3"; |
| case trunks::TPM_RC_REFERENCE_S4: return "TPM_RC_REFERENCE_S4"; |
| case trunks::TPM_RC_REFERENCE_S5: return "TPM_RC_REFERENCE_S5"; |
| case trunks::TPM_RC_REFERENCE_S6: return "TPM_RC_REFERENCE_S6"; |
| case trunks::TPM_RC_NV_RATE: return "TPM_RC_NV_RATE"; |
| case trunks::TPM_RC_LOCKOUT: return "TPM_RC_LOCKOUT"; |
| case trunks::TPM_RC_RETRY: return "TPM_RC_RETRY"; |
| case trunks::TPM_RC_NV_UNAVAILABLE: return "TPM_RC_NV_UNAVAILABLE"; |
| case trunks::TPM_RC_NOT_USED: return "TPM_RC_NOT_USED"; |
| case trunks::TRUNKS_RC_AUTHORIZATION_FAILED: |
| return "TRUNKS_RC_AUTHORIZATION_FAILED"; |
| case trunks::TRUNKS_RC_ENCRYPTION_FAILED: |
| return "TRUNKS_RC_ENCRYPTION_FAILED"; |
| case trunks::TRUNKS_RC_READ_ERROR: return "TRUNKS_RC_READ_ERROR"; |
| case trunks::TRUNKS_RC_WRITE_ERROR: return "TRUNKS_RC_WRITE_ERROR"; |
| case trunks::TCTI_RC_TRY_AGAIN: return "TCTI_RC_TRY_AGAIN"; |
| case trunks::TCTI_RC_GENERAL_FAILURE: return "TCTI_RC_GENERAL_FAILURE"; |
| case trunks::TCTI_RC_BAD_CONTEXT: return "TCTI_RC_BAD_CONTEXT"; |
| case trunks::TCTI_RC_WRONG_ABI_VERSION: return "TCTI_RC_WRONG_ABI_VERSION"; |
| case trunks::TCTI_RC_NOT_IMPLEMENTED: return "TCTI_RC_NOT_IMPLEMENTED"; |
| case trunks::TCTI_RC_BAD_PARAMETER: return "TCTI_RC_BAD_PARAMETER"; |
| case trunks::TCTI_RC_INSUFFICIENT_BUFFER: |
| return "TCTI_RC_INSUFFICIENT_BUFFER"; |
| case trunks::TCTI_RC_NO_CONNECTION: return "TCTI_RC_NO_CONNECTION"; |
| case trunks::TCTI_RC_DRIVER_NOT_FOUND: return "TCTI_RC_DRIVER_NOT_FOUND"; |
| case trunks::TCTI_RC_DRIVERINFO_NOT_FOUND: |
| return "TCTI_RC_DRIVERINFO_NOT_FOUND"; |
| case trunks::TCTI_RC_NO_RESPONSE: return "TCTI_RC_NO_RESPONSE"; |
| case trunks::TCTI_RC_BAD_VALUE: return "TCTI_RC_BAD_VALUE"; |
| case trunks::SAPI_RC_INVALID_SESSIONS: return "SAPI_RC_INVALID_SESSIONS"; |
| case trunks::SAPI_RC_ABI_MISMATCH: return "SAPI_RC_ABI_MISMATCH"; |
| case trunks::SAPI_RC_INSUFFICIENT_BUFFER: |
| return "SAPI_RC_INSUFFICIENT_BUFFER"; |
| case trunks::SAPI_RC_BAD_PARAMETER: return "SAPI_RC_BAD_PARAMETER"; |
| case trunks::SAPI_RC_BAD_SEQUENCE: return "SAPI_RC_BAD_SEQUENCE"; |
| case trunks::SAPI_RC_NO_DECRYPT_PARAM: return "SAPI_RC_NO_DECRYPT_PARAM"; |
| case trunks::SAPI_RC_NO_ENCRYPT_PARAM: return "SAPI_RC_NO_ENCRYPT_PARAM"; |
| case trunks::SAPI_RC_NO_RESPONSE_RECEIVED: |
| return "SAPI_RC_NO_RESPONSE_RECEIVED"; |
| case trunks::SAPI_RC_BAD_SIZE: return "SAPI_RC_BAD_SIZE"; |
| case trunks::SAPI_RC_CORRUPTED_DATA: return "SAPI_RC_CORRUPTED_DATA"; |
| case trunks::SAPI_RC_INSUFFICIENT_CONTEXT: |
| return "SAPI_RC_INSUFFICIENT_CONTEXT"; |
| case trunks::SAPI_RC_INSUFFICIENT_RESPONSE: |
| return "SAPI_RC_INSUFFICIENT_RESPONSE"; |
| case trunks::SAPI_RC_INCOMPATIBLE_TCTI: return "SAPI_RC_INCOMPATIBLE_TCTI"; |
| case trunks::SAPI_RC_MALFORMED_RESPONSE: |
| return "SAPI_RC_MALFORMED_RESPONSE"; |
| case trunks::SAPI_RC_BAD_TCTI_STRUCTURE: |
| return "SAPI_RC_BAD_TCTI_STRUCTURE"; |
| default: return std::string(); |
| } |
| NOTREACHED(); |
| return std::string(); |
| } |
| |
| bool IsFormatOne(trunks::TPM_RC error) { |
| return (error & kLayerMask) == 0 && (error & trunks::RC_FMT1) != 0; |
| } |
| |
| } // namespace |
| |
| namespace trunks { |
| |
| std::string GetErrorString(TPM_RC error) { |
| std::string error_string = GetErrorStringInternal(error); |
| if (!error_string.empty()) { |
| return error_string; |
| } |
| std::stringstream ss; |
| // Check if we have a TPM 'Format-One' response code. |
| if (IsFormatOne(error)) { |
| if (error & TPM_RC_P) { |
| ss << "Parameter "; |
| } else if (error & TPM_RC_S) { |
| ss << "Session "; |
| } else { |
| ss << "Handle "; |
| } |
| // Bits 8-10 specify which handle / parameter / session. |
| ss << ((error & kFormatOneSubjectMask) >> 8) << ": "; |
| // Mask out everything but the format bit and error number. |
| error_string = GetErrorStringInternal(error & kFormatOneErrorMask); |
| if (!error_string.empty()) { |
| ss << error_string; |
| } |
| } |
| if (error_string.empty()) { |
| ss << "Unknown error: " << error << " (0x" << std::hex << error << ")"; |
| } |
| return ss.str(); |
| } |
| |
| TPM_RC CHROMEOS_EXPORT GetFormatOneError(TPM_RC error) { |
| if (IsFormatOne(error)) { |
| return (error & kFormatOneErrorMask); |
| } |
| return error; |
| } |
| |
| } // namespace trunks |