| 1 | #!/usr/bin/env v |
| 2 | |
| 3 | import os |
| 4 | |
| 5 | // generates ML-DSA test vectors by building Go's reference implementation |
| 6 | // and running gen.go with crypto/internal/fips140/mldsa |
| 7 | // |
| 8 | // Usage: |
| 9 | // v run testdata/gen.vsh |
| 10 | // v run testdata/gen.vsh <go-source-path> # uses existing Go tree |
| 11 | |
| 12 | const go_repo = 'https://github.com/golang/go.git' |
| 13 | const go_ref = 'master' |
| 14 | const go_mldsa_subpath = os.join_path('src', 'crypto', 'internal', 'fips140', 'mldsa') |
| 15 | const go_gen_pkg = os.join_path('.', go_mldsa_subpath, 'gen') |
| 16 | |
| 17 | fn main() { |
| 18 | unbuffer_stdout() |
| 19 | script_dir := os.dir(@FILE) |
| 20 | |
| 21 | mut go_root := os.join_path(os.temp_dir(), 'go') |
| 22 | if os.args.len > 1 { |
| 23 | go_root = os.args[1] |
| 24 | if !os.exists(os.join_path(go_root, go_mldsa_subpath)) { |
| 25 | eprintln('error: ${go_root} does not look like a Go source tree') |
| 26 | exit(1) |
| 27 | } |
| 28 | println('> Using existing Go tree at ${go_root}') |
| 29 | } else { |
| 30 | if os.exists(os.join_path(go_root, 'src')) { |
| 31 | println('> Reusing cached Go tree at ${go_root}') |
| 32 | run_or_exit('git -C ${go_root} pull --quiet') |
| 33 | } else { |
| 34 | println('> Cloning Go source tree to ${go_root}...') |
| 35 | run_or_exit('git clone --depth 1 --branch ${go_ref} ${go_repo} ${go_root}') |
| 36 | } |
| 37 | } |
| 38 | |
| 39 | go_bin := os.join_path(go_root, 'bin', 'go') |
| 40 | if !os.exists(go_bin) { |
| 41 | println('> Building Go toolchain...') |
| 42 | run_or_exit('cd ${go_root}/src && bash make.bash') |
| 43 | } |
| 44 | println('> Go binary: ${go_bin}') |
| 45 | |
| 46 | gen_dst_dir := os.join_path(go_root, go_mldsa_subpath, 'gen') |
| 47 | os.mkdir_all(gen_dst_dir) or { |
| 48 | eprintln('error: mkdir failed: ${err}') |
| 49 | exit(1) |
| 50 | } |
| 51 | os.cp(os.join_path(script_dir, 'gen.go'), os.join_path(gen_dst_dir, 'main.go')) or { |
| 52 | eprintln('error: copy failed: ${err}') |
| 53 | exit(1) |
| 54 | } |
| 55 | |
| 56 | println('> Generating test vectors...') |
| 57 | res := run_or_exit('cd ${go_root} && GOROOT=${go_root} ${go_bin} run ${go_gen_pkg}') |
| 58 | |
| 59 | os.rmdir_all(gen_dst_dir) or { eprintln('warning: rmdir failed: ${err}') } |
| 60 | |
| 61 | vectors_path := os.join_path(script_dir, 'vectors.json') |
| 62 | os.write_file(vectors_path, res) or { |
| 63 | eprintln('error: write failed: ${err}') |
| 64 | exit(1) |
| 65 | } |
| 66 | println('> Wrote ${vectors_path}') |
| 67 | } |
| 68 | |
| 69 | fn run_or_exit(cmd string) string { |
| 70 | res := os.execute_opt(cmd) or { |
| 71 | eprintln('error: ${err}') |
| 72 | exit(1) |
| 73 | } |
| 74 | if res.exit_code != 0 { |
| 75 | eprintln('error: ${cmd}\n${res.output}') |
| 76 | exit(1) |
| 77 | } |
| 78 | return res.output |
| 79 | } |
| 80 | |