1230 lines
30 KiB
C
1230 lines
30 KiB
C
/**
|
|
* @file tls13.c
|
|
* @version $Format:%h%d$
|
|
*
|
|
* TLS 1.3 secret and key derivation.
|
|
*/
|
|
/*
|
|
* Copyright (c) 2018 Rambus Inc.
|
|
* Copyright (c) PeerSec Networks, 2002-2011
|
|
* All Rights Reserved
|
|
*
|
|
* The latest version of this code is available at http://www.matrixssl.org
|
|
*
|
|
* This software is open source; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This General Public License does NOT permit incorporating this software
|
|
* into proprietary programs. If you are unable to comply with the GPL, a
|
|
* commercial license for this software may be purchased from Rambus at
|
|
* http://www.rambus.com/
|
|
*
|
|
* This program is distributed in WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
* See the GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
* http://www.gnu.org/copyleft/gpl.html
|
|
*/
|
|
|
|
#include "matrixsslImpl.h"
|
|
|
|
#ifdef USE_TLS_1_3
|
|
|
|
static const char *derivedLabel = "derived";
|
|
static psSize_t derivedLabelLen = 7;
|
|
static const char *extBinderLabel = "ext binder";
|
|
static psSize_t extBinderLabelLen = 10;
|
|
static const char *resBinderLabel = "res binder";
|
|
static psSize_t resBinderLabelLen = 10;
|
|
static const char *cEarlyTrafficLabel = "c e traffic";
|
|
static psSize_t earlyTrafficLabelLen = 11;
|
|
static const char *cHsTrafficLabel = "c hs traffic";
|
|
static const char *sHsTrafficLabel = "s hs traffic";
|
|
static const char *finishedLabel = "finished";
|
|
static psSize_t finishedLabelLen = 8;
|
|
static const char *cApTrafficLabel = "c ap traffic";
|
|
static const char *sApTrafficLabel = "s ap traffic";
|
|
static psSize_t trafficLabelLen = 12;
|
|
static const char *resLabel = "res master";
|
|
static psSize_t resLabelLen = 10;
|
|
|
|
# ifndef DEBUG_TLS_1_3_KEY_DERIVE
|
|
/* # define DEBUG_TLS_1_3_KEY_DERIVE */
|
|
# endif
|
|
|
|
/* Secrets SHOULD be cleared after final use. The following define can
|
|
be used to keep them around longer for debugging purposes. */
|
|
# ifndef DEBUG_TLS_1_3_KEEP_SECRETS
|
|
/* # define DEBUG_TLS_1_3_KEEP_SECRETS */
|
|
#endif
|
|
|
|
static unsigned char sha256OfEmptyInput[] =
|
|
{
|
|
0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8,
|
|
0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
|
|
0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55
|
|
};
|
|
static unsigned char sha384OfEmptyInput[] =
|
|
{
|
|
0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38, 0x4c, 0xd9, 0x32, 0x7e,
|
|
0xb1, 0xb1, 0xe3, 0x6a, 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43,
|
|
0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda, 0x27, 0x4e, 0xde, 0xbf,
|
|
0xe7, 0x6f, 0x65, 0xfb, 0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b
|
|
};
|
|
static unsigned char sm3OfEmptyInput[] =
|
|
{
|
|
0x1a, 0xb2, 0x1d, 0x83, 0x55, 0xcf, 0xa1, 0x7f, 0x8e, 0x61, 0x19, 0x48,
|
|
0x31, 0xe8, 0x1a, 0x8f, 0x22, 0xbe, 0xc8, 0xc7, 0x28, 0xfe, 0xfb, 0x74,
|
|
0x7e, 0xd0, 0x35, 0xeb, 0x50, 0x82, 0xaa, 0x2b
|
|
};
|
|
|
|
static inline
|
|
void tls13ClearSecret(unsigned char *secret,
|
|
psSize_t secretLen)
|
|
{
|
|
# ifndef DEBUG_TLS_1_3_KEEP_SECRETS
|
|
Memset(secret, 0, secretLen);
|
|
# else
|
|
(void)secret;
|
|
(void)secretLen;
|
|
# endif
|
|
}
|
|
|
|
/* Derive-Secret(Secret, Label, Transcript-Hash(Messages)) */
|
|
int32_t tls13DeriveSecret(ssl_t *ssl,
|
|
int32_t hmacAlg,
|
|
const unsigned char *inSecret,
|
|
psSize_t inSecretLen,
|
|
const char *label,
|
|
psSize_t labelLen,
|
|
const unsigned char *trHash,
|
|
psSize_t trHashLen,
|
|
unsigned char outSecret[MAX_TLS_1_3_HASH_SIZE])
|
|
{
|
|
int32_t rc;
|
|
int32_t outLen = psGetOutputBlockLength(hmacAlg);
|
|
const unsigned char *pHash = trHash;
|
|
|
|
#ifdef DEBUG_TLS_1_3_KEY_DERIVE
|
|
psTraceBytes("inSecret", inSecret, inSecretLen);
|
|
psTraceBytes("label", (unsigned char*)label, labelLen);
|
|
psTraceBytes("context", trHash, trHashLen);
|
|
#endif
|
|
|
|
if (outLen < 0)
|
|
{ /* error code. */
|
|
return outLen;
|
|
}
|
|
if (trHashLen == 0)
|
|
{
|
|
/* Hash of no messages. */
|
|
if (hmacAlg == HMAC_SHA256)
|
|
{
|
|
pHash = sha256OfEmptyInput;
|
|
trHashLen = 32;
|
|
}
|
|
else if (hmacAlg == HMAC_SHA384)
|
|
{
|
|
pHash = sha384OfEmptyInput;
|
|
trHashLen = 48;
|
|
}
|
|
else if (hmacAlg == HMAC_SM3)
|
|
{
|
|
pHash = sm3OfEmptyInput;
|
|
trHashLen = 32;
|
|
}
|
|
}
|
|
|
|
rc = psHkdfExpandLabel(ssl->hsPool,
|
|
hmacAlg,
|
|
inSecret,
|
|
inSecretLen,
|
|
label,
|
|
labelLen,
|
|
pHash,
|
|
trHashLen,
|
|
outLen,
|
|
outSecret);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
|
|
return PS_SUCCESS;
|
|
}
|
|
|
|
int32_t tls13GenerateEarlySecret(ssl_t *ssl,
|
|
psTls13Psk_t *psk)
|
|
{
|
|
unsigned char dummyPsk[MAX_TLS_1_3_HASH_SIZE] = {0};
|
|
unsigned char zeroSalt[MAX_TLS_1_3_HASH_SIZE] = {0};
|
|
unsigned char *pskVal;
|
|
psSize_t pskValLen;
|
|
int32_t hmacAlg;
|
|
psResSize_t hashLen;
|
|
unsigned char *earlySecretBuf;
|
|
psSize_t earlySecretLen;
|
|
int32_t rc;
|
|
|
|
/*
|
|
Do not regenerate the secret if we are in the middle of flight
|
|
re-encoding after output buffer resizing. However, we do need to
|
|
regenerate if we tried to use a PSK (and thus bootstrapped
|
|
our key schedule with it), but ended up not with a non-PSK
|
|
handshake.
|
|
*/
|
|
if (ssl->sec.tls13KsState.generateEarlySecretDone)
|
|
{
|
|
if (!ssl->sec.tls13DidEncodePsk || ssl->sec.tls13UsingPsk)
|
|
{
|
|
return PS_SUCCESS;
|
|
}
|
|
}
|
|
|
|
/*
|
|
HKDF-Extract(PSK, 0..0) == Early Secret
|
|
*/
|
|
if (psk != NULL)
|
|
{
|
|
pskVal = psk->pskKey;
|
|
pskValLen = psk->pskLen;
|
|
hmacAlg = tls13GetPskHmacAlg(psk);
|
|
hashLen = tls13GetPskHashLen(psk);
|
|
}
|
|
else
|
|
{
|
|
/* When no PSK is used, PSK = 0..0. */
|
|
pskVal = dummyPsk;
|
|
hmacAlg = tls13GetCipherHmacAlg(ssl);
|
|
hashLen = tls13GetCipherHashSize(ssl);
|
|
pskValLen = hashLen;
|
|
}
|
|
if (hashLen < 0)
|
|
{ /* hashLen is error code */
|
|
return hashLen;
|
|
}
|
|
earlySecretLen = hashLen;
|
|
earlySecretBuf = ssl->sec.tls13EarlySecret;
|
|
if (hashLen == 48)
|
|
{
|
|
earlySecretBuf = ssl->sec.tls13EarlySecretSha384;
|
|
}
|
|
|
|
rc = psHkdfExtract(hmacAlg,
|
|
zeroSalt,
|
|
hashLen,
|
|
pskVal,
|
|
pskValLen,
|
|
earlySecretBuf,
|
|
&earlySecretLen);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
psAssert(earlySecretLen == hashLen);
|
|
|
|
#ifdef DEBUG_TLS_1_3_KEY_DERIVE
|
|
psTraceBytes("Early Secret", earlySecretBuf, hashLen);
|
|
#endif
|
|
|
|
ssl->sec.tls13KsState.generateEarlySecretDone = 1;
|
|
return PS_SUCCESS;
|
|
}
|
|
|
|
/* Derive the first part of the key schedule: the Early Secret
|
|
and the secrets immediately dependent on it. */
|
|
int32_t tls13DeriveEarlySecrets(ssl_t *ssl,
|
|
psTls13Psk_t *psk)
|
|
{
|
|
psSize_t secretLen, hashLen;
|
|
unsigned char *earlySecret;
|
|
unsigned char zeroByte = 0;
|
|
int32_t hmacAlg, rc;
|
|
const char *label;
|
|
psSize_t labelLen;
|
|
|
|
rc = tls13GenerateEarlySecret(ssl, psk);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
|
|
if (psk)
|
|
{
|
|
hmacAlg = tls13GetPskHmacAlg(psk);
|
|
hashLen = tls13GetPskHashLen(psk);
|
|
secretLen = hashLen;
|
|
|
|
if (psk->isResumptionPsk)
|
|
{
|
|
label = resBinderLabel;
|
|
labelLen = resBinderLabelLen;
|
|
}
|
|
else
|
|
{
|
|
label = extBinderLabel;
|
|
labelLen = extBinderLabelLen;
|
|
}
|
|
|
|
earlySecret = ssl->sec.tls13EarlySecret;
|
|
if (hashLen == 48)
|
|
{
|
|
earlySecret = ssl->sec.tls13EarlySecretSha384;
|
|
}
|
|
|
|
/* Derive-Secret(Early Secret, "ext|res_binder", "") */
|
|
rc = tls13DeriveSecret(ssl,
|
|
hmacAlg,
|
|
earlySecret,
|
|
secretLen,
|
|
label,
|
|
labelLen,
|
|
&zeroByte,
|
|
0,
|
|
ssl->sec.tls13ExtBinderSecret);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
return PS_SUCCESS;
|
|
}
|
|
|
|
int32_t tls13DeriveHandshakeTrafficSecrets(ssl_t *ssl)
|
|
{
|
|
unsigned char derivedSecret[MAX_TLS_1_3_HASH_SIZE];
|
|
unsigned char *earlySecret;
|
|
unsigned char *sharedSecret;
|
|
int32_t hmacAlg = tls13GetCipherHmacAlg(ssl);
|
|
psResSize_t secretLen = psGetOutputBlockLength(hmacAlg);
|
|
psSize_t sharedSecretLen;
|
|
psSize_t hsSecretLen;
|
|
unsigned char zeroByte = 0;
|
|
int32_t rc;
|
|
|
|
if (ssl->sec.tls13KsState.deriveHandshakeTrafficSecretsDone)
|
|
{
|
|
/* Already generated. Re-entry? */
|
|
return PS_SUCCESS;
|
|
}
|
|
|
|
if (secretLen < 0)
|
|
{
|
|
/* This is an error code */
|
|
return secretLen;
|
|
}
|
|
rc = tls13DeriveEarlySecrets(ssl,
|
|
ssl->sec.tls13ChosenPsk);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
|
|
earlySecret = ssl->sec.tls13EarlySecret;
|
|
if (secretLen == 48)
|
|
{
|
|
earlySecret = ssl->sec.tls13EarlySecretSha384;
|
|
}
|
|
|
|
/* Derive-Secret(Early Secret, "derived", "") */
|
|
rc = tls13DeriveSecret(ssl,
|
|
hmacAlg,
|
|
earlySecret,
|
|
secretLen,
|
|
derivedLabel,
|
|
derivedLabelLen,
|
|
&zeroByte,
|
|
0,
|
|
derivedSecret);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
tls13ClearSecret(ssl->sec.tls13EarlySecret, secretLen);
|
|
tls13ClearSecret(ssl->sec.tls13EarlySecretSha384, secretLen);
|
|
|
|
#ifdef DEBUG_TLS_1_3_KEY_DERIVE
|
|
psTraceBytes("\"derived\" secret", derivedSecret, secretLen);
|
|
#endif
|
|
|
|
if (ssl->sec.tls13ChosenPskMode == psk_keyex_mode_psk_ke)
|
|
{
|
|
/* psk_ke uses a dummy all-zero shared secret. */
|
|
sharedSecret = psMalloc(ssl->hsPool, secretLen);
|
|
Memset(sharedSecret, 0, secretLen);
|
|
sharedSecretLen = secretLen;
|
|
}
|
|
else
|
|
{
|
|
rc = tls13GenSharedSecret(ssl, &sharedSecret, &sharedSecretLen);
|
|
if (rc < 0)
|
|
{
|
|
ssl->err = SSL_ALERT_INTERNAL_ERROR;
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
/* HKDF-Extract(ECDHE, derivedSecret) == Handshake Secret */
|
|
rc = psHkdfExtract(hmacAlg,
|
|
derivedSecret,
|
|
secretLen,
|
|
sharedSecret,
|
|
sharedSecretLen,
|
|
ssl->sec.tls13HandshakeSecret,
|
|
&hsSecretLen);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
psAssert(hsSecretLen == secretLen);
|
|
tls13ClearSecret(sharedSecret, sharedSecretLen);
|
|
psFree(sharedSecret, ssl->hsPool);
|
|
tls13ClearSecret(derivedSecret, secretLen);
|
|
|
|
#ifdef DEBUG_TLS_1_3_KEY_DERIVE
|
|
psTraceBytes("Handshake Secret",
|
|
ssl->sec.tls13HandshakeSecret, secretLen);
|
|
#endif
|
|
|
|
/* DeriveSecret(Handshake Secret, "c hs traffic",
|
|
Transcript-Hash(ClientHello..ServerHello) ) */
|
|
rc = tls13DeriveSecret(ssl,
|
|
hmacAlg,
|
|
ssl->sec.tls13HandshakeSecret,
|
|
secretLen,
|
|
cHsTrafficLabel,
|
|
trafficLabelLen,
|
|
ssl->sec.tls13TrHashSnapshotCHtoSH,
|
|
secretLen,
|
|
ssl->sec.tls13HsTrafficSecretClient);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
#ifdef DEBUG_TLS_1_3_KEY_DERIVE
|
|
psTraceBytes("client_handshake_traffic_secret",
|
|
ssl->sec.tls13HsTrafficSecretClient, secretLen);
|
|
#endif
|
|
|
|
/* DeriveSecret(Handshake Secret, "s hs traffic",
|
|
Transcript-Hash(ClientHello..ServerHello) ) */
|
|
rc = tls13DeriveSecret(ssl,
|
|
hmacAlg,
|
|
ssl->sec.tls13HandshakeSecret,
|
|
secretLen,
|
|
sHsTrafficLabel,
|
|
trafficLabelLen,
|
|
ssl->sec.tls13TrHashSnapshotCHtoSH,
|
|
secretLen,
|
|
ssl->sec.tls13HsTrafficSecretServer);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
#ifdef DEBUG_TLS_1_3_KEY_DERIVE
|
|
psTraceBytes("server_handshake_traffic_secret",
|
|
ssl->sec.tls13HsTrafficSecretServer, secretLen);
|
|
#endif
|
|
|
|
ssl->sec.tls13KsState.deriveHandshakeTrafficSecretsDone = 1;
|
|
return PS_SUCCESS;
|
|
}
|
|
|
|
int32_t tls13DeriveAppTrafficSecrets(ssl_t *ssl)
|
|
{
|
|
unsigned char derivedSecret[MAX_TLS_1_3_HASH_SIZE];
|
|
unsigned char zeroKey[MAX_TLS_1_3_HASH_SIZE] = {0};
|
|
int32_t hmacAlg = tls13GetCipherHmacAlg(ssl);
|
|
psSize_t secretLen;
|
|
psSize_t hsSecretLen;
|
|
unsigned char zeroByte = 0;
|
|
int32_t rc = psGetOutputBlockLength(hmacAlg);
|
|
|
|
if (ssl->sec.tls13KsState.deriveAppTrafficSecretsDone)
|
|
{
|
|
return PS_SUCCESS;
|
|
}
|
|
|
|
if (rc < 0)
|
|
{ /* this is an error code */
|
|
return rc;
|
|
}
|
|
secretLen = rc;
|
|
|
|
/* Derive-Secret(Handshake Secret, "derived", "") */
|
|
rc = tls13DeriveSecret(ssl,
|
|
hmacAlg,
|
|
ssl->sec.tls13HandshakeSecret,
|
|
secretLen,
|
|
derivedLabel,
|
|
derivedLabelLen,
|
|
&zeroByte,
|
|
0,
|
|
derivedSecret);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
tls13ClearSecret(ssl->sec.tls13HandshakeSecret, secretLen);
|
|
|
|
#ifdef DEBUG_TLS_1_3_KEY_DERIVE
|
|
psTraceBytes("\"derived\" secret", derivedSecret, secretLen);
|
|
#endif
|
|
|
|
/* HKDF-Extract(0..0, derivedSecret) == Master Secret */
|
|
rc = psHkdfExtract(hmacAlg,
|
|
derivedSecret,
|
|
secretLen,
|
|
zeroKey,
|
|
secretLen,
|
|
ssl->sec.tls13MasterSecret,
|
|
&hsSecretLen);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
|
|
#ifdef DEBUG_TLS_1_3_KEY_DERIVE
|
|
psTraceBytes("Master Secret", ssl->sec.tls13MasterSecret, secretLen);
|
|
#endif
|
|
|
|
#ifdef ENABLE_MASTER_SECRET_EXPORT
|
|
psAssert(secretLen <= SSL_HS_MASTER_SIZE);
|
|
memcpy(ssl->masterSecret, ssl->sec.tls13MasterSecret, secretLen);
|
|
ssl->hsMasterSecretLen = secretLen;
|
|
#endif /* ENABLE_MASTER_SECRET_EXPORT */
|
|
|
|
psAssert(hsSecretLen == secretLen);
|
|
tls13ClearSecret(derivedSecret, secretLen);
|
|
|
|
#ifdef DEBUG_TLS_1_3_KEY_DERIVE
|
|
psTraceBytes("HS hash", ssl->sec.tls13TrHashSnapshot, secretLen);
|
|
#endif
|
|
|
|
/* DeriveSecret(Master Secret, "c ap traffic",
|
|
Transcript-Hash(ClientHello..Server Finished) ) */
|
|
rc = tls13DeriveSecret(ssl,
|
|
hmacAlg,
|
|
ssl->sec.tls13MasterSecret,
|
|
secretLen,
|
|
cApTrafficLabel,
|
|
trafficLabelLen,
|
|
ssl->sec.tls13TrHashSnapshot,
|
|
secretLen,
|
|
ssl->sec.tls13AppTrafficSecretClient);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
|
|
#ifdef DEBUG_TLS_1_3_KEY_DERIVE
|
|
psTraceBytes("client_application_data_secret_0",
|
|
ssl->sec.tls13AppTrafficSecretClient, secretLen);
|
|
#endif
|
|
|
|
/* DeriveSecret(Master Secret, "s ap traffic",
|
|
Transcript-Hash(ClientHello..Server Finished) ) */
|
|
rc = tls13DeriveSecret(ssl,
|
|
hmacAlg,
|
|
ssl->sec.tls13MasterSecret,
|
|
secretLen,
|
|
sApTrafficLabel,
|
|
trafficLabelLen,
|
|
ssl->sec.tls13TrHashSnapshot,
|
|
secretLen,
|
|
ssl->sec.tls13AppTrafficSecretServer);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
|
|
#ifdef DEBUG_TLS_1_3_KEY_DERIVE
|
|
psTraceBytes("server_application_data_secret_0",
|
|
ssl->sec.tls13AppTrafficSecretServer, secretLen);
|
|
#endif
|
|
|
|
|
|
|
|
ssl->sec.tls13KsState.deriveAppTrafficSecretsDone = 1;
|
|
return PS_SUCCESS;
|
|
}
|
|
|
|
int32_t tls13DeriveResumptionMasterSecret(ssl_t *ssl)
|
|
{
|
|
int32_t hmacAlg = tls13GetCipherHmacAlg(ssl);
|
|
psSize_t secretLen;
|
|
int32_t rc = psGetOutputBlockLength(hmacAlg);
|
|
|
|
if (rc < 0)
|
|
{ /* this is an error code */
|
|
return rc;
|
|
}
|
|
secretLen = rc;
|
|
|
|
/* Derive-Secret(Master Secret, "res master",
|
|
Transcript-Hash(ClientHello...client Finished) ) */
|
|
rc = tls13DeriveSecret(ssl,
|
|
hmacAlg,
|
|
ssl->sec.tls13MasterSecret,
|
|
secretLen,
|
|
resLabel,
|
|
resLabelLen,
|
|
ssl->sec.tls13TrHashSnapshot,
|
|
secretLen,
|
|
ssl->sec.tls13ResumptionMasterSecret);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
|
|
return PS_SUCCESS;
|
|
}
|
|
|
|
int32_t tls13DeriveHandshakeKeys(ssl_t *ssl)
|
|
{
|
|
int32_t hmacAlg = tls13GetCipherHmacAlg(ssl);
|
|
int32_t rc = psGetOutputBlockLength(hmacAlg);
|
|
psSize_t secretLen;
|
|
psBool_t isServer = (ssl->flags & SSL_FLAGS_SERVER) ? PS_TRUE : PS_FALSE;
|
|
unsigned char *inputSecretRead, *inputSecretWrite;
|
|
|
|
if (ssl->sec.tls13KsState.deriveHandshakeKeysDone)
|
|
{
|
|
return PS_SUCCESS;
|
|
}
|
|
|
|
if (rc < 0)
|
|
{ /* this is an error code */
|
|
return rc;
|
|
}
|
|
secretLen = rc;
|
|
|
|
if (isServer)
|
|
{
|
|
inputSecretRead = ssl->sec.tls13HsTrafficSecretClient;
|
|
inputSecretWrite = ssl->sec.tls13HsTrafficSecretServer;
|
|
}
|
|
else
|
|
{
|
|
inputSecretRead = ssl->sec.tls13HsTrafficSecretServer;
|
|
inputSecretWrite = ssl->sec.tls13HsTrafficSecretClient;
|
|
}
|
|
|
|
/* Read keys. */
|
|
|
|
rc = psHkdfExpandLabel(ssl->hsPool,
|
|
hmacAlg,
|
|
inputSecretRead,
|
|
secretLen,
|
|
"key",
|
|
3,
|
|
NULL,
|
|
0,
|
|
ssl->cipher->keySize,
|
|
ssl->sec.tls13HsReadKey);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
#ifdef DEBUG_TLS_1_3_KEY_DERIVE
|
|
psTraceBytes("tls13HsReadKey",
|
|
ssl->sec.tls13HsReadKey, ssl->cipher->keySize);
|
|
#endif
|
|
|
|
rc = psHkdfExpandLabel(ssl->hsPool,
|
|
hmacAlg,
|
|
inputSecretRead,
|
|
secretLen,
|
|
"iv",
|
|
2,
|
|
NULL,
|
|
0,
|
|
ssl->cipher->ivSize,
|
|
ssl->sec.tls13HsReadIv);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
#ifdef DEBUG_TLS_1_3_KEY_DERIVE
|
|
psTraceBytes("tls13HsReadIv",
|
|
ssl->sec.tls13HsReadIv, ssl->cipher->ivSize);
|
|
psTraceBytes("inputSecretWrite", inputSecretWrite, secretLen);
|
|
#endif
|
|
|
|
/* Write keys. */
|
|
|
|
rc = psHkdfExpandLabel(ssl->hsPool,
|
|
hmacAlg,
|
|
inputSecretWrite,
|
|
secretLen,
|
|
"key",
|
|
3,
|
|
NULL,
|
|
0,
|
|
ssl->cipher->keySize,
|
|
ssl->sec.tls13HsWriteKey);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
|
|
#ifdef DEBUG_TLS_1_3_KEY_DERIVE
|
|
psTraceBytes("tls13HsWriteKey",
|
|
ssl->sec.tls13HsWriteKey, ssl->cipher->keySize);
|
|
#endif
|
|
|
|
rc = psHkdfExpandLabel(ssl->hsPool,
|
|
hmacAlg,
|
|
inputSecretWrite,
|
|
secretLen,
|
|
"iv",
|
|
2,
|
|
NULL,
|
|
0,
|
|
ssl->cipher->ivSize,
|
|
ssl->sec.tls13HsWriteIv);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
|
|
#ifdef DEBUG_TLS_1_3_KEY_DERIVE
|
|
psTraceBytes("tls13HsWriteIv",
|
|
ssl->sec.tls13HsWriteIv, ssl->cipher->ivSize);
|
|
#endif
|
|
|
|
ssl->sec.tls13KsState.deriveHandshakeKeysDone = 1;
|
|
return PS_SUCCESS;
|
|
}
|
|
|
|
int32_t tls13DeriveEarlyDataSecret(ssl_t *ssl, psTls13Psk_t *psk)
|
|
{
|
|
int32_t hmacAlg;
|
|
unsigned char *earlySecret;
|
|
unsigned char *trHash;
|
|
psSize_t secretLen;
|
|
int32_t rc;
|
|
|
|
/* A PSK is required for early data. */
|
|
if (psk == NULL)
|
|
{
|
|
return PS_SUCCESS;
|
|
}
|
|
|
|
rc = tls13GenerateEarlySecret(ssl, psk);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
|
|
hmacAlg = tls13GetPskHmacAlg(psk);
|
|
secretLen = tls13GetPskHashLen(psk);
|
|
|
|
earlySecret = ssl->sec.tls13EarlySecret;
|
|
|
|
if (hmacAlg == HMAC_SHA256)
|
|
{
|
|
trHash = ssl->sec.tls13TrHashSnapshotCH;
|
|
}
|
|
else
|
|
{
|
|
trHash = ssl->sec.tls13TrHashSnapshotCHSha384;
|
|
earlySecret = ssl->sec.tls13EarlySecretSha384;
|
|
}
|
|
|
|
# ifdef DEBUG_TLS_1_3_KEY_DERIVE
|
|
psTraceBytes("ED snapshot CH", trHash, secretLen);
|
|
psTraceIntInfo("ED hmac alg: %d\n", hmacAlg);
|
|
# endif
|
|
|
|
/* Derive-Secret(Early Secret, "c e traffic", "") */
|
|
rc = tls13DeriveSecret(ssl,
|
|
hmacAlg,
|
|
earlySecret,
|
|
secretLen,
|
|
cEarlyTrafficLabel,
|
|
earlyTrafficLabelLen,
|
|
trHash,
|
|
secretLen,
|
|
ssl->sec.tls13EarlyTrafficSecretClient);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
# ifdef DEBUG_TLS_1_3_KEY_DERIVE
|
|
psTraceBytes("tls13EarlyTrafficSecretClient",
|
|
ssl->sec.tls13EarlyTrafficSecretClient, secretLen);
|
|
# endif
|
|
return PS_SUCCESS;
|
|
}
|
|
|
|
|
|
int32_t tls13DeriveEarlyDataKeys(ssl_t *ssl)
|
|
{
|
|
int32_t rc;
|
|
int32_t hmacAlg;
|
|
psSize_t secretLen;
|
|
unsigned char *inputSecretRead;
|
|
|
|
if (ssl->sec.tls13KsState.deriveEarlyDataKeysDone)
|
|
{
|
|
return PS_SUCCESS;
|
|
}
|
|
|
|
hmacAlg = tls13GetPskHmacAlg(ssl->sec.tls13SessionPskList);
|
|
secretLen = tls13GetPskHashLen(ssl->sec.tls13SessionPskList);
|
|
|
|
inputSecretRead = ssl->sec.tls13EarlyTrafficSecretClient;
|
|
|
|
rc = psHkdfExpandLabel(ssl->hsPool,
|
|
hmacAlg,
|
|
inputSecretRead,
|
|
secretLen,
|
|
"key",
|
|
3,
|
|
NULL,
|
|
0,
|
|
ssl->cipher->keySize,
|
|
ssl->sec.tls13EarlyDataKey);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
#ifdef DEBUG_TLS_1_3_KEY_DERIVE
|
|
psTraceBytes("tls13EarlyDataKey",
|
|
ssl->sec.tls13EarlyDataKey, ssl->cipher->keySize);
|
|
#endif
|
|
|
|
rc = psHkdfExpandLabel(ssl->hsPool,
|
|
hmacAlg,
|
|
inputSecretRead,
|
|
secretLen,
|
|
"iv",
|
|
2,
|
|
NULL,
|
|
0,
|
|
ssl->cipher->ivSize,
|
|
ssl->sec.tls13EarlyDataIv);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
#ifdef DEBUG_TLS_1_3_KEY_DERIVE
|
|
psTraceBytes("tls13EarlyDataIv",
|
|
ssl->sec.tls13EarlyDataIv, ssl->cipher->ivSize);
|
|
#endif
|
|
|
|
ssl->sec.tls13KsState.deriveEarlyDataKeysDone = 1;
|
|
return PS_SUCCESS;
|
|
}
|
|
|
|
int32_t tls13DeriveAppKeys(ssl_t *ssl)
|
|
{
|
|
int32_t hmacAlg = tls13GetCipherHmacAlg(ssl);
|
|
int32_t rc = psGetOutputBlockLength(hmacAlg);
|
|
psSize_t secretLen;
|
|
psBool_t isServer = (ssl->flags & SSL_FLAGS_SERVER) ? PS_TRUE : PS_FALSE;
|
|
unsigned char *inputSecretRead, *inputSecretWrite;
|
|
|
|
if (ssl->sec.tls13KsState.deriveAppKeysDone)
|
|
{
|
|
return PS_SUCCESS;
|
|
}
|
|
|
|
if (rc < 0)
|
|
{ /* this is an error code */
|
|
return rc;
|
|
}
|
|
secretLen = rc;
|
|
|
|
if (isServer)
|
|
{
|
|
inputSecretRead = ssl->sec.tls13AppTrafficSecretClient;
|
|
inputSecretWrite = ssl->sec.tls13AppTrafficSecretServer;
|
|
}
|
|
else
|
|
{
|
|
inputSecretRead = ssl->sec.tls13AppTrafficSecretServer;
|
|
inputSecretWrite = ssl->sec.tls13AppTrafficSecretClient;
|
|
}
|
|
|
|
/* Read keys. */
|
|
|
|
rc = psHkdfExpandLabel(ssl->hsPool,
|
|
hmacAlg,
|
|
inputSecretRead,
|
|
secretLen,
|
|
"key",
|
|
3,
|
|
NULL,
|
|
0,
|
|
ssl->cipher->keySize,
|
|
ssl->sec.tls13AppReadKey);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
#ifdef DEBUG_TLS_1_3_KEY_DERIVE
|
|
psTraceBytes("tls13AppReadKey",
|
|
ssl->sec.tls13AppReadKey, ssl->cipher->keySize);
|
|
#endif
|
|
|
|
rc = psHkdfExpandLabel(ssl->hsPool,
|
|
hmacAlg,
|
|
inputSecretRead,
|
|
secretLen,
|
|
"iv",
|
|
2,
|
|
NULL,
|
|
0,
|
|
ssl->cipher->ivSize,
|
|
ssl->sec.tls13AppReadIv);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
#ifdef DEBUG_TLS_1_3_KEY_DERIVE
|
|
psTraceBytes("tls13AppReadIv",
|
|
ssl->sec.tls13AppReadIv, ssl->cipher->ivSize);
|
|
psTraceBytes("inputSecretWrite", inputSecretWrite, secretLen);
|
|
#endif
|
|
|
|
/* Write keys. */
|
|
|
|
rc = psHkdfExpandLabel(ssl->hsPool,
|
|
hmacAlg,
|
|
inputSecretWrite,
|
|
secretLen,
|
|
"key",
|
|
3,
|
|
NULL,
|
|
0,
|
|
ssl->cipher->keySize,
|
|
ssl->sec.tls13AppWriteKey);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
|
|
#ifdef DEBUG_TLS_1_3_KEY_DERIVE
|
|
psTraceBytes("tls13AppWriteKey",
|
|
ssl->sec.tls13AppWriteKey, ssl->cipher->keySize);
|
|
#endif
|
|
|
|
rc = psHkdfExpandLabel(ssl->hsPool,
|
|
hmacAlg,
|
|
inputSecretWrite,
|
|
secretLen,
|
|
"iv",
|
|
2,
|
|
NULL,
|
|
0,
|
|
ssl->cipher->ivSize,
|
|
ssl->sec.tls13AppWriteIv);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
|
|
#ifdef DEBUG_TLS_1_3_KEY_DERIVE
|
|
psTraceBytes("tls13AppWriteIv",
|
|
ssl->sec.tls13AppWriteIv, ssl->cipher->ivSize);
|
|
#endif
|
|
|
|
ssl->sec.tls13KsState.deriveAppKeysDone = 1;
|
|
return PS_SUCCESS;
|
|
}
|
|
|
|
int32_t tls13DeriveBinderKey(ssl_t *ssl,
|
|
int32_t hmacAlg,
|
|
unsigned char *binderSecret,
|
|
psSize_t binderSecretLen,
|
|
unsigned char *binderKeyOut,
|
|
psSize_t *binderKeyOutLen)
|
|
{
|
|
int32 rc;
|
|
psSize_t secretLen;
|
|
unsigned char *base_key;
|
|
|
|
base_key = binderSecret;
|
|
|
|
rc = psGetOutputBlockLength(hmacAlg);
|
|
if (rc < 0)
|
|
{ /* this is an error code */
|
|
return rc;
|
|
}
|
|
secretLen = rc;
|
|
|
|
/*
|
|
finished_key =
|
|
HKDF-Expand-Label(BaseKey, "finished", "", Hash.length)
|
|
*/
|
|
rc = psHkdfExpandLabel(ssl->hsPool,
|
|
hmacAlg,
|
|
base_key,
|
|
secretLen,
|
|
finishedLabel,
|
|
finishedLabelLen,
|
|
NULL,
|
|
0,
|
|
secretLen,
|
|
binderKeyOut);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
|
|
*binderKeyOutLen = secretLen;
|
|
|
|
tls13ClearSecret(base_key, secretLen);
|
|
|
|
#ifdef DEBUG_TLS_1_3_KEY_DERIVE
|
|
psTraceBytes("Binder key", binderKeyOut, *binderKeyOutLen);
|
|
#endif
|
|
|
|
return PS_SUCCESS;
|
|
}
|
|
|
|
int32_t tls13DeriveFinishedKey(ssl_t *ssl, psBool_t wantServerKey)
|
|
{
|
|
int32_t hmacAlg = tls13GetCipherHmacAlg(ssl);
|
|
int32 rc = psGetOutputBlockLength(hmacAlg);
|
|
psSize_t secretLen;
|
|
unsigned char *base_key;
|
|
|
|
if (wantServerKey)
|
|
{
|
|
if (ssl->sec.tls13KsState.deriveServerFinishedKeyDone)
|
|
{
|
|
return PS_SUCCESS;
|
|
}
|
|
base_key = ssl->sec.tls13HsTrafficSecretServer;
|
|
}
|
|
else
|
|
{
|
|
if (ssl->sec.tls13KsState.deriveClientFinishedKeyDone)
|
|
{
|
|
return PS_SUCCESS;
|
|
}
|
|
base_key = ssl->sec.tls13HsTrafficSecretClient;
|
|
}
|
|
|
|
if (rc < 0)
|
|
{ /* this is an error code */
|
|
return rc;
|
|
}
|
|
secretLen = rc;
|
|
|
|
/*
|
|
finished_key =
|
|
HKDF-Expand-Label(BaseKey, "finished", "", Hash.length)
|
|
*/
|
|
rc = psHkdfExpandLabel(ssl->hsPool,
|
|
hmacAlg,
|
|
base_key,
|
|
secretLen,
|
|
finishedLabel,
|
|
finishedLabelLen,
|
|
NULL,
|
|
0,
|
|
secretLen,
|
|
ssl->sec.tls13FinishedKey);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
|
|
tls13ClearSecret(base_key, secretLen);
|
|
|
|
#ifdef DEBUG_TLS_1_3_KEY_DERIVE
|
|
psTraceBytes("Finished key", ssl->sec.tls13FinishedKey, secretLen);
|
|
#endif
|
|
|
|
if (wantServerKey)
|
|
{
|
|
ssl->sec.tls13KsState.deriveServerFinishedKeyDone = 1;
|
|
}
|
|
else
|
|
{
|
|
ssl->sec.tls13KsState.deriveClientFinishedKeyDone = 1;
|
|
}
|
|
|
|
return PS_SUCCESS;
|
|
}
|
|
|
|
int32_t tls13ActivateEarlyDataWriteKeys(ssl_t *ssl)
|
|
{
|
|
int32_t rc;
|
|
|
|
psTraceInfo("++++ K_send = early_traffic ++++\n");
|
|
|
|
ssl->sec.wKeyptr = ssl->sec.tls13EarlyDataKey;
|
|
ssl->sec.wIVptr = ssl->sec.tls13EarlyDataIv;
|
|
|
|
Memcpy(ssl->sec.tls13WriteIv, ssl->sec.tls13EarlyDataIv,
|
|
ssl->cipher->ivSize);
|
|
|
|
#ifdef DEBUG_TLS_1_3_KEY_DERIVE
|
|
psTraceBytes("early_data write key", ssl->sec.tls13EarlyDataKey,
|
|
ssl->cipher->keySize);
|
|
psTraceBytes("early_data write iv", ssl->sec.tls13EarlyDataIv,
|
|
ssl->cipher->ivSize);
|
|
#endif
|
|
|
|
Memset(ssl->sec.seq, 0, 8);
|
|
|
|
rc = sslActivateWriteCipher(ssl);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
|
|
return PS_SUCCESS;
|
|
}
|
|
|
|
int32_t tls13ActivateEarlyDataReadKeys(ssl_t *ssl)
|
|
{
|
|
int32_t rc;
|
|
|
|
psTraceInfo("++++ K_recv = early_traffic ++++\n");
|
|
|
|
ssl->sec.rKeyptr = ssl->sec.tls13EarlyDataKey;
|
|
ssl->sec.rIVptr = ssl->sec.tls13EarlyDataIv;
|
|
|
|
Memcpy(ssl->sec.tls13ReadIv, ssl->sec.tls13EarlyDataIv,
|
|
ssl->cipher->ivSize);
|
|
|
|
#ifdef DEBUG_TLS_1_3_KEY_DERIVE
|
|
psTraceBytes("early_data read key", ssl->sec.tls13EarlyDataKey,
|
|
ssl->cipher->keySize);
|
|
psTraceBytes("early_data read iv", ssl->sec.tls13EarlyDataIv,
|
|
ssl->cipher->ivSize);
|
|
#endif
|
|
|
|
Memset(ssl->sec.seq, 0, 8);
|
|
|
|
rc = sslActivateReadCipher(ssl);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
|
|
return PS_SUCCESS;
|
|
}
|
|
|
|
int32_t tls13ActivateHsWriteKeys(ssl_t *ssl)
|
|
{
|
|
int32_t rc;
|
|
|
|
psTraceInfo("++++ K_send = handshake ++++\n");
|
|
|
|
ssl->sec.wKeyptr = ssl->sec.tls13HsWriteKey;
|
|
ssl->sec.wIVptr = ssl->sec.tls13HsWriteIv;
|
|
|
|
Memcpy(ssl->sec.tls13WriteIv, ssl->sec.tls13HsWriteIv,
|
|
ssl->cipher->ivSize);
|
|
|
|
rc = sslActivateWriteCipher(ssl);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
|
|
return PS_SUCCESS;
|
|
}
|
|
|
|
int32_t tls13ActivateHsReadKeys(ssl_t *ssl)
|
|
{
|
|
int32_t rc;
|
|
|
|
psTraceInfo("++++ K_recv = handshake ++++\n");
|
|
|
|
ssl->sec.rKeyptr = ssl->sec.tls13HsReadKey;
|
|
ssl->sec.rIVptr = ssl->sec.tls13HsReadIv;
|
|
|
|
Memcpy(ssl->sec.tls13ReadIv, ssl->sec.tls13HsReadIv,
|
|
ssl->cipher->ivSize);
|
|
|
|
#ifdef DEBUG_TLS_1_3_KEY_DERIVE
|
|
psTraceBytes("handshake read key", ssl->sec.tls13HsReadKey,
|
|
ssl->cipher->keySize);
|
|
#endif
|
|
|
|
rc = sslActivateReadCipher(ssl);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
|
|
return PS_SUCCESS;
|
|
}
|
|
|
|
int32_t tls13ActivateAppWriteKeys(ssl_t *ssl)
|
|
{
|
|
int32_t rc;
|
|
|
|
psTraceInfo("++++ K_send = application ++++\n");
|
|
|
|
ssl->sec.wKeyptr = ssl->sec.tls13AppWriteKey;
|
|
ssl->sec.wIVptr = ssl->sec.tls13AppWriteIv;
|
|
|
|
Memcpy(ssl->sec.tls13WriteIv, ssl->sec.tls13AppWriteIv,
|
|
ssl->cipher->ivSize);
|
|
|
|
#ifdef DEBUG_TLS_1_3_KEY_DERIVE
|
|
psTraceBytes("app write key", ssl->sec.tls13AppWriteKey,
|
|
ssl->cipher->keySize);
|
|
psTraceBytes("app write iv", ssl->sec.tls13AppWriteIv,
|
|
ssl->cipher->ivSize);
|
|
#endif
|
|
|
|
Memset(ssl->sec.seq, 0, 8);
|
|
|
|
rc = sslActivateWriteCipher(ssl);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
|
|
return PS_SUCCESS;
|
|
}
|
|
|
|
int32_t tls13ActivateAppReadKeys(ssl_t *ssl)
|
|
{
|
|
int32_t rc;
|
|
|
|
psTraceInfo("++++ K_recv = application ++++\n");
|
|
|
|
ssl->sec.rKeyptr = ssl->sec.tls13AppReadKey;
|
|
ssl->sec.rIVptr = ssl->sec.tls13AppReadIv;
|
|
|
|
Memcpy(ssl->sec.tls13ReadIv, ssl->sec.tls13AppReadIv,
|
|
ssl->cipher->ivSize);
|
|
|
|
#ifdef DEBUG_TLS_1_3_KEY_DERIVE
|
|
psTraceBytes("app read key", ssl->sec.tls13AppReadKey,
|
|
ssl->cipher->keySize);
|
|
psTraceBytes("app read iv", ssl->sec.tls13AppReadIv,
|
|
ssl->cipher->ivSize);
|
|
#endif
|
|
|
|
Memset(ssl->sec.remSeq, 0, 8);
|
|
|
|
rc = sslActivateReadCipher(ssl);
|
|
if (rc < 0)
|
|
{
|
|
return rc;
|
|
}
|
|
|
|
return PS_SUCCESS;
|
|
}
|
|
|
|
|
|
#endif /* USE_TLS_1_3 */
|