CryptoAuth_async_test.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  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. #include "crypto/random/Random.h"
  16. #include "crypto/CryptoAuth.h"
  17. #include "io/FileWriter.h"
  18. #include "benc/String.h"
  19. #include "memory/MallocAllocator.h"
  20. #include "util/platform/libc/string.h"
  21. #include "util/events/EventBase.h"
  22. #include "util/Assert.h"
  23. #include "util/Bits.h"
  24. #include "util/log/FileWriterLog.h"
  25. #include "util/CString.h"
  26. #include <stdio.h>
  27. struct Context
  28. {
  29. struct EventBase* base;
  30. struct Random* rand;
  31. struct Log* logger;
  32. };
  33. struct TestContext
  34. {
  35. struct CryptoAuth* alice;
  36. struct CryptoAuth* bob;
  37. /** For sending plain message from Alice. */
  38. struct Interface* aliceInternalIf;
  39. /** For sending encrypted messages to Alice. */
  40. struct Interface aliceExternalIf;
  41. /** When Alice tries to send a message, this will be set to the message. */
  42. struct Message* aliceCryptMsg;
  43. /** When Alice receives a message, this will be set to the message. */
  44. struct Message* aliceMsg;
  45. /** For sending plain messages from Bob. */
  46. struct Interface* bobInternalIf;
  47. /** For sending encrypted messages to Bob. */
  48. struct Interface bobExternalIf;
  49. /** When Bob tries to send a message, this will be set to the message. */
  50. struct Message* bobCryptMsg;
  51. /** When Bob receives a message, this will be set to the message. */
  52. struct Message* bobMsg;
  53. Identity
  54. };
  55. static uint8_t sendMessageAlice(struct Message* msg, struct Interface* iface)
  56. {
  57. struct TestContext* tctx = Identity_check((struct TestContext*)
  58. (((char*)iface) - offsetof(struct TestContext, aliceExternalIf)));
  59. tctx->aliceCryptMsg = msg;
  60. return 0;
  61. }
  62. static uint8_t sendMessageBob(struct Message* msg, struct Interface* iface)
  63. {
  64. struct TestContext* tctx = Identity_check((struct TestContext*)
  65. (((char*)iface) - offsetof(struct TestContext, bobExternalIf)));
  66. tctx->bobCryptMsg = msg;
  67. return 0;
  68. }
  69. static uint8_t receiveMessage(struct Message* msg, struct Interface* iface)
  70. {
  71. struct Message** msgP = iface->receiverContext;
  72. *msgP = msg;
  73. return 0;
  74. }
  75. static struct TestContext* setUp(struct Allocator* alloc, struct Context* ctx, bool authNeeded)
  76. {
  77. uint8_t* alicePrivateKey = (uint8_t*)
  78. "\x5e\x86\xcd\xdd\xfb\x57\xfd\x09\xbd\x38\x08\xb3\x09\x69\xbf\x6b"
  79. "\xe0\x83\x97\x5b\x49\x2a\xca\xce\xda\xb2\x0d\x14\x5c\x0d\x17\x90";
  80. uint8_t* bobPrivateKey = (uint8_t*)
  81. "\x20\xca\x45\xd9\x5b\xbf\xca\xe7\x35\x3c\xd2\xdf\xfa\x12\x84\x4b"
  82. "\x4e\xff\xbe\x7d\x39\xd8\x4d\x8e\x14\x2b\x9d\x21\x89\x5b\x38\x09";
  83. uint8_t* bobPublicKey = (uint8_t*)
  84. "\x51\xaf\x8d\xd9\x35\xe8\x61\x86\x3e\x94\x2b\x1b\x6d\x21\x22\xe0"
  85. "\x2f\xb2\xd0\x88\x20\xbb\xf3\xf0\x6f\xcd\xe5\x85\x30\xe0\x08\x34";
  86. struct TestContext* out = Allocator_clone(alloc, (&(struct TestContext) {
  87. .aliceExternalIf = {
  88. .sendMessage = sendMessageAlice,
  89. .allocator = alloc
  90. },
  91. .bobExternalIf = {
  92. .sendMessage = sendMessageBob,
  93. .allocator = alloc
  94. }
  95. }));
  96. Identity_set(out);
  97. out->alice = CryptoAuth_new(alloc, alicePrivateKey, ctx->base, ctx->logger, ctx->rand);
  98. out->bob = CryptoAuth_new(alloc, bobPrivateKey, ctx->base, ctx->logger, ctx->rand);
  99. out->aliceInternalIf =
  100. CryptoAuth_wrapInterface(&out->aliceExternalIf, bobPublicKey, NULL, 0, "alice", out->alice);
  101. out->bobInternalIf =
  102. CryptoAuth_wrapInterface(&out->bobExternalIf, NULL, NULL, authNeeded, "bob", out->bob);
  103. out->aliceInternalIf->receiveMessage = receiveMessage;
  104. out->aliceInternalIf->receiverContext = &out->aliceMsg;
  105. out->bobInternalIf->receiveMessage = receiveMessage;
  106. out->bobInternalIf->receiverContext = &out->bobMsg;
  107. String* passStr = String_new("abc", alloc);
  108. CryptoAuth_setAuth(passStr, 1, out->aliceInternalIf);
  109. CryptoAuth_addUser(passStr, 1, passStr, out->bob);
  110. return out;
  111. }
  112. static void sendMsg(const char* x, struct Interface* iface)
  113. {
  114. struct Message* msg = Message_new(0, 512, iface->allocator);
  115. Message_push(msg, " ", 8 - (CString_strlen(x) % 8), NULL);
  116. Message_push(msg, x, CString_strlen(x), NULL);
  117. Interface_sendMessage(iface, msg);
  118. }
  119. static void twoKeyPackets(struct Allocator* alloc, struct Context* ctx)
  120. {
  121. struct TestContext* tctx = setUp(alloc, ctx, true);
  122. sendMsg("hello bob", tctx->aliceInternalIf);
  123. Interface_receiveMessage(&tctx->bobExternalIf, tctx->aliceCryptMsg);
  124. sendMsg("hello alice (key packet)", tctx->bobInternalIf);
  125. Interface_receiveMessage(&tctx->aliceExternalIf, tctx->bobCryptMsg);
  126. sendMsg("hello again alice (repeat key packet)", tctx->bobInternalIf);
  127. // Now alice responds
  128. sendMsg("how's it going bob? (initial data packet)", tctx->aliceInternalIf);
  129. Interface_receiveMessage(&tctx->bobExternalIf, tctx->aliceCryptMsg);
  130. // and now the stray repeat key packet is sent
  131. tctx->aliceMsg = NULL;
  132. Interface_receiveMessage(&tctx->aliceExternalIf, tctx->bobCryptMsg);
  133. Assert_always(tctx->aliceMsg);
  134. }
  135. static void clearMessages(struct TestContext* tctx)
  136. {
  137. tctx->aliceMsg = tctx->bobMsg = tctx->aliceCryptMsg = tctx->bobCryptMsg = NULL;
  138. }
  139. static void sendToAlice(char* msg, struct TestContext* tctx)
  140. {
  141. clearMessages(tctx);
  142. sendMsg(msg, tctx->bobInternalIf);
  143. Assert_always(tctx->bobCryptMsg);
  144. Interface_receiveMessage(&tctx->aliceExternalIf, tctx->bobCryptMsg);
  145. Assert_always(tctx->aliceMsg);
  146. clearMessages(tctx);
  147. }
  148. static void sendToBob(char* msg, struct TestContext* tctx)
  149. {
  150. clearMessages(tctx);
  151. sendMsg(msg, tctx->aliceInternalIf);
  152. Assert_always(tctx->aliceCryptMsg);
  153. Interface_receiveMessage(&tctx->bobExternalIf, tctx->aliceCryptMsg);
  154. Assert_always(tctx->bobMsg);
  155. clearMessages(tctx);
  156. }
  157. static void reset(struct Allocator* alloc, struct Context* ctx)
  158. {
  159. struct TestContext* tctx = setUp(alloc, ctx, true);
  160. sendToBob("hello bob", tctx);
  161. sendToAlice("hi alice", tctx);
  162. sendToBob("how goes it?", tctx);
  163. sendToAlice("going well, be right back", tctx);
  164. Assert_always(CryptoAuth_getState(tctx->bobInternalIf) == CryptoAuth_ESTABLISHED);
  165. Assert_always(CryptoAuth_getState(tctx->aliceInternalIf) == CryptoAuth_ESTABLISHED);
  166. CryptoAuth_reset(tctx->bobInternalIf);
  167. // Bob is reset and Alice is still jabbering
  168. sendMsg("A bunch of crap which Bob is totally not going to hear", tctx->aliceInternalIf);
  169. Interface_receiveMessage(&tctx->bobExternalIf, tctx->aliceCryptMsg);
  170. Assert_always(!tctx->bobMsg);
  171. // Bob sends a new hello packet to Alice but it will be dropped because a session is live.
  172. sendMsg("Have to drop this because it might be a replay attack etc", tctx->bobInternalIf);
  173. Interface_receiveMessage(&tctx->aliceExternalIf, tctx->bobCryptMsg);
  174. Assert_always(!tctx->aliceMsg);
  175. CryptoAuth_reset(tctx->aliceInternalIf);
  176. // bob to alice, he didn't originally know her key
  177. sendToAlice("hi again alice", tctx);
  178. sendToBob("the reset worked", tctx);
  179. sendToAlice("perfect", tctx);
  180. sendToBob("ok now I have to go", tctx);
  181. Assert_always(CryptoAuth_getState(tctx->bobInternalIf) == CryptoAuth_ESTABLISHED);
  182. Assert_always(CryptoAuth_getState(tctx->aliceInternalIf) == CryptoAuth_ESTABLISHED);
  183. }
  184. /**
  185. * Alice and Bob both decided they wanted to talk to eachother at precisely the same time.
  186. * This means two Hello packets crossed on the wire. Both arrived at their destination but
  187. * if each triggers a re-initialization of the CA session, nobody will be synchronized!
  188. */
  189. static void crossedOnTheWire(struct Allocator* alloc, struct Context* ctx)
  190. {
  191. struct TestContext* tctx = setUp(alloc, ctx, false);
  192. sendToBob("hello bob", tctx);
  193. sendToAlice("hi alice", tctx);
  194. sendToBob("and we're established", tctx);
  195. sendToAlice("ok shutdown", tctx);
  196. CryptoAuth_reset(tctx->bobInternalIf);
  197. CryptoAuth_reset(tctx->aliceInternalIf);
  198. Log_debug(ctx->logger, "Test begins here");
  199. sendMsg("Hi Bob!", tctx->aliceInternalIf);
  200. sendMsg("Hi Alice!", tctx->bobInternalIf);
  201. Interface_receiveMessage(&tctx->aliceExternalIf, tctx->bobCryptMsg);
  202. Interface_receiveMessage(&tctx->bobExternalIf, tctx->aliceCryptMsg);
  203. sendToBob("hello bob", tctx);
  204. sendToAlice("hi alice", tctx);
  205. sendToBob("and we're established", tctx);
  206. sendToAlice("ok shutdown", tctx);
  207. Assert_always(CryptoAuth_getState(tctx->bobInternalIf) == CryptoAuth_ESTABLISHED);
  208. Assert_always(CryptoAuth_getState(tctx->aliceInternalIf) == CryptoAuth_ESTABLISHED);
  209. }
  210. static void replayKeyPacket(struct Allocator* alloc, struct Context* ctx)
  211. {
  212. struct TestContext* tctx = setUp(alloc, ctx, false);
  213. sendToBob("hello bob", tctx);
  214. sendMsg("Hi Alice!", tctx->bobInternalIf);
  215. struct Message* toReplay = Message_clone(tctx->bobCryptMsg, alloc);
  216. Interface_receiveMessage(&tctx->aliceExternalIf, tctx->bobCryptMsg);
  217. sendMsg("Hi Bob!", tctx->aliceInternalIf);
  218. struct Message* m1 = tctx->aliceCryptMsg;
  219. // packet replay
  220. Interface_receiveMessage(&tctx->aliceExternalIf, toReplay);
  221. sendMsg("Hi Bob!", tctx->aliceInternalIf);
  222. struct Message* m2 = tctx->aliceCryptMsg;
  223. Assert_always(Bits_memcmp(m1->bytes, m2->bytes, 4));
  224. }
  225. int main()
  226. {
  227. struct Allocator* alloc = MallocAllocator_new(1<<22);
  228. struct Log* logger = FileWriterLog_new(stdout, alloc);
  229. struct Random* rand = Random_new(alloc, logger, NULL);
  230. struct EventBase* eventBase = EventBase_new(alloc);
  231. struct Context ctx = {
  232. .base = eventBase,
  233. .rand = rand,
  234. .logger = logger
  235. };
  236. replayKeyPacket(alloc, &ctx);
  237. return 0;
  238. crossedOnTheWire(alloc, &ctx);
  239. twoKeyPackets(alloc, &ctx);
  240. reset(alloc, &ctx);
  241. return 0;
  242. }