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:
km
2026-03-28 20:34:57 +09:00
parent 999e7a6e19
commit 0210082b8c
2 changed files with 45 additions and 27 deletions
+43 -25
View File
@@ -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],
+2 -2
View File
@@ -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;