X-Git-Url: https://gitweb.ps.run/matrix_esp_thesis/blobdiff_plain/b231872efcb97e52856f5972efd161c6e9b03cd6..50f9d03ea29a8ae2f82d5edb5404fdebf4316b13:/src/matrix.c diff --git a/src/matrix.c b/src/matrix.c index 40c2e5b..4ce78ce 100644 --- a/src/matrix.c +++ b/src/matrix.c @@ -3,14 +3,22 @@ #include #include #include +#include +#ifdef ESP_PLATFORM +#include +#endif + +#define STATIC static #define LOGIN_REQUEST_SIZE 1024 #define LOGIN_RESPONSE_SIZE 1024 #define LOGIN_URL "/_matrix/client/v3/login" #define ENCRYPTED_REQUEST_SIZE (1024*5) +STATIC char g_EncryptedRequestBuffer[ENCRYPTED_REQUEST_SIZE]; #define ENCRYPTED_EVENT_SIZE (1024*10) +STATIC char g_EncryptedEventBuffer[ENCRYPTED_EVENT_SIZE]; #define ROOM_SEND_REQUEST_SIZE 256 #define ROOM_SEND_RESPONSE_SIZE 1024 #define ROOM_SEND_URL "/_matrix/client/v3/rooms/%s/send/%s/%d" @@ -18,15 +26,18 @@ #define ROOMKEY_REQUEST_SIZE (1024*4) #define TODEVICE_EVENT_SIZE (1024*5) +STATIC char g_TodeviceEventBuffer[TODEVICE_EVENT_SIZE]; #define TODEVICE_URL "/_matrix/client/v3/sendToDevice/%s/%d" #define KEYS_QUERY_URL "/_matrix/client/v3/keys/query" #define KEYS_QUERY_REQUEST_SIZE 256 -#define KEYS_QUERY_RESPONSE_SIZE (1024*10) +#define KEYS_QUERY_RESPONSE_SIZE (1024*5) #define KEYS_UPLOAD_URL "/_matrix/client/v3/keys/upload" #define KEYS_UPLOAD_REQUEST_SIZE 1024*4 +STATIC char g_KeysUploadRequestBuffer[KEYS_UPLOAD_REQUEST_SIZE]; #define KEYS_UPLOAD_REQUEST_SIGNED_SIZE 2048*4 +STATIC char g_KeysUploadRequestSignedBuffer[KEYS_UPLOAD_REQUEST_SIGNED_SIZE]; #define KEYS_UPLOAD_RESPONSE_SIZE 2048 #define KEYS_CLAIM_URL "/_matrix/client/v3/keys/claim" @@ -47,13 +58,24 @@ Randomize( uint8_t * random, int randomLen) { - static bool first = true; + #ifdef ESP_PLATFORM + + for (int i = 0; i < randomLen; i++) + { + random[i] = esp_random() % 256; + } + + #else + + STATIC bool first = true; if (first) { srand(time(0)); first = false; } for (int i = 0; i < randomLen; i++) { random[i] = rand() % 256; } + + #endif } bool @@ -130,7 +152,7 @@ JsonCanonicalize( int valLen; mjson_find(sIn, sInLen, jp, &valPtr, &valLen); - static char newEntry[JSON_MAX_ENTRY_SIZE]; + STATIC char newEntry[JSON_MAX_ENTRY_SIZE]; snprintf(newEntry, JSON_MAX_ENTRY_SIZE, "{%.*s:%.*s}", keys[i].len, keys[i].ptr, valLen, valPtr); char * buffer = strdup(sOut); @@ -151,7 +173,7 @@ bool JsonSign( const char * sIn, int sInLen, char * sOut, int sOutCap) { - static char signature[OLM_SIGNATURE_SIZE]; + STATIC char signature[OLM_SIGNATURE_SIZE]; size_t res = olm_account_sign(client->olmAccount.account, sIn, sInLen, @@ -159,10 +181,10 @@ bool JsonSign( int signatureLen = res; - static char thisSigningKey[SIGNING_KEY_SIZE]; + STATIC char thisSigningKey[SIGNING_KEY_SIZE]; MatrixOlmAccountGetSigningKey(&client->olmAccount, thisSigningKey, SIGNING_KEY_SIZE); - static char signatureJson[JSON_SIGNATURE_SIZE]; + STATIC char signatureJson[JSON_SIGNATURE_SIZE]; int signatureJsonLen = mjson_snprintf(signatureJson, JSON_SIGNATURE_SIZE, "{" @@ -194,7 +216,7 @@ MatrixOlmAccountInit( { account->account = olm_account(account->memory); - static uint8_t random[OLM_ACCOUNT_RANDOM_SIZE]; + STATIC uint8_t random[OLM_ACCOUNT_RANDOM_SIZE]; Randomize(random, OLM_ACCOUNT_RANDOM_SIZE); size_t res = olm_create_account( @@ -227,7 +249,7 @@ MatrixOlmAccountGetDeviceKey( MatrixOlmAccount * account, char * key, int keyCap) { - static char deviceKeysJson[OLM_IDENTITY_KEYS_JSON_SIZE]; + STATIC char deviceKeysJson[OLM_IDENTITY_KEYS_JSON_SIZE]; size_t res = olm_account_identity_keys(account->account, deviceKeysJson, OLM_IDENTITY_KEYS_JSON_SIZE); @@ -242,7 +264,7 @@ MatrixOlmAccountGetSigningKey( MatrixOlmAccount * account, char * key, int keyCap) { - static char deviceKeysJson[OLM_IDENTITY_KEYS_JSON_SIZE]; + STATIC char deviceKeysJson[OLM_IDENTITY_KEYS_JSON_SIZE]; size_t res = olm_account_identity_keys(account->account, deviceKeysJson, OLM_IDENTITY_KEYS_JSON_SIZE); @@ -268,7 +290,7 @@ MatrixOlmSessionFrom( olm_session(session->memory); char * encryptedCopy = strdup(encrypted); - + size_t res = olm_create_inbound_session_from(session->session, olmAccount, deviceKey, strlen(deviceKey), @@ -296,7 +318,7 @@ MatrixOlmSessionTo( session->session = olm_session(session->memory); - static uint8_t random[OLM_OUTBOUND_SESSION_RANDOM_SIZE]; + STATIC uint8_t random[OLM_OUTBOUND_SESSION_RANDOM_SIZE]; Randomize(random, OLM_OUTBOUND_SESSION_RANDOM_SIZE); size_t res = @@ -345,9 +367,10 @@ MatrixOlmSessionEncrypt( const char * plaintext, char * outBuffer, int outBufferCap) { - static uint8_t random[OLM_ENCRYPT_RANDOM_SIZE]; + STATIC uint8_t random[OLM_ENCRYPT_RANDOM_SIZE]; Randomize(random, OLM_ENCRYPT_RANDOM_SIZE); + memset(outBuffer, 0, outBufferCap); size_t res = olm_encrypt(session->session, plaintext, strlen(plaintext), random, OLM_ENCRYPT_RANDOM_SIZE, @@ -363,7 +386,7 @@ MatrixOlmSessionDecrypt( char * encrypted, char * outBuffer, int outBufferCap) { - static uint8_t random[OLM_ENCRYPT_RANDOM_SIZE]; + STATIC uint8_t random[OLM_ENCRYPT_RANDOM_SIZE]; Randomize(random, OLM_ENCRYPT_RANDOM_SIZE); size_t res = @@ -372,7 +395,7 @@ MatrixOlmSessionDecrypt( encrypted, strlen(encrypted), outBuffer, outBufferCap); - if (res != olm_error() && res < outBufferCap) + if (res != olm_error() && (int)res < outBufferCap) outBuffer[res] = '\0'; return res != olm_error(); @@ -423,7 +446,7 @@ MatrixMegolmInSessionDecrypt( (uint8_t *)outDecrypted, outDecryptedCap, &megolmInMessageIndex); - printf("message index: %d\n", megolmInMessageIndex); + printf("message index: %d\n", (int)megolmInMessageIndex); if (res == olm_error()) { printf("error decrypting megolm message: %s\n", olm_inbound_group_session_last_error(session->session)); @@ -443,7 +466,7 @@ MatrixMegolmOutSessionInit( { memset(session, 0, sizeof(MatrixMegolmOutSession)); - static uint8_t random[MEGOLM_INIT_RANDOM_SIZE]; + STATIC uint8_t random[MEGOLM_INIT_RANDOM_SIZE]; Randomize(random, MEGOLM_INIT_RANDOM_SIZE); strncpy(session->roomId, roomId, ROOM_ID_SIZE); @@ -473,6 +496,7 @@ MatrixMegolmOutSessionEncrypt( const char * plaintext, char * outBuffer, int outBufferCap) { + memset(outBuffer, 0, outBufferCap); size_t res = olm_group_encrypt(session->session, (uint8_t *)plaintext, strlen(plaintext), (uint8_t *)outBuffer, outBufferCap); @@ -480,155 +504,19 @@ MatrixMegolmOutSessionEncrypt( return res != olm_error(); } -bool -MatrixMegolmOutSessionSave( - MatrixMegolmOutSession * session, - const char * filename, - const char * key) -{ - FILE * f = fopen(filename, "w"); - - size_t roomIdLen = strlen(session->roomId); - fwrite(&roomIdLen, sizeof(size_t), 1, f); - fwrite(session->roomId, 1, roomIdLen, f); - - size_t pickleBufferLen = - olm_pickle_outbound_group_session_length( - session->session); - void * pickleBuffer = malloc(pickleBufferLen); - - olm_pickle_outbound_group_session( - session->session, - key, strlen(key), - pickleBuffer, pickleBufferLen); - - fwrite(&pickleBufferLen, sizeof(size_t), 1, f); - fwrite(pickleBuffer, 1, pickleBufferLen, f); - free(pickleBuffer); - - fclose(f); - - return true; -} - -bool -MatrixMegolmOutSessionLoad( - MatrixMegolmOutSession * session, - const char * filename, - const char * key) -{ - FILE * f = fopen(filename, "r"); - - size_t roomIdLen; - fread(&roomIdLen, sizeof(size_t), 1, f); - fread(session->roomId, 1, roomIdLen, f); - for (int i = roomIdLen; i < ROOM_ID_SIZE; i++) - session->roomId[i] = '\0'; - - size_t pickleBufferLen; - fread(&pickleBufferLen, sizeof(size_t), 1, f); - - void * pickleBuffer = malloc(pickleBufferLen); - fread(pickleBuffer, 1, pickleBufferLen, f); - - olm_unpickle_outbound_group_session( - session->session, - key, strlen(key), - pickleBuffer, pickleBufferLen); - - free(pickleBuffer); - - olm_outbound_group_session_id(session->session, (uint8_t *)session->id, MEGOLM_SESSION_ID_SIZE); - olm_outbound_group_session_key(session->session, (uint8_t *)session->key, MEGOLM_SESSION_KEY_SIZE); - - fclose(f); - - return true; -} - - bool MatrixClientInit( - MatrixClient * client, - const char * server) + MatrixClient * client) { memset(client, 0, sizeof(MatrixClient)); - strcpy(client->server, server); - // init olm account MatrixOlmAccountInit(&client->olmAccount); return true; } -bool -MatrixClientSave( - MatrixClient * client, - const char * filename) -{ - FILE * f = fopen(filename, "w"); - - - char thisDeviceKey[DEVICE_KEY_SIZE]; - MatrixOlmAccountGetDeviceKey(&client->olmAccount, thisDeviceKey, DEVICE_KEY_SIZE); - char thisSigningKey[DEVICE_KEY_SIZE]; - MatrixOlmAccountGetSigningKey(&client->olmAccount, thisSigningKey, DEVICE_KEY_SIZE); - - - fwrite(thisDeviceKey, 1, DEVICE_KEY_SIZE, f); - fwrite(thisSigningKey, 1, DEVICE_KEY_SIZE, f); - fwrite(client->userId, 1, USER_ID_SIZE, f); - fwrite(client->server, 1, SERVER_SIZE, f); - fwrite(client->accessToken, 1, ACCESS_TOKEN_SIZE, f); - fwrite(client->deviceId, 1, DEVICE_ID_SIZE, f); - fwrite(client->expireMs, 1, EXPIRE_MS_SIZE, f); - fwrite(client->refreshToken, 1, REFRESH_TOKEN_SIZE, f); - - fwrite(&client->numDevices, sizeof(int), 1, f); - for (int i = 0; i < client->numDevices; i++) { - fwrite(client->devices[i].deviceId, 1, DEVICE_ID_SIZE, f); - fwrite(client->devices[i].deviceKey, 1, DEVICE_KEY_SIZE, f); - } - - fclose(f); - return true; -} - -bool -MatrixClientLoad( - MatrixClient * client, - const char * filename) -{ - FILE * f = fopen(filename, "r"); - - - char thisDeviceKey[DEVICE_KEY_SIZE]; - MatrixOlmAccountGetDeviceKey(&client->olmAccount, thisDeviceKey, DEVICE_KEY_SIZE); - char thisSigningKey[DEVICE_KEY_SIZE]; - MatrixOlmAccountGetSigningKey(&client->olmAccount, thisSigningKey, DEVICE_KEY_SIZE); - - - fread(thisDeviceKey, 1, DEVICE_KEY_SIZE, f); - fread(thisSigningKey, 1, DEVICE_KEY_SIZE, f); - fread(client->userId, 1, USER_ID_SIZE, f); - fread(client->server, 1, SERVER_SIZE, f); - fread(client->accessToken, 1, ACCESS_TOKEN_SIZE, f); - fread(client->deviceId, 1, DEVICE_ID_SIZE, f); - fread(client->expireMs, 1, EXPIRE_MS_SIZE, f); - fread(client->refreshToken, 1, REFRESH_TOKEN_SIZE, f); - - fread(&client->numDevices, sizeof(int), 1, f); - for (int i = 0; i < client->numDevices; i++) { - fread(client->devices[i].deviceId, 1, DEVICE_ID_SIZE, f); - fread(client->devices[i].deviceKey, 1, DEVICE_KEY_SIZE, f); - } - - fclose(f); - return true; -} - bool MatrixClientSetAccessToken( MatrixClient * client, @@ -670,7 +558,7 @@ MatrixClientGenerateOnetimeKeys( MatrixClient * client, int numberOfKeys) { - static uint8_t random[OLM_ONETIME_KEYS_RANDOM_SIZE]; + STATIC uint8_t random[OLM_ONETIME_KEYS_RANDOM_SIZE]; Randomize(random, OLM_ONETIME_KEYS_RANDOM_SIZE); size_t res = @@ -685,12 +573,10 @@ bool MatrixClientUploadOnetimeKeys( MatrixClient * client) { - static char requestBuffer[KEYS_UPLOAD_REQUEST_SIZE]; - - mjson_snprintf(requestBuffer, KEYS_UPLOAD_REQUEST_SIZE, + mjson_snprintf(g_KeysUploadRequestBuffer, KEYS_UPLOAD_REQUEST_SIZE, "{"); - static char onetimeKeysBuffer[1024]; + STATIC char onetimeKeysBuffer[1024]; olm_account_one_time_keys(client->olmAccount.account, onetimeKeysBuffer, 1024); @@ -700,47 +586,46 @@ MatrixClientUploadOnetimeKeys( int koff, klen, voff, vlen, vtype, off = 0; while ((off = mjson_next(keys, keysLen, off, &koff, &klen, &voff, &vlen, &vtype)) != 0) { - static char keyJson[JSON_ONETIME_KEY_SIZE]; + STATIC char keyJson[JSON_ONETIME_KEY_SIZE]; int keyJsonLen = snprintf(keyJson, JSON_ONETIME_KEY_SIZE, "{\"key\":\"%.*s\"}", vlen-2, keys + voff+1); - static char keyJsonSigned[JSON_ONETIME_KEY_SIGNED_SIZE]; + STATIC char keyJsonSigned[JSON_ONETIME_KEY_SIGNED_SIZE]; JsonSign(client, keyJson, keyJsonLen, keyJsonSigned, JSON_ONETIME_KEY_SIGNED_SIZE); - mjson_snprintf(requestBuffer+strlen(requestBuffer), KEYS_UPLOAD_REQUEST_SIZE-strlen(requestBuffer), + mjson_snprintf(g_KeysUploadRequestBuffer+strlen(g_KeysUploadRequestBuffer), KEYS_UPLOAD_REQUEST_SIZE-strlen(g_KeysUploadRequestBuffer), "\"signed_curve25519:%.*s\":%s,", klen-2, keys + koff+1, keyJsonSigned); } - if (requestBuffer[strlen(requestBuffer)-1] == ',') - requestBuffer[strlen(requestBuffer)-1] = '\0'; + if (g_KeysUploadRequestBuffer[strlen(g_KeysUploadRequestBuffer)-1] == ',') + g_KeysUploadRequestBuffer[strlen(g_KeysUploadRequestBuffer)-1] = '\0'; - mjson_snprintf(requestBuffer+strlen(requestBuffer), KEYS_UPLOAD_REQUEST_SIZE-strlen(requestBuffer), + mjson_snprintf(g_KeysUploadRequestBuffer+strlen(g_KeysUploadRequestBuffer), KEYS_UPLOAD_REQUEST_SIZE-strlen(g_KeysUploadRequestBuffer), "}"); - // static char onetimeKeysSignedBuffer[KEYS_UPLOAD_REQUEST_SIGNED_SIZE]; + // STATIC char onetimeKeysSignedBuffer[KEYS_UPLOAD_REQUEST_SIGNED_SIZE]; // JsonSign(client, - // requestBuffer, strlen(requestBuffer), + // g_KeysUploadRequestBuffer, strlen(g_KeysUploadRequestBuffer), // onetimeKeysSignedBuffer, KEYS_UPLOAD_REQUEST_SIZE); - // static char finalEvent[KEYS_UPLOAD_REQUEST_SIGNED_SIZE]; + // STATIC char finalEvent[KEYS_UPLOAD_REQUEST_SIGNED_SIZE]; // snprintf(finalEvent, KEYS_UPLOAD_REQUEST_SIGNED_SIZE, // "{\"one_time_keys\":%s}", onetimeKeysSignedBuffer); - static char finalEvent[KEYS_UPLOAD_REQUEST_SIGNED_SIZE]; - snprintf(finalEvent, KEYS_UPLOAD_REQUEST_SIGNED_SIZE, - "{\"one_time_keys\":%s}", requestBuffer); + snprintf(g_KeysUploadRequestSignedBuffer, KEYS_UPLOAD_REQUEST_SIGNED_SIZE, + "{\"one_time_keys\":%s}", g_KeysUploadRequestBuffer); - static char responseBuffer[KEYS_UPLOAD_RESPONSE_SIZE]; - MatrixHttpPost(client, + STATIC char responseBuffer[KEYS_UPLOAD_RESPONSE_SIZE]; + MatrixHttpPost(client->hc, KEYS_UPLOAD_URL, - finalEvent, + g_KeysUploadRequestSignedBuffer, responseBuffer, KEYS_UPLOAD_RESPONSE_SIZE, true); @@ -749,7 +634,7 @@ MatrixClientUploadOnetimeKeys( // https://spec.matrix.org/v1.7/client-server-api/#post_matrixclientv3keysupload bool -MatrixClientUploadDeviceKey( +MatrixClientUploadDeviceKeys( MatrixClient * client) { char thisDeviceKey[DEVICE_KEY_SIZE]; @@ -757,10 +642,8 @@ MatrixClientUploadDeviceKey( char thisSigningKey[DEVICE_KEY_SIZE]; MatrixOlmAccountGetSigningKey(&client->olmAccount, thisSigningKey, DEVICE_KEY_SIZE); - static char deviceKeysBuffer[KEYS_UPLOAD_REQUEST_SIZE]; - int deviceKeysBufferLen = - mjson_snprintf(deviceKeysBuffer, KEYS_UPLOAD_REQUEST_SIZE, + mjson_snprintf(g_KeysUploadRequestBuffer, KEYS_UPLOAD_REQUEST_SIZE, "{" "\"algorithms\":[\"m.olm.v1.curve25519-aes-sha2\",\"m.megolm.v1.aes-sha2\"]," "\"device_id\":\"%s\"," @@ -775,17 +658,16 @@ MatrixClientUploadDeviceKey( client->deviceId, thisSigningKey, client->userId); - static char deviceKeysSignedBuffer[KEYS_UPLOAD_REQUEST_SIGNED_SIZE]; JsonSign(client, - deviceKeysBuffer, deviceKeysBufferLen, - deviceKeysSignedBuffer, KEYS_UPLOAD_REQUEST_SIZE); + g_KeysUploadRequestBuffer, deviceKeysBufferLen, + g_KeysUploadRequestSignedBuffer, KEYS_UPLOAD_REQUEST_SIZE); - static char finalEvent[KEYS_UPLOAD_REQUEST_SIGNED_SIZE]; - snprintf(finalEvent, KEYS_UPLOAD_REQUEST_SIGNED_SIZE, - "{\"device_keys\":%s}", deviceKeysSignedBuffer); + STATIC char finalEvent[KEYS_UPLOAD_REQUEST_SIGNED_SIZE+30]; + snprintf(finalEvent, KEYS_UPLOAD_REQUEST_SIGNED_SIZE+30, + "{\"device_keys\":%s}", g_KeysUploadRequestSignedBuffer); - static char responseBuffer[KEYS_UPLOAD_RESPONSE_SIZE]; - MatrixHttpPost(client, + STATIC char responseBuffer[KEYS_UPLOAD_RESPONSE_SIZE]; + MatrixHttpPost(client->hc, KEYS_UPLOAD_URL, finalEvent, responseBuffer, KEYS_UPLOAD_RESPONSE_SIZE, @@ -802,7 +684,7 @@ MatrixClientClaimOnetimeKey( const char * deviceId, char * outOnetimeKey, int outOnetimeKeyCap) { - static char requestBuffer[KEYS_CLAIM_REQUEST_SIZE]; + STATIC char requestBuffer[KEYS_CLAIM_REQUEST_SIZE]; mjson_snprintf(requestBuffer, KEYS_CLAIM_REQUEST_SIZE, "{" "\"one_time_keys\":{" @@ -815,18 +697,18 @@ MatrixClientClaimOnetimeKey( userId, deviceId); - static char responseBuffer[KEYS_CLAIM_RESPONSE_SIZE]; - MatrixHttpPost(client, + STATIC char responseBuffer[KEYS_CLAIM_RESPONSE_SIZE]; + MatrixHttpPost(client->hc, KEYS_CLAIM_URL, requestBuffer, responseBuffer, KEYS_CLAIM_RESPONSE_SIZE, true); - char userIdEscaped[USER_ID_SIZE]; + STATIC char userIdEscaped[USER_ID_SIZE]; JsonEscape(userId, strlen(userId), userIdEscaped, USER_ID_SIZE); - static char query[JSON_QUERY_SIZE]; + STATIC char query[JSON_QUERY_SIZE]; snprintf(query, JSON_QUERY_SIZE, "$.one_time_keys.%s.%s", userIdEscaped, @@ -858,7 +740,7 @@ MatrixClientLoginPassword( const char * password, const char * displayName) { - static char requestBuffer[LOGIN_REQUEST_SIZE]; + STATIC char requestBuffer[LOGIN_REQUEST_SIZE]; mjson_snprintf(requestBuffer, LOGIN_REQUEST_SIZE, "{" @@ -874,9 +756,9 @@ MatrixClientLoginPassword( password, displayName); - static char responseBuffer[LOGIN_RESPONSE_SIZE]; + STATIC char responseBuffer[LOGIN_RESPONSE_SIZE]; bool result = - MatrixHttpPost(client, + MatrixHttpPost(client->hc, LOGIN_URL, requestBuffer, responseBuffer, LOGIN_RESPONSE_SIZE, @@ -899,6 +781,8 @@ MatrixClientLoginPassword( mjson_get_string(responseBuffer, responseLen, "$.refresh_token", client->refreshToken, REFRESH_TOKEN_SIZE); + + MatrixHttpSetAccessToken(client->hc, client->accessToken); return true; } @@ -911,13 +795,13 @@ MatrixClientSendEvent( const char * msgType, const char * msgBody) { - static char requestUrl[MAX_URL_LEN]; + STATIC char requestUrl[MAX_URL_LEN]; sprintf(requestUrl, ROOM_SEND_URL, roomId, msgType, (int)time(NULL)); - static char responseBuffer[ROOM_SEND_RESPONSE_SIZE]; + STATIC char responseBuffer[ROOM_SEND_RESPONSE_SIZE]; bool result = - MatrixHttpPut(client, + MatrixHttpPut(client->hc, requestUrl, msgBody, responseBuffer, ROOM_SEND_RESPONSE_SIZE, @@ -936,7 +820,7 @@ MatrixClientSendEventEncrypted( const char * msgBody) { // event json - static char requestBuffer[ROOM_SEND_REQUEST_SIZE]; + STATIC char requestBuffer[ROOM_SEND_REQUEST_SIZE]; sprintf(requestBuffer, "{" "\"type\":\"%s\"," @@ -953,10 +837,9 @@ MatrixClientSendEventEncrypted( MatrixClientNewMegolmOutSession(client, roomId, &outSession); // encrypt - static char encryptedBuffer[ENCRYPTED_REQUEST_SIZE]; MatrixMegolmOutSessionEncrypt(outSession, requestBuffer, - encryptedBuffer, ENCRYPTED_REQUEST_SIZE); + g_EncryptedRequestBuffer, ENCRYPTED_REQUEST_SIZE); char thisDeviceKey[DEVICE_KEY_SIZE]; MatrixOlmAccountGetDeviceKey(&client->olmAccount, thisDeviceKey, DEVICE_KEY_SIZE); @@ -967,8 +850,7 @@ MatrixClientSendEventEncrypted( const char * sessionId = outSession->id; const char * deviceId = client->deviceId; - static char encryptedEventBuffer[ENCRYPTED_EVENT_SIZE]; - sprintf(encryptedEventBuffer, + snprintf(g_EncryptedEventBuffer, ENCRYPTED_EVENT_SIZE, "{" "\"algorithm\":\"m.megolm.v1.aes-sha2\"," "\"ciphertext\":\"%s\"," @@ -976,7 +858,7 @@ MatrixClientSendEventEncrypted( "\"sender_key\":\"%s\"," "\"session_id\":\"%s\"" "}", - encryptedBuffer, + g_EncryptedRequestBuffer, deviceId, senderKey, sessionId); @@ -985,7 +867,442 @@ MatrixClientSendEventEncrypted( return MatrixClientSendEvent(client, roomId, "m.room.encrypted", - encryptedEventBuffer); + g_EncryptedEventBuffer); +} + +void +MatrixClientHandleEvent( + MatrixClient * client, + const char * event, int eventLen +) { + STATIC char eventType[128]; + memset(eventType, 0, sizeof(eventType)); + mjson_get_string(event, eventLen, "$.type", eventType, 128); + + static char transactionId[64]; + static char verifyFromDeviceId[DEVICE_ID_SIZE]; + static OlmSAS * olmSas = NULL; + + if (strcmp(eventType, "m.key.verification.request") == 0) { + memset(transactionId, 0, 64); + if (olmSas != NULL) + free(olmSas); + + mjson_get_string(event, eventLen, "$.content.transaction_id", transactionId, 64); + mjson_get_string(event, eventLen, "$.content.from_device", verifyFromDeviceId, DEVICE_ID_SIZE); + + char verificationReadyBuffer[2048]; + snprintf(verificationReadyBuffer, 2048, + "{" + "\"from_device\":\"%s\"," + "\"methods\":[\"m.sas.v1\"]," + "\"transaction_id\":\"%s\"" + "}", + client->deviceId, + transactionId); + + MatrixClientSendToDevice(client, + client->userId, + verifyFromDeviceId, + verificationReadyBuffer, + "m.key.verification.ready"); + } + else if (strcmp(eventType, "m.key.verification.start") == 0) { + olmSas = olm_sas(malloc(olm_sas_size())); + void * sasRandomBytes = malloc(olm_create_sas_random_length(olmSas)); + olm_create_sas(olmSas, + sasRandomBytes, + olm_create_sas_random_length(olmSas)); + + OlmUtility * olmUtil = olm_utility(malloc(olm_utility_size())); + + STATIC char publicKey[64]; + STATIC char keyStartJsonCanonical[512]; + STATIC char concat[512+64]; + STATIC char commitment[1024]; + olm_sas_get_pubkey(olmSas, + publicKey, + 64); + printf("public key: %.*s\n", olm_sas_pubkey_length(olmSas), publicKey); + + const char * keyStartJson; + int keyStartJsonLen; + mjson_find(event, eventLen, "$.content", &keyStartJson, &keyStartJsonLen); + JsonCanonicalize(keyStartJson, keyStartJsonLen, keyStartJsonCanonical, 512); + + printf("json:\n%.*s\ncanonical json:\n%s\n", keyStartJsonLen, keyStartJson, keyStartJsonCanonical); + + int concatLen = + snprintf(concat, 512+64, "%.*s%s", olm_sas_pubkey_length(olmSas), publicKey, keyStartJsonCanonical); + + int commitmentLen = + olm_sha256(olmUtil, concat, concatLen, commitment, 1024); + + STATIC char verificationAcceptBuffer[512]; + snprintf(verificationAcceptBuffer, 512, + "{" + "\"commitment\":\"%.*s\"," + "\"hash\":\"sha256\"," + "\"key_agreement_protocol\":\"curve25519\"," + "\"message_authentication_code\":\"hkdf-hmac-sha256.v2\"," + "\"method\":\"m.sas.v1\"," + "\"short_authentication_string\":[\"decimal\"]," + "\"transaction_id\":\"%s\"" + "}", + commitmentLen, commitment, + transactionId); + + MatrixClientSendToDevice(client, + client->userId, + verifyFromDeviceId, + verificationAcceptBuffer, + "m.key.verification.accept"); + } + else if (strcmp(eventType, "m.key.verification.key") == 0) { + STATIC char publicKey[128]; + olm_sas_get_pubkey(olmSas, + publicKey, + 128); + + STATIC char theirPublicKey[128]; + int theirPublicKeyLen = + mjson_get_string(event, eventLen, "$.content.key", theirPublicKey, 128); + + printf("event: %.*s\n", eventLen, event); + printf("theirPublicKey: %.*s\n", theirPublicKeyLen, theirPublicKey); + printf("publicKey: %.*s\n", olm_sas_pubkey_length(olmSas), publicKey); + + olm_sas_set_their_key(olmSas, theirPublicKey, theirPublicKeyLen); + + STATIC char verificationKeyBuffer[256]; + snprintf(verificationKeyBuffer, 256, + "{" + "\"key\":\"%.*s\"," + "\"transaction_id\":\"%s\"" + "}", + olm_sas_pubkey_length(olmSas), publicKey, + transactionId); + + MatrixClientSendToDevice(client, + client->userId, + verifyFromDeviceId, + verificationKeyBuffer, + "m.key.verification.key"); + + // sas + STATIC char hkdfInfo[1024]; + int hkdfInfoLen = + snprintf(hkdfInfo, 1024, + "MATRIX_KEY_VERIFICATION_SAS%s%s%s%s%s", + client->userId, + verifyFromDeviceId, + client->userId, + client->deviceId, + transactionId); + + unsigned char sasBytes[5]; + olm_sas_generate_bytes(olmSas, + hkdfInfo, hkdfInfoLen, + sasBytes, 5); + int b0 = sasBytes[0]; + int b1 = sasBytes[1]; + int b2 = sasBytes[2]; + int b3 = sasBytes[3]; + int b4 = sasBytes[4]; + + printf("%d %d %d %d %d\n", b0, b1, b2, b3, b4); + + // https://spec.matrix.org/v1.7/client-server-api/#sas-method-decimal + printf("%d | %d | %d\n", + (b0 << 5 | b1 >> 3) + 1000, + ((b1 & 0x7) << 10 | b2 << 2 | b3 >> 6) + 1000, + ((b3 & 0x3F) << 7 | b4 >> 1) + 1000); + printf("%d | %d | %d\n", + ((b0 << 5) | (b1 >> 3)) + 1000, + (((b1 & 0x7) << 10) | (b2 << 2) | (b3 >> 6)) + 1000, + (((b3 & 0x3F) << 7) | (b4 >> 1)) + 1000); + } + else if (strcmp(eventType, "m.key.verification.mac") == 0) { + // mac + STATIC char masterKey[123]; + MatrixClientRequestMasterKey(client, masterKey, 123); + + STATIC char keyList[256]; + STATIC char keyListMac[256]; + STATIC char key1Id[128]; + STATIC char key1[128]; + STATIC char key1Mac[128]; + STATIC char key2Id[128]; + STATIC char key2[128]; + STATIC char key2Mac[128]; + + if (strcmp(masterKey, client->deviceId) < 0) { + snprintf(key1Id, 1024, "ed25519:%s", masterKey); + strcpy(key1, masterKey); + snprintf(key2Id, 1024, "ed25519:%s", client->deviceId); + MatrixOlmAccountGetSigningKey(&client->olmAccount, key2, 1024); + } + else { + snprintf(key1Id, 1024, "ed25519:%s", client->deviceId); + MatrixOlmAccountGetSigningKey(&client->olmAccount, key1, 1024); + snprintf(key2Id, 1024, "ed25519:%s", masterKey); + strcpy(key2, masterKey); + } + + snprintf(keyList, 1024, + "%s,%s", key1Id, key2Id); + + STATIC char macInfo[1024]; + int macInfoLen; + { + macInfoLen = + snprintf(macInfo, 1024, + "MATRIX_KEY_VERIFICATION_MAC%s%s%s%s%s%s", + client->userId, + client->deviceId, + client->userId, + verifyFromDeviceId, + transactionId, + "KEY_IDS"); + olm_sas_calculate_mac_fixed_base64(olmSas, keyList, strlen(keyList), macInfo, macInfoLen, keyListMac, 1024); + } + { + macInfoLen = + snprintf(macInfo, 1024, + "MATRIX_KEY_VERIFICATION_MAC%s%s%s%s%s%s", + client->userId, + client->deviceId, + client->userId, + verifyFromDeviceId, + transactionId, + key1Id); + olm_sas_calculate_mac_fixed_base64(olmSas, key1, strlen(key1), macInfo, macInfoLen, key1Mac, 1024); + } + { + macInfoLen = + snprintf(macInfo, 1024, + "MATRIX_KEY_VERIFICATION_MAC%s%s%s%s%s%s", + client->userId, + client->deviceId, + client->userId, + verifyFromDeviceId, + transactionId, + key2Id); + olm_sas_calculate_mac_fixed_base64(olmSas, key2, strlen(key2), macInfo, macInfoLen, key2Mac, 1024); + } + + STATIC char verificationMacBuffer[1024]; + snprintf(verificationMacBuffer, 1024, + "{" + "\"keys\":\"%s\"," + "\"mac\":{" + "\"%s\":\"%s\"," + "\"%s\":\"%s\"" + "}," + "\"transaction_id\":\"%s\"" + "}", + keyListMac, + key1Id, + key1Mac, + key2Id, + key2Mac, + transactionId); + + MatrixClientSendToDevice(client, + client->userId, + verifyFromDeviceId, + verificationMacBuffer, + "m.key.verification.mac"); + + STATIC char verificationDoneBuffer[128]; + snprintf(verificationDoneBuffer, 128, + "{" + "\"transaction_id\":\"%s\"" + "}", + transactionId); + + MatrixClientSendToDevice(client, + client->userId, + verifyFromDeviceId, + verificationDoneBuffer, + "m.key.verification.done"); + + free(olmSas); + client->verified = true; + } + else if (strcmp(eventType, "m.room.encrypted") == 0) { + STATIC char algorithm[128]; + mjson_get_string(event, eventLen, "$.content.algorithm", algorithm, 128); + + if (strcmp(algorithm, "m.olm.v1.curve25519-aes-sha2") == 0) { + STATIC char thisDeviceKey[DEVICE_KEY_SIZE]; + MatrixOlmAccountGetDeviceKey(&client->olmAccount, thisDeviceKey, DEVICE_KEY_SIZE); + + STATIC char jp[128]; + snprintf(jp, 128, "$.content.ciphertext.%s.type", thisDeviceKey); + + double messageType; + mjson_get_number(event, eventLen, jp, &messageType); + int messageTypeInt = (int)messageType; + + snprintf(jp, 128, "$.content.ciphertext.%s.body", thisDeviceKey); + + mjson_get_string(event, eventLen, jp, g_EncryptedEventBuffer, 2048); + + MatrixOlmSession * olmSession; + + if (! MatrixClientGetOlmSession(client, client->userId, verifyFromDeviceId, &olmSession)) + { + if (messageTypeInt == 0) { + MatrixClientNewOlmSessionIn(client, + client->userId, + verifyFromDeviceId, + g_EncryptedEventBuffer, + &olmSession); + } + else { + MatrixClientNewOlmSessionOut(client, + client->userId, + verifyFromDeviceId, + &olmSession); + } + } + + STATIC char decrypted[2048]; + MatrixOlmSessionDecrypt(olmSession, + messageTypeInt, g_EncryptedEventBuffer, decrypted, 2048); + + MatrixClientHandleEvent(client, decrypted, strlen(decrypted)); + } + } + else if (strcmp(eventType, "m.room_key") == 0 || + strcmp(eventType, "m.forwarded_room_key") == 0) { + STATIC char roomId[128]; + STATIC char sessionId[128]; + STATIC char sessionKey[1024]; + mjson_get_string(event, eventLen, "$.content.room_id", roomId, 128); + mjson_get_string(event, eventLen, "$.content.session_id", sessionId, 128); + mjson_get_string(event, eventLen, "$.content.session_key", sessionKey, 1024); + + printf("sessionId: %s\n", sessionId); + printf("sessionKey: %s\n", sessionKey); + + MatrixMegolmInSession * megolmInSession; + MatrixClientNewMegolmInSession(client, roomId, sessionId, sessionKey, &megolmInSession); + } +} + +void +MatrixClientHandleRoomEvent( + MatrixClient * client, + const char * room, int roomLen, + const char * event, int eventLen) +{ + STATIC char eventType[128]; + memset(eventType, 0, sizeof(eventType)); + mjson_get_string(event, eventLen, "$.type", eventType, 128); + + if (strcmp(eventType, "m.room.encrypted") == 0) { + STATIC char algorithm[128]; + mjson_get_string(event, eventLen, "$.content.algorithm", algorithm, 128); + + if (strcmp(algorithm, "m.megolm.v1.aes-sha2") == 0) { + STATIC char sessionId[128]; + int sessionIdLen = + mjson_get_string(event, eventLen, "$.content.session_id", sessionId, 128); + + bool res; + + MatrixMegolmInSession * megolmInSession; + res = MatrixClientGetMegolmInSession(client, + room, roomLen, + sessionId, sessionIdLen, + &megolmInSession); + + if (res) { + mjson_get_string(event, eventLen, "$.content.ciphertext", g_EncryptedEventBuffer, 2048); + + STATIC char decrypted[2048]; + MatrixMegolmInSessionDecrypt(megolmInSession, g_EncryptedEventBuffer, strlen(g_EncryptedEventBuffer), decrypted, 2048); + + MatrixClientHandleEvent(client, decrypted, strlen(decrypted)); + } + else { + printf("megolm session not known\n"); + } + } + } + MatrixClientHandleEvent(client, event, eventLen); +} + +void +MatrixClientHandleSync( + MatrixClient * client, + char * syncBuffer, int syncBufferLen, + char * nextBatch, int nextBatchCap) +{ + int res; + + const char * s = syncBuffer; + int slen = syncBufferLen; + + mjson_get_string(s, slen, "$.next_batch", nextBatch, nextBatchCap); + + // to_device + + const char * events; + int eventsLen; + res = + mjson_find(s, slen, "$.to_device.events", &events, &eventsLen); + + if (res != MJSON_TOK_INVALID) { + { + int koff, klen, voff, vlen, vtype, off = 0; + for (off = 0; (off = mjson_next(events, eventsLen, off, &koff, &klen, + &voff, &vlen, &vtype)) != 0; ) { + const char * v = events + voff; + + MatrixClientHandleEvent(client, v, vlen); + } + } + } + + // rooms + + const char * rooms; + int roomsLen; + res = + mjson_find(s, slen, "$.rooms.join", &rooms, &roomsLen); + + if (res != MJSON_TOK_INVALID) { + { + int koff, klen, voff, vlen, vtype, off = 0; + for (off = 0; (off = mjson_next(rooms, roomsLen, off, &koff, &klen, + &voff, &vlen, &vtype)) != 0; ) { + const char * k = rooms + koff; + const char * v = rooms + voff; + + const char * events; + int eventsLen; + res = + mjson_find(v, vlen, "$.timeline.events", &events, &eventsLen); + + if (res != MJSON_TOK_INVALID) { + { + int koff2, klen2, voff2, vlen2, vtype2, off2 = 0; + for (off2 = 0; (off2 = mjson_next(events, eventsLen, off2, &koff2, &klen2, + &voff2, &vlen2, &vtype2)) != 0; ) { + const char * v2 = events + voff2; + + MatrixClientHandleRoomEvent(client, + k+1, klen-2, + v2, vlen2); + } + } + } + } + } + } } // https://spec.matrix.org/v1.6/client-server-api/#get_matrixclientv3sync @@ -993,13 +1310,15 @@ bool MatrixClientSync( MatrixClient * client, char * outSyncBuffer, int outSyncCap, - const char * nextBatch) + char * nextBatch, int nextBatchCap) { // filter={\"event_fields\":[\"to_device\"]} - static char url[MAX_URL_LEN]; + STATIC char url[MAX_URL_LEN]; snprintf(url, MAX_URL_LEN, - "/_matrix/client/v3/sync?timeout=%d%s", + "/_matrix/client/v3/sync?timeout=%d" "%s" "%s", SYNC_TIMEOUT, + "", + // "&filter={\"event_fields\":[\"to_device\"]}", strlen(nextBatch) > 0 ? "&since=" : ""); int index = strlen(url); @@ -1018,11 +1337,17 @@ MatrixClientSync( } url[index] = '\0'; - return - MatrixHttpGet(client, + bool result = + MatrixHttpGet(client->hc, url, outSyncBuffer, outSyncCap, true); + + MatrixClientHandleSync(client, + outSyncBuffer, strlen(outSyncBuffer), + nextBatch, nextBatchCap); + + return result; } // https://spec.matrix.org/v1.7/client-server-api/#get_matrixclientv3roomsroomideventeventid @@ -1033,14 +1358,14 @@ MatrixClientGetRoomEvent( const char * eventId, char * outEvent, int outEventCap) { - static char url[MAX_URL_LEN]; + STATIC char url[MAX_URL_LEN]; snprintf(url, MAX_URL_LEN, "/_matrix/client/v3/rooms/%s/event/%s", roomId, eventId); return - MatrixHttpGet(client, + MatrixHttpGet(client->hc, url, outEvent, outEventCap, true); @@ -1054,7 +1379,7 @@ MatrixClientShareMegolmOutSession( MatrixMegolmOutSession * session) { // generate room key event - static char eventBuffer[KEY_SHARE_EVENT_LEN]; + STATIC char eventBuffer[KEY_SHARE_EVENT_LEN]; sprintf(eventBuffer, "{" "\"algorithm\":\"m.megolm.v1.aes-sha2\"," @@ -1210,7 +1535,7 @@ MatrixClientRequestMegolmInSession( // TODO: cancel requests MatrixClientSendDummy(client, userId, deviceId); - static char event[ROOMKEY_REQUEST_SIZE]; + STATIC char event[ROOMKEY_REQUEST_SIZE]; snprintf(event, ROOMKEY_REQUEST_SIZE, "{" "\"action\":\"request\"," @@ -1220,7 +1545,7 @@ MatrixClientRequestMegolmInSession( "\"sender_key\":\"%s\"," "\"session_id\":\"%s\"" "}," - "\"request_id\":\"%d\"," + "\"request_id\":\"%lld\"," "\"requesting_device_id\":\"%s\"" "}", roomId, @@ -1240,13 +1565,14 @@ MatrixClientRequestMegolmInSession( } bool -MatrixClientGetOlmSessionIn( +MatrixClientGetOlmSession( MatrixClient * client, const char * userId, const char * deviceId, - const char * encrypted, MatrixOlmSession ** outSession) { + (void)userId; //unused for now + for (int i = 0; i < client->numOlmSessions; i++) { if (strcmp(client->olmSessions[i].deviceId, deviceId) == 0) @@ -1256,9 +1582,22 @@ MatrixClientGetOlmSessionIn( } } + return false; +} + +bool +MatrixClientNewOlmSessionIn( + MatrixClient * client, + const char * userId, + const char * deviceId, + const char * encrypted, + MatrixOlmSession ** outSession) +{ + (void)userId; //unused for now + if (client->numOlmSessions < NUM_OLM_SESSIONS) { - static char deviceKey[DEVICE_KEY_SIZE]; + STATIC char deviceKey[DEVICE_KEY_SIZE]; MatrixClientRequestDeviceKey(client, deviceId, deviceKey, DEVICE_KEY_SIZE); @@ -1281,24 +1620,15 @@ MatrixClientGetOlmSessionIn( } bool -MatrixClientGetOlmSessionOut( +MatrixClientNewOlmSessionOut( MatrixClient * client, const char * userId, const char * deviceId, MatrixOlmSession ** outSession) { - for (int i = 0; i < client->numOlmSessions; i++) - { - if (strcmp(client->olmSessions[i].deviceId, deviceId) == 0) - { - *outSession = &client->olmSessions[i]; - return true; - } - } - if (client->numOlmSessions < NUM_OLM_SESSIONS) { - static char deviceKey[DEVICE_KEY_SIZE]; + STATIC char deviceKey[DEVICE_KEY_SIZE]; MatrixClientRequestDeviceKey(client, deviceId, deviceKey, DEVICE_KEY_SIZE); @@ -1335,12 +1665,11 @@ MatrixClientSendToDevice( const char * message, const char * msgType) { - static char requestUrl[MAX_URL_LEN]; + STATIC char requestUrl[MAX_URL_LEN]; sprintf(requestUrl, TODEVICE_URL, msgType, (int)time(NULL)); - static char eventBuffer[TODEVICE_EVENT_SIZE]; - snprintf(eventBuffer, TODEVICE_EVENT_SIZE, + snprintf(g_TodeviceEventBuffer, TODEVICE_EVENT_SIZE, "{" "\"messages\":{" "\"%s\":{" @@ -1352,11 +1681,11 @@ MatrixClientSendToDevice( deviceId, message); - static char responseBuffer[ROOM_SEND_RESPONSE_SIZE]; + STATIC char responseBuffer[ROOM_SEND_RESPONSE_SIZE]; bool result = - MatrixHttpPut(client, + MatrixHttpPut(client->hc, requestUrl, - eventBuffer, + g_TodeviceEventBuffer, responseBuffer, ROOM_SEND_RESPONSE_SIZE, true); @@ -1375,7 +1704,8 @@ MatrixClientSendToDeviceEncrypted( { // get olm session MatrixOlmSession * olmSession; - MatrixClientGetOlmSessionOut(client, userId, deviceId, &olmSession); + if (! MatrixClientGetOlmSession(client, userId, deviceId, &olmSession)) + MatrixClientNewOlmSessionOut(client, userId, deviceId, &olmSession); // create event json char targetDeviceKey[DEVICE_KEY_SIZE]; @@ -1386,18 +1716,17 @@ MatrixClientSendToDeviceEncrypted( char thisSigningKey[DEVICE_KEY_SIZE]; MatrixOlmAccountGetSigningKey(&client->olmAccount, thisSigningKey, DEVICE_KEY_SIZE); - static char eventBuffer[TODEVICE_EVENT_SIZE]; - sprintf(eventBuffer, + snprintf(g_TodeviceEventBuffer, TODEVICE_EVENT_SIZE, "{" "\"type\":\"%s\"," "\"content\":%s," "\"sender\":\"%s\"," "\"recipient\":\"%s\"," "\"recipient_keys\":{" - "\"ed25519\":\"%s\"" + "\"ed25519\":\"%s\"" "}," "\"keys\":{" - "\"ed25519\":\"%s\"" + "\"ed25519\":\"%s\"" "}" "}", msgType, @@ -1408,17 +1737,14 @@ MatrixClientSendToDeviceEncrypted( thisSigningKey); // encrypt - static char encryptedBuffer[ENCRYPTED_REQUEST_SIZE]; MatrixOlmSessionEncrypt(olmSession, - eventBuffer, - encryptedBuffer, ENCRYPTED_REQUEST_SIZE); + g_TodeviceEventBuffer, + g_EncryptedRequestBuffer, ENCRYPTED_REQUEST_SIZE); char thisDeviceKey[DEVICE_KEY_SIZE]; MatrixOlmAccountGetDeviceKey(&client->olmAccount, thisDeviceKey, DEVICE_KEY_SIZE); - - static char encryptedEventBuffer[ENCRYPTED_EVENT_SIZE]; - sprintf(encryptedEventBuffer, + snprintf(g_EncryptedEventBuffer, ENCRYPTED_EVENT_SIZE, "{" "\"algorithm\":\"m.olm.v1.curve25519-aes-sha2\"," "\"ciphertext\":{" @@ -1431,7 +1757,8 @@ MatrixClientSendToDeviceEncrypted( "\"sender_key\":\"%s\"" "}", targetDeviceKey, - encryptedBuffer, + // olm_encrypt_message_length(olmSession->session, strlen(g_TodeviceEventBuffer)), g_EncryptedRequestBuffer, + g_EncryptedRequestBuffer, olm_session_has_received_message(olmSession->session), client->deviceId, thisDeviceKey); @@ -1441,7 +1768,7 @@ MatrixClientSendToDeviceEncrypted( client, userId, deviceId, - encryptedEventBuffer, + g_EncryptedEventBuffer, "m.room.encrypted"); } @@ -1465,6 +1792,15 @@ MatrixClientFindDevice( const char * deviceId, MatrixDevice ** outDevice) { + for (int i = 0; i < client->numDevices; i++) + { + if (strcmp(client->devices[i].deviceId, deviceId) == 0) + { + *outDevice = &client->devices[i]; + return true; + } + } + MatrixClientRequestDeviceKeys(client); for (int i = 0; i < client->numDevices; i++) @@ -1530,21 +1866,46 @@ MatrixClientRequestSigningKey( return false; } +bool +MatrixClientRequestMasterKey( + MatrixClient * client, + char * outMasterKey, int outMasterKeyCap) +{ + if (strlen(client->masterKey) > 0) { + strncpy(outMasterKey, outMasterKeyCap, client->masterKey); + return true; + } + + MatrixClientRequestDeviceKeys(client); + + if (strlen(client->masterKey) > 0) { + strncpy(outMasterKey, outMasterKeyCap, client->masterKey); + return true; + } + + return false; +} + // https://spec.matrix.org/v1.6/client-server-api/#post_matrixclientv3keysquery bool MatrixClientRequestDeviceKeys( MatrixClient * client) { - static char userIdEscaped[USER_ID_SIZE]; + if (client->numDevices >= NUM_DEVICES) { + printf("Maximum number of devices reached\n"); + return false; + } + + STATIC char userIdEscaped[USER_ID_SIZE]; JsonEscape(client->userId, strlen(client->userId), userIdEscaped, USER_ID_SIZE); - static char request[KEYS_QUERY_REQUEST_SIZE]; + STATIC char request[KEYS_QUERY_REQUEST_SIZE]; snprintf(request, KEYS_QUERY_REQUEST_SIZE, "{\"device_keys\":{\"%s\":[]}}", client->userId); - static char responseBuffer[KEYS_QUERY_RESPONSE_SIZE]; - bool requestResult = MatrixHttpPost(client, + STATIC char responseBuffer[KEYS_QUERY_RESPONSE_SIZE]; + bool requestResult = MatrixHttpPost(client->hc, KEYS_QUERY_URL, request, responseBuffer, KEYS_QUERY_RESPONSE_SIZE, @@ -1554,18 +1915,32 @@ MatrixClientRequestDeviceKeys( return false; // query for retrieving device keys for user id - static char query[JSON_QUERY_SIZE]; + STATIC char query[JSON_QUERY_SIZE]; + const char * s; + int slen; + + snprintf(query, JSON_QUERY_SIZE, + "$.master_keys.%s.keys", userIdEscaped); + mjson_find(responseBuffer, strlen(responseBuffer), + query, &s, &slen); + + int koff, klen, voff, vlen, vtype, off = 0; + for (off = 0; (off = mjson_next(s, slen, off, &koff, &klen, + &voff, &vlen, &vtype)) != 0; ) { + snprintf(client->masterKey, MASTER_KEY_SIZE, + "%.*s", vlen-2, s+voff+1); + + printf("found master key: %s\n", client->masterKey); + } + snprintf(query, JSON_QUERY_SIZE, "$.device_keys.%s", userIdEscaped); - const char * s; - int slen; mjson_find(responseBuffer, strlen(responseBuffer), query, &s, &slen); // loop over keys - int koff, klen, voff, vlen, vtype, off = 0; for (off = 0; (off = mjson_next(s, slen, off, &koff, &klen, &voff, &vlen, &vtype)) != 0; ) { const char * key = s + koff; @@ -1577,14 +1952,14 @@ MatrixClientRequestDeviceKeys( "%.*s", klen-2, key+1); // look for device key in value - static char deviceKeyQuery[JSON_QUERY_SIZE]; + STATIC char deviceKeyQuery[JSON_QUERY_SIZE]; snprintf(deviceKeyQuery, JSON_QUERY_SIZE, "$.keys.curve25519:%s", d.deviceId); mjson_get_string(val, vlen, deviceKeyQuery, d.deviceKey, DEVICE_KEY_SIZE); // look for signing key in value - static char signingKeyQuery[JSON_QUERY_SIZE]; + STATIC char signingKeyQuery[JSON_QUERY_SIZE]; snprintf(signingKeyQuery, JSON_QUERY_SIZE, "$.keys.ed25519:%s", d.deviceId); mjson_get_string(val, vlen, @@ -1617,12 +1992,12 @@ bool MatrixClientDeleteDevice( MatrixClient * client) { - static char deleteRequest[1024]; + STATIC char deleteRequest[1024]; snprintf(deleteRequest, 1024, "{\"devices\":[\"%s\"]}", client->deviceId); - static char deleteResponse[1024]; - bool res = MatrixHttpPost(client, "/_matrix/client/v3/delete_devices", + STATIC char deleteResponse[1024]; + bool res = MatrixHttpPost(client->hc, "/_matrix/client/v3/delete_devices", deleteRequest, deleteResponse, 1024, true); return res; -} \ No newline at end of file +}