为该死的 Android 编译新版本的 OpenSSL 库

不知道从什么时候起,大家都喜欢把简单的事情复杂化,好像越难用就越牛逼一样。装逼的倒是无所谓,等到要用的时候就傻了。以上是题外话。手机上的 Android ICS 的 OpenSSL 库版本较旧( 1.0.0e ),在神奇的地方使用容易出现一些问题,因此打算用新版本的替换掉,看看能不能解决在兲朝时不时出现的 SSL 错误(手机上特有的现象)。另外安装 openssl 命令行工具也可以用于手机处理器性能的 benchmark 。

整个工作的基础是 http://crrrazzzy.blogspot.co.il/p/steps-for-porting-openssl-for-android.html ,但是必须跳过第六步——这一步会导致诸多麻烦。最后得到的 SSL 库是为应用设计的,并不能替代系统的 SSL 库,因此还需要修改。

源码修改

首先,去 http://developer.android.com/tools/sdk/ndk/index.html 下载最新的 Android NDK ,去 http://www.openssl.org/source/ 下载 OpenSSL 的最新源码。解压这两个包。

接着,在 OpenSSL 源码目录下执行:

# For ARM Cortex
./Configure android-armv7 -DL_ENDIAN
# For x86
./Configure android-x86 -DL_ENDIAN

然后:

cp LICENSE NOTICE
touch MODULE_LICENSE_BSD_LIKE
rm -f AndroidManifest.xml

接下来,查看 Makefile 里的 CFLAG 和 DEPFLAG ,接着创建如下的 android-config.mk :

# From CLFAG (Please replace)
LOCAL_CFLAGS += -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H \
                -DL_ENDIAN -O3 -fomit-frame-pointer -Wall

# From DEPFLAG (Please replace)
LOCAL_CFLAGS += -DOPENSSL_NO_EC_NISTP_64_GCC_128 -DOPENSSL_NO_SCTP \
                -DOPENSSL_NO_CAMELLIA -DOPENSSL_NO_CAPIENG -DOPENSSL_NO_CAST \
                -DOPENSSL_NO_CMS -DOPENSSL_NO_GMP -DOPENSSL_NO_IDEA \
                -DOPENSSL_NO_JPAKE -DOPENSSL_NO_MD2 -DOPENSSL_NO_MDC2 \
                -DOPENSSL_NO_RC5 -DOPENSSL_NO_SHA0 -DOPENSSL_NO_RFC3779 \
                -DOPENSSL_NO_SEED -DOPENSSL_NO_STORE -DOPENSSL_NO_WHIRLPOOL

# Extra
LOCAL_CFLAGS += -DZLIB -DOPENSSL_NO_HW -DOPENSSL_NO_GOST

然后还需要一大票 Android.mk (老老实实用 Makefile 能死人吗?):

jni/Application.mk (目录需自行创建):

APP_PROJECT_PATH := $(shell pwd)
APP_BUILD_SCRIPT := $(APP_PROJECT_PATH)/Android.mk

Android.mk :

LOCAL_PATH := $(call my-dir)

subdirs := $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, \
		crypto \
		ssl \
		apps \
	))

include $(subdirs)

apps/Android.mk :

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \
	app_rand.c \
	apps.c \
	asn1pars.c \
	ca.c \
	ciphers.c \
	crl.c \
	crl2p7.c \
	dgst.c \
	dh.c \
	dhparam.c \
	dsa.c \
	dsaparam.c \
	ecparam.c \
	ec.c \
	enc.c \
	engine.c \
	errstr.c \
	gendh.c \
	gendsa.c \
	genpkey.c \
	genrsa.c \
	nseq.c \
	ocsp.c \
	openssl.c \
	passwd.c \
	pkcs12.c \
	pkcs7.c \
	pkcs8.c \
	pkey.c \
	pkeyparam.c \
	pkeyutl.c \
	prime.c \
	rand.c \
	req.c \
	rsa.c \
	rsautl.c \
	s_cb.c \
	s_client.c \
	s_server.c \
	s_socket.c \
	s_time.c \
	sess_id.c \
	smime.c \
	speed.c \
	spkac.c \
	srp.c \
	verify.c \
	version.c \
	x509.c

LOCAL_SHARED_LIBRARIES := \
	libssl \
	libcrypto

LOCAL_C_INCLUDES := \
	$(NDK_PROJECT_PATH) \
	$(NDK_PROJECT_PATH)/include \
	$(NDK_PROJECT_PATH)/../include

LOCAL_CFLAGS := -DMONOLITH

include $(LOCAL_PATH)/../android-config.mk

LOCAL_CFLAGS += -DOPENSSL_NO_DTLS1

LOCAL_MODULE:= openssl

LOCAL_MODULE_TAGS := tests

include $(BUILD_EXECUTABLE)

crypto/Android.mk (尤其注意需要打开 engine ):

LOCAL_PATH:= $(call my-dir)

arm_cflags := -DOPENSSL_BN_ASM_MONT -DAES_ASM -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM
arm_src_files := \
    aes/asm/aes-armv4.S \
    bn/asm/armv4-mont.S \
    sha/asm/sha1-armv4-large.S \
    sha/asm/sha256-armv4.S \
    sha/asm/sha512-armv4.S

non_arm_src_files := aes/aes_core.c

local_src_files := \
	cryptlib.c \
	mem.c \
	mem_clr.c \
	mem_dbg.c \
	cversion.c \
	ex_data.c \
	cpt_err.c \
	ebcdic.c \
	uid.c \
	o_time.c \
	o_str.c \
	o_dir.c \
	o_fips.c \
	o_init.c \
	fips_ers.c \
	aes/aes_cbc.c \
	aes/aes_cfb.c \
	aes/aes_ctr.c \
	aes/aes_ecb.c \
	aes/aes_ige.c \
	aes/aes_misc.c \
	aes/aes_ofb.c \
	aes/aes_wrap.c \
	asn1/a_bitstr.c \
	asn1/a_bool.c \
	asn1/a_bytes.c \
	asn1/a_d2i_fp.c \
	asn1/a_digest.c \
	asn1/a_dup.c \
	asn1/a_enum.c \
	asn1/a_gentm.c \
	asn1/a_i2d_fp.c \
	asn1/a_int.c \
	asn1/a_mbstr.c \
	asn1/a_object.c \
	asn1/a_octet.c \
	asn1/a_print.c \
	asn1/a_set.c \
	asn1/a_sign.c \
	asn1/a_strex.c \
	asn1/a_strnid.c \
	asn1/a_time.c \
	asn1/a_type.c \
	asn1/a_utctm.c \
	asn1/a_utf8.c \
	asn1/a_verify.c \
	asn1/ameth_lib.c \
	asn1/asn1_err.c \
	asn1/asn1_gen.c \
	asn1/asn1_lib.c \
	asn1/asn1_par.c \
	asn1/asn_mime.c \
	asn1/asn_moid.c \
	asn1/asn_pack.c \
	asn1/bio_asn1.c \
	asn1/bio_ndef.c \
	asn1/d2i_pr.c \
	asn1/d2i_pu.c \
	asn1/evp_asn1.c \
	asn1/f_enum.c \
	asn1/f_int.c \
	asn1/f_string.c \
	asn1/i2d_pr.c \
	asn1/i2d_pu.c \
	asn1/n_pkey.c \
	asn1/nsseq.c \
	asn1/p5_pbe.c \
	asn1/p5_pbev2.c \
	asn1/p8_pkey.c \
	asn1/t_bitst.c \
	asn1/t_crl.c \
	asn1/t_pkey.c \
	asn1/t_req.c \
	asn1/t_spki.c \
	asn1/t_x509.c \
	asn1/t_x509a.c \
	asn1/tasn_dec.c \
	asn1/tasn_enc.c \
	asn1/tasn_fre.c \
	asn1/tasn_new.c \
	asn1/tasn_prn.c \
	asn1/tasn_typ.c \
	asn1/tasn_utl.c \
	asn1/x_algor.c \
	asn1/x_attrib.c \
	asn1/x_bignum.c \
	asn1/x_crl.c \
	asn1/x_exten.c \
	asn1/x_info.c \
	asn1/x_long.c \
	asn1/x_name.c \
	asn1/x_nx509.c \
	asn1/x_pkey.c \
	asn1/x_pubkey.c \
	asn1/x_req.c \
	asn1/x_sig.c \
	asn1/x_spki.c \
	asn1/x_val.c \
	asn1/x_x509.c \
	asn1/x_x509a.c \
	bf/bf_cfb64.c \
	bf/bf_ecb.c \
	bf/bf_enc.c \
	bf/bf_ofb64.c \
	bf/bf_skey.c \
	bio/b_dump.c \
	bio/b_print.c \
	bio/b_sock.c \
	bio/bf_buff.c \
	bio/bf_nbio.c \
	bio/bf_null.c \
	bio/bio_cb.c \
	bio/bio_err.c \
	bio/bio_lib.c \
	bio/bss_acpt.c \
	bio/bss_bio.c \
	bio/bss_conn.c \
	bio/bss_dgram.c \
	bio/bss_fd.c \
	bio/bss_file.c \
	bio/bss_log.c \
	bio/bss_mem.c \
	bio/bss_null.c \
	bio/bss_sock.c \
	bn/bn_add.c \
	bn/bn_asm.c \
	bn/bn_blind.c \
	bn/bn_const.c \
	bn/bn_ctx.c \
	bn/bn_depr.c \
	bn/bn_div.c \
	bn/bn_err.c \
	bn/bn_exp.c \
	bn/bn_exp2.c \
	bn/bn_gcd.c \
	bn/bn_gf2m.c \
	bn/bn_kron.c \
	bn/bn_lib.c \
	bn/bn_mod.c \
	bn/bn_mont.c \
	bn/bn_mpi.c \
	bn/bn_mul.c \
	bn/bn_nist.c \
	bn/bn_prime.c \
	bn/bn_print.c \
	bn/bn_rand.c \
	bn/bn_recp.c \
	bn/bn_shift.c \
	bn/bn_sqr.c \
	bn/bn_sqrt.c \
	bn/bn_word.c \
	bn/bn_x931p.c \
	buffer/buf_err.c \
	buffer/buf_str.c \
	buffer/buffer.c \
	cmac/cmac.c \
	cmac/cm_ameth.c \
	cmac/cm_pmeth.c \
	comp/c_rle.c \
	comp/c_zlib.c \
	comp/comp_err.c \
	comp/comp_lib.c \
	conf/conf_api.c \
	conf/conf_def.c \
	conf/conf_err.c \
	conf/conf_lib.c \
	conf/conf_mall.c \
	conf/conf_mod.c \
	conf/conf_sap.c \
	des/cbc_cksm.c \
	des/cbc_enc.c \
	des/cfb64ede.c \
	des/cfb64enc.c \
	des/cfb_enc.c \
	des/des_enc.c \
	des/des_old.c \
	des/des_old2.c \
	des/ecb3_enc.c \
	des/ecb_enc.c \
	des/ede_cbcm_enc.c \
	des/enc_read.c \
	des/enc_writ.c \
	des/fcrypt.c \
	des/fcrypt_b.c \
	des/ofb64ede.c \
	des/ofb64enc.c \
	des/ofb_enc.c \
	des/pcbc_enc.c \
	des/qud_cksm.c \
	des/rand_key.c \
	des/read2pwd.c \
	des/rpc_enc.c \
	des/set_key.c \
	des/str2key.c \
	des/xcbc_enc.c \
	dh/dh_ameth.c \
	dh/dh_asn1.c \
	dh/dh_check.c \
	dh/dh_depr.c \
	dh/dh_err.c \
	dh/dh_gen.c \
	dh/dh_key.c \
	dh/dh_lib.c \
	dh/dh_pmeth.c \
	dh/dh_prn.c \
	dsa/dsa_ameth.c \
	dsa/dsa_asn1.c \
	dsa/dsa_depr.c \
	dsa/dsa_err.c \
	dsa/dsa_gen.c \
	dsa/dsa_key.c \
	dsa/dsa_lib.c \
	dsa/dsa_ossl.c \
	dsa/dsa_pmeth.c \
	dsa/dsa_prn.c \
	dsa/dsa_sign.c \
	dsa/dsa_vrf.c \
	dso/dso_dl.c \
	dso/dso_dlfcn.c \
	dso/dso_err.c \
	dso/dso_lib.c \
	dso/dso_null.c \
	dso/dso_openssl.c \
	dso/dso_vms.c \
	dso/dso_win32.c \
	dso/dso_beos.c \
	ec/ec2_mult.c \
	ec/ec2_smpl.c \
	ec/ec_ameth.c \
	ec/ec_asn1.c \
	ec/ec_check.c \
	ec/ec_curve.c \
	ec/ec_cvt.c \
	ec/ec_err.c \
	ec/ec_key.c \
	ec/ec_lib.c \
	ec/ec_mult.c \
	ec/ec_pmeth.c \
	ec/ec_print.c \
	ec/eck_prn.c \
	ec/ecp_mont.c \
	ec/ecp_nist.c \
	ec/ecp_smpl.c \
	ec/ecp_nistp224.c \
	ec/ecp_nistp256.c \
	ec/ecp_nistp521.c \
	ec/ecp_nistputil.c \
	ec/ecp_oct.c \
	ec/ec2_oct.c \
	ec/ec_oct.c \
	ecdh/ech_err.c \
	ecdh/ech_key.c \
	ecdh/ech_lib.c \
	ecdh/ech_ossl.c \
	ecdsa/ecs_asn1.c \
	ecdsa/ecs_err.c \
	ecdsa/ecs_lib.c \
	ecdsa/ecs_ossl.c \
	ecdsa/ecs_sign.c \
	ecdsa/ecs_vrf.c \
	err/err.c \
	err/err_all.c \
	err/err_prn.c \
	evp/bio_b64.c \
	evp/bio_enc.c \
	evp/bio_md.c \
	evp/bio_ok.c \
	evp/c_all.c \
	evp/c_allc.c \
	evp/c_alld.c \
	evp/digest.c \
	evp/e_aes.c \
	evp/e_bf.c \
	evp/e_des.c \
	evp/e_des3.c \
	evp/e_null.c \
	evp/e_old.c \
	evp/e_rc2.c \
	evp/e_rc4.c \
	evp/e_rc5.c \
	evp/e_xcbc_d.c \
	evp/encode.c \
	evp/evp_acnf.c \
	evp/evp_enc.c \
	evp/evp_err.c \
	evp/evp_key.c \
	evp/evp_lib.c \
	evp/evp_pbe.c \
	evp/evp_pkey.c \
	evp/m_dss.c \
	evp/m_dss1.c \
	evp/m_ecdsa.c \
	evp/m_md4.c \
	evp/m_md5.c \
	evp/m_mdc2.c \
	evp/m_null.c \
	evp/m_ripemd.c \
	evp/m_sha1.c \
	evp/m_sigver.c \
	evp/m_wp.c \
	evp/names.c \
	evp/p5_crpt.c \
	evp/p5_crpt2.c \
	evp/p_dec.c \
	evp/p_enc.c \
	evp/p_lib.c \
	evp/p_open.c \
	evp/p_seal.c \
	evp/p_sign.c \
	evp/p_verify.c \
	evp/pmeth_fn.c \
	evp/pmeth_gn.c \
	evp/pmeth_lib.c \
	evp/e_idea.c \
	evp/e_camellia.c \
	evp/e_seed.c \
	evp/e_cast.c \
	evp/m_md2.c \
	evp/m_sha.c \
	evp/evp_fips.c \
	evp/e_aes_cbc_hmac_sha1.c \
	evp/e_rc4_hmac_md5.c \
	hmac/hm_ameth.c \
	hmac/hm_pmeth.c \
	hmac/hmac.c \
	krb5/krb5_asn.c \
	lhash/lh_stats.c \
	lhash/lhash.c \
	md4/md4_dgst.c \
	md4/md4_one.c \
	md5/md5_dgst.c \
	md5/md5_one.c \
	modes/cbc128.c \
	modes/ctr128.c \
	modes/cts128.c \
	modes/cfb128.c \
	modes/ofb128.c \
	modes/gcm128.c \
	modes/ccm128.c \
	modes/xts128.c \
	objects/o_names.c \
	objects/obj_dat.c \
	objects/obj_err.c \
	objects/obj_lib.c \
	objects/obj_xref.c \
	ocsp/ocsp_asn.c \
	ocsp/ocsp_cl.c \
	ocsp/ocsp_err.c \
	ocsp/ocsp_ext.c \
	ocsp/ocsp_ht.c \
	ocsp/ocsp_lib.c \
	ocsp/ocsp_prn.c \
	ocsp/ocsp_srv.c \
	ocsp/ocsp_vfy.c \
	pem/pem_all.c \
	pem/pem_err.c \
	pem/pem_info.c \
	pem/pem_lib.c \
	pem/pem_oth.c \
	pem/pem_pk8.c \
	pem/pem_pkey.c \
	pem/pem_seal.c \
	pem/pem_sign.c \
	pem/pem_x509.c \
	pem/pem_xaux.c \
	pem/pvkfmt.c \
	pkcs12/p12_add.c \
	pkcs12/p12_asn.c \
	pkcs12/p12_attr.c \
	pkcs12/p12_crpt.c \
	pkcs12/p12_crt.c \
	pkcs12/p12_decr.c \
	pkcs12/p12_init.c \
	pkcs12/p12_key.c \
	pkcs12/p12_kiss.c \
	pkcs12/p12_mutl.c \
	pkcs12/p12_npas.c \
	pkcs12/p12_p8d.c \
	pkcs12/p12_p8e.c \
	pkcs12/p12_utl.c \
	pkcs12/pk12err.c \
	pkcs7/pk7_asn1.c \
	pkcs7/pk7_attr.c \
	pkcs7/pk7_doit.c \
	pkcs7/pk7_lib.c	\
	pkcs7/pk7_mime.c \
	pkcs7/pk7_smime.c \
	pkcs7/pkcs7err.c \
	pkcs7/bio_pk7.c \
	pqueue/pqueue.c \
	rand/md_rand.c \
	rand/rand_egd.c \
	rand/rand_err.c \
	rand/rand_lib.c \
	rand/rand_unix.c \
	rand/randfile.c \
	rc2/rc2_cbc.c \
	rc2/rc2_ecb.c \
	rc2/rc2_skey.c \
	rc2/rc2cfb64.c \
	rc2/rc2ofb64.c \
	rc4/rc4_enc.c \
	rc4/rc4_skey.c \
	rc4/rc4_utl.c \
	ripemd/rmd_dgst.c \
	ripemd/rmd_one.c \
	rsa/rsa_ameth.c \
	rsa/rsa_asn1.c \
	rsa/rsa_chk.c \
	rsa/rsa_eay.c \
	rsa/rsa_err.c \
	rsa/rsa_gen.c \
	rsa/rsa_lib.c \
	rsa/rsa_none.c \
	rsa/rsa_null.c \
	rsa/rsa_oaep.c \
	rsa/rsa_pk1.c \
	rsa/rsa_pmeth.c \
	rsa/rsa_prn.c \
	rsa/rsa_pss.c \
	rsa/rsa_saos.c \
	rsa/rsa_sign.c \
	rsa/rsa_ssl.c \
	rsa/rsa_x931.c \
	rsa/rsa_depr.c \
	rsa/rsa_crpt.c \
	sha/sha1_one.c \
	sha/sha1dgst.c \
	sha/sha256.c \
	sha/sha512.c \
	sha/sha_dgst.c \
	sha/sha_one.c \
	srp/srp_lib.c \
	srp/srp_vfy.c \
	stack/stack.c \
	ts/ts_err.c \
	txt_db/txt_db.c \
	ui/ui_compat.c \
	ui/ui_err.c \
	ui/ui_lib.c \
	ui/ui_openssl.c \
	ui/ui_util.c \
	x509/by_dir.c \
	x509/by_file.c \
	x509/x509_att.c \
	x509/x509_cmp.c \
	x509/x509_d2.c \
	x509/x509_def.c \
	x509/x509_err.c \
	x509/x509_ext.c \
	x509/x509_lu.c \
	x509/x509_obj.c \
	x509/x509_r2x.c \
	x509/x509_req.c \
	x509/x509_set.c \
	x509/x509_trs.c \
	x509/x509_txt.c \
	x509/x509_v3.c \
	x509/x509_vfy.c \
	x509/x509_vpm.c \
	x509/x509cset.c \
	x509/x509name.c \
	x509/x509rset.c \
	x509/x509spki.c \
	x509/x509type.c \
	x509/x_all.c \
	x509v3/pcy_cache.c \
	x509v3/pcy_data.c \
	x509v3/pcy_lib.c \
	x509v3/pcy_map.c \
	x509v3/pcy_node.c \
	x509v3/pcy_tree.c \
	x509v3/v3_akey.c \
	x509v3/v3_akeya.c \
	x509v3/v3_alt.c \
	x509v3/v3_asid.c \
	x509v3/v3_addr.c \
	x509v3/v3_bcons.c \
	x509v3/v3_bitst.c \
	x509v3/v3_conf.c \
	x509v3/v3_cpols.c \
	x509v3/v3_crld.c \
	x509v3/v3_enum.c \
	x509v3/v3_extku.c \
	x509v3/v3_genn.c \
	x509v3/v3_ia5.c \
	x509v3/v3_info.c \
	x509v3/v3_int.c \
	x509v3/v3_lib.c \
	x509v3/v3_ncons.c \
	x509v3/v3_ocsp.c \
	x509v3/v3_pci.c \
	x509v3/v3_pcia.c \
	x509v3/v3_pcons.c \
	x509v3/v3_pku.c \
	x509v3/v3_pmaps.c \
	x509v3/v3_prn.c \
	x509v3/v3_purp.c \
	x509v3/v3_skey.c \
	x509v3/v3_sxnet.c \
	x509v3/v3_utl.c \
	x509v3/v3err.c \
	engine/eng_err.c \
	engine/eng_lib.c \
	engine/eng_list.c \
	engine/eng_init.c \
	engine/eng_ctrl.c \
	engine/eng_table.c \
	engine/eng_pkey.c \
	engine/eng_fat.c \
	engine/tb_rsa.c \
	engine/tb_dsa.c \
	engine/tb_ecdsa.c \
	engine/tb_dh.c \
	engine/tb_ecdh.c \
	engine/tb_rand.c \
	engine/tb_store.c \
	engine/tb_cipher.c \
	engine/tb_digest.c \
	engine/tb_pkmeth.c \
	engine/tb_asnmth.c \
	engine/eng_openssl.c \
	engine/eng_cnf.c \
	engine/eng_dyn.c \
	engine/eng_cryptodev.c \
	engine/eng_rsax.c \
	engine/eng_rdrand.c \
	engine/eng_all.c \
	fakewapi.c

local_c_includes := \
	$(NDK_PROJECT_PATH) \
	$(NDK_PROJECT_PATH)/crypto/asn1 \
	$(NDK_PROJECT_PATH)/crypto/evp \
	$(NDK_PROJECT_PATH)/include \
	$(NDK_PROJECT_PATH)/include/openssl \
	$(NDK_PROJECT_PATH)/../include 

local_c_flags := -DNO_WINDOWS_BRAINDEATH

include $(CLEAR_VARS)
include $(LOCAL_PATH)/../android-config.mk
LOCAL_SRC_FILES += $(local_src_files)
LOCAL_CFLAGS += $(local_c_flags)
LOCAL_C_INCLUDES += $(local_c_includes)
LOCAL_LDLIBS += -lz
ifeq ($(TARGET_ARCH),arm)
	LOCAL_SRC_FILES += $(arm_src_files)
	LOCAL_CFLAGS += $(arm_cflags)
else
	LOCAL_SRC_FILES += $(non_arm_src_files)
endif
ifeq ($(TARGET_SIMULATOR),true)
	# Make valgrind happy.
	LOCAL_CFLAGS += -DPURIFY
    LOCAL_LDLIBS += -ldl
endif
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE:= libcrypto
include $(BUILD_SHARED_LIBRARY)

ifeq ($(WITH_HOST_DALVIK),true)
    include $(CLEAR_VARS)
    include $(LOCAL_PATH)/../android-config.mk
    LOCAL_SRC_FILES += $(local_src_files)
    LOCAL_CFLAGS += $(local_c_flags) -DPURIFY
    LOCAL_C_INCLUDES += $(local_c_includes)
    LOCAL_SRC_FILES += $(non_arm_src_files)
    LOCAL_LDLIBS += -ldl
    LOCAL_MODULE_TAGS := optional
    LOCAL_MODULE:= libcrypto
    include $(BUILD_SHARED_LIBRARY)
endif

include $(CLEAR_VARS)
include $(LOCAL_PATH)/../android-config.mk
LOCAL_SRC_FILES += $(local_src_files)
LOCAL_CFLAGS += $(local_c_flags) -DPURIFY
LOCAL_C_INCLUDES += $(local_c_includes)
LOCAL_SRC_FILES += $(non_arm_src_files)
LOCAL_LDLIBS += -ldl
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE:= libcrypto_static
include $(BUILD_STATIC_LIBRARY)

ssl/Android.mk :

LOCAL_PATH:= $(call my-dir)

local_c_includes := \
	$(NDK_PROJECT_PATH) \
	$(NDK_PROJECT_PATH)/include \
	$(NDK_PROJECT_PATH)/crypto \
	$(NDK_PROJECT_PATH)/../include

local_src_files:= \
	s2_meth.c \
	s2_srvr.c \
	s2_clnt.c \
	s2_lib.c \
	s2_enc.c \
	s2_pkt.c \
	s3_meth.c \
	s3_srvr.c \
	s3_clnt.c \
	s3_lib.c \
	s3_enc.c \
	s3_pkt.c \
	s3_both.c \
	s23_meth.c \
	s23_srvr.c \
	s23_clnt.c \
	s23_lib.c \
	s23_pkt.c \
	t1_meth.c \
	t1_srvr.c \
	t1_clnt.c \
	t1_lib.c \
	t1_enc.c \
	t1_reneg.c \
	d1_meth.c \
	d1_srvr.c \
	d1_clnt.c \
	d1_lib.c \
	d1_pkt.c \
	d1_both.c \
	d1_enc.c \
	d1_srtp.c \
	ssl_lib.c \
	ssl_err2.c \
	ssl_cert.c \
	ssl_sess.c \
	ssl_ciph.c \
	ssl_stat.c \
	ssl_rsa.c \
	ssl_asn1.c \
	ssl_txt.c \
	ssl_algs.c \
	bio_ssl.c \
	ssl_err.c \
	kssl.c \
	tls_srp.c

include $(CLEAR_VARS)
include $(LOCAL_PATH)/../android-config.mk
LOCAL_SRC_FILES += $(local_src_files)
LOCAL_C_INCLUDES += $(local_c_includes)
LOCAL_SHARED_LIBRARIES += libcrypto
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE:= libssl
include $(BUILD_SHARED_LIBRARY)

ifeq ($(WITH_HOST_DALVIK),true)
    include $(CLEAR_VARS)
    include $(LOCAL_PATH)/../android-config.mk
    LOCAL_SRC_FILES += $(local_src_files)
    LOCAL_C_INCLUDES += $(local_c_includes)
    LOCAL_SHARED_LIBRARIES += libcrypto
    LOCAL_MODULE_TAGS := optional
    LOCAL_MODULE:= libssl
    include $(BUILD_SHARED_LIBRARY)
endif

include $(CLEAR_VARS)
include $(LOCAL_PATH)/../android-config.mk
LOCAL_SRC_FILES:= ssltest.c
LOCAL_C_INCLUDES += $(local_c_includes)
LOCAL_SHARED_LIBRARIES := libssl libcrypto
LOCAL_MODULE:= ssltest
LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)

接着,生成 libcrypto 的一票子汇编代码。对于 ARM 的机器有:

perl crypto/aes/asm/aes-armv4.pl        > crypto/aes/asm/aes-armv4.S
perl crypto/bn/asm/armv4-mont.pl        > crypto/bn/asm/armv4-mont.S
perl crypto/sha/asm/sha1-armv4-large.pl > crypto/sha/asm/sha1-armv4-large.S
perl crypto/sha/asm/sha256-armv4.pl     > crypto/sha/asm/sha256-armv4.S
perl crypto/sha/asm/sha512-armv4.pl     > crypto/sha/asm/sha512-armv4.S

新建 crypto/fakewapi.c ,用一些 dummy 填充某些支持 WAPI 的机器上 wpa_supplicant 所需的一些函数(源码没找到,这将废掉 WAPI 支持):

int i2o_ECPrivateKey(int i, ...) {
  return 0;
}

int i2o_ECDSA_SIG(int i, ...) {
  return 0;
}

int o2i_ECDSA_SIG(int i, ...) {
  return 0;
}

保存下面这个 patch 到 jsse.patch :

--- openssl-1.0.0b.orig/ssl/ssl.h	2010-11-30 00:03:46.000000000 +0000
+++ openssl-1.0.0b/ssl/ssl.h	2010-11-30 00:03:47.000000000 +0000
@@ -1133,6 +1133,9 @@ struct ssl_st
 	/* This can also be in the session once a session is established */
 	SSL_SESSION *session;

+        /* This can be disabled to prevent the use of uncached sessions */
+	int session_creation_enabled;
+
 	/* Default generate session ID callback. */
 	GEN_SESSION_CB generate_session_id;

@@ -1546,6 +1549,7 @@ const SSL_CIPHER *SSL_get_current_cipher
 int	SSL_CIPHER_get_bits(const SSL_CIPHER *c,int *alg_bits);
 char *	SSL_CIPHER_get_version(const SSL_CIPHER *c);
 const char *	SSL_CIPHER_get_name(const SSL_CIPHER *c);
+const char *	SSL_CIPHER_authentication_method(const SSL_CIPHER *c);

 int	SSL_get_fd(const SSL *s);
 int	SSL_get_rfd(const SSL *s);
@@ -1554,6 +1558,7 @@ const char  * SSL_get_cipher_list(const
 char *	SSL_get_shared_ciphers(const SSL *s, char *buf, int len);
 int	SSL_get_read_ahead(const SSL * s);
 int	SSL_pending(const SSL *s);
+const char *	SSL_authentication_method(const SSL *c);
 #ifndef OPENSSL_NO_SOCK
 int	SSL_set_fd(SSL *s, int fd);
 int	SSL_set_rfd(SSL *s, int fd);
@@ -1565,6 +1570,7 @@ BIO *	SSL_get_rbio(const SSL *s);
 BIO *	SSL_get_wbio(const SSL *s);
 #endif
 int	SSL_set_cipher_list(SSL *s, const char *str);
+int	SSL_set_cipher_lists(SSL *s, STACK_OF(SSL_CIPHER) *sk);
 void	SSL_set_read_ahead(SSL *s, int yes);
 int	SSL_get_verify_mode(const SSL *s);
 int	SSL_get_verify_depth(const SSL *s);
@@ -1580,6 +1586,8 @@ int	SSL_use_PrivateKey(SSL *ssl, EVP_PKE
 int	SSL_use_PrivateKey_ASN1(int pk,SSL *ssl, const unsigned char *d, long len);
 int	SSL_use_certificate(SSL *ssl, X509 *x);
 int	SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len);
+int	SSL_use_certificate_chain(SSL *ssl, STACK_OF(X509) *cert_chain);
+STACK_OF(X509) * SSL_get_certificate_chain(SSL *ssl, X509 *x);

 #ifndef OPENSSL_NO_STDIO
 int	SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type);
@@ -1615,6 +1623,7 @@ void	SSL_copy_session_id(SSL *to,const S
 SSL_SESSION *SSL_SESSION_new(void);
 const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s,
 					unsigned int *len);
+const char *	SSL_SESSION_get_version(const SSL_SESSION *s);
 #ifndef OPENSSL_NO_FP_API
 int	SSL_SESSION_print_fp(FILE *fp,const SSL_SESSION *ses);
 #endif
@@ -1624,6 +1633,7 @@ int	SSL_SESSION_print(BIO *fp,const SSL_
 void	SSL_SESSION_free(SSL_SESSION *ses);
 int	i2d_SSL_SESSION(SSL_SESSION *in,unsigned char **pp);
 int	SSL_set_session(SSL *to, SSL_SESSION *session);
+void	SSL_set_session_creation_enabled(SSL *, int);
 int	SSL_CTX_add_session(SSL_CTX *s, SSL_SESSION *c);
 int	SSL_CTX_remove_session(SSL_CTX *,SSL_SESSION *c);
 int	SSL_CTX_set_generate_session_id(SSL_CTX *, GEN_SESSION_CB);
@@ -2066,6 +2076,7 @@ void ERR_load_SSL_strings(void);
 #define SSL_F_SSL_UNDEFINED_VOID_FUNCTION		 244
 #define SSL_F_SSL_USE_CERTIFICATE			 198
 #define SSL_F_SSL_USE_CERTIFICATE_ASN1			 199
+#define SSL_F_SSL_USE_CERTIFICATE_CHAIN			 2000
 #define SSL_F_SSL_USE_CERTIFICATE_FILE			 200
 #define SSL_F_SSL_USE_PRIVATEKEY			 201
 #define SSL_F_SSL_USE_PRIVATEKEY_ASN1			 202
@@ -2272,6 +2283,7 @@ void ERR_load_SSL_strings(void);
 #define SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING		 345
 #define SSL_R_SERVERHELLO_TLSEXT			 275
 #define SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED		 277
+#define SSL_R_SESSION_MAY_NOT_BE_CREATED		 2000
 #define SSL_R_SHORT_READ				 219
 #define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE	 220
 #define SSL_R_SSL23_DOING_SESSION_ID_REUSE		 221
--- openssl-1.0.0b.orig/ssl/d1_clnt.c	2010-01-26 19:46:29.000000000 +0000
+++ openssl-1.0.0b/ssl/d1_clnt.c	2010-11-30 00:03:47.000000000 +0000
@@ -613,6 +613,12 @@ int dtls1_client_hello(SSL *s)
 #endif
 			(s->session->not_resumable))
 			{
+		        if (!s->session_creation_enabled)
+				{
+				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
+				SSLerr(SSL_F_DTLS1_CLIENT_HELLO,SSL_R_SESSION_MAY_NOT_BE_CREATED);
+				goto err;
+				}
 			if (!ssl_get_new_session(s,0))
 				goto err;
 			}
--- openssl-1.0.0b.orig/ssl/s23_clnt.c	2010-02-16 14:20:40.000000000 +0000
+++ openssl-1.0.0b/ssl/s23_clnt.c	2010-11-30 00:03:47.000000000 +0000
@@ -687,6 +687,13 @@ static int ssl23_get_server_hello(SSL *s

 	/* Since, if we are sending a ssl23 client hello, we are not
 	 * reusing a session-id */
+        if (!s->session_creation_enabled)
+		{
+		if (!(s->client_version == SSL2_VERSION))
+			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
+		SSLerr(SSL_F_SSL23_GET_SERVER_HELLO,SSL_R_SESSION_MAY_NOT_BE_CREATED);
+		goto err;
+		}
 	if (!ssl_get_new_session(s,0))
 		goto err;

--- openssl-1.0.0b.orig/ssl/s3_both.c	2010-11-30 00:03:46.000000000 +0000
+++ openssl-1.0.0b/ssl/s3_both.c	2010-11-30 00:03:47.000000000 +0000
@@ -347,8 +347,11 @@ unsigned long ssl3_output_cert_chain(SSL
 	unsigned long l=7;
 	BUF_MEM *buf;
 	int no_chain;
+	STACK_OF(X509) *cert_chain;

-	if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || s->ctx->extra_certs)
+	cert_chain = SSL_get_certificate_chain(s, x);
+
+	if ((s->mode & SSL_MODE_NO_AUTO_CHAIN) || s->ctx->extra_certs || cert_chain)
 		no_chain = 1;
 	else
 		no_chain = 0;
@@ -400,6 +403,10 @@ unsigned long ssl3_output_cert_chain(SSL
 			return(0);
 		}

+	for (i=0; i<sk_X509_num(cert_chain); i++) +		if (ssl3_add_cert_to_buf(buf, &l, sk_X509_value(cert_chain,i))) +			return(0); +  	l-=7;  	p=(unsigned char *)&(buf->data[4]);
 	l2n3(l,p);
--- openssl-1.0.0b.orig/ssl/s3_clnt.c	2010-11-30 00:03:46.000000000 +0000
+++ openssl-1.0.0b/ssl/s3_clnt.c	2010-11-30 00:03:47.000000000 +0000
@@ -686,6 +686,12 @@ int ssl3_client_hello(SSL *s)
 #endif
 			(sess->not_resumable))
 			{
+		        if (!s->session_creation_enabled)
+				{
+				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
+				SSLerr(SSL_F_SSL3_CLIENT_HELLO,SSL_R_SESSION_MAY_NOT_BE_CREATED);
+				goto err;
+				}
 			if (!ssl_get_new_session(s,0))
 				goto err;
 			}
@@ -894,6 +900,12 @@ int ssl3_get_server_hello(SSL *s)
 		s->hit=0;
 		if (s->session->session_id_length > 0)
 			{
+		        if (!s->session_creation_enabled)
+				{
+				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
+				SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_SESSION_MAY_NOT_BE_CREATED);
+				goto err;
+				}
 			if (!ssl_get_new_session(s,0))
 				{
 				al=SSL_AD_INTERNAL_ERROR;
--- openssl-1.0.0b.orig/ssl/s3_srvr.c	2010-11-30 00:03:46.000000000 +0000
+++ openssl-1.0.0b/ssl/s3_srvr.c	2010-11-30 00:03:47.000000000 +0000
@@ -902,6 +902,12 @@ int ssl3_get_client_hello(SSL *s)
 	 */
 	if ((s->new_session && (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)))
 		{
+	        if (!s->session_creation_enabled)
+			{
+			ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
+			SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_SESSION_MAY_NOT_BE_CREATED);
+			goto err;
+		}
 		if (!ssl_get_new_session(s,1))
 			goto err;
 		}
@@ -916,6 +922,12 @@ int ssl3_get_client_hello(SSL *s)
 			goto err;
 		else /* i == 0 */
 			{
+		        if (!s->session_creation_enabled)
+				{
+				ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE);
+				SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_SESSION_MAY_NOT_BE_CREATED);
+				goto err;
+				}
 			if (!ssl_get_new_session(s,1))
 				goto err;
 			}
--- openssl-1.0.0b.orig/ssl/ssl_ciph.c	2010-06-15 17:25:14.000000000 +0000
+++ openssl-1.0.0b/ssl/ssl_ciph.c	2010-11-30 00:03:47.000000000 +0000
@@ -1652,6 +1652,52 @@ int SSL_CIPHER_get_bits(const SSL_CIPHER
 	return(ret);
 	}

+/* return string version of key exchange algorithm */
+const char* SSL_CIPHER_authentication_method(const SSL_CIPHER* cipher)
+	{
+	switch (cipher->algorithm_mkey)
+		{
+	case SSL_kRSA:
+		return SSL_TXT_RSA;
+	case SSL_kDHr:
+		return SSL_TXT_DH "_" SSL_TXT_RSA;
+	case SSL_kDHd:
+		return SSL_TXT_DH "_" SSL_TXT_DSS;
+	case SSL_kEDH:
+		switch (cipher->algorithm_auth)
+			{
+		case SSL_aDSS:
+			return "DHE_" SSL_TXT_DSS;
+		case SSL_aRSA:
+			return "DHE_" SSL_TXT_RSA;
+		case SSL_aNULL:
+			return SSL_TXT_DH "_anon";
+		default:
+			return "UNKNOWN";
+                        }
+	case SSL_kKRB5:
+		return SSL_TXT_KRB5;
+	case SSL_kECDHr:
+		return SSL_TXT_ECDH "_" SSL_TXT_RSA;
+	case SSL_kECDHe:
+		return SSL_TXT_ECDH "_" SSL_TXT_ECDSA;
+	case SSL_kEECDH:
+		switch (cipher->algorithm_auth)
+			{
+		case SSL_aECDSA:
+			return "ECDHE_" SSL_TXT_ECDSA;
+		case SSL_aRSA:
+			return "ECDHE_" SSL_TXT_RSA;
+		case SSL_aNULL:
+			return SSL_TXT_ECDH "_anon";
+		default:
+			return "UNKNOWN";
+                        }
+        default:
+		return "UNKNOWN";
+		}
+	}
+
 SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n)
 	{
 	SSL_COMP *ctmp;
--- openssl-1.0.0b.orig/ssl/ssl_err.c	2010-11-30 00:03:46.000000000 +0000
+++ openssl-1.0.0b/ssl/ssl_err.c	2010-11-30 00:03:47.000000000 +0000
@@ -465,6 +465,7 @@ static ERR_STRING_DATA SSL_str_reasons[]
 {ERR_REASON(SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING),"scsv received when renegotiating"},
 {ERR_REASON(SSL_R_SERVERHELLO_TLSEXT)    ,"serverhello tlsext"},
 {ERR_REASON(SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED),"session id context uninitialized"},
+{ERR_REASON(SSL_R_SESSION_MAY_NOT_BE_CREATED),"session may not be created"},
 {ERR_REASON(SSL_R_SHORT_READ)            ,"short read"},
 {ERR_REASON(SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE),"signature for non signing certificate"},
 {ERR_REASON(SSL_R_SSL23_DOING_SESSION_ID_REUSE),"ssl23 doing session id reuse"},
--- openssl-1.0.0b.orig/ssl/ssl_lib.c	2010-11-30 00:03:46.000000000 +0000
+++ openssl-1.0.0b/ssl/ssl_lib.c	2010-11-30 00:03:47.000000000 +0000
@@ -326,6 +326,7 @@ SSL *SSL_new(SSL_CTX *ctx)
 	OPENSSL_assert(s->sid_ctx_length <= sizeof s->sid_ctx);
 	memcpy(&s->sid_ctx,&ctx->sid_ctx,sizeof(s->sid_ctx));
 	s->verify_callback=ctx->default_verify_callback;
+	s->session_creation_enabled=1;
 	s->generate_session_id=ctx->generate_session_id;

 	s->param = X509_VERIFY_PARAM_new();
@@ -1311,6 +1312,32 @@ int SSL_set_cipher_list(SSL *s,const cha
 	return 1;
 	}

+/** specify the ciphers to be used by the SSL */
+int SSL_set_cipher_lists(SSL *s,STACK_OF(SSL_CIPHER) *sk)
+	{
+	STACK_OF(SSL_CIPHER) *tmp_cipher_list;
+
+	if (sk == NULL)
+		return 0;
+
+        /* Based on end of ssl_create_cipher_list */
+	tmp_cipher_list = sk_SSL_CIPHER_dup(sk);
+	if (tmp_cipher_list == NULL)
+		{
+		return 0;
+		}
+	if (s->cipher_list != NULL)
+		sk_SSL_CIPHER_free(s->cipher_list);
+	s->cipher_list = sk;
+	if (s->cipher_list_by_id != NULL)
+		sk_SSL_CIPHER_free(s->cipher_list_by_id);
+	s->cipher_list_by_id = tmp_cipher_list;
+	(void)sk_SSL_CIPHER_set_cmp_func(s->cipher_list_by_id,ssl_cipher_ptr_id_cmp);
+
+	sk_SSL_CIPHER_sort(s->cipher_list_by_id);
+	return 1;
+	}
+
 /* works well for SSLv2, not so good for SSLv3 */
 char *SSL_get_shared_ciphers(const SSL *s,char *buf,int len)
 	{
@@ -2551,18 +2578,45 @@ SSL_METHOD *ssl_bad_method(int ver)
 	return(NULL);
 	}

-const char *SSL_get_version(const SSL *s)
+static const char *ssl_get_version(int version)
 	{
-	if (s->version == TLS1_VERSION)
+	if (version == TLS1_VERSION)
 		return("TLSv1");
-	else if (s->version == SSL3_VERSION)
+	else if (version == SSL3_VERSION)
 		return("SSLv3");
-	else if (s->version == SSL2_VERSION)
+	else if (version == SSL2_VERSION)
 		return("SSLv2");
 	else
 		return("unknown");
 	}

+const char *SSL_get_version(const SSL *s)
+	{
+		return ssl_get_version(s->version);
+	}
+
+const char *SSL_SESSION_get_version(const SSL_SESSION *s)
+	{
+		return ssl_get_version(s->ssl_version);
+	}
+
+const char* SSL_authentication_method(const SSL* ssl)
+	{
+	if (ssl->cert != NULL && ssl->cert->rsa_tmp != NULL)
+		return SSL_TXT_RSA "_" SSL_TXT_EXPORT;
+	switch (ssl->version)
+		{
+	case SSL2_VERSION:
+		return SSL_TXT_RSA;
+	case SSL3_VERSION:
+	case TLS1_VERSION:
+	case DTLS1_VERSION:
+		return SSL_CIPHER_authentication_method(ssl->s3->tmp.new_cipher);
+	default:
+		return "UNKNOWN";
+		}
+	}
+
 SSL *SSL_dup(SSL *s)
 	{
 	STACK_OF(X509_NAME) *sk;
--- openssl-1.0.0b.orig/ssl/ssl_locl.h	2010-11-30 00:03:46.000000000 +0000
+++ openssl-1.0.0b/ssl/ssl_locl.h	2010-11-30 00:03:47.000000000 +0000
@@ -456,6 +456,7 @@
 typedef struct cert_pkey_st
 	{
 	X509 *x509;
+	STACK_OF(X509) *cert_chain;
 	EVP_PKEY *privatekey;
 	} CERT_PKEY;

--- openssl-1.0.0b.orig/ssl/ssl_rsa.c	2009-09-12 23:09:26.000000000 +0000
+++ openssl-1.0.0b/ssl/ssl_rsa.c	2010-11-30 00:03:47.000000000 +0000
@@ -697,6 +697,42 @@ int SSL_CTX_use_PrivateKey_ASN1(int type
 	}

+int SSL_use_certificate_chain(SSL *ssl, STACK_OF(X509) *cert_chain)
+	{
+	if (ssl == NULL)
+		{
+		SSLerr(SSL_F_SSL_USE_CERTIFICATE_CHAIN,ERR_R_PASSED_NULL_PARAMETER);
+		return(0);
+		}
+	if (ssl->cert == NULL)
+		{
+		SSLerr(SSL_F_SSL_USE_CERTIFICATE_CHAIN,SSL_R_NO_CERTIFICATE_ASSIGNED);
+		return(0);
+		}
+	if (ssl->cert->key == NULL)
+		{
+		SSLerr(SSL_F_SSL_USE_CERTIFICATE_CHAIN,SSL_R_NO_CERTIFICATE_ASSIGNED);
+		return(0);
+		}
+	ssl->cert->key->cert_chain = cert_chain;
+	return(1);
+	}
+
+STACK_OF(X509) *SSL_get_certificate_chain(SSL *ssl, X509 *x)
+	{
+	int i;
+	if (x == NULL)
+		return NULL;
+	if (ssl == NULL)
+		return NULL;
+	if (ssl->cert == NULL)
+		return NULL;
+	for (i = 0; i < SSL_PKEY_NUM; i++) +		if (ssl->cert->pkeys[i].x509 == x)
+			return ssl->cert->pkeys[i].cert_chain;
+	return NULL;
+	}
+
 #ifndef OPENSSL_NO_STDIO
 /* Read a file that contains our certificate in "PEM" format,
  * possibly followed by a sequence of CA certificates that should be
--- openssl-1.0.0b.orig/ssl/ssl_sess.c	2010-02-01 16:49:42.000000000 +0000
+++ openssl-1.0.0b/ssl/ssl_sess.c	2010-11-30 00:03:47.000000000 +0000
@@ -261,6 +261,11 @@ static int def_generate_session_id(const
 	return 0;
 }

+void SSL_set_session_creation_enabled (SSL *s, int creation_enabled)
+	{
+	s->session_creation_enabled = creation_enabled;
+	}
+
 int ssl_get_new_session(SSL *s, int session)
 	{
 	/* This gets used by clients and servers. */
@@ -269,6 +274,8 @@ int ssl_get_new_session(SSL *s, int sess
 	SSL_SESSION *ss=NULL;
 	GEN_SESSION_CB cb = def_generate_session_id;

+	/* caller should check this if they can do better error handling */
+        if (!s->session_creation_enabled) return(0);
 	if ((ss=SSL_SESSION_new()) == NULL) return(0);

 	/* If the context has a default timeout, use it */

接着应用这个 patch :

patch -p1 < jsse.patch

有些地方会合并失败,需要参照 rej 文件手动 merge 。这个 patch 会提供 Android 需要的一些附加函数。

打开 crypto/bf/blowfish.h ,删除开头的以下内容:

diff --git a/crypto/bf/blowfish.h b/crypto/bf/blowfish.h
index 4b6c892..2a9ae98 100644
--- a/crypto/bf/blowfish.h
+++ b/crypto/bf/blowfish.h
@@ -65,10 +65,6 @@
 extern "C" {
 #endif

-#ifdef OPENSSL_NO_BF
-#error BF is disabled.
-#endif
-
 #define BF_ENCRYPT     1
 #define BF_DECRYPT     0

这样,源码的修改基本就完成了。

编译

编译的过程相对简单,在 OpenSSL 源码目录下输入:

NDK_PROJECT_PATH=. /path/to/android-ndk/ndk-build

稍等片刻即可。

安装

注意!由于 Android 的系统核心库需要连接 libcrypt 和 libssl ,更换缺少符号的 OpenSSL 库会导致大量程序无法启动甚至手机变砖,请确认 OpenSSL 库含有 Android 系统所需的所有符号。

安装前请确认手机已经 root 且 su 和 busybox 可用。

第一步是下载 Android SDK 或者从系统软件源里面安装 adb 。第二步就是打开手机上的 USB 调试。更换 OpenSSL 库后,在确定各个程序运行正常、手机能正常重启并使用 Wifi 之前请不要关掉 USB 调试。

第三步,用 adb 把编译好的文件传送至手机 SD 卡中:

adb push libs/armeabi/libcrypto.so /sdcard/
adb push libs/armeabi/libssl.so /sdcard/
adb push libs/armeabi/openssl /sdcard/

第四步,输入 adb shell ,启动手机上的终端。在里面键入以下命令:

busybox mount -o remount,rw /system
mkdir /system/lib/old-ssl
mv /system/lib/libcrypto.so /system/lib/libssl.so /system/lib/old-ssl/
cp /sdcard/libcrypto.so /system/lib/
cp /sdcard/libssl.so /system/lib/
cp /sdcard/openssl /system/xbin/
chmod 0644 /system/lib/libcrypto.so /system/lib/libssl.so
chmod 0755 /system/xbin/openssl
rm /sdcard/libcrypto.so /sdcard/libssl.so /sdcard/openssl
busybox mount -o remount,ro /system

第五步,测试。新开一个 adb shell ,输入 su ,观察链接器是否报错。输入“ openssl version ”查看版本信息。关闭手机上的浏览器和 Wifi ,杀掉所有进程,重开 Wifi 和浏览器,访问带有 SSL 的网站,观察其工作是否正常。在此期间可以用“ adb logcat ”查看日志。

若出现工作不正常的程序,在 adb shell 里手工调用,观察链接器输出,考虑是否能 patch 代码重新编译来修复。若无法修复,就只好还原 OpenSSL 的备份了:

busybox mount -o remount,rw /system
mv /system/lib/old-ssl/* /system/lib
rmdir /system/lib/old-ssl
rm /system/xbin/openssl
busybox mount -o remount,ro /system

若测试成功,则可以“ adb reboot ”来重启手机,看看各部件是否仍然能正常工作。若手机一直停留在启动画面,则可以尝试通过 adb shell 还原原来的 OpenSSL 库。

《为该死的 Android 编译新版本的 OpenSSL 库》上的5个想法

  1. 尤其注意需要打开 engine 这个是什么意思,怎么打开? 我在编译的时候碰到这块 头文件找不到的问题,但是文件明明在那,求解答。。。。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据