@@ -570,13 +570,11 @@ static HandshakeInfo* HandshakeInfoNew(void* heap)
570570 heap, DYNTYPE_HS);
571571 if (newHs != NULL) {
572572 WMEMSET(newHs, 0, sizeof(HandshakeInfo));
573- newHs->expectMsgId = MSGID_NONE;
574- newHs->kexId = ID_NONE;
575573 newHs->kexHashId = WC_HASH_TYPE_NONE;
576- newHs->pubKeyId = ID_NONE;
577- newHs->encryptId = ID_NONE;
578- newHs->macId = ID_NONE;
579574 newHs->blockSz = MIN_BLOCK_SZ;
575+ newHs->peerBlockSz = MIN_BLOCK_SZ;
576+ /* peerEncryptId, peerMacId, peerAeadMode, peerMacSz: left at 0
577+ * (== ID_NONE / no-MAC) by the WMEMSET above. */
580578 newHs->eSz = (word32)sizeof(newHs->e);
581579 newHs->xSz = (word32)sizeof(newHs->x);
582580#ifndef WOLFSSH_NO_DH_GEX_SHA256
@@ -2625,7 +2623,7 @@ static int GenerateKeys(WOLFSSH* ssh, byte hashId, byte doKeyPad)
26252623 Keys* sK = NULL;
26262624 int ret = WS_SUCCESS;
26272625
2628- if (ssh == NULL)
2626+ if (ssh == NULL || ssh->handshake == NULL )
26292627 ret = WS_BAD_ARGUMENT;
26302628 else {
26312629 if (ssh->ctx->side == WOLFSSH_ENDPOINT_SERVER) {
@@ -2658,19 +2656,17 @@ static int GenerateKeys(WOLFSSH* ssh, byte hashId, byte doKeyPad)
26582656 sK->encKey, sK->encKeySz,
26592657 ssh->k, ssh->kSz, ssh->h, ssh->hSz,
26602658 ssh->sessionId, ssh->sessionIdSz, doKeyPad);
2661- if (ret == WS_SUCCESS) {
2662- if (!ssh->handshake->aeadMode) {
2663- ret = GenerateKey(hashId, 'E',
2664- cK->macKey, cK->macKeySz,
2665- ssh->k, ssh->kSz, ssh->h, ssh->hSz,
2666- ssh->sessionId, ssh->sessionIdSz, doKeyPad);
2667- if (ret == WS_SUCCESS) {
2668- ret = GenerateKey(hashId, 'F',
2669- sK->macKey, sK->macKeySz,
2670- ssh->k, ssh->kSz, ssh->h, ssh->hSz,
2671- ssh->sessionId, ssh->sessionIdSz, doKeyPad);
2672- }
2673- }
2659+ if (ret == WS_SUCCESS && cK->macKeySz > 0) {
2660+ ret = GenerateKey(hashId, 'E',
2661+ cK->macKey, cK->macKeySz,
2662+ ssh->k, ssh->kSz, ssh->h, ssh->hSz,
2663+ ssh->sessionId, ssh->sessionIdSz, doKeyPad);
2664+ }
2665+ if (ret == WS_SUCCESS && sK->macKeySz > 0) {
2666+ ret = GenerateKey(hashId, 'F',
2667+ sK->macKey, sK->macKeySz,
2668+ ssh->k, ssh->kSz, ssh->h, ssh->hSz,
2669+ ssh->sessionId, ssh->sessionIdSz, doKeyPad);
26742670 }
26752671
26762672#ifdef SHOW_SECRETS
@@ -4258,6 +4254,18 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
42584254 word32 cannedAlgoNamesSz;
42594255 word32 skipSz = 0;
42604256 word32 begin;
4257+ /* handshake->keys/encryptId/... always represent the LOCAL endpoint's
4258+ * outgoing direction; peer* counterparts represent the peer's outgoing
4259+ * (= our incoming) direction. Server: local=S2C, peer=C2S.
4260+ * Client: local=C2S, peer=S2C. These aliases let the four enc/MAC
4261+ * parse sections store results without inline side checks, and keep the
4262+ * fields consistent with what GenerateKeys/SendNewKeys/DoNewKeys expect. */
4263+ byte *c2sEncryptId = NULL, *c2sAeadMode = NULL, *c2sBlockSz = NULL,
4264+ *c2sMacId = NULL, *c2sMacSz = NULL;
4265+ Keys *c2sKeys = NULL;
4266+ byte *s2cEncryptId = NULL, *s2cAeadMode = NULL, *s2cBlockSz = NULL,
4267+ *s2cMacId = NULL, *s2cMacSz = NULL;
4268+ Keys *s2cKeys = NULL;
42614269
42624270 WLOG(WS_LOG_DEBUG, "Entering DoKexInit()");
42634271
@@ -4300,6 +4308,35 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
43004308 begin = *idx;
43014309 side = ssh->ctx->side;
43024310
4311+ if (side == WOLFSSH_ENDPOINT_SERVER) {
4312+ c2sEncryptId = &ssh->handshake->peerEncryptId;
4313+ c2sAeadMode = &ssh->handshake->peerAeadMode;
4314+ c2sBlockSz = &ssh->handshake->peerBlockSz;
4315+ c2sMacId = &ssh->handshake->peerMacId;
4316+ c2sMacSz = &ssh->handshake->peerMacSz;
4317+ c2sKeys = &ssh->handshake->peerKeys;
4318+ s2cEncryptId = &ssh->handshake->encryptId;
4319+ s2cAeadMode = &ssh->handshake->aeadMode;
4320+ s2cBlockSz = &ssh->handshake->blockSz;
4321+ s2cMacId = &ssh->handshake->macId;
4322+ s2cMacSz = &ssh->handshake->macSz;
4323+ s2cKeys = &ssh->handshake->keys;
4324+ }
4325+ else {
4326+ c2sEncryptId = &ssh->handshake->encryptId;
4327+ c2sAeadMode = &ssh->handshake->aeadMode;
4328+ c2sBlockSz = &ssh->handshake->blockSz;
4329+ c2sMacId = &ssh->handshake->macId;
4330+ c2sMacSz = &ssh->handshake->macSz;
4331+ c2sKeys = &ssh->handshake->keys;
4332+ s2cEncryptId = &ssh->handshake->peerEncryptId;
4333+ s2cAeadMode = &ssh->handshake->peerAeadMode;
4334+ s2cBlockSz = &ssh->handshake->peerBlockSz;
4335+ s2cMacId = &ssh->handshake->peerMacId;
4336+ s2cMacSz = &ssh->handshake->peerMacSz;
4337+ s2cKeys = &ssh->handshake->peerKeys;
4338+ }
4339+
43034340 /* Check that the cookie exists inside the message */
43044341 if (begin + COOKIE_SZ > len) {
43054342 /* error, out of bounds */
@@ -4399,6 +4436,24 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
43994436 ret = WS_MATCH_ENC_ALGO_E;
44004437 }
44014438 }
4439+ if (ret == WS_SUCCESS) {
4440+ *c2sEncryptId = algoId;
4441+ *c2sAeadMode = AeadModeForId(algoId);
4442+ *c2sBlockSz = BlockSzForId(algoId);
4443+ c2sKeys->encKeySz = KeySzForId(algoId);
4444+ if (!*c2sAeadMode) {
4445+ c2sKeys->ivSz = *c2sBlockSz;
4446+ }
4447+ else {
4448+ /* Reaching here requires an AEAD cipher ID, which requires
4449+ * WOLFSSH_NO_AES_GCM to be unset, hence WOLFSSH_NO_AEAD unset
4450+ * (see internal.h). */
4451+ c2sKeys->ivSz = AEAD_NONCE_SZ;
4452+ *c2sMacSz = *c2sBlockSz;
4453+ *c2sMacId = ID_NONE;
4454+ c2sKeys->macKeySz = 0;
4455+ }
4456+ }
44024457
44034458 /* Enc Algorithms - Server to Client */
44044459 if (ret == WS_SUCCESS) {
@@ -4407,31 +4462,32 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
44074462 ret = GetNameList(list, &listSz, buf, len, &begin);
44084463 }
44094464 if (ret == WS_SUCCESS) {
4410- algoId = MatchIdLists(side, list, listSz, &algoId, 1);
4465+ cannedAlgoNamesSz = AlgoListSz(ssh->algoListCipher);
4466+ cannedListSz = (word32)sizeof(cannedList);
4467+ ret = GetNameListRaw(cannedList, &cannedListSz,
4468+ (const byte*)ssh->algoListCipher, cannedAlgoNamesSz);
4469+ }
4470+ if (ret == WS_SUCCESS) {
4471+ algoId = MatchIdLists(side, list, listSz, cannedList, cannedListSz);
44114472 if (algoId == ID_UNKNOWN) {
44124473 WLOG(WS_LOG_DEBUG, "Unable to negotiate Encryption Algo S2C");
44134474 ret = WS_MATCH_ENC_ALGO_E;
44144475 }
44154476 }
44164477 if (ret == WS_SUCCESS) {
4417- ssh->handshake->encryptId = algoId;
4418- ssh->handshake->aeadMode = AeadModeForId(algoId);
4419- ssh->handshake->blockSz = BlockSzForId(algoId);
4420- ssh->handshake->keys.encKeySz =
4421- ssh->handshake->peerKeys.encKeySz =
4422- KeySzForId(algoId);
4423- if (!ssh->handshake->aeadMode) {
4424- ssh->handshake->keys.ivSz =
4425- ssh->handshake->peerKeys.ivSz =
4426- ssh->handshake->blockSz;
4478+ *s2cEncryptId = algoId;
4479+ *s2cAeadMode = AeadModeForId(algoId);
4480+ *s2cBlockSz = BlockSzForId(algoId);
4481+ s2cKeys->encKeySz = KeySzForId(algoId);
4482+ if (!*s2cAeadMode) {
4483+ s2cKeys->ivSz = *s2cBlockSz;
44274484 }
44284485 else {
4429- #ifndef WOLFSSH_NO_AEAD
4430- ssh->handshake->keys.ivSz =
4431- ssh->handshake->peerKeys.ivSz =
4432- AEAD_NONCE_SZ;
4433- ssh->handshake->macSz = ssh->handshake->blockSz;
4434- #endif
4486+ /* Same invariant as C2S: AEAD cipher ID implies !WOLFSSH_NO_AEAD. */
4487+ s2cKeys->ivSz = AEAD_NONCE_SZ;
4488+ *s2cMacSz = *s2cBlockSz;
4489+ *s2cMacId = ID_NONE;
4490+ s2cKeys->macKeySz = 0;
44354491 }
44364492 }
44374493
@@ -4441,7 +4497,7 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
44414497 listSz = (word32)sizeof(list);
44424498 ret = GetNameList(list, &listSz, buf, len, &begin);
44434499 }
4444- if (ret == WS_SUCCESS && !ssh->handshake->aeadMode ) {
4500+ if (ret == WS_SUCCESS && !*c2sAeadMode ) {
44454501 cannedAlgoNamesSz = AlgoListSz(ssh->algoListMac);
44464502 cannedListSz = (word32)sizeof(cannedList);
44474503 ret = GetNameListRaw(cannedList, &cannedListSz,
@@ -4453,6 +4509,11 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
44534509 WLOG(WS_LOG_DEBUG, "Unable to negotiate MAC Algo C2S");
44544510 ret = WS_MATCH_MAC_ALGO_E;
44554511 }
4512+ else {
4513+ *c2sMacId = algoId;
4514+ *c2sMacSz = MacSzForId(algoId);
4515+ c2sKeys->macKeySz = KeySzForId(algoId);
4516+ }
44564517 }
44574518 }
44584519
@@ -4462,18 +4523,22 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
44624523 listSz = (word32)sizeof(list);
44634524 ret = GetNameList(list, &listSz, buf, len, &begin);
44644525 }
4465- if (ret == WS_SUCCESS && !ssh->handshake->aeadMode) {
4466- algoId = MatchIdLists(side, list, listSz, &algoId, 1);
4467- if (algoId == ID_UNKNOWN) {
4468- WLOG(WS_LOG_DEBUG, "Unable to negotiate MAC Algo S2C");
4469- ret = WS_MATCH_MAC_ALGO_E;
4470- }
4471- else {
4472- ssh->handshake->macId = algoId;
4473- ssh->handshake->macSz = MacSzForId(algoId);
4474- ssh->handshake->keys.macKeySz =
4475- ssh->handshake->peerKeys.macKeySz =
4476- KeySzForId(algoId);
4526+ if (ret == WS_SUCCESS && !*s2cAeadMode) {
4527+ cannedAlgoNamesSz = AlgoListSz(ssh->algoListMac);
4528+ cannedListSz = (word32)sizeof(cannedList);
4529+ ret = GetNameListRaw(cannedList, &cannedListSz,
4530+ (const byte*)ssh->algoListMac, cannedAlgoNamesSz);
4531+ if (ret == WS_SUCCESS) {
4532+ algoId = MatchIdLists(side, list, listSz, cannedList, cannedListSz);
4533+ if (algoId == ID_UNKNOWN) {
4534+ WLOG(WS_LOG_DEBUG, "Unable to negotiate MAC Algo S2C");
4535+ ret = WS_MATCH_MAC_ALGO_E;
4536+ }
4537+ else {
4538+ *s2cMacId = algoId;
4539+ *s2cMacSz = MacSzForId(algoId);
4540+ s2cKeys->macKeySz = KeySzForId(algoId);
4541+ }
44774542 }
44784543 }
44794544
@@ -6226,11 +6291,11 @@ static int DoNewKeys(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
62266291 }
62276292
62286293 if (ret == WS_SUCCESS) {
6229- ssh->peerEncryptId = ssh->handshake->encryptId ;
6230- ssh->peerMacId = ssh->handshake->macId ;
6231- ssh->peerBlockSz = ssh->handshake->blockSz ;
6232- ssh->peerMacSz = ssh->handshake->macSz ;
6233- ssh->peerAeadMode = ssh->handshake->aeadMode ;
6294+ ssh->peerEncryptId = ssh->handshake->peerEncryptId ;
6295+ ssh->peerMacId = ssh->handshake->peerMacId ;
6296+ ssh->peerBlockSz = ssh->handshake->peerBlockSz ;
6297+ ssh->peerMacSz = ssh->handshake->peerMacSz ;
6298+ ssh->peerAeadMode = ssh->handshake->peerAeadMode ;
62346299 WMEMCPY(&ssh->peerKeys, &ssh->handshake->peerKeys, sizeof(Keys));
62356300
62366301 switch (ssh->peerEncryptId) {
@@ -17960,6 +18025,17 @@ int wolfSSH_TestDoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
1796018025 return DoKexInit(ssh, buf, len, idx);
1796118026}
1796218027
18028+ int wolfSSH_TestDoNewKeys(WOLFSSH* ssh)
18029+ {
18030+ /* DoNewKeys ignores buf/len/idx (marked WOLFSSH_UNUSED internally). */
18031+ return DoNewKeys(ssh, NULL, 0, NULL);
18032+ }
18033+
18034+ int wolfSSH_TestGenerateKeys(WOLFSSH* ssh, byte hashId)
18035+ {
18036+ return GenerateKeys(ssh, (enum wc_HashType)hashId, 1);
18037+ }
18038+
1796318039int wolfSSH_TestDoKexDhInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
1796418040{
1796518041 return DoKexDhInit(ssh, buf, len, idx);
0 commit comments