]> gitweb.ps.run Git - matrix_esp_thesis/blob - esp32/esp_project/main/Verify.c
update esp_project
[matrix_esp_thesis] / esp32 / esp_project / main / Verify.c
1 #include <matrix.h>
2 #include <mjson.h>
3 #include <olm/sas.h>
4
5 #if !CONFIG_IDF_TARGET_LINUX
6 #include "freertos/FreeRTOS.h"
7 #include "freertos/task.h"
8 #include "esp_system.h"
9 #include "driver/gpio.h"
10 #endif
11
12 #include <stdio.h>
13
14 #define SERVER       "https://matrix.org"
15 #define USER_ID      "@pscho:matrix.org"
16
17 #define DEVICE_ID    "ULZZOKJBYN"
18 #define SENDER_KEY   "cjP41XzRlY+pd8DoiBuKQJj9o15mrx6gkrpqTkAPZ2c"
19 #define ROOM_ID      "!XKFUjAsGrSSrpDFIxB:matrix.org"
20 #define EVENT_ID     "$vOS09eUaI0CduqAcaIU5ZVk6ljLQfLspz7UThP8vaUM"
21 #define SESSION_ID   "90UbGLue3ADVhvW7hFjoA2c6yg0JJKs/lPdMDZXnZAk"
22
23 // main stack size: 3584
24
25 bool verified = false;
26 char transactionId[64];
27 OlmSAS * olmSas = NULL;
28
29 #define STATIC static
30
31 STATIC char encrypted[2048];
32 STATIC char decrypted[2048];
33
34 void
35 HandleEvent(
36     MatrixClient * client,
37     const char * event, int eventLen
38 ) {
39     STATIC char eventType[128];
40     memset(eventType, 0, sizeof(eventType));
41     mjson_get_string(event, eventLen, "$.type", eventType, 128);
42
43     if (strcmp(eventType, "m.key.verification.request") == 0) {
44         mjson_get_string(event, eventLen, "$.content.transaction_id", transactionId, 256);
45         
46         char verificationReadyBuffer[2048];
47         snprintf(verificationReadyBuffer, 2048,
48             "{"
49             "\"from_device\":\"%s\","
50             "\"methods\":[\"m.sas.v1\"],"
51             "\"transaction_id\":\"%s\""
52             "}",
53             client->deviceId,
54             transactionId);
55         
56         MatrixClientSendToDevice(client,
57             USER_ID,
58             DEVICE_ID,
59             verificationReadyBuffer,
60             "m.key.verification.ready");
61     }
62     else if (strcmp(eventType, "m.key.verification.start") == 0) {
63         olmSas = olm_sas(malloc(olm_sas_size()));
64         void * sasRandomBytes = malloc(olm_create_sas_random_length(olmSas));
65         olm_create_sas(olmSas,
66             sasRandomBytes,
67             olm_create_sas_random_length(olmSas));
68         
69         OlmUtility * olmUtil = olm_utility(malloc(olm_utility_size()));
70         
71         STATIC char publicKey[64];
72         STATIC char keyStartJsonCanonical[512];
73         STATIC char concat[512+64];
74         STATIC char commitment[1024];
75         olm_sas_get_pubkey(olmSas,
76             publicKey,
77             64);
78         printf("public key: %.*s\n", olm_sas_pubkey_length(olmSas), publicKey);
79
80         const char * keyStartJson;
81         int keyStartJsonLen;
82         mjson_find(event, eventLen, "$.content", &keyStartJson, &keyStartJsonLen);
83         JsonCanonicalize(keyStartJson, keyStartJsonLen, keyStartJsonCanonical, 512);
84
85         printf("json:\n%.*s\ncanonical json:\n%s\n", keyStartJsonLen, keyStartJson, keyStartJsonCanonical);
86
87         int concatLen =
88             snprintf(concat, 512+64, "%.*s%s", olm_sas_pubkey_length(olmSas), publicKey, keyStartJsonCanonical);
89
90         int commitmentLen =
91             olm_sha256(olmUtil, concat, concatLen, commitment, 1024);
92         
93         STATIC char verificationAcceptBuffer[512];
94         snprintf(verificationAcceptBuffer, 512,
95             "{"
96             "\"commitment\":\"%.*s\","
97             "\"hash\":\"sha256\","
98             "\"key_agreement_protocol\":\"curve25519\","
99             "\"message_authentication_code\":\"hkdf-hmac-sha256.v2\","
100             "\"method\":\"m.sas.v1\","
101             "\"short_authentication_string\":[\"decimal\"],"
102             "\"transaction_id\":\"%s\""
103             "}",
104             commitmentLen, commitment,
105             transactionId);
106         
107         MatrixClientSendToDevice(client,
108             USER_ID,
109             DEVICE_ID,
110             verificationAcceptBuffer,
111             "m.key.verification.accept");
112     }
113     else if (strcmp(eventType, "m.key.verification.key") == 0) {
114         STATIC char publicKey[128];
115         olm_sas_get_pubkey(olmSas,
116             publicKey,
117             128);
118
119         STATIC char theirPublicKey[128];
120         int theirPublicKeyLen =
121             mjson_get_string(event, eventLen, "$.content.key", theirPublicKey, 128);
122         
123         printf("event: %.*s\n", eventLen, event);
124         printf("theirPublicKey: %.*s\n", theirPublicKeyLen, theirPublicKey);
125         printf("publicKey: %.*s\n", olm_sas_pubkey_length(olmSas), publicKey);
126
127         olm_sas_set_their_key(olmSas, theirPublicKey, theirPublicKeyLen);
128         
129         STATIC char verificationKeyBuffer[256];
130         snprintf(verificationKeyBuffer, 256,
131             "{"
132             "\"key\":\"%.*s\","
133             "\"transaction_id\":\"%s\""
134             "}",
135             olm_sas_pubkey_length(olmSas), publicKey,
136             transactionId);
137         
138         MatrixClientSendToDevice(client,
139             USER_ID,
140             DEVICE_ID,
141             verificationKeyBuffer,
142             "m.key.verification.key");
143         
144         // sas
145         STATIC char hkdfInfo[1024];
146         int hkdfInfoLen =
147             snprintf(hkdfInfo, 1024,
148                 "MATRIX_KEY_VERIFICATION_SAS%s%s%s%s%s",
149                 USER_ID,
150                 DEVICE_ID,
151                 USER_ID,
152                 client->deviceId,
153                 transactionId);
154
155         unsigned char sasBytes[5];
156         olm_sas_generate_bytes(olmSas,
157             hkdfInfo, hkdfInfoLen,
158             sasBytes, 5);
159         int b0 = sasBytes[0];
160         int b1 = sasBytes[1];
161         int b2 = sasBytes[2];
162         int b3 = sasBytes[3];
163         int b4 = sasBytes[4];
164         
165         printf("%d %d %d %d %d\n", b0, b1, b2, b3, b4);
166
167         // https://spec.matrix.org/v1.7/client-server-api/#sas-method-decimal
168         printf("%d | %d | %d\n",
169             (b0 << 5 | b1 >> 3) + 1000,
170             ((b1 & 0x7) << 10 | b2 << 2 | b3 >> 6) + 1000,
171             ((b3 & 0x3F) << 7 | b4 >> 1) + 1000);
172         printf("%d | %d | %d\n",
173             ((b0 << 5) | (b1 >> 3)) + 1000,
174             (((b1 & 0x7) << 10) | (b2 << 2) | (b3 >> 6)) + 1000,
175             (((b3 & 0x3F) << 7) | (b4 >> 1)) + 1000);
176     }
177     else if (strcmp(eventType, "m.key.verification.mac") == 0) {        
178         // mac
179         const char * masterKey = "vt8tJ5/SxqkvXS+XoGxr+4rJNe8fJfZT3/e/FTwlFsI";
180
181         STATIC char keyList[256];
182         STATIC char keyListMac[256];
183         STATIC char key1Id[128];
184         STATIC char key1[128];
185         STATIC char key1Mac[128];
186         STATIC char key2Id[128];
187         STATIC char key2[128];
188         STATIC char key2Mac[128];
189
190         if (strcmp(masterKey, client->deviceId) < 0) {
191             snprintf(key1Id, 1024, "ed25519:%s", masterKey);
192             strcpy(key1, masterKey);
193             snprintf(key2Id, 1024, "ed25519:%s", client->deviceId);
194             MatrixOlmAccountGetSigningKey(&client->olmAccount, key2, 1024);
195         }
196         else {
197             snprintf(key1Id, 1024, "ed25519:%s", client->deviceId);
198             MatrixOlmAccountGetSigningKey(&client->olmAccount, key1, 1024);
199             snprintf(key2Id, 1024, "ed25519:%s", masterKey);
200             strcpy(key2, masterKey);
201         }
202
203         snprintf(keyList, 1024,
204             "%s,%s", key1Id, key2Id);
205         
206         STATIC char macInfo[1024];
207         int macInfoLen;
208         {
209             macInfoLen =
210                 snprintf(macInfo, 1024,
211                     "MATRIX_KEY_VERIFICATION_MAC%s%s%s%s%s%s",
212                     USER_ID,
213                     client->deviceId,
214                     USER_ID,
215                     DEVICE_ID,
216                     transactionId,
217                     "KEY_IDS");
218             olm_sas_calculate_mac_fixed_base64(olmSas, keyList, strlen(keyList), macInfo, macInfoLen, keyListMac, 1024);
219         }
220         {
221             macInfoLen =
222                 snprintf(macInfo, 1024,
223                     "MATRIX_KEY_VERIFICATION_MAC%s%s%s%s%s%s",
224                     USER_ID,
225                     client->deviceId,
226                     USER_ID,
227                     DEVICE_ID,
228                     transactionId,
229                     key1Id);
230             olm_sas_calculate_mac_fixed_base64(olmSas, key1, strlen(key1), macInfo, macInfoLen, key1Mac, 1024);
231         }
232         {
233             macInfoLen =
234                 snprintf(macInfo, 1024,
235                     "MATRIX_KEY_VERIFICATION_MAC%s%s%s%s%s%s",
236                     USER_ID,
237                     client->deviceId,
238                     USER_ID,
239                     DEVICE_ID,
240                     transactionId,
241                     key2Id);
242             olm_sas_calculate_mac_fixed_base64(olmSas, key2, strlen(key2), macInfo, macInfoLen, key2Mac, 1024);
243         }
244
245         STATIC char verificationMacBuffer[1024];
246         snprintf(verificationMacBuffer, 1024,
247             "{"
248             "\"keys\":\"%s\","
249             "\"mac\":{"
250             "\"%s\":\"%s\","
251             "\"%s\":\"%s\""
252             "},"
253             "\"transaction_id\":\"%s\""
254             "}",
255             keyListMac,
256             key1Id,
257             key1Mac,
258             key2Id,
259             key2Mac,
260             transactionId);
261         
262         MatrixClientSendToDevice(client,
263             USER_ID,
264             DEVICE_ID,
265             verificationMacBuffer,
266             "m.key.verification.mac");
267
268         STATIC char verificationDoneBuffer[128];
269         snprintf(verificationDoneBuffer, 128,
270             "{"
271             "\"transaction_id\":\"%s\""
272             "}",
273             transactionId);
274         
275         MatrixClientSendToDevice(client,
276             USER_ID,
277             DEVICE_ID,
278             verificationDoneBuffer,
279             "m.key.verification.done");
280         
281         verified = true;
282     }
283     else if (strcmp(eventType, "m.room.encrypted") == 0) {
284         STATIC char algorithm[128];
285         mjson_get_string(event, eventLen, "$.content.algorithm", algorithm, 128);
286
287         if (strcmp(algorithm, "m.olm.v1.curve25519-aes-sha2") == 0) {
288             STATIC char thisDeviceKey[DEVICE_KEY_SIZE];
289             MatrixOlmAccountGetDeviceKey(&client->olmAccount, thisDeviceKey, DEVICE_KEY_SIZE);
290
291             STATIC char jp[128];
292             snprintf(jp, 128, "$.content.ciphertext.%s.type", thisDeviceKey);
293
294             double messageType;
295             mjson_get_number(event, eventLen, jp, &messageType);
296             int messageTypeInt = (int)messageType;
297
298             snprintf(jp, 128, "$.content.ciphertext.%s.body", thisDeviceKey);
299
300             mjson_get_string(event, eventLen, jp, encrypted, 2048);
301
302             MatrixOlmSession * olmSession;
303             
304             if (! MatrixClientGetOlmSession(client, USER_ID, DEVICE_ID, &olmSession))
305             {
306                 if (messageTypeInt == 0) {
307                     MatrixClientNewOlmSessionIn(client,
308                         USER_ID,
309                         DEVICE_ID,
310                         encrypted,
311                         &olmSession);
312                 }
313                 else {
314                     MatrixClientNewOlmSessionOut(client,
315                         USER_ID,
316                         DEVICE_ID,
317                         &olmSession);
318                 }
319             }
320
321             printf("event: %.*s\n", eventLen, event);
322             printf("encrypted: %s\n", encrypted);
323             
324             MatrixOlmSessionDecrypt(olmSession,
325                 messageTypeInt, encrypted, decrypted, 2048);
326             
327             printf("decrypted: %s\n", decrypted);
328             
329             HandleEvent(client, decrypted, strlen(decrypted));
330         }
331     }
332     else if (strcmp(eventType, "m.room_key") == 0 ||
333              strcmp(eventType, "m.forwarded_room_key") == 0) {
334         STATIC char roomId[128];
335         STATIC char sessionId[128];
336         STATIC char sessionKey[1024];
337         mjson_get_string(event, eventLen, "$.content.room_id", roomId, 128);
338         mjson_get_string(event, eventLen, "$.content.session_id", sessionId, 128);
339         mjson_get_string(event, eventLen, "$.content.session_key", sessionKey, 1024);
340         
341         printf("sessionId: %s\n", sessionId);
342         printf("sessionKey: %s\n", sessionKey);
343
344         MatrixMegolmInSession * megolmInSession;
345         MatrixClientNewMegolmInSession(client, roomId, sessionId, sessionKey, &megolmInSession);
346     }
347 }
348
349 void
350 HandleRoomEvent(
351     MatrixClient * client,
352     const char * room, int roomLen,
353     const char * event, int eventLen)
354 {
355     STATIC char eventType[128];
356     memset(eventType, 0, sizeof(eventType));
357     mjson_get_string(event, eventLen, "$.type", eventType, 128);
358
359     if (strcmp(eventType, "m.room.encrypted") == 0) {
360         STATIC char algorithm[128];
361         mjson_get_string(event, eventLen, "$.content.algorithm", algorithm, 128);
362
363         if (strcmp(algorithm, "m.megolm.v1.aes-sha2") == 0) {
364             STATIC char sessionId[128];
365             int sessionIdLen =
366                 mjson_get_string(event, eventLen, "$.content.session_id", sessionId, 128);
367
368             bool res;
369
370             MatrixMegolmInSession * megolmInSession;
371             res = MatrixClientGetMegolmInSession(client,
372                 room, roomLen,
373                 sessionId, sessionIdLen,
374                 &megolmInSession);
375
376             if (res) {
377                 mjson_get_string(event, eventLen, "$.content.ciphertext", encrypted, 2048);
378
379                 MatrixMegolmInSessionDecrypt(megolmInSession, encrypted, strlen(encrypted), decrypted, 2048);
380
381                 printf("decrypted: %s\n", decrypted);
382
383                 HandleEvent(client, decrypted, strlen(decrypted));
384             }
385             else {
386                 printf("megolm session not known\n");
387             }
388         }
389     }
390     HandleEvent(client, event, eventLen);
391 }
392
393 void
394 Sync(
395     MatrixClient * client,
396     char * syncBuffer, int syncBufferLen)
397 {
398     STATIC char nextBatch[1024] = {0};
399
400     MatrixClientSync(client, syncBuffer, syncBufferLen, nextBatch);
401     
402     int res;
403
404     const char * s = syncBuffer;
405     int slen = strlen(syncBuffer);
406     
407     printf("sync:\n\n%s\n\n", syncBuffer);
408     
409     // {
410     // int koff, klen, voff, vlen, vtype, off = 0;
411     // for (off = 0; (off = mjson_next(s, slen, off, &koff, &klen,
412     //                                 &voff, &vlen, &vtype)) != 0; ) {
413     //     const char * k = s + koff;
414     //     const char * v = s + voff;
415
416     //     printf("%.*s: %.100s\n", klen, k, v);
417     // }
418     // }
419
420     mjson_get_string(s, slen, "$.next_batch", nextBatch, 1024);
421
422     // to_device
423
424     const char * events;
425     int eventsLen;
426     res =
427         mjson_find(s, slen, "$.to_device.events", &events, &eventsLen);
428     
429     if (res != MJSON_TOK_INVALID) {
430         {
431         int koff, klen, voff, vlen, vtype, off = 0;
432         for (off = 0; (off = mjson_next(events, eventsLen, off, &koff, &klen,
433                                         &voff, &vlen, &vtype)) != 0; ) {
434             const char * v = events + voff;
435
436             HandleEvent(client, v, vlen);
437         }
438         }
439     }
440
441     // rooms
442     
443     const char * rooms;
444     int roomsLen;
445     res =
446         mjson_find(s, slen, "$.rooms.join", &rooms, &roomsLen);
447     
448     if (res != MJSON_TOK_INVALID) {
449         {
450         int koff, klen, voff, vlen, vtype, off = 0;
451         for (off = 0; (off = mjson_next(rooms, roomsLen, off, &koff, &klen,
452                                         &voff, &vlen, &vtype)) != 0; ) {
453             const char * k = rooms + koff;
454             const char * v = rooms + voff;
455
456             const char * events;
457             int eventsLen;
458             res =
459                 mjson_find(v, vlen, "$.timeline.events", &events, &eventsLen);
460             
461             if (res != MJSON_TOK_INVALID) {
462                 {
463                 int koff2, klen2, voff2, vlen2, vtype2, off2 = 0;
464                 for (off2 = 0; (off2 = mjson_next(events, eventsLen, off2, &koff2, &klen2,
465                                                 &voff2, &vlen2, &vtype2)) != 0; ) {
466                     const char * v2 = events + voff2;
467
468                     HandleRoomEvent(client,
469                         k+1, klen-2,
470                         v2, vlen2);
471                 }
472                 }
473             }
474         }
475         }
476     }
477 }
478
479
480 int
481 main(void)
482 {
483     // sizeof(MatrixOlmAccount);
484     // sizeof(MatrixMegolmInSession);
485     // sizeof(MatrixMegolmOutSession);
486     // sizeof(MatrixOlmSession);    
487     // sizeof(MatrixDevice);
488
489     // STATIC MatrixClient _client;
490     // MatrixClient * client = &_client;
491     MatrixClient * client = (MatrixClient*)malloc(sizeof(MatrixClient));
492     MatrixClientInit(client);
493
494     MatrixHttpInit(&client->hc, SERVER);
495     MatrixClientSetUserId(client, USER_ID);
496
497     MatrixClientLoginPassword(client,
498         "pscho",
499         "Wc23EbmB9G3faMq",
500         "Test1");
501     printf("deviceId: %s\n", client->deviceId);
502     MatrixClientGenerateOnetimeKeys(client, 10);
503     MatrixClientUploadOnetimeKeys(client);
504     MatrixClientUploadDeviceKey(client);
505
506     STATIC char eventBuffer[1024];
507     MatrixClientGetRoomEvent(client,
508         ROOM_ID,
509         EVENT_ID,
510         eventBuffer, 1024);
511     printf("event: %s\n", eventBuffer);
512
513     #define SYNC_BUFFER_SIZE 1024*10
514
515     // char * syncBuffer = (char*)malloc(SYNC_BUFFER_SIZE);
516     STATIC char syncBuffer[SYNC_BUFFER_SIZE];
517
518     while (! verified) {
519         Sync(client, syncBuffer, SYNC_BUFFER_SIZE);
520     }
521
522     printf("verified!\n");
523
524     // create and share megolm out session
525     MatrixMegolmOutSession * megolmOutSession;
526     MatrixClientNewMegolmOutSession(client,
527         ROOM_ID,
528         &megolmOutSession);
529     printf("megolm session id: %.10s... key: %.10s...\n", megolmOutSession->id, megolmOutSession->key);
530     MatrixClientShareMegolmOutSession(client,
531         USER_ID,
532         "ULZZOKJBYN",
533         megolmOutSession);
534
535     
536     // int c;
537     // while ((c=getchar()) != 'q') {
538     //     vTaskDelay(1000/portTICK_PERIOD_MS);
539
540     //     if (c == 's') {
541     //         Sync(client, syncBuffer, SYNC_BUFFER_SIZE);
542     //     }
543     //     else if (c == 'm') {
544     //         static const char * msgs[] = { "A", "B", "C" };
545     //         static char msg[128];
546     //         snprintf(msg, 128, "{\"body\":\"%s\",\"msgtype\":\"m.text\"}", msgs[rand()%(sizeof(msgs)/sizeof(msgs[0]))]);
547
548     //         MatrixClientSendEventEncrypted(client,
549     //             ROOM_ID,
550     //             "m.room.message",
551     //             msg);
552     //         printf("Message sent. Message index: %d\n", (int)olm_outbound_group_session_message_index(megolmOutSession->session));
553     //     }
554     // }
555
556     for (int i = 0; i < 10; i++) {
557
558         static const char * msgs[] = { "A", "B", "C" };
559         static char msg[128];
560         snprintf(msg, 128, "{\"body\":\"%s\",\"msgtype\":\"m.text\"}", msgs[rand()%(sizeof(msgs)/sizeof(msgs[0]))]);
561
562         MatrixClientSendEventEncrypted(client,
563             ROOM_ID,
564             "m.room.message",
565             msg);
566
567         vTaskDelay(5000/portTICK_PERIOD_MS);
568     }
569     
570     // MatrixClientRequestMegolmInSession(client,
571     //     ROOM_ID,
572     //     SESSION_ID,
573     //     SENDER_KEY,
574     //     USER_ID,
575     //     DEVICE_ID);
576
577     // MatrixMegolmInSession * megolmInSession;
578     // while (! MatrixClientGetMegolmInSession(client,
579     //     ROOM_ID, strlen(ROOM_ID),
580     //     SESSION_ID, strlen(SESSION_ID),
581     //     &megolmInSession))
582     //     Sync(client, syncBuffer, SYNC_BUFFER_SIZE);
583
584     // int encryptedLen =
585     //     mjson_get_string(eventBuffer, strlen(eventBuffer), "$.content.ciphertext", encrypted, 1024);
586     
587     // printf("encrypted: [%.*s]\n", encryptedLen, encrypted);
588
589     // MatrixMegolmInSessionDecrypt(megolmInSession,
590     //     encrypted, encryptedLen,
591     //     decrypted, 1024);
592
593     // printf("decrypted: %s\n", decrypted);
594
595     MatrixClientDeleteDevice(client);
596         
597     MatrixHttpDeinit(&client->hc);
598
599     return 0;
600 }
601
602 #include "wifi.h"
603 #include <esp_netif.h>
604
605 void
606 app_main(void)
607 {
608     // wifi_init("Pixel_7762", "affeaffe");
609     // wifi_init("Hundehuette", "Affensicherespw55");
610     wifi_init("test", "/O801i25");
611
612     esp_netif_ip_info_t ip_info;
613     esp_netif_get_ip_info(IP_EVENT_STA_GOT_IP,&ip_info);
614     printf("My IP: " IPSTR "\n", IP2STR(&ip_info.ip));
615     printf("My GW: " IPSTR "\n", IP2STR(&ip_info.gw));
616     printf("My NETMASK: " IPSTR "\n", IP2STR(&ip_info.netmask));
617
618     // uint64_t bitmask = 0xffffffffffffffff;
619     // bitmask = bitmask & SOC_GPIO_VALID_GPIO_MASK;
620     // gpio_dump_io_configuration(stdout, bitmask);
621     gpio_set_direction(GPIO_NUM_2, GPIO_MODE_OUTPUT);
622     // gpio_dump_io_configuration(stdout, bitmask);
623
624     main();
625 }