1 #include <stdint.h>
2 #include <stdbool.h>
3 #include <stdio.h>
4 #include <time.h>
5 #include "StmUtil.h"
6 #include <wolfssl/wolfcrypt/sha512.h>
7 #undef INLINE
8 #include "Tpm.h"
9 #include "TpmDevice.h"
10
11 volatile tpmOperation_t tpmOp = { 0 };
12 extern char tpmUnique[WC_SHA512_DIGEST_SIZE];
13
14 uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len);
15
16 #ifndef NDEBUG
17 #define TPM_RC_MAX_FM1 (TPM_RC)(RC_FMT1 + 0x03F)
18
19 typedef struct
20 {
21 uint32_t index;
22 char* str;
23 } lookup_t;
24
25 const lookup_t tpm_cc_table[] =
26 {
27 #if CC_NV_UndefineSpaceSpecial == YES
28 {TPM_CC_NV_UndefineSpaceSpecial, "TPM_CC_NV_UndefineSpaceSpecial"},
29 #endif
30 #if CC_EvictControl == YES
31 {TPM_CC_EvictControl, "TPM_CC_EvictControl"},
32 #endif
33 #if CC_HierarchyControl == YES
34 {TPM_CC_HierarchyControl, "TPM_CC_HierarchyControl"},
35 #endif
36 #if CC_NV_UndefineSpace == YES
37 {TPM_CC_NV_UndefineSpace, "TPM_CC_NV_UndefineSpace"},
38 #endif
39 #if CC_ChangeEPS == YES
40 {TPM_CC_ChangeEPS, "TPM_CC_ChangeEPS"},
41 #endif
42 #if CC_ChangePPS == YES
43 {TPM_CC_ChangePPS, "TPM_CC_ChangePPS"},
44 #endif
45 #if CC_Clear == YES
46 {TPM_CC_Clear, "TPM_CC_Clear"},
47 #endif
48 #if CC_ClearControl == YES
49 {TPM_CC_ClearControl, "TPM_CC_ClearControl"},
50 #endif
51 #if CC_ClockSet == YES
52 {TPM_CC_ClockSet, "TPM_CC_ClockSet"},
53 #endif
54 #if CC_HierarchyChangeAuth == YES
55 {TPM_CC_HierarchyChangeAuth, "TPM_CC_HierarchyChangeAuth"},
56 #endif
57 #if CC_NV_DefineSpace == YES
58 {TPM_CC_NV_DefineSpace, "TPM_CC_NV_DefineSpace"},
59 #endif
60 #if CC_PCR_Allocate == YES
61 {TPM_CC_PCR_Allocate, "TPM_CC_PCR_Allocate"},
62 #endif
63 #if CC_PCR_SetAuthPolicy == YES
64 {TPM_CC_PCR_SetAuthPolicy, "TPM_CC_PCR_SetAuthPolicy"},
65 #endif
66 #if CC_PP_Commands == YES
67 {TPM_CC_PP_Commands, "TPM_CC_PP_Commands"},
68 #endif
69 #if CC_SetPrimaryPolicy == YES
70 {TPM_CC_SetPrimaryPolicy, "TPM_CC_SetPrimaryPolicy"},
71 #endif
72 #if CC_FieldUpgradeStart == YES
73 {TPM_CC_FieldUpgradeStart, "TPM_CC_FieldUpgradeStart"},
74 #endif
75 #if CC_ClockRateAdjust == YES
76 {TPM_CC_ClockRateAdjust, "TPM_CC_ClockRateAdjust"},
77 #endif
78 #if CC_CreatePrimary == YES
79 {TPM_CC_CreatePrimary, "TPM_CC_CreatePrimary"},
80 #endif
81 #if CC_NV_GlobalWriteLock == YES
82 {TPM_CC_NV_GlobalWriteLock, "TPM_CC_NV_GlobalWriteLock"},
83 #endif
84 #if CC_GetCommandAuditDigest == YES
85 {TPM_CC_GetCommandAuditDigest, ""},
86 #endif
87 #if CC_NV_Increment == YES
88 {TPM_CC_NV_Increment, "TPM_CC_NV_Increment"},
89 #endif
90 #if CC_NV_SetBits == YES
91 {TPM_CC_NV_SetBits, "TPM_CC_NV_SetBits"},
92 #endif
93 #if CC_NV_Extend == YES
94 {TPM_CC_NV_Extend, "TPM_CC_NV_Extend"},
95 #endif
96 #if CC_NV_Write == YES
97 {TPM_CC_NV_Write, "TPM_CC_NV_Write"},
98 #endif
99 #if CC_NV_WriteLock == YES
100 {TPM_CC_NV_WriteLock, "TPM_CC_NV_WriteLock"},
101 #endif
102 #if CC_DictionaryAttackLockReset == YES
103 {TPM_CC_DictionaryAttackLockReset, "TPM_CC_DictionaryAttackLockReset"},
104 #endif
105 #if CC_DictionaryAttackParameters == YES
106 {TPM_CC_DictionaryAttackParameters, "TPM_CC_DictionaryAttackParameters"},
107 #endif
108 #if CC_NV_ChangeAuth == YES
109 {TPM_CC_NV_ChangeAuth, "TPM_CC_NV_ChangeAuth"},
110 #endif
111 #if CC_PCR_Event == YES
112 {TPM_CC_PCR_Event, "TPM_CC_PCR_Event"},
113 #endif
114 #if CC_PCR_Reset == YES
115 {TPM_CC_PCR_Reset, "TPM_CC_PCR_Reset"},
116 #endif
117 #if CC_SequenceComplete == YES
118 {TPM_CC_SequenceComplete, "TPM_CC_SequenceComplete"},
119 #endif
120 #if CC_SetAlgorithmSet == YES
121 {TPM_CC_SetAlgorithmSet, "TPM_CC_SetAlgorithmSet"},
122 #endif
123 #if CC_SetCommandCodeAuditStatus == YES
124 {TPM_CC_SetCommandCodeAuditStatus, "TPM_CC_SetCommandCodeAuditStatus"},
125 #endif
126 #if CC_FieldUpgradeData == YES
127 {TPM_CC_FieldUpgradeData, "TPM_CC_FieldUpgradeData"},
128 #endif
129 #if CC_IncrementalSelfTest == YES
130 {TPM_CC_IncrementalSelfTest, "TPM_CC_FieldUpgradeData"},
131 #endif
132 #if CC_SelfTest == YES
133 {TPM_CC_SelfTest, "TPM_CC_SelfTest"},
134 #endif
135 #if CC_Startup == YES
136 {TPM_CC_Startup, "TPM_CC_Startup"},
137 #endif
138 #if CC_Shutdown == YES
139 {TPM_CC_Shutdown, "TPM_CC_Shutdown"},
140 #endif
141 #if CC_StirRandom == YES
142 {TPM_CC_StirRandom, ""},
143 #endif
144 #if CC_ActivateCredential == YES
145 {TPM_CC_ActivateCredential, "TPM_CC_ActivateCredential"},
146 #endif
147 #if CC_Certify == YES
148 {TPM_CC_Certify, "TPM_CC_Certify"},
149 #endif
150 #if CC_PolicyNV == YES
151 {TPM_CC_PolicyNV, "TPM_CC_PolicyNV"},
152 #endif
153 #if CC_CertifyCreation == YES
154 {TPM_CC_CertifyCreation, "TPM_CC_CertifyCreation"},
155 #endif
156 #if CC_Duplicate == YES
157 {TPM_CC_Duplicate, "TPM_CC_Duplicate"},
158 #endif
159 #if CC_GetTime == YES
160 {TPM_CC_GetTime, "TPM_CC_GetTime"},
161 #endif
162 #if CC_GetSessionAuditDigest == YES
163 {TPM_CC_GetSessionAuditDigest, "TPM_CC_GetSessionAuditDigest"},
164 #endif
165 #if CC_NV_Read == YES
166 {TPM_CC_NV_Read, "TPM_CC_NV_Read"},
167 #endif
168 #if CC_NV_ReadLock == YES
169 {TPM_CC_NV_ReadLock, "TPM_CC_NV_ReadLock"},
170 #endif
171 #if CC_ObjectChangeAuth == YES
172 {TPM_CC_ObjectChangeAuth, "TPM_CC_ObjectChangeAuth"},
173 #endif
174 #if CC_PolicySecret == YES
175 {TPM_CC_PolicySecret, "TPM_CC_PolicySecret"},
176 #endif
177 #if CC_Rewrap == YES
178 {TPM_CC_Rewrap, "TPM_CC_Rewrap"},
179 #endif
180 #if CC_Create == YES
181 {TPM_CC_Create, "TPM_CC_Create"},
182 #endif
183 #if CC_ECDH_ZGen == YES
184 {TPM_CC_ECDH_ZGen, "TPM_CC_ECDH_ZGen"},
185 #endif
186 #if CC_HMAC == YES
187 {TPM_CC_HMAC, "TPM_CC_HMAC"},
188 #endif
189 #if CC_MAC == YES
190 {TPM_CC_MAC, "TPM_CC_HMAC"},
191 #endif
192 #if CC_Import == YES
193 {TPM_CC_Import, "TPM_CC_Import"},
194 #endif
195 #if CC_Load == YES
196 {TPM_CC_Load, "TPM_CC_Load"},
197 #endif
198 #if CC_Quote == YES
199 {TPM_CC_Quote, "TPM_CC_Quote"},
200 #endif
201 #if CC_RSA_Decrypt == YES
202 {TPM_CC_RSA_Decrypt, "TPM_CC_RSA_Decrypt"},
203 #endif
204 #if CC_HMAC_Start == YES
205 {TPM_CC_HMAC_Start, "TPM_CC_HMAC_Start"},
206 #endif
207 #if CC_MAC_Start == YES
208 {TPM_CC_MAC_Start, "TPM_CC_HMAC_Start"},
209 #endif
210 #if CC_SequenceUpdate == YES
211 {TPM_CC_SequenceUpdate, "TPM_CC_SequenceUpdate"},
212 #endif
213 #if CC_Sign == YES
214 {TPM_CC_Sign, "TPM_CC_Sign"},
215 #endif
216 #if CC_Unseal == YES
217 {TPM_CC_Unseal, "TPM_CC_Sign"},
218 #endif
219 #if CC_PolicySigned == YES
220 {TPM_CC_PolicySigned, "TPM_CC_PolicySigned"},
221 #endif
222 #if CC_ContextLoad == YES
223 {TPM_CC_ContextLoad, "TPM_CC_ContextLoad"},
224 #endif
225 #if CC_ContextSave == YES
226 {TPM_CC_ContextSave, "TPM_CC_ContextSave"},
227 #endif
228 #if CC_ECDH_KeyGen == YES
229 {TPM_CC_ECDH_KeyGen, "TPM_CC_ECDH_KeyGen"},
230 #endif
231 #if CC_EncryptDecrypt == YES
232 {TPM_CC_EncryptDecrypt, "TPM_CC_EncryptDecrypt"},
233 #endif
234 #if CC_FlushContext == YES
235 {TPM_CC_FlushContext, "TPM_CC_FlushContext"},
236 #endif
237 #if CC_LoadExternal == YES
238 {TPM_CC_LoadExternal, ""},
239 #endif
240 #if CC_MakeCredential == YES
241 {TPM_CC_MakeCredential, "TPM_CC_MakeCredential"},
242 #endif
243 #if CC_NV_ReadPublic == YES
244 {TPM_CC_NV_ReadPublic, "TPM_CC_NV_ReadPublic"},
245 #endif
246 #if CC_PolicyAuthorize == YES
247 {TPM_CC_PolicyAuthorize, "TPM_CC_PolicyAuthorize"},
248 #endif
249 #if CC_PolicyAuthValue == YES
250 {TPM_CC_PolicyAuthValue, "TPM_CC_PolicyAuthValue"},
251 #endif
252 #if CC_PolicyCommandCode == YES
253 {TPM_CC_PolicyCommandCode, "TPM_CC_PolicyCommandCode"},
254 #endif
255 #if CC_PolicyCounterTimer == YES
256 {TPM_CC_PolicyCounterTimer, "TPM_CC_PolicyCounterTimer"},
257 #endif
258 #if CC_PolicyCpHash == YES
259 {TPM_CC_PolicyCpHash, "TPM_CC_PolicyCounterTimer"},
260 #endif
261 #if CC_PolicyLocality == YES
262 {TPM_CC_PolicyLocality, "TPM_CC_PolicyLocality"},
263 #endif
264 #if CC_PolicyNameHash == YES
265 {TPM_CC_PolicyNameHash, "TPM_CC_PolicyNameHash"},
266 #endif
267 #if CC_PolicyOR == YES
268 {TPM_CC_PolicyOR, "TPM_CC_PolicyOR"},
269 #endif
270 #if CC_PolicyTicket == YES
271 {TPM_CC_PolicyTicket, "TPM_CC_PolicyTicket"},
272 #endif
273 #if CC_ReadPublic == YES
274 {TPM_CC_ReadPublic, "TPM_CC_ReadPublic"},
275 #endif
276 #if CC_RSA_Encrypt == YES
277 {TPM_CC_RSA_Encrypt, "TPM_CC_RSA_Encrypt"},
278 #endif
279 #if CC_StartAuthSession == YES
280 {TPM_CC_StartAuthSession, "TPM_CC_StartAuthSession"},
281 #endif
282 #if CC_VerifySignature == YES
283 {TPM_CC_VerifySignature, "TPM_CC_VerifySignature"},
284 #endif
285 #if CC_ECC_Parameters == YES
286 {TPM_CC_ECC_Parameters, "TPM_CC_VerifySignature"},
287 #endif
288 #if CC_FirmwareRead == YES
289 {TPM_CC_FirmwareRead, "TPM_CC_FirmwareRead"},
290 #endif
291 #if CC_GetCapability == YES
292 {TPM_CC_GetCapability, "TPM_CC_GetCapability"},
293 #endif
294 #if CC_GetRandom == YES
295 {TPM_CC_GetRandom, "TPM_CC_GetRandom"},
296 #endif
297 #if CC_GetTestResult == YES
298 {TPM_CC_GetTestResult, "TPM_CC_GetTestResult"},
299 #endif
300 #if CC_Hash == YES
301 {TPM_CC_Hash, "TPM_CC_Hash"},
302 #endif
303 #if CC_PCR_Read == YES
304 {TPM_CC_PCR_Read, "TPM_CC_Hash"},
305 #endif
306 #if CC_PolicyPCR == YES
307 {TPM_CC_PolicyPCR, "TPM_CC_PolicyPCR"},
308 #endif
309 #if CC_PolicyRestart == YES
310 {TPM_CC_PolicyRestart, "TPM_CC_PolicyRestart"},
311 #endif
312 #if CC_ReadClock == YES
313 {TPM_CC_ReadClock, "TPM_CC_ReadClock"},
314 #endif
315 #if CC_PCR_Extend == YES
316 {TPM_CC_PCR_Extend, "TPM_CC_PCR_Extend"},
317 #endif
318 #if CC_PCR_SetAuthValue == YES
319 {TPM_CC_PCR_SetAuthValue, "TPM_CC_PCR_SetAuthValue"},
320 #endif
321 #if CC_NV_Certify == YES
322 {TPM_CC_NV_Certify, "TPM_CC_NV_Certify"},
323 #endif
324 #if CC_EventSequenceComplete == YES
325 {TPM_CC_EventSequenceComplete, "TPM_CC_EventSequenceComplete"},
326 #endif
327 #if CC_HashSequenceStart == YES
328 {TPM_CC_HashSequenceStart, "TPM_CC_EventSequenceComplete"},
329 #endif
330 #if CC_PolicyPhysicalPresence == YES
331 {TPM_CC_PolicyPhysicalPresence, ""},
332 #endif
333 #if CC_PolicyDuplicationSelect == YES
334 {TPM_CC_PolicyDuplicationSelect, "TPM_CC_PolicyDuplicationSelect"},
335 #endif
336 #if CC_PolicyGetDigest == YES
337 {TPM_CC_PolicyGetDigest, "TPM_CC_PolicyGetDigest"},
338 #endif
339 #if CC_TestParms == YES
340 {TPM_CC_TestParms, "TPM_CC_TestParms"},
341 #endif
342 #if CC_Commit == YES
343 {TPM_CC_Commit, "TPM_CC_Commit"},
344 #endif
345 #if CC_PolicyPassword == YES
346 {TPM_CC_PolicyPassword, "TPM_CC_PolicyPassword"},
347 #endif
348 #if CC_ZGen_2Phase == YES
349 {TPM_CC_ZGen_2Phase, "TPM_CC_ZGen_2Phase"},
350 #endif
351 #if CC_EC_Ephemeral == YES
352 {TPM_CC_EC_Ephemeral, "TPM_CC_EC_Ephemeral"},
353 #endif
354 #if CC_PolicyNvWritten == YES
355 {TPM_CC_PolicyNvWritten, "TPM_CC_PolicyNvWritten"},
356 #endif
357 #if CC_PolicyTemplate == YES
358 {TPM_CC_PolicyTemplate, "TPM_CC_PolicyTemplate"},
359 #endif
360 #if CC_CreateLoaded == YES
361 {TPM_CC_CreateLoaded, ""},
362 #endif
363 #if CC_PolicyAuthorizeNV == YES
364 {TPM_CC_PolicyAuthorizeNV, "TPM_CC_PolicyAuthorizeNV"},
365 #endif
366 #if CC_EncryptDecrypt2 == YES
367 {TPM_CC_EncryptDecrypt2, "TPM_CC_EncryptDecrypt2"},
368 #endif
369 #if CC_AC_GetCapability == YES
370 {TPM_CC_AC_GetCapability, "TPM_CC_AC_GetCapability"},
371 #endif
372 #if CC_AC_Send == YES
373 {TPM_CC_AC_Send, "TPM_CC_AC_Send"},
374 #endif
375 #if CC_Policy_AC_SendSelect == YES
376 {TPM_CC_Policy_AC_SendSelect, "TPM_CC_Policy_AC_SendSelect"},
377 #endif
378 {(uint32_t)-1, NULL}
379 };
380
381 const lookup_t tpm_rc_globalCodes[] = {
382 {TPM_RC_SUCCESS, "TPM_RC_SUCCESS"},
383 {TPM_RC_BAD_TAG, "TPM_RC_BAD_TAG"},
384 {(uint32_t)-1, NULL}
385 };
386
387 const lookup_t tpm_rc_formatZeroCodes[] = {
388 {TPM_RC_INITIALIZE, "TPM_RC_INITIALIZE"},
389 {TPM_RC_FAILURE, "TPM_RC_FAILURE"},
390 {TPM_RC_SEQUENCE, "TPM_RC_SEQUENCE"},
391 {TPM_RC_PRIVATE, "TPM_RC_PRIVATE"},
392 {TPM_RC_HMAC, "TPM_RC_HMAC"},
393 {TPM_RC_DISABLED, "TPM_RC_DISABLED"},
394 {TPM_RC_EXCLUSIVE, "TPM_RC_EXCLUSIVE"},
395 {TPM_RC_AUTH_TYPE, "TPM_RC_AUTH_TYPE"},
396 {TPM_RC_AUTH_MISSING, "TPM_RC_AUTH_MISSING"},
397 {TPM_RC_POLICY, "TPM_RC_POLICY"},
398 {TPM_RC_PCR, "TPM_RC_PCR"},
399 {TPM_RC_PCR_CHANGED, "TPM_RC_PCR_CHANGED"},
400 {TPM_RC_UPGRADE, "TPM_RC_UPGRADE"},
401 {TPM_RC_TOO_MANY_CONTEXTS, "TPM_RC_TOO_MANY_CONTEXTS"},
402 {TPM_RC_AUTH_UNAVAILABLE, "TPM_RC_AUTH_UNAVAILABLE"},
403 {TPM_RC_REBOOT, "TPM_RC_REBOOT"},
404 {TPM_RC_UNBALANCED, "TPM_RC_UNBALANCED"},
405 {TPM_RC_COMMAND_SIZE, "TPM_RC_COMMAND_SIZE"},
406 {TPM_RC_COMMAND_CODE, "TPM_RC_COMMAND_CODE"},
407 {TPM_RC_AUTHSIZE, "TPM_RC_AUTHSIZE"},
408 {TPM_RC_AUTH_CONTEXT, "TPM_RC_AUTH_CONTEXT"},
409 {TPM_RC_NV_RANGE, "TPM_RC_NV_RANGE"},
410 {TPM_RC_NV_SIZE, "TPM_RC_NV_SIZE"},
411 {TPM_RC_NV_LOCKED, "TPM_RC_NV_LOCKED"},
412 {TPM_RC_NV_AUTHORIZATION, "TPM_RC_NV_AUTHORIZATION"},
413 {TPM_RC_NV_UNINITIALIZED, "TPM_RC_NV_UNINITIALIZED"},
414 {TPM_RC_NV_SPACE, "TPM_RC_NV_SPACE"},
415 {TPM_RC_NV_DEFINED, "TPM_RC_NV_DEFINED"},
416 {TPM_RC_BAD_CONTEXT, "TPM_RC_BAD_CONTEXT"},
417 {TPM_RC_CPHASH, "TPM_RC_CPHASH"},
418 {TPM_RC_PARENT, "TPM_RC_PARENT"},
419 {TPM_RC_NEEDS_TEST, "TPM_RC_NEEDS_TEST"},
420 {TPM_RC_NO_RESULT, "TPM_RC_NO_RESULT"},
421 {TPM_RC_SENSITIVE, "TPM_RC_SENSITIVE"},
422 {(uint32_t)-1, NULL}
423 };
424
425 const lookup_t tpm_rc_warningCodes[] = {
426 {TPM_RC_CONTEXT_GAP, "TPM_RC_CONTEXT_GAP"},
427 {TPM_RC_CONTEXT_GAP, "TPM_RC_CONTEXT_GAP"},
428 {TPM_RC_OBJECT_MEMORY, "TPM_RC_OBJECT_MEMORY"},
429 {TPM_RC_SESSION_MEMORY, "TPM_RC_SESSION_MEMORY"},
430 {TPM_RC_MEMORY, "TPM_RC_MEMORY"},
431 {TPM_RC_SESSION_HANDLES, "TPM_RC_SESSION_HANDLES"},
432 {TPM_RC_OBJECT_HANDLES, "TPM_RC_OBJECT_HANDLES"},
433 {TPM_RC_LOCALITY, "TPM_RC_LOCALITY"},
434 {TPM_RC_YIELDED, "TPM_RC_YIELDED"},
435 {TPM_RC_CANCELED, "TPM_RC_CANCELED"},
436 {TPM_RC_TESTING, "TPM_RC_TESTING"},
437 {TPM_RC_REFERENCE_H0, "TPM_RC_REFERENCE_H0"},
438 {TPM_RC_REFERENCE_H1, "TPM_RC_REFERENCE_H1"},
439 {TPM_RC_REFERENCE_H2, "TPM_RC_REFERENCE_H2"},
440 {TPM_RC_REFERENCE_H3, "TPM_RC_REFERENCE_H3"},
441 {TPM_RC_REFERENCE_H4, "TPM_RC_REFERENCE_H4"},
442 {TPM_RC_REFERENCE_H5, "TPM_RC_REFERENCE_H5"},
443 {TPM_RC_REFERENCE_H6, "TPM_RC_REFERENCE_H6"},
444 {TPM_RC_REFERENCE_S0, "TPM_RC_REFERENCE_S0"},
445 {TPM_RC_REFERENCE_S1, "TPM_RC_REFERENCE_S1"},
446 {TPM_RC_REFERENCE_S2, "TPM_RC_REFERENCE_S2"},
447 {TPM_RC_REFERENCE_S3, "TPM_RC_REFERENCE_S3"},
448 {TPM_RC_REFERENCE_S4, "TPM_RC_REFERENCE_S4"},
449 {TPM_RC_REFERENCE_S5, "TPM_RC_REFERENCE_S5"},
450 {TPM_RC_REFERENCE_S6, "TPM_RC_REFERENCE_S6"},
451 {TPM_RC_NV_RATE, "TPM_RC_NV_RATE"},
452 {TPM_RC_LOCKOUT, "TPM_RC_LOCKOUT"},
453 {TPM_RC_RETRY, "TPM_RC_RETRY"},
454 {TPM_RC_NV_UNAVAILABLE, "TPM_RC_NV_UNAVAILABLE"},
455 {(uint32_t)-1, NULL}
456 };
457
458 const lookup_t tpm_rc_formatCodes[] = {
459 {TPM_RCS_ASYMMETRIC, "TPM_RCS_ASYMMETRIC"},
460 {TPM_RC_ATTRIBUTES, "TPM_RC_ATTRIBUTES"},
461 {TPM_RCS_ATTRIBUTES, "TPM_RCS_ATTRIBUTES"},
462 {TPM_RC_HASH, "TPM_RC_HASH"},
463 {TPM_RCS_HASH, "TPM_RCS_HASH"},
464 {TPM_RC_VALUE, "TPM_RC_VALUE"},
465 {TPM_RCS_VALUE, "TPM_RCS_VALUE"},
466 {TPM_RC_HIERARCHY, "TPM_RC_HIERARCHY"},
467 {TPM_RCS_HIERARCHY, "TPM_RCS_HIERARCHY"},
468 {TPM_RC_KEY_SIZE, "TPM_RC_KEY_SIZE"},
469 {TPM_RCS_KEY_SIZE, "TPM_RCS_KEY_SIZE"},
470 {TPM_RC_MGF, "TPM_RC_MGF"},
471 {TPM_RCS_MGF, "TPM_RCS_MGF"},
472 {TPM_RC_MODE, "TPM_RC_MODE"},
473 {TPM_RCS_MODE, "TPM_RCS_MODE"},
474 {TPM_RC_TYPE, "TPM_RC_TYPE"},
475 {TPM_RCS_TYPE, "TPM_RCS_TYPE"},
476 {TPM_RC_HANDLE, "TPM_RC_HANDLE"},
477 {TPM_RCS_HANDLE, "TPM_RCS_HANDLE"},
478 {TPM_RC_KDF, "TPM_RC_KDF"},
479 {TPM_RCS_KDF, "TPM_RCS_KDF"},
480 {TPM_RC_RANGE, "TPM_RC_RANGE"},
481 {TPM_RCS_RANGE, "TPM_RCS_RANGE"},
482 {TPM_RC_AUTH_FAIL, "TPM_RC_AUTH_FAIL"},
483 {TPM_RCS_AUTH_FAIL, "TPM_RCS_AUTH_FAIL"},
484 {TPM_RC_NONCE, "TPM_RC_NONCE"},
485 {TPM_RCS_NONCE, "TPM_RCS_NONCE"},
486 {TPM_RC_PP, "TPM_RC_PP"},
487 {TPM_RCS_PP, "TPM_RCS_PP"},
488 {TPM_RC_SCHEME, "TPM_RC_SCHEME"},
489 {TPM_RCS_SCHEME, "TPM_RCS_SCHEME"},
490 {TPM_RC_SIZE, "TPM_RC_SIZE"},
491 {TPM_RCS_SIZE, "TPM_RCS_SIZE"},
492 {TPM_RC_SYMMETRIC, "TPM_RC_SYMMETRIC"},
493 {TPM_RCS_SYMMETRIC, "TPM_RCS_SYMMETRIC"},
494 {TPM_RC_TAG, "TPM_RC_TAG"},
495 {TPM_RCS_TAG, "TPM_RCS_TAG"},
496 {TPM_RC_SELECTOR, "TPM_RC_SELECTOR"},
497 {TPM_RCS_SELECTOR, "TPM_RCS_SELECTOR"},
498 {TPM_RC_INSUFFICIENT, "TPM_RC_INSUFFICIENT"},
499 {TPM_RCS_INSUFFICIENT, "TPM_RCS_INSUFFICIENT"},
500 {TPM_RC_SIGNATURE, "TPM_RC_SIGNATURE"},
501 {TPM_RCS_SIGNATURE, "TPM_RCS_SIGNATURE"},
502 {TPM_RC_KEY, "TPM_RC_KEY"},
503 {TPM_RCS_KEY, "TPM_RCS_KEY"},
504 {TPM_RC_POLICY_FAIL, "TPM_RC_POLICY_FAIL"},
505 {TPM_RCS_POLICY_FAIL, "TPM_RCS_POLICY_FAIL"},
506 {TPM_RC_INTEGRITY, "TPM_RC_INTEGRITY"},
507 {TPM_RCS_INTEGRITY, "TPM_RCS_INTEGRITY"},
508 {TPM_RC_TICKET, "TPM_RC_TICKET"},
509 {TPM_RCS_TICKET, "TPM_RCS_TICKET"},
510 {TPM_RC_RESERVED_BITS, "TPM_RC_RESERVED_BITS"},
511 {TPM_RCS_RESERVED_BITS, "TPM_RCS_RESERVED_BITS"},
512 {TPM_RC_BAD_AUTH, "TPM_RC_BAD_AUTH"},
513 {TPM_RCS_BAD_AUTH, "TPM_RCS_BAD_AUTH"},
514 {TPM_RC_EXPIRED, "TPM_RC_EXPIRED"},
515 {TPM_RCS_EXPIRED, "TPM_RCS_EXPIRED"},
516 {TPM_RC_POLICY_CC, "TPM_RC_POLICY_CC"},
517 {TPM_RCS_POLICY_CC, "TPM_RCS_POLICY_CC"},
518 {TPM_RC_BINDING, "TPM_RC_BINDING"},
519 {TPM_RCS_BINDING, "TPM_RCS_BINDING"},
520 {TPM_RC_CURVE, "TPM_RC_CURVE"},
521 {TPM_RCS_CURVE, "TPM_RCS_CURVE"},
522 {TPM_RC_ECC_POINT, "TPM_RC_ECC_POINT"},
523 {TPM_RCS_ECC_POINT, "TPM_RCS_ECC_POINT"},
524 {(uint32_t)-1, NULL}
525 };
526
527 char decodeBuf[100];
528 #else
529 char decodeBuf[6];
530 #endif
531
TpmDecodeTPM_CC(uint8_t * in)532 static char* TpmDecodeTPM_CC(uint8_t* in)
533 {
534 TPM_CC cc = BYTE_ARRAY_TO_UINT32(in);
535 #ifndef NDEBUG
536 uint32_t n;
537 for(n = 0; ((tpm_cc_table[n].index != (uint32_t)-1) && (tpm_cc_table[n].index != cc)) ; n++ );
538 if(tpm_cc_table[n].index != (uint32_t)-1)
539 {
540 sprintf(decodeBuf, "%s()", tpm_cc_table[n].str);
541 }
542 else
543 {
544 #endif
545 sprintf(decodeBuf, "0x%03x", (unsigned int)cc);
546 #ifndef NDEBUG
547 }
548 #endif
549 return decodeBuf;
550 }
551
TpmDecodeTPM_RC(uint8_t * in)552 static char* TpmDecodeTPM_RC(uint8_t* in)
553 {
554 TPM_RC rc = BYTE_ARRAY_TO_UINT32(in);
555 #ifndef NDEBUG
556 uint32_t n;
557 uint32_t cursor = 0;
558
559 for(n = 0; ((tpm_rc_globalCodes[n].index != (uint32_t)-1) && (tpm_rc_globalCodes[n].index != rc)) ; n++ );
560 if(tpm_rc_globalCodes[n].index != (uint32_t)-1)
561 {
562 cursor = sprintf(decodeBuf, "{%s}", tpm_rc_globalCodes[n].str);
563 }
564 else if((rc & RC_FMT1) == RC_FMT1)
565 {
566 if(rc & TPM_RC_P)
567 {
568 cursor = sprintf(decodeBuf, "{RC_FMT1 | TPM_RC_P | TPM_RC_%X | ", (unsigned int)((rc & 0x00000f00) >> 8));
569 }
570 else if(rc & TPM_RC_S)
571 {
572 cursor = sprintf(decodeBuf, "{RC_FMT1 | TPM_RC_S | TPM_RC_%X | ", (unsigned int)((rc & 0x00000700) >> 8));
573 }
574 else
575 {
576 cursor = sprintf(decodeBuf, "{RC_FMT1 | TPM_RC_H | TPM_RC_%X | ", (unsigned int)((rc & 0x00000700) >> 8));
577 }
578
579 for(n = 0; ((tpm_rc_formatCodes[n].index != (uint32_t)-1) && (tpm_rc_formatCodes[n].index != (rc & TPM_RC_MAX_FM1))) ; n++ );
580 if(tpm_rc_formatCodes[n].index != (uint32_t)-1)
581 {
582 cursor = sprintf(&decodeBuf[cursor], "%s}", tpm_rc_formatCodes[n].str);
583 }
584 else
585 {
586 cursor = 0;
587 }
588 }
589 else if((rc & RC_WARN) == RC_WARN)
590 {
591 for(n = 0; ((tpm_rc_warningCodes[n].index != (uint32_t)-1) && (tpm_rc_warningCodes[n].index != rc)) ; n++ );
592 if(tpm_rc_warningCodes[n].index != (uint32_t)-1)
593 {
594 cursor = sprintf(decodeBuf, "{RC_VER1 | RC_WARN | %s}", tpm_rc_warningCodes[n].str);
595 }
596 }
597 else if((rc & RC_VER1) == RC_VER1)
598 {
599 for(n = 0; ((tpm_rc_formatZeroCodes[n].index != (uint32_t)-1) && (tpm_rc_formatZeroCodes[n].index != rc)) ; n++ );
600 if(tpm_rc_formatZeroCodes[n].index != (uint32_t)-1)
601 {
602 cursor = sprintf(decodeBuf, "{RC_VER1 | %s}", tpm_rc_formatZeroCodes[n].str);
603 }
604 }
605
606 if(cursor == 0)
607 {
608 #endif
609 sprintf(decodeBuf, "0x%03x", (unsigned int)rc);
610 return decodeBuf;
611 #ifndef NDEBUG
612 }
613 #endif
614 return decodeBuf;
615 }
616
TpmGenerateUnique(void)617 static bool TpmGenerateUnique(void)
618 {
619 wc_Sha512 hash;
620 struct
621 {
622 uint16_t mcuType;
623 uint16_t mcuRev;
624 uint16_t flashSize;
625 unsigned char serial[12];
626 } mcuInfo;
627
628 ReadMcuInfo(mcuInfo.serial, &mcuInfo.flashSize, &mcuInfo.mcuType, &mcuInfo.mcuRev);
629
630 if((wc_InitSha512(&hash)) ||
631 (wc_Sha512Update(&hash, (const byte*)&mcuInfo, sizeof(mcuInfo))) ||
632 (wc_Sha512Final(&hash, (byte*)tpmUnique)))
633 {
634 logError("Sha512 failed\r\n");
635 return false;
636 }
637 wc_Sha512Free(&hash);
638
639 #ifndef NDEBUG
640 uint8_t unique[WC_SHA512_DIGEST_SIZE] = {0};
641 _plat__GetUnique(0, sizeof(unique), unique);
642 dbgPrint("Generated tpmUnique");
643 for(uint32_t n = 0; n < sizeof(unique); n++)
644 {
645 if(!(n % 16)) dbgPrintAppend("\r\n ");
646 dbgPrintAppend("%02x", ((unsigned int)(unique[n])));
647 }
648 dbgPrintAppend("\r\n");
649 #endif
650 return true;
651 }
652
TpmInitializeDevice(void)653 bool TpmInitializeDevice(void)
654 {
655 int retVal = 0;
656
657 tpmOp.receivingCmd = -1;
658 TpmGenerateUnique();
659
660 SetDutyCycleIndicator(FALSE);
661
662 // Factory reset requested?
663 if(BlueButtonTransitionDetected())
664 {
665 dbgPrint("Factory reset requested.\r\n");
666 if((retVal = _plat__NVEnable((void*)1)) < 0)
667 {
668 logError("_plat__NVEnable(1) failed unrecoverable.")
669 }
670 dbgPrint("Waiting for the button to be released...\r\n");
671 while(BlueButtonTransitionDetected() == 0);
672 }
673 else
674 {
675 if((retVal = _plat__NVEnable((void*)0)) < 0)
676 {
677 logError("_plat__NVEnable(0) failed unrecoverable.")
678 }
679 }
680
681
682 if(retVal > 0)
683 {
684 dbgPrint("TPM_Manufacture(1) requested.\r\n");
685 if((retVal = TPM_Manufacture(1)) != 0)
686 {
687 logError("TPM_Manufacture(1) failed.\r\n");
688 }
689 }
690
691 dbgPrint("_plat__SetNvAvail().\r\n");
692 _plat__SetNvAvail();
693 dbgPrint("_plat__Signal_PowerOn().\r\n");
694 if((retVal =_plat__Signal_PowerOn()) != 0)
695 {
696 logError("_plat__Signal_PowerOn() failed.\r\n");
697 }
698 dbgPrint("_plat__Signal_Reset().\r\n");
699 if((retVal =_plat__Signal_Reset()) != 0)
700 {
701 logError("_plat__Signal_Reset() failed.\r\n");
702 }
703 return (retVal == 0);
704 }
705
TpmOperationsLoop(void)706 bool TpmOperationsLoop(void)
707 {
708 // Device reset
709 if(tpmOp.flags.resetRequested == 1)
710 {
711 tpmOp.flags.resetRequested = 0;
712
713 HAL_Delay(1);
714 dbgPrint("Executing _plat__Signal_PowerOff()\r\n");
715 _plat__Signal_PowerOff();
716 PerformSystemReset();
717 return false;
718 }
719
720 if(tpmOp.flags.powerOffRequested == 1)
721 {
722 tpmOp.flags.powerOffRequested = 0;
723 dbgPrint("Executing _plat__Signal_PowerOff()\r\n");
724 _plat__Signal_PowerOff();
725 KillUSBLink();
726 return false;
727 }
728
729 // Physical presence button (blue button on the Nucleo)
730 int ppButton = BlueButtonTransitionDetected();
731 if(ppButton > 0)
732 {
733 dbgPrint("Executing _plat__Signal_PhysicalPresenceOn().\r\n");
734 _plat__Signal_PhysicalPresenceOn();
735 }
736 else if (ppButton < 0)
737 {
738 dbgPrint("Executing _plat__Signal_PhysicalPresenceOff().\r\n");
739 _plat__Signal_PhysicalPresenceOff();
740 }
741
742 // Command processing
743 if(tpmOp.flags.executionRequested == 1)
744 {
745 tpmOp.flags.executionRequested = 0;
746 unsigned int rspLenTPM = sizeof(tpmOp.msgBuf) - sizeof(rspLenTPM);
747 unsigned char* rspTPM = (unsigned char*)&tpmOp.msgBuf[sizeof(rspLenTPM)];
748
749 itmPrintAppend(ITMCMDRSP, "//%s\r\nunsigned char CmdBuf[%d] = {", GetLogStamp(), tpmOp.cmdSize);
750 for(uint32_t n = 0; n < tpmOp.cmdSize; n++)
751 {
752 if(n > 0) itmPrintAppend(ITMCMDRSP, ", ");
753 if(!(n % 16)) itmPrintAppend(ITMCMDRSP, "\r\n");
754 itmPrintAppend(ITMCMDRSP, "0x%02x", tpmOp.msgBuf[n]);
755 }
756 itmPrintAppend(ITMCMDRSP, "\r\n};\r\n");
757
758 SetDutyCycleIndicator(TRUE);
759 dbgPrint("Executing command %s\r\n", TpmDecodeTPM_CC((uint8_t*)&tpmOp.msgBuf[6]));
760 time_t execStart = time(NULL);
761 _plat__RunCommand((unsigned int)tpmOp.cmdSize, (unsigned char*)tpmOp.msgBuf, &rspLenTPM, &rspTPM);
762 *((unsigned int*)tpmOp.msgBuf) = rspLenTPM;
763 time_t execEnd = time(NULL);
764 dbgPrint("Completion time %u'%u\" with ReturnCode %s\r\n", (unsigned int)(execEnd - execStart) / 60, (unsigned int)(execEnd - execStart) % 60, TpmDecodeTPM_RC(&rspTPM[6]));
765 SetDutyCycleIndicator(FALSE);
766
767 itmPrintAppend(ITMCMDRSP, "//%s\r\nunsigned char RspBuf[%d] = {", GetLogStamp(), tpmOp.cmdSize);
768 for(uint32_t n = 0; n < rspLenTPM; n++)
769 {
770 if(n > 0) itmPrintAppend(ITMCMDRSP, ", ");
771 if(!(n % 16)) itmPrintAppend(ITMCMDRSP, "\r\n");
772 itmPrintAppend(ITMCMDRSP, "0x%02x", rspTPM[n]);
773 }
774 itmPrintAppend(ITMCMDRSP, "\r\n};\r\n");
775
776 tpmOp.rspSize = sizeof(rspLenTPM) + rspLenTPM;
777 tpmOp.cmdSize = 0;
778 tpmOp.flags.responseRequested = 1;
779 }
780
781 if(tpmOp.flags.responseRequested == 1)
782 {
783 tpmOp.flags.responseRequested = 0;
784 if(tpmOp.rspSize > 0)
785 {
786 uint32_t chunk = 0;
787 while(CDC_Transmit_FS((unsigned char*)&tpmOp.msgBuf, 0) != 0); // Wake up the link
788 while(CDC_Transmit_FS((unsigned char*)&tpmOp.msgBuf, 14) != 0); // Send the header which is the minimum size
789 for(uint32_t n = 14; n < tpmOp.rspSize; n += chunk) // Send the rest in 16 byte increments
790 {
791 chunk = MIN(16, tpmOp.rspSize - n);
792 while(CDC_Transmit_FS((unsigned char*)&tpmOp.msgBuf[n], chunk) != 0);
793 // dbgPrint("Sent(%u)\r\n", (unsigned int)(n + chunk));
794 }
795 itmPrint(ITMSIGNAL, "Response(%d)\r\n", tpmOp.rspSize);
796 }
797 }
798
799 return true;
800 }
801
TpmConnectionReset(void)802 void TpmConnectionReset(void)
803 {
804 tpmOp.receivingCmd = -1;
805 tpmOp.cmdSize = 0;
806 tpmOp.rspSize = 0;
807 memset((void*)tpmOp.msgBuf, 0x00, sizeof(tpmOp.msgBuf));
808 }
809
TpmSignalEvent(uint8_t * Buf,uint32_t * Len)810 bool TpmSignalEvent(uint8_t* Buf, uint32_t *Len)
811 {
812 // Pending inbound transfer
813 if(tpmOp.receivingCmd > 0)
814 {
815 memcpy((void*)&tpmOp.msgBuf[tpmOp.cmdSize], (void*)Buf, *Len);
816 tpmOp.cmdSize += *Len;
817 // itmPrint(ITMSIGNAL, "Received(%d)\r\n", tpmOp.cmdSize);
818 if(tpmOp.cmdSize >= tpmOp.receivingCmd)
819 {
820 itmPrint(ITMSIGNAL, "Received(%d)\r\n", tpmOp.cmdSize);
821 tpmOp.receivingCmd = -1;
822 tpmOp.flags.executionRequested = 1;
823 }
824 }
825 else if(sizeof(signalWrapper_t) > *Len)
826 {
827 itmPrint(ITMSIGNAL, "Invalid frame received.\r\n");
828 return false;
829 }
830 else
831 {
832 pSignalWrapper_t sig = (pSignalWrapper_t)Buf;
833 if(sig->s.magic == SIGNALMAGIC)
834 {
835 pSignalPayload_t payload;
836 switch(sig->s.signal)
837 {
838 case SignalNothing:
839 if((sig->s.dataSize != 0) || (*Len != sizeof(signalWrapper_t)))
840 {
841 itmPrint(ITMSIGNAL, "Invalid data size %u for SignalNothing(%u).\r\n", (unsigned int)*Len, (unsigned int)sig->s.dataSize);
842 return false;
843 }
844 itmPrint(ITMSIGNAL, "SignalNothing\r\n");
845 break;
846
847 case SignalShutdown:
848 if((sig->s.dataSize != 0) || (*Len != sizeof(signalWrapper_t)))
849 {
850 itmPrint(ITMSIGNAL, "Invalid data size %u for SignalShutdown(%u).\r\n", (unsigned int)*Len, (unsigned int)sig->s.dataSize);
851 return false;
852 }
853 itmPrint(ITMSIGNAL, "SignalShutdown\r\n");
854 tpmOp.flags.powerOffRequested = 1;
855 break;
856
857 case SignalReset:
858 if((sig->s.dataSize != 0) || (*Len != sizeof(signalWrapper_t)))
859 {
860 itmPrint(ITMSIGNAL, "Invalid data size %u for SignalReset(%u).\r\n", (unsigned int)*Len, (unsigned int)sig->s.dataSize);
861 return false;
862 }
863 itmPrint(ITMSIGNAL, "SignalReset\r\n");
864 tpmOp.flags.resetRequested = 1;
865 break;
866
867 case SignalSetClock:
868 if((sig->s.dataSize != sizeof(unsigned int)) || (*Len != sizeof(signalWrapper_t) + sizeof(unsigned int)))
869 {
870 itmPrint(ITMSIGNAL, "Invalid data size %u for SignalSetClock(%u).\r\n", (unsigned int)*Len, (unsigned int)sig->s.dataSize);
871 return false;
872 }
873 payload = (pSignalPayload_t)&Buf[sizeof(signalWrapper_t)];
874 SetRealTimeClock(payload->SignalSetClockPayload.time);
875 itmPrint(ITMSIGNAL, "SignalSetClock(0x%08x)\r\n", payload->SignalSetClockPayload.time);
876 break;
877
878 case SignalCancelOn:
879 if((sig->s.dataSize != 0) || (*Len != sizeof(signalWrapper_t)))
880 {
881 itmPrint(ITMSIGNAL, "Invalid data size %u for SignalCancelOn(%u).\r\n", (unsigned int)*Len, (unsigned int)sig->s.dataSize);
882 return false;
883 }
884 itmPrint(ITMSIGNAL, "SignalCancelOn\r\n");
885 _plat__SetCancel();
886 break;
887
888 case SignalCancelOff:
889 if((sig->s.dataSize != 0) || (*Len != sizeof(signalWrapper_t)))
890 {
891 itmPrint(ITMSIGNAL, "Invalid data size %u for SignalCancelOff(%u).\r\n", (unsigned int)*Len, (unsigned int)sig->s.dataSize);
892 return false;
893 }
894 itmPrint(ITMSIGNAL, "SignalCancelOff\r\n");
895 _plat__ClearCancel();
896 break;
897
898 case SignalCommand:
899 if((sig->s.dataSize == 0) ||
900 (*Len == sizeof(signalWrapper_t)))
901 {
902 itmPrint(ITMSIGNAL, "Invalid data size %u for SignalCommand(%u).\r\n", (unsigned int)*Len, (unsigned int)sig->s.dataSize);
903 return false;
904 }
905 payload = (pSignalPayload_t)&Buf[sizeof(signalWrapper_t)];
906 unsigned int expected = sizeof(signalWrapper_t) + sizeof(unsigned int) * 2 + payload->SignalCommandPayload.cmdSize;
907 unsigned int maxAllowed = sizeof(tpmOp.msgBuf);
908 memset((unsigned char*)tpmOp.msgBuf, 0x00, sizeof(tpmOp.msgBuf));
909 tpmOp.rspSize = 0;
910 itmPrint(ITMSIGNAL, "SignalCommand(%d)\r\n", payload->SignalCommandPayload.cmdSize);
911
912 // Set the locality for the command
913 if(_plat__LocalityGet() != payload->SignalCommandPayload.locality)
914 {
915 _plat__LocalitySet(payload->SignalCommandPayload.locality);
916 itmPrint(ITMSIGNAL, "SetLocality(%d)\r\n", payload->SignalCommandPayload.locality);
917 }
918
919 if((*Len == expected) &&
920 (payload->SignalCommandPayload.cmdSize <= maxAllowed))
921 {
922 memcpy((void*)tpmOp.msgBuf, (void*)payload->SignalCommandPayload.cmd, payload->SignalCommandPayload.cmdSize);
923 tpmOp.cmdSize = payload->SignalCommandPayload.cmdSize;
924 tpmOp.flags.executionRequested = 1;
925 // itmPrint(ITMSIGNAL, "Received(%d)\r\n", tpmOp.cmdSize);
926 }
927 else if((*Len < expected) &&
928 (payload->SignalCommandPayload.cmdSize <= maxAllowed))
929 {
930 unsigned int dataSnip = *Len - (sizeof(signalWrapper_t) + sizeof(unsigned int) * 2);
931 memcpy((void*)tpmOp.msgBuf, (void*)payload->SignalCommandPayload.cmd, dataSnip);
932 tpmOp.receivingCmd = payload->SignalCommandPayload.cmdSize;
933 tpmOp.cmdSize = dataSnip;
934 // itmPrint(ITMSIGNAL, "Received(%d)\r\n", tpmOp.cmdSize);
935 }
936 else
937 {
938 logError("Invalid command size.\r\n");
939 return false;
940 }
941 break;
942
943 case SignalResponse:
944 if((sig->s.dataSize != 0) || (*Len != sizeof(signalWrapper_t)))
945 {
946 itmPrint(ITMSIGNAL, "Invalid data size %u for SignalResponse(%u).\r\n", (unsigned int)*Len, (unsigned int)sig->s.dataSize);
947 return false;
948 }
949 itmPrint(ITMSIGNAL, "SignalResponse\r\n");
950 if(tpmOp.rspSize > 0)
951 {
952 tpmOp.flags.responseRequested = 1;
953 }
954 break;
955
956 default:
957 itmPrint(ITMSIGNAL, "Unknown Signal %u received.\r\n", sig->s.signal);
958 return false;
959 break;
960 }
961 }
962 }
963 return true;
964 }
965