铜锁支持大数运算硬件加速机制

简介: 背景密码学中的很多算法,如 RSA、Paillier、ECC、EC-ElGamal、Diffie-Hellman 密钥交换等,都涉及大数运算,大素数生成、大数乘法、大数模幂等在加密和解密过程中都是必不可少的运算。加密货币和区块链技术中的密码学算法都依赖于大数运算。我们知道,数字越大,运算速度也越慢,但数字越小就越不安全。所以,RSA 为了安全性,位数要求 2048 位以上,Paillier 与 R

背景

密码学中的很多算法,如 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)(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);
    /* 模开根号 */
    BIGNUM *(*mod_sqrt)(BIGNUM *r, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx);
    /* 模逆 */
    BIGNUM *(*mod_inverse)(BIGNUM *r, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx);
    /* 除法 */
    int (*div)(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx);
};
# endif

通过如下 API 可以给 BN_CTX设置 engine 和 method:

/* 创建 method */
BN_METHOD *BN_METHOD_new(const char *name);
/* 释放 method */
void BN_METHOD_free(BN_METHOD *meth);

/* 给 BN_CTX 设置 engine */
int BN_CTX_set_engine(BN_CTX *ctx, ENGINE *engine);
/* 给 BN_CTX 设置 method */
int BN_CTX_set_method(BN_CTX *ctx, const BN_METHOD *method);

/* 绑定 engine 和 method,一般是在 engine 模块中调用 */
int ENGINE_set_bn_meth(ENGINE *e, const BN_METHOD *bn_meth);

通过如下 API 可以设置 hook 函数:

void BN_METHOD_set_add(BN_METHOD *meth,
                       int (*mod_add)(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
                                      const BIGNUM *m, BN_CTX *ctx));

void BN_METHOD_set_sub(BN_METHOD *meth,
                       int (*mod_sub)(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
                                      const BIGNUM *m, BN_CTX *ctx));

void BN_METHOD_set_mul(BN_METHOD *meth,
                       int (*mod_mul)(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
                                      const BIGNUM *m, BN_CTX *ctx));

void BN_METHOD_set_exp(BN_METHOD *meth,
                       int (*mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
                                      const BIGNUM *m, BN_CTX *ctx));

void BN_METHOD_set_sqr(BN_METHOD *meth,
                       int (*mod_sqr)(BIGNUM *r, const BIGNUM *a, const BIGNUM *m,
                                      BN_CTX *ctx));

void BN_METHOD_set_sqrt(BN_METHOD *meth,
                        BIGNUM *(*mod_sqrt)(BIGNUM *r, const BIGNUM *a,
                                            const BIGNUM *n, BN_CTX *ctx));

void BN_METHOD_set_inverse(BN_METHOD *meth,
                           BIGNUM *(*mod_inverse)(BIGNUM *r, const BIGNUM *a,
                                                  const BIGNUM *n, BN_CTX *ctx));
void BN_METHOD_set_div(BN_METHOD *meth,
                       int (*div)(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m,
                                  const BIGNUM *d, BN_CTX *ctx));

例子

engine 例子

下面是一个实现模加、模减、模乘、模幂操作后再加一的例子:

#include <stdio.h>
#include <string.h>

#include <openssl/engine.h>
#include <openssl/crypto.h>
#include <openssl/bn.h>

static const char *engine_bntest_id = "bntest";
static const char *engine_bntest_name = "Tongsuo bn_method engine support";

static BN_METHOD *bn_method = NULL;
static BN_CTX *bn_ctx = NULL;

static int bntest_destroy(ENGINE *e);
static int bntest_init(ENGINE *e);
static int bntest_finish(ENGINE *e);

#ifndef OPENSSL_NO_BN_METHOD
static int bn_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx)
{
    int ret = 0;
    ret = m ? BN_mod_add(r, a, b, m, bn_ctx) : BN_add(r, a, b);
    BN_add_word(r, 1);
    return ret;
}

static int bn_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx)
{
    int ret = 0;
    ret = m ? BN_mod_sub(r, a, b, m, bn_ctx) : BN_sub(r, a, b);
    BN_add_word(r, 1);
    return ret;
}

static int bn_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx)
{
    int ret = 0;

    ret = m ? BN_mod_mul(r, a, b, m, bn_ctx) : BN_mul(r, a, b, bn_ctx);

    BN_add_word(r, 1);
    return ret;
}

static int bn_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx)
{
    int ret = 0;
    ret = BN_mod_exp(r, a, p, m, bn_ctx);
    BN_add_word(r, 1);
    return ret;
}
#endif

static int bind_bntest(ENGINE *e)
{
    bn_method = BN_METHOD_new("test");
    if (bn_method == NULL)
        return 0;

    bn_ctx = BN_CTX_new();
    if (bn_ctx == NULL)
        return 0;

    if (!ENGINE_set_id(e, engine_bntest_id)
        || !ENGINE_set_name(e, engine_bntest_name)
#ifndef OPENSSL_NO_BN_METHOD
        || !ENGINE_set_bn_meth(e, bn_method)
#endif
        || !ENGINE_set_destroy_function(e, bntest_destroy)
        || !ENGINE_set_init_function(e, bntest_init)
        || !ENGINE_set_finish_function(e, bntest_finish)) {
        return 0;
    }

    return 1;
}

static int bind_helper(ENGINE *e, const char *id)
{
    if (id && (strcmp(id, engine_bntest_id) != 0))
        return 0;
    if (!bind_bntest(e))
        return 0;
    return 1;
}

static int bntest_init(ENGINE *e)
{
#ifndef OPENSSL_NO_BN_METHOD
    BN_METHOD_set_add(bn_method, bn_add);
    BN_METHOD_set_sub(bn_method, bn_sub);
    BN_METHOD_set_mul(bn_method, bn_mul);
    BN_METHOD_set_exp(bn_method, bn_exp);
#endif

    return 1;
}

static int bntest_finish(ENGINE *e)
{
    return 1;
}

static int bntest_destroy(ENGINE *e)
{
    BN_CTX_free(bn_ctx);
    BN_METHOD_free(bn_method);
    return 1;
}

IMPLEMENT_DYNAMIC_CHECK_FN()
IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)

调用例子

/*
 * Copyright 2023 The Tongsuo Project Authors. All Rights Reserved.
 *
 * Licensed under the Apache License 2.0 (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://github.com/Tongsuo-Project/Tongsuo/blob/master/LICENSE.txt
 */

#include <stdio.h>
#include <string.h>
#include <openssl/bn.h>
#include <openssl/bio.h>

#ifndef OPENSSL_NO_ENGINE
# include <openssl/engine.h>
#endif

#ifndef OPENSSL_NO_ENGINE
static ENGINE *e;
#endif

static const char *hex_numbers[] = {
    "10",
    "02",
    "FF",
};

void bn_print(BIO *bio, const BIGNUM *n, const char *name)
{
    BIO *b = NULL;

    if (bio == NULL) {
        bio = b = BIO_new(BIO_s_file());
        BIO_set_fp(bio, stderr, BIO_NOCLOSE);
    }

    BIO_printf(bio, "%s = 0x", name);
    BN_print(bio, n);
    BIO_printf(bio, "\n");

    BIO_free(b);
}

int main(int argc, char *argv[])
{
    int ret = 0, load_engine = 0;
    BN_CTX *ctx = NULL;
    BIGNUM *a, *b, *m, *r;

	if (argc == 2 && strcmp(argv[1], "1") == 0) {
		load_engine = 1;
	}

#ifndef OPENSSL_NO_ENGINE
    if (load_engine && (e = ENGINE_by_id("bntest")) == NULL) {
        fprintf(stderr, "Can't load bntest engine");
    }
#endif

    ctx = BN_CTX_new();
    if (ctx == NULL) {
        goto err;
    }

    BN_CTX_start(ctx);
    a = BN_CTX_get(ctx);
    b = BN_CTX_get(ctx);
    m = BN_CTX_get(ctx);
    r = BN_CTX_get(ctx);
    if (r == NULL) {
        goto err;
	}

#ifndef OPENSSL_NO_ENGINE
    if (load_engine && !BN_CTX_set_engine(ctx, e)) {
        goto err;
	}
#endif

    BN_hex2bn(&a, hex_numbers[0]);
    BN_hex2bn(&b, hex_numbers[1]);
    BN_hex2bn(&m, hex_numbers[2]);

    bn_print(NULL, a, "a");
    bn_print(NULL, b, "b");
    bn_print(NULL, m, "m");

    BN_mul(r, a, b, ctx);
    bn_print(NULL, r, "a*b");

    BN_exp(r, a, b, ctx);
    bn_print(NULL, r, "a^b");

    BN_mod_add(r, a, b, m, ctx);
    bn_print(NULL, r, "a+b mod m");

    BN_mod_sub(r, a, b, m, ctx);
    bn_print(NULL, r, "a-b mod m");

    BN_mod_mul(r, a, b, m, ctx);
    bn_print(NULL, r, "a*b mod m");

    BN_mod_exp(r, a, b, m, ctx);
    bn_print(NULL, r, "a^b mod m");

    ret = 1;
err:
    BN_CTX_end(ctx);
    BN_CTX_free(ctx);
#ifndef OPENSSL_NO_ENGINE
    ENGINE_free(e);
#endif
    return ret;
}

编译&运行

  • 编译 engine
$ gcc -shared -fPIC -o bntest.so ./bntest.c -I/opt/tongsuo-debug/include -L/opt/tongsuo-debug/lib -lcrypto -Wl,-rpath -Wl,/opt/tongsuo-debug/lib
  • 编译 test
$ gcc -Wall -g -o test test.c -I/opt/tongsuo-debug/include -L/opt/tongsuo-debug/lib -lcrypto -Wl,-rpath -Wl,/opt/tongsuo-debug/lib
  • 运行 test
$ ./test
a = 0x10
b = 0x2
m = 0xFF
a*b = 0x20
a^b = 0x100
a+b mod m = 0x12
a-b mod m = 0xE
a*b mod m = 0x20
a^b mod m = 0x1

$ ./test 1
a = 0x10
b = 0x2
m = 0xFF
a*b = 0x21
a^b = 0x101
a+b mod m = 0x13
a-b mod m = 0xF
a*b mod m = 0x21
a^b mod m = 0x2

从上述运行结果可看出,当不加载 bntest engine 时,a 和 b 的乘、幂、模加、模减、模乘、模幂运算均正确,当加载了 bntest engine 后,这些运算的结果均已自动加了 1,说明 bntest engine 发挥了作用,我们可以通过这种方式在 bntest engine 调用硬件的 api 来实现大数运算的加速。

目录
相关文章
|
6月前
|
大数据 API 图形学
Unity优化——批处理的优势
Unity优化——批处理的优势
174 0
|
13天前
|
UED
鸿蒙next版开发:音频并发策略扩展(ArkTS)
在HarmonyOS 5.0中,音频并发策略通过ArkTS的AudioSessionManager接口管理多个音频流的交互和优先级。本文介绍了如何自定义音频焦点策略,包括激活、停用音频会话及注册回调函数,并提供了示例代码。适用于多媒体、通信和游戏应用。
40 4
|
1月前
|
缓存 算法 测试技术
|
3月前
|
缓存 算法 OLTP
自适应软件缓存管理
自适应软件缓存管理
41 1
|
6月前
|
缓存 弹性计算 负载均衡
中间件硬件性能不足
解决中间件硬件性能不足的问题需要从多个方面入手,包括升级硬件设备、优化资源配置、引入负载均衡机制、优化中间件配置、使用数据缓存技术以及进行实时监测与调优等。这些措施可以有效提升中间件的硬件性能,提高整个应用系统的性能和稳定性。
71 5
|
6月前
|
机器学习/深度学习 存储 人工智能
世界最快硬件加速器Groq LPU的底层架构设计!
【2月更文挑战第19天】世界最快硬件加速器Groq LPU的底层架构设计!
142 1
世界最快硬件加速器Groq LPU的底层架构设计!
|
6月前
|
前端开发 JavaScript Java
jtml兼容性优化
【2月更文挑战第11天】jtml兼容性优化
176 1
140 混合的推荐机制
140 混合的推荐机制
42 0
|
算法 安全 Linux
高性能网络 SIG 月度动态:推动 virtio 支持动态中断调节及更灵活的分流机制
高性能网络 SIG 月度动态送达,一键了解 8 月各项目进展。
|
Rust JavaScript 前端开发
WASM 在动画引擎中的设计优化
WASM 在动画引擎中的设计优化
182 0