CryptoAuth_test.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  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 "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 ( \
  27. "\x20\xca\x45\xd9\x5b\xbf\xca\xe7\x35\x3c\xd2\xdf\xfa\x12\x84\x4b" \
  28. "\x4e\xff\xbe\x7d\x39\xd8\x4d\x8e\x14\x2b\x9d\x21\x89\x5b\x38\x09" )
  29. #define PUBLICKEY ( \
  30. "\x51\xaf\x8d\xd9\x35\xe8\x61\x86\x3e\x94\x2b\x1b\x6d\x21\x22\xe0" \
  31. "\x2f\xb2\xd0\x88\x20\xbb\xf3\xf0\x6f\xcd\xe5\x85\x30\xe0\x08\x34" )
  32. #define USEROBJ "This represents a user"
  33. struct Context
  34. {
  35. struct CryptoAuth* ca1;
  36. struct CryptoAuth_Session* sess1;
  37. struct CryptoAuth* ca2;
  38. struct CryptoAuth_Session* sess2;
  39. struct Allocator* alloc;
  40. struct Log* log;
  41. struct Random* rand;
  42. struct EventBase* base;
  43. };
  44. static struct Context* init(uint8_t* privateKey, uint8_t* herPublicKey, uint8_t* password)
  45. {
  46. struct Allocator* alloc = MallocAllocator_new(1048576);
  47. struct Context* ctx = Allocator_calloc(alloc, sizeof(struct Context), 1);
  48. ctx->alloc = alloc;
  49. struct Log* logger = ctx->log = FileWriterLog_new(stdout, alloc);
  50. struct Random* rand = ctx->rand = Random_new(alloc, logger, NULL);
  51. struct EventBase* base = ctx->base = EventBase_new(alloc);
  52. ctx->ca1 = CryptoAuth_new(alloc, NULL, base, logger, rand);
  53. ctx->sess1 = CryptoAuth_newSession(ctx->ca1, alloc, herPublicKey, NULL, false, "cif1");
  54. ctx->ca2 = CryptoAuth_new(alloc, privateKey, base, logger, rand);
  55. if (password) {
  56. String* passStr = String_CONST(password);
  57. CryptoAuth_setAuth(passStr, 1, ctx->sess1);
  58. CryptoAuth_addUser(passStr, 1, String_new(USEROBJ, alloc), ctx->ca2);
  59. }
  60. ctx->sess2 = CryptoAuth_newSession(ctx->ca2, alloc, NULL, NULL, false, "cif2");
  61. return ctx;
  62. }
  63. static struct Context* simpleInit()
  64. {
  65. return init(PRIVATEKEY, PUBLICKEY, NULL);
  66. }
  67. static struct Message* encryptMsg(struct Context* ctx,
  68. struct CryptoAuth_Session* encryptWith,
  69. const char* x)
  70. {
  71. struct Allocator* alloc = Allocator_child(ctx->alloc);
  72. int len = (((CString_strlen(x)+1) / 8) + 1) * 8;
  73. struct Message* msg = Message_new(len, CryptoHeader_SIZE, alloc);
  74. CString_strcpy(msg->bytes, x);
  75. msg->length = CString_strlen(x);
  76. msg->bytes[msg->length] = 0;
  77. Assert_true(!CryptoAuth_encrypt(encryptWith, msg));
  78. Assert_true(msg->length > ((int)CString_strlen(x) + 4));
  79. return msg;
  80. }
  81. static void decryptMsg(struct Context* ctx,
  82. struct Message* msg,
  83. struct CryptoAuth_Session* decryptWith,
  84. const char* x)
  85. {
  86. if (!x) {
  87. // x is null implying it is expected to fail.
  88. Assert_true(CryptoAuth_decrypt(decryptWith, msg));
  89. } else {
  90. Assert_true(!CryptoAuth_decrypt(decryptWith, msg));
  91. if ((int)CString_strlen(x) != msg->length ||
  92. CString_strncmp(msg->bytes, x, msg->length))
  93. {
  94. Assert_failure("expected [%s](%d), got [%s](%d)\n",
  95. x, (int)CString_strlen(x), msg->bytes, msg->length);
  96. }
  97. }
  98. }
  99. static void sendToIf1(struct Context* ctx, const char* x)
  100. {
  101. struct Message* msg = encryptMsg(ctx, ctx->sess2, x);
  102. decryptMsg(ctx, msg, ctx->sess1, x);
  103. Allocator_free(msg->alloc);
  104. }
  105. static void sendToIf2(struct Context* ctx, const char* x)
  106. {
  107. struct Message* msg = encryptMsg(ctx, ctx->sess1, x);
  108. decryptMsg(ctx, msg, ctx->sess2, x);
  109. Allocator_free(msg->alloc);
  110. }
  111. static void normal()
  112. {
  113. struct Context* ctx = simpleInit();
  114. sendToIf2(ctx, "hello world");
  115. sendToIf1(ctx, "hello cjdns");
  116. sendToIf2(ctx, "hai");
  117. sendToIf1(ctx, "goodbye");
  118. Allocator_free(ctx->alloc);
  119. }
  120. static void repeatKey()
  121. {
  122. struct Context* ctx = simpleInit();
  123. sendToIf2(ctx, "hello world");
  124. sendToIf2(ctx, "r u thar?");
  125. sendToIf1(ctx, "hello cjdns");
  126. sendToIf2(ctx, "hai");
  127. sendToIf1(ctx, "goodbye");
  128. Allocator_free(ctx->alloc);
  129. }
  130. static void repeatHello()
  131. {
  132. struct Context* ctx = simpleInit();
  133. sendToIf2(ctx, "hello world");
  134. sendToIf2(ctx, "r u thar?");
  135. sendToIf1(ctx, "hello cjdns");
  136. sendToIf2(ctx, "hai");
  137. sendToIf1(ctx, "goodbye");
  138. Allocator_free(ctx->alloc);
  139. }
  140. static void chatter()
  141. {
  142. struct Context* ctx = simpleInit();
  143. sendToIf2(ctx, "hello world");
  144. sendToIf1(ctx, "hello cjdns");
  145. sendToIf2(ctx, "hai");
  146. sendToIf1(ctx, "goodbye");
  147. sendToIf1(ctx, "hello cjdns");
  148. sendToIf2(ctx, "hai");
  149. sendToIf1(ctx, "goodbye");
  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. Allocator_free(ctx->alloc);
  157. }
  158. static void auth()
  159. {
  160. struct Context* ctx = init(PRIVATEKEY, PUBLICKEY, "password");
  161. sendToIf2(ctx, "hello world");
  162. sendToIf1(ctx, "hello cjdns");
  163. sendToIf2(ctx, "hai");
  164. sendToIf1(ctx, "goodbye");
  165. Allocator_free(ctx->alloc);
  166. }
  167. static void replayKeyPacket(int scenario)
  168. {
  169. struct Context* ctx = simpleInit();
  170. sendToIf2(ctx, "hello world");
  171. struct Message* msg = encryptMsg(ctx, ctx->sess2, "hello replay key");
  172. struct Message* toReplay = Message_clone(msg, ctx->alloc);
  173. decryptMsg(ctx, msg, ctx->sess1, "hello replay key");
  174. if (scenario == 1) {
  175. // the packet is failed because we know it's a dupe from the temp key.
  176. decryptMsg(ctx, toReplay, ctx->sess1, NULL);
  177. }
  178. sendToIf2(ctx, "first traffic packet");
  179. if (scenario == 2) {
  180. decryptMsg(ctx, toReplay, ctx->sess1, NULL);
  181. }
  182. sendToIf1(ctx, "second traffic packet");
  183. if (scenario == 3) {
  184. // If we replay at this stage, the packet is dropped as a stray key
  185. decryptMsg(ctx, toReplay, ctx->sess1, NULL);
  186. }
  187. Allocator_free(ctx->alloc);
  188. }
  189. /**
  190. * Alice and Bob both decided they wanted to talk to eachother at precisely the same time.
  191. * This means two Hello packets crossed on the wire. Both arrived at their destination but
  192. * if each triggers a re-initialization of the CA session, nobody will be synchronized!
  193. */
  194. static void hellosCrossedOnTheWire()
  195. {
  196. struct Context* ctx = simpleInit();
  197. Bits_memcpyConst(ctx->sess2->herPublicKey, ctx->ca1->publicKey, 32);
  198. struct Message* hello2 = encryptMsg(ctx, ctx->sess2, "hello2");
  199. struct Message* hello1 = encryptMsg(ctx, ctx->sess1, "hello1");
  200. decryptMsg(ctx, hello2, ctx->sess1, "hello2");
  201. decryptMsg(ctx, hello1, ctx->sess2, "hello1");
  202. sendToIf2(ctx, "hello world");
  203. sendToIf1(ctx, "hello cjdns");
  204. sendToIf2(ctx, "hai");
  205. sendToIf1(ctx, "goodbye");
  206. Allocator_free(ctx->alloc);
  207. }
  208. static void reset()
  209. {
  210. struct Context* ctx = simpleInit();
  211. sendToIf2(ctx, "hello world");
  212. sendToIf1(ctx, "hello cjdns");
  213. sendToIf2(ctx, "hai");
  214. sendToIf1(ctx, "brb");
  215. Assert_true(CryptoAuth_getState(ctx->sess1) == CryptoAuth_ESTABLISHED);
  216. Assert_true(CryptoAuth_getState(ctx->sess2) == CryptoAuth_ESTABLISHED);
  217. CryptoAuth_reset(ctx->sess1);
  218. // sess2 still talking to sess1 but sess1 is reset and cannot read the packets.
  219. decryptMsg(ctx, encryptMsg(ctx, ctx->sess2, "will be lost"), ctx->sess1, NULL);
  220. decryptMsg(ctx, encryptMsg(ctx, ctx->sess2, "lost"), ctx->sess1, NULL);
  221. // This is because we want to prevent replay attacks from tearing down a session.
  222. decryptMsg(ctx, encryptMsg(ctx, ctx->sess1, "hello"), ctx->sess2, "hello");
  223. sendToIf1(ctx, "hello again");
  224. sendToIf2(ctx, "hai");
  225. sendToIf1(ctx, "ok works");
  226. sendToIf2(ctx, "yup");
  227. Assert_true(CryptoAuth_getState(ctx->sess1) == CryptoAuth_ESTABLISHED);
  228. Assert_true(CryptoAuth_getState(ctx->sess2) == CryptoAuth_ESTABLISHED);
  229. Allocator_free(ctx->alloc);
  230. }
  231. // This is slightly different from replayKeyPacket because the second key packet is valid,
  232. // it's just delayed.
  233. static void twoKeyPackets(int scenario)
  234. {
  235. struct Context* ctx = simpleInit();
  236. sendToIf2(ctx, "hello world");
  237. sendToIf1(ctx, "key packet 1");
  238. struct Message* key2 = encryptMsg(ctx, ctx->sess2, "key packet 2");
  239. if (scenario == 1) {
  240. sendToIf1(ctx, "key packet 3");
  241. decryptMsg(ctx, key2, ctx->sess1, "key packet 2");
  242. } else if (scenario == 2) {
  243. sendToIf2(ctx, "initial data packet");
  244. decryptMsg(ctx, key2, ctx->sess1, "key packet 2");
  245. sendToIf1(ctx, "second data packet");
  246. sendToIf2(ctx, "third data packet");
  247. } else if (scenario == 3) {
  248. sendToIf2(ctx, "initial data packet");
  249. sendToIf1(ctx, "second data packet");
  250. decryptMsg(ctx, key2, ctx->sess1, NULL);
  251. }
  252. Allocator_free(ctx->alloc);
  253. }
  254. int main()
  255. {
  256. normal();
  257. repeatKey();
  258. repeatHello();
  259. chatter();
  260. auth();
  261. replayKeyPacket(1);
  262. replayKeyPacket(2);
  263. replayKeyPacket(3);
  264. hellosCrossedOnTheWire();
  265. reset();
  266. twoKeyPackets(1);
  267. twoKeyPackets(2);
  268. twoKeyPackets(3);
  269. return 0;
  270. }