mirror of https://github.com/wolfSSL/wolfssh.git
added ml-dsa plain key and cert algorithms
parent
422f69de8b
commit
c56dc1027f
27
README.md
27
README.md
|
|
@ -451,22 +451,30 @@ The wolfSSH client and server will automatically negotiate using Curve25519.
|
|||
POST-QUANTUM
|
||||
============
|
||||
|
||||
wolfSSH now supports the post-quantum algorithm ML-KEM (formerly known as
|
||||
Kyber). It uses the ML-KEM-768 parameter set and is hybridized with ECDHE over
|
||||
the P-256 ECC curve.
|
||||
wolfSSH supports both post-quantum key exchange via ML-KEM (formerly known as
|
||||
Kyber) and post-quantum signature verification via ML-DSA (formerly known as
|
||||
Dilithium).
|
||||
|
||||
In order to use this key exchange you must build and install wolfSSL on your
|
||||
system. Here is an example of an effective configuration:
|
||||
* **ML-KEM**: Uses the ML-KEM-768 parameter set hybridized with ECDHE over the
|
||||
P-256 ECC curve.
|
||||
* **ML-DSA**: Supports ML-DSA-44, ML-DSA-65, and ML-DSA-87 parameter sets for
|
||||
both server host keys and client public key authentication. When built with
|
||||
certificate support, ML-DSA X.509 certificates (`x509v3-ssh-mldsa-44`,
|
||||
`x509v3-ssh-mldsa-65`, and `x509v3-ssh-mldsa-87`) are also supported.
|
||||
|
||||
$ ./configure --enable-wolfssh --enable-mlkem
|
||||
In order to use these algorithms you must build and install wolfSSL with
|
||||
support for them. Here is an example of an effective configuration:
|
||||
|
||||
After that, simply configure and build wolfssh as usual:
|
||||
$ ./configure --enable-wolfssh --enable-mlkem --enable-mldsa
|
||||
|
||||
After that, configure and build wolfSSH as usual:
|
||||
|
||||
$ ./configure
|
||||
$ make all
|
||||
|
||||
The wolfSSH client and server will automatically negotiate using ML-KEM-768
|
||||
hybridized with ECDHE over the P-256 ECC curve.
|
||||
hybridized with ECDHE over the P-256 ECC curve and ML-DSA for host keys/client
|
||||
public key authentication.
|
||||
|
||||
$ ./examples/echoserver/echoserver -f
|
||||
|
||||
|
|
@ -476,7 +484,7 @@ On the client side, you will see the following output:
|
|||
|
||||
Server said: Hello, wolfSSH!
|
||||
|
||||
If you want to see interoperability with OpenQauntumSafe's fork of OpenSSH, you
|
||||
If you want to see interoperability with OpenQuantumSafe's fork of OpenSSH, you
|
||||
can build and execute the fork while the echoserver is running. Download the
|
||||
release from here:
|
||||
|
||||
|
|
@ -498,6 +506,7 @@ NOTE: when prompted, enter the password which is "upthehill".
|
|||
You can type a line of text and when you press enter, the line will be echoed
|
||||
back. Use CTRL-C to terminate the connection.
|
||||
|
||||
|
||||
CERTIFICATE SUPPORT
|
||||
===================
|
||||
|
||||
|
|
|
|||
|
|
@ -118,7 +118,18 @@ struct WOLFSSHD_AUTH {
|
|||
#endif
|
||||
|
||||
#ifndef MAX_LINE_SZ
|
||||
#define MAX_LINE_SZ 900
|
||||
/* Sized to hold the largest authorized_keys entry. */
|
||||
#ifndef WOLFSSH_NO_MLDSA
|
||||
#ifndef WOLFSSH_NO_MLDSA87
|
||||
#define MAX_LINE_SZ ((WC_MLDSA_87_PUB_KEY_SIZE + 2) / 3 * 4 + 640)
|
||||
#elif !defined(WOLFSSH_NO_MLDSA65)
|
||||
#define MAX_LINE_SZ ((WC_MLDSA_65_PUB_KEY_SIZE + 2) / 3 * 4 + 640)
|
||||
#else
|
||||
#define MAX_LINE_SZ ((WC_MLDSA_44_PUB_KEY_SIZE + 2) / 3 * 4 + 640)
|
||||
#endif
|
||||
#else
|
||||
#define MAX_LINE_SZ 900
|
||||
#endif
|
||||
#endif
|
||||
#ifndef MAX_PATH_SZ
|
||||
#define MAX_PATH_SZ 80
|
||||
|
|
@ -186,14 +197,7 @@ static int CheckAuthKeysLine(char* line, word32 lineSz, const byte* key,
|
|||
word32 keyCandSz = 0;
|
||||
char* last = NULL;
|
||||
|
||||
enum {
|
||||
#ifdef WOLFSSH_CERTS
|
||||
NUM_ALLOWED_TYPES = 9
|
||||
#else
|
||||
NUM_ALLOWED_TYPES = 5
|
||||
#endif
|
||||
};
|
||||
static const char* allowedTypes[NUM_ALLOWED_TYPES] = {
|
||||
static const char* allowedTypes[] = {
|
||||
"ssh-rsa",
|
||||
"ssh-ed25519",
|
||||
"ecdsa-sha2-nistp256",
|
||||
|
|
@ -205,7 +209,31 @@ static int CheckAuthKeysLine(char* line, word32 lineSz, const byte* key,
|
|||
"x509v3-ecdsa-sha2-nistp384",
|
||||
"x509v3-ecdsa-sha2-nistp521",
|
||||
#endif
|
||||
#ifndef WOLFSSH_NO_MLDSA
|
||||
#ifndef WOLFSSH_NO_MLDSA44
|
||||
"ssh-mldsa-44",
|
||||
#endif
|
||||
#ifndef WOLFSSH_NO_MLDSA65
|
||||
"ssh-mldsa-65",
|
||||
#endif
|
||||
#ifndef WOLFSSH_NO_MLDSA87
|
||||
"ssh-mldsa-87",
|
||||
#endif
|
||||
#ifdef WOLFSSH_CERTS
|
||||
#ifndef WOLFSSH_NO_MLDSA44
|
||||
"x509v3-ssh-mldsa-44",
|
||||
#endif
|
||||
#ifndef WOLFSSH_NO_MLDSA65
|
||||
"x509v3-ssh-mldsa-65",
|
||||
#endif
|
||||
#ifndef WOLFSSH_NO_MLDSA87
|
||||
"x509v3-ssh-mldsa-87",
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
const int NUM_ALLOWED_TYPES =
|
||||
(int)(sizeof(allowedTypes) / sizeof(allowedTypes[0]));
|
||||
int typeOk = 0;
|
||||
int i;
|
||||
|
||||
|
|
|
|||
|
|
@ -1806,6 +1806,123 @@ static int load_key_ed25519(byte* buf, word32 bufSz)
|
|||
#endif /* WOLFSSH_NO_ED25519 */
|
||||
|
||||
|
||||
#ifndef WOLFSSH_NO_MLDSA44
|
||||
static int load_key_mldsa44(byte* buf, word32 bufSz)
|
||||
{
|
||||
word32 sz = 0;
|
||||
#ifndef NO_FILESYSTEM
|
||||
sz = load_file("./keys/server-key-mldsa44.der", buf, &bufSz);
|
||||
#else
|
||||
(void)buf; (void)bufSz;
|
||||
#endif
|
||||
return sz;
|
||||
}
|
||||
#endif /* WOLFSSH_NO_MLDSA44 */
|
||||
|
||||
#ifndef WOLFSSH_NO_MLDSA65
|
||||
static int load_key_mldsa65(byte* buf, word32 bufSz)
|
||||
{
|
||||
word32 sz = 0;
|
||||
#ifndef NO_FILESYSTEM
|
||||
sz = load_file("./keys/server-key-mldsa65.der", buf, &bufSz);
|
||||
#else
|
||||
(void)buf; (void)bufSz;
|
||||
#endif
|
||||
return sz;
|
||||
}
|
||||
#endif /* WOLFSSH_NO_MLDSA65 */
|
||||
|
||||
#ifndef WOLFSSH_NO_MLDSA87
|
||||
static int load_key_mldsa87(byte* buf, word32 bufSz)
|
||||
{
|
||||
word32 sz = 0;
|
||||
#ifndef NO_FILESYSTEM
|
||||
sz = load_file("./keys/server-key-mldsa87.der", buf, &bufSz);
|
||||
#else
|
||||
(void)buf; (void)bufSz;
|
||||
#endif
|
||||
return sz;
|
||||
}
|
||||
#endif /* WOLFSSH_NO_MLDSA87 */
|
||||
|
||||
|
||||
#ifndef WOLFSSH_NO_MLDSA
|
||||
static int LoadMlDsaHostKeys(WOLFSSH_CTX* ctx, const char* keyList)
|
||||
{
|
||||
byte* mldsaBuf;
|
||||
int loaded = 0;
|
||||
|
||||
mldsaBuf = (byte*)WMALLOC(MLDSA_MAX_BOTH_KEY_DER_SIZE, NULL, 0);
|
||||
if (mldsaBuf == NULL) {
|
||||
fprintf(stderr, "Couldn't allocate ML-DSA key load buffer.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifndef WOLFSSH_NO_MLDSA44
|
||||
if (WSTRSTR(keyList, "mldsa-44") != NULL) {
|
||||
int mldsaSz = load_key_mldsa44(mldsaBuf, MLDSA_MAX_BOTH_KEY_DER_SIZE);
|
||||
if (mldsaSz <= 0) {
|
||||
fprintf(stderr, "Couldn't load ML-DSA-44 key file.\n");
|
||||
WFREE(mldsaBuf, NULL, 0);
|
||||
return -1;
|
||||
}
|
||||
if (wolfSSH_CTX_UsePrivateKey_buffer(ctx, mldsaBuf, (word32)mldsaSz,
|
||||
WOLFSSH_FORMAT_ASN1) < 0) {
|
||||
fprintf(stderr, "Couldn't use ML-DSA-44 key buffer.\n");
|
||||
WFREE(mldsaBuf, NULL, 0);
|
||||
return -1;
|
||||
}
|
||||
loaded++;
|
||||
}
|
||||
#endif /* WOLFSSH_NO_MLDSA44 */
|
||||
|
||||
#ifndef WOLFSSH_NO_MLDSA65
|
||||
if (WSTRSTR(keyList, "mldsa-65") != NULL) {
|
||||
int mldsaSz = load_key_mldsa65(mldsaBuf, MLDSA_MAX_BOTH_KEY_DER_SIZE);
|
||||
if (mldsaSz <= 0) {
|
||||
fprintf(stderr, "Couldn't load ML-DSA-65 key file.\n");
|
||||
WFREE(mldsaBuf, NULL, 0);
|
||||
return -1;
|
||||
}
|
||||
if (wolfSSH_CTX_UsePrivateKey_buffer(ctx, mldsaBuf, (word32)mldsaSz,
|
||||
WOLFSSH_FORMAT_ASN1) < 0) {
|
||||
fprintf(stderr, "Couldn't use ML-DSA-65 key buffer.\n");
|
||||
WFREE(mldsaBuf, NULL, 0);
|
||||
return -1;
|
||||
}
|
||||
loaded++;
|
||||
}
|
||||
#endif /* WOLFSSH_NO_MLDSA65 */
|
||||
|
||||
#ifndef WOLFSSH_NO_MLDSA87
|
||||
if (WSTRSTR(keyList, "mldsa-87") != NULL) {
|
||||
int mldsaSz = load_key_mldsa87(mldsaBuf, MLDSA_MAX_BOTH_KEY_DER_SIZE);
|
||||
if (mldsaSz <= 0) {
|
||||
fprintf(stderr, "Couldn't load ML-DSA-87 key file.\n");
|
||||
WFREE(mldsaBuf, NULL, 0);
|
||||
return -1;
|
||||
}
|
||||
if (wolfSSH_CTX_UsePrivateKey_buffer(ctx, mldsaBuf, (word32)mldsaSz,
|
||||
WOLFSSH_FORMAT_ASN1) < 0) {
|
||||
fprintf(stderr, "Couldn't use ML-DSA-87 key buffer.\n");
|
||||
WFREE(mldsaBuf, NULL, 0);
|
||||
return -1;
|
||||
}
|
||||
loaded++;
|
||||
}
|
||||
#endif /* WOLFSSH_NO_MLDSA87 */
|
||||
|
||||
WFREE(mldsaBuf, NULL, 0);
|
||||
if (loaded == 0) {
|
||||
fprintf(stderr, "ML-DSA key list '%s' matched no supported level.\n",
|
||||
keyList);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* WOLFSSH_NO_MLDSA */
|
||||
|
||||
|
||||
typedef struct StrList {
|
||||
const char* str;
|
||||
struct StrList* next;
|
||||
|
|
@ -3137,7 +3254,8 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
|
|||
if (tpmHostKeyPath != NULL) {
|
||||
if (EchoserverInitTpmHostKey(ctx, tpmHostKeyPath,
|
||||
ECHOSERVER_TPM_KEY_AUTH_DEFAULT) != 0) {
|
||||
ES_ERROR("Couldn't load TPM host key from %s.\n", tpmHostKeyPath);
|
||||
ES_ERROR("Couldn't load TPM host key from %s.\n",
|
||||
tpmHostKeyPath);
|
||||
}
|
||||
loadDefaultHostKeys = 0;
|
||||
}
|
||||
|
|
@ -3180,6 +3298,19 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
|
|||
#endif /* WOLFSSH_NO_ED25519 */
|
||||
}
|
||||
|
||||
/* Load only the ML-DSA levels requested in keyList; loading all levels
|
||||
* unconditionally would force mldsa negotiation on non-mldsa tests. */
|
||||
#ifndef WOLFSSH_NO_MLDSA
|
||||
if (keyList != NULL && WSTRSTR(keyList, "mldsa") != NULL) {
|
||||
if (LoadMlDsaHostKeys(ctx, keyList) != 0) {
|
||||
#ifdef WOLFSSH_SMALL_STACK
|
||||
WFREE(keyLoadBuf, NULL, 0);
|
||||
#endif
|
||||
ES_ERROR("Error loading ML-DSA host keys.\n");
|
||||
}
|
||||
}
|
||||
#endif /* WOLFSSH_NO_MLDSA */
|
||||
|
||||
#ifndef NO_FILESYSTEM
|
||||
if (userPubKey) {
|
||||
byte* userBuf = NULL;
|
||||
|
|
|
|||
|
|
@ -24,5 +24,7 @@ EXTRA_DIST+= \
|
|||
keys/server-key.pem keys/fred-key.der keys/fred-key.pem \
|
||||
keys/id_ecdsa keys/id_ecdsa.pub keys/id_rsa keys/id_rsa.pub \
|
||||
keys/renewcerts.sh keys/renewcerts.cnf \
|
||||
keys/server-key-ed25519.der keys/server-key-ed25519.pem
|
||||
keys/server-key-ed25519.der keys/server-key-ed25519.pem \
|
||||
keys/server-key-mldsa44.der keys/server-key-mldsa65.der \
|
||||
keys/server-key-mldsa87.der
|
||||
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
1396
src/internal.c
1396
src/internal.c
File diff suppressed because it is too large
Load Diff
76
src/keygen.c
76
src/keygen.c
|
|
@ -253,6 +253,82 @@ int wolfSSH_MakeEd25519Key(byte* out, word32 outSz, word32 size)
|
|||
#endif
|
||||
}
|
||||
|
||||
int wolfSSH_MakeMlDsaKey(byte* out, word32 outSz, word32 level)
|
||||
{
|
||||
#if !defined(WOLFSSH_NO_MLDSA)
|
||||
int ret = WS_SUCCESS;
|
||||
WC_RNG rng = {0};
|
||||
byte wc_level;
|
||||
|
||||
WLOG(WS_LOG_DEBUG, "Entering wolfSSH_MakeMlDsaKey()");
|
||||
|
||||
if (level == WOLFSSH_MLDSAKEY_44) wc_level = WC_ML_DSA_44;
|
||||
else if (level == WOLFSSH_MLDSAKEY_65) wc_level = WC_ML_DSA_65;
|
||||
else if (level == WOLFSSH_MLDSAKEY_87) wc_level = WC_ML_DSA_87;
|
||||
else {
|
||||
WLOG(WS_LOG_DEBUG, "Invalid ML-DSA key level requested");
|
||||
return WS_BAD_ARGUMENT;
|
||||
}
|
||||
|
||||
if (wc_InitRng(&rng) != 0) {
|
||||
WLOG(WS_LOG_DEBUG, "Couldn't create RNG");
|
||||
ret = WS_CRYPTO_FAILED;
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS) {
|
||||
MlDsaKey key;
|
||||
int keyInit = 0;
|
||||
|
||||
if (wc_MlDsaKey_Init(&key, NULL, INVALID_DEVID) != 0)
|
||||
ret = WS_CRYPTO_FAILED;
|
||||
else {
|
||||
keyInit = 1;
|
||||
if (wc_MlDsaKey_SetParams(&key, wc_level) != 0)
|
||||
ret = WS_CRYPTO_FAILED;
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS) {
|
||||
ret = wc_MlDsaKey_MakeKey(&key, &rng);
|
||||
if (ret != 0) {
|
||||
WLOG(WS_LOG_DEBUG, "ML-DSA key generation failed");
|
||||
ret = WS_CRYPTO_FAILED;
|
||||
}
|
||||
else
|
||||
ret = WS_SUCCESS;
|
||||
}
|
||||
|
||||
if (ret == WS_SUCCESS) {
|
||||
int keySz;
|
||||
|
||||
keySz = wc_MlDsaKey_KeyToDer(&key, out, outSz);
|
||||
if (keySz < 0) {
|
||||
WLOG(WS_LOG_DEBUG, "ML-DSA key to DER failed");
|
||||
ret = WS_CRYPTO_FAILED;
|
||||
}
|
||||
else
|
||||
ret = keySz;
|
||||
}
|
||||
|
||||
if (keyInit) {
|
||||
wc_MlDsaKey_Free(&key);
|
||||
}
|
||||
|
||||
if (wc_FreeRng(&rng) != 0) {
|
||||
WLOG(WS_LOG_DEBUG, "Couldn't free RNG");
|
||||
if (ret >= 0)
|
||||
ret = WS_CRYPTO_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
WLOG(WS_LOG_DEBUG, "Leaving wolfSSH_MakeMlDsaKey(), ret = %d", ret);
|
||||
return ret;
|
||||
#else
|
||||
WOLFSSH_UNUSED(out);
|
||||
WOLFSSH_UNUSED(outSz);
|
||||
WOLFSSH_UNUSED(level);
|
||||
return WS_NOT_COMPILED;
|
||||
#endif
|
||||
}
|
||||
|
||||
#else /* WOLFSSL_KEY_GEN */
|
||||
#error "wolfSSH keygen requires that keygen is enabled in wolfSSL, use --enable-keygen or #define WOLFSSL_KEY_GEN."
|
||||
|
|
|
|||
100
src/ssh.c
100
src/ssh.c
|
|
@ -1712,6 +1712,9 @@ char* wolfSSH_GetUsername(WOLFSSH* ssh)
|
|||
#include <wolfssl/wolfcrypt/rsa.h>
|
||||
#include <wolfssl/wolfcrypt/asn_public.h>
|
||||
#include <wolfssl/wolfcrypt/coding.h>
|
||||
#ifndef WOLFSSH_NO_MLDSA
|
||||
#include <wolfssl/wolfcrypt/dilithium.h>
|
||||
#endif
|
||||
|
||||
union wolfSSH_key {
|
||||
#ifndef WOLFSSH_NO_RSA
|
||||
|
|
@ -1833,7 +1836,72 @@ static int DoAsn1Key(const byte* in, word32 inSz, byte** out,
|
|||
}
|
||||
|
||||
if (ret > 0 && !isPrivate) {
|
||||
#ifndef WOLFSSH_NO_MLDSA
|
||||
if (
|
||||
#ifndef WOLFSSH_NO_MLDSA44
|
||||
ret == ID_MLDSA44 ||
|
||||
#endif
|
||||
#ifndef WOLFSSH_NO_MLDSA65
|
||||
ret == ID_MLDSA65 ||
|
||||
#endif
|
||||
#ifndef WOLFSSH_NO_MLDSA87
|
||||
ret == ID_MLDSA87 ||
|
||||
#endif
|
||||
0) {
|
||||
byte* rawPub = NULL;
|
||||
word32 rawPubSz =
|
||||
#ifndef WOLFSSH_NO_MLDSA87
|
||||
WC_MLDSA_87_PUB_KEY_SIZE;
|
||||
#elif !defined(WOLFSSH_NO_MLDSA65)
|
||||
WC_MLDSA_65_PUB_KEY_SIZE;
|
||||
#else
|
||||
WC_MLDSA_44_PUB_KEY_SIZE;
|
||||
#endif
|
||||
const char* name = IdToName(ret);
|
||||
word32 nameLen = (word32)WSTRLEN(name);
|
||||
word32 localIdx = 0;
|
||||
|
||||
*outType = (const byte*)name;
|
||||
*outTypeSz = nameLen;
|
||||
|
||||
rawPub = (byte*)WMALLOC(rawPubSz, heap, DYNTYPE_PUBKEY);
|
||||
if (rawPub == NULL) {
|
||||
ret = WS_MEMORY_E;
|
||||
}
|
||||
else {
|
||||
int wcRet = wc_MlDsaKey_ExportPubRaw(&key->ks.mldsa.key,
|
||||
rawPub, &rawPubSz);
|
||||
if (wcRet != 0) {
|
||||
ret = WS_CRYPTO_FAILED;
|
||||
}
|
||||
else {
|
||||
*outSz = LENGTH_SZ + nameLen + LENGTH_SZ + rawPubSz;
|
||||
newKey = (byte*)WMALLOC(*outSz, heap, DYNTYPE_PUBKEY);
|
||||
if (newKey == NULL) {
|
||||
ret = WS_MEMORY_E;
|
||||
}
|
||||
else {
|
||||
c32toa(nameLen, &newKey[localIdx]);
|
||||
localIdx += LENGTH_SZ;
|
||||
WMEMCPY(&newKey[localIdx], name, nameLen);
|
||||
localIdx += nameLen;
|
||||
c32toa(rawPubSz, &newKey[localIdx]);
|
||||
localIdx += LENGTH_SZ;
|
||||
WMEMCPY(&newKey[localIdx], rawPub, rawPubSz);
|
||||
*out = newKey;
|
||||
ret = WS_SUCCESS;
|
||||
}
|
||||
}
|
||||
WFREE(rawPub, heap, DYNTYPE_PUBKEY);
|
||||
}
|
||||
}
|
||||
/* The else below intentionally straddles a preprocessor boundary:
|
||||
* when WOLFSSH_NO_MLDSA is defined the entire if/else is removed and
|
||||
* the RSA block becomes a standalone scope, which is harmless. */
|
||||
else
|
||||
#endif /* WOLFSSH_NO_MLDSA */
|
||||
#ifndef WOLFSSH_NO_RSA
|
||||
{
|
||||
long e;
|
||||
byte n[RSA_MAX_SIZE]; /* TODO: Handle small stack */
|
||||
word32 nSz = (word32)sizeof(n), eSz = (word32)sizeof(e);
|
||||
|
|
@ -1882,9 +1950,12 @@ static int DoAsn1Key(const byte* in, word32 inSz, byte** out,
|
|||
|
||||
*out = newKey;
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
WLOG(WS_LOG_DEBUG, "DoAsn1Key failed; WOLFSSH_NO_RSA disabled RSA");
|
||||
ret = WS_UNIMPLEMENTED_E;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (ret > 0 && isPrivate) {
|
||||
|
|
@ -1892,23 +1963,22 @@ static int DoAsn1Key(const byte* in, word32 inSz, byte** out,
|
|||
newKey = (byte*)WMALLOC(inSz, heap, DYNTYPE_PRIVKEY);
|
||||
if (newKey == NULL) {
|
||||
ret = WS_MEMORY_E;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
else if (*outSz < inSz) {
|
||||
WLOG(WS_LOG_DEBUG, "DER private key output size too small");
|
||||
ret = WS_BUFFER_E;
|
||||
}
|
||||
else {
|
||||
if (*outSz < inSz) {
|
||||
WLOG(WS_LOG_DEBUG, "DER private key output size too small");
|
||||
ret = WS_BUFFER_E;
|
||||
return ret;
|
||||
}
|
||||
newKey = *out;
|
||||
}
|
||||
|
||||
*out = newKey;
|
||||
*outSz = inSz;
|
||||
WMEMCPY(newKey, in, inSz);
|
||||
*outType = (const byte*)IdToName(ret);
|
||||
*outTypeSz = (word32)WSTRLEN((const char*)*outType);
|
||||
if (ret > 0) {
|
||||
*out = newKey;
|
||||
*outSz = inSz;
|
||||
WMEMCPY(newKey, in, inSz);
|
||||
*outType = (const byte*)IdToName(ret);
|
||||
*outTypeSz = (word32)WSTRLEN((const char*)*outType);
|
||||
}
|
||||
}
|
||||
|
||||
wolfSSH_KEY_clean(key);
|
||||
|
|
@ -2169,7 +2239,11 @@ int wolfSSH_ReadKey_file(const char* name,
|
|||
|| WSTRNSTR((const char*)in,
|
||||
"ecdsa-sha2-nistp", inSz) == (const char*)in
|
||||
|| WSTRNSTR((const char*)in,
|
||||
"ssh-ed25519", inSz) == (const char*)in) {
|
||||
"ssh-ed25519", inSz) == (const char*)in
|
||||
|| WSTRNSTR((const char*)in,
|
||||
"ssh-mldsa-", inSz) == (const char*)in
|
||||
|| WSTRNSTR((const char*)in,
|
||||
"x509v3-ssh-mldsa-", inSz) == (const char*)in) {
|
||||
*isPrivate = 0;
|
||||
format = WOLFSSH_FORMAT_SSH;
|
||||
in[inSz] = 0;
|
||||
|
|
|
|||
84
tests/kex.c
84
tests/kex.c
|
|
@ -380,6 +380,81 @@ static int wolfSSH_KexTest_Ed25519HostKey(void)
|
|||
}
|
||||
#endif /* WOLFSSH_NO_ED25519 */
|
||||
|
||||
|
||||
#ifndef WOLFSSH_NO_MLDSA
|
||||
static int wolfSSH_KexTest_MlDsaHostKey(const char* keyName)
|
||||
{
|
||||
tcp_ready ready;
|
||||
THREAD_TYPE serverThread;
|
||||
func_args serverArgs;
|
||||
func_args clientArgs;
|
||||
char sA[NUMARGS][ARGLEN];
|
||||
char *serverArgv[NUMARGS] =
|
||||
{ sA[0], sA[1], sA[2], sA[3], sA[4], sA[5], sA[6], sA[7], sA[8],
|
||||
sA[9], sA[10], sA[11] };
|
||||
char cA[NUMARGS][ARGLEN];
|
||||
char *clientArgv[NUMARGS] =
|
||||
{ cA[0], cA[1], cA[2], cA[3], cA[4], cA[5], cA[6], cA[7], cA[8],
|
||||
cA[9], cA[10], cA[11] };
|
||||
int serverArgc = 0;
|
||||
int clientArgc = 0;
|
||||
|
||||
InitTcpReady(&ready);
|
||||
|
||||
ADD_ARG(serverArgv, serverArgc, "echoserver");
|
||||
ADD_ARG(serverArgv, serverArgc, "-1");
|
||||
ADD_ARG(serverArgv, serverArgc, "-f");
|
||||
#if !defined(USE_WINDOWS_API) && !defined(WOLFSSH_ZEPHYR)
|
||||
ADD_ARG(serverArgv, serverArgc, "-p");
|
||||
ADD_ARG(serverArgv, serverArgc, "-0");
|
||||
#endif
|
||||
ADD_ARG(serverArgv, serverArgc, "-k");
|
||||
ADD_ARG(serverArgv, serverArgc, keyName);
|
||||
|
||||
serverArgs.argc = serverArgc;
|
||||
serverArgs.argv = serverArgv;
|
||||
serverArgs.return_code = EXIT_SUCCESS;
|
||||
serverArgs.signal = &ready;
|
||||
serverArgs.user_auth = NULL;
|
||||
ThreadStart(echoserver_test, &serverArgs, &serverThread);
|
||||
WaitTcpReady(&ready);
|
||||
|
||||
ADD_ARG(clientArgv, clientArgc, "client");
|
||||
ADD_ARG(clientArgv, clientArgc, "-u");
|
||||
ADD_ARG(clientArgv, clientArgc, "jill");
|
||||
#if !defined(USE_WINDOWS_API) && !defined(WOLFSSH_ZEPHYR)
|
||||
ADD_ARG(clientArgv, clientArgc, "-p");
|
||||
ADD_ARG_INT(clientArgv, clientArgc, ready.port);
|
||||
#endif
|
||||
|
||||
clientArgs.argc = clientArgc;
|
||||
clientArgs.argv = clientArgv;
|
||||
clientArgs.return_code = EXIT_SUCCESS;
|
||||
clientArgs.signal = &ready;
|
||||
clientArgs.user_auth = tsClientUserAuth;
|
||||
|
||||
client_test(&clientArgs);
|
||||
|
||||
#ifdef WOLFSSH_ZEPHYR
|
||||
k_sleep(Z_TIMEOUT_TICKS(100));
|
||||
#endif
|
||||
ThreadJoin(serverThread);
|
||||
|
||||
if (clientArgs.return_code == WS_SOCKET_ERROR_E) {
|
||||
clientArgs.return_code = WS_SUCCESS;
|
||||
}
|
||||
if (serverArgs.return_code == WS_SOCKET_ERROR_E) {
|
||||
serverArgs.return_code = WS_SUCCESS;
|
||||
}
|
||||
AssertIntEQ(WS_SUCCESS, clientArgs.return_code);
|
||||
AssertIntEQ(WS_SUCCESS, serverArgs.return_code);
|
||||
|
||||
FreeTcpReady(&ready);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
#endif /* WOLFSSH_NO_MLDSA */
|
||||
|
||||
#endif /* KEXTEST_AVAILABLE */
|
||||
|
||||
int wolfSSH_KexTest(int argc, char** argv)
|
||||
|
|
@ -431,6 +506,15 @@ int wolfSSH_KexTest(int argc, char** argv)
|
|||
#ifndef WOLFSSH_NO_ED25519
|
||||
AssertIntEQ(wolfSSH_KexTest_Ed25519HostKey(), EXIT_SUCCESS);
|
||||
#endif
|
||||
#ifndef WOLFSSH_NO_MLDSA44
|
||||
AssertIntEQ(wolfSSH_KexTest_MlDsaHostKey("ssh-mldsa-44"), EXIT_SUCCESS);
|
||||
#endif
|
||||
#ifndef WOLFSSH_NO_MLDSA65
|
||||
AssertIntEQ(wolfSSH_KexTest_MlDsaHostKey("ssh-mldsa-65"), EXIT_SUCCESS);
|
||||
#endif
|
||||
#ifndef WOLFSSH_NO_MLDSA87
|
||||
AssertIntEQ(wolfSSH_KexTest_MlDsaHostKey("ssh-mldsa-87"), EXIT_SUCCESS);
|
||||
#endif
|
||||
|
||||
AssertIntEQ(wolfSSH_Cleanup(), WS_SUCCESS);
|
||||
|
||||
|
|
|
|||
1582
tests/unit.c
1582
tests/unit.c
File diff suppressed because it is too large
Load Diff
|
|
@ -137,8 +137,9 @@ enum WS_ErrorCodes {
|
|||
WS_AUTH_PENDING = -1096, /* User authentication still pending */
|
||||
WS_KDF_E = -1097, /* KDF error*/
|
||||
WS_DISCONNECT = -1098, /* peer sent disconnect */
|
||||
WS_MLDSA_E = -1099, /* MLDSA failure */
|
||||
|
||||
WS_LAST_E = WS_DISCONNECT /* Update this to indicate last error */
|
||||
WS_LAST_E = WS_MLDSA_E /* Last error indicator */
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -43,6 +43,9 @@
|
|||
#ifndef WOLFSSL_WOLFSSH
|
||||
#error "wolfssh requires wolfSSL built with WOLFSSL_WOLFSSH"
|
||||
#endif
|
||||
#ifdef HAVE_DILITHIUM
|
||||
#include <wolfssl/wolfcrypt/dilithium.h>
|
||||
#endif
|
||||
#ifdef WOLFSSH_SCP
|
||||
#include <wolfssh/wolfscp.h>
|
||||
#endif
|
||||
|
|
@ -102,6 +105,17 @@ extern "C" {
|
|||
#define WOLFSSH_NO_DH
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_DILITHIUM
|
||||
#undef WOLFSSH_NO_MLDSA
|
||||
#define WOLFSSH_NO_MLDSA
|
||||
#undef WOLFSSH_NO_MLDSA44
|
||||
#undef WOLFSSH_NO_MLDSA65
|
||||
#undef WOLFSSH_NO_MLDSA87
|
||||
#define WOLFSSH_NO_MLDSA44
|
||||
#define WOLFSSH_NO_MLDSA65
|
||||
#define WOLFSSH_NO_MLDSA87
|
||||
#endif
|
||||
|
||||
#ifdef NO_SHA
|
||||
#undef WOLFSSH_NO_SHA1
|
||||
#define WOLFSSH_NO_SHA1
|
||||
|
|
@ -138,7 +152,6 @@ extern "C" {
|
|||
#error "You need at least one MAC algorithm."
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(WOLFSSH_NO_DH) || defined(WOLFSSH_NO_SHA1)
|
||||
#undef WOLFSSH_NO_DH_GROUP1_SHA1
|
||||
#define WOLFSSH_NO_DH_GROUP1_SHA1
|
||||
|
|
@ -159,6 +172,16 @@ extern "C" {
|
|||
#undef WOLFSSH_NO_DH_GEX_SHA256
|
||||
#define WOLFSSH_NO_DH_GEX_SHA256
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSH_NO_MLDSA
|
||||
#undef WOLFSSH_NO_MLDSA44
|
||||
#undef WOLFSSH_NO_MLDSA65
|
||||
#undef WOLFSSH_NO_MLDSA87
|
||||
#define WOLFSSH_NO_MLDSA44
|
||||
#define WOLFSSH_NO_MLDSA65
|
||||
#define WOLFSSH_NO_MLDSA87
|
||||
#endif
|
||||
|
||||
#if defined(WOLFSSH_NO_ECDH) \
|
||||
|| defined(NO_SHA256) || defined(NO_ECC256)
|
||||
#undef WOLFSSH_NO_ECDH_SHA2_NISTP256
|
||||
|
|
@ -262,7 +285,10 @@ extern "C" {
|
|||
defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256) && \
|
||||
defined(WOLFSSH_NO_ECDSA_SHA2_NISTP384) && \
|
||||
defined(WOLFSSH_NO_ECDSA_SHA2_NISTP521) && \
|
||||
defined(WOLFSSH_NO_ED25519)
|
||||
defined(WOLFSSH_NO_ED25519) && \
|
||||
defined(WOLFSSH_NO_MLDSA44) && \
|
||||
defined(WOLFSSH_NO_MLDSA65) && \
|
||||
defined(WOLFSSH_NO_MLDSA87)
|
||||
#error "You need at least one signing algorithm."
|
||||
#endif
|
||||
|
||||
|
|
@ -373,10 +399,22 @@ enum {
|
|||
ID_ECDSA_SHA2_NISTP384,
|
||||
ID_ECDSA_SHA2_NISTP521,
|
||||
ID_ED25519,
|
||||
/* ML-DSA enum values shift with configs.
|
||||
* Internal-only, never serialized. */
|
||||
#ifndef WOLFSSH_NO_MLDSA
|
||||
ID_MLDSA44,
|
||||
ID_MLDSA65,
|
||||
ID_MLDSA87,
|
||||
#endif
|
||||
ID_X509V3_SSH_RSA,
|
||||
ID_X509V3_ECDSA_SHA2_NISTP256,
|
||||
ID_X509V3_ECDSA_SHA2_NISTP384,
|
||||
ID_X509V3_ECDSA_SHA2_NISTP521,
|
||||
#ifndef WOLFSSH_NO_MLDSA
|
||||
ID_X509V3_MLDSA44,
|
||||
ID_X509V3_MLDSA65,
|
||||
ID_X509V3_MLDSA87,
|
||||
#endif
|
||||
|
||||
/* Service IDs */
|
||||
ID_SERVICE_USERAUTH,
|
||||
|
|
@ -1086,6 +1124,11 @@ typedef struct WS_KeySignature {
|
|||
ed25519_key key;
|
||||
} ed25519;
|
||||
#endif
|
||||
#ifndef WOLFSSH_NO_MLDSA
|
||||
struct {
|
||||
MlDsaKey key;
|
||||
} mldsa;
|
||||
#endif /* WOLFSSH_NO_MLDSA */
|
||||
} ks;
|
||||
} WS_KeySignature;
|
||||
|
||||
|
|
@ -1471,6 +1514,21 @@ enum WS_MessageIdLimits {
|
|||
WOLFSSH_API int wolfSSH_TestDoUserAuthRequestEd25519(WOLFSSH* ssh,
|
||||
WS_UserAuthData* authData);
|
||||
#endif /* !WOLFSSH_NO_ED25519 */
|
||||
#ifndef WOLFSSH_NO_MLDSA
|
||||
WOLFSSH_API int wolfSSH_TestDoUserAuthRequestMlDsa(WOLFSSH* ssh,
|
||||
WS_UserAuthData* authData, word32 pubKeyBlobSz);
|
||||
WOLFSSH_API int wolfSSH_TestPrepareUserAuthRequestMlDsa(WOLFSSH* ssh,
|
||||
word32* payloadSz, const WS_UserAuthData* authData,
|
||||
WS_KeySignature* keySig);
|
||||
#ifdef WOLFSSH_CERTS
|
||||
WOLFSSH_API int wolfSSH_TestPrepareUserAuthRequestMlDsaCert(WOLFSSH* ssh,
|
||||
word32* payloadSz, const WS_UserAuthData* authData,
|
||||
WS_KeySignature* keySig);
|
||||
#endif /* WOLFSSH_CERTS */
|
||||
WOLFSSH_API int wolfSSH_TestBuildUserAuthRequestMlDsa(WOLFSSH* ssh,
|
||||
byte* output, word32* idx, const WS_UserAuthData* authData,
|
||||
const byte* sigStart, word32 sigStartIdx, WS_KeySignature* keySig);
|
||||
#endif /* !WOLFSSH_NO_MLDSA */
|
||||
#if defined(WOLFSSH_SCP) && !defined(WOLFSSH_SCP_USER_CALLBACKS)
|
||||
WOLFSSH_API int wolfSSH_TestScpExtractFileName(const char* filePath,
|
||||
char* fileName, word32 fileNameSz);
|
||||
|
|
|
|||
|
|
@ -42,12 +42,16 @@ extern "C" {
|
|||
#define WOLFSSH_ECDSAKEY_PRIME384 384
|
||||
#define WOLFSSH_ECDSAKEY_PRIME521 521
|
||||
#define WOLFSSH_ED25519KEY 256
|
||||
#define WOLFSSH_MLDSAKEY_44 44
|
||||
#define WOLFSSH_MLDSAKEY_65 65
|
||||
#define WOLFSSH_MLDSAKEY_87 87
|
||||
|
||||
|
||||
WOLFSSH_API int wolfSSH_MakeRsaKey(byte* out, word32 outSz,
|
||||
word32 size, word32 e);
|
||||
WOLFSSH_API int wolfSSH_MakeEcdsaKey(byte* out, word32 outSz, word32 size);
|
||||
WOLFSSH_API int wolfSSH_MakeEd25519Key(byte* out, word32 outSz, word32 size);
|
||||
WOLFSSH_API int wolfSSH_MakeMlDsaKey(byte* out, word32 outSz, word32 level);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
Loading…
Reference in New Issue