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
3f59a49
Create genkey private key files with owner-only permissions
julek-wolfssl Sep 23, 2026
32dd225
Create pkcs8 output files with owner-only permissions
julek-wolfssl Sep 23, 2026
b618409
Create rsa private key output with owner-only permissions
julek-wolfssl Sep 23, 2026
dbc98f8
Create dsaparam -genkey output with owner-only permissions
julek-wolfssl Sep 23, 2026
14e4b65
Create pkcs12 -out files with owner-only permissions
julek-wolfssl Sep 23, 2026
a11eede
Create req -keyout private key with owner-only permissions
julek-wolfssl Sep 23, 2026
6a59c71
Fail s_server on compiled-out protocol versions
julek-wolfssl Sep 23, 2026
3cba222
Bound s_server throughput remainder before narrowing to int
julek-wolfssl Sep 23, 2026
f57dc8a
Reject abbreviated or unsupported cipher modes in parseAlgo
julek-wolfssl Sep 23, 2026
70a8944
Fail cleanly on EOF at the interactive password prompt
julek-wolfssl Sep 23, 2026
44e3887
Mark padding in legacy encrypt header for explicit key/IV
julek-wolfssl Sep 23, 2026
1be9ea4
x509: only force version 3 when signing a CSR
julek-wolfssl Sep 23, 2026
b664922
x509: fail -fingerprint when SHA-1 or hashing is unavailable
julek-wolfssl Sep 23, 2026
5968609
Reset -subj entry encoding after countryName
julek-wolfssl Sep 23, 2026
ea3c36f
Parse basicConstraints as comma separated NAME:VALUE pairs
julek-wolfssl Sep 23, 2026
793134f
Write PKCS#8 DER for pkcs8 -topk8 -outform DER
julek-wolfssl Sep 23, 2026
b8d2176
Create pkey private key output with owner-only permissions
julek-wolfssl Sep 23, 2026
8c873b1
Create dhparam -genkey output with owner-only permissions
julek-wolfssl Sep 23, 2026
8d1766f
Create ecparam -genkey output with owner-only permissions
julek-wolfssl Sep 23, 2026
77dfeac
Verify req -x509 output as a certificate, not a CSR
julek-wolfssl Sep 23, 2026
a3c4288
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 @@ -146,6 +146,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
33 changes: 29 additions & 4 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,7 +293,9 @@ int wolfCLU_PKCS8(int argc, char** argv)
}

if (der != NULL) {
wolfCLU_ForceZero(der, derSz);
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 @@ -513,6 +513,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 @@ -545,10 +546,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 @@ -601,6 +601,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