Loading src/crypto/tls.cpp +65 −19 Original line number Diff line number Diff line Loading @@ -293,6 +293,7 @@ namespace netplus { // defaults bool offeredTLS13 = false; bool secureReneg = false; bool extMasterSecret = false; client_keyshare_ecdhe.clear(); // secure reneg SCSV in suites? Loading Loading @@ -321,6 +322,9 @@ namespace netplus { // renegotiation_info if (et == 0xFF01) secureReneg = true; // extended_master_secret (RFC 7627) if (et == 0x0017 && el == 0) extMasterSecret = true; // supported_versions if (et == 0x002b) { if (el < 3) throwSSL(NetException::Error, "supported_versions too short"); Loading Loading @@ -420,6 +424,7 @@ namespace netplus { // store flags client_offered_tls13 = offeredTLS13; secure_reneg = secureReneg; extended_master_secret = extMasterSecret; auto hasSuite = [&](uint16_t s) { for (auto cs : clientSuites) if (cs == s) return true; Loading Loading @@ -754,17 +759,20 @@ namespace netplus { body.push_back((chosenSuite >> 8) & 0xFF); body.push_back((chosenSuite >> 0) & 0xFF); body.push_back(0x00); // null compression // renegotiation_info if (secure_reneg) { { std::vector<uint8_t> exts; if (secure_reneg) { exts.push_back(0xFF); exts.push_back(0x01); exts.push_back(0x00); exts.push_back(0x01); exts.push_back(0x00); } if (extended_master_secret) { exts.push_back(0x00); exts.push_back(0x17); exts.push_back(0x00); exts.push_back(0x00); } body.push_back((exts.size() >> 8) & 0xFF); body.push_back((exts.size() >> 0) & 0xFF); body.insert(body.end(), exts.begin(), exts.end()); } else { body.push_back(0x00); body.push_back(0x00); } sendHandshake(0x02, body); } Loading Loading @@ -1172,10 +1180,20 @@ namespace netplus { preMaster = extractPreMasterFromPkcs1(pkcs1); } // master_secret = PRF(PMS, "master secret", client_random || server_random) // Add CKE to transcript so session_hash covers it (RFC 5246 + RFC 7627) handshake_transcript.insert(handshake_transcript.end(), msg.begin(), msg.end()); // master_secret derivation if (extended_master_secret) { // RFC 7627: master_secret = PRF(PMS, "extended master secret", session_hash) std::vector<uint8_t> sessionHash = sha256_hash(handshake_transcript); masterSecret = prf(preMaster, "extended master secret", sessionHash, 48); } else { // RFC 5246: master_secret = PRF(PMS, "master secret", ClientRandom || ServerRandom) std::vector<uint8_t> msSeed = clientRandom; msSeed.insert(msSeed.end(), serverRandom.begin(), serverRandom.end()); masterSecret = prf(preMaster, "master secret", msSeed, 48); } // key_block = PRF(master, "key expansion", server_random || client_random) std::vector<uint8_t> kbSeed = serverRandom; Loading Loading @@ -1765,12 +1783,12 @@ namespace netplus { } // extended_master_secret (RFC 7627) if (et == 0x0017 && el == 0) extended_master_secret = true; eoff += el; } // NOTE: ServerHello was already added to transcript by fetchNextHandshakePlain() // Do NOT add it again here! if (tls13) { if (!client_offered_tls13 || !tls13_got_key_share){ NetException e; Loading Loading @@ -1847,6 +1865,9 @@ namespace netplus { // Save server's session_id for future resumption client_session_id = server_sid; // Add ServerHello to transcript (RFC 5246) handshake_transcript.insert(handshake_transcript.end(), sh.begin(), sh.end()); hs_state = HsState::CLI_WAIT_CERT; break; } Loading Loading @@ -2142,6 +2163,9 @@ namespace netplus { } } // Add Certificate to transcript (RFC 5246) handshake_transcript.insert(handshake_transcript.end(), certMsg.begin(), certMsg.end()); hs_state = server_cert_is_ecdsa ? HsState::CLI_TLS12_WAIT_SKE : HsState::CLI_WAIT_SHD; break; } Loading Loading @@ -2197,6 +2221,9 @@ namespace netplus { tls12_srv_ecdhe_pub.assign(msg.begin() + off, msg.begin() + off + pubkey_len); // Signature is after the key — skip verification (like cert verification) // Add ServerKeyExchange to transcript (RFC 5246) handshake_transcript.insert(handshake_transcript.end(), msg.begin(), msg.end()); hs_state = HsState::CLI_WAIT_SHD; break; } Loading Loading @@ -2224,6 +2251,9 @@ namespace netplus { throw e; } // Add ServerHelloDone to transcript (RFC 5246) handshake_transcript.insert(handshake_transcript.end(), msg.begin(), msg.end()); hs_state = HsState::CLI_SEND_CKE; break; } Loading Loading @@ -2299,10 +2329,16 @@ namespace netplus { sendHandshake(0x10, ckeBody); // Derive master_secret // Derive master_secret (sendHandshake above already added CKE to transcript) if (extended_master_secret) { // RFC 7627: master_secret = PRF(PMS, "extended master secret", session_hash) std::vector<uint8_t> sessionHash = sha256_hash(handshake_transcript); masterSecret = prf(preMaster, "extended master secret", sessionHash, 48); } else { std::vector<uint8_t> msSeed = clientRandom; msSeed.insert(msSeed.end(), serverRandom.begin(), serverRandom.end()); masterSecret = prf(preMaster, "master secret", msSeed, 48); } // Derive key_block std::vector<uint8_t> kbSeed = serverRandom; Loading Loading @@ -4033,6 +4069,12 @@ namespace netplus { exts.push_back(0x00); } if (extended_master_secret) { // extended_master_secret (RFC 7627): type=0x0017, length=0x0000 (empty) exts.push_back(0x00); exts.push_back(0x17); exts.push_back(0x00); exts.push_back(0x00); } // Write extensions length (always present in TLS1.2 ServerHello!) body.push_back((exts.size() >> 8) & 0xFF); body.push_back((exts.size() >> 0) & 0xFF); Loading Loading @@ -4728,6 +4770,10 @@ namespace netplus { } } // extended_master_secret (RFC 7627): type=0x0017, length=0x0000 (empty data) exts.push_back(0x00); exts.push_back(0x17); exts.push_back(0x00); exts.push_back(0x00); // Mark that we offered TLS 1.3 (only when not in TLS 1.2-only mode) client_offered_tls13 = !client_tls12_only; Loading src/crypto/tls.h +1 −0 Original line number Diff line number Diff line Loading @@ -416,6 +416,7 @@ namespace netplus { bool handshakeStarted = false; bool handshakeDone = false; bool secure_reneg = true; bool extended_master_secret = false; bool ccs_received = false; bool cli_cke_sent = false; bool cli_ccs_fin_sent = false; Loading Loading
src/crypto/tls.cpp +65 −19 Original line number Diff line number Diff line Loading @@ -293,6 +293,7 @@ namespace netplus { // defaults bool offeredTLS13 = false; bool secureReneg = false; bool extMasterSecret = false; client_keyshare_ecdhe.clear(); // secure reneg SCSV in suites? Loading Loading @@ -321,6 +322,9 @@ namespace netplus { // renegotiation_info if (et == 0xFF01) secureReneg = true; // extended_master_secret (RFC 7627) if (et == 0x0017 && el == 0) extMasterSecret = true; // supported_versions if (et == 0x002b) { if (el < 3) throwSSL(NetException::Error, "supported_versions too short"); Loading Loading @@ -420,6 +424,7 @@ namespace netplus { // store flags client_offered_tls13 = offeredTLS13; secure_reneg = secureReneg; extended_master_secret = extMasterSecret; auto hasSuite = [&](uint16_t s) { for (auto cs : clientSuites) if (cs == s) return true; Loading Loading @@ -754,17 +759,20 @@ namespace netplus { body.push_back((chosenSuite >> 8) & 0xFF); body.push_back((chosenSuite >> 0) & 0xFF); body.push_back(0x00); // null compression // renegotiation_info if (secure_reneg) { { std::vector<uint8_t> exts; if (secure_reneg) { exts.push_back(0xFF); exts.push_back(0x01); exts.push_back(0x00); exts.push_back(0x01); exts.push_back(0x00); } if (extended_master_secret) { exts.push_back(0x00); exts.push_back(0x17); exts.push_back(0x00); exts.push_back(0x00); } body.push_back((exts.size() >> 8) & 0xFF); body.push_back((exts.size() >> 0) & 0xFF); body.insert(body.end(), exts.begin(), exts.end()); } else { body.push_back(0x00); body.push_back(0x00); } sendHandshake(0x02, body); } Loading Loading @@ -1172,10 +1180,20 @@ namespace netplus { preMaster = extractPreMasterFromPkcs1(pkcs1); } // master_secret = PRF(PMS, "master secret", client_random || server_random) // Add CKE to transcript so session_hash covers it (RFC 5246 + RFC 7627) handshake_transcript.insert(handshake_transcript.end(), msg.begin(), msg.end()); // master_secret derivation if (extended_master_secret) { // RFC 7627: master_secret = PRF(PMS, "extended master secret", session_hash) std::vector<uint8_t> sessionHash = sha256_hash(handshake_transcript); masterSecret = prf(preMaster, "extended master secret", sessionHash, 48); } else { // RFC 5246: master_secret = PRF(PMS, "master secret", ClientRandom || ServerRandom) std::vector<uint8_t> msSeed = clientRandom; msSeed.insert(msSeed.end(), serverRandom.begin(), serverRandom.end()); masterSecret = prf(preMaster, "master secret", msSeed, 48); } // key_block = PRF(master, "key expansion", server_random || client_random) std::vector<uint8_t> kbSeed = serverRandom; Loading Loading @@ -1765,12 +1783,12 @@ namespace netplus { } // extended_master_secret (RFC 7627) if (et == 0x0017 && el == 0) extended_master_secret = true; eoff += el; } // NOTE: ServerHello was already added to transcript by fetchNextHandshakePlain() // Do NOT add it again here! if (tls13) { if (!client_offered_tls13 || !tls13_got_key_share){ NetException e; Loading Loading @@ -1847,6 +1865,9 @@ namespace netplus { // Save server's session_id for future resumption client_session_id = server_sid; // Add ServerHello to transcript (RFC 5246) handshake_transcript.insert(handshake_transcript.end(), sh.begin(), sh.end()); hs_state = HsState::CLI_WAIT_CERT; break; } Loading Loading @@ -2142,6 +2163,9 @@ namespace netplus { } } // Add Certificate to transcript (RFC 5246) handshake_transcript.insert(handshake_transcript.end(), certMsg.begin(), certMsg.end()); hs_state = server_cert_is_ecdsa ? HsState::CLI_TLS12_WAIT_SKE : HsState::CLI_WAIT_SHD; break; } Loading Loading @@ -2197,6 +2221,9 @@ namespace netplus { tls12_srv_ecdhe_pub.assign(msg.begin() + off, msg.begin() + off + pubkey_len); // Signature is after the key — skip verification (like cert verification) // Add ServerKeyExchange to transcript (RFC 5246) handshake_transcript.insert(handshake_transcript.end(), msg.begin(), msg.end()); hs_state = HsState::CLI_WAIT_SHD; break; } Loading Loading @@ -2224,6 +2251,9 @@ namespace netplus { throw e; } // Add ServerHelloDone to transcript (RFC 5246) handshake_transcript.insert(handshake_transcript.end(), msg.begin(), msg.end()); hs_state = HsState::CLI_SEND_CKE; break; } Loading Loading @@ -2299,10 +2329,16 @@ namespace netplus { sendHandshake(0x10, ckeBody); // Derive master_secret // Derive master_secret (sendHandshake above already added CKE to transcript) if (extended_master_secret) { // RFC 7627: master_secret = PRF(PMS, "extended master secret", session_hash) std::vector<uint8_t> sessionHash = sha256_hash(handshake_transcript); masterSecret = prf(preMaster, "extended master secret", sessionHash, 48); } else { std::vector<uint8_t> msSeed = clientRandom; msSeed.insert(msSeed.end(), serverRandom.begin(), serverRandom.end()); masterSecret = prf(preMaster, "master secret", msSeed, 48); } // Derive key_block std::vector<uint8_t> kbSeed = serverRandom; Loading Loading @@ -4033,6 +4069,12 @@ namespace netplus { exts.push_back(0x00); } if (extended_master_secret) { // extended_master_secret (RFC 7627): type=0x0017, length=0x0000 (empty) exts.push_back(0x00); exts.push_back(0x17); exts.push_back(0x00); exts.push_back(0x00); } // Write extensions length (always present in TLS1.2 ServerHello!) body.push_back((exts.size() >> 8) & 0xFF); body.push_back((exts.size() >> 0) & 0xFF); Loading Loading @@ -4728,6 +4770,10 @@ namespace netplus { } } // extended_master_secret (RFC 7627): type=0x0017, length=0x0000 (empty data) exts.push_back(0x00); exts.push_back(0x17); exts.push_back(0x00); exts.push_back(0x00); // Mark that we offered TLS 1.3 (only when not in TLS 1.2-only mode) client_offered_tls13 = !client_tls12_only; Loading
src/crypto/tls.h +1 −0 Original line number Diff line number Diff line Loading @@ -416,6 +416,7 @@ namespace netplus { bool handshakeStarted = false; bool handshakeDone = false; bool secure_reneg = true; bool extended_master_secret = false; bool ccs_received = false; bool cli_cke_sent = false; bool cli_ccs_fin_sent = false; Loading