-rw-r--r-- 9041 lib25519-20220726/command/lib25519-speed.c raw
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include <time.h> #include <sys/time.h> #include <sys/types.h> #include <sys/resource.h> #include "cpucycles.h" /* -lcpucycles */ #include "lib25519.h" /* -l25519 */ #include "randombytes.h" /* -lrandombytes_kernel */ #include "limits.inc" static unsigned char *alignedcalloc(unsigned long long len) { unsigned char *x = (unsigned char *) calloc(1,len + 128); if (!x) abort(); /* will never deallocate so shifting is ok */ x += 63 & (-(unsigned long) x); return x; } #define TIMINGS 15 static long long t[TIMINGS+1]; static void t_print(const char *op,long long impl,long long len) { long long median = 0; printf("%s",op); if (impl >= 0) printf(" %lld",impl); else printf(" default"); printf(" %lld",len); for (long long i = 0;i < TIMINGS;++i) t[i] = t[i+1]-t[i]; for (long long j = 0;j < TIMINGS;++j) { long long belowj = 0; long long abovej = 0; for (long long i = 0;i < TIMINGS;++i) if (t[i] < t[j]) ++belowj; for (long long i = 0;i < TIMINGS;++i) if (t[i] > t[j]) ++abovej; if (belowj*2 < TIMINGS && abovej*2 < TIMINGS) { median = t[j]; break; } } printf(" %lld ",median); for (long long i = 0;i < TIMINGS;++i) printf("%+lld",t[i]-median); printf("\n"); fflush(stdout); } #define MAXTEST_BYTES 65536 static void measure_cpucycles(void) { printf("cpucycles default persecond %lld\n",cpucycles_persecond()); printf("cpucycles default implementation %s\n",cpucycles_implementation()); for (long long i = 0;i <= TIMINGS;++i) t[i] = cpucycles(); t_print("cpucycles",-1,0); } static void measure_randombytes(void) { unsigned char *m = alignedcalloc(MAXTEST_BYTES); long long mlen = 0; while (mlen < MAXTEST_BYTES) { for (long long i = 0;i <= TIMINGS;++i) { t[i] = cpucycles(); randombytes(m,mlen); } t_print("randombytes",-1,mlen); mlen += 1+mlen/2; } } static void measure_verify(void) { unsigned char *x = alignedcalloc(lib25519_verify_BYTES); unsigned char *y = alignedcalloc(lib25519_verify_BYTES); for (long long impl = -1;impl < lib25519_numimpl_verify();++impl) { int (*crypto_verify)(const unsigned char *,const unsigned char *); if (impl >= 0) { crypto_verify = lib25519_dispatch_verify(impl); printf("verify %lld implementation %s compiler %s\n",impl,lib25519_dispatch_verify_implementation(impl),lib25519_dispatch_verify_compiler(impl)); } else { crypto_verify = lib25519_verify; printf("verify default implementation %s compiler %s\n",lib25519_verify_implementation(),lib25519_verify_compiler()); } randombytes(x,lib25519_verify_BYTES); randombytes(y,lib25519_verify_BYTES); for (long long i = 0;i <= TIMINGS;++i) { t[i] = cpucycles(); crypto_verify(x,y); } t_print("verify",impl,lib25519_verify_BYTES); } } static void measure_hashblocks(void) { unsigned char *h = alignedcalloc(lib25519_hashblocks_STATEBYTES); unsigned char *m = alignedcalloc(MAXTEST_BYTES); for (long long impl = -1;impl < lib25519_numimpl_hashblocks();++impl) { int (*crypto_hashblocks)(unsigned char *,const unsigned char *,long long); if (impl >= 0) { crypto_hashblocks = lib25519_dispatch_hashblocks(impl); printf("hashblocks %lld implementation %s compiler %s\n",impl,lib25519_dispatch_hashblocks_implementation(impl),lib25519_dispatch_hashblocks_compiler(impl)); } else { crypto_hashblocks = lib25519_hashblocks; printf("hashblocks default implementation %s compiler %s\n",lib25519_hashblocks_implementation(),lib25519_hashblocks_compiler()); } long long mlen = 0; while (mlen < MAXTEST_BYTES) { randombytes(m,mlen); for (long long i = 0;i <= TIMINGS;++i) { t[i] = cpucycles(); crypto_hashblocks(h,m,mlen); } t_print("hashblocks",impl,mlen); mlen += 1+mlen/2; } } } static void measure_hash(void) { unsigned char *h = alignedcalloc(lib25519_hash_BYTES); unsigned char *m = alignedcalloc(MAXTEST_BYTES); for (long long impl = -1;impl < lib25519_numimpl_hash();++impl) { void (*crypto_hash)(unsigned char *,const unsigned char *,long long); if (impl >= 0) { crypto_hash = lib25519_dispatch_hash(impl); printf("hash %lld implementation %s compiler %s\n",impl,lib25519_dispatch_hash_implementation(impl),lib25519_dispatch_hash_compiler(impl)); } else { crypto_hash = lib25519_hash; printf("hash default implementation %s compiler %s\n",lib25519_hash_implementation(),lib25519_hash_compiler()); } long long mlen = 0; while (mlen < MAXTEST_BYTES) { randombytes(m,mlen); for (long long i = 0;i <= TIMINGS;++i) { t[i] = cpucycles(); crypto_hash(h,m,mlen); } t_print("hash",impl,mlen); mlen += 1+mlen/2; } } } static void measure_dh(void) { unsigned char *pka = alignedcalloc(lib25519_dh_PUBLICKEYBYTES); unsigned char *ska = alignedcalloc(lib25519_dh_SECRETKEYBYTES); unsigned char *pkb = alignedcalloc(lib25519_dh_PUBLICKEYBYTES); unsigned char *skb = alignedcalloc(lib25519_dh_SECRETKEYBYTES); unsigned char *ka = alignedcalloc(lib25519_dh_BYTES); for (long long impl = -1;impl < lib25519_numimpl_dh();++impl) { void (*crypto_dh)(unsigned char *,const unsigned char *,const unsigned char *); void (*crypto_dh_keypair)(unsigned char *,unsigned char *); if (impl >= 0) { crypto_dh_keypair = lib25519_dispatch_dh_keypair(impl); crypto_dh = lib25519_dispatch_dh(impl); printf("dh %lld implementation %s compiler %s\n",impl,lib25519_dispatch_dh_implementation(impl),lib25519_dispatch_dh_compiler(impl)); } else { crypto_dh_keypair = lib25519_dh_keypair; crypto_dh = lib25519_dh; printf("dh default implementation %s compiler %s\n",lib25519_dh_implementation(),lib25519_dh_compiler()); } for (long long i = 0;i <= TIMINGS;++i) { t[i] = cpucycles(); crypto_dh_keypair(pka,ska); } t_print("dh_keypair",impl,lib25519_dh_PUBLICKEYBYTES); crypto_dh_keypair(pkb,skb); for (long long i = 0;i <= TIMINGS;++i) { t[i] = cpucycles(); crypto_dh(ka,pkb,ska); } t_print("dh",impl,lib25519_dh_BYTES); } } static void measure_sign(void) { unsigned char *pk = alignedcalloc(lib25519_sign_PUBLICKEYBYTES); unsigned char *sk = alignedcalloc(lib25519_sign_SECRETKEYBYTES); unsigned char *m = alignedcalloc(MAXTEST_BYTES+lib25519_sign_BYTES); unsigned char *sm = alignedcalloc(MAXTEST_BYTES+lib25519_sign_BYTES); unsigned char *m2 = alignedcalloc(MAXTEST_BYTES+lib25519_sign_BYTES); long long mlen; long long smlen; long long m2len; randombytes(sm,MAXTEST_BYTES+lib25519_sign_BYTES); for (long long impl = -1;impl < lib25519_numimpl_sign();++impl) { void (*crypto_sign_keypair)(unsigned char *,unsigned char *); void (*crypto_sign)(unsigned char *,long long *,const unsigned char *,long long,const unsigned char *); int (*crypto_sign_open)(unsigned char *,long long *,const unsigned char *,long long,const unsigned char *); if (impl >= 0) { crypto_sign_keypair = lib25519_dispatch_sign_keypair(impl); crypto_sign = lib25519_dispatch_sign(impl); crypto_sign_open = lib25519_dispatch_sign_open(impl); printf("sign %lld implementation %s compiler %s\n",impl,lib25519_dispatch_sign_implementation(impl),lib25519_dispatch_sign_compiler(impl)); } else { crypto_sign_keypair = lib25519_sign_keypair; crypto_sign = lib25519_sign; crypto_sign_open = lib25519_sign_open; printf("sign default implementation %s compiler %s\n",lib25519_sign_implementation(),lib25519_sign_compiler()); } for (long long i = 0;i <= TIMINGS;++i) { t[i] = cpucycles(); crypto_sign_keypair(pk,sk); } t_print("sign_keypair",impl,lib25519_sign_PUBLICKEYBYTES); mlen = 0; while (mlen <= MAXTEST_BYTES) { randombytes(m,mlen); for (long long i = 0;i <= TIMINGS;++i) { t[i] = cpucycles(); crypto_sign(sm,&smlen,m,mlen,sk); } t_print("sign",impl,mlen); mlen += 1+mlen/4; } mlen = 0; while (mlen <= MAXTEST_BYTES) { randombytes(m,mlen); lib25519_sign(sm,&smlen,m,mlen,sk); for (long long i = 0;i <= TIMINGS;++i) { t[i] = cpucycles(); crypto_sign_open(m2,&m2len,sm,smlen,pk); } t_print("sign_open",impl,mlen); // this is, in principle, not a test program // but some checks here help validate the data flow above assert(m2len == mlen); assert(!memcmp(m,m2,mlen)); mlen += 1+mlen/4; } } } #include "print_cpuid.inc" int main() { printf("lib25519 version %s\n",lib25519_version); printf("lib25519 arch %s\n",lib25519_arch); print_cpuid(); measure_cpucycles(); measure_randombytes(); limits(); measure_verify(); measure_hashblocks(); measure_hash(); measure_dh(); measure_sign(); return 0; }