From 885e1307f5ae25a2c718850c9a07323b3ccf0c4d Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Mon, 27 Jul 2026 09:47:26 -0700 Subject: [PATCH] Fix some length issues --- ChaCha20_Poly1305_64/doc/notes3.md | 77 +++++++++ ChaCha20_Poly1305_64/doc/sanity.py | 33 ++-- .../sim/chacha20_poly1305_32_ll_core.py | 150 +++++++++++++++++- ChaCha20_Poly1305_64/src/chacha20_block.sv | 2 +- .../src/chacha20_poly1305_32_ll_core.sv | 8 +- .../src/chacha20_poly1305_input_fsm.sv | 14 ++ .../src/chacha20_poly1305_mid_fsm.sv | 3 + ChaCha20_Poly1305_64/src/poly1305_ll_stage.sv | 2 +- .../src/poly1305_width_convert_2.sv | 21 +++ 9 files changed, 289 insertions(+), 21 deletions(-) diff --git a/ChaCha20_Poly1305_64/doc/notes3.md b/ChaCha20_Poly1305_64/doc/notes3.md index 320bda4..78b1588 100644 --- a/ChaCha20_Poly1305_64/doc/notes3.md +++ b/ChaCha20_Poly1305_64/doc/notes3.md @@ -100,6 +100,83 @@ which all match still. So the final step is to add s, 0x46ba4f66eb2dd47e52c64c8d4ced78624 +and truncate to 128 bits + +6ba4f66eb2dd47e52c64c8d4ced78624 + SO basically we need to appaned the length to the data when it is going through poly1305. poly1305 should be able to look at the input fifo and know when it is outputting the last valid beat. After this, we need to output the lengths. + + +## Keepalive Packets + +These packets have zero data. They will need to be handled separately. + +After We can look at the UDP length to figure out if it is a keepalive packet, +this only serves to tell software if the connection has failed. We will +need to support sending and receiving these at some point, most likely in +hardware since they need to be authenticated, but they have no data. +perhaps some tuser flag can be passed in to bypass the crypto. We can +send in 16 bytes of zeroes but the user flag says to not actually send +this to poly1305, and the result can just be dropped after resetting some kind +of counter, or we can drop the data and just encapsulate the poly1305 tag. + +## Padding is not always 16 bytes + +The packets are 16 byte aligned UNLESS this would bring the packet over the MTU. +What this means in practice is that we might receive packets which are not 16 +byte aligned. If we are decrypting a packet, the length must be what the packet +actually is and not rounded up. We also need to be careful when we are sending +out packets that we can't always go up to 1500 bytes. + +(Might have to tell end users to set their MTU to 1300 or something). + +If we are decrypting then, the width convert should not round up. + +Or... we can just put that in a different module and not have random rules in the +crypto block itself. + +This also breaks the poly1305, because it is expecting exactly 128 bits every time, +so it has a specific cycle for the lengths. BUT if the incoming data is not 16 byte +aligned, then the lengths will be added at the wrong time. So, based on the length +of the packet, we need to be adding the lengths at a varying position at the end +of the packet. It might be split over 2 cycles, depending on what the length is. +we can figure this out easily by simply taking the length of the packet (which +we have counted already) modulo 16, aka & 0xf. In this case, the length of the packet +is 1420, so the counter is 12. What this means is that the last packet is only +12 bytes, so we need to shift 4 bytes of the counter into the last data beat. + +How do we know its the last data beat? the upconvert module gives us last. Technically +we calulate the total length based on this output. whatever. + +So in the sum state, we set the last flag based on upconvert_last. If this is true, +we also need to check if upconvert_countm1 is 0xf, or if its smaller than that. if +its 15, then we do what we normally do, just 1 extend the existing data. If it is not, +then we need to do 15 - countm1 bytes of the length packet. + + * padding2 -- the padding is up to 15 zero bytes, and it brings + the total length so far to an integral multiple of 16. If the + length of the ciphertext was already an integral multiple of 16 + bytes, this field is zero-length. + +wait... we should still be adding this padding ourselves... + +this is actually an embarassingly easy fix. + + +1420 bytes of inner ip + +16 bytes of wireguard header +16 bytes of wireguard signature + +8 bytes of udp + +20 bytes of ipv4 + +14 bytes of ethernet + +so if you are just looking at wireguard itself, its max is 1420 + 32? + +or, is it that we set the MTU to 1420 which is the max sized of the +encrypted packet, so we can't add any padding? \ No newline at end of file diff --git a/ChaCha20_Poly1305_64/doc/sanity.py b/ChaCha20_Poly1305_64/doc/sanity.py index 35e10de..eb28b81 100644 --- a/ChaCha20_Poly1305_64/doc/sanity.py +++ b/ChaCha20_Poly1305_64/doc/sanity.py @@ -1,16 +1,29 @@ import base64 -from chacha20poly1305 import ChaCha20Poly1305 -cleartext=base64.decodebytes(b"RQAAVOVGQABAAUFMCgoAAgoKAAEIAPlcbAAAAG+tIvUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA") -key = base64.decodebytes(b"IA7buFUDsARj+YequW4OfQR3JsaE9M88dpXKrDjKzIs=") -nonce = bytes([0]*12) +data = base64.decodebytes(b"BAAAALme3iYDAAAAAAAAAK0SmHnTT056FRHPMd66WYNlCDTwvJhkJx79R5psrl+fL/89gBZYHL2mjT9C+55tJuUVjHXYKMYdEVgn2he8p65W7BheKppBmq3mKfRezs8pRpgGVO4yI03t5BponGYn8xC71VtMPWxpBYdy9HsHNiZj4jGT30O+WPrdQTL10beu6ao+qEXUUD1hVHSKcpgOGp/xll7AjPYs1OEt64exAfO8pFeZtQTp16cLuiPNqMld3EYh2p7lF/Ry9GO3lB9sp/PB6cfSOOvLViZ3wsiCF/Q7awYqFuCrcMjU1RQs7RPGW4fhiFazl9NsvSuBvWMII48keUCtkLnbqv9dBZM7BPCVePAwFW5iPZOa7vkxaPF6pqWDSgTwRiLICiix5wQL0a0cBpgMxryNCxmvyRKUyRdo1RFMayfXFOp+6DqmUrNbBr3dnDGE87XuAkOnx9m/DR/yBI/iiePSCnsxeyJVwtBVJeDdzwZAyrVR9vYFfyVRH4MirZYuw33VkTA98OEXcqrdTSOvsTn04JL/1DmKTjdj8HHjtuBism6vOofdrFRmVSREAiE5tI4HecIkZV/iu2345JIe8FTWZZVfvIVG9VamkHPLe0gBQR4eeLfUWIlRQrU+aiWQBaZKMxooyYwZPZGTlUtKmU/Q1/cJ9GeBKuD6Txge+/okOlqvPXgCHeyiAiSHVJ/2lWHTK7BPyPwcIik3q+dIUpIwL5/7doYDcezpnscB5o/KjAvBw3YwqAuNLyVuqFrMGti1eCTi1ll016slCEbDGRvHYielCtdzkw7vYhIPE+k37FxXByoJ3jg5NlOrbRoVvO25Hy2rP4SYMmQ3dEQNRDVkCy8yvQRSAI1UOknXnpDo+SU50FKcmdB94htpRM+ddADNUmJPD7JJAI8AFgkMN7Zujgq7v2ZSXNhpDX1MD+7zdYUwu8GsldMKTYtz+BaShoJtcSSmXYdAup8i12lGBtJJf7FxANSweg5bHgr3OE9VLJZq5JIKhY+0cIKRF8ymI5of9vXETGT7JQe26QVn8zekevI183yiqS5qbxqdt96eT1/W8mF/2TNCYBgiP135gKwVoS3ZY/0kWrx5oN0TXSGjMkRnhucEjsw5W18CFJo+labHkmuZUJ+rdVfEviady27EwgIcU2sGWPWn7jw+WPOG+709CBGtfw7/Ld6MDmNsvT9m7mvTKOVIHxJyaiA997y9P4FD4mjjlHbtncJRtUeqrW4GXrQouF9ur2+OIMAkmo1jz51j6UbyT2RUwr+ABWfwfHUxDzwxRuhj0rodw3a3ZiFtGqIXYeDavMOE3Okn/zSGETIHOnfTufGBddxSRaOUGGMv6xBXzzq+qja6JMLx/M15yhTQE2NpVrNevbrMBBE7TdOVyZP4AdvQOByO1AcTjKtOgKaPfUQeHjn21/43VO9VhnNqozlU5n1ud+xxE+CKwt7kQ9TOn4UVF/x4poIJdV851jIehBZNR+ntWFPr4wc6WMggOJ3//UWKiAvKXrsKk3YsJLdVKIqBnXD3tewpb324LVkizIaUNH1ZWWAxZa/B1Rn3K8fwKl73G+d6I6uNcz0RiiAEYKoEkN7Web3KmIQYIyT4UN2I4HfjRy0i0rXEuEevDarBbfww+fgefYf9lu3hgre4/XMuuuBnjKK4+3BNkT9ipmOzm0gH3LT470OWEDFqm+SaIVW//VdijHsWJkFiSdD8QFYQtjgII1+d1XWXmZdocWm2iDje+4CX/14b+ZQgpWWgHJ+RiYOjEWnNzRtNyy9FrkQxzzlCIgz6hu+E8eDQExP7qunniB6UBPTkmutaaNXhrG4/oWT4yBx0HAmI/VrA/M/AmsDlRpp8MO0zwFQuLbb6aXm1CO88TIeCkXbCsYiy13edfJbf0FsLhIp4P9ZqX07Ug6SKcT8ZjHkc")[16:-16] -cip = ChaCha20Poly1305(key) +r = 0xb92cdec04e0255000c2c598066eeefa +s = 0xef4af5c5bed427d0e93cf8da2ffa5c6 -ciphertag = cip.encrypt(nonce, cleartext) +p = 2**130 - 5 -ciphertext = ciphertag[:-16] -tag = ciphertag[-16:] +chunked_data = [] +while len(data) > 0: + chunk_bytes = data[:16] + chunk = int.from_bytes(chunk_bytes, "little") + chunk |= 1 << (8*len(chunk_bytes)) + chunked_data.append(chunk) -print(ciphertext) -print(tag) \ No newline at end of file + data = data[16:] + +a = 0 + +for chunk in chunked_data: + a += chunk + a = (r * a) % p + + print(hex(a)) + +a += s + +print(hex(a)) \ No newline at end of file diff --git a/ChaCha20_Poly1305_64/sim/chacha20_poly1305_32_ll_core.py b/ChaCha20_Poly1305_64/sim/chacha20_poly1305_32_ll_core.py index e1c2aa4..8778de4 100644 --- a/ChaCha20_Poly1305_64/sim/chacha20_poly1305_32_ll_core.py +++ b/ChaCha20_Poly1305_64/sim/chacha20_poly1305_32_ll_core.py @@ -110,7 +110,11 @@ MESSAGE_KEY_2_BYTES = base64.decodebytes(b"3sZ+QBcwflnvE8t4jv9qgIqIOVaXXwO1bxRo9 MESSAGE_KEY_1 = int.from_bytes(MESSAGE_KEY_1_BYTES, "little") MESSAGE_KEY_2 = int.from_bytes(MESSAGE_KEY_2_BYTES, "little") +MESSAGE_KEY_3_BYTES = base64.decodebytes(b"LbEI5uiueAZ2LJEg41FbMw6l8ZM3ZtaTrKLOb3dT7QI=") +MESSAGE_KEY_4_BYTES = base64.decodebytes(b"H8xSW7vRDaYfl5RilWIwkdF0ehDo30tEJO/IzJMTezY=") +MESSAGE_KEY_3 = int.from_bytes(MESSAGE_KEY_3_BYTES, "little") +MESSAGE_KEY_4 = int.from_bytes(MESSAGE_KEY_4_BYTES, "little") PACKETS = [ CipherContext( @@ -131,7 +135,141 @@ PACKETS = [ tag=int.from_bytes(base64.decodebytes(b"BAAAANg30DAAAAAAAAAAAG9PCA6fUmkbvpSFNfecE+1o8JFF1SPu2whyZfloCC9wc1cpJj7aYnx2g83AuAozVtlTbJ8OKHJ5e1yBcguguOpyM8bev58PvujxDsGJhbgkvzUPi4GA0Ipk5r6YEAiaw9E2PtXhKcoeBCXPfpSWVlk=")[-16:], "little"), cipher=base64.decodebytes(b"BAAAANg30DAAAAAAAAAAAG9PCA6fUmkbvpSFNfecE+1o8JFF1SPu2whyZfloCC9wc1cpJj7aYnx2g83AuAozVtlTbJ8OKHJ5e1yBcguguOpyM8bev58PvujxDsGJhbgkvzUPi4GA0Ipk5r6YEAiaw9E2PtXhKcoeBCXPfpSWVlk=")[16:-16], clear=base64.decodebytes(b"RQAAVKEdAABAAcV1CgoAAQoKAAIAAAFdbAAAAG+tIvUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA") - ) + ), + + CipherContext( + key=MESSAGE_KEY_1, + counter=1, + encrypt=1, + + tag=int.from_bytes(base64.decodebytes(b"BAAAAAb0fasBAAAAAAAAAHzNKCSiKfzNFoU7Hv+UasxWNazSNhCJwxaXBs4Pz2LNqySyHtibW+QDk8FpLPp6KYHljK6RU0il+fyDPap6kagbUeVbtzLq3DhtalfmJbCSy1upQ/apOsaaBwHpnmAipi8Gbzy2IjKAkdrVnfE/bjM=")[-16:], "little"), + cipher=base64.decodebytes(b"BAAAAAb0fasBAAAAAAAAAHzNKCSiKfzNFoU7Hv+UasxWNazSNhCJwxaXBs4Pz2LNqySyHtibW+QDk8FpLPp6KYHljK6RU0il+fyDPap6kagbUeVbtzLq3DhtalfmJbCSy1upQ/apOsaaBwHpnmAipi8Gbzy2IjKAkdrVnfE/bjM=")[16:-16], + clear=base64.decodebytes(b"RQAAVOYnQABAAUBrCgoAAgoKAAEIALT9bAAAAaQLMvUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA") + ), + + CipherContext( + key=MESSAGE_KEY_2, + counter=1, + encrypt=0, + + tag=int.from_bytes(base64.decodebytes(b"BAAAANg30DABAAAAAAAAAEnLMkirrPEmhurVsmRHh5lF0OHX0qYLVBL6ud2/nel70Iv6tf/m/76DfaEOzFYj9Muj7omVUEI90wZsW0+5sBoKcaivdUZhWC6g9ARJI0fqt/R+aXE2Kci0l8p5cgFBcLLDnZnBQcGf4VNr6+uPvyk=")[-16:], "little"), + cipher=base64.decodebytes(b"BAAAANg30DABAAAAAAAAAEnLMkirrPEmhurVsmRHh5lF0OHX0qYLVBL6ud2/nel70Iv6tf/m/76DfaEOzFYj9Muj7omVUEI90wZsW0+5sBoKcaivdUZhWC6g9ARJI0fqt/R+aXE2Kci0l8p5cgFBcLLDnZnBQcGf4VNr6+uPvyk=")[16:-16], + clear=base64.decodebytes(b"RQAAVKH6AABAAcSYCgoAAQoKAAIAALz9bAAAAaQLMvUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA") + ), + + CipherContext( + key=MESSAGE_KEY_1, + counter=2, + encrypt=1, + + tag=int.from_bytes(base64.decodebytes(b"BAAAAAb0fasCAAAAAAAAAAK8hjcszyCKObdjMno0cMU0Iz0tMNJT26kI3GZUjL0WHPVq8pyYw5H5Cv+19Ks8qy7VQoPlhe14MGYbqoxpaSxmKvU3pAhRgOPhtIMZa/FXV7H68rtwMXO+O0wAaub4tGBBfxAZM+O3E5bImRe2MFQ=")[-16:], "little"), + cipher=base64.decodebytes(b"BAAAAAb0fasCAAAAAAAAAAK8hjcszyCKObdjMno0cMU0Iz0tMNJT26kI3GZUjL0WHPVq8pyYw5H5Cv+19Ks8qy7VQoPlhe14MGYbqoxpaSxmKvU3pAhRgOPhtIMZa/FXV7H68rtwMXO+O0wAaub4tGBBfxAZM+O3E5bImRe2MFQ=")[16:-16], + clear=base64.decodebytes(b"RQAAVOZ4QABAAUAaCgoAAgoKAAEIAPSqbAAAAlVdQfUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA") + ), + + CipherContext( + key=MESSAGE_KEY_2, + counter=2, + encrypt=0, + + tag=int.from_bytes(base64.decodebytes(b"BAAAANg30DACAAAAAAAAANVl/HO/AF3XLEDRkTrZ/V7iOIWpZXRUWt3Xaj5pZx+L05YcIMinZnsoR1gjA0KunMnQPjBLXRwx+zH541MWDl9kX2/iT6RisxvvhDdooyunZ+VWV/JIUS31WWE10cWyKk/j47mqdGGCj8ZDP/LlkvM=")[-16:], "little"), + cipher=base64.decodebytes(b"BAAAANg30DACAAAAAAAAANVl/HO/AF3XLEDRkTrZ/V7iOIWpZXRUWt3Xaj5pZx+L05YcIMinZnsoR1gjA0KunMnQPjBLXRwx+zH541MWDl9kX2/iT6RisxvvhDdooyunZ+VWV/JIUS31WWE10cWyKk/j47mqdGGCj8ZDP/LlkvM=")[16:-16], + clear=base64.decodebytes(b"RQAAVKKZAABAAcP5CgoAAQoKAAIAAPyqbAAAAlVdQfUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA") + ), + + CipherContext( + key=MESSAGE_KEY_2, + counter=3, + encrypt=0, + + tag=int.from_bytes(base64.decodebytes(b"BAAAANg30DADAAAAAAAAAPIVoyyT8QyqQd4enxQqF7LuwF57P7ArJTu0jKnZ04yUzfm7M5REwfdusioMH0qQDVMU+VSacW3qKTnW8QuQCLStPz1FDEcyFZzx31jXPEcB")[-16:], "little"), + cipher=base64.decodebytes(b"BAAAANg30DADAAAAAAAAAPIVoyyT8QyqQd4enxQqF7LuwF57P7ArJTu0jKnZ04yUzfm7M5REwfdusioMH0qQDVMU+VSacW3qKTnW8QuQCLStPz1FDEcyFZzx31jXPEcB")[16:-16], + clear=base64.decodebytes(b"RQAAO7tHQABAEXNeCgoAAQEBAQHO1gA1ACeG3RAHAQAAAQAAAAAAAApsZWtlbnN0ZXluAm5sAAABAAE=") + ), + + CipherContext( + key=MESSAGE_KEY_2, + counter=4, + encrypt=0, + + tag=int.from_bytes(base64.decodebytes(b"BAAAANg30DAEAAAAAAAAABF9QjZR6eDhFtX+gZMGK7RgtG9rxhmQ4PuWsusUcIYPVdpQvQHpvyIytVN8rghjlXFTjQPJwnS/u0azC5Y4ibNZtQc2MvPGw2CtNZvjdctJ")[-16:], "little"), + cipher=base64.decodebytes(b"BAAAANg30DAEAAAAAAAAABF9QjZR6eDhFtX+gZMGK7RgtG9rxhmQ4PuWsusUcIYPVdpQvQHpvyIytVN8rghjlXFTjQPJwnS/u0azC5Y4ibNZtQc2MvPGw2CtNZvjdctJ")[16:-16], + clear=base64.decodebytes(b"RQAAO7tIQABAEXNdCgoAAQEBAQHO1gA1ACfptZIuAQAAAQAAAAAAAApsZWtlbnN0ZXluAm5sAAAcAAE=") + ), + + CipherContext( + key=MESSAGE_KEY_1, + counter=4, + encrypt=1, + + tag=int.from_bytes(base64.decodebytes(b"BAAAAAb0fasEAAAAAAAAABWYbKqqAh9E0OCEJSfZMrW0OjvWiMl6N1SSqbWOWlpzH/udELV5KSWtTc1/tc8zFwJLgxDy565wNIUvShAlls+Nj6KjHEZQU7rylH8u4iIOAlrs0XkD1ZIy/hxPxSjUuA==")[-16:], "little"), + cipher=base64.decodebytes(b"BAAAAAb0fasEAAAAAAAAABWYbKqqAh9E0OCEJSfZMrW0OjvWiMl6N1SSqbWOWlpzH/udELV5KSWtTc1/tc8zFwJLgxDy565wNIUvShAlls+Nj6KjHEZQU7rylH8u4iIOAlrs0XkD1ZIy/hxPxSjUuA==")[16:-16], + clear=base64.decodebytes(b"RQAASwAAAAA/EW+WAQEBAQoKAAEANc7WADcuQhAHgYAAAQABAAAAAApsZWtlbnN0ZXluAm5sAAABAAHADAABAAEAABa0AASyFXD7") + ), + + # # should be a keepalive packet here! + + CipherContext( + key=MESSAGE_KEY_1, + counter=5, + encrypt=1, + + tag=int.from_bytes(base64.decodebytes(b"BAAAAAb0fasFAAAAAAAAAHzSuzTFBRFN2GIycujWryZhjoTccbQKpugYmS8w5csSlEO35wpTpXn74TShqfQhNbHxTNwm45kLUL0pozLrNiiGz5U4G7m0lBYDj9b4eeZSfArymZOe0BfYt8w5dx0DUHs53v4xdEC2aBlsMBmv3k0=")[-16:], "little"), + cipher=base64.decodebytes(b"BAAAAAb0fasFAAAAAAAAAHzSuzTFBRFN2GIycujWryZhjoTccbQKpugYmS8w5csSlEO35wpTpXn74TShqfQhNbHxTNwm45kLUL0pozLrNiiGz5U4G7m0lBYDj9b4eeZSfArymZOe0BfYt8w5dx0DUHs53v4xdEC2aBlsMBmv3k0=")[16:-16], + clear=base64.decodebytes(b"RQAAVwABAAA/EW+JAQEBAQoKAAEANc7WAEMO1ZIugYAAAQABAAAAAApsZWtlbnN0ZXluAm5sAAAcAAHADAAcAAEAABa0ABAqAiMIAAAAAAAAA2AAAQAB") + ), + + # Another keepalive here + + CipherContext( + key=MESSAGE_KEY_4, + counter=0, + encrypt=0, + + tag=int.from_bytes(base64.decodebytes(b"BAAAAMVB/b8AAAAAAAAAAK/Th71y1FBFIYi8O6d3P0Dlyte5Dy3zQrD41/6Iiros3Rr6pibFKWWyujj0RpPWIvEWJtCUnKJP9dPZREqfmAuazNKRjiugpL4wSnjpHiz+=")[-16:], "little"), + cipher=base64.decodebytes(b"BAAAAMVB/b8AAAAAAAAAAK/Th71y1FBFIYi8O6d3P0Dlyte5Dy3zQrD41/6Iiros3Rr6pibFKWWyujj0RpPWIvEWJtCUnKJP9dPZREqfmAuazNKRjiugpL4wSnjpHiz+")[16:-16], + clear=base64.decodebytes(b"RQAAPJioQABABnT4CgoAAbIVcPvBQAG7ixsUqAAAAACgAmvQUbcAAAIEBWQEAggKP6q7QwAAAAABAwMH") + ), + + CipherContext( + key=MESSAGE_KEY_3, + counter=1, + encrypt=1, + + tag=int.from_bytes(base64.decodebytes(b"BAAAALme3iYBAAAAAAAAAHmKtCxsplQ4V+bzmLxkrd9iIszgAclV26wj8hAtodPOi3wBBJXT5BZoBmhf76dAgwci+WAo8Neeizq/4Yu+pYQ=")[-16:], "little"), + cipher=base64.decodebytes(b"BAAAALme3iYBAAAAAAAAAHmKtCxsplQ4V+bzmLxkrd9iIszgAclV26wj8hAtodPOi3wBBJXT5BZoBmhf76dAgwci+WAo8Neeizq/4Yu+pYQ=")[16:-16], + clear=base64.decodebytes(b"RQAALAACAAA/Bk6vshVw+woKAAEBu8FAAAD6AYsbFKlgEiAA7jgAAAIEBbQ=") + ), + + CipherContext( + key=MESSAGE_KEY_4, + counter=1, + encrypt=0, + + tag=int.from_bytes(base64.decodebytes(b"BAAAAMVB/b8BAAAAAAAAAHvtESOQTU9ahgXtzw/OK8TvEsrjCkFEAnAcitOFqhqbeqmDtelwklfvLbxyLP9aRPReulhCY3luOLwB57MU6aw=")[-16:], "little"), + cipher=base64.decodebytes(b"BAAAAMVB/b8BAAAAAAAAAHvtESOQTU9ahgXtzw/OK8TvEsrjCkFEAnAcitOFqhqbeqmDtelwklfvLbxyLP9aRPReulhCY3luOLwB57MU6aw=")[16:-16], + clear=base64.decodebytes(b"RQAAKJipQABABnULCgoAAbIVcPvBQAG7ixsUqQAA+gJQEGvQuiUAAA==") + ), + + CipherContext( + key=MESSAGE_KEY_3, + counter=2, + encrypt=1, + + tag=int.from_bytes(base64.decodebytes(b"BAAAALme3iYCAAAAAAAAAMdVYbYHeBkuhSpOOkGEh/rIwcKv4a+17BEgv+T7DY4Ksivu3gNm0DXUh/hpgZ/lhqbgPT1+GUWUOQMypr/T1Nw=")[-16:], "little"), + cipher=base64.decodebytes(b"BAAAALme3iYCAAAAAAAAAMdVYbYHeBkuhSpOOkGEh/rIwcKv4a+17BEgv+T7DY4Ksivu3gNm0DXUh/hpgZ/lhqbgPT1+GUWUOQMypr/T1Nw=")[16:-16], + clear=base64.decodebytes(b"RQAAKAADAAA/Bk6yshVw+woKAAEBu8FAAAD6AosbFYFQECI4AuYAAA==") + ), + + CipherContext( + key=MESSAGE_KEY_3, + counter=3, + encrypt=1, + + tag=int.from_bytes(base64.decodebytes(b"BAAAALme3iYDAAAAAAAAAK0SmHnTT056FRHPMd66WYNlCDTwvJhkJx79R5psrl+fL/89gBZYHL2mjT9C+55tJuUVjHXYKMYdEVgn2he8p65W7BheKppBmq3mKfRezs8pRpgGVO4yI03t5BponGYn8xC71VtMPWxpBYdy9HsHNiZj4jGT30O+WPrdQTL10beu6ao+qEXUUD1hVHSKcpgOGp/xll7AjPYs1OEt64exAfO8pFeZtQTp16cLuiPNqMld3EYh2p7lF/Ry9GO3lB9sp/PB6cfSOOvLViZ3wsiCF/Q7awYqFuCrcMjU1RQs7RPGW4fhiFazl9NsvSuBvWMII48keUCtkLnbqv9dBZM7BPCVePAwFW5iPZOa7vkxaPF6pqWDSgTwRiLICiix5wQL0a0cBpgMxryNCxmvyRKUyRdo1RFMayfXFOp+6DqmUrNbBr3dnDGE87XuAkOnx9m/DR/yBI/iiePSCnsxeyJVwtBVJeDdzwZAyrVR9vYFfyVRH4MirZYuw33VkTA98OEXcqrdTSOvsTn04JL/1DmKTjdj8HHjtuBism6vOofdrFRmVSREAiE5tI4HecIkZV/iu2345JIe8FTWZZVfvIVG9VamkHPLe0gBQR4eeLfUWIlRQrU+aiWQBaZKMxooyYwZPZGTlUtKmU/Q1/cJ9GeBKuD6Txge+/okOlqvPXgCHeyiAiSHVJ/2lWHTK7BPyPwcIik3q+dIUpIwL5/7doYDcezpnscB5o/KjAvBw3YwqAuNLyVuqFrMGti1eCTi1ll016slCEbDGRvHYielCtdzkw7vYhIPE+k37FxXByoJ3jg5NlOrbRoVvO25Hy2rP4SYMmQ3dEQNRDVkCy8yvQRSAI1UOknXnpDo+SU50FKcmdB94htpRM+ddADNUmJPD7JJAI8AFgkMN7Zujgq7v2ZSXNhpDX1MD+7zdYUwu8GsldMKTYtz+BaShoJtcSSmXYdAup8i12lGBtJJf7FxANSweg5bHgr3OE9VLJZq5JIKhY+0cIKRF8ymI5of9vXETGT7JQe26QVn8zekevI183yiqS5qbxqdt96eT1/W8mF/2TNCYBgiP135gKwVoS3ZY/0kWrx5oN0TXSGjMkRnhucEjsw5W18CFJo+labHkmuZUJ+rdVfEviady27EwgIcU2sGWPWn7jw+WPOG+709CBGtfw7/Ld6MDmNsvT9m7mvTKOVIHxJyaiA997y9P4FD4mjjlHbtncJRtUeqrW4GXrQouF9ur2+OIMAkmo1jz51j6UbyT2RUwr+ABWfwfHUxDzwxRuhj0rodw3a3ZiFtGqIXYeDavMOE3Okn/zSGETIHOnfTufGBddxSRaOUGGMv6xBXzzq+qja6JMLx/M15yhTQE2NpVrNevbrMBBE7TdOVyZP4AdvQOByO1AcTjKtOgKaPfUQeHjn21/43VO9VhnNqozlU5n1ud+xxE+CKwt7kQ9TOn4UVF/x4poIJdV851jIehBZNR+ntWFPr4wc6WMggOJ3//UWKiAvKXrsKk3YsJLdVKIqBnXD3tewpb324LVkizIaUNH1ZWWAxZa/B1Rn3K8fwKl73G+d6I6uNcz0RiiAEYKoEkN7Web3KmIQYIyT4UN2I4HfjRy0i0rXEuEevDarBbfww+fgefYf9lu3hgre4/XMuuuBnjKK4+3BNkT9ipmOzm0gH3LT470OWEDFqm+SaIVW//VdijHsWJkFiSdD8QFYQtjgII1+d1XWXmZdocWm2iDje+4CX/14b+ZQgpWWgHJ+RiYOjEWnNzRtNyy9FrkQxzzlCIgz6hu+E8eDQExP7qunniB6UBPTkmutaaNXhrG4/oWT4yBx0HAmI/VrA/M/AmsDlRpp8MO0zwFQuLbb6aXm1CO88TIeCkXbCsYiy13edfJbf0FsLhIp4P9ZqX07Ug6SKcT8ZjHkc")[-16:], "little"), + cipher=base64.decodebytes(b"BAAAALme3iYDAAAAAAAAAK0SmHnTT056FRHPMd66WYNlCDTwvJhkJx79R5psrl+fL/89gBZYHL2mjT9C+55tJuUVjHXYKMYdEVgn2he8p65W7BheKppBmq3mKfRezs8pRpgGVO4yI03t5BponGYn8xC71VtMPWxpBYdy9HsHNiZj4jGT30O+WPrdQTL10beu6ao+qEXUUD1hVHSKcpgOGp/xll7AjPYs1OEt64exAfO8pFeZtQTp16cLuiPNqMld3EYh2p7lF/Ry9GO3lB9sp/PB6cfSOOvLViZ3wsiCF/Q7awYqFuCrcMjU1RQs7RPGW4fhiFazl9NsvSuBvWMII48keUCtkLnbqv9dBZM7BPCVePAwFW5iPZOa7vkxaPF6pqWDSgTwRiLICiix5wQL0a0cBpgMxryNCxmvyRKUyRdo1RFMayfXFOp+6DqmUrNbBr3dnDGE87XuAkOnx9m/DR/yBI/iiePSCnsxeyJVwtBVJeDdzwZAyrVR9vYFfyVRH4MirZYuw33VkTA98OEXcqrdTSOvsTn04JL/1DmKTjdj8HHjtuBism6vOofdrFRmVSREAiE5tI4HecIkZV/iu2345JIe8FTWZZVfvIVG9VamkHPLe0gBQR4eeLfUWIlRQrU+aiWQBaZKMxooyYwZPZGTlUtKmU/Q1/cJ9GeBKuD6Txge+/okOlqvPXgCHeyiAiSHVJ/2lWHTK7BPyPwcIik3q+dIUpIwL5/7doYDcezpnscB5o/KjAvBw3YwqAuNLyVuqFrMGti1eCTi1ll016slCEbDGRvHYielCtdzkw7vYhIPE+k37FxXByoJ3jg5NlOrbRoVvO25Hy2rP4SYMmQ3dEQNRDVkCy8yvQRSAI1UOknXnpDo+SU50FKcmdB94htpRM+ddADNUmJPD7JJAI8AFgkMN7Zujgq7v2ZSXNhpDX1MD+7zdYUwu8GsldMKTYtz+BaShoJtcSSmXYdAup8i12lGBtJJf7FxANSweg5bHgr3OE9VLJZq5JIKhY+0cIKRF8ymI5of9vXETGT7JQe26QVn8zekevI183yiqS5qbxqdt96eT1/W8mF/2TNCYBgiP135gKwVoS3ZY/0kWrx5oN0TXSGjMkRnhucEjsw5W18CFJo+labHkmuZUJ+rdVfEviady27EwgIcU2sGWPWn7jw+WPOG+709CBGtfw7/Ld6MDmNsvT9m7mvTKOVIHxJyaiA997y9P4FD4mjjlHbtncJRtUeqrW4GXrQouF9ur2+OIMAkmo1jz51j6UbyT2RUwr+ABWfwfHUxDzwxRuhj0rodw3a3ZiFtGqIXYeDavMOE3Okn/zSGETIHOnfTufGBddxSRaOUGGMv6xBXzzq+qja6JMLx/M15yhTQE2NpVrNevbrMBBE7TdOVyZP4AdvQOByO1AcTjKtOgKaPfUQeHjn21/43VO9VhnNqozlU5n1ud+xxE+CKwt7kQ9TOn4UVF/x4poIJdV851jIehBZNR+ntWFPr4wc6WMggOJ3//UWKiAvKXrsKk3YsJLdVKIqBnXD3tewpb324LVkizIaUNH1ZWWAxZa/B1Rn3K8fwKl73G+d6I6uNcz0RiiAEYKoEkN7Web3KmIQYIyT4UN2I4HfjRy0i0rXEuEevDarBbfww+fgefYf9lu3hgre4/XMuuuBnjKK4+3BNkT9ipmOzm0gH3LT470OWEDFqm+SaIVW//VdijHsWJkFiSdD8QFYQtjgII1+d1XWXmZdocWm2iDje+4CX/14b+ZQgpWWgHJ+RiYOjEWnNzRtNyy9FrkQxzzlCIgz6hu+E8eDQExP7qunniB6UBPTkmutaaNXhrG4/oWT4yBx0HAmI/VrA/M/AmsDlRpp8MO0zwFQuLbb6aXm1CO88TIeCkXbCsYiy13edfJbf0FsLhIp4P9ZqX07Ug6SKcT8ZjHkc")[16:-16], + clear=base64.decodebytes(b"RQAFjAAEIAA/BilNshVw+woKAAEBu8FAAAD6AosbFYFQECI4yD0AABYDAwBqAgAAZgMDqpKMTdCadtmNVjGh3gODkvSKTc0qQdGxOZTbaOOBJMIgQMCBb2mtCP0D7maJrcd1gyat2SYsDc5UpGvLnuGuF3vALwAAHgAAAAD/AQABAAALAAQDAAECM3QACQhodHRwLzEuMRYDAwq+CwAKugAKtwAGGzCCBhcwggT/oAMCAQICEgNjl8IYWbinreQPsgP6+V5FoDANBgkqhkiG9w0BAQsFADBKMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3MgRW5jcnlwdDEjMCEGA1UEAxMaTGV0J3MgRW5jcnlwdCBBdXRob3JpdHkgWDMwHhcNMTgwNzE1MjEwODM2WhcNMTgxMDEzMjEwODM2WjAYMRYwFAYDVQQDEw1sZWtlbnN0ZXluLm5sMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuVUnC61jiWQv+1/cA4RTj2AqZ5uVNlcpuWO+OEiuZyclfbXE+5w115ixULQhzI6nroJaF6T9SquuCrTxUcoKSlYpAkosCe5ne6BqY8jCJTiDhNhcIKjta/mbJzfCSJ0ZEo7sry3xOtnr50iOhmEJfXsfbDpHADCNZst/+G5YnXGEh5a0yuRo4v6CBHaNd0rO1+HxhhL//uFGy2EiP8J9xSQg8mmFIIBhKyYbw/0TvhiscsOozkoBT1E035IHeTXbdM8/EyWw60CEqgfucKbCW+Kd02hOIe3pduvVmsUKBq9ix5lgxfagWci48+Rw8LUfUlg3kxcbmM2oRpL1OZ5KmwIDAQABo4IDJzCCAyMwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTh2YXInDbV8qE3u7gB+8X5THYuNjAfBgNVHSMEGDAWgBSoSmpjBH3duubRObemRWXv86jsoTBvBggrBgEFBQcBAQRjMGEwLgYIKwYBBQUHMAGGImh0dHA6Ly9vY3NwLmludC14My5sZXRzZW5jcnlwdC5vcmcwLwYIKwYBBQUHMAKGI2h0dHA6Ly9jZXJ0LmludC14My5sZXRzZW5jcnlwdC5vcmcvMCsGA1UdEQQkMCKCDWxla2Vuc3RleW4ubmyCEXd3dy5sZWtlbnN0ZXluLm5sMIH+BgNVHSAEgfYwgfMwCAYGZ4EMAQIBMIHmBgsrBgEEAYLfEwEBATCB1jAmBggrBgEFBQcCARYaaHR0cDovL2Nwcy5sZXRzZW5jcnlwdC5vcmcwgasGCCsGAQUFBwICMIGeDIGbVGhpcyBDZXJ0aWZpY2F0ZSBtYXkgb25seSBiZSByZWxpZWQgdXBvbiBieSBSZWx5aW5nIFBhcnRpZXMgYW5kIG9ubHkgaW4gYWNjb3JkYW5jZSB3aXRoIHRoZSBDZXJ0aWZpY2F0ZSBQb2xpY3kgZm91bmQgYXQgaHR0cHM6Ly9sZXRzZW5jcnlwdC5vcmcvcmVwb3NpdG9yeS8wggEDBgorBgEEAdZ5AgQCBIH0BIHxAO8AdgApPFGWVMg5ZbqqUPxYB9S3b79Yeily3KTDDPTlRUf0eAAAAWSf/QPTAAAEAwBHMEUCIQDu0y+NGbIdvkKji76RH7MrpOuDhRpCbhBgwqEsKUPZFAIgGOq0Lyi2seniX907uqGuMAXdERxs9/NKutzK6GX43TIAdQBVgdTCFpA2AUrqC5tXPFPwwOQ4eHAlCBcvo6odBxPTDAAAAWSf/QdnAAAEAwBGMEQCIHz8RGU2c48kG9uZJdxNfE4ppp7xHMuYT22MAp1gM5nUAg==") + ), ] @@ -160,10 +298,8 @@ async def test_real_packet(dut): await RisingEdge(dut.i_clk) await RisingEdge(dut.i_clk) - - for pkt in PACKETS: - dut.i_nonce.value = pkt.counter + dut.i_nonce.value = pkt.counter << 32 dut.i_key.value = pkt.key dut.i_encrypt.value = pkt.encrypt @@ -189,19 +325,19 @@ async def test_real_packet(dut): dut.i_nonce.value = 0 dut.i_key.value = 0 - for pkt in PACKETS: + for i, pkt in enumerate(PACKETS): packet = await output_queue.get() expected = pkt.cipher if pkt.encrypt else pkt.clear # The packet is rounded up to 16 bytes before encryption, but based on the IP length we # are supposed to truncate it. That would happen outside of this block though. if expected not in packet: - print("Packets didn't match!") + print(f"{i}: Packets didn't match!") print(f"expected={expected} actual={packet}") tag = await tag_queue.get() if tag != pkt.tag: - print("Tags did not match!") + print(f"{i}: Tags did not match!") print(f"expected={pkt.tag:x} actual={tag:x}") diff --git a/ChaCha20_Poly1305_64/src/chacha20_block.sv b/ChaCha20_Poly1305_64/src/chacha20_block.sv index a4de16c..1b3ef55 100644 --- a/ChaCha20_Poly1305_64/src/chacha20_block.sv +++ b/ChaCha20_Poly1305_64/src/chacha20_block.sv @@ -77,7 +77,6 @@ always_ff @(posedge i_clk) begin end end - pre_add_valid <= valid[ROUNDS][0]; if (valid[ROUNDS][0] & i_ready) begin read_initial_state <= initial_states[initial_state_rptr]; @@ -93,6 +92,7 @@ always_ff @(posedge i_clk) begin if (i_ready) begin + pre_add_valid <= valid[ROUNDS][0]; o_valid <= pre_add_valid; // We cannot just add state_pre_add and read_initial state diff --git a/ChaCha20_Poly1305_64/src/chacha20_poly1305_32_ll_core.sv b/ChaCha20_Poly1305_64/src/chacha20_poly1305_32_ll_core.sv index 9a03f79..b596030 100644 --- a/ChaCha20_Poly1305_64/src/chacha20_poly1305_32_ll_core.sv +++ b/ChaCha20_Poly1305_64/src/chacha20_poly1305_32_ll_core.sv @@ -92,6 +92,8 @@ logic meta_fifo_encrypt; logic meta_fifo_read; logic meta_fifo_empty; +logic input_fsm_short_packet; + assign chacha_nonce = i_nonce; assign chacha_key = i_key; @@ -112,7 +114,7 @@ poly1305_width_convert_2 u_chacha_width_convert ( .o_valid (upconvert_valid), .o_countm1 (upconvert_countm1), - .i_ready (upconvert_ready & chacha_o_ready), + .i_ready (upconvert_ready & chacha_o_ready & ~input_fsm_short_packet), .o_data (upconvert_data), .o_last (upconvert_last) ); @@ -146,7 +148,7 @@ fifo_fwft #( .clk (i_clk), .rst (i_rst), .din ({upconvert_data, upconvert_countm1, upconvert_last}), - .wr_en (upconvert_valid & chacha_o_ready), + .wr_en (upconvert_valid & chacha_o_ready & ~input_fsm_short_packet), .full (fifo_full), // probably wrong, think about this .dout ({fifo_data, fifo_countm1, fifo_last}), .rd_en (fifo_rd_en), @@ -174,6 +176,8 @@ chacha20_poly1305_input_fsm u_chacha20_poly1305_input_fsm ( .i_valid (upconvert_valid), .i_last (upconvert_last), + .o_short_packet (input_fsm_short_packet), + .o_counter (chacha_counter), .chacha_valid (chacha_i_valid), .chacha_ready (chacha_i_ready) diff --git a/ChaCha20_Poly1305_64/src/chacha20_poly1305_input_fsm.sv b/ChaCha20_Poly1305_64/src/chacha20_poly1305_input_fsm.sv index 06ba4f2..359e088 100644 --- a/ChaCha20_Poly1305_64/src/chacha20_poly1305_input_fsm.sv +++ b/ChaCha20_Poly1305_64/src/chacha20_poly1305_input_fsm.sv @@ -7,6 +7,8 @@ module chacha20_poly1305_input_fsm ( output logic [31:0] o_counter, + output logic o_short_packet, + output logic chacha_valid, input logic chacha_ready ); @@ -42,6 +44,8 @@ always_comb begin chacha_valid = '0; + o_short_packet = '0; + case (state) IDLE: begin counter_next = '0; @@ -53,6 +57,11 @@ always_comb begin counter_next = counter + 1; last_flag_next = i_last; + // if the first beat is also the last, then lower ready so that + // we run chacha for 2 cycles instead of 1, and keep the key valid. + if (i_last) begin + o_short_packet = '1; + end end end @@ -63,6 +72,11 @@ always_comb begin counter_next = counter + 1; end + + if (i_last || last_flag) begin + state_next = IDLE; + counter_next = '0; + end end ACTIVE2: begin diff --git a/ChaCha20_Poly1305_64/src/chacha20_poly1305_mid_fsm.sv b/ChaCha20_Poly1305_64/src/chacha20_poly1305_mid_fsm.sv index ef61c60..16ffeb0 100644 --- a/ChaCha20_Poly1305_64/src/chacha20_poly1305_mid_fsm.sv +++ b/ChaCha20_Poly1305_64/src/chacha20_poly1305_mid_fsm.sv @@ -72,6 +72,9 @@ always_comb begin o_metadata_read = '0; + o_ciphertext = '0; + o_post = '0; + case (state) IDLE: begin if (i_chacha_valid) begin diff --git a/ChaCha20_Poly1305_64/src/poly1305_ll_stage.sv b/ChaCha20_Poly1305_64/src/poly1305_ll_stage.sv index 6d518bb..1b5fde7 100644 --- a/ChaCha20_Poly1305_64/src/poly1305_ll_stage.sv +++ b/ChaCha20_Poly1305_64/src/poly1305_ll_stage.sv @@ -163,7 +163,7 @@ always_comb begin last_flag_next = upconvert_last; upconvert_ready = '1; - data_1extend = {3'b0, upconvert_data} | (131'b1 << (8*(1+upconvert_countm1))); + data_1extend = {3'b1, upconvert_data}; sum_next = h + data_1extend; data_len_next = data_len + {60'd0, upconvert_countm1} + 1; diff --git a/ChaCha20_Poly1305_64/src/poly1305_width_convert_2.sv b/ChaCha20_Poly1305_64/src/poly1305_width_convert_2.sv index 218cf2a..03a7e65 100644 --- a/ChaCha20_Poly1305_64/src/poly1305_width_convert_2.sv +++ b/ChaCha20_Poly1305_64/src/poly1305_width_convert_2.sv @@ -18,6 +18,13 @@ module poly1305_width_convert_2( // this could definitely be parameterized, // but that can be a future project for the intern +logic [11:0] pkt_len, pkt_len_next; + +// make this an input +logic [11:0] pkt_len_max; + +assign pkt_len_max = 12'd1420; + logic [479:0] width_convert_save, width_convert_save_next; logic [3:0] width_convert_count, width_convert_count_next; @@ -26,9 +33,11 @@ always_ff @(posedge i_clk) begin if (i_rst) begin width_convert_save <= '0; width_convert_count <= '0; + pkt_len <= '0; end else begin width_convert_count <= width_convert_count_next; width_convert_save <= width_convert_save_next; + pkt_len <= pkt_len_next; end end @@ -36,6 +45,8 @@ always_comb begin width_convert_save_next = width_convert_save; width_convert_count_next = width_convert_count; + pkt_len_next = pkt_len; + o_valid = '0; o_ready = '0; o_last = '0; @@ -51,6 +62,7 @@ always_comb begin o_valid = '1; o_last = '1; + pkt_len_next = '0; // wireguard packets are rounded up to 16 bytes o_countm1 = width_convert_count*4 + {4'b0, i_countm1}; @@ -58,6 +70,10 @@ always_comb begin o_countm1 = {o_countm1[5:4], 4'hf}; end + if (pkt_len + 12'(o_countm1) + 1 > pkt_len_max) begin + o_countm1 = 6'(pkt_len_max - pkt_len - 12'd1); + end + if (i_ready) begin width_convert_count_next = '0; width_convert_save_next = '0; @@ -81,6 +97,11 @@ always_comb begin if (i_valid && o_ready) begin width_convert_count_next = '0; width_convert_save_next = '0; + pkt_len_next = pkt_len + 12'(o_countm1) + 12'h1; + + if (i_last) begin + pkt_len_next = '0; + end end end end