Skip to content

Commit

Permalink
[core] Moved KM refresh in packUniqueData() (#2541).
Browse files Browse the repository at this point in the history
  • Loading branch information
maxsharabayko authored Nov 21, 2022
1 parent f864cec commit be1ccf5
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 43 deletions.
2 changes: 1 addition & 1 deletion haicrypt/hcrypt_ctx_tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ int hcryptCtx_Tx_ManageKM(hcrypt_Session *crypto)
* prepare next SEK for announcement
*/
hcryptCtx_Tx_Refresh(crypto);

HCRYPT_LOG(LOG_INFO, "KM[%d] Pre-announced\n",
(ctx->alt->flags & HCRYPT_CTX_F_xSEK)/2);

Expand Down
5 changes: 5 additions & 0 deletions haicrypt/hcrypt_tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ int HaiCrypt_Tx_Data(HaiCrypt_Handle hhc,
/* Get/Set packet index */
ctx->msg_info->indexMsg(in_pfx, ctx->MSpfx_cache);

if (hcryptMsg_GetKeyIndex(ctx->msg_info, in_pfx) != hcryptCtx_GetKeyIndex(ctx))
{
HCRYPT_LOG(LOG_ERR, "Tx_Data: Key mismatch!");
}

/* Encrypt */
{
hcrypt_DataDesc indata;
Expand Down
32 changes: 18 additions & 14 deletions srtcore/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5902,7 +5902,7 @@ void srt::CUDT::considerLegacySrtHandshake(const steady_clock::time_point &timeb
sendSrtMsg(SRT_CMD_HSREQ);
}

void srt::CUDT::checkSndTimers(Whether2RegenKm regen)
void srt::CUDT::checkSndTimers()
{
if (m_SrtHsSide == HSD_INITIATOR)
{
Expand All @@ -5919,17 +5919,18 @@ void srt::CUDT::checkSndTimers(Whether2RegenKm regen)
<< " - not considering legacy handshake");
}

// This must be done always on sender, regardless of HS side.
// When regen == DONT_REGEN_KM, it's a handshake call, so do
// it only for initiator.
if (regen || m_SrtHsSide == HSD_INITIATOR)
{
// Don't call this function in "non-regen mode" (sending only),
// if this side is RESPONDER. This shall be called only with
// regeneration request, which is required by the sender.
if (m_pCryptoControl)
m_pCryptoControl->sendKeysToPeer(this, SRTT(), regen);
}
// Retransmit KM request after a timeout if there is no response (KM RSP).
// Or send KM REQ in case of the HSv4.
if (m_pCryptoControl)
m_pCryptoControl->sendKeysToPeer(this, SRTT());
}

void srt::CUDT::checkSndKMRefresh()
{
// Do not apply the regenerated key to the to the receiver context.
const bool bidir = false;
if (m_pCryptoControl)
m_pCryptoControl->regenCryptoKm(this, bidir);
}

void srt::CUDT::addressAndSend(CPacket& w_pkt)
Expand Down Expand Up @@ -8386,7 +8387,6 @@ void srt::CUDT::processCtrlAck(const CPacket &ctrlpkt, const steady_clock::time_
// cudt->deliveryRate() instead.
}

checkSndTimers(REGEN_KM);
updateCC(TEV_ACK, EventVariant(ackdata_seqno));

enterCS(m_StatsLock);
Expand Down Expand Up @@ -9549,6 +9549,8 @@ bool srt::CUDT::packUniqueData(CPacket& w_packet)
LOGC(qslog.Warn, log << CONID() << "ENCRYPT FAILED - packet won't be sent, size=" << pld_size);
return false;
}

checkSndKMRefresh();
}

#if SRT_DEBUG_TRACE_SND
Expand Down Expand Up @@ -11148,6 +11150,9 @@ bool srt::CUDT::checkExpTimer(const steady_clock::time_point& currtime, int chec

void srt::CUDT::checkRexmitTimer(const steady_clock::time_point& currtime)
{
// Check if HSv4 should be retransmitted, and if KM_REQ should be resent if the side is INITIATOR.
checkSndTimers();

// There are two algorithms of blind packet retransmission: LATEREXMIT and FASTREXMIT.
//
// LATEREXMIT is only used with FileCC.
Expand Down Expand Up @@ -11211,7 +11216,6 @@ void srt::CUDT::checkRexmitTimer(const steady_clock::time_point& currtime)

++m_iReXmitCount;

checkSndTimers(DONT_REGEN_KM);
const ECheckTimerStage stage = is_fastrexmit ? TEV_CHT_FASTREXMIT : TEV_CHT_REXMIT;
updateCC(TEV_CHECKTIMER, EventVariant(stage));

Expand Down
6 changes: 5 additions & 1 deletion srtcore/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,11 @@ class CUDT
void unlose(const CPacket& oldpacket);
void dropFromLossLists(int32_t from, int32_t to);

void checkSndTimers(Whether2RegenKm regen = DONT_REGEN_KM);
void checkSndTimers();

/// @brief Check and perform KM refresh if needed.
void checkSndKMRefresh();

void handshakeDone()
{
m_iSndHsRetryCnt = 0;
Expand Down
22 changes: 7 additions & 15 deletions srtcore/crypto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ int srt::CCryptoControl::processSrtMsg_KMREQ(
// what has called this function. The HSv5 handshake only enforces bidirectional
// connection.

bool bidirectional = hsv > CUDT::HS_VERSION_UDT4;
const bool bidirectional = hsv > CUDT::HS_VERSION_UDT4;

// Local macro to return rejection appropriately.
// CHANGED. The first version made HSv5 reject the connection.
Expand Down Expand Up @@ -447,8 +447,9 @@ int srt::CCryptoControl::processSrtMsg_KMRSP(const uint32_t* srtdata, size_t len
return retstatus;
}

void srt::CCryptoControl::sendKeysToPeer(CUDT* sock SRT_ATR_UNUSED, int iSRTT SRT_ATR_UNUSED, Whether2RegenKm regen SRT_ATR_UNUSED)
void srt::CCryptoControl::sendKeysToPeer(CUDT* sock SRT_ATR_UNUSED, int iSRTT SRT_ATR_UNUSED)
{
sync::ScopedLock lck(m_mtxLock);
if (!m_hSndCrypto || m_SndKmState == SRT_KM_S_UNSECURED)
{
HLOGC(cnlog.Debug, log << "sendKeysToPeer: NOT sending/regenerating keys: "
Expand Down Expand Up @@ -481,21 +482,13 @@ void srt::CCryptoControl::sendKeysToPeer(CUDT* sock SRT_ATR_UNUSED, int iSRTT SR
}
}
}


if (regen)
{
regenCryptoKm(
sock, // send UMSG_EXT + SRT_CMD_KMREQ to the peer using this socket
false // Do not apply the regenerated key to the to the receiver context
); // regenerate and send
}
#endif
}

#ifdef SRT_ENABLE_ENCRYPTION
void srt::CCryptoControl::regenCryptoKm(CUDT* sock, bool bidirectional)
void srt::CCryptoControl::regenCryptoKm(CUDT* sock SRT_ATR_UNUSED, bool bidirectional SRT_ATR_UNUSED)
{
#ifdef SRT_ENABLE_ENCRYPTION
sync::ScopedLock lck(m_mtxLock);
if (!m_hSndCrypto)
return;

Expand Down Expand Up @@ -569,8 +562,8 @@ void srt::CCryptoControl::regenCryptoKm(CUDT* sock, bool bidirectional)

if (sent)
m_SndKmLastTime = srt::sync::steady_clock::now();
}
#endif
}

srt::CCryptoControl::CCryptoControl(SRTSOCKET id)
: m_SocketID(id)
Expand All @@ -583,7 +576,6 @@ srt::CCryptoControl::CCryptoControl(SRTSOCKET id)
, m_bUseGCM(false)
, m_bErrorReported(false)
{

m_KmSecret.len = 0;
//send
m_SndKmMsg[0].MsgLen = 0;
Expand Down
20 changes: 8 additions & 12 deletions srtcore/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@ const size_t SRT_KMR_KMSTATE = 0;
#define SRT_CMD_MAXSZ HCRYPT_MSG_KM_MAX_SZ /* Maximum SRT custom messages payload size (bytes) */
const size_t SRTDATA_MAXSIZE = SRT_CMD_MAXSZ/sizeof(uint32_t);

enum Whether2RegenKm {DONT_REGEN_KM = 0, REGEN_KM = 1};

class CCryptoControl
{
SRTSOCKET m_SocketID;
Expand All @@ -74,6 +72,7 @@ class CCryptoControl
HaiCrypt_Secret m_KmSecret; //Key material shared secret
// Sender
sync::steady_clock::time_point m_SndKmLastTime;
sync::Mutex m_mtxLock; // A mutex to protect concurrent access to CCryptoControl.
struct {
unsigned char Msg[HCRYPT_MSG_KM_MAX_SZ];
size_t MsgLen;
Expand Down Expand Up @@ -112,15 +111,10 @@ class CCryptoControl
return m_KmSecret.len > 0;
}

private:
#ifdef SRT_ENABLE_ENCRYPTION
/// Regenerate cryptographic key material.
/// Regenerate cryptographic key material if needed.
/// @param[in] sock If not null, the socket will be used to send the KM message to the peer (e.g. KM refresh).
/// @param[in] bidirectional If true, the key material will be regenerated for both directions (receiver and sender).
void regenCryptoKm(CUDT* sock, bool bidirectional);
#endif

public:

size_t KeyLen() { return m_iSndKmKeyLen; }

Expand Down Expand Up @@ -210,11 +204,13 @@ class CCryptoControl
bool init(HandshakeSide, const CSrtConfig&, bool);
void close();

/// @return True if the handshake is in progress.
/// (Re)send KM request to a peer on timeout.
/// This function is used in:
/// - HSv4 (initial key material exchange - in HSv5 it's attached to handshake)
/// - case of key regeneration, which should be then exchanged again.
void sendKeysToPeer(CUDT* sock, int iSRTT, Whether2RegenKm regen);
/// - HSv4 (initial key material exchange - in HSv5 it's attached to handshake).
/// - The case of key regeneration (KM refresh), when a new key has to be sent again.
/// In this case the first sending happens in regenCryptoKm(..). This function
/// retransmits the KM request by timeout if not KM response has been received.
void sendKeysToPeer(CUDT* sock, int iSRTT);

void setCryptoSecret(const HaiCrypt_Secret& secret)
{
Expand Down

0 comments on commit be1ccf5

Please sign in to comment.