diff options
author | shridhar kalavagunta <coolshrid@hotmail.com> | 2024-11-28 18:30:50 +0100 |
---|---|---|
committer | Tomas Mraz <tomas@openssl.org> | 2025-01-15 13:26:41 +0100 |
commit | 21f72fa4c8534e918b5cb1b7612a6682d9932977 (patch) | |
tree | 2d7bbb2c0a0c8937f372dec32e25685e89e9ce56 | |
parent | Fix test failure in 30-test_evp_pkey_provided.t (diff) | |
download | openssl-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.c | 49 | ||||
-rw-r--r-- | apps/include/apps.h | 1 | ||||
-rw-r--r-- | apps/lib/apps.c | 26 |
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 */ |