以下的示例演示了采用Engine机制,来改变openssl的各种运算行为。实现的Engine方法有:随机数方法、对称算法、摘要算法以及RSA运算算法。其中,RSA计算中,密钥ID存放在Engine的扩展数据结构中。
#include <openssl/rsa.h>
#include <openssl/rand.h>
#include <openssl/engine.h>
static int hw_get_random_bytes(unsigned char* buf, int num)
{
int i;
printf("call hw_get_random_bytes\n");
for(i=0;i<num;i++)
memset(buf++,i,1);
return 1;
}
/* 生成RSA密钥对 */
static int genrete_rsa_key(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb)
{
printf("genrete_rsa_key \n");
return 1;
}
/* RSA公钥加密 */
int rsa_pub_enc(int flen,const unsigned char *from,unsigned char *to,RSA *rsa,int padding)
{
printf("call rsa_pub_enc \n");
return 1;
}
/*RSA公钥解密 */
int rsa_pub_dec(int flen,const unsigned char *from,unsigned char *to,RSA *rsa,int padding)
{
printf("call rsa_pub_enc \n");
return 1;
}
/* RSA私钥加密 */
int rsa_priv_enc(int flen,const unsigned char *from,unsigned char *to,RSA *rsa,int padding)
{
char*keyid;
/* 获取私钥id */
keyid=(char *)ENGINE_get_ex_data(rsa->engine,0);
printf("call rsa_pub_dec \n");
printf("use key id :%d \n",keyid);
return 1;
}
/* RSA私钥解密 */
int rsa_priv_dec(int flen,const unsigned char *from,unsigned char *to,RSA *rsa,int padding)
{
printf("call rsa_priv_dec \n");
return 1;
}
/* RSA算法 */
RSA_METHOD hw_rsa =
{
"hw cipher",
rsa_pub_enc,
rsa_pub_dec,
rsa_priv_enc,
rsa_priv_dec,
NULL,
NULL,
NULL,
NULL,
RSA_FLAG_SIGN_VER,
NULL,
NULL,
NULL,
genrete_rsa_key
};
/* 随机数方法 */
static RAND_METHOD hw_rand =
{
NULL,
hw_get_random_bytes,
NULL,
NULL,
NULL,
NULL,
};
/* Engine的id */
static const char *engine_hw_id = "ID_hw";
/* Engine的名字 */
static const char *engine_hw_name = "hwTest";
static int hw_init(ENGINE *e)
{
printf("call hw_init\n");
return 1;
}
static int hw_destroy(ENGINE *e)
{
printf("call hw_destroy\n");
return 1;
}
static int hw_finish(ENGINE *e)
{
printf("call hw_finish\n");
return 0;
}
static EVP_PKEY *hw_load_privkey(ENGINE* e, const char* key_id,
UI_METHOD *ui_method, void *callback_data)
{
/* 将密钥id放在ENGINE的扩展数据中 */
int index;
printf("call hw_load_privkey\n");
index=0;
ENGINE_set_ex_data(e, index, (char *)key_id);
return NULL;
}
#define HW_SET_RSA_PRIVATE_KEY 1
/* 实现自己的控制函数 */
static int hw_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
{
switch(cmd)
{
case HW_SET_RSA_PRIVATE_KEY:
hw_load_privkey(e,p,NULL,NULL);
break;
default:
printf("err.\n");
return -1;
}
return 0;
}
static EVP_PKEY *hw_load_pubkey(ENGINE* e, const char* key_id,
UI_METHOD *ui_method, void *callback_data)
{
printf("call hw_load_pubkey\n");
return NULL;
}
static const ENGINE_CMD_DEFN hw_cmd_defns[] = {
{ENGINE_CMD_BASE,
"SO_PATH",
"Specifies the path to the 'hw' shared library",
ENGINE_CMD_FLAG_STRING},
{0, NULL, NULL, 0}
};
static int hw_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
return 1;
}
static int hw_cipher_enc(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, unsigned int inl)
{
memcpy(out,in,inl);
return 1;
}
#include <openssl/objects.h>
/* 定义自己的des_ecb硬件算法*/
static const EVP_CIPHER EVP_hw_c=
{
NID_des_ecb,
1,8,0,
8,
hw_init_key,
hw_cipher_enc,
NULL,
1,
NULL,
NULL,
NULL,
NULL
};
const EVP_CIPHER *EVP_hw_cipher(void)
{
return(&EVP_hw_c);
}
/* 选择对称计算函数 */
static int cipher_nids[] =
{ NID_des_ecb, NID_des_ede3_cbc, 0 };
static int hw_ciphers(ENGINE *e, const EVP_CIPHER **cipher, const int **nids, int nid)
{
if(cipher==NULL)
{
*nids = cipher_nids;
return (sizeof(cipher_nids)-1)/sizeof(cipher_nids[0]);
}
switch (nid)
{
case NID_des_ecb:
*cipher = EVP_hw_ciphe()r;
break;
//其他对称函数
}
return 1;
}
static int init(EVP_MD_CTX *ctx)
{
printf("call md init\n");
return 1;
}
static int update(EVP_MD_CTX *ctx,const void *data,size_t count)
{
printf("call md update\n");
return 1;
}
static int final(EVP_MD_CTX *ctx,unsigned char *md)
{
int i;
printf("call md final\n");
for(i=0;i<20;i++)
memset(md++,i,1);
return 1;
}
int mySign(int type, const unsigned char *m, unsigned int m_length,
unsigned char *sigret, unsigned int *siglen, void *key)
{
RSA*k;
int keyid;
k=(RSA *)key;
/* 获取硬件中的私钥ID,进行计算 */
keyid=ENGINE_get_ex_data(k->engine,0);
printf("call mySign\n");
printf("use key id is %d\n",keyid);
return 1;
}
int myVerify(int type, const unsigned char *m, unsigned int m_length,
const unsigned char *sigbuf, unsigned int siglen,
void *key)
{
printf("call myVerify\n");
return 1;
}
static int digest_nids[] =
{ NID_sha1, NID_md5, 0 };
/* 实现的sha1摘要算法 */
static const EVP_MD hw_newmd=
{
NID_sha1,
NID_sha1WithRSAEncryption,
SHA_DIGEST_LENGTH,
0,
init,
update,
final,
NULL,
NULL,
mySign, /* sign */
myVerify,/* verify */
//sizeof(EVP_MD *)+sizeof(SHA_CTX),
6
};
static EVP_MD * EVP_hw_md()
{
return (&hw_newmd);
}
/* 选择摘要算法的函数 */
static int hw_md(ENGINE *e, const EVP_MD **digest,const int **nids, int nid)
{
if(digest==NULL)
{
*nids = digest_nids;
return (sizeof(digest_nids)-1)/sizeof(digest_nids[0]);
}
switch (nid)
{
case NID_sha1:
*digest = EVP_hw_md();
break;
//其他摘要函数
}
return 1;
}
static int bind_helper(ENGINE *e)
{
int ret;
ret=ENGINE_set_id(e, engine_hw_id);
if(ret!=1)
{
printf("ENGINE_set_id failed\n");
return 0;
}
ret=ENGINE_set_name(e, engine_hw_name);
if(ret!=1)
{
printf("ENGINE_set_name failed\n");
return 0;
}
ret=ENGINE_set_RSA(e, &hw_rsa);
if(ret!=1)
{
printf("ENGINE_set_RSA failed\n");
return 0;
}
ret=ENGINE_set_RAND(e, &hw_rand);
if(ret!=1)
{
printf("ENGINE_set_RAND failed\n");
return 0;
}
ret=ENGINE_set_destroy_function(e, hw_destroy);
if(ret!=1)
{
printf("ENGINE_set_destroy_function failed\n");
return 0;
}
ret=ENGINE_set_init_function(e, hw_init);
if(ret!=1)
{
printf("ENGINE_set_init_function failed\n");
return 0;
}
ret=ENGINE_set_finish_function(e, hw_finish);
if(ret!=1)
{
printf("ENGINE_set_finish_function failed\n");
return 0;
}
ret=ENGINE_set_ctrl_function(e, hw_ctrl);
if(ret!=1)
{
printf("ENGINE_set_ctrl_function failed\n");
return 0;
}
ret=ENGINE_set_load_privkey_function(e, hw_load_privkey);
if(ret!=1)
{
printf("ENGINE_set_load_privkey_function failed\n");
return 0;
}
ret=ENGINE_set_load_pubkey_function(e, hw_load_pubkey);
if(ret!=1)
{
printf("ENGINE_set_load_pubkey_function failed\n");
return 0;
}
ret=ENGINE_set_cmd_defns(e, hw_cmd_defns);
if(ret!=1)
{
printf("ENGINE_set_cmd_defns failed\n");
return 0;
}
ret=ENGINE_set_ciphers(e,hw_ciphers);
if(ret!=1)
{
printf("ENGINE_set_ciphers failed\n");
return 0;
}
ret=ENGINE_set_digests(e,hw_md);
if(ret!=1)
{
printf("ENGINE_set_digests failed\n");
return 0;
}
return 1;
}
static ENGINE *engine_hwcipher(void)
{
ENGINE *ret = ENGINE_new();
if(!ret)
return NULL;
if(!bind_helper(ret))
{
ENGINE_free(ret);
return NULL;
}
return ret;
}
void ENGINE_load_hwcipher()
{
ENGINE *e_hw = engine_hwcipher();
if (!e_hw) return;
ENGINE_add(e_hw);
ENGINE_free(e_hw);
ERR_clear_error();
}
#define HW_set_private_keyID(a) func(e,a,0,(void *)1,NULL)
#include <openssl/engine.h>
#include <openssl/evp.h>
int main()
{
ENGINE *e;
RSA_METHOD *meth;
int ret,num=20,i;
char buf[20],*name;
EVP_CIPHER*cipher;
EVP_MD *md;
EVP_MD_CTX mctx,md_ctx;
EVP_CIPHER_CTX ciph_ctx,dciph_ctx;
unsigned charkey[8],iv[8];
unsigned charin[50],out[100],dd[60];
int inl,outl,total,dtotal;
RSA *rkey;
RSA_METHOD *rsa_m;
EVP_PKEY *ek,*pkey;
ENGINE_CTRL_FUNC_PTR func;
OpenSSL_add_all_algorithms();
ENGINE_load_hwcipher();
e=ENGINE_by_id("ID_hw");
name = (char *)ENGINE_get_name(e);
printf("engine name :%s \n",name);
/* 随机数生成 */
ret=RAND_set_rand_engine(e);
if(ret!=1)
{
printf("RAND_set_rand_engine err\n");
return -1;
}
ret=ENGINE_set_default_RAND(e);
if(ret!=1)
{
printf("ENGINE_set_default_RAND err\n");
return -1;
}
ret=RAND_bytes((unsigned char *)buf,num);
/* 对称加密 */
for(i=0;i<8;i++)
memset(&key[i],i,1);
EVP_CIPHER_CTX_init(&ciph_ctx);
/* 采用Engine对称算法 */
cipher=EVP_des_ecb();
ret=EVP_EncryptInit_ex(&ciph_ctx,cipher,e,key,iv);
if(ret!=1)
{
printf("EVP_EncryptInit_ex err\n");
return -1;
}
strcpy((char *)in,"zcpsssssssssssss");
inl=strlen((const char *)in);
total=0;
ret=EVP_EncryptUpdate(&ciph_ctx,out,&outl,in,inl);
if(ret!=1)
{
printf("EVP_EncryptUpdate err\n");
return -1;
}
total+=outl;
ret=EVP_EncryptFinal(&ciph_ctx,out+total,&outl);
if(ret!=1)
{
printf("EVP_EncryptFinal err\n");
return -1;
}
total+=outl;
/* 解密 */
dtotal=0;
EVP_CIPHER_CTX_init(&dciph_ctx);
ret=EVP_DecryptInit_ex(&dciph_ctx,cipher,e,key,iv);
if(ret!=1)
{
printf("EVP_DecryptInit_ex err\n");
return -1;
}
ret=EVP_DecryptUpdate(&dciph_ctx,dd,&outl,out,total);
if(ret!=1)
{
printf("EVP_DecryptUpdate err\n");
return -1;
}
dtotal+=outl;
ret=EVP_DecryptFinal(&dciph_ctx,dd+dtotal,&outl);
if(ret!=1)
{
printf("EVP_DecryptFinal err\n");
return -1;
}
dtotal+=outl;
/* Engine摘要 */
EVP_MD_CTX_init(&mctx);
md=EVP_sha1();
ret=EVP_DigestInit_ex(&mctx,md,e);
if(ret!=1)
{
printf("EVP_DigestInit_ex err.\n");
return -1;
}
ret=EVP_DigestUpdate(&mctx,in,inl);
if(ret!=1)
{
printf("EVP_DigestInit_ex err.\n");
return -1;
}
ret=EVP_DigestFinal(&mctx,out,(unsigned int *)&outl);
if(ret!=1)
{
printf("EVP_DigestInit_ex err.\n");
return -1;
}
func=ENGINE_get_ctrl_function(e);
/* 设置计算私钥ID */
HW_set_private_keyID(1);
rkey=RSA_new_method(e);
pkey=EVP_PKEY_new();
EVP_PKEY_set1_RSA(pkey,rkey);
EVP_MD_CTX_init(&md_ctx);
ret=EVP_SignInit_ex(&md_ctx,EVP_sha1(),e);
if(ret!=1)
{
printf("EVP_SignInit_ex err\n");
return -1;
}
ret=EVP_SignUpdate(&md_ctx,in,inl);
if(ret!=1)
{
printf("EVP_SignUpdate err\n");
return -1;
}
ret=EVP_SignFinal(&md_ctx,out,(unsigned int *)&outl,pkey);
if(ret!=1)
{
printf("EVP_SignFinal err\n");
return -1;
}
/* 私钥加密 */
RSA_private_encrypt(inl,in,out,rkey,1);
/* 公钥解密 */
/* 公钥加密 */
/* 私钥解密 */
printf("all test ok.\n");
ENGINE_free(e);
ENGINE_finish(e);
return 0;
}
读者可以跟踪调试上述示例来研究各种细节。