首先通过SSLContext.getInstance("TLS")
获取SSLContext
, 此时的SSLContext
中的SSLContextSpi
是OpenSSLContextImpl
, 在OpenSSLContextImpl
构造时, 构造了ClientSessionContext
并记录在OpenSSLContextImpl.clientSessionContext
. 而在ClientSessionContext
构造时, 其父类AbstractSessionContext
的构造函数中, 调用了底层的NativeCrypto.SSL_CTX_new()
创建了SSL_CTX
并记录在OpenSSLContextImpl.super.sslCtxNativePointer
中(主要步骤):
调用TLS_with_buffers_method()
获取SSL_METHOD
:
static const SSL_METHOD kMethod = {
0,
&kTLSProtocolMethod,
&ssl_noop_x509_method,
};
通过SSL_CTX_new()
创建SSL_CTX
并进行一系列设置, 其中, SSL_CTX.method
设置为kMethod
:
SSL_CTX.method
设置为kTLSProtocolMethod
(类型为SSL_PROTOCOL_METHOD
)
SSL_CTX.x509_method
设置为ssl_noop_x509_method
(类型为SSL_X509_METHOD
)
其中: kTLSProtocolMethod
的定义:
static const SSL_PROTOCOL_METHOD kTLSProtocolMethod = {
false /* is_dtls */,
tls_new, // 初始化 SSL, 创建 SSL_HANDSHAKE
tls_free,
tls_get_message, // PEEK 一个 SSLMessage
tls_next_message, // 读取一个 SSLMessage
tls_has_unprocessed_handshake_data,
tls_open_handshake,
tls_open_change_cipher_spec,
tls_open_app_data,
tls_write_app_data, // 加密明文的 app 数据并写到输出
tls_dispatch_alert,
tls_init_message, // 初始化一个 SSLMessage
tls_finish_message,// 销毁一个 SSLMessage
tls_add_message, // 将 SSLMessage 添加到输出
tls_add_change_cipher_spec,
tls_flush_flight, // 冲刷未发送的数据到 BIO
tls_on_handshake_complete,
tls_set_read_state, // 设置 SSL.s3->aead_write_ctx
tls_set_write_state, // 设置 SSL.s3->aead_read_ctx
};
该数据结构设计的方法将会经常出现在后文当中
通过SSL_CTX_set_info_callback()
设置监听SSL连接状态对应的回调函数为: info_callback
, 其调用的上层接口为: ConscryptEngine.onSSLStateChange()
通过SSL_CTX_set_cert_cb()
设置证书回调为: cert_cb
, 其调用的上层接口为: ConscryptEngine.clientCertificateRequested() -> NativeSsl.chooseClientCertificate()
上层调用SSLContext.init() -> OpenSSLContextImpl.engineInit()
, 此时创建了SSLParametersImpl
并记录了上层传递的X509KeyManager
和X509TrustManager
.
创建SSLParametersImpl
时, 其clientSessionContext
成员(类型是ClientSessionContext
)
上层调用SSLContext.getSocketFactory()
获取SSLSocketFactory
(实际是OpenSSLSocketFactoryImpl
), OpenSSLSocketFactoryImpl
保存了SSLParametersImpl
上层调用SSLSocketFactory
(实际是OpenSSLSocketFactoryImpl
)的createSocket()
方法, 经过Platform.createEngineSocket()
创建Java8EngineSocket
(其父类是ConscryptEngineSocket
), 其父类的newEngine
方法创建ConscryptEngine
, 此时将SSLParametersImpl
克隆一份, 并传入. ConscryptEngine
在构造时, 将通过newSsl() -> NativeSsl.newInstance()
实例化NativeSsl
, SSLParametersImpl
将保存在NativeSsl.parameters
, 其基本引用关系:
ConscryptEngineSocket.engine
: Java8EngineSocket
ConscryptEngineSocket.engine.ssl
: NativeSsl
ConscryptEngineSocket.engine.ssl.parameters
: SSLParametersImpl
parameters.getSessionContext()
获取了ClientSessionContext
结构体地址ClientSessionContext.newSsl()
, 传入ClientSessionContext
, 创建SSL
结构体, 其底层调用为NativeCrypto.SSL_new()
, 此处底层调用到: NativeCrypto_SSL_new()
:
to_SSL_CTX()
还原指针ssl_ctx_address
为: SSL_CTX
SSL_CTX
传入SSL_new()
以创建SSL
结构体SSL_set_custom_verify()
设置SSL的回调函数为:cert_verify_callback()
, 该方法负责完成对服务端证书的验证, 在cert_verify_callback()
中, 回调上层的NativeCrypto.verifyCertificateChain()
SSL
结构体被传递给NativeCrypto.SSL_new()
, 保存到NativeSsl.ssl
, 从顶层向下:ConscryptEngineSocket.engine.ssl.ssl
这里注意下 ConscryptEngine.networkBio()
, 它的类型是BioWrapper
, 是很重要的角色, 它负责处理所有 “加密” 的数据, 通过NativeSsl.newBio()
创建, 更底层的方法是:NativeCrypto.SSL_BIO_new()
:
BIO_new_bio_pair()
创建一对BIO
:internal_bio
和network_bio
, 此时创建的BIO.mehtod
被设置为methods_biop
, 因此BIO.mehtod->bread
被设置为bio_read
, 而BIO.mehtod->bwrite
被设置为: bio_write
SSL_set_bio()
将internal_bio
配置给了SSL
, 保存在(SSL.wbio
和SSL.rbio
)network_bio
引用在BioWrapper.bio
ConscryptEngine.networkBio.bio
非常重要, 它将在后文经常被提到.
上层调用ConscryptEngineSocket.startHandshake()
开始执行MTLS协商:
SSLInputStream
并保存到ConscryptEngineSocket.in
, 在此过程中
ByteBuffer.allocateDirect
分配与NativeSsl
交互的DirectByteBuffer
, 此处的 buffer 对于 JNI 来说是没有拷贝成本的. DirectByteBuffer
保存到 ConscryptEngineSocket.in.fromEngine
ByteBuffer.allocate()
分配与SocketInputStream
进行通信的的HeapByteBuffer
, HeapByteBuffer
保存到 ConscryptEngineSocket.in.fromSocket
SSLOutputStream
并保存到ConscryptEngineSocket.out
, 在此过程中:
ByteBuffer.allocate()
分配与SocketOutputStream
进行通信的的HeapByteBuffer
, HeapByteBuffer
保存到 ConscryptEngineSocket.out.target
SSLInputStream.processDataFromSocket()
获取数据, 调用readFromSocket()
从SocketInputStream
读取数据, 然后调用ConscryptEngine.unwrap()
处理读取到的数据, 细节见解密小节TLS协商的主循环:
NativeCrypto_ENGINE_SSL_read_direct() [libjavacrypto.so] ->
::SSL_read() [libssl.so] ->
ssl_read_impl() ->
::SSL_do_handshake() ->
bssl::ssl_run_handshake()
该函数是一个循环, 该循环依次调用SSL_HANDSHAKE.ssl->do_handshake
方法, 对于客户端, 该方法为ssl_client_handshake()
, 在该方法中, 初始状态为state_start_connect()
state_start_connect
对应的执行函数为do_start_connect()
:
SSL.s3
结构体ssl_setup_key_shares()
初始化 keys_sharesssl_setup_extension_permutation()
初始化扩展ssl_encrypt_client_hello()
加密 client_hellossl_add_client_hello()
将 client_hello 附加到消息池(SSL.s3->write_buffer
中)ssl_hs_flush
ssl_run_handshake()
的结果是ssl_hs_flush
, 因此ssl_run_handshake()
继续执行SSL_HANDSHAKE.ssl->method->flush_flight
方法, 该方法为kTLSProtocolMethod.flush_flight
即tls_flush_flight()
, 进一步调用ssl_write_buffer_flush() -> tls_write_buffer_flush() -> BIO_write()
, 将ssl.s3->write_buffer
数据写入到SSL.wbio
的BIO
中, 如前文所述, 该BIO
即internal_bio
, 其关联的对象为network_bio
, 至此上层就可以通过NativeCrypto.ENGINE_SSL_read_BIO_direct()
读取到数 BoringSSL 需要发送的数据了.执行do_enter_early_data()
, 基本没有做太多事情, 判断SSL_HANDSHAKE.early_data_offered
为空就直接切换状态到state_read_server_hello
执行 do_read_server_hello()
, 并读取TLS数据, 调用ssl_parse_server_hello()
解析协议头, 获取版本号, 本文的案例显然是MTLSv1.3, 则切换状态到 state_tls13
执行do_tls13() -> tls13_client_handshake()
, 该函数也是一个循环, 如果SSL_HANDSHAKE.tls13_state
不为state_done
就循环执行后续的状态切换, 初始状态为: state_read_hello_retry_request
调用do_read_hello_retry_request()
:
调用parse_server_hello_tls13()
解析消息头
调用SSL_get_cipher_by_value()
获取服务器要求的算法: SSL_CIPHER
, 本文的案例是TLS1_3_RFC_AES_128_GCM_SHA256
, 协议 id 为 4865, 也就是:
static constexpr SSL_CIPHER kCiphers[] = {
// Cipher 1301
{
TLS1_3_RFC_AES_128_GCM_SHA256,
"TLS_AES_128_GCM_SHA256",
TLS1_3_CK_AES_128_GCM_SHA256,
SSL_kGENERIC,
SSL_aGENERIC,
SSL_AES128GCM,
SSL_AEAD,
SSL_HANDSHAKE_MAC_SHA256,
},
...
};
将 SSL_CIPHER
保存到SSL_HANDSHAKE.new_cipher
切换状态到state_read_server_hello
调用do_read_server_hello()
, 该函数做了很多工作:
server_random
SSL_HANDSHAKE.new_cipher
保存到SSK_HANDSHAKE.new_session->cipher
ssl_ext_key_share_parse_serverhello()
从server_hello
中解析出dhe_secret
tls13_advance_key_schedule()
派生秘钥并保存到SSL_HANDSHAKE.secret_
tls13_derive_handshake_secrets()
派生秘钥并保存到SSL_HANDSHAKE.client_handshake_secret_
tls13_set_traffic_key()
将SSL_HANDSHAKE.client_handshake_secret_
设置到SSL
:
ssl_cipher_get_evp_aead()
确定EVP_AEAD
, 该结构体主要为了确定秘钥长度ssl_session_get_digest()
获取EVP_MD
用于秘钥派生label
调用hkdf_expand_label()
派生秘钥label
调用hkdf_expand_label()
派生初始向量SSLAEADContext::Create()
并传入SSL
, Cipher
, 秘钥, iv
, 创建SSLAEADContext
SSL.method->set_read_state
即tls_set_read_state()
设置SSLAEADContext
到SSL_HANDSHAKE.ssl->s3->aead_read_ctx
SSL_HANDSHAKE.client_handshake_secret_
到SSL.s3->read_traffic_secret
SSL.method->set_write_state
即tls_set_write_state()
设置SSLAEADContext
到SSL_HANDSHAKE.ssl->s3->aead_write_ctx
SSL_HANDSHAKE.client_handshake_secret_
到SSL.s3->write_traffic_secret
从此刻开始, 与服务器的数据往来都使用: SSL_HANDSHAKE.client_handshake_secret_
加密
调用do_read_certificate_request()
调用do_read_server_certificate() -> tls13_process_certificate()
, 从服务器返回的消息解析证书信息, 将证书保存到SSL_HANDSHAKE.new_session->certs
调用do_read_server_certificate_verify() -> ssl_verify_peer_cert() -> SSL_HANDSHAKE.ssl->config->custom_verify_callback
, 根据前文, SSL_HANDSHAKE.ssl->config->custom_verify_callback
已经被SSL_set_custom_verify()
设置为:cert_verify_callback()
:
调用SSL_get0_peer_certificates()
获取上文刚解析到的服务器证书链:SSL_HANDSHAKE.new_session->certs
调用上层: ConscryptEngine.verifyCertificateChain() -> Platform.checkServerTrusted() -> X509Trustmanager.checkServerTrusted()
, 其中ConscryptEngine
继承了NativeCrypto.SSLHandshakeCallbacks
, X509Trustmanager.checkServerTrusted()
为用户自定义的服务器证书验证方法.
调用do_read_server_finished()
:
tls13_advance_key_schedule()
更新加密算法tls13_derive_application_secrets() -> derive_secret("CLIENT_TRAFFIC_SECRET_0")
派生交换凭据的秘钥, 保存到SSL_HANDSHAKE.client_traffic_secret_0_
注意, 此时的SSL_HANDSHAKE.client_traffic_secret_0_
并没有作为会话秘钥, 这是因为还没有发送本地的凭据(这里我们只讨论 MTLSv1.3 )
调用do_send_client_certificate() -> SSL_HANDSHAKE.ssl->cert->cert_cb
, 该回调被SSL_CTX_set_cert_cb()
设置为external/conscrypt/common/src/jni/main/cpp/conscrypt/native_crypto.cc::cert_cb()
将在如下环节被调用:
bssl::ssl_run_handshake() ->
bssl::ssl_client_handshake() ->
bssl::tls13_client_handshake() ->
bssl::do_send_client_certificate() ->
cert_cb() [libjavacrypto.so]
如上文cert_cb()
调用的上层接口为: ConscryptEngine.clientCertificateRequested() -> NativeSsl.chooseClientCertificate()
, 其首先调用ConscryptEngineSocket.chooseClientAlias()
选取本地的证书别名, 而ConscryptEngineSocket.chooseClientAlias()
实际上是调用了X509KeyManager.chooseClientAlias()
, 然后通过setCertificate()
设置本地的证书&密钥, 参数为证书与秘钥的别名:
从SSLParametersImpl
中获取X509KeyManager
从X509KeyManager
中获取PrivateKey
, 这是上层应用自定义的
从X509KeyManager
中获取所有可用的X509Certificate
, 即X509Certificate[]
从PrivateKey
转换到OpenSSLKey
, 这里调用: OpenSSLKey.fromPrivateKeyForTLSStackOnly() -> fromECPrivateKeyForTLSStackOnly() -> OpenSSLECPrivateKey.wrapJCAPrivateKeyForTLSStackOnly()
, 首先调用OpenSSLECGroupContext.getInstance()
从ECParameterSpec
获取OpenSSLECGroupContext
. 创建OpenSSLKey
, 调用NativeCrypto_getECPrivateKeyWrapper()
产生底层的EVP_PKEY
结构体, 传递OpenSSLECGroupContext
作为参数:
上层传递了秘钥的 Group 信息, 通过fromContextObject
转换参数groupRef
转换到EC_GROUP
,
ensure_engine_globals() -> init_engine_globals()
初始化g_rsa_method
和g_ecdsa_method
:
ENGINE_new()
初始化g_engine
ENGINE_set_RSA_method
配置g_rsa_method
给g_engine
ENGINE_set_ECDSA_method
配置g_ecdsa_method
给g_engine
通过EC_KEY_new_method()
创建 EC_KEY
结构体
通过EC_KEY_set_group()
配置 EC_KEY
的 Group
信息
构造KeyExData
结构体, 将上层传递的javaKey
的 jobject
对象保存到刚刚创建的KeyExData.private_key
字段
通过EC_KEY_set_ex_data()
配置KeyExData
结构体到 EC_KEY
通过EVP_PKEY_new()
创建EVP_PKEY
结构体
通过EVP_PKEY_assign_EC_KEY()
将EC_KEY
结构体分配给 EVP_PKEY
结构体
创建的 EVP_PKEY
结构体保存到OpenSSLKey.ctx
中, 所以后续将OpenSSLKey
传递给底层时, 获取ctx
即可
可以看到, OpenSSLKey.ctx
即EVP_PKEY
, 其中:
EVP_PKEY.ameth
被设置为ec_asn1_meth
const EVP_PKEY_ASN1_METHOD ec_asn1_meth = {
EVP_PKEY_EC,
// 1.2.840.10045.2.1
{0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01},
7,
&ec_pkey_meth,
eckey_pub_decode, // 从 DER 中解码 EC-PublicKey
eckey_pub_encode, // 编码 EC-PublicKey 到 DER
eckey_pub_cmp, // 比较两个公钥是否相同
eckey_priv_decode, // 从 DER 解码 EC-PrivateKey
eckey_priv_encode, // 编码 EC-PrivateKey 到 DER
eckey_set1_tls_encodedpoint,
eckey_get1_tls_encodedpoint,
eckey_opaque,
int_ec_size,
ec_bits,
ec_missing_parameters,
ec_copy_parameters, // 拷贝 ECC 秘钥参数
ec_cmp_parameters, // 比较 ECC 秘钥参数
int_ec_free,
};
其中ec_pkey_meth
的类型为EVP_PKEY_METHOD
, 作为EVP_PKEY
的操作方法, 记录在EVP_PKEY_CTX.pmeth
const EVP_PKEY_METHOD ec_pkey_meth = {
EVP_PKEY_EC,
pkey_ec_init,
pkey_ec_copy,
pkey_ec_cleanup,
pkey_ec_keygen, // 生成 ECC 秘钥
pkey_ec_sign, // 使用 EC-PrivateKey 执行签名
pkey_ec_verify, // 使用 EC-PublicKey 验证签名
pkey_ec_derive, // 使用 EC-PrivateKey 进行 ECDH
pkey_ec_paramgen,
pkey_ec_ctrl,
};
EVP_PKEY.pkey
被设置为EC_KEY
,其中:
EC_KEY.ecdsa_meth
被设置为上文提及的: g_ecdsa_method
, 其中:
EC_KEY.ecdsa_meth->sign
为EcdsaMethodSign()
EC_KEY.ecdsa_meth->flags
为ECDSA_FLAG_OPAQUE
EC_KEY.ex_data.sk
被设置为上文体积的: KeyExData
结构体调用NativeCrypto.setLocalCertsAndPrivateKey()
设置上文获取的X509Certificate
(转换到byte[][]
)和OpenSSLKey
到底层
接下来看NativeCrypto.setLocalCertsAndPrivateKey
, 改函数对应: NativeCrypto_setLocalCertsAndPrivateKey()
:
SSL
结构体fromContextObject()
获取上层的EVP_PKEY
结构体(从上文提及的OpenSSLKey.ctx
中获取)CRYPTO_BUFFER
结构体SSL_set_chain_and_key() -> cert_set_chain_and_key()
:
check_leaf_cert_and_privkey()
检查私钥与证书是否配对, 这里需要注意的是, 其中的一个检查步骤为ssl_compare_public_and_private_key()
, 该函数中做了如下逻辑: if (EVP_PKEY_is_opaque(privkey)) {
// We cannot check an opaque private key and have to trust that it
// matches.
return true;
}
EVP_PKEY.ameth->pkey_opaque
为ec_asn1_meth.pkey_opaque
也就是eckey_opaque
该函数通过eckey_opaque()
判断EVP_PKEY.pkey
也就是EC_KEY
中的ECDSA_METHOD.flags
是否设置了ECDSA_FLAG_OPAQUE
, 上文提到EC_KEY.ecdsa_meth.flags
已经设置了ECDSA_FLAG_OPAQUE
, 所以这里不会报错
std::vector
的证书信息和EVP_PKEY
的私钥信息配置给SSL
结构体, 这里:SSL.config->cert->chain
保存数个CRYPTO_BUFFER
SSL.config->cert->privatekey
保存EVP_PKEY
SSL.config->cert->key_method
设置为空执行do_send_client_certificate_verify() -> ssl_private_key_sign()
中:
setup_ctx() -> EVP_DigestSignInit() -> do_sigver_init() -> EVP_PKEY_CTX_new()
, 因为EVP_PKEY.ameth->pkey_method
为ec_asn1_meth.pkey_method
, 即ec_pkey_meth
, 因此创建的EVP_PKEY_CTX.pmeth
为ec_pkey_meth
, 创建的EVP_MD_CTX
在do_sigver_init()
中设置到EVP_MD_CTX.pctx
EVP_DigestSign() -> EVP_DigestSignFinal() -> EVP_PKEY_sign() -> EVP_PKEY.pmeth->sign
, 即上一步骤提及的ec_pkey_meth.sign
即pkey_ec_sign()
, 该方法先 从EVP_PKEY
获取EC_KEY
, 然后调用ECDSA_sign()
, 传入EC_KEY
, 如果设置了EC_KEY.ecdsa_meth->sign
方法, 则调用, 如上文, 这里调用EcdsaMethodSign()
:
EcKeyGetKey() -> EC_KEY_get_ex_data
从EC_KEY
中获取KeyExData
结构体中的PrivateKey
对象对应的jobject
ecSignDigestWithPrivateKey()
, 并将上一步骤获取的PrivateKey
对象以及签名数据做为参数, 对应的上层调用为: CryptoUpcalls.ecSignDigestWithPrivateKey() -> signDigestWithPrivateKey()
:
Signature.getInstance()
获取默认签名算法, 然后调用Signature.initSign()
设置PrivateKey
, 执行 Signature.update()
更新签名数据后, 执行Signature.sign()
进行签名. 这里的 Signature
和上层自定义的PrivateKey
是配套的, 这部分内容, 在后续介绍 Security.Provider
时再介绍.调用do_complete_second_flight()
:
tls13_add_finished()
发送协商结束消息tls13_set_traffic_key()
设置SSL_HANDSHAKE.client_traffic_secret_0_
为新的会话密钥调用do_finish_client_handshake()
, 这里将SSL.s3->established_session
设置为SSL.session
上层调用: SSLOutputStream.write() -> writeInternal() -> ConscryptEngine.wrap()
, ConscryptEngine.wrap()
的语义是: 明文到加密数据的: 加密, 分两个步骤:
writePlaintextData() -> writePlaintextDataHeap() -> writePlaintextDataDirect()
将数据往NativeSsl
写, 更底层的操作是NativeCrypto.ENGINE_SSL_write_direct()
readEncryptedData() -> readEncryptedDataDirect()
从BioWrapper
读取数据, 更底层的操作是NativeCrypto.ENGINE_SSL_read_BIO_direct()
从这里也可以总结出: 对于加密数据, 统一由 BioWrapper
传递, 对于明文数据, 统一通过NativeSsl
直接传递, 这里的BioWrapper
也是后续 MTLS 协商结束后的 AES 加密通道.
NativeCrypto.ENGINE_SSL_write_direct() ->
NativeCrypto_ENGINE_SSL_write_direct() [libjavacrypto.so] ->
::SSL_write() [libssl.so]
此处, SSL.method->write_app_data
为kTLSProtocolMethod
中的tls_write_app_data()
, 因此
::SSL_write() [libssl.so] ->
bssl::tls_write_app_data() ->
bssl::do_tls_write()
此处分两个步骤:
bssl::do_tls_write() -> bssl::tls_seal_record() -> bssl::tls_seal_scatter_record() -> bssl::do_seal_record()
, 此处SSL.s3->aead_write_ctx
为: SSLAEADContext
, 因此:bssl::SSLAEADContext::SealScatter()
被调用, 这里的ctx_
为EVP_AEAD_CTX
, 而EVP_AEAD_CTX.aead
为EVP_aead_aes_256_gcm_tls13
, 因此EVP_AEAD_CTX.aead->seal_scatter
为aead_aes_gcm_tls13_seal_scatter() [libcrypto.so]
, 这里有硬件加速的部分, 简单列出调用的堆栈, 具体细节本文不做讨论: EVP_AEAD_CTX_seal_scatter() [libcrypto.so] ->
aead_aes_gcm_tls13_seal_scatter() ->
aead_aes_gcm_seal_scatter() ->
aead_aes_gcm_seal_scatter_impl() ->
CRYPTO_gcm128_encrypt()
bssl::do_tls_write() -> bssl::tls_seal_record() -> bssl::tls_seal_scatter_record() -> bssl::ssl_write_buffer_flush() -> tls_write_buffer_flush() -> BIO_write()
, 将ssl.s3->write_buffer
数据写入到SSL.wbio
的BIO
中, 如前文所述, 该BIO
即internal_bio
, 其关联的对象为network_bio
, 至此上层就可以通过NativeCrypto.ENGINE_SSL_read_BIO_direct()
读取到数 BoringSSL 需要发送的数据了.NativeCrypto.ENGINE_SSL_read_BIO_direct() ->
NativeCrypto_ENGINE_SSL_read_BIO_direct() [libjavacrypto.so] ->
::BIO_read() ->
bio_read() [external/boringssl/src/crypto/bio/pair.c]
这里从network_bio
读取internal_bio
的加密数据.
上层调用: SSLInputStream.read() -> readUntilDataAvailable() -> processDataFromSocket() -> ConscryptEngine.unwrap()
, ConscryptEngine.unwrap()
的语义是: 加密数据到明文的: 解密, ,unwrap()
分两个步骤进行:
* 首先是writeEncryptedData() -> writeEncryptedDataHeap() -> writeEncryptedDataDirect()
将数据往BioWrapper
写, 更底层的操作是NativeCrypto.ENGINE_SSL_write_BIO_direct()
* 然后是readPlaintextData() -> readPlaintextDataDirect()
从NativeSsl
读取数据, 更底层的操作是NativeCrypto.ENGINE_SSL_read_direct()
NativeCrypto.ENGINE_SSL_write_BIO_direct() ->
NativeCrypto_ENGINE_SSL_write_BIO_direct() [libjavacrypto.so] ->
::BIO_write() ->
bio_write() [external/boringssl/src/crypto/bio/pair.c]
这里通过network_bio
写入加密数据到internal_bio
NativeCrypto.ENGINE_SSL_read_direct() ->
NativeCrypto_ENGINE_SSL_read_direct() [libjavacrypto.so] ->
::SSL_read() ->
::SSL_peek() ->
ssl_read_impl()
这里开始分两部分:
BIO
中读取上层写入的加密数据ssl_read_impl() ->
bssl::ssl_handle_open_record() ->
bssl::ssl_read_buffer_extend_to() ->
tls_read_buffer_extend_to() ->
BIO_read() [libcrypto.so] ->
bio_read()
ssl_read_impl() -> tls_open_app_data() -> tls_open_record()
, 此处SSL.s3->aead_read_ctx
为: SSLAEADContext
, 因此:bssl::SSLAEADContext::Open() -> EVP_AEAD_CTX_open() -> EVP_AEAD_CTX_open_gather()
被调用, 这里的ctx_
为EVP_AEAD_CTX
, 而EVP_AEAD_CTX.aead
为EVP_aead_aes_256_gcm_tls13
, 因此EVP_AEAD_CTX.aead->open_gather
为aead_aes_gcm_open_gather() [libcrypto.so]
, 这里有硬件加速的部分, 简单列出调用的堆栈, 具体细节本文不做讨论:bssl::tls_open_record() ->
bssl::SSLAEADContext::Open() ->
EVP_AEAD_CTX_open() ->
EVP_AEAD_CTX_open_gather() ->
aead_aes_gcm_open_gather_impl() ->
CRYPTO_gcm128_decrypt_ctr32()