diff e54b6c6cbd4d82d70ddb4932aeafb0b028cd71f5 uncommitted --- a//sys/man/2/pushtls +++ b//sys/man/2/pushtls @@ -1,6 +1,6 @@ .TH PUSHTLS 2 .SH NAME -pushtls, tlsClient, tlsServer, initThumbprints, freeThumbprints, okThumbprint, okCertificate, readcert, readcertchain \- attach TLS1 or SSL3 encryption to a communication channel +pushtls, tlsClient, tlsServer, initThumbprints, freeThumbprints, okThumbprint, okCertificate, readcert, readcertchain \- attach TLS encryption to a communication channel .SH SYNOPSIS .B #include .br @@ -45,8 +45,6 @@ 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), --- a//sys/man/3/tls +++ b//sys/man/3/tls @@ -1,6 +1,6 @@ .TH TLS 3 .SH NAME -tls \- TLS and SSL3 record layer +tls \- TLS record layer .SH SYNOPSIS .nf .B bind -a #a /net @@ -16,10 +16,9 @@ .BI /net/tls/ n /status .fi .SH DESCRIPTION -The TLS device implements the record layer protocols -of Transport Layer Security version 1.0-1.2 and Secure Sockets Layer version 3.0. -It does not implement the handshake protocols, which are responsible for -mutual authentication and key exchange. +The TLS device implements the record layer protocols of Transport Layer Security +version 1.0-1.2. It does not implement the handshake protocols, which are responsible +for mutual authentication and key exchange. The .I tls device can be thought of as filters providing optional encryption and anti-tampering. @@ -53,13 +52,11 @@ .I vers format records, but incoming messages of either version are accepted. Valid versions are -.B 0x300 -for SSLv3.0 and .BR 0x301 , .B 0x302 and .B 0x303 -for TLSv1.0 (which could be known as SSLv3.01), TLSv1.1 and TLSv1.2. +for TLSv1.0, TLSv1.1 and TLSv1.2. This command must be issued before any other command and before reading or writing any messages; it may only be executed once. @@ -120,10 +117,9 @@ .TP .BI alert \ alertno Send an alert message. -.I Alertno -may be a valid alert code for either SSLv3.0 or TLS, -and is mapped to an appropriate code for the protocol in use. -If it is a fatal alert, the filter is set into an error state. +If +.I alertno +is a fatal alert, the filter is set into an error state. .PP Application messages and handshake messages are communicated using .I data --- a//sys/src/9/port/devtls.c +++ b//sys/src/9/port/devtls.c @@ -1,5 +1,5 @@ /* - * devtls - record layer for transport layer security 1.2 and secure sockets layer 3.0 + * devtls - record layer for transport layer security 1.0-1.2 */ #include "u.h" #include "../port/lib.h" @@ -24,11 +24,10 @@ MaxMacLen = SHA2_256dlen, /* protocol versions we can accept */ - SSL3Version = 0x0300, TLS10Version = 0x0301, TLS11Version = 0x0302, TLS12Version = 0x0303, - MinProtoVersion = 0x0300, /* limits on version we accept */ + MinProtoVersion = 0x0301, /* limits on version we accept */ MaxProtoVersion = 0x03ff, /* connection states */ @@ -46,9 +45,6 @@ RHandshake, RApplication, - SSL2ClientHello = 1, - HSSL2ClientHello = 9, /* local convention; see tlshand.c */ - /* alerts */ ECloseNotify = 0, EUnexpectedMessage = 10, @@ -57,7 +53,6 @@ ERecordOverflow = 22, EDecompressionFailure = 30, EHandshakeFailure = 40, - ENoCertificate = 41, EBadCertificate = 42, EUnsupportedCertificate = 43, ECertificateRevoked = 44, @@ -89,7 +84,6 @@ int (*enc)(Secret*, uchar*, int); int (*dec)(Secret*, uchar*, int); - int (*unpad)(uchar*, int, int); DigestState* (*mac)(uchar*, ulong, uchar*, ulong, uchar*, DigestState*); int block; /* encryption block len, 0 if none */ @@ -125,12 +119,6 @@ int state; int debug; - /* - * function to genrate authenticated data blob for different - * protocol versions - */ - int (*packAAD)(u64int, uchar*, uchar*); - /* input side -- protected by in.io */ OneWay in; Block *processed; /* next bunch of application data */ @@ -153,37 +141,34 @@ struct TlsErrs{ int err; - int sslerr; - int tlserr; int fatal; char *msg; }; static TlsErrs tlserrs[] = { - {ECloseNotify, ECloseNotify, ECloseNotify, 0, "close notify"}, - {EUnexpectedMessage, EUnexpectedMessage, EUnexpectedMessage, 1, "unexpected message"}, - {EBadRecordMac, EBadRecordMac, EBadRecordMac, 1, "bad record mac"}, - {EDecryptionFailed, EIllegalParameter, EDecryptionFailed, 1, "decryption failed"}, - {ERecordOverflow, EIllegalParameter, ERecordOverflow, 1, "record too long"}, - {EDecompressionFailure, EDecompressionFailure, EDecompressionFailure, 1, "decompression failed"}, - {EHandshakeFailure, EHandshakeFailure, EHandshakeFailure, 1, "could not negotiate acceptable security parameters"}, - {ENoCertificate, ENoCertificate, ECertificateUnknown, 1, "no appropriate certificate available"}, - {EBadCertificate, EBadCertificate, EBadCertificate, 1, "corrupted or invalid certificate"}, - {EUnsupportedCertificate, EUnsupportedCertificate, EUnsupportedCertificate, 1, "unsupported certificate type"}, - {ECertificateRevoked, ECertificateRevoked, ECertificateRevoked, 1, "revoked certificate"}, - {ECertificateExpired, ECertificateExpired, ECertificateExpired, 1, "expired certificate"}, - {ECertificateUnknown, ECertificateUnknown, ECertificateUnknown, 1, "unacceptable certificate"}, - {EIllegalParameter, EIllegalParameter, EIllegalParameter, 1, "illegal parameter"}, - {EUnknownCa, EHandshakeFailure, EUnknownCa, 1, "unknown certificate authority"}, - {EAccessDenied, EHandshakeFailure, EAccessDenied, 1, "access denied"}, - {EDecodeError, EIllegalParameter, EDecodeError, 1, "error decoding message"}, - {EDecryptError, EIllegalParameter, EDecryptError, 1, "error decrypting message"}, - {EExportRestriction, EHandshakeFailure, EExportRestriction, 1, "export restriction violated"}, - {EProtocolVersion, EIllegalParameter, EProtocolVersion, 1, "protocol version not supported"}, - {EInsufficientSecurity, EHandshakeFailure, EInsufficientSecurity, 1, "stronger security routines required"}, - {EInternalError, EHandshakeFailure, EInternalError, 1, "internal error"}, - {EUserCanceled, ECloseNotify, EUserCanceled, 0, "handshake canceled by user"}, - {ENoRenegotiation, EUnexpectedMessage, ENoRenegotiation, 0, "no renegotiation"}, + {ECloseNotify, 0, "close notify"}, + {EUnexpectedMessage, 1, "unexpected message"}, + {EBadRecordMac, 1, "bad record mac"}, + {EDecryptionFailed, 1, "decryption failed"}, + {ERecordOverflow, 1, "record too long"}, + {EDecompressionFailure, 1, "decompression failed"}, + {EHandshakeFailure, 1, "could not negotiate acceptable security parameters"}, + {EBadCertificate, 1, "corrupted or invalid certificate"}, + {EUnsupportedCertificate, 1, "unsupported certificate type"}, + {ECertificateRevoked, 1, "revoked certificate"}, + {ECertificateExpired, 1, "expired certificate"}, + {ECertificateUnknown, 1, "unacceptable certificate"}, + {EIllegalParameter, 1, "illegal parameter"}, + {EUnknownCa, 1, "unknown certificate authority"}, + {EAccessDenied, 1, "access denied"}, + {EDecodeError, 1, "error decoding message"}, + {EDecryptError, 1, "error decrypting message"}, + {EExportRestriction, 1, "export restriction violated"}, + {EProtocolVersion, 1, "protocol version not supported"}, + {EInsufficientSecurity, 1, "stronger security routines required"}, + {EInternalError, 1, "internal error"}, + {EUserCanceled, 0, "handshake canceled by user"}, + {ENoRenegotiation, 0, "no renegotiation"}, }; enum @@ -227,11 +212,8 @@ static void alertHand(TlsRec*, char *); static TlsRec *newtls(Chan *c); static TlsRec *mktlsrec(void); -static DigestState*sslmac_md5(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s); -static DigestState*sslmac_sha1(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s); static DigestState*nomac(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s); -static int sslPackAAD(u64int, uchar*, uchar*); -static int tlsPackAAD(u64int, uchar*, uchar*); +static int packAAD(u64int, uchar*, uchar*); static void packMac(Secret*, uchar*, int, uchar*, int, uchar*); static void put64(uchar *p, u64int); static void put32(uchar *p, u32int); @@ -252,8 +234,7 @@ static int aesgcm_aead_enc(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len); static int aesgcm_aead_dec(Secret *sec, uchar *aad, int aadlen, uchar *reciv, uchar *data, int len); static int noenc(Secret *sec, uchar *buf, int n); -static int sslunpad(uchar *buf, int n, int block); -static int tlsunpad(uchar *buf, int n, int block); +static int unpad(uchar *buf, int n, int block); static void freeSec(Secret *sec); static char *tlsstate(int s); static void pdump(int, void*, char*); @@ -749,20 +730,10 @@ if(tr->debug)pprint("consumed %d header\n", RecHdrLen); nconsumed = RecHdrLen; - if((tr->handin == 0) && (header[0] & 0x80)){ - /* Cope with an SSL3 ClientHello expressed in SSL2 record format. - This is sent by some clients that we must interoperate - with, such as Java's JSSE and Microsoft's Internet Explorer. */ - len = (get16(header) & ~0x8000) - 3; - type = header[2]; - ver = get16(header + 3); - if(type != SSL2ClientHello || len < 22) - rcvError(tr, EProtocolVersion, "invalid initial SSL2-like message"); - }else{ /* normal SSL3 record format */ - type = header[0]; - ver = get16(header+1); - len = get16(header+3); - } + type = header[0]; + ver = get16(header+1); + len = get16(header+3); + if(ver != tr->version && (tr->verset || ver < MinProtoVersion || ver > MaxProtoVersion)) rcvError(tr, EProtocolVersion, "devtls expected ver=%x%s, saw (len=%d) type=%x ver=%x '%.12s'", tr->version, tr->verset?"/set":"", len, type, ver, (char*)header); @@ -823,7 +794,7 @@ /* update length */ put16(header+3, len); - aadlen = (*tr->packAAD)(in->seq++, header, aad); + aadlen = packAAD(in->seq++, header, aad); if(sec->aead_dec != nil) { len = (*sec->aead_dec)(sec, aad, aadlen, p - ivlen, p, unpad_len); if(len < 0) @@ -916,42 +887,12 @@ dechandq(tr); }else{ unlock(&tr->hqlock); - if(tr->verset && tr->version != SSL3Version && !waserror()){ + if(tr->verset && !waserror()){ sendAlert(tr, ENoRenegotiation); poperror(); } } break; - case SSL2ClientHello: - lock(&tr->hqlock); - if(tr->handq != nil){ - tr->hqref++; - unlock(&tr->hqlock); - if(waserror()){ - dechandq(tr); - nexterror(); - } - /* Pass the SSL2 format data, so that the handshake code can compute - the correct checksums. HSSL2ClientHello = HandshakeType 9 is - unused in RFC2246. */ - b = padblock(b, 8); - b->rp[0] = RHandshake; - b->rp[1] = HSSL2ClientHello; - put24(&b->rp[2], len+3); - b->rp[5] = SSL2ClientHello; - put16(&b->rp[6], ver); - qbwrite(tr->handq, b); - b = nil; - poperror(); - dechandq(tr); - }else{ - unlock(&tr->hqlock); - if(tr->verset && tr->version != SSL3Version && !waserror()){ - sendAlert(tr, ENoRenegotiation); - poperror(); - } - } - break; case RApplication: if(!tr->opened) rcvError(tr, EUnexpectedMessage, "application message received before handshake completed"); @@ -1314,7 +1255,7 @@ put16(p+3, n); if(sec != nil){ - aadlen = (*tr->packAAD)(out->seq++, p, aad); + aadlen = packAAD(out->seq++, p, aad); if(sec->aead_enc != nil) n = (*sec->aead_enc)(sec, aad, aadlen, p + RecHdrLen, p + RecHdrLen + ivlen, n) + ivlen; else { @@ -1390,42 +1331,34 @@ { char *name; int maclen; - void (*initkey)(Hashalg *, int, Secret *, uchar*); + void (*initkey)(Hashalg *, Secret *, uchar*); }; static void -initmd5key(Hashalg *ha, int version, Secret *s, uchar *p) +initmd5key(Hashalg *ha, Secret *s, uchar *p) { s->maclen = ha->maclen; - if(version == SSL3Version) - s->mac = sslmac_md5; - else - s->mac = hmac_md5; + s->mac = hmac_md5; memmove(s->mackey, p, ha->maclen); } static void -initclearmac(Hashalg *, int, Secret *s, uchar *) +initclearmac(Hashalg *, Secret *s, uchar *) { s->mac = nomac; } static void -initsha1key(Hashalg *ha, int version, Secret *s, uchar *p) +initsha1key(Hashalg *ha, Secret *s, uchar *p) { s->maclen = ha->maclen; - if(version == SSL3Version) - s->mac = sslmac_sha1; - else - s->mac = hmac_sha1; + s->mac = hmac_sha1; memmove(s->mackey, p, ha->maclen); } static void -initsha2_256key(Hashalg *ha, int version, Secret *s, uchar *p) +initsha2_256key(Hashalg *ha, Secret *s, uchar *p) { - if(version == SSL3Version) - error("sha256 cannot be used with SSL"); s->maclen = ha->maclen; s->mac = hmac_sha2_256; memmove(s->mackey, p, ha->maclen); @@ -1641,10 +1574,6 @@ m = strtol(cb->f[1], nil, 0); if(m < MinProtoVersion || m > MaxProtoVersion) error("unsupported version"); - if(m == SSL3Version) - tr->packAAD = sslPackAAD; - else - tr->packAAD = tlsPackAAD; tr->verset = 1; tr->version = m; }else if(strcmp(cb->f[0], "secret") == 0){ @@ -1685,8 +1614,8 @@ if(!ha->initkey || !ea->initkey) error("misimplemented secret algorithm"); - (*ha->initkey)(ha, tr->version, tos, &x[0]); - (*ha->initkey)(ha, tr->version, toc, &x[ha->maclen]); + (*ha->initkey)(ha, tos, &x[0]); + (*ha->initkey)(ha, toc, &x[ha->maclen]); (*ea->initkey)(ea, tos, &x[2 * ha->maclen], &x[2 * ha->maclen + 2 * ea->keylen]); (*ea->initkey)(ea, toc, &x[2 * ha->maclen + ea->keylen], &x[2 * ha->maclen + 2 * ea->keylen + ea->ivlen]); @@ -1701,13 +1630,6 @@ tr->in.new = toc; tr->out.new = tos; } - if(tr->version == SSL3Version){ - toc->unpad = sslunpad; - tos->unpad = sslunpad; - }else{ - toc->unpad = tlsunpad; - tos->unpad = tlsunpad; - } toc->encalg = ea->name; toc->hashalg = ha->name; tos->encalg = ea->name; @@ -1879,17 +1801,12 @@ if(tr->debug)pprint("sendAlert %d\n", err); fatal = 1; msg = "tls unknown alert"; - for(i=0; i < nelem(tlserrs); i++) { - if(tlserrs[i].err == err) { + for(i=0; i < nelem(tlserrs); i++) + if(tlserrs[i].err == err){ msg = tlserrs[i].msg; - if(tr->version == SSL3Version) - err = tlserrs[i].sslerr; - else - err = tlserrs[i].tlserr; fatal = tlserrs[i].fatal; break; } - } if(!waserror()){ b = allocb(2); @@ -2061,7 +1978,7 @@ } static int -tlsunpad(uchar *buf, int n, int block) +unpad(uchar *buf, int n, int block) { int pad, nn; @@ -2076,18 +1993,6 @@ } static int -sslunpad(uchar *buf, int n, int block) -{ - int pad, nn; - - pad = buf[n - 1]; - nn = n - 1 - pad; - if(nn <= 0 || n % block) - return -1; - return nn; -} - -static int blockpad(uchar *buf, int n, int block) { int pad, nn; @@ -2112,7 +2017,7 @@ des3dec(Secret *sec, uchar *buf, int n) { des3CBCdecrypt(buf, n, sec->enckey); - return (*sec->unpad)(buf, n, 8); + return unpad(buf, n, 8); } static int @@ -2127,7 +2032,7 @@ aesdec(Secret *sec, uchar *buf, int n) { aesCBCdecrypt(buf, n, sec->enckey); - return (*sec->unpad)(buf, n, 16); + return unpad(buf, n, 16); } static void @@ -2213,71 +2118,8 @@ return nil; } -/* - * sslmac: mac calculations for ssl 3.0 only; tls 1.0 uses the standard hmac. - */ -static DigestState* -sslmac_x(uchar *p, ulong len, uchar *key, ulong klen, uchar *digest, DigestState *s, - DigestState*(*x)(uchar*, ulong, uchar*, DigestState*), int xlen, int padlen) -{ - int i; - uchar pad[48], innerdigest[20]; - - if(xlen > sizeof(innerdigest) - || padlen > sizeof(pad)) - return nil; - - if(klen>64) - return nil; - - /* first time through */ - if(s == nil){ - for(i=0; i= TLS10Version){ - m = p - b; - b = erealloc(b, m + 2+2+2+nelem(namedcurves)*2 + 2+2+1+nelem(pointformats)); - p = b + m; + m = p - b; + b = erealloc(b, m + 2+2+2+nelem(namedcurves)*2 + 2+2+1+nelem(pointformats)); + p = b + m; - n = nelem(namedcurves); - put16(p, Extec), p += 2; /* Type: elliptic_curves / supported_groups */ - put16(p, (n+1)*2), p += 2; /* Length */ - put16(p, n*2), p += 2; /* Elliptic Curves Length */ - for(i=0; i < n; i++){ /* Elliptic Curves */ - put16(p, namedcurves[i].tlsid); - p += 2; - } - - n = nelem(pointformats); - put16(p, Extecp), p += 2; /* Type: ec_point_formats */ - put16(p, n+1), p += 2; /* Length */ - *p++ = n; /* EC point formats Length */ - for(i=0; i < n; i++) /* EC point formats */ - *p++ = pointformats[i]; + n = nelem(namedcurves); + put16(p, Extec), p += 2; /* Type: elliptic_curves / supported_groups */ + put16(p, (n+1)*2), p += 2; /* Length */ + put16(p, n*2), p += 2; /* Elliptic Curves Length */ + for(i=0; i < n; i++){ /* Elliptic Curves */ + put16(p, namedcurves[i].tlsid); + p += 2; } + n = nelem(pointformats); + put16(p, Extecp), p += 2; /* Type: ec_point_formats */ + put16(p, n+1), p += 2; /* Length */ + *p++ = n; /* EC point formats Length */ + for(i=0; i < n; i++) /* EC point formats */ + *p++ = pointformats[i]; + // signature algorithms if(ProtocolVersion >= TLS12Version){ n = nelem(sigalgs); @@ -849,10 +835,7 @@ } /* no CertificateVerify; skip to Finished */ - if(tlsSecFinished(c->sec, c->handhash, c->finished.verify, c->finished.n, 1) < 0){ - tlsError(c, EInternalError, "can't set finished: %r"); - goto Err; - } + (*c->sec->setFinished)(c->sec, c->handhash, c->finished, 1); if(!msgRecv(c, &m)) goto Err; if(m.tag != HFinished) { @@ -859,7 +842,7 @@ tlsError(c, EUnexpectedMessage, "expected a finished"); goto Err; } - if(!finishedMatch(c, &m.u.finished)) { + if(tsmemcmp(c->finished, m.u.finished, FinishedLen) != 0) { tlsError(c, EHandshakeFailure, "finished verification failed"); goto Err; } @@ -871,12 +854,9 @@ goto Err; } - if(tlsSecFinished(c->sec, c->handhash, c->finished.verify, c->finished.n, 0) < 0){ - tlsError(c, EInternalError, "can't set finished: %r"); - goto Err; - } + (*c->sec->setFinished)(c->sec, c->handhash, c->finished, 0); m.tag = HFinished; - m.u.finished = c->finished; + memmove(m.u.finished, c->finished, FinishedLen); if(!msgSend(c, &m, AFlush)) goto Err; if(trace) @@ -1220,21 +1200,15 @@ // Cipherchange must occur immediately before Finished to avoid // potential hole; see section 4.3 of Wagner Schneier 1996. - if(tlsSecFinished(c->sec, c->handhash, c->finished.verify, c->finished.n, 1) < 0){ - tlsError(c, EInternalError, "can't set finished 1: %r"); - goto Err; - } + (*c->sec->setFinished)(c->sec, c->handhash, c->finished, 1); m.tag = HFinished; - m.u.finished = c->finished; + memmove(m.u.finished, c->finished, FinishedLen); if(!msgSend(c, &m, AFlush)) { tlsError(c, EInternalError, "can't flush after client Finished: %r"); goto Err; } - if(tlsSecFinished(c->sec, c->handhash, c->finished.verify, c->finished.n, 0) < 0){ - tlsError(c, EInternalError, "can't set finished 0: %r"); - goto Err; - } + (*c->sec->setFinished)(c->sec, c->handhash, c->finished, 0); if(!msgRecv(c, &m)) { tlsError(c, EInternalError, "can't read server Finished: %r"); goto Err; @@ -1244,7 +1218,7 @@ goto Err; } - if(!finishedMatch(c, &m.u.finished)) { + if(tsmemcmp(c->finished, m.u.finished, FinishedLen) != 0) { tlsError(c, EHandshakeFailure, "finished verification failed"); goto Err; } @@ -1418,16 +1392,16 @@ goto Overflow; if(isECDHE(c->cipher)) *p++ = n; - else if(isDHE(c->cipher) || c->version != SSL3Version) + else put16(p, n), p += 2; memmove(p, m->u.clientKeyExchange.key->data, n); p += n; break; case HFinished: - if(p+m->u.finished.n > e) + if(p+FinishedLen > e) goto Overflow; - memmove(p, m->u.finished.verify, m->u.finished.n); - p += m->u.finished.n; + memmove(p, m->u.finished, FinishedLen); + p += FinishedLen; break; } @@ -1495,50 +1469,6 @@ } } - if(type == HSSL2ClientHello){ - /* Cope with an SSL3 ClientHello expressed in SSL2 record format. - This is sent by some clients that we must interoperate - with, such as Java's JSSE and Microsoft's Internet Explorer. */ - int nsid, nrandom, nciph; - - p = tlsReadN(c, n); - if(p == nil) - return 0; - msgHash(c, p, n); - m->tag = HClientHello; - if(n < 22) - goto Short; - m->u.clientHello.version = get16(p+1); - p += 3; - n -= 3; - nn = get16(p); /* cipher_spec_len */ - nsid = get16(p + 2); - nrandom = get16(p + 4); - p += 6; - n -= 6; - if(nsid != 0 /* no sid's, since shouldn't restart using ssl2 header */ - || nrandom < 16 || nn % 3 || n - nrandom < nn) - goto Err; - /* ignore ssl2 ciphers and look for {0x00, ssl3 cipher} */ - nciph = 0; - for(i = 0; i < nn; i += 3) - if(p[i] == 0) - nciph++; - m->u.clientHello.ciphers = newints(nciph); - nciph = 0; - for(i = 0; i < nn; i += 3) - if(p[i] == 0) - m->u.clientHello.ciphers->data[nciph++] = get16(&p[i + 1]); - p += nn; - m->u.clientHello.sid = makebytes(nil, 0); - if(nrandom > RandomSize) - nrandom = RandomSize; - memset(m->u.clientHello.random, 0, RandomSize - nrandom); - memmove(&m->u.clientHello.random[RandomSize - nrandom], p, nrandom); - m->u.clientHello.compressors = newbytes(1); - m->u.clientHello.compressors->data[0] = CompressionNull; - goto Ok; - } msgHash(c, p, 4); p = tlsReadN(c, n); @@ -1790,10 +1720,8 @@ goto Short; if(isECDHE(c->cipher)) nn = *p++, n--; - else if(isDHE(c->cipher) || c->version != SSL3Version) - nn = get16(p), p += 2, n -= 2; else - nn = n; + nn = get16(p), p += 2, n -= 2; if(n < nn) goto Short; m->u.clientKeyExchange.key = makebytes(p, nn); @@ -1800,17 +1728,16 @@ n -= nn; break; case HFinished: - m->u.finished.n = c->finished.n; - if(n < m->u.finished.n) + if(n < FinishedLen) goto Short; - memmove(m->u.finished.verify, p, m->u.finished.n); - n -= m->u.finished.n; + memmove(m->u.finished, p, FinishedLen); + n -= FinishedLen; break; } if(n != 0 && type != HClientHello && type != HServerHello) goto Short; -Ok: + if(c->trace) c->trace("recv %s", msgPrint((char*)c->sendp, &c->buf[sizeof(c->buf)] - c->sendp, m)); return 1; @@ -2000,8 +1927,8 @@ break; case HFinished: bs = seprint(bs, be, "HFinished\n"); - for(i=0; iu.finished.n; i++) - bs = seprint(bs, be, "%.2x", m->u.finished.verify[i]); + for(i=0; iu.finished[i]); bs = seprint(bs, be, "\n"); break; } @@ -2036,23 +1963,11 @@ return -1; if(version > c->version) version = c->version; - if(version == SSL3Version) { + else c->version = version; - c->finished.n = SSL3FinishedLen; - }else { - c->version = version; - c->finished.n = TLSFinishedLen; - } return fprint(c->ctl, "version 0x%x", version); } -// confirm that received Finished message matches the expected value -static int -finishedMatch(TlsConnection *c, Finished *f) -{ - return tsmemcmp(f->verify, c->finished.verify, f->n) == 0; -} - // free memory associated with TlsConnection struct // (but don't close the TLS channel itself) static void @@ -2390,68 +2305,6 @@ hmac_sha2_256, SHA2_256dlen); } -static void -sslPRF(uchar *buf, int nbuf, uchar *key, int nkey, char *label, uchar *seed, int nseed) -{ - uchar sha1dig[SHA1dlen], md5dig[MD5dlen], tmp[26]; - DigestState *s; - 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); - sha1(seed, nseed, 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 void -sslSetFinished(TlsSec *sec, HandshakeHash hsh, 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, &hsh.md5); - md5(sec->sec, MasterSecretSize, nil, &hsh.md5); - memset(pad, 0x36, 48); - md5(pad, 48, nil, &hsh.md5); - md5(nil, 0, h0, &hsh.md5); - 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, &hsh.sha1); - sha1(sec->sec, MasterSecretSize, nil, &hsh.sha1); - memset(pad, 0x36, 40); - sha1(pad, 40, nil, &hsh.sha1); - sha1(nil, 0, h1, &hsh.sha1); - 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 void tls10SetFinished(TlsSec *sec, HandshakeHash hsh, uchar *finished, int isclient) @@ -2460,6 +2313,8 @@ char *label; // get current hash value, but allow further messages to be hashed in + hsh.md5.malloced = 0; + hsh.sha1.malloced = 0; md5(nil, 0, h, &hsh.md5); sha1(nil, 0, h+MD5dlen, &hsh.sha1); @@ -2467,7 +2322,7 @@ label = "client finished"; else label = "server finished"; - tls10PRF(finished, TLSFinishedLen, sec->sec, MasterSecretSize, label, h, sizeof(h)); + tls10PRF(finished, FinishedLen, sec->sec, MasterSecretSize, label, h, sizeof(h)); } static void @@ -2477,6 +2332,7 @@ char *label; // get current hash value, but allow further messages to be hashed in + hsh.sha2_256.malloced = 0; sha2_256(nil, 0, seed, &hsh.sha2_256); if(isclient) @@ -2483,7 +2339,7 @@ label = "client finished"; else label = "server finished"; - tls12PRF(finished, TLSFinishedLen, sec->sec, MasterSecretSize, label, seed, SHA2_256dlen); + tls12PRF(finished, FinishedLen, sec->sec, MasterSecretSize, label, seed, SHA2_256dlen); } static void @@ -2630,34 +2486,14 @@ return epm; } -static int -tlsSecFinished(TlsSec *sec, HandshakeHash hsh, uchar *fin, int nfin, int isclient) -{ - if(sec->nfin != nfin){ - werrstr("invalid finished exchange"); - return -1; - } - hsh.md5.malloced = 0; - hsh.sha1.malloced = 0; - hsh.sha2_256.malloced = 0; - (*sec->setFinished)(sec, hsh, fin, isclient); - return 0; -} - static void tlsSecVers(TlsSec *sec, int v) { - if(v == SSL3Version){ - sec->setFinished = sslSetFinished; - sec->nfin = SSL3FinishedLen; - sec->prf = sslPRF; - }else if(v < TLS12Version) { + if(v < TLS12Version){ sec->setFinished = tls10SetFinished; - sec->nfin = TLSFinishedLen; sec->prf = tls10PRF; - }else { + }else{ sec->setFinished = tls12SetFinished; - sec->nfin = TLSFinishedLen; sec->prf = tls12PRF; } }