19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include <mp.h>
49a747e4fSDavid du Colombier #include <libsec.h>
59a747e4fSDavid du Colombier
69a747e4fSDavid du Colombier enum {
79a747e4fSDavid du Colombier TLSFinishedLen = 12,
89a747e4fSDavid du Colombier HFinished = 20,
99a747e4fSDavid du Colombier };
109a747e4fSDavid du Colombier
119a747e4fSDavid du Colombier static int
finished(int hand,int isclient)129a747e4fSDavid du Colombier finished(int hand, int isclient)
139a747e4fSDavid du Colombier {
149a747e4fSDavid du Colombier int i, n;
159a747e4fSDavid du Colombier uchar buf[500], buf2[500];
169a747e4fSDavid du Colombier
179a747e4fSDavid du Colombier buf[0] = HFinished;
189a747e4fSDavid du Colombier buf[1] = TLSFinishedLen>>16;
199a747e4fSDavid du Colombier buf[2] = TLSFinishedLen>>8;
209a747e4fSDavid du Colombier buf[3] = TLSFinishedLen;
219a747e4fSDavid du Colombier n = TLSFinishedLen+4;
229a747e4fSDavid du Colombier
239a747e4fSDavid du Colombier for(i=0; i<2; i++){
249a747e4fSDavid du Colombier if(i==0)
259a747e4fSDavid du Colombier memmove(buf+4, "client finished", TLSFinishedLen);
269a747e4fSDavid du Colombier else
279a747e4fSDavid du Colombier memmove(buf+4, "server finished", TLSFinishedLen);
289a747e4fSDavid du Colombier if(isclient == 1-i){
299a747e4fSDavid du Colombier if(write(hand, buf, n) != n)
309a747e4fSDavid du Colombier return -1;
319a747e4fSDavid du Colombier }else{
329a747e4fSDavid du Colombier if(readn(hand, buf2, n) != n || memcmp(buf,buf2,n) != 0)
339a747e4fSDavid du Colombier return -1;
349a747e4fSDavid du Colombier }
359a747e4fSDavid du Colombier }
369a747e4fSDavid du Colombier return 1;
379a747e4fSDavid du Colombier }
389a747e4fSDavid du Colombier
399a747e4fSDavid du Colombier
409a747e4fSDavid du Colombier // given a plain fd and secrets established beforehand, return encrypted connection
419a747e4fSDavid du Colombier int
pushtls(int fd,char * hashalg,char * encalg,int isclient,char * secret,char * dir)429a747e4fSDavid du Colombier pushtls(int fd, char *hashalg, char *encalg, int isclient, char *secret, char *dir)
439a747e4fSDavid du Colombier {
449a747e4fSDavid du Colombier char buf[8];
459a747e4fSDavid du Colombier char dname[64];
469a747e4fSDavid du Colombier int n, data, ctl, hand;
479a747e4fSDavid du Colombier
489a747e4fSDavid du Colombier // open a new filter; get ctl fd
499a747e4fSDavid du Colombier data = hand = -1;
509a747e4fSDavid du Colombier // /net/tls uses decimal file descriptors to name channels, hence a
519a747e4fSDavid du Colombier // user-level file server can't stand in for #a; may as well hard-code it.
529a747e4fSDavid du Colombier ctl = open("#a/tls/clone", ORDWR);
539a747e4fSDavid du Colombier if(ctl < 0)
549a747e4fSDavid du Colombier goto error;
559a747e4fSDavid du Colombier n = read(ctl, buf, sizeof(buf)-1);
569a747e4fSDavid du Colombier if(n < 0)
579a747e4fSDavid du Colombier goto error;
589a747e4fSDavid du Colombier buf[n] = 0;
599a747e4fSDavid du Colombier if(dir)
609a747e4fSDavid du Colombier sprint(dir, "#a/tls/%s", buf);
619a747e4fSDavid du Colombier
629a747e4fSDavid du Colombier // get application fd
639a747e4fSDavid du Colombier sprint(dname, "#a/tls/%s/data", buf);
649a747e4fSDavid du Colombier data = open(dname, ORDWR);
659a747e4fSDavid du Colombier if(data < 0)
669a747e4fSDavid du Colombier goto error;
679a747e4fSDavid du Colombier
689a747e4fSDavid du Colombier // get handshake fd
699a747e4fSDavid du Colombier sprint(dname, "#a/tls/%s/hand", buf);
709a747e4fSDavid du Colombier hand = open(dname, ORDWR);
719a747e4fSDavid du Colombier if(hand < 0)
729a747e4fSDavid du Colombier goto error;
739a747e4fSDavid du Colombier
749a747e4fSDavid du Colombier // speak a minimal handshake
759a747e4fSDavid du Colombier if(fprint(ctl, "fd %d 0x301", fd) < 0 ||
769a747e4fSDavid du Colombier fprint(ctl, "version 0x301") < 0 ||
779a747e4fSDavid du Colombier fprint(ctl, "secret %s %s %d %s", hashalg, encalg, isclient, secret) < 0 ||
789a747e4fSDavid du Colombier fprint(ctl, "changecipher") < 0 ||
799a747e4fSDavid du Colombier finished(hand, isclient) < 0 ||
809a747e4fSDavid du Colombier fprint(ctl, "opened") < 0){
819a747e4fSDavid du Colombier close(hand);
829a747e4fSDavid du Colombier hand = -1;
83*e288d156SDavid du Colombier goto error;
849a747e4fSDavid du Colombier }
859a747e4fSDavid du Colombier close(ctl);
869a747e4fSDavid du Colombier close(hand);
879a747e4fSDavid du Colombier close(fd);
889a747e4fSDavid du Colombier return data;
899a747e4fSDavid du Colombier
909a747e4fSDavid du Colombier error:
919a747e4fSDavid du Colombier if(data>=0)
929a747e4fSDavid du Colombier close(data);
939a747e4fSDavid du Colombier if(ctl>=0)
949a747e4fSDavid du Colombier close(ctl);
959a747e4fSDavid du Colombier if(hand>=0)
969a747e4fSDavid du Colombier close(hand);
979a747e4fSDavid du Colombier return -1;
989a747e4fSDavid du Colombier }
99