9front - general discussion about 9front
 help / color / mirror / Atom feed
* [9front] intent to delete: devssl, cpu, oexportfs, import
@ 2021-10-22  1:48 ori
  2021-10-22  1:58 ` sl
  2021-10-22 11:43 ` kemal
  0 siblings, 2 replies; 20+ messages in thread
From: ori @ 2021-10-22  1:48 UTC (permalink / raw)
  To: 9front

SSL 3.0 is implemented by devssl. It has been utterly
broken since the POODLE attacks came out in 2014. It's
not used anywhere except for cpu(1), oexportfs(4), and
import(4).

Since these programs hard code devssl, there's no way to
compatibly upgrade -- which is why rcpu and rimport exist.

I'd like to remove it.

This change strips out the devssl bits, but does not (yet)
remove the code from libsec; that's going to require a bit
more staring at specs.

diff 24bd67f990fde5f25783293f57f651c93ce19125 uncommitted
--- a/sys/include/libc.h
+++ b/sys/include/libc.h
@@ -536,7 +536,6 @@
 /*
  *  encryption
  */
-extern	int	pushssl(int, char*, char*, char*, int*);
 extern	int	pushtls(int, char*, char*, int, char*, char*);
 
 /*
--- a/sys/man/1/cpu
+++ /tmp/diff100001879037
@@ -1,237 +1,0 @@
-.TH CPU 1
-.SH NAME
-cpu \- connection to CPU server
-.SH SYNOPSIS
-.B cpu
-[
-.B -p
-] [
-.B -h
-.I server
-] [
-.B -u
-.I user
-] [
-.B -a
-.I auth-method
-] [
-.B -P
-.I patternfile
-] [
-.B -e
-.I encryption-hash-algs
-] [
-.B -k
-.I keypattern
-] [
-.B -c
-.I cmd args ...
-]
-.PP
-.B cpu
-[
-.B -n
-] [
-.B -A
-.I address
-] [
-.B -R
-]
-.SH DESCRIPTION
-This tool is deprecated and has been replaced by
-.IR rcpu (1).
-.PP
-.I Cpu
-starts an
-.IR rc (1)
-running on the
-.I server
-machine, or the machine named in the
-.B $cpu
-environment variable if there is no
-.B -h
-option.
-.IR Rc 's
-standard input, output, and error files will be
-.B /dev/cons
-in the name space where the
-.I cpu
-command was invoked.
-Normally,
-.I cpu
-is run in an
-.IR rio (1)
-window on a terminal, so
-.IR rc
-output goes to that window, and input comes from the keyboard
-when that window is current.
-.IR Rc 's
-current directory is
-the working directory of the
-.I cpu
-command itself.
-.PP
-The name space for the new
-.I rc
-is an analogue of the name space where the
-.I cpu
-command was invoked:
-it is the same except for architecture-dependent bindings such as
-.B /bin
-and the use of fast paths to file servers, if available.
-.PP
-If a
-.B -u
-argument is present,
-.I cpu
-uses the argument as the remote user id.
-.PP
-If a
-.B -c
-argument is present, the remainder of the command line is executed by
-.I rc
-on the server, and then
-.I cpu
-exits.
-.PP
-If a
-.B -P
-argument is present, the
-.I patternfile
-is passed to
-.IR oexportfs (4)
-to control how much of the local name space will be exported to
-the remote system.
-.PP
-The
-.B -a
-command allows the user to specify the authentication mechanism used
-when connecting to the remote system.  The two possibilities for
-.I auth-method
-are:
-.TF netkey
-.TP
-.B p9
-This is the default.  Authentication is done using the standard Plan 9
-mechanisms, (see
-.IR authsrv (6)).
-No user interaction is required.
-.TP
-.B netkey
-Authentication is done using challenge/response and a hand held
-authenticator or the
-.I netkey
-program
-(see
-.IR passwd (1)).
-The user must encrypt the challenge and type the encryption
-back to
-.IR cpu .
-This is used if the local host is in a different protection domain than
-the server or if the user wants to log into the server as a different
-user.
-.TP
-.B none
-This skips authentication. This requires the
-.IR -n
-flag to be specified on the remote side.
-.PD
-.PP
-The
-.B -e
-option specifies an encryption and/or hash algorithm to
-use for the connection.  If both are specified, they must
-be space separated and comprise a single argument, so they
-must be quoted if in a shell command.  The default is
-.L rc4_256
-encryption and
-.L sha1
-hashing.  See
-.IR ssl (3)
-for details on possible algorithms.  The argument
-.L clear
-specifies no encryption algorithm and can be used to talk
-to older versions of the
-.I cpu
-service.
-.PP
-The
-.B -k
-flag specifies a key pattern to use to restrict the keys
-selected by the
-.I auth_proxy
-call used for authentication.
-.PP
-The name space is built by running
-.B /usr/$user/lib/profile
-with the root of the invoking name space bound to
-.BR /mnt/term .
-The
-.B service
-environment variable is set to
-.BR cpu ;
-the
-.B cputype
-and
-.B objtype
-environment variables reflect the server's architecture.
-.PP
-The
-.B -R
-flag causes
-.I cpu
-to run the server (remote) side of the protocol.
-It is run from service files such as
-.BR /bin/service/tcp17010 .
-The
-.B -n
-option allows using the
-.B none
-authentication method for incoming connections and must be
-specified before the
-.B -R
-flag.
-.PP
-The
-.B -p
-flag pushes the
-.IR aan (8)
-filter onto the connection to protect against temporary
-network outages.
-.PP
-The
-.B -A
-flag sets the announce-string
-.I address
-to use for
-.IR aan (8)
-connections, if requested by the initial protocol.
-.SH FILES
-The name space of the terminal side of the
-.I cpu
-command is mounted, via
-.IR oexportfs (4),
-on the CPU side on directory
-.BR /mnt/term .
-The files such as
-.B /dev/cons
-are bound to their standard locations from there.
-.SH SOURCE
-.B /sys/src/cmd/cpu.c
-.SH SEE ALSO
-.IR rcpu (1) ,
-.IR rc (1) ,
-.IR rio (1) ,
-.IR oexportfs (4) ,
-.IR aan (8)
-.SH BUGS
-Binds and mounts done after the terminal
-.B lib/profile
-is run are not reflected in the new name space.
-.PP
-By default, the entire namespace of the local system is
-exported to the remote system. Use of the
-.B -P
-option in conjunction with a customized patternfile can
-limit this exposure, but also limits the usefulness of
-.B /mnt/term.
--- a/sys/man/4/import
+++ /tmp/diff100001879040
@@ -1,221 +1,0 @@
-.TH IMPORT 4
-.SH NAME
-import \- import a name space from a remote system
-.SH SYNOPSIS
-.B import
-[
-.I options
-]
-.I system
-.I file
-[
-.I mountpoint
-]
-.PP
-.B import
-.B -B
-[
-.I options
-]
-.I mountpoint
-[
-.I cmd
-[
-.I args ...
-]
-]
-.SH DESCRIPTION
-This tool is deprecated and has been replaced by
-.I rimport
-(see
-.IR rcpu (1)).
-.PP
-.I Import
-allows an arbitrary
-.I file
-on a remote
-.I system
-to be imported into the local name space.
-Usually
-.I file
-is a directory, so the complete
-file tree under the directory is made available.
-.PP
-A process is started on the
-remote machine, with authority of the user of
-.IR import ,
-to perform work for the local machine using the
-.IR oexportfs (4)
-service.
-The default port used is TCP 17007.
-If
-.I mountpoint
-is omitted
-.I import
-uses the name of the remote
-.I file
-as the local mount point.
-.PP
-The options are:
-.TF "-s namexxx"
-.PD
-.TP
-.B -a -b -c -C
-Control the construction of union directories, as in
-.I mount
-and
-.IR bind (1).
-Only valid when 
-.I file
-is a directory.
-.TP
-.B -A
-Skip the authentication protocol.
-This is useful for connecting to foreign systems like Inferno.
-.TP
-.B -z
-Bypass the initial protocol request for which remote tree to serve.
-This is necessary when the remote 
-.IR oexportfs (4) 
-is running with the 
-.B -r 
-or 
-.B -S 
-options which pre-select a file tree to serve. The exception is if both sides are
-operating in the
-.B -B
-backwards mode.
-.TP
-.B -B
-Run in ``backwards'' mode, described below.
-.TP
-.B -E \fIenc
-Push an encryption protocol on its network connection.
-The supported protocols are
-.B clear
-(the default, no protocol)
-and
-.BR ssl .
-There are plans to make
-.B tls
-available.
-.TP
-.B -e '\fIenc hash\fR'
-Specify the encryption and hash algorithms to use for
-encrypting and authenticating the wire traffic
-(see
-.IR ssl (3)).
-The defaults are
-.B rc4_256
-and
-.BR sha1 .
-.TP
-.B -k \fIkeypattern
-Use
-.I keypattern
-to select a key to authenticate to the remote side
-(see
-.IR auth (2)).
-.TP
-.B -p
-Push the
-.IR aan (8)
-filter onto the connection to protect against
-temporary network outages.
-.TP
-.B -n
-Specify announce string for
-.IR aan (8)
-filter when run in ``backwards'' mode.
-.TP
-.B -s \fIname
-Post the connection's mountable file descriptor as
-.BI /srv/ name\fR.
-.PD
-.PP
-The 
-.B -B
-option runs
-.I import
-in ``backwards'' mode.
-In this mode,
-.I import
-runs a
-.I p9any
-authentication (as server) over its file descriptor 0
-(expected to be an incoming network connection from
-.B oexportfs
-.BR -B ),
-mounts the connection onto
-.IR mntpt ,
-and optionally runs
-.I cmd
-.IR args .
-.SH EXAMPLES
-Assume a machine
-.B kremvax
-that has IP interfaces for the company intranet and the global
-internet mounted on
-.I /net
-and
-.I /net.alt
-respectively.
-Any machine inside the company can get telnet out to the global
-internet using:
-.IP
-.EX
-import -a kremvax /net.alt
-telnet /net.alt/tcp!ucbvax
-.EE
-.PP
-Suppose that the machine
-.B moscvax
-has access to a private file server containing public web pages
-that need to be served by the less-trusted server
-.BR webvax .
-.B Webvax
-runs the following listener 
-(see
-.IR listen (8))
-on TCP port 999:
-.IP
-.EX
-#!/bin/rc
-import -B -s rowebfs /usr/web /bin/restarthttpd
-.EE
-.PP
-When
-.B moscvax
-boots, it runs
-.IP
-.EX
-oexportfs -R -r /usr/web -B tcp!webvax!999
-.EE
-.PP
-to serve a read-only copy of
-.B /usr/web
-to
-.BR webvax .
-When
-.B webvax
-gets the call, 
-.B import
-mounts the served tree onto its own
-.B /usr/web
-and then runs
-.B /bin/restarthttpd
-to restart
-.IR httpd (8).
-.SH SOURCE
-.B /sys/src/cmd/import.c
-.SH SEE ALSO
-.IR rcpu (1),
-.IR bind (1),
-.IR ssl (3),
-.IR oexportfs (4),
-.IR srv (4),
-.IR aan (8),
-.IR listen (8),
-.B cs
-in
-.IR ndb (8)
--- a/sys/man/4/oexportfs
+++ /tmp/diff100001879043
@@ -1,143 +1,0 @@
-.TH OEXPORTFS 4
-.SH NAME
-oexportfs \- legacy exportfs for cpu and import
-.SH SYNOPSIS
-.PP
-.B oexportfs
-[
-.I options
-]
-.SH DESCRIPTION
-.I Oexportfs
-is older version of the
-.IR exportfs (4)
-program that handles an initial protocol to establish a root directory
-for the exported name space.
-It also provides authentication and encryption using
-the
-.IR ssl (3)
-device.
-.PP
-It is used exclusively by the deprecated
-.IR cpu (1)
-and
-.IR import (4)
-services.
-.PP
-The options are:
-.TP
-.B -d
-Log all 9P traffic to standard error.
-.TP
-.B -P \fIpatternfile
-Restrict the set of exported files.
-.I Patternfile
-contains one regular expression per line,
-to be matched against path names
-relative to the current working directory
-and starting with
-.BR / .
-For a file to be exported, all lines with a prefix
-.B +
-must match and all those with prefix
-.B -
-must not match.
-.TP
-.B -R
-Make the served name space read only.
-.TP
-.B -r \fIroot
-Serve the name space rooted at
-.IR root .
-.TP
-.B -S \fIservice
-Serve the result of mounting
-.IR service .
-A separate mount is used for each
-.IR attach (5)
-message,
-to correctly handle servers in which each mount
-corresponds to a different client
-.IR e.g. , (
-.IR rio (4)).
-.TP
-.B -s
-equivalent to
-.B -r
-.BR / ;
-kept for compatibility.
-.TP
-.B -m \fImsize
-Set the maximum message size that 
-.I oexportfs
-should offer to send (see
-.IR version (5));
-this helps tunneled
-9P connections to avoid unnecessary fragmentation.
-.TP
-.B -A \fIaddress
-Use the network
-.I address
-to announce
-.IR aan (8)
-connections,
-if requested by the initial protocol.
-.TP
-.B -a
-Authenticate the user with the
-.I p9any
-protocol before running the regular
-.I oexportfs
-session; used when 
-.I oexportfs
-is invoked to handle an incoming network connection.
-.I Exportfs
-creates a new name space for each connection, using
-.B /lib/namespace
-by default (see
-.IR namespace (6)).
-.TP
-.B -B \fIaddress
-Dial
-.IR address ,
-authenticate as a
-.I p9any
-client, and then
-serve that network connection.
-Requires setting the root of the name space with 
-.B -r
-or
-.BR -s .
-The remote system should run
-.B import
-.B -B
-to handle the call.
-See
-.IR import (4)
-for an example.
-.TP
-.B -e '\fIenc auth\fL'
-Set the encryption and authentication algorithms to use for
-encrypting the wire traffic (see
-.IR ssl (3)).
-The defaults are
-.B rc4_256
-and
-.BR sha1 .
-.TP
-.B -N \fInsfile
-Serve the name space described by
-.IR nsfile .
-.TP
-.B -n
-Disallow mounts by user
-.BR none .
-.EE
-.SH SOURCE
-.B /sys/src/cmd/exportfs/oexportfs.c
-.SH SEE ALSO
-.IR dial (2),
-.IR exportfs (4),
-.IR import (4),
-.IR aan (8),
-.IR listen (8)
--- a/sys/src/9/bcm/pi
+++ b/sys/src/9/bcm/pi
@@ -10,7 +10,6 @@
 	shr
 	dup
 	arch
-	ssl
 	tls
 	cap
 	fs
--- a/sys/src/9/bcm/pi2
+++ b/sys/src/9/bcm/pi2
@@ -10,7 +10,6 @@
 	shr
 	dup
 	arch
-	ssl
 	tls
 	cap
 	fs
--- a/sys/src/9/bcm/picpuf
+++ b/sys/src/9/bcm/picpuf
@@ -10,7 +10,6 @@
 	shr
 	dup
 	arch
-	ssl
 	tls
 	cap
 	fs
--- a/sys/src/9/bcm64/pi3
+++ b/sys/src/9/bcm64/pi3
@@ -10,7 +10,6 @@
 	shr
 	dup
 	arch
-	ssl
 	tls
 	cap
 	fs
--- a/sys/src/9/bcm64/pi4
+++ b/sys/src/9/bcm64/pi4
@@ -10,7 +10,6 @@
 	shr
 	dup
 	arch
-	ssl
 	tls
 	cap
 	fs
--- a/sys/src/9/cycv/cycv
+++ b/sys/src/9/cycv/cycv
@@ -13,7 +13,6 @@
 	dup
 	ether netif
 	ip		arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno
-	ssl
 	tls
 #	cap
 #	kprof
--- a/sys/src/9/kw/plug
+++ b/sys/src/9/kw/plug
@@ -13,7 +13,6 @@
 	dup
 	rtc
 	arch
-	ssl
 	tls
 	cap
 	kprof
--- a/sys/src/9/mtx/mtx
+++ b/sys/src/9/mtx/mtx
@@ -10,7 +10,6 @@
 	mnt
 	srv
 	dup
-	ssl
 	cap
 	kprof
 	uart
--- a/sys/src/9/omap/beagle
+++ b/sys/src/9/omap/beagle
@@ -11,7 +11,6 @@
 	shr
 	dup
 	arch
-	ssl
 	tls
 	bridge		log
 	sdp		thwack unthwack
--- a/sys/src/9/pc/pc
+++ b/sys/src/9/pc/pc
@@ -13,7 +13,6 @@
 	shr
 	dup
 	rtc
-	ssl
 	tls
 	cap
 	kprof
--- a/sys/src/9/pc64/pc64
+++ b/sys/src/9/pc64/pc64
@@ -13,7 +13,6 @@
 	shr
 	dup
 	rtc
-	ssl
 	tls
 	cap
 	kprof
--- a/sys/src/9/port/devssl.c
+++ /tmp/diff100001879079
@@ -1,1462 +1,0 @@
-/*
- *  devssl - secure sockets layer
- */
-#include	"u.h"
-#include	"../port/lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"../port/error.h"
-
-#include	<libsec.h>
-
-#define NOSPOOKS 1
-
-typedef struct OneWay OneWay;
-struct OneWay
-{
-	QLock	q;
-	QLock	ctlq;
-
-	void	*state;		/* encryption state */
-	int	slen;		/* hash data length */
-	uchar	*secret;	/* secret */
-	ulong	mid;		/* message id */
-};
-
-enum
-{
-	/* connection states */
-	Sincomplete=	0,
-	Sclear=		1,
-	Sencrypting=	2,
-	Sdigesting=	4,
-	Sdigenc=	Sencrypting|Sdigesting,
-
-	/* encryption algorithms */
-	Noencryption=	0,
-	DESCBC=		1,
-	DESECB=		2,
-	RC4=		3
-};
-
-typedef struct Dstate Dstate;
-struct Dstate
-{
-	Chan	*c;		/* io channel */
-	uchar	state;		/* state of connection */
-	int	ref;		/* serialized by dslock for atomic destroy */
-
-	uchar	encryptalg;	/* encryption algorithm */
-	ushort	blocklen;	/* blocking length */
-
-	ushort	diglen;		/* length of digest */
-	DigestState *(*hf)(uchar*, ulong, uchar*, DigestState*);	/* hash func */
-
-	/* for SSL format */
-	int	max;		/* maximum unpadded data per msg */
-	int	maxpad;		/* maximum padded data per msg */
-
-	/* input side */
-	OneWay	in;
-	Block	*processed;
-	Block	*unprocessed;
-
-	/* output side */
-	OneWay	out;
-
-	/* protections */
-	char	*user;
-	int	perm;
-};
-
-enum
-{
-	Maxdmsg=	1<<16,
-	Maxdstate=	512,	/* max. open ssl conn's; must be a power of 2 */
-};
-
-static	Lock	dslock;
-static	int	dshiwat;
-static	char	*dsname[Maxdstate];
-static	Dstate	*dstate[Maxdstate];
-static	char	*encalgs;
-static	char	*hashalgs;
-
-enum{
-	Qtopdir		= 1,	/* top level directory */
-	Qprotodir,
-	Qclonus,
-	Qconvdir,		/* directory for a conversation */
-	Qdata,
-	Qctl,
-	Qsecretin,
-	Qsecretout,
-	Qencalgs,
-	Qhashalgs,
-};
-
-#define TYPE(x) 	((x).path & 0xf)
-#define CONV(x) 	(((x).path >> 5)&(Maxdstate-1))
-#define QID(c, y) 	(((c)<<5) | (y))
-
-static void	ensure(Dstate*, Block**, int);
-static void	consume(Block**, uchar*, int);
-static void	setsecret(OneWay*, uchar*, int);
-static Block*	encryptb(Dstate*, Block*, int);
-static Block*	decryptb(Dstate*, Block*);
-static Block*	digestb(Dstate*, Block*, int);
-static void	checkdigestb(Dstate*, Block*);
-static Chan*	buftochan(char*);
-static void	sslhangup(Dstate*);
-static Dstate*	dsclone(Chan *c);
-static void	dsnew(Chan *c, Dstate **);
-static long	sslput(Dstate *s, Block * volatile b);
-
-char *sslnames[] = {
-[Qclonus]	"clone",
-[Qdata]		"data",
-[Qctl]		"ctl",
-[Qsecretin]	"secretin",
-[Qsecretout]	"secretout",
-[Qencalgs]	"encalgs",
-[Qhashalgs]	"hashalgs",
-};
-
-static int
-sslgen(Chan *c, char*, Dirtab *d, int nd, int s, Dir *dp)
-{
-	Qid q;
-	Dstate *ds;
-	char name[16], *p, *nm;
-	int ft;
-
-	USED(nd);
-	USED(d);
-
-	q.type = QTFILE;
-	q.vers = 0;
-
-	ft = TYPE(c->qid);
-	switch(ft) {
-	case Qtopdir:
-		if(s == DEVDOTDOT){
-			q.path = QID(0, Qtopdir);
-			q.type = QTDIR;
-			devdir(c, q, "#D", 0, eve, 0555, dp);
-			return 1;
-		}
-		if(s > 0)
-			return -1;
-		q.path = QID(0, Qprotodir);
-		q.type = QTDIR;
-		devdir(c, q, "ssl", 0, eve, 0555, dp);
-		return 1;
-	case Qprotodir:
-		if(s == DEVDOTDOT){
-			q.path = QID(0, Qtopdir);
-			q.type = QTDIR;
-			devdir(c, q, ".", 0, eve, 0555, dp);
-			return 1;
-		}
-		if(s < dshiwat) {
-			q.path = QID(s, Qconvdir);
-			q.type = QTDIR;
-			ds = dstate[s];
-			if(ds != 0)
-				nm = ds->user;
-			else
-				nm = eve;
-			if(dsname[s] == nil){
-				sprint(name, "%d", s);
-				kstrdup(&dsname[s], name);
-			}
-			devdir(c, q, dsname[s], 0, nm, 0555, dp);
-			return 1;
-		}
-		if(s > dshiwat)
-			return -1;
-		q.path = QID(0, Qclonus);
-		devdir(c, q, "clone", 0, eve, 0555, dp);
-		return 1;
-	case Qconvdir:
-		if(s == DEVDOTDOT){
-			q.path = QID(0, Qprotodir);
-			q.type = QTDIR;
-			devdir(c, q, "ssl", 0, eve, 0555, dp);
-			return 1;
-		}
-		ds = dstate[CONV(c->qid)];
-		if(ds != 0)
-			nm = ds->user;
-		else
-			nm = eve;
-		switch(s) {
-		default:
-			return -1;
-		case 0:
-			q.path = QID(CONV(c->qid), Qctl);
-			p = "ctl";
-			break;
-		case 1:
-			q.path = QID(CONV(c->qid), Qdata);
-			p = "data";
-			break;
-		case 2:
-			q.path = QID(CONV(c->qid), Qsecretin);
-			p = "secretin";
-			break;
-		case 3:
-			q.path = QID(CONV(c->qid), Qsecretout);
-			p = "secretout";
-			break;
-		case 4:
-			q.path = QID(CONV(c->qid), Qencalgs);
-			p = "encalgs";
-			break;
-		case 5:
-			q.path = QID(CONV(c->qid), Qhashalgs);
-			p = "hashalgs";
-			break;
-		}
-		devdir(c, q, p, 0, nm, 0660, dp);
-		return 1;
-	case Qclonus:
-		devdir(c, c->qid, sslnames[TYPE(c->qid)], 0, eve, 0555, dp);
-		return 1;
-	default:
-		ds = dstate[CONV(c->qid)];
-		if(ds != 0)
-			nm = ds->user;
-		else
-			nm = eve;
-		devdir(c, c->qid, sslnames[TYPE(c->qid)], 0, nm, 0660, dp);
-		return 1;
-	}
-}
-
-static Chan*
-sslattach(char *spec)
-{
-	Chan *c;
-
-	c = devattach('D', spec);
-	c->qid.path = QID(0, Qtopdir);
-	c->qid.vers = 0;
-	c->qid.type = QTDIR;
-	return c;
-}
-
-static Walkqid*
-sslwalk(Chan *c, Chan *nc, char **name, int nname)
-{
-	return devwalk(c, nc, name, nname, nil, 0, sslgen);
-}
-
-static int
-sslstat(Chan *c, uchar *db, int n)
-{
-	return devstat(c, db, n, nil, 0, sslgen);
-}
-
-static Chan*
-sslopen(Chan *c, int omode)
-{
-	Dstate *s, **pp;
-	int ft;
-
-	ft = TYPE(c->qid);
-	switch(ft) {
-	default:
-		panic("sslopen");
-	case Qtopdir:
-	case Qprotodir:
-	case Qconvdir:
-		if(omode != OREAD)
-			error(Eperm);
-		break;
-	case Qclonus:
-		s = dsclone(c);
-		if(s == 0)
-			error(Enodev);
-		break;
-	case Qctl:
-	case Qdata:
-	case Qsecretin:
-	case Qsecretout:
-		if(waserror()) {
-			unlock(&dslock);
-			nexterror();
-		}
-		lock(&dslock);
-		pp = &dstate[CONV(c->qid)];
-		s = *pp;
-		if(s == 0)
-			dsnew(c, pp);
-		else {
-			devpermcheck(s->user, s->perm, omode);
-			s->ref++;
-		}
-		unlock(&dslock);
-		poperror();
-		break;
-	case Qencalgs:
-	case Qhashalgs:
-		if(omode != OREAD)
-			error(Eperm);
-		break;
-	}
-	c->mode = openmode(omode);
-	c->flag |= COPEN;
-	c->offset = 0;
-	return c;
-}
-
-static int
-sslwstat(Chan *c, uchar *db, int n)
-{
-	Dir *dir;
-	Dstate *s;
-	int m;
-
-	s = dstate[CONV(c->qid)];
-	if(s == 0)
-		error(Ebadusefd);
-	if(strcmp(s->user, up->user) != 0)
-		error(Eperm);
-
-	dir = smalloc(sizeof(Dir)+n);
-	m = convM2D(db, n, &dir[0], (char*)&dir[1]);
-	if(m == 0){
-		free(dir);
-		error(Eshortstat);
-	}
-
-	if(!emptystr(dir->uid))
-		kstrdup(&s->user, dir->uid);
-	if(dir->mode != -1)
-		s->perm = dir->mode;
-
-	free(dir);
-	return m;
-}
-
-static void
-sslclose(Chan *c)
-{
-	Dstate *s;
-	int ft;
-
-	ft = TYPE(c->qid);
-	switch(ft) {
-	case Qctl:
-	case Qdata:
-	case Qsecretin:
-	case Qsecretout:
-		if((c->flag & COPEN) == 0)
-			break;
-
-		s = dstate[CONV(c->qid)];
-		if(s == 0)
-			break;
-
-		lock(&dslock);
-		if(--s->ref > 0) {
-			unlock(&dslock);
-			break;
-		}
-		dstate[CONV(c->qid)] = 0;
-		unlock(&dslock);
-
-		if(s->user != nil)
-			free(s->user);
-		sslhangup(s);
-		if(s->c)
-			cclose(s->c);
-		secfree(s->in.secret);
-		secfree(s->out.secret);
-		secfree(s->in.state);
-		secfree(s->out.state);
-		free(s);
-
-	}
-}
-
-/*
- *  make sure we have at least 'n' bytes in list 'l'
- */
-static void
-ensure(Dstate *s, Block **l, int n)
-{
-	int sofar, i;
-	Block *b, *bl;
-
-	sofar = 0;
-	for(b = *l; b; b = b->next){
-		sofar += BLEN(b);
-		if(sofar >= n)
-			return;
-		l = &b->next;
-	}
-
-	while(sofar < n){
-		bl = devtab[s->c->type]->bread(s->c, Maxdmsg, 0);
-		if(bl == 0)
-			nexterror();
-		*l = bl;
-		i = 0;
-		for(b = bl; b; b = b->next){
-			i += BLEN(b);
-			l = &b->next;
-		}
-		if(i == 0)
-			error(Ehungup);
-		sofar += i;
-	}
-}
-
-/*
- *  copy 'n' bytes from 'l' into 'p' and free
- *  the bytes in 'l'
- */
-static void
-consume(Block **l, uchar *p, int n)
-{
-	Block *b;
-	int i;
-
-	for(; *l && n > 0; n -= i){
-		b = *l;
-		i = BLEN(b);
-		if(i > n)
-			i = n;
-		memmove(p, b->rp, i);
-		b->rp += i;
-		p += i;
-		if(BLEN(b) < 0)
-			panic("consume");
-		if(BLEN(b))
-			break;
-		*l = b->next;
-		freeb(b);
-	}
-}
-
-/*
- *  give back n bytes
-static void
-regurgitate(Dstate *s, uchar *p, int n)
-{
-	Block *b;
-
-	if(n <= 0)
-		return;
-	b = s->unprocessed;
-	if(s->unprocessed == nil || b->rp - b->base < n) {
-		b = allocb(n);
-		memmove(b->wp, p, n);
-		b->wp += n;
-		b->next = s->unprocessed;
-		s->unprocessed = b;
-	} else {
-		b->rp -= n;
-		memmove(b->rp, p, n);
-	}
-}
- */
-
-/*
- *  remove at most n bytes from the queue, if discard is set
- *  dump the remainder
- */
-static Block*
-qtake(Block **l, int n, int discard)
-{
-	Block *nb, *b, *first;
-	int i;
-
-	first = *l;
-	for(b = first; b; b = b->next){
-		i = BLEN(b);
-		if(i == n){
-			if(discard){
-				freeblist(b->next);
-				*l = 0;
-			} else
-				*l = b->next;
-			b->next = 0;
-			return first;
-		} else if(i > n){
-			i -= n;
-			if(discard){
-				freeblist(b->next);
-				b->wp -= i;
-				*l = 0;
-			} else {
-				nb = allocb(i);
-				memmove(nb->wp, b->rp+n, i);
-				nb->wp += i;
-				b->wp -= i;
-				nb->next = b->next;
-				*l = nb;
-			}
-			b->next = 0;
-			if(BLEN(b) < 0)
-				panic("qtake");
-			return first;
-		} else
-			n -= i;
-		if(BLEN(b) < 0)
-			panic("qtake");
-	}
-	*l = 0;
-	return first;
-}
-
-/*
- *  We can't let Eintr's lose data since the program
- *  doing the read may be able to handle it.  The only
- *  places Eintr is possible is during the read's in consume.
- *  Therefore, we make sure we can always put back the bytes
- *  consumed before the last ensure.
- */
-static Block*
-sslbread(Chan *c, long n, ulong)
-{
-	Dstate * volatile s;
-	Block *b;
-	uchar consumed[3], *p;
-	int toconsume;
-	int len, pad;
-
-	s = dstate[CONV(c->qid)];
-	if(s == 0)
-		panic("sslbread");
-	if(s->state == Sincomplete)
-		error(Ebadusefd);
-
-	qlock(&s->in.q);
-	if(waserror()){
-		qunlock(&s->in.q);
-		nexterror();
-	}
-
-	if(s->processed == 0){
-		/*
-		 * Read in the whole message.  Until we've got it all,
-		 * it stays on s->unprocessed, so that if we get Eintr,
-		 * we'll pick up where we left off.
-		 */
-		ensure(s, &s->unprocessed, 3);
-		s->unprocessed = pullupblock(s->unprocessed, 2);
-		p = s->unprocessed->rp;
-		if(p[0] & 0x80){
-			len = ((p[0] & 0x7f)<<8) | p[1];
-			ensure(s, &s->unprocessed, len);
-			pad = 0;
-			toconsume = 2;
-		} else {
-			s->unprocessed = pullupblock(s->unprocessed, 3);
-			len = ((p[0] & 0x3f)<<8) | p[1];
-			pad = p[2];
-			if(pad > len){
-				print("pad %d buf len %d\n", pad, len);
-				error("bad pad in ssl message");
-			}
-			toconsume = 3;
-		}
-		ensure(s, &s->unprocessed, toconsume+len);
-
-		/* skip header */
-		consume(&s->unprocessed, consumed, toconsume);
-
-		/* grab the next message and decode/decrypt it */
-		b = qtake(&s->unprocessed, len, 0);
-
-		if(blocklen(b) != len)
-			print("devssl: sslbread got wrong count %d != %d", blocklen(b), len);
-
-		if(waserror()){
-			qunlock(&s->in.ctlq);
-			if(b != nil)
-				freeb(b);
-			nexterror();
-		}
-		qlock(&s->in.ctlq);
-		switch(s->state){
-		case Sencrypting:
-			if(b == nil)
-				error("ssl message too short (encrypting)");
-			b = decryptb(s, b);
-			break;
-		case Sdigesting:
-			b = pullupblock(b, s->diglen);
-			if(b == nil)
-				error("ssl message too short (digesting)");
-			checkdigestb(s, b);
-			pullblock(&b, s->diglen);
-			len -= s->diglen;
-			break;
-		case Sdigenc:
-			b = decryptb(s, b);
-			b = pullupblock(b, s->diglen);
-			if(b == nil)
-				error("ssl message too short (dig+enc)");
-			checkdigestb(s, b);
-			pullblock(&b, s->diglen);
-			len -= s->diglen;
-			break;
-		}
-
-		/* remove pad */
-		if(pad)
-			s->processed = qtake(&b, len - pad, 1);
-		else
-			s->processed = b;
-		b = nil;
-		s->in.mid++;
-		qunlock(&s->in.ctlq);
-		poperror();
-	}
-
-	/* return at most what was asked for */
-	b = qtake(&s->processed, n, 0);
-
-	qunlock(&s->in.q);
-	poperror();
-
-	return b;
-}
-
-static long
-sslread(Chan *c, void *a, long n, vlong off)
-{
-	Block * volatile b;
-	Block *nb;
-	uchar *va;
-	int i;
-	char buf[128];
-	ulong offset = off;
-	int ft;
-
-	if(c->qid.type & QTDIR)
-		return devdirread(c, a, n, 0, 0, sslgen);
-
-	ft = TYPE(c->qid);
-	switch(ft) {
-	default:
-		error(Ebadusefd);
-	case Qctl:
-		ft = CONV(c->qid);
-		sprint(buf, "%d", ft);
-		return readstr(offset, a, n, buf);
-	case Qdata:
-		b = sslbread(c, n, offset);
-		break;
-	case Qencalgs:
-		return readstr(offset, a, n, encalgs);
-		break;
-	case Qhashalgs:
-		return readstr(offset, a, n, hashalgs);
-		break;
-	}
-
-	if(waserror()){
-		freeblist(b);
-		nexterror();
-	}
-
-	n = 0;
-	va = a;
-	for(nb = b; nb; nb = nb->next){
-		i = BLEN(nb);
-		memmove(va+n, nb->rp, i);
-		n += i;
-	}
-
-	freeblist(b);
-	poperror();
-
-	return n;
-}
-
-static long
-sslbwrite(Chan *c, Block *b, ulong)
-{
-	Dstate * volatile s;
-	long rv;
-
-	s = dstate[CONV(c->qid)];
-	if(s == nil)
-		panic("sslbwrite");
-
-	if(s->state == Sincomplete){
-		freeb(b);
-		error(Ebadusefd);
-	}
-
-	/* lock so split writes won't interleave */
-	if(waserror()){
-		qunlock(&s->out.q);
-		nexterror();
-	}
-	qlock(&s->out.q);
-
-	rv = sslput(s, b);
-
-	poperror();
-	qunlock(&s->out.q);
-
-	return rv;
-}
-
-/*
- *  use SSL record format, add in count, digest and/or encrypt.
- *  the write is interruptable.  if it is interrupted, we'll
- *  get out of sync with the far side.  not much we can do about
- *  it since we don't know if any bytes have been written.
- */
-static long
-sslput(Dstate *s, Block * volatile b)
-{
-	Block *nb;
-	int h, n, m, pad, rv;
-	uchar *p;
-	int offset;
-
-	if(waserror()){
-		if(b != nil)
-			freeb(b);
-		nexterror();
-	}
-
-	rv = 0;
-	while(b != nil){
-		m = n = BLEN(b);
-		h = s->diglen + 2;
-
-		/* trim to maximum block size */
-		pad = 0;
-		if(m > s->max){
-			m = s->max;
-		} else if(s->blocklen != 1){
-			pad = (m + s->diglen)%s->blocklen;
-			if(pad){
-				if(m > s->maxpad){
-					pad = 0;
-					m = s->maxpad;
-				} else {
-					pad = s->blocklen - pad;
-					h++;
-				}
-			}
-		}
-
-		rv += m;
-		if(m != n){
-			nb = allocb(m + h + pad);
-			memmove(nb->wp + h, b->rp, m);
-			nb->wp += m + h;
-			b->rp += m;
-		} else {
-			/* add header space */
-			nb = padblock(b, h);
-			b = 0;
-		}
-		m += s->diglen;
-
-		/* SSL style count */
-		if(pad){
-			nb = padblock(nb, -pad);
-			prng(nb->wp, pad);
-			nb->wp += pad;
-			m += pad;
-
-			p = nb->rp;
-			p[0] = (m>>8);
-			p[1] = m;
-			p[2] = pad;
-			offset = 3;
-		} else {
-			p = nb->rp;
-			p[0] = (m>>8) | 0x80;
-			p[1] = m;
-			offset = 2;
-		}
-
-		switch(s->state){
-		case Sencrypting:
-			nb = encryptb(s, nb, offset);
-			break;
-		case Sdigesting:
-			nb = digestb(s, nb, offset);
-			break;
-		case Sdigenc:
-			nb = digestb(s, nb, offset);
-			nb = encryptb(s, nb, offset);
-			break;
-		}
-
-		s->out.mid++;
-
-		m = BLEN(nb);
-		devtab[s->c->type]->bwrite(s->c, nb, s->c->offset);
-		s->c->offset += m;
-	}
-
-	poperror();
-	return rv;
-}
-
-static void
-setsecret(OneWay *w, uchar *secret, int n)
-{
-	secfree(w->secret);
-	w->secret = secalloc(n);
-	memmove(w->secret, secret, n);
-	w->slen = n;
-}
-
-static void
-initDESkey(OneWay *w)
-{
-	secfree(w->state);
-	w->state = secalloc(sizeof(DESstate));
-	if(w->slen >= 16)
-		setupDESstate(w->state, w->secret, w->secret+8);
-	else if(w->slen >= 8)
-		setupDESstate(w->state, w->secret, 0);
-	else
-		error("secret too short");
-}
-
-/*
- *  40 bit DES is the same as 56 bit DES.  However,
- *  16 bits of the key are masked to zero.
- */
-static void
-initDESkey_40(OneWay *w)
-{
-	uchar key[8];
-
-	if(w->slen >= 8){
-		memmove(key, w->secret, 8);
-		key[0] &= 0x0f;
-		key[2] &= 0x0f;
-		key[4] &= 0x0f;
-		key[6] &= 0x0f;
-	}
-	initDESkey(w);
-}
-
-static void
-initRC4key(OneWay *w)
-{
-	secfree(w->state);
-	w->state = secalloc(sizeof(RC4state));
-	setupRC4state(w->state, w->secret, w->slen);
-}
-
-/*
- *  40 bit RC4 is the same as n-bit RC4.  However,
- *  we ignore all but the first 40 bits of the key.
- */
-static void
-initRC4key_40(OneWay *w)
-{
-	if(w->slen > 5)
-		w->slen = 5;
-	initRC4key(w);
-}
-
-/*
- *  128 bit RC4 is the same as n-bit RC4.  However,
- *  we ignore all but the first 128 bits of the key.
- */
-static void
-initRC4key_128(OneWay *w)
-{
-	if(w->slen > 16)
-		w->slen = 16;
-	initRC4key(w);
-}
-
-
-typedef struct Hashalg Hashalg;
-struct Hashalg
-{
-	char	*name;
-	int	diglen;
-	DigestState *(*hf)(uchar*, ulong, uchar*, DigestState*);
-};
-
-Hashalg hashtab[] =
-{
-	{ "md4", MD4dlen, md4, },
-	{ "md5", MD5dlen, md5, },
-	{ "sha1", SHA1dlen, sha1, },
-	{ "sha", SHA1dlen, sha1, },
-	{ 0 }
-};
-
-static int
-parsehashalg(char *p, Dstate *s)
-{
-	Hashalg *ha;
-
-	for(ha = hashtab; ha->name; ha++){
-		if(strcmp(p, ha->name) == 0){
-			s->hf = ha->hf;
-			s->diglen = ha->diglen;
-			s->state &= ~Sclear;
-			s->state |= Sdigesting;
-			return 0;
-		}
-	}
-	return -1;
-}
-
-typedef struct Encalg Encalg;
-struct Encalg
-{
-	char	*name;
-	int	blocklen;
-	int	alg;
-	void	(*keyinit)(OneWay*);
-};
-
-#ifdef NOSPOOKS
-static
-Encalg encrypttab[] =
-{
-	{ "descbc", 8, DESCBC, initDESkey, },           /* DEPRECATED -- use des_56_cbc */
-	{ "desecb", 8, DESECB, initDESkey, },           /* DEPRECATED -- use des_56_ecb */
-	{ "des_56_cbc", 8, DESCBC, initDESkey, },
-	{ "des_56_ecb", 8, DESECB, initDESkey, },
-	{ "des_40_cbc", 8, DESCBC, initDESkey_40, },
-	{ "des_40_ecb", 8, DESECB, initDESkey_40, },
-	{ "rc4", 1, RC4, initRC4key_40, },              /* DEPRECATED -- use rc4_X      */
-	{ "rc4_256", 1, RC4, initRC4key, },
-	{ "rc4_128", 1, RC4, initRC4key_128, },
-	{ "rc4_40", 1, RC4, initRC4key_40, },
-	{ 0 }
-};
-#else
-static
-Encalg encrypttab[] =
-{
-	{ "des_40_cbc", 8, DESCBC, initDESkey_40, },
-	{ "des_40_ecb", 8, DESECB, initDESkey_40, },
-	{ "rc4", 1, RC4, initRC4key_40, },              /* DEPRECATED -- use rc4_X      */
-	{ "rc4_40", 1, RC4, initRC4key_40, },
-	{ 0 }
-};
-#endif NOSPOOKS
-
-static int
-parseencryptalg(char *p, Dstate *s)
-{
-	Encalg *ea;
-
-	for(ea = encrypttab; ea->name; ea++){
-		if(strcmp(p, ea->name) == 0){
-			s->encryptalg = ea->alg;
-			s->blocklen = ea->blocklen;
-			(*ea->keyinit)(&s->in);
-			(*ea->keyinit)(&s->out);
-			s->state &= ~Sclear;
-			s->state |= Sencrypting;
-			return 0;
-		}
-	}
-	return -1;
-}
-
-enum {
-	Cfd,
-	Calg,
-	Csin,
-	Csout,
-};
-	
-static
-Cmdtab sslcmds[] = {
-	{Cfd, 	"fd", 	2 },
-	{Calg, 	"alg", 	0 },
-	{Csin, 	"secretin", 	2 },
-	{Csout,	"secretout",	2 },
-};
-
-static long
-sslwrite(Chan *c, void *a, long n, vlong)
-{
-	Dstate * volatile s;
-	Block * volatile b;
-	int m, t, i;
-	char *p, *e;
-	uchar *x;
-	Cmdbuf *cb;
-	Cmdtab *ct;
-
-	s = dstate[CONV(c->qid)];
-	if(s == 0)
-		panic("sslwrite");
-
-	t = TYPE(c->qid);
-	if(t == Qdata){
-		if(s->state == Sincomplete)
-			error(Ebadusefd);
-
-		/* lock should a write gets split over multiple records */
-		if(waserror()){
-			qunlock(&s->out.q);
-			nexterror();
-		}
-		qlock(&s->out.q);
-
-		p = a;
-		e = p + n;
-		do {
-			m = e - p;
-			if(m > s->max)
-				m = s->max;
-
-			b = allocb(m);
-			if(waserror()){
-				freeb(b);
-				nexterror();
-			}
-			memmove(b->wp, p, m);
-			poperror();
-			b->wp += m;
-
-			sslput(s, b);
-
-			p += m;
-		} while(p < e);
-
-		poperror();
-		qunlock(&s->out.q);
-		return n;
-	}
-
-	/* mutex with operations using what we're about to change */
-	if(waserror()){
-		qunlock(&s->in.ctlq);
-		qunlock(&s->out.q);
-		nexterror();
-	}
-	qlock(&s->in.ctlq);
-	qlock(&s->out.q);
-
-	switch(t){
-	default:
-		panic("sslwrite");
-	case Qsecretin:
-		setsecret(&s->in, a, n);
-		goto out;
-	case Qsecretout:
-		setsecret(&s->out, a, n);
-		goto out;
-	case Qctl:
-		break;
-	}
-
-	cb = parsecmd(a, n);
-	if(waserror()){
-		free(cb);
-		nexterror();
-	}
-	ct = lookupcmd(cb, sslcmds, nelem(sslcmds));
-	switch(ct->index){
-	case Cfd:
-		s->c = buftochan(cb->f[1]);
-
-		/* default is clear (msg delimiters only) */
-		s->state = Sclear;
-		s->blocklen = 1;
-		s->diglen = 0;
-		s->maxpad = s->max = (1<<15) - s->diglen - 1;
-		s->in.mid = 0;
-		s->out.mid = 0;
-		break;
-	case Calg:
-		if(cb->nf < 2)
-			cmderror(cb, "no algorithms");
-
-		s->blocklen = 1;
-		s->diglen = 0;
-
-		if(s->c == 0)
-			error("must set fd before algorithm");
-
-		s->state = Sclear;
-		s->maxpad = s->max = (1<<15) - s->diglen - 1;
-		if(strcmp(cb->f[1], "clear") == 0)
-			break;
-
-		if(s->in.secret && s->out.secret == 0)
-			setsecret(&s->out, s->in.secret, s->in.slen);
-		if(s->out.secret && s->in.secret == 0)
-			setsecret(&s->in, s->out.secret, s->out.slen);
-		if(s->in.secret == 0 || s->out.secret == 0)
-			error("algorithm but no secret");
-
-		s->hf = 0;
-		s->encryptalg = Noencryption;
-		s->blocklen = 1;
-
-		for(i=1; i<cb->nf; i++){
-			p = cb->f[i];
-			if(parsehashalg(p, s) < 0)
-			if(parseencryptalg(p, s) < 0)
-				error("bad algorithm");
-		}
-
-		if(s->hf == 0 && s->encryptalg == Noencryption)
-			error("bad algorithm");
-
-		if(s->blocklen != 1){
-			s->max = (1<<15) - s->diglen - 1;
-			s->max -= s->max % s->blocklen;
-			s->maxpad = (1<<14) - s->diglen - 1;
-			s->maxpad -= s->maxpad % s->blocklen;
-		} else
-			s->maxpad = s->max = (1<<15) - s->diglen - 1;
-		break;
-	case Csin:
-		p = cb->f[1];
-		m = (strlen(p)*3)/2 + 1;
-		x = secalloc(m);
-		t = dec64(x, m, p, strlen(p));
-		memset(p, 0, strlen(p));
-		if(t <= 0){
-			secfree(x);
-			error(Ebadarg);
-		}
-		setsecret(&s->in, x, t);
-		secfree(x);
-		break;
-	case Csout:
-		p = cb->f[1];
-		m = (strlen(p)*3)/2 + 1;
-		x = secalloc(m);
-		t = dec64(x, m, p, strlen(p));
-		memset(p, 0, strlen(p));
-		if(t <= 0){
-			secfree(x);
-			error(Ebadarg);
-		}
-		setsecret(&s->out, x, t);
-		secfree(x);
-		break;
-	}
-	poperror();
-	free(cb);
-
-out:
-	qunlock(&s->in.ctlq);
-	qunlock(&s->out.q);
-	poperror();
-	return n;
-}
-
-static void
-sslinit(void)
-{
-	struct Encalg *e;
-	struct Hashalg *h;
-	int n;
-	char *cp;
-
-	n = 1;
-	for(e = encrypttab; e->name != nil; e++)
-		n += strlen(e->name) + 1;
-	cp = encalgs = smalloc(n);
-	for(e = encrypttab;;){
-		strcpy(cp, e->name);
-		cp += strlen(e->name);
-		e++;
-		if(e->name == nil)
-			break;
-		*cp++ = ' ';
-	}
-	*cp = 0;
-
-	n = 1;
-	for(h = hashtab; h->name != nil; h++)
-		n += strlen(h->name) + 1;
-	cp = hashalgs = smalloc(n);
-	for(h = hashtab;;){
-		strcpy(cp, h->name);
-		cp += strlen(h->name);
-		h++;
-		if(h->name == nil)
-			break;
-		*cp++ = ' ';
-	}
-	*cp = 0;
-}
-
-Dev ssldevtab = {
-	'D',
-	"ssl",
-
-	devreset,
-	sslinit,
-	devshutdown,
-	sslattach,
-	sslwalk,
-	sslstat,
-	sslopen,
-	devcreate,
-	sslclose,
-	sslread,
-	sslbread,
-	sslwrite,
-	sslbwrite,
-	devremove,
-	sslwstat,
-};
-
-static Block*
-encryptb(Dstate *s, Block *b, int offset)
-{
-	uchar *p, *ep, *p2, *ip, *eip;
-	DESstate *ds;
-
-	switch(s->encryptalg){
-	case DESECB:
-		ds = s->out.state;
-		ep = b->rp + BLEN(b);
-		for(p = b->rp + offset; p < ep; p += 8)
-			block_cipher(ds->expanded, p, 0);
-		break;
-	case DESCBC:
-		ds = s->out.state;
-		ep = b->rp + BLEN(b);
-		for(p = b->rp + offset; p < ep; p += 8){
-			p2 = p;
-			ip = ds->ivec;
-			for(eip = ip+8; ip < eip; )
-				*p2++ ^= *ip++;
-			block_cipher(ds->expanded, p, 0);
-			memmove(ds->ivec, p, 8);
-		}
-		break;
-	case RC4:
-		rc4(s->out.state, b->rp + offset, BLEN(b) - offset);
-		break;
-	}
-	return b;
-}
-
-static Block*
-decryptb(Dstate *s, Block *bin)
-{
-	Block *b, **l;
-	uchar *p, *ep, *tp, *ip, *eip;
-	DESstate *ds;
-	uchar tmp[8];
-	int i;
-
-	l = &bin;
-	for(b = bin; b; b = b->next){
-		/* make sure we have a multiple of s->blocklen */
-		if(s->blocklen > 1){
-			i = BLEN(b);
-			if(i % s->blocklen){
-				*l = b = pullupblock(b, i + s->blocklen - (i%s->blocklen));
-				if(b == 0)
-					error("ssl encrypted message too short");
-			}
-		}
-		l = &b->next;
-
-		/* decrypt */
-		switch(s->encryptalg){
-		case DESECB:
-			ds = s->in.state;
-			ep = b->rp + BLEN(b);
-			for(p = b->rp; p < ep; p += 8)
-				block_cipher(ds->expanded, p, 1);
-			break;
-		case DESCBC:
-			ds = s->in.state;
-			ep = b->rp + BLEN(b);
-			for(p = b->rp; p < ep;){
-				memmove(tmp, p, 8);
-				block_cipher(ds->expanded, p, 1);
-				tp = tmp;
-				ip = ds->ivec;
-				for(eip = ip+8; ip < eip; ){
-					*p++ ^= *ip;
-					*ip++ = *tp++;
-				}
-			}
-			break;
-		case RC4:
-			rc4(s->in.state, b->rp, BLEN(b));
-			break;
-		}
-	}
-	return bin;
-}
-
-static Block*
-digestb(Dstate *s, Block *b, int offset)
-{
-	uchar *p;
-	DigestState ss;
-	uchar msgid[4];
-	ulong n, h;
-	OneWay *w;
-
-	w = &s->out;
-
-	memset(&ss, 0, sizeof(ss));
-	h = s->diglen + offset;
-	n = BLEN(b) - h;
-
-	/* hash secret + message */
-	(*s->hf)(w->secret, w->slen, 0, &ss);
-	(*s->hf)(b->rp + h, n, 0, &ss);
-
-	/* hash message id */
-	p = msgid;
-	n = w->mid;
-	*p++ = n>>24;
-	*p++ = n>>16;
-	*p++ = n>>8;
-	*p = n;
-	(*s->hf)(msgid, 4, b->rp + offset, &ss);
-
-	return b;
-}
-
-static void
-checkdigestb(Dstate *s, Block *bin)
-{
-	uchar *p;
-	DigestState ss;
-	uchar msgid[4];
-	int n, h;
-	OneWay *w;
-	uchar digest[128];
-	Block *b;
-
-	w = &s->in;
-
-	memset(&ss, 0, sizeof(ss));
-
-	/* hash secret */
-	(*s->hf)(w->secret, w->slen, 0, &ss);
-
-	/* hash message */
-	h = s->diglen;
-	for(b = bin; b; b = b->next){
-		n = BLEN(b) - h;
-		if(n < 0)
-			panic("checkdigestb");
-		(*s->hf)(b->rp + h, n, 0, &ss);
-		h = 0;
-	}
-
-	/* hash message id */
-	p = msgid;
-	n = w->mid;
-	*p++ = n>>24;
-	*p++ = n>>16;
-	*p++ = n>>8;
-	*p = n;
-	(*s->hf)(msgid, 4, digest, &ss);
-
-	if(tsmemcmp(digest, bin->rp, s->diglen) != 0)
-		error("bad digest");
-}
-
-/* get channel associated with an fd */
-static Chan*
-buftochan(char *p)
-{
-	Chan *c;
-	int fd;
-
-	if(p == 0)
-		error(Ebadarg);
-	fd = strtoul(p, 0, 0);
-	if(fd < 0)
-		error(Ebadarg);
-	c = fdtochan(fd, ORDWR, 1, 1);	/* error check and inc ref */
-	if(devtab[c->type] == &ssldevtab){
-		cclose(c);
-		error("cannot ssl encrypt devssl files");
-	}
-	return c;
-}
-
-/* hand up a digest connection */
-static void
-sslhangup(Dstate *s)
-{
-	Block *b;
-
-	qlock(&s->in.q);
-	for(b = s->processed; b; b = s->processed){
-		s->processed = b->next;
-		freeb(b);
-	}
-	if(s->unprocessed){
-		freeb(s->unprocessed);
-		s->unprocessed = 0;
-	}
-	s->state = Sincomplete;
-	qunlock(&s->in.q);
-}
-
-static Dstate*
-dsclone(Chan *ch)
-{
-	int i;
-	Dstate *ret;
-
-	if(waserror()) {
-		unlock(&dslock);
-		nexterror();
-	}
-	lock(&dslock);
-	ret = nil;
-	for(i=0; i<Maxdstate; i++){
-		if(dstate[i] == nil){
-			dsnew(ch, &dstate[i]);
-			ret = dstate[i];
-			break;
-		}
-	}
-	unlock(&dslock);
-	poperror();
-	return ret;
-}
-
-static void
-dsnew(Chan *ch, Dstate **pp)
-{
-	Dstate *s;
-	int t;
-
-	*pp = s = malloc(sizeof(*s));
-	if(!s)
-		error(Enomem);
-	if(pp - dstate >= dshiwat)
-		dshiwat++;
-	memset(s, 0, sizeof(*s));
-	s->state = Sincomplete;
-	s->ref = 1;
-	kstrdup(&s->user, up->user);
-	s->perm = 0660;
-	t = TYPE(ch->qid);
-	if(t == Qclonus)
-		t = Qctl;
-	ch->qid.path = QID(pp - dstate, t);
-	ch->qid.vers = 0;
-}
--- a/sys/src/9/port/portmkfile
+++ b/sys/src/9/port/portmkfile
@@ -102,7 +102,6 @@
 devcap.$O:	/sys/include/libsec.h
 devfs.$O:	/sys/include/libsec.h
 devsdp.$O:	/sys/include/libsec.h
-devssl.$O:	/sys/include/libsec.h
 devtls.$O:	/sys/include/libsec.h
 devswap.$O:	/sys/include/libsec.h
 random.$O:	/sys/include/libsec.h
--- a/sys/src/cmd/cpu.c
+++ /tmp/diff100001879085
@@ -1,1237 +1,0 @@
-/*
- * cpu.c - Make a connection to a cpu server
- *
- *	   Invoked by listen as 'cpu -R | -N service net netdir'
- *	    	   by users  as 'cpu [-h system] [-c cmd args ...]'
- */
-
-#include <u.h>
-#include <libc.h>
-#include <auth.h>
-#include <fcall.h>
-#include <libsec.h>
-
-#define	Maxfdata 8192
-#define MaxStr 128
-
-void	remoteside(void);
-void	fatal(char*, ...);
-void	lclnoteproc(int);
-void	rmtnoteproc(void);
-void	catcher(void*, char*);
-void	usage(void);
-void	writestr(int, char*, char*, int);
-int	readstr(int, char*, int);
-char	*rexcall(int*, char*, char*);
-int	setamalg(char*);
-char	*keyspec = "";
-
-int 	notechan;
-int	exportpid;
-char	*system;
-int	cflag;
-int	nflag;
-int	dbg;
-char	*user;
-char	*patternfile;
-char	*origargs;
-
-char	*srvname = "ncpu";
-char	*exportfs = "/bin/oexportfs";
-char	*ealgs = "rc4_256 sha1";
-
-/* message size for exportfs; may be larger so we can do big graphics in CPU window */
-int	msgsize = Maxfdata+IOHDRSZ;
-
-/* encryption mechanisms */
-static int	clear(int);
-
-int (*encryption)(int) = clear;
-
-/* authentication mechanisms */
-static int	netkeyauth(int);
-static int	netkeysrvauth(int, char*);
-static int	p9auth(int);
-static int	srvp9auth(int, char*);
-static int	noauth(int);
-static int	srvnoauth(int, char*);
-
-typedef struct AuthMethod AuthMethod;
-struct AuthMethod {
-	char	*name;			/* name of method */
-	int	(*cf)(int);		/* client side authentication */
-	int	(*sf)(int, char*);	/* server side authentication */
-} authmethod[] = {
-	{ "p9",		p9auth,		srvp9auth,},
-	{ "netkey",	netkeyauth,	netkeysrvauth,},
-	{ "none",	noauth,		srvnoauth,},
-	{ nil,	nil}
-};
-AuthMethod *am = authmethod;	/* default is p9 */
-
-int setam(char*);
-
-char	*aan = "/bin/aan";
-char	*anstring = "tcp!*!0";
-char	*filterp = nil;
-
-int filter(int fd, char *host);
-
-void
-usage(void)
-{
-	fprint(2, "usage: cpu [-p] [-h system] [-u user] [-a authmethod] "
-		"[-e 'crypt hash'] [-k keypattern] [-P patternfile] "
-		"[-c cmd arg ...]\n");
-	exits("usage");
-}
-
-/*
- * reading /proc/pid/args yields either "name args" or "name [display args]",
- * so return only args or display args.
- */
-static char *
-procgetname(void)
-{
-	int fd, n;
-	char *lp, *rp;
-	char buf[256];
-
-	snprint(buf, sizeof buf, "#p/%d/args", getpid());
-	if((fd = open(buf, OREAD)) < 0)
-		return strdup("");
-	*buf = '\0';
-	n = read(fd, buf, sizeof buf-1);
-	close(fd);
-	if (n >= 0)
-		buf[n] = '\0';
-	if ((lp = strchr(buf, '[')) == nil || (rp = strrchr(buf, ']')) == nil) {
-		lp = strchr(buf, ' ');
-		if (lp == nil)
-			return strdup("");
-		else
-			return strdup(lp+1);
-	}
-	*rp = '\0';
-	return strdup(lp+1);
-}
-
-void
-main(int argc, char **argv)
-{
-	char dat[MaxStr], buf[MaxStr], cmd[MaxStr], *p, *s, *err;
-	int ac, fd, ms, data;
-	char *av[10];
-
-	quotefmtinstall();
-	origargs = procgetname();
-	/* see if we should use a larger message size */
-	fd = open("/dev/draw", OREAD);
-	if(fd >= 0){
-		ms = iounit(fd);
-		if(msgsize < ms+IOHDRSZ)
-			msgsize = ms+IOHDRSZ;
-		close(fd);
-	}
-
-	user = getuser();
-	if(user == nil)
-		fatal("can't read user name: %r");
-	ARGBEGIN{
-	case 'a':
-		p = EARGF(usage());
-		if(setam(p) < 0)
-			fatal("unknown auth method %s", p);
-		break;
-	case 'e':
-		ealgs = EARGF(usage());
-		if(*ealgs == 0 || strcmp(ealgs, "clear") == 0)
-			ealgs = nil;
-		break;
-	case 'd':
-		dbg++;
-		break;
-	case 'f':
-		/* ignored but accepted for compatibility */
-		break;
-	case 'n':
-		/* must be specified before -R/-O */
-		nflag++;
-		break;
-	case 'A':
-		anstring = EARGF(usage());
-		break;
-	case 'R':				/* From listen */
-		remoteside();
-		break;
-	case 'h':
-		system = EARGF(usage());
-		break;
-	case 'c':
-		cflag++;
-		s = cmd;
-		*s++ = '!';
-		*s = 0;
-		while(p = ARGF())
-			s = seprint(s, cmd+sizeof(cmd), " %q", p);
-		break;
-	case 'k':
-		keyspec = smprint("%s %s", keyspec, EARGF(usage()));
-		break;
-	case 'P':
-		patternfile = EARGF(usage());
-		break;
-	case 'u':
-		user = EARGF(usage());
-		keyspec = smprint("%s user=%s", keyspec, user);
-		break;
-	case 'p':
-		filterp = aan;
-		break;
-	default:
-		usage();
-	}ARGEND;
-
-
-	if(argc != 0)
-		usage();
-
-	if(system == nil) {
-		p = getenv("cpu");
-		if(p == 0)
-			fatal("set $cpu");
-		system = p;
-	}
-
-	if(err = rexcall(&data, system, srvname))
-		fatal("%s: %s: %r", err, system);
-
-	procsetname("%s", origargs);
-	/* Tell the remote side the command to execute and where our working directory is */
-	if(cflag)
-		writestr(data, cmd, "command", 0);
-	if(getwd(dat, sizeof(dat)) == 0)
-		writestr(data, "NO", "dir", 0);
-	else
-		writestr(data, dat, "dir", 0);
-
-	/* start up a process to pass along notes */
-	lclnoteproc(data);
-
-	/* 
-	 *  Wait for the other end to execute and start our file service
-	 *  of /mnt/term
-	 */
-	if(readstr(data, buf, sizeof(buf)) < 0)
-		fatal("waiting for FS: %r");
-	if(strncmp("FS", buf, 2) != 0) {
-		print("remote cpu: %s", buf);
-		exits(buf);
-	}
-
-	/* Begin serving the gnot namespace */
-	close(0);
-	dup(data, 0);
-	close(data);
-
-	sprint(buf, "%d", msgsize);
-	ac = 0;
-	av[ac++] = exportfs;
-	av[ac++] = "-m";
-	av[ac++] = buf;
-	if(dbg)
-		av[ac++] = "-d";
-	if(patternfile != nil){
-		av[ac++] = "-P";
-		av[ac++] = patternfile;
-	}
-	av[ac] = nil;
-	exec(exportfs, av);
-	fatal("starting exportfs: %r");
-}
-
-void
-fatal(char *fmt, ...)
-{
-	char buf[1024];
-	va_list arg;
-
-	va_start(arg, fmt);
-	vsnprint(buf, sizeof(buf), fmt, arg);
-	va_end(arg);
-	fprint(2, "cpu: %s\n", buf);
-	syslog(0, "cpu", "%s", buf);
-	exits(buf);
-}
-
-char *negstr = "negotiating authentication method";
-
-/* Invoked with stdin and stdout connected to the network connection */
-void
-remoteside(void)
-{
-	char user[MaxStr], buf[MaxStr], xdir[MaxStr], cmd[MaxStr];
-	int i, n, fd, badchdir, gotcmd;
-
-	rfork(RFENVG);
-	putenv("service", "cpu");
-	fd = 0;
-
-	/* negotiate authentication mechanism */
-	n = readstr(fd, cmd, sizeof(cmd));
-	if(n < 0)
-		fatal("authenticating: %r");
-	filterp = nil;
-	if(strcmp(cmd, "aan") == 0){
-		filterp = aan;
-		writestr(fd, "", nil, 1);
-		n = readstr(fd, cmd, sizeof(cmd));
-		if(n < 0)
-			fatal("authenticating: %r");
-	}
-	if(setamalg(cmd) < 0 || (nflag == 0 && am->sf == srvnoauth)) {
-		writestr(fd, "unsupported auth method", nil, 0);
-		fatal("bad auth method %s", cmd);
-	} else
-		writestr(fd, "", "", 1);
-
-	if((fd = (*am->sf)(fd, user)) < 0)
-		fatal("srvauth: %r");
-	if((fd = filter(fd, nil)) < 0)
-		fatal("filter: %r");
-	if((fd = encryption(fd)) < 0)
-		fatal("encrypt: %r");
-
-	/* Now collect invoking cpu's current directory or possibly a command */
-	gotcmd = 0;
-	if(readstr(fd, xdir, sizeof(xdir)) < 0)
-		fatal("dir/cmd: %r");
-	if(xdir[0] == '!') {
-		strcpy(cmd, &xdir[1]);
-		gotcmd = 1;
-		if(readstr(fd, xdir, sizeof(xdir)) < 0)
-			fatal("dir: %r");
-	}
-
-	/* Establish the new process at the current working directory of the gnot */
-	badchdir = 0;
-	if(strcmp(xdir, "NO") != 0)
-		if(chdir(xdir) < 0)
-			badchdir = 1;
-
-	/* Start the gnot serving its namespace */
-	writestr(fd, "FS", "FS", 0);
-	writestr(fd, "/", "exportfs dir", 0);
-
-	n = read(fd, buf, sizeof(buf));
-	if(n != 2 || buf[0] != 'O' || buf[1] != 'K')
-		exits("remote tree");
-
-	/* make sure buffers are big by doing fversion explicitly; pick a huge number; other side will trim */
-	strcpy(buf, VERSION9P);
-	if(fversion(fd, 64*1024, buf, sizeof buf) < 0)
-		exits("fversion failed");
-	if(mount(fd, -1, "/mnt/term", MCREATE|MREPL, "") == -1)
-		exits("mount failed");
-
-	close(fd);
-
-	/* the remote noteproc uses the mount so it must follow it */
-	rmtnoteproc();
-
-	for(i = 0; i < 3; i++)
-		close(i);
-
-	if(open("/mnt/term/dev/cons", OREAD) != 0)
-		exits("open stdin");
-	if(open("/mnt/term/dev/cons", OWRITE) != 1)
-		exits("open stdout");
-	dup(1, 2);
-
-	if(badchdir)
-		print("cpu: failed to chdir to '%s'\n", xdir);
-
-	if(gotcmd)
-		execl("/bin/rc", "rc", "-lc", cmd, nil);
-	else
-		execl("/bin/rc", "rc", "-li", nil);
-	fatal("exec shell: %r");
-}
-
-char*
-rexcall(int *fd, char *host, char *service)
-{
-	char *na;
-	char err[ERRMAX];
-	char msg[MaxStr];
-	int n;
-
-	na = netmkaddr(host, 0, service);
-	procsetname("dialing %s", na);
-	if((*fd = dial(na, 0, 0, 0)) < 0)
-		return "can't dial";
-
-	/* negotiate aan filter extension */
-	if(filterp == aan){
-		writestr(*fd, "aan", "negotiating aan", 0);
-		n = readstr(*fd, err, sizeof err);
-		if(n < 0)
-			return "negotiating aan";
-		if(*err){
-			errstr(err, sizeof err);
-			return negstr;
-		}
-	}
-
-	/* negotiate authentication mechanism */
-	if(ealgs != nil)
-		snprint(msg, sizeof(msg), "%s %s", am->name, ealgs);
-	else
-		snprint(msg, sizeof(msg), "%s", am->name);
-	procsetname("writing %s", msg);
-	writestr(*fd, msg, negstr, 0);
-	procsetname("awaiting auth method");
-	n = readstr(*fd, err, sizeof err);
-	if(n < 0)
-		return negstr;
-	if(*err){
-		errstr(err, sizeof err);
-		return negstr;
-	}
-
-	/* authenticate */
-	procsetname("%s: auth via %s", origargs, am->name);
-	if((*fd = (*am->cf)(*fd)) < 0)
-		return "can't authenticate";
-	if((*fd = filter(*fd, system)) < 0)
-		return "can't filter";
-	if((*fd = encryption(*fd)) < 0)
-		return "can't encrypt";
-	return nil;
-}
-
-void
-writestr(int fd, char *str, char *thing, int ignore)
-{
-	int l, n;
-
-	l = strlen(str);
-	n = write(fd, str, l+1);
-	if(!ignore && n < 0)
-		fatal("writing network: %s: %r", thing);
-}
-
-int
-readstr(int fd, char *str, int len)
-{
-	int n;
-
-	while(len) {
-		n = read(fd, str, 1);
-		if(n < 0) 
-			return -1;
-		if(n == 0){
-			werrstr("hung up");
-			return -1;
-		}
-		if(*str == '\0')
-			return 0;
-		str++;
-		len--;
-	}
-	return -1;
-}
-
-static int
-readln(char *buf, int n)
-{
-	int i;
-	char *p;
-
-	n--;	/* room for \0 */
-	p = buf;
-	for(i=0; i<n; i++){
-		if(read(0, p, 1) != 1)
-			break;
-		if(*p == '\n' || *p == '\r')
-			break;
-		p++;
-	}
-	*p = '\0';
-	return p-buf;
-}
-
-/*
- *  chown network connection
- */
-static void
-setnetuser(int fd, char *user)
-{
-	Dir nd;
-	nulldir(&nd);
-	nd.mode = 0660;
-	nd.uid = user;
-	dirfwstat(fd, &nd);
-}
-
-/*
- *  user level challenge/response
- */
-static int
-netkeyauth(int fd)
-{
-	char chall[32];
-	char resp[32];
-
-	strecpy(chall, chall+sizeof chall, getuser());
-	print("user[%s]: ", chall);
-	if(readln(resp, sizeof(resp)) < 0)
-		return -1;
-	if(*resp != 0)
-		strcpy(chall, resp);
-	writestr(fd, chall, "challenge/response", 1);
-
-	for(;;){
-		if(readstr(fd, chall, sizeof chall) < 0)
-			break;
-		if(*chall == 0)
-			return fd;
-		print("challenge: %s\nresponse: ", chall);
-		if(readln(resp, sizeof(resp)) < 0)
-			break;
-		writestr(fd, resp, "challenge/response", 1);
-	}
-	return -1;
-}
-
-static int
-netkeysrvauth(int fd, char *user)
-{
-	char response[32];
-	Chalstate *ch;
-	int tries;
-	AuthInfo *ai;
-
-	if(readstr(fd, user, MaxStr) < 0)
-		return -1;
-
-	ai = nil;
-	ch = nil;
-	for(tries = 0; tries < 10; tries++){
-		if((ch = auth_challenge("proto=p9cr role=server user=%q", user)) == nil)
-			return -1;
-		writestr(fd, ch->chal, "challenge", 1);
-		if(readstr(fd, response, sizeof response) < 0)
-			return -1;
-		ch->resp = response;
-		ch->nresp = strlen(response);
-		if((ai = auth_response(ch)) != nil)
-			break;
-	}
-	auth_freechal(ch);
-	if(ai == nil)
-		return -1;
-	writestr(fd, "", "challenge", 1);
-	if(auth_chuid(ai, 0) < 0)
-		fatal("newns: %r");
-	setnetuser(fd, ai->cuid);
-	auth_freeAI(ai);
-	return fd;
-}
-
-static int
-clear(int fd)
-{
-	return fd;
-}
-
-static char sslsecret[2][21];
-
-static int
-sslencrypt(int fd)
-{
-	return pushssl(fd, ealgs, sslsecret[0], sslsecret[1], nil);
-}
-
-static void
-mksecret(char *t, uchar *f)
-{
-	sprint(t, "%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux",
-		f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7], f[8], f[9]);
-}
-
-static int
-sslsetup(int fd, uchar *secret, int nsecret, int isclient)
-{
-	uchar key[16], digest[SHA1dlen];
-	int i;
-
-	if(ealgs == nil)
-		return fd;
-
-	if(nsecret < 8){
-		werrstr("secret too small to ssl");
-		return -1;
-	}
-	memmove(key+4, secret, 8);
-
-	/* exchange random numbers */
-	srand(truerand());
-
-	if(isclient){
-		for(i = 0; i < 4; i++)
-			key[i] = rand();
-		if(write(fd, key, 4) != 4)
-			return -1;
-		if(readn(fd, key+12, 4) != 4)
-			return -1;
-	} else {
-		for(i = 0; i < 4; i++)
-			key[i+12] = rand();
-		if(readn(fd, key, 4) != 4)
-			return -1;
-		if(write(fd, key+12, 4) != 4)
-			return -1;
-	}
-
-	/* scramble into two secrets */
-	sha1(key, sizeof(key), digest, nil);
-	mksecret(sslsecret[isclient == 0], digest);
-	mksecret(sslsecret[isclient != 0], digest+10);
-
-	encryption = sslencrypt;
-
-	return fd;
-}
-
-/*
- *  plan9 authentication followed by rc4 encryption
- */
-static int
-p9auth(int fd)
-{
-	AuthInfo *ai;
-
-	ai = auth_proxy(fd, auth_getkey, "proto=p9any role=client %s", keyspec);
-	if(ai == nil)
-		return -1;
-	fd = sslsetup(fd, ai->secret, ai->nsecret, 1);
-	auth_freeAI(ai);
-	return fd;
-}
-
-static int
-noauth(int fd)
-{
-	ealgs = nil;
-	return fd;
-}
-
-static int
-srvnoauth(int fd, char *user)
-{
-	strecpy(user, user+MaxStr, getuser());
-	ealgs = nil;
-	newns(user, nil);
-	return fd;
-}
-
-static int
-srvp9auth(int fd, char *user)
-{
-	AuthInfo *ai;
-
-	ai = auth_proxy(fd, nil, "proto=p9any role=server %s", keyspec);
-	if(ai == nil)
-		return -1;
-	if(auth_chuid(ai, nil) < 0)
-		fatal("newns: %r");
-	setnetuser(fd, ai->cuid);
-	snprint(user, MaxStr, "%s", ai->cuid);
-	fd = sslsetup(fd, ai->secret, ai->nsecret, 0);
-	auth_freeAI(ai);
-	return fd;
-}
-
-/*
- *  set authentication mechanism
- */
-int
-setam(char *name)
-{
-	for(am = authmethod; am->name != nil; am++)
-		if(strcmp(am->name, name) == 0)
-			return 0;
-	am = authmethod;
-	return -1;
-}
-
-/*
- *  set authentication mechanism and encryption/hash algs
- */
-int
-setamalg(char *s)
-{
-	ealgs = strchr(s, ' ');
-	if(ealgs != nil)
-		*ealgs++ = 0;
-	return setam(s);
-}
-
-int
-filter(int fd, char *host)
-{
-	char addr[128], buf[256], *s, *file, *argv[16];
-	int p[2], lfd, flags, len, argc;
-
-	if(filterp == nil)
-		return fd;
-	procsetname("filter %s", filterp);
-	flags = RFNOWAIT|RFPROC|RFMEM|RFFDG|RFREND;
-	if(host == nil){
-		/* remote side */
-		if(announce(anstring, addr) < 0)
-			fatal("filter: Cannot announce %s: %r", anstring);
-		snprint(buf, sizeof(buf), "%s/local", addr);
-		if((lfd = open(buf, OREAD)) < 0)
-			fatal("filter: Cannot open %s: %r", buf);
-		if((len = read(lfd, buf, sizeof buf - 1)) < 0)
-			fatal("filter: Cannot read %s: %r", buf);
-		close(lfd);
-		buf[len] = 0;
-		if(s = strchr(buf, '\n'))
-			len = s - buf;
-		if(write(fd, buf, len) != len) 
-			fatal("filter: cannot write port; %r");
-	} else {
-		/* client side */
-		flags |= RFNOTEG;
-		if((len = read(fd, buf, sizeof buf - 1)) < 0)
-			fatal("filter: cannot read port; %r");
-		buf[len] = '\0';
-		if((s = strrchr(buf, '!')) == nil)
-			fatal("filter: malformed remote port: %s", buf);
-		strecpy(addr, addr+sizeof(addr), netmkaddr(host, "tcp", s+1));
-		strecpy(strrchr(addr, '!'), addr+sizeof(addr), s);
-	}
-
-	snprint(buf, sizeof(buf), "%s", filterp);
-	if((argc = tokenize(buf, argv, nelem(argv)-3)) <= 0)
-		fatal("filter: empty command");
-	if(host)
-		argv[argc++] = "-c";
-	argv[argc++] = addr;
-	argv[argc] = nil;
-	file = argv[0];
-	if(s = strrchr(argv[0], '/'))
-		argv[0] = s+1;
-
-	if(pipe(p) < 0)
-		fatal("filter: pipe; %r");
-
-	switch(rfork(flags)) {
-	case -1:
-		fatal("filter: rfork; %r\n");
-	case 0:
-		if (dup(p[0], 1) < 0)
-			fatal("filter: Cannot dup to 1; %r");
-		if (dup(p[0], 0) < 0)
-			fatal("filter: Cannot dup to 0; %r");
-		close(p[0]);
-		close(p[1]);
-		exec(file, argv);
-		fatal("filter: exec; %r");
-	default:
-		close(fd);
-		close(p[0]);
-	}
-	return p[1];	
-}
-
-char *rmtnotefile = "/mnt/term/dev/cpunote";
-
-/*
- *  loop reading /mnt/term/dev/note looking for notes.
- *  The child returns to start the shell.
- */
-void
-rmtnoteproc(void)
-{
-	int n, fd, pid, notepid;
-	char buf[256];
-
-	/* new proc returns to start shell */
-	pid = rfork(RFPROC|RFFDG|RFNOTEG|RFNAMEG|RFMEM);
-	switch(pid){
-	case -1:
-		syslog(0, "cpu", "cpu -R: can't start noteproc: %r");
-		return;
-	case 0:
-		return;
-	}
-
-	/* new proc reads notes from other side and posts them to shell */
-	switch(notepid = rfork(RFPROC|RFFDG|RFMEM)){
-	case -1:
-		syslog(0, "cpu", "cpu -R: can't start wait proc: %r");
-		_exits(0);
-	case 0:
-		fd = open(rmtnotefile, OREAD);
-		if(fd < 0)
-			_exits(0);
-	
-		for(;;){
-			n = read(fd, buf, sizeof(buf)-1);
-			if(n <= 0){
-				postnote(PNGROUP, pid, "hangup");
-				_exits(0);
-			}
-			buf[n] = 0;
-			postnote(PNGROUP, pid, buf);
-		}
-	}
-
-	/* original proc waits for shell proc to die and kills note proc */
-	for(;;){
-		n = waitpid();
-		if(n < 0 || n == pid)
-			break;
-	}
-	postnote(PNPROC, notepid, "kill");
-	_exits(0);
-}
-
-enum
-{
-	Qdir,
-	Qcpunote,
-
-	Nfid = 32,
-};
-
-struct {
-	char	*name;
-	Qid	qid;
-	ulong	perm;
-} fstab[] =
-{
-	[Qdir]		{ ".",		{Qdir, 0, QTDIR},	DMDIR|0555	},
-	[Qcpunote]	{ "cpunote",	{Qcpunote, 0},		0444		},
-};
-
-typedef struct Note Note;
-struct Note
-{
-	Note *next;
-	char msg[ERRMAX];
-};
-
-typedef struct Request Request;
-struct Request
-{
-	Request *next;
-	Fcall f;
-};
-
-typedef struct Fid Fid;
-struct Fid
-{
-	int	fid;
-	int	file;
-	int	omode;
-};
-Fid fids[Nfid];
-
-struct {
-	Lock;
-	Note *nfirst, *nlast;
-	Request *rfirst, *rlast;
-} nfs;
-
-int
-fsreply(int fd, Fcall *f)
-{
-	uchar buf[IOHDRSZ+Maxfdata];
-	int n;
-
-	if(dbg)
-		fprint(2, "notefs: <-%F\n", f);
-	n = convS2M(f, buf, sizeof buf);
-	if(n > 0){
-		if(write(fd, buf, n) != n){
-			close(fd);
-			return -1;
-		}
-	}
-	return 0;
-}
-
-/* match a note read request with a note, reply to the request */
-int
-kick(int fd)
-{
-	Request *rp;
-	Note *np;
-	int rv;
-
-	for(;;){
-		lock(&nfs);
-		rp = nfs.rfirst;
-		np = nfs.nfirst;
-		if(rp == nil || np == nil){
-			unlock(&nfs);
-			break;
-		}
-		nfs.rfirst = rp->next;
-		nfs.nfirst = np->next;
-		unlock(&nfs);
-
-		rp->f.type = Rread;
-		rp->f.count = strlen(np->msg);
-		rp->f.data = np->msg;
-		rv = fsreply(fd, &rp->f);
-		free(rp);
-		free(np);
-		if(rv < 0)
-			return -1;
-	}
-	return 0;
-}
-
-void
-flushreq(int tag)
-{
-	Request **l, *rp;
-
-	lock(&nfs);
-	for(l = &nfs.rfirst; *l != nil; l = &(*l)->next){
-		rp = *l;
-		if(rp->f.tag == tag){
-			*l = rp->next;
-			unlock(&nfs);
-			free(rp);
-			return;
-		}
-	}
-	unlock(&nfs);
-}
-
-Fid*
-getfid(int fid)
-{
-	int i, freefid;
-
-	freefid = -1;
-	for(i = 0; i < Nfid; i++){
-		if(freefid < 0 && fids[i].file < 0)
-			freefid = i;
-		if(fids[i].fid == fid)
-			return &fids[i];
-	}
-	if(freefid >= 0){
-		fids[freefid].fid = fid;
-		return &fids[freefid];
-	}
-	return nil;
-}
-
-int
-fsstat(int fd, Fid *fid, Fcall *f)
-{
-	Dir d;
-	uchar statbuf[256];
-
-	memset(&d, 0, sizeof(d));
-	d.name = fstab[fid->file].name;
-	d.uid = user;
-	d.gid = user;
-	d.muid = user;
-	d.qid = fstab[fid->file].qid;
-	d.mode = fstab[fid->file].perm;
-	d.atime = d.mtime = time(0);
-	f->stat = statbuf;
-	f->nstat = convD2M(&d, statbuf, sizeof statbuf);
-	return fsreply(fd, f);
-}
-
-int
-fsread(int fd, Fid *fid, Fcall *f)
-{
-	Dir d;
-	uchar buf[256];
-	Request *rp;
-
-	switch(fid->file){
-	default:
-		return -1;
-	case Qdir:
-		if(f->offset == 0 && f->count >0){
-			memset(&d, 0, sizeof(d));
-			d.name = fstab[Qcpunote].name;
-			d.uid = user;
-			d.gid = user;
-			d.muid = user;
-			d.qid = fstab[Qcpunote].qid;
-			d.mode = fstab[Qcpunote].perm;
-			d.atime = d.mtime = time(0);
-			f->count = convD2M(&d, buf, sizeof buf);
-			f->data = (char*)buf;
-		} else
-			f->count = 0;
-		return fsreply(fd, f);
-	case Qcpunote:
-		rp = mallocz(sizeof(*rp), 1);
-		if(rp == nil)
-			return -1;
-		rp->f = *f;
-		lock(&nfs);
-		if(nfs.rfirst == nil)
-			nfs.rfirst = rp;
-		else
-			nfs.rlast->next = rp;
-		nfs.rlast = rp;
-		unlock(&nfs);
-		return kick(fd);;
-	}
-}
-
-char Eperm[] = "permission denied";
-char Enofile[] = "out of files";
-char Enotdir[] = "not a directory";
-
-void
-notefs(int fd)
-{
-	uchar buf[IOHDRSZ+Maxfdata];
-	int i, n, ncpunote;
-	Fcall f;
-	Qid wqid[MAXWELEM];
-	Fid *fid, *nfid;
-	int doreply;
-
-	rfork(RFNOTEG);
-	fmtinstall('F', fcallfmt);
-
-	for(n = 0; n < Nfid; n++){
-		fids[n].file = -1;
-		fids[n].omode = -1;
-	}
-
-	ncpunote = 0;
-	for(;;){
-		n = read9pmsg(fd, buf, sizeof(buf));
-		if(n <= 0 || convM2S(buf, n, &f) != n)
-			break;
-		if(dbg)
-			fprint(2, "notefs: ->%F\n", &f);
-		doreply = 1;
-		fid = getfid(f.fid);
-		if(fid == nil){
-nofids:
-			f.type = Rerror;
-			f.ename = Enofile;
-			fsreply(fd, &f);
-			continue;
-		}
-		switch(f.type++){
-		default:
-			f.type = Rerror;
-			f.ename = "unknown type";
-			break;
-		case Tflush:
-			flushreq(f.oldtag);
-			break;
-		case Tversion:
-			if(f.msize > IOHDRSZ+Maxfdata)
-				f.msize = IOHDRSZ+Maxfdata;
-			break;
-		case Tauth:
-			f.type = Rerror;
-			f.ename = "authentication not required";
-			break;
-		case Tattach:
-			f.qid = fstab[Qdir].qid;
-			fid->file = Qdir;
-			break;
-		case Twalk:
-			nfid = nil;
-			if(f.newfid != f.fid){
-				nfid = getfid(f.newfid);
-				if(nfid == nil)
-					goto nofids;
-				nfid->file = fid->file;
-				fid = nfid;
-			}
-			for(i=0; i<f.nwname && i<MAXWELEM; i++){
-				if(fid->file != Qdir){
-					f.type = Rerror;
-					f.ename = Enotdir;
-					break;
-				}
-				if(strcmp(f.wname[i], "..") == 0){
-					wqid[i] = fstab[Qdir].qid;
-					continue;
-				}
-				if(strcmp(f.wname[i], "cpunote") != 0){
-					if(i == 0){
-						f.type = Rerror;
-						f.ename = "file does not exist";
-					}
-					break;
-				}
-				fid->file = Qcpunote;
-				wqid[i] = fstab[Qcpunote].qid;
-			}
-			if(nfid != nil && (f.type == Rerror || i < f.nwname))
-				nfid ->file = -1;
-			if(f.type != Rerror){
-				f.nwqid = i;
-				for(i=0; i<f.nwqid; i++)
-					f.wqid[i] = wqid[i];
-			}
-			break;
-		case Topen:
-			if(f.mode != OREAD){
-				f.type = Rerror;
-				f.ename = Eperm;
-				break;
-			}
-			fid->omode = f.mode;
-			if(fid->file == Qcpunote)
-				ncpunote++;
-			f.qid = fstab[fid->file].qid;
-			f.iounit = 0;
-			break;
-		case Tread:
-			if(fsread(fd, fid, &f) < 0)
-				goto err;
-			doreply = 0;
-			break;
-		case Tclunk:
-			if(fid->omode != -1 && fid->file == Qcpunote){
-				ncpunote--;
-				if(ncpunote == 0)	/* remote side is done */
-					goto err;
-			}
-			fid->file = -1;
-			fid->omode = -1;
-			break;
-		case Tstat:
-			if(fsstat(fd, fid, &f) < 0)
-				goto err;
-			doreply = 0;
-			break;
-		case Tcreate:
-		case Twrite:
-		case Tremove:
-		case Twstat:
-			f.type = Rerror;
-			f.ename = Eperm;
-			break;
-		}
-		if(doreply)
-			if(fsreply(fd, &f) < 0)
-				break;
-	}
-err:
-	if(dbg)
-		fprint(2, "notefs exiting: %r\n");
-	werrstr("success");
-	postnote(PNGROUP, exportpid, "kill");
-	if(dbg)
-		fprint(2, "postnote PNGROUP %d: %r\n", exportpid);
-	close(fd);
-}
-
-char 	notebuf[ERRMAX];
-
-void
-catcher(void*, char *text)
-{
-	int n;
-
-	n = strlen(text);
-	if(n >= sizeof(notebuf))
-		n = sizeof(notebuf)-1;
-	memmove(notebuf, text, n);
-	notebuf[n] = '\0';
-	noted(NCONT);
-}
-
-/*
- *  mount in /dev a note file for the remote side to read.
- */
-void
-lclnoteproc(int netfd)
-{
-	Waitmsg *w;
-	Note *np;
-	int pfd[2];
-	int pid;
-
-	if(pipe(pfd) < 0){
-		fprint(2, "cpu: can't start note proc: pipe: %r\n");
-		return;
-	}
-
-	/* new proc mounts and returns to start exportfs */
-	switch(pid = rfork(RFPROC|RFNAMEG|RFFDG|RFMEM)){
-	default:
-		exportpid = pid;
-		break;
-	case -1:
-		fprint(2, "cpu: can't start note proc: rfork: %r\n");
-		return;
-	case 0:
-		close(pfd[0]);
-		if(mount(pfd[1], -1, "/dev", MBEFORE, "") == -1)
-			fprint(2, "cpu: can't mount note proc: %r\n");
-		close(pfd[1]);
-		return;
-	}
-
-	close(netfd);
-	close(pfd[1]);
-
-	/* new proc listens for note file system rpc's */
-	switch(rfork(RFPROC|RFNAMEG|RFMEM)){
-	case -1:
-		fprint(2, "cpu: can't start note proc: rfork1: %r\n");
-		_exits(0);
-	case 0:
-		notefs(pfd[0]);
-		_exits(0);
-	}
-
-	/* original proc waits for notes */
-	notify(catcher);
-	w = nil;
-	for(;;) {
-		*notebuf = 0;
-		free(w);
-		w = wait();
-		if(w == nil) {
-			if(*notebuf == 0)
-				break;
-			np = mallocz(sizeof(Note), 1);
-			if(np != nil){
-				strcpy(np->msg, notebuf);
-				lock(&nfs);
-				if(nfs.nfirst == nil)
-					nfs.nfirst = np;
-				else
-					nfs.nlast->next = np;
-				nfs.nlast = np;
-				unlock(&nfs);
-				kick(pfd[0]);
-			}
-			unlock(&nfs);
-		} else if(w->pid == exportpid)
-			break;
-	}
-
-	if(w == nil)
-		exits(nil);
-	exits(0);
-/*	exits(w->msg); */
-}
--- a/sys/src/libc/9sys/mkfile
+++ b/sys/src/libc/9sys/mkfile
@@ -33,7 +33,6 @@
 	postnote.$O\
 	privalloc.$O\
 	procsetname.$O\
-	pushssl.$O\
 	pushtls.$O\
 	putenv.$O\
 	qlock.$O\


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [9front] intent to delete: devssl, cpu, oexportfs, import
  2021-10-22  1:48 [9front] intent to delete: devssl, cpu, oexportfs, import ori
@ 2021-10-22  1:58 ` sl
  2021-10-22  2:26   ` ori
  2021-10-22 20:26   ` Stuart Morrow
  2021-10-22 11:43 ` kemal
  1 sibling, 2 replies; 20+ messages in thread
From: sl @ 2021-10-22  1:58 UTC (permalink / raw)
  To: 9front

> not used anywhere except for cpu(1), oexportfs(4), and
> import(4).

so this change would mean 9front users can no longer cpu
or import with plan 9 from bell labs or 9legacy machines?

sl

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [9front] intent to delete: devssl, cpu, oexportfs, import
  2021-10-22  1:58 ` sl
@ 2021-10-22  2:26   ` ori
  2021-10-22  2:44     ` Stanley Lieber
  2021-10-22 20:26   ` Stuart Morrow
  1 sibling, 1 reply; 20+ messages in thread
From: ori @ 2021-10-22  2:26 UTC (permalink / raw)
  To: 9front

Quoth sl@stanleylieber.com:
> > not used anywhere except for cpu(1), oexportfs(4), and
> > import(4).
> 
> so this change would mean 9front users can no longer cpu
> or import with plan 9 from bell labs or 9legacy machines?
> 
> sl

Correct.

I'd like to interoperate, but SSL3 is broken. I don't think
we should drag around broken protocols for eternity.

If you patch 9legacy's cpu listener to use devtls instead of
devssl, then the corresponding cpu(1) patch should be easy. 
I think this is the best option.


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [9front] intent to delete: devssl, cpu, oexportfs, import
  2021-10-22  2:26   ` ori
@ 2021-10-22  2:44     ` Stanley Lieber
  2021-10-22 10:19       ` Philip Silva
  0 siblings, 1 reply; 20+ messages in thread
From: Stanley Lieber @ 2021-10-22  2:44 UTC (permalink / raw)
  To: 9front

On October 22, 2021 2:26:06 AM UTC, ori@eigenstate.org wrote:
>Quoth sl@stanleylieber.com:
>> > not used anywhere except for cpu(1), oexportfs(4), and
>> > import(4).
>> 
>> so this change would mean 9front users can no longer cpu
>> or import with plan 9 from bell labs or 9legacy machines?
>> 
>> sl
>
>Correct.
>
>I'd like to interoperate, but SSL3 is broken. I don't think
>we should drag around broken protocols for eternity.
>
>If you patch 9legacy's cpu listener to use devtls instead of
>devssl, then the corresponding cpu(1) patch should be easy. 
>I think this is the best option.
>
>

just wanted to makes sure this was clear for viewers watching at home.

sl

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [9front] intent to delete: devssl, cpu, oexportfs, import
  2021-10-22  2:44     ` Stanley Lieber
@ 2021-10-22 10:19       ` Philip Silva
  2021-10-22 15:32         ` ori
  0 siblings, 1 reply; 20+ messages in thread
From: Philip Silva @ 2021-10-22 10:19 UTC (permalink / raw)
  To: 9front

That would be a pity to remove interoperability although SSL 3.0 is probably not so good. But I wonder, isn't it possible to just remove the SSL 3.0? Also in the patch list of 9legacy, there seems to be a set of patches for TLS 1.2 for devtls. Not knowing so much about the internals anyway, I thought that cpu'ing (or at least drawterm'ing) to 9legacy was unencrypted anyway.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [9front] intent to delete: devssl, cpu, oexportfs, import
  2021-10-22  1:48 [9front] intent to delete: devssl, cpu, oexportfs, import ori
  2021-10-22  1:58 ` sl
@ 2021-10-22 11:43 ` kemal
  2021-10-22 14:31   ` kemal
  1 sibling, 1 reply; 20+ messages in thread
From: kemal @ 2021-10-22 11:43 UTC (permalink / raw)
  To: 9front

> SSL 3.0 is implemented by devssl.

also by devtls and tlshand. we have to scrap SSL3 from there first.

> not used anywhere except for cpu(1), oexportfs(4), and
> import(4).

as sl said, this change means that 9front machines can longer
cpu/import to bell labs plan 9 machines.

considering all tls/ssl programs use devtls+tlshand, it would be
better to just remove SSL3 from those and keep devssl for the
legacy cpu protocol.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [9front] intent to delete: devssl, cpu, oexportfs, import
  2021-10-22 11:43 ` kemal
@ 2021-10-22 14:31   ` kemal
  2021-10-22 14:36     ` kemal
  2021-10-23 11:18     ` kemal
  0 siblings, 2 replies; 20+ messages in thread
From: kemal @ 2021-10-22 14:31 UTC (permalink / raw)
  To: 9front

[-- Attachment #1: Type: text/plain, Size: 354 bytes --]

> > SSL 3.0 is implemented by devssl.
>
> also by devtls and tlshand. we have to scrap SSL3 from there first.
>

oops, i didn't see that you mentioned libsec in the mail, i read the mail
too quickly. sorry.

also, i made a diff that removes SSL3 from devtls and tlshand. it's attached.
i didn't test the diff throughly, so it might be buggy. i hope not.

[-- Attachment #2: diff.txt --]
[-- Type: text/plain, Size: 16737 bytes --]

diff e54b6c6cbd4d82d70ddb4932aeafb0b028cd71f5 uncommitted
--- a//sys/man/2/pushtls
+++ b//sys/man/2/pushtls
@@ -1,6 +1,6 @@
 .TH PUSHTLS 2
 .SH NAME
-pushtls, tlsClient, tlsServer, initThumbprints, freeThumbprints, okThumbprint, okCertificate, readcert, readcertchain \- attach TLS1 or SSL3 encryption to a communication channel
+pushtls, tlsClient, tlsServer, initThumbprints, freeThumbprints, okThumbprint, okCertificate, readcert, readcertchain \- attach TLS encryption to a communication channel
 .SH SYNOPSIS
 .B #include <u.h>
 .br
@@ -45,8 +45,6 @@
 and a handshake protocol,
 doing initial authentication and secret creation at
 user level and then starting a data channel in the record protocol.
-TLS is nearly the same as SSL 3.0, and the software should interoperate
-with implementations of either standard.
 .PP
 To use just the record layer, as described in
 .IR tls (3),
--- a//sys/man/3/tls
+++ b//sys/man/3/tls
@@ -1,6 +1,6 @@
 .TH TLS 3 
 .SH NAME
-tls \- TLS and SSL3 record layer
+tls \- TLS record layer
 .SH SYNOPSIS
 .nf
 .B bind -a #a /net
@@ -16,10 +16,9 @@
 .BI /net/tls/ n /status
 .fi
 .SH DESCRIPTION
-The TLS device implements the record layer protocols
-of Transport Layer Security version 1.0-1.2 and Secure Sockets Layer version 3.0.
-It does not implement the handshake protocols, which are responsible for
-mutual authentication and key exchange.
+The TLS device implements the record layer protocols of Transport Layer Security
+version 1.0-1.2. It does not implement the handshake protocols, which are responsible
+for mutual authentication and key exchange.
 The
 .I tls
 device can be thought of as filters providing optional encryption and anti-tampering.
@@ -53,13 +52,11 @@
 .I vers
 format records, but incoming messages of either version are accepted.
 Valid versions are
-.B 0x300
-for SSLv3.0 and
 .BR 0x301 ,
 .B 0x302
 and
 .B 0x303
-for TLSv1.0 (which could be known as SSLv3.01), TLSv1.1 and TLSv1.2.
+for TLSv1.0, TLSv1.1 and TLSv1.2.
 This command must be issued before any other command
 and before reading or writing any messages;
 it may only be executed once.
@@ -120,10 +117,9 @@
 .TP
 .BI alert \ alertno
 Send an alert message.
-.I Alertno
-may be a valid alert code for either SSLv3.0 or TLS,
-and is mapped to an appropriate code for the protocol in use.
-If it is a fatal alert, the filter is set into an error state.
+If
+.I alertno
+is a fatal alert, the filter is set into an error state.
 .PP
 Application messages and handshake messages are communicated using
 .I data
--- a//sys/src/libsec/port/tlshand.c
+++ b//sys/src/libsec/port/tlshand.c
@@ -8,14 +8,13 @@
 //		client/server - main handshake protocol definition
 //		message functions - formating handshake messages
 //		cipher choices - catalog of digest and encrypt algorithms
-//		security functions - PKCS#1, sslHMAC, session keygen
+//		security functions - PKCS#1, session keygen
 //		general utility functions - malloc, serialization
-// The handshake protocol builds on the TLS/SSL3 record layer protocol,
-// which is implemented in kernel device #a.  See also /lib/rfc/rfc2246.
+// The handshake protocol builds on the TLS record layer protocol,
+// which is implemented in kernel device #a.  See also /lib/rfc/rfc5246.
 
 enum {
-	TLSFinishedLen = 12,
-	SSL3FinishedLen = MD5dlen+SHA1dlen,
+	FinishedLen = 12,
 	MaxKeyData = 160,	// amount of secret we may need
 	MAXdlen = SHA2_512dlen,
 	RandomSize = 32,
@@ -47,11 +46,6 @@
 	void (*init)(mpint *p, mpint *a, mpint *b, mpint *x, mpint *y, mpint *n, mpint *h);
 } Namedcurve;
 
-typedef struct Finished{
-	uchar verify[SSL3FinishedLen];
-	int n;
-} Finished;
-
 typedef struct HandshakeHash {
 	MD5state	md5;
 	SHAstate	sha1;
@@ -81,7 +75,6 @@
 	// byte generation and handshake checksum
 	void (*prf)(uchar*, int, uchar*, int, char*, uchar*, int);
 	void (*setFinished)(TlsSec*, HandshakeHash, uchar*, int);
-	int nfin;
 };
 
 typedef struct TlsConnection{
@@ -99,7 +92,7 @@
 
 	// for finished messages
 	HandshakeHash	handhash;
-	Finished	finished;
+	uchar		finished[FinishedLen];
 
 	uchar *sendp;
 	uchar buf[1<<16];
@@ -152,18 +145,17 @@
 			int sigalg;
 			Bytes *signature;
 		} certificateVerify;		
-		Finished finished;
+		uchar finished[FinishedLen];
 	} u;
 } Msg;
 
 
 enum {
-	SSL3Version	= 0x0300,
 	TLS10Version	= 0x0301,
 	TLS11Version	= 0x0302,
 	TLS12Version	= 0x0303,
 	ProtocolVersion	= TLS12Version,	// maximum version we speak
-	MinProtoVersion	= 0x0300,	// limits on version we accept
+	MinProtoVersion	= 0x0301,	// limits on version we accept
 	MaxProtoVersion	= 0x03ff,
 };
 
@@ -172,7 +164,6 @@
 	HHelloRequest,
 	HClientHello,
 	HServerHello,
-	HSSL2ClientHello = 9,  /* local convention;  see devtls.c */
 	HCertificate = 11,
 	HServerKeyExchange,
 	HCertificateRequest,
@@ -192,7 +183,6 @@
 	ERecordOverflow = 22,
 	EDecompressionFailure = 30,
 	EHandshakeFailure = 40,
-	ENoCertificate = 41,
 	EBadCertificate = 42,
 	EUnsupportedCertificate = 43,
 	ECertificateRevoked = 44,
@@ -367,7 +357,6 @@
 #pragma	varargck argpos	tlsError 3
 static int setVersion(TlsConnection *c, int version);
 static int setSecrets(TlsConnection *c, int isclient);
-static int finishedMatch(TlsConnection *c, Finished *f);
 static void tlsConnectionFree(TlsConnection *c);
 
 static int isDHE(int tlsid);
@@ -394,7 +383,6 @@
 static Bytes*	tlsSecDHEc(TlsSec *sec, Bytes *p, Bytes *g, Bytes *Ys);
 static Bytes*	tlsSecECDHEc(TlsSec *sec, int curve, Bytes *Ys);
 static void	tlsSecVers(TlsSec *sec, int v);
-static int	tlsSecFinished(TlsSec *sec, HandshakeHash hsh, uchar *fin, int nfin, int isclient);
 static void	setMasterSecret(TlsSec *sec, Bytes *pm);
 static int	digestDHparams(TlsSec *sec, Bytes *par, uchar digest[MAXdlen], int sigalg);
 static char*	verifyDHparams(TlsSec *sec, Bytes *par, Bytes *cert, Bytes *sig, int sigalg);
@@ -511,28 +499,26 @@
 	}
 
 	// Elliptic Curves (also called Supported Groups)
-	if(ProtocolVersion >= TLS10Version){
-		m = p - b;
-		b = erealloc(b, m + 2+2+2+nelem(namedcurves)*2 + 2+2+1+nelem(pointformats));
-		p = b + m;
+	m = p - b;
+	b = erealloc(b, m + 2+2+2+nelem(namedcurves)*2 + 2+2+1+nelem(pointformats));
+	p = b + m;
 
-		n = nelem(namedcurves);
-		put16(p, Extec), p += 2;	/* Type: elliptic_curves / supported_groups */
-		put16(p, (n+1)*2), p += 2;	/* Length */
-		put16(p, n*2), p += 2;		/* Elliptic Curves Length */
-		for(i=0; i < n; i++){		/* Elliptic Curves */
-			put16(p, namedcurves[i].tlsid);
-			p += 2;
-		}
-
-		n = nelem(pointformats);
-		put16(p, Extecp), p += 2;	/* Type: ec_point_formats */
-		put16(p, n+1), p += 2;		/* Length */
-		*p++ = n;			/* EC point formats Length */
-		for(i=0; i < n; i++)		/* EC point formats */
-			*p++ = pointformats[i];
+	n = nelem(namedcurves);
+	put16(p, Extec), p += 2;	/* Type: elliptic_curves / supported_groups */
+	put16(p, (n+1)*2), p += 2;	/* Length */
+	put16(p, n*2), p += 2;		/* Elliptic Curves Length */
+	for(i=0; i < n; i++){		/* Elliptic Curves */
+		put16(p, namedcurves[i].tlsid);
+		p += 2;
 	}
 
+	n = nelem(pointformats);
+	put16(p, Extecp), p += 2;	/* Type: ec_point_formats */
+	put16(p, n+1), p += 2;		/* Length */
+	*p++ = n;			/* EC point formats Length */
+	for(i=0; i < n; i++)		/* EC point formats */
+		*p++ = pointformats[i];
+
 	// signature algorithms
 	if(ProtocolVersion >= TLS12Version){
 		n = nelem(sigalgs);
@@ -849,10 +835,7 @@
 	}
 
 	/* no CertificateVerify; skip to Finished */
-	if(tlsSecFinished(c->sec, c->handhash, c->finished.verify, c->finished.n, 1) < 0){
-		tlsError(c, EInternalError, "can't set finished: %r");
-		goto Err;
-	}
+	(*c->sec->setFinished)(c->sec, c->handhash, c->finished, 1);
 	if(!msgRecv(c, &m))
 		goto Err;
 	if(m.tag != HFinished) {
@@ -859,7 +842,7 @@
 		tlsError(c, EUnexpectedMessage, "expected a finished");
 		goto Err;
 	}
-	if(!finishedMatch(c, &m.u.finished)) {
+	if(tsmemcmp(c->finished, m.u.finished, FinishedLen) != 0) {
 		tlsError(c, EHandshakeFailure, "finished verification failed");
 		goto Err;
 	}
@@ -871,12 +854,9 @@
 		goto Err;
 	}
 
-	if(tlsSecFinished(c->sec, c->handhash, c->finished.verify, c->finished.n, 0) < 0){
-		tlsError(c, EInternalError, "can't set finished: %r");
-		goto Err;
-	}
+	(*c->sec->setFinished)(c->sec, c->handhash, c->finished, 0);
 	m.tag = HFinished;
-	m.u.finished = c->finished;
+	memmove(m.u.finished, c->finished, FinishedLen);
 	if(!msgSend(c, &m, AFlush))
 		goto Err;
 	if(trace)
@@ -1220,21 +1200,15 @@
 
 	// Cipherchange must occur immediately before Finished to avoid
 	// potential hole;  see section 4.3 of Wagner Schneier 1996.
-	if(tlsSecFinished(c->sec, c->handhash, c->finished.verify, c->finished.n, 1) < 0){
-		tlsError(c, EInternalError, "can't set finished 1: %r");
-		goto Err;
-	}
+	(*c->sec->setFinished)(c->sec, c->handhash, c->finished, 1);
 	m.tag = HFinished;
-	m.u.finished = c->finished;
+	memmove(m.u.finished, c->finished, FinishedLen);
 	if(!msgSend(c, &m, AFlush)) {
 		tlsError(c, EInternalError, "can't flush after client Finished: %r");
 		goto Err;
 	}
 
-	if(tlsSecFinished(c->sec, c->handhash, c->finished.verify, c->finished.n, 0) < 0){
-		tlsError(c, EInternalError, "can't set finished 0: %r");
-		goto Err;
-	}
+	(*c->sec->setFinished)(c->sec, c->handhash, c->finished, 0);
 	if(!msgRecv(c, &m)) {
 		tlsError(c, EInternalError, "can't read server Finished: %r");
 		goto Err;
@@ -1244,7 +1218,7 @@
 		goto Err;
 	}
 
-	if(!finishedMatch(c, &m.u.finished)) {
+	if(tsmemcmp(c->finished, m.u.finished, FinishedLen) != 0) {
 		tlsError(c, EHandshakeFailure, "finished verification failed");
 		goto Err;
 	}
@@ -1418,16 +1392,16 @@
 			goto Overflow;
 		if(isECDHE(c->cipher))
 			*p++ = n;
-		else if(isDHE(c->cipher) || c->version != SSL3Version)
+		else if(isDHE(c->cipher))
 			put16(p, n), p += 2;
 		memmove(p, m->u.clientKeyExchange.key->data, n);
 		p += n;
 		break;
 	case HFinished:
-		if(p+m->u.finished.n > e)
+		if(p+FinishedLen > e)
 			goto Overflow;
-		memmove(p, m->u.finished.verify, m->u.finished.n);
-		p += m->u.finished.n;
+		memmove(p, m->u.finished, FinishedLen);
+		p += FinishedLen;
 		break;
 	}
 
@@ -1495,50 +1469,6 @@
 		}
 	}
 
-	if(type == HSSL2ClientHello){
-		/* Cope with an SSL3 ClientHello expressed in SSL2 record format.
-			This is sent by some clients that we must interoperate
-			with, such as Java's JSSE and Microsoft's Internet Explorer. */
-		int nsid, nrandom, nciph;
-
-		p = tlsReadN(c, n);
-		if(p == nil)
-			return 0;
-		msgHash(c, p, n);
-		m->tag = HClientHello;
-		if(n < 22)
-			goto Short;
-		m->u.clientHello.version = get16(p+1);
-		p += 3;
-		n -= 3;
-		nn = get16(p); /* cipher_spec_len */
-		nsid = get16(p + 2);
-		nrandom = get16(p + 4);
-		p += 6;
-		n -= 6;
-		if(nsid != 0 	/* no sid's, since shouldn't restart using ssl2 header */
-		|| nrandom < 16 || nn % 3 || n - nrandom < nn)
-			goto Err;
-		/* ignore ssl2 ciphers and look for {0x00, ssl3 cipher} */
-		nciph = 0;
-		for(i = 0; i < nn; i += 3)
-			if(p[i] == 0)
-				nciph++;
-		m->u.clientHello.ciphers = newints(nciph);
-		nciph = 0;
-		for(i = 0; i < nn; i += 3)
-			if(p[i] == 0)
-				m->u.clientHello.ciphers->data[nciph++] = get16(&p[i + 1]);
-		p += nn;
-		m->u.clientHello.sid = makebytes(nil, 0);
-		if(nrandom > RandomSize)
-			nrandom = RandomSize;
-		memset(m->u.clientHello.random, 0, RandomSize - nrandom);
-		memmove(&m->u.clientHello.random[RandomSize - nrandom], p, nrandom);
-		m->u.clientHello.compressors = newbytes(1);
-		m->u.clientHello.compressors->data[0] = CompressionNull;
-		goto Ok;
-	}
 	msgHash(c, p, 4);
 
 	p = tlsReadN(c, n);
@@ -1790,7 +1720,7 @@
 			goto Short;
 		if(isECDHE(c->cipher))
 			nn = *p++, n--;
-		else if(isDHE(c->cipher) || c->version != SSL3Version)
+		else if(isDHE(c->cipher))
 			nn = get16(p), p += 2, n -= 2;
 		else
 			nn = n;
@@ -1800,17 +1730,16 @@
 		n -= nn;
 		break;
 	case HFinished:
-		m->u.finished.n = c->finished.n;
-		if(n < m->u.finished.n)
+		if(n < FinishedLen)
 			goto Short;
-		memmove(m->u.finished.verify, p, m->u.finished.n);
-		n -= m->u.finished.n;
+		memmove(m->u.finished, p, FinishedLen);
+		n -= FinishedLen;
 		break;
 	}
 
 	if(n != 0 && type != HClientHello && type != HServerHello)
 		goto Short;
-Ok:
+
 	if(c->trace)
 		c->trace("recv %s", msgPrint((char*)c->sendp, &c->buf[sizeof(c->buf)] - c->sendp, m));
 	return 1;
@@ -2000,8 +1929,8 @@
 		break;
 	case HFinished:
 		bs = seprint(bs, be, "HFinished\n");
-		for(i=0; i<m->u.finished.n; i++)
-			bs = seprint(bs, be, "%.2x", m->u.finished.verify[i]);
+		for(i=0; i<FinishedLen; i++)
+			bs = seprint(bs, be, "%.2x", m->u.finished[i]);
 		bs = seprint(bs, be, "\n");
 		break;
 	}
@@ -2036,23 +1965,11 @@
 		return -1;
 	if(version > c->version)
 		version = c->version;
-	if(version == SSL3Version) {
+	else
 		c->version = version;
-		c->finished.n = SSL3FinishedLen;
-	}else {
-		c->version = version;
-		c->finished.n = TLSFinishedLen;
-	}
 	return fprint(c->ctl, "version 0x%x", version);
 }
 
-// confirm that received Finished message matches the expected value
-static int
-finishedMatch(TlsConnection *c, Finished *f)
-{
-	return tsmemcmp(f->verify, c->finished.verify, f->n) == 0;
-}
-
 // free memory associated with TlsConnection struct
 //		(but don't close the TLS channel itself)
 static void
@@ -2390,68 +2307,6 @@
 		hmac_sha2_256, SHA2_256dlen);
 }
 
-static void
-sslPRF(uchar *buf, int nbuf, uchar *key, int nkey, char *label, uchar *seed, int nseed)
-{
-	uchar sha1dig[SHA1dlen], md5dig[MD5dlen], tmp[26];
-	DigestState *s;
-	int i, n, len;
-
-	USED(label);
-	len = 1;
-	while(nbuf > 0){
-		if(len > 26)
-			return;
-		for(i = 0; i < len; i++)
-			tmp[i] = 'A' - 1 + len;
-		s = sha1(tmp, len, nil, nil);
-		s = sha1(key, nkey, nil, s);
-		sha1(seed, nseed, sha1dig, s);
-		s = md5(key, nkey, nil, nil);
-		md5(sha1dig, SHA1dlen, md5dig, s);
-		n = MD5dlen;
-		if(n > nbuf)
-			n = nbuf;
-		memmove(buf, md5dig, n);
-		buf += n;
-		nbuf -= n;
-		len++;
-	}
-}
-
-static void
-sslSetFinished(TlsSec *sec, HandshakeHash hsh, uchar *finished, int isclient)
-{
-	DigestState *s;
-	uchar h0[MD5dlen], h1[SHA1dlen], pad[48];
-	char *label;
-
-	if(isclient)
-		label = "CLNT";
-	else
-		label = "SRVR";
-
-	md5((uchar*)label, 4, nil, &hsh.md5);
-	md5(sec->sec, MasterSecretSize, nil, &hsh.md5);
-	memset(pad, 0x36, 48);
-	md5(pad, 48, nil, &hsh.md5);
-	md5(nil, 0, h0, &hsh.md5);
-	memset(pad, 0x5C, 48);
-	s = md5(sec->sec, MasterSecretSize, nil, nil);
-	s = md5(pad, 48, nil, s);
-	md5(h0, MD5dlen, finished, s);
-
-	sha1((uchar*)label, 4, nil, &hsh.sha1);
-	sha1(sec->sec, MasterSecretSize, nil, &hsh.sha1);
-	memset(pad, 0x36, 40);
-	sha1(pad, 40, nil, &hsh.sha1);
-	sha1(nil, 0, h1, &hsh.sha1);
-	memset(pad, 0x5C, 40);
-	s = sha1(sec->sec, MasterSecretSize, nil, nil);
-	s = sha1(pad, 40, nil, s);
-	sha1(h1, SHA1dlen, finished + MD5dlen, s);
-}
-
 // fill "finished" arg with md5(args)^sha1(args)
 static void
 tls10SetFinished(TlsSec *sec, HandshakeHash hsh, uchar *finished, int isclient)
@@ -2460,6 +2315,8 @@
 	char *label;
 
 	// get current hash value, but allow further messages to be hashed in
+	hsh.md5.malloced = 0;
+	hsh.sha1.malloced = 0;
 	md5(nil, 0, h, &hsh.md5);
 	sha1(nil, 0, h+MD5dlen, &hsh.sha1);
 
@@ -2467,7 +2324,7 @@
 		label = "client finished";
 	else
 		label = "server finished";
-	tls10PRF(finished, TLSFinishedLen, sec->sec, MasterSecretSize, label, h, sizeof(h));
+	tls10PRF(finished, FinishedLen, sec->sec, MasterSecretSize, label, h, sizeof(h));
 }
 
 static void
@@ -2477,6 +2334,7 @@
 	char *label;
 
 	// get current hash value, but allow further messages to be hashed in
+	hsh.sha2_256.malloced = 0;
 	sha2_256(nil, 0, seed, &hsh.sha2_256);
 
 	if(isclient)
@@ -2483,7 +2341,7 @@
 		label = "client finished";
 	else
 		label = "server finished";
-	tls12PRF(finished, TLSFinishedLen, sec->sec, MasterSecretSize, label, seed, SHA2_256dlen);
+	tls12PRF(finished, FinishedLen, sec->sec, MasterSecretSize, label, seed, SHA2_256dlen);
 }
 
 static void
@@ -2630,34 +2488,14 @@
 	return epm;
 }
 
-static int
-tlsSecFinished(TlsSec *sec, HandshakeHash hsh, uchar *fin, int nfin, int isclient)
-{
-	if(sec->nfin != nfin){
-		werrstr("invalid finished exchange");
-		return -1;
-	}
-	hsh.md5.malloced = 0;
-	hsh.sha1.malloced = 0;
-	hsh.sha2_256.malloced = 0;
-	(*sec->setFinished)(sec, hsh, fin, isclient);
-	return 0;
-}
-
 static void
 tlsSecVers(TlsSec *sec, int v)
 {
-	if(v == SSL3Version){
-		sec->setFinished = sslSetFinished;
-		sec->nfin = SSL3FinishedLen;
-		sec->prf = sslPRF;
-	}else if(v < TLS12Version) {
+	if(v < TLS12Version){
 		sec->setFinished = tls10SetFinished;
-		sec->nfin = TLSFinishedLen;
 		sec->prf = tls10PRF;
-	}else {
+	}else{
 		sec->setFinished = tls12SetFinished;
-		sec->nfin = TLSFinishedLen;
 		sec->prf = tls12PRF;
 	}
 }

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [9front] intent to delete: devssl, cpu, oexportfs, import
  2021-10-22 14:31   ` kemal
@ 2021-10-22 14:36     ` kemal
  2021-10-23 15:47       ` ori
  2021-10-23 11:18     ` kemal
  1 sibling, 1 reply; 20+ messages in thread
From: kemal @ 2021-10-22 14:36 UTC (permalink / raw)
  To: 9front

[-- Attachment #1: Type: text/plain, Size: 196 bytes --]

> also, i made a diff that removes SSL3 from devtls and tlshand. it's attached.
> i didn't test the diff throughly, so it might be buggy. i hope not.

forgot to include the diff for devtls, ughhh

[-- Attachment #2: diff.txt --]
[-- Type: text/plain, Size: 14443 bytes --]

diff e54b6c6cbd4d82d70ddb4932aeafb0b028cd71f5 uncommitted
--- a//sys/src/9/port/devtls.c
+++ b//sys/src/9/port/devtls.c
@@ -1,5 +1,5 @@
 /*
- *  devtls - record layer for transport layer security 1.2 and secure sockets layer 3.0
+ *  devtls - record layer for transport layer security 1.0-1.2
  */
 #include	"u.h"
 #include	"../port/lib.h"
@@ -24,11 +24,10 @@
 	MaxMacLen	= SHA2_256dlen,
 
 	/* protocol versions we can accept */
-	SSL3Version	= 0x0300,
 	TLS10Version	= 0x0301,
 	TLS11Version	= 0x0302,
 	TLS12Version	= 0x0303,
-	MinProtoVersion	= 0x0300,	/* limits on version we accept */
+	MinProtoVersion	= 0x0301,	/* limits on version we accept */
 	MaxProtoVersion	= 0x03ff,
 
 	/* connection states */
@@ -46,9 +45,6 @@
 	RHandshake,
 	RApplication,
 
-	SSL2ClientHello = 1,
-	HSSL2ClientHello = 9,  /* local convention;  see tlshand.c */
-
 	/* alerts */
 	ECloseNotify 			= 0,
 	EUnexpectedMessage 	= 10,
@@ -57,7 +53,6 @@
 	ERecordOverflow 		= 22,
 	EDecompressionFailure 	= 30,
 	EHandshakeFailure 		= 40,
-	ENoCertificate 			= 41,
 	EBadCertificate 		= 42,
 	EUnsupportedCertificate 	= 43,
 	ECertificateRevoked 		= 44,
@@ -89,7 +84,6 @@
 
 	int		(*enc)(Secret*, uchar*, int);
 	int		(*dec)(Secret*, uchar*, int);
-	int		(*unpad)(uchar*, int, int);
 	DigestState*	(*mac)(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
 
 	int		block;		/* encryption block len, 0 if none */
@@ -125,12 +119,6 @@
 	int		state;
 	int		debug;
 
-	/*
-	 * function to genrate authenticated data blob for different
-	 * protocol versions
-	 */
-	int		(*packAAD)(u64int, uchar*, uchar*);
-
 	/* input side -- protected by in.io */
 	OneWay		in;
 	Block		*processed;	/* next bunch of application data */
@@ -153,37 +141,34 @@
 
 struct TlsErrs{
 	int	err;
-	int	sslerr;
-	int	tlserr;
 	int	fatal;
 	char	*msg;
 };
 
 static TlsErrs tlserrs[] = {
-	{ECloseNotify,			ECloseNotify,			ECloseNotify,			0, 	"close notify"},
-	{EUnexpectedMessage,	EUnexpectedMessage,	EUnexpectedMessage, 	1, "unexpected message"},
-	{EBadRecordMac,		EBadRecordMac,		EBadRecordMac, 		1, "bad record mac"},
-	{EDecryptionFailed,		EIllegalParameter,		EDecryptionFailed,		1, "decryption failed"},
-	{ERecordOverflow,		EIllegalParameter,		ERecordOverflow,		1, "record too long"},
-	{EDecompressionFailure,	EDecompressionFailure,	EDecompressionFailure,	1, "decompression failed"},
-	{EHandshakeFailure,		EHandshakeFailure,		EHandshakeFailure,		1, "could not negotiate acceptable security parameters"},
-	{ENoCertificate,		ENoCertificate,			ECertificateUnknown,	1, "no appropriate certificate available"},
-	{EBadCertificate,		EBadCertificate,		EBadCertificate,		1, "corrupted or invalid certificate"},
-	{EUnsupportedCertificate,	EUnsupportedCertificate,	EUnsupportedCertificate,	1, "unsupported certificate type"},
-	{ECertificateRevoked,	ECertificateRevoked,		ECertificateRevoked,		1, "revoked certificate"},
-	{ECertificateExpired,		ECertificateExpired,		ECertificateExpired,		1, "expired certificate"},
-	{ECertificateUnknown,	ECertificateUnknown,	ECertificateUnknown,	1, "unacceptable certificate"},
-	{EIllegalParameter,		EIllegalParameter,		EIllegalParameter,		1, "illegal parameter"},
-	{EUnknownCa,			EHandshakeFailure,		EUnknownCa,			1, "unknown certificate authority"},
-	{EAccessDenied,		EHandshakeFailure,		EAccessDenied,		1, "access denied"},
-	{EDecodeError,			EIllegalParameter,		EDecodeError,			1, "error decoding message"},
-	{EDecryptError,			EIllegalParameter,		EDecryptError,			1, "error decrypting message"},
-	{EExportRestriction,		EHandshakeFailure,		EExportRestriction,		1, "export restriction violated"},
-	{EProtocolVersion,		EIllegalParameter,		EProtocolVersion,		1, "protocol version not supported"},
-	{EInsufficientSecurity,	EHandshakeFailure,		EInsufficientSecurity,	1, "stronger security routines required"},
-	{EInternalError,			EHandshakeFailure,		EInternalError,			1, "internal error"},
-	{EUserCanceled,		ECloseNotify,			EUserCanceled,			0, "handshake canceled by user"},
-	{ENoRenegotiation,		EUnexpectedMessage,	ENoRenegotiation,		0, "no renegotiation"},
+	{ECloseNotify,			0, "close notify"},
+	{EUnexpectedMessage,		1, "unexpected message"},
+	{EBadRecordMac,			1, "bad record mac"},
+	{EDecryptionFailed,		1, "decryption failed"},
+	{ERecordOverflow,		1, "record too long"},
+	{EDecompressionFailure,		1, "decompression failed"},
+	{EHandshakeFailure,		1, "could not negotiate acceptable security parameters"},
+	{EBadCertificate,		1, "corrupted or invalid certificate"},
+	{EUnsupportedCertificate,	1, "unsupported certificate type"},
+	{ECertificateRevoked,		1, "revoked certificate"},
+	{ECertificateExpired,		1, "expired certificate"},
+	{ECertificateUnknown,		1, "unacceptable certificate"},
+	{EIllegalParameter,		1, "illegal parameter"},
+	{EUnknownCa,			1, "unknown certificate authority"},
+	{EAccessDenied,			1, "access denied"},
+	{EDecodeError,			1, "error decoding message"},
+	{EDecryptError,			1, "error decrypting message"},
+	{EExportRestriction,		1, "export restriction violated"},
+	{EProtocolVersion,		1, "protocol version not supported"},
+	{EInsufficientSecurity,		1, "stronger security routines required"},
+	{EInternalError,		1, "internal error"},
+	{EUserCanceled,			0, "handshake canceled by user"},
+	{ENoRenegotiation,		0, "no renegotiation"},
 };
 
 enum
@@ -227,11 +212,8 @@
 static void	alertHand(TlsRec*, char *);
 static TlsRec	*newtls(Chan *c);
 static TlsRec	*mktlsrec(void);
-static DigestState*sslmac_md5(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
-static DigestState*sslmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
 static DigestState*nomac(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
-static int	sslPackAAD(u64int, uchar*, uchar*);
-static int	tlsPackAAD(u64int, uchar*, uchar*);
+static int	packAAD(u64int, uchar*, uchar*);
 static void	packMac(Secret*, uchar*, int, uchar*, int, uchar*);
 static void	put64(uchar *p, u64int);
 static void	put32(uchar *p, u32int);
@@ -252,8 +234,7 @@
 static int	aesgcm_aead_enc(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len);
 static int	aesgcm_aead_dec(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len);
 static int	noenc(Secret *sec, uchar *buf, int n);
-static int	sslunpad(uchar *buf, int n, int block);
-static int	tlsunpad(uchar *buf, int n, int block);
+static int	unpad(uchar *buf, int n, int block);
 static void	freeSec(Secret *sec);
 static char	*tlsstate(int s);
 static void	pdump(int, void*, char*);
@@ -749,20 +730,10 @@
 if(tr->debug)pprint("consumed %d header\n", RecHdrLen);
 	nconsumed = RecHdrLen;
 
-	if((tr->handin == 0) && (header[0] & 0x80)){
-		/* Cope with an SSL3 ClientHello expressed in SSL2 record format.
-			This is sent by some clients that we must interoperate
-			with, such as Java's JSSE and Microsoft's Internet Explorer. */
-		len = (get16(header) & ~0x8000) - 3;
-		type = header[2];
-		ver = get16(header + 3);
-		if(type != SSL2ClientHello || len < 22)
-			rcvError(tr, EProtocolVersion, "invalid initial SSL2-like message");
-	}else{  /* normal SSL3 record format */
-		type = header[0];
-		ver = get16(header+1);
-		len = get16(header+3);
-	}
+	type = header[0];
+	ver = get16(header+1);
+	len = get16(header+3);
+
 	if(ver != tr->version && (tr->verset || ver < MinProtoVersion || ver > MaxProtoVersion))
 		rcvError(tr, EProtocolVersion, "devtls expected ver=%x%s, saw (len=%d) type=%x ver=%x '%.12s'",
 			tr->version, tr->verset?"/set":"", len, type, ver, (char*)header);
@@ -823,7 +794,7 @@
 
 		/* update length */
 		put16(header+3, len);
-		aadlen = (*tr->packAAD)(in->seq++, header, aad);
+		aadlen = packAAD(in->seq++, header, aad);
 		if(sec->aead_dec != nil) {
 			len = (*sec->aead_dec)(sec, aad, aadlen, p - ivlen, p, unpad_len);
 			if(len < 0)
@@ -916,42 +887,12 @@
 			dechandq(tr);
 		}else{
 			unlock(&tr->hqlock);
-			if(tr->verset && tr->version != SSL3Version && !waserror()){
+			if(tr->verset && !waserror()){
 				sendAlert(tr, ENoRenegotiation);
 				poperror();
 			}
 		}
 		break;
-	case SSL2ClientHello:
-		lock(&tr->hqlock);
-		if(tr->handq != nil){
-			tr->hqref++;
-			unlock(&tr->hqlock);
-			if(waserror()){
-				dechandq(tr);
-				nexterror();
-			}
-			/* Pass the SSL2 format data, so that the handshake code can compute
-				the correct checksums.  HSSL2ClientHello = HandshakeType 9 is
-				unused in RFC2246. */
-			b = padblock(b, 8);
-			b->rp[0] = RHandshake;
-			b->rp[1] = HSSL2ClientHello;
-			put24(&b->rp[2], len+3);
-			b->rp[5] = SSL2ClientHello;
-			put16(&b->rp[6], ver);
-			qbwrite(tr->handq, b);
-			b = nil;
-			poperror();
-			dechandq(tr);
-		}else{
-			unlock(&tr->hqlock);
-			if(tr->verset && tr->version != SSL3Version && !waserror()){
-				sendAlert(tr, ENoRenegotiation);
-				poperror();
-			}
-		}
-		break;
 	case RApplication:
 		if(!tr->opened)
 			rcvError(tr, EUnexpectedMessage, "application message received before handshake completed");
@@ -1314,7 +1255,7 @@
 		put16(p+3, n);
 
 		if(sec != nil){
-			aadlen = (*tr->packAAD)(out->seq++, p, aad);
+			aadlen = packAAD(out->seq++, p, aad);
 			if(sec->aead_enc != nil)
 				n = (*sec->aead_enc)(sec, aad, aadlen, p + RecHdrLen, p + RecHdrLen + ivlen, n) + ivlen;
 			else {
@@ -1390,42 +1331,34 @@
 {
 	char	*name;
 	int	maclen;
-	void	(*initkey)(Hashalg *, int, Secret *, uchar*);
+	void	(*initkey)(Hashalg *, Secret *, uchar*);
 };
 
 static void
-initmd5key(Hashalg *ha, int version, Secret *s, uchar *p)
+initmd5key(Hashalg *ha, Secret *s, uchar *p)
 {
 	s->maclen = ha->maclen;
-	if(version == SSL3Version)
-		s->mac = sslmac_md5;
-	else
-		s->mac = hmac_md5;
+	s->mac = hmac_md5;
 	memmove(s->mackey, p, ha->maclen);
 }
 
 static void
-initclearmac(Hashalg *, int, Secret *s, uchar *)
+initclearmac(Hashalg *, Secret *s, uchar *)
 {
 	s->mac = nomac;
 }
 
 static void
-initsha1key(Hashalg *ha, int version, Secret *s, uchar *p)
+initsha1key(Hashalg *ha, Secret *s, uchar *p)
 {
 	s->maclen = ha->maclen;
-	if(version == SSL3Version)
-		s->mac = sslmac_sha1;
-	else
-		s->mac = hmac_sha1;
+	s->mac = hmac_sha1;
 	memmove(s->mackey, p, ha->maclen);
 }
 
 static void
-initsha2_256key(Hashalg *ha, int version, Secret *s, uchar *p)
+initsha2_256key(Hashalg *ha, Secret *s, uchar *p)
 {
-	if(version == SSL3Version)
-		error("sha256 cannot be used with SSL");
 	s->maclen = ha->maclen;
 	s->mac = hmac_sha2_256;
 	memmove(s->mackey, p, ha->maclen);
@@ -1641,10 +1574,6 @@
 		m = strtol(cb->f[1], nil, 0);
 		if(m < MinProtoVersion || m > MaxProtoVersion)
 			error("unsupported version");
-		if(m == SSL3Version)
-			tr->packAAD = sslPackAAD;
-		else
-			tr->packAAD = tlsPackAAD;
 		tr->verset = 1;
 		tr->version = m;
 	}else if(strcmp(cb->f[0], "secret") == 0){
@@ -1685,8 +1614,8 @@
 		if(!ha->initkey || !ea->initkey)
 			error("misimplemented secret algorithm");
 
-		(*ha->initkey)(ha, tr->version, tos, &x[0]);
-		(*ha->initkey)(ha, tr->version, toc, &x[ha->maclen]);
+		(*ha->initkey)(ha, tos, &x[0]);
+		(*ha->initkey)(ha, toc, &x[ha->maclen]);
 		(*ea->initkey)(ea, tos, &x[2 * ha->maclen], &x[2 * ha->maclen + 2 * ea->keylen]);
 		(*ea->initkey)(ea, toc, &x[2 * ha->maclen + ea->keylen], &x[2 * ha->maclen + 2 * ea->keylen + ea->ivlen]);
 
@@ -1701,13 +1630,6 @@
 			tr->in.new = toc;
 			tr->out.new = tos;
 		}
-		if(tr->version == SSL3Version){
-			toc->unpad = sslunpad;
-			tos->unpad = sslunpad;
-		}else{
-			toc->unpad = tlsunpad;
-			tos->unpad = tlsunpad;
-		}
 		toc->encalg = ea->name;
 		toc->hashalg = ha->name;
 		tos->encalg = ea->name;
@@ -1879,17 +1801,12 @@
 if(tr->debug)pprint("sendAlert %d\n", err);
 	fatal = 1;
 	msg = "tls unknown alert";
-	for(i=0; i < nelem(tlserrs); i++) {
-		if(tlserrs[i].err == err) {
+	for(i=0; i < nelem(tlserrs); i++)
+		if(tlserrs[i].err == err){
 			msg = tlserrs[i].msg;
-			if(tr->version == SSL3Version)
-				err = tlserrs[i].sslerr;
-			else
-				err = tlserrs[i].tlserr;
 			fatal = tlserrs[i].fatal;
 			break;
 		}
-	}
 
 	if(!waserror()){
 		b = allocb(2);
@@ -2061,7 +1978,7 @@
 }
 
 static int
-tlsunpad(uchar *buf, int n, int block)
+unpad(uchar *buf, int n, int block)
 {
 	int pad, nn;
 
@@ -2076,18 +1993,6 @@
 }
 
 static int
-sslunpad(uchar *buf, int n, int block)
-{
-	int pad, nn;
-
-	pad = buf[n - 1];
-	nn = n - 1 - pad;
-	if(nn <= 0 || n % block)
-		return -1;
-	return nn;
-}
-
-static int
 blockpad(uchar *buf, int n, int block)
 {
 	int pad, nn;
@@ -2112,7 +2017,7 @@
 des3dec(Secret *sec, uchar *buf, int n)
 {
 	des3CBCdecrypt(buf, n, sec->enckey);
-	return (*sec->unpad)(buf, n, 8);
+	return unpad(buf, n, 8);
 }
 
 static int
@@ -2127,7 +2032,7 @@
 aesdec(Secret *sec, uchar *buf, int n)
 {
 	aesCBCdecrypt(buf, n, sec->enckey);
-	return (*sec->unpad)(buf, n, 16);
+	return unpad(buf, n, 16);
 }
 
 static void
@@ -2213,71 +2118,8 @@
 	return nil;
 }
 
-/*
- * sslmac: mac calculations for ssl 3.0 only; tls 1.0 uses the standard hmac.
- */
-static DigestState*
-sslmac_x(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s,
-	DigestState*(*x)(uchar*, ulong, uchar*, DigestState*), int xlen, int padlen)
-{
-	int i;
-	uchar pad[48], innerdigest[20];
-
-	if(xlen > sizeof(innerdigest)
-	|| padlen > sizeof(pad))
-		return nil;
-
-	if(klen>64)
-		return nil;
-
-	/* first time through */
-	if(s == nil){
-		for(i=0; i<padlen; i++)
-			pad[i] = 0x36;
-		s = (*x)(key, klen, nil, nil);
-		s = (*x)(pad, padlen, nil, s);
-		if(s == nil)
-			return nil;
-	}
-
-	s = (*x)(p, len, nil, s);
-	if(digest == nil)
-		return s;
-
-	/* last time through */
-	for(i=0; i<padlen; i++)
-		pad[i] = 0x5c;
-	(*x)(nil, 0, innerdigest, s);
-	s = (*x)(key, klen, nil, nil);
-	s = (*x)(pad, padlen, nil, s);
-	(*x)(innerdigest, xlen, digest, s);
-	return nil;
-}
-
-static DigestState*
-sslmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s)
-{
-	return sslmac_x(p, len, key, klen, digest, s, sha1, SHA1dlen, 40);
-}
-
-static DigestState*
-sslmac_md5(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s)
-{
-	return sslmac_x(p, len, key, klen, digest, s, md5, MD5dlen, 48);
-}
-
 static int
-sslPackAAD(u64int seq, uchar *hdr, uchar *aad)
-{
-	put64(aad, seq);
-	aad[8] = hdr[0];
-	aad[9] = hdr[3];
-	aad[10] = hdr[4];
-	return 11;
-}
-
-static int
-tlsPackAAD(u64int seq, uchar *hdr, uchar *aad)
+packAAD(u64int seq, uchar *hdr, uchar *aad)
 {
 	put64(aad, seq);
 	aad[8] = hdr[0];

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [9front] intent to delete: devssl, cpu, oexportfs, import
  2021-10-22 10:19       ` Philip Silva
@ 2021-10-22 15:32         ` ori
  0 siblings, 0 replies; 20+ messages in thread
From: ori @ 2021-10-22 15:32 UTC (permalink / raw)
  To: 9front

Quoth Philip Silva <philip.silva@protonmail.com>:
> That would be a pity to remove interoperability although SSL 3.0 is
> probably not so good.  But I wonder, isn't it possible to just remove
> the SSL 3.0?  Also in the patch list of 9legacy, there seems to be a
> set of patches for TLS 1.2 for devtls.

cpu, oexportfs, and import bypass version negotiation,
and hard-code devssl (via pushssl()). Moving to tls 1.2
for these programs will simply not be compatible.

> Not knowing so much about the internals anyway, I thought that
> cpu'ing (or at least drawterm'ing) to 9legacy was unencrypted anyway.

SSL 3.0 doesn't work -- so, it prevents casual snooping,
but not a real attack.


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [9front] intent to delete: devssl, cpu, oexportfs, import
  2021-10-22  1:58 ` sl
  2021-10-22  2:26   ` ori
@ 2021-10-22 20:26   ` Stuart Morrow
  2021-12-01  2:13     ` sl
  2021-12-01  2:13     ` sl
  1 sibling, 2 replies; 20+ messages in thread
From: Stuart Morrow @ 2021-10-22 20:26 UTC (permalink / raw)
  To: 9front

Fqa7 contains a reference to cpu(1) and exportfs(1) that probably
should be upgraded regardless.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [9front] intent to delete: devssl, cpu, oexportfs, import
  2021-10-22 14:31   ` kemal
  2021-10-22 14:36     ` kemal
@ 2021-10-23 11:18     ` kemal
  1 sibling, 0 replies; 20+ messages in thread
From: kemal @ 2021-10-23 11:18 UTC (permalink / raw)
  To: 9front

[-- Attachment #1: Type: text/plain, Size: 425 bytes --]

> i didn't test the diff throughly, so it might be buggy. i hope not.

found one bug.

- else if(isDHE(c->cipher) || c->version != SSL3Version)
+ else if(isDHE(c->cipher))
  put16(p, n), p += 2;

and

- else if(isDHE(c->cipher) || c->version != SSL3Version)
+ else if(isDHE(c->cipher))
  nn = get16(p), p += 2, n -= 2;
  else
  nn = n;

it shouldn't check if we have a DHE cipher, we're already on SSL3+!

new diff attached.

[-- Attachment #2: diff.txt --]
[-- Type: text/plain, Size: 31188 bytes --]

diff e54b6c6cbd4d82d70ddb4932aeafb0b028cd71f5 uncommitted
--- a//sys/man/2/pushtls
+++ b//sys/man/2/pushtls
@@ -1,6 +1,6 @@
 .TH PUSHTLS 2
 .SH NAME
-pushtls, tlsClient, tlsServer, initThumbprints, freeThumbprints, okThumbprint, okCertificate, readcert, readcertchain \- attach TLS1 or SSL3 encryption to a communication channel
+pushtls, tlsClient, tlsServer, initThumbprints, freeThumbprints, okThumbprint, okCertificate, readcert, readcertchain \- attach TLS encryption to a communication channel
 .SH SYNOPSIS
 .B #include <u.h>
 .br
@@ -45,8 +45,6 @@
 and a handshake protocol,
 doing initial authentication and secret creation at
 user level and then starting a data channel in the record protocol.
-TLS is nearly the same as SSL 3.0, and the software should interoperate
-with implementations of either standard.
 .PP
 To use just the record layer, as described in
 .IR tls (3),
--- a//sys/man/3/tls
+++ b//sys/man/3/tls
@@ -1,6 +1,6 @@
 .TH TLS 3 
 .SH NAME
-tls \- TLS and SSL3 record layer
+tls \- TLS record layer
 .SH SYNOPSIS
 .nf
 .B bind -a #a /net
@@ -16,10 +16,9 @@
 .BI /net/tls/ n /status
 .fi
 .SH DESCRIPTION
-The TLS device implements the record layer protocols
-of Transport Layer Security version 1.0-1.2 and Secure Sockets Layer version 3.0.
-It does not implement the handshake protocols, which are responsible for
-mutual authentication and key exchange.
+The TLS device implements the record layer protocols of Transport Layer Security
+version 1.0-1.2. It does not implement the handshake protocols, which are responsible
+for mutual authentication and key exchange.
 The
 .I tls
 device can be thought of as filters providing optional encryption and anti-tampering.
@@ -53,13 +52,11 @@
 .I vers
 format records, but incoming messages of either version are accepted.
 Valid versions are
-.B 0x300
-for SSLv3.0 and
 .BR 0x301 ,
 .B 0x302
 and
 .B 0x303
-for TLSv1.0 (which could be known as SSLv3.01), TLSv1.1 and TLSv1.2.
+for TLSv1.0, TLSv1.1 and TLSv1.2.
 This command must be issued before any other command
 and before reading or writing any messages;
 it may only be executed once.
@@ -120,10 +117,9 @@
 .TP
 .BI alert \ alertno
 Send an alert message.
-.I Alertno
-may be a valid alert code for either SSLv3.0 or TLS,
-and is mapped to an appropriate code for the protocol in use.
-If it is a fatal alert, the filter is set into an error state.
+If
+.I alertno
+is a fatal alert, the filter is set into an error state.
 .PP
 Application messages and handshake messages are communicated using
 .I data
--- a//sys/src/9/port/devtls.c
+++ b//sys/src/9/port/devtls.c
@@ -1,5 +1,5 @@
 /*
- *  devtls - record layer for transport layer security 1.2 and secure sockets layer 3.0
+ *  devtls - record layer for transport layer security 1.0-1.2
  */
 #include	"u.h"
 #include	"../port/lib.h"
@@ -24,11 +24,10 @@
 	MaxMacLen	= SHA2_256dlen,
 
 	/* protocol versions we can accept */
-	SSL3Version	= 0x0300,
 	TLS10Version	= 0x0301,
 	TLS11Version	= 0x0302,
 	TLS12Version	= 0x0303,
-	MinProtoVersion	= 0x0300,	/* limits on version we accept */
+	MinProtoVersion	= 0x0301,	/* limits on version we accept */
 	MaxProtoVersion	= 0x03ff,
 
 	/* connection states */
@@ -46,9 +45,6 @@
 	RHandshake,
 	RApplication,
 
-	SSL2ClientHello = 1,
-	HSSL2ClientHello = 9,  /* local convention;  see tlshand.c */
-
 	/* alerts */
 	ECloseNotify 			= 0,
 	EUnexpectedMessage 	= 10,
@@ -57,7 +53,6 @@
 	ERecordOverflow 		= 22,
 	EDecompressionFailure 	= 30,
 	EHandshakeFailure 		= 40,
-	ENoCertificate 			= 41,
 	EBadCertificate 		= 42,
 	EUnsupportedCertificate 	= 43,
 	ECertificateRevoked 		= 44,
@@ -89,7 +84,6 @@
 
 	int		(*enc)(Secret*, uchar*, int);
 	int		(*dec)(Secret*, uchar*, int);
-	int		(*unpad)(uchar*, int, int);
 	DigestState*	(*mac)(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
 
 	int		block;		/* encryption block len, 0 if none */
@@ -125,12 +119,6 @@
 	int		state;
 	int		debug;
 
-	/*
-	 * function to genrate authenticated data blob for different
-	 * protocol versions
-	 */
-	int		(*packAAD)(u64int, uchar*, uchar*);
-
 	/* input side -- protected by in.io */
 	OneWay		in;
 	Block		*processed;	/* next bunch of application data */
@@ -153,37 +141,34 @@
 
 struct TlsErrs{
 	int	err;
-	int	sslerr;
-	int	tlserr;
 	int	fatal;
 	char	*msg;
 };
 
 static TlsErrs tlserrs[] = {
-	{ECloseNotify,			ECloseNotify,			ECloseNotify,			0, 	"close notify"},
-	{EUnexpectedMessage,	EUnexpectedMessage,	EUnexpectedMessage, 	1, "unexpected message"},
-	{EBadRecordMac,		EBadRecordMac,		EBadRecordMac, 		1, "bad record mac"},
-	{EDecryptionFailed,		EIllegalParameter,		EDecryptionFailed,		1, "decryption failed"},
-	{ERecordOverflow,		EIllegalParameter,		ERecordOverflow,		1, "record too long"},
-	{EDecompressionFailure,	EDecompressionFailure,	EDecompressionFailure,	1, "decompression failed"},
-	{EHandshakeFailure,		EHandshakeFailure,		EHandshakeFailure,		1, "could not negotiate acceptable security parameters"},
-	{ENoCertificate,		ENoCertificate,			ECertificateUnknown,	1, "no appropriate certificate available"},
-	{EBadCertificate,		EBadCertificate,		EBadCertificate,		1, "corrupted or invalid certificate"},
-	{EUnsupportedCertificate,	EUnsupportedCertificate,	EUnsupportedCertificate,	1, "unsupported certificate type"},
-	{ECertificateRevoked,	ECertificateRevoked,		ECertificateRevoked,		1, "revoked certificate"},
-	{ECertificateExpired,		ECertificateExpired,		ECertificateExpired,		1, "expired certificate"},
-	{ECertificateUnknown,	ECertificateUnknown,	ECertificateUnknown,	1, "unacceptable certificate"},
-	{EIllegalParameter,		EIllegalParameter,		EIllegalParameter,		1, "illegal parameter"},
-	{EUnknownCa,			EHandshakeFailure,		EUnknownCa,			1, "unknown certificate authority"},
-	{EAccessDenied,		EHandshakeFailure,		EAccessDenied,		1, "access denied"},
-	{EDecodeError,			EIllegalParameter,		EDecodeError,			1, "error decoding message"},
-	{EDecryptError,			EIllegalParameter,		EDecryptError,			1, "error decrypting message"},
-	{EExportRestriction,		EHandshakeFailure,		EExportRestriction,		1, "export restriction violated"},
-	{EProtocolVersion,		EIllegalParameter,		EProtocolVersion,		1, "protocol version not supported"},
-	{EInsufficientSecurity,	EHandshakeFailure,		EInsufficientSecurity,	1, "stronger security routines required"},
-	{EInternalError,			EHandshakeFailure,		EInternalError,			1, "internal error"},
-	{EUserCanceled,		ECloseNotify,			EUserCanceled,			0, "handshake canceled by user"},
-	{ENoRenegotiation,		EUnexpectedMessage,	ENoRenegotiation,		0, "no renegotiation"},
+	{ECloseNotify,			0, "close notify"},
+	{EUnexpectedMessage,		1, "unexpected message"},
+	{EBadRecordMac,			1, "bad record mac"},
+	{EDecryptionFailed,		1, "decryption failed"},
+	{ERecordOverflow,		1, "record too long"},
+	{EDecompressionFailure,		1, "decompression failed"},
+	{EHandshakeFailure,		1, "could not negotiate acceptable security parameters"},
+	{EBadCertificate,		1, "corrupted or invalid certificate"},
+	{EUnsupportedCertificate,	1, "unsupported certificate type"},
+	{ECertificateRevoked,		1, "revoked certificate"},
+	{ECertificateExpired,		1, "expired certificate"},
+	{ECertificateUnknown,		1, "unacceptable certificate"},
+	{EIllegalParameter,		1, "illegal parameter"},
+	{EUnknownCa,			1, "unknown certificate authority"},
+	{EAccessDenied,			1, "access denied"},
+	{EDecodeError,			1, "error decoding message"},
+	{EDecryptError,			1, "error decrypting message"},
+	{EExportRestriction,		1, "export restriction violated"},
+	{EProtocolVersion,		1, "protocol version not supported"},
+	{EInsufficientSecurity,		1, "stronger security routines required"},
+	{EInternalError,		1, "internal error"},
+	{EUserCanceled,			0, "handshake canceled by user"},
+	{ENoRenegotiation,		0, "no renegotiation"},
 };
 
 enum
@@ -227,11 +212,8 @@
 static void	alertHand(TlsRec*, char *);
 static TlsRec	*newtls(Chan *c);
 static TlsRec	*mktlsrec(void);
-static DigestState*sslmac_md5(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
-static DigestState*sslmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
 static DigestState*nomac(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
-static int	sslPackAAD(u64int, uchar*, uchar*);
-static int	tlsPackAAD(u64int, uchar*, uchar*);
+static int	packAAD(u64int, uchar*, uchar*);
 static void	packMac(Secret*, uchar*, int, uchar*, int, uchar*);
 static void	put64(uchar *p, u64int);
 static void	put32(uchar *p, u32int);
@@ -252,8 +234,7 @@
 static int	aesgcm_aead_enc(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len);
 static int	aesgcm_aead_dec(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len);
 static int	noenc(Secret *sec, uchar *buf, int n);
-static int	sslunpad(uchar *buf, int n, int block);
-static int	tlsunpad(uchar *buf, int n, int block);
+static int	unpad(uchar *buf, int n, int block);
 static void	freeSec(Secret *sec);
 static char	*tlsstate(int s);
 static void	pdump(int, void*, char*);
@@ -749,20 +730,10 @@
 if(tr->debug)pprint("consumed %d header\n", RecHdrLen);
 	nconsumed = RecHdrLen;
 
-	if((tr->handin == 0) && (header[0] & 0x80)){
-		/* Cope with an SSL3 ClientHello expressed in SSL2 record format.
-			This is sent by some clients that we must interoperate
-			with, such as Java's JSSE and Microsoft's Internet Explorer. */
-		len = (get16(header) & ~0x8000) - 3;
-		type = header[2];
-		ver = get16(header + 3);
-		if(type != SSL2ClientHello || len < 22)
-			rcvError(tr, EProtocolVersion, "invalid initial SSL2-like message");
-	}else{  /* normal SSL3 record format */
-		type = header[0];
-		ver = get16(header+1);
-		len = get16(header+3);
-	}
+	type = header[0];
+	ver = get16(header+1);
+	len = get16(header+3);
+
 	if(ver != tr->version && (tr->verset || ver < MinProtoVersion || ver > MaxProtoVersion))
 		rcvError(tr, EProtocolVersion, "devtls expected ver=%x%s, saw (len=%d) type=%x ver=%x '%.12s'",
 			tr->version, tr->verset?"/set":"", len, type, ver, (char*)header);
@@ -823,7 +794,7 @@
 
 		/* update length */
 		put16(header+3, len);
-		aadlen = (*tr->packAAD)(in->seq++, header, aad);
+		aadlen = packAAD(in->seq++, header, aad);
 		if(sec->aead_dec != nil) {
 			len = (*sec->aead_dec)(sec, aad, aadlen, p - ivlen, p, unpad_len);
 			if(len < 0)
@@ -916,42 +887,12 @@
 			dechandq(tr);
 		}else{
 			unlock(&tr->hqlock);
-			if(tr->verset && tr->version != SSL3Version && !waserror()){
+			if(tr->verset && !waserror()){
 				sendAlert(tr, ENoRenegotiation);
 				poperror();
 			}
 		}
 		break;
-	case SSL2ClientHello:
-		lock(&tr->hqlock);
-		if(tr->handq != nil){
-			tr->hqref++;
-			unlock(&tr->hqlock);
-			if(waserror()){
-				dechandq(tr);
-				nexterror();
-			}
-			/* Pass the SSL2 format data, so that the handshake code can compute
-				the correct checksums.  HSSL2ClientHello = HandshakeType 9 is
-				unused in RFC2246. */
-			b = padblock(b, 8);
-			b->rp[0] = RHandshake;
-			b->rp[1] = HSSL2ClientHello;
-			put24(&b->rp[2], len+3);
-			b->rp[5] = SSL2ClientHello;
-			put16(&b->rp[6], ver);
-			qbwrite(tr->handq, b);
-			b = nil;
-			poperror();
-			dechandq(tr);
-		}else{
-			unlock(&tr->hqlock);
-			if(tr->verset && tr->version != SSL3Version && !waserror()){
-				sendAlert(tr, ENoRenegotiation);
-				poperror();
-			}
-		}
-		break;
 	case RApplication:
 		if(!tr->opened)
 			rcvError(tr, EUnexpectedMessage, "application message received before handshake completed");
@@ -1314,7 +1255,7 @@
 		put16(p+3, n);
 
 		if(sec != nil){
-			aadlen = (*tr->packAAD)(out->seq++, p, aad);
+			aadlen = packAAD(out->seq++, p, aad);
 			if(sec->aead_enc != nil)
 				n = (*sec->aead_enc)(sec, aad, aadlen, p + RecHdrLen, p + RecHdrLen + ivlen, n) + ivlen;
 			else {
@@ -1390,42 +1331,34 @@
 {
 	char	*name;
 	int	maclen;
-	void	(*initkey)(Hashalg *, int, Secret *, uchar*);
+	void	(*initkey)(Hashalg *, Secret *, uchar*);
 };
 
 static void
-initmd5key(Hashalg *ha, int version, Secret *s, uchar *p)
+initmd5key(Hashalg *ha, Secret *s, uchar *p)
 {
 	s->maclen = ha->maclen;
-	if(version == SSL3Version)
-		s->mac = sslmac_md5;
-	else
-		s->mac = hmac_md5;
+	s->mac = hmac_md5;
 	memmove(s->mackey, p, ha->maclen);
 }
 
 static void
-initclearmac(Hashalg *, int, Secret *s, uchar *)
+initclearmac(Hashalg *, Secret *s, uchar *)
 {
 	s->mac = nomac;
 }
 
 static void
-initsha1key(Hashalg *ha, int version, Secret *s, uchar *p)
+initsha1key(Hashalg *ha, Secret *s, uchar *p)
 {
 	s->maclen = ha->maclen;
-	if(version == SSL3Version)
-		s->mac = sslmac_sha1;
-	else
-		s->mac = hmac_sha1;
+	s->mac = hmac_sha1;
 	memmove(s->mackey, p, ha->maclen);
 }
 
 static void
-initsha2_256key(Hashalg *ha, int version, Secret *s, uchar *p)
+initsha2_256key(Hashalg *ha, Secret *s, uchar *p)
 {
-	if(version == SSL3Version)
-		error("sha256 cannot be used with SSL");
 	s->maclen = ha->maclen;
 	s->mac = hmac_sha2_256;
 	memmove(s->mackey, p, ha->maclen);
@@ -1641,10 +1574,6 @@
 		m = strtol(cb->f[1], nil, 0);
 		if(m < MinProtoVersion || m > MaxProtoVersion)
 			error("unsupported version");
-		if(m == SSL3Version)
-			tr->packAAD = sslPackAAD;
-		else
-			tr->packAAD = tlsPackAAD;
 		tr->verset = 1;
 		tr->version = m;
 	}else if(strcmp(cb->f[0], "secret") == 0){
@@ -1685,8 +1614,8 @@
 		if(!ha->initkey || !ea->initkey)
 			error("misimplemented secret algorithm");
 
-		(*ha->initkey)(ha, tr->version, tos, &x[0]);
-		(*ha->initkey)(ha, tr->version, toc, &x[ha->maclen]);
+		(*ha->initkey)(ha, tos, &x[0]);
+		(*ha->initkey)(ha, toc, &x[ha->maclen]);
 		(*ea->initkey)(ea, tos, &x[2 * ha->maclen], &x[2 * ha->maclen + 2 * ea->keylen]);
 		(*ea->initkey)(ea, toc, &x[2 * ha->maclen + ea->keylen], &x[2 * ha->maclen + 2 * ea->keylen + ea->ivlen]);
 
@@ -1701,13 +1630,6 @@
 			tr->in.new = toc;
 			tr->out.new = tos;
 		}
-		if(tr->version == SSL3Version){
-			toc->unpad = sslunpad;
-			tos->unpad = sslunpad;
-		}else{
-			toc->unpad = tlsunpad;
-			tos->unpad = tlsunpad;
-		}
 		toc->encalg = ea->name;
 		toc->hashalg = ha->name;
 		tos->encalg = ea->name;
@@ -1879,17 +1801,12 @@
 if(tr->debug)pprint("sendAlert %d\n", err);
 	fatal = 1;
 	msg = "tls unknown alert";
-	for(i=0; i < nelem(tlserrs); i++) {
-		if(tlserrs[i].err == err) {
+	for(i=0; i < nelem(tlserrs); i++)
+		if(tlserrs[i].err == err){
 			msg = tlserrs[i].msg;
-			if(tr->version == SSL3Version)
-				err = tlserrs[i].sslerr;
-			else
-				err = tlserrs[i].tlserr;
 			fatal = tlserrs[i].fatal;
 			break;
 		}
-	}
 
 	if(!waserror()){
 		b = allocb(2);
@@ -2061,7 +1978,7 @@
 }
 
 static int
-tlsunpad(uchar *buf, int n, int block)
+unpad(uchar *buf, int n, int block)
 {
 	int pad, nn;
 
@@ -2076,18 +1993,6 @@
 }
 
 static int
-sslunpad(uchar *buf, int n, int block)
-{
-	int pad, nn;
-
-	pad = buf[n - 1];
-	nn = n - 1 - pad;
-	if(nn <= 0 || n % block)
-		return -1;
-	return nn;
-}
-
-static int
 blockpad(uchar *buf, int n, int block)
 {
 	int pad, nn;
@@ -2112,7 +2017,7 @@
 des3dec(Secret *sec, uchar *buf, int n)
 {
 	des3CBCdecrypt(buf, n, sec->enckey);
-	return (*sec->unpad)(buf, n, 8);
+	return unpad(buf, n, 8);
 }
 
 static int
@@ -2127,7 +2032,7 @@
 aesdec(Secret *sec, uchar *buf, int n)
 {
 	aesCBCdecrypt(buf, n, sec->enckey);
-	return (*sec->unpad)(buf, n, 16);
+	return unpad(buf, n, 16);
 }
 
 static void
@@ -2213,71 +2118,8 @@
 	return nil;
 }
 
-/*
- * sslmac: mac calculations for ssl 3.0 only; tls 1.0 uses the standard hmac.
- */
-static DigestState*
-sslmac_x(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s,
-	DigestState*(*x)(uchar*, ulong, uchar*, DigestState*), int xlen, int padlen)
-{
-	int i;
-	uchar pad[48], innerdigest[20];
-
-	if(xlen > sizeof(innerdigest)
-	|| padlen > sizeof(pad))
-		return nil;
-
-	if(klen>64)
-		return nil;
-
-	/* first time through */
-	if(s == nil){
-		for(i=0; i<padlen; i++)
-			pad[i] = 0x36;
-		s = (*x)(key, klen, nil, nil);
-		s = (*x)(pad, padlen, nil, s);
-		if(s == nil)
-			return nil;
-	}
-
-	s = (*x)(p, len, nil, s);
-	if(digest == nil)
-		return s;
-
-	/* last time through */
-	for(i=0; i<padlen; i++)
-		pad[i] = 0x5c;
-	(*x)(nil, 0, innerdigest, s);
-	s = (*x)(key, klen, nil, nil);
-	s = (*x)(pad, padlen, nil, s);
-	(*x)(innerdigest, xlen, digest, s);
-	return nil;
-}
-
-static DigestState*
-sslmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s)
-{
-	return sslmac_x(p, len, key, klen, digest, s, sha1, SHA1dlen, 40);
-}
-
-static DigestState*
-sslmac_md5(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s)
-{
-	return sslmac_x(p, len, key, klen, digest, s, md5, MD5dlen, 48);
-}
-
 static int
-sslPackAAD(u64int seq, uchar *hdr, uchar *aad)
-{
-	put64(aad, seq);
-	aad[8] = hdr[0];
-	aad[9] = hdr[3];
-	aad[10] = hdr[4];
-	return 11;
-}
-
-static int
-tlsPackAAD(u64int seq, uchar *hdr, uchar *aad)
+packAAD(u64int seq, uchar *hdr, uchar *aad)
 {
 	put64(aad, seq);
 	aad[8] = hdr[0];
--- a//sys/src/libsec/port/tlshand.c
+++ b//sys/src/libsec/port/tlshand.c
@@ -8,14 +8,13 @@
 //		client/server - main handshake protocol definition
 //		message functions - formating handshake messages
 //		cipher choices - catalog of digest and encrypt algorithms
-//		security functions - PKCS#1, sslHMAC, session keygen
+//		security functions - PKCS#1, session keygen
 //		general utility functions - malloc, serialization
-// The handshake protocol builds on the TLS/SSL3 record layer protocol,
-// which is implemented in kernel device #a.  See also /lib/rfc/rfc2246.
+// The handshake protocol builds on the TLS record layer protocol,
+// which is implemented in kernel device #a.  See also /lib/rfc/rfc5246.
 
 enum {
-	TLSFinishedLen = 12,
-	SSL3FinishedLen = MD5dlen+SHA1dlen,
+	FinishedLen = 12,
 	MaxKeyData = 160,	// amount of secret we may need
 	MAXdlen = SHA2_512dlen,
 	RandomSize = 32,
@@ -47,11 +46,6 @@
 	void (*init)(mpint *p, mpint *a, mpint *b, mpint *x, mpint *y, mpint *n, mpint *h);
 } Namedcurve;
 
-typedef struct Finished{
-	uchar verify[SSL3FinishedLen];
-	int n;
-} Finished;
-
 typedef struct HandshakeHash {
 	MD5state	md5;
 	SHAstate	sha1;
@@ -81,7 +75,6 @@
 	// byte generation and handshake checksum
 	void (*prf)(uchar*, int, uchar*, int, char*, uchar*, int);
 	void (*setFinished)(TlsSec*, HandshakeHash, uchar*, int);
-	int nfin;
 };
 
 typedef struct TlsConnection{
@@ -99,7 +92,7 @@
 
 	// for finished messages
 	HandshakeHash	handhash;
-	Finished	finished;
+	uchar		finished[FinishedLen];
 
 	uchar *sendp;
 	uchar buf[1<<16];
@@ -152,18 +145,17 @@
 			int sigalg;
 			Bytes *signature;
 		} certificateVerify;		
-		Finished finished;
+		uchar finished[FinishedLen];
 	} u;
 } Msg;
 
 
 enum {
-	SSL3Version	= 0x0300,
 	TLS10Version	= 0x0301,
 	TLS11Version	= 0x0302,
 	TLS12Version	= 0x0303,
 	ProtocolVersion	= TLS12Version,	// maximum version we speak
-	MinProtoVersion	= 0x0300,	// limits on version we accept
+	MinProtoVersion	= 0x0301,	// limits on version we accept
 	MaxProtoVersion	= 0x03ff,
 };
 
@@ -172,7 +164,6 @@
 	HHelloRequest,
 	HClientHello,
 	HServerHello,
-	HSSL2ClientHello = 9,  /* local convention;  see devtls.c */
 	HCertificate = 11,
 	HServerKeyExchange,
 	HCertificateRequest,
@@ -192,7 +183,6 @@
 	ERecordOverflow = 22,
 	EDecompressionFailure = 30,
 	EHandshakeFailure = 40,
-	ENoCertificate = 41,
 	EBadCertificate = 42,
 	EUnsupportedCertificate = 43,
 	ECertificateRevoked = 44,
@@ -367,7 +357,6 @@
 #pragma	varargck argpos	tlsError 3
 static int setVersion(TlsConnection *c, int version);
 static int setSecrets(TlsConnection *c, int isclient);
-static int finishedMatch(TlsConnection *c, Finished *f);
 static void tlsConnectionFree(TlsConnection *c);
 
 static int isDHE(int tlsid);
@@ -394,7 +383,6 @@
 static Bytes*	tlsSecDHEc(TlsSec *sec, Bytes *p, Bytes *g, Bytes *Ys);
 static Bytes*	tlsSecECDHEc(TlsSec *sec, int curve, Bytes *Ys);
 static void	tlsSecVers(TlsSec *sec, int v);
-static int	tlsSecFinished(TlsSec *sec, HandshakeHash hsh, uchar *fin, int nfin, int isclient);
 static void	setMasterSecret(TlsSec *sec, Bytes *pm);
 static int	digestDHparams(TlsSec *sec, Bytes *par, uchar digest[MAXdlen], int sigalg);
 static char*	verifyDHparams(TlsSec *sec, Bytes *par, Bytes *cert, Bytes *sig, int sigalg);
@@ -511,28 +499,26 @@
 	}
 
 	// Elliptic Curves (also called Supported Groups)
-	if(ProtocolVersion >= TLS10Version){
-		m = p - b;
-		b = erealloc(b, m + 2+2+2+nelem(namedcurves)*2 + 2+2+1+nelem(pointformats));
-		p = b + m;
+	m = p - b;
+	b = erealloc(b, m + 2+2+2+nelem(namedcurves)*2 + 2+2+1+nelem(pointformats));
+	p = b + m;
 
-		n = nelem(namedcurves);
-		put16(p, Extec), p += 2;	/* Type: elliptic_curves / supported_groups */
-		put16(p, (n+1)*2), p += 2;	/* Length */
-		put16(p, n*2), p += 2;		/* Elliptic Curves Length */
-		for(i=0; i < n; i++){		/* Elliptic Curves */
-			put16(p, namedcurves[i].tlsid);
-			p += 2;
-		}
-
-		n = nelem(pointformats);
-		put16(p, Extecp), p += 2;	/* Type: ec_point_formats */
-		put16(p, n+1), p += 2;		/* Length */
-		*p++ = n;			/* EC point formats Length */
-		for(i=0; i < n; i++)		/* EC point formats */
-			*p++ = pointformats[i];
+	n = nelem(namedcurves);
+	put16(p, Extec), p += 2;	/* Type: elliptic_curves / supported_groups */
+	put16(p, (n+1)*2), p += 2;	/* Length */
+	put16(p, n*2), p += 2;		/* Elliptic Curves Length */
+	for(i=0; i < n; i++){		/* Elliptic Curves */
+		put16(p, namedcurves[i].tlsid);
+		p += 2;
 	}
 
+	n = nelem(pointformats);
+	put16(p, Extecp), p += 2;	/* Type: ec_point_formats */
+	put16(p, n+1), p += 2;		/* Length */
+	*p++ = n;			/* EC point formats Length */
+	for(i=0; i < n; i++)		/* EC point formats */
+		*p++ = pointformats[i];
+
 	// signature algorithms
 	if(ProtocolVersion >= TLS12Version){
 		n = nelem(sigalgs);
@@ -849,10 +835,7 @@
 	}
 
 	/* no CertificateVerify; skip to Finished */
-	if(tlsSecFinished(c->sec, c->handhash, c->finished.verify, c->finished.n, 1) < 0){
-		tlsError(c, EInternalError, "can't set finished: %r");
-		goto Err;
-	}
+	(*c->sec->setFinished)(c->sec, c->handhash, c->finished, 1);
 	if(!msgRecv(c, &m))
 		goto Err;
 	if(m.tag != HFinished) {
@@ -859,7 +842,7 @@
 		tlsError(c, EUnexpectedMessage, "expected a finished");
 		goto Err;
 	}
-	if(!finishedMatch(c, &m.u.finished)) {
+	if(tsmemcmp(c->finished, m.u.finished, FinishedLen) != 0) {
 		tlsError(c, EHandshakeFailure, "finished verification failed");
 		goto Err;
 	}
@@ -871,12 +854,9 @@
 		goto Err;
 	}
 
-	if(tlsSecFinished(c->sec, c->handhash, c->finished.verify, c->finished.n, 0) < 0){
-		tlsError(c, EInternalError, "can't set finished: %r");
-		goto Err;
-	}
+	(*c->sec->setFinished)(c->sec, c->handhash, c->finished, 0);
 	m.tag = HFinished;
-	m.u.finished = c->finished;
+	memmove(m.u.finished, c->finished, FinishedLen);
 	if(!msgSend(c, &m, AFlush))
 		goto Err;
 	if(trace)
@@ -1220,21 +1200,15 @@
 
 	// Cipherchange must occur immediately before Finished to avoid
 	// potential hole;  see section 4.3 of Wagner Schneier 1996.
-	if(tlsSecFinished(c->sec, c->handhash, c->finished.verify, c->finished.n, 1) < 0){
-		tlsError(c, EInternalError, "can't set finished 1: %r");
-		goto Err;
-	}
+	(*c->sec->setFinished)(c->sec, c->handhash, c->finished, 1);
 	m.tag = HFinished;
-	m.u.finished = c->finished;
+	memmove(m.u.finished, c->finished, FinishedLen);
 	if(!msgSend(c, &m, AFlush)) {
 		tlsError(c, EInternalError, "can't flush after client Finished: %r");
 		goto Err;
 	}
 
-	if(tlsSecFinished(c->sec, c->handhash, c->finished.verify, c->finished.n, 0) < 0){
-		tlsError(c, EInternalError, "can't set finished 0: %r");
-		goto Err;
-	}
+	(*c->sec->setFinished)(c->sec, c->handhash, c->finished, 0);
 	if(!msgRecv(c, &m)) {
 		tlsError(c, EInternalError, "can't read server Finished: %r");
 		goto Err;
@@ -1244,7 +1218,7 @@
 		goto Err;
 	}
 
-	if(!finishedMatch(c, &m.u.finished)) {
+	if(tsmemcmp(c->finished, m.u.finished, FinishedLen) != 0) {
 		tlsError(c, EHandshakeFailure, "finished verification failed");
 		goto Err;
 	}
@@ -1418,16 +1392,16 @@
 			goto Overflow;
 		if(isECDHE(c->cipher))
 			*p++ = n;
-		else if(isDHE(c->cipher) || c->version != SSL3Version)
+		else
 			put16(p, n), p += 2;
 		memmove(p, m->u.clientKeyExchange.key->data, n);
 		p += n;
 		break;
 	case HFinished:
-		if(p+m->u.finished.n > e)
+		if(p+FinishedLen > e)
 			goto Overflow;
-		memmove(p, m->u.finished.verify, m->u.finished.n);
-		p += m->u.finished.n;
+		memmove(p, m->u.finished, FinishedLen);
+		p += FinishedLen;
 		break;
 	}
 
@@ -1495,50 +1469,6 @@
 		}
 	}
 
-	if(type == HSSL2ClientHello){
-		/* Cope with an SSL3 ClientHello expressed in SSL2 record format.
-			This is sent by some clients that we must interoperate
-			with, such as Java's JSSE and Microsoft's Internet Explorer. */
-		int nsid, nrandom, nciph;
-
-		p = tlsReadN(c, n);
-		if(p == nil)
-			return 0;
-		msgHash(c, p, n);
-		m->tag = HClientHello;
-		if(n < 22)
-			goto Short;
-		m->u.clientHello.version = get16(p+1);
-		p += 3;
-		n -= 3;
-		nn = get16(p); /* cipher_spec_len */
-		nsid = get16(p + 2);
-		nrandom = get16(p + 4);
-		p += 6;
-		n -= 6;
-		if(nsid != 0 	/* no sid's, since shouldn't restart using ssl2 header */
-		|| nrandom < 16 || nn % 3 || n - nrandom < nn)
-			goto Err;
-		/* ignore ssl2 ciphers and look for {0x00, ssl3 cipher} */
-		nciph = 0;
-		for(i = 0; i < nn; i += 3)
-			if(p[i] == 0)
-				nciph++;
-		m->u.clientHello.ciphers = newints(nciph);
-		nciph = 0;
-		for(i = 0; i < nn; i += 3)
-			if(p[i] == 0)
-				m->u.clientHello.ciphers->data[nciph++] = get16(&p[i + 1]);
-		p += nn;
-		m->u.clientHello.sid = makebytes(nil, 0);
-		if(nrandom > RandomSize)
-			nrandom = RandomSize;
-		memset(m->u.clientHello.random, 0, RandomSize - nrandom);
-		memmove(&m->u.clientHello.random[RandomSize - nrandom], p, nrandom);
-		m->u.clientHello.compressors = newbytes(1);
-		m->u.clientHello.compressors->data[0] = CompressionNull;
-		goto Ok;
-	}
 	msgHash(c, p, 4);
 
 	p = tlsReadN(c, n);
@@ -1790,10 +1720,8 @@
 			goto Short;
 		if(isECDHE(c->cipher))
 			nn = *p++, n--;
-		else if(isDHE(c->cipher) || c->version != SSL3Version)
-			nn = get16(p), p += 2, n -= 2;
 		else
-			nn = n;
+			nn = get16(p), p += 2, n -= 2;
 		if(n < nn)
 			goto Short;
 		m->u.clientKeyExchange.key = makebytes(p, nn);
@@ -1800,17 +1728,16 @@
 		n -= nn;
 		break;
 	case HFinished:
-		m->u.finished.n = c->finished.n;
-		if(n < m->u.finished.n)
+		if(n < FinishedLen)
 			goto Short;
-		memmove(m->u.finished.verify, p, m->u.finished.n);
-		n -= m->u.finished.n;
+		memmove(m->u.finished, p, FinishedLen);
+		n -= FinishedLen;
 		break;
 	}
 
 	if(n != 0 && type != HClientHello && type != HServerHello)
 		goto Short;
-Ok:
+
 	if(c->trace)
 		c->trace("recv %s", msgPrint((char*)c->sendp, &c->buf[sizeof(c->buf)] - c->sendp, m));
 	return 1;
@@ -2000,8 +1927,8 @@
 		break;
 	case HFinished:
 		bs = seprint(bs, be, "HFinished\n");
-		for(i=0; i<m->u.finished.n; i++)
-			bs = seprint(bs, be, "%.2x", m->u.finished.verify[i]);
+		for(i=0; i<FinishedLen; i++)
+			bs = seprint(bs, be, "%.2x", m->u.finished[i]);
 		bs = seprint(bs, be, "\n");
 		break;
 	}
@@ -2036,23 +1963,11 @@
 		return -1;
 	if(version > c->version)
 		version = c->version;
-	if(version == SSL3Version) {
+	else
 		c->version = version;
-		c->finished.n = SSL3FinishedLen;
-	}else {
-		c->version = version;
-		c->finished.n = TLSFinishedLen;
-	}
 	return fprint(c->ctl, "version 0x%x", version);
 }
 
-// confirm that received Finished message matches the expected value
-static int
-finishedMatch(TlsConnection *c, Finished *f)
-{
-	return tsmemcmp(f->verify, c->finished.verify, f->n) == 0;
-}
-
 // free memory associated with TlsConnection struct
 //		(but don't close the TLS channel itself)
 static void
@@ -2390,68 +2305,6 @@
 		hmac_sha2_256, SHA2_256dlen);
 }
 
-static void
-sslPRF(uchar *buf, int nbuf, uchar *key, int nkey, char *label, uchar *seed, int nseed)
-{
-	uchar sha1dig[SHA1dlen], md5dig[MD5dlen], tmp[26];
-	DigestState *s;
-	int i, n, len;
-
-	USED(label);
-	len = 1;
-	while(nbuf > 0){
-		if(len > 26)
-			return;
-		for(i = 0; i < len; i++)
-			tmp[i] = 'A' - 1 + len;
-		s = sha1(tmp, len, nil, nil);
-		s = sha1(key, nkey, nil, s);
-		sha1(seed, nseed, sha1dig, s);
-		s = md5(key, nkey, nil, nil);
-		md5(sha1dig, SHA1dlen, md5dig, s);
-		n = MD5dlen;
-		if(n > nbuf)
-			n = nbuf;
-		memmove(buf, md5dig, n);
-		buf += n;
-		nbuf -= n;
-		len++;
-	}
-}
-
-static void
-sslSetFinished(TlsSec *sec, HandshakeHash hsh, uchar *finished, int isclient)
-{
-	DigestState *s;
-	uchar h0[MD5dlen], h1[SHA1dlen], pad[48];
-	char *label;
-
-	if(isclient)
-		label = "CLNT";
-	else
-		label = "SRVR";
-
-	md5((uchar*)label, 4, nil, &hsh.md5);
-	md5(sec->sec, MasterSecretSize, nil, &hsh.md5);
-	memset(pad, 0x36, 48);
-	md5(pad, 48, nil, &hsh.md5);
-	md5(nil, 0, h0, &hsh.md5);
-	memset(pad, 0x5C, 48);
-	s = md5(sec->sec, MasterSecretSize, nil, nil);
-	s = md5(pad, 48, nil, s);
-	md5(h0, MD5dlen, finished, s);
-
-	sha1((uchar*)label, 4, nil, &hsh.sha1);
-	sha1(sec->sec, MasterSecretSize, nil, &hsh.sha1);
-	memset(pad, 0x36, 40);
-	sha1(pad, 40, nil, &hsh.sha1);
-	sha1(nil, 0, h1, &hsh.sha1);
-	memset(pad, 0x5C, 40);
-	s = sha1(sec->sec, MasterSecretSize, nil, nil);
-	s = sha1(pad, 40, nil, s);
-	sha1(h1, SHA1dlen, finished + MD5dlen, s);
-}
-
 // fill "finished" arg with md5(args)^sha1(args)
 static void
 tls10SetFinished(TlsSec *sec, HandshakeHash hsh, uchar *finished, int isclient)
@@ -2460,6 +2313,8 @@
 	char *label;
 
 	// get current hash value, but allow further messages to be hashed in
+	hsh.md5.malloced = 0;
+	hsh.sha1.malloced = 0;
 	md5(nil, 0, h, &hsh.md5);
 	sha1(nil, 0, h+MD5dlen, &hsh.sha1);
 
@@ -2467,7 +2322,7 @@
 		label = "client finished";
 	else
 		label = "server finished";
-	tls10PRF(finished, TLSFinishedLen, sec->sec, MasterSecretSize, label, h, sizeof(h));
+	tls10PRF(finished, FinishedLen, sec->sec, MasterSecretSize, label, h, sizeof(h));
 }
 
 static void
@@ -2477,6 +2332,7 @@
 	char *label;
 
 	// get current hash value, but allow further messages to be hashed in
+	hsh.sha2_256.malloced = 0;
 	sha2_256(nil, 0, seed, &hsh.sha2_256);
 
 	if(isclient)
@@ -2483,7 +2339,7 @@
 		label = "client finished";
 	else
 		label = "server finished";
-	tls12PRF(finished, TLSFinishedLen, sec->sec, MasterSecretSize, label, seed, SHA2_256dlen);
+	tls12PRF(finished, FinishedLen, sec->sec, MasterSecretSize, label, seed, SHA2_256dlen);
 }
 
 static void
@@ -2630,34 +2486,14 @@
 	return epm;
 }
 
-static int
-tlsSecFinished(TlsSec *sec, HandshakeHash hsh, uchar *fin, int nfin, int isclient)
-{
-	if(sec->nfin != nfin){
-		werrstr("invalid finished exchange");
-		return -1;
-	}
-	hsh.md5.malloced = 0;
-	hsh.sha1.malloced = 0;
-	hsh.sha2_256.malloced = 0;
-	(*sec->setFinished)(sec, hsh, fin, isclient);
-	return 0;
-}
-
 static void
 tlsSecVers(TlsSec *sec, int v)
 {
-	if(v == SSL3Version){
-		sec->setFinished = sslSetFinished;
-		sec->nfin = SSL3FinishedLen;
-		sec->prf = sslPRF;
-	}else if(v < TLS12Version) {
+	if(v < TLS12Version){
 		sec->setFinished = tls10SetFinished;
-		sec->nfin = TLSFinishedLen;
 		sec->prf = tls10PRF;
-	}else {
+	}else{
 		sec->setFinished = tls12SetFinished;
-		sec->nfin = TLSFinishedLen;
 		sec->prf = tls12PRF;
 	}
 }

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [9front] intent to delete: devssl, cpu, oexportfs, import
  2021-10-22 14:36     ` kemal
@ 2021-10-23 15:47       ` ori
  2021-10-23 16:12         ` cinap_lenrek
  2021-10-23 20:13         ` kemal
  0 siblings, 2 replies; 20+ messages in thread
From: ori @ 2021-10-23 15:47 UTC (permalink / raw)
  To: 9front

Quoth kemal <kemalinanc8@gmail.com>:
> > also, i made a diff that removes SSL3 from devtls and tlshand. it's attached.
> > i didn't test the diff throughly, so it might be buggy. i hope not.
> 
> forgot to include the diff for devtls, ughhh
> 

I'm gonig to look over this in the next few days,
but I think this can go in before we get rid of
devtls; cpu bypasses the handshake, so as long as
we keep devtls it should keep working regardless of
libsec.


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [9front] intent to delete: devssl, cpu, oexportfs, import
  2021-10-23 15:47       ` ori
@ 2021-10-23 16:12         ` cinap_lenrek
  2021-10-23 16:17           ` ori
  2021-10-23 20:13         ` kemal
  1 sibling, 1 reply; 20+ messages in thread
From: cinap_lenrek @ 2021-10-23 16:12 UTC (permalink / raw)
  To: 9front

> I'm gonig to look over this in the next few days,
> but I think this can go in before we get rid of
> devtls; cpu bypasses the handshake, so as long as
> we keep devtls it should keep working regardless of
> libsec.

devtls is the one we use for tlsClient()/tlsServer().

we certainly do not want to get rid of devtls.

cpu, import, oexportfs use devssl by calling pushssl(2),
not devtls.

pushssl() is using devssl only. there is not magic
fallback to use devtls.

--
cinap

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [9front] intent to delete: devssl, cpu, oexportfs, import
  2021-10-23 16:12         ` cinap_lenrek
@ 2021-10-23 16:17           ` ori
  0 siblings, 0 replies; 20+ messages in thread
From: ori @ 2021-10-23 16:17 UTC (permalink / raw)
  To: 9front

Quoth cinap_lenrek@felloff.net:
> 
> devtls is the one we use for tlsClient()/tlsServer().
> 
> we certainly do not want to get rid of devtls.
> 
> cpu, import, oexportfs use devssl by calling pushssl(2),
> not devtls.

mistyped -- devssl.


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [9front] intent to delete: devssl, cpu, oexportfs, import
  2021-10-23 15:47       ` ori
  2021-10-23 16:12         ` cinap_lenrek
@ 2021-10-23 20:13         ` kemal
  2021-10-24 11:46           ` kemal
  1 sibling, 1 reply; 20+ messages in thread
From: kemal @ 2021-10-23 20:13 UTC (permalink / raw)
  To: 9front

[-- Attachment #1: Type: text/plain, Size: 1077 bytes --]

> but I think this can go in before we get rid of
> devtls; cpu bypasses the handshake, so as long as
> we keep devtls it should keep working regardless of
> libsec.

getting rid of devtls o_O? i think you meant devssl.

also, while reviewing my diff more, i found 2 more flaws
in it:

1. i shouldn't have scrapped the ssl2 handshake support.
i learned that some old versions of java that has tls 1.0
still sends the clienthello in the ssl2 format.

2. if initial clienthello has 0x0300 as its record layer
version, devtls will reject it with this diff. this is not good,
clients may put the minimum version they support
in the record layer version, for compatibility with
old servers. fix this up.

3 more changes, that is not related with the diff:

1. don't reject protocol versions that is higher than 0x03ff.
this behavior is useless.

2. devtls shouldn't accept versions higher
than 0x0303 in the fd and version commands.

3. in tlshand, use the minimum protocol version
we support for the record layer version for compatibility
until we manage to negotiate the version.

[-- Attachment #2: diff.txt --]
[-- Type: text/plain, Size: 30282 bytes --]

diff 5b5f69513adcb9939e4ebd93bf8adfbfdc08fcf1 uncommitted
--- a//sys/man/2/pushtls
+++ b//sys/man/2/pushtls
@@ -1,6 +1,6 @@
 .TH PUSHTLS 2
 .SH NAME
-pushtls, tlsClient, tlsServer, initThumbprints, freeThumbprints, okThumbprint, okCertificate, readcert, readcertchain \- attach TLS1 or SSL3 encryption to a communication channel
+pushtls, tlsClient, tlsServer, initThumbprints, freeThumbprints, okThumbprint, okCertificate, readcert, readcertchain \- attach TLS encryption to a communication channel
 .SH SYNOPSIS
 .B #include <u.h>
 .br
@@ -45,8 +45,6 @@
 and a handshake protocol,
 doing initial authentication and secret creation at
 user level and then starting a data channel in the record protocol.
-TLS is nearly the same as SSL 3.0, and the software should interoperate
-with implementations of either standard.
 .PP
 To use just the record layer, as described in
 .IR tls (3),
--- a//sys/man/3/tls
+++ b//sys/man/3/tls
@@ -1,6 +1,6 @@
 .TH TLS 3 
 .SH NAME
-tls \- TLS and SSL3 record layer
+tls \- TLS record layer
 .SH SYNOPSIS
 .nf
 .B bind -a #a /net
@@ -16,10 +16,9 @@
 .BI /net/tls/ n /status
 .fi
 .SH DESCRIPTION
-The TLS device implements the record layer protocols
-of Transport Layer Security version 1.0-1.2 and Secure Sockets Layer version 3.0.
-It does not implement the handshake protocols, which are responsible for
-mutual authentication and key exchange.
+The TLS device implements the record layer protocols of Transport Layer Security
+version 1.0-1.2. It does not implement the handshake protocols, which are responsible
+for mutual authentication and key exchange.
 The
 .I tls
 device can be thought of as filters providing optional encryption and anti-tampering.
@@ -53,13 +52,11 @@
 .I vers
 format records, but incoming messages of either version are accepted.
 Valid versions are
-.B 0x300
-for SSLv3.0 and
 .BR 0x301 ,
 .B 0x302
 and
 .B 0x303
-for TLSv1.0 (which could be known as SSLv3.01), TLSv1.1 and TLSv1.2.
+for TLSv1.0, TLSv1.1 and TLSv1.2.
 This command must be issued before any other command
 and before reading or writing any messages;
 it may only be executed once.
@@ -120,10 +117,9 @@
 .TP
 .BI alert \ alertno
 Send an alert message.
-.I Alertno
-may be a valid alert code for either SSLv3.0 or TLS,
-and is mapped to an appropriate code for the protocol in use.
-If it is a fatal alert, the filter is set into an error state.
+If
+.I alertno
+is a fatal alert, the filter is set into an error state.
 .PP
 Application messages and handshake messages are communicated using
 .I data
--- a//sys/src/9/port/devtls.c
+++ b//sys/src/9/port/devtls.c
@@ -1,5 +1,5 @@
 /*
- *  devtls - record layer for transport layer security 1.2 and secure sockets layer 3.0
+ *  devtls - record layer for transport layer security 1.0-1.2
  */
 #include	"u.h"
 #include	"../port/lib.h"
@@ -24,12 +24,11 @@
 	MaxMacLen	= SHA2_256dlen,
 
 	/* protocol versions we can accept */
-	SSL3Version	= 0x0300,
 	TLS10Version	= 0x0301,
 	TLS11Version	= 0x0302,
 	TLS12Version	= 0x0303,
-	MinProtoVersion	= 0x0300,	/* limits on version we accept */
-	MaxProtoVersion	= 0x03ff,
+	MinProtoVersion	= TLS10Version,	/* limits on version we accept */
+	MaxProtoVersion	= TLS12Version,
 
 	/* connection states */
 	SHandshake	= 1 << 0,	/* doing handshake */
@@ -57,7 +56,6 @@
 	ERecordOverflow 		= 22,
 	EDecompressionFailure 	= 30,
 	EHandshakeFailure 		= 40,
-	ENoCertificate 			= 41,
 	EBadCertificate 		= 42,
 	EUnsupportedCertificate 	= 43,
 	ECertificateRevoked 		= 44,
@@ -89,7 +87,6 @@
 
 	int		(*enc)(Secret*, uchar*, int);
 	int		(*dec)(Secret*, uchar*, int);
-	int		(*unpad)(uchar*, int, int);
 	DigestState*	(*mac)(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
 
 	int		block;		/* encryption block len, 0 if none */
@@ -125,12 +122,6 @@
 	int		state;
 	int		debug;
 
-	/*
-	 * function to genrate authenticated data blob for different
-	 * protocol versions
-	 */
-	int		(*packAAD)(u64int, uchar*, uchar*);
-
 	/* input side -- protected by in.io */
 	OneWay		in;
 	Block		*processed;	/* next bunch of application data */
@@ -153,37 +144,34 @@
 
 struct TlsErrs{
 	int	err;
-	int	sslerr;
-	int	tlserr;
 	int	fatal;
 	char	*msg;
 };
 
 static TlsErrs tlserrs[] = {
-	{ECloseNotify,			ECloseNotify,			ECloseNotify,			0, 	"close notify"},
-	{EUnexpectedMessage,	EUnexpectedMessage,	EUnexpectedMessage, 	1, "unexpected message"},
-	{EBadRecordMac,		EBadRecordMac,		EBadRecordMac, 		1, "bad record mac"},
-	{EDecryptionFailed,		EIllegalParameter,		EDecryptionFailed,		1, "decryption failed"},
-	{ERecordOverflow,		EIllegalParameter,		ERecordOverflow,		1, "record too long"},
-	{EDecompressionFailure,	EDecompressionFailure,	EDecompressionFailure,	1, "decompression failed"},
-	{EHandshakeFailure,		EHandshakeFailure,		EHandshakeFailure,		1, "could not negotiate acceptable security parameters"},
-	{ENoCertificate,		ENoCertificate,			ECertificateUnknown,	1, "no appropriate certificate available"},
-	{EBadCertificate,		EBadCertificate,		EBadCertificate,		1, "corrupted or invalid certificate"},
-	{EUnsupportedCertificate,	EUnsupportedCertificate,	EUnsupportedCertificate,	1, "unsupported certificate type"},
-	{ECertificateRevoked,	ECertificateRevoked,		ECertificateRevoked,		1, "revoked certificate"},
-	{ECertificateExpired,		ECertificateExpired,		ECertificateExpired,		1, "expired certificate"},
-	{ECertificateUnknown,	ECertificateUnknown,	ECertificateUnknown,	1, "unacceptable certificate"},
-	{EIllegalParameter,		EIllegalParameter,		EIllegalParameter,		1, "illegal parameter"},
-	{EUnknownCa,			EHandshakeFailure,		EUnknownCa,			1, "unknown certificate authority"},
-	{EAccessDenied,		EHandshakeFailure,		EAccessDenied,		1, "access denied"},
-	{EDecodeError,			EIllegalParameter,		EDecodeError,			1, "error decoding message"},
-	{EDecryptError,			EIllegalParameter,		EDecryptError,			1, "error decrypting message"},
-	{EExportRestriction,		EHandshakeFailure,		EExportRestriction,		1, "export restriction violated"},
-	{EProtocolVersion,		EIllegalParameter,		EProtocolVersion,		1, "protocol version not supported"},
-	{EInsufficientSecurity,	EHandshakeFailure,		EInsufficientSecurity,	1, "stronger security routines required"},
-	{EInternalError,			EHandshakeFailure,		EInternalError,			1, "internal error"},
-	{EUserCanceled,		ECloseNotify,			EUserCanceled,			0, "handshake canceled by user"},
-	{ENoRenegotiation,		EUnexpectedMessage,	ENoRenegotiation,		0, "no renegotiation"},
+	{ECloseNotify,			0, "close notify"},
+	{EUnexpectedMessage,		1, "unexpected message"},
+	{EBadRecordMac,			1, "bad record mac"},
+	{EDecryptionFailed,		1, "decryption failed"},
+	{ERecordOverflow,		1, "record too long"},
+	{EDecompressionFailure,		1, "decompression failed"},
+	{EHandshakeFailure,		1, "could not negotiate acceptable security parameters"},
+	{EBadCertificate,		1, "corrupted or invalid certificate"},
+	{EUnsupportedCertificate,	1, "unsupported certificate type"},
+	{ECertificateRevoked,		1, "revoked certificate"},
+	{ECertificateExpired,		1, "expired certificate"},
+	{ECertificateUnknown,		1, "unacceptable certificate"},
+	{EIllegalParameter,		1, "illegal parameter"},
+	{EUnknownCa,			1, "unknown certificate authority"},
+	{EAccessDenied,			1, "access denied"},
+	{EDecodeError,			1, "error decoding message"},
+	{EDecryptError,			1, "error decrypting message"},
+	{EExportRestriction,		1, "export restriction violated"},
+	{EProtocolVersion,		1, "protocol version not supported"},
+	{EInsufficientSecurity,		1, "stronger security routines required"},
+	{EInternalError,		1, "internal error"},
+	{EUserCanceled,			0, "handshake canceled by user"},
+	{ENoRenegotiation,		0, "no renegotiation"},
 };
 
 enum
@@ -227,11 +215,8 @@
 static void	alertHand(TlsRec*, char *);
 static TlsRec	*newtls(Chan *c);
 static TlsRec	*mktlsrec(void);
-static DigestState*sslmac_md5(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
-static DigestState*sslmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
 static DigestState*nomac(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
-static int	sslPackAAD(u64int, uchar*, uchar*);
-static int	tlsPackAAD(u64int, uchar*, uchar*);
+static int	packAAD(u64int, uchar*, uchar*);
 static void	packMac(Secret*, uchar*, int, uchar*, int, uchar*);
 static void	put64(uchar *p, u64int);
 static void	put32(uchar *p, u32int);
@@ -252,8 +237,7 @@
 static int	aesgcm_aead_enc(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len);
 static int	aesgcm_aead_dec(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len);
 static int	noenc(Secret *sec, uchar *buf, int n);
-static int	sslunpad(uchar *buf, int n, int block);
-static int	tlsunpad(uchar *buf, int n, int block);
+static int	unpad(uchar *buf, int n, int block);
 static void	freeSec(Secret *sec);
 static char	*tlsstate(int s);
 static void	pdump(int, void*, char*);
@@ -750,7 +734,7 @@
 	nconsumed = RecHdrLen;
 
 	if((tr->handin == 0) && (header[0] & 0x80)){
-		/* Cope with an SSL3 ClientHello expressed in SSL2 record format.
+		/* Cope with a TLS ClientHello expressed in SSL2 record format.
 			This is sent by some clients that we must interoperate
 			with, such as Java's JSSE and Microsoft's Internet Explorer. */
 		len = (get16(header) & ~0x8000) - 3;
@@ -758,12 +742,12 @@
 		ver = get16(header + 3);
 		if(type != SSL2ClientHello || len < 22)
 			rcvError(tr, EProtocolVersion, "invalid initial SSL2-like message");
-	}else{  /* normal SSL3 record format */
+	}else{  /* normal TLS record format */
 		type = header[0];
 		ver = get16(header+1);
 		len = get16(header+3);
 	}
-	if(ver != tr->version && (tr->verset || ver < MinProtoVersion || ver > MaxProtoVersion))
+	if(ver != tr->version && (tr->verset || ver < 0x0300))
 		rcvError(tr, EProtocolVersion, "devtls expected ver=%x%s, saw (len=%d) type=%x ver=%x '%.12s'",
 			tr->version, tr->verset?"/set":"", len, type, ver, (char*)header);
 	if(len > MaxCipherRecLen || len < 0)
@@ -823,7 +807,7 @@
 
 		/* update length */
 		put16(header+3, len);
-		aadlen = (*tr->packAAD)(in->seq++, header, aad);
+		aadlen = packAAD(in->seq++, header, aad);
 		if(sec->aead_dec != nil) {
 			len = (*sec->aead_dec)(sec, aad, aadlen, p - ivlen, p, unpad_len);
 			if(len < 0)
@@ -916,7 +900,7 @@
 			dechandq(tr);
 		}else{
 			unlock(&tr->hqlock);
-			if(tr->verset && tr->version != SSL3Version && !waserror()){
+			if(tr->verset && !waserror()){
 				sendAlert(tr, ENoRenegotiation);
 				poperror();
 			}
@@ -933,7 +917,7 @@
 			}
 			/* Pass the SSL2 format data, so that the handshake code can compute
 				the correct checksums.  HSSL2ClientHello = HandshakeType 9 is
-				unused in RFC2246. */
+				unused in RFC5246. */
 			b = padblock(b, 8);
 			b->rp[0] = RHandshake;
 			b->rp[1] = HSSL2ClientHello;
@@ -946,7 +930,7 @@
 			dechandq(tr);
 		}else{
 			unlock(&tr->hqlock);
-			if(tr->verset && tr->version != SSL3Version && !waserror()){
+			if(tr->verset && !waserror()){
 				sendAlert(tr, ENoRenegotiation);
 				poperror();
 			}
@@ -1314,7 +1298,7 @@
 		put16(p+3, n);
 
 		if(sec != nil){
-			aadlen = (*tr->packAAD)(out->seq++, p, aad);
+			aadlen = packAAD(out->seq++, p, aad);
 			if(sec->aead_enc != nil)
 				n = (*sec->aead_enc)(sec, aad, aadlen, p + RecHdrLen, p + RecHdrLen + ivlen, n) + ivlen;
 			else {
@@ -1390,42 +1374,34 @@
 {
 	char	*name;
 	int	maclen;
-	void	(*initkey)(Hashalg *, int, Secret *, uchar*);
+	void	(*initkey)(Hashalg *, Secret *, uchar*);
 };
 
 static void
-initmd5key(Hashalg *ha, int version, Secret *s, uchar *p)
+initmd5key(Hashalg *ha, Secret *s, uchar *p)
 {
 	s->maclen = ha->maclen;
-	if(version == SSL3Version)
-		s->mac = sslmac_md5;
-	else
-		s->mac = hmac_md5;
+	s->mac = hmac_md5;
 	memmove(s->mackey, p, ha->maclen);
 }
 
 static void
-initclearmac(Hashalg *, int, Secret *s, uchar *)
+initclearmac(Hashalg *, Secret *s, uchar *)
 {
 	s->mac = nomac;
 }
 
 static void
-initsha1key(Hashalg *ha, int version, Secret *s, uchar *p)
+initsha1key(Hashalg *ha, Secret *s, uchar *p)
 {
 	s->maclen = ha->maclen;
-	if(version == SSL3Version)
-		s->mac = sslmac_sha1;
-	else
-		s->mac = hmac_sha1;
+	s->mac = hmac_sha1;
 	memmove(s->mackey, p, ha->maclen);
 }
 
 static void
-initsha2_256key(Hashalg *ha, int version, Secret *s, uchar *p)
+initsha2_256key(Hashalg *ha, Secret *s, uchar *p)
 {
-	if(version == SSL3Version)
-		error("sha256 cannot be used with SSL");
 	s->maclen = ha->maclen;
 	s->mac = hmac_sha2_256;
 	memmove(s->mackey, p, ha->maclen);
@@ -1641,10 +1617,6 @@
 		m = strtol(cb->f[1], nil, 0);
 		if(m < MinProtoVersion || m > MaxProtoVersion)
 			error("unsupported version");
-		if(m == SSL3Version)
-			tr->packAAD = sslPackAAD;
-		else
-			tr->packAAD = tlsPackAAD;
 		tr->verset = 1;
 		tr->version = m;
 	}else if(strcmp(cb->f[0], "secret") == 0){
@@ -1685,8 +1657,8 @@
 		if(!ha->initkey || !ea->initkey)
 			error("misimplemented secret algorithm");
 
-		(*ha->initkey)(ha, tr->version, tos, &x[0]);
-		(*ha->initkey)(ha, tr->version, toc, &x[ha->maclen]);
+		(*ha->initkey)(ha, tos, &x[0]);
+		(*ha->initkey)(ha, toc, &x[ha->maclen]);
 		(*ea->initkey)(ea, tos, &x[2 * ha->maclen], &x[2 * ha->maclen + 2 * ea->keylen]);
 		(*ea->initkey)(ea, toc, &x[2 * ha->maclen + ea->keylen], &x[2 * ha->maclen + 2 * ea->keylen + ea->ivlen]);
 
@@ -1701,13 +1673,6 @@
 			tr->in.new = toc;
 			tr->out.new = tos;
 		}
-		if(tr->version == SSL3Version){
-			toc->unpad = sslunpad;
-			tos->unpad = sslunpad;
-		}else{
-			toc->unpad = tlsunpad;
-			tos->unpad = tlsunpad;
-		}
 		toc->encalg = ea->name;
 		toc->hashalg = ha->name;
 		tos->encalg = ea->name;
@@ -1879,17 +1844,12 @@
 if(tr->debug)pprint("sendAlert %d\n", err);
 	fatal = 1;
 	msg = "tls unknown alert";
-	for(i=0; i < nelem(tlserrs); i++) {
-		if(tlserrs[i].err == err) {
+	for(i=0; i < nelem(tlserrs); i++)
+		if(tlserrs[i].err == err){
 			msg = tlserrs[i].msg;
-			if(tr->version == SSL3Version)
-				err = tlserrs[i].sslerr;
-			else
-				err = tlserrs[i].tlserr;
 			fatal = tlserrs[i].fatal;
 			break;
 		}
-	}
 
 	if(!waserror()){
 		b = allocb(2);
@@ -2061,7 +2021,7 @@
 }
 
 static int
-tlsunpad(uchar *buf, int n, int block)
+unpad(uchar *buf, int n, int block)
 {
 	int pad, nn;
 
@@ -2076,18 +2036,6 @@
 }
 
 static int
-sslunpad(uchar *buf, int n, int block)
-{
-	int pad, nn;
-
-	pad = buf[n - 1];
-	nn = n - 1 - pad;
-	if(nn <= 0 || n % block)
-		return -1;
-	return nn;
-}
-
-static int
 blockpad(uchar *buf, int n, int block)
 {
 	int pad, nn;
@@ -2112,7 +2060,7 @@
 des3dec(Secret *sec, uchar *buf, int n)
 {
 	des3CBCdecrypt(buf, n, sec->enckey);
-	return (*sec->unpad)(buf, n, 8);
+	return unpad(buf, n, 8);
 }
 
 static int
@@ -2127,7 +2075,7 @@
 aesdec(Secret *sec, uchar *buf, int n)
 {
 	aesCBCdecrypt(buf, n, sec->enckey);
-	return (*sec->unpad)(buf, n, 16);
+	return unpad(buf, n, 16);
 }
 
 static void
@@ -2213,71 +2161,8 @@
 	return nil;
 }
 
-/*
- * sslmac: mac calculations for ssl 3.0 only; tls 1.0 uses the standard hmac.
- */
-static DigestState*
-sslmac_x(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s,
-	DigestState*(*x)(uchar*, ulong, uchar*, DigestState*), int xlen, int padlen)
-{
-	int i;
-	uchar pad[48], innerdigest[20];
-
-	if(xlen > sizeof(innerdigest)
-	|| padlen > sizeof(pad))
-		return nil;
-
-	if(klen>64)
-		return nil;
-
-	/* first time through */
-	if(s == nil){
-		for(i=0; i<padlen; i++)
-			pad[i] = 0x36;
-		s = (*x)(key, klen, nil, nil);
-		s = (*x)(pad, padlen, nil, s);
-		if(s == nil)
-			return nil;
-	}
-
-	s = (*x)(p, len, nil, s);
-	if(digest == nil)
-		return s;
-
-	/* last time through */
-	for(i=0; i<padlen; i++)
-		pad[i] = 0x5c;
-	(*x)(nil, 0, innerdigest, s);
-	s = (*x)(key, klen, nil, nil);
-	s = (*x)(pad, padlen, nil, s);
-	(*x)(innerdigest, xlen, digest, s);
-	return nil;
-}
-
-static DigestState*
-sslmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s)
-{
-	return sslmac_x(p, len, key, klen, digest, s, sha1, SHA1dlen, 40);
-}
-
-static DigestState*
-sslmac_md5(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s)
-{
-	return sslmac_x(p, len, key, klen, digest, s, md5, MD5dlen, 48);
-}
-
 static int
-sslPackAAD(u64int seq, uchar *hdr, uchar *aad)
-{
-	put64(aad, seq);
-	aad[8] = hdr[0];
-	aad[9] = hdr[3];
-	aad[10] = hdr[4];
-	return 11;
-}
-
-static int
-tlsPackAAD(u64int seq, uchar *hdr, uchar *aad)
+packAAD(u64int seq, uchar *hdr, uchar *aad)
 {
 	put64(aad, seq);
 	aad[8] = hdr[0];
--- a//sys/src/libsec/port/tlshand.c
+++ b//sys/src/libsec/port/tlshand.c
@@ -8,14 +8,13 @@
 //		client/server - main handshake protocol definition
 //		message functions - formating handshake messages
 //		cipher choices - catalog of digest and encrypt algorithms
-//		security functions - PKCS#1, sslHMAC, session keygen
+//		security functions - PKCS#1, session keygen
 //		general utility functions - malloc, serialization
-// The handshake protocol builds on the TLS/SSL3 record layer protocol,
-// which is implemented in kernel device #a.  See also /lib/rfc/rfc2246.
+// The handshake protocol builds on the TLS record layer protocol,
+// which is implemented in kernel device #a.  See also /lib/rfc/rfc5246.
 
 enum {
-	TLSFinishedLen = 12,
-	SSL3FinishedLen = MD5dlen+SHA1dlen,
+	FinishedLen = 12,
 	MaxKeyData = 160,	// amount of secret we may need
 	MAXdlen = SHA2_512dlen,
 	RandomSize = 32,
@@ -47,11 +46,6 @@
 	void (*init)(mpint *p, mpint *a, mpint *b, mpint *x, mpint *y, mpint *n, mpint *h);
 } Namedcurve;
 
-typedef struct Finished{
-	uchar verify[SSL3FinishedLen];
-	int n;
-} Finished;
-
 typedef struct HandshakeHash {
 	MD5state	md5;
 	SHAstate	sha1;
@@ -81,7 +75,6 @@
 	// byte generation and handshake checksum
 	void (*prf)(uchar*, int, uchar*, int, char*, uchar*, int);
 	void (*setFinished)(TlsSec*, HandshakeHash, uchar*, int);
-	int nfin;
 };
 
 typedef struct TlsConnection{
@@ -99,7 +92,7 @@
 
 	// for finished messages
 	HandshakeHash	handhash;
-	Finished	finished;
+	uchar		finished[FinishedLen];
 
 	uchar *sendp;
 	uchar buf[1<<16];
@@ -152,19 +145,17 @@
 			int sigalg;
 			Bytes *signature;
 		} certificateVerify;		
-		Finished finished;
+		uchar finished[FinishedLen];
 	} u;
 } Msg;
 
 
 enum {
-	SSL3Version	= 0x0300,
 	TLS10Version	= 0x0301,
 	TLS11Version	= 0x0302,
 	TLS12Version	= 0x0303,
 	ProtocolVersion	= TLS12Version,	// maximum version we speak
-	MinProtoVersion	= 0x0300,	// limits on version we accept
-	MaxProtoVersion	= 0x03ff,
+	MinProtoVersion	= TLS10Version,	// limits on version we accept
 };
 
 // handshake type
@@ -192,7 +183,6 @@
 	ERecordOverflow = 22,
 	EDecompressionFailure = 30,
 	EHandshakeFailure = 40,
-	ENoCertificate = 41,
 	EBadCertificate = 42,
 	EUnsupportedCertificate = 43,
 	ECertificateRevoked = 44,
@@ -367,7 +357,6 @@
 #pragma	varargck argpos	tlsError 3
 static int setVersion(TlsConnection *c, int version);
 static int setSecrets(TlsConnection *c, int isclient);
-static int finishedMatch(TlsConnection *c, Finished *f);
 static void tlsConnectionFree(TlsConnection *c);
 
 static int isDHE(int tlsid);
@@ -394,7 +383,6 @@
 static Bytes*	tlsSecDHEc(TlsSec *sec, Bytes *p, Bytes *g, Bytes *Ys);
 static Bytes*	tlsSecECDHEc(TlsSec *sec, int curve, Bytes *Ys);
 static void	tlsSecVers(TlsSec *sec, int v);
-static int	tlsSecFinished(TlsSec *sec, HandshakeHash hsh, uchar *fin, int nfin, int isclient);
 static void	setMasterSecret(TlsSec *sec, Bytes *pm);
 static int	digestDHparams(TlsSec *sec, Bytes *par, uchar digest[MAXdlen], int sigalg);
 static char*	verifyDHparams(TlsSec *sec, Bytes *par, Bytes *cert, Bytes *sig, int sigalg);
@@ -451,7 +439,7 @@
 		return -1;
 	}
 	data = -1;
-	fprint(ctl, "fd %d 0x%x", fd, ProtocolVersion);
+	fprint(ctl, "fd %d 0x%x", fd, MinProtoVersion);
 	tls = tlsServer2(ctl, hand,
 		conn->cert, conn->certlen,
 		conn->pskID, conn->psk, conn->psklen,
@@ -511,28 +499,26 @@
 	}
 
 	// Elliptic Curves (also called Supported Groups)
-	if(ProtocolVersion >= TLS10Version){
-		m = p - b;
-		b = erealloc(b, m + 2+2+2+nelem(namedcurves)*2 + 2+2+1+nelem(pointformats));
-		p = b + m;
+	m = p - b;
+	b = erealloc(b, m + 2+2+2+nelem(namedcurves)*2 + 2+2+1+nelem(pointformats));
+	p = b + m;
 
-		n = nelem(namedcurves);
-		put16(p, Extec), p += 2;	/* Type: elliptic_curves / supported_groups */
-		put16(p, (n+1)*2), p += 2;	/* Length */
-		put16(p, n*2), p += 2;		/* Elliptic Curves Length */
-		for(i=0; i < n; i++){		/* Elliptic Curves */
-			put16(p, namedcurves[i].tlsid);
-			p += 2;
-		}
-
-		n = nelem(pointformats);
-		put16(p, Extecp), p += 2;	/* Type: ec_point_formats */
-		put16(p, n+1), p += 2;		/* Length */
-		*p++ = n;			/* EC point formats Length */
-		for(i=0; i < n; i++)		/* EC point formats */
-			*p++ = pointformats[i];
+	n = nelem(namedcurves);
+	put16(p, Extec), p += 2;	/* Type: elliptic_curves / supported_groups */
+	put16(p, (n+1)*2), p += 2;	/* Length */
+	put16(p, n*2), p += 2;		/* Elliptic Curves Length */
+	for(i=0; i < n; i++){		/* Elliptic Curves */
+		put16(p, namedcurves[i].tlsid);
+		p += 2;
 	}
 
+	n = nelem(pointformats);
+	put16(p, Extecp), p += 2;	/* Type: ec_point_formats */
+	put16(p, n+1), p += 2;		/* Length */
+	*p++ = n;			/* EC point formats Length */
+	for(i=0; i < n; i++)		/* EC point formats */
+		*p++ = pointformats[i];
+
 	// signature algorithms
 	if(ProtocolVersion >= TLS12Version){
 		n = nelem(sigalgs);
@@ -591,7 +577,7 @@
 		close(ctl);
 		return -1;
 	}
-	fprint(ctl, "fd %d 0x%x", fd, ProtocolVersion);
+	fprint(ctl, "fd %d 0x%x", fd, MinProtoVersion);
 	ext = tlsClientExtensions(conn, &n);
 	tls = tlsClient2(ctl, hand,
 		conn->cert, conn->certlen, 
@@ -849,10 +835,7 @@
 	}
 
 	/* no CertificateVerify; skip to Finished */
-	if(tlsSecFinished(c->sec, c->handhash, c->finished.verify, c->finished.n, 1) < 0){
-		tlsError(c, EInternalError, "can't set finished: %r");
-		goto Err;
-	}
+	(*c->sec->setFinished)(c->sec, c->handhash, c->finished, 1);
 	if(!msgRecv(c, &m))
 		goto Err;
 	if(m.tag != HFinished) {
@@ -859,7 +842,7 @@
 		tlsError(c, EUnexpectedMessage, "expected a finished");
 		goto Err;
 	}
-	if(!finishedMatch(c, &m.u.finished)) {
+	if(tsmemcmp(c->finished, m.u.finished, FinishedLen) != 0) {
 		tlsError(c, EHandshakeFailure, "finished verification failed");
 		goto Err;
 	}
@@ -871,12 +854,9 @@
 		goto Err;
 	}
 
-	if(tlsSecFinished(c->sec, c->handhash, c->finished.verify, c->finished.n, 0) < 0){
-		tlsError(c, EInternalError, "can't set finished: %r");
-		goto Err;
-	}
+	(*c->sec->setFinished)(c->sec, c->handhash, c->finished, 0);
 	m.tag = HFinished;
-	m.u.finished = c->finished;
+	memmove(m.u.finished, c->finished, FinishedLen);
 	if(!msgSend(c, &m, AFlush))
 		goto Err;
 	if(trace)
@@ -1220,21 +1200,15 @@
 
 	// Cipherchange must occur immediately before Finished to avoid
 	// potential hole;  see section 4.3 of Wagner Schneier 1996.
-	if(tlsSecFinished(c->sec, c->handhash, c->finished.verify, c->finished.n, 1) < 0){
-		tlsError(c, EInternalError, "can't set finished 1: %r");
-		goto Err;
-	}
+	(*c->sec->setFinished)(c->sec, c->handhash, c->finished, 1);
 	m.tag = HFinished;
-	m.u.finished = c->finished;
+	memmove(m.u.finished, c->finished, FinishedLen);
 	if(!msgSend(c, &m, AFlush)) {
 		tlsError(c, EInternalError, "can't flush after client Finished: %r");
 		goto Err;
 	}
 
-	if(tlsSecFinished(c->sec, c->handhash, c->finished.verify, c->finished.n, 0) < 0){
-		tlsError(c, EInternalError, "can't set finished 0: %r");
-		goto Err;
-	}
+	(*c->sec->setFinished)(c->sec, c->handhash, c->finished, 0);
 	if(!msgRecv(c, &m)) {
 		tlsError(c, EInternalError, "can't read server Finished: %r");
 		goto Err;
@@ -1244,7 +1218,7 @@
 		goto Err;
 	}
 
-	if(!finishedMatch(c, &m.u.finished)) {
+	if(tsmemcmp(c->finished, m.u.finished, FinishedLen) != 0) {
 		tlsError(c, EHandshakeFailure, "finished verification failed");
 		goto Err;
 	}
@@ -1418,16 +1392,16 @@
 			goto Overflow;
 		if(isECDHE(c->cipher))
 			*p++ = n;
-		else if(isDHE(c->cipher) || c->version != SSL3Version)
+		else
 			put16(p, n), p += 2;
 		memmove(p, m->u.clientKeyExchange.key->data, n);
 		p += n;
 		break;
 	case HFinished:
-		if(p+m->u.finished.n > e)
+		if(p+FinishedLen > e)
 			goto Overflow;
-		memmove(p, m->u.finished.verify, m->u.finished.n);
-		p += m->u.finished.n;
+		memmove(p, m->u.finished, FinishedLen);
+		p += FinishedLen;
 		break;
 	}
 
@@ -1496,7 +1470,7 @@
 	}
 
 	if(type == HSSL2ClientHello){
-		/* Cope with an SSL3 ClientHello expressed in SSL2 record format.
+		/* Cope with an TLS ClientHello expressed in SSL2 record format.
 			This is sent by some clients that we must interoperate
 			with, such as Java's JSSE and Microsoft's Internet Explorer. */
 		int nsid, nrandom, nciph;
@@ -1519,7 +1493,7 @@
 		if(nsid != 0 	/* no sid's, since shouldn't restart using ssl2 header */
 		|| nrandom < 16 || nn % 3 || n - nrandom < nn)
 			goto Err;
-		/* ignore ssl2 ciphers and look for {0x00, ssl3 cipher} */
+		/* ignore ssl2 ciphers and look for {0x00, tls cipher} */
 		nciph = 0;
 		for(i = 0; i < nn; i += 3)
 			if(p[i] == 0)
@@ -1790,10 +1764,8 @@
 			goto Short;
 		if(isECDHE(c->cipher))
 			nn = *p++, n--;
-		else if(isDHE(c->cipher) || c->version != SSL3Version)
-			nn = get16(p), p += 2, n -= 2;
 		else
-			nn = n;
+			nn = get16(p), p += 2, n -= 2;
 		if(n < nn)
 			goto Short;
 		m->u.clientKeyExchange.key = makebytes(p, nn);
@@ -1800,11 +1772,10 @@
 		n -= nn;
 		break;
 	case HFinished:
-		m->u.finished.n = c->finished.n;
-		if(n < m->u.finished.n)
+		if(n < FinishedLen)
 			goto Short;
-		memmove(m->u.finished.verify, p, m->u.finished.n);
-		n -= m->u.finished.n;
+		memmove(m->u.finished, p, FinishedLen);
+		n -= FinishedLen;
 		break;
 	}
 
@@ -2000,8 +1971,8 @@
 		break;
 	case HFinished:
 		bs = seprint(bs, be, "HFinished\n");
-		for(i=0; i<m->u.finished.n; i++)
-			bs = seprint(bs, be, "%.2x", m->u.finished.verify[i]);
+		for(i=0; i<FinishedLen; i++)
+			bs = seprint(bs, be, "%.2x", m->u.finished[i]);
 		bs = seprint(bs, be, "\n");
 		break;
 	}
@@ -2032,27 +2003,15 @@
 static int
 setVersion(TlsConnection *c, int version)
 {
-	if(version > MaxProtoVersion || version < MinProtoVersion)
+	if(version < MinProtoVersion)
 		return -1;
 	if(version > c->version)
 		version = c->version;
-	if(version == SSL3Version) {
+	else
 		c->version = version;
-		c->finished.n = SSL3FinishedLen;
-	}else {
-		c->version = version;
-		c->finished.n = TLSFinishedLen;
-	}
 	return fprint(c->ctl, "version 0x%x", version);
 }
 
-// confirm that received Finished message matches the expected value
-static int
-finishedMatch(TlsConnection *c, Finished *f)
-{
-	return tsmemcmp(f->verify, c->finished.verify, f->n) == 0;
-}
-
 // free memory associated with TlsConnection struct
 //		(but don't close the TLS channel itself)
 static void
@@ -2390,68 +2349,6 @@
 		hmac_sha2_256, SHA2_256dlen);
 }
 
-static void
-sslPRF(uchar *buf, int nbuf, uchar *key, int nkey, char *label, uchar *seed, int nseed)
-{
-	uchar sha1dig[SHA1dlen], md5dig[MD5dlen], tmp[26];
-	DigestState *s;
-	int i, n, len;
-
-	USED(label);
-	len = 1;
-	while(nbuf > 0){
-		if(len > 26)
-			return;
-		for(i = 0; i < len; i++)
-			tmp[i] = 'A' - 1 + len;
-		s = sha1(tmp, len, nil, nil);
-		s = sha1(key, nkey, nil, s);
-		sha1(seed, nseed, sha1dig, s);
-		s = md5(key, nkey, nil, nil);
-		md5(sha1dig, SHA1dlen, md5dig, s);
-		n = MD5dlen;
-		if(n > nbuf)
-			n = nbuf;
-		memmove(buf, md5dig, n);
-		buf += n;
-		nbuf -= n;
-		len++;
-	}
-}
-
-static void
-sslSetFinished(TlsSec *sec, HandshakeHash hsh, uchar *finished, int isclient)
-{
-	DigestState *s;
-	uchar h0[MD5dlen], h1[SHA1dlen], pad[48];
-	char *label;
-
-	if(isclient)
-		label = "CLNT";
-	else
-		label = "SRVR";
-
-	md5((uchar*)label, 4, nil, &hsh.md5);
-	md5(sec->sec, MasterSecretSize, nil, &hsh.md5);
-	memset(pad, 0x36, 48);
-	md5(pad, 48, nil, &hsh.md5);
-	md5(nil, 0, h0, &hsh.md5);
-	memset(pad, 0x5C, 48);
-	s = md5(sec->sec, MasterSecretSize, nil, nil);
-	s = md5(pad, 48, nil, s);
-	md5(h0, MD5dlen, finished, s);
-
-	sha1((uchar*)label, 4, nil, &hsh.sha1);
-	sha1(sec->sec, MasterSecretSize, nil, &hsh.sha1);
-	memset(pad, 0x36, 40);
-	sha1(pad, 40, nil, &hsh.sha1);
-	sha1(nil, 0, h1, &hsh.sha1);
-	memset(pad, 0x5C, 40);
-	s = sha1(sec->sec, MasterSecretSize, nil, nil);
-	s = sha1(pad, 40, nil, s);
-	sha1(h1, SHA1dlen, finished + MD5dlen, s);
-}
-
 // fill "finished" arg with md5(args)^sha1(args)
 static void
 tls10SetFinished(TlsSec *sec, HandshakeHash hsh, uchar *finished, int isclient)
@@ -2460,6 +2357,8 @@
 	char *label;
 
 	// get current hash value, but allow further messages to be hashed in
+	hsh.md5.malloced = 0;
+	hsh.sha1.malloced = 0;
 	md5(nil, 0, h, &hsh.md5);
 	sha1(nil, 0, h+MD5dlen, &hsh.sha1);
 
@@ -2467,7 +2366,7 @@
 		label = "client finished";
 	else
 		label = "server finished";
-	tls10PRF(finished, TLSFinishedLen, sec->sec, MasterSecretSize, label, h, sizeof(h));
+	tls10PRF(finished, FinishedLen, sec->sec, MasterSecretSize, label, h, sizeof(h));
 }
 
 static void
@@ -2477,6 +2376,7 @@
 	char *label;
 
 	// get current hash value, but allow further messages to be hashed in
+	hsh.sha2_256.malloced = 0;
 	sha2_256(nil, 0, seed, &hsh.sha2_256);
 
 	if(isclient)
@@ -2483,7 +2383,7 @@
 		label = "client finished";
 	else
 		label = "server finished";
-	tls12PRF(finished, TLSFinishedLen, sec->sec, MasterSecretSize, label, seed, SHA2_256dlen);
+	tls12PRF(finished, FinishedLen, sec->sec, MasterSecretSize, label, seed, SHA2_256dlen);
 }
 
 static void
@@ -2630,34 +2530,14 @@
 	return epm;
 }
 
-static int
-tlsSecFinished(TlsSec *sec, HandshakeHash hsh, uchar *fin, int nfin, int isclient)
-{
-	if(sec->nfin != nfin){
-		werrstr("invalid finished exchange");
-		return -1;
-	}
-	hsh.md5.malloced = 0;
-	hsh.sha1.malloced = 0;
-	hsh.sha2_256.malloced = 0;
-	(*sec->setFinished)(sec, hsh, fin, isclient);
-	return 0;
-}
-
 static void
 tlsSecVers(TlsSec *sec, int v)
 {
-	if(v == SSL3Version){
-		sec->setFinished = sslSetFinished;
-		sec->nfin = SSL3FinishedLen;
-		sec->prf = sslPRF;
-	}else if(v < TLS12Version) {
+	if(v < TLS12Version){
 		sec->setFinished = tls10SetFinished;
-		sec->nfin = TLSFinishedLen;
 		sec->prf = tls10PRF;
-	}else {
+	}else{
 		sec->setFinished = tls12SetFinished;
-		sec->nfin = TLSFinishedLen;
 		sec->prf = tls12PRF;
 	}
 }

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [9front] intent to delete: devssl, cpu, oexportfs, import
  2021-10-23 20:13         ` kemal
@ 2021-10-24 11:46           ` kemal
  2021-10-24 16:06             ` cinap_lenrek
  2021-10-24 16:14             ` cinap_lenrek
  0 siblings, 2 replies; 20+ messages in thread
From: kemal @ 2021-10-24 11:46 UTC (permalink / raw)
  To: 9front

[-- Attachment #1: Type: text/plain, Size: 808 bytes --]

i am sending a new diff, again. i apologise for sending 4 different
diffs for this, i definitely should have checked my diff better...

> 1. don't reject protocol versions that is higher than 0x03ff.
> this behavior is useless.

it is if it's checking the clienthello/serverhello version,
but not if we're checking the record layer version! it might
accept non-TLS data if it doesn't check `major version == 0x03`.
add that behavior back for devtls.

also, 2 more problems i saw in version negotiation code:

1. when setVersion fails, code sends a "illegal_parameter" alert
but "protocol_version" is more suitable and the standard way
for this. send "protocol_version" instead.

2. tlsClient2 should abort if the server sends a version higher
than `c->version`. fix up.

the new (and last) diff is attached.

[-- Attachment #2: diff.txt --]
[-- Type: text/plain, Size: 31496 bytes --]

diff 5b5f69513adcb9939e4ebd93bf8adfbfdc08fcf1 uncommitted
--- a//sys/man/2/pushtls
+++ b//sys/man/2/pushtls
@@ -1,6 +1,6 @@
 .TH PUSHTLS 2
 .SH NAME
-pushtls, tlsClient, tlsServer, initThumbprints, freeThumbprints, okThumbprint, okCertificate, readcert, readcertchain \- attach TLS1 or SSL3 encryption to a communication channel
+pushtls, tlsClient, tlsServer, initThumbprints, freeThumbprints, okThumbprint, okCertificate, readcert, readcertchain \- attach TLS encryption to a communication channel
 .SH SYNOPSIS
 .B #include <u.h>
 .br
@@ -45,8 +45,6 @@
 and a handshake protocol,
 doing initial authentication and secret creation at
 user level and then starting a data channel in the record protocol.
-TLS is nearly the same as SSL 3.0, and the software should interoperate
-with implementations of either standard.
 .PP
 To use just the record layer, as described in
 .IR tls (3),
--- a//sys/man/3/tls
+++ b//sys/man/3/tls
@@ -1,6 +1,6 @@
 .TH TLS 3 
 .SH NAME
-tls \- TLS and SSL3 record layer
+tls \- TLS record layer
 .SH SYNOPSIS
 .nf
 .B bind -a #a /net
@@ -16,10 +16,9 @@
 .BI /net/tls/ n /status
 .fi
 .SH DESCRIPTION
-The TLS device implements the record layer protocols
-of Transport Layer Security version 1.0-1.2 and Secure Sockets Layer version 3.0.
-It does not implement the handshake protocols, which are responsible for
-mutual authentication and key exchange.
+The TLS device implements the record layer protocols of Transport Layer Security
+version 1.0-1.2. It does not implement the handshake protocols, which are responsible
+for mutual authentication and key exchange.
 The
 .I tls
 device can be thought of as filters providing optional encryption and anti-tampering.
@@ -53,13 +52,11 @@
 .I vers
 format records, but incoming messages of either version are accepted.
 Valid versions are
-.B 0x300
-for SSLv3.0 and
 .BR 0x301 ,
 .B 0x302
 and
 .B 0x303
-for TLSv1.0 (which could be known as SSLv3.01), TLSv1.1 and TLSv1.2.
+for TLSv1.0, TLSv1.1 and TLSv1.2.
 This command must be issued before any other command
 and before reading or writing any messages;
 it may only be executed once.
@@ -120,10 +117,9 @@
 .TP
 .BI alert \ alertno
 Send an alert message.
-.I Alertno
-may be a valid alert code for either SSLv3.0 or TLS,
-and is mapped to an appropriate code for the protocol in use.
-If it is a fatal alert, the filter is set into an error state.
+If
+.I alertno
+is a fatal alert, the filter is set into an error state.
 .PP
 Application messages and handshake messages are communicated using
 .I data
--- a//sys/src/9/port/devtls.c
+++ b//sys/src/9/port/devtls.c
@@ -1,5 +1,5 @@
 /*
- *  devtls - record layer for transport layer security 1.2 and secure sockets layer 3.0
+ *  devtls - record layer for transport layer security 1.0-1.2
  */
 #include	"u.h"
 #include	"../port/lib.h"
@@ -24,12 +24,11 @@
 	MaxMacLen	= SHA2_256dlen,
 
 	/* protocol versions we can accept */
-	SSL3Version	= 0x0300,
 	TLS10Version	= 0x0301,
 	TLS11Version	= 0x0302,
 	TLS12Version	= 0x0303,
-	MinProtoVersion	= 0x0300,	/* limits on version we accept */
-	MaxProtoVersion	= 0x03ff,
+	MinProtoVersion	= TLS10Version,	/* limits on version we accept */
+	MaxProtoVersion	= TLS12Version,
 
 	/* connection states */
 	SHandshake	= 1 << 0,	/* doing handshake */
@@ -57,7 +56,6 @@
 	ERecordOverflow 		= 22,
 	EDecompressionFailure 	= 30,
 	EHandshakeFailure 		= 40,
-	ENoCertificate 			= 41,
 	EBadCertificate 		= 42,
 	EUnsupportedCertificate 	= 43,
 	ECertificateRevoked 		= 44,
@@ -89,7 +87,6 @@
 
 	int		(*enc)(Secret*, uchar*, int);
 	int		(*dec)(Secret*, uchar*, int);
-	int		(*unpad)(uchar*, int, int);
 	DigestState*	(*mac)(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
 
 	int		block;		/* encryption block len, 0 if none */
@@ -125,12 +122,6 @@
 	int		state;
 	int		debug;
 
-	/*
-	 * function to genrate authenticated data blob for different
-	 * protocol versions
-	 */
-	int		(*packAAD)(u64int, uchar*, uchar*);
-
 	/* input side -- protected by in.io */
 	OneWay		in;
 	Block		*processed;	/* next bunch of application data */
@@ -153,37 +144,34 @@
 
 struct TlsErrs{
 	int	err;
-	int	sslerr;
-	int	tlserr;
 	int	fatal;
 	char	*msg;
 };
 
 static TlsErrs tlserrs[] = {
-	{ECloseNotify,			ECloseNotify,			ECloseNotify,			0, 	"close notify"},
-	{EUnexpectedMessage,	EUnexpectedMessage,	EUnexpectedMessage, 	1, "unexpected message"},
-	{EBadRecordMac,		EBadRecordMac,		EBadRecordMac, 		1, "bad record mac"},
-	{EDecryptionFailed,		EIllegalParameter,		EDecryptionFailed,		1, "decryption failed"},
-	{ERecordOverflow,		EIllegalParameter,		ERecordOverflow,		1, "record too long"},
-	{EDecompressionFailure,	EDecompressionFailure,	EDecompressionFailure,	1, "decompression failed"},
-	{EHandshakeFailure,		EHandshakeFailure,		EHandshakeFailure,		1, "could not negotiate acceptable security parameters"},
-	{ENoCertificate,		ENoCertificate,			ECertificateUnknown,	1, "no appropriate certificate available"},
-	{EBadCertificate,		EBadCertificate,		EBadCertificate,		1, "corrupted or invalid certificate"},
-	{EUnsupportedCertificate,	EUnsupportedCertificate,	EUnsupportedCertificate,	1, "unsupported certificate type"},
-	{ECertificateRevoked,	ECertificateRevoked,		ECertificateRevoked,		1, "revoked certificate"},
-	{ECertificateExpired,		ECertificateExpired,		ECertificateExpired,		1, "expired certificate"},
-	{ECertificateUnknown,	ECertificateUnknown,	ECertificateUnknown,	1, "unacceptable certificate"},
-	{EIllegalParameter,		EIllegalParameter,		EIllegalParameter,		1, "illegal parameter"},
-	{EUnknownCa,			EHandshakeFailure,		EUnknownCa,			1, "unknown certificate authority"},
-	{EAccessDenied,		EHandshakeFailure,		EAccessDenied,		1, "access denied"},
-	{EDecodeError,			EIllegalParameter,		EDecodeError,			1, "error decoding message"},
-	{EDecryptError,			EIllegalParameter,		EDecryptError,			1, "error decrypting message"},
-	{EExportRestriction,		EHandshakeFailure,		EExportRestriction,		1, "export restriction violated"},
-	{EProtocolVersion,		EIllegalParameter,		EProtocolVersion,		1, "protocol version not supported"},
-	{EInsufficientSecurity,	EHandshakeFailure,		EInsufficientSecurity,	1, "stronger security routines required"},
-	{EInternalError,			EHandshakeFailure,		EInternalError,			1, "internal error"},
-	{EUserCanceled,		ECloseNotify,			EUserCanceled,			0, "handshake canceled by user"},
-	{ENoRenegotiation,		EUnexpectedMessage,	ENoRenegotiation,		0, "no renegotiation"},
+	{ECloseNotify,			0, "close notify"},
+	{EUnexpectedMessage,		1, "unexpected message"},
+	{EBadRecordMac,			1, "bad record mac"},
+	{EDecryptionFailed,		1, "decryption failed"},
+	{ERecordOverflow,		1, "record too long"},
+	{EDecompressionFailure,		1, "decompression failed"},
+	{EHandshakeFailure,		1, "could not negotiate acceptable security parameters"},
+	{EBadCertificate,		1, "corrupted or invalid certificate"},
+	{EUnsupportedCertificate,	1, "unsupported certificate type"},
+	{ECertificateRevoked,		1, "revoked certificate"},
+	{ECertificateExpired,		1, "expired certificate"},
+	{ECertificateUnknown,		1, "unacceptable certificate"},
+	{EIllegalParameter,		1, "illegal parameter"},
+	{EUnknownCa,			1, "unknown certificate authority"},
+	{EAccessDenied,			1, "access denied"},
+	{EDecodeError,			1, "error decoding message"},
+	{EDecryptError,			1, "error decrypting message"},
+	{EExportRestriction,		1, "export restriction violated"},
+	{EProtocolVersion,		1, "protocol version not supported"},
+	{EInsufficientSecurity,		1, "stronger security routines required"},
+	{EInternalError,		1, "internal error"},
+	{EUserCanceled,			0, "handshake canceled by user"},
+	{ENoRenegotiation,		0, "no renegotiation"},
 };
 
 enum
@@ -227,11 +215,8 @@
 static void	alertHand(TlsRec*, char *);
 static TlsRec	*newtls(Chan *c);
 static TlsRec	*mktlsrec(void);
-static DigestState*sslmac_md5(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
-static DigestState*sslmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
 static DigestState*nomac(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s);
-static int	sslPackAAD(u64int, uchar*, uchar*);
-static int	tlsPackAAD(u64int, uchar*, uchar*);
+static int	packAAD(u64int, uchar*, uchar*);
 static void	packMac(Secret*, uchar*, int, uchar*, int, uchar*);
 static void	put64(uchar *p, u64int);
 static void	put32(uchar *p, u32int);
@@ -252,8 +237,7 @@
 static int	aesgcm_aead_enc(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len);
 static int	aesgcm_aead_dec(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len);
 static int	noenc(Secret *sec, uchar *buf, int n);
-static int	sslunpad(uchar *buf, int n, int block);
-static int	tlsunpad(uchar *buf, int n, int block);
+static int	unpad(uchar *buf, int n, int block);
 static void	freeSec(Secret *sec);
 static char	*tlsstate(int s);
 static void	pdump(int, void*, char*);
@@ -750,7 +734,7 @@
 	nconsumed = RecHdrLen;
 
 	if((tr->handin == 0) && (header[0] & 0x80)){
-		/* Cope with an SSL3 ClientHello expressed in SSL2 record format.
+		/* Cope with a TLS ClientHello expressed in SSL2 record format.
 			This is sent by some clients that we must interoperate
 			with, such as Java's JSSE and Microsoft's Internet Explorer. */
 		len = (get16(header) & ~0x8000) - 3;
@@ -757,13 +741,13 @@
 		type = header[2];
 		ver = get16(header + 3);
 		if(type != SSL2ClientHello || len < 22)
-			rcvError(tr, EProtocolVersion, "invalid initial SSL2-like message");
-	}else{  /* normal SSL3 record format */
+			rcvError(tr, EUnexpectedMessage, "invalid initial SSL2-like message");
+	}else{  /* normal TLS record format */
 		type = header[0];
 		ver = get16(header+1);
 		len = get16(header+3);
 	}
-	if(ver != tr->version && (tr->verset || ver < MinProtoVersion || ver > MaxProtoVersion))
+	if(ver != tr->version && (tr->verset || ver>>8 != 0x03))
 		rcvError(tr, EProtocolVersion, "devtls expected ver=%x%s, saw (len=%d) type=%x ver=%x '%.12s'",
 			tr->version, tr->verset?"/set":"", len, type, ver, (char*)header);
 	if(len > MaxCipherRecLen || len < 0)
@@ -823,7 +807,7 @@
 
 		/* update length */
 		put16(header+3, len);
-		aadlen = (*tr->packAAD)(in->seq++, header, aad);
+		aadlen = packAAD(in->seq++, header, aad);
 		if(sec->aead_dec != nil) {
 			len = (*sec->aead_dec)(sec, aad, aadlen, p - ivlen, p, unpad_len);
 			if(len < 0)
@@ -916,7 +900,7 @@
 			dechandq(tr);
 		}else{
 			unlock(&tr->hqlock);
-			if(tr->verset && tr->version != SSL3Version && !waserror()){
+			if(tr->verset && !waserror()){
 				sendAlert(tr, ENoRenegotiation);
 				poperror();
 			}
@@ -933,7 +917,7 @@
 			}
 			/* Pass the SSL2 format data, so that the handshake code can compute
 				the correct checksums.  HSSL2ClientHello = HandshakeType 9 is
-				unused in RFC2246. */
+				unused in RFC5246. */
 			b = padblock(b, 8);
 			b->rp[0] = RHandshake;
 			b->rp[1] = HSSL2ClientHello;
@@ -946,7 +930,7 @@
 			dechandq(tr);
 		}else{
 			unlock(&tr->hqlock);
-			if(tr->verset && tr->version != SSL3Version && !waserror()){
+			if(tr->verset && !waserror()){
 				sendAlert(tr, ENoRenegotiation);
 				poperror();
 			}
@@ -1314,7 +1298,7 @@
 		put16(p+3, n);
 
 		if(sec != nil){
-			aadlen = (*tr->packAAD)(out->seq++, p, aad);
+			aadlen = packAAD(out->seq++, p, aad);
 			if(sec->aead_enc != nil)
 				n = (*sec->aead_enc)(sec, aad, aadlen, p + RecHdrLen, p + RecHdrLen + ivlen, n) + ivlen;
 			else {
@@ -1390,42 +1374,34 @@
 {
 	char	*name;
 	int	maclen;
-	void	(*initkey)(Hashalg *, int, Secret *, uchar*);
+	void	(*initkey)(Hashalg *, Secret *, uchar*);
 };
 
 static void
-initmd5key(Hashalg *ha, int version, Secret *s, uchar *p)
+initmd5key(Hashalg *ha, Secret *s, uchar *p)
 {
 	s->maclen = ha->maclen;
-	if(version == SSL3Version)
-		s->mac = sslmac_md5;
-	else
-		s->mac = hmac_md5;
+	s->mac = hmac_md5;
 	memmove(s->mackey, p, ha->maclen);
 }
 
 static void
-initclearmac(Hashalg *, int, Secret *s, uchar *)
+initclearmac(Hashalg *, Secret *s, uchar *)
 {
 	s->mac = nomac;
 }
 
 static void
-initsha1key(Hashalg *ha, int version, Secret *s, uchar *p)
+initsha1key(Hashalg *ha, Secret *s, uchar *p)
 {
 	s->maclen = ha->maclen;
-	if(version == SSL3Version)
-		s->mac = sslmac_sha1;
-	else
-		s->mac = hmac_sha1;
+	s->mac = hmac_sha1;
 	memmove(s->mackey, p, ha->maclen);
 }
 
 static void
-initsha2_256key(Hashalg *ha, int version, Secret *s, uchar *p)
+initsha2_256key(Hashalg *ha, Secret *s, uchar *p)
 {
-	if(version == SSL3Version)
-		error("sha256 cannot be used with SSL");
 	s->maclen = ha->maclen;
 	s->mac = hmac_sha2_256;
 	memmove(s->mackey, p, ha->maclen);
@@ -1641,10 +1617,6 @@
 		m = strtol(cb->f[1], nil, 0);
 		if(m < MinProtoVersion || m > MaxProtoVersion)
 			error("unsupported version");
-		if(m == SSL3Version)
-			tr->packAAD = sslPackAAD;
-		else
-			tr->packAAD = tlsPackAAD;
 		tr->verset = 1;
 		tr->version = m;
 	}else if(strcmp(cb->f[0], "secret") == 0){
@@ -1685,8 +1657,8 @@
 		if(!ha->initkey || !ea->initkey)
 			error("misimplemented secret algorithm");
 
-		(*ha->initkey)(ha, tr->version, tos, &x[0]);
-		(*ha->initkey)(ha, tr->version, toc, &x[ha->maclen]);
+		(*ha->initkey)(ha, tos, &x[0]);
+		(*ha->initkey)(ha, toc, &x[ha->maclen]);
 		(*ea->initkey)(ea, tos, &x[2 * ha->maclen], &x[2 * ha->maclen + 2 * ea->keylen]);
 		(*ea->initkey)(ea, toc, &x[2 * ha->maclen + ea->keylen], &x[2 * ha->maclen + 2 * ea->keylen + ea->ivlen]);
 
@@ -1701,13 +1673,6 @@
 			tr->in.new = toc;
 			tr->out.new = tos;
 		}
-		if(tr->version == SSL3Version){
-			toc->unpad = sslunpad;
-			tos->unpad = sslunpad;
-		}else{
-			toc->unpad = tlsunpad;
-			tos->unpad = tlsunpad;
-		}
 		toc->encalg = ea->name;
 		toc->hashalg = ha->name;
 		tos->encalg = ea->name;
@@ -1879,17 +1844,12 @@
 if(tr->debug)pprint("sendAlert %d\n", err);
 	fatal = 1;
 	msg = "tls unknown alert";
-	for(i=0; i < nelem(tlserrs); i++) {
-		if(tlserrs[i].err == err) {
+	for(i=0; i < nelem(tlserrs); i++)
+		if(tlserrs[i].err == err){
 			msg = tlserrs[i].msg;
-			if(tr->version == SSL3Version)
-				err = tlserrs[i].sslerr;
-			else
-				err = tlserrs[i].tlserr;
 			fatal = tlserrs[i].fatal;
 			break;
 		}
-	}
 
 	if(!waserror()){
 		b = allocb(2);
@@ -2061,7 +2021,7 @@
 }
 
 static int
-tlsunpad(uchar *buf, int n, int block)
+unpad(uchar *buf, int n, int block)
 {
 	int pad, nn;
 
@@ -2076,18 +2036,6 @@
 }
 
 static int
-sslunpad(uchar *buf, int n, int block)
-{
-	int pad, nn;
-
-	pad = buf[n - 1];
-	nn = n - 1 - pad;
-	if(nn <= 0 || n % block)
-		return -1;
-	return nn;
-}
-
-static int
 blockpad(uchar *buf, int n, int block)
 {
 	int pad, nn;
@@ -2112,7 +2060,7 @@
 des3dec(Secret *sec, uchar *buf, int n)
 {
 	des3CBCdecrypt(buf, n, sec->enckey);
-	return (*sec->unpad)(buf, n, 8);
+	return unpad(buf, n, 8);
 }
 
 static int
@@ -2127,7 +2075,7 @@
 aesdec(Secret *sec, uchar *buf, int n)
 {
 	aesCBCdecrypt(buf, n, sec->enckey);
-	return (*sec->unpad)(buf, n, 16);
+	return unpad(buf, n, 16);
 }
 
 static void
@@ -2213,71 +2161,8 @@
 	return nil;
 }
 
-/*
- * sslmac: mac calculations for ssl 3.0 only; tls 1.0 uses the standard hmac.
- */
-static DigestState*
-sslmac_x(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s,
-	DigestState*(*x)(uchar*, ulong, uchar*, DigestState*), int xlen, int padlen)
-{
-	int i;
-	uchar pad[48], innerdigest[20];
-
-	if(xlen > sizeof(innerdigest)
-	|| padlen > sizeof(pad))
-		return nil;
-
-	if(klen>64)
-		return nil;
-
-	/* first time through */
-	if(s == nil){
-		for(i=0; i<padlen; i++)
-			pad[i] = 0x36;
-		s = (*x)(key, klen, nil, nil);
-		s = (*x)(pad, padlen, nil, s);
-		if(s == nil)
-			return nil;
-	}
-
-	s = (*x)(p, len, nil, s);
-	if(digest == nil)
-		return s;
-
-	/* last time through */
-	for(i=0; i<padlen; i++)
-		pad[i] = 0x5c;
-	(*x)(nil, 0, innerdigest, s);
-	s = (*x)(key, klen, nil, nil);
-	s = (*x)(pad, padlen, nil, s);
-	(*x)(innerdigest, xlen, digest, s);
-	return nil;
-}
-
-static DigestState*
-sslmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s)
-{
-	return sslmac_x(p, len, key, klen, digest, s, sha1, SHA1dlen, 40);
-}
-
-static DigestState*
-sslmac_md5(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s)
-{
-	return sslmac_x(p, len, key, klen, digest, s, md5, MD5dlen, 48);
-}
-
 static int
-sslPackAAD(u64int seq, uchar *hdr, uchar *aad)
-{
-	put64(aad, seq);
-	aad[8] = hdr[0];
-	aad[9] = hdr[3];
-	aad[10] = hdr[4];
-	return 11;
-}
-
-static int
-tlsPackAAD(u64int seq, uchar *hdr, uchar *aad)
+packAAD(u64int seq, uchar *hdr, uchar *aad)
 {
 	put64(aad, seq);
 	aad[8] = hdr[0];
--- a//sys/src/libsec/port/tlshand.c
+++ b//sys/src/libsec/port/tlshand.c
@@ -8,14 +8,13 @@
 //		client/server - main handshake protocol definition
 //		message functions - formating handshake messages
 //		cipher choices - catalog of digest and encrypt algorithms
-//		security functions - PKCS#1, sslHMAC, session keygen
+//		security functions - PKCS#1, session keygen
 //		general utility functions - malloc, serialization
-// The handshake protocol builds on the TLS/SSL3 record layer protocol,
-// which is implemented in kernel device #a.  See also /lib/rfc/rfc2246.
+// The handshake protocol builds on the TLS record layer protocol,
+// which is implemented in kernel device #a.  See also /lib/rfc/rfc5246.
 
 enum {
-	TLSFinishedLen = 12,
-	SSL3FinishedLen = MD5dlen+SHA1dlen,
+	FinishedLen = 12,
 	MaxKeyData = 160,	// amount of secret we may need
 	MAXdlen = SHA2_512dlen,
 	RandomSize = 32,
@@ -47,11 +46,6 @@
 	void (*init)(mpint *p, mpint *a, mpint *b, mpint *x, mpint *y, mpint *n, mpint *h);
 } Namedcurve;
 
-typedef struct Finished{
-	uchar verify[SSL3FinishedLen];
-	int n;
-} Finished;
-
 typedef struct HandshakeHash {
 	MD5state	md5;
 	SHAstate	sha1;
@@ -81,7 +75,6 @@
 	// byte generation and handshake checksum
 	void (*prf)(uchar*, int, uchar*, int, char*, uchar*, int);
 	void (*setFinished)(TlsSec*, HandshakeHash, uchar*, int);
-	int nfin;
 };
 
 typedef struct TlsConnection{
@@ -99,7 +92,7 @@
 
 	// for finished messages
 	HandshakeHash	handhash;
-	Finished	finished;
+	uchar		finished[FinishedLen];
 
 	uchar *sendp;
 	uchar buf[1<<16];
@@ -152,19 +145,17 @@
 			int sigalg;
 			Bytes *signature;
 		} certificateVerify;		
-		Finished finished;
+		uchar finished[FinishedLen];
 	} u;
 } Msg;
 
 
 enum {
-	SSL3Version	= 0x0300,
 	TLS10Version	= 0x0301,
 	TLS11Version	= 0x0302,
 	TLS12Version	= 0x0303,
 	ProtocolVersion	= TLS12Version,	// maximum version we speak
-	MinProtoVersion	= 0x0300,	// limits on version we accept
-	MaxProtoVersion	= 0x03ff,
+	MinProtoVersion	= TLS10Version,	// limits on version we accept
 };
 
 // handshake type
@@ -192,7 +183,6 @@
 	ERecordOverflow = 22,
 	EDecompressionFailure = 30,
 	EHandshakeFailure = 40,
-	ENoCertificate = 41,
 	EBadCertificate = 42,
 	EUnsupportedCertificate = 43,
 	ECertificateRevoked = 44,
@@ -365,9 +355,8 @@
 static int	msgSend(TlsConnection *c, Msg *m, int act);
 static void	tlsError(TlsConnection *c, int err, char *msg, ...);
 #pragma	varargck argpos	tlsError 3
-static int setVersion(TlsConnection *c, int version);
+static int setVersion(TlsConnection *c, int version, int client);
 static int setSecrets(TlsConnection *c, int isclient);
-static int finishedMatch(TlsConnection *c, Finished *f);
 static void tlsConnectionFree(TlsConnection *c);
 
 static int isDHE(int tlsid);
@@ -394,7 +383,6 @@
 static Bytes*	tlsSecDHEc(TlsSec *sec, Bytes *p, Bytes *g, Bytes *Ys);
 static Bytes*	tlsSecECDHEc(TlsSec *sec, int curve, Bytes *Ys);
 static void	tlsSecVers(TlsSec *sec, int v);
-static int	tlsSecFinished(TlsSec *sec, HandshakeHash hsh, uchar *fin, int nfin, int isclient);
 static void	setMasterSecret(TlsSec *sec, Bytes *pm);
 static int	digestDHparams(TlsSec *sec, Bytes *par, uchar digest[MAXdlen], int sigalg);
 static char*	verifyDHparams(TlsSec *sec, Bytes *par, Bytes *cert, Bytes *sig, int sigalg);
@@ -451,7 +439,7 @@
 		return -1;
 	}
 	data = -1;
-	fprint(ctl, "fd %d 0x%x", fd, ProtocolVersion);
+	fprint(ctl, "fd %d 0x%x", fd, MinProtoVersion);
 	tls = tlsServer2(ctl, hand,
 		conn->cert, conn->certlen,
 		conn->pskID, conn->psk, conn->psklen,
@@ -511,28 +499,26 @@
 	}
 
 	// Elliptic Curves (also called Supported Groups)
-	if(ProtocolVersion >= TLS10Version){
-		m = p - b;
-		b = erealloc(b, m + 2+2+2+nelem(namedcurves)*2 + 2+2+1+nelem(pointformats));
-		p = b + m;
+	m = p - b;
+	b = erealloc(b, m + 2+2+2+nelem(namedcurves)*2 + 2+2+1+nelem(pointformats));
+	p = b + m;
 
-		n = nelem(namedcurves);
-		put16(p, Extec), p += 2;	/* Type: elliptic_curves / supported_groups */
-		put16(p, (n+1)*2), p += 2;	/* Length */
-		put16(p, n*2), p += 2;		/* Elliptic Curves Length */
-		for(i=0; i < n; i++){		/* Elliptic Curves */
-			put16(p, namedcurves[i].tlsid);
-			p += 2;
-		}
-
-		n = nelem(pointformats);
-		put16(p, Extecp), p += 2;	/* Type: ec_point_formats */
-		put16(p, n+1), p += 2;		/* Length */
-		*p++ = n;			/* EC point formats Length */
-		for(i=0; i < n; i++)		/* EC point formats */
-			*p++ = pointformats[i];
+	n = nelem(namedcurves);
+	put16(p, Extec), p += 2;	/* Type: elliptic_curves / supported_groups */
+	put16(p, (n+1)*2), p += 2;	/* Length */
+	put16(p, n*2), p += 2;		/* Elliptic Curves Length */
+	for(i=0; i < n; i++){		/* Elliptic Curves */
+		put16(p, namedcurves[i].tlsid);
+		p += 2;
 	}
 
+	n = nelem(pointformats);
+	put16(p, Extecp), p += 2;	/* Type: ec_point_formats */
+	put16(p, n+1), p += 2;		/* Length */
+	*p++ = n;			/* EC point formats Length */
+	for(i=0; i < n; i++)		/* EC point formats */
+		*p++ = pointformats[i];
+
 	// signature algorithms
 	if(ProtocolVersion >= TLS12Version){
 		n = nelem(sigalgs);
@@ -591,7 +577,7 @@
 		close(ctl);
 		return -1;
 	}
-	fprint(ctl, "fd %d 0x%x", fd, ProtocolVersion);
+	fprint(ctl, "fd %d 0x%x", fd, MinProtoVersion);
 	ext = tlsClientExtensions(conn, &n);
 	tls = tlsClient2(ctl, hand,
 		conn->cert, conn->certlen, 
@@ -713,8 +699,8 @@
 	}
 	if(trace)
 		trace("ClientHello version %x\n", m.u.clientHello.version);
-	if(setVersion(c, m.u.clientHello.version) < 0) {
-		tlsError(c, EIllegalParameter, "incompatible version");
+	if(setVersion(c, m.u.clientHello.version, 0) < 0){
+		tlsError(c, EProtocolVersion, "incompatible version");
 		goto Err;
 	}
 	if(c->version < ProtocolVersion
@@ -849,10 +835,7 @@
 	}
 
 	/* no CertificateVerify; skip to Finished */
-	if(tlsSecFinished(c->sec, c->handhash, c->finished.verify, c->finished.n, 1) < 0){
-		tlsError(c, EInternalError, "can't set finished: %r");
-		goto Err;
-	}
+	c->sec->setFinished(c->sec, c->handhash, c->finished, 1);
 	if(!msgRecv(c, &m))
 		goto Err;
 	if(m.tag != HFinished) {
@@ -859,7 +842,7 @@
 		tlsError(c, EUnexpectedMessage, "expected a finished");
 		goto Err;
 	}
-	if(!finishedMatch(c, &m.u.finished)) {
+	if(tsmemcmp(c->finished, m.u.finished, FinishedLen) != 0) {
 		tlsError(c, EHandshakeFailure, "finished verification failed");
 		goto Err;
 	}
@@ -871,12 +854,9 @@
 		goto Err;
 	}
 
-	if(tlsSecFinished(c->sec, c->handhash, c->finished.verify, c->finished.n, 0) < 0){
-		tlsError(c, EInternalError, "can't set finished: %r");
-		goto Err;
-	}
+	c->sec->setFinished(c->sec, c->handhash, c->finished, 0);
 	m.tag = HFinished;
-	m.u.finished = c->finished;
+	memmove(m.u.finished, c->finished, FinishedLen);
 	if(!msgSend(c, &m, AFlush))
 		goto Err;
 	if(trace)
@@ -1056,8 +1036,8 @@
 		tlsError(c, EUnexpectedMessage, "expected a server hello");
 		goto Err;
 	}
-	if(setVersion(c, m.u.serverHello.version) < 0) {
-		tlsError(c, EIllegalParameter, "incompatible version: %r");
+	if(setVersion(c, m.u.serverHello.version, 1) < 0){
+		tlsError(c, EProtocolVersion, "incompatible version: %r");
 		goto Err;
 	}
 	tlsSecVers(c->sec, c->version);
@@ -1220,21 +1200,15 @@
 
 	// Cipherchange must occur immediately before Finished to avoid
 	// potential hole;  see section 4.3 of Wagner Schneier 1996.
-	if(tlsSecFinished(c->sec, c->handhash, c->finished.verify, c->finished.n, 1) < 0){
-		tlsError(c, EInternalError, "can't set finished 1: %r");
-		goto Err;
-	}
+	c->sec->setFinished(c->sec, c->handhash, c->finished, 1);
 	m.tag = HFinished;
-	m.u.finished = c->finished;
+	memmove(m.u.finished, c->finished, FinishedLen);
 	if(!msgSend(c, &m, AFlush)) {
 		tlsError(c, EInternalError, "can't flush after client Finished: %r");
 		goto Err;
 	}
 
-	if(tlsSecFinished(c->sec, c->handhash, c->finished.verify, c->finished.n, 0) < 0){
-		tlsError(c, EInternalError, "can't set finished 0: %r");
-		goto Err;
-	}
+	c->sec->setFinished(c->sec, c->handhash, c->finished, 0);
 	if(!msgRecv(c, &m)) {
 		tlsError(c, EInternalError, "can't read server Finished: %r");
 		goto Err;
@@ -1244,7 +1218,7 @@
 		goto Err;
 	}
 
-	if(!finishedMatch(c, &m.u.finished)) {
+	if(tsmemcmp(c->finished, m.u.finished, FinishedLen) != 0) {
 		tlsError(c, EHandshakeFailure, "finished verification failed");
 		goto Err;
 	}
@@ -1418,16 +1392,16 @@
 			goto Overflow;
 		if(isECDHE(c->cipher))
 			*p++ = n;
-		else if(isDHE(c->cipher) || c->version != SSL3Version)
+		else
 			put16(p, n), p += 2;
 		memmove(p, m->u.clientKeyExchange.key->data, n);
 		p += n;
 		break;
 	case HFinished:
-		if(p+m->u.finished.n > e)
+		if(p+FinishedLen > e)
 			goto Overflow;
-		memmove(p, m->u.finished.verify, m->u.finished.n);
-		p += m->u.finished.n;
+		memmove(p, m->u.finished, FinishedLen);
+		p += FinishedLen;
 		break;
 	}
 
@@ -1496,7 +1470,7 @@
 	}
 
 	if(type == HSSL2ClientHello){
-		/* Cope with an SSL3 ClientHello expressed in SSL2 record format.
+		/* Cope with a TLS ClientHello expressed in SSL2 record format.
 			This is sent by some clients that we must interoperate
 			with, such as Java's JSSE and Microsoft's Internet Explorer. */
 		int nsid, nrandom, nciph;
@@ -1519,7 +1493,7 @@
 		if(nsid != 0 	/* no sid's, since shouldn't restart using ssl2 header */
 		|| nrandom < 16 || nn % 3 || n - nrandom < nn)
 			goto Err;
-		/* ignore ssl2 ciphers and look for {0x00, ssl3 cipher} */
+		/* ignore ssl2 ciphers and look for {0x00, tls cipher} */
 		nciph = 0;
 		for(i = 0; i < nn; i += 3)
 			if(p[i] == 0)
@@ -1790,10 +1764,8 @@
 			goto Short;
 		if(isECDHE(c->cipher))
 			nn = *p++, n--;
-		else if(isDHE(c->cipher) || c->version != SSL3Version)
-			nn = get16(p), p += 2, n -= 2;
 		else
-			nn = n;
+			nn = get16(p), p += 2, n -= 2;
 		if(n < nn)
 			goto Short;
 		m->u.clientKeyExchange.key = makebytes(p, nn);
@@ -1800,11 +1772,10 @@
 		n -= nn;
 		break;
 	case HFinished:
-		m->u.finished.n = c->finished.n;
-		if(n < m->u.finished.n)
+		if(n < FinishedLen)
 			goto Short;
-		memmove(m->u.finished.verify, p, m->u.finished.n);
-		n -= m->u.finished.n;
+		memmove(m->u.finished, p, FinishedLen);
+		n -= FinishedLen;
 		break;
 	}
 
@@ -2000,8 +1971,8 @@
 		break;
 	case HFinished:
 		bs = seprint(bs, be, "HFinished\n");
-		for(i=0; i<m->u.finished.n; i++)
-			bs = seprint(bs, be, "%.2x", m->u.finished.verify[i]);
+		for(i=0; i<FinishedLen; i++)
+			bs = seprint(bs, be, "%.2x", m->u.finished[i]);
 		bs = seprint(bs, be, "\n");
 		break;
 	}
@@ -2030,29 +2001,20 @@
 
 // commit to specific version number
 static int
-setVersion(TlsConnection *c, int version)
+setVersion(TlsConnection *c, int version, int client)
 {
-	if(version > MaxProtoVersion || version < MinProtoVersion)
+	if(version < MinProtoVersion)
 		return -1;
-	if(version > c->version)
-		version = c->version;
-	if(version == SSL3Version) {
+	if(version > c->version){
+		if(client)
+			return -1;
+		else
+			version = c->version;
+	}else
 		c->version = version;
-		c->finished.n = SSL3FinishedLen;
-	}else {
-		c->version = version;
-		c->finished.n = TLSFinishedLen;
-	}
 	return fprint(c->ctl, "version 0x%x", version);
 }
 
-// confirm that received Finished message matches the expected value
-static int
-finishedMatch(TlsConnection *c, Finished *f)
-{
-	return tsmemcmp(f->verify, c->finished.verify, f->n) == 0;
-}
-
 // free memory associated with TlsConnection struct
 //		(but don't close the TLS channel itself)
 static void
@@ -2390,68 +2352,6 @@
 		hmac_sha2_256, SHA2_256dlen);
 }
 
-static void
-sslPRF(uchar *buf, int nbuf, uchar *key, int nkey, char *label, uchar *seed, int nseed)
-{
-	uchar sha1dig[SHA1dlen], md5dig[MD5dlen], tmp[26];
-	DigestState *s;
-	int i, n, len;
-
-	USED(label);
-	len = 1;
-	while(nbuf > 0){
-		if(len > 26)
-			return;
-		for(i = 0; i < len; i++)
-			tmp[i] = 'A' - 1 + len;
-		s = sha1(tmp, len, nil, nil);
-		s = sha1(key, nkey, nil, s);
-		sha1(seed, nseed, sha1dig, s);
-		s = md5(key, nkey, nil, nil);
-		md5(sha1dig, SHA1dlen, md5dig, s);
-		n = MD5dlen;
-		if(n > nbuf)
-			n = nbuf;
-		memmove(buf, md5dig, n);
-		buf += n;
-		nbuf -= n;
-		len++;
-	}
-}
-
-static void
-sslSetFinished(TlsSec *sec, HandshakeHash hsh, uchar *finished, int isclient)
-{
-	DigestState *s;
-	uchar h0[MD5dlen], h1[SHA1dlen], pad[48];
-	char *label;
-
-	if(isclient)
-		label = "CLNT";
-	else
-		label = "SRVR";
-
-	md5((uchar*)label, 4, nil, &hsh.md5);
-	md5(sec->sec, MasterSecretSize, nil, &hsh.md5);
-	memset(pad, 0x36, 48);
-	md5(pad, 48, nil, &hsh.md5);
-	md5(nil, 0, h0, &hsh.md5);
-	memset(pad, 0x5C, 48);
-	s = md5(sec->sec, MasterSecretSize, nil, nil);
-	s = md5(pad, 48, nil, s);
-	md5(h0, MD5dlen, finished, s);
-
-	sha1((uchar*)label, 4, nil, &hsh.sha1);
-	sha1(sec->sec, MasterSecretSize, nil, &hsh.sha1);
-	memset(pad, 0x36, 40);
-	sha1(pad, 40, nil, &hsh.sha1);
-	sha1(nil, 0, h1, &hsh.sha1);
-	memset(pad, 0x5C, 40);
-	s = sha1(sec->sec, MasterSecretSize, nil, nil);
-	s = sha1(pad, 40, nil, s);
-	sha1(h1, SHA1dlen, finished + MD5dlen, s);
-}
-
 // fill "finished" arg with md5(args)^sha1(args)
 static void
 tls10SetFinished(TlsSec *sec, HandshakeHash hsh, uchar *finished, int isclient)
@@ -2460,6 +2360,8 @@
 	char *label;
 
 	// get current hash value, but allow further messages to be hashed in
+	hsh.md5.malloced = 0;
+	hsh.sha1.malloced = 0;
 	md5(nil, 0, h, &hsh.md5);
 	sha1(nil, 0, h+MD5dlen, &hsh.sha1);
 
@@ -2467,7 +2369,7 @@
 		label = "client finished";
 	else
 		label = "server finished";
-	tls10PRF(finished, TLSFinishedLen, sec->sec, MasterSecretSize, label, h, sizeof(h));
+	tls10PRF(finished, FinishedLen, sec->sec, MasterSecretSize, label, h, sizeof(h));
 }
 
 static void
@@ -2477,6 +2379,7 @@
 	char *label;
 
 	// get current hash value, but allow further messages to be hashed in
+	hsh.sha2_256.malloced = 0;
 	sha2_256(nil, 0, seed, &hsh.sha2_256);
 
 	if(isclient)
@@ -2483,7 +2386,7 @@
 		label = "client finished";
 	else
 		label = "server finished";
-	tls12PRF(finished, TLSFinishedLen, sec->sec, MasterSecretSize, label, seed, SHA2_256dlen);
+	tls12PRF(finished, FinishedLen, sec->sec, MasterSecretSize, label, seed, SHA2_256dlen);
 }
 
 static void
@@ -2630,34 +2533,14 @@
 	return epm;
 }
 
-static int
-tlsSecFinished(TlsSec *sec, HandshakeHash hsh, uchar *fin, int nfin, int isclient)
-{
-	if(sec->nfin != nfin){
-		werrstr("invalid finished exchange");
-		return -1;
-	}
-	hsh.md5.malloced = 0;
-	hsh.sha1.malloced = 0;
-	hsh.sha2_256.malloced = 0;
-	(*sec->setFinished)(sec, hsh, fin, isclient);
-	return 0;
-}
-
 static void
 tlsSecVers(TlsSec *sec, int v)
 {
-	if(v == SSL3Version){
-		sec->setFinished = sslSetFinished;
-		sec->nfin = SSL3FinishedLen;
-		sec->prf = sslPRF;
-	}else if(v < TLS12Version) {
+	if(v < TLS12Version){
 		sec->setFinished = tls10SetFinished;
-		sec->nfin = TLSFinishedLen;
 		sec->prf = tls10PRF;
-	}else {
+	}else{
 		sec->setFinished = tls12SetFinished;
-		sec->nfin = TLSFinishedLen;
 		sec->prf = tls12PRF;
 	}
 }

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [9front] intent to delete: devssl, cpu, oexportfs, import
  2021-10-24 11:46           ` kemal
@ 2021-10-24 16:06             ` cinap_lenrek
  2021-10-24 16:14             ` cinap_lenrek
  1 sibling, 0 replies; 20+ messages in thread
From: cinap_lenrek @ 2021-10-24 16:06 UTC (permalink / raw)
  To: 9front

thanks!

looks good to me, but we need a regression test for this
as manual review turns out not to be good enougth as
last time, your refactoring added an assert which broke
all of tls 1.0 prf and nobody noticed for months.

do you have some openssl scripts handy to run ssl3 and tls1.0
and tls1.1 servers and clients against these changes?

can anyone help you with this?

--
cinap

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [9front] intent to delete: devssl, cpu, oexportfs, import
  2021-10-24 11:46           ` kemal
  2021-10-24 16:06             ` cinap_lenrek
@ 2021-10-24 16:14             ` cinap_lenrek
  1 sibling, 0 replies; 20+ messages in thread
From: cinap_lenrek @ 2021-10-24 16:14 UTC (permalink / raw)
  To: 9front

on another note. your devtls and tlshand changes are unrelated
to the topic at hand. maybe have a separate topic for this?

what ori is talking about is to get rid of devssl, which is only
used by cpu, import and oexportfs at this point.

--
cinap

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [9front] intent to delete: devssl, cpu, oexportfs, import
  2021-10-22 20:26   ` Stuart Morrow
@ 2021-12-01  2:13     ` sl
  2021-12-01  2:13     ` sl
  1 sibling, 0 replies; 20+ messages in thread
From: sl @ 2021-12-01  2:13 UTC (permalink / raw)
  To: 9front

> Fqa7 contains a reference to cpu(1) and exportfs(1) that probably
> should be upgraded regardless.

fixed this finally.  thanks.

sl

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [9front] intent to delete: devssl, cpu, oexportfs, import
  2021-10-22 20:26   ` Stuart Morrow
  2021-12-01  2:13     ` sl
@ 2021-12-01  2:13     ` sl
  1 sibling, 0 replies; 20+ messages in thread
From: sl @ 2021-12-01  2:13 UTC (permalink / raw)
  To: 9front

> Fqa7 contains a reference to cpu(1) and exportfs(1) that probably
> should be upgraded regardless.

fixed this finally.  thanks.

sl

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2021-12-01  2:55 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-22  1:48 [9front] intent to delete: devssl, cpu, oexportfs, import ori
2021-10-22  1:58 ` sl
2021-10-22  2:26   ` ori
2021-10-22  2:44     ` Stanley Lieber
2021-10-22 10:19       ` Philip Silva
2021-10-22 15:32         ` ori
2021-10-22 20:26   ` Stuart Morrow
2021-12-01  2:13     ` sl
2021-12-01  2:13     ` sl
2021-10-22 11:43 ` kemal
2021-10-22 14:31   ` kemal
2021-10-22 14:36     ` kemal
2021-10-23 15:47       ` ori
2021-10-23 16:12         ` cinap_lenrek
2021-10-23 16:17           ` ori
2021-10-23 20:13         ` kemal
2021-10-24 11:46           ` kemal
2021-10-24 16:06             ` cinap_lenrek
2021-10-24 16:14             ` cinap_lenrek
2021-10-23 11:18     ` kemal

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).