openssl动态引擎

openssl引擎的例子

ENGINE是OPENSSL预留的用以加载第三方加密库引擎,主要包括了动态库加载的代码和加密函数指针管理的一系列接口。

自定义一个引擎

void

ENGINE_load_rtl8651b(void)

{

        ENGINE *engine = ENGINE_new();

        if (engine == NULL)

                return;

        if (!ENGINE_set_id(engine, "rtl8651b") ||

            !ENGINE_set_name(engine, "BSD rtl8651b engine") ||

            !ENGINE_set_ciphers(engine, rtl8651b_engine_ciphers)||

            !ENGINE_set_digests(engine, rtl8651b_engine_digests)||

            !ENGINE_set_ctrl_function(engine, rtl8651b_ctrl) ||

            !ENGINE_set_cmd_defns(engine, rtl8651b_defns)

          ){

                ENGINE_free(engine);

                return;

        }


        if(!ENGINE_set_default(engine, ENGINE_METHOD_DIGESTS) )


        ENGINE_add(engine);

        ENGINE_free(engine);

        ERR_clear_error();

}

设置替换哪些算法

你可以使用自己的实现来替换openssl的默认算法。
ENGINE_set_default(ENGINE *e, int Flag)

其中Flag的说明如下:

ENGINE_METHOD_ALL 使用所有存在的算法(默认)

ENGINE_METHOD_RSA 仅使用RSA算法

ENGINE_METHOD_DSA 仅使用DSA算法

ENGINE_METHOD_DH 仅使用DH算法

ENGINE_METHOD_RAND 仅使用随机数算法

ENGINE_METHOD_CIPHERS 仅使用对称加解密算法

ENGINE_METHOD_DIGESTS 仅使用摘要算法

动态引擎

动态引擎是openssl提供的一个引擎,这个引擎是用来加载其他引擎的(加载你实现的引擎库so)。

openssl提供了动态绑定宏方法

IMPLEMENT_DYNAMIC_CHECK_FN()
IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
其实就是帮我们定义了两个方法,然后这两个方法是在动态引擎的load方法中调用的。


# define IMPLEMENT_DYNAMIC_CHECK_FN() \
        OPENSSL_EXPORT unsigned long v_check(unsigned long v); \
        OPENSSL_EXPORT unsigned long v_check(unsigned long v) { \
                if (v >= OSSL_DYNAMIC_OLDEST) return OSSL_DYNAMIC_VERSION; \
                return 0; }



# define IMPLEMENT_DYNAMIC_BIND_FN(fn) \
        OPENSSL_EXPORT \
        int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns); \
        OPENSSL_EXPORT \
        int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns) { \
            if (ENGINE_get_static_state() == fns->static_state) goto skip_cbs; \
            CRYPTO_set_mem_functions(fns->mem_fns.malloc_fn, \
                                     fns->mem_fns.realloc_fn, \
                                     fns->mem_fns.free_fn); \
        skip_cbs: \
            if (!fn(e, id)) return 0; \
            return 1; }

定义绑定方法

如下,我们自定义了几个方法。其实就是替换openssl的默认实现,实现自己的功能。

//返回值 1为成功 0为失败
int bind_fn(ENGINE *e, const char *id)
{
  if (id && (strcmp(id, FILE_ENGINE_ID) != 0)) {
    fprintf(stderr, "bad engine id\n");
    return 0;
  }
  if (!bind_helper(e)) {
    fprintf(stderr, "bind failed\n");
    return 0;
  }
}

//设置新引擎的相关方法。
static int bind_helper(ENGINE *e) {
  if (!ENGINE_set_id(e, FILE_ENGINE_ID) ||
      !ENGINE_set_destroy_function(e, file_engine_destroy) ||
      !ENGINE_set_init_function(e, file_init) ||
      !ENGINE_set_finish_function(e, file_finish) ||
      !ENGINE_set_ctrl_function(e, file_engine_ctrl) ||
      !ENGINE_set_cmd_defns(e, file_cmd_defns) ||
      !ENGINE_set_name(e, FILE_ENGINE_NAME) ||
      !ENGINE_set_RSA(e, RSA_get_default_method()) ||
      !ENGINE_set_load_pubkey_function(e, file_load_public_key) ||
      !ENGINE_set_load_privkey_function(e, file_load_private_key)) {
    return 0;
  } else {
    return 1;
  }
}


IMPLEMENT_DYNAMIC_CHECK_FN()
IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)

将上面的新引擎编译成动态库

动态引擎初始化我们定义的引擎库

例子如下。

  1. 判断以前是否已经加载,没有加载才进行加载
  2. 加载动态引擎,因为我们的引擎是个so库,我们需要动态引擎来加载它
  3. 使用动态引擎的命令加载我们的引擎,pszEnginePath是引擎的路径,此方法只是把我们引擎库路径赋值给动态引擎的一个内部变量
    ENGINE_ctrl_cmd_string(e, “SO_PATH”, pszEnginePath, 0)
  4. 调用load方法,此方法会动态加载so库,并调用上面宏定义的检测版本和绑定方法。ENGINE_ctrl_cmd_string(e, “LOAD”, NULL, 0)
  5. 设置引擎的默认flag, 例子中使用引擎所有方法,但是不用他的RSA方法ENGINE_set_default(e, ENGINE_METHOD_ALL & ~ENGINE_METHOD_RSA)
  6. 调用我么定义的引擎初始化方法 ENGINE_init
  7. 调用我们定义的引擎内部定义的命令控制方法ENGINE_ctrl_cmd_string(e, “MODULE_PATH”, m_szProvider, 0),可选
  8. 将引擎加入到链表中。

do{
ENGINE *e = NULL;
    e = ENGINE_by_id("file");
    if (NULL != e) {
      PLOGD << "FileEngine is found in the Engine list!";

      nRet = ST_SUCCESS;
      break;
    }

    int rv = 0;
    char szErr[1024] = "";

    ENGINE_load_dynamic();
    e = ENGINE_by_id("dynamic");
    if (!e) {
      PLOGE << "get dynamic engine error!";
      break;
    }

    if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", pszEnginePath, 0)) {
      PLOGE << "so_path command call error!";
      break;
    }

    if (!ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) {
      PLOGE << "load command call error!";
      break;
    }

    if (!ENGINE_set_default(e, ENGINE_METHOD_ALL & ~ENGINE_METHOD_RSA)) {
      PLOGE << "engine_method_all command call error!";
      break;
    }

    if (!ENGINE_init(e)) {
      PLOGE << "file engine init error!";
      break;
    }

    if (!ENGINE_ctrl_cmd_string(e, "MODULE_PATH", m_szProvider, 0)) {
      PLOGE << "Setup Engine failed to set the Engine!";
      break;
    }

    if (!ENGINE_add(e)) {
      PLOGE << "ENGINE_add to the gloable list error!";
      break;
    }
}while(0);

使用新的引擎库

e = ENGINE_by_id(“file”);
然后传入到EVP相关方法或者自定义的命令中ENGINE_ctrl_cmd_string中实现调用就行了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值