int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx,
const EVP_CIPHER *cipher, ENGINE *impl,
const unsigned char *key,
const unsigned char *iv, int enc)
此初始化方法的实现在evp_enc.c中,此方法中分配了秘钥的内存。 ctx->cipher_data = OPENSSL_zalloc(ctx->cipher->ctx_size);
在初始化方法中进行了加密模式的判断,判断是ECB,CBC,GCM等模式,方法为EVP_CIPHER_CTX_mode(ctx)
最后调用到cipher.init方法
实现是e_aes.c中的aes_init_key方法,在这个方法中将刚才分配的cipher_data强转成 EVP_AES_KEY.
EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
现在这个key还是空的,解下来要给他赋值.
ret = AES_set_decrypt_key(key,
EVP_CIPHER_CTX_key_length(ctx) * 8,
&dat->ks.ks);
dat->block = (block128_f) AES_decrypt;
dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
(cbc128_f) AES_cbc_encrypt : NULL;
AES_set_decrypt_key 此方法中生成了轮密钥。
此方法是在aes_core.c中定义的,想了解轮密钥的生成,可以研究下这个方法
接着刚才的代码,发现设置了两个函数指针。应该就是就是具体的解密算法了。
dat->block = (block128_f) AES_decrypt;
dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
(cbc128_f) AES_cbc_encrypt : NULL;
这样初始化就完成了。
加解密数据
int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
const unsigned char *in, int inl)
此方法定义在evp_enc.c中,定义如下
int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl,
const unsigned char *in, int inl)
{
if (ctx->encrypt)
return EVP_EncryptUpdate(ctx, out, outl, in, inl);
else
return EVP_DecryptUpdate(ctx, out, outl, in, inl);
}
由于这里是解密,进入解密方法,解密方法有调用到下面这个方法
static int evp_EncryptDecryptUpdate(EVP_CIPHER_CTX *ctx,
unsigned char *out, int *outl,
const unsigned char *in, int inl)
此方法中调用cipher.do_cipher,进入到e_aes.c的下面这个方法
static int aes_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
if (dat->stream.cbc)
(*dat->stream.cbc) (in, out, len, &dat->ks,
EVP_CIPHER_CTX_iv_noconst(ctx),
EVP_CIPHER_CTX_encrypting(ctx));
else if (EVP_CIPHER_CTX_encrypting(ctx))
CRYPTO_cbc128_encrypt(in, out, len, &dat->ks,
EVP_CIPHER_CTX_iv_noconst(ctx), dat->block);
else
CRYPTO_cbc128_decrypt(in, out, len, &dat->ks,
EVP_CIPHER_CTX_iv_noconst(ctx), dat->block);
return 1;
}
上面方法走到了dat->stream.cbc方法中,这个方法最终的定义是在aes_cbc.c,这个也是初始化的时候函数指针的指向。
void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
size_t len, const AES_KEY *key,
unsigned char *ivec, const int enc)
{
if (enc)
CRYPTO_cbc128_encrypt(in, out, len, key, ivec,
(block128_f) AES_encrypt);
else
CRYPTO_cbc128_decrypt(in, out, len, key, ivec,
(block128_f) AES_decrypt);
}
由于是解密进入下面方法CRYPTO_cbc128_decrypt,此方法定义在cbc_128.c中
void CRYPTO_cbc128_decrypt(const unsigned char *in, unsigned char *out,
size_t len, const void *key,
unsigned char ivec[16], block128_f block)
这里应该是对cbc_128的通用处理,最终的处理还是在最后一个参数的函数指针AES_decrypt。
AES_decrypt定义在aes_core.c中
void AES_decrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key)
int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
{
if (ctx->encrypt)
return EVP_EncryptFinal(ctx, out, outl);
else
return EVP_DecryptFinal(ctx, out, outl);
}
调用到
int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
在EVP_DecryptFinal_ex这个方法里面没有看到解密的过程,只是一个赋值,把cipherUpdate处理的时缓存到ctx中的final数据拷贝到输出缓存区中就完事了。
n = ctx->cipher->block_size - n;
for (i = 0; i < n; i++)
out[i] = ctx->final[i];
*outl = n;