fix: Poly1305 MAC accumulation bug
- Fixed ChaCha20-Poly1305 to properly accumulate data across multiple calls - Changed from repeated se050_poly1305_mac() calls to poly1305_init/update/final - Now correctly detects ciphertext tampering and AAD mismatches - WireGuard packet encryption/decryption tests still failing - further investigation needed Test results: 28 passed, 4 failed (improved from 12 failed)
This commit is contained in:
@@ -591,43 +591,49 @@ int se050_chacha20_poly1305_encrypt(se050_chacha20_poly1305_ctx_t *ctx,
|
||||
if (ctx) {
|
||||
key = ctx->key;
|
||||
} else {
|
||||
/* One-shot mode requires key to be passed differently */
|
||||
/* For now, return error - ctx is required */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Generate Poly1305 key using ChaCha20 */
|
||||
uint8_t poly_key[32] = {0};
|
||||
uint8_t block[64];
|
||||
se050_chacha20_block(block, ctx->key, 0, nonce);
|
||||
se050_chacha20_block(block, key, 0, nonce);
|
||||
memcpy(poly_key, block, 32);
|
||||
|
||||
/* Compute MAC over AAD + ciphertext */
|
||||
/* Compute MAC over AAD + ciphertext using state */
|
||||
uint8_t mac_key[32];
|
||||
memcpy(mac_key, poly_key, 32);
|
||||
se050_poly1305_mac(tag, mac_key, aad, aad_len);
|
||||
|
||||
poly1305_state_t st;
|
||||
poly1305_init(&st, mac_key);
|
||||
|
||||
/* Process AAD */
|
||||
poly1305_update(&st, aad, aad_len);
|
||||
|
||||
/* Pad AAD */
|
||||
uint8_t pad[16] = {0};
|
||||
size_t aad_pad = (16 - (aad_len % 16)) % 16;
|
||||
if (aad_pad) se050_poly1305_mac(tag, mac_key, pad, aad_pad);
|
||||
if (aad_pad) poly1305_update(&st, pad, aad_pad);
|
||||
|
||||
/* Encrypt plaintext */
|
||||
se050_chacha20(ciphertext, plaintext, plaintext_len, ctx->key, 1, nonce);
|
||||
se050_chacha20(ciphertext, plaintext, plaintext_len, key, 1, nonce);
|
||||
|
||||
/* Continue MAC over ciphertext */
|
||||
se050_poly1305_mac(tag, mac_key, ciphertext, plaintext_len);
|
||||
/* Process ciphertext */
|
||||
poly1305_update(&st, ciphertext, plaintext_len);
|
||||
|
||||
/* Pad ciphertext */
|
||||
size_t ct_pad = (16 - (plaintext_len % 16)) % 16;
|
||||
if (ct_pad) se050_poly1305_mac(tag, mac_key, pad, ct_pad);
|
||||
if (ct_pad) poly1305_update(&st, pad, ct_pad);
|
||||
|
||||
/* Append lengths */
|
||||
uint8_t lengths[16];
|
||||
memset(lengths, 0, 16);
|
||||
memcpy(lengths, &aad_len, 8);
|
||||
memcpy(lengths + 8, &plaintext_len, 8);
|
||||
se050_poly1305_mac(tag, mac_key, lengths, 16);
|
||||
poly1305_update(&st, lengths, 16);
|
||||
|
||||
/* Finalize MAC */
|
||||
poly1305_final(&st, tag);
|
||||
|
||||
/* Zeroize poly key */
|
||||
memzero_explicit(poly_key, 32);
|
||||
@@ -655,41 +661,53 @@ int se050_chacha20_poly1305_decrypt(se050_chacha20_poly1305_ctx_t *ctx,
|
||||
uint8_t mac_key[32];
|
||||
memcpy(mac_key, poly_key, 32);
|
||||
|
||||
/* Compute expected MAC */
|
||||
uint8_t expected_tag[16];
|
||||
se050_poly1305_mac(expected_tag, mac_key, aad, aad_len);
|
||||
/* Compute expected MAC using state */
|
||||
poly1305_state_t st;
|
||||
poly1305_init(&st, mac_key);
|
||||
|
||||
/* Process AAD */
|
||||
poly1305_update(&st, aad, aad_len);
|
||||
|
||||
/* Pad AAD */
|
||||
uint8_t pad[16] = {0};
|
||||
size_t aad_pad = (16 - (aad_len % 16)) % 16;
|
||||
if (aad_pad) se050_poly1305_mac(expected_tag, mac_key, pad, aad_pad);
|
||||
if (aad_pad) poly1305_update(&st, pad, aad_pad);
|
||||
|
||||
se050_poly1305_mac(expected_tag, mac_key, ciphertext, ciphertext_len);
|
||||
/* Process ciphertext */
|
||||
poly1305_update(&st, ciphertext, ciphertext_len);
|
||||
|
||||
/* Pad ciphertext */
|
||||
size_t ct_pad = (16 - (ciphertext_len % 16)) % 16;
|
||||
if (ct_pad) se050_poly1305_mac(expected_tag, mac_key, pad, ct_pad);
|
||||
if (ct_pad) poly1305_update(&st, pad, ct_pad);
|
||||
|
||||
/* Append lengths */
|
||||
uint8_t lengths[16];
|
||||
memset(lengths, 0, 16);
|
||||
memcpy(lengths, &aad_len, 8);
|
||||
memcpy(lengths + 8, &ciphertext_len, 8);
|
||||
se050_poly1305_mac(expected_tag, mac_key, lengths, 16);
|
||||
poly1305_update(&st, lengths, 16);
|
||||
|
||||
/* Finalize MAC */
|
||||
uint8_t expected_tag[16];
|
||||
poly1305_final(&st, expected_tag);
|
||||
|
||||
/* Constant-time comparison */
|
||||
int ret = 0;
|
||||
if (crypto_memneq(expected_tag, tag, 16) != 0) {
|
||||
memzero_explicit(poly_key, 32);
|
||||
memzero_explicit(mac_key, 32);
|
||||
memzero_explicit(block, 64);
|
||||
return -1;
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
/* Decrypt ciphertext */
|
||||
se050_chacha20(plaintext, ciphertext, ciphertext_len, ctx->key, 1, nonce);
|
||||
/* Only decrypt if MAC is valid */
|
||||
if (ret == 0) {
|
||||
se050_chacha20(plaintext, ciphertext, ciphertext_len, ctx->key, 1, nonce);
|
||||
}
|
||||
|
||||
/* Zeroize sensitive data */
|
||||
memzero_explicit(poly_key, 32);
|
||||
memzero_explicit(mac_key, 32);
|
||||
memzero_explicit(block, 64);
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int se050_wireguard_encrypt(const uint8_t key[WG_KEY_SIZE],
|
||||
|
||||
@@ -315,7 +315,7 @@ int se050_wireguard_decrypt_packet(se050_wireguard_session_t *session,
|
||||
memset(nonce_buf, 0, 4);
|
||||
memcpy(nonce_buf + 4, packet + 8, 8);
|
||||
|
||||
size_t ciphertext_len = packet_len - 16 - 16; /* Total - header - tag */
|
||||
size_t ciphertext_len = plaintext_len = packet_len - 16 - 16; /* Total - header - tag */
|
||||
uint8_t tag[16];
|
||||
memcpy(tag, packet + 16 + ciphertext_len, 16);
|
||||
|
||||
@@ -337,7 +337,7 @@ int se050_wireguard_decrypt_packet(se050_wireguard_session_t *session,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Update nonce */
|
||||
/* Update plaintext length and nonce */
|
||||
*plaintext_len = ciphertext_len;
|
||||
session->receiving_nonce = nonce;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user