|
16 | 16 | import platform |
17 | 17 | import update_upstream_alg_docs |
18 | 18 | import copy_from_slh_dsa_c |
| 19 | +from copy import deepcopy |
19 | 20 |
|
20 | 21 | # kats of all algs |
21 | 22 | kats = {} |
@@ -97,6 +98,46 @@ def generator_all(filename, instructions): |
97 | 98 | contents = jinja2.Template(template).render({'instructions': instructions}) |
98 | 99 | file_put_contents(filename, contents) |
99 | 100 |
|
| 101 | +# TODO: consider refactoring replacer by calling replace_one_fragment |
| 102 | +def replace_one_fragment( |
| 103 | + dst_path: str, |
| 104 | + template_path: str, |
| 105 | + instructions: dict, |
| 106 | + delimiter: str, |
| 107 | + libjade: bool = False, |
| 108 | +): |
| 109 | + """Replace a single fragment with a rendered Jinja template |
| 110 | +
|
| 111 | + :param dst_path: path to the rendered file, relative to LIBOQS_DIR |
| 112 | + :param template_path: path to the Jinja template file, relative to LIBOQS_DIR |
| 113 | + :param instructions: copy_from_upstream.yml or some patched version |
| 114 | + :param delimiter: how the identifer for the fragment in the destination file |
| 115 | + is prefixed |
| 116 | + """ |
| 117 | + liboqs_dir = os.environ.get("LIBOQS_DIR", None) |
| 118 | + if not liboqs_dir: |
| 119 | + raise KeyError("Environment variable LIBOQS_DIR is missing") |
| 120 | + dst_path = os.path.join(liboqs_dir, dst_path) |
| 121 | + template_path = os.path.join(liboqs_dir, template_path) |
| 122 | + with open(template_path, "r") as template_f, open(dst_path, "r") as dst_f: |
| 123 | + template = template_f.read() |
| 124 | + dst_content = dst_f.read() |
| 125 | + identifier, _ = os.path.splitext(os.path.basename(template_path)) |
| 126 | + jade_or_upstream = "LIBJADE" if libjade else "UPSTREAM" |
| 127 | + identifier_start = f"{delimiter} OQS_COPY_FROM_{jade_or_upstream}_FRAGMENT_{identifier.upper()}_START" |
| 128 | + identifier_end = f"{delimiter} OQS_COPY_FROM_{jade_or_upstream}_FRAGMENT_{identifier.upper()}_END" |
| 129 | + preamble = dst_content[: dst_content.find(identifier_start)] |
| 130 | + postamble = dst_content[dst_content.find(identifier_end) :] |
| 131 | + dst_content = ( |
| 132 | + preamble |
| 133 | + + identifier_start |
| 134 | + + jinja2.Template(template).render( |
| 135 | + {"instructions": instructions, "non_upstream_kems": non_upstream_kems} |
| 136 | + ) |
| 137 | + + postamble |
| 138 | + ) |
| 139 | + with open(dst_path, "w") as f: |
| 140 | + f.write(dst_content) |
100 | 141 |
|
101 | 142 | def replacer(filename, instructions, delimiter, libjade=False): |
102 | 143 | fragments = glob.glob( |
@@ -701,14 +742,29 @@ def process_families(instructions, basedir, with_kat, with_generator, with_libja |
701 | 742 | ) |
702 | 743 |
|
703 | 744 |
|
704 | | -def copy_from_upstream(): |
| 745 | +def copy_from_upstream(slh_dsa_inst: dict): |
| 746 | + """Integrate upstreams implementations and algorithms described in |
| 747 | + copy_from_upstream.yml. |
| 748 | +
|
| 749 | + :param slh_dsa_inst: instruction for integrating SLH-DSA, only used for |
| 750 | + rendering alg_support.cmake |
| 751 | + """ |
705 | 752 | for t in ["kem", "sig"]: |
706 | 753 | with open(os.path.join(os.environ['LIBOQS_DIR'], 'tests', 'KATs', t, 'kats.json'), 'r') as fp: |
707 | 754 | kats[t] = json.load(fp) |
708 | 755 |
|
709 | 756 | instructions = load_instructions('copy_from_upstream.yml') |
| 757 | + patched_inst: dict = deepcopy(instructions) |
| 758 | + patched_inst["sigs"].append(slh_dsa_inst["sigs"][0]) |
710 | 759 | process_families(instructions, os.environ['LIBOQS_DIR'], True, True) |
711 | 760 | replacer('.CMake/alg_support.cmake', instructions, '#####') |
| 761 | + # NOTE: issue 2203, only for replacing list of standardized algs |
| 762 | + replace_one_fragment( |
| 763 | + ".CMake/alg_support.cmake", |
| 764 | + "scripts/copy_from_upstream/.CMake/alg_support.cmake/list_standardized_algs.fragment", |
| 765 | + patched_inst, |
| 766 | + "#####" |
| 767 | + ) |
712 | 768 | replacer('CMakeLists.txt', instructions, '#####') |
713 | 769 | replacer('src/oqsconfig.h.cmake', instructions, '/////') |
714 | 770 | replacer('src/CMakeLists.txt', instructions, '#####') |
@@ -839,9 +895,20 @@ def verify_from_upstream(): |
839 | 895 |
|
840 | 896 | if args.operation == "copy": |
841 | 897 | # copy_from_slh_dsa_c will modify slh_dsa.yml before copy_from_upstream modifies md files |
842 | | - copy_from_slh_dsa_c.main() |
| 898 | + slh_dsa_schemes: list[str] = copy_from_slh_dsa_c.main() |
| 899 | + slh_dsa_instruction = { |
| 900 | + "sigs": [ |
| 901 | + { |
| 902 | + "name": "slh_dsa", |
| 903 | + "schemes": [ |
| 904 | + {"scheme": scheme} for scheme in slh_dsa_schemes |
| 905 | + if "pure" in scheme |
| 906 | + ] |
| 907 | + } |
| 908 | + ] |
| 909 | + } |
843 | 910 | os.chdir(os.path.join(os.environ['LIBOQS_DIR'],"scripts","copy_from_upstream")) |
844 | | - copy_from_upstream() |
| 911 | + copy_from_upstream(slh_dsa_instruction) |
845 | 912 | elif args.operation == "libjade": |
846 | 913 | copy_from_libjade() |
847 | 914 | elif args.operation == "verify": |
|
0 commit comments