From c7e706e50e764806d264aaa5f6bf1ea1a4e19612 Mon Sep 17 00:00:00 2001 From: garyschulte Date: Tue, 9 Jul 2024 19:32:15 -0700 Subject: [PATCH 1/3] interpret both short input and long input as error conditions Signed-off-by: garyschulte --- gnark/gnark-jni/gnark-eip-196.go | 61 ++++++++----------- .../besu/nativelib/gnark/eip196_g1_add.csv | 5 +- 2 files changed, 28 insertions(+), 38 deletions(-) diff --git a/gnark/gnark-jni/gnark-eip-196.go b/gnark/gnark-jni/gnark-eip-196.go index 785215af..a014d4ea 100644 --- a/gnark/gnark-jni/gnark-eip-196.go +++ b/gnark/gnark-jni/gnark-eip-196.go @@ -18,6 +18,8 @@ import ( ) var ErrMalformedPoint = errors.New("invalid input parameters, invalid point encoding") +var ErrInvalidInputLength = errors.New("invalid input parameters, invalid input length") +var ErrInvalidInputPairingLength = errors.New("invalid input parameters, invalid input length for pairing") var ErrPointNotInField = errors.New("invalid input parameters, point not in field") var ErrPointOnCurveCheckFailed = errors.New("invalid point: point is not on curve") @@ -47,32 +49,21 @@ func eip196altbn128G1Add(javaInputBuf, javaOutputBuf, javaErrorBuf *C.char, cInp inputLen := int(cInputLen) errorLen := int(cErrorLen) - if (inputLen > 2*EIP196PreallocateForG1) { - // trunc if input too long - inputLen = 2*EIP196PreallocateForG1 - } - // Convert error C pointers to Go slices errorBuf := castErrorBuffer(javaErrorBuf, errorLen) - // check we have input size sufficient for a G1Affine - if inputLen < EIP196PreallocateForG1 { - - // if not, check the X point and return an error if it is in the field, edge case - if inputLen >= EIP196PreallocateForFp { - input := (*[EIP196PreallocateForFp]byte)(unsafe.Pointer(javaInputBuf))[:EIP196PreallocateForFp:EIP196PreallocateForFp] - if !checkInField(input[:EIP196PreallocateForFp]) { - copy(errorBuf, ErrPointNotInField.Error()) - return 1 - } - } - // otherwise if we do not have complete input, return 0 - return 0 + if (inputLen > 2*EIP196PreallocateForG1) { + copy(errorBuf, ErrInvalidInputLength.Error()) + return 1 } // Convert input C pointers to Go slices input := (*[2*EIP196PreallocateForG1]byte)(unsafe.Pointer(javaInputBuf))[:inputLen:inputLen] + if (inputLen < EIP196PreallocateForG1) { + return 0 + } + // generate p0 g1 affine p0, err := safeUnmarshal(input[:64]) @@ -87,11 +78,9 @@ func eip196altbn128G1Add(javaInputBuf, javaOutputBuf, javaErrorBuf *C.char, cInp ret := p0.Marshal() g1AffineEncode(ret, javaOutputBuf) return 0; - } else { - // else return an incomplete input error - copy(errorBuf, ErrMalformedPoint.Error()) - return 1 } + copy(errorBuf, ErrInvalidInputLength.Error()) + return 1 } // generate p1 g1 affine @@ -121,23 +110,14 @@ func eip196altbn128G1Mul(javaInputBuf, javaOutputBuf, javaErrorBuf *C.char, cInp errorBuf := castErrorBuffer(javaErrorBuf, errorLen) if inputLen < EIP196PreallocateForG1 { - - // check the X point and return an error if it is in the field, edge case - if inputLen >= EIP196PreallocateForFp { - input := (*[EIP196PreallocateForFp]byte)(unsafe.Pointer(javaInputBuf))[:EIP196PreallocateForFp:EIP196PreallocateForFp] - if !checkInField(input[:EIP196PreallocateForFp]) { - copy(errorBuf, ErrPointNotInField.Error()) - return 1 - } - } - - // otherwise if we do not have complete input, return 0 + // if we do not have complete input, return 0 return 0 } if (inputLen > EIP196PreallocateForG1 + EIP196PreallocateForScalar) { // trunc if input too long - inputLen = EIP196PreallocateForG1 + EIP196PreallocateForScalar + copy(errorBuf, ErrInvalidInputLength.Error()) + return 1 } // Convert input C pointers to Go slice @@ -190,7 +170,7 @@ func eip196altbn128Pairing(javaInputBuf, javaOutputBuf, javaErrorBuf *C.char, cI } if inputLen % (EIP196PreallocateForG2 + EIP196PreallocateForG1) != 0 { - copy(errorBuf, "invalid input parameters, invalid input length for pairing\x00") + copy(errorBuf, ErrInvalidInputPairingLength.Error()) return 1 } @@ -259,13 +239,24 @@ func g1AffineEncode(g1Point []byte, output *C.char) (error) { func safeUnmarshal(input []byte) (*bn254.G1Affine, error) { var g1 bn254.G1Affine + + if (len(input) < 64) { + return nil, ErrMalformedPoint + } + + if !checkInField(input[:32]) { + return nil, ErrPointOnCurveCheckFailed + } + err := g1.X.SetBytesCanonical(input[:32]) + if (err == nil) { err := g1.Y.SetBytesCanonical(input[32:64]) if (err == nil) { return &g1, nil } } + if (!g1.IsOnCurve()) { return nil, ErrPointOnCurveCheckFailed } diff --git a/gnark/src/test/resources/org/hyperledger/besu/nativelib/gnark/eip196_g1_add.csv b/gnark/src/test/resources/org/hyperledger/besu/nativelib/gnark/eip196_g1_add.csv index ccead7db..2a93644e 100644 --- a/gnark/src/test/resources/org/hyperledger/besu/nativelib/gnark/eip196_g1_add.csv +++ b/gnark/src/test/resources/org/hyperledger/besu/nativelib/gnark/eip196_g1_add.csv @@ -101,7 +101,6 @@ input,result,gas,notes 1ca0717a8dfb9c3940a731d7c52f1699f64fe05e76189a91dc622e8fafd99de62313a1df5b32b17c21e53e2d0a1ff3eeac6ab4359a9f86e51b1c236f414d87ea0e9729271df80f9967d618c33d9e8389bd4afb88e8b1e26e20b98868406da8ce1aca0647ae2e8573e39970f442aa3900175beeef2984af814fa51cf4ab59e07c,278782b7f77402d99c21f0bb831e899431703967252026abb6a6cfefd6d368600bd99290fca19622267066ee211842111904f2ced987023a34048236be757231,150, 1ca0717a8dfb9c3940a731d7c52f1699f64fe05e76189a91dc622e8fafd99de62313a1df5b32b17c21e53e2d0a1ff3eeac6ab4359a9f86e51b1c236f414d87ea00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,1ca0717a8dfb9c3940a731d7c52f1699f64fe05e76189a91dc622e8fafd99de62313a1df5b32b17c21e53e2d0a1ff3eeac6ab4359a9f86e51b1c236f414d87ea,150, 1234,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,150, -0174fc233104c2ad4f56a8396b8c1b7d9c6ad10bffc70761c5e8f5280862f137029733a9f20a4cdbb7ae9c5dd1adf6ccc7fe3439d7dc71093af0656ae0ca0f290964773f12e2292f332306374f957d10,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,150,invalid input parameters, invalid point encoding -67376aad340c93eb0fc9bc8e040dc691bd00e426c6456b4d13079e7f1dbb3da847eb0fc271cd23da50c6ebc261928abb1af9bfcea998791e18af1817b06221e1fe708d2f4224275523fcd37460a310ce4b56f1694dfe36280410f0fb6efc5f47b85662e5b08d881242a72acbc2c8e2fa71ac593be977ad3e090c8158aace0247,,150,invalid input parameters, invalid fp.Element encoding +0174fc233104c2ad4f56a8396b8c1b7d9c6ad10bffc70761c5e8f5280862f137029733a9f20a4cdbb7ae9c5dd1adf6ccc7fe3439d7dc71093af0656ae0ca0f290964773f12e2292f332306374f957d10,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,150,invalid input parameters, invalid input length ,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,150, -ff000000000000000000000000000000000000000000000000000000000000ff,,150,invalid input parameters, point not in field +67376aad340c93eb0fc9bc8e040dc691bd00e426c6456b4d13079e7f1dbb3da847eb0fc271cd23da50c6ebc261928abb1af9bfcea998791e18af1817b06221e1fe708d2f4224275523fcd37460a310ce4b56f1694dfe36280410f0fb6efc5f47b85662e5b08d881242a72acbc2c8e2fa71ac593be977ad3e090c8158aace0247,,150,invalid input parameters, invalid point: point is not on curve From ef5e5e3c6f820d7b1ff14ead7260521c29a22c57 Mon Sep 17 00:00:00 2001 From: garyschulte Date: Tue, 9 Jul 2024 22:51:36 -0700 Subject: [PATCH 2/3] add test cases for point not on curve, use IntByReference to indicate error and output length rather than static vals Signed-off-by: garyschulte --- .../nativelib/bls12_381/eip196_g1_add.csv | 2 + .../nativelib/bls12_381/eip196_g1_mul.csv | 1 + gnark/gnark-jni/gnark-eip-196.go | 132 ++++++++++-------- .../besu/nativelib/gnark/LibGnarkEIP196.java | 24 +--- ...8PairingPrecompiledContractLegacyTest.java | 2 +- .../besu/nativelib/gnark/eip196_g1_add.csv | 11 +- .../besu/nativelib/gnark/eip196_g1_mul.csv | 7 +- 7 files changed, 95 insertions(+), 84 deletions(-) diff --git a/bls12-381/src/test/resources/org/hyperledger/besu/nativelib/bls12_381/eip196_g1_add.csv b/bls12-381/src/test/resources/org/hyperledger/besu/nativelib/bls12_381/eip196_g1_add.csv index 5ddf1deb..96725069 100644 --- a/bls12-381/src/test/resources/org/hyperledger/besu/nativelib/bls12_381/eip196_g1_add.csv +++ b/bls12-381/src/test/resources/org/hyperledger/besu/nativelib/bls12_381/eip196_g1_add.csv @@ -102,6 +102,8 @@ input,result,gas,notes 1ca0717a8dfb9c3940a731d7c52f1699f64fe05e76189a91dc622e8fafd99de62313a1df5b32b17c21e53e2d0a1ff3eeac6ab4359a9f86e51b1c236f414d87ea00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,1ca0717a8dfb9c3940a731d7c52f1699f64fe05e76189a91dc622e8fafd99de62313a1df5b32b17c21e53e2d0a1ff3eeac6ab4359a9f86e51b1c236f414d87ea,150, 1234,,150,invalid input parameters, Point 0 is not on curve 0174fc233104c2ad4f56a8396b8c1b7d9c6ad10bffc70761c5e8f5280862f137029733a9f20a4cdbb7ae9c5dd1adf6ccc7fe3439d7dc71093af0656ae0ca0f290964773f12e2292f332306374f957d10,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,150,invalid input parameters, Point 1 is not on curve +0174fc233104c2ad4f56a8396b8c1b7d9c6ad10bffc70761c5e8f5280862f137029733a9f20a4cdbb7ae9c5dd1adf6ccc7fe3439d7dc71093af0656ae0ca0f290964773f12e2292f332306374f957d10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,150,invalid input parameters, Point 1 is not on curve 67376aad340c93eb0fc9bc8e040dc691bd00e426c6456b4d13079e7f1dbb3da847eb0fc271cd23da50c6ebc261928abb1af9bfcea998791e18af1817b06221e1fe708d2f4224275523fcd37460a310ce4b56f1694dfe36280410f0fb6efc5f47b85662e5b08d881242a72acbc2c8e2fa71ac593be977ad3e090c8158aace0247,,150,invalid input parameters, Failed to parse Fp element ,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,150, ff000000000000000000000000000000000000000000000000000000000000ff,,150,invalid input parameters, Failed to parse Fp element +1470b80a6d5de1470aeadfa0b2eb913d9286bd966aa8a99b09879f3b10c985d02432b8ccd7083d421127dac6ad90bd569e763810e32d37114a786c7645864647,1470b80a6d5de1470aeadfa0b2eb913d9286bd966aa8a99b09879f3b10c985d02432b8ccd7083d421127dac6ad90bd569e763810e32d37114a786c7645864647,150, diff --git a/bls12-381/src/test/resources/org/hyperledger/besu/nativelib/bls12_381/eip196_g1_mul.csv b/bls12-381/src/test/resources/org/hyperledger/besu/nativelib/bls12_381/eip196_g1_mul.csv index 936eb937..9e890dd2 100644 --- a/bls12-381/src/test/resources/org/hyperledger/besu/nativelib/bls12_381/eip196_g1_mul.csv +++ b/bls12-381/src/test/resources/org/hyperledger/besu/nativelib/bls12_381/eip196_g1_mul.csv @@ -100,6 +100,7 @@ input,result,gas,notes 1c2cb2b4504b19c7e073679432e625f2706b7c4728cd9bd3ce36579f4de2f3902c8605f723ac2f73baa15eac674f62ab06c79809aa4a4be3391c4d41d5a6e62ca0a73a5b559cd0384ca11d444e34f40e04f2080483db9e54ae09e44ec19c26a1,1147da8fc5774b5ef94fda682437b04f9b6aea72987d1269496769baf7e67dc729fe144eab44c6da4c851123165cd6506ce3e10b7691b8bf11b757e2ae058fcb,6000, 0d6ad8e12b4f61e3e2a2252ce11428941f2a84b7f0a821cb8cc7699303bd4fec2247870562618fd8d6169072d9b33614d2acf800b3ba0ff68ef8d5fd4d6c250d3e70b3bed17894f958579644c83fa9d485121d580e2b061c697e68f950297768,0be6d75e2fe2887835d396dae11321ca7c53083abd6a0b270ee1c087593517aa2ffd1bad577de7cf2b19b82bfff0c66e2afbfb79a72cbe834290437f3caf2f21,6000, d2acf800b3ba0ff68ef8d5fd4d6c250d3e70b3bed17894f958579644c83fa9d485121d580e2b061c697e68f9502977680d6ad8e12b4f61e3e2a2252ce11428941f2a84b7f0a821cb8cc7699303bd4fec2247870562618fd8d6169072d9b33614,,6000,invalid input parameters, Failed to parse Fp element +02acf800b3ba0ff68ef8d5fd4d6c250d3e70b3bed17894f958579644c83fa9d405121d580e2b061c697e68f9502977680d6ad8e12b4f61e3e2a2252ce11428941f2a84b7f0a821cb8cc7699303bd4fec2247870562618fd8d6169072d9b33614,,6000,invalid input parameters, Point is not on curve ,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,6000, 1A87B0584CE92F4593D161480614F2989035225609F08058CCFA3D0F940FEBE31A2F3C951F6DADCC7EE9007DFF81504B0FCD6D7CF59996EFDC33D92BF7F9F8F60100000000000000000000000000000000,0x220cb1540fa85ba04d863dca86de9359a43ac9fc084aebb9f2a936d989abbb602ccdc6c020dd2cf78332132b3f1d1122391b515035623cd6f53d4aea24ea2466,6000, 1A87B0584CE92F4593D161480614F2989035225609F08058CCFA3D0F940FEBE31A2F3C951F6DADCC7EE9007DFF81504B0FCD6D7CF59996EFDC33D92BF7F9F8F60000000000000000000000000000000100000000000000000000000000000000,1051acb0700ec6d42a88215852d582efbaef31529b6fcbc3277b5c1b300f5cf0135b2394bb45ab04b8bd7611bd2dfe1de6a4e6e2ccea1ea1955f577cd66af85b,6000, diff --git a/gnark/gnark-jni/gnark-eip-196.go b/gnark/gnark-jni/gnark-eip-196.go index a014d4ea..f87e718b 100644 --- a/gnark/gnark-jni/gnark-eip-196.go +++ b/gnark/gnark-jni/gnark-eip-196.go @@ -17,11 +17,10 @@ import ( "github.com/consensys/gnark-crypto/ecc/bn254/fp" ) -var ErrMalformedPoint = errors.New("invalid input parameters, invalid point encoding") -var ErrInvalidInputLength = errors.New("invalid input parameters, invalid input length") -var ErrInvalidInputPairingLength = errors.New("invalid input parameters, invalid input length for pairing") -var ErrPointNotInField = errors.New("invalid input parameters, point not in field") -var ErrPointOnCurveCheckFailed = errors.New("invalid point: point is not on curve") +var ErrMalformedPointEIP196 = errors.New("invalid point encoding") +var ErrInvalidInputPairingLengthEIP196 = errors.New("invalid input parameters, invalid input length for pairing") +var ErrPointNotInFieldEIP196 = errors.New("point not in field") +var ErrPointOnCurveCheckFailedEIP196 = errors.New("point is not on curve") const ( EIP196PreallocateForResult = 128 @@ -42,52 +41,52 @@ var bn254Modulus = new(big.Int).SetBytes([]byte{ }) // Predefine a zero slice of length 16 -var zeroSlice = make([]byte, 16) +var zeroEIP196Slice = make([]byte, 16) //export eip196altbn128G1Add -func eip196altbn128G1Add(javaInputBuf, javaOutputBuf, javaErrorBuf *C.char, cInputLen, cOutputLen, cErrorLen C.int) C.int { +func eip196altbn128G1Add(javaInputBuf, javaOutputBuf, javaErrorBuf *C.char, cInputLen C.int, cOutputLen, cErrorLen *C.int) C.int { inputLen := int(cInputLen) - errorLen := int(cErrorLen) + errorLen := (*int)(unsafe.Pointer(cErrorLen)) + outputLen := (*int)(unsafe.Pointer(cOutputLen)) // Convert error C pointers to Go slices - errorBuf := castErrorBuffer(javaErrorBuf, errorLen) + errorBuf := castErrorBufferEIP196(javaErrorBuf, *errorLen) if (inputLen > 2*EIP196PreallocateForG1) { - copy(errorBuf, ErrInvalidInputLength.Error()) - return 1 + // trunc if input too long + inputLen = 2*EIP196PreallocateForG1 } // Convert input C pointers to Go slices input := (*[2*EIP196PreallocateForG1]byte)(unsafe.Pointer(javaInputBuf))[:inputLen:inputLen] - if (inputLen < EIP196PreallocateForG1) { + if (inputLen == 0) { + *outputLen = 0 return 0 } // generate p0 g1 affine - p0, err := safeUnmarshal(input[:64]) + p0, err := safeUnmarshalEIP196(input, 0) if err != nil { - copy(errorBuf, "invalid input parameters, " + err.Error()) + dryError(err, errorBuf, outputLen, errorLen) return 1 } if inputLen < 2*EIP196PreallocateForG1 { // if incomplete input is all zero, return p0 - if isAllZero(input[64:inputLen]) { + if isAllZeroEIP196(input, 64) { ret := p0.Marshal() g1AffineEncode(ret, javaOutputBuf) + *outputLen = EIP196PreallocateForG1 return 0; } - copy(errorBuf, ErrInvalidInputLength.Error()) - return 1 } - // generate p1 g1 affine - p1, err := safeUnmarshal(input[64:]) + p1, err := safeUnmarshalEIP196(input, 64) if err != nil { - copy(errorBuf, "invalid input parameters, " + err.Error()) + dryError(err, errorBuf, outputLen, errorLen) return 1 } @@ -97,38 +96,39 @@ func eip196altbn128G1Add(javaInputBuf, javaOutputBuf, javaErrorBuf *C.char, cInp // marshal the resulting point and encode directly to the output buffer ret := result.Marshal() g1AffineEncode(ret, javaOutputBuf) + *outputLen = EIP196PreallocateForG1 return 0 } //export eip196altbn128G1Mul -func eip196altbn128G1Mul(javaInputBuf, javaOutputBuf, javaErrorBuf *C.char, cInputLen, cOutputLen, cErrorLen C.int) C.int { +func eip196altbn128G1Mul(javaInputBuf, javaOutputBuf, javaErrorBuf *C.char, cInputLen C.int, cOutputLen, cErrorLen *C.int) C.int { inputLen := int(cInputLen) - errorLen := int(cErrorLen) + errorLen := (*int)(unsafe.Pointer(cErrorLen)) + outputLen := (*int)(unsafe.Pointer(cOutputLen)) // Convert error C pointers to Go slices - errorBuf := castErrorBuffer(javaErrorBuf, errorLen) + errorBuf := castErrorBufferEIP196(javaErrorBuf, *errorLen) if inputLen < EIP196PreallocateForG1 { // if we do not have complete input, return 0 + *outputLen = 0 return 0 } if (inputLen > EIP196PreallocateForG1 + EIP196PreallocateForScalar) { // trunc if input too long - copy(errorBuf, ErrInvalidInputLength.Error()) - return 1 + inputLen = EIP196PreallocateForG1 + EIP196PreallocateForScalar } // Convert input C pointers to Go slice input := (*[EIP196PreallocateForG1 + EIP196PreallocateForScalar]byte)(unsafe.Pointer(javaInputBuf))[:inputLen:inputLen] // generate p0 g1 affine - var p0 bn254.G1Affine - err := p0.Unmarshal(input[:64]) + p0, err := safeUnmarshalEIP196(input, 0) if err != nil { - copy(errorBuf, err.Error()) + dryError(err, errorBuf, outputLen, errorLen) return 1 } @@ -144,25 +144,28 @@ func eip196altbn128G1Mul(javaInputBuf, javaOutputBuf, javaErrorBuf *C.char, cInp scalar.SetBytes(scalarBytes[:]) // multiply g1 point by scalar - result := p0.ScalarMultiplication(&p0, scalar) + result := p0.ScalarMultiplication(p0, scalar) // marshal the resulting point and encode directly to the output buffer ret := result.Marshal() g1AffineEncode(ret, javaOutputBuf) + *outputLen = EIP196PreallocateForG1 return 0 } //export eip196altbn128Pairing -func eip196altbn128Pairing(javaInputBuf, javaOutputBuf, javaErrorBuf *C.char, cInputLen, cOutputLen, cErrorLen C.int) C.int { +func eip196altbn128Pairing(javaInputBuf, javaOutputBuf, javaErrorBuf *C.char, cInputLen C.int, cOutputLen, cErrorLen *C.int) C.int { inputLen := int(cInputLen) - outputLen := int(cOutputLen) - errorLen := int(cErrorLen) + errorLen := (*int)(unsafe.Pointer(cErrorLen)) + outputLen := (*int)(unsafe.Pointer(cOutputLen)) // Convert error C pointers to Go slices - output := castBuffer(javaOutputBuf, outputLen) + output := castBufferEIP196(javaOutputBuf, *outputLen) // Convert error C pointers to Go slices - errorBuf := castErrorBuffer(javaErrorBuf, errorLen) + errorBuf := castErrorBufferEIP196(javaErrorBuf, *errorLen) + + *outputLen = 32 if inputLen == 0 { output[31]=0x01 @@ -170,12 +173,12 @@ func eip196altbn128Pairing(javaInputBuf, javaOutputBuf, javaErrorBuf *C.char, cI } if inputLen % (EIP196PreallocateForG2 + EIP196PreallocateForG1) != 0 { - copy(errorBuf, ErrInvalidInputPairingLength.Error()) + dryError(ErrInvalidInputPairingLengthEIP196, errorBuf, outputLen, errorLen) return 1 } // Convert input C pointers to Go slice - input := castBufferToSlice(unsafe.Pointer(javaInputBuf), inputLen) + input := castBufferToSliceEIP196(unsafe.Pointer(javaInputBuf), inputLen) var pairCount = inputLen / (EIP196PreallocateForG2 + EIP196PreallocateForG1) g1Points := make([]bn254.G1Affine, pairCount) @@ -189,7 +192,7 @@ func eip196altbn128Pairing(javaInputBuf, javaOutputBuf, javaErrorBuf *C.char, cI err := g1.Unmarshal(input[i*192:i*192+64]) if err != nil { - copy(errorBuf, err.Error()) + dryError(err, errorBuf, outputLen, errorLen) return 1 } @@ -198,7 +201,7 @@ func eip196altbn128Pairing(javaInputBuf, javaOutputBuf, javaErrorBuf *C.char, cI err = g2.Unmarshal(input[i*192+64:(i+1)*192]) if err != nil { - copy(errorBuf, err.Error()) + dryError(err, errorBuf, outputLen, errorLen) return 1 } @@ -209,7 +212,7 @@ func eip196altbn128Pairing(javaInputBuf, javaOutputBuf, javaErrorBuf *C.char, cI isOne, err := bn254.PairingCheck(g1Points, g2Points) if err != nil { - copy(errorBuf, err.Error()) + dryError(err, errorBuf, outputLen, errorLen) return -1 } @@ -217,7 +220,6 @@ func eip196altbn128Pairing(javaInputBuf, javaOutputBuf, javaErrorBuf *C.char, cI // respond with 1 if pairing check was true, leave 0's intact otherwise output[31]=0x01 } - return 0 } @@ -237,36 +239,40 @@ func g1AffineEncode(g1Point []byte, output *C.char) (error) { return nil } -func safeUnmarshal(input []byte) (*bn254.G1Affine, error) { +func safeUnmarshalEIP196(input []byte, offset int) (*bn254.G1Affine, error) { var g1 bn254.G1Affine - if (len(input) < 64) { - return nil, ErrMalformedPoint + if (len(input) - offset < 64) { + return nil, ErrMalformedPointEIP196 } - if !checkInField(input[:32]) { - return nil, ErrPointOnCurveCheckFailed + if !checkInFieldEIP196(input[offset: offset + 32]) { + return nil, ErrPointNotInFieldEIP196 } - err := g1.X.SetBytesCanonical(input[:32]) + err := g1.X.SetBytesCanonical(input[offset:offset + 32]) if (err == nil) { - err := g1.Y.SetBytesCanonical(input[32:64]) + + if !checkInFieldEIP196(input[offset + 32: offset + 64]) { + return nil, ErrPointNotInFieldEIP196 + } + err := g1.Y.SetBytesCanonical(input[offset + 32:offset + 64]) if (err == nil) { + if (!g1.IsOnCurve()) { + return nil, ErrPointOnCurveCheckFailedEIP196 + } return &g1, nil } } - if (!g1.IsOnCurve()) { - return nil, ErrPointOnCurveCheckFailed - } return nil, err } // checkInField checks that an element is in the field, not-in-field will normally // be caught during unmarshal, but here in case of no-op calls of a single parameter -func checkInField(data []byte) bool { +func checkInFieldEIP196(data []byte) bool { // Convert the byte slice to a big.Int elem := new(big.Int).SetBytes(data) @@ -276,16 +282,26 @@ func checkInField(data []byte) bool { } // isAllZero checks if all elements in the byte slice are zero -func isAllZero(data []byte) bool { - for _, b := range data { - if b != 0 { - return false +func isAllZeroEIP196(data []byte, offset int) bool { + if len(data) > 64 { + slice := data [offset:] + for _, b := range slice { + if b != 0 { + return false + } } } return true } -func castBufferToSlice(buf unsafe.Pointer, length int) []byte { +func dryError(err error, errorBuf []byte, outputLen, errorLen *int) { + errStr := "invalid input parameters, " + err.Error(); + copy(errorBuf, errStr) + *outputLen = 0 + *errorLen = len(errStr) +} + +func castBufferToSliceEIP196(buf unsafe.Pointer, length int) []byte { var slice []byte // Obtain the slice header header := (*reflect.SliceHeader)(unsafe.Pointer(&slice)) @@ -296,7 +312,7 @@ func castBufferToSlice(buf unsafe.Pointer, length int) []byte { return slice } -func castBuffer(javaOutputBuf *C.char, length int) []byte { +func castBufferEIP196(javaOutputBuf *C.char, length int) []byte { bufSize := length if bufSize < EIP196PreallocateForResult { bufSize = EIP196PreallocateForResult @@ -304,7 +320,7 @@ func castBuffer(javaOutputBuf *C.char, length int) []byte { return (*[EIP196PreallocateForResult]byte)(unsafe.Pointer(javaOutputBuf))[:bufSize:bufSize] } -func castErrorBuffer(javaOutputBuf *C.char, length int) []byte { +func castErrorBufferEIP196(javaOutputBuf *C.char, length int) []byte { bufSize := length if bufSize < EIP196PreallocateForError { bufSize = EIP196PreallocateForError diff --git a/gnark/src/main/java/org/hyperledger/besu/nativelib/gnark/LibGnarkEIP196.java b/gnark/src/main/java/org/hyperledger/besu/nativelib/gnark/LibGnarkEIP196.java index 17b1c7af..4be41a8b 100644 --- a/gnark/src/main/java/org/hyperledger/besu/nativelib/gnark/LibGnarkEIP196.java +++ b/gnark/src/main/java/org/hyperledger/besu/nativelib/gnark/LibGnarkEIP196.java @@ -41,30 +41,18 @@ public static int eip196_perform_operation( int ret = -1; switch(op) { case EIP196_ADD_OPERATION_RAW_VALUE: - ret = eip196altbn128G1Add(i, output, err, i_len, - EIP196_PREALLOCATE_FOR_RESULT_BYTES, EIP196_PREALLOCATE_FOR_ERROR_BYTES); - o_len.setValue(64); + ret = eip196altbn128G1Add(i, output, err, i_len, o_len, err_len); break; case EIP196_MUL_OPERATION_RAW_VALUE: - ret = eip196altbn128G1Mul(i, output, err, i_len, - EIP196_PREALLOCATE_FOR_RESULT_BYTES, EIP196_PREALLOCATE_FOR_ERROR_BYTES); - o_len.setValue(64); + ret = eip196altbn128G1Mul(i, output, err, i_len, o_len, err_len); break; case EIP196_PAIR_OPERATION_RAW_VALUE: - ret = eip196altbn128Pairing(i, output, err, i_len, - EIP196_PREALLOCATE_FOR_RESULT_BYTES, EIP196_PREALLOCATE_FOR_ERROR_BYTES); - o_len.setValue(32); + ret = eip196altbn128Pairing(i, output, err, i_len, o_len, err_len); break; default: throw new RuntimeException("Not Implemented EIP-196 operation " + op); } - if (ret != 0) { - err_len.setValue(LibGnarkUtils.findFirstTrailingZeroIndex(err)); - o_len.setValue(0); - } else { - err_len.setValue(0); - } return ret; } @@ -72,17 +60,17 @@ public static native int eip196altbn128G1Add( byte[] input, byte[] output, byte[] error, - int inputSize, int outputSize, int err_len); + int inputSize, IntByReference outputSize, IntByReference err_len); public static native int eip196altbn128G1Mul( byte[] input, byte[] output, byte[] error, - int inputSize, int output_len, int err_len); + int inputSize, IntByReference output_len, IntByReference err_len); public static native int eip196altbn128Pairing( byte[] input, byte[] output, byte[] error, - int inputSize, int output_len, int err_len); + int inputSize, IntByReference output_len, IntByReference err_len); } diff --git a/gnark/src/test/java/org/hyperledger/besu/nativelib/gnark/AltBN128PairingPrecompiledContractLegacyTest.java b/gnark/src/test/java/org/hyperledger/besu/nativelib/gnark/AltBN128PairingPrecompiledContractLegacyTest.java index a7bd961a..22e082db 100644 --- a/gnark/src/test/java/org/hyperledger/besu/nativelib/gnark/AltBN128PairingPrecompiledContractLegacyTest.java +++ b/gnark/src/test/java/org/hyperledger/besu/nativelib/gnark/AltBN128PairingPrecompiledContractLegacyTest.java @@ -130,7 +130,7 @@ public void compute_invalidPointsOutsideSubgroupG2() { // assert there is an error assertThat(errorLength.getValue()).isNotEqualTo(0); String errorStr = new String(error, 0, errorLength.getValue()); - assertThat(errorStr).isEqualTo("invalid point: subgroup check failed"); + assertThat(errorStr).isEqualTo("invalid input parameters, invalid point: subgroup check failed"); // assert there is no output assertThat(outputLength.getValue()).isEqualTo(0); } diff --git a/gnark/src/test/resources/org/hyperledger/besu/nativelib/gnark/eip196_g1_add.csv b/gnark/src/test/resources/org/hyperledger/besu/nativelib/gnark/eip196_g1_add.csv index 2a93644e..6626a8f0 100644 --- a/gnark/src/test/resources/org/hyperledger/besu/nativelib/gnark/eip196_g1_add.csv +++ b/gnark/src/test/resources/org/hyperledger/besu/nativelib/gnark/eip196_g1_add.csv @@ -100,7 +100,10 @@ input,result,gas,notes 16eea4cc6a5c21b361c4d144f81f0c5774181b19b6341ebc3317b6d9c78b493407abc49d40a88a2336ea698f6bcc5b767f290fa5255f1ea9c449237dfa75259210264114425d52ebb998a32b103fe50d3c44b156f53dd16fec92c805c51b3bc117986b497207e3198ca7beb705537ba0d6c82cb8e6e1c507e74dece3fbb17fc2,2ef81763011baa4945a15da4c312cd2c280017994fcbea76048907c58acaf8f01a66e2bd9a4c4e1ca39a7fa9ba43f615c3720ae73c0d2aa6b2cb14e5a24f233d,150, 1ca0717a8dfb9c3940a731d7c52f1699f64fe05e76189a91dc622e8fafd99de62313a1df5b32b17c21e53e2d0a1ff3eeac6ab4359a9f86e51b1c236f414d87ea0e9729271df80f9967d618c33d9e8389bd4afb88e8b1e26e20b98868406da8ce1aca0647ae2e8573e39970f442aa3900175beeef2984af814fa51cf4ab59e07c,278782b7f77402d99c21f0bb831e899431703967252026abb6a6cfefd6d368600bd99290fca19622267066ee211842111904f2ced987023a34048236be757231,150, 1ca0717a8dfb9c3940a731d7c52f1699f64fe05e76189a91dc622e8fafd99de62313a1df5b32b17c21e53e2d0a1ff3eeac6ab4359a9f86e51b1c236f414d87ea00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,1ca0717a8dfb9c3940a731d7c52f1699f64fe05e76189a91dc622e8fafd99de62313a1df5b32b17c21e53e2d0a1ff3eeac6ab4359a9f86e51b1c236f414d87ea,150, -1234,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,150, -0174fc233104c2ad4f56a8396b8c1b7d9c6ad10bffc70761c5e8f5280862f137029733a9f20a4cdbb7ae9c5dd1adf6ccc7fe3439d7dc71093af0656ae0ca0f290964773f12e2292f332306374f957d10,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,150,invalid input parameters, invalid input length -,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,150, -67376aad340c93eb0fc9bc8e040dc691bd00e426c6456b4d13079e7f1dbb3da847eb0fc271cd23da50c6ebc261928abb1af9bfcea998791e18af1817b06221e1fe708d2f4224275523fcd37460a310ce4b56f1694dfe36280410f0fb6efc5f47b85662e5b08d881242a72acbc2c8e2fa71ac593be977ad3e090c8158aace0247,,150,invalid input parameters, invalid point: point is not on curve +1234,,150,invalid input parameters, invalid point encoding +0174fc233104c2ad4f56a8396b8c1b7d9c6ad10bffc70761c5e8f5280862f137029733a9f20a4cdbb7ae9c5dd1adf6ccc7fe3439d7dc71093af0656ae0ca0f290964773f12e2292f332306374f957d10,,150,invalid input parameters, invalid point encoding +0174fc233104c2ad4f56a8396b8c1b7d9c6ad10bffc70761c5e8f5280862f137029733a9f20a4cdbb7ae9c5dd1adf6ccc7fe3439d7dc71093af0656ae0ca0f290964773f12e2292f332306374f957d10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,150,invalid input parameters, point is not on curve +67376aad340c93eb0fc9bc8e040dc691bd00e426c6456b4d13079e7f1dbb3da847eb0fc271cd23da50c6ebc261928abb1af9bfcea998791e18af1817b06221e1fe708d2f4224275523fcd37460a310ce4b56f1694dfe36280410f0fb6efc5f47b85662e5b08d881242a72acbc2c8e2fa71ac593be977ad3e090c8158aace0247,,150,invalid input parameters, point not in field +,,150, +ff000000000000000000000000000000000000000000000000000000000000ff,,150,invalid input parameters, invalid point encoding +1470b80a6d5de1470aeadfa0b2eb913d9286bd966aa8a99b09879f3b10c985d02432b8ccd7083d421127dac6ad90bd569e763810e32d37114a786c7645864647,1470b80a6d5de1470aeadfa0b2eb913d9286bd966aa8a99b09879f3b10c985d02432b8ccd7083d421127dac6ad90bd569e763810e32d37114a786c7645864647,150, diff --git a/gnark/src/test/resources/org/hyperledger/besu/nativelib/gnark/eip196_g1_mul.csv b/gnark/src/test/resources/org/hyperledger/besu/nativelib/gnark/eip196_g1_mul.csv index db45d743..57bdafcd 100644 --- a/gnark/src/test/resources/org/hyperledger/besu/nativelib/gnark/eip196_g1_mul.csv +++ b/gnark/src/test/resources/org/hyperledger/besu/nativelib/gnark/eip196_g1_mul.csv @@ -99,8 +99,9 @@ input,result,gas,notes 03543b804e15103d27c9af197c39630f9f7a6298f210d13792aa674887a899da02423e72c6a7c0e2219edff2d0d76712061ee1e25fda4032b42aba0864fbe48dfd23d4b56a023e64b373fd416904c4d228a50a2f3411fcafbfec6bff70a7ad36,03c8141c0a5b155ce03b928d984018792fd0d984b8a46b81d35df79fc31d24d508a701df38a3e1ec3508d190e2a748d9055f594a2dc80dbb26ea6850c3039b09,6000, 1c2cb2b4504b19c7e073679432e625f2706b7c4728cd9bd3ce36579f4de2f3902c8605f723ac2f73baa15eac674f62ab06c79809aa4a4be3391c4d41d5a6e62ca0a73a5b559cd0384ca11d444e34f40e04f2080483db9e54ae09e44ec19c26a1,1147da8fc5774b5ef94fda682437b04f9b6aea72987d1269496769baf7e67dc729fe144eab44c6da4c851123165cd6506ce3e10b7691b8bf11b757e2ae058fcb,6000, 0d6ad8e12b4f61e3e2a2252ce11428941f2a84b7f0a821cb8cc7699303bd4fec2247870562618fd8d6169072d9b33614d2acf800b3ba0ff68ef8d5fd4d6c250d3e70b3bed17894f958579644c83fa9d485121d580e2b061c697e68f950297768,0be6d75e2fe2887835d396dae11321ca7c53083abd6a0b270ee1c087593517aa2ffd1bad577de7cf2b19b82bfff0c66e2afbfb79a72cbe834290437f3caf2f21,6000, -d2acf800b3ba0ff68ef8d5fd4d6c250d3e70b3bed17894f958579644c83fa9d485121d580e2b061c697e68f9502977680d6ad8e12b4f61e3e2a2252ce11428941f2a84b7f0a821cb8cc7699303bd4fec2247870562618fd8d6169072d9b33614,,6000,invalid compressed coordinate -1c2cb2b4504b19c7e073679432e625f2706b7c4728cd9bd3ce36579f4de2f3902c8605f723ac2f73baa15eac674f62ab,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,6000, -,00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,6000, +d2acf800b3ba0ff68ef8d5fd4d6c250d3e70b3bed17894f958579644c83fa9d485121d580e2b061c697e68f9502977680d6ad8e12b4f61e3e2a2252ce11428941f2a84b7f0a821cb8cc7699303bd4fec2247870562618fd8d6169072d9b33614,,6000,invalid input parameters, point not in field +02acf800b3ba0ff68ef8d5fd4d6c250d3e70b3bed17894f958579644c83fa9d405121d580e2b061c697e68f9502977680d6ad8e12b4f61e3e2a2252ce11428941f2a84b7f0a821cb8cc7699303bd4fec2247870562618fd8d6169072d9b33614,,6000,invalid input parameters, point is not on curve +1c2cb2b4504b19c7e073679432e625f2706b7c4728cd9bd3ce36579f4de2f3902c8605f723ac2f73baa15eac674f62ab,,6000, +,,6000, 1A87B0584CE92F4593D161480614F2989035225609F08058CCFA3D0F940FEBE31A2F3C951F6DADCC7EE9007DFF81504B0FCD6D7CF59996EFDC33D92BF7F9F8F60100000000000000000000000000000000,0x220cb1540fa85ba04d863dca86de9359a43ac9fc084aebb9f2a936d989abbb602ccdc6c020dd2cf78332132b3f1d1122391b515035623cd6f53d4aea24ea2466,6000, 1A87B0584CE92F4593D161480614F2989035225609F08058CCFA3D0F940FEBE31A2F3C951F6DADCC7EE9007DFF81504B0FCD6D7CF59996EFDC33D92BF7F9F8F60000000000000000000000000000000100000000000000000000000000000000,1051acb0700ec6d42a88215852d582efbaef31529b6fcbc3277b5c1b300f5cf0135b2394bb45ab04b8bd7611bd2dfe1de6a4e6e2ccea1ea1955f577cd66af85b,6000, From 010fc4e3fcf0812deedd65bbd6074a97d0d96988 Mon Sep 17 00:00:00 2001 From: garyschulte Date: Tue, 9 Jul 2024 23:21:01 -0700 Subject: [PATCH 3/3] guardrail buffer sizes Signed-off-by: garyschulte --- gnark/gnark-jni/gnark-eip-196.go | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/gnark/gnark-jni/gnark-eip-196.go b/gnark/gnark-jni/gnark-eip-196.go index f87e718b..6aac2bb7 100644 --- a/gnark/gnark-jni/gnark-eip-196.go +++ b/gnark/gnark-jni/gnark-eip-196.go @@ -50,7 +50,7 @@ func eip196altbn128G1Add(javaInputBuf, javaOutputBuf, javaErrorBuf *C.char, cInp outputLen := (*int)(unsafe.Pointer(cOutputLen)) // Convert error C pointers to Go slices - errorBuf := castErrorBufferEIP196(javaErrorBuf, *errorLen) + errorBuf := castErrorBufferEIP196(javaErrorBuf, errorLen) if (inputLen > 2*EIP196PreallocateForG1) { // trunc if input too long @@ -108,7 +108,7 @@ func eip196altbn128G1Mul(javaInputBuf, javaOutputBuf, javaErrorBuf *C.char, cInp outputLen := (*int)(unsafe.Pointer(cOutputLen)) // Convert error C pointers to Go slices - errorBuf := castErrorBufferEIP196(javaErrorBuf, *errorLen) + errorBuf := castErrorBufferEIP196(javaErrorBuf, errorLen) if inputLen < EIP196PreallocateForG1 { // if we do not have complete input, return 0 @@ -160,10 +160,10 @@ func eip196altbn128Pairing(javaInputBuf, javaOutputBuf, javaErrorBuf *C.char, cI outputLen := (*int)(unsafe.Pointer(cOutputLen)) // Convert error C pointers to Go slices - output := castBufferEIP196(javaOutputBuf, *outputLen) + output := castBufferEIP196(javaOutputBuf, outputLen) // Convert error C pointers to Go slices - errorBuf := castErrorBufferEIP196(javaErrorBuf, *errorLen) + errorBuf := castErrorBufferEIP196(javaErrorBuf, errorLen) *outputLen = 32 @@ -312,17 +312,17 @@ func castBufferToSliceEIP196(buf unsafe.Pointer, length int) []byte { return slice } -func castBufferEIP196(javaOutputBuf *C.char, length int) []byte { - bufSize := length - if bufSize < EIP196PreallocateForResult { +func castBufferEIP196(javaOutputBuf *C.char, length *int) []byte { + bufSize := *length + if bufSize != EIP196PreallocateForResult { bufSize = EIP196PreallocateForResult } return (*[EIP196PreallocateForResult]byte)(unsafe.Pointer(javaOutputBuf))[:bufSize:bufSize] } -func castErrorBufferEIP196(javaOutputBuf *C.char, length int) []byte { - bufSize := length - if bufSize < EIP196PreallocateForError { +func castErrorBufferEIP196(javaOutputBuf *C.char, length *int) []byte { + bufSize := *length + if bufSize != EIP196PreallocateForError { bufSize = EIP196PreallocateForError } return (*[EIP196PreallocateForError]byte)(unsafe.Pointer(javaOutputBuf))[:bufSize:bufSize]