diff options
author | Dr. David von Oheimb <David.von.Oheimb@siemens.com> | 2021-12-14 11:29:19 +0100 |
---|---|---|
committer | Dr. David von Oheimb <dev@ddvo.net> | 2022-07-20 11:40:37 +0200 |
commit | b6fbef1159c9aeb1590c116a9426e169d2203506 (patch) | |
tree | fa6a73df8d5bd7fb5357966a96c3c34dddcbb358 /apps | |
parent | fad0f80eff188ef938fed614245a56ed56110deb (diff) |
Add OSSL_CMP_CTX_get0_validatedSrvCert(), correcting OSSL_CMP_validate_msg()
Also change ossl_cmp_ctx_set0_validatedSrvCert() to ossl_cmp_ctx_set1_validatedSrvCert(),
and add respective tests as well as the -srvcertout CLI option using the new function.
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: David von Oheimb <david.von.oheimb@siemens.com>
(Merged from https://github.com/openssl/openssl/pull/18656)
Diffstat (limited to 'apps')
-rw-r--r-- | apps/cmp.c | 94 |
1 files changed, 70 insertions, 24 deletions
diff --git a/apps/cmp.c b/apps/cmp.c index deb709cae0..f3624aa94a 100644 --- a/apps/cmp.c +++ b/apps/cmp.c @@ -86,6 +86,7 @@ static char *opt_srvcert = NULL; static char *opt_expect_sender = NULL; static int opt_ignore_keyusage = 0; static int opt_unprotected_errors = 0; +static char *opt_srvcertout = NULL; static char *opt_extracertsout = NULL; static char *opt_cacertsout = NULL; @@ -220,7 +221,7 @@ typedef enum OPTION_choice { OPT_TRUSTED, OPT_UNTRUSTED, OPT_SRVCERT, OPT_EXPECT_SENDER, OPT_IGNORE_KEYUSAGE, OPT_UNPROTECTED_ERRORS, - OPT_EXTRACERTSOUT, OPT_CACERTSOUT, + OPT_SRVCERTOUT, OPT_EXTRACERTSOUT, OPT_CACERTSOUT, OPT_REF, OPT_SECRET, OPT_CERT, OPT_OWN_TRUSTED, OPT_KEY, OPT_KEYPASS, OPT_DIGEST, OPT_MAC, OPT_EXTRACERTS, @@ -388,6 +389,8 @@ const OPTIONS cmp_options[] = { "certificate responses (ip/cp/kup), revocation responses (rp), and PKIConf"}, {OPT_MORE_STR, 0, 0, "WARNING: This setting leads to behavior allowing violation of RFC 4210"}, + { "srvcertout", OPT_SRVCERTOUT, 's', + "File to save the server cert used and validated for CMP response protection"}, {"extracertsout", OPT_EXTRACERTSOUT, 's', "File to save extra certificates received in the extraCerts field"}, {"cacertsout", OPT_CACERTSOUT, 's', @@ -573,7 +576,7 @@ static varref cmp_vars[] = { /* must be in same order as enumerated above! */ {&opt_trusted}, {&opt_untrusted}, {&opt_srvcert}, {&opt_expect_sender}, {(char **)&opt_ignore_keyusage}, {(char **)&opt_unprotected_errors}, - {&opt_extracertsout}, {&opt_cacertsout}, + {&opt_srvcertout}, {&opt_extracertsout}, {&opt_cacertsout}, {&opt_ref}, {&opt_secret}, {&opt_cert}, {&opt_own_trusted}, {&opt_key}, {&opt_keypass}, @@ -1493,6 +1496,7 @@ static int setup_protection_ctx(OSSL_CMP_CTX *ctx, ENGINE *engine) if (opt_mac != NULL) { int mac = OBJ_ln2nid(opt_mac); + if (mac == NID_undef) { CMP_err1("MAC algorithm name not recognized: '%s'", opt_mac); return 0; @@ -2005,36 +2009,41 @@ static int write_cert(BIO *bio, X509 *cert) } /* - * If destFile != NULL writes out a stack of certs to the given file. - * In any case frees the certs. + * If file != NULL writes out a stack of certs to the given file. + * If certs is NULL, the file is emptied. + * Frees the certs if present. * Depending on options use either PEM or DER format, * where DER does not make much sense for writing more than one cert! * Returns number of written certificates on success, -1 on error. */ -static int save_free_certs(OSSL_CMP_CTX *ctx, - STACK_OF(X509) *certs, char *destFile, char *desc) +static int save_free_certs(OSSL_CMP_CTX *ctx, STACK_OF(X509) *certs, + const char *file, const char *desc) { BIO *bio = NULL; int i; - int n = sk_X509_num(certs); + int n = sk_X509_num(certs /* may be NULL */); - if (destFile == NULL) + if (n < 0) + n = 0; + if (file == NULL) goto end; - CMP_info3("received %d %s certificate(s), saving to file '%s'", - n, desc, destFile); + if (certs != NULL) + CMP_info3("received %d %s certificate(s), saving to file '%s'", + n, desc, file); if (n > 1 && opt_certform != FORMAT_PEM) CMP_warn("saving more than one certificate in non-PEM format"); - if (destFile == NULL || (bio = BIO_new(BIO_s_file())) == NULL - || !BIO_write_filename(bio, (char *)destFile)) { - CMP_err1("could not open file '%s' for writing", destFile); + if ((bio = BIO_new(BIO_s_file())) == NULL + || !BIO_write_filename(bio, (char *)file)) { + CMP_err3("could not open file '%s' for %s %s certificate(s)", + file, certs == NULL ? "deleting" : "writing", desc); n = -1; goto end; } for (i = 0; i < n; i++) { if (!write_cert(bio, sk_X509_value(certs, i))) { - CMP_err1("cannot write certificate to file '%s'", destFile); + CMP_err2("cannot write %s certificate to file '%s'", desc, file); n = -1; goto end; } @@ -2046,6 +2055,35 @@ static int save_free_certs(OSSL_CMP_CTX *ctx, return n; } +static int delete_certfile(const char *file, const char *desc) +{ + if (file == NULL) + return 1; + + if (unlink(file) != 0 && errno != ENOENT) { + CMP_err2("Failed to delete %s, which should be done to indicate there is no %s cert", + file, desc); + return 0; + } + return 1; +} + +static int save_cert(OSSL_CMP_CTX *ctx, X509 *cert, + const char *file, const char *desc) +{ + if (file == NULL || cert == NULL) { + return 1; + } else { + STACK_OF(X509) *certs = sk_X509_new_null(); + + if (!X509_add_cert(certs, cert, X509_ADD_FLAG_UP_REF)) { + sk_X509_free(certs); + return 0; + } + return save_free_certs(ctx, certs, file, desc) >= 0; + } +} + static int print_itavs(const STACK_OF(OSSL_CMP_ITAV) *itavs) { int i, ret = 1; @@ -2422,6 +2460,9 @@ static int get_opts(int argc, char **argv) case OPT_UNPROTECTED_ERRORS: opt_unprotected_errors = 1; break; + case OPT_SRVCERTOUT: + opt_srvcertout = opt_str(); + break; case OPT_EXTRACERTSOUT: opt_extracertsout = opt_str(); break; @@ -2789,6 +2830,7 @@ int cmp_main(int argc, char **argv) opt_section, configfile); } else { const char *end = opt_section + strlen(opt_section); + while ((end = prev_item(opt_section, end)) != NULL) { if (!NCONF_get_section(conf, opt_item)) { CMP_err2("no [%s] section found in config file '%s'", @@ -2812,7 +2854,15 @@ int cmp_main(int argc, char **argv) ret = get_opts(argc, argv); if (ret <= 0) goto err; + ret = 0; + if (!delete_certfile(opt_srvcertout, "validated server") + || !delete_certfile(opt_certout, "enrolled") + || save_free_certs(NULL, NULL, opt_extracertsout, "extra") < 0 + || save_free_certs(NULL, NULL, opt_cacertsout, "CA") < 0 + || save_free_certs(NULL, NULL, opt_chainout, "chain") < 0) + goto err; + if (!app_RAND_load()) goto err; @@ -2942,6 +2992,7 @@ int cmp_main(int argc, char **argv) if (opt_infotype != NID_undef) { OSSL_CMP_ITAV *itav = OSSL_CMP_ITAV_create(OBJ_nid2obj(opt_infotype), NULL); + if (itav == NULL) goto err; OSSL_CMP_CTX_push0_genm_ITAV(cmp_ctx, itav); @@ -2997,19 +3048,14 @@ int cmp_main(int argc, char **argv) if (!ret) goto err; ret = 0; + if (!save_cert(cmp_ctx, OSSL_CMP_CTX_get0_validatedSrvCert(cmp_ctx), + opt_srvcertout, "validated server")) + goto err; if (save_free_certs(cmp_ctx, OSSL_CMP_CTX_get1_caPubs(cmp_ctx), opt_cacertsout, "CA") < 0) goto err; - if (newcert != NULL) { - STACK_OF(X509) *certs = sk_X509_new_null(); - - if (!X509_add_cert(certs, newcert, X509_ADD_FLAG_UP_REF)) { - sk_X509_free(certs); - goto err; - } - if (save_free_certs(cmp_ctx, certs, opt_certout, "enrolled") < 0) - goto err; - } + if (!save_cert(cmp_ctx, newcert, opt_certout, "enrolled")) + goto err; if (save_free_certs(cmp_ctx, OSSL_CMP_CTX_get1_newChain(cmp_ctx), opt_chainout, "chain") < 0) goto err; |