/* ----- sign/ed25519, derived from supercop/crypto_sign/try.c */ #include #include #include #include #include #include "lib25519_test.h" #define fail ((ok = 0),printf) static const char *sign_ed25519_checksums[] = { "ce11fd7c1eac4dd0bc5eec49b26ad1e91aef696fae50ce377dbd806dc394da01", "2ed857f17c917a8185e6c296303a11772ae45683a5e7cb5b095489bad65fffde", } ; static void (*crypto_sign_keypair)(unsigned char *,unsigned char *); static void (*crypto_sign)(unsigned char *,long long *,const unsigned char *,long long,const unsigned char *); static int (*crypto_sign_open)(unsigned char *,long long *,const unsigned char *,long long,const unsigned char *); #define crypto_sign_SECRETKEYBYTES lib25519_sign_ed25519_SECRETKEYBYTES #define crypto_sign_PUBLICKEYBYTES lib25519_sign_ed25519_PUBLICKEYBYTES #define crypto_sign_BYTES lib25519_sign_ed25519_BYTES static void *storage_sign_ed25519_p; static unsigned char *test_sign_ed25519_p; static void *storage_sign_ed25519_s; static unsigned char *test_sign_ed25519_s; static void *storage_sign_ed25519_m; static unsigned char *test_sign_ed25519_m; static void *storage_sign_ed25519_c; static unsigned char *test_sign_ed25519_c; static void *storage_sign_ed25519_t; static unsigned char *test_sign_ed25519_t; static void *storage_sign_ed25519_p2; static unsigned char *test_sign_ed25519_p2; static void *storage_sign_ed25519_s2; static unsigned char *test_sign_ed25519_s2; static void *storage_sign_ed25519_m2; static unsigned char *test_sign_ed25519_m2; static void *storage_sign_ed25519_c2; static unsigned char *test_sign_ed25519_c2; static void *storage_sign_ed25519_t2; static unsigned char *test_sign_ed25519_t2; static void test_sign_ed25519_impl(long long impl) { unsigned char *p = test_sign_ed25519_p; unsigned char *s = test_sign_ed25519_s; unsigned char *m = test_sign_ed25519_m; unsigned char *c = test_sign_ed25519_c; unsigned char *t = test_sign_ed25519_t; unsigned char *p2 = test_sign_ed25519_p2; unsigned char *s2 = test_sign_ed25519_s2; unsigned char *m2 = test_sign_ed25519_m2; unsigned char *c2 = test_sign_ed25519_c2; unsigned char *t2 = test_sign_ed25519_t2; long long plen = crypto_sign_PUBLICKEYBYTES; long long slen = crypto_sign_SECRETKEYBYTES; long long mlen; long long clen; long long tlen; if (targeti && strcmp(targeti,".") && strcmp(targeti,lib25519_dispatch_sign_ed25519_implementation(impl))) return; if (targetn && atol(targetn) != impl) return; if (impl >= 0) { crypto_sign_keypair = lib25519_dispatch_sign_ed25519_keypair(impl); crypto_sign = lib25519_dispatch_sign_ed25519(impl); crypto_sign_open = lib25519_dispatch_sign_ed25519_open(impl); printf("sign_ed25519 %lld implementation %s compiler %s\n",impl,lib25519_dispatch_sign_ed25519_implementation(impl),lib25519_dispatch_sign_ed25519_compiler(impl)); } else { crypto_sign_keypair = lib25519_sign_ed25519_keypair; crypto_sign = lib25519_sign_ed25519; crypto_sign_open = lib25519_sign_ed25519_open; printf("sign_ed25519 selected implementation %s compiler %s\n",lib25519_sign_ed25519_implementation(),lib25519_sign_ed25519_compiler()); } for (long long checksumbig = 0;checksumbig < 2;++checksumbig) { long long loops = checksumbig ? 64 : 8; long long maxtest = checksumbig ? 4096 : 128; checksum_clear(); for (long long loop = 0;loop < loops;++loop) { int result; mlen = myrandom() % (maxtest + 1); output_prepare(p2,p,plen); output_prepare(s2,s,slen); crypto_sign_keypair(p,s); public(p,plen); public(s,slen); checksum(p,plen); checksum(s,slen); output_compare(p2,p,plen,"crypto_sign_keypair"); output_compare(s2,s,slen,"crypto_sign_keypair"); clen = mlen + crypto_sign_BYTES; output_prepare(c2,c,clen); input_prepare(m2,m,mlen); memcpy(s2,s,slen); double_canary(s2,s,slen); secret(m,mlen); secret(s,slen); crypto_sign(c,&clen,m,mlen,s); public(m,mlen); public(s,slen); public(c,clen); if (clen < mlen) fail("failure: crypto_sign returns smaller output than input\n"); if (clen > mlen + crypto_sign_BYTES) fail("failure: crypto_sign returns more than crypto_sign_BYTES extra bytes\n"); checksum(c,clen); output_compare(c2,c,clen,"crypto_sign"); input_compare(m2,m,mlen,"crypto_sign"); input_compare(s2,s,slen,"crypto_sign"); tlen = clen; output_prepare(t2,t,tlen); memcpy(c2,c,clen); double_canary(c2,c,clen); memcpy(p2,p,plen); double_canary(p2,p,plen); public(c,clen); public(p,plen); result = crypto_sign_open(t,&tlen,c,clen,p); public(&result,sizeof result); if (result != 0) fail("failure: crypto_sign_open returns nonzero\n"); public(c,clen); public(p,plen); public(t,tlen); if (tlen != mlen) fail("failure: crypto_sign_open does not match mlen\n"); if (memcmp(t,m,mlen) != 0) fail("failure: crypto_sign_open does not match m\n"); checksum(t,tlen); output_compare(t2,t,clen,"crypto_sign_open"); input_compare(c2,c,clen,"crypto_sign_open"); input_compare(p2,p,plen,"crypto_sign_open"); double_canary(t2,t,tlen); double_canary(c2,c,clen); double_canary(p2,p,plen); public(c2,clen); public(p2,plen); result = crypto_sign_open(t2,&tlen,c2,clen,p2); public(&result,sizeof result); if (result != 0) fail("failure: crypto_sign_open returns nonzero\n"); public(c2,clen); public(p2,plen); public(t2,tlen); if (memcmp(t2,t,tlen) != 0) fail("failure: crypto_sign_open is nondeterministic\n"); double_canary(t2,t,tlen); double_canary(c2,c,clen); double_canary(p2,p,plen); public(c2,clen); public(p,plen); result = crypto_sign_open(c2,&tlen,c2,clen,p); public(&result,sizeof result); if (result != 0) fail("failure: crypto_sign_open with c=t overlap returns nonzero\n"); public(c2,tlen); public(p,plen); if (memcmp(c2,t,tlen) != 0) fail("failure: crypto_sign_open does not handle c=t overlap\n"); memcpy(c2,c,clen); public(c,clen); public(p2,plen); result = crypto_sign_open(p2,&tlen,c,clen,p2); public(&result,sizeof result); if (result != 0) fail("failure: crypto_sign_open with p=t overlap returns nonzero\n"); public(p2,tlen); public(c,clen); if (memcmp(p2,t,tlen) != 0) fail("failure: crypto_sign_open does not handle p=t overlap\n"); memcpy(p2,p,plen); c[myrandom() % clen] += 1 + (myrandom() % 255); if (crypto_sign_open(t,&tlen,c,clen,p) == 0) if ((tlen != mlen) || (memcmp(t,m,mlen) != 0)) fail("failure: crypto_sign_open allows trivial forgeries\n"); c[myrandom() % clen] += 1 + (myrandom() % 255); if (crypto_sign_open(t,&tlen,c,clen,p) == 0) if ((tlen != mlen) || (memcmp(t,m,mlen) != 0)) fail("failure: crypto_sign_open allows trivial forgeries\n"); c[myrandom() % clen] += 1 + (myrandom() % 255); if (crypto_sign_open(t,&tlen,c,clen,p) == 0) if ((tlen != mlen) || (memcmp(t,m,mlen) != 0)) fail("failure: crypto_sign_open allows trivial forgeries\n"); } checksum_expected(sign_ed25519_checksums[checksumbig]); } } void test_sign_ed25519(void) { long long maxalloc = 0; if (targeto && strcmp(targeto,"sign")) return; if (targetp && strcmp(targetp,"ed25519")) return; storage_sign_ed25519_p = callocplus(4096+crypto_sign_BYTES+crypto_sign_PUBLICKEYBYTES+crypto_sign_SECRETKEYBYTES); test_sign_ed25519_p = aligned(storage_sign_ed25519_p,4096+crypto_sign_BYTES+crypto_sign_PUBLICKEYBYTES+crypto_sign_SECRETKEYBYTES); if (4096+crypto_sign_BYTES+crypto_sign_PUBLICKEYBYTES+crypto_sign_SECRETKEYBYTES > maxalloc) maxalloc = 4096+crypto_sign_BYTES+crypto_sign_PUBLICKEYBYTES+crypto_sign_SECRETKEYBYTES; storage_sign_ed25519_s = callocplus(4096+crypto_sign_BYTES+crypto_sign_PUBLICKEYBYTES+crypto_sign_SECRETKEYBYTES); test_sign_ed25519_s = aligned(storage_sign_ed25519_s,4096+crypto_sign_BYTES+crypto_sign_PUBLICKEYBYTES+crypto_sign_SECRETKEYBYTES); if (4096+crypto_sign_BYTES+crypto_sign_PUBLICKEYBYTES+crypto_sign_SECRETKEYBYTES > maxalloc) maxalloc = 4096+crypto_sign_BYTES+crypto_sign_PUBLICKEYBYTES+crypto_sign_SECRETKEYBYTES; storage_sign_ed25519_m = callocplus(4096+crypto_sign_BYTES+crypto_sign_PUBLICKEYBYTES+crypto_sign_SECRETKEYBYTES); test_sign_ed25519_m = aligned(storage_sign_ed25519_m,4096+crypto_sign_BYTES+crypto_sign_PUBLICKEYBYTES+crypto_sign_SECRETKEYBYTES); if (4096+crypto_sign_BYTES+crypto_sign_PUBLICKEYBYTES+crypto_sign_SECRETKEYBYTES > maxalloc) maxalloc = 4096+crypto_sign_BYTES+crypto_sign_PUBLICKEYBYTES+crypto_sign_SECRETKEYBYTES; storage_sign_ed25519_c = callocplus(4096+crypto_sign_BYTES+crypto_sign_PUBLICKEYBYTES+crypto_sign_SECRETKEYBYTES); test_sign_ed25519_c = aligned(storage_sign_ed25519_c,4096+crypto_sign_BYTES+crypto_sign_PUBLICKEYBYTES+crypto_sign_SECRETKEYBYTES); if (4096+crypto_sign_BYTES+crypto_sign_PUBLICKEYBYTES+crypto_sign_SECRETKEYBYTES > maxalloc) maxalloc = 4096+crypto_sign_BYTES+crypto_sign_PUBLICKEYBYTES+crypto_sign_SECRETKEYBYTES; storage_sign_ed25519_t = callocplus(4096+crypto_sign_BYTES+crypto_sign_PUBLICKEYBYTES+crypto_sign_SECRETKEYBYTES); test_sign_ed25519_t = aligned(storage_sign_ed25519_t,4096+crypto_sign_BYTES+crypto_sign_PUBLICKEYBYTES+crypto_sign_SECRETKEYBYTES); if (4096+crypto_sign_BYTES+crypto_sign_PUBLICKEYBYTES+crypto_sign_SECRETKEYBYTES > maxalloc) maxalloc = 4096+crypto_sign_BYTES+crypto_sign_PUBLICKEYBYTES+crypto_sign_SECRETKEYBYTES; storage_sign_ed25519_p2 = callocplus(maxalloc); test_sign_ed25519_p2 = aligned(storage_sign_ed25519_p2,4096+crypto_sign_BYTES+crypto_sign_PUBLICKEYBYTES+crypto_sign_SECRETKEYBYTES); storage_sign_ed25519_s2 = callocplus(maxalloc); test_sign_ed25519_s2 = aligned(storage_sign_ed25519_s2,4096+crypto_sign_BYTES+crypto_sign_PUBLICKEYBYTES+crypto_sign_SECRETKEYBYTES); storage_sign_ed25519_m2 = callocplus(maxalloc); test_sign_ed25519_m2 = aligned(storage_sign_ed25519_m2,4096+crypto_sign_BYTES+crypto_sign_PUBLICKEYBYTES+crypto_sign_SECRETKEYBYTES); storage_sign_ed25519_c2 = callocplus(maxalloc); test_sign_ed25519_c2 = aligned(storage_sign_ed25519_c2,4096+crypto_sign_BYTES+crypto_sign_PUBLICKEYBYTES+crypto_sign_SECRETKEYBYTES); storage_sign_ed25519_t2 = callocplus(maxalloc); test_sign_ed25519_t2 = aligned(storage_sign_ed25519_t2,4096+crypto_sign_BYTES+crypto_sign_PUBLICKEYBYTES+crypto_sign_SECRETKEYBYTES); for (long long offset = 0;offset < 2;++offset) { if (targetoffset && atol(targetoffset) != offset) continue; if (offset && valgrind) break; printf("sign_ed25519 offset %lld\n",offset); for (long long impl = -1;impl < lib25519_numimpl_sign_ed25519();++impl) forked(test_sign_ed25519_impl,impl); ++test_sign_ed25519_p; ++test_sign_ed25519_s; ++test_sign_ed25519_m; ++test_sign_ed25519_c; ++test_sign_ed25519_t; ++test_sign_ed25519_p2; ++test_sign_ed25519_s2; ++test_sign_ed25519_m2; ++test_sign_ed25519_c2; ++test_sign_ed25519_t2; } free(storage_sign_ed25519_t2); free(storage_sign_ed25519_c2); free(storage_sign_ed25519_m2); free(storage_sign_ed25519_s2); free(storage_sign_ed25519_p2); free(storage_sign_ed25519_t); free(storage_sign_ed25519_c); free(storage_sign_ed25519_m); free(storage_sign_ed25519_s); free(storage_sign_ed25519_p); } #undef crypto_sign_SECRETKEYBYTES #undef crypto_sign_PUBLICKEYBYTES #undef crypto_sign_BYTES