diff options
-rw-r--r-- | auto_tests/CMakeLists.txt | 4 | ||||
-rw-r--r-- | auto_tests/cmake/crypto_test.cmake | 10 | ||||
-rw-r--r-- | auto_tests/crypto_test.c | 230 | ||||
-rwxr-xr-x | auto_tests/run_tests | 2 | ||||
-rw-r--r-- | core/net_crypto.c | 97 | ||||
-rw-r--r-- | core/net_crypto.h | 16 | ||||
-rw-r--r-- | other/CMakeLists.txt | 2 |
7 files changed, 340 insertions, 21 deletions
diff --git a/auto_tests/CMakeLists.txt b/auto_tests/CMakeLists.txt index fbbcb7d7..c0b6aee4 100644 --- a/auto_tests/CMakeLists.txt +++ b/auto_tests/CMakeLists.txt | |||
@@ -5,16 +5,18 @@ include_directories(${CHECK_INCLUDE_DIRS}) | |||
5 | 5 | ||
6 | find_package(Check REQUIRED) | 6 | find_package(Check REQUIRED) |
7 | include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/messenger_test.cmake) | 7 | include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/messenger_test.cmake) |
8 | include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/crypto_test.cmake) | ||
8 | include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/friends_test.cmake) | 9 | include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/friends_test.cmake) |
9 | 10 | ||
10 | include( CTest ) | 11 | include( CTest ) |
11 | enable_testing() | 12 | enable_testing() |
12 | 13 | ||
13 | add_test(messenger messenger_test) | 14 | add_test(messenger messenger_test) |
15 | add_test(crypto crypto_test) | ||
14 | # TODO enable once test is fixed | 16 | # TODO enable once test is fixed |
15 | #add_test(friends friends_test) | 17 | #add_test(friends friends_test) |
16 | 18 | ||
17 | add_custom_target( | 19 | add_custom_target( |
18 | test COMMAND ${CMAKE_CTEST_COMMAND} -V | 20 | test COMMAND ${CMAKE_CTEST_COMMAND} -V |
19 | DEPENDS messenger_test | 21 | DEPENDS messenger_test crypto_test |
20 | ) | 22 | ) |
diff --git a/auto_tests/cmake/crypto_test.cmake b/auto_tests/cmake/crypto_test.cmake new file mode 100644 index 00000000..9ca9a331 --- /dev/null +++ b/auto_tests/cmake/crypto_test.cmake | |||
@@ -0,0 +1,10 @@ | |||
1 | cmake_minimum_required(VERSION 2.6.0) | ||
2 | project(crypto_test C) | ||
3 | set(exe_name crypto_test) | ||
4 | |||
5 | add_executable(${exe_name} | ||
6 | crypto_test.c) | ||
7 | |||
8 | linkCoreLibraries(${exe_name}) | ||
9 | add_dependencies(${exe_name} Check) | ||
10 | target_link_libraries(${exe_name} check) | ||
diff --git a/auto_tests/crypto_test.c b/auto_tests/crypto_test.c new file mode 100644 index 00000000..9ac81349 --- /dev/null +++ b/auto_tests/crypto_test.c | |||
@@ -0,0 +1,230 @@ | |||
1 | #include "../core/net_crypto.h" | ||
2 | #include <sys/types.h> | ||
3 | #include <stdint.h> | ||
4 | #include <string.h> | ||
5 | #include <check.h> | ||
6 | #include <stdlib.h> | ||
7 | #include <time.h> | ||
8 | #include <sodium.h> | ||
9 | |||
10 | void rand_bytes(uint8_t *b, size_t blen) | ||
11 | { | ||
12 | size_t i; | ||
13 | for (i = 0; i < blen; i++) | ||
14 | { | ||
15 | b[i] = rand(); | ||
16 | } | ||
17 | } | ||
18 | |||
19 | // These test vectors are from libsodium's test suite | ||
20 | |||
21 | unsigned char alicesk[32] = { | ||
22 | 0x77,0x07,0x6d,0x0a,0x73,0x18,0xa5,0x7d, | ||
23 | 0x3c,0x16,0xc1,0x72,0x51,0xb2,0x66,0x45, | ||
24 | 0xdf,0x4c,0x2f,0x87,0xeb,0xc0,0x99,0x2a, | ||
25 | 0xb1,0x77,0xfb,0xa5,0x1d,0xb9,0x2c,0x2a | ||
26 | }; | ||
27 | |||
28 | unsigned char bobpk[32] = { | ||
29 | 0xde,0x9e,0xdb,0x7d,0x7b,0x7d,0xc1,0xb4, | ||
30 | 0xd3,0x5b,0x61,0xc2,0xec,0xe4,0x35,0x37, | ||
31 | 0x3f,0x83,0x43,0xc8,0x5b,0x78,0x67,0x4d, | ||
32 | 0xad,0xfc,0x7e,0x14,0x6f,0x88,0x2b,0x4f | ||
33 | }; | ||
34 | |||
35 | unsigned char nonce[24] = { | ||
36 | 0x69,0x69,0x6e,0xe9,0x55,0xb6,0x2b,0x73, | ||
37 | 0xcd,0x62,0xbd,0xa8,0x75,0xfc,0x73,0xd6, | ||
38 | 0x82,0x19,0xe0,0x03,0x6b,0x7a,0x0b,0x37 | ||
39 | }; | ||
40 | |||
41 | unsigned char test_m[131] = { | ||
42 | 0xbe,0x07,0x5f,0xc5,0x3c,0x81,0xf2,0xd5, | ||
43 | 0xcf,0x14,0x13,0x16,0xeb,0xeb,0x0c,0x7b, | ||
44 | 0x52,0x28,0xc5,0x2a,0x4c,0x62,0xcb,0xd4, | ||
45 | 0x4b,0x66,0x84,0x9b,0x64,0x24,0x4f,0xfc, | ||
46 | 0xe5,0xec,0xba,0xaf,0x33,0xbd,0x75,0x1a, | ||
47 | 0x1a,0xc7,0x28,0xd4,0x5e,0x6c,0x61,0x29, | ||
48 | 0x6c,0xdc,0x3c,0x01,0x23,0x35,0x61,0xf4, | ||
49 | 0x1d,0xb6,0x6c,0xce,0x31,0x4a,0xdb,0x31, | ||
50 | 0x0e,0x3b,0xe8,0x25,0x0c,0x46,0xf0,0x6d, | ||
51 | 0xce,0xea,0x3a,0x7f,0xa1,0x34,0x80,0x57, | ||
52 | 0xe2,0xf6,0x55,0x6a,0xd6,0xb1,0x31,0x8a, | ||
53 | 0x02,0x4a,0x83,0x8f,0x21,0xaf,0x1f,0xde, | ||
54 | 0x04,0x89,0x77,0xeb,0x48,0xf5,0x9f,0xfd, | ||
55 | 0x49,0x24,0xca,0x1c,0x60,0x90,0x2e,0x52, | ||
56 | 0xf0,0xa0,0x89,0xbc,0x76,0x89,0x70,0x40, | ||
57 | 0xe0,0x82,0xf9,0x37,0x76,0x38,0x48,0x64, | ||
58 | 0x5e,0x07,0x05 | ||
59 | }; | ||
60 | |||
61 | unsigned char test_c[147] = { | ||
62 | 0xf3,0xff,0xc7,0x70,0x3f,0x94,0x00,0xe5, | ||
63 | 0x2a,0x7d,0xfb,0x4b,0x3d,0x33,0x05,0xd9, | ||
64 | 0x8e,0x99,0x3b,0x9f,0x48,0x68,0x12,0x73, | ||
65 | 0xc2,0x96,0x50,0xba,0x32,0xfc,0x76,0xce, | ||
66 | 0x48,0x33,0x2e,0xa7,0x16,0x4d,0x96,0xa4, | ||
67 | 0x47,0x6f,0xb8,0xc5,0x31,0xa1,0x18,0x6a, | ||
68 | 0xc0,0xdf,0xc1,0x7c,0x98,0xdc,0xe8,0x7b, | ||
69 | 0x4d,0xa7,0xf0,0x11,0xec,0x48,0xc9,0x72, | ||
70 | 0x71,0xd2,0xc2,0x0f,0x9b,0x92,0x8f,0xe2, | ||
71 | 0x27,0x0d,0x6f,0xb8,0x63,0xd5,0x17,0x38, | ||
72 | 0xb4,0x8e,0xee,0xe3,0x14,0xa7,0xcc,0x8a, | ||
73 | 0xb9,0x32,0x16,0x45,0x48,0xe5,0x26,0xae, | ||
74 | 0x90,0x22,0x43,0x68,0x51,0x7a,0xcf,0xea, | ||
75 | 0xbd,0x6b,0xb3,0x73,0x2b,0xc0,0xe9,0xda, | ||
76 | 0x99,0x83,0x2b,0x61,0xca,0x01,0xb6,0xde, | ||
77 | 0x56,0x24,0x4a,0x9e,0x88,0xd5,0xf9,0xb3, | ||
78 | 0x79,0x73,0xf6,0x22,0xa4,0x3d,0x14,0xa6, | ||
79 | 0x59,0x9b,0x1f,0x65,0x4c,0xb4,0x5a,0x74, | ||
80 | 0xe3,0x55,0xa5 | ||
81 | }; | ||
82 | |||
83 | START_TEST(test_known) | ||
84 | { | ||
85 | unsigned char c[147]; | ||
86 | unsigned char m[131]; | ||
87 | int clen, mlen; | ||
88 | |||
89 | ck_assert_msg(sizeof(c) == sizeof(m) + ENCRYPTION_PADDING * sizeof(unsigned char), "cyphertext should be ENCRYPTION_PADDING bytes longer than plaintext"); | ||
90 | ck_assert_msg(sizeof(test_c) == sizeof(c), "sanity check failed"); | ||
91 | ck_assert_msg(sizeof(test_m) == sizeof(m), "sanity check failed"); | ||
92 | |||
93 | clen = encrypt_data(bobpk, alicesk, nonce, test_m, sizeof(test_m)/sizeof(unsigned char), c); | ||
94 | |||
95 | ck_assert_msg(memcmp(test_c, c, sizeof(c)) == 0, "cyphertext doesn't match test vector"); | ||
96 | ck_assert_msg(clen == sizeof(c)/sizeof(unsigned char), "wrong ciphertext length"); | ||
97 | |||
98 | mlen = decrypt_data(bobpk, alicesk, nonce, test_c, sizeof(test_c)/sizeof(unsigned char), m); | ||
99 | |||
100 | ck_assert_msg(memcmp(test_m, m, sizeof(m)) == 0, "decrypted text doesn't match test vector"); | ||
101 | ck_assert_msg(mlen == sizeof(m)/sizeof(unsigned char), "wrong plaintext length"); | ||
102 | } | ||
103 | END_TEST | ||
104 | |||
105 | START_TEST(test_fast_known) | ||
106 | { | ||
107 | unsigned char k[crypto_box_BEFORENMBYTES]; | ||
108 | unsigned char c[147]; | ||
109 | unsigned char m[131]; | ||
110 | int clen, mlen; | ||
111 | |||
112 | encrypt_precompute(bobpk, alicesk, k); | ||
113 | |||
114 | ck_assert_msg(sizeof(c) == sizeof(m) + ENCRYPTION_PADDING * sizeof(unsigned char), "cyphertext should be ENCRYPTION_PADDING bytes longer than plaintext"); | ||
115 | ck_assert_msg(sizeof(test_c) == sizeof(c), "sanity check failed"); | ||
116 | ck_assert_msg(sizeof(test_m) == sizeof(m), "sanity check failed"); | ||
117 | |||
118 | clen = encrypt_data_fast(k, nonce, test_m, sizeof(test_m)/sizeof(unsigned char), c); | ||
119 | |||
120 | ck_assert_msg(memcmp(test_c, c, sizeof(c)) == 0, "cyphertext doesn't match test vector"); | ||
121 | ck_assert_msg(clen == sizeof(c)/sizeof(unsigned char), "wrong ciphertext length"); | ||
122 | |||
123 | mlen = decrypt_data_fast(k, nonce, test_c, sizeof(test_c)/sizeof(unsigned char), m); | ||
124 | |||
125 | ck_assert_msg(memcmp(test_m, m, sizeof(m)) == 0, "decrypted text doesn't match test vector"); | ||
126 | ck_assert_msg(mlen == sizeof(m)/sizeof(unsigned char), "wrong plaintext length"); | ||
127 | |||
128 | } | ||
129 | END_TEST | ||
130 | |||
131 | START_TEST(test_endtoend) | ||
132 | { | ||
133 | unsigned char pk1[crypto_box_PUBLICKEYBYTES]; | ||
134 | unsigned char sk1[crypto_box_SECRETKEYBYTES]; | ||
135 | unsigned char pk2[crypto_box_PUBLICKEYBYTES]; | ||
136 | unsigned char sk2[crypto_box_SECRETKEYBYTES]; | ||
137 | unsigned char k1[crypto_box_BEFORENMBYTES]; | ||
138 | unsigned char k2[crypto_box_BEFORENMBYTES]; | ||
139 | |||
140 | unsigned char n[crypto_box_NONCEBYTES]; | ||
141 | |||
142 | unsigned char m[500]; | ||
143 | unsigned char c1[sizeof(m) + ENCRYPTION_PADDING]; | ||
144 | unsigned char c2[sizeof(m) + ENCRYPTION_PADDING]; | ||
145 | unsigned char c3[sizeof(m) + ENCRYPTION_PADDING]; | ||
146 | unsigned char c4[sizeof(m) + ENCRYPTION_PADDING]; | ||
147 | unsigned char m1[sizeof(m)]; | ||
148 | unsigned char m2[sizeof(m)]; | ||
149 | unsigned char m3[sizeof(m)]; | ||
150 | unsigned char m4[sizeof(m)]; | ||
151 | |||
152 | int mlen; | ||
153 | int c1len, c2len, c3len, c4len; | ||
154 | int m1len, m2len, m3len, m4len; | ||
155 | |||
156 | int testno; | ||
157 | |||
158 | // Test 100 random messages and keypairs | ||
159 | for (testno = 0; testno < 100; testno++) | ||
160 | { | ||
161 | //Generate random message (random length from 100 to 500) | ||
162 | mlen = (rand() % 400) + 100; | ||
163 | rand_bytes(m, mlen); | ||
164 | rand_bytes(n, crypto_box_NONCEBYTES); | ||
165 | |||
166 | //Generate keypairs | ||
167 | crypto_box_keypair(pk1,sk1); | ||
168 | crypto_box_keypair(pk2,sk2); | ||
169 | |||
170 | //Precompute shared keys | ||
171 | encrypt_precompute(pk2, sk1, k1); | ||
172 | encrypt_precompute(pk1, sk2, k2); | ||
173 | |||
174 | ck_assert_msg(memcmp(k1, k2, crypto_box_BEFORENMBYTES) == 0, "encrypt_precompute: bad"); | ||
175 | |||
176 | //Encrypt all four ways | ||
177 | c1len = encrypt_data(pk2, sk1, n, m, mlen, c1); | ||
178 | c2len = encrypt_data(pk1, sk2, n, m, mlen, c2); | ||
179 | c3len = encrypt_data_fast(k1, n, m, mlen, c3); | ||
180 | c4len = encrypt_data_fast(k2, n, m, mlen, c4); | ||
181 | |||
182 | ck_assert_msg(c1len == c2len && c1len == c3len && c1len == c4len, "cyphertext lengths differ"); | ||
183 | ck_assert_msg(c1len == mlen + ENCRYPTION_PADDING, "wrong cyphertext length"); | ||
184 | ck_assert_msg(memcmp(c1, c2, c1len) == 0 && memcmp(c1, c3, c1len) == 0 && memcmp(c1, c4, c1len) == 0, "crypertexts differ"); | ||
185 | |||
186 | //Decrypt all four ways | ||
187 | m1len = decrypt_data(pk2, sk1, n, c1, c1len, m1); | ||
188 | m2len = decrypt_data(pk1, sk2, n, c1, c1len, m2); | ||
189 | m3len = decrypt_data_fast(k1, n, c1, c1len, m3); | ||
190 | m4len = decrypt_data_fast(k2, n, c1, c1len, m4); | ||
191 | |||
192 | ck_assert_msg(m1len == m2len && m1len == m3len && m1len == m4len, "decrypted text lengths differ"); | ||
193 | ck_assert_msg(m1len == mlen, "wrong decrypted text length"); | ||
194 | ck_assert_msg(memcmp(m1, m2, mlen) == 0 && memcmp(m1, m3, mlen) == 0 && memcmp(m1, m4, mlen) == 0, "decrypted texts differ"); | ||
195 | ck_assert_msg(memcmp(m1, m, mlen) == 0, "wrong decrypted text"); | ||
196 | } | ||
197 | } | ||
198 | END_TEST | ||
199 | |||
200 | #define DEFTESTCASE(NAME) \ | ||
201 | TCase *NAME = tcase_create(#NAME); \ | ||
202 | tcase_add_test(NAME, test_##NAME); \ | ||
203 | suite_add_tcase(s, NAME); | ||
204 | |||
205 | Suite* crypto_suite(void) | ||
206 | { | ||
207 | Suite *s = suite_create("Crypto"); | ||
208 | |||
209 | DEFTESTCASE(known); | ||
210 | DEFTESTCASE(fast_known); | ||
211 | DEFTESTCASE(endtoend); | ||
212 | |||
213 | return s; | ||
214 | } | ||
215 | |||
216 | int main(int argc, char* argv[]) | ||
217 | { | ||
218 | srand((unsigned int) time(NULL)); | ||
219 | |||
220 | Suite *crypto = crypto_suite(); | ||
221 | SRunner *test_runner = srunner_create(crypto); | ||
222 | int number_failed = 0; | ||
223 | |||
224 | srunner_run_all(test_runner, CK_NORMAL); | ||
225 | number_failed = srunner_ntests_failed(test_runner); | ||
226 | |||
227 | srunner_free(test_runner); | ||
228 | |||
229 | return number_failed; | ||
230 | } | ||
diff --git a/auto_tests/run_tests b/auto_tests/run_tests index 4448b2e2..1899f354 100755 --- a/auto_tests/run_tests +++ b/auto_tests/run_tests | |||
@@ -2,4 +2,4 @@ | |||
2 | # run_tests - run the current tests for tox core | 2 | # run_tests - run the current tests for tox core |
3 | set -e | 3 | set -e |
4 | 4 | ||
5 | ./messenger_test && ./friends_test | 5 | ./messenger_test && ./friends_test && ./crypto_test |
diff --git a/core/net_crypto.c b/core/net_crypto.c index 1c56b95a..1803caba 100644 --- a/core/net_crypto.c +++ b/core/net_crypto.c | |||
@@ -37,6 +37,7 @@ typedef struct { | |||
37 | uint8_t sessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* our public key for this session. */ | 37 | uint8_t sessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* our public key for this session. */ |
38 | uint8_t sessionsecret_key[crypto_box_SECRETKEYBYTES]; /* our private key for this session. */ | 38 | uint8_t sessionsecret_key[crypto_box_SECRETKEYBYTES]; /* our private key for this session. */ |
39 | uint8_t peersessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* The public key of the peer. */ | 39 | uint8_t peersessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* The public key of the peer. */ |
40 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; /* the precomputed shared key from encrypt_precompute */ | ||
40 | uint8_t status; /* 0 if no connection, 1 we have sent a handshake, 2 if connexion is not confirmed yet | 41 | uint8_t status; /* 0 if no connection, 1 we have sent a handshake, 2 if connexion is not confirmed yet |
41 | (we have received a handshake but no empty data packet), 3 if the connection is established. | 42 | (we have received a handshake but no empty data packet), 3 if the connection is established. |
42 | 4 if the connection is timed out. */ | 43 | 4 if the connection is timed out. */ |
@@ -59,6 +60,17 @@ static Crypto_Connection crypto_connections[MAX_CRYPTO_CONNECTIONS]; | |||
59 | /* keeps track of the connection numbers for friends request so we can check later if they were sent */ | 60 | /* keeps track of the connection numbers for friends request so we can check later if they were sent */ |
60 | static int incoming_connections[MAX_INCOMING]; | 61 | static int incoming_connections[MAX_INCOMING]; |
61 | 62 | ||
63 | /* Use this instead of memcmp; not vulnerable to timing attacks. */ | ||
64 | uint8_t crypto_iszero(uint8_t *mem, uint32_t length) | ||
65 | { | ||
66 | uint8_t check = 0; | ||
67 | uint32_t i; | ||
68 | for (i = 0; i < length; ++i) { | ||
69 | check |= mem[i]; | ||
70 | } | ||
71 | return check; // We return zero if mem is made out of zeroes. | ||
72 | } | ||
73 | |||
62 | /* encrypts plain of length length to encrypted of length + 16 using the | 74 | /* encrypts plain of length length to encrypted of length + 16 using the |
63 | public key(32 bytes) of the receiver and the secret key of the sender and a 24 byte nonce | 75 | public key(32 bytes) of the receiver and the secret key of the sender and a 24 byte nonce |
64 | return -1 if there was a problem. | 76 | return -1 if there was a problem. |
@@ -78,12 +90,38 @@ int encrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, | |||
78 | 90 | ||
79 | /* if encryption is successful the first crypto_box_BOXZEROBYTES of the message will be zero | 91 | /* if encryption is successful the first crypto_box_BOXZEROBYTES of the message will be zero |
80 | apparently memcmp should not be used so we do this instead:*/ | 92 | apparently memcmp should not be used so we do this instead:*/ |
81 | uint32_t i; | 93 | if(crypto_iszero(temp_encrypted, crypto_box_BOXZEROBYTES) != 0) |
82 | uint32_t check = 0; | 94 | return -1; |
83 | for(i = 0; i < crypto_box_BOXZEROBYTES; ++i) { | 95 | |
84 | check |= temp_encrypted[i] ^ 0; | 96 | /* unpad the encrypted message */ |
85 | } | 97 | memcpy(encrypted, temp_encrypted + crypto_box_BOXZEROBYTES, length + crypto_box_MACBYTES); |
86 | if(check != 0) | 98 | return length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES; |
99 | } | ||
100 | |||
101 | /* Precomputes the shared key from their public_key and our secret_key. | ||
102 | This way we can avoid an expensive elliptic curve scalar multiply for each | ||
103 | encrypt/decrypt operation. | ||
104 | enc_key has to be crypto_box_BEFORENMBYTES bytes long. */ | ||
105 | void encrypt_precompute(uint8_t *public_key, uint8_t *secret_key, uint8_t *enc_key) | ||
106 | { | ||
107 | crypto_box_beforenm(enc_key, public_key, secret_key); | ||
108 | } | ||
109 | |||
110 | /* Fast encrypt. Depends on enc_key from encrypt_precompute. */ | ||
111 | int encrypt_data_fast(uint8_t *enc_key, uint8_t *nonce, | ||
112 | uint8_t *plain, uint32_t length, uint8_t *encrypted) | ||
113 | { | ||
114 | if (length + crypto_box_MACBYTES > MAX_DATA_SIZE || length == 0) | ||
115 | return -1; | ||
116 | |||
117 | uint8_t temp_plain[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES] = {0}; | ||
118 | uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES]; | ||
119 | |||
120 | memcpy(temp_plain + crypto_box_ZEROBYTES, plain, length); /* pad the message with 32 0 bytes. */ | ||
121 | |||
122 | crypto_box_afternm(temp_encrypted, temp_plain, length + crypto_box_ZEROBYTES, nonce, enc_key); | ||
123 | |||
124 | if(crypto_iszero(temp_encrypted, crypto_box_BOXZEROBYTES) != 0) | ||
87 | return -1; | 125 | return -1; |
88 | 126 | ||
89 | /* unpad the encrypted message */ | 127 | /* unpad the encrypted message */ |
@@ -112,12 +150,33 @@ int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, | |||
112 | 150 | ||
113 | /* if decryption is successful the first crypto_box_ZEROBYTES of the message will be zero | 151 | /* if decryption is successful the first crypto_box_ZEROBYTES of the message will be zero |
114 | apparently memcmp should not be used so we do this instead:*/ | 152 | apparently memcmp should not be used so we do this instead:*/ |
115 | uint32_t i; | 153 | if(crypto_iszero(temp_plain, crypto_box_ZEROBYTES) != 0) |
116 | uint32_t check = 0; | 154 | return -1; |
117 | for(i = 0; i < crypto_box_ZEROBYTES; ++i) { | 155 | |
118 | check |= temp_plain[i] ^ 0; | 156 | /* unpad the plain message */ |
119 | } | 157 | memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_MACBYTES); |
120 | if(check != 0) | 158 | return length - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES; |
159 | } | ||
160 | |||
161 | /* Fast decrypt. Depends on enc_ley from encrypt_precompute. */ | ||
162 | int decrypt_data_fast(uint8_t *enc_key, uint8_t *nonce, | ||
163 | uint8_t *encrypted, uint32_t length, uint8_t *plain) | ||
164 | { | ||
165 | if (length > MAX_DATA_SIZE || length <= crypto_box_BOXZEROBYTES) | ||
166 | return -1; | ||
167 | |||
168 | uint8_t temp_plain[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES]; | ||
169 | uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES] = {0}; | ||
170 | |||
171 | memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); /* pad the message with 16 0 bytes. */ | ||
172 | |||
173 | if (crypto_box_open_afternm(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES, | ||
174 | nonce, enc_key) == -1) | ||
175 | return -1; | ||
176 | |||
177 | /* if decryption is successful the first crypto_box_ZEROBYTES of the message will be zero | ||
178 | apparently memcmp should not be used so we do this instead:*/ | ||
179 | if(crypto_iszero(temp_plain, crypto_box_ZEROBYTES) != 0) | ||
121 | return -1; | 180 | return -1; |
122 | 181 | ||
123 | /* unpad the plain message */ | 182 | /* unpad the plain message */ |
@@ -161,9 +220,9 @@ int read_cryptpacket(int crypt_connection_id, uint8_t *data) | |||
161 | return 0; | 220 | return 0; |
162 | if (temp_data[0] != 3) | 221 | if (temp_data[0] != 3) |
163 | return -1; | 222 | return -1; |
164 | int len = decrypt_data(crypto_connections[crypt_connection_id].peersessionpublic_key, | 223 | int len = decrypt_data_fast(crypto_connections[crypt_connection_id].shared_key, |
165 | crypto_connections[crypt_connection_id].sessionsecret_key, | 224 | crypto_connections[crypt_connection_id].recv_nonce, |
166 | crypto_connections[crypt_connection_id].recv_nonce, temp_data + 1, length - 1, data); | 225 | temp_data + 1, length - 1, data); |
167 | if (len != -1) { | 226 | if (len != -1) { |
168 | increment_nonce(crypto_connections[crypt_connection_id].recv_nonce); | 227 | increment_nonce(crypto_connections[crypt_connection_id].recv_nonce); |
169 | return len; | 228 | return len; |
@@ -182,9 +241,9 @@ int write_cryptpacket(int crypt_connection_id, uint8_t *data, uint32_t length) | |||
182 | if (crypto_connections[crypt_connection_id].status != CONN_ESTABLISHED) | 241 | if (crypto_connections[crypt_connection_id].status != CONN_ESTABLISHED) |
183 | return 0; | 242 | return 0; |
184 | uint8_t temp_data[MAX_DATA_SIZE]; | 243 | uint8_t temp_data[MAX_DATA_SIZE]; |
185 | int len = encrypt_data(crypto_connections[crypt_connection_id].peersessionpublic_key, | 244 | int len = encrypt_data_fast(crypto_connections[crypt_connection_id].shared_key, |
186 | crypto_connections[crypt_connection_id].sessionsecret_key, | 245 | crypto_connections[crypt_connection_id].sent_nonce, |
187 | crypto_connections[crypt_connection_id].sent_nonce, data, length, temp_data + 1); | 246 | data, length, temp_data + 1); |
188 | if (len == -1) | 247 | if (len == -1) |
189 | return 0; | 248 | return 0; |
190 | temp_data[0] = 3; | 249 | temp_data[0] = 3; |
@@ -408,6 +467,7 @@ int accept_crypto_inbound(int connection_id, uint8_t *public_key, uint8_t *secre | |||
408 | random_nonce(crypto_connections[i].recv_nonce); | 467 | random_nonce(crypto_connections[i].recv_nonce); |
409 | memcpy(crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES); | 468 | memcpy(crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES); |
410 | memcpy(crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES); | 469 | memcpy(crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES); |
470 | |||
411 | increment_nonce(crypto_connections[i].sent_nonce); | 471 | increment_nonce(crypto_connections[i].sent_nonce); |
412 | memcpy(crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES); | 472 | memcpy(crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES); |
413 | 473 | ||
@@ -509,6 +569,7 @@ static void receive_crypto(void) | |||
509 | if (memcmp(public_key, crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) { | 569 | if (memcmp(public_key, crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) { |
510 | memcpy(crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES); | 570 | memcpy(crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES); |
511 | memcpy(crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES); | 571 | memcpy(crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES); |
572 | encrypt_precompute(crypto_connections[i].peersessionpublic_key, crypto_connections[i].sessionsecret_key, crypto_connections[i].shared_key); | ||
512 | increment_nonce(crypto_connections[i].sent_nonce); | 573 | increment_nonce(crypto_connections[i].sent_nonce); |
513 | uint32_t zero = 0; | 574 | uint32_t zero = 0; |
514 | crypto_connections[i].status = CONN_ESTABLISHED; /* connection status needs to be 3 for write_cryptpacket() to work */ | 575 | crypto_connections[i].status = CONN_ESTABLISHED; /* connection status needs to be 3 for write_cryptpacket() to work */ |
diff --git a/core/net_crypto.h b/core/net_crypto.h index 66634d45..135e099d 100644 --- a/core/net_crypto.h +++ b/core/net_crypto.h | |||
@@ -36,6 +36,9 @@ extern uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; | |||
36 | 36 | ||
37 | #define ENCRYPTION_PADDING (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES) | 37 | #define ENCRYPTION_PADDING (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES) |
38 | 38 | ||
39 | /* returns zero if the buffer contains only zeros */ | ||
40 | uint8_t crypto_iszero(uint8_t* buffer, uint32_t blen); | ||
41 | |||
39 | /* encrypts plain of length length to encrypted of length + 16 using the | 42 | /* encrypts plain of length length to encrypted of length + 16 using the |
40 | public key(32 bytes) of the receiver and the secret key of the sender and a 24 byte nonce | 43 | public key(32 bytes) of the receiver and the secret key of the sender and a 24 byte nonce |
41 | return -1 if there was a problem. | 44 | return -1 if there was a problem. |
@@ -51,6 +54,19 @@ int encrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, | |||
51 | int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, | 54 | int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, |
52 | uint8_t *encrypted, uint32_t length, uint8_t *plain); | 55 | uint8_t *encrypted, uint32_t length, uint8_t *plain); |
53 | 56 | ||
57 | /* Fast encrypt/decrypt operations. Use if this is not a one-time communication. | ||
58 | encrypt_precompute does the shared-key generation once so it does not have | ||
59 | to be preformed on every encrypt/decrypt. */ | ||
60 | void encrypt_precompute(uint8_t *public_key, uint8_t *secret_key, uint8_t *enc_key); | ||
61 | |||
62 | /* Fast encrypt. Depends on enc_key from encrypt_precompute. */ | ||
63 | int encrypt_data_fast(uint8_t *enc_key, uint8_t *nonce, | ||
64 | uint8_t *plain, uint32_t length, uint8_t *encrypted); | ||
65 | |||
66 | /* Fast decrypt. Depends on enc_ley from encrypt_precompute. */ | ||
67 | int decrypt_data_fast(uint8_t *enc_key, uint8_t *nonce, | ||
68 | uint8_t *encrypted, uint32_t length, uint8_t *plain); | ||
69 | |||
54 | 70 | ||
55 | /* fill the given nonce with random bytes. */ | 71 | /* fill the given nonce with random bytes. */ |
56 | void random_nonce(uint8_t *nonce); | 72 | void random_nonce(uint8_t *nonce); |
diff --git a/other/CMakeLists.txt b/other/CMakeLists.txt index 05b24f06..db742e3e 100644 --- a/other/CMakeLists.txt +++ b/other/CMakeLists.txt | |||
@@ -4,6 +4,6 @@ cmake_policy(SET CMP0011 NEW) | |||
4 | 4 | ||
5 | include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/DHT_bootstrap.cmake) | 5 | include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/DHT_bootstrap.cmake) |
6 | 6 | ||
7 | if(NOT WIN32) | 7 | if(LINUX) |
8 | add_subdirectory(bootstrap_serverdaemon) | 8 | add_subdirectory(bootstrap_serverdaemon) |
9 | endif() | 9 | endif() |