Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extension to support optional headerless records in TLS 1.3 #2

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 21 additions & 5 deletions nss/lib/ssl/ssl3con.c
Original file line number Diff line number Diff line change
Expand Up @@ -2636,12 +2636,21 @@ ssl3_CompressMACEncryptRecord(ssl3CipherSpec * cwSpec,

/* Limit length of ciphertext we produce */
PRUint32 ctextLen = TLS13_PAD_FRAGMENT_LENGTH;
if (cwSpec->writeNextLen != 0) { /* length already committed? */
ctextLen = cwSpec->writeNextLen; /* then abide by it */
headerLen = 0; /* and go headerless */
}

/* Limit cleartext contentLen accordingly */
PRUint32 thisLen = PR_MIN(contentLen, ctextLen - overhead);
PRUint32 nextLen = contentLen - thisLen; /* left for next record */
*pContentLen = contentLen = thisLen;
PRUint32 padLen = ctextLen - contentLen - overhead;

/* The next record can be any multiple of the padding granularity */
cwSpec->writeNextLen = (nextLen+overhead+TLS13_PAD_FRAGMENT_LENGTH-1)
& ~(+TLS13_PAD_FRAGMENT_LENGTH-1);

/* We must copy input into wrBuf to append the internal trailer */
unsigned char *wrPtr = wrBuf->buf + headerLen + nonceLen;
if (pIn != wrPtr) {
Expand All @@ -2654,7 +2663,9 @@ ssl3_CompressMACEncryptRecord(ssl3CipherSpec * cwSpec,
/* Append the TLS 1.3 internal trailer */
unsigned char *trailer = &wrPtr[contentLen];
contentLen += TLS13_RECORD_TRAILER_LENGTH;
trailer[0] = type; /* inner content type */
trailer[0] = cwSpec->writeNextLen >> 8;
trailer[1] = cwSpec->writeNextLen;
trailer[2] = type; /* inner content type */
PORT_Assert(type != 0); /* must be distinct from padding bytes! */
type = content_application_data; /* fixed outer content type */

Expand Down Expand Up @@ -2779,8 +2790,9 @@ ssl3_CompressMACEncryptRecord(ssl3CipherSpec * cwSpec,
PORT_Assert(cipherBytes <= MAX_FRAGMENT_LENGTH + 1024);

wrBuf->len = cipherBytes + headerLen;
wrBuf->buf[0] = type;
if (isDTLS) {
if (headerLen > 0) {
wrBuf->buf[0] = type;
if (isDTLS) {
SSL3ProtocolVersion version;

version = dtls_TLSVersionToDTLSVersion(cwSpec->version);
Expand All @@ -2796,7 +2808,7 @@ ssl3_CompressMACEncryptRecord(ssl3CipherSpec * cwSpec,
wrBuf->buf[10] = (unsigned char)(cwSpec->write_seq_num.low >> 0);
wrBuf->buf[11] = MSB(cipherBytes);
wrBuf->buf[12] = LSB(cipherBytes);
} else {
} else {
SSL3ProtocolVersion version = cwSpec->version;

if (capRecordVersion) {
Expand All @@ -2806,6 +2818,7 @@ ssl3_CompressMACEncryptRecord(ssl3CipherSpec * cwSpec,
wrBuf->buf[2] = LSB(version);
wrBuf->buf[3] = MSB(cipherBytes);
wrBuf->buf[4] = LSB(cipherBytes);
}
}

ssl3_BumpSequenceNumber(&cwSpec->write_seq_num);
Expand Down Expand Up @@ -12255,7 +12268,8 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf)
/* Decode and strip the internal trailer */
decryptedLen -= TLS13_RECORD_TRAILER_LENGTH;
unsigned char *trailer = &plaintext->buf[decryptedLen];
rType = trailer[0];
rType = trailer[2];
ss->gs.readNextLen = (trailer[0] << 8) | trailer[1];
}
plaintext->len = decryptedLen;

Expand Down Expand Up @@ -12525,6 +12539,8 @@ ssl3_InitCipherSpec(sslSocket *ss, ssl3CipherSpec *spec)
spec->read_seq_num.high = 0;
spec->read_seq_num.low = 0;

spec->writeNextLen = 0;

spec->epoch = 0;
dtls_InitRecvdRecords(&spec->recvdRecords);

Expand Down
15 changes: 13 additions & 2 deletions nss/lib/ssl/ssl3gthr.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,19 @@ ssl3_GatherData(sslSocket *ss, sslGather *gs, int flags)

PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
if (gs->state == GS_INIT) {
gs->state = GS_HEADER;
gs->remainder = 5;
if (gs->readNextLen == 0) {
gs->state = GS_HEADER;
gs->remainder = 5;
} else { /* TLS 1.3: length carried in prior record's trailer */
gs->state = GS_DATA;
gs->remainder = gs->readNextLen;
if (gs->remainder > gs->inbuf.space) {
err = sslBuffer_Grow(&gs->inbuf, gs->remainder);
if (err) { /* realloc has set error code to no mem. */
return err;
}
}
}
gs->offset = 0;
gs->writeOffset = 0;
gs->readOffset = 0;
Expand Down
2 changes: 1 addition & 1 deletion nss/lib/ssl/ssl3prot.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ typedef PRUint16 ssl3CipherSuite;
#define MAX_FRAGMENT_LENGTH 16384 /* max payload per record */

/* TLS 1.3 adds a trailer and optional padding in the AEAD-encrypted payload */
#define TLS13_RECORD_TRAILER_LENGTH 1 /* plus optional padding */
#define TLS13_RECORD_TRAILER_LENGTH 3 /* plus optional padding */
#define TLS13_PAD_FRAGMENT_LENGTH 256 /* padding granularity */

typedef enum {
Expand Down
1 change: 1 addition & 0 deletions nss/lib/ssl/sslgathr.c
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@ ssl_InitGather(sslGather *gs)
gs->state = GS_INIT;
gs->writeOffset = 0;
gs->readOffset = 0;
gs->readNextLen = 0;
gs->dtlsPacketOffset = 0;
gs->dtlsPacket.len = 0;
status = sslBuffer_Grow(&gs->buf, 4096);
Expand Down
4 changes: 4 additions & 0 deletions nss/lib/ssl/sslimpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,9 @@ struct sslGatherStr {
*/
unsigned int recordPadding; /* ssl2 only */

/* TLS 1.3: if nonzero, length of next record carried in prior record */
PRUint32 readNextLen;

/* plaintext DATA begins this many bytes into "buf". */
unsigned int recordOffset; /* ssl2 only */

Expand Down Expand Up @@ -589,6 +592,7 @@ typedef struct {
PK11SymKey * master_secret;
SSL3SequenceNumber write_seq_num;
SSL3SequenceNumber read_seq_num;
PRUint32 writeNextLen; /* TLS 1.3 promised next record len */
SSL3ProtocolVersion version;
ssl3KeyMaterial client;
ssl3KeyMaterial server;
Expand Down