#!/bin/sh -e

# kpqc-supercop version 20240502
# SPDX-License-Identifier: LicenseRef-PD-hp OR CC0-1.0 OR 0BSD OR MIT-0 OR MIT

supercop=supercop-20240425

mkdir -p kpqc-supercop-build
cd kpqc-supercop-build

# ===== download and unpack supercop (if not already downloaded)

[ -f unpacked-"$supercop".tar.bz2 ] || (
  echo "downloading $supercop..."
  curl -s -o "$supercop".tar.bz2 https://bench.cr.yp.to/supercop/"$supercop".tar.bz2
  bunzip2 < "$supercop".tar.bz2 | tar -xf - "$supercop"
  sed -i 's/-fomit-frame-pointer/-gdwarf-4/' "$supercop"/okcompilers/c "$supercop"/okcompilers/cpp
  mv "$supercop".tar.bz2 unpacked-"$supercop".tar.bz2
)

# ===== download kpqc submissions (if not already downloaded)

(
  for x in AIMer HAETAE MQ-Sign NCC-Sign NTRU+ Paloma REDOG SMAUG-T
  do
    [ -f complete-"$x".zip ] || [ -f unpacked-"$x".zip ] || (
      echo "downloading $x..."
      if [ "$x" = Paloma ] || [ "$x" = REDOG ]
      then
        curl -s -o partial-"$x".zip https://kpqc.or.kr/images/zip/"$x"_Implementation_package.zip
      else
        curl -s -o partial-"$x".zip https://kpqc.or.kr/images/zip/"$x"_Implementation_package_v2.zip
      fi
      mv partial-"$x".zip complete-"$x".zip
    )
  done
)

# ===== unpack and patch kpqc submissions (if not already downloaded)

(
  for x in AIMer HAETAE MQ-Sign NCC-Sign NTRU+ Paloma REDOG SMAUG-T
  do
    [ -f unpacked-"$x".zip ] || (
      rm -rf "$x"
      mkdir -p "$x"
      ( cd "$x"
        unzip -q ../complete-"$x".zip
        for p in ../../patch-"$x"*
        do
          [ -f "$p" ] && patch -F 40 -p0 < "$p"
        done
      )
      mv complete-"$x".zip unpacked-"$x".zip
    )
  done
)

# ===== AIMer integration
# XXX: patches eliminate various TIMECOP complaints

(
  sourcetop='AIMer/240402_AIMer'
  for p in 128f 128s 192f 192s 256f 256s
  do
    targettop="$supercop/crypto_sign/aimer$p"
    # rm -rf "$targettop"
    mkdir -p "$targettop"
    (
      echo ref "$sourcetop"/Reference_Implementation
      echo opt "$sourcetop"/Optimized_Implementation
      echo aarch64 "$sourcetop"/Additional_Implementation/aarch64
      echo avx2 "$sourcetop"/Additional_Implementation/avx2
    ) |
    while read target source
    do
      x="$targettop/$target"
      [ -d "$x" ] && continue
      mkdir -p "$x"
      echo "integrating $x..."
      cp -pr "$source"/aimer$p/* "$x"
      cp -pr "$source"/aimer$p/shake/* "$x"
      echo '#include "randombytes.h"' > "$x/rng.h"
      rm "$x/rng.c"
      rm "$x/PQCgenKAT_sign.c"
      [ "$target" = "aarch64" ] && echo aarch64 > "$x/architectures"
      [ "$target" = "avx2" ] && echo amd64 > "$x/architectures"
      sed -i '1a#include "crypto_sign.h"' "$x/api.c"
      sed -i '1a#define CRYPTO_BYTES crypto_sign_BYTES' "$x/api.c"
      sed -i 's_shake/KeccakHash.h_KeccakHash.h_' "$x/hash.h"
      touch "$x/goal-constbranch"
      touch "$x/goal-constindex"
    done
  done
)

# ===== HAETAE integration
# XXX: original HAETAE code has different API using size_t etc.

(
  sourcetop='HAETAE/HAETAE_Implementation_package/Implementation package/'
  for p in 2 3 5
  do
    targettop="$supercop/crypto_sign/haetae$p"
    # rm -rf "$targettop"
    mkdir -p "$targettop"
    (
      echo ref "$sourcetop"/reference_implementation
      echo opt "$sourcetop"/optimized_implementation
    ) |
    while read target source
    do
      x="$targettop/$target"
      [ -d "$x" ] && continue
      mkdir -p "$x"
      echo "integrating $x..."
      cp -pr "$source"/include/* "$x"
      cp -pr "$source"/src/* "$x"
      cp -pr "$source"/kat/api.h "$x"
      rm "$x/randombytes.c"
      rm "$x/randombytes.h"
      sed -i '2a#define HAETAE_MODE '$p "$x/config.h"
      sed -i '2a#include "crypto_sign.h"' "$x/sign.h"
      sed -i 's/#define crypto_sign_sign HAETAE_NAMESPACE(sign)/#define crypto_sign_sign crypto_sign/' "$x/sign.h"
      sed -i 's/#define crypto_sign_open HAETAE_NAMESPACE(open)//' "$x/sign.h"
      sed -i 's/#define crypto_sign_keypair HAETAE_NAMESPACE(keypair)//' "$x/sign.h"
      sed -i 's/uint8_t/unsigned char/g' "$x/sign.h"
      sed -i 's/uint8_t/unsigned char/g' "$x/sign.c"
      sed -i 's/uint8_t/unsigned char/g' "$x/api.h"
      sed -i 's/size_t/unsigned long long/g' "$x/sign.h"
      sed -i 's/size_t/unsigned long long/g' "$x/sign.c"
      sed -i 's/size_t/unsigned long long/g' "$x/api.h"
      sed -i 's/CRYPTO_BYTES/crypto_BYTES/g' "$x"/*
      sed -i 's/CRYPTO_SECRETKEYBYTES/crypto_SECRETKEYBYTES/g' "$x"/*
      sed -i 's/CRYPTO_PUBLICKEYBYTES/crypto_PUBLICKEYBYTES/g' "$x"/*
      sed -i '/#include "params.h"/ a#define CRYPTO_BYTES crypto_BYTES' "$x/api.h"
      sed -i '/#include "params.h"/ a#define CRYPTO_SECRETKEYBYTES crypto_SECRETKEYBYTES' "$x/api.h"
      sed -i '/#include "params.h"/ a#define CRYPTO_PUBLICKEYBYTES crypto_PUBLICKEYBYTES' "$x/api.h"
      touch "$x/goal-constbranch"
      touch "$x/goal-constindex"
    done
  done
)

# ===== MQ-Sign integration
# XXX: MQ-Sign's original crypto_sign_open() code doesn't allow sm overlapping m
# XXX: MQ-Sign's original crypto_sign_keypair() and crypto_sign() require seeds as input
# XXX: the original MQLR code does not work unless (pk,sk) is 0-initialized; the integration makes it work
# XXX: the original and integrated code will produce incorrect results for message lengths beyond 32 bits

(
  sourcetop='MQ-Sign/MQ-Sign_Implementation package_v2'
  ( echo mqsignlr MQLR
    echo mqsignrr MQRR
  ) |
  while read mq MQ
  do
    ( echo 2567246 _MQS256_72_46
      echo 25611272 _MQS256_112_72
      echo 25614896 _MQS256_148_96
    ) |
    while read p P
    do
      targettop="$supercop/crypto_sign/$mq$p"
      # rm -rf "$targettop"
      mkdir -p "$targettop"
      (
        echo opt "$sourcetop"/"$MQ"/optimized_implementation/MQSALG
        echo ref "$sourcetop"/"$MQ"/reference_implementation/MQSALG
      ) |
      while read target source
      do
        x="$targettop/$target"
        [ -d "$x" ] && continue
        mkdir -p "$x"
        echo "integrating $x..."
        cp -pr "$source"/* "$x"
        sed -i 's/#define _MQS256_72_46/#define '$P/ "$x/mqs_config.h"
        sed -i 's/\/\/#define _MQS256_112_72//' "$x/mqs_config.h"
        sed -i 's/\/\/#define _MQS256_148_96//' "$x/mqs_config.h"
        sed -i 's/randombytes(/unused_randombytes(/' "$x/rng.c"
        sed -i 's/crypto_sign_keypair/seeded_sign_keypair/' "$x"/api.h
        sed -i 's/crypto_sign_keypair/seeded_sign_keypair/' "$x"/sign.c
        sed -i 's/crypto_sign(/seeded_sign(/' "$x"/api.h "$x"/sign.c
        sed -i 's/crypto_sign_open(/unused_sign_open(/' "$x"/sign.c

        # labels followed by declarations are rejected by some compilers
        sed -i 's/rej:/rej: ;/' "$x"/mqs*.c
        sed -i 's/rej_out:/rej_out: ;/' "$x"/mqs*.c

        [ "$MQ" = "MQLR" ] && sed -i '/generate_keypair_mqlr/ i  memset(pk,0,_PUB_KEY_LEN);' "$x"/sign.c
        [ "$MQ" = "MQLR" ] && sed -i '/generate_keypair_mqlr/ i  memset(sk,0,_SEC_KEY_LEN);' "$x"/sign.c

        (
          verify=mqsc_verify
          [ "$target" = "opt" ] && verify=mqrr_verify
          [ "$MQ" = "MQLR" ] && verify=mqlr_verify
          echo '#include "crypto_sign.h"'
          echo '#include "randombytes.h"'
          echo '#include "api.h"'
          echo '#include "mqs.h"'
          echo '#include <string.h>'
          echo ''
          echo 'int crypto_sign_keypair(unsigned char *pk,unsigned char *sk) {'
          echo '  unsigned char sk_seed[LEN_SKSEED];'
          echo '  randombytes(sk_seed,sizeof sk_seed);'
          echo '  return seeded_sign_keypair(pk,sk,sk_seed);'
          echo '}'
          echo ''
          echo 'int crypto_sign(unsigned char *sm,unsigned long long *smlen,const unsigned char *m,unsigned long long mlen,const unsigned char *sk) {'
          echo '  unsigned char sign_seed[LEN_SKSEED];'
          echo '  unsigned char sign_salt[_SALT_SOURCE_LEN];'
          echo '  randombytes(sign_seed,sizeof sign_seed);'
          echo '  randombytes(sign_salt,sizeof sign_salt);'
          echo '  return seeded_sign(sm,smlen,m,mlen,sk,sign_seed,sign_salt);'
          echo '}'
          echo ''
          echo 'int crypto_sign_open(unsigned char *m,unsigned long long *mlen,const unsigned char *sm,unsigned long long smlen,const unsigned char *pk) {'
          echo '  if( _SIGNATURE_BYTE > smlen ) return -1;'
          echo '  mlen[0] = smlen-_SIGNATURE_BYTE;'
          echo '  if ('"$verify"'(sm, (uint32_t) mlen[0], sm + smlen - _SIGNATURE_BYTE, pk)) return -1;'
          echo '  memmove( m , sm , smlen-_SIGNATURE_BYTE );'
          echo '  return 0;'
          echo '}'
        ) > "$x"/wrapper.c
        touch "$x/goal-constbranch"
        touch "$x/goal-constindex"
      done
    done
  done
)

# ===== NCC-Sign integration
# XXX: secret-key sizes are different from documentation
# XXX: integration is specifically for NIMS_TRI_NTT_MODE and NIMS_TRI_USE_AES
# XXX: documentation shows other options; are those in the original software?
# XXX: supercop checksums show variations, so code is reading something it shouldn't
# XXX: original NCC-Sign code has different API using size_t etc.

(
  sourcetop='NCC-Sign/NCC-Sign_Implementation package_v2'
  for p in 1 3 5
  do
    targettop="$supercop/crypto_sign/nccsign$p"
    # rm -rf "$targettop"
    mkdir -p "$targettop"
    (
      echo ref "$sourcetop"/reference_implementation
      echo opt "$sourcetop"/optimized_implementation
    ) |
    while read target source
    do
      x="$targettop/$target"
      [ -d "$x" ] && continue
      mkdir -p "$x"
      echo "integrating $x..."
      cp -pr "$source"/* "$x"
      rm -rf "$x"/Keccak
      rm -r "$x"/test
      rm "$x/randombytes.c"
      rm "$x/randombytes.h"
      rm "$x/rng.c"
      rm "$x/rng.h"
      rm "$x/PQCgenKAT_sign.c"
      sed -i '2a#define NIMS_TRI_NTT_MODE '$p "$x/config.h"
      sed -i '2a#define NIMS_TRI_USE_AES' "$x/config.h"
      sed -i '2a#include "crypto_sign.h"' "$x/sign.h"
      sed -i 's/uint8_t/unsigned char/g' "$x/sign.h"
      sed -i 's/uint8_t/unsigned char/g' "$x/sign.c"
      sed -i 's/uint8_t/unsigned char/g' "$x/api.h"
      sed -i 's/size_t/unsigned long long/g' "$x/sign.h"
      sed -i 's/size_t/unsigned long long/g' "$x/sign.c"
      sed -i 's/size_t/unsigned long long/g' "$x/api.h"
      sed -i 's/CRYPTO_BYTES/crypto_BYTES/g' "$x"/*
      sed -i 's/CRYPTO_SECRETKEYBYTES/crypto_SECRETKEYBYTES/g' "$x"/*
      sed -i 's/CRYPTO_PUBLICKEYBYTES/crypto_PUBLICKEYBYTES/g' "$x"/*
      sed -i '/#include "params.h"/ a#define CRYPTO_BYTES crypto_BYTES' "$x/api.h"
      sed -i '/#include "params.h"/ a#define CRYPTO_SECRETKEYBYTES crypto_SECRETKEYBYTES' "$x/api.h"
      sed -i '/#include "params.h"/ a#define CRYPTO_PUBLICKEYBYTES crypto_PUBLICKEYBYTES' "$x/api.h"
      sed -i 's_Keccak/_libkeccak.a.headers/_' "$x/fips202.c"
      sed -i '/test.cpucycles.h/ d' "$x/sign.c"
      touch "$x/goal-constbranch"
      touch "$x/goal-constindex"
    done
  done
)

# ===== NTRU+ integration
# XXX: this integration is including only KEM, not PKE

(
  sourcetop='NTRU+/NTRU+_Implementation package_v2'
  for p in 576 768 864 1152
  do
    targettop="$supercop/crypto_kem/ntruplus$p"
    # rm -rf "$targettop"
    mkdir -p "$targettop"
    (
      echo ref "$sourcetop"/Reference_Implementation/crypto_kem/NTRU+KEM"$p"
      echo opt "$sourcetop"/Optimized_Implementation/crypto_kem/NTRU+KEM"$p"
      echo avx2 "$sourcetop"/Additional_Implementation/avx2/crypto_kem/NTRU+KEM"$p"
    ) |
    while read target source
    do
      x="$targettop/$target"
      [ -d "$x" ] && continue
      mkdir -p "$x"
      echo "integrating $x..."
      cp -pr "$source"/* "$x"
      [ "$target" = avx2 ] && cp -pr "$source"/asm/* "$x"
      rm -f "$x"/PQCgenKAT_kem.c
      rm -f "$x"/cpucycles.c
      rm -f "$x"/cpucycles.h
      rm -f "$x"/rng.c
      rm -f "$x"/rng.h
      rm -f "$x"/randombytes.c
      rm -f "$x"/randombytes.h
      rm -f "$x"/test.c
      sed -i '1a#include "crypto_kem.h"' "$x/kem.c"
      [ "$target" = "avx2" ] && echo amd64 > "$x/architectures"
      touch "$x/goal-constbranch"
      touch "$x/goal-constindex"
    done
  done
)

# ===== Paloma integration
# XXX: taking only w_openssl implementation
# XXX: original code has uninitialized hash output buffers in utility.c; integration fixes this
# XXX: original code has different API for tables; integration handles this as a constructor
# XXX: integration removes the weight test from the original code

(
  sourcetop='Paloma/Implementation package'
  for p in 128 192 256
  do
    targettop="$supercop/crypto_kem/paloma$p"
    # rm -rf "$targettop"
    (
      echo ref "$sourcetop"/reference_implementation/2r_paloma_opt_w_openssl
    ) |
    while read target source
    do
      x="$targettop/$target"
      [ -d "$x" ] && continue
      mkdir -p "$x"
      echo "integrating $x..."
      cp -p "$source"/api.h "$x"
      cp -p "$source"/config.h "$x"
      cp -p "$source"/gf_tab_gen.h "$x"
      cp -p "$source"/utility/*.h "$x"
      cp -p "$source"/utility/*.c "$x"
      cp -p "$source"/utility/include/*.h "$x"
      sed -i '/#ifndef CONFIG/ a#define PALOMA_MODE '$p "$x"/config.h
      sed -i '/#ifndef CONFIG/ a#define WORD 64' "$x"/config.h
      sed -i 's,\.\./config.h,config.h,' "$x"/*
      sed -i 's,\.\./api.h,api.h,' "$x"/*
      sed -i 's,\.\./gf_tab_gen\.h,gf_tab_gen.h,' "$x"/*
      sed -i 's_include/__' "$x"/*
      sed -i 's_utility/__' "$x"/*
      sed -i 's_\./rng\.h_randombytes.h_' "$x"/*
      rm -r "$x"/rng.c
      rm -r "$x"/rng.h
      sed -i '/lsh_digest/a    for (int i = 0;i < 32;++i) seed[i / WORD_BYTES] = 0;' "$x"/utility.c
      sed -i '1i#include "crypto_kem.h"' "$x/kem.c"
      sed -i '1i#include "config.h"' "$x"/*.c
      sed -i 's/crypto_kem_keypair/crypto_kem_keypair_usetables/g' "$x"/*
      sed -i 's/crypto_kem_dec/crypto_kem_dec_usetables/g' "$x"/*
      sed -i 's/!check_err_vec(e_hat)/0/' "$x"/decap.c
      echo '
static gf2m_tab gf2m_tables;

__attribute__((constructor))
static void precompute(void)
{
  gen_precomputation_tab(&gf2m_tables);
}

int crypto_kem_keypair(unsigned char *pk,unsigned char *sk)
{
  return crypto_kem_keypair_usetables(pk,sk,&gf2m_tables);
}

int crypto_kem_dec(unsigned char *ss,const unsigned char *c,const unsigned char *sk)
{
  return crypto_kem_dec_usetables(ss,c,sk,&gf2m_tables);
}
  ' >> "$x"/kem.c
      touch "$x/goal-constbranch"
      touch "$x/goal-constindex"
    done
  done
)

# ===== REDOG integration
# XXX: original code seems to be in progress
# XXX: this is a preliminary integration, not working

(
  sourcetop='REDOG/Implementation package_REDOG'
  for p in 1 2 3
  do
    targettop="$supercop/crypto_kem/redog$p"
    # rm -rf "$targettop"
    (
      echo ref "$sourcetop"/reference_implementation/REDOG_C
    ) |
    while read target source
    do
      x="$targettop/$target"
      [ -d "$x" ] && continue
      mkdir -p "$x"
      echo "integrating $x..."
      for s in "$source"/*.[ch]
      do
        t=`echo "$s" | sed 's_.*/__' | tr ' ' '_'`
        sed 's/\xef\xbb\xbf//' < "$s" | tr -d '\015' > "$x/$t"
      done
      cp "$source"/ref/api.h "$x"/api.h
      rm -r "$x"/2*
      cp "$x"/finiteFIeld.h "$x"/finiteField.h
      sed -i 's/<intrin.h>/<immintrin.h>/' "$x"/rbc_lr.h
      touch "$x/goal-constbranch"
      touch "$x/goal-constindex"
    done
  done
)

# ===== SMAUG-T integration
# XXX: documented sk sizes are missing necessary pk copy in sk
# XXX: is additional_implementation also usable? documentation mentions TiMER

(
  sourcetop='SMAUG-T/SMAUG-T_Implementation package_v2'
  for p in 1 3 5
  do
    targettop="$supercop/crypto_kem/smaugt$p"
    # rm -rf "$targettop"
    (
      echo ref "$sourcetop"/reference_implementation
      echo opt "$sourcetop"/optimized_implementation/kem
    ) |
    while read target source
    do
      x="$targettop/$target"
      [ -d "$x" ] && continue
      mkdir -p "$x"
      echo "integrating $x..."
      cp "$source"/src/*.c "$x"
      [ "$target" = opt ] && cp "$source"/src/keccak/* "$x"
      cp "$source"/include/*.h "$x"
      [ "$target" = opt ] && cp "$source"/include/keccak/* "$x"
      rm "$x"/randombytes.c
      rm "$x"/randombytes.h
      rm "$x"/rng.c
      rm "$x"/rng.h
      sed -i '/#define SMAUG_PARAMETERS_H/ a#define SMAUG_MODE '$p "$x"/parameters.h
      sed -i 's/CRYPTO_BYTES/crypto_BYTES/g' "$x"/*
      sed -i 's/crypto_kem_keypair/crypto_kem_keypair_partial/g' "$x"/*
      sed -i 's/int crypto_kem_keypair/void crypto_kem_keypair/g' "$x"/*
      sed -i 's_#include "\.\./_#include "_' "$x"/*
      sed -i 's/int cryptolab_smaug1_crypto_kem_keypair_partial/void cryptolab_smaug1_crypto_kem_keypair_partial/g' "$x"/*
      sed -i 's/int cryptolab_smaug3_crypto_kem_keypair_partial/void cryptolab_smaug3_crypto_kem_keypair_partial/g' "$x"/*
      sed -i 's/int cryptolab_smaug5_crypto_kem_keypair_partial/void cryptolab_smaug5_crypto_kem_keypair_partial/g' "$x"/*
      (
        echo '#include "parameters.h"'
        echo '#define CRYPTO_BYTES crypto_BYTES'
        echo '#define CRYPTO_PUBLICKEYBYTES PUBLICKEY_BYTES'
        echo '#define CRYPTO_SECRETKEYBYTES (KEM_SECRETKEY_BYTES+PUBLICKEY_BYTES)'
        echo '#define CRYPTO_CIPHERTEXTBYTES CIPHERTEXT_BYTES'
      ) >> "$x"/api.h
      ( echo '#include <string.h>
#include "kem.h"
#include "crypto_kem.h"

int crypto_kem_keypair(
  unsigned char *pk,
  unsigned char *sk
)
{
  crypto_kem_keypair_partial(pk,sk);
  memcpy(sk+KEM_SECRETKEY_BYTES,pk,PUBLICKEY_BYTES);
  return 0;
}

int crypto_kem_enc(
  unsigned char *c,
  unsigned char *k,
  const unsigned char *pk
)
{
  return crypto_kem_encap(c,k,pk);
}

int crypto_kem_dec(
  unsigned char *k,
  const unsigned char *c,
  const unsigned char *sk
)
{
  return crypto_kem_decap(k,sk,sk+KEM_SECRETKEY_BYTES,c);
}
'
      ) >> "$x"/wrapper.c
      touch "$x/goal-constbranch"
      touch "$x/goal-constindex"
    done
  done
)

# ===== running supercop

(
  [ -d "$supercop"/bench ] || (
    cd "$supercop"
    chmod +t crypto_*/*/cryptopp
    chmod +t crypto_*/*/rust*
    ./do-part init || :
    ./do-part keccak || :
    ./do-part crypto_hashblocks sha256 || :
    ./do-part crypto_hashblocks sha512 || :
    ./do-part crypto_hash sha256 || :
    ./do-part crypto_hash sha384 || :
    ./do-part crypto_hash sha512 || :
    ./do-part crypto_hash sha3512 || :
    ./do-part crypto_stream chacha20 || :
    ./do-part crypto_rng chacha20 || :
  )

  (
    echo crypto_sign aimer128f
    echo crypto_sign aimer128s
    echo crypto_sign aimer192f
    echo crypto_sign aimer192s
    echo crypto_sign aimer256f
    echo crypto_sign aimer256s
    echo crypto_sign haetae2
    echo crypto_sign haetae3
    echo crypto_sign haetae5
    echo crypto_sign mqsignlr2567246
    echo crypto_sign mqsignlr25611272
    echo crypto_sign mqsignlr25614896
    echo crypto_sign mqsignrr2567246
    echo crypto_sign mqsignrr25611272
    echo crypto_sign mqsignrr25614896
    echo crypto_sign nccsign1
    echo crypto_sign nccsign3
    echo crypto_sign nccsign5
    echo crypto_kem ntruplus576
    echo crypto_kem ntruplus768
    echo crypto_kem ntruplus864
    echo crypto_kem ntruplus1152
    echo crypto_kem paloma128
    echo crypto_kem paloma192
    echo crypto_kem paloma256
    echo crypto_kem redog1
    echo crypto_kem redog2
    echo crypto_kem redog3
    echo crypto_kem smaugt1
    echo crypto_kem smaugt3
    echo crypto_kem smaugt5
  ) |
  while read o p
  do
    [ -f bench-"$p" ] || (
      cd "$supercop"
      ./do-part "$o" "$p" || :
      cp bench/*/data ../bench-"$p"
    )
    [ -f timecop-"$p" ] || (
      cd "$supercop"
      env TIMECOP=1 ./do-part "$o" "$p" || :
      cp bench/*/data ../timecop-"$p"
    )
    python3 -c '

import sys

o = sys.argv[1]
p = sys.argv[2]

pkbytes = None
skbytes = None
outputbytes = None
ctbytes = None
sigbytes = []
keypair_cycles = []
cycles = []
open_cycles = []
enc_cycles = []
dec_cycles = []
checksums = []
tries = []

for line in sys.stdin:
  line = line.split()
  if len(line) < 8: continue
  if line[6] == "publickeybytes": pkbytes = line[7]
  if line[6] == "secretkeybytes": skbytes = line[7]
  if line[6] == "outputbytes": outputbytes = line[7]
  if line[6] == "ciphertextbytes": ctbytes = line[7]
  if line[6] == "bytes": sigbytes += [int(x)-int(line[7]) for x in line[9:]]
  if line[6] == "keypair_cycles": keypair_cycles += [int(x) for x in line[9:]]
  if line[6] == "cycles": cycles += [int(x) for x in line[9:]]
  if line[6] == "open_cycles": open_cycles += [int(x) for x in line[9:]]
  if line[6] == "enc_cycles": enc_cycles += [int(x) for x in line[9:]]
  if line[6] == "dec_cycles": dec_cycles += [int(x) for x in line[9:]]
  if line[6] == "try":
    checksums += [line[7]]
    tries += [(int(line[9]),line[12],line[13])]

def statistics(x):
  x = sorted(x)
  if x == []: return None
  if x[0] == x[-1]: return x[0]
  median = x[len(x)//2] # XXX: handle even cases
  q1 = x[len(x)//4] # XXX: handle other cases
  q3 = x[(3*len(x))//4] # XXX: handle other cases
  return f"{q1}...{median}...{q3}"

if o == "crypto_kem":
  print(p,"bytes","pk",pkbytes,"sk",skbytes,"ct",ctbytes,"shared",outputbytes)
else:
  print(p,"bytes","pk",pkbytes,"sk",skbytes,"sigbuf",outputbytes,"sig",statistics(sigbytes))
print(p,"keypair",statistics(keypair_cycles))
if o == "crypto_kem":
  print(p,"enc",statistics(enc_cycles))
  print(p,"dec",statistics(dec_cycles))
else:
  print(p,"sign",statistics(cycles))
  print(p,"open",statistics(open_cycles))
print(p,"checksums",statistics(checksums))
for c,opi,compiler in sorted(tries):
  print(p,"try",c,opi,compiler)

' "$o" "$p" < bench-"$p" > report-"$p"
  done
)
