blob: 953ef826782e786f2d0a9a4fbed568deb2772d07 [file] [log] [blame]
Darren Krahn0762a2e2021-02-05 15:41:20 -08001# 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 // Copyright 2020 Google LLC
44 //
45 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
46 // use this file except in compliance with the License. You may obtain a copy of
47 // the License at
48 //
49 // https://www.apache.org/licenses/LICENSE-2.0
50 //
51 // Unless required by applicable law or agreed to in writing, software
52 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
53 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
54 // License for the specific language governing permissions and limitations under
55 // the License.
56
57 // !!! GENERATED - DO NOT MODIFY !!!
58 // To update this file, use generate_test_values.py.
59
60 #ifndef DICE_KNOWN_TEST_VALUES_H_
61 #define DICE_KNOWN_TEST_VALUES_H_
62
63 #include <stdint.h>
64
65 namespace dice {
66 namespace test {
67
68 """)
69
70_FILE_FOOTER = textwrap.dedent("""\
71 } // namespace test
72 } // namespace dice
73
74 #endif // DICE_KNOWN_TEST_VALUES_H_
75 """)
76
77
78def _to_camel_case(s):
79 return ''.join(tmp.capitalize() for tmp in s.split('_'))
80
81
82def _read_file(name):
83 try:
84 with open(name, 'rb') as f:
85 return f.read()
86 except OSError:
87 return ''
88
89
90def _generate_array(name, data):
91 return 'constexpr uint8_t %s[%d] = {%s};\n\n' % (
92 name, len(data), ', '.join('0x%02x' % tmp for tmp in data))
93
94
95def _generate_cert_comment(data):
96 return re.sub('^',
97 '// ',
98 subprocess.run([
99 'openssl', 'x509', '-inform', 'DER', '-noout', '-text',
100 '-certopt', 'ext_parse'
101 ],
102 input=data,
103 capture_output=True,
104 check=True).stdout.decode(),
105 flags=re.MULTILINE)[:-3]
106
107
108def _generate_c(name):
109 """Generates C declarations from dumps identified by |name|."""
110 content = ''
111 attest_cdi_data = _read_file('_attest_cdi_%s.bin' % name)
112 content += _generate_array('kExpectedCdiAttest_%s' % _to_camel_case(name),
113 attest_cdi_data)
114 seal_cdi_data = _read_file('_seal_cdi_%s.bin' % name)
115 content += _generate_array('kExpectedCdiSeal_%s' % _to_camel_case(name),
116 seal_cdi_data)
117 for cert_type in ('X509', 'CBOR'):
118 for key_type in ('Ed25519', 'P256'):
119 var_name = 'kExpected%s%sCert_%s' % (_to_camel_case(cert_type),
120 _to_camel_case(key_type),
121 _to_camel_case(name))
122 cert_data = _read_file('_%s_%s_cert_%s.cert' %
123 (cert_type, key_type, name))
124 if cert_type == 'X509':
125 content += (
126 '// $ openssl x509 -inform DER -noout -text -certopt '
127 'ext_parse\n')
128 content += _generate_cert_comment(cert_data)
129 content += _generate_array(var_name, cert_data)
130 return content
131
132
133def main(argv):
134 if len(argv) > 1:
135 raise app.UsageError('Too many command-line arguments.')
136
137 content = _FILE_HEADER
138 content += _generate_c('zero_input')
139 content += _generate_c('hash_only_input')
140 content += _generate_c('descriptor_input')
141 content += _FILE_FOOTER
142 subprocess.run(['clang-format', '--style=file'],
143 input=content.encode(),
144 check=True)
145
146
147if __name__ == '__main__':
148 app.run(main)