| 1198 | } |
| 1199 | |
| 1200 | bool SSU2Session::ProcessSessionConfirmed (uint8_t * buf, size_t len) |
| 1201 | { |
| 1202 | // we are Bob |
| 1203 | if (!m_NoiseState) |
| 1204 | { |
| 1205 | LogPrint (eLogWarning, "SSU2: Unexpected SessionConfirmed message"); |
| 1206 | return false; |
| 1207 | } |
| 1208 | Header header; |
| 1209 | memcpy (header.buf, buf, 16); |
| 1210 | header.ll[0] ^= CreateHeaderMask (i2p::context.GetSSU2IntroKey (), buf + (len - 24)); |
| 1211 | uint8_t kh2[32]; |
| 1212 | i2p::crypto::HKDF (m_NoiseState->m_CK, nullptr, 0, "SessionConfirmed", kh2, 32); // k_header_2 = HKDF(chainKey, ZEROLEN, "SessionConfirmed", 32) |
| 1213 | header.ll[1] ^= CreateHeaderMask (kh2, buf + (len - 12)); |
| 1214 | if (header.h.type != eSSU2SessionConfirmed) |
| 1215 | { |
| 1216 | LogPrint (eLogInfo, "SSU2: Unexpected message type ", (int)header.h.type, " instead ", (int)eSSU2SessionConfirmed); |
| 1217 | // TODO: queue up |
| 1218 | return true; |
| 1219 | } |
| 1220 | // packet num must be always zero |
| 1221 | if (header.h.packetNum) |
| 1222 | { |
| 1223 | LogPrint (eLogError, "SSU2: Non zero packet number in SessionConfirmed"); |
| 1224 | return false; |
| 1225 | } |
| 1226 | // check if fragmented |
| 1227 | uint8_t numFragments = header.h.flags[0] & 0x0F; |
| 1228 | if (numFragments > 1) |
| 1229 | { |
| 1230 | // fragmented |
| 1231 | if (numFragments > 2) |
| 1232 | { |
| 1233 | LogPrint (eLogError, "SSU2: Too many fragments ", (int)numFragments, " in SessionConfirmed from ", m_RemoteEndpoint); |
| 1234 | return false; |
| 1235 | } |
| 1236 | if (len < 32) |
| 1237 | { |
| 1238 | LogPrint (eLogWarning, "SSU2: SessionConfirmed fragment too short ", len); |
| 1239 | if (m_SessionConfirmedFragment) m_SessionConfirmedFragment.reset (nullptr); |
| 1240 | return false; |
| 1241 | } |
| 1242 | if (!(header.h.flags[0] & 0xF0)) |
| 1243 | { |
| 1244 | // first fragment |
| 1245 | if (!m_SessionConfirmedFragment) |
| 1246 | { |
| 1247 | m_SessionConfirmedFragment.reset (new HandshakePacket); |
| 1248 | m_SessionConfirmedFragment->header = header; |
| 1249 | memcpy (m_SessionConfirmedFragment->payload, buf + 16, len - 16); |
| 1250 | m_SessionConfirmedFragment->payloadSize = len - 16; |
| 1251 | return true; // wait for second fragment |
| 1252 | } |
| 1253 | else if (m_SessionConfirmedFragment->isSecondFragment) |
| 1254 | { |
| 1255 | // we have second fragment |
| 1256 | m_SessionConfirmedFragment->header = header; |
| 1257 | memmove (m_SessionConfirmedFragment->payload + (len - 16), m_SessionConfirmedFragment->payload, m_SessionConfirmedFragment->payloadSize); |
nothing calls this directly
no test coverage detected