|
|
@ -256,29 +256,40 @@ namespace garlic |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
uint16_t keyID = bufbe16toh (buf); buf += 2; // keyID
|
|
|
|
uint16_t keyID = bufbe16toh (buf); buf += 2; // keyID
|
|
|
|
if (flag & ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG) |
|
|
|
bool newKey = flag & ECIESX25519_NEXT_KEY_REQUEST_REVERSE_KEY_FLAG; |
|
|
|
|
|
|
|
m_SendReverseKey = true; |
|
|
|
|
|
|
|
if (!m_NextReceiveRatchet) |
|
|
|
|
|
|
|
m_NextReceiveRatchet.reset (new DHRatchet ()); |
|
|
|
|
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
m_IsReverseKeyRequested = true; |
|
|
|
if (keyID == m_NextReceiveRatchet->keyID && newKey == m_NextReceiveRatchet->newKey) |
|
|
|
if (!m_NextReceiveKey) |
|
|
|
|
|
|
|
m_NextReceiveKey.reset (new i2p::crypto::X25519Keys ()); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
if (keyID == m_ReceiveKeyID) return; |
|
|
|
LogPrint (eLogDebug, "Garlic: Duplicate ", newKey ? "new" : "old", " key ", keyID, " received"); |
|
|
|
else m_ReceiveKeyID++; // TODO
|
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
m_NextReceiveKey->GenerateKeys (); |
|
|
|
m_NextReceiveRatchet->keyID = keyID; |
|
|
|
uint8_t sharedSecret[32], tagsetKey[32]; |
|
|
|
} |
|
|
|
m_NextReceiveKey->Agree (buf, sharedSecret); |
|
|
|
int tagsetID = 2*keyID; |
|
|
|
i2p::crypto::HKDF (sharedSecret, nullptr, 0, "XDHRatchetTagSet", tagsetKey, 32); // tagsetKey = HKDF(sharedSecret, ZEROLEN, "XDHRatchetTagSet", 32)
|
|
|
|
if (newKey) |
|
|
|
auto newTagset = std::make_shared<RatchetTagSet>(shared_from_this ()); |
|
|
|
{ |
|
|
|
newTagset->SetTagSetID (1 + keyID + m_ReceiveKeyID); |
|
|
|
m_NextReceiveRatchet->key.GenerateKeys (); |
|
|
|
newTagset->DHInitialize (receiveTagset->GetNextRootKey (), tagsetKey); |
|
|
|
m_NextReceiveRatchet->newKey = true; |
|
|
|
newTagset->NextSessionTagRatchet (); |
|
|
|
tagsetID++; |
|
|
|
GenerateMoreReceiveTags (newTagset, GetOwner ()->GetNumTags ()); |
|
|
|
|
|
|
|
LogPrint (eLogDebug, "Garlic: next receive tagset ", newTagset->GetTagSetID (), " created"); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
LogPrint (eLogWarning, "Garlic: Missing next key"); |
|
|
|
m_NextReceiveRatchet->newKey = false; |
|
|
|
|
|
|
|
if (flag & ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG) |
|
|
|
|
|
|
|
memcpy (m_NextReceiveRatchet->remote, buf, 32); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t sharedSecret[32], tagsetKey[32]; |
|
|
|
|
|
|
|
m_NextReceiveRatchet->key.Agree (m_NextReceiveRatchet->remote, sharedSecret); |
|
|
|
|
|
|
|
i2p::crypto::HKDF (sharedSecret, nullptr, 0, "XDHRatchetTagSet", tagsetKey, 32); // tagsetKey = HKDF(sharedSecret, ZEROLEN, "XDHRatchetTagSet", 32)
|
|
|
|
|
|
|
|
auto newTagset = std::make_shared<RatchetTagSet>(shared_from_this ()); |
|
|
|
|
|
|
|
newTagset->SetTagSetID (tagsetID); |
|
|
|
|
|
|
|
newTagset->DHInitialize (receiveTagset->GetNextRootKey (), tagsetKey); |
|
|
|
|
|
|
|
newTagset->NextSessionTagRatchet (); |
|
|
|
|
|
|
|
GenerateMoreReceiveTags (newTagset, GetOwner ()->GetNumTags ()); |
|
|
|
|
|
|
|
LogPrint (eLogDebug, "Garlic: next receive tagset ", tagsetID, " created"); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -585,8 +596,11 @@ namespace garlic |
|
|
|
} |
|
|
|
} |
|
|
|
if (m_AckRequests.size () > 0) |
|
|
|
if (m_AckRequests.size () > 0) |
|
|
|
payloadLen += m_AckRequests.size ()*4 + 3; |
|
|
|
payloadLen += m_AckRequests.size ()*4 + 3; |
|
|
|
if (m_IsReverseKeyRequested) |
|
|
|
if (m_SendReverseKey) |
|
|
|
payloadLen += 3 + 35; |
|
|
|
{ |
|
|
|
|
|
|
|
payloadLen += 6; |
|
|
|
|
|
|
|
if (m_NextReceiveRatchet->newKey) payloadLen += 32; |
|
|
|
|
|
|
|
} |
|
|
|
uint8_t paddingSize; |
|
|
|
uint8_t paddingSize; |
|
|
|
RAND_bytes (&paddingSize, 1); |
|
|
|
RAND_bytes (&paddingSize, 1); |
|
|
|
paddingSize &= 0x0F; paddingSize++; // 1 - 16
|
|
|
|
paddingSize &= 0x0F; paddingSize++; // 1 - 16
|
|
|
@ -628,14 +642,25 @@ namespace garlic |
|
|
|
m_AckRequests.clear (); |
|
|
|
m_AckRequests.clear (); |
|
|
|
} |
|
|
|
} |
|
|
|
// next keys
|
|
|
|
// next keys
|
|
|
|
if (m_IsReverseKeyRequested) |
|
|
|
if (m_SendReverseKey) |
|
|
|
{ |
|
|
|
{ |
|
|
|
v[offset] = eECIESx25519BlkNextKey; offset++; |
|
|
|
v[offset] = eECIESx25519BlkNextKey; offset++; |
|
|
|
htobe16buf (v.data () + offset, 35); offset += 2; |
|
|
|
htobe16buf (v.data () + offset, m_NextReceiveRatchet->newKey ? 35 : 3); offset += 2; |
|
|
|
v[offset] = ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG | ECIESX25519_NEXT_KEY_REVERSE_KEY_FLAG; offset++; // flag
|
|
|
|
v[offset] = ECIESX25519_NEXT_KEY_REVERSE_KEY_FLAG; |
|
|
|
htobe16buf (v.data () + offset, m_ReceiveKeyID); offset += 2; // keyid
|
|
|
|
int keyID = m_NextReceiveRatchet->keyID - 1; |
|
|
|
memcpy (v.data () + offset, m_NextReceiveKey->GetPublicKey (), 32); offset += 32; // public key
|
|
|
|
if (m_NextReceiveRatchet->newKey) |
|
|
|
m_IsReverseKeyRequested = false; |
|
|
|
{ |
|
|
|
|
|
|
|
v[offset] |= ECIESX25519_NEXT_KEY_KEY_PRESENT_FLAG; |
|
|
|
|
|
|
|
keyID++; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
offset++; // flag
|
|
|
|
|
|
|
|
htobe16buf (v.data () + offset, keyID); offset += 2; // keyid
|
|
|
|
|
|
|
|
if (m_NextReceiveRatchet->newKey) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
memcpy (v.data () + offset, m_NextReceiveRatchet->key.GetPublicKey (), 32); |
|
|
|
|
|
|
|
offset += 32; // public key
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
m_SendReverseKey = false; |
|
|
|
} |
|
|
|
} |
|
|
|
// padding
|
|
|
|
// padding
|
|
|
|
v[offset] = eECIESx25519BlkPadding; offset++; |
|
|
|
v[offset] = eECIESx25519BlkPadding; offset++; |
|
|
|