Commit ff1dcf6a75 for openssl.org

commit ff1dcf6a7514a6766874290d8847f9ed0eedd7fa
Author: Jakub Zelenka <jakub.zelenka@openssl.foundation>
Date:   Mon Jun 22 19:47:23 2026 +0200

    apps: cover pkeyutl oneshot buffer path with empty file input

    The non-mmap buffer fallback in do_raw_keyop() for oneshot (only_nomd)
    keys was never exercised on Unix, since any file with non-zero size
    takes the mmap path and returns before reaching it. Signing and
    verifying an empty file gives filesize 0, which skips the mmap block
    (guarded by filesize > 0) and falls through to the buffer switch,
    covering both the SIGN and VERIFY arms.

    Assisted-by: Claude:claude-opus-4-8

    Reviewed-by: Daniel Kubec <kubec@openssl.foundation>
    Reviewed-by: Tomas Mraz <tomas@openssl.foundation>
    MergeDate: Thu Jun 25 17:00:36 2026
    (Merged from https://github.com/openssl/openssl/pull/31644)

diff --git a/test/recipes/20-test_pkeyutl.t b/test/recipes/20-test_pkeyutl.t
index 4458887f5c..e7552a8021 100644
--- a/test/recipes/20-test_pkeyutl.t
+++ b/test/recipes/20-test_pkeyutl.t
@@ -17,7 +17,7 @@ use File::Compare qw/compare_text compare/;

 setup("test_pkeyutl");

-plan tests => 31;
+plan tests => 32;

 # For the tests below we use the cert itself as the TBS file

@@ -214,7 +214,7 @@ SKIP: {
 }

 SKIP: {
-    skip "EdDSA is not supported by this OpenSSL build", 6
+    skip "EdDSA is not supported by this OpenSSL build", 7
         if disabled("ecx");

     subtest "pkeyutl -rawin oneshot with file input (mmap or buffer path)" => sub {
@@ -273,6 +273,41 @@ SKIP: {
         unlink($stderr_file) if -f $stderr_file;
     };

+    subtest "pkeyutl -rawin oneshot with empty file (buffer path, filesize 0)" => sub {
+        my $ed25519_key = srctop_file("test", "tested25519.pem");
+        my $ed25519_pub = srctop_file("test", "tested25519pub.pem");
+        my $empty = "pkeyutl_empty.bin";
+        my $sigfile = "rawin_empty_ed25519.sig";
+        # Ed25519 is deterministic, so signing the empty message with
+        # tested25519.pem always yields this exact signature.
+        my $expected_sig =
+            "42a443bd375c962f571dbf7402654219655b30c395dee06e" .
+            "d2a4a41342686da620889e374807266a3aab535345985c96" .
+            "cbb7475c8b0df47968d29fbf3d352e0c";
+
+        plan tests => 3;
+
+        # create a zero-length input file
+        open(my $fh, '>', $empty) or die "cannot create $empty: $!";
+        close($fh);
+
+        ok(run(app(['openssl', 'pkeyutl', '-sign', '-rawin', '-inkey', $ed25519_key,
+                    '-in', $empty, '-out', $sigfile])),
+           "Ed25519 -rawin sign from empty file (filesize 0 buffer path)");
+        ok(run(app(['openssl', 'pkeyutl', '-verify', '-rawin', '-pubin', '-inkey', $ed25519_pub,
+                    '-sigfile', $sigfile, '-in', $empty])),
+           "Ed25519 -rawin verify from empty file");
+
+        # check the produced signature matches the known reference value
+        open(my $sfh, '<:raw', $sigfile) or die "cannot open $sigfile: $!";
+        read($sfh, my $sig, -s $sigfile);
+        close($sfh);
+        is(unpack("H*", $sig), $expected_sig,
+           "Ed25519 -rawin empty file signature matches the reference value");
+
+        unlink($empty);
+    };
+
     subtest "Ed2559 CLI signature generation and verification" => sub {
         tsignverify("Ed25519",
                     srctop_file("test","tested25519.pem"),