diff --git a/apps/acert.c b/apps/acert.c index 3911c245c9b0d..9adecbbbdf354 100644 --- a/apps/acert.c +++ b/apps/acert.c @@ -64,7 +64,8 @@ typedef enum OPTION_choice { OPT_DAYS, OPT_SET_SERIAL, OPT_STARTDATE, OPT_ENDDATE, OPT_ADDEXT, OPT_ACERTEXTS, OPT_SECTION, - OPT_PROV_ENUM, OPT_MD + OPT_PROV_ENUM, OPT_MD, + OPT_ASSERTED_BEFORE, OPT_TARGET_CERT } OPTION_CHOICE; const OPTIONS acert_options[] = { @@ -104,6 +105,10 @@ const OPTIONS acert_options[] = { "Additional cert extension key=value pair (may be given more than once)"}, {"acertexts", OPT_ACERTEXTS, 's', "Attribute certificate extension section (override value in config file)"}, + {"asserted-before", OPT_ASSERTED_BEFORE, '-', + "Fail verification if the attribute certificate contains the singleUse extension."}, + {"target-cert", OPT_TARGET_CERT, '<', + "The target certificate path to check against the targetingInformation extension"}, OPT_SECTION("Signing"), {"sigopt", OPT_SIGOPT, 's', "Signature parameter in n:v form"}, @@ -189,21 +194,25 @@ int acert_main(int argc, char **argv) EVP_PKEY_CTX *genctx = NULL; STACK_OF(OPENSSL_STRING) *pkeyopts = NULL, *sigopts = NULL; LHASH_OF(OPENSSL_STRING) *addexts = NULL; - X509 *AAcert = NULL, *holder = NULL; + X509 *AAcert = NULL, *holder = NULL, *target_x509 = NULL; + TARGET_CERT *target_cert = NULL; + OSSL_ISSUER_SERIAL *target_iss_ser = NULL; + GENERAL_NAME *target_cert_name = NULL; + TARGET *target = NULL; X509_ACERT *acert = NULL; BIO *addext_bio = NULL; const char *infile = NULL, *AAfile = NULL, *AAkeyfile = NULL; - const char *holderfile = NULL; + const char *holderfile = NULL, *targetfile = NULL; int hldr_basecertid = 0, hldr_entity = 0; char *outfile = NULL, *digest = NULL; char *keyalgstr = NULL, *p, *prog; char *passin = NULL, *passinarg = NULL; char *acert_exts = NULL; - X509_NAME *fsubj = NULL; + X509_NAME *fsubj = NULL, *target_subj = NULL; char *template = default_config_file; OPTION_CHOICE o; int days = DEFAULT_DAYS; - int ret = 1, i = 0, newacert = 0, verbose = 0; + int ret = 1, i = 0, newacert = 0, verbose = 0, asserted_before = 0; int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyform = FORMAT_UNDEF; int verify = 0, noout = 0, text = 0; unsigned long chtype = MBSTRING_ASC, certflag = 0; @@ -310,6 +319,12 @@ int acert_main(int argc, char **argv) case OPT_ENDDATE: enddate = opt_arg(); break; + case OPT_ASSERTED_BEFORE: + asserted_before = 1; + break; + case OPT_TARGET_CERT: + targetfile = opt_arg(); + break; case OPT_DAYS: days = atoi(opt_arg()); if (days < -1) { @@ -559,15 +574,29 @@ int acert_main(int argc, char **argv) } if (verify) { - if (holderfile == NULL) { - BIO_printf(bio_err, "'-holder' option required to verify.\n"); - goto end; - } - if (holder == NULL) { - BIO_printf(bio_err, "Holder certificate could not be loaded.\n"); - goto end; + if (targetfile) { + if ((target_x509 = load_cert_pass(targetfile, FORMAT_UNDEF, 1, passin, + "target certificate")) == NULL) + goto end; + target_iss_ser = OSSL_ISSUER_SERIAL_new(); + if (OSSL_ISSUER_SERIAL_set1_issuer(target_iss_ser, X509_get_issuer_name(target_x509)) == 0) + goto end; + if (OSSL_ISSUER_SERIAL_set1_serial(target_iss_ser, X509_get_serialNumber(target_x509)) == 0) + goto end; + + target_cert_name = GENERAL_NAME_new(); + target_subj = X509_NAME_dup(X509_get_subject_name(target_x509)); + if (target_subj == NULL) + goto end; + GENERAL_NAME_set0_value(target_cert_name, GEN_DIRNAME, target_subj); + target_cert = TARGET_CERT_new(); + target_cert->targetCertificate = target_iss_ser; + target_cert->targetName = target_cert_name; + target = TARGET_new(); + target->type = TGT_TARGET_CERT; + target->choice.targetCert = target_cert; } - ret = X509_attr_cert_verify_ex(acert, AAcert, holder, NULL, 0); + ret = X509_attr_cert_verify_ex(acert, AAcert, holder, target, asserted_before); if (ret != X509_V_OK) { BIO_printf(bio_err, "Attribute certificate is invalid.\n"); goto end; diff --git a/doc/build.info b/doc/build.info index b81f26d6a8d77..dcfce6012fc19 100644 --- a/doc/build.info +++ b/doc/build.info @@ -2879,6 +2879,10 @@ DEPEND[html/man3/X509_add_cert.html]=man3/X509_add_cert.pod GENERATE[html/man3/X509_add_cert.html]=man3/X509_add_cert.pod DEPEND[man/man3/X509_add_cert.3]=man3/X509_add_cert.pod GENERATE[man/man3/X509_add_cert.3]=man3/X509_add_cert.pod +DEPEND[html/man3/X509_attr_cert_verify.html]=man3/X509_attr_cert_verify.pod +GENERATE[html/man3/X509_attr_cert_verify.html]=man3/X509_attr_cert_verify.pod +DEPEND[man/man3/X509_attr_cert_verify.3]=man3/X509_attr_cert_verify.pod +GENERATE[man/man3/X509_attr_cert_verify.3]=man3/X509_attr_cert_verify.pod DEPEND[html/man3/X509_check_ca.html]=man3/X509_check_ca.pod GENERATE[html/man3/X509_check_ca.html]=man3/X509_check_ca.pod DEPEND[man/man3/X509_check_ca.3]=man3/X509_check_ca.pod @@ -3625,6 +3629,7 @@ html/man3/X509_STORE_new.html \ html/man3/X509_STORE_set_verify_cb_func.html \ html/man3/X509_VERIFY_PARAM_set_flags.html \ html/man3/X509_add_cert.html \ +html/man3/X509_attr_cert_verify.html \ html/man3/X509_check_ca.html \ html/man3/X509_check_host.html \ html/man3/X509_check_issued.html \ @@ -4262,6 +4267,7 @@ man/man3/X509_STORE_new.3 \ man/man3/X509_STORE_set_verify_cb_func.3 \ man/man3/X509_VERIFY_PARAM_set_flags.3 \ man/man3/X509_add_cert.3 \ +man/man3/X509_attr_cert_verify.3 \ man/man3/X509_check_ca.3 \ man/man3/X509_check_host.3 \ man/man3/X509_check_issued.3 \ diff --git a/doc/man1/openssl-acert.pod.in b/doc/man1/openssl-acert.pod.in index 2aab4468f08bc..af626b807ba98 100644 --- a/doc/man1/openssl-acert.pod.in +++ b/doc/man1/openssl-acert.pod.in @@ -25,6 +25,8 @@ B B [B<-holder> I] [B<-use-holder-basecertid>] [B<-use-holder-name>] +[B<-target-cert>] +[B<-asserted-before>] [B<-AA> I|I] [B<-AAkey> I|I] [B<-keyform> B|B|B|B] @@ -121,6 +123,24 @@ holder in the new attribute certificate. Use the holder certificate's subject name to identify the holder in the new attribute certificate. +=item B<-target-cert> I + +The target certificate file, from which a TARGET (using the targetCert +alternative) is constructed and compared against the targets listed in the +targetingInformation X.509v3 extension, if it is present. This argument takes +effect if the B command is used with the B<-verify> option. + +Verification will not fail if the targetingInformation extension does not +exist in the verified attribute certificate, but it will fail if the extension +is present and the target does not appear in the list of targets. + +=item B<-asserted-before> + +Specifies whether the verified attribute certificate has been asserted once +before. If provided, this causes verification of an attribute certificate to +fail if the singleUse X.509v3 extension is present. This argument only takes +effect if the B command is used with the B<-verify> option. + =item B<-AA> I|I Specifies the Attribute Authority certificate to be used for signing with the diff --git a/doc/man3/X509_attr_cert_verify.pod b/doc/man3/X509_attr_cert_verify.pod new file mode 100644 index 0000000000000..886459e80a7d0 --- /dev/null +++ b/doc/man3/X509_attr_cert_verify.pod @@ -0,0 +1,63 @@ +=pod + +=head1 NAME + +X509_attr_cert_verify, X509_attr_cert_verify_ex, acert_crl +- attribute certificate verification functions + +=head1 SYNOPSIS + + int X509_attr_cert_verify(X509_ACERT *acert, X509 *issuer); + int X509_attr_cert_verify_ex(X509_ACERT *acert, X509 *issuer, X509 *holder, + TARGET *tgt, int asserted_before); + int acert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509_ACERT *x); + +=head1 DESCRIPTION + +X509_attr_cert_verify verifies that the attribute ceritifcate B is signed +by the issuer B and that the attribute certificate is valid with +respect to its validity times and its extensions. This function does B +verify the B certificate. + +X509_attr_cert_verify_ex is the extended form of X509_attr_cert_verify, which +takes an optional B argument, B argument, and B +argument. + +If not B, the subject and subject alternative names are extracted from +the B public key certificate and compared against the holder field of +the asserted attribute certificate, B. + +If not B, the target is checked against the list of permitted targets +within the targetingInformation X.509v3 extension, if the extension is present. + +If set to a truthy value, B causes attribute certificate +verification to fail if the singleUse X.509v3 extension is present. + +acert_crl returns 1 if the attribute certificate B is not revoked in the +certificate revocation list B, some other integer otherwise. + +=head1 NOTES + +These functions verify an X.509 attribute certificate to varying degrees. None +of them verify the corresponding public key certificate, but the public key +certificates can just be verified using the normal OpenSSL verification +functions. + +=head1 RETURN VALUES + +Both X509_attr_cert_verify and X509_attr_cert_verify_ex return X509_V_OK (0) if +the attribute certificate is valid with respect to the supplied verification +parameters, or some other X509_V_ERR_ value otherwise. As stated above, +acert_crl returns 1 if the attribute certificate is not revoked in the provided +certificate revocation list, and some other integer otherwise. + +=head1 COPYRIGHT + +Copyright 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 +in the file LICENSE in the source distribution or at +L. + +=cut