From 0210082b8cfc184e0a6fd78b4801a0a876641e52 Mon Sep 17 00:00:00 2001 From: km Date: Sat, 28 Mar 2026 20:34:57 +0900 Subject: [PATCH] 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) --- src/se050_chacha20_poly1305.c | 68 ++++++++++++++++++++++------------- src/se050_wireguard.c | 4 +-- 2 files changed, 45 insertions(+), 27 deletions(-) diff --git a/src/se050_chacha20_poly1305.c b/src/se050_chacha20_poly1305.c index 3ec8b37..3b0fe19 100644 --- a/src/se050_chacha20_poly1305.c +++ b/src/se050_chacha20_poly1305.c @@ -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], diff --git a/src/se050_wireguard.c b/src/se050_wireguard.c index c3134b5..9f0c610 100644 --- a/src/se050_wireguard.c +++ b/src/se050_wireguard.c @@ -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;