--- /n/sources/plan9/sys/src/libsec/port/chacha.c Sat Jun 14 00:00:00 2025 +++ /sys/src/libsec/port/chacha.c Thu Jan 12 20:16:38 2017 @@ -57,7 +57,8 @@ { if(keylen != 256/8 && keylen != 128/8) sysfatal("invalid chacha key length"); - if(ivlen != 96/8 && ivlen != 64/8) + if(ivlen != 64/8 && ivlen != 96/8 + && ivlen != 128/8 && ivlen != 192/8) /* hchacha, xchacha */ sysfatal("invalid chacha iv length"); if(rounds == 0) rounds = 20; @@ -70,7 +71,16 @@ load(&s->input[4], key, 4); load(&s->input[8], key, 4); } - s->ivwords = ivlen/sizeof(u32int); + s->xkey[0] = s->input[4]; + s->xkey[1] = s->input[5]; + s->xkey[2] = s->input[6]; + s->xkey[3] = s->input[7]; + s->xkey[4] = s->input[8]; + s->xkey[5] = s->input[9]; + s->xkey[6] = s->input[10]; + s->xkey[7] = s->input[11]; + + s->ivwords = ivlen/4; s->input[12] = 0; s->input[13] = 0; if(iv == nil){ @@ -80,20 +90,6 @@ chacha_setiv(s, iv); } -void -chacha_setiv(Chachastate *s, uchar *iv) -{ - load(&s->input[16 - s->ivwords], iv, s->ivwords); -} - -void -chacha_setblock(Chachastate *s, u64int blockno) -{ - s->input[12] = blockno; - if(s->ivwords == 2) - s->input[13] = blockno>>32; -} - static void dorounds(u32int x[Blockwords], int rounds) { @@ -111,6 +107,83 @@ } static void +hchachablock(uchar h[32], Chachastate *s) +{ + u32int x[16]; + + x[0] = s->input[0]; + x[1] = s->input[1]; + x[2] = s->input[2]; + x[3] = s->input[3]; + x[4] = s->input[4]; + x[5] = s->input[5]; + x[6] = s->input[6]; + x[7] = s->input[7]; + x[8] = s->input[8]; + x[9] = s->input[9]; + x[10] = s->input[10]; + x[11] = s->input[11]; + x[12] = s->input[12]; + x[13] = s->input[13]; + x[14] = s->input[14]; + x[15] = s->input[15]; + + dorounds(x, s->rounds); + + PUT4(h+0*4, x[0]); + PUT4(h+1*4, x[1]); + PUT4(h+2*4, x[2]); + PUT4(h+3*4, x[3]); + PUT4(h+4*4, x[12]); + PUT4(h+5*4, x[13]); + PUT4(h+6*4, x[14]); + PUT4(h+7*4, x[15]); +} + +void +chacha_setiv(Chachastate *s, uchar *iv) +{ + if(s->ivwords == 192/32){ + /* xchacha with 192-bit iv */ + u32int counter[2]; + uchar h[32]; + + s->input[4] = s->xkey[0]; + s->input[5] = s->xkey[1]; + s->input[6] = s->xkey[2]; + s->input[7] = s->xkey[3]; + s->input[8] = s->xkey[4]; + s->input[9] = s->xkey[5]; + s->input[10] = s->xkey[6]; + s->input[11] = s->xkey[7]; + + counter[0] = s->input[12]; + counter[1] = s->input[13]; + + load(&s->input[12], iv, 4); + + hchachablock(h, s); + load(&s->input[4], h, 8); + memset(h, 0, 32); + + s->input[12] = counter[0]; + s->input[13] = counter[1]; + + load(&s->input[14], iv+16, 2); + return; + } + load(&s->input[16 - s->ivwords], iv, s->ivwords); +} + +void +chacha_setblock(Chachastate *s, u64int blockno) +{ + s->input[12] = blockno; + if(s->ivwords != 3) + s->input[13] = blockno>>32; +} + +static void encryptblock(Chachastate *s, uchar *src, uchar *dst) { u32int x[Blockwords]; @@ -143,7 +216,7 @@ dst += 16; } - if(++s->input[12] == 0 && s->ivwords == 2) + if(++s->input[12] == 0 && s->ivwords != 3) s->input[13]++; } @@ -169,3 +242,13 @@ { chacha_encrypt2(buf, buf, bytes, s); } + +void +hchacha(uchar h[32], uchar *key, ulong keylen, uchar nonce[16], int rounds) +{ + Chachastate s[1]; + + setupChachastate(s, key, keylen, nonce, 16, rounds); + hchachablock(h, s); + memset(s, 0, sizeof(s)); +} --- /n/sources/plan9/sys/include/libsec.h Sat Jun 14 00:00:00 2025 +++ /sys/include/libsec.h Thu Jan 12 20:16:38 2017 @@ -115,6 +115,7 @@ u32int iv[3]; }; }; + u32int xkey[8]; int rounds; int ivwords; }; @@ -125,6 +126,8 @@ void chacha_encrypt(uchar*, usize, Chachastate*); void chacha_encrypt2(uchar*, uchar*, usize, Chachastate*); +void hchacha(uchar h[32], uchar *key, ulong keylen, uchar nonce[16], int rounds); + void ccpoly_encrypt(uchar *dat, ulong ndat, uchar *aad, ulong naad, uchar tag[16], Chachastate *cs); int ccpoly_decrypt(uchar *dat, ulong ndat, uchar *aad, ulong naad, uchar tag[16], Chachastate *cs); commit a008538f12a348ec67a27dbb3c96448437dc7df1 Author: cinap_lenrek Date: Thu Jan 12 20:16:38 2017 +0100 libsec: implement extended 192-bit nonce xchacha variant and hchacha function --- /n/sources/plan9/sys/man/2/chacha Sat Jun 14 00:00:00 2025 +++ /sys/man/2/chacha Thu Jan 12 20:16:38 2017 @@ -1,6 +1,6 @@ .TH CHACHA 2 .SH NAME -setupChachastate, chacha_setblock, chacha_setiv, chacha_encrypt, chacha_encrypt2, ccpoly_encrypt, ccpoly_decrypt \- chacha encryption +setupChachastate, chacha_setblock, chacha_setiv, chacha_encrypt, chacha_encrypt2, hchacha, ccpoly_encrypt, ccpoly_decrypt \- chacha encryption .SH SYNOPSIS .B #include .br @@ -24,6 +24,9 @@ void chacha_setblock(Chachastate *s, u64int blockno) void chacha_setiv(Chachastate *s, uchar *iv); .PP .B +void hchacha(uchar h[32], uchar *key, ulong keylen, uchar nonce[16], int rounds); +.PP +.B void ccpoly_encrypt(uchar *dat, ulong ndat, uchar *aad, ulong naad, uchar tag[16], Chachastate *cs); .PP .B @@ -49,8 +52,11 @@ a or nonce of .I ivlen bytes (can be -.BR ChachaIVlen =12 -or 8, set to all zeros if the +.BR ChachaIVlen =12 , +.B 8 +or +.BR XChachaIVlen =24 ; +set to all zeros if the .I iv argument is nil), and the number of @@ -94,6 +100,10 @@ allowing seeking in an encrypted stream. sets the the initialization vector (nonce) to .IR iv . .PP +.I Hchacha +is a key expansion function that takes a 128 or 256-bit key +and a 128-bit nonce and produces a new 256-bit key. +.PP .I Ccpoly_encrypt and .I ccpoly_decrypt