Commit dc70836ce1 for openssl.org

commit dc70836ce1c51e1ed7a3a9af757aad9589db89d9
Author: Jakub Zelenka <jakub.zelenka@openssl.foundation>
Date:   Tue Jun 30 19:55:44 2026 +0200

    apps: test rsa app -RSAPublicKey_in/-RSAPublicKey_out options

    Cover the previously untested -RSAPublicKey_in and -RSAPublicKey_out
    options of the rsa app, which select the PKCS#1 RSAPublicKey structure
    rather than the SubjectPublicKeyInfo used by -pubin/-pubout. The new
    subtest checks that the RSA PUBLIC KEY header is written, that the
    encoding round-trips, and that it is interchangeable with the
    SubjectPublicKeyInfo form.

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

    Reviewed-by: Paul Dale <paul.dale@oracle.com>
    Reviewed-by: Tomas Mraz <tomas@openssl.foundation>
    MergeDate: Mon Jul 13 15:01:22 2026
    (Merged from https://github.com/openssl/openssl/pull/31802)

diff --git a/test/recipes/15-test_rsa.t b/test/recipes/15-test_rsa.t
index 851814e8af..3e60b23ef4 100644
--- a/test/recipes/15-test_rsa.t
+++ b/test/recipes/15-test_rsa.t
@@ -11,12 +11,13 @@ use strict;
 use warnings;

 use File::Spec;
+use File::Compare qw/compare/;
 use OpenSSL::Test qw/:DEFAULT srctop_file/;
 use OpenSSL::Test::Utils;

 setup("test_rsa");

-plan tests => 14;
+plan tests => 16;

 require_ok(srctop_file('test', 'recipes', 'tconversion.pl'));

@@ -54,7 +55,7 @@ sub run_rsa_tests {

     SKIP: {
          skip "Skipping msblob conversion test", 1
-             if disabled($cmd) || $cmd eq 'pkey';
+             if disabled("rsa") || $cmd eq 'pkey';

          subtest "$cmd conversions -- public key" => sub {
              tconversion( -type => 'msb', -prefix => "$cmd-msb-pub",
@@ -64,7 +65,7 @@ sub run_rsa_tests {
     }
     SKIP: {
          skip "Skipping PVK conversion test", 1
-             if disabled($cmd) || $cmd eq 'pkey' || disabled("rc4")
+             if disabled("rsa") || $cmd eq 'pkey' || disabled("rc4")
                 || disabled ("legacy") || disabled("pvkkdf");

          subtest "$cmd conversions -- private key" => sub {
@@ -76,4 +77,59 @@ sub run_rsa_tests {
                                     "-provider", "legacy"] );
          };
     }
+
+    SKIP: {
+         # -RSAPublicKey_in/-RSAPublicKey_out are specific to the rsa app and
+         # select the PKCS#1 RSAPublicKey structure instead of the
+         # SubjectPublicKeyInfo used by -pubin/-pubout.
+         skip "Skipping RSAPublicKey conversion test", 1
+             if disabled("rsa") || $cmd eq 'pkey';
+
+         subtest "$cmd conversions -- RSAPublicKey (PKCS#1) public key" => sub {
+             plan tests => 9;
+
+             my $priv = srctop_file("test", "testrsa.pem");
+             my $pub = srctop_file("test", "testrsapub.pem");
+
+             my $rsapub = "$cmd-rsapub.pem";
+             ok(run(app(['openssl', 'rsa', '-in', $priv, '-RSAPublicKey_out',
+                         '-out', $rsapub])),
+                "RSAPublicKey_out writes a public key");
+             open(my $fh, '<', $rsapub);
+             my @rsapub_pem = <$fh>;
+             close($fh);
+             ok(grep(/BEGIN RSA PUBLIC KEY/, @rsapub_pem),
+                "RSAPublicKey_out uses the PKCS#1 RSA PUBLIC KEY header");
+
+             # Re-encoding an RSAPublicKey input as RSAPublicKey is stable.
+             my $rsapub2 = "$cmd-rsapub2.pem";
+             ok(run(app(['openssl', 'rsa', '-in', $rsapub, '-RSAPublicKey_in',
+                         '-RSAPublicKey_out', '-out', $rsapub2])),
+                "RSAPublicKey_in reads an RSAPublicKey");
+             is(compare($rsapub, $rsapub2), 0,
+                "RSAPublicKey_in round-trips to an identical RSAPublicKey");
+
+             # RSAPublicKey input re-encoded as SubjectPublicKeyInfo matches the
+             # canonical SubjectPublicKeyInfo public key.
+             my $spki1 = "$cmd-spki1.pem";
+             my $spki2 = "$cmd-spki2.pem";
+             ok(run(app(['openssl', 'rsa', '-in', $rsapub, '-RSAPublicKey_in',
+                         '-pubout', '-out', $spki1])),
+                "RSAPublicKey_in can be written as SubjectPublicKeyInfo");
+             ok(run(app(['openssl', 'rsa', '-in', $pub, '-pubin', '-pubout',
+                         '-out', $spki2])),
+                "canonical SubjectPublicKeyInfo public key written");
+             is(compare($spki1, $spki2), 0,
+                "RSAPublicKey_in -pubout matches the SubjectPublicKeyInfo key");
+
+             # Conversely, a SubjectPublicKeyInfo input written as RSAPublicKey
+             # matches the RSAPublicKey extracted from the private key.
+             my $rsapub3 = "$cmd-rsapub3.pem";
+             ok(run(app(['openssl', 'rsa', '-in', $pub, '-pubin',
+                         '-RSAPublicKey_out', '-out', $rsapub3])),
+                "SubjectPublicKeyInfo input can be written as RSAPublicKey");
+             is(compare($rsapub, $rsapub3), 0,
+                "pubin -RSAPublicKey_out matches the extracted RSAPublicKey");
+         };
+    }
 }