⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tlshand.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 4 页
字号:
			p += 2;			n -= 2;			if(nn < 1 || nn > n)				goto Short;			m->u.certificateRequest.nca = i+1;			m->u.certificateRequest.cas = erealloc(m->u.certificateRequest.cas, (i+1)*sizeof(Bytes));			m->u.certificateRequest.cas[i] = makebytes(p, nn);			p += nn;			n -= nn;			i++;		}		break;	case HServerHelloDone:		break;	case HClientKeyExchange:		/*		 * this message depends upon the encryption selected		 * assume rsa.		 */		if(c->version == SSL3Version)			nn = n;		else{			if(n < 2)				goto Short;			nn = get16(p);			p += 2;			n -= 2;		}		if(n < nn)			goto Short;		m->u.clientKeyExchange.key = makebytes(p, nn);		n -= nn;		break;	case HFinished:		m->u.finished.n = c->finished.n;		if(n < m->u.finished.n)			goto Short;		memmove(m->u.finished.verify, p, m->u.finished.n);		n -= m->u.finished.n;		break;	}	if(type != HClientHello && n != 0)		goto Short;Ok:	if(c->trace){		char *buf;		buf = emalloc(8000);		c->trace("recv %s", msgPrint(buf, 8000, m));		free(buf);	}	return 1;Short:	tlsError(c, EDecodeError, "handshake message has invalid length");Err:	msgClear(m);	return 0;}static voidmsgClear(Msg *m){	int i;	switch(m->tag) {	default:		sysfatal("msgClear: unknown message type: %d\n", m->tag);	case HHelloRequest:		break;	case HClientHello:		freebytes(m->u.clientHello.sid);		freeints(m->u.clientHello.ciphers);		freebytes(m->u.clientHello.compressors);		break;	case HServerHello:		freebytes(m->u.clientHello.sid);		break;	case HCertificate:		for(i=0; i<m->u.certificate.ncert; i++)			freebytes(m->u.certificate.certs[i]);		free(m->u.certificate.certs);		break;	case HCertificateRequest:		freebytes(m->u.certificateRequest.types);		for(i=0; i<m->u.certificateRequest.nca; i++)			freebytes(m->u.certificateRequest.cas[i]);		free(m->u.certificateRequest.cas);		break;	case HServerHelloDone:		break;	case HClientKeyExchange:		freebytes(m->u.clientKeyExchange.key);		break;	case HFinished:		break;	}	memset(m, 0, sizeof(Msg));}static char *bytesPrint(char *bs, char *be, char *s0, Bytes *b, char *s1){	int i;	if(s0)		bs = seprint(bs, be, "%s", s0);	bs = seprint(bs, be, "[");	if(b == nil)		bs = seprint(bs, be, "nil");	else		for(i=0; i<b->len; i++)			bs = seprint(bs, be, "%.2x ", b->data[i]);	bs = seprint(bs, be, "]");	if(s1)		bs = seprint(bs, be, "%s", s1);	return bs;}static char *intsPrint(char *bs, char *be, char *s0, Ints *b, char *s1){	int i;	if(s0)		bs = seprint(bs, be, "%s", s0);	bs = seprint(bs, be, "[");	if(b == nil)		bs = seprint(bs, be, "nil");	else		for(i=0; i<b->len; i++)			bs = seprint(bs, be, "%x ", b->data[i]);	bs = seprint(bs, be, "]");	if(s1)		bs = seprint(bs, be, "%s", s1);	return bs;}static char*msgPrint(char *buf, int n, Msg *m){	int i;	char *bs = buf, *be = buf+n;	switch(m->tag) {	default:		bs = seprint(bs, be, "unknown %d\n", m->tag);		break;	case HClientHello:		bs = seprint(bs, be, "ClientHello\n");		bs = seprint(bs, be, "\tversion: %.4x\n", m->u.clientHello.version);		bs = seprint(bs, be, "\trandom: ");		for(i=0; i<RandomSize; i++)			bs = seprint(bs, be, "%.2x", m->u.clientHello.random[i]);		bs = seprint(bs, be, "\n");		bs = bytesPrint(bs, be, "\tsid: ", m->u.clientHello.sid, "\n");		bs = intsPrint(bs, be, "\tciphers: ", m->u.clientHello.ciphers, "\n");		bs = bytesPrint(bs, be, "\tcompressors: ", m->u.clientHello.compressors, "\n");		break;	case HServerHello:		bs = seprint(bs, be, "ServerHello\n");		bs = seprint(bs, be, "\tversion: %.4x\n", m->u.serverHello.version);		bs = seprint(bs, be, "\trandom: ");		for(i=0; i<RandomSize; i++)			bs = seprint(bs, be, "%.2x", m->u.serverHello.random[i]);		bs = seprint(bs, be, "\n");		bs = bytesPrint(bs, be, "\tsid: ", m->u.serverHello.sid, "\n");		bs = seprint(bs, be, "\tcipher: %.4x\n", m->u.serverHello.cipher);		bs = seprint(bs, be, "\tcompressor: %.2x\n", m->u.serverHello.compressor);		break;	case HCertificate:		bs = seprint(bs, be, "Certificate\n");		for(i=0; i<m->u.certificate.ncert; i++)			bs = bytesPrint(bs, be, "\t", m->u.certificate.certs[i], "\n");		break;	case HCertificateRequest:		bs = seprint(bs, be, "CertificateRequest\n");		bs = bytesPrint(bs, be, "\ttypes: ", m->u.certificateRequest.types, "\n");		bs = seprint(bs, be, "\tcertificateauthorities\n");		for(i=0; i<m->u.certificateRequest.nca; i++)			bs = bytesPrint(bs, be, "\t\t", m->u.certificateRequest.cas[i], "\n");		break;	case HServerHelloDone:		bs = seprint(bs, be, "ServerHelloDone\n");		break;	case HClientKeyExchange:		bs = seprint(bs, be, "HClientKeyExchange\n");		bs = bytesPrint(bs, be, "\tkey: ", m->u.clientKeyExchange.key, "\n");		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]);		bs = seprint(bs, be, "\n");		break;	}	USED(bs);	return buf;}static voidtlsError(TlsConnection *c, int err, char *fmt, ...){	char msg[512];	va_list arg;	va_start(arg, fmt);	vseprint(msg, msg+sizeof(msg), fmt, arg);	va_end(arg);	if(c->trace)		c->trace("tlsError: %s\n", msg);	else if(c->erred)		fprint(2, "double error: %r, %s", msg);	else		werrstr("tls: local %s", msg);	c->erred = 1;	fprint(c->ctl, "alert %d", err);}// commit to specific version numberstatic intsetVersion(TlsConnection *c, int version){	if(c->verset || version > MaxProtoVersion || version < MinProtoVersion)		return -1;	if(version > c->version)		version = c->version;	if(version == SSL3Version) {		c->version = version;		c->finished.n = SSL3FinishedLen;	}else if(version == TLSVersion){		c->version = version;		c->finished.n = TLSFinishedLen;	}else		return -1;	c->verset = 1;	return fprint(c->ctl, "version 0x%x", version);}// confirm that received Finished message matches the expected valuestatic intfinishedMatch(TlsConnection *c, Finished *f){	return memcmp(f->verify, c->finished.verify, f->n) == 0;}// free memory associated with TlsConnection struct//		(but don't close the TLS channel itself)static voidtlsConnectionFree(TlsConnection *c){	tlsSecClose(c->sec);	freebytes(c->sid);	freebytes(c->cert);	memset(c, 0, sizeof(c));	free(c);}//================= cipher choices ========================static int weakCipher[CipherMax] ={	1,	/* TLS_NULL_WITH_NULL_NULL */	1,	/* TLS_RSA_WITH_NULL_MD5 */	1,	/* TLS_RSA_WITH_NULL_SHA */	1,	/* TLS_RSA_EXPORT_WITH_RC4_40_MD5 */	0,	/* TLS_RSA_WITH_RC4_128_MD5 */	0,	/* TLS_RSA_WITH_RC4_128_SHA */	1,	/* TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 */	0,	/* TLS_RSA_WITH_IDEA_CBC_SHA */	1,	/* TLS_RSA_EXPORT_WITH_DES40_CBC_SHA */	0,	/* TLS_RSA_WITH_DES_CBC_SHA */	0,	/* TLS_RSA_WITH_3DES_EDE_CBC_SHA */	1,	/* TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA */	0,	/* TLS_DH_DSS_WITH_DES_CBC_SHA */	0,	/* TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA */	1,	/* TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA */	0,	/* TLS_DH_RSA_WITH_DES_CBC_SHA */	0,	/* TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA */	1,	/* TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA */	0,	/* TLS_DHE_DSS_WITH_DES_CBC_SHA */	0,	/* TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA */	1,	/* TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA */	0,	/* TLS_DHE_RSA_WITH_DES_CBC_SHA */	0,	/* TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA */	1,	/* TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 */	1,	/* TLS_DH_anon_WITH_RC4_128_MD5 */	1,	/* TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA */	1,	/* TLS_DH_anon_WITH_DES_CBC_SHA */	1,	/* TLS_DH_anon_WITH_3DES_EDE_CBC_SHA */};static intsetAlgs(TlsConnection *c, int a){	int i;	for(i = 0; i < nelem(cipherAlgs); i++){		if(cipherAlgs[i].tlsid == a){			c->enc = cipherAlgs[i].enc;			c->digest = cipherAlgs[i].digest;			c->nsecret = cipherAlgs[i].nsecret;			if(c->nsecret > MaxKeyData)				return 0;			return 1;		}	}	return 0;}static intokCipher(Ints *cv){	int weak, i, j, c;	weak = 1;	for(i = 0; i < cv->len; i++) {		c = cv->data[i];		if(c >= CipherMax)			weak = 0;		else			weak &= weakCipher[c];		for(j = 0; j < nelem(cipherAlgs); j++)			if(cipherAlgs[j].ok && cipherAlgs[j].tlsid == c)				return c;	}	if(weak)		return -2;	return -1;}static intokCompression(Bytes *cv){	int i, j, c;	for(i = 0; i < cv->len; i++) {		c = cv->data[i];		for(j = 0; j < nelem(compressors); j++) {			if(compressors[j] == c)				return c;		}	}	return -1;}static Lock	ciphLock;static int	nciphers;static intinitCiphers(void){	enum {MaxAlgF = 1024, MaxAlgs = 10};	char s[MaxAlgF], *flds[MaxAlgs];	int i, j, n, ok;	lock(&ciphLock);	if(nciphers){		unlock(&ciphLock);		return nciphers;	}	j = open("#a/tls/encalgs", OREAD);	if(j < 0){		werrstr("can't open #a/tls/encalgs: %r");		return 0;	}	n = read(j, s, MaxAlgF-1);	close(j);	if(n <= 0){		werrstr("nothing in #a/tls/encalgs: %r");		return 0;	}	s[n] = 0;	n = getfields(s, flds, MaxAlgs, 1, " \t\r\n");	for(i = 0; i < nelem(cipherAlgs); i++){		ok = 0;		for(j = 0; j < n; j++){			if(strcmp(cipherAlgs[i].enc, flds[j]) == 0){				ok = 1;				break;			}		}		cipherAlgs[i].ok = ok;	}	j = open("#a/tls/hashalgs", OREAD);	if(j < 0){		werrstr("can't open #a/tls/hashalgs: %r");		return 0;	}	n = read(j, s, MaxAlgF-1);	close(j);	if(n <= 0){		werrstr("nothing in #a/tls/hashalgs: %r");		return 0;	}	s[n] = 0;	n = getfields(s, flds, MaxAlgs, 1, " \t\r\n");	for(i = 0; i < nelem(cipherAlgs); i++){		ok = 0;		for(j = 0; j < n; j++){			if(strcmp(cipherAlgs[i].digest, flds[j]) == 0){				ok = 1;				break;			}		}		cipherAlgs[i].ok &= ok;		if(cipherAlgs[i].ok)			nciphers++;	}	unlock(&ciphLock);	return nciphers;}static Ints*makeciphers(void){	Ints *is;	int i, j;	is = newints(nciphers);	j = 0;	for(i = 0; i < nelem(cipherAlgs); i++){		if(cipherAlgs[i].ok)			is->data[j++] = cipherAlgs[i].tlsid;	}	return is;}//================= security functions ========================// given X.509 certificate, set up connection to factotum//	for using corresponding private keystatic AuthRpc*factotum_rsa_open(uchar *cert, int certlen){	int afd;	char *s;	mpint *pub = nil;	RSApub *rsapub;	AuthRpc *rpc;	// start talking to factotum	if((afd = open("/mnt/factotum/rpc", ORDWR)) < 0)		return nil;	if((rpc = auth_allocrpc(afd)) == nil){		close(afd);		return nil;	}	s = "proto=rsa service=tls role=client";	if(auth_rpc(rpc, "start", s, strlen(s)) != ARok){		factotum_rsa_close(rpc);		return nil;	}	// roll factotum keyring around to match certificate	rsapub = X509toRSApub(cert, certlen, nil, 0);	while(1){		if(auth_rpc(rpc, "read", nil, 0) != ARok){			factotum_rsa_close(rpc);			rpc = nil;			goto done;		}		pub = strtomp(rpc->arg, nil, 16, nil);		assert(pub != nil);		if(mpcmp(pub,rsapub->n) == 0)			break;	}done:	mpfree(pub);	rsapubfree(rsapub);	return rpc;}static mpint*factotum_rsa_decrypt(AuthRpc *rpc, mpint *cipher){	char *p;	int rv;	if((p = mptoa(cipher, 16, nil, 0)) == nil)		return nil;	rv = auth_rpc(rpc, "write", p, strlen(p));	free(p);	if(rv != ARok || auth_rpc(rpc, "read", nil, 0) != ARok)		return nil;	mpfree(cipher);	return strtomp(rpc->arg, nil, 16, nil);}static voidfactotum_rsa_close(AuthRpc*rpc){	if(!rpc)		return;	close(rpc->afd);	auth_freerpc(rpc);}static voidtlsPmd5(uchar *buf, int nbuf, uchar *key, int nkey, uchar *label, int nlabel, uchar *seed0, int nseed0, uchar *seed1, int nseed1){	uchar ai[MD5dlen], tmp[MD5dlen];	int i, n;	MD5state *s;	// generate a1	s = hmac_md5(label, nlabel, key, nkey, nil, nil);	s = hmac_md5(seed0, nseed0, key, nkey, nil, s);	hmac_md5(seed1, nseed1, key, nkey, ai, s);	while(nbuf > 0) {		s = hmac_md5(ai, MD5dlen, key, nkey, nil, nil);		s = hmac_md5(label, nlabel, key, nkey, nil, s);		s = hmac_md5(seed0, nseed0, key, nkey, nil, s);		hmac_md5(seed1, nseed1, key, nkey, tmp, s);		n = MD5dlen;		if(n > nbuf)			n = nbuf;		for(i = 0; i < n; i++)			buf[i] ^= tmp[i];		buf += n;		nbuf -= n;		hmac_md5(ai, MD5dlen, key, nkey, tmp, nil);		memmove(ai, tmp, MD5dlen);	}}static voidtlsPsha1(uchar *buf, int nbuf, uchar *key, int nkey, uchar *label, int nlabel, uchar *seed0, int nseed0, uchar *seed1, int nseed1){	uchar ai[SHA1dlen], tmp[SHA1dlen];	int i, n;	SHAstate *s;	// generate a1	s = hmac_sha1(label, nlabel, key, nkey, nil, nil);	s = hmac_sha1(seed0, nseed0, key, nkey, nil, s);	hmac_sha1(seed1, nseed1, key, nkey, ai, s);	while(nbuf > 0) {		s = hmac_sha1(ai, SHA1dlen, key, nkey, nil, nil);		s = hmac_sha1(label, nlabel, key, nkey, nil, s);		s = hmac_sha1(seed0, nseed0, key, nkey, nil, s);		hmac_sha1(seed1, nseed1, key, nkey, tmp, s);		n = SHA1dlen;		if(n > nbuf)			n = nbuf;		for(i = 0; i < n; i++)			buf[i] ^= tmp[i];		buf += n;		nbuf -= n;		hmac_sha1(ai, SHA1dlen, key, nkey, tmp, nil);		memmove(ai, tmp, SHA1dlen);	}}// fill buf with md5(args)^sha1(args)static voidtlsPRF(uchar *buf, int nbuf, uchar *key, int nkey, char *label, uchar *seed0, int nseed0, uchar *seed1, int nseed1){	int i;	int nlabel = strlen(label);	int n = (nkey + 1) >> 1;	for(i = 0; i < nbuf; i++)		buf[i] = 0;	tlsPmd5(buf, nbuf, key, n, (uchar*)label, nlabel, seed0, nseed0, seed1, nseed1);	tlsPsha1(buf, nbuf, key+nkey-n, n, (uchar*)label, nlabel, seed0, nseed0, seed1, nseed1);}/* * for setting server session id's */static Lock	sidLock;static long	maxSid = 1;/* the keys are verified to have the same public components

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -