Commit c65bb0c6 authored by jan.koester's avatar jan.koester
Browse files

upload before rework

parent 25f6b1f8
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ list(APPEND netplussrc
    crypto/ecc_p256.cpp
    crypto/hkdf.cpp
    crypto/rsa_pss_sha256.cpp
    crypto/curve25519.cpp
    exception.cpp
    connection.cpp
    ssl.cpp
@@ -63,6 +64,7 @@ set(headers
    crypto/hkdf.h
    crypto/rsa_pss_sha256.h
    crypto/sha.h
    crypto/curve25519.h
)

add_library(netplus SHARED ${netplussrc} ${headers})
+37 −22
Original line number Diff line number Diff line
@@ -273,7 +273,10 @@ block128 aes::encrypt(const block128& plaintext) {
    if (plaintext.size() != 16)
        throw std::invalid_argument("aes::encrypt: block must be 16 bytes");

    uint8_t state[16];
    uint8_t state[16]={0};

    if (plaintext.size() != 16) throw;

    std::memcpy(state, plaintext.data(), 16);

    // round 0
@@ -299,7 +302,8 @@ block128 aes::decrypt(const block128& ciphertext) {
    if (ciphertext.size() != 16)
        throw std::invalid_argument("aes::decrypt: block must be 16 bytes");

    uint8_t state[16];
    uint8_t state[16]={0};

    std::memcpy(state, ciphertext.data(), 16);

    // round 10
@@ -387,8 +391,8 @@ static inline void xor_block_inplace(uint8_t out[16], const uint8_t b[16]) {
    for (int i=0;i<16;i++) out[i] ^= b[i];
}

static inline void store_be64(uint8_t out[8], uint64_t x) {
    for (int i=0;i<8;i++) out[i] = (uint8_t)(x >> (56 - 8*i));
static inline void store_be64(uint8_t* out, uint64_t v) {
    for (int i=7;i>=0;i--) { out[i] = v & 0xFF; v >>= 8; }
}

// multiply in GF(2^128) with poly 0xE1
@@ -437,7 +441,7 @@ static void ghash(uint8_t out[16], const uint8_t H[16],
    ghash_update(Y, H, aad, aad_len);
    ghash_update(Y, H, ct, ct_len);

    uint8_t lenblk[16];
    uint8_t lenblk[16] ={0};
    store_be64(lenblk,     (uint64_t)aad_len * 8);
    store_be64(lenblk + 8, (uint64_t)ct_len  * 8);

@@ -487,29 +491,35 @@ bool aes::aes_gcm_encrypt(
    std::memcpy(J0, iv12, 12);
    J0[15] = 1;

    // CTR keystream
    uint8_t ctr[16];
    // CTR = J0
    uint8_t ctr[16] = {0};
    std::memcpy(ctr, J0, 16);

    // CTR encrypt
    size_t off = 0;
    while (off < pt_len) {
        inc32(ctr);
        uint8_t S[16];

        uint8_t S[16] = {0};              // ✅ MUST init
        aes_encrypt_block(*this, ctr, S);

        size_t take = (pt_len - off < 16) ? (pt_len - off) : 16;
        for (size_t i=0;i<take;i++) ct[off+i] = pt[off+i] ^ S[i];
        for (size_t i=0;i<take;i++)
            ct[off+i] = pt[off+i] ^ S[i];

        off += take;
    }

    // GHASH
    uint8_t Sgh[16];
    uint8_t Sgh[16] = {0};                // ✅ MUST init
    ghash(Sgh, H, aad, aad_len, ct, pt_len);

    // Tag = AES_k(J0) XOR GHASH
    uint8_t EJ0[16];
    uint8_t EJ0[16] = {0};                // ✅ MUST init
    aes_encrypt_block(*this, J0, EJ0);
    for (int i=0;i<16;i++) tag16[i] = EJ0[i] ^ Sgh[i];

    for (int i=0;i<16;i++)
        tag16[i] = EJ0[i] ^ Sgh[i];

    return true;
}
@@ -529,33 +539,38 @@ bool aes::aes_gcm_decrypt(
    J0[15] = 1;

    // expected tag
    uint8_t Sgh[16];
    uint8_t Sgh[16] = {0};                // ✅ MUST init
    ghash(Sgh, H, aad, aad_len, ct, ct_len);

    uint8_t EJ0[16];
    uint8_t EJ0[16] = {0};                // ✅ MUST init
    aes_encrypt_block(*this, J0, EJ0);

    uint8_t expTag[16];
    for (int i=0;i<16;i++) expTag[i] = EJ0[i] ^ Sgh[i];
    uint8_t expTag[16] = {0};             // ✅ MUST init
    for (int i=0;i<16;i++)
        expTag[i] = EJ0[i] ^ Sgh[i];

    if (ct_memeq_mask(expTag, tag16, 16) != 0) return false;
    // IMPORTANT: If ct_memeq_mask returns 0 when equal:
    if (ct_memeq_mask(expTag, tag16, 16) != 0)
        return false;

    // CTR decrypt
    uint8_t ctr[16];
    uint8_t ctr[16] = {0};                // ✅ MUST init
    std::memcpy(ctr, J0, 16);

    size_t off = 0;
    while (off < ct_len) {
        inc32(ctr);
        uint8_t S[16];

        uint8_t S[16] = {0};              // ✅ MUST init
        aes_encrypt_block(*this, ctr, S);

        size_t take = (ct_len - off < 16) ? (ct_len - off) : 16;
        for (size_t i=0;i<take;i++) pt[off+i] = ct[off+i] ^ S[i];
        for (size_t i=0;i<take;i++)
            pt[off+i] = ct[off+i] ^ S[i];

        off += take;
    }

    return true;
}

};
+2 −0
Original line number Diff line number Diff line
@@ -79,6 +79,8 @@ private:
public:
    explicit aes(const key128& key);

    virtual ~aes() = default;

    // NOTE: Keeping your vector-based API, but avoids realloc/extra copies.
    block128 encrypt(const block128& plaintext);
    block128 decrypt(const block128& ciphertext);
+275 −0
Original line number Diff line number Diff line
#include "curve25519.h"
#include <string.h>

namespace netplus {

static inline uint32_t load32(const uint8_t *p) {
    return ((uint32_t)p[0]) |
           ((uint32_t)p[1] << 8) |
           ((uint32_t)p[2] << 16) |
           ((uint32_t)p[3] << 24);
}

static inline void store32(uint8_t *p, uint32_t v) {
    p[0] = (uint8_t)(v);
    p[1] = (uint8_t)(v >> 8);
    p[2] = (uint8_t)(v >> 16);
    p[3] = (uint8_t)(v >> 24);
}

// Field element radix 2^25.5
typedef int32_t fe[10];

static void fe_0(fe h) { memset(h, 0, sizeof(fe)); }
static void fe_1(fe h) { fe_0(h); h[0] = 1; }
static void fe_copy(fe h, const fe f) { memcpy(h, f, sizeof(fe)); }

static void fe_add(fe h, const fe f, const fe g) {
    for (int i=0;i<10;i++) h[i] = f[i] + g[i];
}
static void fe_sub(fe h, const fe f, const fe g) {
    for (int i=0;i<10;i++) h[i] = f[i] - g[i];
}

static void fe_cswap(fe f, fe g, uint32_t b) {
    b = -b;
    for (int i=0;i<10;i++) {
        int32_t x = b & (f[i] ^ g[i]);
        f[i] ^= x;
        g[i] ^= x;
    }
}

static void fe_carry(fe h) {
    int64_t c;
    c = (h[0] + ((int64_t)1<<25)) >> 26; h[1] += c; h[0] -= c<<26;
    c = (h[1] + ((int64_t)1<<24)) >> 25; h[2] += c; h[1] -= c<<25;
    c = (h[2] + ((int64_t)1<<25)) >> 26; h[3] += c; h[2] -= c<<26;
    c = (h[3] + ((int64_t)1<<24)) >> 25; h[4] += c; h[3] -= c<<25;
    c = (h[4] + ((int64_t)1<<25)) >> 26; h[5] += c; h[4] -= c<<26;
    c = (h[5] + ((int64_t)1<<24)) >> 25; h[6] += c; h[5] -= c<<25;
    c = (h[6] + ((int64_t)1<<25)) >> 26; h[7] += c; h[6] -= c<<26;
    c = (h[7] + ((int64_t)1<<24)) >> 25; h[8] += c; h[7] -= c<<25;
    c = (h[8] + ((int64_t)1<<25)) >> 26; h[9] += c; h[8] -= c<<26;
    c = (h[9] + ((int64_t)1<<24)) >> 25; h[0] += c*19; h[9] -= c<<25;

    c = (h[0] + ((int64_t)1<<25)) >> 26; h[1] += c; h[0] -= c<<26;
}

static void fe_mul(fe h, const fe f, const fe g) {
    int64_t f0=f[0], f1=f[1], f2=f[2], f3=f[3], f4=f[4], f5=f[5], f6=f[6], f7=f[7], f8=f[8], f9=f[9];
    int64_t g0=g[0], g1=g[1], g2=g[2], g3=g[3], g4=g[4], g5=g[5], g6=g[6], g7=g[7], g8=g[8], g9=g[9];

    int64_t g1_19 = 19*g1;
    int64_t g2_19 = 19*g2;
    int64_t g3_19 = 19*g3;
    int64_t g4_19 = 19*g4;
    int64_t g5_19 = 19*g5;
    int64_t g6_19 = 19*g6;
    int64_t g7_19 = 19*g7;
    int64_t g8_19 = 19*g8;
    int64_t g9_19 = 19*g9;

    int64_t h0 = f0*g0 + f1*g9_19 + f2*g8_19 + f3*g7_19 + f4*g6_19 + f5*g5_19 + f6*g4_19 + f7*g3_19 + f8*g2_19 + f9*g1_19;
    int64_t h1 = f0*g1 + f1*g0    + f2*g9_19 + f3*g8_19 + f4*g7_19 + f5*g6_19 + f6*g5_19 + f7*g4_19 + f8*g3_19 + f9*g2_19;
    int64_t h2 = f0*g2 + f1*g1    + f2*g0    + f3*g9_19 + f4*g8_19 + f5*g7_19 + f6*g6_19 + f7*g5_19 + f8*g4_19 + f9*g3_19;
    int64_t h3 = f0*g3 + f1*g2    + f2*g1    + f3*g0    + f4*g9_19 + f5*g8_19 + f6*g7_19 + f7*g6_19 + f8*g5_19 + f9*g4_19;
    int64_t h4 = f0*g4 + f1*g3    + f2*g2    + f3*g1    + f4*g0    + f5*g9_19 + f6*g8_19 + f7*g7_19 + f8*g6_19 + f9*g5_19;
    int64_t h5 = f0*g5 + f1*g4    + f2*g3    + f3*g2    + f4*g1    + f5*g0    + f6*g9_19 + f7*g8_19 + f8*g7_19 + f9*g6_19;
    int64_t h6 = f0*g6 + f1*g5    + f2*g4    + f3*g3    + f4*g2    + f5*g1    + f6*g0    + f7*g9_19 + f8*g8_19 + f9*g7_19;
    int64_t h7 = f0*g7 + f1*g6    + f2*g5    + f3*g4    + f4*g3    + f5*g2    + f6*g1    + f7*g0    + f8*g9_19 + f9*g8_19;
    int64_t h8 = f0*g8 + f1*g7    + f2*g6    + f3*g5    + f4*g4    + f5*g3    + f6*g2    + f7*g1    + f8*g0    + f9*g9_19;
    int64_t h9 = f0*g9 + f1*g8    + f2*g7    + f3*g6    + f4*g5    + f5*g4    + f6*g3    + f7*g2    + f8*g1    + f9*g0;

    h[0]=(int32_t)h0; h[1]=(int32_t)h1; h[2]=(int32_t)h2; h[3]=(int32_t)h3; h[4]=(int32_t)h4;
    h[5]=(int32_t)h5; h[6]=(int32_t)h6; h[7]=(int32_t)h7; h[8]=(int32_t)h8; h[9]=(int32_t)h9;
    fe_carry(h);
}

static void fe_sq(fe h, const fe f) { fe_mul(h,f,f); }

static void fe_pow22523(fe out, const fe z) {
    fe t0,t1,t2;
    fe_sq(t0,z);
    fe_sq(t1,t0);
    fe_sq(t1,t1);
    fe_mul(t1,z,t1);
    fe_mul(t0,t0,t1);
    fe_sq(t0,t0);
    fe_mul(t0,t1,t0);

    fe_sq(t1,t0);
    for(int i=1;i<5;i++) fe_sq(t1,t1);
    fe_mul(t0,t1,t0);

    fe_sq(t1,t0);
    for(int i=1;i<10;i++) fe_sq(t1,t1);
    fe_mul(t1,t1,t0);

    fe_sq(t2,t1);
    for(int i=1;i<20;i++) fe_sq(t2,t2);
    fe_mul(t1,t2,t1);

    fe_sq(t1,t1);
    for(int i=1;i<10;i++) fe_sq(t1,t1);
    fe_mul(t0,t1,t0);

    fe_sq(t1,t0);
    for(int i=1;i<50;i++) fe_sq(t1,t1);
    fe_mul(t1,t1,t0);

    fe_sq(t2,t1);
    for(int i=1;i<100;i++) fe_sq(t2,t2);
    fe_mul(t1,t2,t1);

    fe_sq(t1,t1);
    for(int i=1;i<50;i++) fe_sq(t1,t1);
    fe_mul(t0,t1,t0);

    fe_sq(t0,t0);
    fe_sq(t0,t0);
    fe_mul(out,t0,z);
}

static void fe_frombytes(fe h, const uint8_t s[32]) {
    int64_t t0 = load32(s);
    int64_t t1 = load32(s+4);
    int64_t t2 = load32(s+8);
    int64_t t3 = load32(s+12);
    int64_t t4 = load32(s+16);
    int64_t t5 = load32(s+20);
    int64_t t6 = load32(s+24);
    int64_t t7 = load32(s+28);

    h[0] = (int32_t)( t0        & 0x3ffffff);
    h[1] = (int32_t)(((t0>>26) | (t1<<6))  & 0x1ffffff);
    h[2] = (int32_t)(((t1>>19) | (t2<<13)) & 0x3ffffff);
    h[3] = (int32_t)(((t2>>13) | (t3<<19)) & 0x1ffffff);
    h[4] = (int32_t)(( t3>>6)             & 0x3ffffff);
    h[5] = (int32_t)( t4        & 0x1ffffff);
    h[6] = (int32_t)(((t4>>25) | (t5<<7))  & 0x3ffffff);
    h[7] = (int32_t)(((t5>>18) | (t6<<14)) & 0x1ffffff);
    h[8] = (int32_t)(((t6>>12) | (t7<<20)) & 0x3ffffff);
    h[9] = (int32_t)(( t7>>6)             & 0x1ffffff);
}

static void fe_tobytes(uint8_t s[32], fe h) {
    fe_carry(h);

    int32_t q = (19*h[9] + (1<<24)) >> 25;
    q = (h[0] + q) >> 26;
    q = (h[1] + q) >> 25;
    q = (h[2] + q) >> 26;
    q = (h[3] + q) >> 25;
    q = (h[4] + q) >> 26;
    q = (h[5] + q) >> 25;
    q = (h[6] + q) >> 26;
    q = (h[7] + q) >> 25;
    q = (h[8] + q) >> 26;
    q = (h[9] + q) >> 25;

    h[0] += 19*q;
    fe_carry(h);

    int64_t t0 = ((int64_t)h[0]) | ((int64_t)h[1]<<26);
    int64_t t1 = ((int64_t)h[1]>>6) | ((int64_t)h[2]<<19);
    int64_t t2 = ((int64_t)h[2]>>13) | ((int64_t)h[3]<<13);
    int64_t t3 = ((int64_t)h[3]>>19) | ((int64_t)h[4]<<6);

    store32(s, (uint32_t)t0);
    store32(s+4, (uint32_t)(t0>>32));
    store32(s+8, (uint32_t)t1);
    store32(s+12,(uint32_t)(t1>>32));
    store32(s+16,(uint32_t)t2);
    store32(s+20,(uint32_t)(t2>>32));
    store32(s+24,(uint32_t)t3);
    store32(s+28,(uint32_t)(t3>>32));
}

static void x25519_scalarmult(uint8_t out[32],
                              const uint8_t scalar[32],
                              const uint8_t point[32]) {
    uint8_t e[32];
    memcpy(e, scalar, 32);

    // Clamp
    e[0]  &= 248;
    e[31] &= 127;
    e[31] |= 64;

    fe x1, x2, z2, x3, z3, tmp0, tmp1;
    fe_frombytes(x1, point);
    fe_1(x2); fe_0(z2);
    fe_copy(x3, x1); fe_1(z3);

    uint32_t swap = 0;

    for (int pos = 254; pos >= 0; --pos) {
        uint32_t b = (e[pos/8] >> (pos & 7)) & 1;
        swap ^= b;
        fe_cswap(x2, x3, swap);
        fe_cswap(z2, z3, swap);
        swap = b;

        fe_add(tmp0, x2, z2);
        fe_sub(tmp1, x2, z2);
        fe_sq(tmp0, tmp0);
        fe_sq(tmp1, tmp1);
        fe_sub(z2, tmp0, tmp1);

        fe_add(x3, x3, z3);
        fe_sub(z3, x3, z3);

        fe_mul(z3, z3, tmp0);
        fe_mul(x3, x3, tmp1);

        fe_add(tmp0, z3, x3);
        fe_sub(tmp1, z3, x3);
        fe_sq(x3, tmp0);

        fe_sq(tmp0, tmp1);
        fe_mul(z3, tmp0, x1);

        fe_mul(x2, tmp0, tmp1);

        // z2 = E*(AA + 121665*E)
        fe_mul(tmp1, z2, (fe){121665,0,0,0,0,0,0,0,0,0});
        fe_add(tmp1, tmp1, tmp0);
        fe_mul(z2, z2, tmp1);
    }

    fe_cswap(x2, x3, swap);
    fe_cswap(z2, z3, swap);

    fe_pow22523(z2, z2);
    fe_mul(x2, x2, z2);
    fe_tobytes(out, x2);
}

static void x25519_scalarmult_base(uint8_t out[32],
                                   const uint8_t scalar[32]) {
    static const uint8_t base[32] = { 9 };
    x25519_scalarmult(out, scalar, base);
}

bool scalarmult_curve25519(uint8_t out[32],
                           const uint8_t scalar[32],
                           const uint8_t point_u[32]) {
    x25519_scalarmult(out, scalar, point_u);

    // reject all-zero result
    uint8_t acc = 0;
    for (int i=0;i<32;i++) acc |= out[i];
    return acc != 0;
}

bool scalarmult_curve25519_base(uint8_t out[32],
                                const uint8_t scalar[32]) {
    x25519_scalarmult_base(out, scalar);

    uint8_t acc = 0;
    for (int i=0;i<32;i++) acc |= out[i];
    return acc != 0;
}

} // namespace netplus
+16 −0
Original line number Diff line number Diff line
#pragma once
#include <stdint.h>

namespace netplus {

// out = scalar * basepoint(9)
bool scalarmult_curve25519_base(uint8_t out[32],
                                const uint8_t scalar[32]);

// out = scalar * point_u   (point_u = 32-byte u-coordinate)
bool scalarmult_curve25519(uint8_t out[32],
                           const uint8_t scalar[32],
                           const uint8_t point_u[32]);

} // namespace netplus
Loading