3.4 KiB
Data from wireshark
Ok lets work this out by hand. The encyrpted packet matches exaactly, so we know that the chacha20 part is correct, and this must include the first block which is used for the keys.
84 bytes rounded to nearest multiple of 16 is 96 bytes. plus 16 for tag is 112.
so we do know that wireguard is including the tag.
the first output of chacha20, which becomes the keys, is 118b9bfd676a3bd991483cb1746252272e032bfbf2597dafec72576a54d9263ae32c815b30dbd75e7000d9ec14aac879075ada63f40d22180741336f9132e14a
The bottm 256 bits of that is
e32c815b30dbd75e7000d9ec14aac879075ada63f40d22180741336f9132e14a
splitting that into 128 bit sections, we get
0xe32c815b30dbd75e7000d9ec14aac879 0x075ada63f40d22180741336f9132e14a
r_mask is 0x0ffffffc0ffffffc0ffffffc0fffffff
so out final values of r and s are
r = 0x075ada60040d22180741336c0132e14a s = 0xe32c815b30dbd75e7000d9ec14aac879
oh and p = 2**130-5
These values line up with what what we see in the hardware.
according to the spec, the algorithm for poly1305 is as follows:
a = 0 /* a is the accumulator */
p = (1<<130)-5
for i=1 upto ceil(msg length in bytes / 16)
n = le_bytes_to_num(msg[((i-1)*16)..(i*16)] | [0x01])
a += n
a = (r * a) % p
end
a += s
return num_to_16_le_bytes(a)
end
Here is the cipher, which is msg in this case b"\xa4\xeb\xc1.\xe3\xf9\x90\xda\x18\x03:\x07\x89\xc0N'\x00\xf6\xf5\xc2q\xd4*\xc4\xb4\xd6&.feI\xb4E\xa7Cn\x82\x9b\xff\xb6\xace\xf0VH\xbc\x0c9\x1f\xe7\xc5\x88Ht7a'\x16I@\x18\x8f\x03\xdb\xa6z\xf88\x8e\xaa\xb7lY6(\xbf\x9d\xc7\xbe\x034m\x91.\x91m\xad\x86%EEG\x016O-"
here it is split up into 16 byte chunks
b"\xa4\xeb\xc1.\xe3\xf9\x90\xda\x18\x03:\x07\x89\xc0N'" b'\x00\xf6\xf5\xc2q\xd4*\xc4\xb4\xd6&.feI\xb4' b'E\xa7Cn\x82\x9b\xff\xb6\xace\xf0VH\xbc\x0c9' b"\x1f\xe7\xc5\x88Ht7a'\x16I@\x18\x8f\x03\xdb" b'\xa6z\xf88\x8e\xaa\xb7lY6(\xbf\x9d\xc7\xbe\x03' b'4m\x91.\x91m\xad\x86%EEG\x016O-'
The length of the message is 96 bytes, so we have our 6 16 byte chunks.
the next step is to interpret these as little endian integers, then add a leading 1.
0x1274ec089073a0318da90f9e32ec1eba4 0x1b44965662e26d6b4c42ad471c2f5f600 0x1390cbc4856f065acb6ff9b826e43a745 0x1db038f18404916276137744888c5e71f 0x103bec79dbf2836596cb7aa8e38f87aa6 0x12d4f36014745452586ad6d912e916d34
DON'T FORGET ABOUT THE LENGTHS! The length of AAD is 0, and the length of the ciphertext is 96, that becomes
this is aad length, data_length be careful of the order, since aad length comes first, it is on the right side of this hex number, since its little endian.
0x100000000000000600000000000000000
And these also match the hardware, so we are doing good so far.
so after the first round, a = (r * n) % p, since a started at 0, a+=n is just n so a = 0xcfd86a9543d3377baf5be686c46d8491
ok looks good so far.
next is 0x312e451b2a526811c5bd976ce3c27d5e7, looks good as well. the next values in a row are
0x22097b74ef42792da5e02cf9dd8249776 0x2586a4ee24499da642fb6392be59137b2 0xff1ba4984e72db7199c786a00de9de1e 0x2850e6cbbf9869bf410976e82e2ee9b04 0x38878751382017086bc63eee8ba2cbdab
which all match still. So the final step is to add s,
0x46ba4f66eb2dd47e52c64c8d4ced78624
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.