A Discrete-Event Network Simulator
API
qkd-app-004.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2020 DOTFEESA www.tk.etf.unsa.ba
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Emir Dervisevic <emir.dervisevic@etf.unsa.ba>
19  * Miralem Mehic <miralem.mehic@ieee.org>
20  */
21 
22 #include "ns3/address.h"
23 #include "ns3/address-utils.h"
24 #include "ns3/log.h"
25 #include "ns3/inet-socket-address.h"
26 #include "ns3/inet6-socket-address.h"
27 #include "ns3/node.h"
28 #include "ns3/socket.h"
29 #include "ns3/udp-socket-factory.h"
30 #include "ns3/tcp-socket-factory.h"
31 #include "ns3/simulator.h"
32 #include "ns3/socket-factory.h"
33 #include "ns3/packet.h"
34 #include "ns3/trace-source-accessor.h"
35 #include "qkd-app-004.h"
36 
37 namespace ns3 {
38 
39 NS_LOG_COMPONENT_DEFINE ("QKDApp004");
40 
41 NS_OBJECT_ENSURE_REGISTERED (QKDApp004);
42 
43 TypeId
45 {
46  static TypeId tid = TypeId ("ns3::QKDApp004")
48  .SetGroupName("Applications")
49  .AddConstructor<QKDApp004> ()
50  .AddAttribute ("Protocol", "The type of protocol to use.",
54  .AddAttribute ("LengthOfAuthenticationTag",
55  "The default length of the authentication tag",
56  UintegerValue (256), //32 bytes
58  MakeUintegerChecker<uint32_t> ())
59  .AddAttribute ("EncryptionType",
60  "The type of encryption to be used (0-unencrypted, 1-OTP, 2-AES)",
61  UintegerValue (2),
63  MakeUintegerChecker<uint32_t> ())
64  .AddAttribute ("AuthenticationType",
65  "The type of authentication to be used (0-unauthenticated, 1-VMAC, 2-MD5, 3-SHA1)",
66  UintegerValue (3),
68  MakeUintegerChecker<uint32_t> ())
69  .AddAttribute ("AESLifetime",
70  "Lifetime of AES key expressed in number of packets",
71  UintegerValue (1),
73  MakeUintegerChecker<uint32_t> ())
74  .AddAttribute ("UseCrypto",
75  "Should crypto functions be performed (0-No, 1-Yes)",
76  UintegerValue (0),
78  MakeUintegerChecker<uint32_t> ())
79  .AddAttribute ("LengthOfKeyBufferForEncryption",
80  "How many keys to store in local buffer of QKDApp004 for encryption?",
81  UintegerValue (10),
83  MakeUintegerChecker<uint32_t> ())
84  .AddAttribute ("LengthOfKeyBufferForAuthentication",
85  "How many keys to store in local buffer of QKDApp004 for authentication?",
86  UintegerValue (10),
88  MakeUintegerChecker<uint32_t> ())
89  .AddAttribute ("SocketToKMSHoldTime","How long (seconds) should QKDApp004 wait to close socket to KMS after receiving REST response?",
90  TimeValue (Seconds (0.5)),
92  MakeTimeChecker ())
93  .AddAttribute ("MaliciousApplication",
94  "Is this application malicious?",
95  UintegerValue (0), //default value: NO/FALSE
97  MakeUintegerChecker<uint32_t> ())
98  .AddAttribute ("DoSAttackIntensity",
99  "The time elapsed between successive malicious requests; For testing DoS/DDoS attacks;",
100  TimeValue (Seconds (0.1)), //default value: 100ms
102  MakeTimeChecker())
103  .AddAttribute ("MinDataRate", "The minimal data key rate (encryption+authentication) of the app (QoS settings).",
104  DataRateValue (DataRate ("0kb/s")),
105  MakeDataRateAccessor (&QKDApp004::m_minDataRate),
106  MakeDataRateChecker ())
107 
108  .AddAttribute ("Priority",
109  "QoS Priority (0 - default, 1 - premium)",
110  UintegerValue (0),
112  MakeUintegerChecker<uint32_t> ())
113  .AddAttribute ("TTL",
114  "QoS TTL - defines duration (seconds) of ETSI004 association",
115  UintegerValue (5),
117  MakeUintegerChecker<uint32_t> ())
118 
119 
120  .AddTraceSource ("Tx", "A new packet is created and is sent",
122  "ns3::Packet::TracedCallback")
123  .AddTraceSource ("TxSig", "A new signaling packet is created and is sent",
125  "ns3::Packet::TracedCallback")
126  .AddTraceSource ("TxKMS", "A new packet is created and is sent to local KMS",
128  "ns3::Packet::TracedCallback")
129  .AddTraceSource ("Rx", "A new packet is received",
131  "ns3::Packet::TracedCallback")
132  .AddTraceSource ("RxSig", "A new signaling packet is received",
134  "ns3::Packet::TracedCallback")
135  .AddTraceSource ("RxKMS", "A new packet is received from local KMS",
137  "ns3::Packet::TracedCallback")
138  .AddTraceSource ("StateTransition",
139  "Trace fired upon every QKDApp state transition.",
141  "ns3::Application::StateTransitionCallback")
142  .AddTraceSource ("PacketEncrypted",
143  "The change trance for currenly ecrypted packet",
145  "ns3::QKDCrypto::PacketEncrypted")
146  .AddTraceSource ("PacketDecrypted",
147  "The change trance for currenly decrypted packet",
149  "ns3::QKDCrypto::PacketDecrypted")
150  .AddTraceSource ("PacketAuthenticated",
151  "The change trance for currenly authenticated packet",
153  "ns3::QKDCrypto::PacketAuthenticated")
154  .AddTraceSource ("PacketDeAuthenticated",
155  "The change trance for currenly deauthenticated packet",
157  "ns3::QKDCrypto::PacketDeAuthenticated")
158  .AddTraceSource ("Mx", "Missed send packet call",
160  "ns3::Packet::TracedCallback")
161  .AddTraceSource ("KeyObtained", "Trace amount of obtained key material",
163  "ns3::QKDApp004::KeyObtained")
164  ;
165 
166  return tid;
167 }
168 
169 
170 uint32_t QKDApp004::m_applicationCounts = 0;
171 
181  : m_sendSignalingSocketApp (0),
182  m_sinkSignalingSocketApp (0),
183  m_sendDataSocketApp (0),
184  m_sinkDataSocketApp (0),
185  m_sendSocketToKMS (0),
186  m_sinkSocketFromKMS (0),
187  m_packetSize (0),
188  m_dataRate (0),
189  m_sendEvent (),
190  m_packetsSent (0),
191  m_dataSent (0),
192  m_master (0),
193  m_encryptor (0),
194  m_appState (NOT_STARTED)
195 {
197  m_id = UUID::Random();
198  m_random = CreateObject<UniformRandomVariable> ();
199 }
200 
202 {
203  //Data sockets
206  //Signaling sockets
209  //KMS sockets
210  m_sendSocketToKMS = 0;
212 }
213 
214 void
216  std::string socketType,
217  Address src,
218  Address dst,
219  Address kms,
220  UUID dstSaeId,
221  std::string type
222 ){
223  Setup(
224  socketType,
225  src,
226  dst,
227  kms,
228  dstSaeId,
229  0,
230  0,
231  DataRate ("0bps"),
232  type
233  );
234 }
235 
236 void
238  std::string socketType,
239  Address src,
240  Address dst,
241  Address kms,
242  UUID dstSaeId,
243  uint32_t packetSize,
244  uint32_t nPacketsSize,
245  DataRate dataRate,
246  std::string type
247 ){
248 
249  NS_LOG_FUNCTION(this << type << src << dst << packetSize << nPacketsSize << dataRate.GetBitRate());
250 
251  if(type == "alice"){
252  m_master = 1;
254  NS_ASSERT(dataRate.GetBitRate() > 0);
255  }else{
256  m_master = 0;
257  }
258 
259  m_local = src;
260  m_peer = dst;
261  m_kms = kms;
262  m_dstSaeId = dstSaeId;
263 
266  7080
267  );
270  7080
271  );
272 
274  m_dataRate = dataRate;
275  m_socketType = socketType;
276 
277 
280 
281 }
282 
290 void
292 {
293  NS_LOG_FUNCTION (this << m_appState);
294 
296  {
297  //NS_LOG_FUNCTION (this << "QKDApp is running!");
298  m_delay = m_packetSize * 8 / static_cast<double> (m_dataRate.GetBitRate ());
299  //NS_LOG_FUNCTION( this << "delay" << Seconds (delay) );
300  Time tNext (Seconds (m_delay));
302  } else {
303  NS_LOG_FUNCTION (this << "QKDApp is" << GetAppStateString(m_appState));
304  }
305 }
306 
307 void
309 {
310  NS_LOG_FUNCTION(this << eventId);
311 
312  std::map<uint32_t, EventId >::iterator eventEntry = m_scheduledEvents.find ( eventId );
313  if(eventEntry != m_scheduledEvents.end ()){
314  Simulator::Cancel (eventEntry->second);
315  }else{
316  NS_FATAL_ERROR ("Invalid entryId " << eventId );
317  }
318 
319 }
320 
321 
329 void
331 {
332  NS_LOG_FUNCTION(this);
333 
334  if(!m_sinkSocketFromKMS){
335  Address localAddress = InetSocketAddress(
336  //InetSocketAddress::ConvertFrom(m_kms).GetIpv4 (),
338  82
339  //InetSocketAddress::ConvertFrom(m_kms).GetPort ()+1
340  );
342 
343  if (m_sinkSocketFromKMS->Bind (localAddress) == -1)
344  NS_FATAL_ERROR ("Failed to bind socket");
345 
352  );
356  );
357  NS_LOG_FUNCTION (this << "Create new APP socket " << m_sinkSocketFromKMS
358  << " to listen packets from KMS on " << InetSocketAddress::ConvertFrom(localAddress).GetIpv4 ()
359  << " and port " << InetSocketAddress::ConvertFrom(localAddress).GetPort ()
360  );
361  }else{
362  NS_LOG_FUNCTION (this << "Socket to listen from local KMS exists!" << m_sinkSocketFromKMS);
363  }
364 
365 }
366 
367 void
369 {
370  NS_LOG_FUNCTION(this);
371 
372  if(!m_sendSocketToKMS)
374 
375  Address temp;
376  if(m_sendSocketToKMS->GetPeerName (temp) != 0) {
377  Address lkmsAddress = InetSocketAddress(
380  );
389  );
390  m_sendSocketToKMS->Connect ( lkmsAddress );
392  NS_LOG_FUNCTION (this << "Create new APP socket " << m_sendSocketToKMS << " to reach local KMS at "
393  << InetSocketAddress::ConvertFrom(m_kms).GetIpv4 () << ":" << InetSocketAddress::ConvertFrom(m_kms).GetPort ()
394  << "!");
395  }else{
396  NS_LOG_FUNCTION (this << "Active socket to reach local KMS exists!" << m_sendSocketToKMS);
397  }
398 
399 }
400 
401 void
403 {
404  NS_LOG_FUNCTION(this);
405 
407 
409 
410  if(m_socketType == "tcp"){
412  }else{
414  }
415 
416  NS_LOG_FUNCTION (this << "m_sendSignalingSocketApp:" << m_sendSignalingSocketApp
419  );
420 
425  }
426 
427  if(!m_sendDataSocketApp){
428 
429  if(m_socketType == "tcp"){
431  }else{
433  }
434 
435  NS_LOG_FUNCTION (this << "m_sendDataSocketApp:" << m_sendDataSocketApp
438  );
439 
444  }
445 
446  }else{
447  NS_LOG_FUNCTION (this << "Socket to reach peer app exists!" << m_sendSignalingSocketApp);
448  }
449 }
450 
451 void
453 {
454  NS_LOG_FUNCTION(this);
455 
457  {
458 
459  if(m_socketType == "tcp")
461  else
463 
464  NS_LOG_FUNCTION (this << "m_sinkSignalingSocketApp:" << m_sinkSignalingSocketApp
467  );
468 
470  NS_FATAL_ERROR ("Failed to bind socket");
471 
476  MakeNullCallback<bool, Ptr<Socket>, const Address &> (),
478  );
482  );
483 
484  }else{
485  NS_LOG_FUNCTION (this << "Socket to listen signaling from peer app exists!" << m_sinkSignalingSocketApp);
486  }
487 
488 
490  {
491 
492  if(m_socketType == "tcp")
494  else
496 
497  NS_LOG_FUNCTION (this << "m_sinkDataSocketApp:" << m_sinkDataSocketApp
500  );
501 
502  if (m_sinkDataSocketApp->Bind (m_local) == -1)
503  NS_FATAL_ERROR ("Failed to bind socket");
504 
509  MakeNullCallback<bool, Ptr<Socket>, const Address &> (),
511  );
515  );
516  }else{
517  NS_LOG_FUNCTION (this << "Socket to listen data from peer app exists!" << m_sinkSignalingSocketApp);
518  }
519 
520 }
521 
522 bool
524 {
525  NS_LOG_FUNCTION (this << socket << from
526  << InetSocketAddress::ConvertFrom(from).GetIpv4 ()
527  << InetSocketAddress::ConvertFrom(from).GetPort ()
528  );
529  NS_LOG_FUNCTION (this << "QKDApp Connection from KMS requested on socket " << socket);
530  return true; // Unconditionally accept the connection request.
531 
532 }
533 
534 void
536 {
537  Address peer;
538  NS_LOG_FUNCTION (this << socket << from
539  << InetSocketAddress::ConvertFrom(from).GetIpv4 ()
540  << InetSocketAddress::ConvertFrom(from).GetPort ()
541  );
542  NS_LOG_FUNCTION (this << "QKDApp Connection from KMS accepted on socket " << socket);
545 }
546 
547 void
549 {
550  NS_LOG_FUNCTION (this << s << from
551  << InetSocketAddress::ConvertFrom(from).GetIpv4 ()
552  << InetSocketAddress::ConvertFrom(from).GetPort ()
553  );
554 
555  NS_LOG_FUNCTION (this << "QKDApp Connection from APP accepted on socket " << s);
557 }
558 
559 void
561 {
562  NS_LOG_FUNCTION (this << s << from
563  << InetSocketAddress::ConvertFrom(from).GetIpv4 ()
564  << InetSocketAddress::ConvertFrom(from).GetPort ()
565  );
566 
567  NS_LOG_FUNCTION (this << "QKDApp Signaling Connection from APP accepted on socket " << s);
569 }
570 
571 void
573 {
574  NS_LOG_FUNCTION (this << socket << "QKDApp Connection to KMS succeeded via socket " << socket);
575 }
576 
577 void
579 {
580  NS_LOG_FUNCTION (this << socket << "QKDApp, Connection to KMS Failed via socket " << socket);
581 }
582 
583 void
585 {
586  NS_LOG_FUNCTION (this << socket << "QKDApp Connection to APP succeeded via socket " << socket);
587 }
588 
589 void
591 {
592  NS_LOG_FUNCTION (this << socket << "QKDApp, Connection to APP Failed via socket " << socket);
593 }
594 
595 void
597 {
598  NS_LOG_FUNCTION (this << socket << "QKDApp Signaling Connection to APP succeeded via socket " << socket);
599 }
600 
601 void
603 {
604  NS_LOG_FUNCTION (this << socket << "QKDApp, Connection to APP Failed via socket " << socket);
605 }
606 
607 void
609 {
610  NS_LOG_FUNCTION (this << socket);
611 }
612 
613 void
615 {
616  NS_LOG_FUNCTION (this << socket);
617 }
618 
619 void
621 {
622  NS_LOG_FUNCTION (this << socket);
623  if(socket == m_sendSocketToKMS) {
625  MakeNullCallback<void, Ptr<Socket> > (),
626  MakeNullCallback<void, Ptr<Socket> > ()
627  );
629  MakeNullCallback<void, Ptr<Socket> > (),
630  MakeNullCallback<void, Ptr<Socket> > ()
631  );
632  m_sendSocketToKMS = 0;
633  }
634 }
635 
636 void
638 {
639  NS_LOG_FUNCTION (this << socket);
640  if(socket == m_sendSocketToKMS) {
642  MakeNullCallback<void, Ptr<Socket> > (),
643  MakeNullCallback<void, Ptr<Socket> > ()
644  );
646  MakeNullCallback<void, Ptr<Socket> > (),
647  MakeNullCallback<void, Ptr<Socket> > ()
648  );
649  m_sendSocketToKMS = 0;
650  }
651 }
652 
653 void
655 {
656  NS_LOG_FUNCTION (this << socket);
657 }
658 void
660 {
661  NS_LOG_FUNCTION (this << socket);
662 }
663 
664 void
666 {
667  NS_LOG_FUNCTION (this << socket);
668 }
669 
670 void
672 {
673  NS_LOG_FUNCTION (this << socket);
674 }
675 
676 void
678 {
679  NS_LOG_FUNCTION (this << socket);
680 
681  Ptr<Packet> packet;
682  Address from;
683  while ((packet = socket->RecvFrom (from)))
684  {
685  if (packet->GetSize () == 0)
686  { //EOF
687  break;
688  }
689 
690  NS_LOG_FUNCTION (this
691  << packet << "PACKETID: " << packet->GetUid()
692  << " of size: " << packet->GetSize()
693  );
694 
696  {
697  NS_LOG_FUNCTION("At time " << Simulator::Now ().GetSeconds ()
698  << "s packet from KMS received "
699  << packet->GetSize () << " bytes from "
701  << " port " << InetSocketAddress::ConvertFrom (from).GetPort ()
702  );
703  }
704  PacketReceivedFromKMS (packet, from, socket);
705  }
706 
707  if(m_queue_kms.size() == 0){
708  NS_LOG_FUNCTION(this << "Close socket to KMS!");
709  if (m_sendSocketToKMS) {
710  Time tNext (m_holdTime);
712  }
713  }else{
716  }
717 }
718 
719 void
721 
722  NS_LOG_FUNCTION(this);
723  if (m_sendSocketToKMS && m_queue_kms.size() == 0) {
725  m_sendSocketToKMS = 0;
726  }
727 }
728 
729 void
731 
732  NS_LOG_FUNCTION (this << m_queue_kms.size() );
733 
734  //check whether the socket to KMS is active and connected
735  Address temp;
736  if(!m_sendSocketToKMS || m_sendSocketToKMS->GetPeerName (temp) != 0) {
738  }else{
739  if(m_queue_kms.size() > 0){
740  uint32_t c = 0;
741  auto it = m_queue_kms.begin();
742  while (it != m_queue_kms.end())
743  {
744  NS_LOG_FUNCTION(this << c << m_queue_kms.size() << it->keyType );
745  Http004KMSQuery(it->uri, it->ksid, it->keyType);
746 
747  if(it->packet) {
748  m_txKmsTrace (it->packet);
749  m_sendSocketToKMS->Send(it->packet);
750  }
751  m_queue_kms.erase(it);
752  c++;
753  }
754  }
755  }
756 }
757 
758 void
760 {
761  NS_LOG_FUNCTION ( this << p->GetUid() << p->GetSize() << from );
762  std::string receivedStatus = p->ToString();
763  NS_LOG_FUNCTION ( this << "\n\n\n" << p->GetUid() << p->GetSize() << receivedStatus << from );
764 
765  if(m_malicious)
766  return; //Malicious application does not process responses, it only overwhelms KMS by requests
767 
768  Ptr<Packet> buffer;
769  if (receivedStatus.find("Fragment") != std::string::npos) {
770  auto itBuffer = m_buffer_kms.find (from);
771  if (itBuffer == m_buffer_kms.end ()){
772  itBuffer = m_buffer_kms.insert (
773  std::make_pair (from, Create<Packet> (0))
774  ).first;
775  }
776  buffer = itBuffer->second;
777  buffer->AddAtEnd (p);
778  }else{
779  NS_LOG_FUNCTION(this << "Full packet received!");
780  buffer = p;
781  }
782 
784  HTTPMessage request;
785 
786  //copy buffer payload to string
787  uint8_t *b1 = new uint8_t[buffer->GetSize ()];
788  buffer->CopyData(b1, buffer->GetSize ());
789  std::string requestString = std::string((char*)b1);
790  delete[] b1;
791 
792  NS_LOG_FUNCTION(this << "CONTENT OF THE BUFFER: \n" << requestString);
793 
794  NS_LOG_FUNCTION(this << "Packet payload:" << requestString);
795 
796  //parse HTTP message
797  parser.Parse(&request, requestString);
798  if(request.IsFragmented() || request.GetStatusMessage() == "Undefined")
799  {
800  NS_LOG_FUNCTION(this << "HTTP Content Parsed after merge with buffer: " << request.ToString() << "\n ***IsFragmented:" << request.IsFragmented() << "\n\n\n\n");
801  }else{
802  NS_LOG_FUNCTION(this << "Full packet received:" << request.ToString() );
803  }
804  NS_LOG_FUNCTION(this << "HTTPMessage Size:" << request.GetSize());
805 
806  while (buffer->GetSize () >= request.GetSize())
807  {
808  NS_LOG_DEBUG ("Parsing packet pid(" << p->GetUid() << ") of size " << request.GetSize ()
809  << " (Header size:" << request.GetHeadersSize()
810  << " content length:" << request.GetContentLength()
811  << ") from buffer of size " << buffer->GetSize ()
812  );
813  Ptr<Packet> completePacket = buffer->CreateFragment (0, static_cast<uint32_t> (request.GetSize () ));
814 
815  uint8_t *b2 = new uint8_t[completePacket->GetSize ()];
816  completePacket->CopyData(b2, completePacket->GetSize ());
817  std::string completePacketString = std::string((char*)b2);
818 
819  HTTPMessage completePacketHttp;
820  parser.Parse(&completePacketHttp, completePacketString);
821  delete[] b2;
822 
823  NS_LOG_FUNCTION(this << "completePacketHttp" << completePacketHttp.IsFragmented());
824 
825  if(completePacketHttp.IsFragmented() == false){
826  NS_LOG_FUNCTION( this << "821: " << buffer->GetSize() << completePacketHttp.GetSize() << request.GetSize() << completePacketHttp.IsFragmented() );
827  NS_LOG_FUNCTION(this << "Croped HTTP message: " << completePacketHttp.ToString());
828 
829  buffer->RemoveAtStart (static_cast<uint32_t> (completePacketHttp.GetSize () ));
830  m_rxKmsTrace (completePacket);
831  ProcessResponseFromKMS(completePacketHttp, completePacket, socket);
832  }
833  NS_LOG_FUNCTION(this << "Croped HTTP message: " << completePacketHttp.ToString());
834  NS_LOG_FUNCTION(this << "Remains in the buffer " << buffer->GetSize () );
835  break;
836  }
837 }
838 
839 void
841 {
842  NS_LOG_FUNCTION (this << socket);
843 
844  Ptr<Packet> packet;
845  Address from;
846  while ((packet = socket->RecvFrom (from)))
847  {
848  if (packet->GetSize () == 0)
849  { //EOF
850  break;
851  }
852 
853  NS_LOG_FUNCTION (this << packet
854  << "PACKETID: " << packet->GetUid()
855  << " of size: " << packet->GetSize()
856  );
857 
859  {
860  NS_LOG_FUNCTION( this << "At time " << Simulator::Now ().GetSeconds ()
861  << "s packet from APP pair received "
862  << packet->GetSize () << " bytes from "
864  << " port " << InetSocketAddress::ConvertFrom (from).GetPort () << "\n");
865  }
866 
867  DataPacketReceivedFromApp (packet, from, socket);
868  }
869 }
870 
871 void
873 {
874  NS_LOG_FUNCTION ( this << m_master << p->GetUid() << p->GetSize() << from );
875 
876  if (m_master == 0) { //Process encrypted data on Replica QKDApp
877 
878  if (m_appState == READY) { //Replica QKDApp MUST be in ready state to receive data
879 
880  QKDAppHeader header;
881  Ptr<Packet> buffer;
882 
883  auto itBuffer = m_buffer_qkdapp.find (from);
884  if (itBuffer == m_buffer_qkdapp.end ())
885  {
886  itBuffer = m_buffer_qkdapp.insert (std::make_pair (from, Create<Packet> (0))).first;
887  }
888 
889  buffer = itBuffer->second;
890  buffer->AddAtEnd (p);
891  buffer->PeekHeader (header);
892 
893  NS_ABORT_IF (header.GetLength () == 0);
894 
895  while (buffer->GetSize () >= header.GetLength ())
896  {
897  NS_LOG_DEBUG ("Removing packet of size " << header.GetLength () << " from buffer of size " << buffer->GetSize ());
898  Ptr<Packet> completePacket = buffer->CreateFragment (0, static_cast<uint32_t> (header.GetLength ()));
899  buffer->RemoveAtStart (static_cast<uint32_t> (header.GetLength ()));
900 
901  m_txTrace (completePacket, m_associations.first.ksid);
902  m_txTrace (completePacket, m_associations.second.ksid);
903 
904  completePacket->RemoveHeader (header);
905  NS_LOG_FUNCTION(this << "RECEIVED QKDAPP HEADER: " << header);
906 
907  ProcessDataPacketFromApp(header, completePacket, socket);
908 
909  if (buffer->GetSize () > header.GetSerializedSize ())
910  {
911  buffer->PeekHeader (header);
912  }
913  else
914  {
915  break;
916  }
917  }
918 
919  } else {
920  NS_LOG_FUNCTION( this << "Primary/Replica:" << m_master << "Invalid state " << GetAppStateString() );
921  }
922  }
923 
924 }
925 
926 void
928 {
929  NS_LOG_FUNCTION (this << socket);
930 
931  Ptr<Packet> packet;
932  Address from;
933  while ((packet = socket->RecvFrom (from)))
934  {
935  if (packet->GetSize () == 0)
936  { //EOF
937  break;
938  }
939 
940  NS_LOG_FUNCTION (this << packet
941  << "PACKETID: " << packet->GetUid()
942  << " of size: " << packet->GetSize()
943  );
944 
946  {
947  NS_LOG_FUNCTION( this << "At time " << Simulator::Now ().GetSeconds ()
948  << "s signaling packet from APP pair received "
949  << packet->GetSize () << " bytes from "
951  << " port " << InetSocketAddress::ConvertFrom (from).GetPort () << "\n");
952  }
953 
954  SignalingPacketReceivedFromApp (packet, from, socket);
955  }
956 }
957 
958 void
960 {
961  NS_LOG_FUNCTION ( this << p->GetUid() << p->GetSize() << from );
962  std::string receivedStatus = p->ToString();
963  NS_LOG_FUNCTION ( this << "\n\n\n" << p->GetUid() << p->GetSize() << receivedStatus << from );
964 
965  Ptr<Packet> buffer;
966  if (receivedStatus.find("Fragment") != std::string::npos) {
967  auto itBuffer = m_buffer_sig.find (from);
968  if (itBuffer == m_buffer_sig.end ()){
969  itBuffer = m_buffer_sig.insert (
970  std::make_pair (from, Create<Packet> (0))
971  ).first;
972  }
973  buffer = itBuffer->second;
974  buffer->AddAtEnd (p);
975  }else{
976  NS_LOG_FUNCTION(this << "Full packet received!");
977  buffer = p;
978  }
979 
981  HTTPMessage request;
982 
983  //copy buffer payload to string
984  uint8_t *b1 = new uint8_t[buffer->GetSize ()];
985  buffer->CopyData(b1, buffer->GetSize ());
986  std::string requestString = std::string((char*)b1);
987  delete[] b1;
988 
989  //parse HTTP message
990  parser.Parse(&request, requestString);
991  if(request.IsFragmented() || request.GetStatusMessage() == "Undefined")
992  {
993  NS_LOG_FUNCTION(this << "HTTP Content Parsed after merge with buffer: " << request.ToString() << "\n ***IsFragmented:" << request.IsFragmented() << "\n\n\n\n");
994  }else{
995  NS_LOG_FUNCTION(this << "Full packet received:" << request.ToString());
996  }
997 
998  while (buffer->GetSize () >= request.GetSize())
999  {
1000  NS_LOG_DEBUG ("Parsing packet pid(" << p->GetUid() << ") of size " << request.GetSize () << " from buffer of size " << buffer->GetSize ());
1001  Ptr<Packet> completePacket = buffer->CreateFragment (0, static_cast<uint32_t> (request.GetSize () ));
1002 
1003  uint8_t *b2 = new uint8_t[completePacket->GetSize ()];
1004  completePacket->CopyData(b2, completePacket->GetSize ());
1005  std::string s2 = std::string((char*)b2);
1006 
1007  HTTPMessage request2;
1008  parser.Parse(&request2, s2);
1009  delete[] b2;
1010 
1011  if(request2.IsFragmented() == false){
1012  buffer->RemoveAtStart (static_cast<uint32_t> (request2.GetSize () ));
1013  m_rxSigTrace (completePacket);
1014  ProcessSignalingPacketFromApp(request2, socket);
1015  }
1016  NS_LOG_FUNCTION(this << "Croped HTTP message: " << request2.ToString());
1017  NS_LOG_FUNCTION(this << "Remains in the buffer " << buffer->GetSize () );
1018  break;
1019  }
1020 }
1021 
1022 void
1024 {
1025  NS_LOG_FUNCTION (this << "QKDApp Data to KMS Sent via socket " << socket);
1026 }
1027 
1028 
1037 void
1039 {
1040  NS_LOG_FUNCTION( this );
1041 
1042  m_primaryQueueEstablished = false;
1043  m_replicaQueueEstablished = false;
1044 
1045  //Association for encryption
1046  m_associations.first.ksid.clear();
1047  m_associations.first.verified = false;
1048  m_associations.first.queueSize = m_keyBufferLengthEncryption;
1049  m_associations.first.buffer.clear();
1050 
1051  //Association for authentication
1052  m_associations.second.ksid.clear();
1053  m_associations.second.verified = false;
1055  m_associations.second.buffer.clear();
1056 
1057 }
1058 
1059 void
1061 {
1062  NS_LOG_FUNCTION( this << "Checking associations ..." );
1063  NS_ASSERT(m_master); //Only Primary QKDApp checks associations states
1064  /*
1065  Function called after sendksidresponse is recieved.
1066  Main purpose is to check if associations are established!
1067  If they are, then switch application state to:
1068  ASSOCIATIONS_ESTABLISHED and moves on next state in AppTransitionTree
1069  */
1070  bool encAssociation = true;
1071  bool authAssociation = true;
1072  if(GetEncryptionKeySize() != 0 && !m_associations.first.verified)
1073  encAssociation = false;
1074  if(GetAuthenticationKeySize() != 0 && !m_associations.second.verified)
1075  authAssociation = false;
1076 
1077  if(encAssociation && authAssociation && m_appState == ESTABLISHING_ASSOCIATIONS){
1078  NS_LOG_FUNCTION( this << "All necessary associations are established" );
1081  }else
1082  NS_LOG_FUNCTION( this << "Necessary associations are NOT yet established" );
1083 
1084 }
1085 
1086 void
1088 {
1089  NS_LOG_FUNCTION( this << "Checking key queues ... " << m_master );
1090  bool encQueueReady = false;
1091  bool authQueueReady = false;
1092  if(m_associations.first.verified && m_associations.first.buffer.size() < m_associations.first.queueSize)
1093  GetKeyFromKMS(m_associations.first.ksid);
1094  else
1095  encQueueReady = true;
1096 
1097  if(m_associations.second.verified && m_associations.second.buffer.size() < m_associations.second.queueSize)
1098  GetKeyFromKMS(m_associations.second.ksid);
1099  else
1100  authQueueReady = true;
1101 
1102  if(authQueueReady && encQueueReady){
1103  if(!m_master){
1104  NS_LOG_FUNCTION( this << "Replica QKDApp established key queues" );
1107  }else if(m_master){
1109  NS_LOG_FUNCTION( this << "Both Primary and Replica QKDApp established queues!" );
1112  }else{
1113  NS_LOG_FUNCTION( this << "Primary QKDApp establihed queues! Waiting on Replica QKDApp ..." );
1115  }
1116  }
1117  }
1118 
1119 }
1120 
1123 {
1124  NS_LOG_FUNCTION( this << m_master << "Obtaining encryption key from the local QKDApp buffer ..." << m_associations.first.ksid );
1125  if(m_master){ //Primary QKDApp obtains encryption key
1126 
1127  NS_LOG_FUNCTION( this << "We have in total " << m_associations.first.buffer.size() << " encryption keys!");
1128 
1129  QKDApp004::QKDAppKey output;
1130  std::map<uint32_t, QKDAppKey>::iterator it = m_associations.first.buffer.begin();
1131  NS_ASSERT (it != m_associations.first.buffer.end());
1132 
1133  NS_LOG_FUNCTION( this << "The lifetime of the first key is " << (it->second).lifetime );
1134 
1135  output = it->second;
1136  (it->second).lifetime -= m_packetSize; //Decrease key lifetime by packet size!
1137  NS_LOG_FUNCTION( this << "Remaining lifetime: " << output.lifetime );
1138 
1139  uint32_t counter = 0;
1140  for(std::map<uint32_t, QKDAppKey>::iterator it2 = m_associations.first.buffer.begin(); it2 != m_associations.first.buffer.end();)
1141  {
1142 
1143  NS_LOG_FUNCTION(this << "Key " << counter++ << " of size " << output.key.size() << " and lifetime " << (it2->second).lifetime );
1144  if(int32_t ((it2->second).lifetime) <= 0)
1145  {
1146  //Key expires and is deleted!
1147  NS_LOG_FUNCTION( this << "Local encryption key erased " << it2->first << ". Key lifetime expired!" );
1148  m_associations.first.buffer.erase(it2++); //Delete expired key
1149  GetKeyFromKMS(m_associations.first.ksid, 0); //Make new get_key request to obtain the next key!
1150  }else{
1151  ++it2;
1152  }
1153  }
1154 
1155  NS_LOG_FUNCTION(this << "Returning key of size " << output.key.size());
1156  return output; //return encryption key
1157 
1158  }else{ //Replica QKDApp obtains encryption key
1159  std::map<uint32_t, QKDAppKey>::iterator it = m_associations.first.buffer.find(m_associations.first.keyActive),
1160  it1 = m_associations.first.buffer.begin();
1161 
1162  QKDApp004::QKDAppKey encKey;
1163  if(it == m_associations.first.buffer.end())
1164  {
1165  //Out of sync!
1166  //Key is not obtained in time, packet should be stored for delayed processing!
1167  encKey.key = ""; //return empty key
1168  }else
1169  encKey = it->second; //encryption key (keyActive previously read from the QKDApp header)
1170 
1171  std::map<uint32_t, QKDAppKey>::iterator a = m_associations.first.buffer.begin(),
1172  b = m_associations.first.buffer.end();
1173  while(a != b){
1174  NS_LOG_FUNCTION( this << "Local encryption key store entry (test - krecS)" << a->first );
1175  ++a;
1176  }
1177  while(it1 != it){ //Remove any key older then keyActive (NOTE: could cause problems with delayed packets!)
1178  NS_LOG_FUNCTION( this << "Local encryption key erased " << it1->first << ". Synchronization!" );
1179  m_associations.first.buffer.erase(it1); //Remove first entry - oldest key
1180  it1 = m_associations.first.buffer.begin();
1181  }
1182  return encKey; //return encryption key
1183  }
1184 
1185 }
1186 
1189 {
1190  NS_LOG_FUNCTION( this << m_master << "Obtaining authentication key from the local QKDApp buffer ..." << m_associations.second.ksid );
1191  if(m_master){
1192 
1193  NS_LOG_FUNCTION( this << "We have in total " << m_associations.second.buffer.size() << " authentication keys!");
1194 
1195  std::map<uint32_t, QKDAppKey>::iterator it = m_associations.second.buffer.begin();
1196  NS_ASSERT (it != m_associations.second.buffer.end());
1197 
1198  QKDApp004::QKDAppKey authKey = it->second; //Authentication key is the first key in synchronized local QKDApp buffer
1199 
1200  std::map<uint32_t, QKDAppKey>::iterator a = m_associations.second.buffer.begin(),
1201  b = m_associations.second.buffer.end();
1202  while(a != b){
1203  NS_LOG_FUNCTION( this << "Local authentication key store entry (test - krecM)" << a->first << a->second.key.size());
1204  ++a;
1205  }
1206 
1207  NS_LOG_FUNCTION( this << "Local authentication key erased " << it->first );
1208  m_associations.second.buffer.erase(it); //Authentication keys do not have lifetime! One use only!
1209  NS_LOG_FUNCTION( this << "Calling get_key request" );
1210  GetKeyFromKMS(m_associations.second.ksid, 0); //Make new get_key request to obtain the next key!
1211 
1212  return authKey; //return authentication key
1213 
1214  }else{
1215  std::map<uint32_t, QKDAppKey>::iterator it = m_associations.second.buffer.find(m_associations.second.keyActive),
1216  it1 = m_associations.second.buffer.begin();
1217  QKDApp004::QKDAppKey authKey;
1218  if(it == m_associations.second.buffer.end()){ //Out of sync!
1219  //Key is not obtained in time, packet should be stored for delayed processing!
1220  authKey.key = ""; //return empty key
1221  }else
1222  authKey = it->second; //authentication key (keyActive previously read from the QKDApp header)
1223  while(it1 != it){ //Remove any key older then keyActive (NOTE: could cause problems with delayed packets!)
1224  NS_LOG_FUNCTION( this << "Local authentication key erased " << it1->first );
1225  m_associations.second.buffer.erase(it1);
1226  it1 = m_associations.second.buffer.begin();
1227  }
1228  return authKey; //return authentication key
1229  }
1230 
1231 }
1232 
1233 
1234 
1242 void
1243 QKDApp004::Http004AppQuery (uint32_t methodType, std::string ksid)
1244 {
1245  NS_LOG_FUNCTION(this << methodType << ksid);
1246  m_httpRequestsApp.push_back (std::make_pair (methodType, ksid));
1247 }
1248 
1249 void
1251 {
1252  if(m_httpRequestsApp.size() > 0)
1253  m_httpRequestsApp.erase (m_httpRequestsApp.begin());
1254 }
1255 
1256 uint32_t
1258 {
1259  NS_LOG_FUNCTION( this );
1260  return (m_httpRequestsApp[0]).first;
1261 }
1262 
1263 std::string
1265 {
1266  NS_LOG_FUNCTION( this );
1267  return (m_httpRequestsApp[0]).second;
1268 }
1269 
1270 
1271 
1279 void
1280 QKDApp004::Http004KMSQuery (std::string uri, std::string ksid, uint32_t keyType)
1281 {
1282  NS_LOG_FUNCTION(this << uri << ksid << keyType );
1283 
1284  m_httpRequestsKMS.insert(
1285  std::make_pair(
1286  uri,
1287  std::make_pair(ksid, keyType)
1288  )
1289  );
1290 }
1291 
1292 void
1294 {
1295  NS_LOG_FUNCTION(this << uri << m_httpRequestsKMS.size());
1296 
1297  std::map<std::string, std::pair<std::string, uint32_t> >::iterator it = m_httpRequestsKMS.find(uri);
1298  if ( it != m_httpRequestsKMS.end () ){
1299  m_httpRequestsKMS.erase(it);
1300  }
1301 }
1302 
1303 uint32_t
1305 {
1306  NS_LOG_FUNCTION( this << uri );
1307  //OPEN_CONNECT 0, GET_KEY 1, CLOSE 2
1308 
1309  size_t pos = 0;
1310  std::string delimiter = "/";
1311  std::string token;
1312  std::vector<std::string> uriParams;
1313  while ((pos = uri.find(delimiter)) != std::string::npos) {
1314  token = uri.substr(0, pos);
1315  if(token.length() > 0){
1316  uriParams.push_back(token);
1317  }
1318  uri.erase(0, pos + delimiter.length());
1319  }
1320  if(uri.length() > 0){
1321  uriParams.push_back(uri);
1322  }
1323  for(uint32_t i=0; i< uriParams.size(); i++){
1324  if(uriParams[i] == "open_connect"){
1325  return 0;
1326  }else if(uriParams[i] == "get_key"){
1327  return 1;
1328  }else if(uriParams[i] == "close"){
1329  return 2;
1330  }
1331  }
1332  NS_FATAL_ERROR( "METHOD NOT FOUND " << uri );
1333  return 0;
1334 }
1335 
1336 std::string
1338 {
1339  NS_LOG_FUNCTION( this << uri << m_httpRequestsKMS.size() );
1340 
1341  //FETCH KSID FROM CACHE
1342  uri = "http://" + uri;
1343  std::map<std::string, std::pair<std::string, uint32_t> >::iterator it = m_httpRequestsKMS.find(uri);
1344  if ( it != m_httpRequestsKMS.end () ){
1345  return it->second.first;
1346  }
1347 
1348  //FETCH KSID FROM THE URI
1349  size_t pos = 0;
1350  std::string delimiter = "/";
1351  std::string token;
1352  std::vector<std::string> uriParams;
1353  while ((pos = uri.find(delimiter)) != std::string::npos) {
1354  token = uri.substr(0, pos);
1355  if(token.length() > 0){
1356  uriParams.push_back(token);
1357  }
1358  uri.erase(0, pos + delimiter.length());
1359  }
1360  if(uri.length() > 0){
1361  uriParams.push_back(uri);
1362  }
1363  for(uint32_t i=0; i< uriParams.size(); i++){
1364  NS_LOG_FUNCTION(this << i << uriParams[i]);
1365  if(uriParams[i] == "open_connect" || uriParams[i] == "get_key" || uriParams[i] == "close"){
1366  return uriParams[i-1];
1367  }
1368  }
1369 
1370  NS_FATAL_ERROR( "KSID NOT FOUND " << uri );
1371  return "";
1372 }
1373 
1374 uint32_t
1376 {
1377  NS_LOG_FUNCTION( this << uri );
1378  uri = "http://" + uri;
1379 
1380  std::map<std::string, std::pair<std::string, uint32_t> >::iterator it = m_httpRequestsKMS.find(uri);
1381  if ( it != m_httpRequestsKMS.end () ){
1382  return it->second.second;
1383  }
1384 
1385  NS_FATAL_ERROR( "KEY TYPE NOT FOUND " << uri );
1386  return 0;
1387 }
1388 
1389 
1395 void
1397 {
1398  NS_LOG_FUNCTION (this);
1399 
1400  //Check whether the socket to KMS is active and connected
1401  Address temp;
1402  if(!m_sendSocketToKMS || m_sendSocketToKMS->GetPeerName (temp) != 0){
1404  }
1405 
1406  if(m_appState != READY)
1407  return; //Simple malicious application is stopped, abort!
1408 
1409  std::string message;
1410 
1411  if(1 || !m_maliciousPacket){ //Create malicious packet for the first time
1412 
1413  std::string maliciousKsid = UUID::Sequential().string();
1414 
1415  if(GetAppState() == QKDApp004::STOPPED) return;
1417 
1419  std::ostringstream lkmsAddressTemp;
1420  lkmsAddress.Print(lkmsAddressTemp); //IPv4Address to string
1421  std::string headerUri = "http://" + lkmsAddressTemp.str();
1422  //headerUri += "/api/v1/keys/" + maliciousKsid + "/get_key";
1423  headerUri += "/api/v1/keys/" + m_dstSaeId.string() + "/open_connect/1";
1424  NS_LOG_FUNCTION(this << "maliciousKsid: " << headerUri );
1425 
1426  nlohmann::json msgBody; //No metadata
1427  //msgBody["Key_stream_ID"] = maliciousKsid;
1428  msgBody["Source"] = m_id.string();
1429  msgBody["Destination"] = m_dstSaeId.string();
1430  msgBody["QoS"] = {
1431  {"priority", 0},
1432  {"max_bps", 50000},
1433  {"min_bps", 100},
1434  {"jitter", 100},
1435  {"timeout", 100},
1436  {"key_chunk_size", 100},
1437  {"TTL", 10}
1438  };
1439 
1440  message = msgBody.dump();
1441 
1442  //Create packet
1443  HTTPMessage httpMessage;
1444  httpMessage.CreateRequest(headerUri, "POST", message);
1445  std::string hMessage = httpMessage.ToString();
1446  m_maliciousPacket = Create<Packet> (
1447  (uint8_t*) (hMessage).c_str(),
1448  hMessage.size()
1449  );
1450 
1452  }
1453 
1454  //Send malicious packet to KMS
1455  NS_LOG_FUNCTION (this << "Sending malicious PACKETID: " << m_maliciousPacket->GetUid()
1456  << " of size: " << m_maliciousPacket->GetSize()
1457  << " with payload: " << message
1458  << " via socket " << m_sendSocketToKMS
1459  );
1462 
1463  //Schedule next malicious request to KMS
1465 
1466 }
1467 
1473 void
1475 {
1476 
1477  NS_LOG_FUNCTION( this << m_local << m_peer << m_master );
1478  m_packetsSent = 0;
1479 
1480  if(m_malicious && m_master){ //Does not need to validate config. parameters
1481  m_maliciousPacket = NULL;
1484  return; //do not proceed with the function
1485  }
1486 
1487  if(m_encryptionTypeInt < 0 || m_encryptionTypeInt > 2){
1488  NS_FATAL_ERROR( "Invalid encryption type " << m_encryptionTypeInt
1489  << ". Allowed values are (0-unencrypted, 1-OTP, 2-AES)" );
1490  }
1491  if(m_authenticationTypeInt < 0 || m_authenticationTypeInt > 3){
1492  NS_FATAL_ERROR( "Invalid authentication type " << m_authenticationTypeInt
1493  << ". Allowed values are (0-unauthenticated, 1-VMAC, 2-MD5, 3-SHA1)" );
1494  }
1495  if(m_aesLifetime < 0){
1496  NS_FATAL_ERROR( "Invalid AES lifetime " << m_aesLifetime
1497  << ". The value must be larger than zero." );
1498  } else if(m_aesLifetime != 0 && m_aesLifetime < m_packetSize)
1499  NS_FATAL_ERROR( "Invalid AES lifetime " << m_aesLifetime
1500  << ". The value must be larger than one packet size " << m_packetSize );
1501 
1502  if(m_encryptionTypeInt == 1)
1503  m_aesLifetime = m_packetSize; //For when OTP is applied
1504 
1505  if(m_appState == INITIALIZED){
1510  );
1511  AppTransitionTree(); //Transition states
1512  PrepareSinkSocketFromApp(); //Create sink sockets for peer QKD applications
1513 
1514  }else
1515  NS_FATAL_ERROR( "Invalid state " << GetAppStateString ()
1516  << " for StartApplication()." );
1517 
1518 }
1519 
1520 void
1522 {
1523  //@toDo: As any other responsible application, on stopping, application will call CLOSE
1524  // Application will wait for response (but it is optional) and then close sockets!
1525  NS_LOG_FUNCTION( this << "Stopping QKDApp ... " );
1526  if(m_sendEvent.IsRunning())
1528 
1529  if(m_master){ //Only Primary QKDApp calls CLOSE, as it is one responsible for the associations!
1530  NS_LOG_FUNCTION( this << "Closing assocaitions ... ");
1531  if(!m_associations.first.ksid.empty()) //Encrpytion association active
1532  Close(m_associations.first.ksid);
1533 
1534  if(!m_associations.second.ksid.empty()) //Authentication association active
1535  Close(m_associations.second.ksid);
1536 
1537  }else{ //Replica QKDApp closes sockets to the KMS also
1538  if(m_sendSocketToKMS)
1540  if(m_sendSocketToKMS)
1542  }
1543  //Closing send and sink sockets for QKDApp communication!
1552 
1554  InitializeAssociations(); //Clear associations records
1555  NS_LOG_FUNCTION( this << "Data and signaling sockets are closed. Data transmission is stopped ..." );
1556 }
1557 
1558 void
1560 {
1561  NS_LOG_FUNCTION( this );
1563 
1564  if (m_appState == READY) //Direct call from SceduleTx()
1566 
1567  NS_LOG_FUNCTION(this << "testkrec" << m_appState);
1568  if (m_appState == SEND_DATA) {
1569 
1570  if(!m_sendDataSocketApp) {
1572  }
1573 
1574  //Obtain secret keys!
1575  QKDApp004::QKDAppKey encKey;
1576  encKey.index = 0;
1577  QKDApp004::QKDAppKey authKey;
1578  authKey.index = 0;
1579 
1580  //Obtain encryption key!
1581  if (GetEncryptionKeySize() != 0){
1582  encKey = GetEncKey();
1583  if(encKey.key == ""){
1585  return;
1586  }
1587  }
1588 
1589  //Obtain authentication key from application key buffer!
1590  if (GetAuthenticationKeySize() != 0){
1591  authKey = GetAuthKey();
1592  if(authKey.key == ""){
1594  return;
1595  }
1596  }
1597 
1598 
1599  //Keys are not Base64 coded!
1600  NS_LOG_FUNCTION(this << "\nEncryption Key (krec)" << encKey.key << "\nAuthentication Key (krec)" << authKey.key);
1601 
1602  //Define confidential message
1603  std::string confidentialMsg = GetPacketContent();
1604  NS_LOG_FUNCTION( this << "Confidential message" << confidentialMsg.size() << confidentialMsg );
1605 
1606  std::string encryptedMsg;
1607  std::string authTag;
1608  if (m_useCrypto) {
1609 
1610  encryptedMsg = m_encryptor->EncryptMsg(confidentialMsg, encKey.key);
1611  NS_LOG_FUNCTION ( this << "Encryption key" << encKey.index << encKey.key
1612  << "Encrypted message" << m_encryptor->Base64Encode(encryptedMsg));
1613  if(GetAuthenticationKeySize() != 0)
1614  authTag = m_encryptor->Authenticate (encryptedMsg, authKey.key);
1615  else
1616  authTag = GetPacketContent(32);
1617  NS_LOG_FUNCTION( this << "Authentication key" << authKey.index << authKey.key
1618  << "Authentication tag" << authTag );
1619 
1620  } else {
1621 
1622  encryptedMsg = confidentialMsg;
1623  authTag = GetPacketContent(32); //Use random authTag
1624  NS_LOG_FUNCTION ( this << "Encryption key" << encKey.index << encKey.key );
1625  NS_LOG_FUNCTION( this << "Authentication key" << authKey.index << authKey.key );
1626  NS_LOG_FUNCTION( this << "Authentication Tag" << authTag);
1627 
1628  }
1629 
1630  //Create packet with protected/unprotected data
1631  std::string msg = encryptedMsg;
1632  Ptr<Packet> packet = Create<Packet> ( (uint8_t*) msg.c_str(), msg.length() );
1633  NS_ASSERT (packet);
1634  m_authenticationTrace (packet, authTag);
1635 
1636  //Add qkd header!
1637  QKDAppHeader qHeader;
1638  qHeader.SetEncrypted(m_encryptionType);
1639  qHeader.SetEncryptionKeyId(std::to_string(encKey.index));
1641  qHeader.SetAuthenticationKeyId(std::to_string(authKey.index));
1642  qHeader.SetAuthTag(authTag);
1643  qHeader.SetLength(packet->GetSize() + qHeader.GetSerializedSize());
1644  packet->AddHeader(qHeader);
1645 
1646  //Send packet!
1647  m_txTrace (packet, m_associations.first.ksid);
1648  m_txTrace (packet, m_associations.second.ksid);
1649  m_sendDataSocketApp->Send (packet);
1650  m_packetsSent++;
1651  m_dataSent += packet->GetSize();
1652 
1653  NS_LOG_FUNCTION (this << "Sending protected packet: " << packet->GetUid() << " of size " << packet->GetSize() );
1654 
1655  SwitchAppState(READY); //Application should go in ready or wait! If buffer is empty go to WAIT.
1656  //When a number of keys are obtained again, go to READY state.
1657  ScheduleTx (); //Schedule new time instance to send data!
1658 
1659  } else if (m_appState == WAIT) {
1660 
1661  //m_txTrace (0, m_associations.first.ksid);
1662  //m_txTrace (0, m_associations.second.ksid);
1663 
1664  ScheduleTx ();
1665  NS_LOG_FUNCTION( this << "Application is currently unable to send new data! QKDApp state" << GetAppStateString(m_appState) );
1666 
1667  } else {
1668 
1669  NS_FATAL_ERROR( this << "Application is in invalid state!" );
1670 
1671  }
1672 
1673 }
1674 
1675 void
1677 {
1678  NS_LOG_FUNCTION( this << "Processing data packet from peer QKDApp" );
1679  if(!m_master){ //Only Replica QKDApp receives encrypted data!
1680  std::string payload = PacketToString(packet); //Read the packet data
1681  NS_LOG_FUNCTION( this << "Received data packet" << m_encryptor->Base64Encode(payload) );
1682 
1685  std::string decryptedMsg;
1686  bool authSuccessful = false;
1687 
1688  NS_LOG_FUNCTION( this << "Executing authentication check on received packet!" );
1689  if(GetAuthenticationKeySize() != 0){ //Authentication requires QKD key
1690  NS_LOG_FUNCTION(this << "VMAC authentciation" );
1691  if(uint32_t (std::stoi(header.GetAuthenticationKeyId())) > m_associations.second.keyActive){
1692  m_associations.second.keyActive = std::stoi(header.GetAuthenticationKeyId()); //new keyActive read from QKDApp header
1693  NS_LOG_FUNCTION( this << "Synchronization - calling get_key request" );
1694  GetKeyFromKMS(m_associations.second.ksid, 0); //Calling get_key request
1695  }
1696 
1697  QKDApp004::QKDAppKey authKey = GetAuthKey(); //Obtain authentication key
1698  if(authKey.key == ""){ //Packet received out of sync (dealyed packet). Packet is dropped!
1699  NS_LOG_FUNCTION( this << "Authentication key not available" << m_associations.second.keyActive << "Packet is dropped!" );
1701  return;
1702  }
1703 
1704  NS_LOG_FUNCTION( this << "Authentication key obtained from the local key store" << authKey.index << authKey.key );
1705  if(m_useCrypto){ //Perform actual authentication check
1706  //Check authTag
1707  if(m_encryptor->CheckAuthentication(payload, header.GetAuthTag(), authKey.key)) //Check AuthTag
1708  authSuccessful = true;
1709 
1710  }else //We assume packet is successfully authenticated
1711  authSuccessful = true;
1712 
1713  }else if(header.GetAuthenticated()){ //Authentication does not require quantum key
1714  if (m_useCrypto){
1715  if(m_encryptor->CheckAuthentication(payload, header.GetAuthTag(), ""))
1716  authSuccessful = true;
1717 
1718  }else //We assume packet is successfully authenticated
1719  authSuccessful = true;
1720 
1721  }else //No authentication services
1722  authSuccessful = true;
1723 
1724  if(authSuccessful)
1725  NS_LOG_FUNCTION( this << "Packet is successfully authenticated! Processing ... " );
1726  else
1727  NS_LOG_FUNCTION( this << "Authentication of received packet FAILED. Packet is dropped!" );
1728 
1729  //Perform decryption
1730  if (header.GetEncrypted()){
1731  NS_LOG_FUNCTION(this << "Decrypting received packet ... ");
1732  if(uint32_t (std::stoi(header.GetEncryptionKeyId())) > m_associations.first.keyActive){
1733  m_associations.first.keyActive = std::stoi(header.GetEncryptionKeyId()); //new keyActive index
1734  NS_LOG_FUNCTION( this << "Synchronization - calling get_key request" );
1735  GetKeyFromKMS(m_associations.first.ksid, 0); //Calling get_key request
1736  }
1737 
1738  QKDApp004::QKDAppKey encKey = GetEncKey(); //Obtain encryption key
1739  if(encKey.key == ""){ //Out of sync (delayed packet)! Packet is dropped!
1740  NS_LOG_FUNCTION( this << "Encyption key not available" << m_associations.first.keyActive << "Packet is dropped!" );
1742  return;
1743  }
1744 
1745  NS_LOG_FUNCTION( this << "Encryption key obained from the local key store " << encKey.index << encKey.key );
1746  if(m_useCrypto){
1747  if(authSuccessful){ //Packet is decrypted only when it is succesfully authenticated
1748  decryptedMsg = m_encryptor->DecryptMsg (payload, encKey.key);
1749  NS_LOG_FUNCTION( this << "Packet decrypted! Decrypted message: \n" << decryptedMsg );
1750  }
1751  }else{ //Fake decryption process
1752  if(authSuccessful)
1753  NS_LOG_FUNCTION( this << "Packet decrypted!" );
1754  }
1755 
1756  }else //Receiving unprotected packet
1757  NS_LOG_FUNCTION( this << "Packet received unprotected! Received message: \n" << payload );
1758 
1760 
1761  }else
1762  NS_FATAL_ERROR( this << "Only Replica QKDApp receives protected packets! Only unidirectional secure data communication!" );
1763 
1764 }
1765 
1766 
1767 void
1769 {
1770  NS_LOG_FUNCTION (this << "Processing response from KMS" << packet->GetUid() << packet->GetSize());
1771 
1772  std::string requestUri = header.GetRequestUri();
1773  NS_LOG_FUNCTION(this << requestUri);
1774 
1775  uint32_t etsiFunction = GetMethodFromHttp004KMSQuery(requestUri); //Map response to request
1776  //OPEN_CONNECT 0, GET_KEY 1, CLOSE 2
1777 
1778  if(etsiFunction == 0 && m_appState != STOPPED)
1779  { //Response on OPEN_CONNECT
1781  }else if(etsiFunction == 1 && m_appState != STOPPED){ //Response on GET_KEY
1782  ProcessGetKeyResponse(header);
1783  }else if(etsiFunction == 2 && m_appState != STOPPED){ //Response on CLOSE
1784  ProcessCloseResponse(header);
1785  }else
1786  NS_FATAL_ERROR (this << "Invalid ETSI QKD GS 004 function used in request");
1787 
1788  Http004KMSQueryComplete( requestUri ); //Remove request from http query
1789 }
1790 
1791 
1800 void
1801 QKDApp004::OpenConnect (std::string ksid, uint32_t keyType)
1802 {
1803  if(!m_master && m_associations.second.ksid == ksid){
1804  keyType = 1;
1805  }
1806 
1807  NS_LOG_FUNCTION( this << "OPEN_CONNECT(master, ksid, keyType)" <<
1808  m_master << ksid << keyType);
1809  NS_ASSERT(keyType >= 0);
1810  NS_ASSERT(keyType < 3);
1811 
1812  if(!m_sinkSocketFromKMS) {
1814  }
1815 
1816  uint64_t maxRate = GetMaxEncryptionKeyRate() + GetMaxAuthenticationKeyRate();
1817  uint64_t minRate = m_minDataRate.GetBitRate();
1818 
1819  NS_LOG_FUNCTION(this << maxRate << minRate);
1820 
1821  uint32_t keySize {0};
1822  if(!keyType) { //0 - encrption key
1823  keySize = GetEncryptionKeySize();
1824  }else{ //1 - authentication key
1825  keySize = GetAuthenticationKeySize();
1826  }
1827 
1828  if(m_master) NS_ASSERT(keySize != 0);
1829 
1830  NS_ASSERT(m_priority < 2);
1831 
1832  nlohmann::json msgBody;
1833  msgBody["Source"] = m_id.string();
1834  msgBody["Destination"] = m_dstSaeId.string();
1835  msgBody["QoS"] = {
1836  {"priority", m_priority},
1837  {"max_bps", maxRate},
1838  {"min_bps", minRate},
1839  {"jitter", 100},
1840  {"timeout", 100},
1841  {"key_chunk_size", keySize},
1842  {"TTL", m_ttl}
1843  };
1844 
1845  if(!m_master){
1846  msgBody["Key_stream_ID"] = ksid;
1847  }else{
1848  msgBody["QoS"]["key_chunk_size"] = keySize;
1849  }
1850 
1851  std::string message = msgBody.dump();
1852 
1854  std::ostringstream lkmsAddressTemp;
1855  lkmsAddress.Print(lkmsAddressTemp); //IPv4Address to string
1856  std::string headerUri = "http://" + lkmsAddressTemp.str();
1857  headerUri += "/api/v1/keys/" + m_dstSaeId.string() + "/open_connect/" + std::to_string(keyType);
1858 
1859  //Create packet
1860  HTTPMessage httpMessage;
1861  httpMessage.CreateRequest(headerUri, "POST", message);
1862  std::string hMessage = httpMessage.ToString();
1863  Ptr<Packet> packet = Create<Packet> (
1864  (uint8_t*) (hMessage).c_str(),
1865  hMessage.size()
1866  );
1867  NS_ASSERT (packet);
1868 
1869  NS_LOG_FUNCTION (this << "Sending PACKETID: " << packet->GetUid()
1870  << " of size: " << packet->GetSize()
1871  << " via socket " << m_sendSocketToKMS
1872  );
1873  //check whether the socket to KMS is active and connected
1874  Address temp;
1875  if(!m_sendSocketToKMS || m_sendSocketToKMS->GetPeerName(temp) != 0){
1877  QKDApp004::KMSPacket kmsPacket;
1878  kmsPacket.packet = packet;
1879  kmsPacket.methodType = 0;
1880  kmsPacket.uri = headerUri;
1881  if(m_master){
1882  kmsPacket.keyType = keyType;
1883  kmsPacket.ksid = "";
1884  }else{
1885  kmsPacket.keyType = 0;
1886  kmsPacket.ksid = ksid;
1887  }
1888  m_queue_kms.push_back(kmsPacket);
1889 
1890  }else{
1891  Http004KMSQuery(headerUri, ksid, keyType ); //OPEN_CONNECT 0, GET_KEY 1, CLOSE 2; encKey 0, authKey 1)
1892 
1893  m_txKmsTrace(packet);
1894  m_sendSocketToKMS->Send(packet);
1895  }
1896 }
1897 
1898 void
1899 QKDApp004::GetKeyFromKMS (std::string ksid, uint32_t index)
1900 {
1901  NS_LOG_FUNCTION( this << "GET_KEY (master,ksid,index)" << m_master << ksid << index );
1902 
1903  if(GetAppState() == QKDApp004::STOPPED) return;
1905 
1907  std::ostringstream lkmsAddressTemp;
1908  lkmsAddress.Print(lkmsAddressTemp); //IPv4Address to string
1909  std::string headerUri = "http://" + lkmsAddressTemp.str();
1910  headerUri += "/api/v1/keys/" + ksid + "/get_key/fresh/" + std::to_string(m_random->GetValue (0,1000000));
1911 
1912  nlohmann::json msgBody; //No metadata
1913  msgBody["Key_stream_ID"] = ksid;
1914  std::string message = msgBody.dump();
1915 
1916  //Create packet
1917  HTTPMessage httpMessage;
1918  httpMessage.CreateRequest(headerUri, "POST", message);
1919  std::string hMessage = httpMessage.ToString();
1920  Ptr<Packet> packet = Create<Packet> (
1921  (uint8_t*) (hMessage).c_str(),
1922  hMessage.size()
1923  );
1924  NS_ASSERT (packet);
1925 
1926  NS_LOG_FUNCTION (this << "Sending PACKETID: " << packet->GetUid()
1927  << " of size: " << packet->GetSize()
1928  << " via socket " << m_sendSocketToKMS
1929  );
1930 
1931  //Check whether the socket to KMS is active and connected
1932  Address temp;
1933  if(!m_sendSocketToKMS || m_sendSocketToKMS->GetPeerName (temp) != 0){
1935  QKDApp004::KMSPacket kmsPacket;
1936  kmsPacket.packet = packet;
1937  kmsPacket.methodType = 1;
1938  kmsPacket.keyType = 0;
1939  kmsPacket.ksid = ksid;
1940  kmsPacket.uri = headerUri;
1941  m_queue_kms.push_back(kmsPacket);
1942  }else{
1943  Http004KMSQuery(headerUri, ksid, 0); //(etsi 004 function: OPEN_CONNECT 0, GET_KEY 1, CLOSE 2; KSID)
1944  m_txKmsTrace (packet);
1945  m_sendSocketToKMS->Send(packet);
1946  }
1947 }
1948 
1949 void
1950 QKDApp004::Close (std::string ksid)
1951 {
1952  NS_LOG_FUNCTION( this << "Closing key stream association" << m_master << ksid );
1954 
1955  //Empty queues assigned to this association and association registry
1956  if(m_associations.first.ksid == ksid){//close encryption association
1957  //InitializeAssociation(ksid);
1958  NS_LOG_FUNCTION( this << "Encryption key stream association closed on QKDApp side!");
1959  }else if(m_associations.second.ksid == ksid){
1960  //InitializeAssociation(ksid);
1961  NS_LOG_FUNCTION( this << "Authentication key stream association closed on QKDApp side!");
1962  }else
1963  NS_FATAL_ERROR( this << "Closing association failed. Ksid not registered" << ksid );
1964 
1965  //Send CLOSE message to the local KMS
1967  std::ostringstream lkmsAddressTemp;
1968  lkmsAddress.Print(lkmsAddressTemp); //IPv4Address to string
1969  std::string headerUri = "http://" + lkmsAddressTemp.str ();
1970  headerUri += "/api/v1/keys/" + ksid + "/close";
1971 
1972  //Create packet
1973  HTTPMessage httpMessage;
1974  httpMessage.CreateRequest(headerUri, "GET");
1975  std::string hMessage = httpMessage.ToString();
1976  Ptr<Packet> packet = Create<Packet> (
1977  (uint8_t*) (hMessage).c_str(),
1978  hMessage.size()
1979  );
1980  NS_ASSERT (packet);
1981 
1982  NS_LOG_FUNCTION (this << "Sending PACKETID: " << packet->GetUid()
1983  << " of size: " << packet->GetSize()
1984  << " via socket " << m_sendSocketToKMS
1985  );
1986 
1987  //check whether the socket to KMS is active and connected
1988  Address temp;
1989  if(!m_sendSocketToKMS || m_sendSocketToKMS->GetPeerName (temp) != 0){
1991  QKDApp004::KMSPacket kmsPacket;
1992  kmsPacket.packet = packet;
1993  kmsPacket.methodType = 2;
1994  kmsPacket.keyType = 0;
1995  kmsPacket.ksid = ksid;
1996  kmsPacket.uri = headerUri;
1997  m_queue_kms.push_back(kmsPacket);
1998  }else{
1999  //Store request to HTTP requests store (to be able to map responses)
2000  Http004KMSQuery(headerUri, ksid, 2); //(etsi gs 004 function: OPEN_CONNECT 0, GET_KEY 1, CLOSE 2; KSID)
2001  m_txKmsTrace (packet);
2002  m_sendSocketToKMS->Send (packet);
2003  }
2004 
2005 }
2006 
2007 void
2009 {
2010  NS_LOG_FUNCTION( this << "Processing OPEN_CONNECT response!" << m_master );
2011 
2013 
2014  std::string payload = header.GetMessageBodyString(); //Read HTTP body message
2015  nlohmann::json jOpenConnect; //Read JSON data structure from message
2016  if(!payload.empty()){
2017  try{
2018  jOpenConnect = nlohmann::json::parse(payload);
2019  }catch(...){
2020  NS_FATAL_ERROR( this << "JSON parse error!");
2021  }
2022  }
2023 
2024  NS_LOG_FUNCTION(this << payload);
2025 
2026  std::string requestUri = header.GetRequestUri();
2027  HTTPMessage::HttpStatus responseStatus = header.GetStatus();
2028  if(
2029  responseStatus == HTTPMessage::HttpStatus::BadRequest ||
2030  responseStatus == HTTPMessage::HttpStatus::Unauthorized ||
2031  responseStatus == HTTPMessage::HttpStatus::ServiceUnavailable
2032  ){ //Process status field of response (ETSI004 defined: 1, 4, 5, 7)
2033 
2034  if(m_master){
2035 
2036  std::string ksid = GetKsidFromHttp004KMSQuery(requestUri);
2037  uint32_t keyType = GetKeyTypeFromHttp004KMSQuery(requestUri);
2038 
2039  Time t {"5s"};
2040  EventId event = Simulator::Schedule (t, &QKDApp004::OpenConnect, this, ksid, keyType);
2041  //@toDoFuture If (QoS is rejected){repeat request in few sec (stage-1)}else{report fatal_error}
2042  //uint32_t status004 = jOpenConnect["status"]; //Read status code for OPEN_CONNECT
2043  NS_LOG_FUNCTION( this << "QKDApp received ERROR on OPEN_CONNECT." );
2044 
2045  }else{
2046  std::string ksid = GetKsidFromHttp004KMSQuery(requestUri);
2047  ClearAssociation(ksid); //Clear key stream association
2048  SendKsidResponse(HTTPMessage::HttpStatus::ServiceUnavailable); //Send response on /connect indicating error!
2049  }
2050 
2051  }else if(responseStatus == HTTPMessage::HttpStatus::Ok){ //For ETSI004 status 0
2052  NS_LOG_FUNCTION( this << "Successful OPEN_CONNECT" );
2053  if(m_master){ //Primary QKDApp on OPEN_CONNECT response
2054 
2055  std::string ksid;
2056  if(jOpenConnect.contains("Key_stream_ID")) ksid = jOpenConnect["Key_stream_ID"];
2057  NS_ASSERT(!ksid.empty());
2058 
2059  uint32_t keyType = GetKeyTypeFromHttp004KMSQuery(requestUri);
2060  if(keyType == 0){
2061  NS_LOG_FUNCTION( this << "KSID " << ksid << " registered for encryption" );
2062  m_associations.first.ksid = ksid; //Register encryption ksid
2063  }else{
2064  NS_LOG_FUNCTION( this << "KSID " << ksid << " registered for authentication" );
2065  m_associations.second.ksid = ksid; //Register authentication ksid
2066  }
2067  SendKsidRequest(ksid, keyType); //Connect to peer QKDApp by sending ksid
2068 
2069  }else{ //Replica QKDApp on OPEN_CONNECT response
2070 
2071  std::string ksid = GetKsidFromHttp004KMSQuery(requestUri);
2072  if (m_associations.first.ksid == ksid)
2073  m_associations.first.verified = true; //Association is verified if it's established by both QKDApp!
2074  else if (m_associations.second.ksid == ksid)
2075  m_associations.second.verified = true; //Association is verified if it's established by both QKDApp!
2076  else{
2077  NS_FATAL_ERROR( this
2078  << "Unknown ksid: " << ksid << "\t"
2079  << m_associations.first.ksid << "\t"
2080  << m_associations.second.ksid
2081  );
2082  }
2083  SendKsidResponse(HTTPMessage::HttpStatus::Ok); //Send response on /connect indicating success!
2084  }
2085 
2086  }else
2087  NS_FATAL_ERROR( this << "Unsupported error status code" << responseStatus << "of response.");
2088 
2089 }
2090 
2091 void
2093 {
2094  NS_LOG_FUNCTION( this );
2095  std::string payload = header.GetMessageBodyString();
2096  std::string requestUri = header.GetRequestUri();
2097  std::string ksid = GetKsidFromHttp004KMSQuery(requestUri);
2098 
2099  nlohmann::json jGetKeyResponse;
2100  if(!payload.empty()){
2101  try{
2102  jGetKeyResponse = nlohmann::json::parse(payload);
2103  }catch (...){
2104  NS_FATAL_ERROR( this << "JSON parse error!");
2105  }
2106  }
2107 
2108  HTTPMessage::HttpStatus responseStatus = header.GetStatus();
2109  if(
2110  responseStatus == HTTPMessage::HttpStatus::BadRequest ||
2111  responseStatus == HTTPMessage::HttpStatus::Unauthorized ||
2112  responseStatus == HTTPMessage::HttpStatus::ServiceUnavailable
2113  ){
2114  //Process status field of response (ETSI004 defined: 2, 3, 8) @toDo
2115  //uint32_t status004 = jGetKeyResponse["status"];
2116  NS_LOG_FUNCTION( this << "QKDApp received ERROR on GET_KEY" );
2118  Time t {"300ms"};
2119  EventId event = Simulator::Schedule (t, &QKDApp004::GetKeyFromKMS, this, ksid, 0);
2120  }else if(m_master){
2121  Time t {"500ms"};
2122  EventId event = Simulator::Schedule (t, &QKDApp004::GetKeyFromKMS, this, ksid, 0);
2123  }else if(!m_master){
2124  NS_LOG_FUNCTION(this << "Association has been closed ...");
2125  }
2126 
2127  }else if(responseStatus == HTTPMessage::HttpStatus::Ok){ //For ETSI004 status 0
2128  uint32_t index = -1;
2129  std::string key;
2130  if (jGetKeyResponse.contains("index"))
2131  index = jGetKeyResponse["index"];
2132  if (jGetKeyResponse.contains("Key_buffer"))
2133  key = jGetKeyResponse["Key_buffer"];
2134  NS_ASSERT(index >= 0);
2135  NS_ASSERT(!key.empty());
2136 
2137  m_obtainedKeyMaterialTrace (key.size()*8);
2138 
2139  NS_LOG_FUNCTION( this << "Key obtained (master,ksid,index,key)" << m_master << ksid << index << key);
2140  QKDAppKey appKey;
2141  appKey.key = key;
2142  appKey.index = index;
2143  appKey.lifetime = m_aesLifetime;
2144 
2145  if(m_associations.first.ksid == ksid)
2146  m_associations.first.buffer.insert( std::make_pair(index, appKey) );
2147  else if(m_associations.second.ksid == ksid)
2148  m_associations.second.buffer.insert( std::make_pair(index, appKey) );
2149  else
2150  NS_FATAL_ERROR( this << "Association with ksid" << ksid << "does not exist on QKDApp" );
2151 
2153  CheckQueues();
2154  else if(m_appState == WAIT){ //If Auth key and Enc key are ready then go to READY state!
2155  bool ready = true;
2156  if(GetEncryptionKeySize() != 0 && m_associations.first.buffer.empty())
2157  ready = false;
2158  if(GetAuthenticationKeySize() != 0 && m_associations.second.buffer.empty())
2159  ready = false;
2160  if(ready)
2162  }
2163 
2164  }else{
2165  NS_FATAL_ERROR( this << "Unsupported status code" << responseStatus << " of the response.");
2166  }
2167 }
2168 
2169 void
2171 {
2172  NS_LOG_FUNCTION( this << "Processing response on CLOSE method ..." );
2173 
2174  std::string requestUri = header.GetRequestUri();
2175  std::string ksid = GetKsidFromHttp004KMSQuery(requestUri);
2176 
2177  if(m_httpRequestsKMS.empty()){ //Sockets are closed when both CLOSE responses are received!
2180  }
2181 
2182  //Application does not really need to process CLOSE response!
2183  HTTPMessage::HttpStatus responseStatus = header.GetStatus();
2184  if(
2185  responseStatus == HTTPMessage::HttpStatus::BadRequest ||
2186  responseStatus == HTTPMessage::HttpStatus::Unauthorized ||
2187  responseStatus == HTTPMessage::HttpStatus::ServiceUnavailable
2188  ){
2189  NS_LOG_FUNCTION( this << "QKDApp received error message on CLOSE method" );
2191 
2192  }else if(responseStatus == HTTPMessage::HttpStatus::Ok){
2193  NS_LOG_FUNCTION( this << "Application successfully closed association " << ksid );
2194  InitializeAssociations(); //Associations are initialized once again!
2195 
2196  }else{
2197  NS_FATAL_ERROR( this << "Unsupported error status code" << responseStatus << "of response.");
2198  }
2199 
2200 }
2201 
2202 void
2204 {
2205  NS_LOG_FUNCTION( this << "Processing singnaling packet received from peer QKDApp" );
2206 
2207  std::string payload = header.GetMessageBodyString();
2208 
2209  if(m_master){ //Primary QKDApp processes received signaling packet from Replica QKDApp
2210  uint32_t methodType = GetMethodFromHttp004AppQuery(); //Send_ksid or Create_queues
2211  if(methodType == 0){
2212  NS_LOG_FUNCTION( this << "SEND_KSID: Primary QKDApp received response from Replica QKDApp." );
2213  std::string ksid = GetKsidFromHttp004AppQuery();
2214  ProcessSendKsidResponse(header, ksid);
2215  }else if (methodType == 1){
2216  NS_LOG_FUNCTION( this << "ESTABLISH_QUEUES: Primary QKDApp received response from Replica QKDApp. Packet ID" );
2218  }
2220 
2221  }else{ //Replica QKDApp processes received signaling packet from Primary QKDApp.
2222 
2223  std::string s = header.GetUri();
2224  std::string delimiter = "/";
2225  size_t pos = 0;
2226  std::string token;
2227 
2228  std::vector<std::string> uriParams;
2229  while((pos = s.find(delimiter)) != std::string::npos){
2230  token = s.substr(0, pos);
2231  if(token.length() > 0){
2232  uriParams.push_back(token);
2233  }
2234  s.erase(0, pos + delimiter.length());
2235  }
2236  if(s.length() > 0){
2237  uriParams.push_back(s);
2238  }
2239 
2240  std::string requestType;
2241  if(
2242  uriParams.size() > 3 &&
2243  uriParams[1] == "api" &&
2244  uriParams[2] == "v1"
2245  ){
2246  requestType = uriParams[4];
2247  }
2248 
2249  NS_LOG_FUNCTION(this << requestType << s);
2250 
2251  if(requestType == "connect"){ //This is SEND_KSID message
2252 
2253  NS_LOG_FUNCTION( this << "Processing send_ksid request!" );
2254  std::string ksid = uriParams[5];
2255  NS_ASSERT(!ksid.empty());
2256  std::string cryptoT = uriParams[6];
2257  NS_ASSERT(!cryptoT.empty());
2258 
2259  if(cryptoT == "0")
2260  m_associations.first.ksid = ksid; //Register KSID for encryption
2261  else if(cryptoT == "1")
2262  m_associations.second.ksid = ksid; //Register KSID for autentication
2263  else
2264  NS_FATAL_ERROR( this << "Invalid purpose of the association!" );
2265 
2266  NS_LOG_FUNCTION(this << cryptoT << ksid);
2267 
2269  OpenConnect(ksid); //Send OpenConnect to local KMS!
2270 
2271  }else if(requestType == "establish_queues") { //process establish_queues notification
2272  NS_LOG_FUNCTION( this << "Processing establish_queues request!" );
2274  CheckQueues();
2275 
2276  } else {
2277  NS_FATAL_ERROR( this << "Invalid method received on app. RequestType:" << requestType << s );
2278  }
2279 
2280  }
2281 
2282 }
2283 
2292 void
2293 QKDApp004::SendKsidRequest (std::string ksid, uint32_t keyType)
2294 {
2295  NS_LOG_FUNCTION( this << ksid << keyType << this->GetId().string() ); //keyType is enc/auth identifier
2300 
2301  NS_ASSERT(m_master); //Only primary QKDApp calls SendKsid
2302 
2304  std::stringstream ss;
2305  m_peerAddress.Print(ss);
2306  std::string headerUri = "http://" + ss.str();
2307 
2308  NS_LOG_FUNCTION(this << m_peer << headerUri << m_peerAddress << headerUri.size());
2309 
2310  headerUri += "/api/v1/" + this->GetId().string() + "/connect/" + ksid + "/" + std::to_string(keyType);
2311  NS_LOG_FUNCTION(this << headerUri);
2312 
2313  //Create packet
2314  HTTPMessage httpMessage;
2315  httpMessage.CreateRequest(headerUri, "GET");
2316  std::string hMessage = httpMessage.ToString();
2317  Ptr<Packet> packet = Create<Packet> (
2318  (uint8_t*) (hMessage).c_str(),
2319  hMessage.size()
2320  );
2321  NS_ASSERT (packet);
2322 
2323  Http004AppQuery(0, ksid); //0-SendKSID method
2324 
2325  m_txSigTrace (packet);
2326  m_sendSignalingSocketApp->Send(packet);
2327  m_packetsSent++;
2328  m_dataSent += packet->GetSize();
2329  NS_LOG_FUNCTION( this << "SEND_KSID: Primary QKDApp sends KSID to Replica QKDApp" <<
2330  headerUri << ". Packet ID" << packet->GetUid() );
2331 }
2332 
2333 void
2335 {
2336  NS_LOG_FUNCTION( this << "Sending response on SEND_KSID to Primary QKDApp" << httpStatus << msg );
2341  NS_ASSERT(!m_master);
2342 
2343  //create packet
2344  HTTPMessage httpMessage;
2345  if(!msg.empty()){
2346  httpMessage.CreateResponse(httpStatus, msg, {
2347  {"Content-Type", "application/json; charset=utf-8"}
2348  });
2349  }else{
2350  httpMessage.CreateResponse(httpStatus);
2351  }
2352 
2353  std::string hMessage = httpMessage.ToString();
2354  Ptr<Packet> packet = Create<Packet> (
2355  (uint8_t*) (hMessage).c_str(),
2356  hMessage.size()
2357  );
2358  NS_ASSERT (packet);
2359 
2360  m_txSigTrace (packet);
2361  m_sendSignalingSocketApp->Send(packet);
2362  m_packetsSent++;
2363  m_dataSent += packet->GetSize();
2364 
2365  NS_LOG_FUNCTION( this << "SEND_KSID: Replica QKDApp sends respose to Primary QKDApp. Packet ID"
2366  << packet->GetUid() << packet->GetSize() );
2367 }
2368 
2369 void
2371 {
2372  NS_LOG_FUNCTION( this << "Processing /connect response (send_ksid)" );
2373  NS_ASSERT(m_master); //Only on Primary QKDApp can receive response on /connect
2374  if(header.GetStatus() == HTTPMessage::HttpStatus::Ok){
2375  if(m_associations.first.ksid == ksid)
2376  m_associations.first.verified = true; //Acknowledge peer application registered for ksid
2377  else if(m_associations.second.ksid == ksid)
2378  m_associations.second.verified = true; //Acknowledge peer application registered for ksid
2379  else
2380  NS_FATAL_ERROR( this );
2381  NS_LOG_FUNCTION( this << "Association successfully established between QKDApps " << ksid );
2382  CheckAssociationsState(); //Check if the QKDApp is ready to leave ESTABLISHING_ASSOCIATIONS state!
2383 
2384  }else{
2385  NS_LOG_FUNCTION( this << "/connect failed! " << ksid );
2386  Close(ksid); //Close established association
2387  }
2388 }
2389 
2390 void
2392 {
2393  NS_LOG_FUNCTION( this << "Primary QKDApp sending establish_queues notification to Replica QKDApp" );
2394  NS_ASSERT(m_master); //Only Primary QKDApp function
2395 
2397  std::stringstream ss;
2398  m_peerAddress.Print(ss);
2399  std::string headerUri = "http://" + ss.str();
2400  headerUri += "/api/v1/" + this->GetId().string() + "/establish_queues";
2401 
2402  //Create packet
2403  HTTPMessage httpMessage;
2404  httpMessage.CreateRequest(headerUri, "GET"); //GET for a notification message?
2405  std::string hMessage = httpMessage.ToString();
2406  Ptr<Packet> packet = Create<Packet> (
2407  (uint8_t*) (hMessage).c_str(),
2408  hMessage.size()
2409  );
2410  NS_ASSERT (packet);
2411 
2412  Http004AppQuery(1, ""); //1 - establish_queues method!
2413 
2414  m_txSigTrace (packet);
2415  m_sendSignalingSocketApp->Send(packet);
2416  m_packetsSent++;
2417  m_dataSent += packet->GetSize();
2418 
2419  NS_LOG_FUNCTION(this << "Packet ID:" << packet->GetUid() << "Packet size:" << packet->GetSize() );
2420 
2421 }
2422 
2423 void
2425 {
2426  NS_LOG_FUNCTION( this << "Replica QKDApp sending response on /fill indicating success" );
2427  NS_ASSERT(!m_master); //Only Replica QKDApp function
2428 
2429  //create packet
2430  HTTPMessage httpMessage;
2431  httpMessage.CreateResponse(HTTPMessage::HttpStatus::Ok);
2432  std::string hMessage = httpMessage.ToString();
2433  Ptr<Packet> packet = Create<Packet> (
2434  (uint8_t*) (hMessage).c_str(),
2435  hMessage.size()
2436  );
2437  NS_ASSERT (packet);
2438 
2439  m_txSigTrace (packet);
2440  m_sendSignalingSocketApp->Send(packet);
2441  m_packetsSent++;
2442  m_dataSent += packet->GetSize();
2443 
2444  NS_LOG_FUNCTION(this << "Packet ID" << packet->GetUid() << "Packet size" << packet->GetSize() );
2445 
2446 }
2447 
2448 void
2450 {
2451  NS_LOG_FUNCTION( this );
2452 
2454 
2458  }
2459 
2460 }
2461 
2462 void
2464 {
2465 
2466  NS_LOG_FUNCTION( this << "Establishing associations" );
2467  if(GetEncryptionKeySize() != 0 && m_associations.first.ksid == "")
2468  OpenConnect("", 0); //Establish association for a set of future encryption (0) keys
2469  if (GetAuthenticationKeySize() != 0 && m_associations.second.ksid == "")
2470  OpenConnect("", 1); //Establish association for a set of future authentication (1) keys
2471 }
2472 
2473 void
2475 {
2476  NS_LOG_FUNCTION( this << "Clearing key stream association on QKDApp" << ksid );
2477  if(m_associations.first.ksid == ksid){ //Clear association created for encryption
2478  m_associations.first.ksid.clear(); //Clear ksid
2479  m_associations.first.verified = false;
2480  m_associations.first.keyActive = 0;
2481  m_associations.first.buffer.clear(); //Clear any keys in buffer!
2482  }else if(m_associations.second.ksid == ksid){ //Clear association created for authentication
2483  m_associations.second.ksid.clear(); //Clear ksid
2484  m_associations.second.verified = false;
2485  m_associations.second.keyActive = 0;
2486  m_associations.second.buffer.clear(); //Clear any keys in buffer!
2487  }
2488  NS_LOG_FUNCTION( this << "Key stream association " << ksid << " cleared!" );
2489 }
2490 
2491 void
2493 {
2494  NS_LOG_FUNCTION (this << oldRtt << newRtt);
2495 }
2496 
2497 
2506 void
2508 {
2509 
2510  NS_LOG_FUNCTION( this << m_master );
2511  if(m_master){ //Transitions for Primary QKDApp
2512  if(m_appState == INITIALIZED){
2513  if (GetEncryptionKeySize() == 0 && GetAuthenticationKeySize() == 0){ //QKD key material not needed!
2516  SendPacket(); //Immediately sends unprotected packets
2517  }else{ //Establish associations for a set of future QKD keys
2520  CreateKeyStreamAssociations(); //Call OPEN_CONNECT
2521  }
2522  }else if(m_appState == ASSOCIATIONS_ESTABLISHED){
2524  CreateKeyQueues();
2525  CheckQueues();
2526  }else if(m_appState == KEY_QUEUES_ESTABLISHED){
2528  SendPacket(); //Start sending packets!
2529  }else{
2530  NS_FATAL_ERROR( this << "Invalid entry state" << m_appState <<
2531  "for AppTransitionTree()!" );
2532  }
2533 
2534  }else if(!m_master){ //Data transmision state transition for Replica QKDApp
2535  if(m_appState == INITIALIZED){
2537  }else if(m_appState == KEY_QUEUES_ESTABLISHED){
2538  if (m_associations.first.verified)
2539  m_associations.first.keyActive = m_associations.first.buffer.begin()->first;
2540  if (m_associations.second.verified)
2541  m_associations.second.keyActive = m_associations.second.buffer.begin()->first;
2544  }else{
2545  NS_FATAL_ERROR( this << "Invalid entry state" << m_appState <<
2546  "for AppTransitionTree()!" );
2547  }
2548 
2549  }
2550 
2551 }
2552 
2553 
2556 {
2557  return m_appState;
2558 }
2559 
2560 std::string
2562 {
2563  switch (state)
2564  {
2565  case NOT_STARTED:
2566  return "NOT_STARTED";
2567  break;
2568  case INITIALIZED:
2569  return "INITIALIZED";
2570  break;
2572  return "ESTABLISHING_ASSOCIATIONS";
2573  break;
2575  return "ASSOCIATIONS_ESTABLISHED";
2576  break;
2578  return "ESTABLISHING_KEY_QUEUES";
2579  break;
2581  return "KEY_QUEUES_ESTABLISHED";
2582  break;
2583  case READY:
2584  return "READY";
2585  break;
2586  case WAIT:
2587  return "WAIT";
2588  break;
2589  case SEND_DATA:
2590  return "SEND_DATA";
2591  break;
2592  case DECRYPT_DATA:
2593  return "DECRYPT_DATA";
2594  break;
2595  case STOPPED:
2596  return "STOPPED";
2597  break;
2598  default:
2599  NS_FATAL_ERROR ("Unknown state");
2600  return "FATAL_ERROR";
2601  break;
2602  }
2603 }
2604 
2605 
2606 std::string
2608 {
2609  return GetAppStateString (m_appState);
2610 }
2611 
2612 void
2614 {
2615 
2616  const std::string oldState = GetAppStateString ();
2617  const std::string newState = GetAppStateString (state);
2618 
2619  //Check transition matrix! @toDo
2620  if (oldState == "SEND_DATA" && newState == "READY") {
2621  if ( (m_associations.first.ksid != "" && m_associations.first.buffer.empty()) ||
2622  (m_associations.second.ksid != "" && m_associations.second.buffer.empty())
2623  )
2624  state = QKDApp004::QKDAppState::WAIT; //Queues are empty. Go to state WAIT!
2625  }
2626 
2627  m_appState = state;
2628  NS_LOG_FUNCTION( this << "QKDApp" << oldState << "-->" << GetAppStateString (state) );
2629  //m_appStateTransitionTrace(oldState, newState);
2630 
2631 }
2632 
2641 void
2643  uint32_t encryptionType,
2644  uint32_t authenticationType,
2645  uint32_t authenticationTagLengthInBits
2646 ){
2647 
2648  NS_LOG_FUNCTION (this << encryptionType << authenticationType << authenticationTagLengthInBits);
2649 
2650  switch (encryptionType){
2651  case 0:
2653  break;
2654  case 1:
2656  break;
2657  case 2:
2659  break;
2660  }
2661 
2662  switch (authenticationType){
2663  case 0:
2665  break;
2666  case 1:
2668  break;
2669  case 2:
2671  break;
2672  case 3:
2674  break;
2675  }
2676 
2677  if(!m_encryptor){
2678  m_encryptor = CreateObject<QKDEncryptor> (
2681  authenticationTagLengthInBits
2682  );
2683  }else{
2684  m_encryptor->ChangeSettings(
2687  authenticationTagLengthInBits
2688  );
2689  }
2690 
2691 }
2692 
2693 std::string
2694 QKDApp004::GetPacketContent(uint32_t msgLength)
2695 {
2696  NS_LOG_FUNCTION(this);
2697 
2698  if (msgLength == 0)
2699  msgLength = m_packetSize;
2700 
2701  //Generate random string with same size as merged key string
2702  std::string confidentialMessage;
2703  static const char alphanum[] =
2704  "0123456789"
2705  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
2706  "abcdefghijklmnopqrstuvwxyz";
2707 
2708  uint32_t randVal = 0;
2709  for (uint32_t i = 0; i < msgLength; ++i){
2710  randVal = round(m_random->GetValue (0, sizeof(alphanum) - 1));
2711  confidentialMessage += alphanum[ randVal ];
2712  }
2713 
2714  return confidentialMessage;
2715 
2716 }
2717 
2718 uint32_t
2720 {
2721  switch(m_encryptionType){
2723  return 0;
2724  break;
2726  return m_packetSize * 8;
2727  break;
2729  return CryptoPP::AES::MAX_KEYLENGTH * 8; //In bits 256! Quantum resistant!
2730  break;
2731  }
2732  return 0;
2733 }
2734 
2735 uint64_t
2737 {
2738  uint32_t rate = 0;
2739  switch(m_encryptionType){
2741 
2742  NS_LOG_FUNCTION(this << "UNENCRYPTED");
2743  return 0;
2744  break;
2745 
2747 
2748  NS_LOG_FUNCTION(this << "OTP:" << m_dataRate.GetBitRate());
2749  return m_dataRate.GetBitRate();
2750  break;
2751 
2753 
2754  //In bits 256! Quantum resistant!
2756  rate = CryptoPP::AES::MAX_KEYLENGTH * 8;
2757  }else{
2758  rate = round (
2759  (m_dataRate.GetBitRate()/m_aesLifetime) * CryptoPP::AES::MAX_KEYLENGTH * 8
2760  );
2761  }
2762  NS_LOG_FUNCTION(this << "AES:" << rate << m_dataRate.GetBitRate() << m_aesLifetime << CryptoPP::AES::MAX_KEYLENGTH * 8);
2763  return rate;
2764  break;
2765 
2766  }
2767  return rate;
2768 }
2769 
2770 uint32_t
2772 {
2773  uint32_t rate = 0;
2774  switch (m_authenticationType){
2776 
2777  NS_LOG_FUNCTION(this << "UNENCRYPTED");
2778  return 0;
2779  break;
2780 
2782 
2783  rate = CryptoPP::AES::DEFAULT_KEYLENGTH * 8; //Use with AES. In bits 128 bits!
2784  NS_LOG_FUNCTION(this << "QKDCRYPTO_AUTH_VMAC: " << rate);
2785  return rate;
2786  break;
2787 
2789 
2790  NS_LOG_FUNCTION(this << "QKDCRYPTO_AUTH_MD5");
2791  return 0; //NoKey
2792  break;
2793 
2795 
2796  NS_LOG_FUNCTION(this << "QKDCRYPTO_AUTH_SHA1");
2797  return 0; //NoKey
2798  break;
2799 
2800  }
2801  return rate;
2802 }
2803 
2804 uint64_t
2806 {
2809 
2810  uint32_t rate = 0;
2811  switch (m_authenticationType){
2813  return 0;
2814  break;
2816 
2817  //Use with AES. In bits 128 bits!
2818  if(m_aesLifetime){
2819 
2821  rate = CryptoPP::AES::DEFAULT_KEYLENGTH * 8;
2822  }else{
2823  rate = round (
2824  (m_dataRate.GetBitRate()/m_aesLifetime) * CryptoPP::AES::DEFAULT_KEYLENGTH * 8
2825  );
2826  }
2827  return rate;
2828 
2829  }else{
2830 
2832  rate = CryptoPP::AES::DEFAULT_KEYLENGTH * 8;
2833  }else{
2834  rate = round (
2835  (m_dataRate.GetBitRate()/m_packetSize) * CryptoPP::AES::DEFAULT_KEYLENGTH * 8
2836  );
2837  }
2838  return rate;
2839 
2840  }
2841  break;
2843  return 0; //NoKey
2844  break;
2846  return 0; //NoKey
2847  break;
2848  }
2849  return 0;
2850 }
2851 
2852 
2853 std::string
2855 {
2856  NS_LOG_FUNCTION( this );
2857 
2858  uint8_t *buffer = new uint8_t[packet->GetSize ()];
2859  packet->CopyData(buffer, packet->GetSize ());
2860  std::string payload = std::string((char*)buffer, packet->GetSize());
2861  delete[] buffer;
2862 
2863  return payload;
2864 }
2865 
2866 
2867 
2868 } // Namespace ns3
a polymophic address class
Definition: address.h:101
The base class for all ns3 applications.
Definition: application.h:62
Ptr< Node > GetNode() const
Definition: application.cc:108
Class for representing data rates.
Definition: data-rate.h:89
uint64_t GetBitRate() const
Get the underlying bitrate.
Definition: data-rate.cc:305
An identifier for simulation events.
Definition: event-id.h:55
bool IsRunning() const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:76
The basic class to represent both HTTP requests and responses.
Definition: http.h:78
std::string GetRequestUri() const
Definition: http.h:431
std::string ToString()
Takes the headers added to the message along with the body and outputs it to a std::string for use in...
Definition: http.h:633
uint32_t GetSize()
Definition: http.h:686
std::string GetUri() const
Grab the uri.
Definition: http.h:519
void CreateRequest(const std::string &url, const std::string &method)
Definition: http.h:738
bool IsFragmented()
Definition: http.h:852
std::string GetMessageBodyString()
Definition: http.h:714
size_t GetContentLength()
Return the size of the binary body vector.
Definition: http.h:724
void CreateResponse(const HttpStatus status)
Definition: http.h:785
HTTPMessage::HttpStatus GetStatus()
To be returned with a status code in a response is a status text describing the status code by text r...
Definition: http.h:169
uint32_t GetHeadersSize()
Definition: http.h:681
std::string GetStatusMessage() const
Get the current status message for this message.
Definition: http.h:623
A basic class to parse a HTTP message, both request and response.
Definition: http.h:941
an Inet address class
static bool IsMatchingType(const Address &address)
Ipv4Address GetIpv4() const
static InetSocketAddress ConvertFrom(const Address &address)
Returns an InetSocketAddress which corresponds to the input Address.
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:42
void Print(std::ostream &os) const
Print this address to the given output stream.
static Ipv4Address GetAny()
bool TraceConnectWithoutContext(std::string name, const CallbackBase &cb)
Connect a TraceSource to a Callback without a context.
Definition: object-base.cc:315
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:294
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:354
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:268
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:861
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:400
void RemoveAtStart(uint32_t size)
Remove size bytes from the start of the current packet.
Definition: packet.cc:384
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:305
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Create a new packet which contains a fragment of the original packet.
Definition: packet.cc:238
uint64_t GetUid() const
Returns the packet's Uid.
Definition: packet.cc:412
std::string ToString() const
Return a string representation of the packet.
Definition: packet.cc:448
Establish secure communication on application lavel to use the key and test LKSM.
Definition: qkd-app-004.h:72
void ProcessDataPacketFromApp(QKDAppHeader header, Ptr< Packet > packet, Ptr< Socket > socket)
Process data packets from the peer QKD application.
void HandlePeerErrorFromKMS(Ptr< Socket > socket)
Handle a connection error from the KMS.
Definition: qkd-app-004.cc:614
Ptr< Socket > m_sinkSignalingSocketApp
The receiving socket for the signaling messages.
Definition: qkd-app-004.h:790
virtual void StopApplication(void)
Application specific shutdown code.
void HandlePeerCloseFromApp(Ptr< Socket > socket)
Handle a connection close from the peer QKD application.
Definition: qkd-app-004.cc:654
double m_delay
The time interval between two successive data transmissions (calculated based on the application data...
Definition: qkd-app-004.h:808
TracedCallback< Ptr< const Packet > > m_rxSigTrace
A trace for received signaling packets.
Definition: qkd-app-004.h:556
void HandleReadFromApp(Ptr< Socket > socket)
Handle a packet received from the peer QKD application.
Definition: qkd-app-004.cc:840
UUID m_dstSaeId
The peer application identifier.
Definition: qkd-app-004.h:835
TracedCallback< Ptr< Packet >, std::string > m_deauthenticationTrace
A trace callback for the authentication check event.
Definition: qkd-app-004.h:848
void CancelScheduledAction(uint32_t eventId)
Cancel the scheduled event.
Definition: qkd-app-004.cc:308
void ConnectionToKMSSucceeded(Ptr< Socket > socket)
Callback function after the connection to the KMS is complete.
Definition: qkd-app-004.cc:572
std::string GetAppStateString() const
Get the current state of the application in a string notation.
QKDAppState m_appState
The application state.
Definition: qkd-app-004.h:857
QKDAppKey GetAuthKey()
Get the authentication key from the queue.
void Http004AppQueryComplete(void)
Remove the request from the vector of HTTP requests made to the peer QKD application.
DataRate m_dataRate
The application data rate.
Definition: qkd-app-004.h:810
QKDApp004()
Constructor.
Definition: qkd-app-004.cc:180
void ConnectionToKMSFailed(Ptr< Socket > socket)
Callback function after the connection to the KMS has failed.
Definition: qkd-app-004.cc:578
void HandleAcceptFromKMS(Ptr< Socket > s, const Address &from)
Handle an incoming connection from the KMS.
Definition: qkd-app-004.cc:535
uint32_t m_useCrypto
Execute actual cryptographic algorithms?
Definition: qkd-app-004.h:840
void SendPacket(void)
Send the application packet (includes the generation of a random message and optional encryption or/a...
void OpenConnect(std::string ksid, uint32_t keyType=0)
Request a key stream session (an association) from the local KMS.
uint32_t GetMethodFromHttp004AppQuery(void)
Map the HTTP response from the peer QKD application and obtain the ETSI method type.
void PrepareSinkSocketFromKMS()
Prepare the sink socket to listen from the KMS Application.
Definition: qkd-app-004.cc:330
void RegisterAckTime(Time oldRtt, Time newRtt)
Register the acknowledgement time.
Address m_localSignaling
The local address for the signaling data transmission.
Definition: qkd-app-004.h:801
void SendMaliciousRequestToKMS()
Send a malicious request to the KMS.
static TypeId GetTypeId(void)
Get the type ID.
Definition: qkd-app-004.cc:44
uint32_t m_keyBufferLengthEncryption
The size of the encryption key queue at the application layer.
Definition: qkd-app-004.h:854
void ProcessSignalingPacketFromApp(HTTPMessage &header, Ptr< Socket > socket)
Process a signaling packets from the peer QKD application.
Time m_dosAttackIntensity
The intensity of the DoS attack.
Definition: qkd-app-004.h:824
QKDAppState
The QKD application states.
Definition: qkd-app-004.h:109
@ ESTABLISHING_ASSOCIATIONS
Definition: qkd-app-004.h:112
@ ASSOCIATIONS_ESTABLISHED
Definition: qkd-app-004.h:113
void ProcessOpenConnectResponse(HTTPMessage &header)
Process the OPEN_CONNECT response.
void ProcessGetKeyResponse(HTTPMessage &header)
Process the GET_KEY response.
TracedCallback< Ptr< Packet >, std::string > m_authenticationTrace
A trace callback for the authentication event.
Definition: qkd-app-004.h:847
UUID m_id
The application identifier.
Definition: qkd-app-004.h:834
uint32_t m_keyBufferLengthAuthentication
The size of the authentication key queue at the application layer.
Definition: qkd-app-004.h:855
uint32_t m_packetsSent
The number of sent data packets.
Definition: qkd-app-004.h:817
std::map< uint32_t, EventId > m_scheduledEvents
The map of scheduled events.
Definition: qkd-app-004.h:865
TracedCallback< Ptr< Packet > > m_encryptionTrace
A trace callback for the encryption event.
Definition: qkd-app-004.h:845
Address m_peer
The address of the peer for the data transmission.
Definition: qkd-app-004.h:797
void Http004KMSQueryComplete(std::string uri)
Remove the request from the vector of HTTP requests made to the KMS.
void GetKeyFromKMS(std::string ksid, uint32_t index=0)
Get key for the key stream.
ns3::TracedCallback< const std::string &, const std::string & > m_stateTransitionTrace
A trace for the application state transitions.
Definition: qkd-app-004.h:558
uint32_t GetKeyTypeFromHttp004KMSQuery(std::string uri)
Map the HTTP reponse from the KMS and obtain the key type.
std::string m_socketType
The sockets type.
Definition: qkd-app-004.h:805
std::unordered_map< Address, Ptr< Packet >, AddressHash > m_buffer_qkdapp
The buffer for received data packets (fragmentation).
Definition: qkd-app-004.h:863
uint32_t m_packetSize
The data packet size.
Definition: qkd-app-004.h:807
void DataToKMSSend(Ptr< Socket >, uint32_t)
Callback function to notify that data to KMS has been sent.
TracedCallback< Ptr< const Packet > > m_txSigTrace
A trace for transmitted signaling packets.
Definition: qkd-app-004.h:553
void PrepareSinkSocketFromApp()
Prepare the sink socket to listen from the peer QKD Application.
Definition: qkd-app-004.cc:452
void HandleAcceptSignalingFromApp(Ptr< Socket > s, const Address &from)
Handle a signaling incoming connection from the peer QKD application.
Definition: qkd-app-004.cc:560
uint32_t m_aesLifetime
The AES key lifetime.
Definition: qkd-app-004.h:844
void ClearAssociation(std::string ksid)
Delete all records of key stream session identified with a given KSID.
bool m_primaryQueueEstablished
Is the queue established at the sender application?
Definition: qkd-app-004.h:606
void ProcessSendKsidResponse(HTTPMessage &header, std::string ksid)
Process the SEND_KSID response.
virtual ~QKDApp004()
Destructor.
Definition: qkd-app-004.cc:201
Ptr< UniformRandomVariable > m_random
The uniform random variable.
Definition: qkd-app-004.h:609
void HandleReadSignalingFromApp(Ptr< Socket > socket)
Handle a signaling packet received from the peer QKD application.
Definition: qkd-app-004.cc:927
virtual void StartApplication(void)
EventId m_closeSocketEvent
The closing socket event.
Definition: qkd-app-004.h:814
TracedCallback< const uint32_t & > m_obtainedKeyMaterialTrace
A trace callback for the obtained key material.
Definition: qkd-app-004.h:850
void ProcessCreateQueuesResponse()
Start establishing key queues at the reciving application once requested by the sender.
std::string GetKsidFromHttp004AppQuery(void)
Map the HTTP response from the peer QKD application and obtain the key stream identifier.
Ptr< Socket > m_sendDataSocketApp
The sending socket for the data.
Definition: qkd-app-004.h:791
void HandleAcceptFromApp(Ptr< Socket > s, const Address &from)
Handle an incoming connection from the peer QKD application.
Definition: qkd-app-004.cc:548
uint32_t GetMethodFromHttp004KMSQuery(std::string uri)
Read the ETSI request method from the URI.
Address m_peerSignaling
The address of the peer for the signaling data transmission.
Definition: qkd-app-004.h:798
QKDEncryptor::EncryptionType m_encryptionType
The encryption algorithm.
Definition: qkd-app-004.h:851
Ptr< Packet > m_maliciousPacket
The malicious packet.
Definition: qkd-app-004.h:823
uint32_t GetEncryptionKeySize()
Get the required key size for the choosen encryption algorithm.
void ConnectionSignalingToAppFailed(Ptr< Socket > socket)
Callback function after the signaling connection to the APP has failed.
Definition: qkd-app-004.cc:602
Address m_kms
The local KMS address.
Definition: qkd-app-004.h:803
EventId m_sendEvent
The data transmission event.
Definition: qkd-app-004.h:813
void Close(std::string ksid)
Close the keys stream session (the association).
void HandlePeerErrorSignalingFromApp(Ptr< Socket > socket)
Handle a signaling connection error from the peer QKD application.
Definition: qkd-app-004.cc:671
Ptr< Socket > m_sinkSocketFromKMS
The receiving socket from the KMS.
Definition: qkd-app-004.h:795
void InitializeAssociations()
Initialize the key stream sessions.
uint32_t m_ttl
The time-to-live of the key stream session.
Definition: qkd-app-004.h:828
void ProcessPacketsToKMSFromQueue()
Process and send any remaining packets to the KMS.
Definition: qkd-app-004.cc:730
void CloseSocketToKms()
Close the connecting sockets with the KMS.
Definition: qkd-app-004.cc:720
uint32_t GetAuthenticationKeySize()
Get the required key size for the choosen authentication algorithm.
std::pair< Association004, Association004 > m_associations
A pair (encryption/authentication) of the establihed key stream session.
Definition: qkd-app-004.h:604
bool ConnectionRequestedFromKMS(Ptr< Socket > socket, const Address &address)
Callback function after the connection for response from the KMS has been received.
Definition: qkd-app-004.cc:523
uint32_t m_dataSent
The amount of the sent data.
Definition: qkd-app-004.h:818
void PrepareSendSocketToKMS()
Prepare the send socket to communicate with the KMS Application.
Definition: qkd-app-004.cc:368
uint64_t GetMaxEncryptionKeyRate()
Get the maximum key rate required for the encryption (QoS settings).
void ProcessCloseResponse(HTTPMessage &header)
Process the CLOSE response.
void PacketReceivedFromKMS(const Ptr< Packet > &p, const Address &from, Ptr< Socket > socket)
Check for the tcp segmentation of packets received from the KMS.
Definition: qkd-app-004.cc:759
std::string GetPacketContent(uint32_t msgLength=0)
Generate a random packet payload (the message).
bool m_replicaQueueEstablished
Is the queue established at the receiver application?
Definition: qkd-app-004.h:607
TracedCallback< Ptr< const Packet > > m_rxKmsTrace
A trace for received packets from the KMS.
Definition: qkd-app-004.h:557
void Http004KMSQuery(std::string uri, std::string ksid, uint32_t keyType)
Memories the HTTP request made to the local KMS.
void ConnectionSignalingToAppSucceeded(Ptr< Socket > socket)
Callback function after the signaling connection to the APP is complete.
Definition: qkd-app-004.cc:596
void ConnectionToAppSucceeded(Ptr< Socket > socket)
Callback function after the connection to the APP is complete.
Definition: qkd-app-004.cc:584
Time m_holdTime
The holding time before closing sockets.
Definition: qkd-app-004.h:815
std::map< std::string, std::pair< std::string, uint32_t > > m_httpRequestsKMS
A vector of HTTP requests set to the KMS.
Definition: qkd-app-004.h:832
std::vector< std::pair< uint32_t, std::string > > m_httpRequestsApp
A vector of HTTP requests sent to the peer application.
Definition: qkd-app-004.h:831
Ptr< Socket > m_sendSocketToKMS
The sending socket to the KMS.
Definition: qkd-app-004.h:794
TracedCallback< Ptr< const Packet > > m_txKmsTrace
A trace for transmitted packets to the KMS.
Definition: qkd-app-004.h:554
TracedCallback< Ptr< const Packet >, std::string > m_mxTrace
A trace for the missed time slots to send data (due to the lack of keys).
Definition: qkd-app-004.h:559
TypeId m_tid
The type identifier.
Definition: qkd-app-004.h:819
void SignalingPacketReceivedFromApp(const Ptr< Packet > &p, const Address &from, Ptr< Socket > socket)
Check for the tcp segmentation of the signaling packets received from the peer application.
Definition: qkd-app-004.cc:959
QKDAppState GetAppState() const
Get the current state of the application.
void HandlePeerErrorFromApp(Ptr< Socket > socket)
Handle a connection error from the peer QKD application.
Definition: qkd-app-004.cc:659
uint64_t GetMaxAuthenticationKeyRate()
Get the maximum key rate required for the authentication (QoS settings).
QKDEncryptor::AuthenticationType m_authenticationType
The authentication algorithm.
Definition: qkd-app-004.h:852
void CreateKeyQueuesResponse()
Once the receiving application establishes the queues, it sends a response to the sender application.
Ptr< QKDEncryptor > m_encryptor
The QKD encryptor.
Definition: qkd-app-004.h:853
void HandlePeerCloseSignalingFromApp(Ptr< Socket > socket)
Handle a signaling connection close from the peer QKD application.
Definition: qkd-app-004.cc:665
uint32_t m_priority
The application priority (QoS).
Definition: qkd-app-004.h:827
std::string GetKsidFromHttp004KMSQuery(std::string uri)
Map the HTTP response from the KMS and obtain the key stream identifier.
uint32_t m_authenticationTagLengthInBits
The size of the authentication tag in bits (32 by default).
Definition: qkd-app-004.h:843
Address m_local
The local address for the data transmission.
Definition: qkd-app-004.h:800
void SetEncryptionAndAuthenticationSettings(uint32_t encryptionType, uint32_t authenticationType, uint32_t authenticationTagLengthInBits)
Set the encryption and the authentication algorithms.
void SendKsidResponse(HTTPMessage::HttpStatus httpStatus, std::string msg="")
Send a response on the SEND_KSID request.
uint32_t m_master
Is a master (sender/primary) application?
Definition: qkd-app-004.h:820
void CreateKeyQueues()
Create the required key queues to store a set amount of keys from the respective key stream sessions.
void ProcessResponseFromKMS(HTTPMessage &header, Ptr< Packet > packet, Ptr< Socket > socket)
Process a response from the KMS application.
void HandlePeerCloseToKMS(Ptr< Socket > socket)
Handle a connection close to the KMS.
Definition: qkd-app-004.cc:620
void SwitchAppState(QKDAppState state)
Change the state of the application.
void CheckQueues()
Request new keys from the KMS until the key queues at the application layer are established with a se...
void CheckAssociationsState()
Check if the required key stream sessions are successfuly established.
std::unordered_map< Address, Ptr< Packet >, AddressHash > m_buffer_sig
The buffer for the received signaling packets (fragmentation).
Definition: qkd-app-004.h:862
void ConnectionToAppFailed(Ptr< Socket > socket)
Callback function after the connection to the APP has failed.
Definition: qkd-app-004.cc:590
void CreateKeyStreamAssociations()
void HandlePeerCloseFromKMS(Ptr< Socket > socket)
Handle a connection close from the KMS.
Definition: qkd-app-004.cc:608
TracedCallback< Ptr< Packet > > m_decryptionTrace
A trace callback for the decryption event.
Definition: qkd-app-004.h:846
UUID GetId(void)
Get the application identifier.
Definition: qkd-app-004.h:541
uint32_t m_malicious
Is a malicious application?
Definition: qkd-app-004.h:821
void AppTransitionTree(void)
Transition through a tree of the application states and trigger actions.
void HandleReadFromKMS(Ptr< Socket > socket)
Handle a packet received by the QKD application from the KMS application.
Definition: qkd-app-004.cc:677
Ptr< Socket > m_sendSignalingSocketApp
The sending socket for the signaling messages.
Definition: qkd-app-004.h:789
std::string PacketToString(Ptr< Packet > packet)
Convert the packet to a string.
DataRate m_minDataRate
The minimum application data rate.
Definition: qkd-app-004.h:811
static uint32_t m_applicationCounts
The number of running applications.
Definition: qkd-app-004.h:837
QKDAppKey GetEncKey()
Get the encryption key from the queue.
Ptr< Socket > m_sinkDataSocketApp
The receiving socket for the data.
Definition: qkd-app-004.h:792
TracedCallback< Ptr< const Packet >, std::string > m_txTrace
Definition: qkd-app-004.h:552
void ScheduleTx(void)
Schedule the next time slot to send the data.
Definition: qkd-app-004.cc:291
uint32_t m_encryptionTypeInt
The encryption algorithm.
Definition: qkd-app-004.h:841
TracedCallback< Ptr< const Packet >, std::string > m_rxTrace
A trace for received data packets.
Definition: qkd-app-004.h:555
void DataPacketReceivedFromApp(const Ptr< Packet > &p, const Address &from, Ptr< Socket > socket)
Check for the tcp segmentation of the signaling packets received from the KMS.
Definition: qkd-app-004.cc:872
void SendKsidRequest(std::string ksid, uint32_t input)
Inform the peer QKD application of the established key stream session.
void PrepareSendSocketToApp()
Prepare the send socket to communicate with the peer QKD Application.
Definition: qkd-app-004.cc:402
std::vector< KMSPacket > m_queue_kms
The queue of packets waiting for the transmission to the KMS.
Definition: qkd-app-004.h:859
void Http004AppQuery(uint32_t methodType, std::string ksid)
Memories the HTTP request made to the peer QKD application.
void HandlePeerErrorToKMS(Ptr< Socket > socket)
Handle a connection error to the KMS.
Definition: qkd-app-004.cc:637
std::unordered_map< Address, Ptr< Packet >, AddressHash > m_buffer_kms
The buffer for the received packets from the KMS (fragmentation).
Definition: qkd-app-004.h:861
void Setup(std::string socketType, Address src, Address dst, Address kms, UUID dstSaeId, std::string type)
Configure the application.
Definition: qkd-app-004.cc:215
uint32_t m_authenticationTypeInt
The authentication algorithm.
Definition: qkd-app-004.h:842
QKD app packet header that carries info about used encryption, auth tag and other.
std::string GetEncryptionKeyId(void) const
Read the encryption key identifier.
std::string GetAuthTag(void) const
Read the authentication tag.
uint32_t GetSerializedSize() const
Get the serialized size of a packet.
void SetEncryptionKeyId(std::string value)
Set the encryption key identifier.
void SetEncrypted(uint32_t value)
Set the encrypted field.
uint32_t GetLength(void) const
Get message length.
void SetLength(uint32_t value)
Set the message length.
void SetAuthenticated(uint32_t value)
Set the authentication field.
uint32_t GetAuthenticated(void) const
Read the authentication field.
void SetAuthTag(std::string value)
Set the authentication tag.
std::string GetAuthenticationKeyId(void) const
Read the authentication key identifier.
void SetAuthenticationKeyId(std::string keyID)
Set the authentication key identifier.
uint32_t GetEncrypted(void) const
Read the encrypted field.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
static void Cancel(const EventId &id)
Set the cancel bit on this event: the event's associated function will not be invoked when it expires...
Definition: simulator.cc:285
static Time Now()
Return the current simulation virtual time.
Definition: simulator.cc:208
virtual int Send(Ptr< Packet > p, uint32_t flags)=0
Send data (or dummy data) to the remote host.
void SetCloseCallbacks(Callback< void, Ptr< Socket >> normalClose, Callback< void, Ptr< Socket >> errorClose)
Detect socket recv() events such as graceful shutdown or error.
Definition: socket.cc:96
void SetAcceptCallback(Callback< bool, Ptr< Socket >, const Address & > connectionRequest, Callback< void, Ptr< Socket >, const Address & > newConnectionCreated)
Accept connection requests from remote hosts.
Definition: socket.cc:105
void SetRecvCallback(Callback< void, Ptr< Socket >> receivedData)
Notify application when new data is available to be read.
Definition: socket.cc:128
void SetDataSentCallback(Callback< void, Ptr< Socket >, uint32_t > dataSent)
Notify application when a packet has been sent from transport protocol (non-standard socket call)
Definition: socket.cc:114
virtual int GetPeerName(Address &address) const =0
Get the peer address of a connected socket.
virtual int ShutdownSend()=0
virtual int Connect(const Address &address)=0
Initiate a connection to a remote host.
static Ptr< Socket > CreateSocket(Ptr< Node > node, TypeId tid)
This method wraps the creation of sockets that is performed on a given node by a SocketFactory specif...
Definition: socket.cc:72
virtual int Close()=0
Close a socket.
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
virtual int Listen()=0
Listen for incoming connections.
void SetConnectCallback(Callback< void, Ptr< Socket >> connectionSucceeded, Callback< void, Ptr< Socket >> connectionFailed)
Specify callbacks to allow the caller to determine if the connection succeeds of fails.
Definition: socket.cc:87
virtual Ptr< Packet > RecvFrom(uint32_t maxSize, uint32_t flags, Address &fromAddress)=0
Read a single packet from the socket and retrieve the sender address.
static TypeId GetTypeId()
Get the type ID.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
Universally unique identifier (UUID)
Definition: uuid.h:35
static UUID Random()
Generate random UUID4 (randomly or pseudo-randomly generated version)
Definition: uuid.cc:148
static UUID Sequential()
Generate sequential UUID1 (time based version)
Definition: uuid.cc:92
std::string string() const
Get string from the current UUID in format "00000000-0000-0000-0000-000000000000".
Definition: uuid.cc:74
static TypeId GetTypeId()
Get the type ID.
Hold an unsigned integer type.
Definition: uinteger.h:45
double GetValue(double min, double max)
Get the next random value drawn from the distribution.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
Callback< R, Args... > MakeNullCallback()
Definition: callback.h:747
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_ABORT_IF(cond)
Abnormal program termination if a condition is true.
Definition: abort.h:76
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
NLOHMANN_BASIC_JSON_TPL_DECLARATION std::string to_string(const NLOHMANN_BASIC_JSON_TPL &j)
user-defined to_string function for JSON values
Definition: json.h:25255
basic_json<> json
default JSON class
Definition: json.h:3000
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1414
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:704
Ptr< const AttributeChecker > MakeTypeIdChecker()
Definition: type-id.cc:1250
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:533
Ptr< const AttributeAccessor > MakeTypeIdAccessor(T1 a1)
Definition: type-id.h:598
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
A cryptographic key at the application layer.
Definition: qkd-app-004.h:586
static const uint32_t packetSize
Packet size generated at the AP.