]> git.ipfire.org Git - thirdparty/wireguard-tools.git/commitdiff
ctype: use non-locale-specific ctype.h
authorJason A. Donenfeld <Jason@zx2c4.com>
Tue, 4 Aug 2020 12:49:21 +0000 (14:49 +0200)
committerJason A. Donenfeld <Jason@zx2c4.com>
Thu, 6 Aug 2020 15:47:14 +0000 (17:47 +0200)
We also make these constant time, even though we're never distinguishing
between bits of a secret using them. From that perspective, though, this
is markedly better than the locale-specific table lookups in glibc, even
though base64 characters span two cache lines and valid private keys
must hit both.

Co-authored-by: Samuel Neves <sneves@dei.uc.pt>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Signed-off-by: Samuel Neves <sneves@dei.uc.pt>
src/config.c
src/ctype.h [new file with mode: 0644]
src/ipc-uapi.h
src/pubkey.c
src/terminal.c

index b8394a531a3efc4b098d38f107c94811227746e3..e0b4b7ce1dfacc1180fdebe834ba083d0bcc015c 100644 (file)
@@ -5,7 +5,6 @@
 
 #include <arpa/inet.h>
 #include <limits.h>
-#include <ctype.h>
 #include <netdb.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -19,6 +18,7 @@
 #include "containers.h"
 #include "ipc.h"
 #include "encoding.h"
+#include "ctype.h"
 
 #define COMMENT_CHAR '#'
 
@@ -86,7 +86,7 @@ static inline bool parse_fwmark(uint32_t *fwmark, uint32_t *flags, const char *v
                return true;
        }
 
-       if (!isdigit(value[0]))
+       if (!char_is_digit(value[0]))
                goto err;
 
        if (strlen(value) > 2 && value[0] == '0' && value[1] == 'x')
@@ -141,7 +141,7 @@ static bool parse_keyfile(uint8_t key[static WG_KEY_LEN], const char *path)
        dst[WG_KEY_LEN_BASE64 - 1] = '\0';
 
        while ((c = getc(f)) != EOF) {
-               if (!isspace(c)) {
+               if (!char_is_space(c)) {
                        fprintf(stderr, "Found trailing character in key file: `%c'\n", c);
                        goto out;
                }
@@ -290,7 +290,7 @@ static inline bool parse_persistent_keepalive(uint16_t *interval, uint32_t *flag
                return true;
        }
 
-       if (!isdigit(value[0]))
+       if (!char_is_digit(value[0]))
                goto err;
 
        ret = strtoul(value, &end, 10);
@@ -375,7 +375,7 @@ static inline bool parse_allowedips(struct wgpeer *peer, struct wgallowedip **la
                }
 
                if (mask) {
-                       if (!isdigit(mask[0]))
+                       if (!char_is_digit(mask[0]))
                                goto err;
                        cidr = strtoul(mask, &end, 10);
                        if (*end || (cidr > 32 && new_allowedip->family == AF_INET) || (cidr > 128 && new_allowedip->family == AF_INET6))
@@ -501,7 +501,7 @@ bool config_read_line(struct config_ctx *ctx, const char *input)
        }
 
        for (size_t i = 0; i < len; ++i) {
-               if (!isspace(input[i]))
+               if (!char_is_space(input[i]))
                        line[cleaned_len++] = input[i];
        }
        if (!cleaned_len)
@@ -555,7 +555,7 @@ static char *strip_spaces(const char *in)
                return NULL;
        }
        for (i = 0, l = 0; i < t; ++i) {
-               if (!isspace(in[i]))
+               if (!char_is_space(in[i]))
                        out[l++] = in[i];
        }
        return out;
diff --git a/src/ctype.h b/src/ctype.h
new file mode 100644 (file)
index 0000000..98b2283
--- /dev/null
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
+ *
+ * Specialized constant-time ctype.h reimplementations that aren't locale-specific.
+ */
+
+#ifndef CTYPE_H
+#define CTYPE_H
+
+#include <stdbool.h>
+
+static inline bool char_is_space(int c)
+{
+       unsigned char d = c - 9;
+       return (0x80001FU >> (d & 31)) & (1U >> (d >> 5));
+}
+
+static inline bool char_is_digit(int c)
+{
+       return (unsigned int)(('0' - 1 - c) & (c - ('9' + 1))) >> (sizeof(c) * 8 - 1);
+}
+
+static inline bool char_is_alpha(int c)
+{
+       return (unsigned int)(('a' - 1 - (c | 32)) & ((c | 32) - ('z' + 1))) >> (sizeof(c) * 8 - 1);
+}
+
+#endif
index 3b1fff35b6d42ee9bf17f174a8319fedc708f20b..f464be700c0ccc605db5e90628b4cd054cf51e22 100644 (file)
@@ -4,7 +4,6 @@
  */
 
 #include <arpa/inet.h>
-#include <ctype.h>
 #include <errno.h>
 #include <net/if.h>
 #include <netdb.h>
@@ -17,6 +16,7 @@
 #include "containers.h"
 #include "curve25519.h"
 #include "encoding.h"
+#include "ctype.h"
 
 #ifdef _WIN32
 #include "ipc-uapi-windows.h"
@@ -102,7 +102,7 @@ static int userspace_set_device(struct wgdevice *dev)
 #define NUM(max) ({ \
        unsigned long long num; \
        char *end; \
-       if (!isdigit(value[0])) \
+       if (!char_is_digit(value[0])) \
                break; \
        num = strtoull(value, &end, 10); \
        if (*end || num > max) \
@@ -223,7 +223,7 @@ static int userspace_get_device(struct wgdevice **out, const char *iface)
                        struct wgallowedip *new_allowedip;
                        char *end, *mask = value, *ip = strsep(&mask, "/");
 
-                       if (!mask || !isdigit(mask[0]))
+                       if (!mask || !char_is_digit(mask[0]))
                                break;
                        new_allowedip = calloc(1, sizeof(*new_allowedip));
                        if (!new_allowedip) {
index a78fe117d46f92cca3bb4a99e47605dd4e695fe3..b4478dca4d4751d0a5a39e89035fa448af28db62 100644 (file)
@@ -5,11 +5,11 @@
 
 #include <errno.h>
 #include <stdio.h>
-#include <ctype.h>
 
 #include "curve25519.h"
 #include "encoding.h"
 #include "subcommands.h"
+#include "ctype.h"
 
 int pubkey_main(int argc, char *argv[])
 {
@@ -31,7 +31,7 @@ int pubkey_main(int argc, char *argv[])
 
        for (;;) {
                trailing_char = getc(stdin);
-               if (!trailing_char || isspace(trailing_char))
+               if (!trailing_char || char_is_space(trailing_char))
                        continue;
                if (trailing_char == EOF)
                        break;
index bea27ba4734bc3f8372ccee932810196a969dc34..7c293cdf0bc8188de41df9466149c6c8ec24428d 100644 (file)
@@ -3,7 +3,6 @@
  * Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
  */
 
-#include <ctype.h>
 #include <stdarg.h>
 #include <stddef.h>
 #include <stdio.h>
@@ -11,6 +10,7 @@
 #include <string.h>
 #include <stdbool.h>
 #include <unistd.h>
+#include "ctype.h"
 
 static bool color_mode(void)
 {
@@ -46,7 +46,7 @@ static void filter_ansi(const char *fmt, va_list args)
                        if (str[i] == '\x1b' && str[i + 1] == '[') {
                                str[i] = str[i + 1] = '\0';
                                for (j = i + 2; j < len; ++j) {
-                                       if (isalpha(str[j]))
+                                       if (char_is_alpha(str[j]))
                                                break;
                                        str[j] = '\0';
                                }