• 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    """\
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