快速模式第三包收尾之quick_inI2()
快速模式第三包收尾之quick_inI2()

文章目录
1. 序言
快速模式有三个报文交换,四个核心函数入口。我们已经对前三个函数处理流程对了一个简单的学习和这里,下面对第四个函数入口quick_inI2()的处理流程做一个简单的介绍。
首先需要说明的是快速模式的前两个报文是为了协商感兴趣流的相关参数(如使用的加密算法、认证算法、封装方式、感兴趣流以及生成相关的密钥信息等),而第三个报文则简单了很多:只是为了对前两个报文做认证。那么自然而然引出一个问题:为什么需要第三个报文呢?前两个报文不是已经包含HASH杂凑载荷吗? 供大家思考吧。
2. quick_inI2()处理流程图
quick_inI2()的处理流程很简单,其中最主要的便是建立出站IPsecSA。(如果IPsec处理流程都是这种精简的,该多好呀 )

3. 报文格式
quick_inR1_outI2()和quick_inI2()都是用来处理快速模式最后一个包的,报文格式完全一致。,quick_inR1_outI2()包括发送处理流程,而quick_inI2()则只为处理接收流程。

4. quick_inI2()源码
这个源码主要流程很清晰(除了建立IPsecSA),代码也很少。
/* Handle last message of Quick Mode.
* HDR*, HASH(3) -> done
* (see RFC 2409 "IKE" 5.5)
* Installs outbound IPsec SAs, routing, etc.
*/
stf_status
quick_inI2(struct msg_digest *md)
{
struct state *const st = md->st;
/* HASH(3) in *//*验证哈希报文完整性*/
CHECK_QUICK_HASH(md, quick_mode_hash3(hash_val, st)
, "HASH(3)", "Quick I2");
/* Tell the kernel to establish the outbound and routing part of the new SA
* (the previous state established inbound)
* (unless the commit bit is set -- which we don't support).
* We do this before any state updating so that
* failure won't look like success.
*/
if (!install_ipsec_sa(md->pst, st, FALSE))
return STF_INTERNAL_ERROR;
{
DBG(DBG_CONTROLMORE, DBG_log("inI2: instance %s[%ld], setting newest_ipsec_sa to #%ld (was #%ld) (spd.eroute=#%ld)"
, st->st_connection->name
, st->st_connection->instance_serial
, st->st_serialno
, st->st_connection->newest_ipsec_sa
, st->st_connection->spd.eroute_owner));
}
st->st_connection->newest_ipsec_sa = st->st_serialno;
update_iv(st); /* not actually used, but tidy */
/* note (presumed) success */
{
struct gw_info *gw = st->st_connection->gw_info;
if (gw != NULL)
gw->key->last_worked_time = now();
}
/* If we have dpd delay and dpdtimeout set, then we are doing DPD
on this conn, so initialize it */
if(st->st_connection->dpd_delay && st->st_connection->dpd_timeout) {
if(dpd_init(st) != STF_OK) {
delete_ipsec_sa(st, FALSE);
return STF_FAIL;
}
}
return STF_OK;
}
4. 其他接口说明
4.1 hash载荷计算方式
快速模式虽然仅有三个报文交互,但是它们的hash杂凑载荷的计算方式却不相同:
第①包计算方式:
H
A
S
H
(
1
)
=
P
R
F
(
S
K
E
Y
I
D
−
a
,
M
s
g
I
D
∣
S
A
∣
N
i
∣
[
∣
I
D
i
∣
I
D
r
]
)
HASH(1) = PRF(SKEYID-a, MsgID | SA | Ni | [| IDi | IDr ])
HASH(1)=PRF(SKEYID−a,MsgID∣SA∣Ni∣[∣IDi∣IDr])
第②包计算方式:
H
A
S
H
(
2
)
=
P
R
F
(
S
K
E
Y
I
D
−
a
,
M
s
g
I
D
∣
N
i
∣
S
A
∣
N
r
∣
[
∣
I
D
i
∣
I
D
r
]
)
HASH(2) = PRF(SKEYID-a, MsgID | Ni | SA | Nr | [| IDi | IDr ])
HASH(2)=PRF(SKEYID−a,MsgID∣Ni∣SA∣Nr∣[∣IDi∣IDr])
第③包计算方式:
H
A
S
H
(
3
)
=
P
R
F
(
S
K
E
Y
I
D
−
a
,
0
∣
M
s
g
I
D
∣
N
i
∣
N
r
)
HASH(3) = PRF(SKEYID-a, 0 | MsgID | Ni | Nr)
HASH(3)=PRF(SKEYID−a,0∣MsgID∣Ni∣Nr)
- 第①包实现方式和第②包实现方式为同一个函数:
/* Compute HASH(1), HASH(2) of Quick Mode.
* HASH(1) is part of Quick I1 message.
* HASH(2) is part of Quick R1 message.
* Used by: quick_outI1, quick_inI1_outR1 (twice), quick_inR1_outI2
* (see RFC 2409 "IKE" 5.5, pg. 18 or draft-ietf-ipsec-ike-01.txt 6.2 pg 25)
*/
size_t
quick_mode_hash12(u_char *dest, const u_char *start, const u_char *roof
, const struct state *st, const msgid_t *msgid, bool hash2)
{
struct hmac_ctx ctx;
hmac_init_chunk(&ctx, st->st_oakley.prf_hasher, st->st_skeyid_a);/*PRF算法 + 认证秘钥*/
hmac_update(&ctx, (const void *) msgid, sizeof(msgid_t));/*填充msgid,由于认证需要msgid,而它唯一*/
if (hash2)
hmac_update_chunk(&ctx, st->st_ni); /* include Ni_b in the hash */
hmac_update(&ctx, start, roof-start);/*数据起始位置和终止位置*/
hmac_final(dest, &ctx);
return ctx.hmac_digest_len;
}
- 第③包实现方式:
/* Compute HASH(3) in Quick Mode (part of Quick I2 message).
* Used by: quick_inR1_outI2, quick_inI2
* See RFC2409 "The Internet Key Exchange (IKE)" 5.5.
* NOTE: this hash (unlike HASH(1) and HASH(2)) ONLY covers the
* Message ID and Nonces. This is a mistake.
*/
static size_t
quick_mode_hash3(u_char *dest, struct state *st)/*第二阶段的三个报文hash值算法方式各不相同*/
{
struct hmac_ctx ctx;
hmac_init_chunk(&ctx, st->st_oakley.prf_hasher, st->st_skeyid_a);
hmac_update(&ctx, (const u_char *)"\0", 1);
hmac_update(&ctx, (u_char *) &st->st_msgid, sizeof(st->st_msgid));
hmac_update_chunk(&ctx, st->st_ni);
hmac_update_chunk(&ctx, st->st_nr);
hmac_final(dest, &ctx);
DBG_cond_dump(DBG_CRYPT, "HASH(3) computed:", dest, ctx.hmac_digest_len);
return ctx.hmac_digest_len;
}
4.2 install_ipsec_sa

5. 小结
IPsec协商流程之主模式+快速模式学习跨度比较久(3个月多),协商流程却是很复杂,而且只是看原理性知识,很多功能都没有敢去涉及,如证书认证、out_sa、 DPD、建立IPsecSA、NAT-T等等。学习期间最主要的体会是:openswan封装了很多很多接口,常用接口需要好好学习,否则在看代码时很困难。就拿out_sa 、out_struct、out_generic等系列,能恶心死人,全文基本都用这几个接口在封装报文和解封装报文,可以说这些基本函数是看openswan源码的接口。
后面计划继续更新几个函数接口实现,也是以前学习整理过程中遗留的坑,先填几个然后在更新学习其他流程。
快速模式第三包收尾之quick_inI2()的更多相关文章
- 快速模式第三包:quick_inR1_outI2()
快速模式第三包:quick_inR1_outI2() 文章目录 快速模式第三包:quick_inR1_outI2() 1. 序言 2. quick_inR1_outI2()的处理流程 3. 快速模式第 ...
- openswan中ISAKMP交互过程关键函数接口
1. ISAKMP交互过程中关键函数接口 下面分别说明不同的阶段和模式下的函数接口以及对应的报文. 2. 第一阶段(Phase I)主模式函数接口 发送端 响应端 main_outI1 主模式第一包 ...
- IPsec 9个包分析(主模式+快速模式)
第一阶段:ISAKMP协商阶段 1.1 第一包 包1:发起端协商SA,使用的是UDP协议,端口号是500,上层协议是ISAKMP,该协议提供的是一个框架,里面的负载Next payload类似模块,可 ...
- iPhone 6 被盗记录二【写在315前夕:苹果售后福州直信创邺在没有三包的情况下帮小偷翻新、助力小偷换机销赃!无视王法。让人震惊,痛心,憎恨!消费者很受伤很无奈】
投诉公司: 北京直信创邺数码科技有限公司 标题: 写在315前夕:苹果售后在没有三包的情况下帮小偷翻新.助力小偷换机销赃!无视王法.让人震惊,痛心,憎恨!消费者很受伤很无奈 期望: 还我手机,或者赔 ...
- Python自动化 【第十六篇】:JavaScript作用域和Dom收尾
本节内容: javascript作用域 DOM收尾 JavaScript作用域 JavaScript的作用域一直以来是前端开发中比较难以理解的知识点,对于JavaScript的作用域主要记住几句话,走 ...
- Java清除:收尾和垃圾收集
垃圾收收集器(GC)只知道释放由new关键字分配的内存,所以不知道如何释放对象的"特殊"内存.为了解决这个问题,Java提供了一个名为:finalize()的方法,可为我们的类定义 ...
- (八)java垃圾回收和收尾
垃圾回收机制:当一个对象不再被引用时,或者说当一个对象的引用不存在时,我们就认为该对象不再被需要,它所占用的内存就会被释放掉. 垃圾回收只是在程序执行过程中偶尔发生,java不同的运行时刻会产 ...
- python能够执行,但编译第三包遇到 python.h no such file or directory
python能够执行,但编译第三包遇到 python.h no such file or directory 这个问题是由于没有安装python-devel, 安装此包就能够解决次问题,在Linux下 ...
- 数据结构20:KMP算法(快速模式匹配算法)详解
通过上一节的介绍,学习了串的普通模式匹配算法,大体思路是:模式串从主串的第一个字符开始匹配,每匹配失败,主串中记录匹配进度的指针 i 都要进行 i-j+1 的回退操作(这个过程称为“指针回溯”),同时 ...
随机推荐
- HCNA Routing&Switching之GVRP
前文我们了解了不同vlan间路由相关话题,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/15110336.html,今天我们来聊一聊vlan动态注册相关话题: ...
- django有什么CMS比较好用?哪个好?
这个网站有目前在电子商务领域流行的django cms的横向对比表格,可以看看 https://djangopackages.org/grids/g/ecommerce/ 从结果上来看,django- ...
- python grequest模块使用备忘录
手里上有一批链接,需要检查他们是否已经被删除.本来是想用多线程的,但是考虑了下一个是实现起来稍繁琐.而且性能不理想,单机基本超过10线程基本上就没有太多增益了. 所以考虑了下,还是决定用异步IO. 在 ...
- Java异常02——自定义异常
Error与Exception与自定义异常 Error与Exception Error Exception 自定义异常 快捷键: ctrl + alt + t package exception.d ...
- Python3中dict字典的相关操作函数
字典对象的内建函数 1. clear() 清空字典. 例: >>> a = {1:3, 2:4} >>> a.clear() >>> a {} 2 ...
- 浅谈 SQL 注入(注入篇)
一.SQL注入简介 1.1 什么是SQL注入 在用户可控制的参数上过滤不严或没有任何限制,使得用户将传入的参数(如URL,表单,http header)与SQL语句合并构成一条 SQL语句传递给web ...
- HDFS 09 - HDFS NameNode 的高可用机制
目录 1 - 为什么要高可用 2 - NameNode 的高可用发展史 3 - HDFS 的高可用架构 3.1 Standby 和 Active 的命名空间保持一致 3.2 同一时刻只有一个 Acti ...
- Mysql的分区表
概论: 分区表一般用作Mysql库表的水平切割(也就是常说的mysql性能优化的几种通用手法"读写分离.分库分表"中的一种),适用于单表的数据量可能很大的场景.因为分区表可以将一个 ...
- 题解 u
传送门 这里AC解法因为手残 tag2[min(r+l, n+1)][min(c+l+1, n+1)]+=s; 写成 tag2[min(r+l, n+1)][c+l+1]+=s; 惨遭RE,以后注意查 ...
- docker部署Redis6-0-6
下载redis.conf配置 下载地址: http://download.redis.io/redis-stable/redis.conf 拉取docker镜像 docker pull redis:6 ...