[Bug 1703691] Re: Using iter-time doesn't give the desired timeout and security

Jean-Louis Dupond jean-louis at dupond.be
Fri Aug 18 12:15:03 UTC 2017


What version of cryptsetup is this?
Also notice the official repository is on gitlab.

There the issue has some newer updates:
https://gitlab.com/cryptsetup/cryptsetup/issues/185

Some changes were done in 1.7.x to the benchmark. So it might already be
fixed!

-- 
You received this bug notification because you are a member of Ubuntu
Foundations Bugs, which is subscribed to cryptsetup in Ubuntu.
https://bugs.launchpad.net/bugs/1703691

Title:
  Using iter-time doesn't give the desired timeout and security

Status in cryptsetup:
  New
Status in cryptsetup package in Ubuntu:
  Confirmed

Bug description:
  I have formatted using cryptsetup with option iter-time for use longer
  timeout than the default 2000ms. When I write 60000 I get 18 seconds
  and 10000 is 2 seconds. Something is terrible wrong.

  To get a timeout closer to what I want I wrote this script, which is
  an except:

    benchmarkiterations=$(cryptsetup benchmark | grep -e
  '^PBKDF2-sha256' | awk '{print $2}')

    cryptsetup -q --key-file ${keyfileluks} luksFormat -i $(($cryptsetuptimeout)) -c aes -s 256 -h sha256 --uuid=${uuidluks} --use-random $loopluks
    timerstart=$(date +%s.%N)
    cryptsetup -q --key-file ${keyfileluks} luksOpen $loopluks ${uuidluks}_${mapper}crypt
    timerend=$(date +%s.%N)
    cryptsetup -q luksClose ${uuidluks}_${mapper}crypt

    timerdiff=$(bc -l <<< "($timerend-$timerstart)*1000")
    timerfactor=$(bc -l <<< "$cryptsetuptimeout/$timerdiff")
    timeoutnew=$(bc -l <<< "scale=0; ($cryptsetuptimeout*$timerfactor*1.2)/1")

    cryptsetup -q --key-file ${keyfileluks} luksFormat -i $timeoutnew -c aes -s 256 -h sha256 --uuid=${uuidluks} --use-random $loopluks
    iterations=$(cryptsetup luksDump $loopluks | grep -e '[[:space:]]Iterations:' | awk '{print $2}')
    iterationspermsec=$(($iterations/$cryptsetuptimeout))
    if [ "$iterationspermsec" -lt "500" ]; then
     echo "Error too few iterations: $iterationspermsec"
     exit 1
    fi

  First I benchmark the computer with rounds per second and then test
  the desired timeout. Then I compare the benchmark with the rounds per
  seconds got while testing and then calculates a new approximate value.
  Then I finally format the device. This gives better values.

  At lines around 700 in keymanage.c master key digest is set to the 1/8
  of the expected value:

   /* Compute master key digest */
   iteration_time_ms /= 8;
   header->mkDigestIterations = at_least((uint32_t)(*PBKDF2_per_sec/1024) * iteration_time_ms,
             LUKS_MKD_ITERATIONS_MIN);

  At lines around 800 in keymanage.c about half of the timeout goes
  away:

   /*
    * Avoid floating point operation
    * Final iteration count is at least LUKS_SLOT_ITERATIONS_MIN
    */
   PBKDF2_temp = (*PBKDF2_per_sec / 2) * (uint64_t)iteration_time_ms;
   PBKDF2_temp /= 1024;
   if (PBKDF2_temp > UINT32_MAX)
    PBKDF2_temp = UINT32_MAX;
   hdr->keyblock[keyIndex].passwordIterations = at_least((uint32_t)PBKDF2_temp,
               LUKS_SLOT_ITERATIONS_MIN);

  Moreover one second are 1000 ms, not 1024.

  Benchmarking of PBKDF always gives to low speed: (from pbkdf_check.c
  from line 54)

  int crypt_pbkdf_check(const char *kdf, const char *hash,
          const char *password, size_t password_size,
          const char *salt, size_t salt_size,
          uint64_t *iter_secs)
  {
   struct rusage rstart, rend;
   int r = 0, step = 0;
   long ms = 0;
   char buf;
   unsigned int iterations;

   if (!kdf || !hash)
    return -EINVAL;

   iterations = 1 << 15;
   while (ms < 500) {
    if (getrusage(RUSAGE_SELF, &rstart) < 0)
     return -EINVAL;

    r = crypt_pbkdf(kdf, hash, password, password_size, salt,
      salt_size, &buf, 1, iterations);
    if (r < 0)
     return r;

    if (getrusage(RUSAGE_SELF, &rend) < 0)
     return -EINVAL;

    ms = time_ms(&rstart, &rend);
    if (ms > 500)
     break;

    if (ms <= 62)
     iterations <<= 4;
    else if (ms <= 125)
     iterations <<= 3;
    else if (ms <= 250)
     iterations <<= 2;
    else
     iterations <<= 1;

    if (++step > 10 || !iterations)
     return -EINVAL;
   }

   if (iter_secs)
    *iter_secs = (iterations * 1000) / ms;
   return r;
  }

  It is not as secure as you expect. You can decrypt the device with a
  master key.

  https://unix.stackexchange.com/questions/119803/how-to-decrypt-luks-
  with-the-known-master-key

To manage notifications about this bug go to:
https://bugs.launchpad.net/cryptsetup/+bug/1703691/+subscriptions



More information about the foundations-bugs mailing list