@@ -650,6 +650,22 @@ static int HashUpdate(wc_HashAlg* hash, enum wc_HashType type,
650650}
651651
652652
653+ /* Hash an mpint's length and optional 0 pad byte as one update of
654+ * LENGTH_SZ + pad bytes. For K the pad is secret: this avoids a branch on
655+ * it and a zero-length update, which some hash ports reject. The hashed
656+ * length still depends on the pad. */
657+ static INLINE int HashMpintHeader(wc_HashAlg* hash, enum wc_HashType type,
658+ word32 sz, byte pad)
659+ {
660+ byte hdr[LENGTH_SZ + 1];
661+
662+ pad &= 1;
663+ c32toa(sz + pad, hdr);
664+ hdr[LENGTH_SZ] = 0;
665+ return HashUpdate(hash, type, hdr, LENGTH_SZ + pad);
666+ }
667+
668+
653669/* returns WS_SUCCESS on success */
654670static INLINE int HighwaterCheck(WOLFSSH* ssh, byte side)
655671{
@@ -3511,8 +3527,6 @@ int GenerateKey(byte hashId, byte keyId,
35113527 wc_HashAlg hash;
35123528 enum wc_HashType enmhashId = (enum wc_HashType)hashId;
35133529 byte kPad = 0;
3514- byte pad = 0;
3515- byte kSzFlat[LENGTH_SZ];
35163530 int digestSz;
35173531 int ret;
35183532
@@ -3535,17 +3549,14 @@ int GenerateKey(byte hashId, byte keyId,
35353549 /* Data can be define as string and mpint. (see Section 5 of RFC4251).
35363550 * This padding is required in the case of an mpint, but not in the case of
35373551 * a string. */
3538- if (doKeyPad && (k[0] & 0x80)) kPad = 1;
3539- c32toa(kSz + kPad, kSzFlat);
3552+ kPad = (byte)((doKeyPad != 0) & (k[0] >> 7));
35403553
35413554 blocks = keySz / digestSz;
35423555 remainder = keySz % digestSz;
35433556
35443557 ret = wc_HashInit(&hash, enmhashId);
35453558 if (ret == WS_SUCCESS)
3546- ret = HashUpdate(&hash, enmhashId, kSzFlat, LENGTH_SZ);
3547- if (ret == WS_SUCCESS && kPad)
3548- ret = HashUpdate(&hash, enmhashId, &pad, 1);
3559+ ret = HashMpintHeader(&hash, enmhashId, kSz, kPad);
35493560 if (ret == WS_SUCCESS)
35503561 ret = HashUpdate(&hash, enmhashId, k, kSz);
35513562 if (ret == WS_SUCCESS)
@@ -3575,10 +3586,7 @@ int GenerateKey(byte hashId, byte keyId,
35753586 curBlock++) {
35763587 ret = wc_HashInit(&hash, enmhashId);
35773588 if (ret != WS_SUCCESS) break;
3578- ret = HashUpdate(&hash, enmhashId, kSzFlat, LENGTH_SZ);
3579- if (ret != WS_SUCCESS) break;
3580- if (kPad)
3581- ret = HashUpdate(&hash, enmhashId, &pad, 1);
3589+ ret = HashMpintHeader(&hash, enmhashId, kSz, kPad);
35823590 if (ret != WS_SUCCESS) break;
35833591 ret = HashUpdate(&hash, enmhashId, k, kSz);
35843592 if (ret != WS_SUCCESS) break;
@@ -3596,9 +3604,7 @@ int GenerateKey(byte hashId, byte keyId,
35963604 if (ret == WS_SUCCESS)
35973605 ret = wc_HashInit(&hash, enmhashId);
35983606 if (ret == WS_SUCCESS)
3599- ret = HashUpdate(&hash, enmhashId, kSzFlat, LENGTH_SZ);
3600- if (ret == WS_SUCCESS && kPad)
3601- ret = HashUpdate(&hash, enmhashId, &pad, 1);
3607+ ret = HashMpintHeader(&hash, enmhashId, kSz, kPad);
36023608 if (ret == WS_SUCCESS)
36033609 ret = HashUpdate(&hash, enmhashId, k, kSz);
36043610 if (ret == WS_SUCCESS)
@@ -6961,36 +6967,33 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
69616967 */
69626968static int CreateMpint(byte* buf, word32* sz, byte* pad)
69636969{
6964- word32 i;
6970+ word32 i, top, back ;
69656971
69666972 if (buf == NULL || sz == NULL || pad == NULL) {
69676973 WLOG(WS_LOG_ERROR, "Internal argument error with CreateMpint");
69686974 return WS_BAD_ARGUMENT;
69696975 }
69706976
6971- if (*sz == 0)
6972- return WS_SUCCESS;
6973-
69746977 /* check for leading 0's */
69756978 for (i = 0; i < *sz; i++) {
69766979 if (buf[i] != 0x00)
69776980 break;
69786981 }
6979- /* all-zero buffer encodes as empty mpint per RFC 4251 */
6982+ /* empty or all-zero buffer encodes as empty mpint per RFC 4251 */
69806983 if (i == *sz) {
69816984 *pad = 0;
69826985 *sz = 0;
69836986 return WS_SUCCESS;
69846987 }
69856988
6986- *pad = (buf[i] & 0x80) ? 1 : 0;
6987-
6988- /* if padding would be needed and have leading 0's already then do not add
6989- * extra 0's */
6990- if (i > 0 && *pad == 1) {
6991- i = i - 1 ;
6992- *pad = 0 ;
6993- }
6989+ /* If padding is needed and there is a leading 0 already, keep one 0
6990+ * instead of adding a pad byte. No branch on the MSB, which is secret
6991+ * for K. The leading-zero count still shows in the loop above and the
6992+ * move below; the mpint length depends on it by definition. */
6993+ top = (word32)buf[i] >> 7;
6994+ back = top & (word32)(i > 0) ;
6995+ i -= back ;
6996+ *pad = (byte)(top ^ back);
69946997
69956998 /* if i is still greater than 0 then the buffer needs shifted to remove
69966999 * leading 0's */
@@ -8733,13 +8736,7 @@ static int DoKexDhReply(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
87338736 }
87348737
87358738 if (ret == 0) {
8736- c32toa(ssh->kSz + kPad, scratchLen);
8737- ret = HashUpdate(hash, hashId, scratchLen, LENGTH_SZ);
8738- }
8739-
8740- if ((ret == 0) && (kPad)) {
8741- scratchLen[0] = 0;
8742- ret = HashUpdate(hash, hashId, scratchLen, 1);
8739+ ret = HashMpintHeader(hash, hashId, ssh->kSz, kPad);
87438740 }
87448741
87458742 if (ret == 0) {
@@ -18351,6 +18348,7 @@ int SendKexDhReply(WOLFSSH* ssh)
1835118348 c32toa(fSz + fPad, scratchLen);
1835218349 ret = HashUpdate(hash, hashId, scratchLen, LENGTH_SZ);
1835318350 }
18351+ /* f is public, so branching on its pad is fine. */
1835418352 if ((ret == 0) && (fPad)) {
1835518353 scratchLen[0] = 0;
1835618354 ret = HashUpdate(hash, hashId, scratchLen, 1);
@@ -18364,12 +18362,7 @@ int SendKexDhReply(WOLFSSH* ssh)
1836418362 ret = CreateMpint(ssh->k, &ssh->kSz, &kPad);
1836518363 }
1836618364 if (ret == 0) {
18367- c32toa(ssh->kSz + kPad, scratchLen);
18368- ret = HashUpdate(hash, hashId, scratchLen, LENGTH_SZ);
18369- }
18370- if ((ret == 0) && (kPad)) {
18371- scratchLen[0] = 0;
18372- ret = HashUpdate(hash, hashId, scratchLen, 1);
18365+ ret = HashMpintHeader(hash, hashId, ssh->kSz, kPad);
1837318366 }
1837418367 if (ret == 0) {
1837518368 ret = HashUpdate(hash, hashId, ssh->k, ssh->kSz);
@@ -25831,6 +25824,11 @@ int wolfSSH_TestChannelPutData(WOLFSSH_CHANNEL* channel, byte* data,
2583125824 return ChannelPutData(channel, data, dataSz);
2583225825}
2583325826
25827+ int wolfSSH_TestCreateMpint(byte* buf, word32* sz, byte* pad)
25828+ {
25829+ return CreateMpint(buf, sz, pad);
25830+ }
25831+
2583425832int wolfSSH_TestBuildNameList(char* buf, word32 bufSz,
2583525833 const byte* src, word32 srcSz)
2583625834{
0 commit comments