Decrypt attachment key envelopes and retain verified ciphertext

This commit is contained in:
evgeny committed 2026-11-03 12:51:34 +01:00
1 parent de94b5bbaf
commit 7e7e670c0d
2 files changed
+19 -14

No files matched your search

+8 -3
View File
@@ -440,7 +440,9 @@ static int dm_build_body(struct dm_state* dm, const struct dm_conv* c, uint64_t
data += DM_MEDIA_DESC_SIZE;
data_len -= DM_MEDIA_DESC_SIZE;
struct attachment_info info;
if (attachment_decode(data, data_len, &info)) return -1;
const uint8_t* keys;
if (dm_media_metadata_decode(data, data_len, &info, &keys)) return -1;
if (c->mode == DM_MODE_GROUPS && !keys) { DEBUG_WARN(DEBUG_CATEGORY_DM, "DM file: GROUPS keys required"); return -1; }
}
uint64_t conv_num = (uint64_t)strtoull(c->conv_id, NULL, 10);
uint8_t nonce[DM_NONCE_SIZE];
@@ -635,7 +637,9 @@ int dm_accept_message(struct UTUN_INSTANCE* inst, const uint8_t* msg, size_t len
if (media_ccm_decrypt(c.content_key, nonce, message.ciphertext, message.ciphertext_size, plain, &plain_len) != 0) return -1;
if (dm_message_media(msg, len)) {
struct attachment_info info;
if (attachment_decode(plain, plain_len, &info)) return -1;
const uint8_t* keys;
if (dm_media_metadata_decode(plain, plain_len, &info, &keys)) return -1;
if (c.mode == DM_MODE_GROUPS && !keys) { DEBUG_WARN(DEBUG_CATEGORY_DM, "DM file: missing GROUPS key wraps"); return -1; }
}
if (dm_exec(dm, "BEGIN IMMEDIATE") != 0) return -1;
int inserted = dm_store_message(dm, conv_id, dir, msg, len);
@@ -1245,7 +1249,8 @@ int dm_list_messages_json(struct UTUN_INSTANCE* inst, const char* conv_id, int c
struct attachment_info attachment = {0};
int file = ct && !strcmp(ct, "file");
if (file) {
if (attachment_decode((const uint8_t*)text, plen, &attachment)) goto fail;
const uint8_t* keys;
if (dm_media_metadata_decode((const uint8_t*)text, plen, &attachment, &keys)) goto fail;
snprintf(text, sizeof(text), "%s", attachment.name);
}
int ready = sqlite3_column_int(st, 7), downloading = sqlite3_column_int(st, 8);
+11 -11
View File
@@ -681,7 +681,6 @@ static void dm_file_done(void* arg, int error) {
uint8_t stored[24]; memcpy(stored, job->id, 16); memcpy(stored + 16, &expires, 8);
dm_media_send(inst, group, peer, DM_MEDIA_STORED, stored, sizeof(stored));
} else {
dm_file_remove(job->cipher);
dm_media_send(inst, group, peer, DM_MEDIA_RECEIPT, receipt, sizeof(receipt));
dm_mailbox_media_receipt(inst, receipt);
uint64_t conv; memcpy(&conv, body, 8); dm_media_notify(inst, conv);
@@ -724,26 +723,27 @@ static void dm_file_pull(struct dm_media_state* media, int custody, uint64_t gro
if (!job) { DEBUG_ERROR(DEBUG_CATEGORY_DM, "dm_media: download allocation failed"); return; }
job->media = media; job->work = custody ? DM_FILE_CUSTODY : DM_FILE_RECEIVE; job->author = author;
memcpy(job->id, desc, 16); memcpy(&job->size, desc + 16, 8); memcpy(job->hash, desc + 24, 32);
if (dm_file_path(media, custody, job->id, ".download", job->cipher, sizeof(job->cipher)) ||
if (dm_file_path(media, custody, job->id, custody ? ".download" : ".cipher", job->cipher, sizeof(job->cipher)) ||
dm_file_path(media, custody, job->id, ".decrypt", job->temp, sizeof(job->temp)) ||
dm_file_path(media, custody, job->id, custody ? ".cipher" : ".file", job->output, sizeof(job->output))) { u_free(job); return; }
if (!custody) {
snprintf(job->conv, sizeof(job->conv), "%llu", (unsigned long long)dm_derive_conv_id(media->inst->node_id, author));
job->generation = dm_history_generation(media->inst, job->conv);
if (dm_job_hold(job)) { dm_job_free(job); return; }
sqlite3_stmt* st = dm_media_prepare(media->inst, "SELECT x25519_pubkey FROM nodes WHERE node_id=?");
sqlite3_stmt* st = dm_media_prepare(media->inst, "SELECT conv_id,body FROM dm_files WHERE id=? AND dir=0");
if (!st) { dm_job_free(job); return; }
sqlite3_bind_int64(st, 1, (sqlite3_int64)author);
sqlite3_bind_blob(st, 1, job->id, 16, SQLITE_STATIC);
int rc = sqlite3_step(st);
uint8_t pub[32];
int found = rc == SQLITE_ROW && sqlite3_column_bytes(st, 0) == sizeof(pub);
if (found) memcpy(pub, sqlite3_column_blob(st, 0), sizeof(pub));
int found = rc == SQLITE_ROW;
if (found) {
snprintf(job->conv, sizeof(job->conv), "%s", sqlite3_column_text(st, 0));
found = !dm_file_key(media->inst, sqlite3_column_blob(st, 1), (size_t)sqlite3_column_bytes(st, 1), job->key);
}
sqlite3_finalize(st);
if (!found || dm_derive_content_key(media->inst->my_keys.private_key, pub, job->key)) {
if (!found) {
DEBUG_ERROR(DEBUG_CATEGORY_DM, "dm_media: target key unavailable author=%llu", (unsigned long long)author);
dm_job_free(job);
return;
}
job->generation = dm_history_generation(media->inst, job->conv);
if (dm_job_hold(job)) { dm_job_free(job); return; }
}
job->next = media->jobs; media->jobs = job;
job->transfer = file_transfer_pull(media->inst->file_transfer, group, peer, job->id, dm_media_cipher_size(job->size),