-rwxr-xr-x 9458 libntruprime-20241008/autogen/src raw
#!/usr/bin/env python3
systems = ( # p,q,sk,pk,ct,w
(653,4621,1518,994,897,288),
(761,4591,1763,1158,1039,286),
(857,5167,1999,1322,1184,322),
(953,6343,2254,1505,1349,396),
(1013,7177,2417,1623,1455,448),
(1277,7879,3059,2067,1847,492),
)
apiall = {}
topdir = 'crypto_kem'
import shutil
import os
import re
from math import floor,ceil
import subprocess
def readfile(fn):
with open(fn) as f:
return f.read()
def writefile(fn,x):
with open(fn,'w') as f:
f.write(x)
def writefiletime(fn,x,t):
writefile(fn,x)
os.utime(fn,(t,t))
build_subroutine_done = set()
def build_subroutine(sub,macros):
src = 'src/%s'%sub
srctime = os.stat(src).st_mtime
o = sub.split('/')[0]
op = 'crypto_%s'%sub
for m in macros:
op = re.sub(m,str(macros[m]),op)
if op in build_subroutine_done: return
print('building %s'%op)
shutil.rmtree(op,ignore_errors=True)
os.makedirs(op)
api = ''
if sub.startswith('verify/'):
api = '#define CRYPTO_BYTES %s\n'%macros['BYTES']
if sub.startswith('decode/') or sub.startswith('encode/'):
api = '#define CRYPTO_STRBYTES %s\n'%macros['STRBYTES']
api += '#define CRYPTO_ITEMS %s\n'%macros['ITEMS']
api += '#define CRYPTO_ITEMBYTES %s\n'%macros['ITEMBYTES']
if sub.startswith('core/'):
api = '#define CRYPTO_OUTPUTBYTES %s\n'%macros['OUTPUTBYTES']
api += '#define CRYPTO_INPUTBYTES %s\n'%macros['INPUTBYTES']
api += '#define CRYPTO_KEYBYTES %s\n'%macros['KEYBYTES']
api += '#define CRYPTO_CONSTBYTES %s\n'%macros['CONSTBYTES']
if o not in apiall: apiall[o] = ''
apiall[o] += api.replace('CRYPTO_',op.replace('/','_'))
for impl in sorted(os.listdir(src)):
if impl == 'supercop': continue
srci = '%s/%s'%(src,impl)
srcitime = os.stat(srci).st_mtime
opi = '%s/%s'%(op,impl)
os.makedirs(opi)
if impl != 'supercop':
writefiletime('%s/api.h'%opi,api,srctime)
for fn in sorted(os.listdir(srci)):
if fn == 'mult768.c':
if macros['P'] > 768: continue
if fn in ('mult1024.c','precomp7681.inc','precomp10753.inc'):
if macros['P'] < 768: continue
if macros['P'] > 1024: continue
if fn in ('mult1280.c'):
if macros['P'] < 1024: continue
if macros['P'] > 1280: continue
srcif = '%s/%s'%(srci,fn)
opif = '%s/%s'%(opi,fn)
x = readfile(srcif)
for m in macros:
x = re.sub('{%s}'%m,'%s'%macros[m],x)
writefiletime(opif,x,os.stat(srcif).st_mtime)
if os.stat(srcif).st_mode&1: os.chmod(opif,0o755)
if os.path.exists('%s/Makefile'%opi):
subprocess.check_call('cd %s; make'%opi,shell=True)
os.utime(opi,(srcitime,srcitime))
changedsrc = False
for m in macros:
newsrc = re.sub(m,'%s'%macros[m],src)
if newsrc != src:
changedsrc = True
src = newsrc
if changedsrc and os.path.exists(src):
srctime = os.stat(src).st_mtime
for impl in sorted(os.listdir(src)):
if impl == 'supercop': continue
srci = '%s/%s'%(src,impl)
srcitime = os.stat(srci).st_mtime
opi = '%s/%s'%(op,impl)
os.makedirs(opi)
writefiletime('%s/api.h'%opi,api,srctime)
for fn in sorted(os.listdir(srci)):
srcif = '%s/%s'%(srci,fn)
opif = '%s/%s'%(opi,fn)
x = readfile(srcif)
writefiletime(opif,x,os.stat(srcif).st_mtime)
if os.stat(srcif).st_mode&1: os.chmod(opif,0o755)
os.utime(opi,(srcitime,srcitime))
os.utime(op,(srctime,srctime))
build_subroutine_done.add(op)
# ----- sizes of encodings
limit = 16384
def Encode(R,M):
if len(M) == 0: return []
S = []
if len(M) == 1:
r,m = R[0],M[0]
while m > 1:
S += [r%256]
r,m = r//256,(m+255)//256
return S
R2,M2 = [],[]
for i in range(0,len(M)-1,2):
m,r = M[i]*M[i+1],R[i]+M[i]*R[i+1]
while m >= limit:
S += [r%256]
r,m = r//256,(m+255)//256
R2 += [r]
M2 += [m]
if len(M)&1:
R2 += [R[-1]]
M2 += [M[-1]]
return S+Encode(R2,M2)
def encodebytes(M):
return len(Encode([0]*len(M),M))
# ----- main loop
for p,q,sk,pk,ct,w in systems:
q23 = (q+2)//3
q14 = round(2.0**14/q)
q15 = floor(2.0**15/q)
q18 = round(2.0**18/q)
q27 = round(2.0**27/q)
q31 = floor(2.0**31/q)
qinv = pow(q,2**14-1,2**16)
if qinv >= 2**15: qinv -= 2**16
q10753 = (10753<<16)%q
if q10753 >= q/2: q10753 -= q
ppadsort = p
if p == 761: ppadsort = 768
if p == 953: ppadsort = 960
if p == 1013: ppadsort = 1024
if p == 1277: ppadsort = 1280
assert ppadsort >= p
ppad = p
while ppad%16 != 1: ppad += 1
ppad64 = p
while ppad64%64 != 1: ppad64 += 1
# ----- parameter checks
assert p > 0
assert p%4 == 1
assert q > 0
assert q%6 == 1
assert w > 0
assert 2*p >= 3*w
assert q >= 16*w+1
assert p < 1280
assert q < 8192
smallbytes = ceil(p/4.0)
roundedbytes = encodebytes([q23]*p)
assert pk == encodebytes([q]*p)
assert sk == 3*smallbytes+pk+32
assert ct == 32+roundedbytes
# ----- build relevant subroutines first
build_subroutine('verify/BYTES',{'BYTES':ct})
macros = {'STRBYTES':2,'ITEMS':1,'ITEMBYTES':2}
build_subroutine('decode/int16',macros)
build_subroutine('encode/int16',macros)
macros = {'P':p,'STRBYTES':(p+3)//4,'ITEMS':p,'ITEMBYTES':1}
macros['AVXLOOPS'] = ceil(p/128)
macros['AVXOVERSHOOT'] = 32*ceil(p/128)-floor(p/4)
build_subroutine('decode/Px3',macros)
build_subroutine('encode/Px3',macros)
macros = {'P':p,'STRBYTES':p*2,'ITEMS':p,'ITEMBYTES':2}
build_subroutine('decode/Pxint16',macros)
build_subroutine('encode/Pxint16',macros)
macros = {'P':p,'STRBYTES':p*4,'ITEMS':p,'ITEMBYTES':4}
build_subroutine('decode/Pxint32',macros)
macros = {'P':p,'Q':q,'Q12':(q-1)//2,'STRBYTES':encodebytes([q]*p),'ITEMS':p,'ITEMBYTES':2}
build_subroutine('decode/PxQ',macros)
build_subroutine('encode/PxQ',macros)
macros = {'P':p,'Q':q,'Q12':(q-1)//2,'R':q23,'STRBYTES':encodebytes([q23]*p),'ITEMS':p,'ITEMBYTES':2}
build_subroutine('decode/PxR',macros)
build_subroutine('encode/PxR',macros)
build_subroutine('encode/PxRround',macros)
macros = {'P':p,'STRBYTES':p,'ITEMS':p,'ITEMBYTES':2}
build_subroutine('encode/Pxfreeze3',macros)
macros = {'P':p,'PPAD64':ppad64,'OUTPUTBYTES':p+1,'INPUTBYTES':p,'KEYBYTES':0,'CONSTBYTES':0}
build_subroutine('core/inv3sntrupP',macros)
macros = {'P':p,'OUTPUTBYTES':p,'INPUTBYTES':p,'KEYBYTES':p,'CONSTBYTES':0}
build_subroutine('core/mult3sntrupP',macros)
macros = {'P':p,'Q':q,'QINV':qinv,
'Q18':q18,'15Q':q15,'Q27':q27,'Q31':q31,'Q10753':q10753,
'OUTPUTBYTES':2*p,'INPUTBYTES':2*p,'KEYBYTES':p,'CONSTBYTES':0}
build_subroutine('core/multsntrupP',macros)
macros = {'P':p,'PPAD':ppad,'Q':q,'QINV':qinv,
'Q14':q14,'15Q':q15,'Q18':q18,'Q27':q27,'Q31':q31,
'OUTPUTBYTES':2*p+1,'INPUTBYTES':p,'KEYBYTES':0,'CONSTBYTES':0}
build_subroutine('core/invsntrupP',macros)
macros = {'P':p,'Q':q,'OUTPUTBYTES':2*p,'INPUTBYTES':2*p,'KEYBYTES':0,'CONSTBYTES':0}
build_subroutine('core/scale3sntrupP',macros)
macros = {'P':p,'OUTPUTBYTES':2,'INPUTBYTES':p,'KEYBYTES':0,'CONSTBYTES':0}
macros['AVXENDINGMASK'] = ','.join(['1']*(p%32)+['0']*(32-(p%32)))
build_subroutine('core/weightsntrupP',macros)
macros = {'P':p,'W':w,'OUTPUTBYTES':p,'INPUTBYTES':p,'KEYBYTES':0,'CONSTBYTES':0}
build_subroutine('core/wforcesntrupP',macros)
# ----- and now build the kem
system = f'sntrup{p}'
src = 'src/kem/sntrupP'
srctime = os.stat(src).st_mtime
op = '%s/%s'%(topdir,system)
print('building %s'%op)
shutil.rmtree(op,ignore_errors=True)
os.makedirs(op)
opreal = 'crypto_kem/%s'%system
api = '#define CRYPTO_SECRETKEYBYTES %s\n'%sk
api += '#define CRYPTO_PUBLICKEYBYTES %s\n'%pk
api += '#define CRYPTO_CIPHERTEXTBYTES %s\n'%ct
api += '#define CRYPTO_BYTES 32\n'
if 'kem' not in apiall: apiall['kem'] = ''
apiall['kem'] += api.replace('CRYPTO_',opreal.replace('/','_'))
for impl in sorted(os.listdir(src)):
srci = '%s/%s'%(src,impl)
opi = '%s/%s'%(op,impl)
os.makedirs(opi)
target = '%s/api.h'%opi
writefiletime(target,api,os.stat(srci).st_mtime)
for fn in sorted(os.listdir(srci)):
srcif = '%s/%s'%(srci,fn)
opif = '%s/%s'%(opi,fn)
if (impl,fn) in (('factored','params.h'),('avx','Makefile')):
x = readfile(srcif)
x = re.sub('{P}','%s'%p,x)
x = re.sub('{PPADSORT}','%s'%ppadsort,x)
x = re.sub('{Q}','%s'%q,x)
x = re.sub('{R}','%d'%q23,x)
x = re.sub('{Q18}','%d'%q18,x)
x = re.sub('{Q27}','%d'%q27,x)
x = re.sub('{Q31}','%d'%q31,x)
x = re.sub('{W}','%s'%w,x)
x = re.sub('{CIPHERTEXTBYTES}','%s'%ct,x)
writefiletime(opif,x,os.stat(srcif).st_mtime)
continue
if p != 761 and fn == 'CHANGES': continue # XXX
x = readfile(srcif)
writefiletime(opif,x,os.stat(srcif).st_mtime)
if os.stat(srcif).st_mode&1: os.chmod(opif,0o755)
for impl in sorted(os.listdir('src/kem/sntrupP')):
opi = '%s/%s'%(op,impl)
if os.path.exists('%s/Makefile'%opi):
subprocess.check_call('cd %s; make'%opi,shell=True)
os.utime(op,(srctime,srctime))
for impl in sorted(os.listdir(src)):
srci = '%s/%s'%(src,impl)
srcitime = os.stat(srci).st_mtime
opi = '%s/%s'%(op,impl)
os.utime(opi,(srcitime,srcitime))
with open('api','w') as f:
for sub in 'verify','decode','encode','core','kem':
f.write(apiall[sub])
f.write('\n')