Add tests for identity marshal/unmarshal and fix an issue found.

This commit is contained in:
Adam Ierymenko 2020-02-27 15:40:31 -08:00
parent ed8271530f
commit 6262374205
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
4 changed files with 49 additions and 25 deletions

View file

@ -17,6 +17,8 @@
#include "Constants.hpp"
#include "TriviallyCopyable.hpp"
#include <algorithm>
namespace ZeroTier {
/**
@ -62,12 +64,12 @@ public:
return false;
}
ZT_ALWAYS_INLINE bool operator==(const Fingerprint &h) const noexcept { return memcmp(_h,h._h,48) == 0; }
ZT_ALWAYS_INLINE bool operator!=(const Fingerprint &h) const noexcept { return memcmp(_h,h._h,48) != 0; }
ZT_ALWAYS_INLINE bool operator<(const Fingerprint &h) const noexcept { return memcmp(_h,h._h,48) < 0; }
ZT_ALWAYS_INLINE bool operator>(const Fingerprint &h) const noexcept { return memcmp(_h,h._h,48) > 0; }
ZT_ALWAYS_INLINE bool operator<=(const Fingerprint &h) const noexcept { return memcmp(_h,h._h,48) <= 0; }
ZT_ALWAYS_INLINE bool operator>=(const Fingerprint &h) const noexcept { return memcmp(_h,h._h,48) >= 0; }
ZT_ALWAYS_INLINE bool operator==(const Fingerprint &h) const noexcept { return std::equal(_h,_h + (384 / (sizeof(unsigned long) * 8)),h._h); }
ZT_ALWAYS_INLINE bool operator!=(const Fingerprint &h) const noexcept { return !(*this == h); }
ZT_ALWAYS_INLINE bool operator<(const Fingerprint &h) const noexcept { return std::lexicographical_compare(_h,_h + (384 / (sizeof(unsigned long) * 8)),h._h,h._h + (384 / (sizeof(unsigned long) * 8))); }
ZT_ALWAYS_INLINE bool operator>(const Fingerprint &h) const noexcept { return (h < *this); }
ZT_ALWAYS_INLINE bool operator<=(const Fingerprint &h) const noexcept { return !(h < *this); }
ZT_ALWAYS_INLINE bool operator>=(const Fingerprint &h) const noexcept { return !(*this < h); }
private:
unsigned long _h[384 / (sizeof(unsigned long) * 8)];

View file

@ -414,9 +414,7 @@ int Identity::marshal(uint8_t data[ZT_IDENTITY_MARSHAL_SIZE_MAX],const bool incl
switch(_type) {
case C25519:
data[ZT_ADDRESS_LENGTH] = (uint8_t)C25519;
memcpy(data + ZT_ADDRESS_LENGTH + 1,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
if ((includePrivate)&&(_hasPrivate)) {
data[ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN] = ZT_C25519_PRIVATE_KEY_LEN;
memcpy(data + ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1,_priv.c25519,ZT_C25519_PRIVATE_KEY_LEN);
@ -428,9 +426,7 @@ int Identity::marshal(uint8_t data[ZT_IDENTITY_MARSHAL_SIZE_MAX],const bool incl
case P384:
data[ZT_ADDRESS_LENGTH] = (uint8_t)P384;
memcpy(data + ZT_ADDRESS_LENGTH + 1,&_pub,ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE);
if ((includePrivate)&&(_hasPrivate)) {
data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE] = ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE;
memcpy(data + ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1,&_priv,ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE);
@ -451,6 +447,7 @@ int Identity::unmarshal(const uint8_t *data,const int len) noexcept
if (len < (ZT_ADDRESS_LENGTH + 1))
return -1;
_address.setTo(data);
unsigned int privlen;
switch((_type = (Type)data[ZT_ADDRESS_LENGTH])) {
@ -460,21 +457,17 @@ int Identity::unmarshal(const uint8_t *data,const int len) noexcept
return -1;
memcpy(_pub.c25519,data + ZT_ADDRESS_LENGTH + 1,ZT_C25519_PUBLIC_KEY_LEN);
_computeHash();
privlen = data[ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN];
if (privlen == ZT_C25519_PRIVATE_KEY_LEN) {
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1 + ZT_C25519_PRIVATE_KEY_LEN))
return -1;
_hasPrivate = true;
memcpy(_priv.c25519,data + ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1,ZT_C25519_PRIVATE_KEY_LEN);
_computeHash();
return ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1 + ZT_C25519_PRIVATE_KEY_LEN;
} else if (privlen == 0) {
_hasPrivate = false;
_computeHash();
return ZT_ADDRESS_LENGTH + 1 + ZT_C25519_PUBLIC_KEY_LEN + 1;
}
break;
@ -484,21 +477,19 @@ int Identity::unmarshal(const uint8_t *data,const int len) noexcept
return -1;
memcpy(&_pub,data + ZT_ADDRESS_LENGTH + 1,ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE);
_computeHash();
if (_address != Address(_fp.data())) // for v1 we can sanity check this here, but this isn't a full validate
return -1;
privlen = data[ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE];
if (privlen == ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE) {
if (len < (ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE))
return -1;
_hasPrivate = true;
memcpy(&_priv,data + ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1,ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE);
_computeHash();
return ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1 + ZT_IDENTITY_P384_COMPOUND_PRIVATE_KEY_SIZE;
} else if (privlen == 0) {
_hasPrivate = false;
_computeHash();
return ZT_ADDRESS_LENGTH + 1 + ZT_IDENTITY_P384_COMPOUND_PUBLIC_KEY_SIZE + 1;
}
break;

View file

@ -203,10 +203,7 @@ public:
ZT_ALWAYS_INLINE unsigned long hashCode() const noexcept { return _fp.hashCode(); }
ZT_ALWAYS_INLINE bool operator==(const Identity &id) const noexcept
{
return ((_address == id._address)&&(_type == id._type)&&(memcmp(_fp.data(),id._fp.data(),ZT_SHA384_DIGEST_LEN) == 0));
}
ZT_ALWAYS_INLINE bool operator==(const Identity &id) const noexcept { return ((_address == id._address)&&(_fp == id._fp)); }
ZT_ALWAYS_INLINE bool operator!=(const Identity &id) const noexcept { return !(*this == id); }
ZT_ALWAYS_INLINE bool operator<(const Identity &id) const noexcept
{
@ -216,7 +213,7 @@ public:
if ((int)_type < (int)id._type)
return true;
if (_type == id._type)
return memcmp(_fp.data(),id._fp.data(),ZT_SHA384_DIGEST_LEN) < 0;
return _fp < id._fp;
}
return false;
}

View file

@ -590,6 +590,24 @@ extern "C" const char *ZTT_general()
ZT_T_PRINTF("FAILED (validation of known-good identity failed)" ZT_EOL_S);
return "Identity test failed: validation of known-good identity";
}
uint8_t idm[ZT_IDENTITY_MARSHAL_SIZE_MAX];
int ms = id.marshal(idm,true);
if (ms <= 0) {
ZT_T_PRINTF("FAILED (v0 marshal)" ZT_EOL_S);
return "Identity test failed: v0 marshal";
}
ZT_T_PRINTF("(marshal: %d bytes) ",ms);
Identity id2;
if (id2.unmarshal(idm,ms) <= 0) {
ZT_T_PRINTF("FAILED (v0 unmarshal)" ZT_EOL_S);
return "Identity test failed: v0 unmarshal";
}
if (id != id2) {
ZT_T_PRINTF("FAILED (v0 unmarshal !=)" ZT_EOL_S);
return "Identity test failed: v0 unmarshal !=";
}
if (!id.fromString(IDENTITY_V0_KNOWN_BAD_0)) {
ZT_T_PRINTF("FAILED (error parsing test identity #2)" ZT_EOL_S);
return "Identity test failed: parse error";
@ -614,6 +632,22 @@ extern "C" const char *ZTT_general()
ZT_T_PRINTF("FAILED (validation of known-good identity failed)" ZT_EOL_S);
return "Identity test failed: validation of known-good identity";
}
ms = id.marshal(idm,true);
if (ms <= 0) {
ZT_T_PRINTF("FAILED (v1 marshal)" ZT_EOL_S);
return "Identity test failed: v1 marshal";
}
ZT_T_PRINTF("(marshal: %d bytes) ",ms);
if (id2.unmarshal(idm,ms) <= 0) {
ZT_T_PRINTF("FAILED (v1 unmarshal)" ZT_EOL_S);
return "Identity test failed: v1 unmarshal";
}
if (id != id2) {
ZT_T_PRINTF("FAILED (v1 unmarshal !=)" ZT_EOL_S);
return "Identity test failed: v1 unmarshal !=";
}
if (!id.fromString(IDENTITY_V1_KNOWN_BAD_0)) {
ZT_T_PRINTF("FAILED (error parsing test identity #2)" ZT_EOL_S);
return "Identity test failed: parse error";