346f5828e0
initThumbprints() now takes an application tag argument so x509 and ssh can coexist. the thumbprint entries can now hold both sha1 and sha256 hashes. okThumbprint() now takes a len argument for the hash length used. the new function okCertificate() hashes the certificate with both and checks for any matches. on failure, okCertificate() returns 0 and sets error string. we also check for include loops now in thumbfiles, limiting the number of includes to 8.
278 lines
6.4 KiB
Text
278 lines
6.4 KiB
Text
.TH PUSHTLS 2
|
|
.SH NAME
|
|
pushtls, tlsClient, tlsServer, initThumbprints, freeThumbprints, okThumbprint, okCertificate, 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, char *tag)
|
|
.PP
|
|
.B
|
|
void freeThumbprints(Thumbprint *table)
|
|
.PP
|
|
.B
|
|
int okThumbprint(uchar *hash, int len, Thumbprint *table)
|
|
.PP
|
|
.B
|
|
int okCertificate(uchar *cert, int len, 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 .
|
|
.I Pushtls ,
|
|
.IR tlsClient
|
|
and
|
|
.IR tlsServer
|
|
close the original file descriptor on success.
|
|
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 */
|
|
uchar *psk; /* opt IN pre-shared key */
|
|
int certlen, sessionIDlen, psklen;
|
|
int (*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 */
|
|
char *serverName; /* opt IN server name */
|
|
char *pskID; /* opt IN pre-shared key ID */
|
|
} TLSconn;
|
|
.EE
|
|
.PP
|
|
defined in
|
|
.IR libsec.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 libsec.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
|
|
conn = (TLSconn*)mallocz(sizeof *conn, 1);
|
|
fd = tlsClient(fd, conn);
|
|
if(!okCertificate(conn->cert, conn->certlen, table))
|
|
sysfatal("suspect server: %r");
|
|
\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
|
|
.IR pushtls ,
|
|
.IR tlsClient
|
|
and
|
|
.IR tlsServer
|
|
do not close the original file descriptor on failure,
|
|
only on success.
|
|
.PP
|
|
The
|
|
.IR sessionID
|
|
and
|
|
.IR cert
|
|
pointers in the
|
|
.IR TLSconn
|
|
structure have to be freed by the caller.
|
|
.PP
|
|
Note that in the TLS protocol
|
|
.I sessionID
|
|
itself is public; it is used as a pointer to
|
|
secrets stored in
|
|
.IR factotum .
|