让终端支持https,移植OpenSSL和libcurl到嵌入式linux,遇到的问题总结

简介: 让终端支持https,移植OpenSSL和libcurl到嵌入式linux,遇到的问题总结

从官网下载openssl源码和 libcurl源码。OpenSSL顺利交叉编译通过。


版本:OpenSSL openssl-1.1.0c.tar.gz版本


curl版本 curl-7.57.0.tar.gz  


tar -axvf .....


准备开始交叉编译OpenSSL


在openssl解压目录下,使用config命令


CC=arm-linux-gcc ./config no-asm shared --prefix=/home/linux/arm/openssl --openssldir=/home/linux/arm/openssl/ssl


生成了Makefile


然后就是make和make install


之后会在安装目录下生成lib文件


再编译libcurl时编译没问题,但链接时出现问题,如下:


CCLD     curl
/home/yang/b503/ctools/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux/bin/../lib/gcc/arm-linux-gnueabihf/4.9.2/../../../../arm-linux-gnueabihf/bin/ld: warning: libssl.so.1.1, needed by ../lib/.libs/libcurl.so, not found (try using -rpath or -rpath-link)
/home/yang/b503/ctools/gcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux/bin/../lib/gcc/arm-linux-gnueabihf/4.9.2/../../../../arm-linux-gnueabihf/bin/ld: warning: libcrypto.so.1.1, needed by ../lib/.libs/libcurl.so, not found (try using -rpath or -rpath-link)
../lib/.libs/libcurl.so: undefined reference to `X509_EXTENSION_get_object@OPENSSL_1_1_0'
../lib/.libs/libcurl.so: undefined reference to `SHA256_Final@OPENSSL_1_1_0'
../lib/.libs/libcurl.so: undefined reference to `SSL_get_peer_cert_chain@OPENSSL_1_1_0'
../lib/.libs/libcurl.so: undefined reference to `OPENSSL_load_builtin_modules@OPENSSL_1_1_0'
../lib/.libs/libcurl.so: undefined reference to `PKCS12_parse@OPENSSL_1_1_0'
../lib/.libs/libcurl.so: undefined reference to `ASN1_TIME_print@OPENSSL_1_1_0'
../lib/.libs/libcurl.so: undefined reference to `SSL_shutdown@OPENSSL_1_1_0'
../lib/.libs/libcurl.so: undefined reference to `CONF_modules_load_file@OPENSSL_1_1_0'


但是我的configure的配置明明已经指定了OpenSSL库的位置啊,OpenSSL库也是已经编译成功了的。为什么链接时还是报找不到openssl库呢?


我的openssl库编译完成后,位置位于 /home/linux/arm/openssl/lib


我的configure配置如下:


CPPFLAGS="-I/home/linux/arm/openssl/ -I/home/linux/arm/openssl/include" LDFLAGS="-L/home/linux/arm/openssl/lib" LIBS="-ldl" ./configure --host=arm-linux CC=arm-linux-gnueabihf-gcc CXX=arm-linux-gnueabihf-g++ --with-ssl --enable-shared --enable-static --disable-dict --disable-ftp --disable-imap --disable-ldap --disable-ldaps --disable-pop3 --disable-proxy --disable-rtsp --disable-smtp --disable-telnet --disable-tftp --disable-zlib --without-ca-bundle --without-gnutls --without-libidn --without-librtmp --without-libssh2 --without-nss --without-zlib --prefix=/home/linux/arm/curl


这里 LDFLAGS="-L/home/linux/arm/openssl/lib"已经指定了的,链接查找的路径。但是就是找不到。


看了下自动生成的Makefile,没发现有什么问题,


最后打开libtool文件,发现链接查找的路径里没有这个/home/linux/arm/openssl/lib。最后干脆把OpenSSL库拷贝到工具链查找的路径下,最后链接通过了。




但是原因是什么呢?


最后,改 LIBS="-ldl -lssl -lcrypto" ,加上去了 lssl和 lcrypto,顺利编译通过。原因或许就出在这里。


添加了LDFLAGS,相当于扩展了工具链的搜索路径,但是 链接时,得指定下 链接什么,


原来的LIBS="-ldl",没有指定 链接 ssl,


是否就是这个原因引起的?欢迎指正


编译参数 :


root@yang-vir:/home/yang/test/curl-7.57.0# 
setarch i386 ./configure --host=arm-linux CC=arm-linux-gnueabihf-gcc CXX=arm-linux-gnueabihf-g++ CPPFLAGS="-I/home/linux/arm/openssl/ -I/home/linux/arm/openssl/include" LDFLAGS="-L/home/linux/arm/openssl/lib" LIBS="-ldl -lssl -lcrypto" --with-ssl --enable-shared --enable-static --disable-dict --disable-ftp --disable-imap --disable-ldap --disable-ldaps --disable-pop3 --disable-proxy --disable-rtsp --disable-smtp --disable-telnet --disable-tftp --disable-zlib --without-ca-bundle --without-gnutls --without-libidn --without-librtmp --without-libssh2 --without-nss --without-zlib --prefix=/home/linux/arm/curl
openssl1.1.0h 编译参数:
CC=arm-linux-gnueabihf-gcc setarch i386 ./config no-asm shared -DOPENSSL_NO_HEARTBEATS  --prefix=/home/linux/arm/openssl --openssldir=/home/linux/arm/openssl/ssl


遇到一个问题,咱还没解决,同样的测试,在电脑上OK,在ARM板子上报错,如下


curl https://xxx.xxx.xxx.xxx:xxxx-v --cacert ./UP.pem -k -H 'User-Agent: Donjin Http 0.1' -H 'Content-Type: x-ISO-TPDU/x-auth' -H 'Cache-Control: no-cache' -H 'Content-Length: 93' --data-binary @aaa.bin
* Rebuilt URL to: https://xxx.xxx.xxx.xxx
*   Trying xxx.xxx.xxx.xxx...
* TCP_NODELAY set
* Connected to xxx.xxx.xxx.xxx(140.xx.xx.xx) port xxxx (#0)
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: ./UP.pem
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* error:0306E06C:bignum routines:BN_mod_inverse:no inverse
* Closing connection 0
curl: (35) error:0306E06C:bignum routines:BN_mod_inverse:no inverse


最后,问题已解决。原因不明确。用从github上下载的官方稳定版 1.1-stable版,重新编译。


暂未出现上述问题。难道之前下载的版本有bug?


2018.4.26日记:


好消息,有重大发现,之前不一定是这个原因导致的!!!!!


因为我把https加进我的应用后,让我的应用发起https请求总是会崩,报segment falut,连个日志和堆栈信息都看不到。


一度怀疑 是openssl不支持多线程的原因。折腾了几天仍找不到解决办法。想到用 进程间通信暂时解决吧,


但是呢,测试了下,效率太低了,联机银联双免交易速度7~9秒,太长了。让应用的报文通过 进程间通信的


消息队列的方式,发给单独的进程去发起https请求。 又想进一步改为 共享内存的形式看能否提高交易速度。


正准备尝试呢,突然想到,为什么不去做个demo,抛开我的应用,去测测 到底OpenSSL支不支持多线程。


写了个demo,结果发现无论我怎么试,都没有崩。于是乎,,,问题可能出现应用上,但会是哪里呢?


我的测试验证方法如下,把 gcc编译参数 搞成一致,编译后运行看会不会崩。结果不会崩。


在把所有链接的动态库也加上去,虽然没用到,但是至少链接进去不影响什么。结果,,,,你猜怎么?


崩啦,于是我高兴了,定位到问题了,就是链接了某个库导致的,但具体是哪个呢?于是开始挨个试,


最后竟发现,是支付宝二维码的脱机认证库惹的祸。把它去掉,别链接进去。试了下,我的应用也不在崩啦!!


于是乎想看看这libposoffline.so里面到底有什么。咋影响了我的openssl.。


结果,测试如下,果然有影响:看这里面的函数,在openssl里也有。这导致了我的应用只要访问https就崩。


strings libposoffline.so
__gmon_start__
_fini
_ITM_deregisterTMCloneTable
_ITM_registerTMCloneTable
__cxa_finalize
_Jv_RegisterClasses
tolower
strlen
memcpy
memset
sprintf
__fpclassify
floor
strcpy
strchr
strncmp
strcat
strrchr
atoi
strcmp
get_qrcode_info
init_pos_verify
verify_qrcode_v2
verify_qrcode
get_key_id
strncpy
EC_KEY_new_by_curve_name
SHA1_Init
SHA1_Update
SHA1_Final
OPENSSL_cleanse
EC_KEY_generate_key
EC_KEY_get0_group
EC_KEY_get0_private_key
EC_KEY_get0_public_key
BN_bn2hex
EC_POINT_point2hex
EC_KEY_free
CRYPTO_free
EC_POINT_new
EC_POINT_hex2point
EC_KEY_set_public_key
ECDSA_verify
EC_POINT_free
BN_new
BN_hex2bn
EC_KEY_set_private_key
ECDSA_sign
BN_free
EVP_md5
HMAC_CTX_init
HMAC_Init_ex
HMAC_Update
HMAC_Final
HMAC_CTX_cleanup
CRYPTO_set_mem_functions
OPENSSL_init
CRYPTO_set_mem_ex_functions
CRYPTO_set_locked_mem_functions
CRYPTO_set_locked_mem_ex_functions
CRYPTO_set_mem_debug_functions
CRYPTO_get_mem_functions
CRYPTO_get_mem_ex_functions
CRYPTO_get_locked_mem_functions
CRYPTO_get_locked_mem_ex_functions
CRYPTO_get_mem_debug_functions
CRYPTO_malloc_locked
cleanse_ctr
CRYPTO_free_locked
CRYPTO_malloc
CRYPTO_strdup
CRYPTO_realloc
CRYPTO_realloc_clean
CRYPTO_remalloc
CRYPTO_set_mem_debug_options
CRYPTO_get_mem_debug_options
memchr
SHA1_Transform
SHA1_version
EVP_MD_block_size
EVP_DigestInit_ex
EVP_DigestUpdate
EVP_DigestFinal_ex
OpenSSLDie
EVP_MD_CTX_copy_ex
EVP_MD_CTX_init
HMAC_Init
HMAC_CTX_copy
EVP_MD_CTX_copy
EVP_MD_CTX_cleanup
HMAC_CTX_set_flags
EVP_MD_CTX_set_flags
ERR_put_error
BN_set_params
BN_get_params
BN_value_one
BN_num_bits_word
BN_num_bits
BN_clear_free
BN_init
bn_expand2
BN_copy
BN_dup
bn_dup_expand
BN_swap
BN_clear
BN_get_word
BN_set_word
BN_bin2bn
BN_bn2bin
BN_ucmp
BN_cmp
BN_set_bit
BN_clear_bit
BN_is_bit_set
BN_mask_bits
BN_set_negative
bn_cmp_words
bn_cmp_part_words
BN_consttime_swap
BN_version
BN_bn2dec
BN_div_word
BIO_snprintf
__ctype_b_loc
BN_dec2bn
BN_mul_word
BN_add_word
BN_asc2bn
BN_print
BIO_write
BN_print_fp
BIO_s_file
BIO_new
BIO_ctrl
BIO_free
BN_options
BN_mod_word
BN_lshift
bn_div_words
BN_sub_word
bn_mul_words
bn_mul_add_words
bn_sqr_words
bn_add_words
bn_sub_words
bn_mul_comba8
bn_mul_comba4
bn_sqr_comba8
bn_sqr_comba4
bn_mul_mont
EC_GROUP_new
EC_GROUP_method_of
EC_METHOD_get_field_type
EC_GROUP_get0_generator
EC_GROUP_get_mont_data
EC_GROUP_get_order
EC_GROUP_get_cofactor
EC_GROUP_set_curve_name
EC_GROUP_get_curve_name
EC_GROUP_set_asn1_flag
EC_GROUP_get_asn1_flag
EC_GROUP_set_point_conversion_form
EC_GROUP_get_point_conversion_form
EC_GROUP_set_seed
EC_GROUP_get0_seed
EC_GROUP_get_seed_len
EC_GROUP_set_curve_GFp
EC_GROUP_get_curve_GFp
EC_GROUP_set_curve_GF2m
EC_GROUP_get_curve_GF2m
EC_GROUP_get_degree
EC_GROUP_check_discriminant
EC_EX_DATA_set_data
EC_EX_DATA_get_data
EC_EX_DATA_free_data
EC_EX_DATA_clear_free_data
EC_EX_DATA_free_all_data
EC_EX_DATA_clear_free_all_data
EC_GROUP_free
BN_MONT_CTX_free
EC_POINT_clear_free
EC_GROUP_clear_free
EC_POINT_copy
EC_GROUP_copy
BN_MONT_CTX_copy
BN_MONT_CTX_new
EC_GROUP_dup
EC_POINT_dup
EC_POINT_method_of
EC_POINT_set_to_infinity
EC_POINT_set_Jprojective_coordinates_GFp
EC_POINT_get_Jprojective_coordinates_GFp
EC_POINT_set_affine_coordinates_GFp
EC_POINT_set_affine_coordinates_GF2m
EC_POINT_get_affine_coordinates_GFp
EC_POINT_get_affine_coordinates_GF2m
EC_POINT_add
EC_POINT_dbl
EC_POINT_invert
EC_POINT_is_at_infinity
EC_POINT_is_on_curve
EC_POINT_cmp
EC_GROUP_cmp
BN_CTX_start
BN_CTX_get
BN_CTX_end
BN_CTX_free
BN_CTX_new
EC_POINT_make_affine
EC_POINTs_make_affine
EC_POINTs_mul
ec_wNAF_mul
EC_POINT_mul
EC_GROUP_precompute_mult
ec_wNAF_precompute_mult
EC_GROUP_have_precompute_mult
ec_wNAF_have_precompute_mult
ec_precompute_mont_data
BN_MONT_CTX_set
EC_GROUP_set_generator
EC_version
CRYPTO_add_lock
EC_POINT_point2bn
EC_POINT_point2oct
EC_POINT_bn2point
EC_POINT_oct2point
EC_KEY_new
EC_GROUP_new_by_curve_name
EC_KEY_copy
EC_KEY_dup
EC_KEY_up_ref
BN_rand_range
EC_KEY_check_key
EC_KEY_set_group
EC_KEY_set_public_key_affine_coordinates
EC_KEY_get_enc_flags
EC_KEY_set_enc_flags
EC_KEY_get_conv_form
EC_KEY_set_conv_form
EC_KEY_get_key_method_data
CRYPTO_lock
EC_KEY_insert_key_method_data
EC_KEY_set_asn1_flag
EC_KEY_precompute_mult
EC_KEY_get_flags
EC_KEY_set_flags
EC_KEY_clear_flags
EC_POINT_set_compressed_coordinates_GFp
ec_GF2m_simple_set_compressed_coordinates
ec_GFp_simple_set_compressed_coordinates
EC_POINT_set_compressed_coordinates_GF2m
ec_GF2m_simple_point2oct
ec_GFp_simple_point2oct
ec_GF2m_simple_oct2point
ec_GFp_simple_oct2point
ECDSA_do_sign_ex
ecdsa_check
ECDSA_do_sign
ECDSA_sign_ex
RAND_seed
i2d_ECDSA_SIG
ECDSA_SIG_free
ECDSA_sign_setup
ECDSA_do_verify
ECDSA_SIG_new
d2i_ECDSA_SIG
BIO_set
CRYPTO_new_ex_data
CRYPTO_free_ex_data
BIO_vfree
BIO_clear_flags
BIO_test_flags
BIO_set_flags
BIO_get_callback
BIO_set_callback
BIO_set_callback_arg
BIO_get_callback_arg
BIO_method_name
BIO_method_type
BIO_read
BIO_puts
BIO_gets
BIO_indent
BIO_int_ctrl
=========>>>catch signal 11 <<<=========
Dump stack start...
backtrace() returned 0 addresses
Dump stack end...
readData..162..exit..connect..error..
modemDeamon.c...readerLoop...close..client_fd = 4
Segmentation fault
root@b503_lcd:/app/city_app/bin# ./b503_app1
root@b503_lcd:/app# ./test
task1 run...
=================================>>thread tid = 1976562784 start...
thread begin post:
data:00,5b postlen:147
->begin send:
* Rebuilt URL to: https://xx.207.168.xx:xxxxx0/
*   Trying xxx.xxx.xx.xx...
* TCP_NODELAY set
* Connected to xxx.xxx.xxx.xxxx (xxx.xxx.xxx.xxx) port xxxxx (#0)
Segmentation fault


到此为止,这个问题可以结贴了。不要怀疑openssl了。且官网查看说明,openssl1.09之后的版本都内建支持多线程。


之前的版本需要hook进去锁。


因此也总结了一种解决这类问题的方法,写个demo尽最大限度的去模拟,看能否复现问题。排除应用里复杂代码和逻辑等的影响。如果能复现问题,原因就明朗了。


今天又发现一问题,收获满满,在多线程程序中,请慎用类似memcpy等的拷贝。这类涉及内存操作的要尤其谨慎。


今天遇到的新问题,最后定位到原因是memcpy.最后自己写了个拷贝函数解决了。


相关文章
|
8月前
|
JavaScript Linux 网络安全
Termux安卓终端美化与开发实战:从下载到插件优化,小白也能玩转Linux
Termux是一款安卓平台上的开源终端模拟器,支持apt包管理、SSH连接及Python/Node.js/C++开发环境搭建,被誉为“手机上的Linux系统”。其特点包括零ROOT权限、跨平台开发和强大扩展性。本文详细介绍其安装准备、基础与高级环境配置、必备插件推荐、常见问题解决方法以及延伸学习资源,帮助用户充分利用Termux进行开发与学习。适用于Android 7+设备,原创内容转载请注明来源。
1892 77
|
6月前
|
Linux 网络安全 iOS开发
SecureCRT & SecureFX 9.6.3 for macOS, Linux, Windows - 跨平台的多协议终端仿真和文件传输
SecureCRT & SecureFX 9.6.3 for macOS, Linux, Windows - 跨平台的多协议终端仿真和文件传输
1498 4
SecureCRT & SecureFX 9.6.3 for macOS, Linux, Windows - 跨平台的多协议终端仿真和文件传输
|
10月前
|
Ubuntu Linux 开发者
Ubuntu20.04搭建嵌入式linux网络加载内核、设备树和根文件系统
使用上述U-Boot命令配置并启动嵌入式设备。如果配置正确,设备将通过TFTP加载内核和设备树,并通过NFS挂载根文件系统。
543 15
|
11月前
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
489 13
|
运维 Java Linux
Linux 下命令后台运行秘籍:无惧终端断开的魔法
本文详细介绍了在 Linux 系统下使命令不受终端断开影响、持续在后台运行的多种方法及其原理。包括使用 `nohup`、`setsid`、括号括起来、作业调度和 `screen` 等技巧,帮助读者提高工作效率,确保任务不被意外中断。
479 0
Linux 下命令后台运行秘籍:无惧终端断开的魔法
|
Shell Linux API
C语言在linux环境下执行终端命令
本文介绍了在Linux环境下使用C语言执行终端命令的方法。首先,文章描述了`system()`函数,其可以直接执行shell命令并返回结果。接着介绍了更强大的`popen()`函数,它允许程序与命令行命令交互,并详细说明了如何使用此函数及其配套的`pclose()`函数。此外,还讲解了`fork()`和`exec`系列函数,前者创建新进程,后者替换当前进程执行文件。最后,对比了`system()`与`exec`系列函数的区别,并针对不同场景推荐了合适的函数选择。
|
NoSQL Linux C语言
嵌入式GDB调试Linux C程序或交叉编译(开发板)
【8月更文挑战第24天】本文档介绍了如何在嵌入式环境下使用GDB调试Linux C程序及进行交叉编译。调试步骤包括:编译程序时加入`-g`选项以生成调试信息;启动GDB并加载程序;设置断点;运行程序至断点;单步执行代码;查看变量值;继续执行或退出GDB。对于交叉编译,需安装对应架构的交叉编译工具链,配置编译环境,使用工具链编译程序,并将程序传输到开发板进行调试。过程中可能遇到工具链不匹配等问题,需针对性解决。
785 3
|
传感器 人工智能 网络协议
:嵌入式 Linux 及其用途
【8月更文挑战第24天】
617 0
|
消息中间件 缓存 Unix
[面试必备]嵌入式Linux内核开发必须了解的三十道题
[面试必备]嵌入式Linux内核开发必须了解的三十道题
|
Linux Go 人机交互
嵌入式linux之go语言开发(十三)LittlevGL,漂亮的嵌入式GUI的go语言绑定
嵌入式linux之go语言开发(十三)LittlevGL,漂亮的嵌入式GUI的go语言绑定