背景
密码学中的很多算法,如 RSA、Paillier、ECC、EC-ElGamal、Diffie-Hellman 密钥交换等,都涉及大数运算,大素数生成、大数乘法、大数模幂等在加密和解密过程中都是必不可少的运算。加密货币和区块链技术中的密码学算法都依赖于大数运算。我们知道,数字越大,运算速度也越慢,但数字越小就越不安全。所以,RSA 为了安全性,位数要求 2048 位以上,Paillier 与 RSA 类似,推荐位数也是 2048 位以上,随着计算技术的进步、密码学的发展和时间的推移,这个推荐位数可能会增加,性能也会受到挑战。
目前硬件的发展速度很快,比如 FPGA、GPU 这些定制的硬件可以用来解决目前大数运算慢的问题,这些硬件有专门的大数运算专用处理器、专用集成电路或者专用的指令集可以加速大数的运算,解放 CPU 的算力,提高整体计算效率。所以铜锁为了支持这些定制的加速硬件提供了加速的机制,在 engine 机制基础上,支持了大数运算相关接口的 hook 机制,让上层应用在能使用铜锁相关算法的时候也能绑定硬件来加速算法的运行速度,提高其业务性能。
实现
核心思想是在BIGNUM
相关运算 API 中加入 method 函数,或者称为 hook 函数,如果设置了这些 hook 函数则调用到这些 hook 函数,在这些 hook 函数中可以实现加速逻辑(比如调用硬件 API),需要注意的是,由于这些 method 函数是加在 BN_CTX
上,所以该功能仅对含有BN_CTX
参数的 API 有效。
这个机制依靠底层的 engine 框架,只要新增一种类型即可,下面是数据结构的核心改动(主要是宏 OPENSSL_NO_BN_METHOD
包起来的部分):
/* The opaque BN_CTX type */
struct bignum_ctx {
/* The bignum bundles */
BN_POOL pool;
/* The "stack frames", if you will */
BN_STACK stack;
/* The number of bignums currently assigned */
unsigned int used;
/* Depth of stack overflow */
int err_stack;
/* Block "gets" until an "end" (compatibility behaviour) */
int too_many;
/* Flags. */
int flags;
/* The library context */
OSSL_LIB_CTX *libctx;
# ifndef OPENSSL_NO_BN_METHOD
ENGINE *engine;
const BN_METHOD *bn_meth;
# endif
};
# ifndef OPENSSL_NO_BN_METHOD
/* 用户可以在自己 engine 中设置下面支持的 hook 函数 */
struct bn_method_st {
char *name;
/* 模加 */
int (*mod_add)(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx);
/* 模减 */
int (*mod_sub)(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx);
/* 模乘 */
int (*mod_mul)(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx);
/* 模幂 */
int (*mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx);
/* 模平方 */
int (*mod_sqr)(BIGN