@@ -102,20 +102,22 @@ pub fn (c Chacha20Poly1305RE) encrypt(plaintext []u8, nonce []u8, ad []u8) ![]u8
102102 return error ('Chacha20Poly1305RE.encrypt: bad nonce length, only support 12-bytes nonce' )
103103 }
104104
105- // clone the initial poly1305
105+ // clone the initial poly1305 state and updates it with additional data ad
106106 mut po_ad := c.po.clone ()
107107 update_with_padding (mut po_ad, ad)
108-
108+ // make a clone of updated poly1305
109109 mut po_ad_clone := po_ad.clone ()
110- // build the tag
111- tag := psiv_gen_tag (mut po_ad_clone, plaintext, ad.len, c.mac_key, nonce)
112- enc := psiv_encrypt_internal (plaintext, c.enc_key, tag, nonce)!
113110
114- // setup destination buffer
115- mut out := []u8 {cap: plaintext.len + tag_size}
116- out << enc
117- out << tag
111+ // setup output buffer
112+ mut out := []u8 {len: plaintext.len + tag_size}
113+ // write out an authentication tag into the last tag_size bytes of output
114+ psiv_gen_tag (mut out[plaintext.len..], mut po_ad_clone, plaintext, ad.len, c.mac_key,
115+ nonce)
116+ // write out authenticated encrypted plaintext into the first plaintext.len bytes of output
117+ psiv_encrypt_internal (mut out[0 ..plaintext.len], plaintext, c.enc_key, out[plaintext.len..],
118+ nonce)!
118119
120+ // return the result
119121 return out
120122}
121123
@@ -133,19 +135,27 @@ pub fn (c Chacha20Poly1305RE) decrypt(ciphertext []u8, nonce []u8, ad []u8) ![]u
133135 enc := ciphertext[0 ..ciphertext.len - c.overhead ()]
134136 tag := ciphertext[ciphertext.len - c.overhead ()..]
135137
138+ // updates a clone of poly1305 with additional data
136139 mut po_with_ad := c.po.clone ()
137140 update_with_padding (mut po_with_ad, ad)
138-
139- out := psiv_encrypt_internal (enc, c.enc_key, tag, nonce)!
140141 mut poad_clone := po_with_ad.clone ()
141- mac := psiv_gen_tag (mut poad_clone, out, ad.len, c.mac_key, nonce)
142+
143+ // generates authenticated encrypted plaintext with associated mac
144+ mut out := []u8 {len: enc.len}
145+ psiv_encrypt_internal (mut out, enc, c.enc_key, tag, nonce)!
146+
147+ mut mac := []u8 {len: tag_size}
148+ psiv_gen_tag (mut mac, mut poad_clone, out, ad.len, c.mac_key, nonce)
149+
150+ // check if authentication tag was matching or error on fails.
142151 if subtle.constant_time_compare (mac, tag) != 1 {
143152 unsafe {
144153 out.free ()
145154 mac.free ()
146155 }
147156 return error ('unmatching tag' )
148157 }
158+ // return the decrypted ciphertext
149159 return out
150160}
151161
@@ -155,12 +165,11 @@ pub fn (c Chacha20Poly1305RE) decrypt(ciphertext []u8, nonce []u8, ad []u8) ![]u
155165// psiv_encrypt_internal is an internal encryption routine used by the core of psiv construct
156166// for encrypting (or decrypting) message.
157167@[direct_array_access]
158- fn psiv_encrypt_internal (plaintext []u8 , key []u8 , tag []u8 , nonce []u8 ) ! [] u8 {
168+ fn psiv_encrypt_internal (mut dst [] u8 , plaintext []u8 , key []u8 , tag []u8 , nonce []u8 ) ! {
159169 // loads the counter from the first 8-bytes of the tag input
160170 mut ctr := binary.little_endian_u64 (tag[0 ..8 ])
161171
162172 // setup some temporary vars
163- mut dst := []u8 {len: plaintext.len}
164173 mut tc := []u8 {len: 8 } // counter buffer
165174 mut s := chacha20 .State{}
166175 mut b64 := []u8 {len: 64 } // state buffer
@@ -195,46 +204,43 @@ fn psiv_encrypt_internal(plaintext []u8, key []u8, tag []u8, nonce []u8) ![]u8 {
195204 }
196205 n + = want_len
197206 }
198- // reset (release) temporary allocated resources and return the result.
207+ // explicitly reset (release) temporary allocated resources and return the result.
199208 unsafe {
200209 tc.free ()
201210 s.reset ()
202211 b64 .free ()
203212 tt.free ()
204213 }
205- return dst
206214}
207215
208216// psiv_gen_tag computes a tag from the key, nonce, and Poly1305 tag of the associated data
209217// and plaintext using the ChaCha20 permutation with the feed-forward, truncating the output.
210218@[direct_array_access]
211- fn psiv_gen_tag (mut po poly1305 .Poly1305 , input []u8 , ad_len int , mac_key []u8 , nonce []u8 ) [] u8 {
219+ fn psiv_gen_tag (mut out [] u8 , mut po poly1305 .Poly1305 , input []u8 , ad_len int , mac_key []u8 , nonce []u8 ) {
212220 // updates poly1305 mac by input message, associated data length and input length.
213221 update_with_padding (mut po, input)
214222 po.update (length_to_block (ad_len, input.len))
215223
216224 // produces 16-bytes of mac from current poly1305 state.
217- mut digest := []u8 {len: tag_size}
218- po.finish (mut digest)
225+ po.finish (mut out)
219226
220227 // The tag was produced from derived key scrambled with chacha20 quarter round routine,
221228 // and then truncating the output into 16-bytes tag.
222- drv_key := merge_drv_key (mac_key, nonce, digest [0 ..8 ], digest [8 ..16 ])
229+ drv_key := merge_drv_key (mac_key, nonce, out [0 ..8 ], out [8 ..16 ])
223230 mut x := chacha20 .State{}
224231 unpack_into_state (mut x, drv_key)
225232 ws := chacha20_core (x)
226233
227- // truncating state output into tag_sized bytes. As a note, we reuse digest buffer allocated
228- // on previous step to store the result.
229- pack16_from_state (mut digest , ws)
234+ // truncating state output into tag_sized bytes. As a note, we reuse buffer previously allocated
235+ // to store the result.
236+ pack16_from_state (mut out , ws)
230237
231- // releases (reset) temporary allocated resources and return the result.
238+ // explicitly releases (reset) temporary allocated resources
232239 unsafe {
233240 drv_key.free ()
234241 ws.reset ()
235242 x.reset ()
236243 }
237- return digest
238244}
239245
240246// psiv_init initializes and expands master key into desired psiv needed construct.
@@ -479,12 +485,6 @@ fn chacha20_core(s chacha20.State) chacha20.State {
479485 return ws
480486}
481487
482- // split_tag splits 16-bytes of tag into two's 8-bytes block.
483- @[direct_array_access; inline]
484- fn split_tag (tag []u8 ) ([]u8 , []u8 ) {
485- return tag[0 ..8 ].clone (), tag[8 ..16 ].clone ()
486- }
487-
488488// length_to_block transforms two's length in len1 and len2 into 16-bytes block
489489@[inline]
490490fn length_to_block (len1 int , len2 int ) []u8 {
0 commit comments