3024 lines · 70.5 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <auth.h>#include <mp.h>#include <libsec.h> // The main groups of functions are://		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//		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. enum {	TLSFinishedLen = 12,	SSL3FinishedLen = MD5dlen+SHA1dlen,	MaxKeyData = 160,	// amount of secret we may need	MAXdlen = SHA2_512dlen,	RandomSize = 32,	MasterSecretSize = 48,	AQueue = 0,	AFlush = 1,}; typedef struct Bytes{	int len;	uchar data[];} Bytes; typedef struct Ints{	int len;	int data[];} Ints; typedef struct Algs{	char *enc;	char *digest;	int nsecret;	int tlsid;	int ok;} Algs; typedef struct Namedcurve{	int tlsid;	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;	SHA2_256state	sha2_256;} HandshakeHash; typedef struct TlsSec TlsSec;struct TlsSec {	RSApub *rsapub;	AuthRpc *rpc;	// factotum for rsa private key	uchar *psk;	// pre-shared key	int psklen;	int clientVers;			// version in ClientHello	uchar sec[MasterSecretSize];	// master secret	uchar srandom[RandomSize];	// server random	uchar crandom[RandomSize];	// client random 	Namedcurve *nc; // selected curve for ECDHE	// diffie hellman state	DHstate dh;	struct {		ECdomain dom;		ECpriv Q;	} ec;	uchar X[32]; 	// 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{	TlsSec sec[1];	// security management goo	int hand, ctl;	// record layer file descriptors	int erred;		// set when tlsError called	int (*trace)(char*fmt, ...); // for debugging	int version;	// protocol we are speaking	Bytes *cert;	// server certificate; only last - no chain 	int cipher;	int nsecret;	// amount of secret data to init keys	char *digest;	// name of digest algorithm to use	char *enc;	// name of encryption algorithm to use 	// for finished messages	HandshakeHash	handhash;	Finished	finished; 	uchar *sendp;	uchar buf[1<<16];} TlsConnection; typedef struct Msg{	int tag;	union {		struct {			int	version;			uchar 	random[RandomSize];			Bytes*	sid;			Ints*	ciphers;			Bytes*	compressors;			Bytes*	extensions;		} clientHello;		struct {			int	version;			uchar	random[RandomSize];			Bytes*	sid;			int	cipher;			int	compressor;			Bytes*	extensions;		} serverHello;		struct {			int ncert;			Bytes **certs;		} certificate;		struct {			Bytes *types;			Ints *sigalgs;			int nca;			Bytes **cas;		} certificateRequest;		struct {			Bytes *pskid;			Bytes *key;		} clientKeyExchange;		struct {			Bytes *pskid;			Bytes *dh_p;			Bytes *dh_g;			Bytes *dh_Ys;			Bytes *dh_parameters;			Bytes *dh_signature;			int sigalg;			int curve;		} serverKeyExchange;		struct {			int sigalg;			Bytes *signature;		} certificateVerify;				Finished finished;	} 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,}; // handshake typeenum {	HHelloRequest,	HClientHello,	HServerHello,	HSSL2ClientHello = 9,  /* local convention;  see devtls.c */	HCertificate = 11,	HServerKeyExchange,	HCertificateRequest,	HServerHelloDone,	HCertificateVerify,	HClientKeyExchange,	HFinished = 20,	HMax}; // alertsenum {	ECloseNotify = 0,	EUnexpectedMessage = 10,	EBadRecordMac = 20,	EDecryptionFailed = 21,	ERecordOverflow = 22,	EDecompressionFailure = 30,	EHandshakeFailure = 40,	ENoCertificate = 41,	EBadCertificate = 42,	EUnsupportedCertificate = 43,	ECertificateRevoked = 44,	ECertificateExpired = 45,	ECertificateUnknown = 46,	EIllegalParameter = 47,	EUnknownCa = 48,	EAccessDenied = 49,	EDecodeError = 50,	EDecryptError = 51,	EExportRestriction = 60,	EProtocolVersion = 70,	EInsufficientSecurity = 71,	EInternalError = 80,	EInappropriateFallback = 86,	EUserCanceled = 90,	ENoRenegotiation = 100,	EUnknownPSKidentity = 115,	EMax = 256}; // cipher suitesenum {	TLS_RSA_WITH_3DES_EDE_CBC_SHA		= 0X000A,	TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA	= 0X0016, 	TLS_RSA_WITH_AES_128_CBC_SHA		= 0X002F,	TLS_DHE_RSA_WITH_AES_128_CBC_SHA	= 0X0033,	TLS_RSA_WITH_AES_256_CBC_SHA		= 0X0035,	TLS_DHE_RSA_WITH_AES_256_CBC_SHA	= 0X0039,	TLS_RSA_WITH_AES_128_CBC_SHA256		= 0X003C,	TLS_RSA_WITH_AES_256_CBC_SHA256		= 0X003D,	TLS_DHE_RSA_WITH_AES_128_CBC_SHA256	= 0X0067, 	TLS_RSA_WITH_AES_128_GCM_SHA256		= 0x009C,	TLS_DHE_RSA_WITH_AES_128_GCM_SHA256	= 0x009E, 	TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA	= 0xC013,	TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA	= 0xC014,	TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256	= 0xC023,	TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256	= 0xC027, 	TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02B,	TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256	= 0xC02F, 	GOOGLE_ECDHE_RSA_WITH_CHACHA20_POLY1305		= 0xCC13,	GOOGLE_ECDHE_ECDSA_WITH_CHACHA20_POLY1305	= 0xCC14,	GOOGLE_DHE_RSA_WITH_CHACHA20_POLY1305		= 0xCC15, 	TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305	= 0xCCA8,	TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305	= 0xCCA9,	TLS_DHE_RSA_WITH_CHACHA20_POLY1305	= 0xCCAA, 	TLS_PSK_WITH_CHACHA20_POLY1305		= 0xCCAB,	TLS_PSK_WITH_AES_128_CBC_SHA256		= 0x00AE,	TLS_PSK_WITH_AES_128_CBC_SHA		= 0x008C, 	TLS_FALLBACK_SCSV = 0x5600,}; // compression methodsenum {	CompressionNull = 0,	CompressionMax};  // curvesenum {	X25519 = 0x001d,}; // extensionsenum {	Extsni = 0x0000,	Extec = 0x000a,	Extecp = 0x000b,	Extsigalgs = 0x000d,}; static Algs cipherAlgs[] = {	// ECDHE-ECDSA	{"ccpoly96_aead", "clear", 2*(32+12), TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305},	{"ccpoly64_aead", "clear", 2*32, GOOGLE_ECDHE_ECDSA_WITH_CHACHA20_POLY1305},	{"aes_128_gcm_aead", "clear", 2*(16+4), TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},	{"aes_128_cbc", "sha256", 2*(16+16+SHA2_256dlen), TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256}, 	// ECDHE-RSA	{"ccpoly96_aead", "clear", 2*(32+12), TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305},	{"ccpoly64_aead", "clear", 2*32, GOOGLE_ECDHE_RSA_WITH_CHACHA20_POLY1305},	{"aes_128_gcm_aead", "clear", 2*(16+4), TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},	{"aes_128_cbc", "sha256", 2*(16+16+SHA2_256dlen), TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},	{"aes_128_cbc", "sha1", 2*(16+16+SHA1dlen), TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},	{"aes_256_cbc", "sha1", 2*(32+16+SHA1dlen), TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA}, 	// DHE-RSA	{"ccpoly96_aead", "clear", 2*(32+12), TLS_DHE_RSA_WITH_CHACHA20_POLY1305},	{"ccpoly64_aead", "clear", 2*32, GOOGLE_DHE_RSA_WITH_CHACHA20_POLY1305},	{"aes_128_gcm_aead", "clear", 2*(16+4), TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},	{"aes_128_cbc", "sha256", 2*(16+16+SHA2_256dlen), TLS_DHE_RSA_WITH_AES_128_CBC_SHA256},	{"aes_128_cbc", "sha1", 2*(16+16+SHA1dlen), TLS_DHE_RSA_WITH_AES_128_CBC_SHA},	{"aes_256_cbc", "sha1", 2*(32+16+SHA1dlen), TLS_DHE_RSA_WITH_AES_256_CBC_SHA},	{"3des_ede_cbc","sha1",	2*(4*8+SHA1dlen), TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA}, 	// RSA	{"aes_128_gcm_aead", "clear", 2*(16+4), TLS_RSA_WITH_AES_128_GCM_SHA256},	{"aes_128_cbc", "sha256", 2*(16+16+SHA2_256dlen), TLS_RSA_WITH_AES_128_CBC_SHA256},	{"aes_256_cbc", "sha256", 2*(32+16+SHA2_256dlen), TLS_RSA_WITH_AES_256_CBC_SHA256},	{"aes_128_cbc", "sha1", 2*(16+16+SHA1dlen), TLS_RSA_WITH_AES_128_CBC_SHA},	{"aes_256_cbc", "sha1", 2*(32+16+SHA1dlen), TLS_RSA_WITH_AES_256_CBC_SHA},	{"3des_ede_cbc","sha1",	2*(4*8+SHA1dlen), TLS_RSA_WITH_3DES_EDE_CBC_SHA}, 	// PSK	{"ccpoly96_aead", "clear", 2*(32+12), TLS_PSK_WITH_CHACHA20_POLY1305},	{"aes_128_cbc", "sha256", 2*(16+16+SHA2_256dlen), TLS_PSK_WITH_AES_128_CBC_SHA256},	{"aes_128_cbc", "sha1", 2*(16+16+SHA1dlen), TLS_PSK_WITH_AES_128_CBC_SHA},}; static uchar compressors[] = {	CompressionNull,}; static Namedcurve namedcurves[] = {	X25519, nil,	0x0017, secp256r1,	0x0018, secp384r1,}; static uchar pointformats[] = {	CompressionNull /* support of uncompressed point format is mandatory */}; static struct {	DigestState* (*fun)(uchar*, ulong, uchar*, DigestState*);	int len;} hashfun[] = {/*	[0x00]  is reserved for MD5+SHA1 for < TLS1.2 */	[0x01]	{md5,		MD5dlen},	[0x02]	{sha1,		SHA1dlen},	[0x03]	{sha2_224,	SHA2_224dlen},	[0x04]	{sha2_256,	SHA2_256dlen},	[0x05]	{sha2_384,	SHA2_384dlen},	[0x06]	{sha2_512,	SHA2_512dlen},}; // signature algorithms (only RSA and ECDSA at the moment)static int sigalgs[] = {	0x0603,		/* SHA512 ECDSA */	0x0503,		/* SHA384 ECDSA */	0x0403,		/* SHA256 ECDSA */	0x0203,		/* SHA1 ECDSA */ 	0x0601,		/* SHA512 RSA */	0x0501,		/* SHA384 RSA */	0x0401,		/* SHA256 RSA */	0x0201,		/* SHA1 RSA */}; static TlsConnection *tlsServer2(int ctl, int hand,	uchar *cert, int certlen,	char *pskid, uchar *psk, int psklen,	int (*trace)(char*fmt, ...), PEMChain *chain);static TlsConnection *tlsClient2(int ctl, int hand,	uchar *cert, int certlen,	char *pskid, uchar *psk, int psklen,	uchar *ext, int extlen, int (*trace)(char*fmt, ...));static void	msgClear(Msg *m);static char* msgPrint(char *buf, int n, Msg *m);static int	msgRecv(TlsConnection *c, Msg *m);static int	msgSend(TlsConnection *c, Msg *m, int act);static void	tlsError(TlsConnection *c, int err, char *msg, ...);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);static int isECDHE(int tlsid);static int isPSK(int tlsid);static int isECDSA(int tlsid); static int setAlgs(TlsConnection *c, int a);static int okCipher(Ints *cv, int ispsk, int canec);static int okCompression(Bytes *cv);static int initCiphers(void);static Ints* makeciphers(int ispsk); static AuthRpc* factotum_rsa_open(RSApub *rsapub);static mpint* factotum_rsa_decrypt(AuthRpc *rpc, mpint *cipher);static void factotum_rsa_close(AuthRpc *rpc); static void	tlsSecInits(TlsSec *sec, int cvers, uchar *crandom);static int	tlsSecRSAs(TlsSec *sec, Bytes *epm);static Bytes*	tlsSecECDHEs1(TlsSec *sec);static int	tlsSecECDHEs2(TlsSec *sec, Bytes *Yc);static void	tlsSecInitc(TlsSec *sec, int cvers);static Bytes*	tlsSecRSAc(TlsSec *sec, uchar *cert, int ncert);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); static Bytes*	pkcs1_encrypt(Bytes* data, RSApub* key);static Bytes*	pkcs1_decrypt(TlsSec *sec, Bytes *data);static Bytes*	pkcs1_sign(TlsSec *sec, uchar *digest, int digestlen, int sigalg); static void* emalloc(int);static void* erealloc(void*, int);static void put32(uchar *p, u32int);static void put24(uchar *p, int);static void put16(uchar *p, int);static int get24(uchar *p);static int get16(uchar *p);static Bytes* newbytes(int len);static Bytes* makebytes(uchar* buf, int len);static Bytes* mptobytes(mpint* big, int len);static mpint* bytestomp(Bytes* bytes);static void freebytes(Bytes* b);static Ints* newints(int len);static void freeints(Ints* b);static int lookupid(Ints* b, int id); /* x509.c */extern mpint*	pkcs1padbuf(uchar *buf, int len, mpint *modulus, int blocktype);extern int	pkcs1unpadbuf(uchar *buf, int len, mpint *modulus, int blocktype);extern int	asn1encodedigest(DigestState* (*fun)(uchar*, ulong, uchar*, DigestState*), uchar *digest, uchar *buf, int len); //================= client/server ======================== //	push TLS onto fd, returning new (application) file descriptor//		or -1 if error.inttlsServer(int fd, TLSconn *conn){	char buf[8];	char dname[64];	uchar seed[2*RandomSize];	int n, data, ctl, hand;	TlsConnection *tls; 	if(conn == nil)		return -1;	ctl = open("#a/tls/clone", ORDWR|OCEXEC);	if(ctl < 0)		return -1;	n = read(ctl, buf, sizeof(buf)-1);	if(n < 0){		close(ctl);		return -1;	}	buf[n] = 0;	snprint(conn->dir, sizeof(conn->dir), "#a/tls/%s", buf);	snprint(dname, sizeof(dname), "#a/tls/%s/hand", buf);	hand = open(dname, ORDWR|OCEXEC);	if(hand < 0){		close(ctl);		return -1;	}	data = -1;	fprint(ctl, "fd %d 0x%x", fd, ProtocolVersion);	tls = tlsServer2(ctl, hand,		conn->cert, conn->certlen,		conn->pskID, conn->psk, conn->psklen,		conn->trace, conn->chain);	if(tls != nil){		snprint(dname, sizeof(dname), "#a/tls/%s/data", buf);		data = open(dname, ORDWR);	}	close(hand);	close(ctl);	if(data < 0){		tlsConnectionFree(tls);		return -1;	}	free(conn->cert);	conn->cert = nil;  // client certificates are not yet implemented	conn->certlen = 0;	conn->sessionIDlen = 0;	conn->sessionID = nil;	if(conn->sessionKey != nil	&& conn->sessionType != nil	&& strcmp(conn->sessionType, "ttls") == 0){		memmove(seed, tls->sec->crandom, RandomSize);		memmove(seed+RandomSize, tls->sec->srandom, RandomSize);		tls->sec->prf(			conn->sessionKey, conn->sessionKeylen,			tls->sec->sec, MasterSecretSize,			conn->sessionConst, 			seed, sizeof(seed));	}	tlsConnectionFree(tls);	close(fd);	return data;} static uchar*tlsClientExtensions(TLSconn *conn, int *plen){	uchar *b, *p;	int i, n, m; 	p = b = nil;

Lines 1–500 of 3024.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t