summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorshridhar kalavagunta <coolshrid@hotmail.com>2024-11-28 18:30:50 +0100
committerTomas Mraz <tomas@openssl.org>2025-01-15 13:26:41 +0100
commit21f72fa4c8534e918b5cb1b7612a6682d9932977 (patch)
tree2d7bbb2c0a0c8937f372dec32e25685e89e9ce56
parentFix test failure in 30-test_evp_pkey_provided.t (diff)
downloadopenssl-21f72fa4c8534e918b5cb1b7612a6682d9932977.tar.xz
openssl-21f72fa4c8534e918b5cb1b7612a6682d9932977.zip
genpkey: Avoid leaving empty file if encryption passphrase does not match
Fixes #25440 Reviewed-by: Hugo Landau <hlandau@devever.net> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/26081)
-rw-r--r--apps/genpkey.c49
-rw-r--r--apps/include/apps.h1
-rw-r--r--apps/lib/apps.c26
3 files changed, 58 insertions, 18 deletions
diff --git a/apps/genpkey.c b/apps/genpkey.c
index 9a4cf622ce..53e5def6f9 100644
--- a/apps/genpkey.c
+++ b/apps/genpkey.c
@@ -106,7 +106,7 @@ cleanup:
int genpkey_main(int argc, char **argv)
{
CONF *conf = NULL;
- BIO *in = NULL, *out = NULL, *outpubkey = NULL;
+ BIO *mem_out = NULL, *mem_outpubkey = NULL;
ENGINE *e = NULL;
EVP_PKEY *pkey = NULL;
EVP_PKEY_CTX *ctx = NULL;
@@ -237,14 +237,16 @@ int genpkey_main(int argc, char **argv)
goto end;
}
- out = bio_open_owner(outfile, outformat, private);
- if (out == NULL)
+ mem_out = BIO_new(BIO_s_mem());
+ if (mem_out == NULL)
goto end;
+ BIO_set_mem_eof_return(mem_out, 0);
if (outpubkeyfile != NULL) {
- outpubkey = bio_open_owner(outpubkeyfile, outformat, private);
- if (outpubkey == NULL)
+ mem_outpubkey = BIO_new(BIO_s_mem());
+ if (mem_outpubkey == NULL)
goto end;
+ BIO_set_mem_eof_return(mem_outpubkey, 0);
}
if (verbose)
@@ -257,17 +259,17 @@ int genpkey_main(int argc, char **argv)
goto end;
if (do_param) {
- rv = PEM_write_bio_Parameters(out, pkey);
+ rv = PEM_write_bio_Parameters(mem_out, pkey);
} else if (outformat == FORMAT_PEM) {
assert(private);
- rv = PEM_write_bio_PrivateKey(out, pkey, cipher, NULL, 0, NULL, pass);
- if (rv > 0 && outpubkey != NULL)
- rv = PEM_write_bio_PUBKEY(outpubkey, pkey);
+ rv = PEM_write_bio_PrivateKey(mem_out, pkey, cipher, NULL, 0, NULL, pass);
+ if (rv > 0 && mem_outpubkey != NULL)
+ rv = PEM_write_bio_PUBKEY(mem_outpubkey, pkey);
} else if (outformat == FORMAT_ASN1) {
assert(private);
- rv = i2d_PrivateKey_bio(out, pkey);
- if (rv > 0 && outpubkey != NULL)
- rv = i2d_PUBKEY_bio(outpubkey, pkey);
+ rv = i2d_PrivateKey_bio(mem_out, pkey);
+ if (rv > 0 && mem_outpubkey != NULL)
+ rv = i2d_PUBKEY_bio(mem_outpubkey, pkey);
} else {
BIO_printf(bio_err, "Bad format specified for key\n");
goto end;
@@ -282,9 +284,9 @@ int genpkey_main(int argc, char **argv)
if (text) {
if (do_param)
- rv = EVP_PKEY_print_params(out, pkey, 0, NULL);
+ rv = EVP_PKEY_print_params(mem_out, pkey, 0, NULL);
else
- rv = EVP_PKEY_print_private(out, pkey, 0, NULL);
+ rv = EVP_PKEY_print_private(mem_out, pkey, 0, NULL);
if (rv <= 0) {
BIO_puts(bio_err, "Error printing key\n");
@@ -294,14 +296,25 @@ int genpkey_main(int argc, char **argv)
end:
sk_OPENSSL_STRING_free(keyopt);
- if (ret != 0)
+ if (ret != 0) {
ERR_print_errors(bio_err);
+ } else {
+ if (mem_outpubkey != NULL) {
+ rv = mem_bio_to_file(mem_outpubkey, outpubkeyfile, outformat, private);
+ if (!rv)
+ BIO_printf(bio_err, "Error writing to outpubkey: '%s'. Error: %s\n", outpubkeyfile, strerror(errno));
+ }
+ if (mem_out != NULL) {
+ rv = mem_bio_to_file(mem_out, outfile, outformat, private);
+ if (!rv)
+ BIO_printf(bio_err, "Error writing to outfile: '%s'. Error: %s\n", outpubkeyfile, strerror(errno));
+ }
+ }
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(ctx);
EVP_CIPHER_free(cipher);
- BIO_free_all(out);
- BIO_free_all(outpubkey);
- BIO_free(in);
+ BIO_free_all(mem_out);
+ BIO_free_all(mem_outpubkey);
release_engine(e);
OPENSSL_free(pass);
NCONF_free(conf);
diff --git a/apps/include/apps.h b/apps/include/apps.h
index 62b5cf9a01..2e1d06ebdf 100644
--- a/apps/include/apps.h
+++ b/apps/include/apps.h
@@ -63,6 +63,7 @@ BIO *dup_bio_err(int format);
BIO *bio_open_owner(const char *filename, int format, int private);
BIO *bio_open_default(const char *filename, char mode, int format);
BIO *bio_open_default_quiet(const char *filename, char mode, int format);
+int mem_bio_to_file(BIO *in, const char *filename, int format, int private);
char *app_conf_try_string(const CONF *cnf, const char *group, const char *name);
int app_conf_try_number(const CONF *conf, const char *group, const char *name,
long *result);
diff --git a/apps/lib/apps.c b/apps/lib/apps.c
index 59cc6e18e0..3bc6465945 100644
--- a/apps/lib/apps.c
+++ b/apps/lib/apps.c
@@ -3225,6 +3225,32 @@ BIO *bio_open_default_quiet(const char *filename, char mode, int format)
return bio_open_default_(filename, mode, format, 1);
}
+int mem_bio_to_file(BIO *in, const char *filename, int format, int private)
+{
+ int rv = 0, ret = 0;
+ BIO *out = NULL;
+ BUF_MEM *mem_buffer = NULL;
+
+ rv = BIO_get_mem_ptr(in, &mem_buffer);
+ if (rv <= 0) {
+ BIO_puts(bio_err, "Error reading mem buffer\n");
+ goto end;
+ }
+ out = bio_open_owner(filename, format, private);
+ if (out == NULL)
+ goto end;
+ rv = BIO_write(out, mem_buffer->data, mem_buffer->length);
+ if (rv < 0 || (size_t)rv != mem_buffer->length)
+ BIO_printf(bio_err, "Error writing to output file: '%s'\n", filename);
+ else
+ ret = 1;
+end:
+ if (!ret)
+ ERR_print_errors(bio_err);
+ BIO_free_all(out);
+ return ret;
+}
+
void wait_for_async(SSL *s)
{
/* On Windows select only works for sockets, so we simply don't wait */