[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