| 237 | } |
| 238 | |
| 239 | bool NTCP2Establisher::CreateSessionCreatedMessage (std::mt19937& rng) |
| 240 | { |
| 241 | size_t offset = 0; |
| 242 | // encrypt Y |
| 243 | i2p::crypto::CBCEncryption encryption; |
| 244 | encryption.SetKey (i2p::context.GetIdentHash ()); |
| 245 | encryption.Encrypt (GetPub (), 32, m_IV, m_Buffer); // Y |
| 246 | offset += 32; |
| 247 | // encryption key for next block (m_K) |
| 248 | if (!KDF2Bob ()) return false; |
| 249 | size_t maxPaddingLength = m_IsLongPadding ? NTCP2_SESSION_HANDSHAKE_LONG_MAX_SIZE : NTCP2_SESSION_HANDSHAKE_MAX_SIZE; |
| 250 | maxPaddingLength -= 64; |
| 251 | size_t maxMsgSize = m_MaxMsgSize; |
| 252 | #if OPENSSL_PQ |
| 253 | if (m_PQKeys) |
| 254 | { |
| 255 | size_t cipherTextLen = i2p::crypto::GetMLKEMCipherTextLen (m_CryptoType); |
| 256 | std::vector<uint8_t> kemCiphertext(cipherTextLen); |
| 257 | uint8_t sharedSecret[32]; |
| 258 | m_PQKeys->Encaps (kemCiphertext.data (), sharedSecret); |
| 259 | if (!Encrypt (kemCiphertext.data (), m_Buffer + offset, cipherTextLen)) |
| 260 | { |
| 261 | LogPrint (eLogWarning, "NTCP2: SessionCreated ML-KEM ciphertext section AEAD encryption failed"); |
| 262 | return false; |
| 263 | } |
| 264 | MixHash (m_Buffer + offset, cipherTextLen + 16); // encrypt ML-KEM frame |
| 265 | MixKey (sharedSecret); |
| 266 | offset += cipherTextLen + 16; |
| 267 | maxPaddingLength= offset + 32; // 32 bytes following options block size |
| 268 | // adjust max msg size because we might send smaller message that we can receive |
| 269 | maxMsgSize = NTCP2_SESSION_HANDSHAKE_LONG_MAX_SIZE + i2p::crypto::MLKEM1024_KEY_LENGTH + 16; |
| 270 | if (maxMsgSize > m_MaxMsgSize) maxMsgSize = m_MaxMsgSize; |
| 271 | } |
| 272 | #endif |
| 273 | // calculate padding length |
| 274 | if (offset + 32 + maxPaddingLength > maxMsgSize) maxPaddingLength = maxMsgSize - offset - 32; |
| 275 | auto paddingLength = maxPaddingLength ? rng () % maxPaddingLength : 0; |
| 276 | uint8_t options[16]; |
| 277 | memset (options, 0, 16); |
| 278 | htobe16buf (options + 2, paddingLength); // padLen |
| 279 | htobe32buf (options + 8, (i2p::util::GetMillisecondsSinceEpoch () + 500)/1000); // tsB, rounded to seconds |
| 280 | // encrypt options |
| 281 | if (!Encrypt (options, m_Buffer + offset, 16)) |
| 282 | { |
| 283 | LogPrint (eLogWarning, "NTCP2: SessionCreated failed to encrypt options"); |
| 284 | return false; |
| 285 | } |
| 286 | MixHash (m_Buffer + offset, 32); // encrypted options |
| 287 | offset += 32; |
| 288 | // padding |
| 289 | if (paddingLength) |
| 290 | { |
| 291 | RAND_bytes (m_Buffer + offset, paddingLength); |
| 292 | MixHash (m_Buffer + offset, paddingLength); |
| 293 | } |
| 294 | m_BufferLen = offset + paddingLength; |
| 295 | return true; |
| 296 | } |
no test coverage detected