Raise an error on syscall failure in tls_retry_write_records
[openssl.git] / apps / pkey.c
index 5d12cc059a10e95bcb6ef41f7bd71b1c7aaf6593..3e4c09b362552e546dfa99ae365fa07daf6b748f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
 #include <string.h>
 #include "apps.h"
 #include "progs.h"
+#include "ec_common.h"
 #include <openssl/pem.h>
 #include <openssl/err.h>
 #include <openssl/evp.h>
-
-#ifndef OPENSSL_NO_EC
-# include <openssl/ec.h>
-
-static OPT_PAIR ec_conv_forms[] = {
-    {"compressed", POINT_CONVERSION_COMPRESSED},
-    {"uncompressed", POINT_CONVERSION_UNCOMPRESSED},
-    {"hybrid", POINT_CONVERSION_HYBRID},
-    {NULL}
-};
-
-static OPT_PAIR ec_param_enc[] = {
-    {"named_curve", OPENSSL_EC_NAMED_CURVE},
-    {"explicit", 0},
-    {NULL}
-};
-#endif
+#include <openssl/core_names.h>
 
 typedef enum OPTION_choice {
-    OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
+    OPT_COMMON,
     OPT_INFORM, OPT_OUTFORM, OPT_PASSIN, OPT_PASSOUT, OPT_ENGINE,
     OPT_IN, OPT_OUT, OPT_PUBIN, OPT_PUBOUT, OPT_TEXT_PUB,
     OPT_TEXT, OPT_NOOUT, OPT_CIPHER, OPT_TRADITIONAL, OPT_CHECK, OPT_PUB_CHECK,
@@ -82,24 +67,23 @@ const OPTIONS pkey_options[] = {
 
 int pkey_main(int argc, char **argv)
 {
-    BIO *in = NULL, *out = NULL;
+    BIO *out = NULL;
     ENGINE *e = NULL;
     EVP_PKEY *pkey = NULL;
     EVP_PKEY_CTX *ctx = NULL;
-    const EVP_CIPHER *cipher = NULL;
+    EVP_CIPHER *cipher = NULL;
     char *infile = NULL, *outfile = NULL, *passin = NULL, *passout = NULL;
-    char *passinarg = NULL, *passoutarg = NULL, *prog;
+    char *passinarg = NULL, *passoutarg = NULL, *ciphername = NULL, *prog;
     OPTION_CHOICE o;
-    int informat = FORMAT_PEM, outformat = FORMAT_PEM;
+    int informat = FORMAT_UNDEF, outformat = FORMAT_PEM;
     int pubin = 0, pubout = 0, text_pub = 0, text = 0, noout = 0, ret = 1;
     int private = 0, traditional = 0, check = 0, pub_check = 0;
 #ifndef OPENSSL_NO_EC
-    EC_KEY *eckey;
-    int ec_asn1_flag = OPENSSL_EC_NAMED_CURVE, new_ec_asn1_flag = 0;
-    int i, new_ec_form = 0;
-    point_conversion_form_t ec_form = POINT_CONVERSION_UNCOMPRESSED;
+    char *asn1_encoding = NULL;
+    char *point_format = NULL;
 #endif
 
+    opt_set_unknown_name("cipher");
     prog = opt_init(argc, argv, pkey_options);
     while ((o = opt_next()) != OPT_EOF) {
         switch (o) {
@@ -160,27 +144,24 @@ int pkey_main(int argc, char **argv)
             pub_check = 1;
             break;
         case OPT_CIPHER:
-            if (!opt_cipher(opt_unknown(), &cipher))
-                goto opthelp;
+            ciphername = opt_unknown();
             break;
         case OPT_EC_CONV_FORM:
 #ifdef OPENSSL_NO_EC
             goto opthelp;
 #else
-            if (!opt_pair(opt_arg(), ec_conv_forms, &i))
+            point_format = opt_arg();
+            if (!opt_string(point_format, point_format_options))
                 goto opthelp;
-            new_ec_form = 1;
-            ec_form = i;
             break;
 #endif
         case OPT_EC_PARAM_ENC:
 #ifdef OPENSSL_NO_EC
             goto opthelp;
 #else
-            if (!opt_pair(opt_arg(), ec_param_enc, &i))
+            asn1_encoding = opt_arg();
+            if (!opt_string(asn1_encoding, asn1_encoding_options))
                 goto opthelp;
-            new_ec_asn1_flag = 1;
-            ec_asn1_flag = i;
             break;
 #endif
         case OPT_PROV_CASES:
@@ -191,21 +172,26 @@ int pkey_main(int argc, char **argv)
     }
 
     /* No extra arguments. */
-    argc = opt_num_rest();
-    if (argc != 0)
+    if (!opt_check_rest_arg(NULL))
         goto opthelp;
 
-    if (noout && pubout)
-        BIO_printf(bio_err,
-                   "Warning: The -pubout option is ignored with -noout\n");
     if (text && text_pub)
         BIO_printf(bio_err,
                    "Warning: The -text option is ignored with -text_pub\n");
     if (traditional && (noout || outformat != FORMAT_PEM))
         BIO_printf(bio_err,
                    "Warning: The -traditional is ignored since there is no PEM output\n");
+
+    /* -pubout and -text is the same as -text_pub */
+    if (!text_pub && pubout && text) {
+        text = 0;
+        text_pub = 1;
+    }
+
     private = (!noout && !pubout) || (text && !text_pub);
 
+    if (!opt_cipher(ciphername, &cipher))
+        goto opthelp;
     if (cipher == NULL) {
         if (passoutarg != NULL)
             BIO_printf(bio_err,
@@ -234,20 +220,22 @@ int pkey_main(int argc, char **argv)
         goto end;
 
 #ifndef OPENSSL_NO_EC
-    /*
-     * TODO: remove this and use a set params call with a 'pkeyopt' command
-     * line option instead.
-     */
-    if (new_ec_form || new_ec_asn1_flag) {
-        if ((eckey = EVP_PKEY_get0_EC_KEY(pkey)) == NULL) {
-            ERR_print_errors(bio_err);
+    if (asn1_encoding != NULL || point_format != NULL) {
+        OSSL_PARAM params[3], *p = params;
+
+        if (!EVP_PKEY_is_a(pkey, "EC"))
             goto end;
-        }
-        if (new_ec_form)
-            EC_KEY_set_conv_form(eckey, ec_form);
 
-        if (new_ec_asn1_flag)
-            EC_KEY_set_asn1_flag(eckey, ec_asn1_flag);
+        if (asn1_encoding != NULL)
+            *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING,
+                                                    asn1_encoding, 0);
+        if (point_format != NULL)
+            *p++ = OSSL_PARAM_construct_utf8_string(
+                       OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,
+                       point_format, 0);
+        *p = OSSL_PARAM_construct_end();
+        if (EVP_PKEY_set_params(pkey, params) <= 0)
+            goto end;
     }
 #endif
 
@@ -260,7 +248,7 @@ int pkey_main(int argc, char **argv)
             goto end;
         }
 
-        if (check)
+        if (check && !pubin)
             r = EVP_PKEY_check(ctx);
         else
             r = EVP_PKEY_public_check(ctx);
@@ -272,15 +260,8 @@ int pkey_main(int argc, char **argv)
              * Note: at least for RSA keys if this function returns
              * -1, there will be no error reasons.
              */
-            unsigned long err;
-
-            BIO_printf(out, "Key is invalid\n");
-
-            while ((err = ERR_peek_error()) != 0) {
-                BIO_printf(out, "Detailed error: %s\n",
-                           ERR_reason_error_string(err));
-                ERR_get_error(); /* remove err from error stack */
-            }
+            BIO_printf(bio_err, "Key is invalid\n");
+            ERR_print_errors(bio_err);
             goto end;
         }
     }
@@ -339,9 +320,9 @@ int pkey_main(int argc, char **argv)
         ERR_print_errors(bio_err);
     EVP_PKEY_CTX_free(ctx);
     EVP_PKEY_free(pkey);
+    EVP_CIPHER_free(cipher);
     release_engine(e);
     BIO_free_all(out);
-    BIO_free(in);
     OPENSSL_free(passin);
     OPENSSL_free(passout);