Compare commits
609 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
4623f878e0 | ||
|
e42f0e5732 | ||
|
f49e6adedf | ||
|
d1a9bcc4fb | ||
|
bc8bd8c2f8 | ||
|
ca16c3a5e6 | ||
|
7abe19c7d9 | ||
|
f3f528e866 | ||
|
ec6fad552b | ||
|
87b878a09e | ||
|
e66eddd1d5 | ||
|
ec416515f3 | ||
|
d12e540830 | ||
|
e7eecc8ef2 | ||
|
82ba4f7d1b | ||
|
e5ecd33ec4 | ||
|
9217e0e9e6 | ||
|
87b0db8862 | ||
|
8ceaf27eda | ||
|
9f9e8caff6 | ||
|
74f3eb90a7 | ||
|
38286d5c5b | ||
|
ec849322d7 | ||
|
b98a467eed | ||
|
25d3323427 | ||
|
b8e9095135 | ||
|
026f97687a | ||
|
f2f90a9a15 | ||
|
cf23f4d656 | ||
|
59819db2dd | ||
|
cc6ea766c4 | ||
|
509156fc14 | ||
|
cb9059bf3b | ||
|
07e2e695a6 | ||
|
e8daf7c263 | ||
|
5f907e32d7 | ||
|
0e37c1fea4 | ||
|
606bbec351 | ||
|
3fc23f5cf6 | ||
|
f3c8f70f47 | ||
|
6c27502757 | ||
|
5a51248cb0 | ||
|
79bb28fd12 | ||
|
b3e06de4cb | ||
|
b03ae53df6 | ||
|
15c15d5bcb | ||
|
2f0328a41a | ||
|
779ebdd37a | ||
|
5340f0726e | ||
|
e95ee70351 | ||
|
5cc304a261 | ||
|
7636225414 | ||
|
f68c6e211d | ||
|
8c81f7673b | ||
|
c1dfd4e928 | ||
|
7e55b1e132 | ||
|
ee787e0d4a | ||
|
7d481d26b9 | ||
|
168ae1e2ae | ||
|
6230569bbb | ||
|
238e85a5e4 | ||
|
0137dba1fd | ||
|
b6f76827b0 | ||
|
66eb002528 | ||
|
b1f0498472 | ||
|
e5584c73be | ||
|
c855a14ae8 | ||
|
d77271540f | ||
|
6b8852f269 | ||
|
f0e36d7d7c | ||
|
6153aca5d8 | ||
|
92fcdbb31a | ||
|
c72480110f | ||
|
8331610e7a | ||
|
4a1e01c5a5 | ||
|
6ccf6ce3dc | ||
|
a3535364fa | ||
|
4e9000c6b5 | ||
|
a4aba62656 | ||
|
7de2f800f9 | ||
|
233fab4fac | ||
|
6718627e9d | ||
|
b9d4264225 | ||
|
0095f1da5c | ||
|
44fef508a1 | ||
|
d6c0df17f5 | ||
|
8ade602be1 | ||
|
0980d89072 | ||
|
278ade5d36 | ||
|
10869eb197 | ||
|
1bc20c1cdb | ||
|
4bb7367cfa | ||
|
c0c9cc0411 | ||
|
b78dc6673f | ||
|
f52385ccd5 | ||
|
7ad9a6987c | ||
|
184b198470 | ||
|
2dc0670266 | ||
|
6ccd056d41 | ||
|
73daa12db1 | ||
|
80d21e56c7 | ||
|
b0d96a3c47 | ||
|
0682757631 | ||
|
52d540df90 | ||
|
256d1eee69 | ||
|
9e9ad56890 | ||
|
1e98ae10c2 | ||
|
fabe2b3558 | ||
|
565034dbae | ||
|
a7849b3634 | ||
|
3a372b9eee | ||
|
2e8294ab88 | ||
|
30eb96608d | ||
|
822a807e58 | ||
|
f90d1abe05 | ||
|
2f59ce490e | ||
|
4cb60d5997 | ||
|
1155f0547f | ||
|
cac9c56afb | ||
|
f050946ac5 | ||
|
2f0c02def2 | ||
|
c71d256006 | ||
|
946b615acf | ||
|
fef76af3a5 | ||
|
736c3f46b6 | ||
|
bec9c95999 | ||
|
16de522196 | ||
|
232ec4f339 | ||
|
d3cbbe8085 | ||
|
e51c236c20 | ||
|
876649fd74 | ||
|
8a6f89be88 | ||
|
45fca0bbfe | ||
|
cd92410cfe | ||
|
04eec19ab2 | ||
|
423157dbba | ||
|
94e12e6cf5 | ||
|
61512a15ec | ||
|
65943053ff | ||
|
52a911b109 | ||
|
3ab2543715 | ||
|
b9d0375a72 | ||
|
0fc24b6233 | ||
|
4463e21d9e | ||
|
8aeab8cee1 | ||
|
be8e42af1b | ||
|
3862e5a4e2 | ||
|
c0b70c95ca | ||
|
5c7d48e711 | ||
|
b0976dbee6 | ||
|
2c2d897bc2 | ||
|
675ccdf650 | ||
|
f7383575b1 | ||
|
6ea083a49b | ||
|
8fe8653331 | ||
|
2c67c319b7 | ||
|
86a78b223e | ||
|
0c2060028a | ||
|
1f313f1c07 | ||
|
af2513cbc0 | ||
|
65b2d7bc1c | ||
|
a02c22cb3d | ||
|
5a6a2682bc | ||
|
a170650210 | ||
|
b0f62e35cc | ||
|
96b57df4e2 | ||
|
0f756e3166 | ||
|
7cb65ec45d | ||
|
3138b2ca8e | ||
|
7142dd018d | ||
|
2be65585a0 | ||
|
2362f28eb6 | ||
|
0711c7355f | ||
|
c811dc15a3 | ||
|
9a97fbbf4f | ||
|
a884b02b26 | ||
|
85245c5963 | ||
|
4fcae8d54c | ||
|
31f2015ab7 | ||
|
b0613e5b9b | ||
|
7fe8321082 | ||
|
2da0de34a2 | ||
|
29708ba43e | ||
|
1e9404e6ec | ||
|
19b4d45636 | ||
|
c03177b370 | ||
|
c217854190 | ||
|
dc6fc48941 | ||
|
b35edf7486 | ||
|
3bc07d5c86 | ||
|
f081ab751d | ||
|
91097eab5d | ||
|
c22b5e9680 | ||
|
9162a533d3 | ||
|
b01b087949 | ||
|
51b45c8f39 | ||
|
995ea8c98d | ||
|
aec81eb0c9 | ||
|
8b59b4afb9 | ||
|
c33bb552cd | ||
|
9516cfe99d | ||
|
5b1e59cae2 | ||
|
211d7ea4d3 | ||
|
7599d99fcc | ||
|
706cb0b583 | ||
|
43ae798e77 | ||
|
2f12d55229 | ||
|
0a4555dd42 | ||
|
14ece87bc3 | ||
|
50f682daf4 | ||
|
d487ca57f7 | ||
|
482e658858 | ||
|
069a9ba2b4 | ||
|
c591902be1 | ||
|
6a825dc51e | ||
|
1bdb6a5720 | ||
|
1afe8d7317 | ||
|
a54a0e269b | ||
|
e8398d0d31 | ||
|
dc43cb740b | ||
|
2e6be9e159 | ||
|
7a23486533 | ||
|
6515d428e9 | ||
|
c3e1dab838 | ||
|
eedffd90a0 | ||
|
c2aaf9b544 | ||
|
08b14cc9ea | ||
|
6f3eba419e | ||
|
c6cd29dd6f | ||
|
00edb620be | ||
|
95ee6e64dc | ||
|
deeb7395a4 | ||
|
537f8a6311 | ||
|
f34f903317 | ||
|
6e1df4b39f | ||
|
c755a7d7ec | ||
|
6c0642c37e | ||
|
740e10bd04 | ||
|
a549793d82 | ||
|
a989a9f381 | ||
|
54f32f0611 | ||
|
9e173f9513 | ||
|
452661b389 | ||
|
dcde8828c4 | ||
|
fc05e7f080 | ||
|
f096a510b5 | ||
|
8de2506eff | ||
|
3960ca1b36 | ||
|
d778be2bfc | ||
|
0e77b0d5ab | ||
|
545f9796aa | ||
|
32ad8df38d | ||
|
3b0a4c7d08 | ||
|
61d48253f1 | ||
|
e1a97c03b5 | ||
|
6c6b4d2284 | ||
|
3eaf3e908e | ||
|
35603a69e8 | ||
|
4615ab6364 | ||
|
378449ee28 | ||
|
dcc722ff5e | ||
|
661b329930 | ||
|
0de85dd736 | ||
|
fb54df66e4 | ||
|
3cdac6d95c | ||
|
9c51c14ad6 | ||
|
36d6854a57 | ||
|
b239e94342 | ||
|
86483be894 | ||
|
1c831f2911 | ||
|
d250528d29 | ||
|
0de39f1aae | ||
|
09b1cadb45 | ||
|
cf5774d2f4 | ||
|
2810a72a72 | ||
|
f8e64b03de | ||
|
2a4f50a6c6 | ||
|
82771f9e39 | ||
|
9a959c2dcf | ||
|
206dd1565c | ||
|
515d4e1dd8 | ||
|
adbe7d110f | ||
|
0fe1a3d38c | ||
|
9472fe8bb3 | ||
|
a8e5df4b35 | ||
|
cf5babd748 | ||
|
a235a7176e | ||
|
5ef9d3fefa | ||
|
bc3801e17d | ||
|
178327c581 | ||
|
698504aca0 | ||
|
934a65e7bf | ||
|
c8113ccb06 | ||
|
5e8269f8f5 | ||
|
f34d9b2820 | ||
|
6f107ec475 | ||
|
5651efd165 | ||
|
0aba2ab7ba | ||
|
106ac96671 | ||
|
1b72661b49 | ||
|
fc796641a1 | ||
|
91904d6311 | ||
|
3cbad7df23 | ||
|
7fa5b90be8 | ||
|
6c865cc5ab | ||
|
215f2a82f2 | ||
|
063931d1c1 | ||
|
ff6f4b4005 | ||
|
065f4d73fa | ||
|
64f97299a2 | ||
|
67cb1356e4 | ||
|
0cc72802e6 | ||
|
44eb464182 | ||
|
9c64891b28 | ||
|
51bbaa0627 | ||
|
d3290a9a94 | ||
|
9c9c549bd1 | ||
|
c0c7bfda68 | ||
|
87483d2f0d | ||
|
6ef15f0185 | ||
|
16a9b3ba89 | ||
|
1a999fd96d | ||
|
c8694bf080 | ||
|
c467ad5c38 | ||
|
241baede16 | ||
|
d2ebcf6f6d | ||
|
dc52499818 | ||
|
56d4287fc2 | ||
|
d4e2c28cce | ||
|
535642684b | ||
|
cb334f37f0 | ||
|
11ebd6f2ee | ||
|
bd1e7fbc2f | ||
|
1f94c40ccf | ||
|
05156c9366 | ||
|
75e0a7f40a | ||
|
42fb66894f | ||
|
7c4e39cf20 | ||
|
01a1d2b006 | ||
|
57be59e070 | ||
|
fe77bb0c1a | ||
|
cb9504f904 | ||
|
dc4936dc60 | ||
|
53609c25fc | ||
|
60efcbce95 | ||
|
5c4ea515f6 | ||
|
e3b902a950 | ||
|
37f2de2ae4 | ||
|
ae497908a1 | ||
|
b59ba05422 | ||
|
cd34922722 | ||
|
51e5b023b0 | ||
|
b1800fa41a | ||
|
698ff33892 | ||
|
1293b95335 | ||
|
7e74b40977 | ||
|
d1e9bdc5da | ||
|
2b9d5c6db6 | ||
|
b86d475f1f | ||
|
0a7f9b5cc6 | ||
|
eb9633ed59 | ||
|
c0b464aeaf | ||
|
020242b73d | ||
|
2269879a2e | ||
|
057f81007d | ||
|
1f2f0d96fd | ||
|
01e0e51b9b | ||
|
6ef38709a6 | ||
|
57b874ee6d | ||
|
ab0ce3ade3 | ||
|
32f344fd3c | ||
|
968d35178a | ||
|
f8e268769c | ||
|
b9030fe81d | ||
|
e6f0ed035c | ||
|
00e1ddfecc | ||
|
15e1790f73 | ||
|
763b0b7342 | ||
|
c716d617a0 | ||
|
60393d24d8 | ||
|
9e7ed280fc | ||
|
532693edc6 | ||
|
033fa830f7 | ||
|
51464ecbfe | ||
|
dd8539e420 | ||
|
19ce820813 | ||
|
b30a347c23 | ||
|
3a35c5ce5b | ||
|
bab98d8356 | ||
|
283167802c | ||
|
1db6509373 | ||
|
a29cbf3779 | ||
|
da26c5047b | ||
|
38d98b5b37 | ||
|
497320e446 | ||
|
19da7b6972 | ||
|
687666cf05 | ||
|
20f8aa743b | ||
|
8ce51fde50 | ||
|
b9d7a91cae | ||
|
63dd25a0b5 | ||
|
c894596e06 | ||
|
558865f52d | ||
|
604ff2978f | ||
|
9046fd5889 | ||
|
241d305570 | ||
|
edb3edb2cc | ||
|
d9a24a5e42 | ||
|
f9cf1c36a3 | ||
|
4d797fb55d | ||
|
8d1e735041 | ||
|
769b99546b | ||
|
7d9ef910ca | ||
|
5f2838573a | ||
|
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 | ||
|
2af94823e3 | ||
|
00a3955de0 | ||
|
0266163b12 | ||
|
df55271c08 | ||
|
facf7e4049 | ||
|
81209ba25e | ||
|
8c833776da | ||
|
aede2a8680 | ||
|
b0636445e3 | ||
|
f8715a1d1d | ||
|
6205aa6b8f | ||
|
ae0509d7d2 | ||
|
2fa2666479 | ||
|
fdbf1e082f | ||
|
d502de0c7c | ||
|
8487d7c624 | ||
|
83b00e79ad | ||
|
36ed28064a | ||
|
746aefa70a | ||
|
a69cbf23da | ||
|
fc4d178657 | ||
|
ccab523ddf | ||
|
4eb72f6139 | ||
|
6296322e22 | ||
|
3a0c512e43 | ||
|
e01d7059ad | ||
|
5e6d977247 | ||
|
c08bd12ea0 | ||
|
ebdb08873a | ||
|
46b0a00b3e | ||
|
d1934dda4c | ||
|
81e599e84c | ||
|
fadf5a25c2 | ||
|
9f25a61dad | ||
|
165dc193f0 | ||
|
e732ce2a8a | ||
|
d7cae0be18 | ||
|
c1b8eb23a2 | ||
|
1bbe19cdee | ||
|
b16b37c879 | ||
|
9479c95510 | ||
|
90b1897d4a | ||
|
3fa1a99046 | ||
|
eb59012b7b | ||
|
1a2cd767c0 | ||
|
8f04c82788 | ||
|
1b9f2a1e0e | ||
|
7592729abc | ||
|
e890a6344c | ||
|
bc6358aa0a | ||
|
ed6416a30d | ||
|
9378cee8d1 | ||
|
0b3fb41f6f | ||
|
41489af1d1 | ||
|
3a1bacc11e | ||
|
06d7638c5f | ||
|
380971fe2b | ||
|
709258b260 | ||
|
c3a8305e49 | ||
|
5c08d65d91 | ||
|
6f9ab92c1d | ||
|
2f57fa6670 | ||
|
d104074328 | ||
|
7c280ab335 | ||
|
eb8567b693 | ||
|
fec382ebab | ||
|
4d319f54ff | ||
|
a58618c73c | ||
|
456da000f4 | ||
|
91e229616c | ||
|
2251947278 | ||
|
c48c619002 | ||
|
0cac945a26 | ||
|
97738ab3ce | ||
|
a6bb0b50cf | ||
|
e7530fa7f9 | ||
|
cec1257474 | ||
|
c97f09f534 | ||
|
92581be9a1 | ||
|
58ab1f6b15 | ||
|
1b0d4f6d08 | ||
|
91a015b8a8 | ||
|
ce2e6a094d | ||
|
59af4a0135 | ||
|
b5c6176079 | ||
|
83abc1def4 | ||
|
307399b00a | ||
|
44852270ef | ||
|
ae153ceacc | ||
|
da6aafba12 | ||
|
e50d368440 | ||
|
801ecfd0ee | ||
|
45b7ab6285 | ||
|
8271cce383 | ||
|
00dcec9896 | ||
|
6be7034bcb | ||
|
9593528dd4 | ||
|
9884544e34 | ||
|
858928a17f | ||
|
dc6c328d57 | ||
|
716c183886 |
4
.clang-format
Normal file
@ -0,0 +1,4 @@
|
||||
SortIncludes: false
|
||||
BasedOnStyle: Google
|
||||
ColumnLimit: 0
|
||||
IndentWidth: 4
|
1
.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
||||
lib/aes_acc/asm/* linguist-vendored
|
35
CMakeLists.txt
Normal file
@ -0,0 +1,35 @@
|
||||
#note: experimental
|
||||
# currently only used for generating `compile_commands.json` for clangd.
|
||||
# to build this project, it's suggested to use `makefile` instead
|
||||
|
||||
cmake_minimum_required(VERSION 3.7)
|
||||
project(udp2raw)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
|
||||
set(SOURCE_FILES
|
||||
main.cpp
|
||||
lib/md5.cpp
|
||||
lib/pbkdf2-sha1.cpp
|
||||
lib/pbkdf2-sha256.cpp
|
||||
encrypt.cpp
|
||||
log.cpp
|
||||
network.cpp
|
||||
common.cpp
|
||||
connection.cpp
|
||||
misc.cpp
|
||||
fd_manager.cpp
|
||||
client.cpp
|
||||
server.cpp
|
||||
lib/aes_faster_c/aes.cpp
|
||||
lib/aes_faster_c/wrapper.cpp
|
||||
my_ev.cpp
|
||||
)
|
||||
set(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-unused-variable -Wno-unused-parameter -Wno-missing-field-initializers -O2 -g -fsanitize=address,undefined")
|
||||
|
||||
add_executable(udp2raw ${SOURCE_FILES})
|
||||
target_link_libraries(udp2raw rt)
|
||||
target_link_libraries(udp2raw pthread)
|
||||
include_directories(SYSTEM "libev")
|
||||
include_directories(".")
|
1
ISSUE_TEMPLATE.md
Normal file
@ -0,0 +1 @@
|
||||
English Only.
|
231
README.md
@ -1,14 +1,227 @@
|
||||
# udp2raw-tunnel
|
||||
udp2raw tunnel (udp to tcp with fake tcp header)
|
||||
# Udp2raw-tunnel
|
||||
|
||||
#usage
|
||||
|
||||
client:
|
||||
-A INPUT -s 44.55.66.77/32 -p tcp -m tcp --sport 9999 -j DROP
|
||||
A Tunnel which turns UDP Traffic into Encrypted FakeTCP/UDP/ICMP Traffic by using Raw Socket, helps you Bypass UDP FireWalls(or Unstable UDP Environment).
|
||||
|
||||
./raw -l 127.0.0.1:6666 -r44.55.66.77:9999 -c --source-ip 192.168.1.100
|
||||
When used alone,udp2raw tunnels only UDP traffic. Nevertheless,if you used udp2raw + any UDP-based VPN together,you can tunnel any traffic(include TCP/UDP/ICMP),currently OpenVPN/L2TP/ShadowVPN and [tinyfecVPN](https://github.com/wangyu-/tinyfecVPN) are confirmed to be supported.
|
||||
|
||||
server:
|
||||
-A INPUT -p tcp -m tcp --dport 9999 -j DROP
|
||||
|
||||
./raw -l44.55.66.77:9999 -r 127.0.0.1:5555 -s
|
||||

|
||||
|
||||
or
|
||||
|
||||

|
||||
|
||||
[udp2raw wiki](https://github.com/wangyu-/udp2raw-tunnel/wiki)
|
||||
|
||||
[简体中文](/doc/README.zh-cn.md)
|
||||
|
||||
|
||||
# Support Platforms
|
||||
Linux host (including desktop Linux,Android phone/tablet,OpenWRT router,or Raspberry PI) with root account or cap_net_raw capability.
|
||||
|
||||
For Windows and MacOS users, use the udp2raw in [this repo](https://github.com/wangyu-/udp2raw-multiplatform).
|
||||
|
||||
# Features
|
||||
### Send/Receive UDP Packets with ICMP/FakeTCP/UDP headers
|
||||
ICMP/FakeTCP headers help you bypass UDP blocking, UDP QOS or improper UDP NAT behavior on some ISPs. In ICMP header mode,udp2raw works like an ICMP tunnel.
|
||||
|
||||
UDP headers are also supported. In UDP header mode, it behaves just like a normal UDP tunnel, and you can just make use of the other features (such as encryption, anti-replay, or connection stabilization).
|
||||
|
||||
### Simulated TCP with Real-time/Out-of-Order Delivery
|
||||
In FakeTCP header mode,udp2raw simulates 3-way handshake while establishing a connection,simulates seq and ack_seq while data transferring. It also simulates a few TCP options such as: `MSS`, `sackOk`, `TS`, `TS_ack`, `wscale`. Firewalls will regard FakeTCP as a TCP connection, but its essentially UDP: it supports real-time/out-of-order delivery(just as normal UDP does), no congestion control or re-transmission. So there wont be any TCP over TCP problem when using OpenVPN.
|
||||
|
||||
### Encryption, Anti-Replay
|
||||
* Encrypt your traffic with AES-128-CBC.
|
||||
* Protect data integrity by HMAC-SHA1 (or weaker MD5/CRC32).
|
||||
* Defense replay attack with anti-replay window.
|
||||
|
||||
[Notes on encryption](https://github.com/wangyu-/udp2raw-tunnel/wiki/Notes-on-encryption)
|
||||
|
||||
### Failure Dectection & Stabilization (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.
|
||||
|
||||
For example, if you use udp2raw + OpenVPN, OpenVPN won't lose connection after any reconnect, **even if network cable is re-plugged or WiFi access point is changed**.
|
||||
|
||||
### Other Features
|
||||
* **Multiplexing** One client can handle multiple UDP connections, all of which share the same raw connection.
|
||||
|
||||
* **Multiple Clients** One server can have multiple clients.
|
||||
|
||||
* **NAT Support** All of the 3 modes work in NAT environments.
|
||||
|
||||
* **OpenVZ Support** Tested on BandwagonHost VPS.
|
||||
|
||||
* **Easy to Build** No dependencies.To cross-compile udp2raw,all you need to do is just to download a toolchain,modify makefile to point at the toolchain,run `make cross` then everything is done.(Note:Pre-compiled binaries for Desktop,RaspberryPi,Android,some Openwrt Routers are already included in [Releases](https://github.com/wangyu-/udp2raw-tunnel/releases))
|
||||
|
||||
### Keywords
|
||||
`Bypass UDP QoS` `Bypass UDP Blocking` `Bypass OpenVPN TCP over TCP problem` `OpenVPN over ICMP` `UDP to ICMP tunnel` `UDP to TCP tunnel` `UDP over ICMP` `UDP over TCP`
|
||||
|
||||
# Getting Started
|
||||
### Installing
|
||||
Download binary release from https://github.com/wangyu-/udp2raw-tunnel/releases
|
||||
|
||||
### Running
|
||||
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 server side:
|
||||
./udp2raw_amd64 -s -l0.0.0.0:4096 -r 127.0.0.1:7777 -k "passwd" --raw-mode faketcp -a
|
||||
|
||||
# Run at client side
|
||||
./udp2raw_amd64 -c -l0.0.0.0:3333 -r44.55.66.77:4096 -k "passwd" --raw-mode faketcp -a
|
||||
```
|
||||
(The above commands need to be run as root. For better security, with some extra steps, you can run udp2raw as non-root. Check [this link](https://github.com/wangyu-/udp2raw-tunnel/wiki/run-udp2raw-as-non-root) for more info )
|
||||
|
||||
###### Server Output:
|
||||

|
||||
###### 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, check [Android_Guide](https://github.com/wangyu-/udp2raw/wiki/Android-Guide)
|
||||
|
||||
`-a` option automatically adds an iptables rule (or a few iptables rules) for you, udp2raw relies on this iptables rule to work stably. Be aware you dont forget `-a` (its a common mistake). If you dont want udp2raw to add iptables rule automatically, you can add it manually(take a look at `-g` option) and omit `-a`.
|
||||
|
||||
|
||||
# Advanced Topic
|
||||
### Usage
|
||||
```
|
||||
udp2raw-tunnel
|
||||
git version:6e1df4b39f build date:Oct 24 2017 09:21:15
|
||||
repository: https://github.com/wangyu-/udp2raw-tunnel
|
||||
|
||||
usage:
|
||||
run as client : ./this_program -c -l local_listen_ip:local_port -r server_address:server_port [options]
|
||||
run as server : ./this_program -s -l server_listen_ip:server_port -r remote_address:remote_port [options]
|
||||
|
||||
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"
|
||||
--cipher-mode <string> avaliable values:aes128cbc(default),xor,none
|
||||
--auth-mode <string> avaliable values:hmac_sha1,md5(default),crc32,simple,none
|
||||
-a,--auto-rule auto add (and delete) iptables rule
|
||||
-g,--gen-rule generate iptables rule then exit,so that you can copy and
|
||||
add it manually.overrides -a
|
||||
--disable-anti-replay disable anti-replay,not suggested
|
||||
client options:
|
||||
--source-ip <ip> force source-ip for raw socket
|
||||
--source-port <port> force source-port for raw socket,tcp/udp only
|
||||
this option disables port changing while re-connecting
|
||||
other options:
|
||||
--conf-file <string> read options from a configuration file instead of command line.
|
||||
check example.conf in repo for format
|
||||
--fifo <string> use a fifo(named pipe) for sending commands to the running program,
|
||||
check readme.md in repository for supported commands.
|
||||
--log-level <number> 0:never 1:fatal 2:error 3:warn
|
||||
4:info (default) 5:debug 6:trace
|
||||
--log-position enable file name,function name,line number in log
|
||||
--disable-color disable log color
|
||||
--disable-bpf disable the kernel space filter,most time its not necessary
|
||||
unless you suspect there is a bug
|
||||
--sock-buf <number> buf size for socket,>=10 and <=10240,unit:kbyte,default:1024
|
||||
--force-sock-buf bypass system limitation while setting sock-buf
|
||||
--seq-mode <number> seq increase mode for faketcp:
|
||||
0:static header,do not increase seq and ack_seq
|
||||
1:increase seq for every packet,simply ack last seq
|
||||
2:increase seq randomly, about every 3 packets,simply ack last seq
|
||||
3:simulate an almost real seq/ack procedure(default)
|
||||
4:similiar to 3,but do not consider TCP Option Window_Scale,
|
||||
maybe useful when firewall doesnt support TCP Option
|
||||
--lower-level <string> send packets at OSI level 2, format:'if_name#dest_mac_adress'
|
||||
ie:'eth0#00:23:45:67:89:b9'.or try '--lower-level auto' to obtain
|
||||
the parameter automatically,specify it manually if 'auto' failed
|
||||
--gen-add generate iptables rule and add it permanently,then exit.overrides -g
|
||||
--keep-rule monitor iptables and auto re-add if necessary.implys -a
|
||||
--clear clear any iptables rules added by this program.overrides everything
|
||||
-h,--help print this help message
|
||||
|
||||
```
|
||||
|
||||
### Iptables rules,`-a` and `-g`
|
||||
This program sends packets via raw socket. In FakeTCP mode, Linux kernel TCP packet processing has to be blocked by a iptables rule on both sides, otherwise the kernel will automatically send RST for an unrecongized TCP packet and you will sustain from stability / peformance problems. You can use `-a` option to let the program automatically add / delete iptables rule on start / exit. You can also use the `-g` option to generate iptables rule and add it manually.
|
||||
|
||||
### `--cipher-mode` and `--auth-mode`
|
||||
It is suggested to use `aes128cbc` + `hmac_sha1` to obtain maximum security. If you want to run the program on a router, you can try `xor` + `simple`, which can fool packet inspection by firewalls the most of time, but it cannot protect you from serious attacks. Mode none is only for debugging purpose. It is not recommended to set the cipher-mode or auth-mode to none.
|
||||
|
||||
### `--seq-mode`
|
||||
The FakeTCP mode does not behave 100% like a real tcp connection. ISPs may be able to distinguish the simulated tcp traffic from the real TCP traffic (though it's costly). seq-mode can help you change the seq increase behavior slightly. If you experience connection problems, try to change the value.
|
||||
|
||||
### `--lower-level`
|
||||
`--lower-level` allows you to send packet at OSI level 2(link level),so that you can bypass any local iptables rules. If you have a complicated iptables rules which conflicts with udp2raw and you cant(or too lazy to) edit the iptables rules,`--lower-level` can be very useful. Try `--lower-level auto` to auto detect the parameters,you can specify it manually if `auto` fails.
|
||||
|
||||
Manual format `if_name#dest_mac_adress`,ie:`eth0#00:23:45:67:89:b9`.
|
||||
|
||||
### `--keep-rule`
|
||||
Monitor iptables and auto re-add iptables rules(for blocking kernel tcp processing) if necessary.Especially useful when iptables rules may be cleared by other programs(for example,if you are using openwrt,everytime you changed and commited a setting,iptables rule may be cleared and re-constructed).
|
||||
|
||||
### `--conf-file`
|
||||
|
||||
You can also load options from a configuration file in order to keep secrets away from `ps` command.
|
||||
|
||||
For example, rewrite the options for the above `server` example (in Getting Started section) into configuration file:
|
||||
|
||||
`server.conf`
|
||||
|
||||
```
|
||||
-s
|
||||
# You can add comments like this
|
||||
# Comments MUST occupy an entire line
|
||||
# Or they will not work as expected
|
||||
# Listen address
|
||||
-l 0.0.0.0:4096
|
||||
# Remote address
|
||||
-r 127.0.0.1:7777
|
||||
-a
|
||||
-k passwd
|
||||
--raw-mode faketcp
|
||||
```
|
||||
|
||||
Pay attention to the `-k` parameter: In command line mode the quotes around the password will be removed by shell. In configuration files we do not remove quotes.
|
||||
|
||||
Then start the server with
|
||||
|
||||
```bash
|
||||
./udp2raw_amd64 --conf-file server.conf
|
||||
```
|
||||
|
||||
### `--fifo`
|
||||
Use a fifo(named pipe) for sending commands to the running program. For example `--fifo fifo.file`.
|
||||
|
||||
At client side,you can use `echo reconnect >fifo.file` to force client to reconnect.Currently no command has been implemented for server.
|
||||
|
||||
# Peformance Test
|
||||
#### Test method:
|
||||
iperf3 TCP via OpenVPN + udp2raw
|
||||
(iperf3 UDP mode is not used because of a bug mentioned in this issue: https://github.com/esnet/iperf/issues/296 . Instead, we package the TCP traffic into UDP by OpenVPN to test the performance. Read [Application](https://github.com/wangyu-/udp2raw-tunnel#application) for details.
|
||||
|
||||
#### iperf3 command:
|
||||
```
|
||||
iperf3 -c 10.222.2.1 -P40
|
||||
iperf3 -c 10.222.2.1 -P40 -R
|
||||
```
|
||||
#### Environments
|
||||
* **Client** Vultr $2.5/monthly plan (single core 2.4GHz cpu, 512MB RAM, Tokyo, Japan)
|
||||
* **Server** BandwagonHost $3.99/annually plan (single core 2.0GHz cpu, 128MB RAM, Los Angeles, USA)
|
||||
|
||||
### Test1
|
||||
raw_mode: faketcp cipher_mode: xor auth_mode: simple
|
||||
|
||||

|
||||
|
||||
(reverse speed was simliar and not uploaded)
|
||||
|
||||
### Test2
|
||||
raw_mode: faketcp cipher_mode: aes128cbc auth_mode: md5
|
||||
|
||||

|
||||
|
||||
(reverse speed was simliar and not uploaded)
|
||||
|
||||
# wiki
|
||||
|
||||
Check wiki for more info:
|
||||
|
||||
https://github.com/wangyu-/udp2raw-tunnel/wiki
|
||||
|
895
client.cpp
Normal file
@ -0,0 +1,895 @@
|
||||
#include "common.h"
|
||||
#include "network.h"
|
||||
#include "connection.h"
|
||||
#include "misc.h"
|
||||
#include "log.h"
|
||||
#include "lib/md5.h"
|
||||
#include "encrypt.h"
|
||||
#include "fd_manager.h"
|
||||
|
||||
#ifdef UDP2RAW_MP
|
||||
u32_t detect_interval = 1500;
|
||||
u64_t laste_detect_time = 0;
|
||||
|
||||
int use_udp_for_detection = 0;
|
||||
int use_tcp_for_detection = 1;
|
||||
|
||||
extern pcap_t *pcap_handle;
|
||||
|
||||
extern int pcap_captured_full_len;
|
||||
#endif
|
||||
|
||||
int client_on_timer(conn_info_t &conn_info) // for client. called when a timer is ready in epoll
|
||||
{
|
||||
packet_info_t &send_info = conn_info.raw_info.send_info;
|
||||
packet_info_t &recv_info = conn_info.raw_info.recv_info;
|
||||
raw_info_t &raw_info = conn_info.raw_info;
|
||||
conn_info.blob->conv_manager.c.clear_inactive();
|
||||
mylog(log_trace, "timer!\n");
|
||||
|
||||
mylog(log_trace, "roller my %d,oppsite %d,%lld\n", int(conn_info.my_roller), int(conn_info.oppsite_roller), conn_info.last_oppsite_roller_time);
|
||||
|
||||
mylog(log_trace, "<client_on_timer,send_info.ts_ack= %u>\n", send_info.ts_ack);
|
||||
|
||||
#ifdef UDP2RAW_MP
|
||||
// mylog(log_debug,"pcap cnt :%d\n",pcap_cnt);
|
||||
if (send_with_pcap && !pcap_header_captured) {
|
||||
if (get_current_time() - laste_detect_time > detect_interval) {
|
||||
laste_detect_time = get_current_time();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
struct sockaddr_in remote_addr_in={0};
|
||||
|
||||
socklen_t slen = sizeof(sockaddr_in);
|
||||
int port=get_true_random_number()%65534+1;
|
||||
remote_addr_in.sin_family = AF_INET;
|
||||
remote_addr_in.sin_port = htons(port);
|
||||
remote_addr_in.sin_addr.s_addr = remote_ip_uint32;*/
|
||||
int port = get_true_random_number() % 65534 + 1;
|
||||
address_t tmp_addr = remote_addr;
|
||||
tmp_addr.set_port(port);
|
||||
|
||||
if (use_udp_for_detection) {
|
||||
int new_udp_fd = socket(tmp_addr.get_type(), SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (new_udp_fd < 0) {
|
||||
mylog(log_warn, "create new_udp_fd error\n");
|
||||
return -1;
|
||||
}
|
||||
setnonblocking(new_udp_fd);
|
||||
u64_t tmp = get_true_random_number();
|
||||
|
||||
int ret = sendto(new_udp_fd, (char *)(&tmp), sizeof(tmp), 0, (struct sockaddr *)&tmp_addr.inner, tmp_addr.get_len());
|
||||
if (ret == -1) {
|
||||
mylog(log_warn, "sendto() failed\n");
|
||||
}
|
||||
sock_close(new_udp_fd);
|
||||
}
|
||||
|
||||
if (use_tcp_for_detection) {
|
||||
static int last_tcp_fd = -1;
|
||||
|
||||
int new_tcp_fd = socket(tmp_addr.get_type(), SOCK_STREAM, IPPROTO_TCP);
|
||||
if (new_tcp_fd < 0) {
|
||||
mylog(log_warn, "create new_tcp_fd error\n");
|
||||
return -1;
|
||||
}
|
||||
setnonblocking(new_tcp_fd);
|
||||
connect(new_tcp_fd, (struct sockaddr *)&tmp_addr.inner, tmp_addr.get_len());
|
||||
if (last_tcp_fd != -1)
|
||||
sock_close(last_tcp_fd);
|
||||
last_tcp_fd = new_tcp_fd;
|
||||
// close(new_tcp_fd);
|
||||
}
|
||||
|
||||
mylog(log_info, "waiting for a use-able packet to be captured\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if (raw_info.disabled) {
|
||||
conn_info.state.client_current_state = client_idle;
|
||||
conn_info.my_id = get_true_random_number_nz();
|
||||
|
||||
mylog(log_info, "state back to client_idle\n");
|
||||
}
|
||||
|
||||
if (conn_info.state.client_current_state == client_idle) {
|
||||
raw_info.rst_received = 0;
|
||||
raw_info.disabled = 0;
|
||||
|
||||
fail_time_counter++;
|
||||
if (max_fail_time > 0 && fail_time_counter > max_fail_time) {
|
||||
mylog(log_fatal, "max_fail_time exceed\n");
|
||||
myexit(-1);
|
||||
}
|
||||
|
||||
conn_info.blob->anti_replay.re_init();
|
||||
conn_info.my_id = get_true_random_number_nz(); /// todo no need to do this everytime
|
||||
|
||||
address_t tmp_addr;
|
||||
// u32_t new_ip=0;
|
||||
if (!force_source_ip) {
|
||||
if (get_src_adress2(tmp_addr, remote_addr) != 0) {
|
||||
mylog(log_warn, "get_src_adress() failed\n");
|
||||
return -1;
|
||||
}
|
||||
// source_addr=new_addr;
|
||||
// source_addr.set_port(0);
|
||||
|
||||
mylog(log_info, "source_addr is now %s\n", tmp_addr.get_ip());
|
||||
|
||||
/*
|
||||
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;
|
||||
}*/
|
||||
|
||||
} else {
|
||||
tmp_addr = source_addr;
|
||||
}
|
||||
|
||||
send_info.new_src_ip.from_address_t(tmp_addr);
|
||||
|
||||
if (force_source_port == 0) {
|
||||
send_info.src_port = client_bind_to_a_new_port2(bind_fd, tmp_addr);
|
||||
} else {
|
||||
send_info.src_port = source_port;
|
||||
}
|
||||
|
||||
if (raw_mode == mode_icmp) {
|
||||
send_info.dst_port = send_info.src_port;
|
||||
}
|
||||
|
||||
mylog(log_info, "using port %d\n", send_info.src_port);
|
||||
init_filter(send_info.src_port);
|
||||
|
||||
if (raw_mode == mode_icmp || raw_mode == mode_udp) {
|
||||
conn_info.state.client_current_state = client_handshake1;
|
||||
|
||||
mylog(log_info, "state changed from client_idle to client_pre_handshake\n");
|
||||
}
|
||||
if (raw_mode == mode_faketcp) {
|
||||
if (use_tcp_dummy_socket) {
|
||||
setnonblocking(bind_fd);
|
||||
int ret = connect(bind_fd, (struct sockaddr *)&remote_addr.inner, remote_addr.get_len());
|
||||
mylog(log_debug, "ret=%d,errno=%s, %d %s\n", ret, get_sock_error(), bind_fd, remote_addr.get_str());
|
||||
// mylog(log_info,"ret=%d,errno=,%d %s\n",ret,bind_fd,remote_addr.get_str());
|
||||
conn_info.state.client_current_state = client_tcp_handshake_dummy;
|
||||
mylog(log_info, "state changed from client_idle to client_tcp_handshake_dummy\n");
|
||||
} else {
|
||||
conn_info.state.client_current_state = client_tcp_handshake;
|
||||
mylog(log_info, "state changed from client_idle to client_tcp_handshake\n");
|
||||
}
|
||||
}
|
||||
conn_info.last_state_time = get_current_time();
|
||||
conn_info.last_hb_sent_time = 0;
|
||||
// dont return;
|
||||
}
|
||||
if (conn_info.state.client_current_state == client_tcp_handshake) // send and resend syn
|
||||
{
|
||||
assert(raw_mode == mode_faketcp);
|
||||
if (get_current_time() - conn_info.last_state_time > client_handshake_timeout) {
|
||||
conn_info.state.client_current_state = client_idle;
|
||||
mylog(log_info, "state back to client_idle from client_tcp_handshake\n");
|
||||
return 0;
|
||||
|
||||
} else if (get_current_time() - conn_info.last_hb_sent_time > client_retry_interval) {
|
||||
if (raw_mode == mode_faketcp) {
|
||||
if (conn_info.last_hb_sent_time == 0) {
|
||||
send_info.psh = 0;
|
||||
send_info.syn = 1;
|
||||
send_info.ack = 0;
|
||||
send_info.ts_ack = 0;
|
||||
send_info.seq = get_true_random_number();
|
||||
send_info.ack_seq = get_true_random_number();
|
||||
}
|
||||
}
|
||||
|
||||
send_raw0(raw_info, 0, 0);
|
||||
|
||||
conn_info.last_hb_sent_time = get_current_time();
|
||||
mylog(log_info, "(re)sent tcp syn\n");
|
||||
return 0;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
} else if (conn_info.state.client_current_state == client_tcp_handshake_dummy) {
|
||||
assert(raw_mode == mode_faketcp);
|
||||
if (get_current_time() - conn_info.last_state_time > client_handshake_timeout) {
|
||||
conn_info.state.client_current_state = client_idle;
|
||||
mylog(log_info, "state back to client_idle from client_tcp_handshake_dummy\n");
|
||||
return 0;
|
||||
}
|
||||
} else if (conn_info.state.client_current_state == client_handshake1) // send and resend handshake1
|
||||
{
|
||||
if (get_current_time() - conn_info.last_state_time > client_handshake_timeout) {
|
||||
conn_info.state.client_current_state = client_idle;
|
||||
mylog(log_info, "state back to client_idle from client_handshake1\n");
|
||||
return 0;
|
||||
|
||||
} else if (get_current_time() - conn_info.last_hb_sent_time > client_retry_interval) {
|
||||
if (raw_mode == mode_faketcp) {
|
||||
if (conn_info.last_hb_sent_time == 0) {
|
||||
send_info.seq++;
|
||||
send_info.ack_seq = recv_info.seq + 1;
|
||||
send_info.ts_ack = recv_info.ts;
|
||||
raw_info.reserved_send_seq = send_info.seq;
|
||||
}
|
||||
send_info.seq = raw_info.reserved_send_seq;
|
||||
send_info.psh = 0;
|
||||
send_info.syn = 0;
|
||||
send_info.ack = 1;
|
||||
|
||||
if (!use_tcp_dummy_socket)
|
||||
send_raw0(raw_info, 0, 0);
|
||||
|
||||
send_handshake(raw_info, conn_info.my_id, 0, const_id);
|
||||
|
||||
send_info.seq += raw_info.send_info.data_len;
|
||||
} else {
|
||||
send_handshake(raw_info, conn_info.my_id, 0, const_id);
|
||||
if (raw_mode == mode_icmp)
|
||||
send_info.my_icmp_seq++;
|
||||
}
|
||||
|
||||
conn_info.last_hb_sent_time = get_current_time();
|
||||
mylog(log_info, "(re)sent handshake1\n");
|
||||
return 0;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
} else if (conn_info.state.client_current_state == client_handshake2) {
|
||||
if (get_current_time() - conn_info.last_state_time > client_handshake_timeout) {
|
||||
conn_info.state.client_current_state = client_idle;
|
||||
mylog(log_info, "state back to client_idle from client_handshake2\n");
|
||||
return 0;
|
||||
} else if (get_current_time() - conn_info.last_hb_sent_time > client_retry_interval) {
|
||||
if (raw_mode == mode_faketcp) {
|
||||
if (conn_info.last_hb_sent_time == 0) {
|
||||
send_info.ack_seq = recv_info.seq + raw_info.recv_info.data_len;
|
||||
send_info.ts_ack = recv_info.ts;
|
||||
raw_info.reserved_send_seq = send_info.seq;
|
||||
}
|
||||
send_info.seq = raw_info.reserved_send_seq;
|
||||
send_handshake(raw_info, conn_info.my_id, conn_info.oppsite_id, const_id);
|
||||
send_info.seq += raw_info.send_info.data_len;
|
||||
|
||||
} else {
|
||||
send_handshake(raw_info, conn_info.my_id, conn_info.oppsite_id, const_id);
|
||||
if (raw_mode == mode_icmp)
|
||||
send_info.my_icmp_seq++;
|
||||
}
|
||||
conn_info.last_hb_sent_time = get_current_time();
|
||||
mylog(log_info, "(re)sent handshake2\n");
|
||||
return 0;
|
||||
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
} else if (conn_info.state.client_current_state == client_ready) {
|
||||
fail_time_counter = 0;
|
||||
mylog(log_trace, "time %llu,%llu\n", get_current_time(), conn_info.last_state_time);
|
||||
|
||||
if (get_current_time() - conn_info.last_hb_recv_time > client_conn_timeout) {
|
||||
conn_info.state.client_current_state = client_idle;
|
||||
conn_info.my_id = get_true_random_number_nz();
|
||||
mylog(log_info, "state back to client_idle from client_ready bc of server-->client direction timeout\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (get_current_time() - conn_info.last_oppsite_roller_time > client_conn_uplink_timeout) {
|
||||
conn_info.state.client_current_state = client_idle;
|
||||
conn_info.my_id = get_true_random_number_nz();
|
||||
mylog(log_info, "state back to client_idle from client_ready bc of client-->server direction timeout\n");
|
||||
}
|
||||
|
||||
if (get_current_time() - conn_info.last_hb_sent_time < heartbeat_interval) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
mylog(log_debug, "heartbeat sent <%x,%x>\n", conn_info.oppsite_id, conn_info.my_id);
|
||||
|
||||
if (hb_mode == 0)
|
||||
send_safer(conn_info, 'h', hb_buf, 0); /////////////send
|
||||
else
|
||||
send_safer(conn_info, 'h', hb_buf, hb_len);
|
||||
conn_info.last_hb_sent_time = get_current_time();
|
||||
return 0;
|
||||
} else {
|
||||
mylog(log_fatal, "unknown state,this shouldnt happen.\n");
|
||||
myexit(-1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int client_on_raw_recv_hs2_or_ready(conn_info_t &conn_info, char type, char *data, int data_len) {
|
||||
packet_info_t &send_info = conn_info.raw_info.send_info;
|
||||
packet_info_t &recv_info = conn_info.raw_info.recv_info;
|
||||
|
||||
if (!recv_info.new_src_ip.equal(send_info.new_dst_ip) || recv_info.src_port != send_info.dst_port) {
|
||||
mylog(log_warn, "unexpected adress %s %s %d %d,this shouldnt happen.\n", recv_info.new_src_ip.get_str1(), send_info.new_dst_ip.get_str2(), recv_info.src_port, send_info.dst_port);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (conn_info.state.client_current_state == client_handshake2) {
|
||||
mylog(log_info, "changed state from to client_handshake2 to client_ready\n");
|
||||
conn_info.state.client_current_state = client_ready;
|
||||
conn_info.last_hb_sent_time = 0;
|
||||
conn_info.last_hb_recv_time = get_current_time();
|
||||
conn_info.last_oppsite_roller_time = conn_info.last_hb_recv_time;
|
||||
client_on_timer(conn_info);
|
||||
}
|
||||
if (data_len >= 0 && type == 'h') {
|
||||
mylog(log_debug, "[hb]heart beat received,oppsite_roller=%d\n", int(conn_info.oppsite_roller));
|
||||
conn_info.last_hb_recv_time = get_current_time();
|
||||
return 0;
|
||||
} else if (data_len >= int(sizeof(u32_t)) && type == 'd') {
|
||||
mylog(log_trace, "received a data from fake tcp,len:%d\n", data_len);
|
||||
|
||||
if (hb_mode == 0)
|
||||
conn_info.last_hb_recv_time = get_current_time();
|
||||
|
||||
u32_t tmp_conv_id;
|
||||
memcpy(&tmp_conv_id, &data[0], sizeof(tmp_conv_id));
|
||||
tmp_conv_id = ntohl(tmp_conv_id);
|
||||
|
||||
if (!conn_info.blob->conv_manager.c.is_conv_used(tmp_conv_id)) {
|
||||
mylog(log_info, "unknow conv %d,ignore\n", tmp_conv_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
conn_info.blob->conv_manager.c.update_active_time(tmp_conv_id);
|
||||
|
||||
// u64_t u64=conn_info.blob->conv_manager.c.find_data_by_conv(tmp_conv_id);
|
||||
address_t tmp_addr = conn_info.blob->conv_manager.c.find_data_by_conv(tmp_conv_id);
|
||||
|
||||
// sockaddr_in tmp_sockaddr={0};
|
||||
|
||||
// tmp_sockaddr.sin_family = AF_INET;
|
||||
// tmp_sockaddr.sin_addr.s_addr=(u64>>32u);
|
||||
|
||||
// tmp_sockaddr.sin_port= htons(uint16_t((u64<<32u)>>32u));
|
||||
|
||||
int ret = sendto(udp_fd, data + sizeof(u32_t), data_len - (sizeof(u32_t)), 0, (struct sockaddr *)&tmp_addr.inner, tmp_addr.get_len());
|
||||
|
||||
if (ret < 0) {
|
||||
mylog(log_warn, "sento returned %d,%s,%02x,%s\n", ret, get_sock_error(), int(tmp_addr.get_type()), tmp_addr.get_str());
|
||||
// perror("ret<0");
|
||||
}
|
||||
} else {
|
||||
mylog(log_warn, "unknown packet,this shouldnt happen.\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int client_on_raw_recv(conn_info_t &conn_info) // called when raw fd received a packet.
|
||||
{
|
||||
char *data;
|
||||
int data_len;
|
||||
packet_info_t &send_info = conn_info.raw_info.send_info;
|
||||
packet_info_t &recv_info = conn_info.raw_info.recv_info;
|
||||
|
||||
raw_info_t &raw_info = conn_info.raw_info;
|
||||
|
||||
mylog(log_trace, "<client_on_raw_recv,send_info.ts_ack= %u>\n", send_info.ts_ack);
|
||||
|
||||
#ifdef UDP2RAW_LINUX
|
||||
if (pre_recv_raw_packet() < 0) return -1;
|
||||
#endif
|
||||
|
||||
if (conn_info.state.client_current_state == client_idle) {
|
||||
discard_raw_packet();
|
||||
// recv(raw_recv_fd, 0,0, 0 );
|
||||
} else if (conn_info.state.client_current_state == client_tcp_handshake || conn_info.state.client_current_state == client_tcp_handshake_dummy) // received syn ack
|
||||
{
|
||||
assert(raw_mode == mode_faketcp);
|
||||
if (recv_raw0(raw_info, data, data_len) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (data_len >= max_data_len + 1) {
|
||||
mylog(log_debug, "data_len=%d >= max_data_len+1,ignored", data_len);
|
||||
return -1;
|
||||
}
|
||||
if (!recv_info.new_src_ip.equal(send_info.new_dst_ip) || recv_info.src_port != send_info.dst_port) {
|
||||
mylog(log_debug, "unexpected adress %s %s %d %d\n", recv_info.new_src_ip.get_str1(), send_info.new_dst_ip.get_str2(), recv_info.src_port, send_info.dst_port);
|
||||
return -1;
|
||||
}
|
||||
if (data_len == 0 && raw_info.recv_info.syn == 1 && raw_info.recv_info.ack == 1) {
|
||||
if (conn_info.state.client_current_state == client_tcp_handshake) {
|
||||
if (recv_info.ack_seq != send_info.seq + 1) {
|
||||
mylog(log_debug, "seq ack_seq mis match\n");
|
||||
return -1;
|
||||
}
|
||||
mylog(log_info, "state changed from client_tcp_handshake to client_handshake1\n");
|
||||
} else {
|
||||
send_info.seq = recv_info.ack_seq - 1;
|
||||
mylog(log_info, "state changed from client_tcp_dummy to client_handshake1\n");
|
||||
// send_info.ack_seq=recv_info.seq+1;
|
||||
}
|
||||
conn_info.state.client_current_state = client_handshake1;
|
||||
|
||||
conn_info.last_state_time = get_current_time();
|
||||
conn_info.last_hb_sent_time = 0;
|
||||
client_on_timer(conn_info);
|
||||
return 0;
|
||||
} else {
|
||||
mylog(log_debug, "unexpected packet type,expected:syn ack\n");
|
||||
return -1;
|
||||
}
|
||||
} else if (conn_info.state.client_current_state == client_handshake1) // recevied respond of handshake1
|
||||
{
|
||||
if (recv_bare(raw_info, data, data_len) != 0) {
|
||||
mylog(log_debug, "recv_bare failed!\n");
|
||||
return -1;
|
||||
}
|
||||
if (!recv_info.new_src_ip.equal(send_info.new_dst_ip) || recv_info.src_port != send_info.dst_port) {
|
||||
mylog(log_debug, "unexpected adress %s %s %d %d\n", recv_info.new_src_ip.get_str1(), send_info.new_dst_ip.get_str2(), recv_info.src_port, send_info.dst_port);
|
||||
return -1;
|
||||
}
|
||||
if (data_len < int(3 * sizeof(my_id_t))) {
|
||||
mylog(log_debug, "too short to be a handshake\n");
|
||||
return -1;
|
||||
}
|
||||
my_id_t tmp_oppsite_id;
|
||||
memcpy(&tmp_oppsite_id, &data[0], sizeof(tmp_oppsite_id));
|
||||
tmp_oppsite_id = ntohl(tmp_oppsite_id);
|
||||
|
||||
my_id_t tmp_my_id;
|
||||
memcpy(&tmp_my_id, &data[sizeof(my_id_t)], sizeof(tmp_my_id));
|
||||
tmp_my_id = ntohl(tmp_my_id);
|
||||
|
||||
my_id_t tmp_oppsite_const_id;
|
||||
memcpy(&tmp_oppsite_const_id, &data[sizeof(my_id_t) * 2], sizeof(tmp_oppsite_const_id));
|
||||
tmp_oppsite_const_id = ntohl(tmp_oppsite_const_id);
|
||||
|
||||
if (tmp_my_id != conn_info.my_id) {
|
||||
mylog(log_debug, "tmp_my_id doesnt match\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (raw_mode == mode_faketcp) {
|
||||
if (recv_info.ack_seq != send_info.seq) {
|
||||
mylog(log_debug, "seq ack_seq mis match\n");
|
||||
return -1;
|
||||
}
|
||||
if (recv_info.seq != send_info.ack_seq) {
|
||||
mylog(log_debug, "seq ack_seq mis match\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
conn_info.oppsite_id = tmp_oppsite_id;
|
||||
|
||||
mylog(log_info, "changed state from to client_handshake1 to client_handshake2,my_id is %x,oppsite id is %x\n", conn_info.my_id, conn_info.oppsite_id);
|
||||
|
||||
conn_info.state.client_current_state = client_handshake2;
|
||||
conn_info.last_state_time = get_current_time();
|
||||
conn_info.last_hb_sent_time = 0;
|
||||
client_on_timer(conn_info);
|
||||
|
||||
return 0;
|
||||
} else if (conn_info.state.client_current_state == client_handshake2 || conn_info.state.client_current_state == client_ready) // received heartbeat or data
|
||||
{
|
||||
vector<char> type_vec;
|
||||
vector<string> data_vec;
|
||||
recv_safer_multi(conn_info, type_vec, data_vec);
|
||||
if (data_vec.empty()) {
|
||||
mylog(log_debug, "recv_safer failed!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < (int)type_vec.size(); i++) {
|
||||
char type = type_vec[i];
|
||||
char *data = (char *)data_vec[i].c_str(); // be careful, do not append data to it
|
||||
int data_len = data_vec[i].length();
|
||||
client_on_raw_recv_hs2_or_ready(conn_info, type, data, data_len);
|
||||
}
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
mylog(log_fatal, "unknown state,this shouldnt happen.\n");
|
||||
myexit(-1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int client_on_udp_recv(conn_info_t &conn_info) {
|
||||
int recv_len;
|
||||
char buf[buf_len];
|
||||
address_t::storage_t udp_new_addr_in = {{0}};
|
||||
socklen_t udp_new_addr_len = sizeof(address_t::storage_t);
|
||||
if ((recv_len = recvfrom(udp_fd, buf, max_data_len + 1, 0,
|
||||
(struct sockaddr *)&udp_new_addr_in, &udp_new_addr_len)) == -1) {
|
||||
mylog(log_debug, "recv_from error,%s\n", get_sock_error());
|
||||
return -1;
|
||||
// myexit(1);
|
||||
};
|
||||
|
||||
if (recv_len == max_data_len + 1) {
|
||||
mylog(log_warn, "huge packet, data_len > %d,dropped\n", max_data_len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (recv_len >= mtu_warn) {
|
||||
mylog(log_warn, "huge packet,data len=%d (>=%d).strongly suggested to set a smaller mtu at upper level,to get rid of this warn\n ", recv_len, mtu_warn);
|
||||
}
|
||||
|
||||
address_t tmp_addr;
|
||||
tmp_addr.from_sockaddr((sockaddr *)&udp_new_addr_in, udp_new_addr_len);
|
||||
u32_t conv;
|
||||
|
||||
if (!conn_info.blob->conv_manager.c.is_data_used(tmp_addr)) {
|
||||
if (conn_info.blob->conv_manager.c.get_size() >= max_conv_num) {
|
||||
mylog(log_warn, "ignored new udp connect bc max_conv_num exceed\n");
|
||||
return -1;
|
||||
}
|
||||
conv = conn_info.blob->conv_manager.c.get_new_conv();
|
||||
conn_info.blob->conv_manager.c.insert_conv(conv, tmp_addr);
|
||||
mylog(log_info, "new packet from %s,conv_id=%x\n", tmp_addr.get_str(), conv);
|
||||
} else {
|
||||
conv = conn_info.blob->conv_manager.c.find_conv_by_data(tmp_addr);
|
||||
}
|
||||
|
||||
conn_info.blob->conv_manager.c.update_active_time(conv);
|
||||
|
||||
if (conn_info.state.client_current_state == client_ready) {
|
||||
send_data_safer(conn_info, buf, recv_len, conv);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
void udp_accept_cb(struct ev_loop *loop, struct ev_io *watcher, int revents) {
|
||||
conn_info_t &conn_info = *((conn_info_t *)watcher->data);
|
||||
client_on_udp_recv(conn_info);
|
||||
}
|
||||
void raw_recv_cb(struct ev_loop *loop, struct ev_io *watcher, int revents) {
|
||||
if (is_udp2raw_mp) assert(0 == 1);
|
||||
conn_info_t &conn_info = *((conn_info_t *)watcher->data);
|
||||
client_on_raw_recv(conn_info);
|
||||
}
|
||||
#ifdef UDP2RAW_MP
|
||||
void async_cb(struct ev_loop *loop, struct ev_async *watcher, int revents) {
|
||||
conn_info_t &conn_info = *((conn_info_t *)watcher->data);
|
||||
|
||||
if (send_with_pcap && !pcap_header_captured) {
|
||||
int empty = 0;
|
||||
char *p;
|
||||
int len;
|
||||
pthread_mutex_lock(&queue_mutex);
|
||||
empty = my_queue.empty();
|
||||
if (!empty) {
|
||||
my_queue.peek_front(p, len);
|
||||
my_queue.pop_front();
|
||||
}
|
||||
pthread_mutex_unlock(&queue_mutex);
|
||||
if (empty) return;
|
||||
|
||||
pcap_header_captured = 1;
|
||||
assert(pcap_link_header_len != -1);
|
||||
memcpy(pcap_header_buf, p, max_data_len);
|
||||
|
||||
log_bare(log_info, "link level header captured:\n");
|
||||
unsigned char *tmp = (unsigned char *)pcap_header_buf;
|
||||
pcap_captured_full_len = len;
|
||||
for (int i = 0; i < pcap_link_header_len; i++)
|
||||
log_bare(log_info, "<%x>", (u32_t)tmp[i]);
|
||||
|
||||
log_bare(log_info, "\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// mylog(log_info,"async_cb called\n");
|
||||
while (1) {
|
||||
int empty = 0;
|
||||
char *p;
|
||||
int len;
|
||||
pthread_mutex_lock(&queue_mutex);
|
||||
empty = my_queue.empty();
|
||||
if (!empty) {
|
||||
my_queue.peek_front(p, len);
|
||||
my_queue.pop_front();
|
||||
}
|
||||
pthread_mutex_unlock(&queue_mutex);
|
||||
|
||||
if (empty) break;
|
||||
if (g_fix_gro == 0 && len > max_data_len) {
|
||||
mylog(log_warn, "huge packet %d > %d, dropped. maybe you need to turn down mtu at upper level, or maybe you need the --fix-gro option\n", len, max_data_len);
|
||||
break;
|
||||
}
|
||||
|
||||
int new_len = len - pcap_link_header_len;
|
||||
memcpy(g_packet_buf, p + pcap_link_header_len, new_len);
|
||||
g_packet_buf_len = new_len;
|
||||
assert(g_packet_buf_cnt == 0);
|
||||
g_packet_buf_cnt++;
|
||||
client_on_raw_recv(conn_info);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
void clear_timer_cb(struct ev_loop *loop, struct ev_timer *watcher, int revents) {
|
||||
conn_info_t &conn_info = *((conn_info_t *)watcher->data);
|
||||
client_on_timer(conn_info);
|
||||
}
|
||||
void fifo_cb(struct ev_loop *loop, struct ev_io *watcher, int revents) {
|
||||
conn_info_t &conn_info = *((conn_info_t *)watcher->data);
|
||||
|
||||
char buf[buf_len];
|
||||
int fifo_fd = watcher->fd;
|
||||
|
||||
int len = read(fifo_fd, buf, sizeof(buf));
|
||||
if (len < 0) {
|
||||
mylog(log_warn, "fifo read failed len=%d,errno=%s\n", len, get_sock_error());
|
||||
return;
|
||||
}
|
||||
buf[len] = 0;
|
||||
while (len >= 1 && buf[len - 1] == '\n')
|
||||
buf[len - 1] = 0;
|
||||
mylog(log_info, "got data from fifo,len=%d,s=[%s]\n", len, buf);
|
||||
if (strcmp(buf, "reconnect") == 0) {
|
||||
mylog(log_info, "received command: reconnect\n");
|
||||
conn_info.state.client_current_state = client_idle;
|
||||
conn_info.my_id = get_true_random_number_nz();
|
||||
} else {
|
||||
mylog(log_info, "unknown command\n");
|
||||
}
|
||||
}
|
||||
int client_event_loop() {
|
||||
char buf[buf_len];
|
||||
|
||||
conn_info_t conn_info;
|
||||
conn_info.my_id = get_true_random_number_nz();
|
||||
|
||||
conn_info.prepare();
|
||||
packet_info_t &send_info = conn_info.raw_info.send_info;
|
||||
packet_info_t &recv_info = conn_info.raw_info.recv_info;
|
||||
|
||||
#ifdef UDP2RAW_LINUX
|
||||
if (lower_level) {
|
||||
if (lower_level_manual) {
|
||||
int index;
|
||||
init_ifindex(if_name, raw_send_fd, index);
|
||||
// init_ifindex(if_name);
|
||||
memset(&send_info.addr_ll, 0, sizeof(send_info.addr_ll));
|
||||
send_info.addr_ll.sll_family = AF_PACKET;
|
||||
send_info.addr_ll.sll_ifindex = index;
|
||||
send_info.addr_ll.sll_halen = ETHER_ADDR_LEN;
|
||||
send_info.addr_ll.sll_protocol = htons(ETH_P_IP);
|
||||
memcpy(&send_info.addr_ll.sll_addr, dest_hw_addr, ETHER_ADDR_LEN);
|
||||
mylog(log_info, "we are running at lower-level (manual) mode\n");
|
||||
} else {
|
||||
u32_t dest_ip;
|
||||
string if_name_string;
|
||||
string hw_string;
|
||||
assert(remote_addr.get_type() == AF_INET);
|
||||
|
||||
if (retry_on_error == 0) {
|
||||
if (find_lower_level_info(remote_addr.inner.ipv4.sin_addr.s_addr, dest_ip, if_name_string, hw_string) != 0) {
|
||||
mylog(log_fatal, "auto detect lower-level info failed for %s,specific it manually\n", remote_addr.get_ip());
|
||||
myexit(-1);
|
||||
}
|
||||
} else {
|
||||
int ok = 0;
|
||||
while (!ok) {
|
||||
if (find_lower_level_info(remote_addr.inner.ipv4.sin_addr.s_addr, dest_ip, if_name_string, hw_string) != 0) {
|
||||
mylog(log_warn, "auto detect lower-level info failed for %s,retry in %d seconds\n", remote_addr.get_ip(), retry_on_error_interval);
|
||||
sleep(retry_on_error_interval);
|
||||
} else {
|
||||
ok = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
mylog(log_info, "we are running at lower-level (auto) mode,%s %s %s\n", my_ntoa(dest_ip), if_name_string.c_str(), hw_string.c_str());
|
||||
|
||||
u32_t hw[6];
|
||||
memset(hw, 0, sizeof(hw));
|
||||
sscanf(hw_string.c_str(), "%x:%x:%x:%x:%x:%x", &hw[0], &hw[1], &hw[2],
|
||||
&hw[3], &hw[4], &hw[5]);
|
||||
|
||||
mylog(log_warn,
|
||||
"make sure this is correct: if_name=<%s> dest_mac_adress=<%02x:%02x:%02x:%02x:%02x:%02x> \n",
|
||||
if_name_string.c_str(), hw[0], hw[1], hw[2], hw[3], hw[4], hw[5]);
|
||||
for (int i = 0; i < 6; i++) {
|
||||
dest_hw_addr[i] = uint8_t(hw[i]);
|
||||
}
|
||||
|
||||
// mylog(log_fatal,"--lower-level auto for client hasnt been implemented\n");
|
||||
int index;
|
||||
init_ifindex(if_name_string.c_str(), raw_send_fd, index);
|
||||
|
||||
memset(&send_info.addr_ll, 0, sizeof(send_info.addr_ll));
|
||||
send_info.addr_ll.sll_family = AF_PACKET;
|
||||
send_info.addr_ll.sll_ifindex = index;
|
||||
send_info.addr_ll.sll_halen = ETHER_ADDR_LEN;
|
||||
send_info.addr_ll.sll_protocol = htons(ETH_P_IP);
|
||||
memcpy(&send_info.addr_ll.sll_addr, dest_hw_addr, ETHER_ADDR_LEN);
|
||||
// mylog(log_info,"we are running at lower-level (manual) mode\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UDP2RAW_MP
|
||||
|
||||
address_t tmp_addr;
|
||||
if (get_src_adress2(tmp_addr, remote_addr) != 0) {
|
||||
mylog(log_error, "get_src_adress() failed\n");
|
||||
myexit(-1);
|
||||
}
|
||||
if (strcmp(dev, "") == 0) {
|
||||
mylog(log_info, "--dev have not been set, trying to detect automatically, available devices:\n");
|
||||
|
||||
mylog(log_info, "available device(device name: ip address ; description):\n");
|
||||
|
||||
char errbuf[PCAP_ERRBUF_SIZE];
|
||||
|
||||
int found = 0;
|
||||
|
||||
pcap_if_t *interfaces, *d;
|
||||
if (pcap_findalldevs(&interfaces, errbuf) == -1) {
|
||||
mylog(log_fatal, "error in pcap_findalldevs(),%s\n", errbuf);
|
||||
myexit(-1);
|
||||
}
|
||||
|
||||
for (pcap_if_t *d = interfaces; d != NULL; d = d->next) {
|
||||
log_bare(log_warn, "%s:", d->name);
|
||||
int cnt = 0;
|
||||
for (pcap_addr_t *a = d->addresses; a != NULL; a = a->next) {
|
||||
if (a->addr == NULL) {
|
||||
log_bare(log_debug, " [a->addr==NULL]");
|
||||
continue;
|
||||
}
|
||||
if (a->addr->sa_family == AF_INET || a->addr->sa_family == AF_INET6) {
|
||||
cnt++;
|
||||
|
||||
if (a->addr->sa_family == AF_INET) {
|
||||
char s[max_addr_len];
|
||||
inet_ntop(AF_INET, &((struct sockaddr_in *)a->addr)->sin_addr, s, max_addr_len);
|
||||
log_bare(log_warn, " [%s]", s);
|
||||
|
||||
if (a->addr->sa_family == raw_ip_version) {
|
||||
if (((struct sockaddr_in *)a->addr)->sin_addr.s_addr == tmp_addr.inner.ipv4.sin_addr.s_addr) {
|
||||
found++;
|
||||
strcpy(dev, d->name);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
assert(a->addr->sa_family == AF_INET6);
|
||||
|
||||
char s[max_addr_len];
|
||||
inet_ntop(AF_INET6, &((struct sockaddr_in6 *)a->addr)->sin6_addr, s, max_addr_len);
|
||||
log_bare(log_warn, " [%s]", s);
|
||||
|
||||
if (a->addr->sa_family == raw_ip_version) {
|
||||
if (memcmp(&((struct sockaddr_in6 *)a->addr)->sin6_addr, &tmp_addr.inner.ipv6.sin6_addr, sizeof(struct in6_addr)) == 0) {
|
||||
found++;
|
||||
strcpy(dev, d->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log_bare(log_debug, " [unknow:%d]", int(a->addr->sa_family));
|
||||
}
|
||||
}
|
||||
if (cnt == 0) log_bare(log_warn, " [no ip found]");
|
||||
if (d->description == 0) {
|
||||
log_bare(log_warn, "; (no description available)");
|
||||
} else {
|
||||
log_bare(log_warn, "; %s", d->description);
|
||||
}
|
||||
log_bare(log_warn, "\n");
|
||||
}
|
||||
|
||||
if (found == 0) {
|
||||
mylog(log_fatal, "no matched device found for ip: [%s]\n", tmp_addr.get_ip());
|
||||
myexit(-1);
|
||||
} else if (found == 1) {
|
||||
mylog(log_info, "using device:[%s], ip: [%s]\n", dev, tmp_addr.get_ip());
|
||||
} else {
|
||||
mylog(log_fatal, "more than one devices found for ip: [%s] , you need to use --dev manually\n", tmp_addr.get_ip());
|
||||
myexit(-1);
|
||||
}
|
||||
} else {
|
||||
mylog(log_info, "--dev has been manually set, using device:[%s]\n", dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
send_info.src_port = 0;
|
||||
memset(&send_info.new_src_ip, 0, sizeof(send_info.new_src_ip));
|
||||
|
||||
int i, j, k;
|
||||
int ret;
|
||||
|
||||
send_info.new_dst_ip.from_address_t(remote_addr);
|
||||
send_info.dst_port = remote_addr.get_port();
|
||||
|
||||
udp_fd = socket(local_addr.get_type(), SOCK_DGRAM, IPPROTO_UDP);
|
||||
set_buf_size(udp_fd, socket_buf_size);
|
||||
|
||||
if (::bind(udp_fd, (struct sockaddr *)&local_addr.inner, local_addr.get_len()) == -1) {
|
||||
mylog(log_fatal, "socket bind error\n");
|
||||
// perror("socket bind error");
|
||||
myexit(1);
|
||||
}
|
||||
setnonblocking(udp_fd);
|
||||
|
||||
// epollfd = epoll_create1(0);
|
||||
|
||||
// const int max_events = 4096;
|
||||
// struct epoll_event ev, events[max_events];
|
||||
// if (epollfd < 0) {
|
||||
// mylog(log_fatal,"epoll return %d\n", epollfd);
|
||||
// myexit(-1);
|
||||
// }
|
||||
|
||||
struct ev_loop *loop = ev_default_loop(0);
|
||||
assert(loop != NULL);
|
||||
|
||||
// ev.events = EPOLLIN;
|
||||
// ev.data.u64 = udp_fd;
|
||||
// ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, udp_fd, &ev);
|
||||
// if (ret!=0) {
|
||||
// mylog(log_fatal,"add udp_listen_fd error\n");
|
||||
// myexit(-1);
|
||||
// }
|
||||
|
||||
struct ev_io udp_accept_watcher;
|
||||
|
||||
udp_accept_watcher.data = &conn_info;
|
||||
ev_io_init(&udp_accept_watcher, udp_accept_cb, udp_fd, EV_READ);
|
||||
ev_io_start(loop, &udp_accept_watcher);
|
||||
|
||||
// ev.events = EPOLLIN;
|
||||
// ev.data.u64 = raw_recv_fd;
|
||||
|
||||
// ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, raw_recv_fd, &ev);
|
||||
// if (ret!= 0) {
|
||||
// mylog(log_fatal,"add raw_fd error\n");
|
||||
// myexit(-1);
|
||||
// }
|
||||
|
||||
#ifdef UDP2RAW_LINUX
|
||||
struct ev_io raw_recv_watcher;
|
||||
|
||||
raw_recv_watcher.data = &conn_info;
|
||||
ev_io_init(&raw_recv_watcher, raw_recv_cb, raw_recv_fd, EV_READ);
|
||||
ev_io_start(loop, &raw_recv_watcher);
|
||||
#endif
|
||||
|
||||
#ifdef UDP2RAW_MP
|
||||
g_default_loop = loop;
|
||||
async_watcher.data = &conn_info;
|
||||
ev_async_init(&async_watcher, async_cb);
|
||||
ev_async_start(loop, &async_watcher);
|
||||
|
||||
init_raw_socket(); // must be put after dev detection
|
||||
#endif
|
||||
|
||||
// set_timer(epollfd,timer_fd);
|
||||
struct ev_timer clear_timer;
|
||||
|
||||
clear_timer.data = &conn_info;
|
||||
ev_timer_init(&clear_timer, clear_timer_cb, 0, timer_interval / 1000.0);
|
||||
ev_timer_start(loop, &clear_timer);
|
||||
|
||||
mylog(log_debug, "send_raw : from %s %d to %s %d\n", send_info.new_src_ip.get_str1(), send_info.src_port, send_info.new_dst_ip.get_str2(), send_info.dst_port);
|
||||
|
||||
int fifo_fd = -1;
|
||||
|
||||
struct ev_io fifo_watcher;
|
||||
fifo_watcher.data = &conn_info;
|
||||
|
||||
if (fifo_file[0] != 0) {
|
||||
fifo_fd = create_fifo(fifo_file);
|
||||
|
||||
ev_io_init(&fifo_watcher, fifo_cb, fifo_fd, EV_READ);
|
||||
ev_io_start(loop, &fifo_watcher);
|
||||
|
||||
mylog(log_info, "fifo_file=%s\n", fifo_file);
|
||||
}
|
||||
|
||||
ev_run(loop, 0);
|
||||
return 0;
|
||||
}
|
1324
common.cpp
557
common.h
@ -5,103 +5,149 @@
|
||||
* Author: wangyu
|
||||
*/
|
||||
|
||||
#ifndef COMMON_H_
|
||||
#define COMMON_H_
|
||||
#ifndef UDP2RAW_COMMON_H_
|
||||
#define UDP2RAW_COMMON_H_
|
||||
#define __STDC_FORMAT_MACROS 1
|
||||
#include <inttypes.h>
|
||||
|
||||
#include<stdio.h>
|
||||
#include<string.h>
|
||||
#include<stdlib.h>
|
||||
#include<getopt.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include<unistd.h>
|
||||
#include<errno.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/socket.h> //for socket ofcourse
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h> //for exit(0);
|
||||
#include <errno.h> //For errno - the error number
|
||||
#include <netinet/tcp.h> //Provides declarations for tcp header
|
||||
#include <netinet/udp.h>
|
||||
#include <netinet/ip.h> //Provides declarations for ip header
|
||||
#include <netinet/if_ether.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h> //for exit(0);
|
||||
#include <errno.h> //For errno - the error number
|
||||
#include <fcntl.h>
|
||||
#include <byteswap.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/filter.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <sys/timerfd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <net/if.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#ifndef USE_LIBNET
|
||||
#define NO_LIBNET
|
||||
#endif
|
||||
|
||||
#if defined(UDP2RAW_MP)
|
||||
const int is_udp2raw_mp = 1;
|
||||
#if !defined(__CYGWIN__) && !defined(__MINGW32__)
|
||||
#include <pcap.h>
|
||||
#else
|
||||
#include <pcap_wrapper.h>
|
||||
#define NO_LIBNET
|
||||
#endif
|
||||
|
||||
#ifndef NO_LIBNET
|
||||
#include <libnet.h>
|
||||
#endif
|
||||
|
||||
#include<unordered_map>
|
||||
using namespace std;
|
||||
#else
|
||||
#define UDP2RAW_LINUX
|
||||
const int is_udp2raw_mp = 0;
|
||||
//#include <linux/if_ether.h>
|
||||
#include <linux/filter.h>
|
||||
#include <linux/if_packet.h>
|
||||
#include <sys/epoll.h>
|
||||
//#include <sys/wait.h> //signal
|
||||
#include <netinet/if_ether.h>
|
||||
#include <net/if.h>
|
||||
#include <sys/timerfd.h>
|
||||
|
||||
#endif
|
||||
|
||||
typedef unsigned long long u64_t; //this works on most platform,avoid using the PRId64
|
||||
#if !defined(NO_LIBEV_EMBED)
|
||||
#include <my_ev.h>
|
||||
#else
|
||||
#include "ev.h"
|
||||
#endif
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
#include <winsock2.h>
|
||||
#include <ws2ipdef.h>
|
||||
typedef unsigned char u_int8_t;
|
||||
typedef unsigned short u_int16_t;
|
||||
typedef unsigned int u_int32_t;
|
||||
typedef int socklen_t;
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#include <unordered_map>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <list>
|
||||
using namespace std;
|
||||
|
||||
#if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN || \
|
||||
defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ || \
|
||||
defined(__BIG_ENDIAN__) || \
|
||||
defined(__ARMEB__) || \
|
||||
defined(__THUMBEB__) || \
|
||||
defined(__AARCH64EB__) || \
|
||||
defined(_MIBSEB) || defined(__MIBSEB) || defined(__MIBSEB__)
|
||||
#define UDP2RAW_BIG_ENDIAN 1
|
||||
#endif
|
||||
|
||||
#if defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN || \
|
||||
defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ || \
|
||||
defined(__LITTLE_ENDIAN__) || \
|
||||
defined(__ARMEL__) || \
|
||||
defined(__THUMBEL__) || \
|
||||
defined(__AARCH64EL__) || \
|
||||
defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__)
|
||||
#define UDP2RAW_LITTLE_ENDIAN 1
|
||||
#endif
|
||||
|
||||
#if defined(UDP2RAW_BIG_ENDIAN) && defined(UDP2RAW_LITTLE_ENDIAN)
|
||||
#error "endian detection conflicts"
|
||||
#endif
|
||||
|
||||
#if !defined(UDP2RAW_BIG_ENDIAN) && !defined(UDP2RAW_LITTLE_ENDIAN)
|
||||
#error "endian detection failed"
|
||||
#endif
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
int inet_pton(int af, const char *src, void *dst);
|
||||
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
|
||||
#define setsockopt(a, b, c, d, e) setsockopt(a, b, c, (const char *)(d), e)
|
||||
#endif
|
||||
|
||||
char *get_sock_error();
|
||||
int get_sock_errno();
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
typedef SOCKET my_fd_t;
|
||||
inline int sock_close(my_fd_t fd) {
|
||||
return closesocket(fd);
|
||||
}
|
||||
#else
|
||||
typedef int my_fd_t;
|
||||
inline int sock_close(my_fd_t fd) {
|
||||
return close(fd);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
typedef unsigned long long u64_t; // this works on most platform,avoid using the PRId64
|
||||
typedef long long i64_t;
|
||||
|
||||
typedef unsigned int u32_t;
|
||||
typedef int i32_t;
|
||||
|
||||
typedef unsigned short u16_t;
|
||||
typedef short i16_t;
|
||||
|
||||
const int max_data_len=1600;
|
||||
const int buf_len=max_data_len+200;
|
||||
const u32_t max_handshake_conn_num=10000;
|
||||
const u32_t max_ready_conn_num=1000;
|
||||
const u32_t anti_replay_window_size=1000;
|
||||
const int max_conv_num=10000;
|
||||
|
||||
const u32_t client_handshake_timeout=5000;
|
||||
const u32_t client_retry_interval=1000;
|
||||
|
||||
const u32_t server_handshake_timeout=10000;// this should be much longer than clients. client retry initially ,server retry passtively
|
||||
|
||||
const int conv_clear_ratio=10; //conv grabage collecter check 1/10 of all conv one time
|
||||
const int conn_clear_ratio=10;
|
||||
const int conv_clear_min=5;
|
||||
const int conn_clear_min=1;
|
||||
|
||||
const u32_t conv_clear_interval=1000;
|
||||
const u32_t conn_clear_interval=1000;
|
||||
|
||||
|
||||
const i32_t max_fail_time=0;//disable
|
||||
|
||||
const u32_t heartbeat_interval=1000;
|
||||
|
||||
const u32_t timer_interval=400;//this should be smaller than heartbeat_interval and retry interval;
|
||||
|
||||
//const uint32_t conv_timeout=120000; //120 second
|
||||
const u32_t conv_timeout=30000; //for test
|
||||
|
||||
const u32_t client_conn_timeout=10000;
|
||||
|
||||
//const uint32_t server_conn_timeout=conv_timeout+60000;//this should be 60s+ longer than conv_timeout,so that conv_manager can destruct convs gradually,to avoid latency glicth
|
||||
const u32_t server_conn_timeout=conv_timeout+10000;//for test
|
||||
|
||||
extern int about_to_exit;
|
||||
|
||||
enum raw_mode_t{mode_faketcp=0,mode_udp,mode_icmp,mode_end};
|
||||
extern raw_mode_t raw_mode;
|
||||
enum program_mode_t {unset_mode=0,client_mode,server_mode};
|
||||
extern program_mode_t program_mode;
|
||||
extern unordered_map<int, const char*> raw_mode_tostring ;
|
||||
extern int socket_buf_size;
|
||||
|
||||
typedef u32_t id_t;
|
||||
typedef u32_t my_id_t;
|
||||
|
||||
typedef u64_t iv_t;
|
||||
|
||||
@ -109,37 +155,368 @@ typedef u64_t padding_t;
|
||||
|
||||
typedef u64_t anti_replay_seq_t;
|
||||
|
||||
typedef u64_t my_time_t;
|
||||
|
||||
const int max_addr_len = 100;
|
||||
|
||||
extern int force_socket_buf;
|
||||
|
||||
extern int g_fix_gro;
|
||||
|
||||
/*
|
||||
struct ip_port_t
|
||||
{
|
||||
u32_t ip;
|
||||
int port;
|
||||
void from_u64(u64_t u64);
|
||||
u64_t to_u64();
|
||||
char * to_s();
|
||||
};*/
|
||||
|
||||
typedef u64_t fd64_t;
|
||||
|
||||
u32_t djb2(unsigned char *str, int len);
|
||||
u32_t sdbm(unsigned char *str, int len);
|
||||
|
||||
struct address_t // TODO scope id
|
||||
{
|
||||
struct hash_function {
|
||||
u32_t operator()(const address_t &key) const {
|
||||
return sdbm((unsigned char *)&key.inner, sizeof(key.inner));
|
||||
}
|
||||
};
|
||||
|
||||
union storage_t // sockaddr_storage is too huge, we dont use it.
|
||||
{
|
||||
sockaddr_in ipv4;
|
||||
sockaddr_in6 ipv6;
|
||||
};
|
||||
storage_t inner;
|
||||
|
||||
address_t() {
|
||||
clear();
|
||||
}
|
||||
void clear() {
|
||||
memset(&inner, 0, sizeof(inner));
|
||||
}
|
||||
int from_ip_port(u32_t ip, int port) {
|
||||
clear();
|
||||
inner.ipv4.sin_family = AF_INET;
|
||||
inner.ipv4.sin_port = htons(port);
|
||||
inner.ipv4.sin_addr.s_addr = ip;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int from_ip_port_new(int type, void *ip, int port) {
|
||||
clear();
|
||||
if (type == AF_INET) {
|
||||
inner.ipv4.sin_family = AF_INET;
|
||||
inner.ipv4.sin_port = htons(port);
|
||||
inner.ipv4.sin_addr.s_addr = *((u32_t *)ip);
|
||||
} else if (type == AF_INET6) {
|
||||
inner.ipv6.sin6_family = AF_INET6;
|
||||
inner.ipv6.sin6_port = htons(port);
|
||||
inner.ipv6.sin6_addr = *((in6_addr *)ip);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int from_str(char *str);
|
||||
|
||||
int from_str_ip_only(char *str);
|
||||
|
||||
int from_sockaddr(sockaddr *, socklen_t);
|
||||
|
||||
char *get_str();
|
||||
void to_str(char *);
|
||||
|
||||
inline u32_t get_type() {
|
||||
u32_t ret = ((sockaddr *)&inner)->sa_family;
|
||||
assert(ret == AF_INET || ret == AF_INET6);
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline u32_t get_len() {
|
||||
u32_t type = get_type();
|
||||
switch (type) {
|
||||
case AF_INET:
|
||||
return sizeof(sockaddr_in);
|
||||
case AF_INET6:
|
||||
return sizeof(sockaddr_in6);
|
||||
default:
|
||||
assert(0 == 1);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
inline u32_t get_port() {
|
||||
u32_t type = get_type();
|
||||
switch (type) {
|
||||
case AF_INET:
|
||||
return ntohs(inner.ipv4.sin_port);
|
||||
case AF_INET6:
|
||||
return ntohs(inner.ipv6.sin6_port);
|
||||
default:
|
||||
assert(0 == 1);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
inline void set_port(int port) {
|
||||
u32_t type = get_type();
|
||||
switch (type) {
|
||||
case AF_INET:
|
||||
inner.ipv4.sin_port = htons(port);
|
||||
break;
|
||||
case AF_INET6:
|
||||
inner.ipv6.sin6_port = htons(port);
|
||||
break;
|
||||
default:
|
||||
assert(0 == 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
bool operator==(const address_t &b) const {
|
||||
// return this->data==b.data;
|
||||
return memcmp(&this->inner, &b.inner, sizeof(this->inner)) == 0;
|
||||
}
|
||||
|
||||
int new_connected_udp_fd();
|
||||
|
||||
char *get_ip();
|
||||
};
|
||||
|
||||
namespace std {
|
||||
template <>
|
||||
struct hash<address_t> {
|
||||
std::size_t operator()(const address_t &key) const {
|
||||
// return address_t::hash_function(k);
|
||||
return sdbm((unsigned char *)&key.inner, sizeof(key.inner));
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
union my_ip_t // just a simple version of address_t,stores ip only
|
||||
{
|
||||
u32_t v4;
|
||||
in6_addr v6;
|
||||
|
||||
bool equal(const my_ip_t &b) const;
|
||||
|
||||
// int from_str(char * str);
|
||||
char *get_str1() const;
|
||||
char *get_str2() const;
|
||||
|
||||
int from_address_t(address_t a);
|
||||
};
|
||||
|
||||
struct not_copy_able_t {
|
||||
not_copy_able_t() {
|
||||
}
|
||||
not_copy_able_t(const not_copy_able_t &other) {
|
||||
assert(0 == 1);
|
||||
}
|
||||
const not_copy_able_t &operator=(const not_copy_able_t &other) {
|
||||
assert(0 == 1);
|
||||
return other;
|
||||
}
|
||||
};
|
||||
|
||||
const int huge_data_len = 65535 + 100; // a packet with link level header might be larger than 65535
|
||||
const int huge_buf_len = huge_data_len + 100;
|
||||
|
||||
const int max_data_len = 1800;
|
||||
const int buf_len = max_data_len + 400;
|
||||
|
||||
// const int max_address_len=512;
|
||||
|
||||
#ifdef UDP2RAW_MP
|
||||
const int queue_len = 200;
|
||||
|
||||
struct queue_t {
|
||||
char data[queue_len][huge_buf_len];
|
||||
int data_len[queue_len];
|
||||
|
||||
int head = 0;
|
||||
int tail = 0;
|
||||
void clear() {
|
||||
head = tail = 0;
|
||||
}
|
||||
int empty() {
|
||||
if (head == tail)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
int full() {
|
||||
if ((tail + 1) % queue_len == head)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
void peek_front(char *&p, int &len) {
|
||||
assert(!empty());
|
||||
p = data[head];
|
||||
len = data_len[head];
|
||||
}
|
||||
void pop_front() {
|
||||
assert(!empty());
|
||||
head++;
|
||||
head %= queue_len;
|
||||
}
|
||||
void push_back(char *p, int len) {
|
||||
assert(!full());
|
||||
memcpy(data[tail], p, len);
|
||||
data_len[tail] = len;
|
||||
tail++;
|
||||
tail %= queue_len;
|
||||
}
|
||||
};
|
||||
|
||||
int init_ws();
|
||||
#endif
|
||||
u64_t get_current_time();
|
||||
u64_t pack_u64(u32_t a,u32_t b);
|
||||
u64_t pack_u64(u32_t a, u32_t b);
|
||||
|
||||
u32_t get_u64_h(u64_t a);
|
||||
|
||||
u32_t get_u64_l(u64_t a);
|
||||
|
||||
char * my_ntoa(u32_t ip);
|
||||
char *my_ntoa(u32_t ip);
|
||||
|
||||
void myexit(int a);
|
||||
void init_random_number_fd();
|
||||
u64_t get_true_random_number_64();
|
||||
u32_t get_true_random_number();
|
||||
u32_t get_true_random_number_nz();
|
||||
u64_t ntoh64(u64_t a);
|
||||
u64_t hton64(u64_t a);
|
||||
bool larger_than_u16(uint16_t a,uint16_t b);
|
||||
bool larger_than_u32(u32_t a,u32_t b);
|
||||
|
||||
void write_u16(char *, u16_t a); // network order
|
||||
u16_t read_u16(char *);
|
||||
void write_u32(char *, u32_t a); // network order
|
||||
u32_t read_u32(char *);
|
||||
void write_u64(char *, u64_t a);
|
||||
u64_t read_u64(char *);
|
||||
|
||||
bool larger_than_u16(uint16_t a, uint16_t b);
|
||||
bool larger_than_u32(u32_t a, u32_t b);
|
||||
void setnonblocking(int sock);
|
||||
int set_buf_size(int fd);
|
||||
|
||||
unsigned short csum(const unsigned short *ptr,int nbytes);
|
||||
|
||||
void signal_handler(int sig);
|
||||
int numbers_to_char(id_t id1,id_t id2,id_t id3,char * &data,int &len);
|
||||
int char_to_numbers(const char * data,int len,id_t &id1,id_t &id2,id_t &id3);
|
||||
int set_buf_size(int fd, int socket_buf_size);
|
||||
|
||||
void myexit(int a);
|
||||
|
||||
int add_iptables_rule(char *);
|
||||
unsigned short csum(const unsigned short *ptr, int nbytes);
|
||||
unsigned short csum_with_header(char *header, int hlen, const unsigned short *ptr, int nbytes);
|
||||
|
||||
int clear_iptables_rule();
|
||||
int numbers_to_char(my_id_t id1, my_id_t id2, my_id_t id3, char *&data, int &len);
|
||||
int char_to_numbers(const char *data, int len, my_id_t &id1, my_id_t &id2, my_id_t &id3);
|
||||
|
||||
const int show_none = 0;
|
||||
const int show_command = 0x1;
|
||||
const int show_log = 0x2;
|
||||
const int show_all = show_command | show_log;
|
||||
|
||||
int run_command(string command, char *&output, int flag = show_all);
|
||||
// int run_command_no_log(string command,char * &output);
|
||||
int read_file(const char *file, string &output);
|
||||
|
||||
vector<string> string_to_vec(const char *s, const char *sp);
|
||||
vector<vector<string> > string_to_vec2(const char *s);
|
||||
|
||||
string trim(const string &str, char c);
|
||||
|
||||
string trim_conf_line(const string &str);
|
||||
|
||||
vector<string> parse_conf_line(const string &s);
|
||||
|
||||
int hex_to_u32_with_endian(const string &a, u32_t &output);
|
||||
int hex_to_u32(const string &a, u32_t &output);
|
||||
// extern string iptables_pattern;
|
||||
|
||||
int create_fifo(char *file);
|
||||
|
||||
void print_binary_chars(const char *a, int len);
|
||||
|
||||
template <class key_t>
|
||||
struct lru_collector_t : not_copy_able_t {
|
||||
// typedef void* key_t;
|
||||
//#define key_t void*
|
||||
struct lru_pair_t {
|
||||
key_t key;
|
||||
my_time_t ts;
|
||||
};
|
||||
|
||||
unordered_map<key_t, typename list<lru_pair_t>::iterator> mp;
|
||||
|
||||
list<lru_pair_t> q;
|
||||
int update(key_t key) {
|
||||
assert(mp.find(key) != mp.end());
|
||||
auto it = mp[key];
|
||||
q.erase(it);
|
||||
|
||||
my_time_t value = get_current_time();
|
||||
if (!q.empty()) {
|
||||
assert(value >= q.front().ts);
|
||||
}
|
||||
lru_pair_t tmp;
|
||||
tmp.key = key;
|
||||
tmp.ts = value;
|
||||
q.push_front(tmp);
|
||||
mp[key] = q.begin();
|
||||
|
||||
return 0;
|
||||
}
|
||||
int new_key(key_t key) {
|
||||
assert(mp.find(key) == mp.end());
|
||||
|
||||
my_time_t value = get_current_time();
|
||||
if (!q.empty()) {
|
||||
assert(value >= q.front().ts);
|
||||
}
|
||||
lru_pair_t tmp;
|
||||
tmp.key = key;
|
||||
tmp.ts = value;
|
||||
q.push_front(tmp);
|
||||
mp[key] = q.begin();
|
||||
|
||||
return 0;
|
||||
}
|
||||
int size() {
|
||||
return q.size();
|
||||
}
|
||||
int empty() {
|
||||
return q.empty();
|
||||
}
|
||||
void clear() {
|
||||
mp.clear();
|
||||
q.clear();
|
||||
}
|
||||
my_time_t ts_of(key_t key) {
|
||||
assert(mp.find(key) != mp.end());
|
||||
return mp[key]->ts;
|
||||
}
|
||||
|
||||
my_time_t peek_back(key_t &key) {
|
||||
assert(!q.empty());
|
||||
auto it = q.end();
|
||||
it--;
|
||||
key = it->key;
|
||||
return it->ts;
|
||||
}
|
||||
void erase(key_t key) {
|
||||
assert(mp.find(key) != mp.end());
|
||||
q.erase(mp[key]);
|
||||
mp.erase(key);
|
||||
}
|
||||
/*
|
||||
void erase_back()
|
||||
{
|
||||
assert(!q.empty());
|
||||
auto it=q.end(); it--;
|
||||
key_t key=it->key;
|
||||
erase(key);
|
||||
}*/
|
||||
};
|
||||
|
||||
#endif /* COMMON_H_ */
|
||||
|
657
connection.cpp
Normal file
@ -0,0 +1,657 @@
|
||||
/*
|
||||
* connection.cpp
|
||||
*
|
||||
* Created on: Sep 23, 2017
|
||||
* Author: root
|
||||
*/
|
||||
|
||||
#include "connection.h"
|
||||
#include "encrypt.h"
|
||||
#include "fd_manager.h"
|
||||
|
||||
int disable_anti_replay = 0; // if anti_replay windows is diabled
|
||||
|
||||
const int disable_conn_clear = 0; // a raw connection is called conn.
|
||||
|
||||
conn_manager_t conn_manager;
|
||||
|
||||
anti_replay_seq_t anti_replay_t::get_new_seq_for_send() {
|
||||
return anti_replay_seq++;
|
||||
}
|
||||
anti_replay_t::anti_replay_t() {
|
||||
max_packet_received = 0;
|
||||
anti_replay_seq = get_true_random_number_64() / 10; // random first seq
|
||||
// memset(window,0,sizeof(window)); //not necessary
|
||||
}
|
||||
void anti_replay_t::re_init() {
|
||||
max_packet_received = 0;
|
||||
// memset(window,0,sizeof(window));
|
||||
}
|
||||
|
||||
int anti_replay_t::is_vaild(u64_t seq) {
|
||||
if (disable_anti_replay) return 1;
|
||||
// if(disabled) return 0;
|
||||
|
||||
if (seq == max_packet_received)
|
||||
return 0;
|
||||
else if (seq > max_packet_received) {
|
||||
if (seq - max_packet_received >= anti_replay_window_size) {
|
||||
memset(window, 0, sizeof(window));
|
||||
window[seq % anti_replay_window_size] = 1;
|
||||
} else {
|
||||
for (u64_t i = max_packet_received + 1; i < seq; i++)
|
||||
window[i % anti_replay_window_size] = 0;
|
||||
window[seq % anti_replay_window_size] = 1;
|
||||
}
|
||||
max_packet_received = seq;
|
||||
return 1;
|
||||
} else if (seq < max_packet_received) {
|
||||
if (max_packet_received - seq >= anti_replay_window_size)
|
||||
return 0;
|
||||
else {
|
||||
if (window[seq % anti_replay_window_size] == 1)
|
||||
return 0;
|
||||
else {
|
||||
window[seq % anti_replay_window_size] = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0; // for complier check
|
||||
}
|
||||
|
||||
void conn_info_t::recover(const conn_info_t &conn_info) {
|
||||
raw_info = conn_info.raw_info;
|
||||
|
||||
raw_info.rst_received = 0;
|
||||
raw_info.disabled = 0;
|
||||
|
||||
last_state_time = conn_info.last_state_time;
|
||||
last_hb_recv_time = conn_info.last_hb_recv_time;
|
||||
last_hb_sent_time = conn_info.last_hb_sent_time;
|
||||
my_id = conn_info.my_id;
|
||||
oppsite_id = conn_info.oppsite_id;
|
||||
blob->anti_replay.re_init();
|
||||
|
||||
my_roller = 0; // no need to set,but for easier debug,set it to zero
|
||||
oppsite_roller = 0; // same as above
|
||||
last_oppsite_roller_time = 0;
|
||||
}
|
||||
|
||||
void conn_info_t::re_init() {
|
||||
// send_packet_info.protocol=g_packet_info_send.protocol;
|
||||
if (program_mode == server_mode)
|
||||
state.server_current_state = server_idle;
|
||||
else
|
||||
state.client_current_state = client_idle;
|
||||
last_state_time = 0;
|
||||
oppsite_const_id = 0;
|
||||
|
||||
timer_fd64 = 0;
|
||||
|
||||
my_roller = 0;
|
||||
oppsite_roller = 0;
|
||||
last_oppsite_roller_time = 0;
|
||||
}
|
||||
conn_info_t::conn_info_t() {
|
||||
blob = 0;
|
||||
re_init();
|
||||
}
|
||||
void conn_info_t::prepare() {
|
||||
assert(blob == 0);
|
||||
blob = new blob_t;
|
||||
if (program_mode == server_mode) {
|
||||
blob->conv_manager.s.additional_clear_function = server_clear_function;
|
||||
} else {
|
||||
assert(program_mode == client_mode);
|
||||
}
|
||||
}
|
||||
|
||||
conn_info_t::conn_info_t(const conn_info_t &b) {
|
||||
assert(0 == 1);
|
||||
// mylog(log_error,"called!!!!!!!!!!!!!\n");
|
||||
}
|
||||
|
||||
conn_info_t &conn_info_t::operator=(const conn_info_t &b) {
|
||||
mylog(log_fatal, "not allowed\n");
|
||||
myexit(-1);
|
||||
return *this;
|
||||
}
|
||||
conn_info_t::~conn_info_t() {
|
||||
if (program_mode == server_mode) {
|
||||
if (state.server_current_state == server_ready) {
|
||||
assert(blob != 0);
|
||||
assert(oppsite_const_id != 0);
|
||||
// assert(conn_manager.const_id_mp.find(oppsite_const_id)!=conn_manager.const_id_mp.end()); // conn_manager 's deconstuction function erases it
|
||||
} else {
|
||||
assert(blob == 0);
|
||||
assert(oppsite_const_id == 0);
|
||||
}
|
||||
}
|
||||
assert(timer_fd64 == 0);
|
||||
// if(oppsite_const_id!=0) //do this at conn_manager 's deconstuction function
|
||||
// conn_manager.const_id_mp.erase(oppsite_const_id);
|
||||
if (blob != 0)
|
||||
delete blob;
|
||||
|
||||
// send_packet_info.protocol=g_packet_info_send.protocol;
|
||||
}
|
||||
|
||||
conn_manager_t::conn_manager_t() {
|
||||
ready_num = 0;
|
||||
mp.reserve(10007);
|
||||
// clear_it=mp.begin();
|
||||
// timer_fd_mp.reserve(10007);
|
||||
const_id_mp.reserve(10007);
|
||||
// udp_fd_mp.reserve(100007);
|
||||
last_clear_time = 0;
|
||||
// current_ready_ip=0;
|
||||
// current_ready_port=0;
|
||||
}
|
||||
int conn_manager_t::exist(address_t addr) {
|
||||
// u64_t u64=0;
|
||||
// u64=ip;
|
||||
// u64<<=32u;
|
||||
// u64|=port;
|
||||
if (mp.find(addr) != mp.end()) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
int insert(uint32_t ip,uint16_t port)
|
||||
{
|
||||
uint64_t u64=0;
|
||||
u64=ip;
|
||||
u64<<=32u;
|
||||
u64|=port;
|
||||
mp[u64];
|
||||
return 0;
|
||||
}*/
|
||||
conn_info_t *&conn_manager_t::find_insert_p(address_t addr) // be aware,the adress may change after rehash
|
||||
{
|
||||
// u64_t u64=0;
|
||||
// u64=ip;
|
||||
// u64<<=32u;
|
||||
// u64|=port;
|
||||
unordered_map<address_t, conn_info_t *>::iterator it = mp.find(addr);
|
||||
if (it == mp.end()) {
|
||||
mp[addr] = new conn_info_t;
|
||||
// lru.new_key(addr);
|
||||
} else {
|
||||
// lru.update(addr);
|
||||
}
|
||||
return mp[addr];
|
||||
}
|
||||
conn_info_t &conn_manager_t::find_insert(address_t addr) // be aware,the adress may change after rehash
|
||||
{
|
||||
// u64_t u64=0;
|
||||
// u64=ip;
|
||||
// u64<<=32u;
|
||||
// u64|=port;
|
||||
unordered_map<address_t, conn_info_t *>::iterator it = mp.find(addr);
|
||||
if (it == mp.end()) {
|
||||
mp[addr] = new conn_info_t;
|
||||
// lru.new_key(addr);
|
||||
} else {
|
||||
// lru.update(addr);
|
||||
}
|
||||
return *mp[addr];
|
||||
}
|
||||
int conn_manager_t::erase(unordered_map<address_t, conn_info_t *>::iterator erase_it) {
|
||||
if (erase_it->second->state.server_current_state == server_ready) {
|
||||
ready_num--;
|
||||
assert(i32_t(ready_num) != -1);
|
||||
assert(erase_it->second != 0);
|
||||
|
||||
assert(erase_it->second->timer_fd64 != 0);
|
||||
|
||||
assert(fd_manager.exist(erase_it->second->timer_fd64));
|
||||
|
||||
assert(erase_it->second->oppsite_const_id != 0);
|
||||
assert(const_id_mp.find(erase_it->second->oppsite_const_id) != const_id_mp.end());
|
||||
|
||||
// assert(timer_fd_mp.find(erase_it->second->timer_fd)!=timer_fd_mp.end());
|
||||
|
||||
const_id_mp.erase(erase_it->second->oppsite_const_id);
|
||||
|
||||
fd_manager.fd64_close(erase_it->second->timer_fd64);
|
||||
|
||||
erase_it->second->timer_fd64 = 0;
|
||||
// timer_fd_mp.erase(erase_it->second->timer_fd);
|
||||
// close(erase_it->second->timer_fd);// close will auto delte it from epoll
|
||||
delete (erase_it->second);
|
||||
mp.erase(erase_it->first);
|
||||
} else {
|
||||
assert(erase_it->second->blob == 0);
|
||||
assert(erase_it->second->timer_fd64 == 0);
|
||||
|
||||
assert(erase_it->second->oppsite_const_id == 0);
|
||||
delete (erase_it->second);
|
||||
mp.erase(erase_it->first);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int conn_manager_t::clear_inactive() {
|
||||
if (get_current_time() - last_clear_time > conn_clear_interval) {
|
||||
last_clear_time = get_current_time();
|
||||
return clear_inactive0();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int conn_manager_t::clear_inactive0() {
|
||||
unordered_map<address_t, conn_info_t *>::iterator it;
|
||||
unordered_map<address_t, conn_info_t *>::iterator old_it;
|
||||
|
||||
if (disable_conn_clear) return 0;
|
||||
|
||||
// map<uint32_t,uint64_t>::iterator it;
|
||||
int cnt = 0;
|
||||
it = clear_it;
|
||||
int size = mp.size();
|
||||
int num_to_clean = size / conn_clear_ratio + conn_clear_min; // clear 1/10 each time,to avoid latency glitch
|
||||
|
||||
mylog(log_trace, "mp.size() %d\n", size);
|
||||
|
||||
num_to_clean = min(num_to_clean, (int)mp.size());
|
||||
u64_t current_time = get_current_time();
|
||||
|
||||
for (;;) {
|
||||
if (cnt >= num_to_clean) break;
|
||||
if (mp.begin() == mp.end()) break;
|
||||
|
||||
if (it == mp.end()) {
|
||||
it = mp.begin();
|
||||
}
|
||||
|
||||
if (it->second->state.server_current_state == server_ready && current_time - it->second->last_hb_recv_time <= server_conn_timeout) {
|
||||
it++;
|
||||
} else if (it->second->state.server_current_state != server_ready && current_time - it->second->last_state_time <= server_handshake_timeout) {
|
||||
it++;
|
||||
} else if (it->second->blob != 0 && it->second->blob->conv_manager.s.get_size() > 0) {
|
||||
assert(it->second->state.server_current_state == server_ready);
|
||||
it++;
|
||||
} else {
|
||||
mylog(log_info, "[%s:%d]inactive conn cleared \n", it->second->raw_info.recv_info.new_src_ip.get_str1(), it->second->raw_info.recv_info.src_port);
|
||||
old_it = it;
|
||||
it++;
|
||||
erase(old_it);
|
||||
}
|
||||
cnt++;
|
||||
}
|
||||
clear_it = it;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int send_bare(raw_info_t &raw_info, const char *data, int len) // send function with encryption but no anti replay,this is used when client and server verifys each other
|
||||
// you have to design the protocol carefully, so that you wont be affect by relay attack
|
||||
{
|
||||
if (len < 0) {
|
||||
mylog(log_debug, "input_len <0\n");
|
||||
return -1;
|
||||
}
|
||||
packet_info_t &send_info = raw_info.send_info;
|
||||
packet_info_t &recv_info = raw_info.recv_info;
|
||||
|
||||
char send_data_buf[buf_len]; // buf for send data and send hb
|
||||
char send_data_buf2[buf_len];
|
||||
|
||||
// static send_bare[buf_len];
|
||||
iv_t iv = get_true_random_number_64();
|
||||
padding_t padding = get_true_random_number_64();
|
||||
|
||||
memcpy(send_data_buf, &iv, sizeof(iv));
|
||||
memcpy(send_data_buf + sizeof(iv), &padding, sizeof(padding));
|
||||
|
||||
send_data_buf[sizeof(iv) + sizeof(padding)] = 'b';
|
||||
memcpy(send_data_buf + sizeof(iv) + sizeof(padding) + 1, data, len);
|
||||
int new_len = len + sizeof(iv) + sizeof(padding) + 1;
|
||||
|
||||
if (my_encrypt(send_data_buf, send_data_buf2, new_len) != 0) {
|
||||
return -1;
|
||||
}
|
||||
send_raw0(raw_info, send_data_buf2, new_len);
|
||||
return 0;
|
||||
}
|
||||
int reserved_parse_bare(const char *input, int input_len, char *&data, int &len) // a sub function used in recv_bare
|
||||
{
|
||||
static char recv_data_buf[buf_len];
|
||||
|
||||
if (input_len < 0) {
|
||||
mylog(log_debug, "input_len <0\n");
|
||||
return -1;
|
||||
}
|
||||
if (my_decrypt(input, recv_data_buf, input_len) != 0) {
|
||||
mylog(log_debug, "decrypt_fail in recv bare\n");
|
||||
return -1;
|
||||
}
|
||||
if (recv_data_buf[sizeof(iv_t) + sizeof(padding_t)] != 'b') {
|
||||
mylog(log_debug, "not a bare packet\n");
|
||||
return -1;
|
||||
}
|
||||
len = input_len;
|
||||
data = recv_data_buf + sizeof(iv_t) + sizeof(padding_t) + 1;
|
||||
len -= sizeof(iv_t) + sizeof(padding_t) + 1;
|
||||
if (len < 0) {
|
||||
mylog(log_debug, "len <0\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int recv_bare(raw_info_t &raw_info, char *&data, int &len) // recv function with encryption but no anti replay,this is used when client and server verifys each other
|
||||
// you have to design the protocol carefully, so that you wont be affect by relay attack
|
||||
{
|
||||
packet_info_t &send_info = raw_info.send_info;
|
||||
packet_info_t &recv_info = raw_info.recv_info;
|
||||
|
||||
if (recv_raw0(raw_info, data, len) < 0) {
|
||||
// printf("recv_raw_fail in recv bare\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (len >= max_data_len + 1) {
|
||||
mylog(log_debug, "data_len=%d >= max_data_len+1,ignored", len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
mylog(log_trace, "data len=%d\n", len);
|
||||
if ((raw_mode == mode_faketcp && (recv_info.syn == 1 || recv_info.ack != 1))) {
|
||||
mylog(log_debug, "unexpect packet type recv_info.syn=%d recv_info.ack=%d \n", recv_info.syn, recv_info.ack);
|
||||
return -1;
|
||||
}
|
||||
return reserved_parse_bare(data, len, data, len);
|
||||
}
|
||||
|
||||
int send_handshake(raw_info_t &raw_info, my_id_t id1, my_id_t id2, my_id_t id3) // a warp for send_bare for sending handshake(this is not tcp handshake) easily
|
||||
{
|
||||
packet_info_t &send_info = raw_info.send_info;
|
||||
packet_info_t &recv_info = raw_info.recv_info;
|
||||
|
||||
char *data;
|
||||
int len;
|
||||
// len=sizeof(id_t)*3;
|
||||
if (numbers_to_char(id1, id2, id3, data, len) != 0) return -1;
|
||||
if (send_bare(raw_info, data, len) != 0) {
|
||||
mylog(log_warn, "send bare fail\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
int recv_handshake(packet_info_t &info,id_t &id1,id_t &id2,id_t &id3)
|
||||
{
|
||||
char * data;int len;
|
||||
if(recv_bare(info,data,len)!=0) return -1;
|
||||
|
||||
if(char_to_numbers(data,len,id1,id2,id3)!=0) return -1;
|
||||
|
||||
return 0;
|
||||
}*/
|
||||
|
||||
int send_safer(conn_info_t &conn_info, char type, const char *data, int len) // safer transfer function with anti-replay,when mutually verification is done.
|
||||
{
|
||||
packet_info_t &send_info = conn_info.raw_info.send_info;
|
||||
packet_info_t &recv_info = conn_info.raw_info.recv_info;
|
||||
|
||||
if (type != 'h' && type != 'd') {
|
||||
mylog(log_warn, "first byte is not h or d ,%x\n", type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char send_data_buf[buf_len]; // buf for send data and send hb
|
||||
char send_data_buf2[buf_len];
|
||||
|
||||
my_id_t n_tmp_id = htonl(conn_info.my_id);
|
||||
|
||||
memcpy(send_data_buf, &n_tmp_id, sizeof(n_tmp_id));
|
||||
|
||||
n_tmp_id = htonl(conn_info.oppsite_id);
|
||||
|
||||
memcpy(send_data_buf + sizeof(n_tmp_id), &n_tmp_id, sizeof(n_tmp_id));
|
||||
|
||||
anti_replay_seq_t n_seq = hton64(conn_info.blob->anti_replay.get_new_seq_for_send());
|
||||
|
||||
memcpy(send_data_buf + sizeof(n_tmp_id) * 2, &n_seq, sizeof(n_seq));
|
||||
|
||||
send_data_buf[sizeof(n_tmp_id) * 2 + sizeof(n_seq)] = type;
|
||||
send_data_buf[sizeof(n_tmp_id) * 2 + sizeof(n_seq) + 1] = conn_info.my_roller;
|
||||
|
||||
memcpy(send_data_buf + 2 + sizeof(n_tmp_id) * 2 + sizeof(n_seq), data, len); // data;
|
||||
|
||||
int new_len = len + sizeof(n_seq) + sizeof(n_tmp_id) * 2 + 2;
|
||||
|
||||
if (g_fix_gro == 0) {
|
||||
if (my_encrypt(send_data_buf, send_data_buf2, new_len) != 0) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (my_encrypt(send_data_buf, send_data_buf2 + 2, new_len) != 0) {
|
||||
return -1;
|
||||
}
|
||||
write_u16(send_data_buf2, new_len);
|
||||
new_len += 2;
|
||||
if (cipher_mode == cipher_xor) {
|
||||
send_data_buf2[0] ^= gro_xor[0];
|
||||
send_data_buf2[1] ^= gro_xor[1];
|
||||
} else if (cipher_mode == cipher_aes128cbc || cipher_mode == cipher_aes128cfb) {
|
||||
aes_ecb_encrypt1(send_data_buf2);
|
||||
}
|
||||
}
|
||||
|
||||
if (send_raw0(conn_info.raw_info, send_data_buf2, new_len) != 0) return -1;
|
||||
|
||||
if (after_send_raw0(conn_info.raw_info) != 0) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
int send_data_safer(conn_info_t &conn_info, const char *data, int len, u32_t conv_num) // a wrap for send_safer for transfer data.
|
||||
{
|
||||
packet_info_t &send_info = conn_info.raw_info.send_info;
|
||||
packet_info_t &recv_info = conn_info.raw_info.recv_info;
|
||||
|
||||
char send_data_buf[buf_len];
|
||||
// send_data_buf[0]='d';
|
||||
u32_t n_conv_num = htonl(conv_num);
|
||||
memcpy(send_data_buf, &n_conv_num, sizeof(n_conv_num));
|
||||
|
||||
memcpy(send_data_buf + sizeof(n_conv_num), data, len);
|
||||
int new_len = len + sizeof(n_conv_num);
|
||||
send_safer(conn_info, 'd', send_data_buf, new_len);
|
||||
return 0;
|
||||
}
|
||||
int reserved_parse_safer(conn_info_t &conn_info, const char *input, int input_len, char &type, char *&data, int &len) // subfunction for recv_safer,allow overlap
|
||||
{
|
||||
static char recv_data_buf[buf_len];
|
||||
|
||||
// char *recv_data_buf=recv_data_buf0; //fix strict alias warning
|
||||
if (my_decrypt(input, recv_data_buf, input_len) != 0) {
|
||||
// printf("decrypt fail\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// char *a=recv_data_buf;
|
||||
// id_t h_oppiste_id= ntohl ( *((id_t * )(recv_data_buf)) );
|
||||
my_id_t h_oppsite_id;
|
||||
memcpy(&h_oppsite_id, recv_data_buf, sizeof(h_oppsite_id));
|
||||
h_oppsite_id = ntohl(h_oppsite_id);
|
||||
|
||||
// id_t h_my_id= ntohl ( *((id_t * )(recv_data_buf+sizeof(id_t))) );
|
||||
my_id_t h_my_id;
|
||||
memcpy(&h_my_id, recv_data_buf + sizeof(my_id_t), sizeof(h_my_id));
|
||||
h_my_id = ntohl(h_my_id);
|
||||
|
||||
// anti_replay_seq_t h_seq= ntoh64 ( *((anti_replay_seq_t * )(recv_data_buf +sizeof(id_t) *2 )) );
|
||||
anti_replay_seq_t h_seq;
|
||||
memcpy(&h_seq, recv_data_buf + sizeof(my_id_t) * 2, sizeof(h_seq));
|
||||
h_seq = ntoh64(h_seq);
|
||||
|
||||
if (h_oppsite_id != conn_info.oppsite_id || h_my_id != conn_info.my_id) {
|
||||
mylog(log_debug, "id and oppsite_id verification failed %x %x %x %x \n", h_oppsite_id, conn_info.oppsite_id, h_my_id, conn_info.my_id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (conn_info.blob->anti_replay.is_vaild(h_seq) != 1) {
|
||||
mylog(log_debug, "dropped replay packet\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// printf("recv _len %d\n ",recv_len);
|
||||
data = recv_data_buf + sizeof(anti_replay_seq_t) + sizeof(my_id_t) * 2;
|
||||
len = input_len - (sizeof(anti_replay_seq_t) + sizeof(my_id_t) * 2);
|
||||
|
||||
if (data[0] != 'h' && data[0] != 'd') {
|
||||
mylog(log_debug, "first byte is not h or d ,%x\n", data[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t roller = data[1];
|
||||
|
||||
type = data[0];
|
||||
data += 2;
|
||||
len -= 2;
|
||||
|
||||
if (len < 0) {
|
||||
mylog(log_debug, "len <0 ,%d\n", len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (roller != conn_info.oppsite_roller) {
|
||||
conn_info.oppsite_roller = roller;
|
||||
conn_info.last_oppsite_roller_time = get_current_time();
|
||||
}
|
||||
if (hb_mode == 0)
|
||||
conn_info.my_roller++; // increase on a successful recv
|
||||
else if (hb_mode == 1) {
|
||||
if (type == 'h')
|
||||
conn_info.my_roller++;
|
||||
} else {
|
||||
mylog(log_fatal, "unknow hb_mode\n");
|
||||
myexit(-1);
|
||||
}
|
||||
|
||||
if (after_recv_raw0(conn_info.raw_info) != 0) return -1; // TODO might need to move this function to somewhere else after --fix-gro is introduced
|
||||
|
||||
return 0;
|
||||
}
|
||||
int recv_safer_notused(conn_info_t &conn_info, char &type, char *&data, int &len) /// safer transfer function with anti-replay,when mutually verification is done.
|
||||
{
|
||||
packet_info_t &send_info = conn_info.raw_info.send_info;
|
||||
packet_info_t &recv_info = conn_info.raw_info.recv_info;
|
||||
|
||||
char *recv_data;
|
||||
int recv_len;
|
||||
// static char recv_data_buf[buf_len];
|
||||
|
||||
if (recv_raw0(conn_info.raw_info, recv_data, recv_len) != 0) return -1;
|
||||
|
||||
return reserved_parse_safer(conn_info, recv_data, recv_len, type, data, len);
|
||||
}
|
||||
|
||||
int recv_safer_multi(conn_info_t &conn_info, vector<char> &type_arr, vector<string> &data_arr) /// safer transfer function with anti-replay,when mutually verification is done.
|
||||
{
|
||||
packet_info_t &send_info = conn_info.raw_info.send_info;
|
||||
packet_info_t &recv_info = conn_info.raw_info.recv_info;
|
||||
|
||||
char *recv_data;
|
||||
int recv_len;
|
||||
assert(type_arr.empty());
|
||||
assert(data_arr.empty());
|
||||
|
||||
if (recv_raw0(conn_info.raw_info, recv_data, recv_len) != 0) return -1;
|
||||
|
||||
char type;
|
||||
char *data;
|
||||
int len;
|
||||
|
||||
if (g_fix_gro == 0) {
|
||||
int ret = reserved_parse_safer(conn_info, recv_data, recv_len, type, data, len);
|
||||
if (ret == 0) {
|
||||
type_arr.push_back(type);
|
||||
data_arr.emplace_back(data, data + len);
|
||||
// std::copy(data,data+len,data_arr[0]);
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
char *ori_recv_data = recv_data;
|
||||
int ori_recv_len = recv_len;
|
||||
// mylog(log_debug,"recv_len:%d\n",recv_len);
|
||||
int cnt = 0;
|
||||
while (recv_len >= 16) {
|
||||
cnt++;
|
||||
int single_len_no_xor;
|
||||
single_len_no_xor = read_u16(recv_data);
|
||||
int single_len;
|
||||
if (cipher_mode == cipher_xor) {
|
||||
recv_data[0] ^= gro_xor[0];
|
||||
recv_data[1] ^= gro_xor[1];
|
||||
} else if (cipher_mode == cipher_aes128cbc || cipher_mode == cipher_aes128cfb) {
|
||||
aes_ecb_decrypt1(recv_data);
|
||||
}
|
||||
single_len = read_u16(recv_data);
|
||||
recv_len -= 2;
|
||||
recv_data += 2;
|
||||
if (single_len > recv_len) {
|
||||
mylog(log_debug, "illegal single_len %d(%d), recv_len %d left,dropped\n", single_len, single_len_no_xor, recv_len);
|
||||
break;
|
||||
}
|
||||
if (single_len > max_data_len) {
|
||||
mylog(log_warn, "single_len %d(%d) > %d, maybe you need to turn down mtu at upper level\n", single_len, single_len_no_xor, max_data_len);
|
||||
break;
|
||||
}
|
||||
|
||||
int ret = reserved_parse_safer(conn_info, recv_data, single_len, type, data, len);
|
||||
|
||||
if (ret != 0) {
|
||||
mylog(log_debug, "parse failed, offset= %d,single_len=%d(%d)\n", (int)(recv_data - ori_recv_data), single_len, single_len_no_xor);
|
||||
} else {
|
||||
type_arr.push_back(type);
|
||||
data_arr.emplace_back(data, data + len);
|
||||
// std::copy(data,data+len,data_arr[data_arr.size()-1]);
|
||||
}
|
||||
recv_data += single_len;
|
||||
recv_len -= single_len;
|
||||
}
|
||||
if (cnt > 1) {
|
||||
mylog(log_debug, "got a suspected gro packet, %d packets recovered, recv_len=%d, loop_cnt=%d\n", (int)data_arr.size(), ori_recv_len, cnt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void server_clear_function(u64_t u64) // used in conv_manager in server mode.for server we have to use one udp fd for one conv(udp connection),
|
||||
// so we have to close the fd when conv expires
|
||||
{
|
||||
// int fd=int(u64);
|
||||
// int ret;
|
||||
// assert(fd!=0);
|
||||
/*
|
||||
epoll_event ev;
|
||||
|
||||
ev.events = EPOLLIN;
|
||||
ev.data.u64 = u64;
|
||||
|
||||
ret = epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, &ev);
|
||||
if (ret!=0)
|
||||
{
|
||||
mylog(log_fatal,"fd:%d epoll delete failed!!!!\n",fd);
|
||||
myexit(-1); //this shouldnt happen
|
||||
}*/
|
||||
// no need
|
||||
|
||||
/*ret= close(fd); //closed fd should be auto removed from epoll
|
||||
|
||||
if (ret!=0)
|
||||
{
|
||||
mylog(log_fatal,"close fd %d failed !!!!\n",fd);
|
||||
myexit(-1); //this shouldnt happen
|
||||
}*/
|
||||
// mylog(log_fatal,"size:%d !!!!\n",conn_manager.udp_fd_mp.size());
|
||||
fd64_t fd64 = u64;
|
||||
assert(fd_manager.exist(fd64));
|
||||
fd_manager.fd64_close(fd64);
|
||||
|
||||
// assert(conn_manager.udp_fd_mp.find(fd)!=conn_manager.udp_fd_mp.end());
|
||||
// conn_manager.udp_fd_mp.erase(fd);
|
||||
}
|
313
connection.h
Normal file
@ -0,0 +1,313 @@
|
||||
/*
|
||||
* connection.h
|
||||
*
|
||||
* Created on: Sep 23, 2017
|
||||
* Author: root
|
||||
*/
|
||||
|
||||
#ifndef CONNECTION_H_
|
||||
#define CONNECTION_H_
|
||||
|
||||
extern int disable_anti_replay;
|
||||
|
||||
#include "connection.h"
|
||||
#include "common.h"
|
||||
#include "log.h"
|
||||
#include "network.h"
|
||||
#include "misc.h"
|
||||
|
||||
const int disable_conv_clear = 0; // a udp connection in the multiplexer is called conversation in this program,conv for short.
|
||||
|
||||
struct anti_replay_t // its for anti replay attack,similar to openvpn/ipsec 's anti replay window
|
||||
{
|
||||
u64_t max_packet_received;
|
||||
char window[anti_replay_window_size];
|
||||
anti_replay_seq_t anti_replay_seq;
|
||||
anti_replay_seq_t get_new_seq_for_send();
|
||||
anti_replay_t();
|
||||
void re_init();
|
||||
|
||||
int is_vaild(u64_t seq);
|
||||
}; // anti_replay;
|
||||
|
||||
void server_clear_function(u64_t u64);
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
template <class T>
|
||||
struct conv_manager_t // manage the udp connections
|
||||
{
|
||||
// typedef hash_map map;
|
||||
unordered_map<T, u32_t> data_to_conv; // conv and u64 are both supposed to be uniq
|
||||
unordered_map<u32_t, T> conv_to_data;
|
||||
|
||||
lru_collector_t<u32_t> lru;
|
||||
// unordered_map<u32_t,u64_t> conv_last_active_time;
|
||||
|
||||
// unordered_map<u32_t,u64_t>::iterator clear_it;
|
||||
|
||||
void (*additional_clear_function)(T data) = 0;
|
||||
|
||||
long long last_clear_time;
|
||||
|
||||
conv_manager_t() {
|
||||
// clear_it=conv_last_active_time.begin();
|
||||
long long last_clear_time = 0;
|
||||
additional_clear_function = 0;
|
||||
}
|
||||
~conv_manager_t() {
|
||||
clear();
|
||||
}
|
||||
int get_size() {
|
||||
return conv_to_data.size();
|
||||
}
|
||||
void reserve() {
|
||||
data_to_conv.reserve(10007);
|
||||
conv_to_data.reserve(10007);
|
||||
// conv_last_active_time.reserve(10007);
|
||||
|
||||
lru.mp.reserve(10007);
|
||||
}
|
||||
void clear() {
|
||||
if (disable_conv_clear) return;
|
||||
|
||||
if (additional_clear_function != 0) {
|
||||
for (auto it = conv_to_data.begin(); it != conv_to_data.end(); it++) {
|
||||
// int fd=int((it->second<<32u)>>32u);
|
||||
additional_clear_function(it->second);
|
||||
}
|
||||
}
|
||||
data_to_conv.clear();
|
||||
conv_to_data.clear();
|
||||
|
||||
lru.clear();
|
||||
// conv_last_active_time.clear();
|
||||
|
||||
// clear_it=conv_last_active_time.begin();
|
||||
}
|
||||
u32_t get_new_conv() {
|
||||
u32_t conv = get_true_random_number_nz();
|
||||
while (conv_to_data.find(conv) != conv_to_data.end()) {
|
||||
conv = get_true_random_number_nz();
|
||||
}
|
||||
return conv;
|
||||
}
|
||||
int is_conv_used(u32_t conv) {
|
||||
return conv_to_data.find(conv) != conv_to_data.end();
|
||||
}
|
||||
int is_data_used(T data) {
|
||||
return data_to_conv.find(data) != data_to_conv.end();
|
||||
}
|
||||
u32_t find_conv_by_data(T data) {
|
||||
return data_to_conv[data];
|
||||
}
|
||||
T find_data_by_conv(u32_t conv) {
|
||||
return conv_to_data[conv];
|
||||
}
|
||||
int update_active_time(u32_t conv) {
|
||||
// return conv_last_active_time[conv]=get_current_time();
|
||||
lru.update(conv);
|
||||
return 0;
|
||||
}
|
||||
int insert_conv(u32_t conv, T data) {
|
||||
data_to_conv[data] = conv;
|
||||
conv_to_data[conv] = data;
|
||||
// conv_last_active_time[conv]=get_current_time();
|
||||
lru.new_key(conv);
|
||||
return 0;
|
||||
}
|
||||
int erase_conv(u32_t conv) {
|
||||
if (disable_conv_clear) return 0;
|
||||
T data = conv_to_data[conv];
|
||||
if (additional_clear_function != 0) {
|
||||
additional_clear_function(data);
|
||||
}
|
||||
conv_to_data.erase(conv);
|
||||
data_to_conv.erase(data);
|
||||
// conv_last_active_time.erase(conv);
|
||||
lru.erase(conv);
|
||||
return 0;
|
||||
}
|
||||
int clear_inactive(char *info = 0) {
|
||||
if (get_current_time() - last_clear_time > conv_clear_interval) {
|
||||
last_clear_time = get_current_time();
|
||||
return clear_inactive0(info);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int clear_inactive0(char *info) {
|
||||
if (disable_conv_clear) return 0;
|
||||
|
||||
unordered_map<u32_t, u64_t>::iterator it;
|
||||
unordered_map<u32_t, u64_t>::iterator old_it;
|
||||
|
||||
// map<uint32_t,uint64_t>::iterator it;
|
||||
int cnt = 0;
|
||||
// it=clear_it;
|
||||
int size = lru.size();
|
||||
int num_to_clean = size / conv_clear_ratio + conv_clear_min; // clear 1/10 each time,to avoid latency glitch
|
||||
|
||||
num_to_clean = min(num_to_clean, size);
|
||||
|
||||
my_time_t current_time = get_current_time();
|
||||
for (;;) {
|
||||
if (cnt >= num_to_clean) break;
|
||||
if (lru.empty()) break;
|
||||
|
||||
u32_t conv;
|
||||
my_time_t ts = lru.peek_back(conv);
|
||||
|
||||
if (current_time - ts < conv_timeout) break;
|
||||
|
||||
erase_conv(conv);
|
||||
if (info == 0) {
|
||||
mylog(log_info, "conv %x cleared\n", conv);
|
||||
} else {
|
||||
mylog(log_info, "[%s]conv %x cleared\n", info, conv);
|
||||
}
|
||||
cnt++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
conv_manager_t();
|
||||
~conv_manager_t();
|
||||
int get_size();
|
||||
void reserve();
|
||||
void clear();
|
||||
u32_t get_new_conv();
|
||||
int is_conv_used(u32_t conv);
|
||||
int is_u64_used(T u64);
|
||||
u32_t find_conv_by_u64(T u64);
|
||||
T find_u64_by_conv(u32_t conv);
|
||||
int update_active_time(u32_t conv);
|
||||
int insert_conv(u32_t conv,T u64);
|
||||
int erase_conv(u32_t conv);
|
||||
int clear_inactive(char * ip_port=0);
|
||||
int clear_inactive0(char * ip_port);*/
|
||||
}; // g_conv_manager;
|
||||
|
||||
struct blob_t : not_copy_able_t // used in conn_info_t.
|
||||
{
|
||||
union tmp_union_t // conv_manager_t is here to avoid copying when a connection is recovered
|
||||
{
|
||||
conv_manager_t<address_t> c;
|
||||
conv_manager_t<u64_t> s;
|
||||
// avoid templates here and there, avoid pointer and type cast
|
||||
tmp_union_t() {
|
||||
if (program_mode == client_mode) {
|
||||
new (&c) conv_manager_t<address_t>();
|
||||
} else {
|
||||
assert(program_mode == server_mode);
|
||||
new (&s) conv_manager_t<u64_t>();
|
||||
}
|
||||
}
|
||||
~tmp_union_t() {
|
||||
if (program_mode == client_mode) {
|
||||
c.~conv_manager_t<address_t>();
|
||||
} else {
|
||||
assert(program_mode == server_mode);
|
||||
s.~conv_manager_t<u64_t>();
|
||||
}
|
||||
}
|
||||
} conv_manager;
|
||||
|
||||
anti_replay_t anti_replay; // anti_replay_t is here bc its huge,its allocation is delayed.
|
||||
};
|
||||
struct conn_info_t // stores info for a raw connection.for client ,there is only one connection,for server there can be thousand of connection since server can
|
||||
// handle multiple clients
|
||||
{
|
||||
current_state_t state;
|
||||
|
||||
raw_info_t raw_info;
|
||||
u64_t last_state_time;
|
||||
u64_t last_hb_sent_time; // client re-use this for retry
|
||||
u64_t last_hb_recv_time;
|
||||
// long long last_resent_time;
|
||||
|
||||
my_id_t my_id;
|
||||
my_id_t oppsite_id;
|
||||
|
||||
fd64_t timer_fd64;
|
||||
fd64_t udp_fd64;
|
||||
|
||||
my_id_t oppsite_const_id;
|
||||
|
||||
blob_t *blob;
|
||||
|
||||
uint8_t my_roller;
|
||||
uint8_t oppsite_roller;
|
||||
u64_t last_oppsite_roller_time;
|
||||
|
||||
// ip_port_t ip_port;
|
||||
|
||||
/*
|
||||
const uint32_t &ip=raw_info.recv_info.src_ip;
|
||||
const uint16_t &port=raw_info.recv_info.src_port;
|
||||
|
||||
*/
|
||||
void recover(const conn_info_t &conn_info);
|
||||
void re_init();
|
||||
conn_info_t();
|
||||
void prepare();
|
||||
conn_info_t(const conn_info_t &b);
|
||||
conn_info_t &operator=(const conn_info_t &b);
|
||||
~conn_info_t();
|
||||
}; // g_conn_info;
|
||||
|
||||
struct conn_manager_t // manager for connections. for client,we dont need conn_manager since there is only one connection.for server we use one conn_manager for all connections
|
||||
{
|
||||
u32_t ready_num;
|
||||
|
||||
// unordered_map<int,conn_info_t *> udp_fd_mp; //a bit dirty to used pointer,but can void unordered_map search
|
||||
// unordered_map<int,conn_info_t *> timer_fd_mp;//we can use pointer here since unordered_map.rehash() uses shallow copy
|
||||
|
||||
unordered_map<my_id_t, conn_info_t *> const_id_mp;
|
||||
|
||||
unordered_map<address_t, conn_info_t *> mp; // put it at end so that it de-consturcts first
|
||||
|
||||
// lru_collector_t<address_t> lru;
|
||||
|
||||
unordered_map<address_t, conn_info_t *>::iterator clear_it;
|
||||
|
||||
long long last_clear_time;
|
||||
|
||||
conn_manager_t();
|
||||
int exist(address_t addr);
|
||||
/*
|
||||
int insert(uint32_t ip,uint16_t port)
|
||||
{
|
||||
uint64_t u64=0;
|
||||
u64=ip;
|
||||
u64<<=32u;
|
||||
u64|=port;
|
||||
mp[u64];
|
||||
return 0;
|
||||
}*/
|
||||
conn_info_t *&find_insert_p(address_t addr); // be aware,the adress may change after rehash //not true?
|
||||
conn_info_t &find_insert(address_t addr); // be aware,the adress may change after rehash
|
||||
|
||||
int erase(unordered_map<address_t, conn_info_t *>::iterator erase_it);
|
||||
int clear_inactive();
|
||||
int clear_inactive0();
|
||||
};
|
||||
|
||||
extern conn_manager_t conn_manager;
|
||||
|
||||
void server_clear_function(u64_t u64);
|
||||
|
||||
int send_bare(raw_info_t &raw_info, const char *data, int len); // send function with encryption but no anti replay,this is used when client and server verifys each other
|
||||
// you have to design the protocol carefully, so that you wont be affect by relay attack
|
||||
// int reserved_parse_bare(const char *input,int input_len,char* & data,int & len); // a sub function used in recv_bare
|
||||
int recv_bare(raw_info_t &raw_info, char *&data, int &len); // recv function with encryption but no anti replay,this is used when client and server verifys each other
|
||||
// you have to design the protocol carefully, so that you wont be affect by relay attack
|
||||
int send_handshake(raw_info_t &raw_info, my_id_t id1, my_id_t id2, my_id_t id3); // a warp for send_bare for sending handshake(this is not tcp handshake) easily
|
||||
int send_safer(conn_info_t &conn_info, char type, const char *data, int len); // safer transfer function with anti-replay,when mutually verification is done.
|
||||
int send_data_safer(conn_info_t &conn_info, const char *data, int len, u32_t conv_num); // a wrap for send_safer for transfer data.
|
||||
// int reserved_parse_safer(conn_info_t &conn_info,const char * input,int input_len,char &type,char* &data,int &len);//subfunction for recv_safer,allow overlap
|
||||
|
||||
// int recv_safer(conn_info_t &conn_info,char &type,char* &data,int &len);///safer transfer function with anti-replay,when mutually verification is done.
|
||||
|
||||
int recv_safer_multi(conn_info_t &conn_info, vector<char> &type_arr, vector<string> &data_arr); // new api for handle gro
|
||||
#endif /* CONNECTION_H_ */
|
271
doc/README.zh-cn.md
Normal file
@ -0,0 +1,271 @@
|
||||
# Udp2raw-tunnel
|
||||

|
||||
udp2raw tunnel,通过raw socket给UDP包加上TCP或ICMP header,进而绕过UDP屏蔽或QoS,或在UDP不稳定的环境下提升稳定性。可以有效防止在使用kcptun或者finalspeed的情况下udp端口被运营商限速。
|
||||
|
||||
支持心跳保活、自动重连,重连后会恢复上次连接,在底层掉线的情况下可以保持上层不掉线。同时有加密、防重放攻击、信道复用的功能。
|
||||
|
||||
[English](/README.md)
|
||||
|
||||
[udp2raw+kcptun step_by_step教程](kcptun_step_by_step.md)
|
||||
|
||||
[udp2raw+finalspeed step_by_step教程](finalspeed_step_by_step.md)
|
||||
|
||||
[udp2raw wiki](https://github.com/wangyu-/udp2raw-tunnel/wiki)
|
||||
|
||||
**提示:**
|
||||
|
||||
udp2raw不是加速器,只是一个帮助你绕过UDP限制的工具。如果你需要UDP“加速器” (改善UDP丢包),请看UDPspeeder。
|
||||
|
||||
UDPspeeder的repo:
|
||||
|
||||
https://github.com/wangyu-/UDPspeeder
|
||||
# 支持的平台
|
||||
Linux主机,有root权限或cap_net_raw capability.。可以是PC、android手机/平板、openwrt路由器、树莓派。主机上最好安装了iptables命令(apt/yum很容易安装)。
|
||||
|
||||
Release中提供了`amd64`、`x86`、`arm`、`mips_be`、`mips_le`的预编译binary.
|
||||
|
||||
##### 对于windows和mac用户:
|
||||
|
||||
可以用[这个repo](https://github.com/wangyu-/udp2raw-multiplatform)里的udp2raw。
|
||||
|
||||
##### 对于ios和游戏主机用户:
|
||||
|
||||
可以把udp2raw运行在局域网的其他机器/虚拟机上。最好的办法是买个能刷OpenWrt/LEDE/梅林的路由器,把udp2raw运行在路由器上。
|
||||
|
||||
# 功能特性
|
||||
### 把udp流量伪装成tcp /icmp
|
||||
用raw socket给udp包加上tcp/icmp包头,可以突破udp流量限制或Udp QOS。或者在udp nat有问题的环境下,提升稳定性。 另外也支持用raw 发udp包,这样流量不会被伪装,只会被加密。
|
||||
|
||||
### 模拟TCP3次握手
|
||||
模拟TCP3次握手,模拟seq ack过程。另外还模拟了一些tcp option:MSS,sackOk,TS,TS_ack,wscale,用来使流量看起来更像是由普通的linux tcp协议栈发送的。
|
||||
|
||||
### 心跳保活、自动重连,连接恢复
|
||||
心跳保活、自动重连,udp2raw重连可以恢复上次的连接,重连后上层连接继续有效,底层掉线上层不掉线。有效解决上层连接断开的问题。 (功能借鉴自[kcptun-raw](https://github.com/Chion82/kcptun-raw))(**就算你拔掉网线重插,或者重新拨号获得新ip,上层应用也不会断线**)
|
||||
|
||||
### 加密、防重放攻击
|
||||
用aes128cbc加密(或更弱的xor),hmac-sha1(或更弱的md5/crc32/simple)做数据完整校验。用类似ipsec/openvpn的replay window机制来防止重放攻击。
|
||||
|
||||
[Notes on encryption](https://github.com/wangyu-/udp2raw-tunnel/wiki/Notes-on-encryption)
|
||||
|
||||
### 其他特性
|
||||
信道复用,client的udp端支持多个连接。
|
||||
|
||||
server支持多个client,也能正确处理多个连接的重连和连接恢复。
|
||||
|
||||
NAT 穿透 ,tcp icmp udp模式都支持nat穿透。
|
||||
|
||||
支持Openvz,配合finalspeed使用,可以在openvz上用tcp模式的finalspeed.
|
||||
|
||||
支持Openwrt,没有编译依赖,容易编译到任何平台上。
|
||||
|
||||
### 关键词
|
||||
突破udp qos,突破udp屏蔽,openvpn tcp over tcp problem,openvpn over icmp,udp to icmp tunnel,udp to tcp tunnel,udp via icmp,udp via tcp
|
||||
|
||||
# 简明操作说明
|
||||
|
||||
### 安装
|
||||
下载编译好的二进制文件,解压到任意目录。
|
||||
|
||||
https://github.com/wangyu-/udp2raw-tunnel/releases
|
||||
|
||||
### 运行
|
||||
假设你有一个server,ip为44.55.66.77,有一个服务监听在udp 7777端口。 假设你本地的主机到44.55.66.77的UDP流量被屏蔽了,或者被qos了
|
||||
|
||||
```
|
||||
在server端运行:
|
||||
./udp2raw_amd64 -s -l0.0.0.0:4096 -r127.0.0.1:7777 -k "passwd" --raw-mode faketcp --cipher-mode xor -a
|
||||
|
||||
在client端运行:
|
||||
./udp2raw_amd64 -c -l0.0.0.0:3333 -r44.55.66.77:4096 -k "passwd" --raw-mode faketcp --cipher-mode xor -a
|
||||
```
|
||||
(以上例子需要用root账号运行。 用非root运行udp2raw需要一些额外的步骤,具体方法请看 [这个](https://github.com/wangyu-/udp2raw-tunnel/wiki/run-udp2raw-as-non-root) 链接。用非root运行更安全)
|
||||
|
||||
###### Server端输出:
|
||||

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

|
||||
|
||||
现在client和server之间建立起了,tunnel。想要在本地连接44.55.66.77:7777,只需要连接 127.0.0.1:3333。来回的所有的udp流量会被经过tunneling发送。在外界看起来是tcp流量,不会有udp流量暴露到公网。
|
||||
|
||||
### MTU设置(重要)
|
||||
|
||||
不论你用udp2raw来加速kcptun还是vpn,为了稳定使用,都需要设置合理的MTU(在kcptun/vpn里设置,而不是在udp2raw里),建议把MTU设置成1200。client和server端都要设置。
|
||||
|
||||
### 提醒
|
||||
`--cipher-mode xor`表示仅使用简单的XOR加密,这样可以节省CPU占用,以免CPU成为速度瓶颈。如果你需要更强的加密,可以去掉此选项,使用默认的AES加密。加密相关的选项见后文的`--cipher-mode`和`--auth-mode`。
|
||||
|
||||
如果要在anroid上运行,请看[Android简明教程](/doc/android_guide.md)
|
||||
|
||||
`-a`选项会自动添加一条/几条iptables规则,udp2raw必须和相应的iptables规则配合才能稳定工作,一定要注意不要忘了`-a`(这是个常见错误)。 如果你不想让udp2raw自动添加iptables规则,可以自己手动添加相应的iptables规则(看一下`-g`选项),然后以不带`-a`的方式运行udp2raw。
|
||||
|
||||
# 进阶操作说明
|
||||
|
||||
### 命令选项
|
||||
```
|
||||
udp2raw-tunnel
|
||||
git version:6e1df4b39f build date:Oct 24 2017 09:21:15
|
||||
repository: https://github.com/wangyu-/udp2raw-tunnel
|
||||
|
||||
usage:
|
||||
run as client : ./this_program -c -l local_listen_ip:local_port -r server_address:server_port [options]
|
||||
run as server : ./this_program -s -l server_listen_ip:server_port -r remote_address:remote_port [options]
|
||||
|
||||
common options,these options must be same on both side:
|
||||
--raw-mode <string> available values:faketcp(default),udp,icmp
|
||||
-k,--key <string> password to gen symetric key,default:"secret key"
|
||||
--cipher-mode <string> available values:aes128cbc(default),xor,none
|
||||
--auth-mode <string> available values:hmac_sha1,md5(default),crc32,simple,none
|
||||
-a,--auto-rule auto add (and delete) iptables rule
|
||||
-g,--gen-rule generate iptables rule then exit,so that you can copy and
|
||||
add it manually.overrides -a
|
||||
--disable-anti-replay disable anti-replay,not suggested
|
||||
client options:
|
||||
--source-ip <ip> force source-ip for raw socket
|
||||
--source-port <port> force source-port for raw socket,tcp/udp only
|
||||
this option disables port changing while re-connecting
|
||||
other options:
|
||||
--conf-file <string> read options from a configuration file instead of command line.
|
||||
check example.conf in repo for format
|
||||
--fifo <string> use a fifo(named pipe) for sending commands to the running program,
|
||||
check readme.md in repository for supported commands.
|
||||
--log-level <number> 0:never 1:fatal 2:error 3:warn
|
||||
4:info (default) 5:debug 6:trace
|
||||
--log-position enable file name,function name,line number in log
|
||||
--disable-color disable log color
|
||||
--disable-bpf disable the kernel space filter,most time its not necessary
|
||||
unless you suspect there is a bug
|
||||
--sock-buf <number> buf size for socket,>=10 and <=10240,unit:kbyte,default:1024
|
||||
--force-sock-buf bypass system limitation while setting sock-buf
|
||||
--seq-mode <number> seq increase mode for faketcp:
|
||||
0:static header,do not increase seq and ack_seq
|
||||
1:increase seq for every packet,simply ack last seq
|
||||
2:increase seq randomly, about every 3 packets,simply ack last seq
|
||||
3:simulate an almost real seq/ack procedure(default)
|
||||
4:similiar to 3,but do not consider TCP Option Window_Scale,
|
||||
maybe useful when firewall doesnt support TCP Option
|
||||
--lower-level <string> send packets at OSI level 2, format:'if_name#dest_mac_adress'
|
||||
ie:'eth0#00:23:45:67:89:b9'.or try '--lower-level auto' to obtain
|
||||
the parameter automatically,specify it manually if 'auto' failed
|
||||
--gen-add generate iptables rule and add it permanently,then exit.overrides -g
|
||||
--keep-rule monitor iptables and auto re-add if necessary.implys -a
|
||||
--clear clear any iptables rules added by this program.overrides everything
|
||||
-h,--help print this help message
|
||||
|
||||
```
|
||||
|
||||
### iptables 规则,`-a`和`-g`
|
||||
用raw收发tcp包本质上绕过了linux内核的tcp协议栈。linux碰到raw socket发来的包会不认识,如果一直收到不认识的包,会回复大量RST,造成不稳定或性能问题。所以强烈建议添加iptables规则屏蔽Linux内核的对指定端口的处理。用-a选项,udp2raw会在启动的时候自动帮你加上Iptables规则,退出的时候再自动删掉。如果长期使用,可以用-g选项来生成相应的Iptables规则再自己手动添加,这样规则不会在udp2raw退出时被删掉,可以避免停掉udp2raw后内核向对端回复RST。
|
||||
|
||||
用raw收发udp包也类似,只是内核回复的是icmp unreachable。而用raw 收发icmp,内核会自动回复icmp echo。都需要相应的iptables规则。
|
||||
### `--cipher-mode` 和 `--auth-mode`
|
||||
如果要最大的安全性建议用aes128cbc+hmac_sha1。如果要运行在路由器上,建议用xor+simple,可以节省CPU。但是注意xor+simple只能骗过防火墙的包检测,不能防止真正的攻击者。
|
||||
|
||||
### `--seq-mode`
|
||||
faketcp模式并没有模拟tcp的全部。所以理论上有办法把faketcp和真正的tcp流量区分开来(虽然大部分ISP不太可能做这种程度的包检测)。seq-mode可以改变一些seq ack的行为。如果遇到了连接问题,可以尝试更改。在我这边的移动线路用3种模式都没问题。
|
||||
|
||||
### `--keep-rule`
|
||||
定期主动检查iptables,如果udp2raw添加的iptables规则丢了,就重新添加。在一些iptables可能会被其他程序清空的情况下(比如梅林固件和openwrt的路由器)格外有用。
|
||||
|
||||
### `--fifo`
|
||||
指定一个fifo(named pipe)来向运行中的程序发送命令,例如`--fifo fifo.file`:
|
||||
|
||||
在client端,可以用`echo reconnect >fifo.file`来强制client换端口重连(上层不断线).对Server,目前没有效果。
|
||||
|
||||
### `--lower-level`
|
||||
大部分udp2raw不能连通的情况都是设置了不兼容的iptables造成的。--lower-level选项允许绕过本地iptables。在一些iptables不好改动的情况下尤其有效(比如你用的是梅林固件,iptables全是固件自己生成的)。
|
||||
|
||||
##### 格式
|
||||
`if_name#dest_mac_adress`,例如 `eth0#00:23:45:67:89:b9` 。`eth0`换成你的出口网卡名。`00:23:45:67:89:b9`换成网关的mac地址(如果client和server在同一个局域网内,可能不需要网关,这时候直接用对方主机的mac地址,这个属于罕见的应用场景,可以忽略)。
|
||||
|
||||
可以用`--lower-level auto`自动获取参数,如果获取参数失败,再手动填写。
|
||||
|
||||
##### client端获得--lower-level参数的办法
|
||||
在client 端,运行`traceroute <server_ip>`,记下第一跳的地址,这个就是`网关ip`。再运行`arp -s <网关ip>`,可以同时查到出口网卡名和mac。
|
||||
|
||||

|
||||
|
||||
如果traceroute第一跳结果是`* * *`,说明网关屏蔽了对traceroute的应答。需要用`ip route`或`route`查询网关:
|
||||
|
||||

|
||||
##### server端获得--lower-level参数的办法
|
||||
如果client有公网ip,就`traceroute <client_ip>`。下一步和client端的方法一样。
|
||||
|
||||
如果client没有公网ip,就`traceroute google.com` 或`traceroute baidu.com`。下一步和client端的方法一样。
|
||||
|
||||
server端也可以用`--lower-level auto` 来尝试自动获得参数,如果无法连接再手动填写。
|
||||
|
||||
##### 注意
|
||||
如果用了`--lower-level`选项。server虽然还可以bind在0.0.0.0,但是因为你显式指定了网络接口,就只能工作在这一个网络接口了。
|
||||
|
||||
如果`arps -s`命令查询不到,首先再试几次。如果还是查询不到,那么可能是因为你用的是pppoe方式的拨号宽带,查询不到是正常的。这种情况下`if_name`填pppoe产生的虚拟interface,通常名字叫`pppXXXX`,从`ifconfig`命令的输出里找一下;`des_mac_adress`填`00:00:00:00:00:00`,例如`ppp0#00:00:00:00:00:00`
|
||||
|
||||
### `--conf-file`
|
||||
|
||||
为了避免将密码等私密信息暴露给`ps`命令,你也可以使用 `配置文件` 来存储参数。
|
||||
|
||||
比如,将以上服务端参数改写成配置文件
|
||||
|
||||
`server.conf`:
|
||||
|
||||
```
|
||||
-s
|
||||
# 你可以像这样添加注释
|
||||
# 注意,只有整行注释才能在配置文件里使用
|
||||
# 注释必须独占一行
|
||||
-l 0.0.0.0:4096
|
||||
-r 127.0.0.1:7777
|
||||
-a
|
||||
-k passwd
|
||||
--raw-mode faketcp
|
||||
```
|
||||
|
||||
注意,当写入配置文件的时候,密码等参数两边的引号必须去除。
|
||||
|
||||
然后就可以使用下面的方式启动服务端
|
||||
|
||||
```bash
|
||||
./udp2raw_amd64 --conf-file server.conf
|
||||
```
|
||||
|
||||
# 性能测试
|
||||
iperf3 的UDP模式有BUG,所以,这里用iperf3的tcp模式,配合Openvpn,测试udp2raw的性能。(iperf3 udp issue ,https://github.com/esnet/iperf/issues/296 )
|
||||
|
||||
openvpn关掉了自带的加密。
|
||||
#### iperf3 命令:
|
||||
```
|
||||
iperf3 -c 10.222.2.1 -P40
|
||||
iperf3 -c 10.222.2.1 -P40 -R
|
||||
```
|
||||
#### client主机
|
||||
vultr 2.5美元每月套餐(single core 2.4ghz cpu,512m ram,日本东京机房),
|
||||
#### server主机
|
||||
bandwagonhost 3.99美元每年套餐(single core 2.0ghz cpu,128m ram,美国洛杉矶机房)
|
||||
### 测试1
|
||||
raw_mode: faketcp cipher_mode: xor auth_mode: simple
|
||||
|
||||

|
||||
|
||||
(反向的速度几乎一样,所以只发正向测试的图)
|
||||
|
||||
测试中cpu被打满。其中有30%的cpu是被openvpn占的。 如果不用Openvpn中转,实际达到100+Mb/S 应该没问题。
|
||||
|
||||
### 测试2
|
||||
raw_mode: faketcp cipher_mode: aes128cbc auth_mode: md5
|
||||
|
||||

|
||||
|
||||
(反向的速度几乎一样,所以只发正向测试的图)
|
||||
|
||||
测试中cpu被打满。绝大多数cpu都是被udp2raw占用的(主要消耗在aes加密)。即使不用Openvpn,速度也不会快很多了。
|
||||
# 应用
|
||||
### 中转 kcptun
|
||||
[udp2raw+kcptun step_by_step教程](kcptun_step_by_step.md)
|
||||
### 中转 finalspeed
|
||||
[udp2raw+finalspeed step_by_step教程](finalspeed_step_by_step.md)
|
||||
|
||||
# wiki
|
||||
|
||||
更多内容请看 wiki:
|
||||
|
||||
https://github.com/wangyu-/udp2raw-tunnel/wiki
|
||||
|
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.Your device has to be rooted,otherwise you cant use raw socket.
|
||||
|
||||
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
|
||||
|
||||

|
92
doc/build_guide.md
Normal file
@ -0,0 +1,92 @@
|
||||
# udp2raw build guide
|
||||
|
||||
the guide on how to build udp2raw
|
||||
|
||||
## Build udp2raw for a specific platform
|
||||
|
||||
### linux platform which supports local compile
|
||||
such as PC,raspberry pi
|
||||
|
||||
##### install git
|
||||
run on debian/ubuntun:
|
||||
```
|
||||
sudo apt-get install git
|
||||
```
|
||||
run on redhat/centos:
|
||||
```
|
||||
sudo yum install git
|
||||
```
|
||||
##### clone git code
|
||||
|
||||
run in any dir:
|
||||
|
||||
```
|
||||
git clone https://github.com/wangyu-/udp2raw-tunnel.git
|
||||
cd udp2raw-tunnel
|
||||
```
|
||||
|
||||
##### install compile tool
|
||||
run on debian/ubuntun:
|
||||
```
|
||||
sudo apt-get install build-essential
|
||||
```
|
||||
|
||||
run on redhat/centos:
|
||||
```
|
||||
sudo yum groupinstall 'Development Tools'
|
||||
```
|
||||
|
||||
run 'make',compilation done. the udp2raw file is the just compiled binary
|
||||
|
||||
### platform which needs cross-compile
|
||||
such as openwrt router,run following instructions on your PC
|
||||
|
||||
##### install git
|
||||
run on debian/ubuntun:
|
||||
```
|
||||
sudo apt-get install git
|
||||
```
|
||||
run on redhat/centos:
|
||||
```
|
||||
sudo yum install git
|
||||
```
|
||||
|
||||
##### download cross compile tool chain
|
||||
|
||||
find it on downloads.openwrt.org according to your openwrt version and cpu model.
|
||||
|
||||
for example, my tplink wdr4310 runs chaos_calmer 15.05,its with ar71xx cpu,download the following package.
|
||||
|
||||
```
|
||||
http://downloads.openwrt.org/chaos_calmer/15.05/ar71xx/generic/OpenWrt-SDK-15.05-ar71xx-generic_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64.tar.bz2
|
||||
```
|
||||
unzip it to any dir,such as :/home/wangyu/OpenWrt-SDK-ar71xx-for-linux-x86_64-gcc-4.8-linaro_uClibc-0.9.33.2
|
||||
|
||||
cd into staging_dir ,toolchain-xxxxx ,bin .find the soft link with g++ suffix. in my case ,its mips-openwrt-linux-g++ ,check for its full path:
|
||||
|
||||
```
|
||||
/home/wangyu/Desktop/OpenWrt-SDK-15.05-ar71xx-generic_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-g++
|
||||
```
|
||||
##### compile
|
||||
modify first line of makefile to:
|
||||
```
|
||||
cc_cross=/home/wangyu/Desktop/OpenWrt-SDK-15.05-ar71xx-generic_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-g++
|
||||
```
|
||||
|
||||
run `make cross`,the just generated `udp2raw_cross` is the binary,compile done. copy it to your router to run.
|
||||
|
||||
`make cross` generates non-static binary. If you have any problem on running it,try to compile a static binary by using `make cross2` or `make cross3`.If your toolchain supports static compiling, usually one of them will succeed. The generated file is still named `udp2raw_cross`.
|
||||
|
||||
|
||||
|
||||
## Build a full release (include all binaries supported in the makefile)
|
||||
|
||||
1. make sure your linux is amd64 version
|
||||
|
||||
2. clone the repo
|
||||
|
||||
3. make sure you have g++ , make sure your g++ support the `-m32` option; make your your have installed libraries for `-m32` option
|
||||
|
||||
4. download https://github.com/wangyu-/files/releases/download/files/toolchains.tar.gz , and extract it to the right position (according to the makefile)
|
||||
|
||||
5. run `make release` inside udp2raw's directory
|
74
doc/build_guide.zh-cn.md
Normal file
@ -0,0 +1,74 @@
|
||||
# udp2raw编译方法
|
||||
本文演示怎么把udp2raw编译到自己所需的平台。
|
||||
|
||||
## 可以本地编译的linux平台
|
||||
比如电脑、树莓派
|
||||
|
||||
##### 首先安装git
|
||||
debian/ubuntun执行:
|
||||
```
|
||||
sudo apt-get install git
|
||||
```
|
||||
redhat/centos执行:
|
||||
```
|
||||
sudo yum install git
|
||||
```
|
||||
##### 用git把源码clone至本地
|
||||
|
||||
在任意目录执行:
|
||||
|
||||
```
|
||||
git clone https://github.com/wangyu-/udp2raw-tunnel.git
|
||||
cd udp2raw-tunnel
|
||||
```
|
||||
|
||||
##### 安装g++ make 等工具
|
||||
debian/ubuntun执行:
|
||||
```
|
||||
sudo apt-get install build-essential
|
||||
```
|
||||
|
||||
redhat/centos执行:
|
||||
```
|
||||
sudo yum groupinstall 'Development Tools'
|
||||
```
|
||||
|
||||
然后运行make,编译完成。 生成的udp2raw就是编译好的bianry。
|
||||
|
||||
## 需要交叉编译的平台
|
||||
比如各种openwrt路由器
|
||||
|
||||
##### 首先安装git
|
||||
debian/ubuntun执行:
|
||||
```
|
||||
sudo apt-get install git
|
||||
```
|
||||
redhat/centos执行:
|
||||
```
|
||||
sudo yum install git
|
||||
```
|
||||
|
||||
##### 下载安装交叉编译工具包
|
||||
去downloads.openwrt.org上找到自己的openwrt版本和cpu型号对应的SDK。通常openwrt版本号不一样也问题不大,最主要是cpu型号。
|
||||
|
||||
比如我的tplink wdr4310运行的是chaos_calmer 15.05,ar71xx cpu,应该下载这个包:
|
||||
|
||||
```
|
||||
http://downloads.openwrt.org/chaos_calmer/15.05/ar71xx/generic/OpenWrt-SDK-15.05-ar71xx-generic_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64.tar.bz2
|
||||
```
|
||||
解压到本地任意目录,比如:/home/wangyu/OpenWrt-SDK-ar71xx-for-linux-x86_64-gcc-4.8-linaro_uClibc-0.9.33.2
|
||||
|
||||
让后依次进入,staging_dir ,toolchain-xxxxx ,bin 目录,找到后缀是g++的软链,比如我的是mips-openwrt-linux-g++ ,记下这个文件的完整路径:
|
||||
|
||||
```
|
||||
/home/wangyu/Desktop/OpenWrt-SDK-15.05-ar71xx-generic_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-g++
|
||||
```
|
||||
##### 编译
|
||||
把makefile的第一行 cross_cc=后面的内容改成你刚才记下的完整路径:
|
||||
```
|
||||
cc_cross=/home/wangyu/Desktop/OpenWrt-SDK-15.05-ar71xx-generic_gcc-4.8-linaro_uClibc-0.9.33.2.Linux-x86_64/staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-g++
|
||||
```
|
||||
|
||||
执行`make cross`,目录下生成udp2raw_cross文件。编译完成。
|
||||
|
||||
`make cross`编译出的binary是非静态的。如果运行有问题,可以尝试用`make cross2`或`make cross3`编译静态的binary,你的工具链必须带静态库才能成功编译,生成的文件仍然叫udp2raw_cross.
|
71
doc/finalspeed_step_by_step.md
Normal file
@ -0,0 +1,71 @@
|
||||
# udp2raw+finalspeed 加速tcp流量 Step by Step 教程
|
||||

|
||||
|
||||
##### 背景
|
||||
国内有些ISP会对UDP做QOS或屏蔽,这时候加速协议对TCP发包模式的支持就很重要。finalspeed虽然本身支持在底层用TCP发包,但是其依赖的libpcap不支持openvz架构,即使不是openvz架构的主机,也存在不稳定的问题。
|
||||
|
||||
|
||||
##### 摘要
|
||||
udp2raw是一个把udp流量通过raw socket包装成tcp流量的工具。通过用udp2raw配合udp模式的 finalspeed一样可以达到在底层发tcp包,绕过QOS的效果。支持openvz,稳定性也好很多。原理上相当于在finalspeed外面再包了一层tunnel。
|
||||
|
||||
本教程会一步一步演示用udp2raw+finalspeed加速http流量的过程。加速任何其他tcp流量也一样,包括$\*\*\*。本文避免讨论科学上网,所以只演示加速http流量。
|
||||
|
||||
udp2raw也支持把udp流量包装成Icmp发送,本教程不做演示。
|
||||
|
||||
### 环境要求
|
||||
服务器主机是linux,有root权限。 可以是openvz架构的vps。 也可以是openwrt路由器。
|
||||
|
||||
本地主机是windows,本地有openwrt路由器或树莓派或安装了linux虚拟机(网卡设置为桥接模式)。
|
||||
|
||||
(如果嫌给虚拟机安装linux麻烦,可以用release里发布的预装了udp2raw的openwrt_x86虚拟机镜像,容量4.4mb)
|
||||
|
||||
下面的教程按虚拟机演示,如果你有openwrt路由器或树莓派,可以直接运行再路由器或树莓派上,就不需要虚拟机了。
|
||||
|
||||
### 安装
|
||||
下载好udp2raw的压缩包,解压分别解压到服务器和本地的虚拟机。
|
||||
|
||||
https://github.com/wangyu-/udp2raw-tunnel/releases
|
||||
|
||||
在服务器端安装好finalspeed服务端,在本地windows安装好finalspeed的客户端。服务端我以前是用91yun的一键安装脚本安装的,没装过的可以去网上搜一键安装脚本。
|
||||
|
||||
### 运行
|
||||
1.先在服务器主机运行如下命令,确定finalspeed服务端已经正常启动了。
|
||||
|
||||
```
|
||||
netstat -nlp|grep java
|
||||
```
|
||||

|
||||
|
||||
如果显示了150端口,就表示服务端启动好了。
|
||||
|
||||
2.在服务器启动udp2raw server
|
||||
```
|
||||
./udp2raw_amd64 -s -l0.0.0.0:8855 -r 127.0.0.1:150 -a -k "passwd" --raw-mode faketcp
|
||||
```
|
||||

|
||||
|
||||
3.在本地的虚拟机上启动udp2raw client ,假设服务器ip是45.66.77.88
|
||||
```
|
||||
./udp2raw_amd64 -c -r45.66.77.88:8855 -l0.0.0.0:150 --raw-mode faketcp -a -k"passwd"
|
||||
```
|
||||
如果一切正常,client端会显示client_ready:
|
||||
|
||||

|
||||
|
||||
记下红框中的ip,这是虚拟机的网卡ip
|
||||
|
||||
在server端也会显示server_ready
|
||||

|
||||
|
||||
4.在本地windows,按图配置好finalspeed的客户端。注意,192.168.205.8改成你刚才记下来的IP,带宽也要按实际的填。传输协议要选UDP.
|
||||

|
||||
|
||||
5.所有准备工作已经完成了,在本地访问本地的8012端口,相当于访问服务器的80端口。
|
||||
|
||||
来试一下通过http://127.0.0.1:8012/ 下载文件 ,1.5M/s:
|
||||

|
||||
|
||||
再试一下直接通过服务器的ip访问,http://45.66.77.88:80/ ,速度只有600K/s
|
||||

|
||||
|
||||
教程就到这里了,用来加速其他的tcp服务也是一样的,只要再第三步那里设置其他的端口。
|
1
doc/finalspeed_step_by_step/11
Normal file
@ -0,0 +1 @@
|
||||
11
|
BIN
doc/finalspeed_step_by_step/Capture.PNG
Normal file
After Width: | Height: | Size: 46 KiB |
BIN
doc/finalspeed_step_by_step/Capture0.PNG
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
doc/finalspeed_step_by_step/Capture2.PNG
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
doc/finalspeed_step_by_step/Capture3.PNG
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
doc/finalspeed_step_by_step/Capture4.PNG
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
doc/finalspeed_step_by_step/Capture5.PNG
Normal file
After Width: | Height: | Size: 5.4 KiB |
BIN
doc/finalspeed_step_by_step/Capture6.PNG
Normal file
After Width: | Height: | Size: 64 KiB |
BIN
doc/finalspeed_step_by_step/Capture7.PNG
Normal file
After Width: | Height: | Size: 69 KiB |
63
doc/kcptun_step_by_step.md
Normal file
@ -0,0 +1,63 @@
|
||||
# udp2raw+kcptun 加速tcp流量 Step by Step 教程
|
||||

|
||||
|
||||
本教程会一步一步演示用udp2raw+kcptun加速SSH流量的过程。加速任何其他tcp流量也一样,包括$\*\*\*;本文避免涉及科学上网,所以演示ssh。
|
||||
|
||||
### 环境要求
|
||||
两边的主机都是linux,有root权限。 可以是openwrt路由器或树莓派,也可以是root了的android。
|
||||
|
||||
在windows/mac上运行udp2raw可以参考这个教程:
|
||||
|
||||
https://github.com/wangyu-/udp2raw-tunnel/wiki/在windows-mac上运行udp2raw客户端,带图形界面
|
||||
|
||||
|
||||
### 安装
|
||||
下载好kcptun和udp2raw的压缩包,解压分别解压到client端和server端。
|
||||
|
||||
https://github.com/xtaci/kcptun/releases
|
||||
https://github.com/wangyu-/udp2raw-tunnel/releases
|
||||
|
||||
解压好后,如图:
|
||||

|
||||
|
||||
### 运行
|
||||
1.在远程服务器运行 udp2raw_amd64 server模式:
|
||||
```
|
||||
./udp2raw_amd64 -s -l0.0.0.0:8855 -r 127.0.0.1:4000 -k "passwd" --raw-mode faketcp -a
|
||||
```
|
||||

|
||||
|
||||
2.在本地运行udp2raw_amd64 client模式,假设server ip是45.66.77.88:
|
||||
```
|
||||
./udp2raw_amd64 -c -r45.66.77.88:8855 -l0.0.0.0:4000 --raw-mode faketcp -a -k"passwd"
|
||||
```
|
||||
如果一切正常client端输出如下,显示client_ready:
|
||||

|
||||
|
||||
server端也会有类似输出,显示server_ready:
|
||||

|
||||
|
||||
3.在远程服务器运行 kcp server
|
||||
|
||||
|
||||
```
|
||||
./server_linux_amd64 -t "127.0.0.1:22" -l ":4000" -mode fast2 -mtu 1300
|
||||
```
|
||||
-mtu 1300很重要,或者设置成更小。
|
||||

|
||||
|
||||
4.在本地运行
|
||||
|
||||
|
||||
```
|
||||
./client_linux_amd64 -r "127.0.0.1:4000" -l ":3322" -mode fast2 -mtu 1300
|
||||
```
|
||||
-mtu 1300很重要,或者设置成更小。
|
||||

|
||||
|
||||
5.所有准备工作已经做好,在本地运行
|
||||
```
|
||||
ssh -p 3322 root@127.0.0.1
|
||||
```
|
||||
已经连进去了,而且是经过kcptun加速的:
|
||||

|
BIN
doc/kcptun_step_by_step/Capture.PNG
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
doc/kcptun_step_by_step/Capture0.PNG
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
doc/kcptun_step_by_step/Capture00.PNG
Normal file
After Width: | Height: | Size: 28 KiB |
BIN
doc/kcptun_step_by_step/Capture2.PNG
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
doc/kcptun_step_by_step/Capture3.PNG
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
doc/kcptun_step_by_step/Capture6.PNG
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
doc/kcptun_step_by_step/Capture7.PNG
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
doc/kcptun_step_by_step/Capture8.PNG
Normal file
After Width: | Height: | Size: 14 KiB |
94
doc/openvpn_guide.md
Normal file
@ -0,0 +1,94 @@
|
||||
# udp2raw+openvpn config guide
|
||||

|
||||
|
||||

|
||||
|
||||
# udp2raw command
|
||||
#### run at server side
|
||||
```
|
||||
./udp2raw_amd64 -s -l0.0.0.0:8855 -r 127.0.0.1:7777 -k "passwd" --raw-mode faketcp -a
|
||||
```
|
||||
#### run at client side
|
||||
assume server ip is 45.66.77.88
|
||||
```
|
||||
./udp2raw_amd64 -c -l0.0.0.0:3333 -r 45.66.77.88:8855 -k "passwd" --raw-mode faketcp -a
|
||||
```
|
||||
|
||||
#### hint
|
||||
You can add `--cipher-mode xor` `--auth-mode simple` to **both** sides to obtain maximum performance(but poor security).
|
||||
|
||||
# openvpn config
|
||||
|
||||
#### client side config
|
||||
```
|
||||
client
|
||||
dev tun100
|
||||
proto udp
|
||||
|
||||
remote 127.0.0.1 3333
|
||||
resolv-retry infinite
|
||||
nobind
|
||||
persist-key
|
||||
persist-tun
|
||||
|
||||
ca /root/add-on/openvpn/ca.crt
|
||||
cert /root/add-on/openvpn/client.crt
|
||||
key /root/add-on/openvpn/client.key
|
||||
|
||||
keepalive 3 20
|
||||
verb 3
|
||||
mute 20
|
||||
|
||||
comp-lzo no
|
||||
cipher none ##### disable openvpn 's cipher and auth for maxmized peformance.
|
||||
auth none ##### you can enable openvpn's cipher and auth,if you dont care about peformance,or you dont trust udp2raw 's encryption
|
||||
|
||||
fragment 1200 ##### very important you can turn it up a bit. but,the lower the safer
|
||||
mssfix 1200 ##### very important
|
||||
|
||||
sndbuf 2000000 ##### important
|
||||
rcvbuf 2000000 ##### important
|
||||
txqueuelen 4000 ##### suggested
|
||||
```
|
||||
|
||||
|
||||
#### server side config
|
||||
```
|
||||
local 0.0.0.0
|
||||
port 7777
|
||||
proto udp
|
||||
dev tun
|
||||
|
||||
ca /etc/openvpn/easy-rsa/2.0/keys/ca.crt
|
||||
cert /etc/openvpn/easy-rsa/2.0/keys/server.crt
|
||||
key /etc/openvpn/easy-rsa/2.0/keys/server.key
|
||||
dh /etc/openvpn/easy-rsa/2.0/keys/dh1024.pem
|
||||
|
||||
server 10.222.2.0 255.255.255.0
|
||||
ifconfig 10.222.2.1 10.222.2.6
|
||||
|
||||
client-to-client
|
||||
duplicate-cn
|
||||
keepalive 10 60
|
||||
|
||||
max-clients 50
|
||||
|
||||
persist-key
|
||||
persist-tun
|
||||
|
||||
status /etc/openvpn/openvpn-status.log
|
||||
|
||||
verb 3
|
||||
mute 20
|
||||
|
||||
comp-lzo no
|
||||
cipher none ##### disable openvpn 's cipher and auth for maxmized peformance.
|
||||
auth none ##### you can enable openvpn's cipher and auth,if you dont care about peformance,or you dont trust udp2raw 's encryption
|
||||
|
||||
fragment 1200 ##### very important you can turn it up a bit. but,the lower the safer
|
||||
mssfix 1200 ##### very important
|
||||
|
||||
sndbuf 2000000 ##### important
|
||||
rcvbuf 2000000 ##### important
|
||||
txqueuelen 4000 ##### suggested
|
||||
```
|
885
encrypt.cpp
Executable file → Normal file
@ -1,48 +1,137 @@
|
||||
#include <lib/aes.h>
|
||||
#include <lib/md5.h>
|
||||
#include "lib/aes-common.h"
|
||||
#include "lib/md5.h"
|
||||
#include "lib/pbkdf2-sha1.h"
|
||||
#include "lib/pbkdf2-sha256.h"
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <encrypt.h>
|
||||
#include <common.h>
|
||||
#include "encrypt.h"
|
||||
#include "common.h"
|
||||
#include "log.h"
|
||||
|
||||
//static uint64_t seq=1;
|
||||
// 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
|
||||
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
|
||||
/****
|
||||
* security of zero_iv + nonce first data block
|
||||
* https://crypto.stackexchange.com/questions/5421/using-cbc-with-a-fixed-iv-and-a-random-first-plaintext-block
|
||||
****/
|
||||
|
||||
char normal_key[16 + 100]; // generated from key_string by md5. reserved for compatiblity
|
||||
const int hmac_key_len = 64; // generate 512bit long keys, use first n chars when needed
|
||||
const int cipher_key_len = 64;
|
||||
unsigned char hmac_key_encrypt[hmac_key_len + 100]; // key for hmac
|
||||
unsigned char hmac_key_decrypt[hmac_key_len + 100]; // key for hmac
|
||||
unsigned char cipher_key_encrypt[cipher_key_len + 100]; // key for aes etc.
|
||||
unsigned char cipher_key_decrypt[cipher_key_len + 100]; // key for aes etc.
|
||||
|
||||
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"}};
|
||||
char gro_xor[256 + 100]; // dirty fix for gro
|
||||
|
||||
auth_mode_t auth_mode=auth_crc32;
|
||||
cipher_mode_t cipher_mode=cipher_aes128cbc;
|
||||
unordered_map<int, const char *> auth_mode_tostring = {
|
||||
{auth_none, "none"},
|
||||
{auth_md5, "md5"},
|
||||
{auth_crc32, "crc32"},
|
||||
{auth_simple, "simple"},
|
||||
{auth_hmac_sha1, "hmac_sha1"},
|
||||
};
|
||||
|
||||
unordered_map<int, const char *> cipher_mode_tostring = {
|
||||
{cipher_none, "none"},
|
||||
{cipher_aes128cfb, "aes128cfb"},
|
||||
{cipher_aes128cbc, "aes128cbc"},
|
||||
{cipher_xor, "xor"},
|
||||
};
|
||||
// TODO aes-gcm
|
||||
|
||||
auth_mode_t auth_mode = auth_md5;
|
||||
cipher_mode_t cipher_mode = cipher_aes128cbc;
|
||||
int is_hmac_used = 0;
|
||||
|
||||
int aes128cfb_old = 0;
|
||||
|
||||
// TODO key negotiation and forward secrecy
|
||||
|
||||
int my_init_keys(const char *user_passwd, int is_client) {
|
||||
char tmp[1000] = "";
|
||||
int len = strlen(user_passwd);
|
||||
|
||||
strcat(tmp, user_passwd);
|
||||
|
||||
strcat(tmp, "key1");
|
||||
|
||||
md5((uint8_t *)tmp, strlen(tmp), (uint8_t *)normal_key);
|
||||
|
||||
if (auth_mode == auth_hmac_sha1)
|
||||
is_hmac_used = 1;
|
||||
if (is_hmac_used || g_fix_gro || 1) {
|
||||
unsigned char salt[400] = "";
|
||||
char salt_text[400] = "udp2raw_salt1";
|
||||
md5((uint8_t *)(salt_text), strlen(salt_text), salt); // TODO different salt per session
|
||||
|
||||
unsigned char pbkdf2_output1[400] = "";
|
||||
PKCS5_PBKDF2_HMAC_SHA256((uint8_t *)user_passwd, len, salt, 16, 10000, 32, pbkdf2_output1); // TODO argon2 ?
|
||||
|
||||
// unsigned char pbkdf2_output2[400]="";
|
||||
// PKCS5_PBKDF2_HMAC_SHA256(pbkdf2_output1,32,0,0,1, hmac_key_len*2+cipher_key_len*2,pbkdf2_output2); //stretch it
|
||||
|
||||
const char *info_hmac_encrypt = "hmac_key server-->client";
|
||||
const char *info_hmac_decrypt = "hmac_key client-->server";
|
||||
const char *info_cipher_encrypt = "cipher_key server-->client";
|
||||
const char *info_cipher_decrypt = "cipher_key client-->server";
|
||||
|
||||
if (is_client) {
|
||||
const char *tmp;
|
||||
tmp = info_hmac_encrypt;
|
||||
info_hmac_encrypt = info_hmac_decrypt;
|
||||
info_hmac_decrypt = tmp;
|
||||
tmp = info_cipher_encrypt;
|
||||
info_cipher_encrypt = info_cipher_decrypt;
|
||||
info_cipher_decrypt = tmp;
|
||||
} else {
|
||||
// nop
|
||||
}
|
||||
|
||||
assert(hkdf_sha256_expand(pbkdf2_output1, 32, (unsigned char *)info_cipher_encrypt, strlen(info_cipher_encrypt), cipher_key_encrypt, cipher_key_len) == 0);
|
||||
assert(hkdf_sha256_expand(pbkdf2_output1, 32, (unsigned char *)info_cipher_decrypt, strlen(info_cipher_decrypt), cipher_key_decrypt, cipher_key_len) == 0);
|
||||
assert(hkdf_sha256_expand(pbkdf2_output1, 32, (unsigned char *)info_hmac_encrypt, strlen(info_hmac_encrypt), hmac_key_encrypt, hmac_key_len) == 0);
|
||||
assert(hkdf_sha256_expand(pbkdf2_output1, 32, (unsigned char *)info_hmac_decrypt, strlen(info_hmac_decrypt), hmac_key_decrypt, hmac_key_len) == 0);
|
||||
|
||||
const char *gro_info = "gro";
|
||||
assert(hkdf_sha256_expand(pbkdf2_output1, 32, (unsigned char *)gro_info, strlen(gro_info), (unsigned char *)gro_xor, 256) == 0);
|
||||
}
|
||||
|
||||
print_binary_chars(normal_key, 16);
|
||||
print_binary_chars((char *)hmac_key_encrypt, hmac_key_len);
|
||||
print_binary_chars((char *)hmac_key_decrypt, hmac_key_len);
|
||||
print_binary_chars((char *)cipher_key_encrypt, cipher_key_len);
|
||||
print_binary_chars((char *)cipher_key_decrypt, cipher_key_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* this function comes from http://www.hackersdelight.org/hdcodetxt/crc.c.txt
|
||||
*/
|
||||
unsigned int crc32h(unsigned char *message,int len) {
|
||||
int i, crc;
|
||||
unsigned int byte, c;
|
||||
const unsigned int g0 = 0xEDB88320, g1 = g0>>1,
|
||||
g2 = g0>>2, g3 = g0>>3, g4 = g0>>4, g5 = g0>>5,
|
||||
g6 = (g0>>6)^g0, g7 = ((g0>>6)^g0)>>1;
|
||||
unsigned int crc32h(unsigned char *message, int len) {
|
||||
int i, crc;
|
||||
unsigned int byte, c;
|
||||
const unsigned int g0 = 0xEDB88320, g1 = g0 >> 1,
|
||||
g2 = g0 >> 2, g3 = g0 >> 3, g4 = g0 >> 4, g5 = g0 >> 5,
|
||||
g6 = (g0 >> 6) ^ g0, g7 = ((g0 >> 6) ^ g0) >> 1;
|
||||
|
||||
i = 0;
|
||||
crc = 0xFFFFFFFF;
|
||||
while (i!=len) { // Get next byte.
|
||||
byte = message[i];
|
||||
crc = crc ^ byte;
|
||||
c = ((crc<<31>>31) & g7) ^ ((crc<<30>>31) & g6) ^
|
||||
((crc<<29>>31) & g5) ^ ((crc<<28>>31) & g4) ^
|
||||
((crc<<27>>31) & g3) ^ ((crc<<26>>31) & g2) ^
|
||||
((crc<<25>>31) & g1) ^ ((crc<<24>>31) & g0);
|
||||
crc = ((unsigned)crc >> 8) ^ c;
|
||||
i = i + 1;
|
||||
}
|
||||
return ~crc;
|
||||
i = 0;
|
||||
crc = 0xFFFFFFFF;
|
||||
while (i != len) { // Get next byte.
|
||||
byte = message[i];
|
||||
crc = crc ^ byte;
|
||||
c = ((crc << 31 >> 31) & g7) ^ ((crc << 30 >> 31) & g6) ^
|
||||
((crc << 29 >> 31) & g5) ^ ((crc << 28 >> 31) & g4) ^
|
||||
((crc << 27 >> 31) & g3) ^ ((crc << 26 >> 31) & g2) ^
|
||||
((crc << 25 >> 31) & g1) ^ ((crc << 24 >> 31) & g0);
|
||||
crc = ((unsigned)crc >> 8) ^ c;
|
||||
i = i + 1;
|
||||
}
|
||||
return ~crc;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -50,380 +139,450 @@ unsigned int crc32h(unsigned char *message,int len) {
|
||||
memset(res,0,sizeof(int));
|
||||
for(int i=0,j=0;i<len;i++,j++)
|
||||
{
|
||||
if(j==4) j=0;
|
||||
res[j]+=data[i];
|
||||
if(j==4) j=0;
|
||||
res[j]+=data[i];
|
||||
}
|
||||
|
||||
return ;
|
||||
}*/
|
||||
|
||||
void simple_hash(unsigned char *str,int len,unsigned char res[8]) //djb2+ sdbm
|
||||
void simple_hash(unsigned char *str, int len, unsigned char res[8]) // djb2+ sdbm
|
||||
{
|
||||
u32_t hash = 5381;
|
||||
u32_t hash2 = 0;
|
||||
int c;
|
||||
int i=0;
|
||||
while(c = *str++,i++!=len)
|
||||
{
|
||||
u32_t hash = 5381;
|
||||
u32_t hash2 = 0;
|
||||
int c;
|
||||
int i = 0;
|
||||
while (c = *str++, i++ != len) {
|
||||
// hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
|
||||
hash = ((hash << 5) + hash)^c; /* (hash * 33) ^ c */
|
||||
hash2 = c + (hash2 << 6) + (hash2 << 16) - hash2;
|
||||
hash = ((hash << 5) + hash) ^ c; /* (hash * 33) ^ c */
|
||||
hash2 = c + (hash2 << 6) + (hash2 << 16) - hash2;
|
||||
}
|
||||
|
||||
hash=htonl(hash);
|
||||
hash2=htonl(hash2);
|
||||
memcpy(res,&hash,sizeof(hash));
|
||||
memcpy(res+sizeof(hash),&hash2,sizeof(hash2));
|
||||
}
|
||||
|
||||
int auth_md5_cal(const char *data,char * output,int &len)
|
||||
{
|
||||
memcpy(output,data,len);//TODO inefficient code
|
||||
md5((unsigned char *)output,len,(unsigned char *)(output+len));
|
||||
len+=16;
|
||||
return 0;
|
||||
hash = htonl(hash);
|
||||
hash2 = htonl(hash2);
|
||||
memcpy(res, &hash, sizeof(hash));
|
||||
memcpy(res + sizeof(hash), &hash2, sizeof(hash2));
|
||||
}
|
||||
|
||||
int auth_crc32_cal(const char *data,char * output,int &len)
|
||||
{
|
||||
memcpy(output,data,len);//TODO inefficient code
|
||||
unsigned int ret=crc32h((unsigned char *)output,len);
|
||||
unsigned int ret_n=htonl(ret);
|
||||
memcpy(output+len,&ret_n,sizeof(unsigned int));
|
||||
len+=sizeof(unsigned int);
|
||||
return 0;
|
||||
int auth_md5_cal(const char *data, char *output, int &len) {
|
||||
memcpy(output, data, len); // TODO inefficient code
|
||||
md5((unsigned char *)output, len, (unsigned char *)(output + len));
|
||||
len += 16;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int auth_simple_cal(const char *data,char * output,int &len)
|
||||
{
|
||||
//char res[4];
|
||||
memcpy(output,data,len);//TODO inefficient code
|
||||
simple_hash((unsigned char *)output,len,(unsigned char *)(output+len));
|
||||
len+=8;
|
||||
return 0;
|
||||
}
|
||||
int auth_simple_verify(const char *data,int &len)
|
||||
{
|
||||
if(len<8) return -1;
|
||||
unsigned char res[8];
|
||||
len-=8;
|
||||
simple_hash((unsigned char *)data,len,res);
|
||||
if(memcmp(res,data+len,8)!=0)
|
||||
return -1;
|
||||
return 0;
|
||||
int auth_hmac_sha1_cal(const char *data, char *output, int &len) {
|
||||
mylog(log_trace, "auth_hmac_sha1_cal() is called\n");
|
||||
memcpy(output, data, len); // TODO inefficient code
|
||||
sha1_hmac(hmac_key_encrypt, 20, (const unsigned char *)data, len, (unsigned char *)(output + len));
|
||||
// use key len of 20 instead of hmac_key_len, "extra length would not significantly increase the function strength" (rfc2104)
|
||||
len += 20;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int auth_hmac_sha1_verify(const char *data, int &len) {
|
||||
mylog(log_trace, "auth_hmac_sha1_verify() is called\n");
|
||||
if (len < 20) {
|
||||
mylog(log_trace, "auth_hmac_sha1_verify len<20\n");
|
||||
return -1;
|
||||
}
|
||||
char res[20];
|
||||
|
||||
int auth_none_cal(const char *data,char * output,int &len)
|
||||
{
|
||||
memcpy(output,data,len);
|
||||
return 0;
|
||||
}
|
||||
int auth_md5_verify(const char *data,int &len)
|
||||
{
|
||||
if(len<16)
|
||||
{
|
||||
mylog(log_trace,"auth_md5_verify len<16\n");
|
||||
return -1;
|
||||
}
|
||||
char md5_res[16];
|
||||
sha1_hmac(hmac_key_decrypt, 20, (const unsigned char *)data, len - 20, (unsigned char *)(res));
|
||||
|
||||
md5((unsigned char *)data,len-16,(unsigned char *)md5_res);
|
||||
|
||||
if(memcmp(md5_res,data+len-16,16)!=0)
|
||||
{
|
||||
mylog(log_trace,"auth_md5_verify md5 check failed\n");
|
||||
return -2;
|
||||
}
|
||||
len-=16;
|
||||
return 0;
|
||||
}
|
||||
int auth_none_verify(const char *data,int &len)
|
||||
{
|
||||
return 0;
|
||||
if (memcmp(res, data + len - 20, 20) != 0) {
|
||||
mylog(log_trace, "auth_hmac_sha1 check failed\n");
|
||||
return -2;
|
||||
}
|
||||
len -= 20;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cipher_xor_encrypt(const char * data, char *output,int &len, char *key) {
|
||||
int i, j;
|
||||
for (i = 0, j = 0; i < len; i++, j++) {
|
||||
if(j==16) j=0;
|
||||
output[i] = data[i]^key[j];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int cipher_xor_decrypt(const char * data, char *output,int &len, char *key) {
|
||||
int i, j;
|
||||
//char tmp[buf_len];
|
||||
//len=len/16*16+1;
|
||||
//AES128_CBC_decrypt_buffer((uint8_t *)tmp, (uint8_t *)input, len, (uint8_t *)key, (uint8_t *)iv);
|
||||
//for(i=0;i<len;i++)
|
||||
//input[i]=tmp[i];
|
||||
for (i = 0, j = 0; i < len; i++, j++) {
|
||||
if(j==16) j=0;
|
||||
output[i] = data[i]^key[j];
|
||||
}
|
||||
return 0;
|
||||
int auth_crc32_cal(const char *data, char *output, int &len) {
|
||||
memcpy(output, data, len); // TODO inefficient code
|
||||
unsigned int ret = crc32h((unsigned char *)output, len);
|
||||
unsigned int ret_n = htonl(ret);
|
||||
memcpy(output + len, &ret_n, sizeof(unsigned int));
|
||||
len += sizeof(unsigned int);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int padding(char *data ,int &data_len,int padding_num)
|
||||
{
|
||||
int old_len=data_len;
|
||||
data_len+=1;
|
||||
if(data_len%padding_num!=0)
|
||||
{
|
||||
data_len= (data_len/padding_num)*padding_num+padding_num;
|
||||
}
|
||||
data[data_len-1]= (data_len-old_len);
|
||||
return 0;
|
||||
int auth_simple_cal(const char *data, char *output, int &len) {
|
||||
// char res[4];
|
||||
memcpy(output, data, len); // TODO inefficient code
|
||||
simple_hash((unsigned char *)output, len, (unsigned char *)(output + len));
|
||||
len += 8;
|
||||
return 0;
|
||||
}
|
||||
int auth_simple_verify(const char *data, int &len) {
|
||||
if (len < 8) return -1;
|
||||
unsigned char res[8];
|
||||
len -= 8;
|
||||
simple_hash((unsigned char *)data, len, res);
|
||||
if (memcmp(res, data + len, 8) != 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int de_padding(const char *data ,int &data_len,int padding_num)
|
||||
{
|
||||
if((uint8_t)data[data_len-1] >padding_num) return -1;
|
||||
data_len-=(uint8_t)data[data_len-1];
|
||||
if(data_len<0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
int auth_none_cal(const char *data, char *output, int &len) {
|
||||
memcpy(output, data, len);
|
||||
return 0;
|
||||
}
|
||||
int cipher_aes128cbc_encrypt(const char *data,char *output,int &len,char * key)
|
||||
{
|
||||
char buf[buf_len];
|
||||
memcpy(buf,data,len);//TODO inefficient code
|
||||
int auth_md5_verify(const char *data, int &len) {
|
||||
if (len < 16) {
|
||||
mylog(log_trace, "auth_md5_verify len<16\n");
|
||||
return -1;
|
||||
}
|
||||
char md5_res[16];
|
||||
|
||||
md5((unsigned char *)data, len - 16, (unsigned char *)md5_res);
|
||||
|
||||
/*
|
||||
int ori_len=len;
|
||||
len+=2;//length
|
||||
if(len%16!=0)
|
||||
{
|
||||
len= (len/16)*16+16;
|
||||
}
|
||||
//if(len>max_data_len) return -1;
|
||||
|
||||
buf[len-2]= (unsigned char)( (uint16_t(ori_len))>>8);
|
||||
buf[len-1]=(unsigned char)( ((uint16_t(ori_len))<<8)>>8) ;*/
|
||||
if(padding(buf,len,16)<0) return -1;
|
||||
|
||||
AES_CBC_encrypt_buffer((unsigned char *)output,(unsigned char *)buf,len,(unsigned char *)key,(unsigned char *)zero_iv);
|
||||
return 0;
|
||||
if (memcmp(md5_res, data + len - 16, 16) != 0) {
|
||||
mylog(log_trace, "auth_md5_verify md5 check failed\n");
|
||||
return -2;
|
||||
}
|
||||
len -= 16;
|
||||
return 0;
|
||||
}
|
||||
int auth_crc32_verify(const char *data,int &len)
|
||||
{
|
||||
if(len<int(sizeof(unsigned int)))
|
||||
{
|
||||
mylog(log_debug,"auth_crc32_verify len<16\n");
|
||||
return -1;
|
||||
}
|
||||
unsigned int ret=crc32h((unsigned char *)data,len-sizeof(unsigned int));
|
||||
unsigned int ret_n=htonl(ret);
|
||||
|
||||
if(memcmp(data+len-sizeof(unsigned int),&ret_n,sizeof(unsigned int))!=0)
|
||||
{
|
||||
mylog(log_debug,"auth_crc32_verify memcmp fail\n");
|
||||
return -1;
|
||||
}
|
||||
len-=sizeof(unsigned int);
|
||||
return 0;
|
||||
}
|
||||
int cipher_none_encrypt(const char *data,char *output,int &len,char * key)
|
||||
{
|
||||
memcpy(output,data,len);
|
||||
return 0;
|
||||
}
|
||||
int cipher_aes128cbc_decrypt(const char *data,char *output,int &len,char * key)
|
||||
{
|
||||
|
||||
if(len%16 !=0) {mylog(log_debug,"len%%16!=0\n");return -1;}
|
||||
//if(len<0) {mylog(log_debug,"len <0\n");return -1;}
|
||||
AES_CBC_decrypt_buffer((unsigned char *)output,(unsigned char *)data,len,(unsigned char *)key,(unsigned char *)zero_iv);
|
||||
if(de_padding(output,len,16)<0) return -1;
|
||||
return 0;
|
||||
int auth_none_verify(const char *data, int &len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cipher_none_decrypt(const char *data,char *output,int &len,char * key)
|
||||
{
|
||||
memcpy(output,data,len);
|
||||
return 0;
|
||||
int cipher_xor_encrypt(const char *data, char *output, int &len, char *key) {
|
||||
int i, j;
|
||||
for (i = 0, j = 0; i < len; i++, j++) {
|
||||
if (j == 16) j = 0;
|
||||
output[i] = data[i] ^ key[j];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int cipher_xor_decrypt(const char *data, char *output, int &len, char *key) {
|
||||
int i, j;
|
||||
// char tmp[buf_len];
|
||||
// len=len/16*16+1;
|
||||
// AES128_CBC_decrypt_buffer((uint8_t *)tmp, (uint8_t *)input, len, (uint8_t *)key, (uint8_t *)iv);
|
||||
// for(i=0;i<len;i++)
|
||||
// input[i]=tmp[i];
|
||||
for (i = 0, j = 0; i < len; i++, j++) {
|
||||
if (j == 16) j = 0;
|
||||
output[i] = data[i] ^ key[j];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int auth_cal(const char *data,char * output,int &len)
|
||||
{
|
||||
mylog(log_trace,"auth:%d\n",auth_mode);
|
||||
switch(auth_mode)
|
||||
{
|
||||
case auth_crc32:return auth_crc32_cal(data, output, len);
|
||||
case auth_md5:return auth_md5_cal(data, output, len);
|
||||
case auth_simple:return auth_simple_cal(data, output, len);
|
||||
case auth_none:return auth_none_cal(data, output, len);
|
||||
default: return auth_md5_cal(data,output,len);//default
|
||||
}
|
||||
|
||||
}
|
||||
int auth_verify(const char *data,int &len)
|
||||
{
|
||||
mylog(log_trace,"auth:%d\n",auth_mode);
|
||||
switch(auth_mode)
|
||||
{
|
||||
case auth_crc32:return auth_crc32_verify(data, len);
|
||||
case auth_md5:return auth_md5_verify(data, len);
|
||||
case auth_simple:return auth_simple_verify(data, len);
|
||||
case auth_none:return auth_none_verify(data, len);
|
||||
default: return auth_md5_verify(data,len);//default
|
||||
}
|
||||
|
||||
}
|
||||
int cipher_encrypt(const char *data,char *output,int &len,char * key)
|
||||
{
|
||||
mylog(log_trace,"cipher:%d\n",cipher_mode);
|
||||
switch(cipher_mode)
|
||||
{
|
||||
case cipher_aes128cbc:return cipher_aes128cbc_encrypt(data,output,len, key);
|
||||
case cipher_xor:return cipher_xor_encrypt(data,output,len, key);
|
||||
case cipher_none:return cipher_none_encrypt(data,output,len, key);
|
||||
default:return cipher_aes128cbc_encrypt(data,output,len, key);
|
||||
}
|
||||
|
||||
}
|
||||
int cipher_decrypt(const char *data,char *output,int &len,char * key)
|
||||
{
|
||||
mylog(log_trace,"cipher:%d\n",cipher_mode);
|
||||
switch(cipher_mode)
|
||||
{
|
||||
case cipher_aes128cbc:return cipher_aes128cbc_decrypt(data,output,len, key);
|
||||
case cipher_xor:return cipher_xor_decrypt(data,output,len, key);
|
||||
case cipher_none:return cipher_none_decrypt(data,output,len, key);
|
||||
default: return cipher_aes128cbc_decrypt(data,output,len,key);
|
||||
}
|
||||
|
||||
int padding(char *data, int &data_len, int padding_num) {
|
||||
int old_len = data_len;
|
||||
data_len += 1;
|
||||
if (data_len % padding_num != 0) {
|
||||
data_len = (data_len / padding_num) * padding_num + padding_num;
|
||||
}
|
||||
unsigned char *p = (unsigned char *)&data[data_len - 1];
|
||||
*p = (data_len - old_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int my_encrypt(const char *data,char *output,int &len,char * key)
|
||||
{
|
||||
if(len<0) {mylog(log_trace,"len<0");return -1;}
|
||||
if(len>max_data_len) {mylog(log_warn,"len>max_data_len");return -1;}
|
||||
|
||||
char buf[buf_len];
|
||||
char buf2[buf_len];
|
||||
memcpy(buf,data,len);
|
||||
if(auth_cal(buf,buf2,len)!=0) {mylog(log_debug,"auth_cal failed ");return -1;}
|
||||
if(cipher_encrypt(buf2,output,len,key) !=0) {mylog(log_debug,"cipher_encrypt failed ");return -1;}
|
||||
return 0;
|
||||
|
||||
int de_padding(const char *data, int &data_len, int padding_num) {
|
||||
if (data_len == 0) return -1;
|
||||
if ((uint8_t)data[data_len - 1] > padding_num) return -1;
|
||||
data_len -= (uint8_t)data[data_len - 1];
|
||||
if (data_len < 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int my_decrypt(const char *data,char *output,int &len,char * key)
|
||||
{
|
||||
if(len<0) return -1;
|
||||
if(len>max_data_len) {mylog(log_warn,"len>max_data_len");return -1;}
|
||||
void aes_ecb_encrypt(const char *data, char *output) {
|
||||
static int first_time = 1;
|
||||
char *key = (char *)cipher_key_encrypt;
|
||||
if (aes_key_optimize) {
|
||||
if (first_time == 0)
|
||||
key = 0;
|
||||
else
|
||||
first_time = 0;
|
||||
}
|
||||
AES_ECB_encrypt_buffer((uint8_t *)data, (uint8_t *)key, (uint8_t *)output);
|
||||
}
|
||||
void aes_ecb_encrypt1(char *data) {
|
||||
char buf[16];
|
||||
memcpy(buf, data, 16);
|
||||
aes_ecb_encrypt(buf, data);
|
||||
}
|
||||
void aes_ecb_decrypt(const char *data, char *output) {
|
||||
static int first_time = 1;
|
||||
char *key = (char *)cipher_key_decrypt;
|
||||
if (aes_key_optimize) {
|
||||
if (first_time == 0)
|
||||
key = 0;
|
||||
else
|
||||
first_time = 0;
|
||||
}
|
||||
AES_ECB_decrypt_buffer((uint8_t *)data, (uint8_t *)key, (uint8_t *)output);
|
||||
}
|
||||
void aes_ecb_decrypt1(char *data) {
|
||||
char buf[16];
|
||||
memcpy(buf, data, 16);
|
||||
aes_ecb_decrypt(buf, data);
|
||||
}
|
||||
int cipher_aes128cbc_encrypt(const char *data, char *output, int &len, char *key) {
|
||||
static int first_time = 1;
|
||||
|
||||
if(cipher_decrypt(data,output,len,key) !=0) {mylog(log_debug,"cipher_decrypt failed \n"); return -1;}
|
||||
if(auth_verify(output,len)!=0) {mylog(log_debug,"auth_verify failed\n");return -1;}
|
||||
char buf[buf_len];
|
||||
memcpy(buf, data, len); // TODO inefficient code
|
||||
|
||||
return 0;
|
||||
if (padding(buf, len, 16) < 0) return -1;
|
||||
|
||||
if (aes_key_optimize) {
|
||||
if (first_time == 0)
|
||||
key = 0;
|
||||
else
|
||||
first_time = 0;
|
||||
}
|
||||
|
||||
AES_CBC_encrypt_buffer((unsigned char *)output, (unsigned char *)buf, len, (unsigned char *)key, (unsigned char *)zero_iv);
|
||||
return 0;
|
||||
}
|
||||
int cipher_aes128cfb_encrypt(const char *data, char *output, int &len, char *key) {
|
||||
static int first_time = 1;
|
||||
assert(len >= 16);
|
||||
|
||||
char buf[buf_len];
|
||||
memcpy(buf, data, len); // TODO inefficient code
|
||||
if (aes_key_optimize) {
|
||||
if (first_time == 0)
|
||||
key = 0;
|
||||
else
|
||||
first_time = 0;
|
||||
}
|
||||
if (!aes128cfb_old) {
|
||||
aes_ecb_encrypt(data, buf); // encrypt the first block
|
||||
}
|
||||
|
||||
AES_CFB_encrypt_buffer((unsigned char *)output, (unsigned char *)buf, len, (unsigned char *)key, (unsigned char *)zero_iv);
|
||||
return 0;
|
||||
}
|
||||
int auth_crc32_verify(const char *data, int &len) {
|
||||
if (len < int(sizeof(unsigned int))) {
|
||||
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));
|
||||
unsigned int ret_n = htonl(ret);
|
||||
|
||||
if (memcmp(data + len - sizeof(unsigned int), &ret_n, sizeof(unsigned int)) != 0) {
|
||||
mylog(log_debug, "auth_crc32_verify memcmp fail\n");
|
||||
return -1;
|
||||
}
|
||||
len -= sizeof(unsigned int);
|
||||
return 0;
|
||||
}
|
||||
int cipher_none_encrypt(const char *data, char *output, int &len, char *key) {
|
||||
memcpy(output, data, len);
|
||||
return 0;
|
||||
}
|
||||
int cipher_aes128cbc_decrypt(const char *data, char *output, int &len, char *key) {
|
||||
static int first_time = 1;
|
||||
if (len % 16 != 0) {
|
||||
mylog(log_debug, "len%%16!=0\n");
|
||||
return -1;
|
||||
}
|
||||
if (aes_key_optimize) {
|
||||
if (first_time == 0)
|
||||
key = 0;
|
||||
else
|
||||
first_time = 0;
|
||||
}
|
||||
AES_CBC_decrypt_buffer((unsigned char *)output, (unsigned char *)data, len, (unsigned char *)key, (unsigned char *)zero_iv);
|
||||
if (de_padding(output, len, 16) < 0) return -1;
|
||||
return 0;
|
||||
}
|
||||
int cipher_aes128cfb_decrypt(const char *data, char *output, int &len, char *key) {
|
||||
static int first_time = 1;
|
||||
if (len < 16) return -1;
|
||||
|
||||
if (aes_key_optimize) {
|
||||
if (first_time == 0)
|
||||
key = 0;
|
||||
else
|
||||
first_time = 0;
|
||||
}
|
||||
|
||||
AES_CFB_decrypt_buffer((unsigned char *)output, (unsigned char *)data, len, (unsigned char *)key, (unsigned char *)zero_iv);
|
||||
|
||||
if (!aes128cfb_old)
|
||||
aes_ecb_decrypt1(output); // decrypt the first block
|
||||
// if(de_padding(output,len,16)<0) return -1;
|
||||
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 cipher_none_decrypt(const char *data, char *output, int &len, char *key) {
|
||||
memcpy(output, data, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int my_encrypt_pesudo_header(uint8_t *data,uint8_t *output,int &len,uint8_t * key,uint8_t *header,int hlen)
|
||||
{
|
||||
|
||||
return 0;
|
||||
int auth_cal(const char *data, char *output, int &len) {
|
||||
mylog(log_trace, "auth:%d\n", auth_mode);
|
||||
switch (auth_mode) {
|
||||
case auth_crc32:
|
||||
return auth_crc32_cal(data, output, len);
|
||||
case auth_md5:
|
||||
return auth_md5_cal(data, output, len);
|
||||
case auth_simple:
|
||||
return auth_simple_cal(data, output, len);
|
||||
case auth_none:
|
||||
return auth_none_cal(data, output, len);
|
||||
case auth_hmac_sha1:
|
||||
return auth_hmac_sha1_cal(data, output, len);
|
||||
// default: return auth_md5_cal(data,output,len);//default;
|
||||
default:
|
||||
assert(0 == 1);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
int my_decrypt_pesudo_header(uint8_t *data,uint8_t *output,int &len,uint8_t * key,uint8_t *header,int hlen)
|
||||
{
|
||||
return 0;
|
||||
int auth_verify(const char *data, int &len) {
|
||||
mylog(log_trace, "auth:%d\n", auth_mode);
|
||||
switch (auth_mode) {
|
||||
case auth_crc32:
|
||||
return auth_crc32_verify(data, len);
|
||||
case auth_md5:
|
||||
return auth_md5_verify(data, len);
|
||||
case auth_simple:
|
||||
return auth_simple_verify(data, len);
|
||||
case auth_none:
|
||||
return auth_none_verify(data, len);
|
||||
case auth_hmac_sha1:
|
||||
return auth_hmac_sha1_verify(data, len);
|
||||
// default: return auth_md5_verify(data,len);//default
|
||||
default:
|
||||
assert(0 == 1);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
int cipher_encrypt(const char *data, char *output, int &len, char *key) {
|
||||
mylog(log_trace, "cipher:%d\n", cipher_mode);
|
||||
switch (cipher_mode) {
|
||||
case cipher_aes128cbc:
|
||||
return cipher_aes128cbc_encrypt(data, output, len, key);
|
||||
case cipher_aes128cfb:
|
||||
return cipher_aes128cfb_encrypt(data, output, len, key);
|
||||
case cipher_xor:
|
||||
return cipher_xor_encrypt(data, output, len, key);
|
||||
case cipher_none:
|
||||
return cipher_none_encrypt(data, output, len, key);
|
||||
// default:return cipher_aes128cbc_encrypt(data,output,len, key);
|
||||
default:
|
||||
assert(0 == 1);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
int cipher_decrypt(const char *data, char *output, int &len, char *key) {
|
||||
mylog(log_trace, "cipher:%d\n", cipher_mode);
|
||||
switch (cipher_mode) {
|
||||
case cipher_aes128cbc:
|
||||
return cipher_aes128cbc_decrypt(data, output, len, key);
|
||||
case cipher_aes128cfb:
|
||||
return cipher_aes128cfb_decrypt(data, output, len, key);
|
||||
case cipher_xor:
|
||||
return cipher_xor_decrypt(data, output, len, key);
|
||||
case cipher_none:
|
||||
return cipher_none_decrypt(data, output, len, key);
|
||||
// default: return cipher_aes128cbc_decrypt(data,output,len,key);
|
||||
default:
|
||||
assert(0 == 1);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int encrypt_AE(const char *data, char *output, int &len /*,char * key*/) {
|
||||
mylog(log_trace, "encrypt_AE is called\n");
|
||||
char buf[buf_len];
|
||||
char buf2[buf_len];
|
||||
memcpy(buf, data, len);
|
||||
if (cipher_encrypt(buf, buf2, len, (char *)cipher_key_encrypt) != 0) {
|
||||
mylog(log_debug, "cipher_encrypt failed ");
|
||||
return -1;
|
||||
}
|
||||
if (auth_cal(buf2, output, len) != 0) {
|
||||
mylog(log_debug, "auth_cal failed ");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// printf("%d %x %x\n",len,(int)(output[0]),(int)(output[1]));
|
||||
// print_binary_chars(output,len);
|
||||
|
||||
// use encrypt-then-MAC scheme
|
||||
return 0;
|
||||
}
|
||||
|
||||
int decrypt_AE(const char *data, char *output, int &len /*,char * key*/) {
|
||||
mylog(log_trace, "decrypt_AE is called\n");
|
||||
// printf("%d %x %x\n",len,(int)(data[0]),(int)(data[1]));
|
||||
// print_binary_chars(data,len);
|
||||
|
||||
if (auth_verify(data, len) != 0) {
|
||||
mylog(log_debug, "auth_verify failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (cipher_decrypt(data, output, len, (char *)cipher_key_decrypt) != 0) {
|
||||
mylog(log_debug, "cipher_decrypt failed \n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int my_encrypt(const char *data, char *output, int &len /*,char * key*/) {
|
||||
if (len < 0) {
|
||||
mylog(log_trace, "len<0");
|
||||
return -1;
|
||||
}
|
||||
if (len > max_data_len) {
|
||||
mylog(log_warn, "len>max_data_len");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (is_hmac_used)
|
||||
return encrypt_AE(data, output, len);
|
||||
|
||||
char buf[buf_len];
|
||||
char buf2[buf_len];
|
||||
memcpy(buf, data, len);
|
||||
if (auth_cal(buf, buf2, len) != 0) {
|
||||
mylog(log_debug, "auth_cal failed ");
|
||||
return -1;
|
||||
}
|
||||
if (cipher_encrypt(buf2, output, len, normal_key) != 0) {
|
||||
mylog(log_debug, "cipher_encrypt failed ");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int my_decrypt(const char *data, char *output, int &len /*,char * key*/) {
|
||||
if (len < 0) return -1;
|
||||
if (len > max_data_len) {
|
||||
mylog(log_warn, "len>max_data_len");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (is_hmac_used)
|
||||
return decrypt_AE(data, output, len);
|
||||
|
||||
if (cipher_decrypt(data, output, len, normal_key) != 0) {
|
||||
mylog(log_debug, "cipher_decrypt failed \n");
|
||||
return -1;
|
||||
}
|
||||
if (auth_verify(output, len) != 0) {
|
||||
mylog(log_debug, "auth_verify failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int encrypt_AEAD(uint8_t *data, uint8_t *output, int &len, uint8_t *key, uint8_t *header, int hlen) {
|
||||
// TODO
|
||||
return -1;
|
||||
}
|
||||
|
||||
int decrypt_AEAD(uint8_t *data, uint8_t *output, int &len, uint8_t *key, uint8_t *header, int hlen) {
|
||||
// TODO
|
||||
return -1;
|
||||
}
|
||||
|
52
encrypt.h
Executable file → Normal file
@ -1,39 +1,51 @@
|
||||
#ifndef _ENCRYPTION_H_
|
||||
#define _ENCRYPTION_H_
|
||||
|
||||
|
||||
#ifndef UDP2RAW_ENCRYPTION_H_
|
||||
#define UDP2RAW_ENCRYPTION_H_
|
||||
|
||||
//#include "aes.h"
|
||||
//#include "md5.h"
|
||||
#include "common.h"
|
||||
|
||||
// using namespace std;
|
||||
// extern char key[16];
|
||||
|
||||
//using namespace std;
|
||||
const int aes_key_optimize = 1; // if enabled,once you used a key for aes,you cant change it anymore
|
||||
extern int aes128cfb_old;
|
||||
|
||||
int my_encrypt(const char *data,char *output,int &len,char * key);
|
||||
int my_decrypt(const char *data,char *output,int &len,char * key);
|
||||
int my_init_keys(const char *, int);
|
||||
|
||||
int my_encrypt_pesudo_header(uint8_t *data,uint8_t *output,int &len,uint8_t * key,uint8_t *header,int hlen);
|
||||
int my_decrypt_pesudo_header(uint8_t *data,uint8_t *output,int &len,uint8_t * key,uint8_t *header,int hlen);
|
||||
int my_encrypt(const char *data, char *output, int &len);
|
||||
int my_decrypt(const char *data, char *output, int &len);
|
||||
|
||||
unsigned short csum(const unsigned short *ptr, int nbytes);
|
||||
|
||||
unsigned short csum(const unsigned short *ptr,int nbytes) ;
|
||||
|
||||
|
||||
enum auth_mode_t {auth_none=0,auth_md5,auth_crc32,auth_simple,auth_end};
|
||||
|
||||
|
||||
enum cipher_mode_t {cipher_none=0,cipher_aes128cbc,cipher_xor,cipher_end};
|
||||
enum auth_mode_t { auth_none = 0,
|
||||
auth_md5,
|
||||
auth_crc32,
|
||||
auth_simple,
|
||||
auth_hmac_sha1,
|
||||
auth_end };
|
||||
|
||||
enum cipher_mode_t { cipher_none = 0,
|
||||
cipher_aes128cbc,
|
||||
cipher_xor,
|
||||
cipher_aes128cfb,
|
||||
cipher_end };
|
||||
|
||||
extern auth_mode_t auth_mode;
|
||||
extern cipher_mode_t cipher_mode;
|
||||
|
||||
struct a
|
||||
{
|
||||
char * buf[buf_len];
|
||||
};
|
||||
extern unordered_map<int, const char *> auth_mode_tostring;
|
||||
extern unordered_map<int, const char *> cipher_mode_tostring;
|
||||
|
||||
extern char gro_xor[256 + 100];
|
||||
|
||||
int cipher_decrypt(const char *data, char *output, int &len, char *key); // internal interface ,exposed for test only
|
||||
int cipher_encrypt(const char *data, char *output, int &len, char *key); // internal interface ,exposed for test only
|
||||
|
||||
void aes_ecb_encrypt(const char *data, char *output);
|
||||
void aes_ecb_decrypt(const char *data, char *output);
|
||||
|
||||
void aes_ecb_encrypt1(char *data);
|
||||
void aes_ecb_decrypt1(char *data);
|
||||
|
||||
#endif
|
||||
|
16
example.conf
Normal file
@ -0,0 +1,16 @@
|
||||
# Basically this file is the equivalent to splitting the command line options into multiple lines
|
||||
# Each line should contain an option
|
||||
|
||||
# This is client
|
||||
-c
|
||||
# Or use -s if you use it on server side
|
||||
# Define local address
|
||||
-l 127.0.0.1:56789
|
||||
# Define remote address
|
||||
-r 45.66.77.88:45678
|
||||
# Password
|
||||
-k my_awesome_password
|
||||
# Mode
|
||||
--raw-mode faketcp
|
||||
# Log Level
|
||||
--log-level 4
|
53
fd_manager.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* fd_manager.cpp
|
||||
*
|
||||
* Created on: Sep 25, 2017
|
||||
* Author: root
|
||||
*/
|
||||
|
||||
#include "fd_manager.h"
|
||||
int fd_manager_t::fd_exist(int fd) {
|
||||
return fd_to_fd64_mp.find(fd) != fd_to_fd64_mp.end();
|
||||
}
|
||||
int fd_manager_t::exist(fd64_t fd64) {
|
||||
return fd64_to_fd_mp.find(fd64) != fd64_to_fd_mp.end();
|
||||
}
|
||||
int fd_manager_t::to_fd(fd64_t fd64) {
|
||||
assert(exist(fd64));
|
||||
return fd64_to_fd_mp[fd64];
|
||||
}
|
||||
void fd_manager_t::fd64_close(fd64_t fd64) {
|
||||
assert(exist(fd64));
|
||||
int fd = fd64_to_fd_mp[fd64];
|
||||
fd64_to_fd_mp.erase(fd64);
|
||||
fd_to_fd64_mp.erase(fd);
|
||||
if (exist_info(fd64)) {
|
||||
fd_info_mp.erase(fd64);
|
||||
}
|
||||
// assert(close(fd)==0);
|
||||
sock_close(fd);
|
||||
}
|
||||
void fd_manager_t::reserve(int n) {
|
||||
fd_to_fd64_mp.reserve(n);
|
||||
fd64_to_fd_mp.reserve(n);
|
||||
fd_info_mp.reserve(n);
|
||||
}
|
||||
u64_t fd_manager_t::create(int fd) {
|
||||
assert(!fd_exist(fd));
|
||||
fd64_t fd64 = counter++;
|
||||
fd_to_fd64_mp[fd] = fd64;
|
||||
fd64_to_fd_mp[fd64] = fd;
|
||||
return fd64;
|
||||
}
|
||||
fd_manager_t::fd_manager_t() {
|
||||
counter = u32_t(-1);
|
||||
counter += 100;
|
||||
reserve(10007);
|
||||
}
|
||||
fd_info_t& fd_manager_t::get_info(fd64_t fd64) {
|
||||
assert(exist(fd64));
|
||||
return fd_info_mp[fd64];
|
||||
}
|
||||
int fd_manager_t::exist_info(fd64_t fd64) {
|
||||
return fd_info_mp.find(fd64) != fd_info_mp.end();
|
||||
}
|
43
fd_manager.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* fd_manager.h
|
||||
*
|
||||
* Created on: Sep 25, 2017
|
||||
* Author: root
|
||||
*/
|
||||
|
||||
#ifndef FD_MANAGER_H_
|
||||
#define FD_MANAGER_H_
|
||||
|
||||
#include "common.h"
|
||||
//#include "packet.h"
|
||||
#include "connection.h"
|
||||
|
||||
struct fd_info_t {
|
||||
// ip_port_t ip_port;
|
||||
conn_info_t *p_conn_info;
|
||||
};
|
||||
|
||||
struct fd_manager_t // conver fd to a uniq 64bit number,avoid fd value conflict caused by close and re-create
|
||||
// this class is not strictly necessary,it just makes epoll fd handling easier
|
||||
{
|
||||
fd_info_t &get_info(fd64_t fd64);
|
||||
int exist_info(fd64_t);
|
||||
int exist(fd64_t fd64);
|
||||
int to_fd(fd64_t);
|
||||
void fd64_close(fd64_t fd64);
|
||||
void reserve(int n);
|
||||
u64_t create(int fd);
|
||||
fd_manager_t();
|
||||
|
||||
private:
|
||||
u64_t counter;
|
||||
unordered_map<int, fd64_t> fd_to_fd64_mp;
|
||||
unordered_map<fd64_t, int> fd64_to_fd_mp;
|
||||
unordered_map<fd64_t, fd_info_t> fd_info_mp;
|
||||
int fd_exist(int fd);
|
||||
// void remove_fd(int fd);
|
||||
// fd64_t fd_to_fd64(int fd);
|
||||
};
|
||||
|
||||
extern fd_manager_t fd_manager;
|
||||
#endif /* FD_MANAGER_H_ */
|
BIN
images/android.png
Normal file
After Width: | Height: | Size: 366 KiB |
BIN
images/image0.PNG
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
images/image1.PNG
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
images/image2.PNG
Normal file
After Width: | Height: | Size: 37 KiB |
BIN
images/image4.PNG
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
images/image5.PNG
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
images/lower_level.PNG
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
images/openvpn.PNG
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
images/output_client.PNG
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
images/output_server.PNG
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
images/route.PNG
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
images/speed_test.PNG
Normal file
After Width: | Height: | Size: 20 KiB |
1
images/speedtest/111
Normal file
@ -0,0 +1 @@
|
||||
|
BIN
images/speedtest/Capture.PNG
Normal file
After Width: | Height: | Size: 9.0 KiB |
BIN
images/speedtest/Capture2.PNG
Normal file
After Width: | Height: | Size: 8.1 KiB |
BIN
images/udp2rawopenvpn.PNG
Normal file
After Width: | Height: | Size: 58 KiB |
1
images/wiki/111
Normal file
@ -0,0 +1 @@
|
||||
|
BIN
images/wiki/mac_nat_vb1.PNG
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
images/wiki/mac_nat_vb2.PNG
Normal file
After Width: | Height: | Size: 70 KiB |
BIN
images/wiki/mac_nat_vb3.PNG
Normal file
After Width: | Height: | Size: 68 KiB |
BIN
images/wiki/mac_nat_vb4.PNG
Normal file
After Width: | Height: | Size: 75 KiB |
BIN
images/wiki/windows_nat.PNG
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
images/wiki/windows_nat_vb1.PNG
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
images/wiki/windows_nat_vb2.PNG
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
images/wiki/windows_nat_vm1.PNG
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
images/wiki/windows_nat_vm2.PNG
Normal file
After Width: | Height: | Size: 29 KiB |
18
lib/aes-common.h
Executable file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* this file comes from https://github.com/kokke/tiny-AES128-C
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
void AES_ECB_encrypt_buffer(const uint8_t* input, const uint8_t* key, uint8_t *output);
|
||||
void AES_ECB_decrypt_buffer(const uint8_t* input, const uint8_t* key, uint8_t *output);
|
||||
|
||||
void AES_CBC_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv);
|
||||
void AES_CBC_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv);
|
||||
|
||||
|
||||
void AES_CFB_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv);
|
||||
void AES_CFB_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv);
|
600
lib/aes.c
@ -1,600 +0,0 @@
|
||||
|
||||
/*
|
||||
* this file comes from https://github.com/kokke/tiny-AES128-C
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
This is an implementation of the AES algorithm, specifically ECB and CBC mode.
|
||||
Block size can be chosen in aes.h - available choices are AES128, AES192, AES256.
|
||||
|
||||
The implementation is verified against the test vectors in:
|
||||
National Institute of Standards and Technology Special Publication 800-38A 2001 ED
|
||||
|
||||
ECB-AES128
|
||||
----------
|
||||
|
||||
plain-text:
|
||||
6bc1bee22e409f96e93d7e117393172a
|
||||
ae2d8a571e03ac9c9eb76fac45af8e51
|
||||
30c81c46a35ce411e5fbc1191a0a52ef
|
||||
f69f2445df4f9b17ad2b417be66c3710
|
||||
|
||||
key:
|
||||
2b7e151628aed2a6abf7158809cf4f3c
|
||||
|
||||
resulting cipher
|
||||
3ad77bb40d7a3660a89ecaf32466ef97
|
||||
f5d3d58503b9699de785895a96fdbaaf
|
||||
43b1cd7f598ece23881b00e3ed030688
|
||||
7b0c785e27e8ad3f8223207104725dd4
|
||||
|
||||
|
||||
NOTE: String length must be evenly divisible by 16byte (str_len % 16 == 0)
|
||||
You should pad the end of the string with zeros if this is not the case.
|
||||
For AES192/256 the block size is proportionally larger.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Includes: */
|
||||
/*****************************************************************************/
|
||||
#include <stdint.h>
|
||||
#include <string.h> // CBC mode, for memset
|
||||
#include "aes.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Defines: */
|
||||
/*****************************************************************************/
|
||||
// The number of columns comprising a state in AES. This is a constant in AES. Value=4
|
||||
#define Nb 4
|
||||
#define BLOCKLEN 16 //Block length in bytes AES is 128b block only
|
||||
|
||||
#if defined(AES256) && (AES256 == 1)
|
||||
#define Nk 8
|
||||
#define KEYLEN 32
|
||||
#define Nr 14
|
||||
#define keyExpSize 240
|
||||
#elif defined(AES192) && (AES192 == 1)
|
||||
#define Nk 6
|
||||
#define KEYLEN 24
|
||||
#define Nr 12
|
||||
#define keyExpSize 208
|
||||
#else
|
||||
#define Nk 4 // The number of 32 bit words in a key.
|
||||
#define KEYLEN 16 // Key length in bytes
|
||||
#define Nr 10 // The number of rounds in AES Cipher.
|
||||
#define keyExpSize 176
|
||||
#endif
|
||||
|
||||
// jcallan@github points out that declaring Multiply as a function
|
||||
// reduces code size considerably with the Keil ARM compiler.
|
||||
// See this link for more information: https://github.com/kokke/tiny-AES128-C/pull/3
|
||||
#ifndef MULTIPLY_AS_A_FUNCTION
|
||||
#define MULTIPLY_AS_A_FUNCTION 0
|
||||
#endif
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Private variables: */
|
||||
/*****************************************************************************/
|
||||
// state - array holding the intermediate results during decryption.
|
||||
typedef uint8_t state_t[4][4];
|
||||
static state_t* state;
|
||||
|
||||
// The array that stores the round keys.
|
||||
static uint8_t RoundKey[keyExpSize];
|
||||
|
||||
// The Key input to the AES Program
|
||||
static const uint8_t* Key;
|
||||
|
||||
#if defined(CBC) && CBC
|
||||
// Initial Vector used only for CBC mode
|
||||
static uint8_t* Iv;
|
||||
#endif
|
||||
|
||||
// The lookup-tables are marked const so they can be placed in read-only storage instead of RAM
|
||||
// The numbers below can be computed dynamically trading ROM for RAM -
|
||||
// This can be useful in (embedded) bootloader applications, where ROM is often limited.
|
||||
static const uint8_t sbox[256] = {
|
||||
//0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
|
||||
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
|
||||
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
|
||||
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
|
||||
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
|
||||
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
|
||||
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
|
||||
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
|
||||
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
|
||||
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
|
||||
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
|
||||
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
|
||||
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
|
||||
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
|
||||
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 };
|
||||
|
||||
static const uint8_t rsbox[256] = {
|
||||
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
|
||||
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
|
||||
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
|
||||
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
|
||||
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
|
||||
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
|
||||
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
|
||||
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
|
||||
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
|
||||
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
|
||||
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
|
||||
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
|
||||
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
|
||||
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
|
||||
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
|
||||
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d };
|
||||
|
||||
// The round constant word array, Rcon[i], contains the values given by
|
||||
// x to th e power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8)
|
||||
static const uint8_t Rcon[11] = {
|
||||
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 };
|
||||
|
||||
/*
|
||||
* Jordan Goulder points out in PR #12 (https://github.com/kokke/tiny-AES128-C/pull/12),
|
||||
* that you can remove most of the elements in the Rcon array, because they are unused.
|
||||
*
|
||||
* From Wikipedia's article on the Rijndael key schedule @ https://en.wikipedia.org/wiki/Rijndael_key_schedule#Rcon
|
||||
*
|
||||
* "Only the first some of these constants are actually used – up to rcon[10] for AES-128 (as 11 round keys are needed),
|
||||
* up to rcon[8] for AES-192, up to rcon[7] for AES-256. rcon[0] is not used in AES algorithm."
|
||||
*
|
||||
* ... which is why the full array below has been 'disabled' below.
|
||||
*/
|
||||
#if 0
|
||||
static const uint8_t Rcon[256] = {
|
||||
0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
|
||||
0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39,
|
||||
0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a,
|
||||
0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8,
|
||||
0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef,
|
||||
0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc,
|
||||
0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b,
|
||||
0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3,
|
||||
0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94,
|
||||
0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20,
|
||||
0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35,
|
||||
0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f,
|
||||
0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04,
|
||||
0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63,
|
||||
0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd,
|
||||
0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d };
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Private functions: */
|
||||
/*****************************************************************************/
|
||||
static uint8_t getSBoxValue(uint8_t num)
|
||||
{
|
||||
return sbox[num];
|
||||
}
|
||||
|
||||
static uint8_t getSBoxInvert(uint8_t num)
|
||||
{
|
||||
return rsbox[num];
|
||||
}
|
||||
|
||||
// This function produces Nb(Nr+1) round keys. The round keys are used in each round to decrypt the states.
|
||||
static void KeyExpansion(void)
|
||||
{
|
||||
uint32_t i, k;
|
||||
uint8_t tempa[4]; // Used for the column/row operations
|
||||
|
||||
// The first round key is the key itself.
|
||||
for (i = 0; i < Nk; ++i)
|
||||
{
|
||||
RoundKey[(i * 4) + 0] = Key[(i * 4) + 0];
|
||||
RoundKey[(i * 4) + 1] = Key[(i * 4) + 1];
|
||||
RoundKey[(i * 4) + 2] = Key[(i * 4) + 2];
|
||||
RoundKey[(i * 4) + 3] = Key[(i * 4) + 3];
|
||||
}
|
||||
|
||||
// All other round keys are found from the previous round keys.
|
||||
//i == Nk
|
||||
for (; i < Nb * (Nr + 1); ++i)
|
||||
{
|
||||
{
|
||||
tempa[0]=RoundKey[(i-1) * 4 + 0];
|
||||
tempa[1]=RoundKey[(i-1) * 4 + 1];
|
||||
tempa[2]=RoundKey[(i-1) * 4 + 2];
|
||||
tempa[3]=RoundKey[(i-1) * 4 + 3];
|
||||
}
|
||||
|
||||
if (i % Nk == 0)
|
||||
{
|
||||
// This function shifts the 4 bytes in a word to the left once.
|
||||
// [a0,a1,a2,a3] becomes [a1,a2,a3,a0]
|
||||
|
||||
// Function RotWord()
|
||||
{
|
||||
k = tempa[0];
|
||||
tempa[0] = tempa[1];
|
||||
tempa[1] = tempa[2];
|
||||
tempa[2] = tempa[3];
|
||||
tempa[3] = k;
|
||||
}
|
||||
|
||||
// SubWord() is a function that takes a four-byte input word and
|
||||
// applies the S-box to each of the four bytes to produce an output word.
|
||||
|
||||
// Function Subword()
|
||||
{
|
||||
tempa[0] = getSBoxValue(tempa[0]);
|
||||
tempa[1] = getSBoxValue(tempa[1]);
|
||||
tempa[2] = getSBoxValue(tempa[2]);
|
||||
tempa[3] = getSBoxValue(tempa[3]);
|
||||
}
|
||||
|
||||
tempa[0] = tempa[0] ^ Rcon[i/Nk];
|
||||
}
|
||||
#if defined(AES256) && (AES256 == 1)
|
||||
if (i % Nk == 4)
|
||||
{
|
||||
// Function Subword()
|
||||
{
|
||||
tempa[0] = getSBoxValue(tempa[0]);
|
||||
tempa[1] = getSBoxValue(tempa[1]);
|
||||
tempa[2] = getSBoxValue(tempa[2]);
|
||||
tempa[3] = getSBoxValue(tempa[3]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
RoundKey[i * 4 + 0] = RoundKey[(i - Nk) * 4 + 0] ^ tempa[0];
|
||||
RoundKey[i * 4 + 1] = RoundKey[(i - Nk) * 4 + 1] ^ tempa[1];
|
||||
RoundKey[i * 4 + 2] = RoundKey[(i - Nk) * 4 + 2] ^ tempa[2];
|
||||
RoundKey[i * 4 + 3] = RoundKey[(i - Nk) * 4 + 3] ^ tempa[3];
|
||||
}
|
||||
}
|
||||
|
||||
// This function adds the round key to state.
|
||||
// The round key is added to the state by an XOR function.
|
||||
static void AddRoundKey(uint8_t round)
|
||||
{
|
||||
uint8_t i,j;
|
||||
for (i=0;i<4;++i)
|
||||
{
|
||||
for (j = 0; j < 4; ++j)
|
||||
{
|
||||
(*state)[i][j] ^= RoundKey[round * Nb * 4 + i * Nb + j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The SubBytes Function Substitutes the values in the
|
||||
// state matrix with values in an S-box.
|
||||
static void SubBytes(void)
|
||||
{
|
||||
uint8_t i, j;
|
||||
for (i = 0; i < 4; ++i)
|
||||
{
|
||||
for (j = 0; j < 4; ++j)
|
||||
{
|
||||
(*state)[j][i] = getSBoxValue((*state)[j][i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The ShiftRows() function shifts the rows in the state to the left.
|
||||
// Each row is shifted with different offset.
|
||||
// Offset = Row number. So the first row is not shifted.
|
||||
static void ShiftRows(void)
|
||||
{
|
||||
uint8_t temp;
|
||||
|
||||
// Rotate first row 1 columns to left
|
||||
temp = (*state)[0][1];
|
||||
(*state)[0][1] = (*state)[1][1];
|
||||
(*state)[1][1] = (*state)[2][1];
|
||||
(*state)[2][1] = (*state)[3][1];
|
||||
(*state)[3][1] = temp;
|
||||
|
||||
// Rotate second row 2 columns to left
|
||||
temp = (*state)[0][2];
|
||||
(*state)[0][2] = (*state)[2][2];
|
||||
(*state)[2][2] = temp;
|
||||
|
||||
temp = (*state)[1][2];
|
||||
(*state)[1][2] = (*state)[3][2];
|
||||
(*state)[3][2] = temp;
|
||||
|
||||
// Rotate third row 3 columns to left
|
||||
temp = (*state)[0][3];
|
||||
(*state)[0][3] = (*state)[3][3];
|
||||
(*state)[3][3] = (*state)[2][3];
|
||||
(*state)[2][3] = (*state)[1][3];
|
||||
(*state)[1][3] = temp;
|
||||
}
|
||||
|
||||
static uint8_t xtime(uint8_t x)
|
||||
{
|
||||
return ((x<<1) ^ (((x>>7) & 1) * 0x1b));
|
||||
}
|
||||
|
||||
// MixColumns function mixes the columns of the state matrix
|
||||
static void MixColumns(void)
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t Tmp,Tm,t;
|
||||
for (i = 0; i < 4; ++i)
|
||||
{
|
||||
t = (*state)[i][0];
|
||||
Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3] ;
|
||||
Tm = (*state)[i][0] ^ (*state)[i][1] ; Tm = xtime(Tm); (*state)[i][0] ^= Tm ^ Tmp ;
|
||||
Tm = (*state)[i][1] ^ (*state)[i][2] ; Tm = xtime(Tm); (*state)[i][1] ^= Tm ^ Tmp ;
|
||||
Tm = (*state)[i][2] ^ (*state)[i][3] ; Tm = xtime(Tm); (*state)[i][2] ^= Tm ^ Tmp ;
|
||||
Tm = (*state)[i][3] ^ t ; Tm = xtime(Tm); (*state)[i][3] ^= Tm ^ Tmp ;
|
||||
}
|
||||
}
|
||||
|
||||
// Multiply is used to multiply numbers in the field GF(2^8)
|
||||
#if MULTIPLY_AS_A_FUNCTION
|
||||
static uint8_t Multiply(uint8_t x, uint8_t y)
|
||||
{
|
||||
return (((y & 1) * x) ^
|
||||
((y>>1 & 1) * xtime(x)) ^
|
||||
((y>>2 & 1) * xtime(xtime(x))) ^
|
||||
((y>>3 & 1) * xtime(xtime(xtime(x)))) ^
|
||||
((y>>4 & 1) * xtime(xtime(xtime(xtime(x))))));
|
||||
}
|
||||
#else
|
||||
#define Multiply(x, y) \
|
||||
( ((y & 1) * x) ^ \
|
||||
((y>>1 & 1) * xtime(x)) ^ \
|
||||
((y>>2 & 1) * xtime(xtime(x))) ^ \
|
||||
((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ \
|
||||
((y>>4 & 1) * xtime(xtime(xtime(xtime(x)))))) \
|
||||
|
||||
#endif
|
||||
|
||||
// MixColumns function mixes the columns of the state matrix.
|
||||
// The method used to multiply may be difficult to understand for the inexperienced.
|
||||
// Please use the references to gain more information.
|
||||
static void InvMixColumns(void)
|
||||
{
|
||||
int i;
|
||||
uint8_t a, b, c, d;
|
||||
for (i = 0; i < 4; ++i)
|
||||
{
|
||||
a = (*state)[i][0];
|
||||
b = (*state)[i][1];
|
||||
c = (*state)[i][2];
|
||||
d = (*state)[i][3];
|
||||
|
||||
(*state)[i][0] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09);
|
||||
(*state)[i][1] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d);
|
||||
(*state)[i][2] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b);
|
||||
(*state)[i][3] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// The SubBytes Function Substitutes the values in the
|
||||
// state matrix with values in an S-box.
|
||||
static void InvSubBytes(void)
|
||||
{
|
||||
uint8_t i,j;
|
||||
for (i = 0; i < 4; ++i)
|
||||
{
|
||||
for (j = 0; j < 4; ++j)
|
||||
{
|
||||
(*state)[j][i] = getSBoxInvert((*state)[j][i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void InvShiftRows(void)
|
||||
{
|
||||
uint8_t temp;
|
||||
|
||||
// Rotate first row 1 columns to right
|
||||
temp = (*state)[3][1];
|
||||
(*state)[3][1] = (*state)[2][1];
|
||||
(*state)[2][1] = (*state)[1][1];
|
||||
(*state)[1][1] = (*state)[0][1];
|
||||
(*state)[0][1] = temp;
|
||||
|
||||
// Rotate second row 2 columns to right
|
||||
temp = (*state)[0][2];
|
||||
(*state)[0][2] = (*state)[2][2];
|
||||
(*state)[2][2] = temp;
|
||||
|
||||
temp = (*state)[1][2];
|
||||
(*state)[1][2] = (*state)[3][2];
|
||||
(*state)[3][2] = temp;
|
||||
|
||||
// Rotate third row 3 columns to right
|
||||
temp = (*state)[0][3];
|
||||
(*state)[0][3] = (*state)[1][3];
|
||||
(*state)[1][3] = (*state)[2][3];
|
||||
(*state)[2][3] = (*state)[3][3];
|
||||
(*state)[3][3] = temp;
|
||||
}
|
||||
|
||||
|
||||
// Cipher is the main function that encrypts the PlainText.
|
||||
static void Cipher(void)
|
||||
{
|
||||
uint8_t round = 0;
|
||||
|
||||
// Add the First round key to the state before starting the rounds.
|
||||
AddRoundKey(0);
|
||||
|
||||
// There will be Nr rounds.
|
||||
// The first Nr-1 rounds are identical.
|
||||
// These Nr-1 rounds are executed in the loop below.
|
||||
for (round = 1; round < Nr; ++round)
|
||||
{
|
||||
SubBytes();
|
||||
ShiftRows();
|
||||
MixColumns();
|
||||
AddRoundKey(round);
|
||||
}
|
||||
|
||||
// The last round is given below.
|
||||
// The MixColumns function is not here in the last round.
|
||||
SubBytes();
|
||||
ShiftRows();
|
||||
AddRoundKey(Nr);
|
||||
}
|
||||
|
||||
static void InvCipher(void)
|
||||
{
|
||||
uint8_t round=0;
|
||||
|
||||
// Add the First round key to the state before starting the rounds.
|
||||
AddRoundKey(Nr);
|
||||
|
||||
// There will be Nr rounds.
|
||||
// The first Nr-1 rounds are identical.
|
||||
// These Nr-1 rounds are executed in the loop below.
|
||||
for (round = (Nr - 1); round > 0; --round)
|
||||
{
|
||||
InvShiftRows();
|
||||
InvSubBytes();
|
||||
AddRoundKey(round);
|
||||
InvMixColumns();
|
||||
}
|
||||
|
||||
// The last round is given below.
|
||||
// The MixColumns function is not here in the last round.
|
||||
InvShiftRows();
|
||||
InvSubBytes();
|
||||
AddRoundKey(0);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Public functions: */
|
||||
/*****************************************************************************/
|
||||
#if defined(ECB) && (ECB == 1)
|
||||
|
||||
|
||||
void AES_ECB_encrypt(const uint8_t* input, const uint8_t* key, uint8_t* output, const uint32_t length)
|
||||
{
|
||||
// Copy input to output, and work in-memory on output
|
||||
memcpy(output, input, length);
|
||||
state = (state_t*)output;
|
||||
|
||||
Key = key;
|
||||
KeyExpansion();
|
||||
|
||||
// The next function call encrypts the PlainText with the Key using AES algorithm.
|
||||
Cipher();
|
||||
}
|
||||
|
||||
void AES_ECB_decrypt(const uint8_t* input, const uint8_t* key, uint8_t *output, const uint32_t length)
|
||||
{
|
||||
// Copy input to output, and work in-memory on output
|
||||
memcpy(output, input, length);
|
||||
state = (state_t*)output;
|
||||
|
||||
// The KeyExpansion routine must be called before encryption.
|
||||
Key = key;
|
||||
KeyExpansion();
|
||||
|
||||
InvCipher();
|
||||
}
|
||||
|
||||
|
||||
#endif // #if defined(ECB) && (ECB == 1)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#if defined(CBC) && (CBC == 1)
|
||||
|
||||
|
||||
static void XorWithIv(uint8_t* buf)
|
||||
{
|
||||
uint8_t i;
|
||||
for (i = 0; i < BLOCKLEN; ++i) //WAS for(i = 0; i < KEYLEN; ++i) but the block in AES is always 128bit so 16 bytes!
|
||||
{
|
||||
buf[i] ^= Iv[i];
|
||||
}
|
||||
}
|
||||
|
||||
void AES_CBC_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)
|
||||
{
|
||||
uintptr_t i;
|
||||
uint8_t extra = length % BLOCKLEN; /* Remaining bytes in the last non-full block */
|
||||
|
||||
// Skip the key expansion if key is passed as 0
|
||||
if (0 != key)
|
||||
{
|
||||
Key = key;
|
||||
KeyExpansion();
|
||||
}
|
||||
|
||||
if (iv != 0)
|
||||
{
|
||||
Iv = (uint8_t*)iv;
|
||||
}
|
||||
|
||||
for (i = 0; i < length; i += BLOCKLEN)
|
||||
{
|
||||
XorWithIv(input);
|
||||
memcpy(output, input, BLOCKLEN);
|
||||
state = (state_t*)output;
|
||||
Cipher();
|
||||
Iv = output;
|
||||
input += BLOCKLEN;
|
||||
output += BLOCKLEN;
|
||||
//printf("Step %d - %d", i/16, i);
|
||||
}
|
||||
|
||||
if (extra)
|
||||
{
|
||||
memcpy(output, input, extra);
|
||||
state = (state_t*)output;
|
||||
Cipher();
|
||||
}
|
||||
}
|
||||
|
||||
void AES_CBC_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)
|
||||
{
|
||||
uintptr_t i;
|
||||
uint8_t extra = length % BLOCKLEN; /* Remaining bytes in the last non-full block */
|
||||
|
||||
// Skip the key expansion if key is passed as 0
|
||||
if (0 != key)
|
||||
{
|
||||
Key = key;
|
||||
KeyExpansion();
|
||||
}
|
||||
|
||||
// If iv is passed as 0, we continue to encrypt without re-setting the Iv
|
||||
if (iv != 0)
|
||||
{
|
||||
Iv = (uint8_t*)iv;
|
||||
}
|
||||
|
||||
for (i = 0; i < length; i += BLOCKLEN)
|
||||
{
|
||||
memcpy(output, input, BLOCKLEN);
|
||||
state = (state_t*)output;
|
||||
InvCipher();
|
||||
XorWithIv(output);
|
||||
Iv = input;
|
||||
input += BLOCKLEN;
|
||||
output += BLOCKLEN;
|
||||
}
|
||||
|
||||
if (extra)
|
||||
{
|
||||
memcpy(output, input, extra);
|
||||
state = (state_t*)output;
|
||||
InvCipher();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // #if defined(CBC) && (CBC == 1)
|
45
lib/aes.h
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* this file comes from https://github.com/kokke/tiny-AES128-C
|
||||
*/
|
||||
|
||||
#ifndef _AES_H_
|
||||
#define _AES_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
// #define the macros below to 1/0 to enable/disable the mode of operation.
|
||||
//
|
||||
// CBC enables AES encryption in CBC-mode of operation.
|
||||
// ECB enables the basic ECB 16-byte block algorithm. Both can be enabled simultaneously.
|
||||
|
||||
// The #ifndef-guard allows it to be configured before #include'ing or at compile time.
|
||||
#ifndef CBC
|
||||
#define CBC 1
|
||||
#endif
|
||||
|
||||
#ifndef ECB
|
||||
#define ECB 1
|
||||
#endif
|
||||
|
||||
#define AES128 1
|
||||
//#define AES192 1
|
||||
//#define AES256 1
|
||||
|
||||
#if defined(ECB) && (ECB == 1)
|
||||
|
||||
void AES_ECB_encrypt(const uint8_t* input, const uint8_t* key, uint8_t *output, const uint32_t length);
|
||||
void AES_ECB_decrypt(const uint8_t* input, const uint8_t* key, uint8_t *output, const uint32_t length);
|
||||
|
||||
#endif // #if defined(ECB) && (ECB == !)
|
||||
|
||||
|
||||
#if defined(CBC) && (CBC == 1)
|
||||
|
||||
void AES_CBC_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv);
|
||||
void AES_CBC_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv);
|
||||
|
||||
#endif // #if defined(CBC) && (CBC == 1)
|
||||
|
||||
|
||||
#endif //_AES_H_
|
462
lib/aes_acc/aesacc.c
Normal file
@ -0,0 +1,462 @@
|
||||
/*
|
||||
* This file is adapted from PolarSSL 1.3.19 (GPL)
|
||||
*/
|
||||
|
||||
#include "aesni.h"
|
||||
#include "aesarm.h"
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#if defined(AES256) && (AES256 == 1)
|
||||
#define AES_KEYSIZE 256
|
||||
#ifdef HAVE_AMD64
|
||||
#define aeshw_setkey_enc aesni_setkey_enc_256
|
||||
#endif
|
||||
#elif defined(AES192) && (AES192 == 1)
|
||||
#define AES_KEYSIZE 192
|
||||
#ifdef HAVE_AMD64
|
||||
#define aeshw_setkey_enc aesni_setkey_enc_192
|
||||
#endif
|
||||
#else
|
||||
#define AES_KEYSIZE 128
|
||||
#ifdef HAVE_AMD64
|
||||
#define aeshw_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 aeshw_supported aesni_supported
|
||||
#define aeshw_crypt_ecb aesni_crypt_ecb
|
||||
#define aeshw_inverse_key(a,b) aesni_inverse_key(a,b,AES_NR)
|
||||
#endif /* HAVE_AMD64 */
|
||||
|
||||
#ifdef HAVE_ARM64
|
||||
#define HAVE_HARDAES 1
|
||||
#define aeshw_supported aesarm_supported
|
||||
#define aeshw_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 aeshw_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 aeshw_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_HARDAES
|
||||
static void aeshw_setkey_dec(uint8_t *rk, const uint8_t *key)
|
||||
{
|
||||
uint8_t rk_tmp[AES_RKSIZE];
|
||||
aeshw_setkey_enc(rk_tmp, key);
|
||||
aeshw_inverse_key(rk, rk_tmp);
|
||||
}
|
||||
|
||||
static void aeshw_encrypt_ecb( int nr,
|
||||
unsigned char *rk,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] )
|
||||
{
|
||||
aeshw_crypt_ecb(nr, rk, AES_ENCRYPT, input, output);
|
||||
}
|
||||
|
||||
static void aeshw_decrypt_ecb( int nr,
|
||||
unsigned char *rk,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] )
|
||||
{
|
||||
aeshw_crypt_ecb(nr, rk, AES_DECRYPT, input, output);
|
||||
}
|
||||
#endif /* HAVE_HARDAES */
|
||||
|
||||
/* OpenSSL assembly functions */
|
||||
#define AES_MAXNR 14
|
||||
typedef struct {
|
||||
uint32_t rd_key[4 * (AES_MAXNR + 1)];
|
||||
uint32_t rounds;
|
||||
} AES_KEY;
|
||||
|
||||
#if defined(__amd64__) || defined(__x86_64__) || \
|
||||
defined(__aarch64__)
|
||||
#define AES_set_encrypt_key vpaes_set_encrypt_key
|
||||
#define AES_set_decrypt_key vpaes_set_decrypt_key
|
||||
#define AES_encrypt vpaes_encrypt
|
||||
#define AES_decrypt vpaes_decrypt
|
||||
#endif /* VPAES for 64-bit Intel and ARM */
|
||||
|
||||
#ifdef __cplusplus
|
||||
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 void aes_encrypt_ecb( int nr,
|
||||
unsigned char *rk,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] )
|
||||
{
|
||||
AES_encrypt(input, output, (AES_KEY *) rk);
|
||||
}
|
||||
|
||||
static void aes_decrypt_ecb( int nr,
|
||||
unsigned char *rk,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] )
|
||||
{
|
||||
AES_decrypt(input, output, (AES_KEY *) rk);
|
||||
}
|
||||
|
||||
static void aes_setkey_enc(uint8_t *rk, const uint8_t *key)
|
||||
{
|
||||
AES_set_encrypt_key(key, AES_KEYSIZE, (AES_KEY *) rk);
|
||||
}
|
||||
|
||||
static void aes_setkey_dec(uint8_t *rk, const uint8_t *key)
|
||||
{
|
||||
AES_set_decrypt_key(key, AES_KEYSIZE, (AES_KEY *) rk);
|
||||
}
|
||||
|
||||
static void (*encrypt_ecb) ( int nr,
|
||||
unsigned char *rk,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] )
|
||||
= aes_encrypt_ecb;
|
||||
|
||||
static void (*decrypt_ecb) ( int nr,
|
||||
unsigned char *rk,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] )
|
||||
= aes_decrypt_ecb;
|
||||
|
||||
static void (*setkey_enc) (uint8_t *rk, const uint8_t *key)
|
||||
= aes_setkey_enc;
|
||||
|
||||
static void (*setkey_dec) (uint8_t *rk, const uint8_t *key)
|
||||
= aes_setkey_dec;
|
||||
|
||||
/*
|
||||
* AESNI-CBC buffer encryption/decryption
|
||||
*/
|
||||
static void encrypt_cbc( uint8_t* rk,
|
||||
uint32_t length,
|
||||
uint8_t iv[16],
|
||||
const uint8_t *input,
|
||||
uint8_t *output )
|
||||
{
|
||||
int i;
|
||||
uint8_t temp[16];
|
||||
|
||||
while( length > 0 )
|
||||
{
|
||||
for( i = 0; i < 16; i++ )
|
||||
output[i] = (uint8_t)( input[i] ^ iv[i] );
|
||||
|
||||
encrypt_ecb( AES_NR, rk, output, output );
|
||||
memcpy( iv, output, 16 );
|
||||
|
||||
input += 16;
|
||||
output += 16;
|
||||
length -= 16;
|
||||
}
|
||||
}
|
||||
|
||||
static void decrypt_cbc( uint8_t* rk,
|
||||
uint32_t length,
|
||||
uint8_t iv[16],
|
||||
const uint8_t *input,
|
||||
uint8_t *output )
|
||||
{
|
||||
int i;
|
||||
uint8_t temp[16];
|
||||
|
||||
while( length > 0 )
|
||||
{
|
||||
memcpy( temp, input, 16 );
|
||||
decrypt_ecb( AES_NR, rk, 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;
|
||||
}
|
||||
}
|
||||
|
||||
static void aeshw_init(void)
|
||||
{
|
||||
#ifdef HAVE_HARDAES
|
||||
static int done = 0;
|
||||
if (!done) {
|
||||
if (aeshw_supported()) {
|
||||
encrypt_ecb = aeshw_encrypt_ecb;
|
||||
decrypt_ecb = aeshw_decrypt_ecb;
|
||||
setkey_enc = aeshw_setkey_enc;
|
||||
setkey_dec = aeshw_setkey_dec;
|
||||
}
|
||||
done = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int AES_support_hwaccel(void)
|
||||
{
|
||||
#ifdef HAVE_HARDAES
|
||||
return aeshw_supported();
|
||||
#else
|
||||
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)
|
||||
{
|
||||
uint8_t iv_tmp[16];
|
||||
static uint8_t rk[AES_RKSIZE];
|
||||
|
||||
assert(iv!=NULL);
|
||||
aeshw_init();
|
||||
memcpy(iv_tmp, iv, 16);
|
||||
if(key!= NULL)
|
||||
setkey_enc(rk, key);
|
||||
encrypt_cbc(rk, length, iv_tmp, input, output);
|
||||
}
|
||||
|
||||
void AES_CBC_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)
|
||||
{
|
||||
uint8_t iv_tmp[16];
|
||||
static uint8_t rk[AES_RKSIZE];
|
||||
|
||||
assert(iv!=NULL);
|
||||
aeshw_init();
|
||||
memcpy(iv_tmp, iv, 16);
|
||||
if(key!= NULL)
|
||||
{
|
||||
setkey_dec(rk, key);
|
||||
}
|
||||
decrypt_cbc(rk, length, iv_tmp, input, output);
|
||||
}
|
||||
|
||||
void AES_ECB_encrypt_buffer(const uint8_t* input, const uint8_t* key, uint8_t* output)
|
||||
{
|
||||
static uint8_t rk[AES_RKSIZE];
|
||||
|
||||
aeshw_init();
|
||||
if(key!=NULL)
|
||||
setkey_enc(rk, key);
|
||||
encrypt_ecb(AES_NR, rk, input, output);
|
||||
}
|
||||
|
||||
void AES_ECB_decrypt_buffer(const uint8_t* input, const uint8_t* key, uint8_t *output)
|
||||
{
|
||||
static uint8_t rk[AES_RKSIZE];
|
||||
|
||||
aeshw_init();
|
||||
if(key!=NULL)
|
||||
setkey_dec(rk, key);
|
||||
decrypt_ecb(AES_NR, rk, input, output);
|
||||
}
|
||||
|
||||
static void encrypt_cfb( uint8_t* rk,
|
||||
uint32_t length,size_t *iv_off,
|
||||
uint8_t iv[16],
|
||||
const uint8_t *input,
|
||||
uint8_t *output )
|
||||
{
|
||||
int c;
|
||||
size_t n = *iv_off;
|
||||
while( length-- )
|
||||
{
|
||||
if( n == 0 )
|
||||
encrypt_ecb( AES_NR, rk, iv, iv );
|
||||
|
||||
iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
|
||||
|
||||
n = ( n + 1 ) & 0x0F;
|
||||
}
|
||||
|
||||
*iv_off = n;
|
||||
}
|
||||
|
||||
static void decrypt_cfb( uint8_t* rk,
|
||||
uint32_t length,size_t *iv_off,
|
||||
uint8_t iv[16],
|
||||
const uint8_t *input,
|
||||
uint8_t *output )
|
||||
{
|
||||
int c;
|
||||
size_t n = *iv_off;
|
||||
while( length-- )
|
||||
{
|
||||
if( n == 0 )
|
||||
encrypt_ecb( AES_NR, rk, iv, iv );
|
||||
|
||||
c = *input++;
|
||||
*output++ = (unsigned char)( c ^ iv[n] );
|
||||
iv[n] = (unsigned char) c;
|
||||
|
||||
n = ( n + 1 ) & 0x0F;
|
||||
}
|
||||
|
||||
*iv_off = n;
|
||||
}
|
||||
|
||||
void AES_CFB_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)
|
||||
{
|
||||
uint8_t iv_tmp[16];
|
||||
static uint8_t rk[AES_RKSIZE];
|
||||
|
||||
assert(iv!=NULL);
|
||||
aeshw_init();
|
||||
memcpy(iv_tmp, iv, 16);
|
||||
if(key!= NULL)
|
||||
setkey_enc(rk, key);
|
||||
size_t offset=0;
|
||||
encrypt_cfb(rk, length,&offset, iv_tmp, input, output);
|
||||
}
|
||||
|
||||
void AES_CFB_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)
|
||||
{
|
||||
uint8_t iv_tmp[16];
|
||||
static uint8_t rk[AES_RKSIZE];
|
||||
|
||||
assert(iv!=NULL);
|
||||
aeshw_init();
|
||||
memcpy(iv_tmp, iv, 16);
|
||||
if(key!= NULL)
|
||||
{
|
||||
setkey_enc(rk, key);//its enc again,not typo
|
||||
}
|
||||
size_t offset=0;
|
||||
decrypt_cfb(rk, length,&offset, iv_tmp, input, output);
|
||||
}
|
||||
|
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
@ -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 UDP2RAW_AESARM_H_
|
||||
#define UDP2RAW_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
@ -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
|
324
lib/aes_acc/aesni.c
Normal file
@ -0,0 +1,324 @@
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
void 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" );
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 */
|
117
lib/aes_acc/aesni.h
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* 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 UDP2RAW_AESNI_H_
|
||||
#define UDP2RAW_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
|
||||
*/
|
||||
void 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
vendored
Normal file
1178
lib/aes_acc/asm/arm64.S
vendored
Normal file
83
lib/aes_acc/asm/arm_arch.h
vendored
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 UDP2RAW_ARM_ARCH_H_
|
||||
# define UDP2RAW_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
|
1831
lib/aes_acc/asm/mips.S
vendored
Normal file
1831
lib/aes_acc/asm/mips_be.S
vendored
Normal file
827
lib/aes_acc/asm/x64.S
vendored
Normal file
@ -0,0 +1,827 @@
|
||||
.text
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.type _vpaes_encrypt_core,@function
|
||||
.align 16
|
||||
_vpaes_encrypt_core:
|
||||
movq %rdx,%r9
|
||||
movq $16,%r11
|
||||
movl 240(%rdx),%eax
|
||||
movdqa %xmm9,%xmm1
|
||||
movdqa .Lk_ipt(%rip),%xmm2
|
||||
pandn %xmm0,%xmm1
|
||||
movdqu (%r9),%xmm5
|
||||
psrld $4,%xmm1
|
||||
pand %xmm9,%xmm0
|
||||
.byte 102,15,56,0,208
|
||||
movdqa .Lk_ipt+16(%rip),%xmm0
|
||||
.byte 102,15,56,0,193
|
||||
pxor %xmm5,%xmm2
|
||||
addq $16,%r9
|
||||
pxor %xmm2,%xmm0
|
||||
leaq .Lk_mc_backward(%rip),%r10
|
||||
jmp .Lenc_entry
|
||||
|
||||
.align 16
|
||||
.Lenc_loop:
|
||||
|
||||
movdqa %xmm13,%xmm4
|
||||
movdqa %xmm12,%xmm0
|
||||
.byte 102,15,56,0,226
|
||||
.byte 102,15,56,0,195
|
||||
pxor %xmm5,%xmm4
|
||||
movdqa %xmm15,%xmm5
|
||||
pxor %xmm4,%xmm0
|
||||
movdqa -64(%r11,%r10,1),%xmm1
|
||||
.byte 102,15,56,0,234
|
||||
movdqa (%r11,%r10,1),%xmm4
|
||||
movdqa %xmm14,%xmm2
|
||||
.byte 102,15,56,0,211
|
||||
movdqa %xmm0,%xmm3
|
||||
pxor %xmm5,%xmm2
|
||||
.byte 102,15,56,0,193
|
||||
addq $16,%r9
|
||||
pxor %xmm2,%xmm0
|
||||
.byte 102,15,56,0,220
|
||||
addq $16,%r11
|
||||
pxor %xmm0,%xmm3
|
||||
.byte 102,15,56,0,193
|
||||
andq $0x30,%r11
|
||||
subq $1,%rax
|
||||
pxor %xmm3,%xmm0
|
||||
|
||||
.Lenc_entry:
|
||||
|
||||
movdqa %xmm9,%xmm1
|
||||
movdqa %xmm11,%xmm5
|
||||
pandn %xmm0,%xmm1
|
||||
psrld $4,%xmm1
|
||||
pand %xmm9,%xmm0
|
||||
.byte 102,15,56,0,232
|
||||
movdqa %xmm10,%xmm3
|
||||
pxor %xmm1,%xmm0
|
||||
.byte 102,15,56,0,217
|
||||
movdqa %xmm10,%xmm4
|
||||
pxor %xmm5,%xmm3
|
||||
.byte 102,15,56,0,224
|
||||
movdqa %xmm10,%xmm2
|
||||
pxor %xmm5,%xmm4
|
||||
.byte 102,15,56,0,211
|
||||
movdqa %xmm10,%xmm3
|
||||
pxor %xmm0,%xmm2
|
||||
.byte 102,15,56,0,220
|
||||
movdqu (%r9),%xmm5
|
||||
pxor %xmm1,%xmm3
|
||||
jnz .Lenc_loop
|
||||
|
||||
|
||||
movdqa -96(%r10),%xmm4
|
||||
movdqa -80(%r10),%xmm0
|
||||
.byte 102,15,56,0,226
|
||||
pxor %xmm5,%xmm4
|
||||
.byte 102,15,56,0,195
|
||||
movdqa 64(%r11,%r10,1),%xmm1
|
||||
pxor %xmm4,%xmm0
|
||||
.byte 102,15,56,0,193
|
||||
.byte 0xf3,0xc3
|
||||
.size _vpaes_encrypt_core,.-_vpaes_encrypt_core
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.type _vpaes_decrypt_core,@function
|
||||
.align 16
|
||||
_vpaes_decrypt_core:
|
||||
movq %rdx,%r9
|
||||
movl 240(%rdx),%eax
|
||||
movdqa %xmm9,%xmm1
|
||||
movdqa .Lk_dipt(%rip),%xmm2
|
||||
pandn %xmm0,%xmm1
|
||||
movq %rax,%r11
|
||||
psrld $4,%xmm1
|
||||
movdqu (%r9),%xmm5
|
||||
shlq $4,%r11
|
||||
pand %xmm9,%xmm0
|
||||
.byte 102,15,56,0,208
|
||||
movdqa .Lk_dipt+16(%rip),%xmm0
|
||||
xorq $0x30,%r11
|
||||
leaq .Lk_dsbd(%rip),%r10
|
||||
.byte 102,15,56,0,193
|
||||
andq $0x30,%r11
|
||||
pxor %xmm5,%xmm2
|
||||
movdqa .Lk_mc_forward+48(%rip),%xmm5
|
||||
pxor %xmm2,%xmm0
|
||||
addq $16,%r9
|
||||
addq %r10,%r11
|
||||
jmp .Ldec_entry
|
||||
|
||||
.align 16
|
||||
.Ldec_loop:
|
||||
|
||||
|
||||
|
||||
movdqa -32(%r10),%xmm4
|
||||
movdqa -16(%r10),%xmm1
|
||||
.byte 102,15,56,0,226
|
||||
.byte 102,15,56,0,203
|
||||
pxor %xmm4,%xmm0
|
||||
movdqa 0(%r10),%xmm4
|
||||
pxor %xmm1,%xmm0
|
||||
movdqa 16(%r10),%xmm1
|
||||
|
||||
.byte 102,15,56,0,226
|
||||
.byte 102,15,56,0,197
|
||||
.byte 102,15,56,0,203
|
||||
pxor %xmm4,%xmm0
|
||||
movdqa 32(%r10),%xmm4
|
||||
pxor %xmm1,%xmm0
|
||||
movdqa 48(%r10),%xmm1
|
||||
|
||||
.byte 102,15,56,0,226
|
||||
.byte 102,15,56,0,197
|
||||
.byte 102,15,56,0,203
|
||||
pxor %xmm4,%xmm0
|
||||
movdqa 64(%r10),%xmm4
|
||||
pxor %xmm1,%xmm0
|
||||
movdqa 80(%r10),%xmm1
|
||||
|
||||
.byte 102,15,56,0,226
|
||||
.byte 102,15,56,0,197
|
||||
.byte 102,15,56,0,203
|
||||
pxor %xmm4,%xmm0
|
||||
addq $16,%r9
|
||||
.byte 102,15,58,15,237,12
|
||||
pxor %xmm1,%xmm0
|
||||
subq $1,%rax
|
||||
|
||||
.Ldec_entry:
|
||||
|
||||
movdqa %xmm9,%xmm1
|
||||
pandn %xmm0,%xmm1
|
||||
movdqa %xmm11,%xmm2
|
||||
psrld $4,%xmm1
|
||||
pand %xmm9,%xmm0
|
||||
.byte 102,15,56,0,208
|
||||
movdqa %xmm10,%xmm3
|
||||
pxor %xmm1,%xmm0
|
||||
.byte 102,15,56,0,217
|
||||
movdqa %xmm10,%xmm4
|
||||
pxor %xmm2,%xmm3
|
||||
.byte 102,15,56,0,224
|
||||
pxor %xmm2,%xmm4
|
||||
movdqa %xmm10,%xmm2
|
||||
.byte 102,15,56,0,211
|
||||
movdqa %xmm10,%xmm3
|
||||
pxor %xmm0,%xmm2
|
||||
.byte 102,15,56,0,220
|
||||
movdqu (%r9),%xmm0
|
||||
pxor %xmm1,%xmm3
|
||||
jnz .Ldec_loop
|
||||
|
||||
|
||||
movdqa 96(%r10),%xmm4
|
||||
.byte 102,15,56,0,226
|
||||
pxor %xmm0,%xmm4
|
||||
movdqa 112(%r10),%xmm0
|
||||
movdqa -352(%r11),%xmm2
|
||||
.byte 102,15,56,0,195
|
||||
pxor %xmm4,%xmm0
|
||||
.byte 102,15,56,0,194
|
||||
.byte 0xf3,0xc3
|
||||
.size _vpaes_decrypt_core,.-_vpaes_decrypt_core
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.type _vpaes_schedule_core,@function
|
||||
.align 16
|
||||
_vpaes_schedule_core:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
call _vpaes_preheat
|
||||
movdqa .Lk_rcon(%rip),%xmm8
|
||||
movdqu (%rdi),%xmm0
|
||||
|
||||
|
||||
movdqa %xmm0,%xmm3
|
||||
leaq .Lk_ipt(%rip),%r11
|
||||
call _vpaes_schedule_transform
|
||||
movdqa %xmm0,%xmm7
|
||||
|
||||
leaq .Lk_sr(%rip),%r10
|
||||
testq %rcx,%rcx
|
||||
jnz .Lschedule_am_decrypting
|
||||
|
||||
|
||||
movdqu %xmm0,(%rdx)
|
||||
jmp .Lschedule_go
|
||||
|
||||
.Lschedule_am_decrypting:
|
||||
|
||||
movdqa (%r8,%r10,1),%xmm1
|
||||
.byte 102,15,56,0,217
|
||||
movdqu %xmm3,(%rdx)
|
||||
xorq $0x30,%r8
|
||||
|
||||
.Lschedule_go:
|
||||
cmpl $192,%esi
|
||||
ja .Lschedule_256
|
||||
je .Lschedule_192
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.Lschedule_128:
|
||||
movl $10,%esi
|
||||
|
||||
.Loop_schedule_128:
|
||||
call _vpaes_schedule_round
|
||||
decq %rsi
|
||||
jz .Lschedule_mangle_last
|
||||
call _vpaes_schedule_mangle
|
||||
jmp .Loop_schedule_128
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.align 16
|
||||
.Lschedule_192:
|
||||
movdqu 8(%rdi),%xmm0
|
||||
call _vpaes_schedule_transform
|
||||
movdqa %xmm0,%xmm6
|
||||
pxor %xmm4,%xmm4
|
||||
movhlps %xmm4,%xmm6
|
||||
movl $4,%esi
|
||||
|
||||
.Loop_schedule_192:
|
||||
call _vpaes_schedule_round
|
||||
.byte 102,15,58,15,198,8
|
||||
call _vpaes_schedule_mangle
|
||||
call _vpaes_schedule_192_smear
|
||||
call _vpaes_schedule_mangle
|
||||
call _vpaes_schedule_round
|
||||
decq %rsi
|
||||
jz .Lschedule_mangle_last
|
||||
call _vpaes_schedule_mangle
|
||||
call _vpaes_schedule_192_smear
|
||||
jmp .Loop_schedule_192
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.align 16
|
||||
.Lschedule_256:
|
||||
movdqu 16(%rdi),%xmm0
|
||||
call _vpaes_schedule_transform
|
||||
movl $7,%esi
|
||||
|
||||
.Loop_schedule_256:
|
||||
call _vpaes_schedule_mangle
|
||||
movdqa %xmm0,%xmm6
|
||||
|
||||
|
||||
call _vpaes_schedule_round
|
||||
decq %rsi
|
||||
jz .Lschedule_mangle_last
|
||||
call _vpaes_schedule_mangle
|
||||
|
||||
|
||||
pshufd $0xFF,%xmm0,%xmm0
|
||||
movdqa %xmm7,%xmm5
|
||||
movdqa %xmm6,%xmm7
|
||||
call _vpaes_schedule_low_round
|
||||
movdqa %xmm5,%xmm7
|
||||
|
||||
jmp .Loop_schedule_256
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.align 16
|
||||
.Lschedule_mangle_last:
|
||||
|
||||
leaq .Lk_deskew(%rip),%r11
|
||||
testq %rcx,%rcx
|
||||
jnz .Lschedule_mangle_last_dec
|
||||
|
||||
|
||||
movdqa (%r8,%r10,1),%xmm1
|
||||
.byte 102,15,56,0,193
|
||||
leaq .Lk_opt(%rip),%r11
|
||||
addq $32,%rdx
|
||||
|
||||
.Lschedule_mangle_last_dec:
|
||||
addq $-16,%rdx
|
||||
pxor .Lk_s63(%rip),%xmm0
|
||||
call _vpaes_schedule_transform
|
||||
movdqu %xmm0,(%rdx)
|
||||
|
||||
|
||||
pxor %xmm0,%xmm0
|
||||
pxor %xmm1,%xmm1
|
||||
pxor %xmm2,%xmm2
|
||||
pxor %xmm3,%xmm3
|
||||
pxor %xmm4,%xmm4
|
||||
pxor %xmm5,%xmm5
|
||||
pxor %xmm6,%xmm6
|
||||
pxor %xmm7,%xmm7
|
||||
.byte 0xf3,0xc3
|
||||
.size _vpaes_schedule_core,.-_vpaes_schedule_core
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.type _vpaes_schedule_192_smear,@function
|
||||
.align 16
|
||||
_vpaes_schedule_192_smear:
|
||||
pshufd $0x80,%xmm6,%xmm1
|
||||
pshufd $0xFE,%xmm7,%xmm0
|
||||
pxor %xmm1,%xmm6
|
||||
pxor %xmm1,%xmm1
|
||||
pxor %xmm0,%xmm6
|
||||
movdqa %xmm6,%xmm0
|
||||
movhlps %xmm1,%xmm6
|
||||
.byte 0xf3,0xc3
|
||||
.size _vpaes_schedule_192_smear,.-_vpaes_schedule_192_smear
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.type _vpaes_schedule_round,@function
|
||||
.align 16
|
||||
_vpaes_schedule_round:
|
||||
|
||||
pxor %xmm1,%xmm1
|
||||
.byte 102,65,15,58,15,200,15
|
||||
.byte 102,69,15,58,15,192,15
|
||||
pxor %xmm1,%xmm7
|
||||
|
||||
|
||||
pshufd $0xFF,%xmm0,%xmm0
|
||||
.byte 102,15,58,15,192,1
|
||||
|
||||
|
||||
|
||||
|
||||
_vpaes_schedule_low_round:
|
||||
|
||||
movdqa %xmm7,%xmm1
|
||||
pslldq $4,%xmm7
|
||||
pxor %xmm1,%xmm7
|
||||
movdqa %xmm7,%xmm1
|
||||
pslldq $8,%xmm7
|
||||
pxor %xmm1,%xmm7
|
||||
pxor .Lk_s63(%rip),%xmm7
|
||||
|
||||
|
||||
movdqa %xmm9,%xmm1
|
||||
pandn %xmm0,%xmm1
|
||||
psrld $4,%xmm1
|
||||
pand %xmm9,%xmm0
|
||||
movdqa %xmm11,%xmm2
|
||||
.byte 102,15,56,0,208
|
||||
pxor %xmm1,%xmm0
|
||||
movdqa %xmm10,%xmm3
|
||||
.byte 102,15,56,0,217
|
||||
pxor %xmm2,%xmm3
|
||||
movdqa %xmm10,%xmm4
|
||||
.byte 102,15,56,0,224
|
||||
pxor %xmm2,%xmm4
|
||||
movdqa %xmm10,%xmm2
|
||||
.byte 102,15,56,0,211
|
||||
pxor %xmm0,%xmm2
|
||||
movdqa %xmm10,%xmm3
|
||||
.byte 102,15,56,0,220
|
||||
pxor %xmm1,%xmm3
|
||||
movdqa %xmm13,%xmm4
|
||||
.byte 102,15,56,0,226
|
||||
movdqa %xmm12,%xmm0
|
||||
.byte 102,15,56,0,195
|
||||
pxor %xmm4,%xmm0
|
||||
|
||||
|
||||
pxor %xmm7,%xmm0
|
||||
movdqa %xmm0,%xmm7
|
||||
.byte 0xf3,0xc3
|
||||
.size _vpaes_schedule_round,.-_vpaes_schedule_round
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.type _vpaes_schedule_transform,@function
|
||||
.align 16
|
||||
_vpaes_schedule_transform:
|
||||
movdqa %xmm9,%xmm1
|
||||
pandn %xmm0,%xmm1
|
||||
psrld $4,%xmm1
|
||||
pand %xmm9,%xmm0
|
||||
movdqa (%r11),%xmm2
|
||||
.byte 102,15,56,0,208
|
||||
movdqa 16(%r11),%xmm0
|
||||
.byte 102,15,56,0,193
|
||||
pxor %xmm2,%xmm0
|
||||
.byte 0xf3,0xc3
|
||||
.size _vpaes_schedule_transform,.-_vpaes_schedule_transform
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.type _vpaes_schedule_mangle,@function
|
||||
.align 16
|
||||
_vpaes_schedule_mangle:
|
||||
movdqa %xmm0,%xmm4
|
||||
movdqa .Lk_mc_forward(%rip),%xmm5
|
||||
testq %rcx,%rcx
|
||||
jnz .Lschedule_mangle_dec
|
||||
|
||||
|
||||
addq $16,%rdx
|
||||
pxor .Lk_s63(%rip),%xmm4
|
||||
.byte 102,15,56,0,229
|
||||
movdqa %xmm4,%xmm3
|
||||
.byte 102,15,56,0,229
|
||||
pxor %xmm4,%xmm3
|
||||
.byte 102,15,56,0,229
|
||||
pxor %xmm4,%xmm3
|
||||
|
||||
jmp .Lschedule_mangle_both
|
||||
.align 16
|
||||
.Lschedule_mangle_dec:
|
||||
|
||||
leaq .Lk_dksd(%rip),%r11
|
||||
movdqa %xmm9,%xmm1
|
||||
pandn %xmm4,%xmm1
|
||||
psrld $4,%xmm1
|
||||
pand %xmm9,%xmm4
|
||||
|
||||
movdqa 0(%r11),%xmm2
|
||||
.byte 102,15,56,0,212
|
||||
movdqa 16(%r11),%xmm3
|
||||
.byte 102,15,56,0,217
|
||||
pxor %xmm2,%xmm3
|
||||
.byte 102,15,56,0,221
|
||||
|
||||
movdqa 32(%r11),%xmm2
|
||||
.byte 102,15,56,0,212
|
||||
pxor %xmm3,%xmm2
|
||||
movdqa 48(%r11),%xmm3
|
||||
.byte 102,15,56,0,217
|
||||
pxor %xmm2,%xmm3
|
||||
.byte 102,15,56,0,221
|
||||
|
||||
movdqa 64(%r11),%xmm2
|
||||
.byte 102,15,56,0,212
|
||||
pxor %xmm3,%xmm2
|
||||
movdqa 80(%r11),%xmm3
|
||||
.byte 102,15,56,0,217
|
||||
pxor %xmm2,%xmm3
|
||||
.byte 102,15,56,0,221
|
||||
|
||||
movdqa 96(%r11),%xmm2
|
||||
.byte 102,15,56,0,212
|
||||
pxor %xmm3,%xmm2
|
||||
movdqa 112(%r11),%xmm3
|
||||
.byte 102,15,56,0,217
|
||||
pxor %xmm2,%xmm3
|
||||
|
||||
addq $-16,%rdx
|
||||
|
||||
.Lschedule_mangle_both:
|
||||
movdqa (%r8,%r10,1),%xmm1
|
||||
.byte 102,15,56,0,217
|
||||
addq $-16,%r8
|
||||
andq $0x30,%r8
|
||||
movdqu %xmm3,(%rdx)
|
||||
.byte 0xf3,0xc3
|
||||
.size _vpaes_schedule_mangle,.-_vpaes_schedule_mangle
|
||||
|
||||
|
||||
|
||||
|
||||
.globl vpaes_set_encrypt_key
|
||||
.type vpaes_set_encrypt_key,@function
|
||||
.align 16
|
||||
vpaes_set_encrypt_key:
|
||||
movl %esi,%eax
|
||||
shrl $5,%eax
|
||||
addl $5,%eax
|
||||
movl %eax,240(%rdx)
|
||||
|
||||
movl $0,%ecx
|
||||
movl $0x30,%r8d
|
||||
call _vpaes_schedule_core
|
||||
xorl %eax,%eax
|
||||
.byte 0xf3,0xc3
|
||||
.size vpaes_set_encrypt_key,.-vpaes_set_encrypt_key
|
||||
|
||||
.globl vpaes_set_decrypt_key
|
||||
.type vpaes_set_decrypt_key,@function
|
||||
.align 16
|
||||
vpaes_set_decrypt_key:
|
||||
movl %esi,%eax
|
||||
shrl $5,%eax
|
||||
addl $5,%eax
|
||||
movl %eax,240(%rdx)
|
||||
shll $4,%eax
|
||||
leaq 16(%rdx,%rax,1),%rdx
|
||||
|
||||
movl $1,%ecx
|
||||
movl %esi,%r8d
|
||||
shrl $1,%r8d
|
||||
andl $32,%r8d
|
||||
xorl $32,%r8d
|
||||
call _vpaes_schedule_core
|
||||
xorl %eax,%eax
|
||||
.byte 0xf3,0xc3
|
||||
.size vpaes_set_decrypt_key,.-vpaes_set_decrypt_key
|
||||
|
||||
.globl vpaes_encrypt
|
||||
.type vpaes_encrypt,@function
|
||||
.align 16
|
||||
vpaes_encrypt:
|
||||
movdqu (%rdi),%xmm0
|
||||
call _vpaes_preheat
|
||||
call _vpaes_encrypt_core
|
||||
movdqu %xmm0,(%rsi)
|
||||
.byte 0xf3,0xc3
|
||||
.size vpaes_encrypt,.-vpaes_encrypt
|
||||
|
||||
.globl vpaes_decrypt
|
||||
.type vpaes_decrypt,@function
|
||||
.align 16
|
||||
vpaes_decrypt:
|
||||
movdqu (%rdi),%xmm0
|
||||
call _vpaes_preheat
|
||||
call _vpaes_decrypt_core
|
||||
movdqu %xmm0,(%rsi)
|
||||
.byte 0xf3,0xc3
|
||||
.size vpaes_decrypt,.-vpaes_decrypt
|
||||
.globl vpaes_cbc_encrypt
|
||||
.type vpaes_cbc_encrypt,@function
|
||||
.align 16
|
||||
vpaes_cbc_encrypt:
|
||||
xchgq %rcx,%rdx
|
||||
subq $16,%rcx
|
||||
jc .Lcbc_abort
|
||||
movdqu (%r8),%xmm6
|
||||
subq %rdi,%rsi
|
||||
call _vpaes_preheat
|
||||
cmpl $0,%r9d
|
||||
je .Lcbc_dec_loop
|
||||
jmp .Lcbc_enc_loop
|
||||
.align 16
|
||||
.Lcbc_enc_loop:
|
||||
movdqu (%rdi),%xmm0
|
||||
pxor %xmm6,%xmm0
|
||||
call _vpaes_encrypt_core
|
||||
movdqa %xmm0,%xmm6
|
||||
movdqu %xmm0,(%rsi,%rdi,1)
|
||||
leaq 16(%rdi),%rdi
|
||||
subq $16,%rcx
|
||||
jnc .Lcbc_enc_loop
|
||||
jmp .Lcbc_done
|
||||
.align 16
|
||||
.Lcbc_dec_loop:
|
||||
movdqu (%rdi),%xmm0
|
||||
movdqa %xmm0,%xmm7
|
||||
call _vpaes_decrypt_core
|
||||
pxor %xmm6,%xmm0
|
||||
movdqa %xmm7,%xmm6
|
||||
movdqu %xmm0,(%rsi,%rdi,1)
|
||||
leaq 16(%rdi),%rdi
|
||||
subq $16,%rcx
|
||||
jnc .Lcbc_dec_loop
|
||||
.Lcbc_done:
|
||||
movdqu %xmm6,(%r8)
|
||||
.Lcbc_abort:
|
||||
.byte 0xf3,0xc3
|
||||
.size vpaes_cbc_encrypt,.-vpaes_cbc_encrypt
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.type _vpaes_preheat,@function
|
||||
.align 16
|
||||
_vpaes_preheat:
|
||||
leaq .Lk_s0F(%rip),%r10
|
||||
movdqa -32(%r10),%xmm10
|
||||
movdqa -16(%r10),%xmm11
|
||||
movdqa 0(%r10),%xmm9
|
||||
movdqa 48(%r10),%xmm13
|
||||
movdqa 64(%r10),%xmm12
|
||||
movdqa 80(%r10),%xmm15
|
||||
movdqa 96(%r10),%xmm14
|
||||
.byte 0xf3,0xc3
|
||||
.size _vpaes_preheat,.-_vpaes_preheat
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.type _vpaes_consts,@object
|
||||
.align 64
|
||||
_vpaes_consts:
|
||||
.Lk_inv:
|
||||
.quad 0x0E05060F0D080180, 0x040703090A0B0C02
|
||||
.quad 0x01040A060F0B0780, 0x030D0E0C02050809
|
||||
|
||||
.Lk_s0F:
|
||||
.quad 0x0F0F0F0F0F0F0F0F, 0x0F0F0F0F0F0F0F0F
|
||||
|
||||
.Lk_ipt:
|
||||
.quad 0xC2B2E8985A2A7000, 0xCABAE09052227808
|
||||
.quad 0x4C01307D317C4D00, 0xCD80B1FCB0FDCC81
|
||||
|
||||
.Lk_sb1:
|
||||
.quad 0xB19BE18FCB503E00, 0xA5DF7A6E142AF544
|
||||
.quad 0x3618D415FAE22300, 0x3BF7CCC10D2ED9EF
|
||||
.Lk_sb2:
|
||||
.quad 0xE27A93C60B712400, 0x5EB7E955BC982FCD
|
||||
.quad 0x69EB88400AE12900, 0xC2A163C8AB82234A
|
||||
.Lk_sbo:
|
||||
.quad 0xD0D26D176FBDC700, 0x15AABF7AC502A878
|
||||
.quad 0xCFE474A55FBB6A00, 0x8E1E90D1412B35FA
|
||||
|
||||
.Lk_mc_forward:
|
||||
.quad 0x0407060500030201, 0x0C0F0E0D080B0A09
|
||||
.quad 0x080B0A0904070605, 0x000302010C0F0E0D
|
||||
.quad 0x0C0F0E0D080B0A09, 0x0407060500030201
|
||||
.quad 0x000302010C0F0E0D, 0x080B0A0904070605
|
||||
|
||||
.Lk_mc_backward:
|
||||
.quad 0x0605040702010003, 0x0E0D0C0F0A09080B
|
||||
.quad 0x020100030E0D0C0F, 0x0A09080B06050407
|
||||
.quad 0x0E0D0C0F0A09080B, 0x0605040702010003
|
||||
.quad 0x0A09080B06050407, 0x020100030E0D0C0F
|
||||
|
||||
.Lk_sr:
|
||||
.quad 0x0706050403020100, 0x0F0E0D0C0B0A0908
|
||||
.quad 0x030E09040F0A0500, 0x0B06010C07020D08
|
||||
.quad 0x0F060D040B020900, 0x070E050C030A0108
|
||||
.quad 0x0B0E0104070A0D00, 0x0306090C0F020508
|
||||
|
||||
.Lk_rcon:
|
||||
.quad 0x1F8391B9AF9DEEB6, 0x702A98084D7C7D81
|
||||
|
||||
.Lk_s63:
|
||||
.quad 0x5B5B5B5B5B5B5B5B, 0x5B5B5B5B5B5B5B5B
|
||||
|
||||
.Lk_opt:
|
||||
.quad 0xFF9F4929D6B66000, 0xF7974121DEBE6808
|
||||
.quad 0x01EDBD5150BCEC00, 0xE10D5DB1B05C0CE0
|
||||
|
||||
.Lk_deskew:
|
||||
.quad 0x07E4A34047A4E300, 0x1DFEB95A5DBEF91A
|
||||
.quad 0x5F36B5DC83EA6900, 0x2841C2ABF49D1E77
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.Lk_dksd:
|
||||
.quad 0xFEB91A5DA3E44700, 0x0740E3A45A1DBEF9
|
||||
.quad 0x41C277F4B5368300, 0x5FDC69EAAB289D1E
|
||||
.Lk_dksb:
|
||||
.quad 0x9A4FCA1F8550D500, 0x03D653861CC94C99
|
||||
.quad 0x115BEDA7B6FC4A00, 0xD993256F7E3482C8
|
||||
.Lk_dkse:
|
||||
.quad 0xD5031CCA1FC9D600, 0x53859A4C994F5086
|
||||
.quad 0xA23196054FDC7BE8, 0xCD5EF96A20B31487
|
||||
.Lk_dks9:
|
||||
.quad 0xB6116FC87ED9A700, 0x4AED933482255BFC
|
||||
.quad 0x4576516227143300, 0x8BB89FACE9DAFDCE
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.Lk_dipt:
|
||||
.quad 0x0F505B040B545F00, 0x154A411E114E451A
|
||||
.quad 0x86E383E660056500, 0x12771772F491F194
|
||||
|
||||
.Lk_dsb9:
|
||||
.quad 0x851C03539A86D600, 0xCAD51F504F994CC9
|
||||
.quad 0xC03B1789ECD74900, 0x725E2C9EB2FBA565
|
||||
.Lk_dsbd:
|
||||
.quad 0x7D57CCDFE6B1A200, 0xF56E9B13882A4439
|
||||
.quad 0x3CE2FAF724C6CB00, 0x2931180D15DEEFD3
|
||||
.Lk_dsbb:
|
||||
.quad 0xD022649296B44200, 0x602646F6B0F2D404
|
||||
.quad 0xC19498A6CD596700, 0xF3FF0C3E3255AA6B
|
||||
.Lk_dsbe:
|
||||
.quad 0x46F2929626D4D000, 0x2242600464B4F6B0
|
||||
.quad 0x0C55A6CDFFAAC100, 0x9467F36B98593E32
|
||||
.Lk_dsbo:
|
||||
.quad 0x1387EA537EF94000, 0xC7AA6DB9D4943E2D
|
||||
.quad 0x12D7560F93441D00, 0xCA4B8159D8C58E9C
|
||||
.byte 86,101,99,116,111,114,32,80,101,114,109,117,116,97,116,105,111,110,32,65,69,83,32,102,111,114,32,120,56,54,95,54,52,47,83,83,83,69,51,44,32,77,105,107,101,32,72,97,109,98,117,114,103,32,40,83,116,97,110,102,111,114,100,32,85,110,105,118,101,114,115,105,116,121,41,0
|
||||
.align 64
|
||||
.size _vpaes_consts,.-_vpaes_consts
|
3244
lib/aes_acc/asm/x86.S
vendored
Normal file
1459
lib/aes_faster_c/aes.cpp
Normal file
268
lib/aes_faster_c/aes.h
Normal file
@ -0,0 +1,268 @@
|
||||
/**
|
||||
* \file aes.h
|
||||
*
|
||||
* \brief AES block cipher
|
||||
*
|
||||
* Copyright (C) 2006-2014, Brainspark B.V.
|
||||
*
|
||||
* This file is part of PolarSSL (http://www.polarssl.org)
|
||||
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#ifndef POLARSSL_AES_H
|
||||
#define POLARSSL_AES_H
|
||||
/*
|
||||
#if !defined(POLARSSL_CONFIG_FILE)
|
||||
#include "config.h"
|
||||
#else
|
||||
#include POLARSSL_CONFIG_FILE
|
||||
#endif
|
||||
*/
|
||||
|
||||
////////modification begin
|
||||
#define POLARSSL_AES_ROM_TABLES
|
||||
#define POLARSSL_CIPHER_MODE_CBC
|
||||
#define POLARSSL_CIPHER_MODE_CFB
|
||||
//#define POLARSSL_SELF_TEST
|
||||
#define polarssl_printf printf
|
||||
///////add end
|
||||
|
||||
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
|
||||
#include <basetsd.h>
|
||||
typedef UINT32 uint32_t;
|
||||
#else
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
/* padlock.c and aesni.c rely on these values! */
|
||||
#define AES_ENCRYPT 1
|
||||
#define AES_DECRYPT 0
|
||||
|
||||
#define POLARSSL_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */
|
||||
#define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */
|
||||
|
||||
#if !defined(POLARSSL_AES_ALT)
|
||||
// Regular implementation
|
||||
//
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief AES context structure
|
||||
*
|
||||
* \note buf is able to hold 32 extra bytes, which can be used:
|
||||
* - for alignment purposes if VIA padlock is used, and/or
|
||||
* - to simplify key expansion in the 256-bit case by
|
||||
* generating an extra round key
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int nr; /*!< number of rounds */
|
||||
uint32_t *rk; /*!< AES round keys */
|
||||
uint32_t buf[68]; /*!< unaligned data */
|
||||
}
|
||||
aes_context;
|
||||
|
||||
/**
|
||||
* \brief Initialize AES context
|
||||
*
|
||||
* \param ctx AES context to be initialized
|
||||
*/
|
||||
void aes_init( aes_context *ctx );
|
||||
|
||||
/**
|
||||
* \brief Clear AES context
|
||||
*
|
||||
* \param ctx AES context to be cleared
|
||||
*/
|
||||
void aes_free( aes_context *ctx );
|
||||
|
||||
/**
|
||||
* \brief AES key schedule (encryption)
|
||||
*
|
||||
* \param ctx AES context to be initialized
|
||||
* \param key encryption key
|
||||
* \param keysize must be 128, 192 or 256
|
||||
*
|
||||
* \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
|
||||
*/
|
||||
int aes_setkey_enc( aes_context *ctx, const unsigned char *key,
|
||||
unsigned int keysize );
|
||||
|
||||
/**
|
||||
* \brief AES key schedule (decryption)
|
||||
*
|
||||
* \param ctx AES context to be initialized
|
||||
* \param key decryption key
|
||||
* \param keysize must be 128, 192 or 256
|
||||
*
|
||||
* \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
|
||||
*/
|
||||
int aes_setkey_dec( aes_context *ctx, const unsigned char *key,
|
||||
unsigned int keysize );
|
||||
|
||||
/**
|
||||
* \brief AES-ECB block encryption/decryption
|
||||
*
|
||||
* \param ctx AES context
|
||||
* \param mode AES_ENCRYPT or AES_DECRYPT
|
||||
* \param input 16-byte input block
|
||||
* \param output 16-byte output block
|
||||
*
|
||||
* \return 0 if successful
|
||||
*/
|
||||
int aes_crypt_ecb( aes_context *ctx,
|
||||
int mode,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] );
|
||||
|
||||
#if defined(POLARSSL_CIPHER_MODE_CBC)
|
||||
/**
|
||||
* \brief AES-CBC buffer encryption/decryption
|
||||
* Length should be a multiple of the block
|
||||
* size (16 bytes)
|
||||
*
|
||||
* \param ctx AES context
|
||||
* \param mode AES_ENCRYPT or AES_DECRYPT
|
||||
* \param length length of the input data
|
||||
* \param iv initialization vector (updated after use)
|
||||
* \param input buffer holding the input data
|
||||
* \param output buffer holding the output data
|
||||
*
|
||||
* \return 0 if successful, or POLARSSL_ERR_AES_INVALID_INPUT_LENGTH
|
||||
*/
|
||||
int aes_crypt_cbc( aes_context *ctx,
|
||||
int mode,
|
||||
size_t length,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output );
|
||||
#endif /* POLARSSL_CIPHER_MODE_CBC */
|
||||
|
||||
#if defined(POLARSSL_CIPHER_MODE_CFB)
|
||||
/**
|
||||
* \brief AES-CFB128 buffer encryption/decryption.
|
||||
*
|
||||
* Note: Due to the nature of CFB you should use the same key schedule for
|
||||
* both encryption and decryption. So a context initialized with
|
||||
* aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
|
||||
*
|
||||
* \param ctx AES context
|
||||
* \param mode AES_ENCRYPT or AES_DECRYPT
|
||||
* \param length length of the input data
|
||||
* \param iv_off offset in IV (updated after use)
|
||||
* \param iv initialization vector (updated after use)
|
||||
* \param input buffer holding the input data
|
||||
* \param output buffer holding the output data
|
||||
*
|
||||
* \return 0 if successful
|
||||
*/
|
||||
int aes_crypt_cfb128( aes_context *ctx,
|
||||
int mode,
|
||||
size_t length,
|
||||
size_t *iv_off,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output );
|
||||
|
||||
/**
|
||||
* \brief AES-CFB8 buffer encryption/decryption.
|
||||
*
|
||||
* Note: Due to the nature of CFB you should use the same key schedule for
|
||||
* both encryption and decryption. So a context initialized with
|
||||
* aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
|
||||
*
|
||||
* \param ctx AES context
|
||||
* \param mode AES_ENCRYPT or AES_DECRYPT
|
||||
* \param length length of the input data
|
||||
* \param iv initialization vector (updated after use)
|
||||
* \param input buffer holding the input data
|
||||
* \param output buffer holding the output data
|
||||
*
|
||||
* \return 0 if successful
|
||||
*/
|
||||
int aes_crypt_cfb8( aes_context *ctx,
|
||||
int mode,
|
||||
size_t length,
|
||||
unsigned char iv[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output );
|
||||
#endif /*POLARSSL_CIPHER_MODE_CFB */
|
||||
|
||||
#if defined(POLARSSL_CIPHER_MODE_CTR)
|
||||
/**
|
||||
* \brief AES-CTR buffer encryption/decryption
|
||||
*
|
||||
* Warning: You have to keep the maximum use of your counter in mind!
|
||||
*
|
||||
* Note: Due to the nature of CTR you should use the same key schedule for
|
||||
* both encryption and decryption. So a context initialized with
|
||||
* aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
|
||||
*
|
||||
* \param ctx AES context
|
||||
* \param length The length of the data
|
||||
* \param nc_off The offset in the current stream_block (for resuming
|
||||
* within current cipher stream). The offset pointer to
|
||||
* should be 0 at the start of a stream.
|
||||
* \param nonce_counter The 128-bit nonce and counter.
|
||||
* \param stream_block The saved stream-block for resuming. Is overwritten
|
||||
* by the function.
|
||||
* \param input The input data stream
|
||||
* \param output The output data stream
|
||||
*
|
||||
* \return 0 if successful
|
||||
*/
|
||||
int aes_crypt_ctr( aes_context *ctx,
|
||||
size_t length,
|
||||
size_t *nc_off,
|
||||
unsigned char nonce_counter[16],
|
||||
unsigned char stream_block[16],
|
||||
const unsigned char *input,
|
||||
unsigned char *output );
|
||||
#endif /* POLARSSL_CIPHER_MODE_CTR */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#else /* POLARSSL_AES_ALT */
|
||||
#include "aes_alt.h"
|
||||
#endif /* POLARSSL_AES_ALT */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Checkup routine
|
||||
*
|
||||
* \return 0 if successful, or 1 if the test failed
|
||||
*/
|
||||
int aes_self_test( int verbose );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* aes.h */
|
103
lib/aes_faster_c/wrapper.cpp
Normal file
@ -0,0 +1,103 @@
|
||||
#include "aes.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#if defined(AES256) && (AES256 == 1)
|
||||
#define AES_KEYSIZE 256
|
||||
#elif defined(AES192) && (AES192 == 1)
|
||||
#define AES_KEYSIZE 192
|
||||
#else
|
||||
#define AES_KEYSIZE 128
|
||||
#endif
|
||||
|
||||
|
||||
void AES_ECB_encrypt_buffer(const uint8_t* input, const uint8_t* key, uint8_t *output)
|
||||
{
|
||||
static aes_context ctx;
|
||||
if(key!=0)
|
||||
{
|
||||
aes_init( &ctx);
|
||||
aes_setkey_enc(&ctx,key,AES_KEYSIZE);
|
||||
}
|
||||
int ret=aes_crypt_ecb( &ctx, AES_ENCRYPT, (const unsigned char*)input,(unsigned char*) output );
|
||||
assert(ret==0);
|
||||
return ;
|
||||
}
|
||||
void AES_ECB_decrypt_buffer(const uint8_t* input, const uint8_t* key, uint8_t *output)
|
||||
{
|
||||
static aes_context ctx;
|
||||
if(key!=0)
|
||||
{
|
||||
aes_init( &ctx);
|
||||
aes_setkey_dec(&ctx,key,AES_KEYSIZE);
|
||||
}
|
||||
int ret=aes_crypt_ecb( &ctx, AES_DECRYPT, (const unsigned char*)input,(unsigned char*) output );
|
||||
assert(ret==0);
|
||||
return ;
|
||||
}
|
||||
|
||||
void AES_CBC_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)
|
||||
{
|
||||
static aes_context ctx;
|
||||
|
||||
char tmp_iv[16];
|
||||
if(key!=0)
|
||||
{
|
||||
aes_init( &ctx);
|
||||
aes_setkey_enc(&ctx,key,AES_KEYSIZE);
|
||||
}
|
||||
memcpy(tmp_iv,iv,16);
|
||||
int ret=aes_crypt_cbc( &ctx, AES_ENCRYPT, length, (unsigned char* )tmp_iv, (const unsigned char*)input,(unsigned char*) output );
|
||||
assert(ret==0);
|
||||
return ;
|
||||
}
|
||||
void AES_CBC_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)
|
||||
{
|
||||
static aes_context ctx;
|
||||
|
||||
char tmp_iv[16];
|
||||
if(key!=0)
|
||||
{
|
||||
aes_init( &ctx);
|
||||
aes_setkey_dec(&ctx,key,AES_KEYSIZE);
|
||||
}
|
||||
memcpy(tmp_iv,iv,16);
|
||||
int ret=aes_crypt_cbc( &ctx,AES_DECRYPT, length, (unsigned char*)tmp_iv, (const unsigned char*)input, (unsigned char*) output );
|
||||
assert(ret==0);
|
||||
}
|
||||
|
||||
void AES_CFB_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)
|
||||
{
|
||||
static aes_context ctx;
|
||||
|
||||
char tmp_iv[16];
|
||||
if(key!=0)
|
||||
{
|
||||
aes_init( &ctx);
|
||||
aes_setkey_enc(&ctx,key,AES_KEYSIZE);
|
||||
}
|
||||
memcpy(tmp_iv,iv,16);
|
||||
size_t offset=0;
|
||||
int ret=aes_crypt_cfb128( &ctx, AES_ENCRYPT, length,&offset, (unsigned char* )tmp_iv, (const unsigned char*)input,(unsigned char*) output );
|
||||
assert(ret==0);
|
||||
return ;
|
||||
}
|
||||
void AES_CFB_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv)
|
||||
{
|
||||
static aes_context ctx;
|
||||
|
||||
char tmp_iv[16];
|
||||
if(key!=0)
|
||||
{
|
||||
aes_init( &ctx);
|
||||
aes_setkey_enc(&ctx,key,AES_KEYSIZE);// its aes_setkey_enc again, no typo
|
||||
}
|
||||
memcpy(tmp_iv,iv,16);
|
||||
size_t offset=0;
|
||||
int ret=aes_crypt_cfb128( &ctx,AES_DECRYPT, length,&offset, (unsigned char*)tmp_iv, (const unsigned char*)input, (unsigned char*) output );
|
||||
assert(ret==0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
176
lib/md5.c
@ -1,176 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
/*
|
||||
* this file comes from https://github.com/pod32g/MD5/blob/master/md5.c
|
||||
*/
|
||||
|
||||
// Constants are the integer part of the sines of integers (in radians) * 2^32.
|
||||
const uint32_t k[64] = {
|
||||
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee ,
|
||||
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501 ,
|
||||
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be ,
|
||||
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821 ,
|
||||
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa ,
|
||||
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8 ,
|
||||
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed ,
|
||||
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a ,
|
||||
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c ,
|
||||
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70 ,
|
||||
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05 ,
|
||||
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665 ,
|
||||
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039 ,
|
||||
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1 ,
|
||||
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1 ,
|
||||
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 };
|
||||
|
||||
// r specifies the per-round shift amounts
|
||||
const uint32_t r[] = {7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
|
||||
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
|
||||
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
|
||||
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21};
|
||||
|
||||
// leftrotate function definition
|
||||
#define LEFTROTATE(x, c) (((x) << (c)) | ((x) >> (32 - (c))))
|
||||
|
||||
void to_bytes(uint32_t val, uint8_t *bytes)
|
||||
{
|
||||
bytes[0] = (uint8_t) val;
|
||||
bytes[1] = (uint8_t) (val >> 8);
|
||||
bytes[2] = (uint8_t) (val >> 16);
|
||||
bytes[3] = (uint8_t) (val >> 24);
|
||||
}
|
||||
|
||||
uint32_t to_int32(const uint8_t *bytes)
|
||||
{
|
||||
return (uint32_t) bytes[0]
|
||||
| ((uint32_t) bytes[1] << 8)
|
||||
| ((uint32_t) bytes[2] << 16)
|
||||
| ((uint32_t) bytes[3] << 24);
|
||||
}
|
||||
|
||||
void md5(const uint8_t *initial_msg, size_t initial_len, uint8_t *digest) {
|
||||
|
||||
// These vars will contain the hash
|
||||
uint32_t h0, h1, h2, h3;
|
||||
|
||||
// Message (to prepare)
|
||||
uint8_t *msg = NULL;
|
||||
|
||||
size_t new_len, offset;
|
||||
uint32_t w[16];
|
||||
uint32_t a, b, c, d, i, f, g, temp;
|
||||
|
||||
// Initialize variables - simple count in nibbles:
|
||||
h0 = 0x67452301;
|
||||
h1 = 0xefcdab89;
|
||||
h2 = 0x98badcfe;
|
||||
h3 = 0x10325476;
|
||||
|
||||
//Pre-processing:
|
||||
//append "1" bit to message
|
||||
//append "0" bits until message length in bits ≡ 448 (mod 512)
|
||||
//append length mod (2^64) to message
|
||||
|
||||
for (new_len = initial_len + 1; new_len % (512/8) != 448/8; new_len++)
|
||||
;
|
||||
|
||||
uint8_t buf[new_len + 8];
|
||||
msg = buf;//(uint8_t*)malloc(new_len + 8);
|
||||
memcpy(msg, initial_msg, initial_len);
|
||||
msg[initial_len] = 0x80; // append the "1" bit; most significant bit is "first"
|
||||
for (offset = initial_len + 1; offset < new_len; offset++)
|
||||
msg[offset] = 0; // append "0" bits
|
||||
|
||||
// append the len in bits at the end of the buffer.
|
||||
to_bytes(initial_len*8, msg + new_len);
|
||||
// initial_len>>29 == initial_len*8>>32, but avoids overflow.
|
||||
to_bytes(initial_len>>29, msg + new_len + 4);
|
||||
|
||||
// Process the message in successive 512-bit chunks:
|
||||
//for each 512-bit chunk of message:
|
||||
for(offset=0; offset<new_len; offset += (512/8)) {
|
||||
|
||||
// break chunk into sixteen 32-bit words w[j], 0 ≤ j ≤ 15
|
||||
for (i = 0; i < 16; i++)
|
||||
w[i] = to_int32(msg + offset + i*4);
|
||||
|
||||
// Initialize hash value for this chunk:
|
||||
a = h0;
|
||||
b = h1;
|
||||
c = h2;
|
||||
d = h3;
|
||||
|
||||
// Main loop:
|
||||
for(i = 0; i<64; i++) {
|
||||
|
||||
if (i < 16) {
|
||||
f = (b & c) | ((~b) & d);
|
||||
g = i;
|
||||
} else if (i < 32) {
|
||||
f = (d & b) | ((~d) & c);
|
||||
g = (5*i + 1) % 16;
|
||||
} else if (i < 48) {
|
||||
f = b ^ c ^ d;
|
||||
g = (3*i + 5) % 16;
|
||||
} else {
|
||||
f = c ^ (b | (~d));
|
||||
g = (7*i) % 16;
|
||||
}
|
||||
|
||||
temp = d;
|
||||
d = c;
|
||||
c = b;
|
||||
b = b + LEFTROTATE((a + f + k[i] + w[g]), r[i]);
|
||||
a = temp;
|
||||
|
||||
}
|
||||
|
||||
// Add this chunk's hash to result so far:
|
||||
h0 += a;
|
||||
h1 += b;
|
||||
h2 += c;
|
||||
h3 += d;
|
||||
|
||||
}
|
||||
|
||||
// cleanup
|
||||
//free(msg);
|
||||
|
||||
//var char digest[16] := h0 append h1 append h2 append h3 //(Output is in little-endian)
|
||||
to_bytes(h0, digest);
|
||||
to_bytes(h1, digest + 4);
|
||||
to_bytes(h2, digest + 8);
|
||||
to_bytes(h3, digest + 12);
|
||||
}
|
||||
/*
|
||||
int main(int argc, char **argv) {
|
||||
char *msg;
|
||||
size_t len;
|
||||
int i;
|
||||
uint8_t result[16];
|
||||
|
||||
if (argc < 2) {
|
||||
printf("usage: %s 'string'\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
msg = argv[1];
|
||||
|
||||
len = strlen(msg);
|
||||
|
||||
// benchmark
|
||||
for (i = 0; i < 1000000; i++) {
|
||||
md5((uint8_t*)msg, len, result);
|
||||
}
|
||||
|
||||
// display result
|
||||
for (i = 0; i < 16; i++)
|
||||
printf("%2.2x", result[i]);
|
||||
puts("");
|
||||
|
||||
return 0;
|
||||
}
|
||||
*/
|
403
lib/md5.cpp
Executable file
@ -0,0 +1,403 @@
|
||||
/*
|
||||
* This file is adapted from PolarSSL 1.3.19 (GPL)
|
||||
*/
|
||||
|
||||
/*
|
||||
* RFC 1321 compliant MD5 implementation
|
||||
*
|
||||
* Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
|
||||
*
|
||||
* This file is part of mbed TLS (https://tls.mbed.org)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/*
|
||||
* The MD5 algorithm was designed by Ron Rivest in 1991.
|
||||
*
|
||||
* http://www.ietf.org/rfc/rfc1321.txt
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t total[2]; /*!< number of bytes processed */
|
||||
uint32_t state[4]; /*!< intermediate digest state */
|
||||
unsigned char buffer[64]; /*!< data block being processed */
|
||||
|
||||
unsigned char ipad[64]; /*!< HMAC: inner padding */
|
||||
unsigned char opad[64]; /*!< HMAC: outer padding */
|
||||
}
|
||||
md5_context;
|
||||
|
||||
/* Implementation that should never be optimized out by the compiler */
|
||||
static void polarssl_zeroize( void *v, size_t n ) {
|
||||
volatile unsigned char *p = (unsigned char *) v; while( n-- ) *p++ = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 32-bit integer manipulation macros (little endian)
|
||||
*/
|
||||
#ifndef GET_UINT32_LE
|
||||
#define GET_UINT32_LE(n,b,i) \
|
||||
{ \
|
||||
(n) = ( (uint32_t) (b)[(i) ] ) \
|
||||
| ( (uint32_t) (b)[(i) + 1] << 8 ) \
|
||||
| ( (uint32_t) (b)[(i) + 2] << 16 ) \
|
||||
| ( (uint32_t) (b)[(i) + 3] << 24 ); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef PUT_UINT32_LE
|
||||
#define PUT_UINT32_LE(n,b,i) \
|
||||
{ \
|
||||
(b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
|
||||
(b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
|
||||
(b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \
|
||||
(b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \
|
||||
}
|
||||
#endif
|
||||
|
||||
void md5_init( md5_context *ctx )
|
||||
{
|
||||
memset( ctx, 0, sizeof( md5_context ) );
|
||||
}
|
||||
|
||||
void md5_free( md5_context *ctx )
|
||||
{
|
||||
if( ctx == NULL )
|
||||
return;
|
||||
|
||||
polarssl_zeroize( ctx, sizeof( md5_context ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* MD5 context setup
|
||||
*/
|
||||
void md5_starts( md5_context *ctx )
|
||||
{
|
||||
ctx->total[0] = 0;
|
||||
ctx->total[1] = 0;
|
||||
|
||||
ctx->state[0] = 0x67452301;
|
||||
ctx->state[1] = 0xEFCDAB89;
|
||||
ctx->state[2] = 0x98BADCFE;
|
||||
ctx->state[3] = 0x10325476;
|
||||
}
|
||||
|
||||
void md5_process( md5_context *ctx, const unsigned char data[64] )
|
||||
{
|
||||
uint32_t X[16], A, B, C, D;
|
||||
|
||||
GET_UINT32_LE( X[ 0], data, 0 );
|
||||
GET_UINT32_LE( X[ 1], data, 4 );
|
||||
GET_UINT32_LE( X[ 2], data, 8 );
|
||||
GET_UINT32_LE( X[ 3], data, 12 );
|
||||
GET_UINT32_LE( X[ 4], data, 16 );
|
||||
GET_UINT32_LE( X[ 5], data, 20 );
|
||||
GET_UINT32_LE( X[ 6], data, 24 );
|
||||
GET_UINT32_LE( X[ 7], data, 28 );
|
||||
GET_UINT32_LE( X[ 8], data, 32 );
|
||||
GET_UINT32_LE( X[ 9], data, 36 );
|
||||
GET_UINT32_LE( X[10], data, 40 );
|
||||
GET_UINT32_LE( X[11], data, 44 );
|
||||
GET_UINT32_LE( X[12], data, 48 );
|
||||
GET_UINT32_LE( X[13], data, 52 );
|
||||
GET_UINT32_LE( X[14], data, 56 );
|
||||
GET_UINT32_LE( X[15], data, 60 );
|
||||
|
||||
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
|
||||
|
||||
#define P(a,b,c,d,k,s,t) \
|
||||
{ \
|
||||
a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
|
||||
}
|
||||
|
||||
A = ctx->state[0];
|
||||
B = ctx->state[1];
|
||||
C = ctx->state[2];
|
||||
D = ctx->state[3];
|
||||
|
||||
#define F(x,y,z) (z ^ (x & (y ^ z)))
|
||||
|
||||
P( A, B, C, D, 0, 7, 0xD76AA478 );
|
||||
P( D, A, B, C, 1, 12, 0xE8C7B756 );
|
||||
P( C, D, A, B, 2, 17, 0x242070DB );
|
||||
P( B, C, D, A, 3, 22, 0xC1BDCEEE );
|
||||
P( A, B, C, D, 4, 7, 0xF57C0FAF );
|
||||
P( D, A, B, C, 5, 12, 0x4787C62A );
|
||||
P( C, D, A, B, 6, 17, 0xA8304613 );
|
||||
P( B, C, D, A, 7, 22, 0xFD469501 );
|
||||
P( A, B, C, D, 8, 7, 0x698098D8 );
|
||||
P( D, A, B, C, 9, 12, 0x8B44F7AF );
|
||||
P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
|
||||
P( B, C, D, A, 11, 22, 0x895CD7BE );
|
||||
P( A, B, C, D, 12, 7, 0x6B901122 );
|
||||
P( D, A, B, C, 13, 12, 0xFD987193 );
|
||||
P( C, D, A, B, 14, 17, 0xA679438E );
|
||||
P( B, C, D, A, 15, 22, 0x49B40821 );
|
||||
|
||||
#undef F
|
||||
|
||||
#define F(x,y,z) (y ^ (z & (x ^ y)))
|
||||
|
||||
P( A, B, C, D, 1, 5, 0xF61E2562 );
|
||||
P( D, A, B, C, 6, 9, 0xC040B340 );
|
||||
P( C, D, A, B, 11, 14, 0x265E5A51 );
|
||||
P( B, C, D, A, 0, 20, 0xE9B6C7AA );
|
||||
P( A, B, C, D, 5, 5, 0xD62F105D );
|
||||
P( D, A, B, C, 10, 9, 0x02441453 );
|
||||
P( C, D, A, B, 15, 14, 0xD8A1E681 );
|
||||
P( B, C, D, A, 4, 20, 0xE7D3FBC8 );
|
||||
P( A, B, C, D, 9, 5, 0x21E1CDE6 );
|
||||
P( D, A, B, C, 14, 9, 0xC33707D6 );
|
||||
P( C, D, A, B, 3, 14, 0xF4D50D87 );
|
||||
P( B, C, D, A, 8, 20, 0x455A14ED );
|
||||
P( A, B, C, D, 13, 5, 0xA9E3E905 );
|
||||
P( D, A, B, C, 2, 9, 0xFCEFA3F8 );
|
||||
P( C, D, A, B, 7, 14, 0x676F02D9 );
|
||||
P( B, C, D, A, 12, 20, 0x8D2A4C8A );
|
||||
|
||||
#undef F
|
||||
|
||||
#define F(x,y,z) (x ^ y ^ z)
|
||||
|
||||
P( A, B, C, D, 5, 4, 0xFFFA3942 );
|
||||
P( D, A, B, C, 8, 11, 0x8771F681 );
|
||||
P( C, D, A, B, 11, 16, 0x6D9D6122 );
|
||||
P( B, C, D, A, 14, 23, 0xFDE5380C );
|
||||
P( A, B, C, D, 1, 4, 0xA4BEEA44 );
|
||||
P( D, A, B, C, 4, 11, 0x4BDECFA9 );
|
||||
P( C, D, A, B, 7, 16, 0xF6BB4B60 );
|
||||
P( B, C, D, A, 10, 23, 0xBEBFBC70 );
|
||||
P( A, B, C, D, 13, 4, 0x289B7EC6 );
|
||||
P( D, A, B, C, 0, 11, 0xEAA127FA );
|
||||
P( C, D, A, B, 3, 16, 0xD4EF3085 );
|
||||
P( B, C, D, A, 6, 23, 0x04881D05 );
|
||||
P( A, B, C, D, 9, 4, 0xD9D4D039 );
|
||||
P( D, A, B, C, 12, 11, 0xE6DB99E5 );
|
||||
P( C, D, A, B, 15, 16, 0x1FA27CF8 );
|
||||
P( B, C, D, A, 2, 23, 0xC4AC5665 );
|
||||
|
||||
#undef F
|
||||
|
||||
#define F(x,y,z) (y ^ (x | ~z))
|
||||
|
||||
P( A, B, C, D, 0, 6, 0xF4292244 );
|
||||
P( D, A, B, C, 7, 10, 0x432AFF97 );
|
||||
P( C, D, A, B, 14, 15, 0xAB9423A7 );
|
||||
P( B, C, D, A, 5, 21, 0xFC93A039 );
|
||||
P( A, B, C, D, 12, 6, 0x655B59C3 );
|
||||
P( D, A, B, C, 3, 10, 0x8F0CCC92 );
|
||||
P( C, D, A, B, 10, 15, 0xFFEFF47D );
|
||||
P( B, C, D, A, 1, 21, 0x85845DD1 );
|
||||
P( A, B, C, D, 8, 6, 0x6FA87E4F );
|
||||
P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
|
||||
P( C, D, A, B, 6, 15, 0xA3014314 );
|
||||
P( B, C, D, A, 13, 21, 0x4E0811A1 );
|
||||
P( A, B, C, D, 4, 6, 0xF7537E82 );
|
||||
P( D, A, B, C, 11, 10, 0xBD3AF235 );
|
||||
P( C, D, A, B, 2, 15, 0x2AD7D2BB );
|
||||
P( B, C, D, A, 9, 21, 0xEB86D391 );
|
||||
|
||||
#undef F
|
||||
|
||||
ctx->state[0] += A;
|
||||
ctx->state[1] += B;
|
||||
ctx->state[2] += C;
|
||||
ctx->state[3] += D;
|
||||
}
|
||||
|
||||
/*
|
||||
* MD5 process buffer
|
||||
*/
|
||||
void md5_update( md5_context *ctx, const unsigned char *input, size_t ilen )
|
||||
{
|
||||
size_t fill;
|
||||
uint32_t left;
|
||||
|
||||
if( ilen == 0 )
|
||||
return;
|
||||
|
||||
left = ctx->total[0] & 0x3F;
|
||||
fill = 64 - left;
|
||||
|
||||
ctx->total[0] += (uint32_t) ilen;
|
||||
ctx->total[0] &= 0xFFFFFFFF;
|
||||
|
||||
if( ctx->total[0] < (uint32_t) ilen )
|
||||
ctx->total[1]++;
|
||||
|
||||
if( left && ilen >= fill )
|
||||
{
|
||||
memcpy( (void *) (ctx->buffer + left), input, fill );
|
||||
md5_process( ctx, ctx->buffer );
|
||||
input += fill;
|
||||
ilen -= fill;
|
||||
left = 0;
|
||||
}
|
||||
|
||||
while( ilen >= 64 )
|
||||
{
|
||||
md5_process( ctx, input );
|
||||
input += 64;
|
||||
ilen -= 64;
|
||||
}
|
||||
|
||||
if( ilen > 0 )
|
||||
{
|
||||
memcpy( (void *) (ctx->buffer + left), input, ilen );
|
||||
}
|
||||
}
|
||||
|
||||
static const unsigned char md5_padding[64] =
|
||||
{
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/*
|
||||
* MD5 final digest
|
||||
*/
|
||||
void md5_finish( md5_context *ctx, unsigned char output[16] )
|
||||
{
|
||||
uint32_t last, padn;
|
||||
uint32_t high, low;
|
||||
unsigned char msglen[8];
|
||||
|
||||
high = ( ctx->total[0] >> 29 )
|
||||
| ( ctx->total[1] << 3 );
|
||||
low = ( ctx->total[0] << 3 );
|
||||
|
||||
PUT_UINT32_LE( low, msglen, 0 );
|
||||
PUT_UINT32_LE( high, msglen, 4 );
|
||||
|
||||
last = ctx->total[0] & 0x3F;
|
||||
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
|
||||
|
||||
md5_update( ctx, md5_padding, padn );
|
||||
md5_update( ctx, msglen, 8 );
|
||||
|
||||
PUT_UINT32_LE( ctx->state[0], output, 0 );
|
||||
PUT_UINT32_LE( ctx->state[1], output, 4 );
|
||||
PUT_UINT32_LE( ctx->state[2], output, 8 );
|
||||
PUT_UINT32_LE( ctx->state[3], output, 12 );
|
||||
}
|
||||
|
||||
/*
|
||||
* output = MD5( input buffer )
|
||||
*/
|
||||
void md5( const unsigned char *input, size_t ilen, unsigned char output[16] )
|
||||
{
|
||||
/*static md5_context ctx;
|
||||
static int done=0;
|
||||
if(done==0)
|
||||
{
|
||||
md5_init( &ctx );
|
||||
done=1;
|
||||
}*/
|
||||
md5_context ctx;
|
||||
md5_init( &ctx );
|
||||
md5_starts( &ctx );
|
||||
md5_update( &ctx, input, ilen );
|
||||
md5_finish( &ctx, output );
|
||||
md5_free( &ctx );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* MD5 HMAC context setup
|
||||
*/
|
||||
void md5_hmac_starts( md5_context *ctx, const unsigned char *key,
|
||||
size_t keylen )
|
||||
{
|
||||
size_t i;
|
||||
unsigned char sum[16];
|
||||
|
||||
if( keylen > 64 )
|
||||
{
|
||||
md5( key, keylen, sum );
|
||||
keylen = 16;
|
||||
key = sum;
|
||||
}
|
||||
|
||||
memset( ctx->ipad, 0x36, 64 );
|
||||
memset( ctx->opad, 0x5C, 64 );
|
||||
|
||||
for( i = 0; i < keylen; i++ )
|
||||
{
|
||||
ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
|
||||
ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
|
||||
}
|
||||
|
||||
md5_starts( ctx );
|
||||
md5_update( ctx, ctx->ipad, 64 );
|
||||
|
||||
polarssl_zeroize( sum, sizeof( sum ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* MD5 HMAC process buffer
|
||||
*/
|
||||
void md5_hmac_update( md5_context *ctx, const unsigned char *input,
|
||||
size_t ilen )
|
||||
{
|
||||
md5_update( ctx, input, ilen );
|
||||
}
|
||||
|
||||
/*
|
||||
* MD5 HMAC final digest
|
||||
*/
|
||||
void md5_hmac_finish( md5_context *ctx, unsigned char output[16] )
|
||||
{
|
||||
unsigned char tmpbuf[16];
|
||||
|
||||
md5_finish( ctx, tmpbuf );
|
||||
md5_starts( ctx );
|
||||
md5_update( ctx, ctx->opad, 64 );
|
||||
md5_update( ctx, tmpbuf, 16 );
|
||||
md5_finish( ctx, output );
|
||||
|
||||
polarssl_zeroize( tmpbuf, sizeof( tmpbuf ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* MD5 HMAC context reset
|
||||
*/
|
||||
void md5_hmac_reset( md5_context *ctx )
|
||||
{
|
||||
md5_starts( ctx );
|
||||
md5_update( ctx, ctx->ipad, 64 );
|
||||
}
|
||||
|
||||
/*
|
||||
* output = HMAC-MD5( hmac key, input buffer )
|
||||
*/
|
||||
void md5_hmac( const unsigned char *key, size_t keylen,
|
||||
const unsigned char *input, size_t ilen,
|
||||
unsigned char output[16] )
|
||||
{
|
||||
md5_context ctx;
|
||||
|
||||
md5_init( &ctx );
|
||||
md5_hmac_starts( &ctx, key, keylen );
|
||||
md5_hmac_update( &ctx, input, ilen );
|
||||
md5_hmac_finish( &ctx, output );
|
||||
md5_free( &ctx );
|
||||
}
|
@ -1,9 +1,7 @@
|
||||
#ifndef _MD5_H_
|
||||
#define _MD5_H_
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifndef UDP2RAW_MD5_H_
|
||||
#define UDP2RAW_MD5_H_
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
void md5(const uint8_t *initial_msg, size_t initial_len, uint8_t *digest);
|
||||
|
||||
|
865
lib/pbkdf2-sha1.cpp
Normal file
@ -0,0 +1,865 @@
|
||||
/*
|
||||
this file is from https://github.com/kholia/PKCS5_PBKDF2
|
||||
|
||||
*
|
||||
* FIPS-180-1 compliant SHA-1 implementation
|
||||
*
|
||||
* Copyright (C) 2006-2010, Brainspark B.V.
|
||||
*
|
||||
* This file is part of PolarSSL (http://www.polarssl.org)
|
||||
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* The SHA-1 standard was published by NIST in 1993.
|
||||
*
|
||||
* http://www.itl.nist.gov/fipspubs/fip180-1.htm
|
||||
*
|
||||
* Copyright 2012 Mathias Olsson mathias@kompetensum.com
|
||||
*
|
||||
* This file is dual licensed as either GPL version 2 or Apache License 2.0 at your choice
|
||||
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* http://www.apache.org/licenses/
|
||||
*
|
||||
* Note that PolarSSL uses GPL with a FOSS License Exception */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(TEST) ||defined(DEBUG)
|
||||
#undef TEST
|
||||
#undef DEBUG
|
||||
#warning "undefined TEST/DEBUG"
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
unsigned long total[2]; /*!< number of bytes processed */
|
||||
unsigned long state[5]; /*!< intermediate digest state */
|
||||
unsigned char buffer[64]; /*!< data block being processed */
|
||||
|
||||
unsigned char ipad[64]; /*!< HMAC: inner padding */
|
||||
unsigned char opad[64]; /*!< HMAC: outer padding */
|
||||
} sha1_context;
|
||||
|
||||
/*
|
||||
* 32-bit integer manipulation macros (big endian)
|
||||
*/
|
||||
#ifndef GET_ULONG_BE
|
||||
#define GET_ULONG_BE(n,b,i) \
|
||||
{ \
|
||||
(n) = ( (unsigned long) (b)[(i) ] << 24 ) \
|
||||
| ( (unsigned long) (b)[(i) + 1] << 16 ) \
|
||||
| ( (unsigned long) (b)[(i) + 2] << 8 ) \
|
||||
| ( (unsigned long) (b)[(i) + 3] ); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef PUT_ULONG_BE
|
||||
#define PUT_ULONG_BE(n,b,i) \
|
||||
{ \
|
||||
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
|
||||
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
|
||||
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
|
||||
(b)[(i) + 3] = (unsigned char) ( (n) ); \
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* SHA-1 context setup
|
||||
*/
|
||||
void sha1_starts(sha1_context * ctx)
|
||||
{
|
||||
ctx->total[0] = 0;
|
||||
ctx->total[1] = 0;
|
||||
|
||||
ctx->state[0] = 0x67452301;
|
||||
ctx->state[1] = 0xEFCDAB89;
|
||||
ctx->state[2] = 0x98BADCFE;
|
||||
ctx->state[3] = 0x10325476;
|
||||
ctx->state[4] = 0xC3D2E1F0;
|
||||
}
|
||||
|
||||
static void sha1_process(sha1_context * ctx, const unsigned char data[64])
|
||||
{
|
||||
unsigned long temp, W[16], A, B, C, D, E;
|
||||
|
||||
GET_ULONG_BE(W[0], data, 0);
|
||||
GET_ULONG_BE(W[1], data, 4);
|
||||
GET_ULONG_BE(W[2], data, 8);
|
||||
GET_ULONG_BE(W[3], data, 12);
|
||||
GET_ULONG_BE(W[4], data, 16);
|
||||
GET_ULONG_BE(W[5], data, 20);
|
||||
GET_ULONG_BE(W[6], data, 24);
|
||||
GET_ULONG_BE(W[7], data, 28);
|
||||
GET_ULONG_BE(W[8], data, 32);
|
||||
GET_ULONG_BE(W[9], data, 36);
|
||||
GET_ULONG_BE(W[10], data, 40);
|
||||
GET_ULONG_BE(W[11], data, 44);
|
||||
GET_ULONG_BE(W[12], data, 48);
|
||||
GET_ULONG_BE(W[13], data, 52);
|
||||
GET_ULONG_BE(W[14], data, 56);
|
||||
GET_ULONG_BE(W[15], data, 60);
|
||||
|
||||
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
|
||||
|
||||
#define R(t) \
|
||||
( \
|
||||
temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \
|
||||
W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \
|
||||
( W[t & 0x0F] = S(temp,1) ) \
|
||||
)
|
||||
|
||||
#define P(a,b,c,d,e,x) \
|
||||
{ \
|
||||
e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \
|
||||
}
|
||||
|
||||
A = ctx->state[0];
|
||||
B = ctx->state[1];
|
||||
C = ctx->state[2];
|
||||
D = ctx->state[3];
|
||||
E = ctx->state[4];
|
||||
|
||||
#define F(x,y,z) (z ^ (x & (y ^ z)))
|
||||
#define K 0x5A827999
|
||||
|
||||
P(A, B, C, D, E, W[0]);
|
||||
P(E, A, B, C, D, W[1]);
|
||||
P(D, E, A, B, C, W[2]);
|
||||
P(C, D, E, A, B, W[3]);
|
||||
P(B, C, D, E, A, W[4]);
|
||||
P(A, B, C, D, E, W[5]);
|
||||
P(E, A, B, C, D, W[6]);
|
||||
P(D, E, A, B, C, W[7]);
|
||||
P(C, D, E, A, B, W[8]);
|
||||
P(B, C, D, E, A, W[9]);
|
||||
P(A, B, C, D, E, W[10]);
|
||||
P(E, A, B, C, D, W[11]);
|
||||
P(D, E, A, B, C, W[12]);
|
||||
P(C, D, E, A, B, W[13]);
|
||||
P(B, C, D, E, A, W[14]);
|
||||
P(A, B, C, D, E, W[15]);
|
||||
P(E, A, B, C, D, R(16));
|
||||
P(D, E, A, B, C, R(17));
|
||||
P(C, D, E, A, B, R(18));
|
||||
P(B, C, D, E, A, R(19));
|
||||
|
||||
#undef K
|
||||
#undef F
|
||||
|
||||
#define F(x,y,z) (x ^ y ^ z)
|
||||
#define K 0x6ED9EBA1
|
||||
|
||||
P(A, B, C, D, E, R(20));
|
||||
P(E, A, B, C, D, R(21));
|
||||
P(D, E, A, B, C, R(22));
|
||||
P(C, D, E, A, B, R(23));
|
||||
P(B, C, D, E, A, R(24));
|
||||
P(A, B, C, D, E, R(25));
|
||||
P(E, A, B, C, D, R(26));
|
||||
P(D, E, A, B, C, R(27));
|
||||
P(C, D, E, A, B, R(28));
|
||||
P(B, C, D, E, A, R(29));
|
||||
P(A, B, C, D, E, R(30));
|
||||
P(E, A, B, C, D, R(31));
|
||||
P(D, E, A, B, C, R(32));
|
||||
P(C, D, E, A, B, R(33));
|
||||
P(B, C, D, E, A, R(34));
|
||||
P(A, B, C, D, E, R(35));
|
||||
P(E, A, B, C, D, R(36));
|
||||
P(D, E, A, B, C, R(37));
|
||||
P(C, D, E, A, B, R(38));
|
||||
P(B, C, D, E, A, R(39));
|
||||
|
||||
#undef K
|
||||
#undef F
|
||||
|
||||
#define F(x,y,z) ((x & y) | (z & (x | y)))
|
||||
#define K 0x8F1BBCDC
|
||||
|
||||
P(A, B, C, D, E, R(40));
|
||||
P(E, A, B, C, D, R(41));
|
||||
P(D, E, A, B, C, R(42));
|
||||
P(C, D, E, A, B, R(43));
|
||||
P(B, C, D, E, A, R(44));
|
||||
P(A, B, C, D, E, R(45));
|
||||
P(E, A, B, C, D, R(46));
|
||||
P(D, E, A, B, C, R(47));
|
||||
P(C, D, E, A, B, R(48));
|
||||
P(B, C, D, E, A, R(49));
|
||||
P(A, B, C, D, E, R(50));
|
||||
P(E, A, B, C, D, R(51));
|
||||
P(D, E, A, B, C, R(52));
|
||||
P(C, D, E, A, B, R(53));
|
||||
P(B, C, D, E, A, R(54));
|
||||
P(A, B, C, D, E, R(55));
|
||||
P(E, A, B, C, D, R(56));
|
||||
P(D, E, A, B, C, R(57));
|
||||
P(C, D, E, A, B, R(58));
|
||||
P(B, C, D, E, A, R(59));
|
||||
|
||||
#undef K
|
||||
#undef F
|
||||
|
||||
#define F(x,y,z) (x ^ y ^ z)
|
||||
#define K 0xCA62C1D6
|
||||
|
||||
P(A, B, C, D, E, R(60));
|
||||
P(E, A, B, C, D, R(61));
|
||||
P(D, E, A, B, C, R(62));
|
||||
P(C, D, E, A, B, R(63));
|
||||
P(B, C, D, E, A, R(64));
|
||||
P(A, B, C, D, E, R(65));
|
||||
P(E, A, B, C, D, R(66));
|
||||
P(D, E, A, B, C, R(67));
|
||||
P(C, D, E, A, B, R(68));
|
||||
P(B, C, D, E, A, R(69));
|
||||
P(A, B, C, D, E, R(70));
|
||||
P(E, A, B, C, D, R(71));
|
||||
P(D, E, A, B, C, R(72));
|
||||
P(C, D, E, A, B, R(73));
|
||||
P(B, C, D, E, A, R(74));
|
||||
P(A, B, C, D, E, R(75));
|
||||
P(E, A, B, C, D, R(76));
|
||||
P(D, E, A, B, C, R(77));
|
||||
P(C, D, E, A, B, R(78));
|
||||
P(B, C, D, E, A, R(79));
|
||||
|
||||
#undef K
|
||||
#undef F
|
||||
|
||||
ctx->state[0] += A;
|
||||
ctx->state[1] += B;
|
||||
ctx->state[2] += C;
|
||||
ctx->state[3] += D;
|
||||
ctx->state[4] += E;
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA-1 process buffer
|
||||
*/
|
||||
void sha1_update(sha1_context * ctx, const unsigned char *input, int ilen)
|
||||
{
|
||||
int fill;
|
||||
unsigned long left;
|
||||
|
||||
if (ilen <= 0)
|
||||
return;
|
||||
|
||||
left = ctx->total[0] & 0x3F;
|
||||
fill = 64 - left;
|
||||
|
||||
ctx->total[0] += (unsigned long) ilen;
|
||||
ctx->total[0] &= 0xFFFFFFFF;
|
||||
|
||||
if (ctx->total[0] < (unsigned long) ilen)
|
||||
ctx->total[1]++;
|
||||
|
||||
if (left && ilen >= fill) {
|
||||
memcpy((void *) (ctx->buffer + left), (void *) input, fill);
|
||||
sha1_process(ctx, ctx->buffer);
|
||||
input += fill;
|
||||
ilen -= fill;
|
||||
left = 0;
|
||||
}
|
||||
|
||||
while (ilen >= 64) {
|
||||
sha1_process(ctx, input);
|
||||
input += 64;
|
||||
ilen -= 64;
|
||||
}
|
||||
|
||||
if (ilen > 0) {
|
||||
memcpy((void *) (ctx->buffer + left), (void *) input, ilen);
|
||||
}
|
||||
}
|
||||
|
||||
static const unsigned char sha1_padding[64] = {
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
/*
|
||||
* SHA-1 final digest
|
||||
*/
|
||||
void sha1_finish(sha1_context * ctx, unsigned char output[20])
|
||||
{
|
||||
unsigned long last, padn;
|
||||
unsigned long high, low;
|
||||
unsigned char msglen[8];
|
||||
|
||||
high = (ctx->total[0] >> 29)
|
||||
| (ctx->total[1] << 3);
|
||||
low = (ctx->total[0] << 3);
|
||||
|
||||
PUT_ULONG_BE(high, msglen, 0);
|
||||
PUT_ULONG_BE(low, msglen, 4);
|
||||
|
||||
last = ctx->total[0] & 0x3F;
|
||||
padn = (last < 56) ? (56 - last) : (120 - last);
|
||||
|
||||
sha1_update(ctx, (unsigned char *) sha1_padding, padn);
|
||||
sha1_update(ctx, msglen, 8);
|
||||
|
||||
PUT_ULONG_BE(ctx->state[0], output, 0);
|
||||
PUT_ULONG_BE(ctx->state[1], output, 4);
|
||||
PUT_ULONG_BE(ctx->state[2], output, 8);
|
||||
PUT_ULONG_BE(ctx->state[3], output, 12);
|
||||
PUT_ULONG_BE(ctx->state[4], output, 16);
|
||||
}
|
||||
|
||||
/*
|
||||
* output = SHA-1( input buffer )
|
||||
*/
|
||||
void sha1(const unsigned char *input, int ilen, unsigned char output[20])
|
||||
{
|
||||
sha1_context ctx;
|
||||
|
||||
sha1_starts(&ctx);
|
||||
sha1_update(&ctx, input, ilen);
|
||||
sha1_finish(&ctx, output);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* SHA-1 HMAC context setup
|
||||
*/
|
||||
void sha1_hmac_starts(sha1_context * ctx, const unsigned char *key, int keylen)
|
||||
{
|
||||
int i;
|
||||
unsigned char sum[20];
|
||||
|
||||
if (keylen > 64) {
|
||||
sha1(key, keylen, sum);
|
||||
keylen = 20;
|
||||
key = sum;
|
||||
}
|
||||
|
||||
memset(ctx->ipad, 0x36, 64);
|
||||
memset(ctx->opad, 0x5C, 64);
|
||||
|
||||
for (i = 0; i < keylen; i++) {
|
||||
ctx->ipad[i] = (unsigned char) (ctx->ipad[i] ^ key[i]);
|
||||
ctx->opad[i] = (unsigned char) (ctx->opad[i] ^ key[i]);
|
||||
}
|
||||
|
||||
sha1_starts(ctx);
|
||||
sha1_update(ctx, ctx->ipad, 64);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA-1 HMAC process buffer
|
||||
*/
|
||||
void sha1_hmac_update(sha1_context * ctx, const unsigned char *input, int ilen)
|
||||
{
|
||||
sha1_update(ctx, input, ilen);
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA-1 HMAC final digest
|
||||
*/
|
||||
void sha1_hmac_finish(sha1_context * ctx, unsigned char output[20])
|
||||
{
|
||||
unsigned char tmpbuf[20];
|
||||
|
||||
sha1_finish(ctx, tmpbuf);
|
||||
sha1_starts(ctx);
|
||||
sha1_update(ctx, ctx->opad, 64);
|
||||
sha1_update(ctx, tmpbuf, 20);
|
||||
sha1_finish(ctx, output);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA1 HMAC context reset
|
||||
*/
|
||||
void sha1_hmac_reset(sha1_context * ctx)
|
||||
{
|
||||
sha1_starts(ctx);
|
||||
sha1_update(ctx, ctx->ipad, 64);
|
||||
}
|
||||
|
||||
/*
|
||||
* output = HMAC-SHA-1( hmac key, input buffer )
|
||||
*/
|
||||
void sha1_hmac(const unsigned char *key, int keylen,
|
||||
const unsigned char *input, int ilen, unsigned char output[20])
|
||||
{
|
||||
sha1_context ctx;
|
||||
|
||||
sha1_hmac_starts(&ctx, key, keylen);
|
||||
sha1_hmac_update(&ctx, input, ilen);
|
||||
sha1_hmac_finish(&ctx, output);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef min
|
||||
#define min( a, b ) ( ((a) < (b)) ? (a) : (b) )
|
||||
#endif
|
||||
|
||||
void PKCS5_PBKDF2_HMAC_SHA1(const unsigned char *password, size_t plen,
|
||||
const unsigned char *salt, size_t slen,
|
||||
const unsigned long iteration_count, const unsigned long key_length,
|
||||
unsigned char *output)
|
||||
{
|
||||
sha1_context ctx;
|
||||
sha1_starts(&ctx);
|
||||
|
||||
// Size of the generated digest
|
||||
unsigned char md_size = 20;
|
||||
unsigned char md1[20];
|
||||
unsigned char work[20];
|
||||
|
||||
unsigned long counter = 1;
|
||||
unsigned long generated_key_length = 0;
|
||||
while (generated_key_length < key_length) {
|
||||
// U1 ends up in md1 and work
|
||||
unsigned char c[4];
|
||||
c[0] = (counter >> 24) & 0xff;
|
||||
c[1] = (counter >> 16) & 0xff;
|
||||
c[2] = (counter >> 8) & 0xff;
|
||||
c[3] = (counter >> 0) & 0xff;
|
||||
|
||||
sha1_hmac_starts(&ctx, password, plen);
|
||||
sha1_hmac_update(&ctx, salt, slen);
|
||||
sha1_hmac_update(&ctx, c, 4);
|
||||
sha1_hmac_finish(&ctx, md1);
|
||||
memcpy(work, md1, md_size);
|
||||
|
||||
unsigned long ic = 1;
|
||||
for (ic = 1; ic < iteration_count; ic++) {
|
||||
// U2 ends up in md1
|
||||
sha1_hmac_starts(&ctx, password, plen);
|
||||
sha1_hmac_update(&ctx, md1, md_size);
|
||||
sha1_hmac_finish(&ctx, md1);
|
||||
// U1 xor U2
|
||||
unsigned long i = 0;
|
||||
for (i = 0; i < md_size; i++) {
|
||||
work[i] ^= md1[i];
|
||||
}
|
||||
// and so on until iteration_count
|
||||
}
|
||||
|
||||
// Copy the generated bytes to the key
|
||||
unsigned long bytes_to_write =
|
||||
min((key_length - generated_key_length), md_size);
|
||||
memcpy(output + generated_key_length, work, bytes_to_write);
|
||||
generated_key_length += bytes_to_write;
|
||||
++counter;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if defined(TEST)
|
||||
/*
|
||||
* FIPS-180-1 test vectors
|
||||
*/
|
||||
static unsigned char sha1_test_buf[3][57] = {
|
||||
{"abc"},
|
||||
{"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"},
|
||||
{""}
|
||||
};
|
||||
|
||||
static const int sha1_test_buflen[3] = {
|
||||
3, 56, 1000
|
||||
};
|
||||
|
||||
static const unsigned char sha1_test_sum[3][20] = {
|
||||
{0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E,
|
||||
0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D},
|
||||
{0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE,
|
||||
0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1},
|
||||
{0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E,
|
||||
0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F}
|
||||
};
|
||||
|
||||
/*
|
||||
* RFC 2202 test vectors
|
||||
*/
|
||||
static unsigned char sha1_hmac_test_key[7][26] = {
|
||||
{"\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
|
||||
"\x0B\x0B\x0B\x0B"},
|
||||
{"Jefe"},
|
||||
{"\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
|
||||
"\xAA\xAA\xAA\xAA"},
|
||||
{"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
|
||||
"\x11\x12\x13\x14\x15\x16\x17\x18\x19"},
|
||||
{"\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
|
||||
"\x0C\x0C\x0C\x0C"},
|
||||
{""}, /* 0xAA 80 times */
|
||||
{""}
|
||||
};
|
||||
|
||||
static const int sha1_hmac_test_keylen[7] = {
|
||||
20, 4, 20, 25, 20, 80, 80
|
||||
};
|
||||
|
||||
static unsigned char sha1_hmac_test_buf[7][74] = {
|
||||
{"Hi There"},
|
||||
{"what do ya want for nothing?"},
|
||||
{"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
|
||||
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
|
||||
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
|
||||
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
|
||||
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"},
|
||||
{"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
|
||||
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
|
||||
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
|
||||
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
|
||||
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"},
|
||||
{"Test With Truncation"},
|
||||
{"Test Using Larger Than Block-Size Key - Hash Key First"},
|
||||
{"Test Using Larger Than Block-Size Key and Larger"
|
||||
" Than One Block-Size Data"}
|
||||
};
|
||||
|
||||
static const int sha1_hmac_test_buflen[7] = {
|
||||
8, 28, 50, 50, 20, 54, 73
|
||||
};
|
||||
|
||||
static const unsigned char sha1_hmac_test_sum[7][20] = {
|
||||
{0xB6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xE2, 0x8B,
|
||||
0xC0, 0xB6, 0xFB, 0x37, 0x8C, 0x8E, 0xF1, 0x46, 0xBE, 0x00},
|
||||
{0xEF, 0xFC, 0xDF, 0x6A, 0xE5, 0xEB, 0x2F, 0xA2, 0xD2, 0x74,
|
||||
0x16, 0xD5, 0xF1, 0x84, 0xDF, 0x9C, 0x25, 0x9A, 0x7C, 0x79},
|
||||
{0x12, 0x5D, 0x73, 0x42, 0xB9, 0xAC, 0x11, 0xCD, 0x91, 0xA3,
|
||||
0x9A, 0xF4, 0x8A, 0xA1, 0x7B, 0x4F, 0x63, 0xF1, 0x75, 0xD3},
|
||||
{0x4C, 0x90, 0x07, 0xF4, 0x02, 0x62, 0x50, 0xC6, 0xBC, 0x84,
|
||||
0x14, 0xF9, 0xBF, 0x50, 0xC8, 0x6C, 0x2D, 0x72, 0x35, 0xDA},
|
||||
{0x4C, 0x1A, 0x03, 0x42, 0x4B, 0x55, 0xE0, 0x7F, 0xE7, 0xF2,
|
||||
0x7B, 0xE1},
|
||||
{0xAA, 0x4A, 0xE5, 0xE1, 0x52, 0x72, 0xD0, 0x0E, 0x95, 0x70,
|
||||
0x56, 0x37, 0xCE, 0x8A, 0x3B, 0x55, 0xED, 0x40, 0x21, 0x12},
|
||||
{0xE8, 0xE9, 0x9D, 0x0F, 0x45, 0x23, 0x7D, 0x78, 0x6D, 0x6B,
|
||||
0xBA, 0xA7, 0x96, 0x5C, 0x78, 0x08, 0xBB, 0xFF, 0x1A, 0x91}
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
char *t;
|
||||
char *p;
|
||||
int plen;
|
||||
char *s;
|
||||
int slen;
|
||||
int c;
|
||||
int dkLen;
|
||||
char dk[1024]; // Remember to set this to max dkLen
|
||||
} testvector;
|
||||
|
||||
int do_test(testvector * tv)
|
||||
{
|
||||
printf("Started %s\n", tv->t);
|
||||
fflush(stdout);
|
||||
char *key = malloc(tv->dkLen);
|
||||
if (key == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
PKCS5_PBKDF2_HMAC(tv->p, tv->plen, tv->s, tv->slen, tv->c,
|
||||
tv->dkLen, key);
|
||||
|
||||
if (memcmp(tv->dk, key, tv->dkLen) != 0) {
|
||||
// Failed
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static void print_hex(unsigned char *str, int len)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < len; ++i)
|
||||
printf("%02x", str[i]);
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Checkup routine
|
||||
*/
|
||||
int main(int argc,char * argv[])
|
||||
{
|
||||
int verbose = 1;
|
||||
int i, j, buflen;
|
||||
unsigned char buf[1024];
|
||||
unsigned char sha1sum[20];
|
||||
|
||||
sha1_context ctx;
|
||||
|
||||
/*
|
||||
* SHA-1
|
||||
*/
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (verbose != 0)
|
||||
printf(" SHA-1 test #%d: ", i + 1);
|
||||
|
||||
sha1_starts(&ctx);
|
||||
|
||||
if (i == 2) {
|
||||
memset(buf, 'a', buflen = 1000);
|
||||
|
||||
for (j = 0; j < 1000; j++)
|
||||
sha1_update(&ctx, buf, buflen);
|
||||
} else
|
||||
sha1_update(&ctx, sha1_test_buf[i],
|
||||
sha1_test_buflen[i]);
|
||||
|
||||
sha1_finish(&ctx, sha1sum);
|
||||
|
||||
if (memcmp(sha1sum, sha1_test_sum[i], 20) != 0) {
|
||||
if (verbose != 0)
|
||||
printf("failed\n");
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (verbose != 0)
|
||||
printf("passed\n");
|
||||
}
|
||||
|
||||
if (verbose != 0)
|
||||
printf("\n");
|
||||
|
||||
for (i = 0; i < 7; i++) {
|
||||
if (verbose != 0)
|
||||
printf(" HMAC-SHA-1 test #%d: ", i + 1);
|
||||
|
||||
if (i == 5 || i == 6) {
|
||||
memset(buf, '\xAA', buflen = 80);
|
||||
sha1_hmac_starts(&ctx, buf, buflen);
|
||||
} else
|
||||
sha1_hmac_starts(&ctx, sha1_hmac_test_key[i],
|
||||
sha1_hmac_test_keylen[i]);
|
||||
|
||||
sha1_hmac_update(&ctx, sha1_hmac_test_buf[i],
|
||||
sha1_hmac_test_buflen[i]);
|
||||
|
||||
sha1_hmac_finish(&ctx, sha1sum);
|
||||
|
||||
buflen = (i == 4) ? 12 : 20;
|
||||
|
||||
if (memcmp(sha1sum, sha1_hmac_test_sum[i], buflen) != 0) {
|
||||
if (verbose != 0)
|
||||
printf("failed\n");
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (verbose != 0)
|
||||
printf("passed\n");
|
||||
}
|
||||
|
||||
if (verbose != 0)
|
||||
printf("\n");
|
||||
|
||||
// Test vectors from RFC 6070
|
||||
|
||||
testvector *tv = 0;
|
||||
int res = 0;
|
||||
|
||||
/*
|
||||
Input:
|
||||
P = "password" (8 octets)
|
||||
S = "salt" (4 octets)
|
||||
c = 1
|
||||
dkLen = 20
|
||||
|
||||
Output:
|
||||
DK = 0c 60 c8 0f 96 1f 0e 71
|
||||
f3 a9 b5 24 af 60 12 06
|
||||
2f e0 37 a6 (20 octets)
|
||||
|
||||
*/
|
||||
testvector t1 = {
|
||||
"Test 1",
|
||||
"password", 8, "salt", 4, 1, 20,
|
||||
.dk = {0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71,
|
||||
0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06,
|
||||
0x2f, 0xe0, 0x37, 0xa6}
|
||||
};
|
||||
|
||||
tv = &t1;
|
||||
res = do_test(tv);
|
||||
if (res != 0) {
|
||||
printf("%s failed\n", tv->t);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
Input:
|
||||
P = "password" (8 octets)
|
||||
S = "salt" (4 octets)
|
||||
c = 2
|
||||
dkLen = 20
|
||||
|
||||
Output:
|
||||
DK = ea 6c 01 4d c7 2d 6f 8c
|
||||
cd 1e d9 2a ce 1d 41 f0
|
||||
d8 de 89 57 (20 octets)
|
||||
|
||||
*/
|
||||
|
||||
testvector t2 = {
|
||||
"Test 2",
|
||||
"password", 8, "salt", 4, 2, 20,
|
||||
{0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c,
|
||||
0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0,
|
||||
0xd8, 0xde, 0x89, 0x57}
|
||||
};
|
||||
|
||||
tv = &t2;
|
||||
res = do_test(tv);
|
||||
if (res != 0) {
|
||||
printf("%s failed\n", tv->t);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
Input:
|
||||
P = "password" (8 octets)
|
||||
S = "salt" (4 octets)
|
||||
c = 4096
|
||||
dkLen = 20
|
||||
|
||||
Output:
|
||||
DK = 4b 00 79 01 b7 65 48 9a
|
||||
be ad 49 d9 26 f7 21 d0
|
||||
65 a4 29 c1 (20 octets)
|
||||
|
||||
|
||||
*/
|
||||
testvector t3 = {
|
||||
"Test 3",
|
||||
"password", 8, "salt", 4, 4096, 20,
|
||||
{0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a,
|
||||
0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0,
|
||||
0x65, 0xa4, 0x29, 0xc1}
|
||||
};
|
||||
|
||||
tv = &t3;
|
||||
res = do_test(tv);
|
||||
if (res != 0) {
|
||||
printf("%s failed\n", tv->t);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
Input:
|
||||
P = "password" (8 octets)
|
||||
S = "salt" (4 octets)
|
||||
c = 16777216
|
||||
dkLen = 20
|
||||
|
||||
Output:
|
||||
DK = ee fe 3d 61 cd 4d a4 e4
|
||||
e9 94 5b 3d 6b a2 15 8c
|
||||
26 34 e9 84 (20 octets)
|
||||
|
||||
*/
|
||||
testvector t4 = {
|
||||
"Test 4",
|
||||
"password", 8, "salt", 4, 16777216, 20,
|
||||
{0xee, 0xfe, 0x3d, 0x61, 0xcd, 0x4d, 0xa4, 0xe4,
|
||||
0xe9, 0x94, 0x5b, 0x3d, 0x6b, 0xa2, 0x15, 0x8c,
|
||||
0x26, 0x34, 0xe9, 0x84}
|
||||
};
|
||||
|
||||
tv = &t4;
|
||||
// res = do_test(tv);
|
||||
if (res != 0) {
|
||||
printf("%s failed\n", tv->t);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
Input:
|
||||
P = "passwordPASSWORDpassword" (24 octets)
|
||||
S = "saltSALTsaltSALTsaltSALTsaltSALTsalt" (36 octets)
|
||||
c = 4096
|
||||
dkLen = 25
|
||||
|
||||
Output:
|
||||
DK = 3d 2e ec 4f e4 1c 84 9b
|
||||
80 c8 d8 36 62 c0 e4 4a
|
||||
8b 29 1a 96 4c f2 f0 70
|
||||
38 (25 octets)
|
||||
|
||||
*/
|
||||
testvector t5 = {
|
||||
"Test 5",
|
||||
"passwordPASSWORDpassword", 24,
|
||||
"saltSALTsaltSALTsaltSALTsaltSALTsalt", 36, 4096, 25,
|
||||
{0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b,
|
||||
0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a,
|
||||
0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70,
|
||||
0x38}
|
||||
};
|
||||
|
||||
tv = &t5;
|
||||
res = do_test(tv);
|
||||
if (res != 0) {
|
||||
printf("%s failed\n", tv->t);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
Input:
|
||||
P = "pass\0word" (9 octets)
|
||||
S = "sa\0lt" (5 octets)
|
||||
c = 4096
|
||||
dkLen = 16
|
||||
|
||||
Output:
|
||||
DK = 56 fa 6a a7 55 48 09 9d
|
||||
cc 37 d7 f0 34 25 e0 c3 (16 octets)
|
||||
*/
|
||||
testvector t6 = {
|
||||
"Test 6",
|
||||
"pass\0word", 9, "sa\0lt", 5, 4096, 16,
|
||||
{0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d,
|
||||
0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3,
|
||||
}
|
||||
};
|
||||
|
||||
tv = &t6;
|
||||
res = do_test(tv);
|
||||
if (res != 0) {
|
||||
printf("%s failed\n", tv->t);
|
||||
return res;
|
||||
}
|
||||
|
||||
printf("All tests successful\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*
|
||||
int main()
|
||||
{
|
||||
}*/
|
14
lib/pbkdf2-sha1.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
void sha1(const unsigned char *input, int ilen, unsigned char output[20]);
|
||||
|
||||
void sha1_hmac(const unsigned char *key, int keylen, const unsigned char *input, int ilen, unsigned char output[20]);
|
||||
|
||||
void PKCS5_PBKDF2_HMAC_SHA1(const unsigned char *password, size_t plen,
|
||||
const unsigned char *salt, size_t slen,
|
||||
const unsigned long iteration_count, const unsigned long key_length,
|
||||
unsigned char *output);
|
1124
lib/pbkdf2-sha256.cpp
Normal file
28
lib/pbkdf2-sha256.h
Normal file
@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
void PKCS5_PBKDF2_HMAC_SHA256(unsigned char *password, size_t plen,
|
||||
unsigned char *salt, size_t slen,
|
||||
const unsigned long iteration_count, const unsigned long key_length,
|
||||
unsigned char *output);
|
||||
|
||||
//void sha2( const unsigned char *input, size_t ilen,unsigned char output[32], int is224 );
|
||||
|
||||
int hkdf_sha256_extract(
|
||||
const unsigned char *salt, size_t salt_len,
|
||||
const unsigned char *ikm, size_t ikm_len,
|
||||
unsigned char *prk );
|
||||
|
||||
int hkdf_sha256_expand( const unsigned char *prk,
|
||||
size_t prk_len, const unsigned char *info,
|
||||
size_t info_len, unsigned char *okm, size_t okm_len );
|
||||
|
||||
int hkdf_sha256( const unsigned char *salt,
|
||||
size_t salt_len, const unsigned char *ikm, size_t ikm_len,
|
||||
const unsigned char *info, size_t info_len,
|
||||
unsigned char *okm, size_t okm_len );
|
||||
|
||||
|
31
libev/CVS/Entries
Normal file
@ -0,0 +1,31 @@
|
||||
/Changes/1.315/Wed Jun 21 14:42:30 2017//
|
||||
/LICENSE/1.11/Thu Jan 16 11:51:05 2014//
|
||||
/Makefile.am/1.9/Wed Dec 21 18:16:08 2011//
|
||||
/README/1.21/Fri Mar 30 17:43:55 2012//
|
||||
/README.embed/1.29/Sat Nov 24 10:10:26 2007//
|
||||
/Symbols.ev/1.14/Tue Jan 11 13:45:28 2011//
|
||||
/Symbols.event/1.4/Tue May 8 15:52:13 2012//
|
||||
/autogen.sh/1.3/Mon May 30 15:28:54 2011//
|
||||
/configure.ac/1.42/Wed Dec 28 04:22:06 2016//
|
||||
/ev++.h/1.63/Fri Dec 1 06:37:30 2017//
|
||||
/ev.3/1.107/Wed Jun 21 14:42:30 2017//
|
||||
/ev.c/1.481/Thu Jun 1 20:25:50 2017//
|
||||
/ev.h/1.187/Wed Dec 28 04:22:06 2016//
|
||||
/ev.pod/1.441/Thu Jul 13 10:46:52 2017//
|
||||
/ev_epoll.c/1.72/Wed Jun 21 14:42:30 2017//
|
||||
/ev_kqueue.c/1.56/Thu Feb 18 04:48:05 2016//
|
||||
/ev_poll.c/1.40/Thu Feb 18 04:48:05 2016//
|
||||
/ev_port.c/1.29/Thu Feb 18 04:48:05 2016//
|
||||
/ev_select.c/1.56/Thu Feb 18 04:48:05 2016//
|
||||
/ev_vars.h/1.58/Tue Sep 9 21:51:35 2014//
|
||||
/ev_win32.c/1.18/Thu Nov 12 07:02:37 2015//
|
||||
/ev_wrap.h/1.38/Tue Nov 6 20:56:50 2012//
|
||||
/event.c/1.52/Mon Apr 2 23:14:41 2012//
|
||||
/event.h/1.26/Mon Apr 2 23:15:27 2012//
|
||||
/event_compat.h/1.8/Wed Feb 16 08:02:51 2011//
|
||||
/import_libevent/1.29/Tue Apr 15 04:34:07 2008//
|
||||
/libev.m4/1.16/Mon Oct 28 12:36:44 2013//
|
||||
/update_ev_c/1.2/Wed Jan 18 12:13:14 2012//
|
||||
/update_ev_wrap/1.6/Sun May 6 13:09:29 2012//
|
||||
/update_symbols/1.1/Wed Dec 19 01:59:29 2007//
|
||||
D
|
1
libev/CVS/Repository
Normal file
@ -0,0 +1 @@
|
||||
libev
|
1
libev/CVS/Root
Normal file
@ -0,0 +1 @@
|
||||
:pserver:anonymous@cvs.schmorp.de/schmorpforge
|
517
libev/Changes
Normal file
@ -0,0 +1,517 @@
|
||||
Revision history for libev, a high-performance and full-featured event loop.
|
||||
|
||||
- ANDROID => __ANDROID__ (reported by enh@google.com).
|
||||
- disable epoll_create1 on android because it has broken header files
|
||||
and google is unwilling to fix them (reported by enh@google.com).
|
||||
|
||||
4.24 Wed Dec 28 05:19:55 CET 2016
|
||||
- bump version to 4.24, as the release tarball inexplicably
|
||||
didn't have the right version in ev.h, even though the cvs-tagged
|
||||
version did have the right one (reported by Ales Teska).
|
||||
|
||||
4.23 Wed Nov 16 18:23:41 CET 2016
|
||||
- move some declarations at the beginning to help certain retarded
|
||||
microsoft compilers, even though their documentation claims
|
||||
otherwise (reported by Ruslan Osmanov).
|
||||
|
||||
4.22 Sun Dec 20 22:11:50 CET 2015
|
||||
- when epoll detects unremovable fds in the fd set, rebuild
|
||||
only the epoll descriptor, not the signal pipe, to avoid
|
||||
SIGPIPE in ev_async_send. This doesn't solve it on fork,
|
||||
so document what needs to be done in ev_loop_fork
|
||||
(analyzed by Benjamin Mahler).
|
||||
- remove superfluous sys/timeb.h include on win32
|
||||
(analyzed by Jason Madden).
|
||||
- updated libecb.
|
||||
|
||||
4.20 Sat Jun 20 13:01:43 CEST 2015
|
||||
- prefer noexcept over throw () with C++ 11.
|
||||
- update ecb.h due to incompatibilities with c11.
|
||||
- fix a potential aliasing issue when reading and writing
|
||||
watcher callbacks.
|
||||
|
||||
4.19 Thu Sep 25 08:18:25 CEST 2014
|
||||
- ev.h wasn't valid C++ anymore, which tripped compilers other than
|
||||
clang, msvc or gcc (analyzed by Raphael 'kena' Poss). Unfortunately,
|
||||
C++ doesn't support typedefs for function pointers fully, so the affected
|
||||
declarations have to spell out the types each time.
|
||||
- when not using autoconf, tighten the check for clock_gettime and related
|
||||
functionality.
|
||||
|
||||
4.18 Fri Sep 5 17:55:26 CEST 2014
|
||||
- events on files were not always generated properly with the
|
||||
epoll backend (testcase by Assaf Inbal).
|
||||
- mark event pipe fd as cloexec after a fork (analyzed by Sami Farin).
|
||||
- (ecb) support m68k, m88k and sh (patch by Miod Vallat).
|
||||
- use a reasonable fallback for EV_NSIG instead of erroring out
|
||||
when we can't detect the signal set size.
|
||||
- in the absence of autoconf, do not use the clock syscall
|
||||
on glibc >= 2.17 (avoids the syscall AND -lrt on systems
|
||||
doing clock_gettime in userspace).
|
||||
- ensure extern "C" function pointers are used for externally-visible
|
||||
loop callbacks (not watcher callbacks yet).
|
||||
- (ecb) work around memory barriers and volatile apparently both being
|
||||
broken in visual studio 2008 and later (analysed and patch by Nicolas Noble).
|
||||
|
||||
4.15 Fri Mar 1 12:04:50 CET 2013
|
||||
- destroying a non-default loop would stop the global waitpid
|
||||
watcher (Denis Bilenko).
|
||||
- queueing pending watchers of higher priority from a watcher now invokes
|
||||
them in a timely fashion (reported by Denis Bilenko).
|
||||
- add throw() to all libev functions that cannot throw exceptions, for
|
||||
further code size decrease when compiling for C++.
|
||||
- add throw () to callbacks that must not throw exceptions (allocator,
|
||||
syserr, loop acquire/release, periodic reschedule cbs).
|
||||
- fix event_base_loop return code, add event_get_callback, event_base_new,
|
||||
event_base_get_method calls to improve libevent 1.x emulation and add
|
||||
some libevent 2.x functionality (based on a patch by Jeff Davey).
|
||||
- add more memory fences to fix a bug reported by Jeff Davey. Better
|
||||
be overfenced than underprotected.
|
||||
- ev_run now returns a boolean status (true meaning watchers are
|
||||
still active).
|
||||
- ev_once: undef EV_ERROR in ev_kqueue.c, to avoid clashing with
|
||||
libev's EV_ERROR (reported by 191919).
|
||||
- (ecb) add memory fence support for xlC (Darin McBride).
|
||||
- (ecb) add memory fence support for gcc-mips (Anton Kirilov).
|
||||
- (ecb) add memory fence support for gcc-alpha (Christian Weisgerber).
|
||||
- work around some kernels losing file descriptors by leaking
|
||||
the kqueue descriptor in the child.
|
||||
- work around linux inotify not reporting IN_ATTRIB changes for directories
|
||||
in many cases.
|
||||
- include sys/syscall.h instead of plain syscall.h.
|
||||
- check for io watcher loops in ev_verify, check for the most
|
||||
common reported usage bug in ev_io_start.
|
||||
- choose socket vs. WSASocket at compiletime using EV_USE_WSASOCKET.
|
||||
- always use WSASend/WSARecv directly on windows, hoping that this
|
||||
works in all cases (unlike read/write/send/recv...).
|
||||
- try to detect signals around a fork faster (test program by
|
||||
Denis Bilenko).
|
||||
- work around recent glibc versions that leak memory in realloc.
|
||||
- rename ev::embed::set to ev::embed::set_embed to avoid clashing
|
||||
the watcher base set (loop) method.
|
||||
- rewrite the async/signal pipe logic to always keep a valid fd, which
|
||||
simplifies (and hopefully correctifies :) the race checking
|
||||
on fork, at the cost of one extra fd.
|
||||
- add fat, msdos, jffs2, ramfs, ntfs and btrfs to the list of
|
||||
inotify-supporting filesystems.
|
||||
- move orig_CFLAGS assignment to after AC_INIT, as newer autoconf
|
||||
versions ignore it before
|
||||
(https://bugzilla.redhat.com/show_bug.cgi?id=908096).
|
||||
- add some untested android support.
|
||||
- enum expressions must be of type int (reported by Juan Pablo L).
|
||||
|
||||
4.11 Sat Feb 4 19:52:39 CET 2012
|
||||
- INCOMPATIBLE CHANGE: ev_timer_again now clears the pending status, as
|
||||
was documented already, but not implemented in the repeating case.
|
||||
- new compiletime symbols: EV_NO_SMP and EV_NO_THREADS.
|
||||
- fix a race where the workaround against the epoll fork bugs
|
||||
caused signals to not be handled anymore.
|
||||
- correct backend_fudge for most backends, and implement a windows
|
||||
specific workaround to avoid looping because we call both
|
||||
select and Sleep, both with different time resolutions.
|
||||
- document range and guarantees of ev_sleep.
|
||||
- document reasonable ranges for periodics interval and offset.
|
||||
- rename backend_fudge to backend_mintime to avoid future confusion :)
|
||||
- change the default periodic reschedule function to hopefully be more
|
||||
exact and correct even in corner cases or in the far future.
|
||||
- do not rely on -lm anymore: use it when available but use our
|
||||
own floor () if it is missing. This should make it easier to embed,
|
||||
as no external libraries are required.
|
||||
- strategically import macros from libecb and mark rarely-used functions
|
||||
as cache-cold (saving almost 2k code size on typical amd64 setups).
|
||||
- add Symbols.ev and Symbols.event files, that were missing.
|
||||
- fix backend_mintime value for epoll (was 1/1024, is 1/1000 now).
|
||||
- fix #3 "be smart about timeouts" to not "deadlock" when
|
||||
timeout == now, also improve the section overall.
|
||||
- avoid "AVOIDING FINISHING BEFORE RETURNING" idiom.
|
||||
- support new EV_API_STATIC mode to make all libev symbols
|
||||
static.
|
||||
- supply default CFLAGS of -g -O3 with gcc when original CFLAGS
|
||||
were empty.
|
||||
|
||||
4.04 Wed Feb 16 09:01:51 CET 2011
|
||||
- fix two problems in the native win32 backend, where reuse of fd's
|
||||
with different underlying handles caused handles not to be removed
|
||||
or added to the select set (analyzed and tested by Bert Belder).
|
||||
- do no rely on ceil() in ev_e?poll.c.
|
||||
- backport libev to HP-UX versions before 11 v3.
|
||||
- configure did not detect nanosleep and clock_gettime properly when
|
||||
they are available in the libc (as opposed to -lrt).
|
||||
|
||||
4.03 Tue Jan 11 14:37:25 CET 2011
|
||||
- officially support polling files with all backends.
|
||||
- support files, /dev/zero etc. the same way as select in the epoll
|
||||
backend, by generating events on our own.
|
||||
- ports backend: work around solaris bug 6874410 and many related ones
|
||||
(EINTR, maybe more), with no performance loss (note that the solaris
|
||||
bug report is actually wrong, reality is far more bizarre and broken
|
||||
than that).
|
||||
- define EV_READ/EV_WRITE as macros in event.h, as some programs use
|
||||
#ifdef to test for them.
|
||||
- new (experimental) function: ev_feed_signal.
|
||||
- new (to become default) EVFLAG_NOSIGMASK flag.
|
||||
- new EVBACKEND_MASK symbol.
|
||||
- updated COMMON IDIOMS SECTION.
|
||||
|
||||
4.01 Fri Nov 5 21:51:29 CET 2010
|
||||
- automake fucked it up, apparently, --add-missing -f is not quite enough
|
||||
to make it update its files, so 4.00 didn't install ev++.h and
|
||||
event.h on make install. grrr.
|
||||
- ev_loop(count|depth) didn't return anything (Robin Haberkorn).
|
||||
- change EV_UNDEF to 0xffffffff to silence some overzealous compilers.
|
||||
- use "(libev) " prefix for all libev error messages now.
|
||||
|
||||
4.00 Mon Oct 25 12:32:12 CEST 2010
|
||||
- "PORTING FROM LIBEV 3.X TO 4.X" (in ev.pod) is recommended reading.
|
||||
- ev_embed_stop did not correctly stop the watcher (very good
|
||||
testcase by Vladimir Timofeev).
|
||||
- ev_run will now always update the current loop time - it erroneously
|
||||
didn't when idle watchers were active, causing timers not to fire.
|
||||
- fix a bug where a timeout of zero caused the timer not to fire
|
||||
in the libevent emulation (testcase by Péter Szabó).
|
||||
- applied win32 fixes by Michael Lenaghan (also James Mansion).
|
||||
- replace EV_MINIMAL by EV_FEATURES.
|
||||
- prefer EPOLL_CTL_ADD over EPOLL_CTL_MOD in some more cases, as it
|
||||
seems the former is *much* faster than the latter.
|
||||
- linux kernel version detection (for inotify bug workarounds)
|
||||
did not work properly.
|
||||
- reduce the number of spurious wake-ups with the ports backend.
|
||||
- remove dependency on sys/queue.h on freebsd (patch by Vanilla Hsu).
|
||||
- do async init within ev_async_start, not ev_async_set, which avoids
|
||||
an API quirk where the set function must be called in the C++ API
|
||||
even when there is nothing to set.
|
||||
- add (undocumented) EV_ENABLE when adding events with kqueue,
|
||||
this might help with OS X, which seems to need it despite documenting
|
||||
not to need it (helpfully pointed out by Tilghman Lesher).
|
||||
- do not use poll by default on freebsd, it's broken (what isn't
|
||||
on freebsd...).
|
||||
- allow to embed epoll on kernels >= 2.6.32.
|
||||
- configure now prepends -O3, not appends it, so one can still
|
||||
override it.
|
||||
- ev.pod: greatly expanded the portability section, added a porting
|
||||
section, a description of watcher states and made lots of minor fixes.
|
||||
- disable poll backend on AIX, the poll header spams the namespace
|
||||
and it's not worth working around dead platforms (reported
|
||||
and analyzed by Aivars Kalvans).
|
||||
- improve header file compatibility of the standalone eventfd code
|
||||
in an obscure case.
|
||||
- implement EV_AVOID_STDIO option.
|
||||
- do not use sscanf to parse linux version number (smaller, faster,
|
||||
no sscanf dependency).
|
||||
- new EV_CHILD_ENABLE and EV_SIGNAL_ENABLE configurable settings.
|
||||
- update libev.m4 HAVE_CLOCK_SYSCALL test for newer glibcs.
|
||||
- add section on accept() problems to the manpage.
|
||||
- rename EV_TIMEOUT to EV_TIMER.
|
||||
- rename ev_loop_count/depth/verify/loop/unloop.
|
||||
- remove ev_default_destroy and ev_default_fork.
|
||||
- switch to two-digit minor version.
|
||||
- work around an apparent gentoo compiler bug.
|
||||
- define _DARWIN_UNLIMITED_SELECT. just so.
|
||||
- use enum instead of #define for most constants.
|
||||
- improve compatibility to older C++ compilers.
|
||||
- (experimental) ev_run/ev_default_loop/ev_break/ev_loop_new have now
|
||||
default arguments when compiled as C++.
|
||||
- enable automake dependency tracking.
|
||||
- ev_loop_new no longer leaks memory when loop creation failed.
|
||||
- new ev_cleanup watcher type.
|
||||
|
||||
3.9 Thu Dec 31 07:59:59 CET 2009
|
||||
- signalfd is no longer used by default and has to be requested
|
||||
explicitly - this means that easy to catch bugs become hard to
|
||||
catch race conditions, but the users have spoken.
|
||||
- point out the unspecified signal mask in the documentation, and
|
||||
that this is a race condition regardless of EV_SIGNALFD.
|
||||
- backport inotify code to C89.
|
||||
- inotify file descriptors could leak into child processes.
|
||||
- ev_stat watchers could keep an erroneous extra ref on the loop,
|
||||
preventing exit when unregistering all watchers (testcases
|
||||
provided by ry@tinyclouds.org).
|
||||
- implement EV_WIN32_HANDLE_TO_FD and EV_WIN32_CLOSE_FD configuration
|
||||
symbols to make it easier for apps to do their own fd management.
|
||||
- support EV_IDLE_ENABLE being disabled in ev++.h
|
||||
(patch by Didier Spezia).
|
||||
- take advantage of inotify_init1, if available, to set cloexec/nonblock
|
||||
on fd creation, to avoid races.
|
||||
- the signal handling pipe wasn't always initialised under windows
|
||||
(analysed by lekma).
|
||||
- changed minimum glibc requirement from glibc 2.9 to 2.7, for
|
||||
signalfd.
|
||||
- add missing string.h include (Denis F. Latypoff).
|
||||
- only replace ev_stat.prev when we detect an actual difference,
|
||||
so prev is (almost) always different to attr. this might
|
||||
have caused the problems with 04_stat.t.
|
||||
- add ev::timer->remaining () method to C++ API.
|
||||
|
||||
3.8 Sun Aug 9 14:30:45 CEST 2009
|
||||
- incompatible change: do not necessarily reset signal handler
|
||||
to SIG_DFL when a sighandler is stopped.
|
||||
- ev_default_destroy did not properly free or zero some members,
|
||||
potentially causing crashes and memory corruption on repeated
|
||||
ev_default_destroy/ev_default_loop calls.
|
||||
- take advantage of signalfd on GNU/Linux systems.
|
||||
- document that the signal mask might be in an unspecified
|
||||
state when using libev's signal handling.
|
||||
- take advantage of some GNU/Linux calls to set cloexec/nonblock
|
||||
on fd creation, to avoid race conditions.
|
||||
|
||||
3.7 Fri Jul 17 16:36:32 CEST 2009
|
||||
- ev_unloop and ev_loop wrongly used a global variable to exit loops,
|
||||
instead of using a per-loop variable (bug caught by accident...).
|
||||
- the ev_set_io_collect_interval interpretation has changed.
|
||||
- add new functionality: ev_set_userdata, ev_userdata,
|
||||
ev_set_invoke_pending_cb, ev_set_loop_release_cb,
|
||||
ev_invoke_pending, ev_pending_count, together with a long example
|
||||
about thread locking.
|
||||
- add ev_timer_remaining (as requested by Denis F. Latypoff).
|
||||
- add ev_loop_depth.
|
||||
- calling ev_unloop in fork/prepare watchers will no longer poll
|
||||
for new events.
|
||||
- Denis F. Latypoff corrected many typos in example code snippets.
|
||||
- honor autoconf detection of EV_USE_CLOCK_SYSCALL, also double-
|
||||
check that the syscall number is available before trying to
|
||||
use it (reported by ry@tinyclouds).
|
||||
- use GetSystemTimeAsFileTime instead of _timeb on windows, for
|
||||
slightly higher accuracy.
|
||||
- properly declare ev_loop_verify and ev_now_update even when
|
||||
!EV_MULTIPLICITY.
|
||||
- do not compile in any priority code when EV_MAXPRI == EV_MINPRI.
|
||||
- support EV_MINIMAL==2 for a reduced API.
|
||||
- actually 0-initialise struct sigaction when installing signals.
|
||||
- add section on hibernate and stopped processes to ev_timer docs.
|
||||
|
||||
3.6 Tue Apr 28 02:49:30 CEST 2009
|
||||
- multiple timers becoming ready within an event loop iteration
|
||||
will be invoked in the "correct" order now.
|
||||
- do not leave the event loop early just because we have no active
|
||||
watchers, fixing a problem when embedding a kqueue loop
|
||||
that has active kernel events but no registered watchers
|
||||
(reported by blacksand blacksand).
|
||||
- correctly zero the idx values for arrays, so destroying and
|
||||
reinitialising the default loop actually works (patch by
|
||||
Malek Hadj-Ali).
|
||||
- implement ev_suspend and ev_resume.
|
||||
- new EV_CUSTOM revents flag for use by applications.
|
||||
- add documentation section about priorities.
|
||||
- add a glossary to the documentation.
|
||||
- extend the ev_fork description slightly.
|
||||
- optimize a jump out of call_pending.
|
||||
|
||||
3.53 Sun Feb 15 02:38:20 CET 2009
|
||||
- fix a bug in event pipe creation on win32 that would cause a
|
||||
failed assertion on event loop creation (patch by Malek Hadj-Ali).
|
||||
- probe for CLOCK_REALTIME support at runtime as well and fall
|
||||
back to gettimeofday if there is an error, to support older
|
||||
operating systems with newer header files/libraries.
|
||||
- prefer gettimeofday over clock_gettime with USE_CLOCK_SYSCALL
|
||||
(default most everywhere), otherwise not.
|
||||
|
||||
3.52 Wed Jan 7 21:43:02 CET 2009
|
||||
- fix compilation of select backend in fd_set mode when NFDBITS is
|
||||
missing (to get it to compile on QNX, reported by Rodrigo Campos).
|
||||
- better select-nfds handling when select backend is in fd_set mode.
|
||||
- diagnose fd_set overruns when select backend is in fd_set mode.
|
||||
- due to a thinko, instead of disabling everything but
|
||||
select on the borked OS X platform, everything but select was
|
||||
allowed (reported by Emanuele Giaquinta).
|
||||
- actually verify that local and remote port are matching in
|
||||
libev's socketpair emulation, which makes denial-of-service
|
||||
attacks harder (but not impossible - it's windows). Make sure
|
||||
it even works under vista, which thinks that getpeer/sockname
|
||||
should return fantasy port numbers.
|
||||
- include "libev" in all assertion messages for potentially
|
||||
clearer diagnostics.
|
||||
- event_get_version (libevent compatibility) returned
|
||||
a useless string instead of the expected version string
|
||||
(patch by W.C.A. Wijngaards).
|
||||
|
||||
3.51 Wed Dec 24 23:00:11 CET 2008
|
||||
- fix a bug where an inotify watcher was added twice, causing
|
||||
freezes on hash collisions (reported and analysed by Graham Leggett).
|
||||
- new config symbol, EV_USE_CLOCK_SYSCALL, to make libev use
|
||||
a direct syscall - slower, but no dependency on librt et al.
|
||||
- assume negative return values != -1 signals success of port_getn
|
||||
(http://cvs.epicsol.org/cgi/viewcvs.cgi/epic5/source/newio.c?rev=1.52)
|
||||
(no known failure reports, but it doesn't hurt).
|
||||
- fork detection in ev_embed now stops and restarts the watcher
|
||||
automatically.
|
||||
- EXPERIMENTAL: default the method to operator () in ev++.h,
|
||||
to make it nicer to use functors (requested by Benedek László).
|
||||
- fixed const object callbacks in ev++.h.
|
||||
- replaced loop_ref argument of watcher.set (loop) by a direct
|
||||
ev_loop * in ev++.h, to avoid clashes with functor patch.
|
||||
- do not try to watch the empty string via inotify.
|
||||
- inotify watchers could be leaked under certain circumstances.
|
||||
- OS X 10.5 is actually even more broken than earlier versions,
|
||||
so fall back to select on that piece of garbage.
|
||||
- fixed some weirdness in the ev_embed documentation.
|
||||
|
||||
3.49 Wed Nov 19 11:26:53 CET 2008
|
||||
- ev_stat watchers will now use inotify as a mere hint on
|
||||
kernels <2.6.25, or if the filesystem is not in the
|
||||
"known to be good" list.
|
||||
- better mingw32 compatibility (it's not as borked as native win32)
|
||||
(analysed by Roger Pack).
|
||||
- include stdio.h in the example program, as too many people are
|
||||
confused by the weird C language otherwise. I guess the next thing
|
||||
I get told is that the "..." ellipses in the examples don't compile
|
||||
with their C compiler.
|
||||
|
||||
3.48 Thu Oct 30 09:02:37 CET 2008
|
||||
- further optimise away the EPOLL_CTL_ADD/MOD combo in the epoll
|
||||
backend by assuming the kernel event mask hasn't changed if
|
||||
ADD fails with EEXIST.
|
||||
- work around spurious event notification bugs in epoll by using
|
||||
a 32-bit generation counter. recreate kernel state if we receive
|
||||
spurious notifications or unwanted events. this is very costly,
|
||||
but I didn't come up with this horrible design.
|
||||
- use memset to initialise most arrays now and do away with the
|
||||
init functions.
|
||||
- expand time-out strategies into a "Be smart about timeouts" section.
|
||||
- drop the "struct" from all ev_watcher declarations in the
|
||||
documentation and did other clarifications (yeah, it was a mistake
|
||||
to have a struct AND a function called ev_loop).
|
||||
- fix a bug where ev_default would not initialise the default
|
||||
loop again after it was destroyed with ev_default_destroy.
|
||||
- rename syserr to ev_syserr to avoid name clashes when embedding,
|
||||
do similar changes for event.c.
|
||||
|
||||
3.45 Tue Oct 21 21:59:26 CEST 2008
|
||||
- disable inotify usage on linux <2.6.25, as it is broken
|
||||
(reported by Yoann Vandoorselaere).
|
||||
- ev_stat erroneously would try to add inotify watchers
|
||||
even when inotify wasn't available (this should only
|
||||
have a performance impact).
|
||||
- ev_once now passes both timeout and io to the callback if both
|
||||
occur concurrently, instead of giving timeouts precedence.
|
||||
- disable EV_USE_INOTIFY when sys/inotify.h is too old.
|
||||
|
||||
3.44 Mon Sep 29 05:18:39 CEST 2008
|
||||
- embed watchers now automatically invoke ev_loop_fork on the
|
||||
embedded loop when the parent loop forks.
|
||||
- new function: ev_now_update (loop).
|
||||
- verify_watcher was not marked static.
|
||||
- improve the "associating..." manpage section.
|
||||
- documentation tweaks here and there.
|
||||
|
||||
3.43 Sun Jul 6 05:34:41 CEST 2008
|
||||
- include more include files on windows to get struct _stati64
|
||||
(reported by Chris Hulbert, but doesn't quite fix his issue).
|
||||
- add missing #include <io.h> in ev.c on windows (reported by
|
||||
Matt Tolton).
|
||||
|
||||
3.42 Tue Jun 17 12:12:07 CEST 2008
|
||||
- work around yet another windows bug: FD_SET actually adds fd's
|
||||
multiple times to the fd_*SET*, despite official MSN docs claiming
|
||||
otherwise. Reported and well-analysed by Matt Tolton.
|
||||
- define NFDBITS to 0 when EV_SELECT_IS_WINSOCKET to make it compile
|
||||
(reported any analysed by Chris Hulbert).
|
||||
- fix a bug in ev_ebadf (this function is only used to catch
|
||||
programming errors in the libev user). reported by Matt Tolton.
|
||||
- fix a bug in fd_intern on win32 (could lead to compile errors
|
||||
under some circumstances, but would work correctly if it compiles).
|
||||
reported by Matt Tolton.
|
||||
- (try to) work around missing lstat on windows.
|
||||
- pass in the write fd set as except fd set under windows. windows
|
||||
is so uncontrollably lame that it requires this. this means that
|
||||
switching off oobinline is not supported (but tcp/ip doesn't
|
||||
have oob, so that would be stupid anyways.
|
||||
- use posix module symbol to auto-detect monotonic clock presence
|
||||
and some other default values.
|
||||
|
||||
3.41 Fri May 23 18:42:54 CEST 2008
|
||||
- work around an obscure bug in winsocket select: if you
|
||||
provide only empty fd sets then select returns WSAEINVAL. how sucky.
|
||||
- improve timer scheduling stability and reduce use of time_epsilon.
|
||||
- use 1-based 2-heap for EV_MINIMAL, simplifies code, reduces
|
||||
codesize and makes for better cache-efficiency.
|
||||
- use 3-based 4-heap for !EV_MINIMAL. this makes better use
|
||||
of cpu cache lines and gives better growth behaviour than
|
||||
2-based heaps.
|
||||
- cache timestamp within heap for !EV_MINIMAL, to avoid random
|
||||
memory accesses.
|
||||
- document/add EV_USE_4HEAP and EV_HEAP_CACHE_AT.
|
||||
- fix a potential aliasing issue in ev_timer_again.
|
||||
- add/document ev_periodic_at, retract direct access to ->at.
|
||||
- improve ev_stat docs.
|
||||
- add portability requirements section.
|
||||
- fix manpage headers etc.
|
||||
- normalise WSA error codes to lower range on windows.
|
||||
- add consistency check code that can be called automatically
|
||||
or on demand to check for internal structures (ev_loop_verify).
|
||||
|
||||
3.31 Wed Apr 16 20:45:04 CEST 2008
|
||||
- added last minute fix for ev_poll.c by Brandon Black.
|
||||
|
||||
3.3 Wed Apr 16 19:04:10 CEST 2008
|
||||
- event_base_loopexit should return 0 on success
|
||||
(W.C.A. Wijngaards).
|
||||
- added linux eventfd support.
|
||||
- try to autodetect epoll and inotify support
|
||||
by libc header version if not using autoconf.
|
||||
- new symbols: EV_DEFAULT_UC and EV_DEFAULT_UC_.
|
||||
- declare functions defined in ev.h as inline if
|
||||
C99 or gcc are available.
|
||||
- enable inlining with gcc versions 2 and 3.
|
||||
- work around broken poll implementations potentially
|
||||
not clearing revents field in ev_poll (Brandon Black)
|
||||
(no such systems are known at this time).
|
||||
- work around a bug in realloc on openbsd and darwin,
|
||||
also makes the erroneous valgrind complaints
|
||||
go away (noted by various people).
|
||||
- fix ev_async_pending, add c++ wrapper for ev_async
|
||||
(based on patch sent by Johannes Deisenhofer).
|
||||
- add sensible set method to ev::embed.
|
||||
- made integer constants type int in ev.h.
|
||||
|
||||
3.2 Wed Apr 2 17:11:19 CEST 2008
|
||||
- fix a 64 bit overflow issue in the select backend,
|
||||
by using fd_mask instead of int for the mask.
|
||||
- rename internal sighandler to avoid clash with very old perls.
|
||||
- entering ev_loop will not clear the ONESHOT or NONBLOCKING
|
||||
flags of any outer loops anymore.
|
||||
- add ev_async_pending.
|
||||
|
||||
3.1 Thu Mar 13 13:45:22 CET 2008
|
||||
- implement ev_async watchers.
|
||||
- only initialise signal pipe on demand.
|
||||
- make use of sig_atomic_t configurable.
|
||||
- improved documentation.
|
||||
|
||||
3.0 Mon Jan 28 13:14:47 CET 2008
|
||||
- API/ABI bump to version 3.0.
|
||||
- ev++.h includes "ev.h" by default now, not <ev.h>.
|
||||
- slightly improved documentation.
|
||||
- speed up signal detection after a fork.
|
||||
- only optionally return trace status changed in ev_child
|
||||
watchers.
|
||||
- experimental (and undocumented) loop wrappers for ev++.h.
|
||||
|
||||
2.01 Tue Dec 25 08:04:41 CET 2007
|
||||
- separate Changes file.
|
||||
- fix ev_path_set => ev_stat_set typo.
|
||||
- remove event_compat.h from the libev tarball.
|
||||
- change how include files are found.
|
||||
- doc updates.
|
||||
- update licenses, explicitly allow for GPL relicensing.
|
||||
|
||||
2.0 Sat Dec 22 17:47:03 CET 2007
|
||||
- new ev_sleep, ev_set_(io|timeout)_collect_interval.
|
||||
- removed epoll from embeddable fd set.
|
||||
- fix embed watchers.
|
||||
- renamed ev_embed.loop to other.
|
||||
- added exported Symbol tables.
|
||||
- undefine member wrapper macros at the end of ev.c.
|
||||
- respect EV_H in ev++.h.
|
||||
|
||||
1.86 Tue Dec 18 02:36:57 CET 2007
|
||||
- fix memleak on loop destroy (not relevant for perl).
|
||||
|
||||
1.85 Fri Dec 14 20:32:40 CET 2007
|
||||
- fix some aliasing issues w.r.t. timers and periodics
|
||||
(not relevant for perl).
|
||||
|
||||
(for historic versions refer to EV/Changes, found in the Perl interface)
|
||||
|
||||
0.1 Wed Oct 31 21:31:48 CET 2007
|
||||
- original version; hacked together in <24h.
|
||||
|
37
libev/LICENSE
Normal file
@ -0,0 +1,37 @@
|
||||
All files in libev are
|
||||
Copyright (c)2007,2008,2009,2010,2011,2012,2013 Marc Alexander Lehmann.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Alternatively, the contents of this package may be used under the terms
|
||||
of the GNU General Public License ("GPL") version 2 or any later version,
|
||||
in which case the provisions of the GPL are applicable instead of the
|
||||
above. If you wish to allow the use of your version of this package only
|
||||
under the terms of the GPL and not to allow others to use your version of
|
||||
this file under the BSD license, indicate your decision by deleting the
|
||||
provisions above and replace them with the notice and other provisions
|
||||
required by the GPL in this and the other files of this package. If you do
|
||||
not delete the provisions above, a recipient may use your version of this
|
||||
file under either the BSD or the GPL.
|
20
libev/Makefile.am
Normal file
@ -0,0 +1,20 @@
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
|
||||
VERSION_INFO = 4:0:0
|
||||
|
||||
EXTRA_DIST = LICENSE Changes libev.m4 autogen.sh \
|
||||
ev_vars.h ev_wrap.h \
|
||||
ev_epoll.c ev_select.c ev_poll.c ev_kqueue.c ev_port.c ev_win32.c \
|
||||
ev.3 ev.pod Symbols.ev Symbols.event
|
||||
|
||||
man_MANS = ev.3
|
||||
|
||||
include_HEADERS = ev.h ev++.h event.h
|
||||
|
||||
lib_LTLIBRARIES = libev.la
|
||||
|
||||
libev_la_SOURCES = ev.c event.c
|
||||
libev_la_LDFLAGS = -version-info $(VERSION_INFO)
|
||||
|
||||
ev.3: ev.pod
|
||||
pod2man -n LIBEV -r "libev-$(VERSION)" -c "libev - high performance full featured event loop" -s3 <$< >$@
|
58
libev/README
Normal file
@ -0,0 +1,58 @@
|
||||
libev is a high-performance event loop/event model with lots of features.
|
||||
(see benchmark at http://libev.schmorp.de/bench.html)
|
||||
|
||||
|
||||
ABOUT
|
||||
|
||||
Homepage: http://software.schmorp.de/pkg/libev
|
||||
Mailinglist: libev@lists.schmorp.de
|
||||
http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev
|
||||
Library Documentation: http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod
|
||||
|
||||
Libev is modelled (very losely) after libevent and the Event perl
|
||||
module, but is faster, scales better and is more correct, and also more
|
||||
featureful. And also smaller. Yay.
|
||||
|
||||
Some of the specialties of libev not commonly found elsewhere are:
|
||||
|
||||
- extensive and detailed, readable documentation (not doxygen garbage).
|
||||
- fully supports fork, can detect fork in various ways and automatically
|
||||
re-arms kernel mechanisms that do not support fork.
|
||||
- highly optimised select, poll, epoll, kqueue and event ports backends.
|
||||
- filesystem object (path) watching (with optional linux inotify support).
|
||||
- wallclock-based times (using absolute time, cron-like).
|
||||
- relative timers/timeouts (handle time jumps).
|
||||
- fast intra-thread communication between multiple
|
||||
event loops (with optional fast linux eventfd backend).
|
||||
- extremely easy to embed (fully documented, no dependencies,
|
||||
autoconf supported but optional).
|
||||
- very small codebase, no bloated library, simple code.
|
||||
- fully extensible by being able to plug into the event loop,
|
||||
integrate other event loops, integrate other event loop users.
|
||||
- very little memory use (small watchers, small event loop data).
|
||||
- optional C++ interface allowing method and function callbacks
|
||||
at no extra memory or runtime overhead.
|
||||
- optional Perl interface with similar characteristics (capable
|
||||
of running Glib/Gtk2 on libev).
|
||||
- support for other languages (multiple C++ interfaces, D, Ruby,
|
||||
Python) available from third-parties.
|
||||
|
||||
Examples of programs that embed libev: the EV perl module, node.js,
|
||||
auditd, rxvt-unicode, gvpe (GNU Virtual Private Ethernet), the
|
||||
Deliantra MMORPG server (http://www.deliantra.net/), Rubinius (a
|
||||
next-generation Ruby VM), the Ebb web server, the Rev event toolkit.
|
||||
|
||||
|
||||
CONTRIBUTORS
|
||||
|
||||
libev was written and designed by Marc Lehmann and Emanuele Giaquinta.
|
||||
|
||||
The following people sent in patches or made other noteworthy
|
||||
contributions to the design (for minor patches, see the Changes
|
||||
file. If I forgot to include you, please shout at me, it was an
|
||||
accident):
|
||||
|
||||
W.C.A. Wijngaards
|
||||
Christopher Layne
|
||||
Chris Brody
|
||||
|
3
libev/README.embed
Normal file
@ -0,0 +1,3 @@
|
||||
This file is now included in the main libev documentation, see
|
||||
|
||||
http://cvs.schmorp.de/libev/ev.html
|
73
libev/Symbols.ev
Normal file
@ -0,0 +1,73 @@
|
||||
ev_async_send
|
||||
ev_async_start
|
||||
ev_async_stop
|
||||
ev_backend
|
||||
ev_break
|
||||
ev_check_start
|
||||
ev_check_stop
|
||||
ev_child_start
|
||||
ev_child_stop
|
||||
ev_cleanup_start
|
||||
ev_cleanup_stop
|
||||
ev_clear_pending
|
||||
ev_default_loop
|
||||
ev_default_loop_ptr
|
||||
ev_depth
|
||||
ev_embed_start
|
||||
ev_embed_stop
|
||||
ev_embed_sweep
|
||||
ev_embeddable_backends
|
||||
ev_feed_event
|
||||
ev_feed_fd_event
|
||||
ev_feed_signal
|
||||
ev_feed_signal_event
|
||||
ev_fork_start
|
||||
ev_fork_stop
|
||||
ev_idle_start
|
||||
ev_idle_stop
|
||||
ev_invoke
|
||||
ev_invoke_pending
|
||||
ev_io_start
|
||||
ev_io_stop
|
||||
ev_iteration
|
||||
ev_loop_destroy
|
||||
ev_loop_fork
|
||||
ev_loop_new
|
||||
ev_now
|
||||
ev_now_update
|
||||
ev_once
|
||||
ev_pending_count
|
||||
ev_periodic_again
|
||||
ev_periodic_start
|
||||
ev_periodic_stop
|
||||
ev_prepare_start
|
||||
ev_prepare_stop
|
||||
ev_recommended_backends
|
||||
ev_ref
|
||||
ev_resume
|
||||
ev_run
|
||||
ev_set_allocator
|
||||
ev_set_invoke_pending_cb
|
||||
ev_set_io_collect_interval
|
||||
ev_set_loop_release_cb
|
||||
ev_set_syserr_cb
|
||||
ev_set_timeout_collect_interval
|
||||
ev_set_userdata
|
||||
ev_signal_start
|
||||
ev_signal_stop
|
||||
ev_sleep
|
||||
ev_stat_start
|
||||
ev_stat_stat
|
||||
ev_stat_stop
|
||||
ev_supported_backends
|
||||
ev_suspend
|
||||
ev_time
|
||||
ev_timer_again
|
||||
ev_timer_remaining
|
||||
ev_timer_start
|
||||
ev_timer_stop
|
||||
ev_unref
|
||||
ev_userdata
|
||||
ev_verify
|
||||
ev_version_major
|
||||
ev_version_minor
|