Skip to content

Commit 81a22a2

Browse files
Add independent ciper and MAC algorithms negotiation for each direction, And add regress test
1 parent 7241f4e commit 81a22a2

3 files changed

Lines changed: 365 additions & 53 deletions

File tree

src/internal.c

Lines changed: 119 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
1789917965
int wolfSSH_TestDoKexDhInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
1790017966
{
1790117967
return DoKexDhInit(ssh, buf, len, idx);

0 commit comments

Comments
 (0)