Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linking OpenSSL with webassembly

Linking OpenSSL to webassembly

Before asking this question I just want to say that I did some homework. The question is very similar to the one already asked here i.e. How to link OpenSSL with emscripten?

After I found a very good and detail manual how to compile OpenSSL to webassemly here https://www.ip6.li/node/129

I was able to run all steps successfully i.e.

1) first go to the directory where the latest emscripten is downloaded and set some path variables:

~/emscripten/emsdk$ source ./emsdk_env.sh

2) then execute the script from the manual above

./mk-openssl-webassemby.sh:

Basically, it all compiles without any errors but with a specific warning. After the compilation I am able to cd to the crypto/sha directory and see that the files are compiled to the so-called intermediate representation:

/openssl/openssl-1.1.0h/openssl/crypto/sha$ file sha256.o 
sha256.o: LLVM IR bitcode

While reading through other online resources, I was expecting this file to have .bc extension, but it seems that .o is also correct. Not sure about that.

I do see during the compilation the following warning :

make[2]: Entering directory '/openssl/openssl-1.1.0h/openssl'
( :; LIBDEPS="${LIBDEPS:--L. -lssl -L. -lcrypto -lsocket -lnsl }"; LDCMD="${LDCMD:-emcc}"; LDFLAGS="${LDFLAGS:--DNDEBUG -DOPENSSL_NO_DYNAMIC_ENGINE -DOPENSSL_API_COMPAT=0x10100000L -DOPENSSLDIR="\"/tmp\"" -DENGINESDIR="\"/usr/local/lib/engines-1.1\"" -g -Wall   }"; LIBPATH=`for x in $LIBDEPS; do echo $x; done | sed -e 's/^ *-L//;t' -e d | uniq`; LIBPATH=`echo $LIBPATH | sed -e 's/ /:/g'`; echo LD_LIBRARY_PATH=$LIBPATH:$LD_LIBRARY_PATH ${LDCMD} ${LDFLAGS} -o ${APPNAME:=test/buildtest_x509_vfy} test/buildtest_x509_vfy.o ${LIBDEPS}; LD_LIBRARY_PATH=$LIBPATH:$LD_LIBRARY_PATH ${LDCMD} ${LDFLAGS} -o ${APPNAME:=test/buildtest_x509_vfy} test/buildtest_x509_vfy.o ${LIBDEPS} )
LD_LIBRARY_PATH=.: emcc -DNDEBUG -DOPENSSL_NO_DYNAMIC_ENGINE -DOPENSSL_API_COMPAT=0x10100000L -DOPENSSLDIR="/tmp" -DENGINESDIR="/usr/local/lib/engines-1.1" -g -Wall -o test/buildtest_x509_vfy test/buildtest_x509_vfy.o -L. -lssl -L. -lcrypto -lsocket -lnsl
WARNING:root:emcc: cannot find library "socket"
WARNING:root:emcc: cannot find library "nsl"

basically, it says that I can not find the library socket and nsl. The important thing to mention here is that the compilation finishes without errors, i.e., only those warnings. If I manually edit the Makefile and remove those libs and hit compile the compilation finishes without any warnings. That means now that whatever external libs were there before the code would now not link to some x86 or ARM architecture, i.e. ,all need to be wasm VM specific.

export CC=emcc
export CXX=emcc
export LINK=${CXX}
export ARCH_FLAGS=""
export ARCH_LINK=""
export CPPFLAGS=" ${ARCH_FLAGS} "
export CXXFLAGS=" ${ARCH_FLAGS} "
export CFLAGS=" ${ARCH_FLAGS} "
export LDFLAGS=" ${ARCH_LINK} "
echo  $OSTYPE | grep -i darwin > /dev/null 2> /dev/null

./Configure purify --openssldir=/tmp --api=1.1.0 no-engine no-dso no-dgram no-sock no-srtp no-stdio no-ui no-err no-ocsp no-psk no-stdio no-ts

Configuring OpenSSL version 1.1.0h (0x1010008fL)
    no-afalgeng     [forced]   OPENSSL_NO_AFALGENG
    no-apps         [forced]   OPENSSL_NO_APPS
    no-asan         [default]  OPENSSL_NO_ASAN
    no-capieng      [forced]   OPENSSL_NO_CAPIENG
    no-crypto-mdebug [default]  OPENSSL_NO_CRYPTO_MDEBUG
    no-crypto-mdebug-backtrace [default]  OPENSSL_NO_CRYPTO_MDEBUG_BACKTRACE
    no-dgram        [option]   OPENSSL_NO_DGRAM
    no-dso          [option]  
    no-dtls         [forced]   OPENSSL_NO_DTLS
    no-dtls1        [forced]   OPENSSL_NO_DTLS1
    no-dtls1_2      [forced]   OPENSSL_NO_DTLS1_2
    no-dynamic-engine [forced]  
    no-ec_nistp_64_gcc_128 [default]  OPENSSL_NO_EC_NISTP_64_GCC_128
    no-egd          [default]  OPENSSL_NO_EGD
    no-engine       [option]   OPENSSL_NO_ENGINE (skip engines)
    no-err          [option]   OPENSSL_NO_ERR
    no-fuzz-afl     [default]  OPENSSL_NO_FUZZ_AFL
    no-fuzz-libfuzzer [default]  OPENSSL_NO_FUZZ_LIBFUZZER
    no-heartbeats   [default]  OPENSSL_NO_HEARTBEATS
    no-md2          [default]  OPENSSL_NO_MD2 (skip dir)
    no-msan         [default]  OPENSSL_NO_MSAN
    no-ocsp         [option]   OPENSSL_NO_OCSP (skip dir)
    no-psk          [option]   OPENSSL_NO_PSK
    no-rc5          [default]  OPENSSL_NO_RC5 (skip dir)
    no-sctp         [default]  OPENSSL_NO_SCTP
    no-sock         [option]   OPENSSL_NO_SOCK
    no-srtp         [option]   OPENSSL_NO_SRTP
    no-ssl-trace    [default]  OPENSSL_NO_SSL_TRACE
    no-ssl3         [default]  OPENSSL_NO_SSL3
    no-ssl3-method  [default]  OPENSSL_NO_SSL3_METHOD
    no-stdio        [option]   OPENSSL_NO_STDIO
    no-tests        [forced]   OPENSSL_NO_TESTS
    no-ts           [option]   OPENSSL_NO_TS (skip dir)
    no-ubsan        [default]  OPENSSL_NO_UBSAN
    no-ui           [option]   OPENSSL_NO_UI (skip dir)
    no-unit-test    [default]  OPENSSL_NO_UNIT_TEST
    no-weak-ssl-ciphers [default]  OPENSSL_NO_WEAK_SSL_CIPHERS
    no-zlib         [default] 
    no-zlib-dynamic [default] 
Configuring for purify
CC            =emcc
CFLAG         =-g -Wall 
SHARED_CFLAG  =
DEFINES       =NDEBUG OPENSSL_NO_DYNAMIC_ENGINE OPENSSL_API_COMPAT=0x10100000L
LFLAG         =
PLIB_LFLAG    =
EX_LIBS       =  -lsocket -lnsl 
APPS_OBJ      =
CPUID_OBJ     =mem_clr.o
UPLINK_OBJ    =
BN_ASM        =bn_asm.o
EC_ASM        =
DES_ENC       =des_enc.o fcrypt_b.o
AES_ENC       =aes_core.o aes_cbc.o
BF_ENC        =bf_enc.o
CAST_ENC      =c_enc.o
RC4_ENC       =rc4_enc.o rc4_skey.o
RC5_ENC       =rc5_enc.o
MD5_OBJ_ASM   =
SHA1_OBJ_ASM  =
RMD160_OBJ_ASM=
CMLL_ENC      =camellia.o cmll_misc.o cmll_cbc.o
MODES_OBJ     =
PADLOCK_OBJ   =
CHACHA_ENC    =chacha_enc.o
POLY1305_OBJ  =
BLAKE2_OBJ    =
PROCESSOR     =
RANLIB        =ranlib
ARFLAGS       =
PERL          =/usr/bin/perl

THIRTY_TWO_BIT mode

Configured for purify.

The library could not be configured for supporting multi-threaded
applications as the compiler options required on this system are not known.
See file INSTALL for details if you need multi-threading.

The options 'shared', 'pic' and 'dynamic-engine' aren't supported on this
the platform, so we will pretend you gave the option 'no-pic', which also disables
'shared' and 'dynamic-engine'.  If you know how to implement shared libraries
or independent position code, please let us know (but please first make sure
you have tried with a current version of OpenSSL).

After the compilation of the OpenSSL, I do see in the directory the following files

libcrypto.a
libcrypto.pc
libssl.a
libssl.pc

if I test to see what is that for a file, i.e., see that this is the archive that I need to link to

file libcrypto.a
libcrypto.a: current ar archive

If i test to see if the symbols are there i.e.

     llvm-nm libcrypto.a 

        sham_sha1.o:
         U EVP_MD_CTX_md_data
-------- T EVP_sha1
-------- T EVP_sha224
-------- T EVP_sha256
-------- T EVP_sha384
-------- T EVP_sha512
         U OPENSSL_cleanse
         U SHA1_Final
         U SHA1_Init
         U SHA1_Update
         U SHA224_Final
         U SHA224_Init
         U SHA224_Update
         U SHA256_Final
         U SHA256_Init
         U SHA256_Update
         U SHA384_Final
         U SHA384_Init
         U SHA384_Update
         U SHA512_Final
         U SHA512_Init
         U SHA512_Update
-------- t ctrl
-------- t final
-------- t final224
-------- t final256
-------- t final384
-------- t final512
-------- t init
-------- t init224
-------- t init256
-------- t init384
-------- t init512
-------- d sha1_md
-------- d sha224_md
-------- d sha256_md
-------- d sha384_md
-------- d sha512_md
-------- t update
-------- t update224
-------- t update256
-------- t update384
-------- t update512
...
sha256.o:
    ...
    -------- d K256
             U OPENSSL_cleanse
    -------- T SHA224
    -------- d SHA224.m
    -------- T SHA224_Final
    -------- T SHA224_Init
    -------- T SHA224_Update
    -------- T SHA256
    -------- d SHA256.m
    -------- T SHA256_Final
    -------- T SHA256_Init
    -------- T SHA256_Transform
    -------- T SHA256_Update
    -------- t sha256_block_data_order
    -------- d sha256_block_data_order.is_endian
...

llvm-nm libcrypto.a  |grep -i SHA256_Update
         U SHA256_Update
-------- T SHA256_Update

3) the problem starts when I try to link to it in my cmake i.e.

warning: unresolved symbol: SHA256_Final
warning: unresolved symbol: SHA256_Init
warning: unresolved symbol: SHA256_Update

or with verbose output:

VERBOSE is on, this generates a lot of output and can slow down compilation
warning: unresolved symbol: SHA256_Final
adding _SHA256_Final and deps  : function _SHA256_Final() {
err('missing 
warning: unresolved symbol: SHA256_Init
adding _SHA256_Init and deps  : function _SHA256_Init() {
err('missing f
warning: unresolved symbol: SHA256_Update
adding _SHA256_Update and deps  : function _SHA256_Update() {
err('missing
adding ___buildEnvironment and deps $ENV : function ___buildEnvironment(environ) {

the funny thing is that the webassembly loads and I am able to execute method that is not depending on OpenSSL, but as soon as I try to execute some OpenSSL methods then I get the following error in Firefox Console:

missing function: SHA256_Init

in my CmakeLists.txt I have two directories that I use i.e.

set( OPENSSL_INCLUDE_DIR  /openssl/openssl-1.1.0h/openssl/include )
set( OPENSSL_LINK_DIR /openssl/openssl-1.1.0h/openssl )

and I have the target command that looks like

set_target_properties(mainTest PROPERTIES LINK_FLAGS " -s WASM=1  -s NO_EXIT_RUNTIME=1 -s VERBOSE=1 -lssl -lcrypto --pre-js preModule.js")

It builds the wasm, but I can not use those methods. I am wondering why I am getting those " unresolved symbol" warrings. Any help is much appreciated.

like image 756
Tito Avatar asked Sep 14 '18 07:09

Tito


1 Answers

The solution was pretty simple. I have forgotten to add to the cmake file the following

target_link_libraries(mainTest crypto) after that it all worked without warnings.

like image 200
Tito Avatar answered Jan 04 '23 07:01

Tito