Skip to content

Commit

Permalink
Fix proxy return rule at least on john branch
Browse files Browse the repository at this point in the history
  • Loading branch information
nivcertora committed Jun 10, 2024
1 parent ccab47a commit 021d60d
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 3 deletions.
4 changes: 4 additions & 0 deletions certora/confs/ProxySimulator.conf
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
"modules/passkey/contracts/SafeWebAuthnSignerProxy.sol",
"modules/passkey/contracts/SafeWebAuthnSignerSingleton.sol",
"modules/passkey/contracts/libraries/P256.sol",
"modules/passkey/contracts/libraries/WebAuthn.sol",
"certora/harnesses/WebAuthnHarness.sol",

],
"link": [
"ProxySimulator:_proxy=SafeWebAuthnSignerProxy",
Expand All @@ -20,6 +23,7 @@
"optimistic_loop": true,
"loop_iter": "6",
"optimistic_hashing": true,
"hashing_length_bound": "2048",
"rule_sanity": "basic",
"verify": "ProxySimulator:certora/specs/ProxySimulator.spec"
}
36 changes: 33 additions & 3 deletions certora/specs/ProxySimulator.spec
Original file line number Diff line number Diff line change
@@ -1,19 +1,49 @@
using SafeWebAuthnSignerProxy as SafeWebAuthnSignerProxy;
using WebAuthnHarness as WebAuthnHarness;

methods {
function P256.verifySignatureAllowMalleability(P256.Verifiers a, bytes32 b, uint256 c, uint256 d, uint256 e, uint256 f) internal returns (bool) =>
verifySignatureAllowMalleabilityGhost(a, b, c, d, e, f);

function WebAuthn.encodeSigningMessage(bytes32 challenge, bytes calldata authenticatorData, string calldata clientDataFields) internal returns (bytes memory) =>
GETencodeSigningMessageCVL(challenge, authenticatorData, clientDataFields);

function WebAuthnHarness.checkInjective(bytes32 challenge, bytes32 authenticatorData, bytes32 clientDataFields, bytes32 result) internal returns (bool) =>
checkInjectiveSummary(challenge, authenticatorData, clientDataFields, result);
}

function GETencodeSigningMessageCVL(bytes32 challenge, bytes authenticatorData, string clientDataFields) returns bytes
{
env e;
return WebAuthnHarness.GETencodeSigningMessageSummary(e, challenge, authenticatorData, clientDataFields);
}

ghost checkInjectiveSummary(bytes32, bytes32, bytes32, bytes32) returns bool {
axiom forall bytes32 x1. forall bytes32 y1. forall bytes32 z1. forall bytes32 x2. forall bytes32 y2. forall bytes32 z2. forall bytes32 result.
checkInjectiveSummary(x1, y1, z1, result) && checkInjectiveSummary(x2, y2, z2, result) => x1 == x2;
}

ghost verifySignatureAllowMalleabilityGhost(P256.Verifiers, bytes32, uint256, uint256, uint256, uint256) returns bool {
axiom forall P256.Verifiers a. forall bytes32 message1. forall bytes32 message2. forall uint256 c. forall uint256 d. forall uint256 e. forall uint256 f.
verifySignatureAllowMalleabilityGhost(a, message1, c, d, e, f) &&
verifySignatureAllowMalleabilityGhost(a, message2, c, d, e, f) => message1 == message2;
}

// This is the same MAGIC_VALUE constant used in ERC1271.
definition MAGIC_VALUE() returns bytes4 = to_bytes4(0x1626ba7e);

methods {
function authenticate(bytes32, bytes) external returns (bytes4) envfree;
function _._ external => DISPATCH [
SafeWebAuthnSignerProxy._
SafeWebAuthnSignerProxy._,
SafeWebAuthnSignerSingleton._
] default NONDET;
}

/*
Property 14. Proxy - verify return data from the fallback is only one of the magicNumbers
Uses another contract that simulates interaction with the proxy. The reason is that the prover doesn't check all
possible calldata values so this simualtion will make the prover choose different values that will be passed on the calldata.
possible calldata values so this simulation will make the prover choose different values that will be passed on the calldata.
Rule stuck.
*/
rule proxyReturnValue {
Expand All @@ -22,5 +52,5 @@ rule proxyReturnValue {

bytes4 ret = authenticate(message, signature);

assert ret == MAGIC_VALUE();
satisfy ret == MAGIC_VALUE() || ret == to_bytes4(0);
}

0 comments on commit 021d60d

Please sign in to comment.