Skip to content

Commit b76a03d

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

3 files changed

Lines changed: 1158 additions & 57 deletions

File tree

src/internal.c

Lines changed: 132 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -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
@@ -4243,6 +4239,52 @@ static word32 AlgoListSz(const char* algoList)
42434239
}
42444240

42454241

4242+
static void SetLocalAlgoIds(HandshakeInfo* hs,
4243+
byte encId, byte aeadMode, byte macId)
4244+
{
4245+
byte blkSz = BlockSzForId(encId);
4246+
hs->encryptId = encId;
4247+
hs->aeadMode = aeadMode;
4248+
hs->blockSz = blkSz;
4249+
hs->keys.encKeySz = KeySzForId(encId);
4250+
if (!aeadMode) {
4251+
hs->keys.ivSz = blkSz;
4252+
hs->macId = macId;
4253+
hs->macSz = MacSzForId(macId);
4254+
hs->keys.macKeySz = KeySzForId(macId);
4255+
}
4256+
else {
4257+
hs->keys.ivSz = AEAD_NONCE_SZ;
4258+
hs->macId = ID_NONE;
4259+
hs->macSz = blkSz;
4260+
hs->keys.macKeySz = 0;
4261+
}
4262+
}
4263+
4264+
4265+
static void SetPeerAlgoIds(HandshakeInfo* hs,
4266+
byte encId, byte aeadMode, byte macId)
4267+
{
4268+
byte blkSz = BlockSzForId(encId);
4269+
hs->peerEncryptId = encId;
4270+
hs->peerAeadMode = aeadMode;
4271+
hs->peerBlockSz = blkSz;
4272+
hs->peerKeys.encKeySz = KeySzForId(encId);
4273+
if (!aeadMode) {
4274+
hs->peerKeys.ivSz = blkSz;
4275+
hs->peerMacId = macId;
4276+
hs->peerMacSz = MacSzForId(macId);
4277+
hs->peerKeys.macKeySz = KeySzForId(macId);
4278+
}
4279+
else {
4280+
hs->peerKeys.ivSz = AEAD_NONCE_SZ;
4281+
hs->peerMacId = ID_NONE;
4282+
hs->peerMacSz = blkSz;
4283+
hs->peerKeys.macKeySz = 0;
4284+
}
4285+
}
4286+
4287+
42464288
static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
42474289
{
42484290
int ret = WS_SUCCESS;
@@ -4258,6 +4300,9 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
42584300
word32 cannedAlgoNamesSz;
42594301
word32 skipSz = 0;
42604302
word32 begin;
4303+
byte c2sEncryptId = ID_NONE, s2cEncryptId = ID_NONE;
4304+
byte c2sMacId = ID_NONE, s2cMacId = ID_NONE;
4305+
byte c2sAeadMode = 0, s2cAeadMode = 0;
42614306

42624307
WLOG(WS_LOG_DEBUG, "Entering DoKexInit()");
42634308

@@ -4399,6 +4444,10 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
43994444
ret = WS_MATCH_ENC_ALGO_E;
44004445
}
44014446
}
4447+
if (ret == WS_SUCCESS) {
4448+
c2sEncryptId = algoId;
4449+
c2sAeadMode = AeadModeForId(algoId);
4450+
}
44024451

44034452
/* Enc Algorithms - Server to Client */
44044453
if (ret == WS_SUCCESS) {
@@ -4407,32 +4456,21 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
44074456
ret = GetNameList(list, &listSz, buf, len, &begin);
44084457
}
44094458
if (ret == WS_SUCCESS) {
4410-
algoId = MatchIdLists(side, list, listSz, &algoId, 1);
4459+
cannedAlgoNamesSz = AlgoListSz(ssh->algoListCipher);
4460+
cannedListSz = (word32)sizeof(cannedList);
4461+
ret = GetNameListRaw(cannedList, &cannedListSz,
4462+
(const byte*)ssh->algoListCipher, cannedAlgoNamesSz);
4463+
}
4464+
if (ret == WS_SUCCESS) {
4465+
algoId = MatchIdLists(side, list, listSz, cannedList, cannedListSz);
44114466
if (algoId == ID_UNKNOWN) {
44124467
WLOG(WS_LOG_DEBUG, "Unable to negotiate Encryption Algo S2C");
44134468
ret = WS_MATCH_ENC_ALGO_E;
44144469
}
44154470
}
44164471
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;
4427-
}
4428-
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
4435-
}
4472+
s2cEncryptId = algoId;
4473+
s2cAeadMode = AeadModeForId(algoId);
44364474
}
44374475

44384476
/* MAC Algorithms - Client to Server */
@@ -4441,7 +4479,7 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
44414479
listSz = (word32)sizeof(list);
44424480
ret = GetNameList(list, &listSz, buf, len, &begin);
44434481
}
4444-
if (ret == WS_SUCCESS && !ssh->handshake->aeadMode) {
4482+
if (ret == WS_SUCCESS && !c2sAeadMode) {
44454483
cannedAlgoNamesSz = AlgoListSz(ssh->algoListMac);
44464484
cannedListSz = (word32)sizeof(cannedList);
44474485
ret = GetNameListRaw(cannedList, &cannedListSz,
@@ -4453,6 +4491,9 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
44534491
WLOG(WS_LOG_DEBUG, "Unable to negotiate MAC Algo C2S");
44544492
ret = WS_MATCH_MAC_ALGO_E;
44554493
}
4494+
else {
4495+
c2sMacId = algoId;
4496+
}
44564497
}
44574498
}
44584499

@@ -4462,18 +4503,20 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
44624503
listSz = (word32)sizeof(list);
44634504
ret = GetNameList(list, &listSz, buf, len, &begin);
44644505
}
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);
4506+
if (ret == WS_SUCCESS && !s2cAeadMode) {
4507+
cannedAlgoNamesSz = AlgoListSz(ssh->algoListMac);
4508+
cannedListSz = (word32)sizeof(cannedList);
4509+
ret = GetNameListRaw(cannedList, &cannedListSz,
4510+
(const byte*)ssh->algoListMac, cannedAlgoNamesSz);
4511+
if (ret == WS_SUCCESS) {
4512+
algoId = MatchIdLists(side, list, listSz, cannedList, cannedListSz);
4513+
if (algoId == ID_UNKNOWN) {
4514+
WLOG(WS_LOG_DEBUG, "Unable to negotiate MAC Algo S2C");
4515+
ret = WS_MATCH_MAC_ALGO_E;
4516+
}
4517+
else {
4518+
s2cMacId = algoId;
4519+
}
44774520
}
44784521
}
44794522

@@ -4547,6 +4590,19 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
45474590
begin += skipSz;
45484591
}
45494592

4593+
if (ret == WS_SUCCESS) {
4594+
if (ssh->ctx->side == WOLFSSH_ENDPOINT_SERVER) {
4595+
/* s2c = local (server outgoing), c2s = peer (client incoming) */
4596+
SetLocalAlgoIds(ssh->handshake, s2cEncryptId, s2cAeadMode, s2cMacId);
4597+
SetPeerAlgoIds (ssh->handshake, c2sEncryptId, c2sAeadMode, c2sMacId);
4598+
}
4599+
else {
4600+
/* c2s = local (client outgoing), s2c = peer (server incoming) */
4601+
SetLocalAlgoIds(ssh->handshake, c2sEncryptId, c2sAeadMode, c2sMacId);
4602+
SetPeerAlgoIds (ssh->handshake, s2cEncryptId, s2cAeadMode, s2cMacId);
4603+
}
4604+
}
4605+
45504606
if (ret == WS_SUCCESS) {
45514607
wc_HashAlg* hash = &ssh->handshake->kexHash;
45524608
enum wc_HashType hashId = (enum wc_HashType)ssh->handshake->kexHashId;
@@ -6226,11 +6282,11 @@ static int DoNewKeys(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
62266282
}
62276283

62286284
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;
6285+
ssh->peerEncryptId = ssh->handshake->peerEncryptId;
6286+
ssh->peerMacId = ssh->handshake->peerMacId;
6287+
ssh->peerBlockSz = ssh->handshake->peerBlockSz;
6288+
ssh->peerMacSz = ssh->handshake->peerMacSz;
6289+
ssh->peerAeadMode = ssh->handshake->peerAeadMode;
62346290
WMEMCPY(&ssh->peerKeys, &ssh->handshake->peerKeys, sizeof(Keys));
62356291

62366292
switch (ssh->peerEncryptId) {
@@ -17959,6 +18015,25 @@ int wolfSSH_TestDoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
1795918015
return DoKexInit(ssh, buf, len, idx);
1796018016
}
1796118017

18018+
int wolfSSH_TestDoNewKeys(WOLFSSH* ssh)
18019+
{
18020+
/* DoNewKeys ignores buf/len/idx (marked WOLFSSH_UNUSED internally). */
18021+
return DoNewKeys(ssh, NULL, 0, NULL);
18022+
}
18023+
18024+
void wolfSSH_TestFreeHandshake(WOLFSSH* ssh)
18025+
{
18026+
if (ssh != NULL) {
18027+
HandshakeInfoFree(ssh->handshake, ssh->ctx ? ssh->ctx->heap : NULL);
18028+
ssh->handshake = NULL;
18029+
}
18030+
}
18031+
18032+
int wolfSSH_TestGenerateKeys(WOLFSSH* ssh, byte hashId)
18033+
{
18034+
return GenerateKeys(ssh, hashId, 1);
18035+
}
18036+
1796218037
int wolfSSH_TestDoKexDhInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
1796318038
{
1796418039
return DoKexDhInit(ssh, buf, len, idx);

0 commit comments

Comments
 (0)