Skip to content

Commit

Permalink
Merge pull request #20 from datachainlab/fix-operator-dedicated-report
Browse files Browse the repository at this point in the history
Fix registerEnclaveKey to not allow empty signature when an AVR is dedicated to specific operator

Signed-off-by: Jun Kimura <[email protected]>
  • Loading branch information
bluele authored Jun 20, 2024
2 parents 6388e8f + bd6662e commit afa453d
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 13 deletions.
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,13 @@ $ ./target/release/lcp-cgen \
--signing_key=${LCP_PATH}/tests/certs/signing.key \
--enclave=${LCP_PATH}/bin/enclave.signed.so \
--out=/path/to/testdatadir \
--commands wait_blocks:1 update_client verify_channel wait_blocks:1 update_client verify_packet
--eknum=1 \
--commands \
wait_blocks:1 \
update_client:0 \
verify_channel:0 \
wait_blocks:1 \
update_client:0 \
verify_packet:0 \
verify_packet_receipt_absence:0
```
6 changes: 3 additions & 3 deletions contracts/LCPClientBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -497,9 +497,9 @@ abstract contract LCPClientBase is ILightClient, ILCPClientErrors {
operator = verifyECDSASignature(
keccak256(LCPOperator.computeEIP712RegisterEnclaveKey(message.report)), message.operator_signature
);
if (reElems.operator != address(0) && reElems.operator != operator) {
revert LCPClientAVRUnexpectedOperator(operator, reElems.operator);
}
}
if (reElems.operator != address(0) && reElems.operator != operator) {
revert LCPClientAVRUnexpectedOperator(operator, reElems.operator);
}
uint64 expiredAt = reElems.attestationTime + clientStorage.clientState.key_expiration;
if (expiredAt <= block.timestamp) {
Expand Down
74 changes: 65 additions & 9 deletions test/LCPClientOperator.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import {LCPOperator} from "../contracts/LCPOperator.sol";
contract LCPClientOperatorTest is BasicTest {
using IBCHeight for Height.Data;

string internal constant commandAvrFile = "test/data/client/03/001-avr";
string internal constant commandResultSuffix = "_result";

LCPClient lc;
Expand All @@ -28,9 +27,7 @@ contract LCPClientOperatorTest is BasicTest {
lc = new LCPClient(address(this), true, vm.readFileBinary("./test/data/certs/simulation_rootca.der"));
}

function avr(string memory filename) internal pure returns (string memory) {
return string(abi.encodePacked("test/data/client/03/", filename));
}
// ---------------------------- Test Cases ----------------------------

function testPreComputationValues() public pure {
assertEq(LCPOperator.domainSeparatorUniversal(), LCPOperator.DOMAIN_SEPARATOR_REGISTER_ENCLAVE_KEY);
Expand Down Expand Up @@ -97,7 +94,7 @@ contract LCPClientOperatorTest is BasicTest {
}
string memory clientId = generateClientId(1);
{
ClientState.Data memory clientState = createInitialState(commandAvrFile, operators, 2, 3);
ClientState.Data memory clientState = createInitialState(avr("001-avr"), operators, 2, 3);
ConsensusState.Data memory consensusState;
Height.Data memory height = lc.initializeClient(
clientId, LCPProtoMarshaler.marshal(clientState), LCPProtoMarshaler.marshal(consensusState)
Expand Down Expand Up @@ -167,7 +164,7 @@ contract LCPClientOperatorTest is BasicTest {
}
string memory clientId = generateClientId(1);
{
ClientState.Data memory clientState = createInitialState(commandAvrFile, operators, 2, 3);
ClientState.Data memory clientState = createInitialState(avr("001-avr"), operators, 2, 3);
ConsensusState.Data memory consensusState;
Height.Data memory height = lc.initializeClient(
clientId, LCPProtoMarshaler.marshal(clientState), LCPProtoMarshaler.marshal(consensusState)
Expand Down Expand Up @@ -290,6 +287,63 @@ contract LCPClientOperatorTest is BasicTest {
}
}

function testRegisterEnclaveKeyOperatorDedicatedAVR() public {
Vm.Wallet[] memory wallets = createWallets(2);
address[] memory operators = new address[](1);
operators[0] = wallets[0].addr;
string memory avrFile = "test/data/reports/valid/operator_0xc1eae5EF781f4EE5867eC6725630E7dC17fa3436";

{
string memory clientId = generateClientId(1);
ClientState.Data memory clientState = createInitialState(avrFile, operators, 1, 1);
ConsensusState.Data memory consensusState;
lc.initializeClient(
clientId, LCPProtoMarshaler.marshal(clientState), LCPProtoMarshaler.marshal(consensusState)
);
// operator matches the operator address in the AVR
lc.registerEnclaveKey(clientId, createRegisterEnclaveKeyMessage(avrFile, wallets[0].privateKey));
}
{
string memory clientId = generateClientId(2);
ClientState.Data memory clientState = createInitialState(avrFile, operators, 1, 1);
ConsensusState.Data memory consensusState;
lc.initializeClient(
clientId, LCPProtoMarshaler.marshal(clientState), LCPProtoMarshaler.marshal(consensusState)
);

// operator does not match the operator address in the AVR
RegisterEnclaveKeyMessage.Data memory msg_ = createRegisterEnclaveKeyMessage(avrFile, wallets[1].privateKey);
vm.expectRevert(
abi.encodeWithSelector(
ILCPClientErrors.LCPClientAVRUnexpectedOperator.selector, wallets[1].addr, wallets[0].addr
)
);
lc.registerEnclaveKey(clientId, msg_);
}
{
string memory clientId = generateClientId(3);
ClientState.Data memory clientState = createInitialState(avrFile, operators, 1, 1);
ConsensusState.Data memory consensusState;
lc.initializeClient(
clientId, LCPProtoMarshaler.marshal(clientState), LCPProtoMarshaler.marshal(consensusState)
);
// an operator dedicated AVR does not allow an empty signature
RegisterEnclaveKeyMessage.Data memory msg_ = createRegisterEnclaveKeyMessage(avrFile, 0);
vm.expectRevert(
abi.encodeWithSelector(
ILCPClientErrors.LCPClientAVRUnexpectedOperator.selector, address(0), wallets[0].addr
)
);
lc.registerEnclaveKey(clientId, msg_);
}
}

// ---------------------------- Helper Functions ----------------------------

function avr(string memory filename) internal pure returns (string memory) {
return string(abi.encodePacked("test/data/client/03/", filename));
}

function generateSignature(Vm.Wallet memory wallet, bytes32 commitment, bool valid)
internal
pure
Expand Down Expand Up @@ -363,9 +417,11 @@ contract LCPClientOperatorTest is BasicTest {
message.report = readJSON(avrFile, ".avr");
message.signature = readDecodedBytes(avrFile, ".signature");
message.signing_cert = readDecodedBytes(avrFile, ".signing_cert");
(uint8 v, bytes32 r, bytes32 s) =
vm.sign(privateKey, keccak256(LCPOperatorTestHelper.computeEIP712RegisterEnclaveKey(message.report)));
message.operator_signature = abi.encodePacked(r, s, v);
if (privateKey != 0) {
(uint8 v, bytes32 r, bytes32 s) =
vm.sign(privateKey, keccak256(LCPOperatorTestHelper.computeEIP712RegisterEnclaveKey(message.report)));
message.operator_signature = abi.encodePacked(r, s, v);
}
}

function createUpdateClientMessage(string memory updateClientFilePrefix)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"avr":"{\"id\":\"23856791181030202675484781740313693463\",\"timestamp\":\"2024-06-20T14:49:49.761000\",\"version\":4,\"advisoryURL\":\"https://security-center.intel.com\",\"advisoryIDs\":[],\"isvEnclaveQuoteStatus\":\"OK\",\"platformInfoBlob\":null,\"isvEnclaveQuoteBody\":\"AgAAAAsAAADvAO8A7+/v7wAAAAAAAAAAAAAAAAAAAACuQDx+HFlQ7r4EdJ0H5pZhSCDzN2rmsvIDTTt6S0ineAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAAAHAAAAAAAAADKAwI4ZtU0VypJeCmwT/tr/Kv9sCX+ThBq9jZ4aMHK4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACD1xnnferKFHD2uvYqTXdDA8iZ22kCD5xw7h38CMfOngAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABhNeWsFyr39J51cViGUemN7CfskLB6uXveB9O5YZ+xnJWMOfcF/o0NgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"}","signature":"bN61lnClfXx7sQTuvwtaUsUAbJ8GFyI9v2HJBme+8/5XOiQiJbi/HisMtEzgHYWf3u/k3aVPJ4jOXi/sto3JRm8JEAtrUUkNbFQh+ti49O311iQ5PIREecac5WuYNu4UJbzP+OHiG14b9QHiVbnNyGtfZqvVTMOdn+wFocK/ghXvrFBTrmh2i9jr+8XgLEU3e06ap+2YxLh7zR8txc8AtXHD+52HYtAVIz4cyCg9AwabK437s8ZQVeWdcV8Oc9Mpq+gufySgh4ZwHGAT2KbXlfc50yOOwsw6GVbipWCJwRqbbBgpPxynHkRCY1PuZj6VWYJH/G2BF2IAf2ShI7BBfg==","signing_cert":"MIIEADCCAmgCFBubGPb+EfC05/S/6Aw4dX09a1nEMA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEUMBIGA1UEBwwLU2FudGEgQ2xhcmExEDAOBgNVBAoMB0V4YW1wbGUxOTA3BgNVBAMMMFRlc3QgZm9yIEludGVsIFNHWCBBdHRlc3RhdGlvbiBSZXBvcnQgU2lnbmluZyBDQTAgFw0yMzA2MDcwOTQyMjdaGA8yMDUwMTAyMzA5NDIyN1owejELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRQwEgYDVQQHDAtTYW50YSBDbGFyYTEQMA4GA1UECgwHRXhhbXBsZTE2MDQGA1UEAwwtVGVzdCBmb3IgSW50ZWwgU0dYIEF0dGVzdGF0aW9uIFJlcG9ydCBTaWduaW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkNMKASzEqPmh//fz0QPZcz8805DpSBqZ6ZW0dCiBTFzp3NgU03wsC23wgqVR9LAWfDVbaPiOOLhw99NBQizHcXwuKgA02ISpUyu7bQwFhHKWM7YRv14uKcXtdralZOL6uPo5RHZXCTkslxSy29r/Cyg63zxqvTZjuPpd40W1St2/wH8C1/OXW/ugG3y4bZME01qkHj1nJQLjYav8oHhH93Cu4vniS0ZAifVa+l9BHRj+jy7X8lOTFbUUSjXgL6rN2GQD5Dtso5fTwj2ukVmYYumfjctvFj1KJ1c/3Vx9291d8dmBQNxFZ+eleeGOPZKpgrKEj79WGTE1oHqApxBPbwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBgQC39YvP2YVKBbODxkdMG4FQRSAcywdml2GY+ah67sbLF/34i64JzvahLaWo+gl091ivkkUa//fgvGj/BBQq7oLmEJ1K8jsHWR8F3NYQHHSIIf8+vgpqGyox8miwZMrbVkMqIlxiqPnDcLWhiRfeXcwqc3qlfPgtHfGPx3YHlUXZTQLWNffBXXWYxPz5DX5OeMJjlV1VxFd+3xrNltR4klSrGrQLRqyZe7r5AndZ3b9g86xN7eospyhoAGtSOLw0Ml7j3F4zVXkhoPYTVayhi3q71r4AqfaLLdbYGaXMhezqo51l06iRaMkFL49enpDXnCRbd1yJtZZXwe17cItDRNB7k6GrpibuLFfbd2goYR/Rv+lCY/sR5IFwrKuWoxwTvd7pIzYbl9oRurbvpU3srCvNOkQO1oPxP6PpwuScpx7KCha3QtKrJfMGOQ/siGUXMiseT8hQAj5P4DaPV6xFTbYqHEUx6uW5vFzv5QPhCd6Xh3MeUz6Xw2UMbpR2JahkrSM=","mrenclave":"MoDAjhm1TRXKkl4KbBP+2v8q/2wJf5OEGr2Nnhowcrg=","enclave_key":"hNeWsFyr39J51cViGUemN7CfskI="}

0 comments on commit afa453d

Please sign in to comment.