Compiling OpenSSL engine (.so) fails to load undefined symbol


I am compiling the following OpenSSL engine, from Atmel for an ARM platform.

The code, uses 'eckey_asn1_meth' from the OpenSSL codebase:

git grep "eckey_asn1_meth"
engine_meth/eccx08_ameth.c:    extern const EVP_PKEY_ASN1_METHOD eckey_asn1_meth;
engine_meth/eccx08_ameth.c:    eccx08_pkey_asn1_meth.pub_encode = eckey_asn1_meth.pub_encode;
engine_meth/eccx08_ameth.c:    eccx08_pkey_asn1_meth.pub_decode = eckey_asn1_meth.pub_decode;
engine_meth/eccx08_ameth.c:    eccx08_pkey_asn1_meth.pub_cmp = eckey_asn1_meth.pub_cmp;
engine_meth/eccx08_ameth.c:    eccx08_pkey_asn1_meth.pub_print = eckey_asn1_meth.pub_print;
engine_meth/eccx08_ameth.c:    eccx08_pkey_asn1_meth.priv_decode = eckey_asn1_meth.priv_decode;
engine_meth/eccx08_ameth.c:    eccx08_pkey_asn1_meth.priv_encode = eckey_asn1_meth.priv_encode;
engine_meth/eccx08_ameth.c:    eccx08_pkey_asn1_meth.priv_print = eckey_asn1_meth.priv_print;
engine_meth/eccx08_ameth.c:    eccx08_pkey_asn1_meth.pkey_size = eckey_asn1_meth.pkey_size;
engine_meth/eccx08_ameth.c:    eccx08_pkey_asn1_meth.pkey_bits = eckey_asn1_meth.pkey_bits;
engine_meth/eccx08_ameth.c:    eccx08_pkey_asn1_meth.pkey_security_bits = eckey_asn1_meth.pkey_security_bits;
engine_meth/eccx08_ameth.c:    eccx08_pkey_asn1_meth.param_decode = eckey_asn1_meth.param_decode;
engine_meth/eccx08_ameth.c:    eccx08_pkey_asn1_meth.param_encode = eckey_asn1_meth.param_encode;
engine_meth/eccx08_ameth.c:    eccx08_pkey_asn1_meth.param_missing = eckey_asn1_meth.param_missing;
engine_meth/eccx08_ameth.c:    eccx08_pkey_asn1_meth.param_copy = eckey_asn1_meth.param_copy;
engine_meth/eccx08_ameth.c:    eccx08_pkey_asn1_meth.param_cmp = eckey_asn1_meth.param_cmp;
engine_meth/eccx08_ameth.c:    eccx08_pkey_asn1_meth.param_print = eckey_asn1_meth.param_print;
engine_meth/eccx08_ameth.c:    eccx08_pkey_asn1_meth.sig_print = eckey_asn1_meth.sig_print;
engine_meth/eccx08_ameth.c:    eccx08_pkey_asn1_meth.pkey_ctrl = eckey_asn1_meth.pkey_ctrl;
engine_meth/eccx08_ameth.c:    eccx08_pkey_asn1_meth.old_priv_decode = eckey_asn1_meth.old_priv_decode;
engine_meth/eccx08_ameth.c:    eccx08_pkey_asn1_meth.old_priv_encode = eckey_asn1_meth.old_priv_encode;

This is defined in the OpenSSL code:

crypto/ec/ec_ameth.c:const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = {

Now, this is the line of the Makefile that compiles the .so (the OpenSSL engine), which I do not completely understand:

LINK_SO=        \
   $(LD) -r -o $(LIBNAME).o $$ALLSYMSFLAGS $(LIB) $(LIBAMETH) && \
   ($(NM) -Pg $(LIBNAME).o | grep ' [BDT] ' | cut -f1 -d' ' > $(LIBNAME).exp; \
    $$SHAREDCMD $$SHAREDFLAGS -o $(SHLIB) $(LIBNAME).o $(LDFLAGS) -L ../install_dir/lib -lcrypto -lssl -lc \
    -Lengine_meth -Lcryptoauthlib/lib -leccx08_meth -lcryptoauth -lm -lrt)

This generates the shared library:

file ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, BuildID[sha1]=84875c59aecd0c53aaaac8aad84d6899441098c4, not stripped

However when I try to load the engine on the target, it fails:

openssl engine -t dynamic -pre SO_PATH:/usr/lib/ -pre ID:atmel -pre LIST_ADD:1 -pre LOAD
(dynamic) Dynamic engine loading support
[Success]: SO_PATH:/usr/lib/
[Success]: ID:atmel
[Success]: LIST_ADD:1
[Failure]: LOAD
1995961552:error:25066067:DSO support routines:DLFCN_LOAD:could not load the shared library:dso_dlfcn.c:187:filename(/usr/lib/ /usr/lib/ undefined symbol: eckey_asn1_meth
1995961552:error:25070067:DSO support routines:DSO_load:could not load the shared library:dso_lib.c:233:
1995961552:error:260B6084:engine routines:DYNAMIC_LOAD:dso not found:eng_dyn.c:467:
     [ unavailable ]

The undefined symbol eckey_asn1_meth is not present in the .so for the OpenSSL engine. nm shows it is unknown (U):

nm | grep eckey_asn1_meth
         U eckey_asn1_meth

However, objdump shows that the .so for the OpenSSL engine needs libcrypto:

objdump -p     file format elf32-little

Program Header:
    LOAD off    0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**16
         filesz 0x00020e50 memsz 0x00020e50 flags r-x
    LOAD off    0x00021000 vaddr 0x00031000 paddr 0x00031000 align 2**16
         filesz 0x0000119a memsz 0x00001e64 flags rw-
 DYNAMIC off    0x00021144 vaddr 0x00031144 paddr 0x00031144 align 2**2
         filesz 0x000000f0 memsz 0x000000f0 flags rw-
    NOTE off    0x000000d4 vaddr 0x000000d4 paddr 0x000000d4 align 2**2
         filesz 0x00000024 memsz 0x00000024 flags r--
   STACK off    0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**4
         filesz 0x00000000 memsz 0x00000000 flags rw-

Dynamic Section:
  INIT                 0x00005c0c
  FINI                 0x0001ed58
  INIT_ARRAY           0x00031000
  INIT_ARRAYSZ         0x00000004
  FINI_ARRAY           0x00031004
  FINI_ARRAYSZ         0x00000004
  GNU_HASH             0x000000f8
  STRTAB               0x00002d14
  SYMTAB               0x000010c4
  STRSZ                0x00001e3c
  SYMENT               0x00000010
  PLTGOT               0x00031234
  PLTRELSZ             0x00000a18
  PLTREL               0x00000011
  JMPREL               0x000051f4
  REL                  0x00004f1c
  RELSZ                0x000002d8
  RELENT               0x00000008
  VERNEED              0x00004edc
  VERNEEDNUM           0x00000002
  VERSYM               0x00004b50
  RELCOUNT             0x00000022

Version References:
  required from
    0x0d696914 0x00 03 GLIBC_2.4
  required from
    0x06a2b2e4 0x00 02 OPENSSL_1.0.2d

And the libcrypto shared library does include the symbol eckey_asn1_meth:

nm | grep eckey_asn1_meth
001642ac d eckey_asn1_meth

Why is this failing at runtime, if the unknown symbol is available in the Is there a way I can generate the .so for the OpenSSL engine in such a way that the symbol is included, and eliminate the 'U' from the nm output? Any other way to make this work?

asked on Stack Overflow Jun 14, 2017 by José D. • edited Jun 14, 2017 by José D.

0 Answers

Nobody has answered this question yet.

User contributions licensed under CC BY-SA 3.0