From 29172747c117b6fd1f74cf5b833a782d2ebd730c Mon Sep 17 00:00:00 2001 From: Enrico Pozzobon Date: Tue, 9 Jul 2019 01:53:46 +0200 Subject: [PATCH] test vectors tested --- compile_all.py | 46 +++++++++++++++++++++++++++++++++++----------- templates/linux/main.c | 18 ++++++++++-------- test.py | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------ 3 files changed, 117 insertions(+), 31 deletions(-) diff --git a/compile_all.py b/compile_all.py index 429ae54..a9ca585 100755 --- a/compile_all.py +++ b/compile_all.py @@ -2,24 +2,30 @@ import os import sys +import stat import shutil import random import subprocess + def build(algo_dir, template_dir="templates/linux"): + # create a new directory for the build build_dir = None while build_dir is None: r = "%09d" % random.randint(0, 999999999) d = os.path.join("build", r) if not os.path.isdir(d): build_dir = d - + + # copy all the files from the submitted algorithm into the build directory shutil.copytree(algo_dir, build_dir) + # remove the test vectors generator if it is there c = os.path.join(build_dir, "genkat_aead.c") if os.path.exists(c): os.remove(c) + # find all c and h files, since they will be added to the makefile hfiles = [] cfiles = [] for r, d, f in os.walk(build_dir): @@ -29,6 +35,7 @@ def build(algo_dir, template_dir="templates/linux"): elif file.endswith(".h"): hfiles.append(file) + # copy all the files from the template directory into the build directory for f in os.listdir(template_dir): dst = os.path.join(build_dir, f) src = os.path.join(template_dir, f) @@ -39,19 +46,20 @@ def build(algo_dir, template_dir="templates/linux"): else: raise Exception("I don't know what %s is" % src) + # prepare the environmental variables for the makefile env = os.environ env['SRC_FILES'] = ' '.join(cfiles) env['HDR_FILES'] = ' '.join(hfiles) + # enter the directory and execute the makefile wd = os.getcwd() + os.chdir(build_dir) try: - os.chdir(build_dir) if os.path.isfile('./configure'): p = subprocess.Popen(["./configure"]) p.wait() assert p.returncode == 0 - pargs = ['make'] p = subprocess.Popen(['make']) p.wait() assert p.returncode == 0 @@ -59,11 +67,14 @@ def build(algo_dir, template_dir="templates/linux"): finally: os.chdir(wd) + # if execution arrives here, the build was successful return build_dir + +# Find test vectors in directory or one of the parent directories def find_test_vectors(d): kat = None - while kat is None: + while True: if d == '': raise Exception("Test vector not found") for f in os.listdir(d): @@ -71,10 +82,14 @@ def find_test_vectors(d): if kat is not None: raise Exception("Multiple test vectors?") kat = f - d = os.path.split(d)[0] + if kat is None: + d = os.path.split(d)[0] + else: + break kat = os.path.join(d, kat) return kat + def main(argv): submissions_dir = "all-lwc-submission-files" template_dir = "templates/linux" @@ -83,7 +98,7 @@ def main(argv): print("Using template %s" % template_dir) subs = os.listdir(submissions_dir) - # get all the submissions by looking for files named "encrypt.c" + # get all the submissions by looking for files named "api.h" files = [] for submission in subs: implementations_dir = os.path.join(submissions_dir, submission, "Implementations", "crypto_aead") @@ -108,7 +123,7 @@ def main(argv): print(d) t = find_test_vectors(d) print(t) - files.append(d) + files.append((t, d)) c += 1 if c == 0: @@ -119,15 +134,24 @@ def main(argv): # For testing, we only do the first files = files[:1] + # Clear the build directory as it is a leftover from the previous execution if os.path.isdir('build'): shutil.rmtree('build') + os.mkdir('build') print() - for d in files: - print() - print(d) - b = build(d) + # Write a script that executes all the tests one after the other + test_script_path = os.path.join("build", "test_all.sh") + with open(test_script_path, 'w') as test_script: + test_script.write("#!/bin/sh\n") + for t, d in files: + print() + print(d) + b = build(d) + test_script.write("./test.py %s %s\n" % (t, os.path.join(b, 'test'))) + st = os.stat(test_script_path) + os.chmod(test_script_path, st.st_mode | stat.S_IEXEC) if __name__ == "__main__": diff --git a/templates/linux/main.c b/templates/linux/main.c index 53d612a..eb483b1 100644 --- a/templates/linux/main.c +++ b/templates/linux/main.c @@ -71,6 +71,11 @@ static void write_variable(unsigned char *target, unsigned long long len) { fprintf(stderr, "ERROR: didn't write length\r\n"); exit(1); } + + if (len == 0) { + return; + } + if (1 != fwrite(target, olen, 1, stdout)) { fprintf(stderr, "ERROR: didn't write %llu bytes of data\r\n", len); exit(1); @@ -78,11 +83,6 @@ static void write_variable(unsigned char *target, unsigned long long len) { } -static bool is_ready() { - return !(k == NULL || m == NULL || c == NULL || ad == NULL); -} - - int main() { int res; int8_t action; @@ -111,7 +111,8 @@ int main() { case 'e': - if (!is_ready()) { + if (k == NULL || c == NULL) { + fprintf(stderr, c == NULL ? "Missing ciphertext buffer\r\n" : "Missing key\r\n"); return 3; } fprintf(stderr, "mlen = %llu\r\n", mlen); @@ -132,10 +133,11 @@ int main() { break; case 'd': - if (!is_ready()) { + if (m == NULL || k == NULL) { + fprintf(stderr, m == NULL ? "Missing message buffer\r\n" : "Missing key\r\n"); return 3; } - fprintf(stderr, "Starting decryption\r\n"); + fprintf(stderr, "starting decryption\r\n"); res = crypto_aead_decrypt(m, &mlen, nsec, c, clen, ad, adlen, npub, k); fprintf(stderr, "decryption finished %d\r\n", res); diff --git a/test.py b/test.py index 8e224ef..86e45b1 100755 --- a/test.py +++ b/test.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 +import re import os import sys import struct @@ -9,7 +10,11 @@ from subprocess import Popen, PIPE def main(argv): - p = Popen(argv[1:], bufsize=0, stdin=PIPE, stdout=PIPE) + if len(argv) < 3: + print("Usage: test.py LWC_AEAD_KAT.txt program [arguments]") + + test_file = open(argv[1], 'r') + p = Popen(argv[2:], bufsize=0, stdin=PIPE, stdout=PIPE) def write(data): l = p.stdin.write(data) @@ -35,17 +40,72 @@ def main(argv): if read(14) != b"Hello, World!\n": raise Exception("Unexpected output") - submit('c', b"\0" * 32) - submit('m', bytes.fromhex("000102030405060708090A0B0C0D0E0F")) - submit('a', bytes.fromhex("000102030405060708090A0B0C0D0E0F")) - submit('k', bytes.fromhex("000102030405060708090A0B0C0D0E0F")) - submit('p', bytes.fromhex("000102030405060708090A0B0C0D0E0F")) - submit('s', b"") - write(b'e') - write(b'C') - data = obtain() - print(data.hex()) - + m = b"" + ad = b"" + k = b"" + npub = b"" + i = 0 + lineprog = re.compile(r"^\s*([A-Z]+)\s*=\s*(([0-9a-f])*)\s*$", re.IGNORECASE) + for line in test_file.readlines(): + line = line.strip() + res = lineprog.match(line) + if line == "": + print() + print("Count = %d" % i) + print(" m = %s" % m.hex()) + print(" ad = %s" % ad.hex()) + print("npub = %s" % npub.hex()) + print(" k = %s" % k.hex()) + print(" c = %s" % c.hex()) + + submit('c', b"\0" * (len(m) + 32)) + submit('s', b"") + + submit('m', m) + submit('a', ad) + submit('k', k) + submit('p', npub) + write(b'e') + write(b'C') + output = obtain() + print(" c = %s" % output.hex()) + if c != output: + raise Exception("output of encryption is different from expected ciphertext") + + submit('m', b"\0" * len(c)) + submit('s', b"") + + submit('c', c) + submit('a', ad) + submit('k', k) + submit('p', npub) + write(b'd') + write(b'M') + output = obtain() + print(" m = %s" % output.hex()) + if m != output: + raise Exception("output of encryption is different from expected ciphertext") + + + + elif res is not None: + if res[1].lower() == 'count': + i = int(res[2], 10) + elif res[1].lower() == 'key': + k = bytes.fromhex(res[2]) + elif res[1].lower() == 'nonce': + npub = bytes.fromhex(res[2]) + elif res[1].lower() == 'pt': + m = bytes.fromhex(res[2]) + elif res[1].lower() == 'ad': + ad = bytes.fromhex(res[2]) + elif res[1].lower() == 'ct': + c = bytes.fromhex(res[2]) + else: + print("ERROR: unparsed line in test vectors file: '%s'" % res) + else: + print("ERROR: unparsed line in test vectors file: '%s'" % line) + if __name__ == "__main__": sys.exit(main(sys.argv)) -- libgit2 0.26.0