From 2d9dec989bc5e9ec72d0fc9d6878a38cff00809b Mon Sep 17 00:00:00 2001 From: Douglas Stebila Date: Sun, 12 May 2019 14:52:59 -0400 Subject: [PATCH] Auto-generate more KEM files for PQClean implementations --- Makefile.am | 2 + config/features.m4 | 14 +- configure.ac | 2 + .../Makefile.am/if_enable_kem.fragment | 5 + .../config/features.m4/am_cond_if.fragment | 5 + .../features.m4/arg_disbl_set_wrap.fragment | 3 + .../configure.ac/ac_config_files.fragment | 3 + .../copy_from_pqclean/copy_from_pqclean.py | 50 ++++++-- .../copy_from_pqclean/copy_from_pqclean.yml | 121 +++++++++--------- .../src/kem/kem.c/alg_identifier.fragment | 3 + .../src/kem/kem.c/new_case.fragment | 8 ++ .../src/kem/kem.h/alg_identifier.fragment | 4 + .../src/kem/kem.h/include.fragment | 3 + src/kem/kem.c | 6 +- src/kem/kem.h | 4 + 15 files changed, 159 insertions(+), 74 deletions(-) create mode 100644 scripts/copy_from_pqclean/Makefile.am/if_enable_kem.fragment create mode 100644 scripts/copy_from_pqclean/config/features.m4/am_cond_if.fragment create mode 100644 scripts/copy_from_pqclean/config/features.m4/arg_disbl_set_wrap.fragment create mode 100644 scripts/copy_from_pqclean/configure.ac/ac_config_files.fragment create mode 100644 scripts/copy_from_pqclean/src/kem/kem.c/alg_identifier.fragment create mode 100644 scripts/copy_from_pqclean/src/kem/kem.c/new_case.fragment create mode 100644 scripts/copy_from_pqclean/src/kem/kem.h/alg_identifier.fragment create mode 100644 scripts/copy_from_pqclean/src/kem/kem.h/include.fragment diff --git a/Makefile.am b/Makefile.am index ceb529360..9c6456030 100644 --- a/Makefile.am +++ b/Makefile.am @@ -30,9 +30,11 @@ endif if ENABLE_KEM_BIKE liboqs_la_LIBADD += src/kem/bike/libkembike.la endif +##### OQS_COPY_FROM_PQCLEAN_FRAGMENT_IF_ENABLE_KEM_START if ENABLE_KEM_FRODOKEM liboqs_la_LIBADD += src/kem/frodokem/libkemfrodokem.la endif +##### OQS_COPY_FROM_PQCLEAN_FRAGMENT_IF_ENABLE_KEM_END if ENABLE_KEM_SIKE liboqs_la_LIBADD += src/kem/sike/libkemsike.la endif diff --git a/config/features.m4 b/config/features.m4 index 36a55299e..9f44f5371 100644 --- a/config/features.m4 +++ b/config/features.m4 @@ -43,7 +43,9 @@ AC_DEFUN([CONFIG_FEATURE_FLAGS], [AM_CONDITIONAL(ENABLE_KEM_BIKE, [false])] ) +##### OQS_COPY_FROM_PQCLEAN_FRAGMENT_ARG_DISBL_SET_WRAP_START ARG_DISBL_SET_WRAP([kem-frodokem], [kem_frodokem], [ENABLE_KEM_FRODOKEM], [src/kem/frodokem]) +##### OQS_COPY_FROM_PQCLEAN_FRAGMENT_ARG_DISBL_SET_WRAP_END ARG_DISBL_SET_WRAP([kem-sike], [kem_sike], [ENABLE_KEM_SIKE], [src/kem/sike]) ARG_DISBL_SET_WRAP([kem-newhope], [kem_newhope], [ENABLE_KEM_NEWHOPE], [src/kem/newhopenist]) ARG_DISBL_SET_WRAP([kem-kyber], [kem_kyber], [ENABLE_KEM_KYBER], [src/kem/kyber]) @@ -79,14 +81,16 @@ AC_DEFUN([CONFIG_FEATURES], ]) ]) +##### OQS_COPY_FROM_PQCLEAN_FRAGMENT_AM_COND_IF_START AM_COND_IF([ENABLE_KEM_FRODOKEM], [ - AC_DEFINE(OQS_ENABLE_KEM_frodokem_640_aes, 1, "Define to 1 when FrodoKEM-640-AES enabled") - AC_DEFINE(OQS_ENABLE_KEM_frodokem_640_shake, 1, "Define to 1 when FrodoKEM-640-SHAKE enabled") - AC_DEFINE(OQS_ENABLE_KEM_frodokem_976_aes, 1, "Define to 1 when FrodoKEM-976-AES enabled") - AC_DEFINE(OQS_ENABLE_KEM_frodokem_976_shake, 1, "Define to 1 when FrodoKEM-976-SHAKE enabled") - AC_DEFINE(OQS_ENABLE_KEM_frodokem_1344_aes, 1, "Define to 1 when FrodoKEM-1344-AES enabled") + AC_DEFINE(OQS_ENABLE_KEM_frodokem_640_aes, 1, "Define to 1 when FrodoKEM-640-AES enabled") + AC_DEFINE(OQS_ENABLE_KEM_frodokem_640_shake, 1, "Define to 1 when FrodoKEM-640-SHAKE enabled") + AC_DEFINE(OQS_ENABLE_KEM_frodokem_976_aes, 1, "Define to 1 when FrodoKEM-976-AES enabled") + AC_DEFINE(OQS_ENABLE_KEM_frodokem_976_shake, 1, "Define to 1 when FrodoKEM-976-SHAKE enabled") + AC_DEFINE(OQS_ENABLE_KEM_frodokem_1344_aes, 1, "Define to 1 when FrodoKEM-1344-AES enabled") AC_DEFINE(OQS_ENABLE_KEM_frodokem_1344_shake, 1, "Define to 1 when FrodoKEM-1344-SHAKE enabled") ]) +##### OQS_COPY_FROM_PQCLEAN_FRAGMENT_AM_COND_IF_END AM_COND_IF([ENABLE_KEM_SIKE], [ AC_DEFINE(OQS_ENABLE_KEM_sike_p503, 1, "Define to 1 when Sike-p503 enabled") diff --git a/configure.ac b/configure.ac index e91a80ebf..1370155f0 100644 --- a/configure.ac +++ b/configure.ac @@ -71,7 +71,9 @@ AC_CONFIG_FILES([Makefile src/sig/picnic/Makefile src/sig/qtesla/Makefile src/kem/bike/Makefile +##### OQS_COPY_FROM_PQCLEAN_FRAGMENT_AC_CONFIG_FILES_START src/kem/frodokem/Makefile +##### OQS_COPY_FROM_PQCLEAN_FRAGMENT_AC_CONFIG_FILES_END src/kem/sike/Makefile src/kem/newhopenist/Makefile src/kem/kyber/Makefile diff --git a/scripts/copy_from_pqclean/Makefile.am/if_enable_kem.fragment b/scripts/copy_from_pqclean/Makefile.am/if_enable_kem.fragment new file mode 100644 index 000000000..1fcb8431f --- /dev/null +++ b/scripts/copy_from_pqclean/Makefile.am/if_enable_kem.fragment @@ -0,0 +1,5 @@ +{% for family in families %} +if ENABLE_KEM_{{ family['name']|upper }} +liboqs_la_LIBADD += src/kem/{{ family['name'] }}/libkem{{ family['name'] }}.la +endif{% endfor %} + diff --git a/scripts/copy_from_pqclean/config/features.m4/am_cond_if.fragment b/scripts/copy_from_pqclean/config/features.m4/am_cond_if.fragment new file mode 100644 index 000000000..721adca6f --- /dev/null +++ b/scripts/copy_from_pqclean/config/features.m4/am_cond_if.fragment @@ -0,0 +1,5 @@ +{% for family in families %} + AM_COND_IF([ENABLE_KEM_{{ family['name']|upper }}], [{% for scheme in family['schemes'] %} + AC_DEFINE(OQS_ENABLE_KEM_{{ family['name'] }}_{{ scheme['scheme'] }}, 1, "Define to 1 when {{ scheme['pretty_name_full'] }} enabled"){% endfor %} + ]){% endfor %} + diff --git a/scripts/copy_from_pqclean/config/features.m4/arg_disbl_set_wrap.fragment b/scripts/copy_from_pqclean/config/features.m4/arg_disbl_set_wrap.fragment new file mode 100644 index 000000000..9bf66a8fd --- /dev/null +++ b/scripts/copy_from_pqclean/config/features.m4/arg_disbl_set_wrap.fragment @@ -0,0 +1,3 @@ +{% for family in families %} + ARG_DISBL_SET_WRAP([kem-{{ family['name'] }}], [kem_{{ family['name'] }}], [ENABLE_KEM_{{ family['name']|upper }}], [src/kem/{{ family['name'] }}]){% endfor %} + diff --git a/scripts/copy_from_pqclean/configure.ac/ac_config_files.fragment b/scripts/copy_from_pqclean/configure.ac/ac_config_files.fragment new file mode 100644 index 000000000..64508af38 --- /dev/null +++ b/scripts/copy_from_pqclean/configure.ac/ac_config_files.fragment @@ -0,0 +1,3 @@ +{% for family in families %} + src/kem/{{ family['name'] }}/Makefile{% endfor %} + diff --git a/scripts/copy_from_pqclean/copy_from_pqclean.py b/scripts/copy_from_pqclean/copy_from_pqclean.py index 2ff3f6eb5..392b753ec 100755 --- a/scripts/copy_from_pqclean/copy_from_pqclean.py +++ b/scripts/copy_from_pqclean/copy_from_pqclean.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 import copy +import glob import jinja2 import os import shutil @@ -19,25 +20,49 @@ def file_put_contents(filename, s, encoding=None): with open(filename, mode='w', encoding=encoding) as fh: fh.write(s) -def generator(destination_filename, template_filename, pqclean_dir, family, scheme_desired): +def generator(destination_filename, template_filename, family, scheme_desired): template = file_get_contents(os.path.join('scripts', 'copy_from_pqclean', template_filename)) f = copy.deepcopy(family) - f['family'] = f['name'] if scheme_desired != None: f['schemes'] = [x for x in f['schemes'] if x == scheme_desired] assert(len(f['schemes']) == 1) for scheme in f['schemes']: - scheme['metadata'] = yaml.safe_load(file_get_contents(os.path.join(pqclean_dir, 'crypto_kem', scheme['pqclean_scheme'], 'META.yml'))) scheme['metadata']['implementations'] = [imp for imp in scheme['metadata']['implementations'] if imp['name'] == scheme['implementation']] assert(len(scheme['metadata']['implementations']) == 1) - scheme['metadata']['ind_cca'] = 'true' file_put_contents(destination_filename, jinja2.Template(template).render(f)) -instructions = file_get_contents(os.path.join('scripts', 'copy_from_pqclean', 'copy_from_pqclean.yml'), encoding='utf-8') -instructions = yaml.safe_load(instructions) +def replacer(filename, families, delimiter): + fragments = glob.glob(os.path.join('scripts', 'copy_from_pqclean', filename, '*.fragment')) + contents = file_get_contents(filename) + for fragment in fragments: + template = file_get_contents(fragment) + identifier = os.path.splitext(os.path.basename(fragment))[0] + identifier_start = '{} OQS_COPY_FROM_PQCLEAN_FRAGMENT_{}_START'.format(delimiter, identifier.upper()) + identifier_end = '{} OQS_COPY_FROM_PQCLEAN_FRAGMENT_{}_END'.format(delimiter, identifier.upper()) + preamble = contents[:contents.find(identifier_start)] + postamble = contents[contents.find(identifier_end):] + contents = preamble + identifier_start + jinja2.Template(template).render({'families': families}) + postamble + file_put_contents(filename, contents) -for family in instructions: +def load_kems(): + instructions = file_get_contents(os.path.join('scripts', 'copy_from_pqclean', 'copy_from_pqclean.yml'), encoding='utf-8') + instructions = yaml.safe_load(instructions) + kems = instructions['kems'] + for family in kems: + family['family'] = family['name'] + for scheme in family['schemes']: + scheme['metadata'] = yaml.safe_load(file_get_contents(os.path.join(os.environ['PQCLEAN_DIR'], 'crypto_kem', scheme['pqclean_scheme'], 'META.yml'))) + scheme['metadata']['ind_cca'] = 'true' + return kems + +kems = load_kems() + +for family in kems: for scheme in family['schemes']: + try: + os.mkdir(os.path.join('src', 'kem', family['name'])) + except: + pass shutil.rmtree(os.path.join('src', 'kem', family['name'], 'pqclean_{}_clean'.format(scheme['pqclean_scheme'])), ignore_errors=True) subprocess.run([ 'cp', @@ -51,7 +76,6 @@ for family in instructions: generator( os.path.join('src', 'kem', family['name'], 'kem_{}.h'.format(family['name'])), os.path.join('src', 'kem', 'family', 'kem_family.h'), - os.environ['PQCLEAN_DIR'], family, None, ) @@ -59,7 +83,6 @@ for family in instructions: generator( os.path.join('src', 'kem', family['name'], 'Makefile.am'), os.path.join('src', 'kem', 'family', 'Makefile.am'), - os.environ['PQCLEAN_DIR'], family, None, ) @@ -68,7 +91,12 @@ for family in instructions: generator( os.path.join('src', 'kem', family['name'], 'kem_{}.c'.format(scheme['pqclean_scheme'])), os.path.join('src', 'kem', 'family', 'kem_scheme.c'), - os.environ['PQCLEAN_DIR'], family, scheme, - ) \ No newline at end of file + ) + +replacer('config/features.m4', kems, '#####') +replacer('configure.ac', kems, '#####') +replacer('Makefile.am', kems, '#####') +replacer('src/kem/kem.c', kems, '/////') +replacer('src/kem/kem.h', kems, '/////') diff --git a/scripts/copy_from_pqclean/copy_from_pqclean.yml b/scripts/copy_from_pqclean/copy_from_pqclean.yml index e49632ebd..1c649362e 100644 --- a/scripts/copy_from_pqclean/copy_from_pqclean.yml +++ b/scripts/copy_from_pqclean/copy_from_pqclean.yml @@ -1,57 +1,64 @@ -- - name: frodokem - schemes: - - - scheme: 640_aes - pqclean_scheme: frodokem640aes - implementation: clean - sources: - - kem.c - - matrix_aes.c - - noise.c - - util.c - - - scheme: 640_shake - pqclean_scheme: frodokem640shake - implementation: clean - sources: - - kem.c - - matrix_shake.c - - noise.c - - util.c - - - scheme: 976_aes - pqclean_scheme: frodokem976aes - implementation: clean - sources: - - kem.c - - matrix_aes.c - - noise.c - - util.c - - - scheme: 976_shake - pqclean_scheme: frodokem976shake - implementation: clean - sources: - - kem.c - - matrix_shake.c - - noise.c - - util.c - - - scheme: 1344_aes - pqclean_scheme: frodokem1344aes - implementation: clean - sources: - - kem.c - - matrix_aes.c - - noise.c - - util.c - - - scheme: 1344_shake - pqclean_scheme: frodokem1344shake - implementation: clean - sources: - - kem.c - - matrix_shake.c - - noise.c - - util.c +kems: + - + name: frodokem + schemes: + - + scheme: 640_aes + pqclean_scheme: frodokem640aes + pretty_name_full: FrodoKEM-640-AES + implementation: clean + sources: + - kem.c + - matrix_aes.c + - noise.c + - util.c + - + scheme: 640_shake + pqclean_scheme: frodokem640shake + pretty_name_full: FrodoKEM-640-SHAKE + implementation: clean + sources: + - kem.c + - matrix_shake.c + - noise.c + - util.c + - + scheme: 976_aes + pqclean_scheme: frodokem976aes + pretty_name_full: FrodoKEM-976-AES + implementation: clean + sources: + - kem.c + - matrix_aes.c + - noise.c + - util.c + - + scheme: 976_shake + pqclean_scheme: frodokem976shake + pretty_name_full: FrodoKEM-976-SHAKE + implementation: clean + sources: + - kem.c + - matrix_shake.c + - noise.c + - util.c + - + scheme: 1344_aes + pqclean_scheme: frodokem1344aes + pretty_name_full: FrodoKEM-1344-AES + implementation: clean + sources: + - kem.c + - matrix_aes.c + - noise.c + - util.c + - + scheme: 1344_shake + pqclean_scheme: frodokem1344shake + pretty_name_full: FrodoKEM-1344-SHAKE + implementation: clean + sources: + - kem.c + - matrix_shake.c + - noise.c + - util.c diff --git a/scripts/copy_from_pqclean/src/kem/kem.c/alg_identifier.fragment b/scripts/copy_from_pqclean/src/kem/kem.c/alg_identifier.fragment new file mode 100644 index 000000000..b0bae6974 --- /dev/null +++ b/scripts/copy_from_pqclean/src/kem/kem.c/alg_identifier.fragment @@ -0,0 +1,3 @@ +{% for family in families %} + {% for scheme in family['schemes'] %}OQS_KEM_alg_{{ family['name'] }}_{{ scheme['scheme'] }}, {% endfor %}{% endfor %} + diff --git a/scripts/copy_from_pqclean/src/kem/kem.c/new_case.fragment b/scripts/copy_from_pqclean/src/kem/kem.c/new_case.fragment new file mode 100644 index 000000000..cdb0feefe --- /dev/null +++ b/scripts/copy_from_pqclean/src/kem/kem.c/new_case.fragment @@ -0,0 +1,8 @@ +{% for family in families %}{% for scheme in family['schemes'] %} + } else if (0 == strcasecmp(method_name, OQS_KEM_alg_{{ family['name'] }}_{{ scheme['scheme'] }})) { +#ifdef OQS_ENABLE_KEM_{{ family['name'] }}_{{ scheme['scheme'] }} + return OQS_KEM_{{ family['name'] }}_{{ scheme['scheme'] }}_new(); +#else + return NULL; +#endif{% endfor %}{% endfor %} + diff --git a/scripts/copy_from_pqclean/src/kem/kem.h/alg_identifier.fragment b/scripts/copy_from_pqclean/src/kem/kem.h/alg_identifier.fragment new file mode 100644 index 000000000..d75de80fa --- /dev/null +++ b/scripts/copy_from_pqclean/src/kem/kem.h/alg_identifier.fragment @@ -0,0 +1,4 @@ +{% for family in families %}{% for scheme in family['schemes'] %} +/** Algorithm identifier for {{ scheme['pretty_name_full'] }} KEM. */ +#define OQS_KEM_alg_{{ family['name'] }}_{{ scheme['scheme'] }} "{{ scheme['pretty_name_full'] }}"{% endfor %}{% endfor %} + diff --git a/scripts/copy_from_pqclean/src/kem/kem.h/include.fragment b/scripts/copy_from_pqclean/src/kem/kem.h/include.fragment new file mode 100644 index 000000000..6f7724ca8 --- /dev/null +++ b/scripts/copy_from_pqclean/src/kem/kem.h/include.fragment @@ -0,0 +1,3 @@ +{% for family in families %} +#include {% endfor %} + diff --git a/src/kem/kem.c b/src/kem/kem.c index 897cec9a2..153f605df 100644 --- a/src/kem/kem.c +++ b/src/kem/kem.c @@ -13,7 +13,9 @@ OQS_API const char *OQS_KEM_alg_identifier(size_t i) { const char *a[OQS_KEM_algs_length] = { OQS_KEM_alg_default, OQS_KEM_alg_bike1_l1, OQS_KEM_alg_bike1_l3, OQS_KEM_alg_bike1_l5, OQS_KEM_alg_bike2_l1, OQS_KEM_alg_bike2_l3, OQS_KEM_alg_bike2_l5, OQS_KEM_alg_bike3_l1, OQS_KEM_alg_bike3_l3, OQS_KEM_alg_bike3_l5, - OQS_KEM_alg_frodokem_640_aes, OQS_KEM_alg_frodokem_640_shake, OQS_KEM_alg_frodokem_976_aes, OQS_KEM_alg_frodokem_976_shake, OQS_KEM_alg_frodokem_1344_aes, OQS_KEM_alg_frodokem_1344_shake, +///// OQS_COPY_FROM_PQCLEAN_FRAGMENT_ALG_IDENTIFIER_START + OQS_KEM_alg_frodokem_640_aes, OQS_KEM_alg_frodokem_640_shake, OQS_KEM_alg_frodokem_976_aes, OQS_KEM_alg_frodokem_976_shake, OQS_KEM_alg_frodokem_1344_aes, OQS_KEM_alg_frodokem_1344_shake, +///// OQS_COPY_FROM_PQCLEAN_FRAGMENT_ALG_IDENTIFIER_END OQS_KEM_alg_newhope_512_cca_kem, OQS_KEM_alg_newhope_1024_cca_kem, OQS_KEM_alg_kyber_512_cca_kem, OQS_KEM_alg_kyber_768_cca_kem, OQS_KEM_alg_kyber_1024_cca_kem, OQS_KEM_alg_sidh_p503, OQS_KEM_alg_sidh_p751, @@ -89,6 +91,7 @@ OQS_API OQS_KEM *OQS_KEM_new(const char *method_name) { #else return NULL; #endif +///// OQS_COPY_FROM_PQCLEAN_FRAGMENT_NEW_CASE_START } else if (0 == strcasecmp(method_name, OQS_KEM_alg_frodokem_640_aes)) { #ifdef OQS_ENABLE_KEM_frodokem_640_aes return OQS_KEM_frodokem_640_aes_new(); @@ -125,6 +128,7 @@ OQS_API OQS_KEM *OQS_KEM_new(const char *method_name) { #else return NULL; #endif +///// OQS_COPY_FROM_PQCLEAN_FRAGMENT_NEW_CASE_END } else if (0 == strcasecmp(method_name, OQS_KEM_alg_newhope_512_cca_kem)) { #ifdef OQS_ENABLE_KEM_newhope_512_cca_kem return OQS_KEM_newhope_512_cca_kem_new(); diff --git a/src/kem/kem.h b/src/kem/kem.h index ae29ec205..1791466c4 100644 --- a/src/kem/kem.h +++ b/src/kem/kem.h @@ -45,6 +45,7 @@ #define OQS_KEM_alg_bike3_l3 "BIKE3-L3" /** Algorithm identifier for BIKE3-L5 KEM. */ #define OQS_KEM_alg_bike3_l5 "BIKE3-L5" +///// OQS_COPY_FROM_PQCLEAN_FRAGMENT_ALG_IDENTIFIER_START /** Algorithm identifier for FrodoKEM-640-AES KEM. */ #define OQS_KEM_alg_frodokem_640_aes "FrodoKEM-640-AES" /** Algorithm identifier for FrodoKEM-640-SHAKE KEM. */ @@ -57,6 +58,7 @@ #define OQS_KEM_alg_frodokem_1344_aes "FrodoKEM-1344-AES" /** Algorithm identifier for FrodoKEM-1344-SHAKE KEM. */ #define OQS_KEM_alg_frodokem_1344_shake "FrodoKEM-1344-SHAKE" +///// OQS_COPY_FROM_PQCLEAN_FRAGMENT_ALG_IDENTIFIER_END /** Algorithm identifier for NewHope-512-CCA-KEM KEM. */ #define OQS_KEM_alg_newhope_512_cca_kem "NewHope-512-CCA-KEM" /** Algorithm identifier for NewHope-1024-CCA-KEM KEM. */ @@ -242,7 +244,9 @@ OQS_API OQS_STATUS OQS_KEM_decaps(const OQS_KEM *kem, uint8_t *shared_secret, co OQS_API void OQS_KEM_free(OQS_KEM *kem); #include +///// OQS_COPY_FROM_PQCLEAN_FRAGMENT_INCLUDE_START #include +///// OQS_COPY_FROM_PQCLEAN_FRAGMENT_INCLUDE_END #include #include #include