Merge pull request #319 from ejohnstown/agent

Agent Updates
pull/322/head
JacobBarthelmeh 2021-02-03 21:27:18 +07:00 committed by GitHub
commit 8a00381e0c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 269 additions and 150 deletions

View File

@ -172,6 +172,9 @@ static void ShowUsage(void)
printf(" -R raw untranslated output\n");
#endif
#endif
#ifdef WOLFSSH_AGENT
printf(" -a Attempt to use SSH-AGENT\n");
#endif
}
@ -815,6 +818,7 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args)
byte rawMode = 0;
#endif
#ifdef WOLFSSH_AGENT
byte useAgent = 0;
WS_AgentCbActionCtx agentCbCtx;
#endif
@ -822,7 +826,7 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args)
char** argv = ((func_args*)args)->argv;
((func_args*)args)->return_code = 0;
while ((ch = mygetopt(argc, argv, "?c:eh:i:j:p:tu:xzNP:R")) != -1) {
while ((ch = mygetopt(argc, argv, "?ac:eh:i:j:p:tu:xzNP:R")) != -1) {
switch (ch) {
case 'h':
host = myoptarg;
@ -888,6 +892,13 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args)
keepOpen = 1;
break;
#endif
#ifdef WOLFSSH_AGENT
case 'a':
useAgent = 1;
break;
#endif
case '?':
ShowUsage();
exit(EXIT_SUCCESS);
@ -995,9 +1006,11 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args)
wolfSSH_SetUserAuth(ctx, ((func_args*)args)->user_auth);
#ifdef WOLFSSH_AGENT
wolfSSH_CTX_set_agent_cb(ctx,
wolfSSH_AGENT_DefaultActions, wolfSSH_AGENT_IO_Cb);
wolfSSH_CTX_AGENT_enable(ctx, 1);
if (useAgent) {
wolfSSH_CTX_set_agent_cb(ctx,
wolfSSH_AGENT_DefaultActions, wolfSSH_AGENT_IO_Cb);
wolfSSH_CTX_AGENT_enable(ctx, 1);
}
#endif
ssh = wolfSSH_new(ctx);
@ -1013,9 +1026,11 @@ THREAD_RETURN WOLFSSH_THREAD client_test(void* args)
wolfSSH_SetUserAuthCtx(ssh, (void*)password);
#ifdef WOLFSSH_AGENT
memset(&agentCbCtx, 0, sizeof(agentCbCtx));
agentCbCtx.state = AGENT_STATE_INIT;
wolfSSH_set_agent_cb_ctx(ssh, &agentCbCtx);
if (useAgent) {
memset(&agentCbCtx, 0, sizeof(agentCbCtx));
agentCbCtx.state = AGENT_STATE_INIT;
wolfSSH_set_agent_cb_ctx(ssh, &agentCbCtx);
}
#endif
wolfSSH_CTX_SetPublicKeyCheck(ctx, wsPublicKeyCheck);

View File

@ -173,6 +173,33 @@ static int SendSuccess(WOLFSSH_AGENT_CTX* agent)
}
#if 0
static int SendRequestIdentities(WOLFSSH_AGENT_CTX* agent)
{
int ret = WS_SUCCESS;
WLOG_ENTER();
if (agent == NULL)
ret = WS_BAD_ARGUMENT;
if (ret == WS_SUCCESS)
ret = PrepareMessage(agent, MSG_ID_SZ);
if (ret == WS_SUCCESS) {
agent->msg[agent->msgIdx++] = MSGID_AGENT_REQUEST_IDENTITIES;
ret = BundleMessage(agent, MSG_ID_SZ);
}
if (ret == WS_SUCCESS) {
DUMP(agent->msg, agent->msgSz);
}
WLOG_LEAVE(ret);
return ret;
}
#endif
static int SendIdentitiesAnswer(WOLFSSH_AGENT_CTX* agent)
{
WOLFSSH_AGENT_ID* id;
@ -614,163 +641,221 @@ static int PostRequestIds(WOLFSSH_AGENT_CTX* agent)
}
static WOLFSSH_AGENT_ID* FindKeyId(WOLFSSH_AGENT_ID* id,
const byte* keyBlob, word32 keyBlobSz)
{
int ret;
wc_Sha256 sha;
byte digest[WC_SHA256_DIGEST_SIZE];
ret = wc_InitSha256(&sha);
if (ret == 0)
ret = wc_Sha256Update(&sha, keyBlob, keyBlobSz);
if (ret == 0) {
ret = wc_Sha256Final(&sha, digest);
ret = (ret == 0) ? WS_SUCCESS : WS_CRYPTO_FAILED;
}
if (ret == WS_SUCCESS) {
while (id != NULL &&
WMEMCMP(digest, id, WC_SHA256_DIGEST_SIZE) != 0 &&
WMEMCMP(keyBlob, id->keyBlob, keyBlobSz)) {
id = id->next;
}
}
return id;
}
static int SignHashRsa(WOLFSSH_AGENT_KEY_RSA* rawKey, enum wc_HashType hashType,
const byte* digest, word32 digestSz, byte* sig, word32* sigSz,
WC_RNG* rng, void* heap)
{
RsaKey key;
byte encSig[MAX_ENCODED_SIG_SZ];
int encSigSz;
int ret = 0;
wc_InitRsaKey(&key, heap);
mp_read_unsigned_bin(&key.n, rawKey->n, rawKey->nSz);
mp_read_unsigned_bin(&key.e, rawKey->e, rawKey->eSz);
mp_read_unsigned_bin(&key.d, rawKey->d, rawKey->dSz);
mp_read_unsigned_bin(&key.p, rawKey->p, rawKey->pSz);
mp_read_unsigned_bin(&key.q, rawKey->q, rawKey->qSz);
mp_read_unsigned_bin(&key.u, rawKey->iqmp, rawKey->iqmpSz);
encSigSz = wc_EncodeSignature(encSig, digest, digestSz,
wc_HashGetOID(hashType));
if (encSigSz <= 0) {
WLOG(WS_LOG_DEBUG, "Bad Encode Sig");
ret = WS_CRYPTO_FAILED;
}
else {
WLOG(WS_LOG_INFO, "Signing hash with RSA.");
*sigSz = wc_RsaSSL_Sign(encSig, encSigSz, sig, *sigSz, &key, rng);
if (*sigSz <= 0) {
WLOG(WS_LOG_DEBUG, "Bad RSA Sign");
ret = WS_RSA_E;
}
}
wc_FreeRsaKey(&key);
if (ret != 0)
ret = WS_RSA_E;
return ret;
}
static int SignHashEcc(WOLFSSH_AGENT_KEY_ECDSA* rawKey, int curveId,
const byte* digest, word32 digestSz,
byte* sig, word32* sigSz, WC_RNG* rng)
{
ecc_key key;
int ret;
ret = wc_ecc_import_private_key_ex(rawKey->d, rawKey->dSz,
rawKey->q, rawKey->qSz, &key, curveId);
if (ret == 0) {
ret = wc_ecc_sign_hash(digest, digestSz, sig, sigSz, rng, &key);
}
if (ret != 0) {
WLOG(WS_LOG_DEBUG, "SendKexDhReply: Bad ECDSA Sign");
ret = WS_ECC_E;
}
else {
byte r[MAX_ECC_BYTES + ECC_MAX_PAD_SZ];
word32 rSz = sizeof(r);
byte rPad;
byte s[MAX_ECC_BYTES + ECC_MAX_PAD_SZ];
word32 sSz = sizeof(s);
byte sPad;
int idx;
ret = wc_ecc_sig_to_rs(sig, *sigSz, r, &rSz, s, &sSz);
if (ret == 0) {
idx = 0;
rPad = (r[0] & 0x80) ? 1 : 0;
sPad = (s[0] & 0x80) ? 1 : 0;
*sigSz = (LENGTH_SZ * 2) + rSz + rPad + sSz + sPad;
c32toa(rSz + rPad, sig + idx);
idx += LENGTH_SZ;
if (rPad)
sig[idx++] = 0;
WMEMCPY(sig + idx, r, rSz);
idx += rSz;
c32toa(sSz + sPad, sig + idx);
idx += LENGTH_SZ;
if (sPad)
sig[idx++] = 0;
WMEMCPY(sig + idx, s, sSz);
}
}
wc_ecc_free(&key);
if (ret != 0)
ret = WS_ECC_E;
return ret;
}
static int PostSignRequest(WOLFSSH_AGENT_CTX* agent,
byte* keyBlob, word32 keyBlobSz, byte* data, word32 dataSz,
word32 flags)
{
WOLFSSH_AGENT_ID* cur = NULL;
wc_Sha256 sha;
byte digest[WC_SHA256_DIGEST_SIZE];
WOLFSSH_AGENT_ID* id = NULL;
int ret = WS_SUCCESS;
byte sig[256];
byte digest[WC_MAX_DIGEST_SIZE];
word32 sigSz = sizeof(sig);
word32 digestSz = sizeof(digest);
enum wc_HashType hashType;
int curveId = 0, signRsa = 0, signEcc = 0;
WLOG_ENTER();
(void)flags;
(void)curveId;
if (agent == NULL || keyBlob == NULL || keyBlobSz == 0)
ret = WS_BAD_ARGUMENT;
if (ret == WS_SUCCESS) {
ret = wc_InitSha256(&sha);
if (ret == 0)
ret = wc_Sha256Update(&sha, keyBlob, keyBlobSz);
if (ret == 0) {
ret = wc_Sha256Final(&sha, digest);
ret = (ret == 0) ? WS_SUCCESS : WS_CRYPTO_FAILED;
}
if (ret == WS_SUCCESS) {
cur = agent->idList;
while (cur != NULL &&
WMEMCMP(digest, cur->id, WC_SHA256_DIGEST_SIZE) != 0) {
cur = cur->next;
}
if (cur == NULL) {
WLOG(WS_LOG_AGENT, "Sign: Key not found.");
ret = WS_AGENT_NO_KEY_E;
}
if ((id = FindKeyId(agent->idList, keyBlob, keyBlobSz)) == NULL) {
WLOG(WS_LOG_AGENT, "Sign: Key not found.");
ret = WS_AGENT_NO_KEY_E;
}
}
if (ret == WS_SUCCESS) {
if ((cur->keyType == ID_SSH_RSA && flags & AGENT_SIGN_RSA_SHA2_256) ||
cur->keyType == ID_ECDSA_SHA2_NISTP256) {
ret = wc_InitSha256(&sha);
if (ret == 0)
ret = wc_Sha256Update(&sha, data, dataSz);
if (ret == 0) {
ret = wc_Sha256Final(&sha, digest);
ret = (ret == 0) ? WS_SUCCESS : WS_CRYPTO_FAILED;
}
}
else
ret = WS_INVALID_ALGO_ID;
}
if (ret == WS_SUCCESS) {
byte sig[256];
int sigSz = sizeof(sig);
if (cur->keyType == ID_SSH_RSA) {
#ifndef WOLFSSH_NO_RSA
WOLFSSH_AGENT_KEY_RSA* key;
RsaKey rsa;
byte encSig[MAX_ENCODED_SIG_SZ];
int encSigSz;
enum wc_HashType hashType = WC_HASH_TYPE_NONE;
key = &cur->key.rsa;
if (flags & AGENT_SIGN_RSA_SHA2_256)
switch (id->keyType) {
#if !defined(WOLFSSH_NO_SSH_RSA_SHA2_256) || \
!defined(WOLFSSH_NO_SSH_RSA_SHA2_512)
case ID_SSH_RSA:
signRsa = 1;
#ifndef WOLFSSH_NO_SSH_RSA_SHA2_256
if (flags & AGENT_SIGN_RSA_SHA2_256)
hashType = WC_HASH_TYPE_SHA256;
else
#endif
#ifndef WOLFSSH_NO_SSH_RSA_SHA2_512
if (flags & AGENT_SIGN_RSA_SHA2_512)
hashType = WC_HASH_TYPE_SHA512;
else
#endif
ret = WS_INVALID_ALGO_ID;
break;
#endif
#ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP256
case ID_ECDSA_SHA2_NISTP256:
hashType = WC_HASH_TYPE_SHA256;
else if (flags & AGENT_SIGN_RSA_SHA2_512)
curveId = ECC_SECP256R1;
signEcc = 1;
break;
#endif
#ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP384
case ID_ECDSA_SHA2_NISTP384:
hashType = WC_HASH_TYPE_SHA384;
curveId = ECC_SECP384R1;
signEcc = 1;
break;
#endif
#ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP512
case ID_ECDSA_SHA2_NISTP521:
hashType = WC_HASH_TYPE_SHA512;
wc_InitRsaKey(&rsa, agent->heap);
mp_read_unsigned_bin(&rsa.n, key->n, key->nSz);
mp_read_unsigned_bin(&rsa.e, key->e, key->eSz);
mp_read_unsigned_bin(&rsa.d, key->d, key->dSz);
mp_read_unsigned_bin(&rsa.p, key->p, key->pSz);
mp_read_unsigned_bin(&rsa.q, key->q, key->qSz);
mp_read_unsigned_bin(&rsa.u, key->iqmp, key->iqmpSz);
encSigSz = wc_EncodeSignature(encSig, digest,
wc_HashGetDigestSize(hashType),
wc_HashGetOID(hashType));
if (encSigSz <= 0) {
WLOG(WS_LOG_DEBUG, "Bad Encode Sig");
ret = WS_CRYPTO_FAILED;
}
else {
WLOG(WS_LOG_INFO, "Signing hash with RSA.");
sigSz = wc_RsaSSL_Sign(encSig, encSigSz, sig, sizeof(sig),
&rsa, &agent->rng);
if (sigSz <= 0) {
WLOG(WS_LOG_DEBUG, "Bad RSA Sign");
ret = WS_RSA_E;
}
}
wc_FreeRsaKey(&rsa);
if (ret != 0)
ret = WS_RSA_E;
#endif
curveId = ECC_SECP521R1;
signEcc = 1;
break;
#endif
default:
ret = WS_INVALID_ALGO_ID;
}
else if (cur->keyType == ID_ECDSA_SHA2_NISTP256) {
#ifndef WOLFSSH_NO_ECDSA
WOLFSSH_AGENT_KEY_ECDSA* key;
ecc_key ecc;
enum wc_HashType hashType = WC_HASH_TYPE_SHA256;
}
key = &cur->key.ecdsa;
ret = wc_ecc_import_private_key_ex(key->d, key->dSz,
key->q, key->qSz,
&ecc, ECC_SECP256R1);
if (ret == WS_SUCCESS) {
ret = wc_Hash(hashType, data, dataSz, digest, digestSz);
if (ret != 0)
ret = WS_CRYPTO_FAILED;
}
if (ret == 0) {
ret = wc_ecc_sign_hash(digest, wc_HashGetDigestSize(hashType),
sig, (word32*)&sigSz, &agent->rng, &ecc);
}
if (ret != 0) {
WLOG(WS_LOG_DEBUG, "SendKexDhReply: Bad ECDSA Sign");
ret = WS_ECC_E;
}
else {
byte r[MAX_ECC_BYTES + ECC_MAX_PAD_SZ];
word32 rSz = sizeof(r);
byte rPad;
byte s[MAX_ECC_BYTES + ECC_MAX_PAD_SZ];
word32 sSz = sizeof(s);
byte sPad;
int idx;
ret = wc_ecc_sig_to_rs(sig, sigSz, r, &rSz, s, &sSz);
if (ret == 0) {
idx = 0;
rPad = (r[0] & 0x80) ? 1 : 0;
sPad = (s[0] & 0x80) ? 1 : 0;
sigSz = (LENGTH_SZ * 2) + rSz + rPad + sSz + sPad;
c32toa(rSz + rPad, sig + idx);
idx += LENGTH_SZ;
if (rPad)
sig[idx++] = 0;
WMEMCPY(sig + idx, r, rSz);
idx += rSz;
c32toa(sSz + sPad, sig + idx);
idx += LENGTH_SZ;
if (sPad)
sig[idx++] = 0;
WMEMCPY(sig + idx, s, sSz);
}
}
wc_ecc_free(&ecc);
if (ret != 0)
ret = WS_ECC_E;
if (ret == WS_SUCCESS) {
#if !defined(WOLFSSH_NO_SSH_RSA_SHA2_256) || \
!defined(WOLFSSH_NO_SSH_RSA_SHA2_512)
if (signRsa)
ret = SignHashRsa(&id->key.rsa, hashType,
digest, digestSz, sig, &sigSz, &agent->rng, agent->heap);
#endif
#if !defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256) || \
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP384) || \
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP512)
if (signEcc)
ret = SignHashEcc(&id->key.ecdsa, curveId, digest, digestSz,
sig, &sigSz, &agent->rng);
#endif
}
else
ret = WS_INVALID_ALGO_ID;
if (ret == WS_SUCCESS)
ret = SendSignResponse(agent, sig, sigSz);
@ -1708,8 +1793,14 @@ int wolfSSH_AGENT_SignRequest(WOLFSSH* ssh,
rxBuf, sizeof(rxBuf), ssh->agentCbCtx);
if (rxSz > 0) {
ret = DoMessage(ssh->agent, rxBuf, rxSz, &idx);
WMEMCPY(sig, ssh->agent->msg, ssh->agent->msgSz);
*sigSz = ssh->agent->msgSz;
if (ssh->agent->requestFailure) {
ssh->agent->requestFailure = 0;
ret = WS_AGENT_NO_KEY_E;
}
else {
WMEMCPY(sig, ssh->agent->msg, ssh->agent->msgSz);
*sigSz = ssh->agent->msgSz;
}
}
else ret = WS_AGENT_NO_KEY_E;
}

View File

@ -2721,6 +2721,7 @@ static int DoKexDhInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
&& ssh->handshake->kexIdGuess != ssh->handshake->kexId) {
/* skip this message. */
WLOG(WS_LOG_DEBUG, "Skipping the client's KEX init function.");
ssh->handshake->kexPacketFollows = 0;
*idx += len;
return WS_SUCCESS;
@ -6936,7 +6937,8 @@ int SendKexDhReply(WOLFSSH* ssh)
ret = WS_CRYPTO_FAILED;
}
else {
WLOG(WS_LOG_INFO, "Signing hash with RSA.");
WLOG(WS_LOG_INFO, "Signing hash with %s.",
IdToName(ssh->handshake->pubKeyId));
sigSz = wc_RsaSSL_Sign(encSig, encSigSz, sig, sizeof(sig),
&sigKeyBlock.sk.rsa.key, ssh->rng);
if (sigSz <= 0) {
@ -6948,7 +6950,8 @@ int SendKexDhReply(WOLFSSH* ssh)
}
else {
#ifndef WOLFSSH_NO_ECDSA
WLOG(WS_LOG_INFO, "Signing hash with ECDSA.");
WLOG(WS_LOG_INFO, "Signing hash with %s.",
IdToName(ssh->handshake->pubKeyId));
sigSz = sizeof(sig);
ret = wc_ecc_sign_hash(digest, wc_HashGetDigestSize(sigHashId),
sig, &sigSz,
@ -8360,8 +8363,9 @@ int SendUserAuthRequest(WOLFSSH* ssh, byte authId, int addSig)
if (authId == ID_USERAUTH_PASSWORD)
ret = PrepareUserAuthRequestPassword(ssh, &payloadSz, &authData);
else if (authId == ID_USERAUTH_PUBLICKEY) {
else if (authId == ID_USERAUTH_PUBLICKEY && !ssh->userAuthPkDone) {
authData.sf.publicKey.hasSignature = 1;
ssh->userAuthPkDone = 1;
ret = PrepareUserAuthRequestPublicKey(ssh, &payloadSz, &authData,
&keySig);
}

View File

@ -35,7 +35,6 @@
#include <wolfssl/wolfcrypt/dh.h>
#include <wolfssl/wolfcrypt/ecc.h>
#include <wolfssl/wolfcrypt/rsa.h>
#include <wolfssl/wolfcrypt/sha256.h>
#ifdef __cplusplus

View File

@ -160,6 +160,15 @@ extern "C" {
#undef WOLFSSH_NO_SSH_RSA_SHA1
#define WOLFSSH_NO_SSH_RSA_SHA1
#endif
#if defined(WOLFSSH_NO_RSA) || defined(NO_SHA256)
#undef WOLFSSH_NO_SSH_RSA_SHA2_256
#define WOLFSSH_NO_SSH_RSA_SHA2_256
#endif
#if defined(WOLFSSH_NO_RSA) || !defined(WOLFSSL_SHA512)
#undef WOLFSSH_NO_SSH_RSA_SHA2_512
#define WOLFSSH_NO_SSH_RSA_SHA2_512
#endif
#if defined(WOLFSSH_NO_ECDSA) || \
defined(NO_SHA256) || defined(NO_ECC256)
#undef WOLFSSH_NO_ECDSA_SHA2_NISTP256
@ -610,6 +619,7 @@ struct WOLFSSH {
word32 peerProtoIdSz;
void* publicKeyCheckCtx;
byte sendTerminalRequest;
byte userAuthPkDone;
#ifdef USE_WINDOWS_API
word32 defaultAttr; /* default windows attributes */