120 lines
5 KiB
Python
120 lines
5 KiB
Python
#!/usr/bin/env python3
|
|
|
|
import copy
|
|
import glob
|
|
import jinja2
|
|
import jinja2.ext
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
import yaml
|
|
import json
|
|
import sys
|
|
|
|
def file_get_contents(filename, encoding=None):
|
|
with open(filename, mode='r', encoding=encoding) as fh:
|
|
return fh.read()
|
|
|
|
def file_put_contents(filename, s, encoding=None):
|
|
with open(filename, mode='w', encoding=encoding) as fh:
|
|
fh.write(s)
|
|
|
|
def get_kem_nistlevel(alg, docsdir):
|
|
# translate family names in generate.yml to directory names for liboqs algorithm datasheets
|
|
if alg['family'] == 'CRYSTALS-Kyber': datasheetname = 'kyber'
|
|
elif alg['family'] == 'SIDH': datasheetname = 'sike'
|
|
elif alg['family'] == 'NTRU-Prime': datasheetname = 'ntruprime'
|
|
else: datasheetname = alg['family'].lower()
|
|
# load datasheet
|
|
try:
|
|
algymlfilename = os.path.join(docsdir, 'algorithms', 'kem', '{:s}.yml'.format(datasheetname))
|
|
algyml = yaml.safe_load(file_get_contents(algymlfilename, encoding='utf-8'))
|
|
except: # check alternate location in "oldalgs" folder
|
|
algymlfilename = os.path.join("oqs-template", 'oldalgdocs', 'kem', '{:s}.yml'.format(datasheetname))
|
|
algyml = yaml.safe_load(file_get_contents(algymlfilename, encoding='utf-8'))
|
|
|
|
# hacks to match names
|
|
def matches(name, alg):
|
|
def simplify(s):
|
|
return s.lower().replace('_', '').replace('-', '')
|
|
if 'FrodoKEM' in name: name = name.replace('FrodoKEM', 'Frodo')
|
|
if 'Saber-KEM' in name: name = name.replace('-KEM', '')
|
|
if '-90s' in name: name = name.replace('-90s', '').replace('Kyber', 'Kyber90s')
|
|
if simplify(name) == simplify(alg['name_group']): return True
|
|
return False
|
|
# find the variant that matches
|
|
for variant in algyml['parameter-sets']:
|
|
if matches(variant['name'], alg):
|
|
return variant['claimed-nist-level']
|
|
# Information file for algorithms no longer supported by liboqs:
|
|
oldalgs = yaml.safe_load(file_get_contents(os.path.join("oqs-template", "oldalgs.yml"), encoding='utf-8'))
|
|
name = alg['name_group']
|
|
if name in oldalgs:
|
|
return oldalgs[name]['claimed-nist-level']
|
|
return None
|
|
|
|
def get_sig_nistlevel(family, alg, docsdir):
|
|
# translate family names in generate.yml to directory names for liboqs algorithm datasheets
|
|
if family['family'] == 'CRYSTALS-Dilithium': datasheetname = 'dilithium'
|
|
elif family['family'] == 'SPHINCS-Haraka': datasheetname = 'sphincs'
|
|
elif family['family'] == 'SPHINCS-SHA256': datasheetname = 'sphincs'
|
|
elif family['family'] == 'SPHINCS-SHAKE256': datasheetname = 'sphincs'
|
|
elif family['family'] == 'SPHINCS-SHA2': datasheetname = 'sphincs'
|
|
elif family['family'] == 'SPHINCS-SHAKE': datasheetname = 'sphincs'
|
|
else: datasheetname = family['family'].lower()
|
|
# load datasheet
|
|
algymlfilename = os.path.join(docsdir, 'algorithms', 'sig', '{:s}.yml'.format(datasheetname))
|
|
algyml = yaml.safe_load(file_get_contents(algymlfilename, encoding='utf-8'))
|
|
# hacks to match names
|
|
def matches(name, alg):
|
|
def simplify(s):
|
|
return s.lower().replace('_', '').replace('-', '').replace('+', '')
|
|
if simplify(name) == simplify(alg['name']): return True
|
|
return False
|
|
# find the variant that matches
|
|
for variant in algyml['parameter-sets']:
|
|
if matches(variant['name'], alg):
|
|
return variant['claimed-nist-level']
|
|
# Information file for algorithms no longer supported by liboqs:
|
|
oldalgs = yaml.safe_load(file_get_contents(os.path.join("oqs-template", "oldalgs.yml"), encoding='utf-8'))
|
|
name = alg['name']
|
|
if name in oldalgs:
|
|
return oldalgs[name]['claimed-nist-level']
|
|
return None
|
|
|
|
def nist_to_bits(nistlevel):
|
|
if nistlevel==1 or nistlevel==2:
|
|
return 128
|
|
elif nistlevel==3 or nistlevel==4:
|
|
return 192
|
|
elif nistlevel==5:
|
|
return 256
|
|
else:
|
|
return None
|
|
|
|
def complete_config(config, oqsdocsdir = None):
|
|
if oqsdocsdir == None:
|
|
if 'LIBOQS_DOCS_DIR' not in os.environ:
|
|
print("Must include LIBOQS_DOCS_DIR in environment")
|
|
exit(1)
|
|
oqsdocsdir = os.environ["LIBOQS_DOCS_DIR"]
|
|
for kem in config['kems']:
|
|
if not "bit_security" in kem.keys():
|
|
bits_level = nist_to_bits(get_kem_nistlevel(kem, oqsdocsdir))
|
|
if bits_level == None:
|
|
print("Cannot find security level for {:s} {:s}".format(kem['family'], kem['name_group']))
|
|
exit(1)
|
|
kem['bit_security'] = bits_level
|
|
for famsig in config['sigs']:
|
|
for sig in famsig['variants']:
|
|
if not "security" in sig.keys():
|
|
bits_level = nist_to_bits(get_sig_nistlevel(famsig, sig, oqsdocsdir))
|
|
if bits_level == None:
|
|
if sig['name'].startswith("rainbowI"):
|
|
bits_level=128
|
|
else:
|
|
print("Cannot find security level for {:s} {:s}".format(famsig['family'], sig['name']))
|
|
exit(1)
|
|
sig['security'] = bits_level
|
|
return config
|
|
|