1
0

Headers.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408
  1. /* vim: set expandtab ts=4 sw=4: */
  2. /*
  3. * You may redistribute this program and/or modify it under the terms of
  4. * the GNU General Public License as published by the Free Software Foundation,
  5. * either version 3 of the License, or (at your option) any later version.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. * You should have received a copy of the GNU General Public License
  13. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. #ifndef Headers_H
  16. #define Headers_H
  17. #include "util/Assert.h"
  18. #include "util/Endian.h"
  19. #include <stdint.h>
  20. /**
  21. * The header which switches use to decide where to route traffic.
  22. *
  23. * 1 2 3
  24. * 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
  25. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  26. * 0 | |
  27. * + Switch Label +
  28. * 4 | |
  29. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  30. * 8 | Type | Priority |
  31. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  32. */
  33. #define Headers_SwitchHeader_TYPE_DATA 0
  34. #define Headers_SwitchHeader_TYPE_CONTROL 1
  35. #pragma pack(push)
  36. #pragma pack(4)
  37. struct Headers_SwitchHeader
  38. {
  39. /** The label, this is how the switch decides where to send the packet. Big Endian. */
  40. uint64_t label_be;
  41. /**
  42. * Top 8 bits: messageType
  43. * See: MessageType.h
  44. *
  45. * Bottom 24 bits: priority
  46. * Anti-flooding, this is a big endian uint32_t with the high 8 bits cut off.
  47. *
  48. * This entire number is in big endian encoding.
  49. */
  50. uint32_t lowBits_be;
  51. };
  52. #define Headers_SwitchHeader_SIZE 12
  53. Assert_compileTime(sizeof(struct Headers_SwitchHeader) == Headers_SwitchHeader_SIZE);
  54. #pragma pack(pop)
  55. static inline uint32_t Headers_getMessageType(const struct Headers_SwitchHeader* header)
  56. {
  57. return Endian_bigEndianToHost32(header->lowBits_be) >> 24;
  58. }
  59. static inline uint32_t Headers_getPriority(const struct Headers_SwitchHeader* header)
  60. {
  61. return Endian_bigEndianToHost32(header->lowBits_be) & ((1 << 24) - 1);
  62. }
  63. static inline void Headers_setPriorityAndMessageType(struct Headers_SwitchHeader* header,
  64. const uint32_t priority,
  65. const uint32_t messageType)
  66. {
  67. header->lowBits_be =
  68. Endian_hostToBigEndian32( (priority & ((1 << 24) - 1)) | messageType << 24 );
  69. }
  70. /**
  71. * Header for nodes authenticating to one another.
  72. *
  73. * 1 2 3
  74. * 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
  75. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  76. * 0 | Auth Type | |
  77. * +-+-+-+-+-+-+-+-+ Hash Code +
  78. * 4 | |
  79. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  80. * 8 |A| Derivations |S| Additional |
  81. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  82. *
  83. * If the 'A' bit is set, the packets in the connection are to be authenticated with Poly1305.
  84. * The Auth Type and Hash Code combined make a lookup key which can be used to scan a hashtable
  85. * to see if the given password is known. It can be thought of as the "username" although it is
  86. * a derivative of the password.
  87. * The number of derivations represents how many times the hash of the password has been hashed
  88. * again. Assuming Alice and Bob have a secure shared secret and Bob and Charlie have a secure
  89. * shared secret, Bob can provide Charlie with a hash of his password with Alice which will allow
  90. * Charlie to then establish a secure connection with Alice, without relying exclusively on
  91. * asymmetrical cryptography.
  92. *
  93. * If the packet has 0 length and the 'S' bit is set then the packet is only intended for helping
  94. * to setup the Cryptoauth session and should be dropped rather than being passed to the user.
  95. */
  96. union Headers_AuthChallenge
  97. {
  98. struct {
  99. uint8_t type;
  100. uint8_t lookup[7];
  101. /**
  102. * High 1 bit is whether to require poly1305 packet authentication.
  103. * low 15 bits is number of derivations.
  104. */
  105. uint16_t requirePacketAuthAndDerivationCount;
  106. uint16_t additional;
  107. } challenge;
  108. uint8_t bytes[12];
  109. uint32_t ints[3];
  110. };
  111. /** Total size of the auth structure. */
  112. #define Headers_AuthChallenge_SIZE 12
  113. Assert_compileTime(sizeof(union Headers_AuthChallenge) == Headers_AuthChallenge_SIZE);
  114. /** The number of bytes from the beginning which identify the auth for looking up the secret. */
  115. #define Headers_AuthChallenge_KEYSIZE 8
  116. static inline int Headers_isPacketAuthRequired(union Headers_AuthChallenge* ac)
  117. {
  118. return ac->challenge.requirePacketAuthAndDerivationCount & Endian_hostToBigEndian16(1<<15);
  119. }
  120. static inline int Headers_isSetupPacket(union Headers_AuthChallenge* ac)
  121. {
  122. return ac->challenge.additional & Endian_hostToBigEndian16(1<<15);
  123. }
  124. static inline void Headers_setPacketAuthRequired(union Headers_AuthChallenge* ac,
  125. int require)
  126. {
  127. if (require) {
  128. ac->challenge.requirePacketAuthAndDerivationCount |=
  129. Endian_hostToBigEndian16(1<<15);
  130. } else {
  131. ac->challenge.requirePacketAuthAndDerivationCount &=
  132. Endian_hostToBigEndian16(~(1<<15));
  133. }
  134. }
  135. static inline void Headers_setSetupPacket(union Headers_AuthChallenge* ac, int empty)
  136. {
  137. if (empty) {
  138. ac->challenge.additional |= Endian_hostToBigEndian16(1<<15);
  139. } else {
  140. ac->challenge.additional &= Endian_hostToBigEndian16(~(1<<15));
  141. }
  142. }
  143. static inline uint16_t Headers_getAuthChallengeDerivations(union Headers_AuthChallenge* ac)
  144. {
  145. return Endian_hostToBigEndian16(ac->challenge.requirePacketAuthAndDerivationCount)
  146. & (((uint16_t)~0)>>1);
  147. }
  148. static inline void Headers_setAuthChallengeDerivations(union Headers_AuthChallenge* ac,
  149. uint16_t derivations)
  150. {
  151. ac->challenge.requirePacketAuthAndDerivationCount &=
  152. Endian_hostToBigEndian16(1<<15);
  153. ac->challenge.requirePacketAuthAndDerivationCount |=
  154. Endian_hostToBigEndian16(derivations & ~(1<<15));
  155. }
  156. /**
  157. * This is a handshake header packet, there are 2 required to begin an encrypted connection.
  158. *
  159. * 1 2 3
  160. * 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
  161. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  162. * 0 | Session State |
  163. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  164. * 4 | |
  165. * + +
  166. * 8 | Auth Challenge |
  167. * + +
  168. * 12 | |
  169. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  170. * 16 | |
  171. * + +
  172. * 20 | |
  173. * + +
  174. * 24 | |
  175. * + Random Nonce +
  176. * 28 | |
  177. * + +
  178. * 32 | |
  179. * + +
  180. * 36 | |
  181. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  182. * 40 | |
  183. * + +
  184. * 44 | |
  185. * + +
  186. * 48 | |
  187. * + +
  188. * 52 | |
  189. * + Permanent Public Key +
  190. * 56 | |
  191. * + +
  192. * 60 | |
  193. * + +
  194. * 64 | |
  195. * + +
  196. * 68 | |
  197. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  198. * 72 | |
  199. * + +
  200. * 76 | |
  201. * + Poly1305 Authenticator +
  202. * 80 | |
  203. * + +
  204. * 84 | |
  205. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  206. * 88 | |
  207. * + +
  208. * 92 | |
  209. * + +
  210. * 96 | |
  211. * + +
  212. * 100 | |
  213. * + Encrypted/Authenticated Temporary Public Key +
  214. * 104 | |
  215. * + +
  216. * 108 | |
  217. * + +
  218. * 112 | |
  219. * + +
  220. * 116 | |
  221. * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  222. * | |
  223. * + Variable Length Encrypted/Authenticated Content +
  224. * | |
  225. *
  226. * If "Session State" is equal to the bitwise complement of zero, the sender is requesting
  227. * that the recipient begin a connection with him, this is done in cases when the initiator
  228. * of the connection does not know the key for the recipient. If the entire header is not
  229. * present the recipient MUST drop the packet silently, the only field which is read in the
  230. * packet is the "Permanent Public Key" field, all others SHOULD be ignored, specifically,
  231. * content MUST not be passed on because it cannot be authenticated. The recipient of such a
  232. * packet SHOULD send back a "hello" packet if there is no established connection.
  233. * If there is already a connection over the interface, the recipient SHOULD NOT respond
  234. * but MAY allow the connection to time out faster.
  235. *
  236. * If the "Session State" field is equal to the one or two, the packet is a "hello" packet.
  237. * or a repeated hello packet. If no connection is present, one should be established and the
  238. * recipient MAY send a "key" packet in response but it is RECOMMENDED that he wait until
  239. * he has data to send first. A node who has sent a hello packet and gotten no response and
  240. * now wishes to send more data MUST send that data as more (repeat) hello packets.
  241. *
  242. * If the "Session State" field is equal to two or three, the packet is a "key" packet.
  243. * Key packets are responses to hello packets. Once a node receives a key packet it may begin
  244. * sending data packets. A node who has received a hello packet, sent a key packet and gotten
  245. * no further response who now wishes to send more data MUST send that data as more (repeat)
  246. * key packets.
  247. */
  248. union Headers_CryptoAuth
  249. {
  250. uint32_t nonce;
  251. struct {
  252. /**
  253. * Numbers one through three are interpreted as handshake packets, UINT32_MAX is
  254. * a connectToMe packet and anything else is a nonce in a traff packet.
  255. */
  256. uint32_t handshakeStage;
  257. /** Used for authenticating routers to one another. */
  258. union Headers_AuthChallenge auth;
  259. /** Random nonce for the handshake. */
  260. uint8_t nonce[24];
  261. /** This node's permanent public key. */
  262. uint8_t publicKey[32];
  263. /** This is filled in when the tempKey is encrypted. */
  264. uint8_t authenticator[16];
  265. /** The public key to use for this session, encrypted with the private key. */
  266. uint8_t encryptedTempKey[32];
  267. } handshake;
  268. };
  269. #define Headers_CryptoAuth_SIZE 120
  270. Assert_compileTime(sizeof(union Headers_CryptoAuth) == Headers_CryptoAuth_SIZE);
  271. struct Headers_IP6Header
  272. {
  273. uint16_t versionClassAndFlowLabel;
  274. /** Big Endian. */
  275. uint16_t flowLabelLow_be;
  276. /** Big Endian. */
  277. uint16_t payloadLength_be;
  278. uint8_t nextHeader;
  279. uint8_t hopLimit;
  280. uint8_t sourceAddr[16];
  281. uint8_t destinationAddr[16];
  282. };
  283. #define Headers_IP6Header_SIZE 40
  284. Assert_compileTime(sizeof(struct Headers_IP6Header) == Headers_IP6Header_SIZE);
  285. struct Headers_IP6Fragment
  286. {
  287. uint8_t nextHeader;
  288. uint8_t zero;
  289. uint16_t fragmentOffsetAndMoreFragments_be;
  290. uint32_t identifier;
  291. };
  292. #define Headers_IP6Fragment_SIZE 8
  293. Assert_compileTime(sizeof(struct Headers_IP6Fragment) == Headers_IP6Fragment_SIZE);
  294. #define Headers_IP6Fragment_TYPE 44
  295. static inline uint32_t Headers_IP6Fragment_getOffset(struct Headers_IP6Fragment* frag)
  296. {
  297. return Endian_bigEndianToHost16(frag->fragmentOffsetAndMoreFragments_be) >> 3;
  298. }
  299. static inline void Headers_IP6Fragment_setOffset(struct Headers_IP6Fragment* frag, uint16_t offset)
  300. {
  301. frag->fragmentOffsetAndMoreFragments_be &= Endian_hostToBigEndian16(7);
  302. frag->fragmentOffsetAndMoreFragments_be |= Endian_hostToBigEndian16(offset << 3);
  303. }
  304. static inline int Headers_IP6Fragment_hasMoreFragments(struct Headers_IP6Fragment* frag)
  305. {
  306. return frag->fragmentOffsetAndMoreFragments_be & Endian_hostToBigEndian16(1);
  307. }
  308. static inline void Headers_IP6Fragment_setMoreFragments(struct Headers_IP6Fragment* frag, int more)
  309. {
  310. if (more) {
  311. frag->fragmentOffsetAndMoreFragments_be |= Endian_hostToBigEndian16(1);
  312. } else {
  313. frag->fragmentOffsetAndMoreFragments_be &= Endian_hostToBigEndian16(0xFFFF << 1);
  314. }
  315. }
  316. struct Headers_IP4Header
  317. {
  318. uint8_t versionAndHeaderLength;
  319. uint8_t differentiatedServices;
  320. uint16_t totalLength_be;
  321. uint16_t identification_be;
  322. uint16_t flagsAndFragmentOffset;
  323. uint8_t ttl;
  324. uint8_t protocol;
  325. uint16_t checksum_be;
  326. uint8_t sourceAddr[4];
  327. uint8_t destAddr[4];
  328. };
  329. #define Headers_IP4Header_SIZE 20
  330. Assert_compileTime(sizeof(struct Headers_IP4Header) == Headers_IP4Header_SIZE);
  331. static inline int Headers_getIpVersion(void* header)
  332. {
  333. return (((uint8_t*) header)[0] & 0xF0) >> 4;
  334. }
  335. #define Headers_setIpVersion(header) \
  336. (((uint8_t*) header)[0] |= ( \
  337. (sizeof(*header) == Headers_IP4Header_SIZE) ? 4 : 6 \
  338. ) << 4)
  339. struct Headers_UDPHeader {
  340. uint16_t srcPort_be;
  341. uint16_t destPort_be;
  342. uint16_t length_be;
  343. uint16_t checksum_be;
  344. };
  345. #define Headers_UDPHeader_SIZE 8
  346. Assert_compileTime(sizeof(struct Headers_UDPHeader) == Headers_UDPHeader_SIZE);
  347. struct Headers_ICMP6Header {
  348. uint8_t type;
  349. uint8_t code;
  350. uint16_t checksum;
  351. uint32_t additional;
  352. };
  353. #define Headers_ICMP6Header_SIZE 8
  354. Assert_compileTime(sizeof(struct Headers_ICMP6Header) == Headers_ICMP6Header_SIZE);
  355. /**
  356. * A message which is broadcast to signal to other nodes in the local network that they can connect.
  357. */
  358. #define Headers_Beacon_PASSWORD_LEN 20
  359. struct Headers_Beacon {
  360. uint32_t version_be;
  361. uint8_t password[Headers_Beacon_PASSWORD_LEN];
  362. uint8_t publicKey[32];
  363. };
  364. #define Headers_Beacon_SIZE 56
  365. Assert_compileTime(sizeof(struct Headers_Beacon) == Headers_Beacon_SIZE);
  366. #endif