use 64 bit math to avoid signed underflow. upstream code relies on
authordjm <djm@openbsd.org>
Mon, 16 Sep 2024 05:37:05 +0000 (05:37 +0000)
committerdjm <djm@openbsd.org>
Mon, 16 Sep 2024 05:37:05 +0000 (05:37 +0000)
using -fwrapv to provide defined over/underflow behaviour, but we use
-ftrapv to catch integer errors and abort the program. ok dtucker@

usr.bin/ssh/sntrup761.c
usr.bin/ssh/sntrup761.sh

index 81ae5dc..52525cf 100644 (file)
@@ -1,4 +1,4 @@
-/*  $OpenBSD: sntrup761.c,v 1.7 2024/09/15 02:20:51 djm Exp $ */
+/*  $OpenBSD: sntrup761.c,v 1.8 2024/09/16 05:37:05 djm Exp $ */
 
 /*
  * Public Domain, Authors:
@@ -912,8 +912,8 @@ crypto_int32 crypto_int32_min(crypto_int32 crypto_int32_x,crypto_int32 crypto_in
   __asm__ ("cmp %w0,%w1\n csel %w0,%w0,%w1,lt" : "+r"(crypto_int32_x) : "r"(crypto_int32_y) : "cc");
   return crypto_int32_x;
 #else
-  crypto_int32 crypto_int32_r = crypto_int32_y ^ crypto_int32_x;
-  crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x;
+  crypto_int64 crypto_int32_r = (crypto_int64)crypto_int32_y ^ (crypto_int64)crypto_int32_x;
+  crypto_int64 crypto_int32_z = (crypto_int64)crypto_int32_y - (crypto_int64)crypto_int32_x;
   crypto_int32_z ^= crypto_int32_r & (crypto_int32_z ^ crypto_int32_y);
   crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z);
   crypto_int32_z &= crypto_int32_r;
@@ -931,8 +931,8 @@ crypto_int32 crypto_int32_max(crypto_int32 crypto_int32_x,crypto_int32 crypto_in
   __asm__ ("cmp %w0,%w1\n csel %w0,%w1,%w0,lt" : "+r"(crypto_int32_x) : "r"(crypto_int32_y) : "cc");
   return crypto_int32_x;
 #else
-  crypto_int32 crypto_int32_r = crypto_int32_y ^ crypto_int32_x;
-  crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x;
+  crypto_int64 crypto_int32_r = (crypto_int64)crypto_int32_y ^ (crypto_int64)crypto_int32_x;
+  crypto_int64 crypto_int32_z = (crypto_int64)crypto_int32_y - (crypto_int64)crypto_int32_x;
   crypto_int32_z ^= crypto_int32_r & (crypto_int32_z ^ crypto_int32_y);
   crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z);
   crypto_int32_z &= crypto_int32_r;
@@ -956,8 +956,8 @@ void crypto_int32_minmax(crypto_int32 *crypto_int32_p,crypto_int32 *crypto_int32
   *crypto_int32_p = crypto_int32_r;
   *crypto_int32_q = crypto_int32_s;
 #else
-  crypto_int32 crypto_int32_r = crypto_int32_y ^ crypto_int32_x;
-  crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x;
+  crypto_int64 crypto_int32_r = (crypto_int64)crypto_int32_y ^ (crypto_int64)crypto_int32_x;
+  crypto_int64 crypto_int32_z = (crypto_int64)crypto_int32_y - (crypto_int64)crypto_int32_x;
   crypto_int32_z ^= crypto_int32_r & (crypto_int32_z ^ crypto_int32_y);
   crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z);
   crypto_int32_z &= crypto_int32_r;
index 92c803b..4de8dc3 100644 (file)
@@ -1,5 +1,5 @@
 #!/bin/sh
-#       $OpenBSD: sntrup761.sh,v 1.8 2024/09/15 02:20:51 djm Exp $
+#       $OpenBSD: sntrup761.sh,v 1.9 2024/09/16 05:37:05 djm Exp $
 #       Placed in the Public Domain.
 #
 AUTHOR="supercop-20240808/crypto_kem/sntrup761/ref/implementors"
@@ -63,8 +63,13 @@ for i in $FILES; do
                -e "s/static void crypto_int16_minmax/void crypto_int16_minmax/"
            ;;
        */cryptoint/crypto_int32.h)
+       # Use int64_t for intermediate values in crypto_int32_minmax to
+       # prevent signed 32-bit integer overflow when called by
+       # crypto_sort_int32. Original code depends on -fwrapv (we set -ftrapv)
            sed -e "s/static void crypto_int32_store/void crypto_int32_store/" \
                -e "s/^[#]define crypto_int32_optblocker.*//" \
+               -e "s/crypto_int32 crypto_int32_r = crypto_int32_y ^ crypto_int32_x;/crypto_int64 crypto_int32_r = (crypto_int64)crypto_int32_y ^ (crypto_int64)crypto_int32_x;/" \
+               -e "s/crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x;/crypto_int64 crypto_int32_z = (crypto_int64)crypto_int32_y - (crypto_int64)crypto_int32_x;/" \
                -e "s/static void crypto_int32_minmax/void crypto_int32_minmax/"
            ;;
        */cryptoint/crypto_int64.h)