]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
auth: clear keys with memset_explicit
authorRoy Marples <roy@marples.name>
Sun, 21 Jun 2026 15:40:51 +0000 (16:40 +0100)
committerGitHub <noreply@github.com>
Sun, 21 Jun 2026 15:40:51 +0000 (16:40 +0100)
Supply compat/memset_explicit for platforms which lack it.
Adpat compat/arc4random.c for it.

Reported by NVIDIA Project Vanessa

compat/arc4random.c
compat/memset_explicit.c [new file with mode: 0644]
compat/memset_explicit.h [new file with mode: 0644]
configure
src/auth.c

index a07f84e3102b28d5b0dfc1dca5666fec1b4039dd..f99c7651f35c55fbc05b08b658b3ad4c4a4b1e8f 100644 (file)
@@ -204,16 +204,7 @@ _rs_stir(void)
                _rs_init(rnd, sizeof(rnd));
        else
                _rs_rekey(rnd, sizeof(rnd));
-#if defined(HAVE_EXPLICIT_BZERO)
-       explicit_bzero(rnd, sizeof(rnd));       /* discard source seed */
-#elif defined(HAVE_MEMSET_EXPLICIT)
        (void)memset_explicit(rnd, 0, sizeof(rnd));
-#elif defined(HAVE_MEMSET_S)
-       (void)memset_s(rnd, sizeof(rnd), 0, sizeof(rnd));
-#else
-#warning potentially insecure use of memset discarding the source seed
-       (void)memset(rnd, 0, sizeof(rnd));      /* discard source seed */
-#endif
 
        /* invalidate rs_buf */
        rs->rs_have = 0;
diff --git a/compat/memset_explicit.c b/compat/memset_explicit.c
new file mode 100644 (file)
index 0000000..72ad646
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * memset_explicit compat
+ * SPDX-License-Identifier: BSD-2-Clause
+ * Copyright (c) 2026 Roy Marples <roy@marples.name>
+ * All rights reserved
+
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#include "config.h"
+
+#define        __STDC_WANT_LIB_EXT1__ 1
+#include <string.h>
+
+void *
+memset_explicit(void *b, int c, size_t len)
+{
+#if defined(HAVE_EXPLICIT_MEMSET)
+       return explicit_memset(b, c, len);
+#else
+#if defined(HAVE_MEMSET_S)
+       if (memset_s(b, len, c, len) == 0)
+               return b;
+#elif defined(HAVE_EXPLICIT_BZERO)
+       if (c == 0) {
+               explicit_bzero(b, len);
+               return b;
+       }
+#endif
+       void * (* const volatile vmemset)(void *, int, size_t) = memset;
+       return vmemset(b, c, len);
+#endif
+}
diff --git a/compat/memset_explicit.h b/compat/memset_explicit.h
new file mode 100644 (file)
index 0000000..564c4a8
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * memset_explicit compat
+ * SPDX-License-Identifier: BSD-2-Clause
+ * Copyright (c) 2026 Roy Marples <roy@marples.name>
+ * All rights reserved
+
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef MEMSET_EXPLICIT_H
+#define MEMSET_EXPLICIT_H
+
+#include <stddef.h>
+
+void * memset_explicit(void *, int, size_t);
+
+#endif
index 3fbb73540568111335cf139f0fc8f477dae877fc..959b777a5666c251bd1c1e62f43872cdfe37e1ea 100755 (executable)
--- a/configure
+++ b/configure
@@ -938,7 +938,6 @@ if [ "$ARC4RANDOM_UNIFORM" = no ]; then
        echo "#include                  \"compat/arc4random_uniform.h\"" >>$CONFIG_H
 fi
 
-# Our arc4random compat needs memset_explicit, explicit_bzero or memset_s
 if [ -z "$MEMSET_EXPLICIT" ]; then
        printf "Testing for memset_explicit ... "
        cat <<EOF >_memset_explicit.c
@@ -957,11 +956,34 @@ EOF
        echo "$MEMSET_EXPLICIT"
        rm -rf _memset_explicit.* _memset_explicit
 fi
-if [ "$MEMSET_EXPLICIT" = yes ]; then
-       echo "#define   HAVE_MEMSET_EXPLICIT" >>$CONFIG_H
+if [ "$MEMSET_EXPLICIT" = no ]; then
+       echo "COMPAT_SRCS+=     compat/memset_explicit.c" >>$CONFIG_MK
+       echo "#include                  \"compat/memset_explicit.h\"" >>$CONFIG_H
 fi
 
-if [ -z "$EXPLICIT_BZERO" ]; then
+if [ "$MEMSET_EXPLICIT" = no ] && [ -z "$EXPLICIT_MEMSET" ]; then
+       printf "Testing for explicit_memset ... "
+       cat <<EOF >_explicit_memset.c
+#include <string.h>
+int main(void) {
+       int a;
+       (void)explicit_memset(&a, 0, sizeof(a));
+       return 0;
+}
+EOF
+       if $XCC _explicit_memset.c -o _explicit_memset 2>&3; then
+               EXPLICIT_MEMSET=yes
+       else
+               EXPLICIT_MEMSET=no
+       fi
+       echo "$EXPLICIT_MEMSET"
+       rm -rf _explicit_memset.* _explicit_memset
+fi
+if [ "$EXPLICIT_MEMSET" = yes ]; then
+       echo "#define   HAVE_EXPLICIT_MEMSET" >>$CONFIG_H
+fi
+
+if [ "$MEMSET_EXPLICIT" = no ] && [ -z "$EXPLICIT_BZERO" ]; then
        printf "Testing for explicit_bzero ... "
        cat <<EOF >_explicit_bzero.c
 #define _BSD_SOURCE // musl, will be added for Linux in config.h
@@ -984,7 +1006,7 @@ if [ "$EXPLICIT_BZERO" = yes ]; then
        echo "#define   HAVE_EXPLICIT_BZERO" >>$CONFIG_H
 fi
 
-if [ -z "$MEMSET_S" ]; then
+if [ "$MEMSET_EXPLICIT" = no ] && [ -z "$MEMSET_S" ]; then
        printf "Testing for memset_s ... "
        cat <<EOF >_memset_s.c
 #define        __STDC_WANT_LIB_EXT1__ 1
@@ -1004,7 +1026,6 @@ EOF
        rm -rf _memset_s.* _memset_s
 fi
 if [ "$MEMSET_S" = yes ]; then
-       echo "#define   __STDC_WANT_LIB_EXT1__  1" >>$CONFIG_H
        echo "#define   HAVE_MEMSET_S" >>$CONFIG_H
 fi
 
index 597f10c948a811281827c2c5c47e903c0a321400..33aaa5c858b26e98a481a3f6b3043521100242e6 100644 (file)
 
 #define HMAC_LENGTH 16
 
+static void
+free_token(struct token *t)
+{
+       if (t == NULL)
+               return;
+
+       if (t->key != NULL)
+               (void)memset_explicit(t->key, 0, t->key_len);
+       free(t->key);
+       free(t->realm);
+       free(t);
+}
+
 void
 dhcp_auth_reset(struct authstate *state)
 {
        state->replay = 0;
-       if (state->token) {
-               free(state->token->key);
-               free(state->token->realm);
-               free(state->token);
+       if (state->token != NULL) {
+               free_token(state->token);
                state->token = NULL;
        }
        if (state->reconf) {
-               free(state->reconf->key);
-               free(state->reconf->realm);
-               free(state->reconf);
+               free_token(state->reconf);
                state->reconf = NULL;
        }
 }