You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SGX Enclave向外部传递可变大小缓冲区的EDL函数定义问题

How to Define a Dynamic Buffer Passing Function in SGX EDL

Got it, let's break down how to properly define your pass_buffer function in SGX EDL—handling dynamic output buffers can be tricky at first, but I’ve worked through this exact scenario before.

Step 1: Correct EDL Function Definition

Here’s the precise EDL syntax you need, with explanations for each parameter attribute:

enclave {
    public {
        void pass_buffer(
            [out, alloc, size=buffer_out_len] void** buffer_out,
            [out] size_t* buffer_out_len,
            [in, size=buffer_in_len] const void* buffer_in,
            [in] size_t buffer_in_len
        );
    };
};

Let’s unpack the attributes to understand why they matter:

  • [out, alloc, size=buffer_out_len] void** buffer_out:
    • out marks this as an output parameter that the Enclave will populate.
    • alloc tells SGX the Enclave will allocate memory for this buffer (using SGX’s specialized sgx_ocalloc instead of standard malloc).
    • size=buffer_out_len links the buffer’s size to the output length parameter, so SGX knows exactly how much data to copy from the Enclave to the untrusted side.
  • [out] size_t* buffer_out_len: This stores the length of the returned buffer—we set this value before allocating the output buffer in the Enclave.
  • [in, size=buffer_in_len] const void* buffer_in: in flags it as input, and size=buffer_in_len specifies the input buffer’s length so SGX can safely copy it into the Enclave.
  • [in] size_t buffer_in_len: The explicit length of the input buffer, paired with the previous parameter’s size attribute to validate the input.

Step 2: Enclave-Side Implementation

When writing the Enclave function, use SGX’s dedicated allocation function to ensure the buffer can be safely passed back to the untrusted side:

#include "sgx_trts.h" // For sgx_ocalloc
#include <string.h>   // For memcpy/memset

void pass_buffer(void** buffer_out, size_t* buffer_out_len, const void* buffer_in, size_t buffer_in_len) {
    // First: Calculate your required output buffer size (replace this with your actual logic)
    // Example: Return a buffer twice the input size, with original data + zero padding
    *buffer_out_len = buffer_in_len * 2;

    // Allocate the output buffer with sgx_ocalloc (critical for cross-enclave memory safety)
    *buffer_out = sgx_ocalloc(*buffer_out_len);
    if (*buffer_out == NULL) {
        // Handle allocation failure: reset length to 0 to signal error to the untrusted side
        *buffer_out_len = 0;
        return;
    }

    // Process the input data (replace this with your Enclave-specific logic)
    memcpy(*buffer_out, buffer_in, buffer_in_len);
    memset((uint8_t*)*buffer_out + buffer_in_len, 0, buffer_in_len);
}

Key rule: Never use standard malloc/free for buffers passed to the untrusted side—sgx_ocalloc allocates memory in the untrusted heap, which the untrusted code can safely free later.

Step 3: Untrusted Side Call

When calling the function from the untrusted application, initialize the buffer pointer to NULL and remember to free it with sgx_free after use:

#include "sgx_urts.h" // For sgx_enclave_id_t, sgx_status_t, sgx_free
#include <stdio.h>

void example_enclave_call(sgx_enclave_id_t enclave_id) {
    const uint8_t input_data[] = "Hello SGX!";
    size_t input_len = sizeof(input_data);

    void* output_buffer = NULL;
    size_t output_len = 0;

    // Call the Enclave function
    sgx_status_t ret = sgx_pass_buffer(enclave_id, &output_buffer, &output_len, input_data, input_len);
    if (ret != SGX_SUCCESS || output_buffer == NULL || output_len == 0) {
        printf("Error calling pass_buffer!\n");
        return;
    }

    // Use the output buffer here (e.g., print or process data)
    printf("Output buffer length: %zu\n", output_len);
    printf("Output data: %s\n", (char*)output_buffer);

    // Free the allocated buffer (must use sgx_free, not standard free())
    sgx_free(output_buffer);
}

Critical Reminders

  • Always initialize buffer_out to NULL before calling the function—SGX will overwrite it with the allocated pointer.
  • Set buffer_out_len before allocating the output buffer in the Enclave, so the size attribute in EDL has a valid value to reference.
  • Always check for allocation failures in the Enclave and handle them gracefully (resetting buffer_out_len to 0 is a clear way to signal an error to the untrusted side).

内容的提问来源于stack exchange,提问作者Guilherme Borges

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:16:20