快速模式第三包收尾之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 的回退操作(这个过程称为“指针回溯”),同时 ...
随机推荐
- 使用js实现全选功能。(全选,全不选,反选)
作业210721 提交代码 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> ...
- 【水】Dev-c++黑暗模式教程
前言 大家有没有觉得盯着Dev-c++那个白花花的背景盯久了之后会觉得眼睛不舒服-- 本人今天就来给大家带来一个黑暗模式的Dev-c++,可以让眼睛没那么难受(本人亲测有效) 效果如下图(猛男警告): ...
- TCP三次握手、四次挥手理解
tcp三次握手建立连接第一次握手 客户端发送给服务器一段连接请求报文,等待服务器回应 第二次握手 服务器收到报文,并发送给客户端一个确认报文,等待客户端回应 第三次握手 客户端收到新报文 ,再发送给服 ...
- BUUCTF-[SUCTF 2019]CheckIn(.user.ini利用+exif_imagetype绕过)
目录 分析 .user.ini使用条件 解题 参考链接 记一道.user.ini利用+exif_imagetype绕过的文件上传的题. 分析 先正经上传一张图片.回显了存储路径,同时发现还包含了一个i ...
- C++ //构造函数的分类及调用 //分类 // 按照参数分类 无参构造函数(默认构造) 有参构造函数 //按照类型分类 普通构造 拷贝构造
1 //构造函数的分类及调用 2 //分类 3 // 按照参数分类 无参构造函数(默认构造) 有参构造函数 4 //按照类型分类 普通构造 拷贝构造 5 6 #include <iostream ...
- 使用POI导出Word(含表格)的实现方式及操作Word的工具类
.personSunflowerP { background: rgba(51, 153, 0, 0.66); border-bottom: 1px solid rgba(0, 102, 0, 1); ...
- Linux进程理解与实践(一)基本概念和编程概述(fork,vfork,cow)
进程 and 程序 什么是程序? 程序是完成特定任务的一系列指令集合. 什么是进程? [1]从用户的角度来看:进程是程序的一次执行过程 [2]从操作系统的核心来看:进程是操作系统分配的内存.CPU时间 ...
- 000 PCI Express协议入门指南目录
一.001 PCI Express体系结构(一)
- 使用autopep8自动规范化python3代码
技术背景 编码规范是所有编程语言都有可能面临的问题,严格的按照编码规范来写代码,不仅能够提高代码的可读性,在后续程序的可维护性上面也有较大的帮助.尤其是在开源项目中,一个具备良好编程规范的项目往往能够 ...
- noip22
T1 考试的时候打的特殊性质分,然而暴力竟然写假了. 正解: 显然是个贪心,要最大化 \(a_{\min}\times b_{\min}\),肯定是要删掉若干个 \(a\) 最小,\(b\) 最小的矩 ...