Commit 25f6b1f8 authored by jan.koester's avatar jan.koester
Browse files

good news

parent 00f2b4a2
Loading
Loading
Loading
Loading
+205 −149
Original line number Diff line number Diff line
@@ -11,42 +11,45 @@ namespace netplus {

// b coefficient (NORMAL domain literal, then converted once into Montgomery)

static const u256 P256_B_STD = {
    0x27D2604B, 0x3BCE3C3E, 0xCC53B0F6, 0x651D06B0,
    0x769886BC, 0xB3EBBD55, 0xAA3A93E7, 0x5AC635D8
static const uint8_t P256_B_BE[32] = {
  0x5a,0xc6,0x35,0xd8,0xaa,0x3a,0x93,0xe7,
  0xb3,0xeb,0xbd,0x55,0x76,0x98,0x86,0xbc,
  0x65,0x1d,0x06,0xb0,0xcc,0x53,0xb0,0xf6,
  0x3b,0xce,0x3c,0x3e,0x27,0xd2,0x60,0x4b
};

const u256 P256_B = to_mont(P256_B_STD);
const u256 P256_B = bytes_be_to_u256(P256_B_BE);

// ------------------------------------------------------------
// Base point G (Generator) in Montgomery domain
// ------------------------------------------------------------
// NIST P-256 / secp256r1 base point G (uncompressed)
// Gx = 6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296
// Gy = 4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5

// Base point in standard (normal) representation
// Standard basepoint (normal domain, LE u256)
static const P256Point P256_G_STD = []{
    P256Point g;
    g.inf  = false;
    g.mont = false;
    g.x = bytes_be_to_u256(P256_GX_BE);
    g.y = bytes_be_to_u256(P256_GY_BE);
    return g;
}();

    // Gx (std domain)
    g.x = {0xd898c296, 0xf4a13945, 0x2deb33a0, 0x77037d81,
           0x63a440f2, 0xf8bce6e5, 0xe12c4247, 0x6b17d1f2};
const P256Point& P256_G() { return P256_G_STD; }

    // Gy (std domain)
    g.y = {0x37bf51f5, 0xcbb64068, 0x6b315ece, 0x2bce3357,
           0x7c0f9e16, 0x8ee7eb4a, 0xfe1a7f9b, 0x4fe342e2};

    return g;
}();
// Montgomery basepoint (for internal jacobian arithmetic)
static const P256Point P256_G_JAC_MONT = []{
    P256Point j;
    j.mont=true;
    j.inf = false;
    j.x = to_mont(P256_G_STD.x);
    j.y = to_mont(P256_G_STD.y);

static const P256Point P256_G_MONT = []{
    P256Point g = P256_G_STD;
    g.x = to_mont(g.x);
    g.y = to_mont(g.y);
    g.inf = false;
    return g;
}();
    u256 one; u256_zero(one); one.w[0]=1;
    j.z = to_mont(one); // Z=1 in mont

const P256Point& P256_G() { return P256_G_MONT; }
    return j;
}();

// ------------------------------------------------------------
// Point Transformations
@@ -56,16 +59,14 @@ const P256Point& P256_G() { return P256_G_MONT; }
 * Converts Affine (Montgomery) to Jacobian (Montgomery).
 * Z starts as 1 in Montgomery domain: Z = to_mont(1).
 */
P256PointJ toJac(const P256Point& a) {
    P256PointJ r;
    r.inf = a.inf;
    r.X = a.x;
    r.Y = a.y;

    // Z = 1 (Montgomery)
    u256 one = {{1,0,0,0,0,0,0,0}};
    r.Z = to_mont(one);

static inline P256Point jac_inf() {
    P256Point r;
    r.inf = true;
    r.mont = true;
    u256 zero; u256_zero(zero);
    r.x = to_mont(zero);
    r.y = to_mont(zero);
    r.z = to_mont(zero);  // Z=0 => infinity
    return r;
}

@@ -73,24 +74,40 @@ P256PointJ toJac(const P256Point& a) {
 * Converts Jacobian (Montgomery) to Affine (Montgomery).
 * x = X / Z^2, y = Y / Z^3  (all Montgomery domain)
 */
P256Point toAff(const P256PointJ& a) {
    P256Point r;
    if (a.inf || u256_is_zero(a.Z)) {
        r.inf = true;
        return r;
P256Point toAff(const P256Point& Jm)
{
    P256Point P;
    P.mont = false;  // ✅ because we return STD

    if (Jm.inf) {
        P.inf = true;
        return P;
    }

    // zi = 1/Z (Montgomery)
    u256 zi  = fp_inv(a.Z);
    u256 zi2 = fp_sqr(zi);
    u256 zi3 = fp_mul(zi2, zi);
    // Z == 0 ?
    u256 z_std = from_mont(Jm.z);
    if (u256_is_zero(z_std)) {
        P.inf = true;
        return P;
    }

    r.x = fp_mul(a.X, zi2);
    r.y = fp_mul(a.Y, zi3);
    r.inf = false;
    return r;
    // zinv = 1/Z in MONT
    u256 zinv  = fp_inv(Jm.z);
    u256 zinv2 = fp_mul(zinv, zinv);
    u256 zinv3 = fp_mul(zinv2, zinv);

    // affine in MONT
    u256 Xm = fp_mul(Jm.x, zinv2);
    u256 Ym = fp_mul(Jm.y, zinv3);

    // convert to STD for output
    P.inf = false;
    P.x   = from_mont(Xm);
    P.y   = from_mont(Ym);
    return P;
}


// ------------------------------------------------------------
// Point Arithmetic
// ------------------------------------------------------------
@@ -99,18 +116,18 @@ P256Point toAff(const P256PointJ& a) {
 * Jacobian point doubling: R = 2P  (all Montgomery domain)
 * Optimized for a=-3.
 */
P256PointJ point_double(const P256PointJ& a) {
    if (a.inf || u256_is_zero(a.Z)) return a;
P256Point point_double(const P256Point& a) {
    if (a.inf || u256_is_zero(a.z)) return a;

    u256 t1 = fp_sqr(a.Z);              // Z^2
    u256 t2 = fp_sub(a.X, t1);          // X - Z^2
    u256 t3 = fp_add(a.X, t1);          // X + Z^2
    u256 t1 = fp_sqr(a.z);              // Z^2
    u256 t2 = fp_sub(a.x, t1);          // X - Z^2
    u256 t3 = fp_add(a.x, t1);          // X + Z^2
    t2 = fp_mul(t2, t3);                // (X-Z^2)(X+Z^2)
    u256 t4 = fp_add(t2, t2);           // 2*t2
    u256 M  = fp_add(t4, t2);           // 3*(X^2 - Z^4)

    u256 Y2 = fp_sqr(a.Y);              // Y^2
    u256 S  = fp_mul(a.X, Y2);          // X*Y^2
    u256 Y2 = fp_sqr(a.y);              // Y^2
    u256 S  = fp_mul(a.x, Y2);          // X*Y^2
    S = fp_add(S, S);
    S = fp_add(S, S);                   // S = 4*X*Y^2

@@ -126,36 +143,36 @@ P256PointJ point_double(const P256PointJ& a) {
    u256 S_minus_X3 = fp_sub(S, X3);
    u256 Y3 = fp_sub(fp_mul(M, S_minus_X3), Y8);

    u256 YZ = fp_mul(a.Y, a.Z);
    u256 YZ = fp_mul(a.y, a.z);
    u256 Z3 = fp_add(YZ, YZ);

    P256PointJ r;
    P256Point r;
    r.inf = false;
    r.X = X3;
    r.Y = Y3;
    r.Z = Z3;
    r.x = X3;
    r.y = Y3;
    r.z = Z3;
    return r;
}

/**
 * Full Jacobian point addition: R = a + b (Montgomery)
 */
P256PointJ point_add_jac(const P256PointJ& a, const P256PointJ& b) {
P256Point point_add_jac(const P256Point& a, const P256Point& b) {
    if (a.inf) return b;
    if (b.inf) return a;

    u256 z1z1 = fp_sqr(a.Z);
    u256 z2z2 = fp_sqr(b.Z);
    u256 z1z1 = fp_sqr(a.z);
    u256 z2z2 = fp_sqr(b.z);

    u256 u1 = fp_mul(a.X, z2z2);
    u256 u2 = fp_mul(b.X, z1z1);
    u256 u1 = fp_mul(a.x, z2z2);
    u256 u2 = fp_mul(b.x, z1z1);

    u256 s1 = fp_mul(fp_mul(a.Y, b.Z), z2z2);
    u256 s2 = fp_mul(fp_mul(b.Y, a.Z), z1z1);
    u256 s1 = fp_mul(fp_mul(a.y, b.z), z2z2);
    u256 s2 = fp_mul(fp_mul(b.y, a.z), z1z1);

    if (u256_cmp(u1, u2) == 0) {
        if (u256_cmp(s1, s2) == 0) return point_double(a);
        P256PointJ r; r.inf = true; return r;
        P256Point r; r.inf = true; return r;
    }

    u256 h = fp_sub(u2, u1);
@@ -166,13 +183,13 @@ P256PointJ point_add_jac(const P256PointJ& a, const P256PointJ& b) {

    u256 x3 = fp_sub(fp_sub(fp_sqr(r_val), h3), fp_add(v, v));
    u256 y3 = fp_sub(fp_mul(r_val, fp_sub(v, x3)), fp_mul(s1, h3));
    u256 z3 = fp_mul(fp_mul(a.Z, b.Z), h);
    u256 z3 = fp_mul(fp_mul(a.z, b.z), h);

    P256PointJ res;
    P256Point res;
    res.inf = false;
    res.X = x3;
    res.Y = y3;
    res.Z = z3;
    res.x = x3;
    res.y = y3;
    res.z = z3;
    return res;
}

@@ -180,50 +197,111 @@ P256PointJ point_add_jac(const P256PointJ& a, const P256PointJ& b) {
// Scalar Multiplication (Montgomery Ladder)
// ------------------------------------------------------------

static inline void cswap_jac(P256PointJ& a, P256PointJ& b, uint32_t swap) {
    swap = 0 - swap; // 0x00000000 or 0xFFFFFFFF
static inline void cswap_jac(P256Point& A, P256Point& B, uint32_t swap) {
    // swap is 0 or 1
    cswap_u256(A.x, B.x, swap);
    cswap_u256(A.y, B.y, swap);
    cswap_u256(A.z, B.z, swap);

    // IMPORTANT: swap the infinity flag too
    uint32_t t = (uint32_t)A.inf ^ (uint32_t)B.inf;
    t &= (0u - swap);
    A.inf = (bool)((uint32_t)A.inf ^ t);
    B.inf = (bool)((uint32_t)B.inf ^ t);
}

P256Point toJac(const P256Point& Pstd)
{
    P256Point J;
    J.mont = true;

    if (Pstd.inf) {
        J.inf = true;
        u256 z; u256_zero(z);
        J.x = to_mont(z);
        J.y = to_mont(z);
        J.z = to_mont(z); // Z=0 => INF
        return J;
    }

    for (int i = 0; i < 8; i++) {
        uint32_t t;
    J.inf = false;
    J.x = to_mont(Pstd.x);
    J.y = to_mont(Pstd.y);

        t = swap & (a.X.w[i] ^ b.X.w[i]); a.X.w[i] ^= t; b.X.w[i] ^= t;
        t = swap & (a.Y.w[i] ^ b.Y.w[i]); a.Y.w[i] ^= t; b.Y.w[i] ^= t;
        t = swap & (a.Z.w[i] ^ b.Z.w[i]); a.Z.w[i] ^= t; b.Z.w[i] ^= t;
    u256 one; u256_zero(one); one.w[0]=1;
    J.z = to_mont(one); // Z=1
    return J;
}

    uint32_t tinf = swap & (uint32_t)(a.inf ^ b.inf);
    a.inf ^= tinf;
    b.inf ^= tinf;

static bool scalar_is_zero(const uint8_t k[32]) {
    for (int i=0;i<32;i++) if (k[i]) return false;
    return true;
}

P256Point scalar_mul(const uint8_t priv[32], const P256Point& P) {
    P256PointJ R0; R0.inf = true;
P256Point scalar_mul(const uint8_t k[32], const P256Point& Pstd)
{
    // R = INF (Jacobian, MONT)
    P256Point R;
    R.inf  = true;
    R.mont = true;
    u256 z; u256_zero(z);
    R.x = to_mont(z);
    R.y = to_mont(z);
    R.z = to_mont(z);

    // Q = P as Jacobian (MONT)
    P256Point Q = toJac(Pstd);

    // classic double-and-add MSB->LSB (matches get_bit_be)
    for (int i=0;i<256;i++){
        uint32_t bit = get_bit_be(k,i);

    // For infinity point, set dummy values in Montgomery (so ops are defined)
    u256 zero; u256_zero(zero);
    R0.X = to_mont(zero);
    R0.Y = to_mont(zero);
    R0.Z = to_mont(zero);
        R = point_double(R);
        if(bit) R = point_add_jac(R,Q);
    }

    P256PointJ R1 = toJac(P);
    // ✅ Return affine STD
    return toAff(R);
}

    uint32_t prev = 0;
    for (int i = 0; i < 256; i++) {
        uint32_t b = get_bit_be(priv, i);
        uint32_t swap = b ^ prev;
        prev = b;

        cswap_jac(R0, R1, swap);

        R1 = point_add_jac(R0, R1);
        R0 = point_double(R0);
P256Point scalar_mul_G(const uint8_t priv[32])
{
    if (scalar_is_zero(priv)) {
        P256Point R;
        R.inf = true;
        R.mont = false;
        return R;
    }
    cswap_jac(R0, R1, prev);
    return toAff(R0);
    return scalar_mul(priv, P256_G());
}

P256Point scalar_mul_G(const uint8_t priv[32]) {
    return scalar_mul(priv, P256_G());
bool is_on_curve(const P256Point& P)
{
    if (P.inf) return true;

    // reject x>=p or y>=p
    if (u256_cmp(P.x, P256_P) >= 0) return false;
    if (u256_cmp(P.y, P256_P) >= 0) return false;

    u256 x = P.mont ? P.x : to_mont(P.x);
    u256 y = P.mont ? P.y : to_mont(P.y);
    u256 b = to_mont(P256_B);

    u256 y2 = fp_mul(y,y);
    u256 x2 = fp_mul(x,x);
    u256 x3 = fp_mul(x2,x);

    // rhs = x^3 - 3x + b
    u256 three_std = {{3,0,0,0,0,0,0,0}};
    u256 three = to_mont(three_std);

    u256 rhs = fp_sub(x3, fp_mul(three,x));
    rhs = fp_add(rhs,b);

    return u256_cmp(y2,rhs)==0;
}

// ------------------------------------------------------------
@@ -235,66 +313,44 @@ P256Point scalar_mul_G(const uint8_t priv[32]) {
 * Internally stores coordinates in Montgomery domain.
 * Also validates curve equation in Montgomery domain.
 */
bool decode_tls_point(P256Point& out, const uint8_t* p, size_t n) {
    if (!p || n < 65 || p[0] != 0x04) return false;

    // Read coordinates from network Big Endian -> normal u256
    u256 x_std = u256_from_be(p + 1);
    u256 y_std = u256_from_be(p + 33);
bool decode_tls_point(P256Point& out, const uint8_t* in, size_t len)
{
    if (len != 65 || in[0] != 0x04) return false;

    // Convert to Montgomery internal representation
    out.x = to_mont(x_std);
    out.y = to_mont(y_std);
    out.inf  = false;

    // Validate y^2 == x^3 - 3x + b  (all Montgomery)
    u256 y2 = fp_sqr(out.y);
    u256 x2 = fp_sqr(out.x);
    u256 x3 = fp_mul(x2, out.x);

    u256 three_x = fp_add(out.x, out.x);
    three_x = fp_add(three_x, out.x);

    u256 rhs = fp_sub(x3, three_x);
    rhs = fp_add(rhs, P256_B);

    if (u256_cmp(y2, rhs) != 0) {
        out.inf = true;
        return false;
    }
    out.mont = false;
    out.x = bytes_be_to_u256(in + 1);
    out.y = bytes_be_to_u256(in + 33);
    return true;
}


/**
 * Encodes affine point (Montgomery) to TLS (std big endian).
 */
std::vector<uint8_t> encode_tls_point(const P256Point& P) {
    if (P.inf) return {};

    std::vector<uint8_t> res(65);
    res[0] = 0x04;

    // Convert from Montgomery -> standard for output
    u256 x_std = from_mont(P.x);
    u256 y_std = from_mont(P.y);
std::vector<uint8_t> encode_tls_point(const P256Point& P)
{
    std::vector<uint8_t> out(65);
    out[0]=0x04;
    u256_to_be(&out[1], P.x);
    u256_to_be(&out[33],P.y);
    return out;
}

    u256_to_be(res.data() + 1,  x_std);
    u256_to_be(res.data() + 33, y_std);

    return res;
}

/**
 * ECDH: returns Big-Endian X-coordinate of shared point.
 */
bool ecdh_shared_secret(uint8_t out32[32], const uint8_t priv[32], const P256Point& peer) {
bool ecdh_shared_secret(uint8_t out32[32], const uint8_t priv[32], const P256Point& peer)
{
    if (!out32 || peer.inf) return false;

    P256Point shared_point = scalar_mul(priv, peer);
    if (shared_point.inf) return false;
    // scalar_mul returns affine STD
    P256Point shared = scalar_mul(priv, peer);
    if (shared.inf) return false;

    u256 x_std = from_mont(shared_point.x);
    u256_to_be(out32, x_std);
    u256_to_be(out32, shared.x);   // ✅ already STD
    return true;
}

+34 −17
Original line number Diff line number Diff line
@@ -6,6 +6,31 @@

namespace netplus {

static const u256 P256_N = {{
    0xFC632551, // w[0] LSW
    0xF3B9CAC2,
    0xA7179E84,
    0xBCE6FAAD,
    0xFFFFFFFF,
    0xFFFFFFFF,
    0x00000000,
    0xFFFFFFFF  // w[7] MSW
}};

static const uint8_t P256_GX_BE[32] = {
  0x6b,0x17,0xd1,0xf2,0xe1,0x2c,0x42,0x47,
  0xf8,0xbc,0xe6,0xe5,0x63,0xa4,0x40,0xf2,
  0x77,0x03,0x7d,0x81,0x2d,0xeb,0x33,0xa0,
  0xf4,0xa1,0x39,0x45,0xd8,0x98,0xc2,0x96
};

static const uint8_t P256_GY_BE[32] = {
  0x4f,0xe3,0x42,0xe2,0xfe,0x1a,0x7f,0x9b,
  0x8e,0xe7,0xeb,0x4a,0x7c,0x0f,0x9e,0x16,
  0x2b,0xce,0x33,0x57,0x6b,0x31,0x5e,0xce,
  0xcb,0xb6,0x40,0x68,0x37,0xbf,0x51,0xf5
};

/**
 * @brief Affine point on the NIST P-256 curve.
 * Equation: y^2 = x^3 - 3x + b (mod p)
@@ -14,19 +39,9 @@ namespace netplus {
struct P256Point {
    u256 x;
    u256 y;
    bool inf = true; // Flag for Point at Infinity (neutral element)
};

/**
 * @brief Jacobian point representation (X:Y:Z).
 * Conversion to affine: x = X/Z^2, y = Y/Z^3.
 * Used for efficient point arithmetic to avoid frequent modular inversions.
 */
struct P256PointJ {
    u256 X;
    u256 Y;
    u256 Z;
    u256 z;      // only valid if mont=true (Jacobian)
    bool inf = true;
    bool mont = false;
};

// --- NIST P-256 Curve Constants ---
@@ -46,26 +61,26 @@ extern const u256 P256_B;
/** * @brief Converts affine coordinates to Jacobian coordinates.
 * Sets Z = 1.
 */
P256PointJ toJac(const P256Point& a);
P256Point toJac(const P256Point& P);

/** * @brief Converts Jacobian coordinates back to Affine.
 * Requires one modular inversion.
 */
P256Point  toAff(const P256PointJ& a);
P256Point  toAff(const P256Point& a);

/** * @brief Point doubling: R = 2 * P.
 * Optimized for the NIST case where a = -3.
 */
P256PointJ point_double(const P256PointJ& a);
P256Point point_double(const P256Point& a);

/** * @brief Full Jacobian point addition: R = P1 + P2.
 */
P256PointJ point_add_jac(const P256PointJ& a, const P256PointJ& b);
P256Point point_add_jac(const P256Point& a, const P256Point& b);

/** * @brief Mixed addition: R = P1 (Jacobian) + P2 (Affine).
 * Faster than full Jacobian addition when one point is already affine.
 */
P256PointJ point_add_mixed(const P256PointJ& a, const P256Point& b);
P256Point point_add_mixed(const P256Point& a, const P256Point& b);

// --- Scalar Multiplication ---

@@ -81,6 +96,8 @@ P256Point scalar_mul(const uint8_t priv[32], const P256Point& P);
 */
P256Point scalar_mul_G(const uint8_t priv[32]);

bool is_on_curve(const P256Point& P);

// --- TLS / Interoperability ---

/**
+21 −7
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@ const u256 P256_P = {{
    0x00000000u, 0x00000000u, 0x00000001u, 0xFFFFFFFFu
}};


static const u256 P256_R = {{
    0x00000001u,
    0x00000000u,
@@ -115,6 +116,20 @@ void u256_to_be(uint8_t out32[32], const u256& a) {
    }
}

u256 bytes_be_to_u256(const uint8_t in[32]) {
    u256 r;
    for (int i = 0; i < 8; i++) {
        int o = 28 - 4*i;   // ✅ same mapping as u256_to_be
        r.w[i] =
            ((uint32_t)in[o+0] << 24) |
            ((uint32_t)in[o+1] << 16) |
            ((uint32_t)in[o+2] <<  8) |
            ((uint32_t)in[o+3] <<  0);
    }
    return r;
}


// ============================================================================
// 256x256 -> 512 multiply (schoolbook, correct carry), NO __int128
// ============================================================================
@@ -167,7 +182,6 @@ static inline u512 u512_from_be64(const uint8_t be64[64]) {
// ============================================================================
// Montgomery REDC for P-256 (8 limbs, 32-bit, no __int128)
// This version is stable and matches classic HAC REDC.
// ============================================================================
u256 mont_mul(const u256& a, const u256& b) {
    uint32_t t[16] = {0};
    uint32_t extra = 0; // overflow beyond t[15]
@@ -246,7 +260,6 @@ u256 mont_mul(const u256& a, const u256& b) {
    return r;
}


// ----------------------------------------------------------------------------
// to/from Montgomery
// ----------------------------------------------------------------------------
@@ -254,9 +267,9 @@ u256 to_mont(const u256& a) {
    return mont_mul(a, P256_R2);
}

u256 from_mont(const u256& a) {
u256 from_mont(const u256& aR) {
    u256 one; u256_zero(one); one.w[0]=1;
    return mont_mul(a, one);
    return mont_mul(aR, one); // NUR wenn mont_mul als REDC(t) implementiert ist
}

// ----------------------------------------------------------------------------
@@ -294,8 +307,9 @@ u256 fp_sqr(const u256& a) {
// bit access
// ----------------------------------------------------------------------------
uint32_t get_bit_be(const uint8_t priv[32], int bit_index) {
    int byte = bit_index / 8;
    int bit  = 7 - (bit_index % 8);
    // i=0 -> MSB of priv[0]
    int byte = bit_index >> 3;
    int bit  = 7 - (bit_index & 7);
    return (priv[byte] >> bit) & 1;
}

+20 −1
Original line number Diff line number Diff line
@@ -13,6 +13,25 @@ extern const u256 P256_R2;
// -------- low-level helpers --------
void u256_zero(u256& a);
bool u256_is_zero(const u256& a);

static inline void u256_one(u256& a) {
    u256_zero(a);
    a.w[0] = 1;
}

static inline void cswap_u256(u256& A, u256& B, uint32_t swap)
{
    // swap is 0 or 1
    uint32_t mask = 0u - swap;  // 0x00000000 or 0xFFFFFFFF

    for (int i = 0; i < 8; i++) {
        uint32_t t = (A.w[i] ^ B.w[i]) & mask;
        A.w[i] ^= t;
        B.w[i] ^= t;
    }
}


int  u256_cmp(const u256& a, const u256& b);

// raw ops (no mod reduction)
@@ -23,7 +42,7 @@ u256 u256_sub_raw(const u256& a, const u256& b, uint32_t& borrow);
u256 u256_from_be(const uint8_t be32[32]);
void u256_to_be(uint8_t out32[32], const u256& a);
u512 u512_from_be(const uint8_t in[64]);

u256 bytes_be_to_u256(const uint8_t in[32]);
// multiply
u512 u256_mul_raw(const u256& a, const u256& b);

+4 −0
Original line number Diff line number Diff line
@@ -477,6 +477,7 @@ namespace netplus {

		void _tls13_transcript_add_raw(const std::vector<uint8_t>& hsmsg);

		std::vector<uint8_t> _tls13_build_server_finished_body();
		std::vector<uint8_t> _tls13_build_server_finished();

		bool _handshakeStarted = false;
@@ -532,6 +533,9 @@ namespace netplus {
		std::vector<uint8_t> _client_session_id;

		bool _client_offered_tls13 = false;
		bool _encflight_queued   = false;
		bool _compat_ccs_sent = false;
		bool _client_has_tls13_keyshare_x25519=false;

		// --- TLS 1.3 (minimal) ---
        bool     _is_tls13 = false;
Loading