流程
openssl中使用了大量的宏导致方法很难找到,故此分析整理。
获取cipher
- EVP_CIPHER *cipher= EVP_des_ecb();
- EVP_des_ecb的声明在e_des.c中
BLOCK_CIPHER_defs(des, EVP_DES_KEY, NID_des, 8, 8, 8, 64,
EVP_CIPH_RAND_KEY, des_init_key, NULL,
EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, des_ctrl)
BLOCK_CIPHER_def_cfb(des, EVP_DES_KEY, NID_des, 8, 8, 1,
EVP_CIPH_RAND_KEY, des_init_key, NULL,
EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, des_ctrl)
BLOCK_CIPHER_def_cfb(des, EVP_DES_KEY, NID_des, 8, 8, 8,
EVP_CIPH_RAND_KEY, des_init_key, NULL,
EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, des_ctrl)
- evp.h有宏定义BLOCK_CIPHER_defs
#define BLOCK_CIPHER_defs(cname, kstruct, \
nid, block_size, key_len, iv_len, cbits, flags, \
init_key, cleanup, set_asn1, get_asn1, ctrl) \
BLOCK_CIPHER_def_cbc(cname, kstruct, nid, block_size, key_len, iv_len, flags, \
init_key, cleanup, set_asn1, get_asn1, ctrl) \
BLOCK_CIPHER_def_cfb(cname, kstruct, nid, key_len, iv_len, cbits, \
flags, init_key, cleanup, set_asn1, get_asn1, ctrl) \
BLOCK_CIPHER_def_ofb(cname, kstruct, nid, key_len, iv_len, cbits, \
flags, init_key, cleanup, set_asn1, get_asn1, ctrl) \
BLOCK_CIPHER_def_ecb(cname, kstruct, nid, block_size, key_len, flags, \
init_key, cleanup, set_asn1, get_asn1, ctrl)
/*-
#define BLOCK_CIPHER_defs(cname, kstruct, \
nid, block_size, key_len, iv_len, flags,\
init_key, cleanup, set_asn1, get_asn1, ctrl)\
static const EVP_CIPHER cname##_cbc = {\
nid##_cbc, block_size, key_len, iv_len, \
flags | EVP_CIPH_CBC_MODE,\
init_key,\
cname##_cbc_cipher,\
cleanup,\
sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+\
sizeof((((EVP_CIPHER_CTX *)NULL)->c.kstruct)),\
set_asn1, get_asn1,\
ctrl, \
NULL \
};\
const EVP_CIPHER *EVP_##cname##_cbc(void) { return &cname##_cbc; }\
static const EVP_CIPHER cname##_cfb = {\
nid##_cfb64, 1, key_len, iv_len, \
flags | EVP_CIPH_CFB_MODE,\
init_key,\
cname##_cfb_cipher,\
cleanup,\
sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+\
sizeof((((EVP_CIPHER_CTX *)NULL)->c.kstruct)),\
set_asn1, get_asn1,\
ctrl,\
NULL \
};\
const EVP_CIPHER *EVP_##cname##_cfb(void) { return &cname##_cfb; }\
static const EVP_CIPHER cname##_ofb = {\
nid##_ofb64, 1, key_len, iv_len, \
flags | EVP_CIPH_OFB_MODE,\
init_key,\
cname##_ofb_cipher,\
cleanup,\
sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+\
sizeof((((EVP_CIPHER_CTX *)NULL)->c.kstruct)),\
set_asn1, get_asn1,\
ctrl,\
NULL \
};\
const EVP_CIPHER *EVP_##cname##_ofb(void) { return &cname##_ofb; }\
static const EVP_CIPHER cname##_ecb = {\
nid##_ecb, block_size, key_len, iv_len, \
flags | EVP_CIPH_ECB_MODE,\
init_key,\
cname##_ecb_cipher,\
cleanup,\
sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+\
sizeof((((EVP_CIPHER_CTX *)NULL)->c.kstruct)),\
set_asn1, get_asn1,\
ctrl,\
NULL \
};\
const EVP_CIPHER *EVP_##cname##_ecb(void) { return &cname##_ecb; }
*/
初始化
我们以上面的des_ecb为例,初始化方法是des_init_key,do_cipher对应des_ecb_cipher
const EVP_CIPHER *EVP_##cname##_ofb(void) { return &cname##_ofb; }\
static const EVP_CIPHER cname##_ecb = {\
nid##_ecb, block_size, key_len, iv_len, \
flags | EVP_CIPH_ECB_MODE,\
init_key,\
cname##_ecb_cipher,\
cleanup,\
sizeof(EVP_CIPHER_CTX)-sizeof((((EVP_CIPHER_CTX *)NULL)->c))+\
sizeof((((EVP_CIPHER_CTX *)NULL)->c.kstruct)),\
set_asn1, get_asn1,\
ctrl,\
NULL \
};\
const EVP_CIPHER *EVP_##cname##_ecb(void) { return &cname##_ecb; }
- 初始化实现在evp_enc.c中,主要是给ctx赋值,分配空间,将cipher相关信息赋值给ctx,然后调用cihper的init方法
这里的init是上面宏定义中定义的des_init_key方法,在e_des.c中有实现
EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
const unsigned char *key, const unsigned char *iv,
int enc)
加密解密update
- 此方法定义在evp_enc.c中,这个方法最终会调用do_cipher方法,如果是ecb模式实际调用des_ecb_cipher
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);
}
- 在do_cipher是循环处理
static int des_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t inl)
{
BLOCK_CIPHER_ecb_loop()
DES_ecb_encrypt((DES_cblock *)(in + i), (DES_cblock *)(out + i),
EVP_CIPHER_CTX_get_cipher_data(ctx),
EVP_CIPHER_CTX_encrypting(ctx));
return 1;
}
- DES_ecb_encrypt此方法在ecb_enc.c中实现
void DES_ecb_encrypt(const_DES_cblock *input, DES_cblock *output,
DES_key_schedule *ks, int enc)
{
register DES_LONG l;
DES_LONG ll[2];
const unsigned char *in = &(*input)[0];
unsigned char *out = &(*output)[0];
c2l(in, l);
ll[0] = l;
c2l(in, l);
ll[1] = l;
DES_encrypt1(ll, ks, enc);
l = ll[0];
l2c(l, out);
l = ll[1];
l2c(l, out);
l = ll[0] = ll[1] = 0;
}
- 再调用DES_encrypt1,此方法在des_enc.c中,这里面才是最终的des算法的实现
doFinal
- 此方法在evp_enc.c中,此方法实际还是调用的do_cipher方法,只是需要处理缓冲区剩余的数据,剩余几个,给没有数据的位置填几,然后调用do_cipher
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_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
{
int n, ret;
unsigned int i, b, bl;
/* Prevent accidental use of decryption context when encrypting */
if (!ctx->encrypt) {
EVPerr(EVP_F_EVP_ENCRYPTFINAL_EX, EVP_R_INVALID_OPERATION);
return 0;
}
if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) {
ret = ctx->cipher->do_cipher(ctx, out, NULL, 0);
if (ret < 0)
return 0;
else
*outl = ret;
return 1;
}
b = ctx->cipher->block_size;
OPENSSL_assert(b <= sizeof(ctx->buf));
if (b == 1) {
*outl = 0;
return 1;
}
bl = ctx->buf_len;
if (ctx->flags & EVP_CIPH_NO_PADDING) {
if (bl) {
EVPerr(EVP_F_EVP_ENCRYPTFINAL_EX,
EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH);
return 0;
}
*outl = 0;
return 1;
}
n = b - bl;
for (i = bl; i < b; i++)
ctx->buf[i] = n; //剩几个位没有数据,就填几
ret = ctx->cipher->do_cipher(ctx, out, ctx->buf, b);
if (ret)
*outl = b;
return ret;
}