DF-3564 / sip_keyscan.c
/* * sip_keyscan.c -- demonstrate DF-3564: SipHash_SetKey() retains a verbatim * copy of the 128-bit key in stack local k[2] (sys/crypto/siphash/siphash.c:71) * after it returns, with no zeroization (contrast SipHash_End which does * bzero(ctx)). Same-source userland build of the kernel implementation. * * The scan uses an inline byte loop (no calls) so the comparison itself * cannot clobber the dead frame being inspected. */ #include <stdio.h> #include <string.h> #include <stdint.h> #include <stddef.h> #include <stdlib.h> #include <crypto/siphash/siphash.h> static unsigned char the_key[16]; static volatile uint64_t sink; __attribute__((noinline)) static void do_sip_setkey(void) { SIPHASH_CTX ctx; SipHash24_Init(&ctx); SipHash_SetKey(&ctx, the_key); /* return immediately: nothing else may run at this stack depth */ sink = ctx.v[0]; } static int key_at(const unsigned char *p) { int j; for (j = 0; j < 16; j++) if (p[j] != the_key[j]) return 0; return 1; } int main(void) { unsigned char probe[64]; unsigned char *p, *start, *low; int found = 0; int i; for (i = 0; i < 16; i++) the_key[i] = (unsigned char)(0xA0 + i); memset(probe, 0, sizeof probe); do_sip_setkey(); /* the key copy must be dead after this */ start = (unsigned char *)&probe; low = start - 32768; /* callee frames live below us */ for (p = start - 16; p >= low; p--) { if (key_at(p)) { /* inline compare: no call frame */ found = 1; printf("RETAINED: verbatim 16-byte key found on the " "dead stack, offset -%td below caller frame\n", (ptrdiff_t)(start - p)); break; } } if (!found) printf("NOT FOUND: key copy was not retained on stack\n"); printf("%s: raw key bytes %s the stack after SipHash_SetKey " "returned\n", found ? "DF-3564 CONFIRMED" : "not confirmed", found ? "persist on" : "do not persist on"); return found ? 0 : 1; } |