vestigia

Detect where execution depends on secrets.
git clone git://git.ppad.tech/vestigia.git
Log | Files | Refs | README | LICENSE

harness.c (2749B)


      1 /*
      2  * Penumbra's three secret-key roots under vestigia: each call takes
      3  * fresh random secrets, marked secret before the call, with the
      4  * outputs Penumbra reveals marked public after it.
      5  *
      6  * usage: harness ROOT [RUNS [SEED]]
      7  *   ROOT is public_key, key_agreement, or spend_auth_sign
      8  *   SEED (16 hex digits) seeds the secrets alone; public inputs come
      9  *   from a fixed stream, so runs that differ in SEED differ only in
     10  *   their secrets.
     11  */
     12 #include <stdint.h>
     13 #include <stdio.h>
     14 #include <stdlib.h>
     15 #include <string.h>
     16 
     17 #include "vestigia.h"
     18 
     19 void penumbra_audit_public_key(uint8_t *ws);
     20 void penumbra_audit_key_agreement(uint8_t *ws);
     21 void penumbra_audit_spend_auth_sign(uint8_t *ws);
     22 
     23 static uint64_t secrets = 0x9e3779b97f4a7c15ULL;
     24 static uint64_t publics = 0x0123456789abcdefULL;
     25 
     26 static uint64_t splitmix(uint64_t *state) {
     27   uint64_t z = (*state += 0x9e3779b97f4a7c15ULL);
     28   z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9ULL;
     29   z = (z ^ (z >> 27)) * 0x94d049bb133111ebULL;
     30   return z ^ (z >> 31);
     31 }
     32 
     33 static void fill(uint64_t *state, uint8_t *p, size_t n) {
     34   for (size_t i = 0; i < n; i++) p[i] = (uint8_t)splitmix(state);
     35 }
     36 
     37 /* a canonical scalar: random little-endian bytes with the top byte
     38  * cleared, below the decaf377 scalar modulus */
     39 static void scalar(uint64_t *state, uint8_t *p) {
     40   fill(state, p, 32);
     41   p[31] = 0;
     42 }
     43 
     44 static void public_key(void) {
     45   uint8_t ws[64];
     46   scalar(&secrets, ws);
     47   vestigia_secret(ws, 32);
     48   penumbra_audit_public_key(ws);
     49   vestigia_public(ws + 32, 32);
     50 }
     51 
     52 static void key_agreement(void) {
     53   uint8_t peer[64];
     54   uint8_t ws[96];
     55   scalar(&publics, peer);
     56   penumbra_audit_public_key(peer);
     57   scalar(&secrets, ws);
     58   memcpy(ws + 32, peer + 32, 32);
     59   vestigia_secret(ws, 32);
     60   penumbra_audit_key_agreement(ws);
     61 }
     62 
     63 static void spend_auth_sign(void) {
     64   uint8_t ws[208];
     65   scalar(&secrets, ws);
     66   fill(&secrets, ws + 32, 80);
     67   fill(&publics, ws + 112, 32);
     68   /* the key and the signing randomness are secret; the message is
     69    * public */
     70   vestigia_secret(ws, 112);
     71   penumbra_audit_spend_auth_sign(ws);
     72   vestigia_public(ws + 144, 64);
     73 }
     74 
     75 int main(int argc, char **argv) {
     76   if (argc < 2) {
     77     fprintf(stderr, "usage: harness ROOT [RUNS]\n");
     78     return 2;
     79   }
     80   int runs = argc > 2 ? atoi(argv[2]) : 4;
     81   if (argc > 3) secrets = strtoull(argv[3], NULL, 16);
     82   void (*root)(void) = NULL;
     83   if (strcmp(argv[1], "public_key") == 0) root = public_key;
     84   else if (strcmp(argv[1], "key_agreement") == 0) root = key_agreement;
     85   else if (strcmp(argv[1], "spend_auth_sign") == 0)
     86     root = spend_auth_sign;
     87   if (root == NULL) {
     88     fprintf(stderr, "unknown root: %s\n", argv[1]);
     89     return 2;
     90   }
     91   for (int i = 0; i < runs; i++) root();
     92   printf("%s: %d run(s)\n", argv[1], runs);
     93   return 0;
     94 }