sign_tool.cpp 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133
  1. /*
  2. * Copyright (C) 2011-2018 Intel Corporation. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * * Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * * Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in
  12. * the documentation and/or other materials provided with the
  13. * distribution.
  14. * * Neither the name of Intel Corporation nor the names of its
  15. * contributors may be used to endorse or promote products derived
  16. * from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  24. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. *
  30. */
  31. // SignTool.cpp : Defines the entry point for the console application.
  32. //
  33. /**
  34. * File:
  35. * sign_tool.cpp
  36. *Description:
  37. * Defines the entry point for the application.
  38. *
  39. */
  40. #include <openssl/bio.h>
  41. #include <openssl/bn.h>
  42. #include <openssl/sha.h>
  43. #include <openssl/rsa.h>
  44. #include <openssl/evp.h>
  45. #include <openssl/err.h>
  46. #include "metadata.h"
  47. #include "manage_metadata.h"
  48. #include "parse_key_file.h"
  49. #include "enclave_creator_sign.h"
  50. #include "util_st.h"
  51. #include "se_trace.h"
  52. #include "sgx_error.h"
  53. #include "se_version.h"
  54. #include "se_map.h"
  55. #include "loader.h"
  56. #include "parserfactory.h"
  57. #include "elf_helper.h"
  58. #include "crypto_wrapper.h"
  59. #include <unistd.h>
  60. #include <stdio.h>
  61. #include <stdlib.h>
  62. #include <assert.h>
  63. #include <string>
  64. #include <memory>
  65. #include <sstream>
  66. #define SIGNATURE_SIZE 384
  67. typedef enum _file_path_t
  68. {
  69. DLL = 0,
  70. XML = 1,
  71. KEY,
  72. OUTPUT,
  73. SIG,
  74. UNSIGNED,
  75. DUMPFILE
  76. } file_path_t;
  77. static int load_enclave(BinParser *parser, metadata_t *metadata)
  78. {
  79. std::unique_ptr<CLoader> ploader(new CLoader(const_cast<uint8_t *>(parser->get_start_addr()), *parser));
  80. return ploader->load_enclave_ex(NULL, 0, metadata, NULL);
  81. }
  82. #define THE_INVALID_HANDLE (-1)
  83. static int open_file(const char* dllpath)
  84. {
  85. FILE *fp = fopen(dllpath, "rb");
  86. if (fp == NULL)
  87. return THE_INVALID_HANDLE;
  88. return fileno(fp);
  89. }
  90. static void close_handle(int fd)
  91. {
  92. close(fd);
  93. }
  94. static bool get_enclave_info(BinParser *parser, bin_fmt_t *bf, uint64_t * meta_offset, bool is_dump_mode = false)
  95. {
  96. uint64_t meta_rva = parser->get_metadata_offset();
  97. const uint8_t *base_addr = parser->get_start_addr();
  98. metadata_t *metadata = GET_PTR(metadata_t, base_addr, meta_rva);
  99. if(metadata->magic_num == METADATA_MAGIC && is_dump_mode == false)
  100. {
  101. se_trace(SE_TRACE_ERROR, ENCLAVE_ALREADY_SIGNED_ERROR);
  102. return false;
  103. }
  104. *bf = parser->get_bin_format();
  105. *meta_offset = meta_rva;
  106. return true;
  107. }
  108. // measure_enclave():
  109. // 1. Get the enclave hash by loading enclave
  110. // 2. Get the enclave info - metadata offset and enclave file format
  111. static bool measure_enclave(uint8_t *hash, const char *dllpath, const xml_parameter_t *parameter, bool ignore_rel_error, metadata_t *metadata, uint64_t *meta_offset)
  112. {
  113. assert(hash && dllpath && metadata && meta_offset);
  114. bool res = false;
  115. uint32_t file_size = 0;
  116. uint64_t quota = 0;
  117. bin_fmt_t bin_fmt = BF_UNKNOWN;
  118. se_file_handle_t fh = open_file(dllpath);
  119. if (fh == THE_INVALID_HANDLE)
  120. {
  121. se_trace(SE_TRACE_ERROR, OPEN_FILE_ERROR, dllpath);
  122. return false;
  123. }
  124. // Probably we can use `decltype' if all major supported compilers support that.
  125. std::unique_ptr<map_handle_t, void (*)(map_handle_t*)> mh(map_file(fh, &file_size), unmap_file);
  126. if (!mh)
  127. {
  128. close_handle(fh);
  129. return false;
  130. }
  131. // Parse enclave
  132. std::unique_ptr<BinParser> parser(binparser::get_parser(mh->base_addr, (size_t)file_size));
  133. assert(parser != NULL);
  134. sgx_status_t status = parser->run_parser();
  135. if (status != SGX_SUCCESS)
  136. {
  137. se_trace(SE_TRACE_ERROR, INVALID_ENCLAVE_ERROR);
  138. close_handle(fh);
  139. return false;
  140. }
  141. // generate metadata
  142. CMetadata meta(metadata, parser.get());
  143. if(meta.build_metadata(parameter) == false)
  144. {
  145. close_handle(fh);
  146. return false;
  147. }
  148. // Collect enclave info
  149. if(get_enclave_info(parser.get(), &bin_fmt, meta_offset) == false)
  150. {
  151. close_handle(fh);
  152. return false;
  153. }
  154. bool no_rel = false;
  155. if (bin_fmt == BF_ELF64)
  156. {
  157. no_rel = ElfHelper<64>::dump_textrels(parser.get());
  158. }
  159. else
  160. {
  161. no_rel = ElfHelper<32>::dump_textrels(parser.get());
  162. }
  163. if(no_rel == false && ignore_rel_error == false)
  164. {
  165. close_handle(fh);
  166. se_trace(SE_TRACE_ERROR, TEXT_REL_ERROR);
  167. return false;
  168. }
  169. // Load enclave to get enclave hash
  170. int ret = load_enclave(parser.release(), metadata);
  171. close_handle(fh);
  172. switch(ret)
  173. {
  174. case SGX_ERROR_INVALID_METADATA:
  175. se_trace(SE_TRACE_ERROR, OUT_OF_EPC_ERROR);
  176. res = false;
  177. break;
  178. case SGX_ERROR_INVALID_VERSION:
  179. se_trace(SE_TRACE_ERROR, META_VERSION_ERROR);
  180. res = false;
  181. break;
  182. case SGX_ERROR_INVALID_ENCLAVE:
  183. se_trace(SE_TRACE_ERROR, INVALID_ENCLAVE_ERROR);
  184. res = false;
  185. break;
  186. case SGX_SUCCESS:
  187. ret = dynamic_cast<EnclaveCreatorST*>(get_enclave_creator())->get_enclave_info(hash, SGX_HASH_SIZE, &quota);
  188. if(ret != SGX_SUCCESS)
  189. {
  190. res = false;
  191. break;
  192. }
  193. se_trace(SE_TRACE_ERROR, REQUIRED_ENCLAVE_SIZE, quota);
  194. res = true;
  195. break;
  196. default:
  197. res = false;
  198. break;
  199. }
  200. return res;
  201. }
  202. //fill_enclave_css()
  203. // fill the enclave_css_t structure with enclave_hash
  204. // If the 'rsa' is not null, fill the key part
  205. // If the path[UNSIGNED] != NULL, update the header.date(CATSIG mode)
  206. static bool fill_enclave_css(const RSA *rsa, const char **path,
  207. const uint8_t *enclave_hash, enclave_css_t *css)
  208. {
  209. assert(enclave_hash != NULL && path != NULL && css != NULL);
  210. //if rsa is not NULL, fill the public key part
  211. if(rsa)
  212. {
  213. int exponent_size = BN_num_bytes(rsa->e);
  214. int modulus_size = BN_num_bytes(rsa->n);
  215. if(modulus_size > SE_KEY_SIZE)
  216. return false;
  217. unsigned char *modulus = (unsigned char *)malloc(SE_KEY_SIZE);
  218. if(modulus == NULL)
  219. {
  220. return false;
  221. }
  222. memset(modulus, 0, SE_KEY_SIZE);
  223. exponent_size = (uint32_t)(ROUND_TO(exponent_size, sizeof(uint32_t)) / sizeof(uint32_t));
  224. modulus_size = (uint32_t)(ROUND_TO(modulus_size, sizeof(uint32_t)) / sizeof(uint32_t));
  225. if(BN_bn2bin(rsa->n, modulus) != SE_KEY_SIZE)
  226. {
  227. free(modulus);
  228. return false;
  229. }
  230. if(BN_bn2bin(rsa->e, (unsigned char *)&css->key.exponent) != 1)
  231. {
  232. free(modulus);
  233. return false;
  234. }
  235. for(unsigned int i = 0; i < SE_KEY_SIZE; i++)
  236. {
  237. css->key.modulus[i] = modulus[SE_KEY_SIZE -i - 1];
  238. }
  239. free(modulus);
  240. assert(css->key.exponent[0] == 0x03);
  241. assert(exponent_size == 0x1);
  242. assert(modulus_size == 0x60);
  243. }
  244. // fill the enclave hash
  245. memcpy_s(&css->body.enclave_hash, sizeof(css->body.enclave_hash), enclave_hash, SGX_HASH_SIZE);
  246. if(path[UNSIGNED] != NULL)
  247. {
  248. // In catsig mode, update the header.date as the time when the unsigned file is generated.
  249. enclave_css_t enclave_css;
  250. memset(&enclave_css, 0, sizeof(enclave_css));
  251. size_t fsize = get_file_size(path[UNSIGNED]);
  252. if(fsize != sizeof(enclave_css.header) + sizeof(enclave_css.body))
  253. {
  254. se_trace(SE_TRACE_ERROR, UNSIGNED_FILE_ERROR, path[UNSIGNED]);
  255. return false;
  256. }
  257. uint8_t *buf = new uint8_t[fsize];
  258. memset(buf, 0, fsize);
  259. if(read_file_to_buf(path[UNSIGNED], buf, fsize) == false)
  260. {
  261. se_trace(SE_TRACE_ERROR, READ_FILE_ERROR, path[UNSIGNED]);
  262. delete [] buf;
  263. return false;
  264. }
  265. memcpy_s(&enclave_css.header, sizeof(enclave_css.header), buf, sizeof(enclave_css.header));
  266. memcpy_s(&enclave_css.body, sizeof(enclave_css.body), buf + sizeof(enclave_css.header), fsize - sizeof(enclave_css.header));
  267. delete [] buf;
  268. css->header.date = enclave_css.header.date;
  269. // Verify the header and body read from the unsigned file to make sure it's the same as that generated from xml file
  270. if(memcmp(&enclave_css.header, &css->header, sizeof(enclave_css.header)) || memcmp(&enclave_css.body, &css->body, sizeof(enclave_css.body)))
  271. {
  272. se_trace(SE_TRACE_ERROR, UNSIGNED_FILE_XML_MISMATCH);
  273. return false;
  274. }
  275. }
  276. return true;
  277. }
  278. static bool calc_RSAq1q2(int length_s, const uint8_t *data_s, int length_m, const uint8_t *data_m,
  279. uint8_t *data_q1, uint8_t *data_q2)
  280. {
  281. assert(data_s && data_m && data_q1 && data_q2);
  282. bool ret = false;
  283. BIGNUM *ptemp1=NULL, *ptemp2=NULL, *pQ1=NULL, *pQ2=NULL, *pM=NULL, *pS = NULL;
  284. unsigned char *q1 = NULL, *q2= NULL;
  285. BN_CTX *ctx = NULL;
  286. do{
  287. if((ptemp1 = BN_new()) == NULL)
  288. break;
  289. if((ptemp2 = BN_new()) == NULL)
  290. break;
  291. if((pQ1 = BN_new()) == NULL)
  292. break;
  293. if((pQ2 = BN_new()) == NULL)
  294. break;
  295. if((pM = BN_new()) == NULL)
  296. break;
  297. if((pS = BN_new()) == NULL)
  298. break;
  299. if(BN_bin2bn((const unsigned char *)data_m, length_m, pM) == NULL)
  300. break;
  301. if(BN_bin2bn((const unsigned char *)data_s, length_s, pS) == NULL)
  302. break;
  303. if((ctx = BN_CTX_new()) == NULL)
  304. break;
  305. //q1 = floor(signature*signature/modulus)
  306. //q2 = floor((signature*signature.signature - q1*signature*Modulus)/Modulus)
  307. if(BN_mul(ptemp1, pS, pS, ctx) != 1)
  308. break;
  309. if(BN_div(pQ1, ptemp2, ptemp1, pM, ctx) !=1)
  310. break;
  311. if(BN_mul(ptemp1, pS, ptemp2, ctx) !=1)
  312. break;
  313. if(BN_div(pQ2, ptemp2, ptemp1, pM, ctx) !=1)
  314. break;
  315. int q1_len = BN_num_bytes(pQ1);
  316. int q2_len = BN_num_bytes(pQ2);
  317. if((q1 = (unsigned char *)malloc(q1_len)) == NULL)
  318. break;
  319. if((q2 = (unsigned char *)malloc(q2_len)) == NULL)
  320. break;
  321. if(q1_len != BN_bn2bin(pQ1, (unsigned char *)q1))
  322. break;
  323. if(q2_len != BN_bn2bin(pQ2, (unsigned char *)q2))
  324. break;
  325. int size_q1 = (q1_len < SE_KEY_SIZE) ? q1_len : SE_KEY_SIZE;
  326. int size_q2 = (q2_len < SE_KEY_SIZE) ? q2_len : SE_KEY_SIZE;
  327. for(int i = 0; i < size_q1; i++)
  328. {
  329. data_q1[i] = q1[size_q1 - i -1];
  330. }
  331. for(int i = 0; i < size_q2; i++)
  332. {
  333. data_q2[i] = q2[size_q2 - i -1];
  334. }
  335. ret = true;
  336. }while(0);
  337. if(q1)
  338. free(q1);
  339. if(q2)
  340. free(q2);
  341. if(ptemp1)
  342. BN_clear_free(ptemp1);
  343. if(ptemp2)
  344. BN_clear_free(ptemp2);
  345. if(pQ1)
  346. BN_clear_free(pQ1);
  347. if(pQ2)
  348. BN_clear_free(pQ2);
  349. if(pS)
  350. BN_clear_free(pS);
  351. if(pM)
  352. BN_clear_free(pM);
  353. if(ctx)
  354. BN_CTX_free(ctx);
  355. return ret;
  356. }
  357. static bool create_signature(const RSA *rsa, const char *sigpath, enclave_css_t *enclave_css)
  358. {
  359. assert(enclave_css != NULL);
  360. assert(!(rsa == NULL && sigpath == NULL) && !(rsa != NULL && sigpath != NULL));
  361. uint8_t signature[SIGNATURE_SIZE]; // keep the signature in big endian
  362. memset(signature, 0, SIGNATURE_SIZE);
  363. //**********get the signature*********
  364. if(sigpath != NULL)//CATSIG mode
  365. {
  366. if(get_file_size(sigpath) != SIGNATURE_SIZE)
  367. {
  368. se_trace(SE_TRACE_ERROR, SIG_FILE_ERROR, sigpath);
  369. return false;
  370. }
  371. if(read_file_to_buf(sigpath, signature, SIGNATURE_SIZE) == false)
  372. {
  373. se_trace(SE_TRACE_ERROR, READ_FILE_ERROR, sigpath);
  374. return false;
  375. }
  376. }
  377. else //SIGN mode
  378. {
  379. size_t buffer_size = sizeof(enclave_css->header) + sizeof(enclave_css->body);
  380. uint8_t * temp_buffer = (uint8_t *)malloc(buffer_size * sizeof(char));
  381. if(NULL == temp_buffer)
  382. {
  383. se_trace(SE_TRACE_ERROR, NO_MEMORY_ERROR);
  384. return false;
  385. }
  386. memcpy_s(temp_buffer, buffer_size, &enclave_css->header, sizeof(enclave_css->header));
  387. memcpy_s(temp_buffer + sizeof(enclave_css->header), buffer_size - sizeof(enclave_css->header),
  388. &enclave_css->body, sizeof(enclave_css->body));
  389. uint8_t hash[SGX_HASH_SIZE] = {0};
  390. unsigned int hash_size = SGX_HASH_SIZE;
  391. if(SGX_SUCCESS != sgx_EVP_Digest(EVP_sha256(), temp_buffer, (unsigned int)buffer_size, hash, &hash_size))
  392. {
  393. free(temp_buffer);
  394. return false;
  395. }
  396. size_t siglen;
  397. int ret = RSA_sign(NID_sha256, hash, hash_size, signature, (unsigned int *)&siglen, const_cast<RSA *>(rsa));
  398. free(temp_buffer);
  399. if(ret != 1)
  400. return false;
  401. }
  402. for(int i = 0; i<SIGNATURE_SIZE; i++)
  403. {
  404. (enclave_css->key.signature)[i] = signature[SIGNATURE_SIZE-1-i];
  405. }
  406. //************************calculate q1 and q2*********************
  407. uint8_t modulus[SE_KEY_SIZE];
  408. for(int i = 0; i<SE_KEY_SIZE; i++)
  409. {
  410. modulus[i] = enclave_css->key.modulus[SE_KEY_SIZE-1-i];
  411. }
  412. bool res = calc_RSAq1q2(sizeof(enclave_css->key.signature),
  413. (const uint8_t *)signature,
  414. sizeof(enclave_css->key.modulus),
  415. (const uint8_t *)modulus,
  416. (uint8_t *)enclave_css->buffer.q1,
  417. (uint8_t *)enclave_css->buffer.q2);
  418. return res;
  419. }
  420. static bool verify_signature(const RSA *rsa, const enclave_css_t *enclave_css)
  421. {
  422. assert(rsa != NULL && enclave_css != NULL);
  423. size_t buffer_size = sizeof(enclave_css->header) + sizeof(enclave_css->body);
  424. uint8_t *temp_buffer = (uint8_t *)malloc(buffer_size * sizeof(char));
  425. if(NULL == temp_buffer)
  426. {
  427. se_trace(SE_TRACE_ERROR, NO_MEMORY_ERROR);
  428. return false;
  429. }
  430. memcpy_s(temp_buffer, buffer_size, &enclave_css->header, sizeof(enclave_css->header));
  431. memcpy_s(temp_buffer + sizeof(enclave_css->header), buffer_size-sizeof(enclave_css->header),
  432. &enclave_css->body, sizeof(enclave_css->body));
  433. uint8_t hash[SGX_HASH_SIZE] = {0};
  434. unsigned int hash_size = SGX_HASH_SIZE;
  435. if(SGX_SUCCESS != sgx_EVP_Digest(EVP_sha256(), temp_buffer, (unsigned int)buffer_size, hash, &hash_size))
  436. {
  437. free(temp_buffer);
  438. return false;
  439. }
  440. free(temp_buffer);
  441. uint8_t signature[SIGNATURE_SIZE];
  442. for(int i=0; i<SIGNATURE_SIZE; i++)
  443. {
  444. signature[i] = enclave_css->key.signature[SIGNATURE_SIZE-1-i];
  445. }
  446. if(1 != RSA_verify(NID_sha256, hash, hash_size, signature, SIGNATURE_SIZE, const_cast<RSA *>(rsa)))
  447. {
  448. return false;
  449. }
  450. return true;
  451. }
  452. static bool gen_enclave_signing_file(const enclave_css_t *enclave_css, const char *outpath)
  453. {
  454. assert(enclave_css != NULL);
  455. size_t size = sizeof(enclave_css->header) + sizeof(enclave_css->body);
  456. uint8_t *buffer = (uint8_t *)malloc(size);
  457. if(buffer == NULL)
  458. {
  459. se_trace(SE_TRACE_ERROR, NO_MEMORY_ERROR);
  460. return false;
  461. }
  462. memcpy_s(buffer, sizeof(enclave_css->header), &enclave_css->header, sizeof(enclave_css->header));
  463. memcpy_s(buffer + sizeof(enclave_css->header), sizeof(enclave_css->body), &enclave_css->body, sizeof(enclave_css->body));
  464. if(write_data_to_file(outpath, std::ios::out|std::ios::binary, buffer, size) == false)
  465. {
  466. free(buffer);
  467. return false;
  468. }
  469. free(buffer);
  470. return true;
  471. }
  472. static bool cmdline_parse(unsigned int argc, char *argv[], int *mode, const char **path, bool *ignore_rel_error)
  473. {
  474. assert(mode!=NULL && path != NULL);
  475. if(argc<2)
  476. {
  477. se_trace(SE_TRACE_ERROR, LACK_PARA_ERROR);
  478. return false;
  479. }
  480. if(argc == 2 && !STRCMP(argv[1], "-help"))
  481. {
  482. se_trace(SE_TRACE_ERROR, USAGE_STRING);
  483. *mode = -1;
  484. return true;
  485. }
  486. if(argc == 2 && !STRCMP(argv[1], "-version"))
  487. {
  488. se_trace(SE_TRACE_ERROR, VERSION_STRING, STRFILEVER, COPYRIGHT);
  489. *mode = -1;
  490. return true;
  491. }
  492. enum { PAR_REQUIRED, PAR_OPTIONAL, PAR_INVALID };
  493. typedef struct _param_struct_{
  494. const char *name; //options
  495. char *value; //keep the path
  496. int flag; //indicate this parameter is required(0), optional(1) or invalid(2)
  497. }param_struct_t; //keep the parameter pairs
  498. param_struct_t params_sign[] = {
  499. {"-enclave", NULL, PAR_REQUIRED},
  500. {"-config", NULL, PAR_OPTIONAL},
  501. {"-key", NULL, PAR_REQUIRED},
  502. {"-out", NULL, PAR_REQUIRED},
  503. {"-sig", NULL, PAR_INVALID},
  504. {"-unsigned", NULL, PAR_INVALID},
  505. {"-review_enclave", NULL, PAR_INVALID},
  506. {"-dumpfile", NULL, PAR_OPTIONAL}};
  507. param_struct_t params_gendata[] = {
  508. {"-enclave", NULL, PAR_REQUIRED},
  509. {"-config", NULL, PAR_OPTIONAL},
  510. {"-key", NULL, PAR_INVALID},
  511. {"-out", NULL, PAR_REQUIRED},
  512. {"-sig", NULL, PAR_INVALID},
  513. {"-unsigned", NULL, PAR_INVALID},
  514. {"-review_enclave", NULL, PAR_INVALID},
  515. {"-dumpfile", NULL, PAR_INVALID}};
  516. param_struct_t params_catsig[] = {
  517. {"-enclave", NULL, PAR_REQUIRED},
  518. {"-config", NULL, PAR_OPTIONAL},
  519. {"-key", NULL, PAR_REQUIRED},
  520. {"-out", NULL, PAR_REQUIRED},
  521. {"-sig", NULL, PAR_REQUIRED},
  522. {"-unsigned", NULL, PAR_REQUIRED},
  523. {"-review_enclave", NULL, PAR_INVALID},
  524. {"-dumpfile", NULL, PAR_OPTIONAL}};
  525. param_struct_t params_dump[] = {
  526. {"-enclave", NULL, PAR_REQUIRED},
  527. {"-config", NULL, PAR_INVALID},
  528. {"-key", NULL, PAR_INVALID},
  529. {"-out", NULL, PAR_INVALID},
  530. {"-sig", NULL, PAR_INVALID},
  531. {"-unsigned", NULL, PAR_INVALID},
  532. {"-review_enclave", NULL, PAR_INVALID},
  533. {"-dumpfile", NULL, PAR_REQUIRED}};
  534. const char *mode_m[] ={"sign", "gendata","catsig", "dump"};
  535. param_struct_t *params[] = {params_sign, params_gendata, params_catsig, params_dump};
  536. unsigned int tempidx=0;
  537. for(; tempidx<sizeof(mode_m)/sizeof(mode_m[0]); tempidx++)
  538. {
  539. if(!STRCMP(mode_m[tempidx], argv[1]))//match
  540. {
  541. break;
  542. }
  543. }
  544. unsigned int tempmode = tempidx;
  545. if(tempmode>=sizeof(mode_m)/sizeof(mode_m[0]))
  546. {
  547. se_trace(SE_TRACE_ERROR, UNREC_CMD_ERROR, argv[1]);
  548. return false;
  549. }
  550. unsigned int err_idx = 2;
  551. for(; err_idx < argc; err_idx++)
  552. {
  553. if(!STRCMP(argv[err_idx], "-ignore-rel-error"))
  554. break;
  555. }
  556. unsigned int params_count = (unsigned)(sizeof(params_sign)/sizeof(params_sign[0]));
  557. unsigned int params_count_min = 0;
  558. unsigned int params_count_max =0;
  559. for(unsigned int i=0; i< params_count; i++)
  560. {
  561. params_count_max ++;
  562. if(params[tempmode][i].flag == PAR_REQUIRED)
  563. params_count_min ++;
  564. }
  565. unsigned int additional_param = 2;
  566. if(err_idx != argc)
  567. additional_param++;
  568. if(argc<params_count_min * 2 + additional_param)
  569. return false;
  570. if(argc>params_count_max * 2 + additional_param)
  571. return false;
  572. for(unsigned int i=2; i<argc; i=i+2)
  573. {
  574. if(i == err_idx)
  575. {
  576. i++;
  577. continue;
  578. }
  579. unsigned int j=0;
  580. for(; j<params_count; j++)
  581. {
  582. if(STRCMP(argv[i], params[tempmode][j].name)==0) //match
  583. {
  584. if((i<argc-1)&&(STRNCMP(argv[i+1],"-", 1))) // assuming pathname doesn't contain "-"
  585. {
  586. if(params[tempmode][j].value != NULL)
  587. {
  588. se_trace(SE_TRACE_ERROR, REPEAT_OPTION_ERROR, params[tempmode][j].name);
  589. return false;
  590. }
  591. params[tempmode][j].value = argv[i+1];
  592. break;
  593. }
  594. else //didn't match: 1) no path parameter behind option parameter 2) parameters format error.
  595. {
  596. se_trace(SE_TRACE_ERROR, INVALID_FILE_NAME_ERROR, params[tempmode][j].name);
  597. return false;
  598. }
  599. }
  600. }
  601. if(j>=params_count_max)
  602. {
  603. return false;
  604. }
  605. }
  606. for(unsigned int i = 0; i < params_count; i ++)
  607. {
  608. if(params[tempmode][i].flag == PAR_REQUIRED && params[tempmode][i].value == NULL)
  609. {
  610. se_trace(SE_TRACE_ERROR, LACK_REQUIRED_OPTION_ERROR, params[tempmode][i].name, mode_m[tempmode]);
  611. return false;
  612. }
  613. if(params[tempmode][i].flag == PAR_INVALID && params[tempmode][i].value != NULL)
  614. {
  615. se_trace(SE_TRACE_ERROR, GIVE_INVALID_OPTION_ERROR, params[tempmode][i].name, mode_m[tempmode]);
  616. return false;
  617. }
  618. }
  619. for(unsigned int i = 0; i < params_count; i++)
  620. {
  621. path[i] = params[tempmode][i].value;
  622. }
  623. *mode = tempmode;
  624. if(err_idx != argc)
  625. *ignore_rel_error = true;
  626. return true;
  627. }
  628. //generate_output:
  629. // To generate the final output file
  630. // SIGN- need to fill the enclave_css_t(key part included), sign the header and body and
  631. // update the metadata in the out file
  632. // GENDATA- need to fill the enclave_css_t(key part excluded), get the body and header,
  633. // and then write the whole out file with body+header+hash
  634. // CATSIG- need to fill the enclave_css_t(include key), read the signature from the sigpath,
  635. // and then update the metadata in the out file
  636. static bool generate_output(int mode, int ktype, const uint8_t *enclave_hash, const RSA *rsa, metadata_t *metadata,
  637. const char **path)
  638. {
  639. assert(enclave_hash != NULL && metadata != NULL && path != NULL);
  640. switch(mode)
  641. {
  642. case SIGN:
  643. {
  644. if(ktype != PRIVATE_KEY || !rsa)
  645. {
  646. se_trace(SE_TRACE_ERROR, LACK_PRI_KEY_ERROR);
  647. return false;
  648. }
  649. if(false == fill_enclave_css(rsa, path, enclave_hash, &(metadata->enclave_css)))
  650. {
  651. return false;
  652. }
  653. if(false == create_signature(rsa, NULL, &(metadata->enclave_css)))
  654. {
  655. return false;
  656. }
  657. break;
  658. }
  659. case GENDATA:
  660. {
  661. if(false == fill_enclave_css(NULL, path, enclave_hash, &(metadata->enclave_css)))
  662. {
  663. return false;
  664. }
  665. if(false == gen_enclave_signing_file(&(metadata->enclave_css), path[OUTPUT]))
  666. {
  667. return false;
  668. }
  669. break;
  670. }
  671. case CATSIG:
  672. {
  673. if(ktype != PUBLIC_KEY || !rsa)
  674. {
  675. se_trace(SE_TRACE_ERROR, LACK_PUB_KEY_ERROR);
  676. return false;
  677. }
  678. if(false == fill_enclave_css(rsa, path, enclave_hash, &(metadata->enclave_css)))
  679. {
  680. return false;
  681. }
  682. if(false == create_signature(NULL, path[SIG], &(metadata->enclave_css)))
  683. {
  684. return false;
  685. }
  686. break;
  687. }
  688. default:
  689. {
  690. return false;
  691. }
  692. }
  693. return true;
  694. }
  695. #include "se_page_attr.h"
  696. static void metadata_cleanup(metadata_t *metadata, uint32_t size_to_reduce)
  697. {
  698. metadata->dirs[DIR_LAYOUT].size -= size_to_reduce;
  699. metadata->size -= size_to_reduce;
  700. //if there exists LAYOUT_ID_HEAP_MAX, modify it so that it won't be included in the MRENCLAVE
  701. layout_t *start = GET_PTR(layout_t, metadata, metadata->dirs[DIR_LAYOUT].offset);
  702. layout_t *end = GET_PTR(layout_t, start, metadata->dirs[DIR_LAYOUT].size);
  703. for (layout_t *l = start; l < end; l++)
  704. {
  705. if (l->entry.id == LAYOUT_ID_HEAP_MAX)
  706. {
  707. l->entry.si_flags = SI_FLAG_NONE;
  708. l->entry.attributes &= (uint16_t)(~PAGE_ATTR_POST_ADD);
  709. break;
  710. }
  711. }
  712. //remove the PAGE_ATTR_POST_ADD attribute so that dynamic range won't be
  713. //created during enclave loading time
  714. for (layout_t *l = start; l < end; l++)
  715. {
  716. if (l->entry.id == LAYOUT_ID_HEAP_INIT)
  717. {
  718. l->entry.attributes &= (uint16_t)(~PAGE_ATTR_POST_ADD);
  719. break;
  720. }
  721. }
  722. }
  723. static bool append_compatible_metadata(metadata_t *compat_metadata, metadata_t *metadata)
  724. {
  725. metadata_t *dest_meta = metadata;
  726. uint32_t size = 0;
  727. do{
  728. if(dest_meta->magic_num != METADATA_MAGIC || dest_meta->size == 0)
  729. break;
  730. size += dest_meta->size;
  731. if(size < dest_meta->size)
  732. return false;
  733. dest_meta = (metadata_t *)((size_t)dest_meta + dest_meta->size);
  734. } while(size < METADATA_SIZE);
  735. if(size + compat_metadata->size < size ||
  736. size + compat_metadata->size < compat_metadata->size ||
  737. size + compat_metadata->size > METADATA_SIZE)
  738. return false;
  739. if(memcpy_s(dest_meta, METADATA_SIZE - size , compat_metadata, compat_metadata->size))
  740. return false;
  741. return true;
  742. }
  743. static bool generate_compatible_metadata(metadata_t *metadata)
  744. {
  745. metadata_t *metadata2 = (metadata_t *)malloc(metadata->size);
  746. if(!metadata2)
  747. {
  748. se_trace(SE_TRACE_ERROR, NO_MEMORY_ERROR);
  749. return false;
  750. }
  751. // append 2_0 metadata
  752. memcpy(metadata2, metadata, metadata->size);
  753. metadata2->version = META_DATA_MAKE_VERSION(SGX_2_0_MAJOR_VERSION,SGX_2_0_MINOR_VERSION);
  754. if (!append_compatible_metadata(metadata2, metadata))
  755. {
  756. free(metadata2);
  757. return false;
  758. }
  759. // append 1_9 metadata
  760. metadata2->version = META_DATA_MAKE_VERSION(SGX_1_9_MAJOR_VERSION,SGX_1_9_MINOR_VERSION);
  761. layout_t *start = GET_PTR(layout_t, metadata2, metadata2->dirs[DIR_LAYOUT].offset);
  762. layout_t *end = GET_PTR(layout_t, start, metadata2->dirs[DIR_LAYOUT].size);
  763. layout_t tmp_layout, *first_dyn_entry = NULL, *first = NULL, *utility_td = NULL;
  764. uint32_t size_to_reduce = 0;
  765. bool ret = false;
  766. for (layout_t *l = start; l < end; l++)
  767. {
  768. if ((l->entry.id == LAYOUT_ID_STACK_DYN_MAX) ||
  769. (l->entry.id == LAYOUT_ID_STACK_DYN_MIN))
  770. {
  771. first_dyn_entry = l;
  772. break;
  773. }
  774. }
  775. if (first_dyn_entry == NULL)
  776. {
  777. ret = append_compatible_metadata(metadata2, metadata);
  778. free(metadata2);
  779. return ret;
  780. }
  781. //sizeof(layout_t) for the guard page before LAYOUT_ID_STACK_DYN_MAX
  782. size_to_reduce = (uint32_t)((size_t)end - (size_t)first_dyn_entry + sizeof(layout_t));
  783. layout_t *last = &first_dyn_entry[-2];
  784. for (layout_t *l = start; l <= last; l++)
  785. {
  786. if (l->entry.id == LAYOUT_ID_TD)
  787. {
  788. utility_td = l;
  789. break;
  790. }
  791. }
  792. assert(utility_td != NULL);
  793. //Besides dynamic threads, there's only a single utility thread
  794. if (utility_td == last)
  795. {
  796. metadata_cleanup(metadata2, size_to_reduce);
  797. ret = append_compatible_metadata(metadata2, metadata);
  798. free(metadata2);
  799. return ret;
  800. }
  801. //We have some static threads
  802. first = &utility_td[1];
  803. if (first->group.id == LAYOUT_ID_THREAD_GROUP)
  804. {
  805. if (last->group.id == LAYOUT_ID_THREAD_GROUP)
  806. {
  807. //utility thread | thread group for min pool | eremove thread | eremove thread group
  808. if (first != last)
  809. first->group.load_times += last->group.load_times + 1;
  810. //utility thread | thread group for min pool
  811. }
  812. //utility thread | thread group for min pool | eremove thread
  813. else
  814. {
  815. first->group.load_times += 1;
  816. }
  817. size_to_reduce += (uint32_t)((size_t)last - (size_t)first);
  818. }
  819. else
  820. {
  821. memset(&tmp_layout, 0, sizeof(tmp_layout));
  822. tmp_layout.group.id = LAYOUT_ID_THREAD_GROUP;
  823. //utility thread | eremove thread | eremove thread group
  824. if (last->group.id == LAYOUT_ID_THREAD_GROUP)
  825. {
  826. tmp_layout.group.entry_count = (uint16_t)(((size_t)last - (size_t)first) / sizeof(layout_t));
  827. tmp_layout.group.load_times = last->group.load_times + 1;
  828. }
  829. //utility thread | eremove thread
  830. else
  831. {
  832. tmp_layout.group.entry_count = (uint16_t)(((size_t)last - (size_t)first) / sizeof(layout_t) + 1);
  833. tmp_layout.group.load_times = 1;
  834. }
  835. for (uint32_t i = 0; i < tmp_layout.group.entry_count; i++)
  836. {
  837. tmp_layout.group.load_step += (((uint64_t)first[i].entry.page_count) << SE_PAGE_SHIFT);
  838. }
  839. memcpy_s(first, sizeof(layout_t), &tmp_layout, sizeof(layout_t));
  840. size_to_reduce += (uint32_t)((size_t)last - (size_t)first);
  841. }
  842. metadata_cleanup(metadata2, size_to_reduce);
  843. ret = append_compatible_metadata(metadata2, metadata);
  844. free(metadata2);
  845. return ret;
  846. }
  847. static bool dump_enclave_metadata(const char *enclave_path, const char *dumpfile_path)
  848. {
  849. assert(enclave_path != NULL && dumpfile_path != NULL);
  850. uint64_t meta_offset = 0;
  851. bin_fmt_t bin_fmt = BF_UNKNOWN;
  852. uint32_t file_size = 0;
  853. se_file_handle_t fh = open_file(enclave_path);
  854. if (fh == THE_INVALID_HANDLE)
  855. {
  856. se_trace(SE_TRACE_ERROR, OPEN_FILE_ERROR, enclave_path);
  857. return false;
  858. }
  859. std::unique_ptr<map_handle_t, void (*)(map_handle_t*)> mh(map_file(fh, &file_size), unmap_file);
  860. if (!mh)
  861. {
  862. close_handle(fh);
  863. return false;
  864. }
  865. // Parse enclave
  866. std::unique_ptr<BinParser> parser(binparser::get_parser(mh->base_addr, (size_t)file_size));
  867. assert(parser != NULL);
  868. sgx_status_t status = parser->run_parser();
  869. if (status != SGX_SUCCESS)
  870. {
  871. se_trace(SE_TRACE_ERROR, INVALID_ENCLAVE_ERROR);
  872. close_handle(fh);
  873. return false;
  874. }
  875. // Collect enclave info
  876. if(get_enclave_info(parser.get(), &bin_fmt, &meta_offset, true) == false)
  877. {
  878. close_handle(fh);
  879. return false;
  880. }
  881. const metadata_t *metadata = GET_PTR(metadata_t, mh->base_addr, meta_offset);
  882. if(print_metadata(dumpfile_path, metadata) == false)
  883. {
  884. close_handle(fh);
  885. remove(dumpfile_path);
  886. return false;
  887. }
  888. close_handle(fh);
  889. return true;
  890. }
  891. int main(int argc, char* argv[])
  892. {
  893. xml_parameter_t parameter[] = {{"ProdID", 0xFFFF, 0, 0, 0},
  894. {"ISVSVN", 0xFFFF, 0, 0, 0},
  895. {"ReleaseType", 1, 0, 0, 0},
  896. {"IntelSigned", 1, 0, 0, 0},
  897. {"ProvisionKey",1,0,0,0},
  898. {"LaunchKey",1,0,0,0},
  899. {"DisableDebug",1,0,0,0},
  900. {"HW", 0x10,0,0,0},
  901. {"TCSNum",0xFFFFFFFF,TCS_NUM_MIN,TCS_NUM_MIN,0},
  902. {"TCSMaxNum",0xFFFFFFFF,TCS_NUM_MIN,TCS_NUM_MIN,0},
  903. {"TCSMinPool",0xFFFFFFFF,0,TCS_NUM_MIN,0},
  904. {"TCSPolicy",TCS_POLICY_UNBIND,TCS_POLICY_BIND,TCS_POLICY_UNBIND,0},
  905. {"StackMaxSize",0x1FFFFFFFFF,STACK_SIZE_MIN,STACK_SIZE_MAX,0},
  906. {"StackMinSize",0x1FFFFFFFFF,STACK_SIZE_MIN,STACK_SIZE_MIN,0},
  907. {"HeapMaxSize",0x1FFFFFFFFF,0,HEAP_SIZE_MAX,0},
  908. {"HeapMinSize",0x1FFFFFFFFF,0,HEAP_SIZE_MIN,0},
  909. {"HeapInitSize",0x1FFFFFFFFF,0,HEAP_SIZE_MIN,0},
  910. {"MiscSelect", 0xFFFFFFFF, 0, DEFAULT_MISC_SELECT, 0},
  911. {"MiscMask", 0xFFFFFFFF, 0, DEFAULT_MISC_MASK, 0}};
  912. const char *path[8] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
  913. uint8_t enclave_hash[SGX_HASH_SIZE] = {0};
  914. uint8_t metadata_raw[METADATA_SIZE];
  915. metadata_t *metadata = (metadata_t*)metadata_raw;
  916. int res = -1, mode = -1;
  917. int key_type = UNIDENTIFIABLE_KEY; //indicate the type of the input key file
  918. size_t parameter_count = sizeof(parameter)/sizeof(parameter[0]);
  919. uint64_t meta_offset = 0;
  920. bool ignore_rel_error = false;
  921. RSA *rsa = NULL;
  922. memset(&metadata_raw, 0, sizeof(metadata_raw));
  923. OpenSSL_add_all_algorithms();
  924. ERR_load_crypto_strings();
  925. //Parse command line
  926. if(cmdline_parse(argc, argv, &mode, path, &ignore_rel_error) == false)
  927. {
  928. se_trace(SE_TRACE_ERROR, USAGE_STRING);
  929. goto clear_return;
  930. }
  931. if(mode == -1) // User only wants to get the help info or version info
  932. {
  933. res = 0;
  934. goto clear_return;
  935. }
  936. else if(mode == DUMP)
  937. {
  938. // dump metadata info
  939. if(dump_enclave_metadata(path[DLL], path[DUMPFILE]) == false)
  940. {
  941. se_trace(SE_TRACE_ERROR, DUMP_METADATA_ERROR, path[DUMPFILE]);
  942. goto clear_return;
  943. }
  944. else
  945. {
  946. se_trace(SE_TRACE_ERROR, SUCCESS_EXIT);
  947. res = 0;
  948. goto clear_return;
  949. }
  950. }
  951. //Other modes
  952. //
  953. //Parse the xml file to get the metadata
  954. if(parse_metadata_file(path[XML], parameter, (int)parameter_count) == false)
  955. {
  956. goto clear_return;
  957. }
  958. //Parse the key file
  959. if(parse_key_file(mode, path[KEY], &rsa, &key_type) == false && key_type != NO_KEY)
  960. {
  961. goto clear_return;
  962. }
  963. if(copy_file(path[DLL], path[OUTPUT]) == false)
  964. {
  965. se_trace(SE_TRACE_ERROR, OVERALL_ERROR);
  966. goto clear_return;
  967. }
  968. ignore_rel_error = true;
  969. if(measure_enclave(enclave_hash, path[OUTPUT], parameter, ignore_rel_error, metadata, &meta_offset) == false)
  970. {
  971. se_trace(SE_TRACE_ERROR, OVERALL_ERROR);
  972. goto clear_return;
  973. }
  974. if((generate_output(mode, key_type, enclave_hash, rsa, metadata, path)) == false)
  975. {
  976. se_trace(SE_TRACE_ERROR, OVERALL_ERROR);
  977. goto clear_return;
  978. }
  979. //to verify
  980. if(mode == SIGN || mode == CATSIG)
  981. {
  982. if(verify_signature(rsa, &(metadata->enclave_css)) == false)
  983. {
  984. se_trace(SE_TRACE_ERROR, OVERALL_ERROR);
  985. goto clear_return;
  986. }
  987. if(false == generate_compatible_metadata(metadata))
  988. {
  989. se_trace(SE_TRACE_ERROR, OVERALL_ERROR);
  990. goto clear_return;
  991. }
  992. if(false == update_metadata(path[OUTPUT], metadata, meta_offset))
  993. {
  994. se_trace(SE_TRACE_ERROR, OVERALL_ERROR);
  995. goto clear_return;
  996. }
  997. }
  998. if(path[DUMPFILE] != NULL)
  999. {
  1000. if(print_metadata(path[DUMPFILE], metadata) == false)
  1001. {
  1002. se_trace(SE_TRACE_ERROR, DUMP_METADATA_ERROR, path[DUMPFILE]);
  1003. goto clear_return;
  1004. }
  1005. }
  1006. se_trace(SE_TRACE_ERROR, SUCCESS_EXIT);
  1007. res = 0;
  1008. clear_return:
  1009. if(rsa)
  1010. RSA_free(rsa);
  1011. if(res == -1 && path[OUTPUT])
  1012. remove(path[OUTPUT]);
  1013. if(res == -1 && path[DUMPFILE])
  1014. remove(path[DUMPFILE]);
  1015. EVP_cleanup();
  1016. CRYPTO_cleanup_all_ex_data();
  1017. ERR_remove_thread_state(NULL);
  1018. ERR_free_strings();
  1019. return res;
  1020. }