当前位置: 首页 > 工具软件 > strongSwan > 使用案例 >

strongswan对称算法plugin

爱花蜂
2023-12-01

面向对象-父类

strongswan/src/libstrongswan/crypto/crypters/crypter.ccrypters/crypter.h里将对称算法接口抽象封装成了一个父类struct crypter_t, crypter_t结构体里成员函数都是对称算法运算相关的具体实现函数。

struct crypter_t {
    bool (*encrypt)(crypter_t *this, chunk_t data, chunk_t iv,
                    chunk_t *encrypted) __attribute__((warn_unused_result));
    bool (*decrypt)(crypter_t *this, chunk_t data, chunk_t iv,
                    chunk_t *decrypted) __attribute__((warn_unused_result));
    size_t (*get_block_size)(crypter_t *this);
    size_t (*get_iv_size)(crypter_t *this);
    size_t (*get_key_size)(crypter_t *this);
    bool (*set_key)(crypter_t *this,
                    chunk_t key) __attribute__((warn_unused_result));
    void (*destroy)(crypter_t *this);
 };

面向对象-子类

private_aes_crypter_t作为子类继承了父类crypter_t

strongswanAES对称算法软算法实现:

# ls strongswan/src/libstrongswan/plugins/aes
aes_crypter.c  aes_crypter.h  aes_plugin.c  aes_plugin.h  Makefile.am

Makefile.am会把plugins/aes/目录下根据libstrongswan-aes.la生成库文件。

struct private_aes_crypter_t {
    aes_crypter_t public;  /* struct aes_crypter_t里只有一个成员crypter_t crypter; */
    uint32_t aes_Nkey;
    uint32_t aes_Nrnd;
    uint32_t aes_e_key[AES_KS_LENGTH];
    uint32_t aes_d_key[AES_KS_LENGTH];
    uint32_t key_size;
    bool has_iv;
};

aes_crypter.c里的加密和解密的软算法实现函数如下:

static void encrypt_block(const private_aes_crypter_t *this,
                          const unsigned char in_blk[], unsigned char out_blk[]);
static void decrypt_block(const private_aes_crypter_t *this,
                          const unsigned char in_blk[], unsigned char out_blk[]);

用METHOD对private_aes_crypter_t里成员函数指针如encrypt,decrypt,set_key, set_iv等的实现函数进行声明和定义,METHOD声明的函数具体为_encrypt, _decrypt,_get_block_size,_get_iv_size,_get_key_size,_set_key,_destroy。

aes_crypter_create主要完成算法实例对象的初始化

    INIT(this,
        .public = {
            .crypter = {
                .encrypt = _encrypt,
                .decrypt = _decrypt,
                .get_block_size = _get_block_size,
                .get_iv_size = _get_iv_size,
                .get_key_size = _get_key_size,
                .set_key = _set_key,
                .destroy = _destroy,
            },
        },
        .key_size = key_size,
        .aes_Nkey = key_size / 4,
        .has_iv = has_iv,
    );

插件PLUGIN

find_plugin 根据libstrongswan-aes.so文件名查找插件并load_plugin,在load_plugin里先create_plugin,如果找不到会先dlopen再create_plugin。

/**
 * Tries to find the plugin with the given name in the given path.
 */
static bool find_plugin(char *path, char *name, char *buf, char **file)
{
        struct stat stb;

        if (path && snprintf(buf, PATH_MAX, "%s/libstrongswan-%s.so",
                                                 path, name) < PATH_MAX)
        {
                if (stat(buf, &stb) == 0)
                {
                        *file = buf;
                        return TRUE;
                }
        }
        return FALSE;
}

plugin里plugin_featureaes_crypter_create绑定上了关系

        static plugin_feature_t f[] = {
                PLUGIN_REGISTER(CRYPTER, aes_crypter_create),
                        PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CBC, 16),
                        PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CBC, 24),
                        PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CBC, 32),
                        PLUGIN_PROVIDE(CRYPTER, ENCR_AES_ECB, 16),
                        PLUGIN_PROVIDE(CRYPTER, ENCR_AES_ECB, 24),
                        PLUGIN_PROVIDE(CRYPTER, ENCR_AES_ECB, 32),
        };

libstrongswan库初始化算法和加载插件

strongswan/libstrongswan/library.c里面bool library_init(char *settings, const char *namespace);函数中有段代码段如下:

this->public.crypto = crypto_factory_create();
this->public.plugins = plugin_loader_create();

算法使用

以libipsec/esp_context.c里对密码算法的调用为例

/**
 * Create AEAD wrapper around traditional encryption/integrity algorithms
 */
static bool create_traditional(private_esp_context_t *this, int enc_alg,
                                                           chunk_t enc_key, int int_alg, chunk_t int_key)
{
        crypter_t *crypter = NULL;
        signer_t *signer = NULL;
        iv_gen_t *ivg;

        switch (enc_alg)
        {
                case ENCR_AES_CTR:
                case ENCR_CAMELLIA_CTR:
                        /* the key includes a 4 byte salt */
                        crypter = lib->crypto->create_crypter(lib->crypto, enc_alg,
                                                                                                  enc_key.len - 4);
                        break;
                default:
                        crypter = lib->crypto->create_crypter(lib->crypto, enc_alg,
                                                                                                  enc_key.len);
                        break;
        }
        if (!crypter)
        {
                DBG1(DBG_ESP, "failed to create ESP context: unsupported encryption "
                         "algorithm %N", encryption_algorithm_names, enc_alg);
                goto failed;
        }
        if (!crypter->set_key(crypter, enc_key))
        {
                DBG1(DBG_ESP, "failed to create ESP context: setting encryption key "
                         "failed");
                goto failed;
        }

        signer = lib->crypto->create_signer(lib->crypto, int_alg);
        if (!signer)
        {
                DBG1(DBG_ESP, "failed to create ESP context: unsupported integrity "
                         "algorithm %N", integrity_algorithm_names, int_alg);
                goto failed;
        }
        if (!signer->set_key(signer, int_key))
        {
                DBG1(DBG_ESP, "failed to create ESP context: setting signature key "
                         "failed");
                goto failed;
        }
        ivg = iv_gen_create_for_alg(enc_alg);
        if (!ivg)
        {
                DBG1(DBG_ESP, "failed to create ESP context: creating iv gen failed");
                goto failed;
        }
        this->aead = aead_create(crypter, signer, ivg);
        return TRUE;

failed:
        DESTROY_IF(crypter);
        DESTROY_IF(signer);
        return FALSE;
}

其中crypter_t *crypter为算法实例或者对象,最后this->aead = aead_create(crypter, signer, ivg);集成到aead。

在libipsec/esp_packet.c里,ESP数据包的实例初始化为:

static private_esp_packet_t *esp_packet_create_internal(packet_t *packet)
{
        private_esp_packet_t *this;

        INIT(this,
                .public = {
                        .packet = {
                                .set_source = _set_source,
                                .get_source = _get_source,
                                .set_destination = _set_destination,
                                .get_destination = _get_destination,
                                .get_data = _get_data,
                                .set_data = _set_data,
                                .get_dscp = _get_dscp,
                                .set_dscp = _set_dscp,
                                .get_metadata = _get_metadata,
                                .set_metadata = _set_metadata,
                                .skip_bytes = _skip_bytes,
                                .clone = _clone_,
                                .destroy = _destroy,
                        },
                        .get_source = _get_source,
                        .get_destination = _get_destination,
                        .get_next_header = _get_next_header,
                        .parse_header = _parse_header,
                        .decrypt = _decrypt,
                        .encrypt = _encrypt,
                        .get_payload = _get_payload,
                        .extract_payload = _extract_payload,
                        .destroy = _destroy,
                },
                .packet = packet,
                .next_header = IPPROTO_NONE,
        );
        return this;
}

代码段中涉及到的加解密接口为

                        .decrypt = _decrypt,
                        .encrypt = _encrypt,

以_encrypt为例

METHOD(esp_packet_t, encrypt, status_t,
        private_esp_packet_t *this, esp_context_t *esp_context, uint32_t spi)
{
        ......
        /* encrypt/authenticate the content inline */
        if (!aead->encrypt(aead, ciphertext, aad, iv, NULL))
        {
                DBG1(DBG_ESP, "ESP encryption or ICV generation failed");
                writer->destroy(writer);
                return FAILED;
        }
        ......
}

以上就是一系列的嵌套过程,这样面向对象模块化的设计可以让用户忽略不必过分关心的细节,这也是面向对象的好处,而且模块化让代码结构更加低耦合高内聚。

 类似资料: