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_attest_and_seal(name): 126 content = "" 127 attest_cdi_data = _read_file("_attest_cdi_%s.bin" % name) 128 content += _generate_array( 129 "kExpectedCdiAttest_%s" % _to_camel_case(name), attest_cdi_data 130 ) 131 seal_cdi_data = _read_file("_seal_cdi_%s.bin" % name) 132 content += _generate_array( 133 "kExpectedCdiSeal_%s" % _to_camel_case(name), seal_cdi_data 134 ) 135 return content 136 137 138def _generate_cert(name, cert_type, key_type): 139 content = "" 140 var_name = "kExpected%s%sCert_%s" % ( 141 _to_camel_case(cert_type), 142 _to_camel_case(key_type), 143 _to_camel_case(name), 144 ) 145 cert_data = _read_file("_%s_%s_cert_%s.cert" % (cert_type, key_type, name)) 146 if cert_type == "X509" and key_type != "P384": 147 content += ( 148 "// $ openssl x509 -inform DER -noout -text -certopt " "ext_parse\n" 149 ) 150 content += _generate_cert_comment(cert_data) 151 content += _generate_array(var_name, cert_data) 152 return content 153 154 155def _generate_certs(name, cert_type): 156 """Generates C declarations from dumps identified by |name|.""" 157 return "".join( 158 _generate_cert(name, cert_type, key_type) 159 for key_type in ("Ed25519", "P256", "P384") 160 ) 161 162 163def main(argv): 164 if len(argv) > 1: 165 raise app.UsageError("Too many command-line arguments.") 166 167 content = _FILE_HEADER 168 for name in ("zero_input", "hash_only_input", "descriptor_input"): 169 content += _generate_attest_and_seal(name) 170 content += _generate_certs(name, "X509") 171 content += _generate_certs(name, "CBOR") 172 content += _generate_certs("android_" + name, "CBOR") 173 content += _FILE_FOOTER 174 subprocess.run( 175 ["clang-format", "--style=file"], input=content.encode(), check=True 176 ) 177 178 179if __name__ == "__main__": 180 app.run(main) 181