summaryrefslogtreecommitdiff
path: root/sys/src/libauthsrv/form1.c
blob: 9ff4a1fad81e1a29c2b5354d8b28aec4980c49ec (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include <u.h>
#include <libc.h>
#include <authsrv.h>
#include <libsec.h>

/*
 * new ticket format: the reply protector/type is replaced by a
 * 8 byte signature and a 4 byte counter forming the 12 byte
 * nonce for chacha20/poly1305 encryption. a 16 byte poly1305 
 * authentication tag is appended for message authentication.
 * the counter is needed for the AuthPass message which uses
 * the same key for several messages.
 */

static struct {
	char	num;
	char	sig[8];
} form1sig[] = {
	AuthPass,	"form1 PR",	/* password change request encrypted with ticket key */
	AuthTs,		"form1 Ts",	/* ticket encrypted with server's key */
	AuthTc, 	"form1 Tc",	/* ticket encrypted with client's key */
	AuthAs,		"form1 As",	/* server generated authenticator */
	AuthAc,		"form1 Ac",	/* client generated authenticator */
	AuthTp,		"form1 Tp",	/* ticket encrypted with client's key for password change */
	AuthHr,		"form1 Hr",	/* http reply */
};

int
form1check(char *ap, int n)
{
	if(n < 8)
		return -1;

	for(n=0; n<nelem(form1sig); n++)
		if(memcmp(form1sig[n].sig, ap, 8) == 0)
			return form1sig[n].num;

	return -1;
}

int
form1B2M(char *ap, int n, uchar key[32])
{
	static u32int counter;
	Chachastate s;
	uchar *p;
	int i;

	for(i=nelem(form1sig)-1; i>=0; i--)
		if(form1sig[i].num == *ap)
			break;
	if(i < 0)
		abort();

	p = (uchar*)ap + 12;
	memmove(p, ap+1, --n);

	/* nonce[12] = sig[8] | counter[4] */
	memmove(ap, form1sig[i].sig, 8);
	i = counter++;
	ap[8] = i, ap[9] = i>>8, ap[10] = i>>16, ap[11] = i>>24;

	setupChachastate(&s, key, 32, (uchar*)ap, 12, 20);
	ccpoly_encrypt(p, n, nil, 0, p+n, &s);
	return 12+16 + n;
}

int
form1M2B(char *ap, int n, uchar key[32])
{
	Chachastate s;
	uchar *p;
	int num;

	num = form1check(ap, n);
	if(num < 0)
		return -1;
	n -= 12+16;
	if(n <= 0)
		return -1;

	p = (uchar*)ap + 12;
	setupChachastate(&s, key, 32, (uchar*)ap, 12, 20);
	if(ccpoly_decrypt(p, n, nil, 0, p+n, &s))
		return -1;

	memmove(ap+1, p, n);
	ap[0] = num;
	return n+1;
}