Skip to content

Commit afa453d

Browse files
authored
Merge pull request #20 from datachainlab/fix-operator-dedicated-report
Fix registerEnclaveKey to not allow empty signature when an AVR is dedicated to specific operator Signed-off-by: Jun Kimura <jun.kimura@datachain.jp>
2 parents 6388e8f + bd6662e commit afa453d

File tree

4 files changed

+78
-13
lines changed

4 files changed

+78
-13
lines changed

README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,13 @@ $ ./target/release/lcp-cgen \
3232
--signing_key=${LCP_PATH}/tests/certs/signing.key \
3333
--enclave=${LCP_PATH}/bin/enclave.signed.so \
3434
--out=/path/to/testdatadir \
35-
--commands wait_blocks:1 update_client verify_channel wait_blocks:1 update_client verify_packet
35+
--eknum=1 \
36+
--commands \
37+
wait_blocks:1 \
38+
update_client:0 \
39+
verify_channel:0 \
40+
wait_blocks:1 \
41+
update_client:0 \
42+
verify_packet:0 \
43+
verify_packet_receipt_absence:0
3644
```

contracts/LCPClientBase.sol

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -497,9 +497,9 @@ abstract contract LCPClientBase is ILightClient, ILCPClientErrors {
497497
operator = verifyECDSASignature(
498498
keccak256(LCPOperator.computeEIP712RegisterEnclaveKey(message.report)), message.operator_signature
499499
);
500-
if (reElems.operator != address(0) && reElems.operator != operator) {
501-
revert LCPClientAVRUnexpectedOperator(operator, reElems.operator);
502-
}
500+
}
501+
if (reElems.operator != address(0) && reElems.operator != operator) {
502+
revert LCPClientAVRUnexpectedOperator(operator, reElems.operator);
503503
}
504504
uint64 expiredAt = reElems.attestationTime + clientStorage.clientState.key_expiration;
505505
if (expiredAt <= block.timestamp) {

test/LCPClientOperator.t.sol

Lines changed: 65 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import {LCPOperator} from "../contracts/LCPOperator.sol";
1818
contract LCPClientOperatorTest is BasicTest {
1919
using IBCHeight for Height.Data;
2020

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

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

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

3532
function testPreComputationValues() public pure {
3633
assertEq(LCPOperator.domainSeparatorUniversal(), LCPOperator.DOMAIN_SEPARATOR_REGISTER_ENCLAVE_KEY);
@@ -97,7 +94,7 @@ contract LCPClientOperatorTest is BasicTest {
9794
}
9895
string memory clientId = generateClientId(1);
9996
{
100-
ClientState.Data memory clientState = createInitialState(commandAvrFile, operators, 2, 3);
97+
ClientState.Data memory clientState = createInitialState(avr("001-avr"), operators, 2, 3);
10198
ConsensusState.Data memory consensusState;
10299
Height.Data memory height = lc.initializeClient(
103100
clientId, LCPProtoMarshaler.marshal(clientState), LCPProtoMarshaler.marshal(consensusState)
@@ -167,7 +164,7 @@ contract LCPClientOperatorTest is BasicTest {
167164
}
168165
string memory clientId = generateClientId(1);
169166
{
170-
ClientState.Data memory clientState = createInitialState(commandAvrFile, operators, 2, 3);
167+
ClientState.Data memory clientState = createInitialState(avr("001-avr"), operators, 2, 3);
171168
ConsensusState.Data memory consensusState;
172169
Height.Data memory height = lc.initializeClient(
173170
clientId, LCPProtoMarshaler.marshal(clientState), LCPProtoMarshaler.marshal(consensusState)
@@ -290,6 +287,63 @@ contract LCPClientOperatorTest is BasicTest {
290287
}
291288
}
292289

290+
function testRegisterEnclaveKeyOperatorDedicatedAVR() public {
291+
Vm.Wallet[] memory wallets = createWallets(2);
292+
address[] memory operators = new address[](1);
293+
operators[0] = wallets[0].addr;
294+
string memory avrFile = "test/data/reports/valid/operator_0xc1eae5EF781f4EE5867eC6725630E7dC17fa3436";
295+
296+
{
297+
string memory clientId = generateClientId(1);
298+
ClientState.Data memory clientState = createInitialState(avrFile, operators, 1, 1);
299+
ConsensusState.Data memory consensusState;
300+
lc.initializeClient(
301+
clientId, LCPProtoMarshaler.marshal(clientState), LCPProtoMarshaler.marshal(consensusState)
302+
);
303+
// operator matches the operator address in the AVR
304+
lc.registerEnclaveKey(clientId, createRegisterEnclaveKeyMessage(avrFile, wallets[0].privateKey));
305+
}
306+
{
307+
string memory clientId = generateClientId(2);
308+
ClientState.Data memory clientState = createInitialState(avrFile, operators, 1, 1);
309+
ConsensusState.Data memory consensusState;
310+
lc.initializeClient(
311+
clientId, LCPProtoMarshaler.marshal(clientState), LCPProtoMarshaler.marshal(consensusState)
312+
);
313+
314+
// operator does not match the operator address in the AVR
315+
RegisterEnclaveKeyMessage.Data memory msg_ = createRegisterEnclaveKeyMessage(avrFile, wallets[1].privateKey);
316+
vm.expectRevert(
317+
abi.encodeWithSelector(
318+
ILCPClientErrors.LCPClientAVRUnexpectedOperator.selector, wallets[1].addr, wallets[0].addr
319+
)
320+
);
321+
lc.registerEnclaveKey(clientId, msg_);
322+
}
323+
{
324+
string memory clientId = generateClientId(3);
325+
ClientState.Data memory clientState = createInitialState(avrFile, operators, 1, 1);
326+
ConsensusState.Data memory consensusState;
327+
lc.initializeClient(
328+
clientId, LCPProtoMarshaler.marshal(clientState), LCPProtoMarshaler.marshal(consensusState)
329+
);
330+
// an operator dedicated AVR does not allow an empty signature
331+
RegisterEnclaveKeyMessage.Data memory msg_ = createRegisterEnclaveKeyMessage(avrFile, 0);
332+
vm.expectRevert(
333+
abi.encodeWithSelector(
334+
ILCPClientErrors.LCPClientAVRUnexpectedOperator.selector, address(0), wallets[0].addr
335+
)
336+
);
337+
lc.registerEnclaveKey(clientId, msg_);
338+
}
339+
}
340+
341+
// ---------------------------- Helper Functions ----------------------------
342+
343+
function avr(string memory filename) internal pure returns (string memory) {
344+
return string(abi.encodePacked("test/data/client/03/", filename));
345+
}
346+
293347
function generateSignature(Vm.Wallet memory wallet, bytes32 commitment, bool valid)
294348
internal
295349
pure
@@ -363,9 +417,11 @@ contract LCPClientOperatorTest is BasicTest {
363417
message.report = readJSON(avrFile, ".avr");
364418
message.signature = readDecodedBytes(avrFile, ".signature");
365419
message.signing_cert = readDecodedBytes(avrFile, ".signing_cert");
366-
(uint8 v, bytes32 r, bytes32 s) =
367-
vm.sign(privateKey, keccak256(LCPOperatorTestHelper.computeEIP712RegisterEnclaveKey(message.report)));
368-
message.operator_signature = abi.encodePacked(r, s, v);
420+
if (privateKey != 0) {
421+
(uint8 v, bytes32 r, bytes32 s) =
422+
vm.sign(privateKey, keccak256(LCPOperatorTestHelper.computeEIP712RegisterEnclaveKey(message.report)));
423+
message.operator_signature = abi.encodePacked(r, s, v);
424+
}
369425
}
370426

371427
function createUpdateClientMessage(string memory updateClientFilePrefix)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
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 commit comments

Comments
 (0)