1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3
4 #include "tomcrypt_private.h"
5
6 #ifdef LTC_CHACHA20POLY1305_MODE
7
8 /**
9 Set IV + counter data to the ChaCha20Poly1305 state and reset the context
10 @param st The ChaCha20Poly1305 state
11 @param iv The IV data to add
12 @param ivlen The length of the IV (must be 12 or 8)
13 @return CRYPT_OK on success
14 */
chacha20poly1305_setiv(chacha20poly1305_state * st,const unsigned char * iv,unsigned long ivlen)15 int chacha20poly1305_setiv(chacha20poly1305_state *st, const unsigned char *iv, unsigned long ivlen)
16 {
17 chacha_state tmp_st;
18 int i, err;
19 unsigned char polykey[32];
20
21 LTC_ARGCHK(st != NULL);
22 LTC_ARGCHK(iv != NULL);
23 LTC_ARGCHK(ivlen == 12 || ivlen == 8);
24
25 /* set IV for chacha20 */
26 if (ivlen == 12) {
27 /* IV 96bit */
28 if ((err = chacha_ivctr32(&st->chacha, iv, ivlen, 1)) != CRYPT_OK) return err;
29 }
30 else {
31 /* IV 64bit */
32 if ((err = chacha_ivctr64(&st->chacha, iv, ivlen, 1)) != CRYPT_OK) return err;
33 }
34
35 /* copy chacha20 key to temporary state */
36 for(i = 0; i < 12; i++) tmp_st.input[i] = st->chacha.input[i];
37 tmp_st.rounds = 20;
38 /* set IV */
39 if (ivlen == 12) {
40 /* IV 32bit */
41 if ((err = chacha_ivctr32(&tmp_st, iv, ivlen, 0)) != CRYPT_OK) return err;
42 }
43 else {
44 /* IV 64bit */
45 if ((err = chacha_ivctr64(&tmp_st, iv, ivlen, 0)) != CRYPT_OK) return err;
46 }
47 /* (re)generate new poly1305 key */
48 if ((err = chacha_keystream(&tmp_st, polykey, 32)) != CRYPT_OK) return err;
49 /* (re)initialise poly1305 */
50 if ((err = poly1305_init(&st->poly, polykey, 32)) != CRYPT_OK) return err;
51 st->ctlen = 0;
52 st->aadlen = 0;
53 st->aadflg = 1;
54
55 return CRYPT_OK;
56 }
57
58 #endif
59