SSH-AGENT

1. For the client agent command line option, add the flag to the flag string.
2. Update PostSignRequest() to support all flavors of ECDSA and to
   switch out code for missing algorithms.
3. Hide function SendRequestIdentities().
pull/319/head
John Safranek 2020-11-04 14:42:23 -08:00
parent 2b2a30ca54
commit 351bc7585e
No known key found for this signature in database
GPG Key ID: 8CE817DE0D3CCB4A
2 changed files with 231 additions and 140 deletions

View File

@ -826,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;

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,20 +641,13 @@ static int PostRequestIds(WOLFSSH_AGENT_CTX* agent)
}
static int PostSignRequest(WOLFSSH_AGENT_CTX* agent,
byte* keyBlob, word32 keyBlobSz, byte* data, word32 dataSz,
word32 flags)
static WOLFSSH_AGENT_ID* FindKeyId(WOLFSSH_AGENT_ID* id,
const byte* keyBlob, word32 keyBlobSz)
{
WOLFSSH_AGENT_ID* cur = NULL;
int ret;
wc_Sha256 sha;
byte digest[WC_SHA256_DIGEST_SIZE];
int ret = WS_SUCCESS;
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);
@ -637,64 +657,35 @@ static int PostSignRequest(WOLFSSH_AGENT_CTX* agent,
}
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;
}
while (id != NULL &&
WMEMCMP(digest, id, WC_SHA256_DIGEST_SIZE) != 0 &&
WMEMCMP(keyBlob, id->keyBlob, keyBlobSz)) {
id = id->next;
}
}
if (ret == WS_SUCCESS) {
if ((cur->keyType == ID_SSH_RSA && flags & AGENT_SIGN_RSA_SHA2_256) ||
cur->keyType == ID_ECDSA_SHA2_NISTP256) {
return id;
}
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;
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;
enum wc_HashType hashType = WC_HASH_TYPE_NONE;
int ret = 0;
key = &cur->key.rsa;
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);
if (flags & AGENT_SIGN_RSA_SHA2_256)
hashType = WC_HASH_TYPE_SHA256;
else if (flags & AGENT_SIGN_RSA_SHA2_512)
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),
encSigSz = wc_EncodeSignature(encSig, digest, digestSz,
wc_HashGetOID(hashType));
if (encSigSz <= 0) {
WLOG(WS_LOG_DEBUG, "Bad Encode Sig");
@ -702,33 +693,33 @@ static int PostSignRequest(WOLFSSH_AGENT_CTX* agent,
}
else {
WLOG(WS_LOG_INFO, "Signing hash with RSA.");
sigSz = wc_RsaSSL_Sign(encSig, encSigSz, sig, sizeof(sig),
&rsa, &agent->rng);
if (sigSz <= 0) {
*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(&rsa);
wc_FreeRsaKey(&key);
if (ret != 0)
ret = WS_RSA_E;
#endif
}
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);
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, wc_HashGetDigestSize(hashType),
sig, (word32*)&sigSz, &agent->rng, &ecc);
ret = wc_ecc_sign_hash(digest, digestSz, sig, sigSz, rng, &key);
}
if (ret != 0) {
WLOG(WS_LOG_DEBUG, "SendKexDhReply: Bad ECDSA Sign");
@ -743,12 +734,12 @@ static int PostSignRequest(WOLFSSH_AGENT_CTX* agent,
byte sPad;
int idx;
ret = wc_ecc_sig_to_rs(sig, sigSz, r, &rSz, s, &sSz);
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;
*sigSz = (LENGTH_SZ * 2) + rSz + rPad + sSz + sPad;
c32toa(rSz + rPad, sig + idx);
idx += LENGTH_SZ;
@ -764,13 +755,107 @@ static int PostSignRequest(WOLFSSH_AGENT_CTX* agent,
}
}
wc_ecc_free(&ecc);
wc_ecc_free(&key);
if (ret != 0)
ret = WS_ECC_E;
#endif
return ret;
}
static int PostSignRequest(WOLFSSH_AGENT_CTX* agent,
byte* keyBlob, word32 keyBlobSz, byte* data, word32 dataSz,
word32 flags)
{
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) {
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) {
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;
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;
curveId = ECC_SECP521R1;
signEcc = 1;
break;
#endif
default:
ret = WS_INVALID_ALGO_ID;
}
}
if (ret == WS_SUCCESS) {
ret = wc_Hash(hashType, data, dataSz, digest, digestSz);
if (ret != 0)
ret = WS_CRYPTO_FAILED;
}
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
if (ret == WS_SUCCESS)
ret = SendSignResponse(agent, sig, sigSz);
@ -1708,9 +1793,15 @@ int wolfSSH_AGENT_SignRequest(WOLFSSH* ssh,
rxBuf, sizeof(rxBuf), ssh->agentCbCtx);
if (rxSz > 0) {
ret = DoMessage(ssh->agent, rxBuf, rxSz, &idx);
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;
}