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"
14 #define SERVER "https://matrix.org"
15 #define USER_ID "@pscho:matrix.org"
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"
23 // main stack size: 3584
25 bool verified = false;
26 char transactionId[64];
27 OlmSAS * olmSas = NULL;
31 STATIC char encrypted[2048];
32 STATIC char decrypted[2048];
36 MatrixClient * client,
37 const char * event, int eventLen
39 STATIC char eventType[128];
40 memset(eventType, 0, sizeof(eventType));
41 mjson_get_string(event, eventLen, "$.type", eventType, 128);
43 if (strcmp(eventType, "m.key.verification.request") == 0) {
44 mjson_get_string(event, eventLen, "$.content.transaction_id", transactionId, 256);
46 char verificationReadyBuffer[2048];
47 snprintf(verificationReadyBuffer, 2048,
49 "\"from_device\":\"%s\","
50 "\"methods\":[\"m.sas.v1\"],"
51 "\"transaction_id\":\"%s\""
56 MatrixClientSendToDevice(client,
59 verificationReadyBuffer,
60 "m.key.verification.ready");
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,
67 olm_create_sas_random_length(olmSas));
69 OlmUtility * olmUtil = olm_utility(malloc(olm_utility_size()));
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,
78 printf("public key: %.*s\n", olm_sas_pubkey_length(olmSas), publicKey);
80 const char * keyStartJson;
82 mjson_find(event, eventLen, "$.content", &keyStartJson, &keyStartJsonLen);
83 JsonCanonicalize(keyStartJson, keyStartJsonLen, keyStartJsonCanonical, 512);
85 printf("json:\n%.*s\ncanonical json:\n%s\n", keyStartJsonLen, keyStartJson, keyStartJsonCanonical);
88 snprintf(concat, 512+64, "%.*s%s", olm_sas_pubkey_length(olmSas), publicKey, keyStartJsonCanonical);
91 olm_sha256(olmUtil, concat, concatLen, commitment, 1024);
93 STATIC char verificationAcceptBuffer[512];
94 snprintf(verificationAcceptBuffer, 512,
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\""
104 commitmentLen, commitment,
107 MatrixClientSendToDevice(client,
110 verificationAcceptBuffer,
111 "m.key.verification.accept");
113 else if (strcmp(eventType, "m.key.verification.key") == 0) {
114 STATIC char publicKey[128];
115 olm_sas_get_pubkey(olmSas,
119 STATIC char theirPublicKey[128];
120 int theirPublicKeyLen =
121 mjson_get_string(event, eventLen, "$.content.key", theirPublicKey, 128);
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);
127 olm_sas_set_their_key(olmSas, theirPublicKey, theirPublicKeyLen);
129 STATIC char verificationKeyBuffer[256];
130 snprintf(verificationKeyBuffer, 256,
133 "\"transaction_id\":\"%s\""
135 olm_sas_pubkey_length(olmSas), publicKey,
138 MatrixClientSendToDevice(client,
141 verificationKeyBuffer,
142 "m.key.verification.key");
145 STATIC char hkdfInfo[1024];
147 snprintf(hkdfInfo, 1024,
148 "MATRIX_KEY_VERIFICATION_SAS%s%s%s%s%s",
155 unsigned char sasBytes[5];
156 olm_sas_generate_bytes(olmSas,
157 hkdfInfo, hkdfInfoLen,
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];
165 printf("%d %d %d %d %d\n", b0, b1, b2, b3, b4);
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);
177 else if (strcmp(eventType, "m.key.verification.mac") == 0) {
179 const char * masterKey = "vt8tJ5/SxqkvXS+XoGxr+4rJNe8fJfZT3/e/FTwlFsI";
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];
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);
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);
203 snprintf(keyList, 1024,
204 "%s,%s", key1Id, key2Id);
206 STATIC char macInfo[1024];
210 snprintf(macInfo, 1024,
211 "MATRIX_KEY_VERIFICATION_MAC%s%s%s%s%s%s",
218 olm_sas_calculate_mac_fixed_base64(olmSas, keyList, strlen(keyList), macInfo, macInfoLen, keyListMac, 1024);
222 snprintf(macInfo, 1024,
223 "MATRIX_KEY_VERIFICATION_MAC%s%s%s%s%s%s",
230 olm_sas_calculate_mac_fixed_base64(olmSas, key1, strlen(key1), macInfo, macInfoLen, key1Mac, 1024);
234 snprintf(macInfo, 1024,
235 "MATRIX_KEY_VERIFICATION_MAC%s%s%s%s%s%s",
242 olm_sas_calculate_mac_fixed_base64(olmSas, key2, strlen(key2), macInfo, macInfoLen, key2Mac, 1024);
245 STATIC char verificationMacBuffer[1024];
246 snprintf(verificationMacBuffer, 1024,
253 "\"transaction_id\":\"%s\""
262 MatrixClientSendToDevice(client,
265 verificationMacBuffer,
266 "m.key.verification.mac");
268 STATIC char verificationDoneBuffer[128];
269 snprintf(verificationDoneBuffer, 128,
271 "\"transaction_id\":\"%s\""
275 MatrixClientSendToDevice(client,
278 verificationDoneBuffer,
279 "m.key.verification.done");
283 else if (strcmp(eventType, "m.room.encrypted") == 0) {
284 STATIC char algorithm[128];
285 mjson_get_string(event, eventLen, "$.content.algorithm", algorithm, 128);
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);
292 snprintf(jp, 128, "$.content.ciphertext.%s.type", thisDeviceKey);
295 mjson_get_number(event, eventLen, jp, &messageType);
296 int messageTypeInt = (int)messageType;
298 snprintf(jp, 128, "$.content.ciphertext.%s.body", thisDeviceKey);
300 mjson_get_string(event, eventLen, jp, encrypted, 2048);
302 MatrixOlmSession * olmSession;
304 if (! MatrixClientGetOlmSession(client, USER_ID, DEVICE_ID, &olmSession))
306 if (messageTypeInt == 0) {
307 MatrixClientNewOlmSessionIn(client,
314 MatrixClientNewOlmSessionOut(client,
321 printf("event: %.*s\n", eventLen, event);
322 printf("encrypted: %s\n", encrypted);
324 MatrixOlmSessionDecrypt(olmSession,
325 messageTypeInt, encrypted, decrypted, 2048);
327 printf("decrypted: %s\n", decrypted);
329 HandleEvent(client, decrypted, strlen(decrypted));
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);
341 printf("sessionId: %s\n", sessionId);
342 printf("sessionKey: %s\n", sessionKey);
344 MatrixMegolmInSession * megolmInSession;
345 MatrixClientNewMegolmInSession(client, roomId, sessionId, sessionKey, &megolmInSession);
351 MatrixClient * client,
352 const char * room, int roomLen,
353 const char * event, int eventLen)
355 STATIC char eventType[128];
356 memset(eventType, 0, sizeof(eventType));
357 mjson_get_string(event, eventLen, "$.type", eventType, 128);
359 if (strcmp(eventType, "m.room.encrypted") == 0) {
360 STATIC char algorithm[128];
361 mjson_get_string(event, eventLen, "$.content.algorithm", algorithm, 128);
363 if (strcmp(algorithm, "m.megolm.v1.aes-sha2") == 0) {
364 STATIC char sessionId[128];
366 mjson_get_string(event, eventLen, "$.content.session_id", sessionId, 128);
370 MatrixMegolmInSession * megolmInSession;
371 res = MatrixClientGetMegolmInSession(client,
373 sessionId, sessionIdLen,
377 mjson_get_string(event, eventLen, "$.content.ciphertext", encrypted, 2048);
379 MatrixMegolmInSessionDecrypt(megolmInSession, encrypted, strlen(encrypted), decrypted, 2048);
381 printf("decrypted: %s\n", decrypted);
383 HandleEvent(client, decrypted, strlen(decrypted));
386 printf("megolm session not known\n");
390 HandleEvent(client, event, eventLen);
395 MatrixClient * client,
396 char * syncBuffer, int syncBufferLen)
398 STATIC char nextBatch[1024] = {0};
400 MatrixClientSync(client, syncBuffer, syncBufferLen, nextBatch);
404 const char * s = syncBuffer;
405 int slen = strlen(syncBuffer);
407 printf("sync:\n\n%s\n\n", syncBuffer);
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;
416 // printf("%.*s: %.100s\n", klen, k, v);
420 mjson_get_string(s, slen, "$.next_batch", nextBatch, 1024);
427 mjson_find(s, slen, "$.to_device.events", &events, &eventsLen);
429 if (res != MJSON_TOK_INVALID) {
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;
436 HandleEvent(client, v, vlen);
446 mjson_find(s, slen, "$.rooms.join", &rooms, &roomsLen);
448 if (res != MJSON_TOK_INVALID) {
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;
459 mjson_find(v, vlen, "$.timeline.events", &events, &eventsLen);
461 if (res != MJSON_TOK_INVALID) {
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;
468 HandleRoomEvent(client,
483 // sizeof(MatrixOlmAccount);
484 // sizeof(MatrixMegolmInSession);
485 // sizeof(MatrixMegolmOutSession);
486 // sizeof(MatrixOlmSession);
487 // sizeof(MatrixDevice);
489 // STATIC MatrixClient _client;
490 // MatrixClient * client = &_client;
491 MatrixClient * client = (MatrixClient*)malloc(sizeof(MatrixClient));
492 MatrixClientInit(client);
494 MatrixHttpInit(&client->hc, SERVER);
495 MatrixClientSetUserId(client, USER_ID);
497 MatrixClientLoginPassword(client,
501 printf("deviceId: %s\n", client->deviceId);
502 MatrixClientGenerateOnetimeKeys(client, 10);
503 MatrixClientUploadOnetimeKeys(client);
504 MatrixClientUploadDeviceKey(client);
506 STATIC char eventBuffer[1024];
507 MatrixClientGetRoomEvent(client,
511 printf("event: %s\n", eventBuffer);
513 #define SYNC_BUFFER_SIZE 1024*10
515 // char * syncBuffer = (char*)malloc(SYNC_BUFFER_SIZE);
516 STATIC char syncBuffer[SYNC_BUFFER_SIZE];
519 Sync(client, syncBuffer, SYNC_BUFFER_SIZE);
522 printf("verified!\n");
524 // create and share megolm out session
525 MatrixMegolmOutSession * megolmOutSession;
526 MatrixClientNewMegolmOutSession(client,
529 printf("megolm session id: %.10s... key: %.10s...\n", megolmOutSession->id, megolmOutSession->key);
530 MatrixClientShareMegolmOutSession(client,
537 // while ((c=getchar()) != 'q') {
538 // vTaskDelay(1000/portTICK_PERIOD_MS);
541 // Sync(client, syncBuffer, SYNC_BUFFER_SIZE);
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]))]);
548 // MatrixClientSendEventEncrypted(client,
552 // printf("Message sent. Message index: %d\n", (int)olm_outbound_group_session_message_index(megolmOutSession->session));
556 for (int i = 0; i < 10; i++) {
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]))]);
562 MatrixClientSendEventEncrypted(client,
567 vTaskDelay(5000/portTICK_PERIOD_MS);
570 // MatrixClientRequestMegolmInSession(client,
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);
584 // int encryptedLen =
585 // mjson_get_string(eventBuffer, strlen(eventBuffer), "$.content.ciphertext", encrypted, 1024);
587 // printf("encrypted: [%.*s]\n", encryptedLen, encrypted);
589 // MatrixMegolmInSessionDecrypt(megolmInSession,
590 // encrypted, encryptedLen,
593 // printf("decrypted: %s\n", decrypted);
595 MatrixClientDeleteDevice(client);
597 MatrixHttpDeinit(&client->hc);
603 #include <esp_netif.h>
608 // wifi_init("Pixel_7762", "affeaffe");
609 // wifi_init("Hundehuette", "Affensicherespw55");
610 wifi_init("test", "/O801i25");
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));
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);