@@ -571,13 +571,9 @@ static HandshakeInfo* HandshakeInfoNew(void* heap)
571571 heap, DYNTYPE_HS);
572572 if (newHs != NULL) {
573573 WMEMSET(newHs, 0, sizeof(HandshakeInfo));
574- newHs->expectMsgId = MSGID_NONE;
575- newHs->kexId = ID_NONE;
576574 newHs->kexHashId = WC_HASH_TYPE_NONE;
577- newHs->pubKeyId = ID_NONE;
578- newHs->encryptId = ID_NONE;
579- newHs->macId = ID_NONE;
580575 newHs->blockSz = MIN_BLOCK_SZ;
576+ newHs->peerBlockSz = MIN_BLOCK_SZ;
581577 newHs->eSz = (word32)sizeof(newHs->e);
582578 newHs->xSz = (word32)sizeof(newHs->x);
583579#ifndef WOLFSSH_NO_DH_GEX_SHA256
@@ -2659,19 +2655,17 @@ static int GenerateKeys(WOLFSSH* ssh, byte hashId, byte doKeyPad)
26592655 sK->encKey, sK->encKeySz,
26602656 ssh->k, ssh->kSz, ssh->h, ssh->hSz,
26612657 ssh->sessionId, ssh->sessionIdSz, doKeyPad);
2662- if (ret == WS_SUCCESS) {
2663- if (!ssh->handshake->aeadMode) {
2664- ret = GenerateKey(hashId, 'E',
2665- cK->macKey, cK->macKeySz,
2666- ssh->k, ssh->kSz, ssh->h, ssh->hSz,
2667- ssh->sessionId, ssh->sessionIdSz, doKeyPad);
2668- if (ret == WS_SUCCESS) {
2669- ret = GenerateKey(hashId, 'F',
2670- sK->macKey, sK->macKeySz,
2671- ssh->k, ssh->kSz, ssh->h, ssh->hSz,
2672- ssh->sessionId, ssh->sessionIdSz, doKeyPad);
2673- }
2674- }
2658+ if (ret == WS_SUCCESS && cK->macKeySz > 0) {
2659+ ret = GenerateKey(hashId, 'E',
2660+ cK->macKey, cK->macKeySz,
2661+ ssh->k, ssh->kSz, ssh->h, ssh->hSz,
2662+ ssh->sessionId, ssh->sessionIdSz, doKeyPad);
2663+ }
2664+ if (ret == WS_SUCCESS && sK->macKeySz > 0) {
2665+ ret = GenerateKey(hashId, 'F',
2666+ sK->macKey, sK->macKeySz,
2667+ ssh->k, ssh->kSz, ssh->h, ssh->hSz,
2668+ ssh->sessionId, ssh->sessionIdSz, doKeyPad);
26752669 }
26762670
26772671#ifdef SHOW_SECRETS
@@ -4250,6 +4244,18 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
42504244 word32 cannedAlgoNamesSz;
42514245 word32 skipSz = 0;
42524246 word32 begin;
4247+ /* handshake->keys/encryptId/... always represent the LOCAL endpoint's
4248+ * outgoing direction; peer* counterparts represent the peer's outgoing
4249+ * (= our incoming) direction. Server: local=S2C, peer=C2S.
4250+ * Client: local=C2S, peer=S2C. These aliases let the four enc/MAC
4251+ * parse sections store results without inline side checks, and keep the
4252+ * fields consistent with what GenerateKeys/SendNewKeys/DoNewKeys expect. */
4253+ byte *c2sEncryptId = NULL, *c2sAeadMode = NULL, *c2sBlockSz = NULL,
4254+ *c2sMacId = NULL, *c2sMacSz = NULL;
4255+ Keys *c2sKeys = NULL;
4256+ byte *s2cEncryptId = NULL, *s2cAeadMode = NULL, *s2cBlockSz = NULL,
4257+ *s2cMacId = NULL, *s2cMacSz = NULL;
4258+ Keys *s2cKeys = NULL;
42534259
42544260 WLOG(WS_LOG_DEBUG, "Entering DoKexInit()");
42554261
@@ -4292,6 +4298,35 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
42924298 begin = *idx;
42934299 side = ssh->ctx->side;
42944300
4301+ if (side == WOLFSSH_ENDPOINT_SERVER) {
4302+ c2sEncryptId = &ssh->handshake->peerEncryptId;
4303+ c2sAeadMode = &ssh->handshake->peerAeadMode;
4304+ c2sBlockSz = &ssh->handshake->peerBlockSz;
4305+ c2sMacId = &ssh->handshake->peerMacId;
4306+ c2sMacSz = &ssh->handshake->peerMacSz;
4307+ c2sKeys = &ssh->handshake->peerKeys;
4308+ s2cEncryptId = &ssh->handshake->encryptId;
4309+ s2cAeadMode = &ssh->handshake->aeadMode;
4310+ s2cBlockSz = &ssh->handshake->blockSz;
4311+ s2cMacId = &ssh->handshake->macId;
4312+ s2cMacSz = &ssh->handshake->macSz;
4313+ s2cKeys = &ssh->handshake->keys;
4314+ }
4315+ else {
4316+ c2sEncryptId = &ssh->handshake->encryptId;
4317+ c2sAeadMode = &ssh->handshake->aeadMode;
4318+ c2sBlockSz = &ssh->handshake->blockSz;
4319+ c2sMacId = &ssh->handshake->macId;
4320+ c2sMacSz = &ssh->handshake->macSz;
4321+ c2sKeys = &ssh->handshake->keys;
4322+ s2cEncryptId = &ssh->handshake->peerEncryptId;
4323+ s2cAeadMode = &ssh->handshake->peerAeadMode;
4324+ s2cBlockSz = &ssh->handshake->peerBlockSz;
4325+ s2cMacId = &ssh->handshake->peerMacId;
4326+ s2cMacSz = &ssh->handshake->peerMacSz;
4327+ s2cKeys = &ssh->handshake->peerKeys;
4328+ }
4329+
42954330 /* Check that the cookie exists inside the message */
42964331 if (begin + COOKIE_SZ > len) {
42974332 /* error, out of bounds */
@@ -4391,6 +4426,24 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
43914426 ret = WS_MATCH_ENC_ALGO_E;
43924427 }
43934428 }
4429+ if (ret == WS_SUCCESS) {
4430+ *c2sEncryptId = algoId;
4431+ *c2sAeadMode = AeadModeForId(algoId);
4432+ *c2sBlockSz = BlockSzForId(algoId);
4433+ c2sKeys->encKeySz = KeySzForId(algoId);
4434+ if (!*c2sAeadMode) {
4435+ c2sKeys->ivSz = *c2sBlockSz;
4436+ }
4437+ else {
4438+ /* Reaching here requires an AEAD cipher ID, which requires
4439+ * WOLFSSH_NO_AES_GCM to be unset, hence WOLFSSH_NO_AEAD unset
4440+ * (see internal.h). */
4441+ c2sKeys->ivSz = AEAD_NONCE_SZ;
4442+ *c2sMacSz = *c2sBlockSz;
4443+ *c2sMacId = ID_NONE;
4444+ c2sKeys->macKeySz = 0;
4445+ }
4446+ }
43944447
43954448 /* Enc Algorithms - Server to Client */
43964449 if (ret == WS_SUCCESS) {
@@ -4399,31 +4452,32 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
43994452 ret = GetNameList(list, &listSz, buf, len, &begin);
44004453 }
44014454 if (ret == WS_SUCCESS) {
4402- algoId = MatchIdLists(side, list, listSz, &algoId, 1);
4455+ cannedAlgoNamesSz = AlgoListSz(ssh->algoListCipher);
4456+ cannedListSz = (word32)sizeof(cannedList);
4457+ ret = GetNameListRaw(cannedList, &cannedListSz,
4458+ (const byte*)ssh->algoListCipher, cannedAlgoNamesSz);
4459+ }
4460+ if (ret == WS_SUCCESS) {
4461+ algoId = MatchIdLists(side, list, listSz, cannedList, cannedListSz);
44034462 if (algoId == ID_UNKNOWN) {
44044463 WLOG(WS_LOG_DEBUG, "Unable to negotiate Encryption Algo S2C");
44054464 ret = WS_MATCH_ENC_ALGO_E;
44064465 }
44074466 }
44084467 if (ret == WS_SUCCESS) {
4409- ssh->handshake->encryptId = algoId;
4410- ssh->handshake->aeadMode = AeadModeForId(algoId);
4411- ssh->handshake->blockSz = BlockSzForId(algoId);
4412- ssh->handshake->keys.encKeySz =
4413- ssh->handshake->peerKeys.encKeySz =
4414- KeySzForId(algoId);
4415- if (!ssh->handshake->aeadMode) {
4416- ssh->handshake->keys.ivSz =
4417- ssh->handshake->peerKeys.ivSz =
4418- ssh->handshake->blockSz;
4468+ *s2cEncryptId = algoId;
4469+ *s2cAeadMode = AeadModeForId(algoId);
4470+ *s2cBlockSz = BlockSzForId(algoId);
4471+ s2cKeys->encKeySz = KeySzForId(algoId);
4472+ if (!*s2cAeadMode) {
4473+ s2cKeys->ivSz = *s2cBlockSz;
44194474 }
44204475 else {
4421- #ifndef WOLFSSH_NO_AEAD
4422- ssh->handshake->keys.ivSz =
4423- ssh->handshake->peerKeys.ivSz =
4424- AEAD_NONCE_SZ;
4425- ssh->handshake->macSz = ssh->handshake->blockSz;
4426- #endif
4476+ /* Same invariant as C2S: AEAD cipher ID implies !WOLFSSH_NO_AEAD. */
4477+ s2cKeys->ivSz = AEAD_NONCE_SZ;
4478+ *s2cMacSz = *s2cBlockSz;
4479+ *s2cMacId = ID_NONE;
4480+ s2cKeys->macKeySz = 0;
44274481 }
44284482 }
44294483
@@ -4433,7 +4487,7 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
44334487 listSz = (word32)sizeof(list);
44344488 ret = GetNameList(list, &listSz, buf, len, &begin);
44354489 }
4436- if (ret == WS_SUCCESS && !ssh->handshake->aeadMode ) {
4490+ if (ret == WS_SUCCESS && !*c2sAeadMode ) {
44374491 cannedAlgoNamesSz = AlgoListSz(ssh->algoListMac);
44384492 cannedListSz = (word32)sizeof(cannedList);
44394493 ret = GetNameListRaw(cannedList, &cannedListSz,
@@ -4445,6 +4499,11 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
44454499 WLOG(WS_LOG_DEBUG, "Unable to negotiate MAC Algo C2S");
44464500 ret = WS_MATCH_MAC_ALGO_E;
44474501 }
4502+ else {
4503+ *c2sMacId = algoId;
4504+ *c2sMacSz = MacSzForId(algoId);
4505+ c2sKeys->macKeySz = KeySzForId(algoId);
4506+ }
44484507 }
44494508 }
44504509
@@ -4454,18 +4513,22 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
44544513 listSz = (word32)sizeof(list);
44554514 ret = GetNameList(list, &listSz, buf, len, &begin);
44564515 }
4457- if (ret == WS_SUCCESS && !ssh->handshake->aeadMode) {
4458- algoId = MatchIdLists(side, list, listSz, &algoId, 1);
4459- if (algoId == ID_UNKNOWN) {
4460- WLOG(WS_LOG_DEBUG, "Unable to negotiate MAC Algo S2C");
4461- ret = WS_MATCH_MAC_ALGO_E;
4462- }
4463- else {
4464- ssh->handshake->macId = algoId;
4465- ssh->handshake->macSz = MacSzForId(algoId);
4466- ssh->handshake->keys.macKeySz =
4467- ssh->handshake->peerKeys.macKeySz =
4468- KeySzForId(algoId);
4516+ if (ret == WS_SUCCESS && !*s2cAeadMode) {
4517+ cannedAlgoNamesSz = AlgoListSz(ssh->algoListMac);
4518+ cannedListSz = (word32)sizeof(cannedList);
4519+ ret = GetNameListRaw(cannedList, &cannedListSz,
4520+ (const byte*)ssh->algoListMac, cannedAlgoNamesSz);
4521+ if (ret == WS_SUCCESS) {
4522+ algoId = MatchIdLists(side, list, listSz, cannedList, cannedListSz);
4523+ if (algoId == ID_UNKNOWN) {
4524+ WLOG(WS_LOG_DEBUG, "Unable to negotiate MAC Algo S2C");
4525+ ret = WS_MATCH_MAC_ALGO_E;
4526+ }
4527+ else {
4528+ *s2cMacId = algoId;
4529+ *s2cMacSz = MacSzForId(algoId);
4530+ s2cKeys->macKeySz = KeySzForId(algoId);
4531+ }
44694532 }
44704533 }
44714534
@@ -6207,11 +6270,11 @@ static int DoNewKeys(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
62076270 }
62086271
62096272 if (ret == WS_SUCCESS) {
6210- ssh->peerEncryptId = ssh->handshake->encryptId ;
6211- ssh->peerMacId = ssh->handshake->macId ;
6212- ssh->peerBlockSz = ssh->handshake->blockSz ;
6213- ssh->peerMacSz = ssh->handshake->macSz ;
6214- ssh->peerAeadMode = ssh->handshake->aeadMode ;
6273+ ssh->peerEncryptId = ssh->handshake->peerEncryptId ;
6274+ ssh->peerMacId = ssh->handshake->peerMacId ;
6275+ ssh->peerBlockSz = ssh->handshake->peerBlockSz ;
6276+ ssh->peerMacSz = ssh->handshake->peerMacSz ;
6277+ ssh->peerAeadMode = ssh->handshake->peerAeadMode ;
62156278 WMEMCPY(&ssh->peerKeys, &ssh->handshake->peerKeys, sizeof(Keys));
62166279
62176280 switch (ssh->peerEncryptId) {
@@ -17896,6 +17959,13 @@ int wolfSSH_TestDoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
1789617959 return DoKexInit(ssh, buf, len, idx);
1789717960}
1789817961
17962+ int wolfSSH_TestGenerateKeys(WOLFSSH* ssh)
17963+ {
17964+ if (ssh == NULL || ssh->handshake == NULL)
17965+ return WS_BAD_ARGUMENT;
17966+ return GenerateKeys(ssh, (enum wc_HashType)ssh->handshake->kexHashId, 1);
17967+ }
17968+
1789917969int wolfSSH_TestDoKexDhInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
1790017970{
1790117971 return DoKexDhInit(ssh, buf, len, idx);
0 commit comments