Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add util to normalize s values #15

Merged
merged 1 commit into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .gas-snapshot
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
WebAuthnFuzzTest:test_Verify_ShoulReturnFalse_WhenSAboveP256_N_DIV_2() (gas: 429635068)
WebAuthnFuzzTest:test_Verify_ShoulReturnFalse_WhenTheUpFlagIsNotSet() (gas: 435226970)
WebAuthnFuzzTest:test_Verify_ShoulReturnFalse_WhenUserVerifictionIsRequiredButTestWasNotPerformed() (gas: 432526116)
WebAuthnFuzzTest:test_Verify_ShoulReturnTrue_WhenSBelowP256_N_DIV_2() (gas: 456215767)
WebAuthnFuzzTest:test_Verify_ShoulReturnFalse_WhenTheUpFlagIsNotSet() (gas: 435310864)
WebAuthnFuzzTest:test_Verify_ShoulReturnFalse_WhenUserVerifictionIsRequiredButTestWasNotPerformed() (gas: 432573571)
WebAuthnFuzzTest:test_Verify_ShoulReturnTrue_WhenSBelowP256_N_DIV_2() (gas: 456300088)
WebAuthnTest:test_chrome() (gas: 225627)
WebAuthnTest:test_safari() (gas: 221874)
13 changes: 13 additions & 0 deletions test/Utils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
pragma solidity ^0.8.0;

import {Base64Url} from "FreshCryptoLib/utils/Base64Url.sol";
import {FCL_Elliptic_ZZ} from "FreshCryptoLib/FCL_elliptic.sol";

struct WebAuthnInfo {
bytes authenticatorData;
Expand All @@ -10,6 +11,8 @@ struct WebAuthnInfo {
}

library Utils {
uint256 constant P256_N_DIV_2 = FCL_Elliptic_ZZ.n / 2;

function getWebAuthnStruct(bytes32 challenge) public pure returns (WebAuthnInfo memory) {
string memory challengeb64url = Base64Url.encode(abi.encode(challenge));
string memory clientDataJSON = string(
Expand All @@ -28,4 +31,14 @@ library Utils {

return WebAuthnInfo(authenticatorData, clientDataJSON, messageHash);
}

/// @dev normalizes the s value from a p256r1 signature so that
/// it will pass malleability checks.
function normalizeS(uint256 s) public pure returns (uint256) {
if (s > P256_N_DIV_2) {
return FCL_Elliptic_ZZ.n - s;
}

return s;
}
}
20 changes: 5 additions & 15 deletions test/Webauthn.fuzz.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,17 @@
pragma solidity ^0.8.0;

import {FCL_ecdsa} from "FreshCryptoLib/FCL_ecdsa.sol";
import {FCL_Elliptic_ZZ} from "FreshCryptoLib/FCL_elliptic.sol";

import {WebAuthn} from "../src/WebAuthn.sol";

import "forge-std/Test.sol";
import "./Utils.sol";

contract WebAuthnFuzzTest is Test {
using stdJson for string;

string constant testFile = "/test/fixtures/assertions_fixture.json";

uint256 private constant P256_N_DIV_2 = FCL_Elliptic_ZZ.n / 2;

/// @dev `WebAuthn.verify` should return `false` when `s` is above P256_N_DIV_2.
function test_Verify_ShoulReturnFalse_WhenSAboveP256_N_DIV_2() public {
string memory rootPath = vm.projectRoot();
Expand All @@ -35,7 +33,7 @@ contract WebAuthnFuzzTest is Test {
console.log("Veryfing", jsonCaseSelector);

// Only interested in s > P256_N_DIV_2 cases.
if (webAuthnAuth.s <= P256_N_DIV_2) {
if (webAuthnAuth.s <= Utils.P256_N_DIV_2) {
webAuthnAuth.s = FCL_ecdsa.n - webAuthnAuth.s;
}

Expand Down Expand Up @@ -67,10 +65,7 @@ contract WebAuthnFuzzTest is Test {

console.log("Veryfing", jsonCaseSelector);

// Only interested in s <= P256_N_DIV_2 case
if (webAuthnAuth.s > P256_N_DIV_2) {
webAuthnAuth.s = FCL_ecdsa.n - webAuthnAuth.s;
}
webAuthnAuth.s = Utils.normalizeS(webAuthnAuth.s);

// Unset the `up` flag.
webAuthnAuth.authenticatorData[32] = webAuthnAuth.authenticatorData[32] & bytes1(0xfe);
Expand Down Expand Up @@ -109,9 +104,7 @@ contract WebAuthnFuzzTest is Test {
continue;
}

if (webAuthnAuth.s > P256_N_DIV_2) {
webAuthnAuth.s = FCL_ecdsa.n - webAuthnAuth.s;
}
webAuthnAuth.s = Utils.normalizeS(webAuthnAuth.s);

bool res = WebAuthn.verify({
challenge: challenge,
Expand Down Expand Up @@ -149,10 +142,7 @@ contract WebAuthnFuzzTest is Test {

console.log("Veryfing", jsonCaseSelector);

// Only interested in s <= P256_N_DIV_2 cases
if (webAuthnAuth.s > P256_N_DIV_2) {
webAuthnAuth.s = FCL_ecdsa.n - webAuthnAuth.s;
}
webAuthnAuth.s = Utils.normalizeS(webAuthnAuth.s);

bool res = WebAuthn.verify({challenge: challenge, requireUV: uv, webAuthnAuth: webAuthnAuth, x: x, y: y});

Expand Down