Browse Source

misc.c: introduce w64wrapper to handle 64bit numbers

as word64 is not always available, introduce an abstract type and companion
operations. They use a word64 if available and fallback on word32[2] otherwise.
Marco Oliverio 1 year ago
parent
commit
9d22e11776
9 changed files with 487 additions and 0 deletions
  1. 1 0
      CMakeLists.txt
  2. 1 0
      configure.ac
  3. 1 0
      tests/include.am
  4. 8 0
      tests/unit.c
  5. 1 0
      tests/unit.h
  6. 218 0
      tests/w64wrapper.c
  7. 244 0
      wolfcrypt/src/misc.c
  8. 5 0
      wolfssl/wolfcrypt/settings.h
  9. 8 0
      wolfssl/wolfcrypt/types.h

+ 1 - 0
CMakeLists.txt

@@ -279,6 +279,7 @@ if(WOLFSSL_DTLS13)
       message(FATAL_ERROR "DTLS13 requires TLS13")
     endif()
     list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_DTLS13")
+    list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_W64_WRAPPER")
 
     if (WOLFSSL_AES)
       list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_AES_DIRECT")

+ 1 - 0
configure.ac

@@ -3524,6 +3524,7 @@ then
         then
                 AC_MSG_ERROR([You need to enable both DTLS and TLSv1.3 to use DTLSv1.3])
         fi
+  AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DTLS13 -DWOLFSSL_W64_WRAPPER"
   if test "x$ENABLED_AES" = "xyes"
   then
       AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_DIRECT"

+ 1 - 0
tests/include.am

@@ -10,6 +10,7 @@ tests_unit_test_SOURCES = \
                   tests/api.c \
                   tests/suites.c \
                   tests/hash.c \
+                  tests/w64wrapper.c \
                   tests/srp.c \
                   examples/client/client.c \
                   examples/server/server.c

+ 8 - 0
tests/unit.c

@@ -163,6 +163,14 @@ int unit_test(int argc, char** argv)
             printf("hash test failed with %d\n", ret);
             goto exit;
         }
+
+#ifdef WOLFSSL_W64_WRAPPER
+        if ((ret = w64wrapper_test()) != 0) {
+            printf("w64wrapper test failed with %d\n", ret);
+            goto exit;
+        }
+#endif /* WOLFSSL_W64_WRAPPER */
+
     }
 
 #ifndef NO_WOLFSSL_CIPHER_SUITE_TEST

+ 1 - 0
tests/unit.h

@@ -107,6 +107,7 @@ void ApiTest(void);
 int  SuiteTest(int argc, char** argv);
 int  HashTest(void);
 void SrpTest(void);
+int w64wrapper_test(void);
 
 
 #endif /* CyaSSL_UNIT_H */

+ 218 - 0
tests/w64wrapper.c

@@ -0,0 +1,218 @@
+/* w64wrapper.c w64wrapper unit tests
+ *
+ * Copyright (C) 2006-2021 wolfSSL Inc.
+ *
+ * This file is part of wolfSSL.
+ *
+ * wolfSSL is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * wolfSSL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
+ */
+#ifdef HAVE_CONFIG_H
+    #include <config.h>
+#endif
+
+#include <wolfssl/wolfcrypt/settings.h>
+#include <tests/unit.h>
+
+#ifdef WOLFSSL_W64_WRAPPER
+
+#ifndef NO_INLINE
+#define WOLFSSL_MISC_INCLUDED
+#include <wolfcrypt/src/misc.c>
+#else
+#include <wolfssl/wolfcrypt/misc.h>
+#endif
+
+int w64wrapper_test(void)
+{
+    w64wrapper a, b, c;
+    byte wrap, raw[8];
+
+    a = w64From32(0x01020304, 0x05060708);
+#if defined(WORD64_AVAILABLE) && !defined(WOLFSSL_W64_WRAPPER_TEST)
+    if (a.n != 0x0102030405060708)
+        return -1;
+#else
+    if (a.n[0] != 0x01020304 || a.n[1] != 0x05060708)
+        return -1;
+#endif /* WORD64_AVAILABLE && WOLFSSL_W64_WRAPPER_TEST */
+
+    if (w64GetLow32(a) != 0x05060708)
+        return -2;
+    if (w64GetHigh32(a) != 0x01020304)
+        return -3;
+    w64SetLow32(&a, 0xabcdefff);
+    if (w64GetLow32(a) != 0xabcdefff || w64GetHigh32(a) != 0x01020304)
+        return -4;
+
+    a = w64From32(0,0);
+    w64Increment(&a);
+    if (w64GetLow32(a) != 1 || w64GetHigh32(a) != 0)
+        return -5;
+
+    a = w64From32(0, 0xffffffff);
+    w64Increment(&a);
+    if (w64GetLow32(a) != 0 || w64GetHigh32(a) != 1)
+        return -6;
+
+    a = w64From32(0,1);
+    w64Decrement(&a);
+    if (w64GetLow32(a) != 0 || w64GetHigh32(a) != 0)
+        return -7;
+
+    a = w64From32(1,0);
+    w64Decrement(&a);
+    if (w64GetLow32(a) != 0xffffffff || w64GetHigh32(a) != 0)
+        return -8;
+
+    a = w64From32(0xabcdef, 0xdeed);
+    b = w64From32(0xabcdef, 0xdeed);
+    if (!w64Equal(a, b))
+        return -9;
+
+    a = w64From32(1, 1);
+    b = w64From32(0, 1);
+    if (w64Equal(a, b))
+        return -10;
+
+    wrap = 0;
+    a = w64From32(0x0, 0x1);
+    b = w64Add32(a, 0x1, &wrap);
+    if (w64GetLow32(b) != 0x2 || w64GetHigh32(b) != 0x0 || wrap)
+        return -11;
+
+    wrap = 0;
+    a = w64From32(0x0, 0xffffffff);
+    b = w64Add32(a, 0x1, &wrap);
+    if (w64GetLow32(b) != 0x0 || w64GetHigh32(b) != 0x01 || wrap)
+        return -12;
+
+    wrap = 0;
+    a = w64From32(0xffffffff, 0xffffffff);
+    b = w64Add32(a, 0x1, &wrap);
+    if (w64GetLow32(b) != 0x0 || w64GetHigh32(b) != 0x00 || !wrap)
+        return -13;
+
+    wrap = 0;
+    a = w64From32(0x0, 0x1);
+    b = w64Sub32(a, 0x1, &wrap);
+    if (w64GetLow32(b) != 0x0 || w64GetHigh32(b) != 0x00 || wrap)
+        return -14;
+
+    wrap = 0;
+    a = w64From32(0xffffffff, 0x0);
+    b = w64Sub32(a, 0x1, &wrap);
+    if (w64GetLow32(b) != 0xffffffff ||
+            w64GetHigh32(b) != 0xfffffffe || wrap)
+        return -15;
+
+    wrap = 0;
+    a = w64From32(0x0, 0x0);
+    b = w64Sub32(a, 0x1, &wrap);
+    if (w64GetLow32(b) != 0xffffffff ||
+        w64GetHigh32(b) != 0xffffffff || !wrap)
+        return -16;
+
+    a = w64From32(0x0, 0x0);
+    b = w64From32(0x0, 0x0);
+    if (w64GT(a,b) || w64GT(b,a) || !w64GTE(a,b) || w64LT(a,b) || w64LT(b,a))
+        return -17;
+
+    a = w64From32(0x0, 0x1);
+    b = w64From32(0x0, 0x0);
+    if (!w64GT(a, b) || w64GT(b, a) || !w64GTE(a, b) || w64GTE(b, a) ||
+        w64LT(a, b) || !w64LT(b, a))
+        return -18;
+
+    a = w64From32(0x1, 0x0);
+    b = w64From32(0x0, 0x0);
+    if (!w64GT(a, b) || w64GT(b, a) || !w64GTE(a, b) || w64GTE(b, a) ||
+        !w64LT(b, a) || w64LT(a, b))
+        return -19;
+
+    a = w64From32(0x1, 0x0);
+    b = w64From32(0x1, 0x0);
+    if (w64GT(a,b) || w64GT(b,a) || !w64GTE(a,b) || w64LT(a,b))
+        return -20;
+
+    a = w64From32(0x1, 0x1);
+    b = w64From32(0x1, 0x0);
+    if (!w64GT(a, b) || w64GT(b, a) || !w64GTE(a, b) || w64GTE(b, a) ||
+        w64LT(a, b) || !w64LT(b, a))
+        return -21;
+
+    a = w64From32(0x2, 0x1);
+    b = w64From32(0x1, 0x3);
+    if (!w64GT(a, b) || w64GT(b, a) || !w64GTE(a, b) || w64GTE(b, a) ||
+        w64LT(a, b) || !w64LT(b, a))
+        return -22;
+
+    a = w64From32(0x0, 0x0);
+    if (!w64IsZero(a))
+        return -23;
+
+    a = w64From32(0x01020304, 0x05060708);
+    c64toa(&a, raw);
+    if (raw[0] != 0x01
+        ||raw[1] != 0x02
+        ||raw[2] != 0x03
+        ||raw[3] != 0x04
+        ||raw[4] != 0x05
+        ||raw[5] != 0x06
+        ||raw[6] != 0x07
+        ||raw[7] != 0x08) {
+        return -24;
+    }
+
+    b = w64From32(0x0,0x0);
+    ato64(raw, &b);
+    if (w64GetHigh32(b) != 0x01020304 || w64GetLow32(b) != 0x05060708)
+        return -25;
+
+    w64Zero(&b);
+    if (w64GetHigh32(b) != 0x0 || w64GetLow32(b) != 0x0)
+        return -26;
+
+    b = w64From32(0x0, 0xffffffff);
+    w64Increment(&b);
+    if (w64GetHigh32(b) != 0x1 || w64GetLow32(b) != 0x0)
+        return -27;
+    b = w64From32(0xffffffff, 0xffffffff);
+    w64Increment(&b);
+    if (w64GetHigh32(b) != 0x0 || w64GetLow32(b) != 0x0)
+        return -28;
+    b = w64From32(0xffffffff, 0x0);
+    w64Decrement(&b);
+    if (w64GetHigh32(b) != 0xfffffffe || w64GetLow32(b) != 0xffffffff)
+        return -29;
+
+    a = w64From32(0x01, 0x20);
+    b = w64From32(0x01, 0x10);
+    c = w64Sub(a,b);
+    if (w64GetHigh32(c) != 0x0 || w64GetLow32(c) != 0x10)
+        return -30;
+    c = w64Sub(b,a);
+    if (w64GetHigh32(c) != 0xffffffff || w64GetLow32(c) != 0xfffffff0)
+        return -31;
+
+    a = w64From32(0x01, 0x10);
+    b = w64From32(0x00, 0x20);
+    c = w64Sub(a,b);
+    if (w64GetHigh32(c) != 0x00000000 || w64GetLow32(c) != 0xfffffff0)
+        return -32;
+
+    return 0;
+}
+
+#endif /* WOLFSSL_W64_WRAPPER */

+ 244 - 0
wolfcrypt/src/misc.c

@@ -546,6 +546,250 @@ WC_STATIC WC_INLINE byte ctSetLTE(int a, int b)
 }
 #endif
 
+#if defined(WOLFSSL_W64_WRAPPER)
+#if defined(WORD64_AVAILABLE) && !defined(WOLFSSL_W64_WRAPPER_TEST)
+WC_STATIC WC_INLINE void w64Increment(w64wrapper *n) {
+    n->n++;
+}
+
+WC_STATIC WC_INLINE void w64Decrement(w64wrapper *n) {
+    n->n--;
+}
+
+WC_STATIC WC_INLINE byte w64Equal(w64wrapper a, w64wrapper b) {
+    return (a.n == b.n);
+}
+
+WC_STATIC WC_INLINE word32 w64GetLow32(w64wrapper n) {
+    return (word32)n.n;
+}
+
+WC_STATIC WC_INLINE word32 w64GetHigh32(w64wrapper n) {
+    return (word32)(n.n >> 32);
+}
+
+WC_STATIC WC_INLINE void w64SetLow32(w64wrapper *n, word32 low) {
+    n->n = (n->n & (~(word64)(0xffffffff))) | low;
+}
+
+WC_STATIC WC_INLINE w64wrapper w64Add32(w64wrapper a, word32 b, byte *wrap) {
+    a.n = a.n + b;
+    if (a.n < b && wrap != NULL)
+        *wrap = 1;
+
+    return a;
+}
+
+WC_STATIC WC_INLINE w64wrapper w64Sub32(w64wrapper a, word32 b, byte *wrap)
+{
+    if (a.n < b && wrap != NULL)
+        *wrap = 1;
+    a.n = a.n - b;
+    return a;
+}
+
+WC_STATIC WC_INLINE byte w64GT(w64wrapper a, w64wrapper b)
+{
+    return a.n > b.n;
+}
+
+WC_STATIC WC_INLINE byte w64IsZero(w64wrapper a)
+{
+    return a.n == 0;
+}
+
+WC_STATIC WC_INLINE void c64toa(const w64wrapper *a, byte *out)
+{
+#ifdef BIG_ENDIAN_ORDER
+    XMEMCPY(out, &a->n, sizeof(a->n));
+#else
+    word64 _out;
+    _out = ByteReverseWord64(a->n);
+    XMEMCPY(out, &_out, sizeof(_out));
+#endif /* BIG_ENDIAN_ORDER */
+}
+
+WC_STATIC WC_INLINE void ato64(const byte *in, w64wrapper *w64)
+{
+#ifdef BIG_ENDIAN_ORDER
+    XMEMCPY(&w64->n, in, sizeof(w64->n));
+#else
+    word64 _in;
+    XMEMCPY(&_in, in, sizeof(_in));
+    w64->n = ByteReverseWord64(_in);
+#endif /* BIG_ENDIAN_ORDER */
+}
+
+WC_STATIC WC_INLINE w64wrapper w64From32(word32 hi, word32 lo)
+{
+    w64wrapper ret;
+    ret.n = ((word64)hi << 32) | lo;
+    return ret;
+}
+
+WC_STATIC WC_INLINE byte w64GTE(w64wrapper a, w64wrapper b)
+{
+    return a.n >= b.n;
+}
+
+WC_STATIC WC_INLINE byte w64LT(w64wrapper a, w64wrapper b)
+{
+    return a.n < b.n;
+}
+
+WC_STATIC WC_INLINE w64wrapper w64Sub(w64wrapper a, w64wrapper b)
+{
+    a.n -= b.n;
+    return a;
+}
+
+WC_STATIC WC_INLINE void w64Zero(w64wrapper *a)
+{
+    a->n = 0;
+}
+
+#else
+WC_STATIC WC_INLINE void w64Increment(w64wrapper *n)
+{
+    n->n[1]++;
+    if (n->n[1] == 0)
+        n->n[0]++;
+}
+
+WC_STATIC WC_INLINE void w64Decrement(w64wrapper *n) {
+    if (n->n[1] == 0)
+        n->n[0]--;
+    n->n[1]--;
+}
+
+WC_STATIC WC_INLINE byte w64Equal(w64wrapper a, w64wrapper b)
+{
+    return (a.n[0] == b.n[0] && a.n[1] == b.n[1]);
+}
+
+WC_STATIC WC_INLINE word32 w64GetLow32(w64wrapper n) {
+    return n.n[1];
+}
+
+WC_STATIC WC_INLINE word32 w64GetHigh32(w64wrapper n) {
+    return n.n[0];
+}
+
+WC_STATIC WC_INLINE void w64SetLow32(w64wrapper *n, word32 low)
+{
+    n->n[1] = low;
+}
+
+WC_STATIC WC_INLINE w64wrapper w64Add32(w64wrapper a, word32 b, byte *wrap)
+{
+    a.n[1] = a.n[1] + b;
+    if (a.n[1] < b) {
+        a.n[0]++;
+        if (wrap != NULL && a.n[0] == 0)
+                *wrap = 1;
+    }
+
+    return a;
+}
+
+WC_STATIC WC_INLINE w64wrapper w64Sub32(w64wrapper a, word32 b, byte *wrap)
+{
+    byte _underflow = 0;
+    if (a.n[1] < b)
+        _underflow = 1;
+
+    a.n[1] -= b;
+    if (_underflow) {
+        if (a.n[0] == 0 && wrap != NULL)
+            *wrap = 1;
+        a.n[0]--;
+    }
+
+    return a;
+}
+
+WC_STATIC WC_INLINE w64wrapper w64Sub(w64wrapper a, w64wrapper b)
+{
+    if (a.n[1] < b.n[1])
+        a.n[0]--;
+    a.n[1] -= b.n[1];
+    a.n[0] -= b.n[0];
+    return a;
+}
+
+WC_STATIC WC_INLINE void w64Zero(w64wrapper *a)
+{
+    a->n[0] = a->n[1] = 0;
+}
+
+WC_STATIC WC_INLINE byte w64GT(w64wrapper a, w64wrapper b)
+{
+    if (a.n[0] > b.n[0])
+        return 1;
+    if (a.n[0] == b.n[0])
+        return a.n[1] > b.n[1];
+    return 0;
+}
+
+WC_STATIC WC_INLINE byte w64GTE(w64wrapper a, w64wrapper b)
+{
+    if (a.n[0] > b.n[0])
+        return 1;
+    if (a.n[0] == b.n[0])
+        return a.n[1] >= b.n[1];
+    return 0;
+}
+
+WC_STATIC WC_INLINE byte w64IsZero(w64wrapper a)
+{
+    return a.n[0] == 0 && a.n[1] == 0;
+}
+
+WC_STATIC WC_INLINE void c64toa(w64wrapper *a, byte *out)
+{
+#ifdef BIG_ENDIAN_ORDER
+    word32 *_out = (word32*)(out);
+    _out[0] = a->n[0];
+    _out[1] = a->n[1];
+#else
+    c32toa(a->n[0], out);
+    c32toa(a->n[1], out + 4);
+#endif /* BIG_ENDIAN_ORDER */
+}
+
+WC_STATIC WC_INLINE void ato64(const byte *in, w64wrapper *w64)
+{
+#ifdef BIG_ENDIAN_ORDER
+    const word32 *_in = (const word32*)(in);
+    w64->n[0] = *_in;
+    w64->n[1] = *(_in + 1);
+#else
+    ato32(in, &w64->n[0]);
+    ato32(in + 4, &w64->n[1]);
+#endif /* BIG_ENDIAN_ORDER */
+}
+
+WC_STATIC WC_INLINE w64wrapper w64From32(word32 hi, word32 lo)
+{
+    w64wrapper w64;
+    w64.n[0] = hi;
+    w64.n[1] = lo;
+    return w64;
+}
+
+WC_STATIC WC_INLINE byte w64LT(w64wrapper a, w64wrapper b)
+{
+    if (a.n[0] < b.n[0])
+        return 1;
+    if (a.n[0] == b.n[0])
+        return a.n[1] < b.n[1];
+
+    return 0;
+}
+
+#endif /* WORD64_AVAILABLE && !WOLFSSL_W64_WRAPPER_TEST */
+#endif /* WOLFSSL_W64_WRAPPER */
+
 #undef WC_STATIC
 
 #endif /* !WOLFSSL_MISC_INCLUDED && !NO_INLINE */

+ 5 - 0
wolfssl/wolfcrypt/settings.h

@@ -2700,6 +2700,11 @@ extern void uITRON4_free(void *p) ;
     #define NO_SESSION_CACHE_REF
 #endif
 
+/* DTLS v1.3 requires 64-bit number wrappers */
+#if defined(WOLFSSL_DTLS13) && !defined(WOLFSSL_W64_WRAPPER)
+    #define WOLFSSL_W64_WRAPPER
+#endif
+
 /* DTLS v1.3 requires AES ECB if using AES */
 #if defined(WOLFSSL_DTLS13) && !defined(NO_AES) && \
     !defined(WOLFSSL_AES_DIRECT)

+ 8 - 0
wolfssl/wolfcrypt/types.h

@@ -218,6 +218,14 @@ decouple library dependencies with standard string, memory and so on.
                              mp_digit, no 64 bit type so make mp_digit 16 bit */
 #endif
 
+typedef struct w64wrapper {
+#if defined(WORD64_AVAILABLE) && !defined(WOLFSSL_W64_WRAPPER_TEST)
+    word64 n;
+#else
+    word32 n[2];
+#endif /* WORD64_AVAILABLE && WOLFSSL_W64_WRAPPER_TEST */
+} w64wrapper;
+
 #ifdef WC_PTR_TYPE /* Allow user suppied type */
     typedef WC_PTR_TYPE wc_ptr_t;
 #elif defined(HAVE_UINTPTR_T)