Welcome to little lamb

Code » ssp » commit 9235cd7

ssp: Add -I/--iter to set the iteration numbers (for PBKDF2)

author Olivier Brunel
2023-08-20 15:31:11 UTC
committer Olivier Brunel
2023-08-20 17:15:06 UTC
parent 4bcd4aac481861f2901ca0c9890e1e1466e5beb3

ssp: Add -I/--iter to set the iteration numbers (for PBKDF2)

src/doc/ssp.1.md +13 -3
src/include/ssp.h +3 -1
src/ssp/add.c +1 -1
src/ssp/database.c +1 -1
src/ssp/ssp.c +15 -0

diff --git a/src/doc/ssp.1.md b/src/doc/ssp.1.md
index 82145bc..c0e5f78 100644
--- a/src/doc/ssp.1.md
+++ b/src/doc/ssp.1.md
@@ -26,6 +26,15 @@ backup solution.
 
 <inc opt_help.md>
 
+: *-I*, *--iter* `ITER`
+:: Use `ITER` iterations when performing key derivation to write database. See
+:: [[DATABASE]] below for more. Must be at least 50 000; Defaults to 500 000.
+::
+:: Note that this only applies when writing database, not reading it (since the
+:: number of iterations used is stored within the file), but since the database
+:: is re-encrypted each time it is written, any operation requiring to write
+:: the database will make use of this setting.
+
 : *-q*, *--quiet*
 <inc autoopt_quiet.md>
 
@@ -120,9 +129,10 @@ Anything else will be treated as-is.
 
 The database is written as a password-protected file.
 
-More specifically, PBKDF2-HMAC-SHA3-256 is used with 500,000 iterations to
-derive a key from the password and a randomly generated salt, said key is then
-used to encrypt the database using ChaCha20-Poly1305.
+More specifically, PBKDF2-HMAC-SHA3-256 is used with 500,000 iterations (by
+default, can be changed using *--iter*) to derive a key from the password and a
+randomly generated salt, said key is then used to encrypt the database using
+ChaCha20-Poly1305.
 
 Whenever writing to the database, the actual file is not changed. Instead a new
 file is created, encrypted data is written to it and only once successfully
diff --git a/src/include/ssp.h b/src/include/ssp.h
index 60938a7..df7041e 100644
--- a/src/include/ssp.h
+++ b/src/include/ssp.h
@@ -19,7 +19,8 @@ enum {
 #define SALT_LEN        32
 #define NONCE_LEN       12
 #define PWD_MAX         136
-#define ITER            500000
+#define ITER_MIN        50000
+#define ITER_DEF        500000
 
 struct ssp {
     stralloc sa;
@@ -28,6 +29,7 @@ struct ssp {
     cdb_data val;
     size_t cdboff;
     unsigned int options;
+    u32 iter;
     u32 pos;
     char pwd[PWD_MAX + 1];
 };
diff --git a/src/ssp/add.c b/src/ssp/add.c
index f78e217..1054b39 100644
--- a/src/ssp/add.c
+++ b/src/ssp/add.c
@@ -47,7 +47,7 @@ validate_digits(const char *data, size_t dlen)
 int
 validate_counter(u64 *c, const char *data, size_t dlen)
 {
-    dbg("validating counter", ESC, PMLEN(data, dlen), ESC);
+    dbg("validating counter ", ESC, PMLEN(data, dlen), ESC);
     if (u64_scan(c, data) != dlen) {
         warn("invalid counter value: ", PMLEN(data, dlen));
         return -1;
diff --git a/src/ssp/database.c b/src/ssp/database.c
index 04ce283..d300e78 100644
--- a/src/ssp/database.c
+++ b/src/ssp/database.c
@@ -200,7 +200,7 @@ write_db(char *data, size_t dlen, struct ssp *ctx)
     v.iov_len = dlen;
 
     if (!shldata_write(AT_FDCWD, db_file(ctx), SSP_MAGIC, 0, ctx->pwd, plen,
-                ALGO_SHA3_256, ITER, 1, &v, 1)) {
+                ALGO_SHA3_256, (ctx->iter) ? ctx->iter : ITER_DEF, 1, &v, 1)) {
         warnusys("write database to ", ESC, db_file(ctx), ESC);
         return 0;
     }
diff --git a/src/ssp/ssp.c b/src/ssp/ssp.c
index 2dd4904..6dbd89c 100644
--- a/src/ssp/ssp.c
+++ b/src/ssp/ssp.c
@@ -11,6 +11,7 @@
 #include <limb/exitcode.h>
 #include <limb/loadopt.h>
 #include <limb/output.h>
+#include <limb/u32.h>
 #include "ssp.h"
 #include "config.h"
 
@@ -55,6 +56,7 @@ parse_cmdline(int *argc, const char **argv[], struct ssp *ctx)
         OPTION_ARG_OPT ( 0 , "debug",                   0,          OPTID_DEBUG),
         OPTION_ARG_REQ ('D', "database",                OPT_PATH,   OPTID_SHORTOPT),
         OPTION_ARG_NONE('h', "help",                    0,          OPTID_SHORTOPT),
+        OPTION_ARG_REQ ('I', "iter",                    0,          OPTID_SHORTOPT),
         OPTION_ARG_NONE('q', "quiet",                   0,          OPTID_SHORTOPT),
         OPTION_ARG_NONE( 0 , "version",                 0,          OPTID_VERSION),
         LOADOPT_STOP
@@ -68,6 +70,18 @@ parse_cmdline(int *argc, const char **argv[], struct ssp *ctx)
         case 'h':
             ctx->options |= OPT_HELP;
             break;
+        case 'I':
+            {
+                u32 u;
+                if (!u32_scan0(&u, LO_ARG(&lo))
+                        || (errno = ERANGE, u < ITER_MIN)) {
+                    warnsys("invalid iteration number: ", LO_ARG(&lo));
+                    dieusage(EX_USAGE, usage);
+                }
+                ctx->iter = u;
+                dbg("set iteration to ", PMUINT(ctx->iter));
+            }
+            break;
         case 'q':
             autoopt_quiet(&options[LO_IDX(&lo)], LO_ARG(&lo));
             break;
@@ -87,6 +101,7 @@ parse_cmdline(int *argc, const char **argv[], struct ssp *ctx)
     if (LO_CUR(&lo) == *argc)
         dienocommand(EX_USAGE, usage, (ctx->options & OPT_HELP) ?
 " -D, --database FILE                   Use FILE as database [$HOME/ssp.db]\n"
+" -I, --iter ITER                       Use ITER iterations (when writing database) [500000]\n"
 "\n"
 " -q, --quiet                           Enable quiet mode\n"
 "     --debug[=[@[level]:]+FD|FILE]     Enable debug output (to FD|FILE)\n"