void NtfyPacket(std::shared_ptr<GlobalGrid::VSocket> socket,unsigned char* packetData, size_t packetLength) { if(sessions.find(socket) == sessions.end()) { //We should have an AES key in our packet here encrypted with our public key. //Packet header -- thumbprint (16 bytes) (unverified data element), session key (variable length, encrypted) if(packetLength<=16) { return; } void* packet = RSA_Decrypt(privkey,packetData+16,packetLength-16); if(packet == 0) { //Decryption failure. return; } unsigned char* buffer; size_t sz; GlobalGrid::Buffer_Get(packet,&buffer,&sz); if(sz>=32) { //We have a new Session. Session route(socket,buffer,packetData); sessions.insert(route); //Respond with ACK, which verifies our identity //Send challenge to verify remote identity. char hexprint[33]; ToHexString((unsigned char*)route.claimedThumbprint,16,hexprint); hexprint[32] = 0; void* remoteKey = DB_FindAuthority(hexprint); if(remoteKey) { SendChallenge(remoteKey,route,socket); }else { //We don't have a remote key. Request it. unsigned char izard[16]; memset(izard,0,16); izard[0] = 2; aes_encrypt(route.key,izard); socket->Send(izard,16); } GlobalGrid::GGObject_Free(packet); }else { GlobalGrid::GGObject_Free(packet); } }else { //Bind to existing Session. if(packetLength % 16 != 0) { //Invalid packet. return; } Session session = *sessions.find(socket); for(size_t i = 0;i<packetLength;i+=16) { aes_decrypt(session.key,packetData+i); } switch(*packetData) { case 0: //Challenge request { //Decrypt challenge uint16_t len; memcpy(&len,packetData+1,2); void* challenge = RSA_Decrypt(privkey,packetData+1+2,len); if(challenge == 0) { return; } unsigned char* challenge_bytes; size_t challenge_sz; GlobalGrid::Buffer_Get(challenge,&challenge_bytes,&challenge_sz); if(challenge_sz != 16) { GlobalGrid::GGObject_Free(challenge); return; } unsigned char response[32]; memset(response,0,32); response[0] = 1; memcpy(response+1,challenge_bytes,16); aes_encrypt(session.key,response); aes_encrypt(session.key,response+16); socket->Send(response,32); GlobalGrid::GGObject_Free(challenge); } break; case 1: { //Response to challenge (identity verification) if(memcmp(session.challenge,packetData+1,16) == 0) { session.verified = true; printf("Identity verified.\n"); } } break; case 2: { //Request for public encryptionKey. void* key = RSA_Export(privkey,false); unsigned char* key_bytes; size_t key_size; GlobalGrid::Buffer_Get(key,&key_bytes,&key_size); size_t aligned = key_size+1; aligned+=16-(aligned % 16); unsigned char* packet = new unsigned char[aligned]; memcpy(packet+1,key_bytes,key_size); packet[0] = 3; for(size_t i = 0;i<aligned;i+=16) { aes_encrypt(session.key,packet+i); } socket->Send(packet,aligned); delete[] packet; GlobalGrid::GGObject_Free(key); } break; case 3: { //Received public encryption key void* key = RSA_Key(packetData+1,packetLength-1); char thumbprint[33]; RSA_thumbprint(key,thumbprint); thumbprint[32] = 0; void* obj = DB_FindAuthority(thumbprint); if(obj == 0) { void* keybin = RSA_Export(key,false); unsigned char* cert; size_t cert_len; GlobalGrid::Buffer_Get(keybin,&cert,&cert_len); DB_Insert_Certificate(thumbprint,cert,cert_len,false); GlobalGrid::GGObject_Free(keybin); if(session.verified == false) { //TODO: Send verification request SendChallenge(key,session,socket); } }else { RSA_Free(obj); } } break; case 4: { //Route packet packetData++; unsigned char ttl = *packetData; packetData++; //Intended destination GlobalGrid::Guid dest; memcpy(dest.value,packetData,16); packetData+=16; GlobalGrid::Guid localThumbprint; RSA_thumbprint(privkey,(unsigned char*)localThumbprint.value); uint32_t packetSize; memcpy(&packetSize,packetData,4); packetData+=16; if(dest == localGuid) { printf("TODO: Packet destined for ourselves\n"); return; } SendPacket(packetData,packetSize,ttl,dest,session.claimedThumbprint); } break; } } }
int main(int argc, char** argv) { void* privkey = 0; bool(*fptr)(void*,unsigned char*,size_t); void* thisptr = System::ABI::C([&](unsigned char* data, size_t len){ privkey = RSA_Key(data,len); if(privkey == 0) { printf("Unable to decode private key with size %i.\n",(int)len); abort(); } return false; },fptr); DB_EnumPrivateKeys(thisptr,fptr); if(privkey == 0) { printf("Generating 4096-bit RSA key. This may take a while....\n"); privkey = RSA_GenKey(4096); char thumbprint[33]; thumbprint[32] = 0; RSA_thumbprint(privkey,thumbprint); unsigned char* cert; size_t certlen; void* buffy = RSA_Export(privkey,true); GlobalGrid::Buffer_Get(buffy,(void**)&cert,&certlen); printf("Generated certificate taking %i bytes\n",(int)certlen); DB_Insert_Certificate(thumbprint,cert,certlen,true); GlobalGrid::GGObject_Free(buffy); } if(argc>1) { if(strcmp(argv[1],"export") == 0) { //Export public key void* buffy = RSA_Export(privkey,false); unsigned char* mander; size_t sz; GlobalGrid::Buffer_Get(buffy,&mander,&sz); write(STDOUT_FILENO,mander,sz); return 0; }else { if(strcmp(argv[1],"import") == 0) { unsigned char mander[4096]; int len = 0; int cl; while((cl = read(STDIN_FILENO,mander+len,4096-len))>0) { len+=cl; printf("Read\n"); } void* key = RSA_Key(mander,len); if(key == 0) { printf("Invalid key. Cannot import.\n"); return -1; } char thumbprint[33]; thumbprint[32] = 0; RSA_thumbprint(key,thumbprint); DB_Insert_Certificate(thumbprint,mander,len,false); printf("Successfully imported key with thumbprint %s\n",thumbprint); return 0; } } } char thumbprint[33]; thumbprint[32] = 0; RSA_thumbprint(privkey,thumbprint); printf("Your private key thumbprint is %s\n",thumbprint); void* router = GlobalGrid::GlobalGrid_InitRouter(privkey); printf("Registering IP protocol driver with system....\n"); System::Net::IPEndpoint routerBinding; routerBinding.ip = "::"; routerBinding.port = 0; if(argc>1) { routerBinding.ip = argv[4]; routerBinding.port = atoi(argv[5]); } std::shared_ptr<IPProto::IIPDriver> deriver = IPProto::CreateDriver(router,routerBinding); GlobalGrid::GlobalGrid_RegisterProtocolDriver(router,deriver); void* locksock = deriver->SerializeLocalSocket(); unsigned char* socket_data; size_t sock_len; GlobalGrid::Buffer_Get(locksock,&socket_data,&sock_len); uint16_t portno; memcpy(&portno,socket_data+16,2); printf("Protocol driver active and registered (port %i)\n",(int)portno); //TODO: Server is listening on appropriate port, as verified by netstat -l. //Client must not be sending handshake appopriately (or server receive loop isn't working). //Connect to specified endpoint if(argc>1) { System::Net::IPEndpoint ep; ep.ip = argv[1]; ep.port = atoi(argv[2]); const char* thumbprint = argv[3]; //Connect to remote endpoint. void* key = DB_FindAuthority(thumbprint); if(key == 0) { printf("ERR: Unable to find authority figure.\n"); abort(); } GlobalGrid::GlobalGrid_InitiateHandshake(router,deriver->MakeSocket(ep),key); RSA_Free(key); } unsigned char izard[16]; memset(izard,0,16); GlobalGrid::GlobalGrid_SendPacket(router,izard,izard,1); char mander[256]; auto messenger = System::MakeQueue([&](std::shared_ptr<System::Message> msg){ unsigned char pingmsg = 0; GlobalGrid::Guid converted; FromHexString(mander,(unsigned char*)converted.value,16*2); GlobalGrid::GlobalGrid_SendPacket(router,converted,&pingmsg,1); printf("PING %s\n",mander); }); std::thread m([&](){ while(true) { int br = read(0,mander,256); if(br <=0) { break; } mander[br] = 0; messenger->Post(0); } }); m.detach(); System::Enter(); return 0; }