| 144 | } |
| 145 | |
| 146 | bool NTCP2Establisher::CreateSessionRequestMessage (std::mt19937& rng) |
| 147 | { |
| 148 | size_t offset = 0; |
| 149 | // encrypt X |
| 150 | i2p::crypto::CBCEncryption encryption; |
| 151 | encryption.SetKey (m_RemoteIdentHash); |
| 152 | #if OPENSSL_PQ |
| 153 | if (m_CryptoType > i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) |
| 154 | { |
| 155 | uint8_t pub[32]; |
| 156 | memcpy (pub, GetPub (), 32); |
| 157 | pub[31] |= 0x80; // set highest bit |
| 158 | encryption.Encrypt (pub, 32, m_IV, m_Buffer); // X |
| 159 | // ML-KEM encap_key |
| 160 | m_PQKeys = i2p::crypto::CreateMLKEMKeys (m_CryptoType); |
| 161 | m_PQKeys->GenerateKeys (); |
| 162 | } |
| 163 | else |
| 164 | encryption.Encrypt (GetPub (), 32, m_IV, m_Buffer); // X |
| 165 | #else |
| 166 | encryption.Encrypt (GetPub (), 32, m_IV, m_Buffer); // X |
| 167 | #endif |
| 168 | memcpy (m_IV, m_Buffer + 16, 16); // save last block as IV for SessionCreated |
| 169 | offset += 32; |
| 170 | // encryption key for next block |
| 171 | if (!KDF1Alice ()) return false; |
| 172 | size_t maxPaddingLength = m_IsLongPadding ? NTCP2_SESSION_HANDSHAKE_LONG_MAX_SIZE : NTCP2_SESSION_HANDSHAKE_MAX_SIZE; |
| 173 | maxPaddingLength -= 64; |
| 174 | size_t maxMsgSize = m_MaxMsgSize; |
| 175 | #if OPENSSL_PQ |
| 176 | if (m_PQKeys) |
| 177 | { |
| 178 | // ML-KEM frame |
| 179 | auto keyLen = i2p::crypto::GetMLKEMPublicKeyLen (m_CryptoType); |
| 180 | std::vector<uint8_t> encapsKey(keyLen); |
| 181 | m_PQKeys->GetPublicKey (encapsKey.data ()); |
| 182 | // encrypt encapsKey |
| 183 | if (!Encrypt (encapsKey.data (), m_Buffer + offset, keyLen)) |
| 184 | { |
| 185 | LogPrint (eLogWarning, "NTCP2: SessionRequest ML-KEM encap_key frame AEAD encryption failed "); |
| 186 | return false; |
| 187 | } |
| 188 | MixHash (m_Buffer + offset, keyLen + 16); // h = SHA256(h || ciphertext) |
| 189 | offset += keyLen + 16; |
| 190 | maxPaddingLength = offset + 32; // 32 bytes following options block size |
| 191 | // adjust max msg size because we might send smaller message that we can receive |
| 192 | maxMsgSize = NTCP2_SESSION_HANDSHAKE_LONG_MAX_SIZE + i2p::crypto::MLKEM1024_KEY_LENGTH + 16; |
| 193 | if (maxMsgSize > m_MaxMsgSize) maxMsgSize = m_MaxMsgSize; |
| 194 | } |
| 195 | #endif |
| 196 | // calculate padding length |
| 197 | if (offset + 32 + maxPaddingLength > maxMsgSize) maxPaddingLength = maxMsgSize - offset - 32; |
| 198 | auto paddingLength = maxPaddingLength ? rng () % maxPaddingLength : 0; |
| 199 | // fill options |
| 200 | uint8_t options[32]; // actual options size is 16 bytes |
| 201 | memset (options, 0, 16); |
| 202 | options[0] = i2p::context.GetNetID (); // network ID |
| 203 | options[1] = 2; // ver, always 2 regardless actual version |
no test coverage detected