1*1a4050f5SDavid du Colombier #include <u.h>
2*1a4050f5SDavid du Colombier #include <libc.h>
3*1a4050f5SDavid du Colombier #include <auth.h>
4*1a4050f5SDavid du Colombier #include <mp.h>
5*1a4050f5SDavid du Colombier #include <libsec.h>
6*1a4050f5SDavid du Colombier
7*1a4050f5SDavid du Colombier enum {
8*1a4050f5SDavid du Colombier TLSFinishedLen = 12,
9*1a4050f5SDavid du Colombier HFinished = 20,
10*1a4050f5SDavid du Colombier };
11*1a4050f5SDavid du Colombier
12*1a4050f5SDavid du Colombier static int
finished(int hand,int isclient)13*1a4050f5SDavid du Colombier finished(int hand, int isclient)
14*1a4050f5SDavid du Colombier {
15*1a4050f5SDavid du Colombier int i, n;
16*1a4050f5SDavid du Colombier uchar buf[500], buf2[500];
17*1a4050f5SDavid du Colombier
18*1a4050f5SDavid du Colombier buf[0] = HFinished;
19*1a4050f5SDavid du Colombier buf[1] = TLSFinishedLen>>16;
20*1a4050f5SDavid du Colombier buf[2] = TLSFinishedLen>>8;
21*1a4050f5SDavid du Colombier buf[3] = TLSFinishedLen;
22*1a4050f5SDavid du Colombier n = TLSFinishedLen+4;
23*1a4050f5SDavid du Colombier
24*1a4050f5SDavid du Colombier for(i=0; i<2; i++){
25*1a4050f5SDavid du Colombier if(i==0)
26*1a4050f5SDavid du Colombier memmove(buf+4, "client finished", TLSFinishedLen);
27*1a4050f5SDavid du Colombier else
28*1a4050f5SDavid du Colombier memmove(buf+4, "server finished", TLSFinishedLen);
29*1a4050f5SDavid du Colombier if(isclient == 1-i){
30*1a4050f5SDavid du Colombier if(write(hand, buf, n) != n)
31*1a4050f5SDavid du Colombier return -1;
32*1a4050f5SDavid du Colombier }else{
33*1a4050f5SDavid du Colombier if(readn(hand, buf2, n) != n || memcmp(buf,buf2,n) != 0)
34*1a4050f5SDavid du Colombier return -1;
35*1a4050f5SDavid du Colombier }
36*1a4050f5SDavid du Colombier }
37*1a4050f5SDavid du Colombier return 1;
38*1a4050f5SDavid du Colombier }
39*1a4050f5SDavid du Colombier
40*1a4050f5SDavid du Colombier
41*1a4050f5SDavid du Colombier // given a plain fd and secrets established beforehand, return encrypted connection
42*1a4050f5SDavid du Colombier int
pushtls(int fd,char * hashalg,char * encalg,int isclient,char * secret,char * dir)43*1a4050f5SDavid du Colombier pushtls(int fd, char *hashalg, char *encalg, int isclient, char *secret, char *dir)
44*1a4050f5SDavid du Colombier {
45*1a4050f5SDavid du Colombier char buf[8];
46*1a4050f5SDavid du Colombier char dname[64];
47*1a4050f5SDavid du Colombier int n, data, ctl, hand;
48*1a4050f5SDavid du Colombier
49*1a4050f5SDavid du Colombier // open a new filter; get ctl fd
50*1a4050f5SDavid du Colombier data = hand = -1;
51*1a4050f5SDavid du Colombier // /net/tls uses decimal file descriptors to name channels, hence a
52*1a4050f5SDavid du Colombier // user-level file server can't stand in for #a; may as well hard-code it.
53*1a4050f5SDavid du Colombier ctl = open("#a/tls/clone", ORDWR);
54*1a4050f5SDavid du Colombier if(ctl < 0)
55*1a4050f5SDavid du Colombier goto error;
56*1a4050f5SDavid du Colombier n = read(ctl, buf, sizeof(buf)-1);
57*1a4050f5SDavid du Colombier if(n < 0)
58*1a4050f5SDavid du Colombier goto error;
59*1a4050f5SDavid du Colombier buf[n] = 0;
60*1a4050f5SDavid du Colombier if(dir)
61*1a4050f5SDavid du Colombier sprint(dir, "#a/tls/%s", buf);
62*1a4050f5SDavid du Colombier
63*1a4050f5SDavid du Colombier // get application fd
64*1a4050f5SDavid du Colombier sprint(dname, "#a/tls/%s/data", buf);
65*1a4050f5SDavid du Colombier data = open(dname, ORDWR);
66*1a4050f5SDavid du Colombier if(data < 0)
67*1a4050f5SDavid du Colombier goto error;
68*1a4050f5SDavid du Colombier
69*1a4050f5SDavid du Colombier // get handshake fd
70*1a4050f5SDavid du Colombier sprint(dname, "#a/tls/%s/hand", buf);
71*1a4050f5SDavid du Colombier hand = open(dname, ORDWR);
72*1a4050f5SDavid du Colombier if(hand < 0)
73*1a4050f5SDavid du Colombier goto error;
74*1a4050f5SDavid du Colombier
75*1a4050f5SDavid du Colombier // speak a minimal handshake
76*1a4050f5SDavid du Colombier if(fprint(ctl, "fd %d 0x301", fd) < 0 ||
77*1a4050f5SDavid du Colombier fprint(ctl, "version 0x301") < 0 ||
78*1a4050f5SDavid du Colombier fprint(ctl, "secret %s %s %d %s", hashalg, encalg, isclient, secret) < 0 ||
79*1a4050f5SDavid du Colombier fprint(ctl, "changecipher") < 0 ||
80*1a4050f5SDavid du Colombier finished(hand, isclient) < 0 ||
81*1a4050f5SDavid du Colombier fprint(ctl, "opened") < 0){
82*1a4050f5SDavid du Colombier close(hand);
83*1a4050f5SDavid du Colombier hand = -1;
84*1a4050f5SDavid du Colombier goto error;
85*1a4050f5SDavid du Colombier }
86*1a4050f5SDavid du Colombier close(ctl);
87*1a4050f5SDavid du Colombier close(hand);
88*1a4050f5SDavid du Colombier close(fd);
89*1a4050f5SDavid du Colombier return data;
90*1a4050f5SDavid du Colombier
91*1a4050f5SDavid du Colombier error:
92*1a4050f5SDavid du Colombier if(data>=0)
93*1a4050f5SDavid du Colombier close(data);
94*1a4050f5SDavid du Colombier if(ctl>=0)
95*1a4050f5SDavid du Colombier close(ctl);
96*1a4050f5SDavid du Colombier if(hand>=0)
97*1a4050f5SDavid du Colombier close(hand);
98*1a4050f5SDavid du Colombier return -1;
99*1a4050f5SDavid du Colombier }
100