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
24namespace {
25
26// Masks out the P and N bits (see TPM 2.0 Part 2 Table 14).
27const trunks::TPM_RC kFormatOneErrorMask = 0x0BF;
28// Selects just the N bits that identify the subject index.
29const trunks::TPM_RC kFormatOneSubjectMask = 0x700;
30const trunks::TPM_RC kLayerMask = 0xFFFFF000;
31
32// Returns a known error code or the empty string if unknown.
33std::string GetErrorStringInternal(trunks::TPM_RC error) {
34  switch (error) {
35    case trunks::TPM_RC_SUCCESS:
36      return "TPM_RC_SUCCESS";
37    case trunks::TPM_RC_BAD_TAG:
38      return "TPM_RC_BAD_TAG";
39    case trunks::TPM_RC_INITIALIZE:
40      return "TPM_RC_INITIALIZE";
41    case trunks::TPM_RC_FAILURE:
42      return "TPM_RC_FAILURE";
43    case trunks::TPM_RC_SEQUENCE:
44      return "TPM_RC_SEQUENCE";
45    case trunks::TPM_RC_PRIVATE:
46      return "TPM_RC_PRIVATE";
47    case trunks::TPM_RC_HMAC:
48      return "TPM_RC_HMAC";
49    case trunks::TPM_RC_DISABLED:
50      return "TPM_RC_DISABLED";
51    case trunks::TPM_RC_EXCLUSIVE:
52      return "TPM_RC_EXCLUSIVE";
53    case trunks::TPM_RC_AUTH_TYPE:
54      return "TPM_RC_AUTH_TYPE";
55    case trunks::TPM_RC_AUTH_MISSING:
56      return "TPM_RC_AUTH_MISSING";
57    case trunks::TPM_RC_POLICY:
58      return "TPM_RC_POLICY";
59    case trunks::TPM_RC_PCR:
60      return "TPM_RC_PCR";
61    case trunks::TPM_RC_PCR_CHANGED:
62      return "TPM_RC_PCR_CHANGED";
63    case trunks::TPM_RC_UPGRADE:
64      return "TPM_RC_UPGRADE";
65    case trunks::TPM_RC_TOO_MANY_CONTEXTS:
66      return "TPM_RC_TOO_MANY_CONTEXTS";
67    case trunks::TPM_RC_AUTH_UNAVAILABLE:
68      return "TPM_RC_AUTH_UNAVAILABLE";
69    case trunks::TPM_RC_REBOOT:
70      return "TPM_RC_REBOOT";
71    case trunks::TPM_RC_UNBALANCED:
72      return "TPM_RC_UNBALANCED";
73    case trunks::TPM_RC_COMMAND_SIZE:
74      return "TPM_RC_COMMAND_SIZE";
75    case trunks::TPM_RC_COMMAND_CODE:
76      return "TPM_RC_COMMAND_CODE";
77    case trunks::TPM_RC_AUTHSIZE:
78      return "TPM_RC_AUTHSIZE";
79    case trunks::TPM_RC_AUTH_CONTEXT:
80      return "TPM_RC_AUTH_CONTEXT";
81    case trunks::TPM_RC_NV_RANGE:
82      return "TPM_RC_NV_RANGE";
83    case trunks::TPM_RC_NV_SIZE:
84      return "TPM_RC_NV_SIZE";
85    case trunks::TPM_RC_NV_LOCKED:
86      return "TPM_RC_NV_LOCKED";
87    case trunks::TPM_RC_NV_AUTHORIZATION:
88      return "TPM_RC_NV_AUTHORIZATION";
89    case trunks::TPM_RC_NV_UNINITIALIZED:
90      return "TPM_RC_NV_UNINITIALIZED";
91    case trunks::TPM_RC_NV_SPACE:
92      return "TPM_RC_NV_SPACE";
93    case trunks::TPM_RC_NV_DEFINED:
94      return "TPM_RC_NV_DEFINED";
95    case trunks::TPM_RC_BAD_CONTEXT:
96      return "TPM_RC_BAD_CONTEXT";
97    case trunks::TPM_RC_CPHASH:
98      return "TPM_RC_CPHASH";
99    case trunks::TPM_RC_PARENT:
100      return "TPM_RC_PARENT";
101    case trunks::TPM_RC_NEEDS_TEST:
102      return "TPM_RC_NEEDS_TEST";
103    case trunks::TPM_RC_NO_RESULT:
104      return "TPM_RC_NO_RESULT";
105    case trunks::TPM_RC_SENSITIVE:
106      return "TPM_RC_SENSITIVE";
107    case trunks::TPM_RC_ASYMMETRIC:
108      return "TPM_RC_ASYMMETRIC";
109    case trunks::TPM_RC_ATTRIBUTES:
110      return "TPM_RC_ATTRIBUTES";
111    case trunks::TPM_RC_HASH:
112      return "TPM_RC_HASH";
113    case trunks::TPM_RC_VALUE:
114      return "TPM_RC_VALUE";
115    case trunks::TPM_RC_HIERARCHY:
116      return "TPM_RC_HIERARCHY";
117    case trunks::TPM_RC_KEY_SIZE:
118      return "TPM_RC_KEY_SIZE";
119    case trunks::TPM_RC_MGF:
120      return "TPM_RC_MGF";
121    case trunks::TPM_RC_MODE:
122      return "TPM_RC_MODE";
123    case trunks::TPM_RC_TYPE:
124      return "TPM_RC_TYPE";
125    case trunks::TPM_RC_HANDLE:
126      return "TPM_RC_HANDLE";
127    case trunks::TPM_RC_KDF:
128      return "TPM_RC_KDF";
129    case trunks::TPM_RC_RANGE:
130      return "TPM_RC_RANGE";
131    case trunks::TPM_RC_AUTH_FAIL:
132      return "TPM_RC_AUTH_FAIL";
133    case trunks::TPM_RC_NONCE:
134      return "TPM_RC_NONCE";
135    case trunks::TPM_RC_PP:
136      return "TPM_RC_PP";
137    case trunks::TPM_RC_SCHEME:
138      return "TPM_RC_SCHEME";
139    case trunks::TPM_RC_SIZE:
140      return "TPM_RC_SIZE";
141    case trunks::TPM_RC_SYMMETRIC:
142      return "TPM_RC_SYMMETRIC";
143    case trunks::TPM_RC_TAG:
144      return "TPM_RC_TAG";
145    case trunks::TPM_RC_SELECTOR:
146      return "TPM_RC_SELECTOR";
147    case trunks::TPM_RC_INSUFFICIENT:
148      return "TPM_RC_INSUFFICIENT";
149    case trunks::TPM_RC_SIGNATURE:
150      return "TPM_RC_SIGNATURE";
151    case trunks::TPM_RC_KEY:
152      return "TPM_RC_KEY";
153    case trunks::TPM_RC_POLICY_FAIL:
154      return "TPM_RC_POLICY_FAIL";
155    case trunks::TPM_RC_INTEGRITY:
156      return "TPM_RC_INTEGRITY";
157    case trunks::TPM_RC_TICKET:
158      return "TPM_RC_TICKET";
159    case trunks::TPM_RC_RESERVED_BITS:
160      return "TPM_RC_RESERVED_BITS";
161    case trunks::TPM_RC_BAD_AUTH:
162      return "TPM_RC_BAD_AUTH";
163    case trunks::TPM_RC_EXPIRED:
164      return "TPM_RC_EXPIRED";
165    case trunks::TPM_RC_POLICY_CC:
166      return "TPM_RC_POLICY_CC";
167    case trunks::TPM_RC_BINDING:
168      return "TPM_RC_BINDING";
169    case trunks::TPM_RC_CURVE:
170      return "TPM_RC_CURVE";
171    case trunks::TPM_RC_ECC_POINT:
172      return "TPM_RC_ECC_POINT";
173    case trunks::TPM_RC_CONTEXT_GAP:
174      return "TPM_RC_CONTEXT_GAP";
175    case trunks::TPM_RC_OBJECT_MEMORY:
176      return "TPM_RC_OBJECT_MEMORY";
177    case trunks::TPM_RC_SESSION_MEMORY:
178      return "TPM_RC_SESSION_MEMORY";
179    case trunks::TPM_RC_MEMORY:
180      return "TPM_RC_MEMORY";
181    case trunks::TPM_RC_SESSION_HANDLES:
182      return "TPM_RC_SESSION_HANDLES";
183    case trunks::TPM_RC_OBJECT_HANDLES:
184      return "TPM_RC_OBJECT_HANDLES";
185    case trunks::TPM_RC_LOCALITY:
186      return "TPM_RC_LOCALITY";
187    case trunks::TPM_RC_YIELDED:
188      return "TPM_RC_YIELDED";
189    case trunks::TPM_RC_CANCELED:
190      return "TPM_RC_CANCELED";
191    case trunks::TPM_RC_TESTING:
192      return "TPM_RC_TESTING";
193    case trunks::TPM_RC_REFERENCE_H0:
194      return "TPM_RC_REFERENCE_H0";
195    case trunks::TPM_RC_REFERENCE_H1:
196      return "TPM_RC_REFERENCE_H1";
197    case trunks::TPM_RC_REFERENCE_H2:
198      return "TPM_RC_REFERENCE_H2";
199    case trunks::TPM_RC_REFERENCE_H3:
200      return "TPM_RC_REFERENCE_H3";
201    case trunks::TPM_RC_REFERENCE_H4:
202      return "TPM_RC_REFERENCE_H4";
203    case trunks::TPM_RC_REFERENCE_H5:
204      return "TPM_RC_REFERENCE_H5";
205    case trunks::TPM_RC_REFERENCE_H6:
206      return "TPM_RC_REFERENCE_H6";
207    case trunks::TPM_RC_REFERENCE_S0:
208      return "TPM_RC_REFERENCE_S0";
209    case trunks::TPM_RC_REFERENCE_S1:
210      return "TPM_RC_REFERENCE_S1";
211    case trunks::TPM_RC_REFERENCE_S2:
212      return "TPM_RC_REFERENCE_S2";
213    case trunks::TPM_RC_REFERENCE_S3:
214      return "TPM_RC_REFERENCE_S3";
215    case trunks::TPM_RC_REFERENCE_S4:
216      return "TPM_RC_REFERENCE_S4";
217    case trunks::TPM_RC_REFERENCE_S5:
218      return "TPM_RC_REFERENCE_S5";
219    case trunks::TPM_RC_REFERENCE_S6:
220      return "TPM_RC_REFERENCE_S6";
221    case trunks::TPM_RC_NV_RATE:
222      return "TPM_RC_NV_RATE";
223    case trunks::TPM_RC_LOCKOUT:
224      return "TPM_RC_LOCKOUT";
225    case trunks::TPM_RC_RETRY:
226      return "TPM_RC_RETRY";
227    case trunks::TPM_RC_NV_UNAVAILABLE:
228      return "TPM_RC_NV_UNAVAILABLE";
229    case trunks::TPM_RC_NOT_USED:
230      return "TPM_RC_NOT_USED";
231    case trunks::TRUNKS_RC_AUTHORIZATION_FAILED:
232      return "TRUNKS_RC_AUTHORIZATION_FAILED";
233    case trunks::TRUNKS_RC_ENCRYPTION_FAILED:
234      return "TRUNKS_RC_ENCRYPTION_FAILED";
235    case trunks::TRUNKS_RC_READ_ERROR:
236      return "TRUNKS_RC_READ_ERROR";
237    case trunks::TRUNKS_RC_WRITE_ERROR:
238      return "TRUNKS_RC_WRITE_ERROR";
239    case trunks::TRUNKS_RC_IPC_ERROR:
240      return "TRUNKS_RC_IPC_ERROR";
241    case trunks::TRUNKS_RC_SESSION_SETUP_ERROR:
242      return "TRUNKS_RC_SESSION_SETUP_ERROR";
243    case trunks::TCTI_RC_TRY_AGAIN:
244      return "TCTI_RC_TRY_AGAIN";
245    case trunks::TCTI_RC_GENERAL_FAILURE:
246      return "TCTI_RC_GENERAL_FAILURE";
247    case trunks::TCTI_RC_BAD_CONTEXT:
248      return "TCTI_RC_BAD_CONTEXT";
249    case trunks::TCTI_RC_WRONG_ABI_VERSION:
250      return "TCTI_RC_WRONG_ABI_VERSION";
251    case trunks::TCTI_RC_NOT_IMPLEMENTED:
252      return "TCTI_RC_NOT_IMPLEMENTED";
253    case trunks::TCTI_RC_BAD_PARAMETER:
254      return "TCTI_RC_BAD_PARAMETER";
255    case trunks::TCTI_RC_INSUFFICIENT_BUFFER:
256      return "TCTI_RC_INSUFFICIENT_BUFFER";
257    case trunks::TCTI_RC_NO_CONNECTION:
258      return "TCTI_RC_NO_CONNECTION";
259    case trunks::TCTI_RC_DRIVER_NOT_FOUND:
260      return "TCTI_RC_DRIVER_NOT_FOUND";
261    case trunks::TCTI_RC_DRIVERINFO_NOT_FOUND:
262      return "TCTI_RC_DRIVERINFO_NOT_FOUND";
263    case trunks::TCTI_RC_NO_RESPONSE:
264      return "TCTI_RC_NO_RESPONSE";
265    case trunks::TCTI_RC_BAD_VALUE:
266      return "TCTI_RC_BAD_VALUE";
267    case trunks::SAPI_RC_INVALID_SESSIONS:
268      return "SAPI_RC_INVALID_SESSIONS";
269    case trunks::SAPI_RC_ABI_MISMATCH:
270      return "SAPI_RC_ABI_MISMATCH";
271    case trunks::SAPI_RC_INSUFFICIENT_BUFFER:
272      return "SAPI_RC_INSUFFICIENT_BUFFER";
273    case trunks::SAPI_RC_BAD_PARAMETER:
274      return "SAPI_RC_BAD_PARAMETER";
275    case trunks::SAPI_RC_BAD_SEQUENCE:
276      return "SAPI_RC_BAD_SEQUENCE";
277    case trunks::SAPI_RC_NO_DECRYPT_PARAM:
278      return "SAPI_RC_NO_DECRYPT_PARAM";
279    case trunks::SAPI_RC_NO_ENCRYPT_PARAM:
280      return "SAPI_RC_NO_ENCRYPT_PARAM";
281    case trunks::SAPI_RC_NO_RESPONSE_RECEIVED:
282      return "SAPI_RC_NO_RESPONSE_RECEIVED";
283    case trunks::SAPI_RC_BAD_SIZE:
284      return "SAPI_RC_BAD_SIZE";
285    case trunks::SAPI_RC_CORRUPTED_DATA:
286      return "SAPI_RC_CORRUPTED_DATA";
287    case trunks::SAPI_RC_INSUFFICIENT_CONTEXT:
288      return "SAPI_RC_INSUFFICIENT_CONTEXT";
289    case trunks::SAPI_RC_INSUFFICIENT_RESPONSE:
290      return "SAPI_RC_INSUFFICIENT_RESPONSE";
291    case trunks::SAPI_RC_INCOMPATIBLE_TCTI:
292      return "SAPI_RC_INCOMPATIBLE_TCTI";
293    case trunks::SAPI_RC_MALFORMED_RESPONSE:
294      return "SAPI_RC_MALFORMED_RESPONSE";
295    case trunks::SAPI_RC_BAD_TCTI_STRUCTURE:
296      return "SAPI_RC_BAD_TCTI_STRUCTURE";
297    default:
298      return std::string();
299  }
300  NOTREACHED();
301  return std::string();
302}
303
304bool IsFormatOne(trunks::TPM_RC error) {
305  return (error & kLayerMask) == 0 && (error & trunks::RC_FMT1) != 0;
306}
307
308}  // namespace
309
310namespace trunks {
311
312std::string GetErrorString(TPM_RC error) {
313  std::string error_string = GetErrorStringInternal(error);
314  if (!error_string.empty()) {
315    return error_string;
316  }
317  std::stringstream ss;
318  if ((error & kLayerMask) == kResourceManagerTpmErrorBase) {
319    error &= ~kLayerMask;
320    error_string = GetErrorStringInternal(error);
321    ss << "Resource Manager: ";
322  }
323  // Check if we have a TPM 'Format-One' response code.
324  if (IsFormatOne(error)) {
325    if (error & TPM_RC_P) {
326      ss << "Parameter ";
327    } else if (error & TPM_RC_S) {
328      ss << "Session ";
329    } else {
330      ss << "Handle ";
331    }
332    // Bits 8-10 specify which handle / parameter / session.
333    ss << ((error & kFormatOneSubjectMask) >> 8) << ": ";
334    // Mask out everything but the format bit and error number.
335    error_string = GetErrorStringInternal(error & kFormatOneErrorMask);
336    if (!error_string.empty()) {
337      ss << error_string;
338    }
339  }
340  if (error_string.empty()) {
341    ss << "Unknown error: " << error << " (0x" << std::hex << error << ")";
342  }
343  return ss.str();
344}
345
346TPM_RC GetFormatOneError(TPM_RC error) {
347  if (IsFormatOne(error)) {
348    return (error & kFormatOneErrorMask);
349  }
350  return error;
351}
352
353std::string CreateErrorResponse(TPM_RC error_code) {
354  const uint32_t kErrorResponseSize = 10;
355  std::string response;
356  CHECK_EQ(Serialize_TPM_ST(TPM_ST_NO_SESSIONS, &response), TPM_RC_SUCCESS);
357  CHECK_EQ(Serialize_UINT32(kErrorResponseSize, &response), TPM_RC_SUCCESS);
358  CHECK_EQ(Serialize_TPM_RC(error_code, &response), TPM_RC_SUCCESS);
359  return response;
360}
361
362}  // namespace trunks
363