| 1579 | } |
| 1580 | |
| 1581 | bool SSU2Session::ProcessRetry (uint8_t * buf, size_t len) |
| 1582 | { |
| 1583 | // we are Alice |
| 1584 | Header header; |
| 1585 | memcpy (header.buf, buf, 16); |
| 1586 | header.ll[0] ^= CreateHeaderMask (m_Address->i, buf + (len - 24)); |
| 1587 | header.ll[1] ^= CreateHeaderMask (m_Address->i, buf + (len - 12)); |
| 1588 | if (header.h.type != eSSU2Retry) |
| 1589 | { |
| 1590 | LogPrint (eLogWarning, "SSU2: Unexpected message type ", (int)header.h.type, " instead ", (int)eSSU2Retry); |
| 1591 | return false; |
| 1592 | } |
| 1593 | if (len < 48) |
| 1594 | { |
| 1595 | LogPrint (eLogWarning, "SSU2: Retry message too short ", len); |
| 1596 | return false; |
| 1597 | } |
| 1598 | uint8_t nonce[12] = {0}; |
| 1599 | uint64_t headerX[2]; // sourceConnID, token |
| 1600 | m_Server.ChaCha20 (buf + 16, 16, m_Address->i, nonce, (uint8_t *)headerX); |
| 1601 | uint64_t token = headerX[1]; |
| 1602 | if (token) |
| 1603 | m_Server.UpdateOutgoingToken (m_RemoteEndpoint, token, i2p::util::GetSecondsSinceEpoch () + SSU2_TOKEN_EXPIRATION_TIMEOUT); |
| 1604 | // decrypt and handle payload |
| 1605 | uint8_t * payload = buf + 32; |
| 1606 | CreateNonce (be32toh (header.h.packetNum), nonce); |
| 1607 | uint8_t h[32]; |
| 1608 | memcpy (h, header.buf, 16); |
| 1609 | memcpy (h + 16, &headerX, 16); |
| 1610 | if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len - 48, h, 32, |
| 1611 | m_Address->i, nonce, payload, len - 48, false)) |
| 1612 | { |
| 1613 | LogPrint (eLogWarning, "SSU2: Retry AEAD verification failed"); |
| 1614 | return false; |
| 1615 | } |
| 1616 | m_State = eSSU2SessionStateTokenReceived; |
| 1617 | HandlePayload (payload, len - 48); |
| 1618 | if (m_TerminationReason == eSSU2TerminationReasonIncompatibleVersion) |
| 1619 | m_Version = 2; // fallback to non-PQ |
| 1620 | if (!token) |
| 1621 | { |
| 1622 | // we should handle payload even for zero token to handle Datetime block and adjust clock in case of clock skew |
| 1623 | LogPrint (eLogWarning, "SSU2: Retry token is zero"); |
| 1624 | return false; |
| 1625 | } |
| 1626 | |
| 1627 | if (!m_NoiseState) m_NoiseState.reset (new i2p::crypto::NoiseSymmetricState); |
| 1628 | #if OPENSSL_PQ |
| 1629 | if (m_Version > 2) |
| 1630 | InitNoiseXKStateMLKEM1 (*m_NoiseState, (i2p::data::CryptoKeyType)(m_Version + 2), m_Address->s); |
| 1631 | else |
| 1632 | #endif |
| 1633 | InitNoiseXKState1 (*m_NoiseState, m_Address->s); // reset Noise TODO: check state |
| 1634 | |
| 1635 | m_TerminationReason = eSSU2TerminationReasonNormalClose; |
| 1636 | return SendSessionRequest (token); |
| 1637 | } |
| 1638 |
no test coverage detected