| 1040 | } |
| 1041 | |
| 1042 | bool SSU2Session::ProcessSessionCreated (uint8_t * buf, size_t len) |
| 1043 | { |
| 1044 | // we are Alice |
| 1045 | if (!m_NoiseState) |
| 1046 | { |
| 1047 | LogPrint (eLogWarning, "SSU2: Unexpected SessionCreated message"); |
| 1048 | return false; |
| 1049 | } |
| 1050 | Header header; |
| 1051 | memcpy (header.buf, buf, 16); |
| 1052 | header.ll[0] ^= CreateHeaderMask (m_Address->i, buf + (len - 24)); |
| 1053 | uint8_t kh2[32]; |
| 1054 | i2p::crypto::HKDF (m_NoiseState->m_CK, nullptr, 0, "SessCreateHeader", kh2, 32); // k_header_2 = HKDF(chainKey, ZEROLEN, "SessCreateHeader", 32) |
| 1055 | header.ll[1] ^= CreateHeaderMask (kh2, buf + (len - 12)); |
| 1056 | if (header.h.type != eSSU2SessionCreated) |
| 1057 | // this situation is valid, because it might be Retry with different encryption |
| 1058 | return false; |
| 1059 | if (len < 80) |
| 1060 | { |
| 1061 | LogPrint (eLogWarning, "SSU2: SessionCreated message too short ", len); |
| 1062 | return false; |
| 1063 | } |
| 1064 | m_HandshakeInterval = i2p::util::GetMillisecondsSinceEpoch () - m_HandshakeInterval; |
| 1065 | const uint8_t nonce[12] = {0}; |
| 1066 | uint8_t headerX[48]; |
| 1067 | m_Server.ChaCha20 (buf + 16, 48, kh2, nonce, headerX); |
| 1068 | // KDF for SessionCreated |
| 1069 | m_NoiseState->MixHash ( { {header.buf, 16}, {headerX, 16} } ); // h = SHA256(h || header) |
| 1070 | m_NoiseState->MixHash (headerX + 16, 32); // h = SHA256(h || bepk); |
| 1071 | uint8_t sharedSecret[32]; |
| 1072 | m_EphemeralKeys->Agree (headerX + 16, sharedSecret); |
| 1073 | m_NoiseState->MixKey (sharedSecret); |
| 1074 | size_t offset = 64; |
| 1075 | #if OPENSSL_PQ |
| 1076 | if (m_Version > 2 && m_PQKeys) |
| 1077 | { |
| 1078 | i2p::data::CryptoKeyType cryptoType = (i2p::data::CryptoKeyType)(m_Version + 2); |
| 1079 | size_t cipherTextLen = i2p::crypto::GetMLKEMCipherTextLen (cryptoType); |
| 1080 | std::vector<uint8_t> kemCiphertext(cipherTextLen); |
| 1081 | if (!m_NoiseState->Decrypt (buf + offset, kemCiphertext.data (), cipherTextLen)) |
| 1082 | { |
| 1083 | LogPrint (eLogWarning, "SSU2: SessionCreated ML-KEM ciphertext section AEAD decryption failed"); |
| 1084 | return false; |
| 1085 | } |
| 1086 | m_NoiseState->MixHash (buf + offset, cipherTextLen + 16); |
| 1087 | offset += cipherTextLen + 16; |
| 1088 | m_PQKeys->Decaps (kemCiphertext.data (), sharedSecret); |
| 1089 | m_NoiseState->MixKey (sharedSecret); |
| 1090 | } |
| 1091 | #endif |
| 1092 | // decrypt |
| 1093 | if (offset + 16 > len) |
| 1094 | { |
| 1095 | LogPrint (eLogWarning, "SSU2: SessionCreated message is too short ", len); |
| 1096 | return false; |
| 1097 | } |
| 1098 | uint8_t * payload = buf + offset; |
| 1099 | std::vector<uint8_t> decryptedPayload(len - offset - 16); |
nothing calls this directly
no test coverage detected