# Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); you may not # use this file except in compliance with the License. You may obtain a copy of # the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations under # the License. # # Lint as: python3 """Generates known_test_values.h from dumped test values. This program generates the known_test_values.h file used for unit tests. This is useful to correct the baseline test values based on dumps from the tests. Use this after fixing a bug in the code, not to 'fix' test breakage not well understood. Usage: $ cd out $ python ../generate_test_values.py > ../include/dice/known_test_values.h Prerequisites: pip install absl-py """ from __future__ import print_function import re import subprocess import textwrap from absl import app from absl import flags FLAGS = flags.FLAGS _FILE_HEADER = textwrap.dedent( """\ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy of // the License at // // https://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the // License for the specific language governing permissions and limitations under // the License. // !!! GENERATED - DO NOT MODIFY !!! // To update this file, use generate_test_values.py. #ifndef DICE_KNOWN_TEST_VALUES_H_ #define DICE_KNOWN_TEST_VALUES_H_ #include namespace dice { namespace test { """ ) _FILE_FOOTER = textwrap.dedent( """\ } // namespace test } // namespace dice #endif // DICE_KNOWN_TEST_VALUES_H_ """ ) def _to_camel_case(s): return "".join(tmp.capitalize() for tmp in s.split("_")) def _read_file(name): try: with open(name, "rb") as f: return f.read() except OSError: return "" def _generate_array(name, data): return "constexpr uint8_t %s[%d] = {%s};\n\n" % ( name, len(data), ", ".join("0x%02x" % tmp for tmp in data), ) def _generate_cert_comment(data): return re.sub( "^", "// ", subprocess.run( [ "openssl", "x509", "-inform", "DER", "-noout", "-text", "-certopt", "ext_parse", ], input=data, capture_output=True, check=True, ).stdout.decode(), flags=re.MULTILINE, )[:-3] def _generate_c(name): """Generates C declarations from dumps identified by |name|.""" content = "" attest_cdi_data = _read_file("_attest_cdi_%s.bin" % name) content += _generate_array( "kExpectedCdiAttest_%s" % _to_camel_case(name), attest_cdi_data ) seal_cdi_data = _read_file("_seal_cdi_%s.bin" % name) content += _generate_array( "kExpectedCdiSeal_%s" % _to_camel_case(name), seal_cdi_data ) for cert_type in ("X509", "CBOR"): for key_type in ("Ed25519", "P256", "P384"): var_name = "kExpected%s%sCert_%s" % ( _to_camel_case(cert_type), _to_camel_case(key_type), _to_camel_case(name), ) cert_data = _read_file( "_%s_%s_cert_%s.cert" % (cert_type, key_type, name) ) if cert_type == "X509" and key_type != "P384": content += ( "// $ openssl x509 -inform DER -noout -text -certopt " "ext_parse\n" ) content += _generate_cert_comment(cert_data) content += _generate_array(var_name, cert_data) return content def main(argv): if len(argv) > 1: raise app.UsageError("Too many command-line arguments.") content = _FILE_HEADER content += _generate_c("zero_input") content += _generate_c("hash_only_input") content += _generate_c("descriptor_input") content += _FILE_FOOTER subprocess.run( ["clang-format", "--style=file"], input=content.encode(), check=True ) if __name__ == "__main__": app.run(main)