Skip to content

Commit 091399c

Browse files
yosuke-wolfsslejohnstown
authored andcommitted
agent: size the signature buffer from the identity
- PostSignRequest() allocates the signature buffer from agent->heap, sized from the identity's modulus mpint for RSA and from ECDSA_ASN_SIG_SZ for ECDSA, and frees it before returning. A modulus longer than RSA_MAX_SIZE, or a key type that sets no size, returns WS_BUFFER_E. - wolfSSH_AGENT_SignRequest() reads the agent's reply into a heap buffer of WOLFSSH_AGENT_MAX_RSP_SZ, a new overridable define in agent.c, freed after the last use of agent->msg. - tests/api.c carries a 3072-bit RSA key and a P-521 key as hex string components, and build_string() and build_mpint() helpers that write the message fields. AgentTestCtx.response sizes from AGENT_TEST_BUF_SZ. - test_wolfSSH_agent_signrequest_rsa_3072() and test_wolfSSH_agent_signrequest_ecc_p521() add their identity through the agent callbacks and sign with it, then clear the stored private exponent or point and sign again. test_wolfSSH_agent_signrequest_rsa_too_large() adds an identity whose modulus exceeds RSA_MAX_SIZE and expects WS_BUFFER_E. - The comment on test_wolfSSH_agent_signrequest_oversize_rsa_key() describes the identity that test uses. Issue: F-10541
1 parent 754317b commit 091399c

2 files changed

Lines changed: 466 additions & 12 deletions

File tree

src/agent.c

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@
6666
#endif
6767

6868

69+
/* Read buffer size for a reply from an agent. Covers a signature and its
70+
* message header for any key up to RSA-8192. */
71+
#ifndef WOLFSSH_AGENT_MAX_RSP_SZ
72+
#define WOLFSSH_AGENT_MAX_RSP_SZ 2048
73+
#endif
74+
6975
/* payloadSz is an estimate, but it shall be greater-than/equal-to
7076
* the actual value. */
7177
static int PrepareMessage(WOLFSSH_AGENT_CTX* agent, word32 payloadSz)
@@ -826,10 +832,10 @@ static int PostSignRequest(WOLFSSH_AGENT_CTX* agent,
826832
word32 flags)
827833
{
828834
WOLFSSH_AGENT_ID* id = NULL;
835+
byte* sig = NULL;
829836
int ret = WS_SUCCESS;
830-
byte sig[256];
831837
byte digest[WC_MAX_DIGEST_SIZE];
832-
word32 sigSz = sizeof(sig);
838+
word32 sigSz = 0;
833839
word32 digestSz = sizeof(digest);
834840
enum wc_HashType hashType;
835841
int curveId = 0, signRsa = 0, signEcc = 0;
@@ -901,6 +907,36 @@ static int PostSignRequest(WOLFSSH_AGENT_CTX* agent,
901907
ret = WS_CRYPTO_FAILED;
902908
}
903909

910+
/* Size the signature buffer from the identity. */
911+
if (ret == WS_SUCCESS) {
912+
#if !defined(WOLFSSH_NO_RSA_SHA2_256) || \
913+
!defined(WOLFSSH_NO_RSA_SHA2_512)
914+
if (signRsa) {
915+
/* The signature is as long as the modulus. The stored mpint
916+
* carries a leading zero byte for the sign bit. */
917+
sigSz = id->key.rsa.nSz;
918+
if (sigSz > (RSA_MAX_SIZE / 8) + 1) {
919+
WLOG(WS_LOG_AGENT, "Sign: RSA key too large.");
920+
ret = WS_BUFFER_E;
921+
}
922+
}
923+
#endif
924+
#if !defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256) || \
925+
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP384) || \
926+
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP521)
927+
if (signEcc)
928+
sigSz = ECDSA_ASN_SIG_SZ;
929+
#endif
930+
if (ret == WS_SUCCESS && sigSz == 0)
931+
ret = WS_BUFFER_E;
932+
}
933+
934+
if (ret == WS_SUCCESS) {
935+
sig = (byte*)WMALLOC(sigSz, agent->heap, DYNTYPE_AGENT_BUFFER);
936+
if (sig == NULL)
937+
ret = WS_MEMORY_E;
938+
}
939+
904940
if (ret == WS_SUCCESS) {
905941
#if !defined(WOLFSSH_NO_RSA_SHA2_256) || \
906942
!defined(WOLFSSH_NO_RSA_SHA2_512)
@@ -924,6 +960,9 @@ static int PostSignRequest(WOLFSSH_AGENT_CTX* agent,
924960
ret = SendSignResponse(agent, sig, sigSz);
925961
}
926962

963+
if (sig != NULL)
964+
WFREE(sig, agent->heap, DYNTYPE_AGENT_BUFFER);
965+
927966
WLOG_LEAVE(ret);
928967
return ret;
929968
}
@@ -1814,7 +1853,7 @@ int wolfSSH_AGENT_SignRequest(WOLFSSH* ssh,
18141853
word32 flags)
18151854
{
18161855
int ret = WS_SUCCESS;
1817-
byte rxBuf[512];
1856+
byte* rxBuf = NULL;
18181857
int rxSz;
18191858
word32 idx = 0;
18201859
WOLFSSH_AGENT_CTX* agent = NULL;
@@ -1834,6 +1873,13 @@ int wolfSSH_AGENT_SignRequest(WOLFSSH* ssh,
18341873
ret = WS_BAD_ARGUMENT;
18351874
}
18361875

1876+
if (ret == WS_SUCCESS) {
1877+
rxBuf = (byte*)WMALLOC(WOLFSSH_AGENT_MAX_RSP_SZ,
1878+
ssh->agent->heap, DYNTYPE_AGENT_BUFFER);
1879+
if (rxBuf == NULL)
1880+
ret = WS_MEMORY_E;
1881+
}
1882+
18371883
if (ret == WS_SUCCESS) {
18381884
agent = ssh->agent;
18391885
agent->requestFailure = 0;
@@ -1868,7 +1914,7 @@ int wolfSSH_AGENT_SignRequest(WOLFSSH* ssh,
18681914

18691915
if (ret == WS_SUCCESS) {
18701916
rxSz = ssh->ctx->agentIoCb(WOLFSSH_AGENT_IO_READ,
1871-
rxBuf, sizeof(rxBuf), ssh->agentCbCtx);
1917+
rxBuf, WOLFSSH_AGENT_MAX_RSP_SZ, ssh->agentCbCtx);
18721918
if (rxSz > 0) {
18731919
ret = DoMessage(ssh->agent, rxBuf, rxSz, &idx);
18741920
if (ret == WS_SUCCESS) {
@@ -1915,6 +1961,11 @@ int wolfSSH_AGENT_SignRequest(WOLFSSH* ssh,
19151961
ssh->ctx->agentCb(WOLFSSH_AGENT_LOCAL_CLEANUP, ssh->agentCbCtx);
19161962
}
19171963

1964+
/* The agent's message was parsed in place out of this buffer, so it is
1965+
* freed after the last use of agent->msg. */
1966+
if (rxBuf != NULL)
1967+
WFREE(rxBuf, ssh->agent->heap, DYNTYPE_AGENT_BUFFER);
1968+
19181969
WLOG_LEAVE(ret);
19191970
return ret;
19201971
}

0 commit comments

Comments
 (0)