--- /n/sources/plan9/sys/src/cmd/cpu.c Thu Jul 22 22:25:23 2010 +++ /sys/src/cmd/cpu.c Thu Oct 27 00:00:00 2011 @@ -36,9 +36,30 @@ char *patternfile; char *origargs; +enum { + Encnone, + Encssl, + Enctls, +}; + +enum { + MaxKeyData = 136, + RandomSize = 32, +}; + +static char *encprotos[] = { + [Encnone] = "clear", + [Encssl] = "ssl", + [Enctls] = "tls", + nil, +}; + char *srvname = "ncpu"; char *exportfs = "/bin/exportfs"; char *ealgs = "rc4_256 sha1"; +char *ealg[2]; +int encproto = Encssl; +AuthInfo *ai; /* message size for exportfs; may be larger so we can do big graphics in CPU window */ int msgsize = Maxfdata+IOHDRSZ; @@ -73,8 +94,8 @@ usage(void) { fprint(2, "usage: cpu [-h system] [-u user] [-a authmethod] " - "[-e 'crypt hash'] [-k keypattern] [-P patternfile] " - "[-c cmd arg ...]\n"); + "[-E clear|ssl|tls] [-e 'crypt hash'] [-k keypattern] " + "[-P patternfile] [-c cmd arg ...]\n"); exits("usage"); } @@ -133,6 +154,17 @@ free(cmdname); } +static int +lookup(char *s, char *l[]) +{ + int i; + + for (i = 0; l[i] != 0; i++) + if (strcmp(l[i], s) == 0) + return i; + return -1; +} + void main(int argc, char **argv) { @@ -160,6 +192,10 @@ if(setam(p) < 0) fatal(0, "unknown auth method %s", p); break; + case 'E': + if ((encproto = lookup(EARGF(usage()), encprotos)) < 0) + usage(); + break; case 'e': ealgs = EARGF(usage()); if(*ealgs == 0 || strcmp(ealgs, "clear") == 0) @@ -539,7 +575,6 @@ char response[32]; Chalstate *ch; int tries; - AuthInfo *ai; if(readstr(fd, user, 32) < 0) return -1; @@ -574,27 +609,16 @@ f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7], f[8], f[9]); } -/* - * plan9 authentication followed by rc4 encryption - */ static int -p9auth(int fd) +encssl(int fd) { uchar key[16]; uchar digest[SHA1dlen]; char fromclientsecret[21]; char fromserversecret[21]; int i; - AuthInfo *ai; - procsetname("%s: auth_proxy proto=%q role=client %s", - origargs, p9authproto, keyspec); - ai = auth_proxy(fd, auth_getkey, "proto=%q role=client %s", p9authproto, keyspec); - if(ai == nil) - return -1; memmove(key+4, ai->secret, ai->nsecret); - if(ealgs == nil) - return fd; /* exchange random numbers */ srand(truerand()); @@ -614,10 +638,67 @@ /* set up encryption */ procsetname("pushssl"); - i = pushssl(fd, ealgs, fromclientsecret, fromserversecret, nil); - if(i < 0) + return pushssl(fd, ealgs, fromclientsecret, fromserversecret, nil); +} + +static int +enctls(int fd) +{ + uchar key[MaxKeyData]; + uchar crandom[RandomSize]; + uchar srandom[RandomSize]; + char *label, *secrets; + int i; + + /* exchange random numbers */ + for(i = 0; i < RandomSize; i++) + crandom[i] = fastrand(); + if(write(fd, srandom, RandomSize) != RandomSize) + return -1; + if(readn(fd, crandom, RandomSize) != RandomSize) + return -1; + + /* scramble into secrets */ + label = "master secret"; + tls12PRF(key, MaxKeyData, ai->secret, ai->nsecret, label, crandom, RandomSize, srandom, RandomSize); + secrets = malloc(2*sizeof(key)); + enc64(secrets, 2*sizeof(key), key, sizeof(key)); + + /* set up encryption */ + procsetname("pushtls"); + getfields(ealgs, ealg, 2, 0, " "); + return pushtls(fd, ealg[1], ealg[0], 1, secrets, nil); +} + +/* + * plan9 authentication followed by rc4 encryption + */ +static int +p9auth(int fd) +{ + procsetname("%s: auth_proxy proto=%q role=client %s", + origargs, p9authproto, keyspec); + ai = auth_proxy(fd, auth_getkey, "proto=%q role=client %s", p9authproto, keyspec); + if(ai == nil) + return -1; + + if(ealgs == nil || encproto == Encnone) + return fd; + + switch (encproto) { + case Encssl: + fd = encssl(fd); + break; + case Enctls: + fd = enctls(fd); + break; + default: + sysfatal("Unsupported encryption protocol\n"); + } + + if(fd < 0) werrstr("can't establish ssl connection: %r"); - return i; + return fd; } static int @@ -648,26 +729,16 @@ } static int -srvp9auth(int fd, char *user) +srvencssl(int fd) { uchar key[16]; uchar digest[SHA1dlen]; char fromclientsecret[21]; char fromserversecret[21]; int i; - AuthInfo *ai; - ai = auth_proxy(0, nil, "proto=%q role=server %s", p9authproto, keyspec); - if(ai == nil) - return -1; - if(auth_chuid(ai, nil) < 0) - return -1; - strecpy(user, user+MaxStr, ai->cuid); memmove(key+4, ai->secret, ai->nsecret); - if(ealgs == nil) - return fd; - /* exchange random numbers */ srand(truerand()); for(i = 0; i < 4; i++) @@ -683,10 +754,64 @@ mksecret(fromserversecret, digest+10); /* set up encryption */ - i = pushssl(fd, ealgs, fromserversecret, fromclientsecret, nil); - if(i < 0) + return pushssl(fd, ealgs, fromserversecret, fromclientsecret, nil); +} + +static int +srvenctls(int fd) +{ + uchar key[MaxKeyData]; + uchar crandom[RandomSize]; + uchar srandom[RandomSize]; + char *label, *secrets; + int i; + + /* exchange random numbers */ + for(i = 0; i < RandomSize; i++) + srandom[i] = fastrand(); + if(readn(fd, srandom, RandomSize) != RandomSize) + return -1; + if(write(fd, crandom, RandomSize) != RandomSize) + return -1; + + /* scramble into secrets */ + label = "master secret"; + tls12PRF(key, MaxKeyData, ai->secret, ai->nsecret, label, crandom, RandomSize, srandom, RandomSize); + secrets = malloc(2*sizeof(key)); + enc64(secrets, 2*sizeof(key), key, sizeof(key)); + + /* set up encryption */ + getfields(ealgs, ealg, 2, 0, " "); + return pushtls(fd, ealg[1], ealg[0], 0, secrets, nil); +} + +static int +srvp9auth(int fd, char *user) +{ + ai = auth_proxy(0, nil, "proto=%q role=server %s", p9authproto, keyspec); + if(ai == nil) + return -1; + if(auth_chuid(ai, nil) < 0) + return -1; + strecpy(user, user+MaxStr, ai->cuid); + + if(ealgs == nil || encproto == Encnone) + return fd; + + switch (encproto) { + case Encssl: + fd = srvencssl(fd); + break; + case Enctls: + fd = srvenctls(fd); + break; + default: + sysfatal("Unsupported encryption protocol\n"); + } + + if(fd < 0) werrstr("can't establish ssl connection: %r"); - return i; + return fd; } /* --- /n/sources/plan9/sys/src/cmd/import.c Fri May 9 18:10:31 2008 +++ /sys/src/cmd/import.c Thu Oct 27 00:00:00 2011 @@ -9,6 +9,11 @@ Enctls, }; +enum { + MaxKeyData = 136, + RandomSize = 32, +}; + static char *encprotos[] = { [Encnone] = "clear", [Encssl] = "ssl", @@ -19,6 +24,7 @@ char *keyspec = ""; char *filterp; char *ealgs = "rc4_256 sha1"; +char *ealg[2]; int encproto = Encnone; char *aan = "/bin/aan"; AuthInfo *ai; @@ -88,6 +94,71 @@ return -1; } +static int +encssl(int fd, char *argv) +{ + uchar key[16]; + uchar digest[SHA1dlen]; + char fromclientsecret[21]; + char fromserversecret[21]; + int i; + + memmove(key+4, ai->secret, ai->nsecret); + + /* exchange random numbers */ + srand(truerand()); + for(i = 0; i < 4; i++) + key[i] = rand(); + if(write(fd, key, 4) != 4) + sysfatal("can't write key part: %r"); + if(readn(fd, key+12, 4) != 4) + sysfatal("can't read key part: %r"); + + /* scramble into two secrets */ + sha1(key, sizeof(key), digest, nil); + mksecret(fromclientsecret, digest); + mksecret(fromserversecret, digest+10); + + if (filterp) + fd = filter(fd, filterp, argv); + + /* set up encryption */ + procsetname("pushssl"); + return pushssl(fd, ealgs, fromclientsecret, fromserversecret, nil); +} + +static int +enctls(int fd, char *argv) +{ + uchar key[MaxKeyData]; + uchar crandom[RandomSize]; + uchar srandom[RandomSize]; + char *label, *secrets; + int i; + + /* exchange random numbers */ + for(i = 0; i < RandomSize; i++) + crandom[i] = fastrand(); + if(write(fd, srandom, RandomSize) != RandomSize) + sysfatal("can't write key part: %r"); + if(readn(fd, crandom, RandomSize) != RandomSize) + sysfatal("can't read key part: %r"); + + /* scramble into secrets */ + label = "master secret"; + tls12PRF(key, MaxKeyData, ai->secret, ai->nsecret, label, crandom, RandomSize, srandom, RandomSize); + secrets = malloc(2*sizeof(key)); + enc64(secrets, 2*sizeof(key), key, sizeof(key)); + + if (filterp) + fd = filter(fd, filterp, argv); + + /* set up encryption */ + procsetname("pushtls"); + getfields(ealgs, ealg, 2, 0, " "); + return pushtls(fd, ealg[1], ealg[0], 1, secrets, nil); +} + void main(int argc, char **argv) { @@ -171,9 +242,6 @@ } } - if (encproto == Enctls) - sysfatal("%s: tls has not yet been implemented", argv[0]); - notify(catcher); alarm(60*1000); @@ -187,34 +255,17 @@ encprotos[encproto]); if (encproto != Encnone && ealgs && ai) { - uchar key[16]; - uchar digest[SHA1dlen]; - char fromclientsecret[21]; - char fromserversecret[21]; - int i; - - memmove(key+4, ai->secret, ai->nsecret); - - /* exchange random numbers */ - srand(truerand()); - for(i = 0; i < 4; i++) - key[i] = rand(); - if(write(fd, key, 4) != 4) - sysfatal("can't write key part: %r"); - if(readn(fd, key+12, 4) != 4) - sysfatal("can't read key part: %r"); - - /* scramble into two secrets */ - sha1(key, sizeof(key), digest, nil); - mksecret(fromclientsecret, digest); - mksecret(fromserversecret, digest+10); - - if (filterp) - fd = filter(fd, filterp, argv[0]); - - /* set up encryption */ - procsetname("pushssl"); - fd = pushssl(fd, ealgs, fromclientsecret, fromserversecret, nil); + switch (encproto) { + case Encssl: + fd = encssl(fd, argv[0]); + break; + case Enctls: + fd = enctls(fd, argv[0]); + break; + default: + sysfatal("Unsupported encryption protocol\n"); + } + if(fd < 0) sysfatal("can't establish ssl connection: %r"); } --- /n/sources/plan9/sys/src/cmd/exportfs/exportfs.c Wed Jul 8 19:22:28 2009 +++ /sys/src/cmd/exportfs/exportfs.c Thu Oct 27 00:00:00 2011 @@ -18,6 +18,11 @@ Enctls, }; +enum { + MaxKeyData = 136, + RandomSize = 32, +}; + void (*fcalls[])(Fsrpc*) = { [Tversion] Xversion, @@ -47,7 +52,9 @@ int nonone = 1; char *filterp; char *ealgs = "rc4_256 sha1"; +char *ealg[2]; char *aanfilter = "/bin/aan"; +AuthInfo *ai; int encproto = Encnone; int readonly; @@ -82,6 +89,69 @@ freenetconninfo(nci); } +static void +encssl(void) +{ + uchar key[16]; + uchar digest[SHA1dlen]; + char fromclientsecret[21]; + char fromserversecret[21]; + int i; + + memmove(key+4, ai->secret, ai->nsecret); + + /* exchange random numbers */ + srand(truerand()); + for(i = 0; i < 4; i++) + key[i+12] = rand(); + if(readn(netfd, key, 4) != 4) + fatal("can't read key part; %r\n"); + if(write(netfd, key+12, 4) != 4) + fatal("can't write key part; %r\n"); + + /* scramble into two secrets */ + sha1(key, sizeof(key), digest, nil); + mksecret(fromclientsecret, digest); + mksecret(fromserversecret, digest+10); + + if (filterp) + netfd = filter(netfd, filterp); + + /* set up encryption */ + netfd = pushssl(netfd, ealgs, fromserversecret, fromclientsecret, nil); +} + +static void +enctls(void) +{ + uchar key[MaxKeyData]; + uchar crandom[RandomSize]; + uchar srandom[RandomSize]; + char *label, *secrets; + int i; + + /* exchange random numbers */ + for(i = 0; i < 32; i++) + srandom[i] = fastrand(); + if(readn(netfd, srandom, RandomSize) != RandomSize) + fatal("can't read key part; %r\n"); + if(write(netfd, crandom, RandomSize) != RandomSize) + fatal("can't write key part; %r\n"); + + /* scramble into secrets */ + label = "master secret"; + tls12PRF(key, MaxKeyData, ai->secret, ai->nsecret, label, crandom, RandomSize, srandom, RandomSize); + secrets = malloc(2*sizeof(key)); + enc64(secrets, 2*sizeof(key), key, sizeof(key)); + + if (filterp) + netfd = filter(netfd, filterp); + + /* set up encryption */ + getfields(ealgs, ealg, 2, 0, " "); + netfd = pushtls(netfd, ealg[1], ealg[0], 0, secrets, nil); +} + void main(int argc, char **argv) { @@ -89,7 +159,6 @@ Fsrpc *r; int doauth, n, fd; char *dbfile, *srv, *na, *nsfile, *keyspec; - AuthInfo *ai; ulong initial; dbfile = "/tmp/exportdb"; @@ -322,47 +391,18 @@ encproto = Enctls; else if (strcmp(args[1], "clear") != 0) fatal("import encryption proto unsupported: %s\n", args[1]); - - if (encproto == Enctls) - sysfatal("%s: tls has not yet been implemented", argv[0]); } if (encproto != Encnone && ealgs && ai) { - uchar key[16]; - uchar digest[SHA1dlen]; - char fromclientsecret[21]; - char fromserversecret[21]; - int i; - - memmove(key+4, ai->secret, ai->nsecret); - - /* exchange random numbers */ - srand(truerand()); - for(i = 0; i < 4; i++) - key[i+12] = rand(); - if (initial) fatal("Protocol botch: old import\n"); - if(readn(netfd, key, 4) != 4) - fatal("can't read key part; %r\n"); - - if(write(netfd, key+12, 4) != 4) - fatal("can't write key part; %r\n"); - - /* scramble into two secrets */ - sha1(key, sizeof(key), digest, nil); - mksecret(fromclientsecret, digest); - mksecret(fromserversecret, digest+10); - - if (filterp) - netfd = filter(netfd, filterp); - switch (encproto) { case Encssl: - netfd = pushssl(netfd, ealgs, fromserversecret, - fromclientsecret, nil); + encssl(); break; case Enctls: + enctls(); + break; default: fatal("Unsupported encryption protocol\n"); } --- /n/sources/plan9/sys/man/1/cpu Sun Dec 2 23:42:11 2007 +++ /sys/man/1/cpu Tue Oct 25 00:00:00 2011 @@ -16,6 +16,9 @@ .B -P .I patternfile ] [ +.B -E +.I encryption-protocol +] [ .B -e .I encryption-hash-algs ] [ @@ -123,6 +126,16 @@ the server or if the user wants to log into the server as a different user. .PD +.PP +The +.B -E \fIenc +Push an authentication protocol on its network connection. +The supported protocols are +.B clear , +.BR ssl +(the default), +and +.BR tls . .PP The .B -e --- /n/sources/plan9/sys/man/4/import Sun Dec 2 23:42:23 2007 +++ /sys/man/4/import Tue Oct 25 00:00:00 2011 @@ -75,18 +75,18 @@ Push an authentication protocol on its network connection. The supported protocols are .B clear -(the default, no protocol) +(the default, no protocol), +.B ssl and -.BR ssl . -There are plans to make -.B tls -available. +.BR tls . .TP .B -e '\fIenc auth\fR' Specify the encryption and authentication algorithms to use for encrypting the wire traffic (see -.IR ssl (3)). +.IR ssl (3) +and +.IR tls (3)). The defaults are .B rc4_256 and --- /n/sources/plan9/sys/man/4/exportfs Mon Mar 14 19:37:29 2011 +++ /sys/man/4/exportfs Tue Oct 25 00:00:00 2011 @@ -97,7 +97,8 @@ .B -e '\fIenc auth\fL' Set the encryption and authentication algorithms to use for encrypting the wire traffic (see -.IR ssl (3)). +.IR ssl (3) and +.IR tls (3)). The defaults are .B rc4_256 and --- /n/sources/plan9/sys/include/libsec.h Fri Mar 26 04:12:18 2010 +++ /sys/include/libsec.h Thu Oct 27 00:00:00 2011 @@ -391,6 +391,7 @@ /* tlshand.c */ int tlsClient(int fd, TLSconn *c); int tlsServer(int fd, TLSconn *c); +void tls12PRF(uchar*, int nbuf, uchar*, int, char*, uchar*, int, uchar*, int); /* thumb.c */ Thumbprint* initThumbprints(char *ok, char *crl); --- /n/sources/plan9/sys/src/libsec/port/tlshand.c Fri Jul 29 21:12:14 2011 +++ /sys/src/libsec/port/tlshand.c Thu Oct 27 00:00:00 2011 @@ -1721,6 +1719,35 @@ } } +static void +tlsPsha2_256(uchar *buf, int nbuf, uchar *key, int nkey, uchar *label, int nlabel, uchar *seed0, int nseed0, uchar *seed1, int nseed1) +{ + uchar ai[SHA2_256dlen], tmp[SHA2_256dlen]; + int i, n; + SHAstate *s; + + // generate a1 + s = hmac_sha2_256(label, nlabel, key, nkey, nil, nil); + s = hmac_sha2_256(seed0, nseed0, key, nkey, nil, s); + hmac_sha2_256(seed1, nseed1, key, nkey, ai, s); + + while(nbuf > 0) { + s = hmac_sha2_256(ai, SHA2_256dlen, key, nkey, nil, nil); + s = hmac_sha2_256(label, nlabel, key, nkey, nil, s); + s = hmac_sha2_256(seed0, nseed0, key, nkey, nil, s); + hmac_sha2_256(seed1, nseed1, key, nkey, tmp, s); + n = SHA2_256dlen; + if(n > nbuf) + n = nbuf; + for(i = 0; i < n; i++) + buf[i] ^= tmp[i]; + buf += n; + nbuf -= n; + hmac_sha2_256(ai, SHA2_256dlen, key, nkey, tmp, nil); + memmove(ai, tmp, SHA2_256dlen); + } +} + // fill buf with md5(args)^sha1(args) static void tlsPRF(uchar *buf, int nbuf, uchar *key, int nkey, char *label, uchar *seed0, int nseed0, uchar *seed1, int nseed1) @@ -1733,6 +1760,18 @@ buf[i] = 0; tlsPmd5(buf, nbuf, key, n, (uchar*)label, nlabel, seed0, nseed0, seed1, nseed1); tlsPsha1(buf, nbuf, key+nkey-n, n, (uchar*)label, nlabel, seed0, nseed0, seed1, nseed1); +} + +void +tls12PRF(uchar *buf, int nbuf, uchar *key, int nkey, char *label, uchar *seed0, int nseed0, uchar *seed1, int nseed1) +{ + int i; + int nlabel = strlen(label); + int n = (nkey + 1) >> 1; + + for(i = 0; i < nbuf; i++) + buf[i] = 0; + tlsPsha2_256(buf, nbuf, key, n, (uchar*)label, nlabel, seed0, nseed0, seed1, nseed1); } /*