Правильная реализация механизма OpenSSL RSA: вопросы о rsa_meth_st

Обзор

У меня есть несколько конкретных вопросов, касающихся реализации rsa_meth_st (также известного как RSA_METHOD) в openSSL, однако я также обычно не понимаю, где именно мой движок «зацеплен» (или должен быть) пользователем при выполнении стандартных операций 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 использовала функцию «модульного возведения в степень» моего движка без необходимости переписывать семейство функций RSA_[public|private]_[encrypt|decrypt] из /include/openssl/rsa.h?
  2. Если да, то достаточно ли реализовать только функцию rsa_mod_exp? Или я должен также реализовать функции public_enc/dec и private_enc/dec? Я спрашиваю, потому что исходный код старого движка Intel 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, мне НЕ нужно реализовывать rsa_pub_enc/dec и другие? Думаю, я просто не понимаю, в какой момент процесса шифрования/дешифрования RSA должен запускаться мой движок.

Любые слова мудрости будут очень признательны.


person Brett    schedule 23.08.2017    source источник


Ответы (1)


Отказ от ответственности Я никогда не писал модуль/движок Openssl, но сейчас я изучаю RSA-код OpenSSL.

  1. Я думаю, что вы не должны переписывать семейство функций RSA_[public|private]_[encrypt|decrypt]. Я бы попытался сделать модифицированную версию структуры rsa_pkcs1_ossl_meth в файле крипто/rsa/rsa_ossl.c
  2. Нашел где грузятся методы движка. Он находится в crypto/rsa/rsa_lib.c в функции RSA_new_method, где вызывается ENGINE_get_RSA(ret->engine). Инициируйте свой engine->rsa_meth указателем на RSA_METHOD strcut, похожий на rsa_pkcs1_ossl_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.

person fusiled    schedule 10.09.2017