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

Fix registerEnclaveKey to not allow empty signature when an AVR is dedicated to specific operator #20

Merged
merged 2 commits into from
Jun 20, 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
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="}
Loading