• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

safe-global / safe-modules / 8143150668

04 Mar 2024 03:57PM UTC coverage: 64.706% (-35.3%) from 100.0%
8143150668

Pull #298

github

mmv08
Merge branch 'main' of github.com:safe-global/safe-modules into 286-introduce-p256-verifier-contract
Pull Request #298: Introduce P-256 Verifier Contract

2 of 4 branches covered (50.0%)

Branch coverage included in aggregate %.

9 of 13 new or added lines in 2 files covered. (69.23%)

9 of 13 relevant lines covered (69.23%)

2.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/modules/passkey/contracts/verifiers/IP256Verifier.sol
1
// SPDX-License-Identifier: LGPL-3.0-only
2
/* solhint-disable payable-fallback */
3
pragma solidity ^0.8.0;
4

5
/**
6
 * @title P-256 Elliptic Curve Verifier.
7
 * @dev P-256 verifier contract that follows the EIP-7212 EC verify precompile interface. For more
8
 * details, refer to the EIP-7212 specification: <https://eips.ethereum.org/EIPS/eip-7212>
9
 * @custom:security-contact bounty@safe.global
10
 */
11
interface IP256Verifier {
12
    /**
13
     * @notice  A fallback function that takes the following input format and returns a result
14
     * indicating whether the signature is valid or not:
15
     * - `input[  0: 32]`: message
16
     * - `input[ 32: 64]`: signature r
17
     * - `input[ 64: 96]`: signature s
18
     * - `input[ 96:128]`: public key x
19
     * - `input[128:160]`: public key y
20
     *
21
     * The output is a Solidity ABI encoded boolean value indicating whether or not the signature is
22
     * valid. Specifically, it returns 32 bytes with a value of `0x00..00` or `0x00..01` for an
23
     * invalid or valid signature respectively.
24
     *
25
     * Note that this function does not follow the Solidity ABI format (in particular, it does not
26
     * have a 4-byte selector), which is why it requires a fallback function and not regular
27
     * Solidity function. Additionally, it has `view` function semantics, and is expected to be
28
     * called with `STATICCALL` opcode.
29
     *
30
     * @param input The encoded input parameters.
31
     * @return output The encoded signature verification result.
32
     */
33
    fallback(bytes calldata input) external returns (bytes memory output);
34
}
35

36
/**
37
 * @title P-256 Elliptic Curve Verifier.
38
 * @dev P-256 verifier contract that follows the EIP-7212 EC verify precompile interface. For more
39
 * details, refer to the EIP-7212 specification: <https://eips.ethereum.org/EIPS/eip-7212>
40
 */
41
library P256VerifierLib {
42
    /**
43
     * @notice P-256 curve order n divided by 2 for the signature malleability check.
44
     * @dev By convention, non-malleable signatures must have an `s` value that is less than half of
45
     * the curve order.
46
     */
47
    uint256 internal constant _N_DIV_2 = 57896044605178124381348723474703786764998477612067880171211129530534256022184;
48

49
    /**
50
     * @notice Verifies the signature of a message using the P256 elliptic curve with signature
51
     * malleability check.
52
     * @dev Note that a signature is valid for both `+s` and `-s`, making it trivial to, given a
53
     * signature, generate another valid signature by flipping the sign of the `s` value in the
54
     * prime field defined by the P-256 curve order `n`. This signature verification method checks
55
     * that `1 <= s <= n/2` to prevent malleability, such that there is a unique `s` value that is
56
     * accepted for a given signature. Note that for many protocols, signature malleability is not
57
     * an issue, so the use of {verifySignatureAllowMalleability} as long as only that the signature
58
     * is valid is important, and not its actual value.
59
     * @param verifier The P-256 verifier.
60
     * @param message The signed message.
61
     * @param r The r component of the signature.
62
     * @param s The s component of the signature.
63
     * @param x The x coordinate of the public key.
64
     * @param y The y coordinate of the public key.
65
     * @return success A boolean indicating whether the signature is valid or not.
66
     */
67
    function verifySignature(
68
        IP256Verifier verifier,
69
        bytes32 message,
70
        uint256 r,
71
        uint256 s,
72
        uint256 x,
73
        uint256 y
74
    ) internal view returns (bool success) {
NEW
75
        if (s > _N_DIV_2) {
×
NEW
76
            return false;
×
77
        }
78

NEW
79
        success = verifySignatureAllowMalleability(verifier, message, r, s, x, y);
×
80
    }
81

82
    /**
83
     * @notice Verifies the signature of a message using P256 elliptic curve, without signature
84
     * malleability check.
85
     * @param verifier The P-256 verifier.
86
     * @param message The signed message.
87
     * @param r The r component of the signature.
88
     * @param s The s component of the signature.
89
     * @param x The x coordinate of the public key.
90
     * @param y The y coordinate of the public key.
91
     * @return success A boolean indicating whether the signature is valid or not.
92
     */
93
    function verifySignatureAllowMalleability(
94
        IP256Verifier verifier,
95
        bytes32 message,
96
        uint256 r,
97
        uint256 s,
98
        uint256 x,
99
        uint256 y
100
    ) internal view returns (bool success) {
101
        // solhint-disable-next-line no-inline-assembly
NEW
102
        assembly ("memory-safe") {
×
103
            // Prepare input for staticcall
104
            let input := mload(0x40) // Free memory pointer
105
            mstore(input, message)
106
            mstore(add(input, 32), r)
107
            mstore(add(input, 64), s)
108
            mstore(add(input, 96), x)
109
            mstore(add(input, 128), y)
110

111
            // Perform staticcall
112
            success := staticcall(gas(), verifier, input, 160, 0, 32)
113

114
            // Check for success and return value
115
            if iszero(and(success, eq(returndatasize(), 32))) {
116
                revert(0, 0)
117
            }
118
            success := mload(0)
119
        }
120
    }
121
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc