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.
GetErrorStringInternal(trunks::TPM_RC error)33 std::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 
IsFormatOne(trunks::TPM_RC error)304 bool IsFormatOne(trunks::TPM_RC error) {
305   return (error & kLayerMask) == 0 && (error & trunks::RC_FMT1) != 0;
306 }
307 
308 }  // namespace
309 
310 namespace trunks {
311 
GetErrorString(TPM_RC error)312 std::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 
GetFormatOneError(TPM_RC error)346 TPM_RC GetFormatOneError(TPM_RC error) {
347   if (IsFormatOne(error)) {
348     return (error & kFormatOneErrorMask);
349   }
350   return error;
351 }
352 
CreateErrorResponse(TPM_RC error_code)353 std::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