1d4afb5ceSopenharmony_ci/* 2d4afb5ceSopenharmony_cichacha-merged.c version 20080118 3d4afb5ceSopenharmony_ciD. J. Bernstein 4d4afb5ceSopenharmony_ciPublic domain. 5d4afb5ceSopenharmony_ci*/ 6d4afb5ceSopenharmony_ci 7d4afb5ceSopenharmony_ci#include <libwebsockets.h> 8d4afb5ceSopenharmony_ci#include "lws-ssh.h" 9d4afb5ceSopenharmony_ci 10d4afb5ceSopenharmony_ci#include <string.h> 11d4afb5ceSopenharmony_ci#include <stdlib.h> 12d4afb5ceSopenharmony_ci 13d4afb5ceSopenharmony_cistruct chacha_ctx { 14d4afb5ceSopenharmony_ci u_int input[16]; 15d4afb5ceSopenharmony_ci}; 16d4afb5ceSopenharmony_ci 17d4afb5ceSopenharmony_ci#define CHACHA_MINKEYLEN 16 18d4afb5ceSopenharmony_ci#define CHACHA_NONCELEN 8 19d4afb5ceSopenharmony_ci#define CHACHA_CTRLEN 8 20d4afb5ceSopenharmony_ci#define CHACHA_STATELEN (CHACHA_NONCELEN+CHACHA_CTRLEN) 21d4afb5ceSopenharmony_ci#define CHACHA_BLOCKLEN 64 22d4afb5ceSopenharmony_ci 23d4afb5ceSopenharmony_citypedef unsigned char u8; 24d4afb5ceSopenharmony_citypedef unsigned int u32; 25d4afb5ceSopenharmony_ci 26d4afb5ceSopenharmony_citypedef struct chacha_ctx chacha_ctx; 27d4afb5ceSopenharmony_ci 28d4afb5ceSopenharmony_ci#define U8C(v) (v##U) 29d4afb5ceSopenharmony_ci#define U32C(v) (v##U) 30d4afb5ceSopenharmony_ci 31d4afb5ceSopenharmony_ci#define U8V(v) ((u8)((v) & U8C(0xFF))) 32d4afb5ceSopenharmony_ci#define U32V(v) ((u32)(v) & U32C(0xFFFFFFFF)) 33d4afb5ceSopenharmony_ci 34d4afb5ceSopenharmony_ci#define ROTL32(v, n) \ 35d4afb5ceSopenharmony_ci (U32V((v) << (n)) | ((v) >> (32 - (n)))) 36d4afb5ceSopenharmony_ci 37d4afb5ceSopenharmony_ci#define U8TO32_LITTLE(p) \ 38d4afb5ceSopenharmony_ci (((u32)((p)[0]) ) | \ 39d4afb5ceSopenharmony_ci ((u32)((p)[1]) << 8) | \ 40d4afb5ceSopenharmony_ci ((u32)((p)[2]) << 16) | \ 41d4afb5ceSopenharmony_ci ((u32)((p)[3]) << 24)) 42d4afb5ceSopenharmony_ci 43d4afb5ceSopenharmony_ci#define U32TO8_LITTLE(p, v) \ 44d4afb5ceSopenharmony_ci do { \ 45d4afb5ceSopenharmony_ci (p)[0] = U8V((v) ); \ 46d4afb5ceSopenharmony_ci (p)[1] = U8V((v) >> 8); \ 47d4afb5ceSopenharmony_ci (p)[2] = U8V((v) >> 16); \ 48d4afb5ceSopenharmony_ci (p)[3] = U8V((v) >> 24); \ 49d4afb5ceSopenharmony_ci } while (0) 50d4afb5ceSopenharmony_ci 51d4afb5ceSopenharmony_ci#define ROTATE(v,c) (ROTL32(v,c)) 52d4afb5ceSopenharmony_ci#define XOR(v,w) ((v) ^ (w)) 53d4afb5ceSopenharmony_ci#define PLUS(v,w) (U32V((v) + (w))) 54d4afb5ceSopenharmony_ci#define PLUSONE(v) (PLUS((v),1)) 55d4afb5ceSopenharmony_ci 56d4afb5ceSopenharmony_ci#define QUARTERROUND(a,b,c,d) \ 57d4afb5ceSopenharmony_ci a = PLUS(a,b); d = ROTATE(XOR(d,a),16); \ 58d4afb5ceSopenharmony_ci c = PLUS(c,d); b = ROTATE(XOR(b,c),12); \ 59d4afb5ceSopenharmony_ci a = PLUS(a,b); d = ROTATE(XOR(d,a), 8); \ 60d4afb5ceSopenharmony_ci c = PLUS(c,d); b = ROTATE(XOR(b,c), 7); 61d4afb5ceSopenharmony_ci 62d4afb5ceSopenharmony_cistatic const char sigma[16] = "expand 32-byte k"; 63d4afb5ceSopenharmony_cistatic const char tau[16] = "expand 16-byte k"; 64d4afb5ceSopenharmony_ci 65d4afb5ceSopenharmony_civoid 66d4afb5ceSopenharmony_cichacha_keysetup(chacha_ctx *x,const u8 *k,u32 kbits) 67d4afb5ceSopenharmony_ci{ 68d4afb5ceSopenharmony_ci const char *constants; 69d4afb5ceSopenharmony_ci 70d4afb5ceSopenharmony_ci x->input[4] = U8TO32_LITTLE(k + 0); 71d4afb5ceSopenharmony_ci x->input[5] = U8TO32_LITTLE(k + 4); 72d4afb5ceSopenharmony_ci x->input[6] = U8TO32_LITTLE(k + 8); 73d4afb5ceSopenharmony_ci x->input[7] = U8TO32_LITTLE(k + 12); 74d4afb5ceSopenharmony_ci if (kbits == 256) { /* recommended */ 75d4afb5ceSopenharmony_ci k += 16; 76d4afb5ceSopenharmony_ci constants = sigma; 77d4afb5ceSopenharmony_ci } else { /* kbits == 128 */ 78d4afb5ceSopenharmony_ci constants = tau; 79d4afb5ceSopenharmony_ci } 80d4afb5ceSopenharmony_ci x->input[8] = U8TO32_LITTLE(k + 0); 81d4afb5ceSopenharmony_ci x->input[9] = U8TO32_LITTLE(k + 4); 82d4afb5ceSopenharmony_ci x->input[10] = U8TO32_LITTLE(k + 8); 83d4afb5ceSopenharmony_ci x->input[11] = U8TO32_LITTLE(k + 12); 84d4afb5ceSopenharmony_ci x->input[0] = U8TO32_LITTLE(constants + 0); 85d4afb5ceSopenharmony_ci x->input[1] = U8TO32_LITTLE(constants + 4); 86d4afb5ceSopenharmony_ci x->input[2] = U8TO32_LITTLE(constants + 8); 87d4afb5ceSopenharmony_ci x->input[3] = U8TO32_LITTLE(constants + 12); 88d4afb5ceSopenharmony_ci} 89d4afb5ceSopenharmony_ci 90d4afb5ceSopenharmony_civoid 91d4afb5ceSopenharmony_cichacha_ivsetup(chacha_ctx *x, const u8 *iv, const u8 *counter) 92d4afb5ceSopenharmony_ci{ 93d4afb5ceSopenharmony_ci x->input[12] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 0); 94d4afb5ceSopenharmony_ci x->input[13] = counter == NULL ? 0 : U8TO32_LITTLE(counter + 4); 95d4afb5ceSopenharmony_ci x->input[14] = U8TO32_LITTLE(iv + 0); 96d4afb5ceSopenharmony_ci x->input[15] = U8TO32_LITTLE(iv + 4); 97d4afb5ceSopenharmony_ci} 98d4afb5ceSopenharmony_ci 99d4afb5ceSopenharmony_civoid 100d4afb5ceSopenharmony_cichacha_encrypt_bytes(chacha_ctx *x,const u8 *m,u8 *c,u32 bytes) 101d4afb5ceSopenharmony_ci{ 102d4afb5ceSopenharmony_ci u32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; 103d4afb5ceSopenharmony_ci u32 j0, j1, j2, j3, j4, j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15; 104d4afb5ceSopenharmony_ci u8 *ctarget = NULL; 105d4afb5ceSopenharmony_ci u8 tmp[64]; 106d4afb5ceSopenharmony_ci u_int i; 107d4afb5ceSopenharmony_ci 108d4afb5ceSopenharmony_ci if (!bytes) return; 109d4afb5ceSopenharmony_ci 110d4afb5ceSopenharmony_ci j0 = x->input[0]; 111d4afb5ceSopenharmony_ci j1 = x->input[1]; 112d4afb5ceSopenharmony_ci j2 = x->input[2]; 113d4afb5ceSopenharmony_ci j3 = x->input[3]; 114d4afb5ceSopenharmony_ci j4 = x->input[4]; 115d4afb5ceSopenharmony_ci j5 = x->input[5]; 116d4afb5ceSopenharmony_ci j6 = x->input[6]; 117d4afb5ceSopenharmony_ci j7 = x->input[7]; 118d4afb5ceSopenharmony_ci j8 = x->input[8]; 119d4afb5ceSopenharmony_ci j9 = x->input[9]; 120d4afb5ceSopenharmony_ci j10 = x->input[10]; 121d4afb5ceSopenharmony_ci j11 = x->input[11]; 122d4afb5ceSopenharmony_ci j12 = x->input[12]; 123d4afb5ceSopenharmony_ci j13 = x->input[13]; 124d4afb5ceSopenharmony_ci j14 = x->input[14]; 125d4afb5ceSopenharmony_ci j15 = x->input[15]; 126d4afb5ceSopenharmony_ci 127d4afb5ceSopenharmony_ci for (;;) { 128d4afb5ceSopenharmony_ci if (bytes < 64) { 129d4afb5ceSopenharmony_ci for (i = 0;i < bytes;++i) tmp[i] = m[i]; 130d4afb5ceSopenharmony_ci m = tmp; 131d4afb5ceSopenharmony_ci ctarget = c; 132d4afb5ceSopenharmony_ci c = tmp; 133d4afb5ceSopenharmony_ci } 134d4afb5ceSopenharmony_ci x0 = j0; 135d4afb5ceSopenharmony_ci x1 = j1; 136d4afb5ceSopenharmony_ci x2 = j2; 137d4afb5ceSopenharmony_ci x3 = j3; 138d4afb5ceSopenharmony_ci x4 = j4; 139d4afb5ceSopenharmony_ci x5 = j5; 140d4afb5ceSopenharmony_ci x6 = j6; 141d4afb5ceSopenharmony_ci x7 = j7; 142d4afb5ceSopenharmony_ci x8 = j8; 143d4afb5ceSopenharmony_ci x9 = j9; 144d4afb5ceSopenharmony_ci x10 = j10; 145d4afb5ceSopenharmony_ci x11 = j11; 146d4afb5ceSopenharmony_ci x12 = j12; 147d4afb5ceSopenharmony_ci x13 = j13; 148d4afb5ceSopenharmony_ci x14 = j14; 149d4afb5ceSopenharmony_ci x15 = j15; 150d4afb5ceSopenharmony_ci for (i = 20;i > 0;i -= 2) { 151d4afb5ceSopenharmony_ci QUARTERROUND( x0, x4, x8,x12) 152d4afb5ceSopenharmony_ci QUARTERROUND( x1, x5, x9,x13) 153d4afb5ceSopenharmony_ci QUARTERROUND( x2, x6,x10,x14) 154d4afb5ceSopenharmony_ci QUARTERROUND( x3, x7,x11,x15) 155d4afb5ceSopenharmony_ci QUARTERROUND( x0, x5,x10,x15) 156d4afb5ceSopenharmony_ci QUARTERROUND( x1, x6,x11,x12) 157d4afb5ceSopenharmony_ci QUARTERROUND( x2, x7, x8,x13) 158d4afb5ceSopenharmony_ci QUARTERROUND( x3, x4, x9,x14) 159d4afb5ceSopenharmony_ci } 160d4afb5ceSopenharmony_ci x0 = PLUS(x0,j0); 161d4afb5ceSopenharmony_ci x1 = PLUS(x1,j1); 162d4afb5ceSopenharmony_ci x2 = PLUS(x2,j2); 163d4afb5ceSopenharmony_ci x3 = PLUS(x3,j3); 164d4afb5ceSopenharmony_ci x4 = PLUS(x4,j4); 165d4afb5ceSopenharmony_ci x5 = PLUS(x5,j5); 166d4afb5ceSopenharmony_ci x6 = PLUS(x6,j6); 167d4afb5ceSopenharmony_ci x7 = PLUS(x7,j7); 168d4afb5ceSopenharmony_ci x8 = PLUS(x8,j8); 169d4afb5ceSopenharmony_ci x9 = PLUS(x9,j9); 170d4afb5ceSopenharmony_ci x10 = PLUS(x10,j10); 171d4afb5ceSopenharmony_ci x11 = PLUS(x11,j11); 172d4afb5ceSopenharmony_ci x12 = PLUS(x12,j12); 173d4afb5ceSopenharmony_ci x13 = PLUS(x13,j13); 174d4afb5ceSopenharmony_ci x14 = PLUS(x14,j14); 175d4afb5ceSopenharmony_ci x15 = PLUS(x15,j15); 176d4afb5ceSopenharmony_ci 177d4afb5ceSopenharmony_ci x0 = XOR(x0,U8TO32_LITTLE(m + 0)); 178d4afb5ceSopenharmony_ci x1 = XOR(x1,U8TO32_LITTLE(m + 4)); 179d4afb5ceSopenharmony_ci x2 = XOR(x2,U8TO32_LITTLE(m + 8)); 180d4afb5ceSopenharmony_ci x3 = XOR(x3,U8TO32_LITTLE(m + 12)); 181d4afb5ceSopenharmony_ci x4 = XOR(x4,U8TO32_LITTLE(m + 16)); 182d4afb5ceSopenharmony_ci x5 = XOR(x5,U8TO32_LITTLE(m + 20)); 183d4afb5ceSopenharmony_ci x6 = XOR(x6,U8TO32_LITTLE(m + 24)); 184d4afb5ceSopenharmony_ci x7 = XOR(x7,U8TO32_LITTLE(m + 28)); 185d4afb5ceSopenharmony_ci x8 = XOR(x8,U8TO32_LITTLE(m + 32)); 186d4afb5ceSopenharmony_ci x9 = XOR(x9,U8TO32_LITTLE(m + 36)); 187d4afb5ceSopenharmony_ci x10 = XOR(x10,U8TO32_LITTLE(m + 40)); 188d4afb5ceSopenharmony_ci x11 = XOR(x11,U8TO32_LITTLE(m + 44)); 189d4afb5ceSopenharmony_ci x12 = XOR(x12,U8TO32_LITTLE(m + 48)); 190d4afb5ceSopenharmony_ci x13 = XOR(x13,U8TO32_LITTLE(m + 52)); 191d4afb5ceSopenharmony_ci x14 = XOR(x14,U8TO32_LITTLE(m + 56)); 192d4afb5ceSopenharmony_ci x15 = XOR(x15,U8TO32_LITTLE(m + 60)); 193d4afb5ceSopenharmony_ci 194d4afb5ceSopenharmony_ci j12 = PLUSONE(j12); 195d4afb5ceSopenharmony_ci if (!j12) 196d4afb5ceSopenharmony_ci j13 = PLUSONE(j13); 197d4afb5ceSopenharmony_ci /* stopping at 2^70 bytes per nonce is user's responsibility */ 198d4afb5ceSopenharmony_ci 199d4afb5ceSopenharmony_ci U32TO8_LITTLE(c + 0,x0); 200d4afb5ceSopenharmony_ci U32TO8_LITTLE(c + 4,x1); 201d4afb5ceSopenharmony_ci U32TO8_LITTLE(c + 8,x2); 202d4afb5ceSopenharmony_ci U32TO8_LITTLE(c + 12,x3); 203d4afb5ceSopenharmony_ci U32TO8_LITTLE(c + 16,x4); 204d4afb5ceSopenharmony_ci U32TO8_LITTLE(c + 20,x5); 205d4afb5ceSopenharmony_ci U32TO8_LITTLE(c + 24,x6); 206d4afb5ceSopenharmony_ci U32TO8_LITTLE(c + 28,x7); 207d4afb5ceSopenharmony_ci U32TO8_LITTLE(c + 32,x8); 208d4afb5ceSopenharmony_ci U32TO8_LITTLE(c + 36,x9); 209d4afb5ceSopenharmony_ci U32TO8_LITTLE(c + 40,x10); 210d4afb5ceSopenharmony_ci U32TO8_LITTLE(c + 44,x11); 211d4afb5ceSopenharmony_ci U32TO8_LITTLE(c + 48,x12); 212d4afb5ceSopenharmony_ci U32TO8_LITTLE(c + 52,x13); 213d4afb5ceSopenharmony_ci U32TO8_LITTLE(c + 56,x14); 214d4afb5ceSopenharmony_ci U32TO8_LITTLE(c + 60,x15); 215d4afb5ceSopenharmony_ci 216d4afb5ceSopenharmony_ci if (bytes <= 64) { 217d4afb5ceSopenharmony_ci if (bytes < 64) { 218d4afb5ceSopenharmony_ci for (i = 0;i < bytes;++i) ctarget[i] = c[i]; 219d4afb5ceSopenharmony_ci } 220d4afb5ceSopenharmony_ci x->input[12] = j12; 221d4afb5ceSopenharmony_ci x->input[13] = j13; 222d4afb5ceSopenharmony_ci return; 223d4afb5ceSopenharmony_ci } 224d4afb5ceSopenharmony_ci bytes -= 64; 225d4afb5ceSopenharmony_ci c += 64; 226d4afb5ceSopenharmony_ci m += 64; 227d4afb5ceSopenharmony_ci } 228d4afb5ceSopenharmony_ci} 229d4afb5ceSopenharmony_ci 230d4afb5ceSopenharmony_cistruct lws_cipher_chacha { 231d4afb5ceSopenharmony_ci struct chacha_ctx ccctx[2]; 232d4afb5ceSopenharmony_ci}; 233d4afb5ceSopenharmony_ci 234d4afb5ceSopenharmony_ci#define K_1(_keys) &((struct lws_cipher_chacha *)_keys->cipher)->ccctx[0] 235d4afb5ceSopenharmony_ci#define K_2(_keys) &((struct lws_cipher_chacha *)_keys->cipher)->ccctx[1] 236d4afb5ceSopenharmony_ci 237d4afb5ceSopenharmony_ciint 238d4afb5ceSopenharmony_cilws_chacha_activate(struct lws_ssh_keys *keys) 239d4afb5ceSopenharmony_ci{ 240d4afb5ceSopenharmony_ci if (keys->cipher) { 241d4afb5ceSopenharmony_ci free(keys->cipher); 242d4afb5ceSopenharmony_ci keys->cipher = NULL; 243d4afb5ceSopenharmony_ci } 244d4afb5ceSopenharmony_ci 245d4afb5ceSopenharmony_ci keys->cipher = malloc(sizeof(struct lws_cipher_chacha)); 246d4afb5ceSopenharmony_ci if (!keys->cipher) 247d4afb5ceSopenharmony_ci return 1; 248d4afb5ceSopenharmony_ci 249d4afb5ceSopenharmony_ci memset(keys->cipher, 0, sizeof(struct lws_cipher_chacha)); 250d4afb5ceSopenharmony_ci 251d4afb5ceSopenharmony_ci /* uses 2 x 256-bit keys, so 512 bits (64 bytes) needed */ 252d4afb5ceSopenharmony_ci chacha_keysetup(K_2(keys), keys->key[SSH_KEYIDX_ENC], 256); 253d4afb5ceSopenharmony_ci chacha_keysetup(K_1(keys), &keys->key[SSH_KEYIDX_ENC][32], 256); 254d4afb5ceSopenharmony_ci 255d4afb5ceSopenharmony_ci keys->valid = 1; 256d4afb5ceSopenharmony_ci keys->full_length = 1; 257d4afb5ceSopenharmony_ci keys->padding_alignment = 8; // CHACHA_BLOCKLEN; 258d4afb5ceSopenharmony_ci keys->MAC_length = POLY1305_TAGLEN; 259d4afb5ceSopenharmony_ci 260d4afb5ceSopenharmony_ci return 0; 261d4afb5ceSopenharmony_ci} 262d4afb5ceSopenharmony_ci 263d4afb5ceSopenharmony_civoid 264d4afb5ceSopenharmony_cilws_chacha_destroy(struct lws_ssh_keys *keys) 265d4afb5ceSopenharmony_ci{ 266d4afb5ceSopenharmony_ci if (keys->cipher) { 267d4afb5ceSopenharmony_ci free(keys->cipher); 268d4afb5ceSopenharmony_ci keys->cipher = NULL; 269d4afb5ceSopenharmony_ci } 270d4afb5ceSopenharmony_ci} 271d4afb5ceSopenharmony_ci 272d4afb5ceSopenharmony_ciuint32_t 273d4afb5ceSopenharmony_cilws_chachapoly_get_length(struct lws_ssh_keys *keys, uint32_t seq, 274d4afb5ceSopenharmony_ci const uint8_t *in4) 275d4afb5ceSopenharmony_ci{ 276d4afb5ceSopenharmony_ci uint8_t buf[4], seqbuf[8]; 277d4afb5ceSopenharmony_ci 278d4afb5ceSopenharmony_ci /* 279d4afb5ceSopenharmony_ci * When receiving a packet, the length must be decrypted first. When 4 280d4afb5ceSopenharmony_ci * bytes of ciphertext length have been received, they may be decrypted 281d4afb5ceSopenharmony_ci * using the K_1 key, a nonce consisting of the packet sequence number 282d4afb5ceSopenharmony_ci * encoded as a uint64 under the usual SSH wire encoding and a zero 283d4afb5ceSopenharmony_ci * block counter to obtain the plaintext length. 284d4afb5ceSopenharmony_ci */ 285d4afb5ceSopenharmony_ci POKE_U64(seqbuf, seq); 286d4afb5ceSopenharmony_ci chacha_ivsetup(K_1(keys), seqbuf, NULL); 287d4afb5ceSopenharmony_ci chacha_encrypt_bytes(K_1(keys), in4, buf, 4); 288d4afb5ceSopenharmony_ci 289d4afb5ceSopenharmony_ci return PEEK_U32(buf); 290d4afb5ceSopenharmony_ci} 291d4afb5ceSopenharmony_ci 292d4afb5ceSopenharmony_ci/* 293d4afb5ceSopenharmony_ci * chachapoly_crypt() operates as following: 294d4afb5ceSopenharmony_ci * En/decrypt with header key 'aadlen' bytes from 'src', storing result 295d4afb5ceSopenharmony_ci * to 'dest'. The ciphertext here is treated as additional authenticated 296d4afb5ceSopenharmony_ci * data for MAC calculation. 297d4afb5ceSopenharmony_ci * En/decrypt 'len' bytes at offset 'aadlen' from 'src' to 'dest'. Use 298d4afb5ceSopenharmony_ci * POLY1305_TAGLEN bytes at offset 'len'+'aadlen' as the authentication 299d4afb5ceSopenharmony_ci * tag. This tag is written on encryption and verified on decryption. 300d4afb5ceSopenharmony_ci */ 301d4afb5ceSopenharmony_ciint 302d4afb5ceSopenharmony_cichachapoly_crypt(struct lws_ssh_keys *keys, u_int seqnr, u_char *dest, 303d4afb5ceSopenharmony_ci const u_char *src, u_int len, u_int aadlen, u_int authlen, int do_encrypt) 304d4afb5ceSopenharmony_ci{ 305d4afb5ceSopenharmony_ci u_char seqbuf[8]; 306d4afb5ceSopenharmony_ci const u_char one[8] = { 1, 0, 0, 0, 0, 0, 0, 0 }; /* NB little-endian */ 307d4afb5ceSopenharmony_ci u_char expected_tag[POLY1305_TAGLEN], poly_key[POLY1305_KEYLEN]; 308d4afb5ceSopenharmony_ci int r = 1; 309d4afb5ceSopenharmony_ci 310d4afb5ceSopenharmony_ci /* 311d4afb5ceSopenharmony_ci * Run ChaCha20 once to generate the Poly1305 key. The IV is the 312d4afb5ceSopenharmony_ci * packet sequence number. 313d4afb5ceSopenharmony_ci */ 314d4afb5ceSopenharmony_ci memset(poly_key, 0, sizeof(poly_key)); 315d4afb5ceSopenharmony_ci POKE_U64(seqbuf, seqnr); 316d4afb5ceSopenharmony_ci chacha_ivsetup(K_2(keys), seqbuf, NULL); 317d4afb5ceSopenharmony_ci chacha_encrypt_bytes(K_2(keys), 318d4afb5ceSopenharmony_ci poly_key, poly_key, sizeof(poly_key)); 319d4afb5ceSopenharmony_ci 320d4afb5ceSopenharmony_ci /* If decrypting, check tag before anything else */ 321d4afb5ceSopenharmony_ci if (!do_encrypt) { 322d4afb5ceSopenharmony_ci const u_char *tag = src + aadlen + len; 323d4afb5ceSopenharmony_ci 324d4afb5ceSopenharmony_ci poly1305_auth(expected_tag, src, aadlen + len, poly_key); 325d4afb5ceSopenharmony_ci if (lws_timingsafe_bcmp(expected_tag, tag, POLY1305_TAGLEN)) { 326d4afb5ceSopenharmony_ci r = 2; 327d4afb5ceSopenharmony_ci goto out; 328d4afb5ceSopenharmony_ci } 329d4afb5ceSopenharmony_ci } 330d4afb5ceSopenharmony_ci 331d4afb5ceSopenharmony_ci /* Crypt additional data */ 332d4afb5ceSopenharmony_ci if (aadlen) { 333d4afb5ceSopenharmony_ci chacha_ivsetup(K_1(keys), seqbuf, NULL); 334d4afb5ceSopenharmony_ci chacha_encrypt_bytes(K_1(keys), src, dest, aadlen); 335d4afb5ceSopenharmony_ci } 336d4afb5ceSopenharmony_ci 337d4afb5ceSopenharmony_ci /* Set Chacha's block counter to 1 */ 338d4afb5ceSopenharmony_ci chacha_ivsetup(K_2(keys), seqbuf, one); 339d4afb5ceSopenharmony_ci chacha_encrypt_bytes(K_2(keys), src + aadlen, dest + aadlen, len); 340d4afb5ceSopenharmony_ci 341d4afb5ceSopenharmony_ci /* If encrypting, calculate and append tag */ 342d4afb5ceSopenharmony_ci if (do_encrypt) { 343d4afb5ceSopenharmony_ci poly1305_auth(dest + aadlen + len, dest, aadlen + len, 344d4afb5ceSopenharmony_ci poly_key); 345d4afb5ceSopenharmony_ci } 346d4afb5ceSopenharmony_ci r = 0; 347d4afb5ceSopenharmony_ci out: 348d4afb5ceSopenharmony_ci lws_explicit_bzero(expected_tag, sizeof(expected_tag)); 349d4afb5ceSopenharmony_ci lws_explicit_bzero(seqbuf, sizeof(seqbuf)); 350d4afb5ceSopenharmony_ci lws_explicit_bzero(poly_key, sizeof(poly_key)); 351d4afb5ceSopenharmony_ci return r; 352d4afb5ceSopenharmony_ci} 353d4afb5ceSopenharmony_ci 354d4afb5ceSopenharmony_ciint 355d4afb5ceSopenharmony_cilws_chacha_decrypt(struct lws_ssh_keys *keys, uint32_t seq, 356d4afb5ceSopenharmony_ci const uint8_t *ct, uint32_t len, uint8_t *pt) 357d4afb5ceSopenharmony_ci{ 358d4afb5ceSopenharmony_ci return chachapoly_crypt(keys, seq, pt, ct, len - POLY1305_TAGLEN - 4, 4, 359d4afb5ceSopenharmony_ci POLY1305_TAGLEN, 0); 360d4afb5ceSopenharmony_ci} 361d4afb5ceSopenharmony_ci 362d4afb5ceSopenharmony_ciint 363d4afb5ceSopenharmony_cilws_chacha_encrypt(struct lws_ssh_keys *keys, uint32_t seq, 364d4afb5ceSopenharmony_ci const uint8_t *ct, uint32_t len, uint8_t *pt) 365d4afb5ceSopenharmony_ci{ 366d4afb5ceSopenharmony_ci return chachapoly_crypt(keys, seq, pt, ct, len - 4, 4, 0, 1); 367d4afb5ceSopenharmony_ci} 368d4afb5ceSopenharmony_ci 369