strongswan/src/libstrongswan/crypto/crypters/crypter.c
和crypters/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
strongswan里AES对称算法软算法实现:
# 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,
);
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_feature
与aes_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),
};
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;
}
......
}
以上就是一系列的嵌套过程,这样面向对象模块化的设计可以让用户忽略不必过分关心的细节,这也是面向对象的好处,而且模块化让代码结构更加低耦合高内聚。