ref: a291bbdeddfd41a2f0907ecbd7b819f0eedffdaf
dir: /sys/man/2/pushtls/
.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 . .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 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 .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 .