Skip to content

Commit a8a4432

Browse files
yosuke-wolfsslejohnstown
authored andcommitted
Add independent ciper and MAC algorithms negotiation for each direction, And add regress test
1 parent 1843f84 commit a8a4432

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
@@ -2624,7 +2622,7 @@ static int GenerateKeys(WOLFSSH* ssh, byte hashId, byte doKeyPad)
26242622
Keys* sK = NULL;
26252623
int ret = WS_SUCCESS;
26262624

2627-
if (ssh == NULL)
2625+
if (ssh == NULL || ssh->handshake == NULL)
26282626
ret = WS_BAD_ARGUMENT;
26292627
else {
26302628
if (ssh->ctx->side == WOLFSSH_ENDPOINT_SERVER) {
@@ -2657,19 +2655,17 @@ static int GenerateKeys(WOLFSSH* ssh, byte hashId, byte doKeyPad)
26572655
sK->encKey, sK->encKeySz,
26582656
ssh->k, ssh->kSz, ssh->h, ssh->hSz,
26592657
ssh->sessionId, ssh->sessionIdSz, doKeyPad);
2660-
if (ret == WS_SUCCESS) {
2661-
if (!ssh->handshake->aeadMode) {
2662-
ret = GenerateKey(hashId, 'E',
2663-
cK->macKey, cK->macKeySz,
2664-
ssh->k, ssh->kSz, ssh->h, ssh->hSz,
2665-
ssh->sessionId, ssh->sessionIdSz, doKeyPad);
2666-
if (ret == WS_SUCCESS) {
2667-
ret = GenerateKey(hashId, 'F',
2668-
sK->macKey, sK->macKeySz,
2669-
ssh->k, ssh->kSz, ssh->h, ssh->hSz,
2670-
ssh->sessionId, ssh->sessionIdSz, doKeyPad);
2671-
}
2672-
}
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);
26732669
}
26742670

26752671
#ifdef SHOW_SECRETS
@@ -4242,6 +4238,52 @@ static word32 AlgoListSz(const char* algoList)
42424238
}
42434239

42444240

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

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

@@ -4398,6 +4443,10 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
43984443
ret = WS_MATCH_ENC_ALGO_E;
43994444
}
44004445
}
4446+
if (ret == WS_SUCCESS) {
4447+
c2sEncryptId = algoId;
4448+
c2sAeadMode = AeadModeForId(algoId);
4449+
}
44014450

44024451
/* Enc Algorithms - Server to Client */
44034452
if (ret == WS_SUCCESS) {
@@ -4406,32 +4455,21 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
44064455
ret = GetNameList(list, &listSz, buf, len, &begin);
44074456
}
44084457
if (ret == WS_SUCCESS) {
4409-
algoId = MatchIdLists(side, list, listSz, &algoId, 1);
4458+
cannedAlgoNamesSz = AlgoListSz(ssh->algoListCipher);
4459+
cannedListSz = (word32)sizeof(cannedList);
4460+
ret = GetNameListRaw(cannedList, &cannedListSz,
4461+
(const byte*)ssh->algoListCipher, cannedAlgoNamesSz);
4462+
}
4463+
if (ret == WS_SUCCESS) {
4464+
algoId = MatchIdLists(side, list, listSz, cannedList, cannedListSz);
44104465
if (algoId == ID_UNKNOWN) {
44114466
WLOG(WS_LOG_DEBUG, "Unable to negotiate Encryption Algo S2C");
44124467
ret = WS_MATCH_ENC_ALGO_E;
44134468
}
44144469
}
44154470
if (ret == WS_SUCCESS) {
4416-
ssh->handshake->encryptId = algoId;
4417-
ssh->handshake->aeadMode = AeadModeForId(algoId);
4418-
ssh->handshake->blockSz = BlockSzForId(algoId);
4419-
ssh->handshake->keys.encKeySz =
4420-
ssh->handshake->peerKeys.encKeySz =
4421-
KeySzForId(algoId);
4422-
if (!ssh->handshake->aeadMode) {
4423-
ssh->handshake->keys.ivSz =
4424-
ssh->handshake->peerKeys.ivSz =
4425-
ssh->handshake->blockSz;
4426-
}
4427-
else {
4428-
#ifndef WOLFSSH_NO_AEAD
4429-
ssh->handshake->keys.ivSz =
4430-
ssh->handshake->peerKeys.ivSz =
4431-
AEAD_NONCE_SZ;
4432-
ssh->handshake->macSz = ssh->handshake->blockSz;
4433-
#endif
4434-
}
4471+
s2cEncryptId = algoId;
4472+
s2cAeadMode = AeadModeForId(algoId);
44354473
}
44364474

44374475
/* MAC Algorithms - Client to Server */
@@ -4440,7 +4478,7 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
44404478
listSz = (word32)sizeof(list);
44414479
ret = GetNameList(list, &listSz, buf, len, &begin);
44424480
}
4443-
if (ret == WS_SUCCESS && !ssh->handshake->aeadMode) {
4481+
if (ret == WS_SUCCESS && !c2sAeadMode) {
44444482
cannedAlgoNamesSz = AlgoListSz(ssh->algoListMac);
44454483
cannedListSz = (word32)sizeof(cannedList);
44464484
ret = GetNameListRaw(cannedList, &cannedListSz,
@@ -4452,6 +4490,9 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
44524490
WLOG(WS_LOG_DEBUG, "Unable to negotiate MAC Algo C2S");
44534491
ret = WS_MATCH_MAC_ALGO_E;
44544492
}
4493+
else {
4494+
c2sMacId = algoId;
4495+
}
44554496
}
44564497
}
44574498

@@ -4461,18 +4502,20 @@ static int DoKexInit(WOLFSSH* ssh, byte* buf, word32 len, word32* idx)
44614502
listSz = (word32)sizeof(list);
44624503
ret = GetNameList(list, &listSz, buf, len, &begin);
44634504
}
4464-
if (ret == WS_SUCCESS && !ssh->handshake->aeadMode) {
4465-
algoId = MatchIdLists(side, list, listSz, &algoId, 1);
4466-
if (algoId == ID_UNKNOWN) {
4467-
WLOG(WS_LOG_DEBUG, "Unable to negotiate MAC Algo S2C");
4468-
ret = WS_MATCH_MAC_ALGO_E;
4469-
}
4470-
else {
4471-
ssh->handshake->macId = algoId;
4472-
ssh->handshake->macSz = MacSzForId(algoId);
4473-
ssh->handshake->keys.macKeySz =
4474-
ssh->handshake->peerKeys.macKeySz =
4475-
KeySzForId(algoId);
4505+
if (ret == WS_SUCCESS && !s2cAeadMode) {
4506+
cannedAlgoNamesSz = AlgoListSz(ssh->algoListMac);
4507+
cannedListSz = (word32)sizeof(cannedList);
4508+
ret = GetNameListRaw(cannedList, &cannedListSz,
4509+
(const byte*)ssh->algoListMac, cannedAlgoNamesSz);
4510+
if (ret == WS_SUCCESS) {
4511+
algoId = MatchIdLists(side, list, listSz, cannedList, cannedListSz);
4512+
if (algoId == ID_UNKNOWN) {
4513+
WLOG(WS_LOG_DEBUG, "Unable to negotiate MAC Algo S2C");
4514+
ret = WS_MATCH_MAC_ALGO_E;
4515+
}
4516+
else {
4517+
s2cMacId = algoId;
4518+
}
44764519
}
44774520
}
44784521

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

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

62276283
if (ret == WS_SUCCESS) {
6228-
ssh->peerEncryptId = ssh->handshake->encryptId;
6229-
ssh->peerMacId = ssh->handshake->macId;
6230-
ssh->peerBlockSz = ssh->handshake->blockSz;
6231-
ssh->peerMacSz = ssh->handshake->macSz;
6232-
ssh->peerAeadMode = ssh->handshake->aeadMode;
6284+
ssh->peerEncryptId = ssh->handshake->peerEncryptId;
6285+
ssh->peerMacId = ssh->handshake->peerMacId;
6286+
ssh->peerBlockSz = ssh->handshake->peerBlockSz;
6287+
ssh->peerMacSz = ssh->handshake->peerMacSz;
6288+
ssh->peerAeadMode = ssh->handshake->peerAeadMode;
62336289
WMEMCPY(&ssh->peerKeys, &ssh->handshake->peerKeys, sizeof(Keys));
62346290

62356291
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)