Refactor Packet Assembly

1. PreparePacket() is to be given an estimated payloadSz, not the actual
payloadSz. The payloadSz should be larger or equal to the actual.
2. BuildPacket() calculates the actual payloadSz based on the position
of idx and value of idx stored before PreparePacket() returns. The size
of the padding is also calculated at this point.

Currently, everything going into a packet needs to be calculated ahead
of time and saved locally until the output buffer is prepared. This
requires saving RSA and ECDSA signatures in large buffers to be copied
later. Now such things can be calculated directly into the output buffer
without the temporary storage and copy.
pull/168/head
John Safranek 2019-06-05 14:20:31 -07:00
parent a3881e1471
commit 46d97d751c
2 changed files with 28 additions and 20 deletions

View File

@ -5160,26 +5160,20 @@ int SendProtoId(WOLFSSH* ssh)
} }
/* payloadSz is an estimate. It should be a worst case. The actual value
* will be nailed down when the packet is bundled to be sent. */
static int PreparePacket(WOLFSSH* ssh, word32 payloadSz) static int PreparePacket(WOLFSSH* ssh, word32 payloadSz)
{ {
int ret = WS_SUCCESS; int ret = WS_SUCCESS;
byte* output;
word32 outputSz;
word32 packetSz;
word32 usedSz;
byte paddingSz;
if (ssh == NULL) if (ssh == NULL)
ret = WS_BAD_ARGUMENT; ret = WS_BAD_ARGUMENT;
if (ret == WS_SUCCESS) { if (ret == WS_SUCCESS) {
/* Minimum value for paddingSz is 4. */ word32 packetSz, usedSz, outputSz;
paddingSz = ssh->blockSz - byte paddingSz;
((ssh->aeadMode ? 0 : LENGTH_SZ) +
PAD_LENGTH_SZ + payloadSz) % ssh->blockSz; paddingSz = ssh->blockSz * 2;
if (paddingSz < MIN_PAD_LENGTH)
paddingSz += ssh->blockSz;
ssh->paddingSz = paddingSz;
packetSz = PAD_LENGTH_SZ + payloadSz + paddingSz; packetSz = PAD_LENGTH_SZ + payloadSz + paddingSz;
outputSz = LENGTH_SZ + packetSz + ssh->macSz; outputSz = LENGTH_SZ + packetSz + ssh->macSz;
usedSz = ssh->outputBuffer.length - ssh->outputBuffer.idx; usedSz = ssh->outputBuffer.length - ssh->outputBuffer.idx;
@ -5189,12 +5183,6 @@ static int PreparePacket(WOLFSSH* ssh, word32 payloadSz)
if (ret == WS_SUCCESS) { if (ret == WS_SUCCESS) {
ssh->packetStartIdx = ssh->outputBuffer.length; ssh->packetStartIdx = ssh->outputBuffer.length;
output = ssh->outputBuffer.buffer + ssh->outputBuffer.length;
/* fill in the packetSz, paddingSz */
c32toa(packetSz, output);
output[LENGTH_SZ] = paddingSz;
ssh->outputBuffer.length += LENGTH_SZ + PAD_LENGTH_SZ; ssh->outputBuffer.length += LENGTH_SZ + PAD_LENGTH_SZ;
} }
@ -5213,9 +5201,30 @@ static int BundlePacket(WOLFSSH* ssh)
ret = WS_BAD_ARGUMENT; ret = WS_BAD_ARGUMENT;
if (ret == WS_SUCCESS) { if (ret == WS_SUCCESS) {
word32 payloadSz, packetSz;
output = ssh->outputBuffer.buffer; output = ssh->outputBuffer.buffer;
idx = ssh->outputBuffer.length; idx = ssh->outputBuffer.length;
paddingSz = ssh->paddingSz;
/* Calculate the actual payload size based on the data
* written into the buffer. packetStartIdx is before the
* LENGTH and PAD_LENGTH, subtract those out, as well. */
payloadSz = idx - ssh->packetStartIdx - LENGTH_SZ - PAD_LENGTH_SZ;
/* Minimum value for paddingSz is 4. */
paddingSz = ssh->blockSz -
((ssh->aeadMode ? 0 : LENGTH_SZ) +
PAD_LENGTH_SZ + payloadSz) % ssh->blockSz;
if (paddingSz < MIN_PAD_LENGTH)
paddingSz += ssh->blockSz;
packetSz = PAD_LENGTH_SZ + payloadSz + paddingSz;
/* fill in the packetSz, paddingSz */
c32toa(packetSz, output + ssh->packetStartIdx);
output[ssh->packetStartIdx + LENGTH_SZ] = paddingSz;
/* end new */
/* Add the padding */ /* Add the padding */
WLOG(WS_LOG_DEBUG, "BP: paddingSz = %u", paddingSz); WLOG(WS_LOG_DEBUG, "BP: paddingSz = %u", paddingSz);

View File

@ -298,7 +298,6 @@ struct WOLFSSH {
word32 seq; word32 seq;
word32 peerSeq; word32 peerSeq;
word32 packetStartIdx; /* Current send packet start index */ word32 packetStartIdx; /* Current send packet start index */
byte paddingSz; /* Current send packet padding size */
byte acceptState; byte acceptState;
byte connectState; byte connectState;
byte clientState; byte clientState;