From f85ec920e3d59e935743d2c939f6a78ea44c1bda Mon Sep 17 00:00:00 2001 From: John Safranek Date: Mon, 9 Mar 2026 10:56:37 -0700 Subject: [PATCH] Client rsa-sha2-512 1. Separate the key type and signature type when handling user authentication. ssh-rsa is a key type used with rsa-sha2-256 and rsa-sha2-512 signatures, along with ssh-rsa signatures. 2. Allow rsa-sha2-512 to be used. 3. Fix bug where setting the key algorithm on the client command line was setting the list to NULL. 4. Fix bug where adding rsa-sha2-512 to the list of canned algorithms was terminating the list, rather that adding it. Issue: ZD-21247 --- examples/client/client.c | 2 +- src/internal.c | 98 ++++++++++++++++++++-------------------- wolfssh/internal.h | 19 +++----- 3 files changed, 57 insertions(+), 62 deletions(-) diff --git a/examples/client/client.c b/examples/client/client.c index 1eaf951d9..6124c7a90 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -854,7 +854,7 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args) err_sys("Couldn't create wolfSSH client context."); if (keyList) { - if (wolfSSH_CTX_SetAlgoListKey(ctx, NULL) != WS_SUCCESS) { + if (wolfSSH_CTX_SetAlgoListKey(ctx, keyList) != WS_SUCCESS) { err_sys("Error setting key list.\n"); } } diff --git a/src/internal.c b/src/internal.c index e40878584..32bde228e 100644 --- a/src/internal.c +++ b/src/internal.c @@ -943,7 +943,7 @@ static const char cannedKeyAlgoNames[] = "rsa-sha2-256," #endif/* WOLFSSH_NO_RSA_SHA2_256 */ #ifndef WOLFSSH_NO_RSA_SHA2_512 - "rsa-sha2-512", + "rsa-sha2-512," #endif /* WOLFSSH_NO_RSA_SHA2_512 */ #ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP256 "ecdsa-sha2-nistp256," @@ -1403,19 +1403,19 @@ void SshResourceFree(WOLFSSH* ssh, void* heap) void wolfSSH_KEY_clean(WS_KeySignature* key) { if (key != NULL) { - if (key->keySigId == ID_SSH_RSA) { + if (key->keyId == ID_SSH_RSA) { #ifndef WOLFSSH_NO_RSA wc_FreeRsaKey(&key->ks.rsa.key); #endif } - else if (key->keySigId == ID_ED25519) { + else if (key->keyId == ID_ED25519) { #ifndef WOLFSSH_NO_ED25519 wc_ed25519_free(&key->ks.ed25519.key); #endif } - else if (key->keySigId == ID_ECDSA_SHA2_NISTP256 || - key->keySigId == ID_ECDSA_SHA2_NISTP384 || - key->keySigId == ID_ECDSA_SHA2_NISTP521) { + else if (key->keyId == ID_ECDSA_SHA2_NISTP256 || + key->keyId == ID_ECDSA_SHA2_NISTP384 || + key->keyId == ID_ECDSA_SHA2_NISTP521) { #ifndef WOLFSSH_NO_ECDSA wc_ecc_free(&key->ks.ecc.key); #endif @@ -1456,11 +1456,11 @@ int IdentifyAsn1Key(const byte* in, word32 inSz, int isPrivate, void* heap, } else { WMEMSET(key, 0, sizeof(*key)); - key->keySigId = ID_UNKNOWN; + key->keyId = ID_UNKNOWN; #ifndef WOLFSSH_NO_RSA /* Check RSA key */ - if (key->keySigId == ID_UNKNOWN) { + if (key->keyId == ID_UNKNOWN) { idx = 0; ret = wc_InitRsaKey(&key->ks.rsa.key, NULL); @@ -1476,14 +1476,14 @@ int IdentifyAsn1Key(const byte* in, word32 inSz, int isPrivate, void* heap, /* If decode was successful, this is an RSA key. */ if (ret == 0) { - key->keySigId = ID_SSH_RSA; + key->keyId = ID_SSH_RSA; } } } #endif /* WOLFSSH_NO_RSA */ #ifndef WOLFSSH_NO_ECDSA /* Check ECDSA key */ - if (key->keySigId == ID_UNKNOWN) { + if (key->keyId == ID_UNKNOWN) { idx = 0; ret = wc_ecc_init_ex(&key->ks.ecc.key, heap, INVALID_DEVID); @@ -1501,13 +1501,13 @@ int IdentifyAsn1Key(const byte* in, word32 inSz, int isPrivate, void* heap, if (ret == 0) { switch (wc_ecc_get_curve_id(key->ks.ecc.key.idx)) { case ECC_SECP256R1: - key->keySigId = ID_ECDSA_SHA2_NISTP256; + key->keyId = ID_ECDSA_SHA2_NISTP256; break; case ECC_SECP384R1: - key->keySigId = ID_ECDSA_SHA2_NISTP384; + key->keyId = ID_ECDSA_SHA2_NISTP384; break; case ECC_SECP521R1: - key->keySigId = ID_ECDSA_SHA2_NISTP521; + key->keyId = ID_ECDSA_SHA2_NISTP521; break; } } @@ -1515,7 +1515,7 @@ int IdentifyAsn1Key(const byte* in, word32 inSz, int isPrivate, void* heap, } #endif /* WOLFSSH_NO_ECDSA */ #if !defined(WOLFSSH_NO_ED25519) - if (key->keySigId == ID_UNKNOWN) { + if (key->keyId == ID_UNKNOWN) { idx = 0; ret = wc_ed25519_init_ex(&key->ks.ed25519.key, heap, INVALID_DEVID); @@ -1532,17 +1532,17 @@ int IdentifyAsn1Key(const byte* in, word32 inSz, int isPrivate, void* heap, /* If decode was successful, this is a Ed25519 key. */ if (ret == 0) - key->keySigId = ID_ED25519; + key->keyId = ID_ED25519; } #endif /* WOLFSSH_NO_ED25519 */ - if (key->keySigId == ID_UNKNOWN) { + if (key->keyId == ID_UNKNOWN) { ret = WS_UNIMPLEMENTED_E; } else { if (pkey != NULL) *pkey = key; - ret = key->keySigId; + ret = key->keyId; } /* if not returning key then free it */ @@ -1916,7 +1916,7 @@ static int GetOpenSshKey(WS_KeySignature *key, str, strSz, &subIdx); if (ret == WS_SUCCESS) { keyId = NameToId((const char*)subStr, subStrSz); - key->keySigId = keyId; + key->keyId = keyId; } if (ret == WS_SUCCESS) { switch (keyId) { @@ -2004,14 +2004,14 @@ int IdentifyOpenSshKey(const byte* in, word32 inSz, void* heap) else { WMEMSET(key, 0, sizeof(*key)); key->heap = heap; - key->keySigId = ID_NONE; + key->keyId = ID_NONE; ret = GetOpenSshKey(key, in, inSz, &idx); if (ret == WS_SUCCESS) { - ret = key->keySigId; + ret = key->keyId; } - else if (key->keySigId == ID_UNKNOWN) { + else if (key->keyId == ID_UNKNOWN) { ret = WS_UNIMPLEMENTED_E; } @@ -14080,7 +14080,7 @@ static int BuildUserAuthRequestRsa(WOLFSSH* ssh, begin = *idx; if (ret == WS_SUCCESS) { - hashId = HashForId(keySig->keySigId); + hashId = HashForId(keySig->sigId); if (hashId == WC_HASH_TYPE_NONE) ret = WS_INVALID_ALGO_ID; } @@ -14138,7 +14138,7 @@ static int BuildUserAuthRequestRsa(WOLFSSH* ssh, byte encDigest[MAX_ENCODED_SIG_SZ]; int encDigestSz; - switch (keySig->keySigId) { + switch (keySig->sigId) { #ifndef WOLFSSH_NO_SSH_RSA_SHA1 case ID_SSH_RSA: names = cannedKeyAlgoSshRsaNames; @@ -14309,7 +14309,7 @@ static int BuildUserAuthRequestRsaCert(WOLFSSH* ssh, if (ret == WS_SUCCESS) { begin = *idx; - hashId = HashForId(keySig->keySigId); + hashId = HashForId(keySig->sigId); if (hashId == WC_HASH_TYPE_NONE) ret = WS_INVALID_ALGO_ID; WLOG(WS_LOG_DEBUG, "HashForId = %d, ret = %d", hashId, ret); @@ -14531,7 +14531,7 @@ static int BuildUserAuthRequestEcc(WOLFSSH* ssh, begin = *idx; if (ret == WS_SUCCESS) { - hashId = HashForId(keySig->keySigId); + hashId = HashForId(keySig->sigId); WMEMSET(digest, 0, sizeof(digest)); digestSz = wc_HashGetDigestSize(hashId); checkDataSz = LENGTH_SZ + ssh->sessionIdSz + (begin - sigStartIdx); @@ -14597,7 +14597,7 @@ static int BuildUserAuthRequestEcc(WOLFSSH* ssh, rPad = (r_ptr[0] & 0x80) ? 1 : 0; sPad = (s_ptr[0] & 0x80) ? 1 : 0; - switch (keySig->keySigId) { + switch (keySig->sigId) { #ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP256 case ID_ECDSA_SHA2_NISTP256: names = cannedKeyAlgoEcc256Names; @@ -14769,7 +14769,7 @@ static int BuildUserAuthRequestEccCert(WOLFSSH* ssh, begin = *idx; if (ret == WS_SUCCESS) { - hashId = HashForId(keySig->keySigId); + hashId = HashForId(keySig->sigId); WMEMSET(digest, 0, sizeof(digest)); digestSz = wc_HashGetDigestSize(hashId); checkDataSz = LENGTH_SZ + ssh->sessionIdSz + (begin - sigStartIdx); @@ -14840,7 +14840,7 @@ static int BuildUserAuthRequestEccCert(WOLFSSH* ssh, rPad = (r[0] & 0x80) ? 1 : 0; sPad = (s[0] & 0x80) ? 1 : 0; - switch (keySig->keySigId) { + switch (keySig->sigId) { #ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP256 case ID_ECDSA_SHA2_NISTP256: names = cannedKeyAlgoEcc256Names; @@ -15103,13 +15103,17 @@ static int PrepareUserAuthRequestPublicKey(WOLFSSH* ssh, word32* payloadSz, } if (ret == WS_SUCCESS) { - byte keyId, matchId, algoId[4]; + byte matchId, algoId[4]; word32 algoIdSz = 0; - keyId = NameToId( + keySig->keyId = NameToId( (const char*)authData->sf.publicKey.publicKeyType, authData->sf.publicKey.publicKeyTypeSz); - if (keyId == ID_SSH_RSA) { + keySig->keyName = (const char*)authData->sf.publicKey.publicKeyType; + keySig->keyNameSz = authData->sf.publicKey.publicKeyTypeSz; + /* Typically a 1:1 match of key type to signature type. RSA uses + * a key type of ssh-rsa, but different signature types. */ + if (keySig->keyId == ID_SSH_RSA) { #ifndef WOLFSSH_NO_RSA_SHA2_512 algoId[algoIdSz++] = ID_RSA_SHA2_512; #endif @@ -15122,7 +15126,7 @@ static int PrepareUserAuthRequestPublicKey(WOLFSSH* ssh, word32* payloadSz, #endif } else { - algoId[algoIdSz++] = keyId; + algoId[algoIdSz++] = keySig->keyId; } /* Is that in the peerSigId list? */ @@ -15131,9 +15135,9 @@ static int PrepareUserAuthRequestPublicKey(WOLFSSH* ssh, word32* payloadSz, if (matchId == ID_UNKNOWN) { ret = WS_MATCH_KEY_ALGO_E; } - keySig->keySigId = matchId; - keySig->name = IdToName(matchId); - keySig->nameSz = (word32)WSTRLEN(keySig->name); + keySig->sigId = matchId; + keySig->sigName = IdToName(matchId); + keySig->sigNameSz = (word32)WSTRLEN(keySig->sigName); } if (ret == WS_SUCCESS) { @@ -15141,13 +15145,11 @@ static int PrepareUserAuthRequestPublicKey(WOLFSSH* ssh, word32* payloadSz, * the public key algorithm name, and the public key length. * For the X509 types, this accounts for ONLY one certificate.*/ *payloadSz += BOOLEAN_SZ + (LENGTH_SZ * 2) + - keySig->nameSz + authData->sf.publicKey.publicKeySz; + keySig->sigNameSz + authData->sf.publicKey.publicKeySz; - switch (keySig->keySigId) { + switch (keySig->keyId) { #ifndef WOLFSSH_NO_RSA case ID_SSH_RSA: - case ID_RSA_SHA2_256: - case ID_RSA_SHA2_512: ret = PrepareUserAuthRequestRsa(ssh, payloadSz, authData, keySig); break; @@ -15213,22 +15215,21 @@ static int BuildUserAuthRequestPublicKey(WOLFSSH* ssh, if (pk->hasSignature) { WLOG(WS_LOG_DEBUG, "User signature type: %s", - IdToName(keySig->keySigId)); + IdToName(keySig->sigId)); - switch (keySig->keySigId) { + switch (keySig->sigId) { #ifndef WOLFSSH_NO_RSA case ID_SSH_RSA: case ID_RSA_SHA2_256: case ID_RSA_SHA2_512: - c32toa(keySig->nameSz, output + begin); + c32toa(keySig->sigNameSz, output + begin); begin += LENGTH_SZ; - WMEMCPY(output + begin, keySig->name, keySig->nameSz); - begin += keySig->nameSz; + WMEMCPY(output + begin, keySig->sigName, keySig->sigNameSz); + begin += keySig->sigNameSz; c32toa(pk->publicKeySz, output + begin); begin += LENGTH_SZ; WMEMCPY(output + begin, pk->publicKey, pk->publicKeySz); begin += pk->publicKeySz; - keySig->keySigId = ID_RSA_SHA2_256; ret = BuildUserAuthRequestRsa(ssh, output, &begin, authData, sigStart, sigStartIdx, keySig); break; @@ -15241,7 +15242,7 @@ static int BuildUserAuthRequestPublicKey(WOLFSSH* ssh, pk->publicKeyType, pk->publicKeyTypeSz); begin += pk->publicKeyTypeSz; - ret = BuildRFC6187Info(ssh, keySig->keySigId, + ret = BuildRFC6187Info(ssh, keySig->keyId, pk->publicKey, pk->publicKeySz, NULL, 0, output, &ssh->outputBuffer.bufferSz, &begin); if (ret == WS_SUCCESS) { @@ -15279,7 +15280,7 @@ static int BuildUserAuthRequestPublicKey(WOLFSSH* ssh, begin += pk->publicKeyTypeSz; /* build RFC6178 public key to send */ - ret = BuildRFC6187Info(ssh, keySig->keySigId, + ret = BuildRFC6187Info(ssh, keySig->keyId, pk->publicKey, pk->publicKeySz, NULL, 0, output, &ssh->outputBuffer.bufferSz, &begin); if (ret == WS_SUCCESS) { @@ -15447,7 +15448,8 @@ int SendUserAuthRequest(WOLFSSH* ssh, byte authType, int addSig) WMEMSET(&authData, 0, sizeof(authData)); if (ret == WS_SUCCESS) { WMEMSET(keySig_ptr, 0, sizeof(WS_KeySignature)); - keySig_ptr->keySigId = ID_NONE; + keySig_ptr->keyId = ID_NONE; + keySig_ptr->sigId = ID_NONE; keySig_ptr->heap = ssh->ctx->heap; #ifdef WOLFSSH_KEYBOARD_INTERACTIVE diff --git a/wolfssh/internal.h b/wolfssh/internal.h index 02e9afd5a..f6b444c78 100644 --- a/wolfssh/internal.h +++ b/wolfssh/internal.h @@ -72,16 +72,6 @@ extern "C" { #endif -/* - * Not ready for rsa-sha2-512 yet. - */ - -#undef WOLFSSH_NO_RSA_SHA2_512 -#ifndef WOLFSSH_YES_RSA_SHA2_512 - #define WOLFSSH_NO_RSA_SHA2_512 -#endif - - /* * Check options set by wolfSSL and set wolfSSH options as appropriate. If * the derived options and any override options leave wolfSSH without @@ -1009,11 +999,14 @@ WOLFSSH_LOCAL int wolfSSH_FwdWorker(WOLFSSH*); typedef struct WS_KeySignature { - byte keySigId; + byte keyId; + byte sigId; word32 sigSz; - const char *name; + const char *keyName; + const char *sigName; void *heap; - word32 nameSz; + word32 keyNameSz; + word32 sigNameSz; union { #ifndef WOLFSSH_NO_RSA struct {