Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
7bb76c4
Create genkey private key files with owner-only permissions
julek-wolfssl Sep 23, 2026
4fbddc9
Create pkcs8 output files with owner-only permissions
julek-wolfssl Sep 23, 2026
6f169f1
Create rsa private key output with owner-only permissions
julek-wolfssl Sep 23, 2026
cb79142
Create dsaparam -genkey output with owner-only permissions
julek-wolfssl Sep 23, 2026
22e3f0f
Create pkcs12 -out files with owner-only permissions
julek-wolfssl Sep 23, 2026
73543d4
Create req -keyout private key with owner-only permissions
julek-wolfssl Sep 23, 2026
6606924
Fail s_server on compiled-out protocol versions
julek-wolfssl Sep 23, 2026
86cec9c
Bound s_server throughput remainder before narrowing to int
julek-wolfssl Sep 23, 2026
576e8fe
Reject abbreviated or unsupported cipher modes in parseAlgo
julek-wolfssl Sep 23, 2026
d01da47
Fail cleanly on EOF at the interactive password prompt
julek-wolfssl Sep 23, 2026
8f799e7
Mark padding in legacy encrypt header for explicit key/IV
julek-wolfssl Sep 23, 2026
83767e7
x509: only force version 3 when signing a CSR
julek-wolfssl Sep 23, 2026
3d11ff7
x509: fail -fingerprint when SHA-1 or hashing is unavailable
julek-wolfssl Sep 23, 2026
cf023bf
Reset -subj entry encoding after countryName
julek-wolfssl Sep 23, 2026
cc95ce3
Parse basicConstraints as comma separated NAME:VALUE pairs
julek-wolfssl Sep 23, 2026
d1df4a0
Write PKCS#8 DER for pkcs8 -topk8 -outform DER
julek-wolfssl Sep 23, 2026
324e0c2
Create pkey private key output with owner-only permissions
julek-wolfssl Sep 23, 2026
815bd89
Create dhparam -genkey output with owner-only permissions
julek-wolfssl Sep 23, 2026
e013169
Create ecparam -genkey output with owner-only permissions
julek-wolfssl Sep 23, 2026
425bba5
Verify req -x509 output as a certificate, not a CSR
julek-wolfssl Sep 23, 2026
eda40ac
Serialize XMSS signing with a lock on the private state file
julek-wolfssl Sep 23, 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
13 changes: 13 additions & 0 deletions certs/server-ecc-v1-cert.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
-----BEGIN CERTIFICATE-----
MIIB8DCCAZcCAWUwCgYIKoZIzj0EAwIwgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQI
DApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQKDAd3b2xmU1NM
MRQwEgYDVQQLDAtEZXZlbG9wbWVudDEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29t
MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMB4XDTI2MDkyMzEyMTc1
MFoXDTI5MDYxOTEyMTc1MFowcTELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRh
bmExEDAOBgNVBAcMB0JvemVtYW4xEDAOBgNVBAoMB3dvbGZTU0wxEjAQBgNVBAsM
CVZlcnNpb24gMTEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29tMFkwEwYHKoZIzj0C
AQYIKoZIzj0DAQcDQgAEuzOsTCdQSsZKpQTDPN6fNttyLc6U6iv6yyAJOSwW6GEC
6a9N0wKTmjFbl5Ihf/DPGNqREQI0huggWDMLgDSJ2DAKBggqhkjOPQQDAgNHADBE
AiBU/5sbyAc2PPZmKswh5G7wy8vONxP1Jm2Is99fyJ1eWwIgHYNyWJIW8ehRk51A
a2aKxD5x4CAF/vh3A6KR+5w+ktw=
-----END CERTIFICATE-----
2 changes: 1 addition & 1 deletion src/crypto/clu_crypto_setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ int wolfCLU_setup(int argc, char** argv, char action)
char outNameDec[256]; /* default outfile for decrypt */
char inName[256]; /* name of the in File if not provided */

int alg; /* algorithm from name */
int alg = WOLFCLU_ALGO_NONE; /* algorithm from name */
char* mode = NULL; /* mode from name */
char* out = NULL; /* default output file name */
char* in = inName; /* default in data */
Expand Down
5 changes: 5 additions & 0 deletions src/crypto/clu_encrypt.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@ int wolfCLU_encrypt(int alg, char* mode, byte* pwdKey, byte* key, int size,
key[i] = pwdKey[i];
}
}
else {
/* explicit key: salt is unused, but a non-zero salt[0] tells
* decrypt to strip the padding */
salt[0] = (byte)padCounter;
}

/* open the outFile in write mode */
outFile = XFOPEN(out, "wb");
Expand Down
8 changes: 7 additions & 1 deletion src/dh/clu_dh.c
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,13 @@ int wolfCLU_DhParamSetup(int argc, char** argv)
WOLFCLU_LOG(WOLFCLU_E0, "No filesystem support. Unable to open output file");
ret = WOLFCLU_FATAL_ERROR;
#else
bioOut = wolfSSL_BIO_new_file(out, "wb");
/* a generated key is private, so create the file owner-only */
if (genKey) {
bioOut = wolfCLU_BioOpenOwner(out);
}
else {
bioOut = wolfSSL_BIO_new_file(out, "wb");
}
if (bioOut == NULL) {
wolfCLU_LogError("Unable to open output file %s",
optarg);
Expand Down
8 changes: 7 additions & 1 deletion src/dsa/clu_dsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,13 @@ int wolfCLU_DsaParamSetup(int argc, char** argv)
WOLFCLU_LOG(WOLFCLU_E0, "No filesystem support. Unable to open input file");
ret = WOLFCLU_FATAL_ERROR;
#else
bioOut = wolfSSL_BIO_new_file(out, "wb");
/* a generated key is private, so create the file owner-only */
if (genKey) {
bioOut = wolfCLU_BioOpenOwner(out);
}
else {
bioOut = wolfSSL_BIO_new_file(out, "wb");
}
if (bioOut == NULL) {
wolfCLU_LogError("Unable to open output file %s",
optarg);
Expand Down
8 changes: 7 additions & 1 deletion src/ecparam/clu_ecparam.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,13 @@ int wolfCLU_ecparam(int argc, char** argv)
WOLFCLU_LOG(WOLFCLU_E0, "No filesystem support. Unable to open input file");
ret = WOLFCLU_FATAL_ERROR;
#else
bioOut = wolfSSL_BIO_new_file(out, "wb");
/* a generated key is private, so create the file owner-only */
if (genKey) {
bioOut = wolfCLU_BioOpenOwner(out);
}
else {
bioOut = wolfSSL_BIO_new_file(out, "wb");
}
if (bioOut == NULL) {
ret = WOLFCLU_FATAL_ERROR;
}
Expand Down
89 changes: 82 additions & 7 deletions src/genkey/clu_genkey.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@
#include <wolfclu/x509/clu_parse.h>
#include <wolfclu/x509/clu_cert.h> /* PER_FORM/DER_FORM */

#if defined(WOLFSSL_HAVE_XMSS) && defined(WOLFCLU_POSIX_FILE)
#include <errno.h>
#include <fcntl.h>
#include <sys/file.h>
#define WOLFCLU_XMSS_POSIX
#endif

#ifdef HAVE_ED25519
/* return WOLFCLU_SUCCESS on success */
int wolfCLU_genKey_ED25519(WC_RNG* rng, char* fOutNm, int directive, int format)
Expand Down Expand Up @@ -121,7 +128,7 @@ int wolfCLU_genKey_ED25519(WC_RNG* rng, char* fOutNm, int directive, int format)

/* open the file for writing the private key */
if (ret == 0) {
file = XFOPEN(finalOutFNm, "wb");
file = wolfCLU_FileOpenOwner(finalOutFNm);
if (!file) {
ret = OUTPUT_FILE_ERROR;
}
Expand Down Expand Up @@ -663,7 +670,7 @@ int wolfCLU_GenAndOutput_ECC(WC_RNG* rng, char* fName, int directive,
fOutNameBuf[fNameSz + fExtSz] = '\0';
WOLFCLU_LOG(WOLFCLU_L0, "Private key file = %s", fOutNameBuf);

bioPri = wolfSSL_BIO_new_file(fOutNameBuf, "wb");
bioPri = wolfCLU_BioOpenOwner(fOutNameBuf);
if (bioPri == NULL) {
wolfCLU_LogError("unable to read outfile %s",
fOutNameBuf);
Expand Down Expand Up @@ -849,7 +856,7 @@ int wolfCLU_genKey_RSA(WC_RNG* rng, char* fName, int directive, int fmt, int

/* open the file for writing the private key */
if (ret == WOLFCLU_SUCCESS) {
file = XFOPEN(fOutNameBuf, "wb");
file = wolfCLU_FileOpenOwner(fOutNameBuf);
if (!file) {
ret = OUTPUT_FILE_ERROR;
}
Expand Down Expand Up @@ -1180,7 +1187,7 @@ int wolfCLU_genKey_Dilithium(WC_RNG* rng, char* fName, int directive, int fmt,

/* open file and write Private key */
if (ret == WOLFCLU_SUCCESS) {
file = XFOPEN(fOutNameBuf, "wb");
file = wolfCLU_FileOpenOwner(fOutNameBuf);
if (file == XBADFILE) {
wolfCLU_LogError("unable to open file %s",
fOutNameBuf);
Expand Down Expand Up @@ -1428,7 +1435,7 @@ int wolfCLU_genKey_ML_DSA(WC_RNG* rng, char* fName, int directive, int fmt,

/* open file and write Private key */
if (ret == WOLFCLU_SUCCESS) {
file = XFOPEN(fOutNameBuf, "wb");
file = wolfCLU_FileOpenOwner(fOutNameBuf);
if (file == XBADFILE) {
wolfCLU_LogError("unable to open file %s",
fOutNameBuf);
Expand Down Expand Up @@ -1582,9 +1589,9 @@ enum wc_XmssRc wolfCLU_XmssKey_WriteCb(const byte * priv,
file = fopen(filename, "rb+");
if (!file) {
/* Create the file if it didn't exist. */
file = fopen(filename, "wb+");
file = wolfCLU_FileOpenOwner(filename);
if (!file) {
fprintf(stderr, "error: fopen(%s, \"w+\") failed.\n", filename);
fprintf(stderr, "error: unable to create %s\n", filename);
return WC_XMSS_RC_WRITE_FAIL;
}
}
Expand All @@ -1598,6 +1605,26 @@ enum wc_XmssRc wolfCLU_XmssKey_WriteCb(const byte * priv,
return WC_XMSS_RC_WRITE_FAIL;
}

/* The new state must reach the disk before the signature is used. */
err = XFFLUSH(file);
#ifdef WOLFCLU_XMSS_POSIX
if (err == 0) {
err = fsync(fileno(file));
}
#ifdef F_FULLFSYNC
/* macOS fsync() does not flush the drive cache. Not all file systems
* support this, so a failure is ignored. */
if (err == 0) {
(void)fcntl(fileno(file), F_FULLFSYNC);
}
#endif
#endif
if (err) {
fprintf(stderr, "error: flushing %s failed\n", filename);
fclose(file);
return WC_XMSS_RC_WRITE_FAIL;
}

err = fclose(file);
if (err) {
fprintf(stderr, "error: fclose returned %d\n", err);
Expand Down Expand Up @@ -1683,6 +1710,54 @@ enum wc_XmssRc wolfCLU_XmssKey_ReadCb(byte * priv,

return WC_XMSS_RC_READ_TO_MEMORY;
}

/* Lock the private key file so only one process loads, signs and saves the
* one-time key state at a time. flock() is used because, unlike fcntl()
* locks, it is not released when the callbacks close their own handles.
* No lock is taken on other platforms. */
int wolfCLU_XmssKey_Lock(const char* fileName, XFILE* lockFile)
{
#ifdef WOLFCLU_XMSS_POSIX
XFILE file;
int err;
#endif

if (fileName == NULL || lockFile == NULL) {
return WOLFCLU_FATAL_ERROR;
}
*lockFile = XBADFILE;

#ifdef WOLFCLU_XMSS_POSIX
/* NFS only allows an exclusive flock() on a file open for writing. */
file = XFOPEN(fileName, "r+b");
if (file == XBADFILE) {
wolfCLU_LogError("Unable to open %s: %s", fileName, strerror(errno));
return WOLFCLU_FATAL_ERROR;
}

/* wolfSSL has no file lock wrapper */
do {
err = flock(fileno(file), LOCK_EX);
} while (err != 0 && errno == EINTR);

if (err != 0) {
wolfCLU_LogError("Unable to lock %s: %s", fileName, strerror(errno));
XFCLOSE(file);
return WOLFCLU_FATAL_ERROR;
}
*lockFile = file;
#endif

return WOLFCLU_SUCCESS;
}

void wolfCLU_XmssKey_Unlock(XFILE lockFile)
{
/* Closing the file releases the lock. */
if (lockFile != XBADFILE) {
XFCLOSE(lockFile);
}
}
#endif /* WOLFSSL_HAVE_XMSS */

int wolfCLU_genKey_XMSS(WC_RNG* rng, char* fName,
Expand Down
34 changes: 27 additions & 7 deletions src/pkcs/clu_pkcs12.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ int wolfCLU_PKCS12(int argc, char** argv)
WOLF_STACK_OF(WOLFSSL_X509) *extra = NULL;
WOLFSSL_BIO *bioIn = NULL;
WOLFSSL_BIO *bioOut = NULL;
char *outFile = NULL;

opterr = 0; /* do not display unrecognized options */
optind = 0; /* start at indent 0 */
Expand Down Expand Up @@ -115,10 +116,9 @@ int wolfCLU_PKCS12(int argc, char** argv)
break;

case WOLFCLU_OUTFILE:
bioOut = wolfSSL_BIO_new_file(optarg, "wb");
if (bioOut == NULL) {
wolfCLU_LogError("Unable to open output file %s",
optarg);
outFile = optarg;
if (outFile == NULL) {
wolfCLU_LogError("-out requires a file name");
ret = WOLFCLU_FATAL_ERROR;
}
break;
Expand All @@ -140,6 +140,20 @@ int wolfCLU_PKCS12(int argc, char** argv)
}
}

/* output with a key, even encrypted, is created owner only */
if (ret == WOLFCLU_SUCCESS && outFile != NULL) {
if (printKeys) {
bioOut = wolfCLU_BioOpenOwner(outFile);
}
else {
bioOut = wolfSSL_BIO_new_file(outFile, "wb");
}
if (bioOut == NULL) {
wolfCLU_LogError("Unable to open output file %s", outFile);
ret = WOLFCLU_FATAL_ERROR;
}
}

/* with currently only supporting PKCS12 parsing, an input file is expected */
if (ret == WOLFCLU_SUCCESS && bioIn == NULL) {
wolfCLU_LogError("No input file set");
Expand Down Expand Up @@ -227,9 +241,15 @@ int wolfCLU_PKCS12(int argc, char** argv)
if (ret == WOLFCLU_SUCCESS && pkey != NULL && printKeys) {
if (useDES) {
passwordSz = MAX_PASSWORD_SIZE;
wolfCLU_GetStdinPassword((byte*)password, (word32*)&passwordSz);
ret = wolfCLU_pKeyPEMtoPriKeyEnc(bioOut, pkey, DES3b,
(byte*)password, passwordSz);
ret = wolfCLU_GetStdinPassword((byte*)password,
(word32*)&passwordSz);
if (ret != WOLFCLU_SUCCESS) {
wolfCLU_LogError("Unable to get password from stdin");
}
else {
ret = wolfCLU_pKeyPEMtoPriKeyEnc(bioOut, pkey, DES3b,
(byte*)password, passwordSz);
}
}
else {
ret = wolfCLU_pKeyPEMtoPriKey(bioOut, pkey);
Expand Down
32 changes: 29 additions & 3 deletions src/pkcs/clu_pkcs8.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ int wolfCLU_PKCS8(int argc, char** argv)
break;

case WOLFCLU_OUTFILE:
bioOut = wolfSSL_BIO_new_file(optarg, "wb");
bioOut = wolfCLU_BioOpenOwner(optarg);
if (bioOut == NULL) {
wolfCLU_LogError("Unable to open output file %s",
optarg);
Expand Down Expand Up @@ -213,7 +213,10 @@ int wolfCLU_PKCS8(int argc, char** argv)
}

if (ret == WOLFCLU_SUCCESS && pass == NULL && pkey == NULL) {
wolfCLU_GetStdinPassword((byte*)password, (word32*)&passwordSz);
ret = wolfCLU_GetStdinPassword((byte*)password, (word32*)&passwordSz);
if (ret != WOLFCLU_SUCCESS) {
wolfCLU_LogError("Unable to get password from stdin");
}
pass = (byte*)password;
}

Expand Down Expand Up @@ -258,7 +261,27 @@ int wolfCLU_PKCS8(int argc, char** argv)
unsigned char *der = NULL;
int derSz = 0;

if ((derSz = wolfCLU_pKeytoPriKey(pkey, &der)) <= 0) {
derSz = wolfCLU_pKeytoPriKey(pkey, &der);

/* -topk8 wraps the key in a PKCS#8 PrivateKeyInfo. Wrap the
* re-encoded key, since the cached input may already be PKCS#8. */
if (derSz > 0 && toPkcs8 == 1 && traditional == 0) {
const unsigned char *p = der;
WOLFSSL_EVP_PKEY *tradKey;

tradKey = wolfSSL_d2i_PrivateKey(wolfSSL_EVP_PKEY_id(pkey),
NULL, &p, derSz);
wolfCLU_ForceZero(der, (unsigned int)derSz);
XFREE(der, HEAP_HINT, DYNAMIC_TYPE_OPENSSL);
der = NULL;
derSz = 0;
if (tradKey != NULL) {
derSz = wolfSSL_i2d_PKCS8_PKEY(tradKey, &der);
wolfSSL_EVP_PKEY_free(tradKey);
}
}

if (derSz <= 0) {
WOLFCLU_LOG(WOLFCLU_E0,
"Error converting private key to der");
ret = WOLFCLU_FATAL_ERROR;
Expand All @@ -270,6 +293,9 @@ int wolfCLU_PKCS8(int argc, char** argv)
}

if (der != NULL) {
if (derSz > 0) {
wolfCLU_ForceZero(der, (unsigned int)derSz);
}
XFREE(der, HEAP_HINT, DYNAMIC_TYPE_OPENSSL);
}
}
Expand Down
22 changes: 18 additions & 4 deletions src/pkey/clu_pkey.c
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,7 @@ int wolfCLU_pKeySetup(int argc, char** argv)
int pubOut = 0;
int option;
int longIndex = 1;
char *outFile = NULL;
WOLFSSL_EVP_PKEY *pkey = NULL;
WOLFSSL_BIO *bioIn = NULL;
WOLFSSL_BIO *bioOut = NULL;
Expand Down Expand Up @@ -453,10 +454,9 @@ int wolfCLU_pKeySetup(int argc, char** argv)
break;

case WOLFCLU_OUTFILE:
bioOut = wolfSSL_BIO_new_file(optarg, "wb");
if (bioOut == NULL) {
wolfCLU_LogError("Unable to open output file %s",
optarg);
outFile = optarg;
if (outFile == NULL) {
wolfCLU_LogError("-out requires a file name");
ret = WOLFCLU_FATAL_ERROR;
}
break;
Expand Down Expand Up @@ -509,6 +509,20 @@ int wolfCLU_pKeySetup(int argc, char** argv)
}
}

/* open -out once options are known. A private key file is owner-only */
if (ret == WOLFCLU_SUCCESS && outFile != NULL) {
if (pubOut) {
bioOut = wolfSSL_BIO_new_file(outFile, "wb");
}
else {
bioOut = wolfCLU_BioOpenOwner(outFile);
}
if (bioOut == NULL) {
wolfCLU_LogError("Unable to open output file %s", outFile);
ret = WOLFCLU_FATAL_ERROR;
}
}

if (ret == WOLFCLU_SUCCESS && bioOut == NULL) {
bioOut = wolfSSL_BIO_new(wolfSSL_BIO_s_file());
if (bioOut == NULL) {
Expand Down
Loading
Loading