# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
#
# Lint as: python3
"""Generates known_test_values.h from dumped test values.

This program generates the known_test_values.h file used for unit tests. This is
useful to correct the baseline test values based on dumps from the tests. Use
this after fixing a bug in the code, not to 'fix' test breakage not well
understood.

Usage:
  $ cd out
  $ python ../generate_test_values.py > ../include/dice/known_test_values.h

Prerequisites:
  pip install absl-py
"""

from __future__ import print_function

import re
import subprocess
import textwrap

from absl import app
from absl import flags

FLAGS = flags.FLAGS

_FILE_HEADER = textwrap.dedent("""\
    // Copyright 2020 Google LLC
    //
    // Licensed under the Apache License, Version 2.0 (the "License"); you may not
    // use this file except in compliance with the License. You may obtain a copy of
    // the License at
    //
    //     https://www.apache.org/licenses/LICENSE-2.0
    //
    // Unless required by applicable law or agreed to in writing, software
    // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    // License for the specific language governing permissions and limitations under
    // the License.

    // !!! GENERATED - DO NOT MODIFY !!!
    // To update this file, use generate_test_values.py.

    #ifndef DICE_KNOWN_TEST_VALUES_H_
    #define DICE_KNOWN_TEST_VALUES_H_

    #include <stdint.h>

    namespace dice {
    namespace test {

                               """)

_FILE_FOOTER = textwrap.dedent("""\
    }  // namespace test
    }  // namespace dice

    #endif  // DICE_KNOWN_TEST_VALUES_H_
                               """)


def _to_camel_case(s):
    return ''.join(tmp.capitalize() for tmp in s.split('_'))


def _read_file(name):
    try:
        with open(name, 'rb') as f:
            return f.read()
    except OSError:
        return ''


def _generate_array(name, data):
    return 'constexpr uint8_t %s[%d] = {%s};\n\n' % (
        name, len(data), ', '.join('0x%02x' % tmp for tmp in data))


def _generate_cert_comment(data):
    return re.sub('^',
                  '// ',
                  subprocess.run([
                      'openssl', 'x509', '-inform', 'DER', '-noout', '-text',
                      '-certopt', 'ext_parse'
                  ],
                                 input=data,
                                 capture_output=True,
                                 check=True).stdout.decode(),
                  flags=re.MULTILINE)[:-3]


def _generate_c(name):
    """Generates C declarations from dumps identified by |name|."""
    content = ''
    attest_cdi_data = _read_file('_attest_cdi_%s.bin' % name)
    content += _generate_array('kExpectedCdiAttest_%s' % _to_camel_case(name),
                               attest_cdi_data)
    seal_cdi_data = _read_file('_seal_cdi_%s.bin' % name)
    content += _generate_array('kExpectedCdiSeal_%s' % _to_camel_case(name),
                               seal_cdi_data)
    for cert_type in ('X509', 'CBOR'):
        for key_type in ('Ed25519', 'P256'):
            var_name = 'kExpected%s%sCert_%s' % (_to_camel_case(cert_type),
                                                 _to_camel_case(key_type),
                                                 _to_camel_case(name))
            cert_data = _read_file('_%s_%s_cert_%s.cert' %
                                   (cert_type, key_type, name))
            if cert_type == 'X509':
                content += (
                    '// $ openssl x509 -inform DER -noout -text -certopt '
                    'ext_parse\n')
                content += _generate_cert_comment(cert_data)
            content += _generate_array(var_name, cert_data)
    return content


def main(argv):
    if len(argv) > 1:
        raise app.UsageError('Too many command-line arguments.')

    content = _FILE_HEADER
    content += _generate_c('zero_input')
    content += _generate_c('hash_only_input')
    content += _generate_c('descriptor_input')
    content += _FILE_FOOTER
    subprocess.run(['clang-format', '--style=file'],
                   input=content.encode(),
                   check=True)


if __name__ == '__main__':
    app.run(main)
