internal: decode DER Ed25519 user auth keys

PrepareUserAuthRequestEd25519() tries wc_Ed25519PrivateKeyDecode() and
falls back to the OpenSSH container only when that decode fails, as the
RSA and ECDSA paths do. A private-only DER gets its public key derived
the way SendKexGetSigningKey() does, or is rejected when it cannot be.
pull/1260/merge
John Safranek 2026-09-15 15:09:54 -07:00 committed by philljj
parent a072fcc572
commit 6d1292832d
1 changed files with 40 additions and 3 deletions

View File

@ -21297,9 +21297,46 @@ static int PrepareUserAuthRequestEd25519(WOLFSSH* ssh, word32* payloadSz,
else
#endif
{
ret = GetOpenSshKey(keySig,
authData->sf.publicKey.privateKey,
authData->sf.publicKey.privateKeySz, &idx);
int derRet;
/* As in the RSA and ECDSA paths, try DER first and fall back to
* the OpenSSH container. Only a decode failure falls back; a
* derive failure keeps its own error. */
derRet = wc_Ed25519PrivateKeyDecode(
authData->sf.publicKey.privateKey, &idx,
&keySig->ks.ed25519.key,
authData->sf.publicKey.privateKeySz);
if (derRet != 0) {
idx = 0;
ret = GetOpenSshKey(keySig,
authData->sf.publicKey.privateKey,
authData->sf.publicKey.privateKeySz, &idx);
}
else {
ret = WS_SUCCESS;
if (!keySig->ks.ed25519.key.pubKeySet) {
#ifdef HAVE_ED25519_MAKE_KEY
/* Priv-only DER: derive the public key from the seed,
* the way SendKexGetSigningKey() does for a host key. */
byte q[ED25519_PUB_KEY_SIZE];
ret = wc_ed25519_make_public(&keySig->ks.ed25519.key,
q, (word32)sizeof(q));
if (ret == 0) {
/* trusted=1: q came from this key's own scalar. */
ret = wc_ed25519_import_public_ex(q,
ED25519_PUB_KEY_SIZE,
&keySig->ks.ed25519.key, 1);
}
#else
/* Nothing to derive it with; reject here rather than
* failing inside wc_ed25519_sign_msg(). */
ret = WS_KEY_FORMAT_E;
#endif /* HAVE_ED25519_MAKE_KEY */
}
}
}
}