Skip to content

Commit

Permalink
Add additional verification to EspressoTEEVerifier
Browse files Browse the repository at this point in the history
  • Loading branch information
Sneh1999 committed Nov 25, 2024
1 parent dd30940 commit 62dbad6
Show file tree
Hide file tree
Showing 9 changed files with 641 additions and 485 deletions.
2 changes: 1 addition & 1 deletion lib/automata-dcap-attestation
Submodule automata-dcap-attestation updated 47 files
+0 −21 .env.example
+1 −1 .github/workflows/build.yml
+16 −11 .github/workflows/slither.yml
+3 −0 .gitmodules
+61 −30 README.md
+19 −19 broadcast/AttestationScript.s.sol/1398243/configVerifier-latest.json
+56 −0 broadcast/AttestationScript.s.sol/1398243/configureZk-latest.json
+25 −28 broadcast/AttestationScript.s.sol/1398243/deployEntrypoint-latest.json
+56 −0 broadcast/DeployRouter.s.sol/1398243/setAuthorizedCaller-latest.json
+60 −0 broadcast/DeployRouter.s.sol/1398243/updateConfig-latest.json
+19 −18 broadcast/DeployV3.s.sol/1398243/run-latest.json
+20 −19 broadcast/DeployV4.s.sol/1398243/run-latest.json
+171 −0 contracts/AttestationEntrypointBase.sol
+0 −100 contracts/AutomataDcapAttestation.sol
+42 −0 contracts/AutomataDcapAttestationFee.sol
+81 −55 contracts/PCCSRouter.sol
+68 −0 contracts/bases/FeeManagerBase.sol
+17 −24 contracts/bases/QuoteVerifierBase.sol
+14 −76 contracts/bases/X509ChainBase.sol
+9 −4 contracts/bases/tcb/TCBInfoV3Base.sol
+0 −41 contracts/interfaces/IAttestation.sol
+6 −0 contracts/interfaces/IPCCSRouter.sol
+15 −3 contracts/interfaces/IQuoteVerifier.sol
+1 −0 contracts/types/CommonStruct.sol
+1 −1 contracts/types/Constants.sol
+4 −0 contracts/utils/BELE.sol
+12 −4 contracts/utils/P256Verifier.sol
+18 −12 contracts/verifiers/V3QuoteVerifier.sol
+31 −20 contracts/verifiers/V4QuoteVerifier.sol
+26 −0 env/.testnet.env.example
+9 −7 forge-script/AttestationScript.s.sol
+0 −24 forge-script/DeployRisc0Verifier.s.sol
+18 −0 forge-script/DeployRouter.s.sol
+61 −0 forge-script/utils/P256Configuration.sol
+13 −5 forge-script/verifiers/DeployV3.s.sol
+13 −5 forge-script/verifiers/DeployV4.s.sol
+106 −0 forge-test/AutomataDcapAttestationFeeTest.t.sol
+122 −22 forge-test/AutomataDcapAttestationTest.t.sol
+10 −20 forge-test/utils/PCCSSetupBase.sol
+2 −2 forge-test/utils/RiscZeroSetup.sol
+11 −0 forge-test/utils/succinct/Groth16Setup.sol
+11 −0 forge-test/utils/succinct/PlonkSetup.sol
+5 −2 foundry.toml
+1 −1 lib/automata-on-chain-pccs
+1 −1 lib/forge-std
+1 −1 lib/risc0-ethereum
+1 −0 lib/sp1-contracts
2 changes: 1 addition & 1 deletion lib/forge-std
Submodule forge-std updated 2 files
+99 −64 src/Vm.sol
+2 −2 test/Vm.t.sol
18 changes: 14 additions & 4 deletions scripts/deployEspressoTEEVerifier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,25 @@ import { deployContract } from './deploymentUtils'
async function main() {
const [deployer] = await ethers.getSigners()

const pccsRouterAddress = process.env.PCCS_ROUTER_ADDRESS as string
if (!pccsRouterAddress) {
throw new Error('PCCS_ROUTER_ADDRESS not set')
const v3QuoteVerifier = process.env.V3_QUOTE_VERIFIER_ADDRESS
if (!v3QuoteVerifier) {
throw new Error('V3_QUOTE_VERIFIER_ADDRESS not set')
}

const mrEnclave = process.env.MR_ENCLAVE
if (!mrEnclave) {
throw new Error('MR_ENCLAVE not set')
}

const mrSigner = process.env.MR_SIGNER
if (!mrSigner) {
throw new Error('MR_SIGNER not set')
}

const esperssoTEEVerifier = await deployContract(
'EspressoTEEVerifier',
deployer,
[pccsRouterAddress],
[mrEnclave, mrSigner, v3QuoteVerifier],
true
)
console.log(
Expand Down
101 changes: 87 additions & 14 deletions src/bridge/EspressoTEEVerifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,50 +14,83 @@ import {
ENCLAVE_REPORT_LENGTH
} from "@automata-network/dcap-attestation/contracts/types/Constants.sol";
import {EnclaveReport} from "@automata-network/dcap-attestation/contracts/types/V3Structs.sol";
import {
V3QuoteVerifier
} from "@automata-network/dcap-attestation/contracts/verifiers/V3QuoteVerifier.sol";
import {BytesUtils} from "@automata-network/dcap-attestation/contracts/utils/BytesUtils.sol";
import {Ownable} from "solady/auth/Ownable.sol";

/**
*
* @title Verifies quotes from the TEE and attests on-chain
* @notice Contains the logic to verify a quote from the TEE and attest on-chain. It uses the V3QuoteVerifier contract
* to verify the quote. Along with some additional verification logic.
*/

contract EspressoTEEVerifier is V3QuoteVerifier {
constructor(address _router) V3QuoteVerifier(_router) {}
contract EspressoTEEVerifier is Ownable {
using BytesUtils for bytes;
// TODO: add comments
V3QuoteVerifier public quoteVerifier;
bytes32 public mrEnclave;
bytes32 public mrSigner;

constructor(bytes32 _mrEnclave, bytes32 _mrSigner, address _quoteVerifier) {
quoteVerifier = V3QuoteVerifier(_quoteVerifier);
mrEnclave = _mrEnclave;
mrSigner = _mrSigner;
_initializeOwner(msg.sender);
}

/**
/*
@notice Verify a quote from the TEE and attest on-chain
@param rawQuote The quote from the TEE
@return success True if the quote was verified and attested on-chain
*/
function verify(bytes calldata rawQuote) external view returns (bool success) {
@param reportDataHash The hash of the report data
@return success True if the quote was verified and attested on-chain, false otherwise
*/
function verify(
bytes calldata rawQuote,
bytes32 reportDataHash
) external view returns (bool success) {
// Parse the header
Header memory header = _parseQuoteHeader(rawQuote);
Header memory header = parseQuoteHeader(rawQuote);

// Currently only version 3 is supported
if (header.version != 3) {
return false;
}

(success, ) = this.verifyQuote(header, rawQuote);
// Verify the quote
(success, ) = quoteVerifier.verifyQuote(header, rawQuote);
if (!success) {
return false;
}

// Parse enclave quote
// Parse enclave quote
uint256 offset = HEADER_LENGTH + ENCLAVE_REPORT_LENGTH;
EnclaveReport memory localReport;
(success, localReport) = parseEnclaveReport(rawQuote[HEADER_LENGTH:offset]);
if (!success) {
return false;
}

return true;
// Check that mrEnclave and mrSigner match
if (localReport.mrEnclave != mrEnclave || localReport.mrSigner != mrSigner) {
return false;
}

if (reportDataHash != bytes32(localReport.reportData.substring(0, 32))) {
return false;
}

// TODO: Use the parsed enclave report (localReport) to do other verifications
return true;
}

function _parseQuoteHeader(
bytes calldata rawQuote
) private pure returns (Header memory header) {
/*
@notice Parses the header from the quote
@param rawQuote The raw quote in bytes
@return header The parsed header
*/
function parseQuoteHeader(bytes calldata rawQuote) public pure returns (Header memory header) {
bytes2 attestationKeyType = bytes2(rawQuote[2:4]);
bytes2 qeSvn = bytes2(rawQuote[8:10]);
bytes2 pceSvn = bytes2(rawQuote[10:12]);
Expand All @@ -73,4 +106,44 @@ contract EspressoTEEVerifier is V3QuoteVerifier {
userData: bytes20(rawQuote[28:48])
});
}

/*
@notice Parses the enclave report from the quote
@param rawEnclaveReport The raw enclave report from the quote in bytes
@return success True if the enclave report was parsed successfully
@return enclaveReport The parsed enclave report
*/

function parseEnclaveReport(
bytes memory rawEnclaveReport
) public pure returns (bool success, EnclaveReport memory enclaveReport) {
if (rawEnclaveReport.length != ENCLAVE_REPORT_LENGTH) {
return (false, enclaveReport);
}
enclaveReport.cpuSvn = bytes16(rawEnclaveReport.substring(0, 16));
enclaveReport.miscSelect = bytes4(rawEnclaveReport.substring(16, 4));
enclaveReport.reserved1 = bytes28(rawEnclaveReport.substring(20, 28));
enclaveReport.attributes = bytes16(rawEnclaveReport.substring(48, 16));
enclaveReport.mrEnclave = bytes32(rawEnclaveReport.substring(64, 32));
enclaveReport.reserved2 = bytes32(rawEnclaveReport.substring(96, 32));
enclaveReport.mrSigner = bytes32(rawEnclaveReport.substring(128, 32));
enclaveReport.reserved3 = rawEnclaveReport.substring(160, 96);
enclaveReport.isvProdId = uint16(BELE.leBytesToBeUint(rawEnclaveReport.substring(256, 2)));
enclaveReport.isvSvn = uint16(BELE.leBytesToBeUint(rawEnclaveReport.substring(258, 2)));
enclaveReport.reserved4 = rawEnclaveReport.substring(260, 60);
enclaveReport.reportData = rawEnclaveReport.substring(320, 64);
success = true;
}

function setOwner(address newOwner) external onlyOwner {
_setOwner(newOwner);
}

function setMrEnclave(bytes32 _mrEnclave) external onlyOwner {
mrEnclave = _mrEnclave;
}

function setMrSigner(bytes32 _mrSigner) external onlyOwner {
mrSigner = _mrSigner;
}
}
41 changes: 30 additions & 11 deletions src/bridge/SequencerInbox.sol
Original file line number Diff line number Diff line change
Expand Up @@ -182,10 +182,7 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
__LEGACY_MAX_TIME_VARIATION.futureSeconds = 0;
}

function initialize(
IBridge bridge_,
ISequencerInbox.MaxTimeVariation calldata maxTimeVariation_
) external onlyDelegated {
function initialize(IBridge, ISequencerInbox.MaxTimeVariation calldata) external onlyDelegated {
revert Deprecated();
}

Expand Down Expand Up @@ -373,7 +370,18 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
if (msg.sender != tx.origin) revert NotOrigin();
if (!isBatchPoster[msg.sender]) revert NotBatchPoster();

bool success = espressoTEEVerifier.verify(quote);
// take keccak2256 hash of all the function arguments except the quote
bytes32 reportDataHash = keccak256(
abi.encodePacked(
sequenceNumber,
data,
afterDelayedMessagesRead,
address(gasRefunder),
prevMessageCount,
newMessageCount
)
);
bool success = espressoTEEVerifier.verify(quote, reportDataHash);
if (!success) {
revert InvalidTEEAttestationQuote();
}
Expand Down Expand Up @@ -481,12 +489,12 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
}

function addSequencerL2Batch(
uint256 sequenceNumber,
bytes calldata data,
uint256 afterDelayedMessagesRead,
uint256,
bytes calldata,
uint256,
IGasRefunder gasRefunder,
uint256 prevMessageCount,
uint256 newMessageCount
uint256,
uint256
) external override refundsGas(gasRefunder, IReader4844(address(0))) {
revert Deprecated();
}
Expand Down Expand Up @@ -516,7 +524,18 @@ contract SequencerInbox is DelegateCallAware, GasRefundEnabled, ISequencerInbox
// Only check the attestation quote if the batch has been posted by the
// batch poster
if (isBatchPoster[msg.sender]) {
bool success = espressoTEEVerifier.verify(quote);
// take keccak2256 hash of all the function arguments except the quote
bytes32 reportDataHash = keccak256(
abi.encodePacked(
sequenceNumber,
data,
afterDelayedMessagesRead,
address(gasRefunder),
prevMessageCount,
newMessageCount
)
);
bool success = espressoTEEVerifier.verify(quote, reportDataHash);
if (!success) {
revert InvalidTEEAttestationQuote();
}
Expand Down
8 changes: 4 additions & 4 deletions src/rollup/BridgeCreator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,10 @@ contract BridgeCreator is Ownable {

/// @dev Deprecated
function createBridge(
address adminProxy,
address rollup,
address nativeToken,
ISequencerInbox.MaxTimeVariation calldata maxTimeVariation
address,
address,
address,
ISequencerInbox.MaxTimeVariation calldata
) external returns (BridgeContracts memory) {
revert Deprecated();
}
Expand Down
Loading

0 comments on commit 62dbad6

Please sign in to comment.