Skip to content

Commit

Permalink
Add webAuth rules
Browse files Browse the repository at this point in the history
  • Loading branch information
nivcertora committed May 27, 2024
1 parent dca8c02 commit bf0ff62
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 4 deletions.
4 changes: 1 addition & 3 deletions certora/confs/WebAuthn.conf
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
{
"assert_autofinder_success": true,
"files": [
"certora/harnesses/WebAuthnHarness.sol",
"certora/harnesses/ERC20Like/DummyWeth.sol",
"certora/harnesses/Utilities.sol",
"certora/harnesses/WebAuthnHarness.sol"
],
"java_args": [
" -ea -Dlevel.setup.helpers=info"
Expand Down
16 changes: 16 additions & 0 deletions certora/harnesses/WebAuthnHarness.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,22 @@ contract WebAuthnHarness {
return true;
}

function compareSignatures(WebAuthn.Signature memory sig1, WebAuthn.Signature memory sig2) public pure returns (bool) {
if (sig1.r != sig2.r || sig1.s != sig2.s) {
return false;
}

if (keccak256(abi.encodePacked(sig1.clientDataFields)) != keccak256(abi.encodePacked(sig2.clientDataFields))) {
return false;
}

if (keccak256(sig1.authenticatorData) != keccak256(sig2.authenticatorData)) {
return false;
}

return true;
}

function castSignature(bytes calldata signature) external pure returns (bool isValid, WebAuthn.Signature calldata data){
return WebAuthn.castSignature(signature);
}
Expand Down
63 changes: 62 additions & 1 deletion certora/specs/WebAuthn.spec
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ methods{
encodeAxiomSummary(message, signature, result);

//function encodeSigningMessage(bytes32,bytes calldata,string calldata) internal returns(bytes memory) => NONDET;
function castSignature(bytes calldata signature) external returns (bool, WebAuthn.Signature calldata);
}

function getEncodeClientDataJsonSummaryCVL(bytes32 message, string signature) returns string
Expand Down Expand Up @@ -75,7 +76,7 @@ rule uniqueMessagePerChallenge(){

/*
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
verifySignature functions are equivalent
verifySignature functions are equivalent (Vacuity check timeout cert-6290)
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
*/
rule verifySignatureEq(){
Expand Down Expand Up @@ -109,5 +110,65 @@ rule verifySignatureEq(){
assert (firstCallRevert == secondCallRevert) || (result1 == result2);
}

/*
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
CastSignature Consistent (Once valid always valid, Once failed always failed, includes revert cases and middle call)|
│ (Proved) |
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
*/

rule castSignatureConsistent(){
env e;
method f;
calldataarg args;

bytes signature;

bool firstIsValid;
WebAuthn.Signature firstData;

bool secondIsValid;
WebAuthn.Signature secondData;

firstIsValid, firstData = castSignature@withrevert(e, signature);
bool firstRevert = lastReverted;

f(e, args);

secondIsValid, secondData = castSignature@withrevert(e, signature);
bool secondRevert = lastReverted;

if (!firstRevert && !secondRevert) {
assert compareSignatures(e, firstData, secondData) && firstIsValid == secondIsValid;
}

assert firstRevert == secondRevert;
}


/*
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
CastSignature uniqueness (violated) |
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
*/

rule castSignatureUniqueness(){

env e;

bytes signature1;
bytes signature2;

bool firstIsValid;
WebAuthn.Signature firstData;

bool secondIsValid;
WebAuthn.Signature secondData;

firstIsValid, firstData = castSignature(e, signature1);

secondIsValid, secondData = castSignature(e, signature2);

assert (getSha256(e, signature1) != getSha256(e, signature2)) &&
((firstIsValid && secondIsValid)) => !compareSignatures(e, firstData, secondData);
}

0 comments on commit bf0ff62

Please sign in to comment.