Commit 94d9caa2 authored by jan.koester's avatar jan.koester
Browse files

test

parent 92854f14
Loading
Loading
Loading
Loading
+89 −88
Original line number Diff line number Diff line
@@ -445,7 +445,7 @@ namespace netplus {

    static inline std::string hexDump(const std::vector<uint8_t>& v, size_t max = 64) {
        std::ostringstream oss;
        size_t n = std::min(v.size(), max);
        size_t n = (std::min)(v.size(), max);
        for (size_t i = 0; i < n; ++i) {
            oss << std::hex << std::setw(2) << std::setfill('0') << int(v[i]);
        }
@@ -1488,16 +1488,16 @@ void netplus::ssl::connect(std::unique_ptr<socket>& srvsock)
        throw e;
    };

    // ============================================================
    // 0) TCP CONNECT
    // this = real IO socket
    // srvsock = config/target socket (host/port)
    // ============================================================
    // ------------------------------------------------------------
    // 0) Establish underlying TCP connection
    // ------------------------------------------------------------
    // "this" is the real IO socket (the one the caller uses for send/recv).
    // srvsock holds the target config (addr/port/opts).
    tcp::connect(srvsock);

    // ============================================================
    // 1) RESET TLS STATE (MUST RESET THIS OBJECT)
    // ============================================================
    // ------------------------------------------------------------
    // 1) Reset TLS state on THIS object
    // ------------------------------------------------------------
    _send_seq = 0;
    _recv_seq = 0;
    _handshakeDone = false;
@@ -1514,20 +1514,21 @@ void netplus::ssl::connect(std::unique_ptr<socket>& srvsock)

    _rx_netbuf.clear();
    _rx_handshake_buffer.clear();

    _recv_record.clear();
    _recv_off = 0;

    _send_record.clear();
    _send_off = 0;

    // ============================================================
    // 2) HANDSHAKE REASSEMBLY HELPER
    // ============================================================
    // ------------------------------------------------------------
    // Helper: read & reassemble handshake messages
    // ------------------------------------------------------------
    std::vector<uint8_t> hs_buf;

    auto readHandshakeMessage = [&]() -> std::vector<uint8_t> {
        for (;;) {
    auto readHandshakeMessage = [&]() -> std::vector<uint8_t>
    {
        for (;;)
        {
            if (hs_buf.size() >= 4) {
                uint32_t mlen =
                    (uint32_t(hs_buf[1]) << 16) |
@@ -1538,7 +1539,7 @@ void netplus::ssl::connect(std::unique_ptr<socket>& srvsock)
                    std::vector<uint8_t> msg(hs_buf.begin(), hs_buf.begin() + 4 + mlen);
                    hs_buf.erase(hs_buf.begin(), hs_buf.begin() + 4 + mlen);

                    // transcript contains handshake messages only (type+len+body)
                    // transcript contains handshake msg bytes only
                    _handshake_transcript.insert(_handshake_transcript.end(),
                                                 msg.begin(), msg.end());
                    return msg;
@@ -1546,31 +1547,34 @@ void netplus::ssl::connect(std::unique_ptr<socket>& srvsock)
            }

            std::vector<uint8_t> rec = readTlsRecord(this);
            if (rec.size() < 5) throwSSL(netplus::NetException::Error, "TLS record too short");
            if (rec.size() < 5)
                throwSSL(netplus::NetException::Error, "TLS record too short");

            uint8_t ct = rec[0];

            if (ct == 0x16) {
                // Handshake record
                // handshake record fragment
                hs_buf.insert(hs_buf.end(), rec.begin() + 5, rec.end());
                continue;
            }

            if (ct == 0x14) {
                // CCS not in transcript
                // CCS not in transcript, just ignore here
                continue;
            }

            if (ct == 0x15) {
                throwSSL(netplus::NetException::Error, "TLS Alert during handshake");
            }

            throwSSL(netplus::NetException::Error,
                     "Unexpected TLS record type during handshake: " + std::to_string(int(ct)));
                     "Unexpected TLS record during handshake type=" + std::to_string(int(ct)));
        }
    };

    // ============================================================
    // 3) SEND CLIENTHELLO
    // ============================================================
    // ------------------------------------------------------------
    // 2) Send ClientHello
    // ------------------------------------------------------------
    {
        std::vector<uint8_t> ch;

@@ -1585,25 +1589,25 @@ void netplus::ssl::connect(std::unique_ptr<socket>& srvsock)
        }
        ch.insert(ch.end(), _clientRandom.begin(), _clientRandom.end());

        // session id length
        // session id len
        ch.push_back(0x00);

        // cipher suites (include SCSV + RSA AES128/256 SHA1)
        // cipher suites: SCSV + AES128-SHA + AES256-SHA
        std::vector<uint8_t> suites = {
            0x00, 0xFF, // renegotiation SCSV
            0x00, 0x2F, // TLS_RSA_WITH_AES_128_CBC_SHA
            0x00, 0x35  // TLS_RSA_WITH_AES_256_CBC_SHA
            0x00, 0xFF,
            0x00, 0x2F,
            0x00, 0x35
        };

        ch.push_back(uint8_t((suites.size() >> 8) & 0xFF));
        ch.push_back(uint8_t(suites.size() & 0xFF));
        ch.insert(ch.end(), suites.begin(), suites.end());

        // compression: null
        // compression null
        ch.push_back(0x01);
        ch.push_back(0x00);

        // extensions: renegotiation_info
        // extension renegotiation_info (RFC 5746)
        {
            std::vector<uint8_t> exts;
            exts.push_back(0xFF); exts.push_back(0x01);
@@ -1618,9 +1622,9 @@ void netplus::ssl::connect(std::unique_ptr<socket>& srvsock)
        _sendHandshake(0x01, ch, this);
    }

    // ============================================================
    // 4) READ SERVERHELLO
    // ============================================================
    // ------------------------------------------------------------
    // 3) Read ServerHello
    // ------------------------------------------------------------
    std::vector<uint8_t> sh = readHandshakeMessage();
    if (sh.empty() || sh[0] != 0x02)
        throwSSL(netplus::NetException::Error, "Expected ServerHello");
@@ -1628,12 +1632,11 @@ void netplus::ssl::connect(std::unique_ptr<socket>& srvsock)
    if (sh.size() < 4 + 2 + 32 + 1)
        throwSSL(netplus::NetException::Error, "ServerHello too short");

    _serverRandom.assign(sh.begin() + 4 + 2,
                         sh.begin() + 4 + 2 + 32);
    _serverRandom.assign(sh.begin() + 4 + 2, sh.begin() + 4 + 2 + 32);

    // ============================================================
    // 5) READ CERTIFICATE (LEAF)
    // ============================================================
    // ------------------------------------------------------------
    // 4) Read Certificate
    // ------------------------------------------------------------
    std::vector<uint8_t> certMsg = readHandshakeMessage();
    if (certMsg.empty() || certMsg[0] != 0x0b)
        throwSSL(netplus::NetException::Error, "Expected Certificate");
@@ -1649,7 +1652,7 @@ void netplus::ssl::connect(std::unique_ptr<socket>& srvsock)
    p += 3;

    if (p + listLen > certMsg.size())
        throwSSL(netplus::NetException::Error, "Malformed certificate list");
        throwSSL(netplus::NetException::Error, "Malformed certificate_list");

    uint32_t cLen =
        (uint32_t(certMsg[p]) << 16) |
@@ -1666,36 +1669,36 @@ void netplus::ssl::connect(std::unique_ptr<socket>& srvsock)
    serverCert.loadFromBuffer(rawCert);
    _peer_cert = serverCert;

    // ============================================================
    // 6) READ UNTIL SERVERHELLODONE
    // ============================================================
    // ------------------------------------------------------------
    // 5) Read until ServerHelloDone
    // ------------------------------------------------------------
    for (;;) {
        std::vector<uint8_t> msg = readHandshakeMessage();
        if (msg.empty()) throwSSL(netplus::NetException::Error, "Empty handshake message");
        if (msg.empty())
            throwSSL(netplus::NetException::Error, "Unexpected empty handshake msg");

        uint8_t t = msg[0];
        if (t == 0x0e) break; // ServerHelloDone

        if (t == 0x0c)
            throwSSL(netplus::NetException::Error,
                     "ServerKeyExchange received: server requires (EC)DHE; RSA not supported");
                     "ServerKeyExchange received: server uses (EC)DHE; RSA only client");
        if (t == 0x0d)
            throwSSL(netplus::NetException::Error,
                     "CertificateRequest received: client auth not supported");

        throwSSL(netplus::NetException::Error,
                 "Unexpected handshake msg type: " + std::to_string(int(t)));
                 "Unexpected handshake msg type=" + std::to_string(int(t)));
    }

    // ============================================================
    // 7) CLIENTKEYEXCHANGE (RSA PKCS#1 v1.5)
    // ============================================================
    // ------------------------------------------------------------
    // 6) ClientKeyExchange (RSA)
    // ------------------------------------------------------------
    netplus::rsa serverPubKey;
    serverCert.extractPublicKey(serverPubKey);

    std::vector<uint8_t> preMaster(48);
    preMaster[0] = 0x03; preMaster[1] = 0x03;

    preMaster[0] = 0x03; preMaster[1] = 0x03; // TLS 1.2
    {
        std::random_device rd;
        for (size_t i = 2; i < preMaster.size(); ++i)
@@ -1706,10 +1709,8 @@ void netplus::ssl::connect(std::unique_ptr<socket>& srvsock)
    if (kBytes < 11 + preMaster.size())
        throwSSL(netplus::NetException::Error, "server RSA key too small");

    // PKCS#1 v1.5: 0x00 0x02 PS 0x00 PMS
    std::vector<uint8_t> em(kBytes, 0x00);
    em[0] = 0x00;
    em[1] = 0x02;
    em[0] = 0x00; em[1] = 0x02;

    {
        std::random_device rd;
@@ -1734,11 +1735,10 @@ void netplus::ssl::connect(std::unique_ptr<socket>& srvsock)

    _sendHandshake(0x10, cke, this);

    // ============================================================
    // 8) KEY DERIVATION (TLS_RSA_WITH_AES_128_CBC_SHA)
    // ============================================================
    // ------------------------------------------------------------
    // 7) Key Derivation
    // ------------------------------------------------------------
    std::vector<uint8_t> masterSecret;

    {
        std::vector<uint8_t> seed = _clientRandom;
        seed.insert(seed.end(), _serverRandom.begin(), _serverRandom.end());
@@ -1758,24 +1758,26 @@ void netplus::ssl::connect(std::unique_ptr<socket>& srvsock)
        _aes_recv = std::make_unique<aes>(serverKey);
    }

    if (!_aes || !_aes_recv)
        throwSSL(netplus::NetException::Error, "AES contexts not initialized");

    // ============================================================
    // 9) SEND CHANGE CIPHER SPEC (raw)
    // ============================================================
    // ------------------------------------------------------------
    // 8) Send ChangeCipherSpec (portable send)
    // ------------------------------------------------------------
    {
        static const uint8_t ccs[6] = { 0x14, 0x03, 0x03, 0x00, 0x01, 0x01 };
        ssize_t w = ::send(fd(), ccs, sizeof(ccs), MSG_NOSIGNAL);
        if (w != (ssize_t)sizeof(ccs))

#ifdef _WIN32
        int w = ::send((SOCKET)fd(), (const char*)ccs, (int)sizeof(ccs), 0);
#else
        int w = (int)::send(fd(), ccs, sizeof(ccs), MSG_NOSIGNAL);
#endif
        if (w != (int)sizeof(ccs))
            throwSSL(netplus::NetException::Error, "CCS send failed");

        _send_seq = 0;
    }

    // ============================================================
    // 10) SEND FINISHED (encrypted handshake record)
    // ============================================================
    // ------------------------------------------------------------
    // 9) Send Finished (encrypted)
    // ------------------------------------------------------------
    {
        std::vector<uint8_t> th = _sha256_hash(_handshake_transcript);
        std::vector<uint8_t> verify = _prf(masterSecret, "client finished", th, 12);
@@ -1783,18 +1785,19 @@ void netplus::ssl::connect(std::unique_ptr<socket>& srvsock)
        std::vector<uint8_t> fin = { 0x14, 0x00, 0x00, 0x0c };
        fin.insert(fin.end(), verify.begin(), verify.end());

        // Finished is a handshake message: add to transcript BEFORE verifying server finished
        // Finished is part of transcript BEFORE verifying server finished
        _handshake_transcript.insert(_handshake_transcript.end(), fin.begin(), fin.end());

        _sendEncryptedRecord(this, 0x16, fin);
    }

    // ============================================================
    // 11) RECEIVE SERVER CCS
    // ============================================================
    // ------------------------------------------------------------
    // 10) Wait for Server CCS
    // ------------------------------------------------------------
    for (;;) {
        std::vector<uint8_t> rec = readTlsRecord(this);
        if (rec.empty()) throwSSL(netplus::NetException::Error, "EOF waiting for server CCS");
        if (rec.empty())
            throwSSL(netplus::NetException::Error, "EOF waiting server CCS");

        if (rec[0] == 0x14) {
            if (rec.size() < 6 || rec[5] != 0x01)
@@ -1802,13 +1805,14 @@ void netplus::ssl::connect(std::unique_ptr<socket>& srvsock)
            break;
        }
        if (rec[0] == 0x15)
            throwSSL(netplus::NetException::Error, "Alert while waiting for server CCS");
            throwSSL(netplus::NetException::Error, "Server Alert waiting CCS");
    }

    _recv_seq = 0;

    // ============================================================
    // 12) RECEIVE + VERIFY SERVER FINISHED
    // ============================================================
    // ------------------------------------------------------------
    // 11) Receive + verify Server Finished
    // ------------------------------------------------------------
    {
        std::vector<uint8_t> sfinRec = readTlsRecord(this);
        if (sfinRec.size() < 5 || sfinRec[0] != 0x16)
@@ -1829,9 +1833,6 @@ void netplus::ssl::connect(std::unique_ptr<socket>& srvsock)
            throwSSL(netplus::NetException::Error, "Server Finished verify_data mismatch");
    }

    // ============================================================
    // 13) DONE
    // ============================================================
    _handshakeDone = true;
}

@@ -2936,7 +2937,7 @@ bool netplus::ssl::handshakeStepIOCP()
        std::vector<uint8_t> frag(rec.begin() + 5, rec.end());

        // Your decrypt increments _recv_seq after verifying MAC
        std::vector<uint8_t> finPT = _decryptRecordCBC(this, 0x16, 0x0303, frag);
        std::vector<uint8_t> finPT = _decryptRecordCBC(0x16, 0x0303, frag);

        // Structure: 0x14 00 00 0C + 12 bytes
        if (finPT.size() != 4 + 12 || finPT[0] != 0x14 || finPT[1] != 0x00 || finPT[2] != 0x00 || finPT[3] != 0x0c) {