diff --git a/tests/test_dm_identity.c b/tests/test_dm_identity.c index e4041fab6..ee52194bb 100644 --- a/tests/test_dm_identity.c +++ b/tests/test_dm_identity.c @@ -9,6 +9,7 @@ #include "routing_layer/devgroup.h" #include "dm/dm_identity.h" #include "dm/dm_crypto.h" +#include "dm/dm_protocol.h" /* Полноценные ключи/удостоверения без сети: офлайн-узлы входят в snapshot. */ static void device(struct TOPO_NODE* node, struct SC_MYKEYS* keys, uint8_t ed_private[32]) { @@ -47,6 +48,38 @@ static int has_target(const struct dm_target* targets, size_t count, uint64_t no return 0; } +/* Подписанные удостоверения проверяются независимо от последующих объявлений узлов. */ +static void protocol(struct UTUN_INSTANCE* inst, const struct dm_party parties[2]) { + uint8_t body[DM_BODY_MAX] = {0}; size_t context = 0; + uint64_t conv = dm_identity_conv_id(DM_MODE_GROUPS, parties), seq = 1; + memcpy(body, &conv, 8); memcpy(body + 8, &seq, 8); memcpy(body + 24, &inst->node_id, 8); + assert(!dm_context_encode(inst, parties, body + 33, sizeof(body) - 33, &context)); + size_t pos = 33 + context; body[pos++] = 4; memcpy(body + pos, "text", 4); pos += 4; + uint16_t encrypted = 16; memcpy(body + pos, &encrypted, 2); pos += 2 + encrypted; + size_t size = pos + 64; struct dm_message_view view; + assert(!dm_message_parse(body, size, &view) && view.size == size && view.mode == DM_MODE_GROUPS); + assert(!view.media && view.content_type_size == 4 && !memcmp(view.content_type, "text", 4)); + assert(!dm_message_verify_targets(&view) && dm_message_target(&view, inst->node_id, NULL, NULL) == 0); + assert(dm_message_target(&view, 0, NULL, NULL) == -1); + size_t cuts[] = {0, 32, 33, 34, 33 + context - 1, 33 + context, pos - 1, size - 1}; + for (unsigned i = 0; i < sizeof(cuts) / sizeof(cuts[0]); i++) assert(dm_message_parse(body, cuts[i], &view) < 0); + assert(!dm_message_parse(body, size + 1, &view) && view.size == size); + uint8_t* target = body + (view.targets - body); + target[73] ^= 1; assert(dm_message_verify_targets(&view) < 0); target[73] ^= 1; + uint8_t saved[DM_TARGET_PROOF_SIZE]; memcpy(saved, target + DM_TARGET_PROOF_SIZE, sizeof(saved)); + memcpy(target + DM_TARGET_PROOF_SIZE, target, sizeof(saved)); assert(dm_message_verify_targets(&view) < 0); + memcpy(target + DM_TARGET_PROOF_SIZE, saved, sizeof(saved)); assert(!dm_message_verify_targets(&view)); + view.author = 0; assert(dm_message_verify_targets(&view) < 0); + assert(!dm_message_parse(body, size, &view)); view.conv ^= 1; assert(dm_message_verify_targets(&view) < 0); + struct dm_party reversed[2] = {parties[1], parties[0]}; size_t untouched = 999; + assert(dm_context_encode(inst, reversed, body, sizeof(body), &untouched) < 0 && untouched == 999); + assert(dm_context_encode(inst, parties, body, 10, &untouched) < 0 && untouched == 999); + /* Старое DEVICE-тело остаётся пригодным для текущей лички. */ + memset(body, 0, sizeof(body)); body[32] = 4; memcpy(body + 33, "file", 4); memcpy(body + 37, &encrypted, 2); + size = 39 + 16 + 56 + 64; + assert(!dm_message_parse(body, size, &view) && view.mode == DM_MODE_DEVICE && view.media == body + 55); +} + int main(void) { debug_config_init(); debug_set_level(DEBUG_LEVEL_DEBUG); struct UTUN_INSTANCE inst = {0}; @@ -77,6 +110,7 @@ int main(void) { assert(!dm_party_resolve(&inst, nodes[0].node_id, DM_MODE_GROUPS, parties)); assert(!dm_party_resolve(&inst, nodes[2].node_id, DM_MODE_GROUPS, parties + 1)); assert(parties[0].kind == DM_PARTY_GROUP && parties[1].kind == DM_PARTY_GROUP); + protocol(&inst, parties); reversed[0] = parties[1]; reversed[1] = parties[0]; uint64_t conv = dm_identity_conv_id(DM_MODE_GROUPS, parties); assert(conv && conv == dm_identity_conv_id(DM_MODE_GROUPS, reversed));