Use a hardware based number of KDF rounds by default for passphrases
authorkn <kn@openbsd.org>
Sat, 2 Sep 2023 09:14:47 +0000 (09:14 +0000)
committerkn <kn@openbsd.org>
Sat, 2 Sep 2023 09:14:47 +0000 (09:14 +0000)
When creating new crypto volumes with a passphrase or updating one, pick a
number of rounds that aims to take around 1s instead of just 16 (on X230 and
T14 machines, 16 rounds unlock pretty much instantly).

New default [-r auto] never decreases rounds, only explicit '-r N' can.
16 is the absolute minimum.

Motivation is to provide a saner and more modern default, especially for
fresh installations utilizing new disk encryption question.

Prodding for new default from and OK jsing on early "-r auto" installer diff
idea to to pick MAX(auto, old-rounds) from Lucas[AT sexy DOT is]
"seems acceptable to me" deraadt
Feedback kettenis sthen
OK op

sbin/bioctl/bioctl.8
sbin/bioctl/bioctl.c

index 3323de0..a187daf 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: bioctl.8,v 1.113 2023/08/21 08:33:11 kn Exp $
+.\"    $OpenBSD: bioctl.8,v 1.114 2023/09/02 09:14:47 kn Exp $
 .\"
 .\" Copyright (c) 2004, 2005 Marco Peereboom
 .\"
@@ -23,7 +23,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd $Mdocdate: August 21 2023 $
+.Dd $Mdocdate: September 2 2023 $
 .Dt BIOCTL 8
 .Os
 .Sh NAME
@@ -282,11 +282,12 @@ passphrase into a key, in order to create a new encrypted volume or change the
 passphrase of an existing encrypted volume.
 A larger number of iterations takes more time, but offers increased resistance
 against passphrase guessing attacks.
-If
+By default, or if
 .Ar rounds
-is specified as "auto", the number of rounds will be automatically determined
-based on system performance.
-Otherwise the minimum is 4 rounds and the default is 16.
+is specified as
+.Cm auto ,
+the number of rounds will automatically be based on system performance.
+The minimum is 16 rounds.
 .It Fl s
 Read passphrases from
 .Pa /dev/stdin
index 0f1ddf2..9318fa1 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: bioctl.c,v 1.154 2023/08/21 08:33:11 kn Exp $ */
+/* $OpenBSD: bioctl.c,v 1.155 2023/09/02 09:14:47 kn Exp $ */
 
 /*
  * Copyright (c) 2004, 2005 Marco Peereboom
@@ -89,7 +89,7 @@ int                   devh = -1;
 int                    human;
 int                    verbose;
 u_int32_t              cflags = 0;
-int                    rflag = 0;
+int                    rflag = -1;     /* auto */
 char                   *password;
 
 void                   *bio_cookie;
@@ -182,7 +182,7 @@ main(int argc, char *argv[])
                                rflag = -1;
                                break;
                        }
-                       rflag = strtonum(optarg, 4, 1<<30, &errstr);
+                       rflag = strtonum(optarg, 16, 1<<30, &errstr);
                        if (errstr != NULL)
                                errx(1, "number of KDF rounds is %s: %s",
                                    errstr, optarg);
@@ -979,7 +979,7 @@ bio_kdf_generate(struct sr_crypto_kdfinfo *kdfinfo)
 
        kdfinfo->pbkdf.generic.len = sizeof(kdfinfo->pbkdf);
        kdfinfo->pbkdf.generic.type = SR_CRYPTOKDFT_BCRYPT_PBKDF;
-       kdfinfo->pbkdf.rounds = rflag ? rflag : 16;
+       kdfinfo->pbkdf.rounds = rflag;
 
        kdfinfo->flags = SR_CRYPTOKDF_KEY | SR_CRYPTOKDF_HINT;
        kdfinfo->len = sizeof(*kdfinfo);
@@ -1119,12 +1119,14 @@ bio_changepass(char *dev)
        /* Current passphrase. */
        bio_kdf_derive(&kdfinfo1, &kdfhint, "Old passphrase: ", 0);
 
-       /*
-        * Unless otherwise specified, keep the previous number of rounds as
-        * long as we're using the same KDF.
-        */
-       if (kdfhint.generic.type == SR_CRYPTOKDFT_BCRYPT_PBKDF && !rflag)
-               rflag = kdfhint.rounds;
+       if (rflag == -1) {
+               rflag = bcrypt_pbkdf_autorounds();
+
+               /* Use previous number of rounds for the same KDF if higher. */
+               if (kdfhint.generic.type == SR_CRYPTOKDFT_BCRYPT_PBKDF &&
+                   rflag < kdfhint.rounds)
+                       rflag = kdfhint.rounds;
+       }
 
        /* New passphrase. */
        bio_kdf_generate(&kdfinfo2);
@@ -1328,7 +1330,7 @@ derive_key(u_int32_t type, int rounds, u_int8_t *key, size_t keysz,
            type != SR_CRYPTOKDFT_BCRYPT_PBKDF)
                errx(1, "unknown KDF type %d", type);
 
-       if (rounds < (type == SR_CRYPTOKDFT_PKCS5_PBKDF2 ? 1000 : 4))
+       if (rounds < (type == SR_CRYPTOKDFT_PKCS5_PBKDF2 ? 1000 : 16))
                errx(1, "number of KDF rounds is too small: %d", rounds);
 
        /* get passphrase */