主模式第五包:main_inR2_outI3
文章目录
1. 序言
main_inR2_outI3()
函数是ISAKMP协商过程中第五包的核心处理函数的入口,发起端通过此包收到相应端的KE值和Nonce值收到,可以生成需要的密钥信息。这里我们主要说明main_inR2_outI3
的函数调用关系、处理流程以及对源码的注释分析,关于main_inR2_outI3
的上下文环境暂不叙述,留给后面的文章进行更新。
ISAKMP协商报文的处理流程都比较复杂,此函数在协商的报文处理函数中比较复杂的,因此个人学习期间难免有遗漏和理解错误的地方,请大家多多批评指正。
对于源码的学习,我并没有把每一行进行备注,而是将自己认为的关键点做了注释或者标注。
目前主要是整理源码中的处理里流程和实现逻辑,尚未深入比较细节的处理;后续在我整理完毕使用主模式协商的9个报文后,我再次结合代码整理每一个报文的详细流程,到时把每一个报文的注意事项、作用,处理方式做一个整体上的把握。同时结合书本上的描述来解释代码层的实现。
2.函数调用关系
这里暂时给出xmind整理的思维导图。
3. 第五个报文流程图
第五个报文的处理流程主要分为三个大功能:
- 解析收到的对端报文
- 密钥交换载荷KE
- Nonce载荷
- 使用DH算法制作加密密钥、认证密钥、哈希密钥等
- 构造应答报文(第五个报文)
- 签名
- 报文加密
4. main_inR2_outI3()源码学习
该函数主要的功能是:
- 解析对端的KE载荷和Nonce,因为这是制作密钥的基础材料。
- 解析完毕后,开始制作密钥。
stf_status
main_inR2_outI3(struct msg_digest *md)
{
struct dh_continuation *dh;
/*获取受到的第四个报文中的KE载荷*/
pb_stream *const keyex_pbs = &md->chain[ISAKMP_NEXT_KE]->pbs;
struct state *const st = md->st;
/* if we are already processing a packet on this st, we will be unable
* to start another crypto operation below */
if (is_suspended(st)) {
openswan_log("%s: already processing a suspended cyrpto operation "
"on this SA, duplicate will be dropped.", __func__);
return STF_TOOMUCHCRYPTO;
}
/* KE in *//*解析KE载荷并存储在st->st_gr上*/
RETURN_STF_FAILURE(accept_KE(&st->st_gr, "Gr"
, st->st_oakley.group, keyex_pbs));
/* Nr in *//*解析Nonce载荷,并存储在st->st_nr*/
RETURN_STF_FAILURE(accept_v1_nonce(md, &st->st_nr, "Nr"));
dh = alloc_thing(struct dh_continuation, "aggr outR1 DH");
if(!dh) {
return STF_FATAL; }
dh->md = md;
set_suspended(st, md);/*挂起当前报文,防止由于耗时操作重新收到对方的重发报文*/
pcrc_init(&dh->dh_pcrc);
dh->dh_pcrc.pcrc_func = main_inR2_outI3_cryptotail;
return start_dh_secretiv(&dh->dh_pcrc, st
, st->st_import
, INITIATOR
, st->st_oakley.group->group);
}
5. start_dh_secretiv()源码学习
该函数的主要功能:
- 获取协商的认证算法、哈希算法、oakley群信息
- 准备Nonce、KE、cookie、st_sec_chunk(密钥信息?)
- 制作密钥(该流程中会通过回调函数组装报文并发送)
- 发送完毕报文的后续处理
/*
* invoke helper to do DH work.
*/
stf_status start_dh_secretiv(struct pluto_crypto_req_cont *cn
, struct state *st
, enum crypto_importance importance
, enum phase1_role init /* TRUE=g_init,FALSE=g_r */
, u_int16_t oakley_group2)
{
struct pluto_crypto_req r;
struct pcr_skeyid_q *dhq;
const chunk_t *pss = get_preshared_secret(st->st_connection);/*获取预共享秘钥*/
err_t e;
bool toomuch = FALSE;
pcr_init(&r, pcr_compute_dh_iv, importance);/*使用DH算法生成三把秘钥*/
dhq = &r.pcr_d.dhq;
passert(st->st_sec_in_use);
/* convert appropriate data to dhq */
dhq->auth = st->