BlockstreamResearch / secp256k1-zkp

A fork of libsecp256k1 with support for advanced and experimental features such as Confidential Assets and MuSig2
MIT License
365 stars 207 forks source link

question: Build library without standard IO functions #262

Closed ssantos21 closed 1 year ago

ssantos21 commented 1 year ago

I'm using secp256k1-zkp as a library in an Intel SGX Enclave project. When any secp256k1-zkp function is called in the untrusted environment, the project builds successfully. But I got the error below when secp256k1-zkp functions are called in Enclave trusted environment.

The reason, I think, is taht the secp256k1-zkp library seems to have references to fprintf and stderr, which are standard C library functions and global variables. In the context of Intel SGX enclaves, the standard C library is not directly accessible in the same manner as regular applications.

So the linker (/usr/local/bin/ld) is unable to find references for stderr and __fprintf_chk, causing the "undefined reference" error.

Is there a way to compile the secp256k1-zkp library in a way that doesn't reference any functionality that isn't supported inside an enclave, like standard IO functions?

/usr/local/bin/ld: secp256k1-zkp/.libs/libsecp256k1.a(libsecp256k1_la-secp256k1.o): warning: relocation against `stderr' in read-only section `.text'
/usr/local/bin/ld: secp256k1-zkp/.libs/libsecp256k1.a(libsecp256k1_la-secp256k1.o): in function `fprintf':
/usr/include/x86_64-linux-gnu/bits/stdio2.h:105: undefined reference to `stderr'
/usr/local/bin/ld: /usr/include/x86_64-linux-gnu/bits/stdio2.h:105: undefined reference to `__fprintf_chk'
/usr/local/bin/ld: /usr/include/x86_64-linux-gnu/bits/stdio2.h:105: undefined reference to `stderr'
/usr/local/bin/ld: /usr/include/x86_64-linux-gnu/bits/stdio2.h:105: undefined reference to `__fprintf_chk'
/usr/local/bin/ld: warning: creating DT_TEXTREL in a PIE

I am building the secp256k1-zkp lib with --enable-module-schnorrsig --enable-experimental --enable-module-musig flags and including ./secp256k1-zkp/.libs/libsecp256k1.a in the main project build.

real-or-random commented 1 year ago

This is related to the callbacks, see the docs for secp256k1_set_illegal_callback and secp256k1_set_error_callback. The default callbacks print error messages, and so they need fprintf and stderr.

You need to configure with --enable-external-default-callbacks and then provide default callbacks: https://github.com/BlockstreamResearch/secp256k1-zkp/blob/bfeae121fb0e8dd88af33390b1e163feca067bfd/include/secp256k1.h#L277-L285

These should abort your program (but without printing an error message).

ssantos21 commented 1 year ago

@real-or-random Thanks for the quick answer.

I am now compiling with ./configure --enable-module-schnorrsig --enable-experimental --enable-module-musig --enable-external-default-callbacks --enable-benchmark=no --enable-tests=no --enable-exhaustive-tests=no.

The libsecp256k1 compiled successfully, but I got the error below when calling its functions.

/usr/local/bin/ld: secp256k1-zkp/.libs/libsecp256k1.a(libsecp256k1_la-secp256k1.o): in function `secp256k1_callback_call':
/home/user/intel-sgx-enclave-server/secp256k1-zkp/src/util.h:25: undefined reference to `secp256k1_default_illegal_callback_fn'
/usr/local/bin/ld: secp256k1-zkp/.libs/libsecp256k1.a(libsecp256k1_la-secp256k1.o): in function `secp256k1_context_preallocated_create':
/home/user/intel-sgx-enclave-server/secp256k1-zkp/src/secp256k1.c:117: undefined reference to `secp256k1_default_illegal_callback_fn'
/usr/local/bin/ld: /home/user/intel-sgx-enclave-server/secp256k1-zkp/src/secp256k1.c:118: undefined reference to `secp256k1_default_error_callback_fn'
/usr/local/bin/ld: secp256k1-zkp/.libs/libsecp256k1.a(libsecp256k1_la-secp256k1.o): in function `secp256k1_callback_call':
/home/user/intel-sgx-enclave-server/secp256k1-zkp/src/util.h:25: undefined reference to `secp256k1_default_error_callback_fn'
/usr/local/bin/ld: /home/user/intel-sgx-enclave-server/secp256k1-zkp/src/util.h:25: undefined reference to `secp256k1_default_illegal_callback_fn'
/usr/local/bin/ld: /home/user/intel-sgx-enclave-server/secp256k1-zkp/src/util.h:25: undefined reference to `secp256k1_default_illegal_callback_fn'
/usr/local/bin/ld: /home/user/intel-sgx-enclave-server/secp256k1-zkp/src/util.h:25: undefined reference to `secp256k1_default_error_callback_fn'
/usr/local/bin/ld: secp256k1-zkp/.libs/libsecp256k1.a(libsecp256k1_la-secp256k1.o): in function `secp256k1_context_set_illegal_callback':
/home/user/intel-sgx-enclave-server/secp256k1-zkp/src/secp256k1.c:177: undefined reference to `secp256k1_default_illegal_callback_fn'
/usr/local/bin/ld: secp256k1-zkp/.libs/libsecp256k1.a(libsecp256k1_la-secp256k1.o): in function `secp256k1_context_set_error_callback':
/home/user/intel-sgx-enclave-server/secp256k1-zkp/src/secp256k1.c:186: undefined reference to `secp256k1_default_error_callback_fn'
/usr/local/bin/ld: secp256k1-zkp/.libs/libsecp256k1.a(libsecp256k1_la-secp256k1.o):(.data.rel.ro+0xa8): undefined reference to `secp256k1_default_illegal_callback_fn'
/usr/local/bin/ld: secp256k1-zkp/.libs/libsecp256k1.a(libsecp256k1_la-secp256k1.o):(.data.rel.ro+0xb8): undefined reference to `secp256k1_default_error_callback_fn'
collect2: error: ld returned 1 exit status

The code is:

void counting_illegal_callback_fn(const char* str, void* data) {
    /* Dummy callback function that just counts. */
    int32_t *p;
    (void)str;
    p = (int32_t *) data;
    (*p)++;
}

int test_secp256k1_zkp() {
    unsigned char seckey[32];

    secp256k1_context* ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN | SECP256K1_CONTEXT_VERIFY);

    int32_t ecount = 0;
    int32_t ecount2 = 10;
    secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount);
    secp256k1_context_set_illegal_callback(ctx, counting_illegal_callback_fn, &ecount2);

    // ...

   secp256k1_context_destroy(ctx);
    return 1;
}
real-or-random commented 1 year ago

As I quoted above, you have to define functions

  *   - void secp256k1_default_illegal_callback_fn(const char* message, void* data); 
  *   - void secp256k1_default_error_callback_fn(const char* message, void* data); 

I don't see them in your code.

ssantos21 commented 1 year ago

Thanks for the detailed explanation @real-or-random I had misunderstood the solution.

I managed to solve it with the following code:

extern "C" {
    #include "../secp256k1-zkp/include/secp256k1.h"
    #include "../secp256k1-zkp/include/secp256k1_schnorrsig.h"
    #include "../secp256k1-zkp/include/secp256k1_musig.h"

    void secp256k1_default_illegal_callback_fn(const char* str, void* data) {
        (void)str;
        (void)data;
        abort();
    }

    void secp256k1_default_error_callback_fn(const char* str, void* data) {
        (void)str;
        (void)data;
        abort();
    }
}