@@ -40,34 +40,37 @@ static void s_xsalsa20_doubleround(ulong32 *x, int rounds)
4040#undef QUARTERROUND
4141
4242/**
43- Initialize an XSalsa20 context
44- @param st [out] The destination of the XSalsa20 state
43+ HSalsa20: derive a 256-bit subkey from a 256-bit key and 128-bit input.
44+ This is the Salsa20 core (double-rounds) without the final addition step,
45+ extracting output from state positions {0,5,10,15,6,7,8,9}.
46+ @param out [out] The derived 32-byte subkey
47+ @param outlen The length of the output buffer, must be 32 (octets)
4548 @param key The secret key
4649 @param keylen The length of the secret key, must be 32 (octets)
47- @param nonce The nonce
48- @param noncelen The length of the nonce , must be 24 (octets)
50+ @param in The 16-byte input ( nonce or constant)
51+ @param inlen The length of the input , must be 16 (octets)
4952 @param rounds Number of rounds (must be evenly divisible by 2, default is 20)
5053 @return CRYPT_OK if successful
5154*/
52- int xsalsa20_setup (salsa20_state * st , const unsigned char * key , unsigned long keylen ,
53- const unsigned char * nonce , unsigned long noncelen ,
54- int rounds )
55+ int xsalsa20_hsalsa20 (unsigned char * out , unsigned long outlen ,
56+ const unsigned char * key , unsigned long keylen ,
57+ const unsigned char * in , unsigned long inlen ,
58+ int rounds )
5559{
5660 const char * const constants = "expand 32-byte k" ;
57- const int sti [] = {0 , 5 , 10 , 15 , 6 , 7 , 8 , 9 }; /* indices used to build subkey fm x */
58- ulong32 x [64 ]; /* input to & output fm doubleround */
59- unsigned char subkey [32 ];
61+ const int sti [] = {0 , 5 , 10 , 15 , 6 , 7 , 8 , 9 };
62+ ulong32 x [16 ];
6063 int i ;
6164
62- LTC_ARGCHK (st != NULL );
63- LTC_ARGCHK (key != NULL );
64- LTC_ARGCHK (keylen == 32 );
65- LTC_ARGCHK (nonce != NULL );
66- LTC_ARGCHK (noncelen == 24 );
65+ LTC_ARGCHK (out != NULL );
66+ LTC_ARGCHK (outlen == 32 );
67+ LTC_ARGCHK (key != NULL );
68+ LTC_ARGCHK (keylen == 32 );
69+ LTC_ARGCHK (in != NULL );
70+ LTC_ARGCHK (inlen == 16 );
6771 if (rounds == 0 ) rounds = 20 ;
68- LTC_ARGCHK (rounds % 2 == 0 ); /* number of rounds must be evenly divisible by 2 */
72+ LTC_ARGCHK (rounds % 2 == 0 );
6973
70- /* load the state to "hash" the key */
7174 LOAD32L (x [ 0 ], constants + 0 );
7275 LOAD32L (x [ 5 ], constants + 4 );
7376 LOAD32L (x [10 ], constants + 8 );
@@ -80,20 +83,48 @@ int xsalsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long ke
8083 LOAD32L (x [12 ], key + 20 );
8184 LOAD32L (x [13 ], key + 24 );
8285 LOAD32L (x [14 ], key + 28 );
83- LOAD32L (x [ 6 ], nonce + 0 );
84- LOAD32L (x [ 7 ], nonce + 4 );
85- LOAD32L (x [ 8 ], nonce + 8 );
86- LOAD32L (x [ 9 ], nonce + 12 );
86+ LOAD32L (x [ 6 ], in + 0 );
87+ LOAD32L (x [ 7 ], in + 4 );
88+ LOAD32L (x [ 8 ], in + 8 );
89+ LOAD32L (x [ 9 ], in + 12 );
8790
88- /* use modified salsa20 doubleround (no final addition) */
8991 s_xsalsa20_doubleround (x , rounds );
9092
91- /* extract the subkey */
9293 for (i = 0 ; i < 8 ; ++ i ) {
93- STORE32L (x [sti [i ]], subkey + 4 * i );
94+ STORE32L (x [sti [i ]], out + 4 * i );
9495 }
9596
96- /* load the final initial state */
97+ zeromem (x , sizeof (x ));
98+ return CRYPT_OK ;
99+ }
100+
101+ /**
102+ Initialize an XSalsa20 context
103+ @param st [out] The destination of the XSalsa20 state
104+ @param key The secret key
105+ @param keylen The length of the secret key, must be 32 (octets)
106+ @param nonce The nonce
107+ @param noncelen The length of the nonce, must be 24 (octets)
108+ @param rounds Number of rounds (must be evenly divisible by 2, default is 20)
109+ @return CRYPT_OK if successful
110+ */
111+ int xsalsa20_setup (salsa20_state * st , const unsigned char * key , unsigned long keylen ,
112+ const unsigned char * nonce , unsigned long noncelen ,
113+ int rounds )
114+ {
115+ const char * const constants = "expand 32-byte k" ;
116+ unsigned char subkey [32 ];
117+ int err ;
118+
119+ LTC_ARGCHK (st != NULL );
120+ LTC_ARGCHK (nonce != NULL );
121+ LTC_ARGCHK (noncelen == 24 );
122+ if (rounds == 0 ) rounds = 20 ;
123+
124+ /* HSalsa20: derive subkey from key and first 16 bytes of nonce */
125+ if ((err = xsalsa20_hsalsa20 (subkey , 32 , key , keylen , nonce , 16 , rounds )) != CRYPT_OK ) goto cleanup ;
126+
127+ /* load the final initial state with the derived subkey */
97128 LOAD32L (st -> input [ 0 ], constants + 0 );
98129 LOAD32L (st -> input [ 5 ], constants + 4 );
99130 LOAD32L (st -> input [10 ], constants + 8 );
@@ -114,12 +145,12 @@ int xsalsa20_setup(salsa20_state *st, const unsigned char *key, unsigned long ke
114145 st -> ksleft = 0 ;
115146 st -> ivlen = 24 ; /* set switch to say nonce/IV has been loaded */
116147
148+ cleanup :
117149#ifdef LTC_CLEAN_STACK
118- zeromem (x , sizeof (x ));
119150 zeromem (subkey , sizeof (subkey ));
120151#endif
121152
122- return CRYPT_OK ;
153+ return err ;
123154}
124155
125156
0 commit comments