diff --git a/contracts/certificate/signers/CECDSASHA2Signer.sol b/contracts/certificate/signers/CECDSASHA2Signer.sol index fefbae1..e55ab54 100644 --- a/contracts/certificate/signers/CECDSASHA2Signer.sol +++ b/contracts/certificate/signers/CECDSASHA2Signer.sol @@ -131,11 +131,11 @@ contract CECDSASHA2Signer is ICertificateSigner, Initializable { uint256 RHS = U384.modexp(call, x, 3, p); if (!U384.eqInteger(a, 0)) { - RHS = U384.modadd(call, RHS, U384.modmul(call, x, a, p), p); // x^3 + a*x + RHS = U384.modadd(RHS, U384.modmul(call, x, a, p), p); // x^3 + a*x } if (!U384.eqInteger(b, 0)) { - RHS = U384.modadd(call, RHS, b, p); // x^3 + a*x + b + RHS = U384.modadd(RHS, b, p); // x^3 + a*x + b } return U384.eq(LHS, RHS); @@ -260,11 +260,11 @@ contract CECDSASHA2Signer is ICertificateSigner, Initializable { } uint256 u = U384.modmul(call, y0, z0, p); - U384.modshl1Assign(call, u, p); + U384.modshl1Assign(u, p); x1 = U384.modmul(call, u, x0, p); U384.modmulAssign(call, x1, y0, p); - U384.modshl1Assign(call, x1, p); + U384.modshl1Assign(x1, p); x0 = U384.modexp(call, x0, 2, p); @@ -272,24 +272,24 @@ contract CECDSASHA2Signer is ICertificateSigner, Initializable { z0 = U384.modexp(call, z0, 2, p); U384.modmulAssign(call, z0, a, p); - U384.modaddAssign(call, y1, z0, p); + U384.modaddAssign(y1, z0, p); z1 = U384.modexp(call, y1, 2, p); - U384.modshl1AssignTo(call, x0, x1, p); + U384.modshl1AssignTo(x0, x1, p); uint256 diff = U384.sub(p, x0); - U384.modaddAssign(call, z1, diff, p); + U384.modaddAssign(z1, diff, p); U384.subAssignTo(diff, p, z1); - U384.modaddAssignTo(call, x0, x1, diff, p); + U384.modaddAssignTo(x0, x1, diff, p); U384.modmulAssign(call, x0, y1, p); y0 = U384.modmul(call, y0, u, p); U384.modexpAssign(call, y0, 2, p); - U384.modshl1Assign(call, y0, p); + U384.modshl1Assign(y0, p); U384.subAssignTo(diff, p, y0); - U384.modaddAssignTo(call, y1, x0, diff, p); + U384.modaddAssignTo(y1, x0, diff, p); U384.modmulAssignTo(call, x1, u, z1, p); @@ -354,19 +354,19 @@ contract CECDSASHA2Signer is ICertificateSigner, Initializable { ) internal view returns (uint256 x2, uint256 y2, uint256 z2) { unchecked { uint256 diff = U384.sub(p, t1); - y2 = U384.modadd(call, t0, diff, p); + y2 = U384.modadd(t0, diff, p); U384.subAssignTo(diff, p, u1); - x2 = U384.modadd(call, u0, diff, p); + x2 = U384.modadd(u0, diff, p); uint256 u2 = U384.modexp(call, x2, 2, p); z2 = U384.modexp(call, y2, 2, p); U384.modmulAssign(call, z2, v, p); - u1 = U384.modadd(call, u1, u0, p); + u1 = U384.modadd(u1, u0, p); U384.modmulAssign(call, u1, u2, p); U384.subAssignTo(diff, p, u1); - U384.modaddAssign(call, z2, diff, p); + U384.modaddAssign(z2, diff, p); uint256 u3 = U384.modmul(call, u2, x2, p); @@ -375,12 +375,12 @@ contract CECDSASHA2Signer is ICertificateSigner, Initializable { u0 = U384.modmul(call, u0, u2, p); U384.subAssignTo(diff, p, z2); - U384.modaddAssign(call, u0, diff, p); + U384.modaddAssign(u0, diff, p); U384.modmulAssign(call, y2, u0, p); t0 = U384.modmul(call, t0, u3, p); U384.subAssignTo(diff, p, t0); - U384.modaddAssign(call, y2, diff, p); + U384.modaddAssign(y2, diff, p); U384.modmulAssignTo(call, z2, u3, v, p); } diff --git a/contracts/utils/U384.sol b/contracts/utils/U384.sol index d4f0716..2910100 100644 --- a/contracts/utils/U384.sol +++ b/contracts/utils/U384.sol @@ -224,68 +224,36 @@ library U384 { } } - function modadd( - uint256 call_, - uint256 a_, - uint256 b_, - uint256 m_ - ) internal view returns (uint256 r_) { + function modadd(uint256 a_, uint256 b_, uint256 m_) internal view returns (uint256 r_) { unchecked { r_ = _allocate(SHORT_ALLOCATION); - _add(a_, b_, call_ + 0x60); - - assembly { - mstore(call_, 0x40) - mstore(add(0x20, call_), 0x20) - mstore(add(0x40, call_), 0x40) - mstore(add(0xA0, call_), 0x01) - mstore(add(0xC0, call_), mload(m_)) - mstore(add(0xE0, call_), mload(add(m_, 0x20))) + _add(a_, b_, r_); - pop(staticcall(gas(), 0x5, call_, 0x0100, r_, 0x40)) + if (cmp(r_, m_) >= 0) { + _subFrom(r_, m_); } return r_; } } - function modaddAssign(uint256 call_, uint256 a_, uint256 b_, uint256 m_) internal view { + function modaddAssign(uint256 a_, uint256 b_, uint256 m_) internal view { unchecked { - _add(a_, b_, call_ + 0x60); - - assembly { - mstore(call_, 0x40) - mstore(add(0x20, call_), 0x20) - mstore(add(0x40, call_), 0x40) - mstore(add(0xA0, call_), 0x01) - mstore(add(0xC0, call_), mload(m_)) - mstore(add(0xE0, call_), mload(add(m_, 0x20))) + _addTo(a_, b_); - pop(staticcall(gas(), 0x5, call_, 0x0100, a_, 0x40)) + if (cmp(a_, m_) >= 0) { + return _subFrom(a_, m_); } } } - function modaddAssignTo( - uint256 call_, - uint256 to_, - uint256 a_, - uint256 b_, - uint256 m_ - ) internal view { + function modaddAssignTo(uint256 to_, uint256 a_, uint256 b_, uint256 m_) internal view { unchecked { - _add(a_, b_, call_ + 0x60); + _add(a_, b_, to_); - assembly { - mstore(call_, 0x40) - mstore(add(0x20, call_), 0x20) - mstore(add(0x40, call_), 0x40) - mstore(add(0xA0, call_), 0x01) - mstore(add(0xC0, call_), mload(m_)) - mstore(add(0xE0, call_), mload(add(m_, 0x20))) - - pop(staticcall(gas(), 0x5, call_, 0x0100, to_, 0x40)) + if (cmp(to_, m_) >= 0) { + return _subFrom(to_, m_); } } } @@ -479,55 +447,36 @@ library U384 { } } - function modshl1(uint256 call_, uint256 a_, uint256 m_) internal view returns (uint256 r_) { + function modshl1(uint256 a_, uint256 m_) internal view returns (uint256 r_) { unchecked { r_ = _allocate(SHORT_ALLOCATION); - _shl1(a_, call_ + 0x60); + _shl1(a_, r_); - assembly { - mstore(call_, 0x40) - mstore(add(0x20, call_), 0x20) - mstore(add(0x40, call_), 0x40) - mstore(add(0xA0, call_), 0x01) - mstore(add(0xC0, call_), mload(m_)) - mstore(add(0xE0, call_), mload(add(m_, 0x20))) - - pop(staticcall(gas(), 0x5, call_, 0x0100, r_, 0x40)) + if (cmp(r_, m_) >= 0) { + _subFrom(r_, m_); } + + return r_; } } - function modshl1Assign(uint256 call_, uint256 a_, uint256 m_) internal view { + function modshl1Assign(uint256 a_, uint256 m_) internal view { unchecked { - _shl1(a_, call_ + 0x60); - - assembly { - mstore(call_, 0x40) - mstore(add(0x20, call_), 0x20) - mstore(add(0x40, call_), 0x40) - mstore(add(0xA0, call_), 0x01) - mstore(add(0xC0, call_), mload(m_)) - mstore(add(0xE0, call_), mload(add(m_, 0x20))) + _shl1To(a_); - pop(staticcall(gas(), 0x5, call_, 0x0100, a_, 0x40)) + if (cmp(a_, m_) >= 0) { + _subFrom(a_, m_); } } } - function modshl1AssignTo(uint256 call_, uint256 to_, uint256 a_, uint256 m_) internal view { + function modshl1AssignTo(uint256 to_, uint256 a_, uint256 m_) internal view { unchecked { - _shl1(a_, call_ + 0x60); + _shl1(a_, to_); - assembly { - mstore(call_, 0x40) - mstore(add(0x20, call_), 0x20) - mstore(add(0x40, call_), 0x40) - mstore(add(0xA0, call_), 0x01) - mstore(add(0xC0, call_), mload(m_)) - mstore(add(0xE0, call_), mload(add(m_, 0x20))) - - pop(staticcall(gas(), 0x5, call_, 0x0100, to_, 0x40)) + if (cmp(to_, m_) >= 0) { + _subFrom(to_, m_); } } } @@ -542,6 +491,16 @@ library U384 { } } + function _shl1To(uint256 a_) internal pure { + assembly { + let a0_ := mload(a_) + let a1_ := mload(add(a_, 0x20)) + + mstore(a_, or(shl(1, a0_), shr(255, a1_))) + mstore(add(a_, 0x20), shl(1, a1_)) + } + } + function _add(uint256 a_, uint256 b_, uint256 r_) private pure { assembly { let aWord_ := mload(add(a_, 0x20)) @@ -570,6 +529,34 @@ library U384 { } } + function _subFrom(uint256 a_, uint256 b_) private pure { + assembly { + let aWord_ := mload(add(a_, 0x20)) + let diff_ := sub(aWord_, mload(add(b_, 0x20))) + + mstore(add(a_, 0x20), diff_) + + diff_ := gt(diff_, aWord_) + diff_ := sub(sub(mload(a_), mload(b_)), diff_) + + mstore(a_, diff_) + } + } + + function _addTo(uint256 a_, uint256 b_) private pure { + assembly { + let aWord_ := mload(add(a_, 0x20)) + let sum_ := add(aWord_, mload(add(b_, 0x20))) + + mstore(add(a_, 0x20), sum_) + + sum_ := gt(aWord_, sum_) + sum_ := add(sum_, add(mload(a_), mload(b_))) + + mstore(a_, sum_) + } + } + function _mul(uint256 a_, uint256 b_, uint256 r_) private view { assembly { let a0_ := mload(a_) diff --git a/hardhat.config.ts b/hardhat.config.ts index 075123f..5ae7fdb 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -151,7 +151,7 @@ const config: HardhatUserConfig = { gasReporter: { currency: "USD", gasPrice: 50, - enabled: false, + enabled: true, reportPureAndViewMethods: true, coinmarketcap: `${process.env.COINMARKETCAP_KEY}`, }, diff --git a/test/certificate/signers/CECDSASHA2Signer.test.ts b/test/certificate/signers/CECDSASHA2Signer.test.ts index 970356d..2ce1789 100644 --- a/test/certificate/signers/CECDSASHA2Signer.test.ts +++ b/test/certificate/signers/CECDSASHA2Signer.test.ts @@ -21,7 +21,7 @@ describe("CECDSASHA2Signer", () => { afterEach(reverter.revert); - describe("#verifyICAOSignature", () => { + describe.only("#verifyICAOSignature", () => { it("should verify icao signature using SHA2", async () => { const signedAttributes = "0x308203cfa0030201020204492f01a0300a06082a8648ce3d0403023041310b3009060355040613024742310e300c060355040a1305554b4b50413122302006035504031319436f756e747279205369676e696e6720417574686f72697479301e170d3232303830313030303030305a170d3333313230313030303030305a305c310b3009060355040613024742311b3019060355040a1312484d2050617373706f7274204f6666696365310f300d060355040b13064c6f6e646f6e311f301d06035504031316446f63756d656e74205369676e696e67204b657920363082014b3082010306072a8648ce3d02013081f7020101302c06072a8648ce3d0101022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff305b0420ffffffff00000001000000000000000000000000fffffffffffffffffffffffc04205ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b031500c49d360886e704936a6678e1139d26b7819f7e900441046b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63255102010103420004369b6087115805a184e0a04e522acc1c58959aa0c9b19d80c8dd293fdd504ec0675381123b71874d105693f18105022fe4eb9ac7c2dfbcdcc58cbd7351d263d4a38201a4308201a030420603551d11043b30398125646f63756d656e742e746563686e6f6c6f677940686f6d656f66666963652e676f762e756ba410300e310c300a06035504071303474252302b0603551d1004243022800f32303232303830313030303030305a810f32303232313130343030303030305a300e0603551d0f0101ff04040302078030630603551d12045c305aa410300e310c300a06035504071303474252811f646f63756d656e742e746563686e6f6c6f677940686d706f2e676f762e756b8125646f63756d656e742e746563686e6f6c6f677940686f6d656f66666963652e676f762e756b3019060767810801010602040e300c020100310713015013025054305d0603551d1f045630543052a050a04e862068747470733a2f2f686d706f2e676f762e756b2f637363612f4742522e63726c862a68747470733a2f2f706b64646f776e6c6f6164312e6963616f2e696e742f43524c732f4742522e63726c301f0603551d23041830168014499e4730278520c57cfc118024e14c1562a249d6301d0603551d0e0416041439b5abb7415fb8629b55c137d12a01c35fb49486";