Commit 98ed49849e for openssl.org

commit 98ed49849ecca7917cb14c900bb3fafcb667479f
Author: F. R. Da Silva <fdasilvayy@gmail.com>
Date:   Fri Mar 27 00:09:23 2026 +0100

    apps : enforce command-line parameter checking.

    Improve 'verify' option help messages.

    integer value parsing formats are:
    - 'n' is any integer
    - 'N' is a non-negative integer (i.e. value >= 0)
    - 'p' is a positive integer (i.e. value > 0)

    Reviewed-by: Eugene Syromiatnikov <esyr@openssl.org>
    Reviewed-by: Paul Dale <paul.dale@oracle.com>
    Reviewed-by: Frederik Wedel-Heinen <fwh.openssl@gmail.com>
    MergeDate: Mon Apr 13 09:30:22 2026
    (Merged from https://github.com/openssl/openssl/pull/30476)

diff --git a/apps/include/opt.h b/apps/include/opt.h
index a2facb0252..6b22f89ada 100644
--- a/apps/include/opt.h
+++ b/apps/include/opt.h
@@ -39,9 +39,9 @@
         { "purpose", OPT_V_PURPOSE, 's',                                                   \
             "certificate chain purpose" },                                                 \
         { "verify_name", OPT_V_VERIFY_NAME, 's', "verification policy name" },             \
-        { "verify_depth", OPT_V_VERIFY_DEPTH, 'n',                                         \
+        { "verify_depth", OPT_V_VERIFY_DEPTH, 'N',                                         \
             "chain depth limit" },                                                         \
-        { "auth_level", OPT_V_VERIFY_AUTH_LEVEL, 'n',                                      \
+        { "auth_level", OPT_V_VERIFY_AUTH_LEVEL, 'N',                                      \
             "chain authentication security level" },                                       \
         { "attime", OPT_V_ATTIME, 'M', "verification epoch time" },                        \
         { "verify_hostname", OPT_V_VERIFY_HOSTNAME, 's',                                   \
@@ -341,8 +341,9 @@ typedef struct options_st {
      * value type:
      *
      *   '-' no value (also the value zero)
-     *   'n' number (type 'int')
-     *   'p' positive number (type 'int')
+     *   'n' any number (type 'int')
+     *   'p' positive number (type 'int', value > 0)
+     *   'N' is a non-negative number (type 'int', value >= 0)
      *   'u' unsigned number (type 'unsigned long')
      *   'l' number (type 'unsigned long')
      *   'M' number (type 'intmax_t')
@@ -356,7 +357,7 @@ typedef struct options_st {
      *   'A' any ASN1, der/pem/b64 format  [OPT_FMT_ASN1]
      *   'c' pem/der/smime format          [OPT_FMT_PDS]
      *
-     * The 'l', 'n' and 'u' value types include the values zero,
+     * The 'l', 'n', 'N' and 'u' value types include the values zero,
      * the 'p' value type does not.
      */
     int valtype;
diff --git a/apps/kdf.c b/apps/kdf.c
index f94a5d11f2..7eaa1a19de 100644
--- a/apps/kdf.c
+++ b/apps/kdf.c
@@ -39,7 +39,7 @@ const OPTIONS kdf_options[] = {
     { "digest", OPT_DIGEST, 's', "Digest" },
     { "mac", OPT_MAC, 's', "MAC" },
     { OPT_MORE_STR, 1, '-', "See 'Supported Controls' in the EVP_KDF_ docs\n" },
-    { "keylen", OPT_KEYLEN, 's', "The size of the output derived key" },
+    { "keylen", OPT_KEYLEN, 'p', "The size of the output derived key" },

     OPT_SECTION("Output"),
     { "out", OPT_OUT, '>', "Output to filename rather than stdout" },
@@ -176,7 +176,7 @@ int kdf_main(int argc, char **argv)
         goto err;

     if (dkm_len <= 0) {
-        BIO_puts(bio_err, "Invalid derived key length.\n");
+        BIO_puts(bio_err, "Derived key length is mandatory!\n");
         goto err;
     }
     dkm_bytes = app_malloc(dkm_len, "out buffer");
diff --git a/apps/s_client.c b/apps/s_client.c
index b5e996d59c..d2d8175901 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -684,7 +684,7 @@ const OPTIONS s_client_options[] = {
     { "key", OPT_KEY, 's', "Private key file to use; default: -cert file" },
     { "keyform", OPT_KEYFORM, 'f', "Key format (DER/PEM)" },
     { "pass", OPT_PASS, 's', "Private key and cert file pass phrase source" },
-    { "verify", OPT_VERIFY, 'p', "Turn on peer certificate verification" },
+    { "verify", OPT_VERIFY, 'p', "Turn on peer certificate verification, set depth" },
     { "nameopt", OPT_NAMEOPT, 's', "Certificate subject/issuer name printing options" },
     { "CApath", OPT_CAPATH, '/', "PEM format directory of CA's" },
     { "CAfile", OPT_CAFILE, '<', "PEM format file of CA's" },
@@ -1658,6 +1658,12 @@ int s_client_main(int argc, char **argv)
             break;
         case OPT_ECH_GREASE_TYPE:
             ech_grease_type = opt_int_arg();
+            if (ech_grease_type != (ech_grease_type & 0xFFFF)) {
+                BIO_printf(bio_err,
+                    "%s: invalid GREASE ECH type 0x%8x\n permitted values are 0-FFFF",
+                    prog, ech_grease_type);
+                goto opthelp;
+            }
             break;
         case OPT_ECH_IGNORE_CONFIG_ID:
             ech_ignore_cid = 1;
diff --git a/apps/s_server.c b/apps/s_server.c
index 38db88437e..cd5a8aab97 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -1349,9 +1349,9 @@ const OPTIONS s_server_options[] = {
     { "no-CAstore", OPT_NOCASTORE, '-',
         "Do not load certificates from the default certificates store URI" },
     { "nocert", OPT_NOCERT, '-', "Don't use any certificates (Anon-DH)" },
-    { "verify", OPT_VERIFY, 'n', "Turn on peer certificate verification" },
-    { "Verify", OPT_UPPER_V_VERIFY, 'n',
-        "Turn on peer certificate verification, must have a cert" },
+    { "verify", OPT_VERIFY, 'p', "Turn on peer certificate verification, set depth" },
+    { "Verify", OPT_UPPER_V_VERIFY, 'p',
+        "Turn on peer certificate verification, must have a cert, set depth" },
     { "nameopt", OPT_NAMEOPT, 's', "Certificate subject/issuer name printing options" },
     { "cert", OPT_CERT, '<', "Server certificate file to use; default " TEST_CERT },
     { "cert2", OPT_CERT2, '<',
@@ -1442,7 +1442,7 @@ const OPTIONS s_server_options[] = {
         "Provide certificate status response(s) if requested, for the whole chain" },
     { "status_verbose", OPT_STATUS_VERBOSE, '-',
         "Print more output in certificate status callback" },
-    { "status_timeout", OPT_STATUS_TIMEOUT, 'n',
+    { "status_timeout", OPT_STATUS_TIMEOUT, 'N',
         "Status request responder timeout" },
     { "status_url", OPT_STATUS_URL, 's', "Status request fallback URL" },
     { "proxy", OPT_PROXY, 's',
@@ -1499,9 +1499,9 @@ const OPTIONS s_server_options[] = {
 #endif

     OPT_SECTION("Protocol and version"),
-    { "max_early_data", OPT_MAX_EARLY, 'n',
+    { "max_early_data", OPT_MAX_EARLY, 'N',
         "The maximum number of bytes of early data as advertised in tickets" },
-    { "recv_max_early_data", OPT_RECV_MAX_EARLY, 'n',
+    { "recv_max_early_data", OPT_RECV_MAX_EARLY, 'N',
         "The maximum number of bytes of early data (hard limit)" },
     { "early_data", OPT_EARLY_DATA, '-', "Attempt to read early data" },
     { "num_tickets", OPT_S_NUM_TICKETS, 'n',
diff --git a/apps/x509.c b/apps/x509.c
index 7b7706a05e..824daa1ef5 100644
--- a/apps/x509.c
+++ b/apps/x509.c
@@ -197,7 +197,7 @@ const OPTIONS x509_options[] = {
         "[CC]YYMMDDHHMMSSZ value for notBefore certificate field" },
     { "not_after", OPT_NOT_AFTER, 's',
         "[CC]YYMMDDHHMMSSZ value for notAfter certificate field, overrides -days" },
-    { "days", OPT_DAYS, 'n',
+    { "days", OPT_DAYS, 'p',
         "Number of days until newly generated certificate expires - default 30" },
     { "preserve_dates", OPT_PRESERVE_DATES, '-',
         "Preserve existing validity dates" },