// creates a new mesh identity, returns secrets lob_t mesh_generate(mesh_t mesh) { lob_t secrets; if(!mesh || mesh->self) return LOG_ERROR("invalid mesh"); secrets = e3x_generate(); if(!secrets) return LOG_ERROR("failed to generate %s",e3x_err()); if(mesh_load(mesh, secrets, lob_linked(secrets))) return lob_free(secrets); return secrets; }
int main(int argc, char **argv) { lob_t opts = lob_new(); fail_unless(e3x_init(opts) == 0); fail_unless(!lob_get(opts,"err")); fail_unless(!e3x_err()); lob_free(opts); return 0; }
// processes incoming packet, it will take ownership of p link_t mesh_receive(mesh_t mesh, lob_t outer, pipe_t pipe) { lob_t inner; link_t link; char token[17]; hashname_t id; if(!mesh || !outer || !pipe) return LOG("bad args"); LOG("mesh receiving %s to %s via pipe %s",outer->head_len?"handshake":"channel",hashname_short(mesh->id),pipe->id); // process handshakes if(outer->head_len == 1) { inner = e3x_self_decrypt(mesh->self, outer); if(!inner) { LOG("%02x handshake failed %s",outer->head[0],e3x_err()); lob_free(outer); return NULL; } // couple the two together, inner->outer lob_link(inner,outer); // set the unique id string based on some of the first 16 (routing token) bytes in the body base32_encode(outer->body,10,token,17); lob_set(inner,"id",token); // process the handshake return mesh_receive_handshake(mesh, inner, pipe); } // handle channel packets if(outer->head_len == 0) { if(outer->body_len < 16) { LOG("packet too small %d",outer->body_len); lob_free(outer); return NULL; } route_t route; for(route = mesh->routes;route;route = route->next) if(memcmp(route->token,outer->body,8) == 0) break; link = route ? route->link : NULL; if(!link) { LOG("dropping, no link for token %s",util_hex(outer->body,16,NULL)); lob_free(outer); return NULL; } // forward packet if(!route->flag) { LOG("forwarding route token %s via %s len %d",util_hex(route->token,8,NULL),hashname_short(link->id),lob_len(outer)); return link_send(link, outer); } inner = e3x_exchange_receive(link->x, outer); lob_free(outer); if(!inner) return LOG("channel decryption fail for link %s %s",hashname_short(link->id),e3x_err()); LOG("channel packet %d bytes from %s",lob_len(inner),hashname_short(link->id)); return link_receive(link,inner,pipe); } // transform incoming bare link json format into handshake for discovery if((inner = lob_get_json(outer,"keys"))) { if((id = hashname_vkeys(inner))) { lob_set(outer,"hashname",hashname_char(id)); lob_set_int(outer,"at",0); lob_set(outer,"type","link"); LOG("bare incoming link json being discovered %s",lob_json(outer)); } lob_free(inner); } // run everything else through discovery, usually plain handshakes mesh_discover(mesh, outer, pipe); link = mesh_linked(mesh, lob_get(outer,"hashname"), 0); lob_free(outer); return link; }
int main(int argc, char **argv) { lob_t id; mesh_t mesh; lob_t opts = lob_new(); fail_unless(e3x_init(opts) == 0); fail_unless(!e3x_err()); // need cs1a support to continue testing e3x_cipher_t cs = e3x_cipher_set(0x1a,NULL); if(!cs) return 0; cs = e3x_cipher_set(0,"1a"); fail_unless(cs); fail_unless(cs->id == CS_1a); uint8_t buf[32]; fail_unless(e3x_rand(buf,32)); char hex[65]; util_hex(e3x_hash((uint8_t*)"foo",3,buf),32,hex); fail_unless(strcmp(hex,"2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae") == 0); id = util_fjson("/Users/chrigel/.id.json"); if(!id) return -1; lob_t secrets = lob_get_json(id,"secrets"); fail_unless(secrets); fail_unless(lob_get(secrets,"1a")); lob_t keys = lob_get_json(id,"keys"); fail_unless(keys); fail_unless(lob_get(keys,"1a")); LOG("generated key %s secret %s",lob_get(keys,"1a"),lob_get(secrets,"1a")); local_t localA = cs->local_new(keys,secrets); fail_unless(localA); remote_t remoteA = cs->remote_new(lob_get_base32(keys,"1a"), NULL); fail_unless(remoteA); // create another to start testing real packets lob_t secretsB = e3x_generate(); fail_unless(lob_linked(secretsB)); printf("XX %s\n",lob_json(lob_linked(secretsB))); local_t localB = cs->local_new(lob_linked(secretsB),secretsB); fail_unless(localB); remote_t remoteB = cs->remote_new(lob_get_base32(lob_linked(secretsB),"1a"), NULL); fail_unless(remoteB); // generate a message lob_t messageAB = lob_new(); lob_set_int(messageAB,"a",42); lob_t outerAB = cs->remote_encrypt(remoteB,localA,messageAB); fail_unless(outerAB); fail_unless(lob_len(outerAB) == 42); // decrypt and verify it lob_t innerAB = cs->local_decrypt(localB,outerAB); fail_unless(innerAB); fail_unless(lob_get_int(innerAB,"a") == 42); fail_unless(cs->remote_verify(remoteA,localB,outerAB) == 0); ephemeral_t ephemBA = cs->ephemeral_new(remoteA,outerAB); fail_unless(ephemBA); lob_t channelBA = lob_new(); lob_set(channelBA,"type","foo"); lob_t couterBA = cs->ephemeral_encrypt(ephemBA,channelBA); fail_unless(couterBA); fail_unless(lob_len(couterBA) == 42); lob_t outerBA = cs->remote_encrypt(remoteA,localB,messageAB); fail_unless(outerBA); ephemeral_t ephemAB = cs->ephemeral_new(remoteB,outerBA); fail_unless(ephemAB); lob_t cinnerAB = cs->ephemeral_decrypt(ephemAB,couterBA); fail_unless(cinnerAB); fail_unless(util_cmp(lob_get(cinnerAB,"type"),"foo") == 0); return 0; }