mirror of
https://github.com/wangyu-/udp2raw.git
synced 2025-09-16 04:04:27 +08:00
Compare commits
94 Commits
20170813.0
...
20170818.1
Author | SHA1 | Date | |
---|---|---|---|
|
2698ec9395 | ||
|
d09e0c51aa | ||
|
7d306b2451 | ||
|
d6d000e667 | ||
|
00a0fe17bf | ||
|
b74691f40a | ||
|
12741d9b9b | ||
|
ee4fe6cfcf | ||
|
466ce76eca | ||
|
20ab7d920d | ||
|
627e55932f | ||
|
91c427ebe4 | ||
|
4cf1dc7801 | ||
|
acc47afe29 | ||
|
29cfbeb678 | ||
|
fb0daf5994 | ||
|
35af7008ef | ||
|
af8160870b | ||
|
effbda0918 | ||
|
6c578738ca | ||
|
a33133c3de | ||
|
eea016cab4 | ||
|
8356b45c3b | ||
|
e502076394 | ||
|
1ca79a07b6 | ||
|
b35d8ecd34 | ||
|
5ed3bae33d | ||
|
ec298b355e | ||
|
33fb57d6d0 | ||
|
bdc7e3e43f | ||
|
b10d9421d3 | ||
|
bdc1f74f8f | ||
|
5cca489825 | ||
|
3897ac3847 | ||
|
231fd05680 | ||
|
3a362f6598 | ||
|
99b3ddf6a1 | ||
|
09b00ef07b | ||
|
c0628959d4 | ||
|
9aa229569d | ||
|
842766ae76 | ||
|
9e5b2140b3 | ||
|
ac02ea91d7 | ||
|
837de123b2 | ||
|
358c5c47ff | ||
|
19102700a5 | ||
|
f848839232 | ||
|
a13269a0b0 | ||
|
1d8223632b | ||
|
e459b74bdf | ||
|
9429a1c7db | ||
|
f5d93cb80d | ||
|
f591ba101c | ||
|
5236bc2f4e | ||
|
c7d9312cd2 | ||
|
85dfdd416f | ||
|
7a62918b74 | ||
|
138b34335c | ||
|
c5c74a3f35 | ||
|
0a4f53e579 | ||
|
dc41a3dbad | ||
|
bd08278f1b | ||
|
bcab893c53 | ||
|
f3f43b85d2 | ||
|
ed354347fd | ||
|
fb32c56fb2 | ||
|
fb5546f83b | ||
|
bb67509179 | ||
|
4bc4d618db | ||
|
9f4c452cf6 | ||
|
455dcc1e84 | ||
|
cee22ec3dc | ||
|
0612b73e7e | ||
|
84697a35c9 | ||
|
78bf036e04 | ||
|
3ee73b048e | ||
|
8220cf30fb | ||
|
a061af0b89 | ||
|
746cda08d2 | ||
|
06f5541b2a | ||
|
97b73b06c9 | ||
|
f7319680d9 | ||
|
6dd52326b4 | ||
|
1ebef723bf | ||
|
744bf2dece | ||
|
7538204bd1 | ||
|
ae6dd0b196 | ||
|
fc515c770f | ||
|
491c322148 | ||
|
80f1070546 | ||
|
5a4e3302e2 | ||
|
e76ad81a04 | ||
|
7ac0d3561d | ||
|
32166d65ae |
66
.cproject
Normal file
66
.cproject
Normal file
@@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
|
||||
<storageModule moduleId="org.eclipse.cdt.core.settings">
|
||||
<cconfiguration id="cdt.managedbuild.toolchain.gnu.base.436825263">
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.base.436825263" moduleId="org.eclipse.cdt.core.settings" name="Default">
|
||||
<externalSettings/>
|
||||
<extensions>
|
||||
<extension id="org.eclipse.cdt.core.GNU_ELF" point="org.eclipse.cdt.core.BinaryParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
</extensions>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<configuration artifactName="${ProjName}" buildProperties="" description="" id="cdt.managedbuild.toolchain.gnu.base.436825263" name="Default" parent="org.eclipse.cdt.build.core.emptycfg">
|
||||
<folderInfo id="cdt.managedbuild.toolchain.gnu.base.436825263.480908490" name="/" resourcePath="">
|
||||
<toolChain id="cdt.managedbuild.toolchain.gnu.base.1517253393" 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"/>
|
||||
<builder id="cdt.managedbuild.target.gnu.builder.base.1253245139" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" 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.cpp.compiler.base.1940762076" 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>
|
||||
<tool id="cdt.managedbuild.tool.gnu.c.compiler.base.233419498" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base">
|
||||
<inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.460189617" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
|
||||
</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>
|
||||
</folderInfo>
|
||||
</configuration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
||||
</cconfiguration>
|
||||
</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">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.base.436825263;cdt.managedbuild.toolchain.gnu.base.436825263.480908490;cdt.managedbuild.tool.gnu.cpp.compiler.base.1940762076;cdt.managedbuild.tool.gnu.cpp.compiler.input.997669137">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
</scannerConfigBuildInfo>
|
||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.base.436825263;cdt.managedbuild.toolchain.gnu.base.436825263.480908490;cdt.managedbuild.tool.gnu.c.compiler.base.233419498;cdt.managedbuild.tool.gnu.c.compiler.input.460189617">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
</scannerConfigBuildInfo>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
|
||||
</cproject>
|
27
.project
Normal file
27
.project
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>udp2raw-tunnel-desktop</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
|
||||
<triggers>clean,full,incremental,</triggers>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
|
||||
<triggers>full,incremental,</triggers>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.cdt.core.cnature</nature>
|
||||
<nature>org.eclipse.cdt.core.ccnature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
@@ -13,7 +13,7 @@ set(SOURCE_FILES
|
||||
main.cpp
|
||||
network.cpp
|
||||
)
|
||||
set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-unused-variable -Wno-unused-parameter -static")
|
||||
set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-unused-variable -Wno-unused-parameter -Wno-missing-field-initializers -static")
|
||||
#set(CMAKE_LINK_LIBRARY_FLAG "-lrt")
|
||||
add_executable(udp2raw_tunnel ${SOURCE_FILES})
|
||||
target_link_libraries(udp2raw_tunnel rt)
|
||||
add_executable(udp2raw_cmake ${SOURCE_FILES})
|
||||
target_link_libraries(udp2raw_cmake rt)
|
||||
|
56
README.md
56
README.md
@@ -1,9 +1,15 @@
|
||||
# Udp2raw-tunnel
|
||||

|
||||
|
||||
An Encrpyted,Anti-Replay,Multiplexed UDP Tunnel which can help you Bypass UDP Block or QoS by tunneling UDP traffic through Fake-TCP or ICMP by using raw socket.It aslo acts as a Connection Stablizer.
|
||||
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.
|
||||
|
||||
[简体中文](/doc/README.zh-cn.md)
|
||||
# Support Platforms
|
||||
A 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).
|
||||
|
||||
|
||||
# Features
|
||||
### Send / Receive UDP Packet with fake-tcp/icmp 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.
|
||||
@@ -11,11 +17,11 @@ Fake-tcp/icmp headers help you bypass UDP blocking, UDP QOS or improper UDP NAT
|
||||
### Simulate TCP Handshake
|
||||
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, Anti-MITM
|
||||
### Encrpytion, Anti-Replay, No MITM
|
||||
* Encrypt your traffic with AES-128-CBC.
|
||||
* Protect data integrity by MD5 or CRC32.
|
||||
* Defense replay attack with an anti-replay window, smiliar to IPSec and OpenVPN.
|
||||
* Authenticate mutually, no more MITM attacks.
|
||||
* Authenticate mutually, no MITM attacks.
|
||||
|
||||
### 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.
|
||||
@@ -34,21 +40,9 @@ For example, if you use UDP2RAW + OpenVPN, OpenVPN won't lose connection after a
|
||||
* **OpenWRT Support** No dependencies, easy to build. Binary for ar71xx are included in release.
|
||||
|
||||
### 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
|
||||
`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
|
||||
### Prerequisites
|
||||
A Linux host (including desktop Linux, OpenWRT router, or Raspberry PI) with root access.
|
||||
|
||||
If you want to use it on MICRO$OFT Windows, you can use VMware or Hyper-V (both bridged mode and <del>NAT mode</del> are supported).
|
||||
|
||||
### Installing
|
||||
Download binary release from https://github.com/wangyu-/udp2raw-tunnel/releases
|
||||
|
||||
@@ -56,20 +50,27 @@ Download binary release from https://github.com/wangyu-/udp2raw-tunnel/releases
|
||||
Assume your UDP is blocked or being QOS-ed or just poorly supported. Assume your server ip is 44.55.66.77, you have a service listening on udp port 7777.
|
||||
|
||||
```bash
|
||||
# Run at client side
|
||||
./udp2raw_amd64 -c -l0.0.0.0:3333 -r44.55.66.77:4096 -a -k "passwd" --raw-mode faketcp
|
||||
|
||||
# Run at server side:
|
||||
./udp2raw_amd64 -s -l0.0.0.0:4096 -r 127.0.0.1:7777 -a -k "passwd" --raw-mode faketcp
|
||||
|
||||
# Run at client side
|
||||
./udp2raw_amd64 -c -l0.0.0.0:3333 -r44.55.66.77:4096 -a -k "passwd" --raw-mode faketcp
|
||||
```
|
||||
###### Server Output:
|
||||

|
||||
###### Client Output:
|
||||

|
||||
|
||||
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
|
||||
to run on Android, see [Android_Guide](/doc/android_guide.md)
|
||||
|
||||
# Advanced Topic
|
||||
### Usage
|
||||
```
|
||||
udp2raw-tunnel
|
||||
version: Aug 5 2017 21:03:54
|
||||
version: Aug 18 2017 00:29:11
|
||||
repository: https://github.com/wangyu-/udp2raw-tunnel
|
||||
|
||||
usage:
|
||||
@@ -79,8 +80,8 @@ usage:
|
||||
common options,these options must be same on both side:
|
||||
--raw-mode <string> avaliable values:faketcp(default),udp,icmp
|
||||
-k,--key <string> password to gen symetric key,default:"secret key"
|
||||
--auth-mode <string> avaliable values:aes128cbc(default),xor,none
|
||||
--cipher-mode <string> avaliable values:md5(default),crc32,simple,none
|
||||
--cipher-mode <string> avaliable values:aes128cbc(default),xor,none
|
||||
--auth-mode <string> avaliable values:md5(default),crc32,simple,none
|
||||
-a,--auto-rule auto add (and delete) iptables rule
|
||||
-g,--gen-rule generate iptables rule then exit
|
||||
--disable-anti-replay disable anti-replay,not suggested
|
||||
@@ -100,6 +101,8 @@ other options:
|
||||
0:dont increase
|
||||
1:increase every packet
|
||||
2:increase randomly, about every 3 packets (default)
|
||||
--lower-level <string> send packet at OSI level 2, format:'if_name#dest_mac_adress'
|
||||
ie:'eth0#00:23:45:67:89:b9'.Beta.
|
||||
-h,--help print this help message
|
||||
```
|
||||
|
||||
@@ -185,3 +188,12 @@ https://github.com/ccsexyz/kcpraw
|
||||
Transparently tunnel your IP traffic through ICMP echo and reply packets.
|
||||
|
||||
https://github.com/DhavalKapil/icmptunnel
|
||||
|
||||
### Tcp Minion
|
||||
Tcp Minion is a project which modifid the code of tcp stack in kernel,and implemented real-time out-order udp packet delivery through this modified tcp stack.I failed to find the implementation,but there are some papers avaliable:
|
||||
|
||||
https://arxiv.org/abs/1103.0463
|
||||
|
||||
http://korz.cs.yale.edu/2009/tng/papers/pfldnet10.pdf
|
||||
|
||||
https://pdfs.semanticscholar.org/9e6f/e2306f4385b4eb5416d1fcab16e9361d6ba3.pdf
|
||||
|
110
common.cpp
110
common.cpp
@@ -55,13 +55,15 @@ int add_iptables_rule(char * s)
|
||||
strcpy(iptables_rule,s);
|
||||
char buf[300]="iptables -I ";
|
||||
strcat(buf,s);
|
||||
if(system(buf)==0)
|
||||
char *output;
|
||||
if(run_command(buf,output)==0)
|
||||
{
|
||||
mylog(log_warn,"auto added iptables rule by: %s\n",buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
mylog(log_fatal,"auto added iptables failed by: %s\n",buf);
|
||||
//mylog(log_fatal,"reason : %s\n",strerror(errno));
|
||||
myexit(-1);
|
||||
}
|
||||
return 0;
|
||||
@@ -73,13 +75,15 @@ int clear_iptables_rule()
|
||||
{
|
||||
char buf[300]="iptables -D ";
|
||||
strcat(buf,iptables_rule);
|
||||
if(system(buf)==0)
|
||||
char *output;
|
||||
if(run_command(buf,output)==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));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -135,7 +139,7 @@ u64_t ntoh64(u64_t a)
|
||||
{
|
||||
if(__BYTE_ORDER == __LITTLE_ENDIAN)
|
||||
{
|
||||
return __bswap_64( a);
|
||||
return bswap_64( a);
|
||||
}
|
||||
else return a;
|
||||
|
||||
@@ -144,7 +148,7 @@ u64_t hton64(u64_t a)
|
||||
{
|
||||
if(__BYTE_ORDER == __LITTLE_ENDIAN)
|
||||
{
|
||||
return __bswap_64( a);
|
||||
return bswap_64( a);
|
||||
}
|
||||
else return a;
|
||||
|
||||
@@ -310,3 +314,101 @@ bool larger_than_u16(uint16_t a,uint16_t b)
|
||||
}
|
||||
}
|
||||
}
|
||||
vector<string> string_to_vec(const char * s,const char * sp) {
|
||||
vector<string> res;
|
||||
string str=s;
|
||||
char *p = strtok ((char *)str.c_str(),sp);
|
||||
while (p != NULL)
|
||||
{
|
||||
res.push_back(p);
|
||||
//printf ("%s\n",p);
|
||||
p = strtok (NULL, sp);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
vector< vector <string> > string_to_vec2(const char * s)
|
||||
{
|
||||
vector< vector <string> > res;
|
||||
vector<string> lines=string_to_vec(s,"\n");
|
||||
for(int i=0;i<int(lines.size());i++)
|
||||
{
|
||||
vector<string> tmp;
|
||||
tmp=string_to_vec(lines[i].c_str(),"\t ");
|
||||
res.push_back(tmp);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
int read_file(const char * file,char * &output)
|
||||
{
|
||||
static char buf[1024*1024+100];
|
||||
buf[sizeof(buf)-1]=0;
|
||||
int fd=open(file,O_RDONLY);
|
||||
if(fd==-1)
|
||||
{
|
||||
mylog(log_error,"read_file %s fail\n",file);
|
||||
return -1;
|
||||
}
|
||||
int len=read(fd,buf,1024*1024);
|
||||
if(len==1024*1024)
|
||||
{
|
||||
buf[0]=0;
|
||||
mylog(log_error,"too long,buf not larger enough\n");
|
||||
return -2;
|
||||
}
|
||||
else if(len<0)
|
||||
{
|
||||
buf[0]=0;
|
||||
mylog(log_error,"read fail %d\n",len);
|
||||
return -3;
|
||||
}
|
||||
else
|
||||
{
|
||||
output=buf;
|
||||
buf[len]=0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int run_command(const char * command,char * &output) {
|
||||
FILE *in;
|
||||
mylog(log_debug,"run_command %s\n",command);
|
||||
static char buf[1024*1024+100];
|
||||
buf[sizeof(buf)-1]=0;
|
||||
if(!(in = popen(command, "r"))){
|
||||
mylog(log_error,"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_error,"too long,buf not larger enough\n");
|
||||
return -2;
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[len]=0;
|
||||
}
|
||||
int ret;
|
||||
if(( ret=ferror(in) ))
|
||||
{
|
||||
mylog(log_error,"command %s fread failed,ferror return value %d \n",command,ret);
|
||||
return -2;
|
||||
}
|
||||
//if(output!=0)
|
||||
output=buf;
|
||||
ret= pclose(in);
|
||||
|
||||
int ret2=WEXITSTATUS(ret);
|
||||
|
||||
if(ret!=0||ret2!=0)
|
||||
{
|
||||
mylog(log_error,"commnad %s ,pclose returned %d ,WEXITSTATUS %d,errnor :%s \n",command,ret,ret2,strerror(errno));
|
||||
return -3;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
11
common.h
11
common.h
@@ -43,11 +43,12 @@
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
#include <linux/if_packet.h>
|
||||
|
||||
|
||||
#include <byteswap.h>
|
||||
|
||||
|
||||
#include<unordered_map>
|
||||
#include<vector>
|
||||
#include<string>
|
||||
using namespace std;
|
||||
|
||||
|
||||
@@ -144,4 +145,10 @@ int add_iptables_rule(char *);
|
||||
|
||||
int clear_iptables_rule();
|
||||
|
||||
int run_command(const char * command,char * &output);
|
||||
int read_file(const char * file,char * &output);
|
||||
|
||||
vector<string> string_to_vec(const char * s,const char * sp);
|
||||
vector< vector <string> > string_to_vec2(const char * s);
|
||||
|
||||
#endif /* COMMON_H_ */
|
||||
|
@@ -1,6 +1,10 @@
|
||||
Udp2raw-tunnel
|
||||

|
||||
加密、防重放攻击的、信道复用的udp tunnel,利用raw socket中转udp流量.同时有心跳保活,且在断线重连后保持上层连接不掉线的功能。
|
||||
udp2raw tunnel,通过raw socket给UDP包加上TCP或ICMP header,进而绕过UDP屏蔽或QoS,或在UDP不稳定的环境下提升稳定性。可以有效防止在使用kcptun或者finalspeed的情况下udp端口被运营商限速。
|
||||
|
||||
支持心跳保活、自动重连,重连后会恢复上次连接,在底层掉线的情况下可以保持上层不掉线。同时有加密、防重放攻击、信道复用的功能。
|
||||
|
||||
**欢迎任何形式的转载**
|
||||
|
||||
[English](/README.md)
|
||||
|
||||
@@ -11,6 +15,12 @@ Udp2raw-tunnel
|
||||
如果你需要加速跨国网游、网页浏览,解决方案在另一个repo:
|
||||
|
||||
https://github.com/wangyu-/UDPspeeder
|
||||
# 支持的平台
|
||||
Linux主机,有root权限。可以是PC、android手机/平板、openwrt路由器、树莓派。主机上最好安装了iptables命令(apt/yum很容易安装)。
|
||||
|
||||
在windows和mac上预装了udp2raw的虚拟机镜像已发布,可以用Vmware或VirtualBox加载,容量4.4mb,已经配置好了自动获取网卡ip,开机即用,稳定,性能很好。
|
||||
(udp2raw跑在虚拟机里,其他应用照常跑在windows上)(确保虚拟机网卡工作在桥接模式)(Vmware player 75mb,VirtualBox 118mb,很容易安装)。
|
||||
|
||||
# 功能特性
|
||||
### 把udp流量伪装成tcp /icmp
|
||||
用raw socket给udp包加上tcp/icmp包头,可以突破udp流量限制或Udp QOS。或者在udp nat有问题的环境下,提升稳定性。 另外也支持用raw 发udp包,这样流量不会被伪装,只会被加密。
|
||||
@@ -26,7 +36,7 @@ Client能用单倍的超时时间检测到单向链路的失效,不管是上
|
||||
对于有大量client的情况,对于不同client,server发送的心跳是错开时间发送的,不会因为短时间发送大量的心跳而造成拥塞和延迟抖动。
|
||||
|
||||
### 加密 防重放攻击 防中间人攻击
|
||||
用aes128cbc加密,md5/crc32做数据完整校验。用类似ipsec/openvpn的 replay windows机制来防止重放攻击。
|
||||
用aes128cbc加密,md5/crc32做数据完整校验。用类似ipsec/openvpn的 replay window机制来防止重放攻击。
|
||||
|
||||
设计目标是,即使攻击者可以监听到tunnel的所有包,可以选择性丢弃tunnel的任意包,可以重放任意包;攻击者也没办法获得tunnel承载的任何数据,也没办法向tunnel的数据流中通过包构造/包重放插入任何数据。client和server互相认证对方,无法被中间人攻击。
|
||||
|
||||
@@ -48,9 +58,6 @@ epoll纯异步,高并发,除了回收过期连接外,所有操作的时间
|
||||
|
||||
# 简明操作说明
|
||||
|
||||
### 环境要求
|
||||
Linux主机,有root权限。主机上最好安装了iptables命令(apt/yum很容易安装)。在windows和mac上可以开虚拟机(桥接模式和<del>NAT模式</del>经测试都可用)。
|
||||
|
||||
### 安装
|
||||
下载编译好的二进制文件,解压到任意目录。
|
||||
|
||||
@@ -60,22 +67,28 @@ https://github.com/wangyu-/udp2raw-tunnel/releases
|
||||
假设你有一个server,ip为44.55.66.77,有一个服务监听在udp 7777端口。 假设你本地的主机到44.55.66.77的UDP流量被屏蔽了,或者被qos了
|
||||
|
||||
```
|
||||
在client端运行:
|
||||
./udp2raw_amd64 -c -l0.0.0.0:3333 -r44.55.66.77:4096 -a -k "passwd" --raw-mode faketcp
|
||||
|
||||
在server端运行:
|
||||
./udp2raw_amd64 -s -l0.0.0.0:4096 -r 127.0.0.1:7777 -a -k "passwd" --raw-mode faketcp
|
||||
|
||||
在client端运行:
|
||||
./udp2raw_amd64 -c -l0.0.0.0:3333 -r44.55.66.77:4096 -a -k "passwd" --raw-mode faketcp
|
||||
```
|
||||
###### Server端输出:
|
||||

|
||||
###### Client端输出:
|
||||

|
||||
|
||||
现在client和server之间建立起了,tunnel。想要在本地连接44.55.66.77:7777,只需要连接 127.0.0.1:3333。来回的所有的udp流量会被经过tunneling发送。在外界看起来是tcp流量,不会有udp流量暴露到公网。
|
||||
|
||||
### 提醒
|
||||
如果要在anroid上运行,请看[Android简明教程](/doc/android_guide.md)
|
||||
|
||||
# 进阶操作说明
|
||||
|
||||
### 命令选项
|
||||
```
|
||||
udp2raw-tunnel
|
||||
version: Aug 5 2017 21:03:54
|
||||
version: Aug 18 2017 00:29:11
|
||||
repository: https://github.com/wangyu-/udp2raw-tunnel
|
||||
|
||||
usage:
|
||||
@@ -85,8 +98,8 @@ usage:
|
||||
common options,these options must be same on both side:
|
||||
--raw-mode <string> avaliable values:faketcp(default),udp,icmp
|
||||
-k,--key <string> password to gen symetric key,default:"secret key"
|
||||
--auth-mode <string> avaliable values:aes128cbc(default),xor,none
|
||||
--cipher-mode <string> avaliable values:md5(default),crc32,simple,none
|
||||
--cipher-mode <string> avaliable values:aes128cbc(default),xor,none
|
||||
--auth-mode <string> avaliable values:md5(default),crc32,simple,none
|
||||
-a,--auto-rule auto add (and delete) iptables rule
|
||||
-g,--gen-rule generate iptables rule then exit
|
||||
--disable-anti-replay disable anti-replay,not suggested
|
||||
@@ -106,6 +119,8 @@ other options:
|
||||
0:dont increase
|
||||
1:increase every packet
|
||||
2:increase randomly, about every 3 packets (default)
|
||||
--lower-level <string> send packet at OSI level 2, format:'if_name#dest_mac_adress'
|
||||
ie:'eth0#00:23:45:67:89:b9'.Beta.
|
||||
-h,--help print this help message
|
||||
```
|
||||
### iptables 规则
|
||||
@@ -118,6 +133,25 @@ other options:
|
||||
### seq-mode
|
||||
facktcp模式并没有模拟tcp的全部。所以理论上有办法把faketcp和真正的tcp流量区分开来(虽然大部分ISP不太可能做这种程度的包检测)。seq-mode可以改变一些seq ack的行为。如果遇到了连接问题,可以尝试更改。在我这边的移动线路用3种模式都没问题。
|
||||
|
||||
### lower-level
|
||||
大部分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地址,这个属于罕见的应用场景,可以忽略)。
|
||||
|
||||
##### client端获得--lower-level参数的办法
|
||||
在client 端,运行`traceroute <server_ip>`,记下第一跳的地址,这个就是`网关ip`。再运行`arp -s <网关ip>`,可以同时查到出口网卡名和mac。
|
||||
|
||||

|
||||
##### server端获得--lower-level参数的办法
|
||||
如果client有公网ip,就`traceroute <client_ip>`。下一步和client端的方法一样。
|
||||
|
||||
如果client没有公网ip,就`traceroute google.com` 或`traceroute baidu.com`。下一步和client端的方法一样。
|
||||
|
||||
##### 注意
|
||||
如果用了`--lower-level`选项。server虽然还可以bind在0.0.0.0,但是因为你显式指定了网络接口,就只能工作在这一个网络接口了。
|
||||
|
||||
|
||||
# 性能测试
|
||||
iperf3 的UDP模式有BUG,所以,这里用iperf3的tcp模式,配合Openvpn,测试udp2raw的性能。(iperf3 udp issue ,https://github.com/esnet/iperf/issues/296 )
|
||||
|
||||
|
29
doc/android_guide.md
Normal file
29
doc/android_guide.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# How to run udp2raw on a rooted android device(arm cpu)
|
||||
|
||||
There is currently no GUI for udp2raw on android.Make sure you have installed Terminal to run it.
|
||||
|
||||
Download udp2raw_arm from https://github.com/wangyu-/udp2raw-tunnel/releases.
|
||||
|
||||
Copy udp2raw_arm to any dir of your **internal storage** .Copying it to **SD card wont work**.
|
||||
|
||||
# Steps
|
||||
1. run udp2raw_arm as usual, except you must change the -a option to -g
|
||||
```
|
||||
./udp2raw_arm -c -r 44.55.66.77:9966 -l 0.0.0.0:4000 -k1234 --cipher xor -g
|
||||
```
|
||||
|
||||
2. find the generated iptables rule from udp2raw's output,add it manually by running:
|
||||
```
|
||||
iptables -I INPUT -s 44.55.66.77/32 -p tcp -m tcp --sport 9966 -j DROP
|
||||
```
|
||||
|
||||
3. run udp2raw_ram without -g command
|
||||
|
||||
```
|
||||
./udp2raw_arm -c -r 44.55.66.77:9966 -l 0.0.0.0:4000 -k1234 --cipher xor
|
||||
```
|
||||
|
||||
# ScreenShot
|
||||
zoom-in if not large enough
|
||||
|
||||

|
@@ -8,7 +8,7 @@
|
||||
##### 摘要
|
||||
udp2raw是一个把udp流量通过raw socket包装成tcp流量的工具。通过用udp2raw配合udp模式的 finalspeed一样可以达到在底层发tcp包,绕过QOS的效果。支持openvz,稳定性也好很多。原理上相当于在finalspeed外面再包了一层tunnel。
|
||||
|
||||
本教程会一步一步演示用udp2raw+kcptun加速http流量的过程。加速任何其他tcp流量也一样。
|
||||
本教程会一步一步演示用udp2raw+finalspeed加速http流量的过程。加速任何其他tcp流量也一样,包括ss。本文避免讨论科学上网,所以只演示加速http流量。
|
||||
|
||||
udp2raw也支持把udp流量包装成Icmp发送,本教程不做演示。
|
||||
|
||||
@@ -17,12 +17,14 @@ udp2raw也支持把udp流量包装成Icmp发送,本教程不做演示。
|
||||
|
||||
本地主机是windows,本地有openwrt路由器或树莓派或安装了linux虚拟机(网卡设置为桥接模式)。
|
||||
|
||||
(如果嫌给虚拟机安装linux麻烦,可以下载别人提供好的linux虚拟机镜像,比如https://www.kali.org/downloads/ ,不过我没有测试过这个镜像,我用的是debian 7)
|
||||
(如果嫌给虚拟机安装linux麻烦,可以用release里发布的预装了udp2raw的openwrt_x86虚拟机镜像,容量4.4mb)
|
||||
|
||||
下面的教程按虚拟机演示,如果你有openwrt路由器或树莓派,可以直接运行再路由器或树莓派上,就不需要虚拟机了。
|
||||
|
||||
### 安装
|
||||
下载好udp2raw的压缩包,解压分别解压到服务器和本地的虚拟机。
|
||||
|
||||
https://github.com/xtaci/kcptun/releases
|
||||
https://github.com/wangyu-/udp2raw-tunnel/releases
|
||||
|
||||
在服务器端安装好finalspeed服务端,在本地windows安装好finalspeed的客户端。服务端我以前是用91yun的一键安装脚本安装的,没装过的可以去网上搜一键安装脚本。
|
||||
|
||||
@@ -52,7 +54,7 @@ netstat -nlp|grep java
|
||||
|
||||
记下红框中的ip,这是虚拟机的网卡ip
|
||||
|
||||
在server端也会显示server_reay
|
||||
在server端也会显示server_ready
|
||||

|
||||
|
||||
4.在本地windows,按图配置好finalspeed的客户端。注意,192.168.205.8改成你刚才记下来的IP,带宽也要按实际的填。传输协议要选UDP.
|
||||
|
@@ -4,7 +4,9 @@
|
||||
本教程会一步一步演示用udp2raw+kcptun加速SSH流量的过程。加速任何其他tcp流量也一样,包括ss;本文避免涉及科学上网,所以演示ssh。
|
||||
|
||||
### 环境要求
|
||||
两边的主机都是linux,有root权限。 可以是openwrt路由器或树莓派,windows上桥接模式的虚拟机也可用
|
||||
两边的主机都是linux,有root权限。 可以是openwrt路由器或树莓派,也可以是root了的android。
|
||||
|
||||
(windows和mac可以用release里发布的预装了udp2raw的openwrt_x86虚拟机镜像,容量4.4mb,开机即用)
|
||||
|
||||
|
||||
### 安装
|
||||
|
105
encrypt.cpp
105
encrypt.cpp
@@ -11,12 +11,15 @@
|
||||
//static uint64_t seq=1;
|
||||
|
||||
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!
|
||||
* 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
|
||||
****/
|
||||
unordered_map<int, const char *> auth_mode_tostring = {{auth_none, "none"}, {auth_md5, "md5"}, {auth_crc32, "crc32"},{auth_simple,"simple"}};
|
||||
unordered_map<int, const char *> cipher_mode_tostring={{cipher_none,"none"},{cipher_aes128cbc,"aes128cbc"},{cipher_xor,"xor"}};
|
||||
|
||||
auth_mode_t auth_mode=auth_crc32;
|
||||
auth_mode_t auth_mode=auth_md5;
|
||||
cipher_mode_t cipher_mode=cipher_aes128cbc;
|
||||
|
||||
|
||||
@@ -213,7 +216,7 @@ int auth_crc32_verify(const char *data,int &len)
|
||||
{
|
||||
if(len<int(sizeof(unsigned int)))
|
||||
{
|
||||
mylog(log_debug,"auth_crc32_verify len<16\n");
|
||||
mylog(log_debug,"auth_crc32_verify len<%d\n",int(sizeof(unsigned int)));
|
||||
return -1;
|
||||
}
|
||||
unsigned int ret=crc32h((unsigned char *)data,len-sizeof(unsigned int));
|
||||
@@ -313,6 +316,7 @@ int my_encrypt(const char *data,char *output,int &len,char * key)
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int my_decrypt(const char *data,char *output,int &len,char * key)
|
||||
{
|
||||
if(len<0) return -1;
|
||||
@@ -324,99 +328,6 @@ int my_decrypt(const char *data,char *output,int &len,char * key)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int my_encrypt_old(const char *data0,char *output,int &len,char * key)
|
||||
{
|
||||
static const int disable_all=0;
|
||||
static const int disable_aes=0;
|
||||
|
||||
char data[buf_len];
|
||||
memcpy(data,data0,len);
|
||||
|
||||
if(disable_all)
|
||||
{
|
||||
memcpy(output,data,len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ori_len=len;
|
||||
|
||||
len=len+16;//md5
|
||||
len+=2;//length
|
||||
|
||||
if(len%16!=0)
|
||||
{
|
||||
len= (len/16)*16+16;
|
||||
}
|
||||
|
||||
if(len>max_data_len) return -1;
|
||||
|
||||
data[len-16-2]= (unsigned char)( (uint16_t(ori_len))>>8);
|
||||
data[len-16-1]=(unsigned char)( ((uint16_t(ori_len))<<8)>>8) ;
|
||||
|
||||
|
||||
//printf("%d %d\n",data[len-16-2],data[len-16-1]);
|
||||
md5((unsigned char *)data,len-16,(unsigned char *)(data+len-16));
|
||||
|
||||
|
||||
if(disable_aes)
|
||||
{
|
||||
memcpy(output,data,len);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
AES_CBC_encrypt_buffer((unsigned char *)output,(unsigned char *)data,len,(unsigned char *)key,(unsigned char *)zero_iv);
|
||||
//it doesnt allow over lap
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
int my_decrypt_old(const char *data0,char *output,int &len,char * key)
|
||||
{
|
||||
static const int disable_all=0;
|
||||
static const int disable_aes=0;
|
||||
|
||||
char data[buf_len];
|
||||
memcpy(data,data0,len);
|
||||
|
||||
if(disable_all)
|
||||
{
|
||||
memcpy(output,data,len);
|
||||
return 0;
|
||||
}
|
||||
uint8_t md5_res[16];
|
||||
if(len>max_data_len) return -1;
|
||||
if(len<32) return -1;
|
||||
if(len%16 !=0) return -1;
|
||||
|
||||
|
||||
if(disable_aes)
|
||||
{
|
||||
memcpy(output,data,len);
|
||||
}
|
||||
else
|
||||
{
|
||||
AES_CBC_decrypt_buffer((unsigned char *)output,(unsigned char *)data,len,(unsigned char *)key,(unsigned char *)zero_iv);
|
||||
}
|
||||
|
||||
|
||||
//printf("%d %d\n",data[len-16-2],data[len-16-1]);
|
||||
|
||||
//printf("<<%d>>",len);
|
||||
|
||||
md5((unsigned char *)output,len-16,(unsigned char *)md5_res);
|
||||
|
||||
if(memcmp(output+len-16,md5_res,16)!=0)
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
|
||||
len=((unsigned char)output[len-16-2])*256u+((unsigned char)output[len-16-1]); //this may be broken because of sign
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int my_encrypt_pesudo_header(uint8_t *data,uint8_t *output,int &len,uint8_t * key,uint8_t *header,int hlen)
|
||||
{
|
||||
|
||||
|
BIN
images/android.png
Normal file
BIN
images/android.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 366 KiB |
BIN
images/lower_level.PNG
Normal file
BIN
images/lower_level.PNG
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
BIN
images/output_client.PNG
Normal file
BIN
images/output_client.PNG
Normal file
Binary file not shown.
After Width: | Height: | Size: 36 KiB |
BIN
images/output_server.PNG
Normal file
BIN
images/output_server.PNG
Normal file
Binary file not shown.
After Width: | Height: | Size: 33 KiB |
BIN
images/speed_test.PNG
Normal file
BIN
images/speed_test.PNG
Normal file
Binary file not shown.
After Width: | Height: | Size: 20 KiB |
600
lib/aes_acc/aes0.c
Executable file
600
lib/aes_acc/aes0.c
Executable file
@@ -0,0 +1,600 @@
|
||||
|
||||
/*
|
||||
* 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)
|
45
lib/aes_acc/aes0.h
Executable file
45
lib/aes_acc/aes0.h
Executable file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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_
|
388
lib/aes_acc/aesacc.c
Normal file
388
lib/aes_acc/aesacc.c
Normal file
@@ -0,0 +1,388 @@
|
||||
/*
|
||||
* This file is adapted from PolarSSL 1.3.19 (GPL)
|
||||
*/
|
||||
|
||||
#include "aes0.h"
|
||||
#include "aesni.h"
|
||||
#include "aesarm.h"
|
||||
#include "aesacc.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if defined(AES256) && (AES256 == 1)
|
||||
#define AES_KEYSIZE 256
|
||||
#ifdef HAVE_AMD64
|
||||
#define aes_setkey_enc aesni_setkey_enc_256
|
||||
#endif
|
||||
#elif defined(AES192) && (AES192 == 1)
|
||||
#define AES_KEYSIZE 192
|
||||
#ifdef HAVE_AMD64
|
||||
#define aes_setkey_enc aesni_setkey_enc_192
|
||||
#endif
|
||||
#else
|
||||
#define AES_KEYSIZE 128
|
||||
#ifdef HAVE_AMD64
|
||||
#define aes_setkey_enc aesni_setkey_enc_128
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define AES_NR ((AES_KEYSIZE >> 5) + 6)
|
||||
#define AES_RKSIZE 272
|
||||
|
||||
#ifdef HAVE_AMD64
|
||||
#define HAVE_HARDAES 1
|
||||
#define aes_supported aesni_supported
|
||||
#define aes_crypt_ecb aesni_crypt_ecb
|
||||
#define aes_inverse_key(a,b) aesni_inverse_key(a,b,AES_NR)
|
||||
#endif /* HAVE_AMD64 */
|
||||
|
||||
#ifdef HAVE_ARM64
|
||||
#define HAVE_HARDAES 1
|
||||
#define aes_supported aesarm_supported
|
||||
#define aes_crypt_ecb aesarm_crypt_ecb
|
||||
|
||||
#include "aesarm_table.h"
|
||||
|
||||
#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
|
||||
|
||||
static void aes_setkey_enc(uint8_t *rk, const uint8_t *key)
|
||||
{
|
||||
unsigned int i;
|
||||
uint32_t *RK;
|
||||
|
||||
RK = (uint32_t *) rk;
|
||||
|
||||
for( i = 0; i < ( AES_KEYSIZE >> 5 ); i++ )
|
||||
{
|
||||
GET_UINT32_LE( RK[i], key, i << 2 );
|
||||
}
|
||||
|
||||
switch( AES_NR )
|
||||
{
|
||||
case 10:
|
||||
|
||||
for( i = 0; i < 10; i++, RK += 4 )
|
||||
{
|
||||
RK[4] = RK[0] ^ RCON[i] ^
|
||||
( (uint32_t) FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^
|
||||
( (uint32_t) FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^
|
||||
( (uint32_t) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^
|
||||
( (uint32_t) FSb[ ( RK[3] ) & 0xFF ] << 24 );
|
||||
|
||||
RK[5] = RK[1] ^ RK[4];
|
||||
RK[6] = RK[2] ^ RK[5];
|
||||
RK[7] = RK[3] ^ RK[6];
|
||||
}
|
||||
break;
|
||||
|
||||
case 12:
|
||||
|
||||
for( i = 0; i < 8; i++, RK += 6 )
|
||||
{
|
||||
RK[6] = RK[0] ^ RCON[i] ^
|
||||
( (uint32_t) FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^
|
||||
( (uint32_t) FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^
|
||||
( (uint32_t) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^
|
||||
( (uint32_t) FSb[ ( RK[5] ) & 0xFF ] << 24 );
|
||||
|
||||
RK[7] = RK[1] ^ RK[6];
|
||||
RK[8] = RK[2] ^ RK[7];
|
||||
RK[9] = RK[3] ^ RK[8];
|
||||
RK[10] = RK[4] ^ RK[9];
|
||||
RK[11] = RK[5] ^ RK[10];
|
||||
}
|
||||
break;
|
||||
|
||||
case 14:
|
||||
|
||||
for( i = 0; i < 7; i++, RK += 8 )
|
||||
{
|
||||
RK[8] = RK[0] ^ RCON[i] ^
|
||||
( (uint32_t) FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^
|
||||
( (uint32_t) FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^
|
||||
( (uint32_t) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^
|
||||
( (uint32_t) FSb[ ( RK[7] ) & 0xFF ] << 24 );
|
||||
|
||||
RK[9] = RK[1] ^ RK[8];
|
||||
RK[10] = RK[2] ^ RK[9];
|
||||
RK[11] = RK[3] ^ RK[10];
|
||||
|
||||
RK[12] = RK[4] ^
|
||||
( (uint32_t) FSb[ ( RK[11] ) & 0xFF ] ) ^
|
||||
( (uint32_t) FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^
|
||||
( (uint32_t) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^
|
||||
( (uint32_t) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 );
|
||||
|
||||
RK[13] = RK[5] ^ RK[12];
|
||||
RK[14] = RK[6] ^ RK[13];
|
||||
RK[15] = RK[7] ^ RK[14];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void aes_inverse_key(uint8_t *invkey, const uint8_t *fwdkey)
|
||||
{
|
||||
int i, j;
|
||||
uint32_t *RK;
|
||||
uint32_t *SK;
|
||||
|
||||
RK = (uint32_t *) invkey;
|
||||
SK = ((uint32_t *) fwdkey) + AES_NR * 4;
|
||||
|
||||
*RK++ = *SK++;
|
||||
*RK++ = *SK++;
|
||||
*RK++ = *SK++;
|
||||
*RK++ = *SK++;
|
||||
|
||||
for( i = AES_NR - 1, SK -= 8; i > 0; i--, SK -= 8 )
|
||||
{
|
||||
for( j = 0; j < 4; j++, SK++ )
|
||||
{
|
||||
*RK++ = RT0[ FSb[ ( *SK ) & 0xFF ] ] ^
|
||||
RT1[ FSb[ ( *SK >> 8 ) & 0xFF ] ] ^
|
||||
RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^
|
||||
RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ];
|
||||
}
|
||||
}
|
||||
|
||||
*RK++ = *SK++;
|
||||
*RK++ = *SK++;
|
||||
*RK++ = *SK++;
|
||||
*RK++ = *SK++;
|
||||
}
|
||||
|
||||
#endif /* HAVE_ARM64 */
|
||||
|
||||
#ifdef HAVE_ASM
|
||||
|
||||
#define AES_MAXNR 14
|
||||
|
||||
typedef struct {
|
||||
uint32_t rd_key[4 * (AES_MAXNR + 1)];
|
||||
int rounds;
|
||||
} AES_KEY;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
|
||||
AES_KEY *key);
|
||||
int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
|
||||
AES_KEY *key);
|
||||
|
||||
void AES_encrypt(const unsigned char *in, unsigned char *out,
|
||||
const AES_KEY *key);
|
||||
void AES_decrypt(const unsigned char *in, unsigned char *out,
|
||||
const AES_KEY *key);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
static int aes_supported(void)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
static void aes_crypt_ecb( int nr,
|
||||
unsigned char *rk,
|
||||
int mode,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] )
|
||||
{
|
||||
AES_KEY *ctx;
|
||||
ctx = (AES_KEY *) rk;
|
||||
ctx->rounds = nr;
|
||||
if (mode == AES_DECRYPT) {
|
||||
AES_decrypt(input, output, ctx);
|
||||
} else {
|
||||
AES_encrypt(input, output, ctx);
|
||||
}
|
||||
}
|
||||
|
||||
static void aes_setkey_enc(uint8_t *rk, const uint8_t *key)
|
||||
{
|
||||
AES_KEY *ctx;
|
||||
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)
|
||||
{
|
||||
AES_KEY *ctx;
|
||||
ctx = (AES_KEY *) rk;
|
||||
ctx->rounds = AES_NR;
|
||||
AES_set_decrypt_key(key, AES_KEYSIZE, ctx);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_HARDAES
|
||||
|
||||
static void aes_setkey_dec(uint8_t *rk, const uint8_t *key)
|
||||
{
|
||||
uint8_t rk_tmp[AES_RKSIZE];
|
||||
aes_setkey_enc(rk_tmp, key);
|
||||
aes_inverse_key(rk, rk_tmp);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_HARDAES) || defined(HAVE_ASM)
|
||||
|
||||
#define HAVE_ACC 1
|
||||
|
||||
/*
|
||||
* AESNI-CBC buffer encryption/decryption
|
||||
*/
|
||||
static void aes_crypt_cbc( int mode,
|
||||
uint8_t* rk,
|
||||
uint32_t length,
|
||||
uint8_t iv[16],
|
||||
const uint8_t *input,
|
||||
uint8_t *output )
|
||||
{
|
||||
int i;
|
||||
uint8_t temp[16];
|
||||
|
||||
if( mode == AES_DECRYPT )
|
||||
{
|
||||
while( length > 0 )
|
||||
{
|
||||
memcpy( temp, input, 16 );
|
||||
aes_crypt_ecb( AES_NR, rk, mode, input, output );
|
||||
|
||||
for( i = 0; i < 16; i++ )
|
||||
output[i] = (uint8_t)( output[i] ^ iv[i] );
|
||||
|
||||
memcpy( iv, temp, 16 );
|
||||
|
||||
input += 16;
|
||||
output += 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 */
|
||||
|
||||
int AESACC_supported(void)
|
||||
{
|
||||
#if defined(HAVE_ACC)
|
||||
return aes_supported();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
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 rk[AES_RKSIZE];
|
||||
|
||||
if (aes_supported())
|
||||
{
|
||||
if (key == NULL || iv == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
memcpy(iv_tmp, iv, 16);
|
||||
aes_setkey_enc(rk, key);
|
||||
aes_crypt_cbc(AES_ENCRYPT, rk, \
|
||||
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)
|
||||
{
|
||||
#if defined(HAVE_ACC)
|
||||
uint8_t iv_tmp[16];
|
||||
uint8_t rk[AES_RKSIZE];
|
||||
|
||||
if (aes_supported())
|
||||
{
|
||||
if (key == NULL || iv == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
memcpy(iv_tmp, iv, 16);
|
||||
aes_setkey_dec(rk, key);
|
||||
aes_crypt_cbc(AES_DECRYPT, rk, \
|
||||
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)
|
||||
{
|
||||
#if defined(HAVE_ACC)
|
||||
uint8_t rk[AES_RKSIZE];
|
||||
|
||||
if (aes_supported())
|
||||
{
|
||||
if (key == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
aes_setkey_enc(rk, key);
|
||||
aes_crypt_ecb(AES_NR, rk, AES_ENCRYPT, input, output);
|
||||
return;
|
||||
}
|
||||
#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)
|
||||
{
|
||||
#if defined(HAVE_ACC)
|
||||
uint8_t rk[AES_RKSIZE];
|
||||
|
||||
if (aes_supported())
|
||||
{
|
||||
if (key == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
aes_setkey_dec(rk, key);
|
||||
aes_crypt_ecb(AES_NR, rk, AES_DECRYPT, input, output);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
AES_ECB_decrypt0(input, key, output, length);
|
||||
}
|
20
lib/aes_acc/aesacc.h
Normal file
20
lib/aes_acc/aesacc.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#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_ */
|
115
lib/aes_acc/aesarm.c
Normal file
115
lib/aes_acc/aesarm.c
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* This file is adapted from https://github.com/CriticalBlue/mbedtls
|
||||
*/
|
||||
|
||||
/*
|
||||
* ARMv8-A Cryptography Extension AES support functions
|
||||
*
|
||||
* Copyright (C) 2016, CriticalBlue Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
|
||||
#include "aesarm.h"
|
||||
|
||||
#if defined(HAVE_ARM64)
|
||||
|
||||
#include <sys/auxv.h>
|
||||
#include <asm/hwcap.h>
|
||||
#include <arm_neon.h>
|
||||
|
||||
/*
|
||||
* ARMv8a Crypto Extension support detection routine
|
||||
*/
|
||||
int aesarm_supported( void )
|
||||
{
|
||||
static int done = 0;
|
||||
static unsigned int c = 0;
|
||||
|
||||
if ( ! done )
|
||||
{
|
||||
c = getauxval(AT_HWCAP);
|
||||
done = 1;
|
||||
}
|
||||
|
||||
return ( c & HWCAP_AES ) != 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ARMv8a AES-ECB block en(de)cryption
|
||||
*/
|
||||
void aesarm_crypt_ecb( int nr,
|
||||
unsigned char *rk,
|
||||
int mode,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] )
|
||||
{
|
||||
int i;
|
||||
uint8x16_t state_vec, roundkey_vec;
|
||||
uint8_t *RK = (uint8_t *) rk;
|
||||
|
||||
// Load input and round key into into their vectors
|
||||
state_vec = vld1q_u8( input );
|
||||
|
||||
if ( mode == AES_ENCRYPT )
|
||||
{
|
||||
// Initial AddRoundKey is in the loop due to AES instruction always doing AddRoundKey first
|
||||
for( i = 0; i < nr - 1; i++ )
|
||||
{
|
||||
// Load Round Key
|
||||
roundkey_vec = vld1q_u8( RK );
|
||||
// Forward (AESE) round (AddRoundKey, SubBytes and ShiftRows)
|
||||
state_vec = vaeseq_u8( state_vec, roundkey_vec );
|
||||
// Mix Columns (AESMC)
|
||||
state_vec = vaesmcq_u8( state_vec );
|
||||
// Move pointer ready to load next round key
|
||||
RK += 16;
|
||||
}
|
||||
|
||||
// Final Forward (AESE) round (AddRoundKey, SubBytes and ShiftRows). No Mix columns
|
||||
roundkey_vec = vld1q_u8( RK ); /* RK already moved in loop */
|
||||
state_vec = vaeseq_u8( state_vec, roundkey_vec );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Initial AddRoundKey is in the loop due to AES instruction always doing AddRoundKey first
|
||||
for( i = 0; i < nr - 1; i++ )
|
||||
{
|
||||
// Load Round Key
|
||||
roundkey_vec = vld1q_u8( RK );
|
||||
// Reverse (AESD) round (AddRoundKey, SubBytes and ShiftRows)
|
||||
state_vec = vaesdq_u8( state_vec, roundkey_vec );
|
||||
// Inverse Mix Columns (AESIMC)
|
||||
state_vec = vaesimcq_u8( state_vec );
|
||||
// Move pointer ready to load next round key
|
||||
RK += 16;
|
||||
}
|
||||
|
||||
// Final Reverse (AESD) round (AddRoundKey, SubBytes and ShiftRows). No Mix columns
|
||||
roundkey_vec = vld1q_u8( RK ); /* RK already moved in loop */
|
||||
state_vec = vaesdq_u8( state_vec, roundkey_vec );
|
||||
}
|
||||
|
||||
// Manually apply final Add RoundKey step (EOR)
|
||||
RK += 16;
|
||||
roundkey_vec = vld1q_u8( RK );
|
||||
state_vec = veorq_u8( state_vec, roundkey_vec );
|
||||
|
||||
// Write results back to output array
|
||||
vst1q_u8( output, state_vec );
|
||||
}
|
||||
|
||||
#endif /* HAVE_ARM64 */
|
84
lib/aes_acc/aesarm.h
Normal file
84
lib/aes_acc/aesarm.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* This file is adapted from https://github.com/CriticalBlue/mbedtls
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file aes_armv8a_ce.h
|
||||
*
|
||||
* \brief AES support functions using the ARMv8-A Cryptography Extension for
|
||||
* hardware acceleration on some ARM processors.
|
||||
*
|
||||
* Copyright (C) 2016, CriticalBlue Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*/
|
||||
|
||||
#ifndef _AESARM_H_
|
||||
#define _AESARM_H_
|
||||
|
||||
#ifndef AES_ENCRYPT
|
||||
#define AES_ENCRYPT 1
|
||||
#endif
|
||||
|
||||
#ifndef AES_DECRYPT
|
||||
#define AES_DECRYPT 0
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && \
|
||||
__ARM_ARCH >= 8 && \
|
||||
__ARM_ARCH_PROFILE == 'A' && \
|
||||
defined(__aarch64__) && \
|
||||
defined(__ARM_FEATURE_CRYPTO) && \
|
||||
defined(__linux__) && \
|
||||
!defined(NO_AESACC)
|
||||
#define HAVE_ARM64
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_ARM64)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief ARMv8-A features detection routine
|
||||
*
|
||||
* \return 1 if the CPU has support for the feature, 0 otherwise
|
||||
*/
|
||||
int aesarm_supported( void );
|
||||
|
||||
/**
|
||||
* \brief AES ARMv8-A Cryptography Extension AES-ECB block en(de)cryption
|
||||
*
|
||||
* \param nr number of rounds
|
||||
* \param rk AES round keys
|
||||
* \param mode AESARM_ENCRYPT or AESARM_DECRYPT
|
||||
* \param input 16-byte input block
|
||||
* \param output 16-byte output block
|
||||
*/
|
||||
void aesarm_crypt_ecb( int nr,
|
||||
unsigned char *rk,
|
||||
int mode,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAVE_ARM64 */
|
||||
|
||||
#endif /* _AESARM_H_ */
|
140
lib/aes_acc/aesarm_table.h
Normal file
140
lib/aes_acc/aesarm_table.h
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* This file is adapted from PolarSSL 1.3.19 (GPL)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Forward S-box
|
||||
*/
|
||||
static const unsigned char FSb[256] =
|
||||
{
|
||||
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
|
||||
};
|
||||
|
||||
/*
|
||||
* Round constants
|
||||
*/
|
||||
static const uint32_t RCON[10] =
|
||||
{
|
||||
0x00000001, 0x00000002, 0x00000004, 0x00000008,
|
||||
0x00000010, 0x00000020, 0x00000040, 0x00000080,
|
||||
0x0000001B, 0x00000036
|
||||
};
|
||||
|
||||
/*
|
||||
* Reverse tables
|
||||
*/
|
||||
#define RT \
|
||||
\
|
||||
V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \
|
||||
V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \
|
||||
V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \
|
||||
V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \
|
||||
V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \
|
||||
V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \
|
||||
V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \
|
||||
V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \
|
||||
V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \
|
||||
V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \
|
||||
V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \
|
||||
V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \
|
||||
V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \
|
||||
V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \
|
||||
V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \
|
||||
V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \
|
||||
V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \
|
||||
V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \
|
||||
V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \
|
||||
V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \
|
||||
V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \
|
||||
V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \
|
||||
V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \
|
||||
V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \
|
||||
V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \
|
||||
V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \
|
||||
V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \
|
||||
V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \
|
||||
V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \
|
||||
V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \
|
||||
V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \
|
||||
V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \
|
||||
V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \
|
||||
V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \
|
||||
V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \
|
||||
V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \
|
||||
V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \
|
||||
V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \
|
||||
V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \
|
||||
V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \
|
||||
V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \
|
||||
V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \
|
||||
V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \
|
||||
V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \
|
||||
V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \
|
||||
V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \
|
||||
V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \
|
||||
V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \
|
||||
V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \
|
||||
V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \
|
||||
V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \
|
||||
V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \
|
||||
V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \
|
||||
V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \
|
||||
V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \
|
||||
V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \
|
||||
V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \
|
||||
V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \
|
||||
V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \
|
||||
V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \
|
||||
V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \
|
||||
V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \
|
||||
V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \
|
||||
V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0)
|
||||
|
||||
#define V(a,b,c,d) 0x##a##b##c##d
|
||||
static const uint32_t RT0[256] = { RT };
|
||||
#undef V
|
||||
|
||||
#define V(a,b,c,d) 0x##b##c##d##a
|
||||
static const uint32_t RT1[256] = { RT };
|
||||
#undef V
|
||||
|
||||
#define V(a,b,c,d) 0x##c##d##a##b
|
||||
static const uint32_t RT2[256] = { RT };
|
||||
#undef V
|
||||
|
||||
#define V(a,b,c,d) 0x##d##a##b##c
|
||||
static const uint32_t RT3[256] = { RT };
|
||||
#undef V
|
||||
|
||||
#undef RT
|
327
lib/aes_acc/aesni.c
Normal file
327
lib/aes_acc/aesni.c
Normal file
@@ -0,0 +1,327 @@
|
||||
/*
|
||||
* This file is adapted from PolarSSL 1.3.19 (GPL)
|
||||
*/
|
||||
|
||||
/*
|
||||
* AES-NI support functions
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* [AES-WP] http://software.intel.com/en-us/articles/intel-advanced-encryption-standard-aes-instructions-set
|
||||
* [CLMUL-WP] http://software.intel.com/en-us/articles/intel-carry-less-multiplication-instruction-and-its-usage-for-computing-the-gcm-mode/
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "aesni.h"
|
||||
|
||||
#if defined(HAVE_AMD64)
|
||||
|
||||
/*
|
||||
* AES-NI support detection routine
|
||||
*/
|
||||
#define AESNI_AES 0x02000000u
|
||||
|
||||
int aesni_supported( void )
|
||||
{
|
||||
static int done = 0;
|
||||
static unsigned int c = 0;
|
||||
|
||||
if( ! done )
|
||||
{
|
||||
asm( "movl $1, %%eax \n\t"
|
||||
"cpuid \n\t"
|
||||
: "=c" (c)
|
||||
:
|
||||
: "eax", "ebx", "edx" );
|
||||
done = 1;
|
||||
}
|
||||
|
||||
return( ( c & AESNI_AES ) != 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Binutils needs to be at least 2.19 to support AES-NI instructions.
|
||||
* Unfortunately, a lot of users have a lower version now (2014-04).
|
||||
* Emit bytecode directly in order to support "old" version of gas.
|
||||
*
|
||||
* Opcodes from the Intel architecture reference manual, vol. 3.
|
||||
* We always use registers, so we don't need prefixes for memory operands.
|
||||
* Operand macros are in gas order (src, dst) as opposed to Intel order
|
||||
* (dst, src) in order to blend better into the surrounding assembly code.
|
||||
*/
|
||||
#define AESDEC ".byte 0x66,0x0F,0x38,0xDE,"
|
||||
#define AESDECLAST ".byte 0x66,0x0F,0x38,0xDF,"
|
||||
#define AESENC ".byte 0x66,0x0F,0x38,0xDC,"
|
||||
#define AESENCLAST ".byte 0x66,0x0F,0x38,0xDD,"
|
||||
#define AESIMC ".byte 0x66,0x0F,0x38,0xDB,"
|
||||
#define AESKEYGENA ".byte 0x66,0x0F,0x3A,0xDF,"
|
||||
#define PCLMULQDQ ".byte 0x66,0x0F,0x3A,0x44,"
|
||||
|
||||
#define xmm0_xmm0 "0xC0"
|
||||
#define xmm0_xmm1 "0xC8"
|
||||
#define xmm0_xmm2 "0xD0"
|
||||
#define xmm0_xmm3 "0xD8"
|
||||
#define xmm0_xmm4 "0xE0"
|
||||
#define xmm1_xmm0 "0xC1"
|
||||
#define xmm1_xmm2 "0xD1"
|
||||
|
||||
/*
|
||||
* AES-NI AES-ECB block en(de)cryption
|
||||
*/
|
||||
int aesni_crypt_ecb( int nr,
|
||||
unsigned char *rk,
|
||||
int mode,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] )
|
||||
{
|
||||
asm( "movdqu (%3), %%xmm0 \n\t" // load input
|
||||
"movdqu (%1), %%xmm1 \n\t" // load round key 0
|
||||
"pxor %%xmm1, %%xmm0 \n\t" // round 0
|
||||
"addq $16, %1 \n\t" // point to next round key
|
||||
"subl $1, %0 \n\t" // normal rounds = nr - 1
|
||||
"test %2, %2 \n\t" // mode?
|
||||
"jz 2f \n\t" // 0 = decrypt
|
||||
|
||||
"1: \n\t" // encryption loop
|
||||
"movdqu (%1), %%xmm1 \n\t" // load round key
|
||||
AESENC xmm1_xmm0 "\n\t" // do round
|
||||
"addq $16, %1 \n\t" // point to next round key
|
||||
"subl $1, %0 \n\t" // loop
|
||||
"jnz 1b \n\t"
|
||||
"movdqu (%1), %%xmm1 \n\t" // load round key
|
||||
AESENCLAST xmm1_xmm0 "\n\t" // last round
|
||||
"jmp 3f \n\t"
|
||||
|
||||
"2: \n\t" // decryption loop
|
||||
"movdqu (%1), %%xmm1 \n\t"
|
||||
AESDEC xmm1_xmm0 "\n\t" // do round
|
||||
"addq $16, %1 \n\t"
|
||||
"subl $1, %0 \n\t"
|
||||
"jnz 2b \n\t"
|
||||
"movdqu (%1), %%xmm1 \n\t" // load round key
|
||||
AESDECLAST xmm1_xmm0 "\n\t" // last round
|
||||
|
||||
"3: \n\t"
|
||||
"movdqu %%xmm0, (%4) \n\t" // export output
|
||||
:
|
||||
: "r" (nr), "r" (rk), "r" (mode), "r" (input), "r" (output)
|
||||
: "memory", "cc", "xmm0", "xmm1" );
|
||||
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute decryption round keys from encryption round keys
|
||||
*/
|
||||
void aesni_inverse_key( unsigned char *invkey,
|
||||
const unsigned char *fwdkey, int nr )
|
||||
{
|
||||
unsigned char *ik = invkey;
|
||||
const unsigned char *fk = fwdkey + 16 * nr;
|
||||
|
||||
memcpy( ik, fk, 16 );
|
||||
|
||||
for( fk -= 16, ik += 16; fk > fwdkey; fk -= 16, ik += 16 )
|
||||
asm( "movdqu (%0), %%xmm0 \n\t"
|
||||
AESIMC xmm0_xmm0 "\n\t"
|
||||
"movdqu %%xmm0, (%1) \n\t"
|
||||
:
|
||||
: "r" (fk), "r" (ik)
|
||||
: "memory", "xmm0" );
|
||||
|
||||
memcpy( ik, fk, 16 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Key expansion, 128-bit case
|
||||
*/
|
||||
void aesni_setkey_enc_128( unsigned char *rk,
|
||||
const unsigned char *key )
|
||||
{
|
||||
asm( "movdqu (%1), %%xmm0 \n\t" // copy the original key
|
||||
"movdqu %%xmm0, (%0) \n\t" // as round key 0
|
||||
"jmp 2f \n\t" // skip auxiliary routine
|
||||
|
||||
/*
|
||||
* Finish generating the next round key.
|
||||
*
|
||||
* On entry xmm0 is r3:r2:r1:r0 and xmm1 is X:stuff:stuff:stuff
|
||||
* with X = rot( sub( r3 ) ) ^ RCON.
|
||||
*
|
||||
* On exit, xmm0 is r7:r6:r5:r4
|
||||
* with r4 = X + r0, r5 = r4 + r1, r6 = r5 + r2, r7 = r6 + r3
|
||||
* and those are written to the round key buffer.
|
||||
*/
|
||||
"1: \n\t"
|
||||
"pshufd $0xff, %%xmm1, %%xmm1 \n\t" // X:X:X:X
|
||||
"pxor %%xmm0, %%xmm1 \n\t" // X+r3:X+r2:X+r1:r4
|
||||
"pslldq $4, %%xmm0 \n\t" // r2:r1:r0:0
|
||||
"pxor %%xmm0, %%xmm1 \n\t" // X+r3+r2:X+r2+r1:r5:r4
|
||||
"pslldq $4, %%xmm0 \n\t" // etc
|
||||
"pxor %%xmm0, %%xmm1 \n\t"
|
||||
"pslldq $4, %%xmm0 \n\t"
|
||||
"pxor %%xmm1, %%xmm0 \n\t" // update xmm0 for next time!
|
||||
"add $16, %0 \n\t" // point to next round key
|
||||
"movdqu %%xmm0, (%0) \n\t" // write it
|
||||
"ret \n\t"
|
||||
|
||||
/* Main "loop" */
|
||||
"2: \n\t"
|
||||
AESKEYGENA xmm0_xmm1 ",0x01 \n\tcall 1b \n\t"
|
||||
AESKEYGENA xmm0_xmm1 ",0x02 \n\tcall 1b \n\t"
|
||||
AESKEYGENA xmm0_xmm1 ",0x04 \n\tcall 1b \n\t"
|
||||
AESKEYGENA xmm0_xmm1 ",0x08 \n\tcall 1b \n\t"
|
||||
AESKEYGENA xmm0_xmm1 ",0x10 \n\tcall 1b \n\t"
|
||||
AESKEYGENA xmm0_xmm1 ",0x20 \n\tcall 1b \n\t"
|
||||
AESKEYGENA xmm0_xmm1 ",0x40 \n\tcall 1b \n\t"
|
||||
AESKEYGENA xmm0_xmm1 ",0x80 \n\tcall 1b \n\t"
|
||||
AESKEYGENA xmm0_xmm1 ",0x1B \n\tcall 1b \n\t"
|
||||
AESKEYGENA xmm0_xmm1 ",0x36 \n\tcall 1b \n\t"
|
||||
:
|
||||
: "r" (rk), "r" (key)
|
||||
: "memory", "cc", "0" );
|
||||
}
|
||||
|
||||
/*
|
||||
* Key expansion, 192-bit case
|
||||
*/
|
||||
void aesni_setkey_enc_192( unsigned char *rk,
|
||||
const unsigned char *key )
|
||||
{
|
||||
asm( "movdqu (%1), %%xmm0 \n\t" // copy original round key
|
||||
"movdqu %%xmm0, (%0) \n\t"
|
||||
"add $16, %0 \n\t"
|
||||
"movq 16(%1), %%xmm1 \n\t"
|
||||
"movq %%xmm1, (%0) \n\t"
|
||||
"add $8, %0 \n\t"
|
||||
"jmp 2f \n\t" // skip auxiliary routine
|
||||
|
||||
/*
|
||||
* Finish generating the next 6 quarter-keys.
|
||||
*
|
||||
* On entry xmm0 is r3:r2:r1:r0, xmm1 is stuff:stuff:r5:r4
|
||||
* and xmm2 is stuff:stuff:X:stuff with X = rot( sub( r3 ) ) ^ RCON.
|
||||
*
|
||||
* On exit, xmm0 is r9:r8:r7:r6 and xmm1 is stuff:stuff:r11:r10
|
||||
* and those are written to the round key buffer.
|
||||
*/
|
||||
"1: \n\t"
|
||||
"pshufd $0x55, %%xmm2, %%xmm2 \n\t" // X:X:X:X
|
||||
"pxor %%xmm0, %%xmm2 \n\t" // X+r3:X+r2:X+r1:r4
|
||||
"pslldq $4, %%xmm0 \n\t" // etc
|
||||
"pxor %%xmm0, %%xmm2 \n\t"
|
||||
"pslldq $4, %%xmm0 \n\t"
|
||||
"pxor %%xmm0, %%xmm2 \n\t"
|
||||
"pslldq $4, %%xmm0 \n\t"
|
||||
"pxor %%xmm2, %%xmm0 \n\t" // update xmm0 = r9:r8:r7:r6
|
||||
"movdqu %%xmm0, (%0) \n\t"
|
||||
"add $16, %0 \n\t"
|
||||
"pshufd $0xff, %%xmm0, %%xmm2 \n\t" // r9:r9:r9:r9
|
||||
"pxor %%xmm1, %%xmm2 \n\t" // stuff:stuff:r9+r5:r10
|
||||
"pslldq $4, %%xmm1 \n\t" // r2:r1:r0:0
|
||||
"pxor %%xmm2, %%xmm1 \n\t" // xmm1 = stuff:stuff:r11:r10
|
||||
"movq %%xmm1, (%0) \n\t"
|
||||
"add $8, %0 \n\t"
|
||||
"ret \n\t"
|
||||
|
||||
"2: \n\t"
|
||||
AESKEYGENA xmm1_xmm2 ",0x01 \n\tcall 1b \n\t"
|
||||
AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t"
|
||||
AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t"
|
||||
AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t"
|
||||
AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t"
|
||||
AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t"
|
||||
AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t"
|
||||
AESKEYGENA xmm1_xmm2 ",0x80 \n\tcall 1b \n\t"
|
||||
|
||||
:
|
||||
: "r" (rk), "r" (key)
|
||||
: "memory", "cc", "0" );
|
||||
}
|
||||
|
||||
/*
|
||||
* Key expansion, 256-bit case
|
||||
*/
|
||||
void aesni_setkey_enc_256( unsigned char *rk,
|
||||
const unsigned char *key )
|
||||
{
|
||||
asm( "movdqu (%1), %%xmm0 \n\t"
|
||||
"movdqu %%xmm0, (%0) \n\t"
|
||||
"add $16, %0 \n\t"
|
||||
"movdqu 16(%1), %%xmm1 \n\t"
|
||||
"movdqu %%xmm1, (%0) \n\t"
|
||||
"jmp 2f \n\t" // skip auxiliary routine
|
||||
|
||||
/*
|
||||
* Finish generating the next two round keys.
|
||||
*
|
||||
* On entry xmm0 is r3:r2:r1:r0, xmm1 is r7:r6:r5:r4 and
|
||||
* xmm2 is X:stuff:stuff:stuff with X = rot( sub( r7 )) ^ RCON
|
||||
*
|
||||
* On exit, xmm0 is r11:r10:r9:r8 and xmm1 is r15:r14:r13:r12
|
||||
* and those have been written to the output buffer.
|
||||
*/
|
||||
"1: \n\t"
|
||||
"pshufd $0xff, %%xmm2, %%xmm2 \n\t"
|
||||
"pxor %%xmm0, %%xmm2 \n\t"
|
||||
"pslldq $4, %%xmm0 \n\t"
|
||||
"pxor %%xmm0, %%xmm2 \n\t"
|
||||
"pslldq $4, %%xmm0 \n\t"
|
||||
"pxor %%xmm0, %%xmm2 \n\t"
|
||||
"pslldq $4, %%xmm0 \n\t"
|
||||
"pxor %%xmm2, %%xmm0 \n\t"
|
||||
"add $16, %0 \n\t"
|
||||
"movdqu %%xmm0, (%0) \n\t"
|
||||
|
||||
/* Set xmm2 to stuff:Y:stuff:stuff with Y = subword( r11 )
|
||||
* and proceed to generate next round key from there */
|
||||
AESKEYGENA xmm0_xmm2 ",0x00 \n\t"
|
||||
"pshufd $0xaa, %%xmm2, %%xmm2 \n\t"
|
||||
"pxor %%xmm1, %%xmm2 \n\t"
|
||||
"pslldq $4, %%xmm1 \n\t"
|
||||
"pxor %%xmm1, %%xmm2 \n\t"
|
||||
"pslldq $4, %%xmm1 \n\t"
|
||||
"pxor %%xmm1, %%xmm2 \n\t"
|
||||
"pslldq $4, %%xmm1 \n\t"
|
||||
"pxor %%xmm2, %%xmm1 \n\t"
|
||||
"add $16, %0 \n\t"
|
||||
"movdqu %%xmm1, (%0) \n\t"
|
||||
"ret \n\t"
|
||||
|
||||
/*
|
||||
* Main "loop" - Generating one more key than necessary,
|
||||
* see definition of aes_context.buf
|
||||
*/
|
||||
"2: \n\t"
|
||||
AESKEYGENA xmm1_xmm2 ",0x01 \n\tcall 1b \n\t"
|
||||
AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t"
|
||||
AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t"
|
||||
AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t"
|
||||
AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t"
|
||||
AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t"
|
||||
AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t"
|
||||
:
|
||||
: "r" (rk), "r" (key)
|
||||
: "memory", "cc", "0" );
|
||||
}
|
||||
|
||||
#endif /* HAVE_AMD64 */
|
119
lib/aes_acc/aesni.h
Normal file
119
lib/aes_acc/aesni.h
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* This file is adapted from PolarSSL 1.3.19 (GPL)
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file aesni.h
|
||||
*
|
||||
* \brief AES-NI for hardware AES acceleration on some Intel processors
|
||||
*
|
||||
* Copyright (C) 2013, 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.
|
||||
*/
|
||||
|
||||
#ifndef _AESNI_H_
|
||||
#define _AESNI_H_
|
||||
|
||||
#ifndef AES_ENCRYPT
|
||||
#define AES_ENCRYPT 1
|
||||
#endif
|
||||
|
||||
#ifndef AES_DECRYPT
|
||||
#define AES_DECRYPT 0
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && \
|
||||
( defined(__amd64__) || defined(__x86_64__) ) && \
|
||||
!defined(NO_AESACC)
|
||||
#define HAVE_AMD64
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_AMD64)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief AES-NI features detection routine
|
||||
*
|
||||
* \return 1 if CPU has support for AES-NI, 0 otherwise
|
||||
*/
|
||||
int aesni_supported( void );
|
||||
|
||||
/**
|
||||
* \brief AES-NI AES-ECB block en(de)cryption
|
||||
*
|
||||
* \param nr number of rounds
|
||||
* \param rk AES round keys
|
||||
* \param mode AES_ENCRYPT or AES_DECRYPT
|
||||
* \param input 16-byte input block
|
||||
* \param output 16-byte output block
|
||||
*
|
||||
* \return 0 on success (cannot fail)
|
||||
*/
|
||||
int aesni_crypt_ecb( int nr,
|
||||
unsigned char *rk,
|
||||
int mode,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] );
|
||||
|
||||
/**
|
||||
* \brief Compute decryption round keys from encryption round keys
|
||||
*
|
||||
* \param invkey Round keys for the equivalent inverse cipher
|
||||
* \param fwdkey Original round keys (for encryption)
|
||||
* \param nr Number of rounds (that is, number of round keys minus one)
|
||||
*/
|
||||
void aesni_inverse_key( unsigned char *invkey,
|
||||
const unsigned char *fwdkey, int nr );
|
||||
|
||||
/**
|
||||
* \brief Perform 128-bit key expansion (for encryption)
|
||||
*
|
||||
* \param rk Destination buffer where the round keys are written
|
||||
* \param key Encryption key
|
||||
*/
|
||||
void aesni_setkey_enc_128( unsigned char *rk,
|
||||
const unsigned char *key );
|
||||
|
||||
/**
|
||||
* \brief Perform 192-bit key expansion (for encryption)
|
||||
*
|
||||
* \param rk Destination buffer where the round keys are written
|
||||
* \param key Encryption key
|
||||
*/
|
||||
void aesni_setkey_enc_192( unsigned char *rk,
|
||||
const unsigned char *key );
|
||||
|
||||
/**
|
||||
* \brief Perform 256-bit key expansion (for encryption)
|
||||
*
|
||||
* \param rk Destination buffer where the round keys are written
|
||||
* \param key Encryption key
|
||||
*/
|
||||
void aesni_setkey_enc_256( unsigned char *rk,
|
||||
const unsigned char *key );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HAVE_AMD64 */
|
||||
|
||||
#endif /* _AESNI_H_ */
|
1194
lib/aes_acc/asm/arm.S
Normal file
1194
lib/aes_acc/asm/arm.S
Normal file
File diff suppressed because it is too large
Load Diff
83
lib/aes_acc/asm/arm_arch.h
Normal file
83
lib/aes_acc/asm/arm_arch.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#ifndef __ARM_ARCH_H__
|
||||
# define __ARM_ARCH_H__
|
||||
|
||||
# if !defined(__ARM_ARCH__)
|
||||
# if defined(__CC_ARM)
|
||||
# define __ARM_ARCH__ __TARGET_ARCH_ARM
|
||||
# if defined(__BIG_ENDIAN)
|
||||
# define __ARMEB__
|
||||
# else
|
||||
# define __ARMEL__
|
||||
# endif
|
||||
# elif defined(__GNUC__)
|
||||
# if defined(__aarch64__)
|
||||
# define __ARM_ARCH__ 8
|
||||
# if __BYTE_ORDER__==__ORDER_BIG_ENDIAN__
|
||||
# define __ARMEB__
|
||||
# else
|
||||
# define __ARMEL__
|
||||
# endif
|
||||
/*
|
||||
* Why doesn't gcc define __ARM_ARCH__? Instead it defines
|
||||
* bunch of below macros. See all_architectires[] table in
|
||||
* gcc/config/arm/arm.c. On a side note it defines
|
||||
* __ARMEL__/__ARMEB__ for little-/big-endian.
|
||||
*/
|
||||
# elif defined(__ARM_ARCH)
|
||||
# define __ARM_ARCH__ __ARM_ARCH
|
||||
# elif defined(__ARM_ARCH_8A__)
|
||||
# define __ARM_ARCH__ 8
|
||||
# elif defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || \
|
||||
defined(__ARM_ARCH_7R__)|| defined(__ARM_ARCH_7M__) || \
|
||||
defined(__ARM_ARCH_7EM__)
|
||||
# define __ARM_ARCH__ 7
|
||||
# elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \
|
||||
defined(__ARM_ARCH_6K__)|| defined(__ARM_ARCH_6M__) || \
|
||||
defined(__ARM_ARCH_6Z__)|| defined(__ARM_ARCH_6ZK__) || \
|
||||
defined(__ARM_ARCH_6T2__)
|
||||
# define __ARM_ARCH__ 6
|
||||
# elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) || \
|
||||
defined(__ARM_ARCH_5E__)|| defined(__ARM_ARCH_5TE__) || \
|
||||
defined(__ARM_ARCH_5TEJ__)
|
||||
# define __ARM_ARCH__ 5
|
||||
# elif defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)
|
||||
# define __ARM_ARCH__ 4
|
||||
# else
|
||||
# error "unsupported ARM architecture"
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if !defined(__ARM_MAX_ARCH__)
|
||||
# define __ARM_MAX_ARCH__ __ARM_ARCH__
|
||||
# endif
|
||||
|
||||
# if __ARM_MAX_ARCH__<__ARM_ARCH__
|
||||
# error "__ARM_MAX_ARCH__ can't be less than __ARM_ARCH__"
|
||||
# elif __ARM_MAX_ARCH__!=__ARM_ARCH__
|
||||
# if __ARM_ARCH__<7 && __ARM_MAX_ARCH__>=7 && defined(__ARMEB__)
|
||||
# error "can't build universal big-endian binary"
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if !__ASSEMBLER__
|
||||
extern unsigned int OPENSSL_armcap_P;
|
||||
# endif
|
||||
|
||||
# define ARMV7_NEON (1<<0)
|
||||
# define ARMV7_TICK (1<<1)
|
||||
# define ARMV8_AES (1<<2)
|
||||
# define ARMV8_SHA1 (1<<3)
|
||||
# define ARMV8_SHA256 (1<<4)
|
||||
# define ARMV8_PMULL (1<<5)
|
||||
|
||||
#endif
|
1835
lib/aes_acc/asm/mips.S
Normal file
1835
lib/aes_acc/asm/mips.S
Normal file
File diff suppressed because it is too large
Load Diff
3244
lib/aes_acc/asm/x86.S
Normal file
3244
lib/aes_acc/asm/x86.S
Normal file
File diff suppressed because it is too large
Load Diff
187
main.cpp
187
main.cpp
@@ -3,8 +3,10 @@
|
||||
#include "log.h"
|
||||
#include "lib/md5.h"
|
||||
|
||||
char local_address[100]="0.0.0.0", remote_address[100]="255.255.255.255",source_address[100]="0.0.0.0";
|
||||
u32_t local_address_uint32,remote_address_uint32,source_address_uint32;
|
||||
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;
|
||||
|
||||
int force_source_ip=0;
|
||||
int source_port=0,local_port = -1, remote_port = -1;
|
||||
|
||||
id_t const_id=0;
|
||||
@@ -234,6 +236,8 @@ struct conv_manager_t //TODO change map to unordered map
|
||||
int size=conv_last_active_time.size();
|
||||
int num_to_clean=size/conv_clear_ratio+conv_clear_min; //clear 1/10 each time,to avoid latency glitch
|
||||
|
||||
num_to_clean=min(num_to_clean,size);
|
||||
|
||||
u64_t current_time=get_current_time();
|
||||
for(;;)
|
||||
{
|
||||
@@ -860,12 +864,12 @@ int try_to_list_and_bind(int port)
|
||||
close(old_bind_fd);
|
||||
}
|
||||
|
||||
struct sockaddr_in temp_bind_addr;
|
||||
bzero(&temp_bind_addr, sizeof(temp_bind_addr));
|
||||
struct sockaddr_in temp_bind_addr={0};
|
||||
//bzero(&temp_bind_addr, sizeof(temp_bind_addr));
|
||||
|
||||
temp_bind_addr.sin_family = AF_INET;
|
||||
temp_bind_addr.sin_port = htons(port);
|
||||
temp_bind_addr.sin_addr.s_addr = local_address_uint32;
|
||||
temp_bind_addr.sin_addr.s_addr = local_ip_uint32;
|
||||
|
||||
if (bind(bind_fd, (struct sockaddr*)&temp_bind_addr, sizeof(temp_bind_addr)) !=0)
|
||||
{
|
||||
@@ -959,8 +963,7 @@ int set_timer_server(int epollfd,int &timer_fd)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int get_src_adress(u32_t &ip);
|
||||
int client_on_timer(conn_info_t &conn_info) //for client
|
||||
{
|
||||
packet_info_t &send_info=conn_info.raw_info.send_info;
|
||||
@@ -985,6 +988,18 @@ int client_on_timer(conn_info_t &conn_info) //for client
|
||||
conn_info.blob->anti_replay.re_init();
|
||||
conn_info.my_id = get_true_random_number_nz(); ///todo no need to do this everytime
|
||||
|
||||
u32_t new_ip=0;
|
||||
if(!force_source_ip&&get_src_adress(new_ip)==0)
|
||||
{
|
||||
if(new_ip!=source_ip_uint32)
|
||||
{
|
||||
mylog(log_info,"source ip changed from %s to ",my_ntoa(source_ip_uint32));
|
||||
log_bare(log_info,"%s\n",my_ntoa(new_ip));
|
||||
source_ip_uint32=new_ip;
|
||||
send_info.src_ip=new_ip;
|
||||
}
|
||||
}
|
||||
|
||||
if (source_port == 0)
|
||||
{
|
||||
send_info.src_port = client_bind_to_a_new_port();
|
||||
@@ -1375,7 +1390,7 @@ int client_on_raw_recv(conn_info_t &conn_info)
|
||||
u64_t u64=conn_info.blob->conv_manager.find_u64_by_conv(tmp_conv_id);
|
||||
|
||||
|
||||
sockaddr_in tmp_sockaddr;
|
||||
sockaddr_in tmp_sockaddr={0};
|
||||
|
||||
tmp_sockaddr.sin_family = AF_INET;
|
||||
tmp_sockaddr.sin_addr.s_addr=(u64>>32u);
|
||||
@@ -1417,10 +1432,13 @@ int server_on_raw_recv_multi()
|
||||
{
|
||||
recv(raw_recv_fd, 0,0, 0 );//
|
||||
//struct sockaddr saddr;
|
||||
//socklen_t saddr_size;
|
||||
//socklen_t saddr_size=sizeof(saddr);
|
||||
///recvfrom(raw_recv_fd, 0,0, 0 ,&saddr , &saddr_size);//
|
||||
mylog(log_trace,"peek_raw failed\n");
|
||||
return -1;
|
||||
}else
|
||||
{
|
||||
mylog(log_trace,"peek_raw success\n");
|
||||
}
|
||||
u32_t ip=peek_info.src_ip;uint16_t port=peek_info.src_port;
|
||||
|
||||
@@ -1544,9 +1562,11 @@ int server_on_raw_recv_multi()
|
||||
if(conn_info.state.server_current_state==server_ready)
|
||||
{
|
||||
char type;
|
||||
//mylog(log_info,"before recv_safer\n");
|
||||
if (recv_safer(conn_info,type, data, data_len) != 0) {
|
||||
return -1;
|
||||
}
|
||||
//mylog(log_info,"after recv_safer\n");
|
||||
return server_on_raw_recv_ready(conn_info,ip_port,type,data,data_len);
|
||||
}
|
||||
return 0;
|
||||
@@ -1663,13 +1683,13 @@ int server_on_raw_recv_ready(conn_info_t &conn_info,char * ip_port,char type,cha
|
||||
tmp_conv_id);
|
||||
return 0;
|
||||
}
|
||||
struct sockaddr_in remote_addr_in;
|
||||
struct sockaddr_in remote_addr_in={0};
|
||||
|
||||
socklen_t slen = sizeof(sockaddr_in);
|
||||
memset(&remote_addr_in, 0, sizeof(remote_addr_in));
|
||||
//memset(&remote_addr_in, 0, sizeof(remote_addr_in));
|
||||
remote_addr_in.sin_family = AF_INET;
|
||||
remote_addr_in.sin_port = htons(remote_port);
|
||||
remote_addr_in.sin_addr.s_addr = remote_address_uint32;
|
||||
remote_addr_in.sin_addr.s_addr = remote_ip_uint32;
|
||||
|
||||
int new_udp_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (new_udp_fd < 0) {
|
||||
@@ -1857,13 +1877,13 @@ int server_on_raw_recv_pre_ready(conn_info_t &conn_info,char * ip_port,u32_t tmp
|
||||
|
||||
int get_src_adress(u32_t &ip)
|
||||
{
|
||||
struct sockaddr_in remote_addr_in;
|
||||
struct sockaddr_in remote_addr_in={0};
|
||||
|
||||
socklen_t slen = sizeof(sockaddr_in);
|
||||
memset(&remote_addr_in, 0, sizeof(remote_addr_in));
|
||||
//memset(&remote_addr_in, 0, sizeof(remote_addr_in));
|
||||
remote_addr_in.sin_family = AF_INET;
|
||||
remote_addr_in.sin_port = htons(remote_port);
|
||||
remote_addr_in.sin_addr.s_addr = remote_address_uint32;
|
||||
remote_addr_in.sin_addr.s_addr = remote_ip_uint32;
|
||||
|
||||
|
||||
int new_udp_fd=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
@@ -1872,7 +1892,7 @@ int get_src_adress(u32_t &ip)
|
||||
mylog(log_warn,"create udp_fd error\n");
|
||||
return -1;
|
||||
}
|
||||
set_buf_size(new_udp_fd);
|
||||
//set_buf_size(new_udp_fd);
|
||||
|
||||
mylog(log_debug,"created new udp_fd %d\n",new_udp_fd);
|
||||
int ret = connect(new_udp_fd, (struct sockaddr *) &remote_addr_in, slen);
|
||||
@@ -1883,8 +1903,8 @@ int get_src_adress(u32_t &ip)
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct sockaddr_in my_addr;
|
||||
unsigned int len=sizeof(my_addr);
|
||||
struct sockaddr_in my_addr={0};
|
||||
socklen_t len=sizeof(my_addr);
|
||||
|
||||
if(getsockname(new_udp_fd, (struct sockaddr *) &my_addr, &len)!=0) return -1;
|
||||
|
||||
@@ -1894,6 +1914,7 @@ int get_src_adress(u32_t &ip)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int client_event_loop()
|
||||
{
|
||||
char buf[buf_len];
|
||||
@@ -1906,17 +1927,17 @@ int client_event_loop()
|
||||
packet_info_t &recv_info=conn_info.raw_info.recv_info;
|
||||
|
||||
//printf("?????\n");
|
||||
if(source_address_uint32==0)
|
||||
if(source_ip_uint32==0)
|
||||
{
|
||||
mylog(log_info,"get_src_adress called\n");
|
||||
if(get_src_adress(source_address_uint32)!=0)
|
||||
if(get_src_adress(source_ip_uint32)!=0)
|
||||
{
|
||||
mylog(log_fatal,"the trick to auto get source ip failed,you should specific an ip by --source-ip\n");
|
||||
myexit(-1);
|
||||
}
|
||||
}
|
||||
in_addr tmp;
|
||||
tmp.s_addr=source_address_uint32;
|
||||
tmp.s_addr=source_ip_uint32;
|
||||
mylog(log_info,"source ip = %s\n",inet_ntoa(tmp));
|
||||
//printf("done\n");
|
||||
|
||||
@@ -1927,13 +1948,13 @@ int client_event_loop()
|
||||
myexit(-1);
|
||||
}
|
||||
send_info.src_port=source_port;
|
||||
send_info.src_ip = source_address_uint32;
|
||||
send_info.src_ip = source_ip_uint32;
|
||||
|
||||
int i, j, k;int ret;
|
||||
init_raw_socket();
|
||||
|
||||
//init_filter(source_port);
|
||||
send_info.dst_ip=remote_address_uint32;
|
||||
send_info.dst_ip=remote_ip_uint32;
|
||||
send_info.dst_port=remote_port;
|
||||
|
||||
//g_packet_info.src_ip=source_address_uint32;
|
||||
@@ -1945,13 +1966,13 @@ int client_event_loop()
|
||||
int yes = 1;
|
||||
//setsockopt(udp_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
|
||||
|
||||
struct sockaddr_in local_me;
|
||||
struct sockaddr_in local_me={0};
|
||||
|
||||
socklen_t slen = sizeof(sockaddr_in);
|
||||
memset(&local_me, 0, sizeof(local_me));
|
||||
//memset(&local_me, 0, sizeof(local_me));
|
||||
local_me.sin_family = AF_INET;
|
||||
local_me.sin_port = htons(local_port);
|
||||
local_me.sin_addr.s_addr = local_address_uint32;
|
||||
local_me.sin_addr.s_addr = local_ip_uint32;
|
||||
|
||||
|
||||
if (bind(udp_fd, (struct sockaddr*) &local_me, slen) == -1) {
|
||||
@@ -2033,9 +2054,10 @@ int client_event_loop()
|
||||
{
|
||||
|
||||
int recv_len;
|
||||
struct sockaddr_in udp_new_addr_in;
|
||||
struct sockaddr_in udp_new_addr_in={0};
|
||||
socklen_t udp_new_addr_len = sizeof(sockaddr_in);
|
||||
if ((recv_len = recvfrom(udp_fd, buf, max_data_len, 0,
|
||||
(struct sockaddr *) &udp_new_addr_in, &slen)) == -1) {
|
||||
(struct sockaddr *) &udp_new_addr_in, &udp_new_addr_len)) == -1) {
|
||||
mylog(log_error,"recv_from error,this shouldnt happen at client\n");
|
||||
myexit(1);
|
||||
};
|
||||
@@ -2119,7 +2141,7 @@ int server_event_loop()
|
||||
|
||||
int i, j, k;int ret;
|
||||
|
||||
bind_address_uint32=local_address_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(raw_mode==mode_faketcp)
|
||||
@@ -2131,12 +2153,12 @@ int server_event_loop()
|
||||
bind_fd=socket(AF_INET,SOCK_DGRAM,0);
|
||||
}
|
||||
|
||||
struct sockaddr_in temp_bind_addr;
|
||||
bzero(&temp_bind_addr, sizeof(temp_bind_addr));
|
||||
struct sockaddr_in temp_bind_addr={0};
|
||||
// bzero(&temp_bind_addr, sizeof(temp_bind_addr));
|
||||
|
||||
temp_bind_addr.sin_family = AF_INET;
|
||||
temp_bind_addr.sin_port = htons(local_port);
|
||||
temp_bind_addr.sin_addr.s_addr = local_address_uint32;
|
||||
temp_bind_addr.sin_addr.s_addr = local_ip_uint32;
|
||||
|
||||
if (bind(bind_fd, (struct sockaddr*)&temp_bind_addr, sizeof(temp_bind_addr)) !=0)
|
||||
{
|
||||
@@ -2313,7 +2335,8 @@ int server_event_loop()
|
||||
|
||||
if(recv_len<0)
|
||||
{
|
||||
mylog(log_debug,"udp fd,recv_len<0 continue\n");
|
||||
mylog(log_debug,"udp fd,recv_len<0 continue,%s\n",strerror(errno));
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2347,7 +2370,26 @@ int server_event_loop()
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void process_lower_level()
|
||||
{
|
||||
if (strchr(optarg, '#') == 0) {
|
||||
mylog(log_fatal,
|
||||
"lower-level parameter invaild,check help page for format\n");
|
||||
myexit(-1);
|
||||
}
|
||||
lower_level = 1;
|
||||
u32_t hw[6];
|
||||
memset(hw, 0, sizeof(hw));
|
||||
sscanf(optarg, "%[^#]#%x:%x:%x:%x:%x:%x", if_name, &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, 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]);
|
||||
}
|
||||
}
|
||||
void print_help()
|
||||
{
|
||||
printf("udp2raw-tunnel\n");
|
||||
@@ -2361,8 +2403,8 @@ void print_help()
|
||||
printf("common options,these options must be same on both side:\n");
|
||||
printf(" --raw-mode <string> avaliable values:faketcp(default),udp,icmp\n");
|
||||
printf(" -k,--key <string> password to gen symetric key,default:\"secret key\"\n");
|
||||
printf(" --auth-mode <string> avaliable values:aes128cbc(default),xor,none\n");
|
||||
printf(" --cipher-mode <string> avaliable values:md5(default),crc32,simple,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(" -a,--auto-rule auto add (and delete) iptables rule\n");
|
||||
printf(" -g,--gen-rule generate iptables rule then exit\n");
|
||||
printf(" --disable-anti-replay disable anti-replay,not suggested\n");
|
||||
@@ -2388,6 +2430,8 @@ void print_help()
|
||||
printf(" 1:increase every packet\n");
|
||||
printf(" 2:increase randomly, about every 3 packets (default)\n");
|
||||
// printf("\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(" -h,--help print this help message\n");
|
||||
|
||||
//printf("common options,these options must be same on both side\n");
|
||||
@@ -2428,6 +2472,12 @@ void process_arg(int argc, char *argv[])
|
||||
myexit(0);
|
||||
}
|
||||
}
|
||||
if (argc == 1)
|
||||
{
|
||||
print_help();
|
||||
myexit(-1);
|
||||
}
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
{
|
||||
if(strcmp(argv[i],"--log-level")==0)
|
||||
@@ -2458,11 +2508,7 @@ void process_arg(int argc, char *argv[])
|
||||
}
|
||||
log_bare(log_info, "\n");
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
print_help();
|
||||
myexit(-1);
|
||||
}
|
||||
|
||||
|
||||
int no_l = 1, no_r = 1;
|
||||
while ((opt = getopt_long(argc, argv, "l:r:schk:ag",long_options,&option_index)) != -1) {
|
||||
@@ -2472,7 +2518,7 @@ void process_arg(int argc, char *argv[])
|
||||
case 'l':
|
||||
no_l = 0;
|
||||
if (strchr(optarg, ':') != 0) {
|
||||
sscanf(optarg, "%[^:]:%d", local_address, &local_port);
|
||||
sscanf(optarg, "%[^:]:%d", local_ip, &local_port);
|
||||
if(local_port==22)
|
||||
{
|
||||
mylog(log_fatal,"port 22 not allowed\n");
|
||||
@@ -2487,7 +2533,7 @@ void process_arg(int argc, char *argv[])
|
||||
case 'r':
|
||||
no_r = 0;
|
||||
if (strchr(optarg, ':') != 0) {
|
||||
sscanf(optarg, "%[^:]:%d", remote_address, &remote_port);
|
||||
sscanf(optarg, "%[^:]:%d", remote_ip, &remote_port);
|
||||
if(remote_port==22)
|
||||
{
|
||||
mylog(log_fatal,"port 22 not allowed\n");
|
||||
@@ -2536,7 +2582,10 @@ void process_arg(int argc, char *argv[])
|
||||
mylog(log_debug,"option_index: %d\n",option_index);
|
||||
if(strcmp(long_options[option_index].name,"clear")==0)
|
||||
{
|
||||
int ret =system("iptables-save |grep udp2raw_dWRwMnJhdw|sed -n 's/^-A/iptables -D/p'|sh");
|
||||
char *output;
|
||||
//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);
|
||||
|
||||
//system("iptables-save |grep udp2raw_dWRwMnJhdw|sed 's/^-A/iptables -D/'|sh");
|
||||
//system("iptables-save|grep -v udp2raw_dWRwMnJhdw|iptables-restore");
|
||||
mylog(log_info,"tried to clear all iptables rule created previously,return value %d\n",ret);
|
||||
@@ -2545,8 +2594,9 @@ void process_arg(int argc, char *argv[])
|
||||
else if(strcmp(long_options[option_index].name,"source-ip")==0)
|
||||
{
|
||||
mylog(log_debug,"parsing long option :source-ip\n");
|
||||
sscanf(optarg, "%s", source_address);
|
||||
mylog(log_debug,"source: %s\n",source_address);
|
||||
sscanf(optarg, "%s", source_ip);
|
||||
mylog(log_debug,"source: %s\n",source_ip);
|
||||
force_source_ip=1;
|
||||
}
|
||||
else if(strcmp(long_options[option_index].name,"source-port")==0)
|
||||
{
|
||||
@@ -2600,7 +2650,7 @@ void process_arg(int argc, char *argv[])
|
||||
}
|
||||
if(i==cipher_end)
|
||||
{
|
||||
mylog(log_fatal,"no such cipher_mode %s\n",optarg);
|
||||
|
||||
myexit(-1);
|
||||
}
|
||||
}
|
||||
@@ -2609,21 +2659,7 @@ void process_arg(int argc, char *argv[])
|
||||
}
|
||||
else if(strcmp(long_options[option_index].name,"lower-level")==0)
|
||||
{
|
||||
if(strchr(optarg,'#')==0)
|
||||
{
|
||||
mylog(log_fatal,"lower-level parameter invaild,should be if_name#mac_adress ,ie eth0#00:23:45:67:89:b9\n");
|
||||
myexit(-1);
|
||||
}
|
||||
lower_level=1;
|
||||
u32_t hw[6];
|
||||
memset(hw,0,sizeof(hw));
|
||||
sscanf(optarg,"%[^#]#%x:%x:%x:%x:%x:%x",if_name,&hw[0],&hw[1],&hw[2],&hw[3],&hw[4],&hw[5]);
|
||||
|
||||
mylog(log_warn,"make sure this is correct: ifname=<%s> gateway_hw_hd=<%x:%x:%x:%x:%x:%x> \n",if_name,hw[0],hw[1],hw[2],hw[3],hw[4],hw[5]);
|
||||
for(int i=0;i<6;i++)
|
||||
{
|
||||
oppsite_hw_addr[i]=uint8_t(hw[i]);
|
||||
}
|
||||
process_lower_level();
|
||||
}
|
||||
else if(strcmp(long_options[option_index].name,"disable-color")==0)
|
||||
{
|
||||
@@ -2709,11 +2745,11 @@ void process_arg(int argc, char *argv[])
|
||||
|
||||
log_bare(log_info,"key=%s ",key_string);
|
||||
|
||||
log_bare(log_info,"local_ip=%s ",local_address);
|
||||
log_bare(log_info,"local_ip=%s ",local_ip);
|
||||
log_bare(log_info,"local_port=%d ",local_port);
|
||||
log_bare(log_info,"remote_ip=%s ",remote_address);
|
||||
log_bare(log_info,"remote_ip=%s ",remote_ip);
|
||||
log_bare(log_info,"remote_port=%d ",remote_port);
|
||||
log_bare(log_info,"source_ip=%s ",source_address);
|
||||
log_bare(log_info,"source_ip=%s ",source_ip);
|
||||
log_bare(log_info,"source_port=%d ",source_port);
|
||||
|
||||
log_bare(log_info,"socket_buf_size=%d ",socket_buf_size);
|
||||
@@ -2727,17 +2763,17 @@ void iptables_rule()
|
||||
{
|
||||
if(raw_mode==mode_faketcp)
|
||||
{
|
||||
sprintf(rule,"INPUT -s %s/32 -p tcp -m tcp --sport %d -j DROP",remote_address,remote_port);
|
||||
sprintf(rule,"INPUT -s %s/32 -p tcp -m tcp --sport %d -j DROP",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)
|
||||
{
|
||||
sprintf(rule,"INPUT -s %s/32 -p udp -m udp --sport %d -j DROP",remote_address,remote_port);
|
||||
sprintf(rule,"INPUT -s %s/32 -p udp -m udp --sport %d -j DROP",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)
|
||||
{
|
||||
sprintf(rule,"INPUT -s %s/32 -p icmp -j DROP",remote_address);
|
||||
sprintf(rule,"INPUT -s %s/32 -p icmp -j DROP",remote_ip);
|
||||
//mylog(log_warn,"make sure you have run once: iptables -A INPUT -s %s/32 -p icmp -j DROP\n",remote_address);
|
||||
}
|
||||
}
|
||||
@@ -2756,14 +2792,14 @@ void iptables_rule()
|
||||
}
|
||||
if(raw_mode==mode_icmp)
|
||||
{
|
||||
if(local_address_uint32==0)
|
||||
if(local_ip_uint32==0)
|
||||
{
|
||||
sprintf(rule,"INPUT -p icmp -j DROP");
|
||||
//mylog(log_warn,"make sure you have run once: iptables -A INPUT -p icmp -j DROP\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(rule,"INPUT -d %s/32 -p icmp -j DROP",local_address);
|
||||
sprintf(rule,"INPUT -d %s/32 -p icmp -j DROP",local_ip);
|
||||
//mylog(log_warn,"make sure you have run once: iptables -A INPUT -d %s/32 -p icmp -j DROP\n",local_address);
|
||||
}
|
||||
}
|
||||
@@ -2802,6 +2838,8 @@ void iptables_rule()
|
||||
}
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
//auto a=string_to_vec("a b c d ");
|
||||
//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));
|
||||
//assert(0==1);
|
||||
dup2(1, 2);//redirect stderr to stdout
|
||||
@@ -2813,9 +2851,14 @@ int main(int argc, char *argv[])
|
||||
|
||||
process_arg(argc,argv);
|
||||
|
||||
local_address_uint32=inet_addr(local_address);
|
||||
remote_address_uint32=inet_addr(remote_address);
|
||||
source_address_uint32=inet_addr(source_address);
|
||||
if(geteuid() != 0)
|
||||
{
|
||||
mylog(log_error,"root check failed,make sure you run this program with root,we can try to continue,but it will likely fail\n");
|
||||
}
|
||||
|
||||
local_ip_uint32=inet_addr(local_ip);
|
||||
remote_ip_uint32=inet_addr(remote_ip);
|
||||
source_ip_uint32=inet_addr(source_ip);
|
||||
|
||||
|
||||
//current_time_rough=get_current_time();
|
||||
|
52
makefile
52
makefile
@@ -1,37 +1,57 @@
|
||||
cc_cross=/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_cross=/home/wangyu/Desktop/arm-2014.05/bin/arm-none-linux-gnueabi-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_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
|
||||
cc_arm=/home/wangyu/Desktop/arm-2014.05/bin/arm-none-linux-gnueabi-g++
|
||||
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
|
||||
TAR=udp2raw_binaries.tar.gz udp2raw_amd64 udp2raw_x86 udp2raw_ar71xx udp2raw_bcm2708
|
||||
SOURCES_AES_ACC=main.cpp $(wildcard lib/aes_acc/aes*.c) lib/md5.c encrypt.cpp log.cpp network.cpp common.cpp
|
||||
|
||||
NAME=udp2raw
|
||||
TAR=${NAME}_binaries.tar.gz ${NAME}_amd64 ${NAME}_x86 ${NAME}_ar71xx ${NAME}_bcm2708 ${NAME}_arm ${NAME}_amd64_hw_aes
|
||||
|
||||
all:
|
||||
rm -f udp2raw
|
||||
${cc_local} -o udp2raw -I. ${SOURCES} ${FLAGS} -lrt -static -O3
|
||||
rm -f ${NAME}
|
||||
${cc_local} -o ${NAME} -I. ${SOURCES} ${FLAGS} -lrt -static -O3
|
||||
fast:
|
||||
rm -f udp2raw
|
||||
${cc_local} -o udp2raw -I. ${SOURCES} ${FLAGS} -lrt
|
||||
rm -f ${NAME}
|
||||
${cc_local} -o ${NAME} -I. ${SOURCES} ${FLAGS} -lrt
|
||||
debug:
|
||||
rm -f udp2raw
|
||||
${cc_local} -o udp2raw -I. ${SOURCES} ${FLAGS} -lrt -Wformat-nonliteral -D MY_DEBUG
|
||||
rm -f ${NAME}
|
||||
${cc_local} -o ${NAME} -I. ${SOURCES} ${FLAGS} -lrt -Wformat-nonliteral -D MY_DEBUG
|
||||
|
||||
ar71xx:
|
||||
${cc_ar71xx} -o udp2raw_ar71xx -I. ${SOURCES} ${FLAGS} -lrt -lgcc_eh -static -O3
|
||||
${cc_ar71xx} -o ${NAME}_ar71xx -I. ${SOURCES} ${FLAGS} -lrt -lgcc_eh -static -O3
|
||||
bcm2708:
|
||||
${cc_bcm2708} -o udp2raw_bcm2708 -I. ${SOURCES} ${FLAGS} -lrt -static -O3
|
||||
${cc_bcm2708} -o ${NAME}_bcm2708 -I. ${SOURCES} ${FLAGS} -lrt -static -O3
|
||||
amd64:
|
||||
${cc_local} -o ${NAME}_amd64 -I. ${SOURCES} ${FLAGS} -lrt -static -O3
|
||||
amd64_hw_aes:
|
||||
${cc_local} -o ${NAME}_amd64_hw_aes -I. ${SOURCES_AES_ACC} ${FLAGS} -lrt -static -O3
|
||||
x86:
|
||||
${cc_local} -o ${NAME}_x86 -I. ${SOURCES} ${FLAGS} -lrt -static -O3 -m32
|
||||
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
|
||||
arm:
|
||||
${cc_cross} -o ${NAME}_arm -I. ${SOURCES} ${FLAGS} -lrt -static -O3
|
||||
|
||||
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
|
||||
|
||||
cross:
|
||||
${cc_cross} -o udp2raw_cross -I. ${SOURCES} ${FLAGS} -lrt -static -lgcc_eh -O3
|
||||
${cc_cross} -o ${NAME}_cross -I. ${SOURCES} ${FLAGS} -lrt -O3
|
||||
|
||||
cross2:
|
||||
${cc_cross} -o udp2raw_cross -I. ${SOURCES} ${FLAGS} -lrt -O3
|
||||
${cc_cross} -o ${NAME}_cross -I. ${SOURCES} ${FLAGS} -lrt -static -lgcc_eh -O3
|
||||
|
||||
release: ar71xx bcm2708
|
||||
${cc_local} -o udp2raw_amd64 -I. ${SOURCES} ${FLAGS} -lrt -static -O3
|
||||
${cc_local} -o udp2raw_x86 -I. ${SOURCES} ${FLAGS} -lrt -m32 -static -O3
|
||||
cross3:
|
||||
${cc_cross} -o ${NAME}_cross -I. ${SOURCES} ${FLAGS} -lrt -static -O3
|
||||
|
||||
release: amd64 x86 ar71xx bcm2708 arm amd64_hw_aes
|
||||
tar -zcvf ${TAR}
|
||||
|
||||
clean:
|
||||
rm -f ${TAR}
|
||||
rm -f udp2raw udp2raw_cross
|
||||
|
||||
|
61
network.cpp
61
network.cpp
@@ -24,7 +24,9 @@ int lower_level=0;
|
||||
int ifindex=-1;
|
||||
char if_name[100]="";
|
||||
|
||||
unsigned char oppsite_hw_addr[6]=
|
||||
unsigned short g_ip_id_counter=0;
|
||||
|
||||
unsigned char dest_hw_addr[6]=
|
||||
{0xff,0xff,0xff,0xff,0xff,0xff};
|
||||
//{0x00,0x23,0x45,0x67,0x89,0xb9};
|
||||
|
||||
@@ -44,8 +46,8 @@ struct sock_filter code_tcp_old[] = {
|
||||
{ 0x6, 0, 0, 0x00000000 },//12
|
||||
};
|
||||
struct sock_filter code_tcp[] = {
|
||||
{ 0x5, 0, 0, 0x00000001 },//0 //jump to 2,dirty hack from tcpdump -d's output
|
||||
{ 0x5, 0, 0, 0x00000000 },//1
|
||||
//{ 0x5, 0, 0, 0x00000001 },//0 //jump to 2,dirty hack from tcpdump -d's output
|
||||
//{ 0x5, 0, 0, 0x00000000 },//1
|
||||
{ 0x30, 0, 0, 0x00000009 },//2
|
||||
{ 0x15, 0, 6, 0x00000006 },//3
|
||||
{ 0x28, 0, 0, 0x00000006 },//4
|
||||
@@ -56,11 +58,11 @@ struct sock_filter code_tcp[] = {
|
||||
{ 0x6, 0, 0, 0x0000ffff },//9
|
||||
{ 0x6, 0, 0, 0x00000000 },//10
|
||||
};
|
||||
int code_tcp_port_index=8;
|
||||
int code_tcp_port_index=6;
|
||||
|
||||
struct sock_filter code_udp[] = {
|
||||
{ 0x5, 0, 0, 0x00000001 },
|
||||
{ 0x5, 0, 0, 0x00000000 },
|
||||
//{ 0x5, 0, 0, 0x00000001 },
|
||||
//{ 0x5, 0, 0, 0x00000000 },
|
||||
{ 0x30, 0, 0, 0x00000009 },
|
||||
{ 0x15, 0, 6, 0x00000011 },
|
||||
{ 0x28, 0, 0, 0x00000006 },
|
||||
@@ -71,10 +73,10 @@ struct sock_filter code_udp[] = {
|
||||
{ 0x6, 0, 0, 0x0000ffff },
|
||||
{ 0x6, 0, 0, 0x00000000 },
|
||||
};
|
||||
int code_udp_port_index=8;
|
||||
int code_udp_port_index=6;
|
||||
struct sock_filter code_icmp[] = {
|
||||
{ 0x5, 0, 0, 0x00000001 },
|
||||
{ 0x5, 0, 0, 0x00000000 },
|
||||
//{ 0x5, 0, 0, 0x00000001 },
|
||||
//{ 0x5, 0, 0, 0x00000000 },
|
||||
{ 0x30, 0, 0, 0x00000009 },
|
||||
{ 0x15, 0, 1, 0x00000001 },
|
||||
{ 0x6, 0, 0, 0x0000ffff },
|
||||
@@ -162,6 +164,7 @@ packet_info_t::packet_info_t()
|
||||
int init_raw_socket()
|
||||
{
|
||||
|
||||
g_ip_id_counter=get_true_random_number()%65535;
|
||||
if(lower_level==0)
|
||||
{
|
||||
raw_send_fd = socket(AF_INET , SOCK_RAW , IPPROTO_TCP);
|
||||
@@ -306,7 +309,6 @@ int init_ifindex(char * if_name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int send_raw_ip(raw_info_t &raw_info,const char * payload,int payloadlen)
|
||||
{
|
||||
const packet_info_t &send_info=raw_info.send_info;
|
||||
@@ -316,19 +318,18 @@ int send_raw_ip(raw_info_t &raw_info,const char * payload,int payloadlen)
|
||||
struct iphdr *iph = (struct iphdr *) send_raw_ip_buf;
|
||||
memset(iph,0,sizeof(iphdr));
|
||||
|
||||
static unsigned short ip_id=1;
|
||||
|
||||
iph->ihl = sizeof(iphdr)/4; //we dont use ip options,so the length is just sizeof(iphdr)
|
||||
iph->version = 4;
|
||||
iph->tos = 0;
|
||||
|
||||
if(lower_level)
|
||||
{
|
||||
iph->id=0;
|
||||
//iph->id = htons (ip_id++); //Id of this packet
|
||||
//iph->id=0;
|
||||
iph->id = htons (g_ip_id_counter++); //Id of this packet
|
||||
}
|
||||
else
|
||||
iph->id = 0; //Id of this packet ,kernel will auto fill this if id is zero ,or really?????// todo //seems like there is a problem
|
||||
iph->id = htons (g_ip_id_counter++); //Id of this packet
|
||||
//iph->id = 0; //Id of this packet ,kernel will auto fill this if id is zero ,or really?????// todo //seems like there is a problem
|
||||
|
||||
iph->frag_off = htons(0x4000); //DF set,others are zero
|
||||
// iph->frag_off = htons(0x0000); //DF set,others are zero
|
||||
@@ -353,7 +354,7 @@ int send_raw_ip(raw_info_t &raw_info,const char * payload,int payloadlen)
|
||||
int ret;
|
||||
if(lower_level==0)
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
struct sockaddr_in sin={0};
|
||||
sin.sin_family = AF_INET;
|
||||
//sin.sin_port = htons(info.dst_port); //dont need this
|
||||
sin.sin_addr.s_addr = send_info.dst_ip;
|
||||
@@ -363,14 +364,14 @@ int send_raw_ip(raw_info_t &raw_info,const char * payload,int payloadlen)
|
||||
else
|
||||
{
|
||||
|
||||
struct sockaddr_ll addr;
|
||||
memset(&addr,0,sizeof(addr));
|
||||
struct sockaddr_ll addr={0};
|
||||
//memset(&addr,0,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,oppsite_hw_addr,ETHER_ADDR_LEN);
|
||||
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));
|
||||
}
|
||||
if(ret==-1)
|
||||
@@ -389,13 +390,15 @@ int send_raw_ip(raw_info_t &raw_info,const char * payload,int payloadlen)
|
||||
int peek_raw(packet_info_t &peek_info)
|
||||
{ static char peek_raw_buf[buf_len];
|
||||
char *ip_begin=peek_raw_buf+link_level_header_len;
|
||||
struct sockaddr saddr;
|
||||
socklen_t saddr_size;
|
||||
struct sockaddr saddr={0};
|
||||
socklen_t saddr_size=sizeof(saddr);
|
||||
int recv_len = recvfrom(raw_recv_fd, peek_raw_buf,max_data_len, MSG_PEEK ,&saddr , &saddr_size);//change max_data_len to something smaller,we only need header here
|
||||
iphdr * iph = (struct iphdr *) (ip_begin);
|
||||
//mylog(log_info,"recv_len %d\n",recv_len);
|
||||
if(recv_len<int(sizeof(iphdr)))
|
||||
{
|
||||
mylog(log_trace,"failed here %d %d\n",recv_len,int(sizeof(iphdr)));
|
||||
mylog(log_trace,"%s\n ",strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
peek_info.src_ip=iph->saddr;
|
||||
@@ -407,10 +410,17 @@ int peek_raw(packet_info_t &peek_info)
|
||||
{
|
||||
case mode_faketcp:
|
||||
{
|
||||
if(iph->protocol!=IPPROTO_TCP) return -1;
|
||||
if(iph->protocol!=IPPROTO_TCP)
|
||||
{
|
||||
mylog(log_trace,"failed here");
|
||||
return -1;
|
||||
}
|
||||
struct tcphdr *tcph=(tcphdr *)payload;
|
||||
if(recv_len<int( iphdrlen+sizeof(tcphdr) ))
|
||||
{
|
||||
mylog(log_trace,"failed here");
|
||||
return -1;
|
||||
}
|
||||
peek_info.src_port=ntohs(tcph->source);
|
||||
peek_info.syn=tcph->syn;
|
||||
break;
|
||||
@@ -445,11 +455,9 @@ int recv_raw_ip(raw_info_t &raw_info,char * &payload,int &payloadlen)
|
||||
static char recv_raw_ip_buf[buf_len];
|
||||
|
||||
iphdr * iph;
|
||||
struct sockaddr saddr;
|
||||
socklen_t saddr_size;
|
||||
saddr_size = sizeof(saddr);
|
||||
struct sockaddr saddr={0};
|
||||
socklen_t saddr_size = sizeof(saddr);
|
||||
int flag=0;
|
||||
|
||||
int recv_len = recvfrom(raw_recv_fd, recv_raw_ip_buf, max_data_len, flag ,&saddr , &saddr_size);
|
||||
|
||||
if(recv_len<0)
|
||||
@@ -481,6 +489,7 @@ int recv_raw_ip(raw_info_t &raw_info,char * &payload,int &payloadlen)
|
||||
|
||||
if(bind_address_uint32!=0 &&recv_info.dst_ip!=bind_address_uint32)
|
||||
{
|
||||
mylog(log_trace,"bind adress doenst match, dropped\n");
|
||||
//printf(" bind adress doenst match, dropped\n");
|
||||
return -1;
|
||||
}
|
||||
|
Reference in New Issue
Block a user