From 2373ee006137349a2f13209477f785396ffd59a8 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Mon, 13 Dec 2021 19:46:25 +0100 Subject: [PATCH] harden `ecnist` byte export against uninitialized key (#671) Currently, `ecnist`'s `toBytes` and `getBytes` methods operate only on properly initialized keys. If an un-initialized key is given, an `IndexError` may be raised if the key's `xlen` / `qlen` property is larger than the maximum buffer size. This patch hardens those functions to report a proper error in that case. Note that the library functions called by `init` and `initRaw` already reject data that does not have the expected length, so these new checks should not be reachable in practice. --- libp2p/crypto/ecnist.nim | 6 ++++++ tests/testecnist.nim | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/libp2p/crypto/ecnist.nim b/libp2p/crypto/ecnist.nim index f0cf258aa..9e920dbff 100644 --- a/libp2p/crypto/ecnist.nim +++ b/libp2p/crypto/ecnist.nim @@ -381,11 +381,15 @@ proc toBytes*(seckey: EcPrivateKey, data: var openarray[byte]): EcResult[int] = c0.write(Asn1Tag.Oid, Asn1OidSecp521r1) c0.finish() offset = pubkey.getOffset() + if offset < 0: + return err(EcKeyIncorrectError) length = pubkey.key.qlen c1.write(Asn1Tag.BitString, pubkey.buffer.toOpenArray(offset, offset + length - 1)) c1.finish() offset = seckey.getOffset() + if offset < 0: + return err(EcKeyIncorrectError) length = seckey.key.xlen p.write(1'u64) p.write(Asn1Tag.OctetString, @@ -426,6 +430,8 @@ proc toBytes*(pubkey: EcPublicKey, data: var openarray[byte]): EcResult[int] = c.finish() p.write(c) let offset = getOffset(pubkey) + if offset < 0: + return err(EcKeyIncorrectError) let length = pubkey.key.qlen p.write(Asn1Tag.BitString, pubkey.buffer.toOpenArray(offset, offset + length - 1)) diff --git a/tests/testecnist.nim b/tests/testecnist.nim index 27dc5cce7..76999a4f3 100644 --- a/tests/testecnist.nim +++ b/tests/testecnist.nim @@ -315,6 +315,9 @@ suite "EC NIST-P256/384/521 test suite": rkey2 == key rkey3 == key rkey4 == key + rkey1.key.xlen = rkey1.buffer.len + 1 + check: + rkey1.getBytes == EcResult[seq[byte]].err(EcKeyIncorrectError) test "[secp256r1] Public key serialize/deserialize test": for i in 0..