Commit 96f1a2b4 authored by jan.koester's avatar jan.koester
Browse files

tes

parent 9a55719a
Loading
Loading
Loading
Loading
+176 −50
Original line number Diff line number Diff line
@@ -763,6 +763,10 @@ void netplus::ssl::_sendHandshake(uint8_t type, const std::vector<uint8_t>& data
    handshake.push_back(data.size() & 0xFF);
    handshake.insert(handshake.end(), data.begin(), data.end());

    std::cerr << "[TRANSCRIPT] _sendHandshake type=0x" << std::hex << int(type) << std::dec 
              << " adding " << handshake.size() << " bytes, transcript was " 
              << csock->_handshake_transcript.size() << "\n";

    // IMPORTANT: Add the Handshake Layer to the transcript for Finished verification
    csock->_handshake_transcript.insert(csock->_handshake_transcript.end(),
                                    handshake.begin(), handshake.end());
@@ -993,29 +997,6 @@ void netplus::ssl::accept(std::unique_ptr<socket>& csock, bool nonblock)
        cssock->setNonBlock();
}

// --- oben in ssl.cpp (oder anonym namespace) ---
static inline const char* tlsRecTypeName(uint8_t ct) {
    switch (ct) {
        case 0x14: return "change_cipher_spec";
        case 0x15: return "alert";
        case 0x16: return "handshake";
        case 0x17: return "application_data";
        default:   return "unknown";
    }
}

static inline const char* hsTypeName(uint8_t ht) {
    switch (ht) {
        case 0x01: return "ClientHello";
        case 0x02: return "ServerHello";
        case 0x08: return "EncryptedExtensions";
        case 0x0b: return "Certificate";
        case 0x0f: return "CertificateVerify";
        case 0x14: return "Finished";
        default:   return "UnknownHS";
    }
}

// no-op debug helper (can be enabled for troubleshooting)
static inline void dumpHex(const char*, const uint8_t*, size_t, size_t = 64) {}

@@ -1033,7 +1014,6 @@ std::vector<uint8_t> netplus::ssl::_fetchNextHandshakePlain()
        // 1) already buffered handshake message?
        // --------------------------------------------------------
        if (_rx_handshake_buf.size() >= 4) {
            uint8_t  ht  = _rx_handshake_buf[0];
            uint32_t len =
                (uint32_t(_rx_handshake_buf[1]) << 16) |
                (uint32_t(_rx_handshake_buf[2]) <<  8) |
@@ -1045,6 +1025,10 @@ std::vector<uint8_t> netplus::ssl::_fetchNextHandshakePlain()
                _rx_handshake_buf.erase(_rx_handshake_buf.begin(),
                                        _rx_handshake_buf.begin() + 4 + len);

                std::cerr << "[TRANSCRIPT] _fetchNextHandshakePlain type=0x" << std::hex << int(msg[0]) << std::dec
                          << " adding " << msg.size() << " bytes, transcript was "
                          << _handshake_transcript.size() << "\n";

                // transcript: handshake messages only
                _handshake_transcript.insert(_handshake_transcript.end(),
                                             msg.begin(), msg.end());
@@ -1203,8 +1187,10 @@ std::vector<uint8_t> netplus::ssl::_fetchNextHandshakeTLS13()
    uint64_t seq = _tls13_hs_recv_seq;

    // build nonce = iv XOR seq
    // When receiving: client uses s2c IV, server uses c2s IV
    uint8_t nonce[12]={0};
    tls13_make_nonce(nonce, _tls13_hs_iv_s2c, seq);
    const uint8_t* recv_iv = _is_client ? _tls13_hs_iv_s2c : _tls13_hs_iv_c2s;
    tls13_make_nonce(nonce, recv_iv, seq);

    // AAD = record header (type=23, legacy_version=0x0303, length = ciphertext_length)
    uint8_t aad[5];
@@ -1287,8 +1273,20 @@ std::vector<uint8_t> netplus::ssl::_tls13_read_record_handshake()
        throwSSL(NetException::Error, "TLS1.3 hs recv AEAD not initialized");

    // nonce = iv XOR seq
    // When receiving: client uses s2c IV, server uses c2s IV
    uint8_t nonce[12];
    tls13_make_nonce(nonce, _tls13_hs_iv_c2s, _tls13_hs_recv_seq++);
    const uint8_t* recv_iv = _is_client ? _tls13_hs_iv_s2c : _tls13_hs_iv_c2s;
    uint64_t seq_used = _tls13_hs_recv_seq++;
    tls13_make_nonce(nonce, recv_iv, seq_used);

    std::cerr << "[RECV-HS] _is_client=" << _is_client << " seq=" << seq_used << "\n";
    std::cerr << "[RECV-HS] recv_iv: ";
    for(int i=0;i<12;i++) std::cerr << std::hex << std::setw(2) << std::setfill('0') << int(recv_iv[i]);
    std::cerr << std::dec << "\n";
    std::cerr << "[RECV-HS] nonce:   ";
    for(int i=0;i<12;i++) std::cerr << std::hex << std::setw(2) << std::setfill('0') << int(nonce[i]);
    std::cerr << std::dec << "\n";
    std::cerr << "[RECV-HS] ct_len=" << ct_len << " data_len=" << data_len << "\n";

    // AAD = outer header with length=data_len
    uint8_t aad[5];
@@ -1528,24 +1526,6 @@ void netplus::ssl::handshake_after_accept(){
        throw e;
    };

    auto hsStateName = [&](netplus::ssl::HsState s) {
        switch(s){
            case netplus::ssl::HsState::IDLE: return "IDLE";
            case netplus::ssl::HsState::READ_CLIENT_HELLO: return "READ_CLIENT_HELLO";
            case netplus::ssl::HsState::TLS13_SEND_SERVER_HELLO: return "TLS13_SEND_SERVER_HELLO";
            case netplus::ssl::HsState::TLS13_SEND_ENCRYPTED_FLIGHT: return "TLS13_SEND_ENCRYPTED_FLIGHT";
            case netplus::ssl::HsState::TLS13_WAIT_CLIENT_FINISHED: return "TLS13_WAIT_CLIENT_FINISHED";
            case netplus::ssl::HsState::SEND_SERVER_FLIGHT: return "SEND_SERVER_FLIGHT";
            case netplus::ssl::HsState::WAIT_CKE: return "WAIT_CKE";
            case netplus::ssl::HsState::WAIT_CCS: return "WAIT_CCS";
            case netplus::ssl::HsState::WAIT_FIN: return "WAIT_FIN";
            case netplus::ssl::HsState::SEND_CCS_FIN: return "SEND_CCS_FIN";
            case netplus::ssl::HsState::DONE: return "DONE";
            case netplus::ssl::HsState::FAIL: return "FAIL";
            default: return "???";
        }
    };

    auto gen_tls13_p256_scalar = [&](uint8_t out_priv[32]) {
        for (;;) {
            netplus::fillRandomBytes(out_priv, 32);
@@ -1801,6 +1781,9 @@ void netplus::ssl::handshake_after_accept(){
                _is_tls13 = true;
                _chosenSuite = tls13Suite;
                _secure_reneg = false;
                
                // NOTE: ClientHello already added to transcript by _fetchNextHandshakePlain()
                
                _hs_state = HsState::TLS13_SEND_SERVER_HELLO;
                TLSDBG("TLS1.3 selected suite=" << std::hex << _chosenSuite
       << " group=" << _selected_group);
@@ -2450,6 +2433,9 @@ void netplus::ssl::handshake_after_accept(){
                server_pub
            );

            std::cerr << "[TRANSCRIPT] Server adding ServerHello " << hs.size() << " bytes, transcript was "
                      << _handshake_transcript.size() << "\n";

            // transcript includes plaintext SH
            _handshake_transcript.insert(_handshake_transcript.end(), hs.begin(), hs.end());

@@ -2701,6 +2687,14 @@ void netplus::ssl::_tls13_derive_handshake_keys(const std::vector<uint8_t>& ecdh
    if (th.size() != 32)
        throwSSL(NetException::Error, "TLS1.3: transcript hash wrong size");

    std::cerr << "[DERIVE-HS] ecdhe_shared: ";
    for(auto b : ecdhe_shared) std::cerr << std::hex << std::setw(2) << std::setfill('0') << int(b);
    std::cerr << std::dec << "\n";
    std::cerr << "[DERIVE-HS] transcript_len=" << _handshake_transcript.size() << "\n";
    std::cerr << "[DERIVE-HS] transcript_hash: ";
    for(auto b : th) std::cerr << std::hex << std::setw(2) << std::setfill('0') << int(b);
    std::cerr << std::dec << "\n";

    std::vector<uint8_t> zeros(32, 0x00);
    
    // SHA-256 hash of empty string - needed for "derived" context per RFC 8446
@@ -2728,6 +2722,12 @@ void netplus::ssl::_tls13_derive_handshake_keys(const std::vector<uint8_t>& ecdh
    std::vector<uint8_t> s_key = _hkdf_expand_label(_tls13_s_hs_secret, "key", empty, 16);
    std::vector<uint8_t> s_iv  = _hkdf_expand_label(_tls13_s_hs_secret, "iv",  empty, 12);

    std::cerr << "[DERIVE-HS] _is_client=" << _is_client << "\n";
    std::cerr << "[DERIVE-HS] c_key: "; for(auto b:c_key) std::cerr << std::hex << std::setw(2) << std::setfill('0') << int(b); std::cerr << "\n";
    std::cerr << "[DERIVE-HS] c_iv:  "; for(auto b:c_iv) std::cerr << std::hex << std::setw(2) << std::setfill('0') << int(b); std::cerr << "\n";
    std::cerr << "[DERIVE-HS] s_key: "; for(auto b:s_key) std::cerr << std::hex << std::setw(2) << std::setfill('0') << int(b); std::cerr << "\n";
    std::cerr << "[DERIVE-HS] s_iv:  "; for(auto b:s_iv) std::cerr << std::hex << std::setw(2) << std::setfill('0') << int(b); std::cerr << std::dec << "\n";

    // reset handshake record seq
    _tls13_hs_send_seq = 0;
    _tls13_hs_recv_seq = 0;
@@ -2967,9 +2967,21 @@ void netplus::ssl::handshake_after_connect(){
                std::vector<uint8_t> sh;
                sh = _fetchNextHandshakePlain();

                // Handle would-block: _fetchNextHandshakePlain returns empty if no data ready
                if (sh.empty()) {
                    note("ssl::handshake_after_connect: wait ServerHello");
                }

                const uint8_t* p = sh.data();
                size_t n = sh.size();

                std::cerr << "[CLI-SH] ServerHello size=" << n << " type=0x" << std::hex << (n>0?int(p[0]):-1) << std::dec << "\n";
                if (n >= 5) {
                    std::cerr << "[CLI-SH] first 5 bytes: ";
                    for(size_t i=0;i<5;i++) std::cerr << std::hex << std::setw(2) << std::setfill('0') << int(p[i]) << " ";
                    std::cerr << std::dec << "\n";
                }

                if (n < 4 + 2 + 32 + 1 + 2 + 1) {
                    NetException e;
                    e[NetException::Error] << "ServerHello too short";
@@ -2978,6 +2990,9 @@ void netplus::ssl::handshake_after_connect(){

                size_t off = 4; // skip handshake header

                // legacy_version (2 bytes: 0x03, 0x03)
                off += 2;

                // server_random (32)
                _serverRandom.assign(p + off, p + off + 32);
                off += 32;
@@ -3125,10 +3140,8 @@ void netplus::ssl::handshake_after_connect(){
                    eoff += el;
                }

                // transcript: include ClientHello + ServerHello for TLS1.3
                // NOTE: you must have already appended ClientHello earlier when sending it.
                // We'll append ServerHello now:
                _handshake_transcript.insert(_handshake_transcript.end(), sh.begin(), sh.end());
                // 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){
@@ -3147,9 +3160,8 @@ void netplus::ssl::handshake_after_connect(){
                        throw e;
                    }

                    _handshake_transcript.insert(_handshake_transcript.end(), sh.begin(), sh.end());

                    // Derive TLS1.3 handshake keys from ECDHE shared
                    // (transcript already includes ClientHello + ServerHello from above)
                    _tls13_derive_handshake_keys(ecdhe_shared);

                    // switch to TLS 1.3 handshake path
@@ -3229,6 +3241,112 @@ void netplus::ssl::handshake_after_connect(){
                _hs_state = HsState::CLI_TLS13_WAIT_CERT_VERIFY;
                break;
            }

            // ---------------------------
            // TLS 1.3: wait CertificateVerify (type 0x0f)
            // ---------------------------
            case HsState::CLI_TLS13_WAIT_CERT_VERIFY:
            {
                if (_rx_handshake_buf.empty() || _rx_handshake_off >= _rx_handshake_buf.size()) {
                    _rx_handshake_buf = _tls13_read_record_handshake();
                    _rx_handshake_off = 0;
                }

                std::vector<uint8_t> msg;
                if (!_tls13_pop_hs_from_buf(msg)) {
                    _rx_handshake_buf = _tls13_read_record_handshake();
                    _rx_handshake_off = 0;
                    if (!_tls13_pop_hs_from_buf(msg))
                        note("ssl::handshake_after_connect: wait TLS1.3 CertificateVerify");
                }

                if (msg.size() < 4 || msg[0] != 0x0f) {
                    NetException e;
                    e[NetException::Error] << "TLS1.3 expected CertificateVerify got " << int(msg.empty()? -1 : msg[0]);
                    throw e;
                }

                // transcript add
                _handshake_transcript.insert(_handshake_transcript.end(), msg.begin(), msg.end());

                // TODO: verify RSA-PSS signature over transcript
                // For now, skip verification

                _hs_state = HsState::CLI_TLS13_WAIT_FINISHED;
                break;
            }

            // ---------------------------
            // TLS 1.3: wait server Finished (type 0x14)
            // ---------------------------
            case HsState::CLI_TLS13_WAIT_FINISHED:
            {
                if (_rx_handshake_buf.empty() || _rx_handshake_off >= _rx_handshake_buf.size()) {
                    _rx_handshake_buf = _tls13_read_record_handshake();
                    _rx_handshake_off = 0;
                }

                std::vector<uint8_t> msg;
                if (!_tls13_pop_hs_from_buf(msg)) {
                    _rx_handshake_buf = _tls13_read_record_handshake();
                    _rx_handshake_off = 0;
                    if (!_tls13_pop_hs_from_buf(msg))
                        note("ssl::handshake_after_connect: wait TLS1.3 server Finished");
                }

                if (msg.size() < 4 || msg[0] != 0x14) {
                    NetException e;
                    e[NetException::Error] << "TLS1.3 expected server Finished got " << int(msg.empty()? -1 : msg[0]);
                    throw e;
                }

                // Save transcript hash BEFORE adding server Finished (for client Finished)
                std::vector<uint8_t> th_before_sfin = sha256_hash(_handshake_transcript);

                // transcript add server Finished
                _handshake_transcript.insert(_handshake_transcript.end(), msg.begin(), msg.end());

                // TODO: verify server Finished verify_data
                // For now, skip verification

                // Derive application keys using transcript AFTER server Finished
                _tls13_derive_application_keys();

                _hs_state = HsState::CLI_TLS13_SEND_FINISHED;
                break;
            }

            // ---------------------------
            // TLS 1.3: send client Finished
            // ---------------------------
            case HsState::CLI_TLS13_SEND_FINISHED:
            {
                // Build client Finished verify_data
                std::vector<uint8_t> th = sha256_hash(_handshake_transcript);
                std::vector<uint8_t> empty;
                std::vector<uint8_t> finished_key = _hkdf_expand_label(_tls13_c_hs_secret, "finished", empty, 32);
                std::vector<uint8_t> verify_data = _hmac_sha256(finished_key, th);

                // Build Finished handshake message (type 0x14)
                std::vector<uint8_t> fin_msg;
                fin_msg.push_back(0x14);
                fin_msg.push_back(0x00);
                fin_msg.push_back(0x00);
                fin_msg.push_back(0x20); // 32 bytes
                fin_msg.insert(fin_msg.end(), verify_data.begin(), verify_data.end());

                // Add to transcript before sending
                _handshake_transcript.insert(_handshake_transcript.end(), fin_msg.begin(), fin_msg.end());

                // Send encrypted with handshake keys
                _tls13_send_record(0x16, fin_msg, /*handshake_keys=*/true);
                flush_out();

                _handshakeDone = true;
                _hs_state = HsState::DONE;
                return;
            }

            // ---------------------------
            // 3) wait Certificate
            // ---------------------------
@@ -3767,6 +3885,14 @@ void netplus::ssl::_tls13_send_record(uint8_t inner_type,
        s >>= 8;
    }

    std::cerr << "[SEND-REC] _is_client=" << _is_client << " hs_keys=" << handshake_keys << " seq=" << seq << "\n";
    std::cerr << "[SEND-REC] base_iv: ";
    for(int i=0;i<12;i++) std::cerr << std::hex << std::setw(2) << std::setfill('0') << int(base_iv[i]);
    std::cerr << std::dec << "\n";
    std::cerr << "[SEND-REC] nonce:   ";
    for(int i=0;i<12;i++) std::cerr << std::hex << std::setw(2) << std::setfill('0') << int(nonce[i]);
    std::cerr << std::dec << "\n";

    // ------------------------------------------------------------
    // Outer TLSCiphertext header (this is the AEAD AAD)
    // Protected record always has outer content type 0x17