OpenSSL RSA引擎-RSA验证失败

OpenSSL RSA引擎-RSA验证失败,openssl,openssl-engine,Openssl,Openssl Engine,下面是我想做的最简单、完整且可验证的示例。 基本上,我想实现一个集成了一些CUDA代码的OpenSSL RSA引擎。CUDA部分应该进行模幂运算,但在本例中它并不重要,因此我只使用了BN_mod_exp(请参阅engine.c文件modexp函数)来简化代码。我提供的代码是我的项目的简化版本,使用以下命令可以非常轻松地构建/编译: gcc -fPIC -I/usr/local/cuda/include -c engine.c nvcc --compiler-options '-fPIC' -c

下面是我想做的最简单、完整且可验证的示例。
基本上,我想实现一个集成了一些CUDA代码的OpenSSL RSA引擎。CUDA部分应该进行模幂运算,但在本例中它并不重要,因此我只使用了
BN_mod_exp
(请参阅engine.c文件
modexp
函数)来简化代码。我提供的代码是我的项目的简化版本,使用以下命令可以非常轻松地构建/编译:

gcc -fPIC -I/usr/local/cuda/include -c engine.c
nvcc --compiler-options '-fPIC' -c my_cuda.cu -lcrypto
g++ -L/usr/local/cuda/lib64 -shared -o gpu.so engine.o my_cuda.o -lcuda -lcudart
openssl engine -t -c `pwd`/gpu.so
。。。最后一个命令的输出表示RSA引擎可用

/*engine.c*/

#include <openssl/opensslconf.h>

#include <stdio.h>
#include <string.h>
#include <openssl/crypto.h>
#include <openssl/buffer.h>
#include <openssl/engine.h>

#include <openssl/rsa.h>

#include <openssl/bn.h>
#include <openssl/err.h>
#include "my_cuda.h"

/* Constants used when creating the ENGINE */
static const char *engine_e_rsax_id = "rsa_gpu";
static const char *engine_e_rsax_name = "RSAX engine support";
static int modexp(BIGNUM *r, const BIGNUM *I, RSA *rsa, BN_CTX *ctx);// r = r ^ I mod rsa->n
static int e_rsax_rsa_finish(RSA *r);
static int e_rsax_destroy(ENGINE *e);
static int e_rsax_init(ENGINE *e);
static int e_rsax_finish(ENGINE *e);
static int e_rsax_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void));

static const ENGINE_CMD_DEFN e_rsax_cmd_defns[] = {
    {0, NULL, NULL, 0}
};

static ENGINE *ENGINE_rsax (void);
void ENGINE_load_rsax (void)
    {
/* On non-x86 CPUs it just returns. */
    ENGINE *toadd = ENGINE_rsax();
    if(!toadd) return;
    ENGINE_add(toadd);
    ENGINE_free(toadd);
    ERR_clear_error();
    }


static RSA_METHOD e_rsax_rsa =
{
    "Intel RSA-X method",
    NULL,
    NULL,
    NULL,
    NULL,
    modexp,
    NULL,
    NULL,
    NULL,
    RSA_FLAG_CACHE_PUBLIC|RSA_FLAG_CACHE_PRIVATE,
    NULL,
    NULL,
    NULL
};

/* This internal function is used by ENGINE_rsax() */
static int bind_helper(ENGINE *e, const char *id)
    {
        printf("%s\n", id);

    const RSA_METHOD *meth1;

    if(!ENGINE_set_id(e, engine_e_rsax_id) ||
            !ENGINE_set_name(e, engine_e_rsax_name) ||

            !ENGINE_set_RSA(e, &e_rsax_rsa) ||

            !ENGINE_set_destroy_function(e, e_rsax_destroy) ||
            !ENGINE_set_init_function(e, e_rsax_init) ||
            !ENGINE_set_finish_function(e, e_rsax_finish) ||
            !ENGINE_set_ctrl_function(e, e_rsax_ctrl) ||
            !ENGINE_set_cmd_defns(e, e_rsax_cmd_defns))
        return 0;


    meth1 = RSA_PKCS1_SSLeay();
    e_rsax_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
    e_rsax_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
    e_rsax_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
    e_rsax_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
    e_rsax_rsa.bn_mod_exp = meth1->bn_mod_exp;
    e_rsax_rsa.finish = meth1->finish;

    return 1;
    }

    /* Used to attach our own key-data to an RSA structure */
static int rsax_ex_data_idx = -1;


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

/* (de)initialisation functions. */
static int e_rsax_init(ENGINE *e)
{

    if (rsax_ex_data_idx == -1)
        rsax_ex_data_idx = RSA_get_ex_new_index(0,
            NULL,
            NULL, NULL, NULL);

    if (rsax_ex_data_idx  == -1)
        return 0;
    return 1;
}

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

static int e_rsax_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
{
    int to_return = 1;

    switch(cmd)
        {
    /* The command isn't understood by this engine */
    default:
        to_return = 0;
        break;
        }

    return to_return;
}

IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
IMPLEMENT_DYNAMIC_CHECK_FN()

static ENGINE *ENGINE_rsax(void)
{
    ENGINE *ret = ENGINE_new();
    if(!ret)
        return NULL;
    if(!bind_helper(ret, engine_e_rsax_id))
        {
        ENGINE_free(ret);
        return NULL;
        }
    return ret;
}

static int modexp(BIGNUM *r, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)// r = r ^ I mod rsa->n
{
    modexp512();
    return BN_mod_exp(r, r, I, rsa->n, ctx);
}
现在,我想使用

$ openssl speed rsa512 -engine `pwd`/gpu.so
我收到下一个错误

/full/path/gpu.so
engine "rsa_gpu" set.
Doing 512 bit private rsa's for 10s: 575412 512 bit private RSA's in 10.02s
RSA verify failure.  No RSA verify will be done.
140592781633184:error:0407006A:rsa routines:RSA_padding_check_PKCS1_type_1:block type is not 01:rsa_pk1.c:100:
140592781633184:error:04067072:rsa routines:RSA_EAY_PUBLIC_DECRYPT:padding check failed:rsa_eay.c:721:
OpenSSL 1.0.1f 6 Jan 2014
built on: Mon Feb 29 18:11:15 UTC 2016
options:bn(64,64) rc4(16x,int) des(idx,cisc,16,int) aes(partial) blowfish(idx) 
compiler: cc -fPIC -DOPENSSL_PIC -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -m64 -DL_ENDIAN -DTERMIO -g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2 -Wl,-Bsymbolic-functions -Wl,-z,relro -Wa,--noexecstack -Wall -DMD32_REG_T=int -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DAES_ASM -DVPAES_ASM -DBSAES_ASM -DWHIRLPOOL_ASM -DGHASH_ASM
我在互联网上搜索过这些错误,但没有成功。我的问题是:如何消除“RSA验证失败。不会执行RSA验证”错误?似乎OpenSSL不信任我的实现或其他东西。
我已经删除了我以前的帖子,因为它无法被编译和验证。安装了OpenSSL和CUDA[可选]的任何人都可以验证此示例。但是,由于CUDA部分在本例中并不重要,并且有人想尝试它,因此他/她必须注释掉
#包括“my_CUDA.h”
modexp512()
engine.c
文件,并相应地更改生成过程,即:

gcc -fPIC -c engine.c
g++ -shared -o gpu.so -lcrypto engine.o
并尝试相同的命令

$ openssl speed rsa512 -engine `pwd`/gpu.so

我对此做了一些修改,因为我觉得它很有趣。我不相信你做错了什么。我不确定应该如何使用
rsa->\u method\u mod\n
,但我用以下内容替换了您的modexp:

static int modexp(BIGNUM *r, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
{
    const RSA_METHOD *meth = RSA_PKCS1_SSLeay();
    return meth->rsa_mod_exp(r, I, rsa, ctx);
}
它工作得很好,然后这个:

static int modexp(BIGNUM *r, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
{
    const RSA_METHOD *meth = RSA_PKCS1_SSLeay();
    return meth->bn_mod_exp(r, (const BIGNUM*) r, I, rsa->n, ctx, rsa->_method_mod_n);
}
正如你所描述的那样,它失败了


在这两种情况下,我都在使用该方法的OpenSSL函数,因为我对OpenSSL源代码的阅读表明应该使用这些函数。

@Dani Grosu收到赏金真是一个惊喜。我很想知道结果如何。我犯了一个错误,使用了
BN\u mod\u exp
,这根本不适合
rsa\u方法
结构的
rsa\u mod\u exp
成员。我认为
rsa\u mod\u exp
正在处理pkcs1填充。既然我的问题是“我如何才能消除这个[…]错误”,而且你的答案有效,那么你已经收到了赏金。@JimFlood你为什么要在modexp函数中声明新的RSA_方法,而不是在整个文件中使用一个
静态const RSA_方法
?例如,如果我想制作一个只打印“Hello”的RSA引擎,然后将引擎的每个RSA_方法函数重新路由到默认的RSA_方法函数,那么我实际上只需要一个
const RSA_方法*meth=RSA_PKCS1_SSLeay()的实例对吗?而不是将其包含在每个发动机功能中?如果这是一个愚蠢的问题,很抱歉,但它现在与我有关。@Brett我只是将它放在函数中,以便快速编写此代码以获得答案。没有特别的理由将其放在函数中。源文件中的所有函数都可以共享一个常量变量。
static int modexp(BIGNUM *r, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
{
    const RSA_METHOD *meth = RSA_PKCS1_SSLeay();
    return meth->rsa_mod_exp(r, I, rsa, ctx);
}
static int modexp(BIGNUM *r, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
{
    const RSA_METHOD *meth = RSA_PKCS1_SSLeay();
    return meth->bn_mod_exp(r, (const BIGNUM*) r, I, rsa->n, ctx, rsa->_method_mod_n);
}