📄 tlshand.c
字号:
* 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 + -