Skip to content

Commit c514c19

Browse files
Add independent ciper and MAC algorithms negotiation for each direction, And add regress test
1 parent b610dd7 commit c514c19

3 files changed

Lines changed: 569 additions & 53 deletions

File tree

src/internal.c

Lines changed: 123 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,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+
1789917969
int wolfSSH_TestDoKexDhInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
1790017970
{
1790117971
return DoKexDhInit(ssh, buf, len, idx);

0 commit comments

Comments
 (0)