Subversion Repositories planix.SVN

Rev

Rev 33 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
26 7u83 1
#include "os.h"
2
#include <libsec.h>
3
 
4
static void
5
load128(uchar b[16], ulong W[4])
6
{
7
	W[0] = (ulong)b[15] | (ulong)b[14]<<8 | (ulong)b[13]<<16 | (ulong)b[12]<<24;
8
	W[1] = (ulong)b[11] | (ulong)b[10]<<8 | (ulong)b[ 9]<<16 | (ulong)b[ 8]<<24;
9
	W[2] = (ulong)b[ 7] | (ulong)b[ 6]<<8 | (ulong)b[ 5]<<16 | (ulong)b[ 4]<<24;
10
	W[3] = (ulong)b[ 3] | (ulong)b[ 2]<<8 | (ulong)b[ 1]<<16 | (ulong)b[ 0]<<24;
11
}
12
 
13
static void
14
store128(ulong W[4], uchar b[16])
15
{
16
	b[15] = W[0], b[14] = W[0]>>8, b[13] = W[0]>>16, b[12] = W[0]>>24;
17
	b[11] = W[1], b[10] = W[1]>>8, b[ 9] = W[1]>>16, b[ 8] = W[1]>>24;
18
	b[ 7] = W[2], b[ 6] = W[2]>>8, b[ 5] = W[2]>>16, b[ 4] = W[2]>>24;
19
	b[ 3] = W[3], b[ 2] = W[3]>>8, b[ 1] = W[3]>>16, b[ 0] = W[3]>>24;
20
}
21
 
22
static void
23
gfmul(ulong X[4], ulong Y[4], ulong Z[4])
24
{
25
	long m, i;
26
 
27
	Z[0] = Z[1] = Z[2] = Z[3] = 0;
28
	for(i=127; i>=0; i--){
29
		m = ((long)Y[i>>5] << 31-(i&31)) >> 31;
30
		Z[0] ^= X[0] & m;
31
		Z[1] ^= X[1] & m;
32
		Z[2] ^= X[2] & m;
33
		Z[3] ^= X[3] & m;
34
		m = ((long)X[0]<<31) >> 31;
35
		X[0] = X[0]>>1 | X[1]<<31;
36
		X[1] = X[1]>>1 | X[2]<<31;
37
		X[2] = X[2]>>1 | X[3]<<31;
38
		X[3] = X[3]>>1 ^ (0xE1000000 & m);
39
	}
40
}
41
 
42
static void
43
prepareM(ulong H[4], ulong M[16][256][4])
44
{
45
	ulong X[4], i, j;
46
 
47
	for(i=0; i<16; i++){
48
		for(j=0; j<256; j++){
49
			X[0] = X[1] = X[2] = X[3] = 0;
50
			X[i>>2] = j<<((i&3)<<3);
51
			gfmul(X, H, M[i][j]);
52
		}
53
	}
54
}
55
 
56
static void
57
ghash1(AESGCMstate *s, ulong X[4], ulong Y[4])
58
{
59
	ulong *Xi, i;
60
 
61
	X[0] ^= Y[0], X[1] ^= Y[1], X[2] ^= Y[2], X[3] ^= Y[3];
62
	if(0){
63
		gfmul(X, s->H, Y);
64
		return;
65
	}
66
 
67
	Y[0] = Y[1] = Y[2] = Y[3] = 0;
68
	for(i=0; i<16; i++){
69
		Xi = s->M[i][(X[i>>2]>>((i&3)<<3))&0xFF];
70
		Y[0] ^= Xi[0];
71
		Y[1] ^= Xi[1];
72
		Y[2] ^= Xi[2];
73
		Y[3] ^= Xi[3];
74
	}
75
}
76
 
77
static void
78
ghashn(AESGCMstate *s, uchar *dat, ulong len, ulong Y[4])
79
{
80
	uchar tmp[16];
81
	ulong X[4];
82
 
83
	while(len >= 16){
84
		load128(dat, X);
85
		ghash1(s, X, Y);
86
		dat += 16, len -= 16;
87
	}
88
	if(len > 0){
89
		memmove(tmp, dat, len);
90
		memset(tmp+len, 0, 16-len);
91
		load128(tmp, X);
92
		ghash1(s, X, Y);
93
	}
94
}
95
 
96
static ulong
97
aesxctr1(AESstate *s, uchar ctr[AESbsize], uchar *dat, ulong len)
98
{
99
	uchar tmp[AESbsize];
100
	ulong i;
101
 
102
	aes_encrypt(s->ekey, s->rounds, ctr, tmp);
103
	if(len > AESbsize)
104
		len = AESbsize;
105
	for(i=0; i<len; i++)
106
		dat[i] ^= tmp[i];
107
	return len;
108
}
109
 
110
static void
111
aesxctrn(AESstate *s, uchar *dat, ulong len)
112
{
113
	uchar ctr[AESbsize];
114
	ulong i;
115
 
116
	memmove(ctr, s->ivec, AESbsize);
117
	while(len > 0){
118
		for(i=AESbsize-1; i>=AESbsize-4; i--)
119
			if(++ctr[i] != 0)
120
				break;
121
 
122
		if(aesxctr1(s, ctr, dat, len) < AESbsize)
123
			break;
124
		dat += AESbsize;
125
		len -= AESbsize;
126
	}
127
}
128
 
129
void
130
aesgcm_setiv(AESGCMstate *s, uchar *iv, int ivlen)
131
{
132
	if(ivlen == 96/8){
133
		memmove(s->ivec, iv, ivlen);
134
		memset(s->ivec+ivlen, 0, AESbsize-ivlen);
135
		s->ivec[AESbsize-1] = 1;
136
	} else {
137
		ulong L[4], Y[4] = {0};
138
 
139
		ghashn(s, iv, ivlen, Y);
140
		L[0] = ivlen << 3;
141
		L[1] = ivlen >> 29;
142
		L[2] = L[3] = 0;
143
		ghash1(s, L, Y);
144
		store128(Y, s->ivec);
145
	}
146
}
147
 
148
void
149
setupAESGCMstate(AESGCMstate *s, uchar *key, int keylen, uchar *iv, int ivlen)
150
{
151
	setupAESstate(s, key, keylen, nil);
152
 
153
	memset(s->ivec, 0, AESbsize);
154
	aes_encrypt(s->ekey, s->rounds, s->ivec, s->ivec);
155
	load128(s->ivec, s->H);
156
	memset(s->ivec, 0, AESbsize);
157
	prepareM(s->H, s->M);
158
 
159
	if(iv != nil && ivlen > 0)
160
		aesgcm_setiv(s, iv, ivlen);
161
}
162
 
163
void
164
aesgcm_encrypt(uchar *dat, ulong ndat, uchar *aad, ulong naad, uchar tag[16], AESGCMstate *s)
165
{
166
	ulong L[4], Y[4] = {0};
167
 
168
	ghashn(s, aad, naad, Y);
169
	aesxctrn(s, dat, ndat);
170
	ghashn(s, dat, ndat, Y);
171
	L[0] = ndat << 3;
172
	L[1] = ndat >> 29;
173
	L[2] = naad << 3;
174
	L[3] = naad >> 29;
175
	ghash1(s, L, Y);
176
	store128(Y, tag);
177
	aesxctr1(s, s->ivec, tag, 16);
178
}
179
 
180
int
181
aesgcm_decrypt(uchar *dat, ulong ndat, uchar *aad, ulong naad, uchar tag[16], AESGCMstate *s)
182
{
183
	ulong L[4], Y[4] = {0};
184
	uchar tmp[16];
185
 
186
	ghashn(s, aad, naad, Y);
187
	ghashn(s, dat, ndat, Y);
188
	L[0] = ndat << 3;
189
	L[1] = ndat >> 29;
190
	L[2] = naad << 3;
191
	L[3] = naad >> 29;
192
	ghash1(s, L, Y);
193
	store128(Y, tmp);
194
	aesxctr1(s, s->ivec, tmp, 16);
195
	if(tsmemcmp(tag, tmp, 16) != 0)
196
		return -1;
197
	aesxctrn(s, dat, ndat);
198
	return 0;
199
}