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

📄 tlshand.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 4 页
字号:
 * and to function correctly with pkcs 1 encryption and decryption. */static TlsSec*tlsSecInits(int cvers, uchar *csid, int ncsid, uchar *crandom, uchar *ssid, int *nssid, uchar *srandom){	TlsSec *sec = emalloc(sizeof(*sec));	USED(csid); USED(ncsid);  // ignore csid for now	memmove(sec->crandom, crandom, RandomSize);	sec->clientVers = cvers;	put32(sec->srandom, time(0));	genrandom(sec->srandom+4, RandomSize-4);	memmove(srandom, sec->srandom, RandomSize);	/*	 * make up a unique sid: use our pid, and and incrementing id	 * can signal no sid by setting nssid to 0.	 */	memset(ssid, 0, SidSize);	put32(ssid, getpid());	lock(&sidLock);	put32(ssid+4, maxSid++);	unlock(&sidLock);	*nssid = SidSize;	return sec;}static inttlsSecSecrets(TlsSec *sec, int vers, uchar *epm, int nepm, uchar *kd, int nkd){	if(epm != nil){		if(setVers(sec, vers) < 0)			goto Err;		serverMasterSecret(sec, epm, nepm);	}else if(sec->vers != vers){		werrstr("mismatched session versions");		goto Err;	}	setSecrets(sec, kd, nkd);	return 0;Err:	sec->ok = -1;	return -1;}static TlsSec*tlsSecInitc(int cvers, uchar *crandom){	TlsSec *sec = emalloc(sizeof(*sec));	sec->clientVers = cvers;	put32(sec->crandom, time(0));	genrandom(sec->crandom+4, RandomSize-4);	memmove(crandom, sec->crandom, RandomSize);	return sec;}static inttlsSecSecretc(TlsSec *sec, uchar *sid, int nsid, uchar *srandom, uchar *cert, int ncert, int vers, uchar **epm, int *nepm, uchar *kd, int nkd){	RSApub *pub;	pub = nil;	USED(sid);	USED(nsid);		memmove(sec->srandom, srandom, RandomSize);	if(setVers(sec, vers) < 0)		goto Err;	pub = X509toRSApub(cert, ncert, nil, 0);	if(pub == nil){		werrstr("invalid x509/rsa certificate");		goto Err;	}	if(clientMasterSecret(sec, pub, epm, nepm) < 0)		goto Err;	rsapubfree(pub);	setSecrets(sec, kd, nkd);	return 0;Err:	if(pub != nil)		rsapubfree(pub);	sec->ok = -1;	return -1;}static inttlsSecFinished(TlsSec *sec, MD5state md5, SHAstate sha1, uchar *fin, int nfin, int isclient){	if(sec->nfin != nfin){		sec->ok = -1;		werrstr("invalid finished exchange");		return -1;	}	md5.malloced = 0;	sha1.malloced = 0;	(*sec->setFinished)(sec, md5, sha1, fin, isclient);	return 1;}static voidtlsSecOk(TlsSec *sec){	if(sec->ok == 0)		sec->ok = 1;}static voidtlsSecKill(TlsSec *sec){	if(!sec)		return;	factotum_rsa_close(sec->rpc);	sec->ok = -1;}static voidtlsSecClose(TlsSec *sec){	if(!sec)		return;	factotum_rsa_close(sec->rpc);	free(sec->server);	free(sec);}static intsetVers(TlsSec *sec, int v){	if(v == SSL3Version){		sec->setFinished = sslSetFinished;		sec->nfin = SSL3FinishedLen;		sec->prf = sslPRF;	}else if(v == TLSVersion){		sec->setFinished = tlsSetFinished;		sec->nfin = TLSFinishedLen;		sec->prf = tlsPRF;	}else{		werrstr("invalid version");		return -1;	}	sec->vers = v;	return 0;}/* * generate secret keys from the master secret. * * different crypto selections will require different amounts * of key expansion and use of key expansion data, * but it's all generated using the same function. */static voidsetSecrets(TlsSec *sec, uchar *kd, int nkd){	(*sec->prf)(kd, nkd, sec->sec, MasterSecretSize, "key expansion",			sec->srandom, RandomSize, sec->crandom, RandomSize);}/* * set the master secret from the pre-master secret. */static voidsetMasterSecret(TlsSec *sec, Bytes *pm){	(*sec->prf)(sec->sec, MasterSecretSize, pm->data, MasterSecretSize, "master secret",			sec->crandom, RandomSize, sec->srandom, RandomSize);}static voidserverMasterSecret(TlsSec *sec, uchar *epm, int nepm){	Bytes *pm;	pm = pkcs1_decrypt(sec, epm, nepm);	// if the client messed up, just continue as if everything is ok,	// to prevent attacks to check for correctly formatted messages.	// Hence the fprint(2,) can't be replaced by tlsError(), which sends an Alert msg to the client.	if(sec->ok < 0 || pm == nil || get16(pm->data) != sec->clientVers){		fprint(2, "serverMasterSecret failed ok=%d pm=%p pmvers=%x cvers=%x nepm=%d\n",			sec->ok, pm, pm ? get16(pm->data) : -1, sec->clientVers, nepm);		sec->ok = -1;		if(pm != nil)			freebytes(pm);		pm = newbytes(MasterSecretSize);		genrandom(pm->data, MasterSecretSize);	}	setMasterSecret(sec, pm);	memset(pm->data, 0, pm->len);		freebytes(pm);}static intclientMasterSecret(TlsSec *sec, RSApub *pub, uchar **epm, int *nepm){	Bytes *pm, *key;	pm = newbytes(MasterSecretSize);	put16(pm->data, sec->clientVers);	genrandom(pm->data+2, MasterSecretSize - 2);	setMasterSecret(sec, pm);	key = pkcs1_encrypt(pm, pub, 2);	memset(pm->data, 0, pm->len);	freebytes(pm);	if(key == nil){		werrstr("tls pkcs1_encrypt failed");		return -1;	}	*nepm = key->len;	*epm = malloc(*nepm);	if(*epm == nil){		freebytes(key);		werrstr("out of memory");		return -1;	}	memmove(*epm, key->data, *nepm);	freebytes(key);	return 1;}static voidsslSetFinished(TlsSec *sec, MD5state hsmd5, SHAstate hssha1, uchar *finished, int isClient){	DigestState *s;	uchar h0[MD5dlen], h1[SHA1dlen], pad[48];	char *label;	if(isClient)		label = "CLNT";	else		label = "SRVR";	md5((uchar*)label, 4, nil, &hsmd5);	md5(sec->sec, MasterSecretSize, nil, &hsmd5);	memset(pad, 0x36, 48);	md5(pad, 48, nil, &hsmd5);	md5(nil, 0, h0, &hsmd5);	memset(pad, 0x5C, 48);	s = md5(sec->sec, MasterSecretSize, nil, nil);	s = md5(pad, 48, nil, s);	md5(h0, MD5dlen, finished, s);	sha1((uchar*)label, 4, nil, &hssha1);	sha1(sec->sec, MasterSecretSize, nil, &hssha1);	memset(pad, 0x36, 40);	sha1(pad, 40, nil, &hssha1);	sha1(nil, 0, h1, &hssha1);	memset(pad, 0x5C, 40);	s = sha1(sec->sec, MasterSecretSize, nil, nil);	s = sha1(pad, 40, nil, s);	sha1(h1, SHA1dlen, finished + MD5dlen, s);}// fill "finished" arg with md5(args)^sha1(args)static voidtlsSetFinished(TlsSec *sec, MD5state hsmd5, SHAstate hssha1, uchar *finished, int isClient){	uchar h0[MD5dlen], h1[SHA1dlen];	char *label;	// get current hash value, but allow further messages to be hashed in	md5(nil, 0, h0, &hsmd5);	sha1(nil, 0, h1, &hssha1);	if(isClient)		label = "client finished";	else		label = "server finished";	tlsPRF(finished, TLSFinishedLen, sec->sec, MasterSecretSize, label, h0, MD5dlen, h1, SHA1dlen);}static voidsslPRF(uchar *buf, int nbuf, uchar *key, int nkey, char *label, uchar *seed0, int nseed0, uchar *seed1, int nseed1){	DigestState *s;	uchar sha1dig[SHA1dlen], md5dig[MD5dlen], tmp[26];	int i, n, len;	USED(label);	len = 1;	while(nbuf > 0){		if(len > 26)			return;		for(i = 0; i < len; i++)			tmp[i] = 'A' - 1 + len;		s = sha1(tmp, len, nil, nil);		s = sha1(key, nkey, nil, s);		s = sha1(seed0, nseed0, nil, s);		sha1(seed1, nseed1, sha1dig, s);		s = md5(key, nkey, nil, nil);		md5(sha1dig, SHA1dlen, md5dig, s);		n = MD5dlen;		if(n > nbuf)			n = nbuf;		memmove(buf, md5dig, n);		buf += n;		nbuf -= n;		len++;	}}static mpint*bytestomp(Bytes* bytes){	mpint* ans;	ans = betomp(bytes->data, bytes->len, nil);	return ans;}/* * Convert mpint* to Bytes, putting high order byte first. */static Bytes*mptobytes(mpint* big){	int n, m;	uchar *a;	Bytes* ans;	a = nil;	n = (mpsignif(big)+7)/8;	m = mptobe(big, nil, n, &a);	ans = makebytes(a, m);	if(a != nil)		free(a);	return ans;}// Do RSA computation on block according to key, and pad// result on left with zeros to make it modlen long.static Bytes*rsacomp(Bytes* block, RSApub* key, int modlen){	mpint *x, *y;	Bytes *a, *ybytes;	int ylen;	x = bytestomp(block);	y = rsaencrypt(key, x, nil);	mpfree(x);	ybytes = mptobytes(y);	ylen = ybytes->len;	if(ylen < modlen) {		a = newbytes(modlen);		memset(a->data, 0, modlen-ylen);		memmove(a->data+modlen-ylen, ybytes->data, ylen);		freebytes(ybytes);		ybytes = a;	}	else if(ylen > modlen) {		// assume it has leading zeros (mod should make it so)		a = newbytes(modlen);		memmove(a->data, ybytes->data, modlen);		freebytes(ybytes);		ybytes = a;	}	mpfree(y);	return ybytes;}// encrypt data according to PKCS#1, /lib/rfc/rfc2437 9.1.2.1static Bytes*pkcs1_encrypt(Bytes* data, RSApub* key, int blocktype){	Bytes *pad, *eb, *ans;	int i, dlen, padlen, modlen;	modlen = (mpsignif(key->n)+7)/8;	dlen = data->len;	if(modlen < 12 || dlen > modlen - 11)		return nil;	padlen = modlen - 3 - dlen;	pad = newbytes(padlen);	genrandom(pad->data, padlen);	for(i = 0; i < padlen; i++) {		if(blocktype == 0)			pad->data[i] = 0;		else if(blocktype == 1)			pad->data[i] = 255;		else if(pad->data[i] == 0)			pad->data[i] = 1;	}	eb = newbytes(modlen);	eb->data[0] = 0;	eb->data[1] = blocktype;	memmove(eb->data+2, pad->data, padlen);	eb->data[padlen+2] = 0;	memmove(eb->data+padlen+3, data->data, dlen);	ans = rsacomp(eb, key, modlen);	freebytes(eb);	freebytes(pad);	return ans;}// decrypt data according to PKCS#1, with given key.// expect a block type of 2.static Bytes*pkcs1_decrypt(TlsSec *sec, uchar *epm, int nepm){	Bytes *eb, *ans = nil;	int i, modlen;	mpint *x, *y;	modlen = (mpsignif(sec->rsapub->n)+7)/8;	if(nepm != modlen)		return nil;	x = betomp(epm, nepm, nil);	y = factotum_rsa_decrypt(sec->rpc, x);	if(y == nil)		return nil;	eb = mptobytes(y);	if(eb->len < modlen){ // pad on left with zeros		ans = newbytes(modlen);		memset(ans->data, 0, modlen-eb->len);		memmove(ans->data+modlen-eb->len, eb->data, eb->len);		freebytes(eb);		eb = ans;	}	if(eb->data[0] == 0 && eb->data[1] == 2) {		for(i = 2; i < modlen; i++)			if(eb->data[i] == 0)				break;		if(i < modlen - 1)			ans = makebytes(eb->data+i+1, modlen-(i+1));	}	freebytes(eb);	return ans;}//================= general utility functions ========================static void *emalloc(int n){	void *p;	if(n==0)		n=1;	p = malloc(n);	if(p == nil){		exits("out of memory");	}	memset(p, 0, n);	return p;}static void *erealloc(void *ReallocP, int ReallocN){	if(ReallocN == 0)		ReallocN = 1;	if(!ReallocP)		ReallocP = emalloc(ReallocN);	else if(!(ReallocP = realloc(ReallocP, ReallocN))){		exits("out of memory");	}	return(ReallocP);}static voidput32(uchar *p, u32int x){	p[0] = x>>24;	p[1] = x>>16;	p[2] = x>>8;	p[3] = x;}static voidput24(uchar *p, int x){	p[0] = x>>16;	p[1] = x>>8;	p[2] = x;}static voidput16(uchar *p, int x){	p[0] = x>>8;	p[1] = x;}static u32intget32(uchar *p){	return (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3];}static intget24(uchar *p){	return (p[0]<<16)|(p[1]<<8)|p[2];}static intget16(uchar *p){	return (p[0]<<8)|p[1];}/* ANSI offsetof() */#define OFFSET(x, s) ((int)(&(((s*)0)->x)))/* * malloc and return a new Bytes structure capable of * holding len bytes. (len >= 0) * Used to use crypt_malloc, which aborts if malloc fails. */static Bytes*newbytes(int len){	Bytes* ans;	ans = (Bytes*)malloc(OFFSET(data[0], Bytes) + len);	ans->len = len;	return ans;}/* * newbytes(len), with data initialized from buf */static Bytes*makebytes(uchar* buf, int len){	Bytes* ans;	ans = newbytes(len);	memmove(ans->data, buf, len);	return ans;}static voidfreebytes(Bytes* b){	if(b != nil)		free(b);}/* len is number of ints */static Ints*newints(int len){	Ints* ans;	ans = (Ints*)malloc(OFFSET(data[0], Ints) + len*sizeof(int));	ans->len = len;	return ans;}static Ints*makeints(int* buf, int len){	Ints* ans;	ans = newints(len);	if(len > 0)		memmove(ans->data, buf, len*sizeof(int));	return ans;}static voidfreeints(Ints* b){	if(b != nil)		free(b);}

⌨️ 快捷键说明

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