A quick word about “stack-use-after-scope”

Today I was implementing SipHash24 into nsb. Since nsb (unfortunately) still suffers from EVP/EVP_MD internally, I had to implement the siphash_init, siphash_update and siphash_final functions in addition to the one-shot function.

In SipHash, a MAC key is not optional, but required. So, in order to implement EVP_siphash, I had to create a dirty workaround for this issue.

I defined siphash_init this way:

int siphash_init(SIPHASH_CTX *ctx, const void *k, size_t hlen);

In case a nullptr is passed to k, which is very likely when using EVP_siphash or nsb_hash, a key is generated internally using the reference implementation:

  [...]
  if (!k) {
    u8 tmp_key[SIPHASH_KEY_SIZE]; // out-of-scope

    for (size_t i = 0; i < SIPHASH_KEY_SIZE; i++) {
      tmp_key[i] = i;
    }

    k = tmp_key;
  }

  [...]
  u64 k0 = U8TO64_LE((u8 *)k);
  [...]

Well, that blew up in my face when building with -fsanitize=address -fsanitize-address-use-after-scope, which is part of my default FLAGS for DEBUG builds (see https://cgit.xcx.cc/curve4q/tree/CMakeLists.txt for example).

I was staring at the code, not “getting it” at first. I took a quick look at Google, only to find out most people don’t really know what’s the issue here. So I talked to a fellow channel inmate on IRC, and he quickly pointed out the issue at hand (thanks Gert):

I was using k pointing to an address at the stack, which was created “out of scope” (within an if()), so it does no longer belong to “me”.

So, if you ever encounter this issue, make sure the variable you’re accessing is properly declared within the same scope as the accessor. If you overwrite a variable within a different scope, make sure the variable you’re overwriting the original variable with is declared within the same scope, too:

  [...]
  u8 tmp_key[SIPHASH_KEY_SIZE]; // same scope as k & k0

  if (!k) {
    for (size_t i = 0; i < SIPHASH_KEY_SIZE; i++) {
      tmp_key[i] = i;
    }

    k = tmp_key;
  }

  [...]
  u64 k0 = U8TO64_LE((u8 *)k);
  [...]

HTH.

TLS1.3 now active

TLS 1.3 (draft 16) now active on xcx.cc (and all other sites I maintain), using AEAD ciphers (AEAD-AES256-GCM-SHA384, AEAD-AES128-GCM-SHA256, AEAD-CHACHA20-POLY1305-SHA256).

Powered by libnsb & tinx, build with love, safe-stack, scudo allocator, CFI and many more hardening options.

I really need to update both project sites. And release. Soon… :-)

Update 11-17-2016: As of 11-15-2016 the sites have been updated to draft18. Currently, only chrome canary supports this draft.