#define KEYS_QUERY_REQUEST_SIZE 256\r
#define KEYS_QUERY_RESPONSE_SIZE 1024\r
\r
+#define UPLOAD_KEYS_REQUEST_SIZE 512\r
+#define UPLOAD_KEYS_REQUEST_SIGNED_SIZE 1024\r
+\r
#define JSON_QUERY_SIZE 128\r
\r
\r
\r
void\r
-Randomize(uint8_t * random, int randomLen)\r
+Randomize(\r
+ uint8_t * random,\r
+ int randomLen)\r
{\r
static bool first = false;\r
if (first) { srand(time(0)); first = false; }\r
return true;\r
}\r
\r
+bool JsonSign(\r
+ MatrixClient * client,\r
+ char * sIn, int sInLen,\r
+ char * sOut, int sOutCap)\r
+{\r
+ static char signature[OLM_SIGNATURE_SIZE];\r
+ size_t res =\r
+ olm_account_sign(client->olmAccount.account,\r
+ sIn, sInLen,\r
+ signature, OLM_SIGNATURE_SIZE);\r
+ \r
+ int signatureLen = res;\r
+\r
+ static char signatureJson[JSON_SIGNATURE_SIZE];\r
+ int signatureJsonLen =\r
+ mjson_snprintf(signatureJson, JSON_SIGNATURE_SIZE,\r
+ "{"\r
+ "\"signatures\":{"\r
+ "\"%s\":{"\r
+ "\"ed25519:%s\":\"%.*s\""\r
+ "}"\r
+ "}"\r
+ "}",\r
+ client->userId,\r
+ client->deviceId,\r
+ signatureLen, signature);\r
+\r
+ struct mjson_fixedbuf result = { sOut, sOutCap, 0 };\r
+ mjson_merge(\r
+ sIn, sInLen,\r
+ signatureJson, signatureJsonLen,\r
+ mjson_print_fixed_buf,\r
+ &result);\r
+\r
+ return true;\r
+}\r
+\r
+\r
+bool\r
+MatrixOlmAccountInit(\r
+ MatrixOlmAccount * account)\r
+{\r
+ account->account = olm_account(account->memory);\r
+\r
+ static uint8_t random[OLM_ACCOUNT_RANDOM_SIZE];\r
+ Randomize(random, OLM_ACCOUNT_RANDOM_SIZE);\r
+\r
+ size_t res = olm_create_account(\r
+ account->account,\r
+ random,\r
+ OLM_ACCOUNT_RANDOM_SIZE);\r
+\r
+ return res != olm_error();\r
+}\r
+\r
// TODO: in/outbound sessions\r
bool\r
MatrixOlmSessionInit(\r
strcpy(client->server, server);\r
\r
// init olm account\r
- client->olmAccount = olm_account(client->olmAccountMemory);\r
-\r
- static uint8_t random[OLM_ACCOUNT_RANDOM_SIZE];\r
- Randomize(random, OLM_ACCOUNT_RANDOM_SIZE);\r
-\r
- size_t res;\r
- res = olm_create_account(\r
- client->olmAccount,\r
- random,\r
- OLM_ACCOUNT_RANDOM_SIZE);\r
+ MatrixOlmAccountInit(&client->olmAccount);\r
\r
// set device key\r
static char deviceKeysJson[OLM_IDENTITY_KEYS_JSON_SIZE];\r
- res =\r
+ size_t res =\r
olm_account_identity_keys(\r
- client->olmAccount,\r
+ client->olmAccount.account,\r
deviceKeysJson,\r
OLM_IDENTITY_KEYS_JSON_SIZE);\r
\r
return true;\r
}\r
\r
+bool\r
+MatrixClientSetUserId(\r
+ MatrixClient * client,\r
+ const char * userId)\r
+{\r
+ int userIdLen = strlen(userId);\r
+\r
+ if (userIdLen > USER_ID_SIZE - 1)\r
+ return false;\r
+\r
+ for (int i = 0; i < userIdLen; i++)\r
+ client->userId[i] = userId[i];\r
+\r
+ return true;\r
+}\r
+\r
+bool\r
+MatrixClientGenerateOnetimeKeys(\r
+ MatrixClient * client,\r
+ int numberOfKeys)\r
+{\r
+ static uint8_t random[OLM_ONETIME_KEYS_RANDOM_SIZE];\r
+ Randomize(random, OLM_ONETIME_KEYS_RANDOM_SIZE);\r
+\r
+ size_t res =\r
+ olm_account_generate_one_time_keys(client->olmAccount.account,\r
+ numberOfKeys, random, OLM_ONETIME_KEYS_RANDOM_SIZE);\r
+\r
+ return res != olm_error();\r
+}\r
+\r
+bool\r
+MatrixClientUploadOnetimeKeys(\r
+ MatrixClient * client)\r
+{\r
+ static char requestBuffer[UPLOAD_KEYS_REQUEST_SIZE];\r
+\r
+ mjson_snprintf(requestBuffer, UPLOAD_KEYS_REQUEST_SIZE,\r
+ "{\"one_time_keys\":{");\r
+\r
+ static char onetimeKeysBuffer[1024];\r
+ olm_account_one_time_keys(client->olmAccount.account,\r
+ onetimeKeysBuffer, 1024);\r
+\r
+ const char *keys;\r
+ int keysLen;\r
+ mjson_find(onetimeKeysBuffer, strlen(onetimeKeysBuffer), "$.curve25519", &keys, &keysLen);\r
+\r
+ int koff, klen, voff, vlen, vtype, off = 0;\r
+ while ((off = mjson_next(keys, keysLen, off, &koff, &klen, &voff, &vlen, &vtype)) != 0) {\r
+ static char keyJson[JSON_ONETIME_KEY_SIZE];\r
+ \r
+ snprintf(keyJson, JSON_ONETIME_KEY_SIZE,\r
+ "{\"key\":\"%.*s\"}",\r
+ vlen-2, keys + voff+1);\r
+\r
+ static char keyJsonSigned[JSON_ONETIME_KEY_SIGNED_SIZE];\r
+\r
+ JsonSign(client,\r
+ keyJson, JSON_ONETIME_KEY_SIZE,\r
+ keyJsonSigned, JSON_ONETIME_KEY_SIGNED_SIZE);\r
+ \r
+ mjson_snprintf(requestBuffer+strlen(requestBuffer), UPLOAD_KEYS_REQUEST_SIZE-strlen(requestBuffer),\r
+ "\"signed_curve25519:%.*s\":%s,",\r
+ klen-2, keys + koff+1,\r
+ keyJsonSigned);\r
+ }\r
+\r
+ mjson_snprintf(requestBuffer+strlen(requestBuffer), UPLOAD_KEYS_REQUEST_SIZE-strlen(requestBuffer),\r
+ "}}");\r
+\r
+ printf("%s\n", requestBuffer);\r
+\r
+ return true;\r
+}\r
+\r
+bool\r
+MatrixClientUploadDeviceKeys(\r
+ MatrixClient * client)\r
+{\r
+ static char deviceKeysBuffer[UPLOAD_KEYS_REQUEST_SIZE];\r
+\r
+ mjson_snprintf(deviceKeysBuffer, UPLOAD_KEYS_REQUEST_SIZE,\r
+ "{\"device_keys\":{"\r
+ "\"algorithms\":[\"m.olm.v1.curve25519-aes-sha2\",\"m.megolm.v1.aes-sha2\"],"\r
+ "\"device_id\":\"%s\","\r
+ "\"keys\":{"\r
+ "\"curve25519:%s\":\"%s\","\r
+ "\"ed25519:%s\":\"%s\""\r
+ "},"\r
+ "\"user_id\":\"%s\""\r
+ "}}",\r
+ client->deviceId,\r
+ client->deviceId, client->deviceKey,\r
+ client->deviceId, client->signingKey,\r
+ client->userId);\r
+\r
+ static char deviceKeysSignedBuffer[UPLOAD_KEYS_REQUEST_SIGNED_SIZE];\r
+ JsonSign(client,\r
+ deviceKeysBuffer, UPLOAD_KEYS_REQUEST_SIZE,\r
+ deviceKeysSignedBuffer, UPLOAD_KEYS_REQUEST_SIZE);\r
+\r
+ printf("%s\n", deviceKeysSignedBuffer);\r
+\r
+ return true;\r
+}\r
+\r
// https://spec.matrix.org/v1.6/client-server-api/#post_matrixclientv3login\r
bool\r
MatrixClientLoginPassword(\r
return true;\r
}\r
\r
+bool\r
+MatrixClientShareMegolmOutSessionTest(\r
+ MatrixClient * client,\r
+ const char * deviceId,\r
+ MatrixMegolmOutSession * session)\r
+{\r
+ // generate room key event\r
+ char eventBuffer[KEY_SHARE_EVENT_LEN];\r
+ sprintf(eventBuffer,\r
+ "{"\r
+ "\"algorithm\":\"m.megolm.v1.aes-sha2\","\r
+ "\"room_id\":\"%s\","\r
+ "\"session_id\":\"%s\","\r
+ "\"session_key\":\"%s\""\r
+ "}",\r
+ session->roomId,\r
+ session->id,\r
+ session->key\r
+ );\r
+\r
+ // send\r
+ MatrixClientSendToDevice(client,\r
+ client->userId,\r
+ deviceId,\r
+ eventBuffer,\r
+ "m.room_key");\r
+\r
+ return true;\r
+}\r
+\r
// bool\r
// MatrixClientSetMegolmOutSession(\r
// MatrixClient * client,\r
#define KEY_SHARE_EVENT_LEN 1024\r
\r
#define OLM_ACCOUNT_MEMORY_SIZE 7528\r
-#define OLM_ACCOUNT_RANDOM_SIZE 32+32\r
+#define OLM_ACCOUNT_RANDOM_SIZE (32+32)\r
\r
#define OLM_SESSION_MEMORY_SIZE 3352\r
#define OLM_ENCRYPT_RANDOM_SIZE 32\r
\r
+#define OLM_ONETIME_KEYS_RANDOM_SIZE 32*10\r
+#define OLM_KEY_ID_SIZE 32\r
+\r
+#define OLM_SIGNATURE_SIZE 128\r
+\r
#define MEGOLM_OUTBOUND_SESSION_MEMORY_SIZE 232\r
#define MEGOLM_SESSION_ID_SIZE 44\r
#define MEGOLM_SESSION_KEY_SIZE 306\r
#define MEGOLM_INIT_RANDOM_SIZE (4*32 + 32)\r
\r
+#define JSON_ONETIME_KEY_SIZE 128\r
+#define JSON_ONETIME_KEY_SIGNED_SIZE 256\r
+#define JSON_SIGNATURE_SIZE 256\r
+\r
#define NUM_MEGOLM_SESSIONS 10\r
#define NUM_OLM_SESSIONS 10\r
#define NUM_DEVICES 10\r
JsonEscape(\r
char * sIn, int sInLen,\r
char * sOut, int sOutCap);\r
+ \r
+bool JsonSign(\r
+ char * sIn, int sInLen,\r
+ char * sOut, int sOutCap);\r
+\r
+// Matrix Device\r
\r
typedef struct MatrixDevice {\r
char deviceId[DEVICE_ID_SIZE];\r
char deviceKey[DEVICE_KEY_SIZE];\r
} MatrixDevice;\r
\r
+\r
+// Matrix Olm Account\r
+\r
+typedef struct MatrixOlmAccount {\r
+ OlmAccount * account;\r
+ char memory[OLM_ACCOUNT_MEMORY_SIZE];\r
+} MatrixOlmAccount;\r
+\r
+bool\r
+MatrixOlmAccountInit(\r
+ MatrixOlmAccount * account);\r
+\r
+\r
+// Matrix Olm Session\r
+\r
typedef struct MatrixOlmSession {\r
const char * deviceId;\r
\r
char * outBuffer, int outBufferCap);\r
\r
\r
+// Matrix Megolm Session\r
\r
typedef struct MatrixMegolmInSession {\r
OlmInboundGroupSession * session;\r
char * outBuffer, int outBufferCap);\r
\r
\r
+// Matrix Client\r
\r
typedef struct MatrixClient {\r
- OlmAccount * olmAccount;\r
- char olmAccountMemory[OLM_ACCOUNT_MEMORY_SIZE];\r
+ MatrixOlmAccount olmAccount;\r
\r
MatrixMegolmInSession megolmInSessions[NUM_MEGOLM_SESSIONS];\r
int numMegolmInSessions;\r
MatrixClient * client,\r
const char * deviceId);\r
\r
+bool\r
+MatrixClientSetUserId(\r
+ MatrixClient * client,\r
+ const char * userId);\r
+\r
+bool\r
+MatrixClientGenerateOnetimeKeys(\r
+ MatrixClient * client,\r
+ int numberOfKeys);\r
+\r
+bool\r
+MatrixClientUploadOnetimeKeys(\r
+ MatrixClient * client);\r
+\r
+bool\r
+MatrixClientUploadDeviceKeys(\r
+ MatrixClient * client);\r
+\r
bool\r
MatrixClientLoginPassword(\r
MatrixClient * client,\r
const char * deviceId,\r
MatrixMegolmOutSession * session);\r
\r
+bool\r
+MatrixClientShareMegolmOutSessionTest(\r
+ MatrixClient * client,\r
+ const char * deviceId,\r
+ MatrixMegolmOutSession * session);\r
+\r
bool\r
MatrixClientGetMegolmOutSession(\r
MatrixClient * client,\r