Browse Source

Fix DM CCM length setup and separate media nonces

master
evgeny 2 days ago
parent
commit
67bbf80769
  1. 29
      src/dm/dm_crypto.c
  2. 5
      src/dm/dm_crypto.h

29
src/dm/dm_crypto.c

@ -14,6 +14,19 @@
#define DM_ID "dm_crypto"
/* Медиа использует тот же ключ target, но отдельное пространство nonce. */
void dm_build_media_nonce(uint64_t author, const uint8_t media_id[16], uint64_t part, uint8_t nonce[DM_NONCE_SIZE]) {
SHA256_CTX ctx;
uint8_t hash[32];
SHA256_Init(&ctx);
SHA256_Update(&ctx, "utun_dm_media", 13);
SHA256_Update(&ctx, &author, sizeof(author));
SHA256_Update(&ctx, media_id, 16);
SHA256_Update(&ctx, &part, sizeof(part));
SHA256_Final(hash, &ctx);
memcpy(nonce, hash, DM_NONCE_SIZE);
}
uint64_t dm_derive_conv_id(uint64_t a, uint64_t b) {
uint64_t lo = a < b ? a : b;
uint64_t hi = a < b ? b : a;
@ -80,10 +93,17 @@ void dm_build_nonce(uint64_t conv_id, uint64_t author, uint64_t seq, uint8_t non
static int dm_ccm_crypt(const uint8_t key[DM_CONTENT_KEY_SIZE], const uint8_t nonce[DM_NONCE_SIZE],
const uint8_t* in, size_t in_len, uint8_t* out, size_t* out_len,
int encrypt, const uint8_t* tag_in) {
if (!key || !nonce || !in || !out || !out_len) return -1;
if (!key || !nonce || (!in && in_len) || !out || !out_len ||
(encrypt ? in_len > DM_CCM_PLAIN_MAX : in_len < DM_TAG_SIZE || in_len - DM_TAG_SIZE > DM_CCM_PLAIN_MAX)) {
DEBUG_ERROR(DEBUG_CATEGORY_DM, "%s: invalid CCM arguments encrypt=%d bytes=%zu", DM_ID, encrypt, in_len);
return -1;
}
*out_len = 0;
static const uint8_t empty = 0;
if (!in) in = &empty;
EVP_CIPHER_CTX* ectx = EVP_CIPHER_CTX_new();
if (!ectx) return -1;
if (!ectx) { DEBUG_ERROR(DEBUG_CATEGORY_DM, "%s: CCM context allocation failed", DM_ID); return -1; }
const EVP_CIPHER* cipher = EVP_aes_256_ccm();
int rc = -1;
@ -93,6 +113,7 @@ static int dm_ccm_crypt(const uint8_t key[DM_CONTENT_KEY_SIZE], const uint8_t no
|| EVP_CIPHER_CTX_ctrl(ectx, EVP_CTRL_AEAD_SET_TAG, DM_TAG_SIZE, NULL) != 1
|| EVP_EncryptInit_ex(ectx, NULL, NULL, key, nonce) != 1) goto done;
int outl;
if (EVP_EncryptUpdate(ectx, NULL, &outl, NULL, (int)in_len) != 1) goto done;
if (EVP_EncryptUpdate(ectx, out, &outl, in, (int)in_len) != 1 || outl != (int)in_len) goto done;
int tmpl;
if (EVP_EncryptFinal_ex(ectx, out + outl, &tmpl) != 1) goto done;
@ -106,14 +127,14 @@ static int dm_ccm_crypt(const uint8_t key[DM_CONTENT_KEY_SIZE], const uint8_t no
|| EVP_CIPHER_CTX_ctrl(ectx, EVP_CTRL_AEAD_SET_TAG, DM_TAG_SIZE, (void*)(tag_in ? tag_in : in + body)) != 1
|| EVP_DecryptInit_ex(ectx, NULL, NULL, key, nonce) != 1) goto done;
int outl;
if (EVP_DecryptUpdate(ectx, NULL, &outl, NULL, (int)body) != 1) goto done;
if (EVP_DecryptUpdate(ectx, out, &outl, in, (int)body) != 1 || outl != (int)body) goto done;
int tmpl;
if (EVP_DecryptFinal_ex(ectx, out + outl, &tmpl) != 1) goto done;
*out_len = body;
}
rc = 0;
done:
EVP_CIPHER_CTX_free(ectx);
if (rc) DEBUG_ERROR(DEBUG_CATEGORY_DM, "%s: CCM %s failed bytes=%zu", DM_ID, encrypt ? "encrypt" : "decrypt", in_len);
return rc;
}

5
src/dm/dm_crypto.h

@ -20,6 +20,8 @@ extern "C" {
#define DM_CONTENT_KEY_SIZE 32
#define DM_NONCE_SIZE 13 /* AES-CCM требует ровно 13 байт */
#define DM_TAG_SIZE 16
#define DM_CCM_PLAIN_MAX 65535u
#define DM_MEDIA_PLAIN_SIZE 32768u
/* conv_id = SHA256("utun_dm_v1" || min(a,b) || max(a,b))[..8] & 0x7FFF...,
* 63-битное число, одинаковое на обеих сторонах (одна ветка на пару). */
@ -35,6 +37,9 @@ int dm_derive_content_key(const uint8_t my_priv[32], const uint8_t peer_pub[32],
* не пересекается между направлениями (author различается). */
void dm_build_nonce(uint64_t conv_id, uint64_t author, uint64_t seq, uint8_t nonce[DM_NONCE_SIZE]);
/* Nonce порции медиа; media_id неизменен на всех повторах одной отправки. */
void dm_build_media_nonce(uint64_t author, const uint8_t media_id[16], uint64_t part, uint8_t nonce[DM_NONCE_SIZE]);
/* AES-256-CCM. ciphertext = ciphertext(plain_len) || tag(DM_TAG_SIZE).
* out должен вмещать plain_len + DM_TAG_SIZE. 0=ок, <0=ошибка. */
int dm_encrypt(const uint8_t key[DM_CONTENT_KEY_SIZE], const uint8_t nonce[DM_NONCE_SIZE],

Loading…
Cancel
Save