From 5f0637c49a905d57b5d5ac21b0d8ca4327b16ec5 Mon Sep 17 00:00:00 2001 From: Giovanni Petrantoni Date: Tue, 4 Aug 2020 18:19:26 +0900 Subject: [PATCH] Audit curve fixes part2 (#298) * refactor and fix mulgen (curve25519) * crypto tests fixing * fix some confusion in curve25519 mul * removing ForbiddenCurveValues table and checks * fix remaining merge issues --- libp2p/crypto/curve25519.nim | 47 ++++++------------------------- libp2p/protocols/secure/noise.nim | 5 ++-- tests/testcrypto.nim | 32 ++++++++++----------- 3 files changed, 27 insertions(+), 57 deletions(-) diff --git a/libp2p/crypto/curve25519.nim b/libp2p/crypto/curve25519.nim index 304876c..65754df 100644 --- a/libp2p/crypto/curve25519.nim +++ b/libp2p/crypto/curve25519.nim @@ -37,22 +37,6 @@ proc intoCurve25519Key*(s: openarray[byte]): Curve25519Key = proc getBytes*(key: Curve25519Key): seq[byte] = @key -const - ForbiddenCurveValues: array[12, Curve25519Key] = [ - [0.byte, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [1.byte, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [224.byte, 235, 122, 124, 59, 65, 184, 174, 22, 86, 227, 250, 241, 159, 196, 106, 218, 9, 141, 235, 156, 50, 177, 253, 134, 98, 5, 22, 95, 73, 184, 0], - [95.byte, 156, 149, 188, 163, 80, 140, 36, 177, 208, 177, 85, 156, 131, 239, 91, 4, 68, 92, 196, 88, 28, 142, 134, 216, 34, 78, 221, 208, 159, 17, 87], - [236.byte, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 127], - [237.byte, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 127], - [238.byte, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 127], - [205.byte, 235, 122, 124, 59, 65, 184, 174, 22, 86, 227, 250, 241, 159, 196, 106, 218, 9, 141, 235, 156, 50, 177, 253, 134, 98, 5, 22, 95, 73, 184, 128], - [76.byte, 156, 149, 188, 163, 80, 140, 36, 177, 208, 177, 85, 156, 131, 239, 91, 4, 68, 92, 196, 88, 28, 142, 134, 216, 34, 78, 221, 208, 159, 17, 215], - [217.byte, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - [218.byte, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], - [219.byte, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 25], - ] - proc byteswap(buf: var Curve25519Key) {.inline.} = for i in 0..<16: let @@ -60,27 +44,23 @@ proc byteswap(buf: var Curve25519Key) {.inline.} = buf[i] = buf[31 - i] buf[31 - i] = x -proc mul*(_: type[Curve25519], dst: var Curve25519Key, scalar: Curve25519Key, point: Curve25519Key) = +proc mul*(_: type[Curve25519], point: var Curve25519Key, multiplier: Curve25519Key) = let defaultBrEc = brEcGetDefault() - # The source point is provided in array G (of size Glen bytes); - # the multiplication result is written over it. - dst = scalar - - # point needs to be big-endian + # multiplier needs to be big-endian var - rpoint = point - rpoint.byteswap() + multiplierBs = multiplier + multiplierBs.byteswap() let res = defaultBrEc.mul( - cast[pcuchar](addr dst[0]), + cast[pcuchar](addr point[0]), Curve25519KeySize, - cast[pcuchar](addr rpoint[0]), + cast[pcuchar](addr multiplierBs[0]), Curve25519KeySize, EC_curve25519) assert res == 1 -proc mulgen(_: type[Curve25519], dst: var Curve25519Key, point: Curve25519Key): bool = +proc mulgen(_: type[Curve25519], dst: var Curve25519Key, point: Curve25519Key) = let defaultBrEc = brEcGetDefault() var @@ -96,17 +76,8 @@ proc mulgen(_: type[Curve25519], dst: var Curve25519Key, point: Curve25519Key): assert size == Curve25519KeySize - if dst in ForbiddenCurveValues: - false - else: - true - -proc public*(private: Curve25519Key): Result[Curve25519Key, cstring] = - var res: Curve25519Key - if Curve25519.mulgen(res, private): - ok(res) - else: - err("mulgen produced a forbidden key") +proc public*(private: Curve25519Key): Curve25519Key = + Curve25519.mulgen(result, private) proc random*(_: type[Curve25519Key], rng: var BrHmacDrbgContext): Curve25519Key = var res: Curve25519Key diff --git a/libp2p/protocols/secure/noise.nim b/libp2p/protocols/secure/noise.nim index 137b0d3..56e9774 100644 --- a/libp2p/protocols/secure/noise.nim +++ b/libp2p/protocols/secure/noise.nim @@ -90,7 +90,7 @@ type proc genKeyPair(rng: var BrHmacDrbgContext): KeyPair = result.privateKey = Curve25519Key.random(rng) - result.publicKey = result.privateKey.public().tryGet() + result.publicKey = result.privateKey.public() proc hashProtocol(name: string): MDigest[256] = # If protocol_name is less than or equal to HASHLEN bytes in length, @@ -103,7 +103,8 @@ proc hashProtocol(name: string): MDigest[256] = result = sha256.digest(name) proc dh(priv: Curve25519Key, pub: Curve25519Key): Curve25519Key = - Curve25519.mul(result, pub, priv) + result = pub + Curve25519.mul(result, priv) # Cipherstate diff --git a/tests/testcrypto.nim b/tests/testcrypto.nim index 0632264..73d5e65 100644 --- a/tests/testcrypto.nim +++ b/tests/testcrypto.nim @@ -485,42 +485,40 @@ suite "Key interface test suite": test "Curve25519": # from bearssl test_crypto.c var - res: Curve25519Key - bearOp = fromHex("A546E36BF0527C9D3B16154B82465EDD62144C0AC1FC5A18506A2244BA449AC4") - bearIn = fromHex("E6DB6867583030DB3594C1A424B15F7C726624EC26B3353B10A903A6D0AB1C4C") - bearOut = fromHex("C3DA55379DE9C6908E94EA4DF28D084F32ECCF03491C71F754B4075577A28552") + bearOp = fromHex("A546E36BF0527C9D3B16154B82465EDD62144C0AC1FC5A18506A2244BA449AC4").intoCurve25519Key() + bearIn = fromHex("E6DB6867583030DB3594C1A424B15F7C726624EC26B3353B10A903A6D0AB1C4C").intoCurve25519Key() + bearOut = fromHex("C3DA55379DE9C6908E94EA4DF28D084F32ECCF03491C71F754B4075577A28552").intoCurve25519Key() - Curve25519.mul(res, bearIn.intoCurve25519Key, bearOp.intoCurve25519Key) - check res == bearOut + Curve25519.mul(bearIn, bearOp) + check bearIn == bearOut # from https://github.com/golang/crypto/blob/1d94cc7ab1c630336ab82ccb9c9cda72a875c382/curve25519/vectors_test.go#L26 var private1: Curve25519Key = [0x66.byte, 0x8f, 0xb9, 0xf7, 0x6a, 0xd9, 0x71, 0xc8, 0x1a, 0xc9, 0x0, 0x7, 0x1a, 0x15, 0x60, 0xbc, 0xe2, 0xca, 0x0, 0xca, 0xc7, 0xe6, 0x7a, 0xf9, 0x93, 0x48, 0x91, 0x37, 0x61, 0x43, 0x40, 0x14] base: Curve25519Key = [0xdb.byte, 0x5f, 0x32, 0xb7, 0xf8, 0x41, 0xe7, 0xa1, 0xa0, 0x9, 0x68, 0xef, 0xfd, 0xed, 0x12, 0x73, 0x5f, 0xc4, 0x7a, 0x3e, 0xb1, 0x3b, 0x57, 0x9a, 0xac, 0xad, 0xea, 0xe8, 0x9, 0x39, 0xa7, 0xdd] - public1: Curve25519Key public1Test: Curve25519Key = [0x9.byte, 0xd, 0x85, 0xe5, 0x99, 0xea, 0x8e, 0x2b, 0xee, 0xb6, 0x13, 0x4, 0xd3, 0x7b, 0xe1, 0xe, 0xc5, 0xc9, 0x5, 0xf9, 0x92, 0x7d, 0x32, 0xf4, 0x2a, 0x9a, 0xa, 0xfb, 0x3e, 0xb, 0x40, 0x74] - Curve25519.mul(public1, base, private1) - check public1.toHex == public1Test.toHex + Curve25519.mul(base, private1) + check base.toHex == public1Test.toHex # RFC vectors private1 = fromHex("a8abababababababababababababababababababababababababababababab6b").intoCurve25519Key - check private1.public().get().toHex == "E3712D851A0E5D79B831C5E34AB22B41A198171DE209B8B8FACA23A11C624859" + check private1.public().toHex == "E3712D851A0E5D79B831C5E34AB22B41A198171DE209B8B8FACA23A11C624859" private1 = fromHex("c8cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd4d").intoCurve25519Key - check private1.public().get().toHex == "B5BEA823D9C9FF576091C54B7C596C0AE296884F0E150290E88455D7FBA6126F" + check private1.public().toHex == "B5BEA823D9C9FF576091C54B7C596C0AE296884F0E150290E88455D7FBA6126F" private1 = fromHex("77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a").intoCurve25519Key var private2 = fromHex("5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb").intoCurve25519Key - p1Pub = private1.public().get() - p2Pub = private2.public().get() + p1Pub = private1.public() + p2Pub = private2.public() check p1Pub.toHex == "8520F0098930A754748B7DDCB43EF75A0DBF3A0D26381AF4EBA4A98EAA9B4E6A" check p2Pub.toHex == "DE9EDB7D7B7DC1B4D35B61C2ECE435373F8343C85B78674DADFC7E146F882B4F" var - secret1: Curve25519Key - secret2: Curve25519Key - Curve25519.mul(secret1, p2Pub, private1) - Curve25519.mul(secret2, p1Pub, private2) + secret1 = p2Pub + secret2 = p1Pub + Curve25519.mul(secret1, private1) + Curve25519.mul(secret2, private2) check secret1.toHex == secret2.toHex