PageRenderTime 51ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/src/netbsd/src/crypto/external/cpl/tpm-tools/dist/lib/tpm_unseal.c

https://bitbucket.org/killerpenguinassassins/open_distrib_devel
C | 499 lines | 393 code | 58 blank | 48 comment | 95 complexity | 4aedc1b25d4224c773cfd4f293e33f19 MD5 | raw file
Possible License(s): CC0-1.0, MIT, LGPL-2.0, LGPL-3.0, WTFPL, GPL-2.0, BSD-2-Clause, AGPL-3.0, CC-BY-SA-3.0, MPL-2.0, JSON, BSD-3-Clause-No-Nuclear-License-2014, LGPL-2.1, CPL-1.0, AGPL-1.0, 0BSD, ISC, Apache-2.0, GPL-3.0, IPL-1.0, MPL-2.0-no-copyleft-exception, BSD-3-Clause
  1. /*
  2. * The Initial Developer of the Original Code is International
  3. * Business Machines Corporation. Portions created by IBM
  4. * Corporation are Copyright (C) 2005, 2006 International Business
  5. * Machines Corporation. All Rights Reserved.
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the Common Public License as published by
  9. * IBM Corporation; either version 1 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * Common Public License for more details.
  16. *
  17. * You should have received a copy of the Common Public License
  18. * along with this program; if not, a copy can be viewed at
  19. * http://www.opensource.org/licenses/cpl1.0.php.
  20. */
  21. #include "tpm_tspi.h"
  22. #include "tpm_seal.h"
  23. #include "tpm_unseal.h"
  24. #include <errno.h>
  25. #include <string.h>
  26. #include <stdio.h>
  27. #include <sys/types.h>
  28. #include <sys/stat.h>
  29. #include <unistd.h>
  30. #include <openssl/evp.h>
  31. #include <trousers/tss.h>
  32. #include <trousers/trousers.h>
  33. enum tspi_errors {
  34. ETSPICTXCREAT = 0,
  35. ETSPICTXCNCT,
  36. ETSPICTXCO,
  37. ETSPICTXLKBU,
  38. ETSPICTXLKBB,
  39. ETSPISETAD,
  40. ETSPIGETPO,
  41. ETSPIPOLSS,
  42. ETSPIDATU,
  43. ETSPIPOLATO,
  44. };
  45. TSS_HCONTEXT hContext = 0;
  46. #define TSPI_FUNCTION_NAME_MAX 30
  47. char tspi_error_strings[][TSPI_FUNCTION_NAME_MAX]= {
  48. "Tspi_Context_Create",
  49. "Tspi_Context_Connect",
  50. "Tspi_Context_CreateObject",
  51. "Tspi_Context_LoadKeyByUUID",
  52. "Tspi_Context_LoadKeyByBlob",
  53. "Tspi_SetAttribData",
  54. "Tspi_GetPolicyObject",
  55. "Tspi_Policy_SetSecret",
  56. "Tspi_Data_Unseal",
  57. "Tspi_Policy_AssignToObject",
  58. };
  59. #define TSSKEY_DEFAULT_SIZE 768
  60. #define EVPKEY_DEFAULT_SIZE 512
  61. int tpm_errno;
  62. int tpmUnsealFile( char* fname, unsigned char** tss_data, int* tss_size,
  63. BOOL srkWellKnown ) {
  64. int rc, rcLen=0, tssLen=0, evpLen=0;
  65. BYTE* rcPtr;
  66. char data[EVP_CIPHER_block_size(EVP_aes_256_cbc()) * 16];
  67. BYTE *tssKeyData = NULL;
  68. int tssKeyDataSize = 0;
  69. BYTE *evpKeyData = NULL;
  70. int evpKeyDataSize = 0;
  71. struct stat stats;
  72. TSS_HENCDATA hEncdata;
  73. TSS_HKEY hSrk, hKey;
  74. TSS_HPOLICY hPolicy;
  75. UINT32 symKeyLen;
  76. BYTE *symKey;
  77. BYTE wellKnown[TCPA_SHA1_160_HASH_LEN] = TSS_WELL_KNOWN_SECRET;
  78. char *srkSecret = NULL;
  79. int srkSecretLen;
  80. unsigned char* res_data = NULL;
  81. int res_size = 0;
  82. BIO *bdata = NULL, *b64 = NULL, *bmem = NULL;
  83. int bioRc;
  84. if ( tss_data == NULL || tss_size == NULL ) {
  85. rc = TPMSEAL_STD_ERROR;
  86. tpm_errno = EINVAL;
  87. goto out;
  88. }
  89. *tss_data = NULL;
  90. *tss_size = 0;
  91. /* Test for file existence */
  92. if ((rc = stat(fname, &stats))) {
  93. tpm_errno = errno;
  94. goto out;
  95. }
  96. /* Create an input file BIO */
  97. if((bdata = BIO_new_file(fname, "r")) == NULL ) {
  98. tpm_errno = errno;
  99. rc = TPMSEAL_STD_ERROR;
  100. goto out;
  101. }
  102. /* Test file header for TSS */
  103. BIO_gets(bdata, data, sizeof(data));
  104. if (strncmp(data, TPMSEAL_HDR_STRING,
  105. strlen(TPMSEAL_HDR_STRING)) != 0) {
  106. rc = TPMSEAL_FILE_ERROR;
  107. tpm_errno = ENOTSSHDR;
  108. goto out;
  109. }
  110. /* Looking for TSS Key Header */
  111. BIO_gets(bdata, data, sizeof(data));
  112. if (strncmp(data, TPMSEAL_TSS_STRING,
  113. strlen(TPMSEAL_TSS_STRING)) != 0) {
  114. rc = TPMSEAL_FILE_ERROR;
  115. tpm_errno = EWRONGTSSTAG;
  116. goto out;
  117. }
  118. /* Create a memory BIO to hold the base64 TSS key */
  119. if ((bmem = BIO_new(BIO_s_mem())) == NULL) {
  120. tpm_errno = EAGAIN;
  121. rc = TPMSEAL_STD_ERROR;
  122. goto out;
  123. }
  124. BIO_set_mem_eof_return(bmem, 0);
  125. /* Read the base64 TSS key into the memory BIO */
  126. while ((rcLen = BIO_gets(bdata, data, sizeof(data))) > 0) {
  127. /* Look for EVP Key Header (end of key) */
  128. if (strncmp(data, TPMSEAL_EVP_STRING,
  129. strlen(TPMSEAL_EVP_STRING)) == 0)
  130. break;
  131. if (BIO_write(bmem, data, rcLen) <= 0) {
  132. tpm_errno = EIO;
  133. rc = TPMSEAL_STD_ERROR;
  134. goto out;
  135. }
  136. }
  137. if (strncmp(data, TPMSEAL_EVP_STRING,
  138. strlen(TPMSEAL_EVP_STRING)) != 0 ) {
  139. tpm_errno = EWRONGEVPTAG;
  140. rc = TPMSEAL_FILE_ERROR;
  141. goto out;
  142. }
  143. /* Create a base64 BIO to decode the TSS key */
  144. if ((b64 = BIO_new(BIO_f_base64())) == NULL) {
  145. tpm_errno = EAGAIN;
  146. rc = TPMSEAL_STD_ERROR;
  147. goto out;
  148. }
  149. /* Decode the TSS key */
  150. bmem = BIO_push( b64, bmem );
  151. while ((rcLen = BIO_read(bmem, data, sizeof(data))) > 0) {
  152. if ((tssLen + rcLen) > tssKeyDataSize) {
  153. tssKeyDataSize += TSSKEY_DEFAULT_SIZE;
  154. rcPtr = realloc( tssKeyData, tssKeyDataSize);
  155. if ( rcPtr == NULL ) {
  156. tpm_errno = ENOMEM;
  157. rc = TPMSEAL_STD_ERROR;
  158. goto out;
  159. }
  160. tssKeyData = rcPtr;
  161. }
  162. memcpy(tssKeyData + tssLen, data, rcLen);
  163. tssLen += rcLen;
  164. }
  165. bmem = BIO_pop(b64);
  166. BIO_free(b64);
  167. b64 = NULL;
  168. bioRc = BIO_reset(bmem);
  169. /* Check for EVP Key Type Header */
  170. BIO_gets(bdata, data, sizeof(data));
  171. if (strncmp(data, TPMSEAL_KEYTYPE_SYM,
  172. strlen(TPMSEAL_KEYTYPE_SYM)) != 0 ) {
  173. rc = TPMSEAL_FILE_ERROR;
  174. tpm_errno = EWRONGKEYTYPE;
  175. goto out;
  176. }
  177. /* Make sure it's a supported cipher
  178. (currently only AES 256 CBC) */
  179. if (strncmp(data + strlen(TPMSEAL_KEYTYPE_SYM),
  180. TPMSEAL_CIPHER_AES256CBC,
  181. strlen(TPMSEAL_CIPHER_AES256CBC)) != 0) {
  182. rc = TPMSEAL_FILE_ERROR;
  183. tpm_errno = EWRONGKEYTYPE;
  184. goto out;
  185. }
  186. /* Read the base64 Symmetric key into the memory BIO */
  187. while ((rcLen = BIO_gets(bdata, data, sizeof(data))) > 0) {
  188. /* Look for Encrypted Data Header (end of key) */
  189. if (strncmp(data, TPMSEAL_ENC_STRING,
  190. strlen(TPMSEAL_ENC_STRING)) == 0)
  191. break;
  192. if (BIO_write(bmem, data, rcLen) <= 0) {
  193. tpm_errno = EIO;
  194. rc = TPMSEAL_STD_ERROR;
  195. goto out;
  196. }
  197. }
  198. if (strncmp(data, TPMSEAL_ENC_STRING,
  199. strlen(TPMSEAL_ENC_STRING)) != 0 ) {
  200. tpm_errno = EWRONGDATTAG;
  201. rc = TPMSEAL_FILE_ERROR;
  202. goto out;
  203. }
  204. /* Create a base64 BIO to decode the Symmetric key */
  205. if ((b64 = BIO_new(BIO_f_base64())) == NULL) {
  206. tpm_errno = EAGAIN;
  207. rc = TPMSEAL_STD_ERROR;
  208. goto out;
  209. }
  210. /* Decode the Symmetric key */
  211. bmem = BIO_push( b64, bmem );
  212. while ((rcLen = BIO_read(bmem, data, sizeof(data))) > 0) {
  213. if ((evpLen + rcLen) > evpKeyDataSize) {
  214. evpKeyDataSize += EVPKEY_DEFAULT_SIZE;
  215. rcPtr = realloc( evpKeyData, evpKeyDataSize);
  216. if ( rcPtr == NULL ) {
  217. tpm_errno = ENOMEM;
  218. rc = TPMSEAL_STD_ERROR;
  219. goto out;
  220. }
  221. evpKeyData = rcPtr;
  222. }
  223. memcpy(evpKeyData + evpLen, data, rcLen);
  224. evpLen += rcLen;
  225. }
  226. bmem = BIO_pop(b64);
  227. BIO_free(b64);
  228. b64 = NULL;
  229. bioRc = BIO_reset(bmem);
  230. /* Read the base64 encrypted data into the memory BIO */
  231. while ((rcLen = BIO_gets(bdata, data, sizeof(data))) > 0) {
  232. /* Look for TSS Footer (end of data) */
  233. if (strncmp(data, TPMSEAL_FTR_STRING,
  234. strlen(TPMSEAL_FTR_STRING)) == 0)
  235. break;
  236. if (BIO_write(bmem, data, rcLen) <= 0) {
  237. tpm_errno = EIO;
  238. rc = TPMSEAL_STD_ERROR;
  239. goto out;
  240. }
  241. }
  242. if (strncmp(data, TPMSEAL_FTR_STRING,
  243. strlen(TPMSEAL_FTR_STRING)) != 0 ) {
  244. tpm_errno = ENOTSSFTR;
  245. rc = TPMSEAL_FILE_ERROR;
  246. goto out;
  247. }
  248. /* Unseal */
  249. if ((rc=Tspi_Context_Create(&hContext)) != TSS_SUCCESS) {
  250. tpm_errno = ETSPICTXCREAT;
  251. goto out;
  252. }
  253. if (!srkWellKnown) {
  254. /* Prompt for SRK password */
  255. srkSecret = GETPASSWD(_("Enter SRK password: "), &srkSecretLen, FALSE);
  256. if (!srkSecret)
  257. goto out;
  258. }
  259. if ((rc=Tspi_Context_Connect(hContext, NULL)) != TSS_SUCCESS) {
  260. tpm_errno = ETSPICTXCNCT;
  261. goto tss_out;
  262. }
  263. if ((rc=Tspi_Context_CreateObject(hContext,
  264. TSS_OBJECT_TYPE_ENCDATA,
  265. TSS_ENCDATA_SEAL,
  266. &hEncdata)) != TSS_SUCCESS) {
  267. tpm_errno = ETSPICTXCO;
  268. goto tss_out;
  269. }
  270. if ((rc=Tspi_SetAttribData(hEncdata,
  271. TSS_TSPATTRIB_ENCDATA_BLOB,
  272. TSS_TSPATTRIB_ENCDATABLOB_BLOB,
  273. evpLen, evpKeyData)) != TSS_SUCCESS) {
  274. tpm_errno = ETSPISETAD;
  275. goto tss_out;
  276. }
  277. if ((rc=Tspi_Context_CreateObject(hContext,
  278. TSS_OBJECT_TYPE_POLICY,
  279. TSS_POLICY_USAGE,
  280. &hPolicy)) != TSS_SUCCESS) {
  281. tpm_errno = ETSPICTXCO;
  282. goto tss_out;
  283. }
  284. if ((rc=Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_PLAIN,
  285. strlen(TPMSEAL_SECRET),
  286. (BYTE *)TPMSEAL_SECRET)) != TSS_SUCCESS) {
  287. tpm_errno = ETSPIPOLSS;
  288. goto tss_out;
  289. }
  290. if ((rc=Tspi_Policy_AssignToObject(hPolicy, hEncdata)) != TSS_SUCCESS) {
  291. tpm_errno = ETSPIPOLATO;
  292. goto tss_out;
  293. }
  294. if ((rc=Tspi_Context_LoadKeyByUUID(hContext, TSS_PS_TYPE_SYSTEM,
  295. SRK_UUID, &hSrk)) != TSS_SUCCESS) {
  296. tpm_errno = ETSPICTXLKBU;
  297. goto tss_out;
  298. }
  299. /* Don't create a new policy for the SRK's secret, just use the context's
  300. * default policy */
  301. if ((rc=Tspi_GetPolicyObject(hSrk, TSS_POLICY_USAGE,
  302. &hPolicy)) != TSS_SUCCESS){
  303. tpm_errno = ETSPIGETPO;
  304. goto tss_out;
  305. }
  306. if (srkWellKnown)
  307. rc = Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_SHA1,
  308. sizeof(wellKnown),
  309. (BYTE *) wellKnown);
  310. else
  311. rc = Tspi_Policy_SetSecret(hPolicy,TSS_SECRET_MODE_PLAIN,
  312. srkSecretLen,
  313. (BYTE *) srkSecret);
  314. if (rc != TSS_SUCCESS) {
  315. tpm_errno = ETSPIPOLSS;
  316. goto tss_out;
  317. }
  318. /* Failure point if trying to unseal data on a differnt TPM */
  319. if ((rc=Tspi_Context_LoadKeyByBlob(hContext, hSrk, tssLen,
  320. tssKeyData, &hKey)) != TSS_SUCCESS) {
  321. tpm_errno = ETSPICTXLKBB;
  322. goto tss_out;
  323. }
  324. if ((rc=Tspi_Context_CreateObject(hContext,
  325. TSS_OBJECT_TYPE_POLICY,
  326. TSS_POLICY_USAGE,
  327. &hPolicy)) != TSS_SUCCESS) {
  328. tpm_errno = ETSPICTXCO;
  329. goto tss_out;
  330. }
  331. if ((rc=Tspi_Policy_SetSecret(hPolicy, TSS_SECRET_MODE_PLAIN,
  332. strlen(TPMSEAL_SECRET),
  333. (BYTE *)TPMSEAL_SECRET)) != TSS_SUCCESS) {
  334. tpm_errno = ETSPIPOLSS;
  335. goto tss_out;
  336. }
  337. if ((rc=Tspi_Policy_AssignToObject(hPolicy, hKey)) != TSS_SUCCESS) {
  338. tpm_errno = ETSPIPOLATO;
  339. goto tss_out;
  340. }
  341. if ((rc=Tspi_Data_Unseal(hEncdata, hKey, &symKeyLen,
  342. &symKey)) != TSS_SUCCESS) {
  343. tpm_errno = ETSPIDATU;
  344. goto tss_out;
  345. }
  346. /* Malloc a block of storage to hold the decrypted data
  347. Using the size of the mem BIO is more than enough
  348. (plus an extra cipher block size) */
  349. res_data = malloc(BIO_pending(bmem) + EVP_CIPHER_block_size(EVP_aes_256_cbc()));
  350. if ( res_data == NULL ) {
  351. rc = TPMSEAL_STD_ERROR;
  352. tpm_errno = ENOMEM;
  353. goto tss_out;
  354. }
  355. /* Decode and decrypt the encrypted data */
  356. EVP_CIPHER_CTX ctx;
  357. EVP_DecryptInit(&ctx, EVP_aes_256_cbc(), symKey, (unsigned char *)TPMSEAL_IV);
  358. /* Create a base64 BIO to decode the encrypted data */
  359. if ((b64 = BIO_new(BIO_f_base64())) == NULL) {
  360. tpm_errno = EAGAIN;
  361. rc = TPMSEAL_STD_ERROR;
  362. goto tss_out;
  363. }
  364. bmem = BIO_push( b64, bmem );
  365. while ((rcLen = BIO_read(bmem, data, sizeof(data))) > 0) {
  366. EVP_DecryptUpdate(&ctx, res_data+res_size,
  367. &rcLen, (unsigned char *)data, rcLen);
  368. res_size += rcLen;
  369. }
  370. EVP_DecryptFinal(&ctx, res_data+res_size, &rcLen);
  371. res_size += rcLen;
  372. bmem = BIO_pop(b64);
  373. BIO_free(b64);
  374. b64 = NULL;
  375. bioRc = BIO_reset(bmem);
  376. tss_out:
  377. Tspi_Context_Close(hContext);
  378. out:
  379. if (srkSecret)
  380. shredPasswd(srkSecret);
  381. if ( bdata )
  382. BIO_free(bdata);
  383. if ( b64 )
  384. BIO_free(b64);
  385. if ( bmem ) {
  386. bioRc = BIO_set_close(bmem, BIO_CLOSE);
  387. BIO_free(bmem);
  388. }
  389. if ( evpKeyData )
  390. free(evpKeyData);
  391. if ( tssKeyData )
  392. free(tssKeyData);
  393. if ( rc == 0 ) {
  394. *tss_data = res_data;
  395. *tss_size = res_size;
  396. } else
  397. free(res_data);
  398. return rc;
  399. }
  400. void tpmUnsealShred(unsigned char* data, int size) {
  401. if ( data != NULL ) {
  402. memset( data, 0, size);
  403. free(data);
  404. }
  405. }
  406. char tpm_error_buf[512];
  407. char * tpmUnsealStrerror(int rc) {
  408. switch(rc) {
  409. case 0:
  410. return "Success";
  411. case TPMSEAL_STD_ERROR:
  412. return strerror(tpm_errno);
  413. case TPMSEAL_FILE_ERROR:
  414. switch(tpm_errno) {
  415. case ENOTSSHDR:
  416. return _("No TSS header present");
  417. case ENOTSSFTR:
  418. return _("No TSS footer present");
  419. case EWRONGTSSTAG:
  420. return _("Wrong TSS tag");
  421. case EWRONGEVPTAG:
  422. return _("Wrong EVP tag");
  423. case EWRONGDATTAG:
  424. return _("Wrong DATA tag");
  425. case EWRONGKEYTYPE:
  426. return _("Not a Symmetric EVP Key");
  427. case EBADSEEK:
  428. return _("Unable to move to desired file position");
  429. }
  430. default:
  431. snprintf(tpm_error_buf, sizeof(tpm_error_buf),
  432. "%s: 0x%08x - layer=%s, code=%04x (%d), %s",
  433. tspi_error_strings[tpm_errno],
  434. rc, Trspi_Error_Layer(rc),
  435. Trspi_Error_Code(rc),
  436. Trspi_Error_Code(rc),
  437. Trspi_Error_String(rc));
  438. return tpm_error_buf;
  439. }
  440. return "";
  441. }