2016-04-04 66 views
2

我有一個我想要做的最小,完整和可驗證示例。
基本上我想實現一個集成了一些CUDA代碼的OpenSSL RSA引擎。 CUDA部分應該執行模冪運算,但在本例中它並不重要,所以我只使用了BN_mod_exp(請參閱engine.c文件,modexp函數)以簡化代碼。我給出的代碼是我的項目的簡化版本,它可以建立/編譯很容易與這些命令:OpenSSL RSA引擎 - RSA驗證失敗

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); 
} 

...接下來的兩個文件是用於演示的目的,我的再生項目

/*my_cuda.cu*/ 
#include <cuda_runtime.h> 
#include <stdio.h> 
extern "C" { 
#include "my_cuda.h" 
} 

__global__ void dummy_gpu_kernel(){ 
    // stuff here 
} 
extern "C" 
void modexp512(){ 
    dummy_gpu_kernel<<<1,1>>>(); 
} 

...

/*my_cuda.h*/ 
#ifndef MY_DUMMY 
#define MY_DUMMY 

void modexp512(); 

#endif 

現在我想用

$ 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部分是不是在這個例子中重要而有人想嘗試一下,他/她必須註釋掉engine.c文件#include "my_cuda.h"modexp512();並更改相應的構建過程,那就是:

gcc -fPIC -c engine.c 
g++ -shared -o gpu.so -lcrypto engine.o 

和嘗試相同的命令

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

回答

5

我修了這一點,因爲我覺得它很有趣。我不相信你做錯了什麼。我不能肯定rsa->_method_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源碼的閱讀將暗示它們應該被使用。

+0

@Dani Grosu那麼這是一個驚喜收集賞金。我會有興趣聽到它的結果。 –

+0

我錯誤地使用了'BN_mod_exp',它不適合'RSA_METHOD'結構的'rsa_mod_exp'成員。我認爲'rsa_mod_exp'正在處理pkcs1填充。由於我的問題是「我怎樣才能擺脫這個錯誤」,你的答案奏效了,你已經收到了賞金。 –

+0

@JimFlood是否有一個原因,你在modexp函數中聲明瞭新的RSA_METHOD,而不是在整個文件中使用所有引擎函數的'static const RSA_METHOD'?例如,如果我想創建一個只打印「Hello」,然後將每個引擎的RSA_METHOD函數重新路由到默認RSA_METHOD函數的RSA引擎,我實際上只需要一個'const RSA_METHOD * meth = RSA_PKCS1_SSLeay() 「對吧?而不是將其納入每個引擎功能?對不起,如果這是一個愚蠢的問題,但它現在與我有關。 – Brett