• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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    // 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)
149