CryptoAuth_test.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  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/Ca.h"
  17. #include "crypto/CryptoAuth.h"
  18. #include "benc/String.h"
  19. #include "memory/Allocator.h"
  20. #include "util/events/EventBase.h"
  21. #include "util/Assert.h"
  22. #include "util/Bits.h"
  23. #include "util/Hex.h"
  24. #include "util/Endian.h"
  25. #include "util/log/FileWriterLog.h"
  26. #include "wire/CryptoHeader.h"
  27. #include "crypto/test/TestCa.h"
  28. #include "crypto/random/test/DeterminentRandomSeed.h"
  29. #include "util/CString.h"
  30. // console.log(x.replace(/[0-9a-f]{2}/g, (x)=>'\\x'+x))
  31. #define PRIVATEKEY_A \
  32. "\x53\xff\x22\xb2\xeb\x94\xce\x8c\x5f\x18\x52\xc0\xf5\x57\xeb\x90\x1f\x06\x7e\x52\x73\xd5\x41\xe0\xa2\x1e\x14\x3c\x20\xdf\xf9\xda"
  33. // "53ff22b2eb94ce8c5f1852c0f557eb901f067e5273d541e0a21e143c20dff9da"
  34. #define PUBLICKEY_A \
  35. "\xe3\xff\x75\xaf\x6e\x44\x14\x49\x4d\xf2\x2f\x20\x0f\xfe\xaa\x56\xe7\x97\x6d\x99\x1d\x33\xcc\x87\xf5\x24\x27\xe2\x7f\x83\x23\x5d"
  36. // "e3ff75af6e4414494df22f200ffeaa56e7976d991d33cc87f52427e27f83235d"
  37. #define PRIVATEKEY_B \
  38. "\xb7\x1c\x4f\x43\xe3\xd4\xb1\x87\x9b\x50\x65\xd4\x4a\x1c\xb4\x3e\xaf\x07\xdd\xba\x96\xde\x6a\x72\xca\x76\x1c\x4e\xf4\xbd\x29\x88"
  39. // "b71c4f43e3d4b1879b5065d44a1cb43eaf07ddba96de6a72ca761c4ef4bd2988"
  40. #define PUBLICKEY_B \
  41. "\x27\xc3\x03\xcd\xc1\xf9\x6e\x4b\x28\xd5\x1c\x75\x13\x0a\xff\x6c\xad\x52\x09\x8f\x2d\x75\x26\x15\xb7\xb6\x50\x9e\xd6\xa8\x94\x77"
  42. // "27c303cdc1f96e4b28d51c75130aff6cad52098f2d752615b7b6509ed6a89477"
  43. #define USEROBJ "This represents a user"
  44. struct Node
  45. {
  46. TestCa_t* ca;
  47. TestCa_Session_t* sess;
  48. struct Iface plaintext;
  49. struct Iface ciphertext;
  50. const char* expectPlaintext;
  51. enum CryptoAuth_DecryptErr expectErr;
  52. struct Log* log;
  53. Identity
  54. };
  55. struct Context
  56. {
  57. struct Node node1;
  58. struct Node node2;
  59. struct Allocator* alloc;
  60. struct Log* log;
  61. EventBase_t* base;
  62. Identity
  63. };
  64. static struct Random* evilRandom(struct Allocator* alloc, struct Log* logger, const char* seed)
  65. {
  66. uint8_t buf[64] = {0};
  67. Assert_true(CString_strlen(seed) < 60);
  68. CString_strcpy(buf, seed);
  69. RandomSeed_t* evilSeed = DeterminentRandomSeed_new(alloc, buf);
  70. struct Random* out = NULL;
  71. Err_assert(Random_newWithSeed(&out, alloc, logger, evilSeed));
  72. return out;
  73. }
  74. static Iface_DEFUN afterDecrypt(Message_t* msg, struct Iface* if1)
  75. {
  76. struct Node* n = Identity_containerOf(if1, struct Node, plaintext);
  77. Log_debug(n->log, "Got message from afterDecrypt");
  78. enum CryptoAuth_DecryptErr e = 0;
  79. Err(Message_epop32h(&e, msg));
  80. if (e != n->expectErr) {
  81. Assert_failure("expected decrypt error [%d], got [%d]\n", n->expectErr, e);
  82. }
  83. n->expectErr = CryptoAuth_DecryptErr_NONE;
  84. if (!n->expectPlaintext) {
  85. if (e) {
  86. return NULL;
  87. }
  88. Assert_failure("expected <NULL>, got [%s](%d)\n", Message_bytes(msg), Message_getLength(msg));
  89. }
  90. if ((int)CString_strlen(n->expectPlaintext) != Message_getLength(msg) ||
  91. CString_strncmp(Message_bytes(msg), n->expectPlaintext, Message_getLength(msg)))
  92. {
  93. Assert_failure("expected [%s](%d), got [%s](%d)\n",
  94. n->expectPlaintext, (int)CString_strlen(n->expectPlaintext), Message_bytes(msg), Message_getLength(msg));
  95. }
  96. n->expectPlaintext = NULL;
  97. return NULL;
  98. }
  99. static Iface_DEFUN afterEncrypt(Message_t* msg, struct Iface* if1)
  100. {
  101. return NULL;
  102. }
  103. static struct Context* init(uint8_t* privateKeyA,
  104. uint8_t* publicKeyA,
  105. uint8_t* password,
  106. uint8_t* privateKeyB,
  107. uint8_t* publicKeyB,
  108. enum TestCa_Config cfg)
  109. {
  110. struct Allocator* alloc = Allocator_new(1048576);
  111. struct Context* ctx = Allocator_calloc(alloc, sizeof(struct Context), 1);
  112. Identity_set(ctx);
  113. Identity_set(&ctx->node1);
  114. Identity_set(&ctx->node2);
  115. ctx->alloc = alloc;
  116. ctx->node1.plaintext.send = afterDecrypt;
  117. ctx->node2.plaintext.send = afterDecrypt;
  118. ctx->node1.ciphertext.send = afterEncrypt;
  119. ctx->node2.ciphertext.send = afterEncrypt;
  120. struct Log* logger = ctx->log = FileWriterLog_new(stdout, alloc);
  121. struct Random* randA = evilRandom(alloc, logger, "ALPHA");
  122. struct Random* randB = evilRandom(alloc, logger, "ALPHA");
  123. struct Random* randC = evilRandom(alloc, logger, "BRAVO");
  124. struct Random* randD = evilRandom(alloc, logger, "BRAVO");
  125. EventBase_t* base = ctx->base = EventBase_new(alloc);
  126. ctx->node1.log = logger;
  127. ctx->node2.log = logger;
  128. ctx->node1.ca = TestCa_new(alloc, privateKeyA, base, logger, randA, randB, cfg);
  129. ctx->node1.sess = TestCa_newSession(ctx->node1.ca, alloc, publicKeyB, false, "cif1", true);
  130. ctx->node2.ca = TestCa_new(alloc, privateKeyB, base, logger, randC, randD, cfg);
  131. if (password) {
  132. String* passStr = String_CONST(password);
  133. TestCa_setAuth(passStr, NULL, ctx->node1.sess);
  134. TestCa_addUser_ipv6(passStr, String_new(USEROBJ, alloc), NULL, ctx->node2.ca);
  135. }
  136. ctx->node2.sess = TestCa_newSession(ctx->node2.ca, alloc, publicKeyA, false, "cif2", true);
  137. Iface_plumb(&ctx->node1.sess->plaintext, &ctx->node1.plaintext);
  138. Iface_plumb(&ctx->node1.sess->ciphertext, &ctx->node1.ciphertext);
  139. Iface_plumb(&ctx->node2.sess->plaintext, &ctx->node2.plaintext);
  140. Iface_plumb(&ctx->node2.sess->ciphertext, &ctx->node2.ciphertext);
  141. return ctx;
  142. }
  143. static struct Context* simpleInit(enum TestCa_Config cfg)
  144. {
  145. return init(PRIVATEKEY_A, PUBLICKEY_A, NULL, PRIVATEKEY_B, PUBLICKEY_B, cfg);
  146. }
  147. static Message_t* encryptMsg(struct Context* ctx,
  148. struct Node* n,
  149. const char* x)
  150. {
  151. struct Allocator* alloc = Allocator_child(ctx->alloc);
  152. int len = (((CString_strlen(x)+1) / 8) + 1) * 8;
  153. Message_t* msg = Message_new(len, CryptoHeader_SIZE + 32, alloc);
  154. CString_strcpy(Message_bytes(msg), x);
  155. Err_assert(Message_truncate(msg, CString_strlen(x)));
  156. //msg->bytes[Message_getLength(msg)] = 0;
  157. struct RTypes_Error_t* e = Iface_send(&n->plaintext, msg);
  158. if (e) {
  159. printf("%s\n", Rffi_printError(e, ctx->alloc));
  160. Assert_failure("error was not null");
  161. }
  162. Assert_true(Message_getLength(msg) > ((int)CString_strlen(x) + 4));
  163. return msg;
  164. }
  165. static Message_t* decryptMsg(struct Context* ctx,
  166. Message_t* msg,
  167. struct Node* n,
  168. const char* expectResult,
  169. enum CryptoAuth_DecryptErr expectErr)
  170. {
  171. Assert_true(!n->expectPlaintext && !n->expectErr);
  172. n->expectPlaintext = expectResult;
  173. n->expectErr = expectErr;
  174. Err_assert(Message_epush(msg, NULL, 16)); // peer ipv6
  175. Iface_send(&n->ciphertext, msg);
  176. Assert_true(!n->expectPlaintext && !n->expectErr);
  177. return msg;
  178. }
  179. static void sendToIf1(struct Context* ctx, const char* x)
  180. {
  181. Message_t* msg = encryptMsg(ctx, &ctx->node2, x);
  182. decryptMsg(ctx, msg, &ctx->node1, x, CryptoAuth_DecryptErr_NONE);
  183. Allocator_free(Message_getAlloc(msg));
  184. }
  185. static void sendToIf2(struct Context* ctx, const char* x)
  186. {
  187. Message_t* msg = encryptMsg(ctx, &ctx->node1, x);
  188. decryptMsg(ctx, msg, &ctx->node2, x, CryptoAuth_DecryptErr_NONE);
  189. Allocator_free(Message_getAlloc(msg));
  190. }
  191. static void normal(enum TestCa_Config cfg)
  192. {
  193. struct Context* ctx = simpleInit(cfg);
  194. sendToIf2(ctx, "hello world");
  195. sendToIf1(ctx, "hello cjdns");
  196. sendToIf2(ctx, "hai");
  197. sendToIf1(ctx, "goodbye");
  198. Allocator_free(ctx->alloc);
  199. }
  200. static void repeatKey(enum TestCa_Config cfg)
  201. {
  202. struct Context* ctx = simpleInit(cfg);
  203. sendToIf2(ctx, "hello world");
  204. sendToIf2(ctx, "r u thar?");
  205. sendToIf1(ctx, "hello cjdns");
  206. sendToIf2(ctx, "hai");
  207. sendToIf1(ctx, "goodbye");
  208. Allocator_free(ctx->alloc);
  209. }
  210. static void repeatHello(enum TestCa_Config cfg)
  211. {
  212. struct Context* ctx = simpleInit(cfg);
  213. sendToIf2(ctx, "hello world");
  214. sendToIf2(ctx, "r u thar?");
  215. sendToIf1(ctx, "hello cjdns");
  216. sendToIf2(ctx, "hai");
  217. sendToIf1(ctx, "goodbye");
  218. Allocator_free(ctx->alloc);
  219. }
  220. static void chatter(enum TestCa_Config cfg)
  221. {
  222. struct Context* ctx = simpleInit(cfg);
  223. sendToIf2(ctx, "hello world");
  224. sendToIf1(ctx, "hello cjdns");
  225. sendToIf2(ctx, "hai");
  226. sendToIf1(ctx, "goodbye");
  227. sendToIf1(ctx, "hello cjdns");
  228. sendToIf2(ctx, "hai");
  229. sendToIf1(ctx, "goodbye");
  230. sendToIf1(ctx, "hello cjdns");
  231. sendToIf2(ctx, "hai");
  232. sendToIf1(ctx, "goodbye");
  233. sendToIf1(ctx, "hello cjdns");
  234. sendToIf2(ctx, "hai");
  235. sendToIf1(ctx, "goodbye");
  236. Allocator_free(ctx->alloc);
  237. }
  238. static void auth(enum TestCa_Config cfg)
  239. {
  240. struct Context* ctx = init(
  241. PRIVATEKEY_A, PUBLICKEY_A, "password", PRIVATEKEY_B, PUBLICKEY_B, cfg);
  242. sendToIf2(ctx, "hello world");
  243. sendToIf1(ctx, "hello cjdns");
  244. sendToIf2(ctx, "hai");
  245. sendToIf1(ctx, "goodbye");
  246. Allocator_free(ctx->alloc);
  247. }
  248. static void replayKeyPacket(int scenario, enum TestCa_Config cfg)
  249. {
  250. struct Context* ctx = simpleInit(cfg);
  251. sendToIf2(ctx, "hello world");
  252. Message_t* msg = encryptMsg(ctx, &ctx->node2, "hello replay key");
  253. Message_t* toReplay = Message_clone(msg, ctx->alloc);
  254. decryptMsg(ctx, msg, &ctx->node1, "hello replay key", CryptoAuth_DecryptErr_NONE);
  255. if (scenario == 1) {
  256. // the packet is failed because we know it's a dupe from the temp key.
  257. decryptMsg(ctx, toReplay, &ctx->node1, NULL, CryptoAuth_DecryptErr_INVALID_PACKET);
  258. }
  259. sendToIf2(ctx, "first traffic packet");
  260. if (scenario == 2) {
  261. decryptMsg(ctx, toReplay, &ctx->node1, NULL, CryptoAuth_DecryptErr_INVALID_PACKET);
  262. }
  263. sendToIf1(ctx, "second traffic packet");
  264. if (scenario == 3) {
  265. // If we replay at this stage, the packet is dropped as a stray key
  266. decryptMsg(ctx, toReplay, &ctx->node1, NULL, CryptoAuth_DecryptErr_KEY_PKT_ESTABLISHED_SESSION);
  267. }
  268. Allocator_free(ctx->alloc);
  269. }
  270. /**
  271. * Alice and Bob both decided they wanted to talk to eachother at precisely the same time.
  272. * This means two Hello packets crossed on the wire. Both arrived at their destination but
  273. * if each triggers a re-initialization of the CA session, nobody will be synchronized!
  274. */
  275. static void hellosCrossedOnTheWire(enum TestCa_Config cfg)
  276. {
  277. struct Context* ctx = simpleInit(cfg);
  278. uint8_t pk1[32];
  279. TestCa_getPubKey(ctx->node1.ca, pk1);
  280. uint8_t hpk2[32];
  281. TestCa_getHerPubKey(ctx->node2.sess, hpk2);
  282. Assert_true(!Bits_memcmp(pk1, hpk2, 32));
  283. Message_t* hello2 = encryptMsg(ctx, &ctx->node2, "hello2");
  284. Message_t* hello1 = encryptMsg(ctx, &ctx->node1, "hello1");
  285. decryptMsg(ctx, hello2, &ctx->node1, "hello2", 0);
  286. decryptMsg(ctx, hello1, &ctx->node2, "hello1", 0);
  287. sendToIf2(ctx, "hello world");
  288. sendToIf1(ctx, "hello cjdns");
  289. sendToIf2(ctx, "hai");
  290. sendToIf1(ctx, "goodbye");
  291. Allocator_free(ctx->alloc);
  292. }
  293. static void reset(enum TestCa_Config cfg)
  294. {
  295. struct Context* ctx = simpleInit(cfg);
  296. sendToIf2(ctx, "hello world");
  297. sendToIf1(ctx, "hello cjdns");
  298. sendToIf2(ctx, "hai");
  299. sendToIf1(ctx, "brb");
  300. Assert_true(TestCa_getState(ctx->node1.sess) == CryptoAuth_State_ESTABLISHED);
  301. Assert_true(TestCa_getState(ctx->node2.sess) == CryptoAuth_State_ESTABLISHED);
  302. TestCa_reset(ctx->node1.sess);
  303. // sess2 still talking to sess1 but sess1 is reset and cannot read the packets.
  304. decryptMsg(ctx, encryptMsg(ctx, &ctx->node2, "will be lost"), &ctx->node1, NULL,
  305. CryptoAuth_DecryptErr_NO_SESSION);
  306. decryptMsg(ctx, encryptMsg(ctx, &ctx->node2, "lost"), &ctx->node1, NULL,
  307. CryptoAuth_DecryptErr_NO_SESSION);
  308. // This is because we want to prevent replay attacks from tearing down a session.
  309. decryptMsg(ctx, encryptMsg(ctx, &ctx->node1, "hello"), &ctx->node2, "hello", 0);
  310. sendToIf1(ctx, "hello again");
  311. sendToIf2(ctx, "hai");
  312. sendToIf1(ctx, "ok works");
  313. sendToIf2(ctx, "yup");
  314. Assert_true(TestCa_getState(ctx->node1.sess) == CryptoAuth_State_ESTABLISHED);
  315. Assert_true(TestCa_getState(ctx->node2.sess) == CryptoAuth_State_ESTABLISHED);
  316. Allocator_free(ctx->alloc);
  317. }
  318. // This is slightly different from replayKeyPacket because the second key packet is valid,
  319. // it's just delayed.
  320. static void twoKeyPackets(int scenario, enum TestCa_Config cfg)
  321. {
  322. struct Context* ctx = simpleInit(cfg);
  323. sendToIf2(ctx, "hello world");
  324. sendToIf1(ctx, "key packet 1");
  325. Message_t* key2 = encryptMsg(ctx, &ctx->node2, "key packet 2");
  326. if (scenario == 1) {
  327. sendToIf1(ctx, "key packet 3");
  328. decryptMsg(ctx, key2, &ctx->node1, "key packet 2", 0);
  329. } else if (scenario == 2) {
  330. sendToIf2(ctx, "initial data packet");
  331. decryptMsg(ctx, key2, &ctx->node1, "key packet 2", 0);
  332. sendToIf1(ctx, "second data packet");
  333. sendToIf2(ctx, "third data packet");
  334. } else if (scenario == 3) {
  335. sendToIf2(ctx, "initial data packet");
  336. sendToIf1(ctx, "second data packet");
  337. decryptMsg(ctx, key2, &ctx->node1, NULL, CryptoAuth_DecryptErr_KEY_PKT_ESTABLISHED_SESSION);
  338. }
  339. Allocator_free(ctx->alloc);
  340. }
  341. static void iteration(enum TestCa_Config cfg)
  342. {
  343. normal(cfg);
  344. repeatKey(cfg);
  345. repeatHello(cfg);
  346. chatter(cfg);
  347. auth(cfg);
  348. replayKeyPacket(1, cfg);
  349. replayKeyPacket(2, cfg);
  350. replayKeyPacket(3, cfg);
  351. hellosCrossedOnTheWire(cfg);
  352. reset(cfg);
  353. twoKeyPackets(1, cfg);
  354. twoKeyPackets(2, cfg);
  355. twoKeyPackets(3, cfg);
  356. }
  357. int main()
  358. {
  359. iteration(TestCa_Config_OLD);
  360. iteration(TestCa_Config_OLD_NEW);
  361. //iteration(TestCa_Config_NOISE); // TODO(cjd): re-enable this
  362. return 0;
  363. }