OpenSSL RSA引擎的正确实现:关于rsa_meth_st的问题



概述

关于在 openSSL 中实现rsa_meth_st(又名 RSA_METHOD(,我有几个具体的问题,但是在执行标准 RSA 操作时,我也通常对我的引擎被用户"钩住"的确切位置感到困惑。

背景

我正在尝试为自定义 RSA 硬件加速器开发一个引擎,并且对RSA_METHOD结构实现有几个问题。

一些上下文:对于加密,我的加速器将基数、公共指数和模数作为输入,并返回生成的密文。对于解密,它以基数和模数作为输入。它不需要私钥,因为它存储在硬件中,并且只能通过带外通道进行配置。我已经有一个内核模块,它向用户空间程序公开一个 API 以使用加速器。现在我只需要将其集成到openSSL中。

我已经为 AES 和 SHA256 创建了一个类似的引擎,但是我在 RSA 方面苦苦挣扎。理想情况下,除了对预先填充和准备好的数据块执行模块化幂运算之外,我不想担心任何事情。对于 SHA 和 AES,这很简单:所有事情都由 EVP 接口处理,所以我需要担心的只是将数据传入和传出加速器。但对于 RSA 来说,这似乎并不那么简单(如果我错了,请纠正我(。

我的具体问题

我对引擎需要实现哪些RSA_METHOD函数指针感到困惑。 我展示下面的结构以供参考:

struct rsa_meth_st {
char *name;
int (*rsa_pub_enc) (int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
int (*rsa_pub_dec) (int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
int (*rsa_priv_enc) (int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
int (*rsa_priv_dec) (int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
int (*rsa_mod_exp) (BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx);
int (*bn_mod_exp) (BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
/* ....stuff.... */
int flags;
/* .... stuff ... */
};  // TYPEDEF'ED TO RSA_METHOD in include/ossl_typ.h

所以,三个问题:

  1. 标准的OpenSSL RSA实现是否可以使用我的引擎的"模块化幂"函数,而不必从/include/openssl/rsa.h重写RSA_[public|private]_[encrypt|decrypt]系列函数?
  2. 如果是这样,仅实现rsa_mod_exp功能是否足够?还是我必须同时实现 public_enc/dec 和 private_enc/dec 函数?我问,因为旧英特尔 RSAX 引擎的源代码是这样做的,但我无法弄清楚在"RSA 流"中如何以及何时调用引擎的功能。

在/include/openssl/rsa.h 中,我看到了以下用于 RSA_METHOD 标志字段的宏(第 61 行(:

/*
* This flag means the private key operations will be handled by rsa_mod_exp
* and that they do not depend on the private key components being present:
* for example a key stored in external hardware. Without this flag
* bn_mod_exp gets called when private key components are absent.
*/
# define RSA_FLAG_EXT_PKEY               0x0020
  1. 这是否意味着如果我在RSA_METHOD的"flags"字段中使用此标志,则不需要实现rsa_pub_enc/dec和朋友?我想我只是对应该在 RSA 加密/解密过程中的哪个点调用我的引擎感到困惑。

任何智慧的话将不胜感激。

免责声明我从来没有写过Openssl模块/引擎,但是这些天我正在研究OpenSSL的RSA代码。

  1. 我认为您一定不能重写RSA_[public|private]_[encrypt|decrypt]函数系列。我会尝试在文件crypto/rsa/rsa_ossl.c中制作结构rsa_pkcs1_ossl_meth的修改版本
  2. 我找到了引擎方法的加载位置。它在 crypto/rsa/rsa_lib.c 的函数RSA_new_method中调用ENGINE_get_RSA(ret->engine)。使用指向类似于rsa_pkcs1_ossl_methRSA_METHOD条形的指针初始化您的engine->rsa_meth
  3. 我不知道如何使用RSA_FLAG_EXT_PKEY标志,但它在 crypto/rsa/rsa_ossl.c 中使用,就像它在/include/openssl/rsa.h中所说的那样

恕我直言,我只会修改rsa_pkcs1_ossl_meth的几个属性来创建您的RSA_METHOD结构ENGINE

static RSA_METHOD rsa_pkcs1_ossl_meth = {
"my_RSA",
rsa_ossl_public_encrypt,
rsa_ossl_public_decrypt,     /* signature verification */
rsa_ossl_private_encrypt,    /* signing */
rsa_ossl_private_decrypt,
my_mod_exp,                  //<------- YOUR mod_exp_function
NULL,
rsa_ossl_init,
rsa_ossl_finish,
RSA_FLAG_FIPS_METHOD | RSA_FLAG_EXT_PKEY,       //<--- flags
// RSA_FLAG_EXT_PKEY tells to use hardware */
NULL,
0,                          /* rsa_sign */
0,                          /* rsa_verify */
NULL                        /* rsa_keygen */
};

通过这种方式,您可以重用默认OpenSSL引擎的代码,只需要实现my_mod_exp并设置RSA_FLAG_EXT_PKEY即可。

最新更新