Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src adding argon2 support to libcrypt. argon2 user authenticatio...



details:   https://anonhg.NetBSD.org/src/rev/0cbb976593d3
branches:  trunk
changeset: 460390:0cbb976593d3
user:      jhigh <jhigh%NetBSD.org@localhost>
date:      Mon Oct 21 02:36:48 2019 +0000

description:
adding argon2 support to libcrypt. argon2 user authentication now
available via MKARGON2=yes (3 variants supported; argon2id recommended)
before using, please read argon2 paper at
https://github.com/P-H-C/phc-winner-argon2

diffstat:

 external/apache2/argon2/lib/libargon2/Makefile  |   10 +-
 external/apache2/argon2/usr.bin/argon2/Makefile |   11 +-
 lib/libcrypt/Makefile                           |   14 +-
 lib/libcrypt/crypt-argon2.c                     |  254 ++++++++++++++++++++++++
 lib/libcrypt/crypt.3                            |   42 ++-
 lib/libcrypt/crypt.c                            |   17 +-
 lib/libcrypt/crypt.h                            |    9 +-
 lib/libcrypt/pw_gensalt.c                       |  132 ++++++++++++-
 usr.bin/pwhash/Makefile                         |    6 +-
 usr.bin/pwhash/pwhash.1                         |   31 ++-
 usr.bin/pwhash/pwhash.c                         |   46 ++++-
 11 files changed, 524 insertions(+), 48 deletions(-)

diffs (truncated from 826 to 300 lines):

diff -r 890d19d2a3cb -r 0cbb976593d3 external/apache2/argon2/lib/libargon2/Makefile
--- a/external/apache2/argon2/lib/libargon2/Makefile    Sun Oct 20 23:47:14 2019 +0000
+++ b/external/apache2/argon2/lib/libargon2/Makefile    Mon Oct 21 02:36:48 2019 +0000
@@ -12,15 +12,7 @@
 LIB=   argon2  
 SRCS=  argon2.c core.c blake2b.c thread.c encoding.c ref.c
 
-
-CPPFLAGS= -std=c89 -O3 -Wall -g -I../../dist/phc-winner-argon2/include -Isrc -shared -fPIC
-
-.ifdef NO_THREADS
-CPPFLAGS += -DARGON2_NO_THREADS
-.else
-CPPFLAGS += -pthread
-LDADD+=-lpthread
-.endif
+CPPFLAGS= -std=c89 -O3 -Wall -g -I../../dist/phc-winner-argon2/include -Isrc -fPIC -DARGON2_NO_THREADS
 
 OPTTARGET ?= native
 OPTTEST := $(shell $(CC) -Iinclude -Isrc -march=$(OPTTARGET) src/opt.c -c \
diff -r 890d19d2a3cb -r 0cbb976593d3 external/apache2/argon2/usr.bin/argon2/Makefile
--- a/external/apache2/argon2/usr.bin/argon2/Makefile   Sun Oct 20 23:47:14 2019 +0000
+++ b/external/apache2/argon2/usr.bin/argon2/Makefile   Mon Oct 21 02:36:48 2019 +0000
@@ -10,16 +10,7 @@
 SRCS=   argon2.c core.c blake2b.c thread.c encoding.c ref.c
 SRCS+=   run.c
 
-.ifdef NO_THREADS 
-CPPFLAGS += -DARGON2_NO_THREADS
-.else
-CPPFLAGS += -pthread
-LDADD+=-lpthread
-.endif
-
-CPPFLAGS+= -std=c89 -O3 -Wall -g -I../../dist/phc-winner-argon2/include -Isrc #-shared -fPIC
-#LDADD+= -L${LIBARGON2} -largon2
-#DPADD+= ${LIBARGON2_SD}
+CPPFLAGS+= -DARGON2_NO_THREADS -std=c89 -O3 -Wall -g -I../../dist/phc-winner-argon2/include -Isrc 
 
 MAN=argon2.1
 
diff -r 890d19d2a3cb -r 0cbb976593d3 lib/libcrypt/Makefile
--- a/lib/libcrypt/Makefile     Sun Oct 20 23:47:14 2019 +0000
+++ b/lib/libcrypt/Makefile     Mon Oct 21 02:36:48 2019 +0000
@@ -1,12 +1,24 @@
-#      $NetBSD: Makefile,v 1.25 2013/08/10 18:42:29 dholland Exp $
+#      $NetBSD: Makefile,v 1.26 2019/10/21 02:36:48 jhigh Exp $
+
+.include <bsd.own.mk>
 
 USE_SHLIBDIR=  yes
 
+.if (defined(MKARGON2) && ${MKARGON2} != "no")
+HAVE_ARGON2=1
+.endif
+
 LIB=   crypt
 
 SRCS=  crypt.c md5crypt.c bcrypt.c crypt-sha1.c util.c pw_gensalt.c
 SRCS+= hmac_sha1.c
 
+.if defined(HAVE_ARGON2)
+SRCS+=         crypt-argon2.c
+CFLAGS+=       -DHAVE_ARGON2 -I../../external/apache2/argon2/dist/phc-winner-argon2/include/
+LDADD+=                -largon2 
+.endif
+
 WARNS?=        5
 
 MAN=   crypt.3
diff -r 890d19d2a3cb -r 0cbb976593d3 lib/libcrypt/crypt-argon2.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/libcrypt/crypt-argon2.c       Mon Oct 21 02:36:48 2019 +0000
@@ -0,0 +1,254 @@
+#include <stdlib.h>
+#include <stdio.h> 
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <pwd.h>
+#include <errno.h>
+#include <argon2.h>
+
+#include <err.h>
+#include "crypt.h"
+
+/* defaults pulled from run.c */
+#define HASHLEN                32
+#define T_COST_DEF     3 
+#define LOG_M_COST_DEF         12 /* 2^12 = 4 MiB */
+#define LANES_DEF      1
+#define THREADS_DEF    1
+#define OUTLEN_DEF     32
+#define MAX_PASS_LEN   128
+
+#define ARGON2_CONTEXT_INITIALIZER     \
+       {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+       T_COST_DEF, LOG_M_COST_DEF,\
+       LANES_DEF, THREADS_DEF, \
+       ARGON2_VERSION_NUMBER, 0, 0, ARGON2_DEFAULT_FLAGS}
+
+#define ARGON2_ARGON2_STR      "argon2"
+#define ARGON2_ARGON2I_STR     "argon2i"
+#define ARGON2_ARGON2D_STR     "argon2d"
+#define ARGON2_ARGON2ID_STR    "argon2id"
+
+/* getnum also declared in pw_getsalt.c */
+/* maybe move to util.h?? */
+static int
+getnum(const char *str, size_t *num)
+{
+        char *ep;
+        unsigned long rv;
+ 
+        if (str == NULL) {
+                *num = 0;
+                return 0;
+        }
+
+        rv = strtoul(str, &ep, 0);
+
+        if (str == ep || *ep) {
+                errno = EINVAL;
+                return -1;
+        }
+
+        if (errno == ERANGE && rv == ULONG_MAX)
+                return -1;
+        *num = (size_t)rv;
+        return 0;  
+}
+
+/* process params to argon2 */
+/* we don't force param order as input, */
+/* but we do provide the expected order to argon2 api */
+static int decode_option(argon2_context * ctx, argon2_type * atype, const char * option) 
+{
+       size_t tmp=0;
+        char * in = 0,*inp;;
+        char * a=0;
+        char * p=0;
+       size_t sl;
+       int    error=0;
+
+        in = (char *)strdup(option);
+       inp = in;
+
+       if (*inp == '$') inp++;
+
+       a = strsep(&inp, "$");
+
+       sl = strlen(a);
+
+       if (sl == strlen(ARGON2_ARGON2I_STR) && 
+          !(strcmp(ARGON2_ARGON2I_STR, a))) {
+               *atype=Argon2_i;
+       } else if (sl == strlen(ARGON2_ARGON2D_STR) && 
+               !(strcmp(ARGON2_ARGON2D_STR, a))) {
+               *atype=Argon2_d;
+       }
+       else if (sl == strlen(ARGON2_ARGON2ID_STR) && 
+               !(strcmp(ARGON2_ARGON2ID_STR, a))) {
+               *atype=Argon2_id;
+       } else { /* default to id, we assume simple mistake */
+               /* don't abandon yet */
+               *atype=Argon2_id;
+       }
+
+       a = strsep(&inp, "$");
+
+       if ((getnum(a, &tmp))<0) { /* on error, default to current */
+                               /* should start thinking about aborting */
+               ctx->version = ARGON2_VERSION_NUMBER;
+       } else {
+               ctx->version = tmp;
+       }
+
+       a = strsep(&inp, "$");
+
+       /* parse labelled argon2 params */
+       /* m_cost (m)
+        * t_cost (t)
+        * threads (p)
+        */
+       while ((p = strsep(&a, ","))) {
+               switch (*p) {
+                       case 'm':
+                               p += strlen("m=");
+                               if ((getnum(p, &tmp)) < 0) {
+                                       --error;
+                               } else {
+                                       ctx->m_cost = tmp;
+                               }
+                               break;
+                       case 't':
+                               p += strlen("t=");
+                               if ((getnum(p, &tmp)) < 0) {
+                                       --error;
+                               } else {
+                                       ctx->t_cost = tmp;
+                               }
+                               break;
+                       case 'p':
+                               p += strlen("p=");
+                               if ((getnum(p, &tmp)) < 0) {
+                                       --error;
+                               } else {
+                                       ctx->threads = tmp;
+                               }
+                               break;
+                       default:
+                               return -1;
+
+               }
+       }
+
+       a = strsep(&inp, "$");
+
+       snprintf((char *)ctx->salt,ctx->saltlen, "%s", a);
+
+       a = strsep(&inp, "$");
+
+       if (*a) {
+               snprintf((char *)ctx->pwd,ctx->pwdlen, "%s", a);
+       } else {
+               /* don't care if passwd hash is missing */
+               /* if missing, most likely coming from */
+               /* pwhash or similar */ 
+       }
+
+       /* free our token buffer */
+        free(in);
+
+       /* 0 on success, <0 otherwise */
+        return error;
+}
+
+char * 
+__crypt_argon2(const char *pw, const char * salt)
+{
+       /* we use the libargon2 api to generate */
+       /* return code */
+       int rc=0;
+       /* output buffer */
+       char ebuf[32];
+       /* ptr into argon2 encoded buffer */
+       char * blkp=0;
+       /* argon2 variable, default to id */
+       argon2_type atype = Argon2_id;
+       /* default to current argon2 version */
+       int version=ARGON2_VERSION_NUMBER;
+       /* argon2 context to collect params */
+       argon2_context ctx = ARGON2_CONTEXT_INITIALIZER;
+       /* argon2 encoded buffer */
+       char encodebuf[256];
+       /* argon2 salt buffer */
+       char saltbuf[128];
+       /* argon2 pwd buffer */
+       char pwdbuf[128];
+       /* returned static buffer */
+       static char rbuf[512];
+
+       /* clear buffers */
+       memset(encodebuf, 0, sizeof(encodebuf));
+       memset(saltbuf, 0, sizeof(saltbuf));
+       memset(pwdbuf, 0, sizeof(pwdbuf));
+       memset(rbuf, 0, sizeof(rbuf));
+
+       /* we use static buffers to avoid allocation */
+       /* and easier cleanup */
+       ctx.out = (uint8_t *)ebuf;
+       ctx.outlen = sizeof(ebuf);
+
+       ctx.out = (uint8_t *)encodebuf;
+       ctx.outlen = sizeof(encodebuf);
+
+       ctx.salt = (uint8_t *)saltbuf;
+       ctx.saltlen = sizeof(saltbuf);
+
+       ctx.pwd= (uint8_t *)pwdbuf;
+       ctx.pwdlen = sizeof(pwdbuf);
+
+       /* decode salt string to argon2 params */
+       /* argon2 context for param collection */
+       rc = decode_option(&ctx, &atype, salt);
+
+       if (rc < 0) {
+       /* unable to parse input params */
+               return 0;
+       }
+
+       rc = argon2_hash(ctx.t_cost, ctx.m_cost,
+               ctx.threads, pw, strlen(pw), ctx.salt, strlen((char*)ctx.salt),
+               ebuf, sizeof(ebuf), encodebuf, sizeof(encodebuf), atype, ctx.version);
+
+       if (rc != ARGON2_OK) {
+               fprintf(stderr, "Failed: %s\n", argon2_error_message(rc));
+               return 0;
+       }



Home | Main Index | Thread Index | Old Index