Compare commits

...

75 Commits

Author SHA1 Message Date
wangyu-
57be59e070 trival 2017-08-26 06:56:30 -05:00
wangyu-
fe77bb0c1a avoid allocating large buf on stack 2017-08-26 06:35:47 -05:00
wangyu-
cb9504f904 Merge branch 'master' of https://github.com/wangyu-/udp2raw-tunnel 2017-08-26 05:38:40 -05:00
wangyu-
dc4936dc60 implemented --lower-level auto for client. better makefile 2017-08-26 05:38:33 -05:00
wangyu-
53609c25fc Update openvpn_guide.md 2017-08-25 19:14:17 -07:00
wangyu-
60efcbce95 Merge pull request #35 from lance0/patch-1
typo and formatting.md
2017-08-25 08:55:51 -07:00
Lance Tuller
5c4ea515f6 Update README.md 2017-08-25 11:42:22 -04:00
Lance Tuller
e3b902a950 Update README.md
formatting and a typo :)
2017-08-25 11:40:48 -04:00
wangyu-
37f2de2ae4 Update openvpn_guide.md 2017-08-24 01:47:52 -07:00
wangyu-
ae497908a1 Update README.md 2017-08-24 01:06:51 -07:00
wangyu-
b59ba05422 Update README.md 2017-08-24 01:05:12 -07:00
wangyu-
cd34922722 Update README.md 2017-08-24 00:49:28 -07:00
wangyu-
51e5b023b0 Update README.md 2017-08-24 00:35:13 -07:00
wangyu-
b1800fa41a Update README.md 2017-08-24 00:23:58 -07:00
wangyu-
698ff33892 Merge branch 'master' of https://github.com/wangyu-/udp2raw-tunnel 2017-08-23 10:49:33 -05:00
wangyu-
1293b95335 bug fix and improve for conf 2017-08-23 10:47:09 -05:00
wangyu-
7e74b40977 Update README.zh-cn.md 2017-08-23 06:48:21 -07:00
wangyu-
d1e9bdc5da Update README.zh-cn.md 2017-08-23 06:47:05 -07:00
wangyu-
2b9d5c6db6 Update README.md 2017-08-23 06:24:46 -07:00
wangyu-
b86d475f1f moved cmakeLists 2017-08-23 07:23:02 -05:00
wangyu-
0a7f9b5cc6 fixed conf bugs and refactor 2017-08-23 07:01:21 -05:00
wangyu-
eb9633ed59 Update README.md 2017-08-22 22:08:51 -07:00
wangyu-
c0b464aeaf Update README.md 2017-08-22 22:08:04 -07:00
wangyu-
020242b73d Merge pull request #30 from PeterCxy/patch-config-file
Allow loading options from configuration files
2017-08-22 22:01:28 -07:00
Peter Cai
2269879a2e doc: note about comments 2017-08-23 11:22:33 +08:00
Peter Cai
057f81007d main: don't warn config-file as 'unknown' 2017-08-23 11:16:41 +08:00
Peter Cai
1f2f0d96fd main: fix missing includes 2017-08-23 11:09:46 +08:00
Peter Cai
01e0e51b9b config: treat TABs as spaces 2017-08-23 11:03:27 +08:00
Peter Cai
6ef38709a6 config: trim spaces and tabs 2017-08-23 11:03:24 +08:00
Peter Cai
57b874ee6d main: ignore empty lines in configuration 2017-08-23 11:03:21 +08:00
Peter Cai
ab0ce3ade3 main: merge cli/config arguments and check for duplications 2017-08-23 11:03:18 +08:00
Peter Cai
32f344fd3c README: document configuration files 2017-08-23 11:03:16 +08:00
Peter Cai
968d35178a main: allow loading configuration files (--config-file) 2017-08-23 11:03:12 +08:00
wangyu-
f8e268769c trival 2017-08-22 21:10:32 -05:00
wangyu-
b9030fe81d deleted useless headers 2017-08-22 11:00:44 -05:00
wangyu-
e6f0ed035c Update README.md 2017-08-22 00:58:04 -07:00
wangyu-
00e1ddfecc Update README.md 2017-08-21 21:20:24 -07:00
wangyu-
15e1790f73 Update README.md 2017-08-21 21:05:50 -07:00
wangyu-
763b0b7342 Update README.md 2017-08-21 21:03:16 -07:00
wangyu-
c716d617a0 Update README.md 2017-08-21 20:34:05 -07:00
wangyu-
60393d24d8 Merge pull request #33 from YUChoe/master
Fix Typo TCP over TCP
2017-08-21 20:04:30 -07:00
Yong-uk Choe
9e7ed280fc Fix Typo TCP over TCP 2017-08-22 09:44:19 +09:00
root
532693edc6 Merge branch 'master' of https://github.com/wangyu-/udp2raw-tunnel 2017-08-21 23:32:21 +08:00
root
033fa830f7 trival 2017-08-21 23:31:55 +08:00
wangyu-
51464ecbfe Update README.zh-cn.md 2017-08-21 08:07:06 -07:00
root
dd8539e420 fixed --lower-level auto bug 2017-08-21 21:49:29 +08:00
wangyu
19ce820813 added new options to help page 2017-08-21 20:42:59 +08:00
root
b30a347c23 implemented --lower-level auto for server 2017-08-21 20:26:55 +08:00
wangyu-
3a35c5ce5b Update build_guide.md 2017-08-21 02:51:00 -07:00
wangyu-
bab98d8356 Update build_guide.md 2017-08-21 02:50:49 -07:00
wangyu-
283167802c Update build_guide.zh-cn.md 2017-08-21 02:39:43 -07:00
wangyu-
1db6509373 Update build_guide.zh-cn.md 2017-08-21 02:38:07 -07:00
wangyu-
a29cbf3779 Update openvpn_guide.md 2017-08-20 10:55:55 -07:00
wangyu-
da26c5047b Update README.md 2017-08-20 09:11:03 -07:00
wangyu-
38d98b5b37 Update README.md 2017-08-20 09:01:25 -07:00
root
497320e446 added --keep-rule --gen-add option 2017-08-20 16:28:23 +08:00
wangyu
19da7b6972 added -simple rule option,added mips_asm_aes target 2017-08-19 18:17:39 +08:00
wangyu-
687666cf05 Merge pull request #24 from linusyang/md5
Use md5 hash from PolarSSL
2017-08-19 02:59:34 -07:00
Linus Yang
20f8aa743b Use md5 hash from PolarSSL 2017-08-19 17:51:17 +08:00
wangyu-
8ce51fde50 Merge pull request #22 from linusyang/sep
Separate encryption and decryption
2017-08-18 22:45:19 -07:00
Linus Yang
b9d7a91cae Separate en/decryption 2017-08-19 13:22:31 +08:00
wangyu-
63dd25a0b5 Update README.zh-cn.md 2017-08-18 21:40:03 -07:00
wangyu-
c894596e06 Update README.zh-cn.md 2017-08-18 21:39:12 -07:00
wangyu-
558865f52d Update README.zh-cn.md 2017-08-18 21:37:46 -07:00
wangyu-
604ff2978f Update README.zh-cn.md 2017-08-18 21:36:41 -07:00
wangyu-
9046fd5889 Update README.zh-cn.md 2017-08-18 21:34:37 -07:00
wangyu-
241d305570 Update README.md 2017-08-18 21:29:08 -07:00
wangyu
edb3edb2cc trival 2017-08-19 12:25:50 +08:00
wangyu
d9a24a5e42 added gitattributes 2017-08-19 12:19:45 +08:00
wangyu-
f9cf1c36a3 Merge pull request #21 from linusyang/asm
Port more assembly code for AES acceleration
2017-08-18 16:27:45 -07:00
Linus Yang
4d797fb55d Only use assembly code 2017-08-19 00:53:05 +08:00
Linus Yang
8d1e735041 Add mips big-endian asm 2017-08-19 00:53:05 +08:00
wangyu
769b99546b added log,now listeing 2017-08-18 23:37:21 +08:00
wangyu
7d9ef910ca add x86 asm_aes_target 2017-08-18 20:56:58 +08:00
wangyu
5f2838573a added arm_asm_aes target 2017-08-18 20:09:13 +08:00
30 changed files with 5998 additions and 1296 deletions

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage"> <?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
<storageModule moduleId="org.eclipse.cdt.core.settings"> <storageModule moduleId="org.eclipse.cdt.core.settings">
<cconfiguration id="cdt.managedbuild.toolchain.gnu.base.436825263"> <cconfiguration id="cdt.managedbuild.toolchain.gnu.base.1051378038">
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.base.436825263" moduleId="org.eclipse.cdt.core.settings" name="Default"> <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.base.1051378038" moduleId="org.eclipse.cdt.core.settings" name="Default">
<externalSettings/> <externalSettings/>
<extensions> <extensions>
<extension id="org.eclipse.cdt.core.GNU_ELF" point="org.eclipse.cdt.core.BinaryParser"/> <extension id="org.eclipse.cdt.core.GNU_ELF" point="org.eclipse.cdt.core.BinaryParser"/>
@@ -14,28 +14,17 @@
</extensions> </extensions>
</storageModule> </storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0"> <storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildProperties="" description="" id="cdt.managedbuild.toolchain.gnu.base.436825263" name="Default" parent="org.eclipse.cdt.build.core.emptycfg"> <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.436825263.480908490" name="/" resourcePath=""> <folderInfo id="cdt.managedbuild.toolchain.gnu.base.1051378038.1421447843" name="/" resourcePath="">
<toolChain id="cdt.managedbuild.toolchain.gnu.base.1517253393" name="Linux GCC" superClass="cdt.managedbuild.toolchain.gnu.base"> <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.1797790700" name="Debug Platform" osList="linux,hpux,aix,qnx" superClass="cdt.managedbuild.target.gnu.platform.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.1253245139" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="cdt.managedbuild.target.gnu.builder.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.2108168419" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.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.1940762076" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.base"> <tool id="cdt.managedbuild.tool.gnu.cpp.compiler.base.1873425854" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.base"/>
<inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.997669137" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/> <tool id="cdt.managedbuild.tool.gnu.c.compiler.base.1356109619" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base"/>
</tool> <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.c.compiler.base.233419498" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base"> <tool id="cdt.managedbuild.tool.gnu.cpp.linker.base.180014749" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.base"/>
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.460189617" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/> <tool id="cdt.managedbuild.tool.gnu.assembler.base.2017907772" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.base"/>
</tool>
<tool id="cdt.managedbuild.tool.gnu.c.linker.base.54583610" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.base"/>
<tool id="cdt.managedbuild.tool.gnu.cpp.linker.base.2065407163" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.base">
<inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.263855663" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</tool>
<tool id="cdt.managedbuild.tool.gnu.assembler.base.747872161" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.base">
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.1349563828" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
</tool>
</toolChain> </toolChain>
</folderInfo> </folderInfo>
</configuration> </configuration>
@@ -43,16 +32,6 @@
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/> <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
</cconfiguration> </cconfiguration>
</storageModule> </storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="udp2raw-tunnel-desktop.null.370025459" name="udp2raw-tunnel-desktop"/>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
<storageModule moduleId="refreshScope" versionNumber="2">
<configuration configurationName="Default">
<resource resourceType="PROJECT" workspacePath="/udp2raw-tunnel-desktop"/>
</configuration>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
<storageModule moduleId="scannerConfiguration"> <storageModule moduleId="scannerConfiguration">
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/> <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"> <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">
@@ -62,5 +41,8 @@
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/> <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
</scannerConfigBuildInfo> </scannerConfigBuildInfo>
</storageModule> </storageModule>
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/> <storageModule moduleId="cdtBuildSystem" version="4.0.0">
<project id="udp2raw.null.1592488805" name="udp2raw"/>
</storageModule>
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
</cproject> </cproject>

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
lib/aes_acc/asm/* linguist-vendored

View File

@@ -1,32 +1,33 @@
# Udp2raw-tunnel # Udp2raw-tunnel
![image0](images/image0.PNG) ![image0](images/image0.PNG)
A UDP Tunnel which tunnels UDP via FakeTCP/UDP/ICMP Traffic by using Raw Socket,helps you Bypass UDP FireWalls(or Unstable UDP Environment).Its Encrpyted,Anti-Replay and Multiplexed.It aslo acts as a Connection Stablizer. A Tunnel which tunnels UDP via FakeTCP/UDP/ICMP Traffic by using Raw Socket, helps you Bypass UDP FireWalls(or Unstable UDP Environment). Its Encrypted, Anti-Replay and Multiplexed. It also acts as a Connection Stabilizer.
[简体中文](/doc/README.zh-cn.md) [简体中文](/doc/README.zh-cn.md)
# Support Platforms # Support Platforms
A 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 Winodws/MacOS,virtual image with udp2raw pre-installed has been released,you can load it with Vmware/VirtualBox.The virtual image has been set to auto obtain ip,udp2raw can be run imidiately after boot finished(make sure network mode of virtual machine has been set to bridged)(only udp2raw has to be run under virtual machine,all other programs runs under Windows/MacOS as usual). For Winodws/MacOS,the 4.4mb virtual image with udp2raw pre-installed has been released,you can load it with Vmware/VirtualBox.The virtual image has been set to auto obtain ip,udp2raw can be run imidiately after boot finished(make sure network mode of virtual machine has been set to bridged)(only udp2raw has to be run under virtual machine,all other programs runs under Windows/MacOS as usual).
# Features # Features
### Send / Receive UDP Packet with fake-tcp/icmp headers ### Send/Receive UDP Packets with ICMP/FakeTCP/UDP headers
Fake-tcp/icmp headers help you bypass UDP blocking, UDP QOS or improper UDP NAT behavior on some ISPs. Raw packets with UDP headers are also supported.In UDP header mode,it behaves just like a normal UDP tunnel,and you can just make use of the other features. ICMP/FakeTCP headers help you bypass UDP blocking, UDP QOS or improper UDP NAT behavior on some ISPs. In ICMP header mode,udp2raw works like an ICMP tunnel.
### Simulate TCP Handshake UDP headers are also supported. In UDP header mode, it behaves just like a normal UDP tunnel, and you can just make use of the other features (such as encrytion, anti-replay, or connection stalization).
Simulates the 3-way handshake, along with seq and ack_seq. TCP options MSS, sackOk, TS, TS_ack, wscale are also simulated. Real-time delivery guaranteed, no TCP over TCP problem when using OpenVPN.
### Encrpytion, Anti-Replay, No MITM ### Simulated TCP with Real-time/Out-of-Order Delivery
In FakeTCP header mode,udp2raw simulates 3-way handshake while establishing a connection,simulates seq and ack_seq while data transferring. It also simulates following TCP options: `MSS`, `sackOk`, `TS`, `TS_ack`, `wscale`.Firewalls will regard FakeTCP as a TCP connection, but its essentially UDP: it supports real-time/out-of-order delivery(just as normal UDP does), no congrestion control or re-transmission. So there wont be any TCP over TCP problem when using OpenVPN.
### 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 MD5 or 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.
* Authenticate mutually, no MITM attacks.
### Failure Dectection & Stablization (Connection Recovery) ### Failure Dectection & Stablization (Connection Recovery)
Conection failures are detected by heartbeats. If timed-out,client will automatically change port number and reconnect. If reconnection is successful, the previous connection will be recovered, and all existing UDP conversations will stay vaild. Conection failures are detected by heartbeats. If timed-out, client will automatically change port number and reconnect. If reconnection is successful, the previous connection will be recovered, and all existing UDP conversations will stay vaild.
For example, if you use UDP2RAW + OpenVPN, OpenVPN won't lose connection after any reconnect, **even if the network cable is re-plugged or the WiFi access point is changed**. For example, if you use udp2raw + OpenVPN, OpenVPN won't lose connection after any reconnect, **even if network cable is re-plugged or WiFi access point is changed**.
### Other Features ### Other Features
* **Multiplexing** One client can handle multiple UDP connections, all of which share the same raw connection. * **Multiplexing** One client can handle multiple UDP connections, all of which share the same raw connection.
@@ -35,12 +36,12 @@ For example, if you use UDP2RAW + OpenVPN, OpenVPN won't lose connection after a
* **NAT Support** All of the 3 modes work in NAT environments. * **NAT Support** All of the 3 modes work in NAT environments.
* **OpenVZ Support** Tested on BandwagonHost. * **OpenVZ Support** Tested on BandwagonHost VPS.
* **OpenWRT Support** No dependencies, easy to build. Binary for ar71xx are included in release. * **Easy to Build** No dependencies.To cross-compile udp2raw,all you need to do is just to download a toolchain,modify makefile to point at the toolchain,run `make cross` then everything is done.(Note:Pre-compiled binaries for Desktop,RaspberryPi,Android,some Openwrt Routers are already included in [Releases](https://github.com/wangyu-/udp2raw-tunnel/releases))
### Keywords ### Keywords
`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`
# Getting Started # Getting Started
### Installing ### Installing
@@ -64,7 +65,7 @@ Assume your UDP is blocked or being QOS-ed or just poorly supported. Assume your
Now,an encrypted raw tunnel has been established between client and server through TCP port 4096. Connecting to UDP port 3333 at the client side is equivalent to connecting to port 7777 at the server side. No UDP traffic will be exposed. Now,an encrypted raw tunnel has been established between client and server through TCP port 4096. Connecting to UDP port 3333 at the client side is equivalent to connecting to port 7777 at the server side. No UDP traffic will be exposed.
### Note ### Note
to run on Android, see [Android_Guide](/doc/android_guide.md) To run on Android, check [Android_Guide](/doc/android_guide.md)
# Advanced Topic # Advanced Topic
### Usage ### Usage
@@ -90,6 +91,7 @@ client options:
--source-port <port> force source-port for raw socket,tcp/udp only --source-port <port> force source-port for raw socket,tcp/udp only
this option disables port changing while re-connecting this option disables port changing while re-connecting
other options: other options:
--conf-file <string> read options from a configuration file instead of command line
--log-level <number> 0:never 1:fatal 2:error 3:warn --log-level <number> 0:never 1:fatal 2:error 3:warn
4:info (default) 5:debug 6:trace 4:info (default) 5:debug 6:trace
--log-position enable file name,function name,line number in log --log-position enable file name,function name,line number in log
@@ -106,15 +108,46 @@ other options:
-h,--help print this help message -h,--help print this help message
``` ```
### IPTABLES rule ### Iptables rules,`-a` and `-g`
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` + `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.
### 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.
### `--conf-file`
You can also load options from a configuration file in order to keep secrets away from ps command.
For example, rewrite the options for the above `server` example (in Getting Started section) into configuration file:
`server.conf`
```
-s
# You can add comments like this
# Comments MUST occupy an entire line
# Or they will not work as expected
# Listen address
-l 0.0.0.0:4096
# Remote address
-r 127.0.0.1:7777
-a
-k passwd
--raw-mode faketcp
```
Pay attention to the `-k` parameter: In command line mode the quotes around the password will be removed by shell. In configuration files we do not remove quotes.
Then start the server with
```bash
./udp2raw_amd64 --conf-file server.conf
```
# Peformance Test # Peformance Test
#### Test method: #### Test method:
iperf3 TCP via OpenVPN + udp2raw iperf3 TCP via OpenVPN + udp2raw
@@ -144,20 +177,22 @@ raw_mode: faketcp cipher_mode: aes128cbc  auth_mode: md5
(reverse speed was simliar and not uploaded) (reverse speed was simliar and not uploaded)
# Application # Application
### tunneling any traffic via raw traffic by using udp2raw +openvpn ## Tunneling any traffic via raw traffic by using udp2raw +openvpn
![image_vpn](images/openvpn.PNG) ![image_vpn](images/openvpn.PNG)
1. bypasses UDP block/UDP QOS 1. Bypasses UDP block/UDP QOS
2. no TCP ovr tcp problem (tcp over tcp problem http://sites.inka.de/bigred/devel/tcp-tcp.html ,https://community.openvpn.net/openvpn/ticket/2 ) 2. No TCP over TCP problem (TCP over TCP problem http://sites.inka.de/bigred/devel/tcp-tcp.html ,https://community.openvpn.net/openvpn/ticket/2 )
3. openvpn over icmp also becomes a choice 3. OpenVpn over ICMP also becomes a choice
more details at [openvpn+udp2raw_guide](/doc/openvpn_guide.md) 4. Supports almost any UDP-based VPN
### speed-up tcp connection via raw traffic by using udp2raw+kcptun
More details at [openvpn+udp2raw_guide](/doc/openvpn_guide.md)
## 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)
### speed-up tcp connection via raw traffic by using udp2raw+finalspeed ## Speed-up tcp connection via raw traffic by using udp2raw+finalspeed
finalspeed is a tcp connection speed-up program similiar to kcptun,it speeds-up tcp connection by using kcp protocol on-top of udp or tcp.but its tcp mode doesnt support openvz,you can bypass this problem if you use udp2raw+finalspeed together,and icmp mode also becomes avaliable. finalspeed is a tcp connection speed-up program similiar to kcptun,it speeds-up tcp connection by using kcp protocol on-top of udp or tcp.but its tcp mode doesnt support openvz,you can bypass this problem if you use udp2raw+finalspeed together,and icmp mode also becomes avaliable.
# How to build # How to build

View File

@@ -15,8 +15,16 @@ int about_to_exit=0;
raw_mode_t raw_mode=mode_faketcp; raw_mode_t raw_mode=mode_faketcp;
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 socket_buf_size=1024*1024; int socket_buf_size=1024*1024;
static int random_number_fd=-1; static int random_number_fd=-1;
char iptables_rule[200]=""; string iptables_pattern="";
int iptables_rule_added=0;
int iptables_rule_keeped=0;
int iptables_rule_keep_index=0;
//int iptables_rule_no_clear=0;
program_mode_t program_mode=unset_mode;//0 unset; 1client 2server program_mode_t program_mode=unset_mode;//0 unset; 1client 2server
u64_t get_current_time() u64_t get_current_time()
@@ -50,42 +58,161 @@ char * my_ntoa(u32_t ip)
} }
int add_iptables_rule(char * s) /*
int add_iptables_rule(const char * s)
{ {
strcpy(iptables_rule,s);
char buf[300]="iptables -I "; iptables_pattern=s;
strcat(buf,s);
string rule="iptables -I INPUT ";
rule+=iptables_pattern;
rule+=" -j DROP";
char *output; char *output;
if(run_command(buf,output)==0) if(run_command(rule.c_str(),output)==0)
{ {
mylog(log_warn,"auto added iptables rule by: %s\n",buf); mylog(log_warn,"auto added iptables rule by: %s\n",rule.c_str());
} }
else else
{ {
mylog(log_fatal,"auto added iptables failed by: %s\n",buf); mylog(log_fatal,"auto added iptables failed by: %s\n",rule.c_str());
//mylog(log_fatal,"reason : %s\n",strerror(errno)); //mylog(log_fatal,"reason : %s\n",strerror(errno));
myexit(-1); myexit(-1);
} }
iptables_rule_added=1;
return 0;
}*/
string chain[2];
string rule_keep[2];
string rule_keep_add[2];
string rule_keep_del[2];
u64_t keep_rule_last_time=0;
pthread_t keep_thread;
int keep_thread_running=0;
int iptables_gen_add(const char * s,u32_t const_id)
{
string dummy="";
iptables_pattern=s;
chain[0] =dummy+ "udp2rawDwrW_C";
rule_keep[0]=dummy+ iptables_pattern+" -j " +chain[0];
rule_keep_add[0]=dummy+"iptables -I INPUT "+rule_keep[0];
char *output;
run_command(dummy+"iptables -N "+chain[0],output,show_none);
run_command(dummy+"iptables -F "+chain[0],output);
run_command(dummy+"iptables -I "+chain[0] + " -j DROP",output);
rule_keep_del[0]=dummy+"iptables -D INPUT "+rule_keep[0];
run_command(rule_keep_del[0],output,show_none);
run_command(rule_keep_del[0],output,show_none);
if(run_command(rule_keep_add[0],output)!=0)
{
mylog(log_fatal,"auto added iptables failed by: %s\n",rule_keep_add[0].c_str());
myexit(-1);
}
return 0;
}
int iptables_rule_init(const char * s,u32_t const_id,int keep)
{
iptables_pattern=s;
iptables_rule_added=1;
iptables_rule_keeped=keep;
string dummy="";
char const_id_str[100];
sprintf(const_id_str, "%x", const_id);
chain[0] =dummy+ "udp2rawDwrW_"+const_id_str+"_C0";
chain[1] =dummy+ "udp2rawDwrW_"+const_id_str+"_C1";
rule_keep[0]=dummy+ iptables_pattern+" -j " +chain[0];
rule_keep[1]=dummy+ iptables_pattern+" -j " +chain[1];
rule_keep_add[0]=dummy+"iptables -I INPUT "+rule_keep[0];
rule_keep_add[1]=dummy+"iptables -I INPUT "+rule_keep[1];
rule_keep_del[0]=dummy+"iptables -D INPUT "+rule_keep[0];
rule_keep_del[1]=dummy+"iptables -D INPUT "+rule_keep[1];
keep_rule_last_time=get_current_time();
char *output;
for(int i=0;i<=iptables_rule_keeped;i++)
{
run_command(dummy+"iptables -N "+chain[i],output);
run_command(dummy+"iptables -F "+chain[i],output);
run_command(dummy+"iptables -I "+chain[i] + " -j DROP",output);
if(run_command(rule_keep_add[i],output)!=0)
{
mylog(log_fatal,"auto added iptables failed by: %s\n",rule_keep_add[i].c_str());
myexit(-1);
}
}
mylog(log_warn,"auto added iptables rules\n");
return 0;
}
int keep_iptables_rule() //magic to work on a machine without grep/iptables --check/-m commment
{
/*
if(iptables_rule_keeped==0) return 0;
uint64_t tmp_current_time=get_current_time();
if(tmp_current_time-keep_rule_last_time<=iptables_rule_keep_interval)
{
return 0;
}
else
{
keep_rule_last_time=tmp_current_time;
}*/
mylog(log_debug,"keep_iptables_rule begin %llu\n",get_current_time());
iptables_rule_keep_index+=1;
iptables_rule_keep_index%=2;
string dummy="";
char *output;
int i=iptables_rule_keep_index;
run_command(dummy + "iptables -N " + chain[i], output,show_none);
if (run_command(dummy + "iptables -F " + chain[i], output,show_none) != 0)
mylog(log_warn, "iptables -F failed %d\n",i);
if (run_command(dummy + "iptables -I " + chain[i] + " -j DROP",output,show_none) != 0)
mylog(log_warn, "iptables -I failed %d\n",i);
if (run_command(rule_keep_del[i], output,show_none) != 0)
mylog(log_warn, "rule_keep_del failed %d\n",i);
run_command(rule_keep_del[i], output,show_none); //do it twice,incase it fails for unknown random reason
if(run_command(rule_keep_add[i], output,show_log)!=0)
mylog(log_warn, "rule_keep_del failed %d\n",i);
mylog(log_debug,"keep_iptables_rule end %llu\n",get_current_time());
return 0; return 0;
} }
int clear_iptables_rule() int clear_iptables_rule()
{ {
if(iptables_rule[0]!=0)
{
char buf[300]="iptables -D ";
strcat(buf,iptables_rule);
char *output; char *output;
if(run_command(buf,output)==0) string dummy="";
{ if(!iptables_rule_added) return 0;
mylog(log_warn,"iptables rule cleared by: %s \n",buf);
}
else
{
mylog(log_error,"clear iptables failed by: %s\n",buf);
//mylog(log_error,"reason : %s\n",strerror(errno));
}
for(int i=0;i<=iptables_rule_keeped;i++ )
{
run_command(rule_keep_del[i],output);
run_command(dummy+"iptables -F "+chain[i],output);
run_command(dummy+"iptables -X "+chain[i],output);
} }
return 0; return 0;
} }
@@ -217,6 +344,17 @@ void myexit(int a)
{ {
if(enable_log_color) if(enable_log_color)
printf("%s\n",RESET); printf("%s\n",RESET);
if(keep_thread_running)
{
if(pthread_cancel(keep_thread))
{
mylog(log_warn,"pthread_cancel failed\n");
}
else
{
mylog(log_info,"pthread_cancel success\n");
}
}
clear_iptables_rule(); clear_iptables_rule();
exit(a); exit(a);
} }
@@ -252,7 +390,31 @@ int char_to_numbers(const char * data,int len,id_t &id1,id_t &id2,id_t &id3)
id3=ntohl( *((id_t*)(data+sizeof(id_t)*2)) ); id3=ntohl( *((id_t*)(data+sizeof(id_t)*2)) );
return 0; return 0;
} }
int hex_to_u32(const string & a,u32_t &output)
{
//string b="0x";
//b+=a;
if(sscanf(a.c_str(),"%x",&output)==1)
{
//printf("%s %x\n",a.c_str(),output);
return 0;
}
mylog(log_error,"<%s> doesnt contain a hex\n",a.c_str());
return -1;
}
int hex_to_u32_with_endian(const string & a,u32_t &output)
{
//string b="0x";
//b+=a;
if(sscanf(a.c_str(),"%x",&output)==1)
{
output=htonl(output);
//printf("%s %x\n",a.c_str(),output);
return 0;
}
mylog(log_error,"<%s> doesnt contain a hex\n",a.c_str());
return -1;
}
bool larger_than_u32(u32_t a,u32_t b) bool larger_than_u32(u32_t a,u32_t b)
{ {
@@ -322,8 +484,13 @@ vector<string> string_to_vec(const char * s,const char * sp) {
{ {
res.push_back(p); res.push_back(p);
//printf ("%s\n",p); //printf ("%s\n",p);
p = strtok (NULL, sp); p = strtok(NULL, sp);
} }
/* for(int i=0;i<(int)res.size();i++)
{
printf("<<%s>>\n",res[i].c_str());
}*/
return res; return res;
} }
@@ -339,43 +506,63 @@ vector< vector <string> > string_to_vec2(const char * s)
} }
return res; return res;
} }
int read_file(const char * file,char * &output) int read_file(const char * file,string &output)
{ {
static char buf[1024*1024+100]; const int max_len=3*1024*1024;
buf[sizeof(buf)-1]=0; // static char buf[max_len+100];
string buf0;
buf0.reserve(max_len+200);
char * buf=(char *)buf0.c_str();
buf[max_len]=0;
//buf[sizeof(buf)-1]=0;
int fd=open(file,O_RDONLY); int fd=open(file,O_RDONLY);
if(fd==-1) if(fd==-1)
{ {
mylog(log_error,"read_file %s fail\n",file); mylog(log_error,"read_file %s fail\n",file);
return -1; return -1;
} }
int len=read(fd,buf,1024*1024); int len=read(fd,buf,max_len);
if(len==1024*1024) if(len==max_len)
{ {
buf[0]=0; buf[0]=0;
mylog(log_error,"too long,buf not larger enough\n"); mylog(log_error,"%s too long,buf not large enough\n",file);
return -2; return -2;
} }
else if(len<0) else if(len<0)
{ {
buf[0]=0; buf[0]=0;
mylog(log_error,"read fail %d\n",len); mylog(log_error,"%s read fail %d\n",file,len);
return -3; return -3;
} }
else else
{ {
output=buf;
buf[len]=0; buf[len]=0;
output=buf;
} }
return 0; return 0;
} }
int run_command(const char * command,char * &output) { int run_command(string command0,char * &output,int flag) {
FILE *in; FILE *in;
if((flag&show_log)==0) command0+=" 2>&1 ";
const char * command=command0.c_str();
int level= (flag&show_log)?log_warn:log_debug;
if(flag&show_command)
{
mylog(log_info,"run_command %s\n",command);
}
else
{
mylog(log_debug,"run_command %s\n",command); mylog(log_debug,"run_command %s\n",command);
static char buf[1024*1024+100]; }
static __thread char buf[1024*1024+100];
buf[sizeof(buf)-1]=0; buf[sizeof(buf)-1]=0;
if(!(in = popen(command, "r"))){ if(!(in = popen(command, "r"))){
mylog(log_error,"command %s popen failed,errno %s\n",command,strerror(errno)); mylog(level,"command %s popen failed,errno %s\n",command,strerror(errno));
return -1; return -1;
} }
@@ -383,7 +570,7 @@ int run_command(const char * command,char * &output) {
if(len==1024*1024) if(len==1024*1024)
{ {
buf[0]=0; buf[0]=0;
mylog(log_error,"too long,buf not larger enough\n"); mylog(level,"too long,buf not larger enough\n");
return -2; return -2;
} }
else else
@@ -393,8 +580,8 @@ int run_command(const char * command,char * &output) {
int ret; int ret;
if(( ret=ferror(in) )) if(( ret=ferror(in) ))
{ {
mylog(log_error,"command %s fread failed,ferror return value %d \n",command,ret); mylog(level,"command %s fread failed,ferror return value %d \n",command,ret);
return -2; return -3;
} }
//if(output!=0) //if(output!=0)
output=buf; output=buf;
@@ -404,11 +591,139 @@ int run_command(const char * command,char * &output) {
if(ret!=0||ret2!=0) if(ret!=0||ret2!=0)
{ {
mylog(log_error,"commnad %s ,pclose returned %d ,WEXITSTATUS %d,errnor :%s \n",command,ret,ret2,strerror(errno)); mylog(level,"commnad %s ,pclose returned %d ,WEXITSTATUS %d,errnor :%s \n",command,ret,ret2,strerror(errno));
return -3; return -4;
} }
return 0; return 0;
} }
/*
int run_command_no_log(string command0,char * &output) {
FILE *in;
command0+=" 2>&1 ";
const char * command=command0.c_str();
mylog(log_debug,"run_command_no_log %s\n",command);
static char buf[1024*1024+100];
buf[sizeof(buf)-1]=0;
if(!(in = popen(command, "r"))){
mylog(log_debug,"command %s popen failed,errno %s\n",command,strerror(errno));
return -1;
}
int len =fread(buf, 1024*1024, 1, in);
if(len==1024*1024)
{
buf[0]=0;
mylog(log_debug,"too long,buf not larger enough\n");
return -2;
}
else
{
buf[len]=0;
}
int ret;
if(( ret=ferror(in) ))
{
mylog(log_debug,"command %s fread failed,ferror return value %d \n",command,ret);
return -3;
}
//if(output!=0)
output=buf;
ret= pclose(in);
int ret2=WEXITSTATUS(ret);
if(ret!=0||ret2!=0)
{
mylog(log_debug,"commnad %s ,pclose returned %d ,WEXITSTATUS %d,errnor :%s \n",command,ret,ret2,strerror(errno));
return -4;
}
return 0;
}*/
// Remove preceding and trailing characters
string trim(const string& str, char c) {
size_t first = str.find_first_not_of(c);
if(string::npos==first)
{
return "";
}
size_t last = str.find_last_not_of(c);
return str.substr(first,(last-first+1));
}
vector<string> parse_conf_line(const string& s0)
{
string s=s0;
s.reserve(s.length()+200);
char *buf=(char *)s.c_str();
//char buf[s.length()+200];
char *p=buf;
int i=int(s.length())-1;
int j;
vector<string>res;
strcpy(buf,(char *)s.c_str());
while(i>=0)
{
if(buf[i]==' ' || buf[i]== '\t')
buf[i]=0;
else break;
i--;
}
while(*p!=0)
{
if(*p==' ' || *p== '\t')
{
p++;
}
else break;
}
int new_len=strlen(p);
if(new_len==0)return res;
if(p[0]=='#') return res;
if(p[0]!='-')
{
mylog(log_fatal,"line :<%s> not begin with '-' ",s.c_str());
myexit(-1);
}
for(i=0;i<new_len;i++)
{
if(p[i]==' '||p[i]=='\t')
{
break;
}
}
if(i==new_len)
{
res.push_back(p);
return res;
}
j=i;
while(p[j]==' '||p[j]=='\t')
j++;
p[i]=0;
res.push_back(p);
res.push_back(p+j);
return res;
}

View File

@@ -44,7 +44,7 @@
#include <assert.h> #include <assert.h>
#include <linux/if_packet.h> #include <linux/if_packet.h>
#include <byteswap.h> #include <byteswap.h>
#include <pthread.h>
#include<unordered_map> #include<unordered_map>
#include<vector> #include<vector>
@@ -95,7 +95,11 @@ const u32_t client_conn_uplink_timeout=client_conn_timeout+2000;
//const uint32_t server_conn_timeout=conv_timeout+60000;//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;//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=4000;
extern int about_to_exit; extern int about_to_exit;
extern pthread_t keep_thread;
extern int keep_thread_running;
enum raw_mode_t{mode_faketcp=0,mode_udp,mode_icmp,mode_end}; enum raw_mode_t{mode_faketcp=0,mode_udp,mode_icmp,mode_end};
extern raw_mode_t raw_mode; extern raw_mode_t raw_mode;
@@ -141,14 +145,33 @@ int char_to_numbers(const char * data,int len,id_t &id1,id_t &id2,id_t &id3);
void myexit(int a); void myexit(int a);
int add_iptables_rule(char *); int add_iptables_rule(const char *);
int clear_iptables_rule(); int clear_iptables_rule();
int run_command(const char * command,char * &output); int iptables_gen_add(const char * s,u32_t const_id);
int read_file(const char * file,char * &output); int iptables_rule_init(const char * s,u32_t const_id,int keep);
int keep_iptables_rule();
const int show_none=0;
const int show_command=0x1;
const int show_log=0x2;
const int show_all=show_command|show_log;
int run_command(string command,char * &output,int flag=show_all);
//int run_command_no_log(string command,char * &output);
int read_file(const char * file,string &output);
vector<string> string_to_vec(const char * s,const char * sp); vector<string> string_to_vec(const char * s,const char * sp);
vector< vector <string> > string_to_vec2(const char * s); vector< vector <string> > string_to_vec2(const char * s);
string trim(const string& str, char c);
string trim_conf_line(const string& str);
vector<string> parse_conf_line(const string& s);
int hex_to_u32_with_endian(const string & a,u32_t &output);
int hex_to_u32(const string & a,u32_t &output);
//extern string iptables_pattern;
#endif /* COMMON_H_ */ #endif /* COMMON_H_ */

16
config.example Normal file
View File

@@ -0,0 +1,16 @@
# Basically this file is the equivalent to splitting the command line options into multiple lines
# Each line should contain an option
# This is client
-c
# Or use -s if you use it on server side
# Define local address
-l 127.0.0.1:56789
# Define remote address
-r 45.66.77.88:45678
# Password
-k my_awesome_password
# Mode
--raw-mode faketcp
# Log Level
--log-level 4

View File

@@ -35,10 +35,10 @@ Client能用单倍的超时时间检测到单向链路的失效不管是上
对于有大量client的情况对于不同client,server发送的心跳是错开时间发送的不会因为短时间发送大量的心跳而造成拥塞和延迟抖动。 对于有大量client的情况对于不同client,server发送的心跳是错开时间发送的不会因为短时间发送大量的心跳而造成拥塞和延迟抖动。
### 加密 防重放攻击 防中间人攻击 ### 加密 防重放攻击
用aes128cbc加密md5/crc32做数据完整校验。用类似ipsec/openvpn的 replay window机制来防止重放攻击。 用aes128cbc加密md5/crc32做数据完整校验。用类似ipsec/openvpn的 replay window机制来防止重放攻击。
设计目标是即使攻击者可以监听到tunnel的所有包可以选择性丢弃tunnel的任意包可以重放任意包攻击者也没办法获得tunnel承载的任何数据也没办法向tunnel的数据流中通过包构造/包重放插入任何数据。client和server互相认证对方无法被中间人攻击。 设计目标是即使攻击者可以监听到tunnel的所有包可以选择性丢弃tunnel的任意包可以重放任意包攻击者也没办法获得tunnel承载的任何数据也没办法向tunnel的数据流中通过包构造/包重放插入任何数据。
### 其他特性 ### 其他特性
信道复用client的udp端支持多个连接。 信道复用client的udp端支持多个连接。
@@ -123,21 +123,22 @@ other options:
ie:'eth0#00:23:45:67:89:b9'.Beta. ie:'eth0#00:23:45:67:89:b9'.Beta.
-h,--help print this help message -h,--help print this help message
``` ```
### iptables 规则
### iptables 规则,`-a`和`-g`
用raw收发tcp包本质上绕过了linux内核的tcp协议栈。linux碰到raw socket发来的包会不认识如果一直收到不认识的包会回复大量RST造成不稳定或性能问题。所以强烈建议添加iptables规则屏蔽Linux内核的对指定端口的处理。用-a选项udp2raw会在启动的时候自动帮你加上Iptables规则退出的时候再自动删掉。如果长期使用可以用-g选项来生成相应的Iptables规则再自己手动添加这样规则不会在udp2raw退出时被删掉可以避免停掉udp2raw后内核向对端回复RST。 用raw收发tcp包本质上绕过了linux内核的tcp协议栈。linux碰到raw socket发来的包会不认识如果一直收到不认识的包会回复大量RST造成不稳定或性能问题。所以强烈建议添加iptables规则屏蔽Linux内核的对指定端口的处理。用-a选项udp2raw会在启动的时候自动帮你加上Iptables规则退出的时候再自动删掉。如果长期使用可以用-g选项来生成相应的Iptables规则再自己手动添加这样规则不会在udp2raw退出时被删掉可以避免停掉udp2raw后内核向对端回复RST。
用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+md5。如果要运行再路由器上建议xor+simple。但是注意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种模式都没问题。
### lower-level ### `--lower-level`
大部分udp2raw不能连通的情况都是设置了不兼容的iptables造成的。--lower-level选项允许绕过本地iptables。在一些iptables不好改动的情况下尤其有效比如你用的是梅林固件iptables全是固件自己生成的 大部分udp2raw不能连通的情况都是设置了不兼容的iptables造成的。--lower-level选项允许绕过本地iptables。在一些iptables不好改动的情况下尤其有效比如你用的是梅林固件iptables全是固件自己生成的
##### 格式 ##### 格式
`eth0#00:23:45:67:89:b9``eth0`换成你的出口网卡名。`00:23:45:67:89:b9`换成网关的mac地址如果client和server在同一个局域网内可能不需要网关这时候直接用对方主机的mac地址这个属于罕见的应用场景可以忽略 `if_name#dest_mac_adress`,例如 `eth0#00:23:45:67:89:b9``eth0`换成你的出口网卡名。`00:23:45:67:89:b9`换成网关的mac地址如果client和server在同一个局域网内可能不需要网关这时候直接用对方主机的mac地址这个属于罕见的应用场景可以忽略
##### client端获得--lower-level参数的办法 ##### client端获得--lower-level参数的办法
在client 端,运行`traceroute <server_ip>`,记下第一跳的地址,这个就是`网关ip`。再运行`arp -s <网关ip>`可以同时查到出口网卡名和mac。 在client 端,运行`traceroute <server_ip>`,记下第一跳的地址,这个就是`网关ip`。再运行`arp -s <网关ip>`可以同时查到出口网卡名和mac。
@@ -148,9 +149,40 @@ facktcp模式并没有模拟tcp的全部。所以理论上有办法把faketcp和
如果client没有公网ip`traceroute google.com``traceroute baidu.com`。下一步和client端的方法一样。 如果client没有公网ip`traceroute google.com``traceroute baidu.com`。下一步和client端的方法一样。
server端也可以用`--lower-level auto` 来尝试自动获得参数,如果无法连接再手动填写。
##### 注意 ##### 注意
如果用了`--lower-level`选项。server虽然还可以bind在0.0.0.0,但是因为你显式指定了网络接口,就只能工作在这一个网络接口了。 如果用了`--lower-level`选项。server虽然还可以bind在0.0.0.0,但是因为你显式指定了网络接口,就只能工作在这一个网络接口了。
如果`arps -s`命令查询不到首先再试几次。如果还是查询不到那么可能是因为你用的是pppoe方式的拨号宽带查询不到是正常的。这种情况下`if_name`填pppoe产生的虚拟interface通常名字叫`pppXXXX`,从`ifconfig`命令的输出里找一下;`des_mac_adress``00:00:00:00:00:00`,例如`ppp0#00:00:00:00:00:00`
### `--conf-file`
为了避免将密码等私密信息暴露在进程命令行参数内,你也可以使用 `配置文件` 来存储参数。
比如,将以上服务端参数改写成配置文件
`server.conf`:
```
-s
# 你可以像这样添加注释
# 注意,只有整行注释才能在配置文件里使用
# 注释必须独占一行
-l 0.0.0.0:4096
-r 127.0.0.1:7777
-a
-k passwd
--raw-mode faketcp
```
注意,当写入配置文件的时候,密码等参数两边的引号必须去除。
然后就可以使用下面的方式启动服务端
```bash
./udp2raw_amd64 --conf-file server.conf
```
# 性能测试 # 性能测试
iperf3 的UDP模式有BUG所以这里用iperf3的tcp模式配合Openvpn测试udp2raw的性能。iperf3 udp issue ,https://github.com/esnet/iperf/issues/296 iperf3 的UDP模式有BUG所以这里用iperf3的tcp模式配合Openvpn测试udp2raw的性能。iperf3 udp issue ,https://github.com/esnet/iperf/issues/296

View File

@@ -71,4 +71,6 @@ modify first line of makefile to:
cc_cross=/home/wangyu/Desktop/OpenWrt-SDK-15.05-ar71xx-generic_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-g++ cc_cross=/home/wangyu/Desktop/OpenWrt-SDK-15.05-ar71xx-generic_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-g++
``` ```
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`.

View File

@@ -69,4 +69,6 @@ http://downloads.openwrt.org/chaos_calmer/15.05/ar71xx/generic/OpenWrt-SDK-15.05
cc_cross=/home/wangyu/Desktop/OpenWrt-SDK-15.05-ar71xx-generic_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-g++ cc_cross=/home/wangyu/Desktop/OpenWrt-SDK-15.05-ar71xx-generic_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-g++
``` ```
执行make cross目录下生成udp2raw_cross文件。编译完成。 执行`make cross`目录下生成udp2raw_cross文件。编译完成。
`make cross`编译出的binary是非静态的。如果运行有问题可以尝试用`make cross2``make cross3`编译静态的binary,你的工具链必须带静态库才能成功编译,生成的文件仍然叫udp2raw_cross.

View File

@@ -2,6 +2,7 @@
![image_vpn](/images/openvpn.PNG) ![image_vpn](/images/openvpn.PNG)
![image4](/images/image4.PNG) ![image4](/images/image4.PNG)
# udp2raw command # udp2raw command
#### run at server side #### run at server side
``` ```
@@ -13,6 +14,8 @@ assume server ip is 45.66.77.88
./udp2raw_amd64 -s -l0.0.0.0:3333 -r 45.66.77.88:8855 -k "passwd" --raw-mode faketcp -a ./udp2raw_amd64 -s -l0.0.0.0:3333 -r 45.66.77.88:8855 -k "passwd" --raw-mode faketcp -a
``` ```
#### hint
You can add `--cipher-mode xor` `--auth-mode simple` to **both** sides to obtain maximum performance(but poor security).
# openvpn config # openvpn config
@@ -38,7 +41,7 @@ mute 20
comp-lzo no comp-lzo no
cipher none ##### disable openvpn 's cipher and auth for maxmized peformance. cipher none ##### disable openvpn 's cipher and auth for maxmized peformance.
auth none ##### you can enable openvpn's cipher and auth,if you dont care about peformance,oryou dont trust udp2raw 's encryption auth none ##### you can enable openvpn's cipher and auth,if you dont care about peformance,or you dont trust udp2raw 's encryption
fragment 1200 ##### very important you can turn it up a bit. but,the lower the safer fragment 1200 ##### very important you can turn it up a bit. but,the lower the safer
mssfix 1200 ##### very important mssfix 1200 ##### very important
@@ -80,7 +83,7 @@ mute 20
comp-lzo no comp-lzo no
cipher none ##### disable openvpn 's cipher and auth for maxmized peformance. cipher none ##### disable openvpn 's cipher and auth for maxmized peformance.
auth none ##### you can enable openvpn's cipher and auth,if you dont care about peformance,oryou dont trust udp2raw 's encryption auth none ##### you can enable openvpn's cipher and auth,if you dont care about peformance,or you dont trust udp2raw 's encryption
fragment 1200 ##### very important you can turn it up a bit. but,the lower the safer fragment 1200 ##### very important you can turn it up a bit. but,the lower the safer
mssfix 1200 ##### very important mssfix 1200 ##### very important

View File

@@ -12,10 +12,10 @@
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 use zero iv,you should make sure first block of data contains a random/nonce data 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 use zero iv,you should make sure first block of data contains a random/nonce data
/**** /****
* important! * security of zero_iv + nonce first data block
* why zero iv + nonce first data block is secure?
* 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
****/ ****/
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 *> 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"}}; unordered_map<int, const char *> cipher_mode_tostring={{cipher_none,"none"},{cipher_aes128cbc,"aes128cbc"},{cipher_xor,"xor"}};

View File

@@ -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 "aes0.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_encrypt0(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_decrypt0(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_buffer0(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_buffer0(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)

View File

@@ -1,45 +0,0 @@
/*
* this file comes from https://github.com/kokke/tiny-AES128-C
*/
#ifndef _AES_H_
#define _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_encrypt0(const uint8_t* input, const uint8_t* key, uint8_t *output, const uint32_t length);
void AES_ECB_decrypt0(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_buffer0(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv);
void AES_CBC_decrypt_buffer0(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_

View File

@@ -2,27 +2,25 @@
* This file is adapted from PolarSSL 1.3.19 (GPL) * This file is adapted from PolarSSL 1.3.19 (GPL)
*/ */
#include "aes0.h"
#include "aesni.h" #include "aesni.h"
#include "aesarm.h" #include "aesarm.h"
#include "aesacc.h" #include <stdint.h>
#include <string.h> #include <string.h>
#if defined(AES256) && (AES256 == 1) #if defined(AES256) && (AES256 == 1)
#define AES_KEYSIZE 256 #define AES_KEYSIZE 256
#ifdef HAVE_AMD64 #ifdef HAVE_AMD64
#define aes_setkey_enc aesni_setkey_enc_256 #define aeshw_setkey_enc aesni_setkey_enc_256
#endif #endif
#elif defined(AES192) && (AES192 == 1) #elif defined(AES192) && (AES192 == 1)
#define AES_KEYSIZE 192 #define AES_KEYSIZE 192
#ifdef HAVE_AMD64 #ifdef HAVE_AMD64
#define aes_setkey_enc aesni_setkey_enc_192 #define aeshw_setkey_enc aesni_setkey_enc_192
#endif #endif
#else #else
#define AES_KEYSIZE 128 #define AES_KEYSIZE 128
#ifdef HAVE_AMD64 #ifdef HAVE_AMD64
#define aes_setkey_enc aesni_setkey_enc_128 #define aeshw_setkey_enc aesni_setkey_enc_128
#endif #endif
#endif #endif
@@ -31,15 +29,15 @@
#ifdef HAVE_AMD64 #ifdef HAVE_AMD64
#define HAVE_HARDAES 1 #define HAVE_HARDAES 1
#define aes_supported aesni_supported #define aeshw_supported aesni_supported
#define aes_crypt_ecb aesni_crypt_ecb #define aeshw_crypt_ecb aesni_crypt_ecb
#define aes_inverse_key(a,b) aesni_inverse_key(a,b,AES_NR) #define aeshw_inverse_key(a,b) aesni_inverse_key(a,b,AES_NR)
#endif /* HAVE_AMD64 */ #endif /* HAVE_AMD64 */
#ifdef HAVE_ARM64 #ifdef HAVE_ARM64
#define HAVE_HARDAES 1 #define HAVE_HARDAES 1
#define aes_supported aesarm_supported #define aeshw_supported aesarm_supported
#define aes_crypt_ecb aesarm_crypt_ecb #define aeshw_crypt_ecb aesarm_crypt_ecb
#include "aesarm_table.h" #include "aesarm_table.h"
@@ -53,7 +51,7 @@
} }
#endif #endif
static void aes_setkey_enc(uint8_t *rk, const uint8_t *key) static void aeshw_setkey_enc(uint8_t *rk, const uint8_t *key)
{ {
unsigned int i; unsigned int i;
uint32_t *RK; uint32_t *RK;
@@ -129,7 +127,7 @@ static void aes_setkey_enc(uint8_t *rk, const uint8_t *key)
} }
} }
static void aes_inverse_key(uint8_t *invkey, const uint8_t *fwdkey) static void aeshw_inverse_key(uint8_t *invkey, const uint8_t *fwdkey)
{ {
int i, j; int i, j;
uint32_t *RK; uint32_t *RK;
@@ -159,18 +157,48 @@ static void aes_inverse_key(uint8_t *invkey, const uint8_t *fwdkey)
*RK++ = *SK++; *RK++ = *SK++;
*RK++ = *SK++; *RK++ = *SK++;
} }
#endif /* HAVE_ARM64 */ #endif /* HAVE_ARM64 */
#ifdef HAVE_ASM #ifdef HAVE_HARDAES
static void aeshw_setkey_dec(uint8_t *rk, const uint8_t *key)
{
uint8_t rk_tmp[AES_RKSIZE];
aeshw_setkey_enc(rk_tmp, key);
aeshw_inverse_key(rk, rk_tmp);
}
static void aeshw_encrypt_ecb( int nr,
unsigned char *rk,
const unsigned char input[16],
unsigned char output[16] )
{
aeshw_crypt_ecb(nr, rk, AES_ENCRYPT, input, output);
}
static void aeshw_decrypt_ecb( int nr,
unsigned char *rk,
const unsigned char input[16],
unsigned char output[16] )
{
aeshw_crypt_ecb(nr, rk, AES_DECRYPT, input, output);
}
#endif /* HAVE_HARDAES */
/* OpenSSL assembly functions */
#define AES_MAXNR 14 #define AES_MAXNR 14
typedef struct { typedef struct {
uint32_t rd_key[4 * (AES_MAXNR + 1)]; uint32_t rd_key[4 * (AES_MAXNR + 1)];
int rounds; uint32_t rounds;
} AES_KEY; } AES_KEY;
#if defined(__amd64__) || defined(__x86_64__) || \
defined(__aarch64__)
#define AES_set_encrypt_key vpaes_set_encrypt_key
#define AES_set_decrypt_key vpaes_set_decrypt_key
#define AES_encrypt vpaes_encrypt
#define AES_decrypt vpaes_decrypt
#endif /* VPAES for 64-bit Intel and ARM */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@@ -189,65 +217,54 @@ void AES_decrypt(const unsigned char *in, unsigned char *out,
} }
#endif #endif
static int aes_supported(void) static void aes_encrypt_ecb( int nr,
{
return 2;
}
static void aes_crypt_ecb( int nr,
unsigned char *rk, unsigned char *rk,
int mode,
const unsigned char input[16], const unsigned char input[16],
unsigned char output[16] ) unsigned char output[16] )
{ {
AES_KEY *ctx; AES_encrypt(input, output, (AES_KEY *) rk);
ctx = (AES_KEY *) rk; }
ctx->rounds = nr;
if (mode == AES_DECRYPT) { static void aes_decrypt_ecb( int nr,
AES_decrypt(input, output, ctx); unsigned char *rk,
} else { const unsigned char input[16],
AES_encrypt(input, output, ctx); unsigned char output[16] )
} {
AES_decrypt(input, output, (AES_KEY *) rk);
} }
static void aes_setkey_enc(uint8_t *rk, const uint8_t *key) static void aes_setkey_enc(uint8_t *rk, const uint8_t *key)
{ {
AES_KEY *ctx; AES_set_encrypt_key(key, AES_KEYSIZE, (AES_KEY *) rk);
ctx = (AES_KEY *) rk;
ctx->rounds = AES_NR;
AES_set_encrypt_key(key, AES_KEYSIZE, ctx);
} }
static void aes_setkey_dec(uint8_t *rk, const uint8_t *key) static void aes_setkey_dec(uint8_t *rk, const uint8_t *key)
{ {
AES_KEY *ctx; AES_set_decrypt_key(key, AES_KEYSIZE, (AES_KEY *) rk);
ctx = (AES_KEY *) rk;
ctx->rounds = AES_NR;
AES_set_decrypt_key(key, AES_KEYSIZE, ctx);
} }
#endif static void (*encrypt_ecb) ( int nr,
unsigned char *rk,
const unsigned char input[16],
unsigned char output[16] )
= aes_encrypt_ecb;
#ifdef HAVE_HARDAES static void (*decrypt_ecb) ( int nr,
unsigned char *rk,
const unsigned char input[16],
unsigned char output[16] )
= aes_decrypt_ecb;
static void aes_setkey_dec(uint8_t *rk, const uint8_t *key) static void (*setkey_enc) (uint8_t *rk, const uint8_t *key)
{ = aes_setkey_enc;
uint8_t rk_tmp[AES_RKSIZE];
aes_setkey_enc(rk_tmp, key);
aes_inverse_key(rk, rk_tmp);
}
#endif static void (*setkey_dec) (uint8_t *rk, const uint8_t *key)
= aes_setkey_dec;
#if defined(HAVE_HARDAES) || defined(HAVE_ASM)
#define HAVE_ACC 1
/* /*
* AESNI-CBC buffer encryption/decryption * AESNI-CBC buffer encryption/decryption
*/ */
static void aes_crypt_cbc( int mode, static void encrypt_cbc( uint8_t* rk,
uint8_t* rk,
uint32_t length, uint32_t length,
uint8_t iv[16], uint8_t iv[16],
const uint8_t *input, const uint8_t *input,
@@ -256,12 +273,33 @@ static void aes_crypt_cbc( int mode,
int i; int i;
uint8_t temp[16]; uint8_t temp[16];
if( mode == AES_DECRYPT ) while( length > 0 )
{ {
for( i = 0; i < 16; i++ )
output[i] = (uint8_t)( input[i] ^ iv[i] );
encrypt_ecb( AES_NR, rk, output, output );
memcpy( iv, output, 16 );
input += 16;
output += 16;
length -= 16;
}
}
static void decrypt_cbc( uint8_t* rk,
uint32_t length,
uint8_t iv[16],
const uint8_t *input,
uint8_t *output )
{
int i;
uint8_t temp[16];
while( length > 0 ) while( length > 0 )
{ {
memcpy( temp, input, 16 ); memcpy( temp, input, 16 );
aes_crypt_ecb( AES_NR, rk, mode, input, output ); decrypt_ecb( AES_NR, rk, input, output );
for( i = 0; i < 16; i++ ) for( i = 0; i < 16; i++ )
output[i] = (uint8_t)( output[i] ^ iv[i] ); output[i] = (uint8_t)( output[i] ^ iv[i] );
@@ -272,30 +310,28 @@ static void aes_crypt_cbc( int mode,
output += 16; output += 16;
length -= 16; length -= 16;
} }
}
else
{
while( length > 0 )
{
for( i = 0; i < 16; i++ )
output[i] = (uint8_t)( input[i] ^ iv[i] );
aes_crypt_ecb( AES_NR, rk, mode, output, output );
memcpy( iv, output, 16 );
input += 16;
output += 16;
length -= 16;
}
}
} }
#endif /* HAVE_HARDAES or HAVE_ASM */ static void aeshw_init(void)
int AESACC_supported(void)
{ {
#if defined(HAVE_ACC) #ifdef HAVE_HARDAES
return aes_supported(); static int done = 0;
if (!done) {
if (aeshw_supported()) {
encrypt_ecb = aeshw_encrypt_ecb;
decrypt_ecb = aeshw_decrypt_ecb;
setkey_enc = aeshw_setkey_enc;
setkey_dec = aeshw_setkey_dec;
}
done = 1;
}
#endif
}
int AES_support_hwaccel(void)
{
#ifdef HAVE_HARDAES
return aeshw_supported();
#else #else
return 0; return 0;
#endif #endif
@@ -303,86 +339,56 @@ int AESACC_supported(void)
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_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)
{ {
#if defined(HAVE_ACC)
uint8_t iv_tmp[16]; uint8_t iv_tmp[16];
uint8_t rk[AES_RKSIZE]; uint8_t rk[AES_RKSIZE];
if (aes_supported())
{
if (key == NULL || iv == NULL) if (key == NULL || iv == NULL)
{ {
return; return;
} }
aeshw_init();
memcpy(iv_tmp, iv, 16); memcpy(iv_tmp, iv, 16);
aes_setkey_enc(rk, key); setkey_enc(rk, key);
aes_crypt_cbc(AES_ENCRYPT, rk, \ encrypt_cbc(rk, length, iv_tmp, input, output);
length, iv_tmp, input, output);
return;
}
#endif
AES_CBC_encrypt_buffer0(output, input, length, key, 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_CBC_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)
{ {
#if defined(HAVE_ACC)
uint8_t iv_tmp[16]; uint8_t iv_tmp[16];
uint8_t rk[AES_RKSIZE]; uint8_t rk[AES_RKSIZE];
if (aes_supported())
{
if (key == NULL || iv == NULL) if (key == NULL || iv == NULL)
{ {
return; return;
} }
aeshw_init();
memcpy(iv_tmp, iv, 16); memcpy(iv_tmp, iv, 16);
aes_setkey_dec(rk, key); setkey_dec(rk, key);
aes_crypt_cbc(AES_DECRYPT, rk, \ decrypt_cbc(rk, length, iv_tmp, input, output);
length, iv_tmp, input, output);
return;
}
#endif
AES_CBC_decrypt_buffer0(output, input, length, key, iv);
} }
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)
{ {
#if defined(HAVE_ACC)
uint8_t rk[AES_RKSIZE]; uint8_t rk[AES_RKSIZE];
if (aes_supported())
{
if (key == NULL) if (key == NULL)
{ {
return; return;
} }
aes_setkey_enc(rk, key); aeshw_init();
aes_crypt_ecb(AES_NR, rk, AES_ENCRYPT, input, output); setkey_enc(rk, key);
return; encrypt_ecb(AES_NR, rk, input, output);
}
#endif
AES_ECB_encrypt0(input, key, output, length);
} }
void AES_ECB_decrypt(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)
{ {
#if defined(HAVE_ACC)
uint8_t rk[AES_RKSIZE]; uint8_t rk[AES_RKSIZE];
if (aes_supported())
{
if (key == NULL) if (key == NULL)
{ {
return; return;
} }
aes_setkey_dec(rk, key); aeshw_init();
aes_crypt_ecb(AES_NR, rk, AES_DECRYPT, input, output); setkey_dec(rk, key);
return; decrypt_ecb(AES_NR, rk, input, output);
}
#endif
AES_ECB_decrypt0(input, key, output, length);
} }

View File

@@ -1,20 +0,0 @@
#ifndef _AESACC_H_
#define _AESACC_H_
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
int AESACC_supported(void);
void AESACC_ECB_encrypt(const uint8_t* input, const uint8_t* key, uint8_t *output, const uint32_t length);
void AESACC_ECB_decrypt(const uint8_t* input, const uint8_t* key, uint8_t *output, const uint32_t length);
void AESACC_CBC_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv);
void AESACC_CBC_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv);
#ifdef __cplusplus
}
#endif
#endif /* _AESACC_H_ */

View File

@@ -86,7 +86,7 @@ int aesni_supported( void )
/* /*
* AES-NI AES-ECB block en(de)cryption * AES-NI AES-ECB block en(de)cryption
*/ */
int aesni_crypt_ecb( int nr, void aesni_crypt_ecb( int nr,
unsigned char *rk, unsigned char *rk,
int mode, int mode,
const unsigned char input[16], const unsigned char input[16],
@@ -124,9 +124,6 @@ int aesni_crypt_ecb( int nr,
: :
: "r" (nr), "r" (rk), "r" (mode), "r" (input), "r" (output) : "r" (nr), "r" (rk), "r" (mode), "r" (input), "r" (output)
: "memory", "cc", "xmm0", "xmm1" ); : "memory", "cc", "xmm0", "xmm1" );
return( 0 );
} }
/* /*

View File

@@ -64,10 +64,8 @@ int aesni_supported( void );
* \param mode AES_ENCRYPT or AES_DECRYPT * \param mode AES_ENCRYPT or AES_DECRYPT
* \param input 16-byte input block * \param input 16-byte input block
* \param output 16-byte output block * \param output 16-byte output block
*
* \return 0 on success (cannot fail)
*/ */
int aesni_crypt_ecb( int nr, void aesni_crypt_ecb( int nr,
unsigned char *rk, unsigned char *rk,
int mode, int mode,
const unsigned char input[16], const unsigned char input[16],

1178
lib/aes_acc/asm/arm64.S vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -507,6 +507,7 @@ AES_encrypt:
.frame $29,64,$31 .frame $29,64,$31
.mask 0xc0ff0000,-4 .mask 0xc0ff0000,-4
.set noreorder .set noreorder
.cpload $25
sub $29,64 sub $29,64
sw $31,64-1*4($29) sw $31,64-1*4($29)
sw $30,64-2*4($29) sw $30,64-2*4($29)
@@ -518,8 +519,6 @@ AES_encrypt:
sw $18,64-8*4($29) sw $18,64-8*4($29)
sw $17,64-9*4($29) sw $17,64-9*4($29)
sw $16,64-10*4($29) sw $16,64-10*4($29)
.cplocal $7
.cpsetup $25,$0,AES_encrypt
.set reorder .set reorder
la $7,AES_Te # PIC-ified 'load address' la $7,AES_Te # PIC-ified 'load address'
@@ -1050,6 +1049,7 @@ AES_decrypt:
.frame $29,64,$31 .frame $29,64,$31
.mask 0xc0ff0000,-4 .mask 0xc0ff0000,-4
.set noreorder .set noreorder
.cpload $25
sub $29,64 sub $29,64
sw $31,64-1*4($29) sw $31,64-1*4($29)
sw $30,64-2*4($29) sw $30,64-2*4($29)
@@ -1061,8 +1061,6 @@ AES_decrypt:
sw $18,64-8*4($29) sw $18,64-8*4($29)
sw $17,64-9*4($29) sw $17,64-9*4($29)
sw $16,64-10*4($29) sw $16,64-10*4($29)
.cplocal $7
.cpsetup $25,$0,AES_decrypt
.set reorder .set reorder
la $7,AES_Td # PIC-ified 'load address' la $7,AES_Td # PIC-ified 'load address'
@@ -1359,11 +1357,10 @@ AES_set_encrypt_key:
.frame $29,32,$31 .frame $29,32,$31
.mask 0xc0000000,-4 .mask 0xc0000000,-4
.set noreorder .set noreorder
.cpload $25
sub $29,32 sub $29,32
sw $31,32-1*4($29) sw $31,32-1*4($29)
sw $30,32-2*4($29) sw $30,32-2*4($29)
.cplocal $7
.cpsetup $25,$0,AES_set_encrypt_key
.set reorder .set reorder
la $7,AES_Te4 # PIC-ified 'load address' la $7,AES_Te4 # PIC-ified 'load address'
@@ -1383,11 +1380,10 @@ AES_set_decrypt_key:
.frame $29,32,$31 .frame $29,32,$31
.mask 0xc0000000,-4 .mask 0xc0000000,-4
.set noreorder .set noreorder
.cpload $25
sub $29,32 sub $29,32
sw $31,32-1*4($29) sw $31,32-1*4($29)
sw $30,32-2*4($29) sw $30,32-2*4($29)
.cplocal $7
.cpsetup $25,$0,AES_set_decrypt_key
.set reorder .set reorder
la $7,AES_Te4 # PIC-ified 'load address' la $7,AES_Te4 # PIC-ified 'load address'

1831
lib/aes_acc/asm/mips_be.S vendored Normal file

File diff suppressed because it is too large Load Diff

827
lib/aes_acc/asm/x64.S vendored Normal file
View File

@@ -0,0 +1,827 @@
.text
.type _vpaes_encrypt_core,@function
.align 16
_vpaes_encrypt_core:
movq %rdx,%r9
movq $16,%r11
movl 240(%rdx),%eax
movdqa %xmm9,%xmm1
movdqa .Lk_ipt(%rip),%xmm2
pandn %xmm0,%xmm1
movdqu (%r9),%xmm5
psrld $4,%xmm1
pand %xmm9,%xmm0
.byte 102,15,56,0,208
movdqa .Lk_ipt+16(%rip),%xmm0
.byte 102,15,56,0,193
pxor %xmm5,%xmm2
addq $16,%r9
pxor %xmm2,%xmm0
leaq .Lk_mc_backward(%rip),%r10
jmp .Lenc_entry
.align 16
.Lenc_loop:
movdqa %xmm13,%xmm4
movdqa %xmm12,%xmm0
.byte 102,15,56,0,226
.byte 102,15,56,0,195
pxor %xmm5,%xmm4
movdqa %xmm15,%xmm5
pxor %xmm4,%xmm0
movdqa -64(%r11,%r10,1),%xmm1
.byte 102,15,56,0,234
movdqa (%r11,%r10,1),%xmm4
movdqa %xmm14,%xmm2
.byte 102,15,56,0,211
movdqa %xmm0,%xmm3
pxor %xmm5,%xmm2
.byte 102,15,56,0,193
addq $16,%r9
pxor %xmm2,%xmm0
.byte 102,15,56,0,220
addq $16,%r11
pxor %xmm0,%xmm3
.byte 102,15,56,0,193
andq $0x30,%r11
subq $1,%rax
pxor %xmm3,%xmm0
.Lenc_entry:
movdqa %xmm9,%xmm1
movdqa %xmm11,%xmm5
pandn %xmm0,%xmm1
psrld $4,%xmm1
pand %xmm9,%xmm0
.byte 102,15,56,0,232
movdqa %xmm10,%xmm3
pxor %xmm1,%xmm0
.byte 102,15,56,0,217
movdqa %xmm10,%xmm4
pxor %xmm5,%xmm3
.byte 102,15,56,0,224
movdqa %xmm10,%xmm2
pxor %xmm5,%xmm4
.byte 102,15,56,0,211
movdqa %xmm10,%xmm3
pxor %xmm0,%xmm2
.byte 102,15,56,0,220
movdqu (%r9),%xmm5
pxor %xmm1,%xmm3
jnz .Lenc_loop
movdqa -96(%r10),%xmm4
movdqa -80(%r10),%xmm0
.byte 102,15,56,0,226
pxor %xmm5,%xmm4
.byte 102,15,56,0,195
movdqa 64(%r11,%r10,1),%xmm1
pxor %xmm4,%xmm0
.byte 102,15,56,0,193
.byte 0xf3,0xc3
.size _vpaes_encrypt_core,.-_vpaes_encrypt_core
.type _vpaes_decrypt_core,@function
.align 16
_vpaes_decrypt_core:
movq %rdx,%r9
movl 240(%rdx),%eax
movdqa %xmm9,%xmm1
movdqa .Lk_dipt(%rip),%xmm2
pandn %xmm0,%xmm1
movq %rax,%r11
psrld $4,%xmm1
movdqu (%r9),%xmm5
shlq $4,%r11
pand %xmm9,%xmm0
.byte 102,15,56,0,208
movdqa .Lk_dipt+16(%rip),%xmm0
xorq $0x30,%r11
leaq .Lk_dsbd(%rip),%r10
.byte 102,15,56,0,193
andq $0x30,%r11
pxor %xmm5,%xmm2
movdqa .Lk_mc_forward+48(%rip),%xmm5
pxor %xmm2,%xmm0
addq $16,%r9
addq %r10,%r11
jmp .Ldec_entry
.align 16
.Ldec_loop:
movdqa -32(%r10),%xmm4
movdqa -16(%r10),%xmm1
.byte 102,15,56,0,226
.byte 102,15,56,0,203
pxor %xmm4,%xmm0
movdqa 0(%r10),%xmm4
pxor %xmm1,%xmm0
movdqa 16(%r10),%xmm1
.byte 102,15,56,0,226
.byte 102,15,56,0,197
.byte 102,15,56,0,203
pxor %xmm4,%xmm0
movdqa 32(%r10),%xmm4
pxor %xmm1,%xmm0
movdqa 48(%r10),%xmm1
.byte 102,15,56,0,226
.byte 102,15,56,0,197
.byte 102,15,56,0,203
pxor %xmm4,%xmm0
movdqa 64(%r10),%xmm4
pxor %xmm1,%xmm0
movdqa 80(%r10),%xmm1
.byte 102,15,56,0,226
.byte 102,15,56,0,197
.byte 102,15,56,0,203
pxor %xmm4,%xmm0
addq $16,%r9
.byte 102,15,58,15,237,12
pxor %xmm1,%xmm0
subq $1,%rax
.Ldec_entry:
movdqa %xmm9,%xmm1
pandn %xmm0,%xmm1
movdqa %xmm11,%xmm2
psrld $4,%xmm1
pand %xmm9,%xmm0
.byte 102,15,56,0,208
movdqa %xmm10,%xmm3
pxor %xmm1,%xmm0
.byte 102,15,56,0,217
movdqa %xmm10,%xmm4
pxor %xmm2,%xmm3
.byte 102,15,56,0,224
pxor %xmm2,%xmm4
movdqa %xmm10,%xmm2
.byte 102,15,56,0,211
movdqa %xmm10,%xmm3
pxor %xmm0,%xmm2
.byte 102,15,56,0,220
movdqu (%r9),%xmm0
pxor %xmm1,%xmm3
jnz .Ldec_loop
movdqa 96(%r10),%xmm4
.byte 102,15,56,0,226
pxor %xmm0,%xmm4
movdqa 112(%r10),%xmm0
movdqa -352(%r11),%xmm2
.byte 102,15,56,0,195
pxor %xmm4,%xmm0
.byte 102,15,56,0,194
.byte 0xf3,0xc3
.size _vpaes_decrypt_core,.-_vpaes_decrypt_core
.type _vpaes_schedule_core,@function
.align 16
_vpaes_schedule_core:
call _vpaes_preheat
movdqa .Lk_rcon(%rip),%xmm8
movdqu (%rdi),%xmm0
movdqa %xmm0,%xmm3
leaq .Lk_ipt(%rip),%r11
call _vpaes_schedule_transform
movdqa %xmm0,%xmm7
leaq .Lk_sr(%rip),%r10
testq %rcx,%rcx
jnz .Lschedule_am_decrypting
movdqu %xmm0,(%rdx)
jmp .Lschedule_go
.Lschedule_am_decrypting:
movdqa (%r8,%r10,1),%xmm1
.byte 102,15,56,0,217
movdqu %xmm3,(%rdx)
xorq $0x30,%r8
.Lschedule_go:
cmpl $192,%esi
ja .Lschedule_256
je .Lschedule_192
.Lschedule_128:
movl $10,%esi
.Loop_schedule_128:
call _vpaes_schedule_round
decq %rsi
jz .Lschedule_mangle_last
call _vpaes_schedule_mangle
jmp .Loop_schedule_128
.align 16
.Lschedule_192:
movdqu 8(%rdi),%xmm0
call _vpaes_schedule_transform
movdqa %xmm0,%xmm6
pxor %xmm4,%xmm4
movhlps %xmm4,%xmm6
movl $4,%esi
.Loop_schedule_192:
call _vpaes_schedule_round
.byte 102,15,58,15,198,8
call _vpaes_schedule_mangle
call _vpaes_schedule_192_smear
call _vpaes_schedule_mangle
call _vpaes_schedule_round
decq %rsi
jz .Lschedule_mangle_last
call _vpaes_schedule_mangle
call _vpaes_schedule_192_smear
jmp .Loop_schedule_192
.align 16
.Lschedule_256:
movdqu 16(%rdi),%xmm0
call _vpaes_schedule_transform
movl $7,%esi
.Loop_schedule_256:
call _vpaes_schedule_mangle
movdqa %xmm0,%xmm6
call _vpaes_schedule_round
decq %rsi
jz .Lschedule_mangle_last
call _vpaes_schedule_mangle
pshufd $0xFF,%xmm0,%xmm0
movdqa %xmm7,%xmm5
movdqa %xmm6,%xmm7
call _vpaes_schedule_low_round
movdqa %xmm5,%xmm7
jmp .Loop_schedule_256
.align 16
.Lschedule_mangle_last:
leaq .Lk_deskew(%rip),%r11
testq %rcx,%rcx
jnz .Lschedule_mangle_last_dec
movdqa (%r8,%r10,1),%xmm1
.byte 102,15,56,0,193
leaq .Lk_opt(%rip),%r11
addq $32,%rdx
.Lschedule_mangle_last_dec:
addq $-16,%rdx
pxor .Lk_s63(%rip),%xmm0
call _vpaes_schedule_transform
movdqu %xmm0,(%rdx)
pxor %xmm0,%xmm0
pxor %xmm1,%xmm1
pxor %xmm2,%xmm2
pxor %xmm3,%xmm3
pxor %xmm4,%xmm4
pxor %xmm5,%xmm5
pxor %xmm6,%xmm6
pxor %xmm7,%xmm7
.byte 0xf3,0xc3
.size _vpaes_schedule_core,.-_vpaes_schedule_core
.type _vpaes_schedule_192_smear,@function
.align 16
_vpaes_schedule_192_smear:
pshufd $0x80,%xmm6,%xmm1
pshufd $0xFE,%xmm7,%xmm0
pxor %xmm1,%xmm6
pxor %xmm1,%xmm1
pxor %xmm0,%xmm6
movdqa %xmm6,%xmm0
movhlps %xmm1,%xmm6
.byte 0xf3,0xc3
.size _vpaes_schedule_192_smear,.-_vpaes_schedule_192_smear
.type _vpaes_schedule_round,@function
.align 16
_vpaes_schedule_round:
pxor %xmm1,%xmm1
.byte 102,65,15,58,15,200,15
.byte 102,69,15,58,15,192,15
pxor %xmm1,%xmm7
pshufd $0xFF,%xmm0,%xmm0
.byte 102,15,58,15,192,1
_vpaes_schedule_low_round:
movdqa %xmm7,%xmm1
pslldq $4,%xmm7
pxor %xmm1,%xmm7
movdqa %xmm7,%xmm1
pslldq $8,%xmm7
pxor %xmm1,%xmm7
pxor .Lk_s63(%rip),%xmm7
movdqa %xmm9,%xmm1
pandn %xmm0,%xmm1
psrld $4,%xmm1
pand %xmm9,%xmm0
movdqa %xmm11,%xmm2
.byte 102,15,56,0,208
pxor %xmm1,%xmm0
movdqa %xmm10,%xmm3
.byte 102,15,56,0,217
pxor %xmm2,%xmm3
movdqa %xmm10,%xmm4
.byte 102,15,56,0,224
pxor %xmm2,%xmm4
movdqa %xmm10,%xmm2
.byte 102,15,56,0,211
pxor %xmm0,%xmm2
movdqa %xmm10,%xmm3
.byte 102,15,56,0,220
pxor %xmm1,%xmm3
movdqa %xmm13,%xmm4
.byte 102,15,56,0,226
movdqa %xmm12,%xmm0
.byte 102,15,56,0,195
pxor %xmm4,%xmm0
pxor %xmm7,%xmm0
movdqa %xmm0,%xmm7
.byte 0xf3,0xc3
.size _vpaes_schedule_round,.-_vpaes_schedule_round
.type _vpaes_schedule_transform,@function
.align 16
_vpaes_schedule_transform:
movdqa %xmm9,%xmm1
pandn %xmm0,%xmm1
psrld $4,%xmm1
pand %xmm9,%xmm0
movdqa (%r11),%xmm2
.byte 102,15,56,0,208
movdqa 16(%r11),%xmm0
.byte 102,15,56,0,193
pxor %xmm2,%xmm0
.byte 0xf3,0xc3
.size _vpaes_schedule_transform,.-_vpaes_schedule_transform
.type _vpaes_schedule_mangle,@function
.align 16
_vpaes_schedule_mangle:
movdqa %xmm0,%xmm4
movdqa .Lk_mc_forward(%rip),%xmm5
testq %rcx,%rcx
jnz .Lschedule_mangle_dec
addq $16,%rdx
pxor .Lk_s63(%rip),%xmm4
.byte 102,15,56,0,229
movdqa %xmm4,%xmm3
.byte 102,15,56,0,229
pxor %xmm4,%xmm3
.byte 102,15,56,0,229
pxor %xmm4,%xmm3
jmp .Lschedule_mangle_both
.align 16
.Lschedule_mangle_dec:
leaq .Lk_dksd(%rip),%r11
movdqa %xmm9,%xmm1
pandn %xmm4,%xmm1
psrld $4,%xmm1
pand %xmm9,%xmm4
movdqa 0(%r11),%xmm2
.byte 102,15,56,0,212
movdqa 16(%r11),%xmm3
.byte 102,15,56,0,217
pxor %xmm2,%xmm3
.byte 102,15,56,0,221
movdqa 32(%r11),%xmm2
.byte 102,15,56,0,212
pxor %xmm3,%xmm2
movdqa 48(%r11),%xmm3
.byte 102,15,56,0,217
pxor %xmm2,%xmm3
.byte 102,15,56,0,221
movdqa 64(%r11),%xmm2
.byte 102,15,56,0,212
pxor %xmm3,%xmm2
movdqa 80(%r11),%xmm3
.byte 102,15,56,0,217
pxor %xmm2,%xmm3
.byte 102,15,56,0,221
movdqa 96(%r11),%xmm2
.byte 102,15,56,0,212
pxor %xmm3,%xmm2
movdqa 112(%r11),%xmm3
.byte 102,15,56,0,217
pxor %xmm2,%xmm3
addq $-16,%rdx
.Lschedule_mangle_both:
movdqa (%r8,%r10,1),%xmm1
.byte 102,15,56,0,217
addq $-16,%r8
andq $0x30,%r8
movdqu %xmm3,(%rdx)
.byte 0xf3,0xc3
.size _vpaes_schedule_mangle,.-_vpaes_schedule_mangle
.globl vpaes_set_encrypt_key
.type vpaes_set_encrypt_key,@function
.align 16
vpaes_set_encrypt_key:
movl %esi,%eax
shrl $5,%eax
addl $5,%eax
movl %eax,240(%rdx)
movl $0,%ecx
movl $0x30,%r8d
call _vpaes_schedule_core
xorl %eax,%eax
.byte 0xf3,0xc3
.size vpaes_set_encrypt_key,.-vpaes_set_encrypt_key
.globl vpaes_set_decrypt_key
.type vpaes_set_decrypt_key,@function
.align 16
vpaes_set_decrypt_key:
movl %esi,%eax
shrl $5,%eax
addl $5,%eax
movl %eax,240(%rdx)
shll $4,%eax
leaq 16(%rdx,%rax,1),%rdx
movl $1,%ecx
movl %esi,%r8d
shrl $1,%r8d
andl $32,%r8d
xorl $32,%r8d
call _vpaes_schedule_core
xorl %eax,%eax
.byte 0xf3,0xc3
.size vpaes_set_decrypt_key,.-vpaes_set_decrypt_key
.globl vpaes_encrypt
.type vpaes_encrypt,@function
.align 16
vpaes_encrypt:
movdqu (%rdi),%xmm0
call _vpaes_preheat
call _vpaes_encrypt_core
movdqu %xmm0,(%rsi)
.byte 0xf3,0xc3
.size vpaes_encrypt,.-vpaes_encrypt
.globl vpaes_decrypt
.type vpaes_decrypt,@function
.align 16
vpaes_decrypt:
movdqu (%rdi),%xmm0
call _vpaes_preheat
call _vpaes_decrypt_core
movdqu %xmm0,(%rsi)
.byte 0xf3,0xc3
.size vpaes_decrypt,.-vpaes_decrypt
.globl vpaes_cbc_encrypt
.type vpaes_cbc_encrypt,@function
.align 16
vpaes_cbc_encrypt:
xchgq %rcx,%rdx
subq $16,%rcx
jc .Lcbc_abort
movdqu (%r8),%xmm6
subq %rdi,%rsi
call _vpaes_preheat
cmpl $0,%r9d
je .Lcbc_dec_loop
jmp .Lcbc_enc_loop
.align 16
.Lcbc_enc_loop:
movdqu (%rdi),%xmm0
pxor %xmm6,%xmm0
call _vpaes_encrypt_core
movdqa %xmm0,%xmm6
movdqu %xmm0,(%rsi,%rdi,1)
leaq 16(%rdi),%rdi
subq $16,%rcx
jnc .Lcbc_enc_loop
jmp .Lcbc_done
.align 16
.Lcbc_dec_loop:
movdqu (%rdi),%xmm0
movdqa %xmm0,%xmm7
call _vpaes_decrypt_core
pxor %xmm6,%xmm0
movdqa %xmm7,%xmm6
movdqu %xmm0,(%rsi,%rdi,1)
leaq 16(%rdi),%rdi
subq $16,%rcx
jnc .Lcbc_dec_loop
.Lcbc_done:
movdqu %xmm6,(%r8)
.Lcbc_abort:
.byte 0xf3,0xc3
.size vpaes_cbc_encrypt,.-vpaes_cbc_encrypt
.type _vpaes_preheat,@function
.align 16
_vpaes_preheat:
leaq .Lk_s0F(%rip),%r10
movdqa -32(%r10),%xmm10
movdqa -16(%r10),%xmm11
movdqa 0(%r10),%xmm9
movdqa 48(%r10),%xmm13
movdqa 64(%r10),%xmm12
movdqa 80(%r10),%xmm15
movdqa 96(%r10),%xmm14
.byte 0xf3,0xc3
.size _vpaes_preheat,.-_vpaes_preheat
.type _vpaes_consts,@object
.align 64
_vpaes_consts:
.Lk_inv:
.quad 0x0E05060F0D080180, 0x040703090A0B0C02
.quad 0x01040A060F0B0780, 0x030D0E0C02050809
.Lk_s0F:
.quad 0x0F0F0F0F0F0F0F0F, 0x0F0F0F0F0F0F0F0F
.Lk_ipt:
.quad 0xC2B2E8985A2A7000, 0xCABAE09052227808
.quad 0x4C01307D317C4D00, 0xCD80B1FCB0FDCC81
.Lk_sb1:
.quad 0xB19BE18FCB503E00, 0xA5DF7A6E142AF544
.quad 0x3618D415FAE22300, 0x3BF7CCC10D2ED9EF
.Lk_sb2:
.quad 0xE27A93C60B712400, 0x5EB7E955BC982FCD
.quad 0x69EB88400AE12900, 0xC2A163C8AB82234A
.Lk_sbo:
.quad 0xD0D26D176FBDC700, 0x15AABF7AC502A878
.quad 0xCFE474A55FBB6A00, 0x8E1E90D1412B35FA
.Lk_mc_forward:
.quad 0x0407060500030201, 0x0C0F0E0D080B0A09
.quad 0x080B0A0904070605, 0x000302010C0F0E0D
.quad 0x0C0F0E0D080B0A09, 0x0407060500030201
.quad 0x000302010C0F0E0D, 0x080B0A0904070605
.Lk_mc_backward:
.quad 0x0605040702010003, 0x0E0D0C0F0A09080B
.quad 0x020100030E0D0C0F, 0x0A09080B06050407
.quad 0x0E0D0C0F0A09080B, 0x0605040702010003
.quad 0x0A09080B06050407, 0x020100030E0D0C0F
.Lk_sr:
.quad 0x0706050403020100, 0x0F0E0D0C0B0A0908
.quad 0x030E09040F0A0500, 0x0B06010C07020D08
.quad 0x0F060D040B020900, 0x070E050C030A0108
.quad 0x0B0E0104070A0D00, 0x0306090C0F020508
.Lk_rcon:
.quad 0x1F8391B9AF9DEEB6, 0x702A98084D7C7D81
.Lk_s63:
.quad 0x5B5B5B5B5B5B5B5B, 0x5B5B5B5B5B5B5B5B
.Lk_opt:
.quad 0xFF9F4929D6B66000, 0xF7974121DEBE6808
.quad 0x01EDBD5150BCEC00, 0xE10D5DB1B05C0CE0
.Lk_deskew:
.quad 0x07E4A34047A4E300, 0x1DFEB95A5DBEF91A
.quad 0x5F36B5DC83EA6900, 0x2841C2ABF49D1E77
.Lk_dksd:
.quad 0xFEB91A5DA3E44700, 0x0740E3A45A1DBEF9
.quad 0x41C277F4B5368300, 0x5FDC69EAAB289D1E
.Lk_dksb:
.quad 0x9A4FCA1F8550D500, 0x03D653861CC94C99
.quad 0x115BEDA7B6FC4A00, 0xD993256F7E3482C8
.Lk_dkse:
.quad 0xD5031CCA1FC9D600, 0x53859A4C994F5086
.quad 0xA23196054FDC7BE8, 0xCD5EF96A20B31487
.Lk_dks9:
.quad 0xB6116FC87ED9A700, 0x4AED933482255BFC
.quad 0x4576516227143300, 0x8BB89FACE9DAFDCE
.Lk_dipt:
.quad 0x0F505B040B545F00, 0x154A411E114E451A
.quad 0x86E383E660056500, 0x12771772F491F194
.Lk_dsb9:
.quad 0x851C03539A86D600, 0xCAD51F504F994CC9
.quad 0xC03B1789ECD74900, 0x725E2C9EB2FBA565
.Lk_dsbd:
.quad 0x7D57CCDFE6B1A200, 0xF56E9B13882A4439
.quad 0x3CE2FAF724C6CB00, 0x2931180D15DEEFD3
.Lk_dsbb:
.quad 0xD022649296B44200, 0x602646F6B0F2D404
.quad 0xC19498A6CD596700, 0xF3FF0C3E3255AA6B
.Lk_dsbe:
.quad 0x46F2929626D4D000, 0x2242600464B4F6B0
.quad 0x0C55A6CDFFAAC100, 0x9467F36B98593E32
.Lk_dsbo:
.quad 0x1387EA537EF94000, 0xC7AA6DB9D4943E2D
.quad 0x12D7560F93441D00, 0xCA4B8159D8C58E9C
.byte 86,101,99,116,111,114,32,80,101,114,109,117,116,97,116,105,111,110,32,65,69,83,32,102,111,114,32,120,56,54,95,54,52,47,83,83,83,69,51,44,32,77,105,107,101,32,72,97,109,98,117,114,103,32,40,83,116,97,110,102,111,114,100,32,85,110,105,118,101,114,115,105,116,121,41,0
.align 64
.size _vpaes_consts,.-_vpaes_consts

474
lib/md5.c
View File

@@ -1,176 +1,312 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
/* /*
* this file comes from https://github.com/pod32g/MD5/blob/master/md5.c * This file is adapted from PolarSSL 1.3.19 (GPL)
*/ */
// Constants are the integer part of the sines of integers (in radians) * 2^32.
const uint32_t k[64] = {
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee ,
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501 ,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be ,
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821 ,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa ,
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8 ,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed ,
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a ,
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c ,
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70 ,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05 ,
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665 ,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039 ,
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1 ,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1 ,
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 };
// r specifies the per-round shift amounts
const uint32_t r[] = {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21};
// leftrotate function definition
#define LEFTROTATE(x, c) (((x) << (c)) | ((x) >> (32 - (c))))
void to_bytes(uint32_t val, uint8_t *bytes)
{
bytes[0] = (uint8_t) val;
bytes[1] = (uint8_t) (val >> 8);
bytes[2] = (uint8_t) (val >> 16);
bytes[3] = (uint8_t) (val >> 24);
}
uint32_t to_int32(const uint8_t *bytes)
{
return (uint32_t) bytes[0]
| ((uint32_t) bytes[1] << 8)
| ((uint32_t) bytes[2] << 16)
| ((uint32_t) bytes[3] << 24);
}
void md5(const uint8_t *initial_msg, size_t initial_len, uint8_t *digest) {
// These vars will contain the hash
uint32_t h0, h1, h2, h3;
// Message (to prepare)
uint8_t *msg = NULL;
size_t new_len, offset;
uint32_t w[16];
uint32_t a, b, c, d, i, f, g, temp;
// Initialize variables - simple count in nibbles:
h0 = 0x67452301;
h1 = 0xefcdab89;
h2 = 0x98badcfe;
h3 = 0x10325476;
//Pre-processing:
//append "1" bit to message
//append "0" bits until message length in bits ≡ 448 (mod 512)
//append length mod (2^64) to message
for (new_len = initial_len + 1; new_len % (512/8) != 448/8; new_len++)
;
uint8_t buf[new_len + 8];
msg = buf;//(uint8_t*)malloc(new_len + 8);
memcpy(msg, initial_msg, initial_len);
msg[initial_len] = 0x80; // append the "1" bit; most significant bit is "first"
for (offset = initial_len + 1; offset < new_len; offset++)
msg[offset] = 0; // append "0" bits
// append the len in bits at the end of the buffer.
to_bytes(initial_len*8, msg + new_len);
// initial_len>>29 == initial_len*8>>32, but avoids overflow.
to_bytes(initial_len>>29, msg + new_len + 4);
// Process the message in successive 512-bit chunks:
//for each 512-bit chunk of message:
for(offset=0; offset<new_len; offset += (512/8)) {
// break chunk into sixteen 32-bit words w[j], 0 ≤ j ≤ 15
for (i = 0; i < 16; i++)
w[i] = to_int32(msg + offset + i*4);
// Initialize hash value for this chunk:
a = h0;
b = h1;
c = h2;
d = h3;
// Main loop:
for(i = 0; i<64; i++) {
if (i < 16) {
f = (b & c) | ((~b) & d);
g = i;
} else if (i < 32) {
f = (d & b) | ((~d) & c);
g = (5*i + 1) % 16;
} else if (i < 48) {
f = b ^ c ^ d;
g = (3*i + 5) % 16;
} else {
f = c ^ (b | (~d));
g = (7*i) % 16;
}
temp = d;
d = c;
c = b;
b = b + LEFTROTATE((a + f + k[i] + w[g]), r[i]);
a = temp;
}
// Add this chunk's hash to result so far:
h0 += a;
h1 += b;
h2 += c;
h3 += d;
}
// cleanup
//free(msg);
//var char digest[16] := h0 append h1 append h2 append h3 //(Output is in little-endian)
to_bytes(h0, digest);
to_bytes(h1, digest + 4);
to_bytes(h2, digest + 8);
to_bytes(h3, digest + 12);
}
/* /*
int main(int argc, char **argv) { * RFC 1321 compliant MD5 implementation
char *msg; *
size_t len; * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
int i; *
uint8_t result[16]; * 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 MD5 algorithm was designed by Ron Rivest in 1991.
*
* http://www.ietf.org/rfc/rfc1321.txt
*/
if (argc < 2) { #include <string.h>
printf("usage: %s 'string'\n", argv[0]); #include <stddef.h>
return 1; #include <stdint.h>
}
msg = argv[1];
len = strlen(msg); typedef struct
{
// benchmark uint32_t total[2]; /*!< number of bytes processed */
for (i = 0; i < 1000000; i++) { uint32_t state[4]; /*!< intermediate digest state */
md5((uint8_t*)msg, len, result); unsigned char buffer[64]; /*!< data block being processed */
} }
md5_context;
// display result
for (i = 0; i < 16; i++) /* Implementation that should never be optimized out by the compiler */
printf("%2.2x", result[i]); static void polarssl_zeroize( void *v, size_t n ) {
puts(""); volatile unsigned char *p = (unsigned char *) v; while( n-- ) *p++ = 0;
}
return 0;
/*
* 32-bit integer manipulation macros (little endian)
*/
#ifndef GET_UINT32_LE
#define GET_UINT32_LE(n,b,i) \
{ \
(n) = ( (uint32_t) (b)[(i) ] ) \
| ( (uint32_t) (b)[(i) + 1] << 8 ) \
| ( (uint32_t) (b)[(i) + 2] << 16 ) \
| ( (uint32_t) (b)[(i) + 3] << 24 ); \
}
#endif
#ifndef PUT_UINT32_LE
#define PUT_UINT32_LE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
(b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
(b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \
(b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \
}
#endif
void md5_init( md5_context *ctx )
{
memset( ctx, 0, sizeof( md5_context ) );
}
void md5_free( md5_context *ctx )
{
if( ctx == NULL )
return;
polarssl_zeroize( ctx, sizeof( md5_context ) );
}
/*
* MD5 context setup
*/
void md5_starts( md5_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;
}
void md5_process( md5_context *ctx, const unsigned char data[64] )
{
uint32_t X[16], A, B, C, D;
GET_UINT32_LE( X[ 0], data, 0 );
GET_UINT32_LE( X[ 1], data, 4 );
GET_UINT32_LE( X[ 2], data, 8 );
GET_UINT32_LE( X[ 3], data, 12 );
GET_UINT32_LE( X[ 4], data, 16 );
GET_UINT32_LE( X[ 5], data, 20 );
GET_UINT32_LE( X[ 6], data, 24 );
GET_UINT32_LE( X[ 7], data, 28 );
GET_UINT32_LE( X[ 8], data, 32 );
GET_UINT32_LE( X[ 9], data, 36 );
GET_UINT32_LE( X[10], data, 40 );
GET_UINT32_LE( X[11], data, 44 );
GET_UINT32_LE( X[12], data, 48 );
GET_UINT32_LE( X[13], data, 52 );
GET_UINT32_LE( X[14], data, 56 );
GET_UINT32_LE( X[15], data, 60 );
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
#define P(a,b,c,d,k,s,t) \
{ \
a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
}
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
#define F(x,y,z) (z ^ (x & (y ^ z)))
P( A, B, C, D, 0, 7, 0xD76AA478 );
P( D, A, B, C, 1, 12, 0xE8C7B756 );
P( C, D, A, B, 2, 17, 0x242070DB );
P( B, C, D, A, 3, 22, 0xC1BDCEEE );
P( A, B, C, D, 4, 7, 0xF57C0FAF );
P( D, A, B, C, 5, 12, 0x4787C62A );
P( C, D, A, B, 6, 17, 0xA8304613 );
P( B, C, D, A, 7, 22, 0xFD469501 );
P( A, B, C, D, 8, 7, 0x698098D8 );
P( D, A, B, C, 9, 12, 0x8B44F7AF );
P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
P( B, C, D, A, 11, 22, 0x895CD7BE );
P( A, B, C, D, 12, 7, 0x6B901122 );
P( D, A, B, C, 13, 12, 0xFD987193 );
P( C, D, A, B, 14, 17, 0xA679438E );
P( B, C, D, A, 15, 22, 0x49B40821 );
#undef F
#define F(x,y,z) (y ^ (z & (x ^ y)))
P( A, B, C, D, 1, 5, 0xF61E2562 );
P( D, A, B, C, 6, 9, 0xC040B340 );
P( C, D, A, B, 11, 14, 0x265E5A51 );
P( B, C, D, A, 0, 20, 0xE9B6C7AA );
P( A, B, C, D, 5, 5, 0xD62F105D );
P( D, A, B, C, 10, 9, 0x02441453 );
P( C, D, A, B, 15, 14, 0xD8A1E681 );
P( B, C, D, A, 4, 20, 0xE7D3FBC8 );
P( A, B, C, D, 9, 5, 0x21E1CDE6 );
P( D, A, B, C, 14, 9, 0xC33707D6 );
P( C, D, A, B, 3, 14, 0xF4D50D87 );
P( B, C, D, A, 8, 20, 0x455A14ED );
P( A, B, C, D, 13, 5, 0xA9E3E905 );
P( D, A, B, C, 2, 9, 0xFCEFA3F8 );
P( C, D, A, B, 7, 14, 0x676F02D9 );
P( B, C, D, A, 12, 20, 0x8D2A4C8A );
#undef F
#define F(x,y,z) (x ^ y ^ z)
P( A, B, C, D, 5, 4, 0xFFFA3942 );
P( D, A, B, C, 8, 11, 0x8771F681 );
P( C, D, A, B, 11, 16, 0x6D9D6122 );
P( B, C, D, A, 14, 23, 0xFDE5380C );
P( A, B, C, D, 1, 4, 0xA4BEEA44 );
P( D, A, B, C, 4, 11, 0x4BDECFA9 );
P( C, D, A, B, 7, 16, 0xF6BB4B60 );
P( B, C, D, A, 10, 23, 0xBEBFBC70 );
P( A, B, C, D, 13, 4, 0x289B7EC6 );
P( D, A, B, C, 0, 11, 0xEAA127FA );
P( C, D, A, B, 3, 16, 0xD4EF3085 );
P( B, C, D, A, 6, 23, 0x04881D05 );
P( A, B, C, D, 9, 4, 0xD9D4D039 );
P( D, A, B, C, 12, 11, 0xE6DB99E5 );
P( C, D, A, B, 15, 16, 0x1FA27CF8 );
P( B, C, D, A, 2, 23, 0xC4AC5665 );
#undef F
#define F(x,y,z) (y ^ (x | ~z))
P( A, B, C, D, 0, 6, 0xF4292244 );
P( D, A, B, C, 7, 10, 0x432AFF97 );
P( C, D, A, B, 14, 15, 0xAB9423A7 );
P( B, C, D, A, 5, 21, 0xFC93A039 );
P( A, B, C, D, 12, 6, 0x655B59C3 );
P( D, A, B, C, 3, 10, 0x8F0CCC92 );
P( C, D, A, B, 10, 15, 0xFFEFF47D );
P( B, C, D, A, 1, 21, 0x85845DD1 );
P( A, B, C, D, 8, 6, 0x6FA87E4F );
P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
P( C, D, A, B, 6, 15, 0xA3014314 );
P( B, C, D, A, 13, 21, 0x4E0811A1 );
P( A, B, C, D, 4, 6, 0xF7537E82 );
P( D, A, B, C, 11, 10, 0xBD3AF235 );
P( C, D, A, B, 2, 15, 0x2AD7D2BB );
P( B, C, D, A, 9, 21, 0xEB86D391 );
#undef F
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
}
/*
* MD5 process buffer
*/
void md5_update( md5_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 );
md5_process( ctx, ctx->buffer );
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 64 )
{
md5_process( ctx, input );
input += 64;
ilen -= 64;
}
if( ilen > 0 )
{
memcpy( (void *) (ctx->buffer + left), input, ilen );
}
}
static const unsigned char md5_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
};
/*
* MD5 final digest
*/
void md5_finish( md5_context *ctx, unsigned char output[16] )
{
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_LE( low, msglen, 0 );
PUT_UINT32_LE( high, msglen, 4 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
md5_update( ctx, md5_padding, padn );
md5_update( ctx, msglen, 8 );
PUT_UINT32_LE( ctx->state[0], output, 0 );
PUT_UINT32_LE( ctx->state[1], output, 4 );
PUT_UINT32_LE( ctx->state[2], output, 8 );
PUT_UINT32_LE( ctx->state[3], output, 12 );
}
/*
* output = MD5( input buffer )
*/
void md5( const unsigned char *input, size_t ilen, unsigned char output[16] )
{
md5_context ctx;
md5_init( &ctx );
md5_starts( &ctx );
md5_update( &ctx, input, ilen );
md5_finish( &ctx, output );
md5_free( &ctx );
} }
*/

View File

@@ -1,9 +1,7 @@
#ifndef _MD5_H_ #ifndef _MD5_H_
#define _MD5_H_ #define _MD5_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h> #include <stdint.h>
#include <stddef.h>
void md5(const uint8_t *initial_msg, size_t initial_len, uint8_t *digest); void md5(const uint8_t *initial_msg, size_t initial_len, uint8_t *digest);

345
lib/sha1.c Normal file
View File

@@ -0,0 +1,345 @@
/*
* 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 );
}

50
log.h
View File

@@ -2,56 +2,8 @@
#ifndef _LOG_MYLOG_H_ #ifndef _LOG_MYLOG_H_
#define _LOG_MYLOG_H_ #define _LOG_MYLOG_H_
#include<stdio.h>
#include<string.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<getopt.h>
#include <unistd.h>
#include<errno.h>
#include <fcntl.h> #include<common.h>
//#include"aes.h"
#include <sys/epoll.h>
#include <sys/wait.h>
#include<map>
#include<string>
#include<vector>
#include <sys/socket.h> //for socket ofcourse
#include <sys/types.h>
#include <stdlib.h> //for exit(0);
#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 <byteswap.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <linux/if_ether.h>
#include <linux/filter.h>
#include <sys/time.h>
#include <time.h>
#include <sys/timerfd.h>
#include <set>
#include "encrypt.h"
#include <inttypes.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <stdarg.h>
using namespace std; using namespace std;

615
main.cpp
View File

@@ -2,6 +2,12 @@
#include "network.h" #include "network.h"
#include "log.h" #include "log.h"
#include "lib/md5.h" #include "lib/md5.h"
#include "encrypt.h"
#include <fstream>
#include <string>
#include <vector>
#include <map>
#include <set>
char local_ip[100]="0.0.0.0", remote_ip[100]="255.255.255.255",source_ip[100]="0.0.0.0"; char local_ip[100]="0.0.0.0", remote_ip[100]="255.255.255.255",source_ip[100]="0.0.0.0";
u32_t local_ip_uint32,remote_ip_uint32,source_ip_uint32; u32_t local_ip_uint32,remote_ip_uint32,source_ip_uint32;
@@ -32,8 +38,12 @@ int fail_time_counter=0;
int epoll_trigger_counter=0; int epoll_trigger_counter=0;
int debug_flag=0; int debug_flag=0;
int simple_rule=0;
int keep_rule=0;
int auto_add_iptables_rule=0; int auto_add_iptables_rule=0;
int generate_iptables_rule=0; int generate_iptables_rule=0;
int generate_iptables_rule_add=0;
int debug_resend=0; int debug_resend=0;
int disable_anti_replay=0; int disable_anti_replay=0;
@@ -565,6 +575,8 @@ int server_on_raw_recv_pre_ready(conn_info_t &conn_info,char * ip_port,u32_t tmp
int server_on_raw_recv_ready(conn_info_t &conn_info,char * ip_port,char type,char *data,int data_len); int server_on_raw_recv_ready(conn_info_t &conn_info,char * ip_port,char type,char *data,int data_len);
int server_on_raw_recv_handshake1(conn_info_t &conn_info,char * ip_port,char * data, int data_len); int server_on_raw_recv_handshake1(conn_info_t &conn_info,char * ip_port,char * data, int data_len);
void process_arg(int argc, char *argv[]);
int find_lower_level_info(u32_t ip,u32_t &dest_ip,string &if_name,string &hw);
int DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD; int DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD;
////////////////=======================declear divider============================= ////////////////=======================declear divider=============================
@@ -966,6 +978,7 @@ int set_timer_server(int epollfd,int &timer_fd)
int get_src_adress(u32_t &ip); int get_src_adress(u32_t &ip);
int client_on_timer(conn_info_t &conn_info) //for client int client_on_timer(conn_info_t &conn_info) //for client
{ {
//keep_iptables_rule();
packet_info_t &send_info=conn_info.raw_info.send_info; packet_info_t &send_info=conn_info.raw_info.send_info;
packet_info_t &recv_info=conn_info.raw_info.recv_info; packet_info_t &recv_info=conn_info.raw_info.recv_info;
raw_info_t &raw_info=conn_info.raw_info; raw_info_t &raw_info=conn_info.raw_info;
@@ -976,6 +989,9 @@ int client_on_timer(conn_info_t &conn_info) //for client
mylog(log_trace,"<client_on_timer,send_info.ts_ack= %u>\n",send_info.ts_ack); mylog(log_trace,"<client_on_timer,send_info.ts_ack= %u>\n",send_info.ts_ack);
if(conn_info.state.client_current_state==client_idle) if(conn_info.state.client_current_state==client_idle)
{ {
fail_time_counter++; fail_time_counter++;
@@ -1202,6 +1218,7 @@ int client_on_timer(conn_info_t &conn_info) //for client
} }
int server_on_timer_multi(conn_info_t &conn_info,char * ip_port) int server_on_timer_multi(conn_info_t &conn_info,char * ip_port)
{ {
//keep_iptables_rule();
mylog(log_trace,"server timer!\n"); mylog(log_trace,"server timer!\n");
raw_info_t &raw_info=conn_info.raw_info; raw_info_t &raw_info=conn_info.raw_info;
@@ -1423,7 +1440,35 @@ int client_on_raw_recv(conn_info_t &conn_info)
} }
return 0; return 0;
} }
int handle_lower_level(raw_info_t &raw_info)
{
packet_info_t &send_info=raw_info.send_info;
packet_info_t &recv_info=raw_info.recv_info;
if(lower_level_manual)
{
memset(&send_info.addr_ll,0,sizeof(send_info.addr_ll));
send_info.addr_ll.sll_family=AF_PACKET;
send_info.addr_ll.sll_ifindex=ifindex;
send_info.addr_ll.sll_halen=ETHER_ADDR_LEN;
send_info.addr_ll.sll_protocol=htons(ETH_P_IP);
memcpy(&send_info.addr_ll.sll_addr,dest_hw_addr,ETHER_ADDR_LEN);
mylog(log_debug,"[manual]lower level info %x %x\n ",send_info.addr_ll.sll_halen,send_info.addr_ll.sll_protocol);
}
else
{
memset(&send_info.addr_ll,0,sizeof(send_info.addr_ll));
send_info.addr_ll.sll_family=recv_info.addr_ll.sll_family;
send_info.addr_ll.sll_ifindex=recv_info.addr_ll.sll_ifindex;
send_info.addr_ll.sll_protocol=recv_info.addr_ll.sll_protocol;
send_info.addr_ll.sll_halen=recv_info.addr_ll.sll_halen;
memcpy(send_info.addr_ll.sll_addr,recv_info.addr_ll.sll_addr,sizeof(send_info.addr_ll.sll_addr));
//other bytes should be kept zero.
mylog(log_debug,"[auto]lower level info %x %x\n ",send_info.addr_ll.sll_halen,send_info.addr_ll.sll_protocol);
}
return 0;
}
int server_on_raw_recv_multi() int server_on_raw_recv_multi()
{ {
char dummy_buf[buf_len]; char dummy_buf[buf_len];
@@ -1466,6 +1511,12 @@ int server_on_raw_recv_multi()
send_info.dst_port = recv_info.src_port; send_info.dst_port = recv_info.src_port;
send_info.dst_ip = recv_info.src_ip; send_info.dst_ip = recv_info.src_ip;
if(lower_level)
{
handle_lower_level(raw_info);
}
if(data_len==0&&raw_info.recv_info.syn==1&&raw_info.recv_info.ack==0) if(data_len==0&&raw_info.recv_info.syn==1&&raw_info.recv_info.ack==0)
{ {
send_info.ack_seq = recv_info.seq + 1; send_info.ack_seq = recv_info.seq + 1;
@@ -1530,6 +1581,11 @@ int server_on_raw_recv_multi()
send_info.dst_port = recv_info.src_port; send_info.dst_port = recv_info.src_port;
send_info.dst_ip = recv_info.src_ip; send_info.dst_ip = recv_info.src_ip;
if(lower_level)
{
handle_lower_level(raw_info);
}
//id_t tmp_oppsite_id= ntohl(* ((u32_t *)&data[0])); //id_t tmp_oppsite_id= ntohl(* ((u32_t *)&data[0]));
//mylog(log_info,"[%s]handshake1 received %x\n",ip_port,tmp_oppsite_id); //mylog(log_info,"[%s]handshake1 received %x\n",ip_port,tmp_oppsite_id);
@@ -1917,6 +1973,8 @@ int get_src_adress(u32_t &ip)
int client_event_loop() int client_event_loop()
{ {
char buf[buf_len]; char buf[buf_len];
conn_info_t conn_info; conn_info_t conn_info;
@@ -1926,6 +1984,60 @@ int client_event_loop()
packet_info_t &send_info=conn_info.raw_info.send_info; packet_info_t &send_info=conn_info.raw_info.send_info;
packet_info_t &recv_info=conn_info.raw_info.recv_info; packet_info_t &recv_info=conn_info.raw_info.recv_info;
if(lower_level)
{
if(lower_level_manual)
{
int index;
init_ifindex(if_name,index);
//init_ifindex(if_name);
memset(&send_info.addr_ll, 0, sizeof(send_info.addr_ll));
send_info.addr_ll.sll_family = AF_PACKET;
send_info.addr_ll.sll_ifindex =index;
send_info.addr_ll.sll_halen = ETHER_ADDR_LEN;
send_info.addr_ll.sll_protocol = htons(ETH_P_IP);
memcpy(&send_info.addr_ll.sll_addr, dest_hw_addr, ETHER_ADDR_LEN);
mylog(log_info,"we are running at lower-level (manual) mode\n");
}
else
{
u32_t dest_ip;
string if_name_string;
string hw_string;
if(find_lower_level_info(remote_ip_uint32,dest_ip,if_name_string,hw_string)!=0)
{
mylog(log_fatal,"auto detect lower-level info failed for %s,specific it manually\n",remote_ip);
myexit(-1);
}
mylog(log_info,"we are running at lower-level (auto) mode,%s %s %s\n",my_ntoa(dest_ip),if_name_string.c_str(),hw_string.c_str());
u32_t hw[6];
memset(hw, 0, sizeof(hw));
sscanf(hw_string.c_str(), "%x:%x:%x:%x:%x:%x",&hw[0], &hw[1], &hw[2],
&hw[3], &hw[4], &hw[5]);
mylog(log_warn,
"make sure this is correct: if_name=<%s> dest_mac_adress=<%02x:%02x:%02x:%02x:%02x:%02x> \n",
if_name_string.c_str(), hw[0], hw[1], hw[2], hw[3], hw[4], hw[5]);
for (int i = 0; i < 6; i++) {
dest_hw_addr[i] = uint8_t(hw[i]);
}
//mylog(log_fatal,"--lower-level auto for client hasnt been implemented\n");
int index;
init_ifindex(if_name_string.c_str(),index);
memset(&send_info.addr_ll, 0, sizeof(send_info.addr_ll));
send_info.addr_ll.sll_family = AF_PACKET;
send_info.addr_ll.sll_ifindex = index;
send_info.addr_ll.sll_halen = ETHER_ADDR_LEN;
send_info.addr_ll.sll_protocol = htons(ETH_P_IP);
memcpy(&send_info.addr_ll.sll_addr, dest_hw_addr, ETHER_ADDR_LEN);
//mylog(log_info,"we are running at lower-level (manual) mode\n");
}
}
//printf("?????\n"); //printf("?????\n");
if(source_ip_uint32==0) if(source_ip_uint32==0)
{ {
@@ -1951,7 +2063,7 @@ int client_event_loop()
send_info.src_ip = source_ip_uint32; send_info.src_ip = source_ip_uint32;
int i, j, k;int ret; int i, j, k;int ret;
init_raw_socket();
//init_filter(source_port); //init_filter(source_port);
send_info.dst_ip=remote_ip_uint32; send_info.dst_ip=remote_ip_uint32;
@@ -2143,6 +2255,19 @@ int server_event_loop()
bind_address_uint32=local_ip_uint32;//only server has bind adress,client sets it to zero bind_address_uint32=local_ip_uint32;//only server has bind adress,client sets it to zero
if(lower_level)
{
if(lower_level_manual)
{
init_ifindex(if_name,ifindex);
mylog(log_info,"we are running at lower-level (manual) mode\n");
}
else
{
mylog(log_info,"we are running at lower-level (auto) mode\n");
}
}
if(raw_mode==mode_faketcp) if(raw_mode==mode_faketcp)
{ {
@@ -2178,7 +2303,7 @@ int server_event_loop()
init_raw_socket(); //init_raw_socket();
init_filter(local_port);//bpf filter init_filter(local_port);//bpf filter
epollfd = epoll_create1(0); epollfd = epoll_create1(0);
@@ -2205,6 +2330,7 @@ int server_event_loop()
u64_t begin_time=0; u64_t begin_time=0;
u64_t end_time=0; u64_t end_time=0;
mylog(log_info,"now listening at %s:%d\n",my_ntoa(local_ip_uint32),local_port);
while(1)//////////////////////// while(1)////////////////////////
{ {
@@ -2370,8 +2496,16 @@ int server_event_loop()
} }
return 0; return 0;
} }
void process_lower_level() //char lower_level_arg[1000];
int process_lower_level_arg()
{ {
lower_level=1;
if(strcmp(optarg,"auto")==0)
{
return 0;
}
lower_level_manual=1;
if (strchr(optarg, '#') == 0) { if (strchr(optarg, '#') == 0) {
mylog(log_fatal, mylog(log_fatal,
"lower-level parameter invaild,check help page for format\n"); "lower-level parameter invaild,check help page for format\n");
@@ -2389,6 +2523,7 @@ void process_lower_level()
for (int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
dest_hw_addr[i] = uint8_t(hw[i]); dest_hw_addr[i] = uint8_t(hw[i]);
} }
return 0;
} }
void print_help() void print_help()
{ {
@@ -2406,7 +2541,8 @@ void print_help()
printf(" --cipher-mode <string> avaliable values:aes128cbc(default),xor,none\n"); printf(" --cipher-mode <string> avaliable values:aes128cbc(default),xor,none\n");
printf(" --auth-mode <string> avaliable values:md5(default),crc32,simple,none\n"); printf(" --auth-mode <string> avaliable values: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\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(" --disable-anti-replay disable anti-replay,not suggested\n"); printf(" --disable-anti-replay disable anti-replay,not suggested\n");
//printf("\n"); //printf("\n");
@@ -2416,6 +2552,7 @@ void print_help()
printf(" this option disables port changing while re-connecting\n"); printf(" this option disables port changing while re-connecting\n");
// printf(" \n"); // printf(" \n");
printf("other options:\n"); printf("other options:\n");
printf(" --conf-file <string> read options from a configuration file instead of command line\n");
printf(" --log-level <number> 0:never 1:fatal 2:error 3:warn \n"); printf(" --log-level <number> 0:never 1:fatal 2:error 3:warn \n");
printf(" 4:info (default) 5:debug 6:trace\n"); printf(" 4:info (default) 5:debug 6:trace\n");
// printf("\n"); // printf("\n");
@@ -2427,57 +2564,65 @@ void print_help()
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(" --seqmode <number> seq increase mode for faketcp:\n"); printf(" --seqmode <number> seq increase mode for faketcp:\n");
printf(" 0:dont increase\n"); printf(" 0:dont increase\n");
printf(" 1:increase every packet\n"); printf(" 1:increase every packet(default)\n");
printf(" 2:increase randomly, about every 3 packets (default)\n"); printf(" 2:increase randomly, about every 3 packets\n");
// printf("\n"); // printf("\n");
printf(" --lower-level <string> send packet at OSI level 2, format:'if_name#dest_mac_adress'\n"); printf(" --lower-level <string> send packet at OSI level 2, format:'if_name#dest_mac_adress'\n");
printf(" ie:'eth0#00:23:45:67:89:b9'.Beta.\n"); printf(" ie:'eth0#00:23:45:67:89:b9'.Beta.\n");
printf(" --gen-add generate iptables rule and add it for you,then exit.overrides -g\n");
printf(" --keep_rule monitor iptables and auto re-add if necessary.Implys -a\n");
printf(" --clear clear any iptables rules added by this program.overrides everything\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");
} }
void process_arg(int argc, char *argv[])
{
int i,j,k,opt;
static struct option long_options[] =
{
/* These options set a flag. */
{"source-ip", required_argument, 0, 1},
{"source-port", required_argument, 0, 1},
{"log-level", required_argument, 0, 1},
{"key", required_argument, 0, 'k'},
{"auth-mode", required_argument, 0, 1},
{"cipher-mode", required_argument, 0, 1},
{"raw-mode", required_argument, 0, 1},
{"disable-color", no_argument, 0, 1},
{"log-position", no_argument, 0, 1},
{"disable-bpf", no_argument, 0, 1},
{"disable-anti-replay", no_argument, 0, 1},
{"auto-rule", no_argument, 0, 'a'},
{"gen-rule", no_argument, 0, 'g'},
{"debug", no_argument, 0, 1},
{"clear", no_argument, 0, 1},
{"lower-level", required_argument, 0, 1},
{"sock-buf", required_argument, 0, 1},
{"seq-mode", required_argument, 0, 1},
{NULL, 0, 0, 0}
};
int option_index = 0; int load_config(char *file_name, int &argc, vector<string> &argv)
for (i = 0; i < argc; i++) {
// Load configurations from config_file instead of the command line.
// See config.example for example configurations
std::ifstream conf_file(file_name);
std::string line;
if(conf_file.fail())
{ {
if(strcmp(argv[i],"-h")==0||strcmp(argv[i],"--help")==0) mylog(log_fatal,"conf_file %s open failed,reason :%s\n",file_name,strerror(errno));
{
print_help();
myexit(0);
}
}
if (argc == 1)
{
print_help();
myexit(-1); myexit(-1);
} }
while(std::getline(conf_file,line))
{
auto res=parse_conf_line(line);
argc+=res.size();
for(int i=0;i<(int)res.size();i++)
{
argv.push_back(res[i]);
}
}
conf_file.close();
return 0;
}
int unit_test()
{
printf("running unit test\n");
vector<string> conf_lines= {"---aaa","--aaa bbb","-a bbb"," \t \t \t-a\t \t \t bbbbb\t \t \t "};
for(int i=0;i<int(conf_lines.size());i++)
{
printf("orign:%s\n",conf_lines[i].c_str());
auto res=parse_conf_line(conf_lines[i]);
printf("pasrse_result: size %d",int(res.size()));
for(int j=0;j<int(res.size());j++)
{
printf("<%s>",res[j].c_str());
}
printf("\n");
}
return 0;
}
int process_log_level(int argc,char *argv[])
{
int i,j,k;
for (i = 0; i < argc; i++) for (i = 0; i < argc; i++)
{ {
if(strcmp(argv[i],"--log-level")==0) if(strcmp(argv[i],"--log-level")==0)
@@ -2499,6 +2644,94 @@ void process_arg(int argc, char *argv[])
{ {
enable_log_color=0; enable_log_color=0;
} }
if(strcmp(argv[i],"--log-position")==0)
{
enable_log_position=1;
}
}
return 0;
}
void process_arg(int argc, char *argv[])
{
int i,j,k,opt;
int option_index = 0;
char options[]="l:r:schk:ag";
static struct option long_options[] =
{
/* These options set a flag. */
{"source-ip", required_argument, 0, 1},
{"source-port", required_argument, 0, 1},
{"log-level", required_argument, 0, 1},
{"key", required_argument, 0, 'k'},
{"auth-mode", required_argument, 0, 1},
{"cipher-mode", required_argument, 0, 1},
{"raw-mode", required_argument, 0, 1},
{"disable-color", no_argument, 0, 1},
{"log-position", no_argument, 0, 1},
{"disable-bpf", no_argument, 0, 1},
{"disable-anti-replay", no_argument, 0, 1},
{"auto-rule", no_argument, 0, 'a'},
{"gen-rule", no_argument, 0, 'g'},
{"gen-add", no_argument, 0, 1},
{"debug", no_argument, 0, 1},
{"clear", no_argument, 0, 1},
{"simple-rule", no_argument, 0, 1},
{"keep-rule", no_argument, 0, 1},
{"lower-level", required_argument, 0, 1},
{"sock-buf", required_argument, 0, 1},
{"seq-mode", required_argument, 0, 1},
{"conf-file", required_argument, 0, 1},
{NULL, 0, 0, 0}
};
process_log_level(argc,argv);
set<string> all_options;
map<string,string> shortcut_map;
all_options.insert("--help");
all_options.insert("-h");
string dummy="";
for(i=0;i<(int)strlen(options);i++)
{
char val=options[i];
if( ( val>='0'&&val<='9') ||( val>='a'&&val<='z')||(val>='A'&&val<='Z'))
{
all_options.insert(dummy+'-'+val);
}
}
for(i=0;i<int( sizeof(long_options)/sizeof(long_options[0]) );i++)
{
if(long_options[i].name==NULL) break;
int val=long_options[i].val;
if( ( val>='0'&&val<='9') ||( val>='a'&&val<='z')||(val>='A'&&val<='Z'))
{
shortcut_map[dummy+"--"+long_options[i].name]= dummy+"-"+ char(val);
}
all_options.insert(dummy+"--"+long_options[i].name);
}
for (i = 0; i < argc; i++)
{
int len=strlen(argv[i]);
if(len==0)
{
mylog(log_fatal,"found an empty string in options\n");
myexit(-1);
}
if(len==1&&argv[i][0]=='-' )
{
mylog(log_fatal,"invaild option '-' in argv\n");
myexit(-1);
}
if(len==2&&argv[i][0]=='-'&&argv[i][1]=='-' )
{
mylog(log_fatal,"invaild option '--' in argv\n");
myexit(-1);
}
} }
mylog(log_info,"argc=%d ", argc); mylog(log_info,"argc=%d ", argc);
@@ -2508,10 +2741,46 @@ void process_arg(int argc, char *argv[])
} }
log_bare(log_info, "\n"); log_bare(log_info, "\n");
//string dummy="";
for(i=+1;i<argc;i++)
{
if(argv[i][0]!='-') continue;
string a=argv[i];
if(a[0]=='-'&&a[1]!='-')
a=dummy+a[0]+a[1];
if(all_options.find(a.c_str())==all_options.end())
{
mylog(log_fatal,"invaild option %s\n",a.c_str());
myexit(-1);
}
for(j=i+1;j<argc;j++)
{
if(argv[j][0]!='-') continue;
string b=argv[j];
if(b[0]=='-'&&b[1]!='-')
b=dummy+b[0]+b[1];
if(shortcut_map.find(a)!=shortcut_map.end())
a=shortcut_map[a];
if(shortcut_map.find(b)!=shortcut_map.end())
b=shortcut_map[b];
if(a==b)
{
mylog(log_fatal,"%s duplicates with %s\n",argv[i],argv[j]);
myexit(-1);
}
}
}
int no_l = 1, no_r = 1; int no_l = 1, no_r = 1;
while ((opt = getopt_long(argc, argv, "l:r:schk:ag",long_options,&option_index)) != -1) { while ((opt = getopt_long(argc, argv,options,long_options,&option_index)) != -1) {
//string opt_key; //string opt_key;
//opt_key+=opt; //opt_key+=opt;
switch (opt) { switch (opt) {
@@ -2584,11 +2853,12 @@ void process_arg(int argc, char *argv[])
{ {
char *output; char *output;
//int ret =system("iptables-save |grep udp2raw_dWRwMnJhdw|sed -n 's/^-A/iptables -D/p'|sh"); //int ret =system("iptables-save |grep udp2raw_dWRwMnJhdw|sed -n 's/^-A/iptables -D/p'|sh");
int ret =run_command("iptables -S|sed -n '/udp2raw_dWRwMnJhdw/p'|sed -n 's/^-A/iptables -D/p'|sh",output); 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 udp2raw_dWRwMnJhdw|sed 's/^-A/iptables -D/'|sh");
//system("iptables-save|grep -v udp2raw_dWRwMnJhdw|iptables-restore"); //system("iptables-save|grep -v udp2raw_dWRwMnJhdw|iptables-restore");
mylog(log_info,"tried to clear all iptables rule created previously,return value %d\n",ret); mylog(log_info,"tried to clear all iptables rule created previously,return value %d %d\n",ret,ret2);
myexit(-1); myexit(-1);
} }
else if(strcmp(long_options[option_index].name,"source-ip")==0) else if(strcmp(long_options[option_index].name,"source-ip")==0)
@@ -2629,6 +2899,10 @@ void process_arg(int argc, char *argv[])
if(strcmp(optarg,auth_mode_tostring[i])==0) if(strcmp(optarg,auth_mode_tostring[i])==0)
{ {
auth_mode=(auth_mode_t)i; auth_mode=(auth_mode_t)i;
if(auth_mode==auth_none)
{
disable_anti_replay=1;
}
break; break;
} }
} }
@@ -2659,7 +2933,21 @@ void process_arg(int argc, char *argv[])
} }
else if(strcmp(long_options[option_index].name,"lower-level")==0) else if(strcmp(long_options[option_index].name,"lower-level")==0)
{ {
process_lower_level(); process_lower_level_arg();
//lower_level=1;
//strcpy(lower_level_arg,optarg);
}
else if(strcmp(long_options[option_index].name,"simple-rule")==0)
{
simple_rule=1;
}
else if(strcmp(long_options[option_index].name,"keep-rule")==0)
{
keep_rule=1;
}
else if(strcmp(long_options[option_index].name,"gen-add")==0)
{
generate_iptables_rule_add=1;
} }
else if(strcmp(long_options[option_index].name,"disable-color")==0) else if(strcmp(long_options[option_index].name,"disable-color")==0)
{ {
@@ -2677,7 +2965,7 @@ void process_arg(int argc, char *argv[])
} }
else if(strcmp(long_options[option_index].name,"log-position")==0) else if(strcmp(long_options[option_index].name,"log-position")==0)
{ {
enable_log_position=1; //enable_log_position=1;
} }
else if(strcmp(long_options[option_index].name,"disable-bpf")==0) else if(strcmp(long_options[option_index].name,"disable-bpf")==0)
{ {
@@ -2713,6 +3001,10 @@ void process_arg(int argc, char *argv[])
myexit(-1); myexit(-1);
} }
} }
else if(strcmp(long_options[option_index].name,"conf-file")==0)
{
mylog(log_info,"configuration loaded from %s\n",optarg);
}
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);
@@ -2735,6 +3027,8 @@ void process_arg(int argc, char *argv[])
print_help(); print_help();
myexit(-1); myexit(-1);
} }
//if(lower_level)
//process_lower_level_arg();
mylog(log_info,"important variables: "); mylog(log_info,"important variables: ");
@@ -2756,68 +3050,184 @@ void process_arg(int argc, char *argv[])
log_bare(log_info,"\n"); log_bare(log_info,"\n");
} }
void pre_process_arg(int argc, char *argv[])
{
int i,j,k;
for (i = 0; i < argc; i++)
{
if(strcmp(argv[i],"--unit-test")==0)
{
unit_test();
myexit(0);
}
}
for (i = 0; i < argc; i++)
{
if(strcmp(argv[i],"-h")==0||strcmp(argv[i],"--help")==0)
{
print_help();
myexit(0);
}
}
if (argc == 1)
{
print_help();
myexit(-1);
}
process_log_level(argc,argv);
int new_argc=0;
vector<string> new_argv;
int count=0;
int pos=-1;
for (i = 0; i < argc; i++)
{
if(strcmp(argv[i],"--conf-file")==0)
{
count++;
pos=i;
if(i==argc)
{
mylog(log_fatal,"--conf-file need a parameter\n");
myexit(-1);
}
if(argv[i+1][0]=='-')
{
mylog(log_fatal,"--conf-file need a parameter\n");
myexit(-1);
}
i++;
}
else
{
//printf("<%s>",argv[i]);
new_argc++;
new_argv.push_back(argv[i]);
}
}
if(count>1)
{
mylog(log_fatal,"duplicated --conf-file option\n");
myexit(-1);
}
if(count>0)
{
load_config(argv[pos+1],new_argc,new_argv);
}
char* new_argv_char[new_argv.size()];
new_argc=0;
for(i=0;i<(int)new_argv.size();i++)
{
if(strcmp(new_argv[i].c_str(),"--conf-file")==0)
{
mylog(log_fatal,"cant have --conf-file in a config file\n");
myexit(-1);
}
new_argv_char[new_argc++]=(char *)new_argv[i].c_str();
}
process_arg(new_argc,new_argv_char);
}
void *run_keep(void *none)
{
while(1)
{
sleep(10);
keep_iptables_rule();
if(about_to_exit) //just incase it runs forever if there is some bug,not necessary
{
sleep(10);
keep_thread_running=0; //not thread safe ,but wont cause problem
break;
}
}
return NULL;
}
void iptables_rule() void iptables_rule()
{ {
char rule[200]; if(auto_add_iptables_rule&&generate_iptables_rule)
{
mylog(log_warn," -g overrides -a\n");
auto_add_iptables_rule=0;
//myexit(-1);
}
if(generate_iptables_rule_add&&generate_iptables_rule)
{
mylog(log_warn," --gen-add overrides -g\n");
generate_iptables_rule=0;
//myexit(-1);
}
if(keep_rule&&auto_add_iptables_rule==0)
{
auto_add_iptables_rule=1;
mylog(log_warn," --keep_rule implys -a\n");
generate_iptables_rule=0;
//myexit(-1);
}
char tmp_pattern[200];
string pattern="";
if(program_mode==client_mode) if(program_mode==client_mode)
{ {
if(raw_mode==mode_faketcp) if(raw_mode==mode_faketcp)
{ {
sprintf(rule,"INPUT -s %s/32 -p tcp -m tcp --sport %d -j DROP",remote_ip,remote_port); sprintf(tmp_pattern,"-s %s/32 -p tcp -m tcp --sport %d",remote_ip,remote_port);
//mylog(log_warn,"make sure you have run once: iptables -A INPUT -s %s/32 -p tcp -m tcp --sport %d -j DROP\n",remote_address,remote_port);
} }
if(raw_mode==mode_udp) if(raw_mode==mode_udp)
{ {
sprintf(rule,"INPUT -s %s/32 -p udp -m udp --sport %d -j DROP",remote_ip,remote_port); sprintf(tmp_pattern,"-s %s/32 -p udp -m udp --sport %d",remote_ip,remote_port);
//mylog(log_warn,"make sure you have run once: iptables -A INPUT -s %s/32 -p udp -m udp --sport %d -j DROP\n",remote_address,remote_port);
} }
if(raw_mode==mode_icmp) if(raw_mode==mode_icmp)
{ {
sprintf(rule,"INPUT -s %s/32 -p icmp -j DROP",remote_ip); sprintf(tmp_pattern,"-s %s/32 -p icmp",remote_ip);
//mylog(log_warn,"make sure you have run once: iptables -A INPUT -s %s/32 -p icmp -j DROP\n",remote_address);
} }
pattern=tmp_pattern;
} }
if(program_mode==server_mode) if(program_mode==server_mode)
{ {
if(raw_mode==mode_faketcp) if(raw_mode==mode_faketcp)
{ {
sprintf(rule,"INPUT -p tcp -m tcp --dport %d -j DROP",local_port); sprintf(tmp_pattern,"-p tcp -m tcp --dport %d",local_port);
//mylog(log_warn,"make sure you have run once: iptables -A INPUT -p tcp -m tcp --dport %d -j DROP\n",local_port);
} }
if(raw_mode==mode_udp) if(raw_mode==mode_udp)
{ {
sprintf(rule,"INPUT -p udp -m udp --dport %d -j DROP",local_port); sprintf(tmp_pattern,"-p udp -m udp --dport %d",local_port);
//mylog(log_warn,"make sure you have run once: iptables -A INPUT -p udp -m udp --udp %d -j DROP\n",local_port);
} }
if(raw_mode==mode_icmp) if(raw_mode==mode_icmp)
{ {
if(local_ip_uint32==0) if(local_ip_uint32==0)
{ {
sprintf(rule,"INPUT -p icmp -j DROP"); sprintf(tmp_pattern,"-p icmp");
//mylog(log_warn,"make sure you have run once: iptables -A INPUT -p icmp -j DROP\n");
} }
else else
{ {
sprintf(rule,"INPUT -d %s/32 -p icmp -j DROP",local_ip); sprintf(tmp_pattern,"-d %s/32 -p icmp",local_ip);
//mylog(log_warn,"make sure you have run once: iptables -A INPUT -d %s/32 -p icmp -j DROP\n",local_address);
} }
} }
pattern=tmp_pattern;
} }
if(generate_iptables_rule) /*
if(!simple_rule)
{ {
printf("generated iptables rule:\n"); pattern += " -m comment --comment udp2rawDwrW_";
printf("iptables -I %s\n",rule);
myexit(-1);
}
else if(auto_add_iptables_rule)
{
strcat(rule," -m comment --comment udp2raw_dWRwMnJhdw_");
char const_id_str[100]; char const_id_str[100];
sprintf(const_id_str,"%x_",const_id); sprintf(const_id_str, "%x_", const_id);
strcat(rule,const_id_str); pattern += const_id_str;
time_t timer; time_t timer;
char buffer[26]; char buffer[26];
@@ -2828,16 +3238,61 @@ void iptables_rule()
strftime(buffer, 26, "%Y-%m-%d-%H:%M:%S", tm_info); strftime(buffer, 26, "%Y-%m-%d-%H:%M:%S", tm_info);
strcat(rule,buffer); pattern += buffer;
add_iptables_rule(rule);
}
else }*/
if(auto_add_iptables_rule)
{ {
mylog(log_warn,"make sure you have run once: iptables -I %s\n",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)
{
string rule="iptables -I ";
rule+=pattern;
rule+=" -j DROP";
printf("generated iptables rule:\n");
printf("%s\n",rule.c_str());
myexit(0);
}
if(generate_iptables_rule_add)
{
iptables_gen_add(pattern.c_str(),const_id);
myexit(0);
}
} }
/*
int test()
{
char ip_str[100]="8.8.8.8";
u32_t ip=inet_addr(ip_str);
u32_t dest_ip;
string if_name;
string hw;
find_lower_level_info(ip,dest_ip,if_name,hw);
printf("%s %s %s\n",my_ntoa(dest_ip),if_name.c_str(),hw.c_str());
exit(0);
return 0;
}*/
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
//test();
printf("%s\n",my_ntoa(0x00ffffff));
//auto a=string_to_vec("a b c d "); //auto a=string_to_vec("a b c d ");
//printf("%d\n",(int)a.size()); //printf("%d\n",(int)a.size());
//printf("%d %d %d %d",larger_than_u32(1,2),larger_than_u32(2,1),larger_than_u32(0xeeaaeebb,2),larger_than_u32(2,0xeeaaeebb)); //printf("%d %d %d %d",larger_than_u32(1,2),larger_than_u32(2,1),larger_than_u32(0xeeaaeebb,2),larger_than_u32(2,0xeeaaeebb));
@@ -2849,7 +3304,7 @@ int main(int argc, char *argv[])
signal(SIGTERM, signal_handler); signal(SIGTERM, signal_handler);
signal(SIGQUIT, signal_handler); signal(SIGQUIT, signal_handler);
process_arg(argc,argv); pre_process_arg(argc,argv);
if(geteuid() != 0) if(geteuid() != 0)
{ {
@@ -2887,6 +3342,8 @@ int main(int argc, char *argv[])
md5((uint8_t*)tmp,strlen(tmp),(uint8_t*)key2);*/ md5((uint8_t*)tmp,strlen(tmp),(uint8_t*)key2);*/
iptables_rule(); iptables_rule();
init_raw_socket();
if(program_mode==client_mode) if(program_mode==client_mode)
{ {
client_event_loop(); client_event_loop();

View File

@@ -1,43 +1,51 @@
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_ar71xx=/home/wangyu/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_bcm2708=/home/wangyu/raspberry/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-g++ cc_arm= /toolchains/arm-2014.05/bin/arm-none-linux-gnueabi-g++
cc_arm=/home/wangyu/Desktop/arm-2014.05/bin/arm-none-linux-gnueabi-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
SOURCES=main.cpp lib/aes.c lib/md5.c encrypt.cpp log.cpp network.cpp common.cpp SOURCES=main.cpp lib/aes.c lib/md5.c encrypt.cpp log.cpp network.cpp common.cpp -lpthread
SOURCES_AES_ACC=main.cpp $(wildcard lib/aes_acc/aes*.c) lib/md5.c encrypt.cpp log.cpp network.cpp common.cpp SOURCES_AES_ACC=$(filter-out lib/aes.c,$(SOURCES)) $(wildcard lib/aes_acc/aes*.c)
NAME=udp2raw NAME=udp2raw
TAR=${NAME}_binaries.tar.gz ${NAME}_amd64 ${NAME}_x86 ${NAME}_ar71xx ${NAME}_bcm2708 ${NAME}_arm ${NAME}_amd64_hw_aes TARGETS=amd64 mips34kc arm amd64_hw_aes arm_asm_aes mips34kc_asm_aes x86 x86_asm_aes
TAR=${NAME}_binaries.tar.gz `echo ${TARGETS}|sed -r 's/([^ ]+)/udp2raw_\1/g'`
all: all:
rm -f ${NAME} rm -f ${NAME}
${cc_local} -o ${NAME} -I. ${SOURCES} ${FLAGS} -lrt -static -O3 ${cc_local} -o ${NAME} -I. ${SOURCES} ${FLAGS} -lrt -ggdb -static -O3
fast: fast:
rm -f ${NAME} rm -f ${NAME}
${cc_local} -o ${NAME} -I. ${SOURCES} ${FLAGS} -lrt ${cc_local} -o ${NAME} -I. ${SOURCES} ${FLAGS} -lrt -ggdb
debug: debug:
rm -f ${NAME} rm -f ${NAME}
${cc_local} -o ${NAME} -I. ${SOURCES} ${FLAGS} -lrt -Wformat-nonliteral -D MY_DEBUG ${cc_local} -o ${NAME} -I. ${SOURCES} ${FLAGS} -lrt -Wformat-nonliteral -D MY_DEBUG
debug2:
rm -f ${NAME}
${cc_local} -o ${NAME} -I. ${SOURCES} ${FLAGS} -lrt -Wformat-nonliteral -ggdb
ar71xx: mips34kc:
${cc_ar71xx} -o ${NAME}_ar71xx -I. ${SOURCES} ${FLAGS} -lrt -lgcc_eh -static -O3 ${cc_mips34kc} -o ${NAME}_$@ -I. ${SOURCES} ${FLAGS} -lrt -lgcc_eh -static -O3
bcm2708:
${cc_bcm2708} -o ${NAME}_bcm2708 -I. ${SOURCES} ${FLAGS} -lrt -static -O3 mips34kc_asm_aes:
${cc_mips34kc} -o ${NAME}_$@ -I. ${SOURCES_AES_ACC} ${FLAGS} -lrt -lgcc_eh -static -O3 lib/aes_acc/asm/mips_be.S
#bcm2708:
# ${cc_bcm2708} -o ${NAME}_bcm2708 -I. ${SOURCES} ${FLAGS} -lrt -static -O3
amd64: amd64:
${cc_local} -o ${NAME}_amd64 -I. ${SOURCES} ${FLAGS} -lrt -static -O3 ${cc_local} -o ${NAME}_$@ -I. ${SOURCES} ${FLAGS} -lrt -static -O3
amd64_hw_aes: amd64_hw_aes:
${cc_local} -o ${NAME}_amd64_hw_aes -I. ${SOURCES_AES_ACC} ${FLAGS} -lrt -static -O3 ${cc_local} -o ${NAME}_$@ -I. ${SOURCES_AES_ACC} ${FLAGS} -lrt -static -O3 lib/aes_acc/asm/x64.S
x86: x86:
${cc_local} -o ${NAME}_x86 -I. ${SOURCES} ${FLAGS} -lrt -static -O3 -m32 ${cc_local} -o ${NAME}_$@ -I. ${SOURCES} ${FLAGS} -lrt -static -O3 -m32
x86_asm_aes: x86_asm_aes:
${cc_local} -o ${NAME}_x86_asm_aes -I. ${SOURCES_AES_ACC} ${FLAGS} -lrt -static -O3 -m32 -DHAVE_ASM lib/aes_acc/asm/x86.S ${cc_local} -o ${NAME}_$@ -I. ${SOURCES_AES_ACC} ${FLAGS} -lrt -static -O3 -m32 lib/aes_acc/asm/x86.S
arm: arm:
${cc_cross} -o ${NAME}_arm -I. ${SOURCES} ${FLAGS} -lrt -static -O3 ${cc_arm} -o ${NAME}_$@ -I. ${SOURCES} ${FLAGS} -lrt -static -O3
arm_asm_aes: arm_asm_aes:
${cc_cross} -o ${NAME}_arm_asm_aes -I. ${SOURCES_AES_ACC} ${FLAGS} -lrt -static -O3 -DHAVE_ASM lib/aes_acc/asm/arm.S ${cc_arm} -o ${NAME}_$@ -I. ${SOURCES_AES_ACC} ${FLAGS} -lrt -static -O3 lib/aes_acc/asm/arm.S
cross: cross:
${cc_cross} -o ${NAME}_cross -I. ${SOURCES} ${FLAGS} -lrt -O3 ${cc_cross} -o ${NAME}_cross -I. ${SOURCES} ${FLAGS} -lrt -O3
@@ -48,10 +56,10 @@ cross2:
cross3: cross3:
${cc_cross} -o ${NAME}_cross -I. ${SOURCES} ${FLAGS} -lrt -static -O3 ${cc_cross} -o ${NAME}_cross -I. ${SOURCES} ${FLAGS} -lrt -static -O3
release: amd64 x86 ar71xx bcm2708 arm amd64_hw_aes release: ${TARGETS}
tar -zcvf ${TAR} tar -zcvf ${TAR}
clean: clean:
rm -f ${TAR} rm -f ${TAR}
rm -f udp2raw udp2raw_cross rm -f udp2raw udp2raw_cross udp2raw_cmake

View File

@@ -12,7 +12,7 @@ int raw_recv_fd=-1;
int raw_send_fd=-1; int raw_send_fd=-1;
u32_t link_level_header_len=0;//set it to 14 if SOCK_RAW is used in socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP)); u32_t link_level_header_len=0;//set it to 14 if SOCK_RAW is used in socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP));
int seq_mode=2; int seq_mode=1;
int filter_port=-1; int filter_port=-1;
@@ -21,13 +21,14 @@ int disable_bpf_filter=0; //for test only,most time no need to disable this
u32_t bind_address_uint32=0; u32_t bind_address_uint32=0;
int lower_level=0; int lower_level=0;
int lower_level_manual=0;
int ifindex=-1; int ifindex=-1;
char if_name[100]=""; char if_name[100]="";
unsigned short g_ip_id_counter=0; unsigned short g_ip_id_counter=0;
unsigned char dest_hw_addr[6]= unsigned char dest_hw_addr[sizeof(sockaddr_ll::sll_addr)]=
{0xff,0xff,0xff,0xff,0xff,0xff}; {0xff,0xff,0xff,0xff,0xff,0xff,0,0};
//{0x00,0x23,0x45,0x67,0x89,0xb9}; //{0x00,0x23,0x45,0x67,0x89,0xb9};
struct sock_filter code_tcp_old[] = { struct sock_filter code_tcp_old[] = {
@@ -194,7 +195,7 @@ int init_raw_socket()
//perror("Failed to create raw_send_fd"); //perror("Failed to create raw_send_fd");
myexit(1); myexit(1);
} }
init_ifindex(if_name); //init_ifindex(if_name);
} }
@@ -288,7 +289,7 @@ void remove_filter()
//exit(-1); //exit(-1);
} }
} }
int init_ifindex(char * if_name) int init_ifindex(const char * if_name,int &index)
{ {
struct ifreq ifr; struct ifreq ifr;
size_t if_name_len=strlen(if_name); size_t if_name_len=strlen(if_name);
@@ -304,10 +305,230 @@ int init_ifindex(char * if_name)
mylog(log_fatal,"SIOCGIFINDEX fail ,%s\n",strerror(errno)); mylog(log_fatal,"SIOCGIFINDEX fail ,%s\n",strerror(errno));
myexit(-1); myexit(-1);
} }
ifindex=ifr.ifr_ifindex; index=ifr.ifr_ifindex;
mylog(log_info,"ifname:%s ifindex:%d\n",if_name,ifindex); mylog(log_info,"ifname:%s ifindex:%d\n",if_name,index);
return 0; return 0;
} }
bool interface_has_arp(const char * interface) {
struct ifreq ifr;
// int sock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP);
int sock=raw_send_fd;
memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, interface);
if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
//perror("SIOCGIFFLAGS");
mylog(log_fatal,"ioctl(sock, SIOCGIFFLAGS, &ifr) failed for interface %s,errno %s\n",interface,strerror(errno));
myexit(-1);
}
//close(sock);
return !(ifr.ifr_flags & IFF_NOARP);
}
struct route_info_t
{
string if_name;
u32_t dest;
u32_t mask;
u32_t gw;
u32_t flag;
};
int dest_idx=1;
int gw_idx=2;
int if_idx=0;
int mask_idx=7;
int flag_idx=3;
vector<int> find_route_entry(const vector<route_info_t> &route_info_vec,u32_t ip)
{
vector<int> res;
for(u32_t i=0;i<=32;i++)
{
u32_t mask=0xffffffff;
//mask >>=i;
//if(i==32) mask=0; //why 0xffffffff>>32 equals 0xffffffff??
mask <<=i;
if(i==32) mask=0;
log_bare(log_debug,"(mask:%x)",mask);
for(u32_t j=0;j<route_info_vec.size();j++)
{
const route_info_t & info=route_info_vec[j];
if(info.mask!=mask)
continue;
log_bare(log_debug,"<<%d,%d>>",i,j);
if((info.dest&mask)==(ip&mask))
{
log_bare(log_debug,"found!");
res.push_back(j);
}
}
if(res.size()!=0)
{
return res;
}
}
return res;
}
int find_direct_dest(const vector<route_info_t> &route_info_vec,u32_t ip,u32_t &dest_ip,string &if_name)
{
vector<int> res;
for(int i=0;i<1000;i++)
{
res=find_route_entry(route_info_vec,ip);
log_bare(log_debug,"<entry:%u>",(u32_t)res.size());
if(res.size()==0)
{
mylog(log_error,"cant find route entry\n");
return -1;
}
if(res.size()>1)
{
mylog(log_error,"found duplicated entries\n");
return -1;
}
if((route_info_vec[res[0]].flag&2)==0)
{
dest_ip=ip;
if_name=route_info_vec[res[0]].if_name;
return 0;
}
else
{
ip=route_info_vec[res[0]].gw;
}
}
mylog(log_error,"dead loop in find_direct_dest\n");
return -1;
}
struct arp_info_t
{
u32_t ip;
string hw;
string if_name;
};
int arp_ip_idx=0;
int arp_hw_idx=3;
int arp_if_idx=5;
int find_arp(const vector<arp_info_t> &arp_info_vec,u32_t ip,string if_name,string &hw)
{
int pos=-1;
int count=0;
for(u32_t i=0;i<arp_info_vec.size();i++)
{
const arp_info_t & info=arp_info_vec[i];
if(info.if_name!=if_name) continue;
if(info.ip==ip)
{
count++;
pos=i;
}
}
if(count==0)
{
//mylog(log_warn,"cant find arp entry for %s %s,using 00:00:00:00:00:00\n",my_ntoa(ip),if_name.c_str());
//hw="00:00:00:00:00:00";
mylog(log_error,"cant find arp entry for %s %s\n",my_ntoa(ip),if_name.c_str());
return -1;
}
if(count>1)
{
mylog(log_error,"find multiple arp entry for %s %s\n",my_ntoa(ip),if_name.c_str());
return -1;
}
hw=arp_info_vec[pos].hw;
return 0;
}
int find_lower_level_info(u32_t ip,u32_t &dest_ip,string &if_name,string &hw)
{
ip=htonl(ip);
if(ip==htonl(inet_addr("127.0.0.1")))
{
dest_ip=ntohl(ip);
if_name="lo";
hw="00:00:00:00:00:00";
return 0;
}
string route_file;
if(read_file("/proc/net/route",route_file)!=0) return -1;
string arp_file;
if(read_file("/proc/net/arp",arp_file)!=0) return -1;
log_bare(log_debug,"/proc/net/route:<<%s>>\n",route_file.c_str());
log_bare(log_debug,"/proc/net/arp:<<%s>>\n",route_file.c_str());
auto route_vec2=string_to_vec2(route_file.c_str());
vector<route_info_t> route_info_vec;
for(u32_t i=1;i<route_vec2.size();i++)
{
log_bare(log_debug,"<size:%u>",(u32_t)route_vec2[i].size());
if(route_vec2[i].size()!=11)
{
mylog(log_error,"route coloum %d !=11 \n",int(route_vec2[i].size()));
return -1;
}
route_info_t tmp;
tmp.if_name=route_vec2[i][if_idx];
if(hex_to_u32_with_endian(route_vec2[i][dest_idx],tmp.dest)!=0) return -1;
if(hex_to_u32_with_endian(route_vec2[i][gw_idx],tmp.gw)!=0) return -1;
if(hex_to_u32_with_endian(route_vec2[i][mask_idx],tmp.mask)!=0) return -1;
if(hex_to_u32(route_vec2[i][flag_idx],tmp.flag)!=0)return -1;
route_info_vec.push_back(tmp);
for(u32_t j=0;j<route_vec2[i].size();j++)
{
log_bare(log_debug,"<%s>",route_vec2[i][j].c_str());
}
log_bare(log_debug,"%s dest:%x mask:%x gw:%x flag:%x",tmp.if_name.c_str(),tmp.dest,tmp.mask,tmp.gw,tmp.flag);
log_bare(log_debug,"\n");
}
if(find_direct_dest(route_info_vec,ip,dest_ip,if_name)!=0)
{
mylog(log_error,"find_direct_dest failed for ip %s\n",my_ntoa(ntohl(ip)));
return -1;
}
log_bare(log_debug,"========\n");
auto arp_vec2=string_to_vec2(arp_file.c_str());
vector<arp_info_t> arp_info_vec;
for(u32_t i=1;i<arp_vec2.size();i++)
{
log_bare(log_debug,"<<arp_vec2[i].size(): %d>>",(int)arp_vec2[i].size());
for(u32_t j=0;j<arp_vec2[i].size();j++)
{
log_bare(log_debug,"<%s>",arp_vec2[i][j].c_str());
}
if(arp_vec2[i].size()!=6)
{
mylog(log_error,"arp coloum %d !=11 \n",int(arp_vec2[i].size()));
return -1;
}
arp_info_t tmp;
tmp.if_name=arp_vec2[i][arp_if_idx];
tmp.hw=arp_vec2[i][arp_hw_idx];
tmp.ip=htonl(inet_addr(arp_vec2[i][arp_ip_idx].c_str()));
arp_info_vec.push_back(tmp);
log_bare(log_debug,"\n");
}
if(!interface_has_arp(if_name.c_str()))
{
mylog(log_info,"%s is a noarp interface,using 00:00:00:00:00:00\n",if_name.c_str());
hw="00:00:00:00:00:00";
}
else if(find_arp(arp_info_vec,dest_ip,if_name,hw)!=0)
{
mylog(log_error,"find_arp failed for dest_ip %s ,if_name %s\n",my_ntoa(ntohl(ip)),if_name.c_str());
return -1;
}
//printf("%s\n",hw.c_str());
dest_ip=ntohl(dest_ip);
return 0;
}
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)
{ {
@@ -364,14 +585,9 @@ int send_raw_ip(raw_info_t &raw_info,const char * payload,int payloadlen)
else else
{ {
struct sockaddr_ll addr={0}; struct sockaddr_ll addr={0}; //={0} not necessary
//memset(&addr,0,sizeof(addr)); memcpy(&addr,&send_info.addr_ll,sizeof(addr));
addr.sll_family=AF_PACKET;
addr.sll_ifindex=ifindex;
addr.sll_halen=ETHER_ADDR_LEN;
addr.sll_protocol=htons(ETH_P_IP);
memcpy(addr.sll_addr,dest_hw_addr,ETHER_ADDR_LEN);
ret = sendto(raw_send_fd, send_raw_ip_buf, ip_tot_len , 0, (struct sockaddr *) &addr, sizeof (addr)); ret = sendto(raw_send_fd, send_raw_ip_buf, ip_tot_len , 0, (struct sockaddr *) &addr, sizeof (addr));
} }
if(ret==-1) if(ret==-1)
@@ -455,10 +671,10 @@ int recv_raw_ip(raw_info_t &raw_info,char * &payload,int &payloadlen)
static char recv_raw_ip_buf[buf_len]; static char recv_raw_ip_buf[buf_len];
iphdr * iph; iphdr * iph;
struct sockaddr saddr={0}; struct sockaddr_ll saddr={0};
socklen_t saddr_size = sizeof(saddr); socklen_t saddr_size = sizeof(saddr);
int flag=0; int flag=0;
int recv_len = recvfrom(raw_recv_fd, recv_raw_ip_buf, max_data_len, flag ,&saddr , &saddr_size); int recv_len = recvfrom(raw_recv_fd, recv_raw_ip_buf, max_data_len, flag ,(sockaddr*)&saddr , &saddr_size);
if(recv_len<0) if(recv_len<0)
{ {
@@ -485,6 +701,10 @@ int recv_raw_ip(raw_info_t &raw_info,char * &payload,int &payloadlen)
recv_info.dst_ip=iph->daddr; recv_info.dst_ip=iph->daddr;
recv_info.protocol=iph->protocol; recv_info.protocol=iph->protocol;
if(lower_level)
{
memcpy(&recv_info.addr_ll,&saddr,sizeof(recv_info.addr_ll));
}
if(bind_address_uint32!=0 &&recv_info.dst_ip!=bind_address_uint32) if(bind_address_uint32!=0 &&recv_info.dst_ip!=bind_address_uint32)

View File

@@ -16,9 +16,12 @@ 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 char if_name[100]; extern char if_name[100];
extern unsigned char dest_hw_addr[]; extern unsigned char dest_hw_addr[];
extern int ifindex;
struct icmphdr struct icmphdr
{ {
uint8_t type; uint8_t type;
@@ -58,6 +61,9 @@ struct packet_info_t //todo change this to union
uint16_t icmp_seq; uint16_t icmp_seq;
bool has_ts; bool has_ts;
sockaddr_ll addr_ll;
packet_info_t(); packet_info_t();
}; };
@@ -80,8 +86,9 @@ int init_raw_socket();
void init_filter(int port); void init_filter(int port);
void remove_filter(); void remove_filter();
int init_ifindex(char * if_name); int init_ifindex(const char * if_name,int &index);
int find_lower_level_info(u32_t ip,u32_t &dest_ip,string &if_name,string &hw);
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);