OpenSSL 简介
OpenSSL
是包含安全套接字层和传输层安全协议的开源软件库,它几乎成为安全领域的事实标准,大部分的服务器和客户端都使用 OpenSSL
,一些硬件加密算法的实现通常也需要使用 OpenSSL
的命令行工具进行验证。在实际应用中,OpenSSL
可以提供动态引擎框架,可以方便用户使用密码设备完成硬件加速。
GmSSL 简介
国内与OpenSSL
相对应的开源项目为 GmSSL
,该项目中增加了国密算法,如SM2/SM3/SM4/SM9
等,同时也增加了对国家密码标准规范的支持,如SKF/SDF/IPSEC
等。
OpenSSL Engine 介绍
OpenSSL
为第三方提供了Engine
加载框架,方便用户使用自己的硬件设备完成密码学算法,例如服务器厂商可以通过加密卡厂商提供的 OpenSSL
引擎完成HTTPS的加速。OpenSSL 1.1.1
版本之后增加了异步模式的支持,这使得使用OpenSSL Engine
完成硬件加速成为了一种通用的加速手段。例如 intel
的 QAT
,国内的江南天安等。本文的剩余部分将介绍如何完成 OpenSSL
动态引擎的编写。
编写 OpenSSL Engine
除了国际算法,实际应用中可能有国密算法的需求,例如部分应用中需要使用国密套件SM2-WITH-SMS4-SM3
进行TLS
连接。本文将使用GmSSL完成引擎的实现。本文的示例代码可参考 gmssl_engine
。OpenSSL
提供了引擎相关Demo
,编写引擎时首先通过ENGINE_set_x
接口完成引擎相关信息及接口的配置:
static int bind_gmssl_engine(ENGINE *e, const char *id)
{
int ret = 1;
gmssl_engine_create_ciphers();
ret &= ENGINE_set_id(e, engine_id);
ret &= ENGINE_set_name(e, engine_name);
ret &= ENGINE_set_ciphers(e, gmssl_engine_ciphers);
ret &= ENGINE_set_pkey_meths(e, gmssl_engine_pkey);
ret &= ENGINE_set_destroy_function(e, engine_destroy);
ret &= ENGINE_set_init_function(e, engine_init);
ret &= ENGINE_set_finish_function(e, engine_finish);
ret &= ENGINE_set_ctrl_function(e, engine_ctrl);
ret &= ENGINE_set_cmd_defns(e, cmd_defns);
_assert(ret != 0, ret);
return ret;
}
通过IMPLEMENT_DYNAMIC_BIND_FN
宏定义完成引擎的注册:
IMPLEMENT_DYNAMIC_BIND_FN(bind_gmssl_engine)
IMPLEMENT_DYNAMIC_CHECK_FN()
这样只需要实现引擎中注册的相关接口即可,例如前面通过ENGINE_set_pkey_meths
接口设置的gmssl_engine_pkey
接口。以Pkey接口为例,通过EVP_PKEY_meth_set_x
接口完成PKEY
方法的注册。这里也可以通过PKEY
的子方法完成注册,例如ECC
相关的EC_KEY_METHOD
,OpenSSL speed
速度测试中直接调用字方法完成,这样的好处是可以使用speed
工具完成性能测试,但PKEY
接口更加通用,将公钥算法全部包含在内,目前GmSSL
支持的公钥算法相关NID
如下:
# define EVP_PKEY_NONE NID_undef
# define EVP_PKEY_RSA NID_rsaEncryption
# define EVP_PKEY_RSA2 NID_rsa
# define EVP_PKEY_DSA NID_dsa
# define EVP_PKEY_DSA1 NID_dsa_2
# define EVP_PKEY_DSA2 NID_dsaWithSHA
# define EVP_PKEY_DSA3 NID_dsaWithSHA1
# define EVP_PKEY_DSA4 NID_dsaWithSHA1_2
# define EVP_PKEY_DH NID_dhKeyAgreement
# define EVP_PKEY_DHX NID_dhpublicnumber
# define EVP_PKEY_EC NID_X9_62_id_ecPublicKey
# define EVP_PKEY_HMAC NID_hmac
# define EVP_PKEY_CMAC NID_cmac
# define EVP_PKEY_TLS1_PRF NID_tls1_prf
# define EVP_PKEY_HKDF NID_hkdf
# define EVP_PKEY_PAILLIER NID_paillier
# define EVP_PKEY_SM9_MASTER NID_id_sm9MasterSecret
# define EVP_PKEY_SM9 NID_id_sm9PublicKey
OpenSSL
还支持异步模式,引擎中需要增加ASYNC_x
相关接口完成挂起以及唤醒操作,在异步模式过程中,首先通过ASYNC_start_job
接口创建异步Job
,引擎相关加速接口中将任务卸载到硬件后通过ASYNC_get_wait_ctx
接口得到当前异步job
,并通过ASYNC_WAIT_CTX_get_fd
接口得到异步句柄,通过读取异步句柄的方式将任务挂起,当硬件计算完成后通过回调函数将任务唤醒继续执行,该过程和将人物挂起的流程类似,通过写异步句柄的方式将人物唤醒。由于示例代码中没有使用硬件设备,异步模式没有进行添加,但在实际应用中确非常重要。
总结
OpenSSL
不仅提供了很多实用的工具,其引擎框架在实际应用中也非常重要,与之对应的GmSSL
同样非常优秀。从NGINX
到OpenSSL
再到PCIE
加密卡,使得HTTPS
的连接速度变得更快。