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