[openssh-commits] [openssh] 12/14: upstream: missing part of previous commit: update script to

git+noreply at mindrot.org git+noreply at mindrot.org
Wed Sep 16 11:16:06 AEST 2026


This is an automated email from the git hooks/post-receive script.

djm pushed a commit to branch master
in repository openssh.

commit c5c4ca2b77fa8f4498d46d59dde81a57111c5660
Author: djm at openbsd.org <djm at openbsd.org>
AuthorDate: Wed Sep 16 00:46:17 2026 +0000

    upstream: missing part of previous commit: update script to
    
    import ed25519 implementation from libsodium
    
    OpenBSD-Commit-ID: 1f3d60686a8ce15212d8730814dfb8213fdf96ac
---
 ed25519.sh | 425 +++++++++++++++++++++++++++++++++++++------------------------
 1 file changed, 258 insertions(+), 167 deletions(-)

diff --git a/ed25519.sh b/ed25519.sh
index 987f61d80..9a4089a03 100644
--- a/ed25519.sh
+++ b/ed25519.sh
@@ -1,183 +1,274 @@
 #!/bin/sh
-#       $OpenBSD: ed25519.sh,v 1.6 2026/06/14 04:16:19 djm Exp $
+#       $OpenBSD: ed25519.sh,v 1.7 2026/09/16 00:46:17 djm Exp $
 #       Placed in the Public Domain.
-#
-AUTHOR="supercop-20221122/crypto_sign/ed25519/ref/implementors"
-FILES="
-	supercop-20221122/crypto_verify/32/ref/verify.c
-	supercop-20221122/crypto_sign/ed25519/ref/fe25519.h
-	supercop-20221122/crypto_sign/ed25519/ref/fe25519.c
-	supercop-20221122/crypto_sign/ed25519/ref/sc25519.h
-	supercop-20221122/crypto_sign/ed25519/ref/sc25519.c
-	supercop-20221122/crypto_sign/ed25519/ref/ge25519.h
-	supercop-20221122/crypto_sign/ed25519/ref/ge25519.c
-	supercop-20221122/crypto_sign/ed25519/ref/keypair.c
-	supercop-20221122/crypto_sign/ed25519/ref/sign.c
-	supercop-20221122/crypto_sign/ed25519/ref/open.c
-"
-###
-PORTABLE=${PORTABLE:-0}
 
-DATA="supercop-20221122/crypto_sign/ed25519/ref/ge25519_base.data"
+set -eu
+SCRIPT_DIR="$PWD"
+LIBSODIUM_DIR="$SCRIPT_DIR/libsodium"
+OUT="$SCRIPT_DIR/ed25519.c"
+NEW="$OUT.new"
+CHECK_C="$SCRIPT_DIR/ed25519_check.c"
+CHECK="$SCRIPT_DIR/ed25519_check"
+CHECK_O="$SCRIPT_DIR/ed25519_check.o"
+CORE=src/libsodium/crypto_core/ed25519/ref10
+SIGN=src/libsodium/crypto_sign/ed25519/ref10
+PRIVATE=src/libsodium/include/sodium/private
 
-set -e
-test -z "$1" || cd $1
-echo -n '/*  $'
-echo 'OpenBSD: $ */'
-echo
-echo '/*'
-echo ' * Public Domain, Authors:'
-sed -e '/Alphabetical order:/d' -e 's/^/ * - /' < $AUTHOR
-echo ' */'
-echo
-if [ "$PORTABLE" -ne 0 ]; then
-	echo '#include "includes.h"'
-	echo
-	echo '#ifndef OPENSSL_HAS_ED25519'
-	echo
-fi
-echo '#include <string.h>'
-echo
-echo '#include "crypto_api.h"'
-echo
-# Map the types used in this code to the ones in crypto_api.h.  We use #define
-# instead of typedef since some systems have existing intXX types and do not
-# permit multiple typedefs even if they do not conflict.
-for t in int8 uint8 int16 uint16 int32 uint32 int64 uint64; do
-	echo "#define $t crypto_${t}"
+die() { echo "ed25519.sh: $*" >&2; exit 1; }
+cleanup() { return;rm -f "$NEW" "$CHECK_C" "$CHECK" "$CHECK_O"; }
+trap cleanup EXIT HUP INT TERM
+
+test -d "$LIBSODIUM_DIR/.git" || die "$LIBSODIUM_DIR is not a libsodium checkout"
+test -z "$(git -C "$LIBSODIUM_DIR" status --short)" || die "libsodium tree has uncommitted changes"
+LIBSODIUM_REVISION=$(git -C "$LIBSODIUM_DIR" rev-parse HEAD)
+
+for f in LICENSE "$PRIVATE/ed25519_ref10.h" \
+    "$PRIVATE/ed25519_ref10_fe_25_5.h" "$CORE/fe_25_5/constants.h" \
+    "$CORE/fe_25_5/fe.h" "$CORE/fe_25_5/base.h" \
+    "$CORE/fe_25_5/base2.h" "$CORE/ed25519_ref10.c" \
+    "$SIGN/sign_ed25519_ref10.h" "$SIGN/keypair.c" "$SIGN/sign.c" \
+    "$SIGN/open.c"; do
+	test -f "$LIBSODIUM_DIR/$f" || die "missing libsodium source: $f"
 done
-echo
-for i in $FILES; do
-	echo "/* from $i */"
-
-	case "$i" in
-	*/crypto_sign/ed25519/ref/open.c)
-	# Include our malleability fix at the start if open.c
-	cat << _EOF
-
-/*
- * Local OpenSSH addition: check that S < group order L
- * Where L = 2^{252} + 27742317777372353535851937790883648493
- * This can be variable time as the signature is public.
- */
-static inline int sc25519_inrange(const unsigned char *s)
+
+(
+	printf '/*  $OpenBSD: ed25519.sh,v 1.7 2026/09/16 00:46:17 djm Exp $ */\n\n'
+	echo "/* Extracted from libsodium revision $LIBSODIUM_REVISION */"
+	echo
+	cat "$LIBSODIUM_DIR/LICENSE"
+	cat <<'EOF'
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "crypto_api.h"
+
+/* OpenSSH compatibility glue for the small libsodium API subset below. */
+#define ACQUIRE_FENCE (void)0
+#define COMPILER_ASSERT(x) (void)sizeof(char[(x) ? 1 : -1])
+
+#ifdef WITH_OPENSSL
+# include <openssl/sha.h>
+typedef SHA512_CTX crypto_hash_sha512_state;
+#else
+typedef SHA2_CTX crypto_hash_sha512_state;
+#endif
+
+static int
+crypto_hash_sha512_init(crypto_hash_sha512_state *state)
+{
+#ifdef WITH_OPENSSL
+	SHA512_Init(state);
+#else
+	SHA512Init(state);
+#endif
+	return 0;
+}
+
+static int
+crypto_hash_sha512_update(crypto_hash_sha512_state *state,
+    const unsigned char *in, unsigned long long inlen)
 {
-  int i;
+#ifdef WITH_OPENSSL
+	SHA512_Update(state, in, inlen);
+#else
+	SHA512Update(state, in, inlen);
+#endif
+	return 0;
+}
 
-  for (i = 0; i < 32; i++) {
-    if (s[31 - i] > sc25519_m[31 - i]) return -1;
-    if (s[31 - i] < sc25519_m[31 - i]) return 0;
-  }
-  return -1;
+static int
+crypto_hash_sha512_final(crypto_hash_sha512_state *state, unsigned char *out)
+{
+#ifdef WITH_OPENSSL
+	SHA512_Final(out, state);
+#else
+	SHA512Final(out, state);
+#endif
+	return 0;
 }
-_EOF
-	;;
-	esac
-
-	nl=`echo`
-	# Changes to all files:
-	#  - inline ge25519_base.data where it is included
-	#  - expand CRYPTO_NAMESPACE() namespacing define
-	#  - remove all includes, we inline everything required.
-	#  - make functions not required elsewhere static.
-	#  - rename the functions we do use.
+
+static int
+sodium_is_zero(const unsigned char *n, size_t nlen)
+{
+	size_t i;
+	volatile unsigned char d = 0;
+
+	for (i = 0; i < nlen; i++)
+		d |= n[i];
+	return 1 & ((d - 1) >> 8);
+}
+
+EOF
+
+	sed -e '/^#include/d' -e '/^# *include/d' \
+	    -e 's/^void /static void /' \
+	    -e 's/^int /static int /' \
+	    -e '/ ge25519_is_on_curve(/d' \
+	    -e '/ ge25519_is_on_main_subgroup(/d' \
+	    -e '/ ge25519_tobytes(/d' \
+	    -e '/ ge25519_scalarmult(/,/);/d' \
+	    -e '/ ge25519_clear_cofactor(/d' \
+	    -e '/ ge25519_from_uniform(/d' \
+	    -e '/ ge25519_from_hash(/d' \
+	    -e '/ ristretto255_frombytes(/d' \
+	    -e '/ ristretto255_p3_tobytes(/d' \
+	    -e '/ ristretto255_from_hash(/d' \
+	    -e '/ sc25519_mul(/,/);/d' \
+	    -e '/ sc25519_invert(/d' \
+	    "$LIBSODIUM_DIR/$PRIVATE/ed25519_ref10.h"
+	sed -e '/^#include/d' \
+	    "$LIBSODIUM_DIR/$PRIVATE/ed25519_ref10_fe_25_5.h" | \
+	perl -0777 -pe '
+	    s/^static void\nfe25519_cswap\(.*?^\}\n//ms;
+	    s/^static inline void\nfe25519_mul32\(.*?^\}\n//ms;
+	'
+
 	sed \
-	    -e "/#include \"ge25519_base.data\"/r $DATA" \
-	    -e "/#include/d" \
-	    -e "s/^void /static void /g" \
-	    -e 's/CRYPTO_NAMESPACE[(]\([a-zA-Z0-9_]*\)[)]/crypto_sign_ed25519_ref_\1/g' \
-	    $i | \
-	case "$i" in
-	*/crypto_verify/32/ref/verify.c)
-	    # rename crypto_verify() to the name that the ed25519 code expects.
-	    sed -e "/^#include.*/d" \
-	        -e "s/crypto_verify/crypto_verify_32/g" \
-	        -e "s/^int /static int /g"
-	    ;;
-	*/crypto_sign/ed25519/ref/sign.c)
-	    # rename signing function to the name OpenSSH expects
-	    sed -e "s/crypto_sign/crypto_sign_ed25519/g"
-	    ;;
-	*/crypto_sign/ed25519/ref/keypair.c)
-	    # provide an explicit-seed key generation function and rename
-	    # it to the name OpenSSH expects
-	    sed -e "s/int crypto_sign_keypair(unsigned char \*pk,unsigned char \*sk)/int crypto_sign_ed25519_keypair_from_seed(unsigned char *pk,unsigned char *sk, const unsigned char *seed)/g" \
-	        -e "s/randombytes(sk,32);/memcpy(sk, seed, 32);/g"
-	    ;;
-	*/crypto_sign/ed25519/ref/open.c)
-	    # rename verification function to the name OpenSSH expects
-	    # Insert malleability checks
-	    sed -e "s/crypto_sign_open/crypto_sign_ed25519_open/g" | \
-	    perl -0777 -pe 's/(.*if.*ge25519_unpackneg_vartime.*get1,pk.*)/  if (sc25519_inrange(sm+32)) goto badsig;\n\1\n  if (ge25519_isneutral_vartime(&get1)) goto badsig;/'
-	    #perl -0777 -pe 's/^(.*ge25519_unpackneg_vartime.*,pk.*)$/  if (sc25519_inrange(sm+32)) goto badsig;\n$1\n  if (ge25519_isneutral_vartime(&get1)) goto badsig;/'
-	    ;;
-	*/crypto_sign/ed25519/ref/fe25519.*)
-	    # avoid a couple of name collisions with other files
-	    sed -e "s/reduce_add_sub/fe25519_reduce_add_sub/g" \
-	        -e "s/ equal[(]/ fe25519_equal(/g" \
-	        -e "s/^int /static int /g"
-	    ;;
-	*/crypto_sign/ed25519/ref/sc25519.h)
-	    # Lots of unused prototypes to remove
-	    sed -e "s/^int /static int /g" \
-	        -e '/shortsc25519_from16bytes/d' \
-	        -e '/sc25519_iszero_vartime/d' \
-	        -e '/sc25519_isshort_vartime/d' \
-	        -e '/sc25519_lt_vartime/d' \
-	        -e '/sc25519_sub_nored/d' \
-	        -e '/sc25519_mul_shortsc/d' \
-	        -e '/sc25519_from_shortsc/d' \
-	        -e '/sc25519_window5/d'
-	    ;;
-	*/crypto_sign/ed25519/ref/sc25519.c)
-	    # Lots of unused code to remove, some name collisions to avoid
-	    sed -e "s/reduce_add_sub/sc25519_reduce_add_sub/g" \
-	        -e "s/ equal[(]/ sc25519_equal(/g" \
-	        -e "s/^int /static int /g" \
-	        -e "s/m[[]/sc25519_m[/g" \
-	        -e "s/mu[[]/sc25519_mu[/g" \
-	        -e '/shortsc25519_from16bytes/,/^}$/d' \
-	        -e '/sc25519_iszero_vartime/,/^}$/d' \
-	        -e '/sc25519_isshort_vartime/,/^}$/d' \
-	        -e '/sc25519_lt_vartime/,/^}$/d' \
-	        -e '/sc25519_sub_nored/,/^}$/d' \
-	        -e '/sc25519_mul_shortsc/,/^}$/d' \
-	        -e '/sc25519_from_shortsc/,/^}$/d' \
-	        -e '/sc25519_window5/,/^}$/d'
-	    ;;
-	*/crypto_sign/ed25519/ref//ge25519.*)
-	    sed -e "s/^int /static int /g"
-	    ;;
-	# Default: pass through.
-	*)
-	    cat
-	    ;;
-	esac | \
-	sed -e 's/[	 ]*$//'
+	    -e "/# include \"fe_25_5\/constants.h\"/r $LIBSODIUM_DIR/$CORE/fe_25_5/constants.h" \
+	    -e "/# include \"fe_25_5\/fe.h\"/r $LIBSODIUM_DIR/$CORE/fe_25_5/fe.h" \
+	    -e "/# include \"fe_25_5\/base.h\"/r $LIBSODIUM_DIR/$CORE/fe_25_5/base.h" \
+	    -e "/# include \"fe_25_5\/base2.h\"/r $LIBSODIUM_DIR/$CORE/fe_25_5/base2.h" \
+	    -e '/^#include/d' -e '/^# include/d' \
+	    -e 's/^void /static void /' -e 's/^int /static int /' \
+	    "$LIBSODIUM_DIR/$CORE/ed25519_ref10.c" | \
+	sed -e '/^#include/d' -e '/^# include/d' | \
+	perl -0777 -pe '
+	    s/^static const fe25519 (?:ed25519_sqrtam2|ed25519_A|ed25519_sqrtadm1|ed25519_invsqrtamd|ed25519_onemsqd|ed25519_sqdmone) = \{.*?^\};\n//msg;
+	    s/^#define ed25519_A_32 .*\n//m;
+	    s/^static inline void\nfe25519_sqmul\(.*?^\}\n//ms;
+	    s/^static inline void\nfe25519_cneg\(.*?^\}\n//ms;
+	    s/^static inline void\nfe25519_abs\(.*?^\}\n//ms;
+	    s/^static void\nfe25519_unchecked_sqrt\(.*?^\}\n//ms;
+	    s/^static int\nfe25519_sqrt\(.*?^\}\n//ms;
+	    s/^static int\nfe25519_notsquare\(.*?^\}\n//ms;
+	    s/^static void\nge25519_p3_to_precomp\(.*?^\}\n//ms;
+	    s/^static void\nge25519_cached_0\(.*?^\}\n//ms;
+	    s/^static void\nge25519_cmov_cached\(.*?^\}\n//ms;
+	    s/^static void\nge25519_cmov8_cached\(.*?^\}\n//ms;
+	    s/^(?:static )?void\nge25519_tobytes\(.*?^\}\n//ms;
+	    s/^(?:static )?void\nge25519_scalarmult\(.*?^\}\n//ms;
+	    s/^static void\nge25519_p3p3_dbl\(.*?^\}\n//ms;
+	    s/^static void\nge25519_p3_dbladd\(.*?^\}\n//ms;
+	    s/^(?:static )?int\nge25519_is_on_curve\(.*?^\}\n//ms;
+	    s/^(?:static )?int\nge25519_is_on_main_subgroup\(.*?^\}\n//ms;
+	    s/^static void\nge25519_mul_l\(.*?^\}\n//ms;
+	    s/^(?:static )?void\nsc25519_mul\(.*?^\}\n//ms;
+	    s/^static inline void\nsc25519_sqmul\(.*?^\}\n//ms;
+	    s/^static inline void\nsc25519_sq\(.*?^\}\n//ms;
+	    s/^(?:static )?void\nsc25519_invert\(.*?^\}\n//ms;
+	    s/^static void\nge25519_mont_to_ed\(.*?^\}\n//ms;
+	    s/^static int\nge25519_xmont_to_ymont\(.*?^\}\n//ms;
+	    s/^(?:static )?void\nge25519_clear_cofactor\(.*?^\}\n//ms;
+	    s/^static void\nge25519_elligator2\(.*?^\}\n//ms;
+	    s/^(?:static )?void\nge25519_from_uniform\(.*?^\}\n//ms;
+	    s/^static void\nfe25519_reduce64\(.*?^\}\n//ms;
+	    s/^(?:static )?void\nge25519_from_hash\(.*?^\}\n//ms;
+	    s/^static int\nristretto255_sqrt_ratio_m1\([\s\S]*\z//m;
+	'
 
-	# Include implicit-seed keygen function used for ssh-ed25519
-	case "$i" in
-	*/crypto_sign/ed25519/ref/keypair.c)
-	cat << _EOF
+	sed -e '/^#include/d' -e 's/^void /static void /' \
+	    -e 's/^int /static int /' \
+	    "$LIBSODIUM_DIR/$SIGN/sign_ed25519_ref10.h"
+
+	sed -e '/^#include/d' -e 's/sodium_memzero/explicit_bzero/g' \
+	    -e 's/randombytes_buf/arc4random_buf/g' \
+	    -e '/^int$/N; /crypto_sign_ed25519_pk_to_curve25519/,$d' \
+	    "$LIBSODIUM_DIR/$SIGN/keypair.c"
+
+	sed -e '/^#include/d' -e 's/sodium_memzero/explicit_bzero/g' \
+	    -e 's/^void$/static void/' -e '/^int$/N; /crypto_sign_ed25519(/,$d' \
+	    "$LIBSODIUM_DIR/$SIGN/sign.c" | \
+	sed -e '/^int$/N; /_crypto_sign_ed25519_detached/ { s/^int$/static int/; }'
+
+	sed -e '/^#include/d' -e '/^int$/N; /crypto_sign_ed25519_open/,$d' \
+	    "$LIBSODIUM_DIR/$SIGN/open.c" | \
+	sed -e '/^int$/N; /_crypto_sign_ed25519_verify_detached/ { s/^int$/static int/; }'
+
+	echo
+) | sed -e 's/[[:space:]]*$//' > "$NEW"
+
+cat > "$CHECK_C" <<'EOF'
+#include "ed25519.c.new"
+
+#include <err.h>
+
+static int
+hexval(char c)
+{
+	if (c >= '0' && c <= '9') return c - '0';
+	if (c >= 'a' && c <= 'f') return c - 'a' + 10;
+	err(1, "invalid hex digit");
+}
+
+static void
+unhex(unsigned char *out, size_t outlen, const char *hex)
+{
+	size_t i;
+	for (i = 0; i < outlen; i++)
+		out[i] = (hexval(hex[i * 2]) << 4) | hexval(hex[i * 2 + 1]);
+}
 
 int
-crypto_sign_ed25519_keypair(unsigned char *pk, unsigned char *sk)
+main(void)
 {
-  unsigned char seed[32];
-  int r;
+	static const char seedhex[] =
+	    "9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60";
+	static const char pkhex[] =
+	    "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a";
+	static const char sighex[] =
+	    "e5564300c360ac729086e2cc806e828a84877f1e"
+	    "b8e5d974d873e065224901555fb8821590a33bac"
+	    "c61e39701cf9b46bd25bf5f0595bbe2465514143"
+	    "8e7a100b";
+	unsigned char seed[32], pk[32], wantpk[32], sk[64];
+	unsigned char sig[64], wantsig[64], msg[1] = { 0 }, randompk[32], randomsk[64];
+	unsigned long long siglen = 0;
 
-  randombytes(seed, 32);
-  r = crypto_sign_ed25519_keypair_from_seed(pk, sk, seed);
-  explicit_bzero(seed, sizeof(seed));
-  return r;
+	unhex(seed, sizeof(seed), seedhex);
+	unhex(wantpk, sizeof(wantpk), pkhex);
+	unhex(wantsig, sizeof(wantsig), sighex);
+	if (crypto_sign_ed25519_seed_keypair(pk, sk, seed) != 0 ||
+	    memcmp(pk, wantpk, sizeof(pk)) != 0)
+		errx(1, "seed keypair KAT failed");
+	if (crypto_sign_ed25519_detached(sig, &siglen, msg, 0, sk) != 0 ||
+	    siglen != sizeof(sig) || memcmp(sig, wantsig, sizeof(sig)) != 0)
+		errx(1, "signature KAT failed");
+	if (crypto_sign_ed25519_verify_detached(sig, msg, 0, pk) != 0)
+		errx(1, "verification failed");
+	sig[10] ^= 1;
+	if (crypto_sign_ed25519_verify_detached(sig, msg, 0, pk) == 0)
+		errx(1, "corrupt signature accepted");
+	if (crypto_sign_ed25519_keypair(randompk, randomsk) != 0 ||
+	    crypto_sign_ed25519_detached(sig, &siglen, msg, sizeof(msg), randomsk) != 0 ||
+	    crypto_sign_ed25519_verify_detached(sig, msg, sizeof(msg), randompk) != 0)
+		errx(1, "random keypair smoke test failed");
+	msg[0] ^= 1;
+	if (crypto_sign_ed25519_verify_detached(sig, msg, sizeof(msg), randompk) == 0)
+		errx(1, "modified message accepted");
+	return 0;
 }
-_EOF
-	;;
-	esac
+EOF
 
-done
-
-if [ "$PORTABLE" -ne 0 ]; then
-       echo
-       echo '#endif /* OPENSSL_HAS_ED25519 */'
-fi
+cd "$SCRIPT_DIR"
+${CC:-cc} -Wall -Wextra -Wno-unused-function -Wno-unused-parameter \
+    -I. -c ed25519_check.c -o ed25519_check.o
+globals=$(nm -g ed25519_check.o | \
+    grep -E "^([0-9a-fA-F]+)?[[:space:]]+T[[:space:]]" | \
+    awk '{ print $3}' | \
+    grep -v "^main$")
+expected='crypto_sign_ed25519_detached
+crypto_sign_ed25519_keypair
+crypto_sign_ed25519_seed_keypair
+crypto_sign_ed25519_verify_detached'
+test "$globals" = "$expected" || {
+	echo "unexpected global symbols in ed25519.c:" >&2
+	echo "$globals" >&2
+	exit 1
+}
+${CC:-cc} -o ed25519_check ed25519_check.o 
+./ed25519_check
+mv "$NEW" "$OUT"
+echo "ed25519.c OK (libsodium $LIBSODIUM_REVISION)" >&2

-- 
To stop receiving notification emails like this one, please contact
djm at mindrot.org.


More information about the openssh-commits mailing list