diff 5b5f69513adcb9939e4ebd93bf8adfbfdc08fcf1 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,12 +24,11 @@ MaxMacLen = SHA2_256dlen, /* protocol versions we can accept */ - SSL3Version = 0x0300, TLS10Version = 0x0301, TLS11Version = 0x0302, TLS12Version = 0x0303, - MinProtoVersion = 0x0300, /* limits on version we accept */ - MaxProtoVersion = 0x03ff, + MinProtoVersion = TLS10Version, /* limits on version we accept */ + MaxProtoVersion = TLS12Version, /* connection states */ SHandshake = 1 << 0, /* doing handshake */ @@ -57,7 +56,6 @@ ERecordOverflow = 22, EDecompressionFailure = 30, EHandshakeFailure = 40, - ENoCertificate = 41, EBadCertificate = 42, EUnsupportedCertificate = 43, ECertificateRevoked = 44, @@ -89,7 +87,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 +122,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 +144,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 +215,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 +237,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*); @@ -750,7 +734,7 @@ nconsumed = RecHdrLen; if((tr->handin == 0) && (header[0] & 0x80)){ - /* Cope with an SSL3 ClientHello expressed in SSL2 record format. + /* Cope with a TLS 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; @@ -757,13 +741,13 @@ 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 */ + rcvError(tr, EUnexpectedMessage, "invalid initial SSL2-like message"); + }else{ /* normal TLS record format */ type = header[0]; ver = get16(header+1); len = get16(header+3); } - if(ver != tr->version && (tr->verset || ver < MinProtoVersion || ver > MaxProtoVersion)) + if(ver != tr->version && (tr->verset || ver>>8 != 0x03)) 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); if(len > MaxCipherRecLen || len < 0) @@ -823,7 +807,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,7 +900,7 @@ dechandq(tr); }else{ unlock(&tr->hqlock); - if(tr->verset && tr->version != SSL3Version && !waserror()){ + if(tr->verset && !waserror()){ sendAlert(tr, ENoRenegotiation); poperror(); } @@ -933,7 +917,7 @@ } /* Pass the SSL2 format data, so that the handshake code can compute the correct checksums. HSSL2ClientHello = HandshakeType 9 is - unused in RFC2246. */ + unused in RFC5246. */ b = padblock(b, 8); b->rp[0] = RHandshake; b->rp[1] = HSSL2ClientHello; @@ -946,7 +930,7 @@ dechandq(tr); }else{ unlock(&tr->hqlock); - if(tr->verset && tr->version != SSL3Version && !waserror()){ + if(tr->verset && !waserror()){ sendAlert(tr, ENoRenegotiation); poperror(); } @@ -1314,7 +1298,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 +1374,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 +1617,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 +1657,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 +1673,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 +1844,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 +2021,7 @@ } static int -tlsunpad(uchar *buf, int n, int block) +unpad(uchar *buf, int n, int block) { int pad, nn; @@ -2076,18 +2036,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 +2060,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 +2075,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 +2161,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; icert, conn->certlen, conn->pskID, conn->psk, conn->psklen, @@ -511,28 +499,26 @@ } // Elliptic Curves (also called Supported Groups) - if(ProtocolVersion >= 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); @@ -591,7 +577,7 @@ close(ctl); return -1; } - fprint(ctl, "fd %d 0x%x", fd, ProtocolVersion); + fprint(ctl, "fd %d 0x%x", fd, MinProtoVersion); ext = tlsClientExtensions(conn, &n); tls = tlsClient2(ctl, hand, conn->cert, conn->certlen, @@ -713,8 +699,8 @@ } if(trace) trace("ClientHello version %x\n", m.u.clientHello.version); - if(setVersion(c, m.u.clientHello.version) < 0) { - tlsError(c, EIllegalParameter, "incompatible version"); + if(setVersion(c, m.u.clientHello.version, 0) < 0){ + tlsError(c, EProtocolVersion, "incompatible version"); goto Err; } if(c->version < ProtocolVersion @@ -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) @@ -1056,8 +1036,8 @@ tlsError(c, EUnexpectedMessage, "expected a server hello"); goto Err; } - if(setVersion(c, m.u.serverHello.version) < 0) { - tlsError(c, EIllegalParameter, "incompatible version: %r"); + if(setVersion(c, m.u.serverHello.version, 1) < 0){ + tlsError(c, EProtocolVersion, "incompatible version: %r"); goto Err; } tlsSecVers(c->sec, c->version); @@ -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; } @@ -1496,7 +1470,7 @@ } if(type == HSSL2ClientHello){ - /* Cope with an SSL3 ClientHello expressed in SSL2 record format. + /* Cope with a TLS 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; @@ -1519,7 +1493,7 @@ 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} */ + /* ignore ssl2 ciphers and look for {0x00, tls cipher} */ nciph = 0; for(i = 0; i < nn; i += 3) if(p[i] == 0) @@ -1790,10 +1764,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,11 +1772,10 @@ 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; } @@ -2000,8 +1971,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; } @@ -2030,29 +2001,20 @@ // commit to specific version number static int -setVersion(TlsConnection *c, int version) +setVersion(TlsConnection *c, int version, int client) { - if(version > MaxProtoVersion || version < MinProtoVersion) + if(version < MinProtoVersion) return -1; - if(version > c->version) - version = c->version; - if(version == SSL3Version) { + if(version > c->version){ + if(client) + return -1; + else + version = c->version; + }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 +2352,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 +2360,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 +2369,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 +2379,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 +2386,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 +2533,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; } }