Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/feature_posix/sys/src/libsec/port/chacha.c – Rev 26

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
26 7u83 1
/*
2
Adapted from chacha-merged.c version 20080118
3
D. J. Bernstein
4
Public domain.
5
 
6
modified for use in Plan 9 and Inferno (no algorithmic changes),
7
and including the changes to block number and nonce defined in RFC7539
8
*/
9
 
10
#include "os.h"
11
#include <libsec.h>
12
 
13
/* from chachablock.$O */
14
extern void _chachablock(u32int x[16], int rounds);
15
 
16
/* little-endian data order */
17
#define	GET4(p)		((p)[0]|((p)[1]<<8)|((p)[2]<<16)|((p)[3]<<24))
18
#define	PUT4(p,v)	(p)[0]=(v);(p)[1]=(v)>>8;(p)[2]=(v)>>16;(p)[3]=(v)>>24
19
 
20
#define ENCRYPT(s, x, y, d) {\
21
	u32int v; \
22
	v = GET4(s); \
23
	v ^= (x)+(y); \
24
	PUT4(d, v); \
25
}
26
 
27
static uchar sigma[16] = "expand 32-byte k";
28
static uchar tau[16] = "expand 16-byte k";
29
 
30
static void
31
load(u32int *d, uchar *s, int nw)
32
{
33
	int i;
34
 
35
	for(i = 0; i < nw; i++, s+=4)
36
		d[i] = GET4(s);
37
}
38
 
39
void
40
setupChachastate(Chachastate *s, uchar *key, ulong keylen, uchar *iv, ulong ivlen, int rounds)
41
{
42
	if(keylen != 256/8 && keylen != 128/8)
43
		sysfatal("invalid chacha key length");
44
	if(ivlen != 64/8 && ivlen != 96/8
45
	&& ivlen != 128/8 && ivlen != 192/8)	/* hchacha, xchacha */
46
		sysfatal("invalid chacha iv length");
47
	if(rounds == 0)
48
		rounds = 20;
49
	s->rounds = rounds;
50
	if(keylen == 256/8) { /* recommended */
51
		load(&s->input[0], sigma, 4);
52
		load(&s->input[4], key, 8);
53
	}else{
54
		load(&s->input[0], tau, 4);
55
		load(&s->input[4], key, 4);
56
		load(&s->input[8], key, 4);
57
	}
58
	s->xkey[0] = s->input[4];
59
	s->xkey[1] = s->input[5];
60
	s->xkey[2] = s->input[6];
61
	s->xkey[3] = s->input[7];
62
	s->xkey[4] = s->input[8];
63
	s->xkey[5] = s->input[9];
64
	s->xkey[6] = s->input[10];
65
	s->xkey[7] = s->input[11];
66
 
67
	s->ivwords = ivlen/4;
68
	s->input[12] = 0;
69
	s->input[13] = 0;
70
	if(iv == nil){
71
		s->input[14] = 0;
72
		s->input[15] = 0;
73
	}else
74
		chacha_setiv(s, iv);
75
}
76
 
77
static void
78
hchachablock(uchar h[32], Chachastate *s)
79
{
80
	u32int x[16];
81
 
82
	x[0] = s->input[0];
83
	x[1] = s->input[1];
84
	x[2] = s->input[2];
85
	x[3] = s->input[3];
86
	x[4] = s->input[4];
87
	x[5] = s->input[5];
88
	x[6] = s->input[6];
89
	x[7] = s->input[7];
90
	x[8] = s->input[8];
91
	x[9] = s->input[9];
92
	x[10] = s->input[10];
93
	x[11] = s->input[11];
94
	x[12] = s->input[12];
95
	x[13] = s->input[13];
96
	x[14] = s->input[14];
97
	x[15] = s->input[15];
98
 
99
	_chachablock(x, s->rounds);
100
 
101
	PUT4(h+0*4, x[0]);
102
	PUT4(h+1*4, x[1]);
103
	PUT4(h+2*4, x[2]);
104
	PUT4(h+3*4, x[3]);
105
	PUT4(h+4*4, x[12]);
106
	PUT4(h+5*4, x[13]);
107
	PUT4(h+6*4, x[14]);
108
	PUT4(h+7*4, x[15]);
109
}
110
 
111
void
112
chacha_setiv(Chachastate *s, uchar *iv)
113
{
114
	if(s->ivwords == 192/32){
115
		/* xchacha with 192-bit iv */
116
		u32int counter[2];
117
		uchar h[32];
118
 
119
		s->input[4] = s->xkey[0];
120
		s->input[5] = s->xkey[1];
121
		s->input[6] = s->xkey[2];
122
		s->input[7] = s->xkey[3];
123
		s->input[8] = s->xkey[4];
124
		s->input[9] = s->xkey[5];
125
		s->input[10] = s->xkey[6];
126
		s->input[11] = s->xkey[7];
127
 
128
		counter[0] = s->input[12];
129
		counter[1] = s->input[13];
130
 
131
		load(&s->input[12], iv, 4);
132
 
133
		hchachablock(h, s);
134
		load(&s->input[4], h, 8);
135
		memset(h, 0, 32);
136
 
137
		s->input[12] = counter[0];
138
		s->input[13] = counter[1];
139
 
140
		load(&s->input[14], iv+16, 2);
141
		return;
142
	}
143
	load(&s->input[16 - s->ivwords], iv, s->ivwords);
144
}
145
 
146
void
147
chacha_setblock(Chachastate *s, u64int blockno)
148
{
149
	s->input[12] = blockno;
150
	if(s->ivwords != 3)
151
		s->input[13] = blockno>>32;
152
}
153
 
154
static void
155
encryptblock(Chachastate *s, uchar *src, uchar *dst)
156
{
157
	u32int x[16];
158
	int i;
159
 
160
	x[0] = s->input[0];
161
	x[1] = s->input[1];
162
	x[2] = s->input[2];
163
	x[3] = s->input[3];
164
	x[4] = s->input[4];
165
	x[5] = s->input[5];
166
	x[6] = s->input[6];
167
	x[7] = s->input[7];
168
	x[8] = s->input[8];
169
	x[9] = s->input[9];
170
	x[10] = s->input[10];
171
	x[11] = s->input[11];
172
	x[12] = s->input[12];
173
	x[13] = s->input[13];
174
	x[14] = s->input[14];
175
	x[15] = s->input[15];
176
	_chachablock(x, s->rounds);
177
 
178
	for(i=0; i<nelem(x); i+=4){
179
		ENCRYPT(src, x[i], s->input[i], dst);
180
		ENCRYPT(src+4, x[i+1], s->input[i+1], dst+4);
181
		ENCRYPT(src+8, x[i+2], s->input[i+2], dst+8);
182
		ENCRYPT(src+12, x[i+3], s->input[i+3], dst+12);
183
		src += 16;
184
		dst += 16;
185
	}
186
 
187
	if(++s->input[12] == 0 && s->ivwords != 3)
188
		s->input[13]++;
189
}
190
 
191
void
192
chacha_encrypt2(uchar *src, uchar *dst, ulong bytes, Chachastate *s)
193
{
194
	uchar tmp[ChachaBsize];
195
 
196
	for(; bytes >= ChachaBsize; bytes -= ChachaBsize){
197
		encryptblock(s, src, dst);
198
		src += ChachaBsize;
199
		dst += ChachaBsize;
200
	}
201
	if(bytes > 0){
202
		memmove(tmp, src, bytes);
203
		encryptblock(s, tmp, tmp);
204
		memmove(dst, tmp, bytes);
205
	}
206
}
207
 
208
void
209
chacha_encrypt(uchar *buf, ulong bytes, Chachastate *s)
210
{
211
	chacha_encrypt2(buf, buf, bytes, s);
212
}
213
 
214
void
215
hchacha(uchar h[32], uchar *key, ulong keylen, uchar nonce[16], int rounds)
216
{
217
	Chachastate s[1];
218
 
219
	setupChachastate(s, key, keylen, nonce, 16, rounds);
220
	hchachablock(h, s);
221
	memset(s, 0, sizeof(s));
222
}