CryptoAuth_test.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  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 <https://www.gnu.org/licenses/>.
  14. */
  15. #include "crypto/random/Random.h"
  16. #include "crypto/CryptoAuth.h"
  17. #include "benc/String.h"
  18. #include "memory/MallocAllocator.h"
  19. #include "util/events/EventBase.h"
  20. #include "util/Assert.h"
  21. #include "util/Bits.h"
  22. #include "util/Hex.h"
  23. #include "util/Endian.h"
  24. #include "util/log/FileWriterLog.h"
  25. #include "wire/CryptoHeader.h"
  26. #define PRIVATEKEY_A \
  27. Constant_stringForHex("53ff22b2eb94ce8c5f1852c0f557eb901f067e5273d541e0a21e143c20dff9da")
  28. #define PUBLICKEY_A \
  29. Constant_stringForHex("e3ff75af6e4414494df22f200ffeaa56e7976d991d33cc87f52427e27f83235d")
  30. #define PRIVATEKEY_B \
  31. Constant_stringForHex("b71c4f43e3d4b1879b5065d44a1cb43eaf07ddba96de6a72ca761c4ef4bd2988")
  32. #define PUBLICKEY_B \
  33. Constant_stringForHex("27c303cdc1f96e4b28d51c75130aff6cad52098f2d752615b7b6509ed6a89477")
  34. #define USEROBJ "This represents a user"
  35. struct Context
  36. {
  37. struct CryptoAuth* ca1;
  38. struct CryptoAuth_Session* sess1;
  39. struct CryptoAuth* ca2;
  40. struct CryptoAuth_Session* sess2;
  41. struct Allocator* alloc;
  42. struct Log* log;
  43. struct Random* rand;
  44. struct EventBase* base;
  45. };
  46. static struct Context* init(uint8_t* privateKeyA,
  47. uint8_t* publicKeyA,
  48. uint8_t* password,
  49. uint8_t* privateKeyB,
  50. uint8_t* publicKeyB)
  51. {
  52. struct Allocator* alloc = MallocAllocator_new(1048576);
  53. struct Context* ctx = Allocator_calloc(alloc, sizeof(struct Context), 1);
  54. ctx->alloc = alloc;
  55. struct Log* logger = ctx->log = FileWriterLog_new(stdout, alloc);
  56. struct Random* rand = ctx->rand = Random_new(alloc, logger, NULL);
  57. struct EventBase* base = ctx->base = EventBase_new(alloc);
  58. ctx->ca1 = CryptoAuth_new(alloc, privateKeyA, base, logger, rand);
  59. ctx->sess1 = CryptoAuth_newSession(ctx->ca1, alloc, publicKeyB, false, "cif1");
  60. ctx->ca2 = CryptoAuth_new(alloc, privateKeyB, base, logger, rand);
  61. if (password) {
  62. String* passStr = String_CONST(password);
  63. CryptoAuth_setAuth(passStr, NULL, ctx->sess1);
  64. CryptoAuth_addUser(passStr, String_new(USEROBJ, alloc), ctx->ca2);
  65. }
  66. ctx->sess2 = CryptoAuth_newSession(ctx->ca2, alloc, publicKeyA, false, "cif2");
  67. return ctx;
  68. }
  69. static struct Context* simpleInit()
  70. {
  71. return init(PRIVATEKEY_A, PUBLICKEY_A, NULL, PRIVATEKEY_B, PUBLICKEY_B);
  72. }
  73. static struct Message* encryptMsg(struct Context* ctx,
  74. struct CryptoAuth_Session* encryptWith,
  75. const char* x)
  76. {
  77. struct Allocator* alloc = Allocator_child(ctx->alloc);
  78. int len = (((CString_strlen(x)+1) / 8) + 1) * 8;
  79. struct Message* msg = Message_new(len, CryptoHeader_SIZE, alloc);
  80. CString_strcpy(msg->bytes, x);
  81. msg->length = CString_strlen(x);
  82. msg->bytes[msg->length] = 0;
  83. Assert_true(!CryptoAuth_encrypt(encryptWith, msg));
  84. Assert_true(msg->length > ((int)CString_strlen(x) + 4));
  85. return msg;
  86. }
  87. static void decryptMsg(struct Context* ctx,
  88. struct Message* msg,
  89. struct CryptoAuth_Session* decryptWith,
  90. const char* x)
  91. {
  92. if (!x) {
  93. // x is null implying it is expected to fail.
  94. Assert_true(CryptoAuth_decrypt(decryptWith, msg));
  95. } else {
  96. Assert_true(!CryptoAuth_decrypt(decryptWith, msg));
  97. if ((int)CString_strlen(x) != msg->length ||
  98. CString_strncmp(msg->bytes, x, msg->length))
  99. {
  100. Assert_failure("expected [%s](%d), got [%s](%d)\n",
  101. x, (int)CString_strlen(x), msg->bytes, msg->length);
  102. }
  103. }
  104. }
  105. static void sendToIf1(struct Context* ctx, const char* x)
  106. {
  107. struct Message* msg = encryptMsg(ctx, ctx->sess2, x);
  108. decryptMsg(ctx, msg, ctx->sess1, x);
  109. Allocator_free(msg->alloc);
  110. }
  111. static void sendToIf2(struct Context* ctx, const char* x)
  112. {
  113. struct Message* msg = encryptMsg(ctx, ctx->sess1, x);
  114. decryptMsg(ctx, msg, ctx->sess2, x);
  115. Allocator_free(msg->alloc);
  116. }
  117. static void normal()
  118. {
  119. struct Context* ctx = simpleInit();
  120. sendToIf2(ctx, "hello world");
  121. sendToIf1(ctx, "hello cjdns");
  122. sendToIf2(ctx, "hai");
  123. sendToIf1(ctx, "goodbye");
  124. Allocator_free(ctx->alloc);
  125. }
  126. static void repeatKey()
  127. {
  128. struct Context* ctx = simpleInit();
  129. sendToIf2(ctx, "hello world");
  130. sendToIf2(ctx, "r u thar?");
  131. sendToIf1(ctx, "hello cjdns");
  132. sendToIf2(ctx, "hai");
  133. sendToIf1(ctx, "goodbye");
  134. Allocator_free(ctx->alloc);
  135. }
  136. static void repeatHello()
  137. {
  138. struct Context* ctx = simpleInit();
  139. sendToIf2(ctx, "hello world");
  140. sendToIf2(ctx, "r u thar?");
  141. sendToIf1(ctx, "hello cjdns");
  142. sendToIf2(ctx, "hai");
  143. sendToIf1(ctx, "goodbye");
  144. Allocator_free(ctx->alloc);
  145. }
  146. static void chatter()
  147. {
  148. struct Context* ctx = simpleInit();
  149. sendToIf2(ctx, "hello world");
  150. sendToIf1(ctx, "hello cjdns");
  151. sendToIf2(ctx, "hai");
  152. sendToIf1(ctx, "goodbye");
  153. sendToIf1(ctx, "hello cjdns");
  154. sendToIf2(ctx, "hai");
  155. sendToIf1(ctx, "goodbye");
  156. sendToIf1(ctx, "hello cjdns");
  157. sendToIf2(ctx, "hai");
  158. sendToIf1(ctx, "goodbye");
  159. sendToIf1(ctx, "hello cjdns");
  160. sendToIf2(ctx, "hai");
  161. sendToIf1(ctx, "goodbye");
  162. Allocator_free(ctx->alloc);
  163. }
  164. static void auth()
  165. {
  166. struct Context* ctx = init(PRIVATEKEY_A, PUBLICKEY_A, "password", PRIVATEKEY_B, PUBLICKEY_B);
  167. sendToIf2(ctx, "hello world");
  168. sendToIf1(ctx, "hello cjdns");
  169. sendToIf2(ctx, "hai");
  170. sendToIf1(ctx, "goodbye");
  171. Allocator_free(ctx->alloc);
  172. }
  173. static void replayKeyPacket(int scenario)
  174. {
  175. struct Context* ctx = simpleInit();
  176. sendToIf2(ctx, "hello world");
  177. struct Message* msg = encryptMsg(ctx, ctx->sess2, "hello replay key");
  178. struct Message* toReplay = Message_clone(msg, ctx->alloc);
  179. decryptMsg(ctx, msg, ctx->sess1, "hello replay key");
  180. if (scenario == 1) {
  181. // the packet is failed because we know it's a dupe from the temp key.
  182. decryptMsg(ctx, toReplay, ctx->sess1, NULL);
  183. }
  184. sendToIf2(ctx, "first traffic packet");
  185. if (scenario == 2) {
  186. decryptMsg(ctx, toReplay, ctx->sess1, NULL);
  187. }
  188. sendToIf1(ctx, "second traffic packet");
  189. if (scenario == 3) {
  190. // If we replay at this stage, the packet is dropped as a stray key
  191. decryptMsg(ctx, toReplay, ctx->sess1, NULL);
  192. }
  193. Allocator_free(ctx->alloc);
  194. }
  195. /**
  196. * Alice and Bob both decided they wanted to talk to eachother at precisely the same time.
  197. * This means two Hello packets crossed on the wire. Both arrived at their destination but
  198. * if each triggers a re-initialization of the CA session, nobody will be synchronized!
  199. */
  200. static void hellosCrossedOnTheWire()
  201. {
  202. struct Context* ctx = simpleInit();
  203. Bits_memcpy(ctx->sess2->herPublicKey, ctx->ca1->publicKey, 32);
  204. struct Message* hello2 = encryptMsg(ctx, ctx->sess2, "hello2");
  205. struct Message* hello1 = encryptMsg(ctx, ctx->sess1, "hello1");
  206. decryptMsg(ctx, hello2, ctx->sess1, "hello2");
  207. decryptMsg(ctx, hello1, ctx->sess2, "hello1");
  208. sendToIf2(ctx, "hello world");
  209. sendToIf1(ctx, "hello cjdns");
  210. sendToIf2(ctx, "hai");
  211. sendToIf1(ctx, "goodbye");
  212. Allocator_free(ctx->alloc);
  213. }
  214. static void reset()
  215. {
  216. struct Context* ctx = simpleInit();
  217. sendToIf2(ctx, "hello world");
  218. sendToIf1(ctx, "hello cjdns");
  219. sendToIf2(ctx, "hai");
  220. sendToIf1(ctx, "brb");
  221. Assert_true(CryptoAuth_getState(ctx->sess1) == CryptoAuth_State_ESTABLISHED);
  222. Assert_true(CryptoAuth_getState(ctx->sess2) == CryptoAuth_State_ESTABLISHED);
  223. CryptoAuth_reset(ctx->sess1);
  224. // sess2 still talking to sess1 but sess1 is reset and cannot read the packets.
  225. decryptMsg(ctx, encryptMsg(ctx, ctx->sess2, "will be lost"), ctx->sess1, NULL);
  226. decryptMsg(ctx, encryptMsg(ctx, ctx->sess2, "lost"), ctx->sess1, NULL);
  227. // This is because we want to prevent replay attacks from tearing down a session.
  228. decryptMsg(ctx, encryptMsg(ctx, ctx->sess1, "hello"), ctx->sess2, "hello");
  229. sendToIf1(ctx, "hello again");
  230. sendToIf2(ctx, "hai");
  231. sendToIf1(ctx, "ok works");
  232. sendToIf2(ctx, "yup");
  233. Assert_true(CryptoAuth_getState(ctx->sess1) == CryptoAuth_State_ESTABLISHED);
  234. Assert_true(CryptoAuth_getState(ctx->sess2) == CryptoAuth_State_ESTABLISHED);
  235. Allocator_free(ctx->alloc);
  236. }
  237. // This is slightly different from replayKeyPacket because the second key packet is valid,
  238. // it's just delayed.
  239. static void twoKeyPackets(int scenario)
  240. {
  241. struct Context* ctx = simpleInit();
  242. sendToIf2(ctx, "hello world");
  243. sendToIf1(ctx, "key packet 1");
  244. struct Message* key2 = encryptMsg(ctx, ctx->sess2, "key packet 2");
  245. if (scenario == 1) {
  246. sendToIf1(ctx, "key packet 3");
  247. decryptMsg(ctx, key2, ctx->sess1, "key packet 2");
  248. } else if (scenario == 2) {
  249. sendToIf2(ctx, "initial data packet");
  250. decryptMsg(ctx, key2, ctx->sess1, "key packet 2");
  251. sendToIf1(ctx, "second data packet");
  252. sendToIf2(ctx, "third data packet");
  253. } else if (scenario == 3) {
  254. sendToIf2(ctx, "initial data packet");
  255. sendToIf1(ctx, "second data packet");
  256. decryptMsg(ctx, key2, ctx->sess1, NULL);
  257. }
  258. Allocator_free(ctx->alloc);
  259. }
  260. int main()
  261. {
  262. normal();
  263. repeatKey();
  264. repeatHello();
  265. chatter();
  266. auth();
  267. replayKeyPacket(1);
  268. replayKeyPacket(2);
  269. replayKeyPacket(3);
  270. hellosCrossedOnTheWire();
  271. reset();
  272. twoKeyPackets(1);
  273. twoKeyPackets(2);
  274. twoKeyPackets(3);
  275. return 0;
  276. }