From 586cd4ff7993458c90ff29181ca6e609ce115244 Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Thu, 17 Aug 2023 04:35:22 +0000 Subject: [PATCH 01/35] Simplified commands for generating rave() ABI hex and func signatures. --- .gitignore | 1 + src/IRave.sol | 8 +-- src/RAVE.sol | 16 +++--- src/RAVEBase.sol | 8 +-- test/scripts/bin/error.log | 33 ++++++++++++ test/scripts/bin/fields_to_abi | 11 ++++ test/scripts/bin/is_valid_report | 31 +++++++++-- test/scripts/bin/lib/__init__.py | 1 + test/scripts/bin/lib/shared.py | 73 ++++++++++++++++++++++++++ test/scripts/bin/prepend_func_sig | 15 ++++++ test/scripts/bin/report_to_calldata | 13 +---- test/scripts/bin/ss_to_abi | 62 ++++++++++++++++++++++ test/scripts/preprocess_rave_inputs.py | 7 ++- 13 files changed, 246 insertions(+), 33 deletions(-) create mode 100644 test/scripts/bin/lib/__init__.py create mode 100644 test/scripts/bin/lib/shared.py create mode 100755 test/scripts/bin/prepend_func_sig create mode 100755 test/scripts/bin/ss_to_abi diff --git a/.gitignore b/.gitignore index f3e294b..4b8977c 100755 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ env/ .vscode test/mocks/evidence.json test/scripts/ss_out +test/scripts/bin/error.log *ss_out* # Byte-compiled / optimized / DLL files diff --git a/src/IRave.sol b/src/IRave.sol index 0628f75..9f3a860 100755 --- a/src/IRave.sol +++ b/src/IRave.sol @@ -32,8 +32,8 @@ interface IRave { bytes memory leafX509Cert, bytes memory signingMod, bytes memory signingExp, - bytes32 mrenclave, - bytes32 mrsigner + bytes memory mrenclave, + bytes memory mrsigner ) external view returns (bytes memory payload); /* @@ -51,7 +51,7 @@ interface IRave { bytes memory sig, bytes memory signingMod, bytes memory signingExp, - bytes32 mrenclave, - bytes32 mrsigner + bytes memory mrenclave, + bytes memory mrsigner ) external view returns (bytes memory payload); } diff --git a/src/RAVE.sol b/src/RAVE.sol index 537cb39..256a310 100755 --- a/src/RAVE.sol +++ b/src/RAVE.sol @@ -28,8 +28,8 @@ contract RAVE is Test, RAVEBase, JSONBuilder, X509Verifier { bytes memory sig, bytes memory signingMod, bytes memory signingExp, - bytes32 mrenclave, - bytes32 mrsigner + bytes memory mrenclave, + bytes memory mrsigner ) public view override returns (bytes memory payload) { // Decode the encoded report JSON values to a Values struct and reconstruct the original JSON string (Values memory reportValues, bytes memory reportBytes) = _buildReportBytes(reportFieldsABI); @@ -62,8 +62,8 @@ contract RAVE is Test, RAVEBase, JSONBuilder, X509Verifier { bytes memory signingMod, bytes memory signingExp, - bytes32 mrenclave, - bytes32 mrsigner + bytes memory mrenclave, + bytes memory mrsigner ) public view override returns (bytes memory payload) { // Verify the leafX509Cert was signed with signingMod and signingExp (bytes memory leafCertModulus, bytes memory leafCertExponent) = @@ -153,7 +153,7 @@ contract RAVE is Test, RAVEBase, JSONBuilder, X509Verifier { * @param mrsigner The expected enclave signer. * @return The 64 byte payload if the mrenclave and mrsigner values were correctly set. */ - function _verifyReportContents(Values memory reportValues, bytes32 mrenclave, bytes32 mrsigner) + function _verifyReportContents(Values memory reportValues, bytes memory mrenclave, bytes memory mrsigner) internal pure returns (bytes memory payload) @@ -168,11 +168,13 @@ contract RAVE is Test, RAVEBase, JSONBuilder, X509Verifier { // Verify report's MRENCLAVE matches the expected bytes32 mre = quoteBody.readBytes32(MRENCLAVE_OFFSET); - require(mre == mrenclave); + bytes32 mre2 = mrenclave.readBytes32(0); + require(mre2 == mre); // Verify report's MRSIGNER matches the expected bytes32 mrs = quoteBody.readBytes32(MRSIGNER_OFFSET); - require(mrs == mrsigner); + bytes32 mrs2 = mrsigner.readBytes32(0); + require(mrs == mrs2); // Verify report's <= 64B payload matches the expected payload = quoteBody.substring(PAYLOAD_OFFSET, PAYLOAD_SIZE); diff --git a/src/RAVEBase.sol b/src/RAVEBase.sol index 09b0c12..65d6612 100755 --- a/src/RAVEBase.sol +++ b/src/RAVEBase.sol @@ -18,8 +18,8 @@ abstract contract RAVEBase is IRave { bytes memory sig, bytes memory signingMod, bytes memory signingExp, - bytes32 mrenclave, - bytes32 mrsigner + bytes memory mrenclave, + bytes memory mrsigner ) public view virtual returns (bytes memory payload) { } /** @@ -31,7 +31,7 @@ abstract contract RAVEBase is IRave { bytes memory leafX509Cert, bytes memory signingMod, bytes memory signingExp, - bytes32 mrenclave, - bytes32 mrsigner + bytes memory mrenclave, + bytes memory mrsigner ) external view virtual returns (bytes memory payload) { } } diff --git a/test/scripts/bin/error.log b/test/scripts/bin/error.log index dbb7999..4b8e990 100755 --- a/test/scripts/bin/error.log +++ b/test/scripts/bin/error.log @@ -1,2 +1,35 @@ odd len hex '-----BEGIN odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addris_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_sigjson_to_abilibpackpem_to_derre_findrsa_digesttest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addris_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_sigjson_to_abilibpackpem_to_derre_findrsa_digesttest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addris_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_sigjson_to_abilibpackpem_to_derre_findrsa_digesttest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d +whitespace found in report = 'test +'whitespace found in report = 'test\ +'whitespace found in report = 'test +'odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d +odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d +odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d +odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d +odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d +odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d +odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d +odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d +odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d +odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d +odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d +odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d +odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d +odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d +odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d +odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d +odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d +odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d +odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d +odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d +odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d +odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d +odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d +odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d +odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d +odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d +odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d +odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d +odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d +odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d diff --git a/test/scripts/bin/fields_to_abi b/test/scripts/bin/fields_to_abi index e69de29..20d52ea 100755 --- a/test/scripts/bin/fields_to_abi +++ b/test/scripts/bin/fields_to_abi @@ -0,0 +1,11 @@ +#!/usr/bin/python3 + +import sys, eth_abi, binascii + +vals = [] +for hex_val in sys.argv[1:]: + val = binascii.unhexlify(hex_val.encode("ascii")) + vals.append(val) + +payload = eth_abi.encode(['bytes'] * len(vals), vals) +print(payload.hex(), end="") \ No newline at end of file diff --git a/test/scripts/bin/is_valid_report b/test/scripts/bin/is_valid_report index 6779183..0eff59b 100755 --- a/test/scripts/bin/is_valid_report +++ b/test/scripts/bin/is_valid_report @@ -1,7 +1,32 @@ #!/usr/bin/python3 -import re, sys +import re, sys, json +from jsonschema import validate +from lib import * data = sys.stdin.buffer.read() -data = data.encode("utf-8") -print(data) \ No newline at end of file +data = data.decode("utf-8") + +# Whitespace should not exist in the report. +ws = re.findall("\s+", data) +if len(ws): + log(F"whitespace found in report = '{data}'") + print("0", end="") + exit() + +# Should use double quotes. +if "'" in data: + log(f"Double quotes found in report = '{data}'") + print("0", end="") + exit() + +# Use JSON schema to validate the report structure. +try: + instance = json.loads(data) + validate(instance=instance, schema=REPORT_SCHEMA) + print("1", end="") + exit() +except Exception: + log(f"JSON schema validation error for report = '{data}' error = '{str(e)}'") + print("0", end="") + exit() diff --git a/test/scripts/bin/lib/__init__.py b/test/scripts/bin/lib/__init__.py new file mode 100644 index 0000000..734f163 --- /dev/null +++ b/test/scripts/bin/lib/__init__.py @@ -0,0 +1 @@ +from .shared import * \ No newline at end of file diff --git a/test/scripts/bin/lib/shared.py b/test/scripts/bin/lib/shared.py new file mode 100644 index 0000000..5e61900 --- /dev/null +++ b/test/scripts/bin/lib/shared.py @@ -0,0 +1,73 @@ +import sha3 + +REPORT_FIELDS = [ + "id", + "timestamp", + "version", + "epidPseudonym", + "advisoryURL", + "advisoryIDs", + "isvEnclaveQuoteStatus", + "isvEnclaveQuoteBody" +] + +REPORT_SCHEMA = { + "type": "object", + "properties": { + "id": { + "type": "string", + "pattern": "^[0-9]+$" + }, + "timestamp": { + "type": "string", + "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}[.][0-9]+$", + "format": "date-time" + }, + "version": { + "type": "integer", + "minimum": 1 + }, + "epidPseudonym": { + "type": "string", + "pattern": "^[0-9a-zA-Z\\/=+]+$" + }, + "isvEnclaveQuoteStatus": { + "type": "string", + "pattern": "^OK|SW_HARDENING_NEEDED$" + }, + "isvEnclaveQuoteBody": { + "type": "string", + "pattern": "^[0-9a-zA-Z\\/=+]+$" + }, + "advisoryIDs": { + "type": "array", + "items": { + "type": "string", + "pattern": 'INTEL[-]SA[-][0-9]{5}', + } + }, + "advisoryURL": { + "type": "string", + "pattern": "https://security[-]center[.]intel[.]com" + } + }, + "required": [ + "id", + "timestamp", + "version", + "epidPseudonym", + "isvEnclaveQuoteStatus", + "isvEnclaveQuoteBody" + ] +} + +def log(m): + # Writing to file + with open("error.log", "a") as fp: + # Writing data to a file + fp.write(m) + +def sha3_hex(x): + k = sha3.keccak_256() + k.update(x) + return k.hexdigest() \ No newline at end of file diff --git a/test/scripts/bin/prepend_func_sig b/test/scripts/bin/prepend_func_sig new file mode 100755 index 0000000..16b1483 --- /dev/null +++ b/test/scripts/bin/prepend_func_sig @@ -0,0 +1,15 @@ +#!/usr/bin/python3 + +import sys +from lib import * + +data = sys.stdin.buffer.read() +data = data.decode("utf-8") +func_sig = sys.argv[1].encode("ascii") + +# Add function name to out. +out = sha3_hex(func_sig)[:8] +out = out + data + +# Then dump everything as hex. +print(out, end="") \ No newline at end of file diff --git a/test/scripts/bin/report_to_calldata b/test/scripts/bin/report_to_calldata index 3441a36..7d6ea30 100755 --- a/test/scripts/bin/report_to_calldata +++ b/test/scripts/bin/report_to_calldata @@ -1,23 +1,14 @@ #!/usr/bin/python3 import base64, eth_abi, sys, json +from lib import * data = sys.stdin.buffer.read() data = data.decode("utf-8") j = json.loads(data) -names = [ - "id", - "timestamp", - "version", - "epidPseudonym", - "advisoryURL", - "advisoryIDs", - "isvEnclaveQuoteStatus", - "isvEnclaveQuoteBody" -] values = [] -for name in names: +for name in REPORT_FIELDS: value = j[name] # Script takes decoded body. diff --git a/test/scripts/bin/ss_to_abi b/test/scripts/bin/ss_to_abi new file mode 100755 index 0000000..b75332a --- /dev/null +++ b/test/scripts/bin/ss_to_abi @@ -0,0 +1,62 @@ +#!/bin/bash + +# Conf -- set paths to secure signer ############################################# +signer_root=$1 +SECURE_SIGNER_PORT=9001 +if [ "$signer_root" == "" ]; then + echo "./ss_to_abi '/home/matthew/projects/secure-signer'" + exit +fi + +############################################# + +# Constants used by the script. +ROOT_CA_MOD="9F3C647EB5773CBB512D2732C0D7415EBB55A0FA9EDE2E649199E6821DB910D53177370977466A6A5E4786CCD2DDEBD4149D6A2F6325529DD10CC98737B0779C1A07E29C47A1AE004948476C489F45A5A15D7AC8ECC6ACC645ADB43D87679DF59C093BC5A2E9696C5478541B979E754B573914BE55D32FF4C09DDF27219934CD990527B3F92ED78FBF29246ABECB71240EF39C2D7107B447545A7FFB10EB060A68A98580219E36910952683892D6A5E2A80803193E407531404E36B315623799AA825074409754A2DFE8F5AFD5FE631E1FC2AF3808906F28A790D9DD9FE060939B125790C5805D037DF56A99531B96DE69DE33ED226CC1207D1042B5C9AB7F404FC711C0FE4769FB9578B1DC0EC469EA1A25E0FF9914886EF2699B235BB4847DD6FF40B606E6170793C2FB98B314587F9CFD257362DFEAB10B3BD2D97673A1A4BD44C453AAF47FC1F2D3D0F384F74A06F89C089F0DA6CDB7FCEEE8C9821A8E54F25C0416D18C46839A5F8012FBDD3DC74D256279ADC2C0D55AFF6F0622425D1B" +ROOT_CA_EXP="010001" + +# Key variables used by the script. +ss_out_path=$signer_root/ss_out +signer_path=$signer_root/target/x86_64-unknown-linux-musl/release/secure-signer +client_path=$signer_root/target/debug/client +enclave_path=$signer_root/Secure-Signer + +# Get enclave hash values. +pushd ${enclave_path} > /dev/null +mrenclave=$(occlum print mrenclave) # hex +mrsigner=$(occlum print mrsigner) +popd > /dev/null + +# Extract required fields from the keygen response. +keygen_response=$(cat $ss_out_path/keygen_response) +sig=$(echo $keygen_response | jq -r '.evidence.signed_report') +report=$(echo $keygen_response | jq -r '.evidence.raw_report') +certs=$(echo $keygen_response | jq -r '.evidence.signing_cert') + +# Get the right cert from the certs list. +leaf_cert_pem=$(echo "$certs" | ./get_report_cert) + +# Convert it to DER format and store as hex. +leaf_cert_hex=$(echo "$leaf_cert_pem" | ./pem_to_der | ./to_hex) + +# Convert signature from b64 and store as hex. +sig_hex=$(echo "$sig" | base64 --decode | ./to_hex) + +# Convert report JSON to hex format (don't add extra new line!) +report_hex=$(echo -n "$report" | ./to_hex) + +# Extract fields from JSON report and store as ABI encoded hex. +report_calldata_hex=$(echo -n "$report" | ./report_to_calldata) + +# Inputs should all be hex. +abi_out=$( + ./fields_to_abi \ + "$report_calldata_hex" \ + "$sig_hex" \ + "$leaf_cert_hex" \ + "$ROOT_CA_MOD" \ + "$ROOT_CA_EXP" \ + "$mrenclave" \ + "$mrsigner" +) + +echo -n $abi_out diff --git a/test/scripts/preprocess_rave_inputs.py b/test/scripts/preprocess_rave_inputs.py index e617f41..3494671 100755 --- a/test/scripts/preprocess_rave_inputs.py +++ b/test/scripts/preprocess_rave_inputs.py @@ -48,7 +48,6 @@ def cert_wrap(x): # Trucate 0x prefix from args. rm_0x(args) - # unhex_list = [ args["report"], @@ -75,14 +74,14 @@ def cert_wrap(x): "bytes", # Leaf cert "bytes", # Sig modulus "bytes", # Sig exponent - "bytes32", # Mrenclave digest - "bytes32", # Mrsigner digest + "bytes", # Mrenclave digest + "bytes", # Mrsigner digest ], bytes_list ) # Add function name to out. - out = sha3_hex(b"rave(bytes,bytes,bytes,bytes,bytes,bytes32,bytes32)")[:8] + out = sha3_hex(b"rave(bytes,bytes,bytes,bytes,bytes,bytes,bytes)")[:8] out = to_s(out) + ffi_payload.hex() #out = ffi_payload.hex() From ba8d661d8c356e9fb64f8bc48a3dff33e39e6701 Mon Sep 17 00:00:00 2001 From: Jeff Zhao Date: Thu, 17 Aug 2023 15:25:14 -0400 Subject: [PATCH 02/35] fix tests --- test/RAVE.t.sol | 28 ++++++++++++++-------------- test/mocks/MockEvidence.sol | 8 ++++---- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/test/RAVE.t.sol b/test/RAVE.t.sol index 771324b..00a600e 100755 --- a/test/RAVE.t.sol +++ b/test/RAVE.t.sol @@ -22,8 +22,8 @@ abstract contract RAVETester is Test { bytes memory sig = m.sig(); bytes memory signingMod = m.signingMod(); bytes memory signingExp = m.signingExp(); - bytes32 mrenclave = m.mrenclave(); - bytes32 mrsigner = m.mrsigner(); + bytes memory mrenclave = m.mrenclave(); + bytes memory mrsigner = m.mrsigner(); bytes memory payload = m.payload(); run_verifyRemoteAttestation(report, sig, signingMod, signingExp, mrenclave, mrsigner, payload); } @@ -34,8 +34,8 @@ abstract contract RAVETester is Test { bytes memory sig, bytes memory signingMod, bytes memory signingExp, - bytes32 mrenclave, - bytes32 mrsigner, + bytes memory mrenclave, + bytes memory mrsigner, bytes memory expPayload ) public view { bytes memory gotPayload = c.verifyRemoteAttestation(report, sig, signingMod, signingExp, mrenclave, mrsigner); @@ -46,8 +46,8 @@ abstract contract RAVETester is Test { bytes memory report = m.report(); bytes memory sig = m.sig(); bytes memory signingCert = m.signingCert(); - bytes32 mrenclave = m.mrenclave(); - bytes32 mrsigner = m.mrsigner(); + bytes memory mrenclave = m.mrenclave(); + bytes memory mrsigner = m.mrsigner(); bytes memory payload = m.payload(); // Intel's root CA modulus bytes memory intelRootModulus = @@ -65,8 +65,8 @@ abstract contract RAVETester is Test { bytes memory signingCert, bytes memory intelRootModulus, bytes memory intelRootExponent, - bytes32 mrenclave, - bytes32 mrsigner, + bytes memory mrenclave, + bytes memory mrsigner, bytes memory expPayload ) public view { // Run rave to extract its payload @@ -127,7 +127,7 @@ contract RaveFuzzer is Test, X509GenHelper, BytesFFIFuzzer { return (signature, values); } - function runRAVE(bytes32 mrenclave, bytes32 mrsigner, bytes memory p) public { + function runRAVE(bytes memory mrenclave, bytes memory mrsigner, bytes memory p) public { vm.assume(p.length >= 64); // Convert the random bytes into valid utf-8 bytes @@ -182,8 +182,8 @@ contract RaveInstanceTest is RaveFuzzer { function test() public { return; - bytes32 mrenclave = hex"d0ae774774c2064a60dd92541fcc7cb8b3acdea0d793f3b27a27a44dbf71e75f"; - bytes32 mrsigner = hex"83d719e77deaca1470f6baf62a4d774303c899db69020f9c70ee1dfc08c7ce9e"; + bytes memory mrenclave = hex"d0ae774774c2064a60dd92541fcc7cb8b3acdea0d793f3b27a27a44dbf71e75f"; + bytes memory mrsigner = hex"83d719e77deaca1470f6baf62a4d774303c899db69020f9c70ee1dfc08c7ce9e"; bytes memory p = hex"83d719e77deaca1470f6baf62a4d774303c899db69020f9c70ee1dfc08c7ce9e83d719e77deaca1470f6baf62a4d774303c899db69020f9c70ee1dfc08c7ce9e"; @@ -197,8 +197,8 @@ contract RaveSanityTester is Test { bool useCachedX509s = true; function testOnSanityCheckedValues() public { - bytes32 mrenclave = hex"d0ae774774c2064a60dd92541fcc7cb8b3acdea0d793f3b27a27a44dbf71e75f"; - bytes32 mrsigner = hex"83d719e77deaca1470f6baf62a4d774303c899db69020f9c70ee1dfc08c7ce9e"; + bytes memory mrenclave = hex"d0ae774774c2064a60dd92541fcc7cb8b3acdea0d793f3b27a27a44dbf71e75f"; + bytes memory mrsigner = hex"83d719e77deaca1470f6baf62a4d774303c899db69020f9c70ee1dfc08c7ce9e"; bytes memory p = hex"83d719e77deaca1470f6baf62a4d774303c899db69020f9c70ee1dfc08c7ce9e83d719e77deaca1470f6baf62a4d774303c899db69020f9c70ee1dfc08c7ce9e"; @@ -237,7 +237,7 @@ contract RaveFuzzTester is Test { } // Run a fuzz test sequentially on each RAVe parameterization - function testRaveFuzz(bytes32 mrenclave, bytes32 mrsigner, bytes memory p) public { + function testRaveFuzz(bytes memory mrenclave, bytes memory mrsigner, bytes memory p) public { vm.assume(p.length >= 64); for (uint256 i = 0; i < numFuzzers; i++) { c[i].runRAVE(mrenclave, mrsigner, p); diff --git a/test/mocks/MockEvidence.sol b/test/mocks/MockEvidence.sol index c69c9bc..5b6e956 100755 --- a/test/mocks/MockEvidence.sol +++ b/test/mocks/MockEvidence.sol @@ -7,8 +7,8 @@ abstract contract MockEvidence { function signingCert() public pure virtual returns (bytes memory); function signingMod() public pure virtual returns (bytes memory); function signingExp() public pure virtual returns (bytes memory); - function mrenclave() public pure virtual returns (bytes32); - function mrsigner() public pure virtual returns (bytes32); + function mrenclave() public pure virtual returns (bytes memory); + function mrsigner() public pure virtual returns (bytes memory); function payload() public pure virtual returns (bytes memory); } @@ -53,12 +53,12 @@ contract ValidBLSEvidence is MockEvidence { } // The expected MRENCLAVE value in this specific report - function mrenclave() public pure override returns (bytes32) { + function mrenclave() public pure override returns (bytes memory) { return hex"d0ae774774c2064a60dd92541fcc7cb8b3acdea0d793f3b27a27a44dbf71e75f"; } // The expected MRSIGNER value in this specific report - function mrsigner() public pure override returns (bytes32) { + function mrsigner() public pure override returns (bytes memory) { return hex"83d719e77deaca1470f6baf62a4d774303c899db69020f9c70ee1dfc08c7ce9e"; } From 756594989d1ab7118ff577ecf78830277415286f Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Mon, 21 Aug 2023 03:58:10 +0000 Subject: [PATCH 03/35] Working on making DER decoder safer. --- src/ASN1Decode.sol | 37 ++++++++++++++++++++-- test/ASN1Decode.t.sol | 72 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+), 3 deletions(-) create mode 100644 test/ASN1Decode.t.sol diff --git a/src/ASN1Decode.sol b/src/ASN1Decode.sol index da7da1c..8771e56 100755 --- a/src/ASN1Decode.sol +++ b/src/ASN1Decode.sol @@ -38,6 +38,13 @@ library Asn1Decode { * @return A pointer to the outermost node */ function root(bytes memory der) internal pure returns (uint256) { + // seq byte (30) + // len pt 1 (x) + // len pt 2 (optional) + // ... contentbytes (1 or more) ... + // minimum sanity check + // Not the only length check. + require(der.length >= 3); return readNodeLength(der, 0); } @@ -175,25 +182,49 @@ library Asn1Decode { } function readNodeLength(bytes memory der, uint256 ix) private pure returns (uint256) { - uint256 length; - uint80 ixFirstContentByte; - uint80 ixLastContentByte; + // Avoid overflow for first len byte. + require((ix + 1) < der.length); + + // Read length of a DER segment. + uint256 length = 0; + uint80 ixFirstContentByte = 0; + uint80 ixLastContentByte = 0; if ((der[ix + 1] & 0x80) == 0) { length = uint8(der[ix + 1]); ixFirstContentByte = uint80(ix + 2); ixLastContentByte = uint80(ixFirstContentByte + length - 1); } else { + // How large is the length field? uint8 lengthbytesLength = uint8(der[ix + 1] & 0x7F); + + // Avoid overflow. + require((ix + 2) < der.length); if (lengthbytesLength == 1) { length = der.readUint8(ix + 2); } else if (lengthbytesLength == 2) { + require((der.length - (ix + 2)) >= 2); length = der.readUint16(ix + 2); } else { + // Ensure enough bytes left. + require((der.length - (ix + 2)) >= lengthbytesLength); length = uint256(der.readBytesN(ix + 2, lengthbytesLength) >> (32 - lengthbytesLength) * 8); } + + // Content length field must be positive. + require(length > 0); ixFirstContentByte = uint80(ix + 2 + lengthbytesLength); ixLastContentByte = uint80(ixFirstContentByte + length - 1); } + + // Sanity checks for ptrs. + require(ixFirstContentByte >= 2); + require(ixLastContentByte > 2); + + // The expected content segment must not overflow. + require(ixFirstContentByte < der.length); + require(ixLastContentByte < der.length); + + // Return the nodeptr structure. return NodePtr.getPtr(ix, ixFirstContentByte, ixLastContentByte); } } diff --git a/test/ASN1Decode.t.sol b/test/ASN1Decode.t.sol new file mode 100644 index 0000000..6640fbb --- /dev/null +++ b/test/ASN1Decode.t.sol @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity >=0.8.0 <0.9.0; + +import { Test, console } from "forge-std/Test.sol"; +import { BytesUtils } from "ens-contracts/dnssec-oracle/BytesUtils.sol"; +import { Utils } from "rave/Utils.sol"; +import { NodePtr, Asn1Decode } from "rave/ASN1Decode.sol"; + +contract TestASN1 is Test { + + using Asn1Decode for bytes; + using BytesUtils for bytes; + using Utils for bytes; + + bytes cert = hex"308204a130820309a003020102020900d107765d32a3b096300d06092a864886f70d01010b0500307e310b3009060355040613025553310b300906035504080c0243413114301206035504070c0b53616e746120436c617261311a3018060355040a0c11496e74656c20436f72706f726174696f6e3130302e06035504030c27496e74656c20534758204174746573746174696f6e205265706f7274205369676e696e67204341301e170d3136313132323039333635385a170d3236313132303039333635385a307b310b3009060355040613025553310b300906035504080c0243413114301206035504070c0b53616e746120436c617261311a3018060355040a0c11496e74656c20436f72706f726174696f6e312d302b06035504030c24496e74656c20534758204174746573746174696f6e205265706f7274205369676e696e6730820122300d06092a864886f70d01010105000382010f003082010a0282010100a97a2de0e66ea6147c9ee745ac0162686c7192099afc4b3f040fad6de093511d74e802f510d716038157dcaf84f4104bd3fed7e6b8f99c8817fd1ff5b9b864296c3d81fa8f1b729e02d21d72ffee4ced725efe74bea68fbc4d4244286fcdd4bf64406a439a15bcb4cf67754489c423972b4a80df5c2e7c5bc2dbaf2d42bb7b244f7c95bf92c75d3b33fc5410678a89589d1083da3acc459f2704cd99598c275e7c1878e00757e5bdb4e840226c11c0a17ff79c80b15c1ddb5af21cc2417061fbd2a2da819ed3b72b7efaa3bfebe2805c9b8ac19aa346512d484cfc81941e15f55881cc127e8f7aa12300cd5afb5742fa1d20cb467a5beb1c666cf76a368978b50203010001a381a43081a1301f0603551d2304183016801478437b76a67ebcd0af7e4237eb357c3b8701513c300e0603551d0f0101ff0404030206c0300c0603551d130101ff0402300030600603551d1f045930573055a053a051864f687474703a2f2f7472757374656473657276696365732e696e74656c2e636f6d2f636f6e74656e742f43524c2f5347582f4174746573746174696f6e5265706f72745369676e696e6743412e63726c300d06092a864886f70d01010b050003820181006708b61b5c2bd215473e2b46af99284fbb939d3f3b152c996f1a6af3b329bd220b1d3b610f6bce2e6753bded304db21912f385256216cfcba456bd96940be892f5690c260d1ef84f1606040222e5fe08e5326808212a447cfdd64a46e94bf29f6b4b9a721d25b3c4e2f62f58baed5d77c505248f0f801f9fbfb7fd752080095cee80938b339f6dbb4e165600e20e4a718812d49d9901e310a9b51d66c79909c6996599fae6d76a79ef145d9943bf1d3e35d3b42d1fb9a45cbe8ee334c166eee7d32fcdc9935db8ec8bb1d8eb3779dd8ab92b6e387f0147450f1e381d08581fb83df33b15e000a59be57ea94a3a52dc64bdaec959b3464c91e725bbdaea3d99e857e380a23c9d9fb1ef58e9e42d71f12130f9261d7234d6c37e2b03dba40dfdfb13ac4ad8e13fd3756356b6b50015a3ec9580b815d87c2cef715cd28df00bbf2a3c403ebf6691b3f05edd9143803ca085cff57e053eec2f8fea46ea778a68c9be885bc28225bc5f309be4a2b74d3a03945319dd3c7122fed6ff53bb8b8cb3a03c"; + + constructor() { } + + /* + function testASN1RootOverflow() public { + bytes memory bugCert = bytes(cert); + + // Max certificate length portion. + bugCert[1] = hex"02"; + bugCert[2] = hex"99"; + bugCert[3] = hex"99"; + + // [1] len bytes length? + + // Attempt to load the 'root node' of the cert. + uint256 rootPtr = bugCert.root(); + bugCert.firstChildOf(rootPtr); + + test read uint, u16, readn overflow. + } + */ + + function testASN1Uint8Overflow() public { + vm.expectRevert(); + bytes memory buf = hex"029901"; + + uint256 rootPtr = buf.root(); + buf.uintAt(rootPtr); + } + + function testASN1IntegerOverflow() public { + vm.expectRevert(); + + // 02 (type = INTEGER) + // 99 (len = OVERFLOW) + // ... actual buffer to traverse + bytes memory x = hex"0299010010"; + + uint256 rootPtr = x.root(); + uint256 out = x.uintAt(rootPtr); + console.log(out); + } +} + +/* + +https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/ + +3082 +30 SEQUENCE +82 extended byte for tag data? +len + +The length of any DER field can be expressed as a series of up to 126 bytes. So the biggest INTEGER you can represent in DER is 256(2**1008)-1. For a truly unbounded INTEGER you’d have to encode in BER, which allows indefinitely-long fields. + + +*/ From 7be761c88caa4d77f4491b28dda2d24000f044c7 Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Mon, 21 Aug 2023 05:10:49 +0000 Subject: [PATCH 04/35] Saving checks for read no length and root. --- src/ASN1Decode.sol | 17 ++++++++++---- test/ASN1Decode.t.sol | 54 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 5 deletions(-) diff --git a/src/ASN1Decode.sol b/src/ASN1Decode.sol index 8771e56..e7454cb 100755 --- a/src/ASN1Decode.sol +++ b/src/ASN1Decode.sol @@ -3,6 +3,7 @@ pragma solidity >=0.8.0 <0.9.0; import { BytesUtils } from "ens-contracts/dnssec-oracle/BytesUtils.sol"; +import { Math } from "openzeppelin-contracts/contracts/utils/math/Math.sol"; library NodePtr { // Unpack first byte index @@ -190,9 +191,9 @@ library Asn1Decode { uint80 ixFirstContentByte = 0; uint80 ixLastContentByte = 0; if ((der[ix + 1] & 0x80) == 0) { - length = uint8(der[ix + 1]); + length = Math.max(uint8(der[ix + 1]), 1); ixFirstContentByte = uint80(ix + 2); - ixLastContentByte = uint80(ixFirstContentByte + length - 1); + ixLastContentByte = uint80(ixFirstContentByte + (length - 1)); } else { // How large is the length field? uint8 lengthbytesLength = uint8(der[ix + 1] & 0x7F); @@ -205,20 +206,26 @@ library Asn1Decode { require((der.length - (ix + 2)) >= 2); length = der.readUint16(ix + 2); } else { - // Ensure enough bytes left. + // Ensure enough bytes left for len no. require((der.length - (ix + 2)) >= lengthbytesLength); + require(lengthbytesLength <= 32); + + // Read variable length len field. + // Shift out the bit length of the length. + // Max shift is limited to sizeof length. + // But zero is still checked for bellow. length = uint256(der.readBytesN(ix + 2, lengthbytesLength) >> (32 - lengthbytesLength) * 8); } // Content length field must be positive. require(length > 0); ixFirstContentByte = uint80(ix + 2 + lengthbytesLength); - ixLastContentByte = uint80(ixFirstContentByte + length - 1); + ixLastContentByte = uint80(ixFirstContentByte + (length - 1)); } // Sanity checks for ptrs. require(ixFirstContentByte >= 2); - require(ixLastContentByte > 2); + require(ixLastContentByte >= 2); // The expected content segment must not overflow. require(ixFirstContentByte < der.length); diff --git a/test/ASN1Decode.t.sol b/test/ASN1Decode.t.sol index 6640fbb..18ae42f 100644 --- a/test/ASN1Decode.t.sol +++ b/test/ASN1Decode.t.sol @@ -35,6 +35,42 @@ contract TestASN1 is Test { } */ + function testASN1RootOverflowIf() public { + vm.expectRevert(); + + // High order len bit is set + // which triggers else in readNodeLen + bytes memory buf = hex"0281"; + buf.root(); + } + + function testASN1RootOverflowElseIf() public { + vm.expectRevert(); + + // High order len bit is not set + // which triggers else, if in readNodeLen + bytes memory buf = hex"0201"; + buf.root(); + } + + function testASN1RootOverflowElseElIf() public { + vm.expectRevert(); + + // High order len bit is not set + // which triggers else, if in readNodeLen + bytes memory buf = hex"0202"; + buf.root(); + } + + function testASN1RootOverflowElseElse() public { + vm.expectRevert(); + + // High order len bit is not set + // which triggers else, if in readNodeLen + bytes memory buf = hex"0203"; + buf.root(); + } + function testASN1Uint8Overflow() public { vm.expectRevert(); bytes memory buf = hex"029901"; @@ -55,6 +91,24 @@ contract TestASN1 is Test { uint256 out = x.uintAt(rootPtr); console.log(out); } + + function testASN1RootSuccessChances() public { + // if, len = 1, buf 1 + bytes memory a = hex"02010101"; + a.root(); + + // if:if, len 1, buf 1 + bytes memory b = hex"02810101"; + b.root(); + + // if:elseif, len 1 (2 bytes), buf 1 + bytes memory c = hex"0282000101"; + c.root(); + + // if:..else var len 1 (3 bytes), buf 1 + bytes memory d = hex"028300000101"; + d.root(); + } } /* From 3b1a6220075d907494988ff614873cb936fda66f Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Tue, 22 Aug 2023 02:10:47 +0000 Subject: [PATCH 05/35] Slowly testing DER. --- src/ASN1Decode.sol | 88 +++++++++++++++++++++++++------------------ src/X509Verifier.sol | 2 +- test/ASN1Decode.t.sol | 30 +++++++++++++++ 3 files changed, 82 insertions(+), 38 deletions(-) diff --git a/src/ASN1Decode.sol b/src/ASN1Decode.sol index e7454cb..5a8b09c 100755 --- a/src/ASN1Decode.sol +++ b/src/ASN1Decode.sol @@ -7,25 +7,25 @@ import { Math } from "openzeppelin-contracts/contracts/utils/math/Math.sol"; library NodePtr { // Unpack first byte index - function ixs(uint256 self) internal pure returns (uint256) { + function type_index(uint256 self) internal pure returns (uint256) { return uint80(self); } - // Unpack first content byte index - function ixf(uint256 self) internal pure returns (uint256) { + // Unpack first content byte index + function content_index(uint256 self) internal pure returns (uint256) { return uint80(self >> 80); } - // Unpack last content byte index - function ixl(uint256 self) internal pure returns (uint256) { + // Unpack last content byte index + function end_index(uint256 self) internal pure returns (uint256) { return uint80(self >> 160); } - // Pack 3 uint80s into a uint256 - function getPtr(uint256 _ixs, uint256 _ixf, uint256 _ixl) internal pure returns (uint256) { - _ixs |= _ixf << 80; - _ixs |= _ixl << 160; - return _ixs; + // Pack 3 uint80s into a uint256 + function getPtr(uint256 _type_index, uint256 _content_index, uint256 _end_index) internal pure returns (uint256) { + _type_index |= _content_index << 80; + _type_index |= _end_index << 160; + return _type_index; } } @@ -55,8 +55,8 @@ library Asn1Decode { * @return A pointer to the outermost node */ function rootOfBitStringAt(bytes memory der, uint256 ptr) internal pure returns (uint256) { - require(der[ptr.ixs()] == 0x03, "Not type BIT STRING"); - return readNodeLength(der, ptr.ixf() + 1); + require(der[ptr.type_index()] == 0x03, "Not type BIT STRING"); + return readNodeLength(der, ptr.content_index() + 1); } /* @@ -65,8 +65,8 @@ library Asn1Decode { * @return A pointer to the outermost node */ function rootOfOctetStringAt(bytes memory der, uint256 ptr) internal pure returns (uint256) { - require(der[ptr.ixs()] == 0x04, "Not type OCTET STRING"); - return readNodeLength(der, ptr.ixf()); + require(der[ptr.type_index()] == 0x04, "Not type OCTET STRING"); + return readNodeLength(der, ptr.content_index()); } /* @@ -76,7 +76,8 @@ library Asn1Decode { * @return A pointer to the next sibling node */ function nextSiblingOf(bytes memory der, uint256 ptr) internal pure returns (uint256) { - return readNodeLength(der, ptr.ixl() + 1); + require(ptr < der.length); + return readNodeLength(der, ptr.end_index() + 1); } /* @@ -86,8 +87,10 @@ library Asn1Decode { * @return A pointer to the first child node */ function firstChildOf(bytes memory der, uint256 ptr) internal pure returns (uint256) { - require(der[ptr.ixs()] & 0x20 == 0x20, "Not a constructed type"); - return readNodeLength(der, ptr.ixf()); + require(ptr.type_index() < der.length); + require(ptr.content_index() < der.length); + require(der[ptr.type_index()] & 0x20 == 0x20, "Not a constructed type"); + return readNodeLength(der, ptr.content_index()); } /* @@ -97,7 +100,16 @@ library Asn1Decode { * @return True iff j is child of i or i is child of j. */ function isChildOf(uint256 i, uint256 j) internal pure returns (bool) { - return (((i.ixf() <= j.ixs()) && (j.ixl() <= i.ixl())) || ((j.ixf() <= i.ixs()) && (i.ixl() <= j.ixl()))); + return ( + ( + (i.content_index() <= j.type_index()) && + (j.end_index() <= i.end_index()) + ) || + ( + (j.content_index() <= i.type_index()) && + (i.end_index() <= j.end_index()) + ) + ); } /* @@ -107,7 +119,7 @@ library Asn1Decode { * @return Value bytes of node */ function bytesAt(bytes memory der, uint256 ptr) internal pure returns (bytes memory) { - return der.substring(ptr.ixf(), ptr.ixl() + 1 - ptr.ixf()); + return der.substring(ptr.content_index(), ptr.end_index() + 1 - ptr.content_index()); } /* @@ -117,7 +129,7 @@ library Asn1Decode { * @return All bytes of node */ function allBytesAt(bytes memory der, uint256 ptr) internal pure returns (bytes memory) { - return der.substring(ptr.ixs(), ptr.ixl() + 1 - ptr.ixs()); + return der.substring(ptr.type_index(), ptr.end_index() + 1 - ptr.type_index()); } /* @@ -127,7 +139,7 @@ library Asn1Decode { * @return Value bytes of node as bytes32 */ function bytes32At(bytes memory der, uint256 ptr) internal pure returns (bytes32) { - return der.readBytesN(ptr.ixf(), ptr.ixl() + 1 - ptr.ixf()); + return der.readBytesN(ptr.content_index(), ptr.end_index() + 1 - ptr.content_index()); } /* @@ -137,10 +149,10 @@ library Asn1Decode { * @return Uint value of node */ function uintAt(bytes memory der, uint256 ptr) internal pure returns (uint256) { - require(der[ptr.ixs()] == 0x02, "Not type INTEGER"); - require(der[ptr.ixf()] & 0x80 == 0, "Not positive"); - uint256 len = ptr.ixl() + 1 - ptr.ixf(); - return uint256(der.readBytesN(ptr.ixf(), len) >> (32 - len) * 8); + require(der[ptr.type_index()] == 0x02, "Not type INTEGER"); + require(der[ptr.content_index()] & 0x80 == 0, "Not positive"); + uint256 len = ptr.end_index() + 1 - ptr.content_index(); + return uint256(der.readBytesN(ptr.content_index(), len) >> (32 - len) * 8); } /* @@ -150,22 +162,22 @@ library Asn1Decode { * @return Value bytes of a positive integer node */ function uintBytesAt(bytes memory der, uint256 ptr) internal pure returns (bytes memory) { - require(der[ptr.ixs()] == 0x02, "Not type INTEGER"); - require(der[ptr.ixf()] & 0x80 == 0, "Not positive"); - uint256 valueLength = ptr.ixl() + 1 - ptr.ixf(); - if (der[ptr.ixf()] == 0) { - return der.substring(ptr.ixf() + 1, valueLength - 1); + require(der[ptr.type_index()] == 0x02, "Not type INTEGER"); + require(der[ptr.content_index()] & 0x80 == 0, "Not positive"); + uint256 valueLength = ptr.end_index() + 1 - ptr.content_index(); + if (der[ptr.content_index()] == 0) { + return der.substring(ptr.content_index() + 1, valueLength - 1); } else { - return der.substring(ptr.ixf(), valueLength); + return der.substring(ptr.content_index(), valueLength); } } function keccakOfBytesAt(bytes memory der, uint256 ptr) internal pure returns (bytes32) { - return der.keccak(ptr.ixf(), ptr.ixl() + 1 - ptr.ixf()); + return der.keccak(ptr.content_index(), ptr.end_index() + 1 - ptr.content_index()); } function keccakOfAllBytesAt(bytes memory der, uint256 ptr) internal pure returns (bytes32) { - return der.keccak(ptr.ixs(), ptr.ixl() + 1 - ptr.ixs()); + return der.keccak(ptr.type_index(), ptr.end_index() + 1 - ptr.type_index()); } /* @@ -175,11 +187,13 @@ library Asn1Decode { * @return Value of bitstring converted to bytes */ function bitstringAt(bytes memory der, uint256 ptr) internal pure returns (bytes memory) { - require(der[ptr.ixs()] == 0x03, "Not type BIT STRING"); + require(der[ptr.type_index()] == 0x03, "Not type BIT STRING"); // Only 00 padded bitstr can be converted to bytestr! - require(der[ptr.ixf()] == 0x00); - uint256 valueLength = ptr.ixl() + 1 - ptr.ixf(); - return der.substring(ptr.ixf() + 1, valueLength - 1); + require(der[ptr.content_index()] == 0x00); + uint256 valueLength = ptr.end_index() + 1 - ptr.content_index(); + + + return der.substring(ptr.content_index() + 1, valueLength - 1); } function readNodeLength(bytes memory der, uint256 ix) private pure returns (uint256) { diff --git a/src/X509Verifier.sol b/src/X509Verifier.sol index 17eac34..5239b76 100755 --- a/src/X509Verifier.sol +++ b/src/X509Verifier.sol @@ -217,7 +217,7 @@ contract X509Verifier is Test { uint256 ptr = cert.firstChildOf(tbsPtr); // Account for v1 vs v3 - if (cert[NodePtr.ixs(ptr)] == 0xa0) { + if (cert[NodePtr.type_index(ptr)] == 0xa0) { ptr = cert.nextSiblingOf(ptr); } diff --git a/test/ASN1Decode.t.sol b/test/ASN1Decode.t.sol index 18ae42f..d203fe8 100644 --- a/test/ASN1Decode.t.sol +++ b/test/ASN1Decode.t.sol @@ -11,6 +11,7 @@ contract TestASN1 is Test { using Asn1Decode for bytes; using BytesUtils for bytes; using Utils for bytes; + using NodePtr for uint256; bytes cert = hex"308204a130820309a003020102020900d107765d32a3b096300d06092a864886f70d01010b0500307e310b3009060355040613025553310b300906035504080c0243413114301206035504070c0b53616e746120436c617261311a3018060355040a0c11496e74656c20436f72706f726174696f6e3130302e06035504030c27496e74656c20534758204174746573746174696f6e205265706f7274205369676e696e67204341301e170d3136313132323039333635385a170d3236313132303039333635385a307b310b3009060355040613025553310b300906035504080c0243413114301206035504070c0b53616e746120436c617261311a3018060355040a0c11496e74656c20436f72706f726174696f6e312d302b06035504030c24496e74656c20534758204174746573746174696f6e205265706f7274205369676e696e6730820122300d06092a864886f70d01010105000382010f003082010a0282010100a97a2de0e66ea6147c9ee745ac0162686c7192099afc4b3f040fad6de093511d74e802f510d716038157dcaf84f4104bd3fed7e6b8f99c8817fd1ff5b9b864296c3d81fa8f1b729e02d21d72ffee4ced725efe74bea68fbc4d4244286fcdd4bf64406a439a15bcb4cf67754489c423972b4a80df5c2e7c5bc2dbaf2d42bb7b244f7c95bf92c75d3b33fc5410678a89589d1083da3acc459f2704cd99598c275e7c1878e00757e5bdb4e840226c11c0a17ff79c80b15c1ddb5af21cc2417061fbd2a2da819ed3b72b7efaa3bfebe2805c9b8ac19aa346512d484cfc81941e15f55881cc127e8f7aa12300cd5afb5742fa1d20cb467a5beb1c666cf76a368978b50203010001a381a43081a1301f0603551d2304183016801478437b76a67ebcd0af7e4237eb357c3b8701513c300e0603551d0f0101ff0404030206c0300c0603551d130101ff0402300030600603551d1f045930573055a053a051864f687474703a2f2f7472757374656473657276696365732e696e74656c2e636f6d2f636f6e74656e742f43524c2f5347582f4174746573746174696f6e5265706f72745369676e696e6743412e63726c300d06092a864886f70d01010b050003820181006708b61b5c2bd215473e2b46af99284fbb939d3f3b152c996f1a6af3b329bd220b1d3b610f6bce2e6753bded304db21912f385256216cfcba456bd96940be892f5690c260d1ef84f1606040222e5fe08e5326808212a447cfdd64a46e94bf29f6b4b9a721d25b3c4e2f62f58baed5d77c505248f0f801f9fbfb7fd752080095cee80938b339f6dbb4e165600e20e4a718812d49d9901e310a9b51d66c79909c6996599fae6d76a79ef145d9943bf1d3e35d3b42d1fb9a45cbe8ee334c166eee7d32fcdc9935db8ec8bb1d8eb3779dd8ab92b6e387f0147450f1e381d08581fb83df33b15e000a59be57ea94a3a52dc64bdaec959b3464c91e725bbdaea3d99e857e380a23c9d9fb1ef58e9e42d71f12130f9261d7234d6c37e2b03dba40dfdfb13ac4ad8e13fd3756356b6b50015a3ec9580b815d87c2cef715cd28df00bbf2a3c403ebf6691b3f05edd9143803ca085cff57e053eec2f8fea46ea778a68c9be885bc28225bc5f309be4a2b74d3a03945319dd3c7122fed6ff53bb8b8cb3a03c"; @@ -35,6 +36,33 @@ contract TestASN1 is Test { } */ + function testANS1BitStrAtOverflow() public { + + return; + + // High order len bit is set + // which triggers else in readNodeLen + bytes memory buf = hex"030400112233"; + + // 000000000000000000000000000000020000000000000005 + uint256 ptr = 0; + ptr = NodePtr.getPtr(0, 200, 200); + console.log(ptr.content_index()); + buf.bitstringAt(ptr); + } + + function testANS1BitStrAtSuccess() public { + // High order len bit is set + // which triggers else in readNodeLen + bytes memory buf = hex"030400112233"; + + // 000000000000000000000000000000020000000000000005 + uint256 ptr = 0; + ptr = NodePtr.getPtr(0, 2, 5); + + buf.bitstringAt(ptr); + } + function testASN1RootOverflowIf() public { vm.expectRevert(); @@ -113,6 +141,8 @@ contract TestASN1 is Test { /* +TODO: check for x509 hdr byte sequence + https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/ 3082 From 49ff0f4ecfc253c82b3661e077e6edffcb8ee7e3 Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Tue, 22 Aug 2023 03:49:52 +0000 Subject: [PATCH 06/35] Saving ASN.1 tests. --- src/ASN1Decode.sol | 59 ++++++++++++++++----- test/ASN1Decode.t.sol | 116 +++++++++++++++++++++++++++++++++++++----- 2 files changed, 150 insertions(+), 25 deletions(-) diff --git a/src/ASN1Decode.sol b/src/ASN1Decode.sol index 5a8b09c..92b575b 100755 --- a/src/ASN1Decode.sol +++ b/src/ASN1Decode.sol @@ -21,12 +21,22 @@ library NodePtr { return uint80(self >> 160); } + function content_len(uint256 self) public pure returns (uint256) { + return (end_index(self) - content_index(self)) + 1; + } + // Pack 3 uint80s into a uint256 function getPtr(uint256 _type_index, uint256 _content_index, uint256 _end_index) internal pure returns (uint256) { _type_index |= _content_index << 80; _type_index |= _end_index << 160; return _type_index; } + + function overflowCheck(uint256 self, uint len) internal pure { + require(type_index(self) < uint256(len)); + require(content_index(self) < uint256(len)); + require(end_index(self) < uint256(len)); + } } library Asn1Decode { @@ -55,6 +65,7 @@ library Asn1Decode { * @return A pointer to the outermost node */ function rootOfBitStringAt(bytes memory der, uint256 ptr) internal pure returns (uint256) { + ptr.overflowCheck(der.length); require(der[ptr.type_index()] == 0x03, "Not type BIT STRING"); return readNodeLength(der, ptr.content_index() + 1); } @@ -65,6 +76,7 @@ library Asn1Decode { * @return A pointer to the outermost node */ function rootOfOctetStringAt(bytes memory der, uint256 ptr) internal pure returns (uint256) { + ptr.overflowCheck(der.length); require(der[ptr.type_index()] == 0x04, "Not type OCTET STRING"); return readNodeLength(der, ptr.content_index()); } @@ -76,7 +88,7 @@ library Asn1Decode { * @return A pointer to the next sibling node */ function nextSiblingOf(bytes memory der, uint256 ptr) internal pure returns (uint256) { - require(ptr < der.length); + ptr.overflowCheck(der.length); return readNodeLength(der, ptr.end_index() + 1); } @@ -87,8 +99,7 @@ library Asn1Decode { * @return A pointer to the first child node */ function firstChildOf(bytes memory der, uint256 ptr) internal pure returns (uint256) { - require(ptr.type_index() < der.length); - require(ptr.content_index() < der.length); + ptr.overflowCheck(der.length); require(der[ptr.type_index()] & 0x20 == 0x20, "Not a constructed type"); return readNodeLength(der, ptr.content_index()); } @@ -119,7 +130,8 @@ library Asn1Decode { * @return Value bytes of node */ function bytesAt(bytes memory der, uint256 ptr) internal pure returns (bytes memory) { - return der.substring(ptr.content_index(), ptr.end_index() + 1 - ptr.content_index()); + ptr.overflowCheck(der.length); + return der.substring(ptr.content_index(), ptr.content_len()); } /* @@ -129,7 +141,8 @@ library Asn1Decode { * @return All bytes of node */ function allBytesAt(bytes memory der, uint256 ptr) internal pure returns (bytes memory) { - return der.substring(ptr.type_index(), ptr.end_index() + 1 - ptr.type_index()); + ptr.overflowCheck(der.length); + return der.substring(ptr.type_index(), ptr.content_len()); } /* @@ -139,7 +152,9 @@ library Asn1Decode { * @return Value bytes of node as bytes32 */ function bytes32At(bytes memory der, uint256 ptr) internal pure returns (bytes32) { - return der.readBytesN(ptr.content_index(), ptr.end_index() + 1 - ptr.content_index()); + ptr.overflowCheck(der.length); + require(ptr.content_len() <= 32); + return der.readBytesN(ptr.content_index(), ptr.content_len()); } /* @@ -149,10 +164,16 @@ library Asn1Decode { * @return Uint value of node */ function uintAt(bytes memory der, uint256 ptr) internal pure returns (uint256) { + ptr.overflowCheck(der.length); require(der[ptr.type_index()] == 0x02, "Not type INTEGER"); require(der[ptr.content_index()] & 0x80 == 0, "Not positive"); - uint256 len = ptr.end_index() + 1 - ptr.content_index(); - return uint256(der.readBytesN(ptr.content_index(), len) >> (32 - len) * 8); + uint256 len = ptr.content_len(); + + require(len <= 32); + return uint256( + der.readBytesN(ptr.content_index(), len) >> + ((32 - len) * 8) + ); } /* @@ -162,9 +183,13 @@ library Asn1Decode { * @return Value bytes of a positive integer node */ function uintBytesAt(bytes memory der, uint256 ptr) internal pure returns (bytes memory) { + ptr.overflowCheck(der.length); require(der[ptr.type_index()] == 0x02, "Not type INTEGER"); require(der[ptr.content_index()] & 0x80 == 0, "Not positive"); - uint256 valueLength = ptr.end_index() + 1 - ptr.content_index(); + uint256 valueLength = ptr.content_len(); + return der.substring(ptr.content_index(), ptr.content_len()); + + // This seems invalid. if (der[ptr.content_index()] == 0) { return der.substring(ptr.content_index() + 1, valueLength - 1); } else { @@ -173,11 +198,13 @@ library Asn1Decode { } function keccakOfBytesAt(bytes memory der, uint256 ptr) internal pure returns (bytes32) { - return der.keccak(ptr.content_index(), ptr.end_index() + 1 - ptr.content_index()); + ptr.overflowCheck(der.length); + return der.keccak(ptr.content_index(), ptr.content_len()); } function keccakOfAllBytesAt(bytes memory der, uint256 ptr) internal pure returns (bytes32) { - return der.keccak(ptr.type_index(), ptr.end_index() + 1 - ptr.type_index()); + ptr.overflowCheck(der.length); + return der.keccak(ptr.type_index(), ptr.content_len()); } /* @@ -187,12 +214,18 @@ library Asn1Decode { * @return Value of bitstring converted to bytes */ function bitstringAt(bytes memory der, uint256 ptr) internal pure returns (bytes memory) { + ptr.overflowCheck(der.length); + + // Check type is bitstring. require(der[ptr.type_index()] == 0x03, "Not type BIT STRING"); // Only 00 padded bitstr can be converted to bytestr! require(der[ptr.content_index()] == 0x00); - uint256 valueLength = ptr.end_index() + 1 - ptr.content_index(); - + // Return the segment and avoid overflows. + uint256 valueLength = ptr.end_index() + 1 - ptr.content_index(); + require(valueLength > 0); + require(ptr.content_index() + 1 < der.length); + require(valueLength - 1 < der.length); return der.substring(ptr.content_index() + 1, valueLength - 1); } diff --git a/test/ASN1Decode.t.sol b/test/ASN1Decode.t.sol index d203fe8..8d925d3 100644 --- a/test/ASN1Decode.t.sol +++ b/test/ASN1Decode.t.sol @@ -33,21 +33,117 @@ contract TestASN1 is Test { bugCert.firstChildOf(rootPtr); test read uint, u16, readn overflow. + + todo test: isChildOf } */ - function testANS1BitStrAtOverflow() public { + function testANS1BytesAtOverflow() public { + vm.expectRevert(); + + + bytes memory buf = hex"020400112233"; + uint256 ptr = NodePtr.getPtr(0, 200, 200); + buf.bytesAt(ptr); + } + + function testANS1BytesAtSuccess() public { + bytes memory buf = hex"020400112233"; + uint256 ptr = NodePtr.getPtr(0, 2, 5); + buf.bytesAt(ptr); + } + + function testANS1AllBytesAtOverflow() public { + vm.expectRevert(); + + bytes memory buf = hex"020400112233"; + uint256 ptr = NodePtr.getPtr(0, 200, 200); + buf.allBytesAt(ptr); + } + + function testANS1AllBytesAtSuccess() public { + bytes memory buf = hex"020400112233"; + uint256 ptr = NodePtr.getPtr(0, 2, 5); + buf.allBytesAt(ptr); + } - return; + function testANS1Bytes32AtOverflow() public { + vm.expectRevert(); + + bytes memory buf = hex"020400112233"; + uint256 ptr = NodePtr.getPtr(0, 200, 200); + buf.bytes32At(ptr); + } + + function testANS1Bytes32AtSuccess() public { + bytes memory buf = hex"020400112233"; + uint256 ptr = NodePtr.getPtr(0, 2, 5); + buf.bytes32At(ptr); + } + + function testANS1UintAtOverflow() public { + vm.expectRevert(); + + bytes memory buf = hex"020400112233"; + uint256 ptr = NodePtr.getPtr(0, 200, 200); + buf.uintAt(ptr); + } + + function testANS1UintAtSuccess() public { + bytes memory buf = hex"020400112233"; + uint256 ptr = NodePtr.getPtr(0, 2, 5); + buf.uintAt(ptr); + } + + function testANS1UintBytesAtOverflow() public { + vm.expectRevert(); + + bytes memory buf = hex"020400112233"; + uint256 ptr = NodePtr.getPtr(0, 200, 200); + buf.uintBytesAt(ptr); + } + + function testANS1UintBytesAtSuccess() public { + bytes memory buf = hex"020400112233"; + uint256 ptr = NodePtr.getPtr(0, 2, 5); + buf.uintBytesAt(ptr); + } + + function testANS1KeccakBytesAtOverflow() public { + vm.expectRevert(); + + bytes memory buf = hex"030400112233"; + uint256 ptr = NodePtr.getPtr(0, 200, 200); + buf.keccakOfBytesAt(ptr); + } + + function testANS1KeccakBytesAtSuccess() public { + bytes memory buf = hex"030400112233"; + uint256 ptr = NodePtr.getPtr(0, 2, 5); + buf.keccakOfBytesAt(ptr); + } + + function testANS1KeccakAllAtOverflow() public { + vm.expectRevert(); + + bytes memory buf = hex"030400112233"; + uint256 ptr = NodePtr.getPtr(0, 200, 200); + buf.keccakOfAllBytesAt(ptr); + } + + function testANS1KeccakAllAtSuccess() public { + bytes memory buf = hex"030400112233"; + uint256 ptr = NodePtr.getPtr(0, 2, 5); + buf.keccakOfAllBytesAt(ptr); + } + + function testANS1BitStrAtOverflow() public { + vm.expectRevert(); // High order len bit is set // which triggers else in readNodeLen bytes memory buf = hex"030400112233"; - - // 000000000000000000000000000000020000000000000005 - uint256 ptr = 0; - ptr = NodePtr.getPtr(0, 200, 200); - console.log(ptr.content_index()); + uint256 ptr = NodePtr.getPtr(0, 200, 200); buf.bitstringAt(ptr); } @@ -55,11 +151,7 @@ contract TestASN1 is Test { // High order len bit is set // which triggers else in readNodeLen bytes memory buf = hex"030400112233"; - - // 000000000000000000000000000000020000000000000005 - uint256 ptr = 0; - ptr = NodePtr.getPtr(0, 2, 5); - + uint256 ptr = NodePtr.getPtr(0, 2, 5); buf.bitstringAt(ptr); } From 89e6ad6f34e521dd41e1e08fa12fe044096c09a1 Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Tue, 22 Aug 2023 04:07:26 +0000 Subject: [PATCH 07/35] Child functions left to test. --- src/ASN1Decode.sol | 7 ++++++- test/ASN1Decode.t.sol | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/ASN1Decode.sol b/src/ASN1Decode.sol index 92b575b..42de445 100755 --- a/src/ASN1Decode.sol +++ b/src/ASN1Decode.sol @@ -67,7 +67,12 @@ library Asn1Decode { function rootOfBitStringAt(bytes memory der, uint256 ptr) internal pure returns (uint256) { ptr.overflowCheck(der.length); require(der[ptr.type_index()] == 0x03, "Not type BIT STRING"); - return readNodeLength(der, ptr.content_index() + 1); + + // Not sure if the '+1' is right but overflow is checked for. + uint256 len = ptr.content_index() + 1; + require(len < der.length); + + return readNodeLength(der, len); } /* diff --git a/test/ASN1Decode.t.sol b/test/ASN1Decode.t.sol index 8d925d3..28854db 100644 --- a/test/ASN1Decode.t.sol +++ b/test/ASN1Decode.t.sol @@ -34,13 +34,41 @@ contract TestASN1 is Test { test read uint, u16, readn overflow. - todo test: isChildOf + todo test: isChildOf, nextSiblingOf, firstChildOf } */ - function testANS1BytesAtOverflow() public { + function testANS1RootOctetStringAtOverflow() public { + vm.expectRevert(); + + bytes memory buf = hex"040402990133"; + uint256 ptr = NodePtr.getPtr(0, 2, 5); + buf.rootOfOctetStringAt(ptr); + } + + function testANS1RootOctetStringAtSuccess() public { + bytes memory buf = hex"040402020133"; + uint256 ptr = NodePtr.getPtr(0, 2, 5); + buf.rootOfOctetStringAt(ptr); + } + + function testANS1RootOfBitStringAtOverflow() public { vm.expectRevert(); + // len -> 3 -> +1 = len -> 4 + bytes memory buf = hex"030400009933"; + uint256 ptr = NodePtr.getPtr(0, 2, 5); + buf.rootOfBitStringAt(ptr); + } + + function testANS1RootOfBitStringAtSuccess() public { + bytes memory buf = hex"030402020133"; + uint256 ptr = NodePtr.getPtr(0, 2, 5); + buf.rootOfBitStringAt(ptr); + } + + function testANS1BytesAtOverflow() public { + vm.expectRevert(); bytes memory buf = hex"020400112233"; uint256 ptr = NodePtr.getPtr(0, 200, 200); From d7a8e83e01e9101fe8c589b6be6041399581c1e0 Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Tue, 22 Aug 2023 04:19:37 +0000 Subject: [PATCH 08/35] ANS1 patches done. --- src/ASN1Decode.sol | 4 +++- test/ASN1Decode.t.sol | 30 ++++++++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/ASN1Decode.sol b/src/ASN1Decode.sol index 42de445..1bbfe34 100755 --- a/src/ASN1Decode.sol +++ b/src/ASN1Decode.sol @@ -94,7 +94,9 @@ library Asn1Decode { */ function nextSiblingOf(bytes memory der, uint256 ptr) internal pure returns (uint256) { ptr.overflowCheck(der.length); - return readNodeLength(der, ptr.end_index() + 1); + uint256 index = (ptr.end_index() + 1); + require(index < der.length); + return readNodeLength(der, index); } /* diff --git a/test/ASN1Decode.t.sol b/test/ASN1Decode.t.sol index 28854db..62a9dbd 100644 --- a/test/ASN1Decode.t.sol +++ b/test/ASN1Decode.t.sol @@ -33,11 +33,37 @@ contract TestASN1 is Test { bugCert.firstChildOf(rootPtr); test read uint, u16, readn overflow. - - todo test: isChildOf, nextSiblingOf, firstChildOf } */ + function testANS1NextSiblingOfOverflow() public { + vm.expectRevert(); + + bytes memory buf = hex"030400112233030400112233"; + uint256 ptr = NodePtr.getPtr(0, 2, 200); + buf.nextSiblingOf(ptr); + } + + function testANS1NextSiblingOfSuccess() public { + bytes memory buf = hex"030400112233030400112233"; + uint256 ptr = NodePtr.getPtr(0, 2, 5); + buf.nextSiblingOf(ptr); + } + + function testANS1FirstChildOfOverflow() public { + vm.expectRevert(); + + bytes memory buf = hex"00000000200402020133"; + uint256 ptr = NodePtr.getPtr(4, 200, 5); + buf.firstChildOf(ptr); + } + + function testANS1FirstChildOfSuccess() public { + bytes memory buf = hex"00000000200402020133"; + uint256 ptr = NodePtr.getPtr(4, 2, 5); + buf.firstChildOf(ptr); + } + function testANS1RootOctetStringAtOverflow() public { vm.expectRevert(); From a081d1a70cc811ae38314d5c0c252b9aaec12544 Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Tue, 22 Aug 2023 04:27:08 +0000 Subject: [PATCH 09/35] Apply some overflow checks to the pointer packer. --- src/ASN1Decode.sol | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/ASN1Decode.sol b/src/ASN1Decode.sol index 1bbfe34..56c195c 100755 --- a/src/ASN1Decode.sol +++ b/src/ASN1Decode.sol @@ -6,6 +6,8 @@ import { BytesUtils } from "ens-contracts/dnssec-oracle/BytesUtils.sol"; import { Math } from "openzeppelin-contracts/contracts/utils/math/Math.sol"; library NodePtr { + uint80 constant MAX_UNIT80 = 1208925819614629174706175; + // Unpack first byte index function type_index(uint256 self) internal pure returns (uint256) { return uint80(self); @@ -27,12 +29,20 @@ library NodePtr { // Pack 3 uint80s into a uint256 function getPtr(uint256 _type_index, uint256 _content_index, uint256 _end_index) internal pure returns (uint256) { + // This prevents overflowing the individual bit fields. + require(_type_index <= MAX_UNIT80); + require(_content_index <= MAX_UNIT80); + require(_end_index <= MAX_UNIT80); + + // Bit shift fields into correct segements. _type_index |= _content_index << 80; _type_index |= _end_index << 160; return _type_index; } function overflowCheck(uint256 self, uint len) internal pure { + // As len is limited to uint this also limits the max + // value of the offets to what can fit in a uint. require(type_index(self) < uint256(len)); require(content_index(self) < uint256(len)); require(end_index(self) < uint256(len)); From d4c4d7ed0a666432ddb2d504e8e888c614aad33b Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Tue, 22 Aug 2023 04:31:00 +0000 Subject: [PATCH 10/35] Apparently uint is just uint256. --- src/ASN1Decode.sol | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/ASN1Decode.sol b/src/ASN1Decode.sol index 56c195c..d84c73f 100755 --- a/src/ASN1Decode.sol +++ b/src/ASN1Decode.sol @@ -40,9 +40,7 @@ library NodePtr { return _type_index; } - function overflowCheck(uint256 self, uint len) internal pure { - // As len is limited to uint this also limits the max - // value of the offets to what can fit in a uint. + function overflowCheck(uint256 self, uint256 len) internal pure { require(type_index(self) < uint256(len)); require(content_index(self) < uint256(len)); require(end_index(self) < uint256(len)); From d3e1fe1e9316874cb55d146553f3f81c474683f8 Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Tue, 22 Aug 2023 05:02:54 +0000 Subject: [PATCH 11/35] Reject multitag identifiers. --- src/ASN1Decode.sol | 3 +++ test/ASN1Decode.t.sol | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/src/ASN1Decode.sol b/src/ASN1Decode.sol index d84c73f..11e7065 100755 --- a/src/ASN1Decode.sol +++ b/src/ASN1Decode.sol @@ -248,6 +248,9 @@ library Asn1Decode { // Avoid overflow for first len byte. require((ix + 1) < der.length); + // Reject multi-byte identifiers. + require((der[ix] & 0x1F) != 0x1F); + // Read length of a DER segment. uint256 length = 0; uint80 ixFirstContentByte = 0; diff --git a/test/ASN1Decode.t.sol b/test/ASN1Decode.t.sol index 62a9dbd..0098f8d 100644 --- a/test/ASN1Decode.t.sol +++ b/test/ASN1Decode.t.sol @@ -283,6 +283,14 @@ contract TestASN1 is Test { bytes memory d = hex"028300000101"; d.root(); } + + function testASN1RejectMultibyteTags() public { + vm.expectRevert(); + + bytes memory a = hex"1F020102"; + //uint256 ptr = NodePtr.getPtr(0, 2, 3); + a.root(); + } } /* From 4b4a99acedcf24e264dcc7458702fe2f0d1fd5ad Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Wed, 23 Aug 2023 02:35:07 +0000 Subject: [PATCH 12/35] Added new code to support zero length content. Need to expand tests to check that value retrieval matches expectations. --- src/ASN1Decode.sol | 165 ++++++++++++++++++++++++++++++++---------- test/ASN1Decode.t.sol | 10 +++ 2 files changed, 135 insertions(+), 40 deletions(-) diff --git a/src/ASN1Decode.sol b/src/ASN1Decode.sol index 11e7065..153533b 100755 --- a/src/ASN1Decode.sol +++ b/src/ASN1Decode.sol @@ -7,6 +7,7 @@ import { Math } from "openzeppelin-contracts/contracts/utils/math/Math.sol"; library NodePtr { uint80 constant MAX_UNIT80 = 1208925819614629174706175; + uint256 constant ZERO_LEN = 0; // Unpack first byte index function type_index(uint256 self) internal pure returns (uint256) { @@ -18,13 +19,20 @@ library NodePtr { return uint80(self >> 80); } - // Unpack last content byte index + // Points to the end of the DER segement. + // Not necessarily the end of the content segment as + // empty content segements are valid in DER. function end_index(uint256 self) internal pure returns (uint256) { return uint80(self >> 160); } function content_len(uint256 self) public pure returns (uint256) { - return (end_index(self) - content_index(self)) + 1; + if(content_index(self) == 0) { + return 0; + } + else { + return (end_index(self) - content_index(self)) + 1; + } } // Pack 3 uint80s into a uint256 @@ -116,7 +124,14 @@ library Asn1Decode { function firstChildOf(bytes memory der, uint256 ptr) internal pure returns (uint256) { ptr.overflowCheck(der.length); require(der[ptr.type_index()] & 0x20 == 0x20, "Not a constructed type"); - return readNodeLength(der, ptr.content_index()); + if(ptr.content_len() == 0) + { + revert(); + } + else + { + return readNodeLength(der, ptr.content_index()); + } } /* @@ -146,7 +161,10 @@ library Asn1Decode { */ function bytesAt(bytes memory der, uint256 ptr) internal pure returns (bytes memory) { ptr.overflowCheck(der.length); - return der.substring(ptr.content_index(), ptr.content_len()); + if(ptr.content_len() >= 1) { + return der.substring(ptr.content_index(), ptr.content_len()); + } + revert(); } /* @@ -157,7 +175,10 @@ library Asn1Decode { */ function allBytesAt(bytes memory der, uint256 ptr) internal pure returns (bytes memory) { ptr.overflowCheck(der.length); - return der.substring(ptr.type_index(), ptr.content_len()); + if(ptr.content_len() >= 1) { + return der.substring(ptr.type_index(), ptr.content_len()); + } + revert(); } /* @@ -169,7 +190,11 @@ library Asn1Decode { function bytes32At(bytes memory der, uint256 ptr) internal pure returns (bytes32) { ptr.overflowCheck(der.length); require(ptr.content_len() <= 32); - return der.readBytesN(ptr.content_index(), ptr.content_len()); + + if(ptr.content_len() >= 1) { + return der.readBytesN(ptr.content_index(), ptr.content_len()); + } + revert(); } /* @@ -179,16 +204,26 @@ library Asn1Decode { * @return Uint value of node */ function uintAt(bytes memory der, uint256 ptr) internal pure returns (uint256) { + // Sanity checks for pointer fields. ptr.overflowCheck(der.length); - require(der[ptr.type_index()] == 0x02, "Not type INTEGER"); - require(der[ptr.content_index()] & 0x80 == 0, "Not positive"); - uint256 len = ptr.content_len(); - require(len <= 32); - return uint256( - der.readBytesN(ptr.content_index(), len) >> - ((32 - len) * 8) - ); + // Check field types and value. + require(der[ptr.type_index()] == 0x02, "Not type INTEGER"); + if(ptr.content_len() >= 1) { + // Ensure unsigned int. + require(der[ptr.content_index()] & 0x80 == 0, "Not positive"); + + // Specify bytes to read. + uint256 len = ptr.content_len(); + require(len <= 32); + + // Read N bytes into uint field. + return uint256( + der.readBytesN(ptr.content_index(), len) >> + ((32 - len) * 8) + ); + } + revert(); } /* @@ -198,28 +233,45 @@ library Asn1Decode { * @return Value bytes of a positive integer node */ function uintBytesAt(bytes memory der, uint256 ptr) internal pure returns (bytes memory) { + // Sanity check on pointer. ptr.overflowCheck(der.length); - require(der[ptr.type_index()] == 0x02, "Not type INTEGER"); - require(der[ptr.content_index()] & 0x80 == 0, "Not positive"); - uint256 valueLength = ptr.content_len(); - return der.substring(ptr.content_index(), ptr.content_len()); + + // Only if content segment present. + if(ptr.content_len() >= 1) { + // Number must be a positive number. + require(der[ptr.type_index()] == 0x02, "Not type INTEGER"); + require(der[ptr.content_index()] & 0x80 == 0, "Not positive"); + + // Read bytes at offset. + return der.substring(ptr.content_index(), ptr.content_len()); + } + revert(); // This seems invalid. + /* + uint256 valueLength = ptr.content_len(); if (der[ptr.content_index()] == 0) { return der.substring(ptr.content_index() + 1, valueLength - 1); } else { return der.substring(ptr.content_index(), valueLength); } + */ } function keccakOfBytesAt(bytes memory der, uint256 ptr) internal pure returns (bytes32) { ptr.overflowCheck(der.length); - return der.keccak(ptr.content_index(), ptr.content_len()); + if(ptr.content_len() >= 1) { + return der.keccak(ptr.content_index(), ptr.content_len()); + } + revert(); } function keccakOfAllBytesAt(bytes memory der, uint256 ptr) internal pure returns (bytes32) { ptr.overflowCheck(der.length); - return der.keccak(ptr.type_index(), ptr.content_len()); + if(ptr.content_len() >= 1) { + return der.keccak(ptr.type_index(), ptr.content_len()); + } + revert(); } /* @@ -233,17 +285,47 @@ library Asn1Decode { // Check type is bitstring. require(der[ptr.type_index()] == 0x03, "Not type BIT STRING"); - // Only 00 padded bitstr can be converted to bytestr! - require(der[ptr.content_index()] == 0x00); - - // Return the segment and avoid overflows. - uint256 valueLength = ptr.end_index() + 1 - ptr.content_index(); - require(valueLength > 0); - require(ptr.content_index() + 1 < der.length); - require(valueLength - 1 < der.length); - return der.substring(ptr.content_index() + 1, valueLength - 1); + + // Only attempt to read if content set. + if(ptr.content_len() >= 1) { + // Only 00 padded bitstr can be converted to bytestr! + require(der[ptr.content_index()] == 0x00); + + // Return the segment and avoid overflows. + uint256 valueLength = ptr.end_index() + 1 - ptr.content_index(); + require(valueLength > 0); + require(ptr.content_index() + 1 < der.length); + require(valueLength - 1 < der.length); + return der.substring(ptr.content_index() + 1, valueLength - 1); + } + revert(); } + /* + A DER field looks like: + +type, (opt type) (len or len flag) (opt len ... N) (opt buf .. N) + +- Possibility for: one or two-byte type field. +- Possible: + - one byte len field. + - two byte len field. + - len info field followed by: + - variable length len field. +- Possible: + - variable length buffer + - or nothing + + This function returns a NodePtr indexing these fields. + If the buffer (or content) section is empty then + ptr.content_len() == 0 and ptr.content_index() == 0. + + The ptr.end_index() always points to the last byte of + the segment which may be a length field (if there's no + content portion) or the last content byte (if there's + a content / buffer portion set for it.) + + */ function readNodeLength(bytes memory der, uint256 ix) private pure returns (uint256) { // Avoid overflow for first len byte. require((ix + 1) < der.length); @@ -254,11 +336,14 @@ library Asn1Decode { // Read length of a DER segment. uint256 length = 0; uint80 ixFirstContentByte = 0; - uint80 ixLastContentByte = 0; + uint80 ixLastContentByte = uint80(ix + 1); if ((der[ix + 1] & 0x80) == 0) { - length = Math.max(uint8(der[ix + 1]), 1); - ixFirstContentByte = uint80(ix + 2); - ixLastContentByte = uint80(ixFirstContentByte + (length - 1)); + length = uint8(der[ix + 1]); + if(length >= 1) + { + ixFirstContentByte = uint80(ix + 2); + ixLastContentByte += uint80(length); + } } else { // How large is the length field? uint8 lengthbytesLength = uint8(der[ix + 1] & 0x7F); @@ -283,18 +368,18 @@ library Asn1Decode { } // Content length field must be positive. - require(length > 0); - ixFirstContentByte = uint80(ix + 2 + lengthbytesLength); - ixLastContentByte = uint80(ixFirstContentByte + (length - 1)); + ixLastContentByte += uint80(lengthbytesLength); + if(length >= 1) + { + ixFirstContentByte = uint80(ix + 2 + lengthbytesLength); + ixLastContentByte += uint80(length); + } } - // Sanity checks for ptrs. - require(ixFirstContentByte >= 2); - require(ixLastContentByte >= 2); - // The expected content segment must not overflow. require(ixFirstContentByte < der.length); require(ixLastContentByte < der.length); + require(ixLastContentByte > 0); // Return the nodeptr structure. return NodePtr.getPtr(ix, ixFirstContentByte, ixLastContentByte); diff --git a/test/ASN1Decode.t.sol b/test/ASN1Decode.t.sol index 0098f8d..2cd02a1 100644 --- a/test/ASN1Decode.t.sol +++ b/test/ASN1Decode.t.sol @@ -291,6 +291,16 @@ contract TestASN1 is Test { //uint256 ptr = NodePtr.getPtr(0, 2, 3); a.root(); } + + function testASN1ZeroLenContentFieldsSuccess() public { + // field 1: 0200 (len zero) + // field 2: 0202 0001 (len 02) + bytes memory buf = hex"200002020001"; + uint256 root = buf.root(); + uint256 ptr = buf.nextSiblingOf(root); + uint256 out = buf.uintAt(ptr); + console.log(out); + } } /* From 27d0e3cf8f3585ba17daff60434bb0d029aa5c1c Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Wed, 23 Aug 2023 02:47:34 +0000 Subject: [PATCH 13/35] Saving progress on value tests. --- src/ASN1Decode.sol | 2 +- test/ASN1Decode.t.sol | 20 ++++++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/ASN1Decode.sol b/src/ASN1Decode.sol index 153533b..4a2490e 100755 --- a/src/ASN1Decode.sol +++ b/src/ASN1Decode.sol @@ -372,7 +372,7 @@ type, (opt type) (len or len flag) (opt len ... N) (opt buf .. N) if(length >= 1) { ixFirstContentByte = uint80(ix + 2 + lengthbytesLength); - ixLastContentByte += uint80(length); + ixLastContentByte += uint80(length - 1); } } diff --git a/test/ASN1Decode.t.sol b/test/ASN1Decode.t.sol index 2cd02a1..0781163 100644 --- a/test/ASN1Decode.t.sol +++ b/test/ASN1Decode.t.sol @@ -268,20 +268,29 @@ contract TestASN1 is Test { function testASN1RootSuccessChances() public { // if, len = 1, buf 1 - bytes memory a = hex"02010101"; - a.root(); + uint256 out = 0; uint256 ptr = 0; + bytes memory a = hex"02010201"; + ptr = a.root(); + out = a.uintAt(ptr); + assert(out == 2); // if:if, len 1, buf 1 - bytes memory b = hex"02810101"; + bytes memory b = hex"02810201"; b.root(); + out = a.uintAt(ptr); + assert(out == 2); // if:elseif, len 1 (2 bytes), buf 1 - bytes memory c = hex"0282000101"; + bytes memory c = hex"0282000102"; c.root(); + out = a.uintAt(ptr); + assert(out == 2); // if:..else var len 1 (3 bytes), buf 1 - bytes memory d = hex"028300000101"; + bytes memory d = hex"028300000102"; d.root(); + out = a.uintAt(ptr); + assert(out == 2); } function testASN1RejectMultibyteTags() public { @@ -299,7 +308,6 @@ contract TestASN1 is Test { uint256 root = buf.root(); uint256 ptr = buf.nextSiblingOf(root); uint256 out = buf.uintAt(ptr); - console.log(out); } } From c0bacbc8f05a818df332017d4aa750d966748ddd Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Wed, 23 Aug 2023 03:03:07 +0000 Subject: [PATCH 14/35] Adding test value checks. --- src/ASN1Decode.sol | 2 +- test/ASN1Decode.t.sol | 25 +++++++++++++++++++------ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/ASN1Decode.sol b/src/ASN1Decode.sol index 4a2490e..341865f 100755 --- a/src/ASN1Decode.sol +++ b/src/ASN1Decode.sol @@ -269,7 +269,7 @@ library Asn1Decode { function keccakOfAllBytesAt(bytes memory der, uint256 ptr) internal pure returns (bytes32) { ptr.overflowCheck(der.length); if(ptr.content_len() >= 1) { - return der.keccak(ptr.type_index(), ptr.content_len()); + return der.keccak(ptr.type_index(), (ptr.end_index() - ptr.type_index()) + 1); } revert(); } diff --git a/test/ASN1Decode.t.sol b/test/ASN1Decode.t.sol index 0781163..612947a 100644 --- a/test/ASN1Decode.t.sol +++ b/test/ASN1Decode.t.sol @@ -132,7 +132,9 @@ contract TestASN1 is Test { function testANS1Bytes32AtSuccess() public { bytes memory buf = hex"020400112233"; uint256 ptr = NodePtr.getPtr(0, 2, 5); - buf.bytes32At(ptr); + bytes32 out = buf.bytes32At(ptr); + bytes32 expect = hex"00112233"; + assert(out == expect); } function testANS1UintAtOverflow() public { @@ -146,7 +148,9 @@ contract TestASN1 is Test { function testANS1UintAtSuccess() public { bytes memory buf = hex"020400112233"; uint256 ptr = NodePtr.getPtr(0, 2, 5); - buf.uintAt(ptr); + uint256 out = buf.uintAt(ptr); + uint256 expect = 1122867; + assert(out == expect); } function testANS1UintBytesAtOverflow() public { @@ -160,7 +164,9 @@ contract TestASN1 is Test { function testANS1UintBytesAtSuccess() public { bytes memory buf = hex"020400112233"; uint256 ptr = NodePtr.getPtr(0, 2, 5); - buf.uintBytesAt(ptr); + bytes memory out = buf.uintBytesAt(ptr); + bytes memory expect = hex"00112233"; + assert(keccak256(out) == keccak256(expect)); } function testANS1KeccakBytesAtOverflow() public { @@ -174,7 +180,9 @@ contract TestASN1 is Test { function testANS1KeccakBytesAtSuccess() public { bytes memory buf = hex"030400112233"; uint256 ptr = NodePtr.getPtr(0, 2, 5); - buf.keccakOfBytesAt(ptr); + bytes32 out = buf.keccakOfBytesAt(ptr); + bytes memory expect = hex"00112233"; + assert(out == keccak256(expect)); } function testANS1KeccakAllAtOverflow() public { @@ -188,7 +196,8 @@ contract TestASN1 is Test { function testANS1KeccakAllAtSuccess() public { bytes memory buf = hex"030400112233"; uint256 ptr = NodePtr.getPtr(0, 2, 5); - buf.keccakOfAllBytesAt(ptr); + bytes32 out = buf.keccakOfAllBytesAt(ptr); + assert(out == keccak256(buf)); } function testANS1BitStrAtOverflow() public { @@ -206,7 +215,11 @@ contract TestASN1 is Test { // which triggers else in readNodeLen bytes memory buf = hex"030400112233"; uint256 ptr = NodePtr.getPtr(0, 2, 5); - buf.bitstringAt(ptr); + + // It does the weird padded bitstrings. + bytes memory out = buf.bitstringAt(ptr); + bytes memory expect = hex"112233"; + assert(keccak256(out) == keccak256(expect)); } function testASN1RootOverflowIf() public { From a6655fc9ccac204350ada5b1437977c13296ff91 Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Wed, 23 Aug 2023 03:32:07 +0000 Subject: [PATCH 15/35] Working on value checks. --- src/ASN1Decode.sol | 8 +++++--- test/ASN1Decode.t.sol | 29 ++++++++++++++++++++--------- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/ASN1Decode.sol b/src/ASN1Decode.sol index 341865f..b374885 100755 --- a/src/ASN1Decode.sol +++ b/src/ASN1Decode.sol @@ -99,7 +99,7 @@ library Asn1Decode { function rootOfOctetStringAt(bytes memory der, uint256 ptr) internal pure returns (uint256) { ptr.overflowCheck(der.length); require(der[ptr.type_index()] == 0x04, "Not type OCTET STRING"); - return readNodeLength(der, ptr.content_index()); + return readNodeLength(der, ptr.content_index() + 1); } /* @@ -176,7 +176,8 @@ library Asn1Decode { function allBytesAt(bytes memory der, uint256 ptr) internal pure returns (bytes memory) { ptr.overflowCheck(der.length); if(ptr.content_len() >= 1) { - return der.substring(ptr.type_index(), ptr.content_len()); + uint256 len = (ptr.end_index() - ptr.type_index()) + 1; + return der.substring(ptr.type_index(), len); } revert(); } @@ -269,7 +270,8 @@ library Asn1Decode { function keccakOfAllBytesAt(bytes memory der, uint256 ptr) internal pure returns (bytes32) { ptr.overflowCheck(der.length); if(ptr.content_len() >= 1) { - return der.keccak(ptr.type_index(), (ptr.end_index() - ptr.type_index()) + 1); + uint256 len = (ptr.end_index() - ptr.type_index()) + 1; + return der.keccak(ptr.type_index(), len); } revert(); } diff --git a/test/ASN1Decode.t.sol b/test/ASN1Decode.t.sol index 612947a..d3db3c1 100644 --- a/test/ASN1Decode.t.sol +++ b/test/ASN1Decode.t.sol @@ -60,29 +60,35 @@ contract TestASN1 is Test { function testANS1FirstChildOfSuccess() public { bytes memory buf = hex"00000000200402020133"; - uint256 ptr = NodePtr.getPtr(4, 2, 5); - buf.firstChildOf(ptr); + uint256 ptr = NodePtr.getPtr(4, 6, 7); + ptr = buf.firstChildOf(ptr); + uint256 out = buf.uintAt(ptr); + uint256 expect = 307; + console.log(out); + assert(out == expect); } function testANS1RootOctetStringAtOverflow() public { vm.expectRevert(); - bytes memory buf = hex"040402990133"; - uint256 ptr = NodePtr.getPtr(0, 2, 5); + bytes memory buf = hex"040002990133"; + uint256 ptr = NodePtr.getPtr(0, 200, 5); buf.rootOfOctetStringAt(ptr); } function testANS1RootOctetStringAtSuccess() public { bytes memory buf = hex"040402020133"; uint256 ptr = NodePtr.getPtr(0, 2, 5); - buf.rootOfOctetStringAt(ptr); + ptr = buf.rootOfOctetStringAt(ptr); + uint256 out = buf.uintAt(ptr); + assert(out == 51); } function testANS1RootOfBitStringAtOverflow() public { vm.expectRevert(); // len -> 3 -> +1 = len -> 4 - bytes memory buf = hex"030400009933"; + bytes memory buf = hex"039900009933"; uint256 ptr = NodePtr.getPtr(0, 2, 5); buf.rootOfBitStringAt(ptr); } @@ -90,7 +96,9 @@ contract TestASN1 is Test { function testANS1RootOfBitStringAtSuccess() public { bytes memory buf = hex"030402020133"; uint256 ptr = NodePtr.getPtr(0, 2, 5); - buf.rootOfBitStringAt(ptr); + ptr = buf.rootOfBitStringAt(ptr); + uint256 out = buf.uintAt(ptr); + assert(out == 51); } function testANS1BytesAtOverflow() public { @@ -104,7 +112,9 @@ contract TestASN1 is Test { function testANS1BytesAtSuccess() public { bytes memory buf = hex"020400112233"; uint256 ptr = NodePtr.getPtr(0, 2, 5); - buf.bytesAt(ptr); + bytes memory out = buf.bytesAt(ptr); + bytes memory expect = hex"00112233"; + assert(keccak256(out) == keccak256(expect)); } function testANS1AllBytesAtOverflow() public { @@ -118,7 +128,8 @@ contract TestASN1 is Test { function testANS1AllBytesAtSuccess() public { bytes memory buf = hex"020400112233"; uint256 ptr = NodePtr.getPtr(0, 2, 5); - buf.allBytesAt(ptr); + bytes memory out = buf.allBytesAt(ptr); + assert(keccak256(out) == keccak256(buf)); } function testANS1Bytes32AtOverflow() public { From c6e7a3684d3c9a5399596a8b089d50045bf4638e Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Wed, 23 Aug 2023 03:35:39 +0000 Subject: [PATCH 16/35] Software should handle zero len content fields now. --- test/ASN1Decode.t.sol | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/test/ASN1Decode.t.sol b/test/ASN1Decode.t.sol index d3db3c1..57ecbab 100644 --- a/test/ASN1Decode.t.sol +++ b/test/ASN1Decode.t.sol @@ -45,9 +45,12 @@ contract TestASN1 is Test { } function testANS1NextSiblingOfSuccess() public { - bytes memory buf = hex"030400112233030400112233"; + bytes memory buf = hex"030400112233020400112233"; uint256 ptr = NodePtr.getPtr(0, 2, 5); - buf.nextSiblingOf(ptr); + ptr = buf.nextSiblingOf(ptr); + uint256 out = buf.uintAt(ptr); + uint256 expect = 1122867; + assert(out == expect); } function testANS1FirstChildOfOverflow() public { @@ -64,7 +67,6 @@ contract TestASN1 is Test { ptr = buf.firstChildOf(ptr); uint256 out = buf.uintAt(ptr); uint256 expect = 307; - console.log(out); assert(out == expect); } @@ -332,6 +334,7 @@ contract TestASN1 is Test { uint256 root = buf.root(); uint256 ptr = buf.nextSiblingOf(root); uint256 out = buf.uintAt(ptr); + assert(out == 1); } } From 9269bc1ad32a528371f2ce395eca0f76ef49e574 Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Wed, 23 Aug 2023 06:20:51 +0000 Subject: [PATCH 17/35] Get verify child cert working again. --- src/ASN1Decode.sol | 14 ++++--- test/ASN1Decode.t.sol | 58 ++++++++++++++++++++++++++- test/RAVE.t.sol | 2 + test/X509Verifier.t.sol | 5 ++- test/scripts/runReadCached.py | 2 +- test/scripts/runSignRandomEvidence.py | 6 +-- 6 files changed, 76 insertions(+), 11 deletions(-) diff --git a/src/ASN1Decode.sol b/src/ASN1Decode.sol index b374885..c9741b8 100755 --- a/src/ASN1Decode.sol +++ b/src/ASN1Decode.sol @@ -162,7 +162,10 @@ library Asn1Decode { function bytesAt(bytes memory der, uint256 ptr) internal pure returns (bytes memory) { ptr.overflowCheck(der.length); if(ptr.content_len() >= 1) { - return der.substring(ptr.content_index(), ptr.content_len()); + return der.substring( + ptr.content_index(), + ptr.content_len() + ); } revert(); } @@ -344,14 +347,15 @@ type, (opt type) (len or len flag) (opt len ... N) (opt buf .. N) if(length >= 1) { ixFirstContentByte = uint80(ix + 2); - ixLastContentByte += uint80(length); + ixLastContentByte = uint80(ixFirstContentByte + length - 1); } } else { // How large is the length field? uint8 lengthbytesLength = uint8(der[ix + 1] & 0x7F); + // Avoid overflow. - require((ix + 2) < der.length); + require((ix + 2 + lengthbytesLength) < der.length); if (lengthbytesLength == 1) { length = der.readUint8(ix + 2); } else if (lengthbytesLength == 2) { @@ -370,11 +374,11 @@ type, (opt type) (len or len flag) (opt len ... N) (opt buf .. N) } // Content length field must be positive. - ixLastContentByte += uint80(lengthbytesLength); + ixLastContentByte += uint80(lengthbytesLength) + 1; if(length >= 1) { ixFirstContentByte = uint80(ix + 2 + lengthbytesLength); - ixLastContentByte += uint80(length - 1); + ixLastContentByte = uint80(ixFirstContentByte + length - 1); } } diff --git a/test/ASN1Decode.t.sol b/test/ASN1Decode.t.sol index 57ecbab..8cc6c63 100644 --- a/test/ASN1Decode.t.sol +++ b/test/ASN1Decode.t.sol @@ -5,6 +5,7 @@ import { Test, console } from "forge-std/Test.sol"; import { BytesUtils } from "ens-contracts/dnssec-oracle/BytesUtils.sol"; import { Utils } from "rave/Utils.sol"; import { NodePtr, Asn1Decode } from "rave/ASN1Decode.sol"; +import { X509Verifier } from "rave/X509Verifier.sol"; contract TestASN1 is Test { @@ -12,11 +13,66 @@ contract TestASN1 is Test { using BytesUtils for bytes; using Utils for bytes; using NodePtr for uint256; + X509Verifier Certs = new X509Verifier(); + + + // Intel's root CA modulus + bytes intelRootModulus = + hex"9F3C647EB5773CBB512D2732C0D7415EBB55A0FA9EDE2E649199E6821DB910D53177370977466A6A5E4786CCD2DDEBD4149D6A2F6325529DD10CC98737B0779C1A07E29C47A1AE004948476C489F45A5A15D7AC8ECC6ACC645ADB43D87679DF59C093BC5A2E9696C5478541B979E754B573914BE55D32FF4C09DDF27219934CD990527B3F92ED78FBF29246ABECB71240EF39C2D7107B447545A7FFB10EB060A68A98580219E36910952683892D6A5E2A80803193E407531404E36B315623799AA825074409754A2DFE8F5AFD5FE631E1FC2AF3808906F28A790D9DD9FE060939B125790C5805D037DF56A99531B96DE69DE33ED226CC1207D1042B5C9AB7F404FC711C0FE4769FB9578B1DC0EC469EA1A25E0FF9914886EF2699B235BB4847DD6FF40B606E6170793C2FB98B314587F9CFD257362DFEAB10B3BD2D97673A1A4BD44C453AAF47FC1F2D3D0F384F74A06F89C089F0DA6CDB7FCEEE8C9821A8E54F25C0416D18C46839A5F8012FBDD3DC74D256279ADC2C0D55AFF6F0622425D1B"; + + bytes intelRootExponent = hex"010001"; bytes cert = hex"308204a130820309a003020102020900d107765d32a3b096300d06092a864886f70d01010b0500307e310b3009060355040613025553310b300906035504080c0243413114301206035504070c0b53616e746120436c617261311a3018060355040a0c11496e74656c20436f72706f726174696f6e3130302e06035504030c27496e74656c20534758204174746573746174696f6e205265706f7274205369676e696e67204341301e170d3136313132323039333635385a170d3236313132303039333635385a307b310b3009060355040613025553310b300906035504080c0243413114301206035504070c0b53616e746120436c617261311a3018060355040a0c11496e74656c20436f72706f726174696f6e312d302b06035504030c24496e74656c20534758204174746573746174696f6e205265706f7274205369676e696e6730820122300d06092a864886f70d01010105000382010f003082010a0282010100a97a2de0e66ea6147c9ee745ac0162686c7192099afc4b3f040fad6de093511d74e802f510d716038157dcaf84f4104bd3fed7e6b8f99c8817fd1ff5b9b864296c3d81fa8f1b729e02d21d72ffee4ced725efe74bea68fbc4d4244286fcdd4bf64406a439a15bcb4cf67754489c423972b4a80df5c2e7c5bc2dbaf2d42bb7b244f7c95bf92c75d3b33fc5410678a89589d1083da3acc459f2704cd99598c275e7c1878e00757e5bdb4e840226c11c0a17ff79c80b15c1ddb5af21cc2417061fbd2a2da819ed3b72b7efaa3bfebe2805c9b8ac19aa346512d484cfc81941e15f55881cc127e8f7aa12300cd5afb5742fa1d20cb467a5beb1c666cf76a368978b50203010001a381a43081a1301f0603551d2304183016801478437b76a67ebcd0af7e4237eb357c3b8701513c300e0603551d0f0101ff0404030206c0300c0603551d130101ff0402300030600603551d1f045930573055a053a051864f687474703a2f2f7472757374656473657276696365732e696e74656c2e636f6d2f636f6e74656e742f43524c2f5347582f4174746573746174696f6e5265706f72745369676e696e6743412e63726c300d06092a864886f70d01010b050003820181006708b61b5c2bd215473e2b46af99284fbb939d3f3b152c996f1a6af3b329bd220b1d3b610f6bce2e6753bded304db21912f385256216cfcba456bd96940be892f5690c260d1ef84f1606040222e5fe08e5326808212a447cfdd64a46e94bf29f6b4b9a721d25b3c4e2f62f58baed5d77c505248f0f801f9fbfb7fd752080095cee80938b339f6dbb4e165600e20e4a718812d49d9901e310a9b51d66c79909c6996599fae6d76a79ef145d9943bf1d3e35d3b42d1fb9a45cbe8ee334c166eee7d32fcdc9935db8ec8bb1d8eb3779dd8ab92b6e387f0147450f1e381d08581fb83df33b15e000a59be57ea94a3a52dc64bdaec959b3464c91e725bbdaea3d99e857e380a23c9d9fb1ef58e9e42d71f12130f9261d7234d6c37e2b03dba40dfdfb13ac4ad8e13fd3756356b6b50015a3ec9580b815d87c2cef715cd28df00bbf2a3c403ebf6691b3f05edd9143803ca085cff57e053eec2f8fea46ea778a68c9be885bc28225bc5f309be4a2b74d3a03945319dd3c7122fed6ff53bb8b8cb3a03c"; constructor() { } + function testASN1CertTraversial() public { + // Pointer to top level asn1 object: Sequence{tbsCertificate, signatureAlgorithm, signatureValue} + uint256 root = cert.root(); + console.log(root.type_index()); + console.log(root.content_index()); + console.log(root.end_index()); + console.log(root.content_len()); + + + // Traverse to first in sequence (the tbsCertificate) + uint256 tbsPtr = cert.firstChildOf(root); + console.log(tbsPtr.content_len()); + console.log(tbsPtr.type_index()); + console.log(tbsPtr.content_index()); + console.log(tbsPtr.end_index()); + console.log(tbsPtr.content_len()); + + + + // Extracts the TBSCerificate (what is used as input to RSA-SHA256) + bytes memory certBody = cert.allBytesAt(tbsPtr); + //console.log(tbsPtr.content_len()); + + + + // Top level traverse to signatureAlgorithm + uint256 sigAlgPtr = cert.nextSiblingOf(tbsPtr); + console.log(sigAlgPtr.type_index()); + console.log(sigAlgPtr.content_index()); + console.log(sigAlgPtr.end_index()); + console.log(sigAlgPtr.content_len()); + + + // Top level traverse to signatureValue + uint256 sigPtr = cert.nextSiblingOf(sigAlgPtr); + console.log(sigPtr.type_index()); + console.log(sigPtr.content_index()); + console.log(sigPtr.end_index()); + console.log(sigPtr.content_len()); + + // Extracts the signed certificate body + bytes memory signature = cert.bytesAt(sigPtr); + + require(Certs.verifyChildCert(certBody, signature, intelRootModulus, intelRootExponent), "verifyChildCert fail"); + + } + /* function testASN1RootOverflow() public { bytes memory bugCert = bytes(cert); @@ -301,7 +357,7 @@ contract TestASN1 is Test { assert(out == 2); // if:if, len 1, buf 1 - bytes memory b = hex"02810201"; + bytes memory b = hex"02810101"; b.root(); out = a.uintAt(ptr); assert(out == 2); diff --git a/test/RAVE.t.sol b/test/RAVE.t.sol index 00a600e..5865f89 100755 --- a/test/RAVE.t.sol +++ b/test/RAVE.t.sol @@ -9,6 +9,7 @@ import { MockEvidence, ValidBLSEvidence } from "test/mocks/MockEvidence.sol"; import { X509GenHelper, BytesFFIFuzzer } from "test/utils/helper.sol"; import { Test, console } from "forge-std/Test.sol"; +/* abstract contract RAVETester is Test { using BytesUtils for *; @@ -244,3 +245,4 @@ contract RaveFuzzTester is Test { } } } +*/ \ No newline at end of file diff --git a/test/X509Verifier.t.sol b/test/X509Verifier.t.sol index 0faa4d7..5d62dfc 100755 --- a/test/X509Verifier.t.sol +++ b/test/X509Verifier.t.sol @@ -187,7 +187,7 @@ abstract contract TestCertChainVerification is Test, X509GenHelper { } } - +/* contract Test512BitCertChain is TestCertChainVerification { constructor() X509GenHelper("512") { } } @@ -195,11 +195,13 @@ contract Test512BitCertChain is TestCertChainVerification { contract Test1024BitCertChain is TestCertChainVerification { constructor() X509GenHelper("1024") { } } +*/ contract Test2048BitCertChain is TestCertChainVerification { constructor() X509GenHelper("2048") { } } +/* contract Test3072BitCertChain is TestCertChainVerification { constructor() X509GenHelper("3072") { } } @@ -207,3 +209,4 @@ contract Test3072BitCertChain is TestCertChainVerification { contract Test4096BitCertChain is TestCertChainVerification { constructor() X509GenHelper("4096") { } } +*/ \ No newline at end of file diff --git a/test/scripts/runReadCached.py b/test/scripts/runReadCached.py index 33c7d50..3a9bbcd 100755 --- a/test/scripts/runReadCached.py +++ b/test/scripts/runReadCached.py @@ -19,7 +19,7 @@ def main(): for p in paths: with open(p) as f: - hex_data = f.read().strip('0x') + hex_data = f.read().removeprefix('0x') bytes_data = bytes.fromhex(hex_data) cached_data.append(bytes_data) diff --git a/test/scripts/runSignRandomEvidence.py b/test/scripts/runSignRandomEvidence.py index 2cc4062..3772efe 100755 --- a/test/scripts/runSignRandomEvidence.py +++ b/test/scripts/runSignRandomEvidence.py @@ -75,9 +75,9 @@ def sign(fname, message) -> bytes: def main(): # Prepare inputs - stripped_mre = sys.argv[1].lstrip('0x') - stripped_mrs = sys.argv[2].lstrip('0x') - stripped_payload = sys.argv[3].lstrip('0x') + stripped_mre = sys.argv[1].removeprefix('0x') + stripped_mrs = sys.argv[2].removeprefix('0x') + stripped_payload = sys.argv[3].removeprefix('0x') mrenclave = '0' * (64 - len(stripped_mre)) + stripped_mre mrsigner = '0' * (64 - len(stripped_mrs)) + stripped_mrs payload = '0' * (128 - len(stripped_payload)) + stripped_payload From 81b2fff29139e43aefd08dc9f098c05f2d667163 Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Wed, 23 Aug 2023 06:23:43 +0000 Subject: [PATCH 18/35] All tests seem to work again. --- src/ASN1Decode.sol | 3 +-- test/ASN1Decode.t.sol | 24 ------------------------ 2 files changed, 1 insertion(+), 26 deletions(-) diff --git a/src/ASN1Decode.sol b/src/ASN1Decode.sol index c9741b8..63191c9 100755 --- a/src/ASN1Decode.sol +++ b/src/ASN1Decode.sol @@ -353,7 +353,6 @@ type, (opt type) (len or len flag) (opt len ... N) (opt buf .. N) // How large is the length field? uint8 lengthbytesLength = uint8(der[ix + 1] & 0x7F); - // Avoid overflow. require((ix + 2 + lengthbytesLength) < der.length); if (lengthbytesLength == 1) { @@ -374,7 +373,7 @@ type, (opt type) (len or len flag) (opt len ... N) (opt buf .. N) } // Content length field must be positive. - ixLastContentByte += uint80(lengthbytesLength) + 1; + ixLastContentByte += uint80(lengthbytesLength); if(length >= 1) { ixFirstContentByte = uint80(ix + 2 + lengthbytesLength); diff --git a/test/ASN1Decode.t.sol b/test/ASN1Decode.t.sol index 8cc6c63..637d6a7 100644 --- a/test/ASN1Decode.t.sol +++ b/test/ASN1Decode.t.sol @@ -29,48 +29,24 @@ contract TestASN1 is Test { function testASN1CertTraversial() public { // Pointer to top level asn1 object: Sequence{tbsCertificate, signatureAlgorithm, signatureValue} uint256 root = cert.root(); - console.log(root.type_index()); - console.log(root.content_index()); - console.log(root.end_index()); - console.log(root.content_len()); - // Traverse to first in sequence (the tbsCertificate) uint256 tbsPtr = cert.firstChildOf(root); - console.log(tbsPtr.content_len()); - console.log(tbsPtr.type_index()); - console.log(tbsPtr.content_index()); - console.log(tbsPtr.end_index()); - console.log(tbsPtr.content_len()); - - // Extracts the TBSCerificate (what is used as input to RSA-SHA256) bytes memory certBody = cert.allBytesAt(tbsPtr); //console.log(tbsPtr.content_len()); - - // Top level traverse to signatureAlgorithm uint256 sigAlgPtr = cert.nextSiblingOf(tbsPtr); - console.log(sigAlgPtr.type_index()); - console.log(sigAlgPtr.content_index()); - console.log(sigAlgPtr.end_index()); - console.log(sigAlgPtr.content_len()); - // Top level traverse to signatureValue uint256 sigPtr = cert.nextSiblingOf(sigAlgPtr); - console.log(sigPtr.type_index()); - console.log(sigPtr.content_index()); - console.log(sigPtr.end_index()); - console.log(sigPtr.content_len()); // Extracts the signed certificate body bytes memory signature = cert.bytesAt(sigPtr); require(Certs.verifyChildCert(certBody, signature, intelRootModulus, intelRootExponent), "verifyChildCert fail"); - } /* From 4ef96a1a4e583ed4c29e07e9e0a0963524eeba12 Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Wed, 23 Aug 2023 06:28:29 +0000 Subject: [PATCH 19/35] Renable all tests --- src/ASN1Decode.sol | 4 ++-- test/RAVE.t.sol | 3 +-- test/X509Verifier.t.sol | 6 ++---- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/ASN1Decode.sol b/src/ASN1Decode.sol index 63191c9..1dfbf0a 100755 --- a/src/ASN1Decode.sol +++ b/src/ASN1Decode.sol @@ -347,7 +347,7 @@ type, (opt type) (len or len flag) (opt len ... N) (opt buf .. N) if(length >= 1) { ixFirstContentByte = uint80(ix + 2); - ixLastContentByte = uint80(ixFirstContentByte + length - 1); + ixLastContentByte += uint80(length); } } else { // How large is the length field? @@ -377,7 +377,7 @@ type, (opt type) (len or len flag) (opt len ... N) (opt buf .. N) if(length >= 1) { ixFirstContentByte = uint80(ix + 2 + lengthbytesLength); - ixLastContentByte = uint80(ixFirstContentByte + length - 1); + ixLastContentByte += uint80(length); } } diff --git a/test/RAVE.t.sol b/test/RAVE.t.sol index 5865f89..418d17d 100755 --- a/test/RAVE.t.sol +++ b/test/RAVE.t.sol @@ -9,7 +9,7 @@ import { MockEvidence, ValidBLSEvidence } from "test/mocks/MockEvidence.sol"; import { X509GenHelper, BytesFFIFuzzer } from "test/utils/helper.sol"; import { Test, console } from "forge-std/Test.sol"; -/* + abstract contract RAVETester is Test { using BytesUtils for *; @@ -245,4 +245,3 @@ contract RaveFuzzTester is Test { } } } -*/ \ No newline at end of file diff --git a/test/X509Verifier.t.sol b/test/X509Verifier.t.sol index 5d62dfc..408224d 100755 --- a/test/X509Verifier.t.sol +++ b/test/X509Verifier.t.sol @@ -187,7 +187,6 @@ abstract contract TestCertChainVerification is Test, X509GenHelper { } } -/* contract Test512BitCertChain is TestCertChainVerification { constructor() X509GenHelper("512") { } } @@ -195,13 +194,13 @@ contract Test512BitCertChain is TestCertChainVerification { contract Test1024BitCertChain is TestCertChainVerification { constructor() X509GenHelper("1024") { } } -*/ + contract Test2048BitCertChain is TestCertChainVerification { constructor() X509GenHelper("2048") { } } -/* + contract Test3072BitCertChain is TestCertChainVerification { constructor() X509GenHelper("3072") { } } @@ -209,4 +208,3 @@ contract Test3072BitCertChain is TestCertChainVerification { contract Test4096BitCertChain is TestCertChainVerification { constructor() X509GenHelper("4096") { } } -*/ \ No newline at end of file From 3adee57348b56e5e8da6fa7b9da84e035ba64dae Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Wed, 23 Aug 2023 07:35:14 +0000 Subject: [PATCH 20/35] Saving progress fixing tests. --- test/RAVE.t.sol | 19 +++++++++---------- test/scripts/runReadCached.py | 4 +++- test/scripts/runSignRandomEvidence.py | 17 ++++++++--------- test/scripts/utils.py | 3 ++- test/utils/helper.sol | 20 ++++++++++++++++++++ 5 files changed, 42 insertions(+), 21 deletions(-) diff --git a/test/RAVE.t.sol b/test/RAVE.t.sol index 418d17d..8cf36b3 100755 --- a/test/RAVE.t.sol +++ b/test/RAVE.t.sol @@ -6,7 +6,7 @@ import { RAVE } from "rave/RAVE.sol"; import { BytesUtils } from "ens-contracts/dnssec-oracle/BytesUtils.sol"; import { MockEvidence, ValidBLSEvidence } from "test/mocks/MockEvidence.sol"; -import { X509GenHelper, BytesFFIFuzzer } from "test/utils/helper.sol"; +import { X509GenHelper, BytesFFIFuzzer, BytesHelper } from "test/utils/helper.sol"; import { Test, console } from "forge-std/Test.sol"; @@ -102,7 +102,7 @@ contract RaveFuzzer is Test, X509GenHelper, BytesFFIFuzzer { c = new RAVE(); } - function genNewEvidence(string memory mrenclave, string memory mrsigner, string memory payload) + function genNewEvidence(bytes memory mrenclave, bytes memory mrsigner, bytes memory payload) public returns (bytes memory, bytes memory) { @@ -112,9 +112,9 @@ contract RaveFuzzer is Test, X509GenHelper, BytesFFIFuzzer { string[] memory cmds = new string[](6); cmds[0] = "python3"; cmds[1] = "test/scripts/runSignRandomEvidence.py"; - cmds[2] = mrenclave; - cmds[3] = mrsigner; - cmds[4] = payload; + cmds[2] = BytesHelper.toHexString(mrenclave); + cmds[3] = BytesHelper.toHexString(mrsigner); + cmds[4] = BytesHelper.toHexString(payload); cmds[5] = X509_PRIV_KEY_NAME; // Request .py sript to generate and sign mock RA evidence @@ -133,11 +133,11 @@ contract RaveFuzzer is Test, X509GenHelper, BytesFFIFuzzer { // Convert the random bytes into valid utf-8 bytes bytes memory payload = getFriendlyBytes(p).substring(0, 130); - console.log(string(payload)); + // Request new RA evidence (bytes memory signature, bytes memory reportValues) = - genNewEvidence(vm.toString(mrenclave), vm.toString(mrsigner), string(payload)); + genNewEvidence(mrenclave, mrsigner, payload); // Run rave to extract its payload bytes memory gotPayload = c.rave(reportValues, signature, CERT_BYTES, MODULUS, EXPONENT, mrenclave, mrsigner); @@ -176,13 +176,12 @@ contract CacheTheX509s is Test { // Test a single FuzzTest instance on one known input contract RaveInstanceTest is RaveFuzzer { // Manually adjust the parameters - string constant keyBits = "3072"; + string constant keyBits = "2048"; bool constant useCachedX509s = true; constructor() RaveFuzzer(keyBits, useCachedX509s) { } function test() public { - return; bytes memory mrenclave = hex"d0ae774774c2064a60dd92541fcc7cb8b3acdea0d793f3b27a27a44dbf71e75f"; bytes memory mrsigner = hex"83d719e77deaca1470f6baf62a4d774303c899db69020f9c70ee1dfc08c7ce9e"; bytes memory p = @@ -203,7 +202,7 @@ contract RaveSanityTester is Test { bytes memory p = hex"83d719e77deaca1470f6baf62a4d774303c899db69020f9c70ee1dfc08c7ce9e83d719e77deaca1470f6baf62a4d774303c899db69020f9c70ee1dfc08c7ce9e"; - string[1] memory rsaKeySize = ["4096"]; + string[1] memory rsaKeySize = ["2048"]; for (uint256 i = 0; i < rsaKeySize.length; i++) { string memory _rsaKeySize = rsaKeySize[i]; diff --git a/test/scripts/runReadCached.py b/test/scripts/runReadCached.py index 3a9bbcd..495a19d 100755 --- a/test/scripts/runReadCached.py +++ b/test/scripts/runReadCached.py @@ -4,6 +4,7 @@ import json import eth_abi +from utils import * def main(): @@ -19,7 +20,8 @@ def main(): for p in paths: with open(p) as f: - hex_data = f.read().removeprefix('0x') + hex_data = f.read() + hex_data = strip_0x(hex_data) bytes_data = bytes.fromhex(hex_data) cached_data.append(bytes_data) diff --git a/test/scripts/runSignRandomEvidence.py b/test/scripts/runSignRandomEvidence.py index 3772efe..58ccbc7 100755 --- a/test/scripts/runSignRandomEvidence.py +++ b/test/scripts/runSignRandomEvidence.py @@ -10,6 +10,8 @@ from cryptography.hazmat.backends import default_backend import eth_abi +from utils import * + MRENCLAVE_OFFSET = 112 MRSIGNER_OFFSET = 176 PAYLOAD_OFFSET = 368 @@ -75,15 +77,12 @@ def sign(fname, message) -> bytes: def main(): # Prepare inputs - stripped_mre = sys.argv[1].removeprefix('0x') - stripped_mrs = sys.argv[2].removeprefix('0x') - stripped_payload = sys.argv[3].removeprefix('0x') - mrenclave = '0' * (64 - len(stripped_mre)) + stripped_mre - mrsigner = '0' * (64 - len(stripped_mrs)) + stripped_mrs - payload = '0' * (128 - len(stripped_payload)) + stripped_payload - mrenclave = bytes.fromhex(mrenclave) - mrsigner = bytes.fromhex(mrsigner) - payload = bytes.fromhex(payload) + stripped_mre = strip_0x(sys.argv[1]) + stripped_mrs = strip_0x(sys.argv[2]) + stripped_payload = strip_0x(sys.argv[3]) + mrenclave = from_hex(stripped_mre) + mrsigner = from_hex(stripped_mrs) + payload = from_hex(stripped_payload) # mock json report evidence, dec_quote_body = mock_evidence(mrenclave, mrsigner, payload) diff --git a/test/scripts/utils.py b/test/scripts/utils.py index e480cd9..f90ab76 100755 --- a/test/scripts/utils.py +++ b/test/scripts/utils.py @@ -6,13 +6,14 @@ b64_encode = lambda x: to_s(base64.b64encode(to_b(x))) b64_decode = lambda x: to_s(base64.b64decode(to_b(x))) rm_0x = lambda x: [x.update({k: v[2:]}) for k,v in x.items() if x[k] and x[k][0:2] == "0x"] +strip_0x = lambda x: x if x[0:2] != "0x" else x[2:] def from_hex(x): # Make sure the hex string is even. if len(x) % 2: x = "0" + x - return to_s(binascii.unhexlify(to_b(x))) + return binascii.unhexlify(to_b(x)) def to_hex(x): return to_s(binascii.hexlify(to_b(x))) diff --git a/test/utils/helper.sol b/test/utils/helper.sol index 5c83bce..cd5019a 100755 --- a/test/utils/helper.sol +++ b/test/utils/helper.sol @@ -15,6 +15,26 @@ library BytesHelper { } return false; } + + ///@dev converts bytes array to its ASCII hex string representation + /// TODO: Definitely more efficient way to do this by processing multiple (16?) bytes at once + /// but really a helper function for the tests, efficiency not key. + function toHexString(bytes memory input) public pure returns (string memory) { + require(input.length < type(uint256).max / 2 - 1); + bytes16 symbols = "0123456789abcdef"; + bytes memory hex_buffer = new bytes(2 * input.length + 2); + hex_buffer[0] = "0"; + hex_buffer[1] = "x"; + + uint pos = 2; + uint256 length = input.length; + for (uint i = 0; i < length; ++i) { + uint _byte = uint8(input[i]); + hex_buffer[pos++] = symbols[_byte >> 4]; + hex_buffer[pos++] = symbols[_byte & 0xf]; + } + return string(hex_buffer); + } } contract BytesFFIFuzzer is Test { From 48d89459522670d1387aaf5253b7d9fc122406ca Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Thu, 24 Aug 2023 02:23:00 +0000 Subject: [PATCH 21/35] working on fixing broken tests. --- out.key | 28 ++++++++++ src/RAVE.sol | 3 ++ test/RAVE.t.sol | 77 +++++++++++++++------------ test/scripts/bin/error.log | 5 ++ test/scripts/bin/test_report | 1 + test/scripts/runSignRandomEvidence.py | 5 +- test/scripts/runX509Gen.sh | 5 +- 7 files changed, 86 insertions(+), 38 deletions(-) create mode 100644 out.key create mode 100644 test/scripts/bin/test_report diff --git a/out.key b/out.key new file mode 100644 index 0000000..163ee0c --- /dev/null +++ b/out.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDPimz4/B0p2TVY +Sxl7mc8Ju6M62gXfldZGr8PFcURI3ajcbYxBGwbzNHNP/sP/CwGZ4zkCZwiMPjDD +rKNpoSidnQkzmnHev5xuDSjz9Mk0/6tF4iMvd6Tc6yz1dOAElx+yGMlFcaNEPFqg +D2kEM/5FJwoxRxBkQiHpTsPfbMr7BQJTrGLz2c1JnLZl1uWqQuCL4+WP0QRNu06P +ljq7RVbj8ecOwZkQ7O68shxQvMtTlgBi80OSTg+o9Q8807kSATFUyvLh+a7dUERC +Si+qAslaSMqTudmXxj251KpFHq+lscBzVkxALhPeugWbYxG2Mxh1PN9GVugnW0pi +lJbcbFApAgMBAAECggEBAIHDyokPkeiFoD4ZjtBihjpOsSvuADghRr4hzeWZAZoR +xjA06roWfQz54ZPF9qR0LEcc9JtU8tpFVFY0jmRQWMXb11IFomclJVkGL3IBvwC9 +T0i9sURPqaxb+1tp/VvBZhcEOmyKNgxHNF7Z486196kjVNMk3NHjK7LmBcCgFHZI +Nia90NcSukpaLkOJnYt43sZ2Rjtfd8kuTzYjTyjchhnjz86qbOrm5IY/d2yJxS+M +znb71R/1XWGXLMiNUZF0dsrMFuCCCYnlUSxc+50W1N0M6Ioeaqe1MFLU9UATky3/ +cOy8FtEZvDoflAesM8qV+T0nxcgM3f1UHk4HYk41oIECgYEA7OkYs9dyaJ5IBzKG +PuCeN/qfvYi0HTIZYH3TWZHb+3BjDKblJr7HrSsbJBdyUGjlMyO2xN//gCqoN43Z +7ONxIfh9GIRSdt5V9ZoenrOiNvhAoy3vitdM5/ouwBJxICMlpS4s7gM3aq+7Shoj +CUc/RQBAFr0FPkfgVdqpQKygTnECgYEA4EN/43vRJaay0pzNovnod132U/ybTJ/O +7w9XGolxQqvtzZoOvaTRk2CsLn63l8Ppu/loPRM2rkl/9nQkr27Hld2YTi0xTgy9 +4CrSPBdHkFDXJULGGSkrQss6okPdnTHG5SXUrMEeIt1+GobArTj7iVF1VwdDPoqS +ND9QWVG26TkCgYEA2yHkeny+02wMfbPLHp/PWUIVvU+UIikz9d+MvZ2/13wl8g7x +iHwQ3+kuSpzxXNUZo8rWBJaYkylhvTkVKRtbiqt4slO6nz6aTfmHdw367lOEHiug +FVF+TlhII9srDinUaUwjvOf2u1TerPUuESf4qs9HeIDQN8JuC5uc0DicctECgYBI +CCY5sPlaeJKTZ139bPun63xFOavADsxuqKS3l1HTslltYoA9lYTjK3fibz0U+A5J +HDDI/TThAiahyGhIGPLuRgC3i3h8s0cBi39/YZLQ3cZc53eteTW1/ITWvame5fAW +hfIrktPVKwNoDcQxX04bqxhfXavRmLyhH3z1U3PGsQKBgFH2EEJ175cNHR4Fm21R +K6YTJQsIysBBuhnyUv8IJMqqjsJwY42IzD4Gp/MM+jUd+eUzFcQHYMoMJFIycqCK +2KDWJ2jIqdFjXDjZoG/aL5zls0uomCefuOHMklFN45iFSkWgOOCdNXAccCl0VlxU +18ij8ZttH5sZxogzQl1JXjyX +-----END PRIVATE KEY----- diff --git a/src/RAVE.sol b/src/RAVE.sol index 256a310..6e102c4 100755 --- a/src/RAVE.sol +++ b/src/RAVE.sol @@ -37,6 +37,7 @@ contract RAVE is Test, RAVEBase, JSONBuilder, X509Verifier { // Verify the report was signed by the SigningPK if (!verifyRSA(reportBytes, sig, signingMod, signingExp)) { + console.logBytes(sig); revert BadReportSignature(); } @@ -78,6 +79,8 @@ contract RAVE is Test, RAVEBase, JSONBuilder, X509Verifier { console.logBytes(truncMod); console.log(truncMod.length); + console.log("leaf cert modulus"); + console.log(leafCertModulus.length); payload = verifyRemoteAttestation(report, sig, truncMod, leafCertExponent, mrenclave, mrsigner); return payload; } diff --git a/test/RAVE.t.sol b/test/RAVE.t.sol index 8cf36b3..7c7d593 100755 --- a/test/RAVE.t.sol +++ b/test/RAVE.t.sol @@ -43,6 +43,8 @@ abstract contract RAVETester is Test { assert(keccak256(gotPayload.substring(0, expPayload.length)) == keccak256(expPayload)); } + + function test_VerifyRave() public view { bytes memory report = m.report(); bytes memory sig = m.sig(); @@ -79,6 +81,7 @@ abstract contract RAVETester is Test { } } + contract TestHappyRAVE is RAVETester { function setUp() public override { m = new ValidBLSEvidence(); @@ -86,6 +89,33 @@ contract TestHappyRAVE is RAVETester { } } +// Fuzz test every FuzzTest parameterization +contract RaveFuzzTester is Test { + RaveFuzzer[] c; + // Warning, if true this will fail if all x509s do not already exist + bool useCachedX509s = true; + string[1] rsaKeySize = ["4096"]; + uint256 numFuzzers = rsaKeySize.length; + + // Create all possible RAVEFuzzer (expensive so run only once) + constructor() { + for (uint256 i = 0; i < rsaKeySize.length; i++) { + string memory _rsaKeySize = rsaKeySize[i]; + + // Setup fuzzer by running openSSL via FFI or read from cache + c.push(new RaveFuzzer(_rsaKeySize, useCachedX509s)); + } + } + + // Run a fuzz test sequentially on each RAVe parameterization + function testRaveFuzz(bytes memory mrenclave, bytes memory mrsigner, bytes memory p) public { + vm.assume(p.length >= 64); + for (uint256 i = 0; i < numFuzzers; i++) { + c[i].runRAVE(mrenclave, mrsigner, p); + } + } +} + contract RaveFuzzer is Test, X509GenHelper, BytesFFIFuzzer { using BytesUtils for *; @@ -106,9 +136,9 @@ contract RaveFuzzer is Test, X509GenHelper, BytesFFIFuzzer { public returns (bytes memory, bytes memory) { - assertEq(bytes(mrenclave).length, 66, "bad mre len"); - assertEq(bytes(mrsigner).length, 66, "bad mrs len"); - assertEq(bytes(payload).length, 130, "bad payload len"); + assertEq(bytes(mrenclave).length, 32, "bad mre len"); + assertEq(bytes(mrsigner).length, 32, "bad mrs len"); + assertEq(bytes(payload).length, 64, "bad payload len"); string[] memory cmds = new string[](6); cmds[0] = "python3"; cmds[1] = "test/scripts/runSignRandomEvidence.py"; @@ -129,15 +159,12 @@ contract RaveFuzzer is Test, X509GenHelper, BytesFFIFuzzer { } function runRAVE(bytes memory mrenclave, bytes memory mrsigner, bytes memory p) public { - vm.assume(p.length >= 64); - - // Convert the random bytes into valid utf-8 bytes - bytes memory payload = getFriendlyBytes(p).substring(0, 130); + vm.assume(p.length <= 64); // Request new RA evidence (bytes memory signature, bytes memory reportValues) = - genNewEvidence(mrenclave, mrsigner, payload); + genNewEvidence(mrenclave, mrsigner, p); // Run rave to extract its payload bytes memory gotPayload = c.rave(reportValues, signature, CERT_BYTES, MODULUS, EXPONENT, mrenclave, mrsigner); @@ -152,6 +179,7 @@ contract RaveFuzzer is Test, X509GenHelper, BytesFFIFuzzer { } } + // Generate all the x509 certificates used in testing contract CacheTheX509s is Test { bool useCachedX509s = false; @@ -167,17 +195,18 @@ contract CacheTheX509s is Test { // Setup fuzzer by running openSSL via FFI or read from cache new RaveFuzzer(_rsaKeySize, useCachedX509s); - // Stall to prevent race conditions when testing against openSSL via FFI - for (uint256 s = 0; s < 30 ** 6; s++) { } + } } } + + // Test a single FuzzTest instance on one known input contract RaveInstanceTest is RaveFuzzer { // Manually adjust the parameters string constant keyBits = "2048"; - bool constant useCachedX509s = true; + bool constant useCachedX509s = false; constructor() RaveFuzzer(keyBits, useCachedX509s) { } @@ -192,6 +221,7 @@ contract RaveInstanceTest is RaveFuzzer { } } +/* // Test every FuzzTest parameterization on the same known input contract RaveSanityTester is Test { bool useCachedX509s = true; @@ -218,29 +248,6 @@ contract RaveSanityTester is Test { } } -// Fuzz test every FuzzTest parameterization -contract RaveFuzzTester is Test { - RaveFuzzer[] c; - // Warning, if true this will fail if all x509s do not already exist - bool useCachedX509s = true; - string[1] rsaKeySize = ["4096"]; - uint256 numFuzzers = rsaKeySize.length; - // Create all possible RAVEFuzzer (expensive so run only once) - constructor() { - for (uint256 i = 0; i < rsaKeySize.length; i++) { - string memory _rsaKeySize = rsaKeySize[i]; - // Setup fuzzer by running openSSL via FFI or read from cache - c.push(new RaveFuzzer(_rsaKeySize, useCachedX509s)); - } - } - - // Run a fuzz test sequentially on each RAVe parameterization - function testRaveFuzz(bytes memory mrenclave, bytes memory mrsigner, bytes memory p) public { - vm.assume(p.length >= 64); - for (uint256 i = 0; i < numFuzzers; i++) { - c[i].runRAVE(mrenclave, mrsigner, p); - } - } -} +*/ \ No newline at end of file diff --git a/test/scripts/bin/error.log b/test/scripts/bin/error.log index 4b8e990..00cfc62 100755 --- a/test/scripts/bin/error.log +++ b/test/scripts/bin/error.log @@ -33,3 +33,8 @@ odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530 odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d odd len hex 7b226964223a22313030393338333438383438393337323833313538373130383530363736383834393935323531222c2274696d657374616d70223a22323032332d30372d32385430313a31343a35352e393832353036222c2276657273696f6e223a342c226570696450736575646f6e796d223a224562724d3658365943483362726a50585432336756682f49324547357356664859682b533534666230727241715652546952544f53664c73575356545a63387772617a4747376f6f6f476f4d5537476a35544568736733764a2f6a5974784537514b6f4a79704571307766395556644256384f627a776264794a6e72536c61757042446f5854744d485a3232506e2f456b3249567071314c6e725633667a6a526a66382b444b336c7137303d222c2261647669736f727955524c223a2268747470733a2f2f73656375726974792d63656e7465722e696e74656c2e636f6d222c2261647669736f7279494473223a5b22494e54454c2d53412d3030333334222c22494e54454c2d53412d3030363135225d2c22697376456e636c61766551756f7465537461747573223a2253575f48415244454e494e475f4e4545444544222c22697376456e636c61766551756f7465426f6479223a2241674142414b774d4141414e414130414141414141454a68624a6a56504a6353593552487962446e4144384141414141414141414141414141414141414141414652554c422f2b41446741414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack414141414141414141414141414251414141414141414141664141414141414141414874754172786e3666703532656c6d74756756714176783879514469537362367970466f4a4c6f5038486c41414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack41414141414141434431786e6e6665724b4648443275765971545864444138695a32326b434435787737683338434d664f6e674141414141414141414141414141414141414141414141414141414141certsder_to_pemechoerror.logfields_to_abiforge_deployfrom_hexget_cert_keybitsget_forge_deploy_addrget_report_certis_cert_crlis_cert_deris_cert_pemis_mock_mrenclaveis_mock_mrsigneris_mock_payloadis_mock_reportis_mock_signer_certis_mock_signer_expis_mock_signer_modis_mock_signer_sigis_valid_certis_valid_hex_lenis_valid_reportis_valid_signer_certis_valid_signer_expis_valid_signer_modis_valid_signer_siglibpackpem_to_derprepend_func_sigre_findreport_to_calldatarsa_digestss_to_abitest_cert.pemtest_packtest_valid_signer_sigto_hextrim_whitespaceunpack4141414141414143504148677a6958413937433778784b4a384f6d2b482f644d53326d44764a6270583762737137424f386c56664a3359722f4e5469516b4b6e6844314745597a38414141414141414141414141414141414141414141227d +whitespace found in report = '{"id":"142090828149453720542199954221331392599","timestamp":"2023-02-15T01:24:57.989456","version":4,"epidPseudonym":"EbrM6X6YCH3brjPXT23gVh/I2EG5sVfHYh+S54fb0rrAqVRTiRTOSfLsWSVTZc8wrazGG7oooGoMU7Gj5TEhsvsDIV4aYpvkSk/E3Tsb7CaGd+Iy1cEhLO4GPwdmwt/PXNQQ3htLdy3aNb7iQMrNbiFcdkVdV/tepdezMsSB8Go=","isvEnclaveQuoteStatus":"OK","isvEnclaveQuoteBody":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCud0d0wgZKYN2SVB/MfLizrN6g15PzsnonpE2/cedfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACD1xnnferKFHD2uvYqTXdDA8iZ22kCD5xw7h38CMfOngAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACD1xnnferKFHD2uvYqTXdDA8iZ22kCD5xw7h38CMfOnoPXGed96soUcPa69ipNd0MDyJnbaQIPnHDuHfwIx86e"} +'whitespace found in report = '{"id":"142090828149453720542199954221331392599","timestamp":"2023-02-15T01:24:57.989456","version":4,"epidPseudonym":"EbrM6X6YCH3brjPXT23gVh/I2EG5sVfHYh+S54fb0rrAqVRTiRTOSfLsWSVTZc8wrazGG7oooGoMU7Gj5TEhsvsDIV4aYpvkSk/E3Tsb7CaGd+Iy1cEhLO4GPwdmwt/PXNQQ3htLdy3aNb7iQMrNbiFcdkVdV/tepdezMsSB8Go=","isvEnclaveQuoteStatus":"OK","isvEnclaveQuoteBody":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCud0d0wgZKYN2SVB/MfLizrN6g15PzsnonpE2/cedfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACD1xnnferKFHD2uvYqTXdDA8iZ22kCD5xw7h38CMfOngAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACD1xnnferKFHD2uvYqTXdDA8iZ22kCD5xw7h38CMfOnoPXGed96soUcPa69ipNd0MDyJnbaQIPnHDuHfwIx86e"} +'whitespace found in report = '{"id":"142090828149453720542199954221331392599","timestamp":"2023-02-15T01:24:57.989456","version":4,"epidPseudonym":"EbrM6X6YCH3brjPXT23gVh/I2EG5sVfHYh+S54fb0rrAqVRTiRTOSfLsWSVTZc8wrazGG7oooGoMU7Gj5TEhsvsDIV4aYpvkSk/E3Tsb7CaGd+Iy1cEhLO4GPwdmwt/PXNQQ3htLdy3aNb7iQMrNbiFcdkVdV/tepdezMsSB8Go=","isvEnclaveQuoteStatus":"OK","isvEnclaveQuoteBody":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCud0d0wgZKYN2SVB/MfLizrN6g15PzsnonpE2/cedfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACD1xnnferKFHD2uvYqTXdDA8iZ22kCD5xw7h38CMfOngAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACD1xnnferKFHD2uvYqTXdDA8iZ22kCD5xw7h38CMfOnoPXGed96soUcPa69ipNd0MDyJnbaQIPnHDuHfwIx86e"} +'whitespace found in report = '{"id":"142090828149453720542199954221331392599","timestamp":"2023-02-15T01:24:57.989456","version":4,"epidPseudonym":"EbrM6X6YCH3brjPXT23gVh/I2EG5sVfHYh+S54fb0rrAqVRTiRTOSfLsWSVTZc8wrazGG7oooGoMU7Gj5TEhsvsDIV4aYpvkSk/E3Tsb7CaGd+Iy1cEhLO4GPwdmwt/PXNQQ3htLdy3aNb7iQMrNbiFcdkVdV/tepdezMsSB8Go=","isvEnclaveQuoteStatus":"OK","isvEnclaveQuoteBody":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCud0d0wgZKYN2SVB/MfLizrN6g15PzsnonpE2/cedfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACD1xnnferKFHD2uvYqTXdDA8iZ22kCD5xw7h38CMfOngAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACD1xnnferKFHD2uvYqTXdDA8iZ22kCD5xw7h38CMfOnoPXGed96soUcPa69ipNd0MDyJnbaQIPnHDuHfwIx86e"} +' \ No newline at end of file diff --git a/test/scripts/bin/test_report b/test/scripts/bin/test_report new file mode 100644 index 0000000..b475c07 --- /dev/null +++ b/test/scripts/bin/test_report @@ -0,0 +1 @@ +{"id":"142090828149453720542199954221331392599","timestamp":"2023-02-15T01:24:57.989456","version":4,"epidPseudonym":"EbrM6X6YCH3brjPXT23gVh/I2EG5sVfHYh+S54fb0rrAqVRTiRTOSfLsWSVTZc8wrazGG7oooGoMU7Gj5TEhsvsDIV4aYpvkSk/E3Tsb7CaGd+Iy1cEhLO4GPwdmwt/PXNQQ3htLdy3aNb7iQMrNbiFcdkVdV/tepdezMsSB8Go=","isvEnclaveQuoteStatus":"OK","isvEnclaveQuoteBody":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANCud0d0wgZKYN2SVB/MfLizrN6g15PzsnonpE2/cedfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACD1xnnferKFHD2uvYqTXdDA8iZ22kCD5xw7h38CMfOngAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACD1xnnferKFHD2uvYqTXdDA8iZ22kCD5xw7h38CMfOnoPXGed96soUcPa69ipNd0MDyJnbaQIPnHDuHfwIx86e"} \ No newline at end of file diff --git a/test/scripts/runSignRandomEvidence.py b/test/scripts/runSignRandomEvidence.py index 58ccbc7..136c62e 100755 --- a/test/scripts/runSignRandomEvidence.py +++ b/test/scripts/runSignRandomEvidence.py @@ -24,7 +24,8 @@ def build_quote_body(mre, mrs, payload) -> bytes: body_bytes = bytes(MRENCLAVE_OFFSET) + mre body_bytes += bytes(MRSIGNER_OFFSET - len(body_bytes)) + mrs body_bytes += bytes(PAYLOAD_OFFSET - len(body_bytes)) + payload - body_bytes += bytes(64 - len(payload)) # pad extra bytes with 0s + if len(payload) < 64: + body_bytes += bytes(64 - len(payload)) # pad extra bytes with 0s assert len(body_bytes) == QUOTE_BODY_LENGTH return body_bytes @@ -42,7 +43,7 @@ def mock_evidence(mrenclave, mrsigner, payload): ('epidPseudonym', "EbrM6X6YCH3brjPXT23gVh/I2EG5sVfHYh+S54fb0rrAqVRTiRTOSfLsWSVTZc8wrazGG7oooGoMU7Gj5TEhsvsDIV4aYpvkSk/E3Tsb7CaGd+Iy1cEhLO4GPwdmwt/PXNQQ3htLdy3aNb7iQMrNbiFcdkVdV/tepdezMsSB8Go="), ("advisoryURL", "https://security-center.intel.com"), ("advisoryIDs", ["INTEL-SA-00334","INTEL-SA-00615"]), - ("isvEnclaveQuoteStatus", "OK"), + ("isvEnclaveQuoteStatus", "SW_HARDENING_NEEDED"), ("isvEnclaveQuoteBody", f"{enc_quote_body}"), ]) diff --git a/test/scripts/runX509Gen.sh b/test/scripts/runX509Gen.sh index 0998d35..b6fdcf9 100755 --- a/test/scripts/runX509Gen.sh +++ b/test/scripts/runX509Gen.sh @@ -4,5 +4,8 @@ BITS=$1 CERT_NAME=$2 KEY_NAME=$3 +rm $CERT_NAME +rm $KEY_NAME + # Create a private key named $KEY_NAME and then self-sign an x509 certificate -echo -e "US\nCA\nSan Francisco\nMy Organization\nMy PARENT Name\n\n\n" | openssl req -x509 -newkey rsa:$BITS -keyout $KEY_NAME -out $CERT_NAME -sha256 -days 365 -nodes \ No newline at end of file +echo -e "US\nCA\nSan Francisco\nMy Organization\nMy PARENT Name\n\n\n" | openssl req -x509 -newkey rsa:$BITS -keyout $KEY_NAME -out $CERT_NAME -sha256 -days 365 -nodes 2>&1 >/dev/null \ No newline at end of file From 9ac5a1a97d68033ddd7f0219eb412b721c9b0740 Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Thu, 24 Aug 2023 03:32:25 +0000 Subject: [PATCH 22/35] Saving progress on fixing tests. --- test/RAVE.t.sol | 14 ++++++-------- test/utils/helper.sol | 31 ++++++++++++++----------------- 2 files changed, 20 insertions(+), 25 deletions(-) diff --git a/test/RAVE.t.sol b/test/RAVE.t.sol index 7c7d593..182d891 100755 --- a/test/RAVE.t.sol +++ b/test/RAVE.t.sol @@ -43,8 +43,6 @@ abstract contract RAVETester is Test { assert(keccak256(gotPayload.substring(0, expPayload.length)) == keccak256(expPayload)); } - - function test_VerifyRave() public view { bytes memory report = m.report(); bytes memory sig = m.sig(); @@ -94,12 +92,12 @@ contract RaveFuzzTester is Test { RaveFuzzer[] c; // Warning, if true this will fail if all x509s do not already exist bool useCachedX509s = true; - string[1] rsaKeySize = ["4096"]; - uint256 numFuzzers = rsaKeySize.length; + string[1] rsaKeySize = ["2048"]; + uint256 numFuzzers = 1; // Create all possible RAVEFuzzer (expensive so run only once) constructor() { - for (uint256 i = 0; i < rsaKeySize.length; i++) { + for (uint256 i = 0; i < numFuzzers; i++) { string memory _rsaKeySize = rsaKeySize[i]; // Setup fuzzer by running openSSL via FFI or read from cache @@ -142,9 +140,9 @@ contract RaveFuzzer is Test, X509GenHelper, BytesFFIFuzzer { string[] memory cmds = new string[](6); cmds[0] = "python3"; cmds[1] = "test/scripts/runSignRandomEvidence.py"; - cmds[2] = BytesHelper.toHexString(mrenclave); - cmds[3] = BytesHelper.toHexString(mrsigner); - cmds[4] = BytesHelper.toHexString(payload); + cmds[2] = BytesHelper.to_hex(mrenclave); + cmds[3] = BytesHelper.to_hex(mrsigner); + cmds[4] = BytesHelper.to_hex(payload); cmds[5] = X509_PRIV_KEY_NAME; // Request .py sript to generate and sign mock RA evidence diff --git a/test/utils/helper.sol b/test/utils/helper.sol index cd5019a..2358176 100755 --- a/test/utils/helper.sol +++ b/test/utils/helper.sol @@ -16,24 +16,21 @@ library BytesHelper { return false; } - ///@dev converts bytes array to its ASCII hex string representation - /// TODO: Definitely more efficient way to do this by processing multiple (16?) bytes at once - /// but really a helper function for the tests, efficiency not key. - function toHexString(bytes memory input) public pure returns (string memory) { - require(input.length < type(uint256).max / 2 - 1); - bytes16 symbols = "0123456789abcdef"; - bytes memory hex_buffer = new bytes(2 * input.length + 2); - hex_buffer[0] = "0"; - hex_buffer[1] = "x"; - - uint pos = 2; - uint256 length = input.length; - for (uint i = 0; i < length; ++i) { - uint _byte = uint8(input[i]); - hex_buffer[pos++] = symbols[_byte >> 4]; - hex_buffer[pos++] = symbols[_byte & 0xf]; + function to_hex(bytes memory buffer) public pure returns (string memory) { + + // Fixed buffer size for hexadecimal convertion + uint8 ch = 0; uint8 lower = 0; uint8 upper = 0; + bytes memory table = "0123456789ABCDEF"; + bytes memory out = new bytes(buffer.length * 2); + for(uint256 i = 0; i < buffer.length; i++) { + ch = uint8(buffer[i]); + lower = ch % 16; + upper = (ch - (lower + 1)) % 16; + out[(i * 2)] = table[upper]; + out[(i * 2) + 1] = table[lower]; } - return string(hex_buffer); + + return string(out); } } From 2a01140d59fe506a6c728f062f74f7d427075fb3 Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Thu, 24 Aug 2023 04:19:02 +0000 Subject: [PATCH 23/35] Tests failing due to race conditions. --- test/RAVE.t.sol | 10 ++++++---- test/scripts/runSignRandomEvidence.py | 9 +++------ test/utils/helper.sol | 20 +++++++++----------- 3 files changed, 18 insertions(+), 21 deletions(-) diff --git a/test/RAVE.t.sol b/test/RAVE.t.sol index 182d891..de3291a 100755 --- a/test/RAVE.t.sol +++ b/test/RAVE.t.sol @@ -8,7 +8,7 @@ import { BytesUtils } from "ens-contracts/dnssec-oracle/BytesUtils.sol"; import { MockEvidence, ValidBLSEvidence } from "test/mocks/MockEvidence.sol"; import { X509GenHelper, BytesFFIFuzzer, BytesHelper } from "test/utils/helper.sol"; import { Test, console } from "forge-std/Test.sol"; - +import { Base64 } from "openzeppelin/utils/Base64.sol"; abstract contract RAVETester is Test { using BytesUtils for *; @@ -108,6 +108,8 @@ contract RaveFuzzTester is Test { // Run a fuzz test sequentially on each RAVe parameterization function testRaveFuzz(bytes memory mrenclave, bytes memory mrsigner, bytes memory p) public { vm.assume(p.length >= 64); + if(mrenclave.length != 32) return; + if(mrsigner.length != 32) return; for (uint256 i = 0; i < numFuzzers; i++) { c[i].runRAVE(mrenclave, mrsigner, p); } @@ -140,9 +142,9 @@ contract RaveFuzzer is Test, X509GenHelper, BytesFFIFuzzer { string[] memory cmds = new string[](6); cmds[0] = "python3"; cmds[1] = "test/scripts/runSignRandomEvidence.py"; - cmds[2] = BytesHelper.to_hex(mrenclave); - cmds[3] = BytesHelper.to_hex(mrsigner); - cmds[4] = BytesHelper.to_hex(payload); + cmds[2] = Base64.encode(mrenclave); + cmds[3] = Base64.encode(mrsigner); + cmds[4] = Base64.encode(payload); cmds[5] = X509_PRIV_KEY_NAME; // Request .py sript to generate and sign mock RA evidence diff --git a/test/scripts/runSignRandomEvidence.py b/test/scripts/runSignRandomEvidence.py index 136c62e..f5e9a44 100755 --- a/test/scripts/runSignRandomEvidence.py +++ b/test/scripts/runSignRandomEvidence.py @@ -78,12 +78,9 @@ def sign(fname, message) -> bytes: def main(): # Prepare inputs - stripped_mre = strip_0x(sys.argv[1]) - stripped_mrs = strip_0x(sys.argv[2]) - stripped_payload = strip_0x(sys.argv[3]) - mrenclave = from_hex(stripped_mre) - mrsigner = from_hex(stripped_mrs) - payload = from_hex(stripped_payload) + mrenclave = base64.b64decode(to_b(sys.argv[1])) + mrsigner = base64.b64decode(to_b(sys.argv[2])) + payload = base64.b64decode(to_b(sys.argv[3])) # mock json report evidence, dec_quote_body = mock_evidence(mrenclave, mrsigner, payload) diff --git a/test/utils/helper.sol b/test/utils/helper.sol index 2358176..3e71b0a 100755 --- a/test/utils/helper.sol +++ b/test/utils/helper.sol @@ -16,21 +16,19 @@ library BytesHelper { return false; } - function to_hex(bytes memory buffer) public pure returns (string memory) { + function to_hex(bytes memory buffer) public pure returns (bytes memory) { // Fixed buffer size for hexadecimal convertion - uint8 ch = 0; uint8 lower = 0; uint8 upper = 0; - bytes memory table = "0123456789ABCDEF"; - bytes memory out = new bytes(buffer.length * 2); - for(uint256 i = 0; i < buffer.length; i++) { - ch = uint8(buffer[i]); - lower = ch % 16; - upper = (ch - (lower + 1)) % 16; - out[(i * 2)] = table[upper]; - out[(i * 2) + 1] = table[lower]; + bytes memory converted = new bytes(buffer.length * 2); + + bytes memory _base = "0123456789ABCDEF"; + + for (uint256 i = 0; i < buffer.length; i++) { + converted[i * 2] = _base[uint8(buffer[i]) / 16]; + converted[(i * 2) + 1] = _base[uint8(buffer[i]) % 16]; } - return string(out); + return converted; } } From be4e1ededded2fc15e5ef83f5848318116bbc5d9 Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Thu, 24 Aug 2023 04:43:43 +0000 Subject: [PATCH 24/35] Fix broken tests. --- test/RAVE.t.sol | 8 ++------ test/scripts/bin/get_uuid | 5 +++++ test/scripts/runRSAKeygen.sh | 4 ++-- test/scripts/runX509Gen.sh | 5 +---- test/utils/helper.sol | 24 ++++++++++++++++++++++-- 5 files changed, 32 insertions(+), 14 deletions(-) create mode 100644 test/scripts/bin/get_uuid diff --git a/test/RAVE.t.sol b/test/RAVE.t.sol index de3291a..0468338 100755 --- a/test/RAVE.t.sol +++ b/test/RAVE.t.sol @@ -221,10 +221,10 @@ contract RaveInstanceTest is RaveFuzzer { } } -/* + // Test every FuzzTest parameterization on the same known input contract RaveSanityTester is Test { - bool useCachedX509s = true; + bool useCachedX509s = false; function testOnSanityCheckedValues() public { bytes memory mrenclave = hex"d0ae774774c2064a60dd92541fcc7cb8b3acdea0d793f3b27a27a44dbf71e75f"; @@ -247,7 +247,3 @@ contract RaveSanityTester is Test { } } } - - - -*/ \ No newline at end of file diff --git a/test/scripts/bin/get_uuid b/test/scripts/bin/get_uuid new file mode 100644 index 0000000..3ed48a8 --- /dev/null +++ b/test/scripts/bin/get_uuid @@ -0,0 +1,5 @@ +#!/usr/bin/python3 + +import uuid + +print(str(uuid.uuid4()), end="") \ No newline at end of file diff --git a/test/scripts/runRSAKeygen.sh b/test/scripts/runRSAKeygen.sh index 70b14af..3a7c51b 100755 --- a/test/scripts/runRSAKeygen.sh +++ b/test/scripts/runRSAKeygen.sh @@ -1,7 +1,7 @@ #!/bin/bash # Generates new RSA private key with number of bits passed as command line arg -openssl genrsa -out /tmp/private.pem "$1" +openssl genrsa -out /tmp/private.pem "$1" 2>/dev/null # Write the public key to file -openssl rsa -in /tmp/private.pem -outform der -pubout -out /tmp/public.der \ No newline at end of file +openssl rsa -in /tmp/private.pem -outform der -pubout -out /tmp/public.der 2>/dev/null \ No newline at end of file diff --git a/test/scripts/runX509Gen.sh b/test/scripts/runX509Gen.sh index b6fdcf9..e3c53e1 100755 --- a/test/scripts/runX509Gen.sh +++ b/test/scripts/runX509Gen.sh @@ -4,8 +4,5 @@ BITS=$1 CERT_NAME=$2 KEY_NAME=$3 -rm $CERT_NAME -rm $KEY_NAME - # Create a private key named $KEY_NAME and then self-sign an x509 certificate -echo -e "US\nCA\nSan Francisco\nMy Organization\nMy PARENT Name\n\n\n" | openssl req -x509 -newkey rsa:$BITS -keyout $KEY_NAME -out $CERT_NAME -sha256 -days 365 -nodes 2>&1 >/dev/null \ No newline at end of file +out=$(echo -e "US\nCA\nSan Francisco\nMy Organization\nMy PARENT Name\n\n\n" | openssl req -x509 -newkey rsa:$BITS -keyout $KEY_NAME -out $CERT_NAME -sha256 -days 365 -nodes 2>/dev/null) \ No newline at end of file diff --git a/test/utils/helper.sol b/test/utils/helper.sol index 3e71b0a..6e43a24 100755 --- a/test/utils/helper.sol +++ b/test/utils/helper.sol @@ -6,6 +6,7 @@ import { SafeMath } from "openzeppelin-contracts/contracts/utils/math/SafeMath.s + library BytesHelper { function notAllZeroes(bytes memory data) public pure returns (bool) { for (uint256 i = 0; i < data.length; i++) { @@ -32,6 +33,23 @@ library BytesHelper { } } +contract ExtraUtils is Test { + function uuid() + public + returns (string memory) + { + string[] memory cmds = new string[](2); + cmds[0] = "python3"; + cmds[1] = "test/scripts/bin/get_uuid"; + + // Request .py sript to generate and sign mock RA evidence + bytes memory resp = vm.ffi(cmds); + console.logBytes(resp); + + return (string(resp)); + } +} + contract BytesFFIFuzzer is Test { // convert random fuzzed bytes -> hex string -> valid utf-8 bytes function getFriendlyBytes(bytes memory _fuzzedBytes) public pure returns (bytes memory) { @@ -42,6 +60,8 @@ contract BytesFFIFuzzer is Test { function getFriendlyBytes32(bytes32 _fuzzedBytes) public pure returns (bytes memory) { return bytes(vm.toString(_fuzzedBytes)); } + + } contract KeyGenHelper is Test { @@ -66,7 +86,7 @@ contract KeyGenHelper is Test { } // Helper functions to generate self-signed x509 and methods to extract relevant info -contract X509GenHelper is Test { +contract X509GenHelper is Test, ExtraUtils { bytes public CERT_BYTES; bytes public CERT_BODY_BYTES; bytes public CERT_SIG; @@ -81,7 +101,7 @@ contract X509GenHelper is Test { constructor(string memory keyBits) { KEY_BITS = keyBits; X509_NAME = string(abi.encodePacked("/tmp/", keyBits, "BitSelfSignedx509.pem")); - X509_PRIV_KEY_NAME = string(abi.encodePacked("/tmp/", keyBits, "Bitx509SigningKey.pem")); + X509_PRIV_KEY_NAME = string(abi.encodePacked("/tmp/", keyBits, ExtraUtils.uuid(), "Bitx509SigningKey.pem")); } function newSelfSignedX509() public { From 875ee26cb283c810614e4ab692861d09b3e84d8c Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Thu, 24 Aug 2023 06:13:12 +0000 Subject: [PATCH 25/35] Extra checks for errors near sensitive math prone to underflows. --- src/ASN1Decode.sol | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/ASN1Decode.sol b/src/ASN1Decode.sol index 1dfbf0a..bc74ad8 100755 --- a/src/ASN1Decode.sol +++ b/src/ASN1Decode.sol @@ -180,6 +180,7 @@ library Asn1Decode { ptr.overflowCheck(der.length); if(ptr.content_len() >= 1) { uint256 len = (ptr.end_index() - ptr.type_index()) + 1; + require(ptr.type_index() + len <= der.length); return der.substring(ptr.type_index(), len); } revert(); @@ -274,6 +275,7 @@ library Asn1Decode { ptr.overflowCheck(der.length); if(ptr.content_len() >= 1) { uint256 len = (ptr.end_index() - ptr.type_index()) + 1; + require(ptr.type_index() + len <= der.length); return der.keccak(ptr.type_index(), len); } revert(); @@ -297,11 +299,11 @@ library Asn1Decode { require(der[ptr.content_index()] == 0x00); // Return the segment and avoid overflows. - uint256 valueLength = ptr.end_index() + 1 - ptr.content_index(); - require(valueLength > 0); - require(ptr.content_index() + 1 < der.length); - require(valueLength - 1 < der.length); - return der.substring(ptr.content_index() + 1, valueLength - 1); + uint256 start_index = ptr.content_index() + 1; + uint256 valueLength = (ptr.end_index() - ptr.content_index()); + require(start_index < der.length); + require(start_index + valueLength <= der.length); + return der.substring(start_index, valueLength); } revert(); } @@ -358,11 +360,11 @@ type, (opt type) (len or len flag) (opt len ... N) (opt buf .. N) if (lengthbytesLength == 1) { length = der.readUint8(ix + 2); } else if (lengthbytesLength == 2) { - require((der.length - (ix + 2)) >= 2); + require(ix + 3 < der.length); length = der.readUint16(ix + 2); } else { // Ensure enough bytes left for len no. - require((der.length - (ix + 2)) >= lengthbytesLength); + require(ix + 2 + lengthbytesLength <= der.length); require(lengthbytesLength <= 32); // Read variable length len field. @@ -386,6 +388,11 @@ type, (opt type) (len or len flag) (opt len ... N) (opt buf .. N) require(ixLastContentByte < der.length); require(ixLastContentByte > 0); + // If the end pointer value is less than start then + // it may lead to an underflow and this is + // particullarly bad with solidity's wrap-around math. + require(ixLastContentByte >= ixFirstContentByte); + // Return the nodeptr structure. return NodePtr.getPtr(ix, ixFirstContentByte, ixLastContentByte); } From 2aa95956b0ea68e78be7d243d3d8e94bdad57109 Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Mon, 4 Sep 2023 02:15:15 +0000 Subject: [PATCH 26/35] Add check for RSA algorithm ID. --- .gitignore | 3 +++ src/RAVE.sol | 7 +++++-- src/X509Verifier.sol | 11 +++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 4b8977c..839b6ff 100755 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,6 @@ test/scripts/bin/error.log # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] + +# Log file I use for test output. +all.txt \ No newline at end of file diff --git a/src/RAVE.sol b/src/RAVE.sol index 6e102c4..0b1fbca 100755 --- a/src/RAVE.sol +++ b/src/RAVE.sol @@ -35,14 +35,17 @@ contract RAVE is Test, RAVEBase, JSONBuilder, X509Verifier { (Values memory reportValues, bytes memory reportBytes) = _buildReportBytes(reportFieldsABI); console.log(string(reportBytes)); + // Verify the report's contents match the expected + payload = _verifyReportContents(reportValues, mrenclave, mrsigner); + + // Verify the report was signed by the SigningPK if (!verifyRSA(reportBytes, sig, signingMod, signingExp)) { console.logBytes(sig); revert BadReportSignature(); } - // Verify the report's contents match the expected - payload = _verifyReportContents(reportValues, mrenclave, mrsigner); + return payload; } diff --git a/src/X509Verifier.sol b/src/X509Verifier.sol index 5239b76..d79ce97 100755 --- a/src/X509Verifier.sol +++ b/src/X509Verifier.sol @@ -18,6 +18,10 @@ contract X509Verifier is Test { bytes constant _SHA256_PAD_ID_WITH_NULL = hex"3031300d060960864801650304020105000420"; bytes constant _SHA256_PAD_ID_WITHOUT_NULL = hex"302f300b06096086480165030402010420"; + // DER encoded sequence for the RSA algorithm ID. + // Object ID is 1.2.840.113549.1.1.1. + bytes constant _RSA_ALGO_SEQ = hex"06092a864886f70d0101010500"; + constructor() { } /* @@ -248,6 +252,13 @@ contract X509Verifier is Test { // Enter subjectPublicKeyInfo ptr = cert.firstChildOf(ptr); // point to subjectPublicKeyInfo.algorithm + + // Require the algorithm to be RSA. + bytes memory algorithm = cert.bytesAt(ptr); + require(_RSA_ALGO_SEQ.compare(algorithm) == 0); + console.log("algorithm = "); + console.logBytes(algorithm); + ptr = cert.nextSiblingOf(ptr); // point to subjectPublicKeyInfo.subjectPublicKey // Extract DER-encoded RSA public key From 0a28a57ed0fec6b980d517eab93c5d772f171206 Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Mon, 4 Sep 2023 02:37:11 +0000 Subject: [PATCH 27/35] Add checks for sig algorithm. Need to avoid declaring too many variables in this func to avoid stack exhaustion. --- src/X509Verifier.sol | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/X509Verifier.sol b/src/X509Verifier.sol index d79ce97..86d93f2 100755 --- a/src/X509Verifier.sol +++ b/src/X509Verifier.sol @@ -17,10 +17,11 @@ contract X509Verifier is Test { bytes constant _SHA256_PAD_ID_WITH_NULL = hex"3031300d060960864801650304020105000420"; bytes constant _SHA256_PAD_ID_WITHOUT_NULL = hex"302f300b06096086480165030402010420"; + bytes constant _CERT_PUB_ALG = hex"2A864886F70D010101"; + bytes constant _CERT_SIG_ALG = hex"2a864886f70d01010b"; - // DER encoded sequence for the RSA algorithm ID. - // Object ID is 1.2.840.113549.1.1.1. - bytes constant _RSA_ALGO_SEQ = hex"06092a864886f70d0101010500"; + + // 06092a864886f70d01010b0500 constructor() { } @@ -191,17 +192,21 @@ contract X509Verifier is Test { view returns (bytes memory, bytes memory) { - // Pointer to top level asn1 object: Sequence{tbsCertificate, signatureAlgorithm, signatureValue} - uint256 root = cert.root(); - // Traverse to first in sequence (the tbsCertificate) - uint256 tbsPtr = cert.firstChildOf(root); + uint256 tbsPtr = cert.firstChildOf(cert.root()); // Extracts the TBSCerificate (what is used as input to RSA-SHA256) bytes memory certBody = cert.allBytesAt(tbsPtr); // Top level traverse to signatureAlgorithm uint256 sigAlgPtr = cert.nextSiblingOf(tbsPtr); + require( + _CERT_SIG_ALG.compare( + cert.bytesAt( + cert.firstChildOf(sigAlgPtr) + ) + ) == 0 + ); // Top level traverse to signatureValue uint256 sigPtr = cert.nextSiblingOf(sigAlgPtr); @@ -253,11 +258,14 @@ contract X509Verifier is Test { // Enter subjectPublicKeyInfo ptr = cert.firstChildOf(ptr); // point to subjectPublicKeyInfo.algorithm - // Require the algorithm to be RSA. - bytes memory algorithm = cert.bytesAt(ptr); - require(_RSA_ALGO_SEQ.compare(algorithm) == 0); - console.log("algorithm = "); - console.logBytes(algorithm); + // Require the pubkey algorithm to be RSA. + require( + _CERT_PUB_ALG.compare( + cert.bytesAt( + cert.firstChildOf(ptr) + ) + ) == 0 + ); ptr = cert.nextSiblingOf(ptr); // point to subjectPublicKeyInfo.subjectPublicKey From 2c8826d1f5a74451eadf6f25b476d479b1b1f0a8 Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Wed, 20 Sep 2023 00:37:21 +0000 Subject: [PATCH 28/35] Adding fixed params for Intel root CA. --- src/RAVE.sol | 16 +++++++++ src/RAVEConsts.sol | 1 + src/X509Verifier.sol | 73 ++++++++++++++++++++++++++++++-------- test/X509Viewer.sol | 59 ++++++++++++++++++++++++++++++ test/scripts/runX509Gen.sh | 3 +- 5 files changed, 136 insertions(+), 16 deletions(-) create mode 100644 test/X509Viewer.sol diff --git a/src/RAVE.sol b/src/RAVE.sol index 0b1fbca..81c4342 100755 --- a/src/RAVE.sol +++ b/src/RAVE.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 pragma solidity >=0.8.0 <0.9.0; +import { RAVEConsts } from "./RAVEConsts.sol"; import { X509Verifier } from "./X509Verifier.sol"; import { JSONBuilder } from "./JSONBuilder.sol"; import { BytesUtils } from "ens-contracts/dnssec-oracle/BytesUtils.sol"; @@ -69,6 +70,21 @@ contract RAVE is Test, RAVEBase, JSONBuilder, X509Verifier { bytes memory mrenclave, bytes memory mrsigner ) public view override returns (bytes memory payload) { + /* + The root CA params are hard-coded in the contract. + If blank data is passed to the function use these values. + Otherwise use the passed values so self-signed certs + can be used as input test data. + */ + if( + (signingMod.compare(NULL) == 0) + && + (signingExp.compare(NULL) == 0) + ) { + signingMod = _INTEL_ROOT_MOD; + signingExp = _INTEL_ROOT_EXP; + } + // Verify the leafX509Cert was signed with signingMod and signingExp (bytes memory leafCertModulus, bytes memory leafCertExponent) = verifySignedX509(leafX509Cert, signingMod, signingExp); diff --git a/src/RAVEConsts.sol b/src/RAVEConsts.sol index 9c146d6..70da5b4 100755 --- a/src/RAVEConsts.sol +++ b/src/RAVEConsts.sol @@ -11,4 +11,5 @@ abstract contract RAVEConsts { bytes32 constant OK_STATUS = keccak256("OK"); bytes32 constant HARDENING_STATUS = keccak256("SW_HARDENING_NEEDED"); + bytes constant NULL = hex""; } diff --git a/src/X509Verifier.sol b/src/X509Verifier.sol index 86d93f2..5783b75 100755 --- a/src/X509Verifier.sol +++ b/src/X509Verifier.sol @@ -20,7 +20,15 @@ contract X509Verifier is Test { bytes constant _CERT_PUB_ALG = hex"2A864886F70D010101"; bytes constant _CERT_SIG_ALG = hex"2a864886f70d01010b"; - + bytes constant _INTEL_ROOT_MOD = hex"9F3C647EB5773CBB512D2732C0D7415EBB55A0FA9EDE2E649199E6821DB910D53177370977466A6A5E4786CCD2DDEBD4149D6A2F6325529DD10CC98737B0779C1A07E29C47A1AE004948476C489F45A5A15D7AC8ECC6ACC645ADB43D87679DF59C093BC5A2E9696C5478541B979E754B573914BE55D32FF4C09DDF27219934CD990527B3F92ED78FBF29246ABECB71240EF39C2D7107B447545A7FFB10EB060A68A98580219E36910952683892D6A5E2A80803193E407531404E36B315623799AA825074409754A2DFE8F5AFD5FE631E1FC2AF3808906F28A790D9DD9FE060939B125790C5805D037DF56A99531B96DE69DE33ED226CC1207D1042B5C9AB7F404FC711C0FE4769FB9578B1DC0EC469EA1A25E0FF9914886EF2699B235BB4847DD6FF40B606E6170793C2FB98B314587F9CFD257362DFEAB10B3BD2D97673A1A4BD44C453AAF47FC1F2D3D0F384F74A06F89C089F0DA6CDB7FCEEE8C9821A8E54F25C0416D18C46839A5F8012FBDD3DC74D256279ADC2C0D55AFF6F0622425D1B"; + bytes constant _INTEL_ROOT_EXP = hex"010001"; + + // Intel SGX Attestation Report Signing [subject] (issuer blank) + bytes constant _SGX_REPORT_SIGNING_SUBJECT = hex"310b3009060355040613025553310b300906035504080c0243413114301206035504070c0b53616e746120436c617261311a3018060355040a0c11496e74656c20436f72706f726174696f6e3130302e06035504030c27496e74656c20534758204174746573746174696f6e205265706f7274205369676e696e67204341"; + + // Intel SGX Attestation Report Root CA Signing [subject and issuer] + bytes constant _SGX_ROOT_SA_SUBJECT = hex"310b3009060355040613025553310b300906035504080c0243413114301206035504070c0b53616e746120436c617261311a3018060355040a0c11496e74656c20436f72706f726174696f6e3130302e06035504030c27496e74656c20534758204174746573746174696f6e205265706f7274205369676e696e67204341"; + // 06092a864886f70d01010b0500 constructor() { } @@ -192,6 +200,22 @@ contract X509Verifier is Test { view returns (bytes memory, bytes memory) { + /* + Test code calls this function directly + using self-signed certs. Consequently, they + will have different mods and exps to Intel. + Extended checks for issuer and subject will + be disabled in this case. + */ + bool extended_checks = true; + if( + (parentMod.compare(_INTEL_ROOT_MOD) != 0) + && + (parentExp.compare(_INTEL_ROOT_EXP) != 0) + ) { + extended_checks = false; + } + // Traverse to first in sequence (the tbsCertificate) uint256 tbsPtr = cert.firstChildOf(cert.root()); @@ -200,13 +224,15 @@ contract X509Verifier is Test { // Top level traverse to signatureAlgorithm uint256 sigAlgPtr = cert.nextSiblingOf(tbsPtr); - require( - _CERT_SIG_ALG.compare( - cert.bytesAt( - cert.firstChildOf(sigAlgPtr) - ) - ) == 0 - ); + if(extended_checks) { + require( + _CERT_SIG_ALG.compare( + cert.bytesAt( + cert.firstChildOf(sigAlgPtr) + ) + ) == 0 + ); + } // Top level traverse to signatureValue uint256 sigPtr = cert.nextSiblingOf(sigAlgPtr); @@ -236,6 +262,17 @@ contract X509Verifier is Test { // Skip the next 3 fields (signature, issuer, validity, subject) ptr = cert.nextSiblingOf(ptr); // point to signature ptr = cert.nextSiblingOf(ptr); // point to issuer + console.log("issuer..."); + console.logBytes(cert.bytesAt(ptr)); + + /* + require( + _SGX_REPORT_SIGNING_SUBJECT.compare( + cert.bytesAt(ptr) + ) == 0 + ); + */ + ptr = cert.nextSiblingOf(ptr); // point to validity // Arrive at the validity field @@ -253,19 +290,25 @@ contract X509Verifier is Test { // Traverse until the subjectPublicKeyInfo field ptr = cert.nextSiblingOf(ptr); // point to subject + console.log("subject"); + console.logBytes(cert.bytesAt(ptr)); + + ptr = cert.nextSiblingOf(ptr); // point to subjectPublicKeyInfo // Enter subjectPublicKeyInfo ptr = cert.firstChildOf(ptr); // point to subjectPublicKeyInfo.algorithm // Require the pubkey algorithm to be RSA. - require( - _CERT_PUB_ALG.compare( - cert.bytesAt( - cert.firstChildOf(ptr) - ) - ) == 0 - ); + if(extended_checks) { + require( + _CERT_PUB_ALG.compare( + cert.bytesAt( + cert.firstChildOf(ptr) + ) + ) == 0 + ); + } ptr = cert.nextSiblingOf(ptr); // point to subjectPublicKeyInfo.subjectPublicKey diff --git a/test/X509Viewer.sol b/test/X509Viewer.sol new file mode 100644 index 0000000..d4f17dc --- /dev/null +++ b/test/X509Viewer.sol @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity >=0.8.0 <0.9.0; + +import { Test, console } from "forge-std/Test.sol"; +import { Utils } from "rave/Utils.sol"; +import { Asn1Decode, NodePtr } from "rave/ASN1Decode.sol"; +import { X509GenHelper } from "test/utils/helper.sol"; +import { Asn1Decode } from "rave/ASN1Decode.sol"; +import { X509Verifier } from "rave/X509Verifier.sol"; +import { RAVE } from "rave/RAVE.sol"; +import { BytesUtils } from "ens-contracts/dnssec-oracle/BytesUtils.sol"; +import { Base64 } from "openzeppelin/utils/Base64.sol"; + +contract TestViewX509 is Test { + using Asn1Decode for bytes; + using BytesUtils for bytes; + using Utils for bytes; + + bytes constant cert = hex"308204a130820309a003020102020900d107765d32a3b096300d06092a864886f70d01010b0500307e310b3009060355040613025553310b300906035504080c0243413114301206035504070c0b53616e746120436c617261311a3018060355040a0c11496e74656c20436f72706f726174696f6e3130302e06035504030c27496e74656c20534758204174746573746174696f6e205265706f7274205369676e696e67204341301e170d3136313132323039333635385a170d3236313132303039333635385a307b310b3009060355040613025553310b300906035504080c0243413114301206035504070c0b53616e746120436c617261311a3018060355040a0c11496e74656c20436f72706f726174696f6e312d302b06035504030c24496e74656c20534758204174746573746174696f6e205265706f7274205369676e696e6730820122300d06092a864886f70d01010105000382010f003082010a0282010100a97a2de0e66ea6147c9ee745ac0162686c7192099afc4b3f040fad6de093511d74e802f510d716038157dcaf84f4104bd3fed7e6b8f99c8817fd1ff5b9b864296c3d81fa8f1b729e02d21d72ffee4ced725efe74bea68fbc4d4244286fcdd4bf64406a439a15bcb4cf67754489c423972b4a80df5c2e7c5bc2dbaf2d42bb7b244f7c95bf92c75d3b33fc5410678a89589d1083da3acc459f2704cd99598c275e7c1878e00757e5bdb4e840226c11c0a17ff79c80b15c1ddb5af21cc2417061fbd2a2da819ed3b72b7efaa3bfebe2805c9b8ac19aa346512d484cfc81941e15f55881cc127e8f7aa12300cd5afb5742fa1d20cb467a5beb1c666cf76a368978b50203010001a381a43081a1301f0603551d2304183016801478437b76a67ebcd0af7e4237eb357c3b8701513c300e0603551d0f0101ff0404030206c0300c0603551d130101ff0402300030600603551d1f045930573055a053a051864f687474703a2f2f7472757374656473657276696365732e696e74656c2e636f6d2f636f6e74656e742f43524c2f5347582f4174746573746174696f6e5265706f72745369676e696e6743412e63726c300d06092a864886f70d01010b050003820181006708b61b5c2bd215473e2b46af99284fbb939d3f3b152c996f1a6af3b329bd220b1d3b610f6bce2e6753bded304db21912f385256216cfcba456bd96940be892f5690c260d1ef84f1606040222e5fe08e5326808212a447cfdd64a46e94bf29f6b4b9a721d25b3c4e2f62f58baed5d77c505248f0f801f9fbfb7fd752080095cee80938b339f6dbb4e165600e20e4a718812d49d9901e310a9b51d66c79909c6996599fae6d76a79ef145d9943bf1d3e35d3b42d1fb9a45cbe8ee334c166eee7d32fcdc9935db8ec8bb1d8eb3779dd8ab92b6e387f0147450f1e381d08581fb83df33b15e000a59be57ea94a3a52dc64bdaec959b3464c91e725bbdaea3d99e857e380a23c9d9fb1ef58e9e42d71f12130f9261d7234d6c37e2b03dba40dfdfb13ac4ad8e13fd3756356b6b50015a3ec9580b815d87c2cef715cd28df00bbf2a3c403ebf6691b3f05edd9143803ca085cff57e053eec2f8fea46ea778a68c9be885bc28225bc5f309be4a2b74d3a03945319dd3c7122fed6ff53bb8b8cb3a03c"; + + function testViewCert() public { + + // Traverse to first in sequence (the tbsCertificate) + uint256 tbsPtr = cert.firstChildOf(cert.root()); + + // Extracts the TBSCerificate (what is used as input to RSA-SHA256) + bytes memory certBody = cert.allBytesAt(tbsPtr); + + // Top level traverse to signatureAlgorithm + uint256 sigAlgPtr = cert.nextSiblingOf(tbsPtr); + + // Top level traverse to signatureValue + uint256 sigPtr = cert.nextSiblingOf(sigAlgPtr); + + // Extracts the signed certificate body + bytes memory signature = cert.bytesAt(sigPtr); + + // Traverse to first child of tbsCertificate + uint256 ptr = cert.firstChildOf(tbsPtr); + + // Account for v1 vs v3 + if (cert[NodePtr.type_index(ptr)] == 0xa0) { + ptr = cert.nextSiblingOf(ptr); + } + + // Skip the next 3 fields (signature, issuer, validity, subject) + ptr = cert.nextSiblingOf(ptr); // point to signature + ptr = cert.nextSiblingOf(ptr); // point to issuer + console.log("issuer..."); + console.logBytes(cert.bytesAt(ptr)); + ptr = cert.nextSiblingOf(ptr); // point to validity + + // Traverse until the subjectPublicKeyInfo field + ptr = cert.nextSiblingOf(ptr); // point to subject + console.log("subject"); + console.logBytes(cert.bytesAt(ptr)); + } + +} \ No newline at end of file diff --git a/test/scripts/runX509Gen.sh b/test/scripts/runX509Gen.sh index e3c53e1..25d6846 100755 --- a/test/scripts/runX509Gen.sh +++ b/test/scripts/runX509Gen.sh @@ -5,4 +5,5 @@ CERT_NAME=$2 KEY_NAME=$3 # Create a private key named $KEY_NAME and then self-sign an x509 certificate -out=$(echo -e "US\nCA\nSan Francisco\nMy Organization\nMy PARENT Name\n\n\n" | openssl req -x509 -newkey rsa:$BITS -keyout $KEY_NAME -out $CERT_NAME -sha256 -days 365 -nodes 2>/dev/null) \ No newline at end of file +# US\nCA\nSan Francisco\nMy Organization\nMy PARENT Name\n\n\n +out=$(echo -e "US\nCA\nSanta Clara\nIntel Corporation\nIntel SGX Attestation Report Signing\n\n\n" | openssl req -x509 -newkey rsa:$BITS -keyout $KEY_NAME -out $CERT_NAME -sha256 -days 365 -nodes 2>/dev/null) \ No newline at end of file From 3800a27b9681f041df96376b96bad14b8d755015 Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Wed, 20 Sep 2023 01:04:30 +0000 Subject: [PATCH 29/35] Add more comments in RAVE due to its complexity. --- src/RAVE.sol | 73 +++++++++++++++++++++++++++++++++++--- test/scripts/bin/ss_to_abi | 2 +- 2 files changed, 70 insertions(+), 5 deletions(-) diff --git a/src/RAVE.sol b/src/RAVE.sol index 81c4342..9ee85c1 100755 --- a/src/RAVE.sol +++ b/src/RAVE.sol @@ -1,3 +1,43 @@ +/* +The most significant function in this module is rave(). +The purpose of RAVE is to validate the integrity of an +'attestation report' vouched for by Intel and return the +reports payload body on success. + +The process involves: + (1) Re-constructing a JSON attestation report that + byte-for-byte matches the original report returned by + the appropriate Intel attestation APIs. + (2) Confirming that the report was signed by an X509 + 'leaf' certificate issued by a CA. + (3) Confirming that this CA was in fact Intel + (also known as the 'report attestation signer CA -- this + cert can be found in the certs directory in both + DER form and PEM form for convienence.) + +The result is an API that can verify attestation reports +on-chain issued by Intel. Unfortunately, the process to +call the rave() function is quite involved. One has to: + (1) Pack a special list of report fields as bytes. + (2) Extract the right enclave hash values. + (3) And pass in the right leaf certificate values. + +All of this is easier said than done. But I've created some +scripts to make this a little easier. + (1) There is a script that takes the output of the + secure signer binary (ss_out) and converts it into a + list of hex data for calling rave(). It can be found in + /test/scripts/bin/ss_to_abi. The bin directory also + contains other useful commands for working with certs + and doing operations needed for RAVE. You will need to cd + to this dir to use them though. + (2) There is also a script demonstrating full deployment + of the RAVE contract and calling rave() from scratch + using the above function. It can be found in my fork + here: https://github.com/matthew-puffer-finance-forks/rave-foundry/blob/master/deploy.sh +*/ + + // SPDX-License-Identifier: Apache-2.0 pragma solidity >=0.8.0 <0.9.0; @@ -50,23 +90,48 @@ contract RAVE is Test, RAVEBase, JSONBuilder, X509Verifier { return payload; } + + /** * @inheritdoc RAVEBase */ function rave( // ABI encoded list of report fields as bytes. - // current incorrectly passing json. bytes calldata report, + + /* + RSA encryption of the report from the leaf cert. + The exact algorithm is: sha256WithRSA (PKCS#1 padding.) + The signature can be verified with the signing + public key found inside the leaf X509 cert. + */ bytes memory sig, - // root ca or report cert? + /* + This can be a leaf certificate issued by Intel's + 'report signing CA' or it can be a self-signed cert. + Refer to the field bellow for more details. + */ bytes memory leafX509Cert, - // root ca or report cert? - // usage seems to indicate intel root ca + /* + The fields here allow passing in the parameters + for the CA who issued the leaf certificate. + Set the bytes to empty for both to force it to use + the Intel root CA. Otherwise, you can pass in your + own values to test the function with self-signed certs. + */ bytes memory signingMod, bytes memory signingExp, + /* + These are special values that belong to the enclave binary + and hardware that did the attestation report. + You can gather them using: + occlum print mrenclave + occlum print mrsigner + In the enclave directory. + */ bytes memory mrenclave, bytes memory mrsigner ) public view override returns (bytes memory payload) { diff --git a/test/scripts/bin/ss_to_abi b/test/scripts/bin/ss_to_abi index b75332a..7a94a62 100755 --- a/test/scripts/bin/ss_to_abi +++ b/test/scripts/bin/ss_to_abi @@ -45,7 +45,7 @@ sig_hex=$(echo "$sig" | base64 --decode | ./to_hex) report_hex=$(echo -n "$report" | ./to_hex) # Extract fields from JSON report and store as ABI encoded hex. -report_calldata_hex=$(echo -n "$report" | ./report_to_calldata) +report_calldata_hex=$(echo -n "$report" | ./report_tndo_calldata) # Inputs should all be hex. abi_out=$( From f89b008d56922e983c2f09d8e2ffa6985c3b10b4 Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Wed, 20 Sep 2023 01:05:09 +0000 Subject: [PATCH 30/35] Typo. --- src/RAVE.sol | 10 +++++++++- test/scripts/bin/ss_to_abi | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/RAVE.sol b/src/RAVE.sol index 9ee85c1..4c228c7 100755 --- a/src/RAVE.sol +++ b/src/RAVE.sol @@ -13,7 +13,7 @@ The process involves: (3) Confirming that this CA was in fact Intel (also known as the 'report attestation signer CA -- this cert can be found in the certs directory in both - DER form and PEM form for convienence.) + DER form and PEM form for convenience.) The result is an API that can verify attestation reports on-chain issued by Intel. Unfortunately, the process to @@ -35,6 +35,14 @@ scripts to make this a little easier. of the RAVE contract and calling rave() from scratch using the above function. It can be found in my fork here: https://github.com/matthew-puffer-finance-forks/rave-foundry/blob/master/deploy.sh + +Working with signed data is inherently painful because if +anything is off by so much as a single bit it will fail. +While testing this software I had the issue of a single +new line being added to the report due to the echo command. +Nothing was wrong with the code but the addition caused all +checks to fail. There are tools to assess whether much of +the values are correct in the /test/scripts/bin directory. */ diff --git a/test/scripts/bin/ss_to_abi b/test/scripts/bin/ss_to_abi index 7a94a62..b75332a 100755 --- a/test/scripts/bin/ss_to_abi +++ b/test/scripts/bin/ss_to_abi @@ -45,7 +45,7 @@ sig_hex=$(echo "$sig" | base64 --decode | ./to_hex) report_hex=$(echo -n "$report" | ./to_hex) # Extract fields from JSON report and store as ABI encoded hex. -report_calldata_hex=$(echo -n "$report" | ./report_tndo_calldata) +report_calldata_hex=$(echo -n "$report" | ./report_to_calldata) # Inputs should all be hex. abi_out=$( From 2f9acb5bac6af6073c0ee68583335a08a39bfba6 Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Wed, 20 Sep 2023 01:07:18 +0000 Subject: [PATCH 31/35] This test proves that the hard coded root params are being used. --- test/RAVE.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/RAVE.t.sol b/test/RAVE.t.sol index 0468338..556ac5b 100755 --- a/test/RAVE.t.sol +++ b/test/RAVE.t.sol @@ -72,7 +72,7 @@ abstract contract RAVETester is Test { ) public view { // Run rave to extract its payload bytes memory gotPayload = - c.rave(bytes(report), sig, signingCert, intelRootModulus, intelRootExponent, mrenclave, mrsigner); + c.rave(bytes(report), sig, signingCert, hex"", hex"", mrenclave, mrsigner); // Verify it matches the expected payload assert(keccak256(gotPayload.substring(0, expPayload.length)) == keccak256(expPayload)); From b31f71172fc5373a51a3b5cafe78d041785ee33e Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Wed, 20 Sep 2023 01:22:34 +0000 Subject: [PATCH 32/35] Add suggested fixes. Rave sanity checker is flaky and still succeeding inconsistently but its not an issue with the code. --- src/X509Verifier.sol | 66 ++++++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 30 deletions(-) diff --git a/src/X509Verifier.sol b/src/X509Verifier.sol index 5783b75..1d6f26e 100755 --- a/src/X509Verifier.sol +++ b/src/X509Verifier.sol @@ -26,6 +26,8 @@ contract X509Verifier is Test { // Intel SGX Attestation Report Signing [subject] (issuer blank) bytes constant _SGX_REPORT_SIGNING_SUBJECT = hex"310b3009060355040613025553310b300906035504080c0243413114301206035504070c0b53616e746120436c617261311a3018060355040a0c11496e74656c20436f72706f726174696f6e3130302e06035504030c27496e74656c20534758204174746573746174696f6e205265706f7274205369676e696e67204341"; + bytes constant _SGX_REPORT_SIGNING_ISSUER = hex"310b3009060355040613025553310b300906035504080c0243413114301206035504070c0b53616e746120436c617261311a3018060355040a0c11496e74656c20436f72706f726174696f6e312d302b06035504030c24496e74656c20534758204174746573746174696f6e205265706f7274205369676e696e67"; + // Intel SGX Attestation Report Root CA Signing [subject and issuer] bytes constant _SGX_ROOT_SA_SUBJECT = hex"310b3009060355040613025553310b300906035504080c0243413114301206035504070c0b53616e746120436c617261311a3018060355040a0c11496e74656c20436f72706f726174696f6e3130302e06035504030c27496e74656c20534758204174746573746174696f6e205265706f7274205369676e696e67204341"; @@ -207,14 +209,15 @@ contract X509Verifier is Test { Extended checks for issuer and subject will be disabled in this case. */ - bool extended_checks = true; + bool extended_checks = false; if( - (parentMod.compare(_INTEL_ROOT_MOD) != 0) + (parentMod.compare(_INTEL_ROOT_MOD) == 0) && - (parentExp.compare(_INTEL_ROOT_EXP) != 0) + (parentExp.compare(_INTEL_ROOT_EXP) == 0) ) { - extended_checks = false; + extended_checks = true; } + console.log(extended_checks); // Traverse to first in sequence (the tbsCertificate) uint256 tbsPtr = cert.firstChildOf(cert.root()); @@ -224,15 +227,13 @@ contract X509Verifier is Test { // Top level traverse to signatureAlgorithm uint256 sigAlgPtr = cert.nextSiblingOf(tbsPtr); - if(extended_checks) { - require( - _CERT_SIG_ALG.compare( - cert.bytesAt( - cert.firstChildOf(sigAlgPtr) - ) - ) == 0 - ); - } + require( + _CERT_SIG_ALG.compare( + cert.bytesAt( + cert.firstChildOf(sigAlgPtr) + ) + ) == 0 + ); // Top level traverse to signatureValue uint256 sigPtr = cert.nextSiblingOf(sigAlgPtr); @@ -264,14 +265,14 @@ contract X509Verifier is Test { ptr = cert.nextSiblingOf(ptr); // point to issuer console.log("issuer..."); console.logBytes(cert.bytesAt(ptr)); - - /* - require( - _SGX_REPORT_SIGNING_SUBJECT.compare( - cert.bytesAt(ptr) - ) == 0 - ); - */ + if(extended_checks) { + require( + _SGX_REPORT_SIGNING_SUBJECT.compare( + cert.bytesAt(ptr) + ) == 0 + ); + } + ptr = cert.nextSiblingOf(ptr); // point to validity @@ -292,6 +293,13 @@ contract X509Verifier is Test { ptr = cert.nextSiblingOf(ptr); // point to subject console.log("subject"); console.logBytes(cert.bytesAt(ptr)); + if(extended_checks) { + require( + _SGX_REPORT_SIGNING_ISSUER.compare( + cert.bytesAt(ptr) + ) == 0 + ); + } ptr = cert.nextSiblingOf(ptr); // point to subjectPublicKeyInfo @@ -300,15 +308,13 @@ contract X509Verifier is Test { ptr = cert.firstChildOf(ptr); // point to subjectPublicKeyInfo.algorithm // Require the pubkey algorithm to be RSA. - if(extended_checks) { - require( - _CERT_PUB_ALG.compare( - cert.bytesAt( - cert.firstChildOf(ptr) - ) - ) == 0 - ); - } + require( + _CERT_PUB_ALG.compare( + cert.bytesAt( + cert.firstChildOf(ptr) + ) + ) == 0 + ); ptr = cert.nextSiblingOf(ptr); // point to subjectPublicKeyInfo.subjectPublicKey From 2b98ea66dbb35e8045ee8fe0e680c42e82b1fde6 Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Thu, 21 Sep 2023 02:26:40 +0000 Subject: [PATCH 33/35] Saving progress on x509 validity periods. --- .gitmodules | 3 +++ lib/ethereum-datetime | 1 + src/X509Verifier.sol | 27 ++++++++++++++++++++++++++- test/X509Viewer.sol | 10 +++++++++- 4 files changed, 39 insertions(+), 2 deletions(-) create mode 160000 lib/ethereum-datetime diff --git a/.gitmodules b/.gitmodules index 5e08d23..7d947ef 100755 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,6 @@ path = lib/openzeppelin-contracts url = https://github.com/openzeppelin/openzeppelin-contracts branch = v4.9.1 +[submodule "lib/ethereum-datetime"] + path = lib/ethereum-datetime + url = https://github.com/pipermerriam/ethereum-datetime.git diff --git a/lib/ethereum-datetime b/lib/ethereum-datetime new file mode 160000 index 0000000..7a08a9b --- /dev/null +++ b/lib/ethereum-datetime @@ -0,0 +1 @@ +Subproject commit 7a08a9bc10fdff2e0187d4cda7f6f0f7f72b62c0 diff --git a/src/X509Verifier.sol b/src/X509Verifier.sol index 1d6f26e..65d6de4 100755 --- a/src/X509Verifier.sol +++ b/src/X509Verifier.sol @@ -7,9 +7,10 @@ import { BytesUtils } from "ens-contracts/dnssec-oracle/BytesUtils.sol"; import { SafeMath } from "openzeppelin-contracts/contracts/utils/math/SafeMath.sol"; import { Math } from "openzeppelin-contracts/contracts/utils/math/Math.sol"; import { Utils } from "./Utils.sol"; +import "ethereum-datetime/DateTime.sol"; import { Test, console } from "forge-std/Test.sol"; -contract X509Verifier is Test { +contract X509Verifier is Test, DateTime { using Asn1Decode for bytes; using BytesUtils for bytes; using Utils for bytes; @@ -168,6 +169,30 @@ contract X509Verifier is Test { return success && (keccak256(res) == keccak256(encodedMsg)); } + function toX509Time(bytes memory x509Time) public returns (uint) { + uint16 yrs; uint8 mnths; + uint8 dys; uint8 hrs; + uint8 mins; uint8 secs; + uint8 offset; + + if (x509Time.length == 13) { + if (uint8(x509Time[0])-48 < 5) yrs += 2000; + else yrs += 1900; + } + else { + yrs += (uint8(x509Time[0])-48) * 1000 + (uint8(x509Time[1])-48) * 100; + offset = 2; + } + yrs += (uint8(x509Time[offset+0])-48)*10 + uint8(x509Time[offset+1])-48; + mnths = (uint8(x509Time[offset+2])-48)*10 + uint8(x509Time[offset+3])-48; + dys += (uint8(x509Time[offset+4])-48)*10 + uint8(x509Time[offset+5])-48; + hrs += (uint8(x509Time[offset+6])-48)*10 + uint8(x509Time[offset+7])-48; + mins += (uint8(x509Time[offset+8])-48)*10 + uint8(x509Time[offset+9])-48; + secs += (uint8(x509Time[offset+10])-48)*10 + uint8(x509Time[offset+11])-48; + + return toTimestamp(yrs, mnths, dys, hrs, mins, secs); + } + /* * @dev specs: https://www.ietf.org/rfc/rfc5280.txt * @dev Certificate ::= SEQUENCE { diff --git a/test/X509Viewer.sol b/test/X509Viewer.sol index d4f17dc..b3fca57 100644 --- a/test/X509Viewer.sol +++ b/test/X509Viewer.sol @@ -11,7 +11,7 @@ import { RAVE } from "rave/RAVE.sol"; import { BytesUtils } from "ens-contracts/dnssec-oracle/BytesUtils.sol"; import { Base64 } from "openzeppelin/utils/Base64.sol"; -contract TestViewX509 is Test { +contract TestViewX509 is Test, X509Verifier { using Asn1Decode for bytes; using BytesUtils for bytes; using Utils for bytes; @@ -49,6 +49,14 @@ contract TestViewX509 is Test { console.log("issuer..."); console.logBytes(cert.bytesAt(ptr)); ptr = cert.nextSiblingOf(ptr); // point to validity + console.logBytes(cert.bytesAt(ptr)); + + ptr = cert.firstChildOf(ptr); + + uint40 validNotBefore = uint40(toX509Time(cert.bytesAt(ptr))); + console.log(validNotBefore); + + return; // Traverse until the subjectPublicKeyInfo field ptr = cert.nextSiblingOf(ptr); // point to subject From 0b4eceeff24b98491b9524869f601414b5416084 Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Mon, 30 Oct 2023 23:43:56 +0000 Subject: [PATCH 34/35] Working on date time checks. --- src/DateTime.sol | 216 +++++++++++++++++++++++++++++++++++++++++++ src/X509Verifier.sol | 35 +++++-- 2 files changed, 245 insertions(+), 6 deletions(-) create mode 100644 src/DateTime.sol diff --git a/src/DateTime.sol b/src/DateTime.sol new file mode 100644 index 0000000..de1a724 --- /dev/null +++ b/src/DateTime.sol @@ -0,0 +1,216 @@ +pragma solidity >=0.8.0 <0.9.0; + +contract DateTime { + /* + * Date and Time utilities for ethereum contracts + * + */ + struct _DateTime { + uint16 year; + uint8 month; + uint8 day; + uint8 hour; + uint8 minute; + uint8 second; + uint8 weekday; + } + + uint constant DAY_IN_SECONDS = 86400; + uint constant YEAR_IN_SECONDS = 31536000; + uint constant LEAP_YEAR_IN_SECONDS = 31622400; + + uint constant HOUR_IN_SECONDS = 3600; + uint constant MINUTE_IN_SECONDS = 60; + + uint16 constant ORIGIN_YEAR = 1970; + + function isLeapYear(uint16 year) public pure returns (bool) { + if (year % 4 != 0) { + return false; + } + if (year % 100 != 0) { + return true; + } + if (year % 400 != 0) { + return false; + } + return true; + } + + function leapYearsBefore(uint year) public pure returns (uint) { + year -= 1; + return year / 4 - year / 100 + year / 400; + } + + function getDaysInMonth(uint8 month, uint16 year) public pure returns (uint8) { + if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) { + return 31; + } + else if (month == 4 || month == 6 || month == 9 || month == 11) { + return 30; + } + else if (isLeapYear(year)) { + return 29; + } + else { + return 28; + } + } + + function parseTimestamp(uint timestamp) internal pure returns (_DateTime memory dt) { + uint secondsAccountedFor = 0; + uint buf; + uint8 i; + + // Year + dt.year = getYear(timestamp); + buf = leapYearsBefore(dt.year) - leapYearsBefore(ORIGIN_YEAR); + + secondsAccountedFor += LEAP_YEAR_IN_SECONDS * buf; + secondsAccountedFor += YEAR_IN_SECONDS * (dt.year - ORIGIN_YEAR - buf); + + // Month + uint secondsInMonth; + for (i = 1; i <= 12; i++) { + secondsInMonth = DAY_IN_SECONDS * getDaysInMonth(i, dt.year); + if (secondsInMonth + secondsAccountedFor > timestamp) { + dt.month = i; + break; + } + secondsAccountedFor += secondsInMonth; + } + + // Day + for (i = 1; i <= getDaysInMonth(dt.month, dt.year); i++) { + if (DAY_IN_SECONDS + secondsAccountedFor > timestamp) { + dt.day = i; + break; + } + secondsAccountedFor += DAY_IN_SECONDS; + } + + // Hour + dt.hour = getHour(timestamp); + + // Minute + dt.minute = getMinute(timestamp); + + // Second + dt.second = getSecond(timestamp); + + // Day of week. + dt.weekday = getWeekday(timestamp); + } + + function getYear(uint timestamp) public pure returns (uint16) { + uint secondsAccountedFor = 0; + uint16 year; + uint numLeapYears; + + // Year + year = uint16(ORIGIN_YEAR + timestamp / YEAR_IN_SECONDS); + numLeapYears = leapYearsBefore(year) - leapYearsBefore(ORIGIN_YEAR); + + secondsAccountedFor += LEAP_YEAR_IN_SECONDS * numLeapYears; + secondsAccountedFor += YEAR_IN_SECONDS * (year - ORIGIN_YEAR - numLeapYears); + + while (secondsAccountedFor > timestamp) { + if (isLeapYear(uint16(year - 1))) { + secondsAccountedFor -= LEAP_YEAR_IN_SECONDS; + } + else { + secondsAccountedFor -= YEAR_IN_SECONDS; + } + year -= 1; + } + return year; + } + + function getMonth(uint timestamp) public pure returns (uint8) { + return parseTimestamp(timestamp).month; + } + + function getDay(uint timestamp) public pure returns (uint8) { + return parseTimestamp(timestamp).day; + } + + function getHour(uint timestamp) public pure returns (uint8) { + return uint8((timestamp / 60 / 60) % 24); + } + + function getMinute(uint timestamp) public pure returns (uint8) { + return uint8((timestamp / 60) % 60); + } + + function getSecond(uint timestamp) public pure returns (uint8) { + return uint8(timestamp % 60); + } + + function getWeekday(uint timestamp) public pure returns (uint8) { + return uint8((timestamp / DAY_IN_SECONDS + 4) % 7); + } + + function toTimestamp(uint16 year, uint8 month, uint8 day) public pure returns (uint timestamp) { + return toTimestamp(year, month, day, 0, 0, 0); + } + + function toTimestamp(uint16 year, uint8 month, uint8 day, uint8 hour) public pure returns (uint timestamp) { + return toTimestamp(year, month, day, hour, 0, 0); + } + + function toTimestamp(uint16 year, uint8 month, uint8 day, uint8 hour, uint8 minute) public pure returns (uint timestamp) { + return toTimestamp(year, month, day, hour, minute, 0); + } + + function toTimestamp(uint16 year, uint8 month, uint8 day, uint8 hour, uint8 minute, uint8 second) public pure returns (uint timestamp) { + uint16 i; + + // Year + for (i = ORIGIN_YEAR; i < year; i++) { + if (isLeapYear(i)) { + timestamp += LEAP_YEAR_IN_SECONDS; + } + else { + timestamp += YEAR_IN_SECONDS; + } + } + + // Month + uint8[12] memory monthDayCounts; + monthDayCounts[0] = 31; + if (isLeapYear(year)) { + monthDayCounts[1] = 29; + } + else { + monthDayCounts[1] = 28; + } + monthDayCounts[2] = 31; + monthDayCounts[3] = 30; + monthDayCounts[4] = 31; + monthDayCounts[5] = 30; + monthDayCounts[6] = 31; + monthDayCounts[7] = 31; + monthDayCounts[8] = 30; + monthDayCounts[9] = 31; + monthDayCounts[10] = 30; + monthDayCounts[11] = 31; + + for (i = 1; i < month; i++) { + timestamp += DAY_IN_SECONDS * monthDayCounts[i - 1]; + } + + // Day + timestamp += DAY_IN_SECONDS * (day - 1); + + // Hour + timestamp += HOUR_IN_SECONDS * (hour); + + // Minute + timestamp += MINUTE_IN_SECONDS * (minute); + + // Second + timestamp += second; + + return timestamp; + } +} diff --git a/src/X509Verifier.sol b/src/X509Verifier.sol index 65d6de4..b8ff969 100755 --- a/src/X509Verifier.sol +++ b/src/X509Verifier.sol @@ -7,7 +7,7 @@ import { BytesUtils } from "ens-contracts/dnssec-oracle/BytesUtils.sol"; import { SafeMath } from "openzeppelin-contracts/contracts/utils/math/SafeMath.sol"; import { Math } from "openzeppelin-contracts/contracts/utils/math/Math.sol"; import { Utils } from "./Utils.sol"; -import "ethereum-datetime/DateTime.sol"; +import "./DateTime.sol"; import { Test, console } from "forge-std/Test.sol"; contract X509Verifier is Test, DateTime { @@ -169,7 +169,7 @@ contract X509Verifier is Test, DateTime { return success && (keccak256(res) == keccak256(encodedMsg)); } - function toX509Time(bytes memory x509Time) public returns (uint) { + function toX509Time(bytes memory x509Time) public pure returns (uint) { uint16 yrs; uint8 mnths; uint8 dys; uint8 hrs; uint8 mins; uint8 secs; @@ -248,7 +248,7 @@ contract X509Verifier is Test, DateTime { uint256 tbsPtr = cert.firstChildOf(cert.root()); // Extracts the TBSCerificate (what is used as input to RSA-SHA256) - bytes memory certBody = cert.allBytesAt(tbsPtr); + //bytes memory certBody = cert.allBytesAt(tbsPtr); // Top level traverse to signatureAlgorithm uint256 sigAlgPtr = cert.nextSiblingOf(tbsPtr); @@ -267,7 +267,7 @@ contract X509Verifier is Test, DateTime { bytes memory signature = cert.bytesAt(sigPtr); // Verify the parent signed the certBody - require(verifyChildCert(certBody, signature, parentMod, parentExp), "verifyChildCert fail"); + require(verifyChildCert(cert.allBytesAt(tbsPtr), signature, parentMod, parentExp), "verifyChildCert fail"); //require(verifyRSA(certBody, signature, parentMod, parentExp), "verifyChildCert fail"); // ---------------- @@ -289,7 +289,6 @@ contract X509Verifier is Test, DateTime { ptr = cert.nextSiblingOf(ptr); // point to signature ptr = cert.nextSiblingOf(ptr); // point to issuer console.log("issuer..."); - console.logBytes(cert.bytesAt(ptr)); if(extended_checks) { require( _SGX_REPORT_SIGNING_SUBJECT.compare( @@ -300,6 +299,29 @@ contract X509Verifier is Test, DateTime { ptr = cert.nextSiblingOf(ptr); // point to validity + //ptr = cert.firstChildOf(ptr); + + // Arrive at the validity field + // todo verifiy validity timestamps + console.log("Valid before unix = "); + + console.logBytes(cert.bytesAt(ptr)); + console.logBytes(cert.bytesAt(cert.firstChildOf(ptr))); + + // Valid before. + ptr = cert.firstChildOf(ptr); + uint x = toX509Time(cert.bytesAt(ptr)); + console.log(x); + + // Valid after. + ptr = cert.nextSiblingOf(ptr); + x = toX509Time(cert.bytesAt(ptr)); + console.log(x); + + //ptr = cert.firstChildOf(ptr); + //x = toX509Time(cert.bytesAt(cert.firstChildOf(ptr))); + //console.log(x); + // Arrive at the validity field // todo verifiy validity timestamps @@ -313,8 +335,9 @@ contract X509Verifier is Test, DateTime { // console.logBytes(validNotAfter); // uint40 validNotAfter = uint40(toTimestamp(cert.bytesAt(validityPtr))); // console.log("validNotAfter: %s", validNotAfter); - // Traverse until the subjectPublicKeyInfo field + + ptr = cert.nextSiblingOf(ptr); // point to subject console.log("subject"); console.logBytes(cert.bytesAt(ptr)); From fa5f71251ec48ea96d4d76ebeccfd20d20976099 Mon Sep 17 00:00:00 2001 From: Matthew Roberts Date: Tue, 31 Oct 2023 00:39:38 +0000 Subject: [PATCH 35/35] Saving. --- src/X509Verifier.sol | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/X509Verifier.sol b/src/X509Verifier.sol index b8ff969..02b2089 100755 --- a/src/X509Verifier.sol +++ b/src/X509Verifier.sol @@ -318,25 +318,8 @@ contract X509Verifier is Test, DateTime { x = toX509Time(cert.bytesAt(ptr)); console.log(x); - //ptr = cert.firstChildOf(ptr); - //x = toX509Time(cert.bytesAt(cert.firstChildOf(ptr))); - //console.log(x); - // Arrive at the validity field - // todo verifiy validity timestamps - // uint256 validityPtr = ptr; - // bytes memory validNotBefore = cert.bytesAt(validityPtr); - // console.logBytes(validNotBefore); - // uint40 validNotBefore = uint40(toTimestamp(cert.bytesAt(validityPtr))); - // console.log("validNotBefore: %s", validNotBefore); - // validityPtr = cert.nextSiblingOf(validityPtr); - // bytes memory validNotAfter = cert.bytesAt(validityPtr); - // console.logBytes(validNotAfter); - // uint40 validNotAfter = uint40(toTimestamp(cert.bytesAt(validityPtr))); - // console.log("validNotAfter: %s", validNotAfter); - // Traverse until the subjectPublicKeyInfo field - ptr = cert.nextSiblingOf(ptr); // point to subject console.log("subject");