Skip to content

Commit

Permalink
Better error handling for invalid public keys and signatures (dashpay#41
Browse files Browse the repository at this point in the history
)

* Throw error when ep_upk/ep2_upk fail

* Reset error code before throwing C++ exception

Otherwise it will keep throwing on the next CheckRelicErrors call.

* Call CheckRelicErrors after trying to read public keys or signatures

Before this, invalid public keys and signatures were silently ignored.

* Add test cases for error handling

Also move "Should throw on a bad private key" into new test case
  • Loading branch information
codablock authored and mariano54 committed Oct 30, 2018
1 parent f37e5bb commit 0739569
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 15 deletions.
4 changes: 3 additions & 1 deletion contrib/relic/src/ep/relic_ep_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,9 @@ void ep_read_bin(ep_t a, const uint8_t *bin, int len) {
THROW(ERR_NO_VALID);
break;
}
ep_upk(a, a);
if (!ep_upk(a, a)) {
THROW(ERR_NO_VALID);
}
}

if (len == 2 * FP_BYTES + 1) {
Expand Down
4 changes: 3 additions & 1 deletion contrib/relic/src/epx/relic_ep2_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,9 @@ void ep2_read_bin(ep2_t a, uint8_t *bin, int len) {
THROW(ERR_NO_VALID);
break;
}
ep2_upk(a, a);
if (!ep2_upk(a, a)) {
THROW(ERR_NO_VALID);
}
}

if (len == 4 * FP_BYTES + 1) {
Expand Down
1 change: 1 addition & 0 deletions src/bls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ void BLS::CheckRelicErrors() {
throw std::string("Library not initialized properly. Call BLS::Init()");
}
if (core_get()->code != STS_OK) {
core_get()->code = STS_OK;
throw std::string("Relic library error");
}
}
Expand Down
1 change: 1 addition & 0 deletions src/publickey.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ PublicKey PublicKey::FromBytes(const uint8_t * key) {
uncompressed[0] = 0x02; // Insert extra byte for Y=0
}
g1_read_bin(pk.q, uncompressed, PUBLIC_KEY_SIZE + 1);
BLS::CheckRelicErrors();
return pk;
}

Expand Down
1 change: 1 addition & 0 deletions src/signature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ InsecureSignature InsecureSignature::FromBytes(const uint8_t *data) {
uncompressed[0] = 0x02; // Insert extra byte for Y=0
}
g2_read_bin(sigObj.sig, uncompressed, SIGNATURE_SIZE + 1);
BLS::CheckRelicErrors();
return sigObj;
}

Expand Down
58 changes: 45 additions & 13 deletions src/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,51 @@ TEST_CASE("Key generation") {
}
}

TEST_CASE("Error handling") {
SECTION("Should throw on a bad private key") {
uint8_t seed[32];
getRandomSeed(seed);
PrivateKey sk1 = PrivateKey::FromSeed(seed, 32);
uint8_t* skData = Util::SecAlloc<uint8_t>(
Signature::SIGNATURE_SIZE);
sk1.Serialize(skData);
skData[0] = 255;
REQUIRE_THROWS(PrivateKey::FromBytes(skData));

Util::SecFree(skData);
}

SECTION("Should throw on a bad public key") {
uint8_t buf[PublicKey::PUBLIC_KEY_SIZE] = {0};
std::set<int> invalid = {1, 2, 3, 4};

for (int i = 0; i < 10; i++) {
buf[0] = (uint8_t)i;
try {
PublicKey::FromBytes(buf);
REQUIRE(invalid.count(i) == 0);
} catch (std::string& s) {
REQUIRE(invalid.count(i) != 0);
}
}
}

SECTION("Should throw on a bad signature") {
uint8_t buf[Signature::SIGNATURE_SIZE] = {0};
std::set<int> invalid = {0, 1, 2, 3, 5, 6, 7, 8};

for (int i = 0; i < 10; i++) {
buf[0] = (uint8_t)i;
try {
Signature::FromBytes(buf);
REQUIRE(invalid.count(i) == 0);
} catch (std::string& s) {
REQUIRE(invalid.count(i) != 0);
}
}
}
}

TEST_CASE("Util tests") {
SECTION("Should convert an int to four bytes") {
uint32_t x = 1024;
Expand Down Expand Up @@ -335,19 +380,6 @@ TEST_CASE("Signatures") {
REQUIRE(Signature::FromInsecureSig(sig3) == sig2);
}

SECTION("Should throw on a bad private key") {
uint8_t seed[32];
getRandomSeed(seed);
PrivateKey sk1 = PrivateKey::FromSeed(seed, 32);
uint8_t* skData = Util::SecAlloc<uint8_t>(
Signature::SIGNATURE_SIZE);
sk1.Serialize(skData);
skData[0] = 255;
REQUIRE_THROWS(PrivateKey::FromBytes(skData));

Util::SecFree(skData);
}

SECTION("Should not validate a bad sig") {
uint8_t message1[7] = {100, 2, 254, 88, 90, 45, 22};
uint8_t seed[32];
Expand Down

0 comments on commit 0739569

Please sign in to comment.