Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
4ba0fd1
Fix wrong variable in NULL check after EVP_CIPHER_meth_new for AES-CB…
aidangarske Jun 17, 2026
7ed5e44
Validate record length in AES-CBC-HMAC TLS decrypt to prevent underflow
aidangarske Jun 17, 2026
35a9a2a
Handle NULL output length query in RSA private decrypt
aidangarske Jun 17, 2026
d9d3c6f
Use correct element size when copying RSA NID list into digest method
aidangarske Jun 17, 2026
411627c
Correct inverted NULL check on cipher data in we_aes_cbc_ctrl
aidangarske Jun 17, 2026
bfff84a
Correct inverted NULL check on cipher data in we_aes_ecb_ctrl
aidangarske Jun 17, 2026
46ae9c8
Correct inverted NULL check on cipher data in we_des3_cbc_ctrl
aidangarske Jun 17, 2026
86d15cf
Initialize AES-ECB key alongside wc_AesInit when key is provided
aidangarske Jun 17, 2026
29007f3
Reject unknown digest names in TLS1-PRF and HKDF ctrl_str handlers
aidangarske Jun 17, 2026
d25f537
Initialize ECDSA signature mp_ints once in direct sign path
aidangarske Jun 17, 2026
05b0870
Free DH generator buffer on all paths in key generation
aidangarske Jun 17, 2026
dee9486
Clamp GCM IV increment loop to avoid out-of-bounds write for short IVs
aidangarske Jun 17, 2026
bbf0e46
Propagate EVP_CIPHER_asn1_to_param failure in PBES2 key generation
aidangarske Jun 17, 2026
821b1ed
Return 0 not -1 from AES-CTR init on IV-set failure
aidangarske Jun 17, 2026
2f78625
Use AES block size for AES-CTR block counter modulus
aidangarske Jun 17, 2026
92dfc06
Log salt pointer not key in HKDF salt allocation failure
aidangarske Jun 17, 2026
e4e17ac
Advance buffer index by two after debug separator in hex dump
aidangarske Jun 17, 2026
308fbad
Fix mismatched endif comment in we_random.c
aidangarske Jun 17, 2026
3732cb2
Match RNG cleanup condition to RNG init condition
aidangarske Jun 17, 2026
70f603f
Only store RSA-PSS salt length when padding mode is PSS
aidangarske Jun 17, 2026
ddbb407
Free buffered GCM input before reallocating on repeated update
aidangarske Jun 17, 2026
c5a7898
Zeroize buffered GCM plaintext when freeing in final and cleanup
aidangarske Jun 17, 2026
5a3702b
Use clear_realloc to wipe relocated HMAC key padding buffer
aidangarske Jun 17, 2026
0e1cfe6
Free ASN1 key when EVP_PKEY_assign fails in HMAC keygen
aidangarske Jun 17, 2026
c629cb5
Free DH object when EVP_PKEY_assign_DH fails in paramgen
aidangarske Jun 17, 2026
0e92222
Free DH object when EVP_PKEY_assign_DH fails in keygen
aidangarske Jun 17, 2026
c6abe22
Free RSA object when EVP_PKEY_assign_RSA fails in keygen
aidangarske Jun 17, 2026
cbdd2ce
Zeroize HKDF salt buffer on context cleanup
aidangarske Jun 17, 2026
8342ade
Cleanse derived key and IV stack buffers in PBE key generation
aidangarske Jun 17, 2026
76b800f
Zeroize private key BIGNUMs in EC_KEY_oct2priv and DH_set0_key backports
aidangarske Jun 17, 2026
4265cbd
Reject GCM IV generation longer than the IV buffer
aidangarske Jun 17, 2026
ec8af66
Accept zero-length CMAC update to match OpenSSL and HMAC behavior
aidangarske Jun 17, 2026
8e224c2
Bound HMAC ASN1 private key length before narrowing to int
aidangarske Jun 17, 2026
39ea99a
Bound ECDSA signature SEQUENCE length parse to signature buffer
aidangarske Jun 17, 2026
3ed3afe
Pad HMAC key via portable malloc and clear_free instead of clear_realloc
aidangarske Jun 17, 2026
e1f923f
Size debug hex-dump line buffer for the two-byte separator
aidangarske Jun 17, 2026
8b5cd04
Swap GCM buffer only after successful allocation in update
aidangarske Jun 17, 2026
0bbcc46
Allow empty HMAC raw private key import while bounding length
aidangarske Jun 17, 2026
0f87f18
Skip stitched AES-CBC-HMAC and RSA no-padding query tests under FIPS
aidangarske Jun 17, 2026
73177c9
Guard remaining new negative tests under FIPS builds
aidangarske Jun 17, 2026
0a8e791
test: skip AES-CBC-HMAC-SHA256 short-record test when stitched cipher…
aidangarske Jun 17, 2026
5fdc1ca
Revert "Allow empty HMAC raw private key import while bounding length…
aidangarske Jun 18, 2026
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
27 changes: 13 additions & 14 deletions src/we_aes_block.c
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ static int we_aes_cbc_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)

/* Get the AES-CBC data to work with. */
aes = (we_AesBlock *)EVP_CIPHER_CTX_get_cipher_data(ctx);
if (aes != NULL) {
if (aes == NULL) {
WOLFENGINE_ERROR_FUNC_NULL(WE_LOG_CIPHER,
"EVP_CIPHER_CTX_get_cipher_data", aes);
ret = 0;
Expand Down Expand Up @@ -428,14 +428,24 @@ static int we_aes_ecb_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
ret = 0;
}

if ((ret == 1) && (key == NULL)) {
if ((ret == 1) && (key != NULL)) {
WOLFENGINE_MSG(WE_LOG_CIPHER,
"Initializing wolfCrypt Aes structure: %p", &aes->aes);
rc = wc_AesInit(&aes->aes, NULL, INVALID_DEVID);
if (rc != 0) {
WOLFENGINE_ERROR_FUNC(WE_LOG_CIPHER, "wc_AesInit", rc);
ret = 0;
}
if (ret == 1) {
WOLFENGINE_MSG(WE_LOG_CIPHER, "Setting AES key (%d bytes)",
EVP_CIPHER_CTX_key_length(ctx));
rc = wc_AesSetKey(&aes->aes, key, EVP_CIPHER_CTX_key_length(ctx),
NULL, enc ? AES_ENCRYPTION : AES_DECRYPTION);
if (rc != 0) {
WOLFENGINE_ERROR_FUNC(WE_LOG_CIPHER, "wc_AesSetKey", rc);
ret = 0;
}
}
}

if (ret == 1) {
Expand All @@ -444,17 +454,6 @@ static int we_aes_ecb_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
aes->enc = enc;
}

if ((ret == 1) && (key != NULL)) {
WOLFENGINE_MSG(WE_LOG_CIPHER, "Setting AES key (%d bytes)",
EVP_CIPHER_CTX_key_length(ctx));
rc = wc_AesSetKey(&aes->aes, key, EVP_CIPHER_CTX_key_length(ctx),
NULL, enc ? AES_ENCRYPTION : AES_DECRYPTION);
if (rc != 0) {
WOLFENGINE_ERROR_FUNC(WE_LOG_CIPHER, "wc_AesSetKey", rc);
ret = 0;
}
}

WOLFENGINE_LEAVE(WE_LOG_CIPHER, "we_aes_ecb_init", ret);

return ret;
Expand Down Expand Up @@ -732,7 +731,7 @@ static int we_aes_ecb_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)

/* Get the AES-ECB data to work with. */
aes = (we_AesBlock *)EVP_CIPHER_CTX_get_cipher_data(ctx);
if (aes != NULL) {
if (aes == NULL) {
WOLFENGINE_ERROR_FUNC_NULL(WE_LOG_CIPHER,
"EVP_CIPHER_CTX_get_cipher_data", aes);
ret = 0;
Expand Down
18 changes: 12 additions & 6 deletions src/we_aes_cbc_hmac.c
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,14 @@ static int we_aes_cbc_hmac_dec(we_AesCbcHmac* aes, unsigned char *out,
ret = -1;
}
if (ret != -1) {
/* Remove padding and MAC length. */
ret -= pb + 1 + SHA256_DIGEST_LENGTH;
/* Record must hold the padding and MAC or the length underflows. */
if (ret < pb + 1 + SHA256_DIGEST_LENGTH) {
ret = -1;
}
else {
/* Remove padding and MAC length. */
ret -= pb + 1 + SHA256_DIGEST_LENGTH;
}
}

/* Update record header to have correct message length. */
Expand Down Expand Up @@ -577,10 +583,10 @@ int we_init_aescbc_hmac_meths(void)
/* AES128-CBC HMAC-SHA256 */
we_aes128_cbc_hmac_ciph = EVP_CIPHER_meth_new(NID_aes_128_cbc_hmac_sha256,
WC_AES_BLOCK_SIZE, AES_128_KEY_SIZE);
if (we_aes128_cbc_ciph == NULL) {
if (we_aes128_cbc_hmac_ciph == NULL) {
WOLFENGINE_ERROR_FUNC_NULL(WE_LOG_CIPHER,
"EVP_CIPHER_meth_new - AES-128-CBC "
"HMAC SHA256", we_aes128_cbc_ciph);
"HMAC SHA256", we_aes128_cbc_hmac_ciph);
ret = 0;
}
if (ret == 1) {
Expand All @@ -591,10 +597,10 @@ int we_init_aescbc_hmac_meths(void)
if (ret == 1) {
we_aes256_cbc_hmac_ciph = EVP_CIPHER_meth_new(
NID_aes_256_cbc_hmac_sha256, WC_AES_BLOCK_SIZE, AES_256_KEY_SIZE);
if (we_aes256_cbc_ciph == NULL) {
if (we_aes256_cbc_hmac_ciph == NULL) {
WOLFENGINE_ERROR_FUNC_NULL(WE_LOG_CIPHER,
"EVP_CIPHER_meth_new - AES-256-CBC "
"HMAC SHA256", we_aes256_cbc_ciph);
"HMAC SHA256", we_aes256_cbc_hmac_ciph);
ret = 0;
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/we_aes_ctr.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ static int we_aes_ctr_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
rc = wc_AesSetIV(&aes->aes, iv);
if (rc != 0) {
WOLFENGINE_ERROR_FUNC(WE_LOG_CIPHER, "wc_AesSetIV", rc);
ret = -1;
ret = 0;
}
else {
/*
Expand Down Expand Up @@ -150,7 +150,7 @@ static int we_aes_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
}
else {
unsigned int num = EVP_CIPHER_CTX_num(ctx);
num = (num + len) % AES_128_KEY_SIZE;
num = (num + len) % WC_AES_BLOCK_SIZE;
EVP_CIPHER_CTX_set_num(ctx, num);

XMEMCPY(EVP_CIPHER_CTX_iv_noconst(ctx), aes->aes.reg,
Expand Down
29 changes: 15 additions & 14 deletions src/we_aes_gcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ static int we_aes_gcm_cleanup(EVP_CIPHER_CTX *ctx)
OPENSSL_free(aes->aad);
}
if (aes->tmp != NULL) {
OPENSSL_free(aes->tmp);
OPENSSL_clear_free(aes->tmp, aes->tmpLen);
aes->tmp = NULL;
}
aes->tmpLen = 0;
Expand Down Expand Up @@ -328,19 +328,19 @@ static int we_aes_gcm_update(we_AesGcm* aes, const unsigned char* in,
"out = %p]", aes, in, len, out);

if (len != 0 && in != NULL) {
aes->tmp = (unsigned char*)OPENSSL_malloc(len);
if (aes->tmp == NULL) {
WOLFENGINE_ERROR_FUNC_NULL(WE_LOG_CIPHER, "OPENSSL_malloc",
aes->tmp);
unsigned char *newTmp = (unsigned char*)OPENSSL_malloc(len);
if (newTmp == NULL) {
WOLFENGINE_ERROR_FUNC_NULL(WE_LOG_CIPHER, "OPENSSL_malloc", newTmp);
ret = -1;
}
else {
/*
* All encryption/decryption is deferred to we_aes_gcm_final. We
* just save the input data and the address of the output buffer
* here.
*/
XMEMCPY(aes->tmp, in, len);
/* Swap in the new buffer only on success so a failed allocation
* leaves the previously buffered state unchanged. */
if (aes->tmp != NULL) {
OPENSSL_clear_free(aes->tmp, aes->tmpLen);
}
XMEMCPY(newTmp, in, len);
aes->tmp = newTmp;
aes->tmpLen = (int)len;
aes->outputBuf = out;
/* Return length of buffered input data. */
Expand Down Expand Up @@ -430,7 +430,7 @@ static int we_aes_gcm_final(we_AesGcm* aes)
}

if (aes->tmp != NULL) {
OPENSSL_free(aes->tmp);
OPENSSL_clear_free(aes->tmp, aes->tmpLen);
aes->tmp = NULL;
}
aes->tmpLen = 0;
Expand All @@ -443,7 +443,7 @@ static int we_aes_gcm_final(we_AesGcm* aes)

if (aes->ivInc) {
int i;
for (i = aes->ivLen - 1; i >= aes->ivLen - 8; i--) {
for (i = aes->ivLen - 1; (i >= 0) && (i >= aes->ivLen - 8); i--) {
if ((++aes->iv[i]) != 0) {
break;
}
Expand Down Expand Up @@ -649,7 +649,8 @@ static int we_aes_gcm_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)
* arg [in] size of generated IV/nonce
* ptr [in] generated IV/nonce data
*/
if ((arg <= 0) || (arg > GCM_NONCE_MAX_SZ)) {
if ((arg <= 0) || (arg > GCM_NONCE_MAX_SZ) || (ptr == NULL) ||
(arg > aes->ivLen)) {
XSNPRINTF(errBuff, sizeof(errBuff), "Invalid nonce length "
"%d", arg);
WOLFENGINE_ERROR_MSG(WE_LOG_CIPHER, errBuff);
Expand Down
2 changes: 1 addition & 1 deletion src/we_des3_cbc.c
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ static int we_des3_cbc_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr)

/* Get the DES3-CBC data to work with. */
des3 = (we_Des3Cbc *)EVP_CIPHER_CTX_get_cipher_data(ctx);
if (des3 != NULL) {
if (des3 == NULL) {
WOLFENGINE_ERROR_FUNC_NULL(WE_LOG_CIPHER,
"EVP_CIPHER_CTX_get_cipher_data", des3);
ret = 0;
Expand Down
15 changes: 11 additions & 4 deletions src/we_dh.c
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,8 @@ static int we_dh_generate_key_int(DH *dh, we_Dh *engineDh)
unsigned int pubLen = 0;
BIGNUM *privBn = NULL;
BIGNUM *pubBn = NULL;
unsigned char *gBuf = NULL;
int gBufLen = 0;
#ifndef WE_DH_USE_GLOBAL_RNG
WC_RNG *pRng = &engineDh->rng;
#else
Expand Down Expand Up @@ -397,9 +399,6 @@ static int we_dh_generate_key_int(DH *dh, we_Dh *engineDh)
if (ret == 1) {
/* Check if private key already set. */
if ((privBn = (BIGNUM *)DH_get0_priv_key(dh)) != NULL) {
unsigned char *gBuf;
int gBufLen;

/* Get private key into buffer. */
privLen = BN_bn2bin(privBn, priv);
/* Get generator into buffer. */
Expand Down Expand Up @@ -494,6 +493,9 @@ static int we_dh_generate_key_int(DH *dh, we_Dh *engineDh)
if (pub != NULL) {
OPENSSL_free(pub);
}
if (gBuf != NULL) {
OPENSSL_free(gBuf);
}

WOLFENGINE_LEAVE(WE_LOG_KE, "we_dh_generate_key_int", ret);

Expand Down Expand Up @@ -1258,7 +1260,11 @@ static int we_dh_pkey_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)

if (ret == 1) {
/* Assign OpenSSL DH object to PKEY. */
EVP_PKEY_assign_DH(pkey, dh);
if (EVP_PKEY_assign_DH(pkey, dh) != 1) {
WOLFENGINE_ERROR_FUNC(WE_LOG_KE, "EVP_PKEY_assign_DH", 0);
DH_free(dh);
ret = 0;
}
}

if (ret == 1) {
Expand Down Expand Up @@ -1313,6 +1319,7 @@ static int we_dh_pkey_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
ret = EVP_PKEY_assign_DH(pkey, dh);
if (ret != 1) {
WOLFENGINE_ERROR_FUNC(WE_LOG_KE, "EVP_PKEY_assign_DH", ret);
DH_free(dh);
}
}

Expand Down
8 changes: 7 additions & 1 deletion src/we_digest.c
Original file line number Diff line number Diff line change
Expand Up @@ -981,9 +981,15 @@ static int we_init_digest_meth(EVP_MD *method)
if (ret == 1) {
const int *nids;
int cnt;
int maxCnt;

maxCnt = (int)(sizeof(method->required_pkey_type) /
sizeof(method->required_pkey_type[0]));
cnt = we_pkey_get_nids(&nids);
XMEMCPY(method->required_pkey_type, nids, cnt);
if (cnt > maxCnt) {
cnt = maxCnt;
}
XMEMCPY(method->required_pkey_type, nids, cnt * sizeof(*nids));
method->flags |= EVP_MD_FLAG_PKEY_METHOD_SIGNATURE;
}
#endif
Expand Down
33 changes: 18 additions & 15 deletions src/we_ecc.c
Original file line number Diff line number Diff line change
Expand Up @@ -834,8 +834,12 @@ static int we_pkey_ecdsa_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig,
}
}
/* wolfSSL FIPS is not checking SEQUENCE length. */
if ((ret == 1) && (sig[0] == 0x30)) {
size_t len;
if ((ret == 1) && ((sig == NULL) || (sigLen < 2))) {
WOLFENGINE_ERROR_MSG(WE_LOG_PK, "Signature too short");
ret = -1;
}
else if ((ret == 1) && (sig[0] == 0x30)) {
size_t len = 0;
int o = 1;

/* Check for indefinite length - length not specified. */
Expand All @@ -846,10 +850,17 @@ static int we_pkey_ecdsa_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig,
/* Check for multi-byte length. */
else if (sig[o] > 0x80) {
byte cnt = (sig[o++]) & 0x7f;
len = 0;
while ((cnt--) > 0) {
len <<= 8;
len += sig[o++];
/* Length bytes must be present and fit in the length variable. */
if ((cnt == 0) || (cnt > sizeof(len)) ||
((size_t)o + cnt > sigLen)) {
WOLFENGINE_ERROR_MSG(WE_LOG_PK, "Signature length invalid");
ret = -1;
}
else {
while ((cnt--) > 0) {
len <<= 8;
len += sig[o++];
}
}
}
/* Length in byte. */
Expand All @@ -858,7 +869,7 @@ static int we_pkey_ecdsa_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig,
}
/* Check signature length is:
* SEQUENCE header length + SQUENCE data length */
if ((ret == 1) && (o + len != sigLen)) {
if ((ret == 1) && ((size_t)o + len != sigLen)) {
WOLFENGINE_ERROR_MSG(WE_LOG_PK, "Signature length invalid");
ret = -1;
}
Expand Down Expand Up @@ -2106,14 +2117,6 @@ static ECDSA_SIG* we_ecdsa_do_sign_ex(const unsigned char *d, int dlen,
}
}

if (err == 0) {
rc = mp_init_multi(&sig_r, &sig_s, NULL, NULL, NULL, NULL);
if (rc != MP_OKAY) {
WOLFENGINE_ERROR_FUNC(WE_LOG_PK, "mp_init_multi", rc);
err = 1;
}
}

/* Sign hash with ECDSA */
if (err == 0) {
#if defined(WE_ECC_USE_GLOBAL_RNG) && !defined(WE_SINGLE_THREADED)
Expand Down
14 changes: 10 additions & 4 deletions src/we_hkdf.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ static void we_hkdf_cleanup(EVP_PKEY_CTX *ctx)
}
/* Clear and free salt. */
if (hkdf->salt != NULL) {
OPENSSL_free(hkdf->salt);
OPENSSL_clear_free(hkdf->salt, hkdf->saltSz);
}
/* Clear info - sensitive data. */
OPENSSL_cleanse(hkdf->info, hkdf->infoSz);
Expand Down Expand Up @@ -298,7 +298,7 @@ static int we_hkdf_ctrl(EVP_PKEY_CTX *ctx, int type, int num, void *ptr)
hkdf->salt = OPENSSL_memdup(ptr, num);
if (hkdf->salt == NULL) {
WOLFENGINE_ERROR_FUNC_NULL(WE_LOG_PK,
"OPENSSL_memdup(salt)", hkdf->key);
"OPENSSL_memdup(salt)", hkdf->salt);
ret = 0;
}
}
Expand Down Expand Up @@ -399,10 +399,16 @@ static int we_hkdf_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
}
#endif
else if (XSTRNCMP(type, "md", 3) == 0) {
const EVP_MD *md = EVP_get_digestbyname(value);
hkdf = (we_Hkdf *)EVP_PKEY_CTX_get_data(ctx);
/* Cannot get here without initialization succeeding. */
hkdf->mdType =
we_nid_to_wc_hash_type(EVP_MD_type(EVP_get_digestbyname(value)));
if (md == NULL) {
WOLFENGINE_ERROR_MSG(WE_LOG_PK, "Unsupported digest name");
ret = 0;
}
else {
hkdf->mdType = we_nid_to_wc_hash_type(EVP_MD_type(md));
}
}
else if (XSTRNCMP(type, "key", 4) == 0) {
ret = EVP_PKEY_CTX_str2ctrl(ctx, EVP_PKEY_CTRL_HKDF_KEY, value);
Expand Down
3 changes: 2 additions & 1 deletion src/we_internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -1148,7 +1148,8 @@ static int wolfengine_destroy(ENGINE *e)
EVP_MD_meth_free(we_ecdsa_sha1_md);
we_ecdsa_sha1_md = NULL;
#endif
#if defined(WE_HAVE_ECC) || defined(WE_HAVE_AESGCM) || defined(WE_HAVE_RSA)
#if defined(WE_HAVE_ECC) || defined(WE_HAVE_AESGCM) || defined(WE_HAVE_RSA) || \
defined(WE_HAVE_DH) || defined(WE_HAVE_RANDOM)
we_final_random();
#endif

Expand Down
4 changes: 2 additions & 2 deletions src/we_logging.c
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ void WOLFENGINE_BUFFER(int component, const unsigned char* buffer,
unsigned int length)
{
int i, buflen = (int)length, bufidx;
char line[(WOLFENGINE_LINE_LEN * 4) + 3]; /* \t00..0F | chars...chars\0 */
char line[(WOLFENGINE_LINE_LEN * 4) + 4]; /* \t00..0F | chars...chars\0 */

if (!loggingEnabled) {
return;
Expand Down Expand Up @@ -386,7 +386,7 @@ void WOLFENGINE_BUFFER(int component, const unsigned char* buffer,
}

XSNPRINTF(&line[bufidx], sizeof(line)-bufidx, "| ");
bufidx++;
bufidx += 2;

for (i = 0; i < WOLFENGINE_LINE_LEN; i++) {
if (i < buflen) {
Expand Down
Loading