Skip to content

Commit

Permalink
Move CA bundle validation into NitroValidator contract (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
mdehoog authored Jan 11, 2025
1 parent e3bf6f1 commit cc45e9c
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 25 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ This repo provides solidity contracts for the verification of attestations gener

Note it costs around 63m gas to validate an attestation with no prior verified certs.
You can break this up into smaller transactions by verifying each cert in the chain separately.
You can call `CertManager.verifyCert` for each cert in the attestation `cabundle`.
You can call `CertManager.verifyCACert` for each cert in the attestation `cabundle`.

This library does not currently support certificate revocation, which is disabled in AWS's attestation verification documentation
[here](https://github.com/aws/aws-nitro-enclaves-nsm-api/blob/4b851f3006c6fa98f23dcffb2cba03b39de9b8af/docs/attestation_process.md#32-syntactical-validation).
Expand Down
19 changes: 6 additions & 13 deletions src/CertManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -61,21 +61,14 @@ contract CertManager is ICertManager {
);
}

function verifyCert(bytes memory cert, bool ca, bytes32 parentCertHash) external returns (VerifiedCert memory) {
return _verifyCert(cert, keccak256(cert), ca, _loadVerified(parentCertHash));
function verifyCACert(bytes memory cert, bytes32 parentCertHash) external returns (bytes32) {
bytes32 certHash = keccak256(cert);
_verifyCert(cert, certHash, true, _loadVerified(parentCertHash));
return certHash;
}

function verifyCertBundle(bytes memory certificate, bytes[] calldata cabundle)
external
returns (VerifiedCert memory)
{
VerifiedCert memory parent;
for (uint256 i = 0; i < cabundle.length; i++) {
bytes32 certHash = keccak256(cabundle[i]);
require(i > 0 || certHash == ROOT_CA_CERT_HASH, "Root CA cert not matching");
parent = _verifyCert(cabundle[i], certHash, true, parent);
}
return _verifyCert(certificate, keccak256(certificate), false, parent);
function verifyClientCert(bytes memory cert, bytes32 parentCertHash) external returns (VerifiedCert memory) {
return _verifyCert(cert, keccak256(cert), false, _loadVerified(parentCertHash));
}

function _verifyCert(bytes memory certificate, bytes32 certHash, bool ca, VerifiedCert memory parent)
Expand Down
8 changes: 2 additions & 6 deletions src/ICertManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,7 @@ interface ICertManager {
bytes pubKey;
}

function verifyCert(bytes memory cert, bool clientCert, bytes32 parentCertHash)
external
returns (VerifiedCert memory);
function verifyCACert(bytes memory cert, bytes32 parentCertHash) external returns (bytes32);

function verifyCertBundle(bytes memory certificate, bytes[] calldata cabundle)
external
returns (VerifiedCert memory);
function verifyClientCert(bytes memory cert, bytes32 parentCertHash) external returns (VerifiedCert memory);
}
13 changes: 12 additions & 1 deletion src/NitroValidator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,24 @@ contract NitroValidator {
cabundle[i] = attestationTbs.slice(ptrs.cabundle[i]);
}

ICertManager.VerifiedCert memory parent = certManager.verifyCertBundle(cert, cabundle);
ICertManager.VerifiedCert memory parent = verifyCertBundle(cert, cabundle);
bytes memory hash = Sha2Ext.sha384(attestationTbs, 0, attestationTbs.length);
_verifySignature(parent.pubKey, hash, signature);

return ptrs;
}

function verifyCertBundle(bytes memory certificate, bytes[] memory cabundle)
internal
returns (ICertManager.VerifiedCert memory)
{
bytes32 parentHash;
for (uint256 i = 0; i < cabundle.length; i++) {
parentHash = certManager.verifyCACert(cabundle[i], parentHash);
}
return certManager.verifyClientCert(certificate, parentHash);
}

function _constructAttestationTbs(
bytes memory rawProtectedBytes,
uint256 rawProtectedLength,
Expand Down
11 changes: 7 additions & 4 deletions test/CertManager.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,18 @@ contract CertManagerTest is Test {
hex"308203153082029aa003020102021020c20971680e956fc3c8ce925d784bc7300a06082a8648ce3d0403033064310b3009060355040613025553310f300d060355040a0c06416d617a6f6e310c300a060355040b0c034157533136303406035504030c2d353133623665666332313639303264372e75732d656173742d312e6177732e6e6974726f2d656e636c61766573301e170d3234313132353032323230345a170d3234313230313030323230345a308189313c303a06035504030c33626635396531633335623630386133382e7a6f6e616c2e75732d656173742d312e6177732e6e6974726f2d656e636c61766573310c300a060355040b0c03415753310f300d060355040a0c06416d617a6f6e310b3009060355040613025553310b300906035504080c0257413110300e06035504070c0753656174746c653076301006072a8648ce3d020106052b8104002203620004df741cd0537abbbc37bb32b06c835f497df86933b6ac8b4ee15d1251cfde596a7953756bb2759896a4d50c7cfb7d50cfc62fd4010a8c0d4a58a6f38988de6707d5aeaef3e3ca523ffac31260cc7c33546dc667d52ba524c39bd0ed6b82c0652da381ea3081e730120603551d130101ff040830060101ff020101301f0603551d230418301680142b3d75d274a3cdd61b2c13f539e08c960ce757dd301d0603551d0e04160414e8b15a6bc0b83e3d9e50ab9b289fb5fa0c61eabf300e0603551d0f0101ff0404030201863081800603551d1f047930773075a073a071866f687474703a2f2f63726c2d75732d656173742d312d6177732d6e6974726f2d656e636c617665732e73332e75732d656173742d312e616d617a6f6e6177732e636f6d2f63726c2f39636665653133332d613562622d343431392d613462372d3730386661643563363866662e63726c300a06082a8648ce3d04030303690030660231009595351f7c4411011eb4cf1a18181c2ed6901e84c2971c781e2cdc2725d5135066fc8d96ac70c98fc27106cdb345a563023100f96927f5bc58f1c29f8ea06d9bb5eeae3a6e2e572aff9911a8c90ed6e00c1cc7c534b9fde367781807c35ba9427d05fe";
cabundle[3] =
hex"308202bd30820244a00302010202142690c27f442c86646256455d3442f8998be152dc300a06082a8648ce3d040303308189313c303a06035504030c33626635396531633335623630386133382e7a6f6e616c2e75732d656173742d312e6177732e6e6974726f2d656e636c61766573310c300a060355040b0c03415753310f300d060355040a0c06416d617a6f6e310b3009060355040613025553310b300906035504080c0257413110300e06035504070c0753656174746c65301e170d3234313132353133353135375a170d3234313132363133353135375a30818e310b30090603550406130255533113301106035504080c0a57617368696e67746f6e3110300e06035504070c0753656174746c65310f300d060355040a0c06416d617a6f6e310c300a060355040b0c034157533139303706035504030c30692d30666661626464383636323664616631662e75732d656173742d312e6177732e6e6974726f2d656e636c617665733076301006072a8648ce3d020106052b8104002203620004c041c328653a7028db8060f3f19f589197b8c1a17dc755a5629c0f47c3cd3414412fd38b7f87fc70a6f22a0c2698fe1f748eff998f783add861a6b2373fba37a31f9bf0ab75fd2c4e17cc0df8124ddb0a4513483e40721ebb15a80619696747aa366306430120603551d130101ff040830060101ff020100300e0603551d0f0101ff040403020204301d0603551d0e041604145555580de23b6d83eb6a5be1b4dbdb376f69e444301f0603551d23041830168014e8b15a6bc0b83e3d9e50ab9b289fb5fa0c61eabf300a06082a8648ce3d0403030367003064023072c53164609cba5d7a16914d5d2102a9e70009288aae1215cc5e8d70f2d2d4b49bffb0119ec523e620275729f09e566e02302e0f2b7998eb25fa493dc1300329f7f142337b38e76df0a32b8660f41599c5febae120e4ed2c60efbbaa842ba6db8d91";
certManager.verifyCertBundle(cert, cabundle);
certManager.verifyCertBundle(cert, cabundle);
certManager.verifyCACert(cabundle[0], 0);
certManager.verifyCACert(cabundle[1], keccak256(cabundle[0]));
certManager.verifyCACert(cabundle[2], keccak256(cabundle[1]));
certManager.verifyCACert(cabundle[3], keccak256(cabundle[2]));
certManager.verifyClientCert(cert, keccak256(cabundle[3]));
}

function test_VerifyCert() public {
function test_VerifyCACert() public {
bytes memory parent =
hex"3082021130820196a003020102021100f93175681b90afe11d46ccb4e4e7f856300a06082a8648ce3d0403033049310b3009060355040613025553310f300d060355040a0c06416d617a6f6e310c300a060355040b0c03415753311b301906035504030c126177732e6e6974726f2d656e636c61766573301e170d3139313032383133323830355a170d3439313032383134323830355a3049310b3009060355040613025553310f300d060355040a0c06416d617a6f6e310c300a060355040b0c03415753311b301906035504030c126177732e6e6974726f2d656e636c617665733076301006072a8648ce3d020106052b8104002203620004fc0254eba608c1f36870e29ada90be46383292736e894bfff672d989444b5051e534a4b1f6dbe3c0bc581a32b7b176070ede12d69a3fea211b66e752cf7dd1dd095f6f1370f4170843d9dc100121e4cf63012809664487c9796284304dc53ff4a3423040300f0603551d130101ff040530030101ff301d0603551d0e041604149025b50dd90547e796c396fa729dcf99a9df4b96300e0603551d0f0101ff040403020186300a06082a8648ce3d0403030369003066023100a37f2f91a1c9bd5ee7b8627c1698d255038e1f0343f95b63a9628c3d39809545a11ebcbf2e3b55d8aeee71b4c3d6adf3023100a2f39b1605b27028a5dd4ba069b5016e65b4fbde8fe0061d6a53197f9cdaf5d943bc61fc2beb03cb6fee8d2302f3dff6";
bytes memory cert =
hex"308202bf30820244a00302010202100b93e39c65609c59e8144a2ad34ba3a0300a06082a8648ce3d0403033049310b3009060355040613025553310f300d060355040a0c06416d617a6f6e310c300a060355040b0c03415753311b301906035504030c126177732e6e6974726f2d656e636c61766573301e170d3234313132333036333235355a170d3234313231333037333235355a3064310b3009060355040613025553310f300d060355040a0c06416d617a6f6e310c300a060355040b0c034157533136303406035504030c2d353133623665666332313639303264372e75732d656173742d312e6177732e6e6974726f2d656e636c617665733076301006072a8648ce3d020106052b8104002203620004ee78108039725a03e0b63a5d7d1244f6294eb7631f305e360997c8e5c06c779f23cfaeb64cb9aeac8a031bfac9f4dafc3621b4367f003c08c0ce410c2118396cc5d56ec4e92e1b17f9709b2bffcef462f7bcb97d6ca11325c4a30156c9720de7a381d53081d230120603551d130101ff040830060101ff020102301f0603551d230418301680149025b50dd90547e796c396fa729dcf99a9df4b96301d0603551d0e041604142b3d75d274a3cdd61b2c13f539e08c960ce757dd300e0603551d0f0101ff040403020186306c0603551d1f046530633061a05fa05d865b687474703a2f2f6177732d6e6974726f2d656e636c617665732d63726c2e73332e616d617a6f6e6177732e636f6d2f63726c2f61623439363063632d376436332d343262642d396539662d3539333338636236376638342e63726c300a06082a8648ce3d0403030369003066023100fce7a6c2b38e0a8ebf0d28348d74463458b84bfe8b2b95315dd4da665e8e83d4ab911852a4e92a8263ecf571d2df3b89023100ab92be511136be76aa313018f9f4825eaad602d0342d268e6da632767f68f55f761fa9fd2a7ee716c481c67f26e3f8f4";
certManager.verifyCert(cert, true, keccak256(parent));
certManager.verifyCACert(cert, keccak256(parent));
}
}

0 comments on commit cc45e9c

Please sign in to comment.