Skip to content

Commit

Permalink
Add logic for <keys/> nodes and "kex" attribute
Browse files Browse the repository at this point in the history
According to:
https://xmpp.org/extensions/xep-0384.html#message-structure-description

Nodes for encrypted symmetric <key/> for a particular recipient should be nested
in a <keys/> node with its "jid" attribute set to the recipient's bare JID, with
an optional "kex" attribute for key exchange usage.

Functions related to these above are modified accordingly.

Signed-off-by: HardenedVault <root@hardenedvault.net>
  • Loading branch information
root-hardenedvault committed Feb 12, 2021
1 parent 5136540 commit 630151e
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 15 deletions.
39 changes: 34 additions & 5 deletions src/libomemo.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#define ENCRYPTED_NODE_NAME "encrypted"
#define HEADER_NODE_NAME "header"
#define IV_NODE_NAME "iv"
#define RECIPIENT_NODE_NAME "keys"
#define KEY_NODE_NAME "key"
#define PAYLOAD_NODE_NAME "payload"
#define STORE_NODE_NAME "store"
Expand All @@ -61,7 +62,9 @@
#define MESSAGE_NODE_FROM_ATTR_NAME "from"
#define MESSAGE_NODE_TO_ATTR_NAME "to"
#define HEADER_NODE_SID_ATTR_NAME "sid"
#define RECIPIENT_NODE_JID_ATTR_NAME "jid"
#define KEY_NODE_RID_ATTR_NAME "rid"
#define KEY_NODE_KEX_ATTR_NAME "kex"
#define PUBLISH_NODE_NODE_ATTR_NAME "node"
#define SIGNED_PRE_KEY_NODE_ID_ATTR_NAME "signedPreKeyId"
#define PRE_KEY_NODE_ID_ATTR_NAME "preKeyId"
Expand Down Expand Up @@ -1151,7 +1154,7 @@ size_t omemo_message_get_key_len(omemo_message * msg_p) {
return msg_p->key_len + msg_p->tag_len;
}

int omemo_message_add_recipient(omemo_message * msg_p, uint32_t device_id, const uint8_t * encrypted_key_p, size_t key_len) {
int omemo_message_add_recipient(omemo_message * msg_p, const char* recipient_name_bare, uint32_t device_id, const uint8_t * encrypted_key_p, size_t key_len, int kex) {
if (!msg_p || !msg_p->header_node_p || !encrypted_key_p) {
return OMEMO_ERR_NULL;
}
Expand All @@ -1161,13 +1164,22 @@ int omemo_message_add_recipient(omemo_message * msg_p, uint32_t device_id, const
return OMEMO_ERR;
}

mxml_node_t * recipient_node_p = mxmlFindElement(msg_p->header_node_p, msg_p->header_node_p,
RECIPIENT_NODE_NAME, RECIPIENT_NODE_JID_ATTR_NAME,
recipient_name_bare, MXML_DESCEND);
if (!recipient_node_p) {
recipient_node_p = mxmlNewElement(MXML_NO_PARENT, RECIPIENT_NODE_NAME);
mxmlElementSetAttr(recipient_node_p, RECIPIENT_NODE_JID_ATTR_NAME, recipient_name_bare);
}
gchar * key_b64 = g_base64_encode(encrypted_key_p, key_len);
mxml_node_t * key_node_p = mxmlNewElement(MXML_NO_PARENT, KEY_NODE_NAME);
mxml_node_t * key_node_p = mxmlNewElement(MXML_NO_PARENT, KEY_NODE_NAME);
mxmlElementSetAttr(key_node_p, KEY_NODE_RID_ATTR_NAME, device_id_string);
free(device_id_string);
if (kex)
mxmlElementSetAttr(key_node_p, KEY_NODE_KEX_ATTR_NAME, "true");
(void) mxmlNewOpaque(key_node_p, key_b64);

mxmlAdd(msg_p->header_node_p, MXML_ADD_BEFORE, MXML_ADD_TO_PARENT, key_node_p);
mxmlAdd(msg_p->header_node_p, MXML_ADD_BEFORE, MXML_ADD_TO_PARENT, recipient_node_p);
g_free(key_b64);
return 0;
}
Expand Down Expand Up @@ -1351,19 +1363,35 @@ char * omemo_message_get_recipient_name_bare(omemo_message * msg_p) {
return jid_strip_resource(omemo_message_get_recipient_name_full(msg_p));
}

int omemo_message_get_encrypted_key(omemo_message * msg_p, uint32_t own_device_id, uint8_t ** key_pp, size_t * key_len_p ) {
int omemo_message_get_encrypted_key(omemo_message * msg_p, const char* recipient_name, uint32_t own_device_id, uint8_t ** key_pp, size_t * key_len_p ) {
if (!msg_p || !key_pp) {
return OMEMO_ERR_NULL;
}

int ret_val = 0;

gchar * recipient_name_bare = (void *) 0;
mxml_node_t * recipient_node_p = (void *) 0;
mxml_node_t * key_node_p = (void *) 0;
char * rid_string = (void *) 0;
const char * key_b64 = (void *) 0;
size_t key_len = 0;

key_node_p = mxmlFindElement(msg_p->header_node_p, msg_p->header_node_p, KEY_NODE_NAME, NULL, NULL, MXML_DESCEND);
if (recipient_name) {
recipient_name_bare = jid_strip_resource(recipient_name);
} else {
recipient_name_bare = omemo_message_get_recipient_name_bare(msg_p);
}
recipient_node_p = mxmlFindElement(msg_p->header_node_p, msg_p->header_node_p, RECIPIENT_NODE_NAME,
RECIPIENT_NODE_JID_ATTR_NAME, recipient_name_bare,MXML_DESCEND);
if (recipient_node_p) {
key_node_p = mxmlFindElement(recipient_node_p, recipient_node_p, KEY_NODE_NAME,
NULL, NULL, MXML_DESCEND);
} else {
// Assuming there is no RECIPIENT_NODEs in the message.
key_node_p = mxmlFindElement(msg_p->header_node_p, msg_p->header_node_p, KEY_NODE_NAME,
NULL, NULL, MXML_DESCEND);
}
if (!key_node_p) {
// if there is not at least one key, skip the rest of the function
ret_val = 0;
Expand Down Expand Up @@ -1404,6 +1432,7 @@ int omemo_message_get_encrypted_key(omemo_message * msg_p, uint32_t own_device_i
*key_len_p = key_len;

cleanup:
g_free(recipient_name_bare)
free(rid_string);
return ret_val;
}
Expand Down
23 changes: 13 additions & 10 deletions src/libomemo.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ int omemo_bundle_set_signed_pre_key(omemo_bundle * bundle_p, uint32_t pre_key_id
*
* @param bundle_p Pointer to the bundle.
* @param pre_key_id_p Will be set to the pre key id as returned by strtol.
* @param data_pp Will be set to a pointer to the serialized key data. Has to be free()d when done.
* @param data_pp Will be set to a pointer to the serialized key data. Has to be g_free()d when done.
* @param data_len_p Will be set to the length of the data.
* @return 0 on success, negative on error.
*/
Expand All @@ -172,7 +172,7 @@ int omemo_bundle_set_signature(omemo_bundle * bundle_p, uint8_t * data_p, size_t
* Gets the signature from the specified bundle.
*
* @param bundle_p Pointer to the bundle.
* @param data_pp Will be set to a pointer to the signature data. Has to be free()d when done.
* @param data_pp Will be set to a pointer to the signature data. Has to be g_free()d when done.
* @param data_len_p Will be set to the length of the data.
* @return 0 on succcess, negative on error.
*/
Expand All @@ -192,7 +192,7 @@ int omemo_bundle_set_identity_key(omemo_bundle * bundle_p, uint8_t * data_p, siz
* Gets the identity key from the specified bundle.
*
* @param bundle_p Pointer to the bundle.
* @param data_pp Will be set to a pointer to the identity key data. Has to be free()d when done.
* @param data_pp Will be set to a pointer to the identity key data. Has to be g_free()d when done.
* @param data_len_p Will be set to the length of the data.
* @return 0 on success, negative on error.
*/
Expand All @@ -214,7 +214,7 @@ int omemo_bundle_add_pre_key(omemo_bundle * bundle_p, uint32_t pre_key_id, uint8
*
* @param bundle_p Pointer to the bundle.
* @param pre_key_id_p Will be set to the ID of the selected pre key.
* @param data_pp Will be set to a pointer to the serialized public key data. Has to be free()d when done.
* @param data_pp Will be set to a pointer to the serialized public key data. Has to be g_free()d when done.
* @param data_len_p Will be set to the length of the data.
* @return 0 on success, negative on error.
*/
Expand Down Expand Up @@ -440,16 +440,18 @@ const uint8_t * omemo_message_get_key(omemo_message * msg_p);
size_t omemo_message_get_key_len(omemo_message * msg_p);

/**
* Add the encrypted symmetric key for a specific device id to the message.
* Add the encrypted symmetric key for a specific device to the message.
* Only makes sense on outgoing messages.
*
* @param msg_p Pointer to the message to add to.
* @param recipient_name_bare The bare JID of the recipient.
* @param device_id The recipient device ID.
* @param encrypted_key_p The encrypted key data.
* @param key_len Length of the encrypted key data.
* @param kex Whether the added key is intended for key exchange, default to 0.
* @return 0 on success, negative on error.
*/
int omemo_message_add_recipient(omemo_message * msg_p, uint32_t device_id, const uint8_t * encrypted_key_p, size_t key_len);
int omemo_message_add_recipient(omemo_message * msg_p, const char* recipient_name_bare, uint32_t device_id, const uint8_t * encrypted_key_p, size_t key_len, int kex);

/**
* After all recipients have been added, this function can be used to export the resulting <message> stanza.
Expand Down Expand Up @@ -502,7 +504,7 @@ const char * omemo_message_get_sender_name_full(omemo_message * msg_p);
* Note that there is no "from" attribute in outgoing messages.
*
* @param msg_p Pointer to the message.
* @return The bare JID. Has to be free()d.
* @return The bare JID. Has to be g_free()d.
*/
char * omemo_message_get_sender_name_bare(omemo_message * msg_p);

Expand All @@ -523,16 +525,17 @@ const char * omemo_message_get_recipient_name_full(omemo_message * msg_p);
char * omemo_message_get_recipient_name_bare(omemo_message * msg_p);

/**
* Gets the encrypted key data for a specific device ID (usually your own so you can decrypt it).
* Gets the encrypted key data for a specific device (usually your own so you can decrypt it).
*
* @param msg_p Pointer to the message.
* @param recipient_name The JID get the encrypted key for, could be 0 for the intended recipient of the message.
* @param own_device_id The device ID to get the encrypted key for.
* @param key_pp Will be set to the encrypted key data, or NULL if there is no data for the specified ID.
* Has to be free()d.
* Has to be g_free()d.
* @param key_len_p Will be set to length of encrypted key data.
* @return 0 on success, negative on error. Note that success does not mean a key was found.
*/
int omemo_message_get_encrypted_key(omemo_message * msg_p, uint32_t own_device_id, uint8_t ** key_pp, size_t * key_len_p );
int omemo_message_get_encrypted_key(omemo_message * msg_p, const char* recipient_name, uint32_t own_device_id, uint8_t ** key_pp, size_t * key_len_p );

/**
* Using the decrypted symmetric key, this method decrypts the payload and exports the original <message> stanza.
Expand Down

0 comments on commit 630151e

Please sign in to comment.