|  | @@ -88,24 +88,27 @@ uint64_t sgx_copy_to_enclave(const void* ptr, uint64_t maxsize, const void* uptr
 | 
	
		
			
				|  |  |      return usize;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -int sgx_get_report (sgx_arch_hash_t * mrenclave,
 | 
	
		
			
				|  |  | -                    sgx_arch_attributes_t * attributes,
 | 
	
		
			
				|  |  | -                    void * enclave_data,
 | 
	
		
			
				|  |  | -                    sgx_arch_report_t * report)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -    sgx_arch_targetinfo_t targetinfo;
 | 
	
		
			
				|  |  | +static sgx_arch_key128_t enclave_key;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    memset(&targetinfo, 0, sizeof(sgx_arch_targetinfo_t));
 | 
	
		
			
				|  |  | -    memcpy(targetinfo.mrenclave, mrenclave, sizeof(sgx_arch_hash_t));
 | 
	
		
			
				|  |  | -    memcpy(&targetinfo.attributes, attributes, sizeof(sgx_arch_attributes_t));
 | 
	
		
			
				|  |  | +#define KEYBUF_SIZE ((sizeof(sgx_arch_key128_t) * 2) + 1)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +/*
 | 
	
		
			
				|  |  | + * sgx_get_report() obtains a CPU-signed report for local attestation
 | 
	
		
			
				|  |  | + * @target_info:  the enclave target info
 | 
	
		
			
				|  |  | + * @data:         the data to be included and signed in the report
 | 
	
		
			
				|  |  | + * @report:       a buffer for storing the report
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +static int sgx_get_report(sgx_arch_targetinfo_t* target_info, sgx_sign_data_t* data,
 | 
	
		
			
				|  |  | +                          sgx_arch_report_t* report) {
 | 
	
		
			
				|  |  |      struct pal_enclave_state state;
 | 
	
		
			
				|  |  | -    memcpy(&state, &pal_enclave_state, sizeof(struct pal_enclave_state));
 | 
	
		
			
				|  |  | -    memcpy(&state.data, enclave_data, PAL_ATTESTATION_DATA_SIZE);
 | 
	
		
			
				|  |  | +    memcpy(&state, &pal_enclave_state, sizeof(state));
 | 
	
		
			
				|  |  | +    memcpy(&state.enclave_data, data, sizeof(*data));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    int ret = sgx_report(&targetinfo, &state, report);
 | 
	
		
			
				|  |  | -    if (ret)
 | 
	
		
			
				|  |  | -        return -PAL_ERROR_INVAL;
 | 
	
		
			
				|  |  | +    int ret = sgx_report(target_info, &state, report);
 | 
	
		
			
				|  |  | +    if (ret) {
 | 
	
		
			
				|  |  | +        SGX_DBG(DBG_E, "sgx_report failed: ret = %d)\n", ret);
 | 
	
		
			
				|  |  | +        return -PAL_ERROR_DENIED;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      SGX_DBG(DBG_S, "Generated report:\n");
 | 
	
		
			
				|  |  |      SGX_DBG(DBG_S, "    cpusvn:           %08lx %08lx\n", report->cpusvn[0],
 | 
	
	
		
			
				|  | @@ -123,9 +126,6 @@ int sgx_get_report (sgx_arch_hash_t * mrenclave,
 | 
	
		
			
				|  |  |      return 0;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static sgx_arch_key128_t enclave_key;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -#define KEYBUF_SIZE ((sizeof(sgx_arch_key128_t) * 2) + 1)
 | 
	
		
			
				|  |  |  int sgx_verify_report (sgx_arch_report_t * report)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |      sgx_arch_keyrequest_t keyrequest;
 | 
	
	
		
			
				|  | @@ -133,14 +133,34 @@ int sgx_verify_report (sgx_arch_report_t * report)
 | 
	
		
			
				|  |  |      keyrequest.keyname = REPORT_KEY;
 | 
	
		
			
				|  |  |      memcpy(keyrequest.keyid, report->keyid, sizeof(keyrequest.keyid));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    int ret = sgx_getkey(&keyrequest, &enclave_key);
 | 
	
		
			
				|  |  | +    sgx_arch_key128_t report_key;
 | 
	
		
			
				|  |  | +    memset(&report_key, 0, sizeof(report_key));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    int ret = sgx_getkey(&keyrequest, &report_key);
 | 
	
		
			
				|  |  |      if (ret) {
 | 
	
		
			
				|  |  | -        SGX_DBG(DBG_S, "Can't get report key\n");
 | 
	
		
			
				|  |  | +        SGX_DBG(DBG_E, "Can't get report key\n");
 | 
	
		
			
				|  |  |          return -PAL_ERROR_DENIED;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    SGX_DBG(DBG_S, "Get report key for verification: %s\n",
 | 
	
		
			
				|  |  | -            ALLOCA_BYTES2HEXSTR(enclave_key));
 | 
	
		
			
				|  |  | +    SGX_DBG(DBG_S, "Get report key for verification: %s\n", ALLOCA_BYTES2HEXSTR(report_key));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    sgx_arch_mac_t check_mac;
 | 
	
		
			
				|  |  | +    memset(&check_mac, 0, sizeof(check_mac));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    lib_AESCMAC((uint8_t*)&report_key, sizeof(report_key),
 | 
	
		
			
				|  |  | +                (uint8_t*)report, offsetof(sgx_arch_report_t, keyid),
 | 
	
		
			
				|  |  | +                (uint8_t*)&check_mac, sizeof(check_mac));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    memset(&report_key, 0, sizeof(report_key));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    SGX_DBG(DBG_S, "Verify report:\n");
 | 
	
		
			
				|  |  | +    SGX_DBG(DBG_S, "    expected:         %s\n", ALLOCA_BYTES2HEXSTR(report->mac));
 | 
	
		
			
				|  |  | +    SGX_DBG(DBG_S, "    mac:              %s\n", ALLOCA_BYTES2HEXSTR(check_mac));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (memcmp(&check_mac, &report->mac, sizeof(check_mac))) {
 | 
	
		
			
				|  |  | +        SGX_DBG(DBG_E, "Report verification failed\n");
 | 
	
		
			
				|  |  | +        return -PAL_ERROR_DENIED;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      return 0;
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -148,16 +168,16 @@ int sgx_verify_report (sgx_arch_report_t * report)
 | 
	
		
			
				|  |  |  int init_enclave_key (void)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |      sgx_arch_keyrequest_t keyrequest;
 | 
	
		
			
				|  |  | -    memset(&keyrequest, 0, sizeof(sgx_arch_keyrequest_t));
 | 
	
		
			
				|  |  | +    memset(&keyrequest, 0, sizeof(keyrequest));
 | 
	
		
			
				|  |  |      keyrequest.keyname = SEAL_KEY;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      int ret = sgx_getkey(&keyrequest, &enclave_key);
 | 
	
		
			
				|  |  |      if (ret) {
 | 
	
		
			
				|  |  | -        SGX_DBG(DBG_S, "Can't get report key\n");
 | 
	
		
			
				|  |  | +        SGX_DBG(DBG_E, "Can't get seal key\n");
 | 
	
		
			
				|  |  |          return -PAL_ERROR_DENIED;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    SGX_DBG(DBG_S, "Get sealing key: %s\n", ALLOCA_BYTES2HEXSTR(enclave_key));
 | 
	
		
			
				|  |  | +    SGX_DBG(DBG_S, "Seal key: %s\n", ALLOCA_BYTES2HEXSTR(enclave_key));
 | 
	
		
			
				|  |  |      return 0;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -227,7 +247,7 @@ static bool path_is_equal_or_subpath(const struct trusted_file* tf,
 | 
	
		
			
				|  |  |   * sizeptr:  size pointer
 | 
	
		
			
				|  |  |   * create:   this file is newly created or not
 | 
	
		
			
				|  |  |   *
 | 
	
		
			
				|  |  | - * return:  0 succeed
 | 
	
		
			
				|  |  | + * Returns 0 if succeeded, or an error code otherwise.
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  int load_trusted_file (PAL_HANDLE file, sgx_stub_t ** stubptr,
 | 
	
		
			
				|  |  |                         uint64_t * sizeptr, int create)
 | 
	
	
		
			
				|  | @@ -337,8 +357,7 @@ int load_trusted_file (PAL_HANDLE file, sgx_stub_t ** stubptr,
 | 
	
		
			
				|  |  |           * AES-CMAC, and then update the SHA256 digest. */
 | 
	
		
			
				|  |  |          uint64_t mapping_size = MIN(tf->size - offset, TRUSTED_STUB_SIZE);
 | 
	
		
			
				|  |  |          LIB_AESCMAC_CONTEXT aes_cmac;
 | 
	
		
			
				|  |  | -        ret = lib_AESCMACInit(&aes_cmac, (uint8_t *) &enclave_key,
 | 
	
		
			
				|  |  | -                              AES_CMAC_KEY_LEN);
 | 
	
		
			
				|  |  | +        ret = lib_AESCMACInit(&aes_cmac, (uint8_t*)&enclave_key, sizeof(enclave_key));
 | 
	
		
			
				|  |  |          if (ret < 0)
 | 
	
		
			
				|  |  |              goto failed;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -489,7 +508,7 @@ int copy_and_verify_trusted_file (const char * path, const void * umem,
 | 
	
		
			
				|  |  |          /* Check one chunk at a time. */
 | 
	
		
			
				|  |  |          uint64_t checking_size = MIN(total_size - checking, TRUSTED_STUB_SIZE);
 | 
	
		
			
				|  |  |          uint64_t checking_end = checking + checking_size;
 | 
	
		
			
				|  |  | -        uint8_t hash[AES_CMAC_DIGEST_LEN];
 | 
	
		
			
				|  |  | +        sgx_checksum_t hash;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          if (checking >= offset && checking_end <= offset + size) {
 | 
	
		
			
				|  |  |              /* If the checking chunk completely overlaps with the region
 | 
	
	
		
			
				|  | @@ -499,17 +518,15 @@ int copy_and_verify_trusted_file (const char * path, const void * umem,
 | 
	
		
			
				|  |  |                     checking_size);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              /* Storing the checksum (using AES-CMAC) inside hash. */
 | 
	
		
			
				|  |  | -            ret = lib_AESCMAC((uint8_t *) &enclave_key,
 | 
	
		
			
				|  |  | -                              AES_CMAC_KEY_LEN,
 | 
	
		
			
				|  |  | +            ret = lib_AESCMAC((uint8_t*)&enclave_key, sizeof(enclave_key),
 | 
	
		
			
				|  |  |                                buffer + checking - offset, checking_size,
 | 
	
		
			
				|  |  | -                              hash, sizeof(hash));
 | 
	
		
			
				|  |  | +                              (uint8_t*)&hash, sizeof(hash));
 | 
	
		
			
				|  |  |          } else {
 | 
	
		
			
				|  |  |              /* If the checking chunk only partially overlaps with the region,
 | 
	
		
			
				|  |  |               * read the file content in smaller chunks and only copy the part
 | 
	
		
			
				|  |  |               * needed by the caller. */
 | 
	
		
			
				|  |  |              LIB_AESCMAC_CONTEXT aes_cmac;
 | 
	
		
			
				|  |  | -            ret = lib_AESCMACInit(&aes_cmac, (uint8_t *) &enclave_key,
 | 
	
		
			
				|  |  | -                                  AES_CMAC_KEY_LEN);
 | 
	
		
			
				|  |  | +            ret = lib_AESCMACInit(&aes_cmac, (uint8_t*)&enclave_key, sizeof(enclave_key));
 | 
	
		
			
				|  |  |              if (ret < 0)
 | 
	
		
			
				|  |  |                  goto failed;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -547,7 +564,7 @@ int copy_and_verify_trusted_file (const char * path, const void * umem,
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              /* Storing the checksum (using AES-CMAC) inside hash. */
 | 
	
		
			
				|  |  | -            ret = lib_AESCMACFinish(&aes_cmac, hash, sizeof(hash));
 | 
	
		
			
				|  |  | +            ret = lib_AESCMACFinish(&aes_cmac, (uint8_t*)&hash, sizeof(hash));
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          if (ret < 0)
 | 
	
	
		
			
				|  | @@ -562,7 +579,7 @@ int copy_and_verify_trusted_file (const char * path, const void * umem,
 | 
	
		
			
				|  |  |           *
 | 
	
		
			
				|  |  |           * XXX: Maybe we should zero the buffer after denying the access?
 | 
	
		
			
				|  |  |           */
 | 
	
		
			
				|  |  | -        if (memcmp(s, hash, sizeof(sgx_stub_t))) {
 | 
	
		
			
				|  |  | +        if (memcmp(s, &hash, sizeof(sgx_stub_t))) {
 | 
	
		
			
				|  |  |              SGX_DBG(DBG_E, "Accesing file:%s is denied. Does not match with MAC"
 | 
	
		
			
				|  |  |                      " at chunk starting at %lu-%lu.\n",
 | 
	
		
			
				|  |  |                      path, checking, checking_end);
 | 
	
	
		
			
				|  | @@ -958,7 +975,7 @@ int init_enclave (void)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      ret = lib_RSAGenerateKey(rsa, RSA_KEY_SIZE, RSA_E);
 | 
	
		
			
				|  |  |      if (ret < 0) {
 | 
	
		
			
				|  |  | -        SGX_DBG(DBG_S, "lib_RSAGenerateKey failed: %d\n", ret);
 | 
	
		
			
				|  |  | +        SGX_DBG(DBG_E, "lib_RSAGenerateKey failed: %d\n", ret);
 | 
	
		
			
				|  |  |          return ret;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -966,39 +983,38 @@ int init_enclave (void)
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /*
 | 
	
		
			
				|  |  | -     * The enclave identifier is uniquely created for each enclave as a token
 | 
	
		
			
				|  |  | +     * The enclave id is uniquely created for each enclave as a token
 | 
	
		
			
				|  |  |       * for authenticating the enclave as the sender of attestation.
 | 
	
		
			
				|  |  | -     * TODO: documenting the inter-enclave attestation protocol.
 | 
	
		
			
				|  |  | +     * See 'host/Linux-SGX/db_process.c' for further explanation.
 | 
	
		
			
				|  |  |       */
 | 
	
		
			
				|  |  | -    _DkRandomBitsRead(&pal_enclave_state.enclave_identifier,
 | 
	
		
			
				|  |  | -                      sizeof(pal_enclave_state.enclave_identifier));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    SGX_DBG(DBG_S, "enclave (software) key hash: %s\n",
 | 
	
		
			
				|  |  | -            ALLOCA_BYTES2HEXSTR(pal_enclave_state.enclave_identifier));
 | 
	
		
			
				|  |  | +    ret = _DkRandomBitsRead(&pal_enclave_state.enclave_id,
 | 
	
		
			
				|  |  | +                            sizeof(pal_enclave_state.enclave_id));
 | 
	
		
			
				|  |  | +    if (ret < 0) {
 | 
	
		
			
				|  |  | +        SGX_DBG(DBG_E, "Failed to generate a random id: %d\n", ret);
 | 
	
		
			
				|  |  | +        return ret;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      return 0;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -int _DkStreamKeyExchange (PAL_HANDLE stream, PAL_SESSION_KEY * keyptr)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -    uint8_t session_key[sizeof(PAL_SESSION_KEY)]
 | 
	
		
			
				|  |  | -        __attribute__((aligned(sizeof(PAL_SESSION_KEY))));
 | 
	
		
			
				|  |  | +int _DkStreamKeyExchange(PAL_HANDLE stream, PAL_SESSION_KEY* key) {
 | 
	
		
			
				|  |  |      uint8_t pub[DH_SIZE]   __attribute__((aligned(DH_SIZE)));
 | 
	
		
			
				|  |  |      uint8_t agree[DH_SIZE] __attribute__((aligned(DH_SIZE)));
 | 
	
		
			
				|  |  |      PAL_NUM pubsz, agreesz;
 | 
	
		
			
				|  |  |      LIB_DH_CONTEXT context;
 | 
	
		
			
				|  |  | -    int ret;
 | 
	
		
			
				|  |  | +    int64_t bytes;
 | 
	
		
			
				|  |  | +    int64_t ret;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      ret = lib_DhInit(&context);
 | 
	
		
			
				|  |  |      if (ret < 0) {
 | 
	
		
			
				|  |  | -        SGX_DBG(DBG_S, "Key Exchange: DH Init failed: %d\n", ret);
 | 
	
		
			
				|  |  | +        SGX_DBG(DBG_E, "Key Exchange: DH Init failed: %ld\n", ret);
 | 
	
		
			
				|  |  |          goto out_no_final;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      pubsz = sizeof pub;
 | 
	
		
			
				|  |  |      ret = lib_DhCreatePublic(&context, pub, &pubsz);
 | 
	
		
			
				|  |  |      if (ret < 0) {
 | 
	
		
			
				|  |  | -        SGX_DBG(DBG_S, "Key Exchange: DH CreatePublic failed: %d\n", ret);
 | 
	
		
			
				|  |  | +        SGX_DBG(DBG_E, "Key Exchange: DH CreatePublic failed: %ld\n", ret);
 | 
	
		
			
				|  |  |          goto out;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -1012,37 +1028,56 @@ int _DkStreamKeyExchange (PAL_HANDLE stream, PAL_SESSION_KEY * keyptr)
 | 
	
		
			
				|  |  |          memset(pub, 0, DH_SIZE - pubsz);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    ret = _DkStreamWrite(stream, 0, DH_SIZE, pub, NULL, 0);
 | 
	
		
			
				|  |  | -    if (ret != DH_SIZE) {
 | 
	
		
			
				|  |  | -        SGX_DBG(DBG_S, "Key Exchange: DkStreamWrite failed: %d\n", ret);
 | 
	
		
			
				|  |  | -        goto out;
 | 
	
		
			
				|  |  | +    for (bytes = 0, ret = 0; bytes < DH_SIZE; bytes += ret) {
 | 
	
		
			
				|  |  | +        ret = _DkStreamWrite(stream, 0, DH_SIZE - bytes, pub + bytes, NULL, 0);
 | 
	
		
			
				|  |  | +        if (ret < 0) {
 | 
	
		
			
				|  |  | +            if (ret == -PAL_ERROR_INTERRUPTED || ret == -PAL_ERROR_TRYAGAIN) {
 | 
	
		
			
				|  |  | +                ret = 0;
 | 
	
		
			
				|  |  | +                continue;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            SGX_DBG(DBG_E, "Failed to exchange the secret key via RPC: %ld\n", ret);
 | 
	
		
			
				|  |  | +            goto out;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    ret = _DkStreamRead(stream, 0, DH_SIZE, pub, NULL, 0);
 | 
	
		
			
				|  |  | -    if (ret != DH_SIZE) {
 | 
	
		
			
				|  |  | -        SGX_DBG(DBG_S, "Key Exchange: DkStreamRead failed: %d\n", ret);
 | 
	
		
			
				|  |  | -        goto out;
 | 
	
		
			
				|  |  | +    for (bytes = 0, ret = 0 ; bytes < DH_SIZE ; bytes += ret) {
 | 
	
		
			
				|  |  | +        ret = _DkStreamRead(stream, 0, DH_SIZE - bytes, pub + bytes, NULL, 0);
 | 
	
		
			
				|  |  | +        if (ret < 0) {
 | 
	
		
			
				|  |  | +            if (ret == -PAL_ERROR_INTERRUPTED || ret == -PAL_ERROR_TRYAGAIN) {
 | 
	
		
			
				|  |  | +                ret = 0;
 | 
	
		
			
				|  |  | +                continue;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            SGX_DBG(DBG_E, "Failed to exchange the secret key via RPC: %ld\n", ret);
 | 
	
		
			
				|  |  | +            goto out;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      agreesz = sizeof agree;
 | 
	
		
			
				|  |  |      ret = lib_DhCalcSecret(&context, pub, DH_SIZE, agree, &agreesz);
 | 
	
		
			
				|  |  |      if (ret < 0) {
 | 
	
		
			
				|  |  | -        SGX_DBG(DBG_S, "Key Exchange: DH CalcSecret failed: %d\n", ret);
 | 
	
		
			
				|  |  | +        SGX_DBG(DBG_E, "Key Exchange: DH CalcSecret failed: %ld\n", ret);
 | 
	
		
			
				|  |  |          goto out;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      assert(agreesz > 0 && agreesz <= sizeof agree);
 | 
	
		
			
				|  |  | -    // TODO(security): use a real KDF
 | 
	
		
			
				|  |  | -    memset(session_key, 0, sizeof(session_key));
 | 
	
		
			
				|  |  | -    for (uint32_t i = 0 ; i < agreesz ; i++)
 | 
	
		
			
				|  |  | -        session_key[i % sizeof(session_key)] ^= agree[i];
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    SGX_DBG(DBG_S, "key exchange: (%p) %s\n", session_key,
 | 
	
		
			
				|  |  | -            ALLOCA_BYTES2HEXSTR(session_key));
 | 
	
		
			
				|  |  | +    /*
 | 
	
		
			
				|  |  | +     * Using SHA256 as a KDF to convert the 128-byte DH secret to a 256-bit AES key.
 | 
	
		
			
				|  |  | +     * According to the NIST recommendation:
 | 
	
		
			
				|  |  | +     * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Cr1.pdf,
 | 
	
		
			
				|  |  | +     * a key derivation function (KDF) can be a secure hash function (e.g., SHA-256),
 | 
	
		
			
				|  |  | +     * HMAC, or KMAC.
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    LIB_SHA256_CONTEXT sha;
 | 
	
		
			
				|  |  | +    if ((ret = lib_SHA256Init(&sha)) < 0 ||
 | 
	
		
			
				|  |  | +        (ret = lib_SHA256Update(&sha, agree, agreesz)) < 0 ||
 | 
	
		
			
				|  |  | +        (ret = lib_SHA256Final(&sha, (uint8_t*)key)) < 0) {
 | 
	
		
			
				|  |  | +        SGX_DBG(DBG_E, "Failed to derive the session key: %ld\n", ret);
 | 
	
		
			
				|  |  | +        goto out;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    if (keyptr)
 | 
	
		
			
				|  |  | -        memcpy(keyptr, session_key, sizeof(PAL_SESSION_KEY));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    SGX_DBG(DBG_S, "Key exchange succeeded: %s\n", ALLOCA_BYTES2HEXSTR(*key));
 | 
	
		
			
				|  |  |      ret = 0;
 | 
	
		
			
				|  |  |  out:
 | 
	
		
			
				|  |  |      lib_DhFinal(&context);
 | 
	
	
		
			
				|  | @@ -1050,101 +1085,98 @@ out_no_final:
 | 
	
		
			
				|  |  |      return ret;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -struct attestation_request {
 | 
	
		
			
				|  |  | -    sgx_arch_hash_t       mrenclave;
 | 
	
		
			
				|  |  | -    sgx_arch_attributes_t attributes;
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -struct attestation {
 | 
	
		
			
				|  |  | -    sgx_arch_hash_t       mrenclave;
 | 
	
		
			
				|  |  | -    sgx_arch_attributes_t attributes;
 | 
	
		
			
				|  |  | -    sgx_arch_report_t     report;
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -int _DkStreamAttestationRequest (PAL_HANDLE stream, void * data,
 | 
	
		
			
				|  |  | -                                 int (*check_mrenclave) (sgx_arch_hash_t *,
 | 
	
		
			
				|  |  | -                                                         void *, void *),
 | 
	
		
			
				|  |  | -                                 void * check_param)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -    struct attestation_request req;
 | 
	
		
			
				|  |  | -    struct attestation att;
 | 
	
		
			
				|  |  | -    size_t bytes;
 | 
	
		
			
				|  |  | -    int ret;
 | 
	
		
			
				|  |  | +/*
 | 
	
		
			
				|  |  | + * Initalize the request of local report exchange.
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * We refer to this enclave as A and to the other enclave as B, e.g., A is this
 | 
	
		
			
				|  |  | + * parent enclave and B is the child enclave in the fork case (for more info,
 | 
	
		
			
				|  |  | + * see comments in db_process.c).
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +int _DkStreamReportRequest(PAL_HANDLE stream, sgx_sign_data_t* data,
 | 
	
		
			
				|  |  | +                           check_mrenclave_t check_mrenclave) {
 | 
	
		
			
				|  |  | +    sgx_arch_targetinfo_t target_info;
 | 
	
		
			
				|  |  | +    sgx_arch_report_t report;
 | 
	
		
			
				|  |  | +    uint64_t bytes;
 | 
	
		
			
				|  |  | +    int64_t ret;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    memcpy(req.mrenclave, pal_sec.mrenclave, sizeof(sgx_arch_hash_t));
 | 
	
		
			
				|  |  | -    memcpy(&req.attributes, &pal_sec.enclave_attributes,
 | 
	
		
			
				|  |  | +    /* A -> B: targetinfo[A] */
 | 
	
		
			
				|  |  | +    memset(&target_info, 0, sizeof(target_info));
 | 
	
		
			
				|  |  | +    memcpy(&target_info.mrenclave,  &pal_sec.mrenclave, sizeof(sgx_arch_hash_t));
 | 
	
		
			
				|  |  | +    memcpy(&target_info.attributes, &pal_sec.enclave_attributes,
 | 
	
		
			
				|  |  |             sizeof(sgx_arch_attributes_t));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    SGX_DBG(DBG_S, "Sending attestation request ... (mrenclave = %s)\n",\
 | 
	
		
			
				|  |  | -            ALLOCA_BYTES2HEXSTR(req.mrenclave));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    for (bytes = 0, ret = 0 ; bytes < sizeof(req) ; bytes += ret) {
 | 
	
		
			
				|  |  | -        ret = _DkStreamWrite(stream, 0, sizeof(req) - bytes,
 | 
	
		
			
				|  |  | -                             ((void *) &req) + bytes, NULL, 0);
 | 
	
		
			
				|  |  | +    for (bytes = 0, ret = 0; bytes < SGX_TARGETINFO_FILLED_SIZE; bytes += ret) {
 | 
	
		
			
				|  |  | +        ret = _DkStreamWrite(stream, 0, SGX_TARGETINFO_FILLED_SIZE - bytes,
 | 
	
		
			
				|  |  | +                             ((void*)&target_info) + bytes, NULL, 0);
 | 
	
		
			
				|  |  |          if (ret < 0) {
 | 
	
		
			
				|  |  | -            SGX_DBG(DBG_S, "Attestation Request: DkStreamWrite failed: %d\n", ret);
 | 
	
		
			
				|  |  | +            if (ret == -PAL_ERROR_INTERRUPTED || ret == -PAL_ERROR_TRYAGAIN) {
 | 
	
		
			
				|  |  | +                ret = 0;
 | 
	
		
			
				|  |  | +                continue;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            SGX_DBG(DBG_E, "Failed to send target info via RPC: %ld\n", ret);
 | 
	
		
			
				|  |  |              goto out;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    for (bytes = 0, ret = 0 ; bytes < sizeof(att) ; bytes += ret) {
 | 
	
		
			
				|  |  | -        ret = _DkStreamRead(stream, 0, sizeof(att) - bytes,
 | 
	
		
			
				|  |  | -                            ((void *) &att) + bytes, NULL, 0);
 | 
	
		
			
				|  |  | +    /* B -> A: report[B -> A] */
 | 
	
		
			
				|  |  | +    for (bytes = 0, ret = 0 ; bytes < sizeof(report) ; bytes += ret) {
 | 
	
		
			
				|  |  | +        ret = _DkStreamRead(stream, 0, sizeof(report) - bytes,
 | 
	
		
			
				|  |  | +                            ((void*)&report) + bytes, NULL, 0);
 | 
	
		
			
				|  |  |          if (ret < 0) {
 | 
	
		
			
				|  |  | -            SGX_DBG(DBG_S, "Attestation Request: DkStreamRead failed: %d\n", ret);
 | 
	
		
			
				|  |  | +            if (ret == -PAL_ERROR_INTERRUPTED || ret == -PAL_ERROR_TRYAGAIN) {
 | 
	
		
			
				|  |  | +                ret = 0;
 | 
	
		
			
				|  |  | +                continue;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            SGX_DBG(DBG_E, "Failed to receive local report via RPC: %ld\n", ret);
 | 
	
		
			
				|  |  |              goto out;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    SGX_DBG(DBG_S, "Received attestation (mrenclave = %s)\n",
 | 
	
		
			
				|  |  | -            ALLOCA_BYTES2HEXSTR(att.mrenclave));
 | 
	
		
			
				|  |  | +    SGX_DBG(DBG_S, "Received local report (mrenclave = %s)\n",
 | 
	
		
			
				|  |  | +            ALLOCA_BYTES2HEXSTR(report.mrenclave));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    ret = sgx_verify_report(&att.report);
 | 
	
		
			
				|  |  | +    /* Verify report[B -> A] */
 | 
	
		
			
				|  |  | +    ret = sgx_verify_report(&report);
 | 
	
		
			
				|  |  |      if (ret < 0) {
 | 
	
		
			
				|  |  | -        SGX_DBG(DBG_S, "Attestation Request: sgx_verify_report failed: %d\n", ret);
 | 
	
		
			
				|  |  | +        SGX_DBG(DBG_E, "Failed to verify local report: %ld\n", ret);
 | 
	
		
			
				|  |  |          goto out;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    if (ret == 1) {
 | 
	
		
			
				|  |  | -        SGX_DBG(DBG_S, "Remote attestation not signed by SGX!\n");
 | 
	
		
			
				|  |  | -        ret = -PAL_ERROR_DENIED;
 | 
	
		
			
				|  |  | -        goto out;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    ret = check_mrenclave(&att.report.mrenclave, &att.report.report_data,
 | 
	
		
			
				|  |  | -                          check_param);
 | 
	
		
			
				|  |  | +    struct pal_enclave_state* remote_state = (void*)&report.report_data;
 | 
	
		
			
				|  |  | +    ret = check_mrenclave(stream, &report.mrenclave, remote_state);
 | 
	
		
			
				|  |  |      if (ret < 0) {
 | 
	
		
			
				|  |  | -        SGX_DBG(DBG_S, "Attestation Request: check_mrenclave failed: %d\n", ret);
 | 
	
		
			
				|  |  | +        SGX_DBG(DBG_E, "Failed to check local report: %ld\n", ret);
 | 
	
		
			
				|  |  |          goto out;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      if (ret == 1) {
 | 
	
		
			
				|  |  | -        SGX_DBG(DBG_S, "Not an allowed enclave (mrenclave = %s). Maybe missing 'sgx.trusted_children' in the manifest file?\n",
 | 
	
		
			
				|  |  | -                ALLOCA_BYTES2HEXSTR(att.mrenclave));
 | 
	
		
			
				|  |  | +        SGX_DBG(DBG_E, "Not an allowed enclave (mrenclave = %s). Maybe missing 'sgx.trusted_children' in the manifest file?\n",
 | 
	
		
			
				|  |  | +                ALLOCA_BYTES2HEXSTR(report.mrenclave));
 | 
	
		
			
				|  |  |          ret = -PAL_ERROR_DENIED;
 | 
	
		
			
				|  |  |          goto out;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    SGX_DBG(DBG_S, "Remote attestation succeed!\n");
 | 
	
		
			
				|  |  | +    SGX_DBG(DBG_S, "Local attestation succeeded!\n");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /* A -> B: report[A -> B] */
 | 
	
		
			
				|  |  | +    memcpy(&target_info.mrenclave , &report.mrenclave,  sizeof(sgx_arch_hash_t));
 | 
	
		
			
				|  |  | +    memcpy(&target_info.attributes, &report.attributes, sizeof(sgx_arch_attributes_t));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    ret = sgx_get_report(&att.mrenclave, &att.attributes, data, &att.report);
 | 
	
		
			
				|  |  | +    ret = sgx_get_report(&target_info, data, &report);
 | 
	
		
			
				|  |  |      if (ret < 0) {
 | 
	
		
			
				|  |  | -        SGX_DBG(DBG_S, "Attestation Request: sgx_get_report failed: %d\n", ret);
 | 
	
		
			
				|  |  | +        SGX_DBG(DBG_E, "Failed to get local report from CPU: %ld\n", ret);
 | 
	
		
			
				|  |  |          goto out;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    memcpy(att.mrenclave, pal_sec.mrenclave, sizeof(sgx_arch_hash_t));
 | 
	
		
			
				|  |  | -    memcpy(&att.attributes, &pal_sec.enclave_attributes,
 | 
	
		
			
				|  |  | -           sizeof(sgx_arch_attributes_t));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    SGX_DBG(DBG_S, "Sending attestation ... (mrenclave = %s)\n",
 | 
	
		
			
				|  |  | -            ALLOCA_BYTES2HEXSTR(att.mrenclave));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    for (bytes = 0, ret = 0 ; bytes < sizeof(att) ; bytes += ret) {
 | 
	
		
			
				|  |  | -        ret = _DkStreamWrite(stream, 0, sizeof(att) - bytes,
 | 
	
		
			
				|  |  | -                             ((void *) &att) + bytes, NULL, 0);
 | 
	
		
			
				|  |  | +    for (bytes = 0, ret = 0 ; bytes < sizeof(report) ; bytes += ret) {
 | 
	
		
			
				|  |  | +        ret = _DkStreamWrite(stream, 0, sizeof(report) - bytes,
 | 
	
		
			
				|  |  | +                             ((void*)&report) + bytes, NULL, 0);
 | 
	
		
			
				|  |  |          if (ret < 0) {
 | 
	
		
			
				|  |  | -            SGX_DBG(DBG_S, "Attestation Request: DkStreamWrite failed: %d\n", ret);
 | 
	
		
			
				|  |  | +            if (ret == -PAL_ERROR_INTERRUPTED || ret == -PAL_ERROR_TRYAGAIN) {
 | 
	
		
			
				|  |  | +                ret = 0;
 | 
	
		
			
				|  |  | +                continue;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            SGX_DBG(DBG_E, "Failed to send local report via RPC: %ld\n", ret);
 | 
	
		
			
				|  |  |              goto out;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
	
		
			
				|  | @@ -1156,88 +1188,94 @@ out:
 | 
	
		
			
				|  |  |      return ret;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -int _DkStreamAttestationRespond (PAL_HANDLE stream, void * data,
 | 
	
		
			
				|  |  | -                                 int (*check_mrenclave) (sgx_arch_hash_t *,
 | 
	
		
			
				|  |  | -                                                         void *, void *),
 | 
	
		
			
				|  |  | -                                 void * check_param)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -    struct attestation_request req;
 | 
	
		
			
				|  |  | -    struct attestation att;
 | 
	
		
			
				|  |  | -    size_t bytes;
 | 
	
		
			
				|  |  | -    int ret;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    for (bytes = 0, ret = 0 ; bytes < sizeof(req) ; bytes += ret) {
 | 
	
		
			
				|  |  | -        ret = _DkStreamRead(stream, 0, sizeof(req) - bytes,
 | 
	
		
			
				|  |  | -                            ((void *) &req) + bytes, NULL, 0);
 | 
	
		
			
				|  |  | +/*
 | 
	
		
			
				|  |  | + * Respond to the request of local report exchange.
 | 
	
		
			
				|  |  | + *
 | 
	
		
			
				|  |  | + * We refer to this enclave as B and to the other enclave as A, e.g., B is this
 | 
	
		
			
				|  |  | + * child enclave and A is the parent enclave in the fork case (for more info,
 | 
	
		
			
				|  |  | + * see comments in db_process.c).
 | 
	
		
			
				|  |  | + */
 | 
	
		
			
				|  |  | +int _DkStreamReportRespond(PAL_HANDLE stream, sgx_sign_data_t* data,
 | 
	
		
			
				|  |  | +                           check_mrenclave_t check_mrenclave) {
 | 
	
		
			
				|  |  | +    sgx_arch_targetinfo_t target_info;
 | 
	
		
			
				|  |  | +    sgx_arch_report_t report;
 | 
	
		
			
				|  |  | +    uint64_t bytes;
 | 
	
		
			
				|  |  | +    int64_t ret;
 | 
	
		
			
				|  |  | +    memset(&target_info, 0, sizeof(target_info));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /* A -> B: targetinfo[A] */
 | 
	
		
			
				|  |  | +    for (bytes = 0, ret = 0 ; bytes < SGX_TARGETINFO_FILLED_SIZE ; bytes += ret) {
 | 
	
		
			
				|  |  | +        ret = _DkStreamRead(stream, 0, SGX_TARGETINFO_FILLED_SIZE - bytes,
 | 
	
		
			
				|  |  | +                            ((void*)&target_info) + bytes, NULL, 0);
 | 
	
		
			
				|  |  |          if (ret < 0) {
 | 
	
		
			
				|  |  | -            SGX_DBG(DBG_S, "Attestation Respond: DkStreamRead failed: %d\n", ret);
 | 
	
		
			
				|  |  | +            if (ret == -PAL_ERROR_INTERRUPTED || ret == -PAL_ERROR_TRYAGAIN) {
 | 
	
		
			
				|  |  | +                ret = 0;
 | 
	
		
			
				|  |  | +                continue;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            SGX_DBG(DBG_E, "Failed to receive target info via RPC: %ld\n", ret);
 | 
	
		
			
				|  |  |              goto out;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    SGX_DBG(DBG_S, "Received attestation request ... (mrenclave = %s)\n",
 | 
	
		
			
				|  |  | -            ALLOCA_BYTES2HEXSTR(req.mrenclave));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    ret = sgx_get_report(&req.mrenclave, &req.attributes, data, &att.report);
 | 
	
		
			
				|  |  | +    /* B -> A: report[B -> A] */
 | 
	
		
			
				|  |  | +    ret = sgx_get_report(&target_info, data, &report);
 | 
	
		
			
				|  |  |      if (ret < 0) {
 | 
	
		
			
				|  |  | -        SGX_DBG(DBG_S, "Attestation Respond: sgx_get_report failed: %d\n", ret);
 | 
	
		
			
				|  |  | +        SGX_DBG(DBG_E, "Failed to get local report from CPU: %ld\n", ret);
 | 
	
		
			
				|  |  |          goto out;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    memcpy(att.mrenclave, pal_sec.mrenclave, sizeof(sgx_arch_hash_t));
 | 
	
		
			
				|  |  | -    memcpy(&att.attributes, &pal_sec.enclave_attributes,
 | 
	
		
			
				|  |  | -           sizeof(sgx_arch_attributes_t));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    SGX_DBG(DBG_S, "Sending attestation ... (mrenclave = %s)\n",
 | 
	
		
			
				|  |  | -            ALLOCA_BYTES2HEXSTR(att.mrenclave));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    for (bytes = 0, ret = 0 ; bytes < sizeof(att) ; bytes += ret) {
 | 
	
		
			
				|  |  | -        ret = _DkStreamWrite(stream, 0, sizeof(att) - bytes,
 | 
	
		
			
				|  |  | -                             ((void *) &att) + bytes, NULL, 0);
 | 
	
		
			
				|  |  | +    for (bytes = 0, ret = 0 ; bytes < sizeof(report) ; bytes += ret) {
 | 
	
		
			
				|  |  | +        ret = _DkStreamWrite(stream, 0, sizeof(report) - bytes,
 | 
	
		
			
				|  |  | +                             ((void*)&report) + bytes, NULL, 0);
 | 
	
		
			
				|  |  |          if (ret < 0) {
 | 
	
		
			
				|  |  | -            SGX_DBG(DBG_S, "Attestation Respond: DkStreamWrite failed: %d\n", ret);
 | 
	
		
			
				|  |  | +            if (ret == -PAL_ERROR_INTERRUPTED || ret == -PAL_ERROR_TRYAGAIN) {
 | 
	
		
			
				|  |  | +                ret = 0;
 | 
	
		
			
				|  |  | +                continue;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            SGX_DBG(DBG_E, "Failed to send local report via PRC: %ld\n", ret);
 | 
	
		
			
				|  |  |              goto out;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    for (bytes = 0, ret = 0 ; bytes < sizeof(att) ; bytes += ret) {
 | 
	
		
			
				|  |  | -        ret = _DkStreamRead(stream, 0, sizeof(att) - bytes,
 | 
	
		
			
				|  |  | -                            ((void *) &att) + bytes, NULL, 0);
 | 
	
		
			
				|  |  | +    /* A -> B: report[A -> B] */
 | 
	
		
			
				|  |  | +    for (bytes = 0, ret = 0 ; bytes < sizeof(report) ; bytes += ret) {
 | 
	
		
			
				|  |  | +        ret = _DkStreamRead(stream, 0, sizeof(report) - bytes,
 | 
	
		
			
				|  |  | +                            ((void*)&report) + bytes, NULL, 0);
 | 
	
		
			
				|  |  |          if (ret < 0) {
 | 
	
		
			
				|  |  | -            SGX_DBG(DBG_S, "Attestation Respond: DkStreamRead failed: %d\n", ret);
 | 
	
		
			
				|  |  | +            if (ret == -PAL_ERROR_INTERRUPTED || ret == -PAL_ERROR_TRYAGAIN) {
 | 
	
		
			
				|  |  | +                ret = 0;
 | 
	
		
			
				|  |  | +                continue;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            SGX_DBG(DBG_E, "Failed to receive local report via RPC: %ld\n", ret);
 | 
	
		
			
				|  |  |              goto out;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    SGX_DBG(DBG_S, "Received attestation (mrenclave = %s)\n",
 | 
	
		
			
				|  |  | -            ALLOCA_BYTES2HEXSTR(att.mrenclave));
 | 
	
		
			
				|  |  | +    SGX_DBG(DBG_S, "Received local report (mrenclave = %s)\n",
 | 
	
		
			
				|  |  | +            ALLOCA_BYTES2HEXSTR(report.mrenclave));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    ret = sgx_verify_report(&att.report);
 | 
	
		
			
				|  |  | +    /* Verify report[A -> B] */
 | 
	
		
			
				|  |  | +    ret = sgx_verify_report(&report);
 | 
	
		
			
				|  |  |      if (ret < 0) {
 | 
	
		
			
				|  |  | -        SGX_DBG(DBG_S, "Attestation Respond: sgx_verify_report failed: %d\n", ret);
 | 
	
		
			
				|  |  | -        goto out;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    if (ret == 1) {
 | 
	
		
			
				|  |  | -        SGX_DBG(DBG_S, "Remote attestation not signed by SGX!\n");
 | 
	
		
			
				|  |  | +        SGX_DBG(DBG_E, "Failed to verify local report: %ld\n", ret);
 | 
	
		
			
				|  |  |          goto out;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    ret = check_mrenclave(&att.report.mrenclave, &att.report.report_data,
 | 
	
		
			
				|  |  | -                          check_param);
 | 
	
		
			
				|  |  | +    struct pal_enclave_state* remote_state = (void*)&report.report_data;
 | 
	
		
			
				|  |  | +    ret = check_mrenclave(stream, &report.mrenclave, remote_state);
 | 
	
		
			
				|  |  |      if (ret < 0) {
 | 
	
		
			
				|  |  | -        SGX_DBG(DBG_S, "Attestation Request: check_mrenclave failed: %d\n", ret);
 | 
	
		
			
				|  |  | +        SGX_DBG(DBG_E, "Failed to check mrenclave: %ld\n", ret);
 | 
	
		
			
				|  |  |          goto out;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      if (ret == 1) {
 | 
	
		
			
				|  |  | -        SGX_DBG(DBG_S, "Not an allowed enclave (mrenclave = %s). Maybe missing 'sgx.trusted_children' in the manifest file?\n",
 | 
	
		
			
				|  |  | -                ALLOCA_BYTES2HEXSTR(att.mrenclave));
 | 
	
		
			
				|  |  | +        SGX_DBG(DBG_E, "Not an allowed enclave (mrenclave = %s). Maybe missing 'sgx.trusted_children' in the manifest file?\n",
 | 
	
		
			
				|  |  | +                ALLOCA_BYTES2HEXSTR(report.mrenclave));
 | 
	
		
			
				|  |  |          ret = -PAL_ERROR_DENIED;
 | 
	
		
			
				|  |  |          goto out;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    SGX_DBG(DBG_S, "Remote attestation succeeded!\n");
 | 
	
		
			
				|  |  | +    SGX_DBG(DBG_S, "Local attestation succeeded!\n");
 | 
	
		
			
				|  |  |      return 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  out:
 |