summaryrefslogtreecommitdiff
path: root/security/nss/lib/ssl/tls13con.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/ssl/tls13con.c')
-rw-r--r--security/nss/lib/ssl/tls13con.c415
1 files changed, 245 insertions, 170 deletions
diff --git a/security/nss/lib/ssl/tls13con.c b/security/nss/lib/ssl/tls13con.c
index c3528a52f8..b8f31c3f03 100644
--- a/security/nss/lib/ssl/tls13con.c
+++ b/security/nss/lib/ssl/tls13con.c
@@ -29,24 +29,6 @@
static SECStatus tls13_SetCipherSpec(sslSocket *ss, PRUint16 epoch,
SSLSecretDirection install,
PRBool deleteSecret);
-static SECStatus tls13_AESGCM(const ssl3KeyMaterial *keys,
- PRBool doDecrypt,
- unsigned char *out,
- unsigned int *outlen,
- unsigned int maxout,
- const unsigned char *in,
- unsigned int inlen,
- const unsigned char *additionalData,
- unsigned int additionalDataLen);
-static SECStatus tls13_ChaCha20Poly1305(const ssl3KeyMaterial *keys,
- PRBool doDecrypt,
- unsigned char *out,
- unsigned int *outlen,
- unsigned int maxout,
- const unsigned char *in,
- unsigned int inlen,
- const unsigned char *additionalData,
- unsigned int additionalDataLen);
static SECStatus tls13_SendServerHelloSequence(sslSocket *ss);
static SECStatus tls13_SendEncryptedExtensions(sslSocket *ss);
static void tls13_SetKeyExchangeType(sslSocket *ss, const sslNamedGroupDef *group);
@@ -131,6 +113,7 @@ const char kHkdfLabelExporterMasterSecret[] = "exp master";
const char kHkdfLabelResumption[] = "resumption";
const char kHkdfLabelTrafficUpdate[] = "traffic upd";
const char kHkdfPurposeKey[] = "key";
+const char kHkdfPurposeSn[] = "sn";
const char kHkdfPurposeIv[] = "iv";
const char keylogLabelClientEarlyTrafficSecret[] = "CLIENT_EARLY_TRAFFIC_SECRET";
@@ -286,6 +269,34 @@ tls13_GetHash(const sslSocket *ss)
return ss->ssl3.hs.suite_def->prf_hash;
}
+SECStatus
+tls13_GetHashAndCipher(PRUint16 version, PRUint16 cipherSuite,
+ SSLHashType *hash, const ssl3BulkCipherDef **cipher)
+{
+ if (version < SSL_LIBRARY_VERSION_TLS_1_3) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ // Lookup and check the suite.
+ SSLVersionRange vrange = { version, version };
+ if (!ssl3_CipherSuiteAllowedForVersionRange(cipherSuite, &vrange)) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ const ssl3CipherSuiteDef *suiteDef = ssl_LookupCipherSuiteDef(cipherSuite);
+ const ssl3BulkCipherDef *cipherDef = ssl_GetBulkCipherDef(suiteDef);
+ if (cipherDef->type != type_aead) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ *hash = suiteDef->prf_hash;
+ if (cipher != NULL) {
+ *cipher = cipherDef;
+ }
+ return SECSuccess;
+}
+
unsigned int
tls13_GetHashSizeForHash(SSLHashType hash)
{
@@ -306,26 +317,6 @@ tls13_GetHashSize(const sslSocket *ss)
return tls13_GetHashSizeForHash(tls13_GetHash(ss));
}
-CK_MECHANISM_TYPE
-tls13_GetHkdfMechanismForHash(SSLHashType hash)
-{
- switch (hash) {
- case ssl_hash_sha256:
- return CKM_NSS_HKDF_SHA256;
- case ssl_hash_sha384:
- return CKM_NSS_HKDF_SHA384;
- default:
- PORT_Assert(0);
- }
- return CKM_NSS_HKDF_SHA256;
-}
-
-CK_MECHANISM_TYPE
-tls13_GetHkdfMechanism(sslSocket *ss)
-{
- return tls13_GetHkdfMechanismForHash(tls13_GetHash(ss));
-}
-
static CK_MECHANISM_TYPE
tls13_GetHmacMechanism(sslSocket *ss)
{
@@ -595,7 +586,7 @@ tls13_HandleKeyShare(sslSocket *ss,
key = PK11_PubDeriveWithKDF(
keyPair->privKey, peerKey, PR_FALSE, NULL, NULL, mechanism,
- tls13_GetHkdfMechanismForHash(hash), CKA_DERIVE, keySize, CKD_NULL, NULL, NULL);
+ CKM_HKDF_DERIVE, CKA_DERIVE, keySize, CKD_NULL, NULL, NULL);
if (!key) {
ssl_MapLowLevelError(SSL_ERROR_KEY_EXCHANGE_FAILURE);
goto loser;
@@ -641,6 +632,7 @@ tls13_UpdateTrafficKeys(sslSocket *ss, SSLSecretDirection direction)
strlen(kHkdfLabelTrafficUpdate),
tls13_GetHmacMechanism(ss),
tls13_GetHashSize(ss),
+ ss->protocolVariant,
&updatedSecret);
if (rv != SECSuccess) {
return SECFailure;
@@ -3317,8 +3309,9 @@ tls13_DeriveSecret(sslSocket *ss, PK11SymKey *key,
rv = tls13_HkdfExpandLabel(key, tls13_GetHash(ss),
hashes->u.raw, hashes->len,
label, labelLen,
- tls13_GetHkdfMechanism(ss),
- tls13_GetHashSize(ss), dest);
+ CKM_HKDF_DERIVE,
+ tls13_GetHashSize(ss),
+ ss->protocolVariant, dest);
if (rv != SECSuccess) {
LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
@@ -3467,6 +3460,7 @@ tls13_DeriveTrafficKeys(sslSocket *ss, ssl3CipherSpec *spec,
NULL, 0,
kHkdfPurposeKey, strlen(kHkdfPurposeKey),
bulkAlgorithm, keySize,
+ ss->protocolVariant,
&spec->keyMaterial.key);
if (rv != SECSuccess) {
LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE);
@@ -3474,9 +3468,21 @@ tls13_DeriveTrafficKeys(sslSocket *ss, ssl3CipherSpec *spec,
goto loser;
}
+ if (IS_DTLS(ss) && spec->epoch > 0) {
+ rv = ssl_CreateMaskingContextInner(spec->version, ss->ssl3.hs.cipher_suite,
+ ss->protocolVariant, prk, kHkdfPurposeSn,
+ strlen(kHkdfPurposeSn), &spec->maskContext);
+ if (rv != SECSuccess) {
+ LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE);
+ PORT_Assert(0);
+ goto loser;
+ }
+ }
+
rv = tls13_HkdfExpandLabelRaw(prk, tls13_GetHash(ss),
NULL, 0,
kHkdfPurposeIv, strlen(kHkdfPurposeIv),
+ ss->protocolVariant,
spec->keyMaterial.iv, ivSize);
if (rv != SECSuccess) {
LOG_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE);
@@ -3507,21 +3513,6 @@ tls13_SetSpecRecordVersion(sslSocket *ss, ssl3CipherSpec *spec)
SSL_GETPID(), ss->fd, spec, spec->recordVersion));
}
-SSLAEADCipher
-tls13_GetAead(const ssl3BulkCipherDef *cipherDef)
-{
- switch (cipherDef->calg) {
- case ssl_calg_aes_gcm:
- return tls13_AESGCM;
- case ssl_calg_chacha20:
- return tls13_ChaCha20Poly1305;
- default:
- PORT_Assert(PR_FALSE);
- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
- return NULL;
- }
-}
-
static SECStatus
tls13_SetupPendingCipherSpec(sslSocket *ss, ssl3CipherSpec *spec)
{
@@ -3545,10 +3536,6 @@ tls13_SetupPendingCipherSpec(sslSocket *ss, ssl3CipherSpec *spec)
SSL_GETPID(), ss->fd, suite));
spec->cipherDef = ssl_GetBulkCipherDef(ssl_LookupCipherSuiteDef(suite));
- spec->aead = tls13_GetAead(spec->cipherDef);
- if (!spec->aead) {
- return SECFailure;
- }
if (spec->epoch == TrafficKeyEarlyApplicationData) {
spec->earlyDataRemaining =
@@ -3571,6 +3558,38 @@ tls13_SetupPendingCipherSpec(sslSocket *ss, ssl3CipherSpec *spec)
}
/*
+ * Initialize the cipher context. All TLS 1.3 operations are AEAD,
+ * so they are all message contexts.
+ */
+static SECStatus
+tls13_InitPendingContext(sslSocket *ss, ssl3CipherSpec *spec)
+{
+ CK_MECHANISM_TYPE encMechanism;
+ CK_ATTRIBUTE_TYPE encMode;
+ SECItem iv;
+ SSLCipherAlgorithm calg;
+
+ calg = spec->cipherDef->calg;
+
+ encMechanism = ssl3_Alg2Mech(calg);
+ encMode = CKA_NSS_MESSAGE | ((spec->direction == ssl_secret_write) ? CKA_ENCRYPT : CKA_DECRYPT);
+ iv.data = NULL;
+ iv.len = 0;
+
+ /*
+ * build the context
+ */
+ spec->cipherContext = PK11_CreateContextBySymKey(encMechanism, encMode,
+ spec->keyMaterial.key,
+ &iv);
+ if (!spec->cipherContext) {
+ ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE);
+ return SECFailure;
+ }
+ return SECSuccess;
+}
+
+/*
* Called before sending alerts to set up the right key on the client.
* We might encounter errors during the handshake where the current
* key is ClearText or EarlyApplicationData. This
@@ -3649,6 +3668,11 @@ tls13_SetCipherSpec(sslSocket *ss, PRUint16 epoch,
goto loser;
}
+ rv = tls13_InitPendingContext(ss, spec);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+
/* Now that we've set almost everything up, finally cut over. */
specp = (direction == ssl_secret_read) ? &ss->ssl3.crSpec : &ss->ssl3.cwSpec;
ssl_GetSpecWriteLock(ss);
@@ -3811,100 +3835,113 @@ tls13_DestroyEarlyData(PRCList *list)
* See RFC 5288 and https://tools.ietf.org/html/draft-ietf-tls-chacha20-poly1305-04#section-2
*/
static void
-tls13_WriteNonce(const ssl3KeyMaterial *keys,
- const unsigned char *seqNumBuf, unsigned int seqNumLen,
- unsigned char *nonce, unsigned int nonceLen)
+tls13_WriteNonce(const unsigned char *ivIn, unsigned int ivInLen,
+ const unsigned char *nonce, unsigned int nonceLen,
+ unsigned char *ivOut, unsigned int ivOutLen)
{
size_t i;
+ unsigned int offset = ivOutLen - nonceLen;
- PORT_Assert(nonceLen == 12);
- memcpy(nonce, keys->iv, 12);
+ PORT_Assert(ivInLen <= ivOutLen);
+ PORT_Assert(nonceLen <= ivOutLen);
+ PORT_Memset(ivOut, 0, ivOutLen);
+ PORT_Memcpy(ivOut, ivIn, ivInLen);
- /* XOR the last 8 bytes of the IV with the sequence number. */
- PORT_Assert(seqNumLen == 8);
- for (i = 0; i < 8; ++i) {
- nonce[4 + i] ^= seqNumBuf[i];
+ /* XOR the last n bytes of the IV with the nonce (should be a counter). */
+ for (i = 0; i < nonceLen; ++i) {
+ ivOut[offset + i] ^= nonce[i];
}
- PRINT_BUF(50, (NULL, "Nonce", nonce, nonceLen));
+ PRINT_BUF(50, (NULL, "Nonce", ivOut, ivOutLen));
}
-/* Implement the SSLAEADCipher interface defined in sslimpl.h.
- *
- * That interface takes the additional data (see below) and reinterprets that as
- * a sequence number. In TLS 1.3 there is no additional data so this value is
- * just the encoded sequence number.
+/* Setup the IV for AEAD encrypt. The PKCS #11 module will add the
+ * counter, but it doesn't know about the DTLS epic, so we add it here.
*/
-SECStatus
-tls13_AEAD(const ssl3KeyMaterial *keys, PRBool doDecrypt,
- unsigned char *out, unsigned int *outlen, unsigned int maxout,
- const unsigned char *in, unsigned int inlen,
- CK_MECHANISM_TYPE mechanism,
- unsigned char *aeadParams, unsigned int aeadParamLength)
+unsigned int
+tls13_SetupAeadIv(PRBool isDTLS, unsigned char *ivOut, unsigned char *ivIn,
+ unsigned int offset, unsigned int ivLen, DTLSEpoch epoch)
{
- SECItem param = {
- siBuffer, aeadParams, aeadParamLength
- };
-
- if (doDecrypt) {
- return PK11_Decrypt(keys->key, mechanism, &param,
- out, outlen, maxout, in, inlen);
+ PORT_Memcpy(ivOut, ivIn, ivLen);
+ if (isDTLS) {
+ /* handle the tls 1.2 counter mode case, the epoc is copied
+ * instead of xored. We accomplish this by clearing ivOut
+ * before running xor. */
+ if (offset >= ivLen) {
+ ivOut[offset] = ivOut[offset + 1] = 0;
+ }
+ ivOut[offset] ^= (unsigned char)(epoch >> BPB) & 0xff;
+ ivOut[offset + 1] ^= (unsigned char)(epoch)&0xff;
+ offset += 2;
}
- return PK11_Encrypt(keys->key, mechanism, &param,
- out, outlen, maxout, in, inlen);
+ return offset;
}
-static SECStatus
-tls13_AESGCM(const ssl3KeyMaterial *keys,
- PRBool doDecrypt,
- unsigned char *out,
- unsigned int *outlen,
- unsigned int maxout,
- const unsigned char *in,
- unsigned int inlen,
- const unsigned char *additionalData,
- unsigned int additionalDataLen)
+/*
+ * Do a single AEAD for TLS. This differs from PK11_AEADOp in the following
+ * ways.
+ * 1) If context is not supplied, it treats the operation as a single shot
+ * and creates a context from symKey and mech.
+ * 2) It always assumes the tag will be at the end of the buffer
+ * (in on decrypt, out on encrypt) just like the old single shot.
+ * 3) If we aren't generating an IV, it uses tls13_WriteNonce to create the
+ * nonce.
+ * NOTE is context is supplied, symKey and mech are ignored
+ */
+SECStatus
+tls13_AEAD(PK11Context *context, PRBool decrypt,
+ CK_GENERATOR_FUNCTION ivGen, unsigned int fixedbits,
+ const unsigned char *ivIn, unsigned char *ivOut, unsigned int ivLen,
+ const unsigned char *nonceIn, unsigned int nonceLen,
+ const unsigned char *aad, unsigned int aadLen,
+ unsigned char *out, unsigned int *outLen, unsigned int maxout,
+ unsigned int tagLen, const unsigned char *in, unsigned int inLen)
{
- CK_GCM_PARAMS gcmParams;
- unsigned char nonce[12];
-
- PORT_Assert(additionalDataLen >= 8);
- memset(&gcmParams, 0, sizeof(gcmParams));
- gcmParams.pIv = nonce;
- gcmParams.ulIvLen = sizeof(nonce);
- gcmParams.pAAD = (PRUint8 *)(additionalData + 8);
- gcmParams.ulAADLen = additionalDataLen - 8;
- gcmParams.ulTagBits = 128; /* GCM measures tag length in bits. */
-
- tls13_WriteNonce(keys, additionalData, 8,
- nonce, sizeof(nonce));
- return tls13_AEAD(keys, doDecrypt, out, outlen, maxout, in, inlen,
- CKM_AES_GCM,
- (unsigned char *)&gcmParams, sizeof(gcmParams));
-}
+ unsigned char *tag;
+ unsigned char iv[MAX_IV_LENGTH];
+ unsigned char tagbuf[HASH_LENGTH_MAX];
+ SECStatus rv;
-static SECStatus
-tls13_ChaCha20Poly1305(const ssl3KeyMaterial *keys, PRBool doDecrypt,
- unsigned char *out, unsigned int *outlen, unsigned int maxout,
- const unsigned char *in, unsigned int inlen,
- const unsigned char *additionalData,
- unsigned int additionalDataLen)
-{
- CK_NSS_AEAD_PARAMS aeadParams;
- unsigned char nonce[12];
-
- PORT_Assert(additionalDataLen > 8);
- memset(&aeadParams, 0, sizeof(aeadParams));
- aeadParams.pNonce = nonce;
- aeadParams.ulNonceLen = sizeof(nonce);
- aeadParams.pAAD = (PRUint8 *)(additionalData + 8);
- aeadParams.ulAADLen = additionalDataLen - 8;
- aeadParams.ulTagLen = 16; /* The Poly1305 tag is 16 octets. */
-
- tls13_WriteNonce(keys, additionalData, 8,
- nonce, sizeof(nonce));
- return tls13_AEAD(keys, doDecrypt, out, outlen, maxout, in, inlen,
- CKM_NSS_CHACHA20_POLY1305,
- (unsigned char *)&aeadParams, sizeof(aeadParams));
+ /* must have either context or the symKey set */
+ if (!context) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ PORT_Assert(ivLen <= MAX_IV_LENGTH);
+ PORT_Assert(tagLen <= HASH_LENGTH_MAX);
+ if (!ivOut) {
+ ivOut = iv; /* caller doesn't need a returned, iv */
+ }
+
+ if (ivGen == CKG_NO_GENERATE) {
+ tls13_WriteNonce(ivIn, ivLen, nonceIn, nonceLen, ivOut, ivLen);
+ } else if (ivIn != ivOut) {
+ PORT_Memcpy(ivOut, ivIn, ivLen);
+ }
+ if (decrypt) {
+ inLen = inLen - tagLen;
+ tag = (unsigned char *)in + inLen;
+ /* tag is const on decrypt, but returned on encrypt */
+ } else {
+ /* tag is written to a separate buffer, then added to the end
+ * of the actual output buffer. This allows output buffer to be larger
+ * than the input buffer and everything still work */
+ tag = tagbuf;
+ }
+ rv = PK11_AEADOp(context, ivGen, fixedbits, ivOut, ivLen, aad, aadLen,
+ out, (int *)outLen, maxout, tag, tagLen, in, inLen);
+ /* on encrypt SSL always puts the tag at the end of the buffer */
+ if ((rv == SECSuccess) && !(decrypt)) {
+ unsigned int len = *outLen;
+ /* make sure there is still space */
+ if (len + tagLen > maxout) {
+ PORT_SetError(SEC_ERROR_OUTPUT_LEN);
+ return SECFailure;
+ }
+ PORT_Memcpy(out + len, tag, tagLen);
+ *outLen += tagLen;
+ }
+ return rv;
}
static SECStatus
@@ -4392,7 +4429,8 @@ tls13_ComputeFinished(sslSocket *ss, PK11SymKey *baseKey,
NULL, 0,
label, strlen(label),
tls13_GetHmacMechanism(ss),
- tls13_GetHashSize(ss), &secret);
+ tls13_GetHashSize(ss),
+ ss->protocolVariant, &secret);
if (rv != SECSuccess) {
goto abort;
}
@@ -4929,8 +4967,9 @@ tls13_SendNewSessionTicket(sslSocket *ss, const PRUint8 *appToken,
ticketNonce, sizeof(ticketNonce),
kHkdfLabelResumption,
strlen(kHkdfLabelResumption),
- tls13_GetHkdfMechanism(ss),
- tls13_GetHashSize(ss), &secret);
+ CKM_HKDF_DERIVE,
+ tls13_GetHashSize(ss),
+ ss->protocolVariant, &secret);
if (rv != SECSuccess) {
goto loser;
}
@@ -5163,8 +5202,9 @@ tls13_HandleNewSessionTicket(sslSocket *ss, PRUint8 *b, PRUint32 length)
ticket_nonce.data, ticket_nonce.len,
kHkdfLabelResumption,
strlen(kHkdfLabelResumption),
- tls13_GetHkdfMechanism(ss),
- tls13_GetHashSize(ss), &secret);
+ CKM_HKDF_DERIVE,
+ tls13_GetHashSize(ss),
+ ss->protocolVariant, &secret);
if (rv != SECSuccess) {
return SECFailure;
}
@@ -5348,11 +5388,20 @@ tls13_ProtectRecord(sslSocket *ss,
sslBuffer buf = SSL_BUFFER_FIXED(hdr, sizeof(hdr));
PRBool needsLength;
PRUint8 aad[21];
+ const int ivLen = cipher_def->iv_size + cipher_def->explicit_nonce_size;
+ unsigned int ivOffset = ivLen - sizeof(sslSequenceNumber);
+ unsigned char ivOut[MAX_IV_LENGTH];
+
unsigned int aadLen;
unsigned int len;
PORT_Assert(cipher_def->type == type_aead);
+ /* If the following condition holds, we can skip the padding logic for
+ * DTLS 1.3 (4.2.3). This will be the case until we support a cipher
+ * with tag length < 15B. */
+ PORT_Assert(tagLen + 1 /* cType */ >= 16);
+
/* Add the content type at the end. */
*(SSL_BUFFER_NEXT(wrBuf) + contentLen) = type;
@@ -5363,9 +5412,7 @@ tls13_ProtectRecord(sslSocket *ss,
return SECFailure;
}
if (needsLength) {
- rv = sslBuffer_AppendNumber(&buf, contentLen + 1 +
- cwSpec->cipherDef->tag_size,
- 2);
+ rv = sslBuffer_AppendNumber(&buf, contentLen + 1 + tagLen, 2);
if (rv != SECSuccess) {
return SECFailure;
}
@@ -5376,14 +5423,22 @@ tls13_ProtectRecord(sslSocket *ss,
if (rv != SECSuccess) {
return SECFailure;
}
- rv = cwSpec->aead(&cwSpec->keyMaterial,
- PR_FALSE, /* do encrypt */
- SSL_BUFFER_NEXT(wrBuf), /* output */
- &len, /* out len */
- SSL_BUFFER_SPACE(wrBuf), /* max out */
- SSL_BUFFER_NEXT(wrBuf), /* input */
- contentLen + 1, /* input len */
- aad, aadLen);
+ /* set up initial IV value */
+ ivOffset = tls13_SetupAeadIv(IS_DTLS(ss), ivOut, cwSpec->keyMaterial.iv,
+ ivOffset, ivLen, cwSpec->epoch);
+
+ rv = tls13_AEAD(cwSpec->cipherContext, PR_FALSE,
+ CKG_GENERATE_COUNTER_XOR, ivOffset * BPB,
+ ivOut, ivOut, ivLen, /* iv */
+ NULL, 0, /* nonce */
+ aad + sizeof(sslSequenceNumber), /* aad */
+ aadLen - sizeof(sslSequenceNumber),
+ SSL_BUFFER_NEXT(wrBuf), /* output */
+ &len, /* out len */
+ SSL_BUFFER_SPACE(wrBuf), /* max out */
+ tagLen,
+ SSL_BUFFER_NEXT(wrBuf), /* input */
+ contentLen + 1); /* input len */
if (rv != SECSuccess) {
PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
return SECFailure;
@@ -5413,6 +5468,9 @@ tls13_UnprotectRecord(sslSocket *ss,
SSL3AlertDescription *alert)
{
const ssl3BulkCipherDef *cipher_def = spec->cipherDef;
+ const int ivLen = cipher_def->iv_size + cipher_def->explicit_nonce_size;
+ const int tagLen = cipher_def->tag_size;
+
PRUint8 aad[21];
unsigned int aadLen;
SECStatus rv;
@@ -5440,7 +5498,7 @@ tls13_UnprotectRecord(sslSocket *ss,
/* We can perform this test in variable time because the record's total
* length and the ciphersuite are both public knowledge. */
- if (cText->buf->len < cipher_def->tag_size) {
+ if (cText->buf->len < tagLen) {
SSL_TRC(3,
("%d: TLS13[%d]: record too short to contain valid AEAD data",
SSL_GETPID(), ss->fd));
@@ -5467,16 +5525,21 @@ tls13_UnprotectRecord(sslSocket *ss,
spec->epoch, cText->seqNum,
aad, &aadLen, sizeof(aad));
if (rv != SECSuccess) {
+
return SECFailure;
}
- rv = spec->aead(&spec->keyMaterial,
- PR_TRUE, /* do decrypt */
- plaintext->buf, /* out */
+ rv = tls13_AEAD(spec->cipherContext, PR_TRUE,
+ CKG_NO_GENERATE, 0, /* ignored for decrypt */
+ spec->keyMaterial.iv, NULL, ivLen, /* iv */
+ aad, sizeof(sslSequenceNumber), /* nonce */
+ aad + sizeof(sslSequenceNumber), /* aad */
+ aadLen - sizeof(sslSequenceNumber),
+ plaintext->buf, /* output */
&plaintext->len, /* outlen */
plaintext->space, /* maxout */
+ tagLen,
cText->buf->buf, /* in */
- cText->buf->len, /* inlen */
- aad, aadLen);
+ cText->buf->len); /* inlen */
if (rv != SECSuccess) {
SSL_TRC(3,
("%d: TLS13[%d]: record has bogus MAC",
@@ -5763,14 +5826,26 @@ tls13_HandleEarlyApplicationData(sslSocket *ss, sslBuffer *origBuf)
}
PRUint16
-tls13_EncodeDraftVersion(SSL3ProtocolVersion version, SSLProtocolVariant variant)
+tls13_EncodeVersion(SSL3ProtocolVersion version, SSLProtocolVariant variant)
{
+ if (variant == ssl_variant_datagram) {
+ /* TODO: When DTLS 1.3 is out of draft, replace this with
+ * dtls_TLSVersionToDTLSVersion(). */
+ switch (version) {
#ifdef DTLS_1_3_DRAFT_VERSION
- if (version == SSL_LIBRARY_VERSION_TLS_1_3 &&
- variant == ssl_variant_datagram) {
- return 0x7f00 | DTLS_1_3_DRAFT_VERSION;
- }
+ case SSL_LIBRARY_VERSION_TLS_1_3:
+ return 0x7f00 | DTLS_1_3_DRAFT_VERSION;
#endif
+ case SSL_LIBRARY_VERSION_TLS_1_2:
+ return SSL_LIBRARY_VERSION_DTLS_1_2_WIRE;
+ case SSL_LIBRARY_VERSION_TLS_1_1:
+ /* TLS_1_1 maps to DTLS_1_0, see sslproto.h. */
+ return SSL_LIBRARY_VERSION_DTLS_1_0_WIRE;
+ default:
+ PORT_Assert(0);
+ }
+ }
+ /* Stream-variant encodings do not change. */
return (PRUint16)version;
}
@@ -5800,8 +5875,8 @@ tls13_ClientReadSupportedVersion(sslSocket *ss)
return SECFailure;
}
- if (temp != tls13_EncodeDraftVersion(SSL_LIBRARY_VERSION_TLS_1_3,
- ss->protocolVariant)) {
+ if (temp != tls13_EncodeVersion(SSL_LIBRARY_VERSION_TLS_1_3,
+ ss->protocolVariant)) {
/* You cannot negotiate < TLS 1.3 with supported_versions. */
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_SERVER_HELLO, illegal_parameter);
return SECFailure;
@@ -5840,7 +5915,7 @@ tls13_NegotiateVersion(sslSocket *ss, const TLSExtension *supportedVersions)
return SECFailure;
}
- PRUint16 wire = tls13_EncodeDraftVersion(version, ss->protocolVariant);
+ PRUint16 wire = tls13_EncodeVersion(version, ss->protocolVariant);
unsigned long offset;
for (offset = 0; offset < versions.len; offset += 2) {