Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions .github/workflows/python-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@ jobs:
uv run --no-sync pytest tests

build-no-pqc:
# Regression coverage for issue #2659: INVALID_DEVID is only declared
# in the CFFI cdef when ML_KEM or ML_DSA is enabled, so a wolfSSL build
# without those features must still import wolfcrypt.random successfully.

runs-on: ubuntu-latest
env:
USE_LOCAL_WOLFSSL: ${{ github.workspace }}/wolfssl-install
Expand Down Expand Up @@ -93,7 +89,5 @@ jobs:
run: |
uv run --no-sync python -c "from wolfcrypt._ffi import lib as _lib; assert _lib.ML_KEM_ENABLED == 0, 'ML-KEM should be disabled'"
uv run --no-sync python -c "from wolfcrypt._ffi import lib as _lib; assert _lib.ML_DSA_ENABLED == 0, 'ML-DSA should be disabled'"
- name: Import smoke (regression for INVALID_DEVID)
run: uv run --no-sync python -c "from wolfcrypt.random import Random; Random()"
- name: Run tests
run: uv run --no-sync pytest tests
153 changes: 144 additions & 9 deletions scripts/build_ffi.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,10 @@ def make_flags(prefix, fips):
# ML-DSA (note: to be able to use the legacy option of signing without context, pass `yes,no-ctx` as argument)
flags.append("--enable-mldsa=yes")

# Crypto Callbacks
flags.append("--enable-cryptocb")
# flags.append("EXTRACPPFLAGS=-DDEBUG_CRYPTOCB")

# disabling other configs enabled by default
flags.append("--disable-oldtls")
flags.append("--disable-oldnames")
Expand Down Expand Up @@ -394,6 +398,7 @@ def get_features(local_wolfssl, features):
# Unlike the other fatures, HASHDRBG is enabled by default in random.h, unless WC_NO_HASHDRBG or
# CUSTOM_RAND_GENERATE_BLOCK is defined.
features["HASHDRBG"] = 0 if ("#define WC_NO_HASHDRBG" in defines or "#define CUSTOM_RAND_GENERATE_BLOCK" in defines) else 1
features["CRYPTO_CB"] = 1 if "#define WOLF_CRYPTO_CB" in defines else 0

if '#define HAVE_FIPS' in defines:
if not fips:
Expand Down Expand Up @@ -471,6 +476,7 @@ def build_ffi(local_wolfssl, features):
#include <wolfssl/wolfcrypt/chacha20_poly1305.h>
#include <wolfssl/wolfcrypt/wc_mlkem.h>
#include <wolfssl/wolfcrypt/wc_mldsa.h>
#include <wolfssl/wolfcrypt/cryptocb.h>
"""

init_source_string = f"""
Expand Down Expand Up @@ -515,6 +521,7 @@ def build_ffi(local_wolfssl, features):
int ML_DSA_NO_CTX_ENABLED = {features["ML_DSA_NO_CTX"]};
int HKDF_ENABLED = {features["HKDF"]};
int HASHDRBG_ENABLED = {features["HASHDRBG"]};
int CRYPTO_CB_ENABLED = {features["CRYPTO_CB"]};
"""

ffibuilder.set_source( "wolfcrypt._ffi", init_source_string,
Expand Down Expand Up @@ -558,13 +565,18 @@ def build_ffi(local_wolfssl, features):
extern int ML_DSA_NO_CTX_ENABLED;
extern int HKDF_ENABLED;
extern int HASHDRBG_ENABLED;
extern int CRYPTO_CB_ENABLED;

static const int INVALID_DEVID;

typedef unsigned char byte;
typedef unsigned int word32;

typedef struct { ...; } WC_RNG;
typedef struct { ...; } OS_Seed;

int wolfCrypt_Init(void);

int wc_InitRng(WC_RNG*);
int wc_InitRngNonce(WC_RNG*, byte*, word32);
int wc_InitRngNonce_ex(WC_RNG*, byte*, word32, void*, int);
Expand Down Expand Up @@ -860,7 +872,7 @@ def build_ffi(local_wolfssl, features):
if features["SHA"]:
cdef += """
typedef struct { ...; } wc_Sha;
int wc_InitSha(wc_Sha*);
int wc_InitSha_ex(wc_Sha*, void*, int);
int wc_ShaUpdate(wc_Sha*, const byte*, word32);
int wc_ShaFinal(wc_Sha*, byte*);
void wc_ShaFree(wc_Sha*);
Expand All @@ -870,7 +882,7 @@ def build_ffi(local_wolfssl, features):
if features["SHA256"]:
cdef += """
typedef struct { ...; } wc_Sha256;
int wc_InitSha256(wc_Sha256*);
int wc_InitSha256_ex(wc_Sha256*, void*, int);
int wc_Sha256Update(wc_Sha256*, const byte*, word32);
int wc_Sha256Final(wc_Sha256*, byte*);
void wc_Sha256Free(wc_Sha256*);
Expand All @@ -880,7 +892,7 @@ def build_ffi(local_wolfssl, features):
if features["SHA384"]:
cdef += """
typedef struct { ...; } wc_Sha384;
int wc_InitSha384(wc_Sha384*);
int wc_InitSha384_ex(wc_Sha384*, void*, int);
int wc_Sha384Update(wc_Sha384*, const byte*, word32);
int wc_Sha384Final(wc_Sha384*, byte*);
void wc_Sha384Free(wc_Sha384*);
Expand All @@ -891,7 +903,7 @@ def build_ffi(local_wolfssl, features):
cdef += """
typedef struct { ...; } wc_Sha512;

int wc_InitSha512(wc_Sha512*);
int wc_InitSha512_ex(wc_Sha512*, void*, int);
int wc_Sha512Update(wc_Sha512*, const byte*, word32);
int wc_Sha512Final(wc_Sha512*, byte*);
void wc_Sha512Free(wc_Sha512*);
Expand Down Expand Up @@ -1304,11 +1316,6 @@ def build_ffi(local_wolfssl, features):
int wolfCrypt_GetPrivateKeyReadEnable_fips(enum wc_KeyType);
"""

if features["ML_KEM"] or features["ML_DSA"]:
cdef += """
static const int INVALID_DEVID;
"""

if features["ML_KEM"]:
cdef += """
static const int WC_ML_KEM_512;
Expand Down Expand Up @@ -1363,6 +1370,133 @@ def build_ffi(local_wolfssl, features):
int wc_dilithium_verify_msg(const byte* sig, word32 sigLen, const byte* msg, word32 msgLen, int* res, dilithium_key* key);
"""

if features["CRYPTO_CB"]:
cdef += """
static const int WC_ALGO_TYPE_NONE;
static const int WC_ALGO_TYPE_HASH;
static const int WC_ALGO_TYPE_CIPHER;
static const int WC_ALGO_TYPE_PK;
static const int WC_ALGO_TYPE_RNG;
static const int WC_ALGO_TYPE_SEED;
static const int WC_ALGO_TYPE_HMAC;
static const int WC_ALGO_TYPE_CMAC;
static const int WC_ALGO_TYPE_CERT;
static const int WC_ALGO_TYPE_KDF;
static const int WC_ALGO_TYPE_COPY;
static const int WC_ALGO_TYPE_FREE;
static const int WC_ALGO_TYPE_MAX;

static const int WC_HASH_TYPE_SHA; /* SHA-1 (not old SHA-0) */
static const int WC_HASH_TYPE_SHA256;
static const int WC_HASH_TYPE_SHA384;
static const int WC_HASH_TYPE_SHA512;
static const int WC_HASH_TYPE_SHA3_256;
static const int WC_HASH_TYPE_SHA3_384;
static const int WC_HASH_TYPE_SHA3_512;
"""


cdef += """
typedef struct {
int algo_type; /* enum wc_AlgoType */
union {
"""

# The following block is commented out as there are issues with cffi code generation for the
# wc_CryptoInfo structure with two layers of anonymous unions.
# Uncommenting more parts of the cipher struct causes errors regarding conflicting struct sizes of
# other parts of the wc_CryptoInfo struct.
# Cffi cdef and the compiler seem to disagree.
#
# cdef += """
# struct {
# int type; /* enum wc_CipherType */
# int enc;
# union {
# //wc_CryptoCb_AesAuthEnc aesgcm_enc;
# //wc_CryptoCb_AesAuthDec aesgcm_dec;
# //wc_CryptoCb_AesAuthEnc aesccm_enc;
# //wc_CryptoCb_AesAuthDec aesccm_dec;
# struct {
# Aes* aes;
# byte* out;
# const byte* in;
# word32 sz;
# } aescbc;
# //struct {
# // Aes* aes;
# // byte* out;
# // const byte* in;
# // word32 sz;
# //} aesctr;
# //struct {
# // Aes* aes;
# // byte* out;
# // const byte* in;
# // word32 sz;
# //} aesecb;
# //struct {
# // Des3* des;
# // byte* out;
# // const byte* in;
# // word32 sz;
# //} des3;
# //void* ctx;
# };
# } cipher;
# """

cdef += """
Comment thread
dgarske marked this conversation as resolved.
struct {
int type; /* enum wc_HashType */
const byte* data;
word32 data_size;
byte* digest;
union {
"""
if features["SHA"]:
cdef += """
wc_Sha* sha1;
"""
if features["SHA256"]:
cdef += """
wc_Sha256* sha256;
"""
if features["SHA384"]:
cdef += """
wc_Sha384* sha384;
"""
if features["SHA512"]:
cdef += """
wc_Sha512* sha512;
"""
if features["SHA3"]:
cdef += """
wc_Sha3* sha3;
"""
cdef += """
void* ctx;
} u;
} hash;
"""
cdef += """
struct {
WC_RNG* rng;
byte* out;
word32 sz;
} rng;
};
...;
} wc_CryptoInfo;

typedef int (*CryptoDevCallbackFunc)(int devId, wc_CryptoInfo* info, void* ctx);
extern "Python" int py_wc_crypto_callback(int devId, wc_CryptoInfo* info, void* ctx);
int wc_CryptoCb_RegisterDevice(int devId, CryptoDevCallbackFunc cb, void* ctx);
void wc_CryptoCb_UnRegisterDevice(int devId);
int wc_CryptoCb_DefaultDevID();
// void wc_CryptoCb_InfoString(wc_CryptoInfo* info);
"""

ffibuilder.cdef(cdef)

def main(ffibuilder):
Expand Down Expand Up @@ -1400,6 +1534,7 @@ def main(ffibuilder):
"ML_DSA_NO_CTX": 0,
"HKDF": 1,
"HASHDRBG": 1,
"CRYPTO_CB": 1,
}

# Ed448 requires SHAKE256, which isn't part of the Windows build, yet.
Expand Down
Loading