import os, sys # Nice labels for algorithms of all kinds ALG_LABEL = { "AES_128_GCM_SHA256": "AES128", "AES_256_GCM_SHA384": "AES256", "CHACHA20_POLY1305_SHA256": "CHACHA20", "ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,ECDHE_RSA_WITH_AES_128_GCM_SHA256": "AES128", "ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,ECDHE_RSA_WITH_AES_256_GCM_SHA384": "AES256", "ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256": "CHACHA20", "prime256v1": "prime256v1", "rsa2048": "rsa2048", "rsa3072": "rsa3072", "rsa4096": "rsa4096", "X25519": "X25519", "SECP256R1": "SECP256R1", "SECP384R1": "SECP384R1" } # Nice labels for TLS versions using ciphers VER_LABEL = { "AES_128_GCM_SHA256": "1.3", "AES_256_GCM_SHA384": "1.3", "CHACHA20_POLY1305_SHA256": "1.3", "ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,ECDHE_RSA_WITH_AES_128_GCM_SHA256": "1.2", "ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,ECDHE_RSA_WITH_AES_256_GCM_SHA384": "1.2", "ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256": "1.2" } # Titles for measured quantities OBJ_TITLE = { "cpu": "CPU time", "energy": "energy consumption" } # Logfile column names COL = { "cpu": "cpu", "energy": "Wh", "cipher": "cipher", "cert": "alg", "kex": "kex" } # Physical units by object UNIT = { "cpu": "s", "energy": "W" } # Titles for criteria CRITERION_TITLE = { "cipher": "cipher", "cert": "signature algorithm", "kex": "key exchange" } # Where gnuplot files, data files and images are output PLOTS_DIR = "/dev/shm/plots" def gnuplot_histogram(**kwargs): cluster = "" for i in range(kwargs["nb_impls"]-1): cluster += """, "" using {}:xticlabels(1) title col""".format(i+4) f = open("{plots_dir}/{object}_by_{criterion}_{side}.gnuplot".format(plots_dir=PLOTS_DIR, **kwargs), "w") f.write("""\ set terminal pngcairo enhanced font "CMU Sans Serif,11" fontscale 1.0 size 800, 600 set output "{plots_dir}/{object}_by_{criterion}_{side}.png" set boxwidth 0.9 absolute set style fill solid 1.0 border lt -1 set style histogram clustered gap 1 title textcolor lt -1 set style data histograms set title font "CMU Sans Serif,12" "{object_title} by {criterion_title} ({side} side) ({unit})" set xtics border in scale 0,0 nomirror rotate by -45 autojustify set key fixed right top vertical Right noreverse noenhanced autotitle nobox set colorbox vertical origin screen 0.9, 0.2 size screen 0.05, 0.6 front noinvert bdefault set xrange [ * : * ] noreverse writeback plot \ newhistogram "", "{plots_dir}/{object}_by_{criterion}_{side}.dat" using 2:xticlabels(1) notitle col, \ newhistogram "", "{plots_dir}/{object}_by_{criterion}_{side}.dat" using 3:xticlabels(1) title col{cluster} """.format(plots_dir=PLOTS_DIR, cluster=cluster, **kwargs)) f.close() os.system("gnuplot {plots_dir}/{object}_by_{criterion}_{side}.gnuplot".format(plots_dir=PLOTS_DIR, **kwargs)) def make_plot(records, exp, criterion, side, obj): f = open(f"/dev/shm/plots/{obj}_by_{criterion}_{side}.dat", "w") ciphers = {} impls = [] plain_line = None idle_val = None for record in records: if record["exp"] == "idle": idle_val = float(record[COL[obj]]) / float(record["time"]) if record["exp"] != exp: continue if record["setup"] == "none": plain_line = "plain {}".format(float(record[COL[obj]]) - idle_val * float(record["time"])) if plain_line == None: return for record in records: if record["exp"] != exp: continue elif record["setup"] == side: if record[COL[criterion]] not in ciphers: ciphers[record[COL[criterion]]] = {} ciphers[record[COL[criterion]]][record["impl"]] = float(record[COL[obj]]) - idle_val * float(record["time"]) if record["impl"] not in impls: impls.append(record["impl"]) impls.sort() f.write("{} none {}\n".format(criterion, " ".join(impls))) f.write(plain_line+" -"*len(impls)+"\n") for cipher in ciphers: f.write("{}({}) - {}\n".format( ALG_LABEL[cipher], VER_LABEL[record["cipher"]], " ".join([ str(ciphers[cipher][impl]) for impl in impls ]), )) f.close() gnuplot_histogram(object=obj, criterion=criterion, side=side, object_title=OBJ_TITLE[obj], criterion_title=CRITERION_TITLE[criterion], unit=UNIT[obj], nb_impls=len(impls)) if __name__ == "__main__": logfile_name = sys.argv[1] logfile = open(logfile_name, "r") lines = logfile.readlines() logfile.close() colnames = lines[0].removesuffix("\n").split(" ") records = [] for line in lines[1:]: cols = line.removesuffix("\n").split(" ") record = {} for col in range(len(cols)): record[colnames[col]] = cols[col] records.append(record) os.makedirs("/dev/shm/plots", exist_ok=True) for side in ["client", "server"]: make_plot(records, "impl-cipher-ver", "cipher", side, "cpu") make_plot(records, "impl-cipher-ver", "cipher", side, "energy") make_plot(records, "impl-cert-ver", "cert", side, "cpu") make_plot(records, "impl-cert-ver", "cert", side, "energy") make_plot(records, "impl-kex-ver", "kex", side, "cpu") make_plot(records, "impl-kex-ver", "kex", side, "energy")