快速模式第三包:quick_inR1_outI2()
文章目录
1. 序言
在上一篇中博客中长话短说了第二包的处理流程,前两个报文的交互是快速模式的关键交互,用来协商会话参数(加解密算法、会话秘钥等),而第三包则是对前两个报文的认证,流程上简单了很多 。quick_inR1_outI2()
处理流程实现的功能如下:
- 解析SA载荷(对端选择的加解密算法信息)、KE载荷(pfs)、Nonce载荷。
- 构造第三个报文
- 生成密钥生成材料keymats
- 建立完整的IPsec SA
- 发起端建立的为完整IPSec SA,包括入SA和出SA,响应端有所不同。
- 启动DPD检测
2. quick_inR1_outI2()的处理流程
第三个报文的完整处理流程如下:
3. 快速模式第③包报文格式
该报文中的杂凑载荷是对前面交换的认证。第③包仅有ISAKMP头部和杂凑载荷构成,杂凑载荷的消息摘要是以一个0字节的MsgID、去掉载荷头的发起者Nonce以及去掉了载荷头的响应者Nonce为输入参数生成的,计算公式如下:
H A S H ( 3 ) = P R F ( S K E Y − a , 0 ∣ M s g I D ∣ N i b ∣ N r b ) HASH(3) = PRF(SKEY-a, 0|MsgID|Ni_b|Nr_b) HASH(3)=PRF(SKEY−a,0∣MsgID∣Nib∣Nrb)
4. quick_inR1_outI2()源码分析
接口quick_inR1_outI2()
的主要功能如下:
- 验证报文的完整性
- 解析响应端选择的SA载荷
- 加解密算法(ESP协议、AH协议,…)
- 认证算法
- 封装模式(隧道模式 ?传输模式)
- 解析Nonce载荷
- 如果启用PFS
- 解析KE载荷
- 再次计算DH交换值
stf_status
quick_inR1_outI2(struct msg_digest *md)
{
struct state *const st = md->st;
/* HASH(2) in *//*验证报文的哈希载荷*/
CHECK_QUICK_HASH(md
, quick_mode_hash12(hash_val, hash_pbs->roof, md->message_pbs.roof
, st, &st->st_msgid, TRUE)
, "HASH(2)", "Quick R1");
/* SA in */
{
struct payload_digest *const sa_pd = md->chain[ISAKMP_NEXT_SA];
/*解析对端选择的SA载荷*/
RETURN_STF_FAILURE(parse_ipsec_sa_body(&sa_pd->pbs
, &sa_pd->payload.sa, NULL, TRUE, st));
}
/* Nr in *//*解析对端Nonce载荷*/
RETURN_STF_FAILURE(accept_v1_nonce(md, &st->st_nr, "Nr"));
/* [ KE ] in (for PFS) *//*根据配置策略解析对端KE载荷*/
RETURN_STF_FAILURE(accept_PFS_KE(md, &st->st_gr, "Gr", "Quick Mode R1"));
if(st->st_pfs_group) {
/*如果支持PFS功能,则需要进行DH算法计算*/
struct dh_continuation *dh = alloc_thing(struct dh_continuation
, "quick outI2 DH");
/* set up DH calculation */
dh->md = md;
passert(st != NULL);
set_suspended(st, md);
pcrc_init(&dh->dh_pcrc);
dh->dh_pcrc.pcrc_func = quick_inR1_outI2_continue;
return start_dh_secret(&dh->dh_pcrc, st
, st->st_import
, INITIATOR
, st->st_pfs_group->group);
} else {
/* just call the tail function */
struct dh_continuation dh;
dh.md=md;
return quick_inR1_outI2_cryptotail(&dh, NULL);
}
}
4. quick_inR1_outI2_cryptotail()源码分析
接口quick_inR1_outI2_cryptotail()
的主要功能如下:
-
检验ID载荷收发是否一致
这里是通过ID载荷来协商IPSec隧道的保护子网信息
-
NAT-T相关处理
-
构造应答报文
-
计算keymats值
-
建立IPSecSA
-
初始化本隧道的DPD定时器
stf_status
quick_inR1_outI2_cryptotail(struct dh_continuation *dh
, struct pluto_crypto_req *r)