A Discrete-Event Network Simulator
API
onion-routing.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 
3 
4 
5 /*
6 * Copyright (c) 2020 DLTLT
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation;
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 * Author: Niki Hrovatin <niki.hrovatin@famnit.upr.si>
22 */
23 
24 
25 
26 
27 #include "onion-routing.h"
28 
29 namespace ns3 {
30 
31 /* ... */
32 
33 
34 NS_OBJECT_ENSURE_REGISTERED (OnionRouting);
35 
36 NS_LOG_COMPONENT_DEFINE ("onionrouting");
37 
38 
39 TypeId
41 {
42  static TypeId tid = TypeId ("ns3::OnionRouting")
43  .SetParent<Object> ()
44  .SetGroupName ("OnionRouting");
45  return tid;
46 
47 }
48 
49 
50 
51 OnionRouting::OnionRouting (uint16_t sealPadding, const uint16_t protocolNumber)
52 {
54  //set seal bytes
55  m_sealPadding = sealPadding;
56  //set address bytes of the used IP protocol
57  if (protocolNumber == Ipv4L3Protocol::PROT_NUMBER)
58  {
59  m_addressSize = 4;
60  }
61  else if (protocolNumber == Ipv6L3Protocol::PROT_NUMBER)
62  {
63  m_addressSize = 16;
64  }
65  else
66  {
67  NS_LOG_WARN ("The given (IP) protocol number is not valid.");
69  }
70 }
71 
72 
73 
74 
75 
76 void
77 OnionRouting::BuildOnion (uint8_t * cipher, uint8_t ** route, uint8_t ** keys,uint16_t routeLen)
78 {
80 
81  if (routeLen < 4)
82  {
83 
84  NS_LOG_LOGIC ("Route is too short, need at least 3 intermediate hops.");
86 
87  }
88  else
89  {
90  NS_LOG_INFO ("Start creation of the onion");
91 
92  m_onionStream.str ("");
93 
94  CreateOnion (cipher,route,keys, routeLen, routeLen, nullptr, 0, nullptr, 0);
95 
96  AddressToStream (route[0]);
97 
98  NS_LOG_INFO (m_onionStream.str () << "\nOnion ready");
99  }
100 }
101 
102 
103 
104 void
105 OnionRouting::BuildOnion (uint8_t * cipher, uint8_t ** route, uint8_t ** keys, uint16_t routeLen, uint8_t * endContent, uint16_t endContentLen)
106 {
108 
109  if (routeLen < 4)
110  {
111 
112  NS_LOG_LOGIC ("Route is too short, need at least 3 intermediate hops.");
114 
115  }
116  else
117  {
118  NS_LOG_INFO ("Start creation of the onion");
119 
120  m_onionStream.str ("");
121 
122  CreateOnion (cipher,route,keys, routeLen, routeLen, nullptr, 0, endContent, endContentLen);
123 
124  AddressToStream (route[0]);
125 
126  NS_LOG_INFO (m_onionStream.str () << "\nOnion ready");
127  }
128 }
129 
130 
131 
132 void
133 OnionRouting::BuildOnion (uint8_t * cipher, uint8_t ** route, uint8_t ** keys, uint8_t ** layerContent, uint16_t layerContentLen, uint16_t routeLen)
134 {
136 
137  if (routeLen < 4)
138  {
139 
140  NS_LOG_LOGIC ("Route is too short, need at least 3 intermediate hops.");
142 
143  }
144  else
145  {
146  NS_LOG_INFO ("Start creation of the onion");
147 
148  m_onionStream.str ("");
149 
150  CreateOnion (cipher,route,keys, routeLen, routeLen, layerContent, layerContentLen, nullptr, 0);
151 
152  AddressToStream (route[0]);
153 
154  NS_LOG_INFO (m_onionStream.str () << "\nOnion ready");
155  }
156 }
157 
158 
159 void
160 OnionRouting::BuildOnion (uint8_t * cipher, uint8_t ** route, uint8_t ** keys, uint8_t ** layerContent, uint16_t layerContentLen, uint16_t routeLen, uint8_t * endContent, uint16_t endContentLen)
161 {
163 
164  if (routeLen < 4)
165  {
166 
167  NS_LOG_LOGIC ("Route is too short, need at least 3 intermediate hops.");
169  }
170  else
171  {
172  NS_LOG_INFO ("Start creation of the onion");
173 
174  m_onionStream.str ("");
175 
176  CreateOnion (cipher,route,keys, routeLen, routeLen, layerContent, layerContentLen, endContent, endContentLen);
177 
178  AddressToStream (route[0]);
179 
180  NS_LOG_INFO (m_onionStream.str () << "\nOnion ready");
181  }
182 }
183 
184 void
185 OnionRouting::CreateOnion (uint8_t * cipher, uint8_t ** route, uint8_t ** keys, uint16_t index, uint16_t routeLen, uint8_t ** layerContent, uint16_t layerContentLen, uint8_t * endContent, uint16_t endContentLen)
186 {
187  //number of bytes to be encrypted in this layer
188  int plainLayerLen = m_addressSize + layerContentLen + OnionLength (index - 1,layerContentLen,endContentLen);
189 
190  m_onionStream << "("; //fancy output
191 
192  if (index <= 2 && (endContentLen != 0 || layerContentLen != 0)) //stop recursion
193 
194  {
195  for (int i = 0; i < m_addressSize; ++i) //Insert the zero address -- 0.0.0.0 (ipv4)
196  {
197  cipher[m_addressSize + layerContentLen + m_sealPadding + m_sealPadding + i] = 0;
198  }
199 
200  if (endContentLen != 0)
201  {
202  //If end content is set include it & encrypt
203  memcpy (&cipher[m_addressSize + layerContentLen + m_sealPadding + m_sealPadding + m_addressSize], endContent, endContentLen);
204  EncryptLayer (&cipher[m_addressSize + layerContentLen + m_sealPadding],&cipher[m_addressSize + layerContentLen + m_sealPadding + m_sealPadding],m_addressSize + endContentLen,keys[routeLen - index + 1]);
205  }
206  else
207  {
208  //Include layer content & encrypt
209  memcpy (&cipher[m_addressSize + layerContentLen + m_sealPadding + m_sealPadding + m_addressSize], layerContent[routeLen - index + 1], layerContentLen);
210  EncryptLayer (&cipher[m_addressSize + layerContentLen + m_sealPadding],&cipher[m_addressSize + layerContentLen + m_sealPadding + m_sealPadding],m_addressSize + layerContentLen,keys[routeLen - index + 1]);
211  }
212 
213  }
214  else if (index > 2) //recursion
215 
216  {
217  CreateOnion (&cipher[ m_sealPadding + m_addressSize + layerContentLen],route, keys, index - 1,routeLen,layerContent, layerContentLen, endContent,endContentLen);
218  }
219 
220 
221  //Insert next hop address
222  memcpy (&cipher[m_sealPadding], route[routeLen - index + 1], m_addressSize);
223  AddressToStream (route[routeLen - index + 1]); //fancy output
224 
225  if (layerContentLen != 0)
226  {
227  //Include layer content in the current encryption layer
228  memcpy (&cipher[m_sealPadding + m_addressSize], layerContent[routeLen - index], layerContentLen);
229  }
230 
231  EncryptLayer (cipher,&cipher[m_sealPadding],plainLayerLen,keys[routeLen - index]); //encrypt
232 
233  m_onionStream << ") "; //fancy output
234 
235 } //create the onion
236 
237 
238 
239 
240 
241 orLayer * OnionRouting::PeelOnion (uint8_t * onion, uint16_t onionLen, uint8_t * publicKey, uint8_t * secretKey)
242 {
243  uint8_t * innerLayer = new uint8_t[onionLen - (m_sealPadding)];
244 
245  DecryptLayer (innerLayer,onion,onionLen,publicKey,secretKey);
246 
247  orLayer * layer = new orLayer;
248  layer->nextHopIP = innerLayer;
249  layer->innerLayer = &innerLayer[m_addressSize];
250  layer->innerLayerLen = onionLen - m_sealPadding - m_addressSize;
251 
252  return layer;
253 }
254 
255 
256 
257 
258 
259 uint16_t OnionRouting::OnionLength (uint16_t routeLen,uint16_t layerContentLen,uint16_t endContentLen)
260 {
261  routeLen = routeLen - 1;
262  if (endContentLen == 0 && layerContentLen == 0)
263  {
264  return routeLen * (m_sealPadding + m_addressSize);
265  }
266  else if (endContentLen == 0)
267  {
268  return routeLen * (m_sealPadding + m_addressSize + layerContentLen) + m_sealPadding + m_addressSize + layerContentLen;
269  }
270  else
271  {
272  return routeLen * (m_sealPadding + m_addressSize + layerContentLen) + m_sealPadding + m_addressSize + endContentLen;
273  }
274 }
275 
276 
277 
278 
279 void OnionRouting::AddressToStream (uint8_t* ip)
280 {
281  m_onionStream << (int) ip[0];
282  for (int i = 1; i < m_addressSize; ++i)
283  {
284  m_onionStream << "." << (int) ip[i];
285  }
286 }
287 
288 
289 
290 
293 {
294  NS_LOG_FUNCTION (this);
295  return m_errno;
296 }
297 
298 
299 
300 //OnionRoutingDummyEncryption -- Implemented class onion routing with dummy encryption
301 
302 
303 OnionRoutingDummyEncryption::OnionRoutingDummyEncryption (uint16_t sealPadding, const uint16_t protocolNumber) : OnionRouting (sealPadding,protocolNumber)
304 {
305  if (sealPadding < 4)
306  {
307  NS_FATAL_ERROR ("Seal padding must be at least 4-Bytes");
308  }
309 }
310 
311 
312 TypeId
314 {
315  static TypeId tid = TypeId ("ns3::OnionRoutingDummyEncryption")
316  .SetParent<OnionRouting> ()
317  .SetGroupName ("OnionRouting");
318  return tid;
319 
320 }
321 
322 
324 {
325  Ptr<UniformRandomVariable> x = CreateObject<UniformRandomVariable> ();
326  uint32_t key = x->GetInteger (0,UINT32_MAX);
327  memcpy (m_encryptionkey, &key, 4);
328 }
329 
330 
332 {
333  return m_encryptionkey;
334 }
335 
336 
337 
338 void OnionRoutingDummyEncryption::EncryptLayer (uint8_t * ciphertext, uint8_t* message, int len, uint8_t * key) const
339 {
340  memcpy (ciphertext, &key[0], 4); //include the key
341  for (int i = 0; i < m_sealPadding - 4; ++i) //insert seal padding, all zeros
342  {
343  ciphertext[4 + i] = 0;
344  }
345 }
346 
347 
348 
349 void OnionRoutingDummyEncryption::DecryptLayer (uint8_t * innerLayer, uint8_t* onion, uint16_t onionLen, uint8_t * pk, uint8_t * sk) const
350 {
351  for (int i = 0; i < 4; ++i)
352  {
353  if (onion[i] != pk[i])
354  {
355  NS_LOG_INFO ("Messge corrupted or not for this node");
357  return;
358  }
359  }
360  memcpy (innerLayer,&onion[m_sealPadding],onionLen - m_sealPadding);
361 }
362 
363 
364 
365 
366 
367 
368 
369 }
370 
ns3::OnionRouting::GetTypeId
static TypeId GetTypeId(void)
Definition: onion-routing.cc:17
ns3::OnionRoutingDummyEncryption::GetEncryptionKey
uint8_t * GetEncryptionKey(void)
Return the current encryption key.
Definition: onion-routing.cc:331
ns3::OnionRouting
Abstract class for creation and decryption of Onion messages.
Definition: onion-routing.h:29
ns3
Definition: sensornode-helper.cc:26
ns3::orLayer::nextHopIP
uint8_t * nextHopIP
ip address given in the serialized form
Definition: onion-routing.h:23
ns3::OnionRouting::OnionLength
uint16_t OnionLength(uint16_t routeLen, uint16_t contentLen)
Definition: onion-routing.cc:180
ns3::OnionRoutingDummyEncryption::GenerateNewKey
void GenerateNewKey(void)
Generate a new dummy encryption key of 4Bytes using the uniform random generator.
Definition: onion-routing.cc:323
ns3::OnionRouting::PeelOnion
orLayer * PeelOnion(uint8_t *onion, uint16_t onionLen, uint8_t *pk, uint8_t *sk)
Definition: onion-routing.cc:158
ns3::OnionRouting::m_errno
enum OnionErrno m_errno
error status while using the onion class
Definition: onion-routing.h:320
ns3::OnionRouting::DecryptLayer
virtual void DecryptLayer(uint8_t *innerLayer, uint8_t *onion, uint16_t onionLen, uint8_t *pk, uint8_t *sk) const =0
ns3::OnionRouting::ERROR_ROUTE_TO_SHORT
@ ERROR_ROUTE_TO_SHORT
Definition: onion-routing.h:107
ns3::OnionRouting::CreateOnion
int CreateOnion(uint8_t *cipher, uint8_t **route, uint16_t index, uint16_t routeLen, uint8_t **keys, uint8_t *content, uint16_t contentLen)
Definition: onion-routing.cc:103
ns3::OnionRouting::OnionErrno
OnionErrno
Enumeration of the possible errors using the class onion-routing.
Definition: onion-routing.h:104
ns3::OnionRouting::m_sealPadding
uint16_t m_sealPadding
size increase of the ciphertext in bytes, intorduced by the encryption method
Definition: onion-routing.h:50
ns3::OnionRouting::m_addressSize
uint16_t m_addressSize
size in bytes of the used address type (4-Ipv4, 16-Ipv6)
Definition: onion-routing.h:52
ns3::orLayer
structure holding details resulting from layer decryption of an onion message
Definition: onion-routing.h:22
ns3::OnionRouting::ERROR_DECRYPTION
@ ERROR_DECRYPTION
Definition: onion-routing.h:109
ns3::orLayer::innerLayer
uint8_t * innerLayer
inner content of the onion message without the next hop address
Definition: onion-routing.h:24
ns3::OnionRouting::GetErrno
enum OnionErrno GetErrno(void)
Return the last error code of the OnionErrno enum.
Definition: onion-routing.cc:292
onion-routing.h
ns3::OnionRouting::ERROR_PROT_NUMBER
@ ERROR_PROT_NUMBER
Definition: onion-routing.h:106
ns3::OnionRoutingDummyEncryption::m_encryptionkey
uint8_t m_encryptionkey[4]
the current encryption key
Definition: onion-routing.h:381
ns3::OnionRouting::AddressToStream
void AddressToStream(uint8_t *ip)
Definition: onion-routing.cc:200
ns3::orLayer::innerLayerLen
uint16_t innerLayerLen
length of the inner content of the onion message
Definition: onion-routing.h:25
ns3::OnionRoutingDummyEncryption::GetTypeId
static TypeId GetTypeId(void)
Register this type.
Definition: onion-routing.cc:313
ns3::OnionRoutingDummyEncryption::DecryptLayer
virtual void DecryptLayer(uint8_t *innerLayer, uint8_t *onion, uint16_t onionLen, uint8_t *pk, uint8_t *sk) const
Definition: onion-routing.cc:349
ns3::OnionRouting::BuildOnion
int BuildOnion(uint8_t *cipher, uint8_t **route, uint16_t routeLen, uint8_t **keys, uint8_t *content, uint16_t contentLen)
Definition: onion-routing.cc:63
ns3::OnionRouting::EncryptLayer
virtual void EncryptLayer(uint8_t *ciphertext, uint8_t *message, int len, uint8_t *key) const =0
ns3::OnionRouting::ERROR_NOTERROR
@ ERROR_NOTERROR
Definition: onion-routing.h:105
ns3::OnionRoutingDummyEncryption::EncryptLayer
virtual void EncryptLayer(uint8_t *ciphertext, uint8_t *message, int len, uint8_t *key) const
Definition: onion-routing.cc:338
ns3::OnionRouting::m_onionStream
std::stringstream m_onionStream
stringstream used to LOG onion construction
Definition: onion-routing.h:56
ns3::OnionRouting::OnionRouting
OnionRouting()
Definition: onion-routing.cc:27
ns3::OnionRoutingDummyEncryption::OnionRoutingDummyEncryption
OnionRoutingDummyEncryption(uint16_t sealPadding, const uint16_t protocolNumber)
Constructor – Setup parameters for the creation of onions and check that sealPadding is greter than 4...
Definition: onion-routing.cc:303