Add randomized ETCP padding and isolate STCP CTR streams per connection

This commit is contained in:
evgeny committed 2026-10-07 10:45:42 +02:00
1 parent 1f5b42845b
commit a49cf5434e
31 files changed
+854 -103

No files matched your search

+30 -14
View File
@@ -34,11 +34,13 @@ int main(void) {
CHECK(sc_set_peer_public_key(&ctx_a, keys_b.public_key, SC_PEER_PUBKEY_BIN) == SC_OK, "set peer key A<-B");
CHECK(sc_set_peer_public_key(&ctx_b, keys_a.public_key, SC_PEER_PUBKEY_BIN) == SC_OK, "set peer key B<-A");
struct sc_stream_state send_a, recv_a, send_b, recv_b;
CHECK(sc_stream_init(&ctx_a, &send_a, 0) == SC_OK, "init send_A (id=0)");
CHECK(sc_stream_init(&ctx_a, &recv_a, 1) == SC_OK, "init recv_A (id=1)");
CHECK(sc_stream_init(&ctx_b, &recv_b, 0) == SC_OK, "init recv_B (id=0)");
CHECK(sc_stream_init(&ctx_b, &send_b, 1) == SC_OK, "init send_B (id=1)");
const uint8_t salt_a[SC_PUBKEY_ENC_SALT_SIZE] = {1, 2, 3, 4, 5, 6, 7, 8};
const uint8_t salt_b[SC_PUBKEY_ENC_SALT_SIZE] = {8, 7, 6, 5, 4, 3, 2, 1};
struct sc_stream_state send_a = {0}, recv_a = {0}, send_b = {0}, recv_b = {0};
CHECK(sc_stream_init(ctx_a.session_key, &send_a, 0, salt_a) == SC_OK, "init send_A (id=0, salt_A)");
CHECK(sc_stream_init(ctx_a.session_key, &recv_a, 1, salt_b) == SC_OK, "init recv_A (id=1, salt_B)");
CHECK(sc_stream_init(ctx_b.session_key, &recv_b, 0, salt_a) == SC_OK, "init recv_B (id=0, salt_A)");
CHECK(sc_stream_init(ctx_b.session_key, &send_b, 1, salt_b) == SC_OK, "init send_B (id=1, salt_B)");
uint8_t original[2048], data[2048];
for (int i = 0; i < (int)sizeof(original); i++) original[i] = (uint8_t)(i * 3 + 17);
@@ -109,20 +111,34 @@ int main(void) {
// Test 8: error handling
CHECK(sc_stream_xor(&send_a, NULL, 0) == SC_OK, "xor len=0 OK");
CHECK(sc_stream_xor(&send_a, data, 0) == SC_OK, "xor data_len=0 OK");
CHECK(sc_stream_init(&ctx_a, NULL, 0) == SC_ERR_INVALID_ARG, "init NULL state");
CHECK(sc_stream_init(NULL, &send_a, 0) == SC_ERR_INVALID_ARG, "init NULL ctx");
CHECK(sc_stream_init(ctx_a.session_key, NULL, 0, salt_a) == SC_ERR_INVALID_ARG, "init NULL state");
CHECK(sc_stream_init(NULL, &send_a, 0, salt_a) == SC_ERR_INVALID_ARG, "init NULL key");
CHECK(sc_stream_init(ctx_a.session_key, &send_a, 0, NULL) == SC_ERR_INVALID_ARG, "init NULL salt");
CHECK(sc_stream_init(ctx_a.session_key, &send_a, 0, salt_a) == SC_ERR_INVALID_ARG, "reject initialized stream reuse");
struct sc_stream_state uninit;
memset(&uninit, 0, sizeof(uninit));
CHECK(sc_stream_xor(&uninit, data, 1) == SC_ERR_NOT_INITIALIZED, "xor uninitialized");
// У ctx без session_ready
sc_context_t no_session_ctx;
struct SC_MYKEYS dummy_keys;
memset(&dummy_keys, 0, sizeof(dummy_keys));
sc_init_ctx(&no_session_ctx, &dummy_keys);
struct sc_stream_state bad_stream;
CHECK(sc_stream_init(&no_session_ctx, &bad_stream, 0) == SC_ERR_NOT_INITIALIZED, "init without session");
/* Одинаковые ключ, позиция и текст: отдельно проверяем влияние соли и направления на поток. */
for (uint32_t direction = 0; direction < 2; direction++) {
struct sc_stream_state first = {0}, repeat = {0}, fresh = {0}, opposite = {0};
uint8_t one[256] = {0}, same[256] = {0}, other[256] = {0}, reverse[256] = {0};
CHECK(sc_stream_init(ctx_a.session_key, &first, direction, salt_a) == SC_OK, "init reference stream");
CHECK(sc_stream_init(ctx_b.session_key, &repeat, direction, salt_a) == SC_OK, "init matching peer stream");
CHECK(sc_stream_init(ctx_a.session_key, &fresh, direction, salt_b) == SC_OK, "init fresh salt stream");
CHECK(sc_stream_init(ctx_a.session_key, &opposite, direction ^ 1, salt_a) == SC_OK, "init opposite direction");
CHECK(sc_stream_xor(&first, one, sizeof(one)) == SC_OK, "reference zero plaintext");
CHECK(sc_stream_xor(&repeat, same, sizeof(same)) == SC_OK, "matching zero plaintext");
CHECK(sc_stream_xor(&fresh, other, sizeof(other)) == SC_OK, "fresh salt zero plaintext");
CHECK(sc_stream_xor(&opposite, reverse, sizeof(reverse)) == SC_OK, "opposite direction zero plaintext");
CHECK(memcmp(one, same, sizeof(one)) == 0, "peer uses identical key/direction/salt");
CHECK(memcmp(one, other, 32) != 0, "fresh salt changes first 32 encrypted bytes");
CHECK(memcmp(one + 51, other + 51, 158) != 0, "fresh salt changes zero padding keystream");
CHECK(memcmp(one, reverse, sizeof(one)) != 0, "direction separates streams at equal position");
sc_stream_cleanup(&first); sc_stream_cleanup(&repeat);
sc_stream_cleanup(&fresh); sc_stream_cleanup(&opposite);
}
// Cleanup
sc_stream_cleanup(&send_a);