pcl_entry.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  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. #include <stdint.h>
  32. #include <stdlib.h>
  33. #include <sgx_tseal.h>
  34. #include <sgx_lfence.h>
  35. #include <pcl_common.h>
  36. #include <pcl_internal.h>
  37. /*
  38. * g_tbl holds the PCL table. Its content is set by enclave encryption tool at build time
  39. * It is located in its own section (PCLTBL_SECTION_NAME) so that
  40. * enclave encryption tool can find it.
  41. */
  42. pcl_table_t g_tbl __attribute__((section(PCLTBL_SECTION_NAME))) = {PCL_PLAIN};
  43. /*
  44. * g_pcl_imagebase is set at runtime to ELF base address.
  45. * It is used by functions pcl_is_outside_enclave and pcl_is_within_enclave
  46. */
  47. uintptr_t g_pcl_imagebase = 0;
  48. /*
  49. * @func pcl_entry is the PCL entry point. It is called from init_enclave in
  50. * trusted runtime entry point. It extracts the decryption key from the sealed blob
  51. * and use it to decrypt the encrypted portions of the enclave binary.
  52. * @param INOUT void* elf_base, base address of enclave
  53. * @param IN void* sealed_blob, the sealed blob
  54. * @return sgx_status_t
  55. * SGX_ERROR_UNEXPECTED if
  56. * 1. Table inconsistencies:
  57. * a. PCL state in PCL table is not PCL_CIPHER
  58. * b. PCL_SEALED_BLOB_MAX_SIZE < tbl->sealed_blob_size
  59. * 2. pcl_unseal_data returns incorrect values for either guid size or key size
  60. * Respective error returned from pcl_unseal_data, pcl_sha256, pcl_gcm_decrypt or pcl_increment_iv
  61. * SGX_SUCCESS if successfull
  62. */
  63. sgx_status_t pcl_entry(void* elf_base, void* sealed_blob)
  64. {
  65. sgx_status_t ret = SGX_SUCCESS;
  66. pcl_table_t* tbl = &g_tbl;
  67. unsigned char* iv = NULL;
  68. int memcmpret = 0;
  69. sgx_sha256_hash_t hash = {0};
  70. sgx_aes_gcm_128bit_key_t key = {0};
  71. // Verify PCL state:
  72. if(PCL_CIPHER != tbl->pcl_state)
  73. {
  74. return SGX_ERROR_UNEXPECTED;
  75. }
  76. tbl->pcl_state = PCL_RUNNING;
  77. // ELF base address used by pcl_is_outside_enclave and pcl_is_within_enclave
  78. g_pcl_imagebase = (uintptr_t)elf_base;
  79. // Get key from sealed blob:
  80. uint32_t guid_size = SGX_PCL_GUID_SIZE;
  81. uint32_t key_size = SGX_AESGCM_KEY_SIZE;
  82. // Verify the buffer size:
  83. if(PCL_SEALED_BLOB_SIZE != tbl->sealed_blob_size)
  84. {
  85. return SGX_ERROR_UNEXPECTED;
  86. }
  87. if(!(pcl_is_outside_enclave(sealed_blob, PCL_SEALED_BLOB_SIZE)))
  88. {
  89. return SGX_ERROR_UNEXPECTED;
  90. }
  91. // LFENCE after boundary check
  92. sgx_lfence();
  93. // Copy sealed blob into enclave binary.
  94. pcl_memcpy(tbl->sealed_blob, sealed_blob, PCL_SEALED_BLOB_SIZE);
  95. // Unseal the sealed blob:
  96. ret = pcl_unseal_data(
  97. (const sgx_sealed_data_t*)tbl->sealed_blob, // Sealed data
  98. tbl->pcl_guid, // AAD buffer
  99. &guid_size, // pointer to AAD buffer length
  100. key, // Resulting key
  101. &key_size); // Size of resulting key
  102. if(SGX_SUCCESS != ret)
  103. {
  104. goto Label_erase_key;
  105. }
  106. if((sizeof(tbl->pcl_guid) != guid_size) ||
  107. (sizeof(key) != key_size ))
  108. {
  109. ret = SGX_ERROR_UNEXPECTED;
  110. goto Label_erase_key;
  111. }
  112. // Verify key hash matches:
  113. ret = pcl_sha256(key, SGX_AESGCM_KEY_SIZE, hash);
  114. if(SGX_SUCCESS != ret)
  115. {
  116. goto Label_erase_key;
  117. }
  118. memcmpret = pcl_consttime_memequal(hash, tbl->decryption_key_hash, sizeof(sgx_sha256_hash_t));
  119. pcl_volatile_memset((volatile void*)hash, 0, sizeof(sgx_sha256_hash_t)); // Scrub hash
  120. if(1 != memcmpret)
  121. {
  122. ret = SGX_ERROR_PCL_SHA_MISMATCH;
  123. goto Label_erase_key;
  124. }
  125. for(uint32_t i = 0;i< tbl->num_rvas;i++)
  126. {
  127. size_t size = tbl->rvas_sizes_tags_ivs[i].size;
  128. unsigned char* ciphertext = (unsigned char *)((uint64_t)elf_base + tbl->rvas_sizes_tags_ivs[i].rva);
  129. unsigned char* plaintext = ciphertext; // decrypt in place
  130. unsigned char* tag = (unsigned char *)&(tbl->rvas_sizes_tags_ivs[i].tag);
  131. unsigned char* iv = (unsigned char *)&(tbl->rvas_sizes_tags_ivs[i].iv.val);
  132. // Verify ciphertext is inside the enclave:
  133. if(!(pcl_is_within_enclave(ciphertext, size)))
  134. {
  135. ret = SGX_ERROR_UNEXPECTED;
  136. goto Label_erase_key;
  137. }
  138. ret = pcl_gcm_decrypt(plaintext, ciphertext, size, NULL, 0, key, iv, tag);
  139. if(SGX_SUCCESS != ret)
  140. {
  141. goto Label_erase_key;
  142. }
  143. }
  144. // Return success:
  145. ret = SGX_SUCCESS;
  146. Label_erase_key:
  147. // Erase key:
  148. pcl_volatile_memset((volatile void*)key, 0, sizeof(sgx_aes_gcm_128bit_key_t));
  149. tbl->pcl_state = PCL_DONE;
  150. return ret;
  151. }
  152. /*
  153. * @func pcl_bswap32 swaps a 32bit value endianity
  154. * @param uint32_t val, input value
  155. * @return uint32_t, val in opposite endianity
  156. */
  157. uint32_t pcl_bswap32(uint32_t val)
  158. {
  159. uint32_t ret=(val);
  160. asm ("bswap %0":"+r"(ret));
  161. return ret;
  162. }