254 lines
5.9 KiB
Text
254 lines
5.9 KiB
Text
.TH PUSHTLS 2
|
|
.SH NAME
|
|
pushtls, tlsClient, tlsServer, initThumbprints, freeThumbprints, okThumbprint, readcert, readcertchain \- attach TLS1 or SSL3 encryption to a communication channel
|
|
.SH SYNOPSIS
|
|
.B #include <u.h>
|
|
.br
|
|
.B #include <libc.h>
|
|
.PP
|
|
.nf
|
|
.B
|
|
int pushtls(int fd, char *hashalg, char *encalg,
|
|
.B
|
|
int isclient, char *secret, char *dir)
|
|
.PP
|
|
.nf
|
|
.B #include <mp.h>
|
|
.B #include <libsec.h>
|
|
.PP
|
|
.B
|
|
int tlsClient(int fd, TLSconn *conn)
|
|
.PP
|
|
.B
|
|
int tlsServer(int fd, TLSconn *conn)
|
|
.PP
|
|
.B
|
|
uchar *readcert(char *filename, int *pcertlen)
|
|
.PP
|
|
.B
|
|
PEMchain *readcertchain(char *filename)
|
|
.PP
|
|
.B
|
|
Thumbprint *initThumbprints(char *ok, char *crl)
|
|
.PP
|
|
.B
|
|
void freeThumbprints(Thumbprint *table)
|
|
.PP
|
|
.B
|
|
int okThumbprint(uchar *hash, Thumbprint *table)
|
|
.SH DESCRIPTION
|
|
Transport Layer Security (TLS) comprises a record layer protocol,
|
|
doing message digesting and encrypting in the kernel,
|
|
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),
|
|
call
|
|
.I pushtls
|
|
to open the record layer device, connect to the communications channel
|
|
.IR fd ,
|
|
and start up encryption and message authentication as specified
|
|
in
|
|
.IR hashalg ,
|
|
.IR encalg ,
|
|
and
|
|
.IR secret .
|
|
These parameters must have been arranged at the two ends of the
|
|
conversation by other means.
|
|
For example,
|
|
.I hashalg
|
|
could be
|
|
.BR sha1 ,
|
|
.I encalg
|
|
could be
|
|
.BR rc4_128 ,
|
|
and
|
|
.I secret
|
|
could be the base-64 encoding of two (client-to-server and server-to-client)
|
|
20-byte digest keys and two corresponding 16-byte encryption keys.
|
|
.I Pushtls
|
|
returns a file descriptor for the TLS data channel. Anything written to this
|
|
descriptor will get encrypted and authenticated and then written to the
|
|
file descriptor,
|
|
.IR fd .
|
|
If
|
|
.I dir
|
|
is non-zero, the path name of the connection directory is copied into
|
|
.IR dir .
|
|
This path name is guaranteed to be less than 40 bytes long.
|
|
.SS Certificates
|
|
.\" and other horseshit
|
|
Alternatively, call
|
|
.I tlsClient
|
|
to speak the full handshake protocol,
|
|
negotiate the algorithms and secrets,
|
|
and return a new data file descriptor for the data channel.
|
|
.I Conn
|
|
points to a (caller-allocated) struct:
|
|
.IP
|
|
.EX
|
|
typedef struct TLSconn {
|
|
char dir[40]; /* OUT connection directory */
|
|
uchar *cert; /* IN/OUT certificate */
|
|
uchar *sessionID; /* IN/OUT session ID */
|
|
int certlen, sessionIDlen;
|
|
void (*trace)(char*fmt, ...);
|
|
PEMChain *chain;
|
|
char *sessionType; /* opt IN session type */
|
|
uchar *sessionKey; /* opt IN/OUT session key */
|
|
int sessionKeylen; /* opt IN session key length */
|
|
char *sessionConst; /* opt IN session constant */
|
|
} TLSconn;
|
|
.EE
|
|
.PP
|
|
defined in
|
|
.IR tls.h .
|
|
On input, the caller can provide options such as
|
|
.IR cert ,
|
|
the local certificate, and
|
|
.IR sessionID ,
|
|
used by a client to resume a previously negotiated security association.
|
|
On output, the connection directory is set, as with
|
|
.B listen
|
|
(see
|
|
.IR dial (2)).
|
|
The input
|
|
.I cert
|
|
is freed and a freshly allocated copy of the remote's certificate
|
|
is returned in
|
|
.IR conn ,
|
|
to be checked by the caller
|
|
according to its needs.
|
|
One way to check the remote certificate is to use
|
|
.I initThumbprints
|
|
and
|
|
.I freeThumbprints
|
|
which allocate and free, respectively, a table of hashes
|
|
from files of known trusted and revoked certificates.
|
|
.I okThumbprint
|
|
confirms that a particular hash is in the table.
|
|
.PP
|
|
.I TlsClient
|
|
will optionally compute a session key for use
|
|
by higher-level protocols.
|
|
To compute a session key, the caller must set
|
|
.I sessionType
|
|
to a known session type;
|
|
.I sessionKeylen
|
|
to the desired key length;
|
|
.I sessionKey
|
|
to a buffer of length
|
|
.IR sessionKeylen ;
|
|
and
|
|
.I sessionConst
|
|
to the desired salting constant.
|
|
The only supported session type is
|
|
.BR ttls ,
|
|
as used by 802.1x.
|
|
.PP
|
|
.I TlsServer
|
|
executes the server side of the handshake.
|
|
The caller must initialize
|
|
.IB conn ->cert \fR,
|
|
usually by calling
|
|
.I readcert
|
|
to read and decode the PEM-encoded certificate from
|
|
.IR filename ,
|
|
return a pointer to
|
|
.IR malloc ed
|
|
storage containing the certificate,
|
|
and store its length through
|
|
.IR pcertlen .
|
|
The private key corresponding to
|
|
.I cert.pem
|
|
should have been previously loaded into factotum.
|
|
(See
|
|
.IR rsa (8)
|
|
for more about key generation.)
|
|
.PP
|
|
.I Readcertchain
|
|
will read a PEM-encoded chain of certificates from
|
|
.I filename
|
|
and return a pointer to a linked list of
|
|
.IR malloc ed
|
|
.B PEMChain
|
|
structures, defined in
|
|
.IR tls.h :
|
|
.IP
|
|
.EX
|
|
typedef struct PEMChain PEMChain;
|
|
struct PEMChain {
|
|
PEMChain*next;
|
|
uchar *pem;
|
|
int pemlen;
|
|
};
|
|
.EE
|
|
.LP
|
|
By setting
|
|
.IP
|
|
.EX
|
|
conn->chain = readcertchain("intermediate-certs.pem");
|
|
.EE
|
|
.LP
|
|
the server can present extra certificate evidence
|
|
to establish the chain of trust to a root authority
|
|
known to the client.
|
|
.PP
|
|
.I Conn
|
|
is not required for the ongoing conversation and may
|
|
be freed by the application whenever convenient.
|
|
.SH EXAMPLES
|
|
Start the client half of TLS and check the remote certificate:
|
|
.IP
|
|
.EX
|
|
uchar hash[SHA1dlen];
|
|
|
|
conn = (TLSconn*)mallocz(sizeof *conn, 1);
|
|
fd = tlsClient(fd, conn);
|
|
sha1(conn->cert, conn->certlen, hash, nil);
|
|
if(!okThumbprint(hash,table))
|
|
exits("suspect server");
|
|
\fI...application begins...\fP
|
|
.EE
|
|
.PP
|
|
Run the server side:
|
|
.IP
|
|
.EX
|
|
fd = accept(lcfd, ldir);
|
|
conn = (TLSconn*)mallocz(sizeof *conn, 1);
|
|
conn->cert = readcert("cert.pem", &conn->certlen);
|
|
fd = tlsServer(fd, conn);
|
|
\fI...application begins...\fP
|
|
.EE
|
|
.SH FILES
|
|
.TF /sys/lib/tls
|
|
.TP
|
|
.B /sys/lib/tls
|
|
thumbprints of trusted services
|
|
.TP
|
|
.B /sys/lib/ssl
|
|
PEM certificate files
|
|
.SH SOURCE
|
|
.B /sys/src/libc/9sys/pushtls.c
|
|
.br
|
|
.B /sys/src/libsec/port
|
|
.SH "SEE ALSO"
|
|
.IR dial (2),
|
|
.IR tls (3),
|
|
.IR factotum (4),
|
|
.IR thumbprint (6)
|
|
.SH DIAGNOSTICS
|
|
Return \-1 on failure.
|
|
.SH BUGS
|
|
Client certificates and client sessionIDs are not yet
|
|
implemented.
|
|
.PP
|
|
Note that in the TLS protocol
|
|
.I sessionID
|
|
itself is public; it is used as a pointer to
|
|
secrets stored in
|
|
.IR factotum .
|