@@ -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,16 @@ 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, *c2sAeadMode, *c2sBlockSz, *c2sMacId, *c2sMacSz;
4254+ Keys *c2sKeys;
4255+ byte *s2cEncryptId, *s2cAeadMode, *s2cBlockSz, *s2cMacId, *s2cMacSz;
4256+ Keys *s2cKeys;
42534257
42544258 WLOG(WS_LOG_DEBUG, "Entering DoKexInit()");
42554259
@@ -4292,6 +4296,35 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
42924296 begin = *idx;
42934297 side = ssh->ctx->side;
42944298
4299+ if (side == WOLFSSH_ENDPOINT_SERVER) {
4300+ c2sEncryptId = &ssh->handshake->peerEncryptId;
4301+ c2sAeadMode = &ssh->handshake->peerAeadMode;
4302+ c2sBlockSz = &ssh->handshake->peerBlockSz;
4303+ c2sMacId = &ssh->handshake->peerMacId;
4304+ c2sMacSz = &ssh->handshake->peerMacSz;
4305+ c2sKeys = &ssh->handshake->peerKeys;
4306+ s2cEncryptId = &ssh->handshake->encryptId;
4307+ s2cAeadMode = &ssh->handshake->aeadMode;
4308+ s2cBlockSz = &ssh->handshake->blockSz;
4309+ s2cMacId = &ssh->handshake->macId;
4310+ s2cMacSz = &ssh->handshake->macSz;
4311+ s2cKeys = &ssh->handshake->keys;
4312+ }
4313+ else {
4314+ c2sEncryptId = &ssh->handshake->encryptId;
4315+ c2sAeadMode = &ssh->handshake->aeadMode;
4316+ c2sBlockSz = &ssh->handshake->blockSz;
4317+ c2sMacId = &ssh->handshake->macId;
4318+ c2sMacSz = &ssh->handshake->macSz;
4319+ c2sKeys = &ssh->handshake->keys;
4320+ s2cEncryptId = &ssh->handshake->peerEncryptId;
4321+ s2cAeadMode = &ssh->handshake->peerAeadMode;
4322+ s2cBlockSz = &ssh->handshake->peerBlockSz;
4323+ s2cMacId = &ssh->handshake->peerMacId;
4324+ s2cMacSz = &ssh->handshake->peerMacSz;
4325+ s2cKeys = &ssh->handshake->peerKeys;
4326+ }
4327+
42954328 /* Check that the cookie exists inside the message */
42964329 if (begin + COOKIE_SZ > len) {
42974330 /* error, out of bounds */
@@ -4391,6 +4424,24 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
43914424 ret = WS_MATCH_ENC_ALGO_E;
43924425 }
43934426 }
4427+ if (ret == WS_SUCCESS) {
4428+ *c2sEncryptId = algoId;
4429+ *c2sAeadMode = AeadModeForId(algoId);
4430+ *c2sBlockSz = BlockSzForId(algoId);
4431+ c2sKeys->encKeySz = KeySzForId(algoId);
4432+ if (!*c2sAeadMode) {
4433+ c2sKeys->ivSz = *c2sBlockSz;
4434+ }
4435+ else {
4436+ /* Reaching here requires an AEAD cipher ID, which requires
4437+ * WOLFSSH_NO_AES_GCM to be unset, hence WOLFSSH_NO_AEAD unset
4438+ * (see internal.h). */
4439+ c2sKeys->ivSz = AEAD_NONCE_SZ;
4440+ *c2sMacSz = *c2sBlockSz;
4441+ *c2sMacId = ID_NONE;
4442+ c2sKeys->macKeySz = 0;
4443+ }
4444+ }
43944445
43954446 /* Enc Algorithms - Server to Client */
43964447 if (ret == WS_SUCCESS) {
@@ -4399,31 +4450,30 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
43994450 ret = GetNameList(list, &listSz, buf, len, &begin);
44004451 }
44014452 if (ret == WS_SUCCESS) {
4402- algoId = MatchIdLists(side, list, listSz, &algoId, 1);
4453+ cannedAlgoNamesSz = AlgoListSz(ssh->algoListCipher);
4454+ cannedListSz = (word32)sizeof(cannedList);
4455+ ret = GetNameListRaw(cannedList, &cannedListSz,
4456+ (const byte*)ssh->algoListCipher, cannedAlgoNamesSz);
4457+ }
4458+ if (ret == WS_SUCCESS) {
4459+ algoId = MatchIdLists(side, list, listSz, cannedList, cannedListSz);
44034460 if (algoId == ID_UNKNOWN) {
44044461 WLOG(WS_LOG_DEBUG, "Unable to negotiate Encryption Algo S2C");
44054462 ret = WS_MATCH_ENC_ALGO_E;
44064463 }
44074464 }
44084465 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;
4466+ *s2cEncryptId = algoId;
4467+ *s2cAeadMode = AeadModeForId(algoId);
4468+ *s2cBlockSz = BlockSzForId(algoId);
4469+ s2cKeys->encKeySz = KeySzForId(algoId);
4470+ if (!*s2cAeadMode) {
4471+ s2cKeys->ivSz = *s2cBlockSz;
44194472 }
44204473 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
4474+ /* Same invariant as C2S: AEAD cipher ID implies !WOLFSSH_NO_AEAD. */
4475+ s2cKeys->ivSz = AEAD_NONCE_SZ;
4476+ *s2cMacSz = *s2cBlockSz;
44274477 }
44284478 }
44294479
@@ -4433,7 +4483,7 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
44334483 listSz = (word32)sizeof(list);
44344484 ret = GetNameList(list, &listSz, buf, len, &begin);
44354485 }
4436- if (ret == WS_SUCCESS && !ssh->handshake->aeadMode ) {
4486+ if (ret == WS_SUCCESS && !*c2sAeadMode ) {
44374487 cannedAlgoNamesSz = AlgoListSz(ssh->algoListMac);
44384488 cannedListSz = (word32)sizeof(cannedList);
44394489 ret = GetNameListRaw(cannedList, &cannedListSz,
@@ -4445,6 +4495,11 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
44454495 WLOG(WS_LOG_DEBUG, "Unable to negotiate MAC Algo C2S");
44464496 ret = WS_MATCH_MAC_ALGO_E;
44474497 }
4498+ else {
4499+ *c2sMacId = algoId;
4500+ *c2sMacSz = MacSzForId(algoId);
4501+ c2sKeys->macKeySz = KeySzForId(algoId);
4502+ }
44484503 }
44494504 }
44504505
@@ -4454,18 +4509,22 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
44544509 listSz = (word32)sizeof(list);
44554510 ret = GetNameList(list, &listSz, buf, len, &begin);
44564511 }
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);
4512+ if (ret == WS_SUCCESS && !*s2cAeadMode) {
4513+ cannedAlgoNamesSz = AlgoListSz(ssh->algoListMac);
4514+ cannedListSz = (word32)sizeof(cannedList);
4515+ ret = GetNameListRaw(cannedList, &cannedListSz,
4516+ (const byte*)ssh->algoListMac, cannedAlgoNamesSz);
4517+ if (ret == WS_SUCCESS) {
4518+ algoId = MatchIdLists(side, list, listSz, cannedList, cannedListSz);
4519+ if (algoId == ID_UNKNOWN) {
4520+ WLOG(WS_LOG_DEBUG, "Unable to negotiate MAC Algo S2C");
4521+ ret = WS_MATCH_MAC_ALGO_E;
4522+ }
4523+ else {
4524+ *s2cMacId = algoId;
4525+ *s2cMacSz = MacSzForId(algoId);
4526+ s2cKeys->macKeySz = KeySzForId(algoId);
4527+ }
44694528 }
44704529 }
44714530
@@ -6207,11 +6266,11 @@ static int DoNewKeys(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
62076266 }
62086267
62096268 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 ;
6269+ ssh->peerEncryptId = ssh->handshake->peerEncryptId ;
6270+ ssh->peerMacId = ssh->handshake->peerMacId ;
6271+ ssh->peerBlockSz = ssh->handshake->peerBlockSz ;
6272+ ssh->peerMacSz = ssh->handshake->peerMacSz ;
6273+ ssh->peerAeadMode = ssh->handshake->peerAeadMode ;
62156274 WMEMCPY(&ssh->peerKeys, &ssh->handshake->peerKeys, sizeof(Keys));
62166275
62176276 switch (ssh->peerEncryptId) {
@@ -17896,6 +17955,13 @@ int wolfSSH_TestDoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
1789617955 return DoKexInit(ssh, buf, len, idx);
1789717956}
1789817957
17958+ int wolfSSH_TestGenerateKeys(WOLFSSH* ssh)
17959+ {
17960+ if (ssh == NULL || ssh->handshake == NULL)
17961+ return WS_BAD_ARGUMENT;
17962+ return GenerateKeys(ssh, (enum wc_HashType)ssh->handshake->kexHashId, 1);
17963+ }
17964+
1789917965int wolfSSH_TestDoKexDhInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
1790017966{
1790117967 return DoKexDhInit(ssh, buf, len, idx);
0 commit comments