Subject: Re: [Cfrg] Feedback on: draft-irtf-cfrg-chacha20-poly1305-01

From: "Parkinson, Sean" <[email-masked]>
Date: Sun, 12 Oct 2014 18:50:04 -0400

Hi Yoav,

I was intrigued by the idea of using these algorithms and thought I would have a go at implementing them based on the draft.
Here are some comments I have that could help clarify the descriptions for implementers.

First of all I would like to say that I was able to quickly implement the algorithms so I think all of the details are there. What I'm going to suggest are things  that will make it a simpler for an implementer to pick out what they need to do and make it easier to verify the implementation.
1.            The ChaCha quarter round description (2.1) is not really C code. It is a mathematical description. The steps are ordered and therefore should be numbered. The worked example is good for clarity and should use values that show up edge cases: b=0xffeeddcc, a=0x77777777. Rotate by 7 rather than 16 and it is clearer that you have rotated the correct direction.
2.            In the worked example in 2.2.1 it might be helpful to highlight the modified values using, say, a bold font if possible.
3.            In section 2.3, the state and the block are mixed in together. How about separating the 'inner block' (where the quarter rounds are performed) out into its own section?
4.            In section 2.3, putting the adding of the original input words into an algorithm description would help implementers 'tick-off' that they have got all the parts done. Something like:
chacha20_block(key, counter, nonce):
state = key | counter | nonce
working_state = state
for i=1 upto 10
     inner_block(working_state)
state += working_state
serialize(state)
5.            In section 2.3, saying there are 20 rounds but combining the two rounds into one step is confusing. Saying there are 10 rounds of the following 8 steps explicitly could remove the confusion.
6.            In section 2.3, the whole endian thing is very confusing. Thankfully the worked example makes this clear.
7.            In section 2.4, an algorithmic representation of the block counter incrementing would be helpful. Something like:
chacha20_encrypt(key, counter, nonce, plaintext):
for counter=1 upto ceil(length of plaintext in bytes / 64)
     key_stream = chacha20_block(key, counter, nonce)
     encrypted_message += plaintext[((counter-1)*64)..(counter*64-1)] ^ key_stream
8.            In section 2.4, say that a key-stream block can be XOR-ed with a plaintext block before proceeding. Implementation detail should, I think, be kept for a later section.
9.            In section 2.4, a minor quibble but, copying the plaintext and ciphertext into test code is a little difficult.
10.          In section 2.5, a proper algorithmic description would be nice. Something like:
clamp(r): r &= 0x0fffff0c0ffffffc0ffffffcffffffff
poly1305_mac(msg, tag, key):
r = clamp(le_bytes_to_num(tag))
s = le_num(key)
accumulator = 0
p = (1<<130)-5
for i=1 upto ceil(msg length in bytes / 16)
     n = le_bytes_to_num([0x01] | msg[((i-1)*16)..(i*16)])
     a += n
     a = (r * a) % p
a += s
num_to_16_le_bytes(a)
11.          In section 2.6, an algorithmic description would be good too:
poly1305_key_gen(key, iv, constant):
counter = 0
chacha20_block(key, counter, constant | iv)[0..31]
12.          In section 2.8 there is a lot of text and an algorithmic description would be better. Something like:
chacha20_aead_encrypt(aad, key, iv, constant, plaintext):
k = poly1305_key_gen(key, iv, constant)
ciphertext = chacha_encrypt(key, 1, constant | iv, plaintext)
mac_data = aad | [0]*((16 - (aad.length & 15)) & 15)
mac_data |= ciphertext | [0]*((16 - (ciphertext.length & 15)) & 15)
mac_data |= num_to_4_le_bytes(aad.length)
mac_data |= num_to_4_le_bytes(ciphertext.length)
tag = poly1305_mac(mac_data, k[0..15], k[16..31])
(ciphertext, tag)

Hope this is helpful,
Sean
--
Sean Parkinson | Consultant Software Engineer | RSA, The Security Division of EMC
Office +61 7 3032 5232 | Fax +61 7 3032 5299
www.rsa.com<http://www.rsa.com>