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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With