mirror of
https://github.com/wangyu-/udp2raw.git
synced 2025-09-15 19:54:28 +08:00
Compare commits
109 Commits
20171123.1
...
20180728.1
Author | SHA1 | Date | |
---|---|---|---|
|
d6c0df17f5 | ||
|
8ade602be1 | ||
|
0980d89072 | ||
|
278ade5d36 | ||
|
10869eb197 | ||
|
1bc20c1cdb | ||
|
4bb7367cfa | ||
|
c0c9cc0411 | ||
|
b78dc6673f | ||
|
f52385ccd5 | ||
|
7ad9a6987c | ||
|
184b198470 | ||
|
2dc0670266 | ||
|
6ccd056d41 | ||
|
73daa12db1 | ||
|
80d21e56c7 | ||
|
b0d96a3c47 | ||
|
0682757631 | ||
|
52d540df90 | ||
|
256d1eee69 | ||
|
9e9ad56890 | ||
|
1e98ae10c2 | ||
|
fabe2b3558 | ||
|
565034dbae | ||
|
a7849b3634 | ||
|
3a372b9eee | ||
|
2e8294ab88 | ||
|
30eb96608d | ||
|
822a807e58 | ||
|
f90d1abe05 | ||
|
2f59ce490e | ||
|
4cb60d5997 | ||
|
1155f0547f | ||
|
cac9c56afb | ||
|
f050946ac5 | ||
|
2f0c02def2 | ||
|
c71d256006 | ||
|
946b615acf | ||
|
fef76af3a5 | ||
|
736c3f46b6 | ||
|
bec9c95999 | ||
|
16de522196 | ||
|
232ec4f339 | ||
|
d3cbbe8085 | ||
|
e51c236c20 | ||
|
876649fd74 | ||
|
8a6f89be88 | ||
|
45fca0bbfe | ||
|
cd92410cfe | ||
|
04eec19ab2 | ||
|
423157dbba | ||
|
94e12e6cf5 | ||
|
61512a15ec | ||
|
65943053ff | ||
|
52a911b109 | ||
|
3ab2543715 | ||
|
b9d0375a72 | ||
|
0fc24b6233 | ||
|
4463e21d9e | ||
|
8aeab8cee1 | ||
|
be8e42af1b | ||
|
3862e5a4e2 | ||
|
c0b70c95ca | ||
|
5c7d48e711 | ||
|
b0976dbee6 | ||
|
2c2d897bc2 | ||
|
675ccdf650 | ||
|
f7383575b1 | ||
|
6ea083a49b | ||
|
8fe8653331 | ||
|
2c67c319b7 | ||
|
86a78b223e | ||
|
0c2060028a | ||
|
1f313f1c07 | ||
|
af2513cbc0 | ||
|
65b2d7bc1c | ||
|
a02c22cb3d | ||
|
5a6a2682bc | ||
|
a170650210 | ||
|
b0f62e35cc | ||
|
96b57df4e2 | ||
|
0f756e3166 | ||
|
7cb65ec45d | ||
|
3138b2ca8e | ||
|
7142dd018d | ||
|
2be65585a0 | ||
|
2362f28eb6 | ||
|
0711c7355f | ||
|
c811dc15a3 | ||
|
9a97fbbf4f | ||
|
a884b02b26 | ||
|
85245c5963 | ||
|
4fcae8d54c | ||
|
31f2015ab7 | ||
|
b0613e5b9b | ||
|
7fe8321082 | ||
|
2da0de34a2 | ||
|
29708ba43e | ||
|
1e9404e6ec | ||
|
19b4d45636 | ||
|
c03177b370 | ||
|
c217854190 | ||
|
dc6fc48941 | ||
|
b35edf7486 | ||
|
eedffd90a0 | ||
|
c2aaf9b544 | ||
|
08b14cc9ea | ||
|
6f3eba419e | ||
|
c6cd29dd6f |
48
.cproject
48
.cproject
@@ -1,48 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
|
|
||||||
<storageModule moduleId="org.eclipse.cdt.core.settings">
|
|
||||||
<cconfiguration id="cdt.managedbuild.toolchain.gnu.base.1051378038">
|
|
||||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.base.1051378038" moduleId="org.eclipse.cdt.core.settings" name="Default">
|
|
||||||
<externalSettings/>
|
|
||||||
<extensions>
|
|
||||||
<extension id="org.eclipse.cdt.core.GNU_ELF" point="org.eclipse.cdt.core.BinaryParser"/>
|
|
||||||
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
|
||||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
|
||||||
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
|
||||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
|
||||||
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
|
||||||
</extensions>
|
|
||||||
</storageModule>
|
|
||||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
|
||||||
<configuration buildProperties="" id="cdt.managedbuild.toolchain.gnu.base.1051378038" name="Default" parent="org.eclipse.cdt.build.core.emptycfg">
|
|
||||||
<folderInfo id="cdt.managedbuild.toolchain.gnu.base.1051378038.1421447843" name="/" resourcePath="">
|
|
||||||
<toolChain id="cdt.managedbuild.toolchain.gnu.base.1854135910" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.base">
|
|
||||||
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.GNU_ELF" id="cdt.managedbuild.target.gnu.platform.base.708367396" name="Debug Platform" osList="linux,hpux,aix,qnx" superClass="cdt.managedbuild.target.gnu.platform.base"/>
|
|
||||||
<builder id="cdt.managedbuild.target.gnu.builder.base.1743684210" managedBuildOn="false" name="Gnu Make Builder.Default" superClass="cdt.managedbuild.target.gnu.builder.base"/>
|
|
||||||
<tool id="cdt.managedbuild.tool.gnu.archiver.base.1848194835" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
|
|
||||||
<tool id="cdt.managedbuild.tool.gnu.cpp.compiler.base.1873425854" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.base"/>
|
|
||||||
<tool id="cdt.managedbuild.tool.gnu.c.compiler.base.1356109619" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base"/>
|
|
||||||
<tool id="cdt.managedbuild.tool.gnu.c.linker.base.1018655568" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.base"/>
|
|
||||||
<tool id="cdt.managedbuild.tool.gnu.cpp.linker.base.180014749" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.base"/>
|
|
||||||
<tool id="cdt.managedbuild.tool.gnu.assembler.base.2017907772" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.base"/>
|
|
||||||
</toolChain>
|
|
||||||
</folderInfo>
|
|
||||||
</configuration>
|
|
||||||
</storageModule>
|
|
||||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
|
||||||
</cconfiguration>
|
|
||||||
</storageModule>
|
|
||||||
<storageModule moduleId="scannerConfiguration">
|
|
||||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
|
||||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.base.436825263;cdt.managedbuild.toolchain.gnu.base.436825263.480908490;cdt.managedbuild.tool.gnu.cpp.compiler.base.1940762076;cdt.managedbuild.tool.gnu.cpp.compiler.input.997669137">
|
|
||||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
|
||||||
</scannerConfigBuildInfo>
|
|
||||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.base.436825263;cdt.managedbuild.toolchain.gnu.base.436825263.480908490;cdt.managedbuild.tool.gnu.c.compiler.base.233419498;cdt.managedbuild.tool.gnu.c.compiler.input.460189617">
|
|
||||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
|
||||||
</scannerConfigBuildInfo>
|
|
||||||
</storageModule>
|
|
||||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
|
||||||
<project id="udp2raw.null.1592488805" name="udp2raw"/>
|
|
||||||
</storageModule>
|
|
||||||
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
|
|
||||||
</cproject>
|
|
27
.project
27
.project
@@ -1,27 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<projectDescription>
|
|
||||||
<name>udp2raw-tunnel-desktop</name>
|
|
||||||
<comment></comment>
|
|
||||||
<projects>
|
|
||||||
</projects>
|
|
||||||
<buildSpec>
|
|
||||||
<buildCommand>
|
|
||||||
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
|
|
||||||
<triggers>clean,full,incremental,</triggers>
|
|
||||||
<arguments>
|
|
||||||
</arguments>
|
|
||||||
</buildCommand>
|
|
||||||
<buildCommand>
|
|
||||||
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
|
|
||||||
<triggers>full,incremental,</triggers>
|
|
||||||
<arguments>
|
|
||||||
</arguments>
|
|
||||||
</buildCommand>
|
|
||||||
</buildSpec>
|
|
||||||
<natures>
|
|
||||||
<nature>org.eclipse.cdt.core.cnature</nature>
|
|
||||||
<nature>org.eclipse.cdt.core.ccnature</nature>
|
|
||||||
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
|
|
||||||
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
|
|
||||||
</natures>
|
|
||||||
</projectDescription>
|
|
53
README.md
53
README.md
@@ -5,16 +5,20 @@ A Tunnel which turns UDP Traffic into Encrypted FakeTCP/UDP/ICMP Traffic by usin
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
When used alone,udp2raw tunnels only UDP traffic. Nevertheless,if you used udp2raw + any UDP-based VPN together,you can tunnel any traffic(include TCP/UDP/ICMP),currently OpenVPN/L2TP/ShadowVPN and [tinyFecVPN](https://github.com/wangyu-/tinyFecVPN) are confirmed to be supported.
|
When used alone,udp2raw tunnels only UDP traffic. Nevertheless,if you used udp2raw + any UDP-based VPN together,you can tunnel any traffic(include TCP/UDP/ICMP),currently OpenVPN/L2TP/ShadowVPN and [tinyfecVPN](https://github.com/wangyu-/tinyfecVPN) are confirmed to be supported.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
[简体中文](/doc/README.zh-cn.md)
|
[简体中文](/doc/README.zh-cn.md)(内容更丰富)
|
||||||
|
|
||||||
|
[udp2raw wiki](https://github.com/wangyu-/udp2raw-tunnel/wiki)
|
||||||
|
|
||||||
# Support Platforms
|
# Support Platforms
|
||||||
Linux host (including desktop Linux,Android phone/tablet,OpenWRT router,or Raspberry PI) with root access.
|
Linux host (including desktop Linux,Android phone/tablet,OpenWRT router,or Raspberry PI) with root access.
|
||||||
|
|
||||||
For Windows and MacOS You can run udp2raw inside [this](https://github.com/wangyu-/udp2raw-tunnel/releases/download/20171108.0/lede-17.01.2-x86_virtual_machine_image.zip) 7.5mb virtual machine image(make sure network adapter runs at bridged mode).
|
For Windows and MacOS users, use the udp2raw in [this repo](https://github.com/wangyu-/udp2raw-multiplatform).
|
||||||
|
|
||||||
|
<del>For Windows and MacOS You can run udp2raw inside [this](https://github.com/wangyu-/udp2raw-tunnel/releases/download/20171108.0/lede-17.01.2-x86_virtual_machine_image.zip) 7.5mb virtual machine image(make sure network adapter runs at bridged mode).</del>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -29,7 +33,7 @@ In FakeTCP header mode,udp2raw simulates 3-way handshake while establishing a co
|
|||||||
|
|
||||||
### Encrpytion, Anti-Replay
|
### Encrpytion, Anti-Replay
|
||||||
* Encrypt your traffic with AES-128-CBC.
|
* Encrypt your traffic with AES-128-CBC.
|
||||||
* Protect data integrity by MD5 or CRC32.
|
* Protect data integrity by HMAC-SHA1 (or weaker MD5/CRC32).
|
||||||
* Defense replay attack with an anti-replay window, smiliar to IPSec and OpenVPN.
|
* Defense replay attack with an anti-replay window, smiliar to IPSec and OpenVPN.
|
||||||
|
|
||||||
### Failure Dectection & Stablization (Connection Recovery)
|
### Failure Dectection & Stablization (Connection Recovery)
|
||||||
@@ -51,22 +55,6 @@ For example, if you use udp2raw + OpenVPN, OpenVPN won't lose connection after a
|
|||||||
### Keywords
|
### Keywords
|
||||||
`Bypass UDP QoS` `Bypass UDP Blocking` `Bypass OpenVPN TCP over TCP problem` `OpenVPN over ICMP` `UDP to ICMP tunnel` `UDP to TCP tunnel` `UDP over ICMP` `UDP over TCP`
|
`Bypass UDP QoS` `Bypass UDP Blocking` `Bypass OpenVPN TCP over TCP problem` `OpenVPN over ICMP` `UDP to ICMP tunnel` `UDP to TCP tunnel` `UDP over ICMP` `UDP over TCP`
|
||||||
|
|
||||||
# Frequently Asked Questions
|
|
||||||
### Q: What is the advantage of using udp2raw FakeTCP mode,why not use a TCP-based VPN(such as OpenVPN TCP mode)?
|
|
||||||
Answer: **TCP doesnt allow real-time/out-of-order delivery**. **If you use OpenVPN TCP mode to turn UDP traffic into TCP,there will be latency issue**:the loss of a single packet blocks all following packet until re-transmission is done. This will cause unacceptable delay for gaming and voice chatting.
|
|
||||||
|
|
||||||
**TCP also has re-transmission and congestion control which cant be disabled.** UDP programs usualy want to control packet sending rate by themselves. If you use OpenVPN TCP mode this cant be done because of the congestion control of underlying TCP protocol. Further more,with the re-transmission of underlying TCP,**if you send too many udp packets via an OpenVPN TCP connection,the connection will become completely unusable for a while**(It will eventually recover as most of the re-transmission is done,but it wont be very soon).
|
|
||||||
|
|
||||||
Those issues exist for almost all TCP-based VPNs.
|
|
||||||
|
|
||||||
For udp2raw there is no underlying TCP protocol,udp2raw just add TCP headers to UDP packets directly by using raw socket. It supports real-time/out-of-order delivery,there is no re-transmission and congestion control. **Udp2raw doesnt have all above issues**.
|
|
||||||
|
|
||||||
### Q: Is udp2raw designed for replacing VPN?
|
|
||||||
Answer: No. Udp2raw is designed for bypassing UDP restrictions. It doesnt have all of the features a VPN has(such as transparently redirect all traffic).
|
|
||||||
|
|
||||||
Instead of replacing VPN,udp2raw can be used with any UDP-based VPN together to grant UDP-based VPN the ablity of bypassing UDP restrictions,while not having the performance issue involved by a TCP-based VPN. Check [this link](https://github.com/wangyu-/udp2raw-tunnel#tunneling-any-traffic-via-raw-traffic-by-using-udp2raw-openvpn) for more info.
|
|
||||||
|
|
||||||
|
|
||||||
# Getting Started
|
# Getting Started
|
||||||
### Installing
|
### Installing
|
||||||
Download binary release from https://github.com/wangyu-/udp2raw-tunnel/releases
|
Download binary release from https://github.com/wangyu-/udp2raw-tunnel/releases
|
||||||
@@ -76,11 +64,13 @@ Assume your UDP is blocked or being QOS-ed or just poorly supported. Assume your
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Run at server side:
|
# Run at server side:
|
||||||
./udp2raw_amd64 -s -l0.0.0.0:4096 -r 127.0.0.1:7777 -a -k "passwd" --raw-mode faketcp
|
./udp2raw_amd64 -s -l0.0.0.0:4096 -r 127.0.0.1:7777 -k "passwd" --raw-mode faketcp -a
|
||||||
|
|
||||||
# Run at client side
|
# Run at client side
|
||||||
./udp2raw_amd64 -c -l0.0.0.0:3333 -r44.55.66.77:4096 -a -k "passwd" --raw-mode faketcp
|
./udp2raw_amd64 -c -l0.0.0.0:3333 -r44.55.66.77:4096 -k "passwd" --raw-mode faketcp -a
|
||||||
```
|
```
|
||||||
|
(The above commands need to be run as root. For better security, with some extra steps, you can run udp2raw as non-root. Check [this link](https://github.com/wangyu-/udp2raw-tunnel/wiki/run-udp2raw-as-non-root) for more info )
|
||||||
|
|
||||||
###### Server Output:
|
###### Server Output:
|
||||||

|

|
||||||
###### Client Output:
|
###### Client Output:
|
||||||
@@ -91,9 +81,8 @@ Now,an encrypted raw tunnel has been established between client and server throu
|
|||||||
### Note
|
### Note
|
||||||
To run on Android, check [Android_Guide](/doc/android_guide.md)
|
To run on Android, check [Android_Guide](/doc/android_guide.md)
|
||||||
|
|
||||||
If you have connection problems.Take a look at `--seq-mode` option.
|
`-a` option automatically adds an iptables rule (or a few iptables rules) for you, udp2raw relys on this iptables rule to work stably. Be aware you dont forget `-a` (its a common mistake). If you dont want udp2raw to add iptables rule automatically, you can add it manually(take a look at `-g` option) and omit `-a`.
|
||||||
|
|
||||||
You can run udp2raw with a non-root account(for better security).Take a look at [#26](https://github.com/wangyu-/udp2raw-tunnel/issues/26) for more info.
|
|
||||||
|
|
||||||
# Advanced Topic
|
# Advanced Topic
|
||||||
### Usage
|
### Usage
|
||||||
@@ -103,14 +92,14 @@ git version:6e1df4b39f build date:Oct 24 2017 09:21:15
|
|||||||
repository: https://github.com/wangyu-/udp2raw-tunnel
|
repository: https://github.com/wangyu-/udp2raw-tunnel
|
||||||
|
|
||||||
usage:
|
usage:
|
||||||
run as client : ./this_program -c -l local_listen_ip:local_port -r server_ip:server_port [options]
|
run as client : ./this_program -c -l local_listen_ip:local_port -r server_address:server_port [options]
|
||||||
run as server : ./this_program -s -l server_listen_ip:server_port -r remote_ip:remote_port [options]
|
run as server : ./this_program -s -l server_listen_ip:server_port -r remote_address:remote_port [options]
|
||||||
|
|
||||||
common options,these options must be same on both side:
|
common options,these options must be same on both side:
|
||||||
--raw-mode <string> avaliable values:faketcp(default),udp,icmp
|
--raw-mode <string> avaliable values:faketcp(default),udp,icmp
|
||||||
-k,--key <string> password to gen symetric key,default:"secret key"
|
-k,--key <string> password to gen symetric key,default:"secret key"
|
||||||
--cipher-mode <string> avaliable values:aes128cbc(default),xor,none
|
--cipher-mode <string> avaliable values:aes128cbc(default),xor,none
|
||||||
--auth-mode <string> avaliable values:md5(default),crc32,simple,none
|
--auth-mode <string> avaliable values:hmac_sha1,md5(default),crc32,simple,none
|
||||||
-a,--auto-rule auto add (and delete) iptables rule
|
-a,--auto-rule auto add (and delete) iptables rule
|
||||||
-g,--gen-rule generate iptables rule then exit,so that you can copy and
|
-g,--gen-rule generate iptables rule then exit,so that you can copy and
|
||||||
add it manually.overrides -a
|
add it manually.overrides -a
|
||||||
@@ -153,7 +142,7 @@ other options:
|
|||||||
This program sends packets via raw socket. In FakeTCP mode, Linux kernel TCP packet processing has to be blocked by a iptables rule on both sides, otherwise the kernel will automatically send RST for an unrecongized TCP packet and you will sustain from stability / peformance problems. You can use `-a` option to let the program automatically add / delete iptables rule on start / exit. You can also use the `-g` option to generate iptables rule and add it manually.
|
This program sends packets via raw socket. In FakeTCP mode, Linux kernel TCP packet processing has to be blocked by a iptables rule on both sides, otherwise the kernel will automatically send RST for an unrecongized TCP packet and you will sustain from stability / peformance problems. You can use `-a` option to let the program automatically add / delete iptables rule on start / exit. You can also use the `-g` option to generate iptables rule and add it manually.
|
||||||
|
|
||||||
### `--cipher-mode` and `--auth-mode`
|
### `--cipher-mode` and `--auth-mode`
|
||||||
It is suggested to use `aes128cbc` + `md5` to obtain maximum security. If you want to run the program on a router, you can try `xor` + `simple`, which can fool packet inspection by firewalls the most of time, but it cannot protect you from serious attacks. Mode none is only for debugging purpose. It is not recommended to set the cipher-mode or auth-mode to none.
|
It is suggested to use `aes128cbc` + `hmac_sha1` to obtain maximum security. If you want to run the program on a router, you can try `xor` + `simple`, which can fool packet inspection by firewalls the most of time, but it cannot protect you from serious attacks. Mode none is only for debugging purpose. It is not recommended to set the cipher-mode or auth-mode to none.
|
||||||
|
|
||||||
### `--seq-mode`
|
### `--seq-mode`
|
||||||
The FakeTCP mode does not behave 100% like a real tcp connection. ISPs may be able to distinguish the simulated tcp traffic from the real TCP traffic (though it's costly). seq-mode can help you change the seq increase behavior slightly. If you experience connection problems, try to change the value.
|
The FakeTCP mode does not behave 100% like a real tcp connection. ISPs may be able to distinguish the simulated tcp traffic from the real TCP traffic (though it's costly). seq-mode can help you change the seq increase behavior slightly. If you experience connection problems, try to change the value.
|
||||||
@@ -240,7 +229,7 @@ raw_mode: faketcp cipher_mode: aes128cbc auth_mode: md5
|
|||||||
|
|
||||||
4. Supports almost any UDP-based VPN
|
4. Supports almost any UDP-based VPN
|
||||||
|
|
||||||
More details at [openvpn+udp2raw_guide](/doc/openvpn_guide.md)
|
More details at [openvpn+udp2raw_guide](https://github.com/wangyu-/udp2raw-tunnel/wiki/udp2raw-openvpn-config-guide)
|
||||||
## Speed-up tcp connection via raw traffic by using udp2raw+kcptun
|
## Speed-up tcp connection via raw traffic by using udp2raw+kcptun
|
||||||
kcptun is a tcp connection speed-up program,it speeds-up tcp connection by using kcp protocol on-top of udp.by using udp2raw,you can use kcptun while udp is QoSed or blocked.
|
kcptun is a tcp connection speed-up program,it speeds-up tcp connection by using kcp protocol on-top of udp.by using udp2raw,you can use kcptun while udp is QoSed or blocked.
|
||||||
(kcptun, https://github.com/xtaci/kcptun)
|
(kcptun, https://github.com/xtaci/kcptun)
|
||||||
@@ -285,3 +274,9 @@ https://arxiv.org/abs/1103.0463
|
|||||||
http://korz.cs.yale.edu/2009/tng/papers/pfldnet10.pdf
|
http://korz.cs.yale.edu/2009/tng/papers/pfldnet10.pdf
|
||||||
|
|
||||||
https://pdfs.semanticscholar.org/9e6f/e2306f4385b4eb5416d1fcab16e9361d6ba3.pdf
|
https://pdfs.semanticscholar.org/9e6f/e2306f4385b4eb5416d1fcab16e9361d6ba3.pdf
|
||||||
|
|
||||||
|
# wiki
|
||||||
|
|
||||||
|
Check wiki for more info:
|
||||||
|
|
||||||
|
https://github.com/wangyu-/udp2raw-tunnel/wiki
|
||||||
|
497
common.cpp
497
common.cpp
@@ -12,11 +12,344 @@
|
|||||||
|
|
||||||
static int random_number_fd=-1;
|
static int random_number_fd=-1;
|
||||||
|
|
||||||
|
int force_socket_buf=0;
|
||||||
|
|
||||||
|
int address_t::from_str(char *str)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
|
||||||
|
char ip_addr_str[100];u32_t port;
|
||||||
|
mylog(log_info,"parsing address: %s\n",str);
|
||||||
|
int is_ipv6=0;
|
||||||
|
if(sscanf(str, "[%[^]]]:%u", ip_addr_str,&port)==2)
|
||||||
|
{
|
||||||
|
mylog(log_info,"its an ipv6 adress\n");
|
||||||
|
inner.ipv6.sin6_family=AF_INET6;
|
||||||
|
is_ipv6=1;
|
||||||
|
}
|
||||||
|
else if(sscanf(str, "%[^:]:%u", ip_addr_str,&port)==2)
|
||||||
|
{
|
||||||
|
mylog(log_info,"its an ipv4 adress\n");
|
||||||
|
inner.ipv4.sin_family=AF_INET;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mylog(log_error,"failed to parse\n");
|
||||||
|
myexit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
mylog(log_info,"ip_address is {%s}, port is {%u}\n",ip_addr_str,port);
|
||||||
|
|
||||||
|
if(port>65535)
|
||||||
|
{
|
||||||
|
mylog(log_error,"invalid port: %d\n",port);
|
||||||
|
myexit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret=-100;
|
||||||
|
if(is_ipv6)
|
||||||
|
{
|
||||||
|
ret=inet_pton(AF_INET6, ip_addr_str,&(inner.ipv6.sin6_addr));
|
||||||
|
inner.ipv6.sin6_port=htons(port);
|
||||||
|
if(ret==0) // 0 if address type doesnt match
|
||||||
|
{
|
||||||
|
mylog(log_error,"ip_addr %s is not an ipv6 address, %d\n",ip_addr_str,ret);
|
||||||
|
myexit(-1);
|
||||||
|
}
|
||||||
|
else if(ret==1) // inet_pton returns 1 on success
|
||||||
|
{
|
||||||
|
//okay
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mylog(log_error,"ip_addr %s is invalid, %d\n",ip_addr_str,ret);
|
||||||
|
myexit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret=inet_pton(AF_INET, ip_addr_str,&(inner.ipv4.sin_addr));
|
||||||
|
inner.ipv4.sin_port=htons(port);
|
||||||
|
|
||||||
|
if(ret==0)
|
||||||
|
{
|
||||||
|
mylog(log_error,"ip_addr %s is not an ipv4 address, %d\n",ip_addr_str,ret);
|
||||||
|
myexit(-1);
|
||||||
|
}
|
||||||
|
else if(ret==1)
|
||||||
|
{
|
||||||
|
//okay
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mylog(log_error,"ip_addr %s is invalid, %d\n",ip_addr_str,ret);
|
||||||
|
myexit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int address_t::from_str_ip_only(char * str)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
|
||||||
|
u32_t type;
|
||||||
|
|
||||||
|
if(strchr(str,':')==NULL)
|
||||||
|
type=AF_INET;
|
||||||
|
else
|
||||||
|
type=AF_INET6;
|
||||||
|
|
||||||
|
((sockaddr*)&inner)->sa_family=type;
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
if(type==AF_INET)
|
||||||
|
{
|
||||||
|
ret=inet_pton(type, str,&inner.ipv4.sin_addr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret=inet_pton(type, str,&inner.ipv6.sin6_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ret==0) // 0 if address type doesnt match
|
||||||
|
{
|
||||||
|
mylog(log_error,"confusion in parsing %s, %d\n",str,ret);
|
||||||
|
myexit(-1);
|
||||||
|
}
|
||||||
|
else if(ret==1) // inet_pton returns 1 on success
|
||||||
|
{
|
||||||
|
//okay
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mylog(log_error,"ip_addr %s is invalid, %d\n",str,ret);
|
||||||
|
myexit(-1);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char * address_t::get_str()
|
||||||
|
{
|
||||||
|
static char res[max_addr_len];
|
||||||
|
to_str(res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
void address_t::to_str(char * s)
|
||||||
|
{
|
||||||
|
//static char res[max_addr_len];
|
||||||
|
char ip_addr[max_addr_len];
|
||||||
|
u32_t port;
|
||||||
|
const char * ret=0;
|
||||||
|
if(get_type()==AF_INET6)
|
||||||
|
{
|
||||||
|
ret=inet_ntop(AF_INET6, &inner.ipv6.sin6_addr, ip_addr,max_addr_len);
|
||||||
|
port=inner.ipv6.sin6_port;
|
||||||
|
}
|
||||||
|
else if(get_type()==AF_INET)
|
||||||
|
{
|
||||||
|
ret=inet_ntop(AF_INET, &inner.ipv4.sin_addr, ip_addr,max_addr_len);
|
||||||
|
port=inner.ipv4.sin_port;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(0==1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ret==0) //NULL on failure
|
||||||
|
{
|
||||||
|
mylog(log_error,"inet_ntop failed\n");
|
||||||
|
myexit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
port=ntohs(port);
|
||||||
|
|
||||||
|
ip_addr[max_addr_len-1]=0;
|
||||||
|
if(get_type()==AF_INET6)
|
||||||
|
{
|
||||||
|
sprintf(s,"[%s]:%u",ip_addr,(u32_t)port);
|
||||||
|
}else
|
||||||
|
{
|
||||||
|
sprintf(s,"%s:%u",ip_addr,(u32_t)port);
|
||||||
|
}
|
||||||
|
|
||||||
|
//return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* address_t::get_ip()
|
||||||
|
{
|
||||||
|
char ip_addr[max_addr_len];
|
||||||
|
static char s[max_addr_len];
|
||||||
|
const char * ret=0;
|
||||||
|
if(get_type()==AF_INET6)
|
||||||
|
{
|
||||||
|
ret=inet_ntop(AF_INET6, &inner.ipv6.sin6_addr, ip_addr,max_addr_len);
|
||||||
|
}
|
||||||
|
else if(get_type()==AF_INET)
|
||||||
|
{
|
||||||
|
ret=inet_ntop(AF_INET, &inner.ipv4.sin_addr, ip_addr,max_addr_len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(0==1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ret==0) //NULL on failure
|
||||||
|
{
|
||||||
|
mylog(log_error,"inet_ntop failed\n");
|
||||||
|
myexit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ip_addr[max_addr_len-1]=0;
|
||||||
|
if(get_type()==AF_INET6)
|
||||||
|
{
|
||||||
|
sprintf(s,"%s",ip_addr);
|
||||||
|
}else
|
||||||
|
{
|
||||||
|
sprintf(s,"%s",ip_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
int address_t::from_sockaddr(sockaddr * addr,socklen_t slen)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
//memset(&inner,0,sizeof(inner));
|
||||||
|
if(addr->sa_family==AF_INET6)
|
||||||
|
{
|
||||||
|
assert(slen==sizeof(sockaddr_in6));
|
||||||
|
//inner.ipv6= *( (sockaddr_in6*) addr );
|
||||||
|
memcpy(&inner,addr,slen);
|
||||||
|
}
|
||||||
|
else if(addr->sa_family==AF_INET)
|
||||||
|
{
|
||||||
|
assert(slen==sizeof(sockaddr_in));
|
||||||
|
//inner.ipv4= *( (sockaddr_in*) addr );
|
||||||
|
memcpy(&inner,addr,slen);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(0==1);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int address_t::new_connected_udp_fd()
|
||||||
|
{
|
||||||
|
|
||||||
|
int new_udp_fd;
|
||||||
|
new_udp_fd = socket(get_type(), SOCK_DGRAM, IPPROTO_UDP);
|
||||||
|
if (new_udp_fd < 0) {
|
||||||
|
mylog(log_warn, "create udp_fd error\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
setnonblocking(new_udp_fd);
|
||||||
|
set_buf_size(new_udp_fd,socket_buf_size);
|
||||||
|
|
||||||
|
mylog(log_debug, "created new udp_fd %d\n", new_udp_fd);
|
||||||
|
int ret = connect(new_udp_fd, (struct sockaddr *) &inner, get_len());
|
||||||
|
if (ret != 0) {
|
||||||
|
mylog(log_warn, "udp fd connect fail %d %s\n",ret,strerror(errno) );
|
||||||
|
//sock_close(new_udp_fd);
|
||||||
|
close(new_udp_fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new_udp_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool my_ip_t::equal (const my_ip_t &b) const
|
||||||
|
{
|
||||||
|
//extern int raw_ip_version;
|
||||||
|
if(raw_ip_version==AF_INET)
|
||||||
|
{
|
||||||
|
return v4==b.v4;
|
||||||
|
}else if(raw_ip_version==AF_INET6)
|
||||||
|
{
|
||||||
|
return memcmp(&v6,&b.v6,sizeof(v6))==0;
|
||||||
|
}
|
||||||
|
assert(0==1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
char * my_ip_t::get_str1() const
|
||||||
|
{
|
||||||
|
static char res[max_addr_len];
|
||||||
|
if(raw_ip_version==AF_INET6)
|
||||||
|
{
|
||||||
|
assert(inet_ntop(AF_INET6, &v6, res,max_addr_len)!=0);
|
||||||
|
}
|
||||||
|
else if(raw_ip_version==AF_INET6)
|
||||||
|
{
|
||||||
|
assert(inet_ntop(AF_INET, &v4, res,max_addr_len)!=0);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
char * my_ip_t::get_str2() const
|
||||||
|
{
|
||||||
|
static char res[max_addr_len];
|
||||||
|
if(raw_ip_version==AF_INET6)
|
||||||
|
{
|
||||||
|
assert(inet_ntop(AF_INET6, &v6, res,max_addr_len)!=0);
|
||||||
|
}
|
||||||
|
else if(raw_ip_version==AF_INET)
|
||||||
|
{
|
||||||
|
assert(inet_ntop(AF_INET, &v4, res,max_addr_len)!=0);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int my_ip_t::from_address_t(address_t tmp_addr)
|
||||||
|
{
|
||||||
|
if(tmp_addr.get_type()==raw_ip_version&&raw_ip_version==AF_INET)
|
||||||
|
{
|
||||||
|
v4=tmp_addr.inner.ipv4.sin_addr.s_addr;
|
||||||
|
}
|
||||||
|
else if(tmp_addr.get_type()==raw_ip_version&&raw_ip_version==AF_INET6)
|
||||||
|
{
|
||||||
|
v6=tmp_addr.inner.ipv6.sin6_addr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(0==1);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
int my_ip_t::from_str(char * str)
|
||||||
|
{
|
||||||
|
u32_t type;
|
||||||
|
|
||||||
|
if(strchr(str,':')==NULL)
|
||||||
|
type=AF_INET;
|
||||||
|
else
|
||||||
|
type=AF_INET6;
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
ret=inet_pton(type, str,this);
|
||||||
|
|
||||||
|
if(ret==0) // 0 if address type doesnt match
|
||||||
|
{
|
||||||
|
mylog(log_error,"confusion in parsing %s, %d\n",str,ret);
|
||||||
|
myexit(-1);
|
||||||
|
}
|
||||||
|
else if(ret==1) // inet_pton returns 1 on success
|
||||||
|
{
|
||||||
|
//okay
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mylog(log_error,"ip_addr %s is invalid, %d\n",str,ret);
|
||||||
|
myexit(-1);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}*/
|
||||||
u64_t get_current_time()
|
u64_t get_current_time()
|
||||||
{
|
{
|
||||||
timespec tmp_time;
|
timespec tmp_time;
|
||||||
clock_gettime(CLOCK_MONOTONIC, &tmp_time);
|
clock_gettime(CLOCK_MONOTONIC, &tmp_time);
|
||||||
return tmp_time.tv_sec*1000+tmp_time.tv_nsec/(1000*1000l);
|
return ((u64_t)tmp_time.tv_sec)*1000llu+((u64_t)tmp_time.tv_nsec)/(1000*1000llu);
|
||||||
}
|
}
|
||||||
|
|
||||||
u64_t pack_u64(u32_t a,u32_t b)
|
u64_t pack_u64(u32_t a,u32_t b)
|
||||||
@@ -86,23 +419,63 @@ u32_t get_true_random_number_nz() //nz for non-zero
|
|||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64_t ntoh64(u64_t a)
|
u64_t ntoh64(u64_t a)
|
||||||
{
|
{
|
||||||
if(__BYTE_ORDER == __LITTLE_ENDIAN)
|
#ifdef UDP2RAW_LITTLE_ENDIAN
|
||||||
{
|
u32_t h=get_u64_h(a);
|
||||||
return bswap_64( a);
|
u32_t l=get_u64_l(a);
|
||||||
}
|
return pack_u64(ntohl(l),ntohl(h));
|
||||||
else return a;
|
//return bswap_64( a);
|
||||||
|
#else
|
||||||
|
return a;
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
u64_t hton64(u64_t a)
|
u64_t hton64(u64_t a)
|
||||||
{
|
{
|
||||||
if(__BYTE_ORDER == __LITTLE_ENDIAN)
|
return ntoh64(a);
|
||||||
{
|
}
|
||||||
return bswap_64( a);
|
|
||||||
}
|
|
||||||
else return a;
|
|
||||||
|
|
||||||
|
|
||||||
|
void write_u16(char * p,u16_t w)
|
||||||
|
{
|
||||||
|
*(unsigned char*)(p + 1) = (w & 0xff);
|
||||||
|
*(unsigned char*)(p + 0) = (w >> 8);
|
||||||
|
}
|
||||||
|
u16_t read_u16(char * p)
|
||||||
|
{
|
||||||
|
u16_t res;
|
||||||
|
res = *(const unsigned char*)(p + 0);
|
||||||
|
res = *(const unsigned char*)(p + 1) + (res << 8);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_u32(char * p,u32_t l)
|
||||||
|
{
|
||||||
|
*(unsigned char*)(p + 3) = (unsigned char)((l >> 0) & 0xff);
|
||||||
|
*(unsigned char*)(p + 2) = (unsigned char)((l >> 8) & 0xff);
|
||||||
|
*(unsigned char*)(p + 1) = (unsigned char)((l >> 16) & 0xff);
|
||||||
|
*(unsigned char*)(p + 0) = (unsigned char)((l >> 24) & 0xff);
|
||||||
|
}
|
||||||
|
u32_t read_u32(char * p)
|
||||||
|
{
|
||||||
|
u32_t res;
|
||||||
|
res = *(const unsigned char*)(p + 0);
|
||||||
|
res = *(const unsigned char*)(p + 1) + (res << 8);
|
||||||
|
res = *(const unsigned char*)(p + 2) + (res << 8);
|
||||||
|
res = *(const unsigned char*)(p + 3) + (res << 8);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_u64(char * s,u64_t a)
|
||||||
|
{
|
||||||
|
assert(0==1);
|
||||||
|
}
|
||||||
|
u64_t read_u64(char * s)
|
||||||
|
{
|
||||||
|
assert(0==1);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setnonblocking(int sock) {
|
void setnonblocking(int sock) {
|
||||||
@@ -149,7 +522,40 @@ unsigned short csum(const unsigned short *ptr,int nbytes) {//works both for big
|
|||||||
return(answer);
|
return(answer);
|
||||||
}
|
}
|
||||||
|
|
||||||
int set_buf_size(int fd,int socket_buf_size,int force_socket_buf)
|
unsigned short csum_with_header(char* header,int hlen,const unsigned short *ptr,int nbytes) {//works both for big and little endian
|
||||||
|
|
||||||
|
long sum;
|
||||||
|
unsigned short oddbyte;
|
||||||
|
short answer;
|
||||||
|
|
||||||
|
assert(hlen%2==0);
|
||||||
|
|
||||||
|
sum=0;
|
||||||
|
unsigned short * tmp= (unsigned short *)header;
|
||||||
|
for(int i=0;i<hlen/2;i++)
|
||||||
|
{
|
||||||
|
sum+=*tmp++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
while(nbytes>1) {
|
||||||
|
sum+=*ptr++;
|
||||||
|
nbytes-=2;
|
||||||
|
}
|
||||||
|
if(nbytes==1) {
|
||||||
|
oddbyte=0;
|
||||||
|
*((u_char*)&oddbyte)=*(u_char*)ptr;
|
||||||
|
sum+=oddbyte;
|
||||||
|
}
|
||||||
|
|
||||||
|
sum = (sum>>16)+(sum & 0xffff);
|
||||||
|
sum = sum + (sum>>16);
|
||||||
|
answer=(short)~sum;
|
||||||
|
|
||||||
|
return(answer);
|
||||||
|
}
|
||||||
|
|
||||||
|
int set_buf_size(int fd,int socket_buf_size)
|
||||||
{
|
{
|
||||||
if(force_socket_buf)
|
if(force_socket_buf)
|
||||||
{
|
{
|
||||||
@@ -180,11 +586,11 @@ int set_buf_size(int fd,int socket_buf_size,int force_socket_buf)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int numbers_to_char(id_t id1,id_t id2,id_t id3,char * &data,int &len)
|
int numbers_to_char(my_id_t id1,my_id_t id2,my_id_t id3,char * &data,int &len)
|
||||||
{
|
{
|
||||||
static char buf[buf_len];
|
static char buf[buf_len];
|
||||||
data=buf;
|
data=buf;
|
||||||
id_t tmp=htonl(id1);
|
my_id_t tmp=htonl(id1);
|
||||||
memcpy(buf,&tmp,sizeof(tmp));
|
memcpy(buf,&tmp,sizeof(tmp));
|
||||||
|
|
||||||
tmp=htonl(id2);
|
tmp=htonl(id2);
|
||||||
@@ -193,21 +599,21 @@ int numbers_to_char(id_t id1,id_t id2,id_t id3,char * &data,int &len)
|
|||||||
tmp=htonl(id3);
|
tmp=htonl(id3);
|
||||||
memcpy(buf+sizeof(tmp)*2,&tmp,sizeof(tmp));
|
memcpy(buf+sizeof(tmp)*2,&tmp,sizeof(tmp));
|
||||||
|
|
||||||
len=sizeof(id_t)*3;
|
len=sizeof(my_id_t)*3;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int char_to_numbers(const char * data,int len,id_t &id1,id_t &id2,id_t &id3)
|
int char_to_numbers(const char * data,int len,my_id_t &id1,my_id_t &id2,my_id_t &id3)
|
||||||
{
|
{
|
||||||
if(len<int(sizeof(id_t)*3)) return -1;
|
if(len<int(sizeof(my_id_t)*3)) return -1;
|
||||||
//id1=ntohl( *((id_t*)(data+0)) );
|
//id1=ntohl( *((id_t*)(data+0)) );
|
||||||
memcpy(&id1,data+0,sizeof(id1));
|
memcpy(&id1,data+0,sizeof(id1));
|
||||||
id1=ntohl(id1);
|
id1=ntohl(id1);
|
||||||
//id2=ntohl( *((id_t*)(data+sizeof(id_t))) );
|
//id2=ntohl( *((id_t*)(data+sizeof(id_t))) );
|
||||||
memcpy(&id2,data+sizeof(id_t),sizeof(id2));
|
memcpy(&id2,data+sizeof(my_id_t),sizeof(id2));
|
||||||
id2=ntohl(id2);
|
id2=ntohl(id2);
|
||||||
//id3=ntohl( *((id_t*)(data+sizeof(id_t)*2)) );
|
//id3=ntohl( *((id_t*)(data+sizeof(id_t)*2)) );
|
||||||
memcpy(&id3,data+sizeof(id_t)*2,sizeof(id3));
|
memcpy(&id3,data+sizeof(my_id_t)*2,sizeof(id3));
|
||||||
id3=ntohl(id3);
|
id3=ntohl(id3);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -237,10 +643,9 @@ int hex_to_u32_with_endian(const string & a,u32_t &output)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
bool larger_than_u32(u32_t a,u32_t b)
|
bool larger_than_u32(u32_t a,u32_t b)
|
||||||
//TODO
|
|
||||||
//looks like this can simply be done by return ((i32_t)(a-b) >0)
|
|
||||||
{
|
{
|
||||||
|
return ((i32_t(a-b)) >0);
|
||||||
|
/*
|
||||||
u32_t smaller,bigger;
|
u32_t smaller,bigger;
|
||||||
smaller=min(a,b);//smaller in normal sense
|
smaller=min(a,b);//smaller in normal sense
|
||||||
bigger=max(a,b);
|
bigger=max(a,b);
|
||||||
@@ -267,11 +672,13 @@ bool larger_than_u32(u32_t a,u32_t b)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
bool larger_than_u16(uint16_t a,uint16_t b)
|
bool larger_than_u16(uint16_t a,uint16_t b)
|
||||||
{
|
{
|
||||||
|
return ((i16_t(a-b)) >0);
|
||||||
|
/*
|
||||||
uint16_t smaller,bigger;
|
uint16_t smaller,bigger;
|
||||||
smaller=min(a,b);//smaller in normal sense
|
smaller=min(a,b);//smaller in normal sense
|
||||||
bigger=max(a,b);
|
bigger=max(a,b);
|
||||||
@@ -297,7 +704,7 @@ bool larger_than_u16(uint16_t a,uint16_t b)
|
|||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void myexit(int a)
|
void myexit(int a)
|
||||||
@@ -593,6 +1000,7 @@ int create_fifo(char * file)
|
|||||||
return fifo_fd;
|
return fifo_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
void ip_port_t::from_u64(u64_t u64)
|
void ip_port_t::from_u64(u64_t u64)
|
||||||
{
|
{
|
||||||
ip=get_u64_h(u64);
|
ip=get_u64_h(u64);
|
||||||
@@ -607,12 +1015,47 @@ char * ip_port_t::to_s()
|
|||||||
static char res[40];
|
static char res[40];
|
||||||
sprintf(res,"%s:%d",my_ntoa(ip),port);
|
sprintf(res,"%s:%d",my_ntoa(ip),port);
|
||||||
return res;
|
return res;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void print_binary_chars(const char * a,int len)
|
||||||
|
{
|
||||||
|
for(int i=0;i<len;i++)
|
||||||
|
{
|
||||||
|
unsigned char b=a[i];
|
||||||
|
log_bare(log_debug,"<%02x>",(int)b);
|
||||||
|
}
|
||||||
|
log_bare(log_debug,"\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
u32_t djb2(unsigned char *str,int len)
|
||||||
|
{
|
||||||
|
u32_t hash = 5381;
|
||||||
|
int c;
|
||||||
|
int i=0;
|
||||||
|
while(c = *str++,i++!=len)
|
||||||
|
{
|
||||||
|
hash = ((hash << 5) + hash)^c; /* (hash * 33) ^ c */
|
||||||
|
}
|
||||||
|
|
||||||
|
hash=htonl(hash);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32_t sdbm(unsigned char *str,int len)
|
||||||
|
{
|
||||||
|
u32_t hash = 0;
|
||||||
|
int c;
|
||||||
|
int i=0;
|
||||||
|
while(c = *str++,i++!=len)
|
||||||
|
{
|
||||||
|
hash = c + (hash << 6) + (hash << 16) - hash;
|
||||||
|
}
|
||||||
|
//hash=htonl(hash);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
425
common.h
425
common.h
@@ -17,52 +17,135 @@
|
|||||||
|
|
||||||
#include<unistd.h>
|
#include<unistd.h>
|
||||||
#include<errno.h>
|
#include<errno.h>
|
||||||
#include <sys/epoll.h>
|
//#include <sys/epoll.h>
|
||||||
#include <sys/wait.h>
|
//#include <sys/wait.h>
|
||||||
#include <sys/socket.h> //for socket ofcourse
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <stdlib.h> //for exit(0);
|
#include <stdlib.h> //for exit(0);
|
||||||
#include <errno.h> //For errno - the error number
|
#include <errno.h> //For errno - the error number
|
||||||
#include <netinet/tcp.h> //Provides declarations for tcp header
|
|
||||||
#include <netinet/udp.h>
|
|
||||||
#include <netinet/ip.h> //Provides declarations for ip header
|
|
||||||
#include <netinet/if_ether.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <byteswap.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <linux/if_ether.h>
|
|
||||||
#include <linux/filter.h>
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <sys/timerfd.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <net/if.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <linux/if_packet.h>
|
|
||||||
#include <byteswap.h>
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#if defined(UDP2RAW_MP)
|
||||||
|
|
||||||
|
#if !defined(__CYGWIN__) && !defined(__MINGW32__)
|
||||||
|
#include <pcap.h>
|
||||||
|
#else
|
||||||
|
#include <pcap_wrapper.h>
|
||||||
|
#define NO_LIBNET
|
||||||
|
#endif
|
||||||
|
#ifndef NO_LIBNET
|
||||||
|
#include <libnet.h>
|
||||||
|
#endif
|
||||||
|
#include <my_ev.h>
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
//#include <linux/if_ether.h>
|
||||||
|
#include <linux/filter.h>
|
||||||
|
#include <linux/if_packet.h>
|
||||||
|
#include <sys/epoll.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <netinet/if_ether.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <sys/timerfd.h>
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__MINGW32__)
|
||||||
|
#include <winsock2.h>
|
||||||
|
typedef unsigned char u_int8_t;
|
||||||
|
typedef unsigned short u_int16_t;
|
||||||
|
typedef unsigned int u_int32_t;
|
||||||
|
typedef int socklen_t;
|
||||||
|
#else
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include<unordered_map>
|
#include<unordered_map>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <list>
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || \
|
||||||
|
defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ || \
|
||||||
|
defined(__BIG_ENDIAN__) || \
|
||||||
|
defined(__ARMEB__) || \
|
||||||
|
defined(__THUMBEB__) || \
|
||||||
|
defined(__AARCH64EB__) || \
|
||||||
|
defined(_MIBSEB) || defined(__MIBSEB) || defined(__MIBSEB__)
|
||||||
|
#define UDP2RAW_BIG_ENDIAN 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN || \
|
||||||
|
defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ || \
|
||||||
|
defined(__LITTLE_ENDIAN__) || \
|
||||||
|
defined(__ARMEL__) || \
|
||||||
|
defined(__THUMBEL__) || \
|
||||||
|
defined(__AARCH64EL__) || \
|
||||||
|
defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__)
|
||||||
|
#define UDP2RAW_LITTLE_ENDIAN 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(UDP2RAW_BIG_ENDIAN) &&defined(UDP2RAW_LITTLE_ENDIAN)
|
||||||
|
#error "endian detection conflicts"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(UDP2RAW_BIG_ENDIAN) && !defined(UDP2RAW_LITTLE_ENDIAN)
|
||||||
|
#error "endian detection failed"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__MINGW32__)
|
||||||
|
#define setsockopt(a,b,c,d,e) setsockopt(a,b,c,(const char *)(d),e)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
char *get_sock_error();
|
||||||
|
int get_sock_errno();
|
||||||
|
|
||||||
|
#if defined(__MINGW32__)
|
||||||
|
typedef SOCKET my_fd_t;
|
||||||
|
inline int sock_close(my_fd_t fd)
|
||||||
|
{
|
||||||
|
return closesocket(fd);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
typedef int my_fd_t;
|
||||||
|
inline int sock_close(my_fd_t fd)
|
||||||
|
{
|
||||||
|
return close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef unsigned long long u64_t; //this works on most platform,avoid using the PRId64
|
typedef unsigned long long u64_t; //this works on most platform,avoid using the PRId64
|
||||||
typedef long long i64_t;
|
typedef long long i64_t;
|
||||||
|
|
||||||
typedef unsigned int u32_t;
|
typedef unsigned int u32_t;
|
||||||
typedef int i32_t;
|
typedef int i32_t;
|
||||||
|
|
||||||
typedef u32_t id_t;
|
typedef unsigned short u16_t;
|
||||||
|
typedef short i16_t;
|
||||||
|
|
||||||
|
typedef u32_t my_id_t;
|
||||||
|
|
||||||
typedef u64_t iv_t;
|
typedef u64_t iv_t;
|
||||||
|
|
||||||
@@ -70,7 +153,13 @@ typedef u64_t padding_t;
|
|||||||
|
|
||||||
typedef u64_t anti_replay_seq_t;
|
typedef u64_t anti_replay_seq_t;
|
||||||
|
|
||||||
|
typedef u64_t my_time_t;
|
||||||
|
|
||||||
|
const int max_addr_len=100;
|
||||||
|
|
||||||
|
extern int force_socket_buf;
|
||||||
|
|
||||||
|
/*
|
||||||
struct ip_port_t
|
struct ip_port_t
|
||||||
{
|
{
|
||||||
u32_t ip;
|
u32_t ip;
|
||||||
@@ -78,16 +167,190 @@ struct ip_port_t
|
|||||||
void from_u64(u64_t u64);
|
void from_u64(u64_t u64);
|
||||||
u64_t to_u64();
|
u64_t to_u64();
|
||||||
char * to_s();
|
char * to_s();
|
||||||
};
|
};*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef u64_t fd64_t;
|
typedef u64_t fd64_t;
|
||||||
|
|
||||||
const int max_data_len=1600;
|
u32_t djb2(unsigned char *str,int len);
|
||||||
|
u32_t sdbm(unsigned char *str,int len);
|
||||||
|
|
||||||
|
struct address_t //TODO scope id
|
||||||
|
{
|
||||||
|
struct hash_function
|
||||||
|
{
|
||||||
|
u32_t operator()(const address_t &key) const
|
||||||
|
{
|
||||||
|
return sdbm((unsigned char*)&key.inner,sizeof(key.inner));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
union storage_t //sockaddr_storage is too huge, we dont use it.
|
||||||
|
{
|
||||||
|
sockaddr_in ipv4;
|
||||||
|
sockaddr_in6 ipv6;
|
||||||
|
};
|
||||||
|
storage_t inner;
|
||||||
|
|
||||||
|
address_t()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
memset(&inner,0,sizeof(inner));
|
||||||
|
}
|
||||||
|
int from_ip_port(u32_t ip, int port)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
inner.ipv4.sin_family=AF_INET;
|
||||||
|
inner.ipv4.sin_port=htons(port);
|
||||||
|
inner.ipv4.sin_addr.s_addr=ip;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int from_ip_port_new(int type, void * ip, int port)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
if(type==AF_INET)
|
||||||
|
{
|
||||||
|
inner.ipv4.sin_family=AF_INET;
|
||||||
|
inner.ipv4.sin_port=htons(port);
|
||||||
|
inner.ipv4.sin_addr.s_addr=*((u32_t *)ip);
|
||||||
|
}
|
||||||
|
else if(type==AF_INET6)
|
||||||
|
{
|
||||||
|
inner.ipv6.sin6_family=AF_INET6;
|
||||||
|
inner.ipv6.sin6_port=htons(port);
|
||||||
|
inner.ipv6.sin6_addr=*((in6_addr*)ip);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int from_str(char * str);
|
||||||
|
|
||||||
|
int from_str_ip_only(char * str);
|
||||||
|
|
||||||
|
int from_sockaddr(sockaddr *,socklen_t);
|
||||||
|
|
||||||
|
char* get_str();
|
||||||
|
void to_str(char *);
|
||||||
|
|
||||||
|
inline u32_t get_type()
|
||||||
|
{
|
||||||
|
u32_t ret=((sockaddr*)&inner)->sa_family;
|
||||||
|
assert(ret==AF_INET||ret==AF_INET6);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u32_t get_len()
|
||||||
|
{
|
||||||
|
u32_t type=get_type();
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case AF_INET:
|
||||||
|
return sizeof(sockaddr_in);
|
||||||
|
case AF_INET6:
|
||||||
|
return sizeof(sockaddr_in6);
|
||||||
|
default:
|
||||||
|
assert(0==1);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline u32_t get_port()
|
||||||
|
{
|
||||||
|
u32_t type=get_type();
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case AF_INET:
|
||||||
|
return ntohs(inner.ipv4.sin_port);
|
||||||
|
case AF_INET6:
|
||||||
|
return ntohs(inner.ipv6.sin6_port);
|
||||||
|
default:
|
||||||
|
assert(0==1);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void set_port(int port)
|
||||||
|
{
|
||||||
|
u32_t type=get_type();
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case AF_INET:
|
||||||
|
inner.ipv4.sin_port=htons(port);
|
||||||
|
break;
|
||||||
|
case AF_INET6:
|
||||||
|
inner.ipv6.sin6_port=htons(port);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(0==1);
|
||||||
|
}
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator == (const address_t &b) const
|
||||||
|
{
|
||||||
|
//return this->data==b.data;
|
||||||
|
return memcmp(&this->inner,&b.inner,sizeof(this->inner))==0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int new_connected_udp_fd();
|
||||||
|
|
||||||
|
char* get_ip();
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
template <>
|
||||||
|
struct hash<address_t>
|
||||||
|
{
|
||||||
|
std::size_t operator()(const address_t& key) const
|
||||||
|
{
|
||||||
|
|
||||||
|
//return address_t::hash_function(k);
|
||||||
|
return sdbm((unsigned char*)&key.inner,sizeof(key.inner));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
union my_ip_t //just a simple version of address_t,stores ip only
|
||||||
|
{
|
||||||
|
u32_t v4;
|
||||||
|
in6_addr v6;
|
||||||
|
|
||||||
|
bool equal (const my_ip_t &b) const;
|
||||||
|
|
||||||
|
//int from_str(char * str);
|
||||||
|
char * get_str1() const;
|
||||||
|
char * get_str2() const;
|
||||||
|
|
||||||
|
int from_address_t(address_t a);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct not_copy_able_t
|
||||||
|
{
|
||||||
|
not_copy_able_t()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
not_copy_able_t(const not_copy_able_t &other)
|
||||||
|
{
|
||||||
|
assert(0==1);
|
||||||
|
}
|
||||||
|
const not_copy_able_t & operator=(const not_copy_able_t &other)
|
||||||
|
{
|
||||||
|
assert(0==1);
|
||||||
|
return other;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const int max_data_len=1800;
|
||||||
const int buf_len=max_data_len+400;
|
const int buf_len=max_data_len+400;
|
||||||
|
|
||||||
|
//const int max_address_len=512;
|
||||||
|
|
||||||
u64_t get_current_time();
|
u64_t get_current_time();
|
||||||
u64_t pack_u64(u32_t a,u32_t b);
|
u64_t pack_u64(u32_t a,u32_t b);
|
||||||
|
|
||||||
@@ -103,17 +366,28 @@ u32_t get_true_random_number();
|
|||||||
u32_t get_true_random_number_nz();
|
u32_t get_true_random_number_nz();
|
||||||
u64_t ntoh64(u64_t a);
|
u64_t ntoh64(u64_t a);
|
||||||
u64_t hton64(u64_t a);
|
u64_t hton64(u64_t a);
|
||||||
|
|
||||||
|
void write_u16(char *,u16_t a);// network order
|
||||||
|
u16_t read_u16(char *);
|
||||||
|
|
||||||
|
void write_u32(char *,u32_t a);// network order
|
||||||
|
u32_t read_u32(char *);
|
||||||
|
|
||||||
|
void write_u64(char *,u64_t a);
|
||||||
|
u64_t read_uu64(char *);
|
||||||
|
|
||||||
bool larger_than_u16(uint16_t a,uint16_t b);
|
bool larger_than_u16(uint16_t a,uint16_t b);
|
||||||
bool larger_than_u32(u32_t a,u32_t b);
|
bool larger_than_u32(u32_t a,u32_t b);
|
||||||
void setnonblocking(int sock);
|
void setnonblocking(int sock);
|
||||||
int set_buf_size(int fd,int socket_buf_size,int force_socket_buf);
|
int set_buf_size(int fd,int socket_buf_size);
|
||||||
|
|
||||||
void myexit(int a);
|
void myexit(int a);
|
||||||
|
|
||||||
unsigned short csum(const unsigned short *ptr,int nbytes);
|
unsigned short csum(const unsigned short *ptr,int nbytes);
|
||||||
|
unsigned short csum_with_header(char* header,int hlen,const unsigned short *ptr,int nbytes);
|
||||||
|
|
||||||
int numbers_to_char(id_t id1,id_t id2,id_t id3,char * &data,int &len);
|
int numbers_to_char(my_id_t id1,my_id_t id2,my_id_t id3,char * &data,int &len);
|
||||||
int char_to_numbers(const char * data,int len,id_t &id1,id_t &id2,id_t &id3);
|
int char_to_numbers(const char * data,int len,my_id_t &id1,my_id_t &id2,my_id_t &id3);
|
||||||
|
|
||||||
const int show_none=0;
|
const int show_none=0;
|
||||||
const int show_command=0x1;
|
const int show_command=0x1;
|
||||||
@@ -139,4 +413,97 @@ int hex_to_u32(const string & a,u32_t &output);
|
|||||||
|
|
||||||
int create_fifo(char * file);
|
int create_fifo(char * file);
|
||||||
|
|
||||||
|
void print_binary_chars(const char * a,int len);
|
||||||
|
|
||||||
|
|
||||||
|
template <class key_t>
|
||||||
|
struct lru_collector_t:not_copy_able_t
|
||||||
|
{
|
||||||
|
//typedef void* key_t;
|
||||||
|
//#define key_t void*
|
||||||
|
struct lru_pair_t
|
||||||
|
{
|
||||||
|
key_t key;
|
||||||
|
my_time_t ts;
|
||||||
|
};
|
||||||
|
|
||||||
|
unordered_map<key_t,typename list<lru_pair_t>::iterator> mp;
|
||||||
|
|
||||||
|
list<lru_pair_t> q;
|
||||||
|
int update(key_t key)
|
||||||
|
{
|
||||||
|
assert(mp.find(key)!=mp.end());
|
||||||
|
auto it=mp[key];
|
||||||
|
q.erase(it);
|
||||||
|
|
||||||
|
my_time_t value=get_current_time();
|
||||||
|
if(!q.empty())
|
||||||
|
{
|
||||||
|
assert(value >=q.front().ts);
|
||||||
|
}
|
||||||
|
lru_pair_t tmp; tmp.key=key; tmp.ts=value;
|
||||||
|
q.push_front( tmp);
|
||||||
|
mp[key]=q.begin();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int new_key(key_t key)
|
||||||
|
{
|
||||||
|
assert(mp.find(key)==mp.end());
|
||||||
|
|
||||||
|
my_time_t value=get_current_time();
|
||||||
|
if(!q.empty())
|
||||||
|
{
|
||||||
|
assert(value >=q.front().ts);
|
||||||
|
}
|
||||||
|
lru_pair_t tmp; tmp.key=key; tmp.ts=value;
|
||||||
|
q.push_front( tmp);
|
||||||
|
mp[key]=q.begin();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int size()
|
||||||
|
{
|
||||||
|
return q.size();
|
||||||
|
}
|
||||||
|
int empty()
|
||||||
|
{
|
||||||
|
return q.empty();
|
||||||
|
}
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
mp.clear(); q.clear();
|
||||||
|
}
|
||||||
|
my_time_t ts_of(key_t key)
|
||||||
|
{
|
||||||
|
assert(mp.find(key)!=mp.end());
|
||||||
|
return mp[key]->ts;
|
||||||
|
}
|
||||||
|
|
||||||
|
my_time_t peek_back(key_t &key)
|
||||||
|
{
|
||||||
|
assert(!q.empty());
|
||||||
|
auto it=q.end(); it--;
|
||||||
|
key=it->key;
|
||||||
|
return it->ts;
|
||||||
|
}
|
||||||
|
void erase(key_t key)
|
||||||
|
{
|
||||||
|
assert(mp.find(key)!=mp.end());
|
||||||
|
q.erase(mp[key]);
|
||||||
|
mp.erase(key);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
void erase_back()
|
||||||
|
{
|
||||||
|
assert(!q.empty());
|
||||||
|
auto it=q.end(); it--;
|
||||||
|
key_t key=it->key;
|
||||||
|
erase(key);
|
||||||
|
}*/
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* COMMON_H_ */
|
#endif /* COMMON_H_ */
|
||||||
|
272
connection.cpp
272
connection.cpp
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
int disable_anti_replay=0;//if anti_replay windows is diabled
|
int disable_anti_replay=0;//if anti_replay windows is diabled
|
||||||
|
|
||||||
const int disable_conv_clear=0;//a udp connection in the multiplexer is called conversation in this program,conv for short.
|
|
||||||
|
|
||||||
const int disable_conn_clear=0;//a raw connection is called conn.
|
const int disable_conn_clear=0;//a raw connection is called conn.
|
||||||
|
|
||||||
@@ -75,159 +75,15 @@ conn_manager_t conn_manager;
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void server_clear_function(u64_t u64);
|
|
||||||
|
|
||||||
conv_manager_t::conv_manager_t()
|
|
||||||
{
|
|
||||||
clear_it=conv_last_active_time.begin();
|
|
||||||
long long last_clear_time=0;
|
|
||||||
//clear_function=0;
|
|
||||||
}
|
|
||||||
conv_manager_t::~conv_manager_t()
|
|
||||||
{
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
int conv_manager_t::get_size()
|
|
||||||
{
|
|
||||||
return conv_to_u64.size();
|
|
||||||
}
|
|
||||||
void conv_manager_t::reserve()
|
|
||||||
{
|
|
||||||
u64_to_conv.reserve(10007);
|
|
||||||
conv_to_u64.reserve(10007);
|
|
||||||
conv_last_active_time.reserve(10007);
|
|
||||||
}
|
|
||||||
void conv_manager_t::clear()
|
|
||||||
{
|
|
||||||
if(disable_conv_clear) return ;
|
|
||||||
|
|
||||||
if(program_mode==server_mode)
|
|
||||||
{
|
|
||||||
for(it=conv_to_u64.begin();it!=conv_to_u64.end();it++)
|
|
||||||
{
|
|
||||||
//int fd=int((it->second<<32u)>>32u);
|
|
||||||
server_clear_function( it->second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
u64_to_conv.clear();
|
|
||||||
conv_to_u64.clear();
|
|
||||||
conv_last_active_time.clear();
|
|
||||||
|
|
||||||
clear_it=conv_last_active_time.begin();
|
|
||||||
|
|
||||||
}
|
|
||||||
u32_t conv_manager_t::get_new_conv()
|
|
||||||
{
|
|
||||||
u32_t conv=get_true_random_number_nz();
|
|
||||||
while(conv_to_u64.find(conv)!=conv_to_u64.end())
|
|
||||||
{
|
|
||||||
conv=get_true_random_number_nz();
|
|
||||||
}
|
|
||||||
return conv;
|
|
||||||
}
|
|
||||||
int conv_manager_t::is_conv_used(u32_t conv)
|
|
||||||
{
|
|
||||||
return conv_to_u64.find(conv)!=conv_to_u64.end();
|
|
||||||
}
|
|
||||||
int conv_manager_t::is_u64_used(u64_t u64)
|
|
||||||
{
|
|
||||||
return u64_to_conv.find(u64)!=u64_to_conv.end();
|
|
||||||
}
|
|
||||||
u32_t conv_manager_t::find_conv_by_u64(u64_t u64)
|
|
||||||
{
|
|
||||||
return u64_to_conv[u64];
|
|
||||||
}
|
|
||||||
u64_t conv_manager_t::find_u64_by_conv(u32_t conv)
|
|
||||||
{
|
|
||||||
return conv_to_u64[conv];
|
|
||||||
}
|
|
||||||
int conv_manager_t::update_active_time(u32_t conv)
|
|
||||||
{
|
|
||||||
return conv_last_active_time[conv]=get_current_time();
|
|
||||||
}
|
|
||||||
int conv_manager_t::insert_conv(u32_t conv,u64_t u64)
|
|
||||||
{
|
|
||||||
u64_to_conv[u64]=conv;
|
|
||||||
conv_to_u64[conv]=u64;
|
|
||||||
conv_last_active_time[conv]=get_current_time();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int conv_manager_t::erase_conv(u32_t conv)
|
|
||||||
{
|
|
||||||
if(disable_conv_clear) return 0;
|
|
||||||
u64_t u64=conv_to_u64[conv];
|
|
||||||
if(program_mode==server_mode)
|
|
||||||
{
|
|
||||||
server_clear_function(u64);
|
|
||||||
}
|
|
||||||
conv_to_u64.erase(conv);
|
|
||||||
u64_to_conv.erase(u64);
|
|
||||||
conv_last_active_time.erase(conv);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int conv_manager_t::clear_inactive(char * ip_port)
|
|
||||||
{
|
|
||||||
if(get_current_time()-last_clear_time>conv_clear_interval)
|
|
||||||
{
|
|
||||||
last_clear_time=get_current_time();
|
|
||||||
return clear_inactive0(ip_port);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int conv_manager_t::clear_inactive0(char * ip_port)
|
|
||||||
{
|
|
||||||
if(disable_conv_clear) return 0;
|
|
||||||
|
|
||||||
|
|
||||||
//map<uint32_t,uint64_t>::iterator it;
|
|
||||||
int cnt=0;
|
|
||||||
it=clear_it;
|
|
||||||
int size=conv_last_active_time.size();
|
|
||||||
int num_to_clean=size/conv_clear_ratio+conv_clear_min; //clear 1/10 each time,to avoid latency glitch
|
|
||||||
|
|
||||||
num_to_clean=min(num_to_clean,size);
|
|
||||||
|
|
||||||
u64_t current_time=get_current_time();
|
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
if(cnt>=num_to_clean) break;
|
|
||||||
if(conv_last_active_time.begin()==conv_last_active_time.end()) break;
|
|
||||||
|
|
||||||
if(it==conv_last_active_time.end())
|
|
||||||
{
|
|
||||||
it=conv_last_active_time.begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
if( current_time -it->second >conv_timeout )
|
|
||||||
{
|
|
||||||
//mylog(log_info,"inactive conv %u cleared \n",it->first);
|
|
||||||
old_it=it;
|
|
||||||
it++;
|
|
||||||
u32_t conv= old_it->first;
|
|
||||||
erase_conv(old_it->first);
|
|
||||||
if(ip_port==0)
|
|
||||||
{
|
|
||||||
mylog(log_info,"conv %x cleared\n",conv);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mylog(log_info,"[%s]conv %x cleared\n",ip_port,conv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
it++;
|
|
||||||
}
|
|
||||||
cnt++;
|
|
||||||
}
|
|
||||||
clear_it=it;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void conn_info_t::recover(const conn_info_t &conn_info)
|
void conn_info_t::recover(const conn_info_t &conn_info)
|
||||||
{
|
{
|
||||||
raw_info=conn_info.raw_info;
|
raw_info=conn_info.raw_info;
|
||||||
|
|
||||||
|
raw_info.rst_received=0;
|
||||||
|
raw_info.disabled=0;
|
||||||
|
|
||||||
last_state_time=conn_info.last_state_time;
|
last_state_time=conn_info.last_state_time;
|
||||||
last_hb_recv_time=conn_info.last_hb_recv_time;
|
last_hb_recv_time=conn_info.last_hb_recv_time;
|
||||||
last_hb_sent_time=conn_info.last_hb_sent_time;
|
last_hb_sent_time=conn_info.last_hb_sent_time;
|
||||||
@@ -238,6 +94,7 @@ conv_manager_t::~conv_manager_t()
|
|||||||
my_roller=0;//no need to set,but for easier debug,set it to zero
|
my_roller=0;//no need to set,but for easier debug,set it to zero
|
||||||
oppsite_roller=0;//same as above
|
oppsite_roller=0;//same as above
|
||||||
last_oppsite_roller_time=0;
|
last_oppsite_roller_time=0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void conn_info_t::re_init()
|
void conn_info_t::re_init()
|
||||||
@@ -263,18 +120,24 @@ conv_manager_t::~conv_manager_t()
|
|||||||
}
|
}
|
||||||
void conn_info_t::prepare()
|
void conn_info_t::prepare()
|
||||||
{
|
{
|
||||||
|
assert(blob==0);
|
||||||
blob=new blob_t;
|
blob=new blob_t;
|
||||||
|
if(program_mode==server_mode)
|
||||||
}
|
|
||||||
conn_info_t::conn_info_t(const conn_info_t&b)
|
|
||||||
{
|
|
||||||
//mylog(log_error,"called!!!!!!!!!!!!!\n");
|
|
||||||
*this=b;
|
|
||||||
if(blob!=0)
|
|
||||||
{
|
{
|
||||||
blob=new blob_t(*b.blob);
|
blob->conv_manager.s.additional_clear_function=server_clear_function;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(program_mode==client_mode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
conn_info_t::conn_info_t(const conn_info_t&b)
|
||||||
|
{
|
||||||
|
assert(0==1);
|
||||||
|
//mylog(log_error,"called!!!!!!!!!!!!!\n");
|
||||||
|
}
|
||||||
|
|
||||||
conn_info_t& conn_info_t::operator=(const conn_info_t& b)
|
conn_info_t& conn_info_t::operator=(const conn_info_t& b)
|
||||||
{
|
{
|
||||||
mylog(log_fatal,"not allowed\n");
|
mylog(log_fatal,"not allowed\n");
|
||||||
@@ -311,7 +174,7 @@ conv_manager_t::~conv_manager_t()
|
|||||||
{
|
{
|
||||||
ready_num=0;
|
ready_num=0;
|
||||||
mp.reserve(10007);
|
mp.reserve(10007);
|
||||||
clear_it=mp.begin();
|
//clear_it=mp.begin();
|
||||||
// timer_fd_mp.reserve(10007);
|
// timer_fd_mp.reserve(10007);
|
||||||
const_id_mp.reserve(10007);
|
const_id_mp.reserve(10007);
|
||||||
// udp_fd_mp.reserve(100007);
|
// udp_fd_mp.reserve(100007);
|
||||||
@@ -319,13 +182,13 @@ conv_manager_t::~conv_manager_t()
|
|||||||
//current_ready_ip=0;
|
//current_ready_ip=0;
|
||||||
// current_ready_port=0;
|
// current_ready_port=0;
|
||||||
}
|
}
|
||||||
int conn_manager_t::exist(u32_t ip,uint16_t port)
|
int conn_manager_t::exist(address_t addr)
|
||||||
{
|
{
|
||||||
u64_t u64=0;
|
//u64_t u64=0;
|
||||||
u64=ip;
|
//u64=ip;
|
||||||
u64<<=32u;
|
//u64<<=32u;
|
||||||
u64|=port;
|
//u64|=port;
|
||||||
if(mp.find(u64)!=mp.end())
|
if(mp.find(addr)!=mp.end())
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -341,33 +204,43 @@ conv_manager_t::~conv_manager_t()
|
|||||||
mp[u64];
|
mp[u64];
|
||||||
return 0;
|
return 0;
|
||||||
}*/
|
}*/
|
||||||
conn_info_t *& conn_manager_t::find_insert_p(u32_t ip,uint16_t port) //be aware,the adress may change after rehash
|
conn_info_t *& conn_manager_t::find_insert_p(address_t addr) //be aware,the adress may change after rehash
|
||||||
{
|
{
|
||||||
u64_t u64=0;
|
// u64_t u64=0;
|
||||||
u64=ip;
|
//u64=ip;
|
||||||
u64<<=32u;
|
//u64<<=32u;
|
||||||
u64|=port;
|
//u64|=port;
|
||||||
unordered_map<u64_t,conn_info_t*>::iterator it=mp.find(u64);
|
unordered_map<address_t,conn_info_t*>::iterator it=mp.find(addr);
|
||||||
if(it==mp.end())
|
if(it==mp.end())
|
||||||
{
|
{
|
||||||
mp[u64]=new conn_info_t;
|
mp[addr]=new conn_info_t;
|
||||||
|
//lru.new_key(addr);
|
||||||
}
|
}
|
||||||
return mp[u64];
|
else
|
||||||
|
{
|
||||||
|
//lru.update(addr);
|
||||||
|
}
|
||||||
|
return mp[addr];
|
||||||
}
|
}
|
||||||
conn_info_t & conn_manager_t::find_insert(u32_t ip,uint16_t port) //be aware,the adress may change after rehash
|
conn_info_t & conn_manager_t::find_insert(address_t addr) //be aware,the adress may change after rehash
|
||||||
{
|
{
|
||||||
u64_t u64=0;
|
//u64_t u64=0;
|
||||||
u64=ip;
|
//u64=ip;
|
||||||
u64<<=32u;
|
//u64<<=32u;
|
||||||
u64|=port;
|
//u64|=port;
|
||||||
unordered_map<u64_t,conn_info_t*>::iterator it=mp.find(u64);
|
unordered_map<address_t,conn_info_t*>::iterator it=mp.find(addr);
|
||||||
if(it==mp.end())
|
if(it==mp.end())
|
||||||
{
|
{
|
||||||
mp[u64]=new conn_info_t;
|
mp[addr]=new conn_info_t;
|
||||||
|
//lru.new_key(addr);
|
||||||
}
|
}
|
||||||
return *mp[u64];
|
else
|
||||||
|
{
|
||||||
|
//lru.update(addr);
|
||||||
|
}
|
||||||
|
return *mp[addr];
|
||||||
}
|
}
|
||||||
int conn_manager_t::erase(unordered_map<u64_t,conn_info_t*>::iterator erase_it)
|
int conn_manager_t::erase(unordered_map<address_t,conn_info_t*>::iterator erase_it)
|
||||||
{
|
{
|
||||||
if(erase_it->second->state.server_current_state==server_ready)
|
if(erase_it->second->state.server_current_state==server_ready)
|
||||||
{
|
{
|
||||||
@@ -418,8 +291,8 @@ int conn_manager_t::clear_inactive()
|
|||||||
}
|
}
|
||||||
int conn_manager_t::clear_inactive0()
|
int conn_manager_t::clear_inactive0()
|
||||||
{
|
{
|
||||||
unordered_map<u64_t,conn_info_t*>::iterator it;
|
unordered_map<address_t,conn_info_t*>::iterator it;
|
||||||
unordered_map<u64_t,conn_info_t*>::iterator old_it;
|
unordered_map<address_t,conn_info_t*>::iterator old_it;
|
||||||
|
|
||||||
if(disable_conn_clear) return 0;
|
if(disable_conn_clear) return 0;
|
||||||
|
|
||||||
@@ -452,14 +325,14 @@ int conn_manager_t::clear_inactive0()
|
|||||||
{
|
{
|
||||||
it++;
|
it++;
|
||||||
}
|
}
|
||||||
else if(it->second->blob!=0&&it->second->blob->conv_manager.get_size() >0)
|
else if(it->second->blob!=0&&it->second->blob->conv_manager.s.get_size() >0)
|
||||||
{
|
{
|
||||||
assert(it->second->state.server_current_state==server_ready);
|
assert(it->second->state.server_current_state==server_ready);
|
||||||
it++;
|
it++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mylog(log_info,"[%s:%d]inactive conn cleared \n",my_ntoa(it->second->raw_info.recv_info.src_ip),it->second->raw_info.recv_info.src_port);
|
mylog(log_info,"[%s:%d]inactive conn cleared \n",it->second->raw_info.recv_info.new_src_ip.get_str1(),it->second->raw_info.recv_info.src_port);
|
||||||
old_it=it;
|
old_it=it;
|
||||||
it++;
|
it++;
|
||||||
erase(old_it);
|
erase(old_it);
|
||||||
@@ -467,6 +340,7 @@ int conn_manager_t::clear_inactive0()
|
|||||||
cnt++;
|
cnt++;
|
||||||
}
|
}
|
||||||
clear_it=it;
|
clear_it=it;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -499,7 +373,7 @@ int send_bare(raw_info_t &raw_info,const char* data,int len)//send function with
|
|||||||
memcpy(send_data_buf+sizeof(iv)+sizeof(padding)+1,data,len);
|
memcpy(send_data_buf+sizeof(iv)+sizeof(padding)+1,data,len);
|
||||||
int new_len=len+sizeof(iv)+sizeof(padding)+1;
|
int new_len=len+sizeof(iv)+sizeof(padding)+1;
|
||||||
|
|
||||||
if(my_encrypt(send_data_buf,send_data_buf2,new_len,key)!=0)
|
if(my_encrypt(send_data_buf,send_data_buf2,new_len)!=0)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -515,7 +389,7 @@ int reserved_parse_bare(const char *input,int input_len,char* & data,int & len)
|
|||||||
mylog(log_debug,"input_len <0\n");
|
mylog(log_debug,"input_len <0\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if(my_decrypt(input,recv_data_buf,input_len,key)!=0)
|
if(my_decrypt(input,recv_data_buf,input_len)!=0)
|
||||||
{
|
{
|
||||||
mylog(log_debug,"decrypt_fail in recv bare\n");
|
mylog(log_debug,"decrypt_fail in recv bare\n");
|
||||||
return -1;
|
return -1;
|
||||||
@@ -554,7 +428,7 @@ int recv_bare(raw_info_t &raw_info,char* & data,int & len)//recv function with e
|
|||||||
return reserved_parse_bare(data,len,data,len);
|
return reserved_parse_bare(data,len,data,len);
|
||||||
}
|
}
|
||||||
|
|
||||||
int send_handshake(raw_info_t &raw_info,id_t id1,id_t id2,id_t id3)// a warp for send_bare for sending handshake(this is not tcp handshake) easily
|
int send_handshake(raw_info_t &raw_info,my_id_t id1,my_id_t id2,my_id_t id3)// a warp for send_bare for sending handshake(this is not tcp handshake) easily
|
||||||
{
|
{
|
||||||
packet_info_t &send_info=raw_info.send_info;
|
packet_info_t &send_info=raw_info.send_info;
|
||||||
packet_info_t &recv_info=raw_info.recv_info;
|
packet_info_t &recv_info=raw_info.recv_info;
|
||||||
@@ -595,7 +469,7 @@ int send_safer(conn_info_t &conn_info,char type,const char* data,int len) //saf
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
id_t n_tmp_id=htonl(conn_info.my_id);
|
my_id_t n_tmp_id=htonl(conn_info.my_id);
|
||||||
|
|
||||||
memcpy(send_data_buf,&n_tmp_id,sizeof(n_tmp_id));
|
memcpy(send_data_buf,&n_tmp_id,sizeof(n_tmp_id));
|
||||||
|
|
||||||
@@ -615,7 +489,7 @@ int send_safer(conn_info_t &conn_info,char type,const char* data,int len) //saf
|
|||||||
|
|
||||||
int new_len=len+sizeof(n_seq)+sizeof(n_tmp_id)*2+2;
|
int new_len=len+sizeof(n_seq)+sizeof(n_tmp_id)*2+2;
|
||||||
|
|
||||||
if(my_encrypt(send_data_buf,send_data_buf2,new_len,key)!=0)
|
if(my_encrypt(send_data_buf,send_data_buf2,new_len)!=0)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -642,12 +516,12 @@ int send_data_safer(conn_info_t &conn_info,const char* data,int len,u32_t conv_n
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
int parse_safer(conn_info_t &conn_info,const char * input,int input_len,char &type,char* &data,int &len)//subfunction for recv_safer,allow overlap
|
int reserved_parse_safer(conn_info_t &conn_info,const char * input,int input_len,char &type,char* &data,int &len)//subfunction for recv_safer,allow overlap
|
||||||
{
|
{
|
||||||
static char recv_data_buf[buf_len];
|
static char recv_data_buf[buf_len];
|
||||||
|
|
||||||
// char *recv_data_buf=recv_data_buf0; //fix strict alias warning
|
// char *recv_data_buf=recv_data_buf0; //fix strict alias warning
|
||||||
if(my_decrypt(input,recv_data_buf,input_len,key)!=0)
|
if(my_decrypt(input,recv_data_buf,input_len)!=0)
|
||||||
{
|
{
|
||||||
//printf("decrypt fail\n");
|
//printf("decrypt fail\n");
|
||||||
return -1;
|
return -1;
|
||||||
@@ -657,18 +531,18 @@ int parse_safer(conn_info_t &conn_info,const char * input,int input_len,char &ty
|
|||||||
|
|
||||||
//char *a=recv_data_buf;
|
//char *a=recv_data_buf;
|
||||||
//id_t h_oppiste_id= ntohl ( *((id_t * )(recv_data_buf)) );
|
//id_t h_oppiste_id= ntohl ( *((id_t * )(recv_data_buf)) );
|
||||||
id_t h_oppsite_id;
|
my_id_t h_oppsite_id;
|
||||||
memcpy(&h_oppsite_id,recv_data_buf,sizeof(h_oppsite_id));
|
memcpy(&h_oppsite_id,recv_data_buf,sizeof(h_oppsite_id));
|
||||||
h_oppsite_id=ntohl(h_oppsite_id);
|
h_oppsite_id=ntohl(h_oppsite_id);
|
||||||
|
|
||||||
//id_t h_my_id= ntohl ( *((id_t * )(recv_data_buf+sizeof(id_t))) );
|
//id_t h_my_id= ntohl ( *((id_t * )(recv_data_buf+sizeof(id_t))) );
|
||||||
id_t h_my_id;
|
my_id_t h_my_id;
|
||||||
memcpy(&h_my_id,recv_data_buf+sizeof(id_t),sizeof(h_my_id));
|
memcpy(&h_my_id,recv_data_buf+sizeof(my_id_t),sizeof(h_my_id));
|
||||||
h_my_id=ntohl(h_my_id);
|
h_my_id=ntohl(h_my_id);
|
||||||
|
|
||||||
//anti_replay_seq_t h_seq= ntoh64 ( *((anti_replay_seq_t * )(recv_data_buf +sizeof(id_t) *2 )) );
|
//anti_replay_seq_t h_seq= ntoh64 ( *((anti_replay_seq_t * )(recv_data_buf +sizeof(id_t) *2 )) );
|
||||||
anti_replay_seq_t h_seq;
|
anti_replay_seq_t h_seq;
|
||||||
memcpy(&h_seq,recv_data_buf +sizeof(id_t) *2 ,sizeof(h_seq));
|
memcpy(&h_seq,recv_data_buf +sizeof(my_id_t) *2 ,sizeof(h_seq));
|
||||||
h_seq=ntoh64(h_seq);
|
h_seq=ntoh64(h_seq);
|
||||||
|
|
||||||
if(h_oppsite_id!=conn_info.oppsite_id||h_my_id!=conn_info.my_id)
|
if(h_oppsite_id!=conn_info.oppsite_id||h_my_id!=conn_info.my_id)
|
||||||
@@ -683,8 +557,8 @@ int parse_safer(conn_info_t &conn_info,const char * input,int input_len,char &ty
|
|||||||
}
|
}
|
||||||
|
|
||||||
//printf("recv _len %d\n ",recv_len);
|
//printf("recv _len %d\n ",recv_len);
|
||||||
data=recv_data_buf+sizeof(anti_replay_seq_t)+sizeof(id_t)*2;
|
data=recv_data_buf+sizeof(anti_replay_seq_t)+sizeof(my_id_t)*2;
|
||||||
len=input_len-(sizeof(anti_replay_seq_t)+sizeof(id_t)*2 );
|
len=input_len-(sizeof(anti_replay_seq_t)+sizeof(my_id_t)*2 );
|
||||||
|
|
||||||
|
|
||||||
if(data[0]!='h'&&data[0]!='d')
|
if(data[0]!='h'&&data[0]!='d')
|
||||||
@@ -738,7 +612,7 @@ int recv_safer(conn_info_t &conn_info,char &type,char* &data,int &len)///safer t
|
|||||||
|
|
||||||
if(recv_raw0(conn_info.raw_info,recv_data,recv_len)!=0) return -1;
|
if(recv_raw0(conn_info.raw_info,recv_data,recv_len)!=0) return -1;
|
||||||
|
|
||||||
return parse_safer(conn_info,recv_data,recv_len,type,data,len);
|
return reserved_parse_safer(conn_info,recv_data,recv_len,type,data,len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void server_clear_function(u64_t u64)//used in conv_manager in server mode.for server we have to use one udp fd for one conv(udp connection),
|
void server_clear_function(u64_t u64)//used in conv_manager in server mode.for server we have to use one udp fd for one conv(udp connection),
|
||||||
|
243
connection.h
243
connection.h
@@ -16,6 +16,8 @@ extern int disable_anti_replay;
|
|||||||
#include "network.h"
|
#include "network.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
|
||||||
|
const int disable_conv_clear=0;//a udp connection in the multiplexer is called conversation in this program,conv for short.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct anti_replay_t //its for anti replay attack,similar to openvpn/ipsec 's anti replay window
|
struct anti_replay_t //its for anti replay attack,similar to openvpn/ipsec 's anti replay window
|
||||||
@@ -30,24 +32,174 @@ struct anti_replay_t //its for anti replay attack,similar to openvpn/ipsec 's a
|
|||||||
int is_vaild(u64_t seq);
|
int is_vaild(u64_t seq);
|
||||||
};//anti_replay;
|
};//anti_replay;
|
||||||
|
|
||||||
|
void server_clear_function(u64_t u64);
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
template <class T>
|
||||||
struct conv_manager_t // manage the udp connections
|
struct conv_manager_t // manage the udp connections
|
||||||
{
|
{
|
||||||
//typedef hash_map map;
|
//typedef hash_map map;
|
||||||
unordered_map<u64_t,u32_t> u64_to_conv; //conv and u64 are both supposed to be uniq
|
unordered_map<T,u32_t> data_to_conv; //conv and u64 are both supposed to be uniq
|
||||||
unordered_map<u32_t,u64_t> conv_to_u64;
|
unordered_map<u32_t,T> conv_to_data;
|
||||||
|
|
||||||
unordered_map<u32_t,u64_t> conv_last_active_time;
|
lru_collector_t<u32_t> lru;
|
||||||
|
//unordered_map<u32_t,u64_t> conv_last_active_time;
|
||||||
|
|
||||||
unordered_map<u32_t,u64_t>::iterator clear_it;
|
//unordered_map<u32_t,u64_t>::iterator clear_it;
|
||||||
|
|
||||||
unordered_map<u32_t,u64_t>::iterator it;
|
void (*additional_clear_function)(T data) =0;
|
||||||
unordered_map<u32_t,u64_t>::iterator old_it;
|
|
||||||
|
|
||||||
//void (*clear_function)(uint64_t u64) ;
|
|
||||||
|
|
||||||
long long last_clear_time;
|
long long last_clear_time;
|
||||||
|
|
||||||
|
conv_manager_t()
|
||||||
|
{
|
||||||
|
//clear_it=conv_last_active_time.begin();
|
||||||
|
long long last_clear_time=0;
|
||||||
|
additional_clear_function=0;
|
||||||
|
}
|
||||||
|
~conv_manager_t()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
int get_size()
|
||||||
|
{
|
||||||
|
return conv_to_data.size();
|
||||||
|
}
|
||||||
|
void reserve()
|
||||||
|
{
|
||||||
|
data_to_conv.reserve(10007);
|
||||||
|
conv_to_data.reserve(10007);
|
||||||
|
//conv_last_active_time.reserve(10007);
|
||||||
|
|
||||||
|
lru.mp.reserve(10007);
|
||||||
|
}
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
if(disable_conv_clear) return ;
|
||||||
|
|
||||||
|
if(additional_clear_function!=0)
|
||||||
|
{
|
||||||
|
for(auto it=conv_to_data.begin();it!=conv_to_data.end();it++)
|
||||||
|
{
|
||||||
|
//int fd=int((it->second<<32u)>>32u);
|
||||||
|
additional_clear_function( it->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data_to_conv.clear();
|
||||||
|
conv_to_data.clear();
|
||||||
|
|
||||||
|
lru.clear();
|
||||||
|
//conv_last_active_time.clear();
|
||||||
|
|
||||||
|
//clear_it=conv_last_active_time.begin();
|
||||||
|
|
||||||
|
}
|
||||||
|
u32_t get_new_conv()
|
||||||
|
{
|
||||||
|
u32_t conv=get_true_random_number_nz();
|
||||||
|
while(conv_to_data.find(conv)!=conv_to_data.end())
|
||||||
|
{
|
||||||
|
conv=get_true_random_number_nz();
|
||||||
|
}
|
||||||
|
return conv;
|
||||||
|
}
|
||||||
|
int is_conv_used(u32_t conv)
|
||||||
|
{
|
||||||
|
return conv_to_data.find(conv)!=conv_to_data.end();
|
||||||
|
}
|
||||||
|
int is_data_used(T data)
|
||||||
|
{
|
||||||
|
return data_to_conv.find(data)!=data_to_conv.end();
|
||||||
|
}
|
||||||
|
u32_t find_conv_by_data(T data)
|
||||||
|
{
|
||||||
|
return data_to_conv[data];
|
||||||
|
}
|
||||||
|
T find_data_by_conv(u32_t conv)
|
||||||
|
{
|
||||||
|
return conv_to_data[conv];
|
||||||
|
}
|
||||||
|
int update_active_time(u32_t conv)
|
||||||
|
{
|
||||||
|
//return conv_last_active_time[conv]=get_current_time();
|
||||||
|
lru.update(conv);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int insert_conv(u32_t conv,T data)
|
||||||
|
{
|
||||||
|
data_to_conv[data]=conv;
|
||||||
|
conv_to_data[conv]=data;
|
||||||
|
//conv_last_active_time[conv]=get_current_time();
|
||||||
|
lru.new_key(conv);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int erase_conv(u32_t conv)
|
||||||
|
{
|
||||||
|
if(disable_conv_clear) return 0;
|
||||||
|
T data=conv_to_data[conv];
|
||||||
|
if(additional_clear_function!=0)
|
||||||
|
{
|
||||||
|
additional_clear_function(data);
|
||||||
|
}
|
||||||
|
conv_to_data.erase(conv);
|
||||||
|
data_to_conv.erase(data);
|
||||||
|
//conv_last_active_time.erase(conv);
|
||||||
|
lru.erase(conv);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int clear_inactive(char * info=0)
|
||||||
|
{
|
||||||
|
if(get_current_time()-last_clear_time>conv_clear_interval)
|
||||||
|
{
|
||||||
|
last_clear_time=get_current_time();
|
||||||
|
return clear_inactive0(info);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int clear_inactive0(char * info)
|
||||||
|
{
|
||||||
|
if(disable_conv_clear) return 0;
|
||||||
|
|
||||||
|
|
||||||
|
unordered_map<u32_t,u64_t>::iterator it;
|
||||||
|
unordered_map<u32_t,u64_t>::iterator old_it;
|
||||||
|
|
||||||
|
//map<uint32_t,uint64_t>::iterator it;
|
||||||
|
int cnt=0;
|
||||||
|
//it=clear_it;
|
||||||
|
int size=lru.size();
|
||||||
|
int num_to_clean=size/conv_clear_ratio+conv_clear_min; //clear 1/10 each time,to avoid latency glitch
|
||||||
|
|
||||||
|
num_to_clean=min(num_to_clean,size);
|
||||||
|
|
||||||
|
my_time_t current_time=get_current_time();
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
if(cnt>=num_to_clean) break;
|
||||||
|
if(lru.empty()) break;
|
||||||
|
|
||||||
|
u32_t conv;
|
||||||
|
my_time_t ts=lru.peek_back(conv);
|
||||||
|
|
||||||
|
if(current_time- ts < conv_timeout) break;
|
||||||
|
|
||||||
|
erase_conv(conv);
|
||||||
|
if(info==0)
|
||||||
|
{
|
||||||
|
mylog(log_info,"conv %x cleared\n",conv);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mylog(log_info,"[%s]conv %x cleared\n",info,conv);
|
||||||
|
}
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
conv_manager_t();
|
conv_manager_t();
|
||||||
~conv_manager_t();
|
~conv_manager_t();
|
||||||
int get_size();
|
int get_size();
|
||||||
@@ -55,20 +207,50 @@ struct conv_manager_t // manage the udp connections
|
|||||||
void clear();
|
void clear();
|
||||||
u32_t get_new_conv();
|
u32_t get_new_conv();
|
||||||
int is_conv_used(u32_t conv);
|
int is_conv_used(u32_t conv);
|
||||||
int is_u64_used(u64_t u64);
|
int is_u64_used(T u64);
|
||||||
u32_t find_conv_by_u64(u64_t u64);
|
u32_t find_conv_by_u64(T u64);
|
||||||
u64_t find_u64_by_conv(u32_t conv);
|
T find_u64_by_conv(u32_t conv);
|
||||||
int update_active_time(u32_t conv);
|
int update_active_time(u32_t conv);
|
||||||
int insert_conv(u32_t conv,u64_t u64);
|
int insert_conv(u32_t conv,T u64);
|
||||||
int erase_conv(u32_t conv);
|
int erase_conv(u32_t conv);
|
||||||
int clear_inactive(char * ip_port=0);
|
int clear_inactive(char * ip_port=0);
|
||||||
int clear_inactive0(char * ip_port);
|
int clear_inactive0(char * ip_port);*/
|
||||||
};//g_conv_manager;
|
};//g_conv_manager;
|
||||||
|
|
||||||
struct blob_t //used in conn_info_t. conv_manager_t and anti_replay_t are costly data structures ,we dont allocate them until its necessary
|
struct blob_t:not_copy_able_t //used in conn_info_t.
|
||||||
{
|
{
|
||||||
conv_manager_t conv_manager;
|
union tmp_union_t//conv_manager_t is here to avoid copying when a connection is recovered
|
||||||
anti_replay_t anti_replay;
|
{
|
||||||
|
conv_manager_t<address_t> c;
|
||||||
|
conv_manager_t<u64_t> s;
|
||||||
|
//avoid templates here and there, avoid pointer and type cast
|
||||||
|
tmp_union_t()
|
||||||
|
{
|
||||||
|
if(program_mode==client_mode)
|
||||||
|
{
|
||||||
|
new( &c ) conv_manager_t<address_t>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(program_mode==server_mode);
|
||||||
|
new( &s ) conv_manager_t<u64_t>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
~tmp_union_t()
|
||||||
|
{
|
||||||
|
if(program_mode==client_mode)
|
||||||
|
{
|
||||||
|
c.~conv_manager_t<address_t>();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(program_mode==server_mode);
|
||||||
|
s.~conv_manager_t<u64_t>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}conv_manager;
|
||||||
|
|
||||||
|
anti_replay_t anti_replay;//anti_replay_t is here bc its huge,its allocation is delayed.
|
||||||
};
|
};
|
||||||
struct conn_info_t //stores info for a raw connection.for client ,there is only one connection,for server there can be thousand of connection since server can
|
struct conn_info_t //stores info for a raw connection.for client ,there is only one connection,for server there can be thousand of connection since server can
|
||||||
//handle multiple clients
|
//handle multiple clients
|
||||||
@@ -81,13 +263,14 @@ struct conn_info_t //stores info for a raw connection.for client ,there is o
|
|||||||
u64_t last_hb_recv_time;
|
u64_t last_hb_recv_time;
|
||||||
//long long last_resent_time;
|
//long long last_resent_time;
|
||||||
|
|
||||||
id_t my_id;
|
my_id_t my_id;
|
||||||
id_t oppsite_id;
|
my_id_t oppsite_id;
|
||||||
|
|
||||||
|
|
||||||
fd64_t timer_fd64;
|
fd64_t timer_fd64;
|
||||||
|
fd64_t udp_fd64;
|
||||||
|
|
||||||
id_t oppsite_const_id;
|
my_id_t oppsite_const_id;
|
||||||
|
|
||||||
blob_t *blob;
|
blob_t *blob;
|
||||||
|
|
||||||
@@ -119,16 +302,18 @@ struct conn_manager_t //manager for connections. for client,we dont need conn_m
|
|||||||
//unordered_map<int,conn_info_t *> udp_fd_mp; //a bit dirty to used pointer,but can void unordered_map search
|
//unordered_map<int,conn_info_t *> udp_fd_mp; //a bit dirty to used pointer,but can void unordered_map search
|
||||||
//unordered_map<int,conn_info_t *> timer_fd_mp;//we can use pointer here since unordered_map.rehash() uses shallow copy
|
//unordered_map<int,conn_info_t *> timer_fd_mp;//we can use pointer here since unordered_map.rehash() uses shallow copy
|
||||||
|
|
||||||
unordered_map<id_t,conn_info_t *> const_id_mp;
|
unordered_map<my_id_t,conn_info_t *> const_id_mp;
|
||||||
|
|
||||||
unordered_map<u64_t,conn_info_t*> mp; //put it at end so that it de-consturcts first
|
unordered_map<address_t,conn_info_t*> mp; //put it at end so that it de-consturcts first
|
||||||
|
|
||||||
unordered_map<u64_t,conn_info_t*>::iterator clear_it;
|
//lru_collector_t<address_t> lru;
|
||||||
|
|
||||||
|
unordered_map<address_t,conn_info_t*>::iterator clear_it;
|
||||||
|
|
||||||
long long last_clear_time;
|
long long last_clear_time;
|
||||||
|
|
||||||
conn_manager_t();
|
conn_manager_t();
|
||||||
int exist(u32_t ip,uint16_t port);
|
int exist(address_t addr);
|
||||||
/*
|
/*
|
||||||
int insert(uint32_t ip,uint16_t port)
|
int insert(uint32_t ip,uint16_t port)
|
||||||
{
|
{
|
||||||
@@ -139,10 +324,10 @@ struct conn_manager_t //manager for connections. for client,we dont need conn_m
|
|||||||
mp[u64];
|
mp[u64];
|
||||||
return 0;
|
return 0;
|
||||||
}*/
|
}*/
|
||||||
conn_info_t *& find_insert_p(u32_t ip,uint16_t port); //be aware,the adress may change after rehash
|
conn_info_t *& find_insert_p(address_t addr); //be aware,the adress may change after rehash //not true?
|
||||||
conn_info_t & find_insert(u32_t ip,uint16_t port) ; //be aware,the adress may change after rehash
|
conn_info_t & find_insert(address_t addr) ; //be aware,the adress may change after rehash
|
||||||
|
|
||||||
int erase(unordered_map<u64_t,conn_info_t*>::iterator erase_it);
|
int erase(unordered_map<address_t,conn_info_t*>::iterator erase_it);
|
||||||
int clear_inactive();
|
int clear_inactive();
|
||||||
int clear_inactive0();
|
int clear_inactive0();
|
||||||
|
|
||||||
@@ -154,12 +339,12 @@ void server_clear_function(u64_t u64);
|
|||||||
|
|
||||||
int send_bare(raw_info_t &raw_info,const char* data,int len);//send function with encryption but no anti replay,this is used when client and server verifys each other
|
int send_bare(raw_info_t &raw_info,const char* data,int len);//send function with encryption but no anti replay,this is used when client and server verifys each other
|
||||||
//you have to design the protocol carefully, so that you wont be affect by relay attack
|
//you have to design the protocol carefully, so that you wont be affect by relay attack
|
||||||
int reserved_parse_bare(const char *input,int input_len,char* & data,int & len); // a sub function used in recv_bare
|
//int reserved_parse_bare(const char *input,int input_len,char* & data,int & len); // a sub function used in recv_bare
|
||||||
int recv_bare(raw_info_t &raw_info,char* & data,int & len);//recv function with encryption but no anti replay,this is used when client and server verifys each other
|
int recv_bare(raw_info_t &raw_info,char* & data,int & len);//recv function with encryption but no anti replay,this is used when client and server verifys each other
|
||||||
//you have to design the protocol carefully, so that you wont be affect by relay attack
|
//you have to design the protocol carefully, so that you wont be affect by relay attack
|
||||||
int send_handshake(raw_info_t &raw_info,id_t id1,id_t id2,id_t id3);// a warp for send_bare for sending handshake(this is not tcp handshake) easily
|
int send_handshake(raw_info_t &raw_info,my_id_t id1,my_id_t id2,my_id_t id3);// a warp for send_bare for sending handshake(this is not tcp handshake) easily
|
||||||
int send_safer(conn_info_t &conn_info,char type,const char* data,int len); //safer transfer function with anti-replay,when mutually verification is done.
|
int send_safer(conn_info_t &conn_info,char type,const char* data,int len); //safer transfer function with anti-replay,when mutually verification is done.
|
||||||
int send_data_safer(conn_info_t &conn_info,const char* data,int len,u32_t conv_num);//a wrap for send_safer for transfer data.
|
int send_data_safer(conn_info_t &conn_info,const char* data,int len,u32_t conv_num);//a wrap for send_safer for transfer data.
|
||||||
int parse_safer(conn_info_t &conn_info,const char * input,int input_len,char &type,char* &data,int &len);//subfunction for recv_safer,allow overlap
|
//int reserved_parse_safer(conn_info_t &conn_info,const char * input,int input_len,char &type,char* &data,int &len);//subfunction for recv_safer,allow overlap
|
||||||
int recv_safer(conn_info_t &conn_info,char &type,char* &data,int &len);///safer transfer function with anti-replay,when mutually verification is done.
|
int recv_safer(conn_info_t &conn_info,char &type,char* &data,int &len);///safer transfer function with anti-replay,when mutually verification is done.
|
||||||
#endif /* CONNECTION_H_ */
|
#endif /* CONNECTION_H_ */
|
||||||
|
@@ -10,6 +10,8 @@ udp2raw tunnel,通过raw socket给UDP包加上TCP或ICMP header,进而绕过
|
|||||||
|
|
||||||
[udp2raw+finalspeed step_by_step教程](finalspeed_step_by_step.md)
|
[udp2raw+finalspeed step_by_step教程](finalspeed_step_by_step.md)
|
||||||
|
|
||||||
|
[udp2raw wiki](https://github.com/wangyu-/udp2raw-tunnel/wiki)
|
||||||
|
|
||||||
**提示:**
|
**提示:**
|
||||||
|
|
||||||
udp2raw不是加速器,只是一个帮助你绕过UDP限制的工具。如果你需要UDP加速器,请看UDPspeeder。
|
udp2raw不是加速器,只是一个帮助你绕过UDP限制的工具。如果你需要UDP加速器,请看UDPspeeder。
|
||||||
@@ -24,13 +26,13 @@ Release中提供了`amd64`、`x86`、`arm`、`mips_be`、`mips_le`的预编译bi
|
|||||||
|
|
||||||
##### 对于windows和mac用户:
|
##### 对于windows和mac用户:
|
||||||
|
|
||||||
在虚拟机中可以稳定使用(udp2raw跑在Linux里,其他应用照常跑在window里;确保虚拟机网卡工作在桥接模式)。可以使用[这个](https://github.com/wangyu-/udp2raw-tunnel/releases/download/20171108.0/lede-17.01.2-x86_virtual_machine_image.zip)虚拟机镜像,大小只有7.5mb,免去在虚拟机里装系统的麻烦;虚拟机自带ssh server,可以scp拷贝文件,可以ssh进去,可以复制粘贴,root密码123456。
|
可以用[这个repo](https://github.com/wangyu-/udp2raw-multiplatform)里的udp2raw,原生运行。
|
||||||
|
|
||||||
如果你的网络不允许桥接,也是有办法用的,具体方法请看wiki。
|
<del>可以把udp2raw运行在虚拟机上(网络必须是桥接模式)。可以参考: https://github.com/wangyu-/udp2raw-tunnel/wiki/在windows-mac上运行udp2raw客户端,带图形界面 </del>
|
||||||
|
|
||||||
##### 对于ios和游戏主机用户:
|
##### 对于ios和游戏主机用户:
|
||||||
|
|
||||||
可以把udp2raw运行在局域网的其他机器上。最好的办法是买个能刷OpenWrt/LEDE/梅林的路由器,把udp2raw运行在路由器上。
|
可以把udp2raw运行在局域网的其他机器/虚拟机上。最好的办法是买个能刷OpenWrt/LEDE/梅林的路由器,把udp2raw运行在路由器上。
|
||||||
|
|
||||||
# 功能特性
|
# 功能特性
|
||||||
### 把udp流量伪装成tcp /icmp
|
### 把udp流量伪装成tcp /icmp
|
||||||
@@ -39,15 +41,11 @@ Release中提供了`amd64`、`x86`、`arm`、`mips_be`、`mips_le`的预编译bi
|
|||||||
### 模拟TCP3次握手
|
### 模拟TCP3次握手
|
||||||
模拟TCP3次握手,模拟seq ack过程。另外还模拟了一些tcp option:MSS,sackOk,TS,TS_ack,wscale,用来使流量看起来更像是由普通的linux tcp协议栈发送的。
|
模拟TCP3次握手,模拟seq ack过程。另外还模拟了一些tcp option:MSS,sackOk,TS,TS_ack,wscale,用来使流量看起来更像是由普通的linux tcp协议栈发送的。
|
||||||
|
|
||||||
### 心跳保活、自动重连,连接快速恢复,单向链路失效检测
|
### 心跳保活、自动重连,连接恢复
|
||||||
心跳保活、自动重连,udp2raw重连可以恢复上次的连接,重连后上层连接继续有效,底层掉线上层不掉线。有效解决上层连接断开的问题。 (功能借鉴自[kcptun-raw](https://github.com/Chion82/kcptun-raw))(**就算你拔掉网线重插,或者重新拨号获得新ip,上层应用也不会断线**)
|
心跳保活、自动重连,udp2raw重连可以恢复上次的连接,重连后上层连接继续有效,底层掉线上层不掉线。有效解决上层连接断开的问题。 (功能借鉴自[kcptun-raw](https://github.com/Chion82/kcptun-raw))(**就算你拔掉网线重插,或者重新拨号获得新ip,上层应用也不会断线**)
|
||||||
|
|
||||||
Client能用单倍的超时时间检测到单向链路的失效,不管是上行还是下行,只要有一个方向失效就能被client检测到。重连只需要client发起,就可以立即被server处理,不需要等到server端的连接超时后。
|
|
||||||
|
|
||||||
对于有大量client的情况,对于不同client,server发送的心跳是错开时间发送的,不会因为短时间发送大量的心跳而造成拥塞和延迟抖动。
|
|
||||||
|
|
||||||
### 加密 防重放攻击
|
### 加密 防重放攻击
|
||||||
用aes128cbc加密,md5/crc32做数据完整校验。用类似ipsec/openvpn的 replay window机制来防止重放攻击。
|
用aes128cbc加密(或更弱的xor),hmac-sha1(或更弱的md5/crc32/simple)做数据完整校验。用类似ipsec/openvpn的replay window机制来防止重放攻击。
|
||||||
|
|
||||||
设计目标是,即使攻击者可以监听到tunnel的所有包,可以选择性丢弃tunnel的任意包,可以重放任意包;攻击者也没办法获得tunnel承载的任何数据,也没办法向tunnel的数据流中通过包构造/包重放插入任何数据。
|
设计目标是,即使攻击者可以监听到tunnel的所有包,可以选择性丢弃tunnel的任意包,可以重放任意包;攻击者也没办法获得tunnel承载的任何数据,也没办法向tunnel的数据流中通过包构造/包重放插入任何数据。
|
||||||
|
|
||||||
@@ -62,8 +60,6 @@ NAT 穿透 ,tcp icmp udp模式都支持nat穿透。
|
|||||||
|
|
||||||
支持Openwrt,没有编译依赖,容易编译到任何平台上。
|
支持Openwrt,没有编译依赖,容易编译到任何平台上。
|
||||||
|
|
||||||
epoll实现,高并发,除了回收过期连接外,所有操作的时间复杂度都跟连接数无关。回收过期连接的操做也是柔和进行的,不会因为消耗太多cpu时间造成延迟抖动。
|
|
||||||
|
|
||||||
### 关键词
|
### 关键词
|
||||||
突破udp qos,突破udp屏蔽,openvpn tcp over tcp problem,openvpn over icmp,udp to icmp tunnel,udp to tcp tunnel,udp via icmp,udp via tcp
|
突破udp qos,突破udp屏蔽,openvpn tcp over tcp problem,openvpn over icmp,udp to icmp tunnel,udp to tcp tunnel,udp via icmp,udp via tcp
|
||||||
|
|
||||||
@@ -79,11 +75,13 @@ https://github.com/wangyu-/udp2raw-tunnel/releases
|
|||||||
|
|
||||||
```
|
```
|
||||||
在server端运行:
|
在server端运行:
|
||||||
./udp2raw_amd64 -s -l0.0.0.0:4096 -r 127.0.0.1:7777 -a -k "passwd" --raw-mode faketcp
|
./udp2raw_amd64 -s -l0.0.0.0:4096 -r127.0.0.1:7777 -k "passwd" --raw-mode faketcp --cipher-mode xor -a
|
||||||
|
|
||||||
在client端运行:
|
在client端运行:
|
||||||
./udp2raw_amd64 -c -l0.0.0.0:3333 -r44.55.66.77:4096 -a -k "passwd" --raw-mode faketcp
|
./udp2raw_amd64 -c -l0.0.0.0:3333 -r44.55.66.77:4096 -k "passwd" --raw-mode faketcp --cipher-mode xor -a
|
||||||
```
|
```
|
||||||
|
(以上例子需要用root账号运行。 用非root运行udp2raw需要一些额外的步骤,具体方法请看 [这个](https://github.com/wangyu-/udp2raw-tunnel/wiki/run-udp2raw-as-non-root) 链接。用非root运行更安全)
|
||||||
|
|
||||||
###### Server端输出:
|
###### Server端输出:
|
||||||

|

|
||||||
###### Client端输出:
|
###### Client端输出:
|
||||||
@@ -96,13 +94,11 @@ https://github.com/wangyu-/udp2raw-tunnel/releases
|
|||||||
不论你用udp2raw来加速kcptun还是vpn,为了稳定使用,都需要设置合理的MTU(在kcptun/vpn里设置,而不是在udp2raw里),建议把MTU设置成1200。client和server端都要设置。
|
不论你用udp2raw来加速kcptun还是vpn,为了稳定使用,都需要设置合理的MTU(在kcptun/vpn里设置,而不是在udp2raw里),建议把MTU设置成1200。client和server端都要设置。
|
||||||
|
|
||||||
### 提醒
|
### 提醒
|
||||||
|
`--cipher-mode xor`表示仅使用简单的XOR加密,这样可以节省CPU占用,以免CPU成为速度瓶颈。如果你需要更强的加密,可以去掉此选项,使用默认的AES加密。加密相关的选项见后文的`--cipher-mode`和`--auth-mode`。
|
||||||
|
|
||||||
如果要在anroid上运行,请看[Android简明教程](/doc/android_guide.md)
|
如果要在anroid上运行,请看[Android简明教程](/doc/android_guide.md)
|
||||||
|
|
||||||
如果要在梅林固件的路由器上使用,添加`--lower-level auto` `--keep-rule`
|
`-a`选项会自动添加一条/几条iptables规则,udp2raw必须和相应的iptables规则配合才能稳定工作,一定要注意不要忘了`-a`(这是个常见错误)。 如果你不想让udp2raw自动添加iptables规则,可以自己手动添加相应的iptables规则(看一下`-g`选项),然后以不带`-a`的方式运行udp2raw。
|
||||||
|
|
||||||
如果client和server无法连接,或者连接经常断开,请看一下`--seq-mode`的用法,尝试不同的seq-mode。
|
|
||||||
|
|
||||||
udp2raw可以用非root账号运行,这样更安全。具体方法见:[#26](https://github.com/wangyu-/udp2raw-tunnel/issues/26)
|
|
||||||
|
|
||||||
# 进阶操作说明
|
# 进阶操作说明
|
||||||
|
|
||||||
@@ -113,14 +109,14 @@ git version:6e1df4b39f build date:Oct 24 2017 09:21:15
|
|||||||
repository: https://github.com/wangyu-/udp2raw-tunnel
|
repository: https://github.com/wangyu-/udp2raw-tunnel
|
||||||
|
|
||||||
usage:
|
usage:
|
||||||
run as client : ./this_program -c -l local_listen_ip:local_port -r server_ip:server_port [options]
|
run as client : ./this_program -c -l local_listen_ip:local_port -r server_address:server_port [options]
|
||||||
run as server : ./this_program -s -l server_listen_ip:server_port -r remote_ip:remote_port [options]
|
run as server : ./this_program -s -l server_listen_ip:server_port -r remote_address:remote_port [options]
|
||||||
|
|
||||||
common options,these options must be same on both side:
|
common options,these options must be same on both side:
|
||||||
--raw-mode <string> avaliable values:faketcp(default),udp,icmp
|
--raw-mode <string> avaliable values:faketcp(default),udp,icmp
|
||||||
-k,--key <string> password to gen symetric key,default:"secret key"
|
-k,--key <string> password to gen symetric key,default:"secret key"
|
||||||
--cipher-mode <string> avaliable values:aes128cbc(default),xor,none
|
--cipher-mode <string> avaliable values:aes128cbc(default),xor,none
|
||||||
--auth-mode <string> avaliable values:md5(default),crc32,simple,none
|
--auth-mode <string> avaliable values:hmac_sha1,md5(default),crc32,simple,none
|
||||||
-a,--auto-rule auto add (and delete) iptables rule
|
-a,--auto-rule auto add (and delete) iptables rule
|
||||||
-g,--gen-rule generate iptables rule then exit,so that you can copy and
|
-g,--gen-rule generate iptables rule then exit,so that you can copy and
|
||||||
add it manually.overrides -a
|
add it manually.overrides -a
|
||||||
@@ -164,7 +160,7 @@ other options:
|
|||||||
|
|
||||||
用raw收发udp包也类似,只是内核回复的是icmp unreachable。而用raw 收发icmp,内核会自动回复icmp echo。都需要相应的iptables规则。
|
用raw收发udp包也类似,只是内核回复的是icmp unreachable。而用raw 收发icmp,内核会自动回复icmp echo。都需要相应的iptables规则。
|
||||||
### `--cipher-mode` 和 `--auth-mode`
|
### `--cipher-mode` 和 `--auth-mode`
|
||||||
如果要最大的安全性建议用aes128cbc+md5。如果要运行再路由器上,建议xor+simple。但是注意xor+simple只能骗过防火墙的包检测,不能防止真正的攻击者。
|
如果要最大的安全性建议用aes128cbc+hmac_sha1。如果要运行在路由器上,建议用xor+simple,可以节省CPU。但是注意xor+simple只能骗过防火墙的包检测,不能防止真正的攻击者。
|
||||||
|
|
||||||
### `--seq-mode`
|
### `--seq-mode`
|
||||||
facktcp模式并没有模拟tcp的全部。所以理论上有办法把faketcp和真正的tcp流量区分开来(虽然大部分ISP不太可能做这种程度的包检测)。seq-mode可以改变一些seq ack的行为。如果遇到了连接问题,可以尝试更改。在我这边的移动线路用3种模式都没问题。
|
facktcp模式并没有模拟tcp的全部。所以理论上有办法把faketcp和真正的tcp流量区分开来(虽然大部分ISP不太可能做这种程度的包检测)。seq-mode可以改变一些seq ack的行为。如果遇到了连接问题,可以尝试更改。在我这边的移动线路用3种模式都没问题。
|
||||||
@@ -288,3 +284,9 @@ Transparently tunnel your IP traffic through ICMP echo and reply packets.
|
|||||||
|
|
||||||
https://github.com/DhavalKapil/icmptunnel
|
https://github.com/DhavalKapil/icmptunnel
|
||||||
|
|
||||||
|
# wiki
|
||||||
|
|
||||||
|
更多内容请看 wiki:
|
||||||
|
|
||||||
|
https://github.com/wangyu-/udp2raw-tunnel/wiki
|
||||||
|
|
||||||
|
@@ -1,8 +1,10 @@
|
|||||||
# udp2raw build guide
|
# udp2raw build guide
|
||||||
|
|
||||||
the guide on how to build udp2raw to you own platform
|
the guide on how to build udp2raw
|
||||||
|
|
||||||
## linux platform which supports local compile
|
## Build udp2raw for a specific platform
|
||||||
|
|
||||||
|
### linux platform which supports local compile
|
||||||
such as PC,raspberry pi
|
such as PC,raspberry pi
|
||||||
|
|
||||||
##### install git
|
##### install git
|
||||||
@@ -36,7 +38,7 @@ sudo yum groupinstall 'Development Tools'
|
|||||||
|
|
||||||
run 'make',compilation done. the udp2raw file is the just compiled binary
|
run 'make',compilation done. the udp2raw file is the just compiled binary
|
||||||
|
|
||||||
## platform which needs cross-compile
|
### platform which needs cross-compile
|
||||||
such as openwrt router,run following instructions on your PC
|
such as openwrt router,run following instructions on your PC
|
||||||
|
|
||||||
##### install git
|
##### install git
|
||||||
@@ -74,3 +76,17 @@ cc_cross=/home/wangyu/Desktop/OpenWrt-SDK-15.05-ar71xx-generic_gcc-4.8-linaro_uC
|
|||||||
run `make cross`,the just generated `udp2raw_cross` is the binary,compile done. copy it to your router to run.
|
run `make cross`,the just generated `udp2raw_cross` is the binary,compile done. copy it to your router to run.
|
||||||
|
|
||||||
`make cross` generates non-static binary. If you have any problem on running it,try to compile a static binary by using `make cross2` or `make cross3`.If your toolchain supports static compiling, usually one of them will succeed. The generated file is still named `udp2raw_cross`.
|
`make cross` generates non-static binary. If you have any problem on running it,try to compile a static binary by using `make cross2` or `make cross3`.If your toolchain supports static compiling, usually one of them will succeed. The generated file is still named `udp2raw_cross`.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Build a full release (include all binaries supported in the makefile)
|
||||||
|
|
||||||
|
1. make sure your linux is amd64 version
|
||||||
|
|
||||||
|
2. clone the repo
|
||||||
|
|
||||||
|
3. make sure you have g++ , make sure your g++ support the `-m32` option; make your your have installed libraries for `-m32` option
|
||||||
|
|
||||||
|
4. download https://github.com/wangyu-/files/releases/download/files/toolchains.tar.gz , and extract it to the right position (according to the makefile)
|
||||||
|
|
||||||
|
5. run `make release` inside udp2raw's directory
|
||||||
|
@@ -6,7 +6,9 @@
|
|||||||
### 环境要求
|
### 环境要求
|
||||||
两边的主机都是linux,有root权限。 可以是openwrt路由器或树莓派,也可以是root了的android。
|
两边的主机都是linux,有root权限。 可以是openwrt路由器或树莓派,也可以是root了的android。
|
||||||
|
|
||||||
(windows和mac可以用release里发布的预装了udp2raw的openwrt_x86虚拟机镜像,容量4.4mb,开机即用)
|
在windows/mac上运行udp2raw可以参考这个教程:
|
||||||
|
|
||||||
|
https://github.com/wangyu-/udp2raw-tunnel/wiki/在windows-mac上运行udp2raw客户端,带图形界面
|
||||||
|
|
||||||
|
|
||||||
### 安装
|
### 安装
|
||||||
|
230
encrypt.cpp
230
encrypt.cpp
@@ -1,5 +1,7 @@
|
|||||||
#include "lib/aes.h"
|
#include "lib/aes-common.h"
|
||||||
#include "lib/md5.h"
|
#include "lib/md5.h"
|
||||||
|
#include "lib/pbkdf2-sha1.h"
|
||||||
|
#include "lib/pbkdf2-sha256.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -16,29 +18,80 @@ static int8_t zero_iv[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0};//this prog
|
|||||||
* https://crypto.stackexchange.com/questions/5421/using-cbc-with-a-fixed-iv-and-a-random-first-plaintext-block
|
* https://crypto.stackexchange.com/questions/5421/using-cbc-with-a-fixed-iv-and-a-random-first-plaintext-block
|
||||||
****/
|
****/
|
||||||
|
|
||||||
char key[16];//generated from key_string by md5.
|
char normal_key[16 + 100];//generated from key_string by md5. reserved for compatiblity
|
||||||
/*
|
const int hmac_key_len=64;//generate 512bit long keys, use first n chars when needed
|
||||||
TODO
|
const int cipher_key_len=64;
|
||||||
|
unsigned char hmac_key_encrypt[hmac_key_len + 100]; //key for hmac
|
||||||
|
unsigned char hmac_key_decrypt[hmac_key_len + 100]; //key for hmac
|
||||||
|
unsigned char cipher_key_encrypt[cipher_key_len + 100]; //key for aes etc.
|
||||||
|
unsigned char cipher_key_decrypt[cipher_key_len + 100]; //key for aes etc.
|
||||||
|
|
||||||
Change md5 to HMAC-md5 if necessary.Change padding to PKCS#7 style if necessary.
|
unordered_map<int, const char *> auth_mode_tostring = {{auth_none, "none"}, {auth_md5, "md5"}, {auth_crc32, "crc32"},{auth_simple,"simple"},{auth_hmac_sha1,"hmac_sha1"},};
|
||||||
|
|
||||||
Need someone with cryptography knowledge to help review the encryption method.
|
unordered_map<int, const char *> cipher_mode_tostring={{cipher_none,"none"},{cipher_aes128cfb,"aes128cfb"},{cipher_aes128cbc,"aes128cbc"},{cipher_xor,"xor"},};
|
||||||
|
//TODO aes-gcm
|
||||||
Change them if necessary(I can do this by myself,if it turns out to be necessary).
|
|
||||||
|
|
||||||
github issue:
|
|
||||||
|
|
||||||
https://github.com/wangyu-/udp2raw-tunnel/issues/17
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
unordered_map<int, const char *> auth_mode_tostring = {{auth_none, "none"}, {auth_md5, "md5"}, {auth_crc32, "crc32"},{auth_simple,"simple"}};
|
|
||||||
unordered_map<int, const char *> cipher_mode_tostring={{cipher_none,"none"},{cipher_aes128cbc,"aes128cbc"},{cipher_xor,"xor"}};
|
|
||||||
|
|
||||||
auth_mode_t auth_mode=auth_md5;
|
auth_mode_t auth_mode=auth_md5;
|
||||||
cipher_mode_t cipher_mode=cipher_aes128cbc;
|
cipher_mode_t cipher_mode=cipher_aes128cbc;
|
||||||
|
int is_hmac_used=0;
|
||||||
|
|
||||||
|
//TODO key negotiation and forward secrecy
|
||||||
|
|
||||||
|
int my_init_keys(const char * user_passwd,int is_client)
|
||||||
|
{
|
||||||
|
char tmp[1000]="";
|
||||||
|
int len=strlen(user_passwd);
|
||||||
|
|
||||||
|
strcat(tmp,user_passwd);
|
||||||
|
|
||||||
|
strcat(tmp,"key1");
|
||||||
|
|
||||||
|
md5((uint8_t*)tmp,strlen(tmp),(uint8_t*)normal_key);
|
||||||
|
|
||||||
|
if(auth_mode==auth_hmac_sha1)
|
||||||
|
is_hmac_used=1;
|
||||||
|
if(is_hmac_used)
|
||||||
|
{
|
||||||
|
unsigned char salt[400]="";
|
||||||
|
char salt_text[400]="udp2raw_salt1";
|
||||||
|
md5((uint8_t*)(salt_text),strlen(salt_text),salt); //TODO different salt per session
|
||||||
|
|
||||||
|
unsigned char pbkdf2_output1[400]="";
|
||||||
|
PKCS5_PBKDF2_HMAC_SHA256((uint8_t*)user_passwd,len,salt,16,10000, 32,pbkdf2_output1); //TODO argon2 ?
|
||||||
|
|
||||||
|
//unsigned char pbkdf2_output2[400]="";
|
||||||
|
//PKCS5_PBKDF2_HMAC_SHA256(pbkdf2_output1,32,0,0,1, hmac_key_len*2+cipher_key_len*2,pbkdf2_output2); //stretch it
|
||||||
|
|
||||||
|
const char *info_hmac_encrypt="hmac_key server-->client";
|
||||||
|
const char *info_hmac_decrypt="hmac_key client-->server";
|
||||||
|
const char *info_cipher_encrypt="cipher_key server-->client";
|
||||||
|
const char *info_cipher_decrypt="cipher_key client-->server";
|
||||||
|
|
||||||
|
if(is_client)
|
||||||
|
{
|
||||||
|
const char *tmp;
|
||||||
|
tmp=info_hmac_encrypt; info_hmac_encrypt=info_hmac_decrypt;info_hmac_decrypt=tmp;
|
||||||
|
tmp=info_cipher_encrypt; info_cipher_encrypt=info_cipher_decrypt;info_cipher_decrypt=tmp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//nop
|
||||||
|
}
|
||||||
|
|
||||||
|
assert( hkdf_sha256_expand( pbkdf2_output1,32, (unsigned char *)info_cipher_encrypt,strlen(info_cipher_encrypt), cipher_key_encrypt, cipher_key_len ) ==0);
|
||||||
|
assert( hkdf_sha256_expand( pbkdf2_output1,32, (unsigned char *)info_cipher_decrypt,strlen(info_cipher_decrypt), cipher_key_decrypt, cipher_key_len ) ==0);
|
||||||
|
assert( hkdf_sha256_expand( pbkdf2_output1,32, (unsigned char *)info_hmac_encrypt,strlen(info_hmac_encrypt), hmac_key_encrypt, hmac_key_len ) ==0);
|
||||||
|
assert( hkdf_sha256_expand( pbkdf2_output1,32, (unsigned char *)info_hmac_decrypt,strlen(info_hmac_decrypt), hmac_key_decrypt, hmac_key_len ) ==0);
|
||||||
|
}
|
||||||
|
|
||||||
|
print_binary_chars(normal_key,16);
|
||||||
|
print_binary_chars((char *)hmac_key_encrypt,hmac_key_len);
|
||||||
|
print_binary_chars((char *)hmac_key_decrypt,hmac_key_len);
|
||||||
|
print_binary_chars((char *)cipher_key_encrypt,cipher_key_len);
|
||||||
|
print_binary_chars((char *)cipher_key_decrypt,cipher_key_len);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* this function comes from http://www.hackersdelight.org/hdcodetxt/crc.c.txt
|
* this function comes from http://www.hackersdelight.org/hdcodetxt/crc.c.txt
|
||||||
*/
|
*/
|
||||||
@@ -103,6 +156,37 @@ int auth_md5_cal(const char *data,char * output,int &len)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int auth_hmac_sha1_cal(const char *data,char * output,int &len)
|
||||||
|
{
|
||||||
|
mylog(log_trace,"auth_hmac_sha1_cal() is called\n");
|
||||||
|
memcpy(output,data,len);//TODO inefficient code
|
||||||
|
sha1_hmac(hmac_key_encrypt, 20, (const unsigned char *)data, len,(unsigned char *)(output+len));
|
||||||
|
//use key len of 20 instead of hmac_key_len, "extra length would not significantly increase the function strength" (rfc2104)
|
||||||
|
len+=20;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int auth_hmac_sha1_verify(const char *data,int &len)
|
||||||
|
{
|
||||||
|
mylog(log_trace,"auth_hmac_sha1_verify() is called\n");
|
||||||
|
if(len<20)
|
||||||
|
{
|
||||||
|
mylog(log_trace,"auth_hmac_sha1_verify len<20\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
char res[20];
|
||||||
|
|
||||||
|
sha1_hmac(hmac_key_decrypt, 20, (const unsigned char *)data, len-20,(unsigned char *)(res));
|
||||||
|
|
||||||
|
if(memcmp(res,data+len-20,20)!=0)
|
||||||
|
{
|
||||||
|
mylog(log_trace,"auth_hmac_sha1 check failed\n");
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
len-=20;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int auth_crc32_cal(const char *data,char * output,int &len)
|
int auth_crc32_cal(const char *data,char * output,int &len)
|
||||||
{
|
{
|
||||||
memcpy(output,data,len);//TODO inefficient code
|
memcpy(output,data,len);//TODO inefficient code
|
||||||
@@ -192,7 +276,8 @@ int padding(char *data ,int &data_len,int padding_num)
|
|||||||
{
|
{
|
||||||
data_len= (data_len/padding_num)*padding_num+padding_num;
|
data_len= (data_len/padding_num)*padding_num+padding_num;
|
||||||
}
|
}
|
||||||
data[data_len-1]= (data_len-old_len);
|
unsigned char * p= (unsigned char *)&data[data_len-1];
|
||||||
|
*p= (data_len-old_len);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,6 +320,23 @@ int cipher_aes128cbc_encrypt(const char *data,char *output,int &len,char * key)
|
|||||||
AES_CBC_encrypt_buffer((unsigned char *)output,(unsigned char *)buf,len,(unsigned char *)key,(unsigned char *)zero_iv);
|
AES_CBC_encrypt_buffer((unsigned char *)output,(unsigned char *)buf,len,(unsigned char *)key,(unsigned char *)zero_iv);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
int cipher_aes128cfb_encrypt(const char *data,char *output,int &len,char * key)
|
||||||
|
{
|
||||||
|
static int first_time=1;
|
||||||
|
if(aes_key_optimize)
|
||||||
|
{
|
||||||
|
if(first_time==0) key=0;
|
||||||
|
else first_time=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char buf[buf_len];
|
||||||
|
memcpy(buf,data,len);//TODO inefficient code
|
||||||
|
|
||||||
|
//if(padding(buf,len,16)<0) return -1;
|
||||||
|
|
||||||
|
AES_CFB_encrypt_buffer((unsigned char *)output,(unsigned char *)buf,len,(unsigned char *)key,(unsigned char *)zero_iv);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
int auth_crc32_verify(const char *data,int &len)
|
int auth_crc32_verify(const char *data,int &len)
|
||||||
{
|
{
|
||||||
if(len<int(sizeof(unsigned int)))
|
if(len<int(sizeof(unsigned int)))
|
||||||
@@ -272,6 +374,20 @@ int cipher_aes128cbc_decrypt(const char *data,char *output,int &len,char * key)
|
|||||||
if(de_padding(output,len,16)<0) return -1;
|
if(de_padding(output,len,16)<0) return -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
int cipher_aes128cfb_decrypt(const char *data,char *output,int &len,char * key)
|
||||||
|
{
|
||||||
|
static int first_time=1;
|
||||||
|
if(aes_key_optimize)
|
||||||
|
{
|
||||||
|
if(first_time==0) key=0;
|
||||||
|
else first_time=0;
|
||||||
|
}
|
||||||
|
//if(len%16 !=0) {mylog(log_debug,"len%%16!=0\n");return -1;}
|
||||||
|
//if(len<0) {mylog(log_debug,"len <0\n");return -1;}
|
||||||
|
AES_CFB_decrypt_buffer((unsigned char *)output,(unsigned char *)data,len,(unsigned char *)key,(unsigned char *)zero_iv);
|
||||||
|
//if(de_padding(output,len,16)<0) return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int cipher_none_decrypt(const char *data,char *output,int &len,char * key)
|
int cipher_none_decrypt(const char *data,char *output,int &len,char * key)
|
||||||
{
|
{
|
||||||
@@ -288,8 +404,11 @@ int auth_cal(const char *data,char * output,int &len)
|
|||||||
case auth_md5:return auth_md5_cal(data, output, len);
|
case auth_md5:return auth_md5_cal(data, output, len);
|
||||||
case auth_simple:return auth_simple_cal(data, output, len);
|
case auth_simple:return auth_simple_cal(data, output, len);
|
||||||
case auth_none:return auth_none_cal(data, output, len);
|
case auth_none:return auth_none_cal(data, output, len);
|
||||||
default: return auth_md5_cal(data,output,len);//default
|
case auth_hmac_sha1:return auth_hmac_sha1_cal(data,output,len);
|
||||||
|
//default: return auth_md5_cal(data,output,len);//default;
|
||||||
|
default: assert(0==1);
|
||||||
}
|
}
|
||||||
|
return -1;
|
||||||
|
|
||||||
}
|
}
|
||||||
int auth_verify(const char *data,int &len)
|
int auth_verify(const char *data,int &len)
|
||||||
@@ -301,8 +420,11 @@ int auth_verify(const char *data,int &len)
|
|||||||
case auth_md5:return auth_md5_verify(data, len);
|
case auth_md5:return auth_md5_verify(data, len);
|
||||||
case auth_simple:return auth_simple_verify(data, len);
|
case auth_simple:return auth_simple_verify(data, len);
|
||||||
case auth_none:return auth_none_verify(data, len);
|
case auth_none:return auth_none_verify(data, len);
|
||||||
default: return auth_md5_verify(data,len);//default
|
case auth_hmac_sha1:return auth_hmac_sha1_verify(data,len);
|
||||||
|
//default: return auth_md5_verify(data,len);//default
|
||||||
|
default: assert(0==1);
|
||||||
}
|
}
|
||||||
|
return -1;
|
||||||
|
|
||||||
}
|
}
|
||||||
int cipher_encrypt(const char *data,char *output,int &len,char * key)
|
int cipher_encrypt(const char *data,char *output,int &len,char * key)
|
||||||
@@ -311,11 +433,13 @@ int cipher_encrypt(const char *data,char *output,int &len,char * key)
|
|||||||
switch(cipher_mode)
|
switch(cipher_mode)
|
||||||
{
|
{
|
||||||
case cipher_aes128cbc:return cipher_aes128cbc_encrypt(data,output,len, key);
|
case cipher_aes128cbc:return cipher_aes128cbc_encrypt(data,output,len, key);
|
||||||
|
case cipher_aes128cfb:return cipher_aes128cfb_encrypt(data,output,len, key);
|
||||||
case cipher_xor:return cipher_xor_encrypt(data,output,len, key);
|
case cipher_xor:return cipher_xor_encrypt(data,output,len, key);
|
||||||
case cipher_none:return cipher_none_encrypt(data,output,len, key);
|
case cipher_none:return cipher_none_encrypt(data,output,len, key);
|
||||||
default:return cipher_aes128cbc_encrypt(data,output,len, key);
|
//default:return cipher_aes128cbc_encrypt(data,output,len, key);
|
||||||
|
default: assert(0==1);
|
||||||
}
|
}
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
int cipher_decrypt(const char *data,char *output,int &len,char * key)
|
int cipher_decrypt(const char *data,char *output,int &len,char * key)
|
||||||
{
|
{
|
||||||
@@ -323,46 +447,84 @@ int cipher_decrypt(const char *data,char *output,int &len,char * key)
|
|||||||
switch(cipher_mode)
|
switch(cipher_mode)
|
||||||
{
|
{
|
||||||
case cipher_aes128cbc:return cipher_aes128cbc_decrypt(data,output,len, key);
|
case cipher_aes128cbc:return cipher_aes128cbc_decrypt(data,output,len, key);
|
||||||
|
case cipher_aes128cfb:return cipher_aes128cfb_decrypt(data,output,len, key);
|
||||||
case cipher_xor:return cipher_xor_decrypt(data,output,len, key);
|
case cipher_xor:return cipher_xor_decrypt(data,output,len, key);
|
||||||
case cipher_none:return cipher_none_decrypt(data,output,len, key);
|
case cipher_none:return cipher_none_decrypt(data,output,len, key);
|
||||||
default: return cipher_aes128cbc_decrypt(data,output,len,key);
|
// default: return cipher_aes128cbc_decrypt(data,output,len,key);
|
||||||
|
default: assert(0==1);
|
||||||
}
|
}
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int encrypt_AE(const char *data,char *output,int &len /*,char * key*/)
|
||||||
|
{
|
||||||
|
mylog(log_trace,"encrypt_AE is called\n");
|
||||||
|
char buf[buf_len];
|
||||||
|
char buf2[buf_len];
|
||||||
|
memcpy(buf,data,len);
|
||||||
|
if(cipher_encrypt(buf,buf2,len,(char *)cipher_key_encrypt) !=0) {mylog(log_debug,"cipher_encrypt failed ");return -1;}
|
||||||
|
if(auth_cal(buf2,output,len)!=0) {mylog(log_debug,"auth_cal failed ");return -1;}
|
||||||
|
|
||||||
int my_encrypt(const char *data,char *output,int &len,char * key)
|
//printf("%d %x %x\n",len,(int)(output[0]),(int)(output[1]));
|
||||||
|
//print_binary_chars(output,len);
|
||||||
|
|
||||||
|
//use encrypt-then-MAC scheme
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int decrypt_AE(const char *data,char *output,int &len /*,char * key*/)
|
||||||
|
{
|
||||||
|
mylog(log_trace,"decrypt_AE is called\n");
|
||||||
|
//printf("%d %x %x\n",len,(int)(data[0]),(int)(data[1]));
|
||||||
|
//print_binary_chars(data,len);
|
||||||
|
|
||||||
|
if(auth_verify(data,len)!=0) {mylog(log_debug,"auth_verify failed\n");return -1;}
|
||||||
|
if(cipher_decrypt(data,output,len,(char *)cipher_key_decrypt) !=0) {mylog(log_debug,"cipher_decrypt failed \n"); return -1;}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int my_encrypt(const char *data,char *output,int &len /*,char * key*/)
|
||||||
{
|
{
|
||||||
if(len<0) {mylog(log_trace,"len<0");return -1;}
|
if(len<0) {mylog(log_trace,"len<0");return -1;}
|
||||||
if(len>max_data_len) {mylog(log_warn,"len>max_data_len");return -1;}
|
if(len>max_data_len) {mylog(log_warn,"len>max_data_len");return -1;}
|
||||||
|
|
||||||
|
if(is_hmac_used)
|
||||||
|
return encrypt_AE(data,output,len);
|
||||||
|
|
||||||
|
|
||||||
char buf[buf_len];
|
char buf[buf_len];
|
||||||
char buf2[buf_len];
|
char buf2[buf_len];
|
||||||
memcpy(buf,data,len);
|
memcpy(buf,data,len);
|
||||||
if(auth_cal(buf,buf2,len)!=0) {mylog(log_debug,"auth_cal failed ");return -1;}
|
if(auth_cal(buf,buf2,len)!=0) {mylog(log_debug,"auth_cal failed ");return -1;}
|
||||||
if(cipher_encrypt(buf2,output,len,key) !=0) {mylog(log_debug,"cipher_encrypt failed ");return -1;}
|
if(cipher_encrypt(buf2,output,len,normal_key) !=0) {mylog(log_debug,"cipher_encrypt failed ");return -1;}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int my_decrypt(const char *data,char *output,int &len,char * key)
|
int my_decrypt(const char *data,char *output,int &len /*,char * key*/)
|
||||||
{
|
{
|
||||||
if(len<0) return -1;
|
if(len<0) return -1;
|
||||||
if(len>max_data_len) {mylog(log_warn,"len>max_data_len");return -1;}
|
if(len>max_data_len) {mylog(log_warn,"len>max_data_len");return -1;}
|
||||||
|
|
||||||
if(cipher_decrypt(data,output,len,key) !=0) {mylog(log_debug,"cipher_decrypt failed \n"); return -1;}
|
if(is_hmac_used)
|
||||||
|
return decrypt_AE(data,output,len);
|
||||||
|
|
||||||
|
if(cipher_decrypt(data,output,len,normal_key) !=0) {mylog(log_debug,"cipher_decrypt failed \n"); return -1;}
|
||||||
if(auth_verify(output,len)!=0) {mylog(log_debug,"auth_verify failed\n");return -1;}
|
if(auth_verify(output,len)!=0) {mylog(log_debug,"auth_verify failed\n");return -1;}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int my_encrypt_pesudo_header(uint8_t *data,uint8_t *output,int &len,uint8_t * key,uint8_t *header,int hlen)
|
|
||||||
{
|
|
||||||
|
|
||||||
return 0;
|
int encrypt_AEAD(uint8_t *data,uint8_t *output,int &len,uint8_t * key,uint8_t *header,int hlen)
|
||||||
}
|
|
||||||
int my_decrypt_pesudo_header(uint8_t *data,uint8_t *output,int &len,uint8_t * key,uint8_t *header,int hlen)
|
|
||||||
{
|
{
|
||||||
return 0;
|
//TODO
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int decrypt_AEAD(uint8_t *data,uint8_t *output,int &len,uint8_t * key,uint8_t *header,int hlen)
|
||||||
|
{
|
||||||
|
//TODO
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
14
encrypt.h
14
encrypt.h
@@ -9,25 +9,23 @@
|
|||||||
|
|
||||||
|
|
||||||
//using namespace std;
|
//using namespace std;
|
||||||
|
//extern char key[16];
|
||||||
|
|
||||||
const int aes_key_optimize=1; //if enabled,once you used a key for aes,you cant change it anymore
|
const int aes_key_optimize=1; //if enabled,once you used a key for aes,you cant change it anymore
|
||||||
extern char key[16];
|
|
||||||
|
|
||||||
int my_encrypt(const char *data,char *output,int &len,char * key);
|
int my_init_keys(const char *,int);
|
||||||
int my_decrypt(const char *data,char *output,int &len,char * key);
|
|
||||||
|
|
||||||
int my_encrypt_pesudo_header(uint8_t *data,uint8_t *output,int &len,uint8_t * key,uint8_t *header,int hlen);
|
int my_encrypt(const char *data,char *output,int &len);
|
||||||
int my_decrypt_pesudo_header(uint8_t *data,uint8_t *output,int &len,uint8_t * key,uint8_t *header,int hlen);
|
int my_decrypt(const char *data,char *output,int &len);
|
||||||
|
|
||||||
|
|
||||||
unsigned short csum(const unsigned short *ptr,int nbytes) ;
|
unsigned short csum(const unsigned short *ptr,int nbytes) ;
|
||||||
|
|
||||||
|
|
||||||
enum auth_mode_t {auth_none=0,auth_md5,auth_crc32,auth_simple,auth_end};
|
enum auth_mode_t {auth_none=0,auth_md5,auth_crc32,auth_simple,auth_hmac_sha1,auth_end};
|
||||||
|
|
||||||
|
|
||||||
enum cipher_mode_t {cipher_none=0,cipher_aes128cbc,cipher_xor,cipher_end};
|
enum cipher_mode_t {cipher_none=0,cipher_aes128cbc,cipher_xor,cipher_aes128cfb,cipher_end};
|
||||||
|
|
||||||
|
|
||||||
extern auth_mode_t auth_mode;
|
extern auth_mode_t auth_mode;
|
||||||
|
19
lib/aes-common.h
Executable file
19
lib/aes-common.h
Executable file
@@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* this file comes from https://github.com/kokke/tiny-AES128-C
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
|
//not used
|
||||||
|
//void AES_ECB_encrypt(const uint8_t* input, const uint8_t* key, uint8_t *output, const uint32_t length);
|
||||||
|
//void AES_ECB_decrypt(const uint8_t* input, const uint8_t* key, uint8_t *output, const uint32_t length);
|
||||||
|
|
||||||
|
void AES_CBC_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv);
|
||||||
|
void AES_CBC_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv);
|
||||||
|
|
||||||
|
|
||||||
|
void AES_CFB_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv);
|
||||||
|
void AES_CFB_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv);
|
600
lib/aes.c
600
lib/aes.c
@@ -1,600 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
* this file comes from https://github.com/kokke/tiny-AES128-C
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
This is an implementation of the AES algorithm, specifically ECB and CBC mode.
|
|
||||||
Block size can be chosen in aes.h - available choices are AES128, AES192, AES256.
|
|
||||||
|
|
||||||
The implementation is verified against the test vectors in:
|
|
||||||
National Institute of Standards and Technology Special Publication 800-38A 2001 ED
|
|
||||||
|
|
||||||
ECB-AES128
|
|
||||||
----------
|
|
||||||
|
|
||||||
plain-text:
|
|
||||||
6bc1bee22e409f96e93d7e117393172a
|
|
||||||
ae2d8a571e03ac9c9eb76fac45af8e51
|
|
||||||
30c81c46a35ce411e5fbc1191a0a52ef
|
|
||||||
f69f2445df4f9b17ad2b417be66c3710
|
|
||||||
|
|
||||||
key:
|
|
||||||
2b7e151628aed2a6abf7158809cf4f3c
|
|
||||||
|
|
||||||
resulting cipher
|
|
||||||
3ad77bb40d7a3660a89ecaf32466ef97
|
|
||||||
f5d3d58503b9699de785895a96fdbaaf
|
|
||||||
43b1cd7f598ece23881b00e3ed030688
|
|
||||||
7b0c785e27e8ad3f8223207104725dd4
|
|
||||||
|
|
||||||
|
|
||||||
NOTE: String length must be evenly divisible by 16byte (str_len % 16 == 0)
|
|
||||||
You should pad the end of the string with zeros if this is not the case.
|
|
||||||
For AES192/256 the block size is proportionally larger.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Includes: */
|
|
||||||
/*****************************************************************************/
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h> // CBC mode, for memset
|
|
||||||
#include "aes.h"
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Defines: */
|
|
||||||
/*****************************************************************************/
|
|
||||||
// The number of columns comprising a state in AES. This is a constant in AES. Value=4
|
|
||||||
#define Nb 4
|
|
||||||
#define BLOCKLEN 16 //Block length in bytes AES is 128b block only
|
|
||||||
|
|
||||||
#if defined(AES256) && (AES256 == 1)
|
|
||||||
#define Nk 8
|
|
||||||
#define KEYLEN 32
|
|
||||||
#define Nr 14
|
|
||||||
#define keyExpSize 240
|
|
||||||
#elif defined(AES192) && (AES192 == 1)
|
|
||||||
#define Nk 6
|
|
||||||
#define KEYLEN 24
|
|
||||||
#define Nr 12
|
|
||||||
#define keyExpSize 208
|
|
||||||
#else
|
|
||||||
#define Nk 4 // The number of 32 bit words in a key.
|
|
||||||
#define KEYLEN 16 // Key length in bytes
|
|
||||||
#define Nr 10 // The number of rounds in AES Cipher.
|
|
||||||
#define keyExpSize 176
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// jcallan@github points out that declaring Multiply as a function
|
|
||||||
// reduces code size considerably with the Keil ARM compiler.
|
|
||||||
// See this link for more information: https://github.com/kokke/tiny-AES128-C/pull/3
|
|
||||||
#ifndef MULTIPLY_AS_A_FUNCTION
|
|
||||||
#define MULTIPLY_AS_A_FUNCTION 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Private variables: */
|
|
||||||
/*****************************************************************************/
|
|
||||||
// state - array holding the intermediate results during decryption.
|
|
||||||
typedef uint8_t state_t[4][4];
|
|
||||||
static state_t* state;
|
|
||||||
|
|
||||||
// The array that stores the round keys.
|
|
||||||
static uint8_t RoundKey[keyExpSize];
|
|
||||||
|
|
||||||
// The Key input to the AES Program
|
|
||||||
static const uint8_t* Key;
|
|
||||||
|
|
||||||
#if defined(CBC) && CBC
|
|
||||||
// Initial Vector used only for CBC mode
|
|
||||||
static uint8_t* Iv;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// The lookup-tables are marked const so they can be placed in read-only storage instead of RAM
|
|
||||||
// The numbers below can be computed dynamically trading ROM for RAM -
|
|
||||||
// This can be useful in (embedded) bootloader applications, where ROM is often limited.
|
|
||||||
static const uint8_t sbox[256] = {
|
|
||||||
//0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
||||||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
|
|
||||||
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
|
|
||||||
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
|
|
||||||
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
|
|
||||||
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
|
|
||||||
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
|
|
||||||
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
|
|
||||||
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
|
|
||||||
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
|
|
||||||
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
|
|
||||||
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
|
|
||||||
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
|
|
||||||
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
|
|
||||||
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
|
|
||||||
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
|
|
||||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 };
|
|
||||||
|
|
||||||
static const uint8_t rsbox[256] = {
|
|
||||||
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
|
|
||||||
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
|
|
||||||
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
|
|
||||||
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
|
|
||||||
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
|
|
||||||
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
|
|
||||||
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
|
|
||||||
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
|
|
||||||
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
|
|
||||||
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
|
|
||||||
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
|
|
||||||
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
|
|
||||||
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
|
|
||||||
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
|
|
||||||
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
|
|
||||||
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d };
|
|
||||||
|
|
||||||
// The round constant word array, Rcon[i], contains the values given by
|
|
||||||
// x to th e power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8)
|
|
||||||
static const uint8_t Rcon[11] = {
|
|
||||||
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Jordan Goulder points out in PR #12 (https://github.com/kokke/tiny-AES128-C/pull/12),
|
|
||||||
* that you can remove most of the elements in the Rcon array, because they are unused.
|
|
||||||
*
|
|
||||||
* From Wikipedia's article on the Rijndael key schedule @ https://en.wikipedia.org/wiki/Rijndael_key_schedule#Rcon
|
|
||||||
*
|
|
||||||
* "Only the first some of these constants are actually used – up to rcon[10] for AES-128 (as 11 round keys are needed),
|
|
||||||
* up to rcon[8] for AES-192, up to rcon[7] for AES-256. rcon[0] is not used in AES algorithm."
|
|
||||||
*
|
|
||||||
* ... which is why the full array below has been 'disabled' below.
|
|
||||||
*/
|
|
||||||
#if 0
|
|
||||||
static const uint8_t Rcon[256] = {
|
|
||||||
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
|
|
||||||
0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39,
|
|
||||||
0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a,
|
|
||||||
0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8,
|
|
||||||
0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef,
|
|
||||||
0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc,
|
|
||||||
0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b,
|
|
||||||
0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3,
|
|
||||||
0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94,
|
|
||||||
0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20,
|
|
||||||
0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35,
|
|
||||||
0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f,
|
|
||||||
0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04,
|
|
||||||
0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63,
|
|
||||||
0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd,
|
|
||||||
0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d };
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Private functions: */
|
|
||||||
/*****************************************************************************/
|
|
||||||
static uint8_t getSBoxValue(uint8_t num)
|
|
||||||
{
|
|
||||||
return sbox[num];
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t getSBoxInvert(uint8_t num)
|
|
||||||
{
|
|
||||||
return rsbox[num];
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function produces Nb(Nr+1) round keys. The round keys are used in each round to decrypt the states.
|
|
||||||
static void KeyExpansion(void)
|
|
||||||
{
|
|
||||||
uint32_t i, k;
|
|
||||||
uint8_t tempa[4]; // Used for the column/row operations
|
|
||||||
|
|
||||||
// The first round key is the key itself.
|
|
||||||
for (i = 0; i < Nk; ++i)
|
|
||||||
{
|
|
||||||
RoundKey[(i * 4) + 0] = Key[(i * 4) + 0];
|
|
||||||
RoundKey[(i * 4) + 1] = Key[(i * 4) + 1];
|
|
||||||
RoundKey[(i * 4) + 2] = Key[(i * 4) + 2];
|
|
||||||
RoundKey[(i * 4) + 3] = Key[(i * 4) + 3];
|
|
||||||
}
|
|
||||||
|
|
||||||
// All other round keys are found from the previous round keys.
|
|
||||||
//i == Nk
|
|
||||||
for (; i < Nb * (Nr + 1); ++i)
|
|
||||||
{
|
|
||||||
{
|
|
||||||
tempa[0]=RoundKey[(i-1) * 4 + 0];
|
|
||||||
tempa[1]=RoundKey[(i-1) * 4 + 1];
|
|
||||||
tempa[2]=RoundKey[(i-1) * 4 + 2];
|
|
||||||
tempa[3]=RoundKey[(i-1) * 4 + 3];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i % Nk == 0)
|
|
||||||
{
|
|
||||||
// This function shifts the 4 bytes in a word to the left once.
|
|
||||||
// [a0,a1,a2,a3] becomes [a1,a2,a3,a0]
|
|
||||||
|
|
||||||
// Function RotWord()
|
|
||||||
{
|
|
||||||
k = tempa[0];
|
|
||||||
tempa[0] = tempa[1];
|
|
||||||
tempa[1] = tempa[2];
|
|
||||||
tempa[2] = tempa[3];
|
|
||||||
tempa[3] = k;
|
|
||||||
}
|
|
||||||
|
|
||||||
// SubWord() is a function that takes a four-byte input word and
|
|
||||||
// applies the S-box to each of the four bytes to produce an output word.
|
|
||||||
|
|
||||||
// Function Subword()
|
|
||||||
{
|
|
||||||
tempa[0] = getSBoxValue(tempa[0]);
|
|
||||||
tempa[1] = getSBoxValue(tempa[1]);
|
|
||||||
tempa[2] = getSBoxValue(tempa[2]);
|
|
||||||
tempa[3] = getSBoxValue(tempa[3]);
|
|
||||||
}
|
|
||||||
|
|
||||||
tempa[0] = tempa[0] ^ Rcon[i/Nk];
|
|
||||||
}
|
|
||||||
#if defined(AES256) && (AES256 == 1)
|
|
||||||
if (i % Nk == 4)
|
|
||||||
{
|
|
||||||
// Function Subword()
|
|
||||||
{
|
|
||||||
tempa[0] = getSBoxValue(tempa[0]);
|
|
||||||
tempa[1] = getSBoxValue(tempa[1]);
|
|
||||||
tempa[2] = getSBoxValue(tempa[2]);
|
|
||||||
tempa[3] = getSBoxValue(tempa[3]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
RoundKey[i * 4 + 0] = RoundKey[(i - Nk) * 4 + 0] ^ tempa[0];
|
|
||||||
RoundKey[i * 4 + 1] = RoundKey[(i - Nk) * 4 + 1] ^ tempa[1];
|
|
||||||
RoundKey[i * 4 + 2] = RoundKey[(i - Nk) * 4 + 2] ^ tempa[2];
|
|
||||||
RoundKey[i * 4 + 3] = RoundKey[(i - Nk) * 4 + 3] ^ tempa[3];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function adds the round key to state.
|
|
||||||
// The round key is added to the state by an XOR function.
|
|
||||||
static void AddRoundKey(uint8_t round)
|
|
||||||
{
|
|
||||||
uint8_t i,j;
|
|
||||||
for (i=0;i<4;++i)
|
|
||||||
{
|
|
||||||
for (j = 0; j < 4; ++j)
|
|
||||||
{
|
|
||||||
(*state)[i][j] ^= RoundKey[round * Nb * 4 + i * Nb + j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The SubBytes Function Substitutes the values in the
|
|
||||||
// state matrix with values in an S-box.
|
|
||||||
static void SubBytes(void)
|
|
||||||
{
|
|
||||||
uint8_t i, j;
|
|
||||||
for (i = 0; i < 4; ++i)
|
|
||||||
{
|
|
||||||
for (j = 0; j < 4; ++j)
|
|
||||||
{
|
|
||||||
(*state)[j][i] = getSBoxValue((*state)[j][i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The ShiftRows() function shifts the rows in the state to the left.
|
|
||||||
// Each row is shifted with different offset.
|
|
||||||
// Offset = Row number. So the first row is not shifted.
|
|
||||||
static void ShiftRows(void)
|
|
||||||
{
|
|
||||||
uint8_t temp;
|
|
||||||
|
|
||||||
// Rotate first row 1 columns to left
|
|
||||||
temp = (*state)[0][1];
|
|
||||||
(*state)[0][1] = (*state)[1][1];
|
|
||||||
(*state)[1][1] = (*state)[2][1];
|
|
||||||
(*state)[2][1] = (*state)[3][1];
|
|
||||||
(*state)[3][1] = temp;
|
|
||||||
|
|
||||||
// Rotate second row 2 columns to left
|
|
||||||
temp = (*state)[0][2];
|
|
||||||
(*state)[0][2] = (*state)[2][2];
|
|
||||||
(*state)[2][2] = temp;
|
|
||||||
|
|
||||||
temp = (*state)[1][2];
|
|
||||||
(*state)[1][2] = (*state)[3][2];
|
|
||||||
(*state)[3][2] = temp;
|
|
||||||
|
|
||||||
// Rotate third row 3 columns to left
|
|
||||||
temp = (*state)[0][3];
|
|
||||||
(*state)[0][3] = (*state)[3][3];
|
|
||||||
(*state)[3][3] = (*state)[2][3];
|
|
||||||
(*state)[2][3] = (*state)[1][3];
|
|
||||||
(*state)[1][3] = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t xtime(uint8_t x)
|
|
||||||
{
|
|
||||||
return ((x<<1) ^ (((x>>7) & 1) * 0x1b));
|
|
||||||
}
|
|
||||||
|
|
||||||
// MixColumns function mixes the columns of the state matrix
|
|
||||||
static void MixColumns(void)
|
|
||||||
{
|
|
||||||
uint8_t i;
|
|
||||||
uint8_t Tmp,Tm,t;
|
|
||||||
for (i = 0; i < 4; ++i)
|
|
||||||
{
|
|
||||||
t = (*state)[i][0];
|
|
||||||
Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3] ;
|
|
||||||
Tm = (*state)[i][0] ^ (*state)[i][1] ; Tm = xtime(Tm); (*state)[i][0] ^= Tm ^ Tmp ;
|
|
||||||
Tm = (*state)[i][1] ^ (*state)[i][2] ; Tm = xtime(Tm); (*state)[i][1] ^= Tm ^ Tmp ;
|
|
||||||
Tm = (*state)[i][2] ^ (*state)[i][3] ; Tm = xtime(Tm); (*state)[i][2] ^= Tm ^ Tmp ;
|
|
||||||
Tm = (*state)[i][3] ^ t ; Tm = xtime(Tm); (*state)[i][3] ^= Tm ^ Tmp ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Multiply is used to multiply numbers in the field GF(2^8)
|
|
||||||
#if MULTIPLY_AS_A_FUNCTION
|
|
||||||
static uint8_t Multiply(uint8_t x, uint8_t y)
|
|
||||||
{
|
|
||||||
return (((y & 1) * x) ^
|
|
||||||
((y>>1 & 1) * xtime(x)) ^
|
|
||||||
((y>>2 & 1) * xtime(xtime(x))) ^
|
|
||||||
((y>>3 & 1) * xtime(xtime(xtime(x)))) ^
|
|
||||||
((y>>4 & 1) * xtime(xtime(xtime(xtime(x))))));
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#define Multiply(x, y) \
|
|
||||||
( ((y & 1) * x) ^ \
|
|
||||||
((y>>1 & 1) * xtime(x)) ^ \
|
|
||||||
((y>>2 & 1) * xtime(xtime(x))) ^ \
|
|
||||||
((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ \
|
|
||||||
((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))) \
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// MixColumns function mixes the columns of the state matrix.
|
|
||||||
// The method used to multiply may be difficult to understand for the inexperienced.
|
|
||||||
// Please use the references to gain more information.
|
|
||||||
static void InvMixColumns(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
uint8_t a, b, c, d;
|
|
||||||
for (i = 0; i < 4; ++i)
|
|
||||||
{
|
|
||||||
a = (*state)[i][0];
|
|
||||||
b = (*state)[i][1];
|
|
||||||
c = (*state)[i][2];
|
|
||||||
d = (*state)[i][3];
|
|
||||||
|
|
||||||
(*state)[i][0] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09);
|
|
||||||
(*state)[i][1] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d);
|
|
||||||
(*state)[i][2] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b);
|
|
||||||
(*state)[i][3] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// The SubBytes Function Substitutes the values in the
|
|
||||||
// state matrix with values in an S-box.
|
|
||||||
static void InvSubBytes(void)
|
|
||||||
{
|
|
||||||
uint8_t i,j;
|
|
||||||
for (i = 0; i < 4; ++i)
|
|
||||||
{
|
|
||||||
for (j = 0; j < 4; ++j)
|
|
||||||
{
|
|
||||||
(*state)[j][i] = getSBoxInvert((*state)[j][i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void InvShiftRows(void)
|
|
||||||
{
|
|
||||||
uint8_t temp;
|
|
||||||
|
|
||||||
// Rotate first row 1 columns to right
|
|
||||||
temp = (*state)[3][1];
|
|
||||||
(*state)[3][1] = (*state)[2][1];
|
|
||||||
(*state)[2][1] = (*state)[1][1];
|
|
||||||
(*state)[1][1] = (*state)[0][1];
|
|
||||||
(*state)[0][1] = temp;
|
|
||||||
|
|
||||||
// Rotate second row 2 columns to right
|
|
||||||
temp = (*state)[0][2];
|
|
||||||
(*state)[0][2] = (*state)[2][2];
|
|
||||||
(*state)[2][2] = temp;
|
|
||||||
|
|
||||||
temp = (*state)[1][2];
|
|
||||||
(*state)[1][2] = (*state)[3][2];
|
|
||||||
(*state)[3][2] = temp;
|
|
||||||
|
|
||||||
// Rotate third row 3 columns to right
|
|
||||||
temp = (*state)[0][3];
|
|
||||||
(*state)[0][3] = (*state)[1][3];
|
|
||||||
(*state)[1][3] = (*state)[2][3];
|
|
||||||
(*state)[2][3] = (*state)[3][3];
|
|
||||||
(*state)[3][3] = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Cipher is the main function that encrypts the PlainText.
|
|
||||||
static void Cipher(void)
|
|
||||||
{
|
|
||||||
uint8_t round = 0;
|
|
||||||
|
|
||||||
// Add the First round key to the state before starting the rounds.
|
|
||||||
AddRoundKey(0);
|
|
||||||
|
|
||||||
// There will be Nr rounds.
|
|
||||||
// The first Nr-1 rounds are identical.
|
|
||||||
// These Nr-1 rounds are executed in the loop below.
|
|
||||||
for (round = 1; round < Nr; ++round)
|
|
||||||
{
|
|
||||||
SubBytes();
|
|
||||||
ShiftRows();
|
|
||||||
MixColumns();
|
|
||||||
AddRoundKey(round);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The last round is given below.
|
|
||||||
// The MixColumns function is not here in the last round.
|
|
||||||
SubBytes();
|
|
||||||
ShiftRows();
|
|
||||||
AddRoundKey(Nr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void InvCipher(void)
|
|
||||||
{
|
|
||||||
uint8_t round=0;
|
|
||||||
|
|
||||||
// Add the First round key to the state before starting the rounds.
|
|
||||||
AddRoundKey(Nr);
|
|
||||||
|
|
||||||
// There will be Nr rounds.
|
|
||||||
// The first Nr-1 rounds are identical.
|
|
||||||
// These Nr-1 rounds are executed in the loop below.
|
|
||||||
for (round = (Nr - 1); round > 0; --round)
|
|
||||||
{
|
|
||||||
InvShiftRows();
|
|
||||||
InvSubBytes();
|
|
||||||
AddRoundKey(round);
|
|
||||||
InvMixColumns();
|
|
||||||
}
|
|
||||||
|
|
||||||
// The last round is given below.
|
|
||||||
// The MixColumns function is not here in the last round.
|
|
||||||
InvShiftRows();
|
|
||||||
InvSubBytes();
|
|
||||||
AddRoundKey(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/* Public functions: */
|
|
||||||
/*****************************************************************************/
|
|
||||||
#if defined(ECB) && (ECB == 1)
|
|
||||||
|
|
||||||
|
|
||||||
void AES_ECB_encrypt(const uint8_t* input, const uint8_t* key, uint8_t* output, const uint32_t length)
|
|
||||||
{
|
|
||||||
// Copy input to output, and work in-memory on output
|
|
||||||
memcpy(output, input, length);
|
|
||||||
state = (state_t*)output;
|
|
||||||
|
|
||||||
Key = key;
|
|
||||||
KeyExpansion();
|
|
||||||
|
|
||||||
// The next function call encrypts the PlainText with the Key using AES algorithm.
|
|
||||||
Cipher();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AES_ECB_decrypt(const uint8_t* input, const uint8_t* key, uint8_t *output, const uint32_t length)
|
|
||||||
{
|
|
||||||
// Copy input to output, and work in-memory on output
|
|
||||||
memcpy(output, input, length);
|
|
||||||
state = (state_t*)output;
|
|
||||||
|
|
||||||
// The KeyExpansion routine must be called before encryption.
|
|
||||||
Key = key;
|
|
||||||
KeyExpansion();
|
|
||||||
|
|
||||||
InvCipher();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif // #if defined(ECB) && (ECB == 1)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(CBC) && (CBC == 1)
|
|
||||||
|
|
||||||
|
|
||||||
static void XorWithIv(uint8_t* buf)
|
|
||||||
{
|
|
||||||
uint8_t i;
|
|
||||||
for (i = 0; i < BLOCKLEN; ++i) //WAS for(i = 0; i < KEYLEN; ++i) but the block in AES is always 128bit so 16 bytes!
|
|
||||||
{
|
|
||||||
buf[i] ^= Iv[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AES_CBC_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)
|
|
||||||
{
|
|
||||||
uintptr_t i;
|
|
||||||
uint8_t extra = length % BLOCKLEN; /* Remaining bytes in the last non-full block */
|
|
||||||
|
|
||||||
// Skip the key expansion if key is passed as 0
|
|
||||||
if (0 != key)
|
|
||||||
{
|
|
||||||
Key = key;
|
|
||||||
KeyExpansion();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iv != 0)
|
|
||||||
{
|
|
||||||
Iv = (uint8_t*)iv;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < length; i += BLOCKLEN)
|
|
||||||
{
|
|
||||||
XorWithIv(input);
|
|
||||||
memcpy(output, input, BLOCKLEN);
|
|
||||||
state = (state_t*)output;
|
|
||||||
Cipher();
|
|
||||||
Iv = output;
|
|
||||||
input += BLOCKLEN;
|
|
||||||
output += BLOCKLEN;
|
|
||||||
//printf("Step %d - %d", i/16, i);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (extra)
|
|
||||||
{
|
|
||||||
memcpy(output, input, extra);
|
|
||||||
state = (state_t*)output;
|
|
||||||
Cipher();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AES_CBC_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)
|
|
||||||
{
|
|
||||||
uintptr_t i;
|
|
||||||
uint8_t extra = length % BLOCKLEN; /* Remaining bytes in the last non-full block */
|
|
||||||
|
|
||||||
// Skip the key expansion if key is passed as 0
|
|
||||||
if (0 != key)
|
|
||||||
{
|
|
||||||
Key = key;
|
|
||||||
KeyExpansion();
|
|
||||||
}
|
|
||||||
|
|
||||||
// If iv is passed as 0, we continue to encrypt without re-setting the Iv
|
|
||||||
if (iv != 0)
|
|
||||||
{
|
|
||||||
Iv = (uint8_t*)iv;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < length; i += BLOCKLEN)
|
|
||||||
{
|
|
||||||
memcpy(output, input, BLOCKLEN);
|
|
||||||
state = (state_t*)output;
|
|
||||||
InvCipher();
|
|
||||||
XorWithIv(output);
|
|
||||||
Iv = input;
|
|
||||||
input += BLOCKLEN;
|
|
||||||
output += BLOCKLEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (extra)
|
|
||||||
{
|
|
||||||
memcpy(output, input, extra);
|
|
||||||
state = (state_t*)output;
|
|
||||||
InvCipher();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // #if defined(CBC) && (CBC == 1)
|
|
45
lib/aes.h
45
lib/aes.h
@@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
* this file comes from https://github.com/kokke/tiny-AES128-C
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef UDP2RAW_AES_H_
|
|
||||||
#define UDP2RAW_AES_H_
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
|
|
||||||
// #define the macros below to 1/0 to enable/disable the mode of operation.
|
|
||||||
//
|
|
||||||
// CBC enables AES encryption in CBC-mode of operation.
|
|
||||||
// ECB enables the basic ECB 16-byte block algorithm. Both can be enabled simultaneously.
|
|
||||||
|
|
||||||
// The #ifndef-guard allows it to be configured before #include'ing or at compile time.
|
|
||||||
#ifndef CBC
|
|
||||||
#define CBC 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef ECB
|
|
||||||
#define ECB 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define AES128 1
|
|
||||||
//#define AES192 1
|
|
||||||
//#define AES256 1
|
|
||||||
|
|
||||||
#if defined(ECB) && (ECB == 1)
|
|
||||||
|
|
||||||
void AES_ECB_encrypt(const uint8_t* input, const uint8_t* key, uint8_t *output, const uint32_t length);
|
|
||||||
void AES_ECB_decrypt(const uint8_t* input, const uint8_t* key, uint8_t *output, const uint32_t length);
|
|
||||||
|
|
||||||
#endif // #if defined(ECB) && (ECB == !)
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(CBC) && (CBC == 1)
|
|
||||||
|
|
||||||
void AES_CBC_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv);
|
|
||||||
void AES_CBC_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv);
|
|
||||||
|
|
||||||
#endif // #if defined(CBC) && (CBC == 1)
|
|
||||||
|
|
||||||
|
|
||||||
#endif //_AES_H_
|
|
@@ -6,6 +6,7 @@
|
|||||||
#include "aesarm.h"
|
#include "aesarm.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#if defined(AES256) && (AES256 == 1)
|
#if defined(AES256) && (AES256 == 1)
|
||||||
#define AES_KEYSIZE 256
|
#define AES_KEYSIZE 256
|
||||||
@@ -342,10 +343,7 @@ void AES_CBC_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, co
|
|||||||
uint8_t iv_tmp[16];
|
uint8_t iv_tmp[16];
|
||||||
static uint8_t rk[AES_RKSIZE];
|
static uint8_t rk[AES_RKSIZE];
|
||||||
|
|
||||||
if (iv == NULL)
|
assert(iv!=NULL);
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
aeshw_init();
|
aeshw_init();
|
||||||
memcpy(iv_tmp, iv, 16);
|
memcpy(iv_tmp, iv, 16);
|
||||||
if(key!= NULL)
|
if(key!= NULL)
|
||||||
@@ -358,10 +356,7 @@ void AES_CBC_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, co
|
|||||||
uint8_t iv_tmp[16];
|
uint8_t iv_tmp[16];
|
||||||
static uint8_t rk[AES_RKSIZE];
|
static uint8_t rk[AES_RKSIZE];
|
||||||
|
|
||||||
if (iv == NULL)
|
assert(iv!=NULL);
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
aeshw_init();
|
aeshw_init();
|
||||||
memcpy(iv_tmp, iv, 16);
|
memcpy(iv_tmp, iv, 16);
|
||||||
if(key!= NULL)
|
if(key!= NULL)
|
||||||
@@ -371,6 +366,7 @@ void AES_CBC_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, co
|
|||||||
decrypt_cbc(rk, length, iv_tmp, input, output);
|
decrypt_cbc(rk, length, iv_tmp, input, output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
void AES_ECB_encrypt(const uint8_t* input, const uint8_t* key, uint8_t* output, const uint32_t length)
|
void AES_ECB_encrypt(const uint8_t* input, const uint8_t* key, uint8_t* output, const uint32_t length)
|
||||||
{
|
{
|
||||||
uint8_t rk[AES_RKSIZE];
|
uint8_t rk[AES_RKSIZE];
|
||||||
@@ -395,4 +391,79 @@ void AES_ECB_decrypt(const uint8_t* input, const uint8_t* key, uint8_t *output,
|
|||||||
aeshw_init();
|
aeshw_init();
|
||||||
setkey_dec(rk, key);
|
setkey_dec(rk, key);
|
||||||
decrypt_ecb(AES_NR, rk, input, output);
|
decrypt_ecb(AES_NR, rk, input, output);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
static void encrypt_cfb( uint8_t* rk,
|
||||||
|
uint32_t length,size_t *iv_off,
|
||||||
|
uint8_t iv[16],
|
||||||
|
const uint8_t *input,
|
||||||
|
uint8_t *output )
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
size_t n = *iv_off;
|
||||||
|
while( length-- )
|
||||||
|
{
|
||||||
|
if( n == 0 )
|
||||||
|
encrypt_ecb( AES_NR, rk, iv, iv );
|
||||||
|
|
||||||
|
iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
|
||||||
|
|
||||||
|
n = ( n + 1 ) & 0x0F;
|
||||||
|
}
|
||||||
|
|
||||||
|
*iv_off = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void decrypt_cfb( uint8_t* rk,
|
||||||
|
uint32_t length,size_t *iv_off,
|
||||||
|
uint8_t iv[16],
|
||||||
|
const uint8_t *input,
|
||||||
|
uint8_t *output )
|
||||||
|
{
|
||||||
|
int c;
|
||||||
|
size_t n = *iv_off;
|
||||||
|
while( length-- )
|
||||||
|
{
|
||||||
|
if( n == 0 )
|
||||||
|
encrypt_ecb( AES_NR, rk, iv, iv );
|
||||||
|
|
||||||
|
c = *input++;
|
||||||
|
*output++ = (unsigned char)( c ^ iv[n] );
|
||||||
|
iv[n] = (unsigned char) c;
|
||||||
|
|
||||||
|
n = ( n + 1 ) & 0x0F;
|
||||||
|
}
|
||||||
|
|
||||||
|
*iv_off = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AES_CFB_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)
|
||||||
|
{
|
||||||
|
uint8_t iv_tmp[16];
|
||||||
|
static uint8_t rk[AES_RKSIZE];
|
||||||
|
|
||||||
|
assert(iv!=NULL);
|
||||||
|
aeshw_init();
|
||||||
|
memcpy(iv_tmp, iv, 16);
|
||||||
|
if(key!= NULL)
|
||||||
|
setkey_enc(rk, key);
|
||||||
|
size_t offset=0;
|
||||||
|
encrypt_cfb(rk, length,&offset, iv_tmp, input, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AES_CFB_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)
|
||||||
|
{
|
||||||
|
uint8_t iv_tmp[16];
|
||||||
|
static uint8_t rk[AES_RKSIZE];
|
||||||
|
|
||||||
|
assert(iv!=NULL);
|
||||||
|
aeshw_init();
|
||||||
|
memcpy(iv_tmp, iv, 16);
|
||||||
|
if(key!= NULL)
|
||||||
|
{
|
||||||
|
setkey_enc(rk, key);//its enc again,not typo
|
||||||
|
}
|
||||||
|
size_t offset=0;
|
||||||
|
decrypt_cfb(rk, length,&offset, iv_tmp, input, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -37,6 +37,7 @@
|
|||||||
////////modification begin
|
////////modification begin
|
||||||
#define POLARSSL_AES_ROM_TABLES
|
#define POLARSSL_AES_ROM_TABLES
|
||||||
#define POLARSSL_CIPHER_MODE_CBC
|
#define POLARSSL_CIPHER_MODE_CBC
|
||||||
|
#define POLARSSL_CIPHER_MODE_CFB
|
||||||
//#define POLARSSL_SELF_TEST
|
//#define POLARSSL_SELF_TEST
|
||||||
#define polarssl_printf printf
|
#define polarssl_printf printf
|
||||||
///////add end
|
///////add end
|
||||||
|
@@ -1,56 +0,0 @@
|
|||||||
#include "aes.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#if defined(AES256) && (AES256 == 1)
|
|
||||||
#define AES_KEYSIZE 256
|
|
||||||
#elif defined(AES192) && (AES192 == 1)
|
|
||||||
#define AES_KEYSIZE 192
|
|
||||||
#else
|
|
||||||
#define AES_KEYSIZE 128
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
void AES_ECB_encrypt(const uint8_t* input, const uint8_t* key, uint8_t *output, const uint32_t length)
|
|
||||||
{
|
|
||||||
printf("AES_ECB_encrypt not implemented\n");
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
void AES_ECB_decrypt(const uint8_t* input, const uint8_t* key, uint8_t *output, const uint32_t length)
|
|
||||||
{
|
|
||||||
printf("AES_ECB_encrypt not implemented\n");
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AES_CBC_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)
|
|
||||||
{
|
|
||||||
static aes_context ctx;
|
|
||||||
static int done=0;
|
|
||||||
if(done==0)
|
|
||||||
{
|
|
||||||
aes_init( &ctx);
|
|
||||||
done=1;
|
|
||||||
}
|
|
||||||
|
|
||||||
char tmp_iv[16];
|
|
||||||
if(key!=0) aes_setkey_enc(&ctx,key,AES_KEYSIZE);
|
|
||||||
memcpy(tmp_iv,iv,16);
|
|
||||||
aes_crypt_cbc( &ctx, AES_ENCRYPT, length, (unsigned char* )tmp_iv, (const unsigned char*)input,(unsigned char*) output );
|
|
||||||
return ;
|
|
||||||
}
|
|
||||||
void AES_CBC_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)
|
|
||||||
{
|
|
||||||
static aes_context ctx;
|
|
||||||
static int done=0;
|
|
||||||
if(done==0)
|
|
||||||
{
|
|
||||||
aes_init( &ctx);
|
|
||||||
done=1;
|
|
||||||
}
|
|
||||||
|
|
||||||
char tmp_iv[16];
|
|
||||||
if(key!=0) aes_setkey_dec(&ctx,key,AES_KEYSIZE);
|
|
||||||
memcpy(tmp_iv,iv,16);
|
|
||||||
aes_crypt_cbc( &ctx,AES_DECRYPT, length, (unsigned char*)tmp_iv, (const unsigned char*)input, (unsigned char*) output );
|
|
||||||
return;
|
|
||||||
}
|
|
89
lib/aes_faster_c/wrapper.cpp
Normal file
89
lib/aes_faster_c/wrapper.cpp
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
#include "aes.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#if defined(AES256) && (AES256 == 1)
|
||||||
|
#define AES_KEYSIZE 256
|
||||||
|
#elif defined(AES192) && (AES192 == 1)
|
||||||
|
#define AES_KEYSIZE 192
|
||||||
|
#else
|
||||||
|
#define AES_KEYSIZE 128
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void AES_ECB_encrypt(const uint8_t* input, const uint8_t* key, uint8_t *output, const uint32_t length)
|
||||||
|
{
|
||||||
|
printf("AES_ECB_encrypt not implemented\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
void AES_ECB_decrypt(const uint8_t* input, const uint8_t* key, uint8_t *output, const uint32_t length)
|
||||||
|
{
|
||||||
|
printf("AES_ECB_encrypt not implemented\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AES_CBC_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)
|
||||||
|
{
|
||||||
|
static aes_context ctx;
|
||||||
|
|
||||||
|
char tmp_iv[16];
|
||||||
|
if(key!=0)
|
||||||
|
{
|
||||||
|
aes_init( &ctx);
|
||||||
|
aes_setkey_enc(&ctx,key,AES_KEYSIZE);
|
||||||
|
}
|
||||||
|
memcpy(tmp_iv,iv,16);
|
||||||
|
int ret=aes_crypt_cbc( &ctx, AES_ENCRYPT, length, (unsigned char* )tmp_iv, (const unsigned char*)input,(unsigned char*) output );
|
||||||
|
assert(ret==0);
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
void AES_CBC_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)
|
||||||
|
{
|
||||||
|
static aes_context ctx;
|
||||||
|
|
||||||
|
char tmp_iv[16];
|
||||||
|
if(key!=0)
|
||||||
|
{
|
||||||
|
aes_init( &ctx);
|
||||||
|
aes_setkey_dec(&ctx,key,AES_KEYSIZE);
|
||||||
|
}
|
||||||
|
memcpy(tmp_iv,iv,16);
|
||||||
|
int ret=aes_crypt_cbc( &ctx,AES_DECRYPT, length, (unsigned char*)tmp_iv, (const unsigned char*)input, (unsigned char*) output );
|
||||||
|
assert(ret==0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AES_CFB_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)
|
||||||
|
{
|
||||||
|
static aes_context ctx;
|
||||||
|
|
||||||
|
char tmp_iv[16];
|
||||||
|
if(key!=0)
|
||||||
|
{
|
||||||
|
aes_init( &ctx);
|
||||||
|
aes_setkey_enc(&ctx,key,AES_KEYSIZE);
|
||||||
|
}
|
||||||
|
memcpy(tmp_iv,iv,16);
|
||||||
|
size_t offset=0;
|
||||||
|
int ret=aes_crypt_cfb128( &ctx, AES_ENCRYPT, length,&offset, (unsigned char* )tmp_iv, (const unsigned char*)input,(unsigned char*) output );
|
||||||
|
assert(ret==0);
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
void AES_CFB_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)
|
||||||
|
{
|
||||||
|
static aes_context ctx;
|
||||||
|
|
||||||
|
char tmp_iv[16];
|
||||||
|
if(key!=0)
|
||||||
|
{
|
||||||
|
aes_init( &ctx);
|
||||||
|
aes_setkey_enc(&ctx,key,AES_KEYSIZE);// its aes_setkey_enc again, no typo
|
||||||
|
}
|
||||||
|
memcpy(tmp_iv,iv,16);
|
||||||
|
size_t offset=0;
|
||||||
|
int ret=aes_crypt_cfb128( &ctx,AES_DECRYPT, length,&offset, (unsigned char*)tmp_iv, (const unsigned char*)input, (unsigned char*) output );
|
||||||
|
assert(ret==0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@@ -38,6 +38,9 @@ typedef struct
|
|||||||
uint32_t total[2]; /*!< number of bytes processed */
|
uint32_t total[2]; /*!< number of bytes processed */
|
||||||
uint32_t state[4]; /*!< intermediate digest state */
|
uint32_t state[4]; /*!< intermediate digest state */
|
||||||
unsigned char buffer[64]; /*!< data block being processed */
|
unsigned char buffer[64]; /*!< data block being processed */
|
||||||
|
|
||||||
|
unsigned char ipad[64]; /*!< HMAC: inner padding */
|
||||||
|
unsigned char opad[64]; /*!< HMAC: outer padding */
|
||||||
}
|
}
|
||||||
md5_context;
|
md5_context;
|
||||||
|
|
||||||
@@ -302,15 +305,99 @@ void md5_finish( md5_context *ctx, unsigned char output[16] )
|
|||||||
*/
|
*/
|
||||||
void md5( const unsigned char *input, size_t ilen, unsigned char output[16] )
|
void md5( const unsigned char *input, size_t ilen, unsigned char output[16] )
|
||||||
{
|
{
|
||||||
static md5_context ctx;
|
/*static md5_context ctx;
|
||||||
static int done=0;
|
static int done=0;
|
||||||
if(done==0)
|
if(done==0)
|
||||||
{
|
{
|
||||||
md5_init( &ctx );
|
md5_init( &ctx );
|
||||||
done=1;
|
done=1;
|
||||||
}
|
}*/
|
||||||
|
md5_context ctx;
|
||||||
|
md5_init( &ctx );
|
||||||
md5_starts( &ctx );
|
md5_starts( &ctx );
|
||||||
md5_update( &ctx, input, ilen );
|
md5_update( &ctx, input, ilen );
|
||||||
md5_finish( &ctx, output );
|
md5_finish( &ctx, output );
|
||||||
//md5_free( &ctx );
|
md5_free( &ctx );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MD5 HMAC context setup
|
||||||
|
*/
|
||||||
|
void md5_hmac_starts( md5_context *ctx, const unsigned char *key,
|
||||||
|
size_t keylen )
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
unsigned char sum[16];
|
||||||
|
|
||||||
|
if( keylen > 64 )
|
||||||
|
{
|
||||||
|
md5( key, keylen, sum );
|
||||||
|
keylen = 16;
|
||||||
|
key = sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset( ctx->ipad, 0x36, 64 );
|
||||||
|
memset( ctx->opad, 0x5C, 64 );
|
||||||
|
|
||||||
|
for( i = 0; i < keylen; i++ )
|
||||||
|
{
|
||||||
|
ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
|
||||||
|
ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
|
||||||
|
}
|
||||||
|
|
||||||
|
md5_starts( ctx );
|
||||||
|
md5_update( ctx, ctx->ipad, 64 );
|
||||||
|
|
||||||
|
polarssl_zeroize( sum, sizeof( sum ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MD5 HMAC process buffer
|
||||||
|
*/
|
||||||
|
void md5_hmac_update( md5_context *ctx, const unsigned char *input,
|
||||||
|
size_t ilen )
|
||||||
|
{
|
||||||
|
md5_update( ctx, input, ilen );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MD5 HMAC final digest
|
||||||
|
*/
|
||||||
|
void md5_hmac_finish( md5_context *ctx, unsigned char output[16] )
|
||||||
|
{
|
||||||
|
unsigned char tmpbuf[16];
|
||||||
|
|
||||||
|
md5_finish( ctx, tmpbuf );
|
||||||
|
md5_starts( ctx );
|
||||||
|
md5_update( ctx, ctx->opad, 64 );
|
||||||
|
md5_update( ctx, tmpbuf, 16 );
|
||||||
|
md5_finish( ctx, output );
|
||||||
|
|
||||||
|
polarssl_zeroize( tmpbuf, sizeof( tmpbuf ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MD5 HMAC context reset
|
||||||
|
*/
|
||||||
|
void md5_hmac_reset( md5_context *ctx )
|
||||||
|
{
|
||||||
|
md5_starts( ctx );
|
||||||
|
md5_update( ctx, ctx->ipad, 64 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* output = HMAC-MD5( hmac key, input buffer )
|
||||||
|
*/
|
||||||
|
void md5_hmac( const unsigned char *key, size_t keylen,
|
||||||
|
const unsigned char *input, size_t ilen,
|
||||||
|
unsigned char output[16] )
|
||||||
|
{
|
||||||
|
md5_context ctx;
|
||||||
|
|
||||||
|
md5_init( &ctx );
|
||||||
|
md5_hmac_starts( &ctx, key, keylen );
|
||||||
|
md5_hmac_update( &ctx, input, ilen );
|
||||||
|
md5_hmac_finish( &ctx, output );
|
||||||
|
md5_free( &ctx );
|
||||||
}
|
}
|
865
lib/pbkdf2-sha1.cpp
Normal file
865
lib/pbkdf2-sha1.cpp
Normal file
@@ -0,0 +1,865 @@
|
|||||||
|
/*
|
||||||
|
this file is from https://github.com/kholia/PKCS5_PBKDF2
|
||||||
|
|
||||||
|
*
|
||||||
|
* FIPS-180-1 compliant SHA-1 implementation
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006-2010, Brainspark B.V.
|
||||||
|
*
|
||||||
|
* This file is part of PolarSSL (http://www.polarssl.org)
|
||||||
|
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
|
||||||
|
*
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* The SHA-1 standard was published by NIST in 1993.
|
||||||
|
*
|
||||||
|
* http://www.itl.nist.gov/fipspubs/fip180-1.htm
|
||||||
|
*
|
||||||
|
* Copyright 2012 Mathias Olsson mathias@kompetensum.com
|
||||||
|
*
|
||||||
|
* This file is dual licensed as either GPL version 2 or Apache License 2.0 at your choice
|
||||||
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||||
|
* http://www.apache.org/licenses/
|
||||||
|
*
|
||||||
|
* Note that PolarSSL uses GPL with a FOSS License Exception */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#if defined(TEST) ||defined(DEBUG)
|
||||||
|
#undef TEST
|
||||||
|
#undef DEBUG
|
||||||
|
#warning "undefined TEST/DEBUG"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned long total[2]; /*!< number of bytes processed */
|
||||||
|
unsigned long state[5]; /*!< intermediate digest state */
|
||||||
|
unsigned char buffer[64]; /*!< data block being processed */
|
||||||
|
|
||||||
|
unsigned char ipad[64]; /*!< HMAC: inner padding */
|
||||||
|
unsigned char opad[64]; /*!< HMAC: outer padding */
|
||||||
|
} sha1_context;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 32-bit integer manipulation macros (big endian)
|
||||||
|
*/
|
||||||
|
#ifndef GET_ULONG_BE
|
||||||
|
#define GET_ULONG_BE(n,b,i) \
|
||||||
|
{ \
|
||||||
|
(n) = ( (unsigned long) (b)[(i) ] << 24 ) \
|
||||||
|
| ( (unsigned long) (b)[(i) + 1] << 16 ) \
|
||||||
|
| ( (unsigned long) (b)[(i) + 2] << 8 ) \
|
||||||
|
| ( (unsigned long) (b)[(i) + 3] ); \
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PUT_ULONG_BE
|
||||||
|
#define PUT_ULONG_BE(n,b,i) \
|
||||||
|
{ \
|
||||||
|
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
|
||||||
|
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
|
||||||
|
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
|
||||||
|
(b)[(i) + 3] = (unsigned char) ( (n) ); \
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SHA-1 context setup
|
||||||
|
*/
|
||||||
|
void sha1_starts(sha1_context * ctx)
|
||||||
|
{
|
||||||
|
ctx->total[0] = 0;
|
||||||
|
ctx->total[1] = 0;
|
||||||
|
|
||||||
|
ctx->state[0] = 0x67452301;
|
||||||
|
ctx->state[1] = 0xEFCDAB89;
|
||||||
|
ctx->state[2] = 0x98BADCFE;
|
||||||
|
ctx->state[3] = 0x10325476;
|
||||||
|
ctx->state[4] = 0xC3D2E1F0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sha1_process(sha1_context * ctx, const unsigned char data[64])
|
||||||
|
{
|
||||||
|
unsigned long temp, W[16], A, B, C, D, E;
|
||||||
|
|
||||||
|
GET_ULONG_BE(W[0], data, 0);
|
||||||
|
GET_ULONG_BE(W[1], data, 4);
|
||||||
|
GET_ULONG_BE(W[2], data, 8);
|
||||||
|
GET_ULONG_BE(W[3], data, 12);
|
||||||
|
GET_ULONG_BE(W[4], data, 16);
|
||||||
|
GET_ULONG_BE(W[5], data, 20);
|
||||||
|
GET_ULONG_BE(W[6], data, 24);
|
||||||
|
GET_ULONG_BE(W[7], data, 28);
|
||||||
|
GET_ULONG_BE(W[8], data, 32);
|
||||||
|
GET_ULONG_BE(W[9], data, 36);
|
||||||
|
GET_ULONG_BE(W[10], data, 40);
|
||||||
|
GET_ULONG_BE(W[11], data, 44);
|
||||||
|
GET_ULONG_BE(W[12], data, 48);
|
||||||
|
GET_ULONG_BE(W[13], data, 52);
|
||||||
|
GET_ULONG_BE(W[14], data, 56);
|
||||||
|
GET_ULONG_BE(W[15], data, 60);
|
||||||
|
|
||||||
|
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
|
||||||
|
|
||||||
|
#define R(t) \
|
||||||
|
( \
|
||||||
|
temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \
|
||||||
|
W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \
|
||||||
|
( W[t & 0x0F] = S(temp,1) ) \
|
||||||
|
)
|
||||||
|
|
||||||
|
#define P(a,b,c,d,e,x) \
|
||||||
|
{ \
|
||||||
|
e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \
|
||||||
|
}
|
||||||
|
|
||||||
|
A = ctx->state[0];
|
||||||
|
B = ctx->state[1];
|
||||||
|
C = ctx->state[2];
|
||||||
|
D = ctx->state[3];
|
||||||
|
E = ctx->state[4];
|
||||||
|
|
||||||
|
#define F(x,y,z) (z ^ (x & (y ^ z)))
|
||||||
|
#define K 0x5A827999
|
||||||
|
|
||||||
|
P(A, B, C, D, E, W[0]);
|
||||||
|
P(E, A, B, C, D, W[1]);
|
||||||
|
P(D, E, A, B, C, W[2]);
|
||||||
|
P(C, D, E, A, B, W[3]);
|
||||||
|
P(B, C, D, E, A, W[4]);
|
||||||
|
P(A, B, C, D, E, W[5]);
|
||||||
|
P(E, A, B, C, D, W[6]);
|
||||||
|
P(D, E, A, B, C, W[7]);
|
||||||
|
P(C, D, E, A, B, W[8]);
|
||||||
|
P(B, C, D, E, A, W[9]);
|
||||||
|
P(A, B, C, D, E, W[10]);
|
||||||
|
P(E, A, B, C, D, W[11]);
|
||||||
|
P(D, E, A, B, C, W[12]);
|
||||||
|
P(C, D, E, A, B, W[13]);
|
||||||
|
P(B, C, D, E, A, W[14]);
|
||||||
|
P(A, B, C, D, E, W[15]);
|
||||||
|
P(E, A, B, C, D, R(16));
|
||||||
|
P(D, E, A, B, C, R(17));
|
||||||
|
P(C, D, E, A, B, R(18));
|
||||||
|
P(B, C, D, E, A, R(19));
|
||||||
|
|
||||||
|
#undef K
|
||||||
|
#undef F
|
||||||
|
|
||||||
|
#define F(x,y,z) (x ^ y ^ z)
|
||||||
|
#define K 0x6ED9EBA1
|
||||||
|
|
||||||
|
P(A, B, C, D, E, R(20));
|
||||||
|
P(E, A, B, C, D, R(21));
|
||||||
|
P(D, E, A, B, C, R(22));
|
||||||
|
P(C, D, E, A, B, R(23));
|
||||||
|
P(B, C, D, E, A, R(24));
|
||||||
|
P(A, B, C, D, E, R(25));
|
||||||
|
P(E, A, B, C, D, R(26));
|
||||||
|
P(D, E, A, B, C, R(27));
|
||||||
|
P(C, D, E, A, B, R(28));
|
||||||
|
P(B, C, D, E, A, R(29));
|
||||||
|
P(A, B, C, D, E, R(30));
|
||||||
|
P(E, A, B, C, D, R(31));
|
||||||
|
P(D, E, A, B, C, R(32));
|
||||||
|
P(C, D, E, A, B, R(33));
|
||||||
|
P(B, C, D, E, A, R(34));
|
||||||
|
P(A, B, C, D, E, R(35));
|
||||||
|
P(E, A, B, C, D, R(36));
|
||||||
|
P(D, E, A, B, C, R(37));
|
||||||
|
P(C, D, E, A, B, R(38));
|
||||||
|
P(B, C, D, E, A, R(39));
|
||||||
|
|
||||||
|
#undef K
|
||||||
|
#undef F
|
||||||
|
|
||||||
|
#define F(x,y,z) ((x & y) | (z & (x | y)))
|
||||||
|
#define K 0x8F1BBCDC
|
||||||
|
|
||||||
|
P(A, B, C, D, E, R(40));
|
||||||
|
P(E, A, B, C, D, R(41));
|
||||||
|
P(D, E, A, B, C, R(42));
|
||||||
|
P(C, D, E, A, B, R(43));
|
||||||
|
P(B, C, D, E, A, R(44));
|
||||||
|
P(A, B, C, D, E, R(45));
|
||||||
|
P(E, A, B, C, D, R(46));
|
||||||
|
P(D, E, A, B, C, R(47));
|
||||||
|
P(C, D, E, A, B, R(48));
|
||||||
|
P(B, C, D, E, A, R(49));
|
||||||
|
P(A, B, C, D, E, R(50));
|
||||||
|
P(E, A, B, C, D, R(51));
|
||||||
|
P(D, E, A, B, C, R(52));
|
||||||
|
P(C, D, E, A, B, R(53));
|
||||||
|
P(B, C, D, E, A, R(54));
|
||||||
|
P(A, B, C, D, E, R(55));
|
||||||
|
P(E, A, B, C, D, R(56));
|
||||||
|
P(D, E, A, B, C, R(57));
|
||||||
|
P(C, D, E, A, B, R(58));
|
||||||
|
P(B, C, D, E, A, R(59));
|
||||||
|
|
||||||
|
#undef K
|
||||||
|
#undef F
|
||||||
|
|
||||||
|
#define F(x,y,z) (x ^ y ^ z)
|
||||||
|
#define K 0xCA62C1D6
|
||||||
|
|
||||||
|
P(A, B, C, D, E, R(60));
|
||||||
|
P(E, A, B, C, D, R(61));
|
||||||
|
P(D, E, A, B, C, R(62));
|
||||||
|
P(C, D, E, A, B, R(63));
|
||||||
|
P(B, C, D, E, A, R(64));
|
||||||
|
P(A, B, C, D, E, R(65));
|
||||||
|
P(E, A, B, C, D, R(66));
|
||||||
|
P(D, E, A, B, C, R(67));
|
||||||
|
P(C, D, E, A, B, R(68));
|
||||||
|
P(B, C, D, E, A, R(69));
|
||||||
|
P(A, B, C, D, E, R(70));
|
||||||
|
P(E, A, B, C, D, R(71));
|
||||||
|
P(D, E, A, B, C, R(72));
|
||||||
|
P(C, D, E, A, B, R(73));
|
||||||
|
P(B, C, D, E, A, R(74));
|
||||||
|
P(A, B, C, D, E, R(75));
|
||||||
|
P(E, A, B, C, D, R(76));
|
||||||
|
P(D, E, A, B, C, R(77));
|
||||||
|
P(C, D, E, A, B, R(78));
|
||||||
|
P(B, C, D, E, A, R(79));
|
||||||
|
|
||||||
|
#undef K
|
||||||
|
#undef F
|
||||||
|
|
||||||
|
ctx->state[0] += A;
|
||||||
|
ctx->state[1] += B;
|
||||||
|
ctx->state[2] += C;
|
||||||
|
ctx->state[3] += D;
|
||||||
|
ctx->state[4] += E;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SHA-1 process buffer
|
||||||
|
*/
|
||||||
|
void sha1_update(sha1_context * ctx, const unsigned char *input, int ilen)
|
||||||
|
{
|
||||||
|
int fill;
|
||||||
|
unsigned long left;
|
||||||
|
|
||||||
|
if (ilen <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
left = ctx->total[0] & 0x3F;
|
||||||
|
fill = 64 - left;
|
||||||
|
|
||||||
|
ctx->total[0] += (unsigned long) ilen;
|
||||||
|
ctx->total[0] &= 0xFFFFFFFF;
|
||||||
|
|
||||||
|
if (ctx->total[0] < (unsigned long) ilen)
|
||||||
|
ctx->total[1]++;
|
||||||
|
|
||||||
|
if (left && ilen >= fill) {
|
||||||
|
memcpy((void *) (ctx->buffer + left), (void *) input, fill);
|
||||||
|
sha1_process(ctx, ctx->buffer);
|
||||||
|
input += fill;
|
||||||
|
ilen -= fill;
|
||||||
|
left = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (ilen >= 64) {
|
||||||
|
sha1_process(ctx, input);
|
||||||
|
input += 64;
|
||||||
|
ilen -= 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ilen > 0) {
|
||||||
|
memcpy((void *) (ctx->buffer + left), (void *) input, ilen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const unsigned char sha1_padding[64] = {
|
||||||
|
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SHA-1 final digest
|
||||||
|
*/
|
||||||
|
void sha1_finish(sha1_context * ctx, unsigned char output[20])
|
||||||
|
{
|
||||||
|
unsigned long last, padn;
|
||||||
|
unsigned long high, low;
|
||||||
|
unsigned char msglen[8];
|
||||||
|
|
||||||
|
high = (ctx->total[0] >> 29)
|
||||||
|
| (ctx->total[1] << 3);
|
||||||
|
low = (ctx->total[0] << 3);
|
||||||
|
|
||||||
|
PUT_ULONG_BE(high, msglen, 0);
|
||||||
|
PUT_ULONG_BE(low, msglen, 4);
|
||||||
|
|
||||||
|
last = ctx->total[0] & 0x3F;
|
||||||
|
padn = (last < 56) ? (56 - last) : (120 - last);
|
||||||
|
|
||||||
|
sha1_update(ctx, (unsigned char *) sha1_padding, padn);
|
||||||
|
sha1_update(ctx, msglen, 8);
|
||||||
|
|
||||||
|
PUT_ULONG_BE(ctx->state[0], output, 0);
|
||||||
|
PUT_ULONG_BE(ctx->state[1], output, 4);
|
||||||
|
PUT_ULONG_BE(ctx->state[2], output, 8);
|
||||||
|
PUT_ULONG_BE(ctx->state[3], output, 12);
|
||||||
|
PUT_ULONG_BE(ctx->state[4], output, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* output = SHA-1( input buffer )
|
||||||
|
*/
|
||||||
|
void sha1(const unsigned char *input, int ilen, unsigned char output[20])
|
||||||
|
{
|
||||||
|
sha1_context ctx;
|
||||||
|
|
||||||
|
sha1_starts(&ctx);
|
||||||
|
sha1_update(&ctx, input, ilen);
|
||||||
|
sha1_finish(&ctx, output);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SHA-1 HMAC context setup
|
||||||
|
*/
|
||||||
|
void sha1_hmac_starts(sha1_context * ctx, const unsigned char *key, int keylen)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
unsigned char sum[20];
|
||||||
|
|
||||||
|
if (keylen > 64) {
|
||||||
|
sha1(key, keylen, sum);
|
||||||
|
keylen = 20;
|
||||||
|
key = sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(ctx->ipad, 0x36, 64);
|
||||||
|
memset(ctx->opad, 0x5C, 64);
|
||||||
|
|
||||||
|
for (i = 0; i < keylen; i++) {
|
||||||
|
ctx->ipad[i] = (unsigned char) (ctx->ipad[i] ^ key[i]);
|
||||||
|
ctx->opad[i] = (unsigned char) (ctx->opad[i] ^ key[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
sha1_starts(ctx);
|
||||||
|
sha1_update(ctx, ctx->ipad, 64);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SHA-1 HMAC process buffer
|
||||||
|
*/
|
||||||
|
void sha1_hmac_update(sha1_context * ctx, const unsigned char *input, int ilen)
|
||||||
|
{
|
||||||
|
sha1_update(ctx, input, ilen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SHA-1 HMAC final digest
|
||||||
|
*/
|
||||||
|
void sha1_hmac_finish(sha1_context * ctx, unsigned char output[20])
|
||||||
|
{
|
||||||
|
unsigned char tmpbuf[20];
|
||||||
|
|
||||||
|
sha1_finish(ctx, tmpbuf);
|
||||||
|
sha1_starts(ctx);
|
||||||
|
sha1_update(ctx, ctx->opad, 64);
|
||||||
|
sha1_update(ctx, tmpbuf, 20);
|
||||||
|
sha1_finish(ctx, output);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SHA1 HMAC context reset
|
||||||
|
*/
|
||||||
|
void sha1_hmac_reset(sha1_context * ctx)
|
||||||
|
{
|
||||||
|
sha1_starts(ctx);
|
||||||
|
sha1_update(ctx, ctx->ipad, 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* output = HMAC-SHA-1( hmac key, input buffer )
|
||||||
|
*/
|
||||||
|
void sha1_hmac(const unsigned char *key, int keylen,
|
||||||
|
const unsigned char *input, int ilen, unsigned char output[20])
|
||||||
|
{
|
||||||
|
sha1_context ctx;
|
||||||
|
|
||||||
|
sha1_hmac_starts(&ctx, key, keylen);
|
||||||
|
sha1_hmac_update(&ctx, input, ilen);
|
||||||
|
sha1_hmac_finish(&ctx, output);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef min
|
||||||
|
#define min( a, b ) ( ((a) < (b)) ? (a) : (b) )
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void PKCS5_PBKDF2_HMAC_SHA1(const unsigned char *password, size_t plen,
|
||||||
|
const unsigned char *salt, size_t slen,
|
||||||
|
const unsigned long iteration_count, const unsigned long key_length,
|
||||||
|
unsigned char *output)
|
||||||
|
{
|
||||||
|
sha1_context ctx;
|
||||||
|
sha1_starts(&ctx);
|
||||||
|
|
||||||
|
// Size of the generated digest
|
||||||
|
unsigned char md_size = 20;
|
||||||
|
unsigned char md1[20];
|
||||||
|
unsigned char work[20];
|
||||||
|
|
||||||
|
unsigned long counter = 1;
|
||||||
|
unsigned long generated_key_length = 0;
|
||||||
|
while (generated_key_length < key_length) {
|
||||||
|
// U1 ends up in md1 and work
|
||||||
|
unsigned char c[4];
|
||||||
|
c[0] = (counter >> 24) & 0xff;
|
||||||
|
c[1] = (counter >> 16) & 0xff;
|
||||||
|
c[2] = (counter >> 8) & 0xff;
|
||||||
|
c[3] = (counter >> 0) & 0xff;
|
||||||
|
|
||||||
|
sha1_hmac_starts(&ctx, password, plen);
|
||||||
|
sha1_hmac_update(&ctx, salt, slen);
|
||||||
|
sha1_hmac_update(&ctx, c, 4);
|
||||||
|
sha1_hmac_finish(&ctx, md1);
|
||||||
|
memcpy(work, md1, md_size);
|
||||||
|
|
||||||
|
unsigned long ic = 1;
|
||||||
|
for (ic = 1; ic < iteration_count; ic++) {
|
||||||
|
// U2 ends up in md1
|
||||||
|
sha1_hmac_starts(&ctx, password, plen);
|
||||||
|
sha1_hmac_update(&ctx, md1, md_size);
|
||||||
|
sha1_hmac_finish(&ctx, md1);
|
||||||
|
// U1 xor U2
|
||||||
|
unsigned long i = 0;
|
||||||
|
for (i = 0; i < md_size; i++) {
|
||||||
|
work[i] ^= md1[i];
|
||||||
|
}
|
||||||
|
// and so on until iteration_count
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy the generated bytes to the key
|
||||||
|
unsigned long bytes_to_write =
|
||||||
|
min((key_length - generated_key_length), md_size);
|
||||||
|
memcpy(output + generated_key_length, work, bytes_to_write);
|
||||||
|
generated_key_length += bytes_to_write;
|
||||||
|
++counter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(TEST)
|
||||||
|
/*
|
||||||
|
* FIPS-180-1 test vectors
|
||||||
|
*/
|
||||||
|
static unsigned char sha1_test_buf[3][57] = {
|
||||||
|
{"abc"},
|
||||||
|
{"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"},
|
||||||
|
{""}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int sha1_test_buflen[3] = {
|
||||||
|
3, 56, 1000
|
||||||
|
};
|
||||||
|
|
||||||
|
static const unsigned char sha1_test_sum[3][20] = {
|
||||||
|
{0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E,
|
||||||
|
0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D},
|
||||||
|
{0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE,
|
||||||
|
0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1},
|
||||||
|
{0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E,
|
||||||
|
0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RFC 2202 test vectors
|
||||||
|
*/
|
||||||
|
static unsigned char sha1_hmac_test_key[7][26] = {
|
||||||
|
{"\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
|
||||||
|
"\x0B\x0B\x0B\x0B"},
|
||||||
|
{"Jefe"},
|
||||||
|
{"\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
|
||||||
|
"\xAA\xAA\xAA\xAA"},
|
||||||
|
{"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
|
||||||
|
"\x11\x12\x13\x14\x15\x16\x17\x18\x19"},
|
||||||
|
{"\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
|
||||||
|
"\x0C\x0C\x0C\x0C"},
|
||||||
|
{""}, /* 0xAA 80 times */
|
||||||
|
{""}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int sha1_hmac_test_keylen[7] = {
|
||||||
|
20, 4, 20, 25, 20, 80, 80
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned char sha1_hmac_test_buf[7][74] = {
|
||||||
|
{"Hi There"},
|
||||||
|
{"what do ya want for nothing?"},
|
||||||
|
{"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
|
||||||
|
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
|
||||||
|
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
|
||||||
|
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
|
||||||
|
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"},
|
||||||
|
{"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
|
||||||
|
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
|
||||||
|
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
|
||||||
|
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
|
||||||
|
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"},
|
||||||
|
{"Test With Truncation"},
|
||||||
|
{"Test Using Larger Than Block-Size Key - Hash Key First"},
|
||||||
|
{"Test Using Larger Than Block-Size Key and Larger"
|
||||||
|
" Than One Block-Size Data"}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int sha1_hmac_test_buflen[7] = {
|
||||||
|
8, 28, 50, 50, 20, 54, 73
|
||||||
|
};
|
||||||
|
|
||||||
|
static const unsigned char sha1_hmac_test_sum[7][20] = {
|
||||||
|
{0xB6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xE2, 0x8B,
|
||||||
|
0xC0, 0xB6, 0xFB, 0x37, 0x8C, 0x8E, 0xF1, 0x46, 0xBE, 0x00},
|
||||||
|
{0xEF, 0xFC, 0xDF, 0x6A, 0xE5, 0xEB, 0x2F, 0xA2, 0xD2, 0x74,
|
||||||
|
0x16, 0xD5, 0xF1, 0x84, 0xDF, 0x9C, 0x25, 0x9A, 0x7C, 0x79},
|
||||||
|
{0x12, 0x5D, 0x73, 0x42, 0xB9, 0xAC, 0x11, 0xCD, 0x91, 0xA3,
|
||||||
|
0x9A, 0xF4, 0x8A, 0xA1, 0x7B, 0x4F, 0x63, 0xF1, 0x75, 0xD3},
|
||||||
|
{0x4C, 0x90, 0x07, 0xF4, 0x02, 0x62, 0x50, 0xC6, 0xBC, 0x84,
|
||||||
|
0x14, 0xF9, 0xBF, 0x50, 0xC8, 0x6C, 0x2D, 0x72, 0x35, 0xDA},
|
||||||
|
{0x4C, 0x1A, 0x03, 0x42, 0x4B, 0x55, 0xE0, 0x7F, 0xE7, 0xF2,
|
||||||
|
0x7B, 0xE1},
|
||||||
|
{0xAA, 0x4A, 0xE5, 0xE1, 0x52, 0x72, 0xD0, 0x0E, 0x95, 0x70,
|
||||||
|
0x56, 0x37, 0xCE, 0x8A, 0x3B, 0x55, 0xED, 0x40, 0x21, 0x12},
|
||||||
|
{0xE8, 0xE9, 0x9D, 0x0F, 0x45, 0x23, 0x7D, 0x78, 0x6D, 0x6B,
|
||||||
|
0xBA, 0xA7, 0x96, 0x5C, 0x78, 0x08, 0xBB, 0xFF, 0x1A, 0x91}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *t;
|
||||||
|
char *p;
|
||||||
|
int plen;
|
||||||
|
char *s;
|
||||||
|
int slen;
|
||||||
|
int c;
|
||||||
|
int dkLen;
|
||||||
|
char dk[1024]; // Remember to set this to max dkLen
|
||||||
|
} testvector;
|
||||||
|
|
||||||
|
int do_test(testvector * tv)
|
||||||
|
{
|
||||||
|
printf("Started %s\n", tv->t);
|
||||||
|
fflush(stdout);
|
||||||
|
char *key = malloc(tv->dkLen);
|
||||||
|
if (key == 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
PKCS5_PBKDF2_HMAC(tv->p, tv->plen, tv->s, tv->slen, tv->c,
|
||||||
|
tv->dkLen, key);
|
||||||
|
|
||||||
|
if (memcmp(tv->dk, key, tv->dkLen) != 0) {
|
||||||
|
// Failed
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
static void print_hex(unsigned char *str, int len)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < len; ++i)
|
||||||
|
printf("%02x", str[i]);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Checkup routine
|
||||||
|
*/
|
||||||
|
int main(int argc,char * argv[])
|
||||||
|
{
|
||||||
|
int verbose = 1;
|
||||||
|
int i, j, buflen;
|
||||||
|
unsigned char buf[1024];
|
||||||
|
unsigned char sha1sum[20];
|
||||||
|
|
||||||
|
sha1_context ctx;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SHA-1
|
||||||
|
*/
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
if (verbose != 0)
|
||||||
|
printf(" SHA-1 test #%d: ", i + 1);
|
||||||
|
|
||||||
|
sha1_starts(&ctx);
|
||||||
|
|
||||||
|
if (i == 2) {
|
||||||
|
memset(buf, 'a', buflen = 1000);
|
||||||
|
|
||||||
|
for (j = 0; j < 1000; j++)
|
||||||
|
sha1_update(&ctx, buf, buflen);
|
||||||
|
} else
|
||||||
|
sha1_update(&ctx, sha1_test_buf[i],
|
||||||
|
sha1_test_buflen[i]);
|
||||||
|
|
||||||
|
sha1_finish(&ctx, sha1sum);
|
||||||
|
|
||||||
|
if (memcmp(sha1sum, sha1_test_sum[i], 20) != 0) {
|
||||||
|
if (verbose != 0)
|
||||||
|
printf("failed\n");
|
||||||
|
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verbose != 0)
|
||||||
|
printf("passed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verbose != 0)
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
for (i = 0; i < 7; i++) {
|
||||||
|
if (verbose != 0)
|
||||||
|
printf(" HMAC-SHA-1 test #%d: ", i + 1);
|
||||||
|
|
||||||
|
if (i == 5 || i == 6) {
|
||||||
|
memset(buf, '\xAA', buflen = 80);
|
||||||
|
sha1_hmac_starts(&ctx, buf, buflen);
|
||||||
|
} else
|
||||||
|
sha1_hmac_starts(&ctx, sha1_hmac_test_key[i],
|
||||||
|
sha1_hmac_test_keylen[i]);
|
||||||
|
|
||||||
|
sha1_hmac_update(&ctx, sha1_hmac_test_buf[i],
|
||||||
|
sha1_hmac_test_buflen[i]);
|
||||||
|
|
||||||
|
sha1_hmac_finish(&ctx, sha1sum);
|
||||||
|
|
||||||
|
buflen = (i == 4) ? 12 : 20;
|
||||||
|
|
||||||
|
if (memcmp(sha1sum, sha1_hmac_test_sum[i], buflen) != 0) {
|
||||||
|
if (verbose != 0)
|
||||||
|
printf("failed\n");
|
||||||
|
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verbose != 0)
|
||||||
|
printf("passed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verbose != 0)
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
// Test vectors from RFC 6070
|
||||||
|
|
||||||
|
testvector *tv = 0;
|
||||||
|
int res = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Input:
|
||||||
|
P = "password" (8 octets)
|
||||||
|
S = "salt" (4 octets)
|
||||||
|
c = 1
|
||||||
|
dkLen = 20
|
||||||
|
|
||||||
|
Output:
|
||||||
|
DK = 0c 60 c8 0f 96 1f 0e 71
|
||||||
|
f3 a9 b5 24 af 60 12 06
|
||||||
|
2f e0 37 a6 (20 octets)
|
||||||
|
|
||||||
|
*/
|
||||||
|
testvector t1 = {
|
||||||
|
"Test 1",
|
||||||
|
"password", 8, "salt", 4, 1, 20,
|
||||||
|
.dk = {0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71,
|
||||||
|
0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06,
|
||||||
|
0x2f, 0xe0, 0x37, 0xa6}
|
||||||
|
};
|
||||||
|
|
||||||
|
tv = &t1;
|
||||||
|
res = do_test(tv);
|
||||||
|
if (res != 0) {
|
||||||
|
printf("%s failed\n", tv->t);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Input:
|
||||||
|
P = "password" (8 octets)
|
||||||
|
S = "salt" (4 octets)
|
||||||
|
c = 2
|
||||||
|
dkLen = 20
|
||||||
|
|
||||||
|
Output:
|
||||||
|
DK = ea 6c 01 4d c7 2d 6f 8c
|
||||||
|
cd 1e d9 2a ce 1d 41 f0
|
||||||
|
d8 de 89 57 (20 octets)
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
testvector t2 = {
|
||||||
|
"Test 2",
|
||||||
|
"password", 8, "salt", 4, 2, 20,
|
||||||
|
{0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c,
|
||||||
|
0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0,
|
||||||
|
0xd8, 0xde, 0x89, 0x57}
|
||||||
|
};
|
||||||
|
|
||||||
|
tv = &t2;
|
||||||
|
res = do_test(tv);
|
||||||
|
if (res != 0) {
|
||||||
|
printf("%s failed\n", tv->t);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Input:
|
||||||
|
P = "password" (8 octets)
|
||||||
|
S = "salt" (4 octets)
|
||||||
|
c = 4096
|
||||||
|
dkLen = 20
|
||||||
|
|
||||||
|
Output:
|
||||||
|
DK = 4b 00 79 01 b7 65 48 9a
|
||||||
|
be ad 49 d9 26 f7 21 d0
|
||||||
|
65 a4 29 c1 (20 octets)
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
testvector t3 = {
|
||||||
|
"Test 3",
|
||||||
|
"password", 8, "salt", 4, 4096, 20,
|
||||||
|
{0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a,
|
||||||
|
0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0,
|
||||||
|
0x65, 0xa4, 0x29, 0xc1}
|
||||||
|
};
|
||||||
|
|
||||||
|
tv = &t3;
|
||||||
|
res = do_test(tv);
|
||||||
|
if (res != 0) {
|
||||||
|
printf("%s failed\n", tv->t);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Input:
|
||||||
|
P = "password" (8 octets)
|
||||||
|
S = "salt" (4 octets)
|
||||||
|
c = 16777216
|
||||||
|
dkLen = 20
|
||||||
|
|
||||||
|
Output:
|
||||||
|
DK = ee fe 3d 61 cd 4d a4 e4
|
||||||
|
e9 94 5b 3d 6b a2 15 8c
|
||||||
|
26 34 e9 84 (20 octets)
|
||||||
|
|
||||||
|
*/
|
||||||
|
testvector t4 = {
|
||||||
|
"Test 4",
|
||||||
|
"password", 8, "salt", 4, 16777216, 20,
|
||||||
|
{0xee, 0xfe, 0x3d, 0x61, 0xcd, 0x4d, 0xa4, 0xe4,
|
||||||
|
0xe9, 0x94, 0x5b, 0x3d, 0x6b, 0xa2, 0x15, 0x8c,
|
||||||
|
0x26, 0x34, 0xe9, 0x84}
|
||||||
|
};
|
||||||
|
|
||||||
|
tv = &t4;
|
||||||
|
// res = do_test(tv);
|
||||||
|
if (res != 0) {
|
||||||
|
printf("%s failed\n", tv->t);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Input:
|
||||||
|
P = "passwordPASSWORDpassword" (24 octets)
|
||||||
|
S = "saltSALTsaltSALTsaltSALTsaltSALTsalt" (36 octets)
|
||||||
|
c = 4096
|
||||||
|
dkLen = 25
|
||||||
|
|
||||||
|
Output:
|
||||||
|
DK = 3d 2e ec 4f e4 1c 84 9b
|
||||||
|
80 c8 d8 36 62 c0 e4 4a
|
||||||
|
8b 29 1a 96 4c f2 f0 70
|
||||||
|
38 (25 octets)
|
||||||
|
|
||||||
|
*/
|
||||||
|
testvector t5 = {
|
||||||
|
"Test 5",
|
||||||
|
"passwordPASSWORDpassword", 24,
|
||||||
|
"saltSALTsaltSALTsaltSALTsaltSALTsalt", 36, 4096, 25,
|
||||||
|
{0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b,
|
||||||
|
0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a,
|
||||||
|
0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70,
|
||||||
|
0x38}
|
||||||
|
};
|
||||||
|
|
||||||
|
tv = &t5;
|
||||||
|
res = do_test(tv);
|
||||||
|
if (res != 0) {
|
||||||
|
printf("%s failed\n", tv->t);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Input:
|
||||||
|
P = "pass\0word" (9 octets)
|
||||||
|
S = "sa\0lt" (5 octets)
|
||||||
|
c = 4096
|
||||||
|
dkLen = 16
|
||||||
|
|
||||||
|
Output:
|
||||||
|
DK = 56 fa 6a a7 55 48 09 9d
|
||||||
|
cc 37 d7 f0 34 25 e0 c3 (16 octets)
|
||||||
|
*/
|
||||||
|
testvector t6 = {
|
||||||
|
"Test 6",
|
||||||
|
"pass\0word", 9, "sa\0lt", 5, 4096, 16,
|
||||||
|
{0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d,
|
||||||
|
0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
tv = &t6;
|
||||||
|
res = do_test(tv);
|
||||||
|
if (res != 0) {
|
||||||
|
printf("%s failed\n", tv->t);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("All tests successful\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
}*/
|
14
lib/pbkdf2-sha1.h
Normal file
14
lib/pbkdf2-sha1.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
void sha1(const unsigned char *input, int ilen, unsigned char output[20]);
|
||||||
|
|
||||||
|
void sha1_hmac(const unsigned char *key, int keylen, const unsigned char *input, int ilen, unsigned char output[20]);
|
||||||
|
|
||||||
|
void PKCS5_PBKDF2_HMAC_SHA1(const unsigned char *password, size_t plen,
|
||||||
|
const unsigned char *salt, size_t slen,
|
||||||
|
const unsigned long iteration_count, const unsigned long key_length,
|
||||||
|
unsigned char *output);
|
1124
lib/pbkdf2-sha256.cpp
Normal file
1124
lib/pbkdf2-sha256.cpp
Normal file
File diff suppressed because it is too large
Load Diff
28
lib/pbkdf2-sha256.h
Normal file
28
lib/pbkdf2-sha256.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
void PKCS5_PBKDF2_HMAC_SHA256(unsigned char *password, size_t plen,
|
||||||
|
unsigned char *salt, size_t slen,
|
||||||
|
const unsigned long iteration_count, const unsigned long key_length,
|
||||||
|
unsigned char *output);
|
||||||
|
|
||||||
|
//void sha2( const unsigned char *input, size_t ilen,unsigned char output[32], int is224 );
|
||||||
|
|
||||||
|
int hkdf_sha256_extract(
|
||||||
|
const unsigned char *salt, size_t salt_len,
|
||||||
|
const unsigned char *ikm, size_t ikm_len,
|
||||||
|
unsigned char *prk );
|
||||||
|
|
||||||
|
int hkdf_sha256_expand( const unsigned char *prk,
|
||||||
|
size_t prk_len, const unsigned char *info,
|
||||||
|
size_t info_len, unsigned char *okm, size_t okm_len );
|
||||||
|
|
||||||
|
int hkdf_sha256( const unsigned char *salt,
|
||||||
|
size_t salt_len, const unsigned char *ikm, size_t ikm_len,
|
||||||
|
const unsigned char *info, size_t info_len,
|
||||||
|
unsigned char *okm, size_t okm_len );
|
||||||
|
|
||||||
|
|
345
lib/sha1.c
345
lib/sha1.c
@@ -1,345 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is adapted from PolarSSL 1.3.19 (GPL)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* FIPS-180-1 compliant SHA-1 implementation
|
|
||||||
*
|
|
||||||
* Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
|
|
||||||
*
|
|
||||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* The SHA-1 standard was published by NIST in 1993.
|
|
||||||
*
|
|
||||||
* http://www.itl.nist.gov/fipspubs/fip180-1.htm
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
uint32_t total[2]; /*!< number of bytes processed */
|
|
||||||
uint32_t state[5]; /*!< intermediate digest state */
|
|
||||||
unsigned char buffer[64]; /*!< data block being processed */
|
|
||||||
}
|
|
||||||
sha1_context;
|
|
||||||
|
|
||||||
/* Implementation that should never be optimized out by the compiler */
|
|
||||||
static void polarssl_zeroize( void *v, size_t n ) {
|
|
||||||
volatile unsigned char *p = (unsigned char *) v; while( n-- ) *p++ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 32-bit integer manipulation macros (big endian)
|
|
||||||
*/
|
|
||||||
#ifndef GET_UINT32_BE
|
|
||||||
#define GET_UINT32_BE(n,b,i) \
|
|
||||||
{ \
|
|
||||||
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
|
|
||||||
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
|
|
||||||
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
|
|
||||||
| ( (uint32_t) (b)[(i) + 3] ); \
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef PUT_UINT32_BE
|
|
||||||
#define PUT_UINT32_BE(n,b,i) \
|
|
||||||
{ \
|
|
||||||
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
|
|
||||||
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
|
|
||||||
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
|
|
||||||
(b)[(i) + 3] = (unsigned char) ( (n) ); \
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void sha1_init( sha1_context *ctx )
|
|
||||||
{
|
|
||||||
memset( ctx, 0, sizeof( sha1_context ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
void sha1_free( sha1_context *ctx )
|
|
||||||
{
|
|
||||||
if( ctx == NULL )
|
|
||||||
return;
|
|
||||||
|
|
||||||
polarssl_zeroize( ctx, sizeof( sha1_context ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* SHA-1 context setup
|
|
||||||
*/
|
|
||||||
void sha1_starts( sha1_context *ctx )
|
|
||||||
{
|
|
||||||
ctx->total[0] = 0;
|
|
||||||
ctx->total[1] = 0;
|
|
||||||
|
|
||||||
ctx->state[0] = 0x67452301;
|
|
||||||
ctx->state[1] = 0xEFCDAB89;
|
|
||||||
ctx->state[2] = 0x98BADCFE;
|
|
||||||
ctx->state[3] = 0x10325476;
|
|
||||||
ctx->state[4] = 0xC3D2E1F0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sha1_process( sha1_context *ctx, const unsigned char data[64] )
|
|
||||||
{
|
|
||||||
uint32_t temp, W[16], A, B, C, D, E;
|
|
||||||
|
|
||||||
GET_UINT32_BE( W[ 0], data, 0 );
|
|
||||||
GET_UINT32_BE( W[ 1], data, 4 );
|
|
||||||
GET_UINT32_BE( W[ 2], data, 8 );
|
|
||||||
GET_UINT32_BE( W[ 3], data, 12 );
|
|
||||||
GET_UINT32_BE( W[ 4], data, 16 );
|
|
||||||
GET_UINT32_BE( W[ 5], data, 20 );
|
|
||||||
GET_UINT32_BE( W[ 6], data, 24 );
|
|
||||||
GET_UINT32_BE( W[ 7], data, 28 );
|
|
||||||
GET_UINT32_BE( W[ 8], data, 32 );
|
|
||||||
GET_UINT32_BE( W[ 9], data, 36 );
|
|
||||||
GET_UINT32_BE( W[10], data, 40 );
|
|
||||||
GET_UINT32_BE( W[11], data, 44 );
|
|
||||||
GET_UINT32_BE( W[12], data, 48 );
|
|
||||||
GET_UINT32_BE( W[13], data, 52 );
|
|
||||||
GET_UINT32_BE( W[14], data, 56 );
|
|
||||||
GET_UINT32_BE( W[15], data, 60 );
|
|
||||||
|
|
||||||
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
|
|
||||||
|
|
||||||
#define R(t) \
|
|
||||||
( \
|
|
||||||
temp = W[( t - 3 ) & 0x0F] ^ W[( t - 8 ) & 0x0F] ^ \
|
|
||||||
W[( t - 14 ) & 0x0F] ^ W[ t & 0x0F], \
|
|
||||||
( W[t & 0x0F] = S(temp,1) ) \
|
|
||||||
)
|
|
||||||
|
|
||||||
#define P(a,b,c,d,e,x) \
|
|
||||||
{ \
|
|
||||||
e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \
|
|
||||||
}
|
|
||||||
|
|
||||||
A = ctx->state[0];
|
|
||||||
B = ctx->state[1];
|
|
||||||
C = ctx->state[2];
|
|
||||||
D = ctx->state[3];
|
|
||||||
E = ctx->state[4];
|
|
||||||
|
|
||||||
#define F(x,y,z) (z ^ (x & (y ^ z)))
|
|
||||||
#define K 0x5A827999
|
|
||||||
|
|
||||||
P( A, B, C, D, E, W[0] );
|
|
||||||
P( E, A, B, C, D, W[1] );
|
|
||||||
P( D, E, A, B, C, W[2] );
|
|
||||||
P( C, D, E, A, B, W[3] );
|
|
||||||
P( B, C, D, E, A, W[4] );
|
|
||||||
P( A, B, C, D, E, W[5] );
|
|
||||||
P( E, A, B, C, D, W[6] );
|
|
||||||
P( D, E, A, B, C, W[7] );
|
|
||||||
P( C, D, E, A, B, W[8] );
|
|
||||||
P( B, C, D, E, A, W[9] );
|
|
||||||
P( A, B, C, D, E, W[10] );
|
|
||||||
P( E, A, B, C, D, W[11] );
|
|
||||||
P( D, E, A, B, C, W[12] );
|
|
||||||
P( C, D, E, A, B, W[13] );
|
|
||||||
P( B, C, D, E, A, W[14] );
|
|
||||||
P( A, B, C, D, E, W[15] );
|
|
||||||
P( E, A, B, C, D, R(16) );
|
|
||||||
P( D, E, A, B, C, R(17) );
|
|
||||||
P( C, D, E, A, B, R(18) );
|
|
||||||
P( B, C, D, E, A, R(19) );
|
|
||||||
|
|
||||||
#undef K
|
|
||||||
#undef F
|
|
||||||
|
|
||||||
#define F(x,y,z) (x ^ y ^ z)
|
|
||||||
#define K 0x6ED9EBA1
|
|
||||||
|
|
||||||
P( A, B, C, D, E, R(20) );
|
|
||||||
P( E, A, B, C, D, R(21) );
|
|
||||||
P( D, E, A, B, C, R(22) );
|
|
||||||
P( C, D, E, A, B, R(23) );
|
|
||||||
P( B, C, D, E, A, R(24) );
|
|
||||||
P( A, B, C, D, E, R(25) );
|
|
||||||
P( E, A, B, C, D, R(26) );
|
|
||||||
P( D, E, A, B, C, R(27) );
|
|
||||||
P( C, D, E, A, B, R(28) );
|
|
||||||
P( B, C, D, E, A, R(29) );
|
|
||||||
P( A, B, C, D, E, R(30) );
|
|
||||||
P( E, A, B, C, D, R(31) );
|
|
||||||
P( D, E, A, B, C, R(32) );
|
|
||||||
P( C, D, E, A, B, R(33) );
|
|
||||||
P( B, C, D, E, A, R(34) );
|
|
||||||
P( A, B, C, D, E, R(35) );
|
|
||||||
P( E, A, B, C, D, R(36) );
|
|
||||||
P( D, E, A, B, C, R(37) );
|
|
||||||
P( C, D, E, A, B, R(38) );
|
|
||||||
P( B, C, D, E, A, R(39) );
|
|
||||||
|
|
||||||
#undef K
|
|
||||||
#undef F
|
|
||||||
|
|
||||||
#define F(x,y,z) ((x & y) | (z & (x | y)))
|
|
||||||
#define K 0x8F1BBCDC
|
|
||||||
|
|
||||||
P( A, B, C, D, E, R(40) );
|
|
||||||
P( E, A, B, C, D, R(41) );
|
|
||||||
P( D, E, A, B, C, R(42) );
|
|
||||||
P( C, D, E, A, B, R(43) );
|
|
||||||
P( B, C, D, E, A, R(44) );
|
|
||||||
P( A, B, C, D, E, R(45) );
|
|
||||||
P( E, A, B, C, D, R(46) );
|
|
||||||
P( D, E, A, B, C, R(47) );
|
|
||||||
P( C, D, E, A, B, R(48) );
|
|
||||||
P( B, C, D, E, A, R(49) );
|
|
||||||
P( A, B, C, D, E, R(50) );
|
|
||||||
P( E, A, B, C, D, R(51) );
|
|
||||||
P( D, E, A, B, C, R(52) );
|
|
||||||
P( C, D, E, A, B, R(53) );
|
|
||||||
P( B, C, D, E, A, R(54) );
|
|
||||||
P( A, B, C, D, E, R(55) );
|
|
||||||
P( E, A, B, C, D, R(56) );
|
|
||||||
P( D, E, A, B, C, R(57) );
|
|
||||||
P( C, D, E, A, B, R(58) );
|
|
||||||
P( B, C, D, E, A, R(59) );
|
|
||||||
|
|
||||||
#undef K
|
|
||||||
#undef F
|
|
||||||
|
|
||||||
#define F(x,y,z) (x ^ y ^ z)
|
|
||||||
#define K 0xCA62C1D6
|
|
||||||
|
|
||||||
P( A, B, C, D, E, R(60) );
|
|
||||||
P( E, A, B, C, D, R(61) );
|
|
||||||
P( D, E, A, B, C, R(62) );
|
|
||||||
P( C, D, E, A, B, R(63) );
|
|
||||||
P( B, C, D, E, A, R(64) );
|
|
||||||
P( A, B, C, D, E, R(65) );
|
|
||||||
P( E, A, B, C, D, R(66) );
|
|
||||||
P( D, E, A, B, C, R(67) );
|
|
||||||
P( C, D, E, A, B, R(68) );
|
|
||||||
P( B, C, D, E, A, R(69) );
|
|
||||||
P( A, B, C, D, E, R(70) );
|
|
||||||
P( E, A, B, C, D, R(71) );
|
|
||||||
P( D, E, A, B, C, R(72) );
|
|
||||||
P( C, D, E, A, B, R(73) );
|
|
||||||
P( B, C, D, E, A, R(74) );
|
|
||||||
P( A, B, C, D, E, R(75) );
|
|
||||||
P( E, A, B, C, D, R(76) );
|
|
||||||
P( D, E, A, B, C, R(77) );
|
|
||||||
P( C, D, E, A, B, R(78) );
|
|
||||||
P( B, C, D, E, A, R(79) );
|
|
||||||
|
|
||||||
#undef K
|
|
||||||
#undef F
|
|
||||||
|
|
||||||
ctx->state[0] += A;
|
|
||||||
ctx->state[1] += B;
|
|
||||||
ctx->state[2] += C;
|
|
||||||
ctx->state[3] += D;
|
|
||||||
ctx->state[4] += E;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* SHA-1 process buffer
|
|
||||||
*/
|
|
||||||
void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen )
|
|
||||||
{
|
|
||||||
size_t fill;
|
|
||||||
uint32_t left;
|
|
||||||
|
|
||||||
if( ilen == 0 )
|
|
||||||
return;
|
|
||||||
|
|
||||||
left = ctx->total[0] & 0x3F;
|
|
||||||
fill = 64 - left;
|
|
||||||
|
|
||||||
ctx->total[0] += (uint32_t) ilen;
|
|
||||||
ctx->total[0] &= 0xFFFFFFFF;
|
|
||||||
|
|
||||||
if( ctx->total[0] < (uint32_t) ilen )
|
|
||||||
ctx->total[1]++;
|
|
||||||
|
|
||||||
if( left && ilen >= fill )
|
|
||||||
{
|
|
||||||
memcpy( (void *) (ctx->buffer + left), input, fill );
|
|
||||||
sha1_process( ctx, ctx->buffer );
|
|
||||||
input += fill;
|
|
||||||
ilen -= fill;
|
|
||||||
left = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
while( ilen >= 64 )
|
|
||||||
{
|
|
||||||
sha1_process( ctx, input );
|
|
||||||
input += 64;
|
|
||||||
ilen -= 64;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( ilen > 0 )
|
|
||||||
memcpy( (void *) (ctx->buffer + left), input, ilen );
|
|
||||||
}
|
|
||||||
|
|
||||||
static const unsigned char sha1_padding[64] =
|
|
||||||
{
|
|
||||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* SHA-1 final digest
|
|
||||||
*/
|
|
||||||
void sha1_finish( sha1_context *ctx, unsigned char output[20] )
|
|
||||||
{
|
|
||||||
uint32_t last, padn;
|
|
||||||
uint32_t high, low;
|
|
||||||
unsigned char msglen[8];
|
|
||||||
|
|
||||||
high = ( ctx->total[0] >> 29 )
|
|
||||||
| ( ctx->total[1] << 3 );
|
|
||||||
low = ( ctx->total[0] << 3 );
|
|
||||||
|
|
||||||
PUT_UINT32_BE( high, msglen, 0 );
|
|
||||||
PUT_UINT32_BE( low, msglen, 4 );
|
|
||||||
|
|
||||||
last = ctx->total[0] & 0x3F;
|
|
||||||
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
|
|
||||||
|
|
||||||
sha1_update( ctx, sha1_padding, padn );
|
|
||||||
sha1_update( ctx, msglen, 8 );
|
|
||||||
|
|
||||||
PUT_UINT32_BE( ctx->state[0], output, 0 );
|
|
||||||
PUT_UINT32_BE( ctx->state[1], output, 4 );
|
|
||||||
PUT_UINT32_BE( ctx->state[2], output, 8 );
|
|
||||||
PUT_UINT32_BE( ctx->state[3], output, 12 );
|
|
||||||
PUT_UINT32_BE( ctx->state[4], output, 16 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* output = SHA-1( input buffer )
|
|
||||||
*/
|
|
||||||
void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] )
|
|
||||||
{
|
|
||||||
sha1_context ctx;
|
|
||||||
|
|
||||||
sha1_init( &ctx );
|
|
||||||
sha1_starts( &ctx );
|
|
||||||
sha1_update( &ctx, input, ilen );
|
|
||||||
sha1_finish( &ctx, output );
|
|
||||||
sha1_free( &ctx );
|
|
||||||
}
|
|
15
makefile
15
makefile
@@ -1,15 +1,17 @@
|
|||||||
cc_cross=/home/wangyu/Desktop/arm-2014.05/bin/arm-none-linux-gnueabi-g++
|
cc_cross=/home/wangyu/Desktop/arm-2014.05/bin/arm-none-linux-gnueabi-g++
|
||||||
cc_local=g++
|
cc_local=g++
|
||||||
|
#cc_local=/opt/cross/x86_64-linux-musl/bin/x86_64-linux-musl-g++
|
||||||
#cc_mips34kc=/toolchains/OpenWrt-SDK-ar71xx-for-linux-x86_64-gcc-4.8-linaro_uClibc-0.9.33.2/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-g++
|
#cc_mips34kc=/toolchains/OpenWrt-SDK-ar71xx-for-linux-x86_64-gcc-4.8-linaro_uClibc-0.9.33.2/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-g++
|
||||||
cc_mips24kc_be=/toolchains/lede-sdk-17.01.2-ar71xx-generic_gcc-5.4.0_musl-1.1.16.Linux-x86_64/staging_dir/toolchain-mips_24kc_gcc-5.4.0_musl-1.1.16/bin/mips-openwrt-linux-musl-g++
|
cc_mips24kc_be=/toolchains/lede-sdk-17.01.2-ar71xx-generic_gcc-5.4.0_musl-1.1.16.Linux-x86_64/staging_dir/toolchain-mips_24kc_gcc-5.4.0_musl-1.1.16/bin/mips-openwrt-linux-musl-g++
|
||||||
cc_mips24kc_le=/toolchains/lede-sdk-17.01.2-ramips-mt7621_gcc-5.4.0_musl-1.1.16.Linux-x86_64/staging_dir/toolchain-mipsel_24kc_gcc-5.4.0_musl-1.1.16/bin/mipsel-openwrt-linux-musl-g++
|
cc_mips24kc_le=/toolchains/lede-sdk-17.01.2-ramips-mt7621_gcc-5.4.0_musl-1.1.16.Linux-x86_64/staging_dir/toolchain-mipsel_24kc_gcc-5.4.0_musl-1.1.16/bin/mipsel-openwrt-linux-musl-g++
|
||||||
#cc_arm= /toolchains/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabi/bin/arm-linux-gnueabi-g++ -march=armv6 -marm
|
#cc_arm= /toolchains/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabi/bin/arm-linux-gnueabi-g++ -march=armv6 -marm
|
||||||
cc_arm= /toolchains/arm-2014.05/bin/arm-none-linux-gnueabi-g++
|
cc_arm= /toolchains/arm-2014.05/bin/arm-none-linux-gnueabi-g++
|
||||||
|
#cc_arm=/toolchains/lede-sdk-17.01.2-brcm2708-bcm2708_gcc-5.4.0_musl-1.1.16_eabi.Linux-x86_64/staging_dir/toolchain-arm_arm1176jzf-s+vfp_gcc-5.4.0_musl-1.1.16_eabi/bin/arm-openwrt-linux-muslgnueabi-g++
|
||||||
#cc_bcm2708=/home/wangyu/raspberry/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-g++
|
#cc_bcm2708=/home/wangyu/raspberry/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-g++
|
||||||
FLAGS= -std=c++11 -Wall -Wextra -Wno-unused-variable -Wno-unused-parameter -Wno-missing-field-initializers
|
FLAGS= -std=c++11 -Wall -Wextra -Wno-unused-variable -Wno-unused-parameter -Wno-missing-field-initializers ${OPT}
|
||||||
|
|
||||||
COMMON=main.cpp lib/md5.c encrypt.cpp log.cpp network.cpp common.cpp connection.cpp misc.cpp fd_manager.cpp -lpthread
|
COMMON=main.cpp lib/md5.cpp lib/pbkdf2-sha1.cpp lib/pbkdf2-sha256.cpp encrypt.cpp log.cpp network.cpp common.cpp connection.cpp misc.cpp fd_manager.cpp -lpthread
|
||||||
SOURCES= $(COMMON) lib/aes_faster_c/aes.c lib/aes_faster_c/wrapper.c
|
SOURCES= $(COMMON) lib/aes_faster_c/aes.cpp lib/aes_faster_c/wrapper.cpp
|
||||||
SOURCES_TINY_AES= $(COMMON) lib/aes.c
|
SOURCES_TINY_AES= $(COMMON) lib/aes.c
|
||||||
SOURCES_AES_ACC=$(COMMON) $(wildcard lib/aes_acc/aes*.c)
|
SOURCES_AES_ACC=$(COMMON) $(wildcard lib/aes_acc/aes*.c)
|
||||||
|
|
||||||
@@ -47,6 +49,10 @@ mips24kc_le_asm_aes: git_version
|
|||||||
# ${cc_bcm2708} -o ${NAME}_bcm2708 -I. ${SOURCES} ${FLAGS} -lrt -static -O3
|
# ${cc_bcm2708} -o ${NAME}_bcm2708 -I. ${SOURCES} ${FLAGS} -lrt -static -O3
|
||||||
amd64:git_version
|
amd64:git_version
|
||||||
${cc_local} -o ${NAME}_$@ -I. ${SOURCES} ${FLAGS} -lrt -static -O3
|
${cc_local} -o ${NAME}_$@ -I. ${SOURCES} ${FLAGS} -lrt -static -O3
|
||||||
|
|
||||||
|
amd64_perf:git_version
|
||||||
|
${cc_local} -o ${NAME}_$@ -I. ${SOURCES} ${FLAGS} -lrt -static -O0 -fno-omit-frame-pointer -g
|
||||||
|
|
||||||
amd64_hw_aes:git_version
|
amd64_hw_aes:git_version
|
||||||
${cc_local} -o ${NAME}_$@ -I. ${SOURCES_AES_ACC} ${FLAGS} -lrt -static -O3 lib/aes_acc/asm/x64.S
|
${cc_local} -o ${NAME}_$@ -I. ${SOURCES_AES_ACC} ${FLAGS} -lrt -static -O3 lib/aes_acc/asm/x64.S
|
||||||
x86:git_version
|
x86:git_version
|
||||||
@@ -56,6 +62,9 @@ x86_asm_aes:git_version
|
|||||||
arm:git_version
|
arm:git_version
|
||||||
${cc_arm} -o ${NAME}_$@ -I. ${SOURCES} ${FLAGS} -lrt -static -O3
|
${cc_arm} -o ${NAME}_$@ -I. ${SOURCES} ${FLAGS} -lrt -static -O3
|
||||||
|
|
||||||
|
arm_perf:git_version
|
||||||
|
${cc_arm} -o ${NAME}_$@ -I. ${SOURCES} ${FLAGS} -lrt -static -mapcs-frame -fno-omit-frame-pointer -g -O0 -lgcc_eh
|
||||||
|
|
||||||
arm_asm_aes:git_version
|
arm_asm_aes:git_version
|
||||||
${cc_arm} -o ${NAME}_$@ -I. ${SOURCES_AES_ACC} ${FLAGS} -lrt -static -O3 lib/aes_acc/asm/arm.S
|
${cc_arm} -o ${NAME}_$@ -I. ${SOURCES_AES_ACC} ${FLAGS} -lrt -static -O3 lib/aes_acc/asm/arm.S
|
||||||
|
|
||||||
|
316
misc.cpp
316
misc.cpp
@@ -18,16 +18,31 @@ int hb_len=1200;
|
|||||||
|
|
||||||
int mtu_warn=1375;//if a packet larger than mtu warn is receviced,there will be a warning
|
int mtu_warn=1375;//if a packet larger than mtu warn is receviced,there will be a warning
|
||||||
|
|
||||||
|
int max_rst_to_show=15;
|
||||||
|
|
||||||
|
int max_rst_allowed=-1;
|
||||||
|
|
||||||
|
int enable_dns_resolve=0;
|
||||||
|
|
||||||
|
int ttl_value=64;
|
||||||
|
|
||||||
fd_manager_t fd_manager;
|
fd_manager_t fd_manager;
|
||||||
|
|
||||||
char local_ip[100]="0.0.0.0", remote_ip[100]="255.255.255.255",source_ip[100]="0.0.0.0";//local_ip is for -l option,remote_ip for -r option,source for --source-ip
|
//char remote_address[max_address_len]="";
|
||||||
u32_t local_ip_uint32,remote_ip_uint32,source_ip_uint32;//convert from last line.
|
//char local_ip[100]="0.0.0.0", remote_ip[100]="255.255.255.255",source_ip[100]="0.0.0.0";//local_ip is for -l option,remote_ip for -r option,source for --source-ip
|
||||||
int local_port = -1, remote_port=-1,source_port=0;//similiar to local_ip remote_ip,buf for port.source_port=0 indicates --source-port is not enabled
|
//u32_t local_ip_uint32,remote_ip_uint32,source_ip_uint32;//convert from last line.
|
||||||
|
//int local_port = -1, remote_port=-1,source_port=0;//similiar to local_ip remote_ip,buf for port.source_port=0 indicates --source-port is not enabled
|
||||||
|
address_t local_addr,remote_addr,source_addr;
|
||||||
|
|
||||||
|
my_ip_t bind_addr;
|
||||||
|
|
||||||
|
int source_port=-1;
|
||||||
|
|
||||||
|
int bind_addr_used=0;
|
||||||
int force_source_ip=0; //if --source-ip is enabled
|
int force_source_ip=0; //if --source-ip is enabled
|
||||||
|
int force_source_port=0;
|
||||||
|
|
||||||
id_t const_id=0;//an id used for connection recovery,its generated randomly,it never change since its generated
|
my_id_t const_id=0;//an id used for connection recovery,its generated randomly,it never change since its generated
|
||||||
|
|
||||||
int udp_fd=-1; //for client only. client use this fd to listen and handle udp connection
|
int udp_fd=-1; //for client only. client use this fd to listen and handle udp connection
|
||||||
int bind_fd=-1; //bind only,never send or recv. its just a dummy fd for bind,so that other program wont occupy the same port
|
int bind_fd=-1; //bind only,never send or recv. its just a dummy fd for bind,so that other program wont occupy the same port
|
||||||
@@ -44,12 +59,18 @@ int auto_add_iptables_rule=0;//if -a is set
|
|||||||
int generate_iptables_rule=0;//if -g is set
|
int generate_iptables_rule=0;//if -g is set
|
||||||
int generate_iptables_rule_add=0;// if --gen-add is set
|
int generate_iptables_rule_add=0;// if --gen-add is set
|
||||||
|
|
||||||
|
int retry_on_error=0;
|
||||||
|
|
||||||
int debug_resend=0; // debug only
|
int debug_resend=0; // debug only
|
||||||
|
|
||||||
char key_string[1000]= "secret key";// -k option
|
char key_string[1000]= "secret key";// -k option
|
||||||
|
|
||||||
char fifo_file[1000]="";
|
char fifo_file[1000]="";
|
||||||
|
|
||||||
|
int clear_iptables=0;
|
||||||
|
int wait_xtables_lock=0;
|
||||||
|
string iptables_command0="iptables/ip6tables ";
|
||||||
|
string iptables_command="";
|
||||||
string iptables_pattern="";
|
string iptables_pattern="";
|
||||||
int iptables_rule_added=0;
|
int iptables_rule_added=0;
|
||||||
int iptables_rule_keeped=0;
|
int iptables_rule_keeped=0;
|
||||||
@@ -57,6 +78,7 @@ int iptables_rule_keep_index=0;
|
|||||||
|
|
||||||
program_mode_t program_mode=unset_mode;//0 unset; 1client 2server
|
program_mode_t program_mode=unset_mode;//0 unset; 1client 2server
|
||||||
raw_mode_t raw_mode=mode_faketcp;
|
raw_mode_t raw_mode=mode_faketcp;
|
||||||
|
u32_t raw_ip_version=(u32_t)-1;
|
||||||
unordered_map<int, const char*> raw_mode_tostring = {{mode_faketcp, "faketcp"}, {mode_udp, "udp"}, {mode_icmp, "icmp"}};
|
unordered_map<int, const char*> raw_mode_tostring = {{mode_faketcp, "faketcp"}, {mode_udp, "udp"}, {mode_icmp, "icmp"}};
|
||||||
|
|
||||||
int about_to_exit=0;
|
int about_to_exit=0;
|
||||||
@@ -66,7 +88,7 @@ int about_to_exit=0;
|
|||||||
|
|
||||||
|
|
||||||
int socket_buf_size=1024*1024;
|
int socket_buf_size=1024*1024;
|
||||||
int force_socket_buf=0;
|
|
||||||
|
|
||||||
//char lower_level_arg[1000];
|
//char lower_level_arg[1000];
|
||||||
int process_lower_level_arg()//handle --lower-level option
|
int process_lower_level_arg()//handle --lower-level option
|
||||||
@@ -108,14 +130,14 @@ void print_help()
|
|||||||
printf("repository: https://github.com/wangyu-/udp2raw-tunnel\n");
|
printf("repository: https://github.com/wangyu-/udp2raw-tunnel\n");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("usage:\n");
|
printf("usage:\n");
|
||||||
printf(" run as client : ./this_program -c -l local_listen_ip:local_port -r server_ip:server_port [options]\n");
|
printf(" run as client : ./this_program -c -l local_listen_ip:local_port -r server_address:server_port [options]\n");
|
||||||
printf(" run as server : ./this_program -s -l server_listen_ip:server_port -r remote_ip:remote_port [options]\n");
|
printf(" run as server : ./this_program -s -l server_listen_ip:server_port -r remote_address:remote_port [options]\n");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
printf("common options,these options must be same on both side:\n");
|
printf("common options,these options must be same on both side:\n");
|
||||||
printf(" --raw-mode <string> avaliable values:faketcp(default),udp,icmp\n");
|
printf(" --raw-mode <string> avaliable values:faketcp(default),udp,icmp\n");
|
||||||
printf(" -k,--key <string> password to gen symetric key,default:\"secret key\"\n");
|
printf(" -k,--key <string> password to gen symetric key,default:\"secret key\"\n");
|
||||||
printf(" --cipher-mode <string> avaliable values:aes128cbc(default),xor,none\n");
|
printf(" --cipher-mode <string> avaliable values:aes128cfb,aes128cbc(default),xor,none\n");
|
||||||
printf(" --auth-mode <string> avaliable values:md5(default),crc32,simple,none\n");
|
printf(" --auth-mode <string> avaliable values:hmac_sha1,md5(default),crc32,simple,none\n");
|
||||||
printf(" -a,--auto-rule auto add (and delete) iptables rule\n");
|
printf(" -a,--auto-rule auto add (and delete) iptables rule\n");
|
||||||
printf(" -g,--gen-rule generate iptables rule then exit,so that you can copy and\n");
|
printf(" -g,--gen-rule generate iptables rule then exit,so that you can copy and\n");
|
||||||
printf(" add it manually.overrides -a\n");
|
printf(" add it manually.overrides -a\n");
|
||||||
@@ -140,6 +162,7 @@ void print_help()
|
|||||||
printf(" --disable-bpf disable the kernel space filter,most time its not necessary\n");
|
printf(" --disable-bpf disable the kernel space filter,most time its not necessary\n");
|
||||||
printf(" unless you suspect there is a bug\n");
|
printf(" unless you suspect there is a bug\n");
|
||||||
// printf("\n");
|
// printf("\n");
|
||||||
|
printf(" --dev <string> bind raw socket to a device, not necessary but improves performance\n");
|
||||||
printf(" --sock-buf <number> buf size for socket,>=10 and <=10240,unit:kbyte,default:1024\n");
|
printf(" --sock-buf <number> buf size for socket,>=10 and <=10240,unit:kbyte,default:1024\n");
|
||||||
printf(" --force-sock-buf bypass system limitation while setting sock-buf\n");
|
printf(" --force-sock-buf bypass system limitation while setting sock-buf\n");
|
||||||
printf(" --seq-mode <number> seq increase mode for faketcp:\n");
|
printf(" --seq-mode <number> seq increase mode for faketcp:\n");
|
||||||
@@ -153,11 +176,13 @@ void print_help()
|
|||||||
printf(" --lower-level <string> send packets at OSI level 2, format:'if_name#dest_mac_adress'\n");
|
printf(" --lower-level <string> send packets at OSI level 2, format:'if_name#dest_mac_adress'\n");
|
||||||
printf(" ie:'eth0#00:23:45:67:89:b9'.or try '--lower-level auto' to obtain\n");
|
printf(" ie:'eth0#00:23:45:67:89:b9'.or try '--lower-level auto' to obtain\n");
|
||||||
printf(" the parameter automatically,specify it manually if 'auto' failed\n");
|
printf(" the parameter automatically,specify it manually if 'auto' failed\n");
|
||||||
|
printf(" --wait-lock wait for xtables lock while invoking iptables, need iptables v1.4.20+\n");
|
||||||
printf(" --gen-add generate iptables rule and add it permanently,then exit.overrides -g\n");
|
printf(" --gen-add generate iptables rule and add it permanently,then exit.overrides -g\n");
|
||||||
printf(" --keep-rule monitor iptables and auto re-add if necessary.implys -a\n");
|
printf(" --keep-rule monitor iptables and auto re-add if necessary.implys -a\n");
|
||||||
printf(" --hb-len <number> length of heart-beat packet, >=0 and <=1500\n");
|
printf(" --hb-len <number> length of heart-beat packet, >=0 and <=1500\n");
|
||||||
printf(" --mtu-warn <number> mtu warning threshold, unit:byte, default:1375\n");
|
printf(" --mtu-warn <number> mtu warning threshold, unit:byte, default:1375\n");
|
||||||
printf(" --clear clear any iptables rules added by this program.overrides everything\n");
|
printf(" --clear clear any iptables rules added by this program.overrides everything\n");
|
||||||
|
printf(" --retry-on-error retry on error, allow to start udp2raw before network is initialized\n");
|
||||||
printf(" -h,--help print this help message\n");
|
printf(" -h,--help print this help message\n");
|
||||||
|
|
||||||
//printf("common options,these options must be same on both side\n");
|
//printf("common options,these options must be same on both side\n");
|
||||||
@@ -245,6 +270,8 @@ void process_arg(int argc, char *argv[]) //process all options
|
|||||||
{"gen-rule", no_argument, 0, 'g'},
|
{"gen-rule", no_argument, 0, 'g'},
|
||||||
{"gen-add", no_argument, 0, 1},
|
{"gen-add", no_argument, 0, 1},
|
||||||
{"debug", no_argument, 0, 1},
|
{"debug", no_argument, 0, 1},
|
||||||
|
{"dev", required_argument, 0, 1},
|
||||||
|
{"retry-on-error", no_argument, 0, 1},
|
||||||
{"clear", no_argument, 0, 1},
|
{"clear", no_argument, 0, 1},
|
||||||
{"simple-rule", no_argument, 0, 1},
|
{"simple-rule", no_argument, 0, 1},
|
||||||
{"keep-rule", no_argument, 0, 1},
|
{"keep-rule", no_argument, 0, 1},
|
||||||
@@ -253,11 +280,16 @@ void process_arg(int argc, char *argv[]) //process all options
|
|||||||
{"seq-mode", required_argument, 0, 1},
|
{"seq-mode", required_argument, 0, 1},
|
||||||
{"conf-file", required_argument, 0, 1},
|
{"conf-file", required_argument, 0, 1},
|
||||||
{"force-sock-buf", no_argument, 0, 1},
|
{"force-sock-buf", no_argument, 0, 1},
|
||||||
|
{"wait-lock", no_argument, 0, 1},
|
||||||
{"random-drop", required_argument, 0, 1},
|
{"random-drop", required_argument, 0, 1},
|
||||||
{"fifo", required_argument, 0, 1},
|
{"fifo", required_argument, 0, 1},
|
||||||
{"hb-mode", required_argument, 0, 1},
|
{"hb-mode", required_argument, 0, 1},
|
||||||
{"hb-len", required_argument, 0, 1},
|
{"hb-len", required_argument, 0, 1},
|
||||||
{"mtu-warn", required_argument, 0, 1},
|
{"mtu-warn", required_argument, 0, 1},
|
||||||
|
{"max-rst-to-show", required_argument, 0, 1},
|
||||||
|
{"max-rst-allowed", required_argument, 0, 1},
|
||||||
|
{"set-ttl", required_argument, 0, 1},
|
||||||
|
{"dns-resolve", no_argument, 0, 1},
|
||||||
{NULL, 0, 0, 0}
|
{NULL, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -361,6 +393,13 @@ void process_arg(int argc, char *argv[]) //process all options
|
|||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'l':
|
case 'l':
|
||||||
no_l = 0;
|
no_l = 0;
|
||||||
|
local_addr.from_str(optarg);
|
||||||
|
if(local_addr.get_port()==22)
|
||||||
|
{
|
||||||
|
mylog(log_fatal,"port 22 not allowed\n");
|
||||||
|
myexit(-1);
|
||||||
|
}
|
||||||
|
/*
|
||||||
if (strchr(optarg, ':') != 0) {
|
if (strchr(optarg, ':') != 0) {
|
||||||
sscanf(optarg, "%[^:]:%d", local_ip, &local_port);
|
sscanf(optarg, "%[^:]:%d", local_ip, &local_port);
|
||||||
if(local_port==22)
|
if(local_port==22)
|
||||||
@@ -372,12 +411,19 @@ void process_arg(int argc, char *argv[]) //process all options
|
|||||||
mylog(log_fatal,"invalid parameter for -l ,%s,should be ip:port\n",optarg);
|
mylog(log_fatal,"invalid parameter for -l ,%s,should be ip:port\n",optarg);
|
||||||
myexit(-1);
|
myexit(-1);
|
||||||
|
|
||||||
}
|
}*/
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
no_r = 0;
|
no_r = 0;
|
||||||
|
remote_addr.from_str(optarg);
|
||||||
|
if(remote_addr.get_port()==22)
|
||||||
|
{
|
||||||
|
mylog(log_fatal,"port 22 not allowed\n");
|
||||||
|
myexit(-1);
|
||||||
|
}
|
||||||
|
/*
|
||||||
if (strchr(optarg, ':') != 0) {
|
if (strchr(optarg, ':') != 0) {
|
||||||
sscanf(optarg, "%[^:]:%d", remote_ip, &remote_port);
|
sscanf(optarg, "%[^:]:%d", remote_address, &remote_port);
|
||||||
if(remote_port==22)
|
if(remote_port==22)
|
||||||
{
|
{
|
||||||
mylog(log_fatal,"port 22 not allowed\n");
|
mylog(log_fatal,"port 22 not allowed\n");
|
||||||
@@ -386,7 +432,7 @@ void process_arg(int argc, char *argv[]) //process all options
|
|||||||
} else {
|
} else {
|
||||||
mylog(log_fatal,"invalid parameter for -r ,%s,should be ip:port\n",optarg);
|
mylog(log_fatal,"invalid parameter for -r ,%s,should be ip:port\n",optarg);
|
||||||
myexit(-1);
|
myexit(-1);
|
||||||
}
|
}*/
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
if(program_mode==0)
|
if(program_mode==0)
|
||||||
@@ -426,21 +472,15 @@ void process_arg(int argc, char *argv[]) //process all options
|
|||||||
mylog(log_debug,"option_index: %d\n",option_index);
|
mylog(log_debug,"option_index: %d\n",option_index);
|
||||||
if(strcmp(long_options[option_index].name,"clear")==0)
|
if(strcmp(long_options[option_index].name,"clear")==0)
|
||||||
{
|
{
|
||||||
char *output;
|
clear_iptables=1;
|
||||||
//int ret =system("iptables-save |grep udp2raw_dWRwMnJhdw|sed -n 's/^-A/iptables -D/p'|sh");
|
|
||||||
int ret =run_command("iptables -S|sed -n '/udp2rawDwrW/p'|sed -n 's/^-A/iptables -D/p'|sh",output);
|
|
||||||
|
|
||||||
int ret2 =run_command("iptables -S|sed -n '/udp2rawDwrW/p'|sed -n 's/^-N/iptables -X/p'|sh",output);
|
|
||||||
//system("iptables-save |grep udp2raw_dWRwMnJhdw|sed 's/^-A/iptables -D/'|sh");
|
|
||||||
//system("iptables-save|grep -v udp2raw_dWRwMnJhdw|iptables-restore");
|
|
||||||
mylog(log_info,"tried to clear all iptables rule created previously,return value %d %d\n",ret,ret2);
|
|
||||||
myexit(-1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(strcmp(long_options[option_index].name,"source-ip")==0)
|
else if(strcmp(long_options[option_index].name,"source-ip")==0)
|
||||||
{
|
{
|
||||||
mylog(log_debug,"parsing long option :source-ip\n");
|
mylog(log_debug,"parsing long option :source-ip\n");
|
||||||
sscanf(optarg, "%s", source_ip);
|
//sscanf(optarg, "%s", source_ip);
|
||||||
mylog(log_debug,"source: %s\n",source_ip);
|
source_addr.from_str_ip_only(optarg);
|
||||||
|
mylog(log_debug,"source: %s\n",source_addr.get_ip());
|
||||||
force_source_ip=1;
|
force_source_ip=1;
|
||||||
}
|
}
|
||||||
else if(strcmp(long_options[option_index].name,"source-port")==0)
|
else if(strcmp(long_options[option_index].name,"source-port")==0)
|
||||||
@@ -448,6 +488,7 @@ void process_arg(int argc, char *argv[]) //process all options
|
|||||||
mylog(log_debug,"parsing long option :source-port\n");
|
mylog(log_debug,"parsing long option :source-port\n");
|
||||||
sscanf(optarg, "%d", &source_port);
|
sscanf(optarg, "%d", &source_port);
|
||||||
mylog(log_info,"source: %d\n",source_port);
|
mylog(log_info,"source: %d\n",source_port);
|
||||||
|
force_source_port=1;
|
||||||
}
|
}
|
||||||
else if(strcmp(long_options[option_index].name,"raw-mode")==0)
|
else if(strcmp(long_options[option_index].name,"raw-mode")==0)
|
||||||
{
|
{
|
||||||
@@ -500,6 +541,7 @@ void process_arg(int argc, char *argv[]) //process all options
|
|||||||
if(i==cipher_end)
|
if(i==cipher_end)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
mylog(log_fatal,"no such cipher_mode %s\n",optarg);
|
||||||
myexit(-1);
|
myexit(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -533,6 +575,11 @@ void process_arg(int argc, char *argv[]) //process all options
|
|||||||
debug_flag=1;
|
debug_flag=1;
|
||||||
//enable_log_color=0;
|
//enable_log_color=0;
|
||||||
}
|
}
|
||||||
|
else if(strcmp(long_options[option_index].name,"dev")==0)
|
||||||
|
{
|
||||||
|
sscanf(optarg,"%s",dev);
|
||||||
|
//enable_log_color=0;
|
||||||
|
}
|
||||||
else if(strcmp(long_options[option_index].name,"debug-resend")==0)
|
else if(strcmp(long_options[option_index].name,"debug-resend")==0)
|
||||||
{
|
{
|
||||||
//debug_resend=1;
|
//debug_resend=1;
|
||||||
@@ -546,6 +593,14 @@ void process_arg(int argc, char *argv[]) //process all options
|
|||||||
{
|
{
|
||||||
force_socket_buf=1;
|
force_socket_buf=1;
|
||||||
}
|
}
|
||||||
|
else if(strcmp(long_options[option_index].name,"retry-on-error")==0)
|
||||||
|
{
|
||||||
|
retry_on_error=1;
|
||||||
|
}
|
||||||
|
else if(strcmp(long_options[option_index].name,"wait-lock")==0)
|
||||||
|
{
|
||||||
|
wait_xtables_lock=1;
|
||||||
|
}
|
||||||
else if(strcmp(long_options[option_index].name,"disable-bpf")==0)
|
else if(strcmp(long_options[option_index].name,"disable-bpf")==0)
|
||||||
{
|
{
|
||||||
disable_bpf_filter=1;
|
disable_bpf_filter=1;
|
||||||
@@ -618,6 +673,30 @@ void process_arg(int argc, char *argv[]) //process all options
|
|||||||
assert(mtu_warn>0);
|
assert(mtu_warn>0);
|
||||||
mylog(log_info,"mtu_warn=%d \n",mtu_warn);
|
mylog(log_info,"mtu_warn=%d \n",mtu_warn);
|
||||||
}
|
}
|
||||||
|
else if(strcmp(long_options[option_index].name,"max-rst-to-show")==0)
|
||||||
|
{
|
||||||
|
sscanf(optarg,"%d",&max_rst_to_show);
|
||||||
|
assert(max_rst_to_show>=-1);
|
||||||
|
mylog(log_info,"max_rst_to_show=%d \n",max_rst_to_show);
|
||||||
|
}
|
||||||
|
else if(strcmp(long_options[option_index].name,"max-rst-allowed")==0)
|
||||||
|
{
|
||||||
|
sscanf(optarg,"%d",&max_rst_allowed);
|
||||||
|
assert(max_rst_allowed>=-1);
|
||||||
|
mylog(log_info,"max_rst_allowed=%d \n",max_rst_allowed);
|
||||||
|
}
|
||||||
|
else if(strcmp(long_options[option_index].name,"set-ttl")==0)
|
||||||
|
{
|
||||||
|
sscanf(optarg,"%d",&ttl_value);
|
||||||
|
assert(ttl_value>=0&&ttl_value<=255);
|
||||||
|
mylog(log_info,"ttl_value=%d\n",ttl_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if(strcmp(long_options[option_index].name,"dns-resolve")==0) // currently not used
|
||||||
|
{
|
||||||
|
enable_dns_resolve=1;
|
||||||
|
mylog(log_info,"dns-resolve enabled\n");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mylog(log_warn,"ignored unknown long option ,option_index:%d code:<%x>\n",option_index, optopt);
|
mylog(log_warn,"ignored unknown long option ,option_index:%d code:<%x>\n",option_index, optopt);
|
||||||
@@ -640,6 +719,15 @@ void process_arg(int argc, char *argv[]) //process all options
|
|||||||
print_help();
|
print_help();
|
||||||
myexit(-1);
|
myexit(-1);
|
||||||
}
|
}
|
||||||
|
if(program_mode==client_mode)
|
||||||
|
{
|
||||||
|
raw_ip_version=remote_addr.get_type();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
raw_ip_version=local_addr.get_type();
|
||||||
|
}
|
||||||
|
|
||||||
//if(lower_level)
|
//if(lower_level)
|
||||||
//process_lower_level_arg();
|
//process_lower_level_arg();
|
||||||
|
|
||||||
@@ -652,12 +740,14 @@ void process_arg(int argc, char *argv[]) //process all options
|
|||||||
|
|
||||||
log_bare(log_info,"key=%s ",key_string);
|
log_bare(log_info,"key=%s ",key_string);
|
||||||
|
|
||||||
log_bare(log_info,"local_ip=%s ",local_ip);
|
log_bare(log_info,"local_addr=%s ",local_addr.get_str());
|
||||||
log_bare(log_info,"local_port=%d ",local_port);
|
log_bare(log_info,"remote_addr=%s ",remote_addr.get_str());
|
||||||
log_bare(log_info,"remote_ip=%s ",remote_ip);
|
|
||||||
log_bare(log_info,"remote_port=%d ",remote_port);
|
if(force_source_ip)
|
||||||
log_bare(log_info,"source_ip=%s ",source_ip);
|
log_bare(log_info,"source_addr=%s ",source_addr.get_ip());
|
||||||
log_bare(log_info,"source_port=%d ",source_port);
|
|
||||||
|
if(force_source_port)
|
||||||
|
log_bare(log_info,"source_port=%d ",source_port);
|
||||||
|
|
||||||
log_bare(log_info,"socket_buf_size=%d ",socket_buf_size);
|
log_bare(log_info,"socket_buf_size=%d ",socket_buf_size);
|
||||||
|
|
||||||
@@ -768,8 +858,38 @@ void *run_keep(void *none) //called in a new thread for --keep-rule option
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
}
|
}
|
||||||
void iptables_rule() // handles -a -g --gen-add --keep-rule
|
void iptables_rule() // handles -a -g --gen-add --keep-rule --clear --wait-lock
|
||||||
{
|
{
|
||||||
|
assert(raw_ip_version==AF_INET||raw_ip_version==AF_INET6);
|
||||||
|
|
||||||
|
if(raw_ip_version==AF_INET)
|
||||||
|
{
|
||||||
|
iptables_command0="iptables ";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
iptables_command0="ip6tables ";
|
||||||
|
if(!wait_xtables_lock)
|
||||||
|
{
|
||||||
|
iptables_command=iptables_command0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iptables_command=iptables_command0+"-w ";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(clear_iptables)
|
||||||
|
{
|
||||||
|
char *output;
|
||||||
|
//int ret =system("iptables-save |grep udp2raw_dWRwMnJhdw|sed -n 's/^-A/iptables -D/p'|sh");
|
||||||
|
int ret =run_command(iptables_command+"-S|sed -n '/udp2rawDwrW/p'|sed -n 's/^-A/"+iptables_command+"-D/p'|sh",output);
|
||||||
|
|
||||||
|
int ret2 =run_command(iptables_command+"-S|sed -n '/udp2rawDwrW/p'|sed -n 's/^-N/"+iptables_command+"-X/p'|sh",output);
|
||||||
|
//system("iptables-save |grep udp2raw_dWRwMnJhdw|sed 's/^-A/iptables -D/'|sh");
|
||||||
|
//system("iptables-save|grep -v udp2raw_dWRwMnJhdw|iptables-restore");
|
||||||
|
mylog(log_info,"tried to clear all iptables rule created previously,return value %d %d\n",ret,ret2);
|
||||||
|
myexit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
if(auto_add_iptables_rule&&generate_iptables_rule)
|
if(auto_add_iptables_rule&&generate_iptables_rule)
|
||||||
{
|
{
|
||||||
mylog(log_warn," -g overrides -a\n");
|
mylog(log_warn," -g overrides -a\n");
|
||||||
@@ -795,43 +915,61 @@ void iptables_rule() // handles -a -g --gen-add --keep-rule
|
|||||||
|
|
||||||
if(program_mode==client_mode)
|
if(program_mode==client_mode)
|
||||||
{
|
{
|
||||||
|
tmp_pattern[0]=0;
|
||||||
if(raw_mode==mode_faketcp)
|
if(raw_mode==mode_faketcp)
|
||||||
{
|
{
|
||||||
sprintf(tmp_pattern,"-s %s/32 -p tcp -m tcp --sport %d",remote_ip,remote_port);
|
sprintf(tmp_pattern,"-s %s -p tcp -m tcp --sport %d",remote_addr.get_ip(),remote_addr.get_port());
|
||||||
}
|
}
|
||||||
if(raw_mode==mode_udp)
|
if(raw_mode==mode_udp)
|
||||||
{
|
{
|
||||||
sprintf(tmp_pattern,"-s %s/32 -p udp -m udp --sport %d",remote_ip,remote_port);
|
sprintf(tmp_pattern,"-s %s -p udp -m udp --sport %d",remote_addr.get_ip(),remote_addr.get_port());
|
||||||
}
|
}
|
||||||
if(raw_mode==mode_icmp)
|
if(raw_mode==mode_icmp)
|
||||||
{
|
{
|
||||||
sprintf(tmp_pattern,"-s %s/32 -p icmp",remote_ip);
|
if(raw_ip_version==AF_INET)
|
||||||
|
sprintf(tmp_pattern,"-s %s -p icmp --icmp-type 0",remote_addr.get_ip());
|
||||||
|
else
|
||||||
|
sprintf(tmp_pattern,"-s %s -p icmpv6 --icmpv6-type 129",remote_addr.get_ip());
|
||||||
}
|
}
|
||||||
pattern=tmp_pattern;
|
pattern+=tmp_pattern;
|
||||||
}
|
}
|
||||||
if(program_mode==server_mode)
|
if(program_mode==server_mode)
|
||||||
{
|
{
|
||||||
|
tmp_pattern[0]=0;
|
||||||
|
if(raw_ip_version==AF_INET)
|
||||||
|
{
|
||||||
|
if(local_addr.inner.ipv4.sin_addr.s_addr!=0)
|
||||||
|
{
|
||||||
|
sprintf(tmp_pattern,"-d %s ",local_addr.get_ip());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char zero_arr[16]={0};
|
||||||
|
if(memcmp(&local_addr.inner.ipv6.sin6_addr,zero_arr,16)!=0)
|
||||||
|
{
|
||||||
|
sprintf(tmp_pattern,"-d %s ",local_addr.get_ip());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pattern+=tmp_pattern;
|
||||||
|
|
||||||
|
tmp_pattern[0]=0;
|
||||||
if(raw_mode==mode_faketcp)
|
if(raw_mode==mode_faketcp)
|
||||||
{
|
{
|
||||||
sprintf(tmp_pattern,"-p tcp -m tcp --dport %d",local_port);
|
sprintf(tmp_pattern,"-p tcp -m tcp --dport %d",local_addr.get_port());
|
||||||
}
|
}
|
||||||
if(raw_mode==mode_udp)
|
if(raw_mode==mode_udp)
|
||||||
{
|
{
|
||||||
sprintf(tmp_pattern,"-p udp -m udp --dport %d",local_port);
|
sprintf(tmp_pattern,"-p udp -m udp --dport %d",local_addr.get_port());
|
||||||
}
|
}
|
||||||
if(raw_mode==mode_icmp)
|
if(raw_mode==mode_icmp)
|
||||||
{
|
{
|
||||||
if(local_ip_uint32==0)
|
if(raw_ip_version==AF_INET)
|
||||||
{
|
sprintf(tmp_pattern,"-p icmp --icmp-type 8");
|
||||||
sprintf(tmp_pattern,"-p icmp");
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
sprintf(tmp_pattern,"-p icmpv6 --icmpv6-type 128");
|
||||||
sprintf(tmp_pattern,"-d %s/32 -p icmp",local_ip);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pattern=tmp_pattern;
|
pattern+=tmp_pattern;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
if(!simple_rule)
|
if(!simple_rule)
|
||||||
@@ -857,22 +995,9 @@ void iptables_rule() // handles -a -g --gen-add --keep-rule
|
|||||||
|
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
if(auto_add_iptables_rule)
|
|
||||||
{
|
|
||||||
iptables_rule_init(pattern.c_str(),const_id,keep_rule);
|
|
||||||
if(keep_rule)
|
|
||||||
{
|
|
||||||
if(pthread_create(&keep_thread, NULL, run_keep, 0)) {
|
|
||||||
|
|
||||||
mylog(log_fatal, "Error creating thread\n");
|
|
||||||
myexit(-1);
|
|
||||||
}
|
|
||||||
keep_thread_running=1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(generate_iptables_rule)
|
if(generate_iptables_rule)
|
||||||
{
|
{
|
||||||
string rule="iptables -I INPUT ";
|
string rule=iptables_command+"-I INPUT ";
|
||||||
rule+=pattern;
|
rule+=pattern;
|
||||||
rule+=" -j DROP";
|
rule+=" -j DROP";
|
||||||
|
|
||||||
@@ -886,7 +1011,23 @@ void iptables_rule() // handles -a -g --gen-add --keep-rule
|
|||||||
myexit(0);
|
myexit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(auto_add_iptables_rule)
|
||||||
|
{
|
||||||
|
iptables_rule_init(pattern.c_str(),const_id,keep_rule);
|
||||||
|
if(keep_rule)
|
||||||
|
{
|
||||||
|
if(pthread_create(&keep_thread, NULL, run_keep, 0)) {
|
||||||
|
|
||||||
|
mylog(log_fatal, "Error creating thread\n");
|
||||||
|
myexit(-1);
|
||||||
|
}
|
||||||
|
keep_thread_running=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mylog(log_warn," -a has not been set, make sure you have added the needed iptables rules manually\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int unit_test()
|
int unit_test()
|
||||||
@@ -1042,31 +1183,6 @@ int handle_lower_level(raw_info_t &raw_info)//fill lower_level info,when --lower
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
int add_iptables_rule(const char * s)
|
|
||||||
{
|
|
||||||
|
|
||||||
iptables_pattern=s;
|
|
||||||
|
|
||||||
string rule="iptables -I INPUT ";
|
|
||||||
rule+=iptables_pattern;
|
|
||||||
rule+=" -j DROP";
|
|
||||||
|
|
||||||
char *output;
|
|
||||||
if(run_command(rule.c_str(),output)==0)
|
|
||||||
{
|
|
||||||
mylog(log_warn,"auto added iptables rule by: %s\n",rule.c_str());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mylog(log_fatal,"auto added iptables failed by: %s\n",rule.c_str());
|
|
||||||
//mylog(log_fatal,"reason : %s\n",strerror(errno));
|
|
||||||
myexit(-1);
|
|
||||||
}
|
|
||||||
iptables_rule_added=1;
|
|
||||||
return 0;
|
|
||||||
}*/
|
|
||||||
string chain[2];
|
string chain[2];
|
||||||
string rule_keep[2];
|
string rule_keep[2];
|
||||||
string rule_keep_add[2];
|
string rule_keep_add[2];
|
||||||
@@ -1081,14 +1197,14 @@ int iptables_gen_add(const char * s,u32_t const_id)
|
|||||||
iptables_pattern=s;
|
iptables_pattern=s;
|
||||||
chain[0] =dummy+ "udp2rawDwrW_C";
|
chain[0] =dummy+ "udp2rawDwrW_C";
|
||||||
rule_keep[0]=dummy+ iptables_pattern+" -j " +chain[0];
|
rule_keep[0]=dummy+ iptables_pattern+" -j " +chain[0];
|
||||||
rule_keep_add[0]=dummy+"iptables -I INPUT "+rule_keep[0];
|
rule_keep_add[0]=iptables_command+"-I INPUT "+rule_keep[0];
|
||||||
|
|
||||||
char *output;
|
char *output;
|
||||||
run_command(dummy+"iptables -N "+chain[0],output,show_none);
|
run_command(iptables_command+"-N "+chain[0],output,show_none);
|
||||||
run_command(dummy+"iptables -F "+chain[0],output);
|
run_command(iptables_command+"-F "+chain[0],output);
|
||||||
run_command(dummy+"iptables -I "+chain[0] + " -j DROP",output);
|
run_command(iptables_command+"-I "+chain[0] + " -j DROP",output);
|
||||||
|
|
||||||
rule_keep_del[0]=dummy+"iptables -D INPUT "+rule_keep[0];
|
rule_keep_del[0]=iptables_command+"-D INPUT "+rule_keep[0];
|
||||||
|
|
||||||
run_command(rule_keep_del[0],output,show_none);
|
run_command(rule_keep_del[0],output,show_none);
|
||||||
run_command(rule_keep_del[0],output,show_none);
|
run_command(rule_keep_del[0],output,show_none);
|
||||||
@@ -1116,11 +1232,11 @@ int iptables_rule_init(const char * s,u32_t const_id,int keep)
|
|||||||
rule_keep[0]=dummy+ iptables_pattern+" -j " +chain[0];
|
rule_keep[0]=dummy+ iptables_pattern+" -j " +chain[0];
|
||||||
rule_keep[1]=dummy+ iptables_pattern+" -j " +chain[1];
|
rule_keep[1]=dummy+ iptables_pattern+" -j " +chain[1];
|
||||||
|
|
||||||
rule_keep_add[0]=dummy+"iptables -I INPUT "+rule_keep[0];
|
rule_keep_add[0]=iptables_command+"-I INPUT "+rule_keep[0];
|
||||||
rule_keep_add[1]=dummy+"iptables -I INPUT "+rule_keep[1];
|
rule_keep_add[1]=iptables_command+"-I INPUT "+rule_keep[1];
|
||||||
|
|
||||||
rule_keep_del[0]=dummy+"iptables -D INPUT "+rule_keep[0];
|
rule_keep_del[0]=iptables_command+"-D INPUT "+rule_keep[0];
|
||||||
rule_keep_del[1]=dummy+"iptables -D INPUT "+rule_keep[1];
|
rule_keep_del[1]=iptables_command+"-D INPUT "+rule_keep[1];
|
||||||
|
|
||||||
keep_rule_last_time=get_current_time();
|
keep_rule_last_time=get_current_time();
|
||||||
|
|
||||||
@@ -1128,9 +1244,9 @@ int iptables_rule_init(const char * s,u32_t const_id,int keep)
|
|||||||
|
|
||||||
for(int i=0;i<=iptables_rule_keeped;i++)
|
for(int i=0;i<=iptables_rule_keeped;i++)
|
||||||
{
|
{
|
||||||
run_command(dummy+"iptables -N "+chain[i],output);
|
run_command(iptables_command+"-N "+chain[i],output);
|
||||||
run_command(dummy+"iptables -F "+chain[i],output);
|
run_command(iptables_command+"-F "+chain[i],output);
|
||||||
run_command(dummy+"iptables -I "+chain[i] + " -j DROP",output);
|
run_command(iptables_command+"-I "+chain[i] + " -j DROP",output);
|
||||||
|
|
||||||
if(run_command(rule_keep_add[i],output)!=0)
|
if(run_command(rule_keep_add[i],output)!=0)
|
||||||
{
|
{
|
||||||
@@ -1167,12 +1283,12 @@ int keep_iptables_rule() //magic to work on a machine without grep/iptables --c
|
|||||||
|
|
||||||
int i=iptables_rule_keep_index;
|
int i=iptables_rule_keep_index;
|
||||||
|
|
||||||
run_command(dummy + "iptables -N " + chain[i], output,show_none);
|
run_command(iptables_command + "-N " + chain[i], output,show_none);
|
||||||
|
|
||||||
if (run_command(dummy + "iptables -F " + chain[i], output,show_none) != 0)
|
if (run_command(iptables_command + "-F " + chain[i], output,show_none) != 0)
|
||||||
mylog(log_warn, "iptables -F failed %d\n",i);
|
mylog(log_warn, "iptables -F failed %d\n",i);
|
||||||
|
|
||||||
if (run_command(dummy + "iptables -I " + chain[i] + " -j DROP",output,show_none) != 0)
|
if (run_command(iptables_command + "-I " + chain[i] + " -j DROP",output,show_none) != 0)
|
||||||
mylog(log_warn, "iptables -I failed %d\n",i);
|
mylog(log_warn, "iptables -I failed %d\n",i);
|
||||||
|
|
||||||
if (run_command(rule_keep_del[i], output,show_none) != 0)
|
if (run_command(rule_keep_del[i], output,show_none) != 0)
|
||||||
@@ -1196,8 +1312,8 @@ int clear_iptables_rule()
|
|||||||
for(int i=0;i<=iptables_rule_keeped;i++ )
|
for(int i=0;i<=iptables_rule_keeped;i++ )
|
||||||
{
|
{
|
||||||
run_command(rule_keep_del[i],output);
|
run_command(rule_keep_del[i],output);
|
||||||
run_command(dummy+"iptables -F "+chain[i],output);
|
run_command(iptables_command+"-F "+chain[i],output);
|
||||||
run_command(dummy+"iptables -X "+chain[i],output);
|
run_command(iptables_command+"-X "+chain[i],output);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
31
misc.h
31
misc.h
@@ -17,6 +17,14 @@ extern int hb_mode;
|
|||||||
extern int hb_len;
|
extern int hb_len;
|
||||||
extern int mtu_warn;
|
extern int mtu_warn;
|
||||||
|
|
||||||
|
extern int max_rst_allowed;
|
||||||
|
extern int max_rst_to_show;
|
||||||
|
|
||||||
|
extern int enable_dns_resolve;
|
||||||
|
|
||||||
|
extern int ttl_value;
|
||||||
|
|
||||||
|
|
||||||
const u32_t max_handshake_conn_num=10000;
|
const u32_t max_handshake_conn_num=10000;
|
||||||
const u32_t max_ready_conn_num=1000;
|
const u32_t max_ready_conn_num=1000;
|
||||||
const u32_t anti_replay_window_size=4000;
|
const u32_t anti_replay_window_size=4000;
|
||||||
@@ -51,7 +59,7 @@ const u32_t client_conn_uplink_timeout=client_conn_timeout+2000;//ms
|
|||||||
const uint32_t server_conn_timeout=conv_timeout+60000;//ms. this should be 60s+ longer than conv_timeout,so that conv_manager can destruct convs gradually,to avoid latency glicth
|
const uint32_t server_conn_timeout=conv_timeout+60000;//ms. this should be 60s+ longer than conv_timeout,so that conv_manager can destruct convs gradually,to avoid latency glicth
|
||||||
//const u32_t server_conn_timeout=conv_timeout+10000;//for test
|
//const u32_t server_conn_timeout=conv_timeout+10000;//for test
|
||||||
|
|
||||||
const u32_t iptables_rule_keep_interval=15;//unit: second;
|
const u32_t iptables_rule_keep_interval=20;//unit: second;
|
||||||
|
|
||||||
enum server_current_state_t {server_idle=0,server_handshake1,server_ready}; //server state machine
|
enum server_current_state_t {server_idle=0,server_handshake1,server_ready}; //server state machine
|
||||||
enum client_current_state_t {client_idle=0,client_tcp_handshake,client_handshake1,client_handshake2,client_ready};//client state machine
|
enum client_current_state_t {client_idle=0,client_tcp_handshake,client_handshake1,client_handshake2,client_ready};//client state machine
|
||||||
@@ -65,13 +73,21 @@ union current_state_t
|
|||||||
client_current_state_t client_current_state;
|
client_current_state_t client_current_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern char local_ip[100], remote_ip[100],source_ip[100];//local_ip is for -l option,remote_ip for -r option,source for --source-ip
|
//extern char remote_address[max_address_len];
|
||||||
extern u32_t local_ip_uint32,remote_ip_uint32,source_ip_uint32;//convert from last line.
|
//extern char local_ip[100], remote_ip[100],source_ip[100];//local_ip is for -l option,remote_ip for -r option,source for --source-ip
|
||||||
extern int local_port , remote_port,source_port;//similiar to local_ip remote_ip,buf for port.source_port=0 indicates --source-port is not enabled
|
//extern u32_t local_ip_uint32,remote_ip_uint32,source_ip_uint32;//convert from last line.
|
||||||
|
//extern int local_port , remote_port,source_port;//similiar to local_ip remote_ip,buf for port.source_port=0 indicates --source-port is not enabled
|
||||||
|
|
||||||
|
extern address_t local_addr,remote_addr,source_addr;
|
||||||
|
|
||||||
|
extern my_ip_t bind_addr;
|
||||||
|
|
||||||
|
extern int bind_addr_used;
|
||||||
extern int force_source_ip; //if --source-ip is enabled
|
extern int force_source_ip; //if --source-ip is enabled
|
||||||
|
extern int force_source_port;
|
||||||
|
extern int source_port;
|
||||||
|
|
||||||
extern id_t const_id;//an id used for connection recovery,its generated randomly,it never change since its generated
|
extern my_id_t const_id;//an id used for connection recovery,its generated randomly,it never change since its generated
|
||||||
|
|
||||||
extern int udp_fd; //for client only. client use this fd to listen and handle udp connection
|
extern int udp_fd; //for client only. client use this fd to listen and handle udp connection
|
||||||
extern int bind_fd; //bind only,never send or recv. its just a dummy fd for bind,so that other program wont occupy the same port
|
extern int bind_fd; //bind only,never send or recv. its just a dummy fd for bind,so that other program wont occupy the same port
|
||||||
@@ -87,6 +103,8 @@ extern int keep_rule; //whether to monitor the iptables rule periodly,re-add if
|
|||||||
extern int auto_add_iptables_rule;//if -a is set
|
extern int auto_add_iptables_rule;//if -a is set
|
||||||
extern int generate_iptables_rule;//if -g is set
|
extern int generate_iptables_rule;//if -g is set
|
||||||
extern int generate_iptables_rule_add;// if --gen-add is set
|
extern int generate_iptables_rule_add;// if --gen-add is set
|
||||||
|
extern int retry_on_error;
|
||||||
|
const int retry_on_error_interval=10;
|
||||||
|
|
||||||
extern int debug_resend; // debug only
|
extern int debug_resend; // debug only
|
||||||
|
|
||||||
@@ -95,6 +113,7 @@ extern char fifo_file[1000];
|
|||||||
|
|
||||||
|
|
||||||
extern raw_mode_t raw_mode;
|
extern raw_mode_t raw_mode;
|
||||||
|
extern u32_t raw_ip_version;
|
||||||
|
|
||||||
extern program_mode_t program_mode;
|
extern program_mode_t program_mode;
|
||||||
extern unordered_map<int, const char*> raw_mode_tostring ;
|
extern unordered_map<int, const char*> raw_mode_tostring ;
|
||||||
@@ -102,7 +121,7 @@ extern unordered_map<int, const char*> raw_mode_tostring ;
|
|||||||
extern int about_to_exit;
|
extern int about_to_exit;
|
||||||
|
|
||||||
extern int socket_buf_size;
|
extern int socket_buf_size;
|
||||||
extern int force_socket_buf;
|
|
||||||
|
|
||||||
extern pthread_t keep_thread;
|
extern pthread_t keep_thread;
|
||||||
extern int keep_thread_running;
|
extern int keep_thread_running;
|
||||||
|
1175
network.cpp
1175
network.cpp
File diff suppressed because it is too large
Load Diff
176
network.h
176
network.h
@@ -13,19 +13,153 @@ extern int raw_send_fd;
|
|||||||
extern int seq_mode;
|
extern int seq_mode;
|
||||||
extern int max_seq_mode;
|
extern int max_seq_mode;
|
||||||
extern int filter_port;
|
extern int filter_port;
|
||||||
extern u32_t bind_address_uint32;
|
//extern u32_t bind_address_uint32;
|
||||||
extern int disable_bpf_filter;
|
extern int disable_bpf_filter;
|
||||||
|
|
||||||
extern int lower_level;
|
extern int lower_level;
|
||||||
extern int lower_level_manual;
|
extern int lower_level_manual;
|
||||||
extern char if_name[100];
|
extern char if_name[100];
|
||||||
|
extern char dev[100];
|
||||||
extern unsigned char dest_hw_addr[];
|
extern unsigned char dest_hw_addr[];
|
||||||
|
|
||||||
extern int random_drop;
|
extern int random_drop;
|
||||||
|
|
||||||
extern int ifindex;
|
extern int ifindex;
|
||||||
|
|
||||||
struct icmphdr
|
extern char g_packet_buf[buf_len];
|
||||||
|
extern int g_packet_buf_len;
|
||||||
|
extern int g_packet_buf_cnt;
|
||||||
|
|
||||||
|
|
||||||
|
struct my_iphdr
|
||||||
|
{
|
||||||
|
#ifdef UDP2RAW_LITTLE_ENDIAN
|
||||||
|
unsigned char ihl:4;
|
||||||
|
unsigned char version:4;
|
||||||
|
#else
|
||||||
|
unsigned char version:4;
|
||||||
|
unsigned char ihl:4;
|
||||||
|
#endif
|
||||||
|
u_int8_t tos;
|
||||||
|
u_int16_t tot_len;
|
||||||
|
u_int16_t id;
|
||||||
|
u_int16_t frag_off;
|
||||||
|
u_int8_t ttl;
|
||||||
|
u_int8_t protocol;
|
||||||
|
u_int16_t check;
|
||||||
|
u_int32_t saddr;
|
||||||
|
u_int32_t daddr;
|
||||||
|
/*The options start here. */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct my_udphdr
|
||||||
|
{
|
||||||
|
/*__extension__*/ union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
u_int16_t uh_sport; /* source port */
|
||||||
|
u_int16_t uh_dport; /* destination port */
|
||||||
|
u_int16_t uh_ulen; /* udp length */
|
||||||
|
u_int16_t uh_sum; /* udp checksum */
|
||||||
|
};
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
u_int16_t source;
|
||||||
|
u_int16_t dest;
|
||||||
|
u_int16_t len;
|
||||||
|
u_int16_t check;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct my_tcphdr
|
||||||
|
{
|
||||||
|
/*__extension__*/ union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
u_int16_t th_sport; /* source port */
|
||||||
|
u_int16_t th_dport; /* destination port */
|
||||||
|
u_int32_t th_seq; /* sequence number */
|
||||||
|
u_int32_t th_ack; /* acknowledgement number */
|
||||||
|
# ifdef UDP2RAW_LITTLE_ENDIAN
|
||||||
|
u_int8_t th_x2:4; /* (unused) */
|
||||||
|
u_int8_t tc_off:4; /* data offset */
|
||||||
|
# else
|
||||||
|
u_int8_t th_off:4; /* data offset */
|
||||||
|
u_int8_t th_x2:4; /* (unused) */
|
||||||
|
# endif
|
||||||
|
u_int8_t th_flags;
|
||||||
|
# define TH_FIN 0x01
|
||||||
|
# define TH_SYN 0x02
|
||||||
|
# define TH_RST 0x04
|
||||||
|
# define TH_PUSH 0x08
|
||||||
|
# define TH_ACK 0x10
|
||||||
|
# define TH_URG 0x20
|
||||||
|
u_int16_t th_win; /* window */
|
||||||
|
u_int16_t th_sum; /* checksum */
|
||||||
|
u_int16_t th_urp; /* urgent pointer */
|
||||||
|
};
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
u_int16_t source;
|
||||||
|
u_int16_t dest;
|
||||||
|
u_int32_t seq;
|
||||||
|
u_int32_t ack_seq;
|
||||||
|
# ifdef UDP2RAW_LITTLE_ENDIAN
|
||||||
|
u_int16_t res1:4;
|
||||||
|
u_int16_t doff:4;
|
||||||
|
u_int16_t fin:1;
|
||||||
|
u_int16_t syn:1;
|
||||||
|
u_int16_t rst:1;
|
||||||
|
u_int16_t psh:1;
|
||||||
|
u_int16_t ack:1;
|
||||||
|
u_int16_t urg:1;
|
||||||
|
u_int16_t res2:2;
|
||||||
|
# else
|
||||||
|
u_int16_t doff:4;
|
||||||
|
u_int16_t res1:4;
|
||||||
|
u_int16_t res2:2;
|
||||||
|
u_int16_t urg:1;
|
||||||
|
u_int16_t ack:1;
|
||||||
|
u_int16_t psh:1;
|
||||||
|
u_int16_t rst:1;
|
||||||
|
u_int16_t syn:1;
|
||||||
|
u_int16_t fin:1;
|
||||||
|
# endif
|
||||||
|
u_int16_t window;
|
||||||
|
u_int16_t check;
|
||||||
|
u_int16_t urg_ptr;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct my_ip6hdr
|
||||||
|
{
|
||||||
|
# ifdef UDP2RAW_LITTLE_ENDIAN
|
||||||
|
uint8_t traffic_class_high:4;
|
||||||
|
uint8_t version:4;
|
||||||
|
uint8_t flow_label_high:4;
|
||||||
|
uint8_t traffic_class_low:4;
|
||||||
|
#else
|
||||||
|
uint8_t version:4;
|
||||||
|
uint8_t traffic_class_high:4;
|
||||||
|
uint8_t traffic_class_low:4;
|
||||||
|
uint8_t flow_label_high:4;
|
||||||
|
#endif
|
||||||
|
u_int16_t flow_label_low;
|
||||||
|
u_int16_t payload_len;
|
||||||
|
uint8_t next_header;
|
||||||
|
uint8_t hop_limit;
|
||||||
|
|
||||||
|
struct in6_addr src;
|
||||||
|
struct in6_addr dst;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct my_icmphdr
|
||||||
{
|
{
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
uint8_t code;
|
uint8_t code;
|
||||||
@@ -42,14 +176,26 @@ struct pseudo_header {
|
|||||||
u_int16_t tcp_length;
|
u_int16_t tcp_length;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct pseudo_header6 {
|
||||||
|
struct in6_addr src;
|
||||||
|
struct in6_addr dst;
|
||||||
|
u_int32_t tcp_length;
|
||||||
|
u_int16_t placeholder1;
|
||||||
|
u_int8_t placeholder2;
|
||||||
|
u_int8_t next_header;
|
||||||
|
};
|
||||||
|
|
||||||
struct packet_info_t //todo change this to union
|
struct packet_info_t //todo change this to union
|
||||||
{
|
{
|
||||||
uint8_t protocol;
|
uint8_t protocol;
|
||||||
//ip_part:
|
|
||||||
u32_t src_ip;
|
|
||||||
uint16_t src_port;
|
|
||||||
|
|
||||||
u32_t dst_ip;
|
|
||||||
|
//u32_t src_ip;
|
||||||
|
//u32_t dst_ip;
|
||||||
|
my_ip_t new_src_ip;
|
||||||
|
my_ip_t new_dst_ip;
|
||||||
|
|
||||||
|
uint16_t src_port;
|
||||||
uint16_t dst_port;
|
uint16_t dst_port;
|
||||||
|
|
||||||
//tcp_part:
|
//tcp_part:
|
||||||
@@ -62,7 +208,7 @@ struct packet_info_t //todo change this to union
|
|||||||
u32_t ts,ts_ack;
|
u32_t ts,ts_ack;
|
||||||
|
|
||||||
|
|
||||||
uint16_t icmp_seq;
|
uint16_t my_icmp_seq;
|
||||||
|
|
||||||
bool has_ts;
|
bool has_ts;
|
||||||
|
|
||||||
@@ -77,12 +223,14 @@ struct raw_info_t
|
|||||||
{
|
{
|
||||||
packet_info_t send_info;
|
packet_info_t send_info;
|
||||||
packet_info_t recv_info;
|
packet_info_t recv_info;
|
||||||
|
|
||||||
//int last_send_len;
|
//int last_send_len;
|
||||||
//int last_recv_len;
|
//int last_recv_len;
|
||||||
|
bool peek=0;
|
||||||
|
//bool csum=1;
|
||||||
u32_t reserved_send_seq;
|
u32_t reserved_send_seq;
|
||||||
//uint32_t first_seq,first_ack_seq;
|
//uint32_t first_seq,first_ack_seq;
|
||||||
|
int rst_received=0;
|
||||||
|
bool disabled=0;
|
||||||
|
|
||||||
};//g_raw_info;
|
};//g_raw_info;
|
||||||
|
|
||||||
@@ -93,19 +241,25 @@ void init_filter(int port);
|
|||||||
|
|
||||||
void remove_filter();
|
void remove_filter();
|
||||||
|
|
||||||
int init_ifindex(const char * if_name,int &index);
|
int init_ifindex(const char * if_name,int fd,int &index);
|
||||||
|
|
||||||
int find_lower_level_info(u32_t ip,u32_t &dest_ip,string &if_name,string &hw);
|
int find_lower_level_info(u32_t ip,u32_t &dest_ip,string &if_name,string &hw);
|
||||||
|
|
||||||
int get_src_adress(u32_t &ip,u32_t remote_ip_uint32,int remote_port); //a trick to get src adress for a dest adress,so that we can use the src address in raw socket as source ip
|
int get_src_adress(u32_t &ip,u32_t remote_ip_uint32,int remote_port); //a trick to get src adress for a dest adress,so that we can use the src address in raw socket as source ip
|
||||||
|
|
||||||
|
int get_src_adress2(address_t &output_addr,address_t remote_addr);
|
||||||
|
|
||||||
int try_to_list_and_bind(int & bind_fd,u32_t local_ip_uint32,int port); //try to bind to a port,may fail.
|
int try_to_list_and_bind(int & bind_fd,u32_t local_ip_uint32,int port); //try to bind to a port,may fail.
|
||||||
|
|
||||||
int client_bind_to_a_new_port(int & bind_fd,u32_t local_ip_uint32);//find a free port and bind to it.
|
int client_bind_to_a_new_port(int & bind_fd,u32_t local_ip_uint32);//find a free port and bind to it.
|
||||||
|
int client_bind_to_a_new_port2(int &fd,const address_t& address);
|
||||||
|
|
||||||
|
int discard_raw_packet();
|
||||||
|
int pre_recv_raw_packet();
|
||||||
|
|
||||||
int send_raw_ip(raw_info_t &raw_info,const char * payload,int payloadlen);
|
int send_raw_ip(raw_info_t &raw_info,const char * payload,int payloadlen);
|
||||||
|
|
||||||
int peek_raw(packet_info_t &peek_info);
|
int peek_raw(raw_info_t &peek_info);
|
||||||
|
|
||||||
int recv_raw_ip(raw_info_t &raw_info,char * &payload,int &payloadlen);
|
int recv_raw_ip(raw_info_t &raw_info,char * &payload,int &payloadlen);
|
||||||
|
|
||||||
|
1
third-party/luci-app-udp2raw/moved_to_new_repo
vendored
Normal file
1
third-party/luci-app-udp2raw/moved_to_new_repo
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
https://github.com/sensec/luci-app-udp2raw
|
1
third-party/udp2raw-openwrt-makefile/moved_to_new_repo
vendored
Normal file
1
third-party/udp2raw-openwrt-makefile/moved_to_new_repo
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
https://github.com/sensec/openwrt-udp2raw
|
Reference in New Issue
Block a user