corecrypto/scripts/convert_h2c_testvectors.py

152 lines
5.1 KiB
Python
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright (c) (2020) Apple Inc. All rights reserved.
#
# corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
# is contained in the License.txt file distributed with corecrypto) and only to
# people who accept that license. IMPORTANT: Any license rights granted to you by
# Apple Inc. (if any) are limited to internal use within your organization only on
# devices and computers you own or control, for the sole purpose of verifying the
# security characteristics and correct functioning of the Apple Software. You may
# not, directly or indirectly, redistribute the Apple Software or any portions thereof.
import os
import json
import binascii
import argparse
class Compiler(object):
def __init__(self):
self.syms = []
self.decls = []
self.symid = 0
self.prefix = binascii.hexlify(os.urandom(6)).decode("utf-8")
self.c_struct_data = ""
self.test_vector_structs = []
self.STRUCT = None
def gen_sym(self, name):
self.symid += 1
return "cctest_{}_{}_{}".format(self.prefix, name, self.symid)
def convert_hex_uint8t_list(self, name, data):
_ = binascii.unhexlify(data) # Make sure it's hex
data = ["0x{}".format(data[x:x+2]) for x in range(0, len(data), 2)]
sym = self.gen_sym(name)
self.c_struct_data += 'static const uint8_t {}[] = {{ {} }};\n'.format(sym, ', '.join(data))
return (sym, len(data))
def convert_struct(self, struct_name, name, data):
sym = self.gen_sym(name)
fields = []
for k,v in data.items():
fields.append('.{} = {}'.format(k, v))
self.c_struct_data += 'static const struct {} {} = {{ {} }};\n'.format(
self.STRUCT,
sym,
', '.join(fields)
)
return sym
def add_test_vector(self, name, data):
assert self.STRUCT is not None
sym = self.convert_struct(self.STRUCT, name, data)
self.test_vector_structs.append("&{}".format(sym))
return sym
def finish_vectors(self, name):
assert self.STRUCT is not None
self.c_struct_data += 'static const struct {} *{}[] = {{ {} }};\n\n'.format(
self.STRUCT,
name,
', '.join(self.test_vector_structs)
)
return self.c_struct_data
class SSWU(Compiler):
'''
struct cch2c_sswu_test_vector {
unsigned tcId;
unsigned curve;
unsigned hkdf;
const uint8_t *alpha;
size_t alpha_len;
const uint8_t *DST;
size_t DST_len;
const uint8_t *NUx;
size_t NUx_len;
const uint8_t *NUy;
size_t NUy_len;
const uint8_t *ROx;
size_t ROx_len;
const uint8_t *ROy;
size_t ROy_len;
const uint8_t u_nu;
size_t u_nu_len;
const uint8_t u_ro0;
size_t u_ro0_len;
const uint8_t u_ro1;
size_t u_ro1_len;
};
'''
def __init__(self):
super(SSWU, self).__init__()
self.STRUCT = "cch2c_sswu_test_vector"
self.UINT8T_BLOBS = ["alpha", "DST", "NUx", "NUy", "ROx", "ROy", "u_nu", "u_ro0", "u_ro1", "Q0x", "Q0y", "Q1x", "Q1y"]
def process(self, json_data):
for test_group in json_data["testGroups"]:
for test in test_group["tests"]:
test_vector = {}
for blob_name in self.UINT8T_BLOBS:
blob_value = test.get(blob_name, None)
if blob_value is not None:
sym, data_len = self.convert_hex_uint8t_list(blob_name, blob_value)
test_vector[blob_name] = sym
test_vector["{}_len".format(blob_name)] = data_len
test_vector["tcId"] = test.get("tcId", -1)
test_vector["curve"] = test_group.get("curve", -1)
test_vector["hkdf"] = test_group.get("hkdf", -1)
self.add_test_vector("test_vector", test_vector)
TEST_VECTORS = {
"h2c_sswu" : {
"compiler": SSWU,
"files": ["h2c/sswu.json"],
"output_dir": "cch2c/test_vectors",
"test_vectors_name": "h2c_sswu_vectors"
}
}
def convert(srcroot):
for test_name, test_struct in TEST_VECTORS.items():
compiler = test_struct["compiler"]()
input_files = list(map(lambda file: os.path.join(srcroot, "corecrypto_test/test_vectors", file), test_struct["files"]))
output_file = os.path.join(srcroot, test_struct["output_dir"], '{}.kat'.format(test_name))
print(output_file)
with open(output_file, "w") as fout:
for input_file in input_files:
with open(input_file) as fin:
data = fin.read()
json_data = json.loads(data)
compiler.process(json_data)
fout.write(compiler.finish_vectors(test_struct["test_vectors_name"]))
if __name__ == "__main__":
parser = argparse.ArgumentParser(description = "Convert Wycheproof test vectors into C structs")
parser.add_argument("srcroot", help = "Repository srcroot")
args = parser.parse_args()
convert(args.srcroot)