1# Copyright 2020 Google LLC 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); you may not 4# use this file except in compliance with the License. You may obtain a copy of 5# the License at 6# 7# https://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12# License for the specific language governing permissions and limitations under 13# the License. 14# 15# Lint as: python3 16"""Generates known_test_values.h from dumped test values. 17 18This program generates the known_test_values.h file used for unit tests. This is 19useful to correct the baseline test values based on dumps from the tests. Use 20this after fixing a bug in the code, not to 'fix' test breakage not well 21understood. 22 23Usage: 24 $ cd out 25 $ python ../generate_test_values.py > ../include/dice/known_test_values.h 26 27Prerequisites: 28 pip install absl-py 29""" 30 31from __future__ import print_function 32 33import re 34import subprocess 35import textwrap 36 37from absl import app 38from absl import flags 39 40FLAGS = flags.FLAGS 41 42_FILE_HEADER = textwrap.dedent( 43 """\ 44 // Copyright 2020 Google LLC 45 // 46 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 47 // use this file except in compliance with the License. You may obtain a copy of 48 // the License at 49 // 50 // https://www.apache.org/licenses/LICENSE-2.0 51 // 52 // Unless required by applicable law or agreed to in writing, software 53 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 54 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 55 // License for the specific language governing permissions and limitations under 56 // the License. 57 58 // !!! GENERATED - DO NOT MODIFY !!! 59 // To update this file, use generate_test_values.py. 60 61 #ifndef DICE_KNOWN_TEST_VALUES_H_ 62 #define DICE_KNOWN_TEST_VALUES_H_ 63 64 #include <stdint.h> 65 66 namespace dice { 67 namespace test { 68 69 """ 70) 71 72_FILE_FOOTER = textwrap.dedent( 73 """\ 74 } // namespace test 75 } // namespace dice 76 77 #endif // DICE_KNOWN_TEST_VALUES_H_ 78 """ 79) 80 81 82def _to_camel_case(s): 83 return "".join(tmp.capitalize() for tmp in s.split("_")) 84 85 86def _read_file(name): 87 try: 88 with open(name, "rb") as f: 89 return f.read() 90 except OSError: 91 return "" 92 93 94def _generate_array(name, data): 95 return "constexpr uint8_t %s[%d] = {%s};\n\n" % ( 96 name, 97 len(data), 98 ", ".join("0x%02x" % tmp for tmp in data), 99 ) 100 101 102def _generate_cert_comment(data): 103 return re.sub( 104 "^", 105 "// ", 106 subprocess.run( 107 [ 108 "openssl", 109 "x509", 110 "-inform", 111 "DER", 112 "-noout", 113 "-text", 114 "-certopt", 115 "ext_parse", 116 ], 117 input=data, 118 capture_output=True, 119 check=True, 120 ).stdout.decode(), 121 flags=re.MULTILINE, 122 )[:-3] 123 124 125def _generate_c(name): 126 """Generates C declarations from dumps identified by |name|.""" 127 content = "" 128 attest_cdi_data = _read_file("_attest_cdi_%s.bin" % name) 129 content += _generate_array( 130 "kExpectedCdiAttest_%s" % _to_camel_case(name), attest_cdi_data 131 ) 132 seal_cdi_data = _read_file("_seal_cdi_%s.bin" % name) 133 content += _generate_array( 134 "kExpectedCdiSeal_%s" % _to_camel_case(name), seal_cdi_data 135 ) 136 for cert_type in ("X509", "CBOR"): 137 for key_type in ("Ed25519", "P256", "P384"): 138 var_name = "kExpected%s%sCert_%s" % ( 139 _to_camel_case(cert_type), 140 _to_camel_case(key_type), 141 _to_camel_case(name), 142 ) 143 cert_data = _read_file( 144 "_%s_%s_cert_%s.cert" % (cert_type, key_type, name) 145 ) 146 if cert_type == "X509" and key_type != "P384": 147 content += ( 148 "// $ openssl x509 -inform DER -noout -text -certopt " 149 "ext_parse\n" 150 ) 151 content += _generate_cert_comment(cert_data) 152 content += _generate_array(var_name, cert_data) 153 return content 154 155 156def main(argv): 157 if len(argv) > 1: 158 raise app.UsageError("Too many command-line arguments.") 159 160 content = _FILE_HEADER 161 content += _generate_c("zero_input") 162 content += _generate_c("hash_only_input") 163 content += _generate_c("descriptor_input") 164 content += _FILE_FOOTER 165 subprocess.run( 166 ["clang-format", "--style=file"], input=content.encode(), check=True 167 ) 168 169 170if __name__ == "__main__": 171 app.run(main) 172