sys-hmac-auth.int.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. /*
  2. * SPDX-License-Identifier: BSD-2-Clause
  3. * Copyright (c) 2019, Intel Corporation
  4. */
  5. #ifdef HAVE_CONFIG_H
  6. #include <config.h>
  7. #endif
  8. #include <inttypes.h>
  9. #include <stdbool.h>
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include "tss2_sys.h"
  14. #include "context-util.h"
  15. #include "sys-util.h"
  16. #include "session-util.h"
  17. #define LOGMODULE test
  18. #include "util/log.h"
  19. #define TPM20_INDEX_PASSWORD_TEST 0x01500020
  20. #define NV_DATA_SIZE 4
  21. #define NV_DATA { 0x00, 0xff, 0x55, 0xaa }
  22. #define SECRET_SIZE 13
  23. #define SECRET_DATA { 's', 'h', 'a', 'r', 'e', 'd', ' ', \
  24. 's', 'e', 'c', 'r', 'e', 't', }
  25. TSS2_RC
  26. create_policy (TSS2_SYS_CONTEXT *sys_ctx,
  27. TPM2B_DIGEST *authPolicy)
  28. {
  29. TSS2_RC rc;
  30. SESSION *trialPolicySession = NULL;
  31. TPM2B_NONCE nonceCaller = { 0, };
  32. TPM2B_ENCRYPTED_SECRET encryptedSalt = { 0, };
  33. TPMT_SYM_DEF symmetric = {
  34. .algorithm = TPM2_ALG_NULL,
  35. };
  36. TSS2_TCTI_CONTEXT *tcti_ctx;
  37. rc = Tss2_Sys_GetTctiContext (sys_ctx, &tcti_ctx);
  38. if (rc != TSS2_RC_SUCCESS || tcti_ctx == NULL) {
  39. LOG_ERROR("InitSysContext failed, exiting...");
  40. return rc;
  41. }
  42. rc = create_auth_session (&trialPolicySession,
  43. TPM2_RH_NULL,
  44. 0,
  45. TPM2_RH_NULL,
  46. 0,
  47. &nonceCaller,
  48. &encryptedSalt,
  49. TPM2_SE_TRIAL,
  50. &symmetric,
  51. TPM2_ALG_SHA256,
  52. tcti_ctx);
  53. if (rc != TSS2_RC_SUCCESS) {
  54. LOG_ERROR ("create_auth_session failed with rc: 0x%x", rc);
  55. return rc;
  56. }
  57. rc = Tss2_Sys_PolicyAuthValue (sys_ctx,
  58. trialPolicySession->sessionHandle,
  59. 0,
  60. 0);
  61. if (rc != TSS2_RC_SUCCESS) {
  62. LOG_ERROR ("Tss2_Sys_PolicyAuthValue failed with rc: 0x%x", rc);
  63. return rc;
  64. }
  65. rc = Tss2_Sys_PolicyGetDigest (sys_ctx,
  66. trialPolicySession->sessionHandle,
  67. 0,
  68. authPolicy,
  69. 0);
  70. if (rc != TSS2_RC_SUCCESS) {
  71. LOG_ERROR ("Tss2_Sys_PolicyGetDigest failed with rc: 0x%x", rc);
  72. return rc;
  73. }
  74. rc = Tss2_Sys_FlushContext (sys_ctx,
  75. trialPolicySession->sessionHandle);
  76. if (rc != TSS2_RC_SUCCESS) {
  77. LOG_ERROR ("Tss2_Sys_FlushContext failed with rc: 0x%x", rc);
  78. return rc;
  79. }
  80. end_auth_session (trialPolicySession);
  81. return rc;
  82. }
  83. TSS2_RC
  84. nv_rw_with_session (
  85. TSS2_SYS_CONTEXT *sys_ctx,
  86. const TPM2B_DIGEST *authPolicy,
  87. TPMA_NV nvAttributes,
  88. TPM2_SE session_type)
  89. {
  90. TSS2_RC rc;
  91. TPM2B_AUTH nvAuth = {
  92. .size = SECRET_SIZE,
  93. .buffer = SECRET_DATA,
  94. };
  95. SESSION *nvSession = NULL;
  96. TPM2B_NAME nvName;
  97. TPM2B_NONCE nonceCaller = { 0, };
  98. TPM2B_MAX_NV_BUFFER nvWriteData = {
  99. .size = NV_DATA_SIZE,
  100. .buffer = NV_DATA,
  101. };
  102. TPM2B_MAX_NV_BUFFER nvReadData = { .size = TPM2B_SIZE (nvReadData), };
  103. TPM2B_ENCRYPTED_SECRET encryptedSalt = { 0, };
  104. TPMT_SYM_DEF symmetric = {
  105. .algorithm = TPM2_ALG_NULL,
  106. };
  107. TSS2_TCTI_CONTEXT *tcti_ctx;
  108. TSS2L_SYS_AUTH_RESPONSE nvRspAuths;
  109. TSS2L_SYS_AUTH_COMMAND nvCmdAuths = {
  110. .count = 1,
  111. .auths= {
  112. {
  113. .nonce = {
  114. .size = 1,
  115. .buffer = { 0xa5, },
  116. },
  117. .sessionHandle = TPM2_RH_PW,
  118. .sessionAttributes = TPMA_SESSION_CONTINUESESSION,
  119. }
  120. }
  121. };
  122. const TSS2L_SYS_AUTH_COMMAND auth_cmd_null_pwd = {
  123. .count = 1,
  124. .auths = {
  125. {
  126. .sessionHandle = TPM2_RH_PW,
  127. },
  128. },
  129. };
  130. rc = Tss2_Sys_GetTctiContext (sys_ctx, &tcti_ctx);
  131. if (rc != TSS2_RC_SUCCESS || tcti_ctx == NULL) {
  132. LOG_ERROR ("Failed to get TCTI from Sys context, got RC: 0x%x", rc);
  133. return TSS2_SYS_RC_GENERAL_FAILURE;
  134. }
  135. rc = DefineNvIndex (sys_ctx,
  136. TPM2_RH_PLATFORM,
  137. &nvAuth,
  138. authPolicy,
  139. TPM20_INDEX_PASSWORD_TEST,
  140. TPM2_ALG_SHA256,
  141. nvAttributes,
  142. 32);
  143. if (rc != TSS2_RC_SUCCESS) {
  144. LOG_ERROR ("DefineNvIndex failed with RC: 0x%x", rc);
  145. return rc;
  146. }
  147. /*
  148. * Add index and associated authorization value to
  149. * entity table. This helps when we need
  150. * to calculate HMACs.
  151. */
  152. rc = AddEntity(TPM20_INDEX_PASSWORD_TEST, &nvAuth);
  153. if (rc != TSS2_RC_SUCCESS) {
  154. LOG_ERROR ("AddEntity failed with RC: 0x%x", rc);
  155. return rc;
  156. }
  157. /* Get the name of the NV index. */
  158. rc = tpm_handle_to_name (tcti_ctx,
  159. TPM20_INDEX_PASSWORD_TEST,
  160. &nvName);
  161. if (rc != TSS2_RC_SUCCESS) {
  162. LOG_ERROR ("tpm_handle_to_name failed with RC: 0x%x", rc);
  163. return rc;
  164. }
  165. /*
  166. * Start HMAC or real (non-trial) policy authorization session:
  167. * it's an unbound and unsalted session, no symmetric
  168. * encryption algorithm, and SHA256 is the session's
  169. * hash algorithm.
  170. */
  171. rc = create_auth_session (&nvSession,
  172. TPM2_RH_NULL,
  173. 0,
  174. TPM2_RH_NULL,
  175. 0,
  176. &nonceCaller,
  177. &encryptedSalt,
  178. session_type,
  179. &symmetric,
  180. TPM2_ALG_SHA256,
  181. tcti_ctx);
  182. if (rc != TSS2_RC_SUCCESS) {
  183. LOG_ERROR ("create_auth_session failed with RC: 0x%x", rc);
  184. return rc;
  185. }
  186. /* set handle in command auth */
  187. nvCmdAuths.auths[0].sessionHandle = nvSession->sessionHandle;
  188. /*
  189. * Get the name of the session and save it in
  190. * the nvSession structure.
  191. */
  192. rc = tpm_handle_to_name (tcti_ctx,
  193. nvSession->sessionHandle,
  194. &nvSession->name);
  195. if (rc != TSS2_RC_SUCCESS) {
  196. LOG_ERROR ("tpm_handle_to_name failed with RC: 0x%x", rc);
  197. return rc;
  198. }
  199. /*
  200. * Now setup for writing the NV index.
  201. */
  202. if (session_type == TPM2_SE_POLICY) {
  203. rc = Tss2_Sys_PolicyAuthValue (sys_ctx,
  204. nvSession->sessionHandle,
  205. 0,
  206. 0);
  207. if (rc != TSS2_RC_SUCCESS) {
  208. LOG_ERROR ("Tss2_Sys_PolicyAuthValue failed with RC: 0x%x", rc);
  209. return rc;
  210. }
  211. }
  212. /* First call prepare in order to create cpBuffer. */
  213. rc = Tss2_Sys_NV_Write_Prepare (sys_ctx,
  214. TPM20_INDEX_PASSWORD_TEST,
  215. TPM20_INDEX_PASSWORD_TEST,
  216. &nvWriteData,
  217. 0);
  218. if (rc != TSS2_RC_SUCCESS) {
  219. LOG_ERROR ("Tss2_Sys_NV_Write_Prepare failed with RC: 0x%x", rc);
  220. return rc;
  221. }
  222. /* Roll nonces for command */
  223. roll_nonces (nvSession, &nvCmdAuths.auths[0].nonce);
  224. /*
  225. * Complete command authorization area, by computing
  226. * HMAC and setting it in nvCmdAuths.
  227. */
  228. rc = compute_command_hmac(sys_ctx,
  229. TPM20_INDEX_PASSWORD_TEST,
  230. TPM20_INDEX_PASSWORD_TEST,
  231. TPM2_RH_NULL,
  232. &nvCmdAuths);
  233. if (rc != TSS2_RC_SUCCESS) {
  234. LOG_ERROR ("compute_command_hmac failed with RC: 0x%x", rc);
  235. return rc;
  236. }
  237. /*
  238. * Finally!! Write the data to the NV index.
  239. * If the command is successful, the command
  240. * HMAC was correct.
  241. */
  242. rc = TSS2_RETRY_EXP (Tss2_Sys_NV_Write (sys_ctx,
  243. TPM20_INDEX_PASSWORD_TEST,
  244. TPM20_INDEX_PASSWORD_TEST,
  245. &nvCmdAuths,
  246. &nvWriteData,
  247. 0,
  248. &nvRspAuths));
  249. if (rc != TSS2_RC_SUCCESS) {
  250. LOG_ERROR ("Tss2_Sys_NV_Write failed with RC: 0x%x", rc);
  251. return rc;
  252. }
  253. /* Roll nonces for response */
  254. roll_nonces (nvSession, &nvRspAuths.auths[0].nonce);
  255. /*
  256. * If the command was successful, check the
  257. * response HMAC to make sure that the
  258. * response was received correctly.
  259. */
  260. rc = check_response_hmac (sys_ctx,
  261. &nvCmdAuths,
  262. TPM20_INDEX_PASSWORD_TEST,
  263. TPM20_INDEX_PASSWORD_TEST,
  264. TPM2_RH_NULL,
  265. &nvRspAuths);
  266. if (rc != TSS2_RC_SUCCESS) {
  267. LOG_ERROR ("check_response_hmac failed with RC: 0x%x", rc);
  268. return rc;
  269. }
  270. if (session_type == TPM2_SE_POLICY) {
  271. rc = Tss2_Sys_PolicyAuthValue (sys_ctx,
  272. nvSession->sessionHandle,
  273. 0,
  274. 0);
  275. if (rc != TSS2_RC_SUCCESS) {
  276. LOG_ERROR ("Tss2_Sys_PolicyAuthValue failed with RC: 0x%x", rc);
  277. return rc;
  278. }
  279. }
  280. /* First call prepare in order to create cpBuffer. */
  281. rc = Tss2_Sys_NV_Read_Prepare (sys_ctx,
  282. TPM20_INDEX_PASSWORD_TEST,
  283. TPM20_INDEX_PASSWORD_TEST,
  284. NV_DATA_SIZE,
  285. 0);
  286. if (rc != TSS2_RC_SUCCESS) {
  287. LOG_ERROR ("Tss2_Sys_NV_Read_Prepare failed with RC: 0x%x", rc);
  288. return rc;
  289. }
  290. roll_nonces (nvSession, &nvCmdAuths.auths[0].nonce);
  291. /* End the session after next command. */
  292. nvCmdAuths.auths[0].sessionAttributes &= ~TPMA_SESSION_CONTINUESESSION;
  293. /*
  294. * Complete command authorization area, by computing
  295. * HMAC and setting it in nvCmdAuths.
  296. */
  297. rc = compute_command_hmac (sys_ctx,
  298. TPM20_INDEX_PASSWORD_TEST,
  299. TPM20_INDEX_PASSWORD_TEST,
  300. TPM2_RH_NULL,
  301. &nvCmdAuths);
  302. if (rc != TSS2_RC_SUCCESS) {
  303. LOG_ERROR ("compute_command_hmac failed with RC: 0x%x", rc);
  304. return rc;
  305. }
  306. /*
  307. * And now read the data back.
  308. * If the command is successful, the command
  309. * HMAC was correct.
  310. */
  311. rc = Tss2_Sys_NV_Read (sys_ctx,
  312. TPM20_INDEX_PASSWORD_TEST,
  313. TPM20_INDEX_PASSWORD_TEST,
  314. &nvCmdAuths,
  315. NV_DATA_SIZE,
  316. 0,
  317. &nvReadData,
  318. &nvRspAuths);
  319. if (rc != TSS2_RC_SUCCESS) {
  320. LOG_ERROR ("Tss2_Sys_NV_Read failed with RC: 0x%x", rc);
  321. return rc;
  322. }
  323. /* Roll nonces for response */
  324. roll_nonces (nvSession, &nvRspAuths.auths[0].nonce);
  325. /*
  326. * If the command was successful, check the
  327. * response HMAC to make sure that the
  328. * response was received correctly.
  329. */
  330. rc = check_response_hmac (sys_ctx,
  331. &nvCmdAuths,
  332. TPM20_INDEX_PASSWORD_TEST,
  333. TPM20_INDEX_PASSWORD_TEST,
  334. TPM2_RH_NULL,
  335. &nvRspAuths);
  336. if (rc != TSS2_RC_SUCCESS) {
  337. LOG_ERROR ("check_response_hmac failed with RC: 0x%x", rc);
  338. return rc;
  339. }
  340. /* Check that write and read data are equal. */
  341. if (memcmp ((void *)&nvReadData.buffer[0],
  342. (void *)&nvWriteData.buffer[0],
  343. nvReadData.size))
  344. {
  345. LOG_ERROR ("Data read not equal to data written.");
  346. return 1;
  347. }
  348. /*
  349. * Now cleanup: undefine the NV index and delete
  350. * the NV index's entity table entry.
  351. */
  352. /* Undefine the NV index. */
  353. rc = Tss2_Sys_NV_UndefineSpace (sys_ctx,
  354. TPM2_RH_PLATFORM,
  355. TPM20_INDEX_PASSWORD_TEST,
  356. &auth_cmd_null_pwd,
  357. 0);
  358. if (rc != TSS2_RC_SUCCESS) {
  359. LOG_ERROR ("Tss2_Sys_NV_UndefineSpace failed with RC: 0x%x", rc);
  360. return rc;
  361. }
  362. /* Delete the NV index's entry in the entity table. */
  363. DeleteEntity (TPM20_INDEX_PASSWORD_TEST);
  364. /* Remove the real session from sessions table. */
  365. end_auth_session (nvSession);
  366. return rc;
  367. }
  368. int
  369. test_invoke (TSS2_SYS_CONTEXT *sys_ctx)
  370. {
  371. TSS2_RC rc;
  372. TPM2B_DIGEST authPolicy = { 0, };
  373. TPMA_NV nvAttributes;
  374. LOG_INFO ("HMAC session test");
  375. nvAttributes = TPMA_NV_AUTHREAD | TPMA_NV_AUTHWRITE | TPMA_NV_PLATFORMCREATE;
  376. rc = nv_rw_with_session (sys_ctx, &authPolicy, nvAttributes, TPM2_SE_HMAC);
  377. if (rc != TSS2_RC_SUCCESS)
  378. return rc;
  379. LOG_INFO ("Policy session test");
  380. authPolicy.size = TPM2B_SIZE (authPolicy);
  381. rc = create_policy (sys_ctx, &authPolicy);
  382. if (rc != TSS2_RC_SUCCESS)
  383. return rc;
  384. nvAttributes = TPMA_NV_POLICYREAD | TPMA_NV_POLICYWRITE | TPMA_NV_PLATFORMCREATE;
  385. rc = nv_rw_with_session (sys_ctx, &authPolicy, nvAttributes, TPM2_SE_POLICY);
  386. if (rc != TSS2_RC_SUCCESS)
  387. return rc;
  388. return TSS2_RC_SUCCESS;
  389. }